Skip to content

@modoki/engine / index / InteractionHandle

Interface: InteractionHandle

One draggable/clickable handle in an authoring editor, in viewport CSS px.

Rendering

editor

editor: string

Which editor produced it — 'collider2d' | 'dopesheet' | 'curves' | 'skin' | …


id

id: string

Stable id UNIQUE across all providers — namespace it by editor+kind+index, e.g. 'collider:vert:0', 'dope🔑Transform.x:3', 'skin🦴root'. This is how drag-handle/tap-handle address it, so it must survive between a read and the immediately-following gesture (fine while the game is paused/authoring).


kind

kind: string

Handle category — 'collider-vertex' | 'keyframe' | 'tangent' | 'bone-joint' | 'gizmo-axis' | 'slice-rect' | 'gradient-stop' | … — for filtering.


label?

optional label?: string

Optional human-readable label ('vertex 0', 'key t=0.5 Transform.x').


meta?

optional meta?: Record<string, unknown>

Optional provider-specific data (bone name, keyframe time/value, entity id) — passed through verbatim so Claude can pick the right handle semantically. By convention meta.disabled: true marks a control that is present but inert (a greyed-out Paste). That is DATA; a screenshot only offers a shade of grey.


occludedBy?

optional occludedBy?: string | null

Descriptor of whatever currently covers this handle's centre (a modal, an open menu, a scrim). Absent when nothing does, or when occlusion could not be checked. A trusted click hit-tests by coordinate, so an occluded handle CANNOT be clicked where it appears to be — the silent-miss class of bug, surfaced as data.

Filled in by computeHandles, not by providers: occlusion is a property of anything addressed by COORDINATE, which is every handle — not a DOM-chrome feature.


owner?

optional owner?: unknown

The DOM element this handle lives in — its own element for chrome, the owning <canvas> for a Canvas2D/SVG editor's handle. Supplied so occlusion can be checked uniformly: an element is covered iff the topmost element at the handle's point is neither it nor a descendant.

NOT SERIALIZABLE. computeHandles strips it before the handle crosses the agent bridge as JSON. A provider that omits it gets no occlusion check (and is counted in occlusionUnchecked) rather than a silently wrong "not occluded".


rect?

optional rect?: object

The handle's full box, not just its centre — so an agent can compute overlap and aim off-centre. Canvas handles are points and omit it; DOM chrome always has one.

Rendering

h

h: number

w

w: number

x

x: number

y

y: number


x

x: number

Handle CENTRE in viewport CSS px (origin top-left) — the point to drag/click.


y

y: number

Built with Modoki.