@bettercms-ai/kit 1.0.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +33 -0
- package/dist/adapters/dock-values.d.ts +28 -0
- package/dist/adapters/dock-values.js +41 -0
- package/dist/adapters/dock-values.js.map +1 -0
- package/{adapters → dist/adapters}/icons.js +2 -2
- package/dist/adapters/icons.js.map +1 -0
- package/{adapters → dist/adapters}/lossy.d.ts +90 -31
- package/dist/adapters/lossy.js +414 -0
- package/dist/adapters/lossy.js.map +1 -0
- package/{adapters → dist/adapters}/prod-types.d.ts +82 -4
- package/{adapters → dist/adapters}/prod-types.js +71 -3
- package/dist/adapters/prod-types.js.map +1 -0
- package/{adapters → dist/adapters}/schema.d.ts +40 -1
- package/{adapters → dist/adapters}/schema.js +996 -179
- package/dist/adapters/schema.js.map +1 -0
- package/{adapters → dist/adapters}/values.d.ts +26 -5
- package/{adapters → dist/adapters}/values.js +87 -17
- package/dist/adapters/values.js.map +1 -0
- package/dist/brand/logo.js +96 -0
- package/dist/brand/logo.js.map +1 -0
- package/{context.d.ts → dist/context.d.ts} +92 -2
- package/{context.js → dist/context.js} +5 -2
- package/dist/context.js.map +1 -0
- package/{controls → dist/controls}/button.d.ts +19 -5
- package/{controls → dist/controls}/button.js +125 -54
- package/dist/controls/button.js.map +1 -0
- package/{controls → dist/controls}/c1.js +1 -1
- package/dist/controls/c1.js.map +1 -0
- package/{controls → dist/controls}/c2.js +1 -1
- package/dist/controls/c2.js.map +1 -0
- package/{controls → dist/controls}/choice.d.ts +7 -2
- package/{controls → dist/controls}/choice.js +71 -18
- package/dist/controls/choice.js.map +1 -0
- package/{controls → dist/controls}/code-register.js +1 -1
- package/dist/controls/code-register.js.map +1 -0
- package/{controls → dist/controls}/code.js +10 -9
- package/dist/controls/code.js.map +1 -0
- package/{controls → dist/controls}/color.js +8 -8
- package/dist/controls/color.js.map +1 -0
- package/{controls → dist/controls}/component-services.d.ts +42 -0
- package/dist/controls/component-services.js +7 -0
- package/dist/controls/component-services.js.map +1 -0
- package/{controls → dist/controls}/date-register.js +1 -1
- package/dist/controls/date-register.js.map +1 -0
- package/{controls → dist/controls}/date-zone.js +8 -2
- package/dist/controls/date-zone.js.map +1 -0
- package/{controls → dist/controls}/date.js +32 -24
- package/dist/controls/date.js.map +1 -0
- package/{controls → dist/controls}/form-picker-register.js +1 -1
- package/dist/controls/form-picker-register.js.map +1 -0
- package/{controls → dist/controls}/form-picker.js +11 -9
- package/dist/controls/form-picker.js.map +1 -0
- package/{controls → dist/controls}/icon-register.js +1 -1
- package/dist/controls/icon-register.js.map +1 -0
- package/{controls → dist/controls}/icon.d.ts +4 -2
- package/{controls → dist/controls}/icon.js +32 -27
- package/dist/controls/icon.js.map +1 -0
- package/{controls → dist/controls}/index.d.ts +1 -1
- package/{controls → dist/controls}/index.js +4 -3
- package/dist/controls/index.js.map +1 -0
- package/{controls → dist/controls}/json-register.js +1 -1
- package/dist/controls/json-register.js.map +1 -0
- package/{controls → dist/controls}/json.js +13 -3
- package/dist/controls/json.js.map +1 -0
- package/{controls → dist/controls}/link.js +6 -6
- package/dist/controls/link.js.map +1 -0
- package/{controls → dist/controls}/location-register.js +1 -1
- package/dist/controls/location-register.js.map +1 -0
- package/{controls → dist/controls}/location.js +64 -40
- package/dist/controls/location.js.map +1 -0
- package/{controls → dist/controls}/media-register.js +1 -1
- package/dist/controls/media-register.js.map +1 -0
- package/{controls → dist/controls}/media-services.d.ts +6 -0
- package/dist/controls/media-services.js +0 -0
- package/{controls → dist/controls}/media.d.ts +35 -4
- package/{controls → dist/controls}/media.js +491 -171
- package/dist/controls/media.js.map +1 -0
- package/{controls → dist/controls}/number.js +10 -9
- package/dist/controls/number.js.map +1 -0
- package/{controls → dist/controls}/reference-register.js +1 -1
- package/dist/controls/reference-register.js.map +1 -0
- package/{controls → dist/controls}/reference-services.d.ts +4 -0
- package/dist/controls/reference-services.js +0 -0
- package/{controls → dist/controls}/reference.d.ts +1 -1
- package/{controls → dist/controls}/reference.js +93 -77
- package/dist/controls/reference.js.map +1 -0
- package/dist/controls/rich-text/blocks.d.ts +49 -0
- package/{controls → dist/controls}/rich-text/blocks.js +471 -144
- package/dist/controls/rich-text/blocks.js.map +1 -0
- package/{controls → dist/controls}/rich-text/catalog.d.ts +4 -1
- package/{controls → dist/controls}/rich-text/catalog.js +75 -65
- package/dist/controls/rich-text/catalog.js.map +1 -0
- package/{controls → dist/controls}/rich-text/codec.d.ts +9 -1
- package/{controls → dist/controls}/rich-text/codec.js +3 -1
- package/dist/controls/rich-text/codec.js.map +1 -0
- package/{controls → dist/controls}/rich-text/component-card.d.ts +1 -1
- package/{controls → dist/controls}/rich-text/component-card.js +417 -99
- package/dist/controls/rich-text/component-card.js.map +1 -0
- package/dist/controls/rich-text/component-panel.d.ts +47 -0
- package/dist/controls/rich-text/component-panel.js +141 -0
- package/dist/controls/rich-text/component-panel.js.map +1 -0
- package/{controls → dist/controls}/rich-text/control.d.ts +1 -2
- package/{controls → dist/controls}/rich-text/control.js +84 -42
- package/dist/controls/rich-text/control.js.map +1 -0
- package/{controls → dist/controls}/rich-text/dom.d.ts +52 -9
- package/{controls → dist/controls}/rich-text/dom.js +379 -50
- package/dist/controls/rich-text/dom.js.map +1 -0
- package/{controls → dist/controls}/rich-text/editor.d.ts +7 -0
- package/{controls → dist/controls}/rich-text/editor.js +148 -48
- package/dist/controls/rich-text/editor.js.map +1 -0
- package/{controls → dist/controls}/rich-text/floating.d.ts +6 -1
- package/{controls → dist/controls}/rich-text/floating.js +35 -18
- package/dist/controls/rich-text/floating.js.map +1 -0
- package/{controls → dist/controls}/rich-text/index.js +1 -1
- package/dist/controls/rich-text/index.js.map +1 -0
- package/dist/controls/rich-text/link-form.js +147 -0
- package/dist/controls/rich-text/link-form.js.map +1 -0
- package/{controls → dist/controls}/rich-text/markdown.js +4 -2
- package/dist/controls/rich-text/markdown.js.map +1 -0
- package/{controls → dist/controls}/rich-text/ops.js +17 -15
- package/dist/controls/rich-text/ops.js.map +1 -0
- package/dist/controls/rich-text/plain.d.ts +17 -0
- package/dist/controls/rich-text/plain.js +44 -0
- package/dist/controls/rich-text/plain.js.map +1 -0
- package/{controls → dist/controls}/rich-text/toolbar.d.ts +6 -2
- package/{controls → dist/controls}/rich-text/toolbar.js +12 -7
- package/dist/controls/rich-text/toolbar.js.map +1 -0
- package/{controls → dist/controls}/scale.js +5 -5
- package/dist/controls/scale.js.map +1 -0
- package/{controls → dist/controls}/slot-register.js +1 -1
- package/dist/controls/slot-register.js.map +1 -0
- package/{controls → dist/controls}/slot-services.d.ts +25 -0
- package/dist/controls/slot-services.js +155 -0
- package/dist/controls/slot-services.js.map +1 -0
- package/{controls → dist/controls}/slot.js +42 -24
- package/dist/controls/slot.js.map +1 -0
- package/{controls → dist/controls}/table/index.js +1 -1
- package/dist/controls/table/index.js.map +1 -0
- package/{controls → dist/controls}/table/prod.js +3 -3
- package/dist/controls/table/prod.js.map +1 -0
- package/{controls → dist/controls}/table/refs.js +13 -2
- package/dist/controls/table/refs.js.map +1 -0
- package/{controls → dist/controls}/table/stored.js +1 -1
- package/dist/controls/table/stored.js.map +1 -0
- package/{controls → dist/controls}/table/table-editor.js +51 -48
- package/dist/controls/table/table-editor.js.map +1 -0
- package/{controls → dist/controls}/table/table-link.js +3 -3
- package/dist/controls/table/table-link.js.map +1 -0
- package/{controls → dist/controls}/table/table.js +3 -3
- package/dist/controls/table/table.js.map +1 -0
- package/{controls → dist/controls}/text.d.ts +2 -2
- package/{controls → dist/controls}/text.js +78 -43
- package/dist/controls/text.js.map +1 -0
- package/dist/controls/unknown-value.d.ts +17 -0
- package/dist/controls/unknown-value.js +66 -0
- package/dist/controls/unknown-value.js.map +1 -0
- package/dist/core/core.d.ts +63 -0
- package/dist/core/core.js +171 -0
- package/dist/core/core.js.map +1 -0
- package/dist/core/facets.d.ts +347 -0
- package/dist/core/facets.js +334 -0
- package/dist/core/facets.js.map +1 -0
- package/dist/core/index.d.ts +3 -0
- package/dist/core/index.js +3 -0
- package/{engine → dist/engine}/array.js +34 -21
- package/dist/engine/array.js.map +1 -0
- package/{engine → dist/engine}/bits.js +1 -1
- package/dist/engine/bits.js.map +1 -0
- package/{engine → dist/engine}/breadcrumb.d.ts +3 -3
- package/{engine → dist/engine}/breadcrumb.js +12 -36
- package/dist/engine/breadcrumb.js.map +1 -0
- package/{engine → dist/engine}/expand.d.ts +2 -4
- package/{engine → dist/engine}/expand.js +5 -22
- package/dist/engine/expand.js.map +1 -0
- package/{engine → dist/engine}/field-list.js +1 -1
- package/dist/engine/field-list.js.map +1 -0
- package/{engine → dist/engine}/field-shell.js +249 -121
- package/dist/engine/field-shell.js.map +1 -0
- package/{engine → dist/engine}/frame.d.ts +3 -1
- package/{engine → dist/engine}/frame.js +16 -14
- package/dist/engine/frame.js.map +1 -0
- package/{engine → dist/engine}/group-summary.d.ts +2 -1
- package/{engine → dist/engine}/group-summary.js +7 -3
- package/dist/engine/group-summary.js.map +1 -0
- package/{engine → dist/engine}/grouping.d.ts +19 -5
- package/{engine → dist/engine}/grouping.js +193 -21
- package/dist/engine/grouping.js.map +1 -0
- package/{engine → dist/engine}/item-list.d.ts +11 -1
- package/{engine → dist/engine}/item-list.js +35 -13
- package/dist/engine/item-list.js.map +1 -0
- package/{engine → dist/engine}/kit-field.js +45 -10
- package/dist/engine/kit-field.js.map +1 -0
- package/{engine → dist/engine}/schema-form.d.ts +27 -2
- package/{engine → dist/engine}/schema-form.js +182 -40
- package/dist/engine/schema-form.js.map +1 -0
- package/{engine → dist/engine}/slot.js +5 -15
- package/dist/engine/slot.js.map +1 -0
- package/dist/index.js +47 -0
- package/dist/index.js.map +1 -0
- package/{kit.css → dist/kit.css} +19 -0
- package/{lib → dist/lib}/cn.js +7 -4
- package/dist/lib/cn.js.map +1 -0
- package/{lib → dist/lib}/columns.js +4 -1
- package/dist/lib/columns.js.map +1 -0
- package/{lib → dist/lib}/frames.js +2 -2
- package/dist/lib/frames.js.map +1 -0
- package/dist/lib/icon-image.d.ts +10 -0
- package/dist/lib/icon-image.js +8 -0
- package/dist/lib/icon-image.js.map +1 -0
- package/{lib → dist/lib}/icons.js +4 -3
- package/dist/lib/icons.js.map +1 -0
- package/dist/lib/input-modality.d.ts +11 -0
- package/dist/lib/input-modality.js +47 -0
- package/dist/lib/input-modality.js.map +1 -0
- package/dist/lib/key-event.d.ts +11 -0
- package/dist/lib/key-event.js +16 -0
- package/dist/lib/key-event.js.map +1 -0
- package/{lib → dist/lib}/path.js +4 -2
- package/dist/lib/path.js.map +1 -0
- package/{lib → dist/lib}/schema.d.ts +34 -3
- package/{lib → dist/lib}/schema.js +110 -13
- package/dist/lib/schema.js.map +1 -0
- package/{lib → dist/lib}/utils.js +1 -1
- package/dist/lib/utils.js.map +1 -0
- package/{lib → dist/lib}/validate.d.ts +11 -1
- package/{lib → dist/lib}/validate.js +85 -11
- package/dist/lib/validate.js.map +1 -0
- package/dist/library/analysis.d.ts +23 -0
- package/dist/library/analysis.js +160 -0
- package/dist/library/analysis.js.map +1 -0
- package/dist/library/catalog.d.ts +57 -0
- package/dist/library/catalog.js +307 -0
- package/dist/library/catalog.js.map +1 -0
- package/dist/library/coreNotes.d.ts +8 -0
- package/dist/library/coreNotes.js +111 -0
- package/dist/library/coreNotes.js.map +1 -0
- package/dist/library/coverage.d.ts +40 -0
- package/dist/library/coverage.js +59 -0
- package/dist/library/coverage.js.map +1 -0
- package/dist/library/entries/advanced.entries.d.ts +2 -0
- package/dist/library/entries/advanced.entries.js +6579 -0
- package/dist/library/entries/advanced.entries.js.map +1 -0
- package/dist/library/entries/commerce.entries.d.ts +2 -0
- package/dist/library/entries/commerce.entries.js +4140 -0
- package/dist/library/entries/commerce.entries.js.map +1 -0
- package/dist/library/entries/company.entries.d.ts +2 -0
- package/dist/library/entries/company.entries.js +2731 -0
- package/dist/library/entries/company.entries.js.map +1 -0
- package/dist/library/entries/conversion.entries.d.ts +2 -0
- package/dist/library/entries/conversion.entries.js +3707 -0
- package/dist/library/entries/conversion.entries.js.map +1 -0
- package/dist/library/entries/data.entries.d.ts +7 -0
- package/dist/library/entries/data.entries.js +4613 -0
- package/dist/library/entries/data.entries.js.map +1 -0
- package/dist/library/entries/events.entries.d.ts +2 -0
- package/dist/library/entries/events.entries.js +3428 -0
- package/dist/library/entries/events.entries.js.map +1 -0
- package/dist/library/entries/features.entries.d.ts +2 -0
- package/dist/library/entries/features.entries.js +3157 -0
- package/dist/library/entries/features.entries.js.map +1 -0
- package/dist/library/entries/heroes.entries.d.ts +2 -0
- package/dist/library/entries/heroes.entries.js +3401 -0
- package/dist/library/entries/heroes.entries.js.map +1 -0
- package/dist/library/entries/index.d.ts +3 -0
- package/dist/library/entries/index.js +35 -0
- package/dist/library/entries/index.js.map +1 -0
- package/dist/library/entries/listings.entries.d.ts +2 -0
- package/dist/library/entries/listings.entries.js +2976 -0
- package/dist/library/entries/listings.entries.js.map +1 -0
- package/dist/library/entries/longform.entries.d.ts +2 -0
- package/dist/library/entries/longform.entries.js +4227 -0
- package/dist/library/entries/longform.entries.js.map +1 -0
- package/dist/library/entries/media.entries.d.ts +2 -0
- package/dist/library/entries/media.entries.js +2781 -0
- package/dist/library/entries/media.entries.js.map +1 -0
- package/dist/library/entries/navigation.entries.d.ts +2 -0
- package/dist/library/entries/navigation.entries.js +4011 -0
- package/dist/library/entries/navigation.entries.js.map +1 -0
- package/dist/library/entries/pricing.entries.d.ts +2 -0
- package/dist/library/entries/pricing.entries.js +2383 -0
- package/dist/library/entries/pricing.entries.js.map +1 -0
- package/dist/library/entries/social-proof.entries.d.ts +2 -0
- package/dist/library/entries/social-proof.entries.js +2297 -0
- package/dist/library/entries/social-proof.entries.js.map +1 -0
- package/dist/library/examples/bento.d.ts +92 -0
- package/dist/library/examples/bento.js +201 -0
- package/dist/library/examples/bento.js.map +1 -0
- package/dist/library/examples/blocks.d.ts +14 -0
- package/dist/library/examples/blocks.js +313 -0
- package/dist/library/examples/blocks.js.map +1 -0
- package/dist/library/examples/faq.d.ts +28 -0
- package/dist/library/examples/faq.js +230 -0
- package/dist/library/examples/faq.js.map +1 -0
- package/dist/library/examples/hero.d.ts +43 -0
- package/dist/library/examples/hero.js +222 -0
- package/dist/library/examples/hero.js.map +1 -0
- package/dist/library/examples/index.d.ts +36 -0
- package/dist/library/examples/index.js +109 -0
- package/dist/library/examples/index.js.map +1 -0
- package/dist/library/examples/journalStory.d.ts +93 -0
- package/dist/library/examples/journalStory.js +338 -0
- package/dist/library/examples/journalStory.js.map +1 -0
- package/dist/library/examples/megaMenu.d.ts +134 -0
- package/dist/library/examples/megaMenu.js +442 -0
- package/dist/library/examples/megaMenu.js.map +1 -0
- package/dist/library/examples/pricing.d.ts +103 -0
- package/dist/library/examples/pricing.js +479 -0
- package/dist/library/examples/pricing.js.map +1 -0
- package/dist/library/examples/tabs.d.ts +87 -0
- package/dist/library/examples/tabs.js +180 -0
- package/dist/library/examples/tabs.js.map +1 -0
- package/dist/library/export.d.ts +42 -0
- package/dist/library/export.js +80 -0
- package/dist/library/export.js.map +1 -0
- package/dist/library/index.d.ts +13 -0
- package/dist/library/index.js +6 -0
- package/dist/library/kit-catalog.json +1510 -0
- package/dist/library/types.d.ts +42 -0
- package/dist/library/types.js +0 -0
- package/{schema → dist/schema}/adapters.js +1 -2
- package/dist/schema/adapters.js.map +1 -0
- package/{schema → dist/schema}/help.d.ts +2 -0
- package/{schema → dist/schema}/help.js +6 -4
- package/dist/schema/help.js.map +1 -0
- package/{schema → dist/schema}/scale.js +1 -1
- package/dist/schema/scale.js.map +1 -0
- package/{schema → dist/schema}/sources.js +1 -1
- package/dist/schema/sources.js.map +1 -0
- package/{schema → dist/schema}/table.js +11 -10
- package/dist/schema/table.js.map +1 -0
- package/{schema → dist/schema}/types.d.ts +29 -1
- package/{schema → dist/schema}/types.js +1 -1
- package/dist/schema/types.js.map +1 -0
- package/dist/styles.css +2 -0
- package/dist/table/table-view.d.ts +14 -0
- package/dist/table/table-view.js +140 -0
- package/dist/table/table-view.js.map +1 -0
- package/dist/table/table.css +73 -0
- package/dist/testing/corpus.d.ts +63 -0
- package/dist/testing/corpus.js +129 -0
- package/dist/testing/corpus.js.map +1 -0
- package/dist/testing/test-form.d.ts +11 -0
- package/dist/testing/test-form.js +38 -0
- package/dist/testing/test-form.js.map +1 -0
- package/dist/theme.css +345 -0
- package/dist/theme.d.ts +22 -0
- package/dist/theme.js +43 -0
- package/dist/theme.js.map +1 -0
- package/dist/tokens.css +542 -0
- package/dist/types.js +0 -0
- package/{ui → dist/ui}/action-tray.d.ts +1 -1
- package/{ui → dist/ui}/action-tray.js +20 -19
- package/dist/ui/action-tray.js.map +1 -0
- package/dist/ui/autocomplete.d.ts +30 -0
- package/dist/ui/autocomplete.js +139 -0
- package/dist/ui/autocomplete.js.map +1 -0
- package/{ui → dist/ui}/button.d.ts +3 -3
- package/{ui → dist/ui}/button.js +6 -7
- package/dist/ui/button.js.map +1 -0
- package/{ui → dist/ui}/choice-switch.js +1 -1
- package/dist/ui/choice-switch.js.map +1 -0
- package/{ui → dist/ui}/controls.js +51 -39
- package/dist/ui/controls.js.map +1 -0
- package/{ui → dist/ui}/display.d.ts +10 -3
- package/{ui → dist/ui}/display.js +57 -46
- package/dist/ui/display.js.map +1 -0
- package/{ui → dist/ui}/expanded-editor-modal.d.ts +2 -2
- package/{ui → dist/ui}/expanded-editor-modal.js +6 -6
- package/dist/ui/expanded-editor-modal.js.map +1 -0
- package/{ui → dist/ui}/field-context.js +1 -1
- package/dist/ui/field-context.js.map +1 -0
- package/{ui → dist/ui}/floating-panel.d.ts +1 -1
- package/{ui → dist/ui}/floating-panel.js +28 -12
- package/dist/ui/floating-panel.js.map +1 -0
- package/{ui → dist/ui}/index.d.ts +4 -0
- package/dist/ui/index.js +18 -0
- package/{ui → dist/ui}/input.d.ts +1 -1
- package/{ui → dist/ui}/input.js +9 -9
- package/dist/ui/input.js.map +1 -0
- package/{ui → dist/ui}/mode-bar.js +3 -3
- package/dist/ui/mode-bar.js.map +1 -0
- package/{ui → dist/ui}/overlay.d.ts +77 -5
- package/dist/ui/overlay.js +697 -0
- package/dist/ui/overlay.js.map +1 -0
- package/{ui → dist/ui}/path-crumbs.js +37 -3
- package/dist/ui/path-crumbs.js.map +1 -0
- package/{ui → dist/ui}/presence.js +2 -2
- package/dist/ui/presence.js.map +1 -0
- package/{ui → dist/ui}/select.js +89 -87
- package/dist/ui/select.js.map +1 -0
- package/{ui → dist/ui}/shortcut-hint.js +1 -1
- package/dist/ui/shortcut-hint.js.map +1 -0
- package/dist/ui/spinner.d.ts +24 -0
- package/dist/ui/spinner.js +42 -0
- package/dist/ui/spinner.js.map +1 -0
- package/dist/ui/split-button.d.ts +32 -0
- package/dist/ui/split-button.js +60 -0
- package/dist/ui/split-button.js.map +1 -0
- package/{ui → dist/ui}/surfaces.js +1 -1
- package/dist/ui/surfaces.js.map +1 -0
- package/dist/ui/tab.d.ts +38 -0
- package/dist/ui/tab.js +87 -0
- package/dist/ui/tab.js.map +1 -0
- package/dist/ui/toast.d.ts +20 -0
- package/dist/ui/toast.js +115 -0
- package/dist/ui/toast.js.map +1 -0
- package/{ui → dist/ui}/tooltip-root.d.ts +4 -3
- package/{ui → dist/ui}/tooltip-root.js +9 -8
- package/dist/ui/tooltip-root.js.map +1 -0
- package/{ui → dist/ui}/variants.js +1 -1
- package/dist/ui/variants.js.map +1 -0
- package/package.json +77 -23
- package/adapters/icons.js.map +0 -1
- package/adapters/lossy.js +0 -233
- package/adapters/lossy.js.map +0 -1
- package/adapters/prod-types.js.map +0 -1
- package/adapters/schema.js.map +0 -1
- package/adapters/values.js.map +0 -1
- package/brand/logo.js +0 -9
- package/brand/logo.js.map +0 -1
- package/context.js.map +0 -1
- package/controls/button.js.map +0 -1
- package/controls/c1.js.map +0 -1
- package/controls/c2.js.map +0 -1
- package/controls/choice.js.map +0 -1
- package/controls/code-register.js.map +0 -1
- package/controls/code.js.map +0 -1
- package/controls/color.js.map +0 -1
- package/controls/date-register.js.map +0 -1
- package/controls/date-zone.js.map +0 -1
- package/controls/date.js.map +0 -1
- package/controls/form-picker-register.js.map +0 -1
- package/controls/form-picker.js.map +0 -1
- package/controls/icon-register.js.map +0 -1
- package/controls/icon.js.map +0 -1
- package/controls/index.js.map +0 -1
- package/controls/json-register.js.map +0 -1
- package/controls/json.js.map +0 -1
- package/controls/link.js.map +0 -1
- package/controls/location-register.js.map +0 -1
- package/controls/location.js.map +0 -1
- package/controls/media-register.js.map +0 -1
- package/controls/media.js.map +0 -1
- package/controls/number.js.map +0 -1
- package/controls/reference-register.js.map +0 -1
- package/controls/reference.js.map +0 -1
- package/controls/rich-text/blocks.d.ts +0 -28
- package/controls/rich-text/blocks.js.map +0 -1
- package/controls/rich-text/catalog.js.map +0 -1
- package/controls/rich-text/codec.js.map +0 -1
- package/controls/rich-text/component-card.js.map +0 -1
- package/controls/rich-text/control.js.map +0 -1
- package/controls/rich-text/dom.js.map +0 -1
- package/controls/rich-text/editor.js.map +0 -1
- package/controls/rich-text/floating.js.map +0 -1
- package/controls/rich-text/index.js.map +0 -1
- package/controls/rich-text/link-form.js +0 -111
- package/controls/rich-text/link-form.js.map +0 -1
- package/controls/rich-text/markdown.js.map +0 -1
- package/controls/rich-text/ops.js.map +0 -1
- package/controls/rich-text/toolbar.js.map +0 -1
- package/controls/scale.js.map +0 -1
- package/controls/slot-register.js.map +0 -1
- package/controls/slot-services.js +0 -38
- package/controls/slot-services.js.map +0 -1
- package/controls/slot.js.map +0 -1
- package/controls/table/index.js.map +0 -1
- package/controls/table/prod.js.map +0 -1
- package/controls/table/refs.js.map +0 -1
- package/controls/table/stored.js.map +0 -1
- package/controls/table/table-editor.js.map +0 -1
- package/controls/table/table-link.js.map +0 -1
- package/controls/table/table.js.map +0 -1
- package/controls/text.js.map +0 -1
- package/engine/array.js.map +0 -1
- package/engine/bits.js.map +0 -1
- package/engine/breadcrumb.js.map +0 -1
- package/engine/expand.js.map +0 -1
- package/engine/field-list.js.map +0 -1
- package/engine/field-shell.js.map +0 -1
- package/engine/frame.js.map +0 -1
- package/engine/group-summary.js.map +0 -1
- package/engine/grouping.js.map +0 -1
- package/engine/item-list.js.map +0 -1
- package/engine/kit-field.js.map +0 -1
- package/engine/schema-form.js.map +0 -1
- package/engine/slot.js.map +0 -1
- package/index.js +0 -55
- package/index.js.map +0 -1
- package/lib/cn.js.map +0 -1
- package/lib/columns.js.map +0 -1
- package/lib/frames.js.map +0 -1
- package/lib/icons.js.map +0 -1
- package/lib/path.js.map +0 -1
- package/lib/schema.js.map +0 -1
- package/lib/utils.js.map +0 -1
- package/lib/validate.js.map +0 -1
- package/schema/adapters.js.map +0 -1
- package/schema/help.js.map +0 -1
- package/schema/scale.js.map +0 -1
- package/schema/sources.js.map +0 -1
- package/schema/table.js.map +0 -1
- package/schema/types.js.map +0 -1
- package/ui/action-tray.js.map +0 -1
- package/ui/button.js.map +0 -1
- package/ui/choice-switch.js.map +0 -1
- package/ui/controls.js.map +0 -1
- package/ui/display.js.map +0 -1
- package/ui/expanded-editor-modal.js.map +0 -1
- package/ui/field-context.js.map +0 -1
- package/ui/floating-panel.js.map +0 -1
- package/ui/index.js +0 -13
- package/ui/input.js.map +0 -1
- package/ui/mode-bar.js.map +0 -1
- package/ui/overlay.js +0 -378
- package/ui/overlay.js.map +0 -1
- package/ui/path-crumbs.js.map +0 -1
- package/ui/presence.js.map +0 -1
- package/ui/select.js.map +0 -1
- package/ui/shortcut-hint.js.map +0 -1
- package/ui/surfaces.js.map +0 -1
- package/ui/tooltip-root.js.map +0 -1
- package/ui/variants.js.map +0 -1
- /package/{_virtual → dist/_virtual}/_rolldown/runtime.js +0 -0
- /package/{adapters → dist/adapters}/icons.d.ts +0 -0
- /package/{brand → dist/brand}/logo.d.ts +0 -0
- /package/{controls → dist/controls}/c1.d.ts +0 -0
- /package/{controls → dist/controls}/c2.d.ts +0 -0
- /package/{controls → dist/controls}/code-register.d.ts +0 -0
- /package/{controls → dist/controls}/code.d.ts +0 -0
- /package/{controls → dist/controls}/color.d.ts +0 -0
- /package/{controls → dist/controls}/date-register.d.ts +0 -0
- /package/{controls → dist/controls}/date-zone.d.ts +0 -0
- /package/{controls → dist/controls}/date.d.ts +0 -0
- /package/{controls → dist/controls}/form-picker-register.d.ts +0 -0
- /package/{controls → dist/controls}/form-picker.d.ts +0 -0
- /package/{controls → dist/controls}/icon-register.d.ts +0 -0
- /package/{controls → dist/controls}/json-register.d.ts +0 -0
- /package/{controls → dist/controls}/json.d.ts +0 -0
- /package/{controls → dist/controls}/link.d.ts +0 -0
- /package/{controls → dist/controls}/location-register.d.ts +0 -0
- /package/{controls → dist/controls}/location.d.ts +0 -0
- /package/{controls → dist/controls}/media-register.d.ts +0 -0
- /package/{controls → dist/controls}/number.d.ts +0 -0
- /package/{controls → dist/controls}/reference-register.d.ts +0 -0
- /package/{controls → dist/controls}/rich-text/index.d.ts +0 -0
- /package/{controls → dist/controls}/rich-text/link-form.d.ts +0 -0
- /package/{controls → dist/controls}/rich-text/markdown.d.ts +0 -0
- /package/{controls → dist/controls}/rich-text/ops.d.ts +0 -0
- /package/{controls → dist/controls}/scale.d.ts +0 -0
- /package/{controls → dist/controls}/slot-register.d.ts +0 -0
- /package/{controls → dist/controls}/slot.d.ts +0 -0
- /package/{controls → dist/controls}/table/index.d.ts +0 -0
- /package/{controls → dist/controls}/table/prod.d.ts +0 -0
- /package/{controls → dist/controls}/table/refs.d.ts +0 -0
- /package/{controls → dist/controls}/table/stored.d.ts +0 -0
- /package/{controls → dist/controls}/table/table-editor.d.ts +0 -0
- /package/{controls → dist/controls}/table/table-link.d.ts +0 -0
- /package/{controls → dist/controls}/table/table.d.ts +0 -0
- /package/{engine → dist/engine}/array.d.ts +0 -0
- /package/{engine → dist/engine}/bits.d.ts +0 -0
- /package/{engine → dist/engine}/field-list.d.ts +0 -0
- /package/{engine → dist/engine}/field-shell.d.ts +0 -0
- /package/{engine → dist/engine}/kit-field.d.ts +0 -0
- /package/{engine → dist/engine}/slot.d.ts +0 -0
- /package/{index.d.ts → dist/index.d.ts} +0 -0
- /package/{lib → dist/lib}/cn.d.ts +0 -0
- /package/{lib → dist/lib}/columns.d.ts +0 -0
- /package/{lib → dist/lib}/frames.d.ts +0 -0
- /package/{lib → dist/lib}/icons.d.ts +0 -0
- /package/{lib → dist/lib}/path.d.ts +0 -0
- /package/{lib → dist/lib}/utils.d.ts +0 -0
- /package/{schema → dist/schema}/adapters.d.ts +0 -0
- /package/{schema → dist/schema}/scale.d.ts +0 -0
- /package/{schema → dist/schema}/sources.d.ts +0 -0
- /package/{schema → dist/schema}/table.d.ts +0 -0
- /package/{types.d.ts → dist/types.d.ts} +0 -0
- /package/{ui → dist/ui}/choice-switch.d.ts +0 -0
- /package/{ui → dist/ui}/controls.d.ts +0 -0
- /package/{ui → dist/ui}/field-context.d.ts +0 -0
- /package/{ui → dist/ui}/mode-bar.d.ts +0 -0
- /package/{ui → dist/ui}/path-crumbs.d.ts +0 -0
- /package/{ui → dist/ui}/presence.d.ts +0 -0
- /package/{ui → dist/ui}/select.d.ts +0 -0
- /package/{ui → dist/ui}/shortcut-hint.d.ts +0 -0
- /package/{ui → dist/ui}/surfaces.d.ts +0 -0
- /package/{ui → dist/ui}/variants.d.ts +0 -0
|
@@ -1,17 +1,17 @@
|
|
|
1
|
+
import { DOCK_ICON_NAMES, DOCK_ICON_NAME_SET } from "../adapters/prod-types.js";
|
|
2
|
+
import { tablerIconOf } from "../adapters/icons.js";
|
|
1
3
|
import { cn } from "../lib/cn.js";
|
|
4
|
+
import { useKitServices } from "../context.js";
|
|
2
5
|
import { isObj } from "../lib/path.js";
|
|
3
6
|
import { iconLabel } from "../lib/icons.js";
|
|
4
|
-
import { DOCK_ICON_NAMES, DOCK_ICON_NAME_SET } from "../adapters/prod-types.js";
|
|
5
|
-
import { useKitServices } from "../context.js";
|
|
6
7
|
import { TooltipLayer } from "../ui/tooltip-root.js";
|
|
7
8
|
import { Button } from "../ui/button.js";
|
|
8
9
|
import { Popover, PopoverContent, PopoverTrigger } from "../ui/overlay.js";
|
|
9
|
-
import { tablerIconOf } from "../adapters/icons.js";
|
|
10
10
|
import * as React from "react";
|
|
11
|
-
import { IconAlertTriangle, IconChevronDown, IconPhoto, IconSearch, IconX } from "@tabler/icons-react";
|
|
12
11
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
12
|
+
import { IconAlertTriangle, IconChevronDown, IconPhoto, IconSearch, IconX } from "@tabler/icons-react";
|
|
13
13
|
import { Tooltip } from "@base-ui/react/tooltip";
|
|
14
|
-
//#region src/
|
|
14
|
+
//#region src/controls/icon.tsx
|
|
15
15
|
/**
|
|
16
16
|
* ICON — the icon field (DESIGN 8.14), V2 controls/icon.tsx fitted to what prod stores.
|
|
17
17
|
*
|
|
@@ -153,15 +153,16 @@ function IconGrid({ items, selected, onPick, label, tip }) {
|
|
|
153
153
|
"aria-label": it.label,
|
|
154
154
|
tabIndex: it.key === stop ? 0 : -1,
|
|
155
155
|
onClick: () => onPick(it.key),
|
|
156
|
-
className: cn("flex aspect-square
|
|
156
|
+
className: cn("flex aspect-square items-center justify-center rounded-kit-md text-kit-fg-2 transition-colors hover:bg-kit-hover hover:text-kit-fg", it.key === selected && "bg-kit-selected text-kit-fg ring-1 ring-inset ring-kit-line-strong"),
|
|
157
157
|
children: it.node
|
|
158
158
|
})
|
|
159
159
|
}, it.key))
|
|
160
160
|
});
|
|
161
161
|
}
|
|
162
162
|
var NONE = "__none";
|
|
163
|
-
/** The picker: search, Recent, then the whole set ("No icon" first). Search spans the name and its Tabler twin.
|
|
164
|
-
|
|
163
|
+
/** The picker: search, Recent, then the whole set ("No icon" first). Search spans the name and its Tabler twin.
|
|
164
|
+
* `field`: the icon field's popover (V2 IconFieldPicker, a 22rem list); otherwise the app-UI grid (V2 IconPickerGrid, max-h-56). */
|
|
165
|
+
function IconPicker({ value, onPick, onChooseMedia, field }) {
|
|
165
166
|
const [q, setQ] = React.useState("");
|
|
166
167
|
const root = React.useRef(null);
|
|
167
168
|
const tip = React.useMemo(() => Tooltip.createHandle(), []);
|
|
@@ -209,20 +210,23 @@ function IconPicker({ value, onPick, onChooseMedia }) {
|
|
|
209
210
|
})]
|
|
210
211
|
}),
|
|
211
212
|
/* @__PURE__ */ jsx("div", {
|
|
212
|
-
className: "max-h-56 overflow-y-auto pr-0.5",
|
|
213
|
-
children: needle ?
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
"
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
213
|
+
className: field ? "max-h-[22rem] overflow-y-auto pr-0.5" : "max-h-56 overflow-y-auto pr-0.5",
|
|
214
|
+
children: needle ? /* @__PURE__ */ jsx("div", {
|
|
215
|
+
className: "flex flex-col gap-2",
|
|
216
|
+
children: hits.length ? /* @__PURE__ */ jsx(Group, { children: /* @__PURE__ */ jsx(IconGrid, {
|
|
217
|
+
label: "Icons",
|
|
218
|
+
selected: value,
|
|
219
|
+
onPick: pick,
|
|
220
|
+
tip,
|
|
221
|
+
items: hits.map(item)
|
|
222
|
+
}) }) : /* @__PURE__ */ jsxs("p", {
|
|
223
|
+
className: "py-6 text-center text-kit-sm text-kit-fg-3",
|
|
224
|
+
children: [
|
|
225
|
+
"No icons match “",
|
|
226
|
+
q.trim(),
|
|
227
|
+
"”"
|
|
228
|
+
]
|
|
229
|
+
})
|
|
226
230
|
}) : /* @__PURE__ */ jsxs("div", {
|
|
227
231
|
className: "flex flex-col gap-2",
|
|
228
232
|
children: [recent.length ? /* @__PURE__ */ jsx(Group, {
|
|
@@ -312,11 +316,11 @@ function IconControl({ field, value, onChange, readOnly, id, invalid }) {
|
|
|
312
316
|
type: "button",
|
|
313
317
|
disabled: readOnly,
|
|
314
318
|
"aria-invalid": invalid || void 0,
|
|
315
|
-
className: cn("flex h-8 w-full
|
|
319
|
+
className: cn("flex h-8 w-full items-center gap-2.5 rounded-kit-md border border-kit-line-strong bg-kit-field-bg px-1 pr-2.5 text-left text-kit-sm transition-colors hover:border-kit-line-strong data-[popup-open]:border-kit-line-strong data-[popup-open]:bg-kit-field-bg", invalid && "border-[var(--kit-field-invalid)]")
|
|
316
320
|
}),
|
|
317
321
|
children: [
|
|
318
322
|
/* @__PURE__ */ jsx("span", {
|
|
319
|
-
className: "flex size-6
|
|
323
|
+
className: "flex size-6 items-center justify-center rounded-kit-md border border-kit-line bg-kit-control-bg text-kit-fg",
|
|
320
324
|
children: tile
|
|
321
325
|
}),
|
|
322
326
|
/* @__PURE__ */ jsx("span", {
|
|
@@ -324,16 +328,17 @@ function IconControl({ field, value, onChange, readOnly, id, invalid }) {
|
|
|
324
328
|
children: text
|
|
325
329
|
}),
|
|
326
330
|
/* @__PURE__ */ jsx(IconChevronDown, {
|
|
327
|
-
className: "size-3.5
|
|
331
|
+
className: "size-3.5 text-kit-fg-3",
|
|
328
332
|
stroke: 1.5,
|
|
329
333
|
"aria-hidden": true
|
|
330
334
|
})
|
|
331
335
|
]
|
|
332
336
|
}), /* @__PURE__ */ jsx(PopoverContent, {
|
|
333
|
-
className: "w-[
|
|
337
|
+
className: "w-[320px] p-2",
|
|
334
338
|
align: "start",
|
|
335
339
|
"aria-label": `${field.title}: choose an icon`,
|
|
336
340
|
children: /* @__PURE__ */ jsx(IconPicker, {
|
|
341
|
+
field: true,
|
|
337
342
|
value: read.kind === "name" ? read.name : read.kind === "empty" ? void 0 : "",
|
|
338
343
|
onPick: commit,
|
|
339
344
|
onChooseMedia: MediaPicker ? () => {
|
|
@@ -350,6 +355,6 @@ function IconControl({ field, value, onChange, readOnly, id, invalid }) {
|
|
|
350
355
|
}) : null] });
|
|
351
356
|
}
|
|
352
357
|
//#endregion
|
|
353
|
-
export { IconControl };
|
|
358
|
+
export { IconControl, IconPicker };
|
|
354
359
|
|
|
355
360
|
//# sourceMappingURL=icon.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"icon.js","names":[],"sources":["../../src/controls/icon.tsx"],"sourcesContent":["/**\n * ICON — the icon field (DESIGN 8.14), V2 controls/icon.tsx fitted to what prod stores.\n *\n * Values (backend reference-validation `icon`, the classic PropsPanel IconValueInput):\n * \"arrow-right\" a name from the BetterCMS icon set (DOCK_ICON_NAMES, 472 names)\n * \"https://…/logo.svg\" an uploaded icon: an image URL (picked from the media library; a component prop\n * stores the URL string, like the classic panel's codec=\"url\")\n * { url, … } an uploaded icon stored as an image value: shown and kept until replaced\n * null no icon (\"No icon\"; the backend skips an empty value)\n *\n * The grid offers the BetterCMS set, the one prod accepts. Search also matches a name's Tabler twin through the\n * Tabler ↔ dock adapter (adapters/icons.ts), so \"map\" finds earth-americas. A stored name outside the set (a stale\n * Tabler or Lucide name) is shown with its reason and kept until the author picks another.\n *\n * Glyphs: the host draws them (KitServices.IconGlyph: the dashboard's DockIcon, the set the site renders). With no\n * host renderer the kit draws the Tabler twin, loaded on first use; a name with no Tabler twin shows its name.\n */\nimport * as React from \"react\";\nimport type { Icon as TablerIcon } from \"@tabler/icons-react\";\nimport { IconAlertTriangle, IconChevronDown, IconPhoto, IconSearch, IconX } from \"@tabler/icons-react\";\nimport { cn } from \"../lib/cn\";\nimport { isObj } from \"../lib/path\";\nimport { iconLabel } from \"../lib/icons\";\nimport { useKitServices } from \"../context\";\nimport { DOCK_ICON_NAMES, DOCK_ICON_NAME_SET } from \"../adapters/prod-types\";\nimport { tablerIconOf } from \"../adapters/icons\";\nimport type { ControlProps } from \"../types\";\nimport { Button } from \"../ui/button\";\nimport { Tooltip as TooltipPrimitive } from \"@base-ui/react/tooltip\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"../ui/overlay\";\nimport { TooltipLayer } from \"../ui/tooltip-root\";\n\n/* ── Glyphs ───────────────────────────────────────────────────────────── */\ndeclare module \"../context\" {\n interface KitServices {\n /**\n * Draws one icon of the BetterCMS set by name, aria-hidden (the name beside it is the accessible text): the glyphs\n * the site renders. The dashboard passes `DockIcon` (src/components/dock/DockIcon). Absent → the Tabler twin.\n */\n IconGlyph?: React.ComponentType<{ name: string; className?: string }>;\n }\n}\n\nlet tablerSet: Record<string, unknown> | null = null;\nlet tablerLoad: Promise<void> | null = null;\nconst pascal = (kebab: string) => `Icon${kebab.split(\"-\").map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join(\"\")}`;\n\n/** The full Tabler set, loaded once and only when no host renderer is provided. */\nfunction useTablerSet(need: boolean): Record<string, unknown> | null {\n const [, landed] = React.useReducer((n: number) => n + 1, 0);\n React.useEffect(() => {\n if (!need || tablerSet) return;\n let live = true;\n tablerLoad ??= import(\"@tabler/icons-react\").then((m) => {\n tablerSet = m as unknown as Record<string, unknown>;\n });\n tablerLoad.then(() => live && landed(), () => {});\n return () => {\n live = false;\n };\n }, [need]);\n return tablerSet;\n}\n\nfunction Glyph({ name, className }: { name: string; className?: string }) {\n const Host = useKitServices().IconGlyph;\n const set = useTablerSet(!Host);\n if (Host) return <Host name={name} className={className} />;\n const T = set?.[pascal(tablerIconOf(name))] as TablerIcon | undefined;\n if (T) return <T className={className} stroke={1.5} aria-hidden />;\n // no Tabler twin (or the set is still loading): the name itself, never a stand-in shape\n return (\n <span aria-hidden className=\"max-w-full truncate px-0.5 text-[9px] leading-3 text-kit-fg-3\">\n {name}\n </span>\n );\n}\n\n/* ── Values ───────────────────────────────────────────────────────────── */\ntype Read =\n | { kind: \"empty\" }\n | { kind: \"name\"; name: string }\n | { kind: \"unknown\"; name: string }\n | { kind: \"upload\"; url: string }\n | { kind: \"unreadable\" };\nconst isUrlish = (s: string) => /[/.]/.test(s);\nfunction readIcon(v: unknown): Read {\n if (v == null || v === \"\") return { kind: \"empty\" };\n if (typeof v === \"string\") return DOCK_ICON_NAME_SET.has(v) ? { kind: \"name\", name: v } : isUrlish(v) ? { kind: \"upload\", url: v } : { kind: \"unknown\", name: v };\n if (isObj(v) && typeof v.url === \"string\" && v.url) return { kind: \"upload\", url: v.url };\n return { kind: \"unreadable\" };\n}\nconst fileName = (url: string) => decodeURIComponent(url.split(/[?#]/)[0].split(\"/\").pop() || url);\n\n/** Names picked this session, newest first (shown as \"Recent\"). */\nconst recents: string[] = [];\nconst pushRecent = (name: string) => {\n const i = recents.indexOf(name);\n if (i !== -1) recents.splice(i, 1);\n recents.unshift(name);\n recents.length = Math.min(recents.length, COLS);\n};\n\n/* ── The grid: one tab stop, arrow keys, Home / End ───────────────────── */\nconst COLS = 8;\nconst norm = (q: string) => q.toLowerCase().trim().replace(/\\s+/g, \"-\");\ninterface GridItem {\n key: string;\n label: string;\n node: React.ReactNode;\n}\n\ntype TipHandle = ReturnType<typeof TooltipPrimitive.createHandle<string>>;\n\n/** Up / down within a grid keep the column; past its edge they land in the same column of the next / previous grid. */\nfunction verticalTarget(grids: HTMLButtonElement[][], g: number, j: number, down: boolean): HTMLButtonElement | \"search\" | undefined {\n const col = j % COLS;\n const cur = grids[g];\n const within = down ? j + COLS : j - COLS;\n if (within >= 0 && within < cur.length) return cur[within];\n if (down && Math.floor(j / COLS) < Math.floor((cur.length - 1) / COLS)) return cur[cur.length - 1]; // a short last row\n const next = grids[down ? g + 1 : g - 1];\n if (!next) return down ? undefined : \"search\";\n if (down) return next[Math.min(col, next.length - 1)];\n const lastRow = Math.floor((next.length - 1) / COLS) * COLS;\n return next[Math.min(lastRow + col, next.length - 1)];\n}\n\nfunction IconGrid({ items, selected, onPick, label, tip }: { items: GridItem[]; selected?: string; onPick: (key: string) => void; label: string; tip: TipHandle }) {\n const ref = React.useRef<HTMLDivElement>(null);\n const stop = items.some((i) => i.key === selected) ? selected : items[0]?.key;\n const move = (e: React.KeyboardEvent) => {\n // one keyboard space across every group in the picker (Recent, the set, search results)\n const scope = ref.current?.closest(\"[data-icon-picker]\") ?? ref.current;\n const grids = Array.from(scope?.querySelectorAll<HTMLElement>(\"[data-icon-grid]\") ?? []).map((g) => Array.from(g.querySelectorAll<HTMLButtonElement>(\"[data-grid-item]\")));\n const btns = grids.flat();\n const i = btns.indexOf(document.activeElement as HTMLButtonElement);\n if (i === -1) return;\n const g = grids.findIndex((list) => list.includes(btns[i]));\n const j = grids[g].indexOf(btns[i]);\n let to: HTMLButtonElement | \"search\" | undefined;\n if (e.key === \"ArrowRight\") to = btns[Math.min(i + 1, btns.length - 1)];\n else if (e.key === \"ArrowLeft\") to = btns[Math.max(i - 1, 0)];\n else if (e.key === \"Home\") to = btns[0];\n else if (e.key === \"End\") to = btns[btns.length - 1];\n else if (e.key === \"ArrowDown\" || e.key === \"ArrowUp\") to = verticalTarget(grids, g, j, e.key === \"ArrowDown\") ?? btns[i];\n else return;\n e.preventDefault();\n if (to === \"search\") scope?.querySelector<HTMLInputElement>(\"input[data-icon-search]\")?.focus();\n else to?.focus();\n };\n return (\n <div ref={ref} data-icon-grid className=\"grid gap-0.5\" style={{ gridTemplateColumns: `repeat(${COLS}, minmax(0, 1fr))` }} role=\"listbox\" aria-label={label} onKeyDown={move}>\n {items.map((it) => (\n // one shared tooltip for the whole picker (hundreds of icons): each trigger hands it its label\n <TooltipPrimitive.Trigger\n key={it.key}\n handle={tip}\n payload={it.label}\n delay={500}\n render={\n <button\n type=\"button\"\n role=\"option\"\n data-grid-item\n data-icon={it.key}\n aria-selected={it.key === selected}\n aria-label={it.label}\n tabIndex={it.key === stop ? 0 : -1}\n onClick={() => onPick(it.key)}\n className={cn(\n \"flex aspect-square items-center justify-center rounded-kit-md text-kit-fg-2 transition-colors hover:bg-kit-hover hover:text-kit-fg\",\n it.key === selected && \"bg-kit-selected text-kit-fg ring-1 ring-inset ring-kit-line-strong\",\n )}\n >\n {it.node}\n </button>\n }\n />\n ))}\n </div>\n );\n}\n\nconst NONE = \"__none\";\n\n/** The picker: search, Recent, then the whole set (\"No icon\" first). Search spans the name and its Tabler twin.\n * `field`: the icon field's popover (V2 IconFieldPicker, a 22rem list); otherwise the app-UI grid (V2 IconPickerGrid, max-h-56). */\nexport function IconPicker({ value, onPick, onChooseMedia, field }: { value?: string; onPick: (name: string | null) => void; onChooseMedia?: () => void; field?: boolean }) {\n const [q, setQ] = React.useState(\"\");\n const root = React.useRef<HTMLDivElement>(null);\n const tip = React.useMemo(() => TooltipPrimitive.createHandle<string>(), []);\n const needle = norm(q);\n const item = (name: string): GridItem => ({ key: name, label: iconLabel(name), node: <Glyph name={name} className=\"size-[18px]\" /> });\n const pick = (key: string) => onPick(key === NONE ? null : key);\n const hits = needle ? DOCK_ICON_NAMES.filter((n) => n.includes(needle) || tablerIconOf(n).includes(needle)) : [];\n const recent = recents.filter((n) => DOCK_ICON_NAME_SET.has(n));\n return (\n <div ref={root} data-icon-picker className=\"flex flex-col gap-2\">\n <TooltipPrimitive.Root handle={tip}>{({ payload }) => (payload ? <TooltipLayer>{payload}</TooltipLayer> : null)}</TooltipPrimitive.Root>\n <label className=\"flex h-8 items-center gap-2 rounded-kit-md bg-kit-muted px-2.5 text-kit-fg-3 focus-within:bg-kit-field-bg focus-within:ring-1 focus-within:ring-kit-line-strong\">\n <IconSearch className=\"size-4 shrink-0\" stroke={1.5} aria-hidden />\n <input\n autoFocus\n data-icon-search\n value={q}\n onChange={(e) => setQ(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n root.current?.querySelector<HTMLButtonElement>(\"[data-grid-item]\")?.focus();\n }\n }}\n placeholder=\"Search icons\"\n aria-label=\"Search icons\"\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 className={field ? \"max-h-[22rem] overflow-y-auto pr-0.5\" : \"max-h-56 overflow-y-auto pr-0.5\"}>\n {needle ? (\n <div className=\"flex flex-col gap-2\">\n {hits.length ? (\n <Group>\n <IconGrid label=\"Icons\" selected={value} onPick={pick} tip={tip} items={hits.map(item)} />\n </Group>\n ) : (\n <p className=\"py-6 text-center text-kit-sm text-kit-fg-3\">No icons match “{q.trim()}”</p>\n )}\n </div>\n ) : (\n <div className=\"flex flex-col gap-2\">\n {recent.length ? (\n <Group title=\"Recent\">\n <IconGrid label=\"Recent icons\" selected={value} onPick={pick} tip={tip} items={recent.map(item)} />\n </Group>\n ) : null}\n <Group title={recent.length ? \"All icons\" : undefined}>\n <IconGrid\n label=\"Icons\"\n selected={value ?? NONE}\n onPick={pick}\n tip={tip}\n items={[{ key: NONE, label: \"No icon\", node: <IconX className=\"size-4\" stroke={1.5} aria-hidden /> }, ...DOCK_ICON_NAMES.map(item)]}\n />\n </Group>\n </div>\n )}\n </div>\n {onChooseMedia ? (\n <div className=\"flex items-center justify-between gap-2 border-t border-kit-line pt-2\">\n <span className=\"whitespace-nowrap text-kit-xs text-kit-fg-3\">Images keep their colours.</span>\n <Button size=\"xs\" variant=\"ghost\" leftIcon={<IconPhoto stroke={1.5} />} onClick={onChooseMedia}>\n Choose from media\n </Button>\n </div>\n ) : null}\n </div>\n );\n}\n\nfunction Group({ title, children }: { title?: string; children: React.ReactNode }) {\n return (\n <div className=\"flex flex-col gap-1\">\n {title ? <div className=\"px-0.5 text-kit-2xs font-medium text-kit-fg-3\">{title}</div> : null}\n {children}\n </div>\n );\n}\n\n/* ── The control ──────────────────────────────────────────────────────── */\nexport function IconControl({ field, value, onChange, readOnly, id, invalid }: ControlProps) {\n const { MediaPicker, mediaSrc } = useKitServices();\n const [open, setOpen] = React.useState(false);\n const [mediaOpen, setMediaOpen] = React.useState(false);\n const read = readIcon(value);\n\n const commit = (v: string | null) => {\n onChange(v);\n if (v && DOCK_ICON_NAME_SET.has(v)) pushRecent(v);\n setOpen(false);\n };\n\n const tile =\n read.kind === \"name\" ? (\n <Glyph name={read.name} className=\"size-4\" />\n ) : read.kind === \"upload\" ? (\n <img src={mediaSrc ? mediaSrc(read.url) : read.url} alt=\"\" className=\"size-4 object-contain\" />\n ) : read.kind === \"empty\" ? (\n <span className=\"size-3 rounded-kit-md border border-dashed border-[var(--kit-emphasis-line)]\" />\n ) : (\n <IconAlertTriangle className=\"size-3.5 text-kit-warning-fg\" stroke={1.5} aria-hidden />\n );\n const text =\n read.kind === \"name\"\n ? iconLabel(read.name)\n : read.kind === \"upload\"\n ? fileName(read.url)\n : read.kind === \"unknown\"\n ? `“${read.name}” isn't in the icon set`\n : read.kind === \"unreadable\"\n ? \"This value isn't an icon this picker can read\"\n : \"Choose an icon\";\n const warn = read.kind === \"unknown\" || read.kind === \"unreadable\";\n\n return (\n <>\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger\n render={\n <button\n id={id}\n type=\"button\"\n disabled={readOnly}\n aria-invalid={invalid || undefined}\n className={cn(\n \"flex h-8 w-full items-center gap-2.5 rounded-kit-md border border-kit-line-strong bg-kit-field-bg px-1 pr-2.5 text-left text-kit-sm transition-colors hover:border-kit-line-strong data-[popup-open]:border-kit-line-strong data-[popup-open]:bg-kit-field-bg\",\n invalid && \"border-[var(--kit-field-invalid)]\",\n )}\n />\n }\n >\n <span className=\"flex size-6 items-center justify-center rounded-kit-md border border-kit-line bg-kit-control-bg text-kit-fg\">{tile}</span>\n <span className={cn(\"min-w-0 flex-1 truncate\", warn ? \"text-kit-warning-fg\" : read.kind === \"empty\" ? \"text-kit-fg-3\" : \"text-kit-fg\")}>{text}</span>\n <IconChevronDown className=\"size-3.5 text-kit-fg-3\" stroke={1.5} aria-hidden />\n </PopoverTrigger>\n <PopoverContent className=\"w-[320px] p-2\" align=\"start\" aria-label={`${field.title}: choose an icon`}>\n <IconPicker\n field\n value={read.kind === \"name\" ? read.name : read.kind === \"empty\" ? undefined : \"\"}\n onPick={commit}\n onChooseMedia={\n MediaPicker\n ? () => {\n setOpen(false);\n setMediaOpen(true);\n }\n : undefined\n }\n />\n </PopoverContent>\n </Popover>\n {MediaPicker && mediaOpen ? (\n <MediaPicker open={mediaOpen} onOpenChange={setMediaOpen} accept={[\"svg\", \"image\"]} onPick={(assets) => assets[0]?.url && commit(assets[0].url)} />\n ) : null}\n </>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export * from "./c1";
|
|
2
2
|
export * from "./c2";
|
|
3
3
|
export { LinkControl, LinkField, LinkForm, LinkLine, SectionAnchorsProvider, type LinkTarget, type KitLinkServices, type SectionAnchor } from "./link";
|
|
4
|
-
export { ButtonControl, ButtonScreen } from "./button";
|
|
4
|
+
export { ButtonControl, ButtonLinkEditor, ButtonScreen } from "./button";
|
|
5
5
|
export declare function registerKitControls(): void;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { __exportAll } from "../_virtual/_rolldown/runtime.js";
|
|
2
2
|
import { LinkControl, LinkField, LinkForm, LinkLine, SectionAnchorsProvider } from "./link.js";
|
|
3
|
-
import { ButtonControl, ButtonScreen } from "./button.js";
|
|
3
|
+
import { ButtonControl, ButtonLinkEditor, ButtonScreen } from "./button.js";
|
|
4
4
|
import { CONTROLS } from "../engine/kit-field.js";
|
|
5
5
|
import { C1_ACTIONS, C1_CONTROLS, registerC1Controls } from "./c1.js";
|
|
6
6
|
import { C2_CONTROLS, registerC2Controls } from "./c2.js";
|
|
7
|
-
//#region src/
|
|
7
|
+
//#region src/controls/index.ts
|
|
8
8
|
/**
|
|
9
9
|
* The ported kit controls, and the one call that puts them in the engine's CONTROLS / ACTIONS tables (and the scale
|
|
10
10
|
* capsule into the number control). A registered type stops drawing the host's legacy control; a type nobody
|
|
@@ -12,6 +12,7 @@ import { C2_CONTROLS, registerC2Controls } from "./c2.js";
|
|
|
12
12
|
*/
|
|
13
13
|
var controls_exports = /* @__PURE__ */ __exportAll({
|
|
14
14
|
ButtonControl: () => ButtonControl,
|
|
15
|
+
ButtonLinkEditor: () => ButtonLinkEditor,
|
|
15
16
|
ButtonScreen: () => ButtonScreen,
|
|
16
17
|
C1_ACTIONS: () => C1_ACTIONS,
|
|
17
18
|
C1_CONTROLS: () => C1_CONTROLS,
|
|
@@ -32,6 +33,6 @@ function registerKitControls() {
|
|
|
32
33
|
CONTROLS.button = ButtonControl;
|
|
33
34
|
}
|
|
34
35
|
//#endregion
|
|
35
|
-
export { controls_exports, registerKitControls };
|
|
36
|
+
export { ButtonControl, ButtonLinkEditor, ButtonScreen, C1_ACTIONS, C1_CONTROLS, C2_CONTROLS, LinkControl, LinkField, LinkForm, LinkLine, SectionAnchorsProvider, controls_exports, registerC1Controls, registerC2Controls, registerKitControls };
|
|
36
37
|
|
|
37
38
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/controls/index.ts"],"sourcesContent":["/**\n * The ported kit controls, and the one call that puts them in the engine's CONTROLS / ACTIONS tables (and the scale\n * capsule into the number control). A registered type stops drawing the host's legacy control; a type nobody\n * registers keeps it. The kit barrel calls `registerKitControls()` once, so every host that imports the kit gets them.\n */\nimport { ButtonControl } from \"./button\";\nimport { LinkControl } from \"./link\";\nimport { registerC1Controls } from \"./c1\";\nimport { registerC2Controls } from \"./c2\";\nimport { CONTROLS } from \"../engine/kit-field\";\n\nexport * from \"./c1\";\nexport * from \"./c2\";\nexport { LinkControl, LinkField, LinkForm, LinkLine, SectionAnchorsProvider, type LinkTarget, type KitLinkServices, type SectionAnchor } from \"./link\";\nexport { ButtonControl, ButtonLinkEditor, ButtonScreen } from \"./button\";\n\nexport function registerKitControls() {\n registerC1Controls();\n registerC2Controls();\n CONTROLS.link = LinkControl;\n CONTROLS.button = ButtonControl;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgBA,SAAgB,sBAAsB;CACpC,mBAAmB;CACnB,mBAAmB;CACnB,SAAS,OAAO;CAChB,SAAS,SAAS;AACpB"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { JsonControl } from "./json.js";
|
|
2
2
|
import { CONTROLS } from "../engine/kit-field.js";
|
|
3
|
-
//#region src/
|
|
3
|
+
//#region src/controls/json-register.ts
|
|
4
4
|
/** Lane C3: the json field in the engine's dispatch table (one line per type; merge with other lanes by line). */
|
|
5
5
|
CONTROLS.json = JsonControl;
|
|
6
6
|
//#endregion
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-register.js","names":[],"sources":["../../src/controls/json-register.ts"],"sourcesContent":["/** Lane C3: the json field in the engine's dispatch table (one line per type; merge with other lanes by line). */\nimport { CONTROLS } from \"../engine/kit-field\";\nimport { JsonControl } from \"./json\";\n\nCONTROLS.json = JsonControl;\n"],"mappings":";;;;AAIA,SAAS,OAAO"}
|
|
@@ -2,7 +2,7 @@ import { useKitEnv } from "../context.js";
|
|
|
2
2
|
import { CodeDialogField, CodeSurface, jsonProblem } from "./code.js";
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { jsx } from "react/jsx-runtime";
|
|
5
|
-
//#region src/
|
|
5
|
+
//#region src/controls/json.tsx
|
|
6
6
|
/**
|
|
7
7
|
* JSON — the json field (DESIGN 8.21), on the code surface (code.tsx).
|
|
8
8
|
*
|
|
@@ -11,8 +11,18 @@ import { jsx } from "react/jsx-runtime";
|
|
|
11
11
|
* Text that does not parse is never written: the panel's Done refuses with "Invalid JSON · {reason}", the inline
|
|
12
12
|
* (document) surface keeps the last valid value and shows the reason under the code.
|
|
13
13
|
*/
|
|
14
|
-
/** The text a stored JSON value is edited as.
|
|
15
|
-
|
|
14
|
+
/** The text a stored JSON value is edited as. A stored string that is JSON text stays as written; any other string is a
|
|
15
|
+
* JSON string value, so it reads as its literal ("hello" → `"hello"`), never as "Invalid JSON". */
|
|
16
|
+
var jsonText = (v) => {
|
|
17
|
+
if (v == null || v === "") return "";
|
|
18
|
+
if (typeof v !== "string") return JSON.stringify(v, null, 2);
|
|
19
|
+
try {
|
|
20
|
+
JSON.parse(v);
|
|
21
|
+
return v;
|
|
22
|
+
} catch {
|
|
23
|
+
return JSON.stringify(v);
|
|
24
|
+
}
|
|
25
|
+
};
|
|
16
26
|
var parse = (text) => text.trim() ? JSON.parse(text) : null;
|
|
17
27
|
function JsonControl({ field, value, onChange, readOnly, id, invalid }) {
|
|
18
28
|
const { variant } = useKitEnv();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json.js","names":[],"sources":["../../src/controls/json.tsx"],"sourcesContent":["/**\n * JSON — the json field (DESIGN 8.21), on the code surface (code.tsx).\n *\n * Values: whatever JSON the field holds (an object, a list, a number, or a JSON string a textarea wrote). An edit is\n * written PARSED, the way the classic JsonField writes it, and an emptied box writes null; the backend takes both.\n * Text that does not parse is never written: the panel's Done refuses with \"Invalid JSON · {reason}\", the inline\n * (document) surface keeps the last valid value and shows the reason under the code.\n */\nimport * as React from \"react\";\nimport { useKitEnv } from \"../context\";\nimport type { ControlProps } from \"../types\";\nimport { CodeDialogField, CodeSurface, jsonProblem } from \"./code\";\n\n/** The text a stored JSON value is edited as. A stored string that is JSON text stays as written; any other string is a\n * JSON string value, so it reads as its literal (\"hello\" → `\"hello\"`), never as \"Invalid JSON\". */\nconst jsonText = (v: unknown): string => {\n if (v == null || v === \"\") return \"\";\n if (typeof v !== \"string\") return JSON.stringify(v, null, 2);\n try {\n JSON.parse(v);\n return v;\n } catch {\n return JSON.stringify(v);\n }\n};\nconst parse = (text: string): unknown => (text.trim() ? JSON.parse(text) : null);\n\nexport function JsonControl({ field, value, onChange, readOnly, id, invalid }: ControlProps) {\n const { variant } = useKitEnv();\n const text = jsonText(value);\n if (variant === \"document\") return <InlineJson id={id} value={value} text={text} onChange={onChange} readOnly={readOnly} invalid={invalid} />;\n return (\n <CodeDialogField\n kind=\"json\"\n id={id}\n title={field.title}\n description={field.description || undefined}\n text={text}\n readOnly={readOnly}\n invalid={invalid}\n onDone={(draft) => {\n if (draft === text) return null; // nothing edited: Done closes even over a stored string that isn't JSON\n const why = jsonProblem(draft);\n if (why) return `Invalid JSON · ${why}`;\n if (draft !== text) onChange(parse(draft));\n return null;\n }}\n />\n );\n}\n\n/** The document variant: the surface inline over a draft that survives invalid intermediates. */\nfunction InlineJson({ id, value, text, onChange, readOnly, invalid }: { id: string; value: unknown; text: string; onChange: (v: unknown) => void; readOnly?: boolean; invalid?: boolean }) {\n const [draft, setDraft] = React.useState(text);\n const [mine, setMine] = React.useState<unknown>(undefined);\n const [seen, setSeen] = React.useState(value);\n // a value set from elsewhere (undo, another editor) replaces the draft; our own writes keep the author's text\n if (value !== seen) {\n setSeen(value);\n if (value !== mine) setDraft(text);\n }\n return (\n <CodeSurface\n kind=\"json\"\n id={id}\n invalid={invalid}\n readOnly={readOnly}\n value={draft}\n onChange={(next) => {\n setDraft(next);\n if (jsonProblem(next)) return;\n const parsed = parse(next);\n setMine(parsed);\n onChange(parsed);\n }}\n />\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;AAeA,IAAM,YAAY,MAAuB;CACvC,IAAI,KAAK,QAAQ,MAAM,IAAI,OAAO;CAClC,IAAI,OAAO,MAAM,UAAU,OAAO,KAAK,UAAU,GAAG,MAAM,CAAC;CAC3D,IAAI;EACF,KAAK,MAAM,CAAC;EACZ,OAAO;CACT,QAAQ;EACN,OAAO,KAAK,UAAU,CAAC;CACzB;AACF;AACA,IAAM,SAAS,SAA2B,KAAK,KAAK,IAAI,KAAK,MAAM,IAAI,IAAI;AAE3E,SAAgB,YAAY,EAAE,OAAO,OAAO,UAAU,UAAU,IAAI,WAAyB;CAC3F,MAAM,EAAE,YAAY,UAAU;CAC9B,MAAM,OAAO,SAAS,KAAK;CAC3B,IAAI,YAAY,YAAY,OAAO,oBAAC,YAAD;EAAgB;EAAW;EAAa;EAAgB;EAAoB;EAAmB;CAAU,CAAA;CAC5I,OACE,oBAAC,iBAAD;EACE,MAAK;EACD;EACJ,OAAO,MAAM;EACb,aAAa,MAAM,eAAe,KAAA;EAC5B;EACI;EACD;EACT,SAAS,UAAU;GACjB,IAAI,UAAU,MAAM,OAAO;GAC3B,MAAM,MAAM,YAAY,KAAK;GAC7B,IAAI,KAAK,OAAO,kBAAkB;GAClC,IAAI,UAAU,MAAM,SAAS,MAAM,KAAK,CAAC;GACzC,OAAO;EACT;CACD,CAAA;AAEL;;AAGA,SAAS,WAAW,EAAE,IAAI,OAAO,MAAM,UAAU,UAAU,WAAgI;CACzL,MAAM,CAAC,OAAO,YAAY,MAAM,SAAS,IAAI;CAC7C,MAAM,CAAC,MAAM,WAAW,MAAM,SAAkB,KAAA,CAAS;CACzD,MAAM,CAAC,MAAM,WAAW,MAAM,SAAS,KAAK;CAE5C,IAAI,UAAU,MAAM;EAClB,QAAQ,KAAK;EACb,IAAI,UAAU,MAAM,SAAS,IAAI;CACnC;CACA,OACE,oBAAC,aAAD;EACE,MAAK;EACD;EACK;EACC;EACV,OAAO;EACP,WAAW,SAAS;GAClB,SAAS,IAAI;GACb,IAAI,YAAY,IAAI,GAAG;GACvB,MAAM,SAAS,MAAM,IAAI;GACzB,QAAQ,MAAM;GACd,SAAS,MAAM;EACjB;CACD,CAAA;AAEL"}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { cn } from "../lib/cn.js";
|
|
2
|
-
import { isObj } from "../lib/path.js";
|
|
3
2
|
import { useKitEnv, useKitServices } from "../context.js";
|
|
3
|
+
import { isObj } from "../lib/path.js";
|
|
4
4
|
import { Button, IconButton } from "../ui/button.js";
|
|
5
5
|
import { Switch } from "../ui/controls.js";
|
|
6
6
|
import { Menu, MenuContent, MenuItem, MenuTrigger, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, Tooltip } from "../ui/overlay.js";
|
|
7
7
|
import { Input } from "../ui/input.js";
|
|
8
8
|
import { Select } from "../ui/select.js";
|
|
9
9
|
import * as React from "react";
|
|
10
|
-
import { IconAdjustmentsHorizontal, IconArrowUpRight, IconAt, IconCheck, IconChevronDown, IconExternalLink, IconFile, IconFileDatabase, IconFolderOpen, IconHash, IconLink, IconMail, IconPaperclip, IconPhone, IconWorld, IconX } from "@tabler/icons-react";
|
|
11
10
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
12
|
-
|
|
11
|
+
import { IconAdjustmentsHorizontal, IconArrowUpRight, IconAt, IconCheck, IconChevronDown, IconExternalLink, IconFile, IconFileDatabase, IconFolderOpen, IconHash, IconLink, IconMail, IconPaperclip, IconPhone, IconWorld, IconX } from "@tabler/icons-react";
|
|
12
|
+
//#region src/controls/link.tsx
|
|
13
13
|
/**
|
|
14
14
|
* LINK — the ONE link element of the product (V2 HEAD kit/controls/link.tsx, DESIGN §8.7, CPO D43 · D48 · D57).
|
|
15
15
|
*
|
|
@@ -729,7 +729,7 @@ function LinkPicker({ value, onChange, onPick, onEnter, onEscape, autoFocus, sta
|
|
|
729
729
|
side: "bottom",
|
|
730
730
|
sideOffset: 4,
|
|
731
731
|
"data-kit-link-list": "",
|
|
732
|
-
className: "w-[max(var(--anchor-width),280px)] max-w-[min(420px,calc(100vw-24px))] p-1",
|
|
732
|
+
className: "w-[max(var(--anchor-width),280px)] max-w-[min(420px,calc(100vw-24px))] !bg-kit-surface p-1 shadow-kit-lg",
|
|
733
733
|
children: list
|
|
734
734
|
})]
|
|
735
735
|
}),
|
|
@@ -1110,7 +1110,7 @@ function LinkField({ value, onChange: write, valueShape, id: idProp, "aria-label
|
|
|
1110
1110
|
type: "button",
|
|
1111
1111
|
disabled: readOnly,
|
|
1112
1112
|
onClick: () => setEditing(true),
|
|
1113
|
-
"aria-label": has ? `${label}: ${
|
|
1113
|
+
"aria-label": has ? `${label}: ${linkText(v)}. Edit link` : `Add ${label.toLowerCase()}`,
|
|
1114
1114
|
"aria-invalid": invalid || void 0,
|
|
1115
1115
|
className: "flex h-full min-w-0 flex-1 items-center px-2.5 text-left outline-none disabled:cursor-default",
|
|
1116
1116
|
children: /* @__PURE__ */ jsx(LinkLine, {
|
|
@@ -1181,6 +1181,6 @@ function LinkControl({ value, onChange, readOnly, id, field, invalid }) {
|
|
|
1181
1181
|
});
|
|
1182
1182
|
}
|
|
1183
1183
|
//#endregion
|
|
1184
|
-
export { LinkControl, LinkField, LinkForm, LinkLine, LinkQuickEdit, SectionAnchorsProvider, TARGET_KEYS, describeLink, finalizeLink, findTarget, hasLink, hrefOf, linkText, normLink, storedLink, useLinkTargets };
|
|
1184
|
+
export { LINK_TYPES, LinkControl, LinkField, LinkForm, LinkLine, LinkOptions, LinkPicker, LinkPopoverBody, LinkQuickEdit, REL_ITEMS, SectionAnchorsProvider, TARGET_KEYS, describeLink, detectType, fileTarget, finalizeLink, findTarget, hasLink, hrefOf, linkIcon, linkProblem, linkShapeOf, linkText, normLink, storedLink, useLinkTargets, withTarget, withText };
|
|
1185
1185
|
|
|
1186
1186
|
//# sourceMappingURL=link.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"link.js","names":[],"sources":["../../src/controls/link.tsx"],"sourcesContent":["/**\n * LINK — the ONE link element of the product (V2 HEAD kit/controls/link.tsx, DESIGN §8.7, CPO D43 · D48 · D57).\n *\n * - <LinkForm> Type (Page · CMS item · URL · Email · Phone · Section · File) → the target for that type (search over\n * the host's pages and CMS items, paste detection, URL / email / phone / #anchor validation; File =\n * the host's media library) → Section on the picked page → options (new tab · rel · email subject).\n * - <LinkPopoverBody> the link panel: what it links to now + LinkForm + Remove link · Cancel · Apply.\n * - <LinkField> a link at rest (one bordered row): click edits in place (quick edit), the sliders icon opens the panel.\n * - <LinkPicker> the target input inside all of the above.\n * - <LinkLine> how a link READS at rest: page icon + title + path · external icon + domain · mail / phone.\n *\n * Where the targets come from. The kit never fetches: the host hands its own link-target query in as a React hook,\n * `KitServices.useLinkTargets` (KitLinkServices below), and the media library as `KitServices.MediaPicker`. With no hook a\n * page link is typed as a path and the list says so in words; with no media picker the File type is not offered.\n * Section anchors come from the host that knows the page (SectionAnchorsProvider); without one a section is typed (#faq).\n *\n * Stored shape (prod `link`, adapters/values.ts linkToProd / linkFromProd). The kit value is what the field already\n * stores: a STRING href stays a string (legacy fields and the sites that read `href={link}`), an object stays an object.\n * An empty field takes `field.valueShape` and, with none, the string (prod LinkField's default). In the string shape the\n * options (new tab, rel) need the object, so they hide — V2's `valueShape=\"string\"`. An object never carries `target`\n * (derived from newTab), `rel: \"follow\"` (follow = no rel) or `newTab: false`, so it reads back exactly as written.\n *\n * Deviations from V2, each because prod has no source for it: no \"From this entry\" {{token}} targets (no binding store\n * behind them), no seeded page anchors, no fabricated CDN address for a file (a file without a public url is refused).\n */\nimport * as React from \"react\";\nimport {\n IconAdjustmentsHorizontal, IconArrowUpRight, IconAt, IconCheck, IconChevronDown, IconExternalLink, IconFile, IconFileDatabase,\n IconFolderOpen, IconHash, IconLink, IconMail, IconPaperclip, IconPhone, IconWorld, IconX,\n} from \"@tabler/icons-react\";\nimport { cn } from \"../lib/cn\";\nimport { isObj } from \"../lib/path\";\nimport { useKitEnv, useKitServices, type KitMediaAsset, type KitServices } from \"../context\";\nimport { Button, IconButton } from \"../ui/button\";\nimport { Input } from \"../ui/input\";\nimport { Switch } from \"../ui/controls\";\nimport { Select } from \"../ui/select\";\nimport { Menu, MenuContent, MenuItem, MenuTrigger, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, Tooltip } from \"../ui/overlay\";\nimport type { ControlProps } from \"../types\";\n\nexport type LinkType = \"page\" | \"url\" | \"section\" | \"email\" | \"phone\" | \"file\" | \"entry\";\nexport type LinkRel = \"follow\" | \"nofollow\" | \"ugc\" | \"sponsored\";\nexport type ButtonStyle = \"primary\" | \"secondary\" | \"outline\" | \"link\";\nexport interface LinkValue {\n type?: LinkType;\n href: string;\n /** button label / link text */\n label?: string;\n /** resolved title of the target (page or entry name) */\n title?: string;\n pageId?: string;\n entryId?: string;\n anchor?: string;\n assetId?: string;\n email?: string;\n subject?: string;\n phone?: string;\n /** legacy target: read as newTab, never written */\n target?: \"_self\" | \"_blank\";\n newTab?: boolean;\n rel?: LinkRel;\n /* button-only (controls/button.tsx) */\n style?: ButtonStyle;\n variant?: string;\n size?: \"sm\" | \"md\" | \"lg\";\n arrow?: boolean;\n icon?: string;\n fullWidth?: boolean;\n}\n\n/* ── Host services ───────────────────────────────────────────────────── */\n/** A place a link can point at, as the host lists it. */\nexport interface LinkTarget {\n id: string;\n title: string;\n /** the public path (\"/about\", \"/blog/hello\") or a file's url */\n href: string;\n kind: \"page\" | \"entry\" | \"file\" | \"section\";\n /** collection name for an entry, file kind for a file */\n meta?: string;\n /** list group: \"Pages\", the collection's name, \"Files\", \"On this page\" */\n group: string;\n /** draft · published · scheduled · archived … (shown when it is not live) */\n status?: string;\n /** \"#faq\" anchors on that page, when the host knows them */\n anchors?: string[];\n /** a section without an anchor yet gets it when picked */\n onChoose?: () => void;\n}\n/**\n * The link services a host provides next to KitServices (registerKitServices / KitServicesProvider take them as is).\n * `useLinkTargets` is a React HOOK (called on every render of a link control), so a host passes the same function for\n * the life of the form.\n */\nexport type KitLinkServices = Pick<KitServices, \"useLinkTargets\">;\ntype LinkHost = { targets: LinkTarget[]; loading: boolean; error?: string; unavailable: boolean };\nconst NO_TARGETS: LinkTarget[] = [];\nconst useNoTargets = () => ({ targets: NO_TARGETS, loading: false, error: undefined as string | undefined });\n\n/** The host's pages, CMS items (and files, when it lists them). */\nexport function useLinkTargets(): LinkHost {\n const svc = useKitServices();\n const useHost = svc.useLinkTargets ?? useNoTargets;\n const r = useHost();\n return { targets: r.targets ?? NO_TARGETS, loading: !!r.loading, error: r.error, unavailable: !svc.useLinkTargets };\n}\n\n/** A section on the page being edited that a link can jump to (`id` on the block). */\nexport interface SectionAnchor {\n /** \"#faq\" */\n anchor: string;\n /** what a person reads: the block's name */\n label: string;\n /** the block has no anchor yet: give it this one when a link picks it */\n ensure?: () => void;\n}\nconst SectionAnchorsCtx = React.createContext<SectionAnchor[] | null>(null);\n/** The host that knows the page being edited lists its section anchors, so the Section type is a pick. */\nexport function SectionAnchorsProvider({ anchors, children }: { anchors: SectionAnchor[]; children: React.ReactNode }) {\n return <SectionAnchorsCtx.Provider value={anchors}>{children}</SectionAnchorsCtx.Provider>;\n}\nfunction useSectionTargets(): LinkTarget[] {\n const anchors = React.useContext(SectionAnchorsCtx);\n return React.useMemo(\n () =>\n (anchors ?? []).map((a) => ({\n id: `section:${a.anchor}`,\n title: a.label,\n href: a.anchor.startsWith(\"#\") ? a.anchor : `#${a.anchor}`,\n kind: \"section\" as const,\n group: \"On this page\",\n onChoose: a.ensure,\n })),\n [anchors],\n );\n}\n\n/** A file from the media library as a link target, or the reason it can't be one. */\nexport function fileTarget(a: Pick<KitMediaAsset, \"id\" | \"name\" | \"url\">): LinkTarget | { problem: string } {\n if (!a.url || a.url.startsWith(\"blob:\")) return { problem: \"This file has no public address yet. Wait for the upload to finish, then pick it again.\" };\n const name = a.name || fileName(a.url);\n return { id: a.id, title: name, href: a.url, kind: \"file\", meta: name.split(\".\").pop()?.toUpperCase(), group: \"Files\" };\n}\n\n/* ── Value helpers ───────────────────────────────────────────────────── */\nexport const normLink = (v: unknown): LinkValue => {\n const o: LinkValue = typeof v === \"string\" ? { href: v } : isObj(v) ? ({ ...(v as object), href: typeof v.href === \"string\" ? v.href : \"\" } as LinkValue) : { href: \"\" };\n if (o.newTab === undefined && o.target === \"_blank\") o.newTab = true;\n if (!o.type) o.type = detectType(o.href);\n return o;\n};\n\nexport function detectType(raw: string): LinkType {\n const s = raw.trim();\n if (!s) return \"page\";\n if (s.startsWith(\"#\")) return \"section\";\n if (/^mailto:/i.test(s) || /^[^\\s@/]+@[^\\s@]+\\.[^\\s@]+$/.test(s)) return \"email\";\n if (/^tel:/i.test(s) || /^\\+?[\\d\\s().-]{7,}$/.test(s)) return \"phone\";\n if (/\\.(pdf|zip|docx?|csv)$/i.test(s)) return \"file\";\n if (/^https?:\\/\\//i.test(s) || /^www\\./i.test(s) || /^[a-z0-9-]+(\\.[a-z0-9-]+)+(\\/|$)/i.test(s)) return \"url\";\n return \"page\";\n}\n\nexport const LINK_TYPES: { type: LinkType; label: string; icon: React.ReactNode; placeholder: string; target: string }[] = [\n { type: \"page\", label: \"Page\", icon: <IconFile stroke={1.5} />, placeholder: \"Search pages and CMS items, or paste a link\", target: \"Page\" },\n { type: \"entry\", label: \"CMS item\", icon: <IconFileDatabase stroke={1.5} />, placeholder: \"Search CMS items\", target: \"CMS item\" },\n { type: \"url\", label: \"URL\", icon: <IconWorld stroke={1.5} />, placeholder: \"https://example.com\", target: \"Address\" },\n { type: \"email\", label: \"Email\", icon: <IconAt stroke={1.5} />, placeholder: \"name@company.com\", target: \"Email address\" },\n { type: \"phone\", label: \"Phone\", icon: <IconPhone stroke={1.5} />, placeholder: \"+1 541 555 0182\", target: \"Phone number\" },\n { type: \"section\", label: \"Section\", icon: <IconHash stroke={1.5} />, placeholder: \"#section-on-this-page\", target: \"Section on this page\" },\n { type: \"file\", label: \"File\", icon: <IconPaperclip stroke={1.5} />, placeholder: \"Search files\", target: \"File\" },\n];\nconst typeMeta = (t?: string) => LINK_TYPES.find((x) => x.type === t) ?? LINK_TYPES[0];\n\n/** The target a value points at: by id first, then by an exact path (\"/about\" typed by hand still reads as About). */\nexport function findTarget(targets: LinkTarget[], v: LinkValue): LinkTarget | undefined {\n const byId = targets.find((t) => (v.pageId && t.id === v.pageId) || (v.entryId && t.id === v.entryId) || (v.assetId && t.id === v.assetId));\n if (byId) return byId;\n if (v.type === \"section\") return v.href ? targets.find((t) => t.kind === \"section\" && t.href === (v.href.startsWith(\"#\") ? v.href : `#${v.href}`)) : undefined;\n if (!v.href || (v.type !== \"page\" && v.type !== \"entry\" && v.type !== \"file\")) return undefined;\n if (v.type === \"file\") {\n const f = targets.find((t) => t.kind === \"file\" && t.href === v.href);\n // a file picked from the library reads as the file by the name stored with it\n return f ?? (v.title ? { id: v.assetId ?? v.href, title: v.title, href: v.href, kind: \"file\", group: \"Files\" } : undefined);\n }\n const path = v.href.replace(/[?#].*$/, \"\").replace(/\\/$/, \"\") || \"/\";\n return targets.find((t) => t.kind !== \"file\" && t.kind !== \"section\" && t.href === path);\n}\n\n/** The final href for a link value. */\nexport function hrefOf(v: LinkValue): string {\n switch (v.type) {\n case \"email\": {\n const addr = (v.email ?? v.href).replace(/^mailto:/i, \"\").replace(/\\?.*$/, \"\");\n return addr ? `mailto:${addr}${v.subject ? `?subject=${encodeURIComponent(v.subject)}` : \"\"}` : \"\";\n }\n case \"phone\": {\n const n = (v.phone ?? v.href).replace(/^tel:/i, \"\").replace(/[^\\d+]/g, \"\");\n return n ? `tel:${n}` : \"\";\n }\n case \"section\":\n return v.href.startsWith(\"#\") ? v.href : v.href ? `#${v.href}` : \"\";\n default: {\n // idempotent: a stored href already carries its anchor, so a changed or removed anchor replaces it\n const base = v.anchor !== undefined ? v.href.replace(/#.*$/, \"\") : v.href;\n return `${base}${v.anchor && v.anchor !== \"none\" ? v.anchor : \"\"}`;\n }\n }\n}\n\nconst BAD_URL = \"Enter a full address, like https://example.com.\";\n/** Why a link can't be saved yet, in plain words. Undefined when it is fine (or empty). */\nexport function linkProblem(v: LinkValue): string | undefined {\n if (!hasLink(v)) return undefined;\n const raw = (v.type === \"email\" ? v.email ?? v.href : v.type === \"phone\" ? v.phone ?? v.href : v.href).trim();\n if (/^(javascript|data|vbscript):/i.test(raw.replace(/[\\u0000- ]/g, \"\"))) return \"Script links aren't allowed.\";\n switch (v.type) {\n case \"url\": {\n if (raw.startsWith(\"/\") || raw.startsWith(\"#\")) return undefined;\n try {\n const u = new URL(/^[a-z][a-z0-9+.-]*:/i.test(raw) ? raw : `https://${raw}`);\n if (!/^https?:$/.test(u.protocol)) return BAD_URL;\n return /\\.[a-z]{2,}$/i.test(u.hostname) || u.hostname === \"localhost\" ? undefined : BAD_URL;\n } catch {\n return BAD_URL;\n }\n }\n case \"email\":\n return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]{2,}$/.test(raw.replace(/^mailto:/i, \"\").replace(/\\?.*$/, \"\")) ? undefined : \"Enter an email address, like name@company.com.\";\n case \"phone\":\n return raw.replace(/^tel:/i, \"\").replace(/\\D/g, \"\").length >= 7 ? undefined : \"Enter a phone number with at least 7 digits.\";\n case \"section\":\n return /^#?[A-Za-z][\\w-]*$/.test(raw) ? undefined : \"Use letters, numbers and dashes, like #faq.\";\n case \"page\":\n case \"entry\":\n return raw.startsWith(\"/\") || raw.startsWith(\"#\") || v.pageId || v.entryId ? undefined : \"Pick a page, or start a path with /, like /about.\";\n default:\n return undefined;\n }\n}\n\n/** One list for every link editor (dropdown, never a segmented row — D40). */\nexport const REL_ITEMS: { value: LinkRel; label: string; description: string }[] = [\n { value: \"follow\", label: \"Do-follow\", description: \"Normal link. Search engines follow it.\" },\n { value: \"nofollow\", label: \"No-follow\", description: \"Search engines don't follow or credit it.\" },\n { value: \"sponsored\", label: \"Sponsored\", description: \"Paid, affiliate or ad link.\" },\n { value: \"ugc\", label: \"UGC\", description: \"Link added by users, e.g. comments.\" },\n];\n\nexport const hasLink = (v: LinkValue) => !!(v.href || v.email || v.phone);\nexport const TARGET_KEYS = { title: undefined, pageId: undefined, entryId: undefined, assetId: undefined, anchor: undefined } as const;\n\n/** The value a picked target produces (keeps label, style and options). */\nexport function withTarget(v: LinkValue, t: LinkTarget): LinkValue {\n return {\n ...v,\n ...TARGET_KEYS,\n email: undefined,\n phone: undefined,\n subject: undefined,\n type: t.kind === \"file\" ? \"file\" : t.kind === \"entry\" ? \"entry\" : t.kind === \"section\" ? \"section\" : \"page\",\n href: t.href,\n title: t.title,\n pageId: t.kind === \"page\" ? t.id : undefined,\n entryId: t.kind === \"entry\" ? t.id : undefined,\n assetId: t.kind === \"file\" ? t.id : undefined,\n };\n}\n/** The value typed text produces (auto-detects URL / email / phone / #section unless the type was chosen). */\nexport function withText(v: LinkValue, s: string, type?: LinkType): LinkValue {\n const t = type ?? detectType(s);\n const n: LinkValue = { ...v, ...TARGET_KEYS, type: t, email: undefined, phone: undefined };\n if (t === \"email\") Object.assign(n, { email: s.replace(/^mailto:/i, \"\"), href: s });\n else if (t === \"phone\") Object.assign(n, { phone: s.replace(/^tel:/i, \"\"), href: s });\n else n.href = s;\n return n;\n}\n/** Clean a value before it is stored: add https:// to bare domains, refuse script URLs, store the href the site renders. */\nexport function finalizeLink(v: LinkValue): LinkValue | null {\n const out: LinkValue = { ...v };\n if (/^(javascript|data|vbscript):/i.test(out.href.replace(/[\\u0000- ]/g, \"\"))) return null;\n if (out.type === \"url\" && out.href && !/^(https?:|\\/|#)/.test(out.href)) out.href = `https://${out.href.replace(/^\\/+/, \"\")}`;\n // the stored href is the one the site renders (mailto:, tel:, #anchor); every consumer reads `href` as is\n if (hasLink(out)) out.href = hrefOf(out);\n return out;\n}\n/**\n * The object as prod stores it, keyed like the value it replaces (`original`), so an edit changes only what was edited:\n * no undefined keys; no `rel: \"follow\"` (follow is no rel: the backend normalises it away and a button refuses it); no\n * `newTab: false` and no `target` unless the stored value had that key (a stored `target` is kept in sync with newTab,\n * and is then the one that carries it).\n */\nexport function storedLink<T extends LinkValue>(v: T, original?: unknown): T {\n const had = (k: string) => isObj(original) && k in original;\n const out: Record<string, unknown> = {};\n for (const [k, x] of Object.entries(v)) {\n if (x === undefined || k === \"target\") continue;\n if (k === \"rel\" && x === \"follow\") continue;\n if (k === \"newTab\" && !had(\"newTab\") && (x === false || had(\"target\"))) continue;\n out[k] = x;\n }\n if (had(\"target\")) out.target = v.newTab ? \"_blank\" : \"_self\";\n return out as T;\n}\n/** Text the picker's input shows for a value that has no picked target. */\nconst inputText = (v: LinkValue) =>\n v.type === \"email\" ? (v.email ?? v.href.replace(/^mailto:/i, \"\")) : v.type === \"phone\" ? (v.phone ?? v.href.replace(/^tel:/i, \"\")) : v.href;\n\nconst STATUS_LABEL: Record<string, string> = { draft: \"Draft\", changed: \"Edited\", scheduled: \"Scheduled\", review: \"In review\", archived: \"Archived\" };\n\n/* ── How a link reads ───────────────────────────────────────────────── */\nexport function linkIcon(v: LinkValue, target?: LinkTarget): React.ReactNode {\n if (!hasLink(v)) return <IconLink stroke={1.5} />;\n if (target) return target.kind === \"entry\" ? <IconFileDatabase stroke={1.5} /> : target.kind === \"file\" ? <IconPaperclip stroke={1.5} /> : target.kind === \"section\" ? <IconHash stroke={1.5} /> : <IconFile stroke={1.5} />;\n switch (v.type) {\n case \"url\": return <IconExternalLink stroke={1.5} />;\n case \"email\": return <IconMail stroke={1.5} />;\n case \"phone\": return <IconPhone stroke={1.5} />;\n case \"section\": return <IconHash stroke={1.5} />;\n case \"file\": return <IconPaperclip stroke={1.5} />;\n case \"entry\": return <IconFileDatabase stroke={1.5} />;\n default: return <IconFile stroke={1.5} />;\n }\n}\n/** Primary + secondary text: page title + path · domain + rest of the URL · address · number. */\nexport function describeLink(v: LinkValue, target?: LinkTarget): { primary: string; secondary?: string } {\n if (!hasLink(v)) return { primary: \"\" };\n const anchor = v.anchor && v.anchor !== \"none\" ? v.anchor : \"\";\n if (target) return { primary: target.title, secondary: target.kind === \"section\" ? `${target.href} on this page` : target.kind === \"file\" ? fileKind(target) : `${target.href}${anchor}` };\n switch (v.type) {\n case \"url\": {\n try {\n const u = new URL(/^https?:/i.test(v.href) ? v.href : `https://${v.href}`);\n const rest = `${u.pathname === \"/\" ? \"\" : u.pathname}${u.search}${u.hash}`;\n return { primary: u.hostname.replace(/^www\\./, \"\"), secondary: rest || undefined };\n } catch {\n return { primary: v.href };\n }\n }\n case \"email\": return { primary: v.email ?? v.href.replace(/^mailto:/i, \"\").replace(/\\?.*$/, \"\"), secondary: v.subject ? `Subject: ${v.subject}` : undefined };\n case \"phone\": return { primary: v.phone ?? v.href.replace(/^tel:/i, \"\") };\n case \"section\": return { primary: v.href, secondary: \"On this page\" };\n // a stored href already carries its anchor (finalizeLink)\n default: return { primary: v.title || v.href, secondary: v.title ? v.href : undefined };\n }\n}\n/** \"PDF file\": the name is already the title */\nconst fileKind = (t: LinkTarget) => `${t.meta ?? (fileName(t.href).split(\".\").pop() ?? \"\").toUpperCase()} file`.trim();\nfunction fileName(href: string) {\n const last = href.replace(/[?#].*$/, \"\").split(\"/\").pop() ?? href;\n try {\n return decodeURIComponent(last);\n } catch {\n return last;\n }\n}\n/** What a person reads for a link (one string — menus, aria labels, history). */\nexport const linkText = (v: LinkValue) => (hasLink(v) ? v.title || describeLink(v).primary : \"\");\n\n/** A link at rest: icon · title (fg) · path (fg-3) · new-tab mark. Empty → \"Add link\". */\nexport function LinkLine({ v, target, placeholder = \"Add link\", className }: { v: LinkValue; target?: LinkTarget; placeholder?: string; className?: string }) {\n const d = describeLink(v, target);\n const empty = !hasLink(v);\n return (\n <span className={cn(\"flex min-w-0 flex-1 items-center gap-2\", className)}>\n <span className={cn(\"flex shrink-0 [&_svg]:size-4\", empty ? \"text-kit-fg-3\" : \"text-kit-fg-2\")} aria-hidden>{linkIcon(v, target)}</span>\n <span className={cn(\"min-w-0 shrink truncate text-kit-sm\", empty ? \"text-kit-fg-3\" : \"text-kit-fg\")}>{empty ? placeholder : d.primary}</span>\n {d.secondary ? <span className=\"min-w-0 flex-1 truncate text-kit-xs text-kit-fg-3\">{d.secondary}</span> : <span className=\"flex-1\" />}\n {!empty && v.newTab ? (\n <span className=\"inline-flex shrink-0 items-center gap-0.5 text-kit-2xs text-kit-fg-3\">\n <IconArrowUpRight className=\"size-3\" stroke={1.5} aria-hidden />\n New tab\n </span>\n ) : null}\n </span>\n );\n}\n\n/* ── The picker: ONE link input for the whole product ───────────────── */\ntype Row = { key: string; group: string; target: LinkTarget };\n\n/** While the media library is open from a picker, focus sits in its dialog: a quick edit must not close under it. */\nlet libraryOpen = false;\n/** Marks the floating results list, so a quick edit losing focus to it is not \"focus left the editor\". */\nconst LIST_ATTR = \"data-kit-link-list\";\n\nexport interface LinkPickerProps {\n value: LinkValue;\n /** every change: typed text, a picked target, a cleared value */\n onChange: (v: LinkValue) => void;\n /** a target was chosen from the list (quick editors commit here) */\n onPick?: (v: LinkValue) => void;\n /** Enter with no list row active */\n onEnter?: (v: LinkValue) => void;\n /** Escape with the list closed */\n onEscape?: () => void;\n autoFocus?: boolean;\n /** open straight into search (quick edit), even when a target is picked */\n startSearching?: boolean;\n id?: string;\n \"aria-label\"?: string;\n size?: \"sm\" | \"md\";\n /** no border of its own — it sits inside a unit that already draws one (button field) */\n bare?: boolean;\n /** the host shows its own type control (link panel): hide the inline type menu and search only this type */\n lockedType?: LinkType;\n /** results render in the flow under the input instead of a floating list — panels/popovers, never over them */\n inlineList?: boolean;\n /** the link types this place allows. Default: all of them */\n types?: LinkType[];\n /** the value can't be saved as it is (shown as the field's error state) */\n invalid?: boolean;\n \"aria-describedby\"?: string;\n className?: string;\n}\n\nexport function LinkPicker({\n value, onChange, onPick, onEnter, onEscape, autoFocus, startSearching, id, \"aria-label\": ariaLabel = \"Link to\", size = \"md\", bare, lockedType,\n inlineList, types, invalid, \"aria-describedby\": describedBy, className,\n}: LinkPickerProps) {\n const v = normLink(value);\n const host = useLinkTargets();\n const sections = useSectionTargets();\n const { MediaPicker } = useKitServices();\n const targets = React.useMemo(() => [...host.targets, ...sections], [host.targets, sections]);\n const picked = findTarget(targets, v);\n const [library, setLibraryState] = React.useState(false);\n const setLibrary = (o: boolean) => {\n libraryOpen = o;\n setLibraryState(o);\n };\n React.useEffect(() => () => void (libraryOpen = false), []);\n const [fileProblem, setFileProblem] = React.useState<string>();\n const [searching, setSearching] = React.useState(!!startSearching || !picked);\n const [text, setText] = React.useState(() => (picked ? \"\" : inputText(v)));\n const [manualTypeState, setManualType] = React.useState<LinkType | null>(null);\n const manualType = lockedType ?? manualTypeState;\n const [open, setOpen] = React.useState(false);\n const [active, setActive] = React.useState(-1);\n const inputRef = React.useRef<HTMLInputElement>(null);\n const wrapRef = React.useRef<HTMLDivElement>(null);\n const listId = React.useId();\n const type = manualType ?? v.type ?? \"page\";\n const meta = typeMeta(manualType ?? (searching && !text ? \"page\" : v.type));\n const showChip = !!picked && !searching;\n\n React.useEffect(() => {\n if (autoFocus)\n requestAnimationFrame(() => {\n inputRef.current?.focus({ preventScroll: true });\n inputRef.current?.select(); // quick edit: typing replaces, paste replaces\n });\n }, [autoFocus]);\n\n /* rows: the host's pages + every collection's entries (+ files when it lists them) */\n const q = text.trim().toLowerCase().replace(/^[/#]/, \"\");\n const searchable = type === \"page\" || type === \"entry\" || type === \"file\" || (type === \"section\" && sections.length > 0);\n const urlish = type !== \"section\" && (/^(https?:|www\\.|mailto:|tel:|#)/i.test(text.trim()) || (text.trim() !== \"\" && detectType(text) !== \"page\" && !manualType));\n const rows: Row[] = React.useMemo(() => {\n if (!searchable || urlish) return [];\n const pool = targets.filter((t) => (type === \"file\" ? t.kind === \"file\" : type === \"entry\" ? t.kind === \"entry\" : type === \"section\" ? t.kind === \"section\" : t.kind === \"page\" || t.kind === \"entry\"));\n const hit = (t: LinkTarget) => !q || t.title.toLowerCase().includes(q) || t.href.toLowerCase().includes(q) || (t.meta ?? \"\").toLowerCase().includes(q);\n const out: Row[] = [];\n const perGroup = new Map<string, number>();\n const cap = q ? 6 : type === \"page\" ? 4 : 6;\n for (const t of pool) {\n if (!hit(t)) continue;\n const n = perGroup.get(t.group) ?? 0;\n if (n >= cap) continue;\n perGroup.set(t.group, n + 1);\n out.push({ key: `${t.kind}:${t.id}`, group: t.group, target: t });\n }\n // keep each group together, groups in first-seen order (Pages first)\n const order = [...new Set(out.map((r) => r.group))];\n return out.sort((a, b) => order.indexOf(a.group) - order.indexOf(b.group)).slice(0, 24);\n }, [targets, type, q, searchable, urlish]);\n /* No silent empty list: when nothing can be listed, the list says why in one line. */\n const note: string | undefined = (() => {\n if (!searchable || urlish || rows.length) return undefined;\n if (type === \"section\") return undefined;\n if (type === \"file\") return MediaPicker ? \"Choose a file from the library with the folder button.\" : undefined;\n if (host.unavailable) return \"Page search isn't available here. Type a path, like /about.\";\n if (host.error) return `${host.error.replace(/\\.?$/, \".\")} Type a path, like /about.`;\n if (host.loading) return \"Loading pages…\";\n return q ? `Nothing matches “${text.trim()}”. Type a path, like /about.` : type === \"entry\" ? \"No CMS items yet.\" : \"No pages yet. Type a path, like /about.\";\n })();\n const listOpen = open && searching && (rows.length > 0 || !!note);\n /* Esc closes the results first, the surrounding panel only on the next Esc: the list claims the key on window, in the\n capture phase, while it is open. */\n React.useEffect(() => {\n if (!listOpen) return;\n const onKey = (e: KeyboardEvent) => {\n if (e.key !== \"Escape\" || !wrapRef.current?.contains(document.activeElement)) return;\n e.preventDefault();\n e.stopPropagation();\n setOpen(false);\n };\n window.addEventListener(\"keydown\", onKey, true);\n return () => window.removeEventListener(\"keydown\", onKey, true);\n }, [listOpen]);\n\n const choose = (t: LinkTarget) => {\n t.onChoose?.();\n const n = withTarget(v, t);\n setText(\"\");\n setManualType(null);\n setSearching(false);\n setOpen(false);\n setFileProblem(undefined);\n onChange(n);\n onPick?.(n);\n };\n const type_ = (s: string) => {\n setText(s);\n setOpen(true);\n setActive(s.trim() ? 0 : -1);\n onChange(withText(v, s, manualType ?? undefined));\n };\n const clear = () => {\n setText(\"\");\n setManualType(null);\n setSearching(true);\n onChange({ ...withText(v, \"\"), href: \"\" });\n requestAnimationFrame(() => inputRef.current?.focus());\n };\n const setType = (t: LinkType) => {\n setManualType(t);\n setText(\"\");\n setSearching(true);\n onChange({ ...withText(v, \"\", t), href: \"\" });\n setOpen(true);\n requestAnimationFrame(() => inputRef.current?.focus());\n };\n\n const h = size === \"sm\" ? \"h-8\" : \"h-9\";\n const list = (\n <div id={listId} role=\"listbox\" aria-label={type === \"file\" ? \"Files\" : type === \"section\" ? \"Sections on this page\" : \"Pages and CMS items\"} className=\"max-h-72 overflow-y-auto overscroll-contain\">\n {rows.map((r, i) => (\n <React.Fragment key={r.key}>\n {i === 0 || rows[i - 1].group !== r.group ? (\n <div role=\"presentation\" className=\"px-2 pb-1 pt-2 text-kit-xs font-medium text-kit-fg-3 first:pt-1\">\n {r.group}\n </div>\n ) : null}\n <div\n id={`${listId}-${i}`}\n role=\"option\"\n aria-selected={i === active}\n onMouseEnter={() => setActive(i)}\n onClick={() => choose(r.target)}\n className={cn(\"flex h-8 cursor-pointer items-center gap-2 rounded-kit-md px-2 text-kit-sm\", i === active && \"bg-kit-hover\")}\n >\n <span className=\"flex shrink-0 text-kit-fg-3 [&_svg]:size-4\" aria-hidden>\n {linkIcon({ href: r.target.href, type: r.target.kind }, r.target)}\n </span>\n <span className=\"min-w-0 shrink truncate text-kit-fg\">{r.target.title}</span>\n <span className=\"min-w-0 flex-1 truncate text-kit-xs text-kit-fg-3\">{r.target.kind === \"file\" ? fileName(r.target.href) : r.target.href}</span>\n {r.target.status && STATUS_LABEL[r.target.status] ? <span className=\"shrink-0 text-kit-2xs text-kit-fg-3\">{STATUS_LABEL[r.target.status]}</span> : null}\n </div>\n </React.Fragment>\n ))}\n {!rows.length && note ? (\n <p role=\"status\" className=\"px-2 py-1.5 text-kit-xs text-kit-fg-3\">\n {note}\n </p>\n ) : rows.length && host.error && type !== \"file\" && type !== \"section\" ? (\n /* some targets loaded and some did not (a collection's items): the gap is named under the list */\n <p role=\"status\" className=\"px-2 py-1.5 text-kit-xs text-kit-fg-3\">\n {host.error.replace(/\\.?$/, \".\")}\n </p>\n ) : null}\n </div>\n );\n const allowed = LINK_TYPES.filter((t) => (!types || types.includes(t.type)) && (t.type !== \"file\" || MediaPicker || v.type === \"file\"));\n const typeMenu = (\n <Menu>\n <MenuTrigger\n render={\n <button\n type=\"button\"\n aria-label={`Link type: ${meta.label}`}\n className=\"ml-0.5 flex h-7 shrink-0 items-center gap-0.5 rounded-kit-md px-1.5 text-kit-fg-3 hover:bg-kit-hover hover:text-kit-fg data-[popup-open]:bg-kit-hover [&_svg]:size-3.5\"\n />\n }\n >\n {meta.icon}\n <IconChevronDown className=\"!size-3\" stroke={1.5} />\n </MenuTrigger>\n <MenuContent className=\"min-w-48\">\n {allowed.map((t) => (\n <MenuItem key={t.type} icon={t.icon} onClick={() => setType(t.type)}>\n <span className=\"flex w-full items-center justify-between gap-3\">\n {t.label}\n {t.type === type ? <IconCheck className=\"size-3.5 text-kit-fg-2\" stroke={2} /> : null}\n </span>\n </MenuItem>\n ))}\n </MenuContent>\n </Menu>\n );\n\n return (\n <div className={cn(\"flex min-w-0 flex-col gap-1\", className)}>\n <Popover open={listOpen && !inlineList} onOpenChange={(o) => !o && setOpen(false)}>\n <div ref={wrapRef} className=\"min-w-0\">\n <PopoverAnchor\n className={cn(\n \"flex min-w-0 items-center\",\n bare\n ? \"bg-transparent\"\n : \"rounded-kit-md border border-kit-field-border bg-kit-field-bg shadow-kit-field transition-colors hover:border-kit-field-border-hover focus-within:border-kit-field-border-focus\",\n !bare && invalid && \"border-[var(--kit-field-invalid)] hover:border-[var(--kit-field-invalid)]\",\n h,\n )}\n >\n {showChip ? (\n <>\n <span className=\"ml-2 flex shrink-0 text-kit-fg-2 [&_svg]:size-4\" aria-hidden>\n {linkIcon(v, picked)}\n </span>\n <button\n id={id}\n type=\"button\"\n onClick={() => {\n setSearching(true);\n setOpen(true);\n requestAnimationFrame(() => inputRef.current?.focus());\n }}\n aria-label={`${ariaLabel}: ${picked!.title}, ${picked!.href}. Change`}\n className=\"flex h-full min-w-0 flex-1 items-center gap-2 px-2 text-left outline-none\"\n >\n <span className=\"min-w-0 shrink truncate text-kit-sm text-kit-fg\">{picked!.title}</span>\n <span className=\"min-w-0 flex-1 truncate text-kit-xs text-kit-fg-3\">{describeLink(v, picked).secondary}</span>\n </button>\n <IconButton label=\"Clear link\" size=\"xs\" className=\"mr-1\" onClick={clear}>\n <IconX stroke={1.5} />\n </IconButton>\n </>\n ) : (\n <>\n {lockedType !== undefined || inlineList ? (\n <span className=\"ml-2.5 flex shrink-0 text-kit-fg-3 [&_svg]:size-4\" aria-hidden>\n {meta.icon}\n </span>\n ) : (\n typeMenu\n )}\n <input\n ref={inputRef}\n id={id}\n role=\"combobox\"\n aria-label={ariaLabel}\n aria-invalid={invalid || undefined}\n aria-describedby={describedBy}\n aria-expanded={listOpen}\n aria-controls={listOpen ? listId : undefined}\n aria-autocomplete=\"list\"\n aria-activedescendant={listOpen && active >= 0 && rows[active] ? `${listId}-${active}` : undefined}\n value={text}\n onChange={(e) => type_(e.target.value)}\n onFocus={() => setOpen(true)}\n onBlur={(e) => {\n if (wrapRef.current?.contains(e.relatedTarget as Node)) return;\n if (inlineList) setOpen(false);\n // came from a chip: nothing typed → show the chip again\n if (picked && !text) setSearching(false);\n }}\n onKeyDown={(e) => {\n if (e.key === \"ArrowDown\" && rows.length) {\n e.preventDefault();\n setOpen(true);\n setActive((a) => (a + 1) % rows.length);\n } else if (e.key === \"ArrowUp\" && rows.length) {\n e.preventDefault();\n setActive((a) => (a <= 0 ? rows.length - 1 : a - 1));\n } else if (e.key === \"Enter\") {\n e.preventDefault();\n if (listOpen && active >= 0 && rows[active]) choose(rows[active].target);\n else onEnter?.(withText(v, text, manualType ?? undefined));\n } else if (e.key === \"Escape\") {\n if (listOpen) {\n e.preventDefault();\n e.stopPropagation();\n setOpen(false);\n } else if (picked && !text && !startSearching) {\n e.preventDefault();\n e.stopPropagation();\n setSearching(false);\n } else if (onEscape) {\n e.preventDefault();\n e.stopPropagation();\n onEscape();\n }\n }\n }}\n placeholder={picked && !text ? picked.title : meta.placeholder}\n autoComplete=\"off\"\n spellCheck={false}\n className=\"h-full min-w-0 flex-1 bg-transparent px-2 text-kit-sm text-kit-fg outline-none placeholder:text-kit-fg-3\"\n />\n {text ? (\n <IconButton label=\"Clear\" size=\"xs\" className=\"mr-1\" onMouseDown={(e) => e.preventDefault()} onClick={clear}>\n <IconX stroke={1.5} />\n </IconButton>\n ) : null}\n {type === \"file\" && MediaPicker ? (\n <IconButton\n label=\"Choose or upload a file\"\n size=\"xs\"\n className=\"mr-1 text-kit-fg-3\"\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => {\n setOpen(false);\n setLibrary(true);\n }}\n >\n <IconFolderOpen stroke={1.5} />\n </IconButton>\n ) : null}\n </>\n )}\n </PopoverAnchor>\n </div>\n <PopoverContent\n keepFocus\n align=\"start\"\n side=\"bottom\"\n sideOffset={4}\n data-kit-link-list=\"\"\n className=\"w-[max(var(--anchor-width),280px)] max-w-[min(420px,calc(100vw-24px))] !bg-kit-surface p-1 shadow-kit-lg\"\n >\n {list}\n </PopoverContent>\n </Popover>\n {inlineList && listOpen ? (\n <div className=\"rounded-kit-md border border-kit-line bg-kit-surface p-1 [&_[role=listbox]]:max-h-56\" onMouseDown={(e) => e.preventDefault()}>\n {list}\n </div>\n ) : null}\n {fileProblem ? (\n <p role=\"alert\" className=\"text-kit-xs text-kit-danger-fg\">\n {fileProblem}\n </p>\n ) : null}\n {/* File: the host's media library (search, folders, upload) is one click away; mounted only while open */}\n {library && MediaPicker ? (\n <MediaPicker\n open\n accept={[\"file\"]}\n onOpenChange={(o) => !o && setLibrary(false)}\n onPick={(a) => {\n if (!a[0]) return;\n const t = fileTarget(a[0]);\n if (\"problem\" in t) setFileProblem(t.problem);\n else choose(t);\n }}\n />\n ) : null}\n </div>\n );\n}\n\n/* ── Shared options (subject · open in new tab · rel) ───────────────── */\nexport function LinkOptions({ v, onChange, compact, disabled }: { v: LinkValue; onChange: (v: LinkValue) => void; compact?: boolean; disabled?: boolean }) {\n const tabId = React.useId();\n return (\n <div className={cn(\"flex flex-col\", compact ? \"gap-2\" : \"gap-2.5\")}>\n {v.type === \"email\" ? (\n <label className=\"flex items-center justify-between gap-3\">\n <span className=\"text-kit-xs text-kit-fg-2\">Subject</span>\n <Input size=\"sm\" value={v.subject ?? \"\"} onChange={(e) => onChange({ ...v, subject: e.target.value })} placeholder=\"Wholesale inquiry\" className=\"max-w-52\" />\n </label>\n ) : null}\n <label htmlFor={tabId} className=\"flex min-h-7 items-center justify-between gap-3\">\n <span className=\"text-kit-xs text-kit-fg-2\">Open in new tab</span>\n <Switch disabled={disabled} id={tabId} size=\"sm\" checked={!!v.newTab} onCheckedChange={(c) => onChange({ ...v, newTab: c, target: undefined })} />\n </label>\n <div className=\"flex items-center justify-between gap-3\">\n <span className=\"text-kit-xs text-kit-fg-2\">Rel</span>\n <Select disabled={disabled} aria-label=\"Rel\" size=\"sm\" className=\"w-[168px]\" value={v.rel ?? \"follow\"} onValueChange={(r) => onChange({ ...v, rel: r as LinkRel })} options={REL_ITEMS} />\n </div>\n </div>\n );\n}\n\n/* ── The link element ───────────────────────────────────────────────\n * CPO D48 + D57: the ONE way to edit a link, wherever a link is edited: Type (dropdown) → the target for that type\n * (results appear only once you focus or type, in the flow below the input, never over the panel; File adds the media\n * library) → the error in plain words when it can't be saved → Section on the picked page → the options as plain rows\n * (new tab, rel, subject). Hosts wrap it: the link panel (LinkPopoverBody), the button screen. Controlled: the host owns\n * the value; remount (key) to start over.\n */\nexport function LinkForm({\n value,\n onChange,\n onEnter,\n hideOptions,\n types,\n autoFocus,\n readOnly,\n className,\n}: {\n value: LinkValue;\n onChange: (v: LinkValue) => void;\n /** Enter in the target with a value that can be saved */\n onEnter?: (v: LinkValue) => void;\n /** string-only values: no new tab / rel */\n hideOptions?: boolean;\n /** the link types this place allows. Default: all */\n types?: LinkType[];\n /** focus the Type control on open (D48: never the search) */\n autoFocus?: boolean;\n /** the lens can't edit the link: every control is disabled */\n readOnly?: boolean;\n className?: string;\n}) {\n const v = normLink(value);\n const { MediaPicker } = useKitServices();\n const allowed = LINK_TYPES.filter((t) => (!types || types.includes(t.type)) && (t.type !== \"file\" || MediaPicker || v.type === \"file\"));\n const [kind, setKind] = React.useState<LinkType>(() => {\n const k = v.type === \"entry\" && hasLink(v) ? \"page\" : v.type ?? \"page\";\n return allowed.some((t) => t.type === k) ? k : allowed[0]?.type ?? \"page\";\n });\n const [resetKey, setResetKey] = React.useState(0);\n const [touched, setTouched] = React.useState(false);\n const { targets } = useLinkTargets();\n const anchors = findTarget(targets, v)?.anchors;\n const typeId = React.useId();\n const targetId = React.useId();\n const errId = React.useId();\n const problem = touched ? linkProblem(v) : undefined;\n // the type select follows what the target turned out to be (a picked CMS item, a pasted URL) while \"Page\" is searching\n const shownType: LinkType = kind === \"page\" && hasLink(v) ? v.type ?? \"page\" : kind;\n React.useEffect(() => {\n if (autoFocus) requestAnimationFrame(() => document.getElementById(typeId)?.focus({ preventScroll: true }));\n }, [autoFocus, typeId]);\n const changeType = (t: LinkType) => {\n setKind(t);\n setTouched(false);\n onChange({ ...withText(v, \"\", t === \"page\" ? undefined : t), href: \"\", type: t, anchor: undefined });\n setResetKey((k) => k + 1);\n requestAnimationFrame(() => document.getElementById(targetId)?.focus());\n };\n return (\n <div className={cn(\"flex min-w-0 flex-col gap-3\", className)}>\n <div className=\"flex items-center justify-between gap-3\">\n <label htmlFor={typeId} className=\"text-kit-xs text-kit-fg-2\">\n Type\n </label>\n <Select disabled={readOnly} id={typeId} size=\"sm\" className=\"w-[180px]\" value={shownType} onValueChange={(t) => changeType(t as LinkType)} options={allowed.map((t) => ({ value: t.type, label: t.label, icon: t.icon }))} />\n </div>\n <div\n className=\"flex flex-col gap-1.5\"\n onBlur={(e) => {\n if (!e.currentTarget.contains(e.relatedTarget as Node)) setTouched(true);\n }}\n >\n <label htmlFor={targetId} className=\"text-kit-xs text-kit-fg-2\">\n {typeMeta(kind).target}\n </label>\n <LinkPicker\n key={resetKey}\n id={targetId}\n size=\"sm\"\n value={v}\n onChange={onChange}\n onPick={() => setTouched(true)}\n onEnter={(n) => {\n setTouched(true);\n if (!linkProblem(n)) onEnter?.(n);\n }}\n lockedType={kind === \"page\" ? undefined : kind}\n inlineList\n types={types}\n invalid={!!problem}\n aria-describedby={problem ? errId : undefined}\n aria-label={typeMeta(kind).target}\n />\n {problem ? (\n <p id={errId} role=\"alert\" className=\"text-kit-xs text-kit-danger-fg\">\n {problem}\n </p>\n ) : null}\n </div>\n {anchors?.length ? (\n <div className=\"flex items-center justify-between gap-3\">\n <span className=\"text-kit-xs text-kit-fg-2\">Section</span>\n <Select disabled={readOnly} aria-label=\"Section\"\n size=\"sm\"\n className=\"w-[180px]\"\n value={v.anchor ?? \"none\"}\n onValueChange={(a) => onChange({ ...v, anchor: a })}\n options={[{ value: \"none\", label: \"Top of page\" }, ...anchors.map((a) => ({ value: a, label: a }))]}\n />\n </div>\n ) : null}\n {hideOptions ? null : <LinkOptions v={v} onChange={onChange} compact disabled={readOnly} />}\n </div>\n );\n}\n\n/* ── The link panel ─────────────────────────────────────────────────\n * What it links to now → the link element (LinkForm) → Remove link · Cancel · Apply (Apply only when something changed\n * and the link can be saved). Esc closes the results first, then the panel.\n */\nexport function LinkPopoverBody({\n initial,\n onSave,\n onDetach,\n onCancel,\n hideOptions,\n types,\n}: {\n initial: LinkValue;\n onSave: (v: LinkValue) => void;\n onDetach?: () => void;\n onCancel?: () => void;\n /** string-only fields: no new tab / rel */\n hideOptions?: boolean;\n /** the link types this place allows. Default: all */\n types?: LinkType[];\n}) {\n const start = normLink(initial);\n const [v, setV] = React.useState<LinkValue>(start);\n const { targets } = useLinkTargets();\n const startTarget = findTarget(targets, start);\n const fin = (x: LinkValue) => {\n const f = finalizeLink(x);\n return f ? JSON.stringify(storedLink(f)) : \"\";\n };\n const changed = fin(v) !== fin(start);\n const ok = hasLink(v) && !linkProblem(v);\n const apply = (n = v) => {\n const out = finalizeLink(n);\n if (out && hasLink(out) && !linkProblem(out)) onSave(out);\n };\n return (\n <form\n className=\"flex flex-col gap-3\"\n onSubmit={(e) => {\n e.preventDefault();\n e.stopPropagation();\n apply();\n }}\n >\n <div className=\"flex min-w-0 flex-col gap-1\">\n <span className=\"text-kit-sm font-medium text-kit-fg\">Link</span>\n {hasLink(start) ? (\n <span className=\"flex min-w-0 text-kit-fg-2\">\n <LinkLine v={start} target={startTarget} />\n </span>\n ) : (\n <span className=\"text-kit-xs text-kit-fg-3\">No link yet</span>\n )}\n </div>\n <LinkForm value={v} onChange={setV} onEnter={(n) => apply(n)} hideOptions={hideOptions} types={types} autoFocus />\n <div className=\"flex items-center gap-2 border-t border-kit-line pt-2.5\">\n {onDetach ? (\n <Button type=\"button\" size=\"xs\" variant=\"danger-ghost\" onClick={onDetach}>\n Remove link\n </Button>\n ) : null}\n <span className=\"flex-1\" />\n {onCancel ? (\n <Button type=\"button\" size=\"xs\" variant=\"ghost\" onClick={onCancel}>\n Cancel\n </Button>\n ) : null}\n <Button type=\"submit\" size=\"xs\" variant=\"primary\" disabled={!changed || !ok}>\n Apply\n </Button>\n </div>\n </form>\n );\n}\n\n/* ── Quick edit: the link row turns into the picker in place ───────── */\nexport function LinkQuickEdit({\n value,\n onCommit,\n onDone,\n ariaLabel,\n size,\n bare,\n types,\n}: {\n value: LinkValue;\n /** null = cleared */\n onCommit: (v: LinkValue | null) => void;\n onDone: () => void;\n ariaLabel: string;\n size?: \"sm\" | \"md\";\n bare?: boolean;\n types?: LinkType[];\n}) {\n const [draft, setDraft] = React.useState(value);\n const [problem, setProblem] = React.useState<string>();\n const done = React.useRef(false);\n const ref = React.useRef<HTMLDivElement>(null);\n const errId = React.useId();\n const commit = (n: LinkValue, strict = true) => {\n if (done.current) return;\n if (hasLink(n) && strict && linkProblem(n)) return setProblem(linkProblem(n));\n done.current = true;\n if (!hasLink(n)) onCommit(null);\n else {\n const out = finalizeLink(n);\n // a script link is dropped, never written (finalizeLink refuses it)\n if (out) onCommit(out);\n }\n onDone();\n };\n return (\n <div\n ref={ref}\n className=\"flex min-w-0 flex-col gap-1\"\n onBlur={(e) => {\n const next = e.relatedTarget as HTMLElement | null;\n if (libraryOpen || (next && (ref.current?.contains(next) || next.closest?.(`[${LIST_ATTR}],[role=menu]`)))) return;\n // focus left the editor: keep what was typed (nothing changed → nothing written)\n window.setTimeout(() => {\n if (libraryOpen || done.current || ref.current?.contains(document.activeElement)) return;\n if (hrefOf(draft) === hrefOf(value) && draft.pageId === value.pageId && draft.entryId === value.entryId) {\n done.current = true;\n onDone();\n } else commit(draft, false);\n }, 0);\n }}\n >\n <LinkPicker\n value={draft}\n onChange={(n) => {\n setDraft(n);\n setProblem(undefined);\n }}\n onPick={(n) => commit(n)}\n onEnter={(n) => commit(n)}\n onEscape={() => {\n done.current = true;\n onDone();\n }}\n autoFocus\n startSearching\n aria-label={ariaLabel}\n size={size}\n bare={bare}\n types={types}\n invalid={!!problem}\n aria-describedby={problem ? errId : undefined}\n />\n {problem ? (\n <p id={errId} role=\"alert\" className={cn(\"text-kit-xs text-kit-danger-fg\", bare && \"px-2.5 pb-1.5\")}>\n {problem}\n </p>\n ) : null}\n </div>\n );\n}\n\n/* ── Link field: one bordered row; click edits in place, the sliders icon opens the link panel ── */\nexport interface LinkFieldProps {\n /** a LinkValue or a plain href string */\n value: unknown;\n /** null = cleared (object shape); \"\" = cleared (string shape) */\n onChange: (v: LinkValue | string | null) => void;\n /** \"string\": the value is the href alone. New tab and rel need the object shape, so they hide. */\n valueShape?: \"string\" | \"object\";\n id?: string;\n \"aria-label\": string;\n readOnly?: boolean;\n size?: \"sm\" | \"md\";\n /** the link types this place allows. Default: all */\n types?: LinkType[];\n invalid?: boolean;\n placeholder?: string;\n className?: string;\n}\nexport function LinkField({ value, onChange: write, valueShape, id: idProp, \"aria-label\": label, readOnly, size = \"sm\", types, invalid, placeholder, className }: LinkFieldProps) {\n const v = normLink(value);\n const stringOnly = valueShape === \"string\";\n const onChange = (n: LinkValue | null) => write(stringOnly ? (n ? hrefOf(n) : \"\") : n ? storedLink(n, value) : null);\n const autoId = React.useId();\n const id = idProp ?? autoId;\n const [editing, setEditing] = React.useState(false);\n const [open, setOpen] = React.useState(false);\n const { targets } = useLinkTargets();\n const target = findTarget(targets, v);\n const has = hasLink(v);\n if (editing && !readOnly)\n return (\n <LinkQuickEdit\n value={v}\n ariaLabel={label}\n size={size}\n types={types}\n onCommit={onChange}\n onDone={() => {\n setEditing(false);\n requestAnimationFrame(() => document.getElementById(id)?.focus({ preventScroll: true }));\n }}\n />\n );\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverAnchor\n data-kit-link-field=\"\"\n className={cn(\n \"group/link relative flex min-w-0 items-center rounded-kit-md border border-kit-field-border bg-kit-field-bg shadow-kit-field transition-colors hover:border-kit-field-border-hover\",\n size === \"md\" ? \"h-9\" : \"h-8\",\n readOnly && \"hover:border-kit-field-border\",\n invalid && \"border-[var(--kit-field-invalid)]\",\n className,\n )}\n >\n <button\n id={id}\n type=\"button\"\n disabled={readOnly}\n onClick={() => setEditing(true)}\n // V2 link.tsx:977: the name reads the link's own text (its title, else its address), not the picked target's title\n aria-label={has ? `${label}: ${linkText(v)}. Edit link` : `Add ${label.toLowerCase()}`}\n aria-invalid={invalid || undefined}\n className=\"flex h-full min-w-0 flex-1 items-center px-2.5 text-left outline-none disabled:cursor-default\"\n >\n <LinkLine v={v} target={target} placeholder={placeholder} />\n </button>\n {readOnly ? null : (\n <span className=\"mr-1 flex shrink-0 items-center gap-0.5\">\n <Tooltip content=\"Link options\">\n <PopoverTrigger\n render={\n <IconButton label=\"Link options\" tooltip={false} size=\"xs\" className=\"text-kit-fg-3\">\n <IconAdjustmentsHorizontal stroke={1.5} />\n </IconButton>\n }\n />\n </Tooltip>\n {has ? (\n <IconButton\n label={`Clear ${label.toLowerCase()}`}\n size=\"xs\"\n className=\"hidden text-kit-fg-3 group-hover/link:inline-flex group-focus-within/link:inline-flex [@media(pointer:coarse)]:inline-flex\"\n onClick={() => onChange(null)}\n >\n <IconX stroke={1.5} />\n </IconButton>\n ) : null}\n </span>\n )}\n </PopoverAnchor>\n <PopoverContent className=\"w-[340px] p-3\" align=\"start\">\n <LinkPopoverBody\n initial={v}\n hideOptions={stringOnly}\n types={types}\n onSave={(n) => {\n onChange(n);\n setOpen(false);\n }}\n onDetach={\n has\n ? () => {\n onChange(null);\n setOpen(false);\n }\n : undefined\n }\n onCancel={() => setOpen(false)}\n />\n </PopoverContent>\n </Popover>\n );\n}\n\n/**\n * The shape a link field writes: the shape its value already has (a string stays a string, an object an object), and\n * for an empty field `field.valueShape`, else the string prod stores by default.\n */\nexport function linkShapeOf(value: unknown, valueShape?: \"string\" | \"object\"): \"string\" | \"object\" {\n if (isObj(value)) return \"object\";\n if (typeof value === \"string\" && value !== \"\") return \"string\";\n return valueShape ?? \"string\";\n}\n\n/** The Block Kit `link` field: the LinkField above, sized for the form it sits in. */\nexport function LinkControl({ value, onChange, readOnly, id, field, invalid }: ControlProps) {\n const { variant } = useKitEnv();\n return (\n <LinkField\n id={id}\n value={value}\n onChange={onChange}\n valueShape={linkShapeOf(value, field.valueShape)}\n aria-label={field.title}\n readOnly={readOnly}\n size={variant === \"document\" ? \"md\" : \"sm\"}\n invalid={invalid}\n />\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CONTROLS } from "../engine/kit-field.js";
|
|
2
2
|
import { LocationControl } from "./location.js";
|
|
3
|
-
//#region src/
|
|
3
|
+
//#region src/controls/location-register.ts
|
|
4
4
|
/** Lane C3: the geopoint (prod `location`) field in the engine's dispatch table (one line per type; merge by line). */
|
|
5
5
|
CONTROLS.geopoint = LocationControl;
|
|
6
6
|
//#endregion
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"location-register.js","names":[],"sources":["../../src/controls/location-register.ts"],"sourcesContent":["/** Lane C3: the geopoint (prod `location`) field in the engine's dispatch table (one line per type; merge by line). */\nimport { CONTROLS } from \"../engine/kit-field\";\nimport { LocationControl } from \"./location\";\n\nCONTROLS.geopoint = LocationControl;\n"],"mappings":";;;;AAIA,SAAS,WAAW"}
|