@weasel-js/routing 1.7.0 → 1.7.1

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.
package/dist/react.d.ts CHANGED
@@ -1,278 +1,12 @@
1
- import { D as Dispatcher, A as ActionsRegistry, C as Contribution, a as AffordanceHit, R as RuleCtx, b as DepSchema, c as DepRegistry, d as DepName, S as ScopeNode, e as Action, f as DepNode, K as KernelOverlay, g as AnyToolOf, O as OverlayPosition, h as ScopedBinding } from './index-Bmq4lSHY.js';
1
+ export { D as DispatcherChannels, U as UseGestureDispatcherOptions, u as useGestureDispatcher } from './internal--mYnGecm.js';
2
2
  import * as react from 'react';
3
- import { RefObject, ReactNode, ReactElement } from 'react';
4
- import { BodyClassification } from '@weasel-js/gestures';
5
- import { PaintedCursorState } from '@weasel-js/cursor';
3
+ import { ReactNode, ReactElement } from 'react';
4
+ import { D as DepRegistry, a as DepName, b as DepSchema, S as ScopeNode, A as ActionsRegistry, c as Action, d as DepNode, K as KernelOverlay, C as Contribution, e as AnyToolOf, O as OverlayPosition, f as ScopedBinding } from './index-BV53gfyB.js';
6
5
  import { ModeRegistry } from '@weasel-js/modes';
6
+ import '@weasel-js/gestures';
7
+ import '@weasel-js/cursor';
7
8
  import '@weasel-js/history';
8
9
 
9
- /**
10
- * Everything about handling an input event that depends on *which view* it
11
- * landed in: the dispatcher that runs it, and the three lookups that resolve
12
- * a client point against that view's camera.
13
- *
14
- * @internal One per view. The hook builds the `id: null` one from its flat
15
- * options; `views` supplies the rest, and the hook chooses between them per
16
- * event, so that it — and its listener set — still mounts exactly once.
17
- */
18
- interface DispatcherViewTarget {
19
- /** `null` is the root view — the whole canvas. Matches `ViewTarget.id`. */
20
- id: string | null;
21
- dispatcher: Dispatcher;
22
- affordanceAt: UseGestureDispatcherOptions['affordanceAt'];
23
- classifyTarget: UseGestureDispatcherOptions['classifyTarget'];
24
- clientToWorld: UseGestureDispatcherOptions['clientToWorld'];
25
- /**
26
- * The deps this view answers for itself — its camera, its selection, and
27
- * whatever else is per-view rather than per-canvas. Read per event; every
28
- * name it does not carry still resolves through the canvas registry.
29
- *
30
- * This is why a view does not get a `DepRegistryProvider` of its own. The
31
- * registry is where a consumer registers *sources*, and one per view would
32
- * fragment that: a consumer overriding `insert` would have to know how many
33
- * views exist and override each. An overlay keeps one place to register and
34
- * one authority per dep, with the view claiming only what is genuinely its.
35
- *
36
- * Without this a gesture inside a panel pans the whole canvas and selects
37
- * into the canvas's selection — correct coordinates alone do not make
38
- * routing correct.
39
- */
40
- deps?: () => Partial<DepSchema>;
41
- /**
42
- * This view's chrome-caps rule context, for the eligibility filter. The rule
43
- * table is the surface's, but a rule keyed on selection or the in-flight
44
- * action answers per view — so an action hidden in one panel must not
45
- * decline a gesture in another. `undefined` means "nothing gates here", the
46
- * same answer a surface with no mode registry gives.
47
- */
48
- getRuleCtx?: () => RuleCtx | undefined;
49
- }
50
- /**
51
- * The part of `features/viewports`' `ViewResolver` the dispatcher needs: which
52
- * view a client point belongs to, pinned to the view a gesture began in.
53
- *
54
- * @internal Structural on purpose — a `ViewResolver` satisfies it, and the
55
- * dispatcher stays free of the viewport module.
56
- */
57
- interface ViewIdResolver {
58
- begin(pointerId: number, clientX: number, clientY: number): {
59
- id: string | null;
60
- };
61
- at(pointerId: number | null, clientX: number, clientY: number): {
62
- id: string | null;
63
- };
64
- end(pointerId: number): void;
65
- }
66
- /** Per-channel switches for the listeners `useGestureDispatcher` attaches to
67
- * the canvas element. Omitted or `true` attaches the channel. */
68
- interface DispatcherChannels {
69
- /** `pointerdown`, hover `pointermove`, `pointerleave` — press, drag, click,
70
- * long-press, multi-touch and the hover-cursor pump. */
71
- pointer?: boolean;
72
- /** `wheel`. */
73
- wheel?: boolean;
74
- /** WebKit's `gesturestart` / `gesturechange` / `gestureend` — Safari's
75
- * trackpad pinch, dispatched as `pinch` events. */
76
- pinch?: boolean;
77
- /** `contextmenu`. Off leaves the browser's native menu in place. */
78
- contextMenu?: boolean;
79
- /** OS drop on the element plus `paste` on the window. Off leaves the
80
- * element a non-drop-target and stops `weasel-dropover` being applied. */
81
- ingest?: boolean;
82
- }
83
- /** Options for `useGestureDispatcher`: the element to listen on, the actions
84
- * and tools in play, and the hooks that turn raw DOM events into the world
85
- * coordinates and hit targets bindings match against. */
86
- interface UseGestureDispatcherOptions {
87
- /** Ref to the canvas element. Pointer/wheel/multitouch listeners attach here. */
88
- canvasRef: RefObject<HTMLElement | null>;
89
- /** Action registry (ActionsRegistry from registry.tsx). */
90
- actions: ActionsRegistry;
91
- /** Tool definitions keyed by id. Typically passes an empty Map. */
92
- entriesById: ReadonlyMap<string, Contribution<unknown>>;
93
- /** Default true. Set false to opt out of dispatcher wiring (e.g. demos that disable it). */
94
- enabled?: boolean;
95
- /**
96
- * Observer fired whenever the dispatcher synthesizes a double click, in
97
- * world coordinates. Runs BEFORE the event is dispatched and independently
98
- * of which binding (if any) handles it.
99
- *
100
- * This is deliberately not an Action. `<SceneCanvas onDoubleClick>` is a
101
- * notification — "the user double-clicked, here's what they hit" — and a
102
- * notification must not compete with behavior for the gesture. As a binding
103
- * it would lose to `enterPathEdit` on any body hit and silently never fire.
104
- * Routing it here keeps a single definition of "double click" (the point of
105
- * consolidating the kit's three detectors) without giving it
106
- * first-match-wins semantics it shouldn't have.
107
- */
108
- onDoubleClick?: (world: {
109
- x: number;
110
- y: number;
111
- }) => void;
112
- /**
113
- * Default true. Set false to leave the window `keydown`/`keyup` listeners
114
- * unattached so keyboard-bound actions never dispatch — pointer, wheel, and
115
- * contextmenu channels stay live. `<SceneCanvas>` wires this to
116
- * `enableKeybindings`, so opting out of keybindings disables the modern
117
- * dispatcher key path as well as the legacy `useKeybindings` hook.
118
- *
119
- * Every dispatcher hears keys on `window`, and a keystroke one of them
120
- * claims — or anything else calls `preventDefault` on — is not dispatched by
121
- * the rest. `'first'` listens in the capture phase, so this dispatcher gets
122
- * the keystroke ahead of every dispatcher listening normally, whatever the
123
- * mount order: the shape for chrome that owns a key only when it can act.
124
- */
125
- keyboard?: boolean | 'first';
126
- /**
127
- * Optional affordance classifier. Called with the **world** coordinates of
128
- * the pointer — this hook applies the routed view's `clientToWorld` before
129
- * calling it, the same conversion that produces `InputEvent.x`/`y`, so a
130
- * consumer hit-tests in one space. Returns an `AffordanceHit` when the
131
- * pointer lands on a known affordance (resize handle, rotate handle, etc.)
132
- * or `null` when the pointer hit open canvas.
133
- *
134
- * The hit is packed into `InputEvent.pointerdown.affordance` and flows
135
- * through into `InvocationCtx.drag.affordance`. Action invokers that require
136
- * a specific affordance (e.g. `resizeAction` requires `handle:*`) use this
137
- * field as a guard in their `start` body.
138
- *
139
- * When omitted, `affordance` is always `undefined` — meaning only consumers
140
- * that explicitly wire a classifier get affordance-gated behavior.
141
- * `<SceneCanvas>` wires the full chrome→dispatcher bridge.
142
- */
143
- affordanceAt?: (worldPoint: {
144
- x: number;
145
- y: number;
146
- }) => AffordanceHit | null;
147
- /**
148
- * Optional body classifier. Called on every pointerdown with the world-space
149
- * coordinates of the pointer. Its result is packed onto the event as
150
- * `bodyTarget` + `bodyKind`, which `matchTarget` reads to resolve the
151
- * string-form `TargetSpec` values in `Tool.bindings`.
152
- *
153
- * `body` is `'empty'` when nothing is under the pointer, `'selected-body'`
154
- * when the topmost hit belongs to the current selection, or
155
- * `'unselected-body'` when it belongs to a node that isn't selected. `kind`
156
- * is the hit node's semantic kind, when the scene can name it.
157
- *
158
- * When omitted, every body-derived target form (`'empty'`,
159
- * `'selected-body'`, `'unselected-body'`, `kind:<k>`, `kind:<k>:selected`)
160
- * never matches — bindings using those specs are silently skipped.
161
- * `<SceneCanvas>` wires this.
162
- *
163
- * World coordinates, on every path, for the same reason as `affordanceAt`.
164
- */
165
- classifyTarget?: (worldPoint: {
166
- x: number;
167
- y: number;
168
- }) => BodyClassification;
169
- /**
170
- * Optional pre-created `Dispatcher`. When provided, this hook pumps events
171
- * into the supplied instance instead of creating its own. Lets a parent
172
- * scope (e.g. `<SceneCanvas>`) share one dispatcher between the gesture
173
- * mounter and other consumers (the preview-ghost layer).
174
- */
175
- dispatcher?: Dispatcher;
176
- /**
177
- * Converts a client-space pointer position (e.g. `e.clientX`, `e.clientY`)
178
- * to world-space coordinates. When supplied, every pointer/wheel event's
179
- * `x`/`y` is converted before the dispatcher builds `InvocationCtx.world`.
180
- *
181
- * Without this, `ctx.world` is populated with the raw client coords, which
182
- * silently breaks any action whose overlay/output uses absolute world
183
- * positions (marquee, lasso polyline, world-space affordances). Actions
184
- * that only read `drag.delta` are unaffected because client→world deltas
185
- * are equal at scale 1, but as soon as a consumer pans/zooms the view the
186
- * deltas diverge too.
187
- *
188
- * `<SceneCanvas>` always wires this via its canvas rect + current view.
189
- * Tests / harnesses without a view can omit it and continue passing raw
190
- * coordinates as before.
191
- */
192
- clientToWorld?: (clientX: number, clientY: number) => {
193
- x: number;
194
- y: number;
195
- };
196
- /**
197
- * Invoked once per pump event (`pointermove`, `pointerup`, `pointercancel`,
198
- * `key-held` up-phase, `multitouch` move) when a dispatcher-side handle is
199
- * in flight. Lets the host canvas schedule a redraw so dispatcher-only
200
- * overlays (marquee, lasso, preview-ghost) repaint on each frame.
201
- *
202
- * Required because dispatcher actions don't go through the legacy
203
- * `tools.dispatcher.onGestureChange` redraw bump that ambient tool drags
204
- * relied on. Without it, the overlay layer's `draw` never runs between
205
- * pointerdown and pointerup, and the chrome flashes once at gesture start
206
- * and then sits frozen until the gesture ends.
207
- *
208
- * `<SceneCanvas>` wires this to the canvas's `requestRedraw`. Test
209
- * harnesses can omit it; their dispatchers won't paint between events but
210
- * that's already the test contract.
211
- */
212
- requestRedraw?: () => void;
213
- /**
214
- * The surface's painted-cursor channel, read live because the canvas handle
215
- * it lives on arrives a render after this hook runs.
216
- *
217
- * Given one, a cursor the CSS tier cannot express — sized in world units, or
218
- * past the size the browser drops the image at — is published here and drawn
219
- * by the painted-cursor layer instead. Without one, such a cursor resolves to
220
- * `none` and the pointer shows nothing.
221
- */
222
- paintedCursor?: () => PaintedCursorState | undefined;
223
- /**
224
- * Thunk returning the live `RuleCtx` for the current frame. When supplied,
225
- * the dispatcher filters matched candidates by their declared
226
- * `Action.eligible` rule (omitted => always eligible). `<SceneCanvas>`
227
- * wires this; tests / harnesses without chrome-caps state can omit it.
228
- */
229
- getRuleCtx?: () => RuleCtx | undefined;
230
- /**
231
- * Which of the canvas element's input channels to attach. Every one
232
- * defaults to `true`; naming a channel `false` leaves its listeners
233
- * unattached, so the element behaves as if the dispatcher were not there.
234
- *
235
- * A mount that binds two gestures should not also have to take the rest of
236
- * the pipeline's side effects: `contextMenu` suppresses the native menu
237
- * unconditionally, and `ingest` makes the element a valid drop target and
238
- * styles it while an OS drag hovers. `@weasel-js/labkit`'s loupe mounts on
239
- * a lab's own canvas host for a wheel and a held key, and turning the other
240
- * three off is what keeps right-click and file drops working there.
241
- *
242
- * The window keyboard channel is `keyboard` instead of an entry here,
243
- * because `<SceneCanvas enableKeybindings>` drives it.
244
- */
245
- channels?: DispatcherChannels;
246
- /**
247
- * Routing for a canvas hosting more than one view: the non-root dispatch
248
- * records to choose between, read fresh per event, and the resolver that
249
- * chooses. Omit for a single view — then every event runs on the record the
250
- * flat options above describe, which is what they are: view zero.
251
- *
252
- * A resolved id with no live record falls back to the root, so a view that
253
- * unmounts mid-gesture degrades instead of dropping the event.
254
- *
255
- * Keyboard and paste have no coordinates to resolve; they run on the view
256
- * the last coordinate-bearing event resolved to.
257
- *
258
- * @internal
259
- */
260
- views?: {
261
- targets: () => readonly DispatcherViewTarget[];
262
- resolver: ViewIdResolver;
263
- };
264
- }
265
- /**
266
- * Attach the input pipeline to a canvas: DOM pointer, wheel, keyboard and
267
- * multitouch listeners in, normalized input events out, routed through the
268
- * dispatcher to whichever action a binding names.
269
- *
270
- * Everything it needs beyond its options — the active tool, the dep registry —
271
- * comes from context, so it must be mounted inside `<SceneCanvas>`'s
272
- * providers.
273
- */
274
- declare function useGestureDispatcher(opts: UseGestureDispatcherOptions): void;
275
-
276
10
  /** Provides the dep registry for a canvas. `<SceneCanvas>` mounts one; a
277
11
  * consumer registering its own dep sources must be inside it. */
278
12
  declare function DepRegistryProvider({ children }: {
@@ -551,6 +285,7 @@ interface ToolsApi<TOverlay = KernelOverlay> {
551
285
  */
552
286
  declare function useTools<TOverlay = KernelOverlay>(opts: UseToolsOptions<TOverlay>): ToolsApi<TOverlay>;
553
287
 
288
+ /** Options for {@link useContributions}. */
554
289
  interface UseContributionsOptions<TOverlay = KernelOverlay> {
555
290
  /** Every registry entry, in declaration order. Order decides which of two
556
291
  * same-specificity bindings in one scope tier wins. */
@@ -563,6 +298,7 @@ interface UseContributionsOptions<TOverlay = KernelOverlay> {
563
298
  * registry it checks against the kit's `DEFAULT_MODES`. */
564
299
  modes?: ModeRegistry;
565
300
  }
301
+ /** The assembled registry {@link useContributions} returns. */
566
302
  interface ContributionsApi<TOverlay = KernelOverlay> {
567
303
  /** Every entry, as passed in. */
568
304
  entries: readonly Contribution<TOverlay>[];
@@ -597,4 +333,4 @@ declare function useContributions<TOverlay = KernelOverlay>(opts: UseContributio
597
333
  */
598
334
  declare function useOffhandAction(entries: readonly Contribution<unknown>[]): void;
599
335
 
600
- export { ActionsProvider, ActiveToolContextProvider, ActiveToolContextProviderIfRoot, type ActiveToolContextProviderProps, type ActiveToolContextValue, type ContributionsApi, DepRegistry, DepRegistryProvider, type DispatcherChannels, type DispatcherViewTarget, InputScope, type InputScopeProps, type OngoingAction, type ToolsApi, type UseContributionsOptions, type UseGestureDispatcherOptions, type UseToolsOptions, type ViewIdResolver, Yoke, type YokeProps, useAction, useActionsRegistry, useActiveToolContext, useContributions, useDepRegistry, useDepSource, useGestureDispatcher, useOffhandAction, useOngoingAction, useOptionalActiveToolContext, useOptionalDepRegistry, useTools, useYoke };
336
+ export { ActionsProvider, ActiveToolContextProvider, ActiveToolContextProviderIfRoot, type ActiveToolContextProviderProps, type ActiveToolContextValue, type ContributionsApi, DepRegistry, DepRegistryProvider, InputScope, type InputScopeProps, type OngoingAction, type ToolsApi, type UseContributionsOptions, type UseToolsOptions, Yoke, type YokeProps, useAction, useActionsRegistry, useActiveToolContext, useContributions, useDepRegistry, useDepSource, useOffhandAction, useOngoingAction, useOptionalActiveToolContext, useOptionalDepRegistry, useTools, useYoke };