@numueg/theme-sdk 0.3.1 → 0.4.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/dist/index.cjs +417 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +12 -215
- package/dist/index.d.ts +12 -215
- package/dist/index.mjs +408 -6
- package/dist/index.mjs.map +1 -1
- package/dist/mount-BN2mz_wx.d.ts +225 -0
- package/dist/mount-DH9dz3dq.d.mts +225 -0
- package/dist/v2-compat.cjs.map +1 -1
- package/dist/v2-compat.mjs.map +1 -1
- package/dist/validation.cjs +408 -0
- package/dist/validation.cjs.map +1 -0
- package/dist/validation.d.mts +89 -0
- package/dist/validation.d.ts +89 -0
- package/dist/validation.mjs +397 -0
- package/dist/validation.mjs.map +1 -0
- package/dist/verify.cjs +200 -0
- package/dist/verify.cjs.map +1 -0
- package/dist/verify.d.mts +65 -0
- package/dist/verify.d.ts +65 -0
- package/dist/verify.mjs +191 -0
- package/dist/verify.mjs.map +1 -0
- package/package.json +11 -1
package/dist/index.cjs
CHANGED
|
@@ -6,6 +6,400 @@ var jsxRuntime = require('react/jsx-runtime');
|
|
|
6
6
|
|
|
7
7
|
// src/types/theme.ts
|
|
8
8
|
var MAX_BLOCK_DEPTH = 5;
|
|
9
|
+
|
|
10
|
+
// src/validation/index.ts
|
|
11
|
+
var THEME_CONTRACT_VERSION = 1;
|
|
12
|
+
var SDK_VERSION = "0.4.0" ;
|
|
13
|
+
var REQUIRED_TEMPLATES = [
|
|
14
|
+
"home",
|
|
15
|
+
"product",
|
|
16
|
+
"collection",
|
|
17
|
+
"cart",
|
|
18
|
+
"page",
|
|
19
|
+
"search",
|
|
20
|
+
"404"
|
|
21
|
+
];
|
|
22
|
+
var KNOWN_TEMPLATES = /* @__PURE__ */ new Set([
|
|
23
|
+
...REQUIRED_TEMPLATES,
|
|
24
|
+
"blog",
|
|
25
|
+
"article",
|
|
26
|
+
"policies",
|
|
27
|
+
"password",
|
|
28
|
+
"account",
|
|
29
|
+
"checkout"
|
|
30
|
+
]);
|
|
31
|
+
var KNOWN_SETTING_TYPES = /* @__PURE__ */ new Set([
|
|
32
|
+
"text",
|
|
33
|
+
"textarea",
|
|
34
|
+
"richtext",
|
|
35
|
+
"number",
|
|
36
|
+
"range",
|
|
37
|
+
"color",
|
|
38
|
+
"checkbox",
|
|
39
|
+
"select",
|
|
40
|
+
"radio",
|
|
41
|
+
"font",
|
|
42
|
+
"image_picker",
|
|
43
|
+
"url",
|
|
44
|
+
"product",
|
|
45
|
+
"product_list",
|
|
46
|
+
"collection",
|
|
47
|
+
"collection_list",
|
|
48
|
+
"header",
|
|
49
|
+
"paragraph",
|
|
50
|
+
"html",
|
|
51
|
+
"date",
|
|
52
|
+
"time",
|
|
53
|
+
"video_picker",
|
|
54
|
+
"color_scheme",
|
|
55
|
+
"page_picker",
|
|
56
|
+
"blog_picker",
|
|
57
|
+
"link_list_picker",
|
|
58
|
+
"variant_picker",
|
|
59
|
+
"file_upload",
|
|
60
|
+
"icon_picker",
|
|
61
|
+
"icon"
|
|
62
|
+
]);
|
|
63
|
+
var PRESENTATIONAL_SETTING_TYPES = /* @__PURE__ */ new Set([
|
|
64
|
+
"header",
|
|
65
|
+
"paragraph",
|
|
66
|
+
"html"
|
|
67
|
+
]);
|
|
68
|
+
var SECTION_TYPE_RE = /^[a-z][a-z0-9_-]*$/;
|
|
69
|
+
var THEME_ID_RE = /^[a-z0-9][a-z0-9_-]*[a-z0-9]$/;
|
|
70
|
+
var SEMVER_RE = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z-.]+)?(?:\+[0-9A-Za-z-.]+)?$/;
|
|
71
|
+
function isObject(v) {
|
|
72
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
73
|
+
}
|
|
74
|
+
function isNonEmptyString(v) {
|
|
75
|
+
return typeof v === "string" && v.trim().length > 0;
|
|
76
|
+
}
|
|
77
|
+
var IssueBag = class {
|
|
78
|
+
constructor() {
|
|
79
|
+
this.issues = [];
|
|
80
|
+
}
|
|
81
|
+
err(code, message, path) {
|
|
82
|
+
this.issues.push({ level: "error", code, message, path });
|
|
83
|
+
}
|
|
84
|
+
warn(code, message, path) {
|
|
85
|
+
this.issues.push({ level: "warning", code, message, path });
|
|
86
|
+
}
|
|
87
|
+
result() {
|
|
88
|
+
return {
|
|
89
|
+
valid: !this.issues.some((i) => i.level === "error"),
|
|
90
|
+
issues: this.issues
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
function collectPresetSectionTypes(manifest) {
|
|
95
|
+
const types = /* @__PURE__ */ new Set();
|
|
96
|
+
const presets = manifest.presets;
|
|
97
|
+
if (!isObject(presets)) return types;
|
|
98
|
+
const buckets = [presets.templates, presets.section_groups];
|
|
99
|
+
for (const bucket of buckets) {
|
|
100
|
+
if (!isObject(bucket)) continue;
|
|
101
|
+
for (const entry of Object.values(bucket)) {
|
|
102
|
+
if (!isObject(entry)) continue;
|
|
103
|
+
const sections = entry.sections;
|
|
104
|
+
const instances = Array.isArray(sections) ? sections : isObject(sections) ? Object.values(sections) : [];
|
|
105
|
+
for (const inst of instances) {
|
|
106
|
+
if (isObject(inst) && isNonEmptyString(inst.type)) types.add(inst.type);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return types;
|
|
111
|
+
}
|
|
112
|
+
function validateSettingInto(bag, setting, pathPrefix, seenIds) {
|
|
113
|
+
if (!isObject(setting)) {
|
|
114
|
+
bag.err("schema.setting.invalid", "Setting must be an object.", pathPrefix);
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
const type = setting.type;
|
|
118
|
+
if (!isNonEmptyString(type)) {
|
|
119
|
+
bag.err("schema.setting.type.missing", "Setting is missing a `type`.", pathPrefix);
|
|
120
|
+
} else if (!KNOWN_SETTING_TYPES.has(type)) {
|
|
121
|
+
bag.warn(
|
|
122
|
+
"schema.setting.type.unknown",
|
|
123
|
+
`Unknown setting type "${type}" \u2014 the customizer will fall back to a text input.`,
|
|
124
|
+
pathPrefix
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
const presentational = isNonEmptyString(type) && PRESENTATIONAL_SETTING_TYPES.has(type);
|
|
128
|
+
if (!presentational) {
|
|
129
|
+
if (!isNonEmptyString(setting.id)) {
|
|
130
|
+
bag.err("schema.setting.id.missing", "Setting is missing an `id`.", pathPrefix);
|
|
131
|
+
} else {
|
|
132
|
+
if (seenIds.has(setting.id)) {
|
|
133
|
+
bag.err(
|
|
134
|
+
"schema.setting.id.duplicate",
|
|
135
|
+
`Duplicate setting id "${setting.id}".`,
|
|
136
|
+
pathPrefix
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
seenIds.add(setting.id);
|
|
140
|
+
}
|
|
141
|
+
if (!isNonEmptyString(setting.label)) {
|
|
142
|
+
bag.warn("schema.setting.label.missing", "Setting has no `label`.", pathPrefix);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
if (type === "select" || type === "radio") {
|
|
146
|
+
const options = setting.options;
|
|
147
|
+
if (!Array.isArray(options) || options.length === 0) {
|
|
148
|
+
bag.err(
|
|
149
|
+
"schema.setting.options.missing",
|
|
150
|
+
`"${type}" setting "${String(setting.id)}" must declare a non-empty \`options\` array.`,
|
|
151
|
+
pathPrefix
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
if (type === "range") {
|
|
156
|
+
if (typeof setting.min !== "number" || typeof setting.max !== "number") {
|
|
157
|
+
bag.err(
|
|
158
|
+
"schema.setting.range.bounds",
|
|
159
|
+
`"range" setting "${String(setting.id)}" must declare numeric \`min\` and \`max\`.`,
|
|
160
|
+
pathPrefix
|
|
161
|
+
);
|
|
162
|
+
} else if (setting.min >= setting.max) {
|
|
163
|
+
bag.err(
|
|
164
|
+
"schema.setting.range.order",
|
|
165
|
+
`"range" setting "${String(setting.id)}" has min >= max.`,
|
|
166
|
+
pathPrefix
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
function validateSectionSchema(schema, opts = {}) {
|
|
172
|
+
const bag = new IssueBag();
|
|
173
|
+
const where = opts.filenameType ? `${opts.filenameType}.json` : "section schema";
|
|
174
|
+
if (!isObject(schema)) {
|
|
175
|
+
bag.err("schema.invalid", "Section schema must be a JSON object.", where);
|
|
176
|
+
return bag.result();
|
|
177
|
+
}
|
|
178
|
+
const type = schema.type;
|
|
179
|
+
if (!isNonEmptyString(type)) {
|
|
180
|
+
bag.err("schema.type.missing", "Section schema is missing a `type`.", where);
|
|
181
|
+
} else {
|
|
182
|
+
if (!SECTION_TYPE_RE.test(type)) {
|
|
183
|
+
bag.err(
|
|
184
|
+
"schema.type.format",
|
|
185
|
+
`Section type "${type}" must match ${SECTION_TYPE_RE} (lowercase, start with a letter).`,
|
|
186
|
+
where
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
if (opts.filenameType && type !== opts.filenameType) {
|
|
190
|
+
bag.err(
|
|
191
|
+
"schema.type.filename_mismatch",
|
|
192
|
+
`Schema type "${type}" must equal its filename "${opts.filenameType}" (component-filename = schema-type convention).`,
|
|
193
|
+
where
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
if (!isNonEmptyString(schema.name)) {
|
|
198
|
+
bag.err("schema.name.missing", "Section schema is missing a `name`.", where);
|
|
199
|
+
}
|
|
200
|
+
if (schema.settings === void 0) {
|
|
201
|
+
bag.warn("schema.settings.missing", "Section schema has no `settings`.", where);
|
|
202
|
+
} else if (!Array.isArray(schema.settings)) {
|
|
203
|
+
bag.err("schema.settings.invalid", "`settings` must be an array.", where);
|
|
204
|
+
} else {
|
|
205
|
+
const seen = /* @__PURE__ */ new Set();
|
|
206
|
+
schema.settings.forEach(
|
|
207
|
+
(s, i) => validateSettingInto(bag, s, `${where}.settings[${i}]`, seen)
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
if (schema.blocks !== void 0) {
|
|
211
|
+
if (!Array.isArray(schema.blocks)) {
|
|
212
|
+
bag.err("schema.blocks.invalid", "`blocks` must be an array.", where);
|
|
213
|
+
} else {
|
|
214
|
+
schema.blocks.forEach((b, i) => {
|
|
215
|
+
if (!isObject(b) || !isNonEmptyString(b.type)) {
|
|
216
|
+
bag.err("schema.block.type.missing", `Block[${i}] is missing a \`type\`.`, where);
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
if (!SECTION_TYPE_RE.test(b.type)) {
|
|
220
|
+
bag.err(
|
|
221
|
+
"schema.block.type.format",
|
|
222
|
+
`Block type "${b.type}" must match ${SECTION_TYPE_RE}.`,
|
|
223
|
+
where
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
if (Array.isArray(b.settings)) {
|
|
227
|
+
const seen = /* @__PURE__ */ new Set();
|
|
228
|
+
b.settings.forEach(
|
|
229
|
+
(s, j) => validateSettingInto(bag, s, `${where}.blocks[${i}].settings[${j}]`, seen)
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return bag.result();
|
|
236
|
+
}
|
|
237
|
+
function validateSettingsAgainstSchema(settings, schema, pathPrefix = "settings") {
|
|
238
|
+
const bag = new IssueBag();
|
|
239
|
+
if (!isObject(settings)) {
|
|
240
|
+
bag.err("instance.settings.invalid", "Section settings must be an object.", pathPrefix);
|
|
241
|
+
return bag.result();
|
|
242
|
+
}
|
|
243
|
+
const defs = Array.isArray(schema.settings) ? schema.settings : [];
|
|
244
|
+
const byId = /* @__PURE__ */ new Map();
|
|
245
|
+
for (const d of defs) if (isNonEmptyString(d?.id)) byId.set(d.id, d);
|
|
246
|
+
for (const [key, value] of Object.entries(settings)) {
|
|
247
|
+
const def = byId.get(key);
|
|
248
|
+
if (!def) {
|
|
249
|
+
bag.warn(
|
|
250
|
+
"instance.setting.unknown",
|
|
251
|
+
`Setting "${key}" is not declared in the "${String(schema.type)}" schema.`,
|
|
252
|
+
`${pathPrefix}.${key}`
|
|
253
|
+
);
|
|
254
|
+
continue;
|
|
255
|
+
}
|
|
256
|
+
if (value === null || value === void 0) continue;
|
|
257
|
+
const p = `${pathPrefix}.${key}`;
|
|
258
|
+
if ((def.type === "select" || def.type === "radio") && Array.isArray(def.options)) {
|
|
259
|
+
const allowed = def.options.map((o) => o.value);
|
|
260
|
+
if (typeof value === "string" && !allowed.includes(value)) {
|
|
261
|
+
bag.err(
|
|
262
|
+
"instance.setting.option.invalid",
|
|
263
|
+
`"${key}" = "${value}" is not one of: ${allowed.join(", ")}.`,
|
|
264
|
+
p
|
|
265
|
+
);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
if (def.type === "range" && typeof value === "number") {
|
|
269
|
+
if (typeof def.min === "number" && value < def.min) {
|
|
270
|
+
bag.err("instance.setting.range.under", `"${key}" = ${value} is below min ${def.min}.`, p);
|
|
271
|
+
}
|
|
272
|
+
if (typeof def.max === "number" && value > def.max) {
|
|
273
|
+
bag.err("instance.setting.range.over", `"${key}" = ${value} is above max ${def.max}.`, p);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
if (def.type === "checkbox" && typeof value !== "boolean") {
|
|
277
|
+
bag.warn("instance.setting.type.mismatch", `"${key}" should be a boolean.`, p);
|
|
278
|
+
}
|
|
279
|
+
if ((def.type === "number" || def.type === "range") && typeof value !== "number") {
|
|
280
|
+
bag.warn("instance.setting.type.mismatch", `"${key}" should be a number.`, p);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
return bag.result();
|
|
284
|
+
}
|
|
285
|
+
function validateManifestCore(bag, m) {
|
|
286
|
+
if (!isNonEmptyString(m.id)) {
|
|
287
|
+
bag.err("manifest.id.missing", "theme.json is missing `id`.", "id");
|
|
288
|
+
} else if (!THEME_ID_RE.test(m.id)) {
|
|
289
|
+
bag.err(
|
|
290
|
+
"manifest.id.format",
|
|
291
|
+
`Theme id "${m.id}" must be lowercase alphanumeric with dashes/underscores (no leading/trailing separator).`,
|
|
292
|
+
"id"
|
|
293
|
+
);
|
|
294
|
+
}
|
|
295
|
+
const name = m.name;
|
|
296
|
+
const nameOk = isNonEmptyString(name) || isObject(name) && Object.values(name).some((v) => isNonEmptyString(v));
|
|
297
|
+
if (!nameOk) {
|
|
298
|
+
bag.err("manifest.name.missing", "theme.json is missing a non-empty `name`.", "name");
|
|
299
|
+
}
|
|
300
|
+
if (!isNonEmptyString(m.version)) {
|
|
301
|
+
bag.err("manifest.version.missing", "theme.json is missing `version`.", "version");
|
|
302
|
+
} else if (!SEMVER_RE.test(m.version)) {
|
|
303
|
+
bag.err("manifest.version.invalid", `Version "${m.version}" is not valid semver.`, "version");
|
|
304
|
+
}
|
|
305
|
+
if (!isNonEmptyString(m.author)) {
|
|
306
|
+
bag.err("manifest.author.missing", "theme.json is missing `author`.", "author");
|
|
307
|
+
}
|
|
308
|
+
if (m.min_sdk_version !== void 0 && !SEMVER_RE.test(String(m.min_sdk_version))) {
|
|
309
|
+
bag.warn("manifest.min_sdk_version.invalid", "`min_sdk_version` is not valid semver.", "min_sdk_version");
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
function validateManifest(manifest, ctx = {}) {
|
|
313
|
+
const bag = new IssueBag();
|
|
314
|
+
if (!isObject(manifest)) {
|
|
315
|
+
bag.err("manifest.invalid", "theme.json must be a JSON object.", "theme.json");
|
|
316
|
+
return bag.result();
|
|
317
|
+
}
|
|
318
|
+
validateManifestCore(bag, manifest);
|
|
319
|
+
const presets = manifest.presets;
|
|
320
|
+
if (!isObject(presets) || Object.keys(presets).length === 0) {
|
|
321
|
+
bag.warn("manifest.presets.empty", "theme.json has no presets \u2014 merchants start with an empty page.", "presets");
|
|
322
|
+
} else {
|
|
323
|
+
if (ctx.sectionTypes) {
|
|
324
|
+
for (const type of collectPresetSectionTypes(manifest)) {
|
|
325
|
+
if (!ctx.sectionTypes.has(type)) {
|
|
326
|
+
bag.err(
|
|
327
|
+
"manifest.preset.unknown_section",
|
|
328
|
+
`Preset references section type "${type}" with no schemas/sections/${type}.json.`,
|
|
329
|
+
"presets"
|
|
330
|
+
);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
const templates = isObject(presets.templates) ? presets.templates : {};
|
|
335
|
+
for (const t of REQUIRED_TEMPLATES) {
|
|
336
|
+
if (!(t in templates)) {
|
|
337
|
+
bag.warn(
|
|
338
|
+
"manifest.template.missing",
|
|
339
|
+
`No preset for required template "${t}" \u2014 the storefront will fall back to its built-in.`,
|
|
340
|
+
`presets.templates.${t}`
|
|
341
|
+
);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
return bag.result();
|
|
346
|
+
}
|
|
347
|
+
function validateBuiltManifest(builtManifest, importMap, opts = {}) {
|
|
348
|
+
const bag = new IssueBag();
|
|
349
|
+
if (!isObject(builtManifest)) {
|
|
350
|
+
bag.err("built.invalid", "manifest.json must be a JSON object.", "manifest.json");
|
|
351
|
+
return bag.result();
|
|
352
|
+
}
|
|
353
|
+
validateManifestCore(bag, builtManifest);
|
|
354
|
+
const schemas = builtManifest.section_schemas;
|
|
355
|
+
const shipped = new Set(isObject(schemas) ? Object.keys(schemas) : []);
|
|
356
|
+
if (!isObject(schemas)) {
|
|
357
|
+
bag.warn("built.section_schemas.missing", "manifest.json has no `section_schemas`.", "section_schemas");
|
|
358
|
+
}
|
|
359
|
+
for (const type of collectPresetSectionTypes(builtManifest)) {
|
|
360
|
+
if (!shipped.has(type)) {
|
|
361
|
+
bag.err(
|
|
362
|
+
"built.preset.unknown_section",
|
|
363
|
+
`Preset references section type "${type}" not present in section_schemas.`,
|
|
364
|
+
"presets"
|
|
365
|
+
);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
if (isObject(schemas)) {
|
|
369
|
+
for (const [type, schema] of Object.entries(schemas)) {
|
|
370
|
+
const r = validateSectionSchema(schema, { filenameType: type });
|
|
371
|
+
for (const issue of r.issues) bag.issues.push(issue);
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
if (!isNonEmptyString(builtManifest.plugin_version)) {
|
|
375
|
+
bag.warn("built.plugin_version.missing", "manifest.json has no `plugin_version`.", "plugin_version");
|
|
376
|
+
}
|
|
377
|
+
if (importMap !== void 0) {
|
|
378
|
+
if (!isObject(importMap)) {
|
|
379
|
+
bag.err("importmap.invalid", "import-map.json must be a JSON object.", "import-map.json");
|
|
380
|
+
} else {
|
|
381
|
+
const cv = importMap.contract_version;
|
|
382
|
+
if (typeof cv !== "number") {
|
|
383
|
+
bag.warn(
|
|
384
|
+
"importmap.contract_version.missing",
|
|
385
|
+
"import-map.json has no numeric `contract_version` \u2014 built by an older plugin.",
|
|
386
|
+
"contract_version"
|
|
387
|
+
);
|
|
388
|
+
} else if (typeof opts.hostContractVersion === "number" && cv > opts.hostContractVersion) {
|
|
389
|
+
bag.err(
|
|
390
|
+
"importmap.contract_version.incompatible",
|
|
391
|
+
`Theme built for contract v${cv}; this platform supports up to v${opts.hostContractVersion}.`,
|
|
392
|
+
"contract_version"
|
|
393
|
+
);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
return bag.result();
|
|
398
|
+
}
|
|
399
|
+
function mergeResults(...results) {
|
|
400
|
+
const issues = results.flatMap((r) => r.issues);
|
|
401
|
+
return { valid: !issues.some((i) => i.level === "error"), issues };
|
|
402
|
+
}
|
|
9
403
|
var ShopContext = react.createContext(null);
|
|
10
404
|
var ProductContext = react.createContext(null);
|
|
11
405
|
var CollectionContext = react.createContext(null);
|
|
@@ -528,9 +922,8 @@ function toNavigationItem(raw, locale) {
|
|
|
528
922
|
url: raw.url || "/",
|
|
529
923
|
resource_type: mapResourceType(raw.type),
|
|
530
924
|
resource_handle: raw.resource_id ?? null,
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
)
|
|
925
|
+
target_visible: raw.target_visible !== false,
|
|
926
|
+
children: (raw.children ?? []).map((child) => toNavigationItem(child, locale)).filter((child) => child.target_visible)
|
|
534
927
|
};
|
|
535
928
|
}
|
|
536
929
|
function useNavigation(handle, options) {
|
|
@@ -540,7 +933,8 @@ function useNavigation(handle, options) {
|
|
|
540
933
|
const hostProvidedAny = !!navMap && Object.keys(navMap).length > 0;
|
|
541
934
|
const rawItems = handle ? navMap?.[handle] : void 0;
|
|
542
935
|
const hostItems = react.useMemo(() => {
|
|
543
|
-
if (rawItems)
|
|
936
|
+
if (rawItems)
|
|
937
|
+
return rawItems.map((it) => toNavigationItem(it, locale)).filter((it) => it.target_visible);
|
|
544
938
|
if (hostProvidedAny) return [];
|
|
545
939
|
return null;
|
|
546
940
|
}, [rawItems, hostProvidedAny, locale]);
|
|
@@ -1477,7 +1871,15 @@ function normalizeCartFromServer(cart) {
|
|
|
1477
1871
|
subtotal: toMajor(cart.subtotal),
|
|
1478
1872
|
total: toMajor(cart.total),
|
|
1479
1873
|
...cart.discount_amount != null ? { discount_amount: toMajor(cart.discount_amount) } : {},
|
|
1480
|
-
items: Array.isArray(cart.items) ? cart.items.map((it) =>
|
|
1874
|
+
items: Array.isArray(cart.items) ? cart.items.map((it) => {
|
|
1875
|
+
const raw = it;
|
|
1876
|
+
return {
|
|
1877
|
+
...it,
|
|
1878
|
+
name: raw.name || raw.product_name || "",
|
|
1879
|
+
price: toMajor(raw.price ?? raw.unit_price),
|
|
1880
|
+
variant_name: raw.variant_name ?? void 0
|
|
1881
|
+
};
|
|
1882
|
+
}) : []
|
|
1481
1883
|
};
|
|
1482
1884
|
}
|
|
1483
1885
|
function unwrapCart(json) {
|
|
@@ -3564,6 +3966,8 @@ exports.ICON_NAMES = ICON_NAMES;
|
|
|
3564
3966
|
exports.Icon = Icon;
|
|
3565
3967
|
exports.IconMap = IconMap;
|
|
3566
3968
|
exports.Image = Image;
|
|
3969
|
+
exports.KNOWN_SETTING_TYPES = KNOWN_SETTING_TYPES;
|
|
3970
|
+
exports.KNOWN_TEMPLATES = KNOWN_TEMPLATES;
|
|
3567
3971
|
exports.Link = Link;
|
|
3568
3972
|
exports.LocaleSwitcher = LocaleSwitcher;
|
|
3569
3973
|
exports.LocalizationContext = LocalizationContext;
|
|
@@ -3575,10 +3979,13 @@ exports.PageContext = PageContext;
|
|
|
3575
3979
|
exports.ProductCard = ProductCard;
|
|
3576
3980
|
exports.ProductContext = ProductContext;
|
|
3577
3981
|
exports.ProductProvider = ProductProvider;
|
|
3982
|
+
exports.REQUIRED_TEMPLATES = REQUIRED_TEMPLATES;
|
|
3578
3983
|
exports.RichText = RichText;
|
|
3984
|
+
exports.SDK_VERSION = SDK_VERSION;
|
|
3579
3985
|
exports.Section = Section;
|
|
3580
3986
|
exports.SectionContext = SectionContext;
|
|
3581
3987
|
exports.ShopContext = ShopContext;
|
|
3988
|
+
exports.THEME_CONTRACT_VERSION = THEME_CONTRACT_VERSION;
|
|
3582
3989
|
exports.ThemeSettingsContext = ThemeSettingsContext;
|
|
3583
3990
|
exports.applyGlobalStyleTokens = applyGlobalStyleTokens;
|
|
3584
3991
|
exports.applyImageTransform = applyImageTransform;
|
|
@@ -3605,6 +4012,7 @@ exports.isDefinedBlock = isDefinedBlock;
|
|
|
3605
4012
|
exports.isDefinedSection = isDefinedSection;
|
|
3606
4013
|
exports.isDynamicSource = isDynamicSource;
|
|
3607
4014
|
exports.isSdkAvailable = isSdkAvailable;
|
|
4015
|
+
exports.mergeResults = mergeResults;
|
|
3608
4016
|
exports.mountTheme = mountTheme;
|
|
3609
4017
|
exports.pickTranslations = pickTranslations;
|
|
3610
4018
|
exports.registerReactSingleton = registerReactSingleton;
|
|
@@ -3656,5 +4064,9 @@ exports.useThemeSettings = useThemeSettings;
|
|
|
3656
4064
|
exports.useTranslation = useTranslation;
|
|
3657
4065
|
exports.useVariantSelection = useVariantSelection;
|
|
3658
4066
|
exports.useWishlist = useWishlist;
|
|
4067
|
+
exports.validateBuiltManifest = validateBuiltManifest;
|
|
4068
|
+
exports.validateManifest = validateManifest;
|
|
4069
|
+
exports.validateSectionSchema = validateSectionSchema;
|
|
4070
|
+
exports.validateSettingsAgainstSchema = validateSettingsAgainstSchema;
|
|
3659
4071
|
//# sourceMappingURL=index.cjs.map
|
|
3660
4072
|
//# sourceMappingURL=index.cjs.map
|