@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
|
@@ -5,9 +5,9 @@ import { Popover, PopoverContent, PopoverTrigger } from "../../ui/overlay.js";
|
|
|
5
5
|
import { Input } from "../../ui/input.js";
|
|
6
6
|
import { Select } from "../../ui/select.js";
|
|
7
7
|
import * as React from "react";
|
|
8
|
-
import { IconLink } from "@tabler/icons-react";
|
|
9
8
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
10
|
-
|
|
9
|
+
import { IconLink } from "@tabler/icons-react";
|
|
10
|
+
//#region src/controls/table/table-link.tsx
|
|
11
11
|
/**
|
|
12
12
|
* A link cell's address (BE TableLink `{ label, href, newTab?, rel? }`): the address, "Open in a new tab" and the
|
|
13
13
|
* relationship search engines read. V2 opened its global link panel (controls/link.tsx LinkPopoverBody); that panel is the
|
|
@@ -175,6 +175,6 @@ function LinkAddressButton({ link, onSave, readOnly, className }) {
|
|
|
175
175
|
});
|
|
176
176
|
}
|
|
177
177
|
//#endregion
|
|
178
|
-
export { LinkAddressButton, isScriptHref, tableLink };
|
|
178
|
+
export { LINK_RELS, LinkAddressButton, LinkAddressEditor, hrefProblem, isScriptHref, tableLink };
|
|
179
179
|
|
|
180
180
|
//# sourceMappingURL=table-link.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"table-link.js","names":[],"sources":["../../../src/controls/table/table-link.tsx"],"sourcesContent":["/**\n * A link cell's address (BE TableLink `{ label, href, newTab?, rel? }`): the address, \"Open in a new tab\" and the\n * relationship search engines read. V2 opened its global link panel (controls/link.tsx LinkPopoverBody); that panel is the\n * link lane's, so the table carries this one, writing the same four keys the backend takes and nothing else.\n *\n * Refusals are named before anything is written: a script address (javascript:, data:, vbscript:) is refused here\n * exactly as the backend refuses it (`link_value_invalid`).\n */\nimport * as React from \"react\";\nimport { IconLink } from \"@tabler/icons-react\";\nimport { cn } from \"../../lib/cn\";\nimport { Button } from \"../../ui/button\";\nimport { Input } from \"../../ui/input\";\nimport { Switch } from \"../../ui/controls\";\nimport { Select } from \"../../ui/select\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"../../ui/overlay\";\nimport type { TableLink } from \"../../schema/table\";\n\nexport const LINK_RELS: { value: NonNullable<TableLink[\"rel\"]>; label: string }[] = [\n { value: \"follow\", label: \"Follow (default)\" },\n { value: \"nofollow\", label: \"Don't vouch for it (nofollow)\" },\n { value: \"sponsored\", label: \"Paid or sponsored\" },\n { value: \"ugc\", label: \"Written by visitors\" },\n];\n\n/** BE link-value.ts isScriptHref: what no link may hold. */\nexport const isScriptHref = (href: string) => /^\\s*(javascript|data|vbscript):/i.test(href.replace(/[\\p{Cc}\\s]+/gu, \"\"));\nexport const hrefProblem = (href: string) => (isScriptHref(href) ? \"Script links (javascript:, data:, vbscript:) aren't allowed.\" : null);\n\n/** The stored link with only the keys it uses: `newTab` only when on, `rel` only when not the default. */\nexport function tableLink(label: string, href: string, newTab?: boolean, rel?: TableLink[\"rel\"]): TableLink {\n return { label, href, ...(newTab ? { newTab: true } : {}), ...(rel && rel !== \"follow\" ? { rel } : {}) };\n}\n\n/** Address + options, as one popover body (the spreadsheet's link button) or inline (a row's link cell). */\nexport function LinkAddressEditor({\n link,\n onSave,\n onCancel,\n autoFocus,\n}: {\n link: TableLink;\n onSave: (next: TableLink) => void;\n onCancel?: () => void;\n autoFocus?: boolean;\n}) {\n const [href, setHref] = React.useState(link.href);\n const [newTab, setNewTab] = React.useState(!!link.newTab);\n const [rel, setRel] = React.useState<NonNullable<TableLink[\"rel\"]>>(link.rel ?? \"follow\");\n const id = React.useId();\n const problem = hrefProblem(href);\n const save = () => !problem && onSave(tableLink(link.label, href.trim(), newTab, rel));\n return (\n <div className=\"flex flex-col gap-3\">\n <div className=\"flex flex-col gap-1.5\">\n <label htmlFor={`${id}-href`} className=\"text-kit-xs font-medium text-kit-fg-2\">Address</label>\n <Input\n id={`${id}-href`}\n size=\"sm\"\n autoFocus={autoFocus}\n value={href}\n placeholder=\"https://… or /pricing\"\n aria-invalid={problem ? true : undefined}\n aria-describedby={problem ? `${id}-problem` : undefined}\n onChange={(e) => setHref(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") { e.preventDefault(); save(); }\n }}\n />\n {problem ? <p id={`${id}-problem`} role=\"alert\" className=\"text-kit-xs text-kit-danger-fg\">{problem}</p> : null}\n </div>\n <div className=\"flex min-h-8 items-center justify-between gap-2 text-kit-sm text-kit-fg-2\">\n <span aria-hidden>Open in a new tab</span>\n <Switch size=\"sm\" checked={newTab} onCheckedChange={setNewTab} aria-label=\"Open in a new tab\" />\n </div>\n <div className=\"flex flex-col gap-1.5\">\n <span id={`${id}-rel`} className=\"text-kit-xs font-medium text-kit-fg-2\">Search engines</span>\n <Select aria-label=\"Search engines\" size=\"sm\" value={rel} onValueChange={(v) => setRel(v as typeof rel)} options={LINK_RELS} />\n </div>\n <div className=\"flex items-center justify-end gap-1.5\">\n {link.href ? (\n <Button size=\"sm\" variant=\"ghost\" className=\"mr-auto text-kit-fg-2\" onClick={() => onSave(tableLink(link.label, \"\"))}>\n Remove link\n </Button>\n ) : null}\n {onCancel ? (\n <Button size=\"sm\" variant=\"ghost\" onClick={onCancel}>\n Cancel\n </Button>\n ) : null}\n <Button size=\"sm\" variant=\"primary\" disabled={!!problem} onClick={save}>\n Save\n </Button>\n </div>\n </div>\n );\n}\n\n/** The small link button beside a link cell's words: opens the address editor. */\nexport function LinkAddressButton({ link, onSave, readOnly, className }: { link: TableLink; onSave: (l: TableLink) => void; readOnly?: boolean; className?: string }) {\n const [open, setOpen] = React.useState(false);\n if (readOnly && !link.href) return null;\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger\n disabled={readOnly}\n tabIndex={-1}\n aria-label={link.href ? `Link: ${link.href}` : \"Add a link address\"}\n className={cn(\n \"flex size-5 shrink-0 items-center justify-center rounded-kit-sm text-kit-fg-4 outline-none hover:bg-kit-hover hover:text-kit-fg\",\n link.href && \"text-kit-fg-2\",\n className,\n )}\n >\n <IconLink className=\"size-3.5\" stroke={1.75} />\n </PopoverTrigger>\n <PopoverContent align=\"end\" className=\"w-[320px] p-3\">\n <LinkAddressEditor\n link={link}\n autoFocus\n onCancel={() => setOpen(false)}\n onSave={(l) => {\n onSave(l);\n setOpen(false);\n }}\n />\n </PopoverContent>\n </Popover>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { pathKey } from "../../lib/path.js";
|
|
2
|
-
import { resolveFieldAccess, useForm, useKitEnv } from "../../context.js";
|
|
3
1
|
import { GENERAL_TABLE, emptyTable, isTableValue, normalizeTable } from "../../schema/table.js";
|
|
2
|
+
import { resolveFieldAccess, useForm, useKitEnv } from "../../context.js";
|
|
3
|
+
import { pathKey } from "../../lib/path.js";
|
|
4
4
|
import { TableEditor, TableFullScreenButton, TableItemEditor } from "./table-editor.js";
|
|
5
5
|
import { storedTable } from "./stored.js";
|
|
6
6
|
import * as React from "react";
|
|
7
7
|
import { jsx } from "react/jsx-runtime";
|
|
8
|
-
//#region src/
|
|
8
|
+
//#region src/controls/table/table.tsx
|
|
9
9
|
/**
|
|
10
10
|
* TABLE control (CPO D42, D50, D52; port of V2 kit/controls/table.tsx): the `table` field type (a content-model `table`
|
|
11
11
|
* field, or a component `table` prop with `config.mode: "data"`) edits like any nested array, with no container of its
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"table.js","names":[],"sources":["../../../src/controls/table/table.tsx"],"sourcesContent":["/**\n * TABLE control (CPO D42, D50, D52; port of V2 kit/controls/table.tsx): the `table` field type (a content-model `table`\n * field, or a component `table` prop with `config.mode: \"data\"`) edits like any nested array, with no container of its\n * own: Title, Columns, Rows (groups live in the row list), Note under the table, and a collapsed Table settings that\n * offers only what `field.table.settings` allows (no `table` options = a general table, everything offered). A row or a\n * column drills through the form's own navigation (TableFrame), so the breadcrumb and frame header are the ones every\n * FAQ or feature item uses. The ⤢ button in the field's label row (TableFullScreenAction) opens the spreadsheet in the\n * expanded-editor modal (D49).\n *\n * Value: `TableValue` (schema/table.ts), written in the exact shape the backend stores (stored.ts): keys the editor\n * fills in for itself are never written back unless the person changed them.\n */\nimport * as React from \"react\";\nimport { resolveFieldAccess, useForm, useKitEnv } from \"../../context\";\nimport type { Frame } from \"../../lib/frames\";\nimport { pathKey } from \"../../lib/path\";\nimport type { FieldPath } from \"../../schema/types\";\nimport { GENERAL_TABLE, emptyTable, isTableValue, normalizeTable, type TableValue } from \"../../schema/table\";\nimport type { ControlProps } from \"../../types\";\nimport { TableEditor, TableFullScreenButton, TableItemEditor } from \"./table-editor\";\nimport { storedTable } from \"./stored\";\n\n/* Which table field has its spreadsheet open (the label-row button and the control share it). */\nlet fullKey: string | null = null;\nconst subs = new Set<() => void>();\nconst setFullKey = (k: string | null) => {\n fullKey = k;\n subs.forEach((f) => f());\n};\nconst subscribe = (f: () => void) => (subs.add(f), () => void subs.delete(f));\nconst useFullOpen = (k: string) => React.useSyncExternalStore(subscribe, () => fullKey === k, () => false);\nconst fullKeyOf = (docId: string, path: FieldPath) => `${docId}:${pathKey(path)}`;\n\n/** Label-row action of a table field (KitField ACTIONS.table): the one way into the full-screen spreadsheet (D49). */\nexport function TableFullScreenAction({ path }: Pick<ControlProps, \"path\">) {\n const env = useKitEnv();\n return <TableFullScreenButton className=\"-my-1\" onOpen={() => setFullKey(fullKeyOf(env.docId, path))} />;\n}\n\nexport function TableControl({ field, value, onChange, readOnly, path }: ControlProps) {\n const env = useKitEnv();\n const form = useForm();\n const t = React.useMemo(() => (isTableValue(value) ? normalizeTable(value) : null), [value]);\n // no value yet: the field's default table, else an empty 3 × 2 one (nothing is written until the person edits it)\n const fallback = React.useMemo(() => (isTableValue(field.initialValue) ? normalizeTable(field.initialValue) : emptyTable()), [field.initialValue]);\n const key = fullKeyOf(env.docId, path);\n const full = useFullOpen(key);\n // the spreadsheet belongs to this mount: a dock closed with it open must not reopen it on the next visit\n React.useEffect(() => () => void (fullKey === key && setFullKey(null)), [key]);\n const host = React.useRef<HTMLDivElement>(null);\n const nav = React.useMemo(\n () => (form?.canNavigate ? { id: key, basePath: path, open: (kind: \"rows\" | \"columns\", i: number) => form.navigate([...path, kind, i]) } : undefined),\n [form, key, path],\n );\n return (\n <div ref={host} className=\"min-w-0\" data-kit-control=\"table\">\n <TableEditor\n value={t ?? fallback}\n onChange={(next: TableValue) => onChange(storedTable(next, value))}\n readOnly={readOnly}\n options={field.table ?? GENERAL_TABLE}\n developer={env.can(\"schema.manage\")}\n label={field.title}\n parentTitle={env.docTitle}\n nav={nav}\n fullScreen={{\n open: full,\n onOpenChange: (o) => setFullKey(o ? key : null),\n returnFocus: () => host.current?.closest(\"[data-field-key]\")?.querySelector<HTMLElement>('button[aria-label=\"Edit in full screen\"]') ?? null,\n }}\n />\n </div>\n );\n}\n\n/** The body of a drilled table row or column frame (FrameView draws the standard header above it): FrameSlots.TableFrame. */\nexport function TableFrame({ frame }: { frame: Frame }) {\n const form = useForm()!;\n const env = useKitEnv();\n const it = frame.item!;\n const field = frame.field!;\n const tablePath = it.arrayPath.slice(0, -1);\n const raw = form.getAt(tablePath);\n const readOnly = resolveFieldAccess(field, env).readOnly;\n return (\n <TableItemEditor\n kind={frame.kind === \"tableRow\" ? \"row\" : \"column\"}\n index={it.index}\n value={normalizeTable(raw)}\n onChange={(next) => form.setAt(tablePath, storedTable(next, raw))}\n options={field.table ?? GENERAL_TABLE}\n developer={env.can(\"schema.manage\")}\n readOnly={readOnly}\n />\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAuBA,IAAI,UAAyB;AAC7B,IAAM,uBAAO,IAAI,IAAgB;AACjC,IAAM,cAAc,MAAqB;CACvC,UAAU;CACV,KAAK,SAAS,MAAM,EAAE,CAAC;AACzB;AACA,IAAM,aAAa,OAAmB,KAAK,IAAI,CAAC,SAAS,KAAK,KAAK,OAAO,CAAC;AAC3E,IAAM,eAAe,MAAc,MAAM,qBAAqB,iBAAiB,YAAY,SAAS,KAAK;AACzG,IAAM,aAAa,OAAe,SAAoB,GAAG,MAAM,GAAG,QAAQ,IAAI;;AAG9E,SAAgB,sBAAsB,EAAE,QAAoC;CAC1E,MAAM,MAAM,UAAU;CACtB,OAAO,oBAAC,uBAAD;EAAuB,WAAU;EAAQ,cAAc,WAAW,UAAU,IAAI,OAAO,IAAI,CAAC;CAAI,CAAA;AACzG;AAEA,SAAgB,aAAa,EAAE,OAAO,OAAO,UAAU,UAAU,QAAsB;CACrF,MAAM,MAAM,UAAU;CACtB,MAAM,OAAO,QAAQ;CACrB,MAAM,IAAI,MAAM,cAAe,aAAa,KAAK,IAAI,eAAe,KAAK,IAAI,MAAO,CAAC,KAAK,CAAC;CAE3F,MAAM,WAAW,MAAM,cAAe,aAAa,MAAM,YAAY,IAAI,eAAe,MAAM,YAAY,IAAI,WAAW,GAAI,CAAC,MAAM,YAAY,CAAC;CACjJ,MAAM,MAAM,UAAU,IAAI,OAAO,IAAI;CACrC,MAAM,OAAO,YAAY,GAAG;CAE5B,MAAM,sBAAsB,MAAM,YAAY,OAAO,WAAW,IAAI,IAAI,CAAC,GAAG,CAAC;CAC7E,MAAM,OAAO,MAAM,OAAuB,IAAI;CAC9C,MAAM,MAAM,MAAM,cACT,MAAM,cAAc;EAAE,IAAI;EAAK,UAAU;EAAM,OAAO,MAA0B,MAAc,KAAK,SAAS;GAAC,GAAG;GAAM;GAAM;EAAC,CAAC;CAAE,IAAI,KAAA,GAC3I;EAAC;EAAM;EAAK;CAAI,CAClB;CACA,OACE,oBAAC,OAAD;EAAK,KAAK;EAAM,WAAU;EAAU,oBAAiB;EACnD,UAAA,oBAAC,aAAD;GACE,OAAO,KAAK;GACZ,WAAW,SAAqB,SAAS,YAAY,MAAM,KAAK,CAAC;GACvD;GACV,SAAS,MAAM,SAAS;GACxB,WAAW,IAAI,IAAI,eAAe;GAClC,OAAO,MAAM;GACb,aAAa,IAAI;GACZ;GACL,YAAY;IACV,MAAM;IACN,eAAe,MAAM,WAAW,IAAI,MAAM,IAAI;IAC9C,mBAAmB,KAAK,SAAS,QAAQ,kBAAkB,CAAC,EAAE,cAA2B,4CAA0C,KAAK;GAC1I;EACD,CAAA;CACE,CAAA;AAET;;AAGA,SAAgB,WAAW,EAAE,SAA2B;CACtD,MAAM,OAAO,QAAQ;CACrB,MAAM,MAAM,UAAU;CACtB,MAAM,KAAK,MAAM;CACjB,MAAM,QAAQ,MAAM;CACpB,MAAM,YAAY,GAAG,UAAU,MAAM,GAAG,EAAE;CAC1C,MAAM,MAAM,KAAK,MAAM,SAAS;CAChC,MAAM,WAAW,mBAAmB,OAAO,GAAG,CAAC,CAAC;CAChD,OACE,oBAAC,iBAAD;EACE,MAAM,MAAM,SAAS,aAAa,QAAQ;EAC1C,OAAO,GAAG;EACV,OAAO,eAAe,GAAG;EACzB,WAAW,SAAS,KAAK,MAAM,WAAW,YAAY,MAAM,GAAG,CAAC;EAChE,SAAS,MAAM,SAAS;EACxB,WAAW,IAAI,IAAI,eAAe;EACxB;CACX,CAAA;AAEL"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ControlProps } from "../types";
|
|
2
2
|
export declare const str: (v: unknown) => string;
|
|
3
|
-
/** border-only focus (no halo) for text entry
|
|
4
|
-
export declare const TEXT_FOCUS = "focus:shadow-none focus-visible:shadow-none
|
|
3
|
+
/** border-only focus (no halo) for text entry */
|
|
4
|
+
export declare const TEXT_FOCUS = "focus:shadow-none focus-visible:shadow-none";
|
|
5
5
|
export declare function StringControl({ field, value, onChange, readOnly, id, invalid, onBlur }: ControlProps): import("react/jsx-runtime").JSX.Element;
|
|
6
6
|
export declare function TextControl({ field, value, onChange, readOnly, id, invalid, onBlur }: ControlProps): import("react/jsx-runtime").JSX.Element;
|
|
7
7
|
export declare function EmailControl({ field, value, onChange, readOnly, id, invalid, onBlur }: ControlProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { cn } from "../lib/cn.js";
|
|
2
2
|
import { useForm, useKitEnv, useKitServices } from "../context.js";
|
|
3
3
|
import { Button, IconButton } from "../ui/button.js";
|
|
4
|
+
import { Checkbox } from "../ui/controls.js";
|
|
4
5
|
import { Tooltip } from "../ui/overlay.js";
|
|
5
6
|
import { plainText } from "../lib/schema.js";
|
|
6
7
|
import { Input, Textarea } from "../ui/input.js";
|
|
7
8
|
import { slugify } from "../lib/utils.js";
|
|
8
9
|
import * as React from "react";
|
|
9
|
-
import { IconAlertTriangle, IconExternalLink, IconMail, IconWorld } from "@tabler/icons-react";
|
|
10
10
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
11
|
-
|
|
11
|
+
import { IconAlertTriangle, IconExternalLink, IconMail, IconWorld } from "@tabler/icons-react";
|
|
12
|
+
//#region src/controls/text.tsx
|
|
12
13
|
/**
|
|
13
14
|
* TEXT — string · text · email · url · slug (V2 HEAD 9829bf1 kit/controls/text.tsx, DESIGN §8.2–8.3).
|
|
14
15
|
* Founder rule: text grows to show its whole value, never clipped. Text entry gets NO focus ring or halo — the border
|
|
@@ -19,8 +20,8 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
19
20
|
* (a trailing "-" before the next word) are tidied on blur.
|
|
20
21
|
*/
|
|
21
22
|
var str = (v) => typeof v === "string" ? v : v == null ? "" : String(v);
|
|
22
|
-
/** border-only focus (no halo) for text entry
|
|
23
|
-
var TEXT_FOCUS = "focus:shadow-none focus-visible:shadow-none
|
|
23
|
+
/** border-only focus (no halo) for text entry */
|
|
24
|
+
var TEXT_FOCUS = "focus:shadow-none focus-visible:shadow-none";
|
|
24
25
|
function StringControl({ field, value, onChange, readOnly, id, invalid, onBlur }) {
|
|
25
26
|
const { variant } = useKitEnv();
|
|
26
27
|
return /* @__PURE__ */ jsx(Textarea, {
|
|
@@ -137,9 +138,9 @@ function SlugControl({ value, onChange, readOnly, id, invalid, parent, path, onB
|
|
|
137
138
|
const v = str(value);
|
|
138
139
|
const env = useKitEnv();
|
|
139
140
|
const form = useForm();
|
|
140
|
-
const { toast } = useKitServices();
|
|
141
|
+
const { toast, redirectSlug, saveSlug } = useKitServices();
|
|
141
142
|
const src = slugSource(parent, env.docTitle);
|
|
142
|
-
const following = React.useRef(env.isPublished
|
|
143
|
+
const following = React.useRef(!env.isPublished && (v === "" || v === slugify(src)));
|
|
143
144
|
const seenSrc = React.useRef(src);
|
|
144
145
|
React.useEffect(() => {
|
|
145
146
|
if (seenSrc.current === src) return;
|
|
@@ -148,7 +149,9 @@ function SlugControl({ value, onChange, readOnly, id, invalid, parent, path, onB
|
|
|
148
149
|
const next = slugify(src);
|
|
149
150
|
if (next && next !== v) onChange(next);
|
|
150
151
|
}, [src]);
|
|
151
|
-
const live = form?.hasPublished ? str(form.publishedAt(path)) : env.isPublished ? str(form?.baselineAt(path) ?? "") : "";
|
|
152
|
+
const live = !env.slugIsAddress ? "" : form?.hasPublished ? str(form.publishedAt(path)) : env.isPublished ? str(form?.baselineAt(path) ?? "") : "";
|
|
153
|
+
const [saving, setSaving] = React.useState(false);
|
|
154
|
+
const [redirect, setRedirect] = React.useState(true);
|
|
152
155
|
const [confirmed, setConfirmed] = React.useState(null);
|
|
153
156
|
const changedLive = !!live && live !== v && confirmed !== v;
|
|
154
157
|
const host = env.urlPrefix?.replace(/^https?:\/\//, "");
|
|
@@ -162,7 +165,7 @@ function SlugControl({ value, onChange, readOnly, id, invalid, parent, path, onB
|
|
|
162
165
|
readOnly,
|
|
163
166
|
"aria-invalid": invalid,
|
|
164
167
|
placeholder: "empty-is-the-home-page",
|
|
165
|
-
className: cn(TEXT_FOCUS, "font-kit-mono"),
|
|
168
|
+
className: cn(TEXT_FOCUS, "font-kit-mono [&_input]:font-kit-mono"),
|
|
166
169
|
onChange: (e) => {
|
|
167
170
|
following.current = false;
|
|
168
171
|
onChange(slugTyping(e.target.value));
|
|
@@ -174,41 +177,71 @@ function SlugControl({ value, onChange, readOnly, id, invalid, parent, path, onB
|
|
|
174
177
|
}
|
|
175
178
|
}),
|
|
176
179
|
changedLive ? /* @__PURE__ */ jsxs("div", {
|
|
177
|
-
role: "status",
|
|
178
180
|
className: "flex flex-col gap-2 rounded-kit-md border border-kit-warning-line bg-kit-warning-soft px-3 py-2.5 text-kit-sm",
|
|
179
|
-
children: [
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
})
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
181
|
+
children: [
|
|
182
|
+
/* @__PURE__ */ jsxs("p", {
|
|
183
|
+
className: "flex items-start gap-1.5 text-kit-warning-fg",
|
|
184
|
+
children: [/* @__PURE__ */ jsx(IconAlertTriangle, {
|
|
185
|
+
className: "mt-0.5 size-4 shrink-0",
|
|
186
|
+
stroke: 1.5
|
|
187
|
+
}), /* @__PURE__ */ jsxs("span", { children: [
|
|
188
|
+
"The old address ",
|
|
189
|
+
/* @__PURE__ */ jsxs("span", {
|
|
190
|
+
className: "font-kit-mono",
|
|
191
|
+
children: ["/", live]
|
|
192
|
+
}),
|
|
193
|
+
" will stop working."
|
|
194
|
+
] })]
|
|
195
|
+
}),
|
|
196
|
+
redirectSlug ? /* @__PURE__ */ jsxs("label", {
|
|
197
|
+
className: "flex items-center gap-2 text-kit-fg-2",
|
|
198
|
+
children: [/* @__PURE__ */ jsx(Checkbox, {
|
|
199
|
+
checked: redirect,
|
|
200
|
+
onCheckedChange: (c) => setRedirect(c === true),
|
|
201
|
+
nativeButton: true,
|
|
202
|
+
render: /* @__PURE__ */ jsx("button", { type: "button" })
|
|
203
|
+
}), "Redirect it to the new address"]
|
|
204
|
+
}) : null,
|
|
205
|
+
/* @__PURE__ */ jsxs("div", {
|
|
206
|
+
className: "flex gap-1.5",
|
|
207
|
+
children: [/* @__PURE__ */ jsx(Button, {
|
|
208
|
+
size: "xs",
|
|
209
|
+
variant: "primary",
|
|
210
|
+
disabled: saving,
|
|
211
|
+
onClick: async () => {
|
|
212
|
+
const from = live;
|
|
213
|
+
const to = v;
|
|
214
|
+
const redirected = redirect && !!redirectSlug;
|
|
215
|
+
setSaving(true);
|
|
216
|
+
try {
|
|
217
|
+
if (saveSlug) await saveSlug(to);
|
|
218
|
+
} catch (err) {
|
|
219
|
+
setSaving(false);
|
|
220
|
+
toast?.("Couldn't save the new address", { description: errorText(err) });
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
setSaving(false);
|
|
224
|
+
setConfirmed(to);
|
|
225
|
+
if (redirected) try {
|
|
226
|
+
await redirectSlug(from, to);
|
|
227
|
+
} catch (err) {
|
|
228
|
+
toast?.("New address saved. The redirect wasn't created", { description: errorText(err) });
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
toast?.success("New address saved", { description: redirected ? `/${from} now redirects to /${to}` : `/${from} will return “Not found”` });
|
|
232
|
+
},
|
|
233
|
+
children: "Save new address"
|
|
234
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
235
|
+
size: "xs",
|
|
236
|
+
variant: "ghost",
|
|
237
|
+
onClick: () => {
|
|
238
|
+
following.current = false;
|
|
239
|
+
onChange(live);
|
|
240
|
+
},
|
|
241
|
+
children: "Keep the old slug"
|
|
242
|
+
})]
|
|
243
|
+
})
|
|
244
|
+
]
|
|
212
245
|
}) : null,
|
|
213
246
|
url && host ? /* @__PURE__ */ jsx(AddressLine, {
|
|
214
247
|
url,
|
|
@@ -233,6 +266,8 @@ function SlugControl({ value, onChange, readOnly, id, invalid, parent, path, onB
|
|
|
233
266
|
]
|
|
234
267
|
});
|
|
235
268
|
}
|
|
269
|
+
/** A host's refusal as one line (an Error's message, else the value itself). */
|
|
270
|
+
var errorText = (err) => err instanceof Error ? err.message : String(err);
|
|
236
271
|
function splitTail(display) {
|
|
237
272
|
const cut = display.indexOf("/") >= 0 ? display.lastIndexOf("/") : -1;
|
|
238
273
|
let tail = cut > 0 ? display.slice(cut) : "";
|
|
@@ -282,6 +317,6 @@ function AddressLine({ url, domain, status, onCopy, children }) {
|
|
|
282
317
|
});
|
|
283
318
|
}
|
|
284
319
|
//#endregion
|
|
285
|
-
export { EmailControl, SlugControl, SlugGenerate, StringControl, TEXT_FOCUS, TextControl, UrlControl, str };
|
|
320
|
+
export { EmailControl, SlugControl, SlugGenerate, StringControl, TEXT_FOCUS, TextControl, UrlControl, slugSource, slugTidy, slugTyping, str };
|
|
286
321
|
|
|
287
322
|
//# sourceMappingURL=text.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text.js","names":[],"sources":["../../src/controls/text.tsx"],"sourcesContent":["/**\n * TEXT — string · text · email · url · slug (V2 HEAD 9829bf1 kit/controls/text.tsx, DESIGN §8.2–8.3).\n * Founder rule: text grows to show its whole value, never clipped. Text entry gets NO focus ring or halo — the border\n * steps rest → hover → focus on the box only (prod CPO-069).\n *\n * Stored shapes (prod): string / longtext / email / slug / url (text + inputType \"url\") all store a plain string.\n * Slug keeps the backend's `^[a-z0-9]+(?:-[a-z0-9]+)*$`: keystrokes are filtered, and the stray hyphens typing leaves\n * (a trailing \"-\" before the next word) are tidied on blur.\n */\nimport * as React from \"react\";\nimport { IconAlertTriangle, IconExternalLink, IconMail, IconWorld } from \"@tabler/icons-react\";\nimport { cn } from \"../lib/cn\";\nimport { slugify } from \"../lib/utils\";\nimport { plainText } from \"../lib/schema\";\nimport { useForm, useKitEnv, useKitServices } from \"../context\";\nimport { Button, IconButton } from \"../ui/button\";\nimport { Input, Textarea } from \"../ui/input\";\nimport { Tooltip } from \"../ui/overlay\";\nimport { Checkbox } from \"../ui/controls\";\nimport type { ControlProps } from \"../types\";\n\nexport const str = (v: unknown) => (typeof v === \"string\" ? v : v == null ? \"\" : String(v));\n/** border-only focus (no halo) for text entry */\nexport const TEXT_FOCUS = \"focus:shadow-none focus-visible:shadow-none\";\n\nexport function StringControl({ field, value, onChange, readOnly, id, invalid, onBlur }: ControlProps) {\n const { variant } = useKitEnv();\n return (\n <Textarea\n id={id}\n rows={1}\n value={str(value)}\n readOnly={readOnly}\n aria-invalid={invalid}\n placeholder={field.placeholder}\n onBlur={onBlur}\n onKeyDown={(e) => e.key === \"Enter\" && e.preventDefault()}\n onChange={(e) => onChange(e.target.value.replace(/\\r?\\n/g, \" \"))}\n className={cn(TEXT_FOCUS, \"min-h-8 py-1.5 leading-5\", variant === \"document\" && \"min-h-9 py-2\")}\n />\n );\n}\n\nexport function TextControl({ field, value, onChange, readOnly, id, invalid, onBlur }: ControlProps) {\n return (\n <Textarea\n id={id}\n rows={field.rows ?? 3}\n value={str(value)}\n readOnly={readOnly}\n aria-invalid={invalid}\n placeholder={field.placeholder}\n onBlur={onBlur}\n onChange={(e) => onChange(e.target.value)}\n className={cn(TEXT_FOCUS, \"leading-5\")}\n />\n );\n}\n\nexport function EmailControl({ field, value, onChange, readOnly, id, invalid, onBlur }: ControlProps) {\n const { variant } = useKitEnv();\n return (\n <Input\n id={id}\n size={variant === \"document\" ? \"lg\" : \"md\"}\n type=\"email\"\n value={str(value)}\n readOnly={readOnly}\n aria-invalid={invalid}\n onBlur={onBlur}\n placeholder={field.placeholder ?? \"name@company.com\"}\n leading={<IconMail stroke={1.5} />}\n onChange={(e) => onChange(e.target.value.trim())}\n className={TEXT_FOCUS}\n />\n );\n}\n\nexport function UrlControl({ field, value, onChange, readOnly, id, invalid, onBlur }: ControlProps) {\n const v = str(value);\n const { variant } = useKitEnv();\n const open = /^https?:\\/\\/\\S+/.test(v);\n return (\n <Input\n id={id}\n size={variant === \"document\" ? \"lg\" : \"md\"}\n value={v}\n readOnly={readOnly}\n aria-invalid={invalid}\n onBlur={onBlur}\n placeholder={field.placeholder ?? \"https://example.com\"}\n onChange={(e) => onChange(e.target.value.trim())}\n leading={<IconWorld stroke={1.5} />}\n className={cn(TEXT_FOCUS, \"[&_input]:text-kit-accent-fg\")}\n trailing={\n open ? (\n <Tooltip content=\"Open link in a new tab\">\n <button\n type=\"button\"\n aria-label=\"Open link\"\n className=\"pointer-events-auto flex rounded-kit-md p-0.5 hover:bg-kit-selected hover:text-kit-fg\"\n onClick={() => window.open(v, \"_blank\", \"noopener\")}\n >\n <IconExternalLink className=\"size-4\" stroke={1.5} />\n </button>\n </Tooltip>\n ) : undefined\n }\n />\n );\n}\n\n/* ── Slug ──────────────────────────────────────────────────────────── */\nconst TITLE_KEYS = [\"title\", \"name\", \"heading\", \"question\", \"label\"];\n/** The text a slug follows: the first title-like sibling, else the document title. */\nexport function slugSource(parent: Record<string, unknown> | undefined, docTitle?: string) {\n for (const k of TITLE_KEYS) {\n const t = plainText(parent?.[k]);\n if (t) return t;\n }\n return docTitle ?? \"\";\n}\n/** What a keystroke may leave in a slug: lowercase letters, digits and hyphens (spaces become hyphens). */\nexport const slugTyping = (s: string) => s.toLowerCase().replace(/\\s+/g, \"-\").replace(/[^a-z0-9-]/g, \"\");\n/** The stored slug: no leading, trailing or doubled hyphens (the backend's pattern). */\nexport const slugTidy = (s: string) => slugTyping(s).replace(/-+/g, \"-\").replace(/^-|-$/g, \"\");\n\n/** Label-row \"Generate\" for slug fields (ACTIONS.slug; prod: ghost button in the label row). */\nexport function SlugGenerate({ parent, value, onChange, readOnly }: Pick<ControlProps, \"parent\" | \"value\" | \"onChange\" | \"readOnly\">) {\n const { docTitle } = useKitEnv();\n const src = slugSource(parent, docTitle);\n if (readOnly || !src) return null;\n const next = slugify(src);\n if (!next) return null;\n return (\n <Tooltip content={`Generate from “${src.length > 32 ? `${src.slice(0, 30)}…` : src}”`}>\n <Button size=\"xs\" variant=\"ghost\" className=\"h-5 px-1.5 text-kit-xs text-kit-fg-2\" disabled={next === value} onClick={() => onChange(next)}>\n Generate\n </Button>\n </Tooltip>\n );\n}\n\nexport function SlugControl({ value, onChange, readOnly, id, invalid, parent, path, onBlur }: ControlProps) {\n const v = str(value);\n const env = useKitEnv();\n const form = useForm();\n const { toast, redirectSlug, saveSlug } = useKitServices();\n const src = slugSource(parent, env.docTitle);\n /* Follows the title until someone edits it or the document is published (CPO-087), V2's rule (`!env.isPublished`):\n a host that passes no isPublished (the dock) follows too, as the help line says. It reacts to a title edit, never\n to mounting, so opening a form writes nothing. */\n const following = React.useRef(!env.isPublished && (v === \"\" || v === slugify(src)));\n const seenSrc = React.useRef(src);\n React.useEffect(() => {\n if (seenSrc.current === src) return;\n seenSrc.current = src;\n if (!following.current || readOnly) return;\n const next = slugify(src);\n if (next && next !== v) onChange(next);\n }, [src]); // eslint-disable-line react-hooks/exhaustive-deps\n\n /* the address the site serves today: the published value, else (published doc, no published copy) the mount value.\n Only where the host says the slug IS the address: a slug prop or a key has no address to break. */\n const live = !env.slugIsAddress ? \"\" : form?.hasPublished ? str(form.publishedAt(path)) : env.isPublished ? str(form?.baselineAt(path) ?? \"\") : \"\";\n const [saving, setSaving] = React.useState(false);\n const [redirect, setRedirect] = React.useState(true);\n const [confirmed, setConfirmed] = React.useState<string | null>(null);\n const changedLive = !!live && live !== v && confirmed !== v;\n const host = env.urlPrefix?.replace(/^https?:\\/\\//, \"\");\n const url = host ? `https://${host}${v}` : \"\";\n\n return (\n <div className=\"flex flex-col gap-1.5\">\n <Input\n id={id}\n value={v}\n readOnly={readOnly}\n aria-invalid={invalid}\n placeholder=\"empty-is-the-home-page\"\n className={cn(TEXT_FOCUS, \"font-kit-mono [&_input]:font-kit-mono\")}\n onChange={(e) => {\n following.current = false;\n onChange(slugTyping(e.target.value));\n }}\n onBlur={() => {\n const tidy = slugTidy(v);\n if (tidy !== v) onChange(tidy);\n onBlur?.();\n }}\n />\n {changedLive ? (\n <div className=\"flex flex-col gap-2 rounded-kit-md border border-kit-warning-line bg-kit-warning-soft px-3 py-2.5 text-kit-sm\">\n <p className=\"flex items-start gap-1.5 text-kit-warning-fg\">\n <IconAlertTriangle className=\"mt-0.5 size-4 shrink-0\" stroke={1.5} />\n <span>\n The old address <span className=\"font-kit-mono\">/{live}</span> will stop working.\n </span>\n </p>\n {/* only where the host files the redirect: the box must not promise one nothing creates */}\n {redirectSlug ? (\n <label className=\"flex items-center gap-2 text-kit-fg-2\">\n <Checkbox checked={redirect} onCheckedChange={(c) => setRedirect(c === true)} nativeButton render={<button type=\"button\" />} />\n Redirect it to the new address\n </label>\n ) : null}\n <div className=\"flex gap-1.5\">\n <Button\n size=\"xs\"\n variant=\"primary\"\n disabled={saving}\n onClick={async () => {\n const from = live;\n const to = v;\n const redirected = redirect && !!redirectSlug;\n setSaving(true);\n try {\n if (saveSlug) await saveSlug(to);\n } catch (err) {\n setSaving(false);\n toast?.(\"Couldn't save the new address\", { description: errorText(err) });\n return;\n }\n setSaving(false);\n setConfirmed(to);\n if (redirected) {\n try {\n await redirectSlug(from, to);\n } catch (err) {\n toast?.(\"New address saved. The redirect wasn't created\", { description: errorText(err) });\n return;\n }\n }\n toast?.success(\"New address saved\", { description: redirected ? `/${from} now redirects to /${to}` : `/${from} will return “Not found”` });\n }}\n >\n Save new address\n </Button>\n <Button\n size=\"xs\"\n variant=\"ghost\"\n onClick={() => {\n following.current = false;\n onChange(live);\n }}\n >\n Keep the old slug\n </Button>\n </div>\n </div>\n ) : null}\n {url && host ? (\n <AddressLine\n url={url}\n domain={host.replace(/\\/.*$/, \"\")}\n status={env.isPublished === undefined ? undefined : env.isPublished ? { live: true, label: \"Live\" } : { live: false, label: \"Not live yet\" }}\n onCopy={() => {\n void navigator.clipboard?.writeText(url).then(\n () => toast?.success(\"Address copied\", { description: url }),\n () => toast?.(\"Couldn't copy the address\", { description: \"The browser blocked clipboard access.\" }),\n );\n }}\n >\n {env.isPublished ? (\n <IconButton size=\"xs\" label=\"Open live\" onClick={() => window.open(url, \"_blank\", \"noopener\")}>\n <IconExternalLink stroke={1.5} />\n </IconButton>\n ) : null}\n </AddressLine>\n ) : null}\n </div>\n );\n}\n\n/** A host's refusal as one line (an Error's message, else the value itself). */\nconst errorText = (err: unknown) => (err instanceof Error ? err.message : String(err));\n\n/* V2 features/hosting/address-line.tsx (D66): one calm line under the slug — the mono URL (middle-truncated so the slug\n end stays; full URL in the tooltip; copies on click) · the live state as a dot and a word · trailing icon buttons. */\nfunction splitTail(display: string): [string, string] {\n const cut = display.indexOf(\"/\") >= 0 ? display.lastIndexOf(\"/\") : -1;\n let tail = cut > 0 ? display.slice(cut) : \"\";\n if (tail.length > 18) tail = tail.slice(-14);\n return [display.slice(0, display.length - tail.length), tail];\n}\n\nfunction AddressLine({ url, domain, status, onCopy, children }: { url: string; domain: string; status?: { live: boolean; label: string }; onCopy: () => void; children?: React.ReactNode }) {\n const display = url.replace(/^https?:\\/\\//, \"\");\n const [head, tail] = splitTail(display);\n const domainPart = head.startsWith(domain) ? domain : \"\";\n return (\n <div className=\"flex h-6 min-w-0 items-center gap-2\">\n <Tooltip content={<span className=\"font-kit-mono\">{display}</span>}>\n <button\n type=\"button\"\n onClick={onCopy}\n aria-label={`Copy address ${url}`}\n className=\"-ml-1 flex h-6 min-w-0 items-center rounded-kit-md px-1 font-kit-mono text-kit-xs text-kit-fg-2 transition-colors hover:bg-kit-hover hover:text-kit-fg\"\n >\n <span className=\"min-w-0 truncate\">\n {domainPart ? <span className=\"text-kit-fg-3\">{domainPart}</span> : null}\n {head.slice(domainPart.length)}\n </span>\n {tail ? <span className=\"shrink-0 whitespace-pre\">{tail}</span> : null}\n </button>\n </Tooltip>\n <span className=\"ml-auto flex shrink-0 items-center gap-1.5\">\n {status ? (\n <span className=\"mr-0.5 inline-flex shrink-0 items-center gap-1.5 whitespace-nowrap text-kit-xs text-kit-fg-2\">\n <span aria-hidden className={cn(\"size-1.5 shrink-0 rounded-full\", status.live ? \"bg-kit-success\" : \"bg-kit-fg-4\")} />\n {status.label}\n </span>\n ) : null}\n {children ? <span className=\"flex items-center gap-0.5\">{children}</span> : null}\n </span>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface UnknownValue {
|
|
2
|
+
/** what identifies the value to `onRemap` / `onRemove` */
|
|
3
|
+
key: string;
|
|
4
|
+
/** what the dock says: the stored value as stored, or its kind and name ("Heading 2 style “h2”") */
|
|
5
|
+
label: string;
|
|
6
|
+
/** the declared values it may be changed to; empty = remove only */
|
|
7
|
+
options: {
|
|
8
|
+
value: string;
|
|
9
|
+
label: string;
|
|
10
|
+
}[];
|
|
11
|
+
}
|
|
12
|
+
export declare function UnknownValueNote({ items, onRemap, onRemove, readOnly, }: {
|
|
13
|
+
items: readonly UnknownValue[];
|
|
14
|
+
onRemap: (key: string, to: string) => void;
|
|
15
|
+
onRemove: (key: string) => void;
|
|
16
|
+
readOnly?: boolean;
|
|
17
|
+
}): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { Button } from "../ui/button.js";
|
|
2
|
+
import { Menu, MenuContent, MenuItem, MenuLabel, MenuSeparator, MenuTrigger } from "../ui/overlay.js";
|
|
3
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
import { IconAlertTriangle, IconChevronDown } from "@tabler/icons-react";
|
|
5
|
+
//#region src/controls/unknown-value.tsx
|
|
6
|
+
/**
|
|
7
|
+
* UNKNOWN VALUE — a stored value the field's schema no longer declares (H4).
|
|
8
|
+
*
|
|
9
|
+
* A select option that was renamed or removed, a rich-text style or mark the field's Accept list no longer names: the
|
|
10
|
+
* value is KEPT, by the control and by every save, and said here, with the two ways out a person can take on purpose:
|
|
11
|
+
* change it to a value the field does declare, or remove it. Nothing changes until they pick one. (Sanity empties the
|
|
12
|
+
* select and strips the mark; we never drop a value in silence.)
|
|
13
|
+
*/
|
|
14
|
+
function UnknownValueNote({ items, onRemap, onRemove, readOnly }) {
|
|
15
|
+
if (items.length === 0) return null;
|
|
16
|
+
return /* @__PURE__ */ jsx("ul", {
|
|
17
|
+
"data-slot": "kit-unknown-values",
|
|
18
|
+
role: "status",
|
|
19
|
+
className: "flex flex-col gap-1",
|
|
20
|
+
children: items.map((item) => /* @__PURE__ */ jsxs("li", {
|
|
21
|
+
className: "flex min-h-8 min-w-0 items-center gap-2 rounded-kit-md bg-kit-warning-soft py-1 pl-2.5 pr-1 text-kit-xs text-kit-warning-fg",
|
|
22
|
+
children: [
|
|
23
|
+
/* @__PURE__ */ jsx(IconAlertTriangle, {
|
|
24
|
+
"aria-hidden": true,
|
|
25
|
+
className: "size-3.5 shrink-0",
|
|
26
|
+
stroke: 1.5
|
|
27
|
+
}),
|
|
28
|
+
/* @__PURE__ */ jsxs("span", {
|
|
29
|
+
className: "min-w-0 flex-1 truncate",
|
|
30
|
+
children: [
|
|
31
|
+
"Unknown value ",
|
|
32
|
+
item.label,
|
|
33
|
+
". Kept as it is."
|
|
34
|
+
]
|
|
35
|
+
}),
|
|
36
|
+
readOnly ? null : /* @__PURE__ */ jsxs(Menu, { children: [/* @__PURE__ */ jsx(MenuTrigger, {
|
|
37
|
+
render: /* @__PURE__ */ jsx(Button, {
|
|
38
|
+
size: "xs",
|
|
39
|
+
variant: "ghost",
|
|
40
|
+
rightIcon: /* @__PURE__ */ jsx(IconChevronDown, { stroke: 1.5 }),
|
|
41
|
+
"aria-label": `Fix unknown value ${item.label}`
|
|
42
|
+
}),
|
|
43
|
+
children: "Fix"
|
|
44
|
+
}), /* @__PURE__ */ jsxs(MenuContent, {
|
|
45
|
+
align: "end",
|
|
46
|
+
children: [item.options.length ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
47
|
+
/* @__PURE__ */ jsx(MenuLabel, { children: "Change to" }),
|
|
48
|
+
item.options.map((o) => /* @__PURE__ */ jsx(MenuItem, {
|
|
49
|
+
onClick: () => onRemap(item.key, o.value),
|
|
50
|
+
children: o.label
|
|
51
|
+
}, o.value)),
|
|
52
|
+
/* @__PURE__ */ jsx(MenuSeparator, {})
|
|
53
|
+
] }) : null, /* @__PURE__ */ jsx(MenuItem, {
|
|
54
|
+
danger: true,
|
|
55
|
+
onClick: () => onRemove(item.key),
|
|
56
|
+
children: "Remove"
|
|
57
|
+
})]
|
|
58
|
+
})] })
|
|
59
|
+
]
|
|
60
|
+
}, item.key))
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
//#endregion
|
|
64
|
+
export { UnknownValueNote };
|
|
65
|
+
|
|
66
|
+
//# sourceMappingURL=unknown-value.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unknown-value.js","names":[],"sources":["../../src/controls/unknown-value.tsx"],"sourcesContent":["/**\n * UNKNOWN VALUE — a stored value the field's schema no longer declares (H4).\n *\n * A select option that was renamed or removed, a rich-text style or mark the field's Accept list no longer names: the\n * value is KEPT, by the control and by every save, and said here, with the two ways out a person can take on purpose:\n * change it to a value the field does declare, or remove it. Nothing changes until they pick one. (Sanity empties the\n * select and strips the mark; we never drop a value in silence.)\n */\nimport { IconAlertTriangle, IconChevronDown } from \"@tabler/icons-react\";\nimport { Button } from \"../ui/button\";\nimport { Menu, MenuContent, MenuItem, MenuLabel, MenuSeparator, MenuTrigger } from \"../ui/overlay\";\n\nexport interface UnknownValue {\n /** what identifies the value to `onRemap` / `onRemove` */\n key: string;\n /** what the dock says: the stored value as stored, or its kind and name (\"Heading 2 style “h2”\") */\n label: string;\n /** the declared values it may be changed to; empty = remove only */\n options: { value: string; label: string }[];\n}\n\nexport function UnknownValueNote({\n items,\n onRemap,\n onRemove,\n readOnly,\n}: {\n items: readonly UnknownValue[];\n onRemap: (key: string, to: string) => void;\n onRemove: (key: string) => void;\n readOnly?: boolean;\n}) {\n if (items.length === 0) return null;\n return (\n <ul data-slot=\"kit-unknown-values\" role=\"status\" className=\"flex flex-col gap-1\">\n {items.map((item) => (\n <li key={item.key} className=\"flex min-h-8 min-w-0 items-center gap-2 rounded-kit-md bg-kit-warning-soft py-1 pl-2.5 pr-1 text-kit-xs text-kit-warning-fg\">\n <IconAlertTriangle aria-hidden className=\"size-3.5 shrink-0\" stroke={1.5} />\n <span className=\"min-w-0 flex-1 truncate\">Unknown value {item.label}. Kept as it is.</span>\n {readOnly ? null : (\n <Menu>\n <MenuTrigger render={<Button size=\"xs\" variant=\"ghost\" rightIcon={<IconChevronDown stroke={1.5} />} aria-label={`Fix unknown value ${item.label}`} />}>\n Fix\n </MenuTrigger>\n <MenuContent align=\"end\">\n {item.options.length ? (\n <>\n <MenuLabel>Change to</MenuLabel>\n {item.options.map((o) => (\n <MenuItem key={o.value} onClick={() => onRemap(item.key, o.value)}>\n {o.label}\n </MenuItem>\n ))}\n <MenuSeparator />\n </>\n ) : null}\n <MenuItem danger onClick={() => onRemove(item.key)}>\n Remove\n </MenuItem>\n </MenuContent>\n </Menu>\n )}\n </li>\n ))}\n </ul>\n );\n}\n"],"mappings":";;;;;;;;;;;;;AAqBA,SAAgB,iBAAiB,EAC/B,OACA,SACA,UACA,YAMC;CACD,IAAI,MAAM,WAAW,GAAG,OAAO;CAC/B,OACE,oBAAC,MAAD;EAAI,aAAU;EAAqB,MAAK;EAAS,WAAU;EACxD,UAAA,MAAM,KAAK,SACV,qBAAC,MAAD;GAAmB,WAAU;GAA7B,UAAA;IACE,oBAAC,mBAAD;KAAmB,eAAA;KAAY,WAAU;KAAoB,QAAQ;IAAM,CAAA;IAC3E,qBAAC,QAAD;KAAM,WAAU;KAAhB,UAAA;MAA0C;MAAe,KAAK;MAAM;KAAsB;;IACzF,WAAW,OACV,qBAAC,MAAD,EAAA,UAAA,CACE,oBAAC,aAAD;KAAa,QAAQ,oBAAC,QAAD;MAAQ,MAAK;MAAK,SAAQ;MAAQ,WAAW,oBAAC,iBAAD,EAAiB,QAAQ,IAAM,CAAA;MAAG,cAAY,qBAAqB,KAAK;KAAU,CAAA;KAAG,UAAA;IAE1I,CAAA,GACb,qBAAC,aAAD;KAAa,OAAM;KAAnB,UAAA,CACG,KAAK,QAAQ,SACZ,qBAAA,UAAA,EAAA,UAAA;MACE,oBAAC,WAAD,EAAA,UAAW,YAAoB,CAAA;MAC9B,KAAK,QAAQ,KAAK,MACjB,oBAAC,UAAD;OAAwB,eAAe,QAAQ,KAAK,KAAK,EAAE,KAAK;OAC7D,UAAA,EAAE;MACK,GAFK,EAAE,KAEP,CACX;MACD,oBAAC,eAAD,CAAgB,CAAA;KAChB,EAAA,CAAA,IACA,MACJ,oBAAC,UAAD;MAAU,QAAA;MAAO,eAAe,SAAS,KAAK,GAAG;MAAG,UAAA;KAE1C,CAAA,CACC;IACT,CAAA,CAAA,EAAA,CAAA;GAEN;EA1BK,GAAA,KAAK,GA0BV,CACL;CACC,CAAA;AAER"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE CORE SCHEMA `C` (P2 C1): one canonical, versioned form of a V2 schema that both directions meet in.
|
|
3
|
+
*
|
|
4
|
+
* normV2: V2 → C canonical JSON (sorted keys, no undefined) of the V2 schema, with V2's own equivalences folded
|
|
5
|
+
* embedV2: C → V2 the schema C holds
|
|
6
|
+
* embedProd: C → prod the prod adapter (fromTypeSchema, the façade) on embedV2(c)
|
|
7
|
+
* normProd: prod → C normV2 of what the prod schema reads back as (toTypeSchema / propsToTypeSchema, the façades)
|
|
8
|
+
*
|
|
9
|
+
* Laws (PBT, src/core/__tests__): norm∘embed = id on C (P1); normProd(embedProd(c)) equals c except under the paths
|
|
10
|
+
* the adapter names (P2); prod zod accepts embedProd(c) (P3); every named loss is excluded, pending or out of its bound
|
|
11
|
+
* (P4); both normalisers are idempotent (P5); the hash is byte-stable (P6); one prod key per facet (P7); out-of-domain
|
|
12
|
+
* prod keys survive a write (P8).
|
|
13
|
+
*
|
|
14
|
+
* V2's equivalences folded by normV2 (what the V2 engine draws the same, so C cannot tell apart):
|
|
15
|
+
* - a list's itemNoun equal to the engine's fallback (lib/schema.ts itemNoun) is the absent one
|
|
16
|
+
* - a fieldset a field names but the schema does not declare is the declared { name, title: name } (engine/field-list
|
|
17
|
+
* arrange), appended after the declared ones in first-use order
|
|
18
|
+
*/
|
|
19
|
+
import { type AdapterTarget, type FromTypeSchemaResult, type ToTypeSchemaOptions } from "../adapters/schema";
|
|
20
|
+
import type { ProdComponent, ProdContentModel } from "../adapters/prod-types";
|
|
21
|
+
import type { TypeSchema } from "../schema/types";
|
|
22
|
+
import { type FacetRow } from "./facets";
|
|
23
|
+
export declare const CORE_VERSION: 1;
|
|
24
|
+
export interface CoreSchema {
|
|
25
|
+
v: typeof CORE_VERSION;
|
|
26
|
+
schema: TypeSchema;
|
|
27
|
+
}
|
|
28
|
+
/** Canonical JSON value: object keys sorted, undefined dropped, arrays in their order (order is meaning). */
|
|
29
|
+
export declare function canonical<T>(v: T): T;
|
|
30
|
+
export declare function normV2(v2: TypeSchema): CoreSchema;
|
|
31
|
+
export declare const embedV2: (c: CoreSchema) => TypeSchema;
|
|
32
|
+
export declare function embedProd(c: CoreSchema, lane: "fields"): FromTypeSchemaResult<ProdContentModel>;
|
|
33
|
+
export declare function embedProd(c: CoreSchema, lane: "props"): FromTypeSchemaResult<ProdComponent>;
|
|
34
|
+
export declare function embedProd(c: CoreSchema, lane: AdapterTarget): FromTypeSchemaResult<ProdContentModel | ProdComponent>;
|
|
35
|
+
export declare function normProd(prod: ProdContentModel | ProdComponent, lane: AdapterTarget, opts?: ToTypeSchemaOptions): CoreSchema;
|
|
36
|
+
/** Byte-stable serialisation of C: the hash input, and the form fixtures are frozen in. */
|
|
37
|
+
export declare const coreJson: (c: CoreSchema) => string;
|
|
38
|
+
/** `schema_hash`: "v1:" + sha256 of coreJson (Web Crypto: the same in the browser, Node and Bun). */
|
|
39
|
+
export declare function coreHash(c: CoreSchema): Promise<string>;
|
|
40
|
+
/** The leaf paths where two JSON values differ ("/fields/0/title"); a missing object or list compares as an empty one. */
|
|
41
|
+
export declare function leafDiff(a: unknown, b: unknown, path?: string, out?: string[]): string[];
|
|
42
|
+
export interface CoreLossItem {
|
|
43
|
+
path: string;
|
|
44
|
+
feature: string;
|
|
45
|
+
facet: FacetRow | undefined;
|
|
46
|
+
}
|
|
47
|
+
export interface CoreRoundTrip {
|
|
48
|
+
prod: ProdContentModel | ProdComponent;
|
|
49
|
+
back: CoreSchema;
|
|
50
|
+
/** the paths where C and normProd(embedProd(C)) differ */
|
|
51
|
+
diffs: string[];
|
|
52
|
+
/** loss(c): each item the adapter names that has a difference under it (an item C's equivalences absorb is no loss) */
|
|
53
|
+
loss: CoreLossItem[];
|
|
54
|
+
/** a difference no named item covers: a silent drop (P2 fails on any) */
|
|
55
|
+
unreported: string[];
|
|
56
|
+
}
|
|
57
|
+
/** C through prod and back, against the lane's read: the oracle P2 and P4 assert on. */
|
|
58
|
+
export declare function roundTripCore(c: CoreSchema, lane: AdapterTarget): CoreRoundTrip;
|
|
59
|
+
/**
|
|
60
|
+
* A prod definition written from C, with every out-of-domain key (facets.ts OUT_OF_DOMAIN: a prop's binding, host and
|
|
61
|
+
* server config) the stored definition held carried over by key. What write_schema stores (C6).
|
|
62
|
+
*/
|
|
63
|
+
export declare function preserveOutOfDomain<T extends ProdContentModel | ProdComponent>(written: T, stored: T | undefined, lane: AdapterTarget): T;
|