@bettercms-ai/kit 2.0.0 → 2.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/lossy.d.ts +14 -6
- package/dist/adapters/lossy.js +23 -11
- package/dist/adapters/lossy.js.map +1 -1
- package/dist/adapters/prod-types.d.ts +46 -14
- package/dist/adapters/prod-types.js +37 -35
- package/dist/adapters/prod-types.js.map +1 -1
- package/dist/adapters/schema.d.ts +39 -0
- package/dist/adapters/schema.js +281 -82
- package/dist/adapters/schema.js.map +1 -1
- package/dist/context.d.ts +39 -0
- package/dist/context.js +40 -1
- package/dist/context.js.map +1 -1
- package/dist/controls/form-picker-register.d.ts +7 -1
- package/dist/controls/form-picker-register.js +1 -5
- package/dist/controls/form-picker-register.js.map +1 -1
- package/dist/controls/icon.d.ts +1 -1
- package/dist/controls/icon.js +1 -1
- package/dist/controls/icon.js.map +1 -1
- package/dist/controls/link.d.ts +11 -4
- package/dist/controls/link.js +120 -202
- package/dist/controls/link.js.map +1 -1
- package/dist/controls/location.js +3 -8
- package/dist/controls/location.js.map +1 -1
- package/dist/controls/media.d.ts +0 -14
- package/dist/controls/media.js +52 -95
- package/dist/controls/media.js.map +1 -1
- package/dist/controls/reference-services.d.ts +23 -2
- package/dist/controls/reference.d.ts +2 -2
- package/dist/controls/reference.js +79 -28
- package/dist/controls/reference.js.map +1 -1
- package/dist/controls/rich-text/article-shell.d.ts +145 -0
- package/dist/controls/rich-text/article-shell.js +514 -0
- package/dist/controls/rich-text/article-shell.js.map +1 -0
- package/dist/controls/rich-text/author.d.ts +25 -0
- package/dist/controls/rich-text/author.js +107 -0
- package/dist/controls/rich-text/author.js.map +1 -0
- package/dist/controls/rich-text/blocks.d.ts +19 -2
- package/dist/controls/rich-text/blocks.js +275 -638
- package/dist/controls/rich-text/blocks.js.map +1 -1
- package/dist/controls/rich-text/button.d.ts +23 -0
- package/dist/controls/rich-text/button.js +81 -0
- package/dist/controls/rich-text/button.js.map +1 -0
- package/dist/controls/rich-text/catalog.d.ts +2 -5
- package/dist/controls/rich-text/catalog.js +121 -7
- package/dist/controls/rich-text/catalog.js.map +1 -1
- package/dist/controls/rich-text/checklist.d.ts +24 -0
- package/dist/controls/rich-text/checklist.js +115 -0
- package/dist/controls/rich-text/checklist.js.map +1 -0
- package/dist/controls/rich-text/codec.d.ts +15 -1
- package/dist/controls/rich-text/codec.js +11 -1
- package/dist/controls/rich-text/codec.js.map +1 -1
- package/dist/controls/rich-text/columns.d.ts +41 -0
- package/dist/controls/rich-text/columns.js +181 -0
- package/dist/controls/rich-text/columns.js.map +1 -0
- package/dist/controls/rich-text/control.js +1 -0
- package/dist/controls/rich-text/control.js.map +1 -1
- package/dist/controls/rich-text/dom.d.ts +84 -4
- package/dist/controls/rich-text/dom.js +171 -10
- package/dist/controls/rich-text/dom.js.map +1 -1
- package/dist/controls/rich-text/editor.d.ts +4 -2
- package/dist/controls/rich-text/editor.js +199 -26
- package/dist/controls/rich-text/editor.js.map +1 -1
- package/dist/controls/rich-text/embed.d.ts +28 -0
- package/dist/controls/rich-text/embed.js +210 -0
- package/dist/controls/rich-text/embed.js.map +1 -0
- package/dist/controls/rich-text/footnote.d.ts +41 -0
- package/dist/controls/rich-text/footnote.js +185 -0
- package/dist/controls/rich-text/footnote.js.map +1 -0
- package/dist/controls/rich-text/gallery.d.ts +28 -0
- package/dist/controls/rich-text/gallery.js +167 -0
- package/dist/controls/rich-text/gallery.js.map +1 -0
- package/dist/controls/rich-text/link-form.d.ts +13 -1
- package/dist/controls/rich-text/link-form.js +41 -7
- package/dist/controls/rich-text/link-form.js.map +1 -1
- package/dist/controls/rich-text/ops.js +6 -0
- package/dist/controls/rich-text/ops.js.map +1 -1
- package/dist/controls/rich-text/related.d.ts +49 -0
- package/dist/controls/rich-text/related.js +233 -0
- package/dist/controls/rich-text/related.js.map +1 -0
- package/dist/controls/rich-text/toc.d.ts +47 -0
- package/dist/controls/rich-text/toc.js +160 -0
- package/dist/controls/rich-text/toc.js.map +1 -0
- package/dist/controls/slot-register.d.ts +6 -1
- package/dist/controls/slot-register.js +1 -4
- package/dist/controls/slot-register.js.map +1 -1
- package/dist/core/core.d.ts +11 -3
- package/dist/core/core.js +24 -6
- package/dist/core/core.js.map +1 -1
- package/dist/core/facets.d.ts +16 -0
- package/dist/core/facets.js +17 -1
- package/dist/core/facets.js.map +1 -1
- package/dist/core/index.js +2 -2
- package/dist/index.js +16 -5
- package/dist/index.js.map +1 -1
- package/dist/ledgers/exclusions.v1.js +141 -0
- package/dist/ledgers/exclusions.v1.js.map +1 -0
- package/dist/library/coverage.d.ts +13 -1
- package/dist/library/coverage.js +12 -1
- package/dist/library/coverage.js.map +1 -1
- package/dist/library/kit-catalog.json +158 -154
- package/dist/schema/types.d.ts +17 -0
- package/dist/schema/types.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/testing/coverage-extras.d.ts +8 -0
- package/dist/testing/coverage-extras.js +44 -0
- package/dist/testing/coverage-extras.js.map +1 -0
- package/dist/testing/exclusions.d.ts +30 -0
- package/dist/testing/exclusions.js +13 -0
- package/dist/testing/exclusions.js.map +1 -0
- package/dist/ui/autocomplete.d.ts +29 -1
- package/dist/ui/autocomplete.js +102 -47
- package/dist/ui/autocomplete.js.map +1 -1
- package/dist/ui/button.js +3 -5
- package/dist/ui/button.js.map +1 -1
- package/dist/ui/index.js +2 -2
- package/dist/ui/overlay.d.ts +4 -1
- package/dist/ui/overlay.js +2 -1
- package/dist/ui/overlay.js.map +1 -1
- package/dist/ui/toast.js +1 -1
- package/package.json +8 -2
package/dist/adapters/schema.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { CATALOG, FEATURES, isHostConfigKey } from "./lossy.js";
|
|
2
|
-
import { CONTROL_TYPES, HELP_MORE_MAX, ITEM_NAME_RE, UI_CONTROLS } from "./prod-types.js";
|
|
2
|
+
import { CONTROL_TYPES, FIELDSET_DESCRIPTION_MAX, FIELD_HELP_MAX, HELP_MORE_MAX, ITEM_NAME_RE, MAX_FIELD_DEPTH, OPTION_DESCRIPTION_MAX, PROP_GROUP_DESCRIPTION_MAX, PROP_HELP_MAX, PROP_PLACEHOLDER_MAX, PROP_TAB_MAX, TAB_MAX as TAB_MAX$1, UI_CONTROLS, UI_PLACEHOLDER_MAX } from "./prod-types.js";
|
|
3
3
|
import { dockIconOf, tablerIconOf } from "./icons.js";
|
|
4
4
|
import { slotChildrenFromStored, slotChildrenToStored } from "../controls/slot-services.js";
|
|
5
5
|
import { isDataTableProp, tableConfigFromOptions, tableOptionsFromConfig } from "../controls/table/prod.js";
|
|
6
6
|
import { buttonFromProd, buttonToProd, datetimeFromProd, datetimeToProd, imageFromProd, imageToProd, isCropRect, linkFromProd, linkToProd, listFromProd, listToProd, ratingFromProd, ratingToProd, referenceFromProd, referenceToProd, scaleFromProd, scaleToProd, typedRowsFromProd, typedRowsToProd, videoFromProd, videoToProd, zoneListFromProd, zoneListToProd } from "./values.js";
|
|
7
|
+
import { BLOCK_FIELD_TYPES_RENDERABLE_NOW, KEY_FORMAT, KIT_CATEGORIES, PRIMITIVE_ARRAY_RULE, RICHTEXT_FEATURES, SEGMENTED_MAX, SEGMENTED_MIN, isReservedKey, normaliseRichTextFeatures } from "@bettercms-ai/types";
|
|
7
8
|
//#region src/adapters/schema.ts
|
|
8
9
|
var isObj = (v) => !!v && typeof v === "object" && !Array.isArray(v);
|
|
9
10
|
function deepEqual(a, b) {
|
|
@@ -182,8 +183,12 @@ var CATEGORY_TO_PROD = {
|
|
|
182
183
|
Content: "content",
|
|
183
184
|
Layout: "section"
|
|
184
185
|
};
|
|
185
|
-
/** The field types a kind:'block' model
|
|
186
|
-
var BLOCK_FIELD_TYPES =
|
|
186
|
+
/** The field types a kind:'block' model holds today: the ones a block primitive renders (types, staged to G7). */
|
|
187
|
+
var BLOCK_FIELD_TYPES = new Set(BLOCK_FIELD_TYPES_RENDERABLE_NOW);
|
|
188
|
+
/** What a block row's cell may hold, and a primitive list's items (backend block-model-mapping.ts CELL_FIELD_TYPES, LIST_ITEM_TYPES). */
|
|
189
|
+
/** The block-variant select's key on a model (c2ee279dd: a top-level select, only beside v2.variants). */
|
|
190
|
+
var BLOCK_VARIANT_KEY = "_variant";
|
|
191
|
+
var BLOCK_CELL_TYPES = /* @__PURE__ */ new Set([
|
|
187
192
|
"text",
|
|
188
193
|
"longtext",
|
|
189
194
|
"richtext",
|
|
@@ -200,6 +205,24 @@ var BLOCK_FIELD_TYPES = /* @__PURE__ */ new Set([
|
|
|
200
205
|
"datetime",
|
|
201
206
|
"boolean"
|
|
202
207
|
]);
|
|
208
|
+
var BLOCK_LIST_ITEM_TYPES = /* @__PURE__ */ new Set([
|
|
209
|
+
"text",
|
|
210
|
+
"number",
|
|
211
|
+
"date"
|
|
212
|
+
]);
|
|
213
|
+
/**
|
|
214
|
+
* Whether a block model may hold this stored field (backend findUnmappableFields / containerProblem): its type has a
|
|
215
|
+
* primitive, and an object or array has rows of cells (an array no non-repeating fields), or lists text, numbers or dates.
|
|
216
|
+
*/
|
|
217
|
+
function blockRenders(f) {
|
|
218
|
+
if (!BLOCK_FIELD_TYPES.has(f.type)) return false;
|
|
219
|
+
if (f.type !== "object" && f.type !== "array") return true;
|
|
220
|
+
const zones = f.config?.zones;
|
|
221
|
+
if (f.type === "array" && zones?.nonRepeatable?.length) return false;
|
|
222
|
+
const row = f.type === "object" ? f.fields ?? [] : zones ? zones.repeatable?.fields ?? [] : null;
|
|
223
|
+
if (row === null) return BLOCK_LIST_ITEM_TYPES.has(String(f.config?.itemType));
|
|
224
|
+
return row.length > 0 && row.every((c) => BLOCK_CELL_TYPES.has(c.type));
|
|
225
|
+
}
|
|
203
226
|
/** A slot prop's config.minItems / maxItems cap (SLOT_ITEMS_CAP, componentPropDefSchema). */
|
|
204
227
|
var SLOT_ITEMS_CAP = 50;
|
|
205
228
|
/** A table prop's rows and an array prop's items: their config.minItems / maxItems cap (LIST_ITEMS_CAP). */
|
|
@@ -358,23 +381,26 @@ function shapeOf(f, lv, ctx, top, nest) {
|
|
|
358
381
|
};
|
|
359
382
|
return shape;
|
|
360
383
|
}
|
|
361
|
-
/**
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
function modelKeyOf(name) {
|
|
384
|
+
/**
|
|
385
|
+
* The key a model field is stored under: a V2 name the API refuses (types' isReservedKey, the API lane: `derived`,
|
|
386
|
+
* `layout`, `page`, a forbidden key or a leading `_`; or one off KEY_FORMAT), renamed. V2 authoring follows the API
|
|
387
|
+
* lane, so `id` is a field key like any other (only the derive lane, which mints keys, reserves it).
|
|
388
|
+
*/
|
|
389
|
+
/** The address-prefix keys a model may hold below its top level (019141ffc): they are no address there. */
|
|
390
|
+
var NESTED_OK_KEYS = /* @__PURE__ */ new Set(["layout", "page"]);
|
|
391
|
+
function modelKeyOf(name, nested = false) {
|
|
392
|
+
if (KEY_FORMAT.test(name) && (!isReservedKey(name) || nested && NESTED_OK_KEYS.has(name))) return name;
|
|
369
393
|
let k = name.replace(/^_+/, "").replace(/[^A-Za-z0-9_-]/g, "");
|
|
370
394
|
if (!/^[A-Za-z]/.test(k)) k = `f${k}`;
|
|
371
|
-
return
|
|
395
|
+
return isReservedKey(k) ? `${k}Field` : k;
|
|
372
396
|
}
|
|
397
|
+
/** The config keys a model's primitive list holds (types' PRIMITIVE_ARRAY_RULE). */
|
|
398
|
+
var MODEL_LIST_KEYS = new Set(PRIMITIVE_ARRAY_RULE.configKeys);
|
|
373
399
|
/** A slot's V2 allow list as the backend keeps it: 1–50 distinct block names of 1–64 characters (slotAllowIssues). */
|
|
374
400
|
var slotAllowOk = (allow) => Array.isArray(allow) && allow.length >= 1 && allow.length <= SLOT_ALLOW_MAX && new Set(allow).size === allow.length && allow.every((n) => typeof n === "string" && n === n.trim() && n.length >= 1 && n.length <= SLOT_ALLOW_NAME_MAX);
|
|
375
401
|
function shapeOfField(f, lv, ctx, top) {
|
|
376
402
|
const props = ctx.lane === "props";
|
|
377
|
-
const deep = lv >=
|
|
403
|
+
const deep = lv >= MAX_FIELD_DEPTH;
|
|
378
404
|
const of = Array.isArray(f.of) ? f.of : void 0;
|
|
379
405
|
/** a prop reference names a content model or a page / form / collection target (refTargetNamed): with none it is stored as json */
|
|
380
406
|
const noEntry = (r) => props && !(r?.to ?? []).some((t) => ENTRY_TARGET(t) || REF_TARGET_KINDS.includes(t));
|
|
@@ -498,6 +524,36 @@ var trunc = (ctx, at, s, max, feature) => {
|
|
|
498
524
|
lose(ctx, at, feature);
|
|
499
525
|
return s.slice(0, max);
|
|
500
526
|
};
|
|
527
|
+
/** The prod field types that store a rich text and its features (config.features). */
|
|
528
|
+
var RICH_TYPES = /* @__PURE__ */ new Set(["richtext", "document"]);
|
|
529
|
+
/** Every feature, canonical: RICHTEXT_FEATURES through normaliseRichTextFeatures, so no alias is ever in it. */
|
|
530
|
+
var ALL_RICH_FEATURES = normaliseRichTextFeatures(RICHTEXT_FEATURES).features;
|
|
531
|
+
/**
|
|
532
|
+
* A rich text's features through types normaliseRichTextFeatures (its aliases expand there: `headings` is h1–h6), distinct,
|
|
533
|
+
* in the order given. `named`: something was not carried (a name outside RICHTEXT_FEATURES, a repeat, a non-list).
|
|
534
|
+
*/
|
|
535
|
+
/** A content model's id, as the backend's config.references rule reads one. */
|
|
536
|
+
var MODEL_ID = /^[A-Za-z0-9_-]{1,64}$/;
|
|
537
|
+
/** A rich text's references: posts and authors, each a model id; `named` when anything else was there. */
|
|
538
|
+
function richRefs(v) {
|
|
539
|
+
if (!v || typeof v !== "object" || Array.isArray(v)) return { named: true };
|
|
540
|
+
const r = v;
|
|
541
|
+
const kept = {};
|
|
542
|
+
for (const k of ["posts", "authors"]) if (typeof r[k] === "string" && MODEL_ID.test(r[k])) kept[k] = r[k];
|
|
543
|
+
const named = Object.keys(r).some((k) => k !== "posts" && k !== "authors" || r[k] !== void 0 && kept[k] === void 0);
|
|
544
|
+
return {
|
|
545
|
+
kept: Object.keys(kept).length ? kept : void 0,
|
|
546
|
+
named
|
|
547
|
+
};
|
|
548
|
+
}
|
|
549
|
+
function richFeatures(v) {
|
|
550
|
+
const names = Array.isArray(v) ? v.filter((x) => typeof x === "string") : [];
|
|
551
|
+
const { features, unknown } = normaliseRichTextFeatures(names);
|
|
552
|
+
return {
|
|
553
|
+
kept: [...new Set(features)],
|
|
554
|
+
named: !Array.isArray(v) || names.length !== v.length || new Set(names).size !== names.length || unknown.length > 0
|
|
555
|
+
};
|
|
556
|
+
}
|
|
501
557
|
function convertField(f, at, lv, ctx, siblings, top, inTable = false, inItem = false, inSetting = false) {
|
|
502
558
|
const props = ctx.lane === "props";
|
|
503
559
|
const shape = shapeOf(f, lv, ctx, top, inTable ? "rows" : inItem ? "item" : inSetting ? "setting" : void 0);
|
|
@@ -512,8 +568,8 @@ function convertField(f, at, lv, ctx, siblings, top, inTable = false, inItem = f
|
|
|
512
568
|
if (twins) {
|
|
513
569
|
node.key = `${f.name}_${twins + 1}`;
|
|
514
570
|
lose(ctx, `${at}/name`, "duplicate name");
|
|
515
|
-
} else if (!props && modelKeyOf(f.name) !== f.name) {
|
|
516
|
-
node.key = modelKeyOf(f.name);
|
|
571
|
+
} else if (!props && modelKeyOf(f.name, lv > 1) !== f.name) {
|
|
572
|
+
node.key = modelKeyOf(f.name, lv > 1);
|
|
517
573
|
lose(ctx, `${at}/name`, "reserved name");
|
|
518
574
|
}
|
|
519
575
|
const nesting = shape.kind === "object" || shape.kind === "zones" || shape.kind === "types";
|
|
@@ -554,15 +610,15 @@ function convertField(f, at, lv, ctx, siblings, top, inTable = false, inItem = f
|
|
|
554
610
|
case "title":
|
|
555
611
|
case "type": break;
|
|
556
612
|
case "description":
|
|
557
|
-
node.helpText = trunc(ctx, p, f.description, props ?
|
|
613
|
+
node.helpText = trunc(ctx, p, f.description, props ? PROP_HELP_MAX : FIELD_HELP_MAX, "help>limit");
|
|
558
614
|
break;
|
|
559
615
|
case "helpMore":
|
|
560
616
|
node.helpMore = trunc(ctx, p, f.helpMore, HELP_MORE_MAX, "help>limit");
|
|
561
617
|
break;
|
|
562
618
|
case "placeholder":
|
|
563
|
-
if (props) node.placeholder = trunc(ctx, p, f.placeholder,
|
|
619
|
+
if (props) node.placeholder = trunc(ctx, p, f.placeholder, PROP_PLACEHOLDER_MAX, "help>limit");
|
|
564
620
|
else if (looseConfig) node.placeholder = f.placeholder;
|
|
565
|
-
else node.ui.placeholder = trunc(ctx, p, f.placeholder,
|
|
621
|
+
else node.ui.placeholder = trunc(ctx, p, f.placeholder, UI_PLACEHOLDER_MAX, "help>limit");
|
|
566
622
|
break;
|
|
567
623
|
case "initialValue":
|
|
568
624
|
if (props && (shape.type === "reference" || shape.type === "multi-reference" || shape.kind === "slot")) cat(ctx, p, "seeded instance");
|
|
@@ -597,7 +653,7 @@ function convertField(f, at, lv, ctx, siblings, top, inTable = false, inItem = f
|
|
|
597
653
|
case "hidden":
|
|
598
654
|
if (typeof f.hidden === "boolean") node.ui.hidden = f.hidden;
|
|
599
655
|
else {
|
|
600
|
-
const showIf = conditionToShowIf(f.hidden, p, siblings, ctx,
|
|
656
|
+
const showIf = conditionToShowIf(f.hidden, p, siblings, ctx, top && (props || !!ctx.variants));
|
|
601
657
|
if (showIf) node.showIf = showIf;
|
|
602
658
|
}
|
|
603
659
|
break;
|
|
@@ -630,7 +686,7 @@ function convertField(f, at, lv, ctx, siblings, top, inTable = false, inItem = f
|
|
|
630
686
|
node.advanced = f.advanced;
|
|
631
687
|
break;
|
|
632
688
|
case "ai":
|
|
633
|
-
|
|
689
|
+
node.ai = f.ai;
|
|
634
690
|
break;
|
|
635
691
|
case "reference":
|
|
636
692
|
if (shape.kind === "leaf" && shape.type === "reference") referenceToConfig(f.reference, node, p, ctx);
|
|
@@ -703,10 +759,27 @@ function convertField(f, at, lv, ctx, siblings, top, inTable = false, inItem = f
|
|
|
703
759
|
if (shape.kind === "leaf" && shape.type === "table") Object.assign(node.config, tableConfigFromOptions(f.table));
|
|
704
760
|
else lose(ctx, p, "type:table");
|
|
705
761
|
break;
|
|
762
|
+
case "references":
|
|
763
|
+
if (!RICH_TYPES.has(shape.type)) lose(ctx, p, "unsupported key");
|
|
764
|
+
else {
|
|
765
|
+
const { kept, named } = richRefs(f.references);
|
|
766
|
+
if (named) lose(ctx, p, "richtext references");
|
|
767
|
+
if (kept) node.config.references = kept;
|
|
768
|
+
}
|
|
769
|
+
break;
|
|
770
|
+
case "features":
|
|
771
|
+
if (!RICH_TYPES.has(shape.type)) lose(ctx, p, "unsupported key");
|
|
772
|
+
else {
|
|
773
|
+
const { kept, named } = richFeatures(f.features);
|
|
774
|
+
if (named) lose(ctx, p, "richtext features");
|
|
775
|
+
node.config.features = kept;
|
|
776
|
+
}
|
|
777
|
+
break;
|
|
706
778
|
default: lose(ctx, p, "unsupported key");
|
|
707
779
|
}
|
|
708
780
|
}
|
|
709
781
|
if (props && f.description === void 0) node.helpText = null;
|
|
782
|
+
if (RICH_TYPES.has(shape.type) && shape.kind === "leaf" && f.features === void 0) node.config.features = [...ALL_RICH_FEATURES];
|
|
710
783
|
if (f.itemNoun === void 0 && shape.kind === "zones" && node.ui.itemLabel !== void 0) cat(ctx, `${at}/itemNoun`, "itemNoun (derived)");
|
|
711
784
|
placeInSet(f, node, at, ctx, top, siblings);
|
|
712
785
|
if (f.type === "rating" && node.type === "rating" && f.numeric?.step === void 0) {
|
|
@@ -760,10 +833,24 @@ function placeInSet(f, node, at, ctx, top, siblings) {
|
|
|
760
833
|
}
|
|
761
834
|
return;
|
|
762
835
|
}
|
|
836
|
+
if (f.fieldset !== void 0 && !ctx.sets.has(f.fieldset) && !ctx.tabs.has(f.fieldset) && !ctx.droppedTabs.has(f.fieldset) && f.fieldset.length <= 60) {
|
|
837
|
+
const derived = ctx.derivedSets ??= [];
|
|
838
|
+
if (derived.length + ctx.sets.size + ctx.tabs.size < 30) {
|
|
839
|
+
derived.push({
|
|
840
|
+
id: f.fieldset,
|
|
841
|
+
name: f.fieldset,
|
|
842
|
+
kind: "group"
|
|
843
|
+
});
|
|
844
|
+
ctx.sets.set(f.fieldset, void 0);
|
|
845
|
+
}
|
|
846
|
+
}
|
|
763
847
|
const set = f.fieldset !== void 0 && ctx.sets.has(f.fieldset) ? f.fieldset : void 0;
|
|
764
848
|
if (f.fieldset !== void 0 && !set) lose(ctx, `${at}/fieldset`, "fieldset collision");
|
|
765
849
|
if (!top) {
|
|
766
|
-
if (f.group !== void 0)
|
|
850
|
+
if (f.group !== void 0) {
|
|
851
|
+
if (ctx.tabs.has(f.group)) node.ui.tab = { id: f.group };
|
|
852
|
+
else lose(ctx, `${at}/group`, "group (nested)");
|
|
853
|
+
}
|
|
767
854
|
if (set) node.fieldsetId = set;
|
|
768
855
|
return;
|
|
769
856
|
}
|
|
@@ -787,7 +874,7 @@ function propGroupOf(s, ctx) {
|
|
|
787
874
|
if (ctx.groupOrder) g.order = Math.min(99, ctx.propOrder.get(s.name) ?? 0);
|
|
788
875
|
return g;
|
|
789
876
|
}
|
|
790
|
-
var groupDescriptionOk = (d) => typeof d === "string" && d === d.trim() && d.length >= 1 && d.length <=
|
|
877
|
+
var groupDescriptionOk = (d) => typeof d === "string" && d === d.trim() && d.length >= 1 && d.length <= PROP_GROUP_DESCRIPTION_MAX;
|
|
791
878
|
/** The zone a datetime field fixes, if any (what lets a stored instant read back with its [Zone]). */
|
|
792
879
|
var fixedZone = (f) => typeof f.timezone === "string" && f.timezone.startsWith("fixed:") ? f.timezone.slice(6) : void 0;
|
|
793
880
|
/**
|
|
@@ -1226,7 +1313,7 @@ function optionsToProd(f, shape, node, at, ctx) {
|
|
|
1226
1313
|
}
|
|
1227
1314
|
const d = o.description;
|
|
1228
1315
|
if (d !== void 0) {
|
|
1229
|
-
if (typeof d === "string" && d.trim() !== "" && !/[\r\n]/.test(d) && d.length <=
|
|
1316
|
+
if (typeof d === "string" && d.trim() !== "" && !/[\r\n]/.test(d) && d.length <= OPTION_DESCRIPTION_MAX) out.description = d;
|
|
1230
1317
|
else lose(ctx, `${at}/${i}/description`, "option description");
|
|
1231
1318
|
}
|
|
1232
1319
|
for (const k of Object.keys(o)) if (![
|
|
@@ -1244,8 +1331,8 @@ function layoutToProd(f, shape, node, at, ctx) {
|
|
|
1244
1331
|
const t = shape.type;
|
|
1245
1332
|
const n = f.options?.length ?? 0;
|
|
1246
1333
|
if (l === "segmented" && t === "select") {
|
|
1247
|
-
if (n >=
|
|
1248
|
-
else if (n
|
|
1334
|
+
if (n >= SEGMENTED_MIN && n <= SEGMENTED_MAX) node.ui.control = "segmented";
|
|
1335
|
+
else if (n > SEGMENTED_MAX) cat(ctx, at, "segmented fallback");
|
|
1249
1336
|
else lose(ctx, at, "layout");
|
|
1250
1337
|
} else if (l === "slider" && t === "number" && f.type === "number") node.ui.control = "slider";
|
|
1251
1338
|
else if (UI_CONTROLS.includes(l) && l !== "segmented" && l !== "slider" && CONTROL_TYPES[l]?.includes(t)) node.ui.control = l;
|
|
@@ -1435,7 +1522,7 @@ function ofToProd(f, shape, node, at, lv, ctx) {
|
|
|
1435
1522
|
if (shape.kind === "itemType") node.config.itemType = shape.itemType;
|
|
1436
1523
|
itemIdentity(item, conventionItem(f.name, f.title), node, ip, ctx);
|
|
1437
1524
|
const settings = {};
|
|
1438
|
-
const scalars = shape.kind === "itemType" && !shape.shopify && ctx.lane === "props";
|
|
1525
|
+
const scalars = shape.kind === "itemType" && !shape.shopify && (ctx.lane === "props" || MODEL_LIST_KEYS.has("item"));
|
|
1439
1526
|
for (const k of Object.keys(item)) {
|
|
1440
1527
|
const v = item[k];
|
|
1441
1528
|
if (v === void 0) continue;
|
|
@@ -1446,7 +1533,7 @@ function ofToProd(f, shape, node, at, lv, ctx) {
|
|
|
1446
1533
|
if (shape.kind === "itemType" && item.type === "text") lose(ctx, p, "item settings");
|
|
1447
1534
|
} else if (k === "reference" && shape.kind === "refs") referenceToConfig(item.reference, node, p, ctx);
|
|
1448
1535
|
else if (k === "reference" && shape.kind === "itemType" && shape.shopify) continue;
|
|
1449
|
-
else if (scalars && k === "description" && typeof v === "string" && v.trim() === v && v.length >= 1 && v.length <=
|
|
1536
|
+
else if (scalars && k === "description" && typeof v === "string" && v.trim() === v && v.length >= 1 && v.length <= PROP_HELP_MAX) settings.helpText = v;
|
|
1450
1537
|
else if (scalars && k === "localized" && typeof v === "boolean") settings.localized = v;
|
|
1451
1538
|
else if (scalars && k === "validation") itemValidationToProd(item, shape.itemType, settings, p, ctx);
|
|
1452
1539
|
else lose(ctx, p, "item settings");
|
|
@@ -1548,28 +1635,8 @@ function blockModelFor(item, at, ctx, list) {
|
|
|
1548
1635
|
if (item[k] === void 0 || k === "type" || k === "title") continue;
|
|
1549
1636
|
if (k === "name") {
|
|
1550
1637
|
if (camel(slug) !== item.name) lose(ctx, p, "item identity");
|
|
1551
|
-
} else if (k === "fields") {
|
|
1552
|
-
|
|
1553
|
-
let shifted = false;
|
|
1554
|
-
fields.forEach((c, j) => {
|
|
1555
|
-
const fp = `${p}/${j}`;
|
|
1556
|
-
const mark = ctx.lossy.length;
|
|
1557
|
-
const markCat = ctx.catalog.length;
|
|
1558
|
-
const node = convertField(c, fp, 1, sub, fields, false);
|
|
1559
|
-
if (BLOCK_FIELD_TYPES.has(node.type)) {
|
|
1560
|
-
kept.push(emitField(node));
|
|
1561
|
-
if (dropped && !shifted) {
|
|
1562
|
-
shifted = true;
|
|
1563
|
-
lose(ctx, p, "block model field");
|
|
1564
|
-
}
|
|
1565
|
-
return;
|
|
1566
|
-
}
|
|
1567
|
-
ctx.lossy.length = mark;
|
|
1568
|
-
ctx.catalog.length = markCat;
|
|
1569
|
-
dropped = true;
|
|
1570
|
-
lose(ctx, fp, "block model field");
|
|
1571
|
-
});
|
|
1572
|
-
} else if (k === "openMode") cat(ctx, p, "item openMode");
|
|
1638
|
+
} else if (k === "fields") fields.forEach((c, j) => kept.push(emitField(convertField(c, `${p}/${j}`, 1, sub, fields, false))));
|
|
1639
|
+
else if (k === "openMode") chrome.openMode = item.openMode;
|
|
1573
1640
|
else if (k === "icon") {
|
|
1574
1641
|
const dock = dockIconOf(item.icon);
|
|
1575
1642
|
if (dock) chrome.icon = dock;
|
|
@@ -1577,11 +1644,17 @@ function blockModelFor(item, at, ctx, list) {
|
|
|
1577
1644
|
} else if (k === "preview") chrome.preview = previewToProd(item.preview, fields, p, ctx);
|
|
1578
1645
|
else lose(ctx, p, "item identity");
|
|
1579
1646
|
}
|
|
1580
|
-
const model = {
|
|
1647
|
+
const model = kept.every(blockRenders) ? {
|
|
1581
1648
|
name: item.title,
|
|
1582
1649
|
slug,
|
|
1583
1650
|
kind: "block",
|
|
1584
1651
|
fields: kept
|
|
1652
|
+
} : {
|
|
1653
|
+
name: item.title,
|
|
1654
|
+
slug,
|
|
1655
|
+
kind: "model",
|
|
1656
|
+
fields: kept,
|
|
1657
|
+
v2: { shape: "block" }
|
|
1585
1658
|
};
|
|
1586
1659
|
const prev = ctx.blockModels.get(slug);
|
|
1587
1660
|
const keep = () => {
|
|
@@ -1751,13 +1824,14 @@ function conditionToShowIf(h, at, siblings, ctx, variantOk) {
|
|
|
1751
1824
|
/** One V2 rule as a prod rule, or null when prod cannot hold it (a scope, a non-sibling, a value showIf cannot test). */
|
|
1752
1825
|
function conditionRule(r, head, siblings, variantOk) {
|
|
1753
1826
|
const variant = variantOk && r.field === "_variant";
|
|
1754
|
-
if (!r.field || r.scope
|
|
1827
|
+
if (!r.field || r.scope === void 0 && !variant && !siblings.some((s) => s.name === r.field)) return null;
|
|
1755
1828
|
const allowed = head ? [
|
|
1756
1829
|
"field",
|
|
1757
1830
|
"equals",
|
|
1758
1831
|
"notEmpty",
|
|
1759
1832
|
"op",
|
|
1760
1833
|
"value",
|
|
1834
|
+
"scope",
|
|
1761
1835
|
"also",
|
|
1762
1836
|
"match"
|
|
1763
1837
|
] : [
|
|
@@ -1765,7 +1839,8 @@ function conditionRule(r, head, siblings, variantOk) {
|
|
|
1765
1839
|
"equals",
|
|
1766
1840
|
"notEmpty",
|
|
1767
1841
|
"op",
|
|
1768
|
-
"value"
|
|
1842
|
+
"value",
|
|
1843
|
+
"scope"
|
|
1769
1844
|
];
|
|
1770
1845
|
if (Object.keys(r).some((k) => !allowed.includes(k) && r[k] !== void 0)) return null;
|
|
1771
1846
|
if ([
|
|
@@ -1773,22 +1848,26 @@ function conditionRule(r, head, siblings, variantOk) {
|
|
|
1773
1848
|
r.equals !== void 0,
|
|
1774
1849
|
r.notEmpty !== void 0
|
|
1775
1850
|
].filter(Boolean).length !== 1) return null;
|
|
1851
|
+
const scope = r.scope ? { scope: r.scope } : {};
|
|
1776
1852
|
if (r.notEmpty !== void 0) return r.notEmpty === true ? {
|
|
1777
1853
|
field: r.field,
|
|
1778
|
-
op: "notEmpty"
|
|
1854
|
+
op: "notEmpty",
|
|
1855
|
+
...scope
|
|
1779
1856
|
} : null;
|
|
1780
1857
|
const target = r.op !== void 0 ? r.value : r.equals;
|
|
1781
1858
|
const op = r.op !== void 0 ? SHOW_IF_OP[r.op] : Array.isArray(target) ? "in" : "eq";
|
|
1782
1859
|
if (!op) return null;
|
|
1783
1860
|
if (VALUELESS.has(op)) return r.value === void 0 ? {
|
|
1784
1861
|
field: r.field,
|
|
1785
|
-
op
|
|
1862
|
+
op,
|
|
1863
|
+
...scope
|
|
1786
1864
|
} : null;
|
|
1787
|
-
const sibType = variant ? void 0 : siblings.find((s) => s.name === r.field)?.type;
|
|
1865
|
+
const sibType = variant || r.scope ? void 0 : siblings.find((s) => s.name === r.field)?.type;
|
|
1788
1866
|
if (op === "gt" || op === "lt") return typeof target === "number" && Number.isFinite(target) ? {
|
|
1789
1867
|
field: r.field,
|
|
1790
1868
|
op,
|
|
1791
|
-
value: String(target)
|
|
1869
|
+
value: String(target),
|
|
1870
|
+
...scope
|
|
1792
1871
|
} : null;
|
|
1793
1872
|
const list = Array.isArray(target) ? target : [target];
|
|
1794
1873
|
const strs = [];
|
|
@@ -1805,16 +1884,19 @@ function conditionRule(r, head, siblings, variantOk) {
|
|
|
1805
1884
|
if (op === "in" || op === "notIn") return {
|
|
1806
1885
|
field: r.field,
|
|
1807
1886
|
op,
|
|
1808
|
-
value: strs
|
|
1887
|
+
value: strs,
|
|
1888
|
+
...scope
|
|
1809
1889
|
};
|
|
1810
1890
|
return Array.isArray(target) ? strs.length ? {
|
|
1811
1891
|
field: r.field,
|
|
1812
1892
|
op: op === "eq" ? "in" : "notIn",
|
|
1813
|
-
value: strs
|
|
1893
|
+
value: strs,
|
|
1894
|
+
...scope
|
|
1814
1895
|
} : null : {
|
|
1815
1896
|
field: r.field,
|
|
1816
1897
|
op,
|
|
1817
|
-
value: strs[0]
|
|
1898
|
+
value: strs[0],
|
|
1899
|
+
...scope
|
|
1818
1900
|
};
|
|
1819
1901
|
}
|
|
1820
1902
|
var nonEmpty = (o) => Object.keys(o).length ? o : void 0;
|
|
@@ -1831,6 +1913,7 @@ function common(n) {
|
|
|
1831
1913
|
"showIf",
|
|
1832
1914
|
"helpMore",
|
|
1833
1915
|
"advanced",
|
|
1916
|
+
"ai",
|
|
1834
1917
|
"recommendedMax",
|
|
1835
1918
|
"openMode",
|
|
1836
1919
|
"localized",
|
|
@@ -1924,9 +2007,12 @@ function fromTypeSchema(v2, target) {
|
|
|
1924
2007
|
blockModels: /* @__PURE__ */ new Map()
|
|
1925
2008
|
};
|
|
1926
2009
|
const props = target === "props";
|
|
2010
|
+
if (!props && v2.variants?.length) ctx.variants = true;
|
|
1927
2011
|
const slug = kebab(v2.name);
|
|
1928
|
-
const
|
|
2012
|
+
const kitCategory = KIT_CATEGORIES.includes(v2.category ?? "") ? v2.category : void 0;
|
|
2013
|
+
const category = kitCategory ?? (v2.category !== void 0 ? CATEGORY_TO_PROD[v2.category] : void 0);
|
|
1929
2014
|
const fieldsets = [];
|
|
2015
|
+
const block = {};
|
|
1930
2016
|
for (const k of Object.keys(v2)) {
|
|
1931
2017
|
if (v2[k] === void 0) continue;
|
|
1932
2018
|
const p = `/${k}`;
|
|
@@ -1940,23 +2026,22 @@ function fromTypeSchema(v2, target) {
|
|
|
1940
2026
|
case "fieldsets":
|
|
1941
2027
|
case "groups": break;
|
|
1942
2028
|
case "kind":
|
|
1943
|
-
if (props
|
|
1944
|
-
else if (!props && v2.kind !== "entry") cat(ctx, p, v2.kind === "global" ? "kind:global" : v2.kind === "page" ? "kind:page" : v2.kind === "block" ? "kind:block (fields)" : "kind:object");
|
|
2029
|
+
if (props ? v2.kind !== "block" : v2.kind !== "entry") block.shape = v2.kind;
|
|
1945
2030
|
break;
|
|
1946
2031
|
case "icon":
|
|
1947
|
-
if (!
|
|
1948
|
-
break;
|
|
1949
|
-
case "preview":
|
|
1950
|
-
if (!props) cat(ctx, p, "document preview");
|
|
2032
|
+
if (!dockIconOf(v2.icon)) cat(ctx, p, "block icon");
|
|
1951
2033
|
break;
|
|
2034
|
+
case "preview": break;
|
|
1952
2035
|
case "variants":
|
|
1953
|
-
cat(ctx, p, "variants");
|
|
2036
|
+
if (!ctx.variants) cat(ctx, p, "variants");
|
|
1954
2037
|
break;
|
|
1955
2038
|
case "category":
|
|
1956
|
-
if (
|
|
2039
|
+
if (kitCategory) {
|
|
2040
|
+
if (!props) block.category = kitCategory;
|
|
2041
|
+
} else if (!props || !category || capitalize(category) !== v2.category) cat(ctx, p, "category");
|
|
1957
2042
|
break;
|
|
1958
2043
|
case "placement":
|
|
1959
|
-
|
|
2044
|
+
block.placement = v2.placement;
|
|
1960
2045
|
break;
|
|
1961
2046
|
case "initialValue":
|
|
1962
2047
|
cat(ctx, p, "seeded instance");
|
|
@@ -1977,6 +2062,7 @@ function fromTypeSchema(v2, target) {
|
|
|
1977
2062
|
};
|
|
1978
2063
|
if (v2.description !== void 0) component.description = v2.description;
|
|
1979
2064
|
if (category) component.category = category;
|
|
2065
|
+
if (nonEmpty(block)) component.v2 = { ...block };
|
|
1980
2066
|
const icon = v2.icon === void 0 ? void 0 : dockIconOf(v2.icon);
|
|
1981
2067
|
if (icon) component.icon = icon;
|
|
1982
2068
|
if (v2.preview !== void 0) {
|
|
@@ -1997,7 +2083,35 @@ function fromTypeSchema(v2, target) {
|
|
|
1997
2083
|
fields: nodes.map(emitField)
|
|
1998
2084
|
};
|
|
1999
2085
|
if (v2.description !== void 0) model.description = v2.description;
|
|
2000
|
-
|
|
2086
|
+
const modelIcon = v2.icon === void 0 ? void 0 : dockIconOf(v2.icon);
|
|
2087
|
+
if (modelIcon) model.icon = modelIcon;
|
|
2088
|
+
model.kind = block.shape === "block" && model.fields.every(blockRenders) ? "block" : "model";
|
|
2089
|
+
if (ctx.variants) {
|
|
2090
|
+
const variants = v2.variants;
|
|
2091
|
+
model.fields.unshift({
|
|
2092
|
+
key: BLOCK_VARIANT_KEY,
|
|
2093
|
+
label: "Variant",
|
|
2094
|
+
type: "select",
|
|
2095
|
+
required: false,
|
|
2096
|
+
options: variants.map((v) => ({
|
|
2097
|
+
label: v.name,
|
|
2098
|
+
value: v.id
|
|
2099
|
+
}))
|
|
2100
|
+
});
|
|
2101
|
+
model.v2 = {
|
|
2102
|
+
...block,
|
|
2103
|
+
variants: Object.fromEntries(variants.map((v) => [v.id, v.description !== void 0 ? { description: v.description } : {}]))
|
|
2104
|
+
};
|
|
2105
|
+
} else if (nonEmpty(block)) model.v2 = { ...block };
|
|
2106
|
+
if (v2.preview !== void 0) {
|
|
2107
|
+
const preview = componentPreviewToProd(v2.preview, new Set(model.fields.map((x) => x.key)), v2.fields, "/preview", ctx);
|
|
2108
|
+
if (Object.keys(preview).length) model.listPreview = preview;
|
|
2109
|
+
}
|
|
2110
|
+
if (ctx.derivedSets) {
|
|
2111
|
+
const declared = fieldsets.filter((x) => x.kind !== "tab").length;
|
|
2112
|
+
ctx.derivedSets.forEach((_, i) => cat(ctx, `/fieldsets/${declared + i}`, "fieldset (derived)"));
|
|
2113
|
+
fieldsets.push(...ctx.derivedSets);
|
|
2114
|
+
}
|
|
2001
2115
|
if (fieldsets.length) model.fieldsets = fieldsets;
|
|
2002
2116
|
return {
|
|
2003
2117
|
schema: model,
|
|
@@ -2021,7 +2135,7 @@ function fieldsetsFor(v2, ctx, out) {
|
|
|
2021
2135
|
lose(ctx, p, why);
|
|
2022
2136
|
};
|
|
2023
2137
|
if (ctx.tabs.has(g.name) || names.has(folded)) return drop("group name collision");
|
|
2024
|
-
if (out.length >=
|
|
2138
|
+
if (out.length >= TAB_MAX$1) return drop("groups>3");
|
|
2025
2139
|
names.add(folded);
|
|
2026
2140
|
const tab = {
|
|
2027
2141
|
id: g.name,
|
|
@@ -2066,7 +2180,7 @@ function fieldsetsFor(v2, ctx, out) {
|
|
|
2066
2180
|
const v = fs[k];
|
|
2067
2181
|
if (v === void 0 || k === "name" || k === "title") continue;
|
|
2068
2182
|
if (k === "description") {
|
|
2069
|
-
if (v.length <=
|
|
2183
|
+
if (v.length <= FIELDSET_DESCRIPTION_MAX) set.description = v;
|
|
2070
2184
|
else lose(ctx, `${p}/${k}`, "help>limit");
|
|
2071
2185
|
} else if (k === "collapsed" || k === "collapsible" || k === "columns" || k === "layout") set[k] = v;
|
|
2072
2186
|
else lose(ctx, `${p}/${k}`, "unsupported key");
|
|
@@ -2095,7 +2209,7 @@ function propTabsFor(v2, ctx) {
|
|
|
2095
2209
|
const label = g.title.slice(0, 40).trim();
|
|
2096
2210
|
const folded = label.toLowerCase();
|
|
2097
2211
|
if (kept.some((k) => k.g.name === g.name) || labels.has(folded)) return drop("group name collision");
|
|
2098
|
-
if (kept.length >=
|
|
2212
|
+
if (kept.length >= PROP_TAB_MAX || g.name.length < 1 || g.name.length > 40) return drop("prop tab limit");
|
|
2099
2213
|
if (!label) return drop("group title");
|
|
2100
2214
|
labels.add(folded);
|
|
2101
2215
|
const tab = {
|
|
@@ -2198,7 +2312,7 @@ function propSetsFor(v2, ctx) {
|
|
|
2198
2312
|
firstSeen.push(f.fieldset);
|
|
2199
2313
|
if (!named.has(f.fieldset)) undeclared.push(f.fieldset);
|
|
2200
2314
|
}
|
|
2201
|
-
if (lv >=
|
|
2315
|
+
if (lv >= MAX_FIELD_DEPTH) continue;
|
|
2202
2316
|
const kids = previewKids(f);
|
|
2203
2317
|
if (kids) visit(kids, lv + 1);
|
|
2204
2318
|
}
|
|
@@ -2381,9 +2495,12 @@ function previewFromProd(pv, children) {
|
|
|
2381
2495
|
function showIfToCondition(s, siblings, at, ctx) {
|
|
2382
2496
|
const conds = [];
|
|
2383
2497
|
for (const r of s.rules) {
|
|
2384
|
-
const c = showIfRuleToCondition(r, siblings);
|
|
2498
|
+
const c = showIfRuleToCondition(r, r.scope ? [] : siblings);
|
|
2385
2499
|
if (!c) return void ctx.onLoss(at, "condition", `V2 conditions have no "${r.op}" with this value; the field always shows.`);
|
|
2386
|
-
conds.push(
|
|
2500
|
+
conds.push(r.scope ? {
|
|
2501
|
+
...c,
|
|
2502
|
+
scope: r.scope
|
|
2503
|
+
} : c);
|
|
2387
2504
|
}
|
|
2388
2505
|
if (!conds.length) return void 0;
|
|
2389
2506
|
const [head, ...also] = conds;
|
|
@@ -2497,6 +2614,7 @@ function readToV2(n, at, siblings, ctx, top, lane) {
|
|
|
2497
2614
|
if (n.unique !== void 0) val.unique = n.unique;
|
|
2498
2615
|
if (n.recommendedMax !== void 0) val.recommendedMax = n.recommendedMax;
|
|
2499
2616
|
if (n.advanced !== void 0) f.advanced = n.advanced;
|
|
2617
|
+
if (n.ai !== void 0) f.ai = n.ai;
|
|
2500
2618
|
if (n.openMode !== void 0) f.openMode = n.openMode;
|
|
2501
2619
|
if (n.readOnly === true) f.readOnly = true;
|
|
2502
2620
|
if (n.archived === true) f.archived = true;
|
|
@@ -2536,7 +2654,7 @@ function readToV2(n, at, siblings, ctx, top, lane) {
|
|
|
2536
2654
|
} else loss("fieldsetId", "fieldset", `No fieldset "${n.fieldsetId}" exists on this model; the membership is dropped.`);
|
|
2537
2655
|
}
|
|
2538
2656
|
if (lane === "props" && n.ui.group) f.fieldset = n.ui.group.id;
|
|
2539
|
-
if (lane === "props" && n.ui.tab) f.group = n.ui.tab.id;
|
|
2657
|
+
if ((lane === "props" || !top) && n.ui.tab) f.group = n.ui.tab.id;
|
|
2540
2658
|
for (const k of [
|
|
2541
2659
|
"target",
|
|
2542
2660
|
"stale",
|
|
@@ -2560,8 +2678,21 @@ function readToV2(n, at, siblings, ctx, top, lane) {
|
|
|
2560
2678
|
]);
|
|
2561
2679
|
const use = (...k) => k.forEach((x) => used.add(x));
|
|
2562
2680
|
const useUi = (...k) => k.forEach((x) => usedUi.add(x));
|
|
2681
|
+
if (!top && lane === "fields") useUi("tab");
|
|
2563
2682
|
if (lane === "props") useUi("group");
|
|
2564
2683
|
if (lane === "props") useUi("tab");
|
|
2684
|
+
if (RICH_TYPES.has(n.type) && cfg.references !== void 0) {
|
|
2685
|
+
use("references");
|
|
2686
|
+
const { kept, named } = richRefs(cfg.references);
|
|
2687
|
+
if (named) loss("config/references", "richtext references", FEATURES["richtext references"].reason);
|
|
2688
|
+
if (kept) f.references = kept;
|
|
2689
|
+
}
|
|
2690
|
+
if (RICH_TYPES.has(n.type) && cfg.features !== void 0) {
|
|
2691
|
+
use("features");
|
|
2692
|
+
const { kept, named } = richFeatures(cfg.features);
|
|
2693
|
+
if (named) loss("config/features", "richtext features", FEATURES["richtext features"].reason);
|
|
2694
|
+
if (kept.length < ALL_RICH_FEATURES.length) f.features = kept;
|
|
2695
|
+
}
|
|
2565
2696
|
if ([
|
|
2566
2697
|
"text",
|
|
2567
2698
|
"longtext",
|
|
@@ -2770,6 +2901,7 @@ function readToV2(n, at, siblings, ctx, top, lane) {
|
|
|
2770
2901
|
};
|
|
2771
2902
|
if (chrome?.icon) item.icon = tablerIconOf(chrome.icon);
|
|
2772
2903
|
if (chrome?.preview) item.preview = previewFromProd(chrome.preview, kids);
|
|
2904
|
+
if (chrome?.openMode) item.openMode = chrome.openMode;
|
|
2773
2905
|
return item;
|
|
2774
2906
|
});
|
|
2775
2907
|
const missing = slugs.filter((s) => !ctx.blockModels.has(s));
|
|
@@ -2927,14 +3059,27 @@ function toTypeSchema(model, opts = {}) {
|
|
|
2927
3059
|
if (s.icon !== void 0) ctx.onLoss(`/fieldsets/${i}/icon`, "fieldset icon", "V2 sections have no icon.");
|
|
2928
3060
|
fieldsets.push(fs);
|
|
2929
3061
|
});
|
|
2930
|
-
const
|
|
3062
|
+
const variantField = model.v2?.variants ? model.fields.find((f) => f.key === BLOCK_VARIANT_KEY && f.type === "select") : void 0;
|
|
3063
|
+
const nodes = model.fields.filter((f) => f !== variantField).map(readField);
|
|
2931
3064
|
const out = {
|
|
2932
3065
|
name: camel(model.slug),
|
|
2933
3066
|
title: model.name,
|
|
2934
|
-
kind: model.kind === "block" ? "block" : "entry",
|
|
3067
|
+
kind: model.kind === "block" ? "block" : model.v2?.shape ?? "entry",
|
|
2935
3068
|
fields: nodes.map((n, i) => readToV2(n, `/fields/${i}`, nodes, ctx, true, "fields"))
|
|
2936
3069
|
};
|
|
3070
|
+
if (model.v2?.placement) out.placement = model.v2.placement;
|
|
3071
|
+
if (variantField) {
|
|
3072
|
+
const meta = model.v2.variants;
|
|
3073
|
+
out.variants = (variantField.options ?? []).map((o) => ({
|
|
3074
|
+
id: o.value,
|
|
3075
|
+
name: o.label,
|
|
3076
|
+
...meta[o.value]?.description !== void 0 ? { description: meta[o.value].description } : {}
|
|
3077
|
+
}));
|
|
3078
|
+
}
|
|
3079
|
+
if (model.listPreview) out.preview = previewFromProd(model.listPreview, nodes);
|
|
3080
|
+
if (model.v2?.category) out.category = model.v2.category;
|
|
2937
3081
|
if (model.description !== void 0) out.description = model.description;
|
|
3082
|
+
if (model.icon) out.icon = tablerIconOf(model.icon);
|
|
2938
3083
|
if (fieldsets.length) out.fieldsets = fieldsets;
|
|
2939
3084
|
if (groups.length) out.groups = groups;
|
|
2940
3085
|
return out;
|
|
@@ -3003,18 +3148,72 @@ function propsToTypeSchema(component, opts = {}) {
|
|
|
3003
3148
|
const out = {
|
|
3004
3149
|
name: camel(component.slug),
|
|
3005
3150
|
title: component.name,
|
|
3006
|
-
kind: "block",
|
|
3151
|
+
kind: component.v2?.shape ?? "block",
|
|
3007
3152
|
fields: nodes.map((n, i) => readToV2(n, `/fields/${i}`, nodes, ctx, true, "props"))
|
|
3008
3153
|
};
|
|
3154
|
+
if (component.v2?.placement) out.placement = component.v2.placement;
|
|
3009
3155
|
if (component.description !== void 0 && component.description !== null) out.description = component.description;
|
|
3010
|
-
if (component.category !== void 0 && component.category !== "custom") out.category = capitalize(component.category);
|
|
3156
|
+
if (component.category !== void 0 && component.category !== "custom") out.category = KIT_CATEGORIES.includes(component.category) ? component.category : capitalize(component.category);
|
|
3011
3157
|
if (component.icon) out.icon = tablerIconOf(component.icon);
|
|
3012
3158
|
if (component.preview) out.preview = previewFromProd(component.preview, nodes);
|
|
3013
3159
|
if (fieldsets.length) out.fieldsets = fieldsets;
|
|
3014
3160
|
if (groups.length) out.groups = groups;
|
|
3015
3161
|
return out;
|
|
3016
3162
|
}
|
|
3163
|
+
/** A V2 variant id a member slug can carry, so the read takes it back verbatim (the component slug rule). */
|
|
3164
|
+
var VARIANT_ID_RE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
3165
|
+
function variantFamilyFromTypeSchema(v2) {
|
|
3166
|
+
const base = fromTypeSchema(v2, "props");
|
|
3167
|
+
const variants = v2.variants ?? [];
|
|
3168
|
+
if (!variants.length || !variants.every((v) => VARIANT_ID_RE.test(v.id))) return {
|
|
3169
|
+
members: [base.schema],
|
|
3170
|
+
group: null,
|
|
3171
|
+
lossy: base.lossy,
|
|
3172
|
+
catalog: base.catalog
|
|
3173
|
+
};
|
|
3174
|
+
const slug = base.schema.slug;
|
|
3175
|
+
return {
|
|
3176
|
+
members: variants.map((v) => ({
|
|
3177
|
+
...base.schema,
|
|
3178
|
+
name: v.name,
|
|
3179
|
+
slug: `${slug}-${v.id}`,
|
|
3180
|
+
sectionType: v2.title
|
|
3181
|
+
})),
|
|
3182
|
+
group: {
|
|
3183
|
+
name: v2.title,
|
|
3184
|
+
slug,
|
|
3185
|
+
variants: variants.map((v) => ({
|
|
3186
|
+
member: `${slug}-${v.id}`,
|
|
3187
|
+
...v.description !== void 0 ? { description: v.description } : {}
|
|
3188
|
+
}))
|
|
3189
|
+
},
|
|
3190
|
+
lossy: base.lossy,
|
|
3191
|
+
catalog: base.catalog.filter((c) => c.feature !== "variants")
|
|
3192
|
+
};
|
|
3193
|
+
}
|
|
3194
|
+
/** The group's `v2` (component_variant_groups.v2, variantGroupV2Schema) once the members exist: `idOf` maps a member slug to its id. */
|
|
3195
|
+
function variantGroupV2(group, idOf) {
|
|
3196
|
+
return { variants: group.variants.map((v) => ({
|
|
3197
|
+
componentId: idOf(v.member),
|
|
3198
|
+
...v.description !== void 0 ? { description: v.description } : {}
|
|
3199
|
+
})) };
|
|
3200
|
+
}
|
|
3201
|
+
/**
|
|
3202
|
+
* A family read back as one V2 block: the first member's props, the family's name and title, and its variants from the
|
|
3203
|
+
* group's members in `v2.variants` order (the id after the group slug, the member's name, the meta's description).
|
|
3204
|
+
*/
|
|
3205
|
+
function variantFamilyToTypeSchema(members, group, opts = {}) {
|
|
3206
|
+
const out = propsToTypeSchema(members[0], opts);
|
|
3207
|
+
out.name = camel(group.slug);
|
|
3208
|
+
if (members[0].sectionType) out.title = members[0].sectionType;
|
|
3209
|
+
out.variants = members.map((m, i) => ({
|
|
3210
|
+
id: m.slug.slice(group.slug.length + 1),
|
|
3211
|
+
name: m.name,
|
|
3212
|
+
...group.variants[i]?.description !== void 0 ? { description: group.variants[i].description } : {}
|
|
3213
|
+
}));
|
|
3214
|
+
return out;
|
|
3215
|
+
}
|
|
3017
3216
|
//#endregion
|
|
3018
|
-
export { CATEGORY_TO_PROD, SHOPIFY_REF_LOCK, fromTypeSchema, leafValuePlan, planFromProd, planToProd, propsToTypeSchema, schemaSlugOf, toTypeSchema };
|
|
3217
|
+
export { CATEGORY_TO_PROD, SHOPIFY_REF_LOCK, fromTypeSchema, leafValuePlan, planFromProd, planToProd, propsToTypeSchema, schemaSlugOf, toTypeSchema, variantFamilyFromTypeSchema, variantFamilyToTypeSchema, variantGroupV2 };
|
|
3019
3218
|
|
|
3020
3219
|
//# sourceMappingURL=schema.js.map
|