@weasel-js/core 1.1.0 → 1.3.0-pre.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.
Files changed (61) hide show
  1. package/CHANGELOG.md +1988 -0
  2. package/dist/{DrawCommand-BbPrSTra.d.ts → DrawCommand-BnZyQaDc.d.ts} +29 -189
  3. package/dist/chunk-2KKYDDDD.js +121 -0
  4. package/dist/chunk-2KKYDDDD.js.map +1 -0
  5. package/dist/{chunk-J7LUY47N.js → chunk-3FB44DBC.js} +3 -3
  6. package/dist/{chunk-J7LUY47N.js.map → chunk-3FB44DBC.js.map} +1 -1
  7. package/dist/{chunk-J3YC3GVF.js → chunk-3ZV53ZW2.js} +51 -14
  8. package/dist/chunk-3ZV53ZW2.js.map +1 -0
  9. package/dist/{chunk-JOSUVS6C.js → chunk-67KE7SDP.js} +4 -4
  10. package/dist/chunk-67KE7SDP.js.map +1 -0
  11. package/dist/{chunk-CSMF654J.js → chunk-AQS4JGRA.js} +50 -7
  12. package/dist/chunk-AQS4JGRA.js.map +1 -0
  13. package/dist/{chunk-HGF5X6MZ.js → chunk-BJN5ZRIJ.js} +2 -2
  14. package/dist/chunk-BJN5ZRIJ.js.map +1 -0
  15. package/dist/{chunk-4Z6J4IVH.js → chunk-F74NVEHT.js} +14 -46
  16. package/dist/chunk-F74NVEHT.js.map +1 -0
  17. package/dist/{chunk-3B4QEB2G.js → chunk-IFOVTYAK.js} +26291 -24809
  18. package/dist/chunk-IFOVTYAK.js.map +1 -0
  19. package/dist/{chunk-UGFFCMQP.js → chunk-MXFSHJOM.js} +4 -4
  20. package/dist/{chunk-UGFFCMQP.js.map → chunk-MXFSHJOM.js.map} +1 -1
  21. package/dist/{chunk-BHVYVFGV.js → chunk-ZB7UYJVG.js} +3 -3
  22. package/dist/{chunk-BHVYVFGV.js.map → chunk-ZB7UYJVG.js.map} +1 -1
  23. package/dist/clipboard.d.ts +3 -3
  24. package/dist/clipboard.js +3 -3
  25. package/dist/clone.d.ts +2 -2
  26. package/dist/clone.js +3 -3
  27. package/dist/{geometry-C56YbnfD.d.ts → geometry-Dtt_k6Dq.d.ts} +1 -1
  28. package/dist/{grid-DqOi0Vgi.d.ts → grid-nnXU4VjN.d.ts} +1 -1
  29. package/dist/index.d.ts +1929 -1342
  30. package/dist/index.js +10 -10
  31. package/dist/insert.d.ts +3 -3
  32. package/dist/insert.js +1 -1
  33. package/dist/move.d.ts +4 -4
  34. package/dist/move.js +3 -3
  35. package/dist/{options-C6HYCKP7.d.ts → options-CdFl510T.d.ts} +1 -1
  36. package/dist/{path-B6MMiodD.d.ts → path-JEV2c5If.d.ts} +2 -13
  37. package/dist/patterns-builtin.d.ts +1 -1
  38. package/dist/patterns-builtin.js +1 -1
  39. package/dist/{pointSnapToGrid-BBtn5bus.d.ts → pointSnapToGrid-Dmthv94u.d.ts} +2 -2
  40. package/dist/{registry-DGBrjGbB.d.ts → registry-BU1_3L_C.d.ts} +691 -38
  41. package/dist/renderer.d.ts +38 -83
  42. package/dist/renderer.js +10 -10
  43. package/dist/resize.d.ts +4 -4
  44. package/dist/resize.js +2 -2
  45. package/dist/routing.d.ts +35 -9
  46. package/dist/routing.js +1 -1
  47. package/dist/stroke-5pBwOm9s.d.ts +190 -0
  48. package/dist/{types-vqxpCFVp.d.ts → types-DIQAisSG.d.ts} +107 -5
  49. package/dist/{types-DbysOO-2.d.ts → types-XBcDEp3Y.d.ts} +14 -9
  50. package/dist/{types-BhrifbZ1.d.ts → types-miXHGrZM.d.ts} +1 -1
  51. package/package.json +8 -6
  52. package/dist/chunk-3B4QEB2G.js.map +0 -1
  53. package/dist/chunk-4Z6J4IVH.js.map +0 -1
  54. package/dist/chunk-CSMF654J.js.map +0 -1
  55. package/dist/chunk-GVCNT7UH.js +0 -47
  56. package/dist/chunk-GVCNT7UH.js.map +0 -1
  57. package/dist/chunk-HGF5X6MZ.js.map +0 -1
  58. package/dist/chunk-J3YC3GVF.js.map +0 -1
  59. package/dist/chunk-JOSUVS6C.js.map +0 -1
  60. package/dist/paint-types-CnLIzqq1.d.ts +0 -261
  61. package/dist/viewToMat3-CQW_YqDw.d.ts +0 -67
@@ -1,69 +1,12 @@
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
- import { G as GradStop, S as Stroke } from './paint-types-CnLIzqq1.js';
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-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
- import { P as Path } from './path-B6MMiodD.js';
1
+ import { M as Mesh, S as ShaderProgram, I as ImageMinification, G as GLImageCache } from './stroke-5pBwOm9s.js';
2
+ export { a as ShaderCompileError, b as SpriteSheet, c as StrokeOptions, V as ViewLike, f as frameRect, t as tessellateStroke, v as viewToMat3 } from './stroke-5pBwOm9s.js';
3
+ import { GradStop, TextureHandle } from '@weasel-js/paint';
4
+ export { TextureHandle } from '@weasel-js/paint';
5
+ import { M as Mat3, S as ShaderProgramHandle, D as DrawCommand } from './DrawCommand-BnZyQaDc.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-BnZyQaDc.js';
7
+ import { P as Path } from './path-JEV2c5If.js';
8
8
  export { canQueryLocalFonts, enableLocalFontOutlines, hasFontOutlines, isCanvasFont, listFontOutlines, outlineStatus, registerCanvasFont, registerFont, registerFontOutlines, subscribeGlyphReady, unregisterCanvasFont, unregisterFontOutlines } from '@weasel-js/font';
9
-
10
- /**
11
- * Minimal compile/link/lookup wrapper for a GL program. Throws
12
- * `ShaderCompileError` on compile or link failure with the GL info log
13
- * embedded in the error message — never returns a half-initialized program.
14
- *
15
- * Designed so test code can stub `getShaderParameter` / `getProgramParameter`
16
- * via the recorder Proxy without further special-casing.
17
- */
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. */
21
- declare class ShaderCompileError extends Error {
22
- readonly stage: Stage;
23
- readonly log: string;
24
- constructor(stage: Stage, log: string);
25
- }
26
- declare class ShaderProgram {
27
- private readonly gl;
28
- readonly handle: WebGLProgram;
29
- private readonly uniforms;
30
- private readonly attributes;
31
- constructor(gl: WebGL2RenderingContext, vertSrc: string, fragSrc: string);
32
- private compile;
33
- lookupUniforms(names: readonly string[]): void;
34
- lookupAttributes(names: readonly string[]): void;
35
- uniform(name: string): WebGLUniformLocation | undefined;
36
- attribute(name: string): number | undefined;
37
- }
38
-
39
- /**
40
- * A tessellated representation of a Path, ready to upload to GL.
41
- *
42
- * - `vertices` is interleaved x,y in path-local coordinates (`Float32Array`
43
- * of length `2 * vertexCount`).
44
- * - `indices` are triangle indices into `vertices` (`Uint32Array`, length
45
- * `3 * triangleCount`).
46
- * - `requiresStencil` is set for paths whose fillRule is `'evenodd'` and
47
- * whose triangulation is a *naive* per-contour fan rather than a clean
48
- * inside/outside triangulation. The renderer must use a stencil
49
- * two-pass when this flag is true. Single-contour paths and `'nonzero'`
50
- * multi-contour paths leave it false.
51
- * - `anchorA` / `anchorB` / `anchorT` parameterize each mesh vertex by
52
- * the two consecutive path anchors it lies between and the arc-length
53
- * fraction along that segment (0 = at A, 1 = at B). Vertices that fall
54
- * exactly on an anchor set A === B and t = 0. Used at draw time when
55
- * the DrawCommand supplies per-anchor colors so the renderer can lerp
56
- * per mesh vertex. Optional — emitted by the path tessellators; absent
57
- * on meshes built by other paths (e.g. text glyphs).
58
- */
59
- interface Mesh {
60
- readonly vertices: Float32Array;
61
- readonly indices: Uint32Array;
62
- readonly requiresStencil?: boolean;
63
- readonly anchorA?: Uint32Array;
64
- readonly anchorB?: Uint32Array;
65
- readonly anchorT?: Float32Array;
66
- }
9
+ import '@weasel-js/text';
67
10
 
68
11
  interface GLMeshHandle {
69
12
  readonly vao: WebGLVertexArrayObject;
@@ -256,6 +199,28 @@ declare class GroupState {
256
199
  pop(): void;
257
200
  }
258
201
 
202
+ /**
203
+ * registerTexture — accepts an image source, assigns an opaque id, stores in
204
+ * a module-level registry. Actual GL upload happens lazily at draw time in
205
+ * drawShader() via GLTextureCache.upload (which is idempotent).
206
+ *
207
+ * Lifecycle: textures live for the renderer's lifetime. No unregister in v1.
208
+ *
209
+ * Convention §9: this registry stores image data only — no per-renderer state.
210
+ * Each WeaselRenderer's GLTextureCache does its own dedup via has(id).
211
+ */
212
+
213
+ /**
214
+ * Register an image for use as a shader texture uniform.
215
+ *
216
+ * Returns a TextureHandle whose `id` can be passed as a ShaderUniform value.
217
+ * The handle is valid for the lifetime of the renderer it will be used with.
218
+ *
219
+ * @param image The image to register. HTMLImageElement must be fully loaded.
220
+ * @returns Opaque TextureHandle.
221
+ */
222
+ declare function registerTexture(image: HTMLImageElement | ImageBitmap): TextureHandle;
223
+
259
224
  /**
260
225
  * Growable vertex staging for consecutive solid-fill geometry.
261
226
  *
@@ -402,6 +367,13 @@ declare class WeaselRenderer {
402
367
  * @experimental
403
368
  */
404
369
  registerProgram(handle: ShaderProgramHandle): void;
370
+ /**
371
+ * The compiled program for `id`, compiling it against this context on first
372
+ * use. Unlike {@link registerProgram} this neither throws on a missing
373
+ * source nor on a compile failure: a paint kind asking for a program it
374
+ * never registered must decline the paint, not take down the frame.
375
+ */
376
+ private ensureProgram;
405
377
  private applyViewport;
406
378
  isContextLost(): boolean;
407
379
  private onContextLost;
@@ -475,23 +447,6 @@ interface TessellateOptions {
475
447
  * line segments, then the resulting polygon triangulated. */
476
448
  declare function tessellate(path: Path, opts?: TessellateOptions): Mesh;
477
449
 
478
- /** Options for stroke tessellation. */
479
- interface StrokeOptions {
480
- flattenTolerance?: number;
481
- }
482
- /**
483
- * Build a triangle-mesh ribbon from a stroked Path.
484
- *
485
- * Supports:
486
- * - cap: 'butt' | 'round' | 'square'
487
- * - join: 'miter' | 'round' | 'bevel'
488
- * - center alignment directly; RectPath inner/outer alignment via a
489
- * pre-shifted rect; PolygonPath inner/outer alignment via stencil at the
490
- * renderer level
491
- * - dash splitting
492
- */
493
- declare function tessellateStroke(path: Path, stroke: Stroke, opts?: StrokeOptions): Mesh;
494
-
495
450
  /**
496
451
  * On-screen glyph size (CSS px) at or above which a face with registered
497
452
  * outlines is drawn as geometry instead of sampled from a distance field.
@@ -507,4 +462,4 @@ declare function tessellateStroke(path: Path, stroke: Stroke, opts?: StrokeOptio
507
462
  */
508
463
  declare const OUTLINE_MIN_SCREEN_PX = 48;
509
464
 
510
- export { DrawCommand, IDENTITY_COLOR_MATRIX, ImageMinification, Mat3, type Mesh, OUTLINE_MIN_SCREEN_PX, ShaderCompileError, ShaderProgramHandle, type StrokeOptions, type TessellateOptions, WeaselRenderer, type WeaselRendererOptions, buildGradientRamp, tessellate, tessellateStroke };
465
+ export { DrawCommand, IDENTITY_COLOR_MATRIX, ImageMinification, Mat3, Mesh, OUTLINE_MIN_SCREEN_PX, ShaderProgramHandle, type TessellateOptions, WeaselRenderer, type WeaselRendererOptions, buildGradientRamp, registerTexture, tessellate };
package/dist/renderer.js CHANGED
@@ -1,12 +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-3B4QEB2G.js';
2
- import './chunk-J3YC3GVF.js';
3
- import './chunk-CSMF654J.js';
4
- import './chunk-J7LUY47N.js';
5
- import './chunk-4Z6J4IVH.js';
6
- import './chunk-JOSUVS6C.js';
7
- import './chunk-UGFFCMQP.js';
8
- import './chunk-BHVYVFGV.js';
9
- import './chunk-GVCNT7UH.js';
10
- export { registerTexture } from './chunk-HGF5X6MZ.js';
1
+ export { IDENTITY_COLOR_MATRIX, OUTLINE_MIN_SCREEN_PX, ShaderCompileError, WeaselRenderer, buildGradientRamp, canQueryLocalFonts, enableLocalFontOutlines, frameRect, hasFontOutlines, isCanvasFont, listFontOutlines, mat3, outlineStatus, registerCanvasFont, registerFont, registerFontOutlines, registerProgram, subscribeGlyphReady, tessellate, tessellateStroke, unregisterCanvasFont, unregisterFontOutlines, viewToMat3 } from './chunk-IFOVTYAK.js';
2
+ import './chunk-3ZV53ZW2.js';
3
+ import './chunk-AQS4JGRA.js';
4
+ import './chunk-3FB44DBC.js';
5
+ import './chunk-F74NVEHT.js';
6
+ import './chunk-67KE7SDP.js';
7
+ import './chunk-MXFSHJOM.js';
8
+ import './chunk-ZB7UYJVG.js';
9
+ import './chunk-2KKYDDDD.js';
10
+ export { registerTexture } from './chunk-BJN5ZRIJ.js';
11
11
  //# sourceMappingURL=renderer.js.map
12
12
  //# sourceMappingURL=renderer.js.map
package/dist/resize.d.ts CHANGED
@@ -1,11 +1,11 @@
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-BBtn5bus.js';
2
- export { P as PoseProjection, R as RECT_POSE_DESCRIPTOR, a as ROTATED_POSE_DESCRIPTOR } from './geometry-C56YbnfD.js';
3
- import { R as ResizePose, B as BoundsConstraint, M as ModifierState } from './types-BhrifbZ1.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-Dmthv94u.js';
2
+ export { P as PoseProjection, R as RECT_POSE_DESCRIPTOR, a as ROTATED_POSE_DESCRIPTOR } from './geometry-Dtt_k6Dq.js';
3
+ import { R as ResizePose, B as BoundsConstraint, M as ModifierState } from './types-miXHGrZM.js';
4
4
  import { G as Guide } from './types-D2tTKEU0.js';
5
5
  import { V as View } from './view-DSQgxBJB.js';
6
6
  import './types-BHK2dkMu.js';
7
7
  import '@weasel-js/history';
8
- import './types-DbysOO-2.js';
8
+ import './types-XBcDEp3Y.js';
9
9
 
10
10
  /** Resize constraint that stops a node shrinking past a minimum. The anchored
11
11
  * edge stays put, so clamping pushes the dragged edge back rather than moving
package/dist/resize.js CHANGED
@@ -1,4 +1,4 @@
1
- export { CORNER_ANCHORS, DEFAULT_RESIZE_BEHAVIORS, clampMinSize, cornerPoint, cornerResizeHandles, fixedCornerOf, hitCornerHandle, lockAspectWithModifier, pointSnapToGrid, snapToGrid, snapToGuides } from './chunk-J7LUY47N.js';
2
- export { RECT_POSE_DESCRIPTOR, ROTATED_POSE_DESCRIPTOR } from './chunk-4Z6J4IVH.js';
1
+ export { CORNER_ANCHORS, DEFAULT_RESIZE_BEHAVIORS, clampMinSize, cornerPoint, cornerResizeHandles, fixedCornerOf, hitCornerHandle, lockAspectWithModifier, pointSnapToGrid, snapToGrid, snapToGuides } from './chunk-3FB44DBC.js';
2
+ export { RECT_POSE_DESCRIPTOR, ROTATED_POSE_DESCRIPTOR } from './chunk-F74NVEHT.js';
3
3
  //# sourceMappingURL=resize.js.map
4
4
  //# sourceMappingURL=resize.js.map
package/dist/routing.d.ts CHANGED
@@ -1,17 +1,18 @@
1
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 { T as Tool } from './registry-DGBrjGbB.js';
4
- import './types-vqxpCFVp.js';
3
+ import { T as Tool } from './registry-BU1_3L_C.js';
4
+ import './types-DIQAisSG.js';
5
5
  import '@weasel-js/history';
6
- import './path-B6MMiodD.js';
7
- import './types-BhrifbZ1.js';
8
- import './types-DbysOO-2.js';
6
+ import './path-JEV2c5If.js';
7
+ import './types-miXHGrZM.js';
8
+ import './types-XBcDEp3Y.js';
9
9
  import './view-DSQgxBJB.js';
10
10
  import '@weasel-js/modes';
11
11
  import 'react';
12
- import './geometry-C56YbnfD.js';
13
- import './paint-types-CnLIzqq1.js';
14
- import './DrawCommand-BbPrSTra.js';
12
+ import './DrawCommand-BnZyQaDc.js';
13
+ import '@weasel-js/paint';
14
+ import '@weasel-js/text';
15
+ import './geometry-Dtt_k6Dq.js';
15
16
  import 'react/jsx-runtime';
16
17
  import './types-BHK2dkMu.js';
17
18
  import '@weasel-js/geom';
@@ -53,6 +54,16 @@ interface RegistryEntry {
53
54
  * than re-walking `Tool.bindings`. */
54
55
  spec: GestureSpec;
55
56
  }
57
+ /**
58
+ * Stand-in target for a `{ kindOf }` predicate spec.
59
+ *
60
+ * The route grammar can name target *classes* (`empty`, `selected-body`,
61
+ * `kind:rect`) but not arbitrary predicates, so three distinct select-tool
62
+ * bindings all render as this one token. Narrowing it would mean giving the
63
+ * grammar a way to describe a function, which is a real design question and
64
+ * not one this reflection layer should answer by inventing syntax.
65
+ */
66
+ declare const PREDICATE_TARGET = "predicate";
56
67
  /**
57
68
  * Flatten every tool's `bindings` into route-registry rows.
58
69
  *
@@ -65,6 +76,21 @@ interface RegistryEntry {
65
76
  * suggested otherwise.
66
77
  */
67
78
  declare function buildRouteRegistry(tools: readonly Tool<unknown>[]): RegistryEntry[];
79
+ /** The route-grammar gesture a `GestureSpec.kind` routes as, or `undefined`
80
+ * for kinds the grammar has no name for. */
81
+ declare function routeGestureForSpecKind(kind: GestureSpec['kind']): GestureName | undefined;
82
+ /**
83
+ * Every route string one `GestureSpec` declares, in route-grammar notation.
84
+ *
85
+ * One string per arg alternative — a spec bound to `['ArrowUp','ArrowDown']`
86
+ * yields two routes, because each is separately conflictable and separately
87
+ * readable. Returns `[]` for spec kinds the grammar can't name.
88
+ *
89
+ * This is the display counterpart to {@link buildRouteRegistry}: same
90
+ * projection of a spec onto the grammar, rendered as text instead of as a
91
+ * conflict-checkable row.
92
+ */
93
+ declare function routesForSpec(spec: GestureSpec): readonly string[];
68
94
 
69
95
  /** Two or more tools declare the same exact (phase, gesture, arg, target,
70
96
  * modifiers) tuple — the dispatcher's slot precedence picks one
@@ -112,4 +138,4 @@ interface Conflict {
112
138
  */
113
139
  declare function findConflicts(tools: readonly Tool<unknown>[]): Conflict[];
114
140
 
115
- export { type Conflict, type RegistryEntry, buildRouteRegistry, findConflicts };
141
+ export { type Conflict, PREDICATE_TARGET, type RegistryEntry, buildRouteRegistry, findConflicts, routeGestureForSpecKind, routesForSpec };
package/dist/routing.js CHANGED
@@ -1,3 +1,3 @@
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-J3YC3GVF.js';
1
+ export { GESTURE_DESCRIPTORS, PREDICATE_TARGET, RESERVED_ID_NAMES, RESERVED_ID_PREFIXES, ROUTE_FIELD_DEFINITIONS, ROUTE_TERMS, buildRouteRegistry, canonicalModifiers, collapseShiftPairs, describeRoute, describeRouteParts, findConflicts, formatPhaseAtom, formatRoute, getGestureDescriptor, isKnownGestureName, parseRoute, routeGestureForSpecKind, routesForSpec } from './chunk-3ZV53ZW2.js';
2
2
  //# sourceMappingURL=routing.js.map
3
3
  //# sourceMappingURL=routing.js.map
@@ -0,0 +1,190 @@
1
+ import { M as Mat3 } from './DrawCommand-BnZyQaDc.js';
2
+ import { P as Path } from './path-JEV2c5If.js';
3
+ import { Stroke } from '@weasel-js/paint';
4
+
5
+ /**
6
+ * Minimal compile/link/lookup wrapper for a GL program. Throws
7
+ * `ShaderCompileError` on compile or link failure with the GL info log
8
+ * embedded in the error message — never returns a half-initialized program.
9
+ *
10
+ * Designed so test code can stub `getShaderParameter` / `getProgramParameter`
11
+ * via the recorder Proxy without further special-casing.
12
+ */
13
+ type Stage = 'vertex' | 'fragment' | 'link';
14
+ /** Thrown when a shader fails to compile or link, carrying which stage failed
15
+ * and the driver's log. */
16
+ declare class ShaderCompileError extends Error {
17
+ readonly stage: Stage;
18
+ readonly log: string;
19
+ constructor(stage: Stage, log: string);
20
+ }
21
+ declare class ShaderProgram {
22
+ private readonly gl;
23
+ readonly handle: WebGLProgram;
24
+ private readonly uniforms;
25
+ private readonly attributes;
26
+ constructor(gl: WebGL2RenderingContext, vertSrc: string, fragSrc: string);
27
+ private compile;
28
+ lookupUniforms(names: readonly string[]): void;
29
+ lookupAttributes(names: readonly string[]): void;
30
+ uniform(name: string): WebGLUniformLocation | undefined;
31
+ attribute(name: string): number | undefined;
32
+ }
33
+
34
+ /**
35
+ * A tessellated representation of a Path, ready to upload to GL.
36
+ *
37
+ * - `vertices` is interleaved x,y in path-local coordinates (`Float32Array`
38
+ * of length `2 * vertexCount`).
39
+ * - `indices` are triangle indices into `vertices` (`Uint32Array`, length
40
+ * `3 * triangleCount`).
41
+ * - `requiresStencil` is set for paths whose fillRule is `'evenodd'` and
42
+ * whose triangulation is a *naive* per-contour fan rather than a clean
43
+ * inside/outside triangulation. The renderer must use a stencil
44
+ * two-pass when this flag is true. Single-contour paths and `'nonzero'`
45
+ * multi-contour paths leave it false.
46
+ * - `anchorA` / `anchorB` / `anchorT` parameterize each mesh vertex by
47
+ * the two consecutive path anchors it lies between and the arc-length
48
+ * fraction along that segment (0 = at A, 1 = at B). Vertices that fall
49
+ * exactly on an anchor set A === B and t = 0. Used at draw time when
50
+ * the DrawCommand supplies per-anchor colors so the renderer can lerp
51
+ * per mesh vertex. Optional — emitted by the path tessellators; absent
52
+ * on meshes built by other paths (e.g. text glyphs).
53
+ */
54
+ interface Mesh {
55
+ readonly vertices: Float32Array;
56
+ readonly indices: Uint32Array;
57
+ readonly requiresStencil?: boolean;
58
+ readonly anchorA?: Uint32Array;
59
+ readonly anchorB?: Uint32Array;
60
+ readonly anchorT?: Float32Array;
61
+ }
62
+
63
+ /**
64
+ * GL texture upload cache for ImageBitmap objects.
65
+ *
66
+ * Key: ImageBitmap (or pattern source object) identity (WeakMap) — lets GC
67
+ * reclaim unreferenced bitmaps. The GL textures are NOT freed when the source
68
+ * is gc'd; deferred to v2.
69
+ *
70
+ * Wrapping is set once at upload time per the `repetition` parameter:
71
+ * - undefined / 'no-repeat' → CLAMP_TO_EDGE
72
+ * - 'repeat' → REPEAT (both axes)
73
+ * - 'repeat-x' → REPEAT on S, CLAMP on T
74
+ * - 'repeat-y' → CLAMP on S, REPEAT on T
75
+ *
76
+ * Convention §2: texels stored straight; shader premultiplies.
77
+ */
78
+ type PatternRepetition = 'repeat' | 'repeat-x' | 'repeat-y' | 'no-repeat';
79
+ /** MIN_FILTER strategy for uploaded textures. */
80
+ type ImageMinification = 'linear' | 'mipmap';
81
+ type TexSource = ImageBitmap | ImageData | HTMLCanvasElement | HTMLImageElement;
82
+ declare class GLImageCache {
83
+ private readonly gl;
84
+ private readonly minification;
85
+ private readonly map;
86
+ /** `minification` selects the MIN_FILTER strategy for uploaded textures.
87
+ * `'linear'` (default) is the screen path's existing behavior. `'mipmap'`
88
+ * generates mipmaps and filters LINEAR_MIPMAP_LINEAR — required for
89
+ * quality minification when a large source bitmap is drawn small (the
90
+ * headless print/export path); bilinear-only minification undersamples
91
+ * and produces moiré. */
92
+ constructor(gl: WebGL2RenderingContext, minification?: ImageMinification);
93
+ upload(key: object, source: TexSource, repetition?: PatternRepetition): WebGLTexture;
94
+ bind(key: object, unit: number): void;
95
+ }
96
+
97
+ /**
98
+ * Uniform-grid sprite sheet layout — frame index to the source rect an
99
+ * `ImageDrawCommand` samples. Pure arithmetic over the grid description; it
100
+ * never touches the bitmap.
101
+ */
102
+ /** A sprite sheet's grid. `margin` and `spacing` follow the Tiled / Aseprite
103
+ * tileset convention, so a sheet exported from either describes itself here. */
104
+ interface SpriteSheet {
105
+ frameWidth: number;
106
+ frameHeight: number;
107
+ columns: number;
108
+ /** Empty pixels around the whole grid. Default 0. */
109
+ margin?: number;
110
+ /** Empty pixels between adjacent cells — the gutter that keeps linear
111
+ * sampling off the neighboring frame. Default 0. */
112
+ spacing?: number;
113
+ }
114
+ /**
115
+ * Row-major source rect for frame `index`, counting from 0 at the top-left.
116
+ *
117
+ * `index` is not range-checked and does not wrap: past the last cell this
118
+ * returns a rect below the sheet, which draws as an edge smear. Wrapping is
119
+ * the animation's business (`frameRect(sheet, tick % count)`) — a sheet does
120
+ * not know how many of its cells are filled.
121
+ */
122
+ declare function frameRect(sheet: SpriteSheet, index: number): {
123
+ x: number;
124
+ y: number;
125
+ w: number;
126
+ h: number;
127
+ };
128
+
129
+ /**
130
+ * View → Mat3 helper for layer `draw` implementations on world-space layers.
131
+ *
132
+ * The kit's main package ships a `View` type at
133
+ * `src/core/viewport/view.ts`; we re-declare a structurally compatible
134
+ * shape here to avoid a runtime cross-package import. Exported as
135
+ * `ViewLike` from the package barrel.
136
+ */
137
+
138
+ /** A weasel View — `{x, y, scale: {x, y}}`. Local type to avoid a cross-package import. */
139
+ interface View {
140
+ x: number;
141
+ y: number;
142
+ scale: {
143
+ x: number;
144
+ y: number;
145
+ };
146
+ }
147
+ /**
148
+ * Build the world→screen transform matrix for a `View`.
149
+ * Use as the `transform` field of a `kind: 'group'` DrawCommand to wrap
150
+ * world-space content emitted from a layer `draw` implementation.
151
+ *
152
+ * Mapping: `screen = (world − {view.x, view.y}) × {view.scale.x, view.scale.y}`.
153
+ *
154
+ * Column-major layout (matches `mat3.identity()`):
155
+ * `[scale.x, 0, 0, 0, scale.y, 0, -view.x*scale.x, -view.y*scale.y, 1]`.
156
+ */
157
+ declare function viewToMat3(view: View): Mat3;
158
+
159
+ /** Options for stroke tessellation. */
160
+ interface StrokeOptions {
161
+ flattenTolerance?: number;
162
+ /**
163
+ * Shorten each open subpath by this much at its start / end, in the same
164
+ * world units as the path. Stroke markers use this so a filled head is not
165
+ * speared by its own line; the caller resolves the distance, because this
166
+ * layer knows nothing about the marker registry.
167
+ */
168
+ startInset?: number;
169
+ endInset?: number;
170
+ }
171
+ /** Resolve a stroke width to world units. A number is already world units;
172
+ * `{ px }` is screen pixels divided by the accumulated scale, so it holds its
173
+ * on-screen thickness as the view zooms. */
174
+ declare function resolveStrokeWidth(width: number | {
175
+ px: number;
176
+ }, scale: number): number;
177
+ /**
178
+ * Build a triangle-mesh ribbon from a stroked Path.
179
+ *
180
+ * Supports:
181
+ * - cap: 'butt' | 'round' | 'square'
182
+ * - join: 'miter' | 'round' | 'bevel'
183
+ * - center alignment directly; RectPath inner/outer alignment via a
184
+ * pre-shifted rect; PolygonPath inner/outer alignment via stencil at the
185
+ * renderer level
186
+ * - dash splitting
187
+ */
188
+ declare function tessellateStroke(path: Path, stroke: Stroke, opts?: StrokeOptions): Mesh;
189
+
190
+ export { GLImageCache as G, type ImageMinification as I, type Mesh as M, ShaderProgram as S, type View as V, ShaderCompileError as a, type SpriteSheet as b, type StrokeOptions as c, frameRect as f, resolveStrokeWidth as r, tessellateStroke as t, viewToMat3 as v };
@@ -1,6 +1,6 @@
1
1
  import * as _weasel_js_history from '@weasel-js/history';
2
2
  import { Op, SerializedHistory } from '@weasel-js/history';
3
- import { P as Path } from './path-B6MMiodD.js';
3
+ import { P as Path } from './path-JEV2c5If.js';
4
4
 
5
5
  /**
6
6
  * Axis-aligned rectangle pose with optional rotation. The canonical pose
@@ -79,6 +79,20 @@ interface NodeBase<TData, TLayer extends string, TPose> {
79
79
  pose: TPose;
80
80
  data: TData;
81
81
  parent: NodeId | null;
82
+ /** Nodes whose poses this node's geometry is computed from. Fixed at add
83
+ * time. Absent or empty means the node's geometry is authored, which is the
84
+ * normal case. */
85
+ dependsOn?: readonly NodeId[];
86
+ /** Computes this node's path from its dependencies' poses, in `dependsOn`
87
+ * order. A dependency that has been removed arrives as `undefined`.
88
+ * Returning `null` means "nothing to draw right now". Re-evaluated when a
89
+ * dependency's world pose changes, never authored. Absolute-pose `Scene`
90
+ * makes that the dependency's own pose, and an ancestor's move reaches it as
91
+ * a `setPose` of its own from the container cascade.
92
+ * `node` is deliberately widened: naming `TData`/`TLayer` here puts them in
93
+ * a contravariant position, making `Scene` invariant in both and breaking
94
+ * assignment kit-wide. The cost is that a `derivePath` casts to read `node.data`. */
95
+ derivePath?: (node: Node<unknown, string, TPose>, deps: readonly (TPose | undefined)[]) => Path | null;
82
96
  }
83
97
  /** A node with no children — a shape, a label, an image. */
84
98
  interface LeafNode<TData, TLayer extends string, TPose = RectPose> extends NodeBase<TData, TLayer, TPose> {
@@ -133,6 +147,11 @@ interface AddNodeSpec<TData, TLayer extends string, TPose = RectPose> {
133
147
  /** Only meaningful when `kind === 'container'`. Attach a clip-path function
134
148
  * to the node; ignored for leaves. Mirrors `ContainerNode.clipFromPose`. */
135
149
  clipFromPose?: (pose: TPose) => Path | null;
150
+ /** Mirrors `SceneNode.dependsOn`. */
151
+ dependsOn?: readonly NodeId[];
152
+ /** Mirrors `SceneNode.derivePath`. Taken as a live function; its registry key is
153
+ * looked up from it, never passed in. */
154
+ derivePath?: (node: Node<unknown, string, TPose>, deps: readonly (TPose | undefined)[]) => Path | null;
136
155
  }
137
156
  /** A custom scene mutation registered with `Scene.registerOp`: how to apply
138
157
  * it and how to undo it. The pair is what makes it participate in history. */
@@ -180,6 +199,10 @@ interface SerializedNode<TData, TLayer extends string, TPose> {
180
199
  /** Registry key for the container's clip-path factory.
181
200
  * Containers only; omitted when the container has no clip. */
182
201
  clipFromPoseKey?: string;
202
+ /** Ids this node's geometry derives from. Omitted when it derives from nothing. */
203
+ dependsOn?: readonly string[];
204
+ /** Registry key for the node's `derivePath` function. Omitted when it has none. */
205
+ derivePathKey?: string;
183
206
  }
184
207
  /** Per-scene registry mapping string keys to live function references.
185
208
  * Passed to `createScene({ ..., registry })` and `sceneFromJSON(json, { registry })`.
@@ -187,6 +210,8 @@ interface SerializedNode<TData, TLayer extends string, TPose> {
187
210
  interface SceneRegistry<TPose> {
188
211
  /** Maps registry keys to `clipFromPose` factory functions for container nodes. */
189
212
  clipFromPose?: Readonly<Record<string, (pose: TPose) => Path | null>>;
213
+ /** Maps registry keys to `derivePath` functions for nodes with `dependsOn`. */
214
+ derivePath?: Readonly<Record<string, (node: Node<unknown, string, TPose>, deps: readonly (TPose | undefined)[]) => Path | null>>;
190
215
  }
191
216
  /** Options for `useScene` — the layers the scene has, what it starts out
192
217
  * holding, and how its history behaves. */
@@ -222,6 +247,58 @@ interface UseSceneOptions<TData, TLayer extends string, TPose = RectPose> {
222
247
  * mode machines that depend on `scene.history`), pass nothing here and
223
248
  * wire it after construction via `scene.setActiveJournalAccessor(fn)`. */
224
249
  getActiveJournal?: () => _weasel_js_history.Journal | null;
250
+ /** Re-render the host on every scene mutation. Default `true`. Set `false`
251
+ * when the scene is read by a frame loop rather than by a render — a game
252
+ * loop, a simulation — and nothing in the host's DOM derives from it.
253
+ * Read by `useScene`; `createScene` ignores it. */
254
+ subscribe?: boolean;
255
+ }
256
+ /**
257
+ * One node's ephemeral presentation override — what a frame loop wants to say
258
+ * about a node without saying it about the document.
259
+ *
260
+ * Not document content: never recorded in history, never in `toJSON`, and
261
+ * writing one does not bump `Scene.getVersion()`. Hoist one entry per node and
262
+ * mutate it in place on a frame loop; `PoseOverrides.commit()` is what makes a
263
+ * mutation visible.
264
+ */
265
+ interface PoseOverride<TPose> {
266
+ /** Replaces the node's document pose everywhere the render and hit-test
267
+ * paths read one, including the clip a container derives from its pose.
268
+ * Resolved by `effectivePose` — reading `node.pose` directly is how those
269
+ * paths came to disagree about where a node is. */
270
+ pose?: TPose;
271
+ /** Multiplied into the node's painted alpha, on top of any `alphaFor`. */
272
+ alpha?: number;
273
+ }
274
+ /**
275
+ * The scene's ephemeral per-node overrides — see {@link PoseOverride}.
276
+ *
277
+ * The intended shape of a frame is: `set` each node once, mutate the entries
278
+ * in place per frame, `commit()` once. `commit` is not optional bookkeeping —
279
+ * the painter memo keys on pose *reference*, so a mutation without a commit
280
+ * paints the previous frame with no error.
281
+ *
282
+ * To promote a frame to document state (dropping a drag, baking an animation),
283
+ * write it once through `Scene.setPose` and `clear` the override.
284
+ */
285
+ interface PoseOverrides<TPose> {
286
+ /** Store `entry` for `id` **by reference**; the caller keeps mutating it. */
287
+ set(id: NodeId, entry: PoseOverride<TPose>): void;
288
+ get(id: NodeId): PoseOverride<TPose> | undefined;
289
+ has(id: NodeId): boolean;
290
+ /** The overridden ids, as a snapshot array. */
291
+ ids(): readonly NodeId[];
292
+ clear(id: NodeId): void;
293
+ clearAll(): void;
294
+ /** Publish this frame's in-place mutations: invalidate the painter memo for
295
+ * every overridden node, then notify subscribers. */
296
+ commit(): void;
297
+ /** Notified after every write. The canvas uses this to repaint without a
298
+ * scene version bump. */
299
+ subscribe(fn: () => void): () => void;
300
+ /** Monotonic write counter. A snapshot for observers that poll. */
301
+ getGeneration(): number;
225
302
  }
226
303
  /**
227
304
  * The kit-owned scene tree: nodes, layers, and the undo history over both.
@@ -251,10 +328,19 @@ interface Scene<TData, TLayer extends string, TPose = RectPose> {
251
328
  * not a live view, and not yours to mutate. */
252
329
  renderOrderNodes(): readonly Node<TData, TLayer, TPose>[];
253
330
  add(spec: AddNodeSpec<TData, TLayer, TPose>): NodeId;
254
- /** Delete `id` **and its entire subtree** every descendant is removed in
255
- * the same operation. Recorded as one undoable step; `undo()` restores the
256
- * whole subtree (root + descendants, child order intact). */
331
+ /** Delete `id`, its **entire subtree**, and **everything that derives from**
332
+ * any of those nodes a node listing one of them in `dependsOn` goes too,
333
+ * along with its own subtree, transitively. A dependent can live anywhere in
334
+ * the tree, so this deletes nodes the caller never named and may unlink
335
+ * several disjoint subtrees at once. Recorded as one undoable step; `undo()`
336
+ * restores every one of them where it was, child order intact. */
257
337
  remove(id: NodeId): void;
338
+ /** {@link remove} over several roots at once, as a **single** undoable step.
339
+ * Ids resolve against the tree as it stands at the call, so an id that
340
+ * another one would cascade away is absorbed rather than removed twice —
341
+ * which is what makes it safe to pass a whole selection. Throws if any id is
342
+ * not in the scene; an empty list does nothing and records no step. */
343
+ removeMany(ids: readonly NodeId[]): void;
258
344
  update(id: NodeId, patch: {
259
345
  data: TData;
260
346
  }): void;
@@ -290,6 +376,9 @@ interface Scene<TData, TLayer extends string, TPose = RectPose> {
290
376
  setLayerVisible(layer: TLayer, visible: boolean): void;
291
377
  setLayerLocked(layer: TLayer, locked: boolean): void;
292
378
  addLayer(spec: AddLayerSpec<TLayer>): void;
379
+ /** Drop a user layer and every node tagged to it, as one undoable step.
380
+ * Removal cascades, so this also deletes nodes **on other layers** that
381
+ * derive from a node on this one. */
293
382
  removeLayer(layer: TLayer): void;
294
383
  renameLayer(layer: TLayer, name: string): void;
295
384
  moveLayer(layer: TLayer, index: number): void;
@@ -323,6 +412,19 @@ interface Scene<TData, TLayer extends string, TPose = RectPose> {
323
412
  * `SceneCanvasAdapter`). Pass `this` from `sceneToAdapter` or a compatible
324
413
  * adapter. */
325
414
  applyBatch(ops: Op[], label: string, adapter: unknown): void;
415
+ /** The transient set of active ids — "operate on these N as a unit".
416
+ * Shared by every view over this scene unless a view supplies its own
417
+ * (see `CanvasView.selection`). Not document content: it never appears
418
+ * in `toJSON`. It does ride on history entries, so undo and redo put
419
+ * back the selection an edit was made under; changing it is never an
420
+ * undo step of its own. */
421
+ getSelection(): readonly NodeId[];
422
+ setSelection(ids: readonly NodeId[]): void;
423
+ /** Per-node pose / alpha overrides the render and hit-test paths read
424
+ * through. Like {@link Scene.getSelection} this is not document content:
425
+ * writes are never recorded, never serialized, and do not bump
426
+ * {@link Scene.getVersion}. See {@link PoseOverrides}. */
427
+ readonly overrides: PoseOverrides<TPose>;
326
428
  undo(): boolean;
327
429
  redo(): boolean;
328
430
  canUndo(): boolean;
@@ -388,4 +490,4 @@ interface Scene<TData, TLayer extends string, TPose = RectPose> {
388
490
  getVersion(): number;
389
491
  }
390
492
 
391
- export { type AddLayerSpec as A, type ContainerNode as C, type LayerRecord as L, type NodeId as N, type RectPose as R, type Scene as S, type UseSceneOptions as U, type Node as a, type SerializedScene as b, type SceneRegistry as c, type RegisteredOp as d, type AddNodeSpec as e, type LeafNode as f, type SerializedNode as g, type SystemLayerRecord as h, type SystemLayerSpec as i, type UserLayerRecord as j, asNodeId as k };
493
+ export { type AddLayerSpec as A, type ContainerNode as C, type LayerRecord as L, type NodeId as N, type PoseOverride as P, type RectPose as R, type Scene as S, type UseSceneOptions as U, type Node as a, type SerializedScene as b, type SceneRegistry as c, type RegisteredOp as d, type AddNodeSpec as e, type LeafNode as f, type PoseOverrides as g, type SerializedNode as h, type SystemLayerRecord as i, type SystemLayerSpec as j, type UserLayerRecord as k, asNodeId as l };