@snowcone-app/canvas 0.22.0 → 0.26.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.
- package/ERROR_CONTRACT.md +600 -0
- package/README.md +2 -1
- package/STYLING_CONTRACT.md +173 -93
- package/dist/{ContextualToolbars-BDEt9ND0.js → ContextualToolbars-DUhBKVxe.js} +3 -3
- package/dist/{ContextualToolbars-BDEt9ND0.js.map → ContextualToolbars-DUhBKVxe.js.map} +1 -1
- package/dist/{EditorCanvasImpl-BH_bKy-F.js → EditorCanvasImpl-BLZV_el0.js} +6 -6
- package/dist/{EditorCanvasImpl-BH_bKy-F.js.map → EditorCanvasImpl-BLZV_el0.js.map} +1 -1
- package/dist/{ImagePanel-BwqFDKvW.js → ImagePanel-sLSjaPWS.js} +3 -3
- package/dist/{ImagePanel-BwqFDKvW.js.map → ImagePanel-sLSjaPWS.js.map} +1 -1
- package/dist/{SnowconeCanvas-Cx7nXlBI.js → SnowconeCanvas-4ef4a61J.js} +6 -6
- package/dist/{SnowconeCanvas-Cx7nXlBI.js.map → SnowconeCanvas-4ef4a61J.js.map} +1 -1
- package/dist/{UnifiedFontService-CC3CSmH5.js → UnifiedFontService-Bx2MxFfy.js} +867 -834
- package/dist/{UnifiedFontService-CC3CSmH5.js.map → UnifiedFontService-Bx2MxFfy.js.map} +1 -1
- package/dist/advanced.mjs +7 -7
- package/dist/api/embed.d.ts +4 -4
- package/dist/components/editor/EditorLoadingOverlay.d.ts +12 -0
- package/dist/components/editor/EditorPlacements.d.ts +14 -0
- package/dist/components/editor/EditorPreview.d.ts +32 -8
- package/dist/components/editor/EditorRoot.d.ts +12 -0
- package/dist/components/editor/PreviewPrismOverlay.d.ts +23 -0
- package/dist/components/editor/RootInternals.d.ts +31 -0
- package/dist/components/editor/editorAudit.d.ts +66 -0
- package/dist/components/editor/index.d.ts +14 -0
- package/dist/components/editor/usePlacements.d.ts +14 -0
- package/dist/components/embed-realtime/context.d.ts +11 -2
- package/dist/components/embed-realtime/validateEmbed.d.ts +20 -1
- package/dist/{custom-icons-BW6hqmkL.js → custom-icons-DeYIrTK1.js} +7 -7
- package/dist/{custom-icons-BW6hqmkL.js.map → custom-icons-DeYIrTK1.js.map} +1 -1
- package/dist/design/design-builder.d.ts +108 -15
- package/dist/design/product-config.d.ts +10 -0
- package/dist/design-builder-U7Su9MMC.js +470 -0
- package/dist/design-builder-U7Su9MMC.js.map +1 -0
- package/dist/editorErrors-B2mb1sVN.js.map +1 -1
- package/dist/embed-DXGydZOT.js +1586 -0
- package/dist/embed-DXGydZOT.js.map +1 -0
- package/dist/embed.mjs +34 -31
- package/dist/errors/editorError.d.ts +27 -1
- package/dist/hooks/bindingGuards.d.ts +16 -0
- package/dist/hooks/useColorBinding.d.ts +2 -1
- package/dist/hooks/useFontBinding.d.ts +2 -1
- package/dist/hooks/useImageBinding.d.ts +2 -1
- package/dist/hooks/useTextBinding.d.ts +2 -1
- package/dist/index.mjs +6 -6
- package/dist/style.css +1 -1
- package/dist/template-fields-DJ157D3E.js +548 -0
- package/dist/template-fields-DJ157D3E.js.map +1 -0
- package/dist/testing/failureFixtures.d.ts +2 -2
- package/dist/testing.mjs +1 -1
- package/dist/{validation-C9Fe9ahK.js → validation-DnAkXdUg.js} +7 -7
- package/dist/{validation-C9Fe9ahK.js.map → validation-DnAkXdUg.js.map} +1 -1
- package/example/package.json +1 -1
- package/llms.txt +3 -0
- package/package.json +6 -3
- package/dist/design-builder-CT4DHIPe.js +0 -367
- package/dist/design-builder-CT4DHIPe.js.map +0 -1
- package/dist/embed-8ecUMMH-.js +0 -1226
- package/dist/embed-8ecUMMH-.js.map +0 -1
- package/dist/template-fields-C2pSfMBh.js +0 -494
- package/dist/template-fields-C2pSfMBh.js.map +0 -1
|
@@ -0,0 +1,1586 @@
|
|
|
1
|
+
import { E as Le, o as Ve, p as Be, C as Fe, q as H, r as J, t as Ue, v as Me, w as je, x as qe, y as ze, g as Ke, e as We } from "./UnifiedFontService-Bx2MxFfy.js";
|
|
2
|
+
import { y as L } from "./FontAnalyzer-CwIpgTGd.js";
|
|
3
|
+
import { jsx as l, jsxs as N, Fragment as Ge } from "react/jsx-runtime";
|
|
4
|
+
import { useContext as He, createContext as Je, useRef as x, useState as C, useMemo as O, useCallback as F, useLayoutEffect as Q, useEffect as $, useSyncExternalStore as z, Component as Qe, forwardRef as be, useId as de, memo as Ye, isValidElement as we } from "react";
|
|
5
|
+
import { assertVariantSelected as Xe, RenderSession as Ze, createCartDetail as et } from "@snowcone-app/sdk";
|
|
6
|
+
import { g as T, i as Ee, B as tt, E as nt, r as rt } from "./editorErrors-B2mb1sVN.js";
|
|
7
|
+
import { u as ot, p as it } from "./usePieceGuideBundle-CbJJg66S.js";
|
|
8
|
+
import { s as le, i as st } from "./design-builder-U7Su9MMC.js";
|
|
9
|
+
import { D as at, C as dt, g as lt, e as ct } from "./template-fields-DJ157D3E.js";
|
|
10
|
+
import "./CanvasStateV1-DmZ1Qvvn.js";
|
|
11
|
+
const xe = Je(void 0);
|
|
12
|
+
function K() {
|
|
13
|
+
const t = He(xe);
|
|
14
|
+
if (!t)
|
|
15
|
+
throw new Error(
|
|
16
|
+
"useRealtimeMockups / <RealtimeCanvas> / <RealtimeMockup> must be rendered inside <RealtimeEmbed>. Wrap them: <RealtimeEmbed shop=… product=… design=… grantUrl=…>…</RealtimeEmbed>"
|
|
17
|
+
);
|
|
18
|
+
return t;
|
|
19
|
+
}
|
|
20
|
+
const ut = "[RealtimeEmbed]";
|
|
21
|
+
function mt(t) {
|
|
22
|
+
var r, i;
|
|
23
|
+
if ((r = t == null ? void 0 : t.requiredPlacements) != null && r.length)
|
|
24
|
+
return t.requiredPlacements.filter((s) => !s.autoFilledByVariant).map((s) => s.label);
|
|
25
|
+
const e = new Set(
|
|
26
|
+
(((i = t == null ? void 0 : t.options) == null ? void 0 : i.combinations) ?? []).map((s) => s.variantId).filter((s) => typeof s == "string" && s !== "")
|
|
27
|
+
);
|
|
28
|
+
return !!(t != null && t.variantId) || e.size > 1 ? [] : (t == null ? void 0 : t.placements) ?? [];
|
|
29
|
+
}
|
|
30
|
+
function Re({ shop: t, product: e, design: n, hasGrant: r }) {
|
|
31
|
+
var y, b;
|
|
32
|
+
const i = [];
|
|
33
|
+
if (t || i.push({
|
|
34
|
+
severity: "error",
|
|
35
|
+
issue: "missing-shop",
|
|
36
|
+
message: "`shop` is required (your publishable shop id)."
|
|
37
|
+
}), r || i.push({
|
|
38
|
+
severity: "error",
|
|
39
|
+
issue: "missing-grant",
|
|
40
|
+
message: "no grant source — pass `grantUrl` (a proxy to mintRealtimeGrant) or `grant`. Without it the session can never authorize and no mockup renders."
|
|
41
|
+
}), (y = e == null ? void 0 : e.mockupIds) != null && y.length || i.push({
|
|
42
|
+
severity: "error",
|
|
43
|
+
issue: "empty-mockup-ids",
|
|
44
|
+
message: 'product.mockupIds is empty — pass the catalog scene codes (product.mockups[].id) you want rendered, e.g. ["FV1qjO"].'
|
|
45
|
+
}), e != null && e.options)
|
|
46
|
+
try {
|
|
47
|
+
Xe(e);
|
|
48
|
+
} catch (o) {
|
|
49
|
+
i.push({
|
|
50
|
+
severity: "error",
|
|
51
|
+
issue: "variant-required",
|
|
52
|
+
message: o instanceof Error ? o.message : String(o)
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
const s = n.toJSON(), d = s.artboards.map((o) => o.name), c = mt(e), u = c.filter((o) => !d.includes(o));
|
|
56
|
+
c.length > 1 && u.length > 0 && i.push({
|
|
57
|
+
severity: "error",
|
|
58
|
+
issue: "multi-placement",
|
|
59
|
+
message: `product ${e.productId} requires placements [${c.join(", ")}] but the design only has artboards [${d.join(", ")}] — missing [${u.join(", ")}]. The render would time out waiting for the missing canvas_states. Add each missing placement to the seed: design(…).artboard('` + u[0] + "', { width, height })… (ADR-0088), or use the eject path — see https://developers.snowcone.app/embed-mode#eject."
|
|
60
|
+
});
|
|
61
|
+
const a = (b = e == null ? void 0 : e.placements) != null && b.length ? d.filter((o) => !e.placements.includes(o)) : [];
|
|
62
|
+
a.length > 0 && i.push({
|
|
63
|
+
severity: "error",
|
|
64
|
+
issue: "placement-mismatch",
|
|
65
|
+
message: `the design's artboard(s) [${a.join(", ")}] are not in product.placements [${e.placements.join(", ")}]. Every artboard name must equal a real product placement label (renderState targets placements by that name), or the server renders a blank mockup. Fix the \`name\` passed to design({ name }) / design().artboard(name, …).`
|
|
66
|
+
});
|
|
67
|
+
const p = s.elements.map((o) => o.name).filter((o) => !!o), m = p.filter((o, g) => p.indexOf(o) !== g);
|
|
68
|
+
return m.length && i.push({
|
|
69
|
+
severity: "warn",
|
|
70
|
+
issue: "duplicate-layer-names",
|
|
71
|
+
message: `duplicate layer name(s) [${[...new Set(m)].join(", ")}] — useTextBinding(name) / useImageBinding(name) bind to the FIRST match, so a duplicate name makes a control edit the wrong layer. Keep names unique.`
|
|
72
|
+
}), i;
|
|
73
|
+
}
|
|
74
|
+
function ft(t) {
|
|
75
|
+
for (const e of Re(t))
|
|
76
|
+
(e.severity === "error" && e.issue !== "placement-mismatch" ? console.error : console.warn)(`${ut} ${e.message}`);
|
|
77
|
+
}
|
|
78
|
+
function Se({ registry: t, store: e, product: n }) {
|
|
79
|
+
const r = [], i = t.getParts(), s = t.getTextFields(), d = t.requiresCanvasPartNames();
|
|
80
|
+
d.length > 0 && !t.hasCanvas() && r.push({
|
|
81
|
+
code: "A_REQUIRES_CANVAS",
|
|
82
|
+
severity: "error",
|
|
83
|
+
message: `${d.join(", ")} ${d.length === 1 ? "is" : "are"} mounted with no <Editor.Canvas> under this Root — they operate on the editable artboard (selection, editor commands) and throw E_REQUIRES_CANVAS.`,
|
|
84
|
+
fix: `Mount <Editor.Canvas/> under the same <Editor.Root>, or remove ${d.join(", ")}. Canvas-free parts: Editor.Preview, Editor.Buy, Editor.TextField, Editor.Layers.`
|
|
85
|
+
});
|
|
86
|
+
const c = i.filter((o) => o.name === "Editor.Canvas").some((o) => o.meta.floatingToolbar !== !1);
|
|
87
|
+
t.hasDockedControls() && c && r.push({
|
|
88
|
+
code: "A_CONTROLS_INERT",
|
|
89
|
+
severity: "warn",
|
|
90
|
+
message: "a docked <Editor.Controls> is mounted while <Editor.Canvas> still has floatingToolbar={true} (the default) — both contextual zones are armed, and the floating toolbar is suppressed only as a side effect of the docked Controls being mounted this frame (it silently reappears when the Controls unmounts).",
|
|
91
|
+
fix: 'Declare contextual-zone ownership in the type surface: pass floatingToolbar={false} on <Editor.Canvas> when a <Editor.Controls placement="docked"> owns the zone.'
|
|
92
|
+
});
|
|
93
|
+
const u = (n == null ? void 0 : n.mockupIds) ?? [];
|
|
94
|
+
if (u.length > 1) {
|
|
95
|
+
const o = i.filter((g) => g.name === "Editor.Preview" && g.meta.mockupId === void 0);
|
|
96
|
+
o.length > 0 && r.push({
|
|
97
|
+
code: "A_PREVIEW_AMBIGUOUS",
|
|
98
|
+
severity: "warn",
|
|
99
|
+
message: `${o.length} <Editor.Preview> part${o.length === 1 ? " has" : "s have"} no mockupId while the product renders ${u.length} mockup scenes [${u.join(", ")}] — each shows whichever scene renders first, an ambiguous fan-out.`,
|
|
100
|
+
fix: `Pin each <Editor.Preview> to a scene: mockupId="${u[0]}" (one of product.mockupIds).`
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
const a = i.some((o) => o.name === "Editor.Buy");
|
|
104
|
+
if (s.length > 0 && !a) {
|
|
105
|
+
const o = s.map((g) => g.name);
|
|
106
|
+
r.push({
|
|
107
|
+
code: "A_NO_BUY",
|
|
108
|
+
severity: "info",
|
|
109
|
+
message: `<Editor.TextField> parts are mounted (layers [${o.join(", ")}]) but no <Editor.Buy> — personalization has no commerce gate, so nothing enforces completeness (C2/C3) before the design is bought.`,
|
|
110
|
+
fix: "Mount <Editor.Buy onAddToCart={…}/> under the same <Editor.Root> (it assembles the payload and gates on completeness), or ignore if this composition is deliberately non-commerce."
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
const p = [];
|
|
114
|
+
for (const o of s)
|
|
115
|
+
e.layerKindOf(o.name) === void 0 ? r.push({
|
|
116
|
+
code: "A_LAYER_UNMATCHED",
|
|
117
|
+
severity: "error",
|
|
118
|
+
message: `<Editor.TextField layer={design.layer("${o.name}")}> matches zero elements in the current design state — the layer was removed or renamed after the field mounted, so the binding is dead and writes will fail. Bindable layers now: ${JSON.stringify(e.bindableLayerNames())}.`,
|
|
119
|
+
fix: `Restore a text layer named "${o.name}" to the design, or bind the field to an existing layer: layer={design.layer(<one of ${JSON.stringify(e.bindableLayerNames())}>)}.`
|
|
120
|
+
}) : p.push(o);
|
|
121
|
+
const m = p.filter((o) => !o.optional);
|
|
122
|
+
if (m.length > 0 && m.every((o) => e.textOf(o.name) === e.seedTextOf(o.name))) {
|
|
123
|
+
const o = m.map((g) => g.name);
|
|
124
|
+
r.push({
|
|
125
|
+
code: "A_TEXT_AT_SEED",
|
|
126
|
+
severity: "info",
|
|
127
|
+
message: `every required <Editor.TextField> still equals its seed value (layers [${o.join(", ")}]) — <Editor.Buy>'s completeness rule C3 gates checkout until the shopper's text differs from the seed (placeholder text must not be bought).`,
|
|
128
|
+
fix: "Nothing to change for a fresh mount — this clears when the shopper edits the fields. For a field that should NOT gate Buy, pass optional on that <Editor.TextField>."
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
e.hasRenderableElement() || r.push({
|
|
132
|
+
code: "A_EMPTY_DESIGN",
|
|
133
|
+
severity: "warn",
|
|
134
|
+
message: "the design state has zero renderable elements (no non-empty text, no image with a URL, no shape) — every mockup renders blank.",
|
|
135
|
+
fix: "Seed content on the builder passed to <Editor.Root design={…}> — design({…}).text(…)/.background(…)/.shape(…) — or add elements through <Editor.Add>."
|
|
136
|
+
});
|
|
137
|
+
const y = /* @__PURE__ */ new Map();
|
|
138
|
+
for (const o of i) y.set(o.name, (y.get(o.name) ?? 0) + 1);
|
|
139
|
+
const b = [...y.entries()].map(([o, g]) => ({ name: o, count: g })).sort((o, g) => o.name.localeCompare(g.name));
|
|
140
|
+
return { findings: r, parts: b };
|
|
141
|
+
}
|
|
142
|
+
const G = [];
|
|
143
|
+
function pt(t) {
|
|
144
|
+
return G.push(t), () => {
|
|
145
|
+
const e = G.indexOf(t);
|
|
146
|
+
e !== -1 && G.splice(e, 1);
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
function rn() {
|
|
150
|
+
const t = G[G.length - 1];
|
|
151
|
+
if (!t)
|
|
152
|
+
throw new T(
|
|
153
|
+
"E_AUDIT_NO_ROOT",
|
|
154
|
+
"auditEditor() found no mounted <Editor.Root>. Mount a Root first — or, to audit at mount time, pass onAudit on the Root: <Editor.Root onAudit={(report) => …}>.",
|
|
155
|
+
{ docSlug: "embed-mode" }
|
|
156
|
+
);
|
|
157
|
+
return t.compute();
|
|
158
|
+
}
|
|
159
|
+
const ke = 8e3;
|
|
160
|
+
function ht(t) {
|
|
161
|
+
return `[RealtimeEmbed] No mockup after ${Math.round(ke / 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.`;
|
|
162
|
+
}
|
|
163
|
+
function gt(t) {
|
|
164
|
+
if ("grantUrl" in t && t.grantUrl)
|
|
165
|
+
return { grantUrl: t.grantUrl };
|
|
166
|
+
const e = t.grant;
|
|
167
|
+
return typeof e == "function" ? { getToken: e } : { getToken: () => Promise.resolve(e) };
|
|
168
|
+
}
|
|
169
|
+
function Ce({ error: t, onRetry: e }) {
|
|
170
|
+
const n = Ee(t) ? t.code : "EDITOR_ERROR";
|
|
171
|
+
return /* @__PURE__ */ N(
|
|
172
|
+
"div",
|
|
173
|
+
{
|
|
174
|
+
"data-sc-part": "error",
|
|
175
|
+
role: "alert",
|
|
176
|
+
style: {
|
|
177
|
+
padding: "16px",
|
|
178
|
+
borderRadius: "12px",
|
|
179
|
+
border: "1px solid var(--sc-color-destructive, #b91c1c)",
|
|
180
|
+
background: "var(--sc-color-surface, #fef2f2)",
|
|
181
|
+
color: "var(--sc-color-foreground, #7f1d1d)",
|
|
182
|
+
fontFamily: "ui-sans-serif, system-ui, sans-serif",
|
|
183
|
+
fontSize: "13px",
|
|
184
|
+
lineHeight: 1.5
|
|
185
|
+
},
|
|
186
|
+
children: [
|
|
187
|
+
/* @__PURE__ */ N("p", { style: { margin: 0, fontWeight: 700 }, children: [
|
|
188
|
+
"Editor failed: ",
|
|
189
|
+
n
|
|
190
|
+
] }),
|
|
191
|
+
/* @__PURE__ */ l("p", { style: { margin: "4px 0 0" }, children: t.message }),
|
|
192
|
+
e ? /* @__PURE__ */ l(
|
|
193
|
+
"button",
|
|
194
|
+
{
|
|
195
|
+
type: "button",
|
|
196
|
+
"data-sc-part": "error-retry",
|
|
197
|
+
onClick: e,
|
|
198
|
+
style: {
|
|
199
|
+
marginTop: "10px",
|
|
200
|
+
padding: "6px 14px",
|
|
201
|
+
borderRadius: "9999px",
|
|
202
|
+
border: "1px solid currentColor",
|
|
203
|
+
background: "transparent",
|
|
204
|
+
color: "inherit",
|
|
205
|
+
font: "inherit",
|
|
206
|
+
fontWeight: 600,
|
|
207
|
+
cursor: "pointer"
|
|
208
|
+
},
|
|
209
|
+
children: "Retry"
|
|
210
|
+
}
|
|
211
|
+
) : null
|
|
212
|
+
]
|
|
213
|
+
}
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
class yt extends Qe {
|
|
217
|
+
constructor() {
|
|
218
|
+
super(...arguments), this.state = { caught: null };
|
|
219
|
+
}
|
|
220
|
+
static getDerivedStateFromError(e) {
|
|
221
|
+
return { caught: e };
|
|
222
|
+
}
|
|
223
|
+
componentDidCatch(e) {
|
|
224
|
+
var n;
|
|
225
|
+
rt(e), typeof L < "u" && ((n = L.env) == null ? void 0 : n.NODE_ENV) !== "production" && console.error("[Editor.Root] contained a composition error:", e);
|
|
226
|
+
}
|
|
227
|
+
render() {
|
|
228
|
+
return this.state.caught ? /* @__PURE__ */ l(Ce, { error: this.state.caught }) : this.props.children;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
function vt({ reportedError: t, onRetry: e, children: n }) {
|
|
232
|
+
if (t) {
|
|
233
|
+
const r = Ee(t) && t.code === "E_CHUNK_LOAD_FAILED";
|
|
234
|
+
return /* @__PURE__ */ l(Ce, { error: t, onRetry: r ? e : void 0 });
|
|
235
|
+
}
|
|
236
|
+
return /* @__PURE__ */ l(yt, { reportedError: null, onRetry: e, children: n });
|
|
237
|
+
}
|
|
238
|
+
function bt(t) {
|
|
239
|
+
const {
|
|
240
|
+
shop: e,
|
|
241
|
+
product: n,
|
|
242
|
+
design: r,
|
|
243
|
+
throttleMs: i = 200,
|
|
244
|
+
onMockups: s,
|
|
245
|
+
onRenderError: d,
|
|
246
|
+
onIssue: c,
|
|
247
|
+
wsUrl: u,
|
|
248
|
+
services: a,
|
|
249
|
+
children: p,
|
|
250
|
+
internals: m,
|
|
251
|
+
recordAudit: y,
|
|
252
|
+
__validation: b = "throw"
|
|
253
|
+
} = t, o = O(() => r.toJSON().activeArtboard, [r]), g = O(() => r.toJSON().artboards.map((h) => h.name), [r]), [w, f] = C(null), S = w && w.design === r ? w.label : o, v = O(
|
|
254
|
+
() => (h) => {
|
|
255
|
+
if (!g.includes(h))
|
|
256
|
+
throw new T(
|
|
257
|
+
"E_UNKNOWN_PLACEMENT",
|
|
258
|
+
`no placement "${h}" in this design — its artboards are ${JSON.stringify(g)}. Add it to the seed with design(…).artboard('${h}', { width, height }) (ADR-0088).`,
|
|
259
|
+
{ placement: h, validNames: g, docSlug: "embed-mode" }
|
|
260
|
+
);
|
|
261
|
+
f({ design: r, label: h });
|
|
262
|
+
},
|
|
263
|
+
[r, g]
|
|
264
|
+
), V = O(() => {
|
|
265
|
+
const h = r.toJSON().artboards[0];
|
|
266
|
+
if (h)
|
|
267
|
+
return {
|
|
268
|
+
name: h.name,
|
|
269
|
+
width: h.width,
|
|
270
|
+
height: h.height,
|
|
271
|
+
...h.backgroundColor ? { backgroundColor: h.backgroundColor } : {}
|
|
272
|
+
};
|
|
273
|
+
}, [r]);
|
|
274
|
+
z(
|
|
275
|
+
m.commerce.subscribe,
|
|
276
|
+
m.commerce.getVersion,
|
|
277
|
+
m.commerce.getVersion
|
|
278
|
+
);
|
|
279
|
+
const R = m.commerce.renderVariantId(), _ = ot(R ?? n.variantId ?? n.defaultGvid), D = O(() => {
|
|
280
|
+
if (!_) return null;
|
|
281
|
+
const h = r.toJSON().artboards[0];
|
|
282
|
+
return it(_, h) ?? null;
|
|
283
|
+
}, [_, r]), P = x(s), A = x(d), j = x(c);
|
|
284
|
+
P.current = s, A.current = d, j.current = c;
|
|
285
|
+
const [ce, _e] = C([]), [Y, W] = C(!0), [ue, X] = C(null), ne = !!("grantUrl" in t && t.grantUrl || "grant" in t && t.grant), re = gt(t), Ae = "grantUrl" in re ? re.grantUrl : "getToken", me = `${n.productId}|${n.mockupIds.join(",")}|${n.variantId ?? ""}`, q = `${e}|${me}|${o}|${ne}`, oe = O(() => {
|
|
286
|
+
var I;
|
|
287
|
+
const h = Re({ shop: e, product: n, design: r, hasGrant: ne });
|
|
288
|
+
if (b !== "throw") return h;
|
|
289
|
+
const E = h.find((B) => B.severity === "error");
|
|
290
|
+
if (E)
|
|
291
|
+
throw new T("E_EMBED_CONFIG", E.message, {
|
|
292
|
+
issue: E.issue,
|
|
293
|
+
docSlug: "embed-mode"
|
|
294
|
+
});
|
|
295
|
+
for (const B of h)
|
|
296
|
+
typeof L < "u" && ((I = L.env) == null ? void 0 : I.NODE_ENV) !== "production" && console.warn(`[Editor.Root] ${B.message}`);
|
|
297
|
+
return h;
|
|
298
|
+
}, [q, b]), fe = x(null);
|
|
299
|
+
$(() => {
|
|
300
|
+
var h;
|
|
301
|
+
if (oe.length !== 0 && fe.current !== q) {
|
|
302
|
+
fe.current = q;
|
|
303
|
+
for (const E of oe) (h = j.current) == null || h.call(j, E);
|
|
304
|
+
}
|
|
305
|
+
}, [oe, q]);
|
|
306
|
+
const pe = x(null);
|
|
307
|
+
$(() => {
|
|
308
|
+
var h;
|
|
309
|
+
if (b === "warn" && typeof L < "u" && ((h = L.env) == null ? void 0 : h.NODE_ENV) !== "production") {
|
|
310
|
+
if (pe.current === q) return;
|
|
311
|
+
pe.current = q, ft({ shop: e, product: n, design: r, hasGrant: ne });
|
|
312
|
+
}
|
|
313
|
+
}, [q, b]);
|
|
314
|
+
const Z = O(
|
|
315
|
+
() => {
|
|
316
|
+
try {
|
|
317
|
+
return { session: new Ze({ shop: e, product: n, wsUrl: u, ...re }) };
|
|
318
|
+
} catch (h) {
|
|
319
|
+
return { error: h instanceof Error ? h.message : String(h) };
|
|
320
|
+
}
|
|
321
|
+
},
|
|
322
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
323
|
+
[e, me, o, u, Ae]
|
|
324
|
+
), k = "session" in Z ? Z.session : null, ee = "error" in Z ? Z.error : null, te = O(() => (h, E = i) => {
|
|
325
|
+
if (!k) return;
|
|
326
|
+
X(null), W(!0);
|
|
327
|
+
const I = (U) => {
|
|
328
|
+
var ye;
|
|
329
|
+
const ge = U instanceof Error ? U.message : String(U);
|
|
330
|
+
X(ge), W(!1), (ye = A.current) == null || ye.call(A, ge);
|
|
331
|
+
}, B = h.artboards ?? [];
|
|
332
|
+
if (B.length > 1) {
|
|
333
|
+
for (const U of B)
|
|
334
|
+
k.renderState(
|
|
335
|
+
typeof U.name == "string" && U.name ? U.name : o,
|
|
336
|
+
{ schemaVersion: h.schemaVersion, artboards: [U] },
|
|
337
|
+
E
|
|
338
|
+
).catch(I);
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
k.renderState(o, h, E).catch(I);
|
|
342
|
+
}, [k, o, i]);
|
|
343
|
+
$(() => {
|
|
344
|
+
var h;
|
|
345
|
+
if (ee) {
|
|
346
|
+
X(ee), W(!1), (h = A.current) == null || h.call(A, ee);
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
if (k)
|
|
350
|
+
return k.onMockups((E) => {
|
|
351
|
+
var I;
|
|
352
|
+
_e(E), W(!1), (I = P.current) == null || I.call(P, E);
|
|
353
|
+
}), k.onError((E) => {
|
|
354
|
+
var I;
|
|
355
|
+
X(E), W(!1), (I = A.current) == null || I.call(A, E);
|
|
356
|
+
}), te(r.toServerRequest()), () => k.close();
|
|
357
|
+
}, [k, ee]);
|
|
358
|
+
const ie = x({
|
|
359
|
+
session: null,
|
|
360
|
+
variantId: void 0
|
|
361
|
+
});
|
|
362
|
+
$(() => {
|
|
363
|
+
if (!k || !R) return;
|
|
364
|
+
const h = ie.current, E = h.session === k ? h.variantId : n.variantId;
|
|
365
|
+
if (R === E) {
|
|
366
|
+
ie.current = { session: k, variantId: E };
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
ie.current = { session: k, variantId: R }, k.setProduct({ ...n, variantId: R }), te(le(m.store.getState()));
|
|
370
|
+
}, [k, R]), $(() => {
|
|
371
|
+
if (!Y) return;
|
|
372
|
+
const h = setTimeout(() => {
|
|
373
|
+
var I, B;
|
|
374
|
+
const E = ht(o);
|
|
375
|
+
typeof L < "u" && ((I = L.env) == null ? void 0 : I.NODE_ENV) !== "production" && console.warn(E), (B = j.current) == null || B.call(j, { severity: "warn", issue: "slow-render", message: E });
|
|
376
|
+
}, ke);
|
|
377
|
+
return () => clearTimeout(h);
|
|
378
|
+
}, [Y, o]);
|
|
379
|
+
const De = O(
|
|
380
|
+
() => ({
|
|
381
|
+
session: k,
|
|
382
|
+
design: r,
|
|
383
|
+
// The ACTIVE placement (ADR-0088): Editor.Canvas follows it as its
|
|
384
|
+
// controlled artboard; single-placement designs never see it move.
|
|
385
|
+
placement: S,
|
|
386
|
+
placements: g,
|
|
387
|
+
selectPlacement: v,
|
|
388
|
+
product: n,
|
|
389
|
+
mockups: ce,
|
|
390
|
+
isRendering: Y,
|
|
391
|
+
error: ue,
|
|
392
|
+
throttleMs: i,
|
|
393
|
+
pieceGuides: D,
|
|
394
|
+
pushRender: te,
|
|
395
|
+
stateStore: m.store
|
|
396
|
+
}),
|
|
397
|
+
[k, r, S, g, v, n, ce, Y, ue, i, D, te, m.store]
|
|
398
|
+
), Pe = z(
|
|
399
|
+
m.registry.subscribe,
|
|
400
|
+
m.registry.getVersion,
|
|
401
|
+
m.registry.getVersion
|
|
402
|
+
);
|
|
403
|
+
O(() => {
|
|
404
|
+
y(
|
|
405
|
+
Se({ registry: m.registry, store: m.store, product: n })
|
|
406
|
+
), m.registry.validate();
|
|
407
|
+
}, [m.registry, Pe]);
|
|
408
|
+
const he = /* @__PURE__ */ l(Be.Provider, { value: m, children: /* @__PURE__ */ l(xe.Provider, { value: De, children: /* @__PURE__ */ l(tt.Provider, { value: m.registry, children: /* @__PURE__ */ l(
|
|
409
|
+
nt,
|
|
410
|
+
{
|
|
411
|
+
...V ? { initialArtboardConfig: V } : {},
|
|
412
|
+
children: p
|
|
413
|
+
}
|
|
414
|
+
) }) }) });
|
|
415
|
+
return a ? /* @__PURE__ */ l(Fe, { services: a, children: he }) : he;
|
|
416
|
+
}
|
|
417
|
+
function Ie(t) {
|
|
418
|
+
const { design: e, product: n, onAudit: r } = t, i = `${n.productId}|${n.variantId ?? ""}`, s = x(null), d = x(null), [c, u] = C(null);
|
|
419
|
+
(s.current === null || s.current.design !== e) && (s.current = {
|
|
420
|
+
design: e,
|
|
421
|
+
internals: {
|
|
422
|
+
store: new at(e.toJSON()),
|
|
423
|
+
registry: new Le()
|
|
424
|
+
}
|
|
425
|
+
}), (d.current === null || d.current.productIdentity !== i) && (d.current = { productIdentity: i, commerce: new dt(n) });
|
|
426
|
+
const a = O(
|
|
427
|
+
() => ({
|
|
428
|
+
...s.current.internals,
|
|
429
|
+
commerce: d.current.commerce,
|
|
430
|
+
...Ve(u)
|
|
431
|
+
}),
|
|
432
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
433
|
+
[s.current.internals, d.current.commerce]
|
|
434
|
+
), p = x(n);
|
|
435
|
+
p.current = n;
|
|
436
|
+
const m = x(r);
|
|
437
|
+
m.current = r;
|
|
438
|
+
const y = x(null), b = F((w) => {
|
|
439
|
+
y.current = w;
|
|
440
|
+
}, []), o = F(
|
|
441
|
+
() => Se({
|
|
442
|
+
registry: s.current.internals.registry,
|
|
443
|
+
store: s.current.internals.store,
|
|
444
|
+
product: p.current
|
|
445
|
+
}),
|
|
446
|
+
[]
|
|
447
|
+
);
|
|
448
|
+
Q(() => pt({ compute: o }), [o]);
|
|
449
|
+
const g = x(!1);
|
|
450
|
+
return $(() => {
|
|
451
|
+
let w = !1;
|
|
452
|
+
return queueMicrotask(() => {
|
|
453
|
+
var f;
|
|
454
|
+
w || g.current || (g.current = !0, (f = m.current) == null || f.call(m, y.current ?? o()));
|
|
455
|
+
}), () => {
|
|
456
|
+
w = !0;
|
|
457
|
+
};
|
|
458
|
+
}, [o]), // `display: contents` — the .sc-root scope without a layout box, so the
|
|
459
|
+
// host's grid/flex sees the parts directly (and the legacy RealtimeEmbed
|
|
460
|
+
// wrapper, which had no DOM at all, stays layout-identical).
|
|
461
|
+
/* @__PURE__ */ l("div", { className: "sc-root", style: { display: "contents" }, "data-sc-part": "root", children: /* @__PURE__ */ l(vt, { reportedError: c, onRetry: () => u(null), children: /* @__PURE__ */ l(bt, { ...t, internals: a, recordAudit: b }) }) });
|
|
462
|
+
}
|
|
463
|
+
let wt = () => import("./EditorCanvasImpl-BLZV_el0.js").then((t) => t.EditorCanvasImpl);
|
|
464
|
+
function Oe() {
|
|
465
|
+
return wt();
|
|
466
|
+
}
|
|
467
|
+
const Et = be(function({ children: e, maxHeight: n, floatingToolbar: r = !0, className: i, style: s }, d) {
|
|
468
|
+
const c = H("Editor.Canvas");
|
|
469
|
+
J("Editor.Canvas", { floatingToolbar: r });
|
|
470
|
+
const u = de();
|
|
471
|
+
Q(() => c.registry.registerCanvas(u), [c.registry, u]);
|
|
472
|
+
const [a, p] = C(null);
|
|
473
|
+
return $(() => {
|
|
474
|
+
let m = !1;
|
|
475
|
+
return Oe().then(
|
|
476
|
+
(y) => {
|
|
477
|
+
m || p(() => y);
|
|
478
|
+
},
|
|
479
|
+
(y) => {
|
|
480
|
+
m || c.reportRuntimeError(
|
|
481
|
+
new T(
|
|
482
|
+
"E_CHUNK_LOAD_FAILED",
|
|
483
|
+
`the editor's rendering chunk failed to load (${y instanceof Error ? y.message : String(y)}). This is a network/CDN failure, not a composition mistake — retry, or check the deployment serves the @snowcone-app/canvas lazy chunks.`,
|
|
484
|
+
{ cause: y instanceof Error ? y.message : String(y), docSlug: "embed-mode" }
|
|
485
|
+
)
|
|
486
|
+
);
|
|
487
|
+
}
|
|
488
|
+
), () => {
|
|
489
|
+
m = !0;
|
|
490
|
+
};
|
|
491
|
+
}, [c]), a ? (
|
|
492
|
+
// `builtinControls`: the canvas owns the floating contextual toolbar
|
|
493
|
+
// unless the host opts out via `floatingToolbar={false}` or a docked
|
|
494
|
+
// <Editor.Controls> is mounted (ADR-0085 §5). Only here — the legacy
|
|
495
|
+
// <RealtimeCanvas> wrapper stays chrome-less.
|
|
496
|
+
/* @__PURE__ */ l(
|
|
497
|
+
a,
|
|
498
|
+
{
|
|
499
|
+
ref: d,
|
|
500
|
+
kit: "embed-only",
|
|
501
|
+
partAttr: "canvas",
|
|
502
|
+
builtinControls: r,
|
|
503
|
+
maxHeight: n,
|
|
504
|
+
className: i,
|
|
505
|
+
style: s,
|
|
506
|
+
children: e
|
|
507
|
+
}
|
|
508
|
+
)
|
|
509
|
+
) : /* @__PURE__ */ l(
|
|
510
|
+
"div",
|
|
511
|
+
{
|
|
512
|
+
"data-sc-part": "canvas",
|
|
513
|
+
"data-sc-state": "loading",
|
|
514
|
+
className: i,
|
|
515
|
+
style: { minHeight: n ?? 200, ...s },
|
|
516
|
+
"aria-busy": "true"
|
|
517
|
+
}
|
|
518
|
+
);
|
|
519
|
+
});
|
|
520
|
+
function xt() {
|
|
521
|
+
const { placements: t, placement: e, selectPlacement: n } = K();
|
|
522
|
+
return O(
|
|
523
|
+
() => ({
|
|
524
|
+
placements: t.map((r) => ({ label: r, active: r === e })),
|
|
525
|
+
activePlacement: e,
|
|
526
|
+
select: n
|
|
527
|
+
}),
|
|
528
|
+
[t, e, n]
|
|
529
|
+
);
|
|
530
|
+
}
|
|
531
|
+
function Rt({ className: t, style: e }) {
|
|
532
|
+
const { placements: n, select: r } = xt();
|
|
533
|
+
return n.length < 2 ? null : /* @__PURE__ */ l(
|
|
534
|
+
"div",
|
|
535
|
+
{
|
|
536
|
+
"data-sc-part": "placements",
|
|
537
|
+
className: t,
|
|
538
|
+
style: { display: "flex", alignItems: "center", gap: "4px", ...e },
|
|
539
|
+
children: n.map(({ label: i, active: s }) => /* @__PURE__ */ l(
|
|
540
|
+
"button",
|
|
541
|
+
{
|
|
542
|
+
type: "button",
|
|
543
|
+
"data-sc-part": "placements-item",
|
|
544
|
+
"data-sc-active": s ? "true" : "false",
|
|
545
|
+
"aria-pressed": s,
|
|
546
|
+
onClick: () => r(i),
|
|
547
|
+
style: {
|
|
548
|
+
font: "inherit",
|
|
549
|
+
fontSize: "13px",
|
|
550
|
+
fontWeight: s ? 700 : 400,
|
|
551
|
+
color: "var(--sc-color-foreground, inherit)",
|
|
552
|
+
background: "transparent",
|
|
553
|
+
border: "none",
|
|
554
|
+
borderRadius: "9999px",
|
|
555
|
+
padding: "2px 8px",
|
|
556
|
+
cursor: s ? "default" : "pointer",
|
|
557
|
+
textDecoration: s ? "underline" : "none",
|
|
558
|
+
textUnderlineOffset: "4px"
|
|
559
|
+
},
|
|
560
|
+
children: i
|
|
561
|
+
},
|
|
562
|
+
i
|
|
563
|
+
))
|
|
564
|
+
}
|
|
565
|
+
);
|
|
566
|
+
}
|
|
567
|
+
const St = 200, kt = 400;
|
|
568
|
+
function Ct() {
|
|
569
|
+
return Array.from({ length: 10 }, () => ({
|
|
570
|
+
left: 2 + Math.random() * 96,
|
|
571
|
+
top: 2 + Math.random() * 96,
|
|
572
|
+
delay: (Math.random() * 3.5).toFixed(1),
|
|
573
|
+
duration: (3 + Math.random() * 2).toFixed(1),
|
|
574
|
+
size: 3 + Math.random() * 5
|
|
575
|
+
}));
|
|
576
|
+
}
|
|
577
|
+
let ve = !1;
|
|
578
|
+
function It() {
|
|
579
|
+
if (!(ve || typeof CSS > "u" || typeof CSS.registerProperty != "function")) {
|
|
580
|
+
ve = !0;
|
|
581
|
+
try {
|
|
582
|
+
CSS.registerProperty({ name: "--sc-prism-mount", syntax: "<number>", initialValue: "0", inherits: !0 });
|
|
583
|
+
} catch {
|
|
584
|
+
}
|
|
585
|
+
try {
|
|
586
|
+
CSS.registerProperty({ name: "--sc-prism-band", syntax: "<number>", initialValue: "0", inherits: !1 });
|
|
587
|
+
} catch {
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
const Ne = Ye(function({
|
|
592
|
+
visible: e = !0,
|
|
593
|
+
onExited: n,
|
|
594
|
+
variant: r = "dark"
|
|
595
|
+
}) {
|
|
596
|
+
It();
|
|
597
|
+
const [i, s] = C([]);
|
|
598
|
+
$(() => {
|
|
599
|
+
s(Ct());
|
|
600
|
+
}, []);
|
|
601
|
+
const [d, c] = C(!1);
|
|
602
|
+
$(() => {
|
|
603
|
+
const p = requestAnimationFrame(() => c(!0));
|
|
604
|
+
return () => cancelAnimationFrame(p);
|
|
605
|
+
}, []);
|
|
606
|
+
const u = F(
|
|
607
|
+
(p) => {
|
|
608
|
+
p.propertyName === "background-color" && (e || n == null || n());
|
|
609
|
+
},
|
|
610
|
+
[e, n]
|
|
611
|
+
);
|
|
612
|
+
let a = "";
|
|
613
|
+
return e ? d && (a = "sc-prism-fade-in") : a = "sc-prism-fade-out", /* @__PURE__ */ N(
|
|
614
|
+
"div",
|
|
615
|
+
{
|
|
616
|
+
"data-sc-part": "preview-loading",
|
|
617
|
+
className: ["sc-prism-overlay", r === "light" ? "sc-prism-on-light" : "", a].filter(Boolean).join(" "),
|
|
618
|
+
onTransitionEnd: u,
|
|
619
|
+
"aria-hidden": "true",
|
|
620
|
+
children: [
|
|
621
|
+
Array.from({ length: 6 }, (p, m) => /* @__PURE__ */ l("div", { className: "sc-prism-band" }, `b-${m}`)),
|
|
622
|
+
i.map((p, m) => /* @__PURE__ */ l(
|
|
623
|
+
"div",
|
|
624
|
+
{
|
|
625
|
+
className: "sc-prism-particle",
|
|
626
|
+
style: {
|
|
627
|
+
left: `${p.left}%`,
|
|
628
|
+
top: `${p.top}%`,
|
|
629
|
+
animationDelay: `${p.delay}s`,
|
|
630
|
+
animationDuration: `${p.duration}s`,
|
|
631
|
+
width: `${p.size}px`,
|
|
632
|
+
height: `${p.size}px`
|
|
633
|
+
}
|
|
634
|
+
},
|
|
635
|
+
`p-${m}`
|
|
636
|
+
))
|
|
637
|
+
]
|
|
638
|
+
}
|
|
639
|
+
);
|
|
640
|
+
});
|
|
641
|
+
function Te(t) {
|
|
642
|
+
const [e, n] = C(!1), [r, i] = C(!1), s = x(null), d = x(null), c = x(!1);
|
|
643
|
+
c.current = e, $(() => (t ? (i(!1), d.current && clearTimeout(d.current), s.current = setTimeout(() => n(!0), St)) : (s.current && (clearTimeout(s.current), s.current = null), c.current && (i(!0), d.current = setTimeout(() => i(!1), kt))), () => {
|
|
644
|
+
s.current && clearTimeout(s.current), d.current && clearTimeout(d.current);
|
|
645
|
+
}), [t]);
|
|
646
|
+
const u = F(() => n(!1), []);
|
|
647
|
+
return {
|
|
648
|
+
showOverlay: e,
|
|
649
|
+
overlayVisible: t || r,
|
|
650
|
+
handleExited: u
|
|
651
|
+
};
|
|
652
|
+
}
|
|
653
|
+
const Ot = 1.2, se = [1200, 1400, 1600, 1800, 2e3, 2500, 3e3, 4e3];
|
|
654
|
+
function Nt(t) {
|
|
655
|
+
for (const e of se)
|
|
656
|
+
if (e >= t) return e;
|
|
657
|
+
return se[se.length - 1];
|
|
658
|
+
}
|
|
659
|
+
function Tt(t, e) {
|
|
660
|
+
if (!(t > 0) || !(e > 0) || e <= t * Ot) return null;
|
|
661
|
+
const n = Nt(e);
|
|
662
|
+
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.`;
|
|
663
|
+
}
|
|
664
|
+
function $t(t) {
|
|
665
|
+
if (t === void 0 || t === !0 || t === "dark") return "dark";
|
|
666
|
+
if (t === "light" || t === "host-owned" || we(t)) return t;
|
|
667
|
+
throw new T(
|
|
668
|
+
"E_PREVIEW_NO_LOADER",
|
|
669
|
+
`Editor.Preview: invalid loadingOverlay value ${JSON.stringify(t)}. A mockup preview always has a render-in-flight treatment (the loader paints over the still-visible previous mockup). Omit the prop for the default rainbow overlay, pass "dark" | "light", pass a custom ReactElement, or declare "host-owned" if the host renders its own indicator off data-sc-preview-state / <Editor.LoadingOverlay>.`,
|
|
670
|
+
{ docSlug: "preview-loading-overlay" }
|
|
671
|
+
);
|
|
672
|
+
}
|
|
673
|
+
function $e({
|
|
674
|
+
mockupId: t,
|
|
675
|
+
fallback: e = null,
|
|
676
|
+
alt: n = "Live product mockup",
|
|
677
|
+
loadingOverlay: r,
|
|
678
|
+
className: i,
|
|
679
|
+
style: s
|
|
680
|
+
}) {
|
|
681
|
+
const { mockups: d, error: c, isRendering: u } = K();
|
|
682
|
+
J("Editor.Preview", { ...t !== void 0 ? { mockupId: t } : {} });
|
|
683
|
+
const a = $t(r), p = a === "dark" || a === "light" ? a : null, m = we(a) ? a : null, y = a !== "host-owned", { showOverlay: b, overlayVisible: o, handleExited: g } = Te(
|
|
684
|
+
y && u
|
|
685
|
+
), w = x(/* @__PURE__ */ new Set()), f = t ? d.find((v) => v.mockupId === t && v.imageUrl) : d.find((v) => v.imageUrl), S = (v) => {
|
|
686
|
+
var P;
|
|
687
|
+
if (!f || typeof L > "u" || ((P = L.env) == null ? void 0 : P.NODE_ENV) === "production" || typeof window > "u" || w.current.has(f.mockupId)) return;
|
|
688
|
+
const V = v.currentTarget, R = V.getBoundingClientRect().width;
|
|
689
|
+
if (R <= 0) return;
|
|
690
|
+
const _ = Math.round(R * (window.devicePixelRatio || 1)), D = Tt(V.naturalWidth, _);
|
|
691
|
+
D && (w.current.add(f.mockupId), console.warn(D));
|
|
692
|
+
};
|
|
693
|
+
if (y) {
|
|
694
|
+
const v = f != null && f.imageUrl ? u ? "rendering" : "ready" : c ? "error" : "rendering";
|
|
695
|
+
return /* @__PURE__ */ N(
|
|
696
|
+
"div",
|
|
697
|
+
{
|
|
698
|
+
"data-sc-part": "preview",
|
|
699
|
+
"data-sc-preview-state": v,
|
|
700
|
+
"aria-busy": v === "rendering" || void 0,
|
|
701
|
+
className: `sc-preview-frame${i ? ` ${i}` : ""}`,
|
|
702
|
+
style: s,
|
|
703
|
+
children: [
|
|
704
|
+
f != null && f.imageUrl ? (
|
|
705
|
+
// eslint-disable-next-line @next/next/no-img-element
|
|
706
|
+
/* @__PURE__ */ l("img", { "data-sc-part": "preview-image", src: f.imageUrl, alt: n, onLoad: S })
|
|
707
|
+
) : c ? /* @__PURE__ */ l("div", { "data-sc-part": "preview-error", role: "alert", "data-sc-error": c, children: e ?? `Render failed: ${c}` }) : e,
|
|
708
|
+
m ? (
|
|
709
|
+
// Custom indicator: same show-delay + linger window; no exit fade
|
|
710
|
+
// (the host owns its animation), so it unmounts when the window
|
|
711
|
+
// closes.
|
|
712
|
+
b && o ? /* @__PURE__ */ l(
|
|
713
|
+
"div",
|
|
714
|
+
{
|
|
715
|
+
"data-sc-part": "preview-loading",
|
|
716
|
+
className: "sc-preview-custom-loading",
|
|
717
|
+
"aria-hidden": "true",
|
|
718
|
+
children: m
|
|
719
|
+
}
|
|
720
|
+
) : null
|
|
721
|
+
) : b && p ? /* @__PURE__ */ l(
|
|
722
|
+
Ne,
|
|
723
|
+
{
|
|
724
|
+
visible: o,
|
|
725
|
+
variant: p,
|
|
726
|
+
onExited: g
|
|
727
|
+
}
|
|
728
|
+
) : null
|
|
729
|
+
]
|
|
730
|
+
}
|
|
731
|
+
);
|
|
732
|
+
}
|
|
733
|
+
return f != null && f.imageUrl ? (
|
|
734
|
+
// eslint-disable-next-line @next/next/no-img-element
|
|
735
|
+
/* @__PURE__ */ l(
|
|
736
|
+
"img",
|
|
737
|
+
{
|
|
738
|
+
"data-sc-part": "preview",
|
|
739
|
+
"data-sc-preview-state": u ? "rendering" : "ready",
|
|
740
|
+
src: f.imageUrl,
|
|
741
|
+
alt: n,
|
|
742
|
+
className: i,
|
|
743
|
+
style: s,
|
|
744
|
+
onLoad: S
|
|
745
|
+
}
|
|
746
|
+
)
|
|
747
|
+
) : c ? /* @__PURE__ */ l(
|
|
748
|
+
"div",
|
|
749
|
+
{
|
|
750
|
+
"data-sc-part": "preview-error",
|
|
751
|
+
"data-sc-preview-state": "error",
|
|
752
|
+
role: "alert",
|
|
753
|
+
"data-sc-error": c,
|
|
754
|
+
className: i,
|
|
755
|
+
style: s,
|
|
756
|
+
children: e ?? `Render failed: ${c}`
|
|
757
|
+
}
|
|
758
|
+
) : /* @__PURE__ */ l("div", { "data-sc-part": "preview", "data-sc-preview-state": "rendering", "aria-busy": "true", style: { display: "contents" }, children: e });
|
|
759
|
+
}
|
|
760
|
+
function _t(t) {
|
|
761
|
+
const { layer: e, optional: n = !1, placeholder: r, className: i, style: s } = t, d = H("Editor.TextField");
|
|
762
|
+
J("Editor.TextField");
|
|
763
|
+
const { pushRender: c, throttleMs: u, stateStore: a } = K(), p = de(), m = x(null);
|
|
764
|
+
if (!st(e))
|
|
765
|
+
throw new T(
|
|
766
|
+
"E_LAYER_TOKEN_REQUIRED",
|
|
767
|
+
`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.`,
|
|
768
|
+
{ received: typeof e == "string" ? e : typeof e, docSlug: "embed-mode" }
|
|
769
|
+
);
|
|
770
|
+
if (m.current !== e.name) {
|
|
771
|
+
const o = a.layerKindOf(e.name);
|
|
772
|
+
if (o === void 0)
|
|
773
|
+
throw new T(
|
|
774
|
+
"E_LAYER_NOT_FOUND",
|
|
775
|
+
`no layer "${e.name}" in this Root's design — the token was minted from a different design than the one passed to <Editor.Root design={…}>. Bindable layers here: ${JSON.stringify(a.bindableLayerNames())}.`,
|
|
776
|
+
{ layerName: e.name, validNames: a.bindableLayerNames(), docSlug: "embed-mode" }
|
|
777
|
+
);
|
|
778
|
+
if (o !== "text")
|
|
779
|
+
throw new T(
|
|
780
|
+
"E_LAYER_WRONG_KIND",
|
|
781
|
+
`layer "${e.name}" is ${o === null ? "not a bindable kind" : `an ${o} layer`} — <Editor.TextField> binds text layers only.`,
|
|
782
|
+
{ layerName: e.name, actualKind: o, docSlug: "embed-mode" }
|
|
783
|
+
);
|
|
784
|
+
m.current = e.name;
|
|
785
|
+
}
|
|
786
|
+
Q(() => d.registry.registerTextField(p, { name: e.name, optional: n }), [d.registry, p, e.name, n]);
|
|
787
|
+
const y = z(
|
|
788
|
+
a.subscribe,
|
|
789
|
+
() => a.textOf(e.name) ?? "",
|
|
790
|
+
() => a.textOf(e.name) ?? ""
|
|
791
|
+
), b = F(
|
|
792
|
+
(o) => {
|
|
793
|
+
const g = o.target.value, w = d.registry.getCanvasBridge();
|
|
794
|
+
if (w) {
|
|
795
|
+
w.setTextByName(e.name, g) || d.reportInvariant(
|
|
796
|
+
new T(
|
|
797
|
+
"E_LAYER_NOT_FOUND",
|
|
798
|
+
`layer "${e.name}" no longer exists in the mounted canvas — it was removed or renamed after this <Editor.TextField> bound to it. Bound layers must not be renamed or deleted while a field is mounted (ADR-0085 §3).`,
|
|
799
|
+
{ layerName: e.name, docSlug: "embed-mode" }
|
|
800
|
+
)
|
|
801
|
+
);
|
|
802
|
+
return;
|
|
803
|
+
}
|
|
804
|
+
a.updateTextLayer(e.name, g), c(le(a.getState()), u);
|
|
805
|
+
},
|
|
806
|
+
[d, e.name, a, c, u]
|
|
807
|
+
);
|
|
808
|
+
return /* @__PURE__ */ l(
|
|
809
|
+
"input",
|
|
810
|
+
{
|
|
811
|
+
"data-sc-part": "textfield",
|
|
812
|
+
"data-sc-layer": e.name,
|
|
813
|
+
type: "text",
|
|
814
|
+
value: y,
|
|
815
|
+
onChange: b,
|
|
816
|
+
placeholder: r,
|
|
817
|
+
"aria-label": t["aria-label"] ?? e.name,
|
|
818
|
+
className: i,
|
|
819
|
+
style: s
|
|
820
|
+
}
|
|
821
|
+
);
|
|
822
|
+
}
|
|
823
|
+
function At(t) {
|
|
824
|
+
const e = [];
|
|
825
|
+
for (const n of t.missingOptionKeys)
|
|
826
|
+
e.push(`option:${n}`);
|
|
827
|
+
t.missingOptionKeys.length === 0 && !t.selectionValid && e.push("variant");
|
|
828
|
+
for (const n of t.textFields) {
|
|
829
|
+
if (n.optional) continue;
|
|
830
|
+
const r = (t.textOf(n.name) ?? "").trim();
|
|
831
|
+
if (r.length === 0) {
|
|
832
|
+
e.push(`layer:${n.name}`);
|
|
833
|
+
continue;
|
|
834
|
+
}
|
|
835
|
+
const i = (t.seedTextOf(n.name) ?? "").trim();
|
|
836
|
+
i.length > 0 && r === i && e.push(`layer-seed:${n.name}`);
|
|
837
|
+
}
|
|
838
|
+
return t.hasRenderableElement || e.push("empty-design"), (!Number.isInteger(t.quantity) || t.quantity < 1) && e.push("quantity"), e;
|
|
839
|
+
}
|
|
840
|
+
function Dt(t, e) {
|
|
841
|
+
const n = e.getCombinations(), r = e.getAttributes();
|
|
842
|
+
if (Object.keys(r).length === 0 || n.length === 0) return null;
|
|
843
|
+
const i = Object.fromEntries(
|
|
844
|
+
Object.entries(r).map(([s, d]) => [s, { ...d, choices: lt(d) }])
|
|
845
|
+
);
|
|
846
|
+
return et({
|
|
847
|
+
productId: t.productId,
|
|
848
|
+
quantity: e.getQuantity(),
|
|
849
|
+
selection: e.getSelection(),
|
|
850
|
+
combinations: n,
|
|
851
|
+
attributes: i
|
|
852
|
+
});
|
|
853
|
+
}
|
|
854
|
+
function Pt(t) {
|
|
855
|
+
const { onAddToCart: e, defaultQuantity: n, children: r, className: i, style: s } = t, d = H("Editor.Buy");
|
|
856
|
+
J("Editor.Buy");
|
|
857
|
+
const { product: c, stateStore: u } = K(), a = d.commerce;
|
|
858
|
+
if (!(c != null && c.productId))
|
|
859
|
+
throw new T(
|
|
860
|
+
"E_BUY_NO_PRODUCT",
|
|
861
|
+
"<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.",
|
|
862
|
+
{ docSlug: "embed-mode" }
|
|
863
|
+
);
|
|
864
|
+
const p = x(!1);
|
|
865
|
+
Q(() => {
|
|
866
|
+
p.current || (p.current = !0, typeof n == "number" && a.setQuantity(n));
|
|
867
|
+
}, [a]);
|
|
868
|
+
const m = z(u.subscribe, u.getState, u.getState), y = z(a.subscribe, a.getVersion, a.getVersion), b = z(
|
|
869
|
+
d.registry.subscribe,
|
|
870
|
+
d.registry.getVersion,
|
|
871
|
+
d.registry.getVersion
|
|
872
|
+
), o = a.getQuantity(), g = O(
|
|
873
|
+
() => At({
|
|
874
|
+
quantity: o,
|
|
875
|
+
missingOptionKeys: a.missingOptionKeys(),
|
|
876
|
+
selectionValid: a.selectionValid(),
|
|
877
|
+
textFields: d.registry.getTextFields(),
|
|
878
|
+
textOf: (R) => u.textOf(R),
|
|
879
|
+
seedTextOf: (R) => u.seedTextOf(R),
|
|
880
|
+
hasRenderableElement: u.hasRenderableElement()
|
|
881
|
+
}),
|
|
882
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
883
|
+
[a, o, m, y, b]
|
|
884
|
+
), w = g.length === 0, [f, S] = C(!1), v = x(!1), V = F(() => {
|
|
885
|
+
if (v.current || !w) return;
|
|
886
|
+
v.current = !0, S(!0);
|
|
887
|
+
const R = u.getState(), _ = a.resolvedVariantId(), D = {
|
|
888
|
+
productId: c.productId,
|
|
889
|
+
..._ ? { variantId: _ } : {},
|
|
890
|
+
quantity: a.getQuantity(),
|
|
891
|
+
selection: a.getSelection(),
|
|
892
|
+
cartDetail: Dt(c, a),
|
|
893
|
+
designState: R,
|
|
894
|
+
serverRequest: le(R)
|
|
895
|
+
};
|
|
896
|
+
let P;
|
|
897
|
+
try {
|
|
898
|
+
P = e(D);
|
|
899
|
+
} catch (A) {
|
|
900
|
+
throw v.current = !1, S(!1), A;
|
|
901
|
+
}
|
|
902
|
+
Promise.resolve(P).finally(() => {
|
|
903
|
+
v.current = !1, S(!1);
|
|
904
|
+
});
|
|
905
|
+
}, [w, c, a, u, e]);
|
|
906
|
+
return /* @__PURE__ */ l(
|
|
907
|
+
"button",
|
|
908
|
+
{
|
|
909
|
+
type: "button",
|
|
910
|
+
"data-sc-part": "buy",
|
|
911
|
+
"data-sc-buy-state": f ? "busy" : w ? "ready" : "incomplete",
|
|
912
|
+
"data-sc-buy-missing": g.join(",") || void 0,
|
|
913
|
+
disabled: !w || f,
|
|
914
|
+
"aria-busy": f || void 0,
|
|
915
|
+
onClick: V,
|
|
916
|
+
className: i,
|
|
917
|
+
style: s,
|
|
918
|
+
children: r ?? "Add to cart"
|
|
919
|
+
}
|
|
920
|
+
);
|
|
921
|
+
}
|
|
922
|
+
function Lt({
|
|
923
|
+
placement: t = "docked",
|
|
924
|
+
className: e,
|
|
925
|
+
style: n
|
|
926
|
+
}) {
|
|
927
|
+
const r = H("Editor.Controls");
|
|
928
|
+
Ue("Editor.Controls"), J("Editor.Controls");
|
|
929
|
+
const i = de();
|
|
930
|
+
Q(
|
|
931
|
+
() => r.registry.registerControls(i, t),
|
|
932
|
+
[r.registry, i, t]
|
|
933
|
+
);
|
|
934
|
+
const s = t === "docked", [d, c] = C(null);
|
|
935
|
+
return $(() => {
|
|
936
|
+
if (!s) return;
|
|
937
|
+
let u = !1;
|
|
938
|
+
return import("./ContextualToolbars-DUhBKVxe.js").then((a) => a.s).then(
|
|
939
|
+
(a) => {
|
|
940
|
+
u || c(() => a.ContextualToolbars);
|
|
941
|
+
},
|
|
942
|
+
(a) => {
|
|
943
|
+
u || r.reportRuntimeError(
|
|
944
|
+
new T(
|
|
945
|
+
"E_CHUNK_LOAD_FAILED",
|
|
946
|
+
`the editor's controls chunk failed to load (${a instanceof Error ? a.message : String(a)}). This is a network/CDN failure, not a composition mistake — retry, or check the deployment serves the @snowcone-app/canvas lazy chunks.`,
|
|
947
|
+
{ cause: a instanceof Error ? a.message : String(a), docSlug: "embed-mode" }
|
|
948
|
+
)
|
|
949
|
+
);
|
|
950
|
+
}
|
|
951
|
+
), () => {
|
|
952
|
+
u = !0;
|
|
953
|
+
};
|
|
954
|
+
}, [s, r]), s ? /* @__PURE__ */ l(
|
|
955
|
+
"div",
|
|
956
|
+
{
|
|
957
|
+
"data-sc-part": "controls",
|
|
958
|
+
"data-sc-placement": "docked",
|
|
959
|
+
className: e,
|
|
960
|
+
style: n,
|
|
961
|
+
"aria-busy": d ? void 0 : "true",
|
|
962
|
+
children: d ? /* @__PURE__ */ l(d, { mode: "embedded" }) : null
|
|
963
|
+
}
|
|
964
|
+
) : null;
|
|
965
|
+
}
|
|
966
|
+
function Vt({
|
|
967
|
+
variant: t = "dark",
|
|
968
|
+
className: e,
|
|
969
|
+
style: n
|
|
970
|
+
}) {
|
|
971
|
+
const { isRendering: r } = K(), { showOverlay: i, overlayVisible: s, handleExited: d } = Te(r);
|
|
972
|
+
return i ? /* @__PURE__ */ l(
|
|
973
|
+
"div",
|
|
974
|
+
{
|
|
975
|
+
"data-sc-part": "loading-overlay",
|
|
976
|
+
className: `sc-loading-overlay-host${e ? ` ${e}` : ""}`,
|
|
977
|
+
style: n,
|
|
978
|
+
"aria-hidden": "true",
|
|
979
|
+
children: /* @__PURE__ */ l(Ne, { visible: s, variant: t, onExited: d })
|
|
980
|
+
}
|
|
981
|
+
) : null;
|
|
982
|
+
}
|
|
983
|
+
function Bt() {
|
|
984
|
+
const e = H("useProductSelection").commerce, n = z(e.subscribe, e.getVersion, e.getVersion), r = F((s, d) => e.select(s, d), [e]), i = F((s) => e.setQuantity(s), [e]);
|
|
985
|
+
return O(
|
|
986
|
+
() => ({
|
|
987
|
+
attributes: e.getAttributes(),
|
|
988
|
+
selection: e.getSelection(),
|
|
989
|
+
select: r,
|
|
990
|
+
disabledChoices: e.disabledChoices(),
|
|
991
|
+
variantId: e.resolvedVariantId(),
|
|
992
|
+
price: e.resolvedPrice(),
|
|
993
|
+
quantity: e.getQuantity(),
|
|
994
|
+
setQuantity: i,
|
|
995
|
+
complete: e.selectionValid(),
|
|
996
|
+
missing: e.missingOptionKeys()
|
|
997
|
+
}),
|
|
998
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
999
|
+
[e, r, i, n]
|
|
1000
|
+
);
|
|
1001
|
+
}
|
|
1002
|
+
const M = {
|
|
1003
|
+
/** The one provider boundary — session, design, live state, error boundary. */
|
|
1004
|
+
Root: Ie,
|
|
1005
|
+
/** The editable artboard (the ONE lazy renderer boundary — D9). */
|
|
1006
|
+
Canvas: Et,
|
|
1007
|
+
/** Live product mockup. ×N under one Root is valid. */
|
|
1008
|
+
Preview: $e,
|
|
1009
|
+
/** Placement switcher tabs (ADR-0088). Renders nothing for a
|
|
1010
|
+
* single-placement design; headless floor = usePlacements(). */
|
|
1011
|
+
Placements: Rt,
|
|
1012
|
+
/** Form input bound to a design text layer by typed token (T1). */
|
|
1013
|
+
TextField: _t,
|
|
1014
|
+
/** Smart commerce part: completeness + payload assembly; submit = host callback. */
|
|
1015
|
+
Buy: Pt,
|
|
1016
|
+
/** Layer list. The one editor part that works canvas-free (ADR-0085 §4). */
|
|
1017
|
+
Layers: ze,
|
|
1018
|
+
/** Morphing contextual zone — ONE coarse part; placement docked|floating (§5). */
|
|
1019
|
+
Controls: Lt,
|
|
1020
|
+
/** Undo/redo controls. Requires Editor.Canvas. */
|
|
1021
|
+
History: qe,
|
|
1022
|
+
/** The one ⋯ overflow menu. Requires Editor.Canvas. */
|
|
1023
|
+
Menu: je,
|
|
1024
|
+
/** The ⊕ add-element menu. Requires Editor.Canvas. */
|
|
1025
|
+
Add: Me,
|
|
1026
|
+
/** Standalone render-in-flight rainbow for host-owned preview surfaces.
|
|
1027
|
+
* Fills its positioned parent; rides the session (canvas-free). */
|
|
1028
|
+
LoadingOverlay: Vt
|
|
1029
|
+
};
|
|
1030
|
+
function on(t) {
|
|
1031
|
+
return /* @__PURE__ */ l(Ie, { ...t, __validation: "warn" });
|
|
1032
|
+
}
|
|
1033
|
+
const sn = be(
|
|
1034
|
+
function(e, n) {
|
|
1035
|
+
const { children: r, className: i, style: s, maxHeight: d, ...c } = e, [u, a] = C(null);
|
|
1036
|
+
return $(() => {
|
|
1037
|
+
let p = !1;
|
|
1038
|
+
return Oe().then(
|
|
1039
|
+
(m) => {
|
|
1040
|
+
p || a(() => m);
|
|
1041
|
+
},
|
|
1042
|
+
(m) => {
|
|
1043
|
+
console.error("[RealtimeCanvas] failed to load the rendering chunk:", m);
|
|
1044
|
+
}
|
|
1045
|
+
), () => {
|
|
1046
|
+
p = !0;
|
|
1047
|
+
};
|
|
1048
|
+
}, []), u ? /* @__PURE__ */ l(u, { ref: n, selfScope: !0, maxHeight: d, className: i, style: s, ...c, children: r }) : /* @__PURE__ */ l(
|
|
1049
|
+
"div",
|
|
1050
|
+
{
|
|
1051
|
+
className: `sc-root${i ? ` ${i}` : ""}`,
|
|
1052
|
+
style: { minHeight: d ?? 200, ...s },
|
|
1053
|
+
"aria-busy": "true"
|
|
1054
|
+
}
|
|
1055
|
+
);
|
|
1056
|
+
}
|
|
1057
|
+
);
|
|
1058
|
+
function an(t) {
|
|
1059
|
+
return /* @__PURE__ */ l($e, { ...t });
|
|
1060
|
+
}
|
|
1061
|
+
function dn() {
|
|
1062
|
+
const { mockups: t, isRendering: e, error: n } = K();
|
|
1063
|
+
return { mockups: t, isRendering: e, error: n };
|
|
1064
|
+
}
|
|
1065
|
+
function Ft(t) {
|
|
1066
|
+
return t.type !== "color" && typeof t.width == "number" && t.width > 0 && typeof t.height == "number" && t.height > 0;
|
|
1067
|
+
}
|
|
1068
|
+
function ln(t, e = {}) {
|
|
1069
|
+
var y, b, o, g, w;
|
|
1070
|
+
const n = (t.placements ?? []).filter(Ft), r = n.map((f) => f.label), i = e.placement ? n.find((f) => f.label === e.placement) : n[0];
|
|
1071
|
+
if (!i)
|
|
1072
|
+
throw e.placement ? new T(
|
|
1073
|
+
"E_PRODUCT_NOT_RENDERABLE",
|
|
1074
|
+
`product ${t.id} has no renderable placement "${e.placement}". Renderable image placements: [${r.join(", ")}].`,
|
|
1075
|
+
{ productId: t.id, requested: e.placement, validNames: r, docSlug: "embed-mode" }
|
|
1076
|
+
) : new T(
|
|
1077
|
+
"E_PRODUCT_NOT_RENDERABLE",
|
|
1078
|
+
`product ${t.id} has no renderable image placement (a non-color placement with width/height). The catalog payload may be incomplete — fetch it via getProduct(), not a search hit.`,
|
|
1079
|
+
{ productId: t.id, docSlug: "embed-mode" }
|
|
1080
|
+
);
|
|
1081
|
+
const s = ((y = t.options) == null ? void 0 : y.attributes) ?? {}, c = Object.values(s).some(
|
|
1082
|
+
(f) => {
|
|
1083
|
+
var S;
|
|
1084
|
+
return (S = f == null ? void 0 : f.choices) == null ? void 0 : S.some((v) => v == null ? void 0 : v.hex);
|
|
1085
|
+
}
|
|
1086
|
+
) ? (g = (o = (b = t.options) == null ? void 0 : b.combinations) == null ? void 0 : o.find(
|
|
1087
|
+
(f) => typeof f.variantId == "string" && f.variantId !== ""
|
|
1088
|
+
)) == null ? void 0 : g.variantId : void 0, u = t.mockups ?? [], a = c ? u.filter((f) => {
|
|
1089
|
+
var S;
|
|
1090
|
+
return (S = f.gvids) == null ? void 0 : S.includes(c);
|
|
1091
|
+
}) : u, p = (a.length > 0 ? a : u).map((f) => f.id);
|
|
1092
|
+
if (p.length === 0)
|
|
1093
|
+
throw new T(
|
|
1094
|
+
"E_PRODUCT_NOT_RENDERABLE",
|
|
1095
|
+
`product ${t.id} has no mockup scenes — nothing to render a preview into.`,
|
|
1096
|
+
{ productId: t.id, docSlug: "embed-mode" }
|
|
1097
|
+
);
|
|
1098
|
+
return {
|
|
1099
|
+
product: {
|
|
1100
|
+
productId: t.id,
|
|
1101
|
+
mockupIds: p,
|
|
1102
|
+
...typeof c == "string" ? { variantId: c } : {},
|
|
1103
|
+
options: t.options,
|
|
1104
|
+
placements: (w = t.placements) == null ? void 0 : w.map((f) => f.label),
|
|
1105
|
+
mockups: u,
|
|
1106
|
+
requiredPlacements: t.requiredPlacements,
|
|
1107
|
+
...t.defaultGvid ? { defaultGvid: t.defaultGvid } : {},
|
|
1108
|
+
...typeof e.width == "number" ? { width: e.width } : {}
|
|
1109
|
+
},
|
|
1110
|
+
placement: {
|
|
1111
|
+
label: i.label,
|
|
1112
|
+
width: i.width,
|
|
1113
|
+
height: i.height,
|
|
1114
|
+
aspectRatio: i.width / i.height
|
|
1115
|
+
},
|
|
1116
|
+
placementLabels: r,
|
|
1117
|
+
placements: n.map((f) => ({
|
|
1118
|
+
label: f.label,
|
|
1119
|
+
width: f.width,
|
|
1120
|
+
height: f.height,
|
|
1121
|
+
aspectRatio: f.width / f.height
|
|
1122
|
+
})),
|
|
1123
|
+
primaryMockupId: p[0],
|
|
1124
|
+
variantId: c
|
|
1125
|
+
};
|
|
1126
|
+
}
|
|
1127
|
+
function Ut(t) {
|
|
1128
|
+
return new Intl.NumberFormat("en-US", {
|
|
1129
|
+
style: "currency",
|
|
1130
|
+
currency: "USD",
|
|
1131
|
+
minimumFractionDigits: t % 100 === 0 ? 0 : 2,
|
|
1132
|
+
maximumFractionDigits: t % 100 === 0 ? 0 : 2
|
|
1133
|
+
}).format(t / 100);
|
|
1134
|
+
}
|
|
1135
|
+
const Mt = {
|
|
1136
|
+
display: "inline-flex",
|
|
1137
|
+
alignItems: "center",
|
|
1138
|
+
justifyContent: "center",
|
|
1139
|
+
width: 32,
|
|
1140
|
+
height: 32,
|
|
1141
|
+
padding: 0,
|
|
1142
|
+
borderRadius: 9999,
|
|
1143
|
+
border: "none",
|
|
1144
|
+
background: "transparent",
|
|
1145
|
+
color: "var(--sc-color-foreground, #111)",
|
|
1146
|
+
font: "inherit",
|
|
1147
|
+
fontSize: 16,
|
|
1148
|
+
lineHeight: 1,
|
|
1149
|
+
cursor: "pointer"
|
|
1150
|
+
}, jt = {
|
|
1151
|
+
display: "flex",
|
|
1152
|
+
alignItems: "center",
|
|
1153
|
+
gap: 10,
|
|
1154
|
+
width: "100%",
|
|
1155
|
+
padding: "8px 10px",
|
|
1156
|
+
borderRadius: 8,
|
|
1157
|
+
border: "none",
|
|
1158
|
+
background: "transparent",
|
|
1159
|
+
color: "inherit",
|
|
1160
|
+
font: "inherit",
|
|
1161
|
+
fontSize: 12,
|
|
1162
|
+
fontWeight: 500,
|
|
1163
|
+
textAlign: "left",
|
|
1164
|
+
cursor: "pointer"
|
|
1165
|
+
};
|
|
1166
|
+
function ae({
|
|
1167
|
+
label: t,
|
|
1168
|
+
onSelect: e
|
|
1169
|
+
}) {
|
|
1170
|
+
return /* @__PURE__ */ l(
|
|
1171
|
+
"button",
|
|
1172
|
+
{
|
|
1173
|
+
type: "button",
|
|
1174
|
+
role: "menuitem",
|
|
1175
|
+
"data-sc-part": "snowcone-editor-menu-item",
|
|
1176
|
+
style: jt,
|
|
1177
|
+
onClick: e,
|
|
1178
|
+
children: t
|
|
1179
|
+
}
|
|
1180
|
+
);
|
|
1181
|
+
}
|
|
1182
|
+
function qt({
|
|
1183
|
+
fullscreen: t,
|
|
1184
|
+
onToggleFullscreen: e,
|
|
1185
|
+
viewCount: n,
|
|
1186
|
+
viewIndex: r,
|
|
1187
|
+
onSelectView: i,
|
|
1188
|
+
onExport: s
|
|
1189
|
+
}) {
|
|
1190
|
+
const [d, c] = C(!1), u = () => c(!1);
|
|
1191
|
+
return /* @__PURE__ */ N("div", { style: { position: "relative" }, children: [
|
|
1192
|
+
/* @__PURE__ */ l(
|
|
1193
|
+
"button",
|
|
1194
|
+
{
|
|
1195
|
+
type: "button",
|
|
1196
|
+
"aria-label": "Editor menu",
|
|
1197
|
+
"aria-haspopup": "menu",
|
|
1198
|
+
"aria-expanded": d,
|
|
1199
|
+
"data-sc-part": "snowcone-editor-menu",
|
|
1200
|
+
style: Mt,
|
|
1201
|
+
onClick: () => c((a) => !a),
|
|
1202
|
+
children: "⋮"
|
|
1203
|
+
}
|
|
1204
|
+
),
|
|
1205
|
+
d ? /* @__PURE__ */ N(Ge, { children: [
|
|
1206
|
+
/* @__PURE__ */ l(
|
|
1207
|
+
"div",
|
|
1208
|
+
{
|
|
1209
|
+
style: { position: "fixed", inset: 0, zIndex: 39 },
|
|
1210
|
+
onClick: u,
|
|
1211
|
+
"aria-hidden": "true"
|
|
1212
|
+
}
|
|
1213
|
+
),
|
|
1214
|
+
/* @__PURE__ */ N(
|
|
1215
|
+
"div",
|
|
1216
|
+
{
|
|
1217
|
+
role: "menu",
|
|
1218
|
+
"data-sc-part": "snowcone-editor-menu-list",
|
|
1219
|
+
style: {
|
|
1220
|
+
position: "absolute",
|
|
1221
|
+
right: 0,
|
|
1222
|
+
top: "100%",
|
|
1223
|
+
marginTop: 4,
|
|
1224
|
+
minWidth: 176,
|
|
1225
|
+
padding: 4,
|
|
1226
|
+
borderRadius: 12,
|
|
1227
|
+
background: "var(--sc-color-surface, #fff)",
|
|
1228
|
+
boxShadow: "0 8px 24px rgba(0,0,0,0.14)",
|
|
1229
|
+
border: "1px solid rgba(0,0,0,0.08)",
|
|
1230
|
+
zIndex: 40
|
|
1231
|
+
},
|
|
1232
|
+
children: [
|
|
1233
|
+
/* @__PURE__ */ l(
|
|
1234
|
+
ae,
|
|
1235
|
+
{
|
|
1236
|
+
label: t ? "Exit fullscreen" : "Fullscreen",
|
|
1237
|
+
onSelect: () => {
|
|
1238
|
+
u(), e();
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
),
|
|
1242
|
+
n > 1 ? Array.from({ length: n }, (a, p) => /* @__PURE__ */ l(
|
|
1243
|
+
ae,
|
|
1244
|
+
{
|
|
1245
|
+
label: `View ${p + 1}${p === r ? " ✓" : ""}`,
|
|
1246
|
+
onSelect: () => {
|
|
1247
|
+
u(), i(p);
|
|
1248
|
+
}
|
|
1249
|
+
},
|
|
1250
|
+
p
|
|
1251
|
+
)) : null,
|
|
1252
|
+
/* @__PURE__ */ l(
|
|
1253
|
+
ae,
|
|
1254
|
+
{
|
|
1255
|
+
label: "Export PNG",
|
|
1256
|
+
onSelect: () => {
|
|
1257
|
+
u(), s();
|
|
1258
|
+
}
|
|
1259
|
+
}
|
|
1260
|
+
)
|
|
1261
|
+
]
|
|
1262
|
+
}
|
|
1263
|
+
)
|
|
1264
|
+
] }) : null
|
|
1265
|
+
] });
|
|
1266
|
+
}
|
|
1267
|
+
function zt() {
|
|
1268
|
+
const { flatLayers: t, selectLayer: e, generateAllPreviews: n } = Ke({ previewSize: 96 });
|
|
1269
|
+
return $(() => {
|
|
1270
|
+
t.length > 0 && n();
|
|
1271
|
+
}, [t.length, n]), /* @__PURE__ */ N(
|
|
1272
|
+
"div",
|
|
1273
|
+
{
|
|
1274
|
+
"data-sc-part": "snowcone-editor-idle-dock",
|
|
1275
|
+
style: { display: "flex", alignItems: "center", justifyContent: "center", gap: 8, minHeight: 44 },
|
|
1276
|
+
children: [
|
|
1277
|
+
/* @__PURE__ */ l(M.Add, {}),
|
|
1278
|
+
t.length > 0 ? /* @__PURE__ */ l("div", { style: { width: 1, height: 28, background: "rgba(0,0,0,0.1)", flexShrink: 0 }, "aria-hidden": "true" }) : null,
|
|
1279
|
+
t.map((r) => /* @__PURE__ */ l(
|
|
1280
|
+
"button",
|
|
1281
|
+
{
|
|
1282
|
+
type: "button",
|
|
1283
|
+
"data-sc-part": "snowcone-editor-layer-thumb",
|
|
1284
|
+
"aria-label": `Select ${r.name}`,
|
|
1285
|
+
onClick: () => e(r.id),
|
|
1286
|
+
style: {
|
|
1287
|
+
width: 44,
|
|
1288
|
+
height: 44,
|
|
1289
|
+
padding: 2,
|
|
1290
|
+
borderRadius: 12,
|
|
1291
|
+
border: "1px solid rgba(0,0,0,0.1)",
|
|
1292
|
+
background: "var(--sc-color-surface, #fff)",
|
|
1293
|
+
overflow: "hidden",
|
|
1294
|
+
cursor: "pointer",
|
|
1295
|
+
flexShrink: 0,
|
|
1296
|
+
display: "inline-flex",
|
|
1297
|
+
alignItems: "center",
|
|
1298
|
+
justifyContent: "center"
|
|
1299
|
+
},
|
|
1300
|
+
children: r.previewUrl ? (
|
|
1301
|
+
// eslint-disable-next-line @next/next/no-img-element
|
|
1302
|
+
/* @__PURE__ */ l("img", { src: r.previewUrl, alt: "", style: { width: "100%", height: "100%", objectFit: "contain" } })
|
|
1303
|
+
) : /* @__PURE__ */ l(
|
|
1304
|
+
"span",
|
|
1305
|
+
{
|
|
1306
|
+
style: {
|
|
1307
|
+
fontSize: 10,
|
|
1308
|
+
fontWeight: 600,
|
|
1309
|
+
maxWidth: "100%",
|
|
1310
|
+
overflow: "hidden",
|
|
1311
|
+
textOverflow: "ellipsis",
|
|
1312
|
+
whiteSpace: "nowrap"
|
|
1313
|
+
},
|
|
1314
|
+
children: r.name
|
|
1315
|
+
}
|
|
1316
|
+
)
|
|
1317
|
+
},
|
|
1318
|
+
r.id
|
|
1319
|
+
))
|
|
1320
|
+
]
|
|
1321
|
+
}
|
|
1322
|
+
);
|
|
1323
|
+
}
|
|
1324
|
+
function Kt({
|
|
1325
|
+
onAddToCart: t,
|
|
1326
|
+
defaultQuantity: e
|
|
1327
|
+
}) {
|
|
1328
|
+
const { price: n, complete: r } = Bt();
|
|
1329
|
+
return /* @__PURE__ */ N(
|
|
1330
|
+
M.Buy,
|
|
1331
|
+
{
|
|
1332
|
+
onAddToCart: t,
|
|
1333
|
+
...typeof e == "number" ? { defaultQuantity: e } : {},
|
|
1334
|
+
style: {
|
|
1335
|
+
display: "inline-flex",
|
|
1336
|
+
alignItems: "center",
|
|
1337
|
+
gap: 6,
|
|
1338
|
+
padding: "7px 16px",
|
|
1339
|
+
marginLeft: 4,
|
|
1340
|
+
borderRadius: 9999,
|
|
1341
|
+
border: "none",
|
|
1342
|
+
background: "var(--sc-color-foreground, #111)",
|
|
1343
|
+
color: "var(--sc-color-surface, #fff)",
|
|
1344
|
+
font: "inherit",
|
|
1345
|
+
fontSize: 12,
|
|
1346
|
+
fontWeight: 700,
|
|
1347
|
+
whiteSpace: "nowrap",
|
|
1348
|
+
cursor: r ? "pointer" : "not-allowed",
|
|
1349
|
+
opacity: r ? 1 : 0.5
|
|
1350
|
+
},
|
|
1351
|
+
children: [
|
|
1352
|
+
"Add to cart",
|
|
1353
|
+
typeof n == "number" ? ` · ${Ut(n)}` : ""
|
|
1354
|
+
]
|
|
1355
|
+
}
|
|
1356
|
+
);
|
|
1357
|
+
}
|
|
1358
|
+
function Wt({
|
|
1359
|
+
title: t,
|
|
1360
|
+
height: e,
|
|
1361
|
+
mockupIds: n,
|
|
1362
|
+
onAddToCart: r,
|
|
1363
|
+
defaultQuantity: i,
|
|
1364
|
+
className: s,
|
|
1365
|
+
style: d
|
|
1366
|
+
}) {
|
|
1367
|
+
const [c, u] = C(!1), [a, p] = C(0), [m, y] = C(!1), b = x(null), o = ct(), g = n[Math.min(a, n.length - 1)], w = F(async () => {
|
|
1368
|
+
var D;
|
|
1369
|
+
const v = await ((D = b.current) == null ? void 0 : D.exportArtboards({ format: "dataUrl" }));
|
|
1370
|
+
if (!v) return;
|
|
1371
|
+
const [V, R] = Object.entries(v)[0] ?? [];
|
|
1372
|
+
if (typeof R != "string") return;
|
|
1373
|
+
const _ = document.createElement("a");
|
|
1374
|
+
_.href = R, _.download = `${V ?? "design"}.png`, _.click();
|
|
1375
|
+
}, []), f = {
|
|
1376
|
+
display: "flex",
|
|
1377
|
+
flexDirection: "column",
|
|
1378
|
+
overflow: "hidden",
|
|
1379
|
+
background: "var(--sc-color-surface, #fff)",
|
|
1380
|
+
color: "var(--sc-color-foreground, #111)",
|
|
1381
|
+
fontFamily: "ui-sans-serif, system-ui, sans-serif",
|
|
1382
|
+
...c ? {
|
|
1383
|
+
position: "fixed",
|
|
1384
|
+
inset: 0,
|
|
1385
|
+
zIndex: 9999,
|
|
1386
|
+
height: "100dvh",
|
|
1387
|
+
paddingBottom: "env(safe-area-inset-bottom)"
|
|
1388
|
+
} : {
|
|
1389
|
+
position: "relative",
|
|
1390
|
+
height: e,
|
|
1391
|
+
borderRadius: 16,
|
|
1392
|
+
border: "1px solid rgba(0,0,0,0.08)",
|
|
1393
|
+
boxShadow: "0 1px 3px rgba(0,0,0,0.08)"
|
|
1394
|
+
},
|
|
1395
|
+
...d
|
|
1396
|
+
}, S = {
|
|
1397
|
+
position: "absolute",
|
|
1398
|
+
top: 8,
|
|
1399
|
+
right: 12,
|
|
1400
|
+
width: 96,
|
|
1401
|
+
aspectRatio: "2 / 3",
|
|
1402
|
+
borderRadius: 12,
|
|
1403
|
+
overflow: "hidden",
|
|
1404
|
+
border: "1px solid rgba(0,0,0,0.1)",
|
|
1405
|
+
boxShadow: "0 4px 12px rgba(0,0,0,0.12)",
|
|
1406
|
+
background: "var(--sc-color-surface, #fff)",
|
|
1407
|
+
padding: 0,
|
|
1408
|
+
cursor: "pointer",
|
|
1409
|
+
zIndex: 2
|
|
1410
|
+
};
|
|
1411
|
+
return /* @__PURE__ */ N(
|
|
1412
|
+
"div",
|
|
1413
|
+
{
|
|
1414
|
+
"data-sc-part": "snowcone-editor",
|
|
1415
|
+
"data-sc-fullscreen": c ? "true" : void 0,
|
|
1416
|
+
className: s,
|
|
1417
|
+
style: f,
|
|
1418
|
+
children: [
|
|
1419
|
+
/* @__PURE__ */ N(
|
|
1420
|
+
"div",
|
|
1421
|
+
{
|
|
1422
|
+
"data-sc-part": "snowcone-editor-header",
|
|
1423
|
+
style: {
|
|
1424
|
+
display: "flex",
|
|
1425
|
+
alignItems: "center",
|
|
1426
|
+
gap: 2,
|
|
1427
|
+
padding: "10px 12px 4px 16px",
|
|
1428
|
+
flexShrink: 0
|
|
1429
|
+
},
|
|
1430
|
+
children: [
|
|
1431
|
+
/* @__PURE__ */ l("span", { style: { fontSize: 14, fontWeight: 700, marginRight: "auto" }, children: t }),
|
|
1432
|
+
/* @__PURE__ */ l(M.History, {}),
|
|
1433
|
+
/* @__PURE__ */ l(
|
|
1434
|
+
qt,
|
|
1435
|
+
{
|
|
1436
|
+
fullscreen: c,
|
|
1437
|
+
onToggleFullscreen: () => u((v) => !v),
|
|
1438
|
+
viewCount: n.length,
|
|
1439
|
+
viewIndex: a,
|
|
1440
|
+
onSelectView: p,
|
|
1441
|
+
onExport: () => void w()
|
|
1442
|
+
}
|
|
1443
|
+
),
|
|
1444
|
+
/* @__PURE__ */ l(Kt, { onAddToCart: r, defaultQuantity: i })
|
|
1445
|
+
]
|
|
1446
|
+
}
|
|
1447
|
+
),
|
|
1448
|
+
/* @__PURE__ */ N(
|
|
1449
|
+
"div",
|
|
1450
|
+
{
|
|
1451
|
+
"data-sc-part": "snowcone-editor-stage",
|
|
1452
|
+
style: { position: "relative", flex: 1, minHeight: 0, padding: "4px 12px" },
|
|
1453
|
+
children: [
|
|
1454
|
+
/* @__PURE__ */ l(M.Canvas, { ref: b, style: { height: "100%" } }),
|
|
1455
|
+
m ? (
|
|
1456
|
+
// Swapped: the mockup IS the stage; the corner chip returns to the
|
|
1457
|
+
// artwork. The canvas stays mounted underneath (no document
|
|
1458
|
+
// teardown), just covered.
|
|
1459
|
+
/* @__PURE__ */ N(
|
|
1460
|
+
"div",
|
|
1461
|
+
{
|
|
1462
|
+
"data-sc-part": "snowcone-editor-swap-stage",
|
|
1463
|
+
style: {
|
|
1464
|
+
position: "absolute",
|
|
1465
|
+
inset: 0,
|
|
1466
|
+
zIndex: 1,
|
|
1467
|
+
display: "flex",
|
|
1468
|
+
alignItems: "center",
|
|
1469
|
+
justifyContent: "center",
|
|
1470
|
+
background: "var(--sc-color-surface, #fff)",
|
|
1471
|
+
padding: 8
|
|
1472
|
+
},
|
|
1473
|
+
children: [
|
|
1474
|
+
/* @__PURE__ */ l(
|
|
1475
|
+
M.Preview,
|
|
1476
|
+
{
|
|
1477
|
+
mockupId: g,
|
|
1478
|
+
alt: "Product mockup",
|
|
1479
|
+
loadingOverlay: !0,
|
|
1480
|
+
fallback: /* @__PURE__ */ l("div", { "aria-busy": "true", children: "Rendering…" }),
|
|
1481
|
+
style: { maxWidth: "100%", maxHeight: "100%", borderRadius: 12 }
|
|
1482
|
+
}
|
|
1483
|
+
),
|
|
1484
|
+
/* @__PURE__ */ l(
|
|
1485
|
+
"button",
|
|
1486
|
+
{
|
|
1487
|
+
type: "button",
|
|
1488
|
+
"aria-label": "Back to artwork",
|
|
1489
|
+
"data-sc-part": "snowcone-editor-swap-back",
|
|
1490
|
+
onClick: () => y(!1),
|
|
1491
|
+
style: {
|
|
1492
|
+
...S,
|
|
1493
|
+
display: "flex",
|
|
1494
|
+
alignItems: "center",
|
|
1495
|
+
justifyContent: "center",
|
|
1496
|
+
fontSize: 11,
|
|
1497
|
+
fontWeight: 600,
|
|
1498
|
+
color: "inherit",
|
|
1499
|
+
border: "1px dashed rgba(0,0,0,0.25)"
|
|
1500
|
+
},
|
|
1501
|
+
children: "artwork"
|
|
1502
|
+
}
|
|
1503
|
+
)
|
|
1504
|
+
]
|
|
1505
|
+
}
|
|
1506
|
+
)
|
|
1507
|
+
) : /* @__PURE__ */ l(
|
|
1508
|
+
"button",
|
|
1509
|
+
{
|
|
1510
|
+
type: "button",
|
|
1511
|
+
"aria-label": "Show product mockup",
|
|
1512
|
+
"data-sc-part": "snowcone-editor-pip",
|
|
1513
|
+
onClick: () => y(!0),
|
|
1514
|
+
style: S,
|
|
1515
|
+
children: /* @__PURE__ */ l(
|
|
1516
|
+
M.Preview,
|
|
1517
|
+
{
|
|
1518
|
+
mockupId: g,
|
|
1519
|
+
alt: "Product mockup preview",
|
|
1520
|
+
loadingOverlay: !0,
|
|
1521
|
+
fallback: /* @__PURE__ */ l("span", { style: { fontSize: 10, opacity: 0.5 }, "aria-busy": "true", children: "mockup…" }),
|
|
1522
|
+
style: { width: "100%", height: "100%", display: "block" }
|
|
1523
|
+
}
|
|
1524
|
+
)
|
|
1525
|
+
}
|
|
1526
|
+
)
|
|
1527
|
+
]
|
|
1528
|
+
}
|
|
1529
|
+
),
|
|
1530
|
+
/* @__PURE__ */ N(
|
|
1531
|
+
"div",
|
|
1532
|
+
{
|
|
1533
|
+
"data-sc-part": "snowcone-editor-zone",
|
|
1534
|
+
"data-sc-zone-state": o ? "selected" : "idle",
|
|
1535
|
+
style: { flexShrink: 0, padding: "4px 16px 14px" },
|
|
1536
|
+
children: [
|
|
1537
|
+
/* @__PURE__ */ l("div", { style: { display: o ? void 0 : "none" }, children: /* @__PURE__ */ l(M.Controls, { placement: "docked" }) }),
|
|
1538
|
+
o ? null : /* @__PURE__ */ l(zt, {})
|
|
1539
|
+
]
|
|
1540
|
+
}
|
|
1541
|
+
)
|
|
1542
|
+
]
|
|
1543
|
+
}
|
|
1544
|
+
);
|
|
1545
|
+
}
|
|
1546
|
+
function cn(t) {
|
|
1547
|
+
const {
|
|
1548
|
+
onAddToCart: e,
|
|
1549
|
+
defaultQuantity: n,
|
|
1550
|
+
title: r = "Editor",
|
|
1551
|
+
height: i = 480,
|
|
1552
|
+
className: s,
|
|
1553
|
+
style: d,
|
|
1554
|
+
...c
|
|
1555
|
+
} = t;
|
|
1556
|
+
return /* @__PURE__ */ l(M.Root, { ...c, children: /* @__PURE__ */ l(
|
|
1557
|
+
Wt,
|
|
1558
|
+
{
|
|
1559
|
+
title: r,
|
|
1560
|
+
height: i,
|
|
1561
|
+
mockupIds: c.product.mockupIds,
|
|
1562
|
+
onAddToCart: e,
|
|
1563
|
+
...typeof n == "number" ? { defaultQuantity: n } : {},
|
|
1564
|
+
className: s,
|
|
1565
|
+
style: d
|
|
1566
|
+
}
|
|
1567
|
+
) });
|
|
1568
|
+
}
|
|
1569
|
+
We();
|
|
1570
|
+
export {
|
|
1571
|
+
M as E,
|
|
1572
|
+
sn as R,
|
|
1573
|
+
cn as S,
|
|
1574
|
+
on as a,
|
|
1575
|
+
an as b,
|
|
1576
|
+
rn as c,
|
|
1577
|
+
Re as d,
|
|
1578
|
+
xt as e,
|
|
1579
|
+
Ut as f,
|
|
1580
|
+
Bt as g,
|
|
1581
|
+
dn as h,
|
|
1582
|
+
ln as p,
|
|
1583
|
+
K as u,
|
|
1584
|
+
ft as v
|
|
1585
|
+
};
|
|
1586
|
+
//# sourceMappingURL=embed-DXGydZOT.js.map
|