@weasel-js/routing 1.10.1 → 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';
5
- import { ClaimableGesture, GestureSpec, IngestItem, InputEvent, TargetSpec, KeyHeldSpec, TargetPredicate, KeySpec, ParsedModifiers, GestureName } from '@weasel-js/gestures';
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';
6
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';
7
8
  import { CursorSpec } from '@weasel-js/cursor';
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,101 +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
- /** World affines the shape will also be drawn under once it lands, by
829
- * the container it is drawn into: the preview is painted under each. */
830
- copies?: readonly (readonly [number, number, number, number, number, number])[];
831
- };
796
+
832
797
  /** Handle returned from an `OngoingInvoker.start`. The dispatcher pumps
833
798
  * `onMove` on subsequent input events of the same gesture and calls
834
799
  * `onEnd` exactly once (with `'commit'` on natural completion or `'cancel'`
@@ -885,10 +850,19 @@ interface OngoingHandle {
885
850
  previewData?(id: string): unknown | null;
886
851
  /**
887
852
  * Optional chrome surface: a non-ghost visual (marquee rectangle, lasso
888
- * polyline) painted while the gesture is in flight. Returning `null`, or
889
- * 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.
890
857
  */
891
- overlay?(): OngoingOverlay | null;
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.
864
+ */
865
+ onWheel?(ctx: InvocationCtx): boolean | void;
892
866
  }
893
867
  /** Fire-once invocation. Runs to completion synchronously (or fires off an
894
868
  * async side-effect; the registry doesn't wait). */
@@ -935,7 +909,6 @@ type BoundGesture = GestureSpec | {
935
909
  opts: BindingOpts;
936
910
  };
937
911
  /**
938
- * @experimental
939
912
  * The whole of an action `actionBindings` reads. Routing needs this much and
940
913
  * none of `Action`'s palette fields, so it is the narrowest type the
941
914
  * dispatcher's binding walk can be written against.
@@ -952,14 +925,12 @@ interface BindingSource {
952
925
  defaultBinding?: GestureSpec | BoundGesture[];
953
926
  }
954
927
  /**
955
- * @experimental
956
928
  * Flatten an action's `defaultBinding` into `GestureBinding`s. A bare
957
929
  * `GestureSpec` has `kind` at top level; the object form has `spec`.
958
930
  */
959
931
  declare function actionBindings(action: BindingSource): GestureBinding[];
960
932
 
961
933
  /**
962
- * @experimental
963
934
  * Closed enum of reasons an action might report itself as disabled. The
964
935
  * consumer (palette, menu, etc.) maps these symbolic values to display
965
936
  * strings via its own label map.
@@ -974,20 +945,23 @@ declare const ActionDisabledReason: {
974
945
  /** Why an action is unavailable right now. */
975
946
  type ActionDisabledReason = (typeof ActionDisabledReason)[keyof typeof ActionDisabledReason];
976
947
  /**
977
- * @experimental
978
948
  * What a palette, menu or toolbar renders for an action. No part of this is
979
949
  * read during dispatch.
980
950
  */
981
951
  interface ActionPresentation {
982
952
  label: string;
983
- /** Inline-SVG icon for palette / toolbar surfaces. May be a static
984
- * `ReactNode` or a function (rare; useful for state-aware icons like a
985
- * "lock" toggle). */
986
- icon?: ReactNode | (() => ReactNode);
953
+ /** The action's icon, by qualified name: `icon('group')` in the package that draws it. */
954
+ icon?: IconRef;
987
955
  /** Grouping key for palette/menu surfaces. Free-form string; the kit
988
956
  * ships defaults for `'align'` (six edges/centers), `'distribute'`
989
957
  * (two axes), and recommends `'pathfinder'` for boolean ops. */
990
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[];
991
965
  /** Display override for the keyboard shortcut. When omitted, palette
992
966
  * surfaces derive a label from `defaultBinding` via their own
993
967
  * formatter. */
@@ -1000,7 +974,6 @@ interface ActionPresentation {
1000
974
  variants?: readonly ActionVariant[];
1001
975
  }
1002
976
  /**
1003
- * @experimental
1004
977
  * One entry a parametric action contributes to a bar, menu or palette.
1005
978
  */
1006
979
  interface ActionVariant {
@@ -1008,13 +981,14 @@ interface ActionVariant {
1008
981
  key: string;
1009
982
  label: string;
1010
983
  /** Falls back to the action's own `icon`. */
1011
- icon?: ReactNode | (() => ReactNode);
984
+ icon?: IconRef;
985
+ /** Tags this variant carries besides its action's, which it carries too. */
986
+ tags?: readonly string[];
1012
987
  /** Passed to `trigger`, and matched against each binding's
1013
988
  * `opts.params` to find the variant's shortcuts. */
1014
989
  params: Readonly<Record<string, unknown>>;
1015
990
  }
1016
991
  /**
1017
- * @experimental
1018
992
  * What routing consults: the bindings that reach the action, the deps its
1019
993
  * invoker reads, the gates it passes, and the cursors it claims.
1020
994
  */
@@ -1036,14 +1010,14 @@ interface ActionDispatch extends BindingSource {
1036
1010
  * shortcuts and global held-key triggers. Default: ambient. */
1037
1011
  scope?: 'hotkey';
1038
1012
  /**
1039
- * @experimental
1040
1013
  * Optional predicate saying whether the action can run right now. Return
1041
1014
  * `true` when it can, or an `ActionDisabledReason` when it cannot. The
1042
1015
  * command palette greys out a disabled row, skips it in keyboard nav,
1043
1016
  * ignores clicks, and shows the reason next to the label. The dispatcher
1044
1017
  * skips a disabled action too, on a key as on a pointer, and falls through
1045
- * to the next binding that matches. `ActionsRegistry.trigger` does not ask,
1046
- * 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.
1047
1021
  *
1048
1022
  * **Contract:** must be pure (no side effects), fast (< 4ms in dev), and
1049
1023
  * must not throw. A throw is caught and treated as disabled with reason
@@ -1058,8 +1032,10 @@ interface ActionDispatch extends BindingSource {
1058
1032
  * click, a press, a long-press. An action that only applies somewhere
1059
1033
  * (on a path segment, say) refuses other points here, so the dispatcher
1060
1034
  * falls through to the next binding and hover prediction shows the
1061
- * action's `cursor` only where it would act. Palettes and keystrokes
1062
- * 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".
1063
1039
  *
1064
1040
  * `carried` is what a drop or a paste being routed brings: its items. For
1065
1041
  * a drag still in flight they hold a MIME and nothing else, since a
@@ -1074,7 +1050,6 @@ interface ActionDispatch extends BindingSource {
1074
1050
  items: readonly IngestItem[];
1075
1051
  }) => true | ActionDisabledReason;
1076
1052
  /**
1077
- * @experimental
1078
1053
  * Whether the action reads as held down right now: bold on the selected
1079
1054
  * text, snapping switched on. A toolbar button draws it as pressed.
1080
1055
  * Omitted = the action has no pressed state, which is not the same as
@@ -1084,6 +1059,15 @@ interface ActionDispatch extends BindingSource {
1084
1059
  * throw. `deps` is the bag `enabled` is given.
1085
1060
  */
1086
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;
1087
1071
  /**
1088
1072
  * Declarative eligibility rule, evaluated against the current
1089
1073
  * `RuleCtx` by the dispatcher before invoking `start()`. Omitted =
@@ -1106,12 +1090,14 @@ interface ActionDispatch extends BindingSource {
1106
1090
  * resolved earlier in the pump via `AffordanceRegion.cursor` and never
1107
1091
  * reach this field.
1108
1092
  *
1109
- * Static value only. Prediction runs `enabled()` but cannot run the
1110
- * invoker, so an action that matches yet bails at `start()` (empty
1111
- * handle) may still show its cursor — keep `enabled` accurate for
1112
- * 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.
1113
1099
  */
1114
- cursor?: CursorSpec;
1100
+ cursor?: CursorSpec | ((params: Record<string, unknown> | undefined) => CursorSpec | undefined);
1115
1101
  /**
1116
1102
  * CSS cursor shown while THIS action's ongoing handle is in flight —
1117
1103
  * grabbing while panning, `move` while dragging a selection, `crosshair`
@@ -1124,15 +1110,22 @@ interface ActionDispatch extends BindingSource {
1124
1110
  * gesture.
1125
1111
  */
1126
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;
1127
1122
  }
1128
1123
  /**
1129
- * @experimental
1130
1124
  * Single registered action.
1131
1125
  */
1132
1126
  interface Action extends ActionDispatch, ActionPresentation {
1133
1127
  }
1134
1128
  /**
1135
- * @experimental
1136
1129
  * The whole of an actions registry the dispatcher reads. It walks the list
1137
1130
  * once per event to build its actionId lookup and never mutates it, so the
1138
1131
  * routing side depends on this rather than on `ActionsRegistry`, whose
@@ -1141,6 +1134,200 @@ interface Action extends ActionDispatch, ActionPresentation {
1141
1134
  interface ActionSource {
1142
1135
  list(): readonly Action[];
1143
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;
1144
1331
 
1145
1332
  /**
1146
1333
  * Tuning: what a host changes about an action it did not write — the params
@@ -1168,41 +1355,93 @@ interface ActionTuning<P = Record<string, unknown>> {
1168
1355
  params?: ActionParams<P>;
1169
1356
  /** Bindings added after the action's own `defaultBinding`. */
1170
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;
1171
1361
  }
1172
1362
  /** `action` with each tuning applied in turn, a later one's params over an
1173
1363
  * earlier one's. Applying a tuning to a copy it already tuned changes nothing. */
1174
1364
  declare function tuneAction(action: Action, tunings: readonly ActionTuning[]): Action;
1175
1365
 
1176
1366
  /**
1177
- * @experimental
1178
1367
  * The entries an action contributes to a bar, menu or palette — one per
1179
1368
  * variant, or the action itself when it declares none.
1180
1369
  */
1181
1370
 
1182
- /** @experimental One renderable entry: an action, optionally with params. */
1371
+ /** One renderable entry: an action, optionally with params. */
1183
1372
  interface ActionItem {
1184
1373
  /** `action.id`, or `action.id:variant.key` — unique across a registry. */
1185
1374
  key: string;
1186
1375
  action: Action;
1187
1376
  label: string;
1188
- icon?: ReactNode | (() => ReactNode);
1377
+ icon?: IconRef;
1378
+ /** The action's tags, then the variant's own. */
1379
+ tags: readonly string[];
1189
1380
  /** What to pass to `trigger(action.id, params)`; absent for a plain action. */
1190
1381
  params?: Readonly<Record<string, unknown>>;
1191
1382
  }
1192
- /** @experimental Expand `action` into the entries a surface renders. An
1383
+ /** Expand `action` into the entries a surface renders. An
1193
1384
  * action without an immediate invoker has none: `trigger` cannot start a
1194
1385
  * drag, so a button for one would do nothing. */
1195
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;
1196
1437
 
1197
1438
  /**
1198
- * @experimental
1199
1439
  * Palette-side evaluation of `Action.enabled`. The dispatcher calls the
1200
1440
  * predicate raw as a gate; this is the surface that also enforces the
1201
1441
  * contract the predicate's JSDoc states — no throwing, under 4ms in dev.
1202
1442
  */
1203
1443
 
1204
1444
  /**
1205
- * @experimental
1206
1445
  * Result of evaluating an Action's `enabled` predicate.
1207
1446
  */
1208
1447
  interface ActionEnabledResult {
@@ -1210,16 +1449,17 @@ interface ActionEnabledResult {
1210
1449
  reason?: ActionDisabledReason;
1211
1450
  }
1212
1451
  /**
1213
- * @experimental
1214
1452
  * Safely evaluate an action's `enabled` predicate. Returns `{enabled: true}`
1215
1453
  * when no predicate is supplied. Catches throws and treats them as disabled
1216
1454
  * with reason `'(predicate threw)'`. In dev mode, warns once per action id
1217
1455
  * when a single call exceeds 4ms (single frame at 240fps — generous; real
1218
1456
  * predicates should be sub-millisecond).
1219
1457
  */
1220
- 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;
1221
1462
  /**
1222
- * @experimental
1223
1463
  * Safely evaluate an action's `active` predicate. `undefined` for an action
1224
1464
  * with no pressed state; a predicate that throws reads as not active.
1225
1465
  */
@@ -1290,9 +1530,8 @@ type HotkeyTrigger = 'space' | 'alt' | 'ctrl' | 'meta' | 'shift' | (string & {})
1290
1530
  interface ToolPresentation {
1291
1531
  /** Human-readable label, distinct from the `id`. Falls back to `id`. */
1292
1532
  label?: string;
1293
- /** Inline-SVG icon component output: a static `ReactNode`, or a function
1294
- * returning one. */
1295
- 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;
1296
1535
  /** Palette grouping key. Tools sharing a group render contiguously
1297
1536
  * with separators between groups. Free-form string; the kit
1298
1537
  * recommends 'select' | 'shape' | 'draw' | 'type' | 'view'. */
@@ -1342,6 +1581,8 @@ interface ContributionRouting {
1342
1581
  eligibility: Eligibility;
1343
1582
  bindings?: GestureBinding[];
1344
1583
  actions?: Action[];
1584
+ /** Menus this entry declares: always, for an ambient entry; while active, for a tool. */
1585
+ menus?: MenuDef[];
1345
1586
  /** Dep sources this entry provides while it is installed. A host installs
1346
1587
  * them for as long as the entry is registered, whatever its eligibility. */
1347
1588
  deps?: ContributionDeps;
@@ -1654,6 +1895,8 @@ interface ResolveOnlyResult {
1654
1895
  scope: BindingScope;
1655
1896
  /** Tool id owning the winning binding; `null` for ambient action bindings. */
1656
1897
  ownerId: string | null;
1898
+ /** The params the winning binding would start the action with, resolved now. */
1899
+ params?: Record<string, unknown>;
1657
1900
  }
1658
1901
  /**
1659
1902
  * One candidate from `Dispatcher.resolveAll` — a binding that matched the
@@ -1864,6 +2107,7 @@ declare function recordModeSwitch(mode: string, from: string | null, to: string
1864
2107
  * with no `pointerId` (a synthesized probe, a programmatic drag, most tests)
1865
2108
  * keys to `pointer-mouse`.
1866
2109
  * - `multitouch`: `multitouch-<fingers>`.
2110
+ * - `carry`: `carry-<pointerId>`, keyed as a pointer is.
1867
2111
  * - any other kind that starts an ongoing invoker: `ongoing-<kind>`.
1868
2112
  */
1869
2113
 
@@ -1911,18 +2155,15 @@ declare function createDispatcher(opts?: {
1911
2155
  }): Dispatcher;
1912
2156
 
1913
2157
  /**
1914
- * @experimental
1915
2158
  * Partial override or full descriptor passed via `<SceneCanvas actions={...}>`.
1916
2159
  * `null` disables a default at this id.
1917
2160
  */
1918
2161
  type ActionEntry = null | Partial<Action> | Action;
1919
2162
  /**
1920
- * @experimental
1921
2163
  * Shape of the `actions` prop on `<SceneCanvas>`. `null` disables all defaults.
1922
2164
  */
1923
2165
  type ActionsProp = null | Record<string, ActionEntry>;
1924
2166
  /**
1925
- * @experimental
1926
2167
  * Imperative API exposed by `useActionsRegistry()`.
1927
2168
  */
1928
2169
  interface ActionsRegistry {
@@ -1943,14 +2184,25 @@ interface ActionsRegistry {
1943
2184
  * apply to whichever descriptor is live for it, registered before the
1944
2185
  * tuning or after. Returns a release. See {@link ActionTuning}. */
1945
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>;
1946
2191
  list(): readonly Action[];
1947
2192
  /** Fire an immediate-invoker action by id. The optional `params` arg is
1948
2193
  * forwarded to `ImmediateInvoker.run` as its second argument — use it for
1949
2194
  * parametric actions (e.g. `trigger('tool.activate', { toolId: 'rect' })`).
1950
2195
  * Returns whether it ran one: `false` for an unknown id, for an action
1951
2196
  * whose `enabled` refuses, and for an ongoing-invoker action, which
1952
- * `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. */
1953
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;
1954
2206
  /**
1955
2207
  * Subscribe to registry mutations. The callback fires after any
1956
2208
  * `register`/`unregister` that changes the version. Returns an
@@ -2062,7 +2314,7 @@ declare const isSelectedBody: BodyPredicate;
2062
2314
  declare const isUnselectedBody: BodyPredicate;
2063
2315
  /** Empty-canvas hit — no node beneath cursor. */
2064
2316
  declare const isEmpty: BodyPredicate;
2065
- /** 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`, …). */
2066
2318
  declare const isResizeHandle: TargetPredicate & {
2067
2319
  readsAffordance: true;
2068
2320
  };
@@ -2078,6 +2330,10 @@ declare const isAnchor: TargetPredicate & {
2078
2330
  declare const isControlHandle: TargetPredicate & {
2079
2331
  readsAffordance: true;
2080
2332
  };
2333
+ /** A corner-shape widget, set inside a corner anchor of the edited path. */
2334
+ declare const isCornerWidget: TargetPredicate & {
2335
+ readsAffordance: true;
2336
+ };
2081
2337
  /** Any of the three anchor-editing affordances (anchor + both controls). */
2082
2338
  declare const isAnchorOrControl: TargetPredicate & {
2083
2339
  readsAffordance: true;
@@ -2086,7 +2342,13 @@ declare const isAnchorOrControl: TargetPredicate & {
2086
2342
  declare const isSegment: TargetPredicate & {
2087
2343
  readsAffordance: true;
2088
2344
  };
2089
- /** Anything path edit puts on the path: an anchor, a control, or a segment. */
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. */
2090
2352
  declare const isPathEditPart: TargetPredicate & {
2091
2353
  readsAffordance: true;
2092
2354
  };
@@ -2164,6 +2426,29 @@ interface LongPressOptions {
2164
2426
  /** A store holding the press currently being held, or none. Pass it as `LongPressOptions.state`. */
2165
2427
  declare function createLongPressStore(): LongPressStore;
2166
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
+
2167
2452
  /**
2168
2453
  * The DOM half of a drag: one pointer, held down, from press to release.
2169
2454
  *
@@ -2221,6 +2506,60 @@ interface PointerSession {
2221
2506
  */
2222
2507
  declare function openPointerSession(origin: Element, down: PointerEvent | React.PointerEvent, cb: PointerSessionCallbacks, opts?: PointerSessionOptions): PointerSession;
2223
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
+
2224
2563
  /** What the registry knows at dispatch time. */
2225
2564
  interface EligibilityState {
2226
2565
  focusedId: string | null;
@@ -2401,6 +2740,8 @@ interface ToolDef<TOverlay = KernelOverlay> {
2401
2740
  * binding that points at an action id nothing registered.
2402
2741
  */
2403
2742
  actions?: Action[];
2743
+ /** Menus this tool adds while it is active. */
2744
+ menus?: MenuDef[];
2404
2745
  /** Hook name as exported from the kit barrel (e.g. `'useHandTool'`).
2405
2746
  * Set by built-in hooks for inspector / debugging. Consumer-authored
2406
2747
  * tools may set this to surface their hook name; omitted is fine.
@@ -2607,8 +2948,7 @@ interface ToolScopes {
2607
2948
  /**
2608
2949
  * Detect reachable route conflicts in an assembled tool set and report each one.
2609
2950
  *
2610
- * Call it once wherever a tool set is assembled, behind a
2611
- * `process.env.NODE_ENV !== 'production'` guard.
2951
+ * Call it once wherever a tool set is assembled, behind an `isDev()` guard.
2612
2952
  *
2613
2953
  * **Warn, never throw.** A conflict between a consumer's tool and a kit tool
2614
2954
  * is sometimes deliberate, since the loser can still take the gesture when
@@ -2673,6 +3013,30 @@ declare function matchesKeyBinding(e: KeyboardEvent, b: KeyBinding): boolean;
2673
3013
  * React keyboard event as readily as a DOM one. */
2674
3014
  declare function historyKey(e: Pick<KeyboardEvent, 'key' | 'metaKey' | 'ctrlKey' | 'shiftKey' | 'altKey'>): 'undo' | 'redo' | null;
2675
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
+
2676
3040
  /**
2677
3041
  * Typed keys for the gesture/behavior scratch store, `ctx.scratch`.
2678
3042
  * `ScratchKey<T>` carries its payload type at the typing layer; at runtime
@@ -2805,15 +3169,15 @@ declare function dlog(namespace: string, ...args: unknown[]): void;
2805
3169
  * (e.g. no-op op batches suppressed). */
2806
3170
  declare function dwarn(namespace: string, ...args: unknown[]): void;
2807
3171
 
2808
- /**
2809
- * @weasel-js/routing — binding-to-action routing.
2810
- *
2811
- * The pure half: no React, no DOM. The React seam that pumps browser events
2812
- * into the dispatcher, and the providers that feed it, live behind
2813
- * `@weasel-js/routing/react`.
2814
- *
2815
- * @packageDocumentation
2816
- */
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;
2817
3181
 
2818
3182
  /**
2819
3183
  * The dependency schema — the map of dep name → value type that
@@ -2836,6 +3200,8 @@ declare function dwarn(namespace: string, ...args: unknown[]): void;
2836
3200
  interface DepSchema {
2837
3201
  /** Currently active tool id + hotkey-hold stack. */
2838
3202
  activeTool: ActiveToolContextValue;
3203
+ /** The menu host of the `ActionsProvider` in scope. */
3204
+ menuHost?: MenuHost;
2839
3205
  }
2840
3206
  /** Every dep name declared by anything that has merged into {@link DepSchema}. */
2841
3207
  type DepName = keyof DepSchema;
@@ -2846,7 +3212,7 @@ type DepName = keyof DepSchema;
2846
3212
  *
2847
3213
  * ```ts
2848
3214
  * declare module '@weasel-js/core' {
2849
- * interface ActionParamSchema { brushDeleteAnchors: { radiusPx: number } }
3215
+ * interface ActionParamSchema { simplifyBrush: { radiusPx: number } }
2850
3216
  * }
2851
3217
  * ```
2852
3218
  *
@@ -2883,4 +3249,4 @@ type KernelOverlay = OverlaySchema extends {
2883
3249
  overlay: infer O;
2884
3250
  } ? O : unknown;
2885
3251
 
2886
- export { DEFAULT_ALLOWED_CAPABILITIES as $, type ActionsRegistry as A, type ActionVariant as B, type Contribution as C, type DepRegistry as D, type ActionsProp as E, type AnyTool as F, type AssemblyInputs as G, type BindingOpts as H, type BindingScope as I, type BindingSource as J, type KernelOverlay as K, type LongPressOptions as L, type BodyPredicate as M, type NodeId as N, type OverlayPosition as O, type BoundGesture as P, type Bounds as Q, type RuleCtx as R, ScopeNode as S, ToolNode as T, type BuildRuleCtxArgs as U, COARSE_TARGET_SCALE as V, type Condition as W, type Conflict as X, type ContributionChrome as Y, type ContributionDeps as Z, type ContributionRouting as _, type DepName as a, type TraceLogEntry as a$, DEFAULT_DEVICE_PROFILE as a0, type DebugSink as a1, type DetectedDeviceFacts as a2, type DeviceProfile as a3, type DispatchRecord as a4, type DispatchRecordInput as a5, type DispatcherContext as a6, type DragSample as a7, type DroppedCandidate as a8, type Eligibility as a9, type Point2 as aA, type PointerSession as aB, type PointerSessionCallbacks as aC, type PointerSessionCancelReason as aD, type PointerSessionOptions as aE, type RankedCandidate as aF, type RecordCandidate as aG, type RegistryEntry as aH, type ResizeAnchor as aI, type ResolveAllOptions as aJ, type ResolveOnlyResult as aK, type ResolvedCandidate as aL, type Rule as aM, type ScopedBinding as aN, type ScratchKey as aO, type ScratchStore as aP, type SelectionApi as aQ, type Selector as aR, type SpecificityPart as aS, TOOL_OFFHAND_ID as aT, type ToolDef as aU, type ToolKeybinding as aV, type ToolModifiers as aW, type ToolOffhandBindingSpec as aX, type ToolPresentation as aY, type ToolScopes as aZ, type ToolSlot as a_, type EligibilityState as aa, type GestureBinding as ab, type HandleKind as ac, type HitShape as ad, type HotkeyTrigger as ae, INGEST_STRING_MIMES as af, type ImmediateInvoker as ag, type InvocationCtx as ah, type Invoker as ai, type KeyBinding as aj, type LongPressState as ak, type LongPressStore as al, type MatchOutcome as am, type MatchResult as an, type ModeShortcutHandlers as ao, type ModeSwitchLogEntry as ap, type ModifierState as aq, NEVER as ar, type OngoingHandle as as, type OngoingInvoker as at, type OngoingOverlay as au, type OverlayRole as av, type OverlaySchema as aw, PREDICATE_TARGET as ax, type PendingLongPress as ay, type PlacedBy as az, type DepSchema as b, ruleCanHoldIn as b$, type TunedBinding as b0, type UiOngoingControl as b1, type ViewportGestureKind as b2, type WalkStep as b3, actionBindings as b4, actionItems as b5, assembleEntries as b6, buildDepsFromRequires as b7, buildRouteRegistry as b8, buildRuleCtx as b9, isRotateHandle as bA, isSegment as bB, isSelectedBody as bC, isTool as bD, isUnselectedBody as bE, itemTypesFromDataTransfer as bF, itemsFromClipboardData as bG, itemsFromDataTransfer as bH, itemsFromFiles as bI, liveScope as bJ, makeToolOffhandAction as bK, matchBest as bL, matchSorted as bM, matchSortedWithBarred as bN, matchesKeyBinding as bO, mergeContributions as bP, modeShortcutSpec as bQ, modeShortcuts as bR, multiTouchGestureId as bS, offhandKeyFor as bT, openPointerSession as bU, pointerGestureId as bV, recordModeSwitch as bW, reportRouteConflicts as bX, resolveDeviceProfile as bY, resolveParams as bZ, routesForSpec as b_, buildToolOffhandBindings as ba, clientToCanvas as bb, clientToCanvasRect as bc, createDepRegistry as bd, createDispatcher as be, createLongPressStore as bf, defineTool as bg, deleteScratch as bh, describeRule as bi, dlog as bj, dwarn as bk, evaluate as bl, evaluateActive as bm, evaluateEnabled as bn, findConflicts as bo, getScratch as bp, heldKeySpec as bq, historyKey as br, isAnchor as bs, isAnchorOrControl as bt, isBody as bu, isControlHandle as bv, isDebugEnabled as bw, isEmpty as bx, isPathEditPart as by, isResizeHandle as bz, type Action as c, rulesExclusive as c0, scopeBindings as c1, scratchKey as c2, setScratch as c3, targetConsultsAffordance as c4, tuneAction as c5, validateActionDefaultBinding as c6, validateActionId as c7, 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 ActionParamSchema as t, useActiveToolContext as u, type ActionParams as v, type ActionPresentation as w, type ActionSource as x, type ActionTuning as y, type ActionTunings 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 };