@snowcone-app/canvas 0.21.3 → 0.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/STYLING_CONTRACT.md +131 -92
  2. package/dist/{EditorCanvasImpl-M7rw1c1k.js → EditorCanvasImpl-Ckg7WO2j.js} +4 -4
  3. package/dist/{EditorCanvasImpl-M7rw1c1k.js.map → EditorCanvasImpl-Ckg7WO2j.js.map} +1 -1
  4. package/dist/{SnowconeCanvas-Cx7nXlBI.js → SnowconeCanvas-D1sLcIja.js} +2 -2
  5. package/dist/{SnowconeCanvas-Cx7nXlBI.js.map → SnowconeCanvas-D1sLcIja.js.map} +1 -1
  6. package/dist/api/embed.d.ts +5 -3
  7. package/dist/components/editor/EditorCanvas.d.ts +9 -0
  8. package/dist/components/editor/EditorRoot.d.ts +11 -0
  9. package/dist/components/embed-realtime/validateEmbed.d.ts +10 -4
  10. package/dist/design/design-builder.d.ts +67 -12
  11. package/dist/design/product-config.d.ts +48 -0
  12. package/dist/design-builder-2VUjfmdt.js +422 -0
  13. package/dist/design-builder-2VUjfmdt.js.map +1 -0
  14. package/dist/editorErrors-B2mb1sVN.js.map +1 -1
  15. package/dist/{embed-QBZkgWDr.js → embed-DxsaqZJF.js} +524 -430
  16. package/dist/embed-DxsaqZJF.js.map +1 -0
  17. package/dist/embed.mjs +31 -29
  18. package/dist/errors/editorError.d.ts +13 -0
  19. package/dist/hooks/bindingGuards.d.ts +16 -0
  20. package/dist/hooks/useColorBinding.d.ts +2 -1
  21. package/dist/hooks/useFontBinding.d.ts +2 -1
  22. package/dist/hooks/useImageBinding.d.ts +2 -1
  23. package/dist/hooks/useTextBinding.d.ts +2 -1
  24. package/dist/index.mjs +3 -3
  25. package/dist/template-fields-CQ6n2P4V.js +548 -0
  26. package/dist/template-fields-CQ6n2P4V.js.map +1 -0
  27. package/dist/testing/failureFixtures.d.ts +2 -2
  28. package/dist/testing.mjs +1 -1
  29. package/example/package.json +1 -1
  30. package/package.json +1 -1
  31. package/dist/design-builder-CT4DHIPe.js +0 -367
  32. package/dist/design-builder-CT4DHIPe.js.map +0 -1
  33. package/dist/embed-QBZkgWDr.js.map +0 -1
  34. package/dist/template-fields-C2pSfMBh.js +0 -494
  35. package/dist/template-fields-C2pSfMBh.js.map +0 -1
@@ -1,494 +0,0 @@
1
- import { g as _, u as G, c as D, b as I } from "./editorErrors-B2mb1sVN.js";
2
- import { l as H } from "./design-builder-CT4DHIPe.js";
3
- import { toOptionAttributes as Z, toCombinations as tt, getMissingSelections as et, validateProductSelection as nt, findBestCombination as w, computeDisabledChoices as st } from "@snowcone-app/sdk";
4
- import { useCallback as v, useEffect as ot, useMemo as A, useRef as S, useState as L } from "react";
5
- import { c as rt, y as W, T as k, I as q, z as it } from "./FontAnalyzer-CwIpgTGd.js";
6
- import { U as at } from "./UnifiedFontService-CC3CSmH5.js";
7
- import { a as ct, o as N, b as c, n as lt, l as y, u as Y, c as ft } from "./CanvasStateV1-DmZ1Qvvn.js";
8
- function U(s) {
9
- return s.text;
10
- }
11
- function O(s) {
12
- return s.name;
13
- }
14
- class Ut {
15
- constructor(t) {
16
- this.listeners = /* @__PURE__ */ new Set(), this.getState = () => this.state, this.subscribe = (e) => (this.listeners.add(e), () => this.listeners.delete(e)), this.state = t;
17
- const n = /* @__PURE__ */ new Map();
18
- for (const e of t.elements) {
19
- const r = O(e), o = U(e);
20
- r && typeof o == "string" && n.set(r, o);
21
- }
22
- this.seedTextByName = n;
23
- }
24
- /** Replace the whole state (the canvas `onChange` path). */
25
- setState(t) {
26
- this.state = t, this.emit();
27
- }
28
- /** The seed value of a named text layer (for completeness rule C3). */
29
- seedTextOf(t) {
30
- return this.seedTextByName.get(t);
31
- }
32
- /** Current text of a named text layer, or undefined when absent. */
33
- textOf(t) {
34
- const n = this.state.elements.find((e) => O(e) === t);
35
- return n ? U(n) : void 0;
36
- }
37
- /** Kind of the named layer in the CURRENT state ('text' | 'image' | null
38
- * for unbindable), or undefined when no layer has the name. */
39
- layerKindOf(t) {
40
- const n = this.state.elements.find((e) => O(e) === t);
41
- return n ? H(n) : void 0;
42
- }
43
- /** Names of bindable layers in the current state, for error messages. */
44
- bindableLayerNames() {
45
- return this.state.elements.filter((t) => H(t) !== null).map(O).filter((t) => !!t);
46
- }
47
- /**
48
- * Direct write path for `Editor.TextField` when NO canvas is mounted (with
49
- * one, writes route through the editor command path and arrive back here
50
- * via `setState`). Immutable update; last-write-wins.
51
- */
52
- updateTextLayer(t, n) {
53
- let e = !1;
54
- const r = this.state.elements.map((o) => O(o) !== t ? o : (e = !0, { ...o, text: n }));
55
- if (!e)
56
- throw new _(
57
- "E_LAYER_NOT_FOUND",
58
- `no layer "${t}" in the current design state. Bindable layers: ${JSON.stringify(this.bindableLayerNames())}.`,
59
- { layerName: t, validNames: this.bindableLayerNames(), docSlug: "embed-mode" }
60
- );
61
- this.setState({ ...this.state, elements: r });
62
- }
63
- /** ≥1 element with visible content (completeness rule C4): non-empty text,
64
- * an image with a URL, or a shape. Hidden elements don't count. */
65
- hasRenderableElement() {
66
- return this.state.elements.some((t) => {
67
- if (t.visible === !1) return !1;
68
- const n = t.transformType;
69
- if (n === "image") return !!t.imageUrl;
70
- if (n === "shape" || n === "group" || n === "path") return !0;
71
- const e = U(t);
72
- return typeof e == "string" && e.trim().length > 0;
73
- });
74
- }
75
- emit() {
76
- for (const t of [...this.listeners]) t();
77
- }
78
- }
79
- function K(s) {
80
- return (s.choices ?? []).map((t) => typeof t == "string" ? t : t.label ?? "").filter((t) => t !== "");
81
- }
82
- function ut(s, t) {
83
- if (!s.variantId) return {};
84
- const n = t.find((r) => r.variantId === s.variantId);
85
- if (!n) return {};
86
- const e = {};
87
- for (const [r, o] of Object.entries(n))
88
- r === "variantId" || r === "price" || (typeof o == "string" ? e[r] = o : typeof o == "number" && (e[r] = String(o)));
89
- return e;
90
- }
91
- class Ft {
92
- constructor(t) {
93
- this.quantity = 1, this.version = 0, this.listeners = /* @__PURE__ */ new Set(), this.getVersion = () => this.version, this.subscribe = (n) => (this.listeners.add(n), () => this.listeners.delete(n)), this.product = t, this.attrs = Z({ options: t.options }), this.combos = tt({ options: t.options }), this.selection = ut(t, this.combos);
94
- }
95
- getAttributes() {
96
- return this.attrs;
97
- }
98
- getSelection() {
99
- return this.selection;
100
- }
101
- getQuantity() {
102
- return this.quantity;
103
- }
104
- /**
105
- * Select a choice for a variant attribute. Strict + loud (D4/E3): an
106
- * attribute key or choice that doesn't exist on the product is a wiring
107
- * mistake, not user state — throws `E_UNKNOWN_OPTION` listing what IS valid.
108
- */
109
- select(t, n) {
110
- const e = this.attrs[t];
111
- if (!e)
112
- throw new _(
113
- "E_UNKNOWN_OPTION",
114
- `product ${this.product.productId} has no option "${t}". Valid option keys: ${JSON.stringify(Object.keys(this.attrs))}.`,
115
- { key: t, validKeys: Object.keys(this.attrs), docSlug: "embed-mode" }
116
- );
117
- const r = K(e);
118
- if (r.length > 0 && !r.includes(n))
119
- throw new _(
120
- "E_UNKNOWN_OPTION",
121
- `"${n}" is not a choice of option "${t}" on product ${this.product.productId}. Valid choices: ${JSON.stringify(r)}.`,
122
- { key: t, choice: n, validChoices: r, docSlug: "embed-mode" }
123
- );
124
- this.selection[t] !== n && (this.selection = { ...this.selection, [t]: n }, this.bump());
125
- }
126
- /** Quantity is USER state (completeness rule C5 gates on it) — never throws. */
127
- setQuantity(t) {
128
- this.quantity !== t && (this.quantity = t, this.bump());
129
- }
130
- /** Attribute keys still required (non-optional) but unselected — Buy's
131
- * `option:<key>` reason codes. */
132
- missingOptionKeys() {
133
- return Object.keys(this.attrs).length === 0 ? [] : et(this.attrs, this.selection);
134
- }
135
- /** Full selection resolution (the C1 amendment): true when every required
136
- * attribute is selected AND the selection matches a valid combination. */
137
- selectionValid() {
138
- return Object.keys(this.attrs).length === 0 ? !0 : nt(this.attrs, this.selection, this.combos);
139
- }
140
- /** The variant (gvid) the current selection resolves to. Falls back to the
141
- * product's initial `variantId` while nothing has been selected. */
142
- resolvedVariantId() {
143
- if (Object.keys(this.attrs).length === 0 || this.combos.length === 0)
144
- return this.product.variantId;
145
- if (!this.selectionValid()) return;
146
- const t = w(this.selection, this.combos, this.attrs);
147
- return (typeof (t == null ? void 0 : t.variantId) == "string" && t.variantId !== "" ? t.variantId : void 0) ?? this.product.variantId;
148
- }
149
- /**
150
- * The variant (gvid) to RENDER with — deliberately looser than
151
- * {@link resolvedVariantId}. That one is Buy's currency: it returns
152
- * `undefined` while the selection is incomplete so completeness can gate.
153
- * But the PRODUCT PHOTO must follow the shopper's picks immediately —
154
- * "choose the Oak frame" should render Oak even while an unrelated axis
155
- * (size, pocket) is still unselected. This resolves the best combination
156
- * matching the CURRENT (possibly partial) selection, falling back to the
157
- * product's initial variant. (Before this split, switching a color swatch
158
- * with any axis unselected rendered nothing — the mockup silently stayed
159
- * on the old color.)
160
- */
161
- renderVariantId() {
162
- if (Object.keys(this.attrs).length === 0 || this.combos.length === 0)
163
- return this.product.variantId;
164
- const t = w(this.selection, this.combos, this.attrs);
165
- return (typeof (t == null ? void 0 : t.variantId) == "string" && t.variantId !== "" ? t.variantId : void 0) ?? this.product.variantId;
166
- }
167
- /** Price of the resolved combination, when the catalog carries one. */
168
- resolvedPrice() {
169
- if (!this.selectionValid()) return;
170
- const t = w(this.selection, this.combos, this.attrs);
171
- return typeof (t == null ? void 0 : t.price) == "number" ? t.price : void 0;
172
- }
173
- /** Choices invalid given the rest of the current selection — for hosts to
174
- * disable/grey out in their variant UI. */
175
- disabledChoices() {
176
- const t = {};
177
- for (const [n, e] of Object.entries(this.attrs))
178
- t[n] = { ...e, choices: K(e) };
179
- return st(this.selection, t, this.combos);
180
- }
181
- /** The combinations (for payload assembly via `createCartDetail`). */
182
- getCombinations() {
183
- return this.combos;
184
- }
185
- bump() {
186
- this.version++;
187
- for (const t of [...this.listeners]) t();
188
- }
189
- }
190
- const V = rt("useCommands");
191
- function _t() {
192
- const s = G(), {
193
- undo: t,
194
- redo: n,
195
- canUndo: e,
196
- canRedo: r,
197
- executeElementUpdate: o,
198
- executeAddElement: i,
199
- executeRemoveElement: a,
200
- executeReorderElement: u,
201
- executeCommandBatch: l,
202
- executeCreateArtboard: h,
203
- executeDeleteArtboard: b,
204
- executeUpdateArtboard: m
205
- } = s, d = v(() => {
206
- V.warn("[useCommands] clearHistory is not yet implemented in EditorContext");
207
- }, []), $ = v((C) => {
208
- V.warn("[useCommands] clearArtboardHistory is not yet implemented in EditorContext");
209
- }, []);
210
- return {
211
- // Undo/Redo
212
- undo: t,
213
- redo: n,
214
- canUndo: e,
215
- canRedo: r,
216
- // History management
217
- clearHistory: d,
218
- clearArtboardHistory: $,
219
- // Command execution
220
- executeElementUpdate: o,
221
- executeAddElement: i,
222
- executeRemoveElement: a,
223
- executeReorderElement: u,
224
- executeCreateArtboard: h,
225
- executeDeleteArtboard: b,
226
- executeUpdateArtboard: m,
227
- // Batch execution
228
- executeCommandBatch: l
229
- };
230
- }
231
- function kt() {
232
- const { selectedElement: s } = G();
233
- return s ?? null;
234
- }
235
- const mt = 3e3, z = {
236
- text: "useTextBinding",
237
- image: "useImageBinding",
238
- font: "useFontBinding"
239
- }, dt = {
240
- text: "setText",
241
- image: "setImageUrl",
242
- font: "setFontFamily"
243
- }, ht = {
244
- text: "text",
245
- image: "image",
246
- font: "text"
247
- }, F = /* @__PURE__ */ new Set();
248
- function X(s) {
249
- return s instanceof k ? "text" : s instanceof q ? "image" : "other";
250
- }
251
- function pt(s, t, n) {
252
- const e = `[${z[s]}]`, r = `the binding is dead (isConnected: false, ${dt[s]} is a no-op)`, o = ht[s], i = n.getAllByName(t);
253
- if (i.length > 0) {
254
- const l = [...new Set(i.map(X))], h = o === "text" ? "image" : "text", b = l.length === 1 && l[0] === h ? ` Bind it with ${z[h]}("${t}") instead.` : "";
255
- return `${e} the layer named "${t}" is ${l.join("/")}, not ${o} — ${r}.${b}`;
256
- }
257
- const a = n.getAll().filter((l) => l.name).map((l) => `"${l.name}" (${X(l)})`), u = a.length ? `Named layers on this canvas: ${a.join(", ")}. Check the name for a typo.` : `No element on this canvas has a name — name one via design().${o}(…, { name: '${t}' }) or the element's \`name\` property.`;
258
- return `${e} no ${o} layer named "${t}" exists — ${r}. ${u}`;
259
- }
260
- function M(s, t, n, e) {
261
- ot(() => {
262
- var i;
263
- if (e || typeof W > "u" || ((i = W.env) == null ? void 0 : i.NODE_ENV) === "production") return;
264
- const r = `${s}:${t}`;
265
- if (F.has(r)) return;
266
- const o = setTimeout(() => {
267
- F.has(r) || (F.add(r), console.warn(pt(s, t, n)));
268
- }, mt);
269
- return () => clearTimeout(o);
270
- }, [s, t, n, e]);
271
- }
272
- const gt = () => {
273
- }, yt = [];
274
- function Mt(s) {
275
- const { elementStore: t } = D(), { executeElementUpdate: n } = I(), e = A(() => t.getAllByName(s).filter((i) => i instanceof k), [t, s]), r = v(
276
- (o) => {
277
- for (const i of e) {
278
- const a = i.clone();
279
- a.setText(o), n(i, a);
280
- }
281
- },
282
- [e, n]
283
- );
284
- return M("text", s, t, e.length > 0), e.length === 0 ? { text: "", setText: gt, element: null, elements: yt, isConnected: !1 } : {
285
- text: e[0].getText(),
286
- setText: r,
287
- element: e[0],
288
- elements: e,
289
- isConnected: !0
290
- };
291
- }
292
- const bt = () => {
293
- }, xt = [];
294
- function vt(s, t, n) {
295
- const e = s / t;
296
- if (n >= e) {
297
- const r = t, o = r * n, i = s / o;
298
- return {
299
- width: o,
300
- height: r,
301
- cropX: (1 - i) / 2,
302
- cropY: 0,
303
- cropWidth: i,
304
- cropHeight: 1
305
- };
306
- } else {
307
- const r = s, o = r / n, i = t / o;
308
- return {
309
- width: r,
310
- height: o,
311
- cropX: 0,
312
- cropY: (1 - i) / 2,
313
- cropWidth: 1,
314
- cropHeight: i
315
- };
316
- }
317
- }
318
- function Pt(s, t) {
319
- const n = (t == null ? void 0 : t.fit) ?? "cover", { elementStore: e, setElements: r } = D(), { executeElementUpdate: o } = I(), i = A(() => e.getAllByName(s).filter((d) => d instanceof q), [e, s]), a = S(/* @__PURE__ */ new Map());
320
- for (const m of i)
321
- if (!a.current.has(m.id)) {
322
- const d = m.transformData;
323
- a.current.set(m.id, {
324
- width: d.width * d.cropWidth,
325
- height: d.height * d.cropHeight
326
- });
327
- }
328
- const u = S(i);
329
- u.current = i;
330
- const l = S(o);
331
- l.current = o;
332
- const h = S(r);
333
- h.current = r;
334
- const b = v(
335
- (m) => {
336
- const d = u.current, $ = l.current;
337
- for (const C of d) {
338
- const P = a.current.get(C.id);
339
- if (!P) continue;
340
- const { width: R, height: j } = P, p = C.clone();
341
- p.imageLoaded = !1, p.imageElement = null, p.isCropping = !1, p.imageUrl = m, n === "cover" ? (p.preserveDimensions = !0, p.onLoadCallback = (f) => {
342
- const E = f.imageAspectRatio || 1, g = vt(R, j, E);
343
- f.transformData.width = g.width, f.transformData.height = g.height, f.transformData.cropX = g.cropX, f.transformData.cropY = g.cropY, f.transformData.cropWidth = g.cropWidth, f.transformData.cropHeight = g.cropHeight, $(C, f);
344
- }) : (p.preserveDimensions = !1, p.onLoadCallback = (f) => {
345
- const E = f.transformData.width, g = f.transformData.height, B = Math.min(R / E, j / g, 1);
346
- B < 1 && (f.transformData.width = E * B, f.transformData.height = g * B), f.transformData.cropX = 0, f.transformData.cropY = 0, f.transformData.cropWidth = 1, f.transformData.cropHeight = 1, $(C, f);
347
- }), p.loadImage(m);
348
- }
349
- },
350
- [n]
351
- // Stable deps only — imageElements/executeElementUpdate/setElements accessed via refs
352
- );
353
- return M("image", s, e, i.length > 0), i.length === 0 ? { imageUrl: "", setImageUrl: bt, element: null, elements: xt, isConnected: !1 } : {
354
- imageUrl: i[0].imageUrl,
355
- setImageUrl: b,
356
- element: i[0],
357
- elements: i,
358
- isConnected: !0
359
- };
360
- }
361
- const Ct = [];
362
- function T(s) {
363
- let t = s.trim().toUpperCase();
364
- return t.length === 4 && t.startsWith("#") && (t = "#" + t[1] + t[1] + t[2] + t[2] + t[3] + t[3]), t;
365
- }
366
- function x(s, t) {
367
- return typeof s == "string" && T(s) === t;
368
- }
369
- function J(s, t) {
370
- var e, r, o;
371
- const n = s;
372
- return x(n.color, t) || x((e = n.transformData) == null ? void 0 : e.fillColor, t) || x((r = n.transformData) == null ? void 0 : r.strokeColor, t) || ((o = n.stroke) == null ? void 0 : o.enabled) === !0 && x(n.stroke.color, t);
373
- }
374
- function Nt(s, t, n) {
375
- var i, a, u;
376
- if (!J(s, t)) return null;
377
- const e = s.clone(), r = s, o = e;
378
- return x(r.color, t) && (typeof o.setColor == "function" ? o.setColor(n) : o.color = n), x((i = r.transformData) == null ? void 0 : i.fillColor, t) && (o.transformData = { ...o.transformData, fillColor: n }), x((a = r.transformData) == null ? void 0 : a.strokeColor, t) && (o.transformData = { ...o.transformData, strokeColor: n }), ((u = r.stroke) == null ? void 0 : u.enabled) === !0 && x(r.stroke.color, t) && (o.stroke = { ...o.stroke, color: n }), e;
379
- }
380
- function Rt(s) {
381
- const { elementStore: t } = D(), { executeElementUpdate: n } = I(), [e, r] = L(() => T(s)), [o, i] = L(s);
382
- s !== o && (i(s), r(T(s)));
383
- const a = A(
384
- () => t.getAll().filter((l) => J(l, e)),
385
- [t, e]
386
- ), u = v(
387
- (l) => {
388
- const h = T(l);
389
- if (h !== e) {
390
- for (const b of t.getAll()) {
391
- const m = Nt(b, e, l);
392
- m && n(b, m);
393
- }
394
- r(h);
395
- }
396
- },
397
- [t, e, n]
398
- );
399
- return a.length === 0 ? { color: e, setColor: u, elements: Ct, isConnected: !1 } : { color: e, setColor: u, elements: a, isConnected: !0 };
400
- }
401
- const Ot = () => {
402
- }, Dt = [];
403
- function jt(s) {
404
- const { elementStore: t } = D(), { executeElementUpdate: n } = I(), e = A(() => t.getAllByName(s).filter((i) => i instanceof k), [t, s]), r = v(
405
- (o) => {
406
- at.loadGoogleFontByName(o);
407
- for (const i of e) {
408
- if (i.fontFamily === o) continue;
409
- it.clearCache(i.fontFamily);
410
- const a = i.clone();
411
- a.fontFamily = o, n(i, a);
412
- }
413
- },
414
- [e, n]
415
- );
416
- return M("font", s, t, e.length > 0), e.length === 0 ? { fontFamily: "", setFontFamily: Ot, element: null, elements: Dt, isConnected: !1 } : {
417
- fontFamily: e[0].fontFamily,
418
- setFontFamily: r,
419
- element: e[0],
420
- elements: e,
421
- isConnected: !0
422
- };
423
- }
424
- function Ht(s) {
425
- const { elementStore: t } = D();
426
- return s ? t.getByName(s) ?? null : null;
427
- }
428
- const Q = "personalization", $t = ct("type", [
429
- N({
430
- type: y("text"),
431
- name: c().min(1),
432
- label: c(),
433
- placeholder: c().optional(),
434
- maxLength: lt().int().positive().optional(),
435
- artboard: c().min(1).optional(),
436
- group: c().optional()
437
- }),
438
- N({
439
- type: y("image"),
440
- name: c().min(1),
441
- label: c(),
442
- placeholder: c().optional(),
443
- fit: Y([y("cover"), y("contain")]).optional(),
444
- artboard: c().min(1).optional(),
445
- group: c().optional()
446
- }),
447
- N({
448
- type: y("color"),
449
- color: c().min(1),
450
- label: c(),
451
- artboard: c().min(1).optional(),
452
- group: c().optional()
453
- }),
454
- N({
455
- type: y("select"),
456
- name: c().min(1),
457
- label: c(),
458
- property: Y([y("text"), y("imageUrl"), y("fontFamily")]),
459
- options: ft(N({ label: c(), value: c() })).min(1),
460
- artboard: c().min(1).optional(),
461
- group: c().optional()
462
- })
463
- ]);
464
- function Lt(s) {
465
- if (!s || typeof s != "object") return [];
466
- const t = s[Q];
467
- if (!Array.isArray(t)) return [];
468
- const n = [];
469
- for (const e of t) {
470
- if (!e || typeof e != "object") continue;
471
- const r = "type" in e ? e : { ...e, type: "text" }, o = $t.safeParse(r);
472
- o.success && n.push(o.data);
473
- }
474
- return n;
475
- }
476
- function Wt(s, t) {
477
- return { ...s, [Q]: t };
478
- }
479
- export {
480
- Ft as C,
481
- Ut as D,
482
- Q as T,
483
- _t as a,
484
- Ht as b,
485
- jt as c,
486
- Pt as d,
487
- kt as e,
488
- Mt as f,
489
- K as g,
490
- Lt as r,
491
- Rt as u,
492
- Wt as w
493
- };
494
- //# sourceMappingURL=template-fields-C2pSfMBh.js.map