@bettercms-ai/kit 1.0.0 → 2.0.0-next.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/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 +94 -31
- package/dist/adapters/lossy.js +419 -0
- package/dist/adapters/lossy.js.map +1 -0
- package/{adapters → dist/adapters}/prod-types.d.ts +91 -26
- package/{adapters → dist/adapters}/prod-types.js +82 -13
- package/dist/adapters/prod-types.js.map +1 -0
- package/{adapters → dist/adapters}/schema.d.ts +40 -1
- package/{adapters → dist/adapters}/schema.js +1038 -204
- 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} +131 -2
- package/{context.js → dist/context.js} +44 -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/dist/controls/form-picker-register.d.ts +7 -0
- package/{controls → dist/controls}/form-picker-register.js +2 -6
- 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 +116 -200
- 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 +59 -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 +21 -4
- package/{controls → dist/controls}/media.js +407 -130
- 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/article-shell.d.ts +145 -0
- package/dist/controls/rich-text/article-shell.js +510 -0
- package/dist/controls/rich-text/article-shell.js.map +1 -0
- package/dist/controls/rich-text/author.d.ts +25 -0
- package/dist/controls/rich-text/author.js +104 -0
- package/dist/controls/rich-text/author.js.map +1 -0
- package/dist/controls/rich-text/blocks.d.ts +60 -0
- package/{controls → dist/controls}/rich-text/blocks.js +164 -389
- package/dist/controls/rich-text/blocks.js.map +1 -0
- package/dist/controls/rich-text/button.d.ts +23 -0
- package/dist/controls/rich-text/button.js +85 -0
- package/dist/controls/rich-text/button.js.map +1 -0
- package/{controls → dist/controls}/rich-text/catalog.d.ts +7 -4
- package/{controls → dist/controls}/rich-text/catalog.js +94 -68
- package/dist/controls/rich-text/catalog.js.map +1 -0
- package/dist/controls/rich-text/checklist.d.ts +24 -0
- package/dist/controls/rich-text/checklist.js +115 -0
- package/dist/controls/rich-text/checklist.js.map +1 -0
- package/{controls → dist/controls}/rich-text/codec.d.ts +9 -1
- package/{controls → dist/controls}/rich-text/codec.js +7 -2
- package/dist/controls/rich-text/codec.js.map +1 -0
- package/dist/controls/rich-text/columns.d.ts +41 -0
- package/dist/controls/rich-text/columns.js +181 -0
- package/dist/controls/rich-text/columns.js.map +1 -0
- package/{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 +53 -9
- package/{controls → dist/controls}/rich-text/dom.js +388 -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 +226 -44
- package/dist/controls/rich-text/editor.js.map +1 -0
- package/dist/controls/rich-text/embed.d.ts +28 -0
- package/dist/controls/rich-text/embed.js +210 -0
- package/dist/controls/rich-text/embed.js.map +1 -0
- package/{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/dist/controls/rich-text/footnote.d.ts +41 -0
- package/dist/controls/rich-text/footnote.js +185 -0
- package/dist/controls/rich-text/footnote.js.map +1 -0
- package/dist/controls/rich-text/gallery.d.ts +28 -0
- package/dist/controls/rich-text/gallery.js +167 -0
- package/dist/controls/rich-text/gallery.js.map +1 -0
- package/{controls → dist/controls}/rich-text/index.js +1 -1
- package/dist/controls/rich-text/index.js.map +1 -0
- package/{controls → dist/controls}/rich-text/link-form.d.ts +3 -1
- 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/dist/controls/rich-text/related.d.ts +36 -0
- package/dist/controls/rich-text/related.js +213 -0
- package/dist/controls/rich-text/related.js.map +1 -0
- package/dist/controls/rich-text/toc.d.ts +46 -0
- package/dist/controls/rich-text/toc.js +161 -0
- package/dist/controls/rich-text/toc.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/dist/controls/slot-register.d.ts +6 -0
- package/{controls → dist/controls}/slot-register.js +2 -5
- 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 +70 -0
- package/dist/core/core.js +187 -0
- package/dist/core/core.js.map +1 -0
- package/dist/core/facets.d.ts +355 -0
- package/dist/core/facets.js +342 -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 +58 -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 +1511 -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 +36 -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 +58 -0
- package/dist/ui/autocomplete.js +194 -0
- package/dist/ui/autocomplete.js.map +1 -0
- package/{ui → dist/ui}/button.d.ts +3 -3
- package/{ui → dist/ui}/button.js +8 -11
- 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 +83 -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.d.ts +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.d.ts +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.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/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.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,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CATALOG, FEATURES, isHostConfigKey } from "./lossy.js";
|
|
2
|
+
import { CONTROL_TYPES, FIELDSET_DESCRIPTION_MAX, FIELD_HELP_MAX, HELP_MORE_MAX, ITEM_NAME_RE, MAX_FIELD_DEPTH, OPTION_DESCRIPTION_MAX, PROP_GROUP_DESCRIPTION_MAX, PROP_HELP_MAX, PROP_PLACEHOLDER_MAX, PROP_TAB_MAX, TAB_MAX as TAB_MAX$1, UI_CONTROLS, UI_PLACEHOLDER_MAX } from "./prod-types.js";
|
|
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
|
-
|
|
6
|
+
import { buttonFromProd, buttonToProd, datetimeFromProd, datetimeToProd, imageFromProd, imageToProd, isCropRect, linkFromProd, linkToProd, listFromProd, listToProd, ratingFromProd, ratingToProd, referenceFromProd, referenceToProd, scaleFromProd, scaleToProd, typedRowsFromProd, typedRowsToProd, videoFromProd, videoToProd, zoneListFromProd, zoneListToProd } from "./values.js";
|
|
7
|
+
import { BLOCK_FIELD_TYPES_RENDERABLE_NOW, KEY_FORMAT, PRIMITIVE_ARRAY_RULE, RICHTEXT_FEATURES, isReservedKey, normaliseRichTextFeatures } from "@bettercms-ai/types";
|
|
8
|
+
//#region src/adapters/schema.ts
|
|
7
9
|
var isObj = (v) => !!v && typeof v === "object" && !Array.isArray(v);
|
|
8
10
|
function deepEqual(a, b) {
|
|
9
11
|
if (a === b) return true;
|
|
@@ -14,6 +16,8 @@ function deepEqual(a, b) {
|
|
|
14
16
|
var singular = (t) => t.endsWith("ies") ? `${t.slice(0, -3)}y` : t.endsWith("s") && !t.endsWith("ss") ? t.slice(0, -1) : t;
|
|
15
17
|
var kebab = (s) => s.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "") || "schema";
|
|
16
18
|
var camel = (s) => s.replace(/-([a-z0-9])/g, (_, c) => c.toUpperCase());
|
|
19
|
+
/** The slug a V2 schema name is stored under (a component's, when the host seeds a /kit block): `textBlock` → `text-block`. */
|
|
20
|
+
var schemaSlugOf = kebab;
|
|
17
21
|
var capitalize = (s) => s.charAt(0).toUpperCase() + s.slice(1);
|
|
18
22
|
var ZONE_NAMES = new Set(typeof Intl.supportedValuesOf === "function" ? [...Intl.supportedValuesOf("timeZone"), "UTC"] : ["UTC"]);
|
|
19
23
|
/** An IANA zone name (isTimeZoneName): ICU's canonical list, or a current name Intl itself accepts (Asia/Kolkata). */
|
|
@@ -94,7 +98,7 @@ var PROP_TYPE = {
|
|
|
94
98
|
code: "code"
|
|
95
99
|
};
|
|
96
100
|
/** Field types whose `config` the backend parses strictly (unknown keys stripped or refused). */
|
|
97
|
-
var STRICT_CONFIG = new Set([
|
|
101
|
+
var STRICT_CONFIG = /* @__PURE__ */ new Set([
|
|
98
102
|
"array",
|
|
99
103
|
"reference",
|
|
100
104
|
"multi-reference",
|
|
@@ -107,7 +111,9 @@ var STRICT_CONFIG = new Set([
|
|
|
107
111
|
"tags",
|
|
108
112
|
"rating",
|
|
109
113
|
"code",
|
|
110
|
-
"video"
|
|
114
|
+
"video",
|
|
115
|
+
"table",
|
|
116
|
+
"slot"
|
|
111
117
|
]);
|
|
112
118
|
/** V2 list item types → prod `config.itemType` (ARRAY_ITEM_TYPES); a V2 `text` item reads back as `string`. */
|
|
113
119
|
var PRIM_ITEM = {
|
|
@@ -125,6 +131,23 @@ var ENTRY_TARGET = (t) => ![
|
|
|
125
131
|
"shopify",
|
|
126
132
|
"collection"
|
|
127
133
|
].includes(t);
|
|
134
|
+
/** The non-entry targets a prop reference stores in config.targets (backend reference-target-config.ts REF_TARGET_KINDS). */
|
|
135
|
+
var REF_TARGET_KINDS = [
|
|
136
|
+
"page",
|
|
137
|
+
"form",
|
|
138
|
+
"collection"
|
|
139
|
+
];
|
|
140
|
+
/**
|
|
141
|
+
* A prop reference whose only target is Shopify (backend reference-target-config.ts UNSUPPORTED_TARGETS refuses it by
|
|
142
|
+
* name) is stored as locked text holding the id (a list of them: a list of text), so the value stays the plain gid
|
|
143
|
+
* string V2 holds. This lock reason is the marker the read side turns back into V2's reference (allowed deviation
|
|
144
|
+
* "shopify reference").
|
|
145
|
+
*/
|
|
146
|
+
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.";
|
|
147
|
+
var shopifyOnly = (r) => !!r?.to?.length && r.to.every((t) => t === "shopify");
|
|
148
|
+
/** backend REFERENCE_FILTER_MAX; parameters ($x) and the parent document (^) are refused there (reference_filter_invalid). */
|
|
149
|
+
var REFERENCE_FILTER_MAX = 500;
|
|
150
|
+
var filterKept = (f) => typeof f === "string" && f.trim() !== "" && f.length <= REFERENCE_FILTER_MAX && !/[$^]/.test(f);
|
|
128
151
|
/** The old rating: a number with ui.control "rating" and these bounds read back as no `numeric` (read side only). */
|
|
129
152
|
var RATING_CONFIG = {
|
|
130
153
|
min: 0,
|
|
@@ -132,6 +155,12 @@ var RATING_CONFIG = {
|
|
|
132
155
|
step: .5
|
|
133
156
|
};
|
|
134
157
|
/**
|
|
158
|
+
* 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
|
|
159
|
+
* 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
|
|
160
|
+
* scale) and that step reads back as none; a prod rating with no step reads back as its real step, 1.
|
|
161
|
+
*/
|
|
162
|
+
var V2_RATING_STEP = .1;
|
|
163
|
+
/**
|
|
135
164
|
* V2 block-picker category (KitCategory, and the core examples' own) → the nearest prod ComponentCategory. A category
|
|
136
165
|
* with no row has no prod twin; the server defaults the component to "custom".
|
|
137
166
|
*/
|
|
@@ -154,33 +183,22 @@ var CATEGORY_TO_PROD = {
|
|
|
154
183
|
Content: "content",
|
|
155
184
|
Layout: "section"
|
|
156
185
|
};
|
|
157
|
-
/** The field types a kind:'block' model
|
|
158
|
-
var BLOCK_FIELD_TYPES = new Set(
|
|
159
|
-
|
|
160
|
-
"longtext",
|
|
161
|
-
"richtext",
|
|
162
|
-
"image",
|
|
163
|
-
"link",
|
|
164
|
-
"slug",
|
|
165
|
-
"email",
|
|
166
|
-
"phone",
|
|
167
|
-
"color",
|
|
168
|
-
"select",
|
|
169
|
-
"number",
|
|
170
|
-
"rating",
|
|
171
|
-
"date",
|
|
172
|
-
"datetime",
|
|
173
|
-
"boolean"
|
|
174
|
-
]);
|
|
175
|
-
/** A prop's config.minItems / maxItems cap (SLOT_ITEMS_CAP, componentPropDefSchema). */
|
|
186
|
+
/** The field types a kind:'block' model holds today: the ones a block primitive renders (types, staged to G7). */
|
|
187
|
+
var BLOCK_FIELD_TYPES = new Set(BLOCK_FIELD_TYPES_RENDERABLE_NOW);
|
|
188
|
+
/** A slot prop's config.minItems / maxItems cap (SLOT_ITEMS_CAP, componentPropDefSchema). */
|
|
176
189
|
var SLOT_ITEMS_CAP = 50;
|
|
190
|
+
/** A table prop's rows and an array prop's items: their config.minItems / maxItems cap (LIST_ITEMS_CAP). */
|
|
191
|
+
var LIST_ITEMS_CAP = 500;
|
|
192
|
+
/** backend slotAllowIssues: a slot's config.allow holds 1–50 block names of 1–64 characters, no repeats. */
|
|
193
|
+
var SLOT_ALLOW_MAX = 50;
|
|
194
|
+
var SLOT_ALLOW_NAME_MAX = 64;
|
|
177
195
|
/** Backend dock-vocabulary.ts SLIDER_MAX_STOPS: a slider's (max − min) / step. */
|
|
178
196
|
var SLIDER_MAX_STOPS = 1e3;
|
|
179
197
|
/**
|
|
180
198
|
* The field types prod's unique flag accepts (uniqueFlagRules): a comparable scalar (UNIQUE_FIELD_TYPES, no two entries
|
|
181
199
|
* share it; a reference only to one model) or a list (UNIQUE_ITEMS_FIELD_TYPES, no item repeats).
|
|
182
200
|
*/
|
|
183
|
-
var UNIQUE_TYPES = new Set([
|
|
201
|
+
var UNIQUE_TYPES = /* @__PURE__ */ new Set([
|
|
184
202
|
"text",
|
|
185
203
|
"longtext",
|
|
186
204
|
"slug",
|
|
@@ -197,14 +215,14 @@ var UNIQUE_TYPES = new Set([
|
|
|
197
215
|
"multi-reference"
|
|
198
216
|
]);
|
|
199
217
|
/** 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([
|
|
218
|
+
var UNIQUE_LIST_PROPS = /* @__PURE__ */ new Set([
|
|
201
219
|
"multiselect",
|
|
202
220
|
"tags",
|
|
203
221
|
"multi-reference",
|
|
204
222
|
"table",
|
|
205
223
|
"array"
|
|
206
224
|
]);
|
|
207
|
-
var UNIQUE_ROW_PROPS = new Set([
|
|
225
|
+
var UNIQUE_ROW_PROPS = /* @__PURE__ */ new Set([
|
|
208
226
|
"text",
|
|
209
227
|
"url",
|
|
210
228
|
"slug",
|
|
@@ -215,19 +233,19 @@ var UNIQUE_ROW_PROPS = new Set([
|
|
|
215
233
|
"date"
|
|
216
234
|
]);
|
|
217
235
|
/** Types measured by minLength / maxLength (fields: LENGTH_FIELD_TYPES; props: LENGTH_TWIN), and those that take a pattern. */
|
|
218
|
-
var LENGTH_FIELDS = new Set([
|
|
236
|
+
var LENGTH_FIELDS = /* @__PURE__ */ new Set([
|
|
219
237
|
"text",
|
|
220
238
|
"longtext",
|
|
221
239
|
"richtext",
|
|
222
240
|
"document"
|
|
223
241
|
]);
|
|
224
|
-
var LENGTH_PROPS = new Set([
|
|
242
|
+
var LENGTH_PROPS = /* @__PURE__ */ new Set([
|
|
225
243
|
"text",
|
|
226
244
|
"url",
|
|
227
245
|
"longtext",
|
|
228
246
|
"richtext"
|
|
229
247
|
]);
|
|
230
|
-
var PATTERN_TYPES = new Set([
|
|
248
|
+
var PATTERN_TYPES = /* @__PURE__ */ new Set([
|
|
231
249
|
"text",
|
|
232
250
|
"longtext",
|
|
233
251
|
"url"
|
|
@@ -236,7 +254,7 @@ var PATTERN_TYPES = new Set([
|
|
|
236
254
|
* Leaf types whose value is an object a dotted preview path may read into (previewPathProblem OBJECT_VALUE_TYPES), and the
|
|
237
255
|
* keys an image or video value holds (LEAF_VALUE_KEYS). V2 reads `image.alt`; prod stores the key as `altText`.
|
|
238
256
|
*/
|
|
239
|
-
var OBJECT_VALUE_TYPES = new Set([
|
|
257
|
+
var OBJECT_VALUE_TYPES = /* @__PURE__ */ new Set([
|
|
240
258
|
"image",
|
|
241
259
|
"link",
|
|
242
260
|
"button",
|
|
@@ -268,6 +286,8 @@ var LEAF_VALUE_KEYS = {
|
|
|
268
286
|
]
|
|
269
287
|
};
|
|
270
288
|
var IMAGE_PATH_KEY = { alt: "altText" };
|
|
289
|
+
/** The keys of a data table's value a preview path may end on (previewPathProblem `<table>.caption` / `.notes`). */
|
|
290
|
+
var TABLE_PATH_KEYS = ["caption", "notes"];
|
|
271
291
|
var lose = (ctx, path, feature) => ctx.lossy.push({
|
|
272
292
|
path,
|
|
273
293
|
feature,
|
|
@@ -279,7 +299,7 @@ var cat = (ctx, path, feature) => ctx.catalog.push({
|
|
|
279
299
|
reason: CATALOG[feature]
|
|
280
300
|
});
|
|
281
301
|
/** Keys every type keeps, including a field degraded to json. */
|
|
282
|
-
var COMMON_KEYS = new Set([
|
|
302
|
+
var COMMON_KEYS = /* @__PURE__ */ new Set([
|
|
283
303
|
"name",
|
|
284
304
|
"title",
|
|
285
305
|
"type",
|
|
@@ -296,14 +316,54 @@ var COMMON_KEYS = new Set([
|
|
|
296
316
|
"advanced",
|
|
297
317
|
"localized",
|
|
298
318
|
"ai",
|
|
299
|
-
"placeholder"
|
|
319
|
+
"placeholder",
|
|
320
|
+
"archived"
|
|
300
321
|
]);
|
|
301
|
-
|
|
322
|
+
/** Types a slot setting may not be (backend slotSettingsHardening, and a model slot's SLOT_SETTINGS_NESTING: leaf fields only). */
|
|
323
|
+
var SETTING_NESTING_TYPES = /* @__PURE__ */ new Set([
|
|
324
|
+
"object",
|
|
325
|
+
"group",
|
|
326
|
+
"array",
|
|
327
|
+
"table",
|
|
328
|
+
"slot",
|
|
329
|
+
"form",
|
|
330
|
+
"modular"
|
|
331
|
+
]);
|
|
332
|
+
/** backend slotSettingsHardening: at most this many per-child settings. */
|
|
333
|
+
var SLOT_SETTINGS_MAX = 20;
|
|
334
|
+
/** backend ITEM_TYPE_NAME (what a row's `_type` holds), and an item type label's cap. */
|
|
335
|
+
var ITEM_TYPE_NAME = /^[a-zA-Z][a-zA-Z0-9_-]{0,63}$/;
|
|
336
|
+
var ITEM_TYPE_LABEL_MAX = 120;
|
|
337
|
+
function shapeOf(f, lv, ctx, top, nest) {
|
|
338
|
+
const shape = shapeOfField(f, lv, ctx, top);
|
|
339
|
+
if (nest === "setting" && SETTING_NESTING_TYPES.has(shape.type)) return {
|
|
340
|
+
kind: "json",
|
|
341
|
+
type: "json",
|
|
342
|
+
feature: "slotSettings"
|
|
343
|
+
};
|
|
344
|
+
return shape;
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* The key a model field is stored under: a V2 name the API refuses (types' isReservedKey, the API lane: `derived`,
|
|
348
|
+
* `layout`, `page`, a forbidden key or a leading `_`; or one off KEY_FORMAT), renamed. V2 authoring follows the API
|
|
349
|
+
* lane, so `id` is a field key like any other (only the derive lane, which mints keys, reserves it).
|
|
350
|
+
*/
|
|
351
|
+
function modelKeyOf(name) {
|
|
352
|
+
if (KEY_FORMAT.test(name) && !isReservedKey(name)) return name;
|
|
353
|
+
let k = name.replace(/^_+/, "").replace(/[^A-Za-z0-9_-]/g, "");
|
|
354
|
+
if (!/^[A-Za-z]/.test(k)) k = `f${k}`;
|
|
355
|
+
return isReservedKey(k) ? `${k}Field` : k;
|
|
356
|
+
}
|
|
357
|
+
/** The config keys a model's primitive list holds (types' PRIMITIVE_ARRAY_RULE). */
|
|
358
|
+
var MODEL_LIST_KEYS = new Set(PRIMITIVE_ARRAY_RULE.configKeys);
|
|
359
|
+
/** A slot's V2 allow list as the backend keeps it: 1–50 distinct block names of 1–64 characters (slotAllowIssues). */
|
|
360
|
+
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);
|
|
361
|
+
function shapeOfField(f, lv, ctx, top) {
|
|
302
362
|
const props = ctx.lane === "props";
|
|
303
|
-
const deep = lv >=
|
|
363
|
+
const deep = lv >= MAX_FIELD_DEPTH;
|
|
304
364
|
const of = Array.isArray(f.of) ? f.of : void 0;
|
|
305
|
-
/** a prop reference
|
|
306
|
-
const noEntry = (r) => props && !(r?.to ?? []).some(ENTRY_TARGET);
|
|
365
|
+
/** a prop reference names a content model or a page / form / collection target (refTargetNamed): with none it is stored as json */
|
|
366
|
+
const noEntry = (r) => props && !(r?.to ?? []).some((t) => ENTRY_TARGET(t) || REF_TARGET_KINDS.includes(t));
|
|
307
367
|
switch (f.type) {
|
|
308
368
|
case "object": return deep ? {
|
|
309
369
|
kind: "json",
|
|
@@ -314,11 +374,22 @@ function shapeOf(f, lv, ctx, top) {
|
|
|
314
374
|
type: "object"
|
|
315
375
|
};
|
|
316
376
|
case "array": {
|
|
317
|
-
if (of && of.length > 1 &&
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
377
|
+
if (of && of.length > 1 && of.every((i) => i.type === "object")) {
|
|
378
|
+
if (!props) return {
|
|
379
|
+
kind: "modular",
|
|
380
|
+
type: "modular",
|
|
381
|
+
items: of
|
|
382
|
+
};
|
|
383
|
+
return deep ? {
|
|
384
|
+
kind: "json",
|
|
385
|
+
type: "json",
|
|
386
|
+
feature: "depth>10"
|
|
387
|
+
} : {
|
|
388
|
+
kind: "types",
|
|
389
|
+
type: "table",
|
|
390
|
+
items: of
|
|
391
|
+
};
|
|
392
|
+
}
|
|
322
393
|
if (!of || of.length !== 1) return {
|
|
323
394
|
kind: "json",
|
|
324
395
|
type: "json",
|
|
@@ -334,6 +405,13 @@ function shapeOf(f, lv, ctx, top) {
|
|
|
334
405
|
type: props ? "table" : "array",
|
|
335
406
|
item
|
|
336
407
|
};
|
|
408
|
+
if (item.type === "reference" && shopifyOnly(item.reference)) return {
|
|
409
|
+
kind: "itemType",
|
|
410
|
+
type: "array",
|
|
411
|
+
item,
|
|
412
|
+
itemType: "text",
|
|
413
|
+
shopify: true
|
|
414
|
+
};
|
|
337
415
|
if (item.type === "reference") return noEntry(item.reference) ? {
|
|
338
416
|
kind: "json",
|
|
339
417
|
type: "json",
|
|
@@ -356,24 +434,30 @@ function shapeOf(f, lv, ctx, top) {
|
|
|
356
434
|
feature: "type:primitive-array"
|
|
357
435
|
};
|
|
358
436
|
}
|
|
359
|
-
case "slot":
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
437
|
+
case "slot":
|
|
438
|
+
if (!props && !slotAllowOk(f.of?.allow)) return {
|
|
439
|
+
kind: "json",
|
|
440
|
+
type: "json",
|
|
441
|
+
feature: "type:slot"
|
|
442
|
+
};
|
|
443
|
+
return {
|
|
444
|
+
kind: "slot",
|
|
445
|
+
type: "slot"
|
|
446
|
+
};
|
|
447
|
+
case "table": return {
|
|
365
448
|
kind: "leaf",
|
|
366
449
|
type: "table"
|
|
367
|
-
} : {
|
|
368
|
-
kind: "json",
|
|
369
|
-
type: "json",
|
|
370
|
-
feature: "type:table"
|
|
371
450
|
};
|
|
372
451
|
case "reference":
|
|
373
452
|
if (props && top && f.reference?.to?.length === 1 && f.reference.to[0] === "form" && !f.reference.filter) return {
|
|
374
453
|
kind: "leaf",
|
|
375
454
|
type: "form"
|
|
376
455
|
};
|
|
456
|
+
if (shopifyOnly(f.reference)) return {
|
|
457
|
+
kind: "leaf",
|
|
458
|
+
type: "text",
|
|
459
|
+
shopify: true
|
|
460
|
+
};
|
|
377
461
|
return noEntry(f.reference) ? {
|
|
378
462
|
kind: "json",
|
|
379
463
|
type: "json",
|
|
@@ -400,9 +484,25 @@ var trunc = (ctx, at, s, max, feature) => {
|
|
|
400
484
|
lose(ctx, at, feature);
|
|
401
485
|
return s.slice(0, max);
|
|
402
486
|
};
|
|
403
|
-
|
|
487
|
+
/** The prod field types that store a rich text and its features (config.features). */
|
|
488
|
+
var RICH_TYPES = /* @__PURE__ */ new Set(["richtext", "document"]);
|
|
489
|
+
/** Every feature, canonical: RICHTEXT_FEATURES through normaliseRichTextFeatures, so no alias is ever in it. */
|
|
490
|
+
var ALL_RICH_FEATURES = normaliseRichTextFeatures(RICHTEXT_FEATURES).features;
|
|
491
|
+
/**
|
|
492
|
+
* A rich text's features through types normaliseRichTextFeatures (its aliases expand there: `headings` is h1–h6), distinct,
|
|
493
|
+
* in the order given. `named`: something was not carried (a name outside RICHTEXT_FEATURES, a repeat, a non-list).
|
|
494
|
+
*/
|
|
495
|
+
function richFeatures(v) {
|
|
496
|
+
const names = Array.isArray(v) ? v.filter((x) => typeof x === "string") : [];
|
|
497
|
+
const { features, unknown } = normaliseRichTextFeatures(names);
|
|
498
|
+
return {
|
|
499
|
+
kept: [...new Set(features)],
|
|
500
|
+
named: !Array.isArray(v) || names.length !== v.length || new Set(names).size !== names.length || unknown.length > 0
|
|
501
|
+
};
|
|
502
|
+
}
|
|
503
|
+
function convertField(f, at, lv, ctx, siblings, top, inTable = false, inItem = false, inSetting = false) {
|
|
404
504
|
const props = ctx.lane === "props";
|
|
405
|
-
const shape = shapeOf(f, lv, ctx, top);
|
|
505
|
+
const shape = shapeOf(f, lv, ctx, top, inTable ? "rows" : inItem ? "item" : inSetting ? "setting" : void 0);
|
|
406
506
|
const node = {
|
|
407
507
|
key: f.name,
|
|
408
508
|
label: f.title,
|
|
@@ -414,17 +514,28 @@ function convertField(f, at, lv, ctx, siblings, top, inTable = false) {
|
|
|
414
514
|
if (twins) {
|
|
415
515
|
node.key = `${f.name}_${twins + 1}`;
|
|
416
516
|
lose(ctx, `${at}/name`, "duplicate name");
|
|
517
|
+
} else if (!props && modelKeyOf(f.name) !== f.name) {
|
|
518
|
+
node.key = modelKeyOf(f.name);
|
|
519
|
+
lose(ctx, `${at}/name`, "reserved name");
|
|
417
520
|
}
|
|
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";
|
|
521
|
+
const nesting = shape.kind === "object" || shape.kind === "zones" || shape.kind === "types";
|
|
522
|
+
/** a list of items (objects, block models, item types, scalars or entries): ui.itemLabel names one item */
|
|
523
|
+
const listy = shape.kind === "zones" || shape.kind === "modular" || shape.kind === "types" || shape.kind === "itemType" || shape.kind === "refs";
|
|
421
524
|
const looseConfig = props || !STRICT_CONFIG.has(shape.type);
|
|
422
525
|
if (shape.kind === "json") lose(ctx, `${at}/type`, shape.feature);
|
|
526
|
+
const shopify = (shape.kind === "leaf" || shape.kind === "itemType") && shape.shopify === true;
|
|
527
|
+
if (shopify) {
|
|
528
|
+
if (f.readOnly !== true) lose(ctx, `${at}/readOnly`, "shopify reference");
|
|
529
|
+
node.readOnly = true;
|
|
530
|
+
node.lockReason = SHOPIFY_REF_LOCK;
|
|
531
|
+
}
|
|
423
532
|
if (!props && f.type === "url") node.config.inputType = "url";
|
|
424
533
|
if (shape.type === "datetime" && !props) node.config.includeTime = true;
|
|
425
534
|
if (shape.kind === "leaf" && shape.type === "table") node.config.mode = "data";
|
|
535
|
+
if (shape.kind === "types") node.config.mode = "types";
|
|
536
|
+
if (shape.kind === "slot" && props) node.config.multiple = true;
|
|
426
537
|
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;
|
|
538
|
+
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
539
|
if (label !== void 0 && label.length <= 24) node.ui.itemLabel = label;
|
|
429
540
|
}
|
|
430
541
|
const devLock = f.access?.edit === "schema.manage" && !!f.lockReason;
|
|
@@ -435,23 +546,28 @@ function convertField(f, at, lv, ctx, siblings, top, inTable = false) {
|
|
|
435
546
|
lose(ctx, p, shape.feature);
|
|
436
547
|
continue;
|
|
437
548
|
}
|
|
549
|
+
if (shopify && (k === "reference" || k === "readOnly")) continue;
|
|
550
|
+
if (shopify && (k === "access" || k === "lockReason")) {
|
|
551
|
+
lose(ctx, p, "shopify reference");
|
|
552
|
+
continue;
|
|
553
|
+
}
|
|
438
554
|
switch (k) {
|
|
439
555
|
case "name":
|
|
440
556
|
case "title":
|
|
441
557
|
case "type": break;
|
|
442
558
|
case "description":
|
|
443
|
-
node.helpText = trunc(ctx, p, f.description, props ?
|
|
559
|
+
node.helpText = trunc(ctx, p, f.description, props ? PROP_HELP_MAX : FIELD_HELP_MAX, "help>limit");
|
|
444
560
|
break;
|
|
445
561
|
case "helpMore":
|
|
446
562
|
node.helpMore = trunc(ctx, p, f.helpMore, HELP_MORE_MAX, "help>limit");
|
|
447
563
|
break;
|
|
448
564
|
case "placeholder":
|
|
449
|
-
if (props) node.placeholder = trunc(ctx, p, f.placeholder,
|
|
565
|
+
if (props) node.placeholder = trunc(ctx, p, f.placeholder, PROP_PLACEHOLDER_MAX, "help>limit");
|
|
450
566
|
else if (looseConfig) node.placeholder = f.placeholder;
|
|
451
|
-
else node.ui.placeholder = trunc(ctx, p, f.placeholder,
|
|
567
|
+
else node.ui.placeholder = trunc(ctx, p, f.placeholder, UI_PLACEHOLDER_MAX, "help>limit");
|
|
452
568
|
break;
|
|
453
569
|
case "initialValue":
|
|
454
|
-
if (props && (shape.type === "reference" || shape.type === "multi-reference")) cat(ctx, p, "seeded instance");
|
|
570
|
+
if (props && (shape.type === "reference" || shape.type === "multi-reference" || shape.kind === "slot")) cat(ctx, p, "seeded instance");
|
|
455
571
|
else node.defaultValue = defaultToProd(f, shape, f.initialValue, p, ctx, lv, top);
|
|
456
572
|
break;
|
|
457
573
|
case "validation":
|
|
@@ -471,7 +587,7 @@ function convertField(f, at, lv, ctx, siblings, top, inTable = false) {
|
|
|
471
587
|
ofToProd(f, shape, node, p, lv, ctx);
|
|
472
588
|
break;
|
|
473
589
|
case "openMode":
|
|
474
|
-
if (nesting) node.openMode = f.openMode;
|
|
590
|
+
if (nesting || props && shape.type === "code") node.openMode = f.openMode;
|
|
475
591
|
else lose(ctx, p, "openMode");
|
|
476
592
|
break;
|
|
477
593
|
case "preview":
|
|
@@ -509,6 +625,9 @@ function convertField(f, at, lv, ctx, siblings, top, inTable = false) {
|
|
|
509
625
|
case "localized":
|
|
510
626
|
node.localized = f.localized;
|
|
511
627
|
break;
|
|
628
|
+
case "archived":
|
|
629
|
+
if (f.archived) node.archived = true;
|
|
630
|
+
break;
|
|
512
631
|
case "advanced":
|
|
513
632
|
node.advanced = f.advanced;
|
|
514
633
|
break;
|
|
@@ -527,7 +646,7 @@ function convertField(f, at, lv, ctx, siblings, top, inTable = false) {
|
|
|
527
646
|
else lose(ctx, p, "unsupported key");
|
|
528
647
|
break;
|
|
529
648
|
case "icon": {
|
|
530
|
-
const dock = shape.kind === "object" || shape.kind === "modular" ? dockIconOf(f.icon) : void 0;
|
|
649
|
+
const dock = shape.kind === "object" || shape.kind === "modular" || shape.kind === "types" ? dockIconOf(f.icon) : void 0;
|
|
531
650
|
if (dock) node.ui.icon = dock;
|
|
532
651
|
else lose(ctx, p, "icon");
|
|
533
652
|
break;
|
|
@@ -543,13 +662,14 @@ function convertField(f, at, lv, ctx, siblings, top, inTable = false) {
|
|
|
543
662
|
break;
|
|
544
663
|
}
|
|
545
664
|
case "slotSettings":
|
|
546
|
-
|
|
665
|
+
if (shape.kind === "slot") slotSettingsToProd(f.slotSettings, node, p, lv, ctx);
|
|
666
|
+
else lose(ctx, p, "slotSettings");
|
|
547
667
|
break;
|
|
548
668
|
case "itemNoun":
|
|
549
669
|
if (!listy || node.ui.itemLabel?.toLowerCase() !== f.itemNoun) lose(ctx, p, "itemNoun");
|
|
550
670
|
break;
|
|
551
671
|
case "arrayLayout":
|
|
552
|
-
if (shape.kind === "zones" || shape.kind === "modular") node.ui.layout = f.arrayLayout;
|
|
672
|
+
if (shape.kind === "zones" || shape.kind === "modular" || shape.kind === "types") node.ui.layout = f.arrayLayout;
|
|
553
673
|
else if ((shape.kind === "itemType" || shape.kind === "refs") && f.arrayLayout === "grid") node.ui.layout = "gallery";
|
|
554
674
|
else lose(ctx, p, "layout");
|
|
555
675
|
break;
|
|
@@ -557,6 +677,14 @@ function convertField(f, at, lv, ctx, siblings, top, inTable = false) {
|
|
|
557
677
|
if (shape.type === "link" || shape.type === "image" || shape.type === "button") node.ui.valueShape = f.valueShape;
|
|
558
678
|
else lose(ctx, p, "valueShape");
|
|
559
679
|
break;
|
|
680
|
+
case "linkHref":
|
|
681
|
+
if (typeof f.linkHref === "string" && f.linkHref) node.config.linkHref = f.linkHref;
|
|
682
|
+
else lose(ctx, p, "unsupported key");
|
|
683
|
+
break;
|
|
684
|
+
case "svgOnly":
|
|
685
|
+
if (shape.type === "image" && f.svgOnly === true) node.config.media = "icon";
|
|
686
|
+
else if (f.svgOnly !== false) lose(ctx, p, "unsupported key");
|
|
687
|
+
break;
|
|
560
688
|
case "timezone":
|
|
561
689
|
if (shape.type === "date" || shape.type === "datetime") {
|
|
562
690
|
const tz = f.timezone;
|
|
@@ -577,11 +705,26 @@ function convertField(f, at, lv, ctx, siblings, top, inTable = false) {
|
|
|
577
705
|
if (shape.kind === "leaf" && shape.type === "table") Object.assign(node.config, tableConfigFromOptions(f.table));
|
|
578
706
|
else lose(ctx, p, "type:table");
|
|
579
707
|
break;
|
|
708
|
+
case "features":
|
|
709
|
+
if (!RICH_TYPES.has(shape.type)) lose(ctx, p, "unsupported key");
|
|
710
|
+
else {
|
|
711
|
+
const { kept, named } = richFeatures(f.features);
|
|
712
|
+
if (named) lose(ctx, p, "richtext features");
|
|
713
|
+
node.config.features = kept;
|
|
714
|
+
}
|
|
715
|
+
break;
|
|
580
716
|
default: lose(ctx, p, "unsupported key");
|
|
581
717
|
}
|
|
582
718
|
}
|
|
719
|
+
if (props && f.description === void 0) node.helpText = null;
|
|
720
|
+
if (RICH_TYPES.has(shape.type) && shape.kind === "leaf" && f.features === void 0) node.config.features = [...ALL_RICH_FEATURES];
|
|
583
721
|
if (f.itemNoun === void 0 && shape.kind === "zones" && node.ui.itemLabel !== void 0) cat(ctx, `${at}/itemNoun`, "itemNoun (derived)");
|
|
584
722
|
placeInSet(f, node, at, ctx, top, siblings);
|
|
723
|
+
if (f.type === "rating" && node.type === "rating" && f.numeric?.step === void 0) {
|
|
724
|
+
const lo = typeof node.config.min === "number" ? node.config.min : 0;
|
|
725
|
+
const stops = ((typeof node.config.max === "number" ? node.config.max : 5) - lo) / V2_RATING_STEP;
|
|
726
|
+
if (Math.abs(stops - Math.round(stops)) < 1e-9 && Math.round(stops) <= 100) node.config.step = V2_RATING_STEP;
|
|
727
|
+
}
|
|
585
728
|
if (node.ui.control === "slider" && !sliderOk(node.config)) {
|
|
586
729
|
delete node.ui.control;
|
|
587
730
|
lose(ctx, `${at}/layout`, "layout");
|
|
@@ -606,7 +749,16 @@ function sliderOk({ min, max, step }) {
|
|
|
606
749
|
/** Where a field sits: its tab (fields lane) or prop group (props lane). */
|
|
607
750
|
function placeInSet(f, node, at, ctx, top, siblings) {
|
|
608
751
|
if (ctx.lane === "props") {
|
|
609
|
-
if (
|
|
752
|
+
if (!top) {
|
|
753
|
+
if (f.group !== void 0) {
|
|
754
|
+
if (ctx.keptTabs.has(f.group)) node.ui.tab = { id: f.group };
|
|
755
|
+
else lose(ctx, `${at}/group`, "group (nested)");
|
|
756
|
+
}
|
|
757
|
+
} else {
|
|
758
|
+
const t = ctx.propTabs.get(f);
|
|
759
|
+
if (t?.loss) lose(ctx, `${at}/group`, t.loss);
|
|
760
|
+
if (t?.tab) node.ui.tab = ctx.definedTabs.has(t.tab.id) ? { id: t.tab.id } : (ctx.definedTabs.add(t.tab.id), t.tab);
|
|
761
|
+
}
|
|
610
762
|
if (f.fieldset === void 0) return;
|
|
611
763
|
const set = ctx.propSets.get(f.fieldset);
|
|
612
764
|
if (!set) return lose(ctx, `${at}/fieldset`, "fieldset collision");
|
|
@@ -646,7 +798,7 @@ function propGroupOf(s, ctx) {
|
|
|
646
798
|
if (ctx.groupOrder) g.order = Math.min(99, ctx.propOrder.get(s.name) ?? 0);
|
|
647
799
|
return g;
|
|
648
800
|
}
|
|
649
|
-
var groupDescriptionOk = (d) => typeof d === "string" && d === d.trim() && d.length >= 1 && d.length <=
|
|
801
|
+
var groupDescriptionOk = (d) => typeof d === "string" && d === d.trim() && d.length >= 1 && d.length <= PROP_GROUP_DESCRIPTION_MAX;
|
|
650
802
|
/** The zone a datetime field fixes, if any (what lets a stored instant read back with its [Zone]). */
|
|
651
803
|
var fixedZone = (f) => typeof f.timezone === "string" && f.timezone.startsWith("fixed:") ? f.timezone.slice(6) : void 0;
|
|
652
804
|
/**
|
|
@@ -663,7 +815,7 @@ function defaultToProd(f, shape, v, at, ctx, lv, top) {
|
|
|
663
815
|
var AS_IS = { k: "as-is" };
|
|
664
816
|
/** The write side's plan, from the V2 field and the shape it is stored as. */
|
|
665
817
|
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)]));
|
|
818
|
+
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
819
|
switch (shape.kind) {
|
|
668
820
|
case "json": return AS_IS;
|
|
669
821
|
case "itemType": return shape.itemType === "image" || shape.itemType === "link" ? {
|
|
@@ -677,8 +829,13 @@ function writePlan(f, shape, lv, ctx, top) {
|
|
|
677
829
|
case "zones": return {
|
|
678
830
|
k: "rows",
|
|
679
831
|
zoned: ctx.lane === "fields",
|
|
680
|
-
fields: kids(shape.item.fields ?? [])
|
|
832
|
+
fields: kids(shape.item.fields ?? [], ctx.lane === "props" ? "rows" : void 0)
|
|
833
|
+
};
|
|
834
|
+
case "types": return {
|
|
835
|
+
k: "types",
|
|
836
|
+
types: new Map(shape.items.map((i) => [i.name, kids(i.fields ?? [], "item")]))
|
|
681
837
|
};
|
|
838
|
+
case "slot": return ctx.lane === "fields" ? { k: "blocks" } : AS_IS;
|
|
682
839
|
case "modular": {
|
|
683
840
|
const top1 = (fields) => new Map(fields.map((c) => [c.name, writePlan(c, shapeOf(c, 1, ctx, false), 1, ctx, false)]));
|
|
684
841
|
return {
|
|
@@ -688,6 +845,7 @@ function writePlan(f, shape, lv, ctx, top) {
|
|
|
688
845
|
}
|
|
689
846
|
case "refs": return { k: "refs" };
|
|
690
847
|
case "leaf":
|
|
848
|
+
if (shape.shopify) return AS_IS;
|
|
691
849
|
if (f.type === "link" || f.type === "url") return { k: "link" };
|
|
692
850
|
if (f.type === "button" || f.type === "image") return { k: f.type };
|
|
693
851
|
if (f.type === "datetime") return {
|
|
@@ -706,7 +864,7 @@ function leafPlan(f, prodType) {
|
|
|
706
864
|
scale: {
|
|
707
865
|
min: f.numeric?.min,
|
|
708
866
|
max: f.numeric?.max,
|
|
709
|
-
step: f.numeric?.step
|
|
867
|
+
step: f.numeric?.step ?? V2_RATING_STEP
|
|
710
868
|
}
|
|
711
869
|
};
|
|
712
870
|
if (f.type === "number" && f.scale) return {
|
|
@@ -716,11 +874,12 @@ function leafPlan(f, prodType) {
|
|
|
716
874
|
return prodType === "number" ? { k: "number" } : AS_IS;
|
|
717
875
|
}
|
|
718
876
|
/**
|
|
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
|
|
877
|
+
* The read side's plan, from the V2 field read back (`zoned`: lists read from an array's repeatable zone and groups
|
|
878
|
+
* read from its non-repeatable zone; `modular`: lists read from a modular field, whose item fields live in their block
|
|
879
|
+
* models and pass as stored).
|
|
721
880
|
*/
|
|
722
|
-
function readPlan(f, prodType, zoned, modular) {
|
|
723
|
-
const kids = (fields) => new Map(fields.map((c) => [c.name, readPlan(c, "", zoned, modular)]));
|
|
881
|
+
function readPlan(f, prodType, zoned, modular, types, slots, blocks) {
|
|
882
|
+
const kids = (fields) => new Map(fields.map((c) => [c.name, readPlan(c, "", zoned, modular, types, slots, blocks)]));
|
|
724
883
|
switch (f.type) {
|
|
725
884
|
case "link":
|
|
726
885
|
case "url": return { k: "link" };
|
|
@@ -731,16 +890,29 @@ function readPlan(f, prodType, zoned, modular) {
|
|
|
731
890
|
zone: fixedZone(f)
|
|
732
891
|
};
|
|
733
892
|
case "date": return { k: "date" };
|
|
734
|
-
case "reference":
|
|
893
|
+
case "reference":
|
|
894
|
+
if (shopifyOnly(f.reference)) return AS_IS;
|
|
895
|
+
return { k: prodType === "form" ? "form" : "ref" };
|
|
735
896
|
case "object": return {
|
|
736
897
|
k: "object",
|
|
898
|
+
...zoned.has(f) ? { zoned: true } : {},
|
|
737
899
|
fields: kids(f.fields ?? [])
|
|
738
900
|
};
|
|
901
|
+
case "slot":
|
|
902
|
+
if (blocks?.has(f)) return { k: "blocks" };
|
|
903
|
+
return slots?.has(f) ? {
|
|
904
|
+
k: "slot",
|
|
905
|
+
multiple: slots.get(f)
|
|
906
|
+
} : AS_IS;
|
|
739
907
|
case "array": {
|
|
740
908
|
if (modular.has(f)) return {
|
|
741
909
|
k: "modular",
|
|
742
910
|
types: new Map((Array.isArray(f.of) ? f.of : []).map((i) => [i.name, kids(i.fields ?? [])]))
|
|
743
911
|
};
|
|
912
|
+
if (types?.has(f)) return {
|
|
913
|
+
k: "types",
|
|
914
|
+
types: new Map((Array.isArray(f.of) ? f.of : []).map((i) => [i.name, kids(i.fields ?? [])]))
|
|
915
|
+
};
|
|
744
916
|
const item = Array.isArray(f.of) && f.of.length === 1 ? f.of[0] : void 0;
|
|
745
917
|
if (item?.type === "object") return {
|
|
746
918
|
k: "rows",
|
|
@@ -751,7 +923,7 @@ function readPlan(f, prodType, zoned, modular) {
|
|
|
751
923
|
k: "list",
|
|
752
924
|
item: item.type
|
|
753
925
|
};
|
|
754
|
-
return item?.type === "reference" ? { k: "refs" } : AS_IS;
|
|
926
|
+
return item?.type === "reference" && !shopifyOnly(item.reference) ? { k: "refs" } : AS_IS;
|
|
755
927
|
}
|
|
756
928
|
default: return leafPlan(f, prodType);
|
|
757
929
|
}
|
|
@@ -791,7 +963,10 @@ function planToProd(plan, v, lost, at = "") {
|
|
|
791
963
|
case "list": return take(listToProd(v, plan.item));
|
|
792
964
|
case "scale": return take(scaleToProd(v, plan.scale));
|
|
793
965
|
case "rating": return take(ratingToProd(v, plan.scale));
|
|
794
|
-
case "object":
|
|
966
|
+
case "object": {
|
|
967
|
+
const out = mapKeys(v, plan.fields, (p, x, k) => planToProd(p, x, lost, under(k)));
|
|
968
|
+
return plan.zoned && isObj(out) ? { nonRepeatable: out } : out;
|
|
969
|
+
}
|
|
795
970
|
case "rows": {
|
|
796
971
|
if (!Array.isArray(v)) return v;
|
|
797
972
|
const rows = v.map((row, i) => mapKeys(row, plan.fields, (p, x, k) => planToProd(p, x, lost, `${under(i)}/${k}`)));
|
|
@@ -809,24 +984,46 @@ function planToProd(plan, v, lost, at = "") {
|
|
|
809
984
|
data: fields ? mapKeys(rest, fields, (p, x, k) => planToProd(p, x, lost, `${under(i)}/${k}`)) : rest
|
|
810
985
|
};
|
|
811
986
|
});
|
|
987
|
+
case "blocks": return Array.isArray(v) ? v.map((c) => isObj(c) && typeof c._type === "string" ? {
|
|
988
|
+
...c,
|
|
989
|
+
_type: kebab(c._type)
|
|
990
|
+
} : c) : v;
|
|
991
|
+
case "slot": {
|
|
992
|
+
const kids = (type) => plan.child?.(type);
|
|
993
|
+
return slotChildrenToStored(plan.family ? childVariantsToTypes(v, plan.family) : v, plan.multiple !== false, (type, values, i) => {
|
|
994
|
+
const fields = kids(type);
|
|
995
|
+
return fields ? mapKeys(values, fields, (p, x, k) => planToProd(p, x, lost, `${under(i)}/${k}`)) : values;
|
|
996
|
+
}, (rel) => lost?.push(under(rel)));
|
|
997
|
+
}
|
|
998
|
+
case "types": return take(typedRowsToProd(v, (row, i) => {
|
|
999
|
+
const fields = plan.types.get(row._type);
|
|
1000
|
+
return fields ? mapKeys(row, fields, (p, x, k) => planToProd(p, x, lost, `${under(i)}/${k}`)) : row;
|
|
1001
|
+
}));
|
|
812
1002
|
default: return v;
|
|
813
1003
|
}
|
|
814
1004
|
}
|
|
815
1005
|
/** The keys the kit reads back from a stored image object (imageFromProd) and writes again (imageToProd). */
|
|
816
|
-
var IMAGE_KIT_KEYS = new Set([
|
|
1006
|
+
var IMAGE_KIT_KEYS = /* @__PURE__ */ new Set([
|
|
817
1007
|
"url",
|
|
818
1008
|
"id",
|
|
819
1009
|
"name",
|
|
820
1010
|
"altText",
|
|
821
1011
|
"focal"
|
|
822
1012
|
]);
|
|
823
|
-
/**
|
|
1013
|
+
/**
|
|
1014
|
+
* Every key of a stored image the kit cannot hand back. A crop rect is read back as it is (imageFromProd), and an older
|
|
1015
|
+
* `{ 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
|
|
1016
|
+
* kit does not model, is.
|
|
1017
|
+
*/
|
|
824
1018
|
function imageStoredLoss(v, rel, loss) {
|
|
825
1019
|
if (!isObj(v)) return;
|
|
1020
|
+
const legacy = typeof v.url !== "string" && typeof v.src === "string";
|
|
826
1021
|
for (const [k, x] of Object.entries(v)) {
|
|
827
1022
|
if (IMAGE_KIT_KEYS.has(k) || x === void 0) continue;
|
|
1023
|
+
if (legacy && k === "src") continue;
|
|
1024
|
+
if (k === "alt" && typeof x === "string" && v.altText === void 0) continue;
|
|
828
1025
|
if (k === "crop") {
|
|
829
|
-
if (x != null) loss(`${rel}/crop`, "A saved crop
|
|
1026
|
+
if (x != null && !isCropRect(x)) loss(`${rel}/crop`, "A saved crop the kit can't read; editing the image would drop it.");
|
|
830
1027
|
} else loss(`${rel}/${k}`, `The image's saved "${k}" is not kept by the kit; editing the image would drop it.`);
|
|
831
1028
|
}
|
|
832
1029
|
}
|
|
@@ -859,7 +1056,14 @@ function planFromProd(plan, v, loss, rel = "") {
|
|
|
859
1056
|
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
1057
|
}
|
|
861
1058
|
return referenceFromProd(v);
|
|
862
|
-
case "object":
|
|
1059
|
+
case "object": {
|
|
1060
|
+
const env = plan.zoned && isObj(v) && "nonRepeatable" in v ? v : void 0;
|
|
1061
|
+
if (env && loss) {
|
|
1062
|
+
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.`);
|
|
1063
|
+
}
|
|
1064
|
+
const at = env ? `${rel}/nonRepeatable` : rel;
|
|
1065
|
+
return mapKeys(env ? isObj(env.nonRepeatable) ? env.nonRepeatable : {} : v, plan.fields, (p, x, k) => planFromProd(p, x, loss, `${at}/${k}`));
|
|
1066
|
+
}
|
|
863
1067
|
case "rows": {
|
|
864
1068
|
const rows = plan.zoned ? zoneListFromProd(v) : v;
|
|
865
1069
|
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 +1079,27 @@ function planFromProd(plan, v, loss, rel = "") {
|
|
|
875
1079
|
...back
|
|
876
1080
|
};
|
|
877
1081
|
}) : v;
|
|
1082
|
+
case "blocks": return Array.isArray(v) ? v.map((c) => isObj(c) && typeof c._type === "string" ? {
|
|
1083
|
+
...c,
|
|
1084
|
+
_type: camel(c._type)
|
|
1085
|
+
} : c) : v;
|
|
1086
|
+
case "slot": return slotChildrenFromStored(v, (type, values, i) => {
|
|
1087
|
+
const fields = plan.child?.(type);
|
|
1088
|
+
const read = fields ? mapKeys(values, fields, (p, x, k) => planFromProd(p, x, loss, `${rel}/${i}/${k}`)) : values;
|
|
1089
|
+
const variant = plan.family?.(type)?.current;
|
|
1090
|
+
return variant === void 0 ? read : {
|
|
1091
|
+
...read,
|
|
1092
|
+
_variant: variant
|
|
1093
|
+
};
|
|
1094
|
+
}, (i, reason) => loss?.(`${rel}/${i}`, reason));
|
|
1095
|
+
case "types": return typedRowsFromProd(v, (row, i) => {
|
|
1096
|
+
const fields = plan.types.get(row._type);
|
|
1097
|
+
if (!fields) {
|
|
1098
|
+
loss?.(`${rel}/${i}/_type`, `A stored row of item type "${row._type}", which this list no longer declares; editing the list would drop it.`);
|
|
1099
|
+
return row;
|
|
1100
|
+
}
|
|
1101
|
+
return mapKeys(row, fields, (p, x, k) => planFromProd(p, x, loss, `${rel}/${i}/${k}`));
|
|
1102
|
+
});
|
|
878
1103
|
default: return v;
|
|
879
1104
|
}
|
|
880
1105
|
}
|
|
@@ -895,7 +1120,7 @@ function diffPaths(a, b, path = "", out = []) {
|
|
|
895
1120
|
if ((isObj(a) || a === void 0) && (isObj(b) || b === void 0) && (a !== void 0 || b !== void 0)) {
|
|
896
1121
|
const A = a ?? {};
|
|
897
1122
|
const B = b ?? {};
|
|
898
|
-
for (const k of new Set([...Object.keys(A), ...Object.keys(B)])) diffPaths(A[k], B[k], `${path}/${k}`, out);
|
|
1123
|
+
for (const k of /* @__PURE__ */ new Set([...Object.keys(A), ...Object.keys(B)])) diffPaths(A[k], B[k], `${path}/${k}`, out);
|
|
899
1124
|
} 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
1125
|
else out.push(path);
|
|
901
1126
|
return out;
|
|
@@ -935,17 +1160,21 @@ function validationToProd(f, shape, node, at, ctx, inTable, top) {
|
|
|
935
1160
|
case "max": {
|
|
936
1161
|
const n = v;
|
|
937
1162
|
const lo = k === "min";
|
|
938
|
-
if (lengthy)
|
|
939
|
-
|
|
940
|
-
|
|
1163
|
+
if (lengthy) {
|
|
1164
|
+
if (isWhole(n)) set(lo ? "minLength" : "maxLength", n, "validation.length", "minLength", "maxLength");
|
|
1165
|
+
else lose(ctx, p, "validation.length");
|
|
1166
|
+
} else if (t === "number") {
|
|
941
1167
|
const b = node.config.validation ??= {};
|
|
942
1168
|
b[k] = n;
|
|
943
1169
|
} 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
|
|
1170
|
+
else if (shape.kind === "zones" || shape.kind === "modular" || shape.kind === "types" || shape.kind === "slot" || shape.kind === "itemType") {
|
|
1171
|
+
const cap = shape.kind === "slot" ? SLOT_ITEMS_CAP : LIST_ITEMS_CAP;
|
|
1172
|
+
if (props && top || shape.kind === "slot" ? isWhole(n, lo ? 0 : 1, cap) : isWhole(n)) set(lo ? "minItems" : "maxItems", n, "validation.items", "minItems", "maxItems");
|
|
1173
|
+
else lose(ctx, p, "validation.items");
|
|
1174
|
+
} else if (shape.kind === "refs" || t === "multiselect" || t === "tags") {
|
|
1175
|
+
if (t === "tags" ? isWhole(n, lo ? 0 : 1, 500) : isWhole(n)) set(k, n, "validation.items", "min", "max");
|
|
1176
|
+
else lose(ctx, p, "validation.items");
|
|
1177
|
+
} else lose(ctx, p, "validation.length");
|
|
949
1178
|
break;
|
|
950
1179
|
}
|
|
951
1180
|
case "recommendedMax":
|
|
@@ -962,9 +1191,11 @@ function validationToProd(f, shape, node, at, ctx, inTable, top) {
|
|
|
962
1191
|
break;
|
|
963
1192
|
case "unique":
|
|
964
1193
|
if (val.unique === false) node.unique = false;
|
|
965
|
-
else if (
|
|
966
|
-
else
|
|
967
|
-
|
|
1194
|
+
else if (shape.kind === "types") lose(ctx, p, "validation.unique");
|
|
1195
|
+
else if (props) {
|
|
1196
|
+
if (UNIQUE_LIST_PROPS.has(t) || inTable && UNIQUE_ROW_PROPS.has(t)) node.unique = true;
|
|
1197
|
+
else cat(ctx, p, "not applicable (props)");
|
|
1198
|
+
} else {
|
|
968
1199
|
const polymorphic = t === "reference" && (f.reference?.to ?? []).filter(ENTRY_TARGET).length > 1;
|
|
969
1200
|
if (UNIQUE_TYPES.has(t) && !polymorphic) node.unique = true;
|
|
970
1201
|
else lose(ctx, p, "validation.unique");
|
|
@@ -1000,11 +1231,15 @@ function optionsToProd(f, shape, node, at, ctx) {
|
|
|
1000
1231
|
label: o.label,
|
|
1001
1232
|
value: o.value
|
|
1002
1233
|
};
|
|
1003
|
-
if (o.icon !== void 0)
|
|
1004
|
-
|
|
1234
|
+
if (o.icon !== void 0) {
|
|
1235
|
+
if (allIcons) out.icon = icons[i];
|
|
1236
|
+
else lose(ctx, `${at}/${i}/icon`, "option icon");
|
|
1237
|
+
}
|
|
1005
1238
|
const d = o.description;
|
|
1006
|
-
if (d !== void 0)
|
|
1007
|
-
|
|
1239
|
+
if (d !== void 0) {
|
|
1240
|
+
if (typeof d === "string" && d.trim() !== "" && !/[\r\n]/.test(d) && d.length <= OPTION_DESCRIPTION_MAX) out.description = d;
|
|
1241
|
+
else lose(ctx, `${at}/${i}/description`, "option description");
|
|
1242
|
+
}
|
|
1008
1243
|
for (const k of Object.keys(o)) if (![
|
|
1009
1244
|
"value",
|
|
1010
1245
|
"label",
|
|
@@ -1019,14 +1254,13 @@ function layoutToProd(f, shape, node, at, ctx) {
|
|
|
1019
1254
|
const l = f.layout;
|
|
1020
1255
|
const t = shape.type;
|
|
1021
1256
|
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";
|
|
1257
|
+
if (l === "segmented" && t === "select") {
|
|
1258
|
+
if (n >= 2 && n <= 4) node.ui.control = "segmented";
|
|
1259
|
+
else if (n >= 5) cat(ctx, at, "segmented fallback");
|
|
1260
|
+
else lose(ctx, at, "layout");
|
|
1261
|
+
} else if (l === "slider" && t === "number" && f.type === "number") node.ui.control = "slider";
|
|
1028
1262
|
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";
|
|
1263
|
+
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
1264
|
else lose(ctx, at, "layout");
|
|
1031
1265
|
}
|
|
1032
1266
|
/** The prod type a V2 field is stored as, for a preview path reading into it (no loss is reported). */
|
|
@@ -1061,6 +1295,7 @@ function previewPathToProd(path, children, ctx) {
|
|
|
1061
1295
|
node = next;
|
|
1062
1296
|
continue;
|
|
1063
1297
|
}
|
|
1298
|
+
if (node.type === "table") return TABLE_PATH_KEYS.includes(segs[i]) && i === segs.length - 1 ? [...out, segs[i]].join(".") : void 0;
|
|
1064
1299
|
const type = storedType(node, ctx);
|
|
1065
1300
|
if (!OBJECT_VALUE_TYPES.has(type)) return void 0;
|
|
1066
1301
|
const key = type === "image" ? IMAGE_PATH_KEY[segs[i]] ?? segs[i] : segs[i];
|
|
@@ -1094,10 +1329,71 @@ function previewToProd(pv, children, at, ctx) {
|
|
|
1094
1329
|
}
|
|
1095
1330
|
return out;
|
|
1096
1331
|
}
|
|
1332
|
+
/**
|
|
1333
|
+
* A V2 dotted document preview path (`slides.0.heading`, `default.heading`) the backend keeps (componentPreviewRefusals
|
|
1334
|
+
* previewPathOfProps): its head a top-level prop, an index segment stepping into an item of a list, the rest a path
|
|
1335
|
+
* previewPathToProd stores unchanged (a renamed key, `image.alt` → `altText`, has no stored form here).
|
|
1336
|
+
*/
|
|
1337
|
+
function documentPreviewPathOk(path, keys, fields, ctx) {
|
|
1338
|
+
const segs = path.split(".");
|
|
1339
|
+
if (segs.length < 2 || !keys.has(segs[0])) return false;
|
|
1340
|
+
const head = fields.find((f) => f.name === segs[0]);
|
|
1341
|
+
if (!head) return false;
|
|
1342
|
+
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;
|
|
1343
|
+
let node = head;
|
|
1344
|
+
const kept = [segs[0]];
|
|
1345
|
+
let poly = false;
|
|
1346
|
+
for (let i = 1; i < segs.length; i++) {
|
|
1347
|
+
const seg = segs[i];
|
|
1348
|
+
if (/^\d+$/.test(seg) && (node.type === "array" || node.type === "multiselect" || node.type === "tags")) continue;
|
|
1349
|
+
const types = polyOf(node);
|
|
1350
|
+
const kids = types ? types.flatMap((o) => o.fields ?? []) : previewKids(node);
|
|
1351
|
+
if (!kids) {
|
|
1352
|
+
kept.push(...segs.slice(i));
|
|
1353
|
+
break;
|
|
1354
|
+
}
|
|
1355
|
+
const next = kids.find((c) => c.name === seg);
|
|
1356
|
+
if (!next) return false;
|
|
1357
|
+
if (types) poly = true;
|
|
1358
|
+
kept.push(seg);
|
|
1359
|
+
node = next;
|
|
1360
|
+
}
|
|
1361
|
+
if (poly) return true;
|
|
1362
|
+
const clean = kept.join(".");
|
|
1363
|
+
return previewPathToProd(clean, fields, ctx) === clean;
|
|
1364
|
+
}
|
|
1365
|
+
/**
|
|
1366
|
+
* A V2 schema's document-level preview → component.preview (BE componentPreviewSchema): `title` / `subtitle` / `media`
|
|
1367
|
+
* kept when they name a top-level prop key or a dotted path into one (else preview_key_unknown; a catalog note: the row
|
|
1368
|
+
* reads the first text),
|
|
1369
|
+
* `fallback` trimmed and at most COMPONENT_PREVIEW_FALLBACK_MAX, `icon` a dock icon.
|
|
1370
|
+
*/
|
|
1371
|
+
function componentPreviewToProd(pv, keys, fields, at, ctx) {
|
|
1372
|
+
const out = {};
|
|
1373
|
+
for (const k of Object.keys(pv)) {
|
|
1374
|
+
const v = pv[k];
|
|
1375
|
+
if (v === void 0) continue;
|
|
1376
|
+
if (k === "title" || k === "subtitle" || k === "media") {
|
|
1377
|
+
if ((keys.has(v) || documentPreviewPathOk(v, keys, fields, ctx)) && v.length <= 64) out[k] = v;
|
|
1378
|
+
else cat(ctx, `${at}/${k}`, "document preview path");
|
|
1379
|
+
} else if (k === "fallback") {
|
|
1380
|
+
const t = v.trim();
|
|
1381
|
+
if (t && t === v && t.length <= 120) out.fallback = v;
|
|
1382
|
+
else lose(ctx, `${at}/${k}`, "help>limit");
|
|
1383
|
+
} else if (k === "icon") {
|
|
1384
|
+
const dock = dockIconOf(v);
|
|
1385
|
+
if (dock) out.icon = dock;
|
|
1386
|
+
else lose(ctx, `${at}/${k}`, "preview icon");
|
|
1387
|
+
} else lose(ctx, `${at}/${k}`, "unsupported key");
|
|
1388
|
+
}
|
|
1389
|
+
return out;
|
|
1390
|
+
}
|
|
1097
1391
|
/** A list item's name and title: the convention, else ui.itemName / ui.itemTitle (chromeUiProblems). */
|
|
1098
1392
|
function itemIdentity(item, conv, node, ip, ctx) {
|
|
1099
|
-
if (item.name !== conv.name)
|
|
1100
|
-
|
|
1393
|
+
if (item.name !== conv.name) {
|
|
1394
|
+
if (ITEM_NAME_RE.test(item.name)) node.ui.itemName = item.name;
|
|
1395
|
+
else lose(ctx, `${ip}/name`, "item identity");
|
|
1396
|
+
}
|
|
1101
1397
|
if (item.title !== conv.title) {
|
|
1102
1398
|
const t = item.title;
|
|
1103
1399
|
if (t === t.trim() && t.length >= 1 && t.length <= 60) node.ui.itemTitle = t;
|
|
@@ -1111,6 +1407,21 @@ function ofToProd(f, shape, node, at, lv, ctx) {
|
|
|
1111
1407
|
shape.items.forEach((item, i) => blockModelFor(item, `${at}/${i}`, ctx, node));
|
|
1112
1408
|
return;
|
|
1113
1409
|
}
|
|
1410
|
+
if (shape.kind === "types") return itemTypesToProd(shape.items, node, at, lv, ctx);
|
|
1411
|
+
if (shape.kind === "slot") {
|
|
1412
|
+
const of = f.of;
|
|
1413
|
+
for (const k of Object.keys(of)) {
|
|
1414
|
+
if (of[k] === void 0) continue;
|
|
1415
|
+
if (k === "allow" && ctx.lane === "fields") {
|
|
1416
|
+
node.config.blockSlugs = of.allow.map(kebab);
|
|
1417
|
+
of.allow.forEach((n, i) => camel(kebab(n)) !== n && lose(ctx, `${at}/allow/${i}`, "type name"));
|
|
1418
|
+
} else if (k === "allow") {
|
|
1419
|
+
if (slotAllowOk(of.allow)) node.config.allow = [...of.allow];
|
|
1420
|
+
else cat(ctx, `${at}/allow`, "slot allow");
|
|
1421
|
+
} else if (k !== "type" || of.type !== "block") lose(ctx, `${at}/${k}`, "unsupported key");
|
|
1422
|
+
}
|
|
1423
|
+
return;
|
|
1424
|
+
}
|
|
1114
1425
|
const item = shape.item;
|
|
1115
1426
|
const ip = `${at}/0`;
|
|
1116
1427
|
if (shape.kind === "zones") {
|
|
@@ -1134,15 +1445,96 @@ function ofToProd(f, shape, node, at, lv, ctx) {
|
|
|
1134
1445
|
}
|
|
1135
1446
|
if (shape.kind === "itemType") node.config.itemType = shape.itemType;
|
|
1136
1447
|
itemIdentity(item, conventionItem(f.name, f.title), node, ip, ctx);
|
|
1448
|
+
const settings = {};
|
|
1449
|
+
const scalars = shape.kind === "itemType" && !shape.shopify && (ctx.lane === "props" || MODEL_LIST_KEYS.has("item"));
|
|
1137
1450
|
for (const k of Object.keys(item)) {
|
|
1138
|
-
|
|
1451
|
+
const v = item[k];
|
|
1452
|
+
if (v === void 0) continue;
|
|
1139
1453
|
const p = `${ip}/${k}`;
|
|
1140
1454
|
if (k === "name" || k === "title") continue;
|
|
1141
1455
|
if (k === "type") {
|
|
1456
|
+
if (shape.kind === "itemType" && shape.shopify) continue;
|
|
1142
1457
|
if (shape.kind === "itemType" && item.type === "text") lose(ctx, p, "item settings");
|
|
1143
1458
|
} else if (k === "reference" && shape.kind === "refs") referenceToConfig(item.reference, node, p, ctx);
|
|
1459
|
+
else if (k === "reference" && shape.kind === "itemType" && shape.shopify) continue;
|
|
1460
|
+
else if (scalars && k === "description" && typeof v === "string" && v.trim() === v && v.length >= 1 && v.length <= PROP_HELP_MAX) settings.helpText = v;
|
|
1461
|
+
else if (scalars && k === "localized" && typeof v === "boolean") settings.localized = v;
|
|
1462
|
+
else if (scalars && k === "validation") itemValidationToProd(item, shape.itemType, settings, p, ctx);
|
|
1144
1463
|
else lose(ctx, p, "item settings");
|
|
1145
1464
|
}
|
|
1465
|
+
if (nonEmpty(settings)) node.config.item = settings;
|
|
1466
|
+
}
|
|
1467
|
+
/** A scalar list item's V2 validation → config.item: required, a text / rich text item's length, a text item's pattern. */
|
|
1468
|
+
function itemValidationToProd(item, itemType, out, at, ctx) {
|
|
1469
|
+
const val = item.validation;
|
|
1470
|
+
const lengthy = itemType === "text" || itemType === "richtext";
|
|
1471
|
+
for (const k of Object.keys(val)) {
|
|
1472
|
+
const v = val[k];
|
|
1473
|
+
if (v === void 0) continue;
|
|
1474
|
+
if (k === "required" && typeof v === "boolean") out.required = v;
|
|
1475
|
+
else if ((k === "min" || k === "max") && lengthy && isWhole(v)) out[k === "min" ? "minLength" : "maxLength"] = v;
|
|
1476
|
+
else if (k === "pattern" && itemType === "text" && typeof v === "string" && v.length <= 200 && compiles(v)) out.pattern = v;
|
|
1477
|
+
else if (k === "patternMessage" && typeof v === "string" && v.trim() !== "" && v.length <= 200) out.patternMessage = v;
|
|
1478
|
+
else lose(ctx, `${at}/${k}`, "item settings");
|
|
1479
|
+
}
|
|
1480
|
+
if (out.minLength !== void 0 && out.maxLength !== void 0 && out.minLength > out.maxLength) {
|
|
1481
|
+
delete out.minLength;
|
|
1482
|
+
delete out.maxLength;
|
|
1483
|
+
lose(ctx, `${at}/min`, "item settings");
|
|
1484
|
+
}
|
|
1485
|
+
if (out.patternMessage !== void 0 && out.pattern === void 0) {
|
|
1486
|
+
delete out.patternMessage;
|
|
1487
|
+
lose(ctx, `${at}/patternMessage`, "item settings");
|
|
1488
|
+
}
|
|
1489
|
+
}
|
|
1490
|
+
/** A slot's per-child settings → config.slotSettings: leaf sub-fields, at most SLOT_SETTINGS_MAX (slotSettingsHardening). */
|
|
1491
|
+
function slotSettingsToProd(settings, node, at, lv, ctx) {
|
|
1492
|
+
const kept = settings.slice(0, SLOT_SETTINGS_MAX);
|
|
1493
|
+
if (settings.length > SLOT_SETTINGS_MAX) settings.slice(SLOT_SETTINGS_MAX).forEach((_, i) => lose(ctx, `${at}/${SLOT_SETTINGS_MAX + i}`, "slotSettings"));
|
|
1494
|
+
node.slotSettings = kept.map((c, i) => convertField(c, `${at}/${i}`, lv + 1, ctx, kept, false, false, false, true));
|
|
1495
|
+
}
|
|
1496
|
+
/**
|
|
1497
|
+
* A polymorphic list's item types → config.itemTypes `{ name, label, fields }`: the name is what a row's `_type` holds,
|
|
1498
|
+
* the title its label, its icon and row preview `icon` / `preview` (paths over its own fields). One prod cannot name is
|
|
1499
|
+
* not stored, which moves the ones after it up a place, so the whole list is named.
|
|
1500
|
+
*/
|
|
1501
|
+
function itemTypesToProd(items, node, at, lv, ctx) {
|
|
1502
|
+
const names = /* @__PURE__ */ new Set();
|
|
1503
|
+
node.itemTypes = [];
|
|
1504
|
+
let dropped = false;
|
|
1505
|
+
items.forEach((item, i) => {
|
|
1506
|
+
const ip = `${at}/${i}`;
|
|
1507
|
+
const fields = item.fields ?? [];
|
|
1508
|
+
const why = !ITEM_TYPE_NAME.test(item.name) || !fields.length ? "item identity" : names.has(item.name) ? "duplicate name" : void 0;
|
|
1509
|
+
if (why) {
|
|
1510
|
+
lose(ctx, ip, why);
|
|
1511
|
+
dropped = true;
|
|
1512
|
+
return;
|
|
1513
|
+
}
|
|
1514
|
+
names.add(item.name);
|
|
1515
|
+
const label = trunc(ctx, `${ip}/title`, item.title, ITEM_TYPE_LABEL_MAX, "item identity");
|
|
1516
|
+
const children = fields.map((c, j) => convertField(c, `${ip}/fields/${j}`, lv + 1, ctx, fields, false, false, true));
|
|
1517
|
+
const type = {
|
|
1518
|
+
name: item.name,
|
|
1519
|
+
label,
|
|
1520
|
+
children
|
|
1521
|
+
};
|
|
1522
|
+
for (const k of Object.keys(item)) {
|
|
1523
|
+
if (item[k] === void 0 || k === "name" || k === "title" || k === "type" || k === "fields") continue;
|
|
1524
|
+
const p = `${ip}/${k}`;
|
|
1525
|
+
if (k === "preview") {
|
|
1526
|
+
const preview = previewToProd(item.preview, fields, p, ctx);
|
|
1527
|
+
if (nonEmpty(preview)) type.preview = preview;
|
|
1528
|
+
} else if (k === "icon") {
|
|
1529
|
+
const dock = dockIconOf(item.icon);
|
|
1530
|
+
if (dock) type.icon = dock;
|
|
1531
|
+
else lose(ctx, p, "item icon");
|
|
1532
|
+
} else if (k === "openMode") cat(ctx, p, "item openMode");
|
|
1533
|
+
else lose(ctx, p, "item identity");
|
|
1534
|
+
}
|
|
1535
|
+
node.itemTypes.push(type);
|
|
1536
|
+
});
|
|
1537
|
+
if (dropped && node.itemTypes.length < items.length && node.itemTypes.length) lose(ctx, at, "item identity");
|
|
1146
1538
|
}
|
|
1147
1539
|
/**
|
|
1148
1540
|
* A modular item type → the kind:'block' model its rows are stored against: the item title is the model name, its fields
|
|
@@ -1219,16 +1611,28 @@ function blockModelFor(item, at, ctx, list) {
|
|
|
1219
1611
|
ctx.catalog.length = startCat;
|
|
1220
1612
|
lose(ctx, at, "duplicate name");
|
|
1221
1613
|
}
|
|
1614
|
+
/**
|
|
1615
|
+
* A reference's targets: entry models → contentModelId / polymorphic + allowedModelSlugs; page, form and collection →
|
|
1616
|
+
* config.targets and the filter → config.filter (backend refTargetKeys, both lanes). Read back, entry models come first,
|
|
1617
|
+
* then the targets.
|
|
1618
|
+
*/
|
|
1222
1619
|
function referenceToConfig(ref, node, at, ctx) {
|
|
1223
1620
|
const to = ref.to ?? [];
|
|
1224
1621
|
const entries = to.filter(ENTRY_TARGET);
|
|
1225
|
-
|
|
1622
|
+
const targets = to.filter((t) => REF_TARGET_KINDS.includes(t));
|
|
1623
|
+
const kept = entries.length + targets.length;
|
|
1624
|
+
if (kept < to.length) lose(ctx, kept || !to.length ? `${at}/to` : at, "shopify reference");
|
|
1625
|
+
else if (to.join() !== [...entries, ...targets].join()) lose(ctx, `${at}/to`, "reference order");
|
|
1226
1626
|
if (entries.length === 1) node.config.contentModelId = entries[0];
|
|
1227
1627
|
else if (entries.length > 1) Object.assign(node.config, {
|
|
1228
1628
|
polymorphic: true,
|
|
1229
1629
|
allowedModelSlugs: entries
|
|
1230
1630
|
});
|
|
1231
|
-
if (
|
|
1631
|
+
if (targets.length) node.config.targets = targets;
|
|
1632
|
+
if (ref.filter !== void 0) {
|
|
1633
|
+
if (filterKept(ref.filter)) node.config.filter = ref.filter;
|
|
1634
|
+
else lose(ctx, `${at}/filter`, "reference filter");
|
|
1635
|
+
}
|
|
1232
1636
|
for (const k of Object.keys(ref)) if (k !== "to" && k !== "filter") lose(ctx, `${at}/${k}`, "unsupported key");
|
|
1233
1637
|
}
|
|
1234
1638
|
function numericToProd(f, node, at, ctx) {
|
|
@@ -1236,7 +1640,7 @@ function numericToProd(f, node, at, ctx) {
|
|
|
1236
1640
|
const n = f.numeric;
|
|
1237
1641
|
const lo = n.min ?? 0;
|
|
1238
1642
|
const hi = n.max ?? 5;
|
|
1239
|
-
const st = n.step ?? 1;
|
|
1643
|
+
const st = n.step ?? (f.type === "rating" ? V2_RATING_STEP : 1);
|
|
1240
1644
|
const stops = (hi - lo) / st;
|
|
1241
1645
|
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
1646
|
for (const k of Object.keys(n)) {
|
|
@@ -1247,13 +1651,14 @@ function numericToProd(f, node, at, ctx) {
|
|
|
1247
1651
|
const u = v;
|
|
1248
1652
|
if (f.type === "number" && typeof u === "string" && u.trim() !== "" && u.length <= 24) node.config.unit = u;
|
|
1249
1653
|
else lose(ctx, p, "numeric unit");
|
|
1250
|
-
} else if (k === "min" || k === "max" || k === "step")
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1654
|
+
} else if (k === "min" || k === "max" || k === "step") {
|
|
1655
|
+
if (f.type === "number") node.config[k] = v;
|
|
1656
|
+
else if (ratingOk) node.config[k] = v;
|
|
1657
|
+
else lose(ctx, p, "rating bounds");
|
|
1658
|
+
} else lose(ctx, p, "unsupported key");
|
|
1254
1659
|
}
|
|
1255
1660
|
}
|
|
1256
|
-
var SCALE_UNIT_SET = new Set([
|
|
1661
|
+
var SCALE_UNIT_SET = /* @__PURE__ */ new Set([
|
|
1257
1662
|
"px",
|
|
1258
1663
|
"%",
|
|
1259
1664
|
"rem",
|
|
@@ -1298,13 +1703,16 @@ function scaleToConfig(s, node, at, ctx) {
|
|
|
1298
1703
|
const v = s[k];
|
|
1299
1704
|
if (v === void 0 || k === "steps") continue;
|
|
1300
1705
|
const p = `${at}/${k}`;
|
|
1301
|
-
if (k === "units")
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
else
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
else if (k === "
|
|
1706
|
+
if (k === "units") {
|
|
1707
|
+
if (unitsOk(v)) out.units = [...v];
|
|
1708
|
+
else lose(ctx, p, "scale rules");
|
|
1709
|
+
} else if (k === "defaultUnit") {
|
|
1710
|
+
if (SCALE_UNIT_SET.has(v)) out.defaultUnit = s.defaultUnit;
|
|
1711
|
+
else lose(ctx, p, "scale rules");
|
|
1712
|
+
} else if (k === "allowCustom") {
|
|
1713
|
+
if (customOk) out.allowCustom = typeof c === "boolean" ? c : JSON.parse(JSON.stringify(c));
|
|
1714
|
+
else lose(ctx, p, "scale rules");
|
|
1715
|
+
} else if (k === "presets") {
|
|
1308
1716
|
const presets = s.presets;
|
|
1309
1717
|
if (presets.length <= 20 && presets.every((x) => {
|
|
1310
1718
|
if (x.label !== void 0 && !textOk(x.label, 24)) return false;
|
|
@@ -1322,45 +1730,102 @@ function scaleToConfig(s, node, at, ctx) {
|
|
|
1322
1730
|
}
|
|
1323
1731
|
node.config.scale = out;
|
|
1324
1732
|
}
|
|
1733
|
+
/** V2 operator → prod showIf op (the legacy `equals` / `notEmpty` forms read as is / is one of / has a value). */
|
|
1734
|
+
var SHOW_IF_OP = {
|
|
1735
|
+
is: "eq",
|
|
1736
|
+
isNot: "neq",
|
|
1737
|
+
in: "in",
|
|
1738
|
+
notIn: "notIn",
|
|
1739
|
+
empty: "empty",
|
|
1740
|
+
notEmpty: "notEmpty",
|
|
1741
|
+
gt: "gt",
|
|
1742
|
+
lt: "lt"
|
|
1743
|
+
};
|
|
1744
|
+
var VALUELESS = /* @__PURE__ */ new Set([
|
|
1745
|
+
"empty",
|
|
1746
|
+
"notEmpty",
|
|
1747
|
+
"isSet"
|
|
1748
|
+
]);
|
|
1325
1749
|
function conditionToShowIf(h, at, siblings, ctx, variantOk) {
|
|
1326
|
-
const
|
|
1327
|
-
|
|
1328
|
-
|
|
1750
|
+
const rules = [];
|
|
1751
|
+
for (const [i, r] of [h, ...h.also ?? []].entries()) {
|
|
1752
|
+
const rule = conditionRule(r, i === 0, siblings, variantOk);
|
|
1753
|
+
if (!rule) return void lose(ctx, at, "condition");
|
|
1754
|
+
rules.push(rule);
|
|
1755
|
+
}
|
|
1756
|
+
if (h.match !== void 0 && h.match !== "all" && h.match !== "any") return void lose(ctx, at, "condition");
|
|
1757
|
+
return {
|
|
1758
|
+
match: h.match ?? "all",
|
|
1759
|
+
rules
|
|
1760
|
+
};
|
|
1761
|
+
}
|
|
1762
|
+
/** One V2 rule as a prod rule, or null when prod cannot hold it (a scope, a non-sibling, a value showIf cannot test). */
|
|
1763
|
+
function conditionRule(r, head, siblings, variantOk) {
|
|
1764
|
+
const variant = variantOk && r.field === "_variant";
|
|
1765
|
+
if (!r.field || r.scope !== void 0 || !variant && !siblings.some((s) => s.name === r.field)) return null;
|
|
1766
|
+
const allowed = head ? [
|
|
1329
1767
|
"field",
|
|
1330
1768
|
"equals",
|
|
1331
|
-
"notEmpty"
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1769
|
+
"notEmpty",
|
|
1770
|
+
"op",
|
|
1771
|
+
"value",
|
|
1772
|
+
"also",
|
|
1773
|
+
"match"
|
|
1774
|
+
] : [
|
|
1775
|
+
"field",
|
|
1776
|
+
"equals",
|
|
1777
|
+
"notEmpty",
|
|
1778
|
+
"op",
|
|
1779
|
+
"value"
|
|
1780
|
+
];
|
|
1781
|
+
if (Object.keys(r).some((k) => !allowed.includes(k) && r[k] !== void 0)) return null;
|
|
1782
|
+
if ([
|
|
1783
|
+
r.op !== void 0,
|
|
1784
|
+
r.equals !== void 0,
|
|
1785
|
+
r.notEmpty !== void 0
|
|
1786
|
+
].filter(Boolean).length !== 1) return null;
|
|
1787
|
+
if (r.notEmpty !== void 0) return r.notEmpty === true ? {
|
|
1788
|
+
field: r.field,
|
|
1789
|
+
op: "notEmpty"
|
|
1790
|
+
} : null;
|
|
1791
|
+
const target = r.op !== void 0 ? r.value : r.equals;
|
|
1792
|
+
const op = r.op !== void 0 ? SHOW_IF_OP[r.op] : Array.isArray(target) ? "in" : "eq";
|
|
1793
|
+
if (!op) return null;
|
|
1794
|
+
if (VALUELESS.has(op)) return r.value === void 0 ? {
|
|
1795
|
+
field: r.field,
|
|
1796
|
+
op
|
|
1797
|
+
} : null;
|
|
1798
|
+
const sibType = variant ? void 0 : siblings.find((s) => s.name === r.field)?.type;
|
|
1799
|
+
if (op === "gt" || op === "lt") return typeof target === "number" && Number.isFinite(target) ? {
|
|
1800
|
+
field: r.field,
|
|
1801
|
+
op,
|
|
1802
|
+
value: String(target)
|
|
1803
|
+
} : null;
|
|
1804
|
+
const list = Array.isArray(target) ? target : [target];
|
|
1342
1805
|
const strs = [];
|
|
1343
1806
|
for (const v of list) {
|
|
1344
1807
|
if (![
|
|
1345
1808
|
"string",
|
|
1346
1809
|
"number",
|
|
1347
1810
|
"boolean"
|
|
1348
|
-
].includes(typeof v)) return
|
|
1811
|
+
].includes(typeof v)) return null;
|
|
1349
1812
|
const s = String(v);
|
|
1350
|
-
if (coerceRuleValue(sibType, s) !== v) return
|
|
1813
|
+
if (coerceRuleValue(sibType, s) !== v) return null;
|
|
1351
1814
|
strs.push(s);
|
|
1352
1815
|
}
|
|
1353
|
-
return {
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1816
|
+
if (op === "in" || op === "notIn") return {
|
|
1817
|
+
field: r.field,
|
|
1818
|
+
op,
|
|
1819
|
+
value: strs
|
|
1820
|
+
};
|
|
1821
|
+
return Array.isArray(target) ? strs.length ? {
|
|
1822
|
+
field: r.field,
|
|
1823
|
+
op: op === "eq" ? "in" : "notIn",
|
|
1824
|
+
value: strs
|
|
1825
|
+
} : null : {
|
|
1826
|
+
field: r.field,
|
|
1827
|
+
op,
|
|
1828
|
+
value: strs[0]
|
|
1364
1829
|
};
|
|
1365
1830
|
}
|
|
1366
1831
|
var nonEmpty = (o) => Object.keys(o).length ? o : void 0;
|
|
@@ -1379,7 +1844,8 @@ function common(n) {
|
|
|
1379
1844
|
"advanced",
|
|
1380
1845
|
"recommendedMax",
|
|
1381
1846
|
"openMode",
|
|
1382
|
-
"localized"
|
|
1847
|
+
"localized",
|
|
1848
|
+
"archived"
|
|
1383
1849
|
]) if (n[k] !== void 0) out[k] = n[k];
|
|
1384
1850
|
return out;
|
|
1385
1851
|
}
|
|
@@ -1394,6 +1860,7 @@ function emitField(n) {
|
|
|
1394
1860
|
if (n.type === "select" && n.options) out.options = n.options;
|
|
1395
1861
|
if ((n.type === "multiselect" || n.type === "tags") && n.options) config.options = n.options;
|
|
1396
1862
|
if (n.type === "object") out.fields = (n.children ?? []).map(emitField);
|
|
1863
|
+
if (n.slotSettings) config.slotSettings = n.slotSettings.map(emitField);
|
|
1397
1864
|
if (n.zoned) {
|
|
1398
1865
|
const { minItems, maxItems, ...rest } = config;
|
|
1399
1866
|
out.config = {
|
|
@@ -1418,6 +1885,8 @@ function emitProp(n) {
|
|
|
1418
1885
|
const config = { ...n.config };
|
|
1419
1886
|
if (n.options) config.options = n.options;
|
|
1420
1887
|
if (n.children) config.fields = n.children.map(emitSubField);
|
|
1888
|
+
if (n.itemTypes) config.itemTypes = emitItemTypes(n.itemTypes);
|
|
1889
|
+
if (n.slotSettings) config.slotSettings = n.slotSettings.map(emitSubField);
|
|
1421
1890
|
if (nonEmpty(config)) out.config = config;
|
|
1422
1891
|
const ui = nonEmpty(n.ui);
|
|
1423
1892
|
if (ui) out.ui = ui;
|
|
@@ -1431,11 +1900,22 @@ function emitSubField(n) {
|
|
|
1431
1900
|
if (n.placeholder !== void 0) out.placeholder = n.placeholder;
|
|
1432
1901
|
if (n.options) out.options = n.options;
|
|
1433
1902
|
if (n.children) out.fields = n.children.map(emitSubField);
|
|
1434
|
-
|
|
1903
|
+
const config = { ...n.config };
|
|
1904
|
+
if (n.itemTypes) config.itemTypes = emitItemTypes(n.itemTypes);
|
|
1905
|
+
if (n.slotSettings) config.slotSettings = n.slotSettings.map(emitSubField);
|
|
1906
|
+
if (nonEmpty(config)) out.config = config;
|
|
1435
1907
|
const ui = nonEmpty(n.ui);
|
|
1436
1908
|
if (ui) out.ui = ui;
|
|
1437
1909
|
return out;
|
|
1438
1910
|
}
|
|
1911
|
+
/** A polymorphic list's item types as the backend stores them: `{ name, label, fields }` (typesTableHardening). */
|
|
1912
|
+
var emitItemTypes = (types) => types.map((t) => ({
|
|
1913
|
+
name: t.name,
|
|
1914
|
+
label: t.label,
|
|
1915
|
+
fields: t.children.map(emitSubField),
|
|
1916
|
+
...t.icon ? { icon: t.icon } : {},
|
|
1917
|
+
...t.preview ? { preview: t.preview } : {}
|
|
1918
|
+
}));
|
|
1439
1919
|
function fromTypeSchema(v2, target) {
|
|
1440
1920
|
const ctx = {
|
|
1441
1921
|
lane: target,
|
|
@@ -1448,6 +1928,10 @@ function fromTypeSchema(v2, target) {
|
|
|
1448
1928
|
definedGroups: /* @__PURE__ */ new WeakMap(),
|
|
1449
1929
|
propOrder: /* @__PURE__ */ new Map(),
|
|
1450
1930
|
groupOrder: false,
|
|
1931
|
+
propTabs: /* @__PURE__ */ new Map(),
|
|
1932
|
+
definedTabs: /* @__PURE__ */ new Set(),
|
|
1933
|
+
keptTabs: /* @__PURE__ */ new Set(),
|
|
1934
|
+
declaredTabs: [],
|
|
1451
1935
|
blockModels: /* @__PURE__ */ new Map()
|
|
1452
1936
|
};
|
|
1453
1937
|
const props = target === "props";
|
|
@@ -1471,10 +1955,10 @@ function fromTypeSchema(v2, target) {
|
|
|
1471
1955
|
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
1956
|
break;
|
|
1473
1957
|
case "icon":
|
|
1474
|
-
cat(ctx, p, "block icon");
|
|
1958
|
+
if (!props || !dockIconOf(v2.icon)) cat(ctx, p, "block icon");
|
|
1475
1959
|
break;
|
|
1476
1960
|
case "preview":
|
|
1477
|
-
cat(ctx, p, "document preview");
|
|
1961
|
+
if (!props) cat(ctx, p, "document preview");
|
|
1478
1962
|
break;
|
|
1479
1963
|
case "variants":
|
|
1480
1964
|
cat(ctx, p, "variants");
|
|
@@ -1492,7 +1976,7 @@ function fromTypeSchema(v2, target) {
|
|
|
1492
1976
|
}
|
|
1493
1977
|
}
|
|
1494
1978
|
if (props) {
|
|
1495
|
-
|
|
1979
|
+
propTabsFor(v2, ctx);
|
|
1496
1980
|
propSetsFor(v2, ctx);
|
|
1497
1981
|
} else fieldsetsFor(v2, ctx, fieldsets);
|
|
1498
1982
|
const nodes = v2.fields.map((f, i) => convertField(f, `/fields/${i}`, 1, ctx, v2.fields, true));
|
|
@@ -1504,6 +1988,13 @@ function fromTypeSchema(v2, target) {
|
|
|
1504
1988
|
};
|
|
1505
1989
|
if (v2.description !== void 0) component.description = v2.description;
|
|
1506
1990
|
if (category) component.category = category;
|
|
1991
|
+
const icon = v2.icon === void 0 ? void 0 : dockIconOf(v2.icon);
|
|
1992
|
+
if (icon) component.icon = icon;
|
|
1993
|
+
if (v2.preview !== void 0) {
|
|
1994
|
+
const preview = componentPreviewToProd(v2.preview, new Set(component.props.map((x) => x.key)), v2.fields, "/preview", ctx);
|
|
1995
|
+
if (Object.keys(preview).length) component.preview = preview;
|
|
1996
|
+
}
|
|
1997
|
+
if (ctx.declaredTabs.length) component.tabs = ctx.declaredTabs.map((t) => ({ ...t }));
|
|
1507
1998
|
return {
|
|
1508
1999
|
schema: component,
|
|
1509
2000
|
blockModels: [],
|
|
@@ -1533,7 +2024,7 @@ function fieldsetsFor(v2, ctx, out) {
|
|
|
1533
2024
|
let shifted = false;
|
|
1534
2025
|
(v2.groups ?? []).forEach((g, i) => {
|
|
1535
2026
|
const p = `/groups/${i}`;
|
|
1536
|
-
const stored = g.title.slice(0,
|
|
2027
|
+
const stored = g.title.slice(0, 40);
|
|
1537
2028
|
const folded = stored.trim().toLowerCase();
|
|
1538
2029
|
const drop = (why) => {
|
|
1539
2030
|
if (!ctx.tabs.has(g.name) && !ctx.droppedTabs.has(g.name)) ctx.droppedTabs.set(g.name, why);
|
|
@@ -1541,14 +2032,14 @@ function fieldsetsFor(v2, ctx, out) {
|
|
|
1541
2032
|
lose(ctx, p, why);
|
|
1542
2033
|
};
|
|
1543
2034
|
if (ctx.tabs.has(g.name) || names.has(folded)) return drop("group name collision");
|
|
1544
|
-
if (out.length >=
|
|
2035
|
+
if (out.length >= TAB_MAX$1) return drop("groups>3");
|
|
1545
2036
|
names.add(folded);
|
|
1546
2037
|
const tab = {
|
|
1547
2038
|
id: g.name,
|
|
1548
2039
|
name: stored,
|
|
1549
2040
|
kind: "tab"
|
|
1550
2041
|
};
|
|
1551
|
-
if (g.title.length >
|
|
2042
|
+
if (g.title.length > 40) lose(ctx, `${p}/title`, "group name>40");
|
|
1552
2043
|
if (g.icon !== void 0) {
|
|
1553
2044
|
const dock = dockIconOf(g.icon);
|
|
1554
2045
|
if (dock) tab.icon = dock;
|
|
@@ -1585,9 +2076,10 @@ function fieldsetsFor(v2, ctx, out) {
|
|
|
1585
2076
|
for (const k of Object.keys(fs)) {
|
|
1586
2077
|
const v = fs[k];
|
|
1587
2078
|
if (v === void 0 || k === "name" || k === "title") continue;
|
|
1588
|
-
if (k === "description")
|
|
1589
|
-
|
|
1590
|
-
|
|
2079
|
+
if (k === "description") {
|
|
2080
|
+
if (v.length <= FIELDSET_DESCRIPTION_MAX) set.description = v;
|
|
2081
|
+
else lose(ctx, `${p}/${k}`, "help>limit");
|
|
2082
|
+
} else if (k === "collapsed" || k === "collapsible" || k === "columns" || k === "layout") set[k] = v;
|
|
1591
2083
|
else lose(ctx, `${p}/${k}`, "unsupported key");
|
|
1592
2084
|
}
|
|
1593
2085
|
ctx.sets.set(fs.name, tab);
|
|
@@ -1595,25 +2087,146 @@ function fieldsetsFor(v2, ctx, out) {
|
|
|
1595
2087
|
});
|
|
1596
2088
|
}
|
|
1597
2089
|
/**
|
|
2090
|
+
* Props lane: V2 groups → each top-level prop's `ui.tab`, defined on the first prop in it (label, icon, and `order` when
|
|
2091
|
+
* the V2 order differs from where each tab is first used). A field with no group sits in the V2 default group; a group
|
|
2092
|
+
* not stored puts its fields in the default tab; a fieldset's top-level members share the tab most of them sit in
|
|
2093
|
+
* (prop_group_split_tabs). No groups → no tab anywhere, so a component without tabs stores as before.
|
|
2094
|
+
*/
|
|
2095
|
+
function propTabsFor(v2, ctx) {
|
|
2096
|
+
const groups = v2.groups ?? [];
|
|
2097
|
+
const kept = [];
|
|
2098
|
+
const dropped = /* @__PURE__ */ new Map();
|
|
2099
|
+
const labels = /* @__PURE__ */ new Set();
|
|
2100
|
+
groups.forEach((g, i) => {
|
|
2101
|
+
const p = `/groups/${i}`;
|
|
2102
|
+
const drop = (why) => {
|
|
2103
|
+
if (!kept.some((k) => k.g.name === g.name) && !dropped.has(g.name)) dropped.set(g.name, why);
|
|
2104
|
+
lose(ctx, p, why);
|
|
2105
|
+
};
|
|
2106
|
+
const label = g.title.slice(0, 40).trim();
|
|
2107
|
+
const folded = label.toLowerCase();
|
|
2108
|
+
if (kept.some((k) => k.g.name === g.name) || labels.has(folded)) return drop("group name collision");
|
|
2109
|
+
if (kept.length >= PROP_TAB_MAX || g.name.length < 1 || g.name.length > 40) return drop("prop tab limit");
|
|
2110
|
+
if (!label) return drop("group title");
|
|
2111
|
+
labels.add(folded);
|
|
2112
|
+
const tab = {
|
|
2113
|
+
id: g.name,
|
|
2114
|
+
label
|
|
2115
|
+
};
|
|
2116
|
+
if (label !== g.title.trim()) lose(ctx, `${p}/title`, "group name>40");
|
|
2117
|
+
else if (label !== g.title) lose(ctx, `${p}/title`, "group title");
|
|
2118
|
+
if (g.icon !== void 0) {
|
|
2119
|
+
const dock = dockIconOf(g.icon);
|
|
2120
|
+
if (dock) tab.icon = dock;
|
|
2121
|
+
else lose(ctx, `${p}/icon`, "group icon");
|
|
2122
|
+
}
|
|
2123
|
+
if (i === 0 ? g.default !== true : g.default !== void 0) lose(ctx, `${p}/default`, "group default");
|
|
2124
|
+
for (const k of Object.keys(g)) if (![
|
|
2125
|
+
"name",
|
|
2126
|
+
"title",
|
|
2127
|
+
"icon",
|
|
2128
|
+
"default"
|
|
2129
|
+
].includes(k) && g[k] !== void 0) lose(ctx, `${p}/${k}`, "unsupported key");
|
|
2130
|
+
kept.push({
|
|
2131
|
+
g,
|
|
2132
|
+
i,
|
|
2133
|
+
tab
|
|
2134
|
+
});
|
|
2135
|
+
});
|
|
2136
|
+
const isKept = (name) => name !== void 0 && kept.some((k) => k.g.name === name);
|
|
2137
|
+
const v2Default = (groups.find((g) => g.default) ?? groups[0])?.name;
|
|
2138
|
+
const fallback = isKept(v2Default) ? v2Default : kept[0]?.g.name;
|
|
2139
|
+
const place = /* @__PURE__ */ new Map();
|
|
2140
|
+
for (const f of v2.fields) {
|
|
2141
|
+
const want = f.group ?? v2Default;
|
|
2142
|
+
if (isKept(want)) place.set(f, { tab: want });
|
|
2143
|
+
else if (f.group !== void 0 || want !== void 0) place.set(f, {
|
|
2144
|
+
tab: fallback,
|
|
2145
|
+
loss: dropped.get(want) ?? "unsupported key"
|
|
2146
|
+
});
|
|
2147
|
+
}
|
|
2148
|
+
if (!kept.length) {
|
|
2149
|
+
for (const [f, t] of place) if (f.group !== void 0) ctx.propTabs.set(f, { loss: t.loss });
|
|
2150
|
+
return;
|
|
2151
|
+
}
|
|
2152
|
+
const tally = /* @__PURE__ */ new Map();
|
|
2153
|
+
for (const f of v2.fields) {
|
|
2154
|
+
if (f.fieldset === void 0) continue;
|
|
2155
|
+
const t = tally.get(f.fieldset) ?? /* @__PURE__ */ new Map();
|
|
2156
|
+
t.set(place.get(f)?.tab, (t.get(place.get(f)?.tab) ?? 0) + 1);
|
|
2157
|
+
tally.set(f.fieldset, t);
|
|
2158
|
+
}
|
|
2159
|
+
for (const f of v2.fields) {
|
|
2160
|
+
const counts = f.fieldset !== void 0 ? tally.get(f.fieldset) : void 0;
|
|
2161
|
+
if (!counts) continue;
|
|
2162
|
+
const best = [...counts.entries()].sort((a, b) => b[1] - a[1])[0][0];
|
|
2163
|
+
const cur = place.get(f);
|
|
2164
|
+
if (cur?.tab !== best) place.set(f, {
|
|
2165
|
+
tab: best,
|
|
2166
|
+
loss: cur?.loss ?? "fieldset spans groups"
|
|
2167
|
+
});
|
|
2168
|
+
}
|
|
2169
|
+
const firstUse = [];
|
|
2170
|
+
for (const f of v2.fields) {
|
|
2171
|
+
const t = place.get(f)?.tab;
|
|
2172
|
+
if (t !== void 0 && !firstUse.includes(t)) firstUse.push(t);
|
|
2173
|
+
}
|
|
2174
|
+
const used = kept.filter((k) => firstUse.includes(k.g.name));
|
|
2175
|
+
const unused = kept.filter((k) => !firstUse.includes(k.g.name));
|
|
2176
|
+
for (const k of kept) ctx.keptTabs.add(k.g.name);
|
|
2177
|
+
const firstGap = groups.findIndex((g) => !kept.some((k) => k.g === g));
|
|
2178
|
+
if (firstGap >= 0 && kept.some((k) => k.i > firstGap)) {
|
|
2179
|
+
const g = groups[firstGap];
|
|
2180
|
+
lose(ctx, "/groups", dropped.get(g.name) ?? "unsupported key");
|
|
2181
|
+
}
|
|
2182
|
+
const ordered = unused.length > 0 || used.some((k, i) => k.g.name !== firstUse[i]);
|
|
2183
|
+
kept.forEach((k, i) => {
|
|
2184
|
+
if (ordered) k.tab.order = Math.min(99, i);
|
|
2185
|
+
});
|
|
2186
|
+
ctx.declaredTabs = unused.map((k) => k.tab);
|
|
2187
|
+
for (const [f, t] of place) {
|
|
2188
|
+
const k = used.find((u) => u.g.name === t.tab);
|
|
2189
|
+
if (k) ctx.propTabs.set(f, {
|
|
2190
|
+
tab: k.tab,
|
|
2191
|
+
loss: t.loss
|
|
2192
|
+
});
|
|
2193
|
+
else if (t.loss) ctx.propTabs.set(f, { loss: t.loss });
|
|
2194
|
+
}
|
|
2195
|
+
}
|
|
2196
|
+
/**
|
|
1598
2197
|
* Props lane: a V2 fieldset is an inline ui.group, defined on the first prop (at each level, sub-fields too) that uses
|
|
1599
2198
|
* it. A fieldset no prop uses has nothing to be defined on; when the V2 order differs from where each group is first
|
|
1600
2199
|
* met (depth first, a prop before its sub-fields: how propsToTypeSchema meets them), every group carries its `order`.
|
|
1601
2200
|
*/
|
|
1602
2201
|
function propSetsFor(v2, ctx) {
|
|
1603
2202
|
const sets = v2.fieldsets ?? [];
|
|
1604
|
-
if (!sets.length) return;
|
|
1605
2203
|
const named = new Set(sets.map((s) => s.name));
|
|
1606
2204
|
const firstSeen = [];
|
|
2205
|
+
const undeclared = [];
|
|
1607
2206
|
const visit = (fields, lv) => {
|
|
1608
2207
|
for (const f of fields) {
|
|
1609
|
-
if (f.fieldset !== void 0 &&
|
|
1610
|
-
|
|
2208
|
+
if (f.fieldset !== void 0 && !firstSeen.includes(f.fieldset)) {
|
|
2209
|
+
firstSeen.push(f.fieldset);
|
|
2210
|
+
if (!named.has(f.fieldset)) undeclared.push(f.fieldset);
|
|
2211
|
+
}
|
|
2212
|
+
if (lv >= MAX_FIELD_DEPTH) continue;
|
|
1611
2213
|
const kids = previewKids(f);
|
|
1612
2214
|
if (kids) visit(kids, lv + 1);
|
|
1613
2215
|
}
|
|
1614
2216
|
};
|
|
1615
2217
|
visit(v2.fields, 1);
|
|
1616
|
-
|
|
2218
|
+
const derived = undeclared.map((name) => ({
|
|
2219
|
+
name,
|
|
2220
|
+
title: name
|
|
2221
|
+
}));
|
|
2222
|
+
const declaredUsed = sets.filter((s) => firstSeen.includes(s.name)).length;
|
|
2223
|
+
derived.forEach((s, j) => {
|
|
2224
|
+
ctx.propSets.set(s.name, s);
|
|
2225
|
+
ctx.propOrder.set(s.name, sets.length + j);
|
|
2226
|
+
cat(ctx, `/fieldsets/${declaredUsed + j}`, "fieldset (derived)");
|
|
2227
|
+
});
|
|
2228
|
+
if (!sets.length && !derived.length) return;
|
|
2229
|
+
ctx.groupOrder = [...sets, ...derived].filter((s) => firstSeen.includes(s.name)).some((s, i) => s.name !== firstSeen[i]);
|
|
1617
2230
|
let gap = false;
|
|
1618
2231
|
sets.forEach((s, i) => {
|
|
1619
2232
|
ctx.propSets.set(s.name, s);
|
|
@@ -1654,6 +2267,10 @@ function readField(f) {
|
|
|
1654
2267
|
delete cfg.options;
|
|
1655
2268
|
}
|
|
1656
2269
|
n.fields = f.fields?.map(readField);
|
|
2270
|
+
if (f.type === "array" && !cfg.zones && Array.isArray(cfg.fields)) {
|
|
2271
|
+
n.fields = [...n.fields ?? [], ...cfg.fields.map(readField)];
|
|
2272
|
+
delete cfg.fields;
|
|
2273
|
+
}
|
|
1657
2274
|
if (cfg.zones) {
|
|
1658
2275
|
const z = cfg.zones;
|
|
1659
2276
|
n.zones = {
|
|
@@ -1717,12 +2334,32 @@ function scaleFromConfig(s, at, ctx) {
|
|
|
1717
2334
|
}));
|
|
1718
2335
|
return out;
|
|
1719
2336
|
}
|
|
2337
|
+
/**
|
|
2338
|
+
* Slot children with each `_variant` written as the family member that places it (`_type`): the variant the child's
|
|
2339
|
+
* component already is drops, another member swaps in. A variant no member places stays, and the write names it lost.
|
|
2340
|
+
*/
|
|
2341
|
+
function childVariantsToTypes(v, family) {
|
|
2342
|
+
if (!Array.isArray(v)) return v;
|
|
2343
|
+
return v.map((c) => {
|
|
2344
|
+
if (!isObj(c) || typeof c._variant !== "string") return c;
|
|
2345
|
+
const own = family(typeof c._type === "string" ? c._type : "");
|
|
2346
|
+
const { _variant: _gone, ...rest } = c;
|
|
2347
|
+
if (own?.current === c._variant) return rest;
|
|
2348
|
+
const member = own?.member(c._variant);
|
|
2349
|
+
if (!member) return c;
|
|
2350
|
+
return {
|
|
2351
|
+
...rest,
|
|
2352
|
+
_type: member
|
|
2353
|
+
};
|
|
2354
|
+
});
|
|
2355
|
+
}
|
|
1720
2356
|
/** 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
2357
|
var readKids = (n) => n.zones ? [...n.zones.nonRepeatable ?? [], ...n.zones.repeatable?.fields ?? []] : n.fields && [
|
|
1722
2358
|
"object",
|
|
1723
2359
|
"group",
|
|
1724
2360
|
"repeater",
|
|
1725
|
-
"table"
|
|
2361
|
+
"table",
|
|
2362
|
+
"array"
|
|
1726
2363
|
].includes(n.type) ? n.fields : null;
|
|
1727
2364
|
/** A stored preview path → the V2 path: `image.altText` reads as `image.alt`, the rest as it is. */
|
|
1728
2365
|
function previewPathFromProd(path, children) {
|
|
@@ -1753,12 +2390,26 @@ function previewFromProd(pv, children) {
|
|
|
1753
2390
|
return out;
|
|
1754
2391
|
}
|
|
1755
2392
|
function showIfToCondition(s, siblings, at, ctx) {
|
|
1756
|
-
const
|
|
1757
|
-
|
|
1758
|
-
|
|
2393
|
+
const conds = [];
|
|
2394
|
+
for (const r of s.rules) {
|
|
2395
|
+
const c = showIfRuleToCondition(r, siblings);
|
|
2396
|
+
if (!c) return void ctx.onLoss(at, "condition", `V2 conditions have no "${r.op}" with this value; the field always shows.`);
|
|
2397
|
+
conds.push(c);
|
|
2398
|
+
}
|
|
2399
|
+
if (!conds.length) return void 0;
|
|
2400
|
+
const [head, ...also] = conds;
|
|
2401
|
+
return {
|
|
2402
|
+
...head,
|
|
2403
|
+
...also.length ? { also } : {},
|
|
2404
|
+
...s.match === "any" && conds.length > 1 ? { match: "any" } : {}
|
|
2405
|
+
};
|
|
2406
|
+
}
|
|
2407
|
+
/** One prod rule as a V2 rule: eq / in / isSet keep V2's legacy forms, the rest name their `op`. */
|
|
2408
|
+
function showIfRuleToCondition(r, siblings) {
|
|
1759
2409
|
const sib = siblings.find((x) => x.key === r.field);
|
|
1760
2410
|
const t = sib?.type === "number" ? "number" : sib?.type;
|
|
1761
2411
|
const read = (v) => coerceRuleValue(t, v);
|
|
2412
|
+
const list = (Array.isArray(r.value) ? r.value : [r.value ?? ""]).map(read);
|
|
1762
2413
|
switch (r.op) {
|
|
1763
2414
|
case "eq": return Array.isArray(r.value) ? {
|
|
1764
2415
|
field: r.field,
|
|
@@ -1769,14 +2420,37 @@ function showIfToCondition(s, siblings, at, ctx) {
|
|
|
1769
2420
|
};
|
|
1770
2421
|
case "in": return {
|
|
1771
2422
|
field: r.field,
|
|
1772
|
-
equals:
|
|
2423
|
+
equals: list
|
|
1773
2424
|
};
|
|
1774
2425
|
case "isSet":
|
|
1775
2426
|
case "notEmpty": return {
|
|
1776
2427
|
field: r.field,
|
|
1777
2428
|
notEmpty: true
|
|
1778
2429
|
};
|
|
1779
|
-
|
|
2430
|
+
case "empty": return {
|
|
2431
|
+
field: r.field,
|
|
2432
|
+
op: "empty"
|
|
2433
|
+
};
|
|
2434
|
+
case "neq": return {
|
|
2435
|
+
field: r.field,
|
|
2436
|
+
op: "isNot",
|
|
2437
|
+
value: Array.isArray(r.value) ? list : read(r.value ?? "")
|
|
2438
|
+
};
|
|
2439
|
+
case "notIn": return {
|
|
2440
|
+
field: r.field,
|
|
2441
|
+
op: "notIn",
|
|
2442
|
+
value: list
|
|
2443
|
+
};
|
|
2444
|
+
case "gt":
|
|
2445
|
+
case "lt": {
|
|
2446
|
+
const n = Number(r.value);
|
|
2447
|
+
return typeof r.value === "string" && r.value.trim() !== "" && Number.isFinite(n) ? {
|
|
2448
|
+
field: r.field,
|
|
2449
|
+
op: r.op,
|
|
2450
|
+
value: n
|
|
2451
|
+
} : void 0;
|
|
2452
|
+
}
|
|
2453
|
+
default: return;
|
|
1780
2454
|
}
|
|
1781
2455
|
}
|
|
1782
2456
|
function v2Type(n, at, ctx) {
|
|
@@ -1811,9 +2485,14 @@ function v2Type(n, at, ctx) {
|
|
|
1811
2485
|
}
|
|
1812
2486
|
}
|
|
1813
2487
|
function readToV2(n, at, siblings, ctx, top, lane) {
|
|
1814
|
-
/** a data
|
|
1815
|
-
|
|
1816
|
-
const
|
|
2488
|
+
/** a data table holds one TableValue: the V2 `table` field, not a list of rows. A prop says so (config.mode "data");
|
|
2489
|
+
* a field's table is always one (BE tableFieldSchema: `mode` is optional there and can only be "data") */
|
|
2490
|
+
const dataTable = isDataTableProp(n) || lane === "fields" && n.type === "table";
|
|
2491
|
+
/** a slot prop: component instances, read as the V2 slot (its children `{ _key, _type, _settings?, ...props }`) */
|
|
2492
|
+
const slotProp = lane === "props" && n.type === "slot";
|
|
2493
|
+
/** a model slot field: inline children of the kind:'block' models config.blockSlugs names */
|
|
2494
|
+
const blockSlot = lane === "fields" && n.type === "slot";
|
|
2495
|
+
const type = dataTable ? "table" : slotProp || blockSlot ? "slot" : v2Type(n, at, ctx);
|
|
1817
2496
|
const f = {
|
|
1818
2497
|
name: n.key,
|
|
1819
2498
|
title: n.label,
|
|
@@ -1822,7 +2501,7 @@ function readToV2(n, at, siblings, ctx, top, lane) {
|
|
|
1822
2501
|
const cfg = n.config;
|
|
1823
2502
|
const val = {};
|
|
1824
2503
|
const loss = (k, feature, reason) => ctx.onLoss(`${at}/${k}`, feature, reason);
|
|
1825
|
-
if (n.helpText
|
|
2504
|
+
if (typeof n.helpText === "string") f.description = n.helpText;
|
|
1826
2505
|
if (n.helpMore !== void 0) f.helpMore = n.helpMore;
|
|
1827
2506
|
if (n.placeholder !== void 0) f.placeholder = n.placeholder;
|
|
1828
2507
|
if (n.required !== void 0) val.required = n.required;
|
|
@@ -1831,9 +2510,18 @@ function readToV2(n, at, siblings, ctx, top, lane) {
|
|
|
1831
2510
|
if (n.advanced !== void 0) f.advanced = n.advanced;
|
|
1832
2511
|
if (n.openMode !== void 0) f.openMode = n.openMode;
|
|
1833
2512
|
if (n.readOnly === true) f.readOnly = true;
|
|
2513
|
+
if (n.archived === true) f.archived = true;
|
|
1834
2514
|
if (n.ui.access) f.access = { ...n.ui.access };
|
|
1835
2515
|
else if (n.readOnly === "developer") f.access = { edit: "schema.manage" };
|
|
1836
2516
|
if (n.lockReason !== void 0) f.lockReason = n.lockReason;
|
|
2517
|
+
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");
|
|
2518
|
+
if (shopify) {
|
|
2519
|
+
delete f.lockReason;
|
|
2520
|
+
if (n.type === "text") {
|
|
2521
|
+
f.type = "reference";
|
|
2522
|
+
f.reference = { to: ["shopify"] };
|
|
2523
|
+
}
|
|
2524
|
+
}
|
|
1837
2525
|
if (n.localized !== void 0) f.localized = n.localized;
|
|
1838
2526
|
if (n.ui.hidden !== void 0) f.hidden = n.ui.hidden;
|
|
1839
2527
|
if (n.ui.rows !== void 0) f.rows = n.ui.rows;
|
|
@@ -1850,26 +2538,28 @@ function readToV2(n, at, siblings, ctx, top, lane) {
|
|
|
1850
2538
|
if (n.ui.input !== void 0) loss("ui/input", "ui.input", "Custom dock inputs are a dock feature V2 has no key for.");
|
|
1851
2539
|
if (n.fieldsetId !== void 0) {
|
|
1852
2540
|
const set = ctx.sets.get(n.fieldsetId);
|
|
1853
|
-
if (set?.kind === "tab")
|
|
1854
|
-
|
|
1855
|
-
|
|
2541
|
+
if (set?.kind === "tab") {
|
|
2542
|
+
if (top) f.group = set.id;
|
|
2543
|
+
else loss("fieldsetId", "fieldset", "Only top-level V2 fields sit in a tab; this nested field's tab is dropped.");
|
|
2544
|
+
} else if (set) {
|
|
1856
2545
|
f.fieldset = set.id;
|
|
1857
2546
|
if (top && set.tab !== void 0) f.group = set.tab;
|
|
1858
2547
|
} else loss("fieldsetId", "fieldset", `No fieldset "${n.fieldsetId}" exists on this model; the membership is dropped.`);
|
|
1859
2548
|
}
|
|
1860
2549
|
if (lane === "props" && n.ui.group) f.fieldset = n.ui.group.id;
|
|
2550
|
+
if (lane === "props" && n.ui.tab) f.group = n.ui.tab.id;
|
|
1861
2551
|
for (const k of [
|
|
1862
2552
|
"target",
|
|
1863
2553
|
"stale",
|
|
1864
2554
|
"origin"
|
|
1865
2555
|
]) 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([
|
|
2556
|
+
const used = /* @__PURE__ */ new Set([
|
|
1867
2557
|
"placeholder",
|
|
1868
2558
|
"zones",
|
|
1869
2559
|
"options",
|
|
1870
2560
|
"fields"
|
|
1871
2561
|
]);
|
|
1872
|
-
const usedUi = new Set([
|
|
2562
|
+
const usedUi = /* @__PURE__ */ new Set([
|
|
1873
2563
|
"collapsed",
|
|
1874
2564
|
"reorderable",
|
|
1875
2565
|
"input",
|
|
@@ -1882,6 +2572,13 @@ function readToV2(n, at, siblings, ctx, top, lane) {
|
|
|
1882
2572
|
const use = (...k) => k.forEach((x) => used.add(x));
|
|
1883
2573
|
const useUi = (...k) => k.forEach((x) => usedUi.add(x));
|
|
1884
2574
|
if (lane === "props") useUi("group");
|
|
2575
|
+
if (lane === "props") useUi("tab");
|
|
2576
|
+
if (RICH_TYPES.has(n.type) && cfg.features !== void 0) {
|
|
2577
|
+
use("features");
|
|
2578
|
+
const { kept, named } = richFeatures(cfg.features);
|
|
2579
|
+
if (named) loss("config/features", "richtext features", FEATURES["richtext features"].reason);
|
|
2580
|
+
if (kept.length < ALL_RICH_FEATURES.length) f.features = kept;
|
|
2581
|
+
}
|
|
1885
2582
|
if ([
|
|
1886
2583
|
"text",
|
|
1887
2584
|
"longtext",
|
|
@@ -1902,6 +2599,10 @@ function readToV2(n, at, siblings, ctx, top, lane) {
|
|
|
1902
2599
|
"max",
|
|
1903
2600
|
"step"
|
|
1904
2601
|
]) if (typeof cfg[k] === "number") numeric[k] = cfg[k];
|
|
2602
|
+
if (n.type === "rating") {
|
|
2603
|
+
if (numeric.step === V2_RATING_STEP) delete numeric.step;
|
|
2604
|
+
else if (numeric.step === void 0) numeric.step = 1;
|
|
2605
|
+
}
|
|
1905
2606
|
const ratingDefault = type === "rating" && n.type === "number" && ratingIsDefault(numeric);
|
|
1906
2607
|
if (typeof cfg.unit === "string") numeric.unit = cfg.unit;
|
|
1907
2608
|
if (Object.keys(numeric).length && !ratingDefault) f.numeric = numeric;
|
|
@@ -1920,6 +2621,12 @@ function readToV2(n, at, siblings, ctx, top, lane) {
|
|
|
1920
2621
|
useUi("control");
|
|
1921
2622
|
}
|
|
1922
2623
|
if (n.type === "select") use("multiSelect");
|
|
2624
|
+
if (n.type === "image") {
|
|
2625
|
+
use("media");
|
|
2626
|
+
if (cfg.media === "icon") f.svgOnly = true;
|
|
2627
|
+
}
|
|
2628
|
+
if (typeof cfg.linkHref === "string" && cfg.linkHref) f.linkHref = cfg.linkHref;
|
|
2629
|
+
use("linkHref");
|
|
1923
2630
|
if ((type === "select" || type === "multiselect" || type === "tags") && n.options) f.options = optionsFromProd(n.options);
|
|
1924
2631
|
if (type === "multiselect" || type === "tags") {
|
|
1925
2632
|
if (typeof cfg.min === "number") val.min = cfg.min;
|
|
@@ -1937,10 +2644,10 @@ function readToV2(n, at, siblings, ctx, top, lane) {
|
|
|
1937
2644
|
if (type === "date" || type === "datetime") use("timezone", "includeTime");
|
|
1938
2645
|
if ((type === "date" || type === "datetime") && typeof cfg.timezone === "string") f.timezone = cfg.timezone === "site" ? "site" : `fixed:${cfg.timezone}`;
|
|
1939
2646
|
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");
|
|
2647
|
+
if (n.type === "reference" || n.type === "multi-reference" || n.type === "multiReference") use("contentModelId", "polymorphic", "allowedModelSlugs", "targets", "filter");
|
|
1941
2648
|
if (n.type === "reference") {
|
|
1942
|
-
const
|
|
1943
|
-
if (
|
|
2649
|
+
const ref = referenceFromConfig(cfg);
|
|
2650
|
+
if (ref) f.reference = ref;
|
|
1944
2651
|
}
|
|
1945
2652
|
if (n.type === "form") f.reference = { to: ["form"] };
|
|
1946
2653
|
if (n.type === "object" || n.type === "group") {
|
|
@@ -1951,22 +2658,87 @@ function readToV2(n, at, siblings, ctx, top, lane) {
|
|
|
1951
2658
|
}
|
|
1952
2659
|
if (n.type === "array" && n.zones?.nonRepeatable) {
|
|
1953
2660
|
const nr = n.zones.nonRepeatable;
|
|
1954
|
-
const
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
2661
|
+
const fields = nr.map((c, i) => readToV2(c, `${at}/config/zones/nonRepeatable/${i}`, nr, ctx, false, lane));
|
|
2662
|
+
if (n.zones.repeatable) {
|
|
2663
|
+
const kids = [{
|
|
2664
|
+
name: "nonRepeatable",
|
|
2665
|
+
title: n.label,
|
|
2666
|
+
type: "object",
|
|
2667
|
+
fields
|
|
2668
|
+
}, listOf(n, n.zones.repeatable.fields, "repeatable", `${at}/config/zones/repeatable`, ctx, lane)];
|
|
2669
|
+
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.");
|
|
2670
|
+
Object.assign(f, {
|
|
2671
|
+
type: "object",
|
|
2672
|
+
fields: kids
|
|
2673
|
+
});
|
|
2674
|
+
} else {
|
|
2675
|
+
Object.assign(f, {
|
|
2676
|
+
type: "object",
|
|
2677
|
+
fields
|
|
2678
|
+
});
|
|
2679
|
+
ctx.zoned.add(f);
|
|
2680
|
+
}
|
|
2681
|
+
} else if (slotProp) {
|
|
2682
|
+
const ids = Array.isArray(cfg.componentIds) ? cfg.componentIds.filter((x) => typeof x === "string") : [];
|
|
2683
|
+
const names = Array.isArray(cfg.allow) ? cfg.allow.filter((x) => typeof x === "string") : [];
|
|
2684
|
+
f.of = ids.length ? {
|
|
2685
|
+
type: "block",
|
|
2686
|
+
allow: ids
|
|
2687
|
+
} : names.length ? {
|
|
2688
|
+
type: "block",
|
|
2689
|
+
allow: names
|
|
2690
|
+
} : { type: "block" };
|
|
2691
|
+
ctx.slots.set(f, cfg.multiple === true);
|
|
2692
|
+
const settings = Array.isArray(cfg.slotSettings) ? cfg.slotSettings.map(readProp) : [];
|
|
2693
|
+
if (settings.length) f.slotSettings = settings.map((c, k) => readToV2(c, `${at}/config/slotSettings/${k}`, settings, ctx, false, lane));
|
|
2694
|
+
if (cfg.multiple !== true) {
|
|
2695
|
+
val.max = 1;
|
|
2696
|
+
loss("config/multiple", "slot single", "A single slot holds one component instance; V2 reads it as a slot of at most one block.");
|
|
2697
|
+
} else {
|
|
2698
|
+
if (typeof cfg.minItems === "number") val.min = cfg.minItems;
|
|
2699
|
+
if (typeof cfg.maxItems === "number") val.max = cfg.maxItems;
|
|
2700
|
+
}
|
|
2701
|
+
use("multiple", "componentIds", "allow", "minItems", "maxItems", "slotSettings");
|
|
2702
|
+
} else if (blockSlot) {
|
|
2703
|
+
const slugs = Array.isArray(cfg.blockSlugs) ? cfg.blockSlugs.filter((x) => typeof x === "string") : [];
|
|
2704
|
+
f.of = slugs.length ? {
|
|
2705
|
+
type: "block",
|
|
2706
|
+
allow: slugs.map(camel)
|
|
2707
|
+
} : { type: "block" };
|
|
2708
|
+
ctx.blocks.add(f);
|
|
2709
|
+
const settings = Array.isArray(cfg.slotSettings) ? cfg.slotSettings.map(readField) : [];
|
|
2710
|
+
if (settings.length) f.slotSettings = settings.map((c, k) => readToV2(c, `${at}/config/slotSettings/${k}`, settings, ctx, false, lane));
|
|
2711
|
+
if (typeof cfg.minItems === "number") val.min = cfg.minItems;
|
|
2712
|
+
if (typeof cfg.maxItems === "number") val.max = cfg.maxItems;
|
|
2713
|
+
use("blockSlugs", "minItems", "maxItems", "slotSettings");
|
|
2714
|
+
} else if (lane === "props" && n.type === "table" && cfg.mode === "types") {
|
|
2715
|
+
f.of = (Array.isArray(cfg.itemTypes) ? cfg.itemTypes : []).map((t, j) => {
|
|
2716
|
+
const kids = (t.fields ?? []).map(readProp);
|
|
2717
|
+
const item = {
|
|
2718
|
+
name: t.name,
|
|
2719
|
+
title: t.label ?? t.name,
|
|
2720
|
+
type: "object",
|
|
2721
|
+
fields: kids.map((c, k) => readToV2(c, `${at}/config/itemTypes/${j}/fields/${k}`, kids, ctx, false, lane))
|
|
2722
|
+
};
|
|
2723
|
+
if (t.icon) item.icon = tablerIconOf(t.icon);
|
|
2724
|
+
if (t.preview) item.preview = previewFromProd(t.preview, kids);
|
|
2725
|
+
return item;
|
|
1965
2726
|
});
|
|
2727
|
+
ctx.types.add(f);
|
|
2728
|
+
if (n.ui.itemLabel !== void 0) f.itemNoun = n.ui.itemLabel.toLowerCase();
|
|
2729
|
+
if (n.ui.icon) f.icon = tablerIconOf(n.ui.icon);
|
|
2730
|
+
const l = n.ui.layout;
|
|
2731
|
+
if (l === "grid" || l === "list") f.arrayLayout = l;
|
|
2732
|
+
else if (l === "rows") f.layout = "list";
|
|
2733
|
+
else if (l) loss("ui/layout", "ui.layout", `V2 has no "${l}" layout for a list of item types.`);
|
|
2734
|
+
if (typeof cfg.minItems === "number") val.min = cfg.minItems;
|
|
2735
|
+
if (typeof cfg.maxItems === "number") val.max = cfg.maxItems;
|
|
2736
|
+
use("mode", "itemTypes", "minItems", "maxItems");
|
|
2737
|
+
useUi("itemLabel", "icon", "layout");
|
|
1966
2738
|
} else if (dataTable) {
|
|
1967
2739
|
f.table = tableOptionsFromConfig(cfg);
|
|
1968
2740
|
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") {
|
|
2741
|
+
} else if (n.type === "array" && (n.zones?.repeatable || !n.zones && !cfg.itemType && n.fields?.length) || n.type === "repeater" || n.type === "table") {
|
|
1970
2742
|
const list = listOf(n, n.zones?.repeatable?.fields ?? n.fields ?? [], n.key, at, ctx, lane);
|
|
1971
2743
|
useUi("preview", "icon", "itemLabel", "layout", "itemName", "itemTitle");
|
|
1972
2744
|
if (n.zones?.repeatable) ctx.zoned.add(f);
|
|
@@ -1982,14 +2754,19 @@ function readToV2(n, at, siblings, ctx, top, lane) {
|
|
|
1982
2754
|
if (typeof r?.maxItems === "number") val.max = r.maxItems;
|
|
1983
2755
|
if (n.type === "table") use("minItems", "maxItems");
|
|
1984
2756
|
} else if (n.type === "array" && cfg.itemType) {
|
|
1985
|
-
f.of = [{
|
|
2757
|
+
f.of = [shopify ? {
|
|
1986
2758
|
...itemOf(n),
|
|
1987
|
-
type:
|
|
2759
|
+
type: "reference",
|
|
2760
|
+
reference: { to: ["shopify"] }
|
|
2761
|
+
} : {
|
|
2762
|
+
...itemOf(n),
|
|
2763
|
+
type: cfg.itemType === "text" ? "string" : cfg.itemType,
|
|
2764
|
+
...itemSettingsFromProd(cfg.item)
|
|
1988
2765
|
}];
|
|
1989
2766
|
leafListChrome(n, f, loss, "a list of scalars");
|
|
1990
2767
|
if (typeof cfg.minItems === "number") val.min = cfg.minItems;
|
|
1991
2768
|
if (typeof cfg.maxItems === "number") val.max = cfg.maxItems;
|
|
1992
|
-
use("itemType", "minItems", "maxItems");
|
|
2769
|
+
use("itemType", "minItems", "maxItems", "item");
|
|
1993
2770
|
useUi("layout", "itemLabel", "itemName", "itemTitle");
|
|
1994
2771
|
} else if (n.type === "modular") {
|
|
1995
2772
|
const slugs = cfg.blockSlugs ?? [];
|
|
@@ -2026,11 +2803,11 @@ function readToV2(n, at, siblings, ctx, top, lane) {
|
|
|
2026
2803
|
use("blockSlugs", "minItems", "maxItems");
|
|
2027
2804
|
useUi("itemLabel", "icon", "layout", "blocks");
|
|
2028
2805
|
} else if (n.type === "multi-reference" || n.type === "multiReference") {
|
|
2029
|
-
const
|
|
2806
|
+
const ref = referenceFromConfig(cfg);
|
|
2030
2807
|
f.of = [{
|
|
2031
2808
|
...itemOf(n),
|
|
2032
2809
|
type: "reference",
|
|
2033
|
-
...
|
|
2810
|
+
...ref ? { reference: ref } : {}
|
|
2034
2811
|
}];
|
|
2035
2812
|
leafListChrome(n, f, loss, "a list of entries");
|
|
2036
2813
|
if (typeof cfg.min === "number") val.min = cfg.min;
|
|
@@ -2039,16 +2816,47 @@ function readToV2(n, at, siblings, ctx, top, lane) {
|
|
|
2039
2816
|
useUi("layout", "itemLabel", "itemName", "itemTitle");
|
|
2040
2817
|
}
|
|
2041
2818
|
if (n.type === "array" && n.zones?.nonRepeatable && n.zones.repeatable) useUi("preview", "icon", "itemLabel", "layout");
|
|
2042
|
-
for (const [k, x] of Object.entries(cfg))
|
|
2819
|
+
for (const [k, x] of Object.entries(cfg)) {
|
|
2820
|
+
if (x === void 0 || used.has(k)) continue;
|
|
2821
|
+
if (isHostConfigKey(n.type, k) || isHostConfigKey(type, k)) loss(`config/${k}`, "host config", CATALOG["host config"]);
|
|
2822
|
+
else loss(`config/${k}`, "config", `V2 has no "${k}" setting on a ${type} field.`);
|
|
2823
|
+
}
|
|
2043
2824
|
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
2825
|
if (n.defaultValue !== void 0 || top && ctx.plans) {
|
|
2045
|
-
const plan = readPlan(f, n.type, ctx.zoned, ctx.modular);
|
|
2826
|
+
const plan = readPlan(f, n.type, ctx.zoned, ctx.modular, ctx.types, ctx.slots, ctx.blocks);
|
|
2046
2827
|
if (top) ctx.plans?.set(f.name, plan);
|
|
2047
2828
|
if (n.defaultValue !== void 0) f.initialValue = planFromProd(plan, n.defaultValue, (rel, reason) => loss(`defaultValue${rel}`, "stored value", reason));
|
|
2048
2829
|
}
|
|
2049
2830
|
if (Object.keys(val).length) f.validation = val;
|
|
2050
2831
|
return f;
|
|
2051
2832
|
}
|
|
2833
|
+
/** config.item → the V2 item field's description, localized flag and validation (in V2's key order). */
|
|
2834
|
+
function itemSettingsFromProd(item) {
|
|
2835
|
+
if (!isObj(item)) return {};
|
|
2836
|
+
const s = item;
|
|
2837
|
+
const out = {};
|
|
2838
|
+
const val = {};
|
|
2839
|
+
if (s.required !== void 0) val.required = s.required;
|
|
2840
|
+
if (s.minLength !== void 0) val.min = s.minLength;
|
|
2841
|
+
if (s.maxLength !== void 0) val.max = s.maxLength;
|
|
2842
|
+
if (s.pattern !== void 0) val.pattern = s.pattern;
|
|
2843
|
+
if (s.patternMessage !== void 0) val.patternMessage = s.patternMessage;
|
|
2844
|
+
if (Object.keys(val).length) out.validation = val;
|
|
2845
|
+
if (s.localized !== void 0) out.localized = s.localized;
|
|
2846
|
+
if (s.helpText !== void 0) out.description = s.helpText;
|
|
2847
|
+
return out;
|
|
2848
|
+
}
|
|
2849
|
+
/** A reference config → the V2 `reference`: entry models first, then config.targets; config.filter as written. */
|
|
2850
|
+
function referenceFromConfig(cfg) {
|
|
2851
|
+
const entries = cfg.polymorphic ? cfg.allowedModelSlugs ?? [] : cfg.contentModelId ? [cfg.contentModelId] : [];
|
|
2852
|
+
const targets = Array.isArray(cfg.targets) ? cfg.targets.filter((t) => typeof t === "string") : [];
|
|
2853
|
+
const to = [...entries, ...targets];
|
|
2854
|
+
if (!to.length && typeof cfg.filter !== "string") return void 0;
|
|
2855
|
+
return {
|
|
2856
|
+
to,
|
|
2857
|
+
...typeof cfg.filter === "string" ? { filter: cfg.filter } : {}
|
|
2858
|
+
};
|
|
2859
|
+
}
|
|
2052
2860
|
/** A list of scalars or entries: its item's name and title (ui.itemName / ui.itemTitle, else the convention). */
|
|
2053
2861
|
var itemOf = (n) => {
|
|
2054
2862
|
const conv = conventionItem(n.key, n.label);
|
|
@@ -2100,6 +2908,9 @@ function toTypeSchema(model, opts = {}) {
|
|
|
2100
2908
|
sets: /* @__PURE__ */ new Map(),
|
|
2101
2909
|
zoned: /* @__PURE__ */ new WeakSet(),
|
|
2102
2910
|
modular: /* @__PURE__ */ new WeakSet(),
|
|
2911
|
+
types: /* @__PURE__ */ new WeakSet(),
|
|
2912
|
+
slots: /* @__PURE__ */ new WeakMap(),
|
|
2913
|
+
blocks: /* @__PURE__ */ new WeakSet(),
|
|
2103
2914
|
blockModels: new Map((opts.blockModels ?? []).map((m) => [m.slug, m])),
|
|
2104
2915
|
plans: opts.plans
|
|
2105
2916
|
};
|
|
@@ -2156,6 +2967,9 @@ function propsToTypeSchema(component, opts = {}) {
|
|
|
2156
2967
|
sets: /* @__PURE__ */ new Map(),
|
|
2157
2968
|
zoned: /* @__PURE__ */ new WeakSet(),
|
|
2158
2969
|
modular: /* @__PURE__ */ new WeakSet(),
|
|
2970
|
+
types: /* @__PURE__ */ new WeakSet(),
|
|
2971
|
+
slots: /* @__PURE__ */ new WeakMap(),
|
|
2972
|
+
blocks: /* @__PURE__ */ new WeakSet(),
|
|
2159
2973
|
blockModels: new Map((opts.blockModels ?? []).map((m) => [m.slug, m])),
|
|
2160
2974
|
plans: opts.plans
|
|
2161
2975
|
};
|
|
@@ -2186,6 +3000,23 @@ function propsToTypeSchema(component, opts = {}) {
|
|
|
2186
3000
|
const at = new Map(fieldsets.map((s, i) => [s.name, i]));
|
|
2187
3001
|
fieldsets.sort((a, b) => (order.get(a.name) ?? at.get(a.name)) - (order.get(b.name) ?? at.get(b.name)));
|
|
2188
3002
|
}
|
|
3003
|
+
const groups = [];
|
|
3004
|
+
const tabOrder = /* @__PURE__ */ new Map();
|
|
3005
|
+
for (const t of [...nodes.map((n) => n.ui.tab), ...component.tabs ?? []]) {
|
|
3006
|
+
if (!t || groups.some((g) => g.name === t.id)) continue;
|
|
3007
|
+
const g = {
|
|
3008
|
+
name: t.id,
|
|
3009
|
+
title: t.label ?? t.id
|
|
3010
|
+
};
|
|
3011
|
+
if (t.icon) g.icon = tablerIconOf(t.icon);
|
|
3012
|
+
if (typeof t.order === "number") tabOrder.set(t.id, t.order);
|
|
3013
|
+
groups.push(g);
|
|
3014
|
+
}
|
|
3015
|
+
if (tabOrder.size) {
|
|
3016
|
+
const at = new Map(groups.map((g, i) => [g.name, i]));
|
|
3017
|
+
groups.sort((a, b) => (tabOrder.get(a.name) ?? at.get(a.name)) - (tabOrder.get(b.name) ?? at.get(b.name)));
|
|
3018
|
+
}
|
|
3019
|
+
if (groups.length) groups[0].default = true;
|
|
2189
3020
|
const out = {
|
|
2190
3021
|
name: camel(component.slug),
|
|
2191
3022
|
title: component.name,
|
|
@@ -2194,10 +3025,13 @@ function propsToTypeSchema(component, opts = {}) {
|
|
|
2194
3025
|
};
|
|
2195
3026
|
if (component.description !== void 0 && component.description !== null) out.description = component.description;
|
|
2196
3027
|
if (component.category !== void 0 && component.category !== "custom") out.category = capitalize(component.category);
|
|
3028
|
+
if (component.icon) out.icon = tablerIconOf(component.icon);
|
|
3029
|
+
if (component.preview) out.preview = previewFromProd(component.preview, nodes);
|
|
2197
3030
|
if (fieldsets.length) out.fieldsets = fieldsets;
|
|
3031
|
+
if (groups.length) out.groups = groups;
|
|
2198
3032
|
return out;
|
|
2199
3033
|
}
|
|
2200
3034
|
//#endregion
|
|
2201
|
-
export { CATEGORY_TO_PROD, fromTypeSchema, leafValuePlan, planFromProd, planToProd, propsToTypeSchema, toTypeSchema };
|
|
3035
|
+
export { CATEGORY_TO_PROD, SHOPIFY_REF_LOCK, fromTypeSchema, leafValuePlan, planFromProd, planToProd, propsToTypeSchema, schemaSlugOf, toTypeSchema };
|
|
2202
3036
|
|
|
2203
3037
|
//# sourceMappingURL=schema.js.map
|