@bettercms-ai/kit 1.0.0 → 2.0.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/README.md +33 -0
- package/dist/adapters/dock-values.d.ts +28 -0
- package/dist/adapters/dock-values.js +41 -0
- package/dist/adapters/dock-values.js.map +1 -0
- package/{adapters → dist/adapters}/icons.js +2 -2
- package/dist/adapters/icons.js.map +1 -0
- package/{adapters → dist/adapters}/lossy.d.ts +90 -31
- package/dist/adapters/lossy.js +414 -0
- package/dist/adapters/lossy.js.map +1 -0
- package/{adapters → dist/adapters}/prod-types.d.ts +82 -4
- package/{adapters → dist/adapters}/prod-types.js +71 -3
- package/dist/adapters/prod-types.js.map +1 -0
- package/{adapters → dist/adapters}/schema.d.ts +40 -1
- package/{adapters → dist/adapters}/schema.js +996 -179
- package/dist/adapters/schema.js.map +1 -0
- package/{adapters → dist/adapters}/values.d.ts +26 -5
- package/{adapters → dist/adapters}/values.js +87 -17
- package/dist/adapters/values.js.map +1 -0
- package/dist/brand/logo.js +96 -0
- package/dist/brand/logo.js.map +1 -0
- package/{context.d.ts → dist/context.d.ts} +92 -2
- package/{context.js → dist/context.js} +5 -2
- package/dist/context.js.map +1 -0
- package/{controls → dist/controls}/button.d.ts +19 -5
- package/{controls → dist/controls}/button.js +125 -54
- package/dist/controls/button.js.map +1 -0
- package/{controls → dist/controls}/c1.js +1 -1
- package/dist/controls/c1.js.map +1 -0
- package/{controls → dist/controls}/c2.js +1 -1
- package/dist/controls/c2.js.map +1 -0
- package/{controls → dist/controls}/choice.d.ts +7 -2
- package/{controls → dist/controls}/choice.js +71 -18
- package/dist/controls/choice.js.map +1 -0
- package/{controls → dist/controls}/code-register.js +1 -1
- package/dist/controls/code-register.js.map +1 -0
- package/{controls → dist/controls}/code.js +10 -9
- package/dist/controls/code.js.map +1 -0
- package/{controls → dist/controls}/color.js +8 -8
- package/dist/controls/color.js.map +1 -0
- package/{controls → dist/controls}/component-services.d.ts +42 -0
- package/dist/controls/component-services.js +7 -0
- package/dist/controls/component-services.js.map +1 -0
- package/{controls → dist/controls}/date-register.js +1 -1
- package/dist/controls/date-register.js.map +1 -0
- package/{controls → dist/controls}/date-zone.js +8 -2
- package/dist/controls/date-zone.js.map +1 -0
- package/{controls → dist/controls}/date.js +32 -24
- package/dist/controls/date.js.map +1 -0
- package/{controls → dist/controls}/form-picker-register.js +1 -1
- package/dist/controls/form-picker-register.js.map +1 -0
- package/{controls → dist/controls}/form-picker.js +11 -9
- package/dist/controls/form-picker.js.map +1 -0
- package/{controls → dist/controls}/icon-register.js +1 -1
- package/dist/controls/icon-register.js.map +1 -0
- package/{controls → dist/controls}/icon.d.ts +4 -2
- package/{controls → dist/controls}/icon.js +32 -27
- package/dist/controls/icon.js.map +1 -0
- package/{controls → dist/controls}/index.d.ts +1 -1
- package/{controls → dist/controls}/index.js +4 -3
- package/dist/controls/index.js.map +1 -0
- package/{controls → dist/controls}/json-register.js +1 -1
- package/dist/controls/json-register.js.map +1 -0
- package/{controls → dist/controls}/json.js +13 -3
- package/dist/controls/json.js.map +1 -0
- package/{controls → dist/controls}/link.js +6 -6
- package/dist/controls/link.js.map +1 -0
- package/{controls → dist/controls}/location-register.js +1 -1
- package/dist/controls/location-register.js.map +1 -0
- package/{controls → dist/controls}/location.js +64 -40
- package/dist/controls/location.js.map +1 -0
- package/{controls → dist/controls}/media-register.js +1 -1
- package/dist/controls/media-register.js.map +1 -0
- package/{controls → dist/controls}/media-services.d.ts +6 -0
- package/dist/controls/media-services.js +0 -0
- package/{controls → dist/controls}/media.d.ts +35 -4
- package/{controls → dist/controls}/media.js +491 -171
- package/dist/controls/media.js.map +1 -0
- package/{controls → dist/controls}/number.js +10 -9
- package/dist/controls/number.js.map +1 -0
- package/{controls → dist/controls}/reference-register.js +1 -1
- package/dist/controls/reference-register.js.map +1 -0
- package/{controls → dist/controls}/reference-services.d.ts +4 -0
- package/dist/controls/reference-services.js +0 -0
- package/{controls → dist/controls}/reference.d.ts +1 -1
- package/{controls → dist/controls}/reference.js +93 -77
- package/dist/controls/reference.js.map +1 -0
- package/dist/controls/rich-text/blocks.d.ts +49 -0
- package/{controls → dist/controls}/rich-text/blocks.js +471 -144
- package/dist/controls/rich-text/blocks.js.map +1 -0
- package/{controls → dist/controls}/rich-text/catalog.d.ts +4 -1
- package/{controls → dist/controls}/rich-text/catalog.js +75 -65
- package/dist/controls/rich-text/catalog.js.map +1 -0
- package/{controls → dist/controls}/rich-text/codec.d.ts +9 -1
- package/{controls → dist/controls}/rich-text/codec.js +3 -1
- package/dist/controls/rich-text/codec.js.map +1 -0
- package/{controls → dist/controls}/rich-text/component-card.d.ts +1 -1
- package/{controls → dist/controls}/rich-text/component-card.js +417 -99
- package/dist/controls/rich-text/component-card.js.map +1 -0
- package/dist/controls/rich-text/component-panel.d.ts +47 -0
- package/dist/controls/rich-text/component-panel.js +141 -0
- package/dist/controls/rich-text/component-panel.js.map +1 -0
- package/{controls → dist/controls}/rich-text/control.d.ts +1 -2
- package/{controls → dist/controls}/rich-text/control.js +84 -42
- package/dist/controls/rich-text/control.js.map +1 -0
- package/{controls → dist/controls}/rich-text/dom.d.ts +52 -9
- package/{controls → dist/controls}/rich-text/dom.js +379 -50
- package/dist/controls/rich-text/dom.js.map +1 -0
- package/{controls → dist/controls}/rich-text/editor.d.ts +7 -0
- package/{controls → dist/controls}/rich-text/editor.js +148 -48
- package/dist/controls/rich-text/editor.js.map +1 -0
- package/{controls → dist/controls}/rich-text/floating.d.ts +6 -1
- package/{controls → dist/controls}/rich-text/floating.js +35 -18
- package/dist/controls/rich-text/floating.js.map +1 -0
- package/{controls → dist/controls}/rich-text/index.js +1 -1
- package/dist/controls/rich-text/index.js.map +1 -0
- package/dist/controls/rich-text/link-form.js +147 -0
- package/dist/controls/rich-text/link-form.js.map +1 -0
- package/{controls → dist/controls}/rich-text/markdown.js +4 -2
- package/dist/controls/rich-text/markdown.js.map +1 -0
- package/{controls → dist/controls}/rich-text/ops.js +17 -15
- package/dist/controls/rich-text/ops.js.map +1 -0
- package/dist/controls/rich-text/plain.d.ts +17 -0
- package/dist/controls/rich-text/plain.js +44 -0
- package/dist/controls/rich-text/plain.js.map +1 -0
- package/{controls → dist/controls}/rich-text/toolbar.d.ts +6 -2
- package/{controls → dist/controls}/rich-text/toolbar.js +12 -7
- package/dist/controls/rich-text/toolbar.js.map +1 -0
- package/{controls → dist/controls}/scale.js +5 -5
- package/dist/controls/scale.js.map +1 -0
- package/{controls → dist/controls}/slot-register.js +1 -1
- package/dist/controls/slot-register.js.map +1 -0
- package/{controls → dist/controls}/slot-services.d.ts +25 -0
- package/dist/controls/slot-services.js +155 -0
- package/dist/controls/slot-services.js.map +1 -0
- package/{controls → dist/controls}/slot.js +42 -24
- package/dist/controls/slot.js.map +1 -0
- package/{controls → dist/controls}/table/index.js +1 -1
- package/dist/controls/table/index.js.map +1 -0
- package/{controls → dist/controls}/table/prod.js +3 -3
- package/dist/controls/table/prod.js.map +1 -0
- package/{controls → dist/controls}/table/refs.js +13 -2
- package/dist/controls/table/refs.js.map +1 -0
- package/{controls → dist/controls}/table/stored.js +1 -1
- package/dist/controls/table/stored.js.map +1 -0
- package/{controls → dist/controls}/table/table-editor.js +51 -48
- package/dist/controls/table/table-editor.js.map +1 -0
- package/{controls → dist/controls}/table/table-link.js +3 -3
- package/dist/controls/table/table-link.js.map +1 -0
- package/{controls → dist/controls}/table/table.js +3 -3
- package/dist/controls/table/table.js.map +1 -0
- package/{controls → dist/controls}/text.d.ts +2 -2
- package/{controls → dist/controls}/text.js +78 -43
- package/dist/controls/text.js.map +1 -0
- package/dist/controls/unknown-value.d.ts +17 -0
- package/dist/controls/unknown-value.js +66 -0
- package/dist/controls/unknown-value.js.map +1 -0
- package/dist/core/core.d.ts +63 -0
- package/dist/core/core.js +171 -0
- package/dist/core/core.js.map +1 -0
- package/dist/core/facets.d.ts +347 -0
- package/dist/core/facets.js +334 -0
- package/dist/core/facets.js.map +1 -0
- package/dist/core/index.d.ts +3 -0
- package/dist/core/index.js +3 -0
- package/{engine → dist/engine}/array.js +34 -21
- package/dist/engine/array.js.map +1 -0
- package/{engine → dist/engine}/bits.js +1 -1
- package/dist/engine/bits.js.map +1 -0
- package/{engine → dist/engine}/breadcrumb.d.ts +3 -3
- package/{engine → dist/engine}/breadcrumb.js +12 -36
- package/dist/engine/breadcrumb.js.map +1 -0
- package/{engine → dist/engine}/expand.d.ts +2 -4
- package/{engine → dist/engine}/expand.js +5 -22
- package/dist/engine/expand.js.map +1 -0
- package/{engine → dist/engine}/field-list.js +1 -1
- package/dist/engine/field-list.js.map +1 -0
- package/{engine → dist/engine}/field-shell.js +249 -121
- package/dist/engine/field-shell.js.map +1 -0
- package/{engine → dist/engine}/frame.d.ts +3 -1
- package/{engine → dist/engine}/frame.js +16 -14
- package/dist/engine/frame.js.map +1 -0
- package/{engine → dist/engine}/group-summary.d.ts +2 -1
- package/{engine → dist/engine}/group-summary.js +7 -3
- package/dist/engine/group-summary.js.map +1 -0
- package/{engine → dist/engine}/grouping.d.ts +19 -5
- package/{engine → dist/engine}/grouping.js +193 -21
- package/dist/engine/grouping.js.map +1 -0
- package/{engine → dist/engine}/item-list.d.ts +11 -1
- package/{engine → dist/engine}/item-list.js +35 -13
- package/dist/engine/item-list.js.map +1 -0
- package/{engine → dist/engine}/kit-field.js +45 -10
- package/dist/engine/kit-field.js.map +1 -0
- package/{engine → dist/engine}/schema-form.d.ts +27 -2
- package/{engine → dist/engine}/schema-form.js +182 -40
- package/dist/engine/schema-form.js.map +1 -0
- package/{engine → dist/engine}/slot.js +5 -15
- package/dist/engine/slot.js.map +1 -0
- package/dist/index.js +47 -0
- package/dist/index.js.map +1 -0
- package/{kit.css → dist/kit.css} +19 -0
- package/{lib → dist/lib}/cn.js +7 -4
- package/dist/lib/cn.js.map +1 -0
- package/{lib → dist/lib}/columns.js +4 -1
- package/dist/lib/columns.js.map +1 -0
- package/{lib → dist/lib}/frames.js +2 -2
- package/dist/lib/frames.js.map +1 -0
- package/dist/lib/icon-image.d.ts +10 -0
- package/dist/lib/icon-image.js +8 -0
- package/dist/lib/icon-image.js.map +1 -0
- package/{lib → dist/lib}/icons.js +4 -3
- package/dist/lib/icons.js.map +1 -0
- package/dist/lib/input-modality.d.ts +11 -0
- package/dist/lib/input-modality.js +47 -0
- package/dist/lib/input-modality.js.map +1 -0
- package/dist/lib/key-event.d.ts +11 -0
- package/dist/lib/key-event.js +16 -0
- package/dist/lib/key-event.js.map +1 -0
- package/{lib → dist/lib}/path.js +4 -2
- package/dist/lib/path.js.map +1 -0
- package/{lib → dist/lib}/schema.d.ts +34 -3
- package/{lib → dist/lib}/schema.js +110 -13
- package/dist/lib/schema.js.map +1 -0
- package/{lib → dist/lib}/utils.js +1 -1
- package/dist/lib/utils.js.map +1 -0
- package/{lib → dist/lib}/validate.d.ts +11 -1
- package/{lib → dist/lib}/validate.js +85 -11
- package/dist/lib/validate.js.map +1 -0
- package/dist/library/analysis.d.ts +23 -0
- package/dist/library/analysis.js +160 -0
- package/dist/library/analysis.js.map +1 -0
- package/dist/library/catalog.d.ts +57 -0
- package/dist/library/catalog.js +307 -0
- package/dist/library/catalog.js.map +1 -0
- package/dist/library/coreNotes.d.ts +8 -0
- package/dist/library/coreNotes.js +111 -0
- package/dist/library/coreNotes.js.map +1 -0
- package/dist/library/coverage.d.ts +40 -0
- package/dist/library/coverage.js +59 -0
- package/dist/library/coverage.js.map +1 -0
- package/dist/library/entries/advanced.entries.d.ts +2 -0
- package/dist/library/entries/advanced.entries.js +6579 -0
- package/dist/library/entries/advanced.entries.js.map +1 -0
- package/dist/library/entries/commerce.entries.d.ts +2 -0
- package/dist/library/entries/commerce.entries.js +4140 -0
- package/dist/library/entries/commerce.entries.js.map +1 -0
- package/dist/library/entries/company.entries.d.ts +2 -0
- package/dist/library/entries/company.entries.js +2731 -0
- package/dist/library/entries/company.entries.js.map +1 -0
- package/dist/library/entries/conversion.entries.d.ts +2 -0
- package/dist/library/entries/conversion.entries.js +3707 -0
- package/dist/library/entries/conversion.entries.js.map +1 -0
- package/dist/library/entries/data.entries.d.ts +7 -0
- package/dist/library/entries/data.entries.js +4613 -0
- package/dist/library/entries/data.entries.js.map +1 -0
- package/dist/library/entries/events.entries.d.ts +2 -0
- package/dist/library/entries/events.entries.js +3428 -0
- package/dist/library/entries/events.entries.js.map +1 -0
- package/dist/library/entries/features.entries.d.ts +2 -0
- package/dist/library/entries/features.entries.js +3157 -0
- package/dist/library/entries/features.entries.js.map +1 -0
- package/dist/library/entries/heroes.entries.d.ts +2 -0
- package/dist/library/entries/heroes.entries.js +3401 -0
- package/dist/library/entries/heroes.entries.js.map +1 -0
- package/dist/library/entries/index.d.ts +3 -0
- package/dist/library/entries/index.js +35 -0
- package/dist/library/entries/index.js.map +1 -0
- package/dist/library/entries/listings.entries.d.ts +2 -0
- package/dist/library/entries/listings.entries.js +2976 -0
- package/dist/library/entries/listings.entries.js.map +1 -0
- package/dist/library/entries/longform.entries.d.ts +2 -0
- package/dist/library/entries/longform.entries.js +4227 -0
- package/dist/library/entries/longform.entries.js.map +1 -0
- package/dist/library/entries/media.entries.d.ts +2 -0
- package/dist/library/entries/media.entries.js +2781 -0
- package/dist/library/entries/media.entries.js.map +1 -0
- package/dist/library/entries/navigation.entries.d.ts +2 -0
- package/dist/library/entries/navigation.entries.js +4011 -0
- package/dist/library/entries/navigation.entries.js.map +1 -0
- package/dist/library/entries/pricing.entries.d.ts +2 -0
- package/dist/library/entries/pricing.entries.js +2383 -0
- package/dist/library/entries/pricing.entries.js.map +1 -0
- package/dist/library/entries/social-proof.entries.d.ts +2 -0
- package/dist/library/entries/social-proof.entries.js +2297 -0
- package/dist/library/entries/social-proof.entries.js.map +1 -0
- package/dist/library/examples/bento.d.ts +92 -0
- package/dist/library/examples/bento.js +201 -0
- package/dist/library/examples/bento.js.map +1 -0
- package/dist/library/examples/blocks.d.ts +14 -0
- package/dist/library/examples/blocks.js +313 -0
- package/dist/library/examples/blocks.js.map +1 -0
- package/dist/library/examples/faq.d.ts +28 -0
- package/dist/library/examples/faq.js +230 -0
- package/dist/library/examples/faq.js.map +1 -0
- package/dist/library/examples/hero.d.ts +43 -0
- package/dist/library/examples/hero.js +222 -0
- package/dist/library/examples/hero.js.map +1 -0
- package/dist/library/examples/index.d.ts +36 -0
- package/dist/library/examples/index.js +109 -0
- package/dist/library/examples/index.js.map +1 -0
- package/dist/library/examples/journalStory.d.ts +93 -0
- package/dist/library/examples/journalStory.js +338 -0
- package/dist/library/examples/journalStory.js.map +1 -0
- package/dist/library/examples/megaMenu.d.ts +134 -0
- package/dist/library/examples/megaMenu.js +442 -0
- package/dist/library/examples/megaMenu.js.map +1 -0
- package/dist/library/examples/pricing.d.ts +103 -0
- package/dist/library/examples/pricing.js +479 -0
- package/dist/library/examples/pricing.js.map +1 -0
- package/dist/library/examples/tabs.d.ts +87 -0
- package/dist/library/examples/tabs.js +180 -0
- package/dist/library/examples/tabs.js.map +1 -0
- package/dist/library/export.d.ts +42 -0
- package/dist/library/export.js +80 -0
- package/dist/library/export.js.map +1 -0
- package/dist/library/index.d.ts +13 -0
- package/dist/library/index.js +6 -0
- package/dist/library/kit-catalog.json +1510 -0
- package/dist/library/types.d.ts +42 -0
- package/dist/library/types.js +0 -0
- package/{schema → dist/schema}/adapters.js +1 -2
- package/dist/schema/adapters.js.map +1 -0
- package/{schema → dist/schema}/help.d.ts +2 -0
- package/{schema → dist/schema}/help.js +6 -4
- package/dist/schema/help.js.map +1 -0
- package/{schema → dist/schema}/scale.js +1 -1
- package/dist/schema/scale.js.map +1 -0
- package/{schema → dist/schema}/sources.js +1 -1
- package/dist/schema/sources.js.map +1 -0
- package/{schema → dist/schema}/table.js +11 -10
- package/dist/schema/table.js.map +1 -0
- package/{schema → dist/schema}/types.d.ts +29 -1
- package/{schema → dist/schema}/types.js +1 -1
- package/dist/schema/types.js.map +1 -0
- package/dist/styles.css +2 -0
- package/dist/table/table-view.d.ts +14 -0
- package/dist/table/table-view.js +140 -0
- package/dist/table/table-view.js.map +1 -0
- package/dist/table/table.css +73 -0
- package/dist/testing/corpus.d.ts +63 -0
- package/dist/testing/corpus.js +129 -0
- package/dist/testing/corpus.js.map +1 -0
- package/dist/testing/test-form.d.ts +11 -0
- package/dist/testing/test-form.js +38 -0
- package/dist/testing/test-form.js.map +1 -0
- package/dist/theme.css +345 -0
- package/dist/theme.d.ts +22 -0
- package/dist/theme.js +43 -0
- package/dist/theme.js.map +1 -0
- package/dist/tokens.css +542 -0
- package/dist/types.js +0 -0
- package/{ui → dist/ui}/action-tray.d.ts +1 -1
- package/{ui → dist/ui}/action-tray.js +20 -19
- package/dist/ui/action-tray.js.map +1 -0
- package/dist/ui/autocomplete.d.ts +30 -0
- package/dist/ui/autocomplete.js +139 -0
- package/dist/ui/autocomplete.js.map +1 -0
- package/{ui → dist/ui}/button.d.ts +3 -3
- package/{ui → dist/ui}/button.js +6 -7
- package/dist/ui/button.js.map +1 -0
- package/{ui → dist/ui}/choice-switch.js +1 -1
- package/dist/ui/choice-switch.js.map +1 -0
- package/{ui → dist/ui}/controls.js +51 -39
- package/dist/ui/controls.js.map +1 -0
- package/{ui → dist/ui}/display.d.ts +10 -3
- package/{ui → dist/ui}/display.js +57 -46
- package/dist/ui/display.js.map +1 -0
- package/{ui → dist/ui}/expanded-editor-modal.d.ts +2 -2
- package/{ui → dist/ui}/expanded-editor-modal.js +6 -6
- package/dist/ui/expanded-editor-modal.js.map +1 -0
- package/{ui → dist/ui}/field-context.js +1 -1
- package/dist/ui/field-context.js.map +1 -0
- package/{ui → dist/ui}/floating-panel.d.ts +1 -1
- package/{ui → dist/ui}/floating-panel.js +28 -12
- package/dist/ui/floating-panel.js.map +1 -0
- package/{ui → dist/ui}/index.d.ts +4 -0
- package/dist/ui/index.js +18 -0
- package/{ui → dist/ui}/input.d.ts +1 -1
- package/{ui → dist/ui}/input.js +9 -9
- package/dist/ui/input.js.map +1 -0
- package/{ui → dist/ui}/mode-bar.js +3 -3
- package/dist/ui/mode-bar.js.map +1 -0
- package/{ui → dist/ui}/overlay.d.ts +77 -5
- package/dist/ui/overlay.js +697 -0
- package/dist/ui/overlay.js.map +1 -0
- package/{ui → dist/ui}/path-crumbs.js +37 -3
- package/dist/ui/path-crumbs.js.map +1 -0
- package/{ui → dist/ui}/presence.js +2 -2
- package/dist/ui/presence.js.map +1 -0
- package/{ui → dist/ui}/select.js +89 -87
- package/dist/ui/select.js.map +1 -0
- package/{ui → dist/ui}/shortcut-hint.js +1 -1
- package/dist/ui/shortcut-hint.js.map +1 -0
- package/dist/ui/spinner.d.ts +24 -0
- package/dist/ui/spinner.js +42 -0
- package/dist/ui/spinner.js.map +1 -0
- package/dist/ui/split-button.d.ts +32 -0
- package/dist/ui/split-button.js +60 -0
- package/dist/ui/split-button.js.map +1 -0
- package/{ui → dist/ui}/surfaces.js +1 -1
- package/dist/ui/surfaces.js.map +1 -0
- package/dist/ui/tab.d.ts +38 -0
- package/dist/ui/tab.js +87 -0
- package/dist/ui/tab.js.map +1 -0
- package/dist/ui/toast.d.ts +20 -0
- package/dist/ui/toast.js +115 -0
- package/dist/ui/toast.js.map +1 -0
- package/{ui → dist/ui}/tooltip-root.d.ts +4 -3
- package/{ui → dist/ui}/tooltip-root.js +9 -8
- package/dist/ui/tooltip-root.js.map +1 -0
- package/{ui → dist/ui}/variants.js +1 -1
- package/dist/ui/variants.js.map +1 -0
- package/package.json +77 -23
- package/adapters/icons.js.map +0 -1
- package/adapters/lossy.js +0 -233
- package/adapters/lossy.js.map +0 -1
- package/adapters/prod-types.js.map +0 -1
- package/adapters/schema.js.map +0 -1
- package/adapters/values.js.map +0 -1
- package/brand/logo.js +0 -9
- package/brand/logo.js.map +0 -1
- package/context.js.map +0 -1
- package/controls/button.js.map +0 -1
- package/controls/c1.js.map +0 -1
- package/controls/c2.js.map +0 -1
- package/controls/choice.js.map +0 -1
- package/controls/code-register.js.map +0 -1
- package/controls/code.js.map +0 -1
- package/controls/color.js.map +0 -1
- package/controls/date-register.js.map +0 -1
- package/controls/date-zone.js.map +0 -1
- package/controls/date.js.map +0 -1
- package/controls/form-picker-register.js.map +0 -1
- package/controls/form-picker.js.map +0 -1
- package/controls/icon-register.js.map +0 -1
- package/controls/icon.js.map +0 -1
- package/controls/index.js.map +0 -1
- package/controls/json-register.js.map +0 -1
- package/controls/json.js.map +0 -1
- package/controls/link.js.map +0 -1
- package/controls/location-register.js.map +0 -1
- package/controls/location.js.map +0 -1
- package/controls/media-register.js.map +0 -1
- package/controls/media.js.map +0 -1
- package/controls/number.js.map +0 -1
- package/controls/reference-register.js.map +0 -1
- package/controls/reference.js.map +0 -1
- package/controls/rich-text/blocks.d.ts +0 -28
- package/controls/rich-text/blocks.js.map +0 -1
- package/controls/rich-text/catalog.js.map +0 -1
- package/controls/rich-text/codec.js.map +0 -1
- package/controls/rich-text/component-card.js.map +0 -1
- package/controls/rich-text/control.js.map +0 -1
- package/controls/rich-text/dom.js.map +0 -1
- package/controls/rich-text/editor.js.map +0 -1
- package/controls/rich-text/floating.js.map +0 -1
- package/controls/rich-text/index.js.map +0 -1
- package/controls/rich-text/link-form.js +0 -111
- package/controls/rich-text/link-form.js.map +0 -1
- package/controls/rich-text/markdown.js.map +0 -1
- package/controls/rich-text/ops.js.map +0 -1
- package/controls/rich-text/toolbar.js.map +0 -1
- package/controls/scale.js.map +0 -1
- package/controls/slot-register.js.map +0 -1
- package/controls/slot-services.js +0 -38
- package/controls/slot-services.js.map +0 -1
- package/controls/slot.js.map +0 -1
- package/controls/table/index.js.map +0 -1
- package/controls/table/prod.js.map +0 -1
- package/controls/table/refs.js.map +0 -1
- package/controls/table/stored.js.map +0 -1
- package/controls/table/table-editor.js.map +0 -1
- package/controls/table/table-link.js.map +0 -1
- package/controls/table/table.js.map +0 -1
- package/controls/text.js.map +0 -1
- package/engine/array.js.map +0 -1
- package/engine/bits.js.map +0 -1
- package/engine/breadcrumb.js.map +0 -1
- package/engine/expand.js.map +0 -1
- package/engine/field-list.js.map +0 -1
- package/engine/field-shell.js.map +0 -1
- package/engine/frame.js.map +0 -1
- package/engine/group-summary.js.map +0 -1
- package/engine/grouping.js.map +0 -1
- package/engine/item-list.js.map +0 -1
- package/engine/kit-field.js.map +0 -1
- package/engine/schema-form.js.map +0 -1
- package/engine/slot.js.map +0 -1
- package/index.js +0 -55
- package/index.js.map +0 -1
- package/lib/cn.js.map +0 -1
- package/lib/columns.js.map +0 -1
- package/lib/frames.js.map +0 -1
- package/lib/icons.js.map +0 -1
- package/lib/path.js.map +0 -1
- package/lib/schema.js.map +0 -1
- package/lib/utils.js.map +0 -1
- package/lib/validate.js.map +0 -1
- package/schema/adapters.js.map +0 -1
- package/schema/help.js.map +0 -1
- package/schema/scale.js.map +0 -1
- package/schema/sources.js.map +0 -1
- package/schema/table.js.map +0 -1
- package/schema/types.js.map +0 -1
- package/ui/action-tray.js.map +0 -1
- package/ui/button.js.map +0 -1
- package/ui/choice-switch.js.map +0 -1
- package/ui/controls.js.map +0 -1
- package/ui/display.js.map +0 -1
- package/ui/expanded-editor-modal.js.map +0 -1
- package/ui/field-context.js.map +0 -1
- package/ui/floating-panel.js.map +0 -1
- package/ui/index.js +0 -13
- package/ui/input.js.map +0 -1
- package/ui/mode-bar.js.map +0 -1
- package/ui/overlay.js +0 -378
- package/ui/overlay.js.map +0 -1
- package/ui/path-crumbs.js.map +0 -1
- package/ui/presence.js.map +0 -1
- package/ui/select.js.map +0 -1
- package/ui/shortcut-hint.js.map +0 -1
- package/ui/surfaces.js.map +0 -1
- package/ui/tooltip-root.js.map +0 -1
- package/ui/variants.js.map +0 -1
- /package/{_virtual → dist/_virtual}/_rolldown/runtime.js +0 -0
- /package/{adapters → dist/adapters}/icons.d.ts +0 -0
- /package/{brand → dist/brand}/logo.d.ts +0 -0
- /package/{controls → dist/controls}/c1.d.ts +0 -0
- /package/{controls → dist/controls}/c2.d.ts +0 -0
- /package/{controls → dist/controls}/code-register.d.ts +0 -0
- /package/{controls → dist/controls}/code.d.ts +0 -0
- /package/{controls → dist/controls}/color.d.ts +0 -0
- /package/{controls → dist/controls}/date-register.d.ts +0 -0
- /package/{controls → dist/controls}/date-zone.d.ts +0 -0
- /package/{controls → dist/controls}/date.d.ts +0 -0
- /package/{controls → dist/controls}/form-picker-register.d.ts +0 -0
- /package/{controls → dist/controls}/form-picker.d.ts +0 -0
- /package/{controls → dist/controls}/icon-register.d.ts +0 -0
- /package/{controls → dist/controls}/json-register.d.ts +0 -0
- /package/{controls → dist/controls}/json.d.ts +0 -0
- /package/{controls → dist/controls}/link.d.ts +0 -0
- /package/{controls → dist/controls}/location-register.d.ts +0 -0
- /package/{controls → dist/controls}/location.d.ts +0 -0
- /package/{controls → dist/controls}/media-register.d.ts +0 -0
- /package/{controls → dist/controls}/number.d.ts +0 -0
- /package/{controls → dist/controls}/reference-register.d.ts +0 -0
- /package/{controls → dist/controls}/rich-text/index.d.ts +0 -0
- /package/{controls → dist/controls}/rich-text/link-form.d.ts +0 -0
- /package/{controls → dist/controls}/rich-text/markdown.d.ts +0 -0
- /package/{controls → dist/controls}/rich-text/ops.d.ts +0 -0
- /package/{controls → dist/controls}/scale.d.ts +0 -0
- /package/{controls → dist/controls}/slot-register.d.ts +0 -0
- /package/{controls → dist/controls}/slot.d.ts +0 -0
- /package/{controls → dist/controls}/table/index.d.ts +0 -0
- /package/{controls → dist/controls}/table/prod.d.ts +0 -0
- /package/{controls → dist/controls}/table/refs.d.ts +0 -0
- /package/{controls → dist/controls}/table/stored.d.ts +0 -0
- /package/{controls → dist/controls}/table/table-editor.d.ts +0 -0
- /package/{controls → dist/controls}/table/table-link.d.ts +0 -0
- /package/{controls → dist/controls}/table/table.d.ts +0 -0
- /package/{engine → dist/engine}/array.d.ts +0 -0
- /package/{engine → dist/engine}/bits.d.ts +0 -0
- /package/{engine → dist/engine}/field-list.d.ts +0 -0
- /package/{engine → dist/engine}/field-shell.d.ts +0 -0
- /package/{engine → dist/engine}/kit-field.d.ts +0 -0
- /package/{engine → dist/engine}/slot.d.ts +0 -0
- /package/{index.d.ts → dist/index.d.ts} +0 -0
- /package/{lib → dist/lib}/cn.d.ts +0 -0
- /package/{lib → dist/lib}/columns.d.ts +0 -0
- /package/{lib → dist/lib}/frames.d.ts +0 -0
- /package/{lib → dist/lib}/icons.d.ts +0 -0
- /package/{lib → dist/lib}/path.d.ts +0 -0
- /package/{lib → dist/lib}/utils.d.ts +0 -0
- /package/{schema → dist/schema}/adapters.d.ts +0 -0
- /package/{schema → dist/schema}/scale.d.ts +0 -0
- /package/{schema → dist/schema}/sources.d.ts +0 -0
- /package/{schema → dist/schema}/table.d.ts +0 -0
- /package/{types.d.ts → dist/types.d.ts} +0 -0
- /package/{ui → dist/ui}/choice-switch.d.ts +0 -0
- /package/{ui → dist/ui}/controls.d.ts +0 -0
- /package/{ui → dist/ui}/field-context.d.ts +0 -0
- /package/{ui → dist/ui}/mode-bar.d.ts +0 -0
- /package/{ui → dist/ui}/path-crumbs.d.ts +0 -0
- /package/{ui → dist/ui}/presence.d.ts +0 -0
- /package/{ui → dist/ui}/select.d.ts +0 -0
- /package/{ui → dist/ui}/shortcut-hint.d.ts +0 -0
- /package/{ui → dist/ui}/surfaces.d.ts +0 -0
- /package/{ui → dist/ui}/variants.d.ts +0 -0
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { CATALOG, FEATURES, isHostConfigKey } from "./lossy.js";
|
|
1
2
|
import { CONTROL_TYPES, HELP_MORE_MAX, ITEM_NAME_RE, UI_CONTROLS } from "./prod-types.js";
|
|
2
3
|
import { dockIconOf, tablerIconOf } from "./icons.js";
|
|
3
|
-
import {
|
|
4
|
+
import { slotChildrenFromStored, slotChildrenToStored } from "../controls/slot-services.js";
|
|
4
5
|
import { isDataTableProp, tableConfigFromOptions, tableOptionsFromConfig } from "../controls/table/prod.js";
|
|
5
|
-
import { buttonFromProd, buttonToProd, datetimeFromProd, datetimeToProd, imageFromProd, imageToProd, linkFromProd, linkToProd, listFromProd, listToProd, ratingFromProd, ratingToProd, referenceFromProd, referenceToProd, scaleFromProd, scaleToProd, videoFromProd, videoToProd, zoneListFromProd, zoneListToProd } from "./values.js";
|
|
6
|
-
//#region src/
|
|
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
|
+
//#region src/adapters/schema.ts
|
|
7
8
|
var isObj = (v) => !!v && typeof v === "object" && !Array.isArray(v);
|
|
8
9
|
function deepEqual(a, b) {
|
|
9
10
|
if (a === b) return true;
|
|
@@ -14,6 +15,8 @@ function deepEqual(a, b) {
|
|
|
14
15
|
var singular = (t) => t.endsWith("ies") ? `${t.slice(0, -3)}y` : t.endsWith("s") && !t.endsWith("ss") ? t.slice(0, -1) : t;
|
|
15
16
|
var kebab = (s) => s.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "") || "schema";
|
|
16
17
|
var camel = (s) => s.replace(/-([a-z0-9])/g, (_, c) => c.toUpperCase());
|
|
18
|
+
/** The slug a V2 schema name is stored under (a component's, when the host seeds a /kit block): `textBlock` → `text-block`. */
|
|
19
|
+
var schemaSlugOf = kebab;
|
|
17
20
|
var capitalize = (s) => s.charAt(0).toUpperCase() + s.slice(1);
|
|
18
21
|
var ZONE_NAMES = new Set(typeof Intl.supportedValuesOf === "function" ? [...Intl.supportedValuesOf("timeZone"), "UTC"] : ["UTC"]);
|
|
19
22
|
/** An IANA zone name (isTimeZoneName): ICU's canonical list, or a current name Intl itself accepts (Asia/Kolkata). */
|
|
@@ -94,7 +97,7 @@ var PROP_TYPE = {
|
|
|
94
97
|
code: "code"
|
|
95
98
|
};
|
|
96
99
|
/** Field types whose `config` the backend parses strictly (unknown keys stripped or refused). */
|
|
97
|
-
var STRICT_CONFIG = new Set([
|
|
100
|
+
var STRICT_CONFIG = /* @__PURE__ */ new Set([
|
|
98
101
|
"array",
|
|
99
102
|
"reference",
|
|
100
103
|
"multi-reference",
|
|
@@ -107,7 +110,9 @@ var STRICT_CONFIG = new Set([
|
|
|
107
110
|
"tags",
|
|
108
111
|
"rating",
|
|
109
112
|
"code",
|
|
110
|
-
"video"
|
|
113
|
+
"video",
|
|
114
|
+
"table",
|
|
115
|
+
"slot"
|
|
111
116
|
]);
|
|
112
117
|
/** V2 list item types → prod `config.itemType` (ARRAY_ITEM_TYPES); a V2 `text` item reads back as `string`. */
|
|
113
118
|
var PRIM_ITEM = {
|
|
@@ -125,6 +130,23 @@ var ENTRY_TARGET = (t) => ![
|
|
|
125
130
|
"shopify",
|
|
126
131
|
"collection"
|
|
127
132
|
].includes(t);
|
|
133
|
+
/** The non-entry targets a prop reference stores in config.targets (backend reference-target-config.ts REF_TARGET_KINDS). */
|
|
134
|
+
var REF_TARGET_KINDS = [
|
|
135
|
+
"page",
|
|
136
|
+
"form",
|
|
137
|
+
"collection"
|
|
138
|
+
];
|
|
139
|
+
/**
|
|
140
|
+
* A prop reference whose only target is Shopify (backend reference-target-config.ts UNSUPPORTED_TARGETS refuses it by
|
|
141
|
+
* name) is stored as locked text holding the id (a list of them: a list of text), so the value stays the plain gid
|
|
142
|
+
* string V2 holds. This lock reason is the marker the read side turns back into V2's reference (allowed deviation
|
|
143
|
+
* "shopify reference").
|
|
144
|
+
*/
|
|
145
|
+
var SHOPIFY_REF_LOCK = "A Shopify product id. No Shopify integration backs a reference in BetterCMS yet, so the id is kept as it is.";
|
|
146
|
+
var shopifyOnly = (r) => !!r?.to?.length && r.to.every((t) => t === "shopify");
|
|
147
|
+
/** backend REFERENCE_FILTER_MAX; parameters ($x) and the parent document (^) are refused there (reference_filter_invalid). */
|
|
148
|
+
var REFERENCE_FILTER_MAX = 500;
|
|
149
|
+
var filterKept = (f) => typeof f === "string" && f.trim() !== "" && f.length <= REFERENCE_FILTER_MAX && !/[$^]/.test(f);
|
|
128
150
|
/** The old rating: a number with ui.control "rating" and these bounds read back as no `numeric` (read side only). */
|
|
129
151
|
var RATING_CONFIG = {
|
|
130
152
|
min: 0,
|
|
@@ -132,6 +154,12 @@ var RATING_CONFIG = {
|
|
|
132
154
|
step: .5
|
|
133
155
|
};
|
|
134
156
|
/**
|
|
157
|
+
* A V2 rating sets no step and holds any number on its scale (a 4.8 average). Prod's unset step is 1, which refuses
|
|
158
|
+
* 4.8 (rating_value_invalid), so a rating with no step is written with step 0.1 (≤ RATING_MAX_STOPS stops on a 1–10
|
|
159
|
+
* scale) and that step reads back as none; a prod rating with no step reads back as its real step, 1.
|
|
160
|
+
*/
|
|
161
|
+
var V2_RATING_STEP = .1;
|
|
162
|
+
/**
|
|
135
163
|
* V2 block-picker category (KitCategory, and the core examples' own) → the nearest prod ComponentCategory. A category
|
|
136
164
|
* with no row has no prod twin; the server defaults the component to "custom".
|
|
137
165
|
*/
|
|
@@ -155,7 +183,7 @@ var CATEGORY_TO_PROD = {
|
|
|
155
183
|
Layout: "section"
|
|
156
184
|
};
|
|
157
185
|
/** The field types a kind:'block' model may hold (backend block-model-mapping.ts FIELD_PRIMITIVE). */
|
|
158
|
-
var BLOCK_FIELD_TYPES = new Set([
|
|
186
|
+
var BLOCK_FIELD_TYPES = /* @__PURE__ */ new Set([
|
|
159
187
|
"text",
|
|
160
188
|
"longtext",
|
|
161
189
|
"richtext",
|
|
@@ -172,15 +200,20 @@ var BLOCK_FIELD_TYPES = new Set([
|
|
|
172
200
|
"datetime",
|
|
173
201
|
"boolean"
|
|
174
202
|
]);
|
|
175
|
-
/** A prop's config.minItems / maxItems cap (SLOT_ITEMS_CAP, componentPropDefSchema). */
|
|
203
|
+
/** A slot prop's config.minItems / maxItems cap (SLOT_ITEMS_CAP, componentPropDefSchema). */
|
|
176
204
|
var SLOT_ITEMS_CAP = 50;
|
|
205
|
+
/** A table prop's rows and an array prop's items: their config.minItems / maxItems cap (LIST_ITEMS_CAP). */
|
|
206
|
+
var LIST_ITEMS_CAP = 500;
|
|
207
|
+
/** backend slotAllowIssues: a slot's config.allow holds 1–50 block names of 1–64 characters, no repeats. */
|
|
208
|
+
var SLOT_ALLOW_MAX = 50;
|
|
209
|
+
var SLOT_ALLOW_NAME_MAX = 64;
|
|
177
210
|
/** Backend dock-vocabulary.ts SLIDER_MAX_STOPS: a slider's (max − min) / step. */
|
|
178
211
|
var SLIDER_MAX_STOPS = 1e3;
|
|
179
212
|
/**
|
|
180
213
|
* The field types prod's unique flag accepts (uniqueFlagRules): a comparable scalar (UNIQUE_FIELD_TYPES, no two entries
|
|
181
214
|
* share it; a reference only to one model) or a list (UNIQUE_ITEMS_FIELD_TYPES, no item repeats).
|
|
182
215
|
*/
|
|
183
|
-
var UNIQUE_TYPES = new Set([
|
|
216
|
+
var UNIQUE_TYPES = /* @__PURE__ */ new Set([
|
|
184
217
|
"text",
|
|
185
218
|
"longtext",
|
|
186
219
|
"slug",
|
|
@@ -197,14 +230,14 @@ var UNIQUE_TYPES = new Set([
|
|
|
197
230
|
"multi-reference"
|
|
198
231
|
]);
|
|
199
232
|
/** Prop types whose value is a list (UNIQUE_LIST_PROP_TYPES), and the sub-field types a table row compares (UNIQUE_ROW_PROP_TYPES). */
|
|
200
|
-
var UNIQUE_LIST_PROPS = new Set([
|
|
233
|
+
var UNIQUE_LIST_PROPS = /* @__PURE__ */ new Set([
|
|
201
234
|
"multiselect",
|
|
202
235
|
"tags",
|
|
203
236
|
"multi-reference",
|
|
204
237
|
"table",
|
|
205
238
|
"array"
|
|
206
239
|
]);
|
|
207
|
-
var UNIQUE_ROW_PROPS = new Set([
|
|
240
|
+
var UNIQUE_ROW_PROPS = /* @__PURE__ */ new Set([
|
|
208
241
|
"text",
|
|
209
242
|
"url",
|
|
210
243
|
"slug",
|
|
@@ -215,19 +248,19 @@ var UNIQUE_ROW_PROPS = new Set([
|
|
|
215
248
|
"date"
|
|
216
249
|
]);
|
|
217
250
|
/** Types measured by minLength / maxLength (fields: LENGTH_FIELD_TYPES; props: LENGTH_TWIN), and those that take a pattern. */
|
|
218
|
-
var LENGTH_FIELDS = new Set([
|
|
251
|
+
var LENGTH_FIELDS = /* @__PURE__ */ new Set([
|
|
219
252
|
"text",
|
|
220
253
|
"longtext",
|
|
221
254
|
"richtext",
|
|
222
255
|
"document"
|
|
223
256
|
]);
|
|
224
|
-
var LENGTH_PROPS = new Set([
|
|
257
|
+
var LENGTH_PROPS = /* @__PURE__ */ new Set([
|
|
225
258
|
"text",
|
|
226
259
|
"url",
|
|
227
260
|
"longtext",
|
|
228
261
|
"richtext"
|
|
229
262
|
]);
|
|
230
|
-
var PATTERN_TYPES = new Set([
|
|
263
|
+
var PATTERN_TYPES = /* @__PURE__ */ new Set([
|
|
231
264
|
"text",
|
|
232
265
|
"longtext",
|
|
233
266
|
"url"
|
|
@@ -236,7 +269,7 @@ var PATTERN_TYPES = new Set([
|
|
|
236
269
|
* Leaf types whose value is an object a dotted preview path may read into (previewPathProblem OBJECT_VALUE_TYPES), and the
|
|
237
270
|
* keys an image or video value holds (LEAF_VALUE_KEYS). V2 reads `image.alt`; prod stores the key as `altText`.
|
|
238
271
|
*/
|
|
239
|
-
var OBJECT_VALUE_TYPES = new Set([
|
|
272
|
+
var OBJECT_VALUE_TYPES = /* @__PURE__ */ new Set([
|
|
240
273
|
"image",
|
|
241
274
|
"link",
|
|
242
275
|
"button",
|
|
@@ -268,6 +301,8 @@ var LEAF_VALUE_KEYS = {
|
|
|
268
301
|
]
|
|
269
302
|
};
|
|
270
303
|
var IMAGE_PATH_KEY = { alt: "altText" };
|
|
304
|
+
/** The keys of a data table's value a preview path may end on (previewPathProblem `<table>.caption` / `.notes`). */
|
|
305
|
+
var TABLE_PATH_KEYS = ["caption", "notes"];
|
|
271
306
|
var lose = (ctx, path, feature) => ctx.lossy.push({
|
|
272
307
|
path,
|
|
273
308
|
feature,
|
|
@@ -279,7 +314,7 @@ var cat = (ctx, path, feature) => ctx.catalog.push({
|
|
|
279
314
|
reason: CATALOG[feature]
|
|
280
315
|
});
|
|
281
316
|
/** Keys every type keeps, including a field degraded to json. */
|
|
282
|
-
var COMMON_KEYS = new Set([
|
|
317
|
+
var COMMON_KEYS = /* @__PURE__ */ new Set([
|
|
283
318
|
"name",
|
|
284
319
|
"title",
|
|
285
320
|
"type",
|
|
@@ -296,14 +331,53 @@ var COMMON_KEYS = new Set([
|
|
|
296
331
|
"advanced",
|
|
297
332
|
"localized",
|
|
298
333
|
"ai",
|
|
299
|
-
"placeholder"
|
|
334
|
+
"placeholder",
|
|
335
|
+
"archived"
|
|
336
|
+
]);
|
|
337
|
+
/** Types a slot setting may not be (backend slotSettingsHardening, and a model slot's SLOT_SETTINGS_NESTING: leaf fields only). */
|
|
338
|
+
var SETTING_NESTING_TYPES = /* @__PURE__ */ new Set([
|
|
339
|
+
"object",
|
|
340
|
+
"group",
|
|
341
|
+
"array",
|
|
342
|
+
"table",
|
|
343
|
+
"slot",
|
|
344
|
+
"form",
|
|
345
|
+
"modular"
|
|
300
346
|
]);
|
|
301
|
-
|
|
347
|
+
/** backend slotSettingsHardening: at most this many per-child settings. */
|
|
348
|
+
var SLOT_SETTINGS_MAX = 20;
|
|
349
|
+
/** backend ITEM_TYPE_NAME (what a row's `_type` holds), and an item type label's cap. */
|
|
350
|
+
var ITEM_TYPE_NAME = /^[a-zA-Z][a-zA-Z0-9_-]{0,63}$/;
|
|
351
|
+
var ITEM_TYPE_LABEL_MAX = 120;
|
|
352
|
+
function shapeOf(f, lv, ctx, top, nest) {
|
|
353
|
+
const shape = shapeOfField(f, lv, ctx, top);
|
|
354
|
+
if (nest === "setting" && SETTING_NESTING_TYPES.has(shape.type)) return {
|
|
355
|
+
kind: "json",
|
|
356
|
+
type: "json",
|
|
357
|
+
feature: "slotSettings"
|
|
358
|
+
};
|
|
359
|
+
return shape;
|
|
360
|
+
}
|
|
361
|
+
/** backend content.ts keyRuleProblem: keys a resolver would misread (KEY_RESERVED), and a key's format (KEY_FORMAT). */
|
|
362
|
+
var MODEL_RESERVED_KEYS = /* @__PURE__ */ new Set([
|
|
363
|
+
"derived",
|
|
364
|
+
"layout",
|
|
365
|
+
"page"
|
|
366
|
+
]);
|
|
367
|
+
/** The key a model field is stored under: a reserved or malformed V2 name, renamed. */
|
|
368
|
+
function modelKeyOf(name) {
|
|
369
|
+
let k = name.replace(/^_+/, "").replace(/[^A-Za-z0-9_-]/g, "");
|
|
370
|
+
if (!/^[A-Za-z]/.test(k)) k = `f${k}`;
|
|
371
|
+
return MODEL_RESERVED_KEYS.has(k) ? `${k}Field` : k;
|
|
372
|
+
}
|
|
373
|
+
/** A slot's V2 allow list as the backend keeps it: 1–50 distinct block names of 1–64 characters (slotAllowIssues). */
|
|
374
|
+
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
|
+
function shapeOfField(f, lv, ctx, top) {
|
|
302
376
|
const props = ctx.lane === "props";
|
|
303
377
|
const deep = lv >= 10;
|
|
304
378
|
const of = Array.isArray(f.of) ? f.of : void 0;
|
|
305
|
-
/** a prop reference
|
|
306
|
-
const noEntry = (r) => props && !(r?.to ?? []).some(ENTRY_TARGET);
|
|
379
|
+
/** a prop reference names a content model or a page / form / collection target (refTargetNamed): with none it is stored as json */
|
|
380
|
+
const noEntry = (r) => props && !(r?.to ?? []).some((t) => ENTRY_TARGET(t) || REF_TARGET_KINDS.includes(t));
|
|
307
381
|
switch (f.type) {
|
|
308
382
|
case "object": return deep ? {
|
|
309
383
|
kind: "json",
|
|
@@ -314,11 +388,22 @@ function shapeOf(f, lv, ctx, top) {
|
|
|
314
388
|
type: "object"
|
|
315
389
|
};
|
|
316
390
|
case "array": {
|
|
317
|
-
if (of && of.length > 1 &&
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
391
|
+
if (of && of.length > 1 && of.every((i) => i.type === "object")) {
|
|
392
|
+
if (!props) return {
|
|
393
|
+
kind: "modular",
|
|
394
|
+
type: "modular",
|
|
395
|
+
items: of
|
|
396
|
+
};
|
|
397
|
+
return deep ? {
|
|
398
|
+
kind: "json",
|
|
399
|
+
type: "json",
|
|
400
|
+
feature: "depth>10"
|
|
401
|
+
} : {
|
|
402
|
+
kind: "types",
|
|
403
|
+
type: "table",
|
|
404
|
+
items: of
|
|
405
|
+
};
|
|
406
|
+
}
|
|
322
407
|
if (!of || of.length !== 1) return {
|
|
323
408
|
kind: "json",
|
|
324
409
|
type: "json",
|
|
@@ -334,6 +419,13 @@ function shapeOf(f, lv, ctx, top) {
|
|
|
334
419
|
type: props ? "table" : "array",
|
|
335
420
|
item
|
|
336
421
|
};
|
|
422
|
+
if (item.type === "reference" && shopifyOnly(item.reference)) return {
|
|
423
|
+
kind: "itemType",
|
|
424
|
+
type: "array",
|
|
425
|
+
item,
|
|
426
|
+
itemType: "text",
|
|
427
|
+
shopify: true
|
|
428
|
+
};
|
|
337
429
|
if (item.type === "reference") return noEntry(item.reference) ? {
|
|
338
430
|
kind: "json",
|
|
339
431
|
type: "json",
|
|
@@ -356,24 +448,30 @@ function shapeOf(f, lv, ctx, top) {
|
|
|
356
448
|
feature: "type:primitive-array"
|
|
357
449
|
};
|
|
358
450
|
}
|
|
359
|
-
case "slot":
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
451
|
+
case "slot":
|
|
452
|
+
if (!props && !slotAllowOk(f.of?.allow)) return {
|
|
453
|
+
kind: "json",
|
|
454
|
+
type: "json",
|
|
455
|
+
feature: "type:slot"
|
|
456
|
+
};
|
|
457
|
+
return {
|
|
458
|
+
kind: "slot",
|
|
459
|
+
type: "slot"
|
|
460
|
+
};
|
|
461
|
+
case "table": return {
|
|
365
462
|
kind: "leaf",
|
|
366
463
|
type: "table"
|
|
367
|
-
} : {
|
|
368
|
-
kind: "json",
|
|
369
|
-
type: "json",
|
|
370
|
-
feature: "type:table"
|
|
371
464
|
};
|
|
372
465
|
case "reference":
|
|
373
466
|
if (props && top && f.reference?.to?.length === 1 && f.reference.to[0] === "form" && !f.reference.filter) return {
|
|
374
467
|
kind: "leaf",
|
|
375
468
|
type: "form"
|
|
376
469
|
};
|
|
470
|
+
if (shopifyOnly(f.reference)) return {
|
|
471
|
+
kind: "leaf",
|
|
472
|
+
type: "text",
|
|
473
|
+
shopify: true
|
|
474
|
+
};
|
|
377
475
|
return noEntry(f.reference) ? {
|
|
378
476
|
kind: "json",
|
|
379
477
|
type: "json",
|
|
@@ -400,9 +498,9 @@ var trunc = (ctx, at, s, max, feature) => {
|
|
|
400
498
|
lose(ctx, at, feature);
|
|
401
499
|
return s.slice(0, max);
|
|
402
500
|
};
|
|
403
|
-
function convertField(f, at, lv, ctx, siblings, top, inTable = false) {
|
|
501
|
+
function convertField(f, at, lv, ctx, siblings, top, inTable = false, inItem = false, inSetting = false) {
|
|
404
502
|
const props = ctx.lane === "props";
|
|
405
|
-
const shape = shapeOf(f, lv, ctx, top);
|
|
503
|
+
const shape = shapeOf(f, lv, ctx, top, inTable ? "rows" : inItem ? "item" : inSetting ? "setting" : void 0);
|
|
406
504
|
const node = {
|
|
407
505
|
key: f.name,
|
|
408
506
|
label: f.title,
|
|
@@ -414,17 +512,28 @@ function convertField(f, at, lv, ctx, siblings, top, inTable = false) {
|
|
|
414
512
|
if (twins) {
|
|
415
513
|
node.key = `${f.name}_${twins + 1}`;
|
|
416
514
|
lose(ctx, `${at}/name`, "duplicate name");
|
|
515
|
+
} else if (!props && modelKeyOf(f.name) !== f.name) {
|
|
516
|
+
node.key = modelKeyOf(f.name);
|
|
517
|
+
lose(ctx, `${at}/name`, "reserved name");
|
|
417
518
|
}
|
|
418
|
-
const nesting = shape.kind === "object" || shape.kind === "zones";
|
|
419
|
-
/** a list of items (objects, block models, scalars or entries): ui.itemLabel names one item */
|
|
420
|
-
const listy = shape.kind === "zones" || shape.kind === "modular" || shape.kind === "itemType" || shape.kind === "refs";
|
|
519
|
+
const nesting = shape.kind === "object" || shape.kind === "zones" || shape.kind === "types";
|
|
520
|
+
/** a list of items (objects, block models, item types, scalars or entries): ui.itemLabel names one item */
|
|
521
|
+
const listy = shape.kind === "zones" || shape.kind === "modular" || shape.kind === "types" || shape.kind === "itemType" || shape.kind === "refs";
|
|
421
522
|
const looseConfig = props || !STRICT_CONFIG.has(shape.type);
|
|
422
523
|
if (shape.kind === "json") lose(ctx, `${at}/type`, shape.feature);
|
|
524
|
+
const shopify = (shape.kind === "leaf" || shape.kind === "itemType") && shape.shopify === true;
|
|
525
|
+
if (shopify) {
|
|
526
|
+
if (f.readOnly !== true) lose(ctx, `${at}/readOnly`, "shopify reference");
|
|
527
|
+
node.readOnly = true;
|
|
528
|
+
node.lockReason = SHOPIFY_REF_LOCK;
|
|
529
|
+
}
|
|
423
530
|
if (!props && f.type === "url") node.config.inputType = "url";
|
|
424
531
|
if (shape.type === "datetime" && !props) node.config.includeTime = true;
|
|
425
532
|
if (shape.kind === "leaf" && shape.type === "table") node.config.mode = "data";
|
|
533
|
+
if (shape.kind === "types") node.config.mode = "types";
|
|
534
|
+
if (shape.kind === "slot" && props) node.config.multiple = true;
|
|
426
535
|
if (listy) {
|
|
427
|
-
const label = f.itemNoun !== void 0 ? capitalize(f.itemNoun) : shape.kind === "zones" && shape.item.title !== conventionItem(f.name, f.title).title ? shape.item.title : void 0;
|
|
536
|
+
const label = f.itemNoun !== void 0 ? capitalize(f.itemNoun) : props && shape.kind === "zones" && shape.item.title !== conventionItem(f.name, f.title).title ? shape.item.title : void 0;
|
|
428
537
|
if (label !== void 0 && label.length <= 24) node.ui.itemLabel = label;
|
|
429
538
|
}
|
|
430
539
|
const devLock = f.access?.edit === "schema.manage" && !!f.lockReason;
|
|
@@ -435,6 +544,11 @@ function convertField(f, at, lv, ctx, siblings, top, inTable = false) {
|
|
|
435
544
|
lose(ctx, p, shape.feature);
|
|
436
545
|
continue;
|
|
437
546
|
}
|
|
547
|
+
if (shopify && (k === "reference" || k === "readOnly")) continue;
|
|
548
|
+
if (shopify && (k === "access" || k === "lockReason")) {
|
|
549
|
+
lose(ctx, p, "shopify reference");
|
|
550
|
+
continue;
|
|
551
|
+
}
|
|
438
552
|
switch (k) {
|
|
439
553
|
case "name":
|
|
440
554
|
case "title":
|
|
@@ -451,7 +565,7 @@ function convertField(f, at, lv, ctx, siblings, top, inTable = false) {
|
|
|
451
565
|
else node.ui.placeholder = trunc(ctx, p, f.placeholder, 120, "help>limit");
|
|
452
566
|
break;
|
|
453
567
|
case "initialValue":
|
|
454
|
-
if (props && (shape.type === "reference" || shape.type === "multi-reference")) cat(ctx, p, "seeded instance");
|
|
568
|
+
if (props && (shape.type === "reference" || shape.type === "multi-reference" || shape.kind === "slot")) cat(ctx, p, "seeded instance");
|
|
455
569
|
else node.defaultValue = defaultToProd(f, shape, f.initialValue, p, ctx, lv, top);
|
|
456
570
|
break;
|
|
457
571
|
case "validation":
|
|
@@ -471,7 +585,7 @@ function convertField(f, at, lv, ctx, siblings, top, inTable = false) {
|
|
|
471
585
|
ofToProd(f, shape, node, p, lv, ctx);
|
|
472
586
|
break;
|
|
473
587
|
case "openMode":
|
|
474
|
-
if (nesting) node.openMode = f.openMode;
|
|
588
|
+
if (nesting || props && shape.type === "code") node.openMode = f.openMode;
|
|
475
589
|
else lose(ctx, p, "openMode");
|
|
476
590
|
break;
|
|
477
591
|
case "preview":
|
|
@@ -509,6 +623,9 @@ function convertField(f, at, lv, ctx, siblings, top, inTable = false) {
|
|
|
509
623
|
case "localized":
|
|
510
624
|
node.localized = f.localized;
|
|
511
625
|
break;
|
|
626
|
+
case "archived":
|
|
627
|
+
if (f.archived) node.archived = true;
|
|
628
|
+
break;
|
|
512
629
|
case "advanced":
|
|
513
630
|
node.advanced = f.advanced;
|
|
514
631
|
break;
|
|
@@ -527,7 +644,7 @@ function convertField(f, at, lv, ctx, siblings, top, inTable = false) {
|
|
|
527
644
|
else lose(ctx, p, "unsupported key");
|
|
528
645
|
break;
|
|
529
646
|
case "icon": {
|
|
530
|
-
const dock = shape.kind === "object" || shape.kind === "modular" ? dockIconOf(f.icon) : void 0;
|
|
647
|
+
const dock = shape.kind === "object" || shape.kind === "modular" || shape.kind === "types" ? dockIconOf(f.icon) : void 0;
|
|
531
648
|
if (dock) node.ui.icon = dock;
|
|
532
649
|
else lose(ctx, p, "icon");
|
|
533
650
|
break;
|
|
@@ -543,13 +660,14 @@ function convertField(f, at, lv, ctx, siblings, top, inTable = false) {
|
|
|
543
660
|
break;
|
|
544
661
|
}
|
|
545
662
|
case "slotSettings":
|
|
546
|
-
|
|
663
|
+
if (shape.kind === "slot") slotSettingsToProd(f.slotSettings, node, p, lv, ctx);
|
|
664
|
+
else lose(ctx, p, "slotSettings");
|
|
547
665
|
break;
|
|
548
666
|
case "itemNoun":
|
|
549
667
|
if (!listy || node.ui.itemLabel?.toLowerCase() !== f.itemNoun) lose(ctx, p, "itemNoun");
|
|
550
668
|
break;
|
|
551
669
|
case "arrayLayout":
|
|
552
|
-
if (shape.kind === "zones" || shape.kind === "modular") node.ui.layout = f.arrayLayout;
|
|
670
|
+
if (shape.kind === "zones" || shape.kind === "modular" || shape.kind === "types") node.ui.layout = f.arrayLayout;
|
|
553
671
|
else if ((shape.kind === "itemType" || shape.kind === "refs") && f.arrayLayout === "grid") node.ui.layout = "gallery";
|
|
554
672
|
else lose(ctx, p, "layout");
|
|
555
673
|
break;
|
|
@@ -557,6 +675,14 @@ function convertField(f, at, lv, ctx, siblings, top, inTable = false) {
|
|
|
557
675
|
if (shape.type === "link" || shape.type === "image" || shape.type === "button") node.ui.valueShape = f.valueShape;
|
|
558
676
|
else lose(ctx, p, "valueShape");
|
|
559
677
|
break;
|
|
678
|
+
case "linkHref":
|
|
679
|
+
if (typeof f.linkHref === "string" && f.linkHref) node.config.linkHref = f.linkHref;
|
|
680
|
+
else lose(ctx, p, "unsupported key");
|
|
681
|
+
break;
|
|
682
|
+
case "svgOnly":
|
|
683
|
+
if (shape.type === "image" && f.svgOnly === true) node.config.media = "icon";
|
|
684
|
+
else if (f.svgOnly !== false) lose(ctx, p, "unsupported key");
|
|
685
|
+
break;
|
|
560
686
|
case "timezone":
|
|
561
687
|
if (shape.type === "date" || shape.type === "datetime") {
|
|
562
688
|
const tz = f.timezone;
|
|
@@ -580,8 +706,14 @@ function convertField(f, at, lv, ctx, siblings, top, inTable = false) {
|
|
|
580
706
|
default: lose(ctx, p, "unsupported key");
|
|
581
707
|
}
|
|
582
708
|
}
|
|
709
|
+
if (props && f.description === void 0) node.helpText = null;
|
|
583
710
|
if (f.itemNoun === void 0 && shape.kind === "zones" && node.ui.itemLabel !== void 0) cat(ctx, `${at}/itemNoun`, "itemNoun (derived)");
|
|
584
711
|
placeInSet(f, node, at, ctx, top, siblings);
|
|
712
|
+
if (f.type === "rating" && node.type === "rating" && f.numeric?.step === void 0) {
|
|
713
|
+
const lo = typeof node.config.min === "number" ? node.config.min : 0;
|
|
714
|
+
const stops = ((typeof node.config.max === "number" ? node.config.max : 5) - lo) / V2_RATING_STEP;
|
|
715
|
+
if (Math.abs(stops - Math.round(stops)) < 1e-9 && Math.round(stops) <= 100) node.config.step = V2_RATING_STEP;
|
|
716
|
+
}
|
|
585
717
|
if (node.ui.control === "slider" && !sliderOk(node.config)) {
|
|
586
718
|
delete node.ui.control;
|
|
587
719
|
lose(ctx, `${at}/layout`, "layout");
|
|
@@ -606,7 +738,16 @@ function sliderOk({ min, max, step }) {
|
|
|
606
738
|
/** Where a field sits: its tab (fields lane) or prop group (props lane). */
|
|
607
739
|
function placeInSet(f, node, at, ctx, top, siblings) {
|
|
608
740
|
if (ctx.lane === "props") {
|
|
609
|
-
if (
|
|
741
|
+
if (!top) {
|
|
742
|
+
if (f.group !== void 0) {
|
|
743
|
+
if (ctx.keptTabs.has(f.group)) node.ui.tab = { id: f.group };
|
|
744
|
+
else lose(ctx, `${at}/group`, "group (nested)");
|
|
745
|
+
}
|
|
746
|
+
} else {
|
|
747
|
+
const t = ctx.propTabs.get(f);
|
|
748
|
+
if (t?.loss) lose(ctx, `${at}/group`, t.loss);
|
|
749
|
+
if (t?.tab) node.ui.tab = ctx.definedTabs.has(t.tab.id) ? { id: t.tab.id } : (ctx.definedTabs.add(t.tab.id), t.tab);
|
|
750
|
+
}
|
|
610
751
|
if (f.fieldset === void 0) return;
|
|
611
752
|
const set = ctx.propSets.get(f.fieldset);
|
|
612
753
|
if (!set) return lose(ctx, `${at}/fieldset`, "fieldset collision");
|
|
@@ -663,7 +804,7 @@ function defaultToProd(f, shape, v, at, ctx, lv, top) {
|
|
|
663
804
|
var AS_IS = { k: "as-is" };
|
|
664
805
|
/** The write side's plan, from the V2 field and the shape it is stored as. */
|
|
665
806
|
function writePlan(f, shape, lv, ctx, top) {
|
|
666
|
-
const kids = (fields) => new Map(fields.map((c) => [c.name, writePlan(c, shapeOf(c, lv + 1, ctx, false), lv + 1, ctx, false)]));
|
|
807
|
+
const kids = (fields, nest) => new Map(fields.map((c) => [c.name, writePlan(c, shapeOf(c, lv + 1, ctx, false, nest), lv + 1, ctx, false)]));
|
|
667
808
|
switch (shape.kind) {
|
|
668
809
|
case "json": return AS_IS;
|
|
669
810
|
case "itemType": return shape.itemType === "image" || shape.itemType === "link" ? {
|
|
@@ -677,8 +818,13 @@ function writePlan(f, shape, lv, ctx, top) {
|
|
|
677
818
|
case "zones": return {
|
|
678
819
|
k: "rows",
|
|
679
820
|
zoned: ctx.lane === "fields",
|
|
680
|
-
fields: kids(shape.item.fields ?? [])
|
|
821
|
+
fields: kids(shape.item.fields ?? [], ctx.lane === "props" ? "rows" : void 0)
|
|
681
822
|
};
|
|
823
|
+
case "types": return {
|
|
824
|
+
k: "types",
|
|
825
|
+
types: new Map(shape.items.map((i) => [i.name, kids(i.fields ?? [], "item")]))
|
|
826
|
+
};
|
|
827
|
+
case "slot": return ctx.lane === "fields" ? { k: "blocks" } : AS_IS;
|
|
682
828
|
case "modular": {
|
|
683
829
|
const top1 = (fields) => new Map(fields.map((c) => [c.name, writePlan(c, shapeOf(c, 1, ctx, false), 1, ctx, false)]));
|
|
684
830
|
return {
|
|
@@ -688,6 +834,7 @@ function writePlan(f, shape, lv, ctx, top) {
|
|
|
688
834
|
}
|
|
689
835
|
case "refs": return { k: "refs" };
|
|
690
836
|
case "leaf":
|
|
837
|
+
if (shape.shopify) return AS_IS;
|
|
691
838
|
if (f.type === "link" || f.type === "url") return { k: "link" };
|
|
692
839
|
if (f.type === "button" || f.type === "image") return { k: f.type };
|
|
693
840
|
if (f.type === "datetime") return {
|
|
@@ -706,7 +853,7 @@ function leafPlan(f, prodType) {
|
|
|
706
853
|
scale: {
|
|
707
854
|
min: f.numeric?.min,
|
|
708
855
|
max: f.numeric?.max,
|
|
709
|
-
step: f.numeric?.step
|
|
856
|
+
step: f.numeric?.step ?? V2_RATING_STEP
|
|
710
857
|
}
|
|
711
858
|
};
|
|
712
859
|
if (f.type === "number" && f.scale) return {
|
|
@@ -716,11 +863,12 @@ function leafPlan(f, prodType) {
|
|
|
716
863
|
return prodType === "number" ? { k: "number" } : AS_IS;
|
|
717
864
|
}
|
|
718
865
|
/**
|
|
719
|
-
* The read side's plan, from the V2 field read back (`zoned`: lists read from an array's repeatable zone
|
|
720
|
-
* lists read from a modular field, whose item fields live in their block
|
|
866
|
+
* The read side's plan, from the V2 field read back (`zoned`: lists read from an array's repeatable zone and groups
|
|
867
|
+
* read from its non-repeatable zone; `modular`: lists read from a modular field, whose item fields live in their block
|
|
868
|
+
* models and pass as stored).
|
|
721
869
|
*/
|
|
722
|
-
function readPlan(f, prodType, zoned, modular) {
|
|
723
|
-
const kids = (fields) => new Map(fields.map((c) => [c.name, readPlan(c, "", zoned, modular)]));
|
|
870
|
+
function readPlan(f, prodType, zoned, modular, types, slots, blocks) {
|
|
871
|
+
const kids = (fields) => new Map(fields.map((c) => [c.name, readPlan(c, "", zoned, modular, types, slots, blocks)]));
|
|
724
872
|
switch (f.type) {
|
|
725
873
|
case "link":
|
|
726
874
|
case "url": return { k: "link" };
|
|
@@ -731,16 +879,29 @@ function readPlan(f, prodType, zoned, modular) {
|
|
|
731
879
|
zone: fixedZone(f)
|
|
732
880
|
};
|
|
733
881
|
case "date": return { k: "date" };
|
|
734
|
-
case "reference":
|
|
882
|
+
case "reference":
|
|
883
|
+
if (shopifyOnly(f.reference)) return AS_IS;
|
|
884
|
+
return { k: prodType === "form" ? "form" : "ref" };
|
|
735
885
|
case "object": return {
|
|
736
886
|
k: "object",
|
|
887
|
+
...zoned.has(f) ? { zoned: true } : {},
|
|
737
888
|
fields: kids(f.fields ?? [])
|
|
738
889
|
};
|
|
890
|
+
case "slot":
|
|
891
|
+
if (blocks?.has(f)) return { k: "blocks" };
|
|
892
|
+
return slots?.has(f) ? {
|
|
893
|
+
k: "slot",
|
|
894
|
+
multiple: slots.get(f)
|
|
895
|
+
} : AS_IS;
|
|
739
896
|
case "array": {
|
|
740
897
|
if (modular.has(f)) return {
|
|
741
898
|
k: "modular",
|
|
742
899
|
types: new Map((Array.isArray(f.of) ? f.of : []).map((i) => [i.name, kids(i.fields ?? [])]))
|
|
743
900
|
};
|
|
901
|
+
if (types?.has(f)) return {
|
|
902
|
+
k: "types",
|
|
903
|
+
types: new Map((Array.isArray(f.of) ? f.of : []).map((i) => [i.name, kids(i.fields ?? [])]))
|
|
904
|
+
};
|
|
744
905
|
const item = Array.isArray(f.of) && f.of.length === 1 ? f.of[0] : void 0;
|
|
745
906
|
if (item?.type === "object") return {
|
|
746
907
|
k: "rows",
|
|
@@ -751,7 +912,7 @@ function readPlan(f, prodType, zoned, modular) {
|
|
|
751
912
|
k: "list",
|
|
752
913
|
item: item.type
|
|
753
914
|
};
|
|
754
|
-
return item?.type === "reference" ? { k: "refs" } : AS_IS;
|
|
915
|
+
return item?.type === "reference" && !shopifyOnly(item.reference) ? { k: "refs" } : AS_IS;
|
|
755
916
|
}
|
|
756
917
|
default: return leafPlan(f, prodType);
|
|
757
918
|
}
|
|
@@ -791,7 +952,10 @@ function planToProd(plan, v, lost, at = "") {
|
|
|
791
952
|
case "list": return take(listToProd(v, plan.item));
|
|
792
953
|
case "scale": return take(scaleToProd(v, plan.scale));
|
|
793
954
|
case "rating": return take(ratingToProd(v, plan.scale));
|
|
794
|
-
case "object":
|
|
955
|
+
case "object": {
|
|
956
|
+
const out = mapKeys(v, plan.fields, (p, x, k) => planToProd(p, x, lost, under(k)));
|
|
957
|
+
return plan.zoned && isObj(out) ? { nonRepeatable: out } : out;
|
|
958
|
+
}
|
|
795
959
|
case "rows": {
|
|
796
960
|
if (!Array.isArray(v)) return v;
|
|
797
961
|
const rows = v.map((row, i) => mapKeys(row, plan.fields, (p, x, k) => planToProd(p, x, lost, `${under(i)}/${k}`)));
|
|
@@ -809,24 +973,46 @@ function planToProd(plan, v, lost, at = "") {
|
|
|
809
973
|
data: fields ? mapKeys(rest, fields, (p, x, k) => planToProd(p, x, lost, `${under(i)}/${k}`)) : rest
|
|
810
974
|
};
|
|
811
975
|
});
|
|
976
|
+
case "blocks": return Array.isArray(v) ? v.map((c) => isObj(c) && typeof c._type === "string" ? {
|
|
977
|
+
...c,
|
|
978
|
+
_type: kebab(c._type)
|
|
979
|
+
} : c) : v;
|
|
980
|
+
case "slot": {
|
|
981
|
+
const kids = (type) => plan.child?.(type);
|
|
982
|
+
return slotChildrenToStored(plan.family ? childVariantsToTypes(v, plan.family) : v, plan.multiple !== false, (type, values, i) => {
|
|
983
|
+
const fields = kids(type);
|
|
984
|
+
return fields ? mapKeys(values, fields, (p, x, k) => planToProd(p, x, lost, `${under(i)}/${k}`)) : values;
|
|
985
|
+
}, (rel) => lost?.push(under(rel)));
|
|
986
|
+
}
|
|
987
|
+
case "types": return take(typedRowsToProd(v, (row, i) => {
|
|
988
|
+
const fields = plan.types.get(row._type);
|
|
989
|
+
return fields ? mapKeys(row, fields, (p, x, k) => planToProd(p, x, lost, `${under(i)}/${k}`)) : row;
|
|
990
|
+
}));
|
|
812
991
|
default: return v;
|
|
813
992
|
}
|
|
814
993
|
}
|
|
815
994
|
/** The keys the kit reads back from a stored image object (imageFromProd) and writes again (imageToProd). */
|
|
816
|
-
var IMAGE_KIT_KEYS = new Set([
|
|
995
|
+
var IMAGE_KIT_KEYS = /* @__PURE__ */ new Set([
|
|
817
996
|
"url",
|
|
818
997
|
"id",
|
|
819
998
|
"name",
|
|
820
999
|
"altText",
|
|
821
1000
|
"focal"
|
|
822
1001
|
]);
|
|
823
|
-
/**
|
|
1002
|
+
/**
|
|
1003
|
+
* Every key of a stored image the kit cannot hand back. A crop rect is read back as it is (imageFromProd), and an older
|
|
1004
|
+
* `{ src, alt }` value reads as its url and alt text, so neither is a loss (QA item 3); a malformed crop, or a key the
|
|
1005
|
+
* kit does not model, is.
|
|
1006
|
+
*/
|
|
824
1007
|
function imageStoredLoss(v, rel, loss) {
|
|
825
1008
|
if (!isObj(v)) return;
|
|
1009
|
+
const legacy = typeof v.url !== "string" && typeof v.src === "string";
|
|
826
1010
|
for (const [k, x] of Object.entries(v)) {
|
|
827
1011
|
if (IMAGE_KIT_KEYS.has(k) || x === void 0) continue;
|
|
1012
|
+
if (legacy && k === "src") continue;
|
|
1013
|
+
if (k === "alt" && typeof x === "string" && v.altText === void 0) continue;
|
|
828
1014
|
if (k === "crop") {
|
|
829
|
-
if (x != null) loss(`${rel}/crop`, "A saved crop
|
|
1015
|
+
if (x != null && !isCropRect(x)) loss(`${rel}/crop`, "A saved crop the kit can't read; editing the image would drop it.");
|
|
830
1016
|
} else loss(`${rel}/${k}`, `The image's saved "${k}" is not kept by the kit; editing the image would drop it.`);
|
|
831
1017
|
}
|
|
832
1018
|
}
|
|
@@ -859,7 +1045,14 @@ function planFromProd(plan, v, loss, rel = "") {
|
|
|
859
1045
|
else if (isObj(x) && referenceFromProd(x) === null) loss(`${rel}${Array.isArray(v) ? `/${i}` : ""}` || "(value)", "A stored reference the kit can't read; editing it would drop it.");
|
|
860
1046
|
}
|
|
861
1047
|
return referenceFromProd(v);
|
|
862
|
-
case "object":
|
|
1048
|
+
case "object": {
|
|
1049
|
+
const env = plan.zoned && isObj(v) && "nonRepeatable" in v ? v : void 0;
|
|
1050
|
+
if (env && loss) {
|
|
1051
|
+
for (const k of Object.keys(env)) if (k !== "nonRepeatable" && env[k] !== void 0) loss(`${rel}/${k}`, `The group's saved "${k}" is not one of its fields; editing the group would drop it.`);
|
|
1052
|
+
}
|
|
1053
|
+
const at = env ? `${rel}/nonRepeatable` : rel;
|
|
1054
|
+
return mapKeys(env ? isObj(env.nonRepeatable) ? env.nonRepeatable : {} : v, plan.fields, (p, x, k) => planFromProd(p, x, loss, `${at}/${k}`));
|
|
1055
|
+
}
|
|
863
1056
|
case "rows": {
|
|
864
1057
|
const rows = plan.zoned ? zoneListFromProd(v) : v;
|
|
865
1058
|
return Array.isArray(rows) ? rows.map((row, i) => mapKeys(row, plan.fields, (p, x, k) => planFromProd(p, x, loss, `${rel}/${i}/${k}`))) : rows;
|
|
@@ -875,6 +1068,27 @@ function planFromProd(plan, v, loss, rel = "") {
|
|
|
875
1068
|
...back
|
|
876
1069
|
};
|
|
877
1070
|
}) : v;
|
|
1071
|
+
case "blocks": return Array.isArray(v) ? v.map((c) => isObj(c) && typeof c._type === "string" ? {
|
|
1072
|
+
...c,
|
|
1073
|
+
_type: camel(c._type)
|
|
1074
|
+
} : c) : v;
|
|
1075
|
+
case "slot": return slotChildrenFromStored(v, (type, values, i) => {
|
|
1076
|
+
const fields = plan.child?.(type);
|
|
1077
|
+
const read = fields ? mapKeys(values, fields, (p, x, k) => planFromProd(p, x, loss, `${rel}/${i}/${k}`)) : values;
|
|
1078
|
+
const variant = plan.family?.(type)?.current;
|
|
1079
|
+
return variant === void 0 ? read : {
|
|
1080
|
+
...read,
|
|
1081
|
+
_variant: variant
|
|
1082
|
+
};
|
|
1083
|
+
}, (i, reason) => loss?.(`${rel}/${i}`, reason));
|
|
1084
|
+
case "types": return typedRowsFromProd(v, (row, i) => {
|
|
1085
|
+
const fields = plan.types.get(row._type);
|
|
1086
|
+
if (!fields) {
|
|
1087
|
+
loss?.(`${rel}/${i}/_type`, `A stored row of item type "${row._type}", which this list no longer declares; editing the list would drop it.`);
|
|
1088
|
+
return row;
|
|
1089
|
+
}
|
|
1090
|
+
return mapKeys(row, fields, (p, x, k) => planFromProd(p, x, loss, `${rel}/${i}/${k}`));
|
|
1091
|
+
});
|
|
878
1092
|
default: return v;
|
|
879
1093
|
}
|
|
880
1094
|
}
|
|
@@ -895,7 +1109,7 @@ function diffPaths(a, b, path = "", out = []) {
|
|
|
895
1109
|
if ((isObj(a) || a === void 0) && (isObj(b) || b === void 0) && (a !== void 0 || b !== void 0)) {
|
|
896
1110
|
const A = a ?? {};
|
|
897
1111
|
const B = b ?? {};
|
|
898
|
-
for (const k of new Set([...Object.keys(A), ...Object.keys(B)])) diffPaths(A[k], B[k], `${path}/${k}`, out);
|
|
1112
|
+
for (const k of /* @__PURE__ */ new Set([...Object.keys(A), ...Object.keys(B)])) diffPaths(A[k], B[k], `${path}/${k}`, out);
|
|
899
1113
|
} else if (Array.isArray(a) && Array.isArray(b)) for (let i = 0; i < Math.max(a.length, b.length); i++) diffPaths(a[i], b[i], `${path}/${i}`, out);
|
|
900
1114
|
else out.push(path);
|
|
901
1115
|
return out;
|
|
@@ -935,17 +1149,21 @@ function validationToProd(f, shape, node, at, ctx, inTable, top) {
|
|
|
935
1149
|
case "max": {
|
|
936
1150
|
const n = v;
|
|
937
1151
|
const lo = k === "min";
|
|
938
|
-
if (lengthy)
|
|
939
|
-
|
|
940
|
-
|
|
1152
|
+
if (lengthy) {
|
|
1153
|
+
if (isWhole(n)) set(lo ? "minLength" : "maxLength", n, "validation.length", "minLength", "maxLength");
|
|
1154
|
+
else lose(ctx, p, "validation.length");
|
|
1155
|
+
} else if (t === "number") {
|
|
941
1156
|
const b = node.config.validation ??= {};
|
|
942
1157
|
b[k] = n;
|
|
943
1158
|
} else if (t === "rating") lose(ctx, p, "rating bounds");
|
|
944
|
-
else if (shape.kind === "zones" || shape.kind === "modular" || shape.kind === "
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
else
|
|
1159
|
+
else if (shape.kind === "zones" || shape.kind === "modular" || shape.kind === "types" || shape.kind === "slot" || shape.kind === "itemType") {
|
|
1160
|
+
const cap = shape.kind === "slot" ? SLOT_ITEMS_CAP : LIST_ITEMS_CAP;
|
|
1161
|
+
if (props && top || shape.kind === "slot" ? isWhole(n, lo ? 0 : 1, cap) : isWhole(n)) set(lo ? "minItems" : "maxItems", n, "validation.items", "minItems", "maxItems");
|
|
1162
|
+
else lose(ctx, p, "validation.items");
|
|
1163
|
+
} else if (shape.kind === "refs" || t === "multiselect" || t === "tags") {
|
|
1164
|
+
if (t === "tags" ? isWhole(n, lo ? 0 : 1, 500) : isWhole(n)) set(k, n, "validation.items", "min", "max");
|
|
1165
|
+
else lose(ctx, p, "validation.items");
|
|
1166
|
+
} else lose(ctx, p, "validation.length");
|
|
949
1167
|
break;
|
|
950
1168
|
}
|
|
951
1169
|
case "recommendedMax":
|
|
@@ -962,9 +1180,11 @@ function validationToProd(f, shape, node, at, ctx, inTable, top) {
|
|
|
962
1180
|
break;
|
|
963
1181
|
case "unique":
|
|
964
1182
|
if (val.unique === false) node.unique = false;
|
|
965
|
-
else if (
|
|
966
|
-
else
|
|
967
|
-
|
|
1183
|
+
else if (shape.kind === "types") lose(ctx, p, "validation.unique");
|
|
1184
|
+
else if (props) {
|
|
1185
|
+
if (UNIQUE_LIST_PROPS.has(t) || inTable && UNIQUE_ROW_PROPS.has(t)) node.unique = true;
|
|
1186
|
+
else cat(ctx, p, "not applicable (props)");
|
|
1187
|
+
} else {
|
|
968
1188
|
const polymorphic = t === "reference" && (f.reference?.to ?? []).filter(ENTRY_TARGET).length > 1;
|
|
969
1189
|
if (UNIQUE_TYPES.has(t) && !polymorphic) node.unique = true;
|
|
970
1190
|
else lose(ctx, p, "validation.unique");
|
|
@@ -1000,11 +1220,15 @@ function optionsToProd(f, shape, node, at, ctx) {
|
|
|
1000
1220
|
label: o.label,
|
|
1001
1221
|
value: o.value
|
|
1002
1222
|
};
|
|
1003
|
-
if (o.icon !== void 0)
|
|
1004
|
-
|
|
1223
|
+
if (o.icon !== void 0) {
|
|
1224
|
+
if (allIcons) out.icon = icons[i];
|
|
1225
|
+
else lose(ctx, `${at}/${i}/icon`, "option icon");
|
|
1226
|
+
}
|
|
1005
1227
|
const d = o.description;
|
|
1006
|
-
if (d !== void 0)
|
|
1007
|
-
|
|
1228
|
+
if (d !== void 0) {
|
|
1229
|
+
if (typeof d === "string" && d.trim() !== "" && !/[\r\n]/.test(d) && d.length <= 140) out.description = d;
|
|
1230
|
+
else lose(ctx, `${at}/${i}/description`, "option description");
|
|
1231
|
+
}
|
|
1008
1232
|
for (const k of Object.keys(o)) if (![
|
|
1009
1233
|
"value",
|
|
1010
1234
|
"label",
|
|
@@ -1019,14 +1243,13 @@ function layoutToProd(f, shape, node, at, ctx) {
|
|
|
1019
1243
|
const l = f.layout;
|
|
1020
1244
|
const t = shape.type;
|
|
1021
1245
|
const n = f.options?.length ?? 0;
|
|
1022
|
-
if (l === "segmented" && t === "select")
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
lose(ctx, at, "
|
|
1026
|
-
} else
|
|
1027
|
-
else if (l === "slider" && t === "number" && f.type === "number") node.ui.control = "slider";
|
|
1246
|
+
if (l === "segmented" && t === "select") {
|
|
1247
|
+
if (n >= 2 && n <= 4) node.ui.control = "segmented";
|
|
1248
|
+
else if (n >= 5) cat(ctx, at, "segmented fallback");
|
|
1249
|
+
else lose(ctx, at, "layout");
|
|
1250
|
+
} else if (l === "slider" && t === "number" && f.type === "number") node.ui.control = "slider";
|
|
1028
1251
|
else if (UI_CONTROLS.includes(l) && l !== "segmented" && l !== "slider" && CONTROL_TYPES[l]?.includes(t)) node.ui.control = l;
|
|
1029
|
-
else if (l === "list" && (shape.kind === "zones" || shape.kind === "itemType" || shape.kind === "modular" || shape.kind === "refs") && f.arrayLayout === void 0) node.ui.layout = "rows";
|
|
1252
|
+
else if (l === "list" && (shape.kind === "zones" || shape.kind === "itemType" || shape.kind === "modular" || shape.kind === "types" || shape.kind === "refs") && f.arrayLayout === void 0) node.ui.layout = "rows";
|
|
1030
1253
|
else lose(ctx, at, "layout");
|
|
1031
1254
|
}
|
|
1032
1255
|
/** The prod type a V2 field is stored as, for a preview path reading into it (no loss is reported). */
|
|
@@ -1061,6 +1284,7 @@ function previewPathToProd(path, children, ctx) {
|
|
|
1061
1284
|
node = next;
|
|
1062
1285
|
continue;
|
|
1063
1286
|
}
|
|
1287
|
+
if (node.type === "table") return TABLE_PATH_KEYS.includes(segs[i]) && i === segs.length - 1 ? [...out, segs[i]].join(".") : void 0;
|
|
1064
1288
|
const type = storedType(node, ctx);
|
|
1065
1289
|
if (!OBJECT_VALUE_TYPES.has(type)) return void 0;
|
|
1066
1290
|
const key = type === "image" ? IMAGE_PATH_KEY[segs[i]] ?? segs[i] : segs[i];
|
|
@@ -1094,10 +1318,71 @@ function previewToProd(pv, children, at, ctx) {
|
|
|
1094
1318
|
}
|
|
1095
1319
|
return out;
|
|
1096
1320
|
}
|
|
1321
|
+
/**
|
|
1322
|
+
* A V2 dotted document preview path (`slides.0.heading`, `default.heading`) the backend keeps (componentPreviewRefusals
|
|
1323
|
+
* previewPathOfProps): its head a top-level prop, an index segment stepping into an item of a list, the rest a path
|
|
1324
|
+
* previewPathToProd stores unchanged (a renamed key, `image.alt` → `altText`, has no stored form here).
|
|
1325
|
+
*/
|
|
1326
|
+
function documentPreviewPathOk(path, keys, fields, ctx) {
|
|
1327
|
+
const segs = path.split(".");
|
|
1328
|
+
if (segs.length < 2 || !keys.has(segs[0])) return false;
|
|
1329
|
+
const head = fields.find((f) => f.name === segs[0]);
|
|
1330
|
+
if (!head) return false;
|
|
1331
|
+
const polyOf = (f) => f.type === "array" && Array.isArray(f.of) && f.of.length > 1 && f.of.every((o) => o.type === "object") ? f.of : void 0;
|
|
1332
|
+
let node = head;
|
|
1333
|
+
const kept = [segs[0]];
|
|
1334
|
+
let poly = false;
|
|
1335
|
+
for (let i = 1; i < segs.length; i++) {
|
|
1336
|
+
const seg = segs[i];
|
|
1337
|
+
if (/^\d+$/.test(seg) && (node.type === "array" || node.type === "multiselect" || node.type === "tags")) continue;
|
|
1338
|
+
const types = polyOf(node);
|
|
1339
|
+
const kids = types ? types.flatMap((o) => o.fields ?? []) : previewKids(node);
|
|
1340
|
+
if (!kids) {
|
|
1341
|
+
kept.push(...segs.slice(i));
|
|
1342
|
+
break;
|
|
1343
|
+
}
|
|
1344
|
+
const next = kids.find((c) => c.name === seg);
|
|
1345
|
+
if (!next) return false;
|
|
1346
|
+
if (types) poly = true;
|
|
1347
|
+
kept.push(seg);
|
|
1348
|
+
node = next;
|
|
1349
|
+
}
|
|
1350
|
+
if (poly) return true;
|
|
1351
|
+
const clean = kept.join(".");
|
|
1352
|
+
return previewPathToProd(clean, fields, ctx) === clean;
|
|
1353
|
+
}
|
|
1354
|
+
/**
|
|
1355
|
+
* A V2 schema's document-level preview → component.preview (BE componentPreviewSchema): `title` / `subtitle` / `media`
|
|
1356
|
+
* kept when they name a top-level prop key or a dotted path into one (else preview_key_unknown; a catalog note: the row
|
|
1357
|
+
* reads the first text),
|
|
1358
|
+
* `fallback` trimmed and at most COMPONENT_PREVIEW_FALLBACK_MAX, `icon` a dock icon.
|
|
1359
|
+
*/
|
|
1360
|
+
function componentPreviewToProd(pv, keys, fields, at, ctx) {
|
|
1361
|
+
const out = {};
|
|
1362
|
+
for (const k of Object.keys(pv)) {
|
|
1363
|
+
const v = pv[k];
|
|
1364
|
+
if (v === void 0) continue;
|
|
1365
|
+
if (k === "title" || k === "subtitle" || k === "media") {
|
|
1366
|
+
if ((keys.has(v) || documentPreviewPathOk(v, keys, fields, ctx)) && v.length <= 64) out[k] = v;
|
|
1367
|
+
else cat(ctx, `${at}/${k}`, "document preview path");
|
|
1368
|
+
} else if (k === "fallback") {
|
|
1369
|
+
const t = v.trim();
|
|
1370
|
+
if (t && t === v && t.length <= 120) out.fallback = v;
|
|
1371
|
+
else lose(ctx, `${at}/${k}`, "help>limit");
|
|
1372
|
+
} else if (k === "icon") {
|
|
1373
|
+
const dock = dockIconOf(v);
|
|
1374
|
+
if (dock) out.icon = dock;
|
|
1375
|
+
else lose(ctx, `${at}/${k}`, "preview icon");
|
|
1376
|
+
} else lose(ctx, `${at}/${k}`, "unsupported key");
|
|
1377
|
+
}
|
|
1378
|
+
return out;
|
|
1379
|
+
}
|
|
1097
1380
|
/** A list item's name and title: the convention, else ui.itemName / ui.itemTitle (chromeUiProblems). */
|
|
1098
1381
|
function itemIdentity(item, conv, node, ip, ctx) {
|
|
1099
|
-
if (item.name !== conv.name)
|
|
1100
|
-
|
|
1382
|
+
if (item.name !== conv.name) {
|
|
1383
|
+
if (ITEM_NAME_RE.test(item.name)) node.ui.itemName = item.name;
|
|
1384
|
+
else lose(ctx, `${ip}/name`, "item identity");
|
|
1385
|
+
}
|
|
1101
1386
|
if (item.title !== conv.title) {
|
|
1102
1387
|
const t = item.title;
|
|
1103
1388
|
if (t === t.trim() && t.length >= 1 && t.length <= 60) node.ui.itemTitle = t;
|
|
@@ -1111,6 +1396,21 @@ function ofToProd(f, shape, node, at, lv, ctx) {
|
|
|
1111
1396
|
shape.items.forEach((item, i) => blockModelFor(item, `${at}/${i}`, ctx, node));
|
|
1112
1397
|
return;
|
|
1113
1398
|
}
|
|
1399
|
+
if (shape.kind === "types") return itemTypesToProd(shape.items, node, at, lv, ctx);
|
|
1400
|
+
if (shape.kind === "slot") {
|
|
1401
|
+
const of = f.of;
|
|
1402
|
+
for (const k of Object.keys(of)) {
|
|
1403
|
+
if (of[k] === void 0) continue;
|
|
1404
|
+
if (k === "allow" && ctx.lane === "fields") {
|
|
1405
|
+
node.config.blockSlugs = of.allow.map(kebab);
|
|
1406
|
+
of.allow.forEach((n, i) => camel(kebab(n)) !== n && lose(ctx, `${at}/allow/${i}`, "type name"));
|
|
1407
|
+
} else if (k === "allow") {
|
|
1408
|
+
if (slotAllowOk(of.allow)) node.config.allow = [...of.allow];
|
|
1409
|
+
else cat(ctx, `${at}/allow`, "slot allow");
|
|
1410
|
+
} else if (k !== "type" || of.type !== "block") lose(ctx, `${at}/${k}`, "unsupported key");
|
|
1411
|
+
}
|
|
1412
|
+
return;
|
|
1413
|
+
}
|
|
1114
1414
|
const item = shape.item;
|
|
1115
1415
|
const ip = `${at}/0`;
|
|
1116
1416
|
if (shape.kind === "zones") {
|
|
@@ -1134,15 +1434,96 @@ function ofToProd(f, shape, node, at, lv, ctx) {
|
|
|
1134
1434
|
}
|
|
1135
1435
|
if (shape.kind === "itemType") node.config.itemType = shape.itemType;
|
|
1136
1436
|
itemIdentity(item, conventionItem(f.name, f.title), node, ip, ctx);
|
|
1437
|
+
const settings = {};
|
|
1438
|
+
const scalars = shape.kind === "itemType" && !shape.shopify && ctx.lane === "props";
|
|
1137
1439
|
for (const k of Object.keys(item)) {
|
|
1138
|
-
|
|
1440
|
+
const v = item[k];
|
|
1441
|
+
if (v === void 0) continue;
|
|
1139
1442
|
const p = `${ip}/${k}`;
|
|
1140
1443
|
if (k === "name" || k === "title") continue;
|
|
1141
1444
|
if (k === "type") {
|
|
1445
|
+
if (shape.kind === "itemType" && shape.shopify) continue;
|
|
1142
1446
|
if (shape.kind === "itemType" && item.type === "text") lose(ctx, p, "item settings");
|
|
1143
1447
|
} else if (k === "reference" && shape.kind === "refs") referenceToConfig(item.reference, node, p, ctx);
|
|
1448
|
+
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 <= 200) settings.helpText = v;
|
|
1450
|
+
else if (scalars && k === "localized" && typeof v === "boolean") settings.localized = v;
|
|
1451
|
+
else if (scalars && k === "validation") itemValidationToProd(item, shape.itemType, settings, p, ctx);
|
|
1144
1452
|
else lose(ctx, p, "item settings");
|
|
1145
1453
|
}
|
|
1454
|
+
if (nonEmpty(settings)) node.config.item = settings;
|
|
1455
|
+
}
|
|
1456
|
+
/** A scalar list item's V2 validation → config.item: required, a text / rich text item's length, a text item's pattern. */
|
|
1457
|
+
function itemValidationToProd(item, itemType, out, at, ctx) {
|
|
1458
|
+
const val = item.validation;
|
|
1459
|
+
const lengthy = itemType === "text" || itemType === "richtext";
|
|
1460
|
+
for (const k of Object.keys(val)) {
|
|
1461
|
+
const v = val[k];
|
|
1462
|
+
if (v === void 0) continue;
|
|
1463
|
+
if (k === "required" && typeof v === "boolean") out.required = v;
|
|
1464
|
+
else if ((k === "min" || k === "max") && lengthy && isWhole(v)) out[k === "min" ? "minLength" : "maxLength"] = v;
|
|
1465
|
+
else if (k === "pattern" && itemType === "text" && typeof v === "string" && v.length <= 200 && compiles(v)) out.pattern = v;
|
|
1466
|
+
else if (k === "patternMessage" && typeof v === "string" && v.trim() !== "" && v.length <= 200) out.patternMessage = v;
|
|
1467
|
+
else lose(ctx, `${at}/${k}`, "item settings");
|
|
1468
|
+
}
|
|
1469
|
+
if (out.minLength !== void 0 && out.maxLength !== void 0 && out.minLength > out.maxLength) {
|
|
1470
|
+
delete out.minLength;
|
|
1471
|
+
delete out.maxLength;
|
|
1472
|
+
lose(ctx, `${at}/min`, "item settings");
|
|
1473
|
+
}
|
|
1474
|
+
if (out.patternMessage !== void 0 && out.pattern === void 0) {
|
|
1475
|
+
delete out.patternMessage;
|
|
1476
|
+
lose(ctx, `${at}/patternMessage`, "item settings");
|
|
1477
|
+
}
|
|
1478
|
+
}
|
|
1479
|
+
/** A slot's per-child settings → config.slotSettings: leaf sub-fields, at most SLOT_SETTINGS_MAX (slotSettingsHardening). */
|
|
1480
|
+
function slotSettingsToProd(settings, node, at, lv, ctx) {
|
|
1481
|
+
const kept = settings.slice(0, SLOT_SETTINGS_MAX);
|
|
1482
|
+
if (settings.length > SLOT_SETTINGS_MAX) settings.slice(SLOT_SETTINGS_MAX).forEach((_, i) => lose(ctx, `${at}/${SLOT_SETTINGS_MAX + i}`, "slotSettings"));
|
|
1483
|
+
node.slotSettings = kept.map((c, i) => convertField(c, `${at}/${i}`, lv + 1, ctx, kept, false, false, false, true));
|
|
1484
|
+
}
|
|
1485
|
+
/**
|
|
1486
|
+
* A polymorphic list's item types → config.itemTypes `{ name, label, fields }`: the name is what a row's `_type` holds,
|
|
1487
|
+
* the title its label, its icon and row preview `icon` / `preview` (paths over its own fields). One prod cannot name is
|
|
1488
|
+
* not stored, which moves the ones after it up a place, so the whole list is named.
|
|
1489
|
+
*/
|
|
1490
|
+
function itemTypesToProd(items, node, at, lv, ctx) {
|
|
1491
|
+
const names = /* @__PURE__ */ new Set();
|
|
1492
|
+
node.itemTypes = [];
|
|
1493
|
+
let dropped = false;
|
|
1494
|
+
items.forEach((item, i) => {
|
|
1495
|
+
const ip = `${at}/${i}`;
|
|
1496
|
+
const fields = item.fields ?? [];
|
|
1497
|
+
const why = !ITEM_TYPE_NAME.test(item.name) || !fields.length ? "item identity" : names.has(item.name) ? "duplicate name" : void 0;
|
|
1498
|
+
if (why) {
|
|
1499
|
+
lose(ctx, ip, why);
|
|
1500
|
+
dropped = true;
|
|
1501
|
+
return;
|
|
1502
|
+
}
|
|
1503
|
+
names.add(item.name);
|
|
1504
|
+
const label = trunc(ctx, `${ip}/title`, item.title, ITEM_TYPE_LABEL_MAX, "item identity");
|
|
1505
|
+
const children = fields.map((c, j) => convertField(c, `${ip}/fields/${j}`, lv + 1, ctx, fields, false, false, true));
|
|
1506
|
+
const type = {
|
|
1507
|
+
name: item.name,
|
|
1508
|
+
label,
|
|
1509
|
+
children
|
|
1510
|
+
};
|
|
1511
|
+
for (const k of Object.keys(item)) {
|
|
1512
|
+
if (item[k] === void 0 || k === "name" || k === "title" || k === "type" || k === "fields") continue;
|
|
1513
|
+
const p = `${ip}/${k}`;
|
|
1514
|
+
if (k === "preview") {
|
|
1515
|
+
const preview = previewToProd(item.preview, fields, p, ctx);
|
|
1516
|
+
if (nonEmpty(preview)) type.preview = preview;
|
|
1517
|
+
} else if (k === "icon") {
|
|
1518
|
+
const dock = dockIconOf(item.icon);
|
|
1519
|
+
if (dock) type.icon = dock;
|
|
1520
|
+
else lose(ctx, p, "item icon");
|
|
1521
|
+
} else if (k === "openMode") cat(ctx, p, "item openMode");
|
|
1522
|
+
else lose(ctx, p, "item identity");
|
|
1523
|
+
}
|
|
1524
|
+
node.itemTypes.push(type);
|
|
1525
|
+
});
|
|
1526
|
+
if (dropped && node.itemTypes.length < items.length && node.itemTypes.length) lose(ctx, at, "item identity");
|
|
1146
1527
|
}
|
|
1147
1528
|
/**
|
|
1148
1529
|
* A modular item type → the kind:'block' model its rows are stored against: the item title is the model name, its fields
|
|
@@ -1219,16 +1600,28 @@ function blockModelFor(item, at, ctx, list) {
|
|
|
1219
1600
|
ctx.catalog.length = startCat;
|
|
1220
1601
|
lose(ctx, at, "duplicate name");
|
|
1221
1602
|
}
|
|
1603
|
+
/**
|
|
1604
|
+
* A reference's targets: entry models → contentModelId / polymorphic + allowedModelSlugs; page, form and collection →
|
|
1605
|
+
* config.targets and the filter → config.filter (backend refTargetKeys, both lanes). Read back, entry models come first,
|
|
1606
|
+
* then the targets.
|
|
1607
|
+
*/
|
|
1222
1608
|
function referenceToConfig(ref, node, at, ctx) {
|
|
1223
1609
|
const to = ref.to ?? [];
|
|
1224
1610
|
const entries = to.filter(ENTRY_TARGET);
|
|
1225
|
-
|
|
1611
|
+
const targets = to.filter((t) => REF_TARGET_KINDS.includes(t));
|
|
1612
|
+
const kept = entries.length + targets.length;
|
|
1613
|
+
if (kept < to.length) lose(ctx, kept || !to.length ? `${at}/to` : at, "shopify reference");
|
|
1614
|
+
else if (to.join() !== [...entries, ...targets].join()) lose(ctx, `${at}/to`, "reference order");
|
|
1226
1615
|
if (entries.length === 1) node.config.contentModelId = entries[0];
|
|
1227
1616
|
else if (entries.length > 1) Object.assign(node.config, {
|
|
1228
1617
|
polymorphic: true,
|
|
1229
1618
|
allowedModelSlugs: entries
|
|
1230
1619
|
});
|
|
1231
|
-
if (
|
|
1620
|
+
if (targets.length) node.config.targets = targets;
|
|
1621
|
+
if (ref.filter !== void 0) {
|
|
1622
|
+
if (filterKept(ref.filter)) node.config.filter = ref.filter;
|
|
1623
|
+
else lose(ctx, `${at}/filter`, "reference filter");
|
|
1624
|
+
}
|
|
1232
1625
|
for (const k of Object.keys(ref)) if (k !== "to" && k !== "filter") lose(ctx, `${at}/${k}`, "unsupported key");
|
|
1233
1626
|
}
|
|
1234
1627
|
function numericToProd(f, node, at, ctx) {
|
|
@@ -1236,7 +1629,7 @@ function numericToProd(f, node, at, ctx) {
|
|
|
1236
1629
|
const n = f.numeric;
|
|
1237
1630
|
const lo = n.min ?? 0;
|
|
1238
1631
|
const hi = n.max ?? 5;
|
|
1239
|
-
const st = n.step ?? 1;
|
|
1632
|
+
const st = n.step ?? (f.type === "rating" ? V2_RATING_STEP : 1);
|
|
1240
1633
|
const stops = (hi - lo) / st;
|
|
1241
1634
|
const ratingOk = (n.min === void 0 || Number.isFinite(n.min) && n.min >= 0) && (n.max === void 0 || isWhole(n.max, 1, 10)) && (n.step === void 0 || Number.isFinite(n.step) && n.step > 0) && lo < hi && Math.abs(stops - Math.round(stops)) < 1e-9 && Math.round(stops) <= 100;
|
|
1242
1635
|
for (const k of Object.keys(n)) {
|
|
@@ -1247,13 +1640,14 @@ function numericToProd(f, node, at, ctx) {
|
|
|
1247
1640
|
const u = v;
|
|
1248
1641
|
if (f.type === "number" && typeof u === "string" && u.trim() !== "" && u.length <= 24) node.config.unit = u;
|
|
1249
1642
|
else lose(ctx, p, "numeric unit");
|
|
1250
|
-
} else if (k === "min" || k === "max" || k === "step")
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1643
|
+
} else if (k === "min" || k === "max" || k === "step") {
|
|
1644
|
+
if (f.type === "number") node.config[k] = v;
|
|
1645
|
+
else if (ratingOk) node.config[k] = v;
|
|
1646
|
+
else lose(ctx, p, "rating bounds");
|
|
1647
|
+
} else lose(ctx, p, "unsupported key");
|
|
1254
1648
|
}
|
|
1255
1649
|
}
|
|
1256
|
-
var SCALE_UNIT_SET = new Set([
|
|
1650
|
+
var SCALE_UNIT_SET = /* @__PURE__ */ new Set([
|
|
1257
1651
|
"px",
|
|
1258
1652
|
"%",
|
|
1259
1653
|
"rem",
|
|
@@ -1298,13 +1692,16 @@ function scaleToConfig(s, node, at, ctx) {
|
|
|
1298
1692
|
const v = s[k];
|
|
1299
1693
|
if (v === void 0 || k === "steps") continue;
|
|
1300
1694
|
const p = `${at}/${k}`;
|
|
1301
|
-
if (k === "units")
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
else
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
else if (k === "
|
|
1695
|
+
if (k === "units") {
|
|
1696
|
+
if (unitsOk(v)) out.units = [...v];
|
|
1697
|
+
else lose(ctx, p, "scale rules");
|
|
1698
|
+
} else if (k === "defaultUnit") {
|
|
1699
|
+
if (SCALE_UNIT_SET.has(v)) out.defaultUnit = s.defaultUnit;
|
|
1700
|
+
else lose(ctx, p, "scale rules");
|
|
1701
|
+
} else if (k === "allowCustom") {
|
|
1702
|
+
if (customOk) out.allowCustom = typeof c === "boolean" ? c : JSON.parse(JSON.stringify(c));
|
|
1703
|
+
else lose(ctx, p, "scale rules");
|
|
1704
|
+
} else if (k === "presets") {
|
|
1308
1705
|
const presets = s.presets;
|
|
1309
1706
|
if (presets.length <= 20 && presets.every((x) => {
|
|
1310
1707
|
if (x.label !== void 0 && !textOk(x.label, 24)) return false;
|
|
@@ -1322,45 +1719,102 @@ function scaleToConfig(s, node, at, ctx) {
|
|
|
1322
1719
|
}
|
|
1323
1720
|
node.config.scale = out;
|
|
1324
1721
|
}
|
|
1722
|
+
/** V2 operator → prod showIf op (the legacy `equals` / `notEmpty` forms read as is / is one of / has a value). */
|
|
1723
|
+
var SHOW_IF_OP = {
|
|
1724
|
+
is: "eq",
|
|
1725
|
+
isNot: "neq",
|
|
1726
|
+
in: "in",
|
|
1727
|
+
notIn: "notIn",
|
|
1728
|
+
empty: "empty",
|
|
1729
|
+
notEmpty: "notEmpty",
|
|
1730
|
+
gt: "gt",
|
|
1731
|
+
lt: "lt"
|
|
1732
|
+
};
|
|
1733
|
+
var VALUELESS = /* @__PURE__ */ new Set([
|
|
1734
|
+
"empty",
|
|
1735
|
+
"notEmpty",
|
|
1736
|
+
"isSet"
|
|
1737
|
+
]);
|
|
1325
1738
|
function conditionToShowIf(h, at, siblings, ctx, variantOk) {
|
|
1326
|
-
const
|
|
1327
|
-
|
|
1328
|
-
|
|
1739
|
+
const rules = [];
|
|
1740
|
+
for (const [i, r] of [h, ...h.also ?? []].entries()) {
|
|
1741
|
+
const rule = conditionRule(r, i === 0, siblings, variantOk);
|
|
1742
|
+
if (!rule) return void lose(ctx, at, "condition");
|
|
1743
|
+
rules.push(rule);
|
|
1744
|
+
}
|
|
1745
|
+
if (h.match !== void 0 && h.match !== "all" && h.match !== "any") return void lose(ctx, at, "condition");
|
|
1746
|
+
return {
|
|
1747
|
+
match: h.match ?? "all",
|
|
1748
|
+
rules
|
|
1749
|
+
};
|
|
1750
|
+
}
|
|
1751
|
+
/** 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
|
+
function conditionRule(r, head, siblings, variantOk) {
|
|
1753
|
+
const variant = variantOk && r.field === "_variant";
|
|
1754
|
+
if (!r.field || r.scope !== void 0 || !variant && !siblings.some((s) => s.name === r.field)) return null;
|
|
1755
|
+
const allowed = head ? [
|
|
1756
|
+
"field",
|
|
1757
|
+
"equals",
|
|
1758
|
+
"notEmpty",
|
|
1759
|
+
"op",
|
|
1760
|
+
"value",
|
|
1761
|
+
"also",
|
|
1762
|
+
"match"
|
|
1763
|
+
] : [
|
|
1329
1764
|
"field",
|
|
1330
1765
|
"equals",
|
|
1331
|
-
"notEmpty"
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1766
|
+
"notEmpty",
|
|
1767
|
+
"op",
|
|
1768
|
+
"value"
|
|
1769
|
+
];
|
|
1770
|
+
if (Object.keys(r).some((k) => !allowed.includes(k) && r[k] !== void 0)) return null;
|
|
1771
|
+
if ([
|
|
1772
|
+
r.op !== void 0,
|
|
1773
|
+
r.equals !== void 0,
|
|
1774
|
+
r.notEmpty !== void 0
|
|
1775
|
+
].filter(Boolean).length !== 1) return null;
|
|
1776
|
+
if (r.notEmpty !== void 0) return r.notEmpty === true ? {
|
|
1777
|
+
field: r.field,
|
|
1778
|
+
op: "notEmpty"
|
|
1779
|
+
} : null;
|
|
1780
|
+
const target = r.op !== void 0 ? r.value : r.equals;
|
|
1781
|
+
const op = r.op !== void 0 ? SHOW_IF_OP[r.op] : Array.isArray(target) ? "in" : "eq";
|
|
1782
|
+
if (!op) return null;
|
|
1783
|
+
if (VALUELESS.has(op)) return r.value === void 0 ? {
|
|
1784
|
+
field: r.field,
|
|
1785
|
+
op
|
|
1786
|
+
} : null;
|
|
1787
|
+
const sibType = variant ? void 0 : siblings.find((s) => s.name === r.field)?.type;
|
|
1788
|
+
if (op === "gt" || op === "lt") return typeof target === "number" && Number.isFinite(target) ? {
|
|
1789
|
+
field: r.field,
|
|
1790
|
+
op,
|
|
1791
|
+
value: String(target)
|
|
1792
|
+
} : null;
|
|
1793
|
+
const list = Array.isArray(target) ? target : [target];
|
|
1342
1794
|
const strs = [];
|
|
1343
1795
|
for (const v of list) {
|
|
1344
1796
|
if (![
|
|
1345
1797
|
"string",
|
|
1346
1798
|
"number",
|
|
1347
1799
|
"boolean"
|
|
1348
|
-
].includes(typeof v)) return
|
|
1800
|
+
].includes(typeof v)) return null;
|
|
1349
1801
|
const s = String(v);
|
|
1350
|
-
if (coerceRuleValue(sibType, s) !== v) return
|
|
1802
|
+
if (coerceRuleValue(sibType, s) !== v) return null;
|
|
1351
1803
|
strs.push(s);
|
|
1352
1804
|
}
|
|
1353
|
-
return {
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1805
|
+
if (op === "in" || op === "notIn") return {
|
|
1806
|
+
field: r.field,
|
|
1807
|
+
op,
|
|
1808
|
+
value: strs
|
|
1809
|
+
};
|
|
1810
|
+
return Array.isArray(target) ? strs.length ? {
|
|
1811
|
+
field: r.field,
|
|
1812
|
+
op: op === "eq" ? "in" : "notIn",
|
|
1813
|
+
value: strs
|
|
1814
|
+
} : null : {
|
|
1815
|
+
field: r.field,
|
|
1816
|
+
op,
|
|
1817
|
+
value: strs[0]
|
|
1364
1818
|
};
|
|
1365
1819
|
}
|
|
1366
1820
|
var nonEmpty = (o) => Object.keys(o).length ? o : void 0;
|
|
@@ -1379,7 +1833,8 @@ function common(n) {
|
|
|
1379
1833
|
"advanced",
|
|
1380
1834
|
"recommendedMax",
|
|
1381
1835
|
"openMode",
|
|
1382
|
-
"localized"
|
|
1836
|
+
"localized",
|
|
1837
|
+
"archived"
|
|
1383
1838
|
]) if (n[k] !== void 0) out[k] = n[k];
|
|
1384
1839
|
return out;
|
|
1385
1840
|
}
|
|
@@ -1394,6 +1849,7 @@ function emitField(n) {
|
|
|
1394
1849
|
if (n.type === "select" && n.options) out.options = n.options;
|
|
1395
1850
|
if ((n.type === "multiselect" || n.type === "tags") && n.options) config.options = n.options;
|
|
1396
1851
|
if (n.type === "object") out.fields = (n.children ?? []).map(emitField);
|
|
1852
|
+
if (n.slotSettings) config.slotSettings = n.slotSettings.map(emitField);
|
|
1397
1853
|
if (n.zoned) {
|
|
1398
1854
|
const { minItems, maxItems, ...rest } = config;
|
|
1399
1855
|
out.config = {
|
|
@@ -1418,6 +1874,8 @@ function emitProp(n) {
|
|
|
1418
1874
|
const config = { ...n.config };
|
|
1419
1875
|
if (n.options) config.options = n.options;
|
|
1420
1876
|
if (n.children) config.fields = n.children.map(emitSubField);
|
|
1877
|
+
if (n.itemTypes) config.itemTypes = emitItemTypes(n.itemTypes);
|
|
1878
|
+
if (n.slotSettings) config.slotSettings = n.slotSettings.map(emitSubField);
|
|
1421
1879
|
if (nonEmpty(config)) out.config = config;
|
|
1422
1880
|
const ui = nonEmpty(n.ui);
|
|
1423
1881
|
if (ui) out.ui = ui;
|
|
@@ -1431,11 +1889,22 @@ function emitSubField(n) {
|
|
|
1431
1889
|
if (n.placeholder !== void 0) out.placeholder = n.placeholder;
|
|
1432
1890
|
if (n.options) out.options = n.options;
|
|
1433
1891
|
if (n.children) out.fields = n.children.map(emitSubField);
|
|
1434
|
-
|
|
1892
|
+
const config = { ...n.config };
|
|
1893
|
+
if (n.itemTypes) config.itemTypes = emitItemTypes(n.itemTypes);
|
|
1894
|
+
if (n.slotSettings) config.slotSettings = n.slotSettings.map(emitSubField);
|
|
1895
|
+
if (nonEmpty(config)) out.config = config;
|
|
1435
1896
|
const ui = nonEmpty(n.ui);
|
|
1436
1897
|
if (ui) out.ui = ui;
|
|
1437
1898
|
return out;
|
|
1438
1899
|
}
|
|
1900
|
+
/** A polymorphic list's item types as the backend stores them: `{ name, label, fields }` (typesTableHardening). */
|
|
1901
|
+
var emitItemTypes = (types) => types.map((t) => ({
|
|
1902
|
+
name: t.name,
|
|
1903
|
+
label: t.label,
|
|
1904
|
+
fields: t.children.map(emitSubField),
|
|
1905
|
+
...t.icon ? { icon: t.icon } : {},
|
|
1906
|
+
...t.preview ? { preview: t.preview } : {}
|
|
1907
|
+
}));
|
|
1439
1908
|
function fromTypeSchema(v2, target) {
|
|
1440
1909
|
const ctx = {
|
|
1441
1910
|
lane: target,
|
|
@@ -1448,6 +1917,10 @@ function fromTypeSchema(v2, target) {
|
|
|
1448
1917
|
definedGroups: /* @__PURE__ */ new WeakMap(),
|
|
1449
1918
|
propOrder: /* @__PURE__ */ new Map(),
|
|
1450
1919
|
groupOrder: false,
|
|
1920
|
+
propTabs: /* @__PURE__ */ new Map(),
|
|
1921
|
+
definedTabs: /* @__PURE__ */ new Set(),
|
|
1922
|
+
keptTabs: /* @__PURE__ */ new Set(),
|
|
1923
|
+
declaredTabs: [],
|
|
1451
1924
|
blockModels: /* @__PURE__ */ new Map()
|
|
1452
1925
|
};
|
|
1453
1926
|
const props = target === "props";
|
|
@@ -1471,10 +1944,10 @@ function fromTypeSchema(v2, target) {
|
|
|
1471
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");
|
|
1472
1945
|
break;
|
|
1473
1946
|
case "icon":
|
|
1474
|
-
cat(ctx, p, "block icon");
|
|
1947
|
+
if (!props || !dockIconOf(v2.icon)) cat(ctx, p, "block icon");
|
|
1475
1948
|
break;
|
|
1476
1949
|
case "preview":
|
|
1477
|
-
cat(ctx, p, "document preview");
|
|
1950
|
+
if (!props) cat(ctx, p, "document preview");
|
|
1478
1951
|
break;
|
|
1479
1952
|
case "variants":
|
|
1480
1953
|
cat(ctx, p, "variants");
|
|
@@ -1492,7 +1965,7 @@ function fromTypeSchema(v2, target) {
|
|
|
1492
1965
|
}
|
|
1493
1966
|
}
|
|
1494
1967
|
if (props) {
|
|
1495
|
-
|
|
1968
|
+
propTabsFor(v2, ctx);
|
|
1496
1969
|
propSetsFor(v2, ctx);
|
|
1497
1970
|
} else fieldsetsFor(v2, ctx, fieldsets);
|
|
1498
1971
|
const nodes = v2.fields.map((f, i) => convertField(f, `/fields/${i}`, 1, ctx, v2.fields, true));
|
|
@@ -1504,6 +1977,13 @@ function fromTypeSchema(v2, target) {
|
|
|
1504
1977
|
};
|
|
1505
1978
|
if (v2.description !== void 0) component.description = v2.description;
|
|
1506
1979
|
if (category) component.category = category;
|
|
1980
|
+
const icon = v2.icon === void 0 ? void 0 : dockIconOf(v2.icon);
|
|
1981
|
+
if (icon) component.icon = icon;
|
|
1982
|
+
if (v2.preview !== void 0) {
|
|
1983
|
+
const preview = componentPreviewToProd(v2.preview, new Set(component.props.map((x) => x.key)), v2.fields, "/preview", ctx);
|
|
1984
|
+
if (Object.keys(preview).length) component.preview = preview;
|
|
1985
|
+
}
|
|
1986
|
+
if (ctx.declaredTabs.length) component.tabs = ctx.declaredTabs.map((t) => ({ ...t }));
|
|
1507
1987
|
return {
|
|
1508
1988
|
schema: component,
|
|
1509
1989
|
blockModels: [],
|
|
@@ -1533,7 +2013,7 @@ function fieldsetsFor(v2, ctx, out) {
|
|
|
1533
2013
|
let shifted = false;
|
|
1534
2014
|
(v2.groups ?? []).forEach((g, i) => {
|
|
1535
2015
|
const p = `/groups/${i}`;
|
|
1536
|
-
const stored = g.title.slice(0,
|
|
2016
|
+
const stored = g.title.slice(0, 40);
|
|
1537
2017
|
const folded = stored.trim().toLowerCase();
|
|
1538
2018
|
const drop = (why) => {
|
|
1539
2019
|
if (!ctx.tabs.has(g.name) && !ctx.droppedTabs.has(g.name)) ctx.droppedTabs.set(g.name, why);
|
|
@@ -1548,7 +2028,7 @@ function fieldsetsFor(v2, ctx, out) {
|
|
|
1548
2028
|
name: stored,
|
|
1549
2029
|
kind: "tab"
|
|
1550
2030
|
};
|
|
1551
|
-
if (g.title.length >
|
|
2031
|
+
if (g.title.length > 40) lose(ctx, `${p}/title`, "group name>40");
|
|
1552
2032
|
if (g.icon !== void 0) {
|
|
1553
2033
|
const dock = dockIconOf(g.icon);
|
|
1554
2034
|
if (dock) tab.icon = dock;
|
|
@@ -1585,9 +2065,10 @@ function fieldsetsFor(v2, ctx, out) {
|
|
|
1585
2065
|
for (const k of Object.keys(fs)) {
|
|
1586
2066
|
const v = fs[k];
|
|
1587
2067
|
if (v === void 0 || k === "name" || k === "title") continue;
|
|
1588
|
-
if (k === "description")
|
|
1589
|
-
|
|
1590
|
-
|
|
2068
|
+
if (k === "description") {
|
|
2069
|
+
if (v.length <= 500) set.description = v;
|
|
2070
|
+
else lose(ctx, `${p}/${k}`, "help>limit");
|
|
2071
|
+
} else if (k === "collapsed" || k === "collapsible" || k === "columns" || k === "layout") set[k] = v;
|
|
1591
2072
|
else lose(ctx, `${p}/${k}`, "unsupported key");
|
|
1592
2073
|
}
|
|
1593
2074
|
ctx.sets.set(fs.name, tab);
|
|
@@ -1595,25 +2076,146 @@ function fieldsetsFor(v2, ctx, out) {
|
|
|
1595
2076
|
});
|
|
1596
2077
|
}
|
|
1597
2078
|
/**
|
|
2079
|
+
* Props lane: V2 groups → each top-level prop's `ui.tab`, defined on the first prop in it (label, icon, and `order` when
|
|
2080
|
+
* the V2 order differs from where each tab is first used). A field with no group sits in the V2 default group; a group
|
|
2081
|
+
* not stored puts its fields in the default tab; a fieldset's top-level members share the tab most of them sit in
|
|
2082
|
+
* (prop_group_split_tabs). No groups → no tab anywhere, so a component without tabs stores as before.
|
|
2083
|
+
*/
|
|
2084
|
+
function propTabsFor(v2, ctx) {
|
|
2085
|
+
const groups = v2.groups ?? [];
|
|
2086
|
+
const kept = [];
|
|
2087
|
+
const dropped = /* @__PURE__ */ new Map();
|
|
2088
|
+
const labels = /* @__PURE__ */ new Set();
|
|
2089
|
+
groups.forEach((g, i) => {
|
|
2090
|
+
const p = `/groups/${i}`;
|
|
2091
|
+
const drop = (why) => {
|
|
2092
|
+
if (!kept.some((k) => k.g.name === g.name) && !dropped.has(g.name)) dropped.set(g.name, why);
|
|
2093
|
+
lose(ctx, p, why);
|
|
2094
|
+
};
|
|
2095
|
+
const label = g.title.slice(0, 40).trim();
|
|
2096
|
+
const folded = label.toLowerCase();
|
|
2097
|
+
if (kept.some((k) => k.g.name === g.name) || labels.has(folded)) return drop("group name collision");
|
|
2098
|
+
if (kept.length >= 8 || g.name.length < 1 || g.name.length > 40) return drop("prop tab limit");
|
|
2099
|
+
if (!label) return drop("group title");
|
|
2100
|
+
labels.add(folded);
|
|
2101
|
+
const tab = {
|
|
2102
|
+
id: g.name,
|
|
2103
|
+
label
|
|
2104
|
+
};
|
|
2105
|
+
if (label !== g.title.trim()) lose(ctx, `${p}/title`, "group name>40");
|
|
2106
|
+
else if (label !== g.title) lose(ctx, `${p}/title`, "group title");
|
|
2107
|
+
if (g.icon !== void 0) {
|
|
2108
|
+
const dock = dockIconOf(g.icon);
|
|
2109
|
+
if (dock) tab.icon = dock;
|
|
2110
|
+
else lose(ctx, `${p}/icon`, "group icon");
|
|
2111
|
+
}
|
|
2112
|
+
if (i === 0 ? g.default !== true : g.default !== void 0) lose(ctx, `${p}/default`, "group default");
|
|
2113
|
+
for (const k of Object.keys(g)) if (![
|
|
2114
|
+
"name",
|
|
2115
|
+
"title",
|
|
2116
|
+
"icon",
|
|
2117
|
+
"default"
|
|
2118
|
+
].includes(k) && g[k] !== void 0) lose(ctx, `${p}/${k}`, "unsupported key");
|
|
2119
|
+
kept.push({
|
|
2120
|
+
g,
|
|
2121
|
+
i,
|
|
2122
|
+
tab
|
|
2123
|
+
});
|
|
2124
|
+
});
|
|
2125
|
+
const isKept = (name) => name !== void 0 && kept.some((k) => k.g.name === name);
|
|
2126
|
+
const v2Default = (groups.find((g) => g.default) ?? groups[0])?.name;
|
|
2127
|
+
const fallback = isKept(v2Default) ? v2Default : kept[0]?.g.name;
|
|
2128
|
+
const place = /* @__PURE__ */ new Map();
|
|
2129
|
+
for (const f of v2.fields) {
|
|
2130
|
+
const want = f.group ?? v2Default;
|
|
2131
|
+
if (isKept(want)) place.set(f, { tab: want });
|
|
2132
|
+
else if (f.group !== void 0 || want !== void 0) place.set(f, {
|
|
2133
|
+
tab: fallback,
|
|
2134
|
+
loss: dropped.get(want) ?? "unsupported key"
|
|
2135
|
+
});
|
|
2136
|
+
}
|
|
2137
|
+
if (!kept.length) {
|
|
2138
|
+
for (const [f, t] of place) if (f.group !== void 0) ctx.propTabs.set(f, { loss: t.loss });
|
|
2139
|
+
return;
|
|
2140
|
+
}
|
|
2141
|
+
const tally = /* @__PURE__ */ new Map();
|
|
2142
|
+
for (const f of v2.fields) {
|
|
2143
|
+
if (f.fieldset === void 0) continue;
|
|
2144
|
+
const t = tally.get(f.fieldset) ?? /* @__PURE__ */ new Map();
|
|
2145
|
+
t.set(place.get(f)?.tab, (t.get(place.get(f)?.tab) ?? 0) + 1);
|
|
2146
|
+
tally.set(f.fieldset, t);
|
|
2147
|
+
}
|
|
2148
|
+
for (const f of v2.fields) {
|
|
2149
|
+
const counts = f.fieldset !== void 0 ? tally.get(f.fieldset) : void 0;
|
|
2150
|
+
if (!counts) continue;
|
|
2151
|
+
const best = [...counts.entries()].sort((a, b) => b[1] - a[1])[0][0];
|
|
2152
|
+
const cur = place.get(f);
|
|
2153
|
+
if (cur?.tab !== best) place.set(f, {
|
|
2154
|
+
tab: best,
|
|
2155
|
+
loss: cur?.loss ?? "fieldset spans groups"
|
|
2156
|
+
});
|
|
2157
|
+
}
|
|
2158
|
+
const firstUse = [];
|
|
2159
|
+
for (const f of v2.fields) {
|
|
2160
|
+
const t = place.get(f)?.tab;
|
|
2161
|
+
if (t !== void 0 && !firstUse.includes(t)) firstUse.push(t);
|
|
2162
|
+
}
|
|
2163
|
+
const used = kept.filter((k) => firstUse.includes(k.g.name));
|
|
2164
|
+
const unused = kept.filter((k) => !firstUse.includes(k.g.name));
|
|
2165
|
+
for (const k of kept) ctx.keptTabs.add(k.g.name);
|
|
2166
|
+
const firstGap = groups.findIndex((g) => !kept.some((k) => k.g === g));
|
|
2167
|
+
if (firstGap >= 0 && kept.some((k) => k.i > firstGap)) {
|
|
2168
|
+
const g = groups[firstGap];
|
|
2169
|
+
lose(ctx, "/groups", dropped.get(g.name) ?? "unsupported key");
|
|
2170
|
+
}
|
|
2171
|
+
const ordered = unused.length > 0 || used.some((k, i) => k.g.name !== firstUse[i]);
|
|
2172
|
+
kept.forEach((k, i) => {
|
|
2173
|
+
if (ordered) k.tab.order = Math.min(99, i);
|
|
2174
|
+
});
|
|
2175
|
+
ctx.declaredTabs = unused.map((k) => k.tab);
|
|
2176
|
+
for (const [f, t] of place) {
|
|
2177
|
+
const k = used.find((u) => u.g.name === t.tab);
|
|
2178
|
+
if (k) ctx.propTabs.set(f, {
|
|
2179
|
+
tab: k.tab,
|
|
2180
|
+
loss: t.loss
|
|
2181
|
+
});
|
|
2182
|
+
else if (t.loss) ctx.propTabs.set(f, { loss: t.loss });
|
|
2183
|
+
}
|
|
2184
|
+
}
|
|
2185
|
+
/**
|
|
1598
2186
|
* Props lane: a V2 fieldset is an inline ui.group, defined on the first prop (at each level, sub-fields too) that uses
|
|
1599
2187
|
* it. A fieldset no prop uses has nothing to be defined on; when the V2 order differs from where each group is first
|
|
1600
2188
|
* met (depth first, a prop before its sub-fields: how propsToTypeSchema meets them), every group carries its `order`.
|
|
1601
2189
|
*/
|
|
1602
2190
|
function propSetsFor(v2, ctx) {
|
|
1603
2191
|
const sets = v2.fieldsets ?? [];
|
|
1604
|
-
if (!sets.length) return;
|
|
1605
2192
|
const named = new Set(sets.map((s) => s.name));
|
|
1606
2193
|
const firstSeen = [];
|
|
2194
|
+
const undeclared = [];
|
|
1607
2195
|
const visit = (fields, lv) => {
|
|
1608
2196
|
for (const f of fields) {
|
|
1609
|
-
if (f.fieldset !== void 0 &&
|
|
2197
|
+
if (f.fieldset !== void 0 && !firstSeen.includes(f.fieldset)) {
|
|
2198
|
+
firstSeen.push(f.fieldset);
|
|
2199
|
+
if (!named.has(f.fieldset)) undeclared.push(f.fieldset);
|
|
2200
|
+
}
|
|
1610
2201
|
if (lv >= 10) continue;
|
|
1611
2202
|
const kids = previewKids(f);
|
|
1612
2203
|
if (kids) visit(kids, lv + 1);
|
|
1613
2204
|
}
|
|
1614
2205
|
};
|
|
1615
2206
|
visit(v2.fields, 1);
|
|
1616
|
-
|
|
2207
|
+
const derived = undeclared.map((name) => ({
|
|
2208
|
+
name,
|
|
2209
|
+
title: name
|
|
2210
|
+
}));
|
|
2211
|
+
const declaredUsed = sets.filter((s) => firstSeen.includes(s.name)).length;
|
|
2212
|
+
derived.forEach((s, j) => {
|
|
2213
|
+
ctx.propSets.set(s.name, s);
|
|
2214
|
+
ctx.propOrder.set(s.name, sets.length + j);
|
|
2215
|
+
cat(ctx, `/fieldsets/${declaredUsed + j}`, "fieldset (derived)");
|
|
2216
|
+
});
|
|
2217
|
+
if (!sets.length && !derived.length) return;
|
|
2218
|
+
ctx.groupOrder = [...sets, ...derived].filter((s) => firstSeen.includes(s.name)).some((s, i) => s.name !== firstSeen[i]);
|
|
1617
2219
|
let gap = false;
|
|
1618
2220
|
sets.forEach((s, i) => {
|
|
1619
2221
|
ctx.propSets.set(s.name, s);
|
|
@@ -1654,6 +2256,10 @@ function readField(f) {
|
|
|
1654
2256
|
delete cfg.options;
|
|
1655
2257
|
}
|
|
1656
2258
|
n.fields = f.fields?.map(readField);
|
|
2259
|
+
if (f.type === "array" && !cfg.zones && Array.isArray(cfg.fields)) {
|
|
2260
|
+
n.fields = [...n.fields ?? [], ...cfg.fields.map(readField)];
|
|
2261
|
+
delete cfg.fields;
|
|
2262
|
+
}
|
|
1657
2263
|
if (cfg.zones) {
|
|
1658
2264
|
const z = cfg.zones;
|
|
1659
2265
|
n.zones = {
|
|
@@ -1717,12 +2323,32 @@ function scaleFromConfig(s, at, ctx) {
|
|
|
1717
2323
|
}));
|
|
1718
2324
|
return out;
|
|
1719
2325
|
}
|
|
2326
|
+
/**
|
|
2327
|
+
* Slot children with each `_variant` written as the family member that places it (`_type`): the variant the child's
|
|
2328
|
+
* component already is drops, another member swaps in. A variant no member places stays, and the write names it lost.
|
|
2329
|
+
*/
|
|
2330
|
+
function childVariantsToTypes(v, family) {
|
|
2331
|
+
if (!Array.isArray(v)) return v;
|
|
2332
|
+
return v.map((c) => {
|
|
2333
|
+
if (!isObj(c) || typeof c._variant !== "string") return c;
|
|
2334
|
+
const own = family(typeof c._type === "string" ? c._type : "");
|
|
2335
|
+
const { _variant: _gone, ...rest } = c;
|
|
2336
|
+
if (own?.current === c._variant) return rest;
|
|
2337
|
+
const member = own?.member(c._variant);
|
|
2338
|
+
if (!member) return c;
|
|
2339
|
+
return {
|
|
2340
|
+
...rest,
|
|
2341
|
+
_type: member
|
|
2342
|
+
};
|
|
2343
|
+
});
|
|
2344
|
+
}
|
|
1720
2345
|
/** The prod children a preview path segment may name below a node (an object's, a list's rows'), or null for a leaf. */
|
|
1721
2346
|
var readKids = (n) => n.zones ? [...n.zones.nonRepeatable ?? [], ...n.zones.repeatable?.fields ?? []] : n.fields && [
|
|
1722
2347
|
"object",
|
|
1723
2348
|
"group",
|
|
1724
2349
|
"repeater",
|
|
1725
|
-
"table"
|
|
2350
|
+
"table",
|
|
2351
|
+
"array"
|
|
1726
2352
|
].includes(n.type) ? n.fields : null;
|
|
1727
2353
|
/** A stored preview path → the V2 path: `image.altText` reads as `image.alt`, the rest as it is. */
|
|
1728
2354
|
function previewPathFromProd(path, children) {
|
|
@@ -1753,12 +2379,26 @@ function previewFromProd(pv, children) {
|
|
|
1753
2379
|
return out;
|
|
1754
2380
|
}
|
|
1755
2381
|
function showIfToCondition(s, siblings, at, ctx) {
|
|
1756
|
-
const
|
|
1757
|
-
|
|
1758
|
-
|
|
2382
|
+
const conds = [];
|
|
2383
|
+
for (const r of s.rules) {
|
|
2384
|
+
const c = showIfRuleToCondition(r, siblings);
|
|
2385
|
+
if (!c) return void ctx.onLoss(at, "condition", `V2 conditions have no "${r.op}" with this value; the field always shows.`);
|
|
2386
|
+
conds.push(c);
|
|
2387
|
+
}
|
|
2388
|
+
if (!conds.length) return void 0;
|
|
2389
|
+
const [head, ...also] = conds;
|
|
2390
|
+
return {
|
|
2391
|
+
...head,
|
|
2392
|
+
...also.length ? { also } : {},
|
|
2393
|
+
...s.match === "any" && conds.length > 1 ? { match: "any" } : {}
|
|
2394
|
+
};
|
|
2395
|
+
}
|
|
2396
|
+
/** One prod rule as a V2 rule: eq / in / isSet keep V2's legacy forms, the rest name their `op`. */
|
|
2397
|
+
function showIfRuleToCondition(r, siblings) {
|
|
1759
2398
|
const sib = siblings.find((x) => x.key === r.field);
|
|
1760
2399
|
const t = sib?.type === "number" ? "number" : sib?.type;
|
|
1761
2400
|
const read = (v) => coerceRuleValue(t, v);
|
|
2401
|
+
const list = (Array.isArray(r.value) ? r.value : [r.value ?? ""]).map(read);
|
|
1762
2402
|
switch (r.op) {
|
|
1763
2403
|
case "eq": return Array.isArray(r.value) ? {
|
|
1764
2404
|
field: r.field,
|
|
@@ -1769,14 +2409,37 @@ function showIfToCondition(s, siblings, at, ctx) {
|
|
|
1769
2409
|
};
|
|
1770
2410
|
case "in": return {
|
|
1771
2411
|
field: r.field,
|
|
1772
|
-
equals:
|
|
2412
|
+
equals: list
|
|
1773
2413
|
};
|
|
1774
2414
|
case "isSet":
|
|
1775
2415
|
case "notEmpty": return {
|
|
1776
2416
|
field: r.field,
|
|
1777
2417
|
notEmpty: true
|
|
1778
2418
|
};
|
|
1779
|
-
|
|
2419
|
+
case "empty": return {
|
|
2420
|
+
field: r.field,
|
|
2421
|
+
op: "empty"
|
|
2422
|
+
};
|
|
2423
|
+
case "neq": return {
|
|
2424
|
+
field: r.field,
|
|
2425
|
+
op: "isNot",
|
|
2426
|
+
value: Array.isArray(r.value) ? list : read(r.value ?? "")
|
|
2427
|
+
};
|
|
2428
|
+
case "notIn": return {
|
|
2429
|
+
field: r.field,
|
|
2430
|
+
op: "notIn",
|
|
2431
|
+
value: list
|
|
2432
|
+
};
|
|
2433
|
+
case "gt":
|
|
2434
|
+
case "lt": {
|
|
2435
|
+
const n = Number(r.value);
|
|
2436
|
+
return typeof r.value === "string" && r.value.trim() !== "" && Number.isFinite(n) ? {
|
|
2437
|
+
field: r.field,
|
|
2438
|
+
op: r.op,
|
|
2439
|
+
value: n
|
|
2440
|
+
} : void 0;
|
|
2441
|
+
}
|
|
2442
|
+
default: return;
|
|
1780
2443
|
}
|
|
1781
2444
|
}
|
|
1782
2445
|
function v2Type(n, at, ctx) {
|
|
@@ -1811,9 +2474,14 @@ function v2Type(n, at, ctx) {
|
|
|
1811
2474
|
}
|
|
1812
2475
|
}
|
|
1813
2476
|
function readToV2(n, at, siblings, ctx, top, lane) {
|
|
1814
|
-
/** a data
|
|
1815
|
-
|
|
1816
|
-
const
|
|
2477
|
+
/** a data table holds one TableValue: the V2 `table` field, not a list of rows. A prop says so (config.mode "data");
|
|
2478
|
+
* a field's table is always one (BE tableFieldSchema: `mode` is optional there and can only be "data") */
|
|
2479
|
+
const dataTable = isDataTableProp(n) || lane === "fields" && n.type === "table";
|
|
2480
|
+
/** a slot prop: component instances, read as the V2 slot (its children `{ _key, _type, _settings?, ...props }`) */
|
|
2481
|
+
const slotProp = lane === "props" && n.type === "slot";
|
|
2482
|
+
/** a model slot field: inline children of the kind:'block' models config.blockSlugs names */
|
|
2483
|
+
const blockSlot = lane === "fields" && n.type === "slot";
|
|
2484
|
+
const type = dataTable ? "table" : slotProp || blockSlot ? "slot" : v2Type(n, at, ctx);
|
|
1817
2485
|
const f = {
|
|
1818
2486
|
name: n.key,
|
|
1819
2487
|
title: n.label,
|
|
@@ -1822,7 +2490,7 @@ function readToV2(n, at, siblings, ctx, top, lane) {
|
|
|
1822
2490
|
const cfg = n.config;
|
|
1823
2491
|
const val = {};
|
|
1824
2492
|
const loss = (k, feature, reason) => ctx.onLoss(`${at}/${k}`, feature, reason);
|
|
1825
|
-
if (n.helpText
|
|
2493
|
+
if (typeof n.helpText === "string") f.description = n.helpText;
|
|
1826
2494
|
if (n.helpMore !== void 0) f.helpMore = n.helpMore;
|
|
1827
2495
|
if (n.placeholder !== void 0) f.placeholder = n.placeholder;
|
|
1828
2496
|
if (n.required !== void 0) val.required = n.required;
|
|
@@ -1831,9 +2499,18 @@ function readToV2(n, at, siblings, ctx, top, lane) {
|
|
|
1831
2499
|
if (n.advanced !== void 0) f.advanced = n.advanced;
|
|
1832
2500
|
if (n.openMode !== void 0) f.openMode = n.openMode;
|
|
1833
2501
|
if (n.readOnly === true) f.readOnly = true;
|
|
2502
|
+
if (n.archived === true) f.archived = true;
|
|
1834
2503
|
if (n.ui.access) f.access = { ...n.ui.access };
|
|
1835
2504
|
else if (n.readOnly === "developer") f.access = { edit: "schema.manage" };
|
|
1836
2505
|
if (n.lockReason !== void 0) f.lockReason = n.lockReason;
|
|
2506
|
+
const shopify = n.readOnly === true && n.lockReason === "A Shopify product id. No Shopify integration backs a reference in BetterCMS yet, so the id is kept as it is." && (n.type === "text" || n.type === "array" && n.config.itemType === "text");
|
|
2507
|
+
if (shopify) {
|
|
2508
|
+
delete f.lockReason;
|
|
2509
|
+
if (n.type === "text") {
|
|
2510
|
+
f.type = "reference";
|
|
2511
|
+
f.reference = { to: ["shopify"] };
|
|
2512
|
+
}
|
|
2513
|
+
}
|
|
1837
2514
|
if (n.localized !== void 0) f.localized = n.localized;
|
|
1838
2515
|
if (n.ui.hidden !== void 0) f.hidden = n.ui.hidden;
|
|
1839
2516
|
if (n.ui.rows !== void 0) f.rows = n.ui.rows;
|
|
@@ -1850,26 +2527,28 @@ function readToV2(n, at, siblings, ctx, top, lane) {
|
|
|
1850
2527
|
if (n.ui.input !== void 0) loss("ui/input", "ui.input", "Custom dock inputs are a dock feature V2 has no key for.");
|
|
1851
2528
|
if (n.fieldsetId !== void 0) {
|
|
1852
2529
|
const set = ctx.sets.get(n.fieldsetId);
|
|
1853
|
-
if (set?.kind === "tab")
|
|
1854
|
-
|
|
1855
|
-
|
|
2530
|
+
if (set?.kind === "tab") {
|
|
2531
|
+
if (top) f.group = set.id;
|
|
2532
|
+
else loss("fieldsetId", "fieldset", "Only top-level V2 fields sit in a tab; this nested field's tab is dropped.");
|
|
2533
|
+
} else if (set) {
|
|
1856
2534
|
f.fieldset = set.id;
|
|
1857
2535
|
if (top && set.tab !== void 0) f.group = set.tab;
|
|
1858
2536
|
} else loss("fieldsetId", "fieldset", `No fieldset "${n.fieldsetId}" exists on this model; the membership is dropped.`);
|
|
1859
2537
|
}
|
|
1860
2538
|
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;
|
|
1861
2540
|
for (const k of [
|
|
1862
2541
|
"target",
|
|
1863
2542
|
"stale",
|
|
1864
2543
|
"origin"
|
|
1865
2544
|
]) if (n[k] !== void 0) loss(k, k, k === "target" ? "A prop's target (where it writes in the component) is binding, not schema: V2 has no key for it, so the host keeps it." : `V2 has no "${k}" key.`);
|
|
1866
|
-
const used = new Set([
|
|
2545
|
+
const used = /* @__PURE__ */ new Set([
|
|
1867
2546
|
"placeholder",
|
|
1868
2547
|
"zones",
|
|
1869
2548
|
"options",
|
|
1870
2549
|
"fields"
|
|
1871
2550
|
]);
|
|
1872
|
-
const usedUi = new Set([
|
|
2551
|
+
const usedUi = /* @__PURE__ */ new Set([
|
|
1873
2552
|
"collapsed",
|
|
1874
2553
|
"reorderable",
|
|
1875
2554
|
"input",
|
|
@@ -1882,6 +2561,7 @@ function readToV2(n, at, siblings, ctx, top, lane) {
|
|
|
1882
2561
|
const use = (...k) => k.forEach((x) => used.add(x));
|
|
1883
2562
|
const useUi = (...k) => k.forEach((x) => usedUi.add(x));
|
|
1884
2563
|
if (lane === "props") useUi("group");
|
|
2564
|
+
if (lane === "props") useUi("tab");
|
|
1885
2565
|
if ([
|
|
1886
2566
|
"text",
|
|
1887
2567
|
"longtext",
|
|
@@ -1902,6 +2582,10 @@ function readToV2(n, at, siblings, ctx, top, lane) {
|
|
|
1902
2582
|
"max",
|
|
1903
2583
|
"step"
|
|
1904
2584
|
]) if (typeof cfg[k] === "number") numeric[k] = cfg[k];
|
|
2585
|
+
if (n.type === "rating") {
|
|
2586
|
+
if (numeric.step === V2_RATING_STEP) delete numeric.step;
|
|
2587
|
+
else if (numeric.step === void 0) numeric.step = 1;
|
|
2588
|
+
}
|
|
1905
2589
|
const ratingDefault = type === "rating" && n.type === "number" && ratingIsDefault(numeric);
|
|
1906
2590
|
if (typeof cfg.unit === "string") numeric.unit = cfg.unit;
|
|
1907
2591
|
if (Object.keys(numeric).length && !ratingDefault) f.numeric = numeric;
|
|
@@ -1920,6 +2604,12 @@ function readToV2(n, at, siblings, ctx, top, lane) {
|
|
|
1920
2604
|
useUi("control");
|
|
1921
2605
|
}
|
|
1922
2606
|
if (n.type === "select") use("multiSelect");
|
|
2607
|
+
if (n.type === "image") {
|
|
2608
|
+
use("media");
|
|
2609
|
+
if (cfg.media === "icon") f.svgOnly = true;
|
|
2610
|
+
}
|
|
2611
|
+
if (typeof cfg.linkHref === "string" && cfg.linkHref) f.linkHref = cfg.linkHref;
|
|
2612
|
+
use("linkHref");
|
|
1923
2613
|
if ((type === "select" || type === "multiselect" || type === "tags") && n.options) f.options = optionsFromProd(n.options);
|
|
1924
2614
|
if (type === "multiselect" || type === "tags") {
|
|
1925
2615
|
if (typeof cfg.min === "number") val.min = cfg.min;
|
|
@@ -1937,10 +2627,10 @@ function readToV2(n, at, siblings, ctx, top, lane) {
|
|
|
1937
2627
|
if (type === "date" || type === "datetime") use("timezone", "includeTime");
|
|
1938
2628
|
if ((type === "date" || type === "datetime") && typeof cfg.timezone === "string") f.timezone = cfg.timezone === "site" ? "site" : `fixed:${cfg.timezone}`;
|
|
1939
2629
|
if ((type === "date" || type === "datetime") && typeof cfg.timezone === "boolean") f.timezone = cfg.timezone;
|
|
1940
|
-
if (n.type === "reference" || n.type === "multi-reference" || n.type === "multiReference") use("contentModelId", "polymorphic", "allowedModelSlugs");
|
|
2630
|
+
if (n.type === "reference" || n.type === "multi-reference" || n.type === "multiReference") use("contentModelId", "polymorphic", "allowedModelSlugs", "targets", "filter");
|
|
1941
2631
|
if (n.type === "reference") {
|
|
1942
|
-
const
|
|
1943
|
-
if (
|
|
2632
|
+
const ref = referenceFromConfig(cfg);
|
|
2633
|
+
if (ref) f.reference = ref;
|
|
1944
2634
|
}
|
|
1945
2635
|
if (n.type === "form") f.reference = { to: ["form"] };
|
|
1946
2636
|
if (n.type === "object" || n.type === "group") {
|
|
@@ -1951,22 +2641,87 @@ function readToV2(n, at, siblings, ctx, top, lane) {
|
|
|
1951
2641
|
}
|
|
1952
2642
|
if (n.type === "array" && n.zones?.nonRepeatable) {
|
|
1953
2643
|
const nr = n.zones.nonRepeatable;
|
|
1954
|
-
const
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
2644
|
+
const fields = nr.map((c, i) => readToV2(c, `${at}/config/zones/nonRepeatable/${i}`, nr, ctx, false, lane));
|
|
2645
|
+
if (n.zones.repeatable) {
|
|
2646
|
+
const kids = [{
|
|
2647
|
+
name: "nonRepeatable",
|
|
2648
|
+
title: n.label,
|
|
2649
|
+
type: "object",
|
|
2650
|
+
fields
|
|
2651
|
+
}, listOf(n, n.zones.repeatable.fields, "repeatable", `${at}/config/zones/repeatable`, ctx, lane)];
|
|
2652
|
+
ctx.onLoss(`${at}/config/zones`, "zone envelope", "A zone pair reads as an object with nonRepeatable and repeatable children, matching its stored {nonRepeatable, repeatable} value.");
|
|
2653
|
+
Object.assign(f, {
|
|
2654
|
+
type: "object",
|
|
2655
|
+
fields: kids
|
|
2656
|
+
});
|
|
2657
|
+
} else {
|
|
2658
|
+
Object.assign(f, {
|
|
2659
|
+
type: "object",
|
|
2660
|
+
fields
|
|
2661
|
+
});
|
|
2662
|
+
ctx.zoned.add(f);
|
|
2663
|
+
}
|
|
2664
|
+
} else if (slotProp) {
|
|
2665
|
+
const ids = Array.isArray(cfg.componentIds) ? cfg.componentIds.filter((x) => typeof x === "string") : [];
|
|
2666
|
+
const names = Array.isArray(cfg.allow) ? cfg.allow.filter((x) => typeof x === "string") : [];
|
|
2667
|
+
f.of = ids.length ? {
|
|
2668
|
+
type: "block",
|
|
2669
|
+
allow: ids
|
|
2670
|
+
} : names.length ? {
|
|
2671
|
+
type: "block",
|
|
2672
|
+
allow: names
|
|
2673
|
+
} : { type: "block" };
|
|
2674
|
+
ctx.slots.set(f, cfg.multiple === true);
|
|
2675
|
+
const settings = Array.isArray(cfg.slotSettings) ? cfg.slotSettings.map(readProp) : [];
|
|
2676
|
+
if (settings.length) f.slotSettings = settings.map((c, k) => readToV2(c, `${at}/config/slotSettings/${k}`, settings, ctx, false, lane));
|
|
2677
|
+
if (cfg.multiple !== true) {
|
|
2678
|
+
val.max = 1;
|
|
2679
|
+
loss("config/multiple", "slot single", "A single slot holds one component instance; V2 reads it as a slot of at most one block.");
|
|
2680
|
+
} else {
|
|
2681
|
+
if (typeof cfg.minItems === "number") val.min = cfg.minItems;
|
|
2682
|
+
if (typeof cfg.maxItems === "number") val.max = cfg.maxItems;
|
|
2683
|
+
}
|
|
2684
|
+
use("multiple", "componentIds", "allow", "minItems", "maxItems", "slotSettings");
|
|
2685
|
+
} else if (blockSlot) {
|
|
2686
|
+
const slugs = Array.isArray(cfg.blockSlugs) ? cfg.blockSlugs.filter((x) => typeof x === "string") : [];
|
|
2687
|
+
f.of = slugs.length ? {
|
|
2688
|
+
type: "block",
|
|
2689
|
+
allow: slugs.map(camel)
|
|
2690
|
+
} : { type: "block" };
|
|
2691
|
+
ctx.blocks.add(f);
|
|
2692
|
+
const settings = Array.isArray(cfg.slotSettings) ? cfg.slotSettings.map(readField) : [];
|
|
2693
|
+
if (settings.length) f.slotSettings = settings.map((c, k) => readToV2(c, `${at}/config/slotSettings/${k}`, settings, ctx, false, lane));
|
|
2694
|
+
if (typeof cfg.minItems === "number") val.min = cfg.minItems;
|
|
2695
|
+
if (typeof cfg.maxItems === "number") val.max = cfg.maxItems;
|
|
2696
|
+
use("blockSlugs", "minItems", "maxItems", "slotSettings");
|
|
2697
|
+
} else if (lane === "props" && n.type === "table" && cfg.mode === "types") {
|
|
2698
|
+
f.of = (Array.isArray(cfg.itemTypes) ? cfg.itemTypes : []).map((t, j) => {
|
|
2699
|
+
const kids = (t.fields ?? []).map(readProp);
|
|
2700
|
+
const item = {
|
|
2701
|
+
name: t.name,
|
|
2702
|
+
title: t.label ?? t.name,
|
|
2703
|
+
type: "object",
|
|
2704
|
+
fields: kids.map((c, k) => readToV2(c, `${at}/config/itemTypes/${j}/fields/${k}`, kids, ctx, false, lane))
|
|
2705
|
+
};
|
|
2706
|
+
if (t.icon) item.icon = tablerIconOf(t.icon);
|
|
2707
|
+
if (t.preview) item.preview = previewFromProd(t.preview, kids);
|
|
2708
|
+
return item;
|
|
1965
2709
|
});
|
|
2710
|
+
ctx.types.add(f);
|
|
2711
|
+
if (n.ui.itemLabel !== void 0) f.itemNoun = n.ui.itemLabel.toLowerCase();
|
|
2712
|
+
if (n.ui.icon) f.icon = tablerIconOf(n.ui.icon);
|
|
2713
|
+
const l = n.ui.layout;
|
|
2714
|
+
if (l === "grid" || l === "list") f.arrayLayout = l;
|
|
2715
|
+
else if (l === "rows") f.layout = "list";
|
|
2716
|
+
else if (l) loss("ui/layout", "ui.layout", `V2 has no "${l}" layout for a list of item types.`);
|
|
2717
|
+
if (typeof cfg.minItems === "number") val.min = cfg.minItems;
|
|
2718
|
+
if (typeof cfg.maxItems === "number") val.max = cfg.maxItems;
|
|
2719
|
+
use("mode", "itemTypes", "minItems", "maxItems");
|
|
2720
|
+
useUi("itemLabel", "icon", "layout");
|
|
1966
2721
|
} else if (dataTable) {
|
|
1967
2722
|
f.table = tableOptionsFromConfig(cfg);
|
|
1968
2723
|
use("mode", "columnTypes", "lockColumns", "requireCaption", "allowGroups", "allowFootnotes", "allowNote", "minRows", "maxRows", "maxColumns", "settings", "jsonLd");
|
|
1969
|
-
} else if (n.type === "array" && n.zones?.repeatable || n.type === "repeater" || n.type === "table") {
|
|
2724
|
+
} else if (n.type === "array" && (n.zones?.repeatable || !n.zones && !cfg.itemType && n.fields?.length) || n.type === "repeater" || n.type === "table") {
|
|
1970
2725
|
const list = listOf(n, n.zones?.repeatable?.fields ?? n.fields ?? [], n.key, at, ctx, lane);
|
|
1971
2726
|
useUi("preview", "icon", "itemLabel", "layout", "itemName", "itemTitle");
|
|
1972
2727
|
if (n.zones?.repeatable) ctx.zoned.add(f);
|
|
@@ -1982,14 +2737,19 @@ function readToV2(n, at, siblings, ctx, top, lane) {
|
|
|
1982
2737
|
if (typeof r?.maxItems === "number") val.max = r.maxItems;
|
|
1983
2738
|
if (n.type === "table") use("minItems", "maxItems");
|
|
1984
2739
|
} else if (n.type === "array" && cfg.itemType) {
|
|
1985
|
-
f.of = [{
|
|
2740
|
+
f.of = [shopify ? {
|
|
2741
|
+
...itemOf(n),
|
|
2742
|
+
type: "reference",
|
|
2743
|
+
reference: { to: ["shopify"] }
|
|
2744
|
+
} : {
|
|
1986
2745
|
...itemOf(n),
|
|
1987
|
-
type: cfg.itemType === "text" ? "string" : cfg.itemType
|
|
2746
|
+
type: cfg.itemType === "text" ? "string" : cfg.itemType,
|
|
2747
|
+
...itemSettingsFromProd(cfg.item)
|
|
1988
2748
|
}];
|
|
1989
2749
|
leafListChrome(n, f, loss, "a list of scalars");
|
|
1990
2750
|
if (typeof cfg.minItems === "number") val.min = cfg.minItems;
|
|
1991
2751
|
if (typeof cfg.maxItems === "number") val.max = cfg.maxItems;
|
|
1992
|
-
use("itemType", "minItems", "maxItems");
|
|
2752
|
+
use("itemType", "minItems", "maxItems", "item");
|
|
1993
2753
|
useUi("layout", "itemLabel", "itemName", "itemTitle");
|
|
1994
2754
|
} else if (n.type === "modular") {
|
|
1995
2755
|
const slugs = cfg.blockSlugs ?? [];
|
|
@@ -2026,11 +2786,11 @@ function readToV2(n, at, siblings, ctx, top, lane) {
|
|
|
2026
2786
|
use("blockSlugs", "minItems", "maxItems");
|
|
2027
2787
|
useUi("itemLabel", "icon", "layout", "blocks");
|
|
2028
2788
|
} else if (n.type === "multi-reference" || n.type === "multiReference") {
|
|
2029
|
-
const
|
|
2789
|
+
const ref = referenceFromConfig(cfg);
|
|
2030
2790
|
f.of = [{
|
|
2031
2791
|
...itemOf(n),
|
|
2032
2792
|
type: "reference",
|
|
2033
|
-
...
|
|
2793
|
+
...ref ? { reference: ref } : {}
|
|
2034
2794
|
}];
|
|
2035
2795
|
leafListChrome(n, f, loss, "a list of entries");
|
|
2036
2796
|
if (typeof cfg.min === "number") val.min = cfg.min;
|
|
@@ -2039,16 +2799,47 @@ function readToV2(n, at, siblings, ctx, top, lane) {
|
|
|
2039
2799
|
useUi("layout", "itemLabel", "itemName", "itemTitle");
|
|
2040
2800
|
}
|
|
2041
2801
|
if (n.type === "array" && n.zones?.nonRepeatable && n.zones.repeatable) useUi("preview", "icon", "itemLabel", "layout");
|
|
2042
|
-
for (const [k, x] of Object.entries(cfg))
|
|
2802
|
+
for (const [k, x] of Object.entries(cfg)) {
|
|
2803
|
+
if (x === void 0 || used.has(k)) continue;
|
|
2804
|
+
if (isHostConfigKey(n.type, k) || isHostConfigKey(type, k)) loss(`config/${k}`, "host config", CATALOG["host config"]);
|
|
2805
|
+
else loss(`config/${k}`, "config", `V2 has no "${k}" setting on a ${type} field.`);
|
|
2806
|
+
}
|
|
2043
2807
|
for (const [k, x] of Object.entries(n.ui)) if (x !== void 0 && !usedUi.has(k)) loss(`ui/${k}`, `ui.${k}`, `V2 has no ui.${k} on a ${type} field.`);
|
|
2044
2808
|
if (n.defaultValue !== void 0 || top && ctx.plans) {
|
|
2045
|
-
const plan = readPlan(f, n.type, ctx.zoned, ctx.modular);
|
|
2809
|
+
const plan = readPlan(f, n.type, ctx.zoned, ctx.modular, ctx.types, ctx.slots, ctx.blocks);
|
|
2046
2810
|
if (top) ctx.plans?.set(f.name, plan);
|
|
2047
2811
|
if (n.defaultValue !== void 0) f.initialValue = planFromProd(plan, n.defaultValue, (rel, reason) => loss(`defaultValue${rel}`, "stored value", reason));
|
|
2048
2812
|
}
|
|
2049
2813
|
if (Object.keys(val).length) f.validation = val;
|
|
2050
2814
|
return f;
|
|
2051
2815
|
}
|
|
2816
|
+
/** config.item → the V2 item field's description, localized flag and validation (in V2's key order). */
|
|
2817
|
+
function itemSettingsFromProd(item) {
|
|
2818
|
+
if (!isObj(item)) return {};
|
|
2819
|
+
const s = item;
|
|
2820
|
+
const out = {};
|
|
2821
|
+
const val = {};
|
|
2822
|
+
if (s.required !== void 0) val.required = s.required;
|
|
2823
|
+
if (s.minLength !== void 0) val.min = s.minLength;
|
|
2824
|
+
if (s.maxLength !== void 0) val.max = s.maxLength;
|
|
2825
|
+
if (s.pattern !== void 0) val.pattern = s.pattern;
|
|
2826
|
+
if (s.patternMessage !== void 0) val.patternMessage = s.patternMessage;
|
|
2827
|
+
if (Object.keys(val).length) out.validation = val;
|
|
2828
|
+
if (s.localized !== void 0) out.localized = s.localized;
|
|
2829
|
+
if (s.helpText !== void 0) out.description = s.helpText;
|
|
2830
|
+
return out;
|
|
2831
|
+
}
|
|
2832
|
+
/** A reference config → the V2 `reference`: entry models first, then config.targets; config.filter as written. */
|
|
2833
|
+
function referenceFromConfig(cfg) {
|
|
2834
|
+
const entries = cfg.polymorphic ? cfg.allowedModelSlugs ?? [] : cfg.contentModelId ? [cfg.contentModelId] : [];
|
|
2835
|
+
const targets = Array.isArray(cfg.targets) ? cfg.targets.filter((t) => typeof t === "string") : [];
|
|
2836
|
+
const to = [...entries, ...targets];
|
|
2837
|
+
if (!to.length && typeof cfg.filter !== "string") return void 0;
|
|
2838
|
+
return {
|
|
2839
|
+
to,
|
|
2840
|
+
...typeof cfg.filter === "string" ? { filter: cfg.filter } : {}
|
|
2841
|
+
};
|
|
2842
|
+
}
|
|
2052
2843
|
/** A list of scalars or entries: its item's name and title (ui.itemName / ui.itemTitle, else the convention). */
|
|
2053
2844
|
var itemOf = (n) => {
|
|
2054
2845
|
const conv = conventionItem(n.key, n.label);
|
|
@@ -2100,6 +2891,9 @@ function toTypeSchema(model, opts = {}) {
|
|
|
2100
2891
|
sets: /* @__PURE__ */ new Map(),
|
|
2101
2892
|
zoned: /* @__PURE__ */ new WeakSet(),
|
|
2102
2893
|
modular: /* @__PURE__ */ new WeakSet(),
|
|
2894
|
+
types: /* @__PURE__ */ new WeakSet(),
|
|
2895
|
+
slots: /* @__PURE__ */ new WeakMap(),
|
|
2896
|
+
blocks: /* @__PURE__ */ new WeakSet(),
|
|
2103
2897
|
blockModels: new Map((opts.blockModels ?? []).map((m) => [m.slug, m])),
|
|
2104
2898
|
plans: opts.plans
|
|
2105
2899
|
};
|
|
@@ -2156,6 +2950,9 @@ function propsToTypeSchema(component, opts = {}) {
|
|
|
2156
2950
|
sets: /* @__PURE__ */ new Map(),
|
|
2157
2951
|
zoned: /* @__PURE__ */ new WeakSet(),
|
|
2158
2952
|
modular: /* @__PURE__ */ new WeakSet(),
|
|
2953
|
+
types: /* @__PURE__ */ new WeakSet(),
|
|
2954
|
+
slots: /* @__PURE__ */ new WeakMap(),
|
|
2955
|
+
blocks: /* @__PURE__ */ new WeakSet(),
|
|
2159
2956
|
blockModels: new Map((opts.blockModels ?? []).map((m) => [m.slug, m])),
|
|
2160
2957
|
plans: opts.plans
|
|
2161
2958
|
};
|
|
@@ -2186,6 +2983,23 @@ function propsToTypeSchema(component, opts = {}) {
|
|
|
2186
2983
|
const at = new Map(fieldsets.map((s, i) => [s.name, i]));
|
|
2187
2984
|
fieldsets.sort((a, b) => (order.get(a.name) ?? at.get(a.name)) - (order.get(b.name) ?? at.get(b.name)));
|
|
2188
2985
|
}
|
|
2986
|
+
const groups = [];
|
|
2987
|
+
const tabOrder = /* @__PURE__ */ new Map();
|
|
2988
|
+
for (const t of [...nodes.map((n) => n.ui.tab), ...component.tabs ?? []]) {
|
|
2989
|
+
if (!t || groups.some((g) => g.name === t.id)) continue;
|
|
2990
|
+
const g = {
|
|
2991
|
+
name: t.id,
|
|
2992
|
+
title: t.label ?? t.id
|
|
2993
|
+
};
|
|
2994
|
+
if (t.icon) g.icon = tablerIconOf(t.icon);
|
|
2995
|
+
if (typeof t.order === "number") tabOrder.set(t.id, t.order);
|
|
2996
|
+
groups.push(g);
|
|
2997
|
+
}
|
|
2998
|
+
if (tabOrder.size) {
|
|
2999
|
+
const at = new Map(groups.map((g, i) => [g.name, i]));
|
|
3000
|
+
groups.sort((a, b) => (tabOrder.get(a.name) ?? at.get(a.name)) - (tabOrder.get(b.name) ?? at.get(b.name)));
|
|
3001
|
+
}
|
|
3002
|
+
if (groups.length) groups[0].default = true;
|
|
2189
3003
|
const out = {
|
|
2190
3004
|
name: camel(component.slug),
|
|
2191
3005
|
title: component.name,
|
|
@@ -2194,10 +3008,13 @@ function propsToTypeSchema(component, opts = {}) {
|
|
|
2194
3008
|
};
|
|
2195
3009
|
if (component.description !== void 0 && component.description !== null) out.description = component.description;
|
|
2196
3010
|
if (component.category !== void 0 && component.category !== "custom") out.category = capitalize(component.category);
|
|
3011
|
+
if (component.icon) out.icon = tablerIconOf(component.icon);
|
|
3012
|
+
if (component.preview) out.preview = previewFromProd(component.preview, nodes);
|
|
2197
3013
|
if (fieldsets.length) out.fieldsets = fieldsets;
|
|
3014
|
+
if (groups.length) out.groups = groups;
|
|
2198
3015
|
return out;
|
|
2199
3016
|
}
|
|
2200
3017
|
//#endregion
|
|
2201
|
-
export { CATEGORY_TO_PROD, fromTypeSchema, leafValuePlan, planFromProd, planToProd, propsToTypeSchema, toTypeSchema };
|
|
3018
|
+
export { CATEGORY_TO_PROD, SHOPIFY_REF_LOCK, fromTypeSchema, leafValuePlan, planFromProd, planToProd, propsToTypeSchema, schemaSlugOf, toTypeSchema };
|
|
2202
3019
|
|
|
2203
3020
|
//# sourceMappingURL=schema.js.map
|