@snowcone-app/canvas 0.17.0 → 0.17.2

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 (66) hide show
  1. package/dist/{CanvasStateV1-C6i6vU6p.js → CanvasStateV1-BG2hEc3-.js} +3 -3
  2. package/dist/{CanvasStateV1-C6i6vU6p.js.map → CanvasStateV1-BG2hEc3-.js.map} +1 -1
  3. package/dist/EditorCanvasImpl-DgXvuWXX.js +70 -0
  4. package/dist/EditorCanvasImpl-DgXvuWXX.js.map +1 -0
  5. package/dist/EditorContext-CGkfmbgo.js +1178 -0
  6. package/dist/EditorContext-CGkfmbgo.js.map +1 -0
  7. package/dist/{ElementFactory-C05JJkRp.js → ElementFactory-CuHSAPfg.js} +1469 -710
  8. package/dist/ElementFactory-CuHSAPfg.js.map +1 -0
  9. package/dist/{HybridHistoryManager-Bht98XRv.js → FontAnalyzer-CLv7_msL.js} +2104 -2903
  10. package/dist/FontAnalyzer-CLv7_msL.js.map +1 -0
  11. package/dist/{ImportManager-kRYfIX-D.js → ImportManager-C_wBjWaV.js} +147 -147
  12. package/dist/{ImportManager-kRYfIX-D.js.map → ImportManager-C_wBjWaV.js.map} +1 -1
  13. package/dist/SnowconeCanvas-wdckG-6O.js +1179 -0
  14. package/dist/SnowconeCanvas-wdckG-6O.js.map +1 -0
  15. package/dist/{UnifiedFontService-BAtqqkU4.js → UnifiedFontService-Dsu5cwfT.js} +141 -141
  16. package/dist/UnifiedFontService-Dsu5cwfT.js.map +1 -0
  17. package/dist/advanced.mjs +10 -10
  18. package/dist/components/editor/RootInternals.d.ts +7 -0
  19. package/dist/components/editor/designStateStore.d.ts +1 -1
  20. package/dist/components/embed/EmbedRoot.d.ts +23 -0
  21. package/dist/components/embed/SnowconeCanvas.d.ts +13 -0
  22. package/dist/components/embed/kernel.d.ts +114 -0
  23. package/dist/contexts/BoundLayerGuardContext.d.ts +36 -0
  24. package/dist/core/GroupElement.d.ts +0 -5
  25. package/dist/core/TextElement.d.ts +8 -3
  26. package/dist/core/paint-registry.d.ts +42 -0
  27. package/dist/core/rich-text-layout.d.ts +28 -0
  28. package/dist/{editorErrors-DbIEtCTt.js → editorErrors-BY4Pdg7a.js} +2 -2
  29. package/dist/{editorErrors-DbIEtCTt.js.map → editorErrors-BY4Pdg7a.js.map} +1 -1
  30. package/dist/{embed-Bdj4PKUA.js → embed-32ZVWfmj.js} +209 -200
  31. package/dist/embed-32ZVWfmj.js.map +1 -0
  32. package/dist/embed.mjs +21 -22
  33. package/dist/embed.mjs.map +1 -1
  34. package/dist/index.mjs +7 -7
  35. package/dist/internals.mjs +93 -93
  36. package/dist/rendering/element-painters.d.ts +16 -0
  37. package/dist/rendering/rich-text-renderer.d.ts +3 -28
  38. package/dist/{template-fields-GOM4MNfq.js → template-fields-Z9x13sjM.js} +32 -33
  39. package/dist/{template-fields-GOM4MNfq.js.map → template-fields-Z9x13sjM.js.map} +1 -1
  40. package/dist/testing.mjs +7 -7
  41. package/dist/transforms/ArchTransform.d.ts +0 -1
  42. package/dist/transforms/AscendTransform.d.ts +0 -1
  43. package/dist/transforms/CircleTransform.d.ts +0 -1
  44. package/dist/transforms/FlagTransform.d.ts +0 -1
  45. package/dist/transforms/LeanTransform.d.ts +0 -1
  46. package/dist/transforms/WaveTransform.d.ts +0 -1
  47. package/dist/{usePieceGuideBundle-CGERAQJl.js → usePieceGuideBundle-C1ipFnZd.js} +2 -2
  48. package/dist/{usePieceGuideBundle-CGERAQJl.js.map → usePieceGuideBundle-C1ipFnZd.js.map} +1 -1
  49. package/dist/{validation-DEd6EOCP.js → validation-C795COGQ.js} +4803 -4791
  50. package/dist/validation-C795COGQ.js.map +1 -0
  51. package/dist/vendor/ui/primitives/kbd.d.ts +1 -1
  52. package/dist/workers/export-worker.bundle.string.d.ts +1 -1
  53. package/package.json +7 -4
  54. package/dist/EditorCanvasImpl-DkgE5-C2.js +0 -68
  55. package/dist/EditorCanvasImpl-DkgE5-C2.js.map +0 -1
  56. package/dist/EditorContext-CyanYzo2.js +0 -1131
  57. package/dist/EditorContext-CyanYzo2.js.map +0 -1
  58. package/dist/ElementFactory-C05JJkRp.js.map +0 -1
  59. package/dist/HybridHistoryManager-Bht98XRv.js.map +0 -1
  60. package/dist/SnowconeCanvas-C3eZ9PP8.js +0 -1047
  61. package/dist/SnowconeCanvas-C3eZ9PP8.js.map +0 -1
  62. package/dist/UnifiedFontService-BAtqqkU4.js.map +0 -1
  63. package/dist/editorError-DMENTZ-3.js +0 -19
  64. package/dist/editorError-DMENTZ-3.js.map +0 -1
  65. package/dist/embed-Bdj4PKUA.js.map +0 -1
  66. package/dist/validation-DEd6EOCP.js.map +0 -1
@@ -1,16 +1,15 @@
1
- import { C as Ee, e as Re } from "./UnifiedFontService-BAtqqkU4.js";
2
- import { y as x } from "./HybridHistoryManager-Bht98XRv.js";
1
+ import { C as Ee, e as Re } from "./UnifiedFontService-Dsu5cwfT.js";
2
+ import { y as x } from "./FontAnalyzer-CLv7_msL.js";
3
3
  import { jsx as f, jsxs as Q, Fragment as we } from "react/jsx-runtime";
4
- import { useContext as Z, createContext as ee, useRef as T, useState as O, useMemo as I, useEffect as $, useSyncExternalStore as A, Component as xe, forwardRef as te, useId as ne, useLayoutEffect as re, useCallback as se } from "react";
4
+ import { useContext as Z, createContext as ee, useRef as N, useState as O, useMemo as I, useEffect as $, useSyncExternalStore as L, Component as xe, forwardRef as te, useId as re, useLayoutEffect as ne, useCallback as se } from "react";
5
5
  import { assertVariantSelected as ie, RenderSession as Se, createCartDetail as Ie } from "@snowcone-app/sdk";
6
- import { u as Ce, p as Ne } from "./usePieceGuideBundle-CGERAQJl.js";
7
- import { E as R, i as Te, a as ae } from "./editorError-DMENTZ-3.js";
8
- import { r as oe } from "./editorErrors-DbIEtCTt.js";
9
- import { l as X, i as Oe, s as le } from "./template-fields-GOM4MNfq.js";
10
- import "./EditorContext-CyanYzo2.js";
11
- import "./CanvasStateV1-C6i6vU6p.js";
6
+ import { g as R, i as Ce, h as ae, B as Te, E as Ne } from "./EditorContext-CGkfmbgo.js";
7
+ import { u as Oe, p as ke } from "./usePieceGuideBundle-C1ipFnZd.js";
8
+ import { r as oe } from "./editorErrors-BY4Pdg7a.js";
9
+ import { l as X, i as _e, s as le } from "./template-fields-Z9x13sjM.js";
10
+ import "./CanvasStateV1-BG2hEc3-.js";
12
11
  const de = ee(void 0);
13
- function L() {
12
+ function A() {
14
13
  const t = Z(de);
15
14
  if (!t)
16
15
  throw new Error(
@@ -18,42 +17,42 @@ function L() {
18
17
  );
19
18
  return t;
20
19
  }
21
- const ke = "[RealtimeEmbed]";
22
- function _e(t) {
23
- var r, s;
24
- if ((r = t == null ? void 0 : t.requiredPlacements) != null && r.length)
20
+ const $e = "[RealtimeEmbed]";
21
+ function Be(t) {
22
+ var n, s;
23
+ if ((n = t == null ? void 0 : t.requiredPlacements) != null && n.length)
25
24
  return t.requiredPlacements.filter((a) => !a.autoFilledByVariant).map((a) => a.label);
26
25
  const e = new Set(
27
26
  (((s = t == null ? void 0 : t.options) == null ? void 0 : s.combinations) ?? []).map((a) => a.variantId).filter((a) => typeof a == "string" && a !== "")
28
27
  );
29
28
  return !!(t != null && t.variantId) || e.size > 1 ? [] : (t == null ? void 0 : t.placements) ?? [];
30
29
  }
31
- function ue({ shop: t, product: e, design: n, hasGrant: r }) {
32
- var m, d;
30
+ function ue({ shop: t, product: e, design: r, hasGrant: n }) {
31
+ var c, d;
33
32
  const s = [];
34
33
  if (t || s.push({
35
34
  severity: "error",
36
35
  issue: "missing-shop",
37
36
  message: "`shop` is required (your publishable shop id)."
38
- }), r || s.push({
37
+ }), n || s.push({
39
38
  severity: "error",
40
39
  issue: "missing-grant",
41
40
  message: "no grant source — pass `grantUrl` (a proxy to mintRealtimeGrant) or `grant`. Without it the session can never authorize and no mockup renders."
42
- }), (m = e == null ? void 0 : e.mockupIds) != null && m.length || s.push({
41
+ }), (c = e == null ? void 0 : e.mockupIds) != null && c.length || s.push({
43
42
  severity: "error",
44
43
  issue: "empty-mockup-ids",
45
44
  message: 'product.mockupIds is empty — pass the catalog scene codes (product.mockups[].id) you want rendered, e.g. ["FV1qjO"].'
46
45
  }), e != null && e.options)
47
46
  try {
48
47
  ie(e);
49
- } catch (c) {
48
+ } catch (m) {
50
49
  s.push({
51
50
  severity: "error",
52
51
  issue: "variant-required",
53
- message: c instanceof Error ? c.message : String(c)
52
+ message: m instanceof Error ? m.message : String(m)
54
53
  });
55
54
  }
56
- const a = n.toJSON(), l = a.activeArtboard, i = _e(e);
55
+ const a = r.toJSON(), l = a.activeArtboard, i = Be(e);
57
56
  i.length > 1 && s.push({
58
57
  severity: "error",
59
58
  issue: "multi-placement",
@@ -63,16 +62,16 @@ function ue({ shop: t, product: e, design: n, hasGrant: r }) {
63
62
  issue: "placement-mismatch",
64
63
  message: `the design's placement "${l}" is not in product.placements [${e.placements.join(", ")}]. The canvas artboard name and renderState placement must equal a real product placement label, or the server renders a blank mockup. Fix the \`name\` passed to design({ name }).`
65
64
  });
66
- const o = a.elements.map((c) => c.name).filter((c) => !!c), u = o.filter((c, y) => o.indexOf(c) !== y);
65
+ const o = a.elements.map((m) => m.name).filter((m) => !!m), u = o.filter((m, y) => o.indexOf(m) !== y);
67
66
  return u.length && s.push({
68
67
  severity: "warn",
69
68
  issue: "duplicate-layer-names",
70
69
  message: `duplicate layer name(s) [${[...new Set(u)].join(", ")}] — useTextBinding(name) / useImageBinding(name) bind to the FIRST match, so a duplicate name makes a control edit the wrong layer. Keep names unique.`
71
70
  }), s;
72
71
  }
73
- function $e(t) {
72
+ function Fe(t) {
74
73
  for (const e of ue(t))
75
- (e.severity === "error" && e.issue !== "placement-mismatch" ? console.error : console.warn)(`${ke} ${e.message}`);
74
+ (e.severity === "error" && e.issue !== "placement-mismatch" ? console.error : console.warn)(`${$e} ${e.message}`);
76
75
  }
77
76
  function j(t) {
78
77
  return t.text;
@@ -80,15 +79,15 @@ function j(t) {
80
79
  function _(t) {
81
80
  return t.name;
82
81
  }
83
- class Be {
82
+ class De {
84
83
  constructor(e) {
85
- this.listeners = /* @__PURE__ */ new Set(), this.getState = () => this.state, this.subscribe = (r) => (this.listeners.add(r), () => this.listeners.delete(r)), this.state = e;
86
- const n = /* @__PURE__ */ new Map();
87
- for (const r of e.elements) {
88
- const s = _(r), a = j(r);
89
- s && typeof a == "string" && n.set(s, a);
84
+ this.listeners = /* @__PURE__ */ new Set(), this.getState = () => this.state, this.subscribe = (n) => (this.listeners.add(n), () => this.listeners.delete(n)), this.state = e;
85
+ const r = /* @__PURE__ */ new Map();
86
+ for (const n of e.elements) {
87
+ const s = _(n), a = j(n);
88
+ s && typeof a == "string" && r.set(s, a);
90
89
  }
91
- this.seedTextByName = n;
90
+ this.seedTextByName = r;
92
91
  }
93
92
  /** Replace the whole state (the canvas `onChange` path). */
94
93
  setState(e) {
@@ -100,14 +99,14 @@ class Be {
100
99
  }
101
100
  /** Current text of a named text layer, or undefined when absent. */
102
101
  textOf(e) {
103
- const n = this.state.elements.find((r) => _(r) === e);
104
- return n ? j(n) : void 0;
102
+ const r = this.state.elements.find((n) => _(n) === e);
103
+ return r ? j(r) : void 0;
105
104
  }
106
105
  /** Kind of the named layer in the CURRENT state ('text' | 'image' | null
107
106
  * for unbindable), or undefined when no layer has the name. */
108
107
  layerKindOf(e) {
109
- const n = this.state.elements.find((r) => _(r) === e);
110
- return n ? X(n) : void 0;
108
+ const r = this.state.elements.find((n) => _(n) === e);
109
+ return r ? X(r) : void 0;
111
110
  }
112
111
  /** Names of bindable layers in the current state, for error messages. */
113
112
  bindableLayerNames() {
@@ -118,10 +117,10 @@ class Be {
118
117
  * one, writes route through the editor command path and arrive back here
119
118
  * via `setState`). Immutable update; last-write-wins.
120
119
  */
121
- updateTextLayer(e, n) {
122
- let r = !1;
123
- const s = this.state.elements.map((a) => _(a) !== e ? a : (r = !0, { ...a, text: n }));
124
- if (!r)
120
+ updateTextLayer(e, r) {
121
+ let n = !1;
122
+ const s = this.state.elements.map((a) => _(a) !== e ? a : (n = !0, { ...a, text: r }));
123
+ if (!n)
125
124
  throw new R(
126
125
  "E_LAYER_NOT_FOUND",
127
126
  `no layer "${e}" in the current design state. Bindable layers: ${JSON.stringify(this.bindableLayerNames())}.`,
@@ -130,21 +129,22 @@ class Be {
130
129
  this.setState({ ...this.state, elements: s });
131
130
  }
132
131
  /** ≥1 element with visible content (completeness rule C4): non-empty text,
133
- * an image with a URL, or a shape. */
132
+ * an image with a URL, or a shape. Hidden elements don't count. */
134
133
  hasRenderableElement() {
135
134
  return this.state.elements.some((e) => {
136
- const n = e.transformType;
137
- if (n === "image") return !!e.imageUrl;
138
- if (n === "shape" || n === "group" || n === "path") return !0;
139
- const r = j(e);
140
- return typeof r == "string" && r.trim().length > 0;
135
+ if (e.visible === !1) return !1;
136
+ const r = e.transformType;
137
+ if (r === "image") return !!e.imageUrl;
138
+ if (r === "shape" || r === "group" || r === "path") return !0;
139
+ const n = j(e);
140
+ return typeof n == "string" && n.trim().length > 0;
141
141
  });
142
142
  }
143
143
  emit() {
144
144
  for (const e of [...this.listeners]) e();
145
145
  }
146
146
  }
147
- class De {
147
+ class Ue {
148
148
  constructor() {
149
149
  this.canvasIds = /* @__PURE__ */ new Set(), this.requirements = /* @__PURE__ */ new Map(), this.textFields = /* @__PURE__ */ new Map(), this.bridge = null, this.listeners = /* @__PURE__ */ new Set(), this.version = 0, this.getVersion = () => this.version, this.subscribe = (e) => (this.listeners.add(e), () => this.listeners.delete(e));
150
150
  }
@@ -158,8 +158,8 @@ class De {
158
158
  }
159
159
  /** Declare that a part is meaningless without a mounted Canvas (ADR-0085 §4
160
160
  * table). Validated by Root once per commit. */
161
- requireCanvas(e, n) {
162
- return this.requirements.set(e, n), this.bump(), () => {
161
+ requireCanvas(e, r) {
162
+ return this.requirements.set(e, r), this.bump(), () => {
163
163
  this.requirements.delete(e), this.bump();
164
164
  };
165
165
  }
@@ -182,8 +182,8 @@ class De {
182
182
  );
183
183
  }
184
184
  }
185
- registerTextField(e, n) {
186
- return this.textFields.set(e, n), this.bump(), () => {
185
+ registerTextField(e, r) {
186
+ return this.textFields.set(e, r), this.bump(), () => {
187
187
  this.textFields.delete(e), this.bump();
188
188
  };
189
189
  }
@@ -192,6 +192,15 @@ class De {
192
192
  getTextFields() {
193
193
  return [...this.textFields.values()];
194
194
  }
195
+ /** Bound-layer lookup for the mutation guard (ADR-0085 §3 /
196
+ * `E_BOUND_LAYER_MUTATION`): a layer is bound while ANY mounted
197
+ * `Editor.TextField` carries its name. Satisfies `BoundLayerGuard`
198
+ * structurally (subscribe/getVersion above). */
199
+ getBoundLayer(e) {
200
+ for (const r of this.textFields.values())
201
+ if (r.name === e) return { part: "Editor.TextField" };
202
+ return null;
203
+ }
195
204
  registerCanvasBridge(e) {
196
205
  return this.bridge = e, this.bump(), () => {
197
206
  this.bridge === e && (this.bridge = null), this.bump();
@@ -206,7 +215,7 @@ class De {
206
215
  }
207
216
  }
208
217
  const ce = ee(null);
209
- function G(t) {
218
+ function K(t) {
210
219
  const e = Z(ce);
211
220
  if (!e)
212
221
  throw new R(
@@ -216,10 +225,10 @@ function G(t) {
216
225
  );
217
226
  return e;
218
227
  }
219
- function Fe(t) {
228
+ function Le(t) {
220
229
  return {
221
230
  reportInvariant(e) {
222
- if (Te()) throw e;
231
+ if (Ce()) throw e;
223
232
  t(e);
224
233
  },
225
234
  reportRuntimeError(e) {
@@ -228,17 +237,17 @@ function Fe(t) {
228
237
  };
229
238
  }
230
239
  const me = 8e3;
231
- function Ue(t) {
240
+ function Ae(t) {
232
241
  return `[RealtimeEmbed] No mockup after ${Math.round(me / 1e3)}s. Common causes: a variant product missing \`variantId\` (pass \`product.options\` so the embed can flag it up front), a multi-placement product (the server waits for every required placement but <RealtimeEmbed> sends only "${t}" — pass \`product.requiredPlacements\` so this is flagged at mount; such products need the eject path), an unreachable or non-public asset URL in the design, or the placement "${t}" not existing on the product. The render may still arrive — this is a heads-up, not a failure.`;
233
242
  }
234
- function Ae(t) {
243
+ function qe(t) {
235
244
  if ("grantUrl" in t && t.grantUrl)
236
245
  return { grantUrl: t.grantUrl };
237
246
  const e = t.grant;
238
247
  return typeof e == "function" ? { getToken: e } : { getToken: () => Promise.resolve(e) };
239
248
  }
240
249
  function fe({ error: t, onRetry: e }) {
241
- const n = ae(t) ? t.code : "EDITOR_ERROR";
250
+ const r = ae(t) ? t.code : "EDITOR_ERROR";
242
251
  return /* @__PURE__ */ Q(
243
252
  "div",
244
253
  {
@@ -257,7 +266,7 @@ function fe({ error: t, onRetry: e }) {
257
266
  children: [
258
267
  /* @__PURE__ */ Q("p", { style: { margin: 0, fontWeight: 700 }, children: [
259
268
  "Editor failed: ",
260
- n
269
+ r
261
270
  ] }),
262
271
  /* @__PURE__ */ f("p", { style: { margin: "4px 0 0" }, children: t.message }),
263
272
  e ? /* @__PURE__ */ f(
@@ -284,7 +293,7 @@ function fe({ error: t, onRetry: e }) {
284
293
  }
285
294
  );
286
295
  }
287
- class Le extends xe {
296
+ class Me extends xe {
288
297
  constructor() {
289
298
  super(...arguments), this.state = { caught: null };
290
299
  }
@@ -292,44 +301,44 @@ class Le extends xe {
292
301
  return { caught: e };
293
302
  }
294
303
  componentDidCatch(e) {
295
- var n;
296
- oe(e), typeof x < "u" && ((n = x.env) == null ? void 0 : n.NODE_ENV) !== "production" && console.error("[Editor.Root] contained a composition error:", e);
304
+ var r;
305
+ oe(e), typeof x < "u" && ((r = x.env) == null ? void 0 : r.NODE_ENV) !== "production" && console.error("[Editor.Root] contained a composition error:", e);
297
306
  }
298
307
  render() {
299
308
  return this.state.caught ? /* @__PURE__ */ f(fe, { error: this.state.caught }) : this.props.children;
300
309
  }
301
310
  }
302
- function qe({ reportedError: t, onRetry: e, children: n }) {
311
+ function Ve({ reportedError: t, onRetry: e, children: r }) {
303
312
  if (t) {
304
- const r = ae(t) && t.code === "E_CHUNK_LOAD_FAILED";
305
- return /* @__PURE__ */ f(fe, { error: t, onRetry: r ? e : void 0 });
313
+ const n = ae(t) && t.code === "E_CHUNK_LOAD_FAILED";
314
+ return /* @__PURE__ */ f(fe, { error: t, onRetry: n ? e : void 0 });
306
315
  }
307
- return /* @__PURE__ */ f(Le, { reportedError: null, onRetry: e, children: n });
316
+ return /* @__PURE__ */ f(Me, { reportedError: null, onRetry: e, children: r });
308
317
  }
309
- function Me(t) {
318
+ function Pe(t) {
310
319
  const {
311
320
  shop: e,
312
- product: n,
313
- design: r,
321
+ product: r,
322
+ design: n,
314
323
  throttleMs: s = 200,
315
324
  onMockups: a,
316
325
  onRenderError: l,
317
326
  wsUrl: i,
318
327
  services: o,
319
328
  children: u,
320
- internals: m,
329
+ internals: c,
321
330
  __validation: d = "throw"
322
- } = t, c = I(() => r.toJSON().activeArtboard, [r]), y = Ce(n.variantId ?? n.defaultGvid), g = I(() => {
331
+ } = t, m = I(() => n.toJSON().activeArtboard, [n]), y = Oe(r.variantId ?? r.defaultGvid), g = I(() => {
323
332
  if (!y) return null;
324
- const h = r.toJSON().artboards[0];
325
- return Ne(y, h) ?? null;
326
- }, [y, r]), b = T(a), p = T(l);
333
+ const h = n.toJSON().artboards[0];
334
+ return ke(y, h) ?? null;
335
+ }, [y, n]), b = N(a), p = N(l);
327
336
  b.current = a, p.current = l;
328
- const [S, q] = O([]), [C, N] = O(!0), [H, B] = O(null), M = !!("grantUrl" in t && t.grantUrl || "grant" in t && t.grant), V = Ae(t), ye = "grantUrl" in V ? V.grantUrl : "getToken", W = `${n.productId}|${n.mockupIds.join(",")}|${n.variantId ?? ""}`, D = `${e}|${W}|${c}|${M}`;
337
+ const [S, q] = O([]), [C, T] = O(!0), [H, B] = O(null), M = !!("grantUrl" in t && t.grantUrl || "grant" in t && t.grant), V = qe(t), ye = "grantUrl" in V ? V.grantUrl : "getToken", W = `${r.productId}|${r.mockupIds.join(",")}|${r.variantId ?? ""}`, F = `${e}|${W}|${m}|${M}`;
329
338
  I(() => {
330
339
  var E;
331
340
  if (d !== "throw") return;
332
- const h = ue({ shop: e, product: n, design: r, hasGrant: M }), v = h.find((k) => k.severity === "error");
341
+ const h = ue({ shop: e, product: r, design: n, hasGrant: M }), v = h.find((k) => k.severity === "error");
333
342
  if (v)
334
343
  throw new R("E_EMBED_CONFIG", v.message, {
335
344
  issue: v.issue,
@@ -337,116 +346,116 @@ function Me(t) {
337
346
  });
338
347
  for (const k of h)
339
348
  typeof x < "u" && ((E = x.env) == null ? void 0 : E.NODE_ENV) !== "production" && console.warn(`[Editor.Root] ${k.message}`);
340
- }, [D, d]);
341
- const z = T(null);
349
+ }, [F, d]);
350
+ const z = N(null);
342
351
  $(() => {
343
352
  var h;
344
353
  if (d === "warn" && typeof x < "u" && ((h = x.env) == null ? void 0 : h.NODE_ENV) !== "production") {
345
- if (z.current === D) return;
346
- z.current = D, $e({ shop: e, product: n, design: r, hasGrant: M });
354
+ if (z.current === F) return;
355
+ z.current = F, Fe({ shop: e, product: r, design: n, hasGrant: M });
347
356
  }
348
- }, [D, d]);
349
- const F = I(
357
+ }, [F, d]);
358
+ const D = I(
350
359
  () => {
351
360
  try {
352
- return { session: new Se({ shop: e, product: n, wsUrl: i, ...V }) };
361
+ return { session: new Se({ shop: e, product: r, wsUrl: i, ...V }) };
353
362
  } catch (h) {
354
363
  return { error: h instanceof Error ? h.message : String(h) };
355
364
  }
356
365
  },
357
366
  // eslint-disable-next-line react-hooks/exhaustive-deps
358
- [e, W, c, i, ye]
359
- ), w = "session" in F ? F.session : null, U = "error" in F ? F.error : null, P = I(() => (h, v = s) => {
360
- w && (B(null), N(!0), w.renderState(c, h, v).catch((E) => {
367
+ [e, W, m, i, ye]
368
+ ), w = "session" in D ? D.session : null, U = "error" in D ? D.error : null, P = I(() => (h, v = s) => {
369
+ w && (B(null), T(!0), w.renderState(m, h, v).catch((E) => {
361
370
  var Y;
362
371
  const k = E instanceof Error ? E.message : String(E);
363
- B(k), N(!1), (Y = p.current) == null || Y.call(p, k);
372
+ B(k), T(!1), (Y = p.current) == null || Y.call(p, k);
364
373
  }));
365
- }, [w, c, s]);
374
+ }, [w, m, s]);
366
375
  $(() => {
367
376
  var h;
368
377
  if (U) {
369
- B(U), N(!1), (h = p.current) == null || h.call(p, U);
378
+ B(U), T(!1), (h = p.current) == null || h.call(p, U);
370
379
  return;
371
380
  }
372
381
  if (w)
373
382
  return w.onMockups((v) => {
374
383
  var E;
375
- q(v), N(!1), (E = b.current) == null || E.call(b, v);
384
+ q(v), T(!1), (E = b.current) == null || E.call(b, v);
376
385
  }), w.onError((v) => {
377
386
  var E;
378
- B(v), N(!1), (E = p.current) == null || E.call(p, v);
379
- }), P(r.toServerRequest()), () => w.close();
387
+ B(v), T(!1), (E = p.current) == null || E.call(p, v);
388
+ }), P(n.toServerRequest()), () => w.close();
380
389
  }, [w, U]), $(() => {
381
390
  var v;
382
391
  if (!C || typeof x > "u" || ((v = x.env) == null ? void 0 : v.NODE_ENV) === "production") return;
383
- const h = setTimeout(() => console.warn(Ue(c)), me);
392
+ const h = setTimeout(() => console.warn(Ae(m)), me);
384
393
  return () => clearTimeout(h);
385
- }, [C, c]);
394
+ }, [C, m]);
386
395
  const ve = I(
387
396
  () => ({
388
397
  session: w,
389
- design: r,
390
- placement: c,
391
- product: n,
398
+ design: n,
399
+ placement: m,
400
+ product: r,
392
401
  mockups: S,
393
402
  isRendering: C,
394
403
  error: H,
395
404
  throttleMs: s,
396
405
  pieceGuides: g,
397
406
  pushRender: P,
398
- stateStore: m.store
407
+ stateStore: c.store
399
408
  }),
400
- [w, r, c, n, S, C, H, s, g, P, m.store]
401
- ), be = A(
402
- m.registry.subscribe,
403
- m.registry.getVersion,
404
- m.registry.getVersion
409
+ [w, n, m, r, S, C, H, s, g, P, c.store]
410
+ ), be = L(
411
+ c.registry.subscribe,
412
+ c.registry.getVersion,
413
+ c.registry.getVersion
405
414
  );
406
- I(() => m.registry.validate(), [m.registry, be]);
407
- const J = /* @__PURE__ */ f(ce.Provider, { value: m, children: /* @__PURE__ */ f(de.Provider, { value: ve, children: u }) });
415
+ I(() => c.registry.validate(), [c.registry, be]);
416
+ const J = /* @__PURE__ */ f(ce.Provider, { value: c, children: /* @__PURE__ */ f(de.Provider, { value: ve, children: /* @__PURE__ */ f(Te.Provider, { value: c.registry, children: /* @__PURE__ */ f(Ne, { children: u }) }) }) });
408
417
  return o ? /* @__PURE__ */ f(Ee, { services: o, children: J }) : J;
409
418
  }
410
419
  function he(t) {
411
- const { design: e } = t, n = T(null), [r, s] = O(null);
412
- (n.current === null || n.current.design !== e) && (n.current = {
420
+ const { design: e } = t, r = N(null), [n, s] = O(null);
421
+ (r.current === null || r.current.design !== e) && (r.current = {
413
422
  design: e,
414
423
  internals: {
415
- store: new Be(e.toJSON()),
416
- registry: new De()
424
+ store: new De(e.toJSON()),
425
+ registry: new Ue()
417
426
  }
418
427
  });
419
428
  const a = I(
420
429
  () => ({
421
- ...n.current.internals,
422
- ...Fe(s)
430
+ ...r.current.internals,
431
+ ...Le(s)
423
432
  }),
424
433
  // eslint-disable-next-line react-hooks/exhaustive-deps
425
- [n.current.internals]
434
+ [r.current.internals]
426
435
  );
427
436
  return (
428
437
  // `display: contents` — the .sc-root scope without a layout box, so the
429
438
  // host's grid/flex sees the parts directly (and the legacy RealtimeEmbed
430
439
  // wrapper, which had no DOM at all, stays layout-identical).
431
- /* @__PURE__ */ f("div", { className: "sc-root", style: { display: "contents" }, "data-sc-part": "root", children: /* @__PURE__ */ f(qe, { reportedError: r, onRetry: () => s(null), children: /* @__PURE__ */ f(Me, { ...t, internals: a }) }) })
440
+ /* @__PURE__ */ f("div", { className: "sc-root", style: { display: "contents" }, "data-sc-part": "root", children: /* @__PURE__ */ f(Ve, { reportedError: n, onRetry: () => s(null), children: /* @__PURE__ */ f(Pe, { ...t, internals: a }) }) })
432
441
  );
433
442
  }
434
- let Ve = () => import("./EditorCanvasImpl-DkgE5-C2.js").then((t) => t.EditorCanvasImpl);
443
+ let je = () => import("./EditorCanvasImpl-DgXvuWXX.js").then((t) => t.EditorCanvasImpl);
435
444
  function ge() {
436
- return Ve();
445
+ return je();
437
446
  }
438
- const Pe = te(function({ children: e, maxHeight: n, className: r, style: s }, a) {
439
- const l = G("Editor.Canvas"), i = ne();
440
- re(() => l.registry.registerCanvas(i), [l.registry, i]);
447
+ const Ge = te(function({ children: e, maxHeight: r, className: n, style: s }, a) {
448
+ const l = K("Editor.Canvas"), i = re();
449
+ ne(() => l.registry.registerCanvas(i), [l.registry, i]);
441
450
  const [o, u] = O(null);
442
451
  return $(() => {
443
- let m = !1;
452
+ let c = !1;
444
453
  return ge().then(
445
454
  (d) => {
446
- m || u(() => d);
455
+ c || u(() => d);
447
456
  },
448
457
  (d) => {
449
- m || l.reportRuntimeError(
458
+ c || l.reportRuntimeError(
450
459
  new R(
451
460
  "E_CHUNK_LOAD_FAILED",
452
461
  `the editor's rendering chunk failed to load (${d instanceof Error ? d.message : String(d)}). This is a network/CDN failure, not a composition mistake — retry, or check the deployment serves the @snowcone-app/canvas lazy chunks.`,
@@ -455,45 +464,45 @@ const Pe = te(function({ children: e, maxHeight: n, className: r, style: s }, a)
455
464
  );
456
465
  }
457
466
  ), () => {
458
- m = !0;
467
+ c = !0;
459
468
  };
460
- }, [l]), o ? /* @__PURE__ */ f(o, { ref: a, kit: "embed-only", partAttr: "canvas", maxHeight: n, className: r, style: s, children: e }) : /* @__PURE__ */ f(
469
+ }, [l]), o ? /* @__PURE__ */ f(o, { ref: a, kit: "embed-only", partAttr: "canvas", maxHeight: r, className: n, style: s, children: e }) : /* @__PURE__ */ f(
461
470
  "div",
462
471
  {
463
472
  "data-sc-part": "canvas",
464
473
  "data-sc-state": "loading",
465
- className: r,
466
- style: { minHeight: n ?? 200, ...s },
474
+ className: n,
475
+ style: { minHeight: r ?? 200, ...s },
467
476
  "aria-busy": "true"
468
477
  }
469
478
  );
470
- }), je = 1.2, K = [1200, 1400, 1600, 1800, 2e3, 2500, 3e3, 4e3];
471
- function Ke(t) {
472
- for (const e of K)
479
+ }), Ke = 1.2, G = [1200, 1400, 1600, 1800, 2e3, 2500, 3e3, 4e3];
480
+ function He(t) {
481
+ for (const e of G)
473
482
  if (e >= t) return e;
474
- return K[K.length - 1];
483
+ return G[G.length - 1];
475
484
  }
476
- function Ge(t, e) {
477
- if (!(t > 0) || !(e > 0) || e <= t * je) return null;
478
- const n = Ke(e);
479
- return `[RealtimeMockup] mockup rendered at ${t}px but displayed at ~${e} device px — the preview will look soft. Pass \`product.width\` (e.g. ${n}) on the embed for a crisp preview.`;
485
+ function We(t, e) {
486
+ if (!(t > 0) || !(e > 0) || e <= t * Ke) return null;
487
+ const r = He(e);
488
+ return `[RealtimeMockup] mockup rendered at ${t}px but displayed at ~${e} device px — the preview will look soft. Pass \`product.width\` (e.g. ${r}) on the embed for a crisp preview.`;
480
489
  }
481
490
  function pe({
482
491
  mockupId: t,
483
492
  fallback: e = null,
484
- alt: n = "Live product mockup",
485
- className: r,
493
+ alt: r = "Live product mockup",
494
+ className: n,
486
495
  style: s
487
496
  }) {
488
- const { mockups: a } = L(), l = T(/* @__PURE__ */ new Set()), i = t ? a.find((u) => u.mockupId === t && u.imageUrl) : a.find((u) => u.imageUrl);
497
+ const { mockups: a } = A(), l = N(/* @__PURE__ */ new Set()), i = t ? a.find((u) => u.mockupId === t && u.imageUrl) : a.find((u) => u.imageUrl);
489
498
  if (!(i != null && i.imageUrl))
490
499
  return /* @__PURE__ */ f(we, { children: e });
491
500
  const o = (u) => {
492
501
  var g;
493
502
  if (typeof x > "u" || ((g = x.env) == null ? void 0 : g.NODE_ENV) === "production" || typeof window > "u" || l.current.has(i.mockupId)) return;
494
- const m = u.currentTarget, d = m.getBoundingClientRect().width;
503
+ const c = u.currentTarget, d = c.getBoundingClientRect().width;
495
504
  if (d <= 0) return;
496
- const c = Math.round(d * (window.devicePixelRatio || 1)), y = Ge(m.naturalWidth, c);
505
+ const m = Math.round(d * (window.devicePixelRatio || 1)), y = We(c.naturalWidth, m);
497
506
  y && (l.current.add(i.mockupId), console.warn(y));
498
507
  };
499
508
  return (
@@ -503,17 +512,17 @@ function pe({
503
512
  {
504
513
  "data-sc-part": "preview",
505
514
  src: i.imageUrl,
506
- alt: n,
507
- className: r,
515
+ alt: r,
516
+ className: n,
508
517
  style: s,
509
518
  onLoad: o
510
519
  }
511
520
  )
512
521
  );
513
522
  }
514
- function He(t) {
515
- const { layer: e, optional: n = !1, placeholder: r, className: s, style: a } = t, l = G("Editor.TextField"), { pushRender: i, throttleMs: o, stateStore: u } = L(), m = ne(), d = T(null);
516
- if (!Oe(e))
523
+ function ze(t) {
524
+ const { layer: e, optional: r = !1, placeholder: n, className: s, style: a } = t, l = K("Editor.TextField"), { pushRender: i, throttleMs: o, stateStore: u } = A(), c = re(), d = N(null);
525
+ if (!_e(e))
517
526
  throw new R(
518
527
  "E_LAYER_TOKEN_REQUIRED",
519
528
  `the \`layer\` prop must be a token minted by the design — pass layer={design.layer("name")}, not ${typeof e == "string" ? `the bare string "${e}"` : "a plain value"}. Tokens validate the name against the design's layers at mint time.`,
@@ -535,8 +544,8 @@ function He(t) {
535
544
  );
536
545
  d.current = e.name;
537
546
  }
538
- re(() => l.registry.registerTextField(m, { name: e.name, optional: n }), [l.registry, m, e.name, n]);
539
- const c = A(
547
+ ne(() => l.registry.registerTextField(c, { name: e.name, optional: r }), [l.registry, c, e.name, r]);
548
+ const m = L(
540
549
  u.subscribe,
541
550
  () => u.textOf(e.name) ?? "",
542
551
  () => u.textOf(e.name) ?? ""
@@ -563,16 +572,16 @@ function He(t) {
563
572
  "data-sc-part": "textfield",
564
573
  "data-sc-layer": e.name,
565
574
  type: "text",
566
- value: c,
575
+ value: m,
567
576
  onChange: y,
568
- placeholder: r,
577
+ placeholder: n,
569
578
  "aria-label": t["aria-label"] ?? e.name,
570
579
  className: s,
571
580
  style: a
572
581
  }
573
582
  );
574
583
  }
575
- function We(t) {
584
+ function Je(t) {
576
585
  const e = [];
577
586
  if (t.product.options)
578
587
  try {
@@ -580,22 +589,22 @@ function We(t) {
580
589
  } catch {
581
590
  e.push("variant");
582
591
  }
583
- for (const n of t.textFields) {
584
- if (n.optional) continue;
585
- const r = (t.textOf(n.name) ?? "").trim();
586
- if (r.length === 0) {
587
- e.push(`layer:${n.name}`);
592
+ for (const r of t.textFields) {
593
+ if (r.optional) continue;
594
+ const n = (t.textOf(r.name) ?? "").trim();
595
+ if (n.length === 0) {
596
+ e.push(`layer:${r.name}`);
588
597
  continue;
589
598
  }
590
- const s = (t.seedTextOf(n.name) ?? "").trim();
591
- s.length > 0 && r === s && e.push(`layer-seed:${n.name}`);
599
+ const s = (t.seedTextOf(r.name) ?? "").trim();
600
+ s.length > 0 && n === s && e.push(`layer-seed:${r.name}`);
592
601
  }
593
602
  return t.hasRenderableElement || e.push("empty-design"), (!Number.isInteger(t.quantity) || t.quantity < 1) && e.push("quantity"), e;
594
603
  }
595
- function ze(t, e) {
596
- const n = t.options, r = n == null ? void 0 : n.combinations;
597
- if (!n || !(r != null && r.length)) return null;
598
- const s = r.find((i) => i.variantId && i.variantId === t.variantId) ?? r[0];
604
+ function Ye(t, e) {
605
+ const r = t.options, n = r == null ? void 0 : r.combinations;
606
+ if (!r || !(n != null && n.length)) return null;
607
+ const s = n.find((i) => i.variantId && i.variantId === t.variantId) ?? n[0];
599
608
  if (!s) return null;
600
609
  const a = {};
601
610
  for (const [i, o] of Object.entries(s))
@@ -603,108 +612,108 @@ function ze(t, e) {
603
612
  const l = Object.fromEntries(
604
613
  Object.keys(a).map((i) => [
605
614
  i,
606
- { key: i, affectsCombinations: !0, choices: [...new Set(r.map((o) => String(o[i] ?? "")))] }
615
+ { key: i, affectsCombinations: !0, choices: [...new Set(n.map((o) => String(o[i] ?? "")))] }
607
616
  ])
608
617
  );
609
618
  return Ie({
610
619
  productId: t.productId,
611
620
  quantity: e,
612
621
  selection: a,
613
- combinations: r,
622
+ combinations: n,
614
623
  attributes: l
615
624
  });
616
625
  }
617
- function Je(t) {
618
- const { onAddToCart: e, quantity: n = 1, children: r, className: s, style: a } = t, l = G("Editor.Buy"), { product: i, stateStore: o } = L();
626
+ function Qe(t) {
627
+ const { onAddToCart: e, quantity: r = 1, children: n, className: s, style: a } = t, l = K("Editor.Buy"), { product: i, stateStore: o } = A();
619
628
  if (!(i != null && i.productId))
620
629
  throw new R(
621
630
  "E_BUY_NO_PRODUCT",
622
631
  "<Editor.Buy> has no product context — pass `product` (with `productId`) on <Editor.Root product={…}>. Buy assembles its cart payload from the Root product and the live design state.",
623
632
  { docSlug: "embed-mode" }
624
633
  );
625
- const u = A(o.subscribe, o.getState, o.getState), m = A(
634
+ const u = L(o.subscribe, o.getState, o.getState), c = L(
626
635
  l.registry.subscribe,
627
636
  l.registry.getVersion,
628
637
  l.registry.getVersion
629
638
  ), d = I(
630
- () => We({
639
+ () => Je({
631
640
  product: i,
632
- quantity: n,
641
+ quantity: r,
633
642
  textFields: l.registry.getTextFields(),
634
643
  textOf: (S) => o.textOf(S),
635
644
  seedTextOf: (S) => o.seedTextOf(S),
636
645
  hasRenderableElement: o.hasRenderableElement()
637
646
  }),
638
647
  // eslint-disable-next-line react-hooks/exhaustive-deps
639
- [i, n, u, m]
640
- ), c = d.length === 0, [y, g] = O(!1), b = T(!1), p = se(() => {
641
- if (b.current || !c) return;
648
+ [i, r, u, c]
649
+ ), m = d.length === 0, [y, g] = O(!1), b = N(!1), p = se(() => {
650
+ if (b.current || !m) return;
642
651
  b.current = !0, g(!0);
643
652
  const S = o.getState(), q = {
644
653
  productId: i.productId,
645
654
  ...i.variantId ? { variantId: i.variantId } : {},
646
- quantity: n,
647
- cartDetail: ze(i, n),
655
+ quantity: r,
656
+ cartDetail: Ye(i, r),
648
657
  designState: S,
649
658
  serverRequest: le(S)
650
659
  };
651
660
  let C;
652
661
  try {
653
662
  C = e(q);
654
- } catch (N) {
655
- throw b.current = !1, g(!1), N;
663
+ } catch (T) {
664
+ throw b.current = !1, g(!1), T;
656
665
  }
657
666
  Promise.resolve(C).finally(() => {
658
667
  b.current = !1, g(!1);
659
668
  });
660
- }, [c, i, n, o, e]);
669
+ }, [m, i, r, o, e]);
661
670
  return /* @__PURE__ */ f(
662
671
  "button",
663
672
  {
664
673
  type: "button",
665
674
  "data-sc-part": "buy",
666
- "data-sc-buy-state": y ? "busy" : c ? "ready" : "incomplete",
675
+ "data-sc-buy-state": y ? "busy" : m ? "ready" : "incomplete",
667
676
  "data-sc-buy-missing": d.join(",") || void 0,
668
- disabled: !c || y,
677
+ disabled: !m || y,
669
678
  "aria-busy": y || void 0,
670
679
  onClick: p,
671
680
  className: s,
672
681
  style: a,
673
- children: r ?? "Add to cart"
682
+ children: n ?? "Add to cart"
674
683
  }
675
684
  );
676
685
  }
677
- const ot = {
686
+ const lt = {
678
687
  /** The one provider boundary — session, design, live state, error boundary. */
679
688
  Root: he,
680
689
  /** The editable artboard (the ONE lazy renderer boundary — D9). */
681
- Canvas: Pe,
690
+ Canvas: Ge,
682
691
  /** Live product mockup. ×N under one Root is valid. */
683
692
  Preview: pe,
684
693
  /** Form input bound to a design text layer by typed token (T1). */
685
- TextField: He,
694
+ TextField: ze,
686
695
  /** Smart commerce part: completeness + payload assembly; submit = host callback. */
687
- Buy: Je
696
+ Buy: Qe
688
697
  };
689
- function lt(t) {
698
+ function dt(t) {
690
699
  return /* @__PURE__ */ f(he, { ...t, __validation: "warn" });
691
700
  }
692
- const dt = te(
693
- function(e, n) {
694
- const { children: r, className: s, style: a, maxHeight: l, ...i } = e, [o, u] = O(null);
701
+ const ut = te(
702
+ function(e, r) {
703
+ const { children: n, className: s, style: a, maxHeight: l, ...i } = e, [o, u] = O(null);
695
704
  return $(() => {
696
- let m = !1;
705
+ let c = !1;
697
706
  return ge().then(
698
707
  (d) => {
699
- m || u(() => d);
708
+ c || u(() => d);
700
709
  },
701
710
  (d) => {
702
711
  console.error("[RealtimeCanvas] failed to load the rendering chunk:", d);
703
712
  }
704
713
  ), () => {
705
- m = !0;
714
+ c = !0;
706
715
  };
707
- }, []), o ? /* @__PURE__ */ f(o, { ref: n, selfScope: !0, maxHeight: l, className: s, style: a, ...i, children: r }) : /* @__PURE__ */ f(
716
+ }, []), o ? /* @__PURE__ */ f(o, { ref: r, selfScope: !0, maxHeight: l, className: s, style: a, ...i, children: n }) : /* @__PURE__ */ f(
708
717
  "div",
709
718
  {
710
719
  className: `sc-root${s ? ` ${s}` : ""}`,
@@ -714,24 +723,24 @@ const dt = te(
714
723
  );
715
724
  }
716
725
  );
717
- function ut(t) {
726
+ function ct(t) {
718
727
  return /* @__PURE__ */ f(pe, { ...t });
719
728
  }
720
- function ct() {
721
- const { mockups: t, isRendering: e, error: n } = L();
722
- return { mockups: t, isRendering: e, error: n };
729
+ function mt() {
730
+ const { mockups: t, isRendering: e, error: r } = A();
731
+ return { mockups: t, isRendering: e, error: r };
723
732
  }
724
733
  Re();
725
734
  export {
726
- Be as D,
735
+ De as D,
727
736
  ce as E,
728
- dt as R,
729
- ot as a,
730
- lt as b,
731
- ut as c,
737
+ ut as R,
738
+ lt as a,
739
+ dt as b,
740
+ ct as c,
732
741
  ue as d,
733
- ct as e,
734
- L as u,
735
- $e as v
742
+ mt as e,
743
+ A as u,
744
+ Fe as v
736
745
  };
737
- //# sourceMappingURL=embed-Bdj4PKUA.js.map
746
+ //# sourceMappingURL=embed-32ZVWfmj.js.map