@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.
- package/dist/{chunk-VCEIQ64H.js → chunk-QBQQIFPI.js} +580 -51
- package/dist/chunk-QBQQIFPI.js.map +1 -0
- package/dist/{index-DkOqUxow.d.ts → index-CmfVvwWD.d.ts} +645 -279
- package/dist/index.d.ts +6 -3
- package/dist/index.js +54 -17
- package/dist/index.js.map +1 -1
- package/dist/{internal-Boc2I3zn.d.ts → internal-21M1rTVo.d.ts} +23 -1
- package/dist/internal.d.ts +8 -5
- package/dist/react.d.ts +59 -27
- package/dist/react.js +413 -220
- package/dist/react.js.map +1 -1
- package/package.json +13 -9
- package/dist/chunk-VCEIQ64H.js.map +0 -1
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
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
|
-
*
|
|
27
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
889
|
-
*
|
|
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
|
-
/**
|
|
984
|
-
|
|
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?:
|
|
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`
|
|
1046
|
-
*
|
|
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.
|
|
1062
|
-
*
|
|
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
|
-
*
|
|
1110
|
-
*
|
|
1111
|
-
*
|
|
1112
|
-
*
|
|
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
|
-
/**
|
|
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?:
|
|
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
|
-
/**
|
|
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
|
|
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
|
-
/**
|
|
1294
|
-
|
|
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
|
|
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
|
|
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
|
-
/**
|
|
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
|
|
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
|
-
*
|
|
2810
|
-
*
|
|
2811
|
-
*
|
|
2812
|
-
*
|
|
2813
|
-
*
|
|
2814
|
-
|
|
2815
|
-
|
|
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 {
|
|
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 {
|
|
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 };
|