@weasel-js/core 1.0.2 → 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.
- package/CHANGELOG.md +61 -0
- package/dist/{DrawCommand-DCmiNkBj.d.ts → DrawCommand-BbPrSTra.d.ts} +24 -0
- package/dist/{chunk-Z3KNFTTS.js → chunk-3JYFAQIB.js} +3 -3
- package/dist/chunk-3JYFAQIB.js.map +1 -0
- package/dist/{chunk-UB6A6L77.js → chunk-3KGMJMOS.js} +3 -3
- package/dist/{chunk-UB6A6L77.js.map → chunk-3KGMJMOS.js.map} +1 -1
- package/dist/{chunk-IO5Z75X4.js → chunk-HGF5X6MZ.js} +2 -2
- package/dist/chunk-HGF5X6MZ.js.map +1 -0
- package/dist/{chunk-775XXAHR.js → chunk-JOSUVS6C.js} +2 -2
- package/dist/{chunk-775XXAHR.js.map → chunk-JOSUVS6C.js.map} +1 -1
- package/dist/{chunk-PI56ORHE.js → chunk-SMCZRSYB.js} +88 -59
- package/dist/chunk-SMCZRSYB.js.map +1 -0
- package/dist/{chunk-W2WB4352.js → chunk-TR3HZN34.js} +2 -2
- package/dist/chunk-TR3HZN34.js.map +1 -0
- package/dist/{chunk-6SHZHXXR.js → chunk-U45SODC2.js} +2 -2
- package/dist/{chunk-6SHZHXXR.js.map → chunk-U45SODC2.js.map} +1 -1
- package/dist/clipboard.d.ts +5 -2
- package/dist/clipboard.js +1 -1
- package/dist/clone.d.ts +2 -2
- package/dist/{geometry-CnISZ11w.d.ts → geometry-5X6TrAkX.d.ts} +1 -1
- package/dist/{grid-CBiLBnyc.d.ts → grid-sfilv5HP.d.ts} +7 -2
- package/dist/index.d.ts +546 -20
- package/dist/index.js +7 -7
- package/dist/insert.d.ts +6 -3
- package/dist/insert.js +1 -1
- package/dist/insert.js.map +1 -1
- package/dist/move.d.ts +26 -5
- package/dist/move.js +2 -2
- package/dist/move.js.map +1 -1
- package/dist/{options-DoOvx50U.d.ts → options-CbsIgQci.d.ts} +3 -1
- package/dist/patterns-builtin.d.ts +8 -0
- package/dist/patterns-builtin.js +1 -1
- package/dist/{pointSnapToGrid-Bj4r_lEQ.d.ts → pointSnapToGrid-C3wowsQy.d.ts} +9 -3
- package/dist/{registry-BQL4oyTg.d.ts → registry-CxnkXbG8.d.ts} +90 -6
- package/dist/renderer.d.ts +25 -4
- package/dist/renderer.js +7 -7
- package/dist/resize.d.ts +12 -5
- package/dist/resize.js +2 -2
- package/dist/routing.d.ts +7 -7
- package/dist/routing.js +1 -1
- package/dist/{types-Dtxe7jTS.d.ts → types-BHK2dkMu.d.ts} +23 -0
- package/dist/{types-Ct4n0Z38.d.ts → types-ByZxoD6P.d.ts} +1 -1
- package/dist/{types-Ch0Goo-j.d.ts → types-DpQ0cWYC.d.ts} +20 -0
- package/dist/{types-Kh_osAq9.d.ts → types-vqxpCFVp.d.ts} +31 -0
- package/dist/{viewToMat3-BvaWCN99.d.ts → viewToMat3-CQW_YqDw.d.ts} +1 -1
- package/package.json +6 -6
- package/dist/chunk-IO5Z75X4.js.map +0 -1
- package/dist/chunk-PI56ORHE.js.map +0 -1
- package/dist/chunk-W2WB4352.js.map +0 -1
- package/dist/chunk-Z3KNFTTS.js.map +0 -1
package/dist/renderer.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { I as ImageMinification, G as GLImageCache } from './viewToMat3-
|
|
2
|
-
export { V as ViewLike, v as viewToMat3 } from './viewToMat3-
|
|
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-
|
|
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-
|
|
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;
|
|
@@ -203,6 +205,8 @@ declare class GLTextureCache {
|
|
|
203
205
|
* shader applies premultiplication before writing outColor.
|
|
204
206
|
*/
|
|
205
207
|
|
|
208
|
+
/** Bake gradient stops into a 256-entry RGBA lookup strip, which the shader
|
|
209
|
+
* samples instead of evaluating stops per fragment. */
|
|
206
210
|
declare function buildGradientRamp(stops: GradStop[]): Uint8ClampedArray;
|
|
207
211
|
declare class GradientRampCache {
|
|
208
212
|
private readonly gl;
|
|
@@ -294,6 +298,9 @@ declare class SolidBatch {
|
|
|
294
298
|
private growGpu;
|
|
295
299
|
}
|
|
296
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. */
|
|
297
304
|
interface WeaselRendererOptions {
|
|
298
305
|
gl?: WebGL2RenderingContext;
|
|
299
306
|
canvas?: HTMLCanvasElement;
|
|
@@ -326,6 +333,14 @@ interface WeaselRendererOptions {
|
|
|
326
333
|
* print has no reason to sample a field it could evaluate exactly). */
|
|
327
334
|
textOutlineMinScreenSize?: number;
|
|
328
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
|
+
*/
|
|
329
344
|
declare class WeaselRenderer {
|
|
330
345
|
private readonly gl;
|
|
331
346
|
private pathFill;
|
|
@@ -433,12 +448,18 @@ declare class WeaselRenderer {
|
|
|
433
448
|
/** @internal */ _dpr(): number;
|
|
434
449
|
}
|
|
435
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. */
|
|
436
454
|
interface TessellateOptions {
|
|
437
455
|
/** Flatness tolerance for bezier subdivision in path-local units. */
|
|
438
456
|
flattenTolerance?: number;
|
|
439
457
|
}
|
|
458
|
+
/** Turn a path into a triangle mesh the renderer can draw: curves flattened to
|
|
459
|
+
* line segments, then the resulting polygon triangulated. */
|
|
440
460
|
declare function tessellate(path: Path, opts?: TessellateOptions): Mesh;
|
|
441
461
|
|
|
462
|
+
/** Options for stroke tessellation. */
|
|
442
463
|
interface StrokeOptions {
|
|
443
464
|
flattenTolerance?: number;
|
|
444
465
|
}
|
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-
|
|
2
|
-
import './chunk-
|
|
3
|
-
import './chunk-
|
|
4
|
-
import './chunk-
|
|
5
|
-
import './chunk-
|
|
6
|
-
import './chunk-
|
|
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-
|
|
10
|
+
export { registerTexture } from './chunk-HGF5X6MZ.js';
|
|
11
11
|
//# sourceMappingURL=renderer.js.map
|
|
12
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-
|
|
2
|
-
export { P as PoseProjection, R as RECT_POSE_DESCRIPTOR, a as ROTATED_POSE_DESCRIPTOR } from './geometry-
|
|
3
|
-
import { R as ResizePose, B as BoundsConstraint, M as ModifierState } from './types-
|
|
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-
|
|
6
|
+
import './types-BHK2dkMu.js';
|
|
7
7
|
import '@weasel-js/history';
|
|
8
|
-
import './types-
|
|
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,4 +1,4 @@
|
|
|
1
|
-
export { CORNER_ANCHORS, DEFAULT_RESIZE_BEHAVIORS, clampMinSize, cornerPoint, cornerResizeHandles, fixedCornerOf, hitCornerHandle, lockAspectWithModifier, pointSnapToGrid, snapToGrid, snapToGuides } from './chunk-
|
|
2
|
-
export { RECT_POSE_DESCRIPTOR, ROTATED_POSE_DESCRIPTOR } from './chunk-
|
|
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';
|
|
3
3
|
//# sourceMappingURL=resize.js.map
|
|
4
4
|
//# sourceMappingURL=resize.js.map
|
package/dist/routing.d.ts
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
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-
|
|
4
|
-
import './types-
|
|
3
|
+
import { T as Tool } from './registry-CxnkXbG8.js';
|
|
4
|
+
import './types-vqxpCFVp.js';
|
|
5
5
|
import '@weasel-js/history';
|
|
6
6
|
import './path-B6MMiodD.js';
|
|
7
|
-
import './types-
|
|
8
|
-
import './types-
|
|
7
|
+
import './types-ByZxoD6P.js';
|
|
8
|
+
import './types-DpQ0cWYC.js';
|
|
9
9
|
import './view-DSQgxBJB.js';
|
|
10
10
|
import '@weasel-js/modes';
|
|
11
11
|
import 'react';
|
|
12
|
-
import './geometry-
|
|
12
|
+
import './geometry-5X6TrAkX.js';
|
|
13
13
|
import './paint-types-CnLIzqq1.js';
|
|
14
|
-
import './DrawCommand-
|
|
14
|
+
import './DrawCommand-BbPrSTra.js';
|
|
15
15
|
import 'react/jsx-runtime';
|
|
16
|
-
import './types-
|
|
16
|
+
import './types-BHK2dkMu.js';
|
|
17
17
|
import '@weasel-js/geom';
|
|
18
18
|
|
|
19
19
|
/**
|
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-
|
|
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';
|
|
2
2
|
//# sourceMappingURL=routing.js.map
|
|
3
3
|
//# sourceMappingURL=routing.js.map
|
|
@@ -20,7 +20,10 @@ interface DebugConfig {
|
|
|
20
20
|
* {@link DEFAULT_DEBUG_STROKES}. */
|
|
21
21
|
strokes?: Partial<DebugStrokes>;
|
|
22
22
|
}
|
|
23
|
+
/** The name of one debug-overlay feature — the keys of {@link DebugConfig}
|
|
24
|
+
* that toggle a visualization. */
|
|
23
25
|
type DebugFeature = 'hitboxes' | 'handles' | 'bounds' | 'origins' | 'snap' | 'layers' | 'ids' | 'fps';
|
|
26
|
+
/** Colors the debug overlay draws with, one entry per feature. */
|
|
24
27
|
interface DebugTheme {
|
|
25
28
|
hitboxFill: string;
|
|
26
29
|
hitboxStroke: string;
|
|
@@ -52,7 +55,10 @@ interface DebugStrokes {
|
|
|
52
55
|
/** Rejected snap candidates only; accepted ones paint as a filled dot. */
|
|
53
56
|
snap: DebugStroke;
|
|
54
57
|
}
|
|
58
|
+
/** Which kind of handle a recorded handle marker represents. */
|
|
55
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. */
|
|
56
62
|
type HitShape = {
|
|
57
63
|
kind: 'rect';
|
|
58
64
|
x: number;
|
|
@@ -69,11 +75,13 @@ type HitShape = {
|
|
|
69
75
|
kind: 'path';
|
|
70
76
|
d: Path2D;
|
|
71
77
|
};
|
|
78
|
+
/** A hit region tested during the current frame. */
|
|
72
79
|
interface RecordedHitbox {
|
|
73
80
|
id: string;
|
|
74
81
|
kind: 'body' | 'handle' | 'rotation' | 'anchor';
|
|
75
82
|
shape: HitShape;
|
|
76
83
|
}
|
|
84
|
+
/** A handle drawn during the current frame, and where. */
|
|
77
85
|
interface RecordedHandle {
|
|
78
86
|
id: string;
|
|
79
87
|
position: {
|
|
@@ -82,6 +90,7 @@ interface RecordedHandle {
|
|
|
82
90
|
};
|
|
83
91
|
kind: HandleKind;
|
|
84
92
|
}
|
|
93
|
+
/** A node's bounds as computed during the current frame. */
|
|
85
94
|
interface RecordedBounds {
|
|
86
95
|
id: string;
|
|
87
96
|
bounds: {
|
|
@@ -91,6 +100,7 @@ interface RecordedBounds {
|
|
|
91
100
|
height: number;
|
|
92
101
|
};
|
|
93
102
|
}
|
|
103
|
+
/** A node's transform origin as used during the current frame. */
|
|
94
104
|
interface RecordedOrigin {
|
|
95
105
|
id: string;
|
|
96
106
|
point: {
|
|
@@ -98,6 +108,9 @@ interface RecordedOrigin {
|
|
|
98
108
|
y: number;
|
|
99
109
|
};
|
|
100
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. */
|
|
101
114
|
interface RecordedSnap {
|
|
102
115
|
point: {
|
|
103
116
|
x: number;
|
|
@@ -105,12 +118,14 @@ interface RecordedSnap {
|
|
|
105
118
|
};
|
|
106
119
|
accepted: boolean;
|
|
107
120
|
}
|
|
121
|
+
/** A render layer that drew during the current frame. */
|
|
108
122
|
interface RecordedLayer {
|
|
109
123
|
id: string;
|
|
110
124
|
label: string;
|
|
111
125
|
space: 'world' | 'screen';
|
|
112
126
|
index: number;
|
|
113
127
|
}
|
|
128
|
+
/** Everything the sink collected, ready for the overlay to draw. */
|
|
114
129
|
interface DebugSnapshot {
|
|
115
130
|
hitboxes: RecordedHitbox[];
|
|
116
131
|
handles: RecordedHandle[];
|
|
@@ -119,6 +134,14 @@ interface DebugSnapshot {
|
|
|
119
134
|
snap: RecordedSnap[];
|
|
120
135
|
layers: RecordedLayer[];
|
|
121
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
|
+
*/
|
|
122
145
|
interface DebugSink {
|
|
123
146
|
recordHitbox(id: string, kind: 'body' | 'handle' | 'rotation' | 'anchor', shape: HitShape): void;
|
|
124
147
|
recordHandle(id: string, position: {
|
|
@@ -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-
|
|
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>[];
|
|
@@ -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[];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@weasel-js/core",
|
|
3
|
-
"version": "1.0.
|
|
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.
|
|
78
|
-
"@weasel-js/geom": "1.0.
|
|
79
|
-
"@weasel-js/gestures": "1.0.
|
|
80
|
-
"@weasel-js/history": "1.0.
|
|
81
|
-
"@weasel-js/modes": "1.0.
|
|
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
|
},
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/renderer/textures/registerTexture.ts","../src/features/patterns/tileGeometry.ts","../src/features/patterns/index.ts","../src/features/patterns/patterns-builtin.ts"],"names":[],"mappings":"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","file":"chunk-IO5Z75X4.js","sourcesContent":["/**\n * registerTexture — accepts an image source, assigns an opaque id, stores in\n * a module-level registry. Actual GL upload happens lazily at draw time in\n * drawShader() via GLTextureCache.upload (which is idempotent).\n *\n * Lifecycle: textures live for the renderer's lifetime. No unregister in v1.\n *\n * Convention §9: this registry stores image data only — no per-renderer state.\n * Each WeaselRenderer's GLTextureCache does its own dedup via has(id).\n */\n\nexport interface TextureHandle {\n readonly id: string;\n}\n\nexport interface TextureEntry {\n source: HTMLImageElement | ImageBitmap;\n}\n\nlet counter = 0;\nlet registry = new Map<string, TextureEntry>();\n\n/** @internal Test helper — do not call from product code. */\nexport function _resetTextureRegistryForTests(): void {\n registry = new Map();\n counter = 0;\n}\n\nexport function getTexture(id: string): TextureEntry | null {\n return registry.get(id) ?? null;\n}\n\n/**\n * Register an image for use as a shader texture uniform.\n *\n * Returns a TextureHandle whose `id` can be passed as a ShaderUniform value.\n * The handle is valid for the lifetime of the renderer it will be used with.\n *\n * @param image The image to register. HTMLImageElement must be fully loaded.\n * @returns Opaque TextureHandle.\n */\nexport function registerTexture(\n image: HTMLImageElement | ImageBitmap,\n): TextureHandle {\n const id = `tex_${++counter}`;\n registry.set(id, { source: image });\n return { id };\n}\n","/**\n * The shapes a built-in tile is made of, as data.\n *\n * One description, two renderers: `patterns-builtin` strokes/fills these to\n * an `OffscreenCanvas` to build the GL texture, and `@weasel-js/svg` maps\n * them to `<pattern>` children. Duplicating the tile drawing in the\n * serializer would let the raster and vector forms drift apart silently.\n */\n\nimport type { TilePatternSpec } from '../../core/paint-types';\n\nexport type TileShape =\n | { kind: 'line'; x1: number; y1: number; x2: number; y2: number; width: number; color: string }\n | { kind: 'circle'; cx: number; cy: number; r: number; color: string }\n | { kind: 'ellipse'; cx: number; cy: number; rx: number; ry: number; rotation: number; color: string }\n | { kind: 'rect'; x: number; y: number; width: number; height: number; color: string };\n\n/** A built-in tile's shapes plus the edge length they're drawn within. */\nexport interface TileGeometry {\n size: number;\n shapes: TileShape[];\n}\n\n/** Defaults per tile kind, matching each factory's signature. */\nexport function tileSize(spec: TilePatternSpec): number {\n if (spec.size !== undefined) return spec.size;\n switch (spec.tile) {\n case 'hatch': return 5;\n case 'crosshatch': return 6;\n case 'dots': return 6;\n case 'chunks': return 48;\n default: return 8;\n }\n}\n\n/** Seeded PRNG (mulberry32) — `chunks` places its scatter with this, so the\n * same `seed` yields the same tile in both the raster and vector paths. */\nfunction mulberry32(seed: number): () => number {\n let s = seed | 0;\n return () => {\n s = (s + 0x6D2B79F5) | 0;\n let t = Math.imul(s ^ (s >>> 15), 1 | s);\n t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n };\n}\n\nexport function tileGeometry(spec: TilePatternSpec): TileGeometry {\n const s = tileSize(spec);\n const { color } = spec;\n\n switch (spec.tile) {\n case 'hatch': {\n const width = spec.lineWidth ?? 1;\n return { size: s, shapes: forwardDiagonals(s, width, color) };\n }\n case 'crosshatch': {\n const width = spec.lineWidth ?? 0.8;\n return {\n size: s,\n shapes: [...forwardDiagonals(s, width, color), ...backwardDiagonals(s, width, color)],\n };\n }\n case 'dots': {\n const r = spec.radius ?? 1;\n return { size: s, shapes: [{ kind: 'circle', cx: s / 2, cy: s / 2, r, color }] };\n }\n case 'chunks': {\n const density = spec.density ?? 0.35;\n const chunkSize = spec.chunkSize ?? 3;\n const rand = mulberry32(spec.seed ?? 42);\n const count = Math.round((s * s * density) / (chunkSize * chunkSize));\n const shapes: TileShape[] = [];\n if (spec.bg !== undefined) {\n shapes.push({ kind: 'rect', x: 0, y: 0, width: s, height: s, color: spec.bg });\n }\n for (let i = 0; i < count; i++) {\n const cx = rand() * s;\n const cy = rand() * s;\n const w = chunkSize * (0.5 + rand());\n const h = chunkSize * (0.5 + rand());\n const rotation = rand() * Math.PI;\n shapes.push({ kind: 'ellipse', cx, cy, rx: w / 2, ry: h / 2, rotation, color });\n }\n return { size: s, shapes };\n }\n default:\n return { size: s, shapes: [] };\n }\n}\n\n/** The forward (`/`) diagonal, plus the two corner stubs that make it tile\n * seamlessly across the edges. */\nfunction forwardDiagonals(s: number, width: number, color: string): TileShape[] {\n return [\n { kind: 'line', x1: -1, y1: s + 1, x2: s + 1, y2: -1, width, color },\n { kind: 'line', x1: -1, y1: 1, x2: 1, y2: -1, width, color },\n { kind: 'line', x1: s - 1, y1: s + 1, x2: s + 1, y2: s - 1, width, color },\n ];\n}\n\n/** The backward (`\\`) diagonal and its two stubs. */\nfunction backwardDiagonals(s: number, width: number, color: string): TileShape[] {\n return [\n { kind: 'line', x1: -1, y1: -1, x2: s + 1, y2: s + 1, width, color },\n { kind: 'line', x1: s - 1, y1: -1, x2: s + 1, y2: 1, width, color },\n { kind: 'line', x1: -1, y1: s - 1, x2: 1, y2: s + 1, width, color },\n ];\n}\n\n/** Draw a tile's shapes to a 2D context — the raster half of the pair. */\nexport function drawTileShapes(oc: CanvasRenderingContext2D, geometry: TileGeometry): void {\n for (const shape of geometry.shapes) {\n if (shape.kind === 'line') {\n oc.strokeStyle = shape.color;\n oc.lineWidth = shape.width;\n oc.beginPath();\n oc.moveTo(shape.x1, shape.y1);\n oc.lineTo(shape.x2, shape.y2);\n oc.stroke();\n continue;\n }\n oc.fillStyle = shape.color;\n if (shape.kind === 'rect') {\n oc.fillRect(shape.x, shape.y, shape.width, shape.height);\n continue;\n }\n oc.beginPath();\n if (shape.kind === 'circle') {\n oc.arc(shape.cx, shape.cy, shape.r, 0, Math.PI * 2);\n } else {\n oc.ellipse(shape.cx, shape.cy, shape.rx, shape.ry, shape.rotation, 0, Math.PI * 2);\n }\n oc.fill();\n }\n}\n","/**\n * Tile-pattern primitive — a small helper for building repeating texture\n * tiles from a draw callback. The result plugs into a `FillStyle` of\n * `{ fill: 'pattern', pattern }` (see `../../core/paint-types.ts`).\n *\n * GL-backed: the tile is rendered to an `OffscreenCanvas` (with a 2D fallback\n * to a regular `<canvas>` for environments without `OffscreenCanvas`),\n * converted to an `ImageBitmap`, and registered with `registerTexture()`.\n * The returned `TextureHandle` is what `FillStyle.pattern` accepts.\n *\n * For ready-to-use named patterns (hatch, crosshatch, dots, chunks),\n * see the `@weasel-js/core/patterns-builtin` subpath.\n */\n\nimport { registerTexture } from '../../renderer/textures/registerTexture';\nimport type { TextureHandle } from '../../renderer/textures/registerTexture';\n\n/** Options for `createTilePattern`. */\nexport interface TilePatternOpts {\n /** Edge length (in pixels) of the square offscreen tile. */\n size: number;\n /** FillStyle one tile at integer-pixel coordinates `(0, 0) .. (size, size)`. */\n draw: (oc: CanvasRenderingContext2D, size: number) => void;\n}\n\n/**\n * Render a single tile to an offscreen canvas and register it as a GL\n * texture, returning a `TextureHandle` you can wrap in a `FillStyle` of\n * `{ fill: 'pattern', pattern }`. Returns `null` only when an\n * `OffscreenCanvas`/2D context can't be acquired (very rare; same fallback\n * semantics as the prior `CanvasPattern`-based implementation).\n */\nexport function createTilePattern(opts: TilePatternOpts): TextureHandle | null {\n // Prefer OffscreenCanvas; fall back to <canvas> for environments without it\n // (tests in jsdom may need that fallback — try OffscreenCanvas first).\n let off: OffscreenCanvas | HTMLCanvasElement;\n try {\n off = new OffscreenCanvas(opts.size, opts.size);\n } catch {\n if (typeof document === 'undefined') return null;\n const c = document.createElement('canvas');\n c.width = opts.size;\n c.height = opts.size;\n off = c;\n }\n const oc = off.getContext('2d') as CanvasRenderingContext2D | null;\n if (!oc) return null;\n opts.draw(oc, opts.size);\n\n // Convert to ImageBitmap so registerTexture can store it.\n // OffscreenCanvas.transferToImageBitmap() is the fast path; the\n // synchronous path requires OffscreenCanvas. If we got here without it,\n // the env doesn't support OffscreenCanvas — fail gracefully.\n let bitmap: ImageBitmap;\n if (typeof (off as OffscreenCanvas).transferToImageBitmap === 'function') {\n bitmap = (off as OffscreenCanvas).transferToImageBitmap();\n } else {\n return null;\n }\n return registerTexture(bitmap);\n}\n","/**\n * Built-in pattern factories — generic line/dot/scatter textures. Each\n * returns a `TextureHandle` you can wrap in a `FillStyle` of\n * `{ fill: 'pattern', pattern }` and pass to anything that accepts a `FillStyle`\n * (`FillStyle`-aware layers, path fills, etc.).\n * Imported from a subpath so consumers that ship their own catalog can\n * avoid the bundle cost.\n *\n * All factories require an explicit `color` (and `bg` for `chunks`). No\n * defaults are baked in — the caller's design system is the source of truth\n * for palette decisions.\n *\n * Each is a thin wrapper over `tileGeometry`, which describes the tile as\n * shapes so `@weasel-js/svg` can emit the same tile as a `<pattern>`.\n * Prefer naming a tile in a `TilePatternSpec` over calling these directly —\n * a spec serializes, a `TextureHandle` does not.\n */\n\nexport { tileGeometry, tileSize, drawTileShapes } from './tileGeometry';\nexport type { TileShape, TileGeometry } from './tileGeometry';\n\nimport { createTilePattern } from '.';\nimport { tileGeometry, drawTileShapes, tileSize } from './tileGeometry';\nimport type { TilePatternSpec } from '../../core/paint-types';\nimport type { TextureHandle } from '../../renderer/textures/registerTexture';\n\nfunction build(spec: TilePatternSpec): TextureHandle | null {\n const geometry = tileGeometry(spec);\n return createTilePattern({\n size: tileSize(spec),\n draw: (oc) => drawTileShapes(oc, geometry),\n });\n}\n\n/** Diagonal hatch (forward slash). */\nexport interface HatchParams {\n color: string;\n size?: number;\n lineWidth?: number;\n}\n\nexport function hatch(params: HatchParams): TextureHandle | null {\n return build({ tile: 'hatch', ...params });\n}\n\n/** Diagonal hatch in both directions. */\nexport interface CrosshatchParams {\n color: string;\n size?: number;\n lineWidth?: number;\n}\n\nexport function crosshatch(params: CrosshatchParams): TextureHandle | null {\n return build({ tile: 'crosshatch', ...params });\n}\n\n/** Regular grid of filled dots. */\nexport interface DotsParams {\n color: string;\n size?: number;\n radius?: number;\n}\n\nexport function dots(params: DotsParams): TextureHandle | null {\n return build({ tile: 'dots', ...params });\n}\n\n/**\n * Random scatter of small ellipses on top of a solid background. Driven by a\n * seeded PRNG so the same `seed` produces a deterministic tile.\n *\n * Note: the `bg` field is optional — omit it for a transparent background\n * (the scatter shapes draw directly onto whatever sits beneath the overlay).\n */\nexport interface ChunksParams {\n color: string;\n bg?: string;\n size?: number;\n /** Coverage: `chunks * chunkSize²` per `size²` tile. Range ~[0, 1]. */\n density?: number;\n chunkSize?: number;\n seed?: number;\n}\n\nexport function chunks(params: ChunksParams): TextureHandle | null {\n return build({ tile: 'chunks', ...params });\n}\n"]}
|