@weasel-js/routing 1.7.0 → 1.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -126,10 +126,21 @@ type HitShape = {
126
126
  cx: number;
127
127
  cy: number;
128
128
  r: number;
129
+ }
130
+ /** A world-space polygon — for a region that is a turned square on screen,
131
+ * which under non-uniform zoom is no rotated rect in world. */
132
+ | {
133
+ kind: 'polygon';
134
+ points: readonly {
135
+ x: number;
136
+ y: number;
137
+ }[];
129
138
  } | {
130
139
  kind: 'path';
131
140
  d: Path2D;
132
141
  };
142
+ /** What a recorded viewport change was: a translation or a scale change. */
143
+ type ViewportGestureKind = 'pan' | 'zoom';
133
144
  /**
134
145
  * Where a tool reports its internal hit math so the debug overlay can draw it.
135
146
  * Routing threads a sink through `ToolCtx` and never calls one.
@@ -155,6 +166,16 @@ interface DebugSink {
155
166
  y: number;
156
167
  }, accepted: boolean): void;
157
168
  recordLayer(id: string, label: string, space: 'world' | 'screen', index: number): void;
169
+ /**
170
+ * A viewport change a gesture made: the view it started from, the view it
171
+ * produced, and the world point it held fixed — a pan's grab point, a zoom's
172
+ * focal point — when it had one. Survives `beginFrame`; the next record
173
+ * replaces it.
174
+ */
175
+ recordViewport(kind: ViewportGestureKind, from: View, to: View, anchor?: {
176
+ x: number;
177
+ y: number;
178
+ }): void;
158
179
  /** Clears every non-snap array. Called at the start of each Canvas render. */
159
180
  beginFrame(): void;
160
181
  /** Clears the snap array. Called at gesture end. */
@@ -1470,6 +1491,7 @@ interface DispatchRecord {
1470
1491
  fired: string | null;
1471
1492
  outcome: 'handled' | 'unhandled';
1472
1493
  }
1494
+ /** The input a {@link DispatchRecord} describes, reduced to plain data. */
1473
1495
  interface DispatchRecordInput {
1474
1496
  /** `InputEvent.kind`: `'key'`, `'pointerdown'`, `'wheel'`, … */
1475
1497
  eventKind: string;
@@ -1506,6 +1528,7 @@ interface RecordCandidate {
1506
1528
  /** The action's `eligible` rule as text, when it declares one. */
1507
1529
  eligible?: string;
1508
1530
  }
1531
+ /** A matched candidate a filter removed before ranking, and which filter. */
1509
1532
  type DroppedCandidate =
1510
1533
  /** An exclusive claim on the input barred bindings that do not read the
1511
1534
  * claim's affordance. */
@@ -1520,6 +1543,7 @@ type DroppedCandidate =
1520
1543
  filter: 'ineligible';
1521
1544
  rule: string;
1522
1545
  };
1546
+ /** One field of the `specificity` tuple, in the order it is compared. */
1523
1547
  type SpecificityPart = 'target' | 'mods' | 'phase' | 'exact';
1524
1548
  /** The ranking step that put a candidate below the one before it. */
1525
1549
  type PlacedBy = {
@@ -1582,6 +1606,8 @@ type WalkStep = {
1582
1606
  | {
1583
1607
  kind: 'outranked';
1584
1608
  };
1609
+ /** A candidate that survived the filters: why it sits where it does, and
1610
+ * what the walk did with it. */
1585
1611
  interface RankedCandidate {
1586
1612
  candidate: RecordCandidate;
1587
1613
  placedBy: PlacedBy;
@@ -1666,15 +1692,6 @@ interface ModeSwitchLogEntry {
1666
1692
  }
1667
1693
  /** A trace entry: one {@link DispatchRecord} per resolved input, or a mode switch. */
1668
1694
  type TraceLogEntry = DispatchRecord | ModeSwitchLogEntry;
1669
- /**
1670
- * Dev only: offer the record for what a press at the pointer would do, as a
1671
- * thunk on `window.__weaselDispatchLive__`. The hover pump offers one per move
1672
- * and a reader builds the record only when it looks, so no record is built
1673
- * while nothing is watching. `null` withdraws it when the pointer leaves.
1674
- *
1675
- * @internal
1676
- */
1677
- declare function publishLiveDispatch(explain: (() => DispatchRecord) | null): void;
1678
1695
  /** Push a mode-switch record into the trace log. Safe to call from
1679
1696
  * anywhere; no-ops outside DEV. */
1680
1697
  declare function recordModeSwitch(mode: string, from: string | null, to: string | null, detail?: string): void;
@@ -1713,35 +1730,6 @@ interface DispatcherContext {
1713
1730
  */
1714
1731
  viewId?: string | null;
1715
1732
  }
1716
- /**
1717
- * Filter `matches` to only those whose backing action has no `eligible`
1718
- * rule, or whose rule evaluates true against `ruleCtx`. Exported for
1719
- * unit testing.
1720
- *
1721
- * @internal
1722
- */
1723
- declare function filterEligible<M extends {
1724
- binding: {
1725
- actionId: string;
1726
- };
1727
- }>(matches: readonly M[], actionLookup: (id: string) => Action | undefined, ruleCtx: RuleCtx): M[];
1728
- /**
1729
- * Among matches tied on scope and specificity, put those whose action is
1730
- * gated by an `eligible` rule that holds now ahead of those with no rule: a
1731
- * binding that applies only in the current context — Escape while editing a
1732
- * path — outranks one that applies everywhere. Otherwise stable.
1733
- *
1734
- * @internal
1735
- */
1736
- declare function preferContextual<M extends {
1737
- binding: GestureBinding;
1738
- scope: string;
1739
- }>(matches: readonly M[], actionLookup: (id: string) => Action | undefined,
1740
- /** Whether a gated action's rule holds; skip re-asking where the matches
1741
- * were already filtered by it. */
1742
- holds: (action: Action) => boolean,
1743
- /** The routed view: a binding naming it is never tied with one that does not. */
1744
- view: string | null): M[];
1745
1733
  /**
1746
1734
  * Handle returned by `Dispatcher.beginUiOngoing()` for driving an
1747
1735
  * ongoing invoker from a UI control (color picker, slider).
@@ -2122,6 +2110,85 @@ declare const isControlHandle: (target: unknown) => boolean;
2122
2110
  /** Any of the three anchor-editing affordances (anchor + both controls). */
2123
2111
  declare const isAnchorOrControl: (target: unknown) => boolean;
2124
2112
 
2113
+ /**
2114
+ * The long-press the gesture dispatcher is timing, as observable state: where
2115
+ * the press landed, when the hold started, how far through it is, and whether
2116
+ * any binding would fire on it. Feedback — a filling ring, a haptic — reads
2117
+ * this; nothing here decides what the feedback looks like.
2118
+ */
2119
+ /** A press being held toward a long-press. */
2120
+ interface PendingLongPress {
2121
+ pointerId: number;
2122
+ /** Long-press is synthesized for these two only; a mouse never arms one. */
2123
+ pointerType: 'touch' | 'pen';
2124
+ /** Where the press landed, in client coordinates. */
2125
+ client: {
2126
+ x: number;
2127
+ y: number;
2128
+ };
2129
+ /** The same point in CSS pixels from the canvas element's top-left — what a
2130
+ * `space: 'screen'` layer draws in. */
2131
+ local: {
2132
+ x: number;
2133
+ y: number;
2134
+ };
2135
+ /** The same point in the routed view's world coordinates. */
2136
+ world: {
2137
+ x: number;
2138
+ y: number;
2139
+ };
2140
+ /** The view the press routed to; `null` is the root view. */
2141
+ viewId: string | null;
2142
+ /** `performance.now()` when the hold started. */
2143
+ startedAt: number;
2144
+ /** How long the hold must last before the long-press fires, in ms. */
2145
+ duration: number;
2146
+ /**
2147
+ * Whether holding to the end would fire anything — a `longPress` binding,
2148
+ * or a `contextMenu` binding through the fallback. Resolved at press time.
2149
+ * Feedback shows only when this is true: a press that will do nothing must
2150
+ * not promise that it will.
2151
+ */
2152
+ armed: boolean;
2153
+ }
2154
+ /** Read side of the pending long-press. Published as the `longPress` dep. */
2155
+ interface LongPressState {
2156
+ /** The press being held, or `null` when none is. Cleared when the
2157
+ * long-press fires, and when movement, release, cancel or a second
2158
+ * pointer abandons it. */
2159
+ get(): PendingLongPress | null;
2160
+ /** How far through the hold the pending press is, 0→1, at `now`
2161
+ * (`performance.now()` by default). 0 when nothing is pending. */
2162
+ progress(now?: number): number;
2163
+ /** Called whenever {@link get} changes. Progress is derived from the
2164
+ * clock, so it does not notify — a loop drawing it asks for frames. */
2165
+ subscribe(fn: () => void): () => void;
2166
+ }
2167
+ /** The dispatcher's writable half of {@link LongPressState}. */
2168
+ interface LongPressStore extends LongPressState {
2169
+ set(next: PendingLongPress | null): void;
2170
+ }
2171
+ /** How long a touch or pen press is held before it fires `longPress`, in ms. */
2172
+ declare const LONG_PRESS_MS = 500;
2173
+ /** How `useGestureDispatcher` times, publishes and signals a long-press. */
2174
+ interface LongPressOptions {
2175
+ /** Hold time in ms. Default {@link LONG_PRESS_MS}. */
2176
+ duration?: number;
2177
+ /**
2178
+ * Where the press being held is published: position, start time, progress,
2179
+ * and whether any binding would fire on it. `<SceneCanvas>` passes one and
2180
+ * republishes it as the `longPress` dep, which its default press ring
2181
+ * reads. Omit it and nothing is published.
2182
+ */
2183
+ state?: LongPressStore;
2184
+ /**
2185
+ * Default true. A long-press some binding handled pulses `navigator.vibrate`
2186
+ * briefly, for touch and pen pointers, where the API exists.
2187
+ */
2188
+ haptics?: boolean;
2189
+ }
2190
+ declare function createLongPressStore(): LongPressStore;
2191
+
2125
2192
  /**
2126
2193
  * The DOM half of a drag: one pointer, held down, from press to release.
2127
2194
  *
@@ -2141,6 +2208,7 @@ type PointerSessionCancelReason =
2141
2208
  | 'aborted'
2142
2209
  /** A new press arrived on this pointer, so the tracked one had ended. */
2143
2210
  | 'superseded';
2211
+ /** What {@link openPointerSession} reports. Exactly one of `onEnd` / `onCancel` fires when the session ends. */
2144
2212
  interface PointerSessionCallbacks {
2145
2213
  /** Every move belonging to this pointer, while it is still held. */
2146
2214
  onMove?: (e: PointerEvent) => void;
@@ -2149,13 +2217,16 @@ interface PointerSessionCallbacks {
2149
2217
  /** The session ended without a release. Fires once. */
2150
2218
  onCancel?: (reason: PointerSessionCancelReason) => void;
2151
2219
  }
2220
+ /** Options for {@link openPointerSession}. */
2152
2221
  interface PointerSessionOptions {
2153
2222
  /** Ask the origin element to capture the pointer. Default `true`. Capture
2154
2223
  * keeps hover and click off everything the drag passes over; the session
2155
2224
  * does not depend on it to keep receiving events. */
2156
2225
  capture?: boolean;
2157
2226
  }
2227
+ /** A live drag opened by {@link openPointerSession}. */
2158
2228
  interface PointerSession {
2229
+ /** The pointer this session follows, taken from the press. */
2159
2230
  readonly pointerId: number;
2160
2231
  /** False once the session has ended, by any route. */
2161
2232
  readonly active: boolean;
@@ -2648,9 +2719,11 @@ declare function reportRouteConflicts(scopes: ToolScopes, warn?: (message: strin
2648
2719
  * consumers don't depend on its disappearance.
2649
2720
  */
2650
2721
  /**
2651
- * @internal — runtime shape consumed by `matchesKeyBinding`. Public tool authors
2652
- * should use `ToolKeybinding` from `@weasel-js/core` for declaring
2653
- * configurable activation keys.
2722
+ * A key plus a modifier policy, as {@link matchesKeyBinding} tests it against a
2723
+ * `KeyboardEvent`. Every modifier left unset is forbidden, so `{ key: 'a' }`
2724
+ * does not fire on Cmd+A. The matcher ignores `skipInEditable`, `enabled` and
2725
+ * `preventDefault`; those are for whatever attaches the listener. Tools
2726
+ * declaring an activation key use `ToolKeybinding` instead.
2654
2727
  */
2655
2728
  interface KeyBinding {
2656
2729
  /**
@@ -2856,4 +2929,4 @@ type KernelOverlay = OverlaySchema extends {
2856
2929
  overlay: infer O;
2857
2930
  } ? O : unknown;
2858
2931
 
2859
- export { type HandleKind as $, type ActionsRegistry as A, type BindingOpts as B, type Contribution as C, type Dispatcher as D, COARSE_TARGET_SCALE as E, type Condition as F, type Conflict as G, type ContributionChrome as H, type ContributionDeps as I, type ContributionRouting as J, type KernelOverlay as K, DEFAULT_ALLOWED_CAPABILITIES as L, DEFAULT_DEVICE_PROFILE as M, type DebugSink as N, type OverlayPosition as O, type DetectedDeviceFacts as P, type DeviceProfile as Q, type RuleCtx as R, ScopeNode as S, type DispatchRecord as T, type DispatchRecordInput as U, type DispatcherContext as V, type DragSample as W, type DroppedCandidate as X, type Eligibility as Y, type EligibilityState as Z, type GestureBinding as _, type AffordanceHit as a, clientToCanvasRect as a$, type HitShape as a0, type HotkeyTrigger as a1, INGEST_STRING_MIMES as a2, type ImmediateInvoker as a3, type InvocationCtx as a4, type Invoker as a5, type KeyBinding as a6, type MatchOutcome as a7, type MatchResult as a8, type ModeShortcutHandlers as a9, type SelectionApi as aA, type SelectionExtendKey as aB, type SelectionMode as aC, type Selector as aD, type SpecificityPart as aE, TOOL_OFFHAND_ID as aF, type Tool as aG, type ToolBounds as aH, type ToolCtx as aI, type ToolDef as aJ, type ToolKeybinding as aK, type ToolLifecycleCtx as aL, type ToolModifiers as aM, type ToolOffhandBindingSpec as aN, type ToolPresentation as aO, type ToolSlot as aP, type TraceLogEntry as aQ, type UiOngoingControl as aR, type View as aS, type WalkStep as aT, actionBindings as aU, actionItems as aV, buildDepsFromRequires as aW, buildRouteRegistry as aX, buildRuleCtx as aY, buildToolOffhandBindings as aZ, clientToCanvas as a_, type ModeSwitchLogEntry as aa, type ModifierState as ab, NEVER as ac, type NodeId as ad, type OngoingHandle as ae, type OngoingInvoker as af, type OngoingOverlay as ag, type OverlayRole as ah, type OverlaySchema as ai, PREDICATE_TARGET as aj, type PlacedBy as ak, type Point2 as al, type PointerSession as am, type PointerSessionCallbacks as an, type PointerSessionCancelReason as ao, type PointerSessionOptions as ap, type RankedCandidate as aq, type RecordCandidate as ar, type RegistryEntry as as, type ResizeAnchor as at, type ResolveAllOptions as au, type ResolveOnlyResult as av, type ResolvedCandidate as aw, type Rule as ax, type ScratchKey as ay, type ScratchStore as az, type DepSchema as b, createDepRegistry as b0, createDispatcher as b1, defineTool as b2, deleteScratch as b3, describeRule as b4, dlog as b5, evaluate as b6, evaluateEnabled as b7, filterEligible as b8, findConflicts as b9, pointerGestureId as bA, preferContextual as bB, publishLiveDispatch as bC, recordModeSwitch as bD, reportRouteConflicts as bE, resolveDeviceProfile as bF, resolveParams as bG, routesForSpec as bH, ruleCanHoldIn as bI, rulesExclusive as bJ, scopeBindings as bK, scratchKey as bL, setScratch as bM, targetConsultsAffordance as bN, validateActionDefaultBinding as bO, validateActionId as bP, getScratch as ba, isAnchor as bb, isAnchorOrControl as bc, isBody as bd, isControlHandle as be, isEditableTarget as bf, isEmpty as bg, isResizeHandle as bh, isRotateHandle as bi, isSelectedBody as bj, isTool as bk, isUnselectedBody as bl, itemsFromClipboardData as bm, itemsFromDataTransfer as bn, itemsFromFiles as bo, liveScope as bp, makeToolOffhandAction as bq, matchBest as br, matchSorted as bs, matchSortedWithBarred as bt, matchesKeyBinding as bu, mergeContributions as bv, modeShortcutSpec as bw, modeShortcuts as bx, offhandKeyFor as by, openPointerSession as bz, type DepRegistry as c, type DepName as d, type Action as e, DepNode as f, type AnyToolOf as g, type ScopedBinding as h, ALWAYS as i, type ActionDeps as j, ActionDisabledReason as k, type ActionDispatch as l, type ActionEnabledResult as m, type ActionEntry as n, type ActionItem as o, type ActionPresentation as p, type ActionSource as q, type ActionVariant as r, type ActionsProp as s, type AnyTool as t, type BindingScope as u, type BindingSource as v, type BodyPredicate as w, type BoundGesture as x, type Bounds as y, type BuildRuleCtxArgs as z };
2932
+ export { type GestureBinding as $, type ActionsRegistry as A, type BindingOpts as B, type Contribution as C, type DepRegistry as D, COARSE_TARGET_SCALE as E, type Condition as F, type Conflict as G, type ContributionChrome as H, type ContributionDeps as I, type ContributionRouting as J, type KernelOverlay as K, type LongPressOptions as L, DEFAULT_ALLOWED_CAPABILITIES as M, DEFAULT_DEVICE_PROFILE as N, type OverlayPosition as O, type DebugSink as P, type DetectedDeviceFacts as Q, type RuleCtx as R, ScopeNode as S, type DeviceProfile as T, type DispatchRecord as U, type DispatchRecordInput as V, type DispatcherContext as W, type DragSample as X, type DroppedCandidate as Y, type Eligibility as Z, type EligibilityState as _, type DepName as a, actionItems as a$, type HandleKind as a0, type HitShape as a1, type HotkeyTrigger as a2, INGEST_STRING_MIMES as a3, type ImmediateInvoker as a4, type InvocationCtx as a5, type Invoker as a6, type KeyBinding as a7, LONG_PRESS_MS as a8, type LongPressState as a9, type ResolveOnlyResult as aA, type ResolvedCandidate as aB, type Rule as aC, type ScratchKey as aD, type ScratchStore as aE, type SelectionApi as aF, type SelectionExtendKey as aG, type SelectionMode as aH, type Selector as aI, type SpecificityPart as aJ, TOOL_OFFHAND_ID as aK, type Tool as aL, type ToolBounds as aM, type ToolCtx as aN, type ToolDef as aO, type ToolKeybinding as aP, type ToolLifecycleCtx as aQ, type ToolModifiers as aR, type ToolOffhandBindingSpec as aS, type ToolPresentation as aT, type ToolSlot as aU, type TraceLogEntry as aV, type UiOngoingControl as aW, type View as aX, type ViewportGestureKind as aY, type WalkStep as aZ, actionBindings as a_, type LongPressStore as aa, type MatchOutcome as ab, type MatchResult as ac, type ModeShortcutHandlers as ad, type ModeSwitchLogEntry as ae, type ModifierState as af, NEVER as ag, type NodeId as ah, type OngoingHandle as ai, type OngoingInvoker as aj, type OngoingOverlay as ak, type OverlayRole as al, type OverlaySchema as am, PREDICATE_TARGET as an, type PendingLongPress as ao, type PlacedBy as ap, type Point2 as aq, type PointerSession as ar, type PointerSessionCallbacks as as, type PointerSessionCancelReason as at, type PointerSessionOptions as au, type RankedCandidate as av, type RecordCandidate as aw, type RegistryEntry as ax, type ResizeAnchor as ay, type ResolveAllOptions as az, type DepSchema as b, buildDepsFromRequires as b0, buildRouteRegistry as b1, buildRuleCtx as b2, buildToolOffhandBindings as b3, clientToCanvas as b4, clientToCanvasRect as b5, createDepRegistry as b6, createDispatcher as b7, createLongPressStore as b8, defineTool as b9, matchesKeyBinding as bA, mergeContributions as bB, modeShortcutSpec as bC, modeShortcuts as bD, offhandKeyFor as bE, openPointerSession as bF, pointerGestureId as bG, recordModeSwitch as bH, reportRouteConflicts as bI, resolveDeviceProfile as bJ, resolveParams as bK, routesForSpec as bL, ruleCanHoldIn as bM, rulesExclusive as bN, scopeBindings as bO, scratchKey as bP, setScratch as bQ, targetConsultsAffordance as bR, validateActionDefaultBinding as bS, validateActionId as bT, deleteScratch as ba, describeRule as bb, dlog as bc, evaluate as bd, evaluateEnabled as be, findConflicts as bf, getScratch as bg, isAnchor as bh, isAnchorOrControl as bi, isBody as bj, isControlHandle as bk, isEditableTarget as bl, isEmpty as bm, isResizeHandle as bn, isRotateHandle as bo, isSelectedBody as bp, isTool as bq, isUnselectedBody as br, itemsFromClipboardData as bs, itemsFromDataTransfer as bt, itemsFromFiles as bu, liveScope as bv, makeToolOffhandAction as bw, matchBest as bx, matchSorted as by, matchSortedWithBarred as bz, type Action as c, DepNode as d, type AnyToolOf as e, type ScopedBinding as f, type Dispatcher as g, type AffordanceHit as h, ALWAYS as i, type ActionDeps as j, ActionDisabledReason as k, type ActionDispatch as l, type ActionEnabledResult as m, type ActionEntry as n, type ActionItem as o, type ActionPresentation as p, type ActionSource as q, type ActionVariant as r, type ActionsProp as s, type AnyTool as t, type BindingScope as u, type BindingSource as v, type BodyPredicate as w, type BoundGesture as x, type Bounds as y, type BuildRuleCtxArgs as z };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { i as ALWAYS, e as Action, j as ActionDeps, k as ActionDisabledReason, k as ActionDisabledReasonValue, l as ActionDispatch, m as ActionEnabledResult, n as ActionEntry, o as ActionItem, p as ActionPresentation, q as ActionSource, r as ActionVariant, s as ActionsProp, A as ActionsRegistry, a as AffordanceHit, t as AnyTool, g as AnyToolOf, B as BindingOpts, u as BindingScope, v as BindingSource, w as BodyPredicate, x as BoundGesture, y as Bounds, z as BuildRuleCtxArgs, E as COARSE_TARGET_SCALE, F as Condition, G as Conflict, C as Contribution, H as ContributionChrome, I as ContributionDeps, J as ContributionRouting, L as DEFAULT_ALLOWED_CAPABILITIES, M as DEFAULT_DEVICE_PROFILE, N as DebugSink, d as DepName, c as DepRegistry, b as DepSchema, P as DetectedDeviceFacts, Q as DeviceProfile, T as DispatchRecord, U as DispatchRecordInput, D as Dispatcher, V as DispatcherContext, W as DragSample, X as DroppedCandidate, Y as Eligibility, Z as EligibilityState, _ as GestureBinding, $ as HandleKind, a0 as HitShape, a1 as HotkeyTrigger, a2 as INGEST_STRING_MIMES, a3 as ImmediateInvoker, a4 as InvocationCtx, a5 as Invoker, K as KernelOverlay, a6 as KeyBinding, a7 as MatchOutcome, a8 as MatchResult, a9 as ModeShortcutHandlers, aa as ModeSwitchLogEntry, ab as ModifierState, ac as NEVER, ad as NodeId, ae as OngoingHandle, af as OngoingInvoker, ag as OngoingOverlay, O as OverlayPosition, ah as OverlayRole, ai as OverlaySchema, aj as PREDICATE_TARGET, ak as PlacedBy, al as Point2, am as PointerSession, an as PointerSessionCallbacks, ao as PointerSessionCancelReason, ap as PointerSessionOptions, aq as RankedCandidate, ar as RecordCandidate, as as RegistryEntry, at as ResizeAnchor, au as ResolveAllOptions, av as ResolveOnlyResult, aw as ResolvedCandidate, ax as Rule, R as RuleCtx, h as ScopedBinding, ay as ScratchKey, az as ScratchStore, aA as SelectionApi, aB as SelectionExtendKey, aC as SelectionMode, aD as Selector, aE as SpecificityPart, aF as TOOL_OFFHAND_ID, aG as Tool, aH as ToolBounds, aI as ToolCtx, aJ as ToolDef, aK as ToolKeybinding, aL as ToolLifecycleCtx, aM as ToolModifiers, aN as ToolOffhandBindingSpec, aO as ToolPresentation, aP as ToolSlot, aQ as TraceLogEntry, aR as UiOngoingControl, aS as View, aT as WalkStep, aU as actionBindings, aV as actionItems, aW as buildDepsFromRequires, aX as buildRouteRegistry, aY as buildRuleCtx, aZ as buildToolOffhandBindings, a_ as clientToCanvas, a$ as clientToCanvasRect, b0 as createDepRegistry, b1 as createDispatcher, b2 as defineTool, b3 as deleteScratch, b4 as describeRule, b5 as dlog, b6 as evaluate, b7 as evaluateEnabled, b8 as filterEligible, b9 as findConflicts, ba as getScratch, bb as isAnchor, bc as isAnchorOrControl, bd as isBody, be as isControlHandle, bf as isEditableTarget, bg as isEmpty, bh as isResizeHandle, bi as isRotateHandle, bj as isSelectedBody, bk as isTool, bl as isUnselectedBody, bm as itemsFromClipboardData, bn as itemsFromDataTransfer, bo as itemsFromFiles, bp as liveScope, bq as makeToolOffhandAction, br as matchBest, bs as matchSorted, bt as matchSortedWithBarred, bu as matchesKeyBinding, bv as mergeContributions, bw as modeShortcutSpec, bx as modeShortcuts, by as offhandKeyFor, bz as openPointerSession, bA as pointerGestureId, bB as preferContextual, bC as publishLiveDispatch, bD as recordModeSwitch, bE as reportRouteConflicts, bF as resolveDeviceProfile, bG as resolveParams, bH as routesForSpec, bI as ruleCanHoldIn, bJ as rulesExclusive, bK as scopeBindings, bL as scratchKey, bM as setScratch, bN as targetConsultsAffordance, bO as validateActionDefaultBinding, bP as validateActionId } from './index-Bmq4lSHY.js';
1
+ export { i as ALWAYS, c as Action, j as ActionDeps, k as ActionDisabledReason, k as ActionDisabledReasonValue, l as ActionDispatch, m as ActionEnabledResult, n as ActionEntry, o as ActionItem, p as ActionPresentation, q as ActionSource, r as ActionVariant, s as ActionsProp, A as ActionsRegistry, h as AffordanceHit, t as AnyTool, e as AnyToolOf, B as BindingOpts, u as BindingScope, v as BindingSource, w as BodyPredicate, x as BoundGesture, y as Bounds, z as BuildRuleCtxArgs, E as COARSE_TARGET_SCALE, F as Condition, G as Conflict, C as Contribution, H as ContributionChrome, I as ContributionDeps, J as ContributionRouting, M as DEFAULT_ALLOWED_CAPABILITIES, N as DEFAULT_DEVICE_PROFILE, P as DebugSink, a as DepName, D as DepRegistry, b as DepSchema, Q as DetectedDeviceFacts, T as DeviceProfile, U as DispatchRecord, V as DispatchRecordInput, g as Dispatcher, W as DispatcherContext, X as DragSample, Y as DroppedCandidate, Z as Eligibility, _ as EligibilityState, $ as GestureBinding, a0 as HandleKind, a1 as HitShape, a2 as HotkeyTrigger, a3 as INGEST_STRING_MIMES, a4 as ImmediateInvoker, a5 as InvocationCtx, a6 as Invoker, K as KernelOverlay, a7 as KeyBinding, a8 as LONG_PRESS_MS, L as LongPressOptions, a9 as LongPressState, aa as LongPressStore, ab as MatchOutcome, ac as MatchResult, ad as ModeShortcutHandlers, ae as ModeSwitchLogEntry, af as ModifierState, ag as NEVER, ah as NodeId, ai as OngoingHandle, aj as OngoingInvoker, ak as OngoingOverlay, O as OverlayPosition, al as OverlayRole, am as OverlaySchema, an as PREDICATE_TARGET, ao as PendingLongPress, ap as PlacedBy, aq as Point2, ar as PointerSession, as as PointerSessionCallbacks, at as PointerSessionCancelReason, au as PointerSessionOptions, av as RankedCandidate, aw as RecordCandidate, ax as RegistryEntry, ay as ResizeAnchor, az as ResolveAllOptions, aA as ResolveOnlyResult, aB as ResolvedCandidate, aC as Rule, R as RuleCtx, f as ScopedBinding, aD as ScratchKey, aE as ScratchStore, aF as SelectionApi, aG as SelectionExtendKey, aH as SelectionMode, aI as Selector, aJ as SpecificityPart, aK as TOOL_OFFHAND_ID, aL as Tool, aM as ToolBounds, aN as ToolCtx, aO as ToolDef, aP as ToolKeybinding, aQ as ToolLifecycleCtx, aR as ToolModifiers, aS as ToolOffhandBindingSpec, aT as ToolPresentation, aU as ToolSlot, aV as TraceLogEntry, aW as UiOngoingControl, aX as View, aY as ViewportGestureKind, aZ as WalkStep, a_ as actionBindings, a$ as actionItems, b0 as buildDepsFromRequires, b1 as buildRouteRegistry, b2 as buildRuleCtx, b3 as buildToolOffhandBindings, b4 as clientToCanvas, b5 as clientToCanvasRect, b6 as createDepRegistry, b7 as createDispatcher, b8 as createLongPressStore, b9 as defineTool, ba as deleteScratch, bb as describeRule, bc as dlog, bd as evaluate, be as evaluateEnabled, bf as findConflicts, bg as getScratch, bh as isAnchor, bi as isAnchorOrControl, bj as isBody, bk as isControlHandle, bl as isEditableTarget, bm as isEmpty, bn as isResizeHandle, bo as isRotateHandle, bp as isSelectedBody, bq as isTool, br as isUnselectedBody, bs as itemsFromClipboardData, bt as itemsFromDataTransfer, bu as itemsFromFiles, bv as liveScope, bw as makeToolOffhandAction, bx as matchBest, by as matchSorted, bz as matchSortedWithBarred, bA as matchesKeyBinding, bB as mergeContributions, bC as modeShortcutSpec, bD as modeShortcuts, bE as offhandKeyFor, bF as openPointerSession, bG as pointerGestureId, bH as recordModeSwitch, bI as reportRouteConflicts, bJ as resolveDeviceProfile, bK as resolveParams, bL as routesForSpec, bM as ruleCanHoldIn, bN as rulesExclusive, bO as scopeBindings, bP as scratchKey, bQ as setScratch, bR as targetConsultsAffordance, bS as validateActionDefaultBinding, bT as validateActionId } from './index-BV53gfyB.js';
2
2
  export { ChannelRef, DRAG_THRESHOLD_PX, DescribeRouteOptions, GESTURE_DESCRIPTORS, GestureArgSpec, GestureDescriptor, GestureName, IngestItem, InputEvent, ModRequirement, ModifierKey, ParsedModifiers, ParsedRoute, PhaseAtom, PhaseContext, RESERVED_ID_NAMES, RESERVED_ID_PREFIXES, ROUTE_FIELD_DEFINITIONS, ROUTE_TERMS, RouteDescriptionPart, RouteFieldName, RouteTermLabel, canonicalModifiers, collapseShiftPairs, describeRoute, describeRouteParts, formatPhaseAtom, formatRoute, getGestureDescriptor, isKnownGestureName, matchKey, matchModifiers, matchPhase, matchSpec, matchTarget, parseRoute, pastDragThreshold, routeGestureForSpecKind, specKindForRouteGesture, specificity } from '@weasel-js/gestures';
3
3
  import '@weasel-js/modes';
4
4
  import 'react';
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { isDev } from './chunk-Q3Y3DPKH.js';
2
- export { ALWAYS, COARSE_TARGET_SCALE, DEFAULT_ALLOWED_CAPABILITIES, DEFAULT_DEVICE_PROFILE, GESTURE_DESCRIPTORS, INGEST_STRING_MIMES, NEVER, PREDICATE_TARGET, RESERVED_ID_NAMES, RESERVED_ID_PREFIXES, ROUTE_FIELD_DEFINITIONS, ROUTE_TERMS, TOOL_OFFHAND_ID, actionBindings, buildDepsFromRequires, buildRouteRegistry, buildRuleCtx, buildToolOffhandBindings, canonicalModifiers, clientToCanvas, clientToCanvasRect, collapseShiftPairs, createDepRegistry, createDispatcher, describeRoute, describeRouteParts, describeRule, dlog, evaluate, filterEligible, findConflicts, formatPhaseAtom, formatRoute, getGestureDescriptor, isEditableTarget, isKnownGestureName, isTool, itemsFromClipboardData, itemsFromDataTransfer, itemsFromFiles, liveScope, makeToolOffhandAction, matchBest, matchKey, matchModifiers, matchPhase, matchSorted, matchSortedWithBarred, matchSpec, matchTarget, matchesKeyBinding, offhandKeyFor, openPointerSession, parseRoute, pointerGestureId, preferContextual, publishLiveDispatch, recordModeSwitch, reportRouteConflicts, resolveDeviceProfile, resolveParams, routeGestureForSpecKind, routesForSpec, ruleCanHoldIn, rulesExclusive, scopeBindings, specKindForRouteGesture, specificity, targetConsultsAffordance, validateActionDefaultBinding, validateActionId } from './chunk-Q3Y3DPKH.js';
1
+ import { isDev } from './chunk-ZGKJWZ4S.js';
2
+ export { ALWAYS, COARSE_TARGET_SCALE, DEFAULT_ALLOWED_CAPABILITIES, DEFAULT_DEVICE_PROFILE, GESTURE_DESCRIPTORS, INGEST_STRING_MIMES, LONG_PRESS_MS, NEVER, PREDICATE_TARGET, RESERVED_ID_NAMES, RESERVED_ID_PREFIXES, ROUTE_FIELD_DEFINITIONS, ROUTE_TERMS, TOOL_OFFHAND_ID, actionBindings, buildDepsFromRequires, buildRouteRegistry, buildRuleCtx, buildToolOffhandBindings, canonicalModifiers, clientToCanvas, clientToCanvasRect, collapseShiftPairs, createDepRegistry, createDispatcher, createLongPressStore, describeRoute, describeRouteParts, describeRule, dlog, evaluate, findConflicts, formatPhaseAtom, formatRoute, getGestureDescriptor, isEditableTarget, isKnownGestureName, isTool, itemsFromClipboardData, itemsFromDataTransfer, itemsFromFiles, liveScope, makeToolOffhandAction, matchBest, matchKey, matchModifiers, matchPhase, matchSorted, matchSortedWithBarred, matchSpec, matchTarget, matchesKeyBinding, offhandKeyFor, openPointerSession, parseRoute, pointerGestureId, recordModeSwitch, reportRouteConflicts, resolveDeviceProfile, resolveParams, routeGestureForSpecKind, routesForSpec, ruleCanHoldIn, rulesExclusive, scopeBindings, specKindForRouteGesture, specificity, targetConsultsAffordance, validateActionDefaultBinding, validateActionId } from './chunk-ZGKJWZ4S.js';
3
3
  import { RESERVED_ID_PREFIXES, RESERVED_ID_NAMES } from '@weasel-js/gestures';
4
4
  export { DRAG_THRESHOLD_PX, pastDragThreshold } from '@weasel-js/gestures';
5
5
  import { modeLabel } from '@weasel-js/modes';
@@ -0,0 +1,275 @@
1
+ import { g as Dispatcher, A as ActionsRegistry, C as Contribution, h as AffordanceHit, L as LongPressOptions, R as RuleCtx, b as DepSchema } from './index-BV53gfyB.js';
2
+ import { RefObject } from 'react';
3
+ import { BodyClassification } from '@weasel-js/gestures';
4
+ import { PaintedCursorState } from '@weasel-js/cursor';
5
+
6
+ /**
7
+ * Everything about handling an input event that depends on *which view* it
8
+ * landed in: the dispatcher that runs it, and the three lookups that resolve
9
+ * a client point against that view's camera.
10
+ *
11
+ * @internal One per view. The hook builds the `id: null` one from its flat
12
+ * options; `views` supplies the rest, and the hook chooses between them per
13
+ * event, so that it — and its listener set — still mounts exactly once.
14
+ */
15
+ interface DispatcherViewTarget {
16
+ /** `null` is the root view — the whole canvas. Matches `ViewTarget.id`. */
17
+ id: string | null;
18
+ dispatcher: Dispatcher;
19
+ affordanceAt: UseGestureDispatcherOptions['affordanceAt'];
20
+ classifyTarget: UseGestureDispatcherOptions['classifyTarget'];
21
+ clientToWorld: UseGestureDispatcherOptions['clientToWorld'];
22
+ /**
23
+ * The deps this view answers for itself — its camera, its selection, and
24
+ * whatever else is per-view rather than per-canvas. Read per event; every
25
+ * name it does not carry still resolves through the canvas registry.
26
+ *
27
+ * This is why a view does not get a `DepRegistryProvider` of its own. The
28
+ * registry is where a consumer registers *sources*, and one per view would
29
+ * fragment that: a consumer overriding `insert` would have to know how many
30
+ * views exist and override each. An overlay keeps one place to register and
31
+ * one authority per dep, with the view claiming only what is genuinely its.
32
+ *
33
+ * Without this a gesture inside a panel pans the whole canvas and selects
34
+ * into the canvas's selection — correct coordinates alone do not make
35
+ * routing correct.
36
+ */
37
+ deps?: () => Partial<DepSchema>;
38
+ /**
39
+ * This view's chrome-caps rule context, for the eligibility filter. The rule
40
+ * table is the surface's, but a rule keyed on selection or the in-flight
41
+ * action answers per view — so an action hidden in one panel must not
42
+ * decline a gesture in another. `undefined` means "nothing gates here", the
43
+ * same answer a surface with no mode registry gives.
44
+ */
45
+ getRuleCtx?: () => RuleCtx | undefined;
46
+ }
47
+ /**
48
+ * The part of `features/viewports`' `ViewResolver` the dispatcher needs: which
49
+ * view a client point belongs to, pinned to the view a gesture began in.
50
+ *
51
+ * @internal Structural on purpose — a `ViewResolver` satisfies it, and the
52
+ * dispatcher stays free of the viewport module.
53
+ */
54
+ interface ViewIdResolver {
55
+ begin(pointerId: number, clientX: number, clientY: number): {
56
+ id: string | null;
57
+ };
58
+ at(pointerId: number | null, clientX: number, clientY: number): {
59
+ id: string | null;
60
+ };
61
+ end(pointerId: number): void;
62
+ }
63
+ /** Per-channel switches for the listeners `useGestureDispatcher` attaches to
64
+ * the canvas element. Omitted or `true` attaches the channel. */
65
+ interface DispatcherChannels {
66
+ /** `pointerdown`, hover `pointermove`, `pointerleave` — press, drag, click,
67
+ * long-press, multi-touch and the hover-cursor pump. */
68
+ pointer?: boolean;
69
+ /** `wheel`. */
70
+ wheel?: boolean;
71
+ /** WebKit's `gesturestart` / `gesturechange` / `gestureend` — Safari's
72
+ * trackpad pinch, dispatched as `pinch` events. */
73
+ pinch?: boolean;
74
+ /** `contextmenu`. Off leaves the browser's native menu in place. */
75
+ contextMenu?: boolean;
76
+ /** OS drop on the element plus `paste` on the window. Off leaves the
77
+ * element a non-drop-target and stops `weasel-dropover` being applied. */
78
+ ingest?: boolean;
79
+ }
80
+ /** Options for `useGestureDispatcher`: the element to listen on, the actions
81
+ * and tools in play, and the hooks that turn raw DOM events into the world
82
+ * coordinates and hit targets bindings match against. */
83
+ interface UseGestureDispatcherOptions {
84
+ /** Ref to the canvas element. Pointer/wheel/multitouch listeners attach here. */
85
+ canvasRef: RefObject<HTMLElement | null>;
86
+ /** Action registry (ActionsRegistry from registry.tsx). */
87
+ actions: ActionsRegistry;
88
+ /** Tool definitions keyed by id. Typically passes an empty Map. */
89
+ entriesById: ReadonlyMap<string, Contribution<unknown>>;
90
+ /** Default true. Set false to opt out of dispatcher wiring (e.g. demos that disable it). */
91
+ enabled?: boolean;
92
+ /**
93
+ * Observer fired whenever the dispatcher synthesizes a double click, in
94
+ * world coordinates. Runs BEFORE the event is dispatched and independently
95
+ * of which binding (if any) handles it.
96
+ *
97
+ * This is deliberately not an Action. `<SceneCanvas onDoubleClick>` is a
98
+ * notification — "the user double-clicked, here's what they hit" — and a
99
+ * notification must not compete with behavior for the gesture. As a binding
100
+ * it would lose to `enterPathEdit` on any body hit and silently never fire.
101
+ * Routing it here keeps a single definition of "double click" (the point of
102
+ * consolidating the kit's three detectors) without giving it
103
+ * first-match-wins semantics it shouldn't have.
104
+ */
105
+ onDoubleClick?: (world: {
106
+ x: number;
107
+ y: number;
108
+ }) => void;
109
+ /**
110
+ * Default true. Set false to leave the window `keydown`/`keyup` listeners
111
+ * unattached so keyboard-bound actions never dispatch — pointer, wheel, and
112
+ * contextmenu channels stay live. `<SceneCanvas>` wires this to
113
+ * `enableKeybindings`, so opting out of keybindings disables the modern
114
+ * dispatcher key path as well as the legacy `useKeybindings` hook.
115
+ *
116
+ * Every dispatcher hears keys on `window`, and a keystroke one of them
117
+ * claims — or anything else calls `preventDefault` on — is not dispatched by
118
+ * the rest. `'first'` listens in the capture phase, so this dispatcher gets
119
+ * the keystroke ahead of every dispatcher listening normally, whatever the
120
+ * mount order: the shape for chrome that owns a key only when it can act.
121
+ */
122
+ keyboard?: boolean | 'first';
123
+ /**
124
+ * Optional affordance classifier. Called with the **world** coordinates of
125
+ * the pointer — this hook applies the routed view's `clientToWorld` before
126
+ * calling it, the same conversion that produces `InputEvent.x`/`y`, so a
127
+ * consumer hit-tests in one space. Returns an `AffordanceHit` when the
128
+ * pointer lands on a known affordance (resize handle, rotate handle, etc.)
129
+ * or `null` when the pointer hit open canvas.
130
+ *
131
+ * The hit is packed into `InputEvent.pointerdown.affordance` and flows
132
+ * through into `InvocationCtx.drag.affordance`. Action invokers that require
133
+ * a specific affordance (e.g. `resizeAction` requires `handle:*`) use this
134
+ * field as a guard in their `start` body.
135
+ *
136
+ * When omitted, `affordance` is always `undefined` — meaning only consumers
137
+ * that explicitly wire a classifier get affordance-gated behavior.
138
+ * `<SceneCanvas>` wires the full chrome→dispatcher bridge.
139
+ */
140
+ affordanceAt?: (worldPoint: {
141
+ x: number;
142
+ y: number;
143
+ }) => AffordanceHit | null;
144
+ /**
145
+ * Optional body classifier. Called on every pointerdown with the world-space
146
+ * coordinates of the pointer. Its result is packed onto the event as
147
+ * `bodyTarget` + `bodyKind`, which `matchTarget` reads to resolve the
148
+ * string-form `TargetSpec` values in `Tool.bindings`.
149
+ *
150
+ * `body` is `'empty'` when nothing is under the pointer, `'selected-body'`
151
+ * when the topmost hit belongs to the current selection, or
152
+ * `'unselected-body'` when it belongs to a node that isn't selected. `kind`
153
+ * is the hit node's semantic kind, when the scene can name it.
154
+ *
155
+ * When omitted, every body-derived target form (`'empty'`,
156
+ * `'selected-body'`, `'unselected-body'`, `kind:<k>`, `kind:<k>:selected`)
157
+ * never matches — bindings using those specs are silently skipped.
158
+ * `<SceneCanvas>` wires this.
159
+ *
160
+ * World coordinates, on every path, for the same reason as `affordanceAt`.
161
+ */
162
+ classifyTarget?: (worldPoint: {
163
+ x: number;
164
+ y: number;
165
+ }) => BodyClassification;
166
+ /**
167
+ * Optional pre-created `Dispatcher`. When provided, this hook pumps events
168
+ * into the supplied instance instead of creating its own. Lets a parent
169
+ * scope (e.g. `<SceneCanvas>`) share one dispatcher between the gesture
170
+ * mounter and other consumers (the preview-ghost layer).
171
+ */
172
+ dispatcher?: Dispatcher;
173
+ /**
174
+ * Converts a client-space pointer position (e.g. `e.clientX`, `e.clientY`)
175
+ * to world-space coordinates. When supplied, every pointer/wheel event's
176
+ * `x`/`y` is converted before the dispatcher builds `InvocationCtx.world`.
177
+ *
178
+ * Without this, `ctx.world` is populated with the raw client coords, which
179
+ * silently breaks any action whose overlay/output uses absolute world
180
+ * positions (marquee, lasso polyline, world-space affordances). Actions
181
+ * that only read `drag.delta` are unaffected because client→world deltas
182
+ * are equal at scale 1, but as soon as a consumer pans/zooms the view the
183
+ * deltas diverge too.
184
+ *
185
+ * `<SceneCanvas>` always wires this via its canvas rect + current view.
186
+ * Tests / harnesses without a view can omit it and continue passing raw
187
+ * coordinates as before.
188
+ */
189
+ clientToWorld?: (clientX: number, clientY: number) => {
190
+ x: number;
191
+ y: number;
192
+ };
193
+ /**
194
+ * Invoked once per pump event (`pointermove`, `pointerup`, `pointercancel`,
195
+ * `key-held` up-phase, `multitouch` move) when a dispatcher-side handle is
196
+ * in flight. Lets the host canvas schedule a redraw so dispatcher-only
197
+ * overlays (marquee, lasso, preview-ghost) repaint on each frame.
198
+ *
199
+ * Required because dispatcher actions don't go through the legacy
200
+ * `tools.dispatcher.onGestureChange` redraw bump that ambient tool drags
201
+ * relied on. Without it, the overlay layer's `draw` never runs between
202
+ * pointerdown and pointerup, and the chrome flashes once at gesture start
203
+ * and then sits frozen until the gesture ends.
204
+ *
205
+ * `<SceneCanvas>` wires this to the canvas's `requestRedraw`. Test
206
+ * harnesses can omit it; their dispatchers won't paint between events but
207
+ * that's already the test contract.
208
+ */
209
+ requestRedraw?: () => void;
210
+ /**
211
+ * The surface's painted-cursor channel, read live because the canvas handle
212
+ * it lives on arrives a render after this hook runs.
213
+ *
214
+ * Given one, a cursor the CSS tier cannot express — sized in world units, or
215
+ * past the size the browser drops the image at — is published here and drawn
216
+ * by the painted-cursor layer instead. Without one, such a cursor resolves to
217
+ * `none` and the pointer shows nothing.
218
+ */
219
+ paintedCursor?: () => PaintedCursorState | undefined;
220
+ /** How touch and pen long-presses are timed, published and felt. */
221
+ longPress?: LongPressOptions;
222
+ /**
223
+ * Thunk returning the live `RuleCtx` for the current frame. When supplied,
224
+ * the dispatcher filters matched candidates by their declared
225
+ * `Action.eligible` rule (omitted => always eligible). `<SceneCanvas>`
226
+ * wires this; tests / harnesses without chrome-caps state can omit it.
227
+ */
228
+ getRuleCtx?: () => RuleCtx | undefined;
229
+ /**
230
+ * Which of the canvas element's input channels to attach. Every one
231
+ * defaults to `true`; naming a channel `false` leaves its listeners
232
+ * unattached, so the element behaves as if the dispatcher were not there.
233
+ *
234
+ * A mount that binds two gestures should not also have to take the rest of
235
+ * the pipeline's side effects: `contextMenu` suppresses the native menu
236
+ * unconditionally, and `ingest` makes the element a valid drop target and
237
+ * styles it while an OS drag hovers. `@weasel-js/labkit`'s loupe mounts on
238
+ * a lab's own canvas host for a wheel and a held key, and turning the other
239
+ * three off is what keeps right-click and file drops working there.
240
+ *
241
+ * The window keyboard channel is `keyboard` instead of an entry here,
242
+ * because `<SceneCanvas enableKeybindings>` drives it.
243
+ */
244
+ channels?: DispatcherChannels;
245
+ /**
246
+ * Routing for a canvas hosting more than one view: the non-root dispatch
247
+ * records to choose between, read fresh per event, and the resolver that
248
+ * chooses. Omit for a single view — then every event runs on the record the
249
+ * flat options above describe, which is what they are: view zero.
250
+ *
251
+ * A resolved id with no live record falls back to the root, so a view that
252
+ * unmounts mid-gesture degrades instead of dropping the event.
253
+ *
254
+ * Keyboard and paste have no coordinates to resolve; they run on the view
255
+ * the last coordinate-bearing event resolved to.
256
+ *
257
+ * @internal
258
+ */
259
+ views?: {
260
+ targets: () => readonly DispatcherViewTarget[];
261
+ resolver: ViewIdResolver;
262
+ };
263
+ }
264
+ /**
265
+ * Attach the input pipeline to a canvas: DOM pointer, wheel, keyboard and
266
+ * multitouch listeners in, normalized input events out, routed through the
267
+ * dispatcher to whichever action a binding names.
268
+ *
269
+ * Everything it needs beyond its options — the active tool, the dep registry —
270
+ * comes from context, so it must be mounted inside `<SceneCanvas>`'s
271
+ * providers.
272
+ */
273
+ declare function useGestureDispatcher(opts: UseGestureDispatcherOptions): void;
274
+
275
+ export { type DispatcherChannels as D, type UseGestureDispatcherOptions as U, type ViewIdResolver as V, type DispatcherViewTarget as a, useGestureDispatcher as u };
@@ -0,0 +1,7 @@
1
+ export { a as DispatcherViewTarget, V as ViewIdResolver } from './internal--mYnGecm.js';
2
+ import './index-BV53gfyB.js';
3
+ import '@weasel-js/modes';
4
+ import 'react';
5
+ import '@weasel-js/cursor';
6
+ import '@weasel-js/gestures';
7
+ import '@weasel-js/history';
@@ -0,0 +1,3 @@
1
+
2
+ //# sourceMappingURL=internal.js.map
3
+ //# sourceMappingURL=internal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"internal.js"}