@weasel-js/core 0.7.2 → 1.0.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/CHANGELOG.md +541 -0
- package/dist/{DrawCommand-CJtqqt8H.d.ts → DrawCommand-DCmiNkBj.d.ts} +38 -170
- package/dist/{chunk-CQNKCG34.js → chunk-6SHZHXXR.js} +47 -10
- package/dist/chunk-6SHZHXXR.js.map +1 -0
- package/dist/{chunk-5F3PIERN.js → chunk-D2C6K6FO.js} +1420 -652
- package/dist/chunk-D2C6K6FO.js.map +1 -0
- package/dist/chunk-DCIU3SRK.js +505 -0
- package/dist/chunk-DCIU3SRK.js.map +1 -0
- package/dist/chunk-IO5Z75X4.js +167 -0
- package/dist/chunk-IO5Z75X4.js.map +1 -0
- package/dist/{chunk-VOVKONXA.js → chunk-UB6A6L77.js} +3 -3
- package/dist/{chunk-VOVKONXA.js.map → chunk-UB6A6L77.js.map} +1 -1
- package/dist/{chunk-BGGZ4CVF.js → chunk-Z3KNFTTS.js} +6 -6
- package/dist/chunk-Z3KNFTTS.js.map +1 -0
- package/dist/clipboard.d.ts +2 -2
- package/dist/clone.d.ts +1 -1
- package/dist/{geometry-D9BDMiQi.d.ts → geometry-DVeZ2i-c.d.ts} +1 -1
- package/dist/{grid-CaSK9bHV.d.ts → grid-XcFQVS0f.d.ts} +1 -1
- package/dist/{index-DOYRTfP0.d.ts → index-ChM3ZJ2v.d.ts} +278 -93
- package/dist/index.d.ts +442 -57
- package/dist/index.js +6 -6
- package/dist/insert.d.ts +2 -2
- package/dist/insert.js +5 -5
- package/dist/insert.js.map +1 -1
- package/dist/move.d.ts +3 -3
- package/dist/move.js +2 -2
- package/dist/{options-DMWeTELe.d.ts → options-wAvCnOZd.d.ts} +1 -1
- package/dist/paint-types-CnLIzqq1.d.ts +261 -0
- package/dist/patterns-builtin.d.ts +57 -2
- package/dist/patterns-builtin.js +1 -97
- package/dist/patterns-builtin.js.map +1 -1
- package/dist/{pointSnapToGrid-C3EruUwt.d.ts → pointSnapToGrid-BuDZWBrL.d.ts} +2 -2
- package/dist/renderer.d.ts +25 -8
- package/dist/renderer.js +6 -6
- package/dist/resize.d.ts +3 -3
- package/dist/resize.js +2 -2
- package/dist/routing.d.ts +7 -7
- package/dist/routing.js +1 -1
- package/dist/{types-Dcaa0tPq.d.ts → types-BhJJ2OCM.d.ts} +9 -1
- package/dist/{types-Cpb4hii1.d.ts → types-DUpI7Apc.d.ts} +3 -95
- package/dist/{viewToMat3-D4lrBigW.d.ts → viewToMat3-BvaWCN99.d.ts} +1 -1
- package/package.json +6 -6
- package/dist/chunk-5F3PIERN.js.map +0 -1
- package/dist/chunk-BGGZ4CVF.js.map +0 -1
- package/dist/chunk-CQNKCG34.js.map +0 -1
- package/dist/chunk-SYM6RAM4.js +0 -232
- package/dist/chunk-SYM6RAM4.js.map +0 -1
- package/dist/chunk-Y52N27PF.js +0 -39
- package/dist/chunk-Y52N27PF.js.map +0 -1
- package/dist/registerTexture-BzHTLhD9.d.ts +0 -25
- /package/dist/{types-B6MMiodD.d.ts → path-B6MMiodD.d.ts} +0 -0
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
import { N as NodeId,
|
|
2
|
-
import { M as ModifierState, A as ActionBehavior, c as ResizeAnchor, R as ResizePose, B as BoundsConstraint, P as PointSnapBehavior } from './types-
|
|
1
|
+
import { N as NodeId, R as RectPose, S as Scene } from './types-DUpI7Apc.js';
|
|
2
|
+
import { M as ModifierState, A as ActionBehavior, c as ResizeAnchor, R as ResizePose, B as BoundsConstraint, P as PointSnapBehavior } from './types-BhJJ2OCM.js';
|
|
3
3
|
import { V as View } from './view-DSQgxBJB.js';
|
|
4
4
|
import { CapabilityTag } from '@weasel-js/modes';
|
|
5
5
|
import * as React from 'react';
|
|
6
6
|
import { MutableRefObject, ReactNode, ReactElement } from 'react';
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
7
|
+
import { GestureSpec, IngestItem, InputEvent, ParsedModifiers, GestureName, ChannelRef, DescribeRouteOptions, GESTURE_DESCRIPTORS, GestureArgSpec, GestureDescriptor, ModRequirement, ModifierKey, ParsedRoute, PhaseAtom, RESERVED_ID_NAMES, RESERVED_ID_PREFIXES, ROUTE_FIELD_DEFINITIONS, ROUTE_TERMS, RouteDescriptionPart, RouteFieldName, RouteTermLabel, canonicalModifiers, collapseShiftPairs, describeRoute, describeRouteParts, formatPhaseAtom, formatRoute, getGestureDescriptor, isKnownGestureName, parseRoute } from '@weasel-js/gestures';
|
|
8
|
+
import { B as Bounds, P as PoseProjection } from './geometry-DVeZ2i-c.js';
|
|
9
|
+
import { F as FillStyle, S as Stroke } from './paint-types-CnLIzqq1.js';
|
|
10
|
+
import { D as DrawCommand } from './DrawCommand-DCmiNkBj.js';
|
|
9
11
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
10
|
-
import { P as Path } from './
|
|
12
|
+
import { P as Path } from './path-B6MMiodD.js';
|
|
11
13
|
import { Op, History } from '@weasel-js/history';
|
|
12
14
|
import { L as LayoutStrategy, I as InsertAdapter } from './types-B_-khFM0.js';
|
|
13
|
-
import { B as Bounds, P as PoseProjection } from './geometry-D9BDMiQi.js';
|
|
14
15
|
import { Mat3 } from '@weasel-js/geom';
|
|
15
16
|
import { D as DebugSink } from './types-BJ8_cyT7.js';
|
|
16
17
|
|
|
@@ -239,6 +240,31 @@ interface CommonAffordanceScratch {
|
|
|
239
240
|
y: number;
|
|
240
241
|
};
|
|
241
242
|
}
|
|
243
|
+
/**
|
|
244
|
+
* What a **registered layer's** `hitTest` returns. Extends `AffordanceBinding`
|
|
245
|
+
* so existing implementations keep typechecking; the added fields are how a
|
|
246
|
+
* consumer's own chrome says the things kit chrome says through
|
|
247
|
+
* `AffordanceRegion` — which cursor to show, and whether it owns the point
|
|
248
|
+
* outright.
|
|
249
|
+
*/
|
|
250
|
+
interface LayerHit<TScratch = unknown> extends AffordanceBinding<TScratch> {
|
|
251
|
+
/** CSS cursor while the pointer is over this hit. Reaches the hover-cursor
|
|
252
|
+
* pump as `AffordanceHit.cursor`, the same path kit chrome uses. */
|
|
253
|
+
cursor?: string;
|
|
254
|
+
/** `'exclusive'` bars every binding whose target doesn't consult the
|
|
255
|
+
* affordance. Omitted means `'shared'` — today's behavior. Same name and
|
|
256
|
+
* meaning as `AffordanceHit.strength`, which it becomes. */
|
|
257
|
+
strength?: 'exclusive' | 'shared';
|
|
258
|
+
/** Which gestures an exclusive claim bars. Omitted bars all of them. */
|
|
259
|
+
claimedKinds?: readonly ClaimableGesture[];
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Gesture kinds an affordance claim can bar, in the spec vocabulary bindings
|
|
263
|
+
* are written in. `'pointer'` is one token because `pointerDown` / `click` /
|
|
264
|
+
* `drag` are a single press protocol — at the event level the first two are
|
|
265
|
+
* the same `kind: 'pointerdown'`, told apart only by `stage`.
|
|
266
|
+
*/
|
|
267
|
+
type ClaimableGesture = 'pointer' | 'doubleClick' | 'contextMenu' | 'longPress' | 'wheel';
|
|
242
268
|
|
|
243
269
|
/**
|
|
244
270
|
* Canvas size in CSS pixels — passed to `draw` for layers that anchor to
|
|
@@ -317,7 +343,7 @@ interface RenderLayer<TData> {
|
|
|
317
343
|
/** Chrome-caps visibility predicate. When supplied, the layer must
|
|
318
344
|
* not return a hit from any chrome element whose id reports
|
|
319
345
|
* `false`. Absent → every element is hittable. */
|
|
320
|
-
isVisible?: (id: string) => boolean) =>
|
|
346
|
+
isVisible?: (id: string) => boolean) => LayerHit | null;
|
|
321
347
|
/**
|
|
322
348
|
* Called on every pointermove when no gesture is currently captured.
|
|
323
349
|
* Lets layers (e.g. HUD widgets) track hover state without participating
|
|
@@ -348,6 +374,31 @@ interface RenderLayer<TData> {
|
|
|
348
374
|
*/
|
|
349
375
|
declare function drawLayers<TData>(layers: RenderLayer<TData>[], data: TData, visibility: Record<string, boolean>, order: string[] | undefined, view: View | undefined, dims: Dims): DrawCommand[];
|
|
350
376
|
|
|
377
|
+
/**
|
|
378
|
+
* Facts about the device the canvas is running on.
|
|
379
|
+
*
|
|
380
|
+
* One object, recomputed when the underlying media queries change, read by
|
|
381
|
+
* two consumers: the chrome-caps rule layer (via `RuleCtx.device`) and the
|
|
382
|
+
* handle-sizing constants (via `targetScale`).
|
|
383
|
+
*
|
|
384
|
+
* Deliberately NOT a form-factor concept. There is no `isPhone` here and
|
|
385
|
+
* there should never be one: chrome layout is the consuming app's decision.
|
|
386
|
+
* The kit's job is to stop assuming a mouse.
|
|
387
|
+
*/
|
|
388
|
+
interface DeviceProfile {
|
|
389
|
+
/** `matchMedia('(pointer: coarse)')` — the primary pointer is imprecise. */
|
|
390
|
+
readonly coarsePointer: boolean;
|
|
391
|
+
/** `matchMedia('(hover: hover)')` — the primary pointer can hover. */
|
|
392
|
+
readonly canHover: boolean;
|
|
393
|
+
/** Live device pixel ratio. */
|
|
394
|
+
readonly dpr: number;
|
|
395
|
+
/** Multiplier for handle sizes and hit radii. Derived from
|
|
396
|
+
* `coarsePointer` unless explicitly overridden. */
|
|
397
|
+
readonly targetScale: number;
|
|
398
|
+
}
|
|
399
|
+
/** The detected half of a profile — everything except the derived scale. */
|
|
400
|
+
type DetectedDeviceFacts = Omit<DeviceProfile, 'targetScale'>;
|
|
401
|
+
|
|
351
402
|
/**
|
|
352
403
|
* Live state read by rule evaluation. Built once per frame on the consuming
|
|
353
404
|
* surface — chrome-caps, the affordance pipeline, the dispatcher's
|
|
@@ -389,6 +440,13 @@ interface RuleCtx {
|
|
|
389
440
|
* with nothing being edited should draw no anchors. Absent is treated
|
|
390
441
|
* as false. */
|
|
391
442
|
readonly editingAnchors?: boolean;
|
|
443
|
+
/** Device facts — pointer coarseness, hover capability, density.
|
|
444
|
+
*
|
|
445
|
+
* Absent (legacy ctx builders) is treated as
|
|
446
|
+
* {@link DEFAULT_DEVICE_PROFILE}: a fine pointer that can hover, at
|
|
447
|
+
* density 1. That is what the kit assumed before this field existed, so
|
|
448
|
+
* an absent profile is behavior-preserving by construction. */
|
|
449
|
+
readonly device?: DeviceProfile;
|
|
392
450
|
}
|
|
393
451
|
interface BuildRuleCtxArgs {
|
|
394
452
|
focused: boolean;
|
|
@@ -407,6 +465,8 @@ interface BuildRuleCtxArgs {
|
|
|
407
465
|
selectionResizable?: boolean;
|
|
408
466
|
/** Optional — omitted means "no path is being anchor-edited". */
|
|
409
467
|
editingAnchors?: boolean;
|
|
468
|
+
/** Optional — omitted means {@link DEFAULT_DEVICE_PROFILE}. */
|
|
469
|
+
device?: DeviceProfile;
|
|
410
470
|
}
|
|
411
471
|
declare function buildRuleCtx(args: BuildRuleCtxArgs): RuleCtx;
|
|
412
472
|
|
|
@@ -444,6 +504,12 @@ interface Selector {
|
|
|
444
504
|
* (resizable), so `{ resizable: true }` passes for legacy ctx builders
|
|
445
505
|
* that don't compute it. */
|
|
446
506
|
resizable?: boolean;
|
|
507
|
+
/** Matches `ctx.device.coarsePointer` — the primary pointer is imprecise
|
|
508
|
+
* (touch, most styluses). Absent device is treated as `false`. */
|
|
509
|
+
coarsePointer?: boolean;
|
|
510
|
+
/** Matches `ctx.device.canHover` — the primary pointer can hover. Absent
|
|
511
|
+
* device is treated as `true`. */
|
|
512
|
+
canHover?: boolean;
|
|
447
513
|
}
|
|
448
514
|
/**
|
|
449
515
|
* Composable visibility/eligibility rule. Trees of `all`/`any`/`not` nodes
|
|
@@ -583,6 +649,15 @@ interface Point2 {
|
|
|
583
649
|
interface AffordanceHit {
|
|
584
650
|
/** Discriminator string, e.g. `'handle:bottom-right'`. */
|
|
585
651
|
kind: string;
|
|
652
|
+
/** Id of whatever produced this hit — a kit affordance's `id`, or the
|
|
653
|
+
* registered layer's id. Read only by the dispatcher's dead-claim warning today. */
|
|
654
|
+
owner?: string;
|
|
655
|
+
/** `'exclusive'` means no binding may act on this point unless its target
|
|
656
|
+
* consults the affordance. `'shared'` (the default) competes on scope and
|
|
657
|
+
* specificity as bindings always have. */
|
|
658
|
+
strength?: 'exclusive' | 'shared';
|
|
659
|
+
/** Which gestures an exclusive claim bars. Omitted bars all of them. */
|
|
660
|
+
claimedKinds?: readonly ClaimableGesture[];
|
|
586
661
|
/** World-space fixed/pivot point. For resize: opposite corner. For rotate: pivot. */
|
|
587
662
|
fixedPoint?: {
|
|
588
663
|
x: number;
|
|
@@ -910,6 +985,114 @@ interface OngoingInvoker {
|
|
|
910
985
|
* the `Action` type. */
|
|
911
986
|
type Invoker = ImmediateInvoker | OngoingInvoker;
|
|
912
987
|
|
|
988
|
+
/**
|
|
989
|
+
* GestureBinding — connects a GestureSpec to an Action id (with per-binding
|
|
990
|
+
* options). Tools own arrays of these on their `bindings` field; ambient
|
|
991
|
+
* gesture-bindings are registered globally.
|
|
992
|
+
*
|
|
993
|
+
* See `docs/superpowers/specs/2026-05-16-registry-unification-design.md`.
|
|
994
|
+
*/
|
|
995
|
+
|
|
996
|
+
interface GestureBinding {
|
|
997
|
+
spec: GestureSpec;
|
|
998
|
+
actionId: string;
|
|
999
|
+
opts?: BindingOpts;
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
/**
|
|
1003
|
+
* Pose composition for hierarchical scene graphs.
|
|
1004
|
+
*
|
|
1005
|
+
* As of the nesting change, `getPose(id)` on adapters returns the
|
|
1006
|
+
* **local** pose — relative to the object's direct parent. Anything in the
|
|
1007
|
+
* kit that needs to draw, hit-test, snap, or otherwise reason about world
|
|
1008
|
+
* coordinates routes through `composeWorldPose`, which walks the parent
|
|
1009
|
+
* chain and folds local poses together via a consumer-supplied `compose`.
|
|
1010
|
+
*
|
|
1011
|
+
* Pose shape is generic, so the compose strategy is too. For the common
|
|
1012
|
+
* `{x, y, width, height}` axis-aligned rect, use `composeRectPose` —
|
|
1013
|
+
* translation only, child dimensions preserved. Custom pose shapes (paths,
|
|
1014
|
+
* matrix transforms) supply their own.
|
|
1015
|
+
*
|
|
1016
|
+
* The inverse — `rebaseLocalPose` — converts a world-space pose into a
|
|
1017
|
+
* local pose under a target parent. Used when reparenting so the visual
|
|
1018
|
+
* world position of a child is preserved across the parent change.
|
|
1019
|
+
*/
|
|
1020
|
+
/** Re-exported; the declaration lives in `core/scene/types.ts`, which names
|
|
1021
|
+
* it and may not import from features. */
|
|
1022
|
+
|
|
1023
|
+
/** Minimal adapter needed by `composeWorldPose` and friends — pose lookup plus parent walk. */
|
|
1024
|
+
interface PoseAdapter<TPose> {
|
|
1025
|
+
getPose(id: string): TPose;
|
|
1026
|
+
getParent(id: string): string | null;
|
|
1027
|
+
}
|
|
1028
|
+
/** Consumer's pose-composition strategy for hierarchical scenes. `compose`
|
|
1029
|
+
* folds a child's pose (in parent's frame) up to the next frame; `decompose`
|
|
1030
|
+
* is its inverse. Default is IDENTITY — an absolute-pose scene where every
|
|
1031
|
+
* node already stores world coords (parent is grouping-only, no transform). */
|
|
1032
|
+
interface PoseComposition<TPose> {
|
|
1033
|
+
compose: (parent: TPose, child: TPose) => TPose;
|
|
1034
|
+
decompose: (parent: TPose, world: TPose) => TPose;
|
|
1035
|
+
}
|
|
1036
|
+
/** Default pose-composition strategy: IDENTITY. Both `compose` and
|
|
1037
|
+
* `decompose` return the child/world pose unchanged, modeling an
|
|
1038
|
+
* absolute-pose scene where every node stores world coords and parents are
|
|
1039
|
+
* grouping-only (no transform). With this strategy `composeWorldPose`
|
|
1040
|
+
* returns a node's own raw pose and `rebaseLocalPose` is a no-op. */
|
|
1041
|
+
declare const IDENTITY_POSE_COMPOSITION: PoseComposition<unknown>;
|
|
1042
|
+
/**
|
|
1043
|
+
* Walk `id`'s parent chain (root first to id last) and fold local poses into
|
|
1044
|
+
* a world pose via `compose`. Returns the world pose for `id`. Cycle-safe:
|
|
1045
|
+
* a visited-set guard breaks if the chain ever loops back to itself.
|
|
1046
|
+
*
|
|
1047
|
+
* `compose(parent, child)` interprets `child` as expressed *in `parent`'s
|
|
1048
|
+
* local frame* and returns the equivalent pose in the next frame up. For a
|
|
1049
|
+
* standard translation-only rect: `world = { x: p.x + c.x, y: p.y + c.y,
|
|
1050
|
+
* width: c.width, height: c.height }`.
|
|
1051
|
+
*/
|
|
1052
|
+
declare function composeWorldPose<TPose>(adapter: PoseAdapter<TPose>, id: string, compose: (parent: TPose, child: TPose) => TPose): TPose;
|
|
1053
|
+
/**
|
|
1054
|
+
* Default `compose` for axis-aligned rectangles. Adds translation; preserves
|
|
1055
|
+
* child width/height. Treat as the canonical compose for any
|
|
1056
|
+
* `{x, y, width, height}` pose under a translation-only hierarchy.
|
|
1057
|
+
*
|
|
1058
|
+
* Generic over the concrete pose type so callers with a wider pose
|
|
1059
|
+
* (e.g. `RectPose & { rotation }`) can pass it through; the extra fields
|
|
1060
|
+
* are taken from the child unchanged.
|
|
1061
|
+
*/
|
|
1062
|
+
declare function composeRectPose<TPose extends RectPose>(parent: TPose, child: TPose): TPose;
|
|
1063
|
+
/**
|
|
1064
|
+
* Translate a `RectPose`-shaped pose by `(dx, dy)`. Suitable as the default
|
|
1065
|
+
* `translatePose` for `useMove` when poses carry top-level `x`/`y`. Other
|
|
1066
|
+
* fields (width/height, plus any extra props on `TPose`) are preserved.
|
|
1067
|
+
*/
|
|
1068
|
+
declare function translateRectPose<TPose extends RectPose>(pose: TPose, dx: number, dy: number): TPose;
|
|
1069
|
+
/**
|
|
1070
|
+
* Convert `worldPose` into a local pose expressed under `newParentId`'s
|
|
1071
|
+
* frame. Used when reparenting so the child's visual world position is
|
|
1072
|
+
* preserved despite the change of frame. Inverse of one `compose` step.
|
|
1073
|
+
*
|
|
1074
|
+
* `decompose(parent, world)` returns the local pose `child` such that
|
|
1075
|
+
* `compose(parent, child) === world`. For axis-aligned rects:
|
|
1076
|
+
* `child = { ...world, x: world.x - parent.x, y: world.y - parent.y }`.
|
|
1077
|
+
*
|
|
1078
|
+
* Pass `newParentId === null` for the root frame; the function returns
|
|
1079
|
+
* `worldPose` unchanged.
|
|
1080
|
+
*/
|
|
1081
|
+
declare function rebaseLocalPose<TPose>(adapter: PoseAdapter<TPose>, worldPose: TPose, newParentId: string | null, compose: (parent: TPose, child: TPose) => TPose, decompose: (parent: TPose, world: TPose) => TPose): TPose;
|
|
1082
|
+
/** Inverse of `composeRectPose` — subtracts parent translation. */
|
|
1083
|
+
declare function decomposeRectPose<TPose extends RectPose>(parent: TPose, world: TPose): TPose;
|
|
1084
|
+
/**
|
|
1085
|
+
* Build a `(id) => world pose | null` callback over a `PoseAdapter`.
|
|
1086
|
+
* Convenience for RenderLayers that take a `getPose` callback (selection
|
|
1087
|
+
* overlays, debug layers, etc.) so consumers don't hand-write a
|
|
1088
|
+
* `composeWorldPose` call per layer.
|
|
1089
|
+
*
|
|
1090
|
+
* Returns `null` when `adapter.getPose` or `adapter.getParent` throws — the
|
|
1091
|
+
* common case is an id removed mid-render between selection state and the
|
|
1092
|
+
* next paint. Layers should treat `null` as "skip this id."
|
|
1093
|
+
*/
|
|
1094
|
+
declare function worldPoseLookup<TPose>(adapter: PoseAdapter<TPose>, compose: (parent: TPose, child: TPose) => TPose): (id: string) => TPose | null;
|
|
1095
|
+
|
|
913
1096
|
/** Boolean op identifiers — five Pathfinder primaries plus Crop. */
|
|
914
1097
|
type BooleanOp = 'union' | 'intersect' | 'subtract' | 'exclude' | 'divide' | 'crop';
|
|
915
1098
|
/**
|
|
@@ -1320,6 +1503,35 @@ declare const sliceAction: Action & {
|
|
|
1320
1503
|
requires: string[];
|
|
1321
1504
|
};
|
|
1322
1505
|
|
|
1506
|
+
/**
|
|
1507
|
+
* Clipboard dep — the imperative surface `useClipboardOps` returns.
|
|
1508
|
+
*
|
|
1509
|
+
* Consumers publish their live clipboard through `useDepSource('clipboard',
|
|
1510
|
+
* …)` from inside the `<DepRegistryProvider>` (i.e. under `<SceneCanvas>`).
|
|
1511
|
+
* The kit deliberately does not build one for them: `useClipboardOps` needs
|
|
1512
|
+
* an adapter and a selection reader that only the consumer can supply.
|
|
1513
|
+
*/
|
|
1514
|
+
interface ClipboardDep {
|
|
1515
|
+
copy(): void;
|
|
1516
|
+
paste(): void;
|
|
1517
|
+
isEmpty(): boolean;
|
|
1518
|
+
}
|
|
1519
|
+
/**
|
|
1520
|
+
* @experimental
|
|
1521
|
+
* Static descriptor for the `clipboard.copy` Action (Cmd/Ctrl+C).
|
|
1522
|
+
*/
|
|
1523
|
+
declare const clipboardCopyAction: Action & {
|
|
1524
|
+
requires: string[];
|
|
1525
|
+
};
|
|
1526
|
+
/**
|
|
1527
|
+
* @experimental
|
|
1528
|
+
* Static descriptor for the `clipboard.cut` Action (Cmd/Ctrl+X) — copy, then
|
|
1529
|
+
* the same batched delete `deleteAction` performs, as one undo entry.
|
|
1530
|
+
*/
|
|
1531
|
+
declare const clipboardCutAction: Action & {
|
|
1532
|
+
requires: string[];
|
|
1533
|
+
};
|
|
1534
|
+
|
|
1323
1535
|
/** Optional consumer seam: given a node and the affine `m` that a pose-transform
|
|
1324
1536
|
* action applied to the node's POSE, return updated `data` with the node's
|
|
1325
1537
|
* data-held geometry transformed by `m`, or `null` if this node has no
|
|
@@ -1832,6 +2044,15 @@ interface DepSchema {
|
|
|
1832
2044
|
* Optional: when absent, `sliceAction` is a no-op.
|
|
1833
2045
|
*/
|
|
1834
2046
|
slice?: SliceDep;
|
|
2047
|
+
/**
|
|
2048
|
+
* Clipboard dep — the imperative surface `useClipboardOps` returns.
|
|
2049
|
+
*
|
|
2050
|
+
* Published by the consumer (`useDepSource('clipboard', …)` from under
|
|
2051
|
+
* `<SceneCanvas>`), because `useClipboardOps` needs an adapter and a
|
|
2052
|
+
* selection reader only the consumer has. Feeds `clipboard.copy` /
|
|
2053
|
+
* `clipboard.cut`; both no-op when the dep is absent.
|
|
2054
|
+
*/
|
|
2055
|
+
clipboard?: ClipboardDep;
|
|
1835
2056
|
/**
|
|
1836
2057
|
* Optional consumer commit hook. When present, `moveAction` (and other
|
|
1837
2058
|
* default actions) submit their committed ops through it instead of
|
|
@@ -1901,17 +2122,35 @@ declare function useOptionalDepRegistry(): DepRegistry | null;
|
|
|
1901
2122
|
declare function useDepSource<K extends DepName>(name: K, source: () => DepSchema[K]): void;
|
|
1902
2123
|
|
|
1903
2124
|
/**
|
|
1904
|
-
*
|
|
1905
|
-
*
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
2125
|
+
* When an entry's bindings are live. A set, not one value: the hand tool is
|
|
2126
|
+
* palette-selectable AND engaged by holding space, and both hold at once.
|
|
2127
|
+
*/
|
|
2128
|
+
interface Eligibility {
|
|
2129
|
+
/** Selectable as the focused entry — exclusive, one at a time. */
|
|
2130
|
+
focus?: boolean;
|
|
2131
|
+
/** Also live while this key is held. */
|
|
2132
|
+
offhand?: HotkeyTrigger;
|
|
2133
|
+
/** Live regardless of what is focused. */
|
|
2134
|
+
always?: boolean;
|
|
2135
|
+
/** Live only for input this entry's own affordances produced. */
|
|
2136
|
+
claimed?: boolean;
|
|
2137
|
+
/** Modality filter, applied wherever it would otherwise be live. */
|
|
2138
|
+
capabilities?: CapabilityTag[];
|
|
2139
|
+
}
|
|
2140
|
+
/**
|
|
2141
|
+
* A registry entry: what it contributes, and when it is eligible. Every role
|
|
2142
|
+
* is optional and independent — an entry that only routes input declares only
|
|
2143
|
+
* `bindings` and `actions`.
|
|
1909
2144
|
*/
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
2145
|
+
interface Contribution {
|
|
2146
|
+
id: string;
|
|
2147
|
+
eligibility: Eligibility;
|
|
2148
|
+
bindings?: GestureBinding[];
|
|
2149
|
+
actions?: Action[];
|
|
2150
|
+
overlay?: RenderLayer<unknown>;
|
|
2151
|
+
presentation?: ToolPresentation;
|
|
2152
|
+
/** Reflection escape hatch — the authored form, when there was one. */
|
|
2153
|
+
def?: unknown;
|
|
1915
2154
|
}
|
|
1916
2155
|
|
|
1917
2156
|
/** Modifier-key snapshot at event dispatch time. `space` is included
|
|
@@ -1975,8 +2214,8 @@ type ToolBounds = Bounds;
|
|
|
1975
2214
|
* tool — consumers that render a palette (`<ToolPalette>`) read these
|
|
1976
2215
|
* fields to display the tool; consumers that don't can ignore them.
|
|
1977
2216
|
*
|
|
1978
|
-
* Note: cursor is NOT here.
|
|
1979
|
-
* already plumbed through `<Canvas>` to `style.cursor` on the host. */
|
|
2217
|
+
* Note: cursor is NOT here. `Tool.cursor` (inherited from `Contribution`)
|
|
2218
|
+
* is already plumbed through `<Canvas>` to `style.cursor` on the host. */
|
|
1980
2219
|
interface ToolPresentation<TScratch = unknown> {
|
|
1981
2220
|
/** Human-readable label, distinct from the `id`. Falls back to `id`. */
|
|
1982
2221
|
label?: string;
|
|
@@ -1991,34 +2230,13 @@ interface ToolPresentation<TScratch = unknown> {
|
|
|
1991
2230
|
* derives one from `Tool.keybinding` via its own formatter. */
|
|
1992
2231
|
shortcut?: string;
|
|
1993
2232
|
}
|
|
1994
|
-
/**
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
* strings — apps can define their own. Untagged tools are treated as
|
|
2002
|
-
* ineligible by all modes except those whose `allows` list includes
|
|
2003
|
-
* every implicit-or-declared tag (i.e. `normal` in the default preset).
|
|
2004
|
-
*/
|
|
2005
|
-
capabilities?: CapabilityTag[];
|
|
2006
|
-
/**
|
|
2007
|
-
* Actions this tool owns and needs registered while it is in the tools
|
|
2008
|
-
* registry — e.g. polygon's `polygon.adjustSides`, which its own bindings
|
|
2009
|
-
* reference by id.
|
|
2010
|
-
*
|
|
2011
|
-
* Declared here rather than registered by the hook with `useAction`,
|
|
2012
|
-
* because tool hooks run wherever the consumer calls them — for
|
|
2013
|
-
* `<SceneCanvas>` that is ABOVE `<ActionsProviderIfRoot>`, where
|
|
2014
|
-
* `useActionsRegistry()` returns null and `useAction` silently no-ops. The
|
|
2015
|
-
* result was a binding pointing at an action id nothing had registered, so
|
|
2016
|
-
* the gesture fell through to whatever matched next (polygon's
|
|
2017
|
-
* wheel/arrow-key side adjustment did nothing and `nudge.*` moved the
|
|
2018
|
-
* selection instead). `<ToolActionsMounter>` registers these from inside
|
|
2019
|
-
* the provider.
|
|
2020
|
-
*/
|
|
2021
|
-
actions?: Action[];
|
|
2233
|
+
/**
|
|
2234
|
+
* The focus-declaring case of a `Contribution`: a mode the user switches
|
|
2235
|
+
* into, plus the hooks that only make sense for one (`initScratch`,
|
|
2236
|
+
* activate/deactivate, live preview, `cursor`). Everything else — bindings,
|
|
2237
|
+
* actions, overlay, presentation — is inherited.
|
|
2238
|
+
*/
|
|
2239
|
+
interface Tool<TScratch = unknown> extends Contribution {
|
|
2022
2240
|
/** Optional caller-supplied key. Most built-in tools have their activation
|
|
2023
2241
|
* key declared in `BUILTIN_SELECT_KEYS` in `useKeybindings.ts`; this field
|
|
2024
2242
|
* is for tools that want their activation key to be configurable by the
|
|
@@ -2028,11 +2246,9 @@ interface Tool<TScratch = unknown> {
|
|
|
2028
2246
|
* the invoker knows which tool to switch to). */
|
|
2029
2247
|
keybinding?: ToolKeybinding;
|
|
2030
2248
|
initScratch?: () => TScratch;
|
|
2249
|
+
cursor?: string | ((ctx: ToolCtx<TScratch>) => string);
|
|
2031
2250
|
onActivate?: (ctx: ToolCtx<TScratch>) => void;
|
|
2032
2251
|
onDeactivate?: (ctx: ToolCtx<TScratch>) => void;
|
|
2033
|
-
cursor?: string | ((ctx: ToolCtx<TScratch>) => string);
|
|
2034
|
-
/** Presentation metadata for tool palettes. See `ToolPresentation`. */
|
|
2035
|
-
presentation?: ToolPresentation<TScratch>;
|
|
2036
2252
|
/** Returns the in-flight preview pose for `id` if this tool is mid-gesture
|
|
2037
2253
|
* on it; otherwise `null`. Lets `Canvas.helpersRef.getEffectivePose`
|
|
2038
2254
|
* reflect live gesture state without reaching into hook internals. The
|
|
@@ -2050,26 +2266,6 @@ interface Tool<TScratch = unknown> {
|
|
|
2050
2266
|
* consults this alongside `previewPose` to avoid double-rendering. Returns
|
|
2051
2267
|
* `null` when no gesture is in flight. */
|
|
2052
2268
|
previewIds?: () => Iterable<string> | null;
|
|
2053
|
-
/** Optional overlay layer rendered on top of the scene/chrome whenever
|
|
2054
|
-
* this tool is in any active slot (active, hotkey, or ambient).
|
|
2055
|
-
* The layer's `draw` function reads from this tool's scratch via React
|
|
2056
|
-
* closure (re-evaluated each render). Return early from `draw` to render
|
|
2057
|
-
* nothing — typically gated on a scratch field like
|
|
2058
|
-
* `if (!scratch.overlay) return`. */
|
|
2059
|
-
overlay?: RenderLayer<unknown>;
|
|
2060
|
-
/** Declarative gesture bindings — the tool's entire input surface. The
|
|
2061
|
-
* gesture dispatcher consults these at active scope while this tool is
|
|
2062
|
-
* active, and at hotkey scope while it is held. See
|
|
2063
|
-
* `docs/superpowers/specs/2026-05-16-registry-unification-design.md`. */
|
|
2064
|
-
bindings?: GestureBinding[];
|
|
2065
|
-
/** Reflection escape hatch: when this `Tool` was produced by `defineTool`,
|
|
2066
|
-
* the source `ToolDef` is attached here so introspection consumers
|
|
2067
|
-
* (`buildRouteRegistry`, `findConflicts`, the toolkit-builder UI, the
|
|
2068
|
-
* reflection demo) can read the authored form — `hookName` in particular,
|
|
2069
|
-
* which the runtime `Tool` doesn't carry. Tools constructed without
|
|
2070
|
-
* `defineTool` may leave this undefined. Typed as `unknown` to keep this
|
|
2071
|
-
* file from importing the routing types — consumers cast at the use site. */
|
|
2072
|
-
def?: unknown;
|
|
2073
2269
|
}
|
|
2074
2270
|
/** Internal — which slot a tool occupies in the dispatch order. */
|
|
2075
2271
|
type ToolSlot = 'hotkey' | 'active' | 'ambient';
|
|
@@ -2162,17 +2358,6 @@ interface DispatcherContext {
|
|
|
2162
2358
|
activeToolId: string;
|
|
2163
2359
|
/** Held-hotkey stack, top of stack last. */
|
|
2164
2360
|
hotkeyStack: readonly string[];
|
|
2165
|
-
/**
|
|
2166
|
-
* Ids of always-on tools. Their bindings are assembled at AMBIENT scope, so
|
|
2167
|
-
* they lose to the active tool on a tie — which is what "always listening,
|
|
2168
|
-
* never in the way" needs. Chrome that floats over the scene lives here:
|
|
2169
|
-
* `@weasel-js/hud`'s tool is the worked example.
|
|
2170
|
-
*
|
|
2171
|
-
* Without this an ambient tool's `bindings` were assembled nowhere at all:
|
|
2172
|
-
* the walk covered hotkey and active tools plus actions' `defaultBinding`,
|
|
2173
|
-
* and an ambient tool is in neither set.
|
|
2174
|
-
*/
|
|
2175
|
-
ambientToolIds?: readonly string[];
|
|
2176
2361
|
/** Lookup for tool definitions. */
|
|
2177
2362
|
toolsById: ReadonlyMap<string, Tool>;
|
|
2178
2363
|
/** Platform flag for `mod` shorthand resolution. */
|
|
@@ -2700,13 +2885,10 @@ interface ToolDef<TScratch = void> {
|
|
|
2700
2885
|
* to the consolidated `tool.activate` action (with `opts.params.toolId`
|
|
2701
2886
|
* set so the invoker knows which tool to switch to). */
|
|
2702
2887
|
keybinding?: ToolKeybinding;
|
|
2703
|
-
/**
|
|
2704
|
-
*
|
|
2705
|
-
*
|
|
2706
|
-
*
|
|
2707
|
-
* declare held keys in `BUILTIN_OFFHAND_ACTIONS`; configurable-hotkey
|
|
2708
|
-
* tools rely on the host to wire the binding. Setting this field does NOT
|
|
2709
|
-
* automatically engage the held-key behavior. */
|
|
2888
|
+
/** Held-key trigger: this tool engages while the key is down and
|
|
2889
|
+
* disengages on release. Carried onto `Tool.eligibility.offhand`, which
|
|
2890
|
+
* assembly reads to register the consolidated `tool.offhand` action — the
|
|
2891
|
+
* declaration is the wiring, with nothing for the host to do. */
|
|
2710
2892
|
hotkey?: HotkeyTrigger;
|
|
2711
2893
|
onActivate?: (ctx: ToolCtx<TScratch>) => void;
|
|
2712
2894
|
onDeactivate?: (ctx: ToolCtx<TScratch>) => void;
|
|
@@ -2884,6 +3066,9 @@ interface ToolScopes {
|
|
|
2884
3066
|
registry: readonly Tool<unknown>[] | Readonly<Record<string, Tool<unknown>>>;
|
|
2885
3067
|
/** Always-on tools. Every one of these is live at once. */
|
|
2886
3068
|
ambient?: readonly Tool<unknown>[];
|
|
3069
|
+
/** Registered actions. Their `defaultBinding`s assemble at ambient scope
|
|
3070
|
+
* (hotkey scope when `Action.scope` says so), alongside the tools above. */
|
|
3071
|
+
actions?: readonly Action[];
|
|
2887
3072
|
}
|
|
2888
3073
|
/**
|
|
2889
3074
|
* Detect the same-tuple overlaps that are *reachable* — the ones where the
|
|
@@ -2903,10 +3088,10 @@ interface ToolScopes {
|
|
|
2903
3088
|
* ordered only by registration;
|
|
2904
3089
|
* - two **hotkey-capable** tools, which can stack.
|
|
2905
3090
|
*
|
|
2906
|
-
*
|
|
2907
|
-
*
|
|
2908
|
-
*
|
|
2909
|
-
*
|
|
3091
|
+
* Registered actions join the same two buckets: their `defaultBinding`s
|
|
3092
|
+
* assemble at ambient scope (hotkey scope when `Action.scope` says so), so an
|
|
3093
|
+
* ambient tool and an action claiming one tuple really do fall back on
|
|
3094
|
+
* declaration order.
|
|
2910
3095
|
*/
|
|
2911
3096
|
declare function findScopedConflicts(scopes: ToolScopes): Conflict[];
|
|
2912
3097
|
/**
|
|
@@ -2983,4 +3168,4 @@ declare namespace index {
|
|
|
2983
3168
|
export { index_ChannelRef as ChannelRef, type index_Conflict as Conflict, index_DescribeRouteOptions as DescribeRouteOptions, index_GESTURE_DESCRIPTORS as GESTURE_DESCRIPTORS, index_GestureArgSpec as GestureArgSpec, index_GestureDescriptor as GestureDescriptor, index_GestureName as GestureName, index_ModRequirement as ModRequirement, index_ModifierKey as ModifierKey, index_PREDICATE_TARGET as PREDICATE_TARGET, index_ParsedModifiers as ParsedModifiers, index_ParsedRoute as ParsedRoute, index_PhaseAtom as PhaseAtom, index_RESERVED_ID_NAMES as RESERVED_ID_NAMES, index_RESERVED_ID_PREFIXES as RESERVED_ID_PREFIXES, index_ROUTE_FIELD_DEFINITIONS as ROUTE_FIELD_DEFINITIONS, index_ROUTE_TERMS as ROUTE_TERMS, type index_RegistryEntry as RegistryEntry, index_RouteDescriptionPart as RouteDescriptionPart, index_RouteFieldName as RouteFieldName, index_RouteTermLabel as RouteTermLabel, type index_ToolDef as ToolDef, type index_ToolKeybinding as ToolKeybinding, type index_ToolScopes as ToolScopes, type index_ViewportToolDef as ViewportToolDef, index_buildRouteRegistry as buildRouteRegistry, index_canonicalModifiers as canonicalModifiers, index_collapseShiftPairs as collapseShiftPairs, index_defineTool as defineTool, index_defineViewportTool as defineViewportTool, index_describeRoute as describeRoute, index_describeRouteParts as describeRouteParts, index_findConflicts as findConflicts, index_findScopedConflicts as findScopedConflicts, index_formatConflict as formatConflict, index_formatPhaseAtom as formatPhaseAtom, index_formatRoute as formatRoute, index_getGestureDescriptor as getGestureDescriptor, index_isKnownGestureName as isKnownGestureName, index_parseRoute as parseRoute, index_reportRouteConflicts as reportRouteConflicts };
|
|
2984
3169
|
}
|
|
2985
3170
|
|
|
2986
|
-
export {
|
|
3171
|
+
export { type BoundGesture as $, type Action as A, type BooleansAdapter as B, type Condition as C, type Dims as D, type Eligibility as E, type ActionDeps as F, type GeometryProjection as G, type HotkeyTrigger as H, type InsertExtras as I, ActionDisabledReason as J, type ActionEnabledResult as K, type LayerHit as L, type ActionEntry as M, ActionsProvider as N, ActiveToolContextProvider as O, ActiveToolContextProviderIfRoot as P, type ActiveToolContextProviderProps as Q, type RenderLayer as R, type SliceDep as S, type Tool as T, type UseSelectionOptions as U, type VisibilityRules as V, type ActiveToolContextValue as W, type AreaSelectDep as X, type BindingOpts as Y, type BooleanOp as Z, type BooleanOpResult as _, type DeviceProfile as a, index as a$, type BuildRuleCtxArgs as a0, type ClaimableGesture as a1, type ClipboardDep as a2, type ClipboardIngestCtx as a3, type CustomPaintContext as a4, type DepName as a5, type DepRegistry as a6, DepRegistryProvider as a7, type DispatcherContext as a8, type DragSample as a9, type ResolvedCandidate as aA, type SelectionExtendKey as aB, type SelectionMode as aC, type Selector as aD, type SnapDep as aE, type SvgUnpacker as aF, type TextEditDep as aG, type ToolModifiers as aH, type ToolPresentation as aI, type ToolSlot as aJ, type UiOngoingControl as aK, type ViewApi as aL, applyBooleanOp as aM, buildRuleCtx as aN, clipboardCopyAction as aO, clipboardCutAction as aP, composeRectPose as aQ, composeWorldPose as aR, createDispatcher as aS, decomposeRectPose as aT, describeRule as aU, drawLayers as aV, enterTextEditAction as aW, evaluate as aX, evaluateEnabled as aY, rebaseLocalPose as aZ, registerContentHandler as a_, type EditAnchorsDep as aa, type GestureBinding as ab, IDENTITY_POSE_COMPOSITION as ac, type ImmediateInvoker as ad, type IngestCtx as ae, type IngestionDep as af, type InsertDep as ag, type InvocationCtx as ah, type Invoker as ai, type LassoSelectDep as aj, type LayoutDep as ak, type MatchResult as al, NEVER as am, type NodeAtPointDep as an, type OngoingHandle as ao, type OngoingInvoker as ap, type OngoingOverlay as aq, type Point2 as ar, PointerContextProvider as as, type PointerContextValue as at, type PointerWorldPos as au, type PoseAdapter as av, type PoseComposition as aw, type ResizePolicy as ax, type ResolveAllOptions as ay, type ResolveOnlyResult as az, type DetectedDeviceFacts as b, sliceAction as b0, specificity as b1, translateRectPose as b2, useAction as b3, useActionsRegistry as b4, useActiveToolContext as b5, useDepRegistry as b6, useDepSource as b7, useOptionalActiveToolContext as b8, useOptionalDepRegistry as b9, usePointerContext as ba, useSelection as bb, worldPoseLookup as bc, type Conflict as bd, PREDICATE_TARGET as be, type RegistryEntry as bf, type ToolDef as bg, type ToolScopes as bh, type ViewportToolDef as bi, buildRouteRegistry as bj, defineTool as bk, defineViewportTool as bl, findConflicts as bm, findScopedConflicts as bn, formatConflict as bo, reportRouteConflicts as bp, type Rule as c, type RuleCtx as d, type ChromeCtx as e, type ChromeId as f, type DepSchema as g, type ActionsRegistry as h, type AffordanceHit as i, type Dispatcher as j, type AnyTool as k, type ToolCtx as l, type ToolKeybinding as m, type ChromeState as n, type SelectionApi as o, type ContentHandlerEntry as p, type SvgIngestOptions as q, type ActionsProp as r, type Affordance as s, type AffordanceBinding as t, type AffordanceRegion as u, type CommonAffordanceScratch as v, type BindingScope as w, type Contribution as x, type ScopedBinding as y, ALWAYS as z };
|