@snowcone-app/canvas 0.8.1 → 0.11.1
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/dist/CanvasStateV1-D3THl2Zc.js +456 -0
- package/dist/CanvasStateV1-D3THl2Zc.js.map +1 -0
- package/dist/HybridHistoryManager-DANuzx7G.js.map +1 -1
- package/dist/advanced.mjs +2 -2
- package/dist/api/embed.d.ts +4 -0
- package/dist/api/stable.d.ts +6 -2
- package/dist/components/embed/SnowconeCanvas.d.ts +8 -0
- package/dist/components/embed-realtime/RealtimeMockup.d.ts +20 -0
- package/dist/contexts/CanvasServicesContext.d.ts +9 -2
- package/dist/design/design-builder.d.ts +23 -1
- package/dist/design/template-fields.d.ts +59 -0
- package/dist/embed.mjs +136 -111
- package/dist/embed.mjs.map +1 -1
- package/dist/fonts/google-fonts.d.ts +1 -6
- package/dist/hooks/useArtboards.d.ts +1 -0
- package/dist/hooks/useColorBinding.d.ts +21 -0
- package/dist/index.mjs +45 -40
- package/dist/internals.mjs +1 -1
- package/dist/rendering/serialize-for-server.d.ts +1 -0
- package/dist/schemas-B4UXytQB.js +3250 -0
- package/dist/schemas-B4UXytQB.js.map +1 -0
- package/dist/services/imageSearch.d.ts +30 -0
- package/dist/style.css +1 -1
- package/dist/template-fields-C8Tj67ek.js +1585 -0
- package/dist/template-fields-C8Tj67ek.js.map +1 -0
- package/dist/utils/UnifiedFontService.d.ts +9 -30
- package/dist/{validation-CZ4CZV5B.js → validation-C857Ptxn.js} +5804 -6344
- package/dist/validation-C857Ptxn.js.map +1 -0
- package/package.json +3 -3
- package/dist/CanvasStateV1-D7mGz8FR.js +0 -3692
- package/dist/CanvasStateV1-D7mGz8FR.js.map +0 -1
- package/dist/components/MonotypeDemoPage.d.ts +0 -2
- package/dist/design-builder-CM5wSK5w.js +0 -1467
- package/dist/design-builder-CM5wSK5w.js.map +0 -1
- package/dist/utils/MonotypeCategoryMapping.d.ts +0 -36
- package/dist/utils/MonotypeService.d.ts +0 -148
- package/dist/validation-CZ4CZV5B.js.map +0 -1
package/dist/advanced.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { D as te, I as q, r as re, v as ne,
|
|
2
|
-
import {
|
|
1
|
+
import { D as te, I as q, r as re, v as ne, i as oe, e as ae } from "./validation-C857Ptxn.js";
|
|
2
|
+
import { j as it, k as lt, l as ct, B as dt, m as ut, n as mt, o as ft, p as ht, q as pt, s as gt, t as xt, w as bt, x as yt, y as vt, F as wt, z as St, G as Ct, H as Tt, J as Et, K as $t, L as kt, N as At, O as Ft, Q as Pt, R as Nt, S as Rt, T as Bt, U as Mt, V as Dt, W as zt, X as It, Y as Ot, Z as Lt, _ as Wt, $ as Kt, a0 as _t, a1 as Gt, a2 as Ut, a3 as jt, a4 as Jt, a5 as qt, a6 as Vt, a7 as Xt, a8 as Yt, a9 as Zt, aa as Ht, ab as Qt, ac as er, ad as tr, ae as rr, af as nr } from "./validation-C857Ptxn.js";
|
|
3
3
|
import { u as V } from "./ThemeContext-U-VDtIiS.js";
|
|
4
4
|
import { E as ar, P as sr, T as ir, p as lr, s as cr, b as dr, c as ur, d as mr, e as fr, f as hr, g as pr, a as gr } from "./ThemeContext-U-VDtIiS.js";
|
|
5
5
|
import { c as se, G as ie, F as le, g as ce, r as de, u as ue } from "./HybridHistoryManager-DANuzx7G.js";
|
package/dist/api/embed.d.ts
CHANGED
|
@@ -48,7 +48,11 @@ export { design, DesignBuilder } from '../design/design-builder.js';
|
|
|
48
48
|
export type { Anchor, ShapeKind, DesignArtboard } from '../design/design-builder.js';
|
|
49
49
|
export { useTextBinding } from '../hooks/useTextBinding.js';
|
|
50
50
|
export { useImageBinding } from '../hooks/useImageBinding.js';
|
|
51
|
+
export { useColorBinding } from '../hooks/useColorBinding.js';
|
|
52
|
+
export type { ColorBindingResult } from '../hooks/useColorBinding.js';
|
|
51
53
|
export { useElementByName } from '../hooks/useElementByName.js';
|
|
54
|
+
export { readTemplateFields, withTemplateFields, TEMPLATE_FIELDS_KEY, } from '../design/template-fields.js';
|
|
55
|
+
export type { TemplateField, TemplateTextField, TemplateImageField, TemplateColorField, } from '../design/template-fields.js';
|
|
52
56
|
export { CanvasServicesProvider, useCanvasServices } from '../contexts/CanvasServicesContext.js';
|
|
53
57
|
export type { CanvasServices, ResolvedCanvasServices } from '../contexts/CanvasServicesContext.js';
|
|
54
58
|
export { createProxyImageSearch, createProxyGenerate } from '../services/imageSearch.js';
|
package/dist/api/stable.d.ts
CHANGED
|
@@ -10,8 +10,8 @@ export { SnowconeCanvas, SnowconeCanvas as default } from '../components/embed/S
|
|
|
10
10
|
export type { SnowconeCanvasProps, SnowconeCanvasHandle, ArtboardConfig, CanvasState, ClipShape, AlignmentPoint, ExportStatusEvent, ExportConfig, ImageConfig, LayoutConfig, CanvasCutoutShape } from '../components/embed/SnowconeCanvas.js';
|
|
11
11
|
export { CanvasServicesProvider, useCanvasServices } from '../contexts/CanvasServicesContext.js';
|
|
12
12
|
export type { CanvasServices, ResolvedCanvasServices, VectorSearchProvider, VectorSearchResult, } from '../contexts/CanvasServicesContext.js';
|
|
13
|
-
export { createProxyImageSearch, createProxyGenerate } from '../services/imageSearch.js';
|
|
14
|
-
export type { ImageSearchProvider, ImageSearchResult, ImageSearchResponse, ImageSearchParams, GenerateProvider, GenerateParams, GenerateResponse, } from '../services/imageSearch.js';
|
|
13
|
+
export { createProxyImageSearch, createProxyGenerate, createProxyBgRemove } from '../services/imageSearch.js';
|
|
14
|
+
export type { ImageSearchProvider, ImageSearchResult, ImageSearchResponse, ImageSearchParams, GenerateProvider, GenerateParams, GenerateResponse, BgRemoveProvider, } from '../services/imageSearch.js';
|
|
15
15
|
export { useEditor } from '../contexts/EditorContext.js';
|
|
16
16
|
export type { EditorContextValue, EditorProviderProps } from '../contexts/EditorContext.js';
|
|
17
17
|
export { useArtboards } from '../hooks/useArtboards.js';
|
|
@@ -30,6 +30,8 @@ export { useTextBinding } from '../hooks/useTextBinding.js';
|
|
|
30
30
|
export type { TextBindingResult } from '../hooks/useTextBinding.js';
|
|
31
31
|
export { useImageBinding } from '../hooks/useImageBinding.js';
|
|
32
32
|
export type { ImageBindingResult, ImageBindingOptions, ImageFitMode } from '../hooks/useImageBinding.js';
|
|
33
|
+
export { useColorBinding } from '../hooks/useColorBinding.js';
|
|
34
|
+
export type { ColorBindingResult } from '../hooks/useColorBinding.js';
|
|
33
35
|
export { useElementByName } from '../hooks/useElementByName.js';
|
|
34
36
|
export { useContentReady } from '../hooks/useContentReady.js';
|
|
35
37
|
export type { UseContentReadyOptions } from '../hooks/useContentReady.js';
|
|
@@ -48,4 +50,6 @@ export { serializeStateForServer, CANVAS_STATE_SCHEMA_VERSION, } from '../render
|
|
|
48
50
|
export type { ServerRenderRequest } from '../rendering/serialize-for-server.js';
|
|
49
51
|
export { design, DesignBuilder } from '../design/design-builder.js';
|
|
50
52
|
export type { Anchor, ShapeKind, DesignArtboard, BackgroundOptions, ImageOptions, TextOptions, ShapeOptions, } from '../design/design-builder.js';
|
|
53
|
+
export { readTemplateFields, withTemplateFields, TEMPLATE_FIELDS_KEY, } from '../design/template-fields.js';
|
|
54
|
+
export type { TemplateField, TemplateTextField, TemplateImageField, TemplateColorField, } from '../design/template-fields.js';
|
|
51
55
|
export type { CanvasStateV1, SerializedArtboard, SerializedElement, DeserializeResult, ValidationResult, } from '../state/index.js';
|
|
@@ -33,6 +33,14 @@ export interface ArtboardConfig {
|
|
|
33
33
|
clipShape?: ClipShape;
|
|
34
34
|
/** Optional background color */
|
|
35
35
|
backgroundColor?: string;
|
|
36
|
+
/**
|
|
37
|
+
* Whether the background color is part of the design — painted in exports
|
|
38
|
+
* and server renders (realtime mockups), not just in the editor. Defaults to
|
|
39
|
+
* `true` when `backgroundColor` is explicitly set (and not 'transparent'),
|
|
40
|
+
* `false` otherwise: an author who sets a background expects the mockup to
|
|
41
|
+
* match the editor.
|
|
42
|
+
*/
|
|
43
|
+
exportBackground?: boolean;
|
|
36
44
|
/** Scale mode for initial image: "cover" fills area (may crop), "contain" fits inside (may have space). Default: "cover" */
|
|
37
45
|
scaleMode?: 'cover' | 'contain';
|
|
38
46
|
/** Top margin in pixels for contain mode (reduces available area) */
|
|
@@ -11,4 +11,24 @@ export interface RealtimeMockupProps {
|
|
|
11
11
|
className?: string;
|
|
12
12
|
style?: CSSProperties;
|
|
13
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* How far the displayed device-pixel width may exceed the delivered mockup's
|
|
16
|
+
* natural width before {@link resolutionMismatchHint} fires. Renders default to
|
|
17
|
+
* 1000px wide, so a 1000px image inside a ~1100 device-px slot is fine (browser
|
|
18
|
+
* downscale slack), but stretched across 2000 device px it looks soft and the
|
|
19
|
+
* developer deserves to hear why.
|
|
20
|
+
*/
|
|
21
|
+
export declare const RESOLUTION_MISMATCH_RATIO = 1.2;
|
|
22
|
+
/** Rounds a device-pixel width up to the next {@link SUGGESTED_WIDTHS} step
|
|
23
|
+
* (capped at the top step). */
|
|
24
|
+
export declare function suggestRenderWidth(devicePx: number): number;
|
|
25
|
+
/**
|
|
26
|
+
* Builds the dev-console warning shown when a delivered mockup's natural width
|
|
27
|
+
* is meaningfully below the width it's displayed at in DEVICE pixels (CSS width
|
|
28
|
+
* × `devicePixelRatio`) — the "my preview looks soft and nothing says why"
|
|
29
|
+
* trap: renders default to 1000px wide, which blurs on a large or high-density
|
|
30
|
+
* display. Returns `null` when the resolution is adequate (within
|
|
31
|
+
* {@link RESOLUTION_MISMATCH_RATIO}) or either measurement is unusable.
|
|
32
|
+
*/
|
|
33
|
+
export declare function resolutionMismatchHint(naturalWidth: number, devicePx: number): string | null;
|
|
14
34
|
export declare function RealtimeMockup({ mockupId, fallback, alt, className, style, }: RealtimeMockupProps): React.ReactElement;
|
|
@@ -58,8 +58,15 @@ export interface CanvasServices {
|
|
|
58
58
|
/** Vector/icon search provider (dev playground only — no wire contract yet). */
|
|
59
59
|
vectors?: VectorSearchProvider;
|
|
60
60
|
/**
|
|
61
|
-
*
|
|
62
|
-
*
|
|
61
|
+
* URL of your background-removal proxy route (`POST { imageUrl }` →
|
|
62
|
+
* `{ imageUrl }`; see `createProxyBgRemove` for the wire contract). Host this
|
|
63
|
+
* URL on your server; your bg-remove vendor key lives there.
|
|
64
|
+
*/
|
|
65
|
+
bgRemoveUrl?: string;
|
|
66
|
+
/**
|
|
67
|
+
* Advanced override: full background-removal provider. Given an image URL
|
|
68
|
+
* (or data URL), resolve to the processed image URL/data URL. Wins over
|
|
69
|
+
* `bgRemoveUrl`.
|
|
63
70
|
*/
|
|
64
71
|
removeBackground?: (imageUrl: string) => Promise<string>;
|
|
65
72
|
}
|
|
@@ -11,7 +11,8 @@ export interface DesignArtboard {
|
|
|
11
11
|
name?: string;
|
|
12
12
|
width: number;
|
|
13
13
|
height: number;
|
|
14
|
-
/** Optional solid background fill behind all elements.
|
|
14
|
+
/** Optional solid background fill behind all elements. Rendered everywhere
|
|
15
|
+
* the design is — editor, exports, and server renders (realtime mockups). */
|
|
15
16
|
backgroundColor?: string;
|
|
16
17
|
}
|
|
17
18
|
/** A stable layer name. Set it so you can bind the layer in an interactive
|
|
@@ -77,6 +78,26 @@ export declare class DesignBuilder {
|
|
|
77
78
|
private readonly els;
|
|
78
79
|
private idCounter;
|
|
79
80
|
constructor(artboard: DesignArtboard);
|
|
81
|
+
/**
|
|
82
|
+
* Seed a builder from a previously saved canvas state — the editor shape
|
|
83
|
+
* `<SnowconeCanvas onChange>` emits (and `toJSON()` produces).
|
|
84
|
+
*
|
|
85
|
+
* This is how a saved editable template re-enters the turnkey embed path:
|
|
86
|
+
* load the template's state JSON, lift it back into a `DesignBuilder`, and
|
|
87
|
+
* hand it to `<RealtimeEmbed design={…}>`. The active artboard becomes the
|
|
88
|
+
* builder's artboard; elements tagged for other artboards are skipped
|
|
89
|
+
* (untagged elements are assumed to belong to the active one).
|
|
90
|
+
*/
|
|
91
|
+
static fromState(state: {
|
|
92
|
+
elements: AnyElementConfig[];
|
|
93
|
+
artboards: Array<{
|
|
94
|
+
name: string;
|
|
95
|
+
width: number;
|
|
96
|
+
height: number;
|
|
97
|
+
backgroundColor?: string;
|
|
98
|
+
}>;
|
|
99
|
+
activeArtboard: string;
|
|
100
|
+
}): DesignBuilder;
|
|
80
101
|
private nextId;
|
|
81
102
|
/** Full-bleed background image (fills the whole artboard). Cover-fit (no
|
|
82
103
|
* distortion) when `aspectRatio` is supplied. Inserted at the bottom of the
|
|
@@ -100,6 +121,7 @@ export declare class DesignBuilder {
|
|
|
100
121
|
width: number;
|
|
101
122
|
height: number;
|
|
102
123
|
backgroundColor?: string;
|
|
124
|
+
exportBackground?: boolean;
|
|
103
125
|
}>;
|
|
104
126
|
activeArtboard: string;
|
|
105
127
|
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { ImageFitMode } from '../hooks/useImageBinding.js';
|
|
2
|
+
/** A buyer-editable text slot, bound to elements by their `name` property. */
|
|
3
|
+
export interface TemplateTextField {
|
|
4
|
+
type: 'text';
|
|
5
|
+
/** Element name (matches canvas layer `name` property). */
|
|
6
|
+
name: string;
|
|
7
|
+
/** Label shown to the buyer (e.g. "Your name"). */
|
|
8
|
+
label: string;
|
|
9
|
+
/** Placeholder text for the input. */
|
|
10
|
+
placeholder?: string;
|
|
11
|
+
}
|
|
12
|
+
/** A buyer-swappable image slot, bound to elements by their `name` property. */
|
|
13
|
+
export interface TemplateImageField {
|
|
14
|
+
type: 'image';
|
|
15
|
+
/** Element name (matches canvas layer `name` property). */
|
|
16
|
+
name: string;
|
|
17
|
+
/** Label shown to the buyer (e.g. "Upload your logo"). */
|
|
18
|
+
label: string;
|
|
19
|
+
/** Placeholder text for the input. */
|
|
20
|
+
placeholder?: string;
|
|
21
|
+
/** How the buyer's image fits the original element bounds. Default: "cover". */
|
|
22
|
+
fit?: ImageFitMode;
|
|
23
|
+
}
|
|
24
|
+
/** A buyer-editable color, matched by value across all elements that use it. */
|
|
25
|
+
export interface TemplateColorField {
|
|
26
|
+
type: 'color';
|
|
27
|
+
/** Original hex color to match (e.g. "#FF0000"). */
|
|
28
|
+
color: string;
|
|
29
|
+
/** Label shown to the buyer (e.g. "Accent color"). */
|
|
30
|
+
label: string;
|
|
31
|
+
}
|
|
32
|
+
/** One buyer-editable aspect of a template. */
|
|
33
|
+
export type TemplateField = TemplateTextField | TemplateImageField | TemplateColorField;
|
|
34
|
+
/**
|
|
35
|
+
* The key template fields are stored under on the state document.
|
|
36
|
+
* Kept as `personalization` for compatibility with designs saved on snowcone.app.
|
|
37
|
+
*/
|
|
38
|
+
export declare const TEMPLATE_FIELDS_KEY = "personalization";
|
|
39
|
+
/**
|
|
40
|
+
* Read the template fields off a parsed state document.
|
|
41
|
+
*
|
|
42
|
+
* Accepts any JSON value — a `CanvasState` from `onChange`, a `CanvasStateV1`
|
|
43
|
+
* document, or a raw `JSON.parse` of a stored state file. Legacy fields with
|
|
44
|
+
* no `type` are normalized to text fields; malformed entries are dropped.
|
|
45
|
+
* Returns `[]` when the document carries no fields (a plain, non-template design).
|
|
46
|
+
*/
|
|
47
|
+
export declare function readTemplateFields(state: unknown): TemplateField[];
|
|
48
|
+
/**
|
|
49
|
+
* Attach template fields to a state document before persisting it.
|
|
50
|
+
*
|
|
51
|
+
* ```ts
|
|
52
|
+
* onChange={(state) => setDraft(state)}
|
|
53
|
+
* // …on save:
|
|
54
|
+
* save(JSON.stringify(withTemplateFields(draft, fields)));
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export declare function withTemplateFields<T extends object>(state: T, fields: TemplateField[]): T & {
|
|
58
|
+
[TEMPLATE_FIELDS_KEY]: TemplateField[];
|
|
59
|
+
};
|
package/dist/embed.mjs
CHANGED
|
@@ -1,185 +1,210 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
import {
|
|
3
|
-
import { y as
|
|
4
|
-
import { jsx as
|
|
5
|
-
import { createContext as
|
|
1
|
+
import { a as W, e as H } from "./validation-C857Ptxn.js";
|
|
2
|
+
import { b as we, d as ye, f as Se } from "./validation-C857Ptxn.js";
|
|
3
|
+
import { y as b } from "./HybridHistoryManager-DANuzx7G.js";
|
|
4
|
+
import { jsx as E, Fragment as z } from "react/jsx-runtime";
|
|
5
|
+
import { createContext as J, useContext as Y, useMemo as S, useRef as x, useState as q, useEffect as B } from "react";
|
|
6
6
|
import { assertVariantSelected as Q, RenderSession as X } from "@snowcone-app/sdk";
|
|
7
|
-
import { S as
|
|
8
|
-
import { D as $e, d as
|
|
9
|
-
const
|
|
10
|
-
function
|
|
11
|
-
const e =
|
|
7
|
+
import { S as Z, s as ee } from "./template-fields-C8Tj67ek.js";
|
|
8
|
+
import { D as $e, T as Re, d as Te, r as Ie, a as xe, e as Me, f as Ue, g as Ce, w as Ne } from "./template-fields-C8Tj67ek.js";
|
|
9
|
+
const L = J(void 0);
|
|
10
|
+
function _() {
|
|
11
|
+
const e = Y(L);
|
|
12
12
|
if (!e)
|
|
13
13
|
throw new Error(
|
|
14
14
|
"useRealtimeMockups / <RealtimeCanvas> / <RealtimeMockup> must be rendered inside <RealtimeEmbed>. Wrap them: <RealtimeEmbed shop=… product=… design=… grantUrl=…>…</RealtimeEmbed>"
|
|
15
15
|
);
|
|
16
16
|
return e;
|
|
17
17
|
}
|
|
18
|
-
const
|
|
19
|
-
function
|
|
20
|
-
var
|
|
21
|
-
if ((
|
|
18
|
+
const v = "[RealtimeEmbed]";
|
|
19
|
+
function ne(e) {
|
|
20
|
+
var o, l;
|
|
21
|
+
if ((o = e == null ? void 0 : e.requiredPlacements) != null && o.length)
|
|
22
22
|
return e.requiredPlacements.filter((t) => !t.autoFilledByVariant).map((t) => t.label);
|
|
23
23
|
const n = new Set(
|
|
24
|
-
(((
|
|
24
|
+
(((l = e == null ? void 0 : e.options) == null ? void 0 : l.combinations) ?? []).map((t) => t.variantId).filter((t) => typeof t == "string" && t !== "")
|
|
25
25
|
);
|
|
26
26
|
return !!(e != null && e.variantId) || n.size > 1 ? [] : (e == null ? void 0 : e.placements) ?? [];
|
|
27
27
|
}
|
|
28
|
-
function
|
|
29
|
-
var
|
|
30
|
-
if (e || console.error(`${
|
|
31
|
-
`${
|
|
32
|
-
), (
|
|
33
|
-
`${
|
|
28
|
+
function te({ shop: e, product: n, design: s, hasGrant: o }) {
|
|
29
|
+
var u, a;
|
|
30
|
+
if (e || console.error(`${v} \`shop\` is required (your publishable shop id).`), o || console.error(
|
|
31
|
+
`${v} no grant source — pass \`grantUrl\` (a proxy to mintRealtimeGrant) or \`grant\`. Without it the session can never authorize and no mockup renders.`
|
|
32
|
+
), (u = n == null ? void 0 : n.mockupIds) != null && u.length || console.error(
|
|
33
|
+
`${v} product.mockupIds is empty — pass the catalog scene codes (product.mockups[].id) you want rendered, e.g. ["FV1qjO"].`
|
|
34
34
|
), n != null && n.options)
|
|
35
35
|
try {
|
|
36
36
|
Q(n);
|
|
37
37
|
} catch (r) {
|
|
38
|
-
console.error(`${
|
|
38
|
+
console.error(`${v} ${r instanceof Error ? r.message : String(r)}`);
|
|
39
39
|
}
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
`${
|
|
43
|
-
), (
|
|
44
|
-
`${
|
|
40
|
+
const l = s.toJSON(), t = l.activeArtboard, f = ne(n);
|
|
41
|
+
f.length > 1 && console.error(
|
|
42
|
+
`${v} product ${n.productId} requires placements [${f.join(", ")}] but <RealtimeEmbed> renders a single placement ("${t}"). The render will time out waiting for the others. This product needs the eject path — see https://developers.snowcone.app/embed-mode#eject.`
|
|
43
|
+
), (a = n == null ? void 0 : n.placements) != null && a.length && !n.placements.includes(t) && console.warn(
|
|
44
|
+
`${v} the design's placement "${t}" is not in product.placements [${n.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 }).`
|
|
45
45
|
);
|
|
46
|
-
const c =
|
|
46
|
+
const c = l.elements.map((r) => r.name).filter((r) => !!r), h = c.filter((r, i) => c.indexOf(r) !== i);
|
|
47
47
|
h.length && console.warn(
|
|
48
|
-
`${
|
|
48
|
+
`${v} duplicate layer name(s) [${[...new Set(h)].join(", ")}] — useTextBinding(name) / useImageBinding(name) bind to the FIRST match, so a duplicate name makes a control edit the wrong layer. Keep names unique.`
|
|
49
49
|
);
|
|
50
50
|
}
|
|
51
|
-
function
|
|
51
|
+
function re(e) {
|
|
52
52
|
if ("grantUrl" in e && e.grantUrl)
|
|
53
53
|
return { grantUrl: e.grantUrl };
|
|
54
54
|
const n = e.grant;
|
|
55
55
|
return typeof n == "function" ? { getToken: n } : { getToken: () => Promise.resolve(n) };
|
|
56
56
|
}
|
|
57
|
-
const
|
|
58
|
-
function
|
|
59
|
-
return `[RealtimeEmbed] No mockup after ${Math.round(
|
|
57
|
+
const V = 8e3;
|
|
58
|
+
function se(e) {
|
|
59
|
+
return `[RealtimeEmbed] No mockup after ${Math.round(V / 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 "${e}" — 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 "${e}" not existing on the product. The render may still arrive — this is a heads-up, not a failure.`;
|
|
60
60
|
}
|
|
61
|
-
function
|
|
62
|
-
const { shop: n, product: s, design:
|
|
63
|
-
r.current = t,
|
|
64
|
-
const [
|
|
61
|
+
function ge(e) {
|
|
62
|
+
const { shop: n, product: s, design: o, throttleMs: l = 200, onMockups: t, onRenderError: f, wsUrl: c, services: h, children: u } = e, a = S(() => o.toJSON().activeArtboard, [o]), r = x(t), i = x(f);
|
|
63
|
+
r.current = t, i.current = f;
|
|
64
|
+
const [w, k] = q([]), [$, y] = q(!0), [j, R] = q(null), M = !!("grantUrl" in e && e.grantUrl || "grant" in e && e.grant), U = re(e), G = "grantUrl" in U ? U.grantUrl : "getToken", C = `${s.productId}|${s.mockupIds.join(",")}|${s.variantId ?? ""}`, T = S(
|
|
65
65
|
() => {
|
|
66
66
|
try {
|
|
67
|
-
return { session: new X({ shop: n, product: s, wsUrl: c, ...
|
|
67
|
+
return { session: new X({ shop: n, product: s, wsUrl: c, ...U }) };
|
|
68
68
|
} catch (m) {
|
|
69
69
|
return { error: m instanceof Error ? m.message : String(m) };
|
|
70
70
|
}
|
|
71
71
|
},
|
|
72
72
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
73
|
-
[n,
|
|
74
|
-
), g = "session" in
|
|
75
|
-
|
|
73
|
+
[n, C, a, c, G]
|
|
74
|
+
), g = "session" in T ? T.session : null, I = "error" in T ? T.error : null, P = x(null);
|
|
75
|
+
B(() => {
|
|
76
76
|
var m;
|
|
77
|
-
if (typeof
|
|
78
|
-
const
|
|
79
|
-
if (P.current ===
|
|
80
|
-
P.current =
|
|
77
|
+
if (typeof b < "u" && ((m = b.env) == null ? void 0 : m.NODE_ENV) !== "production") {
|
|
78
|
+
const d = `${n}|${C}|${a}|${M}`;
|
|
79
|
+
if (P.current === d) return;
|
|
80
|
+
P.current = d, te({ shop: n, product: s, design: o, hasGrant: M });
|
|
81
81
|
}
|
|
82
|
-
}, [n,
|
|
83
|
-
const
|
|
84
|
-
g && (
|
|
85
|
-
var
|
|
86
|
-
const
|
|
87
|
-
|
|
82
|
+
}, [n, C, a, M]);
|
|
83
|
+
const N = S(() => (m, d = l) => {
|
|
84
|
+
g && (R(null), y(!0), g.renderState(a, m, d).catch((p) => {
|
|
85
|
+
var F;
|
|
86
|
+
const D = p instanceof Error ? p.message : String(p);
|
|
87
|
+
R(D), y(!1), (F = i.current) == null || F.call(i, D);
|
|
88
88
|
}));
|
|
89
|
-
}, [g,
|
|
90
|
-
|
|
89
|
+
}, [g, a, l]);
|
|
90
|
+
B(() => {
|
|
91
91
|
var m;
|
|
92
|
-
if (
|
|
93
|
-
|
|
92
|
+
if (I) {
|
|
93
|
+
R(I), y(!1), (m = i.current) == null || m.call(i, I);
|
|
94
94
|
return;
|
|
95
95
|
}
|
|
96
96
|
if (g)
|
|
97
|
-
return g.onMockups((
|
|
98
|
-
var
|
|
99
|
-
|
|
100
|
-
}), g.onError((
|
|
101
|
-
var
|
|
102
|
-
|
|
103
|
-
}),
|
|
104
|
-
}, [g,
|
|
105
|
-
var
|
|
106
|
-
if (
|
|
107
|
-
const m = setTimeout(() => console.warn(
|
|
97
|
+
return g.onMockups((d) => {
|
|
98
|
+
var p;
|
|
99
|
+
k(d), y(!1), (p = r.current) == null || p.call(r, d);
|
|
100
|
+
}), g.onError((d) => {
|
|
101
|
+
var p;
|
|
102
|
+
R(d), y(!1), (p = i.current) == null || p.call(i, d);
|
|
103
|
+
}), N(o.toServerRequest()), () => g.close();
|
|
104
|
+
}, [g, I]), B(() => {
|
|
105
|
+
var d;
|
|
106
|
+
if (!$ || typeof b > "u" || ((d = b.env) == null ? void 0 : d.NODE_ENV) === "production") return;
|
|
107
|
+
const m = setTimeout(() => console.warn(se(a)), V);
|
|
108
108
|
return () => clearTimeout(m);
|
|
109
|
-
}, [
|
|
110
|
-
const K =
|
|
109
|
+
}, [$, a]);
|
|
110
|
+
const K = S(
|
|
111
111
|
() => ({
|
|
112
112
|
session: g,
|
|
113
|
-
design:
|
|
114
|
-
placement:
|
|
113
|
+
design: o,
|
|
114
|
+
placement: a,
|
|
115
115
|
product: s,
|
|
116
|
-
mockups:
|
|
117
|
-
isRendering:
|
|
118
|
-
error:
|
|
119
|
-
throttleMs:
|
|
120
|
-
pushRender:
|
|
116
|
+
mockups: w,
|
|
117
|
+
isRendering: $,
|
|
118
|
+
error: j,
|
|
119
|
+
throttleMs: l,
|
|
120
|
+
pushRender: N
|
|
121
121
|
}),
|
|
122
|
-
[g,
|
|
123
|
-
),
|
|
124
|
-
return h ? /* @__PURE__ */
|
|
122
|
+
[g, o, a, s, w, $, j, l, N]
|
|
123
|
+
), A = /* @__PURE__ */ E(L.Provider, { value: K, children: u });
|
|
124
|
+
return h ? /* @__PURE__ */ E(W, { services: h, children: A }) : A;
|
|
125
125
|
}
|
|
126
|
-
function
|
|
126
|
+
function he({
|
|
127
127
|
children: e,
|
|
128
128
|
kit: n = "embed-only",
|
|
129
129
|
inheritTheme: s = !0,
|
|
130
|
-
maxHeight:
|
|
131
|
-
services:
|
|
130
|
+
maxHeight: o,
|
|
131
|
+
services: l,
|
|
132
132
|
className: t,
|
|
133
|
-
style:
|
|
133
|
+
style: f
|
|
134
134
|
}) {
|
|
135
|
-
const { design: c, placement: h, throttleMs:
|
|
136
|
-
return /* @__PURE__ */
|
|
137
|
-
|
|
135
|
+
const { design: c, placement: h, throttleMs: u, pushRender: a } = _(), r = S(() => c.toJSON(), [c]);
|
|
136
|
+
return /* @__PURE__ */ E("div", { className: `app-modern${t ? ` ${t}` : ""}`, style: f, children: /* @__PURE__ */ E(
|
|
137
|
+
Z,
|
|
138
138
|
{
|
|
139
139
|
kit: n,
|
|
140
140
|
inheritTheme: s,
|
|
141
|
-
services:
|
|
141
|
+
services: l,
|
|
142
142
|
artboards: r.artboards,
|
|
143
143
|
activeArtboard: h,
|
|
144
144
|
initialElements: r.elements,
|
|
145
|
-
layoutConfig:
|
|
145
|
+
layoutConfig: o ? { maxHeight: o } : void 0,
|
|
146
146
|
overlay: e,
|
|
147
|
-
onChange: (
|
|
147
|
+
onChange: (i) => a(ee(i), u)
|
|
148
148
|
}
|
|
149
149
|
) });
|
|
150
150
|
}
|
|
151
|
-
|
|
151
|
+
const ae = 1.2, O = [1200, 1400, 1600, 1800, 2e3, 2500, 3e3, 4e3];
|
|
152
|
+
function oe(e) {
|
|
153
|
+
for (const n of O)
|
|
154
|
+
if (n >= e) return n;
|
|
155
|
+
return O[O.length - 1];
|
|
156
|
+
}
|
|
157
|
+
function ie(e, n) {
|
|
158
|
+
if (!(e > 0) || !(n > 0) || n <= e * ae) return null;
|
|
159
|
+
const s = oe(n);
|
|
160
|
+
return `[RealtimeMockup] mockup rendered at ${e}px but displayed at ~${n} device px — the preview will look soft. Pass \`product.width\` (e.g. ${s}) on <RealtimeEmbed> for a crisp preview.`;
|
|
161
|
+
}
|
|
162
|
+
function pe({
|
|
152
163
|
mockupId: e,
|
|
153
164
|
fallback: n = null,
|
|
154
165
|
alt: s = "Live product mockup",
|
|
155
|
-
className:
|
|
156
|
-
style:
|
|
166
|
+
className: o,
|
|
167
|
+
style: l
|
|
157
168
|
}) {
|
|
158
|
-
const { mockups: t } =
|
|
159
|
-
|
|
169
|
+
const { mockups: t } = _(), f = x(/* @__PURE__ */ new Set()), c = e ? t.find((u) => u.mockupId === e && u.imageUrl) : t.find((u) => u.imageUrl);
|
|
170
|
+
if (!(c != null && c.imageUrl))
|
|
171
|
+
return /* @__PURE__ */ E(z, { children: n });
|
|
172
|
+
const h = (u) => {
|
|
173
|
+
var k;
|
|
174
|
+
if (typeof b > "u" || ((k = b.env) == null ? void 0 : k.NODE_ENV) === "production" || typeof window > "u" || f.current.has(c.mockupId)) return;
|
|
175
|
+
const a = u.currentTarget, r = a.getBoundingClientRect().width;
|
|
176
|
+
if (r <= 0) return;
|
|
177
|
+
const i = Math.round(r * (window.devicePixelRatio || 1)), w = ie(a.naturalWidth, i);
|
|
178
|
+
w && (f.current.add(c.mockupId), console.warn(w));
|
|
179
|
+
};
|
|
180
|
+
return (
|
|
160
181
|
// eslint-disable-next-line @next/next/no-img-element
|
|
161
|
-
/* @__PURE__ */
|
|
162
|
-
)
|
|
182
|
+
/* @__PURE__ */ E("img", { src: c.imageUrl, alt: s, className: o, style: l, onLoad: h })
|
|
183
|
+
);
|
|
163
184
|
}
|
|
164
|
-
function
|
|
165
|
-
const { mockups: e, isRendering: n, error: s } =
|
|
185
|
+
function ve() {
|
|
186
|
+
const { mockups: e, isRendering: n, error: s } = _();
|
|
166
187
|
return { mockups: e, isRendering: n, error: s };
|
|
167
188
|
}
|
|
168
|
-
|
|
189
|
+
H();
|
|
169
190
|
export {
|
|
170
|
-
|
|
191
|
+
W as CanvasServicesProvider,
|
|
171
192
|
$e as DesignBuilder,
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
193
|
+
he as RealtimeCanvas,
|
|
194
|
+
ge as RealtimeEmbed,
|
|
195
|
+
pe as RealtimeMockup,
|
|
196
|
+
Re as TEMPLATE_FIELDS_KEY,
|
|
197
|
+
we as createProxyGenerate,
|
|
198
|
+
ye as createProxyImageSearch,
|
|
199
|
+
Te as design,
|
|
200
|
+
Ie as readTemplateFields,
|
|
201
|
+
Se as useCanvasServices,
|
|
202
|
+
xe as useColorBinding,
|
|
203
|
+
Me as useElementByName,
|
|
204
|
+
Ue as useImageBinding,
|
|
205
|
+
ve as useRealtimeMockups,
|
|
206
|
+
Ce as useTextBinding,
|
|
207
|
+
te as validateEmbed,
|
|
208
|
+
Ne as withTemplateFields
|
|
184
209
|
};
|
|
185
210
|
//# sourceMappingURL=embed.mjs.map
|