@weasel-js/core 1.0.1 → 1.0.3

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.
Files changed (53) hide show
  1. package/CHANGELOG.md +330 -0
  2. package/dist/{DrawCommand-DCmiNkBj.d.ts → DrawCommand-BbPrSTra.d.ts} +24 -0
  3. package/dist/{chunk-Z3KNFTTS.js → chunk-3JYFAQIB.js} +3 -3
  4. package/dist/chunk-3JYFAQIB.js.map +1 -0
  5. package/dist/{chunk-UB6A6L77.js → chunk-3KGMJMOS.js} +3 -3
  6. package/dist/{chunk-UB6A6L77.js.map → chunk-3KGMJMOS.js.map} +1 -1
  7. package/dist/{chunk-IO5Z75X4.js → chunk-HGF5X6MZ.js} +2 -2
  8. package/dist/chunk-HGF5X6MZ.js.map +1 -0
  9. package/dist/{chunk-775XXAHR.js → chunk-JOSUVS6C.js} +2 -2
  10. package/dist/{chunk-775XXAHR.js.map → chunk-JOSUVS6C.js.map} +1 -1
  11. package/dist/{chunk-FVNWK7U3.js → chunk-SMCZRSYB.js} +1677 -1371
  12. package/dist/chunk-SMCZRSYB.js.map +1 -0
  13. package/dist/{chunk-DCIU3SRK.js → chunk-TR3HZN34.js} +79 -151
  14. package/dist/chunk-TR3HZN34.js.map +1 -0
  15. package/dist/{chunk-6SHZHXXR.js → chunk-U45SODC2.js} +2 -2
  16. package/dist/{chunk-6SHZHXXR.js.map → chunk-U45SODC2.js.map} +1 -1
  17. package/dist/clipboard.d.ts +5 -2
  18. package/dist/clipboard.js +1 -2
  19. package/dist/clone.d.ts +2 -2
  20. package/dist/clone.js +0 -1
  21. package/dist/{geometry-DVeZ2i-c.d.ts → geometry-5X6TrAkX.d.ts} +1 -1
  22. package/dist/{grid-XcFQVS0f.d.ts → grid-sfilv5HP.d.ts} +7 -2
  23. package/dist/index.d.ts +695 -49
  24. package/dist/index.js +7 -8
  25. package/dist/insert.d.ts +6 -3
  26. package/dist/insert.js +1 -2
  27. package/dist/insert.js.map +1 -1
  28. package/dist/move.d.ts +26 -5
  29. package/dist/move.js +2 -3
  30. package/dist/move.js.map +1 -1
  31. package/dist/{options-wAvCnOZd.d.ts → options-CbsIgQci.d.ts} +3 -1
  32. package/dist/patterns-builtin.d.ts +8 -0
  33. package/dist/patterns-builtin.js +1 -2
  34. package/dist/{pointSnapToGrid-BuDZWBrL.d.ts → pointSnapToGrid-C3wowsQy.d.ts} +9 -3
  35. package/dist/{index-DPI8DV0A.d.ts → registry-CxnkXbG8.d.ts} +225 -350
  36. package/dist/renderer.d.ts +36 -4
  37. package/dist/renderer.js +7 -8
  38. package/dist/resize.d.ts +12 -5
  39. package/dist/resize.js +2 -3
  40. package/dist/routing.d.ts +106 -7
  41. package/dist/routing.js +1 -2
  42. package/dist/{types-BJ8_cyT7.d.ts → types-BHK2dkMu.d.ts} +43 -1
  43. package/dist/{types-BhJJ2OCM.d.ts → types-ByZxoD6P.d.ts} +1 -1
  44. package/dist/{types-B_-khFM0.d.ts → types-DpQ0cWYC.d.ts} +32 -0
  45. package/dist/{types-Kh_osAq9.d.ts → types-vqxpCFVp.d.ts} +31 -0
  46. package/dist/{viewToMat3-BvaWCN99.d.ts → viewToMat3-CQW_YqDw.d.ts} +1 -1
  47. package/package.json +6 -6
  48. package/dist/chunk-DCIU3SRK.js.map +0 -1
  49. package/dist/chunk-FVNWK7U3.js.map +0 -1
  50. package/dist/chunk-IO5Z75X4.js.map +0 -1
  51. package/dist/chunk-PZ5AY32C.js +0 -9
  52. package/dist/chunk-PZ5AY32C.js.map +0 -1
  53. package/dist/chunk-Z3KNFTTS.js.map +0 -1
@@ -1,9 +1,9 @@
1
- import { I as ImageMinification, G as GLImageCache } from './viewToMat3-BvaWCN99.js';
2
- export { V as ViewLike, v as viewToMat3 } from './viewToMat3-BvaWCN99.js';
1
+ import { I as ImageMinification, G as GLImageCache } from './viewToMat3-CQW_YqDw.js';
2
+ export { V as ViewLike, v as viewToMat3 } from './viewToMat3-CQW_YqDw.js';
3
3
  import { G as GradStop, S as Stroke } from './paint-types-CnLIzqq1.js';
4
4
  export { a as TextureHandle, r as registerTexture } from './paint-types-CnLIzqq1.js';
5
- import { M as Mat3, S as ShaderProgramHandle, D as DrawCommand } from './DrawCommand-DCmiNkBj.js';
6
- export { G as GroupDrawCommand, I as ImageDrawCommand, P as PathDrawCommand, a as ShaderDrawCommand, b as ShaderUniform, c as SolidPaint, T as TextDrawCommand, m as mat3, r as registerProgram } from './DrawCommand-DCmiNkBj.js';
5
+ import { M as Mat3, S as ShaderProgramHandle, D as DrawCommand } from './DrawCommand-BbPrSTra.js';
6
+ export { G as GroupDrawCommand, I as ImageDrawCommand, P as PathDrawCommand, a as ShaderDrawCommand, b as ShaderUniform, c as SolidPaint, T as TextDrawCommand, m as mat3, r as registerProgram } from './DrawCommand-BbPrSTra.js';
7
7
  import { P as Path } from './path-B6MMiodD.js';
8
8
  export { canQueryLocalFonts, enableLocalFontOutlines, hasFontOutlines, isCanvasFont, listFontOutlines, outlineStatus, registerCanvasFont, registerFont, registerFontOutlines, subscribeGlyphReady, unregisterCanvasFont, unregisterFontOutlines } from '@weasel-js/font';
9
9
 
@@ -16,6 +16,8 @@ export { canQueryLocalFonts, enableLocalFontOutlines, hasFontOutlines, isCanvasF
16
16
  * via the recorder Proxy without further special-casing.
17
17
  */
18
18
  type Stage = 'vertex' | 'fragment' | 'link';
19
+ /** Thrown when a shader fails to compile or link, carrying which stage failed
20
+ * and the driver's log. */
19
21
  declare class ShaderCompileError extends Error {
20
22
  readonly stage: Stage;
21
23
  readonly log: string;
@@ -109,6 +111,8 @@ declare class GLMeshCache {
109
111
  private readonly gl;
110
112
  private readonly aPositionLoc;
111
113
  private readonly map;
114
+ /** Meshes this context has drawn at least once; see `uploadRecurring`. */
115
+ private readonly seen;
112
116
  private readonly finalizer;
113
117
  private readonly pendingDeletes;
114
118
  /** Transient resources allocated this frame; freed at end of render(). */
@@ -123,6 +127,15 @@ declare class GLMeshCache {
123
127
  * and the FinalizationRegistry, so transient meshes never wait on GC.
124
128
  */
125
129
  uploadTransient(mesh: Mesh): GLMeshHandle;
130
+ /**
131
+ * Upload a Mesh that may or may not recur across frames. Its first sight in
132
+ * *this* context takes `uploadTransient`; every later one takes the
133
+ * persistent handle. One transient upload to find out is cheaper than
134
+ * stranding a persistent VAO on a mesh that never returns, whose release
135
+ * would wait on GC. The transient upload does not populate the persistent
136
+ * map, so steady-state reuse begins on the third frame.
137
+ */
138
+ uploadRecurring(mesh: Mesh): GLMeshHandle;
126
139
  /**
127
140
  * Free all transient resources allocated since the last call. Called by
128
141
  * the renderer at the end of each `render()`. Safe under context loss.
@@ -192,6 +205,8 @@ declare class GLTextureCache {
192
205
  * shader applies premultiplication before writing outColor.
193
206
  */
194
207
 
208
+ /** Bake gradient stops into a 256-entry RGBA lookup strip, which the shader
209
+ * samples instead of evaluating stops per fragment. */
195
210
  declare function buildGradientRamp(stops: GradStop[]): Uint8ClampedArray;
196
211
  declare class GradientRampCache {
197
212
  private readonly gl;
@@ -283,6 +298,9 @@ declare class SolidBatch {
283
298
  private growGpu;
284
299
  }
285
300
 
301
+ /** How to construct a `WeaselRenderer`: the GL context or canvas to draw
302
+ * into, the output size, and the quality knobs that separate screen
303
+ * rendering from print. */
286
304
  interface WeaselRendererOptions {
287
305
  gl?: WebGL2RenderingContext;
288
306
  canvas?: HTMLCanvasElement;
@@ -315,6 +333,14 @@ interface WeaselRendererOptions {
315
333
  * print has no reason to sample a field it could evaluate exactly). */
316
334
  textOutlineMinScreenSize?: number;
317
335
  }
336
+ /**
337
+ * The WebGL2 renderer: takes a list of draw commands and paints them.
338
+ *
339
+ * It knows nothing about the scene — commands are the whole interface, which
340
+ * is what lets layers, HUD widgets and overlays all draw through the same
341
+ * pipeline. GPU resources (meshes, textures, gradient ramps) are cached across
342
+ * frames and keyed by identity, so re-issuing the same command is cheap.
343
+ */
318
344
  declare class WeaselRenderer {
319
345
  private readonly gl;
320
346
  private pathFill;
@@ -422,12 +448,18 @@ declare class WeaselRenderer {
422
448
  /** @internal */ _dpr(): number;
423
449
  }
424
450
 
451
+ /** Options for `tessellate`. A smaller tolerance means more triangles and
452
+ * smoother curves; it is in path-local units, so callers rendering at a
453
+ * larger scale should tighten it. */
425
454
  interface TessellateOptions {
426
455
  /** Flatness tolerance for bezier subdivision in path-local units. */
427
456
  flattenTolerance?: number;
428
457
  }
458
+ /** Turn a path into a triangle mesh the renderer can draw: curves flattened to
459
+ * line segments, then the resulting polygon triangulated. */
429
460
  declare function tessellate(path: Path, opts?: TessellateOptions): Mesh;
430
461
 
462
+ /** Options for stroke tessellation. */
431
463
  interface StrokeOptions {
432
464
  flattenTolerance?: number;
433
465
  }
package/dist/renderer.js CHANGED
@@ -1,13 +1,12 @@
1
- export { IDENTITY_COLOR_MATRIX, OUTLINE_MIN_SCREEN_PX, ShaderCompileError, WeaselRenderer, buildGradientRamp, canQueryLocalFonts, enableLocalFontOutlines, hasFontOutlines, isCanvasFont, listFontOutlines, mat3, outlineStatus, registerCanvasFont, registerFont, registerFontOutlines, registerProgram, subscribeGlyphReady, tessellate, tessellateStroke, unregisterCanvasFont, unregisterFontOutlines, viewToMat3 } from './chunk-FVNWK7U3.js';
2
- import './chunk-DCIU3SRK.js';
3
- import './chunk-UB6A6L77.js';
4
- import './chunk-Z3KNFTTS.js';
5
- import './chunk-6SHZHXXR.js';
6
- import './chunk-775XXAHR.js';
1
+ export { IDENTITY_COLOR_MATRIX, OUTLINE_MIN_SCREEN_PX, ShaderCompileError, WeaselRenderer, buildGradientRamp, canQueryLocalFonts, enableLocalFontOutlines, hasFontOutlines, isCanvasFont, listFontOutlines, mat3, outlineStatus, registerCanvasFont, registerFont, registerFontOutlines, registerProgram, subscribeGlyphReady, tessellate, tessellateStroke, unregisterCanvasFont, unregisterFontOutlines, viewToMat3 } from './chunk-SMCZRSYB.js';
2
+ import './chunk-TR3HZN34.js';
3
+ import './chunk-3KGMJMOS.js';
4
+ import './chunk-3JYFAQIB.js';
5
+ import './chunk-U45SODC2.js';
6
+ import './chunk-JOSUVS6C.js';
7
7
  import './chunk-UGFFCMQP.js';
8
8
  import './chunk-BHVYVFGV.js';
9
9
  import './chunk-GVCNT7UH.js';
10
- export { registerTexture } from './chunk-IO5Z75X4.js';
11
- import './chunk-PZ5AY32C.js';
10
+ export { registerTexture } from './chunk-HGF5X6MZ.js';
12
11
  //# sourceMappingURL=renderer.js.map
13
12
  //# sourceMappingURL=renderer.js.map
package/dist/resize.d.ts CHANGED
@@ -1,12 +1,15 @@
1
- export { C as CORNER_ANCHORS, a as CornerAnchor, b as CornerHandle, U as UseResizeOptions, c as cornerPoint, d as cornerResizeHandles, f as fixedCornerOf, h as hitCornerHandle, p as pointSnapToGrid } from './pointSnapToGrid-BuDZWBrL.js';
2
- export { P as PoseProjection, R as RECT_POSE_DESCRIPTOR, a as ROTATED_POSE_DESCRIPTOR } from './geometry-DVeZ2i-c.js';
3
- import { R as ResizePose, B as BoundsConstraint, M as ModifierState } from './types-BhJJ2OCM.js';
1
+ export { C as CORNER_ANCHORS, a as CornerAnchor, b as CornerHandle, U as UseResizeOptions, c as cornerPoint, d as cornerResizeHandles, f as fixedCornerOf, h as hitCornerHandle, p as pointSnapToGrid } from './pointSnapToGrid-C3wowsQy.js';
2
+ export { P as PoseProjection, R as RECT_POSE_DESCRIPTOR, a as ROTATED_POSE_DESCRIPTOR } from './geometry-5X6TrAkX.js';
3
+ import { R as ResizePose, B as BoundsConstraint, M as ModifierState } from './types-ByZxoD6P.js';
4
4
  import { G as Guide } from './types-D2tTKEU0.js';
5
5
  import { V as View } from './view-DSQgxBJB.js';
6
- import './types-BJ8_cyT7.js';
6
+ import './types-BHK2dkMu.js';
7
7
  import '@weasel-js/history';
8
- import './types-B_-khFM0.js';
8
+ import './types-DpQ0cWYC.js';
9
9
 
10
+ /** Resize constraint that stops a node shrinking past a minimum. The anchored
11
+ * edge stays put, so clamping pushes the dragged edge back rather than moving
12
+ * the node. */
10
13
  declare function clampMinSize<TPose extends ResizePose>(args: {
11
14
  minWidth: number;
12
15
  minHeight: number;
@@ -39,6 +42,10 @@ declare function lockAspectWithModifier<TPose extends ResizePose>(opts?: {
39
42
  }): BoundsConstraint<TPose>;
40
43
 
41
44
  type ModKey$1 = keyof ModifierState;
45
+ /** Resize constraint that snaps the moving edges to a grid, leaving the
46
+ * anchored ones where they are. By default a node already smaller than one
47
+ * grid cell on an axis is left unsnapped on that axis, so it stays resizable
48
+ * at sub-grid sizes. */
42
49
  declare function snapToGrid<TPose extends ResizePose>(args: {
43
50
  spacing: number;
44
51
  bypassKey?: ModKey$1;
package/dist/resize.js CHANGED
@@ -1,5 +1,4 @@
1
- export { CORNER_ANCHORS, DEFAULT_RESIZE_BEHAVIORS, clampMinSize, cornerPoint, cornerResizeHandles, fixedCornerOf, hitCornerHandle, lockAspectWithModifier, pointSnapToGrid, snapToGrid, snapToGuides } from './chunk-Z3KNFTTS.js';
2
- export { RECT_POSE_DESCRIPTOR, ROTATED_POSE_DESCRIPTOR } from './chunk-6SHZHXXR.js';
3
- import './chunk-PZ5AY32C.js';
1
+ export { CORNER_ANCHORS, DEFAULT_RESIZE_BEHAVIORS, clampMinSize, cornerPoint, cornerResizeHandles, fixedCornerOf, hitCornerHandle, lockAspectWithModifier, pointSnapToGrid, snapToGrid, snapToGuides } from './chunk-3JYFAQIB.js';
2
+ export { RECT_POSE_DESCRIPTOR, ROTATED_POSE_DESCRIPTOR } from './chunk-U45SODC2.js';
4
3
  //# sourceMappingURL=resize.js.map
5
4
  //# sourceMappingURL=resize.js.map
package/dist/routing.d.ts CHANGED
@@ -1,16 +1,115 @@
1
- export { bd as Conflict, be as PREDICATE_TARGET, bf as RegistryEntry, bg as ToolDef, m as ToolKeybinding, bh as ToolScopes, bi as ViewportToolDef, bj as buildRouteRegistry, bk as defineTool, bl as defineViewportTool, bm as findConflicts, bn as findScopedConflicts, bo as formatConflict, bp as reportRouteConflicts } from './index-DPI8DV0A.js';
1
+ import { ParsedModifiers, GestureName, GestureSpec } from '@weasel-js/gestures';
2
2
  export { ChannelRef, DescribeRouteOptions, GESTURE_DESCRIPTORS, GestureArgSpec, GestureDescriptor, GestureName, ModRequirement, ModifierKey, ParsedModifiers, 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';
3
- import './types-Kh_osAq9.js';
3
+ import { T as Tool } from './registry-CxnkXbG8.js';
4
+ import './types-vqxpCFVp.js';
4
5
  import '@weasel-js/history';
5
6
  import './path-B6MMiodD.js';
6
- import './types-BhJJ2OCM.js';
7
- import './types-B_-khFM0.js';
7
+ import './types-ByZxoD6P.js';
8
+ import './types-DpQ0cWYC.js';
8
9
  import './view-DSQgxBJB.js';
9
10
  import '@weasel-js/modes';
10
11
  import 'react';
11
- import './geometry-DVeZ2i-c.js';
12
+ import './geometry-5X6TrAkX.js';
12
13
  import './paint-types-CnLIzqq1.js';
13
- import './DrawCommand-DCmiNkBj.js';
14
+ import './DrawCommand-BbPrSTra.js';
14
15
  import 'react/jsx-runtime';
16
+ import './types-BHK2dkMu.js';
15
17
  import '@weasel-js/geom';
16
- import './types-BJ8_cyT7.js';
18
+
19
+ /**
20
+ * One row in the route registry — a single `GestureBinding` on one tool,
21
+ * flattened into the route grammar's vocabulary so the inspector, the
22
+ * conflict checker, and `describeRoute` can all read the same shape.
23
+ *
24
+ * Multiple rows can share (gesture, arg, target, modifiers) if different tools
25
+ * declare them; consumers walk the list and group client-side.
26
+ */
27
+ interface RegistryEntry {
28
+ toolId: string;
29
+ /** Which phase the binding's `phase` spec restricts it to. `'any'` when it
30
+ * declares none, declares `'*'`, or declares an atom list whose atoms
31
+ * don't agree on one phase — such a binding fires in either phase, and
32
+ * reporting it as `'initial'` made it collide with genuinely-initial
33
+ * bindings in `findConflicts`' bucket key. */
34
+ phase: 'initial' | 'engaged' | 'any';
35
+ /** Structured v3 modifier requirements. Empty object = "no modifiers
36
+ * held" (the strict default). */
37
+ modifiers: ParsedModifiers;
38
+ gesture: GestureName;
39
+ /** Resolved arg value for arg-bearing gestures (wheel direction,
40
+ * key name, multiTouchTap fingers). Undefined for gestures whose
41
+ * descriptor has no `arg`. */
42
+ arg: string | undefined;
43
+ /** Target class for hit-testing gestures. `undefined` when the descriptor
44
+ * has `hasTarget: false` or the spec declares no target;
45
+ * {@link PREDICATE_TARGET} when the spec uses a `kindOf` predicate, which
46
+ * the route grammar has no notation for. */
47
+ target: string | undefined;
48
+ /** The action this binding fires. */
49
+ actionId: string;
50
+ /** The `GestureSpec` this row was flattened from, by reference. Reflection
51
+ * consumers that need something the grammar doesn't capture — the
52
+ * specificity tuple, a `kindOf` predicate identity — read it here rather
53
+ * than re-walking `Tool.bindings`. */
54
+ spec: GestureSpec;
55
+ }
56
+ /**
57
+ * Flatten every tool's `bindings` into route-registry rows.
58
+ *
59
+ * This was `buildActionRegistry`, and it walked `ToolDef.initial` /
60
+ * `.engaged` phase tables — the grammar that no longer exists. It was also
61
+ * blind to `Tool.bindings` the entire time the two lived side by side, which
62
+ * is why the inspector under-reported select by more than half. The rename
63
+ * fixes a second thing: it never had anything to do with the Actions
64
+ * Registry, and reading `buildActionRegistry` next to `ActionsRegistry`
65
+ * suggested otherwise.
66
+ */
67
+ declare function buildRouteRegistry(tools: readonly Tool<unknown>[]): RegistryEntry[];
68
+
69
+ /** Two or more tools declare the same exact (phase, gesture, arg, target,
70
+ * modifiers) tuple — the dispatcher's slot precedence picks one
71
+ * arbitrarily (well, deterministically by slot order, but the author
72
+ * probably didn't intend the duplication). */
73
+ interface Conflict {
74
+ phase: 'initial' | 'engaged' | 'any';
75
+ gesture: GestureName;
76
+ arg: string | undefined;
77
+ target: string | undefined;
78
+ modifiers: ParsedModifiers;
79
+ /** All tool ids that registered the same tuple. At least 2 by
80
+ * construction. Order matches the input tools[] order. */
81
+ toolIds: string[];
82
+ }
83
+ /** Detect exact-tuple overlaps across a tool registration set.
84
+ *
85
+ * Intentionally NOT flagged:
86
+ * - Broad vs. narrow targets (e.g. an untargeted `click` alongside
87
+ * `click` on `empty`) — the dispatcher's specificity ordering resolves
88
+ * those cleanly, and the broad one is usually the intended fallback.
89
+ * - Different modifier requirements on the same target — they fire on
90
+ * different inputs.
91
+ * - A binding whose action declines via `enabled()` so a lower-priority
92
+ * one can take the gesture. Detecting that intent would mean evaluating
93
+ * the action; consumers can suppress known-intentional compositions in
94
+ * their UI layer.
95
+ *
96
+ * - Two `{ kindOf }` predicate targets. The route grammar renders every
97
+ * predicate as the single token {@link PREDICATE_TARGET}, so bucketing on
98
+ * the rendered target alone reported select's `resize` / `rotate` / `move`
99
+ * drags — three genuinely different predicates — as a three-way conflict.
100
+ * Predicate entries bucket by function identity instead, which means two
101
+ * *separately written but equivalent* predicates go unflagged. That's the
102
+ * right way to be wrong here: this check has to be silent when nothing is
103
+ * wrong or nobody will keep it on.
104
+ *
105
+ * Note that two bindings sharing a tuple on the SAME tool are now possible
106
+ * (bindings are an array, where phase tables were objects with unique
107
+ * keys) — so a conflict may name one tool twice.
108
+ *
109
+ * This is the raw same-tuple detector. Feeding it a whole tool *registry*
110
+ * over-reports, because registry tools take turns in the active slot and
111
+ * can't collide with each other — see {@link findScopedConflicts}.
112
+ */
113
+ declare function findConflicts(tools: readonly Tool<unknown>[]): Conflict[];
114
+
115
+ export { type Conflict, type RegistryEntry, buildRouteRegistry, findConflicts };
package/dist/routing.js CHANGED
@@ -1,4 +1,3 @@
1
- export { GESTURE_DESCRIPTORS, PREDICATE_TARGET, RESERVED_ID_NAMES, RESERVED_ID_PREFIXES, ROUTE_FIELD_DEFINITIONS, ROUTE_TERMS, buildRouteRegistry, canonicalModifiers, collapseShiftPairs, defineTool, defineViewportTool, describeRoute, describeRouteParts, findConflicts, findScopedConflicts, formatConflict, formatPhaseAtom, formatRoute, getGestureDescriptor, isKnownGestureName, parseRoute, reportRouteConflicts } from './chunk-DCIU3SRK.js';
2
- import './chunk-PZ5AY32C.js';
1
+ export { GESTURE_DESCRIPTORS, RESERVED_ID_NAMES, RESERVED_ID_PREFIXES, ROUTE_FIELD_DEFINITIONS, ROUTE_TERMS, buildRouteRegistry, canonicalModifiers, collapseShiftPairs, describeRoute, describeRouteParts, findConflicts, formatPhaseAtom, formatRoute, getGestureDescriptor, isKnownGestureName, parseRoute } from './chunk-TR3HZN34.js';
3
2
  //# sourceMappingURL=routing.js.map
4
3
  //# sourceMappingURL=routing.js.map
@@ -16,8 +16,14 @@ interface DebugConfig {
16
16
  fps?: boolean;
17
17
  /** Optional per-feature color overrides; falls back to the default theme. */
18
18
  theme?: Partial<DebugTheme>;
19
+ /** Optional per-feature line-width / dash overrides; falls back to
20
+ * {@link DEFAULT_DEBUG_STROKES}. */
21
+ strokes?: Partial<DebugStrokes>;
19
22
  }
23
+ /** The name of one debug-overlay feature — the keys of {@link DebugConfig}
24
+ * that toggle a visualization. */
20
25
  type DebugFeature = 'hitboxes' | 'handles' | 'bounds' | 'origins' | 'snap' | 'layers' | 'ids' | 'fps';
26
+ /** Colors the debug overlay draws with, one entry per feature. */
21
27
  interface DebugTheme {
22
28
  hitboxFill: string;
23
29
  hitboxStroke: string;
@@ -33,7 +39,26 @@ interface DebugTheme {
33
39
  fpsText: string;
34
40
  fpsTextBg: string;
35
41
  }
42
+ /** Line width and dash pattern for one stroked debug feature. An empty (or
43
+ * omitted) `dash` is a solid line. */
44
+ interface DebugStroke {
45
+ width: number;
46
+ dash?: readonly number[];
47
+ }
48
+ /** The stroked half of the debug overlay's appearance, split from
49
+ * {@link DebugTheme} because only some features draw a line at all — text
50
+ * panels and filled origin dots take color and nothing else. */
51
+ interface DebugStrokes {
52
+ hitbox: DebugStroke;
53
+ bounds: DebugStroke;
54
+ handle: DebugStroke;
55
+ /** Rejected snap candidates only; accepted ones paint as a filled dot. */
56
+ snap: DebugStroke;
57
+ }
58
+ /** Which kind of handle a recorded handle marker represents. */
36
59
  type HandleKind = 'corner' | 'rotation' | 'anchor';
60
+ /** The geometry a hit region actually tests against, as reported to the debug
61
+ * sink so the overlay can draw the real shape rather than its bounding box. */
37
62
  type HitShape = {
38
63
  kind: 'rect';
39
64
  x: number;
@@ -50,11 +75,13 @@ type HitShape = {
50
75
  kind: 'path';
51
76
  d: Path2D;
52
77
  };
78
+ /** A hit region tested during the current frame. */
53
79
  interface RecordedHitbox {
54
80
  id: string;
55
81
  kind: 'body' | 'handle' | 'rotation' | 'anchor';
56
82
  shape: HitShape;
57
83
  }
84
+ /** A handle drawn during the current frame, and where. */
58
85
  interface RecordedHandle {
59
86
  id: string;
60
87
  position: {
@@ -63,6 +90,7 @@ interface RecordedHandle {
63
90
  };
64
91
  kind: HandleKind;
65
92
  }
93
+ /** A node's bounds as computed during the current frame. */
66
94
  interface RecordedBounds {
67
95
  id: string;
68
96
  bounds: {
@@ -72,6 +100,7 @@ interface RecordedBounds {
72
100
  height: number;
73
101
  };
74
102
  }
103
+ /** A node's transform origin as used during the current frame. */
75
104
  interface RecordedOrigin {
76
105
  id: string;
77
106
  point: {
@@ -79,6 +108,9 @@ interface RecordedOrigin {
79
108
  y: number;
80
109
  };
81
110
  }
111
+ /** A snap candidate considered during the current gesture, and whether it
112
+ * won. Unlike the other records these survive across frames, until the
113
+ * gesture ends. */
82
114
  interface RecordedSnap {
83
115
  point: {
84
116
  x: number;
@@ -86,12 +118,14 @@ interface RecordedSnap {
86
118
  };
87
119
  accepted: boolean;
88
120
  }
121
+ /** A render layer that drew during the current frame. */
89
122
  interface RecordedLayer {
90
123
  id: string;
91
124
  label: string;
92
125
  space: 'world' | 'screen';
93
126
  index: number;
94
127
  }
128
+ /** Everything the sink collected, ready for the overlay to draw. */
95
129
  interface DebugSnapshot {
96
130
  hitboxes: RecordedHitbox[];
97
131
  handles: RecordedHandle[];
@@ -100,6 +134,14 @@ interface DebugSnapshot {
100
134
  snap: RecordedSnap[];
101
135
  layers: RecordedLayer[];
102
136
  }
137
+ /**
138
+ * Where the kit reports what it is doing so the debug overlay can draw it.
139
+ *
140
+ * Recording is push-based and cheap: hit-testers, handle painters and snap
141
+ * strategies call these as they run, whether or not any overlay is watching.
142
+ * Nothing here affects behavior — a sink that discards everything is a valid
143
+ * sink.
144
+ */
103
145
  interface DebugSink {
104
146
  recordHitbox(id: string, kind: 'body' | 'handle' | 'rotation' | 'anchor', shape: HitShape): void;
105
147
  recordHandle(id: string, position: {
@@ -127,4 +169,4 @@ interface DebugSink {
127
169
  clearSnap(): void;
128
170
  }
129
171
 
130
- export type { DebugSink as D, HandleKind as H, RecordedBounds as R, DebugConfig as a, DebugSnapshot as b, DebugTheme as c, DebugFeature as d, HitShape as e, RecordedHandle as f, RecordedHitbox as g, RecordedLayer as h, RecordedOrigin as i, RecordedSnap as j };
172
+ export type { DebugSink as D, HandleKind as H, RecordedBounds as R, DebugConfig as a, DebugSnapshot as b, DebugStrokes as c, DebugTheme as d, DebugFeature as e, DebugStroke as f, HitShape as g, RecordedHandle as h, RecordedHitbox as i, RecordedLayer as j, RecordedOrigin as k, RecordedSnap as l };
@@ -1,5 +1,5 @@
1
1
  import { Op } from '@weasel-js/history';
2
- import { S as SnapTarget, M as MoveAdapter, I as InsertAdapter } from './types-B_-khFM0.js';
2
+ import { S as SnapTarget, M as MoveAdapter, I as InsertAdapter } from './types-DpQ0cWYC.js';
3
3
 
4
4
  /**
5
5
  * Snapshot of modifier-key state at gesture dispatch.
@@ -1,15 +1,20 @@
1
1
  import { Op } from '@weasel-js/history';
2
2
 
3
+ /** A layout container's extent in world units. */
3
4
  type ContainerBounds = {
4
5
  x: number;
5
6
  y: number;
6
7
  width: number;
7
8
  height: number;
8
9
  };
10
+ /** A child a layout strategy is arranging. */
9
11
  interface LayoutChild<TPose> {
10
12
  id: string;
11
13
  pose: TPose;
12
14
  }
15
+ /** One place a dragged child could land. A strategy offers these as the drag
16
+ * moves, a `LayoutSnap` picks between them, and the chosen one decides both
17
+ * the preview and the committed poses. */
13
18
  interface DropTarget<TPose> {
14
19
  /** Where the dragged child lands if this target is picked. */
15
20
  pose: TPose;
@@ -33,16 +38,22 @@ interface DropTarget<TPose> {
33
38
  /** Strategy-private metadata (e.g. cell coords for tile-grid). */
34
39
  meta?: unknown;
35
40
  }
41
+ /** Chooses which of a strategy's drop targets the pointer means, or `null`
42
+ * to reject the drop. Separate from the strategy so the same arrangement can
43
+ * be paired with different snapping rules. */
36
44
  interface LayoutSnap<TPose> {
37
45
  pickTarget(targets: DropTarget<TPose>[], pointer: {
38
46
  x: number;
39
47
  y: number;
40
48
  }): DropTarget<TPose> | null;
41
49
  }
50
+ /** The container a layout strategy is arranging children within. */
42
51
  interface LayoutContainer {
43
52
  id: string;
44
53
  bounds: ContainerBounds;
45
54
  }
55
+ /** The child currently being dragged: where it started, where the pointer
56
+ * currently proposes it goes, and which container it came from. */
46
57
  interface LayoutDragged<TPose> {
47
58
  id: string;
48
59
  /** The pose the dragged child currently has (pre-drop). */
@@ -51,6 +62,15 @@ interface LayoutDragged<TPose> {
51
62
  pose: TPose;
52
63
  sourceContainerId: string | null;
53
64
  }
65
+ /**
66
+ * How a container arranges its children, and what happens when one is dragged
67
+ * into or around it.
68
+ *
69
+ * The four required methods cover the whole cycle: `childPoses` is the resting
70
+ * arrangement, `getDropTargets` enumerates where a drag could land,
71
+ * `reflowPoses` is the live preview once a target is picked, and `commitDrop`
72
+ * turns the result into ops so the drop is undoable.
73
+ */
54
74
  interface LayoutStrategy<TPose> {
55
75
  childPoses(container: LayoutContainer, children: ReadonlyArray<LayoutChild<TPose>>): Map<string, TPose>;
56
76
  getDropTargets(container: LayoutContainer, children: ReadonlyArray<LayoutChild<TPose>>, dragged: LayoutDragged<TPose>): DropTarget<TPose>[];
@@ -66,6 +86,12 @@ interface LayoutStrategy<TPose> {
66
86
  x: number;
67
87
  y: number;
68
88
  }): boolean;
89
+ /** Optional: reject a drag before any drop-target work happens. A type-aware
90
+ * container (a palette that only takes swatches, say) returns `false` and
91
+ * the drag falls through to whatever container is under it next. When
92
+ * absent, every drag is considered — rejection is still possible later, by
93
+ * `snap.pickTarget` returning null. */
94
+ acceptsDrop?(container: LayoutContainer, dragged: LayoutDragged<TPose>): boolean;
69
95
  }
70
96
 
71
97
  /**
@@ -134,6 +160,12 @@ interface MoveAdapter<TNode extends {
134
160
  * targeting (`getLayout` present), nested-hit collapse
135
161
  * (`pickTopMostHit`), and group-pose composition. Flat scenes may omit. */
136
162
  getParent?(id: string): string | null;
163
+ /** Optional paint depth, read by `pickTopMostHit` to resolve two *siblings*
164
+ * whose bodies both cover the pointer. Without it the hit list's own order
165
+ * decides, which is right for a back-to-front walk and wrong for anything
166
+ * else. See `PickTopMostHitAdapter` for the `compareZ` alternative. */
167
+ getZIndex?(id: string): number | null | undefined;
168
+ compareZ?(a: string, b: string): number;
137
169
  setPose(id: string, pose: TPose): void;
138
170
  /** Optional. Used only by reparent ops (e.g. drag-into-container drops via
139
171
  * layout strategies). Flat scenes that never reparent may omit. */
@@ -80,9 +80,13 @@ interface NodeBase<TData, TLayer extends string, TPose> {
80
80
  data: TData;
81
81
  parent: NodeId | null;
82
82
  }
83
+ /** A node with no children — a shape, a label, an image. */
83
84
  interface LeafNode<TData, TLayer extends string, TPose = RectPose> extends NodeBase<TData, TLayer, TPose> {
84
85
  kind: 'leaf';
85
86
  }
87
+ /** A node with an ordered list of children. This is the real group: what
88
+ * Cmd+G creates, what SVG `<g>` round-trips to. A container has its own pose,
89
+ * which its children's poses are relative to, and may optionally clip them. */
86
90
  interface ContainerNode<TData, TLayer extends string, TPose = RectPose> extends NodeBase<TData, TLayer, TPose> {
87
91
  kind: 'container';
88
92
  children: NodeId[];
@@ -93,20 +97,30 @@ interface ContainerNode<TData, TLayer extends string, TPose = RectPose> extends
93
97
  * paints descendants only where it covers. */
94
98
  clipFromPose?: (pose: TPose) => Path | null;
95
99
  }
100
+ /** A node in the scene tree: either a leaf or a container. Re-exported
101
+ * publicly as `SceneNode`, to avoid colliding with the DOM's `Node`. */
96
102
  type Node<TData, TLayer extends string, TPose = RectPose> = LeafNode<TData, TLayer, TPose> | ContainerNode<TData, TLayer, TPose>;
97
103
  interface LayerRecordBase<TLayer extends string> {
98
104
  id: TLayer;
99
105
  visible: boolean;
100
106
  locked: boolean;
101
107
  }
108
+ /** A layer declared when the scene was created. Fixed set, no display name —
109
+ * these are the kit's own render bands, not something a user manages. */
102
110
  interface SystemLayerRecord<TLayer extends string> extends LayerRecordBase<TLayer> {
103
111
  kind: 'system';
104
112
  }
113
+ /** A layer the user created and can rename, reorder or delete. */
105
114
  interface UserLayerRecord<TLayer extends string> extends LayerRecordBase<TLayer> {
106
115
  kind: 'user';
107
116
  name: string;
108
117
  }
118
+ /** Per-layer metadata held by the scene: whether it is visible and locked,
119
+ * and where it sits in the render stack. Distinct from a node's `layer` tag,
120
+ * which merely names one of these. */
109
121
  type LayerRecord<TLayer extends string> = SystemLayerRecord<TLayer> | UserLayerRecord<TLayer>;
122
+ /** What `Scene.add` needs to mint a node. Everything except the id is
123
+ * required; the id is generated unless one is supplied. */
110
124
  interface AddNodeSpec<TData, TLayer extends string, TPose = RectPose> {
111
125
  kind: 'leaf' | 'container';
112
126
  layer: TLayer;
@@ -120,10 +134,13 @@ interface AddNodeSpec<TData, TLayer extends string, TPose = RectPose> {
120
134
  * to the node; ignored for leaves. Mirrors `ContainerNode.clipFromPose`. */
121
135
  clipFromPose?: (pose: TPose) => Path | null;
122
136
  }
137
+ /** A custom scene mutation registered with `Scene.registerOp`: how to apply
138
+ * it and how to undo it. The pair is what makes it participate in history. */
123
139
  interface RegisteredOp<P> {
124
140
  apply: (payload: P) => void;
125
141
  revert: (payload: P) => void;
126
142
  }
143
+ /** One of the layers a scene is created with. */
127
144
  interface SystemLayerSpec<TLayer extends string> {
128
145
  id: TLayer;
129
146
  visible?: boolean;
@@ -171,6 +188,8 @@ interface SceneRegistry<TPose> {
171
188
  /** Maps registry keys to `clipFromPose` factory functions for container nodes. */
172
189
  clipFromPose?: Readonly<Record<string, (pose: TPose) => Path | null>>;
173
190
  }
191
+ /** Options for `useScene` — the layers the scene has, what it starts out
192
+ * holding, and how its history behaves. */
174
193
  interface UseSceneOptions<TData, TLayer extends string, TPose = RectPose> {
175
194
  systemLayers: readonly SystemLayerSpec<TLayer>[];
176
195
  initial?: readonly AddNodeSpec<TData, TLayer, TPose>[];
@@ -204,6 +223,18 @@ interface UseSceneOptions<TData, TLayer extends string, TPose = RectPose> {
204
223
  * wire it after construction via `scene.setActiveJournalAccessor(fn)`. */
205
224
  getActiveJournal?: () => _weasel_js_history.Journal | null;
206
225
  }
226
+ /**
227
+ * The kit-owned scene tree: nodes, layers, and the undo history over both.
228
+ *
229
+ * A scene is logical, not visual — it says what exists and where, and nothing
230
+ * about how it is painted. Every mutating method is undoable, and reads are
231
+ * snapshots rather than live views. Nodes are addressed by `NodeId`; hold ids
232
+ * across mutations, not node objects.
233
+ *
234
+ * Three type parameters keep it domain-agnostic: `TData` is the app's payload,
235
+ * which the kit never inspects; `TPose` is the transform shape, `RectPose` by
236
+ * default; `TLayer` is the union of layer names.
237
+ */
207
238
  interface Scene<TData, TLayer extends string, TPose = RectPose> {
208
239
  readonly nodes: ReadonlyMap<NodeId, Node<TData, TLayer, TPose>>;
209
240
  readonly roots: readonly NodeId[];
@@ -1,4 +1,4 @@
1
- import { M as Mat3 } from './DrawCommand-DCmiNkBj.js';
1
+ import { M as Mat3 } from './DrawCommand-BbPrSTra.js';
2
2
 
3
3
  /**
4
4
  * GL texture upload cache for ImageBitmap objects.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@weasel-js/core",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "Domain-agnostic 2D scene graph primitives for React: viewport math, drag/resize/insert/clone interactions, layered canvas rendering.",
5
5
  "license": "MIT",
6
6
  "author": "orochi235",
@@ -74,11 +74,11 @@
74
74
  "react": ">=18"
75
75
  },
76
76
  "dependencies": {
77
- "@weasel-js/font": "1.0.1",
78
- "@weasel-js/geom": "1.0.1",
79
- "@weasel-js/gestures": "1.0.1",
80
- "@weasel-js/history": "1.0.1",
81
- "@weasel-js/modes": "1.0.1",
77
+ "@weasel-js/font": "1.0.3",
78
+ "@weasel-js/geom": "1.0.3",
79
+ "@weasel-js/gestures": "1.0.3",
80
+ "@weasel-js/history": "1.0.3",
81
+ "@weasel-js/modes": "1.0.3",
82
82
  "earcut": "2.2.4",
83
83
  "polygon-clipping": "^0.15.7"
84
84
  },