@weasel-js/routing 1.10.0 → 1.11.0

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.
@@ -1,10 +1,14 @@
1
- import { PoseLinear, View } from '@weasel-js/geom';
2
- import * as react from 'react';
3
- import { ReactNode } from 'react';
4
- import { Emitter } from '@weasel-js/registry';
1
+ import { MenuEntry, Rect, MenuShortcut } from '@weasel-js/menu';
2
+ import { PrefGroup } from '@weasel-js/prefs';
3
+ import { FramedBox, View, Point } from '@weasel-js/geom';
5
4
  import { CapabilityTag, ActiveMode, ModeRegistry } from '@weasel-js/modes';
5
+ import { ModifierKey, ClaimableGesture, GestureSpec, IngestItem, BodyTarget, InputEvent, TargetSpec, KeyHeldSpec, TargetPredicate, KeySpec, ParsedModifiers, GestureName } from '@weasel-js/gestures';
6
+ import * as _weasel_js_icons from '@weasel-js/icons';
7
+ import { IconRef } from '@weasel-js/icons';
6
8
  import { CursorSpec } from '@weasel-js/cursor';
7
- import { ClaimableGesture, GestureSpec, IngestItem, InputEvent, TargetSpec, KeyHeldSpec, TargetPredicate, KeySpec, ParsedModifiers, GestureName } from '@weasel-js/gestures';
9
+ import * as react from 'react';
10
+ import { ReactNode } from 'react';
11
+ import { Emitter, QueryMatch } from '@weasel-js/registry';
8
12
  import '@weasel-js/select';
9
13
 
10
14
  /**
@@ -22,20 +26,9 @@ type NodeId = string & {
22
26
  readonly __brand: 'NodeId';
23
27
  };
24
28
 
25
- /**
26
- * Axis-aligned rectangle in world space. The optional `rotation` (radians,
27
- * around the AABB center) and `transform` (inside it, about the same center)
28
- * let chrome carry the frame a box is drawn in without a parallel type;
29
- * `poseFrameOf` composes the two.
30
- */
31
- interface Bounds {
32
- x: number;
33
- y: number;
34
- width: number;
35
- height: number;
36
- rotation?: number;
37
- transform?: PoseLinear;
38
- }
29
+ /** Axis-aligned rectangle in world space, with the frame it is drawn in;
30
+ * geom's `FramedBox`. */
31
+ type Bounds = FramedBox;
39
32
  /** The selection as routing reads and writes it. */
40
33
  interface SelectionApi {
41
34
  /** Current selection. Re-renders trigger when this reference changes. */
@@ -176,106 +169,6 @@ type ResizeAnchor = {
176
169
  y: 'min' | 'max' | 'free';
177
170
  };
178
171
 
179
- /**
180
- * The tree both input registries hang on. A provider is a root; every canvas
181
- * mounts a scope under the registry in scope; a yoke sits between the two. A
182
- * registration lives in the node it was made in, and a lookup starts at a leaf
183
- * and walks up, so one canvas never answers for another.
184
- */
185
-
186
- /** What every node of one tree shares: a version and the listeners to it. */
187
- interface ScopeTree {
188
- version: number;
189
- readonly listeners: Emitter;
190
- }
191
- declare class ScopeNode<N extends ScopeNode<N>> {
192
- readonly parent: N | null;
193
- readonly descends: boolean;
194
- readonly tree: ScopeTree;
195
- private readonly children;
196
- private activeChild;
197
- /** `descends`: whether reads made here answer from the active child down —
198
- * true for a root or a yoke, which chrome reads through; false for a scope,
199
- * which answers for itself even with a scope nested inside it. */
200
- constructor(parent: N | null, descends: boolean);
201
- /** Bump the tree's version and tell every listener in it. */
202
- changed(): void;
203
- /** Join the parent's children, newest last; returns the leave. */
204
- mount(): () => void;
205
- /** Make this node the one its ancestors resolve through. */
206
- activate(): void;
207
- /** The node a lookup made here starts from: down the active children, or the
208
- * newest where nothing has been activated yet. A yoke with no members yet
209
- * is passed over — there is no canvas behind it to answer. */
210
- leaf(): N;
211
- private newestMember;
212
- /** Where a read made through this node starts. */
213
- start(): N;
214
- /** Whether this node is on the path a read from the root takes. */
215
- isActive(): boolean;
216
- /** This node, then each ancestor up to the root. */
217
- chain(): Generator<N>;
218
- }
219
-
220
- /** Which tool is active, plus the stack of tools temporarily held active by a
221
- * hotkey (space-for-hand and the like). The dispatcher reads this to decide
222
- * whose bindings are in scope. */
223
- interface ActiveToolContextValue {
224
- /** The focused tool's id, or `null` when no tool holds the active slot —
225
- * a canvas can run on ambient bindings alone. */
226
- active: string | null;
227
- hotkeyStack: string[];
228
- setActive(id: string | null): void;
229
- pushHotkey(id: string): void;
230
- /**
231
- * Disengage a hotkey-held tool. With `id`, removes that tool's own entry
232
- * wherever it now sits — holds do not have to come up in the order they went
233
- * down, and popping the top would disengage a tool whose key is still held.
234
- * With no id, pops the top.
235
- */
236
- popHotkey(id?: string): void;
237
- }
238
- /**
239
- * One node of the tool tree. A node that `owns` a tool holds its state; one
240
- * that does not — a scope inside a yoke — reads and writes its yoke's.
241
- */
242
- declare class ToolNode extends ScopeNode<ToolNode> {
243
- private state;
244
- private value;
245
- constructor(parent: ToolNode | null, descends: boolean, owns: boolean, initialActive: string | null);
246
- /** The node whose tool a read here resolves to. */
247
- owner(): ToolNode;
248
- private update;
249
- /** A stable value per owner and state, for `useSyncExternalStore`. */
250
- snapshot(): ActiveToolContextValue;
251
- subscribe: (listener: () => void) => (() => void);
252
- }
253
- /** Props for `<ActiveToolContextProvider>`. */
254
- interface ActiveToolContextProviderProps {
255
- children: ReactNode;
256
- /** Seeds the active slot, and wins over the first `useTools` call's
257
- * `active`. Omitted, the slot starts empty and that call seeds it. */
258
- initialActive?: string | null;
259
- }
260
- /** Provides root active-tool state. Every canvas below has a tool of its own;
261
- * reads and writes here reach the one last used. */
262
- declare function ActiveToolContextProvider({ children, initialActive, }: ActiveToolContextProviderProps): react.JSX.Element;
263
- /** The active-tool state in scope. Throws outside a provider; use
264
- * `useOptionalActiveToolContext` where one is not guaranteed. */
265
- declare function useActiveToolContext(): ActiveToolContextValue;
266
- /**
267
- * Like `useActiveToolContext`, but returns `null` when no
268
- * `<ActiveToolContextProvider>` is in scope instead of throwing.
269
- */
270
- declare function useOptionalActiveToolContext(): ActiveToolContextValue | null;
271
- /**
272
- * Mounts an `<ActiveToolContextProvider>` only when no parent provider is in
273
- * scope; otherwise renders children unwrapped.
274
- */
275
- declare function ActiveToolContextProviderIfRoot({ children, }: {
276
- children: ReactNode;
277
- }): react.JSX.Element;
278
-
279
172
  /**
280
173
  * Live state read by rule evaluation. Built once per frame on the consuming
281
174
  * surface — chrome-caps, the affordance pipeline, the dispatcher's
@@ -523,6 +416,155 @@ declare function resolveDeviceProfile(detected: DetectedDeviceFacts, overrides?:
523
416
  */
524
417
  declare const DEFAULT_DEVICE_PROFILE: DeviceProfile;
525
418
 
419
+ /**
420
+ * Modifier roles: the modifiers an ongoing action reads while it runs, named
421
+ * by what they do rather than which key they are, so a binding or a tuning can
422
+ * move one to another key without forking the action.
423
+ */
424
+
425
+ /** The keys that hold a role: any one of them held holds it. `'mod'` is Cmd
426
+ * on a Mac and Ctrl elsewhere. An empty list never holds it. */
427
+ type RoleKeys = readonly ModifierKey[];
428
+ /** One modifier an action reads mid-gesture. */
429
+ interface ModifierRole {
430
+ label: string;
431
+ /** The keys that hold it unless a tuning or a binding says otherwise. */
432
+ keys: RoleKeys;
433
+ }
434
+ /** An action's roles by id, e.g. `'handle.holdAngle'`. */
435
+ type ModifierRoles = Readonly<Record<string, ModifierRole>>;
436
+ /** Keys a tuning or a binding gives some of an action's roles. */
437
+ type RoleRebinds = Readonly<Record<string, RoleKeys>>;
438
+ /** Whether any of `keys` is held. */
439
+ declare function keysHeld(keys: RoleKeys, modifiers: ModifierState, isMac: boolean): boolean;
440
+ /**
441
+ * A reader for an action's own roles. It answers from `ctx.roles`, which the
442
+ * dispatcher resolves on every event, and falls back to the role's default
443
+ * keys where nothing resolved them: an invoker called directly, or a context
444
+ * a cancel-all built with no event.
445
+ */
446
+ declare function roleReader<R extends ModifierRoles>(roles: R): (ctx: {
447
+ roles?: Readonly<Record<string, boolean>>;
448
+ modifiers: ModifierState;
449
+ }, id: keyof R & string) => boolean;
450
+
451
+ /** The chrome an in-flight gesture paints beside the scene. */
452
+
453
+ /**
454
+ * What a `polyline` overlay is, in a word — the narrowest thing an action can
455
+ * say about how its run should look without naming a paint.
456
+ *
457
+ * The named roles are the kit's; a painter maps each to a style and falls back
458
+ * to plain chrome for one it does not know, so a package outside core can coin
459
+ * its own and still be drawn.
460
+ */
461
+ type OverlayRole =
462
+ /** Generic in-flight chrome — the marquee/lasso paint. */
463
+ 'chrome'
464
+ /** A cut the gesture would make. */
465
+ | 'cut'
466
+ /** An edge the gesture would author between two points. */
467
+ | 'connector'
468
+ /** The stretch of a path a soft-selection drag reaches. */
469
+ | 'falloff'
470
+ /** What a lock holds a dragged point to — a line, a circle. */
471
+ | 'lock' | (string & {});
472
+ /**
473
+ * What an in-flight gesture proposes to paint *beside* the scene, returned by
474
+ * `OngoingHandle.overlay()` — a marquee rect, a lasso trail, the outline of a
475
+ * shape being dragged out, the line a slice would cut along.
476
+ *
477
+ * Every variant is world geometry and nothing else — no `DrawCommand`, no
478
+ * color, no coordinate space to choose — so a surface rendering the same
479
+ * gesture some other way can still read it. The painter owns every style
480
+ * decision.
481
+ */
482
+ type OngoingOverlay = {
483
+ kind: 'marquee';
484
+ start: {
485
+ x: number;
486
+ y: number;
487
+ };
488
+ current: {
489
+ x: number;
490
+ y: number;
491
+ };
492
+ shiftHeld: boolean;
493
+ } | {
494
+ kind: 'lasso';
495
+ vertices: ReadonlyArray<{
496
+ x: number;
497
+ y: number;
498
+ }>;
499
+ current: {
500
+ x: number;
501
+ y: number;
502
+ };
503
+ shiftHeld: boolean;
504
+ } | {
505
+ /**
506
+ * An open run of world points the gesture is proposing — a cut line, a
507
+ * routed connector. `role` is the whole of what an action says about
508
+ * appearance.
509
+ */
510
+ kind: 'polyline';
511
+ /** At least two points. Anything shorter is dropped in resolution. */
512
+ points: ReadonlyArray<{
513
+ x: number;
514
+ y: number;
515
+ }>;
516
+ /** What the run means. Omitted reads as {@link OverlayRole} `'chrome'`. */
517
+ role?: OverlayRole;
518
+ } | {
519
+ /**
520
+ * A round brush dragged through world points: the area it has swept so
521
+ * far, and its footprint at the last point. The radius is in screen
522
+ * pixels, so the footprint keeps its size at every zoom.
523
+ */
524
+ kind: 'brush';
525
+ /** The brush's path so far, at least one point; the last is where it is now. */
526
+ points: ReadonlyArray<{
527
+ x: number;
528
+ y: number;
529
+ }>;
530
+ radiusPx: number;
531
+ } | {
532
+ /**
533
+ * Live insert-drag preview. Pre-commit there is no scene node to ghost
534
+ * via `previewIds()`/`previewPose()`, so insert paints its preview
535
+ * through the overlay instead.
536
+ *
537
+ * `bounds` is the AABB of the current drag (start/current normalized).
538
+ * `extras` is the per-kind extras the action already collected; the
539
+ * overlay renderer narrows on `shape` and casts the field shape it
540
+ * expects.
541
+ */
542
+ kind: 'insertPreview';
543
+ /** Which preview the dispatcher's overlay draws. The kit's own shape
544
+ * kinds are the ones it knows how to render; a consumer-defined kind
545
+ * is legal and simply gets no live preview. */
546
+ shape: string;
547
+ bounds: {
548
+ x: number;
549
+ y: number;
550
+ width: number;
551
+ height: number;
552
+ };
553
+ extras: unknown;
554
+ /** World-space point to paint a small "anchor" dot at, marking the
555
+ * click point — for radial shapes (polygon/star), where no vertex
556
+ * sits on it, and for any shape in center mode. */
557
+ anchorPoint?: {
558
+ x: number;
559
+ y: number;
560
+ };
561
+ /** World affines the shape will also be drawn under once it lands, by
562
+ * the container it is drawn into: the preview is painted under each. */
563
+ copies?: readonly (readonly [number, number, number, number, number, number])[];
564
+ };
565
+ /** A handle's overlays as a list: empty when it has none. */
566
+ declare function overlaysOf(handle: OngoingHandle): readonly OngoingOverlay[];
567
+
526
568
  /**
527
569
  * Invoker — pluggable invocation strategy for an Action.
528
570
  *
@@ -531,11 +573,8 @@ declare const DEFAULT_DEVICE_PROFILE: DeviceProfile;
531
573
  * driven by the dispatcher (move, resize, pinch-zoom).
532
574
  */
533
575
 
534
- /** A 2D point in either world or screen coordinates. */
535
- interface Point2 {
536
- x: number;
537
- y: number;
538
- }
576
+ /** A 2D point in either world or screen coordinates; geom's `Point`. */
577
+ type Point2 = Point;
539
578
  /**
540
579
  * Which UI affordance was hit at pointerdown. Populated by the dispatcher when
541
580
  * the `affordanceAt` thunk is provided to `useGestureDispatcher`.
@@ -543,6 +582,8 @@ interface Point2 {
543
582
  * `kind` is a discriminator string:
544
583
  * - `'handle:top-left'` / `'handle:top-right'` / `'handle:bottom-left'` /
545
584
  * `'handle:bottom-right'` — corner resize handles.
585
+ * - `'handle:top'` / `'handle:right'` / `'handle:bottom'` / `'handle:left'` —
586
+ * edge resize handles.
546
587
  * - `'rotate-handle'` — the rotation affordance.
547
588
  * - `'anchor:N'` — a path anchor at index N.
548
589
  */
@@ -565,8 +606,8 @@ interface AffordanceHit {
565
606
  };
566
607
  /** Which nodes this affordance belongs to. */
567
608
  targetIds?: string[];
568
- /** Set only when `kind` matches `'handle:*'`: which corner stays fixed
569
- * during a resize. */
609
+ /** Set only when `kind` matches `'handle:*'`: which corner or edge stays
610
+ * fixed during a resize; `'free'` on the axis an edge handle leaves alone. */
570
611
  anchor?: ResizeAnchor;
571
612
  /** Cursor to show while the pointer hovers this affordance (no gesture in
572
613
  * flight). Unset falls through to action-cursor prediction, then to the
@@ -676,6 +717,12 @@ interface InvocationCtx {
676
717
  key: string;
677
718
  repeat: boolean;
678
719
  };
720
+ /** What a carry over the surface brings: its payload, as `startCarry` was
721
+ * handed it. Present for every event of a `carry` binding's gesture. */
722
+ carry?: {
723
+ type: string;
724
+ value: unknown;
725
+ };
679
726
  /**
680
727
  * The view the input landed in, as the surface's view resolver assigned it:
681
728
  * a view id, or `null` for the surface's own camera. Absent where no
@@ -689,6 +736,13 @@ interface InvocationCtx {
689
736
  * params via `BindingOpts.params` on `start` (the `opts` arg).
690
737
  */
691
738
  params?: Record<string, unknown>;
739
+ /**
740
+ * Which of the action's `modifierRoles` are held for this event, by role
741
+ * id. The dispatcher fills it on every event of a gesture whose action
742
+ * declares roles; absent otherwise. Read it through `roleReader`, which
743
+ * falls back to the roles' default keys where it is absent.
744
+ */
745
+ roles?: Readonly<Record<string, boolean>>;
692
746
  }
693
747
  /** Per-invocation options the dispatcher reads from a `GestureBinding`'s
694
748
  * `opts` field and passes to `OngoingInvoker.start`. */
@@ -723,6 +777,11 @@ interface BindingOpts {
723
777
  * binding; this tells the route-conflict check the order is the design.
724
778
  */
725
779
  yields?: boolean;
780
+ /**
781
+ * Keys for some of the action's `modifierRoles` on this binding, by role
782
+ * id, over the action's defaults and any tuning's.
783
+ */
784
+ roles?: RoleRebinds;
726
785
  }
727
786
  /** Resolve `BindingOpts.params` to a concrete record (calling the thunk if
728
787
  * needed). Returns `undefined` for absent params. */
@@ -734,98 +793,7 @@ declare function resolveParams(params: BindingOpts['params']): Record<string, un
734
793
  interface ActionDeps extends Partial<DepSchema> {
735
794
  [k: string]: unknown;
736
795
  }
737
- /**
738
- * What a `polyline` overlay is, in a word — the narrowest thing an action can
739
- * say about how its run should look without naming a paint.
740
- *
741
- * The named roles are the kit's; a painter maps each to a style and falls back
742
- * to plain chrome for one it does not know, so a package outside core can coin
743
- * its own and still be drawn.
744
- */
745
- type OverlayRole =
746
- /** Generic in-flight chrome — the marquee/lasso paint. */
747
- 'chrome'
748
- /** A cut the gesture would make. */
749
- | 'cut'
750
- /** An edge the gesture would author between two points. */
751
- | 'connector' | (string & {});
752
- /**
753
- * What an in-flight gesture proposes to paint *beside* the scene, returned by
754
- * `OngoingHandle.overlay()` — a marquee rect, a lasso trail, the outline of a
755
- * shape being dragged out, the line a slice would cut along.
756
- *
757
- * Every variant is world geometry and nothing else — no `DrawCommand`, no
758
- * color, no coordinate space to choose — so a surface rendering the same
759
- * gesture some other way can still read it. The painter owns every style
760
- * decision.
761
- */
762
- type OngoingOverlay = {
763
- kind: 'marquee';
764
- start: {
765
- x: number;
766
- y: number;
767
- };
768
- current: {
769
- x: number;
770
- y: number;
771
- };
772
- shiftHeld: boolean;
773
- } | {
774
- kind: 'lasso';
775
- vertices: ReadonlyArray<{
776
- x: number;
777
- y: number;
778
- }>;
779
- current: {
780
- x: number;
781
- y: number;
782
- };
783
- shiftHeld: boolean;
784
- } | {
785
- /**
786
- * An open run of world points the gesture is proposing — a cut line, a
787
- * routed connector. `role` is the whole of what an action says about
788
- * appearance.
789
- */
790
- kind: 'polyline';
791
- /** At least two points. Anything shorter is dropped in resolution. */
792
- points: ReadonlyArray<{
793
- x: number;
794
- y: number;
795
- }>;
796
- /** What the run means. Omitted reads as {@link OverlayRole} `'chrome'`. */
797
- role?: OverlayRole;
798
- } | {
799
- /**
800
- * Live insert-drag preview. Pre-commit there is no scene node to ghost
801
- * via `previewIds()`/`previewPose()`, so insert paints its preview
802
- * through the overlay instead.
803
- *
804
- * `bounds` is the AABB of the current drag (start/current normalized).
805
- * `extras` is the per-kind extras the action already collected; the
806
- * overlay renderer narrows on `shape` and casts the field shape it
807
- * expects.
808
- */
809
- kind: 'insertPreview';
810
- /** Which preview the dispatcher's overlay draws. The kit's own shape
811
- * kinds are the ones it knows how to render; a consumer-defined kind
812
- * is legal and simply gets no live preview. */
813
- shape: string;
814
- bounds: {
815
- x: number;
816
- y: number;
817
- width: number;
818
- height: number;
819
- };
820
- extras: unknown;
821
- /** World-space point to paint a small "anchor" dot at, marking the
822
- * click point — for radial shapes (polygon/star), where no vertex
823
- * sits on it, and for any shape in center mode. */
824
- anchorPoint?: {
825
- x: number;
826
- y: number;
827
- };
828
- };
796
+
829
797
  /** Handle returned from an `OngoingInvoker.start`. The dispatcher pumps
830
798
  * `onMove` on subsequent input events of the same gesture and calls
831
799
  * `onEnd` exactly once (with `'commit'` on natural completion or `'cancel'`
@@ -840,6 +808,12 @@ interface OngoingHandle {
840
808
  * handle is in flight.
841
809
  */
842
810
  kind?: string;
811
+ /**
812
+ * The cursor this gesture shows now, read after every move. Wins over the
813
+ * action's `activeCursor`, for a cursor that follows the gesture — the
814
+ * rotate glyph turning about its pivot. `undefined` defers to the action.
815
+ */
816
+ cursor?(): CursorSpec | undefined;
843
817
  onMove?(ctx: InvocationCtx): void;
844
818
  onEnd?(ctx: InvocationCtx, reason: 'commit' | 'cancel'): void;
845
819
  /**
@@ -876,10 +850,19 @@ interface OngoingHandle {
876
850
  previewData?(id: string): unknown | null;
877
851
  /**
878
852
  * Optional chrome surface: a non-ghost visual (marquee rectangle, lasso
879
- * polyline) painted while the gesture is in flight. Returning `null`, or
880
- * omitting the method, means "no overlay this gesture".
853
+ * polyline) painted while the gesture is in flight — one, or a list for a
854
+ * gesture showing several runs at once. Returning `null`, or omitting the
855
+ * method, means "no overlay this gesture". Read it through
856
+ * {@link overlaysOf}, which answers a list either way.
857
+ */
858
+ overlay?(): OngoingOverlay | readonly OngoingOverlay[] | null;
859
+ /**
860
+ * A wheel turned while this gesture is in flight — scrubbing a value the
861
+ * drag is using, say. Return `true` to claim the wheel, so no wheel binding
862
+ * (the viewport's zoom or pan) sees it; anything else lets it through.
863
+ * Omit it and the wheel goes to the bindings as usual.
881
864
  */
882
- overlay?(): OngoingOverlay | null;
865
+ onWheel?(ctx: InvocationCtx): boolean | void;
883
866
  }
884
867
  /** Fire-once invocation. Runs to completion synchronously (or fires off an
885
868
  * async side-effect; the registry doesn't wait). */
@@ -903,8 +886,6 @@ type Invoker = ImmediateInvoker | OngoingInvoker;
903
886
  * GestureBinding — connects a GestureSpec to an Action id (with per-binding
904
887
  * options). Tools own arrays of these on their `bindings` field; ambient
905
888
  * gesture-bindings are registered globally.
906
- *
907
- * See `docs/superpowers/specs/2026-05-16-registry-unification-design.md`.
908
889
  */
909
890
 
910
891
  /** An interaction: a gesture spec composed with the id of the action it
@@ -916,7 +897,6 @@ interface GestureBinding {
916
897
  opts?: BindingOpts;
917
898
  }
918
899
  /**
919
- * @experimental
920
900
  * A single entry in `Action.defaultBinding[]`. Either a bare `GestureSpec`
921
901
  * (no per-binding opts) or an object form that pairs a spec with
922
902
  * `BindingOpts` for parametric actions (e.g. `{ params: { axis: 'x' } }`).
@@ -929,7 +909,6 @@ type BoundGesture = GestureSpec | {
929
909
  opts: BindingOpts;
930
910
  };
931
911
  /**
932
- * @experimental
933
912
  * The whole of an action `actionBindings` reads. Routing needs this much and
934
913
  * none of `Action`'s palette fields, so it is the narrowest type the
935
914
  * dispatcher's binding walk can be written against.
@@ -946,14 +925,12 @@ interface BindingSource {
946
925
  defaultBinding?: GestureSpec | BoundGesture[];
947
926
  }
948
927
  /**
949
- * @experimental
950
928
  * Flatten an action's `defaultBinding` into `GestureBinding`s. A bare
951
929
  * `GestureSpec` has `kind` at top level; the object form has `spec`.
952
930
  */
953
931
  declare function actionBindings(action: BindingSource): GestureBinding[];
954
932
 
955
933
  /**
956
- * @experimental
957
934
  * Closed enum of reasons an action might report itself as disabled. The
958
935
  * consumer (palette, menu, etc.) maps these symbolic values to display
959
936
  * strings via its own label map.
@@ -968,20 +945,23 @@ declare const ActionDisabledReason: {
968
945
  /** Why an action is unavailable right now. */
969
946
  type ActionDisabledReason = (typeof ActionDisabledReason)[keyof typeof ActionDisabledReason];
970
947
  /**
971
- * @experimental
972
948
  * What a palette, menu or toolbar renders for an action. No part of this is
973
949
  * read during dispatch.
974
950
  */
975
951
  interface ActionPresentation {
976
952
  label: string;
977
- /** Inline-SVG icon for palette / toolbar surfaces. May be a static
978
- * `ReactNode` or a function (rare; useful for state-aware icons like a
979
- * "lock" toggle). */
980
- icon?: ReactNode | (() => ReactNode);
953
+ /** The action's icon, by qualified name: `icon('group')` in the package that draws it. */
954
+ icon?: IconRef;
981
955
  /** Grouping key for palette/menu surfaces. Free-form string; the kit
982
956
  * ships defaults for `'align'` (six edges/centers), `'distribute'`
983
957
  * (two axes), and recommends `'pathfinder'` for boolean ops. */
984
958
  group?: string;
959
+ /** Words the action is also found by and gathered under. Where `group` is
960
+ * the one place an action sits, an action carries any number of tags: a
961
+ * palette search matches them as it matches the label, and
962
+ * `actionsTagged` / `taggedActionItems` gather every action or entry
963
+ * carrying one, for a bar or a menu built from a tag. */
964
+ tags?: readonly string[];
985
965
  /** Display override for the keyboard shortcut. When omitted, palette
986
966
  * surfaces derive a label from `defaultBinding` via their own
987
967
  * formatter. */
@@ -994,7 +974,6 @@ interface ActionPresentation {
994
974
  variants?: readonly ActionVariant[];
995
975
  }
996
976
  /**
997
- * @experimental
998
977
  * One entry a parametric action contributes to a bar, menu or palette.
999
978
  */
1000
979
  interface ActionVariant {
@@ -1002,13 +981,14 @@ interface ActionVariant {
1002
981
  key: string;
1003
982
  label: string;
1004
983
  /** Falls back to the action's own `icon`. */
1005
- icon?: ReactNode | (() => ReactNode);
984
+ icon?: IconRef;
985
+ /** Tags this variant carries besides its action's, which it carries too. */
986
+ tags?: readonly string[];
1006
987
  /** Passed to `trigger`, and matched against each binding's
1007
988
  * `opts.params` to find the variant's shortcuts. */
1008
989
  params: Readonly<Record<string, unknown>>;
1009
990
  }
1010
991
  /**
1011
- * @experimental
1012
992
  * What routing consults: the bindings that reach the action, the deps its
1013
993
  * invoker reads, the gates it passes, and the cursors it claims.
1014
994
  */
@@ -1030,14 +1010,14 @@ interface ActionDispatch extends BindingSource {
1030
1010
  * shortcuts and global held-key triggers. Default: ambient. */
1031
1011
  scope?: 'hotkey';
1032
1012
  /**
1033
- * @experimental
1034
1013
  * Optional predicate saying whether the action can run right now. Return
1035
1014
  * `true` when it can, or an `ActionDisabledReason` when it cannot. The
1036
1015
  * command palette greys out a disabled row, skips it in keyboard nav,
1037
1016
  * ignores clicks, and shows the reason next to the label. The dispatcher
1038
1017
  * skips a disabled action too, on a key as on a pointer, and falls through
1039
- * to the next binding that matches. `ActionsRegistry.trigger` does not ask,
1040
- * so the action's own `run` should still self-guard.
1018
+ * to the next binding that matches. `ActionsRegistry.trigger` asks too, but
1019
+ * with no point, so a `run` whose answer depends on `at` should still
1020
+ * self-guard.
1041
1021
  *
1042
1022
  * **Contract:** must be pure (no side effects), fast (< 4ms in dev), and
1043
1023
  * must not throw. A throw is caught and treated as disabled with reason
@@ -1052,8 +1032,10 @@ interface ActionDispatch extends BindingSource {
1052
1032
  * click, a press, a long-press. An action that only applies somewhere
1053
1033
  * (on a path segment, say) refuses other points here, so the dispatcher
1054
1034
  * falls through to the next binding and hover prediction shows the
1055
- * action's `cursor` only where it would act. Palettes and keystrokes
1056
- * pass no point; treat absent as "anywhere".
1035
+ * action's `cursor` only where it would act. `trigger` passes the
1036
+ * `worldX`/`worldY` its params carry, so a menu row is run under the
1037
+ * question it was shown enabled for. Palettes and keystrokes pass no
1038
+ * point; treat absent as "anywhere".
1057
1039
  *
1058
1040
  * `carried` is what a drop or a paste being routed brings: its items. For
1059
1041
  * a drag still in flight they hold a MIME and nothing else, since a
@@ -1068,7 +1050,6 @@ interface ActionDispatch extends BindingSource {
1068
1050
  items: readonly IngestItem[];
1069
1051
  }) => true | ActionDisabledReason;
1070
1052
  /**
1071
- * @experimental
1072
1053
  * Whether the action reads as held down right now: bold on the selected
1073
1054
  * text, snapping switched on. A toolbar button draws it as pressed.
1074
1055
  * Omitted = the action has no pressed state, which is not the same as
@@ -1078,6 +1059,15 @@ interface ActionDispatch extends BindingSource {
1078
1059
  * throw. `deps` is the bag `enabled` is given.
1079
1060
  */
1080
1061
  active?: (deps?: ActionDeps) => boolean;
1062
+ /**
1063
+ * Show what running the action now would do, and change nothing: the
1064
+ * result an operation would make, drawn over the canvas. A toolbar asks
1065
+ * while its button is hovered or focused, through
1066
+ * `ActionsRegistry.preview`, and calls what this returns when that ends.
1067
+ * Asked only while `enabled` says yes, with the deps and params `run`
1068
+ * would get. Omitted = the action has nothing to show.
1069
+ */
1070
+ preview?: (deps: ActionDeps, params?: Record<string, unknown>) => (() => void) | void;
1081
1071
  /**
1082
1072
  * Declarative eligibility rule, evaluated against the current
1083
1073
  * `RuleCtx` by the dispatcher before invoking `start()`. Omitted =
@@ -1100,12 +1090,14 @@ interface ActionDispatch extends BindingSource {
1100
1090
  * resolved earlier in the pump via `AffordanceRegion.cursor` and never
1101
1091
  * reach this field.
1102
1092
  *
1103
- * Static value only. Prediction runs `enabled()` but cannot run the
1104
- * invoker, so an action that matches yet bails at `start()` (empty
1105
- * handle) may still show its cursor — keep `enabled` accurate for
1106
- * actions that declare one.
1093
+ * A function is asked each time with the params the winning binding would
1094
+ * start the action with, tunings included, so a cursor can follow them — a
1095
+ * brush ring as wide as the brush. Read it through {@link actionCursor}.
1096
+ * Prediction runs `enabled()` but cannot run the invoker, so an action that
1097
+ * matches yet bails at `start()` (empty handle) may still show its cursor —
1098
+ * keep `enabled` accurate for actions that declare one.
1107
1099
  */
1108
- cursor?: CursorSpec;
1100
+ cursor?: CursorSpec | ((params: Record<string, unknown> | undefined) => CursorSpec | undefined);
1109
1101
  /**
1110
1102
  * CSS cursor shown while THIS action's ongoing handle is in flight —
1111
1103
  * grabbing while panning, `move` while dragging a selection, `crosshair`
@@ -1118,15 +1110,22 @@ interface ActionDispatch extends BindingSource {
1118
1110
  * gesture.
1119
1111
  */
1120
1112
  activeCursor?: CursorSpec;
1113
+ /**
1114
+ * The modifiers an ongoing action reads while it runs, by role: Shift
1115
+ * holding a handle's angle, Alt breaking its mirror. The dispatcher resolves
1116
+ * each into `InvocationCtx.roles` on the press, every move, and the release,
1117
+ * so a binding's `opts.roles` or a tuning's `roles` can move one to another
1118
+ * key. Read them with {@link roleReader}. A binding's own `mods` are matched
1119
+ * once, at the press; these are read throughout.
1120
+ */
1121
+ modifierRoles?: ModifierRoles;
1121
1122
  }
1122
1123
  /**
1123
- * @experimental
1124
1124
  * Single registered action.
1125
1125
  */
1126
1126
  interface Action extends ActionDispatch, ActionPresentation {
1127
1127
  }
1128
1128
  /**
1129
- * @experimental
1130
1129
  * The whole of an actions registry the dispatcher reads. It walks the list
1131
1130
  * once per event to build its actionId lookup and never mutates it, so the
1132
1131
  * routing side depends on this rather than on `ActionsRegistry`, whose
@@ -1135,37 +1134,314 @@ interface Action extends ActionDispatch, ActionPresentation {
1135
1134
  interface ActionSource {
1136
1135
  list(): readonly Action[];
1137
1136
  }
1137
+ /** `action`'s hover cursor for an invocation given `params`: its `cursor`,
1138
+ * asked when it is a function. */
1139
+ declare function actionCursor(action: Pick<Action, 'cursor'> | undefined, params?: Record<string, unknown>): CursorSpec | undefined;
1140
+
1141
+ /** Which canvas hit a menu answers. Every field given must match. */
1142
+ interface MenuWhen {
1143
+ bodyTarget?: BodyTarget | readonly BodyTarget[];
1144
+ bodyKind?: string | readonly string[];
1145
+ }
1146
+ /** A menu as data: a prefs schema drawn as a menu (`resolveSchemaMenu`).
1147
+ * A def without `when` is opened only by id, from chrome. */
1148
+ interface MenuDef {
1149
+ id: string;
1150
+ when?: MenuWhen;
1151
+ menu: PrefGroup;
1152
+ }
1153
+ /** What a right-click landed on. */
1154
+ interface MenuHit {
1155
+ bodyTarget?: BodyTarget;
1156
+ bodyKind?: string;
1157
+ }
1158
+ /** A def with who contributed it: a tool id, or `null` for ambient. */
1159
+ interface OwnedMenuDef {
1160
+ def: MenuDef;
1161
+ owner: string | null;
1162
+ }
1163
+
1164
+ /** What resolving reads: the registered actions, each one's deps, how to run
1165
+ * one, and the values behind the schema's value leaves. */
1166
+ interface MenuSources {
1167
+ actions(): readonly Action[];
1168
+ depsFor(action: Action): ActionDeps | undefined;
1169
+ trigger(id: string, params?: Record<string, unknown>): boolean;
1170
+ /** The value at a leaf's dotted path. Booleans, enums, and numbers are left
1171
+ * out of a menu without both this and `onChange`, colors and strings without
1172
+ * this, and `showIf`/`enableIf` are checked only with it. */
1173
+ values?(path: string): unknown;
1174
+ onChange?(path: string, value: unknown): void;
1175
+ /** The schema an `alias` leaf's `of` is read in. Default: the menu's own. */
1176
+ over?: PrefGroup;
1177
+ }
1178
+ /**
1179
+ * Draw a prefs schema as menu entries. Action leaves become items from the
1180
+ * registry (one per variant for a parametric action), an `actions` leaf one
1181
+ * item per action in its group, a boolean a checked item, an enum radio
1182
+ * rows, and a number a row edited in place (all through `src.values`/`src.onChange`);
1183
+ * a color shows as a swatch and a string as a disabled row, both read-only. A group drawn `as` a
1184
+ * `menu`, `page`, `tab`, or `panel` is a submenu, and any other group's rows
1185
+ * sit inline between separators. Paint, field, compound, and app-defined leaves are left out.
1186
+ * `at` is the world point the menu was opened at and reaches `enabled` and
1187
+ * every action's params; `params` go to every action, under its own.
1188
+ */
1189
+ declare function resolveSchemaMenu(schema: PrefGroup, src: MenuSources, at?: Point, params?: Record<string, unknown>): MenuEntry[];
1190
+ /** Turn a declared menu into model entries; see {@link resolveSchemaMenu}. */
1191
+ declare function resolveMenu(def: MenuDef, src: MenuSources, at?: Point, params?: Record<string, unknown>): MenuEntry[];
1192
+
1193
+ /** Ask to open a menu: by id (chrome) or by what was hit (canvas). */
1194
+ interface MenuOpenRequest {
1195
+ menu?: string;
1196
+ hit?: MenuHit;
1197
+ /** Viewport point the menu is placed at, unless `under` is set. */
1198
+ client: Point;
1199
+ /** Viewport rect of the button the menu hangs from: placed below it, or above when below does not fit. */
1200
+ under?: Rect;
1201
+ /** World point, passed to `enabled` and to every item. */
1202
+ world?: Point;
1203
+ params?: Record<string, unknown>;
1204
+ source?: 'pointer' | 'keyboard';
1205
+ }
1206
+ /** The menu on screen. `seq` changes on every open, so a renderer remounts. */
1207
+ interface OpenMenu {
1208
+ seq: number;
1209
+ entries: readonly MenuEntry[];
1210
+ client: Point;
1211
+ under?: Rect;
1212
+ world?: Point;
1213
+ source: 'pointer' | 'keyboard';
1214
+ }
1215
+ /** Holds the declared menus and the one open menu. */
1216
+ interface MenuHost {
1217
+ /** Declare a menu; `owner` is a tool id, or `null` for always. Returns a release. */
1218
+ define(def: MenuDef, owner?: string | null): () => void;
1219
+ /** Pick, resolve and show. False when nothing matched or nothing resolved. */
1220
+ open(req: MenuOpenRequest): boolean;
1221
+ /** Whether `open(req)` would show anything. Changes no state and notifies no one. */
1222
+ has(req: MenuOpenRequest): boolean;
1223
+ close(): void;
1224
+ current(): OpenMenu | null;
1225
+ subscribe(fn: () => void): () => void;
1226
+ }
1227
+ /** Creates the host that decides which context menu is open, from the menus registered to it. */
1228
+ declare function createMenuHost(src: MenuSources & {
1229
+ activeTool(): string | null;
1230
+ }): MenuHost;
1231
+
1232
+ /**
1233
+ * The tree both input registries hang on. A provider is a root; every canvas
1234
+ * mounts a scope under the registry in scope; a yoke sits between the two. A
1235
+ * registration lives in the node it was made in, and a lookup starts at a leaf
1236
+ * and walks up, so one canvas never answers for another.
1237
+ */
1238
+
1239
+ /** What every node of one tree shares: a version and the listeners to it. */
1240
+ interface ScopeTree {
1241
+ version: number;
1242
+ readonly listeners: Emitter;
1243
+ }
1244
+ declare class ScopeNode<N extends ScopeNode<N>> {
1245
+ readonly parent: N | null;
1246
+ readonly descends: boolean;
1247
+ readonly tree: ScopeTree;
1248
+ private readonly children;
1249
+ private activeChild;
1250
+ /** `descends`: whether reads made here answer from the active child down —
1251
+ * true for a root or a yoke, which chrome reads through; false for a scope,
1252
+ * which answers for itself even with a scope nested inside it. */
1253
+ constructor(parent: N | null, descends: boolean);
1254
+ /** Bump the tree's version and tell every listener in it. */
1255
+ changed(): void;
1256
+ /** Join the parent's children, newest last; returns the leave. */
1257
+ mount(): () => void;
1258
+ /** Make this node the one its ancestors resolve through. */
1259
+ activate(): void;
1260
+ /** The node a lookup made here starts from: down the active children, or the
1261
+ * newest where nothing has been activated yet. A yoke with no members yet
1262
+ * is passed over — there is no canvas behind it to answer. */
1263
+ leaf(): N;
1264
+ private newestMember;
1265
+ /** Where a read made through this node starts. */
1266
+ start(): N;
1267
+ /** Whether this node is on the path a read from the root takes. */
1268
+ isActive(): boolean;
1269
+ /** This node, then each ancestor up to the root. */
1270
+ chain(): Generator<N>;
1271
+ }
1272
+
1273
+ /** Which tool is active, plus the stack of tools temporarily held active by a
1274
+ * hotkey (space-for-hand and the like). The dispatcher reads this to decide
1275
+ * whose bindings are in scope. */
1276
+ interface ActiveToolContextValue {
1277
+ /** The focused tool's id, or `null` when no tool holds the active slot —
1278
+ * a canvas can run on ambient bindings alone. */
1279
+ active: string | null;
1280
+ hotkeyStack: string[];
1281
+ setActive(id: string | null): void;
1282
+ pushHotkey(id: string): void;
1283
+ /**
1284
+ * Disengage a hotkey-held tool. With `id`, removes that tool's own entry
1285
+ * wherever it now sits — holds do not have to come up in the order they went
1286
+ * down, and popping the top would disengage a tool whose key is still held.
1287
+ * With no id, pops the top.
1288
+ */
1289
+ popHotkey(id?: string): void;
1290
+ }
1291
+ /**
1292
+ * One node of the tool tree. A node that `owns` a tool holds its state; one
1293
+ * that does not — a scope inside a yoke — reads and writes its yoke's.
1294
+ */
1295
+ declare class ToolNode extends ScopeNode<ToolNode> {
1296
+ private state;
1297
+ private value;
1298
+ constructor(parent: ToolNode | null, descends: boolean, owns: boolean, initialActive: string | null);
1299
+ /** The node whose tool a read here resolves to. */
1300
+ owner(): ToolNode;
1301
+ private update;
1302
+ /** A stable value per owner and state, for `useSyncExternalStore`. */
1303
+ snapshot(): ActiveToolContextValue;
1304
+ subscribe: (listener: () => void) => (() => void);
1305
+ }
1306
+ /** Props for `<ActiveToolContextProvider>`. */
1307
+ interface ActiveToolContextProviderProps {
1308
+ children: ReactNode;
1309
+ /** Seeds the active slot, and wins over the first `useTools` call's
1310
+ * `active`. Omitted, the slot starts empty and that call seeds it. */
1311
+ initialActive?: string | null;
1312
+ }
1313
+ /** Provides root active-tool state. Every canvas below has a tool of its own;
1314
+ * reads and writes here reach the one last used. */
1315
+ declare function ActiveToolContextProvider({ children, initialActive, }: ActiveToolContextProviderProps): react.JSX.Element;
1316
+ /** The active-tool state in scope. Throws outside a provider; use
1317
+ * `useOptionalActiveToolContext` where one is not guaranteed. */
1318
+ declare function useActiveToolContext(): ActiveToolContextValue;
1319
+ /**
1320
+ * Like `useActiveToolContext`, but returns `null` when no
1321
+ * `<ActiveToolContextProvider>` is in scope instead of throwing.
1322
+ */
1323
+ declare function useOptionalActiveToolContext(): ActiveToolContextValue | null;
1324
+ /**
1325
+ * Mounts an `<ActiveToolContextProvider>` only when no parent provider is in
1326
+ * scope; otherwise renders children unwrapped.
1327
+ */
1328
+ declare function ActiveToolContextProviderIfRoot({ children, }: {
1329
+ children: ReactNode;
1330
+ }): react.JSX.Element;
1331
+
1332
+ /**
1333
+ * Tuning: what a host changes about an action it did not write — the params
1334
+ * every invocation starts from, and bindings added beside the action's own —
1335
+ * without restating the descriptor. `ActionsRegistry.tune` holds tunings and
1336
+ * applies them to whatever descriptor is live for the id.
1337
+ */
1338
+
1339
+ /** An action's params, or a thunk read each time the action asks for them. */
1340
+ type ActionParams<P = Record<string, unknown>> = Partial<P> | (() => Partial<P>);
1341
+ /** A binding added for an action: a gesture alone, or a gesture with the
1342
+ * options it passes — the {@link BoundGesture} shape, its params typed. */
1343
+ type TunedBinding<P = Record<string, unknown>> = GestureSpec | {
1344
+ spec: GestureSpec;
1345
+ opts: Omit<BindingOpts, 'params'> & {
1346
+ params?: ActionParams<P>;
1347
+ };
1348
+ };
1349
+ /** What a host changes about one action. */
1350
+ interface ActionTuning<P = Record<string, unknown>> {
1351
+ /** Params every invocation starts from. What a binding or a `trigger` call
1352
+ * passes is laid over them, so these fill in what it leaves out. A thunk is
1353
+ * read on every call, and an ongoing action resolving its `opts.params`
1354
+ * mid-gesture sees the value as it is then. */
1355
+ params?: ActionParams<P>;
1356
+ /** Bindings added after the action's own `defaultBinding`. */
1357
+ bindings?: readonly TunedBinding<P>[];
1358
+ /** Keys for some of the action's `modifierRoles`, by role id. A binding's
1359
+ * own `opts.roles` is laid over these. */
1360
+ roles?: RoleRebinds;
1361
+ }
1362
+ /** `action` with each tuning applied in turn, a later one's params over an
1363
+ * earlier one's. Applying a tuning to a copy it already tuned changes nothing. */
1364
+ declare function tuneAction(action: Action, tunings: readonly ActionTuning[]): Action;
1138
1365
 
1139
1366
  /**
1140
- * @experimental
1141
1367
  * The entries an action contributes to a bar, menu or palette — one per
1142
1368
  * variant, or the action itself when it declares none.
1143
1369
  */
1144
1370
 
1145
- /** @experimental One renderable entry: an action, optionally with params. */
1371
+ /** One renderable entry: an action, optionally with params. */
1146
1372
  interface ActionItem {
1147
1373
  /** `action.id`, or `action.id:variant.key` — unique across a registry. */
1148
1374
  key: string;
1149
1375
  action: Action;
1150
1376
  label: string;
1151
- icon?: ReactNode | (() => ReactNode);
1377
+ icon?: IconRef;
1378
+ /** The action's tags, then the variant's own. */
1379
+ tags: readonly string[];
1152
1380
  /** What to pass to `trigger(action.id, params)`; absent for a plain action. */
1153
1381
  params?: Readonly<Record<string, unknown>>;
1154
1382
  }
1155
- /** @experimental Expand `action` into the entries a surface renders. An
1383
+ /** Expand `action` into the entries a surface renders. An
1156
1384
  * action without an immediate invoker has none: `trigger` cannot start a
1157
1385
  * drag, so a button for one would do nothing. */
1158
1386
  declare function actionItems(action: Action): ActionItem[];
1387
+ /** How a palette titles `item`: a variant reads as its action's
1388
+ * label and its own ("New: A4"), unless its label already holds the action's
1389
+ * as whole words ("Zoom In", "Reset Zoom"). */
1390
+ declare function actionItemTitle(item: ActionItem): string;
1391
+
1392
+ /**
1393
+ * Project an action's keyboard bindings into the shape a shortcut chip
1394
+ * renders from (`formatShortcut` / `formatShortcutParts` in `@weasel-js/ui`).
1395
+ */
1396
+
1397
+ /** One keyboard shortcut, flattened for display: the chip a menu row draws
1398
+ * (`MenuShortcut` in `@weasel-js/menu`, `ShortcutInput` in `@weasel-js/gestures`). */
1399
+ type ActionShortcut = MenuShortcut;
1400
+ /**
1401
+ * The chip form of a single gesture spec, or `undefined` when the spec has
1402
+ * none.
1403
+ *
1404
+ * - A spec's `key` may list spellings of one keycap (`['[', '{']` — the
1405
+ * shifted bracket reports as `'{'`). The first is the shortcut's name.
1406
+ * - A modifier declared `'optional'` matches held or unheld, so it isn't
1407
+ * part of what the user has to press.
1408
+ *
1409
+ * Non-keyboard specs (drag, wheel, click) have no chip form. Neither does a
1410
+ * *required* `ctrl` or `meta`: the display shape carries only `mod`.
1411
+ */
1412
+ declare function keySpecShortcut(spec: GestureSpec): ActionShortcut | undefined;
1413
+ /**
1414
+ * Every keyboard shortcut an action answers to, in declaration order.
1415
+ * Specs `keySpecShortcut` has no chip for are skipped, and bindings it leaves
1416
+ * identical are emitted once; an action bound only to those returns empty.
1417
+ *
1418
+ * With `params` — an `ActionItem`'s — only the bindings that pass those same
1419
+ * values count, so each variant of `flip` gets its own key.
1420
+ */
1421
+ declare function actionShortcuts(action: Action, params?: Readonly<Record<string, unknown>>): readonly ActionShortcut[];
1422
+
1423
+ /**
1424
+ * Finding actions by tag: gathering the ones that carry it, and a person's
1425
+ * search matching it as it matches a label.
1426
+ */
1427
+
1428
+ /** The actions carrying `tag`, themselves or on any variant, in
1429
+ * the order given. Drags included, which have no entries to show. */
1430
+ declare function actionsTagged(actions: readonly Action[], tag: string): Action[];
1431
+ /** The entries carrying `tag`: what a bar or a menu built from
1432
+ * a tag shows. A variant that does not carry it is left out. */
1433
+ declare function taggedActionItems(actions: readonly Action[], tag: string): ActionItem[];
1434
+ /** Whether `item` answers a search for `query`, by its palette title or
1435
+ * by a tag, and which. */
1436
+ declare function matchActionItem(item: ActionItem, query: string): QueryMatch | null;
1159
1437
 
1160
1438
  /**
1161
- * @experimental
1162
1439
  * Palette-side evaluation of `Action.enabled`. The dispatcher calls the
1163
1440
  * predicate raw as a gate; this is the surface that also enforces the
1164
1441
  * contract the predicate's JSDoc states — no throwing, under 4ms in dev.
1165
1442
  */
1166
1443
 
1167
1444
  /**
1168
- * @experimental
1169
1445
  * Result of evaluating an Action's `enabled` predicate.
1170
1446
  */
1171
1447
  interface ActionEnabledResult {
@@ -1173,16 +1449,17 @@ interface ActionEnabledResult {
1173
1449
  reason?: ActionDisabledReason;
1174
1450
  }
1175
1451
  /**
1176
- * @experimental
1177
1452
  * Safely evaluate an action's `enabled` predicate. Returns `{enabled: true}`
1178
1453
  * when no predicate is supplied. Catches throws and treats them as disabled
1179
1454
  * with reason `'(predicate threw)'`. In dev mode, warns once per action id
1180
1455
  * when a single call exceeds 4ms (single frame at 240fps — generous; real
1181
1456
  * predicates should be sub-millisecond).
1182
1457
  */
1183
- declare function evaluateEnabled(action: Action, deps?: ActionDeps): ActionEnabledResult;
1458
+ declare function evaluateEnabled(action: Action, deps?: ActionDeps, at?: {
1459
+ x: number;
1460
+ y: number;
1461
+ }): ActionEnabledResult;
1184
1462
  /**
1185
- * @experimental
1186
1463
  * Safely evaluate an action's `active` predicate. `undefined` for an action
1187
1464
  * with no pressed state; a predicate that throws reads as not active.
1188
1465
  */
@@ -1253,9 +1530,8 @@ type HotkeyTrigger = 'space' | 'alt' | 'ctrl' | 'meta' | 'shift' | (string & {})
1253
1530
  interface ToolPresentation {
1254
1531
  /** Human-readable label, distinct from the `id`. Falls back to `id`. */
1255
1532
  label?: string;
1256
- /** Inline-SVG icon component output: a static `ReactNode`, or a function
1257
- * returning one. */
1258
- icon?: react.ReactNode | (() => react.ReactNode);
1533
+ /** The tool's icon, by qualified name: `icon('rect')` in the package that draws it. */
1534
+ icon?: _weasel_js_icons.IconRef;
1259
1535
  /** Palette grouping key. Tools sharing a group render contiguously
1260
1536
  * with separators between groups. Free-form string; the kit
1261
1537
  * recommends 'select' | 'shape' | 'draw' | 'type' | 'view'. */
@@ -1305,6 +1581,8 @@ interface ContributionRouting {
1305
1581
  eligibility: Eligibility;
1306
1582
  bindings?: GestureBinding[];
1307
1583
  actions?: Action[];
1584
+ /** Menus this entry declares: always, for an ambient entry; while active, for a tool. */
1585
+ menus?: MenuDef[];
1308
1586
  /** Dep sources this entry provides while it is installed. A host installs
1309
1587
  * them for as long as the entry is registered, whatever its eligibility. */
1310
1588
  deps?: ContributionDeps;
@@ -1617,6 +1895,8 @@ interface ResolveOnlyResult {
1617
1895
  scope: BindingScope;
1618
1896
  /** Tool id owning the winning binding; `null` for ambient action bindings. */
1619
1897
  ownerId: string | null;
1898
+ /** The params the winning binding would start the action with, resolved now. */
1899
+ params?: Record<string, unknown>;
1620
1900
  }
1621
1901
  /**
1622
1902
  * One candidate from `Dispatcher.resolveAll` — a binding that matched the
@@ -1827,6 +2107,7 @@ declare function recordModeSwitch(mode: string, from: string | null, to: string
1827
2107
  * with no `pointerId` (a synthesized probe, a programmatic drag, most tests)
1828
2108
  * keys to `pointer-mouse`.
1829
2109
  * - `multitouch`: `multitouch-<fingers>`.
2110
+ * - `carry`: `carry-<pointerId>`, keyed as a pointer is.
1830
2111
  * - any other kind that starts an ongoing invoker: `ongoing-<kind>`.
1831
2112
  */
1832
2113
 
@@ -1874,18 +2155,15 @@ declare function createDispatcher(opts?: {
1874
2155
  }): Dispatcher;
1875
2156
 
1876
2157
  /**
1877
- * @experimental
1878
2158
  * Partial override or full descriptor passed via `<SceneCanvas actions={...}>`.
1879
2159
  * `null` disables a default at this id.
1880
2160
  */
1881
2161
  type ActionEntry = null | Partial<Action> | Action;
1882
2162
  /**
1883
- * @experimental
1884
2163
  * Shape of the `actions` prop on `<SceneCanvas>`. `null` disables all defaults.
1885
2164
  */
1886
2165
  type ActionsProp = null | Record<string, ActionEntry>;
1887
2166
  /**
1888
- * @experimental
1889
2167
  * Imperative API exposed by `useActionsRegistry()`.
1890
2168
  */
1891
2169
  interface ActionsRegistry {
@@ -1902,14 +2180,29 @@ interface ActionsRegistry {
1902
2180
  * `trigger` nor `begin` will fire it. Returns a release. This is the
1903
2181
  * "not for me" door — `unregister` is the "should not exist" one. */
1904
2182
  mute(id: string): () => void;
2183
+ /** Tune `id` here and in scopes below: its params and added bindings
2184
+ * apply to whichever descriptor is live for it, registered before the
2185
+ * tuning or after. Returns a release. See {@link ActionTuning}. */
2186
+ tune(id: string, tuning: ActionTuning): () => void;
2187
+ /** The params an invocation of `id` from this scope starts with when it
2188
+ * passes `given`: every tuning's params, `given` laid over them. What a
2189
+ * tool's chrome reads to show what the action it binds will do. */
2190
+ paramsOf(id: string, given?: Record<string, unknown>): Record<string, unknown>;
1905
2191
  list(): readonly Action[];
1906
2192
  /** Fire an immediate-invoker action by id. The optional `params` arg is
1907
2193
  * forwarded to `ImmediateInvoker.run` as its second argument — use it for
1908
2194
  * parametric actions (e.g. `trigger('tool.activate', { toolId: 'rect' })`).
1909
2195
  * Returns whether it ran one: `false` for an unknown id, for an action
1910
2196
  * whose `enabled` refuses, and for an ongoing-invoker action, which
1911
- * `trigger` cannot reach (see `begin`). `enabled` is asked with no point. */
2197
+ * `trigger` cannot reach (see `begin`). `enabled` is asked at
2198
+ * `{ x: params.worldX, y: params.worldY }` when both are numbers, and with
2199
+ * no point otherwise. */
1912
2200
  trigger(id: string, params?: Record<string, unknown>): boolean;
2201
+ /** Show what firing `id` with `params` would do, by its `Action.preview`,
2202
+ * and return what takes it down; calling that twice is harmless. Shows
2203
+ * nothing for an unknown id, one with no preview, and one whose `enabled`
2204
+ * refuses, asked as `trigger` asks it. */
2205
+ preview(id: string, params?: Record<string, unknown>): () => void;
1913
2206
  /**
1914
2207
  * Subscribe to registry mutations. The callback fires after any
1915
2208
  * `register`/`unregister` that changes the version. Returns an
@@ -1977,7 +2270,11 @@ declare function offhandKeyFor(trigger: HotkeyTrigger): string;
1977
2270
  /** Build the per-tool `BoundGesture` list for the consolidated action's
1978
2271
  * `defaultBinding`. Each entry pairs a `key-held` spec with
1979
2272
  * `opts.params.toolId` so the invoker's `start` can pick out which tool
1980
- * to engage. */
2273
+ * to engage.
2274
+ *
2275
+ * An offhand tool engages only between gestures. Swapping the tool out
2276
+ * mid-drag would cancel the drag, and the key is free for the gesture's own
2277
+ * tool to use — Space repositions a shape being drawn. */
1981
2278
  declare function buildToolOffhandBindings(specs: readonly ToolOffhandBindingSpec[]): BoundGesture[];
1982
2279
  /** The `key-held` spec for holding `key` (a `KeyboardEvent.key`, or several).
1983
2280
  * A modifier key gets every modifier optional, since its own keydown reports
@@ -2017,7 +2314,7 @@ declare const isSelectedBody: BodyPredicate;
2017
2314
  declare const isUnselectedBody: BodyPredicate;
2018
2315
  /** Empty-canvas hit — no node beneath cursor. */
2019
2316
  declare const isEmpty: BodyPredicate;
2020
- /** Any corner resize handle — top-left/top-right/bottom-left/bottom-right. */
2317
+ /** Any resize handle: a corner (`handle:top-left`, …) or an edge (`handle:top`, …). */
2021
2318
  declare const isResizeHandle: TargetPredicate & {
2022
2319
  readsAffordance: true;
2023
2320
  };
@@ -2033,10 +2330,28 @@ declare const isAnchor: TargetPredicate & {
2033
2330
  declare const isControlHandle: TargetPredicate & {
2034
2331
  readsAffordance: true;
2035
2332
  };
2333
+ /** A corner-shape widget, set inside a corner anchor of the edited path. */
2334
+ declare const isCornerWidget: TargetPredicate & {
2335
+ readsAffordance: true;
2336
+ };
2036
2337
  /** Any of the three anchor-editing affordances (anchor + both controls). */
2037
2338
  declare const isAnchorOrControl: TargetPredicate & {
2038
2339
  readsAffordance: true;
2039
2340
  };
2341
+ /** The outline of the path being edited, between its anchors. */
2342
+ declare const isSegment: TargetPredicate & {
2343
+ readsAffordance: true;
2344
+ };
2345
+ /** The grip midway along a curved segment's balance line, `balance:N`, where
2346
+ * N is the flat index of the anchor the segment starts at. */
2347
+ declare const isBalanceGrip: TargetPredicate & {
2348
+ readsAffordance: true;
2349
+ };
2350
+ /** Anything path edit puts on the path: an anchor, a control, a segment, a
2351
+ * segment's balance grip, or a corner widget. */
2352
+ declare const isPathEditPart: TargetPredicate & {
2353
+ readsAffordance: true;
2354
+ };
2040
2355
 
2041
2356
  /** A press being held toward a long-press. */
2042
2357
  interface PendingLongPress {
@@ -2111,6 +2426,29 @@ interface LongPressOptions {
2111
2426
  /** A store holding the press currently being held, or none. Pass it as `LongPressOptions.state`. */
2112
2427
  declare function createLongPressStore(): LongPressStore;
2113
2428
 
2429
+ /**
2430
+ * The `gestures` kit settings area. Declared here rather than in core because
2431
+ * the dispatcher reads it, and routing sits below core.
2432
+ */
2433
+ /** Pointer gesture timings and travel; each falls back to its constant in `@weasel-js/gestures`. */
2434
+ interface GestureKitSettings {
2435
+ /** Longest gap between the clicks of a double click, in ms. */
2436
+ doubleClickMs: number;
2437
+ /** Farthest apart the clicks of a double click may land, in CSS px. */
2438
+ doubleClickPx: number;
2439
+ /** How long a touch or pen press is held to fire a long-press, in ms. */
2440
+ longPressMs: number;
2441
+ /** Farthest a multitouch tap's fingers may travel, in CSS px. */
2442
+ tapPx: number;
2443
+ /** Travel that makes a press a drag, in CSS px. */
2444
+ dragPx: number;
2445
+ }
2446
+ declare module '@weasel-js/react' {
2447
+ interface KitSettings {
2448
+ gestures: GestureKitSettings;
2449
+ }
2450
+ }
2451
+
2114
2452
  /**
2115
2453
  * The DOM half of a drag: one pointer, held down, from press to release.
2116
2454
  *
@@ -2168,6 +2506,60 @@ interface PointerSession {
2168
2506
  */
2169
2507
  declare function openPointerSession(origin: Element, down: PointerEvent | React.PointerEvent, cb: PointerSessionCallbacks, opts?: PointerSessionOptions): PointerSession;
2170
2508
 
2509
+ /**
2510
+ * A press that begins on one element and is carried over another: the in-app
2511
+ * sibling of an OS drag. The source opens the carry; every dispatcher with a
2512
+ * `carry` channel registers its element as a surface, and the one under the
2513
+ * pointer dispatches the carry as `carry` events through its bindings.
2514
+ */
2515
+
2516
+ /** What a carry brings. `type` is what a `carry` spec's `types` globs filter. */
2517
+ interface CarryPayload {
2518
+ type: string;
2519
+ value: unknown;
2520
+ }
2521
+ /** The pointer facts a surface reads off each step of a carry. */
2522
+ interface CarryPointer {
2523
+ clientX: number;
2524
+ clientY: number;
2525
+ altKey: boolean;
2526
+ ctrlKey: boolean;
2527
+ metaKey: boolean;
2528
+ shiftKey: boolean;
2529
+ }
2530
+ /** What a carry did on a surface: came over it, moved on it, was released on
2531
+ * it, or left it — off it, or canceled while over it. */
2532
+ type CarryStage = 'enter' | 'move' | 'drop' | 'leave';
2533
+ /** What {@link startCarry} reports to its source. Exactly one of `onEnd` /
2534
+ * `onCancel` fires. */
2535
+ interface CarryCallbacks {
2536
+ /** Every move of the carrying pointer. */
2537
+ onMove?: (e: PointerEvent) => void;
2538
+ /** The pointer was released. `taken` is whether a binding on the surface
2539
+ * under it took the carry. */
2540
+ onEnd?: (result: {
2541
+ taken: boolean;
2542
+ event: PointerEvent;
2543
+ }) => void;
2544
+ /** The carry ended without a release. Any surface it was over has had its leave. */
2545
+ onCancel?: (reason: PointerSessionCancelReason) => void;
2546
+ }
2547
+ /** A live carry, opened by {@link startCarry}. */
2548
+ interface Carry {
2549
+ readonly pointerId: number;
2550
+ readonly active: boolean;
2551
+ /** End the carry now, as a cancel. Idempotent. */
2552
+ cancel(): void;
2553
+ }
2554
+ /**
2555
+ * Carry `payload` from the press `down` on `origin` until the pointer is
2556
+ * released or the press is canceled. While it moves, the surface under it
2557
+ * hears the carry come over, move, and leave; a release over one is a drop
2558
+ * there. The press is captured to `origin` as any drag is, so nothing the
2559
+ * pointer passes over sees it as a press of its own.
2560
+ */
2561
+ declare function startCarry(origin: Element, down: PointerEvent | React.PointerEvent, payload: CarryPayload, cb?: CarryCallbacks): Carry;
2562
+
2171
2563
  /** What the registry knows at dispatch time. */
2172
2564
  interface EligibilityState {
2173
2565
  focusedId: string | null;
@@ -2348,6 +2740,8 @@ interface ToolDef<TOverlay = KernelOverlay> {
2348
2740
  * binding that points at an action id nothing registered.
2349
2741
  */
2350
2742
  actions?: Action[];
2743
+ /** Menus this tool adds while it is active. */
2744
+ menus?: MenuDef[];
2351
2745
  /** Hook name as exported from the kit barrel (e.g. `'useHandTool'`).
2352
2746
  * Set by built-in hooks for inspector / debugging. Consumer-authored
2353
2747
  * tools may set this to surface their hook name; omitted is fine.
@@ -2554,8 +2948,7 @@ interface ToolScopes {
2554
2948
  /**
2555
2949
  * Detect reachable route conflicts in an assembled tool set and report each one.
2556
2950
  *
2557
- * Call it once wherever a tool set is assembled, behind a
2558
- * `process.env.NODE_ENV !== 'production'` guard.
2951
+ * Call it once wherever a tool set is assembled, behind an `isDev()` guard.
2559
2952
  *
2560
2953
  * **Warn, never throw.** A conflict between a consumer's tool and a kit tool
2561
2954
  * is sometimes deliberate, since the loser can still take the gesture when
@@ -2573,6 +2966,8 @@ declare function reportRouteConflicts(scopes: ToolScopes, warn?: (message: strin
2573
2966
  *
2574
2967
  * Extracted from the deleted singular `useKeybinding` hook so the remaining
2575
2968
  * consumers don't depend on its disappearance.
2969
+ *
2970
+ * @packageDocumentation
2576
2971
  */
2577
2972
 
2578
2973
  /**
@@ -2618,6 +3013,30 @@ declare function matchesKeyBinding(e: KeyboardEvent, b: KeyBinding): boolean;
2618
3013
  * React keyboard event as readily as a DOM one. */
2619
3014
  declare function historyKey(e: Pick<KeyboardEvent, 'key' | 'metaKey' | 'ctrlKey' | 'shiftKey' | 'altKey'>): 'undo' | 'redo' | null;
2620
3015
 
3016
+ /**
3017
+ * Key chords a major browser or the desktop under it takes before a page can:
3018
+ * reload, devtools, tab and window commands, menu accelerators. A binding on
3019
+ * one never fires for some users, so kit defaults steer clear of them.
3020
+ *
3021
+ * `mod` is Cmd on macOS and Ctrl elsewhere, as in a `KeySpec`. The list is
3022
+ * the union across Chrome, Safari, Firefox and Edge on macOS, Windows and
3023
+ * Linux, and errs toward listing a chord.
3024
+ */
3025
+
3026
+ /** One reserved chord, and what takes it. */
3027
+ interface ReservedChord {
3028
+ key: string;
3029
+ mod?: boolean;
3030
+ alt?: boolean;
3031
+ shift?: boolean;
3032
+ /** Who takes it, for a message. */
3033
+ use: string;
3034
+ }
3035
+ /** Every chord the module's header describes, one entry per key. */
3036
+ declare const BROWSER_RESERVED_CHORDS: readonly ReservedChord[];
3037
+ /** The first reserved chord `spec` can fire on, or `null` when none. */
3038
+ declare function browserReservedChord(spec: KeySpec): ReservedChord | null;
3039
+
2621
3040
  /**
2622
3041
  * Typed keys for the gesture/behavior scratch store, `ctx.scratch`.
2623
3042
  * `ScratchKey<T>` carries its payload type at the typing layer; at runtime
@@ -2750,13 +3169,15 @@ declare function dlog(namespace: string, ...args: unknown[]): void;
2750
3169
  * (e.g. no-op op batches suppressed). */
2751
3170
  declare function dwarn(namespace: string, ...args: unknown[]): void;
2752
3171
 
2753
- /**
2754
- * @weasel-js/routing — binding-to-action routing.
2755
- *
2756
- * The pure half: no React, no DOM. The React seam that pumps browser events
2757
- * into the dispatcher, and the providers that feed it, live behind
2758
- * `@weasel-js/routing/react`.
2759
- */
3172
+ /** The menus live now: ambient defs, then the active tool's. Defs that share
3173
+ * an id become one menu: each contribution's children in turn, with a
3174
+ * separator between contributions. Children stay at their own keys, so the
3175
+ * paths their values are read at do not move; a key a previous contribution
3176
+ * took gets `~n` appended. The first def of an id supplies the schema's
3177
+ * name and the def's `when`. */
3178
+ declare function mergeMenuDefs(defs: readonly OwnedMenuDef[], activeTool: string | null): MenuDef[];
3179
+ /** The first def whose `when` matches `hit`. */
3180
+ declare function pickMenu(defs: readonly MenuDef[], hit: MenuHit): MenuDef | undefined;
2760
3181
 
2761
3182
  /**
2762
3183
  * The dependency schema — the map of dep name → value type that
@@ -2779,9 +3200,34 @@ declare function dwarn(namespace: string, ...args: unknown[]): void;
2779
3200
  interface DepSchema {
2780
3201
  /** Currently active tool id + hotkey-hold stack. */
2781
3202
  activeTool: ActiveToolContextValue;
3203
+ /** The menu host of the `ActionsProvider` in scope. */
3204
+ menuHost?: MenuHost;
2782
3205
  }
2783
3206
  /** Every dep name declared by anything that has merged into {@link DepSchema}. */
2784
3207
  type DepName = keyof DepSchema;
3208
+ /**
3209
+ * The params each action reads, by action id — what types a tuning's
3210
+ * `params` and the params on the bindings it adds. Whoever ships an action
3211
+ * merges its entry in, as with {@link DepSchema}:
3212
+ *
3213
+ * ```ts
3214
+ * declare module '@weasel-js/core' {
3215
+ * interface ActionParamSchema { simplifyBrush: { radiusPx: number } }
3216
+ * }
3217
+ * ```
3218
+ *
3219
+ * Declare an entry as a type literal, not an interface: an interface has no
3220
+ * index signature, so it is not a `Record<string, unknown>`.
3221
+ */
3222
+ interface ActionParamSchema {
3223
+ }
3224
+ /** Tunings keyed by action id: typed by {@link ActionParamSchema} for an id it
3225
+ * declares, `Record<string, unknown>` params for any other. */
3226
+ type ActionTunings = {
3227
+ readonly [K in keyof ActionParamSchema]?: ActionTuning<ActionParamSchema[K]>;
3228
+ } & {
3229
+ readonly [id: string]: ActionTuning | undefined;
3230
+ };
2785
3231
  /**
2786
3232
  * What the kernel drawing these tools takes as an overlay. Routing never reads
2787
3233
  * an overlay, so it has no type of its own for one; the kernel merges its type
@@ -2803,4 +3249,4 @@ type KernelOverlay = OverlaySchema extends {
2803
3249
  overlay: infer O;
2804
3250
  } ? O : unknown;
2805
3251
 
2806
- export { type DeviceProfile as $, type ActionsRegistry as A, type BindingOpts as B, type Contribution as C, type DepRegistry as D, type BindingScope as E, type BindingSource as F, type BodyPredicate as G, type BoundGesture as H, type Bounds as I, type BuildRuleCtxArgs as J, type KernelOverlay as K, type LongPressOptions as L, COARSE_TARGET_SCALE as M, type NodeId as N, type OverlayPosition as O, type Condition as P, type Conflict as Q, type RuleCtx as R, ScopeNode as S, ToolNode as T, type ContributionChrome as U, type ContributionDeps as V, type ContributionRouting as W, DEFAULT_ALLOWED_CAPABILITIES as X, DEFAULT_DEVICE_PROFILE as Y, type DebugSink as Z, type DetectedDeviceFacts as _, type DepName as a, actionBindings as a$, type DispatchRecord as a0, type DispatchRecordInput as a1, type DispatcherContext as a2, type DragSample as a3, type DroppedCandidate as a4, type Eligibility as a5, type EligibilityState as a6, type GestureBinding as a7, type HandleKind as a8, type HitShape as a9, type PointerSessionOptions as aA, type RankedCandidate as aB, type RecordCandidate as aC, type RegistryEntry as aD, type ResizeAnchor as aE, type ResolveAllOptions as aF, type ResolveOnlyResult as aG, type ResolvedCandidate as aH, type Rule as aI, type ScopedBinding as aJ, type ScratchKey as aK, type ScratchStore as aL, type SelectionApi as aM, type Selector as aN, type SpecificityPart as aO, TOOL_OFFHAND_ID as aP, type ToolDef as aQ, type ToolKeybinding as aR, type ToolModifiers as aS, type ToolOffhandBindingSpec as aT, type ToolPresentation as aU, type ToolScopes as aV, type ToolSlot as aW, type TraceLogEntry as aX, type UiOngoingControl as aY, type ViewportGestureKind as aZ, type WalkStep as a_, type HotkeyTrigger as aa, INGEST_STRING_MIMES as ab, type ImmediateInvoker as ac, type InvocationCtx as ad, type Invoker as ae, type KeyBinding as af, type LongPressState as ag, type LongPressStore as ah, type MatchOutcome as ai, type MatchResult as aj, type ModeShortcutHandlers as ak, type ModeSwitchLogEntry as al, type ModifierState as am, NEVER as an, type OngoingHandle as ao, type OngoingInvoker as ap, type OngoingOverlay as aq, type OverlayRole as ar, type OverlaySchema as as, PREDICATE_TARGET as at, type PendingLongPress as au, type PlacedBy as av, type Point2 as aw, type PointerSession as ax, type PointerSessionCallbacks as ay, type PointerSessionCancelReason as az, type DepSchema as b, validateActionId as b$, actionItems as b0, assembleEntries as b1, buildDepsFromRequires as b2, buildRouteRegistry as b3, buildRuleCtx as b4, buildToolOffhandBindings as b5, clientToCanvas as b6, clientToCanvasRect as b7, createDepRegistry as b8, createDispatcher as b9, itemsFromDataTransfer as bA, itemsFromFiles as bB, liveScope as bC, makeToolOffhandAction as bD, matchBest as bE, matchSorted as bF, matchSortedWithBarred as bG, matchesKeyBinding as bH, mergeContributions as bI, modeShortcutSpec as bJ, modeShortcuts as bK, multiTouchGestureId as bL, offhandKeyFor as bM, openPointerSession as bN, pointerGestureId as bO, recordModeSwitch as bP, reportRouteConflicts as bQ, resolveDeviceProfile as bR, resolveParams as bS, routesForSpec as bT, ruleCanHoldIn as bU, rulesExclusive as bV, scopeBindings as bW, scratchKey as bX, setScratch as bY, targetConsultsAffordance as bZ, validateActionDefaultBinding as b_, createLongPressStore as ba, defineTool as bb, deleteScratch as bc, describeRule as bd, dlog as be, dwarn as bf, evaluate as bg, evaluateActive as bh, evaluateEnabled as bi, findConflicts as bj, getScratch as bk, heldKeySpec as bl, historyKey as bm, isAnchor as bn, isAnchorOrControl as bo, isBody as bp, isControlHandle as bq, isDebugEnabled as br, isEmpty as bs, isResizeHandle as bt, isRotateHandle as bu, isSelectedBody as bv, isTool as bw, isUnselectedBody as bx, itemTypesFromDataTransfer as by, itemsFromClipboardData as bz, type Action as c, DepNode as d, type Tool as e, ActiveToolContextProvider as f, ActiveToolContextProviderIfRoot as g, type ActiveToolContextProviderProps as h, type ActiveToolContextValue as i, useOptionalActiveToolContext as j, type Dispatcher as k, type AffordanceHit as l, ALWAYS as m, type ActionDeps as n, ActionDisabledReason as o, type ActionDispatch as p, type ActionEnabledResult as q, type ActionEntry as r, type ActionItem as s, type ActionPresentation as t, useActiveToolContext as u, type ActionSource as v, type ActionVariant as w, type ActionsProp as x, type AnyTool as y, type AssemblyInputs as z };
3252
+ export { type CarryCallbacks as $, type Action as A, type BoundGesture as B, type Contribution as C, type DepRegistry as D, type ActionSource as E, type ActionTuning as F, type ActionTunings as G, type ActionsProp as H, type AnyTool as I, type AssemblyInputs as J, type KernelOverlay as K, type LongPressOptions as L, type MenuHost as M, type NodeId as N, type OverlayPosition as O, BROWSER_RESERVED_CHORDS as P, type BindingOpts as Q, type RuleCtx as R, ScopeNode as S, ToolNode as T, type BindingScope as U, type BindingSource as V, type BodyPredicate as W, type Bounds as X, type BuildRuleCtxArgs as Y, COARSE_TARGET_SCALE as Z, type Carry as _, type DepName as a, type ResizeAnchor as a$, type CarryPayload as a0, type CarryPointer as a1, type CarryStage as a2, type Condition as a3, type Conflict as a4, type ContributionChrome as a5, type ContributionDeps as a6, type ContributionRouting as a7, DEFAULT_ALLOWED_CAPABILITIES as a8, DEFAULT_DEVICE_PROFILE as a9, type MenuSources as aA, type MenuWhen as aB, type ModeShortcutHandlers as aC, type ModeSwitchLogEntry as aD, type ModifierRole as aE, type ModifierRoles as aF, type ModifierState as aG, NEVER as aH, type OngoingHandle as aI, type OngoingInvoker as aJ, type OngoingOverlay as aK, type OpenMenu as aL, type OverlayRole as aM, type OverlaySchema as aN, type OwnedMenuDef as aO, PREDICATE_TARGET as aP, type PendingLongPress as aQ, type PlacedBy as aR, type Point2 as aS, type PointerSession as aT, type PointerSessionCallbacks as aU, type PointerSessionCancelReason as aV, type PointerSessionOptions as aW, type RankedCandidate as aX, type RecordCandidate as aY, type RegistryEntry as aZ, type ReservedChord as a_, type DebugSink as aa, type DetectedDeviceFacts as ab, type DeviceProfile as ac, type DispatchRecord as ad, type DispatchRecordInput as ae, type DispatcherContext as af, type DragSample as ag, type DroppedCandidate as ah, type Eligibility as ai, type EligibilityState as aj, type GestureBinding as ak, type GestureKitSettings as al, type HandleKind as am, type HitShape as an, type HotkeyTrigger as ao, INGEST_STRING_MIMES as ap, type ImmediateInvoker as aq, type InvocationCtx as ar, type Invoker as as, type KeyBinding as at, type LongPressState as au, type LongPressStore as av, type MatchOutcome as aw, type MatchResult as ax, type MenuHit as ay, type MenuOpenRequest as az, type DepSchema as b, isPathEditPart as b$, type ResolveAllOptions as b0, type ResolveOnlyResult as b1, type ResolvedCandidate as b2, type RoleKeys as b3, type RoleRebinds as b4, type Rule as b5, type ScopedBinding as b6, type ScratchKey as b7, type ScratchStore as b8, type SelectionApi as b9, buildToolOffhandBindings as bA, clientToCanvas as bB, clientToCanvasRect as bC, createDepRegistry as bD, createDispatcher as bE, createLongPressStore as bF, createMenuHost as bG, defineTool as bH, deleteScratch as bI, describeRule as bJ, dlog as bK, dwarn as bL, evaluate as bM, evaluateActive as bN, evaluateEnabled as bO, findConflicts as bP, getScratch as bQ, heldKeySpec as bR, historyKey as bS, isAnchor as bT, isAnchorOrControl as bU, isBalanceGrip as bV, isBody as bW, isControlHandle as bX, isCornerWidget as bY, isDebugEnabled as bZ, isEmpty as b_, type Selector as ba, type SpecificityPart as bb, TOOL_OFFHAND_ID as bc, type ToolDef as bd, type ToolKeybinding as be, type ToolModifiers as bf, type ToolOffhandBindingSpec as bg, type ToolPresentation as bh, type ToolScopes as bi, type ToolSlot as bj, type TraceLogEntry as bk, type TunedBinding as bl, type UiOngoingControl as bm, type ViewportGestureKind as bn, type WalkStep as bo, actionBindings as bp, actionCursor as bq, actionItemTitle as br, actionItems as bs, actionShortcuts as bt, actionsTagged as bu, assembleEntries as bv, browserReservedChord as bw, buildDepsFromRequires as bx, buildRouteRegistry as by, buildRuleCtx as bz, type ActionDeps as c, isResizeHandle as c0, isRotateHandle as c1, isSegment as c2, isSelectedBody as c3, isTool as c4, isUnselectedBody as c5, itemTypesFromDataTransfer as c6, itemsFromClipboardData as c7, itemsFromDataTransfer as c8, itemsFromFiles as c9, routesForSpec as cA, ruleCanHoldIn as cB, rulesExclusive as cC, scopeBindings as cD, scratchKey as cE, setScratch as cF, startCarry as cG, taggedActionItems as cH, targetConsultsAffordance as cI, tuneAction as cJ, validateActionDefaultBinding as cK, validateActionId as cL, keySpecShortcut as ca, keysHeld as cb, liveScope as cc, makeToolOffhandAction as cd, matchActionItem as ce, matchBest as cf, matchSorted as cg, matchSortedWithBarred as ch, matchesKeyBinding as ci, mergeContributions as cj, mergeMenuDefs as ck, modeShortcutSpec as cl, modeShortcuts as cm, multiTouchGestureId as cn, offhandKeyFor as co, openPointerSession as cp, overlaysOf as cq, pickMenu as cr, pointerGestureId as cs, recordModeSwitch as ct, reportRouteConflicts as cu, resolveDeviceProfile as cv, resolveMenu as cw, resolveParams as cx, resolveSchemaMenu as cy, roleReader as cz, type ActionsRegistry as d, ActionDisabledReason as e, type ActionVariant as f, type MenuDef as g, DepNode as h, type Tool as i, ActiveToolContextProvider as j, ActiveToolContextProviderIfRoot as k, type ActiveToolContextProviderProps as l, type ActiveToolContextValue as m, useOptionalActiveToolContext as n, type Dispatcher as o, type AffordanceHit as p, ALWAYS as q, type ActionDispatch as r, type ActionEnabledResult as s, type ActionEntry as t, useActiveToolContext as u, type ActionItem as v, type ActionParamSchema as w, type ActionParams as x, type ActionPresentation as y, type ActionShortcut as z };