@bettercms-ai/kit 1.0.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +33 -0
- package/dist/adapters/dock-values.d.ts +28 -0
- package/dist/adapters/dock-values.js +41 -0
- package/dist/adapters/dock-values.js.map +1 -0
- package/{adapters → dist/adapters}/icons.js +2 -2
- package/dist/adapters/icons.js.map +1 -0
- package/{adapters → dist/adapters}/lossy.d.ts +90 -31
- package/dist/adapters/lossy.js +414 -0
- package/dist/adapters/lossy.js.map +1 -0
- package/{adapters → dist/adapters}/prod-types.d.ts +82 -4
- package/{adapters → dist/adapters}/prod-types.js +71 -3
- package/dist/adapters/prod-types.js.map +1 -0
- package/{adapters → dist/adapters}/schema.d.ts +40 -1
- package/{adapters → dist/adapters}/schema.js +996 -179
- package/dist/adapters/schema.js.map +1 -0
- package/{adapters → dist/adapters}/values.d.ts +26 -5
- package/{adapters → dist/adapters}/values.js +87 -17
- package/dist/adapters/values.js.map +1 -0
- package/dist/brand/logo.js +96 -0
- package/dist/brand/logo.js.map +1 -0
- package/{context.d.ts → dist/context.d.ts} +92 -2
- package/{context.js → dist/context.js} +5 -2
- package/dist/context.js.map +1 -0
- package/{controls → dist/controls}/button.d.ts +19 -5
- package/{controls → dist/controls}/button.js +125 -54
- package/dist/controls/button.js.map +1 -0
- package/{controls → dist/controls}/c1.js +1 -1
- package/dist/controls/c1.js.map +1 -0
- package/{controls → dist/controls}/c2.js +1 -1
- package/dist/controls/c2.js.map +1 -0
- package/{controls → dist/controls}/choice.d.ts +7 -2
- package/{controls → dist/controls}/choice.js +71 -18
- package/dist/controls/choice.js.map +1 -0
- package/{controls → dist/controls}/code-register.js +1 -1
- package/dist/controls/code-register.js.map +1 -0
- package/{controls → dist/controls}/code.js +10 -9
- package/dist/controls/code.js.map +1 -0
- package/{controls → dist/controls}/color.js +8 -8
- package/dist/controls/color.js.map +1 -0
- package/{controls → dist/controls}/component-services.d.ts +42 -0
- package/dist/controls/component-services.js +7 -0
- package/dist/controls/component-services.js.map +1 -0
- package/{controls → dist/controls}/date-register.js +1 -1
- package/dist/controls/date-register.js.map +1 -0
- package/{controls → dist/controls}/date-zone.js +8 -2
- package/dist/controls/date-zone.js.map +1 -0
- package/{controls → dist/controls}/date.js +32 -24
- package/dist/controls/date.js.map +1 -0
- package/{controls → dist/controls}/form-picker-register.js +1 -1
- package/dist/controls/form-picker-register.js.map +1 -0
- package/{controls → dist/controls}/form-picker.js +11 -9
- package/dist/controls/form-picker.js.map +1 -0
- package/{controls → dist/controls}/icon-register.js +1 -1
- package/dist/controls/icon-register.js.map +1 -0
- package/{controls → dist/controls}/icon.d.ts +4 -2
- package/{controls → dist/controls}/icon.js +32 -27
- package/dist/controls/icon.js.map +1 -0
- package/{controls → dist/controls}/index.d.ts +1 -1
- package/{controls → dist/controls}/index.js +4 -3
- package/dist/controls/index.js.map +1 -0
- package/{controls → dist/controls}/json-register.js +1 -1
- package/dist/controls/json-register.js.map +1 -0
- package/{controls → dist/controls}/json.js +13 -3
- package/dist/controls/json.js.map +1 -0
- package/{controls → dist/controls}/link.js +6 -6
- package/dist/controls/link.js.map +1 -0
- package/{controls → dist/controls}/location-register.js +1 -1
- package/dist/controls/location-register.js.map +1 -0
- package/{controls → dist/controls}/location.js +64 -40
- package/dist/controls/location.js.map +1 -0
- package/{controls → dist/controls}/media-register.js +1 -1
- package/dist/controls/media-register.js.map +1 -0
- package/{controls → dist/controls}/media-services.d.ts +6 -0
- package/dist/controls/media-services.js +0 -0
- package/{controls → dist/controls}/media.d.ts +35 -4
- package/{controls → dist/controls}/media.js +491 -171
- package/dist/controls/media.js.map +1 -0
- package/{controls → dist/controls}/number.js +10 -9
- package/dist/controls/number.js.map +1 -0
- package/{controls → dist/controls}/reference-register.js +1 -1
- package/dist/controls/reference-register.js.map +1 -0
- package/{controls → dist/controls}/reference-services.d.ts +4 -0
- package/dist/controls/reference-services.js +0 -0
- package/{controls → dist/controls}/reference.d.ts +1 -1
- package/{controls → dist/controls}/reference.js +93 -77
- package/dist/controls/reference.js.map +1 -0
- package/dist/controls/rich-text/blocks.d.ts +49 -0
- package/{controls → dist/controls}/rich-text/blocks.js +471 -144
- package/dist/controls/rich-text/blocks.js.map +1 -0
- package/{controls → dist/controls}/rich-text/catalog.d.ts +4 -1
- package/{controls → dist/controls}/rich-text/catalog.js +75 -65
- package/dist/controls/rich-text/catalog.js.map +1 -0
- package/{controls → dist/controls}/rich-text/codec.d.ts +9 -1
- package/{controls → dist/controls}/rich-text/codec.js +3 -1
- package/dist/controls/rich-text/codec.js.map +1 -0
- package/{controls → dist/controls}/rich-text/component-card.d.ts +1 -1
- package/{controls → dist/controls}/rich-text/component-card.js +417 -99
- package/dist/controls/rich-text/component-card.js.map +1 -0
- package/dist/controls/rich-text/component-panel.d.ts +47 -0
- package/dist/controls/rich-text/component-panel.js +141 -0
- package/dist/controls/rich-text/component-panel.js.map +1 -0
- package/{controls → dist/controls}/rich-text/control.d.ts +1 -2
- package/{controls → dist/controls}/rich-text/control.js +84 -42
- package/dist/controls/rich-text/control.js.map +1 -0
- package/{controls → dist/controls}/rich-text/dom.d.ts +52 -9
- package/{controls → dist/controls}/rich-text/dom.js +379 -50
- package/dist/controls/rich-text/dom.js.map +1 -0
- package/{controls → dist/controls}/rich-text/editor.d.ts +7 -0
- package/{controls → dist/controls}/rich-text/editor.js +148 -48
- package/dist/controls/rich-text/editor.js.map +1 -0
- package/{controls → dist/controls}/rich-text/floating.d.ts +6 -1
- package/{controls → dist/controls}/rich-text/floating.js +35 -18
- package/dist/controls/rich-text/floating.js.map +1 -0
- package/{controls → dist/controls}/rich-text/index.js +1 -1
- package/dist/controls/rich-text/index.js.map +1 -0
- package/dist/controls/rich-text/link-form.js +147 -0
- package/dist/controls/rich-text/link-form.js.map +1 -0
- package/{controls → dist/controls}/rich-text/markdown.js +4 -2
- package/dist/controls/rich-text/markdown.js.map +1 -0
- package/{controls → dist/controls}/rich-text/ops.js +17 -15
- package/dist/controls/rich-text/ops.js.map +1 -0
- package/dist/controls/rich-text/plain.d.ts +17 -0
- package/dist/controls/rich-text/plain.js +44 -0
- package/dist/controls/rich-text/plain.js.map +1 -0
- package/{controls → dist/controls}/rich-text/toolbar.d.ts +6 -2
- package/{controls → dist/controls}/rich-text/toolbar.js +12 -7
- package/dist/controls/rich-text/toolbar.js.map +1 -0
- package/{controls → dist/controls}/scale.js +5 -5
- package/dist/controls/scale.js.map +1 -0
- package/{controls → dist/controls}/slot-register.js +1 -1
- package/dist/controls/slot-register.js.map +1 -0
- package/{controls → dist/controls}/slot-services.d.ts +25 -0
- package/dist/controls/slot-services.js +155 -0
- package/dist/controls/slot-services.js.map +1 -0
- package/{controls → dist/controls}/slot.js +42 -24
- package/dist/controls/slot.js.map +1 -0
- package/{controls → dist/controls}/table/index.js +1 -1
- package/dist/controls/table/index.js.map +1 -0
- package/{controls → dist/controls}/table/prod.js +3 -3
- package/dist/controls/table/prod.js.map +1 -0
- package/{controls → dist/controls}/table/refs.js +13 -2
- package/dist/controls/table/refs.js.map +1 -0
- package/{controls → dist/controls}/table/stored.js +1 -1
- package/dist/controls/table/stored.js.map +1 -0
- package/{controls → dist/controls}/table/table-editor.js +51 -48
- package/dist/controls/table/table-editor.js.map +1 -0
- package/{controls → dist/controls}/table/table-link.js +3 -3
- package/dist/controls/table/table-link.js.map +1 -0
- package/{controls → dist/controls}/table/table.js +3 -3
- package/dist/controls/table/table.js.map +1 -0
- package/{controls → dist/controls}/text.d.ts +2 -2
- package/{controls → dist/controls}/text.js +78 -43
- package/dist/controls/text.js.map +1 -0
- package/dist/controls/unknown-value.d.ts +17 -0
- package/dist/controls/unknown-value.js +66 -0
- package/dist/controls/unknown-value.js.map +1 -0
- package/dist/core/core.d.ts +63 -0
- package/dist/core/core.js +171 -0
- package/dist/core/core.js.map +1 -0
- package/dist/core/facets.d.ts +347 -0
- package/dist/core/facets.js +334 -0
- package/dist/core/facets.js.map +1 -0
- package/dist/core/index.d.ts +3 -0
- package/dist/core/index.js +3 -0
- package/{engine → dist/engine}/array.js +34 -21
- package/dist/engine/array.js.map +1 -0
- package/{engine → dist/engine}/bits.js +1 -1
- package/dist/engine/bits.js.map +1 -0
- package/{engine → dist/engine}/breadcrumb.d.ts +3 -3
- package/{engine → dist/engine}/breadcrumb.js +12 -36
- package/dist/engine/breadcrumb.js.map +1 -0
- package/{engine → dist/engine}/expand.d.ts +2 -4
- package/{engine → dist/engine}/expand.js +5 -22
- package/dist/engine/expand.js.map +1 -0
- package/{engine → dist/engine}/field-list.js +1 -1
- package/dist/engine/field-list.js.map +1 -0
- package/{engine → dist/engine}/field-shell.js +249 -121
- package/dist/engine/field-shell.js.map +1 -0
- package/{engine → dist/engine}/frame.d.ts +3 -1
- package/{engine → dist/engine}/frame.js +16 -14
- package/dist/engine/frame.js.map +1 -0
- package/{engine → dist/engine}/group-summary.d.ts +2 -1
- package/{engine → dist/engine}/group-summary.js +7 -3
- package/dist/engine/group-summary.js.map +1 -0
- package/{engine → dist/engine}/grouping.d.ts +19 -5
- package/{engine → dist/engine}/grouping.js +193 -21
- package/dist/engine/grouping.js.map +1 -0
- package/{engine → dist/engine}/item-list.d.ts +11 -1
- package/{engine → dist/engine}/item-list.js +35 -13
- package/dist/engine/item-list.js.map +1 -0
- package/{engine → dist/engine}/kit-field.js +45 -10
- package/dist/engine/kit-field.js.map +1 -0
- package/{engine → dist/engine}/schema-form.d.ts +27 -2
- package/{engine → dist/engine}/schema-form.js +182 -40
- package/dist/engine/schema-form.js.map +1 -0
- package/{engine → dist/engine}/slot.js +5 -15
- package/dist/engine/slot.js.map +1 -0
- package/dist/index.js +47 -0
- package/dist/index.js.map +1 -0
- package/{kit.css → dist/kit.css} +19 -0
- package/{lib → dist/lib}/cn.js +7 -4
- package/dist/lib/cn.js.map +1 -0
- package/{lib → dist/lib}/columns.js +4 -1
- package/dist/lib/columns.js.map +1 -0
- package/{lib → dist/lib}/frames.js +2 -2
- package/dist/lib/frames.js.map +1 -0
- package/dist/lib/icon-image.d.ts +10 -0
- package/dist/lib/icon-image.js +8 -0
- package/dist/lib/icon-image.js.map +1 -0
- package/{lib → dist/lib}/icons.js +4 -3
- package/dist/lib/icons.js.map +1 -0
- package/dist/lib/input-modality.d.ts +11 -0
- package/dist/lib/input-modality.js +47 -0
- package/dist/lib/input-modality.js.map +1 -0
- package/dist/lib/key-event.d.ts +11 -0
- package/dist/lib/key-event.js +16 -0
- package/dist/lib/key-event.js.map +1 -0
- package/{lib → dist/lib}/path.js +4 -2
- package/dist/lib/path.js.map +1 -0
- package/{lib → dist/lib}/schema.d.ts +34 -3
- package/{lib → dist/lib}/schema.js +110 -13
- package/dist/lib/schema.js.map +1 -0
- package/{lib → dist/lib}/utils.js +1 -1
- package/dist/lib/utils.js.map +1 -0
- package/{lib → dist/lib}/validate.d.ts +11 -1
- package/{lib → dist/lib}/validate.js +85 -11
- package/dist/lib/validate.js.map +1 -0
- package/dist/library/analysis.d.ts +23 -0
- package/dist/library/analysis.js +160 -0
- package/dist/library/analysis.js.map +1 -0
- package/dist/library/catalog.d.ts +57 -0
- package/dist/library/catalog.js +307 -0
- package/dist/library/catalog.js.map +1 -0
- package/dist/library/coreNotes.d.ts +8 -0
- package/dist/library/coreNotes.js +111 -0
- package/dist/library/coreNotes.js.map +1 -0
- package/dist/library/coverage.d.ts +40 -0
- package/dist/library/coverage.js +59 -0
- package/dist/library/coverage.js.map +1 -0
- package/dist/library/entries/advanced.entries.d.ts +2 -0
- package/dist/library/entries/advanced.entries.js +6579 -0
- package/dist/library/entries/advanced.entries.js.map +1 -0
- package/dist/library/entries/commerce.entries.d.ts +2 -0
- package/dist/library/entries/commerce.entries.js +4140 -0
- package/dist/library/entries/commerce.entries.js.map +1 -0
- package/dist/library/entries/company.entries.d.ts +2 -0
- package/dist/library/entries/company.entries.js +2731 -0
- package/dist/library/entries/company.entries.js.map +1 -0
- package/dist/library/entries/conversion.entries.d.ts +2 -0
- package/dist/library/entries/conversion.entries.js +3707 -0
- package/dist/library/entries/conversion.entries.js.map +1 -0
- package/dist/library/entries/data.entries.d.ts +7 -0
- package/dist/library/entries/data.entries.js +4613 -0
- package/dist/library/entries/data.entries.js.map +1 -0
- package/dist/library/entries/events.entries.d.ts +2 -0
- package/dist/library/entries/events.entries.js +3428 -0
- package/dist/library/entries/events.entries.js.map +1 -0
- package/dist/library/entries/features.entries.d.ts +2 -0
- package/dist/library/entries/features.entries.js +3157 -0
- package/dist/library/entries/features.entries.js.map +1 -0
- package/dist/library/entries/heroes.entries.d.ts +2 -0
- package/dist/library/entries/heroes.entries.js +3401 -0
- package/dist/library/entries/heroes.entries.js.map +1 -0
- package/dist/library/entries/index.d.ts +3 -0
- package/dist/library/entries/index.js +35 -0
- package/dist/library/entries/index.js.map +1 -0
- package/dist/library/entries/listings.entries.d.ts +2 -0
- package/dist/library/entries/listings.entries.js +2976 -0
- package/dist/library/entries/listings.entries.js.map +1 -0
- package/dist/library/entries/longform.entries.d.ts +2 -0
- package/dist/library/entries/longform.entries.js +4227 -0
- package/dist/library/entries/longform.entries.js.map +1 -0
- package/dist/library/entries/media.entries.d.ts +2 -0
- package/dist/library/entries/media.entries.js +2781 -0
- package/dist/library/entries/media.entries.js.map +1 -0
- package/dist/library/entries/navigation.entries.d.ts +2 -0
- package/dist/library/entries/navigation.entries.js +4011 -0
- package/dist/library/entries/navigation.entries.js.map +1 -0
- package/dist/library/entries/pricing.entries.d.ts +2 -0
- package/dist/library/entries/pricing.entries.js +2383 -0
- package/dist/library/entries/pricing.entries.js.map +1 -0
- package/dist/library/entries/social-proof.entries.d.ts +2 -0
- package/dist/library/entries/social-proof.entries.js +2297 -0
- package/dist/library/entries/social-proof.entries.js.map +1 -0
- package/dist/library/examples/bento.d.ts +92 -0
- package/dist/library/examples/bento.js +201 -0
- package/dist/library/examples/bento.js.map +1 -0
- package/dist/library/examples/blocks.d.ts +14 -0
- package/dist/library/examples/blocks.js +313 -0
- package/dist/library/examples/blocks.js.map +1 -0
- package/dist/library/examples/faq.d.ts +28 -0
- package/dist/library/examples/faq.js +230 -0
- package/dist/library/examples/faq.js.map +1 -0
- package/dist/library/examples/hero.d.ts +43 -0
- package/dist/library/examples/hero.js +222 -0
- package/dist/library/examples/hero.js.map +1 -0
- package/dist/library/examples/index.d.ts +36 -0
- package/dist/library/examples/index.js +109 -0
- package/dist/library/examples/index.js.map +1 -0
- package/dist/library/examples/journalStory.d.ts +93 -0
- package/dist/library/examples/journalStory.js +338 -0
- package/dist/library/examples/journalStory.js.map +1 -0
- package/dist/library/examples/megaMenu.d.ts +134 -0
- package/dist/library/examples/megaMenu.js +442 -0
- package/dist/library/examples/megaMenu.js.map +1 -0
- package/dist/library/examples/pricing.d.ts +103 -0
- package/dist/library/examples/pricing.js +479 -0
- package/dist/library/examples/pricing.js.map +1 -0
- package/dist/library/examples/tabs.d.ts +87 -0
- package/dist/library/examples/tabs.js +180 -0
- package/dist/library/examples/tabs.js.map +1 -0
- package/dist/library/export.d.ts +42 -0
- package/dist/library/export.js +80 -0
- package/dist/library/export.js.map +1 -0
- package/dist/library/index.d.ts +13 -0
- package/dist/library/index.js +6 -0
- package/dist/library/kit-catalog.json +1510 -0
- package/dist/library/types.d.ts +42 -0
- package/dist/library/types.js +0 -0
- package/{schema → dist/schema}/adapters.js +1 -2
- package/dist/schema/adapters.js.map +1 -0
- package/{schema → dist/schema}/help.d.ts +2 -0
- package/{schema → dist/schema}/help.js +6 -4
- package/dist/schema/help.js.map +1 -0
- package/{schema → dist/schema}/scale.js +1 -1
- package/dist/schema/scale.js.map +1 -0
- package/{schema → dist/schema}/sources.js +1 -1
- package/dist/schema/sources.js.map +1 -0
- package/{schema → dist/schema}/table.js +11 -10
- package/dist/schema/table.js.map +1 -0
- package/{schema → dist/schema}/types.d.ts +29 -1
- package/{schema → dist/schema}/types.js +1 -1
- package/dist/schema/types.js.map +1 -0
- package/dist/styles.css +2 -0
- package/dist/table/table-view.d.ts +14 -0
- package/dist/table/table-view.js +140 -0
- package/dist/table/table-view.js.map +1 -0
- package/dist/table/table.css +73 -0
- package/dist/testing/corpus.d.ts +63 -0
- package/dist/testing/corpus.js +129 -0
- package/dist/testing/corpus.js.map +1 -0
- package/dist/testing/test-form.d.ts +11 -0
- package/dist/testing/test-form.js +38 -0
- package/dist/testing/test-form.js.map +1 -0
- package/dist/theme.css +345 -0
- package/dist/theme.d.ts +22 -0
- package/dist/theme.js +43 -0
- package/dist/theme.js.map +1 -0
- package/dist/tokens.css +542 -0
- package/dist/types.js +0 -0
- package/{ui → dist/ui}/action-tray.d.ts +1 -1
- package/{ui → dist/ui}/action-tray.js +20 -19
- package/dist/ui/action-tray.js.map +1 -0
- package/dist/ui/autocomplete.d.ts +30 -0
- package/dist/ui/autocomplete.js +139 -0
- package/dist/ui/autocomplete.js.map +1 -0
- package/{ui → dist/ui}/button.d.ts +3 -3
- package/{ui → dist/ui}/button.js +6 -7
- package/dist/ui/button.js.map +1 -0
- package/{ui → dist/ui}/choice-switch.js +1 -1
- package/dist/ui/choice-switch.js.map +1 -0
- package/{ui → dist/ui}/controls.js +51 -39
- package/dist/ui/controls.js.map +1 -0
- package/{ui → dist/ui}/display.d.ts +10 -3
- package/{ui → dist/ui}/display.js +57 -46
- package/dist/ui/display.js.map +1 -0
- package/{ui → dist/ui}/expanded-editor-modal.d.ts +2 -2
- package/{ui → dist/ui}/expanded-editor-modal.js +6 -6
- package/dist/ui/expanded-editor-modal.js.map +1 -0
- package/{ui → dist/ui}/field-context.js +1 -1
- package/dist/ui/field-context.js.map +1 -0
- package/{ui → dist/ui}/floating-panel.d.ts +1 -1
- package/{ui → dist/ui}/floating-panel.js +28 -12
- package/dist/ui/floating-panel.js.map +1 -0
- package/{ui → dist/ui}/index.d.ts +4 -0
- package/dist/ui/index.js +18 -0
- package/{ui → dist/ui}/input.d.ts +1 -1
- package/{ui → dist/ui}/input.js +9 -9
- package/dist/ui/input.js.map +1 -0
- package/{ui → dist/ui}/mode-bar.js +3 -3
- package/dist/ui/mode-bar.js.map +1 -0
- package/{ui → dist/ui}/overlay.d.ts +77 -5
- package/dist/ui/overlay.js +697 -0
- package/dist/ui/overlay.js.map +1 -0
- package/{ui → dist/ui}/path-crumbs.js +37 -3
- package/dist/ui/path-crumbs.js.map +1 -0
- package/{ui → dist/ui}/presence.js +2 -2
- package/dist/ui/presence.js.map +1 -0
- package/{ui → dist/ui}/select.js +89 -87
- package/dist/ui/select.js.map +1 -0
- package/{ui → dist/ui}/shortcut-hint.js +1 -1
- package/dist/ui/shortcut-hint.js.map +1 -0
- package/dist/ui/spinner.d.ts +24 -0
- package/dist/ui/spinner.js +42 -0
- package/dist/ui/spinner.js.map +1 -0
- package/dist/ui/split-button.d.ts +32 -0
- package/dist/ui/split-button.js +60 -0
- package/dist/ui/split-button.js.map +1 -0
- package/{ui → dist/ui}/surfaces.js +1 -1
- package/dist/ui/surfaces.js.map +1 -0
- package/dist/ui/tab.d.ts +38 -0
- package/dist/ui/tab.js +87 -0
- package/dist/ui/tab.js.map +1 -0
- package/dist/ui/toast.d.ts +20 -0
- package/dist/ui/toast.js +115 -0
- package/dist/ui/toast.js.map +1 -0
- package/{ui → dist/ui}/tooltip-root.d.ts +4 -3
- package/{ui → dist/ui}/tooltip-root.js +9 -8
- package/dist/ui/tooltip-root.js.map +1 -0
- package/{ui → dist/ui}/variants.js +1 -1
- package/dist/ui/variants.js.map +1 -0
- package/package.json +77 -23
- package/adapters/icons.js.map +0 -1
- package/adapters/lossy.js +0 -233
- package/adapters/lossy.js.map +0 -1
- package/adapters/prod-types.js.map +0 -1
- package/adapters/schema.js.map +0 -1
- package/adapters/values.js.map +0 -1
- package/brand/logo.js +0 -9
- package/brand/logo.js.map +0 -1
- package/context.js.map +0 -1
- package/controls/button.js.map +0 -1
- package/controls/c1.js.map +0 -1
- package/controls/c2.js.map +0 -1
- package/controls/choice.js.map +0 -1
- package/controls/code-register.js.map +0 -1
- package/controls/code.js.map +0 -1
- package/controls/color.js.map +0 -1
- package/controls/date-register.js.map +0 -1
- package/controls/date-zone.js.map +0 -1
- package/controls/date.js.map +0 -1
- package/controls/form-picker-register.js.map +0 -1
- package/controls/form-picker.js.map +0 -1
- package/controls/icon-register.js.map +0 -1
- package/controls/icon.js.map +0 -1
- package/controls/index.js.map +0 -1
- package/controls/json-register.js.map +0 -1
- package/controls/json.js.map +0 -1
- package/controls/link.js.map +0 -1
- package/controls/location-register.js.map +0 -1
- package/controls/location.js.map +0 -1
- package/controls/media-register.js.map +0 -1
- package/controls/media.js.map +0 -1
- package/controls/number.js.map +0 -1
- package/controls/reference-register.js.map +0 -1
- package/controls/reference.js.map +0 -1
- package/controls/rich-text/blocks.d.ts +0 -28
- package/controls/rich-text/blocks.js.map +0 -1
- package/controls/rich-text/catalog.js.map +0 -1
- package/controls/rich-text/codec.js.map +0 -1
- package/controls/rich-text/component-card.js.map +0 -1
- package/controls/rich-text/control.js.map +0 -1
- package/controls/rich-text/dom.js.map +0 -1
- package/controls/rich-text/editor.js.map +0 -1
- package/controls/rich-text/floating.js.map +0 -1
- package/controls/rich-text/index.js.map +0 -1
- package/controls/rich-text/link-form.js +0 -111
- package/controls/rich-text/link-form.js.map +0 -1
- package/controls/rich-text/markdown.js.map +0 -1
- package/controls/rich-text/ops.js.map +0 -1
- package/controls/rich-text/toolbar.js.map +0 -1
- package/controls/scale.js.map +0 -1
- package/controls/slot-register.js.map +0 -1
- package/controls/slot-services.js +0 -38
- package/controls/slot-services.js.map +0 -1
- package/controls/slot.js.map +0 -1
- package/controls/table/index.js.map +0 -1
- package/controls/table/prod.js.map +0 -1
- package/controls/table/refs.js.map +0 -1
- package/controls/table/stored.js.map +0 -1
- package/controls/table/table-editor.js.map +0 -1
- package/controls/table/table-link.js.map +0 -1
- package/controls/table/table.js.map +0 -1
- package/controls/text.js.map +0 -1
- package/engine/array.js.map +0 -1
- package/engine/bits.js.map +0 -1
- package/engine/breadcrumb.js.map +0 -1
- package/engine/expand.js.map +0 -1
- package/engine/field-list.js.map +0 -1
- package/engine/field-shell.js.map +0 -1
- package/engine/frame.js.map +0 -1
- package/engine/group-summary.js.map +0 -1
- package/engine/grouping.js.map +0 -1
- package/engine/item-list.js.map +0 -1
- package/engine/kit-field.js.map +0 -1
- package/engine/schema-form.js.map +0 -1
- package/engine/slot.js.map +0 -1
- package/index.js +0 -55
- package/index.js.map +0 -1
- package/lib/cn.js.map +0 -1
- package/lib/columns.js.map +0 -1
- package/lib/frames.js.map +0 -1
- package/lib/icons.js.map +0 -1
- package/lib/path.js.map +0 -1
- package/lib/schema.js.map +0 -1
- package/lib/utils.js.map +0 -1
- package/lib/validate.js.map +0 -1
- package/schema/adapters.js.map +0 -1
- package/schema/help.js.map +0 -1
- package/schema/scale.js.map +0 -1
- package/schema/sources.js.map +0 -1
- package/schema/table.js.map +0 -1
- package/schema/types.js.map +0 -1
- package/ui/action-tray.js.map +0 -1
- package/ui/button.js.map +0 -1
- package/ui/choice-switch.js.map +0 -1
- package/ui/controls.js.map +0 -1
- package/ui/display.js.map +0 -1
- package/ui/expanded-editor-modal.js.map +0 -1
- package/ui/field-context.js.map +0 -1
- package/ui/floating-panel.js.map +0 -1
- package/ui/index.js +0 -13
- package/ui/input.js.map +0 -1
- package/ui/mode-bar.js.map +0 -1
- package/ui/overlay.js +0 -378
- package/ui/overlay.js.map +0 -1
- package/ui/path-crumbs.js.map +0 -1
- package/ui/presence.js.map +0 -1
- package/ui/select.js.map +0 -1
- package/ui/shortcut-hint.js.map +0 -1
- package/ui/surfaces.js.map +0 -1
- package/ui/tooltip-root.js.map +0 -1
- package/ui/variants.js.map +0 -1
- /package/{_virtual → dist/_virtual}/_rolldown/runtime.js +0 -0
- /package/{adapters → dist/adapters}/icons.d.ts +0 -0
- /package/{brand → dist/brand}/logo.d.ts +0 -0
- /package/{controls → dist/controls}/c1.d.ts +0 -0
- /package/{controls → dist/controls}/c2.d.ts +0 -0
- /package/{controls → dist/controls}/code-register.d.ts +0 -0
- /package/{controls → dist/controls}/code.d.ts +0 -0
- /package/{controls → dist/controls}/color.d.ts +0 -0
- /package/{controls → dist/controls}/date-register.d.ts +0 -0
- /package/{controls → dist/controls}/date-zone.d.ts +0 -0
- /package/{controls → dist/controls}/date.d.ts +0 -0
- /package/{controls → dist/controls}/form-picker-register.d.ts +0 -0
- /package/{controls → dist/controls}/form-picker.d.ts +0 -0
- /package/{controls → dist/controls}/icon-register.d.ts +0 -0
- /package/{controls → dist/controls}/json-register.d.ts +0 -0
- /package/{controls → dist/controls}/json.d.ts +0 -0
- /package/{controls → dist/controls}/link.d.ts +0 -0
- /package/{controls → dist/controls}/location-register.d.ts +0 -0
- /package/{controls → dist/controls}/location.d.ts +0 -0
- /package/{controls → dist/controls}/media-register.d.ts +0 -0
- /package/{controls → dist/controls}/number.d.ts +0 -0
- /package/{controls → dist/controls}/reference-register.d.ts +0 -0
- /package/{controls → dist/controls}/rich-text/index.d.ts +0 -0
- /package/{controls → dist/controls}/rich-text/link-form.d.ts +0 -0
- /package/{controls → dist/controls}/rich-text/markdown.d.ts +0 -0
- /package/{controls → dist/controls}/rich-text/ops.d.ts +0 -0
- /package/{controls → dist/controls}/scale.d.ts +0 -0
- /package/{controls → dist/controls}/slot-register.d.ts +0 -0
- /package/{controls → dist/controls}/slot.d.ts +0 -0
- /package/{controls → dist/controls}/table/index.d.ts +0 -0
- /package/{controls → dist/controls}/table/prod.d.ts +0 -0
- /package/{controls → dist/controls}/table/refs.d.ts +0 -0
- /package/{controls → dist/controls}/table/stored.d.ts +0 -0
- /package/{controls → dist/controls}/table/table-editor.d.ts +0 -0
- /package/{controls → dist/controls}/table/table-link.d.ts +0 -0
- /package/{controls → dist/controls}/table/table.d.ts +0 -0
- /package/{engine → dist/engine}/array.d.ts +0 -0
- /package/{engine → dist/engine}/bits.d.ts +0 -0
- /package/{engine → dist/engine}/field-list.d.ts +0 -0
- /package/{engine → dist/engine}/field-shell.d.ts +0 -0
- /package/{engine → dist/engine}/kit-field.d.ts +0 -0
- /package/{engine → dist/engine}/slot.d.ts +0 -0
- /package/{index.d.ts → dist/index.d.ts} +0 -0
- /package/{lib → dist/lib}/cn.d.ts +0 -0
- /package/{lib → dist/lib}/columns.d.ts +0 -0
- /package/{lib → dist/lib}/frames.d.ts +0 -0
- /package/{lib → dist/lib}/icons.d.ts +0 -0
- /package/{lib → dist/lib}/path.d.ts +0 -0
- /package/{lib → dist/lib}/utils.d.ts +0 -0
- /package/{schema → dist/schema}/adapters.d.ts +0 -0
- /package/{schema → dist/schema}/scale.d.ts +0 -0
- /package/{schema → dist/schema}/sources.d.ts +0 -0
- /package/{schema → dist/schema}/table.d.ts +0 -0
- /package/{types.d.ts → dist/types.d.ts} +0 -0
- /package/{ui → dist/ui}/choice-switch.d.ts +0 -0
- /package/{ui → dist/ui}/controls.d.ts +0 -0
- /package/{ui → dist/ui}/field-context.d.ts +0 -0
- /package/{ui → dist/ui}/mode-bar.d.ts +0 -0
- /package/{ui → dist/ui}/path-crumbs.d.ts +0 -0
- /package/{ui → dist/ui}/presence.d.ts +0 -0
- /package/{ui → dist/ui}/select.d.ts +0 -0
- /package/{ui → dist/ui}/shortcut-hint.d.ts +0 -0
- /package/{ui → dist/ui}/surfaces.d.ts +0 -0
- /package/{ui → dist/ui}/variants.d.ts +0 -0
|
@@ -95,3 +95,28 @@ export interface SlotReading {
|
|
|
95
95
|
export declare function readSlot(value: unknown): SlotReading;
|
|
96
96
|
/** Write a multiple slot: the items as they are (no `_key` the engine's list helpers add, which prod never stores). */
|
|
97
97
|
export declare function slotList(items: unknown[]): KitSlotItem[];
|
|
98
|
+
export declare function slotItemsFromStored(value: unknown): unknown;
|
|
99
|
+
export declare function slotItemsToStored(value: unknown): unknown;
|
|
100
|
+
type Values = Record<string, unknown>;
|
|
101
|
+
/** A legacy `{ componentId, overrides }` item has no `_key`: its row is keyed by position, stable while the list is. */
|
|
102
|
+
export declare const legacyChildKey: (i: number) => string;
|
|
103
|
+
/**
|
|
104
|
+
* A stored slot value as SlotField's V2 children `{ _key, _type, _settings?, ...values }` (`_type` the component id),
|
|
105
|
+
* each child's own values read by `read` (the host converts them per the CHILD's definition):
|
|
106
|
+
* a V2 child → itself, values read
|
|
107
|
+
* `{ componentId, … }` → a child keyed `legacy-<i>`, its overrides as the values; `style` / `window` (and any other
|
|
108
|
+
* key) ride in `_legacy` so a write keeps them
|
|
109
|
+
* a single object → a list of one; a detached `{ componentId: "" }` → none
|
|
110
|
+
* a component's own child blocks (no instance, no child) → none: the inherited content, shown until a block is added
|
|
111
|
+
* An entry that is none of these is named through `lose` (a write would drop it).
|
|
112
|
+
*/
|
|
113
|
+
export declare function slotChildrenFromStored(value: unknown, read: (type: string, values: Values, at: string) => Values, lose?: (at: string, reason: string) => void): unknown;
|
|
114
|
+
/**
|
|
115
|
+
* SlotField's children back as the slot stores them, each child's values written by `write` (per its definition). A
|
|
116
|
+
* multiple slot stores V2 children `{ _key, _type, _settings?, ...values }`; a child read from a legacy item that
|
|
117
|
+
* carried placement keys (`_legacy`) is written back as that item, keys and all. A single slot stores
|
|
118
|
+
* `{ componentId, overrides? }` (none: `{ componentId: "" }`). A child `_variant` is named through `lose`: the backend
|
|
119
|
+
* refuses one on a prop slot (a component variant is its own component, named in `_type`).
|
|
120
|
+
*/
|
|
121
|
+
export declare function slotChildrenToStored(value: unknown, multiple: boolean, write: (type: string, values: Values, at: string) => Values, lose: (at: string) => void): unknown;
|
|
122
|
+
export {};
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
//#region src/controls/slot-services.ts
|
|
2
|
+
/** SLOT_MAX_ITEMS / SLOT_ITEMS_CAP (@bettercms-ai/types): the default and the hard cap of a multiple slot. */
|
|
3
|
+
var SLOT_MAX_ITEMS = 12;
|
|
4
|
+
var SLOT_ITEMS_CAP = 50;
|
|
5
|
+
/** The renderers' nesting cap: past it a tree renders as nothing, so the editor refuses to nest further. */
|
|
6
|
+
var SLOT_DEPTH_MAX = 10;
|
|
7
|
+
var isObj = (v) => !!v && typeof v === "object" && !Array.isArray(v);
|
|
8
|
+
var isItem = (v) => isObj(v) && typeof v.componentId === "string" && v.componentId !== "";
|
|
9
|
+
/**
|
|
10
|
+
* A stored slot value as its instances (`slotItems`, the one reading of a slot value): a list is its items, a single
|
|
11
|
+
* `{ componentId }` is a list of one, a detached `{ componentId: "" }` is none. A non-empty list with no instance and no
|
|
12
|
+
* V2 child is the component's own child blocks (the inherited value), not something to drop.
|
|
13
|
+
*/
|
|
14
|
+
function readSlot(value) {
|
|
15
|
+
if (Array.isArray(value)) {
|
|
16
|
+
const items = value.filter(isItem);
|
|
17
|
+
const rest = value.filter((v) => !isItem(v));
|
|
18
|
+
const v2 = rest.filter((v) => isObj(v) && v.componentId === void 0 && ("_type" in v || "_key" in v));
|
|
19
|
+
const inherited = items.length === 0 && v2.length === 0 && rest.length > 0;
|
|
20
|
+
return {
|
|
21
|
+
items,
|
|
22
|
+
inherited,
|
|
23
|
+
unreadable: inherited ? 0 : rest.length
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
return {
|
|
27
|
+
items: isItem(value) ? [value] : [],
|
|
28
|
+
inherited: false,
|
|
29
|
+
unreadable: 0
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/** Write a multiple slot: the items as they are (no `_key` the engine's list helpers add, which prod never stores). */
|
|
33
|
+
function slotList(items) {
|
|
34
|
+
return items.filter(isItem).map((it) => {
|
|
35
|
+
if (!("_key" in it)) return it;
|
|
36
|
+
const { _key, ...rest } = it;
|
|
37
|
+
return rest;
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* A stored V2 slot child (`{ _key, _type, _settings?, ...props }`, `_type` the component id: BE slot-values.ts isV2Child)
|
|
42
|
+
* as the item this control edits, and back. The child's props are its overrides; its `_key` rides along as `_v2Key` (the
|
|
43
|
+
* engine's own `_key` is stripped on write, slotList) and its `_settings` as they are, so an edit writes the child in
|
|
44
|
+
* the shape it was read. Items stored as `{ componentId, overrides? }` (and a component's own child blocks) pass as
|
|
45
|
+
* they are.
|
|
46
|
+
*/
|
|
47
|
+
var isV2Child = (v) => isObj(v) && v.componentId === void 0 && ("_type" in v || "_key" in v);
|
|
48
|
+
function slotItemsFromStored(value) {
|
|
49
|
+
if (!Array.isArray(value)) return value;
|
|
50
|
+
return value.map((child) => {
|
|
51
|
+
if (!isV2Child(child)) return child;
|
|
52
|
+
const { _key, _type, _settings, ...overrides } = child;
|
|
53
|
+
return {
|
|
54
|
+
componentId: typeof _type === "string" ? _type : "",
|
|
55
|
+
overrides,
|
|
56
|
+
...typeof _key === "string" ? { _v2Key: _key } : {},
|
|
57
|
+
..._settings !== void 0 ? { _settings } : {}
|
|
58
|
+
};
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
function slotItemsToStored(value) {
|
|
62
|
+
if (!Array.isArray(value)) return value;
|
|
63
|
+
return value.map((item) => {
|
|
64
|
+
if (!isObj(item) || typeof item._v2Key !== "string") return item;
|
|
65
|
+
const { _v2Key, componentId, overrides, _settings, ...rest } = item;
|
|
66
|
+
return {
|
|
67
|
+
_key: _v2Key,
|
|
68
|
+
_type: componentId,
|
|
69
|
+
..._settings !== void 0 ? { _settings } : {},
|
|
70
|
+
...rest,
|
|
71
|
+
...isObj(overrides) ? overrides : {}
|
|
72
|
+
};
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
/** The child's reserved keys (BE slot-child.ts SLOT_CHILD_KEYS) plus `_legacy`, where a legacy item's placement keys ride. */
|
|
76
|
+
var RESERVED = /* @__PURE__ */ new Set([
|
|
77
|
+
"_key",
|
|
78
|
+
"_type",
|
|
79
|
+
"_variant",
|
|
80
|
+
"_settings",
|
|
81
|
+
"_legacy"
|
|
82
|
+
]);
|
|
83
|
+
var ownValues = (child) => Object.fromEntries(Object.entries(child).filter(([k]) => !RESERVED.has(k)));
|
|
84
|
+
/** A legacy `{ componentId, overrides }` item has no `_key`: its row is keyed by position, stable while the list is. */
|
|
85
|
+
var legacyChildKey = (i) => `legacy-${i}`;
|
|
86
|
+
/**
|
|
87
|
+
* A stored slot value as SlotField's V2 children `{ _key, _type, _settings?, ...values }` (`_type` the component id),
|
|
88
|
+
* each child's own values read by `read` (the host converts them per the CHILD's definition):
|
|
89
|
+
* a V2 child → itself, values read
|
|
90
|
+
* `{ componentId, … }` → a child keyed `legacy-<i>`, its overrides as the values; `style` / `window` (and any other
|
|
91
|
+
* key) ride in `_legacy` so a write keeps them
|
|
92
|
+
* a single object → a list of one; a detached `{ componentId: "" }` → none
|
|
93
|
+
* a component's own child blocks (no instance, no child) → none: the inherited content, shown until a block is added
|
|
94
|
+
* An entry that is none of these is named through `lose` (a write would drop it).
|
|
95
|
+
*/
|
|
96
|
+
function slotChildrenFromStored(value, read, lose) {
|
|
97
|
+
const one = (v, i) => {
|
|
98
|
+
if (isItem(v)) {
|
|
99
|
+
const { componentId, overrides, ...extras } = v;
|
|
100
|
+
return [{
|
|
101
|
+
_key: legacyChildKey(i),
|
|
102
|
+
_type: componentId,
|
|
103
|
+
...Object.keys(extras).length ? { _legacy: extras } : {},
|
|
104
|
+
...read(componentId, isObj(overrides) ? overrides : {}, `${i}`)
|
|
105
|
+
}];
|
|
106
|
+
}
|
|
107
|
+
if (isV2Child(v)) {
|
|
108
|
+
const type = typeof v._type === "string" ? v._type : "";
|
|
109
|
+
return [{
|
|
110
|
+
...Object.fromEntries(Object.entries(v).filter(([k]) => RESERVED.has(k) && k !== "_legacy")),
|
|
111
|
+
...read(type, ownValues(v), `${i}`)
|
|
112
|
+
}];
|
|
113
|
+
}
|
|
114
|
+
lose?.(`${i}`, "This slot entry is neither a block instance nor a slot child, so a write would drop it.");
|
|
115
|
+
return [];
|
|
116
|
+
};
|
|
117
|
+
if (!Array.isArray(value)) {
|
|
118
|
+
if (isObj(value) && value.componentId === "") return [];
|
|
119
|
+
return isItem(value) || isV2Child(value) ? one(value, 0) : value;
|
|
120
|
+
}
|
|
121
|
+
if (value.length && !value.some((v) => isItem(v) || isV2Child(v))) return [];
|
|
122
|
+
return value.flatMap(one);
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* SlotField's children back as the slot stores them, each child's values written by `write` (per its definition). A
|
|
126
|
+
* multiple slot stores V2 children `{ _key, _type, _settings?, ...values }`; a child read from a legacy item that
|
|
127
|
+
* carried placement keys (`_legacy`) is written back as that item, keys and all. A single slot stores
|
|
128
|
+
* `{ componentId, overrides? }` (none: `{ componentId: "" }`). A child `_variant` is named through `lose`: the backend
|
|
129
|
+
* refuses one on a prop slot (a component variant is its own component, named in `_type`).
|
|
130
|
+
*/
|
|
131
|
+
function slotChildrenToStored(value, multiple, write, lose) {
|
|
132
|
+
if (!Array.isArray(value)) return value;
|
|
133
|
+
const out = value.map((c, i) => {
|
|
134
|
+
if (!isObj(c)) return c;
|
|
135
|
+
const type = typeof c._type === "string" ? c._type : "";
|
|
136
|
+
if (c._variant !== void 0) lose(`${i}/_variant`);
|
|
137
|
+
const own = write(type, ownValues(c), `${i}`);
|
|
138
|
+
if (!multiple || isObj(c._legacy)) return {
|
|
139
|
+
componentId: type,
|
|
140
|
+
...Object.keys(own).length ? { overrides: own } : {},
|
|
141
|
+
...isObj(c._legacy) ? c._legacy : {}
|
|
142
|
+
};
|
|
143
|
+
return {
|
|
144
|
+
_key: c._key,
|
|
145
|
+
_type: type,
|
|
146
|
+
...c._settings !== void 0 ? { _settings: c._settings } : {},
|
|
147
|
+
...own
|
|
148
|
+
};
|
|
149
|
+
});
|
|
150
|
+
return multiple ? out : out[0] ?? { componentId: "" };
|
|
151
|
+
}
|
|
152
|
+
//#endregion
|
|
153
|
+
export { SLOT_DEPTH_MAX, SLOT_ITEMS_CAP, SLOT_MAX_ITEMS, legacyChildKey, readSlot, slotChildrenFromStored, slotChildrenToStored, slotItemsFromStored, slotItemsToStored, slotList };
|
|
154
|
+
|
|
155
|
+
//# sourceMappingURL=slot-services.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slot-services.js","names":[],"sources":["../../src/controls/slot-services.ts"],"sourcesContent":["/**\n * Component slots (lane L3): the services the slot control reads and the reading of a stored slot value, declared as\n * augmentations so context.tsx and schema/types.ts stay untouched by this lane.\n *\n * A prod `slot` prop holds component instances, not V2 blocks:\n * single `{ componentId, overrides? }` (a detached slot is `{ componentId: \"\" }`)\n * multiple `[{ componentId, overrides?, style?, window? }, …]`; a single object reads as a list of one\n * The host marks such a field with `componentSlot` (the dock reads it off the prop's config) and the slot control draws\n * it; the value is written back in exactly that shape, each item spread with the keys this control does not show.\n *\n * useSlotCatalog → a React HOOK: the components this slot may take, with the SERVER's insertability verdicts\n * (GET /components/section-catalog) already turned into words, and the name of any component id\n * SlotChild → the host's editor for one child's own props (its overrides), drawn under the child's row\n */\nimport type { ComponentType } from \"react\";\n\n/** One component the slot picker lists. `insertable: false` always carries `reason`, a sentence the picker shows. */\nexport interface KitSlotEntry {\n id: string;\n title: string;\n /** the section family (\"Hero\"), shown as the picker's group */\n category?: string | null;\n description?: string | null;\n icon?: string;\n insertable: boolean;\n reason?: string;\n}\n\nexport interface KitSlotCatalog {\n entries: KitSlotEntry[];\n loading?: boolean;\n /** a whole sentence naming what failed (\"Sections couldn't be loaded: …\") */\n error?: string;\n /** a sentence under the picker's list naming what can never fill a slot and why (built-in sections) */\n note?: string;\n /** a component id's name; `missing` when the project has no such component (deleted, or another project's) */\n nameOf: (componentId: string) => { title: string; missing?: boolean } | undefined;\n}\n\nexport interface KitSlotChildProps {\n componentId: string;\n title: string;\n overrides: Record<string, unknown>;\n onChange: (next: Record<string, unknown>) => void;\n readOnly?: boolean;\n /** how many slots deep this child sits (1 for a top-level slot's child) */\n depth: number;\n}\n\n/** The slot's own rules, mirrored from the prop's config so a save is not refused (BE slot-values.ts). */\nexport interface KitComponentSlot {\n multiple: boolean;\n /** config.componentIds: the only components it takes (empty or absent: any) */\n componentIds?: string[];\n /** config.minItems (multiple only) */\n min: number;\n /** config.maxItems, defaulted to 12 and capped at 50 (multiple only; a single slot holds one) */\n max: number;\n}\n\ndeclare module \"../context\" {\n interface KitServices {\n useSlotCatalog?: (req: { componentIds?: string[] }) => KitSlotCatalog;\n SlotChild?: ComponentType<KitSlotChildProps>;\n }\n}\n\ndeclare module \"../schema/types\" {\n interface FieldSchema {\n /** a component slot (prod `slot` prop): drawn by the slot control instead of the json editor */\n componentSlot?: KitComponentSlot;\n }\n}\n\n/** SLOT_MAX_ITEMS / SLOT_ITEMS_CAP (@bettercms-ai/types): the default and the hard cap of a multiple slot. */\nexport const SLOT_MAX_ITEMS = 12;\nexport const SLOT_ITEMS_CAP = 50;\n/** The renderers' nesting cap: past it a tree renders as nothing, so the editor refuses to nest further. */\nexport const SLOT_DEPTH_MAX = 10;\n\nexport interface KitSlotItem {\n componentId: string;\n overrides?: Record<string, unknown>;\n [key: string]: unknown;\n}\n\nexport interface SlotReading {\n items: KitSlotItem[];\n /** the value is the component's own content (its child blocks), shown until an item is added */\n inherited: boolean;\n /** entries this control can't read and would drop on a write (V2 block children, malformed rows) */\n unreadable: number;\n}\n\nconst isObj = (v: unknown): v is Record<string, unknown> => !!v && typeof v === \"object\" && !Array.isArray(v);\nconst isItem = (v: unknown): v is KitSlotItem => isObj(v) && typeof v.componentId === \"string\" && v.componentId !== \"\";\n\n/**\n * A stored slot value as its instances (`slotItems`, the one reading of a slot value): a list is its items, a single\n * `{ componentId }` is a list of one, a detached `{ componentId: \"\" }` is none. A non-empty list with no instance and no\n * V2 child is the component's own child blocks (the inherited value), not something to drop.\n */\nexport function readSlot(value: unknown): SlotReading {\n if (Array.isArray(value)) {\n const items = value.filter(isItem);\n const rest = value.filter((v) => !isItem(v));\n const v2 = rest.filter((v) => isObj(v) && v.componentId === undefined && (\"_type\" in v || \"_key\" in v));\n const inherited = items.length === 0 && v2.length === 0 && rest.length > 0;\n return { items, inherited, unreadable: inherited ? 0 : rest.length };\n }\n return { items: isItem(value) ? [value] : [], inherited: false, unreadable: 0 };\n}\n\n/** Write a multiple slot: the items as they are (no `_key` the engine's list helpers add, which prod never stores). */\nexport function slotList(items: unknown[]): KitSlotItem[] {\n return items.filter(isItem).map((it) => {\n if (!(\"_key\" in it)) return it;\n const { _key, ...rest } = it;\n void _key;\n return rest as KitSlotItem;\n });\n}\n\n/**\n * A stored V2 slot child (`{ _key, _type, _settings?, ...props }`, `_type` the component id: BE slot-values.ts isV2Child)\n * as the item this control edits, and back. The child's props are its overrides; its `_key` rides along as `_v2Key` (the\n * engine's own `_key` is stripped on write, slotList) and its `_settings` as they are, so an edit writes the child in\n * the shape it was read. Items stored as `{ componentId, overrides? }` (and a component's own child blocks) pass as\n * they are.\n */\nconst isV2Child = (v: unknown): v is Record<string, unknown> => isObj(v) && v.componentId === undefined && (\"_type\" in v || \"_key\" in v);\n\nexport function slotItemsFromStored(value: unknown): unknown {\n if (!Array.isArray(value)) return value;\n return value.map((child) => {\n if (!isV2Child(child)) return child;\n const { _key, _type, _settings, ...overrides } = child;\n return {\n componentId: typeof _type === \"string\" ? _type : \"\",\n overrides,\n ...(typeof _key === \"string\" ? { _v2Key: _key } : {}),\n ...(_settings !== undefined ? { _settings } : {}),\n };\n });\n}\n\nexport function slotItemsToStored(value: unknown): unknown {\n if (!Array.isArray(value)) return value;\n return value.map((item) => {\n if (!isObj(item) || typeof item._v2Key !== \"string\") return item;\n const { _v2Key, componentId, overrides, _settings, ...rest } = item;\n return { _key: _v2Key, _type: componentId, ...(_settings !== undefined ? { _settings } : {}), ...rest, ...(isObj(overrides) ? overrides : {}) };\n });\n}\n\n/* ── V2 slot children (SlotField) ───────────────────────────────────────── */\ntype Values = Record<string, unknown>;\n/** The child's reserved keys (BE slot-child.ts SLOT_CHILD_KEYS) plus `_legacy`, where a legacy item's placement keys ride. */\nconst RESERVED = new Set([\"_key\", \"_type\", \"_variant\", \"_settings\", \"_legacy\"]);\nconst ownValues = (child: Values): Values => Object.fromEntries(Object.entries(child).filter(([k]) => !RESERVED.has(k)));\n/** A legacy `{ componentId, overrides }` item has no `_key`: its row is keyed by position, stable while the list is. */\nexport const legacyChildKey = (i: number) => `legacy-${i}`;\n\n/**\n * A stored slot value as SlotField's V2 children `{ _key, _type, _settings?, ...values }` (`_type` the component id),\n * each child's own values read by `read` (the host converts them per the CHILD's definition):\n * a V2 child → itself, values read\n * `{ componentId, … }` → a child keyed `legacy-<i>`, its overrides as the values; `style` / `window` (and any other\n * key) ride in `_legacy` so a write keeps them\n * a single object → a list of one; a detached `{ componentId: \"\" }` → none\n * a component's own child blocks (no instance, no child) → none: the inherited content, shown until a block is added\n * An entry that is none of these is named through `lose` (a write would drop it).\n */\nexport function slotChildrenFromStored(value: unknown, read: (type: string, values: Values, at: string) => Values, lose?: (at: string, reason: string) => void): unknown {\n const one = (v: unknown, i: number): Values[] => {\n if (isItem(v)) {\n const { componentId, overrides, ...extras } = v;\n return [{ _key: legacyChildKey(i), _type: componentId, ...(Object.keys(extras).length ? { _legacy: extras } : {}), ...read(componentId, isObj(overrides) ? overrides : {}, `${i}`) }];\n }\n if (isV2Child(v)) {\n const type = typeof v._type === \"string\" ? v._type : \"\";\n const kept = Object.fromEntries(Object.entries(v).filter(([k]) => RESERVED.has(k) && k !== \"_legacy\"));\n return [{ ...kept, ...read(type, ownValues(v), `${i}`) }];\n }\n lose?.(`${i}`, \"This slot entry is neither a block instance nor a slot child, so a write would drop it.\");\n return [];\n };\n if (!Array.isArray(value)) {\n if (isObj(value) && value.componentId === \"\") return [];\n return isItem(value) || isV2Child(value) ? one(value, 0) : value;\n }\n if (value.length && !value.some((v) => isItem(v) || isV2Child(v))) return [];\n return value.flatMap(one);\n}\n\n/**\n * SlotField's children back as the slot stores them, each child's values written by `write` (per its definition). A\n * multiple slot stores V2 children `{ _key, _type, _settings?, ...values }`; a child read from a legacy item that\n * carried placement keys (`_legacy`) is written back as that item, keys and all. A single slot stores\n * `{ componentId, overrides? }` (none: `{ componentId: \"\" }`). A child `_variant` is named through `lose`: the backend\n * refuses one on a prop slot (a component variant is its own component, named in `_type`).\n */\nexport function slotChildrenToStored(value: unknown, multiple: boolean, write: (type: string, values: Values, at: string) => Values, lose: (at: string) => void): unknown {\n if (!Array.isArray(value)) return value;\n const out = value.map((c, i) => {\n if (!isObj(c)) return c;\n const type = typeof c._type === \"string\" ? c._type : \"\";\n if (c._variant !== undefined) lose(`${i}/_variant`);\n const own = write(type, ownValues(c), `${i}`);\n if (!multiple || isObj(c._legacy)) return { componentId: type, ...(Object.keys(own).length ? { overrides: own } : {}), ...(isObj(c._legacy) ? c._legacy : {}) };\n return { _key: c._key, _type: type, ...(c._settings !== undefined ? { _settings: c._settings } : {}), ...own };\n });\n return multiple ? out : (out[0] ?? { componentId: \"\" });\n}\n"],"mappings":"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"}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
+
import { readSlot, slotList } from "./slot-services.js";
|
|
1
2
|
import { cn } from "../lib/cn.js";
|
|
2
|
-
import { KitIcon } from "../lib/icons.js";
|
|
3
3
|
import { useKitServices } from "../context.js";
|
|
4
|
+
import { KitIcon } from "../lib/icons.js";
|
|
4
5
|
import { Button } from "../ui/button.js";
|
|
5
6
|
import { Popover, PopoverContent, PopoverTrigger } from "../ui/overlay.js";
|
|
6
7
|
import { RowList, useListOps } from "../engine/array.js";
|
|
7
|
-
import { readSlot, slotList } from "./slot-services.js";
|
|
8
8
|
import * as React from "react";
|
|
9
|
-
import { IconPlus, IconSearch } from "@tabler/icons-react";
|
|
10
9
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
11
|
-
|
|
10
|
+
import { IconPlus, IconSearch } from "@tabler/icons-react";
|
|
11
|
+
//#region src/controls/slot.tsx
|
|
12
12
|
/**
|
|
13
13
|
* COMPONENT SLOT — a prop that holds component instances (prod `slot`), on the engine's slot surface (engine/slot.tsx,
|
|
14
14
|
* V2 HEAD 9829bf1): the block rows (icon tile, name, ⋯ menu, drag to reorder) and the compact searchable picker.
|
|
@@ -24,7 +24,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
24
24
|
*/
|
|
25
25
|
/** How many slots deep the control sits: the host's SlotChild editor sits inside a provider one level down. */
|
|
26
26
|
var SlotDepthContext = React.createContext(0);
|
|
27
|
-
var count = (n) => `${n}
|
|
27
|
+
var count = (n) => `${n} block${n === 1 ? "" : "s"}`;
|
|
28
28
|
var NO_CATALOG = {
|
|
29
29
|
entries: [],
|
|
30
30
|
nameOf: () => void 0
|
|
@@ -46,7 +46,7 @@ function ComponentSlotControl({ field, value, onChange, readOnly, id, path }) {
|
|
|
46
46
|
max: 1
|
|
47
47
|
};
|
|
48
48
|
const depth = React.useContext(SlotDepthContext);
|
|
49
|
-
const { useSlotCatalog, SlotChild } = useKitServices();
|
|
49
|
+
const { useSlotCatalog, SlotChild, toast } = useKitServices();
|
|
50
50
|
const catalog = useSlotCatalog ? useSlotCatalog({ componentIds: slot.componentIds }) : null;
|
|
51
51
|
const read = readSlot(value);
|
|
52
52
|
const items = read.items;
|
|
@@ -71,7 +71,7 @@ function ComponentSlotControl({ field, value, onChange, readOnly, id, path }) {
|
|
|
71
71
|
const ops = useListOps(opsField, path, items, write);
|
|
72
72
|
if (depth >= 10) return /* @__PURE__ */ jsx(SlotNote, {
|
|
73
73
|
id,
|
|
74
|
-
children: "Nested
|
|
74
|
+
children: "Nested block limit reached. A slot this deep would render as nothing, so it can’t hold more blocks here."
|
|
75
75
|
});
|
|
76
76
|
const pick = (componentId) => {
|
|
77
77
|
if (!slot.multiple) {
|
|
@@ -104,20 +104,38 @@ function ComponentSlotControl({ field, value, onChange, readOnly, id, path }) {
|
|
|
104
104
|
item: it,
|
|
105
105
|
path: [...path, i],
|
|
106
106
|
preview: {
|
|
107
|
-
title: name.missing ? "Missing
|
|
107
|
+
title: name.missing ? "Missing block" : name.title,
|
|
108
108
|
icon: entry?.icon ?? "box",
|
|
109
109
|
empty: false
|
|
110
110
|
},
|
|
111
|
-
extra: name.missing ? "Deleted, or not in this project. Replace or remove it." : entry?.category ?? `
|
|
111
|
+
extra: name.missing ? "Deleted, or not in this project. Replace or remove it." : entry?.category ?? `Block ${i + 1} of ${items.length}`
|
|
112
112
|
};
|
|
113
113
|
});
|
|
114
|
-
const
|
|
114
|
+
const only = slot.componentIds?.length === 1 ? catalog?.entries.find((e) => e.id === slot.componentIds[0]) : void 0;
|
|
115
|
+
const quickAdd = only?.insertable && (slot.multiple || items.length === 0) ? only : void 0;
|
|
116
|
+
const addOnly = (entry) => {
|
|
117
|
+
const before = value;
|
|
118
|
+
pick(entry.id);
|
|
119
|
+
toast?.(`${entry.title} added to ${field.title}`, { action: {
|
|
120
|
+
label: "Undo",
|
|
121
|
+
onClick: () => onChange(before)
|
|
122
|
+
} });
|
|
123
|
+
};
|
|
124
|
+
const picker = quickAdd ? /* @__PURE__ */ jsxs(Button, {
|
|
125
|
+
size: "lg",
|
|
126
|
+
variant: "ghost",
|
|
127
|
+
className: "text-kit-fg-2",
|
|
128
|
+
leftIcon: /* @__PURE__ */ jsx(IconPlus, { stroke: 1.5 }),
|
|
129
|
+
disabled: locked || slot.multiple && items.length >= max,
|
|
130
|
+
onClick: () => addOnly(quickAdd),
|
|
131
|
+
children: ["Add ", quickAdd.title]
|
|
132
|
+
}) : catalog ? /* @__PURE__ */ jsx(SlotPicker, {
|
|
115
133
|
entries: catalog.entries,
|
|
116
134
|
loading: catalog.loading,
|
|
117
135
|
error: catalog.error,
|
|
118
136
|
note: catalog.note,
|
|
119
137
|
current: slot.multiple ? void 0 : items[0]?.componentId,
|
|
120
|
-
label: slot.multiple ? "Add
|
|
138
|
+
label: slot.multiple ? "Add block" : items.length ? "Replace block" : "Choose a block",
|
|
121
139
|
disabled: locked || slot.multiple && items.length >= max,
|
|
122
140
|
onPick: pick
|
|
123
141
|
}) : null;
|
|
@@ -128,13 +146,13 @@ function ComponentSlotControl({ field, value, onChange, readOnly, id, path }) {
|
|
|
128
146
|
read.unreadable > 0 ? /* @__PURE__ */ jsxs(SlotNote, {
|
|
129
147
|
tone: "warning",
|
|
130
148
|
children: [
|
|
131
|
-
read.unreadable === 1 ? "One child here isn't a
|
|
149
|
+
read.unreadable === 1 ? "One child here isn't a block instance" : `${read.unreadable} children here aren't block instances`,
|
|
132
150
|
" (blocks written by another editor). This editor would drop ",
|
|
133
151
|
read.unreadable === 1 ? "it" : "them",
|
|
134
152
|
" on save, so the slot is shown read-only and its value is kept."
|
|
135
153
|
]
|
|
136
154
|
}) : null,
|
|
137
|
-
read.inherited && items.length === 0 ? /* @__PURE__ */ jsx(SlotNote, { children: "Shows the
|
|
155
|
+
read.inherited && items.length === 0 ? /* @__PURE__ */ jsx(SlotNote, { children: "Shows the block’s own content until a block is added here." }) : null,
|
|
138
156
|
/* @__PURE__ */ jsx("div", {
|
|
139
157
|
id,
|
|
140
158
|
tabIndex: -1,
|
|
@@ -177,9 +195,9 @@ function ComponentSlotControl({ field, value, onChange, readOnly, id, path }) {
|
|
|
177
195
|
className: "size-4"
|
|
178
196
|
})
|
|
179
197
|
}),
|
|
180
|
-
emptyLabel: slot.multiple ? "No
|
|
198
|
+
emptyLabel: slot.multiple ? "No blocks yet. Add one to start composing." : "No block yet. Choose one to fill this slot.",
|
|
181
199
|
addButton: picker ?? /* @__PURE__ */ jsxs(SlotNote, { children: [
|
|
182
|
-
"No
|
|
200
|
+
"No block library is connected to this editor, so ",
|
|
183
201
|
field.title,
|
|
184
202
|
" can’t be changed here."
|
|
185
203
|
] })
|
|
@@ -202,8 +220,8 @@ function SlotPicker({ entries, loading, error, note, current, label, disabled, o
|
|
|
202
220
|
const [active, setActive] = React.useState(0);
|
|
203
221
|
const listId = React.useId();
|
|
204
222
|
const list = entries.filter((b) => !q || `${b.title} ${b.category ?? ""} ${b.description ?? ""}`.toLowerCase().includes(q.toLowerCase()));
|
|
205
|
-
const cats = Array.from(new Set(list.map((b) => b.category || "
|
|
206
|
-
const flat = cats.flatMap((c) => list.filter((b) => (b.category || "
|
|
223
|
+
const cats = Array.from(new Set(list.map((b) => b.category || "Blocks")));
|
|
224
|
+
const flat = cats.flatMap((c) => list.filter((b) => (b.category || "Blocks") === c));
|
|
207
225
|
const choose = (b) => {
|
|
208
226
|
if (!b || !b.insertable) return;
|
|
209
227
|
onPick(b.id);
|
|
@@ -256,8 +274,8 @@ function SlotPicker({ entries, loading, error, note, current, label, disabled, o
|
|
|
256
274
|
choose(flat[active]);
|
|
257
275
|
}
|
|
258
276
|
},
|
|
259
|
-
placeholder: "Search
|
|
260
|
-
"aria-label": "Search
|
|
277
|
+
placeholder: "Search blocks",
|
|
278
|
+
"aria-label": "Search blocks",
|
|
261
279
|
role: "combobox",
|
|
262
280
|
"aria-expanded": true,
|
|
263
281
|
"aria-controls": listId,
|
|
@@ -269,17 +287,17 @@ function SlotPicker({ entries, loading, error, note, current, label, disabled, o
|
|
|
269
287
|
id: listId,
|
|
270
288
|
className: "max-h-80 overflow-y-auto p-1",
|
|
271
289
|
role: "listbox",
|
|
272
|
-
"aria-label": "
|
|
290
|
+
"aria-label": "Blocks",
|
|
273
291
|
"aria-busy": loading || void 0,
|
|
274
292
|
children: [
|
|
275
293
|
loading && entries.length === 0 ? /* @__PURE__ */ jsx("p", {
|
|
276
294
|
role: "status",
|
|
277
295
|
className: "px-3 py-6 text-center text-kit-sm text-kit-fg-3",
|
|
278
|
-
children: "Loading
|
|
296
|
+
children: "Loading blocks…"
|
|
279
297
|
}) : null,
|
|
280
298
|
!loading && !error && flat.length === 0 ? /* @__PURE__ */ jsx("p", {
|
|
281
299
|
className: "px-3 py-6 text-center text-kit-sm text-kit-fg-3",
|
|
282
|
-
children: entries.length ? "No
|
|
300
|
+
children: entries.length ? "No blocks match" : "This project has no blocks that can go here yet."
|
|
283
301
|
}) : null,
|
|
284
302
|
error ? /* @__PURE__ */ jsx("p", {
|
|
285
303
|
role: "alert",
|
|
@@ -294,7 +312,7 @@ function SlotPicker({ entries, loading, error, note, current, label, disabled, o
|
|
|
294
312
|
"aria-hidden": true,
|
|
295
313
|
className: "px-2 pb-1 pt-1.5 text-kit-2xs font-medium text-kit-fg-3",
|
|
296
314
|
children: c
|
|
297
|
-
}), list.filter((b) => (b.category || "
|
|
315
|
+
}), list.filter((b) => (b.category || "Blocks") === c).map((b) => {
|
|
298
316
|
const i = flat.indexOf(b);
|
|
299
317
|
return /* @__PURE__ */ jsxs("div", {
|
|
300
318
|
id: optionId(i),
|
|
@@ -343,6 +361,6 @@ function SlotPicker({ entries, loading, error, note, current, label, disabled, o
|
|
|
343
361
|
});
|
|
344
362
|
}
|
|
345
363
|
//#endregion
|
|
346
|
-
export { ComponentSlotControl };
|
|
364
|
+
export { ComponentSlotControl, SlotDepthContext, SlotPicker };
|
|
347
365
|
|
|
348
366
|
//# sourceMappingURL=slot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slot.js","names":[],"sources":["../../src/controls/slot.tsx"],"sourcesContent":["/**\n * COMPONENT SLOT — a prop that holds component instances (prod `slot`), on the engine's slot surface (engine/slot.tsx,\n * V2 HEAD 9829bf1): the block rows (icon tile, name, ⋯ menu, drag to reorder) and the compact searchable picker.\n *\n * What differs from V2's block slot is where the rows come from and what they store:\n * - the picker lists the host's slot catalog (`useSlotCatalog`): the project's components with the SERVER's\n * insertability verdict for each; one that can't go here stays in the list, disabled, with the reason under its name;\n * - a row opens in place and edits that child's own props through the host's `SlotChild`;\n * - the value is written in the stored shape (slot-services.ts): one `{ componentId, overrides? }`, or a list of them\n * for a multiple slot, every item spread back with the keys this control does not show (style, window).\n *\n * Refusals are said in words, never by an inert control: no catalog service, an unreadable stored value, the nesting cap.\n */\nimport * as React from \"react\";\nimport { IconPlus, IconSearch } from \"@tabler/icons-react\";\nimport { useKitServices } from \"../context\";\nimport { KitIcon } from \"../lib/icons\";\nimport { cn } from \"../lib/cn\";\nimport { Button } from \"../ui/button\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"../ui/overlay\";\nimport { RowList, useListOps, type RowModel } from \"../engine/array\";\nimport type { FieldSchema } from \"../schema/types\";\nimport type { ControlProps } from \"../types\";\nimport { readSlot, slotList, SLOT_DEPTH_MAX, type KitComponentSlot, type KitSlotEntry, type KitSlotItem } from \"./slot-services\";\n\n/** How many slots deep the control sits: the host's SlotChild editor sits inside a provider one level down. */\nexport const SlotDepthContext = React.createContext(0);\n\nconst count = (n: number) => `${n} block${n === 1 ? \"\" : \"s\"}`;\nconst NO_CATALOG = { entries: [] as KitSlotEntry[], nameOf: () => undefined };\n\n/** A note in words, labelable and focusable (the field label's `for` lands on it). */\nfunction SlotNote({ id, children, tone = \"muted\" }: { id?: string; children: React.ReactNode; tone?: \"muted\" | \"warning\" }) {\n return (\n <output\n id={id}\n role=\"note\"\n tabIndex={id ? 0 : undefined}\n className={cn(\n \"block rounded-kit-sm text-kit-xs outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-kit-focus-ring focus-visible:[outline-style:solid] [html[data-input-modality=pointer]_&]:focus-visible:outline-none\",\n tone === \"warning\" ? \"text-kit-warning-fg\" : \"text-kit-fg-3\",\n )}\n >\n {children}\n </output>\n );\n}\n\nexport function ComponentSlotControl({ field, value, onChange, readOnly, id, path }: ControlProps) {\n const slot: KitComponentSlot = field.componentSlot ?? { multiple: false, min: 0, max: 1 };\n const depth = React.useContext(SlotDepthContext);\n const { useSlotCatalog, SlotChild, toast } = useKitServices();\n // a hook service: one identity for the life of the form, so it is called on every render or never\n const catalog = useSlotCatalog ? useSlotCatalog({ componentIds: slot.componentIds }) : null; // eslint-disable-line react-hooks/rules-of-hooks\n const read = readSlot(value);\n const items = read.items;\n const max = slot.multiple ? slot.max : 1;\n const [openId, setOpenId] = React.useState<string | null>(null);\n const nameOf = (componentId: string) => (catalog ?? NO_CATALOG).nameOf(componentId) ?? { title: catalog?.loading ? \"Loading…\" : componentId };\n const locked = readOnly || read.unreadable > 0;\n\n /* writes: the stored shape, never a `_key` (useListOps' duplicate adds one) */\n const write = (next: unknown[]) => {\n setOpenId(null);\n if (slot.multiple) return onChange(slotList(next));\n const [first] = slotList(next);\n onChange(first ?? { componentId: \"\" });\n };\n const opsField: FieldSchema = { ...field, validation: { ...field.validation, min: slot.multiple ? slot.min : 0, max } };\n const ops = useListOps(opsField, path, items, write);\n if (depth >= SLOT_DEPTH_MAX) return <SlotNote id={id}>Nested block limit reached. A slot this deep would render as nothing, so it can’t hold more blocks here.</SlotNote>;\n const pick = (componentId: string) => {\n if (!slot.multiple) {\n const cur = items[0];\n // a different component's overrides are keyed by the old component's props: dropped, never half-applied\n onChange(cur && cur.componentId === componentId ? cur : { componentId });\n setOpenId(null);\n return;\n }\n if (items.length >= max) return;\n onChange([...items, { componentId }]);\n setOpenId(`i${items.length}`);\n };\n const setOverrides = (index: number, overrides: Record<string, unknown>) => {\n const next = items.map((it, i) => (i === index ? { ...it, overrides } : it));\n if (slot.multiple) onChange(next);\n else onChange({ componentId: next[0].componentId, overrides });\n };\n\n const rows: RowModel[] = items.map((it, i) => {\n const name = nameOf(it.componentId);\n const entry = catalog?.entries.find((e) => e.id === it.componentId);\n return {\n id: `i${i}`,\n index: i,\n item: it,\n path: [...path, i],\n preview: { title: name.missing ? \"Missing block\" : name.title, icon: entry?.icon ?? \"box\", empty: false },\n extra: name.missing ? \"Deleted, or not in this project. Replace or remove it.\" : (entry?.category ?? `Block ${i + 1} of ${items.length}`),\n };\n });\n\n /*\n * A slot that takes exactly one block type adds it in one press (V2 content-form.tsx \"Add {child}\"): no picker to\n * choose from a list of one. Not insertable here → the picker, which says why. Undo puts the slot back as it was.\n */\n const only = slot.componentIds?.length === 1 ? catalog?.entries.find((e) => e.id === slot.componentIds![0]) : undefined;\n const quickAdd = only?.insertable && (slot.multiple || items.length === 0) ? only : undefined;\n const addOnly = (entry: KitSlotEntry) => {\n const before = value;\n pick(entry.id);\n toast?.(`${entry.title} added to ${field.title}`, { action: { label: \"Undo\", onClick: () => onChange(before) } });\n };\n\n const picker = quickAdd ? (\n <Button\n size=\"lg\"\n variant=\"ghost\"\n className=\"text-kit-fg-2\"\n leftIcon={<IconPlus stroke={1.5} />}\n disabled={locked || (slot.multiple && items.length >= max)}\n onClick={() => addOnly(quickAdd)}\n >\n Add {quickAdd.title}\n </Button>\n ) : catalog ? (\n <SlotPicker\n entries={catalog.entries}\n loading={catalog.loading}\n error={catalog.error}\n note={catalog.note}\n current={slot.multiple ? undefined : items[0]?.componentId}\n label={slot.multiple ? \"Add block\" : items.length ? \"Replace block\" : \"Choose a block\"}\n disabled={locked || (slot.multiple && items.length >= max)}\n onPick={pick}\n />\n ) : null;\n\n return (\n <div className=\"flex min-w-0 flex-col gap-1.5\" data-slot=\"kit-component-slot\">\n {read.unreadable > 0 ? (\n <SlotNote tone=\"warning\">\n {read.unreadable === 1 ? \"One child here isn't a block instance\" : `${read.unreadable} children here aren't block instances`} (blocks written by another editor). This editor\n would drop {read.unreadable === 1 ? \"it\" : \"them\"} on save, so the slot is shown read-only and its value is kept.\n </SlotNote>\n ) : null}\n {read.inherited && items.length === 0 ? <SlotNote>Shows the block’s own content until a block is added here.</SlotNote> : null}\n <div id={id} tabIndex={-1} className=\"min-w-0 outline-none\">\n <RowList\n field={opsField}\n rows={rows}\n readOnly={locked}\n layout=\"list\"\n mode=\"inline\"\n openId={openId}\n onOpen={(r) => setOpenId(openId === r.id ? null : r.id)}\n onCloseInline={() => setOpenId(null)}\n ops={ops}\n renderInline={(r) => {\n const it = r.item as KitSlotItem;\n const title = r.preview.title;\n if (nameOf(it.componentId).missing) return <SlotNote>This component no longer exists, so its props can’t be edited. Replace it or remove it.</SlotNote>;\n if (!SlotChild) return <SlotNote>This editor can’t open {title}’s own props.</SlotNote>;\n return (\n <SlotDepthContext.Provider value={depth + 1}>\n <SlotChild\n componentId={it.componentId}\n title={title}\n overrides={it.overrides && typeof it.overrides === \"object\" ? it.overrides : {}}\n onChange={(o) => setOverrides(r.index, o)}\n readOnly={locked}\n depth={depth + 1}\n />\n </SlotDepthContext.Provider>\n );\n }}\n leading={(r) => (\n <span className=\"flex size-7 shrink-0 items-center justify-center rounded-kit-md border border-kit-line bg-kit-control-bg text-kit-fg-2 shadow-kit-xs\">\n <KitIcon name={r.preview.icon} className=\"size-4\" />\n </span>\n )}\n emptyLabel={slot.multiple ? \"No blocks yet. Add one to start composing.\" : \"No block yet. Choose one to fill this slot.\"}\n addButton={picker ?? <SlotNote>No block library is connected to this editor, so {field.title} can’t be changed here.</SlotNote>}\n />\n </div>\n {slot.multiple ? (\n <span className=\"text-kit-xs text-kit-fg-3\">\n {items.length >= max ? `This slot holds at most ${count(max)}.` : slot.min > 0 ? `Between ${slot.min} and ${count(max)}.` : `Up to ${count(max)}.`}\n {slot.min > 0 && items.length > 0 && items.length <= slot.min ? ` It needs at least ${slot.min}, so none can be removed.` : \"\"}\n </span>\n ) : null}\n </div>\n );\n}\n\n/**\n * The compact block picker (engine/slot.tsx BlockPicker), over the slot catalog: grouped by family, searchable, ↵ adds.\n * A component the server says can't go here is listed disabled with its reason in place of the description.\n */\nexport function SlotPicker({\n entries,\n loading,\n error,\n note,\n current,\n label,\n disabled,\n onPick,\n}: {\n entries: KitSlotEntry[];\n loading?: boolean;\n error?: string;\n note?: string;\n current?: string;\n label: string;\n disabled?: boolean;\n onPick: (componentId: string) => void;\n}) {\n const [open, setOpen] = React.useState(false);\n const [q, setQ] = React.useState(\"\");\n const [active, setActive] = React.useState(0);\n const listId = React.useId();\n const list = entries.filter((b) => !q || `${b.title} ${b.category ?? \"\"} ${b.description ?? \"\"}`.toLowerCase().includes(q.toLowerCase()));\n const cats = Array.from(new Set(list.map((b) => b.category || \"Blocks\")));\n const flat = cats.flatMap((c) => list.filter((b) => (b.category || \"Blocks\") === c));\n const choose = (b: KitSlotEntry | undefined) => {\n if (!b || !b.insertable) return;\n onPick(b.id);\n setOpen(false);\n setQ(\"\");\n };\n const optionId = (i: number) => `${listId}-${i}`;\n return (\n <Popover\n open={open}\n onOpenChange={(o) => {\n setOpen(o);\n setQ(\"\");\n setActive(0);\n }}\n >\n <PopoverTrigger render={<Button size=\"sm\" variant=\"ghost\" className=\"text-kit-fg-2\" leftIcon={<IconPlus stroke={1.5} />} disabled={disabled} />}>{label}</PopoverTrigger>\n <PopoverContent className=\"w-[300px] p-0\" align=\"start\">\n <label className=\"flex h-10 items-center gap-2 border-b border-kit-line px-3 text-kit-fg-3\">\n <IconSearch className=\"size-4 shrink-0\" stroke={1.5} aria-hidden />\n <input\n autoFocus\n value={q}\n onChange={(e) => {\n setQ(e.target.value);\n setActive(0);\n }}\n onKeyDown={(e) => {\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n setActive((a) => (a + 1) % Math.max(1, flat.length));\n } else if (e.key === \"ArrowUp\") {\n e.preventDefault();\n setActive((a) => (a - 1 + flat.length) % Math.max(1, flat.length));\n } else if (e.key === \"Enter\") {\n e.preventDefault();\n choose(flat[active]);\n }\n }}\n placeholder=\"Search blocks\"\n aria-label=\"Search blocks\"\n role=\"combobox\"\n aria-expanded\n aria-controls={listId}\n aria-activedescendant={flat.length ? optionId(Math.min(active, flat.length - 1)) : undefined}\n className=\"h-full min-w-0 flex-1 bg-transparent text-kit-sm text-kit-fg outline-none placeholder:text-kit-fg-3\"\n />\n </label>\n <div id={listId} className=\"max-h-80 overflow-y-auto p-1\" role=\"listbox\" aria-label=\"Blocks\" aria-busy={loading || undefined}>\n {loading && entries.length === 0 ? (\n <p role=\"status\" className=\"px-3 py-6 text-center text-kit-sm text-kit-fg-3\">\n Loading blocks…\n </p>\n ) : null}\n {!loading && !error && flat.length === 0 ? <p className=\"px-3 py-6 text-center text-kit-sm text-kit-fg-3\">{entries.length ? \"No blocks match\" : \"This project has no blocks that can go here yet.\"}</p> : null}\n {error ? (\n <p role=\"alert\" className=\"px-3 py-3 text-kit-xs text-kit-danger-fg\">\n {error}\n </p>\n ) : null}\n {cats.map((c) => (\n <div key={c} role=\"group\" aria-label={c} className=\"pb-1\">\n <div aria-hidden className=\"px-2 pb-1 pt-1.5 text-kit-2xs font-medium text-kit-fg-3\">\n {c}\n </div>\n {list\n .filter((b) => (b.category || \"Blocks\") === c)\n .map((b) => {\n const i = flat.indexOf(b);\n return (\n <div\n key={b.id}\n id={optionId(i)}\n role=\"option\"\n aria-selected={b.id === current}\n aria-disabled={!b.insertable || undefined}\n onMouseEnter={() => setActive(i)}\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => choose(b)}\n className={cn(\"flex w-full items-center gap-2.5 rounded-kit-md p-1.5 text-left\", b.insertable ? \"cursor-pointer\" : \"cursor-not-allowed\", i === active && \"bg-kit-hover\")}\n >\n <span className={cn(\"flex size-8 shrink-0 items-center justify-center rounded-kit-md border border-kit-line bg-kit-surface text-kit-fg-2 shadow-kit-xs\", !b.insertable && \"opacity-50\")}>\n <KitIcon name={b.icon ?? \"box\"} className=\"size-4\" />\n </span>\n <span className=\"min-w-0 flex-1\">\n <span className={cn(\"block truncate text-kit-sm\", b.insertable ? \"text-kit-fg\" : \"text-kit-fg-3\")}>{b.title}</span>\n {!b.insertable && b.reason ? (\n <span className=\"block text-kit-xs text-kit-fg-3\">{b.reason}</span>\n ) : b.description ? (\n <span className=\"block truncate text-kit-xs text-kit-fg-3\">{b.description}</span>\n ) : null}\n </span>\n </div>\n );\n })}\n </div>\n ))}\n </div>\n {note ? <p className=\"border-t border-kit-line px-3 py-2 text-kit-xs text-kit-fg-3\">{note}</p> : null}\n <div data-hint=\"shortcuts\" className=\"border-t border-kit-line px-3 py-1.5 text-kit-2xs text-kit-fg-3\">\n ↵ add · type to search\n </div>\n </PopoverContent>\n </Popover>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { TableControl, TableFullScreenAction } from "./table.js";
|
|
2
2
|
import { ACTIONS, CONTROLS } from "../../engine/kit-field.js";
|
|
3
|
-
//#region src/
|
|
3
|
+
//#region src/controls/table/index.ts
|
|
4
4
|
/**
|
|
5
5
|
* Data table: registers the control and its label-row action (one line each, so lanes merge cleanly).
|
|
6
6
|
* Imported for its side effect by the kit entry; import the parts themselves by path.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/controls/table/index.ts"],"sourcesContent":["/**\n * Data table: registers the control and its label-row action (one line each, so lanes merge cleanly).\n * Imported for its side effect by the kit entry; import the parts themselves by path.\n */\nimport { ACTIONS, CONTROLS } from \"../../engine/kit-field\";\nimport { TableControl, TableFullScreenAction } from \"./table\";\n\nCONTROLS.table = TableControl;\nACTIONS.table = TableFullScreenAction;\n"],"mappings":";;;;;;;AAOA,SAAS,QAAQ;AACjB,QAAQ,QAAQ"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { TABLE_COLUMN_TYPES } from "../../schema/table.js";
|
|
2
|
-
//#region src/
|
|
2
|
+
//#region src/controls/table/prod.ts
|
|
3
3
|
/**
|
|
4
4
|
* The production side of a data table, for the schema adapter (adapters/schema.ts) to call when it reads one:
|
|
5
5
|
*
|
|
@@ -13,12 +13,12 @@ import { TABLE_COLUMN_TYPES } from "../../schema/table.js";
|
|
|
13
13
|
*/
|
|
14
14
|
var isObj = (v) => !!v && typeof v === "object" && !Array.isArray(v);
|
|
15
15
|
var COLUMN_TYPES = new Set(TABLE_COLUMN_TYPES.map((t) => t.value));
|
|
16
|
-
var PHONES = new Set([
|
|
16
|
+
var PHONES = /* @__PURE__ */ new Set([
|
|
17
17
|
"scroll",
|
|
18
18
|
"stack",
|
|
19
19
|
"cards"
|
|
20
20
|
]);
|
|
21
|
-
var JSONLD = new Set([
|
|
21
|
+
var JSONLD = /* @__PURE__ */ new Set([
|
|
22
22
|
"ItemList",
|
|
23
23
|
"Dataset",
|
|
24
24
|
"Offers"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prod.js","names":[],"sources":["../../../src/controls/table/prod.ts"],"sourcesContent":["/**\n * The production side of a data table, for the schema adapter (adapters/schema.ts) to call when it reads one:\n *\n * - a component `table` prop with `config.mode: \"data\"` (BE @bettercms-ai/types component.ts; prop-fields.ts\n * isDataTable) holds ONE TableValue, with the table field's options beside `mode` in its `config`;\n * - a content-model `table` field (BE content-model.ts) holds the same value, its options in `config`.\n *\n * A `table` prop with no mode (or `\"rows\"` / `\"types\"`) is the older array of rows and is NOT this value.\n * Only the option keys the backend defines are read, each only when it has the type the backend reads, so a stray key\n * never turns into a setting the backend would not honour.\n */\nimport { TABLE_COLUMN_TYPES, type TableColumnType, type TableFieldOptions, type TableJsonLdType, type TableResponsive, type TableSettingsOptions } from \"../../schema/table\";\n\nconst isObj = (v: unknown): v is Record<string, unknown> => !!v && typeof v === \"object\" && !Array.isArray(v);\nconst COLUMN_TYPES = new Set<string>(TABLE_COLUMN_TYPES.map((t) => t.value));\nconst PHONES = new Set<string>([\"scroll\", \"stack\", \"cards\"]);\nconst JSONLD = new Set<string>([\"ItemList\", \"Dataset\", \"Offers\"]);\nconst SETTING_FLAGS = [\"headers\", \"totals\", \"highlight\", \"sticky\", \"sort\", \"search\"] as const;\n\n/** BE isDataTable: a `table` prop or sub-field holding one TableValue. */\nexport const isDataTableProp = (p: { type?: unknown; config?: unknown }): boolean => p.type === \"table\" && isObj(p.config) && p.config.mode === \"data\";\n\n/** The field options a data table's `config` carries, as the kit's `FieldSchema.table`. */\nexport function tableOptionsFromConfig(config: unknown): TableFieldOptions {\n if (!isObj(config)) return {};\n const o: TableFieldOptions = {};\n const strs = (v: unknown, ok: Set<string>) => (Array.isArray(v) ? v.filter((x): x is string => typeof x === \"string\" && ok.has(x)) : undefined);\n const columnTypes = strs(config.columnTypes, COLUMN_TYPES);\n if (columnTypes) o.columnTypes = columnTypes as TableColumnType[];\n for (const k of [\"lockColumns\", \"requireCaption\", \"allowGroups\", \"allowFootnotes\", \"allowNote\"] as const) if (typeof config[k] === \"boolean\") o[k] = config[k] as boolean;\n for (const k of [\"minRows\", \"maxRows\", \"maxColumns\"] as const) {\n const n = config[k];\n if (typeof n === \"number\" && Number.isInteger(n) && n >= 0) o[k] = n;\n }\n if (isObj(config.settings)) {\n const s: TableSettingsOptions = {};\n for (const k of SETTING_FLAGS) if (typeof config.settings[k] === \"boolean\") s[k] = config.settings[k] as boolean;\n const phones = strs(config.settings.phones, PHONES);\n if (phones) s.phones = phones as TableResponsive[];\n o.settings = s;\n }\n const jsonLd = strs(config.jsonLd, JSONLD);\n if (jsonLd) o.jsonLd = jsonLd as TableJsonLdType[];\n return o;\n}\n\n/** The `config` a data-table prop is written with (the inverse of tableOptionsFromConfig). */\nexport function tableConfigFromOptions(o: TableFieldOptions | undefined): Record<string, unknown> {\n return { mode: \"data\", ...(o ? JSON.parse(JSON.stringify(o)) : {}) };\n}\n"],"mappings":";;;;;;;;;;;;;AAaA,IAAM,SAAS,MAA6C,CAAC,CAAC,KAAK,OAAO,MAAM,YAAY,CAAC,MAAM,QAAQ,CAAC;AAC5G,IAAM,eAAe,IAAI,IAAY,mBAAmB,KAAK,MAAM,EAAE,KAAK,CAAC;AAC3E,IAAM,yBAAS,IAAI,IAAY;CAAC;CAAU;CAAS;AAAO,CAAC;AAC3D,IAAM,yBAAS,IAAI,IAAY;CAAC;CAAY;CAAW;AAAQ,CAAC;AAChE,IAAM,gBAAgB;CAAC;CAAW;CAAU;CAAa;CAAU;CAAQ;AAAQ;;AAGnF,IAAa,mBAAmB,MAAqD,EAAE,SAAS,WAAW,MAAM,EAAE,MAAM,KAAK,EAAE,OAAO,SAAS;;AAGhJ,SAAgB,uBAAuB,QAAoC;CACzE,IAAI,CAAC,MAAM,MAAM,GAAG,OAAO,CAAC;CAC5B,MAAM,IAAuB,CAAC;CAC9B,MAAM,QAAQ,GAAY,OAAqB,MAAM,QAAQ,CAAC,IAAI,EAAE,QAAQ,MAAmB,OAAO,MAAM,YAAY,GAAG,IAAI,CAAC,CAAC,IAAI,KAAA;CACrI,MAAM,cAAc,KAAK,OAAO,aAAa,YAAY;CACzD,IAAI,aAAa,EAAE,cAAc;CACjC,KAAK,MAAM,KAAK;EAAC;EAAe;EAAkB;EAAe;EAAkB;CAAW,GAAY,IAAI,OAAO,OAAO,OAAO,WAAW,EAAE,KAAK,OAAO;CAC5J,KAAK,MAAM,KAAK;EAAC;EAAW;EAAW;CAAY,GAAY;EAC7D,MAAM,IAAI,OAAO;EACjB,IAAI,OAAO,MAAM,YAAY,OAAO,UAAU,CAAC,KAAK,KAAK,GAAG,EAAE,KAAK;CACrE;CACA,IAAI,MAAM,OAAO,QAAQ,GAAG;EAC1B,MAAM,IAA0B,CAAC;EACjC,KAAK,MAAM,KAAK,eAAe,IAAI,OAAO,OAAO,SAAS,OAAO,WAAW,EAAE,KAAK,OAAO,SAAS;EACnG,MAAM,SAAS,KAAK,OAAO,SAAS,QAAQ,MAAM;EAClD,IAAI,QAAQ,EAAE,SAAS;EACvB,EAAE,WAAW;CACf;CACA,MAAM,SAAS,KAAK,OAAO,QAAQ,MAAM;CACzC,IAAI,QAAQ,EAAE,SAAS;CACvB,OAAO;AACT;;AAGA,SAAgB,uBAAuB,GAA2D;CAChG,OAAO;EAAE,MAAM;EAAQ,GAAI,IAAI,KAAK,MAAM,KAAK,UAAU,CAAC,CAAC,IAAI,CAAC;CAAG;AACrE"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useKitServices } from "../../context.js";
|
|
2
2
|
import * as React from "react";
|
|
3
|
-
//#region src/
|
|
3
|
+
//#region src/controls/table/refs.ts
|
|
4
4
|
/**
|
|
5
5
|
* Reference cells: what a `reference` column's cell may point at, found through the HOST (the kit never fetches).
|
|
6
6
|
*
|
|
@@ -16,6 +16,17 @@ import * as React from "react";
|
|
|
16
16
|
*
|
|
17
17
|
* Absent → the picker says, in words, that this view cannot search pages or entries (stored cells still show).
|
|
18
18
|
*/
|
|
19
|
+
/**
|
|
20
|
+
* The POST /content/reference-options `config` bodies one column's `refTo` needs (the host sends each and merges the
|
|
21
|
+
* answers): pages through `targets: ["page"]`, each collection through `contentModelId`.
|
|
22
|
+
*/
|
|
23
|
+
function tableRefConfigs(refTo) {
|
|
24
|
+
const to = refTo?.length ? refTo : ["page"];
|
|
25
|
+
const out = [];
|
|
26
|
+
if (to.includes("page")) out.push({ targets: ["page"] });
|
|
27
|
+
for (const id of to) if (id !== "page" && id) out.push({ contentModelId: id });
|
|
28
|
+
return out;
|
|
29
|
+
}
|
|
19
30
|
/** The words a stored reference shows: what a read resolved onto it, its stored label, else its id. */
|
|
20
31
|
function refLabel(r) {
|
|
21
32
|
return r.resolved?.title || r.label || r.ref;
|
|
@@ -63,6 +74,6 @@ function useRefSearch(open, refTo, q) {
|
|
|
63
74
|
return answer?.ask === ask ? answer.state : { status: "loading" };
|
|
64
75
|
}
|
|
65
76
|
//#endregion
|
|
66
|
-
export { refLabel, useRefSearch };
|
|
77
|
+
export { refLabel, tableRefConfigs, useRefSearch };
|
|
67
78
|
|
|
68
79
|
//# sourceMappingURL=refs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"refs.js","names":[],"sources":["../../../src/controls/table/refs.ts"],"sourcesContent":["/**\n * Reference cells: what a `reference` column's cell may point at, found through the HOST (the kit never fetches).\n *\n * A reference cell stores `{ ref, label?, href? }` (BE table-value.ts TableRef): the id of a page or an entry. Its column's\n * `refTo` narrows the targets (\"page\", and collections by content-model id or slug); with no `refTo` V2 offers pages. The\n * backend checks the id exists and is a kind `refTo` allows (`reference_target_not_allowed`), so the picker only lists\n * what the same rule accepts: the host answers through POST /content/reference-options with the configs\n * `tableRefConfigs(refTo)` names.\n *\n * Host contract (a KitServices key, provided by src/features/dock-v2 and the /style-guide/kit sandbox):\n *\n * tableRefSearch(req) → Promise<TableRefOption[]>\n *\n * Absent → the picker says, in words, that this view cannot search pages or entries (stored cells still show).\n */\nimport * as React from \"react\";\nimport { useKitServices } from \"../../context\";\nimport type { TableRef } from \"../../schema/table\";\n\nexport interface TableRefOption {\n /** page or entry id: what the cell stores as `ref` */\n id: string;\n title: string;\n /** \"Blog post · my-slug\", \"Page\" */\n subtitle?: string;\n /** the public path, stored as the cell's `href` so the published table links without a read */\n href?: string;\n}\nexport interface TableRefSearchRequest {\n /** the column's `refTo` (null = pages, as V2) */\n refTo: string[] | null;\n q: string;\n signal: AbortSignal;\n}\nexport type TableRefSearch = (req: TableRefSearchRequest) => Promise<TableRefOption[]>;\nexport interface TableKitServices {\n tableRefSearch?: TableRefSearch;\n}\ndeclare module \"../../context\" {\n interface KitServices {\n /** Search pages and entries for a table's reference cells (see above). Absent → the picker names why it can't. */\n tableRefSearch?: TableRefSearch;\n }\n}\n\n/**\n * The POST /content/reference-options `config` bodies one column's `refTo` needs (the host sends each and merges the\n * answers): pages through `targets: [\"page\"]`, each collection through `contentModelId`.\n */\nexport function tableRefConfigs(refTo: string[] | null | undefined): Record<string, unknown>[] {\n const to = refTo?.length ? refTo : [\"page\"];\n const out: Record<string, unknown>[] = [];\n if (to.includes(\"page\")) out.push({ targets: [\"page\"] });\n for (const id of to) if (id !== \"page\" && id) out.push({ contentModelId: id });\n return out;\n}\n\n/** The words a stored reference shows: what a read resolved onto it, its stored label, else its id. */\nexport function refLabel(r: TableRef & { resolved?: { title?: string } }): string {\n return r.resolved?.title || r.label || r.ref;\n}\n\nexport type RefSearchState =\n | { status: \"unavailable\" }\n | { status: \"loading\" }\n | { status: \"ready\"; options: TableRefOption[] }\n | { status: \"error\"; message: string };\n\n/** Search while `open`, 200ms after the last keystroke; a newer query aborts the older one. */\nexport function useRefSearch(open: boolean, refTo: string[] | null, q: string): RefSearchState {\n const search = useKitServices().tableRefSearch;\n const key = refTo?.join(\",\") ?? \"\";\n const ask = `${key}\\u0000${q.trim()}`;\n // the answer, tagged with the question it answers: a different question reads as loading until its own answer lands\n const [answer, setAnswer] = React.useState<{ ask: string; state: RefSearchState } | null>(null);\n React.useEffect(() => {\n if (!search || !open) return;\n const ctl = new AbortController();\n const t = window.setTimeout(() => {\n search({ refTo: key ? key.split(\",\") : null, q: q.trim(), signal: ctl.signal }).then(\n (options) => !ctl.signal.aborted && setAnswer({ ask, state: { status: \"ready\", options } }),\n (e: unknown) => !ctl.signal.aborted && setAnswer({ ask, state: { status: \"error\", message: e instanceof Error && e.message ? e.message : \"The search did not answer.\" } }),\n );\n }, 200);\n return () => {\n ctl.abort();\n window.clearTimeout(t);\n };\n }, [search, open, key, q, ask]);\n if (!search) return { status: \"unavailable\" };\n return answer?.ask === ask ? answer.state : { status: \"loading\" };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAiDA,SAAgB,gBAAgB,OAA+D;CAC7F,MAAM,KAAK,OAAO,SAAS,QAAQ,CAAC,MAAM;CAC1C,MAAM,MAAiC,CAAC;CACxC,IAAI,GAAG,SAAS,MAAM,GAAG,IAAI,KAAK,EAAE,SAAS,CAAC,MAAM,EAAE,CAAC;CACvD,KAAK,MAAM,MAAM,IAAI,IAAI,OAAO,UAAU,IAAI,IAAI,KAAK,EAAE,gBAAgB,GAAG,CAAC;CAC7E,OAAO;AACT;;AAGA,SAAgB,SAAS,GAAyD;CAChF,OAAO,EAAE,UAAU,SAAS,EAAE,SAAS,EAAE;AAC3C;;AASA,SAAgB,aAAa,MAAe,OAAwB,GAA2B;CAC7F,MAAM,SAAS,eAAe,CAAC,CAAC;CAChC,MAAM,MAAM,OAAO,KAAK,GAAG,KAAK;CAChC,MAAM,MAAM,GAAG,IAAI,QAAQ,EAAE,KAAK;CAElC,MAAM,CAAC,QAAQ,aAAa,MAAM,SAAwD,IAAI;CAC9F,MAAM,gBAAgB;EACpB,IAAI,CAAC,UAAU,CAAC,MAAM;EACtB,MAAM,MAAM,IAAI,gBAAgB;EAChC,MAAM,IAAI,OAAO,iBAAiB;GAChC,OAAO;IAAE,OAAO,MAAM,IAAI,MAAM,GAAG,IAAI;IAAM,GAAG,EAAE,KAAK;IAAG,QAAQ,IAAI;GAAO,CAAC,CAAC,CAAC,MAC7E,YAAY,CAAC,IAAI,OAAO,WAAW,UAAU;IAAE;IAAK,OAAO;KAAE,QAAQ;KAAS;IAAQ;GAAE,CAAC,IACzF,MAAe,CAAC,IAAI,OAAO,WAAW,UAAU;IAAE;IAAK,OAAO;KAAE,QAAQ;KAAS,SAAS,aAAa,SAAS,EAAE,UAAU,EAAE,UAAU;IAA6B;GAAE,CAAC,CAC3K;EACF,GAAG,GAAG;EACN,aAAa;GACX,IAAI,MAAM;GACV,OAAO,aAAa,CAAC;EACvB;CACF,GAAG;EAAC;EAAQ;EAAM;EAAK;EAAG;CAAG,CAAC;CAC9B,IAAI,CAAC,QAAQ,OAAO,EAAE,QAAQ,cAAc;CAC5C,OAAO,QAAQ,QAAQ,MAAM,OAAO,QAAQ,EAAE,QAAQ,UAAU;AAClE"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { TABLE_COLUMN_TYPES, isTableValue } from "../../schema/table.js";
|
|
2
|
-
//#region src/
|
|
2
|
+
//#region src/controls/table/stored.ts
|
|
3
3
|
/**
|
|
4
4
|
* The table value as the backend stores it (BE `packages/types/src/table-value.ts`, a `table` field or a `table` prop with
|
|
5
5
|
* `config.mode: "data"`). The editor works on `normalizeTable(value)`, which fills keys the stored value may not have
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stored.js","names":[],"sources":["../../../src/controls/table/stored.ts"],"sourcesContent":["/**\n * The table value as the backend stores it (BE `packages/types/src/table-value.ts`, a `table` field or a `table` prop with\n * `config.mode: \"data\"`). The editor works on `normalizeTable(value)`, which fills keys the stored value may not have\n * (`id`, empty `columnGroups` / `rowGroups` / `footnotes`). Writing those back would change a value nobody edited, so\n * `storedTable` hands back exactly what the person changed:\n *\n * - keys normalize invented (an `id`, an empty list the stored value did not carry) are dropped again;\n * - `undefined` keys (a switch turned off: `highlight`, `sortable`, `notes`…) are removed, as JSON would remove them;\n * - a reference cell's `resolved` (what a read writes onto it) is never written back (BE normalizeTableValue drops it too).\n *\n * The backend refuses any key it does not know (`table_value_invalid`), so nothing else is added here.\n */\nimport { TABLE_COLUMN_TYPES, isTableValue, type TableValue } from \"../../schema/table\";\n\nconst LISTS = [\"columnGroups\", \"rowGroups\", \"footnotes\"] as const;\n\n/** A JSON copy without `undefined` keys (what the save would send), and without a reference cell's read-only `resolved`. */\nfunction plain<T>(v: T): T {\n return JSON.parse(JSON.stringify(v, (k, x) => (k === \"resolved\" ? undefined : x))) as T;\n}\n\n/** `next` as the backend stores it, given the value it was loaded from (`prev`; undefined for a new table). */\nexport function storedTable(next: TableValue, prev: unknown): TableValue {\n const out = plain(next) as TableValue & Record<string, unknown>;\n const was = isTableValue(prev) ? (prev as unknown as Record<string, unknown>) : null;\n if (was) {\n if (!(\"id\" in was) && out.id !== undefined) delete out.id;\n for (const k of LISTS) if (!(k in was) && Array.isArray(out[k]) && (out[k] as unknown[]).length === 0) delete out[k];\n // normalize reads a column type it does not know (or none) as \"text\": unless the person picked another type, the\n // stored one is written back as it was\n const prevCols = new Map((Array.isArray(was.columns) ? was.columns : []).filter((c): c is Record<string, unknown> => !!c && typeof c === \"object\").map((c) => [c._key, c] as const));\n for (const col of out.columns as unknown as Record<string, unknown>[]) {\n const p = prevCols.get(col._key);\n if (!p || col.type !== \"text\" || TABLE_COLUMN_TYPES.some((t) => t.value === p.type)) continue;\n if (p.type === undefined) delete col.type;\n else col.type = p.type;\n }\n } else {\n for (const k of LISTS) if (Array.isArray(out[k]) && (out[k] as unknown[]).length === 0) delete out[k];\n }\n return out;\n}\n"],"mappings":";;;;;;;;;;;;;;AAcA,IAAM,QAAQ;CAAC;CAAgB;CAAa;AAAW;;AAGvD,SAAS,MAAS,GAAS;CACzB,OAAO,KAAK,MAAM,KAAK,UAAU,IAAI,GAAG,MAAO,MAAM,aAAa,KAAA,IAAY,CAAE,CAAC;AACnF;;AAGA,SAAgB,YAAY,MAAkB,MAA2B;CACvE,MAAM,MAAM,MAAM,IAAI;CACtB,MAAM,MAAM,aAAa,IAAI,IAAK,OAA8C;CAChF,IAAI,KAAK;EACP,IAAI,EAAE,QAAQ,QAAQ,IAAI,OAAO,KAAA,GAAW,OAAO,IAAI;EACvD,KAAK,MAAM,KAAK,OAAO,IAAI,EAAE,KAAK,QAAQ,MAAM,QAAQ,IAAI,EAAE,KAAM,IAAI,EAAE,CAAe,WAAW,GAAG,OAAO,IAAI;EAGlH,MAAM,WAAW,IAAI,KAAK,MAAM,QAAQ,IAAI,OAAO,IAAI,IAAI,UAAU,CAAC,EAAA,CAAG,QAAQ,MAAoC,CAAC,CAAC,KAAK,OAAO,MAAM,QAAQ,CAAC,CAAC,KAAK,MAAM,CAAC,EAAE,MAAM,CAAC,CAAU,CAAC;EACnL,KAAK,MAAM,OAAO,IAAI,SAAiD;GACrE,MAAM,IAAI,SAAS,IAAI,IAAI,IAAI;GAC/B,IAAI,CAAC,KAAK,IAAI,SAAS,UAAU,mBAAmB,MAAM,MAAM,EAAE,UAAU,EAAE,IAAI,GAAG;GACrF,IAAI,EAAE,SAAS,KAAA,GAAW,OAAO,IAAI;QAChC,IAAI,OAAO,EAAE;EACpB;CACF,OACE,KAAK,MAAM,KAAK,OAAO,IAAI,MAAM,QAAQ,IAAI,EAAE,KAAM,IAAI,EAAE,CAAe,WAAW,GAAG,OAAO,IAAI;CAErG,OAAO;AACT"}
|