@snowcone-app/canvas 0.29.0 → 0.31.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 (92) hide show
  1. package/ERROR_CONTRACT.md +13 -0
  2. package/STYLING_CONTRACT.md +2 -2
  3. package/dist/{CanvasRenderer-_lFoIoz5.js → CanvasRenderer-hpJ05JGO.js} +4 -4
  4. package/dist/{CanvasRenderer-_lFoIoz5.js.map → CanvasRenderer-hpJ05JGO.js.map} +1 -1
  5. package/dist/{CanvasStateV1-BMxr6xb8.js → CanvasStateV1-jLOibojY.js} +876 -844
  6. package/dist/{CanvasStateV1-BMxr6xb8.js.map → CanvasStateV1-jLOibojY.js.map} +1 -1
  7. package/dist/ContextualToolbars-DRbuUE7W.js +6061 -0
  8. package/dist/ContextualToolbars-DRbuUE7W.js.map +1 -0
  9. package/dist/{EditorCanvasImpl-BNz8TPFs.js → EditorCanvasImpl-P2GHPNA3.js} +19 -20
  10. package/dist/{EditorCanvasImpl-BNz8TPFs.js.map → EditorCanvasImpl-P2GHPNA3.js.map} +1 -1
  11. package/dist/{ExportManager-B8Td7uR5.js → ExportManager-Bkzzyxgw.js} +973 -576
  12. package/dist/ExportManager-Bkzzyxgw.js.map +1 -0
  13. package/dist/{FontAnalyzer-D4Sg-P6_.js → FontAnalyzer-BYhwxDhe.js} +542 -477
  14. package/dist/FontAnalyzer-BYhwxDhe.js.map +1 -0
  15. package/dist/{ImagePanel-CN2Bu3hf.js → ImagePanel-CEr0_FYy.js} +38 -38
  16. package/dist/{ImagePanel-CN2Bu3hf.js.map → ImagePanel-CEr0_FYy.js.map} +1 -1
  17. package/dist/SnowconeCanvas-Fa0isFpO.js +1192 -0
  18. package/dist/SnowconeCanvas-Fa0isFpO.js.map +1 -0
  19. package/dist/advanced.mjs +14 -14
  20. package/dist/api/embed.d.ts +2 -0
  21. package/dist/api/stable.d.ts +2 -0
  22. package/dist/components/CanvasContextMenu.d.ts +15 -0
  23. package/dist/components/CanvasEditor/hooks/useCanvasInteraction.d.ts +27 -0
  24. package/dist/components/CanvasEditor.d.ts +8 -0
  25. package/dist/components/ImageToolbar.d.ts +4 -0
  26. package/dist/components/embed/SnowconeCanvas.d.ts +13 -0
  27. package/dist/components/embed/kernel.d.ts +8 -0
  28. package/dist/components/toolbars/EmbeddedToolbarLayout.d.ts +2 -0
  29. package/dist/components/toolbars/SecondaryPanels.d.ts +17 -1
  30. package/dist/components/toolbars/index.d.ts +2 -2
  31. package/dist/components/ui/SliderRow.d.ts +6 -0
  32. package/dist/components/ui/icons.d.ts +2 -0
  33. package/dist/components/ui/toolbar-button.d.ts +2 -2
  34. package/dist/contexts/CanvasServicesContext.d.ts +17 -0
  35. package/dist/contexts/EditorContext.d.ts +7 -0
  36. package/dist/core/image-adjustments.d.ts +32 -0
  37. package/dist/{custom-icons-B5TRC1Ed.js → custom-icons-Co4rcW0S.js} +7 -7
  38. package/dist/{custom-icons-B5TRC1Ed.js.map → custom-icons-Co4rcW0S.js.map} +1 -1
  39. package/dist/design-builder-CBG2hKc8.js +1672 -0
  40. package/dist/design-builder-CBG2hKc8.js.map +1 -0
  41. package/dist/{embed-BTRtoktw.js → embed-D4TIzO7g.js} +20 -20
  42. package/dist/{embed-BTRtoktw.js.map → embed-D4TIzO7g.js.map} +1 -1
  43. package/dist/embed.mjs +51 -46
  44. package/dist/embed.mjs.map +1 -1
  45. package/dist/errors/editorError.d.ts +8 -0
  46. package/dist/{guards-uQtEQJbs.js → guards-DgZuwVgu.js} +2 -2
  47. package/dist/{guards-uQtEQJbs.js.map → guards-DgZuwVgu.js.map} +1 -1
  48. package/dist/hooks/elementPatch.d.ts +7 -2
  49. package/dist/hooks/useKeyboardShortcuts.d.ts +15 -2
  50. package/dist/hooks/useLayers.d.ts +2 -0
  51. package/dist/index.mjs +57 -52
  52. package/dist/index.mjs.map +1 -1
  53. package/dist/internals.mjs +201 -132
  54. package/dist/internals.mjs.map +1 -1
  55. package/dist/rendering/element-painters.d.ts +0 -13
  56. package/dist/rendering/element-serializer.d.ts +3 -1
  57. package/dist/rendering/image-adjustments.d.ts +24 -0
  58. package/dist/rendering/renderer-types.d.ts +8 -1
  59. package/dist/state/CanvasStateV1.d.ts +36 -3
  60. package/dist/state/index.d.ts +2 -2
  61. package/dist/template-fields-CvFcr5zy.js +505 -0
  62. package/dist/template-fields-CvFcr5zy.js.map +1 -0
  63. package/dist/testing.mjs +46 -47
  64. package/dist/testing.mjs.map +1 -1
  65. package/dist/types/index.d.ts +21 -0
  66. package/dist/{UnifiedFontService-CgYnYTj7.js → useCommands-bPXY9rCh.js} +2429 -2145
  67. package/dist/useCommands-bPXY9rCh.js.map +1 -0
  68. package/dist/{usePieceGuideBundle-CTQszfKA.js → usePieceGuideBundle-Bj98nPk0.js} +2 -2
  69. package/dist/{usePieceGuideBundle-CTQszfKA.js.map → usePieceGuideBundle-Bj98nPk0.js.map} +1 -1
  70. package/dist/utils/custom-fonts.d.ts +99 -0
  71. package/dist/utils/featureApplied.d.ts +2 -0
  72. package/dist/validation-CsTlSvJJ.js +8686 -0
  73. package/dist/validation-CsTlSvJJ.js.map +1 -0
  74. package/dist/workers/export-protocol.d.ts +13 -0
  75. package/dist/workers/export-worker.bundle.string.d.ts +1 -1
  76. package/example/package.json +1 -1
  77. package/package.json +1 -1
  78. package/dist/ContextualToolbars-0jWvnQgp.js +0 -5833
  79. package/dist/ContextualToolbars-0jWvnQgp.js.map +0 -1
  80. package/dist/ExportManager-B8Td7uR5.js.map +0 -1
  81. package/dist/FontAnalyzer-D4Sg-P6_.js.map +0 -1
  82. package/dist/SnowconeCanvas-CR_LdRFP.js +0 -1173
  83. package/dist/SnowconeCanvas-CR_LdRFP.js.map +0 -1
  84. package/dist/UnifiedFontService-CgYnYTj7.js.map +0 -1
  85. package/dist/design-builder-COj0zkxu.js +0 -470
  86. package/dist/design-builder-COj0zkxu.js.map +0 -1
  87. package/dist/editorErrors-CCvoKj_P.js +0 -1219
  88. package/dist/editorErrors-CCvoKj_P.js.map +0 -1
  89. package/dist/template-fields-BLRp84Ny.js +0 -716
  90. package/dist/template-fields-BLRp84Ny.js.map +0 -1
  91. package/dist/validation-eCebhplp.js +0 -8402
  92. package/dist/validation-eCebhplp.js.map +0 -1
@@ -0,0 +1,1672 @@
1
+ import { jsx as k } from "react/jsx-runtime";
2
+ import { useContext as X, useSyncExternalStore as pe, useCallback as m, createContext as Q, useRef as pt, useState as b, useEffect as Dt, useMemo as q } from "react";
3
+ import { Z as Ae, E as ot, U as ye, am as ge, G as jt, an as xe, ao as be, ap as we, aq as Ee, ar as Se, c as Zt, C as Re, as as Ce, at as Ie, au as Te, O as Oe, X as Wt, I as ve, g as Fe, S as Pe, av as Ne, aw as Mt, y as ze, D as He, K as ke } from "./FontAnalyzer-BYhwxDhe.js";
4
+ const Jt = Q(null), Ue = () => () => {
5
+ }, Xt = () => 0;
6
+ function go() {
7
+ const e = X(Jt), t = pe(
8
+ e ? e.subscribe : Ue,
9
+ e ? e.getVersion : Xt,
10
+ e ? e.getVersion : Xt
11
+ );
12
+ return m(
13
+ (o) => !!(e && o && e.getBoundLayer(o)),
14
+ // `version` is the reactivity key: a registry change must mint a new
15
+ // callback so memoized consumers re-evaluate.
16
+ [e, t]
17
+ );
18
+ }
19
+ const gt = Zt("useCommandHistory");
20
+ function Ve(e, t, o, n) {
21
+ const i = pt(new Ae(o)), s = X(Jt), c = m(
22
+ (l, f) => {
23
+ const g = l == null ? void 0 : l.name;
24
+ if (!s || !g) return;
25
+ const y = s.getBoundLayer(g);
26
+ if (y)
27
+ throw new ot(
28
+ "E_BOUND_LAYER_MUTATION",
29
+ `cannot ${f} layer "${g}" — a mounted <${y.part} layer={design.layer("${g}")}> is bound to it. Unmount that field first, or keep the layer and set its text through the field / its binding instead.`,
30
+ { layer: g, part: y.part, operation: f, docSlug: "embed-mode" }
31
+ );
32
+ },
33
+ [s]
34
+ ), [r, d] = b({
35
+ canUndo: !1,
36
+ canRedo: !1,
37
+ // Per-artboard state for the active artboard
38
+ canUndoActiveArtboard: !1,
39
+ canRedoActiveArtboard: !1
40
+ }), a = m(() => {
41
+ const l = i.current, f = o.getActiveArtboardId();
42
+ d({
43
+ canUndo: l.canUndo(),
44
+ canRedo: l.canRedo(),
45
+ // Per-artboard state - only check active artboard's history
46
+ canUndoActiveArtboard: f ? l.canUndoArtboard(f) : !1,
47
+ canRedoActiveArtboard: f ? l.canRedoArtboard(f) : !1
48
+ });
49
+ }, [o]), z = m(
50
+ (l, f) => {
51
+ l && l.name !== f.name && c(l, "rename");
52
+ const g = new ye(
53
+ f.id,
54
+ l || null,
55
+ f,
56
+ (C) => {
57
+ t(($) => $.map((P) => P.id === C.id ? C : P));
58
+ }
59
+ ), y = o.getArtboardIdForElement(f.id);
60
+ if (y)
61
+ i.current.executeOnArtboard(y, g);
62
+ else {
63
+ const C = o.getActiveArtboardId();
64
+ C && i.current.executeOnArtboard(C, g);
65
+ }
66
+ a();
67
+ },
68
+ [t, o, a, c]
69
+ ), F = m(
70
+ (l, f, g, y) => {
71
+ const C = f || o.getActiveArtboardId();
72
+ if (!C) {
73
+ gt.warn("No active artboard to add element to");
74
+ return;
75
+ }
76
+ const $ = new ge(
77
+ l,
78
+ (P) => {
79
+ const U = P;
80
+ t((N) => {
81
+ if (y) {
82
+ const H = N.findIndex((O) => O.id === y);
83
+ if (H !== -1) {
84
+ const O = [...N];
85
+ return O.splice(H, 0, U), O;
86
+ }
87
+ }
88
+ if (g) {
89
+ const H = N.findIndex((O) => O.id === g);
90
+ if (H !== -1) {
91
+ const O = [...N];
92
+ return O.splice(H + 1, 0, U), O;
93
+ }
94
+ for (let O = 0; O < N.length; O++) {
95
+ const Y = N[O];
96
+ if (Y instanceof jt && Y.children) {
97
+ const rt = Y.children.findIndex((K) => K.id === g);
98
+ if (rt !== -1) {
99
+ const K = Y.clone();
100
+ K.children.splice(rt + 1, 0, U);
101
+ const G = [...N];
102
+ return G[O] = K, G;
103
+ }
104
+ }
105
+ }
106
+ }
107
+ return [...N, U];
108
+ }), o.addElementToArtboard(P.id, C);
109
+ },
110
+ (P) => {
111
+ t((U) => U.filter((N) => N.id !== P)), o.removeElementFromArtboard(P);
112
+ }
113
+ );
114
+ i.current.executeOnArtboard(C, $), a();
115
+ },
116
+ [t, o, a]
117
+ ), V = m(
118
+ (l) => {
119
+ c(l, "delete");
120
+ const f = o.getArtboardIdForElement(l.id);
121
+ if (!f) {
122
+ gt.warn("Element not found in any artboard");
123
+ return;
124
+ }
125
+ const g = new xe(
126
+ l,
127
+ (y) => {
128
+ t((C) => [...C, y]), o.addElementToArtboard(y.id, f);
129
+ },
130
+ (y) => {
131
+ t((C) => C.filter(($) => $.id !== y)), o.removeElementFromArtboard(y);
132
+ }
133
+ );
134
+ i.current.executeOnArtboard(f, g), a();
135
+ },
136
+ [t, o, a, c]
137
+ ), E = m(
138
+ (l) => {
139
+ const f = new be(l, o);
140
+ i.current.executeGlobal(f), a(), n == null || n();
141
+ },
142
+ [o, a, n]
143
+ ), D = m(
144
+ (l) => {
145
+ const f = new we(l, o);
146
+ i.current.executeGlobal(f), a(), n == null || n();
147
+ },
148
+ [o, a, n]
149
+ ), p = m(
150
+ (l, f, g) => {
151
+ const y = new Ee(l, f, g, o);
152
+ i.current.executeGlobal(y), a(), n == null || n();
153
+ },
154
+ [o, a, n]
155
+ ), h = m(
156
+ (l) => {
157
+ if (l.length === 0)
158
+ return;
159
+ const f = o.getActiveArtboardId();
160
+ if (!f) {
161
+ gt.warn("No active artboard for batch execution");
162
+ return;
163
+ }
164
+ const g = l.map((y) => new class extends Object {
165
+ execute() {
166
+ y.execute();
167
+ }
168
+ undo() {
169
+ y.undo();
170
+ }
171
+ }());
172
+ i.current.executeBatchOnArtboard(f, g), a();
173
+ },
174
+ [o, a]
175
+ ), S = m(() => {
176
+ i.current.undo() && (a(), n == null || n());
177
+ }, [a, n]), v = m(() => {
178
+ i.current.redo() && (a(), n == null || n());
179
+ }, [a, n]), R = m(() => {
180
+ const l = o.getActiveArtboardId();
181
+ l && i.current.undoArtboard(l) && (a(), n == null || n());
182
+ }, [o, a, n]), w = m(() => {
183
+ const l = o.getActiveArtboardId();
184
+ l && i.current.redoArtboard(l) && (a(), n == null || n());
185
+ }, [o, a, n]), L = m(() => {
186
+ i.current.clear(), a();
187
+ }, [a]), nt = m(
188
+ (l) => {
189
+ i.current.clearArtboardHistory(l), a();
190
+ },
191
+ [a]
192
+ ), _ = pt(null);
193
+ Dt(() => {
194
+ const l = o.getActiveArtboardId();
195
+ l !== _.current && (_.current = l, a());
196
+ });
197
+ const M = m(
198
+ (l, f, g) => {
199
+ const y = e.map((P) => P.id), C = o.getArtboardIdForElement(l);
200
+ if (!C) {
201
+ gt.warn("Element not found in any artboard");
202
+ return;
203
+ }
204
+ const $ = new Se(l, f, g, y, (P) => {
205
+ t((U) => {
206
+ const N = new Map(U.map((H) => [H.id, H]));
207
+ return P.map((H) => N.get(H)).filter(Boolean);
208
+ });
209
+ });
210
+ i.current.executeOnArtboard(C, $), a();
211
+ },
212
+ [e, t, o, a]
213
+ );
214
+ return {
215
+ // Element operations
216
+ executeElementUpdate: z,
217
+ executeAddElement: F,
218
+ executeRemoveElement: V,
219
+ executeReorderElement: M,
220
+ // Batch operations
221
+ executeCommandBatch: h,
222
+ // Artboard operations
223
+ executeCreateArtboard: E,
224
+ executeDeleteArtboard: D,
225
+ executeUpdateArtboard: p,
226
+ // Undo/redo (smart - considers last operation and active artboard)
227
+ undo: S,
228
+ redo: v,
229
+ // Undo/redo for active artboard only (element operations)
230
+ undoActiveArtboard: R,
231
+ redoActiveArtboard: w,
232
+ clearHistory: L,
233
+ clearArtboardHistory: nt,
234
+ // State (smart - considers last operation)
235
+ canUndo: r.canUndo,
236
+ canRedo: r.canRedo,
237
+ // State for active artboard only
238
+ canUndoActiveArtboard: r.canUndoActiveArtboard,
239
+ canRedoActiveArtboard: r.canRedoActiveArtboard,
240
+ historyManager: i.current
241
+ };
242
+ }
243
+ function dt(e) {
244
+ return e && "fontSize" in e && "color" in e && "fontFamily" in e;
245
+ }
246
+ function De(e, t) {
247
+ const [o, n] = b(32), [i, s] = b("#333333"), [c, r] = b("Arial"), [d, a] = b("center");
248
+ Dt(() => {
249
+ if (e && dt(e)) {
250
+ const p = e.transformType === "circle" && "getEffectiveFontSize" in e ? Math.round(e.getEffectiveFontSize()) : Math.round(e.fontSize), h = e.color, S = e.fontFamily, v = e.textAlign;
251
+ n((R) => R !== p ? p : R), s((R) => R !== h ? h : R), r((R) => R !== S ? S : R), a((R) => R !== v ? v : R);
252
+ }
253
+ }, [e]);
254
+ const z = m(
255
+ (p) => {
256
+ if (!e || !dt(e)) return;
257
+ const h = Math.max(Ce, Math.min(Ie, o + p));
258
+ n(h);
259
+ const S = e.clone();
260
+ S.transformType === "circle" && "setEffectiveFontSize" in S ? S.setEffectiveFontSize(h) : S.setFontSize(h), t(S);
261
+ },
262
+ [e, o, t]
263
+ ), F = m(
264
+ (p) => {
265
+ if (!e || !dt(e)) return;
266
+ n(p);
267
+ const h = e.clone();
268
+ h.transformType === "circle" && "setEffectiveFontSize" in h ? h.setEffectiveFontSize(p) : h.setFontSize(p), t(h);
269
+ },
270
+ [e, t]
271
+ ), V = m(
272
+ (p) => {
273
+ if (!e || !dt(e)) return;
274
+ s(p);
275
+ const h = e.clone();
276
+ if (h.color = p, h.richText)
277
+ for (const S of h.richText.spans)
278
+ S.style.color = void 0;
279
+ t(h);
280
+ },
281
+ [e, t]
282
+ ), E = m(
283
+ (p) => {
284
+ if (!e || !dt(e)) return;
285
+ const h = e.fontFamily;
286
+ h !== p && Re.clearCache(h), r(p);
287
+ const S = e.clone();
288
+ S.fontFamily = p, t(S);
289
+ },
290
+ [e, t]
291
+ ), D = m(
292
+ (p) => {
293
+ if (!e || !dt(e)) return;
294
+ a(p);
295
+ const h = e.clone();
296
+ h.textAlign = p, t(h);
297
+ },
298
+ [e, t]
299
+ );
300
+ return {
301
+ // State
302
+ fontSize: o,
303
+ fontColor: i,
304
+ fontFamily: c,
305
+ textAlign: d,
306
+ // State setters (for UI only)
307
+ setFontSize: n,
308
+ setFontColor: s,
309
+ setFontFamily: r,
310
+ setTextAlign: a,
311
+ // Update functions (update element + UI)
312
+ updateFontSize: z,
313
+ setFontSizeValue: F,
314
+ updateFontColor: V,
315
+ updateFontFamily: E,
316
+ updateTextAlign: D
317
+ };
318
+ }
319
+ const qt = "data-preserve-selection";
320
+ function _e(e) {
321
+ if (!(e instanceof Element))
322
+ return !1;
323
+ let t = e;
324
+ const o = [];
325
+ for (; t; ) {
326
+ const n = t.id ? `#${t.id}` : "", i = t.className ? `.${String(t.className).split(" ").slice(0, 2).join(".")}` : "";
327
+ if (o.push(`${t.tagName.toLowerCase()}${n}${i}`), t.hasAttribute(qt))
328
+ return !0;
329
+ const s = t.getAttribute("role");
330
+ if (s === "dialog" || s === "alertdialog" || s === "menu" || s === "listbox")
331
+ return !0;
332
+ const c = t.getAttribute("data-slot");
333
+ if (c && (c.includes("popover") || c.includes("dialog")) || t.hasAttribute("data-radix-popper-content-wrapper"))
334
+ return !0;
335
+ t = t.parentElement;
336
+ }
337
+ return !1;
338
+ }
339
+ const xo = {
340
+ [qt]: ""
341
+ };
342
+ function Le(e) {
343
+ const t = Qt(e);
344
+ return t !== null && t < 0.5;
345
+ }
346
+ function bo(e) {
347
+ const t = Qt(e);
348
+ return t !== null && t >= 0.5;
349
+ }
350
+ function Qt(e) {
351
+ const t = e.trim();
352
+ if (t.startsWith("#")) {
353
+ const n = t.slice(1);
354
+ let i, s, c;
355
+ if (n.length === 3)
356
+ i = parseInt(n[0] + n[0], 16), s = parseInt(n[1] + n[1], 16), c = parseInt(n[2] + n[2], 16);
357
+ else if (n.length === 6)
358
+ i = parseInt(n.slice(0, 2), 16), s = parseInt(n.slice(2, 4), 16), c = parseInt(n.slice(4, 6), 16);
359
+ else return null;
360
+ return Number.isNaN(i) || Number.isNaN(s) || Number.isNaN(c) ? null : Yt(i, s, c);
361
+ }
362
+ const o = t.match(/^rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)/);
363
+ return o ? Yt(Number(o[1]), Number(o[2]), Number(o[3])) : null;
364
+ }
365
+ function Yt(e, t, o) {
366
+ const n = (i) => {
367
+ const s = i / 255;
368
+ return s <= 0.03928 ? s / 12.92 : Math.pow((s + 0.055) / 1.055, 2.4);
369
+ };
370
+ return 0.2126 * n(e) + 0.7152 * n(t) + 0.0722 * n(o);
371
+ }
372
+ const $e = "#333333", Be = "#f4f4f5";
373
+ function We(e) {
374
+ return e && Le(e) ? Be : $e;
375
+ }
376
+ const te = Q(null), Me = 0.1, Xe = 4, Kt = 0.25, Ye = ({
377
+ children: e,
378
+ artboardManager: t,
379
+ canvasRef: o,
380
+ viewPadding: n = 0.9
381
+ }) => {
382
+ const [i, s] = b(1), [c, r] = b({ x: 0, y: 0 }), [d, a] = b(!1), [z, F] = b(1), V = m(() => {
383
+ F(1), r({ x: 0, y: 0 });
384
+ }, []), E = m(() => {
385
+ s((v) => Math.min(v + Kt, Xe));
386
+ }, []), D = m(() => {
387
+ s((v) => Math.max(v - Kt, Me));
388
+ }, []), p = m(() => {
389
+ const v = t.getActiveArtboard();
390
+ if (!v || !o.current) return;
391
+ let R = o.current.parentElement, w = 0, L = 0;
392
+ for (; R && (w = R.clientWidth, L = R.clientHeight, !(w > 0 && L > 0)); )
393
+ R = R.parentElement;
394
+ if (!w || !L) return;
395
+ const nt = Math.min(
396
+ w * n / v.width,
397
+ L * n / v.height,
398
+ 1
399
+ // Never zoom in beyond 100%
400
+ );
401
+ s(nt), r({ x: 0, y: 0 });
402
+ }, [t, o, n]), h = m(() => {
403
+ s(1), r({ x: 0, y: 0 });
404
+ }, []), S = q(
405
+ () => ({
406
+ zoom: i,
407
+ panOffset: c,
408
+ isPanning: d,
409
+ zoomIn: E,
410
+ zoomOut: D,
411
+ zoomToFit: p,
412
+ resetView: h,
413
+ setZoom: s,
414
+ setPanOffset: r,
415
+ setIsPanning: a,
416
+ userZoom: z,
417
+ setUserZoom: F,
418
+ resetUserView: V
419
+ }),
420
+ [i, c, d, E, D, p, h, z, V]
421
+ );
422
+ return /* @__PURE__ */ k(te.Provider, { value: S, children: e });
423
+ };
424
+ function Ke() {
425
+ const e = X(te);
426
+ if (!e)
427
+ throw new Error("useViewportContext must be used within a ViewportProvider (or EditorProvider)");
428
+ return e;
429
+ }
430
+ const ee = Q(null), Ge = ({ children: e }) => {
431
+ const [t, o] = b(null), [n, i] = b([]), [s, c] = b(null), [r, d] = b(null), [a, z] = b(!1), F = m((D) => {
432
+ o(D);
433
+ }, []), V = m((D) => {
434
+ c(D);
435
+ }, []), E = q(
436
+ () => ({
437
+ selectedId: t,
438
+ multiSelection: n,
439
+ activeChildElement: s,
440
+ hoveredElementId: r,
441
+ hideHandles: a,
442
+ setSelectedId: o,
443
+ setMultiSelection: i,
444
+ setHoveredElementId: d,
445
+ setHideHandles: z,
446
+ handleSelectionChange: F,
447
+ handleActiveChildChange: V
448
+ }),
449
+ [
450
+ t,
451
+ n,
452
+ s,
453
+ r,
454
+ a,
455
+ F,
456
+ V
457
+ ]
458
+ );
459
+ return /* @__PURE__ */ k(ee.Provider, { value: E, children: e });
460
+ };
461
+ function je() {
462
+ const e = X(ee);
463
+ if (!e)
464
+ throw new Error("useSelectionContext must be used within a SelectionProvider (or EditorProvider)");
465
+ return e;
466
+ }
467
+ const oe = Q(null), Ze = ({ children: e, value: t }) => {
468
+ const o = q(
469
+ () => ({
470
+ undo: t.undo,
471
+ redo: t.redo,
472
+ canUndo: t.canUndo,
473
+ canRedo: t.canRedo,
474
+ undoActiveArtboard: t.undoActiveArtboard,
475
+ redoActiveArtboard: t.redoActiveArtboard,
476
+ canUndoActiveArtboard: t.canUndoActiveArtboard,
477
+ canRedoActiveArtboard: t.canRedoActiveArtboard
478
+ }),
479
+ [
480
+ t.undo,
481
+ t.redo,
482
+ t.canUndo,
483
+ t.canRedo,
484
+ t.undoActiveArtboard,
485
+ t.redoActiveArtboard,
486
+ t.canUndoActiveArtboard,
487
+ t.canRedoActiveArtboard
488
+ ]
489
+ );
490
+ return /* @__PURE__ */ k(oe.Provider, { value: o, children: e });
491
+ };
492
+ function wo() {
493
+ const e = X(oe);
494
+ if (!e)
495
+ throw new Error("useHistoryContext must be used within a HistoryProvider (or EditorProvider)");
496
+ return e;
497
+ }
498
+ const ne = Q(null), Je = ({ children: e }) => {
499
+ const [t, o] = b(null), [n, i] = b(!1), [s, c] = b(0), [r, d] = b(!1), [a, z] = b(!1), F = q(
500
+ () => ({
501
+ expandedPanelType: t,
502
+ setExpandedPanelType: o,
503
+ isToolbarMenuOpen: n,
504
+ setIsToolbarMenuOpen: i,
505
+ textSelectionVersion: s,
506
+ setTextSelectionVersion: c,
507
+ isCanvasReady: r,
508
+ setCanvasReady: d,
509
+ isRotating: a,
510
+ setIsRotating: z
511
+ }),
512
+ [t, n, s, r, a]
513
+ );
514
+ return /* @__PURE__ */ k(ne.Provider, { value: F, children: e });
515
+ };
516
+ function qe() {
517
+ const e = X(ne);
518
+ if (!e)
519
+ throw new Error("useToolStateContext must be used within a ToolStateProvider (or EditorProvider)");
520
+ return e;
521
+ }
522
+ const re = Q(null), Qe = ({ children: e, value: t }) => {
523
+ const o = q(
524
+ () => ({
525
+ elements: t.elements,
526
+ elementStore: t.elementStore,
527
+ artboards: t.artboards,
528
+ artboardManager: t.artboardManager,
529
+ artboardVersion: t.artboardVersion,
530
+ setElements: t.setElements,
531
+ refreshArtboards: t.refreshArtboards,
532
+ getElementById: t.getElementById,
533
+ handleAddElement: t.handleAddElement,
534
+ handleElementUpdate: t.handleElementUpdate,
535
+ handleLoadWorkspace: t.handleLoadWorkspace,
536
+ handleCopyElements: t.handleCopyElements,
537
+ handlePasteElements: t.handlePasteElements,
538
+ fontSize: t.fontSize,
539
+ fontColor: t.fontColor,
540
+ fontFamily: t.fontFamily,
541
+ textAlign: t.textAlign,
542
+ updateFontSize: t.updateFontSize,
543
+ setFontSizeValue: t.setFontSizeValue,
544
+ updateFontColor: t.updateFontColor,
545
+ updateFontFamily: t.updateFontFamily,
546
+ updateTextAlign: t.updateTextAlign,
547
+ canvasRef: t.canvasRef,
548
+ canvasEditorRef: t.canvasEditorRef
549
+ }),
550
+ [
551
+ t.elements,
552
+ t.elementStore,
553
+ t.artboards,
554
+ t.artboardManager,
555
+ t.artboardVersion,
556
+ t.setElements,
557
+ t.refreshArtboards,
558
+ t.getElementById,
559
+ t.handleAddElement,
560
+ t.handleElementUpdate,
561
+ t.handleLoadWorkspace,
562
+ t.handleCopyElements,
563
+ t.handlePasteElements,
564
+ t.fontSize,
565
+ t.fontColor,
566
+ t.fontFamily,
567
+ t.textAlign,
568
+ t.updateFontSize,
569
+ t.setFontSizeValue,
570
+ t.updateFontColor,
571
+ t.updateFontFamily,
572
+ t.updateTextAlign,
573
+ t.canvasRef,
574
+ t.canvasEditorRef
575
+ ]
576
+ );
577
+ return /* @__PURE__ */ k(re.Provider, { value: o, children: e });
578
+ };
579
+ function Eo() {
580
+ const e = X(re);
581
+ if (!e)
582
+ throw new Error("useElementsContext must be used within an ElementsProvider (or EditorProvider)");
583
+ return e;
584
+ }
585
+ const ie = Q(null), to = ({ children: e, value: t }) => {
586
+ const o = q(
587
+ () => ({
588
+ executeElementUpdate: t.executeElementUpdate,
589
+ executeAddElement: t.executeAddElement,
590
+ executeRemoveElement: t.executeRemoveElement,
591
+ executeReorderElement: t.executeReorderElement,
592
+ executeCreateArtboard: t.executeCreateArtboard,
593
+ executeDeleteArtboard: t.executeDeleteArtboard,
594
+ executeUpdateArtboard: t.executeUpdateArtboard,
595
+ executeCommandBatch: t.executeCommandBatch,
596
+ undo: t.undo,
597
+ redo: t.redo,
598
+ canUndo: t.canUndo,
599
+ canRedo: t.canRedo,
600
+ undoActiveArtboard: t.undoActiveArtboard,
601
+ redoActiveArtboard: t.redoActiveArtboard,
602
+ canUndoActiveArtboard: t.canUndoActiveArtboard,
603
+ canRedoActiveArtboard: t.canRedoActiveArtboard,
604
+ historyManager: t.historyManager
605
+ }),
606
+ [
607
+ t.executeElementUpdate,
608
+ t.executeAddElement,
609
+ t.executeRemoveElement,
610
+ t.executeReorderElement,
611
+ t.executeCreateArtboard,
612
+ t.executeDeleteArtboard,
613
+ t.executeUpdateArtboard,
614
+ t.executeCommandBatch,
615
+ t.undo,
616
+ t.redo,
617
+ t.canUndo,
618
+ t.canRedo,
619
+ t.undoActiveArtboard,
620
+ t.redoActiveArtboard,
621
+ t.canUndoActiveArtboard,
622
+ t.canRedoActiveArtboard,
623
+ t.historyManager
624
+ ]
625
+ );
626
+ return /* @__PURE__ */ k(ie.Provider, { value: o, children: e });
627
+ };
628
+ function So() {
629
+ const e = X(ie);
630
+ if (!e)
631
+ throw new Error("useCommandContext must be used within a CommandProvider (or EditorProvider)");
632
+ return e;
633
+ }
634
+ const eo = Zt("EditorContext"), se = Q(null), ce = Q(null), Ro = () => {
635
+ const e = X(ce);
636
+ if (!e)
637
+ throw new Error("useEditorHandles must be used within EditorProvider");
638
+ return e;
639
+ }, oo = ({ children: e, artboardManager: t, canvasRef: o, canvasEditorRef: n }) => {
640
+ const i = pt(null), s = q(() => ({ get: () => i.current }), []), c = Ke(), r = je(), d = qe(), [a, z] = b(
641
+ () => t.getAllArtboards()
642
+ ), [F, V] = b(0), [E, D] = b(
643
+ () => new Wt()
644
+ ), p = q(() => E.toArray(), [E]), h = m((u) => {
645
+ D((A) => {
646
+ const x = A.toArray(), I = typeof u == "function" ? u(x) : u;
647
+ return I === x ? A : Wt.fromArray(I);
648
+ });
649
+ }, []), S = m(
650
+ (u) => E.get(u),
651
+ [E]
652
+ ), [v, R] = b([]), w = r.selectedId ? E.get(r.selectedId) : void 0, L = m(() => {
653
+ z([...t.getAllArtboards()]), V((u) => u + 1);
654
+ }, [t]), {
655
+ historyManager: nt,
656
+ executeElementUpdate: _,
657
+ executeAddElement: M,
658
+ executeRemoveElement: l,
659
+ executeReorderElement: f,
660
+ executeCommandBatch: g,
661
+ executeCreateArtboard: y,
662
+ executeDeleteArtboard: C,
663
+ executeUpdateArtboard: $,
664
+ undo: P,
665
+ redo: U,
666
+ canUndo: N,
667
+ canRedo: H,
668
+ undoActiveArtboard: O,
669
+ redoActiveArtboard: Y,
670
+ canUndoActiveArtboard: rt,
671
+ canRedoActiveArtboard: K
672
+ } = Ve(
673
+ p,
674
+ h,
675
+ t,
676
+ L
677
+ ), G = m(
678
+ (u) => {
679
+ const A = E.get(u.id);
680
+ _(A, u);
681
+ },
682
+ [E, _]
683
+ ), ue = m(
684
+ (u) => {
685
+ if (!w || !(w instanceof jt))
686
+ return;
687
+ const A = w.clone(), x = A.children.findIndex(
688
+ (I) => I.id === u.id
689
+ );
690
+ x >= 0 && (A.children[x] = u, G(A));
691
+ },
692
+ [w, G]
693
+ ), me = r.activeChildElement || w, he = r.activeChildElement ? ue : G, {
694
+ fontSize: bt,
695
+ fontColor: wt,
696
+ fontFamily: Et,
697
+ textAlign: St,
698
+ updateFontSize: Rt,
699
+ setFontSizeValue: Ct,
700
+ updateFontColor: It,
701
+ updateFontFamily: Tt,
702
+ updateTextAlign: Ot
703
+ } = De(me, he), At = m(
704
+ async (u) => {
705
+ var Lt;
706
+ const A = u.type, x = u, I = t.getActiveArtboardId();
707
+ if (!I)
708
+ throw new ot(
709
+ "E_NO_ACTIVE_ARTBOARD",
710
+ `addElement({ type: "${A}" }) needs an active artboard and none exists. <Editor.Root> seeds one automatically; with a raw EditorProvider create one first (executeCreateArtboard) or select one (artboardManager.setActiveArtboard).`,
711
+ { type: A, docSlug: "embed-mode" }
712
+ );
713
+ const T = `element-${Date.now()}`, B = t.getActiveArtboard(), mt = B ? B.x + B.width / 2 : window.innerWidth / 2, st = B ? B.y + B.height / 2 : window.innerHeight / 2, j = ((Lt = n.current) == null ? void 0 : Lt.getZoom()) || c.zoom || 1;
714
+ if (A === "image") {
715
+ const ft = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==", et = 200 / j, Z = x == null ? void 0 : x.src, W = new ve({
716
+ id: T,
717
+ name: u.name,
718
+ x: mt,
719
+ y: st,
720
+ // Defer loading `src` until after the element is in the store so a
721
+ // synchronously-cached image can't fire onLoadCallback too early.
722
+ imageUrl: Z ? "" : ft,
723
+ transformData: {
724
+ type: "image",
725
+ width: et,
726
+ height: et,
727
+ cropX: 0,
728
+ cropY: 0,
729
+ cropWidth: 1,
730
+ cropHeight: 1,
731
+ flipHorizontal: !1,
732
+ flipVertical: !1,
733
+ borderRadius: 0
734
+ }
735
+ });
736
+ return Z && (W.imageLoaded = !1, W.imageElement = null, W.isCropping = !1, W.imageUrl = Z, W.preserveDimensions = !1, W.onLoadCallback = (J) => {
737
+ const $t = J.transformData.width, Bt = J.transformData.height, kt = Math.min(et / $t, et / Bt, 1);
738
+ kt < 1 && (J.transformData.width = $t * kt, J.transformData.height = Bt * kt), J.transformData.cropX = 0, J.transformData.cropY = 0, J.transformData.cropWidth = 1, J.transformData.cropHeight = 1, _(W, J);
739
+ }), M(W, I), r.setSelectedId(W.id), Z && W.loadImage(Z), { id: W.id, name: u.name ?? "" };
740
+ }
741
+ let tt;
742
+ const at = {
743
+ text: "custom",
744
+ circle: "circle",
745
+ wave: "wave",
746
+ arch: "arch",
747
+ shape: "shape"
748
+ }[A] || "custom", zt = Fe(at);
749
+ if (!zt || !zt.Component)
750
+ throw new Error(`[EditorContext] no transform registered for element type "${A}"`);
751
+ const ht = t.getActiveArtboard(), fe = ht ? Math.min(ht.width, ht.height) * 0.1 : 80, Ht = ht ? ht.width * 0.5 : 300;
752
+ if (A === "shape") {
753
+ const ft = (x == null ? void 0 : x.shapeType) ?? "rectangle";
754
+ let et = 200 / j, Z = 200 / j;
755
+ ft === "ellipse" ? (et = 150 / j, Z = 250 / j) : ft === "line" && (et = 300 / j, Z = 8 / j), tt = new Pe({
756
+ id: T,
757
+ name: u.name,
758
+ x: mt,
759
+ y: st,
760
+ transformData: {
761
+ type: "shape",
762
+ shapeType: ft,
763
+ width: et,
764
+ height: Z,
765
+ fillColor: "#3b82f6",
766
+ fillOpacity: 1
767
+ }
768
+ });
769
+ } else
770
+ tt = new zt.Component({
771
+ id: T,
772
+ name: u.name,
773
+ text: "New Text",
774
+ x: mt,
775
+ y: st,
776
+ fontSize: fe,
777
+ fontFamily: "Poppins",
778
+ color: We(B == null ? void 0 : B.backgroundColor),
779
+ transformData: at === "arch" ? {
780
+ type: "arch",
781
+ width: Ht,
782
+ archHeight: Ne.archHeight
783
+ } : at === "wave" ? {
784
+ type: "wave",
785
+ width: Ht,
786
+ amplitude: Mt.amplitude,
787
+ frequency: Mt.frequency
788
+ } : at === "circle" ? {
789
+ type: "circle",
790
+ radius: Ht / 2
791
+ } : void 0
792
+ });
793
+ return t.addElementToArtboard(T, I), M(
794
+ tt,
795
+ I,
796
+ r.selectedId || void 0
797
+ ), r.setSelectedId(T), { id: T, name: u.name ?? "" };
798
+ },
799
+ [t, M, _, r, c.zoom, n]
800
+ ), vt = m(
801
+ async (u, A) => {
802
+ await At({ ...A, type: u });
803
+ },
804
+ [At]
805
+ ), Ft = m(() => {
806
+ const u = [];
807
+ if (r.multiSelection.length > 0) {
808
+ const A = p.filter(
809
+ (x) => r.multiSelection.includes(x.id)
810
+ );
811
+ u.push(...A);
812
+ } else w && u.push(w);
813
+ if (u.length > 0) {
814
+ const A = u.map((x) => x.clone());
815
+ R(A);
816
+ }
817
+ }, [w, r.multiSelection, p]), Pt = m(() => {
818
+ if (v.length === 0) return;
819
+ const u = [], A = 30, x = 30;
820
+ v.forEach((I) => {
821
+ const T = E.get(I.id), B = T ? T.x : I.x, mt = T ? T.y : I.y, st = I.toJSON();
822
+ delete st.id;
823
+ const j = I.constructor, tt = new j(st);
824
+ tt.x = B + A, tt.y = mt + x;
825
+ let ct = null;
826
+ if (T && (ct = t.getArtboardIdForElement(
827
+ T.id
828
+ )), ct || (ct = t.getActiveArtboardId()), !ct) {
829
+ eo.warn("[handlePasteElements] No artboard found for pasting");
830
+ return;
831
+ }
832
+ const at = T ? T.id : void 0;
833
+ M(tt, ct, at), u.push(tt.id);
834
+ }), u.length === 1 ? r.handleSelectionChange(u[0]) : u.length > 1 && r.setMultiSelection(u);
835
+ }, [
836
+ v,
837
+ E,
838
+ t,
839
+ M,
840
+ r
841
+ ]), yt = m(() => {
842
+ if (d.expandedPanelType === "crop" && (w == null ? void 0 : w.transformType) === "image") {
843
+ const u = w;
844
+ if (u.isCropping) {
845
+ const A = u.clone();
846
+ A.exitCropMode(), _(u, A);
847
+ }
848
+ }
849
+ d.setExpandedPanelType(null);
850
+ }, [
851
+ d.expandedPanelType,
852
+ d.setExpandedPanelType,
853
+ w,
854
+ _
855
+ ]);
856
+ Dt(() => {
857
+ const u = (A) => {
858
+ const x = A.target;
859
+ if (x.tagName === "CANVAS" || _e(x))
860
+ return;
861
+ const T = document.activeElement;
862
+ if (T != null && T.hasAttribute("data-preserve-selection")) {
863
+ T.blur();
864
+ return;
865
+ }
866
+ if (d.expandedPanelType !== null) {
867
+ yt();
868
+ return;
869
+ }
870
+ r.selectedId !== null && r.setSelectedId(null), r.multiSelection.length > 0 && r.setMultiSelection([]);
871
+ };
872
+ return document.addEventListener("pointerdown", u), () => document.removeEventListener("pointerdown", u);
873
+ }, [d.expandedPanelType, yt, r]);
874
+ const Nt = m(
875
+ (u, A, x) => {
876
+ t.clear(), u.forEach((I) => {
877
+ t.createArtboard(I.toJSON());
878
+ }), x && t.setActiveArtboard(x), z([...t.getAllArtboards()]), V((I) => I + 1), h(A), r.setSelectedId(null);
879
+ },
880
+ [t, r, h]
881
+ ), _t = q(() => ({
882
+ // From ViewportContext
883
+ zoom: c.zoom,
884
+ panOffset: c.panOffset,
885
+ isPanning: c.isPanning,
886
+ zoomIn: c.zoomIn,
887
+ zoomOut: c.zoomOut,
888
+ zoomToFit: c.zoomToFit,
889
+ resetView: c.resetView,
890
+ setZoom: c.setZoom,
891
+ setPanOffset: c.setPanOffset,
892
+ setIsPanning: c.setIsPanning,
893
+ // From SelectionContext
894
+ selectedId: r.selectedId,
895
+ multiSelection: r.multiSelection,
896
+ activeChildElement: r.activeChildElement,
897
+ hoveredElementId: r.hoveredElementId,
898
+ hideHandles: r.hideHandles,
899
+ setSelectedId: r.setSelectedId,
900
+ setMultiSelection: r.setMultiSelection,
901
+ setHoveredElementId: r.setHoveredElementId,
902
+ setHideHandles: r.setHideHandles,
903
+ handleSelectionChange: r.handleSelectionChange,
904
+ handleActiveChildChange: r.handleActiveChildChange,
905
+ // From ToolStateContext
906
+ expandedPanelType: d.expandedPanelType,
907
+ setExpandedPanelType: d.setExpandedPanelType,
908
+ isToolbarMenuOpen: d.isToolbarMenuOpen,
909
+ setIsToolbarMenuOpen: d.setIsToolbarMenuOpen,
910
+ textSelectionVersion: d.textSelectionVersion,
911
+ setTextSelectionVersion: d.setTextSelectionVersion,
912
+ isCanvasReady: d.isCanvasReady,
913
+ setCanvasReady: d.setCanvasReady,
914
+ isRotating: d.isRotating,
915
+ setIsRotating: d.setIsRotating,
916
+ // Cross-context handler
917
+ clearExpandedPanel: yt,
918
+ // Core state (element/artboard domain)
919
+ artboardManager: t,
920
+ artboards: a,
921
+ elements: p,
922
+ elementStore: E,
923
+ getElementById: S,
924
+ // Derived state (cross-context)
925
+ selectedElement: w,
926
+ // Refs
927
+ canvasRef: o,
928
+ canvasEditorRef: n,
929
+ // Element setters
930
+ setElements: h,
931
+ // Artboard version counter
932
+ artboardVersion: F,
933
+ // Handlers
934
+ refreshArtboards: L,
935
+ handleElementUpdate: G,
936
+ addElement: At,
937
+ handleAddElement: vt,
938
+ handleLoadWorkspace: Nt,
939
+ handleCopyElements: Ft,
940
+ handlePasteElements: Pt,
941
+ hasClipboardContent: v.length > 0,
942
+ // Command history (undo/redo actions + execute functions)
943
+ historyManager: nt,
944
+ executeElementUpdate: _,
945
+ executeAddElement: M,
946
+ executeRemoveElement: l,
947
+ executeReorderElement: f,
948
+ executeCommandBatch: g,
949
+ executeCreateArtboard: y,
950
+ executeDeleteArtboard: C,
951
+ executeUpdateArtboard: $,
952
+ undo: P,
953
+ redo: U,
954
+ canUndo: N,
955
+ canRedo: H,
956
+ undoActiveArtboard: O,
957
+ redoActiveArtboard: Y,
958
+ canUndoActiveArtboard: rt,
959
+ canRedoActiveArtboard: K,
960
+ // Element properties
961
+ fontSize: bt,
962
+ fontColor: wt,
963
+ fontFamily: Et,
964
+ textAlign: St,
965
+ updateFontSize: Rt,
966
+ setFontSizeValue: Ct,
967
+ updateFontColor: It,
968
+ updateFontFamily: Tt,
969
+ updateTextAlign: Ot
970
+ }), [
971
+ // Viewport
972
+ c.zoom,
973
+ c.panOffset,
974
+ c.isPanning,
975
+ c.zoomIn,
976
+ c.zoomOut,
977
+ c.zoomToFit,
978
+ c.resetView,
979
+ c.setZoom,
980
+ c.setPanOffset,
981
+ c.setIsPanning,
982
+ // Selection
983
+ r.selectedId,
984
+ r.multiSelection,
985
+ r.activeChildElement,
986
+ r.hoveredElementId,
987
+ r.hideHandles,
988
+ r.setSelectedId,
989
+ r.setMultiSelection,
990
+ r.setHoveredElementId,
991
+ r.setHideHandles,
992
+ r.handleSelectionChange,
993
+ r.handleActiveChildChange,
994
+ // Tool state
995
+ d.expandedPanelType,
996
+ d.setExpandedPanelType,
997
+ d.isToolbarMenuOpen,
998
+ d.setIsToolbarMenuOpen,
999
+ d.textSelectionVersion,
1000
+ d.setTextSelectionVersion,
1001
+ d.isCanvasReady,
1002
+ d.setCanvasReady,
1003
+ d.isRotating,
1004
+ d.setIsRotating,
1005
+ yt,
1006
+ // Element/artboard domain
1007
+ t,
1008
+ a,
1009
+ p,
1010
+ E,
1011
+ S,
1012
+ w,
1013
+ o,
1014
+ n,
1015
+ h,
1016
+ F,
1017
+ L,
1018
+ G,
1019
+ At,
1020
+ vt,
1021
+ Nt,
1022
+ Ft,
1023
+ Pt,
1024
+ v,
1025
+ // Command history
1026
+ nt,
1027
+ _,
1028
+ M,
1029
+ l,
1030
+ f,
1031
+ g,
1032
+ y,
1033
+ C,
1034
+ $,
1035
+ P,
1036
+ U,
1037
+ N,
1038
+ H,
1039
+ O,
1040
+ Y,
1041
+ rt,
1042
+ K,
1043
+ // Element properties
1044
+ bt,
1045
+ wt,
1046
+ Et,
1047
+ St,
1048
+ Rt,
1049
+ Ct,
1050
+ It,
1051
+ Tt,
1052
+ Ot
1053
+ ]);
1054
+ return i.current = _t, /* @__PURE__ */ k(ce.Provider, { value: s, children: /* @__PURE__ */ k(
1055
+ Ze,
1056
+ {
1057
+ value: {
1058
+ undo: P,
1059
+ redo: U,
1060
+ canUndo: N,
1061
+ canRedo: H,
1062
+ undoActiveArtboard: O,
1063
+ redoActiveArtboard: Y,
1064
+ canUndoActiveArtboard: rt,
1065
+ canRedoActiveArtboard: K
1066
+ },
1067
+ children: /* @__PURE__ */ k(
1068
+ Qe,
1069
+ {
1070
+ value: {
1071
+ elements: p,
1072
+ elementStore: E,
1073
+ artboards: a,
1074
+ artboardManager: t,
1075
+ artboardVersion: F,
1076
+ setElements: h,
1077
+ refreshArtboards: L,
1078
+ getElementById: S,
1079
+ handleAddElement: vt,
1080
+ handleElementUpdate: G,
1081
+ handleLoadWorkspace: Nt,
1082
+ handleCopyElements: Ft,
1083
+ handlePasteElements: Pt,
1084
+ fontSize: bt,
1085
+ fontColor: wt,
1086
+ fontFamily: Et,
1087
+ textAlign: St,
1088
+ updateFontSize: Rt,
1089
+ setFontSizeValue: Ct,
1090
+ updateFontColor: It,
1091
+ updateFontFamily: Tt,
1092
+ updateTextAlign: Ot,
1093
+ canvasRef: o,
1094
+ canvasEditorRef: n
1095
+ },
1096
+ children: /* @__PURE__ */ k(
1097
+ to,
1098
+ {
1099
+ value: {
1100
+ executeElementUpdate: _,
1101
+ executeAddElement: M,
1102
+ executeRemoveElement: l,
1103
+ executeReorderElement: f,
1104
+ executeCommandBatch: g,
1105
+ executeCreateArtboard: y,
1106
+ executeDeleteArtboard: C,
1107
+ executeUpdateArtboard: $,
1108
+ undo: P,
1109
+ redo: U,
1110
+ canUndo: N,
1111
+ canRedo: H,
1112
+ undoActiveArtboard: O,
1113
+ redoActiveArtboard: Y,
1114
+ canUndoActiveArtboard: rt,
1115
+ canRedoActiveArtboard: K,
1116
+ historyManager: nt
1117
+ },
1118
+ children: /* @__PURE__ */ k(se.Provider, { value: _t, children: e })
1119
+ }
1120
+ )
1121
+ }
1122
+ )
1123
+ }
1124
+ ) });
1125
+ }, Co = ({
1126
+ children: e,
1127
+ initialArtboardConfig: t = {},
1128
+ viewPadding: o = 0.9
1129
+ }) => {
1130
+ const [n] = b(() => {
1131
+ const c = new Oe(), r = {
1132
+ name: t.name || "Artboard 1",
1133
+ x: t.x ?? 0,
1134
+ y: t.y ?? 0,
1135
+ width: t.width ?? 1e3,
1136
+ height: t.height ?? 1e3,
1137
+ backgroundColor: t.backgroundColor || Te
1138
+ };
1139
+ return c.createArtboard(r), c;
1140
+ }), i = pt(null), s = pt(null);
1141
+ return /* @__PURE__ */ k(
1142
+ Ye,
1143
+ {
1144
+ artboardManager: n,
1145
+ canvasRef: i,
1146
+ viewPadding: o,
1147
+ children: /* @__PURE__ */ k(Ge, { children: /* @__PURE__ */ k(Je, { children: /* @__PURE__ */ k(
1148
+ oo,
1149
+ {
1150
+ artboardManager: n,
1151
+ canvasRef: i,
1152
+ canvasEditorRef: s,
1153
+ children: e
1154
+ }
1155
+ ) }) })
1156
+ }
1157
+ );
1158
+ }, Io = () => {
1159
+ const e = X(se);
1160
+ if (!e)
1161
+ throw new Error("useEditor must be used within EditorProvider");
1162
+ return e;
1163
+ }, ut = [];
1164
+ function To(e) {
1165
+ He() && ut.push(e);
1166
+ }
1167
+ function Oo() {
1168
+ return [...ut];
1169
+ }
1170
+ function vo() {
1171
+ ut.length = 0;
1172
+ }
1173
+ function Fo() {
1174
+ if (ut.length === 0) return;
1175
+ const e = ut.map((t) => ze(t) ? `${t.code}: ${t.message}` : `${t.name}: ${t.message}`).join(`
1176
+ - `);
1177
+ throw ut.length = 0, new Error(
1178
+ `expectNoEditorErrors: ${e.includes(`
1179
+ `) ? "errors were" : "an error was"} contained by <Editor.Root>'s boundary during this test:
1180
+ - ${e}
1181
+ A contained error renders an error card in prod — this composition is broken even if the test rendered "successfully".`
1182
+ );
1183
+ }
1184
+ const no = 1;
1185
+ function it(e) {
1186
+ return typeof e == "number" && Number.isFinite(e) ? Math.round(e * 100) / 100 : e;
1187
+ }
1188
+ function ae(e) {
1189
+ return {
1190
+ ...e,
1191
+ ...e.x !== void 0 && { x: it(e.x) },
1192
+ ...e.y !== void 0 && { y: it(e.y) },
1193
+ ...e.width !== void 0 && { width: it(e.width) },
1194
+ ...e.height !== void 0 && { height: it(e.height) },
1195
+ ...e.rotation !== void 0 && { rotation: it(e.rotation) }
1196
+ };
1197
+ }
1198
+ function ro(e) {
1199
+ var n;
1200
+ const t = (n = e.artboards) != null && n.length ? e.artboards : [{ name: "Front", width: 800, height: 800 }], o = t.map(() => []);
1201
+ for (const i of e.elements || []) {
1202
+ const s = i == null ? void 0 : i.artboard, c = typeof s == "string" ? t.findIndex((r) => (r.name || "Front") === s) : -1;
1203
+ o[c >= 0 ? c : 0].push(io(i));
1204
+ }
1205
+ return {
1206
+ schemaVersion: no,
1207
+ artboards: t.map((i, s) => ({
1208
+ id: `artboard-${s + 1}`,
1209
+ name: i.name || "Front",
1210
+ x: 0,
1211
+ y: 0,
1212
+ width: it(i.width || 800),
1213
+ height: it(i.height || 800),
1214
+ backgroundColor: i.backgroundColor || "transparent",
1215
+ // Pass the artboard's flag through — the server worker only paints the
1216
+ // background when this is true. Hardcoding `false` here silently dropped
1217
+ // explicitly-set artboard backgrounds from every realtime mockup while
1218
+ // the editor kept showing them (WYSIWYG drift).
1219
+ exportBackground: i.exportBackground ?? !1,
1220
+ elements: o[s],
1221
+ distressTexture: i.distressTexture,
1222
+ imageMask: i.imageMask
1223
+ }))
1224
+ };
1225
+ }
1226
+ function io(e) {
1227
+ const t = e.type || e.transformType;
1228
+ if (t === "image")
1229
+ return so(e);
1230
+ const { artboard: o, ...n } = e;
1231
+ return ae({
1232
+ ...n,
1233
+ type: t
1234
+ });
1235
+ }
1236
+ function so(e) {
1237
+ var a;
1238
+ const t = e.transformData || {}, o = e.masks && e.masks.length > 0, n = t.width || 0, i = t.height || 0, s = o ? n : n * (t.cropWidth ?? 1), c = o ? i : i * (t.cropHeight ?? 1), r = {
1239
+ id: e.id,
1240
+ type: "image",
1241
+ x: e.x || 0,
1242
+ y: e.y || 0,
1243
+ width: s,
1244
+ height: c,
1245
+ rotation: e.rotation || 0,
1246
+ imageUrl: e.imageUrl,
1247
+ imageAspectRatio: e.imageAspectRatio
1248
+ };
1249
+ return !o && (t.cropX !== 0 || t.cropY !== 0 || t.cropWidth !== 1 || t.cropHeight !== 1) && (r.cropX = t.cropX, r.cropY = t.cropY, r.cropWidth = t.cropWidth, r.cropHeight = t.cropHeight, r.needsCropPixelConversion = !0), t.flipHorizontal && (r.flipHorizontal = t.flipHorizontal), t.flipVertical && (r.flipVertical = t.flipVertical), t.borderRadius && (r.borderRadius = t.borderRadius), ke(t.adjustments) || (r.adjustments = { ...t.adjustments }), e.opacity !== void 0 && (r.opacity = e.opacity), e.distressEffect && (r.distressEffect = e.distressEffect), ((a = e.masks) == null ? void 0 : a.length) > 0 && (r.masks = e.masks), e.blendMode && (r.blendMode = e.blendMode), e.knockoutParts && (r.knockoutParts = e.knockoutParts), e.stroke && (r.stroke = e.stroke), ae(r);
1250
+ }
1251
+ const Gt = "center", de = Symbol.for("snowcone.canvas.layerToken");
1252
+ function Po(e) {
1253
+ return typeof e == "object" && e !== null && e[de] === !0 && typeof e.name == "string" && (e.kind === "text" || e.kind === "image");
1254
+ }
1255
+ function co(e, t) {
1256
+ return Object.freeze({ kind: e, name: t, [de]: !0 });
1257
+ }
1258
+ const le = Symbol.for("snowcone.canvas.colorToken");
1259
+ function ao(e) {
1260
+ return typeof e == "object" && e !== null && e[le] === !0 && typeof e.name == "string" && typeof e.value == "string";
1261
+ }
1262
+ function lo(e, t) {
1263
+ return Object.freeze({ name: e, value: t, [le]: !0 });
1264
+ }
1265
+ function uo(e) {
1266
+ let t = e.trim().toUpperCase();
1267
+ return /^#[0-9A-F]{3}$/.test(t) && (t = "#" + t[1] + t[1] + t[2] + t[2] + t[3] + t[3]), /^#[0-9A-F]{6}$/.test(t) ? t : null;
1268
+ }
1269
+ function xt(e) {
1270
+ return ao(e) ? e.value : e;
1271
+ }
1272
+ function Vt(e) {
1273
+ const t = e.transformType;
1274
+ return t === "image" ? "image" : t === "shape" || t === "group" || t === "path" ? null : "text";
1275
+ }
1276
+ function mo(e) {
1277
+ return e === "top-left" || e === "left" || e === "bottom-left" ? "left" : e === "top-right" || e === "right" || e === "bottom-right" ? "right" : "center";
1278
+ }
1279
+ function ho(e) {
1280
+ return e === "top-left" || e === "top" || e === "top-right" ? "top" : e === "bottom-left" || e === "bottom" || e === "bottom-right" ? "bottom" : "middle";
1281
+ }
1282
+ function Ut(e, t, o, n, i, s) {
1283
+ const c = mo(e), r = ho(e), d = c === "left" ? t / 2 + s : c === "right" ? n - t / 2 - s : n / 2, a = r === "top" ? o / 2 + s : r === "bottom" ? i - o / 2 - s : i / 2;
1284
+ return { x: d, y: a };
1285
+ }
1286
+ function fo(e, t, o) {
1287
+ const n = t / o;
1288
+ if (e >= n) {
1289
+ const c = o * e, r = t / c;
1290
+ return {
1291
+ width: c,
1292
+ height: o,
1293
+ cropX: (1 - r) / 2,
1294
+ cropY: 0,
1295
+ cropWidth: r,
1296
+ cropHeight: 1
1297
+ };
1298
+ }
1299
+ const i = t / e, s = o / i;
1300
+ return {
1301
+ width: t,
1302
+ height: i,
1303
+ cropX: 0,
1304
+ cropY: (1 - s) / 2,
1305
+ cropWidth: 1,
1306
+ cropHeight: s
1307
+ };
1308
+ }
1309
+ class lt {
1310
+ constructor(t) {
1311
+ if (this.els = [], this.colorRoles = /* @__PURE__ */ new Map(), this.idCounter = 0, !(t.width > 0) || !(t.height > 0))
1312
+ throw new Error("design(): artboard width and height must be positive numbers");
1313
+ for (const [o, n] of Object.entries(t.colors ?? {})) {
1314
+ const i = uo(n);
1315
+ if (i === null)
1316
+ throw new ot(
1317
+ "E_COLOR_ROLE_INVALID",
1318
+ `color role "${o}" is ${JSON.stringify(n)} — roles must be #RGB/#RRGGBB hex (useColorBinding matches by normalized hex value; other syntaxes can't bind).`,
1319
+ { roleName: o, value: n, docSlug: "embed-mode" }
1320
+ );
1321
+ const s = [...this.colorRoles.entries()].find(([, c]) => c === i);
1322
+ if (s)
1323
+ throw new ot(
1324
+ "E_COLOR_ROLE_COLLISION",
1325
+ `color roles "${s[0]}" and "${o}" both normalize to ${i}. useColorBinding matches elements by VALUE, so colliding roles would repaint each other's elements — give every role a distinct hex.`,
1326
+ { roles: [s[0], o], value: i, docSlug: "embed-mode" }
1327
+ );
1328
+ this.colorRoles.set(o, i);
1329
+ }
1330
+ this.current = {
1331
+ name: t.name || "Front",
1332
+ width: t.width,
1333
+ height: t.height,
1334
+ backgroundColor: xt(t.backgroundColor),
1335
+ role: t.role
1336
+ }, this.activeName = this.current.name;
1337
+ }
1338
+ /**
1339
+ * Seed a builder from a previously saved canvas state — the editor shape
1340
+ * `<SnowconeCanvas onChange>` emits (and `toJSON()` produces).
1341
+ *
1342
+ * This is how a saved editable template re-enters the turnkey embed path:
1343
+ * load the template's state JSON, lift it back into a `DesignBuilder`, and
1344
+ * hand it to `<RealtimeEmbed design={…}>`. By default the active artboard
1345
+ * becomes the builder's artboard; elements tagged for other artboards are
1346
+ * skipped (untagged elements are assumed to belong to the active one).
1347
+ *
1348
+ * Pass `{ artboards: 'all' }` to load a multi-page template (ADR-0086)
1349
+ * whole: every artboard (with its pacing `role`) and every element are
1350
+ * kept, membership tags preserved, so `toJSON()` / `toServerRequest()`
1351
+ * emit all pages and `TemplateField.artboard` can scope fields per page.
1352
+ */
1353
+ static fromState(t, o = {}) {
1354
+ const n = t.artboards.find((s) => s.name === t.activeArtboard) ?? t.artboards[0];
1355
+ if (!n)
1356
+ throw new Error("DesignBuilder.fromState(): state has no artboards");
1357
+ const i = new lt({
1358
+ name: n.name,
1359
+ width: n.width,
1360
+ height: n.height,
1361
+ backgroundColor: n.backgroundColor,
1362
+ role: n.role
1363
+ });
1364
+ if (o.artboards === "all") {
1365
+ i.allArtboards = t.artboards.map((s) => ({ ...s }));
1366
+ for (const s of t.elements)
1367
+ i.els.push(s.artboard ? { ...s } : { ...s, artboard: n.name });
1368
+ return i;
1369
+ }
1370
+ for (const s of t.elements)
1371
+ s.artboard && s.artboard !== n.name || i.els.push({ ...s });
1372
+ return i;
1373
+ }
1374
+ nextId(t) {
1375
+ return `${t}-${++this.idCounter}`;
1376
+ }
1377
+ /** A wire-shape snapshot of an authoring artboard, applying the same
1378
+ * background-export rule everywhere (a design background is part of the
1379
+ * design — exports and server renders paint it). */
1380
+ static snapshotArtboard(t) {
1381
+ return {
1382
+ name: t.name,
1383
+ width: t.width,
1384
+ height: t.height,
1385
+ ...t.backgroundColor ? {
1386
+ backgroundColor: t.backgroundColor,
1387
+ exportBackground: t.backgroundColor !== "transparent"
1388
+ } : {},
1389
+ ...t.role ? { role: t.role } : {}
1390
+ };
1391
+ }
1392
+ /**
1393
+ * Open a NEW artboard (placement) and make it the authoring context: layer
1394
+ * calls after this target the new artboard — anchor math uses its
1395
+ * dimensions, and the elements carry its membership tag (the public
1396
+ * `artboard` field, PR #482). The FIRST artboard (from `design({ name })`)
1397
+ * remains the initially-active placement when the design mounts; switch at
1398
+ * runtime with `usePlacements()` / `<Editor.Placements/>` (ADR-0088).
1399
+ *
1400
+ * `label` must be the product's placement label (case-sensitive) — the same
1401
+ * artboard-name-is-placement-label rule as `design({ name })`.
1402
+ *
1403
+ * ```ts
1404
+ * const seed = design({ name: 'Front', width: 1480, height: 2328 })
1405
+ * .text('YOUR NAME', { anchor: 'top', name: 'headline' })
1406
+ * .artboard('Back', { width: 1480, height: 2328 })
1407
+ * .text('EST. 2026', { anchor: 'center', name: 'backline' });
1408
+ * ```
1409
+ *
1410
+ * @throws EditorError `E_DUPLICATE_ARTBOARD` — the design already has an
1411
+ * artboard with this label.
1412
+ */
1413
+ artboard(t, o) {
1414
+ if (!(o.width > 0) || !(o.height > 0))
1415
+ throw new Error("design().artboard(): width and height must be positive numbers");
1416
+ if (this.allArtboards || (this.allArtboards = [lt.snapshotArtboard(this.current)]), this.allArtboards.some((n) => n.name === t))
1417
+ throw new ot(
1418
+ "E_DUPLICATE_ARTBOARD",
1419
+ `the design already has an artboard "${t}" — artboard names are placement labels and must be unique. Existing: ${JSON.stringify(this.allArtboards.map((n) => n.name))}.`,
1420
+ { artboardName: t, validNames: this.allArtboards.map((n) => n.name), docSlug: "embed-mode" }
1421
+ );
1422
+ for (const n of this.els)
1423
+ n.artboard || (n.artboard = this.current.name);
1424
+ return this.current = {
1425
+ name: t,
1426
+ width: o.width,
1427
+ height: o.height,
1428
+ backgroundColor: xt(o.backgroundColor),
1429
+ role: o.role
1430
+ }, this.allArtboards.push(lt.snapshotArtboard(this.current)), this;
1431
+ }
1432
+ background(t, o = {}) {
1433
+ const { width: n, height: i } = this.current;
1434
+ let s;
1435
+ if (o.aspectRatio && o.aspectRatio > 0) {
1436
+ const r = fo(o.aspectRatio, n, i);
1437
+ s = {
1438
+ type: "image",
1439
+ width: r.width,
1440
+ height: r.height,
1441
+ cropX: r.cropX,
1442
+ cropY: r.cropY,
1443
+ cropWidth: r.cropWidth,
1444
+ cropHeight: r.cropHeight,
1445
+ flipHorizontal: !1,
1446
+ flipVertical: !1,
1447
+ borderRadius: 0
1448
+ };
1449
+ } else
1450
+ s = {
1451
+ type: "image",
1452
+ width: n,
1453
+ height: i,
1454
+ cropX: 0,
1455
+ cropY: 0,
1456
+ cropWidth: 1,
1457
+ cropHeight: 1,
1458
+ flipHorizontal: !1,
1459
+ flipVertical: !1,
1460
+ borderRadius: 0
1461
+ };
1462
+ const c = {
1463
+ id: this.nextId("bg"),
1464
+ transformType: "image",
1465
+ x: n / 2,
1466
+ y: i / 2,
1467
+ rotation: 0,
1468
+ opacity: o.opacity ?? 1,
1469
+ imageUrl: t,
1470
+ imageAspectRatio: o.aspectRatio,
1471
+ transformData: s,
1472
+ name: o.name ?? "Background"
1473
+ };
1474
+ return this.els.unshift(c), this;
1475
+ }
1476
+ image(t, o = {}) {
1477
+ const { width: n, height: i } = this.current, s = o.width ?? Math.round(n / 3), c = o.height ?? (o.aspectRatio ? Math.round(s / o.aspectRatio) : s), { x: r, y: d } = Ut(o.anchor ?? Gt, s, c, n, i, o.padding ?? 0), a = {
1478
+ id: this.nextId("img"),
1479
+ transformType: "image",
1480
+ x: r,
1481
+ y: d,
1482
+ rotation: o.rotation ?? 0,
1483
+ opacity: o.opacity ?? 1,
1484
+ imageUrl: t,
1485
+ imageAspectRatio: o.aspectRatio,
1486
+ transformData: {
1487
+ type: "image",
1488
+ width: s,
1489
+ height: c,
1490
+ cropX: 0,
1491
+ cropY: 0,
1492
+ cropWidth: 1,
1493
+ cropHeight: 1,
1494
+ flipHorizontal: !1,
1495
+ flipVertical: !1,
1496
+ borderRadius: 0
1497
+ },
1498
+ ...o.name ? { name: o.name } : {}
1499
+ };
1500
+ return this.els.push(a), this;
1501
+ }
1502
+ text(t, o = {}) {
1503
+ const { width: n, height: i } = this.current, s = o.fontSize ?? Math.round(this.current.height / 12), { x: c, y: r } = Ut(o.anchor ?? "top", 0, s, n, i, o.padding ?? Math.round(i / 20)), d = {
1504
+ id: this.nextId("text"),
1505
+ transformType: "custom",
1506
+ x: c,
1507
+ y: r,
1508
+ rotation: o.rotation ?? 0,
1509
+ text: t,
1510
+ fontSize: s,
1511
+ fontFamily: o.fontFamily ?? "Anton",
1512
+ color: xt(o.color) ?? "#ffffff",
1513
+ textAlign: o.textAlign ?? "center",
1514
+ bold: o.bold ?? !1,
1515
+ italic: o.italic ?? !1,
1516
+ transformData: { type: "custom" },
1517
+ ...o.name ? { name: o.name } : {}
1518
+ };
1519
+ return this.els.push(d), this;
1520
+ }
1521
+ /**
1522
+ * Mint a {@link LayerToken} for a named layer — the only currency
1523
+ * `Editor.TextField` accepts (ADR-0085 §1). Compile time: `name` is
1524
+ * constrained to this design's declared layer names, kind inferred from
1525
+ * which per-kind union it falls in. Runtime: validated EAGERLY against the
1526
+ * built elements (nearest the mistake), so CMS/JSON-loaded designs get the
1527
+ * same protection with `string` typing.
1528
+ *
1529
+ * @throws EditorError `E_LAYER_NOT_FOUND` — no layer with this name; lists
1530
+ * the valid names per kind.
1531
+ * @throws EditorError `E_LAYER_WRONG_KIND` — the name matches a layer that
1532
+ * is not bindable (shape/group/path).
1533
+ */
1534
+ layer(t) {
1535
+ const o = this.els.find((i) => i.name === t);
1536
+ if (!o) {
1537
+ const i = this.layerNamesOfKind("text"), s = this.layerNamesOfKind("image");
1538
+ throw new ot(
1539
+ "E_LAYER_NOT_FOUND",
1540
+ `no layer "${t}" in this design. Text layers: ${JSON.stringify(i)}; image layers: ${JSON.stringify(s)}. Fix the name, or add the layer first — e.g. design(…).text('…', { name: '${t}' }).`,
1541
+ { layerName: t, validNames: [...i, ...s], textNames: i, imageNames: s, docSlug: "embed-mode" }
1542
+ );
1543
+ }
1544
+ const n = Vt(o);
1545
+ if (!n)
1546
+ throw new ot(
1547
+ "E_LAYER_WRONG_KIND",
1548
+ `layer "${t}" is a ${o.transformType} element — only text and image layers are bindable. Bindable layers: ${JSON.stringify([...this.layerNamesOfKind("text"), ...this.layerNamesOfKind("image")])}.`,
1549
+ { layerName: t, actualType: o.transformType, docSlug: "embed-mode" }
1550
+ );
1551
+ return co(n, t);
1552
+ }
1553
+ /**
1554
+ * Mint a {@link ColorToken} for a declared color role. Compile time: `name`
1555
+ * is constrained to the roles declared in `design({ colors })`. Runtime:
1556
+ * validated against the declared roles (CMS/JSON-built designs degrade to
1557
+ * `string` typing and rely on this throw).
1558
+ *
1559
+ * Use the token wherever the design paints the role (`fill`, `color`) AND
1560
+ * as the `useColorBinding` argument — one source of truth, no hand-synced
1561
+ * hex pairs.
1562
+ *
1563
+ * @throws EditorError `E_COLOR_ROLE_NOT_FOUND` — no role with this name;
1564
+ * lists the declared roles.
1565
+ */
1566
+ color(t) {
1567
+ const o = this.colorRoles.get(t);
1568
+ if (o === void 0)
1569
+ throw new ot(
1570
+ "E_COLOR_ROLE_NOT_FOUND",
1571
+ `no color role "${t}" in this design. Declared roles: ${JSON.stringify([...this.colorRoles.keys()])}. Declare roles up front — design({ …, colors: { ${t}: '#FF2D8A' } }).`,
1572
+ { roleName: t, validNames: [...this.colorRoles.keys()], docSlug: "embed-mode" }
1573
+ );
1574
+ return lo(t, o);
1575
+ }
1576
+ /** Names of bindable layers of one kind, in stack order. @internal */
1577
+ layerNamesOfKind(t) {
1578
+ return this.els.filter((o) => Vt(o) === t).map((o) => o.name).filter((o) => !!o);
1579
+ }
1580
+ /** An anchored vector shape. */
1581
+ shape(t, o = {}) {
1582
+ const { width: n, height: i } = this.current, s = o.size ?? Math.round(n / 6), c = typeof s == "number" ? s : s.width, r = typeof s == "number" ? s : s.height, { x: d, y: a } = Ut(o.anchor ?? Gt, c, r, n, i, o.padding ?? 0), z = {
1583
+ type: "shape",
1584
+ shapeType: t,
1585
+ width: c,
1586
+ height: r,
1587
+ fillColor: xt(o.fill) ?? "#000000",
1588
+ fillOpacity: o.opacity ?? 1,
1589
+ ...o.points !== void 0 ? { points: o.points } : {},
1590
+ ...o.sides !== void 0 ? { sides: o.sides } : {}
1591
+ }, F = {
1592
+ id: this.nextId("shape"),
1593
+ transformType: "shape",
1594
+ x: d,
1595
+ y: a,
1596
+ rotation: o.rotation ?? 0,
1597
+ transformData: z,
1598
+ ...o.name ? { name: o.name } : {}
1599
+ };
1600
+ return this.els.push(F), this;
1601
+ }
1602
+ /** The composed elements, in render order (background first). Editor shape. */
1603
+ get elements() {
1604
+ return this.els.map((t) => ({ ...t }));
1605
+ }
1606
+ /** Editor-shape canvas state for `<SnowconeCanvas initialElements=… />` and
1607
+ * `serializeStateForServer`. `activeArtboard` is the artboard name. A
1608
+ * builder loaded with `fromState(…, { artboards: 'all' })` emits every
1609
+ * page (artboard `role`s and element membership tags included). */
1610
+ toJSON() {
1611
+ return this.allArtboards ? {
1612
+ // Elements added via builder methods since the last context switch are
1613
+ // untagged — they belong to the CURRENT authoring artboard; stamp them
1614
+ // so the multi-artboard state groups them correctly.
1615
+ elements: this.els.map(
1616
+ (t) => t.artboard ? { ...t } : { ...t, artboard: this.current.name }
1617
+ ),
1618
+ artboards: this.allArtboards.map((t) => ({ ...t })),
1619
+ // The initially-active placement (first artboard / saved state's
1620
+ // active) — NOT the last `.artboard()` authoring context.
1621
+ activeArtboard: this.activeName
1622
+ } : {
1623
+ elements: this.elements,
1624
+ // A background set on a design is part of the design: flag it renderable
1625
+ // so exports and server renders paint it, matching the editor (the
1626
+ // export worker skips it without `exportBackground`) — see snapshotArtboard.
1627
+ artboards: [lt.snapshotArtboard(this.current)],
1628
+ activeArtboard: this.current.name
1629
+ };
1630
+ }
1631
+ /** Server-render payload for `RenderSession.renderState(placement, …)`.
1632
+ * Equivalent to `serializeStateForServer(design.toJSON())`. */
1633
+ toServerRequest() {
1634
+ return ro(this.toJSON());
1635
+ }
1636
+ }
1637
+ function No(e) {
1638
+ return new lt(e);
1639
+ }
1640
+ function zo(e) {
1641
+ return Vt(e);
1642
+ }
1643
+ export {
1644
+ Jt as B,
1645
+ no as C,
1646
+ lt as D,
1647
+ Co as E,
1648
+ qt as P,
1649
+ Ke as a,
1650
+ _e as b,
1651
+ So as c,
1652
+ No as d,
1653
+ Eo as e,
1654
+ wo as f,
1655
+ je as g,
1656
+ qe as h,
1657
+ Po as i,
1658
+ ao as j,
1659
+ go as k,
1660
+ zo as l,
1661
+ Ro as m,
1662
+ Fo as n,
1663
+ Oo as o,
1664
+ xo as p,
1665
+ vo as q,
1666
+ To as r,
1667
+ ro as s,
1668
+ Le as t,
1669
+ Io as u,
1670
+ bo as v
1671
+ };
1672
+ //# sourceMappingURL=design-builder-CBG2hKc8.js.map