@snowcone-app/canvas 0.8.1 → 0.11.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 (36) hide show
  1. package/dist/CanvasStateV1-D3THl2Zc.js +456 -0
  2. package/dist/CanvasStateV1-D3THl2Zc.js.map +1 -0
  3. package/dist/HybridHistoryManager-DANuzx7G.js.map +1 -1
  4. package/dist/advanced.mjs +2 -2
  5. package/dist/api/embed.d.ts +4 -0
  6. package/dist/api/stable.d.ts +6 -2
  7. package/dist/components/embed/SnowconeCanvas.d.ts +8 -0
  8. package/dist/contexts/CanvasServicesContext.d.ts +9 -2
  9. package/dist/design/design-builder.d.ts +23 -1
  10. package/dist/design/template-fields.d.ts +59 -0
  11. package/dist/embed.mjs +67 -63
  12. package/dist/embed.mjs.map +1 -1
  13. package/dist/fonts/google-fonts.d.ts +1 -6
  14. package/dist/hooks/useArtboards.d.ts +1 -0
  15. package/dist/hooks/useColorBinding.d.ts +21 -0
  16. package/dist/index.mjs +45 -40
  17. package/dist/internals.mjs +1 -1
  18. package/dist/rendering/serialize-for-server.d.ts +1 -0
  19. package/dist/schemas-B4UXytQB.js +3250 -0
  20. package/dist/schemas-B4UXytQB.js.map +1 -0
  21. package/dist/services/imageSearch.d.ts +30 -0
  22. package/dist/style.css +1 -1
  23. package/dist/template-fields-C8Tj67ek.js +1585 -0
  24. package/dist/template-fields-C8Tj67ek.js.map +1 -0
  25. package/dist/utils/UnifiedFontService.d.ts +9 -30
  26. package/dist/{validation-CZ4CZV5B.js → validation-C857Ptxn.js} +5804 -6344
  27. package/dist/validation-C857Ptxn.js.map +1 -0
  28. package/package.json +3 -3
  29. package/dist/CanvasStateV1-D7mGz8FR.js +0 -3692
  30. package/dist/CanvasStateV1-D7mGz8FR.js.map +0 -1
  31. package/dist/components/MonotypeDemoPage.d.ts +0 -2
  32. package/dist/design-builder-CM5wSK5w.js +0 -1467
  33. package/dist/design-builder-CM5wSK5w.js.map +0 -1
  34. package/dist/utils/MonotypeCategoryMapping.d.ts +0 -36
  35. package/dist/utils/MonotypeService.d.ts +0 -148
  36. package/dist/validation-CZ4CZV5B.js.map +0 -1
@@ -1,1467 +0,0 @@
1
- import { c as _, y as X, z as Fe, I as Mt, T as te } from "./HybridHistoryManager-DANuzx7G.js";
2
- import { jsxs as q, jsx as x, Fragment as ee } from "react/jsx-runtime";
3
- import { useCallback as B, useMemo as pt, useRef as M, useEffect as k, Component as He, useState as ot, forwardRef as re, useImperativeHandle as $e } from "react";
4
- import { u as ne, T as Xt, E as We, c as Tt, b as oe } from "./ThemeContext-U-VDtIiS.js";
5
- import { af as Vt, ag as jt, a7 as Be, a8 as Kt, a4 as Pe, N as Le, w as Ue, x as ze, z as Oe, G as Ye, j as Xe, p as Ve, a2 as je, Q as Gt, q as Ke, k as Ge, s as qe, r as Je, v as Qe, u as Ze, f as _e, W as tr, L as er, a as rr, m as nr } from "./validation-CZ4CZV5B.js";
6
- import { C as Rt, E as or } from "./ImportManager-NCtkY5Z0.js";
7
- const qt = _("useCommands");
8
- function ar() {
9
- const t = ne(), {
10
- undo: e,
11
- redo: r,
12
- canUndo: o,
13
- canRedo: n,
14
- executeElementUpdate: a,
15
- executeAddElement: i,
16
- executeRemoveElement: s,
17
- executeReorderElement: c,
18
- executeCommandBatch: u,
19
- executeCreateArtboard: E,
20
- executeDeleteArtboard: D,
21
- executeUpdateArtboard: C
22
- } = t, R = B(() => {
23
- qt.warn("[useCommands] clearHistory is not yet implemented in EditorContext");
24
- }, []), T = B((g) => {
25
- qt.warn("[useCommands] clearArtboardHistory is not yet implemented in EditorContext");
26
- }, []);
27
- return {
28
- // Undo/Redo
29
- undo: e,
30
- redo: r,
31
- canUndo: o,
32
- canRedo: n,
33
- // History management
34
- clearHistory: R,
35
- clearArtboardHistory: T,
36
- // Command execution
37
- executeElementUpdate: a,
38
- executeAddElement: i,
39
- executeRemoveElement: s,
40
- executeReorderElement: c,
41
- executeCreateArtboard: E,
42
- executeDeleteArtboard: D,
43
- executeUpdateArtboard: C,
44
- // Batch execution
45
- executeCommandBatch: u
46
- };
47
- }
48
- const ir = () => {
49
- const { undo: t, redo: e, canUndo: r, canRedo: o } = ar();
50
- return /* @__PURE__ */ q("div", { className: "sc-undo-redo", style: { display: "inline-flex", gap: 4 }, children: [
51
- /* @__PURE__ */ x(
52
- Vt,
53
- {
54
- icon: jt.undo,
55
- onClick: t,
56
- disabled: !r,
57
- tooltip: "Undo",
58
- "aria-label": "Undo"
59
- }
60
- ),
61
- /* @__PURE__ */ x(
62
- Vt,
63
- {
64
- icon: jt.redo,
65
- onClick: e,
66
- disabled: !o,
67
- tooltip: "Redo",
68
- "aria-label": "Redo"
69
- }
70
- )
71
- ] });
72
- }, ae = _("KitLayout"), nt = "canvas", St = 320;
73
- let Jt = !1;
74
- function sr() {
75
- Jt || (Jt = !0, Be({
76
- LayersPanel: Le,
77
- EffectsPanel: Ue,
78
- ExportPanel: ze,
79
- ImagePanel: Oe,
80
- GlyphPanel: Ye,
81
- ArtboardTabs: Xe,
82
- ContextualToolbars: Ve,
83
- ZoomControls: je,
84
- MenuButton: Gt,
85
- CropPanel: Ke
86
- }), Kt("add-element-menu", {
87
- component: Gt,
88
- label: "Add Element",
89
- icon: "gravity-ui:plus",
90
- position: "topbar"
91
- }), Kt("undo-redo-controls", {
92
- component: ir,
93
- label: "Undo / Redo",
94
- icon: "lucide:undo-2",
95
- position: "topbar"
96
- }));
97
- }
98
- function gt({ ids: t }) {
99
- return !t || t.length === 0 ? null : /* @__PURE__ */ x(ee, { children: t.map((e) => {
100
- var n;
101
- if (e === nt) return null;
102
- const r = Pe(e);
103
- if (!r)
104
- return typeof X < "u" && ((n = X.env) == null ? void 0 : n.NODE_ENV) === "development" && ae.warn(
105
- `Kit layout references unknown section "${e}" — skipping. Register it with registerSection("${e}", { ... }).`
106
- ), null;
107
- const o = r.component;
108
- return /* @__PURE__ */ x(o, {}, e);
109
- }) });
110
- }
111
- function cr({ kit: t, canvas: e }) {
112
- var D, C, R, T;
113
- sr();
114
- const r = t.layout.slots, o = !!((D = r.topbar) != null && D.some((g) => g !== nt)), n = !!((C = r.left) != null && C.some((g) => g !== nt)), a = !!((R = r.right) != null && R.some((g) => g !== nt)), i = !!((T = r.bottombar) != null && T.some((g) => g !== nt)), s = pt(
115
- () => !o && !n && !a && !i,
116
- [o, n, a, i]
117
- ), c = M(null), u = o || n || a || i, E = M(!1);
118
- return k(() => {
119
- var p;
120
- if (typeof X > "u" || ((p = X.env) == null ? void 0 : p.NODE_ENV) !== "development" || !u) return;
121
- const g = c.current;
122
- if (!g || typeof ResizeObserver > "u") return;
123
- const F = (w) => {
124
- w > 0 && w < St && !E.current ? (E.current = !0, ae.warn(
125
- `Kit "${t.name}" declares chrome (toolbar / panels) but its container is only ${Math.round(w)}px wide — below the ~${St}px needed to render it, so the toolbar / panels are suppressed and the editor looks like a bare canvas. Give the editor more container width, or pass kit="embed-only" if a chrome-less canvas is intended.`
126
- )) : w >= St && (E.current = !1);
127
- };
128
- F(g.getBoundingClientRect().width);
129
- const S = new ResizeObserver((w) => {
130
- for (const v of w) F(v.contentRect.width);
131
- });
132
- return S.observe(g), () => S.disconnect();
133
- }, [u, t.name]), s ? /* @__PURE__ */ x(ee, { children: e }) : /* @__PURE__ */ q("div", { ref: c, className: "sc-kit-layout", style: { display: "flex", flexDirection: "column", height: "100%", minHeight: 0 }, children: [
134
- o && /* @__PURE__ */ x(
135
- "div",
136
- {
137
- className: "sc-kit-topbar toolbar",
138
- style: { display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap", flexShrink: 0 },
139
- children: /* @__PURE__ */ x(gt, { ids: r.topbar })
140
- }
141
- ),
142
- /* @__PURE__ */ q("div", { className: "sc-kit-body", style: { display: "flex", flex: 1, minHeight: 0 }, children: [
143
- n && /* @__PURE__ */ x("div", { className: "sc-kit-left", style: { flexShrink: 0, overflow: "auto" }, children: /* @__PURE__ */ x(gt, { ids: r.left }) }),
144
- /* @__PURE__ */ x("div", { className: "sc-kit-canvas", style: { flex: 1, minWidth: 0, position: "relative" }, children: e }),
145
- a && /* @__PURE__ */ x("div", { className: "sc-kit-right", style: { flexShrink: 0, overflow: "auto" }, children: /* @__PURE__ */ x(gt, { ids: r.right }) })
146
- ] }),
147
- i && /* @__PURE__ */ x(
148
- "div",
149
- {
150
- className: "sc-kit-bottombar toolbar",
151
- style: { display: "flex", alignItems: "center", gap: 8, flexShrink: 0 },
152
- children: /* @__PURE__ */ x(gt, { ids: r.bottombar })
153
- }
154
- )
155
- ] });
156
- }
157
- const lr = _("ErrorBoundary");
158
- class dr extends He {
159
- constructor(e) {
160
- super(e), this.resetError = () => {
161
- this.setState({
162
- hasError: !1,
163
- error: null
164
- });
165
- }, this.state = {
166
- hasError: !1,
167
- error: null
168
- };
169
- }
170
- static getDerivedStateFromError(e) {
171
- return {
172
- hasError: !0,
173
- error: e
174
- };
175
- }
176
- componentDidCatch(e, r) {
177
- if (lr.error("Caught error:", e, r), this.props.onError && this.props.onError(e, r), this.props.onCanvasError) {
178
- const o = {
179
- category: "unknown",
180
- message: e.message,
181
- originalError: e,
182
- recoverable: !1
183
- };
184
- this.props.onCanvasError(o);
185
- }
186
- }
187
- render() {
188
- return this.state.hasError && this.state.error ? this.props.renderError ? this.props.renderError(this.state.error, this.resetError) : this.props.fallback ? typeof this.props.fallback == "function" ? this.props.fallback(this.state.error, this.resetError) : this.props.fallback : /* @__PURE__ */ q(
189
- "div",
190
- {
191
- style: {
192
- padding: "24px",
193
- border: "2px solid var(--danger)",
194
- borderRadius: "8px",
195
- backgroundColor: "color-mix(in oklch, var(--danger) 10%, var(--background))",
196
- color: "var(--danger)",
197
- fontFamily: "system-ui, sans-serif"
198
- },
199
- children: [
200
- /* @__PURE__ */ x("h2", { style: { margin: "0 0 16px 0", fontSize: "18px", fontWeight: 600 }, children: "Something went wrong" }),
201
- /* @__PURE__ */ x(
202
- "pre",
203
- {
204
- style: {
205
- margin: "0 0 16px 0",
206
- padding: "12px",
207
- backgroundColor: "color-mix(in oklch, var(--danger) 15%, var(--background))",
208
- borderRadius: "4px",
209
- fontSize: "14px",
210
- overflow: "auto",
211
- maxHeight: "200px"
212
- },
213
- children: this.state.error.message
214
- }
215
- ),
216
- /* @__PURE__ */ x(
217
- "button",
218
- {
219
- onClick: this.resetError,
220
- style: {
221
- padding: "8px 16px",
222
- backgroundColor: "var(--danger)",
223
- color: "var(--danger-foreground)",
224
- border: "none",
225
- borderRadius: "4px",
226
- fontSize: "14px",
227
- fontWeight: 500,
228
- cursor: "pointer"
229
- },
230
- children: "Try again"
231
- }
232
- )
233
- ]
234
- }
235
- ) : this.props.children;
236
- }
237
- }
238
- const ur = _("useAutoExport");
239
- function hr(t) {
240
- const { config: e, historyManager: r, artboards: o, elements: n, onExport: a, onExportScheduled: i, isCanvasReady: s = !1 } = t, c = M(null), u = M(!1), E = M({
241
- totalExports: 0,
242
- skippedExports: 0,
243
- lastExportTime: null,
244
- avgExportInterval: 0
245
- }), [D, C] = ot(E.current), R = M(a);
246
- R.current = a, k(() => {
247
- const p = new Ge({
248
- ...qe,
249
- ...e
250
- });
251
- return p.onExport(async () => {
252
- try {
253
- await R.current(), E.current = p.getStats();
254
- } catch (w) {
255
- ur.error("[useAutoExport] Export failed:", w);
256
- }
257
- }), c.current = p, () => {
258
- p.destroy();
259
- };
260
- }, []), k(() => {
261
- s && u.current && c.current && (u.current = !1, c.current.forceExport());
262
- }, [s]), k(() => {
263
- c.current && e && c.current.updateConfig(e);
264
- }, [e == null ? void 0 : e.enabled, e == null ? void 0 : e.debounceMs, e == null ? void 0 : e.maxWaitMs]), k(() => {
265
- c.current && i && c.current.onExportScheduled(i);
266
- }, [i]), k(() => {
267
- if (!r || !c.current)
268
- return;
269
- const p = r.onCommandExecuted(() => {
270
- if (c.current) {
271
- if (!s) {
272
- u.current = !0;
273
- return;
274
- }
275
- c.current.scheduleExport();
276
- }
277
- });
278
- return () => {
279
- p();
280
- };
281
- }, [r, s]), k(() => {
282
- if (c.current) {
283
- if (!s) {
284
- u.current = !0;
285
- return;
286
- }
287
- c.current.scheduleExport();
288
- }
289
- }, [n, o, s]), k(() => Fe((w) => {
290
- if (!c.current || !s) return;
291
- n.some((W) => W.id === w) && c.current.scheduleExport();
292
- }), [n, s]);
293
- const T = B((p) => {
294
- c.current && c.current.updateConfig(p);
295
- }, []), g = B(async () => {
296
- c.current && (await c.current.forceExport(), E.current = c.current.getStats(), C(E.current));
297
- }, []), F = B(() => {
298
- c.current && (c.current.resetStats(), E.current = c.current.getStats(), C(E.current));
299
- }, []), S = B(() => {
300
- c.current && c.current.resetChangeDetection();
301
- }, []);
302
- return {
303
- stats: D,
304
- updateConfig: T,
305
- forceExport: g,
306
- resetStats: F,
307
- resetChangeDetection: S
308
- };
309
- }
310
- const ie = _("useContentReady");
311
- function fr(t) {
312
- var r;
313
- const e = /* @__PURE__ */ new Set();
314
- for (const o of t)
315
- if ("fontFamily" in o && typeof o.fontFamily == "string" && o.fontFamily && e.add(o.fontFamily), "getRichText" in o && typeof o.getRichText == "function")
316
- try {
317
- const n = o.getRichText();
318
- if (n != null && n.spans)
319
- for (const a of n.spans)
320
- (r = a.style) != null && r.fontFamily && e.add(a.style.fontFamily);
321
- } catch {
322
- }
323
- return Array.from(e);
324
- }
325
- async function mr(t) {
326
- if (t.length === 0 || typeof document > "u" || !document.fonts) return;
327
- const e = [];
328
- for (const r of t) {
329
- const o = `16px "${r}"`;
330
- e.push(document.fonts.load(o));
331
- }
332
- await Promise.all(e), document.fonts.ready && await Promise.race([
333
- document.fonts.ready,
334
- new Promise((r) => setTimeout(r, 250))
335
- ]), ie.debug(`Awaited ${e.length} font(s)`);
336
- }
337
- function gr() {
338
- return new Promise((t) => requestAnimationFrame(() => t()));
339
- }
340
- function pr(t) {
341
- const { isCanvasReady: e, elements: r, hasInitialElements: o, initialElementsLoaded: n } = t, [a, i] = ot(!1), s = M(!1);
342
- return k(() => {
343
- if (a || !e || o && !n || o && r.length === 0 || s.current) return;
344
- s.current = !0;
345
- let c = !1;
346
- return (async () => {
347
- try {
348
- const u = fr(r);
349
- if (u.length > 0 && (await mr(u), c) || (await gr(), c)) return;
350
- i(!0);
351
- } catch (u) {
352
- ie.error("Error during content readiness check:", u), c || i(!0);
353
- } finally {
354
- s.current = !1;
355
- }
356
- })(), () => {
357
- c = !0, s.current = !1;
358
- };
359
- }, [e, r, o, n, a]), a;
360
- }
361
- const br = {
362
- // Vertical alignments (map to top/center/bottom center)
363
- "far-top": "t",
364
- top: "t",
365
- center: "c",
366
- bottom: "b",
367
- "far-bottom": "b",
368
- // Horizontal alignments (map to left/center/right middle)
369
- "far-left": "l",
370
- left: "l",
371
- right: "r",
372
- "far-right": "r",
373
- // Direct 9-point values
374
- tl: "tl",
375
- t: "t",
376
- tr: "tr",
377
- l: "l",
378
- c: "c",
379
- r: "r",
380
- bl: "bl",
381
- b: "b",
382
- br: "br"
383
- };
384
- function yr(t) {
385
- return t && br[t] || "c";
386
- }
387
- function vr(t, e) {
388
- const r = e.scaleMode || "cover", o = (r === "contain" ? e.marginTop : 0) || 0, n = (r === "contain" ? e.marginRight : 0) || 0, a = (r === "contain" ? e.marginBottom : 0) || 0, i = (r === "contain" ? e.marginLeft : 0) || 0, s = e.width - i - n, c = e.height - o - a, u = s / t.width, E = c / t.height, D = r === "contain" ? Math.min(u, E) : Math.max(u, E), C = e.scale || 1, R = D * C, T = t.width * R, g = t.height * R, F = e.align || "c";
389
- let S = 0, p = 0;
390
- const w = T - s, v = g - c;
391
- switch (F) {
392
- // Top row
393
- case "tl":
394
- S = 0, p = 0;
395
- break;
396
- case "t":
397
- S = -w / 2, p = 0;
398
- break;
399
- case "tr":
400
- S = -w, p = 0;
401
- break;
402
- // Middle row
403
- case "l":
404
- S = 0, p = -v / 2;
405
- break;
406
- case "c":
407
- // Center (default)
408
- default:
409
- S = -w / 2, p = -v / 2;
410
- break;
411
- case "r":
412
- S = -w, p = -v / 2;
413
- break;
414
- // Bottom row
415
- case "bl":
416
- S = 0, p = -v;
417
- break;
418
- case "b":
419
- S = -w / 2, p = -v;
420
- break;
421
- case "br":
422
- S = -w, p = -v;
423
- break;
424
- }
425
- S += i, p += o;
426
- const W = e.offsetX || 0, H = e.offsetY || 0, O = w, at = v;
427
- return S += W * O, p += H * at, S = Math.round(S), p = Math.round(p), {
428
- // Final scale to apply to artwork
429
- scale: R,
430
- // Final artwork dimensions after scaling
431
- width: Math.round(T),
432
- height: Math.round(g),
433
- // Position to draw artwork (relative to artboard origin)
434
- x: S,
435
- y: p,
436
- // Debug info
437
- debug: {
438
- coverScale: D,
439
- userScale: C,
440
- overflow: { x: w, y: v },
441
- alignment: F,
442
- appliedOffset: { x: W * O, y: H * at }
443
- }
444
- };
445
- }
446
- const xr = {
447
- timeout: 3e4,
448
- retries: 1,
449
- retryDelay: 1e3,
450
- validateUrl: !0
451
- };
452
- function wr(t) {
453
- try {
454
- const e = new URL(t);
455
- return ["http:", "https:", "data:", "blob:"].includes(e.protocol);
456
- } catch {
457
- return !1;
458
- }
459
- }
460
- async function Er(t, e = {}) {
461
- const r = { ...xr, ...e };
462
- if (r.validateUrl && !wr(t))
463
- return {
464
- success: !1,
465
- error: new Error(`Invalid image URL: ${t}`)
466
- };
467
- let o;
468
- for (let n = 0; n <= r.retries; n++)
469
- try {
470
- return await Ar(t, r.timeout);
471
- } catch (a) {
472
- o = a instanceof Error ? a : new Error(String(a)), n < r.retries && await Sr(r.retryDelay);
473
- }
474
- return {
475
- success: !1,
476
- error: o || new Error("Failed to load image after retries")
477
- };
478
- }
479
- function Ar(t, e) {
480
- return new Promise((r) => {
481
- const o = new Image();
482
- o.crossOrigin = "anonymous";
483
- let n = null, a = !1;
484
- const i = () => {
485
- n && (clearTimeout(n), n = null);
486
- }, s = () => {
487
- if (a) return;
488
- a = !0, i();
489
- const u = o.naturalWidth || o.width, E = o.naturalHeight || o.height;
490
- r({
491
- success: !0,
492
- element: o,
493
- width: u,
494
- height: E,
495
- aspectRatio: E > 0 ? u / E : 1
496
- });
497
- }, c = (u) => {
498
- a || (a = !0, i(), r({
499
- success: !1,
500
- error: new Error(u)
501
- }));
502
- };
503
- o.onload = s, o.onerror = () => {
504
- c(`Failed to load image: ${t}`);
505
- }, n = setTimeout(() => {
506
- c(`Image load timed out after ${e}ms: ${t}`);
507
- }, e), o.src = t;
508
- });
509
- }
510
- async function Rr(t, e, r = {}, o = {}) {
511
- var C, R, T, g, F, S, p;
512
- const n = await Er(t, o);
513
- if (!n.success || !n.width || !n.height)
514
- return {
515
- success: !1,
516
- error: n.error || new Error("Failed to get image dimensions")
517
- };
518
- const a = {
519
- width: e.artboard.width,
520
- height: e.artboard.height,
521
- scale: e.scale,
522
- align: yr(e.alignment),
523
- offsetX: e.offsetX,
524
- offsetY: e.offsetY,
525
- scaleMode: e.scaleMode,
526
- marginTop: e.marginTop,
527
- marginRight: e.marginRight,
528
- marginBottom: e.marginBottom,
529
- marginLeft: e.marginLeft
530
- }, i = vr(
531
- { width: n.width, height: n.height },
532
- a
533
- ), s = e.artboard.x + i.x, c = e.artboard.y + i.y, u = s + i.width / 2, E = c + i.height / 2;
534
- return {
535
- success: !0,
536
- element: new Mt({
537
- ...r,
538
- x: u,
539
- y: E,
540
- imageUrl: t,
541
- imageAspectRatio: n.aspectRatio,
542
- preserveDimensions: !0,
543
- // Don't recalculate dimensions on image load
544
- transformData: {
545
- type: "image",
546
- width: i.width,
547
- height: i.height,
548
- cropX: ((C = r.transformData) == null ? void 0 : C.cropX) ?? 0,
549
- cropY: ((R = r.transformData) == null ? void 0 : R.cropY) ?? 0,
550
- cropWidth: ((T = r.transformData) == null ? void 0 : T.cropWidth) ?? 1,
551
- cropHeight: ((g = r.transformData) == null ? void 0 : g.cropHeight) ?? 1,
552
- flipHorizontal: ((F = r.transformData) == null ? void 0 : F.flipHorizontal) ?? !1,
553
- flipVertical: ((S = r.transformData) == null ? void 0 : S.flipVertical) ?? !1,
554
- borderRadius: ((p = r.transformData) == null ? void 0 : p.borderRadius) ?? 0
555
- }
556
- }),
557
- placement: {
558
- artworkSize: { width: n.width, height: n.height },
559
- finalSize: { width: i.width, height: i.height },
560
- position: { x: u, y: E },
561
- scale: i.scale
562
- }
563
- };
564
- }
565
- function Sr(t) {
566
- return new Promise((e) => setTimeout(e, t));
567
- }
568
- const K = _("SnowconeCanvas");
569
- function kt(t, e, r, o) {
570
- if (o <= 0 || !isFinite(o))
571
- return r;
572
- const n = t * r, a = e * r;
573
- if (Math.max(n, a) <= o)
574
- return r;
575
- const s = Math.max(t, e), c = o / s;
576
- return Math.min(c, r);
577
- }
578
- const se = re((t, e) => {
579
- const {
580
- exportConfig: r,
581
- imageConfig: o,
582
- layoutConfig: n,
583
- kit: a,
584
- artboards: i,
585
- activeArtboard: s,
586
- onArtboardChange: c,
587
- initialElements: u,
588
- onChange: E,
589
- onSelectionChange: D,
590
- autoExportInterval: C,
591
- onExport: R,
592
- onExportScheduled: T,
593
- onExportStatus: g,
594
- onExportReady: F,
595
- onImageLoad: S,
596
- onImageError: p,
597
- onError: w,
598
- onReady: v,
599
- className: W,
600
- style: H,
601
- enableShortcuts: O,
602
- overlay: at
603
- } = t, Nt = C, tt = t.autoExportConfig ?? (r == null ? void 0 : r.autoExportConfig), J = t.autoExportFormat ?? (r == null ? void 0 : r.format) ?? "dataUrl", bt = t.autoExportAll ?? (r == null ? void 0 : r.exportAll) ?? !1, V = t.exportScale ?? (r == null ? void 0 : r.scale) ?? 2, L = t.maxExportSize ?? (r == null ? void 0 : r.maxSize) ?? 4e3, it = t.exportImageFormat ?? (r == null ? void 0 : r.imageFormat) ?? "png", st = t.exportImageQuality ?? (r == null ? void 0 : r.imageQuality) ?? 0.92, U = t.initialImage ?? (o == null ? void 0 : o.src), Dt = t.initialImageAlignment ?? (o == null ? void 0 : o.alignment) ?? "center", Ft = t.initialImageScale ?? (o == null ? void 0 : o.scale) ?? 1, Ht = t.initialImageScaleMode ?? (o == null ? void 0 : o.scaleMode) ?? "cover", de = t.width ?? (n == null ? void 0 : n.width) ?? 1200, ue = t.height ?? (n == null ? void 0 : n.height) ?? 1200, he = t.viewPadding ?? (n == null ? void 0 : n.viewPadding) ?? 0.9, fe = t.artboardBorderRadius ?? (n == null ? void 0 : n.artboardBorderRadius) ?? 0, me = t.fixedMargin ?? (n == null ? void 0 : n.fixedMargin), ge = t.maxHeight ?? (n == null ? void 0 : n.maxHeight), pe = t.showRotationHandle ?? (n == null ? void 0 : n.showRotationHandle) ?? !0, be = t.hideCanvas ?? (n == null ? void 0 : n.hideCanvas) ?? !1, $t = t.canvasWrapperClassName ?? (n == null ? void 0 : n.canvasWrapperClassName), Wt = t.canvasWrapperStyle ?? (n == null ? void 0 : n.canvasWrapperStyle), ye = t.canvasCutouts ?? (n == null ? void 0 : n.canvasCutouts), Bt = t.pieceGuides, ve = t.pieceFocus, xe = O ?? !0, et = pt(() => Je(a ?? "pro-studio"), [a]);
604
- k(() => {
605
- var l;
606
- if (typeof X < "u" && ((l = X.env) == null ? void 0 : l.NODE_ENV) === "development" && et) {
607
- const d = Qe(et);
608
- d.valid || K.warn("Kit validation warnings:", d.errors), d.warnings.length > 0 && K.warn("Kit validation warnings:", d.warnings);
609
- }
610
- }, [et]);
611
- const ct = M(w);
612
- ct.current = w;
613
- const P = B((l) => {
614
- var d;
615
- K.error(`[${l.category}] ${l.message}`, l.originalError), (d = ct.current) == null || d.call(ct, l);
616
- }, []);
617
- k(() => (Rt.onRenderError = P, () => {
618
- Rt.onRenderError === P && (Rt.onRenderError = null);
619
- }), [P]);
620
- const {
621
- elements: j,
622
- setElements: lt,
623
- selectedId: Pt,
624
- artboardManager: I,
625
- refreshArtboards: we,
626
- historyManager: Ee,
627
- isCanvasReady: yt,
628
- setCanvasReady: dt
629
- } = ne(), { createArtboard: Ae, selectArtboard: Re, artboards: $ } = Ze(), { exportArtboard: Q, exportAllArtboards: ut, exportArtboardAsBlob: Z, exportAllArtboardsAsBlobs: ht } = _e();
630
- $e(e, () => ({
631
- exportArtboards: async (l = {}) => {
632
- const d = l.format || J, A = l.scale || V, h = l.all ?? !1;
633
- let m = A;
634
- if (L > 0 && isFinite(L))
635
- for (const b of $) {
636
- const y = kt(b.width, b.height, A, L);
637
- m = Math.min(m, y);
638
- }
639
- const f = { scale: m, format: it, quality: st };
640
- if (h) {
641
- const b = d === "blob" ? await ht(f) : await ut(f), y = {};
642
- for (const [N, z] of Object.entries(b)) {
643
- const Y = $.find((rt) => rt.id === N);
644
- Y && (y[Y.name] = z);
645
- }
646
- return y;
647
- } else {
648
- const b = I.getActiveArtboard();
649
- if (!b)
650
- throw new Error("[SnowconeCanvas] No active artboard found");
651
- if (d === "blob") {
652
- const y = await Z(b.id, f);
653
- return { [b.name]: y };
654
- } else {
655
- const y = await Q(b.id, f);
656
- return { [b.name]: y };
657
- }
658
- }
659
- }
660
- }), [Q, ut, Z, ht, J, V, L, it, st, I, $]), k(() => {
661
- F && F(async () => {
662
- const d = I.getActiveArtboard();
663
- if (!d)
664
- throw new Error("[SnowconeCanvas] No active artboard found");
665
- const A = kt(
666
- d.width,
667
- d.height,
668
- V,
669
- L
670
- ), h = J === "blob" ? await Z(d.id, { scale: A }) : await Q(d.id, { scale: A });
671
- return { [d.name]: h };
672
- });
673
- }, [F, Q, Z, I, J, V, L]);
674
- const [Lt, ft] = ot("idle"), [Ut, vt] = ot(null), xt = M(void 0), wt = M(!1), zt = M(!1), [Se, ke] = ot(!1), Ce = M(0), Ie = M(0), Et = M(!1);
675
- k(() => {
676
- if (wt.current) return;
677
- wt.current = !0;
678
- const l = i || [{ name: "Design", width: de, height: ue }], d = I.getAllArtboards();
679
- if (d.length > 0) {
680
- const A = l[0], h = d[0], m = Bt ? "transparent" : void 0;
681
- h.name = A.name, h.width = A.width, h.height = A.height, h.clipShape = A.clipShape, A.backgroundColor ? h.backgroundColor = A.backgroundColor : m && (h.backgroundColor = m);
682
- for (let f = 1; f < l.length; f++)
683
- Ae(l[f].width, l[f].height, {
684
- name: l[f].name,
685
- backgroundColor: l[f].backgroundColor ?? m,
686
- clipShape: l[f].clipShape
687
- });
688
- !s && l.length > 1 && I.setActiveArtboard(h.id);
689
- }
690
- we();
691
- }, []), k(() => {
692
- if (!(!u || u.length === 0) && !zt.current && wt.current) {
693
- zt.current = !0, ke(!0);
694
- try {
695
- const l = or.createManyFromJSON(u), d = I.getAllArtboards();
696
- if (d.length > 0) {
697
- const h = new Map(d.map((m) => [m.name, m]));
698
- l.forEach((m, f) => {
699
- var N;
700
- const b = (N = u[f]) == null ? void 0 : N.artboard, y = b && h.get(b) || d[0];
701
- I.addElementToArtboard(m.id, y.id);
702
- });
703
- }
704
- lt(l);
705
- const A = /* @__PURE__ */ new Set();
706
- for (const h of l) {
707
- const m = h.fontFamily;
708
- typeof m == "string" && m.trim().length > 0 && A.add(m);
709
- }
710
- if (A.size > 0 && typeof document < "u") {
711
- const h = document.fonts ?? null, m = Array.from(A).map((f) => {
712
- const b = `font-${f.replace(/\s+/g, "-").toLowerCase()}`;
713
- let y = document.getElementById(b);
714
- return y || (y = document.createElement("link"), y.id = b, y.rel = "stylesheet", y.href = `https://fonts.googleapis.com/css2?family=${f.replace(
715
- /\s+/g,
716
- "+"
717
- )}:wght@400;700&display=swap`, document.head.appendChild(y)), new Promise((N) => {
718
- if (y.sheet) {
719
- N(f);
720
- return;
721
- }
722
- const z = () => N(f);
723
- y.addEventListener("load", z, { once: !0 }), y.addEventListener("error", z, { once: !0 }), setTimeout(z, 4e3);
724
- });
725
- });
726
- Promise.all(m).then((f) => {
727
- if (h)
728
- return Promise.all(
729
- f.flatMap((b) => [
730
- h.load(`400 16px "${b}"`).catch(() => {
731
- }),
732
- h.load(`700 16px "${b}"`).catch(() => {
733
- })
734
- ])
735
- );
736
- }).then(() => {
737
- lt((f) => f.slice());
738
- });
739
- }
740
- } catch (l) {
741
- K.error("Failed to load initial elements:", l);
742
- const d = l instanceof Error ? l : new Error(String(l));
743
- P({
744
- category: "import",
745
- message: `Failed to load initial elements: ${d.message}`,
746
- originalError: d,
747
- recoverable: !0
748
- });
749
- }
750
- }
751
- }, [u, I, lt, P]), k(() => {
752
- if (!s) {
753
- Et.current = !0;
754
- return;
755
- }
756
- const l = $.find((d) => d.name === s);
757
- if (l) {
758
- const d = I.getActiveArtboard();
759
- (d == null ? void 0 : d.name) !== s && Re(l.id), Et.current = !0;
760
- }
761
- }, [s, $]), k(() => {
762
- if (!U || xt.current === U) return;
763
- if (j.length > 0) {
764
- xt.current = U;
765
- return;
766
- }
767
- xt.current = U, (async () => {
768
- ft("loading"), vt(null);
769
- try {
770
- const d = I.getAllArtboards();
771
- if (d.length === 0)
772
- throw new Error("No artboards available");
773
- const A = [];
774
- for (const h of d) {
775
- const m = i == null ? void 0 : i.find((y) => y.name === h.name), f = (m == null ? void 0 : m.scaleMode) || Ht, b = await Rr(
776
- U,
777
- {
778
- artboard: {
779
- width: h.width,
780
- height: h.height,
781
- x: h.x,
782
- y: h.y
783
- },
784
- alignment: (m == null ? void 0 : m.fitAlign) || Dt,
785
- scale: Ft,
786
- scaleMode: f,
787
- marginTop: m == null ? void 0 : m.fitMarginTop,
788
- marginRight: m == null ? void 0 : m.fitMarginRight,
789
- marginBottom: m == null ? void 0 : m.fitMarginBottom,
790
- marginLeft: m == null ? void 0 : m.fitMarginLeft
791
- }
792
- );
793
- b.success && b.element ? (I.addElementToArtboard(b.element.id, h.id), A.push(b.element)) : K.error("Failed to load image for artboard:", h.name, b.error);
794
- }
795
- if (A.length > 0)
796
- lt((h) => [...h, ...A]), ft("success"), S == null || S(U);
797
- else {
798
- const h = new Error("Failed to load image into any artboard");
799
- ft("error"), vt(h), p == null || p(U, h), P({
800
- category: "image",
801
- message: h.message,
802
- originalError: h,
803
- recoverable: !0
804
- });
805
- }
806
- } catch (d) {
807
- const A = d instanceof Error ? d : new Error(String(d));
808
- ft("error"), vt(A), p == null || p(U, A), P({
809
- category: "image",
810
- message: A.message,
811
- originalError: A,
812
- recoverable: !0
813
- });
814
- }
815
- })();
816
- }, [U, Dt, Ft, Ht]);
817
- const mt = M(D);
818
- mt.current = D, k(() => {
819
- var l;
820
- (l = mt.current) == null || l.call(mt, Pt);
821
- }, [Pt]);
822
- const Ot = M(E);
823
- Ot.current = E, k(() => {
824
- const l = Ot.current;
825
- if (!l) return;
826
- const d = I.getActiveArtboard(), A = {
827
- // Stamp each element with the NAME of the artboard it lives on (the
828
- // manager is the membership source of truth). Without this the public
829
- // state is flat and a multi-placement design cannot round-trip: restore
830
- // collapses everything onto the first artboard, and per-placement render
831
- // states can't be derived from onChange. Pinned by
832
- // SnowconeCanvas.artboard-membership.test.tsx.
833
- elements: j.map((h) => {
834
- const m = h.toJSON(), f = I.getArtboardForElement(h.id);
835
- return f ? { ...m, artboard: f.name } : m;
836
- }),
837
- artboards: $.map((h) => ({
838
- name: h.name,
839
- width: h.width,
840
- height: h.height,
841
- clipShape: h.clipShape,
842
- backgroundColor: h.backgroundColor
843
- })),
844
- activeArtboard: (d == null ? void 0 : d.name) || "Design"
845
- };
846
- l(A);
847
- }, [j, $]), k(() => {
848
- if (!c || !Et.current) return;
849
- const l = I.getActiveArtboard();
850
- l && c(l.name);
851
- }, [I.getActiveArtboardId()]);
852
- const Me = B(async () => {
853
- if (!R && !g) return;
854
- const l = ++Ie.current, d = Date.now();
855
- let A = V;
856
- if (L > 0 && isFinite(L))
857
- for (const f of $) {
858
- const b = kt(f.width, f.height, V, L);
859
- A = Math.min(A, b);
860
- }
861
- const h = I.getActiveArtboard(), m = (h == null ? void 0 : h.id) ?? "unknown";
862
- g == null || g({ status: "rendering", artboardId: m }), Ce.current = d;
863
- try {
864
- let f;
865
- const b = {
866
- format: it,
867
- scale: A,
868
- quality: st
869
- };
870
- if (J === "blob")
871
- if (bt) {
872
- const y = await ht(b);
873
- f = {};
874
- for (const [N, z] of Object.entries(y)) {
875
- const Y = $.find((rt) => rt.id === N);
876
- Y && (f[Y.name] = z);
877
- }
878
- } else {
879
- const y = I.getActiveArtboard();
880
- if (!y) return;
881
- const N = await Z(y.id, b);
882
- f = { [y.name]: N };
883
- }
884
- else if (bt) {
885
- const y = await ut(b);
886
- f = {};
887
- for (const [N, z] of Object.entries(y)) {
888
- const Y = $.find((rt) => rt.id === N);
889
- Y && (f[Y.name] = z);
890
- }
891
- } else {
892
- const y = I.getActiveArtboard();
893
- if (!y) return;
894
- const N = await Q(y.id, b);
895
- f = { [y.name]: N };
896
- }
897
- R == null || R(f), g == null || g({ status: "complete", artboardId: m, result: f });
898
- } catch (f) {
899
- const b = f instanceof Error ? f.message : String(f);
900
- if (b.includes("Canvas ref not available"))
901
- return;
902
- const y = Date.now() - d;
903
- K.error("Export failed (export #" + l + "):", {
904
- duration: `${y}ms`,
905
- error: b
906
- });
907
- const N = f instanceof Error ? f : new Error(b);
908
- g == null || g({ status: "error", artboardId: m, error: N }), P({
909
- category: "export",
910
- message: N.message,
911
- originalError: N,
912
- artboardId: m,
913
- recoverable: !0
914
- });
915
- }
916
- }, [R, g, bt, J, V, L, it, st, Q, ut, Z, ht, $, I, j, tt, P]);
917
- k(() => {
918
- Nt !== void 0 && Nt > 0 && K.warn(
919
- "autoExportInterval is deprecated and ignored. Use autoExportConfig={{ enabled: true, debounceMs: 100, maxWaitMs: 1000 }} instead."
920
- );
921
- }, []), k(() => {
922
- }, [j]);
923
- const Te = B(() => {
924
- if (T == null || T(), g) {
925
- const l = I.getActiveArtboard();
926
- g({ status: "scheduled", artboardId: (l == null ? void 0 : l.id) ?? "unknown" });
927
- }
928
- }, [T, g, I]), Ne = !!u && u.length > 0, At = pr({
929
- isCanvasReady: yt,
930
- elements: j,
931
- hasInitialElements: Ne,
932
- initialElementsLoaded: Se
933
- }), Yt = M(!1);
934
- k(() => {
935
- At && !Yt.current && (Yt.current = !0, v == null || v());
936
- }, [At, v]), hr({
937
- config: tt ? {
938
- enabled: tt.enabled ?? !0,
939
- debounceMs: tt.debounceMs ?? 100,
940
- maxWaitMs: tt.maxWaitMs ?? 1e3
941
- } : {
942
- enabled: !1
943
- // Only use smart export if autoExportConfig is provided
944
- },
945
- historyManager: Ee,
946
- artboards: $,
947
- elements: j,
948
- onExport: Me,
949
- onExportScheduled: Te,
950
- isCanvasReady: At
951
- // Gate exports until content is fully ready (fonts loaded, elements deserialized)
952
- }), k(() => {
953
- if ($.length > 0 && !yt) {
954
- const l = requestAnimationFrame(() => {
955
- dt(!0);
956
- });
957
- return () => cancelAnimationFrame(l);
958
- }
959
- }, [$.length, yt, dt]), k(() => () => {
960
- dt(!1);
961
- }, [dt]);
962
- const De = B((l) => {
963
- P({
964
- category: "unknown",
965
- message: l.message,
966
- originalError: l,
967
- recoverable: !1
968
- });
969
- }, [P]);
970
- return Lt === "loading" ? /* @__PURE__ */ x(
971
- "div",
972
- {
973
- className: W,
974
- style: {
975
- ...H,
976
- display: "flex",
977
- alignItems: "center",
978
- justifyContent: "center",
979
- backgroundColor: "var(--surface, #f5f5f5)"
980
- },
981
- children: /* @__PURE__ */ x(tr, { size: 48 })
982
- }
983
- ) : Lt === "error" && Ut ? /* @__PURE__ */ x(
984
- "div",
985
- {
986
- className: W,
987
- style: {
988
- ...H,
989
- display: "flex",
990
- alignItems: "center",
991
- justifyContent: "center",
992
- backgroundColor: "var(--surface, #f5f5f5)",
993
- color: "var(--danger, #dc2626)",
994
- padding: "1rem"
995
- },
996
- children: /* @__PURE__ */ q("div", { className: "text-center", children: [
997
- /* @__PURE__ */ x("div", { className: "font-medium", children: "Failed to load image" }),
998
- /* @__PURE__ */ x("div", { className: "text-sm mt-1 opacity-70", children: Ut.message })
999
- ] })
1000
- }
1001
- ) : /* @__PURE__ */ x(er, { kit: et, children: /* @__PURE__ */ x("div", { className: `app-modern ${W || ""}`, style: { ...H, position: "relative" }, children: /* @__PURE__ */ q(
1002
- dr,
1003
- {
1004
- onError: De,
1005
- fallback: (l, d) => /* @__PURE__ */ q(
1006
- "div",
1007
- {
1008
- style: {
1009
- display: "flex",
1010
- flexDirection: "column",
1011
- alignItems: "center",
1012
- justifyContent: "center",
1013
- padding: "24px",
1014
- minHeight: "200px",
1015
- backgroundColor: "var(--surface, #f5f5f5)",
1016
- color: "var(--foreground, #333)",
1017
- fontFamily: "system-ui, sans-serif",
1018
- textAlign: "center"
1019
- },
1020
- children: [
1021
- /* @__PURE__ */ x("div", { style: { fontSize: "18px", fontWeight: 600, marginBottom: "8px" }, children: "Something went wrong" }),
1022
- /* @__PURE__ */ x("div", { style: { fontSize: "14px", opacity: 0.7, marginBottom: "16px", maxWidth: "400px" }, children: l.message }),
1023
- /* @__PURE__ */ x(
1024
- "button",
1025
- {
1026
- onClick: d,
1027
- style: {
1028
- padding: "8px 20px",
1029
- backgroundColor: "var(--primary, #333)",
1030
- color: "var(--primary-foreground, #fff)",
1031
- border: "none",
1032
- borderRadius: "6px",
1033
- fontSize: "14px",
1034
- fontWeight: 500,
1035
- cursor: "pointer"
1036
- },
1037
- children: "Try again"
1038
- }
1039
- )
1040
- ]
1041
- }
1042
- ),
1043
- children: [
1044
- !be && /* @__PURE__ */ (() => {
1045
- const l = /* @__PURE__ */ x(
1046
- nr,
1047
- {
1048
- style: { width: "100%" },
1049
- fitPadding: he,
1050
- artboardBorderRadius: fe,
1051
- fixedMargin: me,
1052
- maxHeight: ge,
1053
- showRotationHandle: pe,
1054
- enableShortcuts: xe,
1055
- canvasCutouts: ye,
1056
- pieceGuides: Bt,
1057
- pieceFocus: ve
1058
- }
1059
- );
1060
- return /* @__PURE__ */ x(cr, { kit: et, canvas: $t || Wt ? /* @__PURE__ */ x("div", { className: $t, style: Wt, children: l }) : l });
1061
- })(),
1062
- at
1063
- ]
1064
- }
1065
- ) }) });
1066
- });
1067
- se.displayName = "SnowconeCanvasInner";
1068
- const kr = re((t, e) => {
1069
- var c;
1070
- const { inheritTheme: r, externalProvider: o, services: n } = t, a = t.viewPadding ?? ((c = t.layoutConfig) == null ? void 0 : c.viewPadding), i = /* @__PURE__ */ x(se, { ref: e, ...t }), s = o ? /* @__PURE__ */ x(Xt, { defaultTheme: "light", passive: r, children: i }) : /* @__PURE__ */ x(Xt, { defaultTheme: "light", passive: r, children: /* @__PURE__ */ x(We, { viewPadding: a, children: i }) });
1071
- return n ? /* @__PURE__ */ x(rr, { services: n, children: s }) : s;
1072
- });
1073
- kr.displayName = "SnowconeCanvas";
1074
- const Cr = 3e3, Qt = {
1075
- text: "useTextBinding",
1076
- image: "useImageBinding"
1077
- }, Ir = {
1078
- text: "setText",
1079
- image: "setImageUrl"
1080
- }, Ct = /* @__PURE__ */ new Set();
1081
- function Zt(t) {
1082
- return t instanceof te ? "text" : t instanceof Mt ? "image" : "other";
1083
- }
1084
- function Mr(t, e, r) {
1085
- const o = `[${Qt[t]}]`, n = `the binding is dead (isConnected: false, ${Ir[t]} is a no-op)`, a = r.getAllByName(e);
1086
- if (a.length > 0) {
1087
- const c = [...new Set(a.map(Zt))], u = t === "text" ? "image" : "text", E = c.length === 1 && c[0] === u ? ` Bind it with ${Qt[u]}("${e}") instead.` : "";
1088
- return `${o} the layer named "${e}" is ${c.join("/")}, not ${t} — ${n}.${E}`;
1089
- }
1090
- const i = r.getAll().filter((c) => c.name).map((c) => `"${c.name}" (${Zt(c)})`), s = i.length ? `Named layers on this canvas: ${i.join(", ")}. Check the name for a typo.` : `No element on this canvas has a name — name one via design().${t}(…, { name: '${e}' }) or the element's \`name\` property.`;
1091
- return `${o} no ${t} layer named "${e}" exists — ${n}. ${s}`;
1092
- }
1093
- function ce(t, e, r, o) {
1094
- k(() => {
1095
- var i;
1096
- if (o || typeof X > "u" || ((i = X.env) == null ? void 0 : i.NODE_ENV) === "production") return;
1097
- const n = `${t}:${e}`;
1098
- if (Ct.has(n)) return;
1099
- const a = setTimeout(() => {
1100
- Ct.has(n) || (Ct.add(n), console.warn(Mr(t, e, r)));
1101
- }, Cr);
1102
- return () => clearTimeout(a);
1103
- }, [t, e, r, o]);
1104
- }
1105
- const Tr = () => {
1106
- }, Nr = [];
1107
- function qr(t) {
1108
- const { elementStore: e } = Tt(), { executeElementUpdate: r } = oe(), o = pt(() => e.getAllByName(t).filter((i) => i instanceof te), [e, t]), n = B(
1109
- (a) => {
1110
- for (const i of o) {
1111
- const s = i.clone();
1112
- s.setText(a), r(i, s);
1113
- }
1114
- },
1115
- [o, r]
1116
- );
1117
- return ce("text", t, e, o.length > 0), o.length === 0 ? { text: "", setText: Tr, element: null, elements: Nr, isConnected: !1 } : {
1118
- text: o[0].getText(),
1119
- setText: n,
1120
- element: o[0],
1121
- elements: o,
1122
- isConnected: !0
1123
- };
1124
- }
1125
- const Dr = () => {
1126
- }, Fr = [];
1127
- function Hr(t, e, r) {
1128
- const o = t / e;
1129
- if (r >= o) {
1130
- const n = e, a = n * r, i = t / a;
1131
- return {
1132
- width: a,
1133
- height: n,
1134
- cropX: (1 - i) / 2,
1135
- cropY: 0,
1136
- cropWidth: i,
1137
- cropHeight: 1
1138
- };
1139
- } else {
1140
- const n = t, a = n / r, i = e / a;
1141
- return {
1142
- width: n,
1143
- height: a,
1144
- cropX: 0,
1145
- cropY: (1 - i) / 2,
1146
- cropWidth: 1,
1147
- cropHeight: i
1148
- };
1149
- }
1150
- }
1151
- function Jr(t, e) {
1152
- const r = (e == null ? void 0 : e.fit) ?? "cover", { elementStore: o, setElements: n } = Tt(), { executeElementUpdate: a } = oe(), i = pt(() => o.getAllByName(t).filter((R) => R instanceof Mt), [o, t]), s = M(/* @__PURE__ */ new Map());
1153
- for (const C of i)
1154
- if (!s.current.has(C.id)) {
1155
- const R = C.transformData;
1156
- s.current.set(C.id, {
1157
- width: R.width * R.cropWidth,
1158
- height: R.height * R.cropHeight
1159
- });
1160
- }
1161
- const c = M(i);
1162
- c.current = i;
1163
- const u = M(a);
1164
- u.current = a;
1165
- const E = M(n);
1166
- E.current = n;
1167
- const D = B(
1168
- (C) => {
1169
- const R = c.current, T = u.current;
1170
- for (const g of R) {
1171
- const F = s.current.get(g.id);
1172
- if (!F) continue;
1173
- const { width: S, height: p } = F, w = g.clone();
1174
- w.imageLoaded = !1, w.imageElement = null, w.isCropping = !1, w.imageUrl = C, r === "cover" ? (w.preserveDimensions = !0, w.onLoadCallback = (v) => {
1175
- const W = v.imageAspectRatio || 1, H = Hr(S, p, W);
1176
- v.transformData.width = H.width, v.transformData.height = H.height, v.transformData.cropX = H.cropX, v.transformData.cropY = H.cropY, v.transformData.cropWidth = H.cropWidth, v.transformData.cropHeight = H.cropHeight, T(g, v);
1177
- }) : (w.preserveDimensions = !1, w.onLoadCallback = (v) => {
1178
- const W = v.transformData.width, H = v.transformData.height, O = Math.min(S / W, p / H, 1);
1179
- O < 1 && (v.transformData.width = W * O, v.transformData.height = H * O), v.transformData.cropX = 0, v.transformData.cropY = 0, v.transformData.cropWidth = 1, v.transformData.cropHeight = 1, T(g, v);
1180
- }), w.loadImage(C);
1181
- }
1182
- },
1183
- [r]
1184
- // Stable deps only — imageElements/executeElementUpdate/setElements accessed via refs
1185
- );
1186
- return ce("image", t, o, i.length > 0), i.length === 0 ? { imageUrl: "", setImageUrl: Dr, element: null, elements: Fr, isConnected: !1 } : {
1187
- imageUrl: i[0].imageUrl,
1188
- setImageUrl: D,
1189
- element: i[0],
1190
- elements: i,
1191
- isConnected: !0
1192
- };
1193
- }
1194
- function Qr(t) {
1195
- const { elementStore: e } = Tt();
1196
- return t ? e.getByName(t) ?? null : null;
1197
- }
1198
- const $r = 1;
1199
- function G(t) {
1200
- return typeof t == "number" && Number.isFinite(t) ? Math.round(t * 100) / 100 : t;
1201
- }
1202
- function le(t) {
1203
- return {
1204
- ...t,
1205
- ...t.x !== void 0 && { x: G(t.x) },
1206
- ...t.y !== void 0 && { y: G(t.y) },
1207
- ...t.width !== void 0 && { width: G(t.width) },
1208
- ...t.height !== void 0 && { height: G(t.height) },
1209
- ...t.rotation !== void 0 && { rotation: G(t.rotation) }
1210
- };
1211
- }
1212
- function Wr(t) {
1213
- var o;
1214
- const e = (o = t.artboards) != null && o.length ? t.artboards : [{ name: "Front", width: 800, height: 800 }], r = e.map(() => []);
1215
- for (const n of t.elements || []) {
1216
- const a = n == null ? void 0 : n.artboard, i = typeof a == "string" ? e.findIndex((s) => (s.name || "Front") === a) : -1;
1217
- r[i >= 0 ? i : 0].push(Br(n));
1218
- }
1219
- return {
1220
- schemaVersion: $r,
1221
- artboards: e.map((n, a) => ({
1222
- id: `artboard-${a + 1}`,
1223
- name: n.name || "Front",
1224
- x: 0,
1225
- y: 0,
1226
- width: G(n.width || 800),
1227
- height: G(n.height || 800),
1228
- backgroundColor: n.backgroundColor || "transparent",
1229
- exportBackground: !1,
1230
- elements: r[a],
1231
- distressTexture: n.distressTexture,
1232
- imageMask: n.imageMask
1233
- }))
1234
- };
1235
- }
1236
- function Br(t) {
1237
- const e = t.type || t.transformType;
1238
- if (e === "image")
1239
- return Pr(t);
1240
- const { artboard: r, ...o } = t;
1241
- return le({
1242
- ...o,
1243
- type: e
1244
- });
1245
- }
1246
- function Pr(t) {
1247
- var u;
1248
- const e = t.transformData || {}, r = t.masks && t.masks.length > 0, o = e.width || 0, n = e.height || 0, a = r ? o : o * (e.cropWidth ?? 1), i = r ? n : n * (e.cropHeight ?? 1), s = {
1249
- id: t.id,
1250
- type: "image",
1251
- x: t.x || 0,
1252
- y: t.y || 0,
1253
- width: a,
1254
- height: i,
1255
- rotation: t.rotation || 0,
1256
- imageUrl: t.imageUrl,
1257
- imageAspectRatio: t.imageAspectRatio
1258
- };
1259
- return !r && (e.cropX !== 0 || e.cropY !== 0 || e.cropWidth !== 1 || e.cropHeight !== 1) && (s.cropX = e.cropX, s.cropY = e.cropY, s.cropWidth = e.cropWidth, s.cropHeight = e.cropHeight, s.needsCropPixelConversion = !0), e.flipHorizontal && (s.flipHorizontal = e.flipHorizontal), e.flipVertical && (s.flipVertical = e.flipVertical), e.borderRadius && (s.borderRadius = e.borderRadius), t.opacity !== void 0 && (s.opacity = t.opacity), t.distressEffect && (s.distressEffect = t.distressEffect), ((u = t.masks) == null ? void 0 : u.length) > 0 && (s.masks = t.masks), t.blendMode && (s.blendMode = t.blendMode), t.knockoutParts && (s.knockoutParts = t.knockoutParts), t.stroke && (s.stroke = t.stroke), le(s);
1260
- }
1261
- const _t = "center";
1262
- function Lr(t) {
1263
- return t === "top-left" || t === "left" || t === "bottom-left" ? "left" : t === "top-right" || t === "right" || t === "bottom-right" ? "right" : "center";
1264
- }
1265
- function Ur(t) {
1266
- return t === "top-left" || t === "top" || t === "top-right" ? "top" : t === "bottom-left" || t === "bottom" || t === "bottom-right" ? "bottom" : "middle";
1267
- }
1268
- function It(t, e, r, o, n, a) {
1269
- const i = Lr(t), s = Ur(t), c = i === "left" ? e / 2 + a : i === "right" ? o - e / 2 - a : o / 2, u = s === "top" ? r / 2 + a : s === "bottom" ? n - r / 2 - a : n / 2;
1270
- return { x: c, y: u };
1271
- }
1272
- function zr(t, e, r) {
1273
- const o = e / r;
1274
- if (t >= o) {
1275
- const i = r * t, s = e / i;
1276
- return {
1277
- width: i,
1278
- height: r,
1279
- cropX: (1 - s) / 2,
1280
- cropY: 0,
1281
- cropWidth: s,
1282
- cropHeight: 1
1283
- };
1284
- }
1285
- const n = e / t, a = r / n;
1286
- return {
1287
- width: e,
1288
- height: n,
1289
- cropX: 0,
1290
- cropY: (1 - a) / 2,
1291
- cropWidth: 1,
1292
- cropHeight: a
1293
- };
1294
- }
1295
- class Or {
1296
- constructor(e) {
1297
- if (this.els = [], this.idCounter = 0, !(e.width > 0) || !(e.height > 0))
1298
- throw new Error("design(): artboard width and height must be positive numbers");
1299
- this.artboard = {
1300
- name: e.name || "Front",
1301
- width: e.width,
1302
- height: e.height,
1303
- backgroundColor: e.backgroundColor
1304
- };
1305
- }
1306
- nextId(e) {
1307
- return `${e}-${++this.idCounter}`;
1308
- }
1309
- /** Full-bleed background image (fills the whole artboard). Cover-fit (no
1310
- * distortion) when `aspectRatio` is supplied. Inserted at the bottom of the
1311
- * stack regardless of call order. */
1312
- background(e, r = {}) {
1313
- const { width: o, height: n } = this.artboard;
1314
- let a;
1315
- if (r.aspectRatio && r.aspectRatio > 0) {
1316
- const s = zr(r.aspectRatio, o, n);
1317
- a = {
1318
- type: "image",
1319
- width: s.width,
1320
- height: s.height,
1321
- cropX: s.cropX,
1322
- cropY: s.cropY,
1323
- cropWidth: s.cropWidth,
1324
- cropHeight: s.cropHeight,
1325
- flipHorizontal: !1,
1326
- flipVertical: !1,
1327
- borderRadius: 0
1328
- };
1329
- } else
1330
- a = {
1331
- type: "image",
1332
- width: o,
1333
- height: n,
1334
- cropX: 0,
1335
- cropY: 0,
1336
- cropWidth: 1,
1337
- cropHeight: 1,
1338
- flipHorizontal: !1,
1339
- flipVertical: !1,
1340
- borderRadius: 0
1341
- };
1342
- const i = {
1343
- id: this.nextId("bg"),
1344
- transformType: "image",
1345
- x: o / 2,
1346
- y: n / 2,
1347
- rotation: 0,
1348
- opacity: r.opacity ?? 1,
1349
- imageUrl: e,
1350
- imageAspectRatio: r.aspectRatio,
1351
- transformData: a,
1352
- name: r.name ?? "Background"
1353
- };
1354
- return this.els.unshift(i), this;
1355
- }
1356
- /** An anchored image element (not full-bleed). */
1357
- image(e, r = {}) {
1358
- const { width: o, height: n } = this.artboard, a = r.width ?? Math.round(o / 3), i = r.height ?? (r.aspectRatio ? Math.round(a / r.aspectRatio) : a), { x: s, y: c } = It(r.anchor ?? _t, a, i, o, n, r.padding ?? 0), u = {
1359
- id: this.nextId("img"),
1360
- transformType: "image",
1361
- x: s,
1362
- y: c,
1363
- rotation: r.rotation ?? 0,
1364
- opacity: r.opacity ?? 1,
1365
- imageUrl: e,
1366
- imageAspectRatio: r.aspectRatio,
1367
- transformData: {
1368
- type: "image",
1369
- width: a,
1370
- height: i,
1371
- cropX: 0,
1372
- cropY: 0,
1373
- cropWidth: 1,
1374
- cropHeight: 1,
1375
- flipHorizontal: !1,
1376
- flipVertical: !1,
1377
- borderRadius: 0
1378
- },
1379
- ...r.name ? { name: r.name } : {}
1380
- };
1381
- return this.els.push(u), this;
1382
- }
1383
- /** An anchored text layer. Horizontal centring is exact (textAlign); vertical
1384
- * anchoring uses the font size as the line-height estimate. */
1385
- text(e, r = {}) {
1386
- const { width: o, height: n } = this.artboard, a = r.fontSize ?? Math.round(this.artboard.height / 12), { x: i, y: s } = It(r.anchor ?? "top", 0, a, o, n, r.padding ?? Math.round(n / 20)), c = {
1387
- id: this.nextId("text"),
1388
- transformType: "custom",
1389
- x: i,
1390
- y: s,
1391
- rotation: r.rotation ?? 0,
1392
- text: e,
1393
- fontSize: a,
1394
- fontFamily: r.fontFamily ?? "Anton",
1395
- color: r.color ?? "#ffffff",
1396
- textAlign: r.textAlign ?? "center",
1397
- bold: r.bold ?? !1,
1398
- italic: r.italic ?? !1,
1399
- transformData: { type: "custom" },
1400
- ...r.name ? { name: r.name } : {}
1401
- };
1402
- return this.els.push(c), this;
1403
- }
1404
- /** An anchored vector shape. */
1405
- shape(e, r = {}) {
1406
- const { width: o, height: n } = this.artboard, a = r.size ?? Math.round(o / 6), i = typeof a == "number" ? a : a.width, s = typeof a == "number" ? a : a.height, { x: c, y: u } = It(r.anchor ?? _t, i, s, o, n, r.padding ?? 0), E = {
1407
- type: "shape",
1408
- shapeType: e,
1409
- width: i,
1410
- height: s,
1411
- fillColor: r.fill ?? "#000000",
1412
- fillOpacity: r.opacity ?? 1,
1413
- ...r.points !== void 0 ? { points: r.points } : {},
1414
- ...r.sides !== void 0 ? { sides: r.sides } : {}
1415
- }, D = {
1416
- id: this.nextId("shape"),
1417
- transformType: "shape",
1418
- x: c,
1419
- y: u,
1420
- rotation: r.rotation ?? 0,
1421
- transformData: E,
1422
- ...r.name ? { name: r.name } : {}
1423
- };
1424
- return this.els.push(D), this;
1425
- }
1426
- /** The composed elements, in render order (background first). Editor shape. */
1427
- get elements() {
1428
- return this.els.map((e) => ({ ...e }));
1429
- }
1430
- /** Editor-shape canvas state for `<SnowconeCanvas initialElements=… />` and
1431
- * `serializeStateForServer`. `activeArtboard` is the artboard name. */
1432
- toJSON() {
1433
- return {
1434
- elements: this.elements,
1435
- artboards: [{
1436
- name: this.artboard.name,
1437
- width: this.artboard.width,
1438
- height: this.artboard.height,
1439
- ...this.artboard.backgroundColor ? { backgroundColor: this.artboard.backgroundColor } : {}
1440
- }],
1441
- activeArtboard: this.artboard.name
1442
- };
1443
- }
1444
- /** Server-render payload for `RenderSession.renderState(placement, …)`.
1445
- * Equivalent to `serializeStateForServer(design.toJSON())`. */
1446
- toServerRequest() {
1447
- return Wr(this.toJSON());
1448
- }
1449
- }
1450
- function Zr(t) {
1451
- return new Or(t);
1452
- }
1453
- export {
1454
- $r as C,
1455
- Or as D,
1456
- dr as E,
1457
- kr as S,
1458
- ar as a,
1459
- pr as b,
1460
- Qr as c,
1461
- Zr as d,
1462
- Jr as e,
1463
- qr as f,
1464
- Wr as s,
1465
- hr as u
1466
- };
1467
- //# sourceMappingURL=design-builder-CM5wSK5w.js.map