canvas-can-do 0.1.9 → 0.1.13

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 (39) hide show
  1. package/README.md +405 -27
  2. package/dist/{SharedSystems-CZrQpXWg.js → SharedSystems-Cg8-nEUA.js} +2 -2
  3. package/dist/{WebGLRenderer-guxg9y4k.js → WebGLRenderer-CWOX7V4e.js} +3 -3
  4. package/dist/{WebGPURenderer-v9P1o84e.js → WebGPURenderer-pdpNSHly.js} +3 -3
  5. package/dist/{browserAll-CKZpLV_L.js → browserAll-D358sNiQ.js} +2 -2
  6. package/dist/canvas-can-do.js +1 -1
  7. package/dist/canvas-can-do.umd.cjs +110 -110
  8. package/dist/{colorToUniform-DOf21nfM.js → colorToUniform-Dy_GZxOz.js} +1 -1
  9. package/dist/{index-D_NFBR4n.js → index-CbUjW4XO.js} +5361 -3842
  10. package/dist/types/PointerController.d.ts +30 -0
  11. package/dist/types/PointerController.d.ts.map +1 -1
  12. package/dist/types/core/export/exportSettings.d.ts +25 -0
  13. package/dist/types/core/export/exportSettings.d.ts.map +1 -0
  14. package/dist/types/core/fonts/fontOptions.d.ts +8 -0
  15. package/dist/types/core/fonts/fontOptions.d.ts.map +1 -0
  16. package/dist/types/core/history/HistoryManager.d.ts +21 -1
  17. package/dist/types/core/history/HistoryManager.d.ts.map +1 -1
  18. package/dist/types/core/layers/LayerHierarchy.d.ts.map +1 -1
  19. package/dist/types/core/nodes/BaseNode.d.ts +3 -2
  20. package/dist/types/core/nodes/BaseNode.d.ts.map +1 -1
  21. package/dist/types/core/nodes/FrameNode.d.ts +42 -0
  22. package/dist/types/core/nodes/FrameNode.d.ts.map +1 -0
  23. package/dist/types/core/nodes/ImageNode.d.ts.map +1 -1
  24. package/dist/types/core/nodes/LineNode.d.ts.map +1 -1
  25. package/dist/types/core/nodes/TextNode.d.ts.map +1 -1
  26. package/dist/types/core/nodes/index.d.ts +1 -0
  27. package/dist/types/core/nodes/index.d.ts.map +1 -1
  28. package/dist/types/core/selection/LineTransformController.d.ts +1 -0
  29. package/dist/types/core/selection/LineTransformController.d.ts.map +1 -1
  30. package/dist/types/core/selection/SelectionManager.d.ts +27 -2
  31. package/dist/types/core/selection/SelectionManager.d.ts.map +1 -1
  32. package/dist/types/core/selection/TransformController.d.ts +1 -0
  33. package/dist/types/core/selection/TransformController.d.ts.map +1 -1
  34. package/dist/types/events.d.ts +1 -0
  35. package/dist/types/events.d.ts.map +1 -1
  36. package/dist/types/index.d.ts +163 -17
  37. package/dist/types/index.d.ts.map +1 -1
  38. package/dist/{webworkerAll-B_02fub1.js → webworkerAll-EieaH4C5.js} +2 -2
  39. package/package.json +3 -3
package/README.md CHANGED
@@ -21,12 +21,13 @@ app.useTool('select');
21
21
 
22
22
  ## Key Features
23
23
 
24
+ - Frame creation: via API (`addFrame`) and drag-to-draw frame tool (`useTool('frame')` / `F`)
24
25
  - Shapes: rectangle, ellipse, line, star, text, image
25
26
  - Transform tools: move, resize, rotate, multi-select
26
27
  - Shift to constrain resize ratio
27
28
  - Undo/redo (Ctrl/Cmd+Z, Ctrl/Cmd+Shift+Z, Ctrl/Cmd+Y)
28
- - Export: PNG/JPG/SVG (all objects or selection)
29
- - Save/Load: JSON with embedded image data URLs
29
+ - Export: PNG/JPG/SVG via node-linked presets
30
+ - Save/Load: JSON with embedded image data URLs + document export preset store
30
31
  - Rulers with pan/zoom indicators
31
32
 
32
33
  ## API Highlights
@@ -34,47 +35,424 @@ app.useTool('select');
34
35
  ```ts
35
36
  // Tools
36
37
  app.useTool('rectangle');
37
-
38
- // Export raster (PNG/JPG)
39
- const png = await app.exportRaster({ type: 'png', scope: 'all' });
40
-
41
- // Export SVG (embed images)
42
- const svg = await app.exportSVG({
43
- scope: 'selection',
44
- imageEmbed: 'display', // 'original' | 'display' | 'max'
45
- imageMaxEdge: 2048,
46
- });
38
+ app.useTool('frame'); // drag to draw a frame
47
39
 
48
40
  // Save/Load JSON (embedded images)
49
41
  const doc = await app.exportJSON();
50
42
  if (doc) await app.importJSON(doc);
51
43
 
44
+ // Frames
45
+ const frame = await app.addFrame({
46
+ name: 'Frame 1',
47
+ width: 1280,
48
+ height: 720,
49
+ backgroundColor: '#ffffff',
50
+ clipContent: true,
51
+ });
52
+ const frames = app.getFrames();
53
+
54
+ // Document export preset store linked to node ids (persisted in exportJSON/importJSON)
55
+ const preset = await app.addExportSetting(frame!.id, {
56
+ format: 'png',
57
+ scale: 2,
58
+ suffix: '@2x',
59
+ });
60
+ const asset = preset ? await app.exportNodeByPreset(frame!.id, preset.id) : null;
61
+ if (asset?.contentType === 'dataUrl') {
62
+ // asset.content => data URL
63
+ }
64
+
52
65
  // Access Pixi Application
53
66
  const pixiApp = app.getPixiApp();
67
+
68
+ // Layers (for external layer panel UIs)
69
+ const flatLayers = app.getFlatLayers({ recursive: true, topFirst: true });
70
+ const canMove = app.canMoveLayers(['node-a'], 'node-b', 'before');
71
+ if (canMove.ok) {
72
+ await app.moveLayers(['node-a'], 'node-b', 'before');
73
+ }
54
74
  ```
55
75
 
56
- ## Export Options
76
+ ## Layer Reordering API
77
+
78
+ Use this API when your layer panel UI lives outside this library and you need a stable, id-based way to reorder layers and move nodes in/out of groups.
79
+
80
+ ### Goals
81
+
82
+ - Keep UI code decoupled from Pixi internals
83
+ - Support reorder and reparent in one atomic operation
84
+ - Preserve visual placement when moving across parents/groups
85
+ - Keep undo/redo clean (`1 drop = 1 history entry`)
86
+
87
+ ### Read Layers
57
88
 
58
89
  ```ts
59
- // Raster
60
- exportRaster({
61
- type: 'png' | 'jpg',
62
- scope: 'all' | 'selection',
63
- quality?: number, // for JPG
64
- padding?: number, // extra pixels around bounds
65
- background?: string, // e.g. '#ffffff'
90
+ const layers = app.getFlatLayers({
91
+ parentId: null, // null = root object layer
92
+ recursive: true, // include descendants
93
+ topFirst: true, // top-most first (panel-friendly)
66
94
  });
95
+ ```
96
+
97
+ Each item includes:
98
+
99
+ - `id`, `type`, `name`
100
+ - `parentId`, `depth`
101
+ - `zIndex`
102
+ - `isGroup`, `childCount`
103
+ - `visible`, `locked`
104
+
105
+ ### Move Semantics
106
+
107
+ Position values:
108
+
109
+ - `'before'`: insert source before target in target's parent
110
+ - `'after'`: insert source after target in target's parent
111
+ - `'inside'`: insert source into target (target must be a group or frame)
112
+
113
+ Helpers:
114
+
115
+ ```ts
116
+ const checkOne = app.canMoveLayer(sourceId, targetId, 'before');
117
+ const checkMany = app.canMoveLayers(sourceIds, targetId, 'inside');
118
+
119
+ if (checkMany.ok) {
120
+ await app.moveLayers(sourceIds, targetId, 'inside');
121
+ }
122
+ ```
123
+
124
+ Write methods:
125
+
126
+ - `moveLayer(sourceId, targetId, position, options?)`
127
+ - `moveLayers(sourceIds, targetId, position, options?)`
128
+
129
+ Options:
130
+
131
+ - `recordHistory?: boolean` (default `true`)
132
+
133
+ ### Validation Rules
134
+
135
+ Move is rejected (`ok: false`) when:
136
+
137
+ - source/target ids are invalid
138
+ - source and target are the same node
139
+ - `position === 'inside'` but target is not a group/frame
140
+ - source node is locked
141
+ - destination parent is locked
142
+ - move would create a parent/child cycle (ancestor into descendant)
143
+ - moving a frame into non-root parent (frames are root-only)
144
+
145
+ ### Atomic Move Behavior
67
146
 
68
- // SVG
69
- exportSVG({
70
- scope: 'all' | 'selection',
71
- padding?: number,
72
- background?: string,
73
- imageEmbed?: 'original' | 'display' | 'max',
74
- imageMaxEdge?: number,
147
+ `moveLayer(s)` performs one transaction-like operation:
148
+
149
+ 1. Validate request
150
+ 2. Normalize source list (avoid parent+child duplicate moves)
151
+ 3. Resolve insertion index
152
+ 4. Capture each source node world transform
153
+ 5. Reparent/reorder
154
+ 6. Re-apply transform in destination parent space (so node does not jump)
155
+ 7. Emit `layer:changed`
156
+ 8. Capture history (unless `recordHistory: false`)
157
+
158
+ This is what enables: selecting an item inside a group, dragging it above an external layer, and having it both leave the group and land at the correct z-order in one drop.
159
+
160
+ ### Typical External UI Flow
161
+
162
+ ```ts
163
+ // 1) render panel from library state
164
+ const layers = app.getFlatLayers({ recursive: true, topFirst: true });
165
+
166
+ // 2) while dragging, probe validity
167
+ const probe = app.canMoveLayers(dragSourceIds, hoverTargetId, hoverPosition);
168
+ showDropIndicator(probe.ok);
169
+
170
+ // 3) on drop, commit once
171
+ if (probe.ok) {
172
+ await app.moveLayers(dragSourceIds, hoverTargetId, hoverPosition);
173
+ }
174
+
175
+ // 4) listen and re-render
176
+ app.addEventListener('layer:changed', () => {
177
+ rerenderPanel(app.getFlatLayers({ recursive: true, topFirst: true }));
75
178
  });
76
179
  ```
77
180
 
181
+ ## Frame Concept (Figma-like)
182
+
183
+ `Frame` is different from `Group`.
184
+
185
+ - `Group`: logical grouping for transforming multiple nodes together
186
+ - `Frame`: a bounded working area with optional background and clipping
187
+
188
+ Think of `Frame` as an artboard/container that can also be used as an export boundary.
189
+
190
+ ### Frame Behavior
191
+
192
+ - Frame is **root-only**:
193
+ - cannot be grouped
194
+ - cannot be child of group/frame
195
+ - Can contain child nodes (like a container)
196
+ - Has explicit `width` and `height`
197
+ - Supports background color or transparent background
198
+ - Supports clipping/masking at frame bounds (`clipContent`)
199
+ - Can be target of drag/drop reparent operations (`inside`)
200
+ - Can be used as export target node for preset-based export
201
+
202
+ ### Drawing and Moving In/Out of Frame
203
+
204
+ - Frame can be created by API (`addFrame`) or drag tool (`frame` / `F`)
205
+ - Drawing non-frame shapes starts in the frame under pointer (if any), otherwise root canvas
206
+ - Drag/drop can move nodes into a frame (`inside`) or out of a frame (`before`/`after` against external target)
207
+ - Reparent + z-order update happen in one atomic operation
208
+ - World transform is preserved when reparenting so nodes do not visually jump
209
+ - Auto drag-reparent is blocked for group-managed nodes (group or descendants of group)
210
+
211
+ ### Canvas Presentation (Editor Visual)
212
+
213
+ Frame should look visibly different from regular objects so users can immediately identify it as a working boundary.
214
+
215
+ - Visible frame border at all times (scale-aware stroke)
216
+ - Frame name label near top-left corner
217
+ - Optional background fill (or transparent mode)
218
+ - Clear visual cue when clipping is enabled
219
+ - Distinct `idle`, `hover`, `selected`, and `drop-target` states
220
+
221
+ Recommended editor-only rendering split:
222
+
223
+ - `FrameNode` for document content (background + children + clip)
224
+ - `FrameOverlay` for editor cues (border, label, highlight, drop indicator)
225
+
226
+ This keeps export output clean while still giving strong authoring feedback on canvas.
227
+
228
+ ### Suggested Frame Visual States
229
+
230
+ - `idle`: neutral border, subtle label
231
+ - `hover`: stronger border to indicate targetability
232
+ - `selected`: accent border + resize handles + prominent label
233
+ - `drop-target`: temporary insertion highlight while dragging
234
+
235
+ ### Export Semantics
236
+
237
+ - Support exporting by frame id (raster/SVG)
238
+ - If `clipContent=true`, export respects frame bounds
239
+ - If transparent background is selected, exported background remains transparent
240
+
241
+ ### Suggested API Surface
242
+
243
+ ```ts
244
+ // creation / query
245
+ const frame = await app.addFrame({
246
+ name: 'Frame 1',
247
+ x: 100,
248
+ y: 80,
249
+ width: 1280,
250
+ height: 720,
251
+ backgroundColor: '#ffffff', // null for transparent
252
+ clipContent: true,
253
+ });
254
+
255
+ const frames = app.getFrames();
256
+
257
+ // export by preset
258
+ const pngPreset = await app.addExportSetting(frame.id, { format: 'png', scale: 1, suffix: '' });
259
+ const pngAsset = pngPreset ? await app.exportNodeByPreset(frame.id, pngPreset.id) : null;
260
+ ```
261
+
262
+ ## Export Presets (Figma-like)
263
+
264
+ Presets are stored in a centralized document-level registry (`exportStore`) and linked to nodes by id.
265
+ This keeps lookup/edit fast and avoids recursive node scans.
266
+
267
+ ```ts
268
+ type NodeExportPreset = {
269
+ id: string;
270
+ format: 'png' | 'jpg' | 'svg';
271
+ scale: number;
272
+ suffix: string; // e.g. '', '@2x'
273
+ quality?: number; // jpg
274
+ padding?: number;
275
+ backgroundMode?: 'auto' | 'transparent' | 'solid';
276
+ backgroundColor?: string; // used when backgroundMode = 'solid'
277
+ imageEmbed?: 'original' | 'display' | 'max'; // svg
278
+ imageMaxEdge?: number; // svg
279
+ };
280
+ ```
281
+
282
+ ### Preset APIs
283
+
284
+ ```ts
285
+ // add preset and link to node
286
+ const added = await app.addExportSetting(nodeId, {
287
+ format: 'png',
288
+ scale: 1,
289
+ suffix: '',
290
+ });
291
+
292
+ // get preset entity by id
293
+ const preset = app.getExportSettingById(added!.id);
294
+
295
+ // edit preset entity
296
+ await app.editExportSetting(added!.id, {
297
+ scale: 2,
298
+ suffix: '@2x',
299
+ });
300
+
301
+ // list preset ids linked to a node
302
+ const presetIds = app.getExportSettingIds(nodeId);
303
+
304
+ // list all presets in document (without scanning nodes manually)
305
+ const allPresets = app.getAllExportSettings();
306
+ // [{ id, preset, linkedNodeIds }]
307
+
308
+ // inspect linked nodes before editing shared presets
309
+ const usedBy = app.getExportPresetUsage(preset!.id);
310
+
311
+ // export one node using its preset
312
+ const asset = await app.exportNodeByPreset(nodeId, preset!.id);
313
+ if (asset) {
314
+ // asset.filename, asset.mimeType, asset.contentType, asset.content
315
+ }
316
+
317
+ // export many nodes in one call
318
+ const frameAPreset = await app.addExportSetting(frameA, { format: 'png', scale: 1, suffix: '' });
319
+ const frameBPreset = await app.addExportSetting(frameB, { format: 'svg', scale: 1, suffix: '' });
320
+ const assets = await app.exportNodesByPreset([
321
+ { nodeId: frameA, presetId: frameAPreset!.id },
322
+ { nodeId: frameB, presetId: frameBPreset!.id },
323
+ ]);
324
+
325
+ // delete preset entity (and unlink from all nodes)
326
+ await app.deleteExportSetting(added!.id);
327
+ ```
328
+
329
+ ## Export Contract
330
+
331
+ Preset-first only:
332
+
333
+ - Create preset via `addExportSetting(nodeId, preset)`
334
+ - Edit/delete via `editExportSetting` / `deleteExportSetting`
335
+ - Export only via `exportNodeByPreset(nodeId, presetId)` or `exportNodesByPreset(...)`
336
+ - `presetId` must be explicitly provided and linked to that node
337
+
338
+ Format behavior:
339
+
340
+ - `jpg` should use opaque background (`backgroundMode: 'solid'`, `backgroundColor`)
341
+ - `png` / `svg` can keep transparency with `backgroundMode: 'auto'` or `'transparent'`
342
+
343
+ ## Save/Load Contract (Revision)
344
+
345
+ This section defines the document model expectations after adding frames and expanded layer behavior.
346
+
347
+ ### Document Goals
348
+
349
+ - Preserve exact hierarchy (parent/child + order).
350
+ - Preserve per-node transform and visibility/locking.
351
+ - Preserve frame-specific properties and behavior.
352
+ - Enforce frame root-only invariant on import/restore.
353
+
354
+ ### Required Frame Fields (logical model)
355
+
356
+ - geometry: `x`, `y`, `width`, `height`
357
+ - transform: `rotation` (currently fixed to 0 by interaction), `scale`
358
+ - visibility/state: `visible`, `locked`
359
+ - frame style: `backgroundColor`
360
+ - frame behavior: `clipContent`
361
+ - hierarchy: `children[]` in stable z-order
362
+
363
+ ### Round-trip Invariants
364
+
365
+ After `exportJSON -> importJSON`:
366
+
367
+ - node count and hierarchy must match
368
+ - z-order must match
369
+ - frame bounds/style/clip settings must match
370
+ - locked/visible state must match
371
+ - export output for same node + preset should remain equivalent
372
+ - frame never appears as a child of group/frame after import normalization
373
+
374
+ ### Versioning and Migration
375
+
376
+ - Current baseline is `document.version = 1` only.
377
+ - Keep schema simple while not in production.
378
+ - If schema changes later, introduce migrations in the next version.
379
+
380
+ Import normalization defaults for frame fields:
381
+
382
+ - `backgroundColor = '#ffffff'`
383
+ - `clipContent = true`
384
+
385
+ ### Server Persistence Flow
386
+
387
+ Use `exportJSON()` as the payload to your backend.
388
+ This payload now includes `exportStore` (preset registry + node links), so loading back with `importJSON()` restores export presets too.
389
+
390
+ ```ts
391
+ // save
392
+ const doc = await app.exportJSON();
393
+ await fetch('/api/documents/123', {
394
+ method: 'PUT',
395
+ headers: { 'content-type': 'application/json' },
396
+ body: JSON.stringify(doc),
397
+ });
398
+
399
+ // load
400
+ const loaded = await fetch('/api/documents/123').then((r) => r.json());
401
+ await app.importJSON(loaded);
402
+ ```
403
+
404
+ ### Round-trip (including export presets)
405
+
406
+ After `exportJSON -> save to server -> load from server -> importJSON`:
407
+
408
+ - node hierarchy/order must match
409
+ - frame properties must match
410
+ - export registry + node links must match (`id/format/scale/suffix/...`)
411
+ - exporting the same node + preset should produce equivalent output
412
+
413
+ ### Post-change Checklist
414
+
415
+ - Verify preset-based export for PNG/JPG/SVG on target nodes.
416
+ - Verify frame with `clipContent` on/off.
417
+ - Verify frame remains root-only after save/load.
418
+ - Verify lock/visible states survive save/load.
419
+ - Verify undo/redo still works immediately after load.
420
+
421
+ ## Interaction Policy
422
+
423
+ - Group-first hit test: pointer hover/click on a group or any descendant selects the group.
424
+ - Frame-child-first hit test: inside frame, children are preferred over selecting frame body.
425
+ - Frame body selection is intentionally disabled on canvas hit-test; select frame via label or layer/API.
426
+ - Layer panel/API can still select specific child ids directly (`selectNodeById` / `selectNodesById`).
427
+
428
+ ## UI Recommendation (Figma-like Export)
429
+
430
+ Suggested UX in the right sidebar when 1 node is selected:
431
+
432
+ 1. Section title: `Export`
433
+ 2. List rows: one row per preset (`PNG 1x`, `PNG 2x`, `SVG`)
434
+ 3. Each row editable: `format`, `scale`, `suffix`, advanced options
435
+ 4. Row actions: duplicate / delete preset
436
+ 5. Primary button: `Export <NodeName>` (export selected preset)
437
+ 6. Secondary button: `Export All` (all presets for current node)
438
+
439
+ Suggested UI behavior:
440
+
441
+ - Auto-save preset edits immediately via `addExportSetting` / `editExportSetting` / `deleteExportSetting`
442
+ - Keep preset `id` stable; use `id` for persistence and updates (shared ids = shared edits)
443
+ - Export requires explicit `presetId` linked to that node (no implicit fallback preset)
444
+ - Show final filename preview from `name + suffix + extension`
445
+ - When exporting multiple selected nodes, call `exportNodesByPreset`
446
+
447
+ ## Implementation Guide
448
+
449
+ 1. Add an `ExportPanel` in your inspector that reads `getAllExportSettings()` for document-level preset list, and `getExportSettingIds(nodeId)` for per-node links.
450
+ 2. Bind form fields to preset objects and debounce writes to `editExportSetting`.
451
+ 3. On export click, call `exportNodeByPreset(nodeId, presetId)`.
452
+ 4. If `asset.contentType === 'dataUrl'`, download with anchor `href = dataUrl`.
453
+ 5. If `asset.contentType === 'text'` (SVG), create `Blob([asset.content], { type: asset.mimeType })`.
454
+ 6. For batch export, call `exportNodesByPreset` then zip/download in your app shell.
455
+
78
456
  ## Events
79
457
 
80
458
  ```ts
@@ -1,5 +1,5 @@
1
- import { x as Oe, n as ie, M as g, G as Fe, a as Le, y as oe, E as u, e as F, z as w, F as He, H as L, I as y, R as H, J as le, K as We, v as m, d as f, k as G, w as W, L as X, N as ze, h as Q, B as k, l as A, O as Ve, u as M, m as S, Q as P, V as Ne, b as je, W as ue, X as de, Y as ce, Z as he, C as U, _ as qe, $ as I, a0 as Z, D as z, a1 as $e, a2 as Ke, P as Ye, i as Je, T as ee, a3 as te, a4 as v, a5 as Xe, a6 as Qe } from "./index-D_NFBR4n.js";
2
- import { F as Ze, S as et, B as fe, c as tt } from "./colorToUniform-DOf21nfM.js";
1
+ import { x as Oe, n as ie, M as g, G as Fe, a as Le, y as oe, E as u, e as F, z as w, F as He, H as L, I as y, R as H, J as le, K as We, v as m, d as f, k as G, w as W, L as X, N as ze, h as Q, B as k, l as A, O as Ve, u as M, m as S, Q as P, V as Ne, b as je, W as ue, X as de, Y as ce, Z as he, C as U, _ as qe, $ as I, a0 as Z, D as z, a1 as $e, a2 as Ke, P as Ye, i as Je, T as ee, a3 as te, a4 as v, a5 as Xe, a6 as Qe } from "./index-CbUjW4XO.js";
2
+ import { F as Ze, S as et, B as fe, c as tt } from "./colorToUniform-Dy_GZxOz.js";
3
3
  var rt = `in vec2 vMaskCoord;
4
4
  in vec2 vTextureCoord;
5
5
 
@@ -1,6 +1,6 @@
1
- import { E as d, c as G, B as T, w as m, D as S, L as K, a as Be, S as U, v as b, a7 as Ae, m as $, a8 as Ne, d as p, Q as w, l as B, k as A, n as F, M as z, a9 as Y, aa as ye, ab as q, ac as Ce, ad as De, A as Ie, R as Ge, e as v } from "./index-D_NFBR4n.js";
2
- import { S as O, b as Z } from "./colorToUniform-DOf21nfM.js";
3
- import { e as Ue, G as Fe, c as Oe, b as Pe, U as Me, R as Le, B as Q, d as N, f as we, S as He, a as ke } from "./SharedSystems-CZrQpXWg.js";
1
+ import { E as d, c as G, B as T, w as m, D as S, L as K, a as Be, S as U, v as b, a7 as Ae, m as $, a8 as Ne, d as p, Q as w, l as B, k as A, n as F, M as z, a9 as Y, aa as ye, ab as q, ac as Ce, ad as De, A as Ie, R as Ge, e as v } from "./index-CbUjW4XO.js";
2
+ import { S as O, b as Z } from "./colorToUniform-Dy_GZxOz.js";
3
+ import { e as Ue, G as Fe, c as Oe, b as Pe, U as Me, R as Le, B as Q, d as N, f as we, S as He, a as ke } from "./SharedSystems-Cg8-nEUA.js";
4
4
  class J {
5
5
  constructor() {
6
6
  this._tempState = O.for2d(), this._didUploadHash = {};
@@ -1,6 +1,6 @@
1
- import { g as E, E as f, c as L, u as ue, f as ce, D as P, d as v, B as T, h as de, i as A, j as M, w as C, k as x, l as he, m as pe, n as D, o as w, M as k, p as z, q as le, s as F, t as fe, S as I, v as R, A as ge, R as me, e as B } from "./index-D_NFBR4n.js";
2
- import { S as O, l as _e, a as be } from "./colorToUniform-DOf21nfM.js";
3
- import { c as xe, u as ye, U as Ge, B as Pe, G as Be, e as Se, R as Te, t as ve, S as Ce, a as Ue } from "./SharedSystems-CZrQpXWg.js";
1
+ import { g as E, E as f, c as L, u as ue, f as ce, D as P, d as v, B as T, h as de, i as A, j as M, w as C, k as x, l as he, m as pe, n as D, o as w, M as k, p as z, q as le, s as F, t as fe, S as I, v as R, A as ge, R as me, e as B } from "./index-CbUjW4XO.js";
2
+ import { S as O, l as _e, a as be } from "./colorToUniform-Dy_GZxOz.js";
3
+ import { c as xe, u as ye, U as Ge, B as Pe, G as Be, e as Se, R as Te, t as ve, S as Ce, a as Ue } from "./SharedSystems-Cg8-nEUA.js";
4
4
  const y = O.for2d();
5
5
  class W {
6
6
  start(e, t, r) {
@@ -1,5 +1,5 @@
1
- import { T as M, U as Z, P as m, r as te, E as y, b as ie, w as g, e as P, C as V } from "./index-D_NFBR4n.js";
2
- import "./webworkerAll-B_02fub1.js";
1
+ import { T as M, U as Z, P as m, r as te, E as y, b as ie, w as g, e as P, C as V } from "./index-CbUjW4XO.js";
2
+ import "./webworkerAll-EieaH4C5.js";
3
3
  class q {
4
4
  constructor(e) {
5
5
  this._lastTransform = "", this._observer = null, this._tickerAttached = !1, this.updateTranslation = () => {
@@ -1,4 +1,4 @@
1
- import { as as o, at as p, au as r } from "./index-D_NFBR4n.js";
1
+ import { as as o, at as p, au as r } from "./index-CbUjW4XO.js";
2
2
  export {
3
3
  o as CCDApp,
4
4
  p as TOOL_CURSOR,