@bettercms-ai/kit 1.0.0 → 2.0.0-next.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +33 -0
- package/dist/adapters/dock-values.d.ts +28 -0
- package/dist/adapters/dock-values.js +41 -0
- package/dist/adapters/dock-values.js.map +1 -0
- package/{adapters → dist/adapters}/icons.js +2 -2
- package/dist/adapters/icons.js.map +1 -0
- package/{adapters → dist/adapters}/lossy.d.ts +94 -31
- package/dist/adapters/lossy.js +419 -0
- package/dist/adapters/lossy.js.map +1 -0
- package/{adapters → dist/adapters}/prod-types.d.ts +91 -26
- package/{adapters → dist/adapters}/prod-types.js +82 -13
- package/dist/adapters/prod-types.js.map +1 -0
- package/{adapters → dist/adapters}/schema.d.ts +40 -1
- package/{adapters → dist/adapters}/schema.js +1038 -204
- package/dist/adapters/schema.js.map +1 -0
- package/{adapters → dist/adapters}/values.d.ts +26 -5
- package/{adapters → dist/adapters}/values.js +87 -17
- package/dist/adapters/values.js.map +1 -0
- package/dist/brand/logo.js +96 -0
- package/dist/brand/logo.js.map +1 -0
- package/{context.d.ts → dist/context.d.ts} +131 -2
- package/{context.js → dist/context.js} +44 -2
- package/dist/context.js.map +1 -0
- package/{controls → dist/controls}/button.d.ts +19 -5
- package/{controls → dist/controls}/button.js +125 -54
- package/dist/controls/button.js.map +1 -0
- package/{controls → dist/controls}/c1.js +1 -1
- package/dist/controls/c1.js.map +1 -0
- package/{controls → dist/controls}/c2.js +1 -1
- package/dist/controls/c2.js.map +1 -0
- package/{controls → dist/controls}/choice.d.ts +7 -2
- package/{controls → dist/controls}/choice.js +71 -18
- package/dist/controls/choice.js.map +1 -0
- package/{controls → dist/controls}/code-register.js +1 -1
- package/dist/controls/code-register.js.map +1 -0
- package/{controls → dist/controls}/code.js +10 -9
- package/dist/controls/code.js.map +1 -0
- package/{controls → dist/controls}/color.js +8 -8
- package/dist/controls/color.js.map +1 -0
- package/{controls → dist/controls}/component-services.d.ts +42 -0
- package/dist/controls/component-services.js +7 -0
- package/dist/controls/component-services.js.map +1 -0
- package/{controls → dist/controls}/date-register.js +1 -1
- package/dist/controls/date-register.js.map +1 -0
- package/{controls → dist/controls}/date-zone.js +8 -2
- package/dist/controls/date-zone.js.map +1 -0
- package/{controls → dist/controls}/date.js +32 -24
- package/dist/controls/date.js.map +1 -0
- package/dist/controls/form-picker-register.d.ts +7 -0
- package/{controls → dist/controls}/form-picker-register.js +2 -6
- package/dist/controls/form-picker-register.js.map +1 -0
- package/{controls → dist/controls}/form-picker.js +11 -9
- package/dist/controls/form-picker.js.map +1 -0
- package/{controls → dist/controls}/icon-register.js +1 -1
- package/dist/controls/icon-register.js.map +1 -0
- package/{controls → dist/controls}/icon.d.ts +4 -2
- package/{controls → dist/controls}/icon.js +32 -27
- package/dist/controls/icon.js.map +1 -0
- package/{controls → dist/controls}/index.d.ts +1 -1
- package/{controls → dist/controls}/index.js +4 -3
- package/dist/controls/index.js.map +1 -0
- package/{controls → dist/controls}/json-register.js +1 -1
- package/dist/controls/json-register.js.map +1 -0
- package/{controls → dist/controls}/json.js +13 -3
- package/dist/controls/json.js.map +1 -0
- package/{controls → dist/controls}/link.js +116 -200
- package/dist/controls/link.js.map +1 -0
- package/{controls → dist/controls}/location-register.js +1 -1
- package/dist/controls/location-register.js.map +1 -0
- package/{controls → dist/controls}/location.js +59 -40
- package/dist/controls/location.js.map +1 -0
- package/{controls → dist/controls}/media-register.js +1 -1
- package/dist/controls/media-register.js.map +1 -0
- package/{controls → dist/controls}/media-services.d.ts +6 -0
- package/dist/controls/media-services.js +0 -0
- package/{controls → dist/controls}/media.d.ts +21 -4
- package/{controls → dist/controls}/media.js +407 -130
- package/dist/controls/media.js.map +1 -0
- package/{controls → dist/controls}/number.js +10 -9
- package/dist/controls/number.js.map +1 -0
- package/{controls → dist/controls}/reference-register.js +1 -1
- package/dist/controls/reference-register.js.map +1 -0
- package/{controls → dist/controls}/reference-services.d.ts +4 -0
- package/dist/controls/reference-services.js +0 -0
- package/{controls → dist/controls}/reference.d.ts +1 -1
- package/{controls → dist/controls}/reference.js +93 -77
- package/dist/controls/reference.js.map +1 -0
- package/dist/controls/rich-text/article-shell.d.ts +145 -0
- package/dist/controls/rich-text/article-shell.js +510 -0
- package/dist/controls/rich-text/article-shell.js.map +1 -0
- package/dist/controls/rich-text/author.d.ts +25 -0
- package/dist/controls/rich-text/author.js +104 -0
- package/dist/controls/rich-text/author.js.map +1 -0
- package/dist/controls/rich-text/blocks.d.ts +60 -0
- package/{controls → dist/controls}/rich-text/blocks.js +164 -389
- package/dist/controls/rich-text/blocks.js.map +1 -0
- package/dist/controls/rich-text/button.d.ts +23 -0
- package/dist/controls/rich-text/button.js +85 -0
- package/dist/controls/rich-text/button.js.map +1 -0
- package/{controls → dist/controls}/rich-text/catalog.d.ts +7 -4
- package/{controls → dist/controls}/rich-text/catalog.js +94 -68
- package/dist/controls/rich-text/catalog.js.map +1 -0
- package/dist/controls/rich-text/checklist.d.ts +24 -0
- package/dist/controls/rich-text/checklist.js +115 -0
- package/dist/controls/rich-text/checklist.js.map +1 -0
- package/{controls → dist/controls}/rich-text/codec.d.ts +9 -1
- package/{controls → dist/controls}/rich-text/codec.js +7 -2
- package/dist/controls/rich-text/codec.js.map +1 -0
- package/dist/controls/rich-text/columns.d.ts +41 -0
- package/dist/controls/rich-text/columns.js +181 -0
- package/dist/controls/rich-text/columns.js.map +1 -0
- package/{controls → dist/controls}/rich-text/component-card.d.ts +1 -1
- package/{controls → dist/controls}/rich-text/component-card.js +417 -99
- package/dist/controls/rich-text/component-card.js.map +1 -0
- package/dist/controls/rich-text/component-panel.d.ts +47 -0
- package/dist/controls/rich-text/component-panel.js +141 -0
- package/dist/controls/rich-text/component-panel.js.map +1 -0
- package/{controls → dist/controls}/rich-text/control.d.ts +1 -2
- package/{controls → dist/controls}/rich-text/control.js +84 -42
- package/dist/controls/rich-text/control.js.map +1 -0
- package/{controls → dist/controls}/rich-text/dom.d.ts +53 -9
- package/{controls → dist/controls}/rich-text/dom.js +388 -50
- package/dist/controls/rich-text/dom.js.map +1 -0
- package/{controls → dist/controls}/rich-text/editor.d.ts +7 -0
- package/{controls → dist/controls}/rich-text/editor.js +226 -44
- package/dist/controls/rich-text/editor.js.map +1 -0
- package/dist/controls/rich-text/embed.d.ts +28 -0
- package/dist/controls/rich-text/embed.js +210 -0
- package/dist/controls/rich-text/embed.js.map +1 -0
- package/{controls → dist/controls}/rich-text/floating.d.ts +6 -1
- package/{controls → dist/controls}/rich-text/floating.js +35 -18
- package/dist/controls/rich-text/floating.js.map +1 -0
- package/dist/controls/rich-text/footnote.d.ts +41 -0
- package/dist/controls/rich-text/footnote.js +185 -0
- package/dist/controls/rich-text/footnote.js.map +1 -0
- package/dist/controls/rich-text/gallery.d.ts +28 -0
- package/dist/controls/rich-text/gallery.js +167 -0
- package/dist/controls/rich-text/gallery.js.map +1 -0
- package/{controls → dist/controls}/rich-text/index.js +1 -1
- package/dist/controls/rich-text/index.js.map +1 -0
- package/{controls → dist/controls}/rich-text/link-form.d.ts +3 -1
- package/dist/controls/rich-text/link-form.js +147 -0
- package/dist/controls/rich-text/link-form.js.map +1 -0
- package/{controls → dist/controls}/rich-text/markdown.js +4 -2
- package/dist/controls/rich-text/markdown.js.map +1 -0
- package/{controls → dist/controls}/rich-text/ops.js +17 -15
- package/dist/controls/rich-text/ops.js.map +1 -0
- package/dist/controls/rich-text/plain.d.ts +17 -0
- package/dist/controls/rich-text/plain.js +44 -0
- package/dist/controls/rich-text/plain.js.map +1 -0
- package/dist/controls/rich-text/related.d.ts +36 -0
- package/dist/controls/rich-text/related.js +213 -0
- package/dist/controls/rich-text/related.js.map +1 -0
- package/dist/controls/rich-text/toc.d.ts +46 -0
- package/dist/controls/rich-text/toc.js +161 -0
- package/dist/controls/rich-text/toc.js.map +1 -0
- package/{controls → dist/controls}/rich-text/toolbar.d.ts +6 -2
- package/{controls → dist/controls}/rich-text/toolbar.js +12 -7
- package/dist/controls/rich-text/toolbar.js.map +1 -0
- package/{controls → dist/controls}/scale.js +5 -5
- package/dist/controls/scale.js.map +1 -0
- package/dist/controls/slot-register.d.ts +6 -0
- package/{controls → dist/controls}/slot-register.js +2 -5
- package/dist/controls/slot-register.js.map +1 -0
- package/{controls → dist/controls}/slot-services.d.ts +25 -0
- package/dist/controls/slot-services.js +155 -0
- package/dist/controls/slot-services.js.map +1 -0
- package/{controls → dist/controls}/slot.js +42 -24
- package/dist/controls/slot.js.map +1 -0
- package/{controls → dist/controls}/table/index.js +1 -1
- package/dist/controls/table/index.js.map +1 -0
- package/{controls → dist/controls}/table/prod.js +3 -3
- package/dist/controls/table/prod.js.map +1 -0
- package/{controls → dist/controls}/table/refs.js +13 -2
- package/dist/controls/table/refs.js.map +1 -0
- package/{controls → dist/controls}/table/stored.js +1 -1
- package/dist/controls/table/stored.js.map +1 -0
- package/{controls → dist/controls}/table/table-editor.js +51 -48
- package/dist/controls/table/table-editor.js.map +1 -0
- package/{controls → dist/controls}/table/table-link.js +3 -3
- package/dist/controls/table/table-link.js.map +1 -0
- package/{controls → dist/controls}/table/table.js +3 -3
- package/dist/controls/table/table.js.map +1 -0
- package/{controls → dist/controls}/text.d.ts +2 -2
- package/{controls → dist/controls}/text.js +78 -43
- package/dist/controls/text.js.map +1 -0
- package/dist/controls/unknown-value.d.ts +17 -0
- package/dist/controls/unknown-value.js +66 -0
- package/dist/controls/unknown-value.js.map +1 -0
- package/dist/core/core.d.ts +70 -0
- package/dist/core/core.js +187 -0
- package/dist/core/core.js.map +1 -0
- package/dist/core/facets.d.ts +355 -0
- package/dist/core/facets.js +342 -0
- package/dist/core/facets.js.map +1 -0
- package/dist/core/index.d.ts +3 -0
- package/dist/core/index.js +3 -0
- package/{engine → dist/engine}/array.js +34 -21
- package/dist/engine/array.js.map +1 -0
- package/{engine → dist/engine}/bits.js +1 -1
- package/dist/engine/bits.js.map +1 -0
- package/{engine → dist/engine}/breadcrumb.d.ts +3 -3
- package/{engine → dist/engine}/breadcrumb.js +12 -36
- package/dist/engine/breadcrumb.js.map +1 -0
- package/{engine → dist/engine}/expand.d.ts +2 -4
- package/{engine → dist/engine}/expand.js +5 -22
- package/dist/engine/expand.js.map +1 -0
- package/{engine → dist/engine}/field-list.js +1 -1
- package/dist/engine/field-list.js.map +1 -0
- package/{engine → dist/engine}/field-shell.js +249 -121
- package/dist/engine/field-shell.js.map +1 -0
- package/{engine → dist/engine}/frame.d.ts +3 -1
- package/{engine → dist/engine}/frame.js +16 -14
- package/dist/engine/frame.js.map +1 -0
- package/{engine → dist/engine}/group-summary.d.ts +2 -1
- package/{engine → dist/engine}/group-summary.js +7 -3
- package/dist/engine/group-summary.js.map +1 -0
- package/{engine → dist/engine}/grouping.d.ts +19 -5
- package/{engine → dist/engine}/grouping.js +193 -21
- package/dist/engine/grouping.js.map +1 -0
- package/{engine → dist/engine}/item-list.d.ts +11 -1
- package/{engine → dist/engine}/item-list.js +35 -13
- package/dist/engine/item-list.js.map +1 -0
- package/{engine → dist/engine}/kit-field.js +45 -10
- package/dist/engine/kit-field.js.map +1 -0
- package/{engine → dist/engine}/schema-form.d.ts +27 -2
- package/{engine → dist/engine}/schema-form.js +182 -40
- package/dist/engine/schema-form.js.map +1 -0
- package/{engine → dist/engine}/slot.js +5 -15
- package/dist/engine/slot.js.map +1 -0
- package/dist/index.js +58 -0
- package/dist/index.js.map +1 -0
- package/{kit.css → dist/kit.css} +19 -0
- package/{lib → dist/lib}/cn.js +7 -4
- package/dist/lib/cn.js.map +1 -0
- package/{lib → dist/lib}/columns.js +4 -1
- package/dist/lib/columns.js.map +1 -0
- package/{lib → dist/lib}/frames.js +2 -2
- package/dist/lib/frames.js.map +1 -0
- package/dist/lib/icon-image.d.ts +10 -0
- package/dist/lib/icon-image.js +8 -0
- package/dist/lib/icon-image.js.map +1 -0
- package/{lib → dist/lib}/icons.js +4 -3
- package/dist/lib/icons.js.map +1 -0
- package/dist/lib/input-modality.d.ts +11 -0
- package/dist/lib/input-modality.js +47 -0
- package/dist/lib/input-modality.js.map +1 -0
- package/dist/lib/key-event.d.ts +11 -0
- package/dist/lib/key-event.js +16 -0
- package/dist/lib/key-event.js.map +1 -0
- package/{lib → dist/lib}/path.js +4 -2
- package/dist/lib/path.js.map +1 -0
- package/{lib → dist/lib}/schema.d.ts +34 -3
- package/{lib → dist/lib}/schema.js +110 -13
- package/dist/lib/schema.js.map +1 -0
- package/{lib → dist/lib}/utils.js +1 -1
- package/dist/lib/utils.js.map +1 -0
- package/{lib → dist/lib}/validate.d.ts +11 -1
- package/{lib → dist/lib}/validate.js +85 -11
- package/dist/lib/validate.js.map +1 -0
- package/dist/library/analysis.d.ts +23 -0
- package/dist/library/analysis.js +160 -0
- package/dist/library/analysis.js.map +1 -0
- package/dist/library/catalog.d.ts +57 -0
- package/dist/library/catalog.js +307 -0
- package/dist/library/catalog.js.map +1 -0
- package/dist/library/coreNotes.d.ts +8 -0
- package/dist/library/coreNotes.js +111 -0
- package/dist/library/coreNotes.js.map +1 -0
- package/dist/library/coverage.d.ts +40 -0
- package/dist/library/coverage.js +59 -0
- package/dist/library/coverage.js.map +1 -0
- package/dist/library/entries/advanced.entries.d.ts +2 -0
- package/dist/library/entries/advanced.entries.js +6579 -0
- package/dist/library/entries/advanced.entries.js.map +1 -0
- package/dist/library/entries/commerce.entries.d.ts +2 -0
- package/dist/library/entries/commerce.entries.js +4140 -0
- package/dist/library/entries/commerce.entries.js.map +1 -0
- package/dist/library/entries/company.entries.d.ts +2 -0
- package/dist/library/entries/company.entries.js +2731 -0
- package/dist/library/entries/company.entries.js.map +1 -0
- package/dist/library/entries/conversion.entries.d.ts +2 -0
- package/dist/library/entries/conversion.entries.js +3707 -0
- package/dist/library/entries/conversion.entries.js.map +1 -0
- package/dist/library/entries/data.entries.d.ts +7 -0
- package/dist/library/entries/data.entries.js +4613 -0
- package/dist/library/entries/data.entries.js.map +1 -0
- package/dist/library/entries/events.entries.d.ts +2 -0
- package/dist/library/entries/events.entries.js +3428 -0
- package/dist/library/entries/events.entries.js.map +1 -0
- package/dist/library/entries/features.entries.d.ts +2 -0
- package/dist/library/entries/features.entries.js +3157 -0
- package/dist/library/entries/features.entries.js.map +1 -0
- package/dist/library/entries/heroes.entries.d.ts +2 -0
- package/dist/library/entries/heroes.entries.js +3401 -0
- package/dist/library/entries/heroes.entries.js.map +1 -0
- package/dist/library/entries/index.d.ts +3 -0
- package/dist/library/entries/index.js +35 -0
- package/dist/library/entries/index.js.map +1 -0
- package/dist/library/entries/listings.entries.d.ts +2 -0
- package/dist/library/entries/listings.entries.js +2976 -0
- package/dist/library/entries/listings.entries.js.map +1 -0
- package/dist/library/entries/longform.entries.d.ts +2 -0
- package/dist/library/entries/longform.entries.js +4227 -0
- package/dist/library/entries/longform.entries.js.map +1 -0
- package/dist/library/entries/media.entries.d.ts +2 -0
- package/dist/library/entries/media.entries.js +2781 -0
- package/dist/library/entries/media.entries.js.map +1 -0
- package/dist/library/entries/navigation.entries.d.ts +2 -0
- package/dist/library/entries/navigation.entries.js +4011 -0
- package/dist/library/entries/navigation.entries.js.map +1 -0
- package/dist/library/entries/pricing.entries.d.ts +2 -0
- package/dist/library/entries/pricing.entries.js +2383 -0
- package/dist/library/entries/pricing.entries.js.map +1 -0
- package/dist/library/entries/social-proof.entries.d.ts +2 -0
- package/dist/library/entries/social-proof.entries.js +2297 -0
- package/dist/library/entries/social-proof.entries.js.map +1 -0
- package/dist/library/examples/bento.d.ts +92 -0
- package/dist/library/examples/bento.js +201 -0
- package/dist/library/examples/bento.js.map +1 -0
- package/dist/library/examples/blocks.d.ts +14 -0
- package/dist/library/examples/blocks.js +313 -0
- package/dist/library/examples/blocks.js.map +1 -0
- package/dist/library/examples/faq.d.ts +28 -0
- package/dist/library/examples/faq.js +230 -0
- package/dist/library/examples/faq.js.map +1 -0
- package/dist/library/examples/hero.d.ts +43 -0
- package/dist/library/examples/hero.js +222 -0
- package/dist/library/examples/hero.js.map +1 -0
- package/dist/library/examples/index.d.ts +36 -0
- package/dist/library/examples/index.js +109 -0
- package/dist/library/examples/index.js.map +1 -0
- package/dist/library/examples/journalStory.d.ts +93 -0
- package/dist/library/examples/journalStory.js +338 -0
- package/dist/library/examples/journalStory.js.map +1 -0
- package/dist/library/examples/megaMenu.d.ts +134 -0
- package/dist/library/examples/megaMenu.js +442 -0
- package/dist/library/examples/megaMenu.js.map +1 -0
- package/dist/library/examples/pricing.d.ts +103 -0
- package/dist/library/examples/pricing.js +479 -0
- package/dist/library/examples/pricing.js.map +1 -0
- package/dist/library/examples/tabs.d.ts +87 -0
- package/dist/library/examples/tabs.js +180 -0
- package/dist/library/examples/tabs.js.map +1 -0
- package/dist/library/export.d.ts +42 -0
- package/dist/library/export.js +80 -0
- package/dist/library/export.js.map +1 -0
- package/dist/library/index.d.ts +13 -0
- package/dist/library/index.js +6 -0
- package/dist/library/kit-catalog.json +1511 -0
- package/dist/library/types.d.ts +42 -0
- package/dist/library/types.js +0 -0
- package/{schema → dist/schema}/adapters.js +1 -2
- package/dist/schema/adapters.js.map +1 -0
- package/{schema → dist/schema}/help.d.ts +2 -0
- package/{schema → dist/schema}/help.js +6 -4
- package/dist/schema/help.js.map +1 -0
- package/{schema → dist/schema}/scale.js +1 -1
- package/dist/schema/scale.js.map +1 -0
- package/{schema → dist/schema}/sources.js +1 -1
- package/dist/schema/sources.js.map +1 -0
- package/{schema → dist/schema}/table.js +11 -10
- package/dist/schema/table.js.map +1 -0
- package/{schema → dist/schema}/types.d.ts +36 -1
- package/{schema → dist/schema}/types.js +1 -1
- package/dist/schema/types.js.map +1 -0
- package/dist/styles.css +2 -0
- package/dist/table/table-view.d.ts +14 -0
- package/dist/table/table-view.js +140 -0
- package/dist/table/table-view.js.map +1 -0
- package/dist/table/table.css +73 -0
- package/dist/testing/corpus.d.ts +63 -0
- package/dist/testing/corpus.js +129 -0
- package/dist/testing/corpus.js.map +1 -0
- package/dist/testing/test-form.d.ts +11 -0
- package/dist/testing/test-form.js +38 -0
- package/dist/testing/test-form.js.map +1 -0
- package/dist/theme.css +345 -0
- package/dist/theme.d.ts +22 -0
- package/dist/theme.js +43 -0
- package/dist/theme.js.map +1 -0
- package/dist/tokens.css +542 -0
- package/dist/types.js +0 -0
- package/{ui → dist/ui}/action-tray.d.ts +1 -1
- package/{ui → dist/ui}/action-tray.js +20 -19
- package/dist/ui/action-tray.js.map +1 -0
- package/dist/ui/autocomplete.d.ts +58 -0
- package/dist/ui/autocomplete.js +194 -0
- package/dist/ui/autocomplete.js.map +1 -0
- package/{ui → dist/ui}/button.d.ts +3 -3
- package/{ui → dist/ui}/button.js +8 -11
- package/dist/ui/button.js.map +1 -0
- package/{ui → dist/ui}/choice-switch.js +1 -1
- package/dist/ui/choice-switch.js.map +1 -0
- package/{ui → dist/ui}/controls.js +51 -39
- package/dist/ui/controls.js.map +1 -0
- package/{ui → dist/ui}/display.d.ts +10 -3
- package/{ui → dist/ui}/display.js +57 -46
- package/dist/ui/display.js.map +1 -0
- package/{ui → dist/ui}/expanded-editor-modal.d.ts +2 -2
- package/{ui → dist/ui}/expanded-editor-modal.js +6 -6
- package/dist/ui/expanded-editor-modal.js.map +1 -0
- package/{ui → dist/ui}/field-context.js +1 -1
- package/dist/ui/field-context.js.map +1 -0
- package/{ui → dist/ui}/floating-panel.d.ts +1 -1
- package/{ui → dist/ui}/floating-panel.js +28 -12
- package/dist/ui/floating-panel.js.map +1 -0
- package/{ui → dist/ui}/index.d.ts +4 -0
- package/dist/ui/index.js +18 -0
- package/{ui → dist/ui}/input.d.ts +1 -1
- package/{ui → dist/ui}/input.js +9 -9
- package/dist/ui/input.js.map +1 -0
- package/{ui → dist/ui}/mode-bar.js +3 -3
- package/dist/ui/mode-bar.js.map +1 -0
- package/{ui → dist/ui}/overlay.d.ts +77 -5
- package/dist/ui/overlay.js +697 -0
- package/dist/ui/overlay.js.map +1 -0
- package/{ui → dist/ui}/path-crumbs.js +37 -3
- package/dist/ui/path-crumbs.js.map +1 -0
- package/{ui → dist/ui}/presence.js +2 -2
- package/dist/ui/presence.js.map +1 -0
- package/{ui → dist/ui}/select.js +89 -87
- package/dist/ui/select.js.map +1 -0
- package/{ui → dist/ui}/shortcut-hint.js +1 -1
- package/dist/ui/shortcut-hint.js.map +1 -0
- package/dist/ui/spinner.d.ts +24 -0
- package/dist/ui/spinner.js +42 -0
- package/dist/ui/spinner.js.map +1 -0
- package/dist/ui/split-button.d.ts +32 -0
- package/dist/ui/split-button.js +60 -0
- package/dist/ui/split-button.js.map +1 -0
- package/{ui → dist/ui}/surfaces.js +1 -1
- package/dist/ui/surfaces.js.map +1 -0
- package/dist/ui/tab.d.ts +38 -0
- package/dist/ui/tab.js +87 -0
- package/dist/ui/tab.js.map +1 -0
- package/dist/ui/toast.d.ts +20 -0
- package/dist/ui/toast.js +115 -0
- package/dist/ui/toast.js.map +1 -0
- package/{ui → dist/ui}/tooltip-root.d.ts +4 -3
- package/{ui → dist/ui}/tooltip-root.js +9 -8
- package/dist/ui/tooltip-root.js.map +1 -0
- package/{ui → dist/ui}/variants.js +1 -1
- package/dist/ui/variants.js.map +1 -0
- package/package.json +83 -23
- package/adapters/icons.js.map +0 -1
- package/adapters/lossy.js +0 -233
- package/adapters/lossy.js.map +0 -1
- package/adapters/prod-types.js.map +0 -1
- package/adapters/schema.js.map +0 -1
- package/adapters/values.js.map +0 -1
- package/brand/logo.js +0 -9
- package/brand/logo.js.map +0 -1
- package/context.js.map +0 -1
- package/controls/button.js.map +0 -1
- package/controls/c1.js.map +0 -1
- package/controls/c2.js.map +0 -1
- package/controls/choice.js.map +0 -1
- package/controls/code-register.js.map +0 -1
- package/controls/code.js.map +0 -1
- package/controls/color.js.map +0 -1
- package/controls/date-register.js.map +0 -1
- package/controls/date-zone.js.map +0 -1
- package/controls/date.js.map +0 -1
- package/controls/form-picker-register.d.ts +0 -1
- package/controls/form-picker-register.js.map +0 -1
- package/controls/form-picker.js.map +0 -1
- package/controls/icon-register.js.map +0 -1
- package/controls/icon.js.map +0 -1
- package/controls/index.js.map +0 -1
- package/controls/json-register.js.map +0 -1
- package/controls/json.js.map +0 -1
- package/controls/link.js.map +0 -1
- package/controls/location-register.js.map +0 -1
- package/controls/location.js.map +0 -1
- package/controls/media-register.js.map +0 -1
- package/controls/media.js.map +0 -1
- package/controls/number.js.map +0 -1
- package/controls/reference-register.js.map +0 -1
- package/controls/reference.js.map +0 -1
- package/controls/rich-text/blocks.d.ts +0 -28
- package/controls/rich-text/blocks.js.map +0 -1
- package/controls/rich-text/catalog.js.map +0 -1
- package/controls/rich-text/codec.js.map +0 -1
- package/controls/rich-text/component-card.js.map +0 -1
- package/controls/rich-text/control.js.map +0 -1
- package/controls/rich-text/dom.js.map +0 -1
- package/controls/rich-text/editor.js.map +0 -1
- package/controls/rich-text/floating.js.map +0 -1
- package/controls/rich-text/index.js.map +0 -1
- package/controls/rich-text/link-form.js +0 -111
- package/controls/rich-text/link-form.js.map +0 -1
- package/controls/rich-text/markdown.js.map +0 -1
- package/controls/rich-text/ops.js.map +0 -1
- package/controls/rich-text/toolbar.js.map +0 -1
- package/controls/scale.js.map +0 -1
- package/controls/slot-register.d.ts +0 -1
- package/controls/slot-register.js.map +0 -1
- package/controls/slot-services.js +0 -38
- package/controls/slot-services.js.map +0 -1
- package/controls/slot.js.map +0 -1
- package/controls/table/index.js.map +0 -1
- package/controls/table/prod.js.map +0 -1
- package/controls/table/refs.js.map +0 -1
- package/controls/table/stored.js.map +0 -1
- package/controls/table/table-editor.js.map +0 -1
- package/controls/table/table-link.js.map +0 -1
- package/controls/table/table.js.map +0 -1
- package/controls/text.js.map +0 -1
- package/engine/array.js.map +0 -1
- package/engine/bits.js.map +0 -1
- package/engine/breadcrumb.js.map +0 -1
- package/engine/expand.js.map +0 -1
- package/engine/field-list.js.map +0 -1
- package/engine/field-shell.js.map +0 -1
- package/engine/frame.js.map +0 -1
- package/engine/group-summary.js.map +0 -1
- package/engine/grouping.js.map +0 -1
- package/engine/item-list.js.map +0 -1
- package/engine/kit-field.js.map +0 -1
- package/engine/schema-form.js.map +0 -1
- package/engine/slot.js.map +0 -1
- package/index.js +0 -55
- package/index.js.map +0 -1
- package/lib/cn.js.map +0 -1
- package/lib/columns.js.map +0 -1
- package/lib/frames.js.map +0 -1
- package/lib/icons.js.map +0 -1
- package/lib/path.js.map +0 -1
- package/lib/schema.js.map +0 -1
- package/lib/utils.js.map +0 -1
- package/lib/validate.js.map +0 -1
- package/schema/adapters.js.map +0 -1
- package/schema/help.js.map +0 -1
- package/schema/scale.js.map +0 -1
- package/schema/sources.js.map +0 -1
- package/schema/table.js.map +0 -1
- package/schema/types.js.map +0 -1
- package/ui/action-tray.js.map +0 -1
- package/ui/button.js.map +0 -1
- package/ui/choice-switch.js.map +0 -1
- package/ui/controls.js.map +0 -1
- package/ui/display.js.map +0 -1
- package/ui/expanded-editor-modal.js.map +0 -1
- package/ui/field-context.js.map +0 -1
- package/ui/floating-panel.js.map +0 -1
- package/ui/index.js +0 -13
- package/ui/input.js.map +0 -1
- package/ui/mode-bar.js.map +0 -1
- package/ui/overlay.js +0 -378
- package/ui/overlay.js.map +0 -1
- package/ui/path-crumbs.js.map +0 -1
- package/ui/presence.js.map +0 -1
- package/ui/select.js.map +0 -1
- package/ui/shortcut-hint.js.map +0 -1
- package/ui/surfaces.js.map +0 -1
- package/ui/tooltip-root.js.map +0 -1
- package/ui/variants.js.map +0 -1
- /package/{_virtual → dist/_virtual}/_rolldown/runtime.js +0 -0
- /package/{adapters → dist/adapters}/icons.d.ts +0 -0
- /package/{brand → dist/brand}/logo.d.ts +0 -0
- /package/{controls → dist/controls}/c1.d.ts +0 -0
- /package/{controls → dist/controls}/c2.d.ts +0 -0
- /package/{controls → dist/controls}/code-register.d.ts +0 -0
- /package/{controls → dist/controls}/code.d.ts +0 -0
- /package/{controls → dist/controls}/color.d.ts +0 -0
- /package/{controls → dist/controls}/date-register.d.ts +0 -0
- /package/{controls → dist/controls}/date-zone.d.ts +0 -0
- /package/{controls → dist/controls}/date.d.ts +0 -0
- /package/{controls → dist/controls}/form-picker.d.ts +0 -0
- /package/{controls → dist/controls}/icon-register.d.ts +0 -0
- /package/{controls → dist/controls}/json-register.d.ts +0 -0
- /package/{controls → dist/controls}/json.d.ts +0 -0
- /package/{controls → dist/controls}/link.d.ts +0 -0
- /package/{controls → dist/controls}/location-register.d.ts +0 -0
- /package/{controls → dist/controls}/location.d.ts +0 -0
- /package/{controls → dist/controls}/media-register.d.ts +0 -0
- /package/{controls → dist/controls}/number.d.ts +0 -0
- /package/{controls → dist/controls}/reference-register.d.ts +0 -0
- /package/{controls → dist/controls}/rich-text/index.d.ts +0 -0
- /package/{controls → dist/controls}/rich-text/markdown.d.ts +0 -0
- /package/{controls → dist/controls}/rich-text/ops.d.ts +0 -0
- /package/{controls → dist/controls}/scale.d.ts +0 -0
- /package/{controls → dist/controls}/slot.d.ts +0 -0
- /package/{controls → dist/controls}/table/index.d.ts +0 -0
- /package/{controls → dist/controls}/table/prod.d.ts +0 -0
- /package/{controls → dist/controls}/table/refs.d.ts +0 -0
- /package/{controls → dist/controls}/table/stored.d.ts +0 -0
- /package/{controls → dist/controls}/table/table-editor.d.ts +0 -0
- /package/{controls → dist/controls}/table/table-link.d.ts +0 -0
- /package/{controls → dist/controls}/table/table.d.ts +0 -0
- /package/{engine → dist/engine}/array.d.ts +0 -0
- /package/{engine → dist/engine}/bits.d.ts +0 -0
- /package/{engine → dist/engine}/field-list.d.ts +0 -0
- /package/{engine → dist/engine}/field-shell.d.ts +0 -0
- /package/{engine → dist/engine}/kit-field.d.ts +0 -0
- /package/{engine → dist/engine}/slot.d.ts +0 -0
- /package/{index.d.ts → dist/index.d.ts} +0 -0
- /package/{lib → dist/lib}/cn.d.ts +0 -0
- /package/{lib → dist/lib}/columns.d.ts +0 -0
- /package/{lib → dist/lib}/frames.d.ts +0 -0
- /package/{lib → dist/lib}/icons.d.ts +0 -0
- /package/{lib → dist/lib}/path.d.ts +0 -0
- /package/{lib → dist/lib}/utils.d.ts +0 -0
- /package/{schema → dist/schema}/adapters.d.ts +0 -0
- /package/{schema → dist/schema}/scale.d.ts +0 -0
- /package/{schema → dist/schema}/sources.d.ts +0 -0
- /package/{schema → dist/schema}/table.d.ts +0 -0
- /package/{types.d.ts → dist/types.d.ts} +0 -0
- /package/{ui → dist/ui}/choice-switch.d.ts +0 -0
- /package/{ui → dist/ui}/controls.d.ts +0 -0
- /package/{ui → dist/ui}/field-context.d.ts +0 -0
- /package/{ui → dist/ui}/mode-bar.d.ts +0 -0
- /package/{ui → dist/ui}/path-crumbs.d.ts +0 -0
- /package/{ui → dist/ui}/presence.d.ts +0 -0
- /package/{ui → dist/ui}/select.d.ts +0 -0
- /package/{ui → dist/ui}/shortcut-hint.d.ts +0 -0
- /package/{ui → dist/ui}/surfaces.d.ts +0 -0
- /package/{ui → dist/ui}/variants.d.ts +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"choice.js","names":[],"sources":["../../src/controls/choice.tsx"],"sourcesContent":["/**\n * CHOICE — boolean · select · multiselect · tags (V2 HEAD 9829bf1 kit/controls/choice.tsx, DESIGN 8.10–8.12).\n * Rule (production): few options → segmented, many → dropdown, many values → checkboxes, on/off → switch card.\n * D46: `layout: \"segmented\"` is a request, not a promise. With 4+ options, or labels that would wrap or truncate\n * in a 340px inspector (`fitsSegmented`), it renders the dropdown instead, so every schema follows the rule.\n *\n * Values are the ones production stores, untouched by any adapter (schema.ts plans them AS_IS): boolean, the option's\n * string, a string[] of option values, a string[] of tags. Tags are written the way the backend judges them\n * (tagsValueProblem: trimmed, case-insensitively unique, at most TAG_VALUE_MAX_LENGTH characters), and a tag the\n * control will not add says why under the box instead of vanishing.\n *\n * Option icons are all or none per list (the schema adapter's rule): a list draws icons only when every option names an\n * icon that can be drawn, so labels stay aligned and no option gets a stand-in glyph. The host's glyphs come first\n * (KitServices.IconGlyph, the BetterCMS set the site renders: every stored option icon is one of its names); with no\n * host renderer, the kit's own drawn icons.\n */\nimport * as React from \"react\";\nimport { IconCheck, IconPlus, IconX } from \"@tabler/icons-react\";\nimport { Checkbox, Segmented, Switch } from \"../ui/controls\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"../ui/overlay\";\nimport { Select } from \"../ui/select\";\nimport { fitsSegmented } from \"../ui/choice-switch\";\nimport { shortcutHintsOn } from \"../ui/shortcut-hint\";\nimport { cn } from \"../lib/cn\";\nimport { KitIcon, iconKey } from \"../lib/icons\";\nimport type { Option } from \"../schema/types\";\nimport { useKitEnv, useKitServices, type KitServices } from \"../context\";\nimport { dockIconOf } from \"../adapters/icons\";\nimport type { ControlProps } from \"../types\";\nimport { TAG_VALUE_MAX_LENGTH } from \"../adapters/prod-types\";\nimport { UnknownValueNote } from \"./unknown-value\";\n\nconst str = (v: unknown) => (typeof v === \"string\" ? v : v == null ? \"\" : String(v));\nconst opts = (o?: Option[]) => o ?? [];\n\n/**\n * Icons for a list: every option's icon when all of them resolve, otherwise none (never a fallback glyph). `Glyph` is\n * the host's renderer (KitServices.IconGlyph): it draws every BetterCMS icon name (the option's kit name read back\n * through dockIconOf); without it, or when a name is not in that set, the kit's own drawn icons.\n */\nexport function optionIcons(options: Option[], className?: string, Glyph?: KitServices[\"IconGlyph\"]): (React.ReactNode | undefined)[] {\n if (options.length === 0) return [];\n const dock = options.map((o) => dockIconOf(o.icon));\n // a block box, as the kit's own <svg> is under preflight: an inline glyph would sit on a line box and grow the row\n if (Glyph && dock.every((n) => n !== undefined)) return dock.map((n) => <Glyph name={n!} className={cn(\"flex\", className)} />);\n const all = options.every((o) => iconKey(o.icon) !== undefined);\n return options.map((o) => (all ? <KitIcon name={o.icon} className={className} /> : undefined));\n}\n\n/** The limit sentence (DESIGN 8.12), shared by multiselect and tags. */\nfunction LimitLine({ max }: { max: number }) {\n return <span className=\"px-0.5 text-kit-xs text-kit-fg-3\">That's the limit of {max}. Remove one to add another.</span>;\n}\n\n/**\n * Roving focus for a radiogroup of buttons (WAI-ARIA radio group, as Segmented does): Tab lands on the selected option\n * (or the first), arrows move and select, Home / End jump.\n */\nfunction useRadioKeys(values: string[], current: string, onPick: (v: string) => void, readOnly?: boolean) {\n const focusable = values.includes(current) ? current : values[0];\n const onKeyDown = (e: React.KeyboardEvent, i: number) => {\n if (readOnly || !values.length) return;\n const n = values.length;\n const next =\n e.key === \"ArrowRight\" || e.key === \"ArrowDown\"\n ? (i + 1) % n\n : e.key === \"ArrowLeft\" || e.key === \"ArrowUp\"\n ? (i - 1 + n) % n\n : e.key === \"Home\"\n ? 0\n : e.key === \"End\"\n ? n - 1\n : -1;\n if (next < 0) return;\n e.preventDefault();\n onPick(values[next]);\n const group = (e.currentTarget as HTMLElement).closest(\"[role=radiogroup]\");\n group?.querySelector<HTMLElement>(`[data-choice-value=\"${CSS.escape(values[next])}\"]`)?.focus();\n };\n return { tabIndexOf: (v: string) => (v === focusable ? 0 : -1), onKeyDown };\n}\n\n/**\n * Adds or removes one id of the control's own in aria-describedby, leaving the ids FieldShell wires (help, issue)\n * in place (as ScaleSlider does).\n */\nexport function useOwnDescription(ref: React.RefObject<HTMLElement | null>, ownId: string | null) {\n const last = React.useRef<string | null>(null);\n React.useEffect(() => {\n const el = ref.current;\n if (!el) return;\n const ids = (el.getAttribute(\"aria-describedby\") ?? \"\").split(\" \").filter((t) => t && t !== last.current && t !== ownId);\n if (ownId) ids.push(ownId);\n if (ids.length) el.setAttribute(\"aria-describedby\", ids.join(\" \"));\n else el.removeAttribute(\"aria-describedby\");\n last.current = ownId;\n });\n}\n\n/** Boolean switch (used inside the switch card the shell draws). Commits immediately. */\nexport function BooleanControl({ field, value, onChange, readOnly, id }: ControlProps) {\n if (field.layout === \"checkbox\")\n return <Checkbox id={id} checked={Boolean(value)} disabled={readOnly} onCheckedChange={(c) => onChange(c === true)} aria-label={field.title} nativeButton render={<button type=\"button\" />} />;\n /* V2's switch is a native <button role=\"switch\"> (Radix); Base UI draws a <span> unless asked for the button */\n return <Switch id={id} checked={Boolean(value)} disabled={readOnly} onCheckedChange={(c) => onChange(c)} aria-label={field.title} nativeButton render={<button type=\"button\" />} />;\n}\n\n/**\n * A stored value none of the options names any more (renamed or removed) is kept and flagged under the control, with\n * change-to and remove (H4). @see UnknownValueNote\n */\nexport function SelectControl(props: ControlProps) {\n const options = opts(props.field.options);\n const v = str(props.value);\n if (v === \"\" || options.length === 0 || options.some((o) => o.value === v)) return <SelectInput {...props} />;\n return (\n <div className=\"flex min-w-0 flex-col gap-1.5\">\n <SelectInput {...props} />\n <UnknownValueNote\n items={[{ key: v, label: `“${v}”`, options: options.map((o) => ({ value: o.value, label: o.label })) }]}\n onRemap={(_, to) => props.onChange(to)}\n onRemove={() => props.onChange(null)}\n readOnly={props.readOnly}\n />\n </div>\n );\n}\n\nfunction SelectInput({ field, value, onChange, readOnly, id }: ControlProps) {\n const { variant } = useKitEnv();\n const { IconGlyph } = useKitServices();\n const options = opts(field.options);\n const v = str(value);\n const fits = fitsSegmented(options.map((o) => o.label));\n const layout = field.layout ?? (fits ? \"segmented\" : \"dropdown\");\n const pick = (n: string) => {\n if (!readOnly && n !== v) onChange(n);\n };\n const keys = useRadioKeys(\n options.map((o) => o.value),\n v,\n pick,\n readOnly,\n );\n\n if (layout === \"segmented\" && fits) {\n const icons = optionIcons(options, \"size-3.5\", IconGlyph);\n return (\n <Segmented\n aria-label={field.title}\n value={v}\n onChange={pick}\n items={options.map((o, i) => ({ value: o.value, label: o.label, icon: icons[i], disabled: readOnly }))}\n className=\"w-full [&>button]:min-w-0 [&>button]:flex-1\"\n />\n );\n }\n if (layout === \"radio\")\n return (\n <div role=\"radiogroup\" id={id} aria-label={field.title} className=\"flex flex-col gap-0.5\">\n {options.map((o, i) => (\n <button\n key={o.value}\n type=\"button\"\n role=\"radio\"\n data-choice-value={o.value}\n aria-checked={o.value === v}\n tabIndex={keys.tabIndexOf(o.value)}\n disabled={readOnly}\n onClick={() => pick(o.value)}\n onKeyDown={(e) => keys.onKeyDown(e, i)}\n className=\"flex items-start gap-2.5 rounded-kit-md px-1.5 py-1.5 text-left hover:bg-kit-hover\"\n >\n <span className={cn(\"mt-0.5 flex size-4 shrink-0 items-center justify-center rounded-full border transition-colors\", o.value === v ? \"border-kit-accent\" : \"border-kit-line-strong\")}>\n {o.value === v ? <span className=\"size-2 rounded-full bg-kit-accent\" /> : null}\n </span>\n <span className=\"min-w-0\">\n <span className=\"block text-kit-sm text-kit-fg\">{o.label}</span>\n {o.description ? <span className=\"block text-kit-xs text-kit-fg-3\">{o.description}</span> : null}\n </span>\n </button>\n ))}\n </div>\n );\n if (layout === \"cards\" || layout === \"grid\") {\n /* V2 draws the icon itself as the button's first child (no wrapper), coloured by the selected state */\n const iconsOn = optionIcons(options, \"size-4 text-kit-fg\", IconGlyph);\n const iconsOff = optionIcons(options, \"size-4 text-kit-fg-3\", IconGlyph);\n return (\n <div role=\"radiogroup\" id={id} aria-label={field.title} className={cn(\"grid gap-1.5\", variant === \"document\" ? \"grid-cols-3\" : \"grid-cols-2\")}>\n {options.map((o, i) => {\n const on = o.value === v;\n return (\n <button\n key={o.value}\n type=\"button\"\n role=\"radio\"\n data-choice-value={o.value}\n aria-checked={on}\n tabIndex={keys.tabIndexOf(o.value)}\n disabled={readOnly}\n onClick={() => pick(o.value)}\n onKeyDown={(e) => keys.onKeyDown(e, i)}\n className={cn(\n \"relative flex flex-col items-start gap-1.5 rounded-kit-lg border p-2.5 text-left transition-[border-color,box-shadow] duration-150\",\n on ? \"border-[var(--kit-emphasis-line)] bg-kit-control-bg shadow-kit-xs\" : \"border-kit-line hover:border-kit-line-strong\",\n )}\n >\n {(on ? iconsOn : iconsOff)[i] ?? null}\n <span className=\"text-kit-sm font-medium text-kit-fg\">{o.label}</span>\n {o.description ? <span className=\"text-kit-xs leading-4 text-kit-fg-3\">{o.description}</span> : null}\n {on ? <IconCheck aria-hidden className=\"absolute right-2 top-2 size-3.5 text-kit-fg\" stroke={2} /> : null}\n </button>\n );\n })}\n </div>\n );\n }\n const icons = optionIcons(options, undefined, IconGlyph);\n return (\n <Select\n id={id}\n aria-label={field.title}\n size={variant === \"document\" ? \"lg\" : \"md\"}\n value={v || undefined}\n disabled={readOnly}\n onValueChange={pick}\n placeholder={field.placeholder ?? \"Select…\"}\n options={options.map((o, i) => ({ value: o.value, label: o.label, description: o.description, icon: icons[i] }))}\n />\n );\n}\n\n/** As `SelectControl`: each stored choice no option names any more is kept and flagged, with change-to and remove. */\nexport function MultiSelectControl(props: ControlProps) {\n const list = Array.isArray(props.value) ? (props.value as unknown[]).filter((x): x is string => typeof x === \"string\") : [];\n const options = opts(props.field.options);\n const unknown = options.length ? list.filter((x) => !options.some((o) => o.value === x)) : [];\n if (unknown.length === 0) return <MultiSelectInput {...props} />;\n return (\n <div className=\"flex min-w-0 flex-col gap-1.5\">\n <MultiSelectInput {...props} />\n <UnknownValueNote\n items={unknown.map((x) => ({ key: x, label: `“${x}”`, options: options.filter((o) => !list.includes(o.value)).map((o) => ({ value: o.value, label: o.label })) }))}\n onRemap={(from, to) => props.onChange(list.map((x) => (x === from ? to : x)))}\n onRemove={(from) => props.onChange(list.filter((x) => x !== from))}\n readOnly={props.readOnly}\n />\n </div>\n );\n}\n\nfunction MultiSelectInput({ field, value, onChange, readOnly, id }: ControlProps) {\n const list = Array.isArray(value) ? (value as unknown[]).filter((x): x is string => typeof x === \"string\") : [];\n const options = opts(field.options);\n const max = field.validation?.max;\n const full = max != null && list.length >= max;\n const toggle = (o: string) => {\n if (readOnly) return;\n if (list.includes(o)) onChange(list.filter((x) => x !== o));\n else if (!full) onChange([...list, o]);\n };\n const label = (val: string) => options.find((o) => o.value === val)?.label ?? val;\n /* V2 draws the control bare; the limit line (ours: say why the next pick is refused) wraps it only while it shows */\n const withLimit = (body: React.ReactElement) =>\n full && !readOnly ? (\n <div className=\"flex flex-col gap-1\">\n {body}\n <LimitLine max={max!} />\n </div>\n ) : (\n body\n );\n if (field.layout === \"checkbox\" || field.layout === \"list\")\n return withLimit(\n <>\n <div id={id} role=\"group\" aria-label={field.title} className=\"flex flex-col gap-0.5\">\n {options.map((o) => {\n const on = list.includes(o.value);\n return (\n <label key={o.value} className={cn(\"flex cursor-pointer items-center gap-2.5 rounded-kit-md px-1.5 py-1.5 hover:bg-kit-hover\", !on && full && \"cursor-not-allowed hover:bg-transparent\")}>\n <Checkbox checked={on} disabled={readOnly || (!on && full)} onCheckedChange={() => toggle(o.value)} nativeButton render={<button type=\"button\" />} />\n <span className=\"text-kit-sm text-kit-fg\">{o.label}</span>\n </label>\n );\n })}\n </div>\n </>,\n );\n return withLimit(\n <>\n <Popover>\n {/* read-only there is no trigger to carry the field id, so the chip row is the named group */}\n <div\n id={readOnly ? id : undefined}\n role={readOnly ? \"group\" : undefined}\n aria-label={readOnly ? field.title : undefined}\n className=\"flex min-h-8 flex-wrap items-center gap-1 rounded-kit-md border border-kit-line-strong bg-kit-field-bg p-1 transition-colors hover:border-kit-line-strong\"\n >\n {list.map((o) => (\n <span key={o} className=\"inline-flex h-6 items-center gap-1 rounded-kit-md border border-kit-line bg-kit-control-bg pl-2 pr-1 text-kit-sm text-kit-fg shadow-kit-xs\">\n {label(o)}\n {readOnly ? null : (\n <button type=\"button\" aria-label={`Remove ${label(o)}`} onClick={() => toggle(o)} className=\"flex rounded-kit-md p-0.5 text-kit-fg-3 hover:bg-kit-hover hover:text-kit-fg\">\n <IconX className=\"size-3\" stroke={1.5} />\n </button>\n )}\n </span>\n ))}\n {readOnly ? null : (\n <PopoverTrigger id={id} className=\"inline-flex h-6 items-center gap-1 rounded-kit-md px-1.5 text-kit-sm text-kit-fg-3 hover:bg-kit-hover hover:text-kit-fg\">\n <IconPlus aria-hidden className=\"size-3.5\" stroke={1.5} />\n {list.length ? \"Add\" : field.placeholder ?? \"Choose…\"}\n </PopoverTrigger>\n )}\n </div>\n <PopoverContent className=\"w-60 p-1\">\n <div role=\"group\" aria-label={field.title}>\n {options.map((o) => {\n const on = list.includes(o.value);\n const blocked = !on && full;\n return (\n <button\n key={o.value}\n type=\"button\"\n role=\"checkbox\"\n aria-checked={on}\n disabled={blocked}\n onClick={() => toggle(o.value)}\n className={cn(\"flex h-8 w-full items-center gap-2 rounded-kit-md px-2 text-left text-kit-sm hover:bg-kit-hover\", blocked && \"opacity-40 hover:bg-transparent\")}\n >\n <span className={cn(\"flex size-4 items-center justify-center rounded-kit-md border\", on ? \"border-kit-accent bg-kit-accent text-kit-accent-on\" : \"border-kit-line-strong\")}>\n {on ? <IconCheck aria-hidden className=\"size-3\" stroke={3} /> : null}\n </span>\n {o.label}\n </button>\n );\n })}\n </div>\n {full ? <div className=\"px-2 pb-1 pt-1.5\"><LimitLine max={max!} /></div> : null}\n </PopoverContent>\n </Popover>\n </>,\n );\n}\n\n/** Why a typed tag is not added, or null when it is (the backend's own checks, said in words). */\nexport function tagRefusal(tag: string, list: string[]): string | null {\n if (Array.from(tag).length > TAG_VALUE_MAX_LENGTH) return `A tag can be up to ${TAG_VALUE_MAX_LENGTH} characters.`;\n const folded = tag.toLowerCase();\n const twin = list.find((t) => t.trim().toLowerCase() === folded);\n if (twin !== undefined) return `\"${twin}\" is already a tag.`;\n return null;\n}\n\n/** Chip input. Says so at its limit, and says why a tag was not added, instead of silently dropping it. */\nexport function TagsControl({ field, value, onChange, readOnly, id, onBlur }: ControlProps) {\n const list = Array.isArray(value) ? (value as unknown[]).map((x) => str(x)) : [];\n const [draft, setDraft] = React.useState(\"\");\n const [refusal, setRefusal] = React.useState<string | null>(null);\n const reasonId = React.useId();\n const inputRef = React.useRef<HTMLInputElement>(null);\n useOwnDescription(inputRef, refusal ? reasonId : null);\n const max = field.validation?.max;\n const full = max != null && list.length >= max;\n const add = () => {\n const t = draft.trim().replace(/,$/, \"\").trim();\n if (!t || full) {\n setDraft(\"\");\n setRefusal(null);\n return;\n }\n const why = tagRefusal(t, list);\n if (why) {\n // keep the text so it can be fixed; the reason reads under the box\n setRefusal(why);\n return;\n }\n onChange([...list, t]);\n setDraft(\"\");\n setRefusal(null);\n };\n return (\n <div className=\"flex flex-col gap-1\">\n <div className=\"flex min-h-8 flex-wrap items-center gap-1 rounded-kit-md border border-kit-line-strong bg-kit-field-bg p-1 transition-colors focus-within:border-kit-line-strong focus-within:bg-kit-field-bg hover:border-kit-line-strong\">\n {list.map((t, i) => (\n <span key={`${t}-${i}`} className=\"inline-flex h-6 items-center gap-1 rounded-kit-md bg-kit-selected pl-2 pr-1 text-kit-sm text-kit-fg\">\n {t}\n {readOnly ? null : (\n <button type=\"button\" aria-label={`Remove ${t}`} onClick={() => onChange(list.filter((_, j) => j !== i))} className=\"flex rounded-kit-md p-0.5 text-kit-fg-3 hover:bg-kit-hover hover:text-kit-fg\">\n <IconX className=\"size-3\" stroke={1.5} />\n </button>\n )}\n </span>\n ))}\n {readOnly ? null : (\n <input\n ref={inputRef}\n id={id}\n value={draft}\n disabled={full}\n onChange={(e) => {\n setDraft(e.target.value);\n if (refusal) setRefusal(null);\n }}\n onBlur={() => {\n add();\n onBlur?.();\n }}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \",\") {\n e.preventDefault();\n add();\n } else if (e.key === \"Backspace\" && !draft && list.length) onChange(list.slice(0, -1));\n }}\n placeholder={full ? \"\" : list.length ? \"Add…\" : field.placeholder ?? (shortcutHintsOn() ? \"Type and press Enter\" : \"Add…\")}\n className=\"h-6 min-w-20 flex-1 bg-transparent px-1.5 text-kit-sm text-kit-fg outline-none placeholder:text-kit-fg-3\"\n />\n )}\n </div>\n {refusal && !readOnly ? (\n <span id={reasonId} role=\"status\" aria-live=\"polite\" className=\"px-0.5 text-kit-xs text-kit-fg-3\">\n {refusal}\n </span>\n ) : null}\n {full && !readOnly ? <LimitLine max={max!} /> : null}\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CodeControl } from "./code.js";
|
|
2
2
|
import { CONTROLS } from "../engine/kit-field.js";
|
|
3
|
-
//#region src/
|
|
3
|
+
//#region src/controls/code-register.ts
|
|
4
4
|
/** Lane C3: the code field in the engine's dispatch table (one line per type; merge with other lanes by line). */
|
|
5
5
|
CONTROLS.code = CodeControl;
|
|
6
6
|
//#endregion
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code-register.js","names":[],"sources":["../../src/controls/code-register.ts"],"sourcesContent":["/** Lane C3: the code field in the engine's dispatch table (one line per type; merge with other lanes by line). */\nimport { CONTROLS } from \"../engine/kit-field\";\nimport { CodeControl } from \"./code\";\n\nCONTROLS.code = CodeControl;\n"],"mappings":";;;;AAIA,SAAS,OAAO"}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { cn } from "../lib/cn.js";
|
|
2
|
-
import { isObj } from "../lib/path.js";
|
|
3
1
|
import { CODE_MAX_LENGTH } from "../adapters/prod-types.js";
|
|
2
|
+
import { cn } from "../lib/cn.js";
|
|
4
3
|
import { useKitEnv, useKitServices } from "../context.js";
|
|
4
|
+
import { isObj } from "../lib/path.js";
|
|
5
5
|
import { Button } from "../ui/button.js";
|
|
6
6
|
import { Modal, ModalBody, ModalContent, ModalFooter, ModalHeader } from "../ui/overlay.js";
|
|
7
7
|
import { Select } from "../ui/select.js";
|
|
8
8
|
import * as React from "react";
|
|
9
|
-
import { IconAlertTriangle, IconBraces, IconCode, IconMaximize } from "@tabler/icons-react";
|
|
10
9
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
11
|
-
|
|
10
|
+
import { IconAlertTriangle, IconBraces, IconCode, IconMaximize } from "@tabler/icons-react";
|
|
11
|
+
//#region src/controls/code.tsx
|
|
12
12
|
/**
|
|
13
13
|
* CODE — the code field (DESIGN 8.21), V2 controls/misc.tsx (CodeSurface, CodeControl) fitted to what prod stores.
|
|
14
14
|
*
|
|
@@ -103,7 +103,7 @@ function CodeSurface({ kind, value, onChange, language, onLanguage, languages, r
|
|
|
103
103
|
toast?.success("Copied");
|
|
104
104
|
};
|
|
105
105
|
return /* @__PURE__ */ jsxs("div", {
|
|
106
|
-
className: cn("overflow-hidden rounded-kit-lg border bg-kit-subtle
|
|
106
|
+
className: cn("overflow-hidden rounded-kit-lg border bg-kit-subtle", invalid || problem ? "border-[var(--kit-field-invalid)]" : "border-kit-line"),
|
|
107
107
|
children: [
|
|
108
108
|
/* @__PURE__ */ jsxs("div", {
|
|
109
109
|
className: "flex h-8 items-center justify-between border-b border-kit-line px-2",
|
|
@@ -126,7 +126,7 @@ function CodeSurface({ kind, value, onChange, language, onLanguage, languages, r
|
|
|
126
126
|
children: [kind === "json" ? /* @__PURE__ */ jsx("button", {
|
|
127
127
|
type: "button",
|
|
128
128
|
disabled: readOnly,
|
|
129
|
-
className: "rounded-kit-md px-1.5 py-0.5 text-kit-xs text-kit-fg-2 hover:bg-kit-hover hover:text-kit-fg
|
|
129
|
+
className: "rounded-kit-md px-1.5 py-0.5 text-kit-xs text-kit-fg-2 hover:bg-kit-hover hover:text-kit-fg",
|
|
130
130
|
onClick: format,
|
|
131
131
|
children: "Format"
|
|
132
132
|
}) : null, /* @__PURE__ */ jsx("button", {
|
|
@@ -194,7 +194,7 @@ function CodeDialogField({ kind, title, description, text, readOnly, id, invalid
|
|
|
194
194
|
setRefusal(null);
|
|
195
195
|
setOpen(true);
|
|
196
196
|
},
|
|
197
|
-
className: cn("group/code flex w-full
|
|
197
|
+
className: cn("group/code flex w-full items-center gap-2 rounded-kit-md border border-kit-line bg-kit-subtle px-2.5 py-2 text-left transition-colors hover:border-kit-line-strong", invalid && "border-[var(--kit-field-invalid)]"),
|
|
198
198
|
children: [
|
|
199
199
|
/* @__PURE__ */ jsx(Icon, {
|
|
200
200
|
className: "size-4 shrink-0 text-kit-fg-3",
|
|
@@ -206,7 +206,7 @@ function CodeDialogField({ kind, title, description, text, readOnly, id, invalid
|
|
|
206
206
|
children: first || "Empty"
|
|
207
207
|
}),
|
|
208
208
|
/* @__PURE__ */ jsx("span", {
|
|
209
|
-
className: "shrink-0 text-kit-2xs
|
|
209
|
+
className: "tabular-nums shrink-0 text-kit-2xs text-kit-fg-3",
|
|
210
210
|
children: text ? `${text.split("\n").length} lines` : ""
|
|
211
211
|
}),
|
|
212
212
|
/* @__PURE__ */ jsx(IconMaximize, {
|
|
@@ -246,6 +246,7 @@ function CodeDialogField({ kind, title, description, text, readOnly, id, invalid
|
|
|
246
246
|
}) : null] }),
|
|
247
247
|
/* @__PURE__ */ jsxs(ModalFooter, { children: [
|
|
248
248
|
/* @__PURE__ */ jsx("span", {
|
|
249
|
+
"data-hint": "shortcuts",
|
|
249
250
|
className: "text-kit-xs text-kit-fg-3",
|
|
250
251
|
children: "Esc to close"
|
|
251
252
|
}),
|
|
@@ -391,6 +392,6 @@ function UnreadableValue({ id, title, kind, value }) {
|
|
|
391
392
|
});
|
|
392
393
|
}
|
|
393
394
|
//#endregion
|
|
394
|
-
export { CodeControl, CodeDialogField, CodeSurface, jsonProblem };
|
|
395
|
+
export { CodeControl, CodeDialogField, CodeSurface, UnreadableValue, jsonProblem };
|
|
395
396
|
|
|
396
397
|
//# sourceMappingURL=code.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code.js","names":[],"sources":["../../src/controls/code.tsx"],"sourcesContent":["/**\n * CODE — the code field (DESIGN 8.21), V2 controls/misc.tsx (CodeSurface, CodeControl) fitted to what prod stores.\n *\n * Values (backend reference-validation `code`, adapters/values.ts codeToProd):\n * \"<p>hi</p>\" a bare string, kept a string\n * { language?: \"html\", code: \"…\" } the object form; only `code` and `language` are written back\n * The language list sits in the surface header. Picking one writes the object form; a value that never changes its\n * language keeps the shape it was stored in. A value over CODE_MAX_LENGTH characters is refused with the reason.\n *\n * Panel: a one-line summary button that opens a `lg` dialog editing a draft (Cancel / Done). Document: the surface\n * inline. The surface: mono 12/20 textarea with line numbers, Tab inserts two spaces (Shift+Tab leaves the field),\n * Copy, and for JSON a Format action and a live \"Invalid JSON · {reason}\" footer (json.tsx).\n */\nimport * as React from \"react\";\nimport { IconAlertTriangle, IconBraces, IconCode, IconMaximize } from \"@tabler/icons-react\";\nimport { cn } from \"../lib/cn\";\nimport { isObj } from \"../lib/path\";\nimport { useKitEnv, useKitServices } from \"../context\";\nimport { CODE_MAX_LENGTH } from \"../adapters/prod-types\";\nimport type { ControlProps } from \"../types\";\nimport { Button } from \"../ui/button\";\nimport { Modal, ModalBody, ModalContent, ModalFooter, ModalHeader } from \"../ui/overlay\";\nimport { Select } from \"../ui/select\";\n\nconst CODE_LANGUAGES: { value: string; label: string }[] = [\n { value: \"html\", label: \"HTML\" },\n { value: \"css\", label: \"CSS\" },\n { value: \"js\", label: \"JS\" },\n { value: \"ts\", label: \"TS\" },\n { value: \"json\", label: \"JSON\" },\n { value: \"liquid\", label: \"Liquid\" },\n { value: \"markdown\", label: \"Markdown\" },\n { value: \"shell\", label: \"Shell\" },\n];\nconst PLAIN = \"plain\";\n\n/** The picker: Plain text, then the field's allowed languages (or the built-in list), then the stored one if it is outside them. */\nfunction languageOptions(language: string | undefined, allowed: string[] | undefined) {\n const list = allowed ? allowed.map((v) => CODE_LANGUAGES.find((l) => l.value === v) ?? { value: v, label: v }) : CODE_LANGUAGES;\n return [{ value: PLAIN, label: \"Plain text\" }, ...list, ...(language && !list.some((l) => l.value === language) ? [{ value: language, label: language }] : [])];\n}\n\n/** Why a JSON text does not parse (\"\" when it does, or is empty). */\nexport function jsonProblem(text: string): string {\n if (!text.trim()) return \"\";\n try {\n JSON.parse(text);\n return \"\";\n } catch (e) {\n return (e as Error).message.replace(/^JSON\\.parse: /, \"\");\n }\n}\n\n/* ── The surface ──────────────────────────────────────────────────────── */\nexport interface CodeSurfaceProps {\n /** \"json\": the JSON header, Format and the parse footer. \"code\": the language list. */\n kind: \"json\" | \"code\";\n value: string;\n onChange: (v: string) => void;\n /** code: the language shown in the header (\"\" = none) and what picking one does; absent = no list */\n language?: string;\n onLanguage?: (language: string) => void;\n /** code: the only languages the field allows (its config.languages); absent = the built-in list */\n languages?: string[];\n readOnly?: boolean;\n id?: string;\n invalid?: boolean;\n minRows?: number;\n label?: string;\n describedBy?: string;\n}\n\nexport function CodeSurface({ kind, value, onChange, language, onLanguage, languages, readOnly, id, invalid, minRows = 8, label, describedBy }: CodeSurfaceProps) {\n const { toast } = useKitServices();\n const lines = Math.max(minRows, value.split(\"\\n\").length);\n const problem = kind === \"json\" ? jsonProblem(value) : value.length > CODE_MAX_LENGTH ? `Code can hold up to ${CODE_MAX_LENGTH.toLocaleString(\"en-US\")} characters; this has ${value.length.toLocaleString(\"en-US\")}.` : \"\";\n const footerId = id ? `${id}-problem` : undefined;\n const format = () => {\n try {\n onChange(JSON.stringify(JSON.parse(value), null, 2));\n toast?.success(\"JSON formatted\");\n } catch {\n toast?.(\"Fix the JSON before formatting\");\n }\n };\n const copy = () => {\n void navigator.clipboard?.writeText(value);\n toast?.success(\"Copied\");\n };\n return (\n <div className={cn(\"overflow-hidden rounded-kit-lg border bg-kit-subtle\", invalid || problem ? \"border-[var(--kit-field-invalid)]\" : \"border-kit-line\")}>\n <div className=\"flex h-8 items-center justify-between border-b border-kit-line px-2\">\n {kind === \"json\" ? (\n <span className=\"px-1 font-kit-mono text-kit-xs text-kit-fg-3\">JSON</span>\n ) : onLanguage ? (\n <Select\n aria-label=\"Code language\"\n size=\"sm\"\n variant=\"ghost\"\n disabled={readOnly}\n value={language || PLAIN}\n onValueChange={(l) => onLanguage(l === PLAIN ? \"\" : l)}\n options={languageOptions(language, languages)}\n />\n ) : (\n <span className=\"px-1 font-kit-mono text-kit-xs text-kit-fg-3\">Code</span>\n )}\n <div className=\"flex items-center gap-1\">\n {kind === \"json\" ? (\n <button type=\"button\" disabled={readOnly} className=\"rounded-kit-md px-1.5 py-0.5 text-kit-xs text-kit-fg-2 hover:bg-kit-hover hover:text-kit-fg\" onClick={format}>\n Format\n </button>\n ) : null}\n <button type=\"button\" className=\"rounded-kit-md px-1.5 py-0.5 text-kit-xs text-kit-fg-2 hover:bg-kit-hover hover:text-kit-fg\" onClick={copy}>\n Copy\n </button>\n </div>\n </div>\n <div className=\"flex max-h-[60vh] overflow-auto font-kit-mono text-kit-xs leading-5\">\n <div aria-hidden className=\"select-none border-r border-kit-line bg-kit-subtle px-2 py-2 text-right text-kit-fg-4\">\n {Array.from({ length: lines }).map((_, i) => (\n <div key={i}>{i + 1}</div>\n ))}\n </div>\n <textarea\n id={id}\n spellCheck={false}\n autoCapitalize=\"off\"\n autoCorrect=\"off\"\n value={value}\n readOnly={readOnly}\n aria-invalid={invalid || !!problem || undefined}\n aria-label={label}\n aria-describedby={[describedBy, problem ? footerId : undefined].filter(Boolean).join(\" \") || undefined}\n onChange={(e) => onChange(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Tab\" && !e.shiftKey && !readOnly) {\n e.preventDefault();\n const el = e.currentTarget;\n const s = el.selectionStart;\n onChange(value.slice(0, s) + \" \" + value.slice(el.selectionEnd));\n requestAnimationFrame(() => el.setSelectionRange(s + 2, s + 2));\n }\n }}\n style={{ height: lines * 20 + 16 }}\n className=\"min-w-0 flex-1 resize-none bg-kit-field-bg px-3 py-2 text-kit-fg outline-none\"\n />\n </div>\n {problem ? (\n <div id={footerId} className=\"border-t border-kit-danger-line bg-kit-danger-soft px-3 py-1.5 text-kit-xs text-kit-danger-fg\">\n {kind === \"json\" ? `Invalid JSON · ${problem}` : problem}\n </div>\n ) : null}\n </div>\n );\n}\n\n/* ── Panel: summary button + dialog over a draft ─────────────────────── */\nexport function CodeDialogField({\n kind, title, description, text, readOnly, id, invalid, language, languages, onDone,\n}: {\n kind: \"json\" | \"code\";\n title: string;\n description?: string;\n text: string;\n readOnly?: boolean;\n id: string;\n invalid?: boolean;\n language?: string;\n languages?: string[];\n /** commit the draft; returns the reason it can't be saved, or null when saved */\n onDone: (draft: string, language: string | undefined) => string | null;\n}) {\n const { toast } = useKitServices();\n const [open, setOpen] = React.useState(false);\n const [draft, setDraft] = React.useState(text);\n const [lang, setLang] = React.useState(language);\n const [refusal, setRefusal] = React.useState<string | null>(null);\n const first = text.split(\"\\n\").find((l) => l.trim()) ?? \"\";\n const Icon = kind === \"json\" ? IconBraces : IconCode;\n return (\n <>\n <button\n id={id}\n type=\"button\"\n aria-haspopup=\"dialog\"\n aria-invalid={invalid || undefined}\n onClick={() => {\n setDraft(text);\n setLang(language);\n setRefusal(null);\n setOpen(true);\n }}\n className={cn(\n \"group/code flex w-full items-center gap-2 rounded-kit-md border border-kit-line bg-kit-subtle px-2.5 py-2 text-left transition-colors hover:border-kit-line-strong\",\n invalid && \"border-[var(--kit-field-invalid)]\",\n )}\n >\n <Icon className=\"size-4 shrink-0 text-kit-fg-3\" stroke={1.5} aria-hidden />\n <span className={cn(\"min-w-0 flex-1 truncate font-kit-mono text-kit-xs\", first ? \"text-kit-fg-2\" : \"text-kit-fg-3\")}>{first || \"Empty\"}</span>\n <span className=\"tabular-nums shrink-0 text-kit-2xs text-kit-fg-3\">{text ? `${text.split(\"\\n\").length} lines` : \"\"}</span>\n <IconMaximize className=\"size-3.5 shrink-0 text-kit-fg-3 group-hover/code:text-kit-fg\" stroke={1.5} aria-hidden />\n </button>\n <Modal open={open} onOpenChange={setOpen}>\n <ModalContent size=\"lg\">\n <ModalHeader title={title} description={description ?? (kind === \"json\" ? \"Structured data for developers\" : \"Custom code\")} />\n <ModalBody>\n <CodeSurface kind={kind} value={draft} onChange={setDraft} language={lang ?? \"\"} onLanguage={kind === \"code\" ? setLang : undefined} languages={languages} readOnly={readOnly} minRows={14} label={title} />\n {refusal ? (\n <p role=\"alert\" className=\"mt-2 flex items-start gap-1.5 text-kit-xs text-kit-danger-fg\">\n <IconAlertTriangle className=\"mt-0.5 size-3.5 shrink-0\" stroke={1.5} aria-hidden />\n {refusal}\n </p>\n ) : null}\n </ModalBody>\n <ModalFooter>\n <span data-hint=\"shortcuts\" className=\"text-kit-xs text-kit-fg-3\">\n Esc to close\n </span>\n <span className=\"mr-auto\" aria-hidden />\n <Button variant=\"ghost\" onClick={() => setOpen(false)}>\n Cancel\n </Button>\n <Button\n variant=\"primary\"\n disabled={readOnly}\n onClick={() => {\n const why = onDone(draft, lang);\n if (why) {\n setRefusal(why);\n toast?.(kind === \"json\" ? \"Invalid JSON\" : \"Can't save this code\", { description: \"Fix it before saving.\" });\n return;\n }\n setOpen(false);\n }}\n >\n Done\n </Button>\n </ModalFooter>\n </ModalContent>\n </Modal>\n </>\n );\n}\n\n/* ── The control ──────────────────────────────────────────────────────── */\ntype CodeRead = { ok: true; code: string; language?: string; object: boolean } | { ok: false };\nfunction readCode(v: unknown): CodeRead {\n if (v == null) return { ok: true, code: \"\", object: false };\n if (typeof v === \"string\") return { ok: true, code: v, object: false };\n if (isObj(v) && typeof v.code === \"string\" && (v.language === undefined || typeof v.language === \"string\")) return { ok: true, code: v.code, language: v.language as string | undefined, object: true };\n return { ok: false };\n}\n\n/** The stored shape for edited code: a string stays a string until a language is picked; the object keeps its form. */\nfunction codeValue(prev: CodeRead & { ok: true }, code: string, language: string | undefined): string | { language?: string; code: string } {\n const lang = language ?? prev.language ?? \"\";\n if (!prev.object && !lang) return code;\n return lang ? { language: lang, code } : { code };\n}\nconst tooLong = (code: string) => (code.length > CODE_MAX_LENGTH ? `Code can hold up to ${CODE_MAX_LENGTH.toLocaleString(\"en-US\")} characters; this has ${code.length.toLocaleString(\"en-US\")}.` : null);\n\nexport function CodeControl({ field, value, onChange, readOnly, id, invalid }: ControlProps) {\n const { variant } = useKitEnv();\n const [refused, setRefused] = React.useState<string | null>(null);\n const read = readCode(value);\n if (!read.ok) return <UnreadableValue id={id} title={field.title} kind=\"code\" value={value} />;\n if (variant === \"document\")\n return (\n <div className=\"flex flex-col gap-1.5\">\n <CodeSurface\n kind=\"code\"\n id={id}\n invalid={invalid || !!refused}\n readOnly={readOnly}\n value={read.code}\n language={read.language ?? \"\"}\n languages={field.languages}\n onChange={(code) => {\n const why = tooLong(code);\n setRefused(why);\n if (!why) onChange(codeValue(read, code, undefined));\n }}\n onLanguage={(l) => onChange(codeValue(read, read.code, l))}\n />\n {refused ? (\n <p role=\"alert\" className=\"text-kit-xs text-kit-danger-fg\">\n {refused}\n </p>\n ) : null}\n </div>\n );\n return (\n <CodeDialogField\n kind=\"code\"\n id={id}\n title={field.title}\n description={field.description || undefined}\n text={read.code}\n language={read.language}\n languages={field.languages}\n readOnly={readOnly}\n invalid={invalid}\n onDone={(draft, lang) => {\n const why = tooLong(draft);\n if (why) return why;\n const next = codeValue(read, draft, lang);\n if (draft !== read.code || (lang ?? \"\") !== (read.language ?? \"\")) onChange(next);\n return null;\n }}\n />\n );\n}\n\n/** A stored value the control cannot read: named, shown, kept as it is (never replaced by a stray edit). */\nexport function UnreadableValue({ id, title, kind, value }: { id: string; title: string; kind: string; value: unknown }) {\n let raw: string;\n try {\n raw = typeof value === \"string\" ? value : JSON.stringify(value, null, 2);\n } catch {\n raw = String(value);\n }\n return (\n <output\n id={id}\n tabIndex={0}\n data-slot={`${kind}-unreadable`}\n className=\"flex min-w-0 items-start gap-2 rounded-kit-md border border-dashed border-kit-line-strong bg-kit-subtle px-2.5 py-2 text-kit-xs text-kit-fg-2 outline-none focus-visible:outline-2 focus-visible:outline-kit-focus-ring\"\n >\n <IconAlertTriangle className=\"mt-0.5 size-3.5 shrink-0 text-kit-warning-fg\" stroke={1.5} aria-hidden />\n <span className=\"min-w-0\">\n {title} holds a value this {kind} editor can't read, so it is kept as it is:{\" \"}\n <span className=\"block max-h-24 overflow-auto whitespace-pre-wrap break-all font-kit-mono text-kit-fg\">{raw}</span>\n </span>\n </output>\n );\n}\n"],"mappings":"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"}
|
|
@@ -5,7 +5,7 @@ import { Input } from "../ui/input.js";
|
|
|
5
5
|
import { TEXT_FOCUS, str } from "./text.js";
|
|
6
6
|
import * as React from "react";
|
|
7
7
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
-
//#region src/
|
|
8
|
+
//#region src/controls/color.tsx
|
|
9
9
|
/**
|
|
10
10
|
* COLOR — site-palette swatches first, then a custom colour (V2 HEAD 9829bf1 kit/controls/misc.tsx, DESIGN §8.13).
|
|
11
11
|
*
|
|
@@ -43,7 +43,7 @@ function ColorControl({ field, value, onChange, readOnly, id, invalid, onBlur })
|
|
|
43
43
|
"aria-label": `Choose a colour for ${field.title}`,
|
|
44
44
|
render: /* @__PURE__ */ jsx("button", {
|
|
45
45
|
type: "button",
|
|
46
|
-
className: "flex h-8 min-w-0 flex-1 items-center gap-2 rounded-kit-md border border-kit-
|
|
46
|
+
className: "flex h-8 min-w-0 flex-1 items-center gap-2 rounded-kit-md border border-kit-line-strong bg-kit-field-bg pl-1 pr-2.5 text-left text-kit-sm hover:border-kit-line-strong data-[popup-open]:border-kit-line-strong data-[popup-open]:bg-kit-field-bg"
|
|
47
47
|
}),
|
|
48
48
|
children: [
|
|
49
49
|
/* @__PURE__ */ jsx("span", {
|
|
@@ -52,7 +52,7 @@ function ColorControl({ field, value, onChange, readOnly, id, invalid, onBlur })
|
|
|
52
52
|
}),
|
|
53
53
|
/* @__PURE__ */ jsx("span", {
|
|
54
54
|
className: cn("min-w-0 flex-1 truncate", v ? "text-kit-fg" : "text-kit-fg-3"),
|
|
55
|
-
children: sw ? sw.name : v ? "Custom" : "No
|
|
55
|
+
children: sw ? sw.name : v ? "Custom" : "No colour"
|
|
56
56
|
}),
|
|
57
57
|
sw?.token ? /* @__PURE__ */ jsx("span", {
|
|
58
58
|
className: "truncate font-kit-mono text-kit-2xs text-kit-fg-3",
|
|
@@ -74,13 +74,13 @@ function ColorControl({ field, value, onChange, readOnly, id, invalid, onBlur })
|
|
|
74
74
|
"aria-label": s.name,
|
|
75
75
|
"aria-pressed": s.value.toLowerCase() === v.toLowerCase(),
|
|
76
76
|
onClick: () => write(s.value),
|
|
77
|
-
className: cn("relative size-9 rounded-kit-md border border-kit-swatch-ring transition-transform hover:scale-
|
|
77
|
+
className: cn("relative size-9 rounded-kit-md border border-kit-swatch-ring transition-transform duration-150 ease-out motion-reduce:transition-none can-hover:hover:scale-[1.02]", s.value.toLowerCase() === v.toLowerCase() && "ring-2 ring-kit-fg ring-offset-2 ring-offset-kit-surface"),
|
|
78
78
|
style: { background: s.value }
|
|
79
79
|
})
|
|
80
80
|
}, s.value))
|
|
81
81
|
})] }) : null,
|
|
82
82
|
/* @__PURE__ */ jsxs("label", {
|
|
83
|
-
className: cn("flex items-center gap-2 text-kit-xs text-kit-fg-3", palette.length && "mt-
|
|
83
|
+
className: cn("mt-3 flex items-center gap-2 border-t border-kit-line pt-3 text-kit-xs text-kit-fg-3", !palette.length && "mt-0 border-t-0 pt-0"),
|
|
84
84
|
children: ["Custom", /* @__PURE__ */ jsx("input", {
|
|
85
85
|
type: "color",
|
|
86
86
|
value: pickerHex(v),
|
|
@@ -92,7 +92,7 @@ function ColorControl({ field, value, onChange, readOnly, id, invalid, onBlur })
|
|
|
92
92
|
type: "button",
|
|
93
93
|
onClick: () => write(null),
|
|
94
94
|
className: "mt-2 w-full rounded-kit-md px-1.5 py-1 text-left text-kit-xs text-kit-fg-2 hover:bg-kit-hover hover:text-kit-fg",
|
|
95
|
-
children: "No
|
|
95
|
+
children: "No colour"
|
|
96
96
|
}) : null
|
|
97
97
|
]
|
|
98
98
|
})] }), /* @__PURE__ */ jsx(Input, {
|
|
@@ -110,7 +110,7 @@ function ColorControl({ field, value, onChange, readOnly, id, invalid, onBlur })
|
|
|
110
110
|
else setDraft(e.target.value);
|
|
111
111
|
},
|
|
112
112
|
onBlur,
|
|
113
|
-
className: cn(TEXT_FOCUS, "w-28 shrink-0 font-kit-mono")
|
|
113
|
+
className: cn(TEXT_FOCUS, "w-28 shrink-0 font-kit-mono [&_input]:font-kit-mono")
|
|
114
114
|
})]
|
|
115
115
|
}), bad ? /* @__PURE__ */ jsxs("p", {
|
|
116
116
|
id: errId,
|
|
@@ -125,6 +125,6 @@ function ColorControl({ field, value, onChange, readOnly, id, invalid, onBlur })
|
|
|
125
125
|
});
|
|
126
126
|
}
|
|
127
127
|
//#endregion
|
|
128
|
-
export { ColorControl };
|
|
128
|
+
export { ColorControl, HEX_COLOR, pickerHex };
|
|
129
129
|
|
|
130
130
|
//# sourceMappingURL=color.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"color.js","names":[],"sources":["../../src/controls/color.tsx"],"sourcesContent":["/**\n * COLOR — site-palette swatches first, then a custom colour (V2 HEAD 9829bf1 kit/controls/misc.tsx, DESIGN §8.13).\n *\n * Stored shape (prod `color`): a hex string the backend accepts — #RGB, #RRGGBB or #RRGGBBAA — or null when cleared.\n * The hex box keeps what you type as a draft and writes it only once it is a hex colour; while it is not, the box is\n * marked invalid and says why, so a half-typed \"#12\" never reaches the save (the API would refuse it).\n * The palette is the host's (`env.palette`, the project's brand colours); with none, the popover offers the custom\n * picker alone.\n */\nimport * as React from \"react\";\nimport { cn } from \"../lib/cn\";\nimport { useKitEnv } from \"../context\";\nimport { Input } from \"../ui/input\";\nimport { Popover, PopoverContent, PopoverTrigger, Tooltip } from \"../ui/overlay\";\nimport type { ControlProps } from \"../types\";\nimport { str, TEXT_FOCUS } from \"./text\";\n\nexport const HEX_COLOR = /^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/;\n/** #RGB / #RRGGBBAA → #RRGGBB for the native picker, which takes only six digits. */\nexport function pickerHex(v: string): string {\n if (!HEX_COLOR.test(v)) return \"#000000\";\n const h = v.slice(1);\n const six = h.length === 3 ? h.split(\"\").map((c) => c + c).join(\"\") : h.slice(0, 6);\n return `#${six.toLowerCase()}`;\n}\n\nexport function ColorControl({ field, value, onChange, readOnly, id, invalid, onBlur }: ControlProps) {\n const { palette } = useKitEnv();\n const v = str(value);\n const [draft, setDraft] = React.useState<string | null>(null);\n const shown = draft ?? v;\n const bad = draft !== null && draft.trim() !== \"\" && !HEX_COLOR.test(draft.trim());\n const sw = palette.find((p) => p.value.toLowerCase() === v.toLowerCase());\n const errId = React.useId();\n const write = (next: string | null) => {\n setDraft(null);\n onChange(next);\n };\n return (\n <div className=\"flex flex-col gap-1\">\n <div className=\"flex items-center gap-2\">\n <Popover>\n <PopoverTrigger\n disabled={readOnly}\n aria-label={`Choose a colour for ${field.title}`}\n render={\n <button\n type=\"button\"\n className=\"flex h-8 min-w-0 flex-1 items-center gap-2 rounded-kit-md border border-kit-line-strong bg-kit-field-bg pl-1 pr-2.5 text-left text-kit-sm hover:border-kit-line-strong data-[popup-open]:border-kit-line-strong data-[popup-open]:bg-kit-field-bg\"\n />\n }\n >\n <span className=\"size-6 shrink-0 rounded-kit-md border border-kit-swatch-ring shadow-kit-xs\" style={{ background: v || \"transparent\" }} />\n <span className={cn(\"min-w-0 flex-1 truncate\", v ? \"text-kit-fg\" : \"text-kit-fg-3\")}>{sw ? sw.name : v ? \"Custom\" : \"No colour\"}</span>\n {sw?.token ? <span className=\"truncate font-kit-mono text-kit-2xs text-kit-fg-3\">{sw.token}</span> : null}\n </PopoverTrigger>\n <PopoverContent className=\"w-64\">\n {palette.length ? (\n <>\n <div className=\"mb-2 text-kit-xs text-kit-fg-3\">Site palette</div>\n <div className=\"grid grid-cols-5 gap-2\">\n {palette.map((s) => (\n <Tooltip key={s.value} content={`${s.name}${s.token ? ` · ${s.token}` : \"\"}`}>\n <button\n type=\"button\"\n aria-label={s.name}\n aria-pressed={s.value.toLowerCase() === v.toLowerCase()}\n onClick={() => write(s.value)}\n className={cn(\n // 1–2% hover scale, only for a hovering pointer (canvas revamp V463)\n \"relative size-9 rounded-kit-md border border-kit-swatch-ring transition-transform duration-150 ease-out motion-reduce:transition-none can-hover:hover:scale-[1.02]\",\n s.value.toLowerCase() === v.toLowerCase() && \"ring-2 ring-kit-fg ring-offset-2 ring-offset-kit-surface\",\n )}\n style={{ background: s.value }}\n />\n </Tooltip>\n ))}\n </div>\n </>\n ) : null}\n <label className={cn(\"mt-3 flex items-center gap-2 border-t border-kit-line pt-3 text-kit-xs text-kit-fg-3\", !palette.length && \"mt-0 border-t-0 pt-0\")}>\n Custom\n <input\n type=\"color\"\n value={pickerHex(v)}\n onChange={(e) => write(e.target.value.toUpperCase())}\n className=\"h-7 w-full cursor-pointer rounded-kit-md border border-kit-line bg-transparent\"\n />\n </label>\n {v ? (\n <button type=\"button\" onClick={() => write(null)} className=\"mt-2 w-full rounded-kit-md px-1.5 py-1 text-left text-kit-xs text-kit-fg-2 hover:bg-kit-hover hover:text-kit-fg\">\n No colour\n </button>\n ) : null}\n </PopoverContent>\n </Popover>\n <Input\n id={id}\n value={shown}\n readOnly={readOnly}\n aria-invalid={invalid || bad}\n aria-describedby={bad ? errId : undefined}\n placeholder=\"#RRGGBB\"\n spellCheck={false}\n onChange={(e) => {\n const t = e.target.value.trim();\n if (t === \"\") write(null);\n else if (HEX_COLOR.test(t)) write(t);\n else setDraft(e.target.value);\n }}\n onBlur={onBlur}\n className={cn(TEXT_FOCUS, \"w-28 shrink-0 font-kit-mono [&_input]:font-kit-mono\")}\n />\n </div>\n {bad ? (\n <p id={errId} role=\"alert\" className=\"text-kit-xs text-kit-danger-fg\">\n “{draft!.trim()}” isn't a hex color, so it isn't saved. Use #RGB or #RRGGBB.\n </p>\n ) : null}\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -13,6 +13,13 @@ export interface KitComponentField {
|
|
|
13
13
|
label: string;
|
|
14
14
|
/** the component's own value for it (its default), before this place's overrides */
|
|
15
15
|
value?: unknown;
|
|
16
|
+
/** a choice field's options: the card lists the chosen option's LABEL, never its stored value (an id) */
|
|
17
|
+
options?: {
|
|
18
|
+
value: string;
|
|
19
|
+
label: string;
|
|
20
|
+
}[];
|
|
21
|
+
/** the component expects every place to fill it (an editor hint): an empty one marks the card's scope chip */
|
|
22
|
+
required?: boolean;
|
|
16
23
|
}
|
|
17
24
|
export interface KitComponentInfo {
|
|
18
25
|
/** the component's current name */
|
|
@@ -23,6 +30,8 @@ export interface KitComponentInfo {
|
|
|
23
30
|
places?: number;
|
|
24
31
|
/** its content fields in order; an override counts as "Edited here" only when its key is one of these */
|
|
25
32
|
fields?: KitComponentField[];
|
|
33
|
+
/** its block icon (V2 instance card BlockIcon), a name the host's IconGlyph draws; absent → the components glyph */
|
|
34
|
+
icon?: string;
|
|
26
35
|
/** a picture of the component as readers see it (the host's snapshot of it) */
|
|
27
36
|
image?: string | null;
|
|
28
37
|
/**
|
|
@@ -78,6 +87,12 @@ declare module "../context" {
|
|
|
78
87
|
overrides: Record<string, unknown>;
|
|
79
88
|
variant?: string;
|
|
80
89
|
}) => Promise<KitComponentCopy>;
|
|
90
|
+
/**
|
|
91
|
+
* The component that IS `variant` of `ref`'s section family (a variant is its own component): an embedded instance
|
|
92
|
+
* with a per-instance layout reads as that member, so the card draws the variant itself (V2 instance card draws
|
|
93
|
+
* `r.variant`). Undefined → `ref` has no family member for it, and the card names the layout instead.
|
|
94
|
+
*/
|
|
95
|
+
componentVariantMember?: (ref: string, variant: string) => string | undefined;
|
|
81
96
|
/**
|
|
82
97
|
* A React HOOK (one identity for the life of the form): the components the rich-text field at `at` may embed,
|
|
83
98
|
* already narrowed to the ones its config accepts. `error` is a whole sentence. Absent → the "/" menu offers no
|
|
@@ -99,8 +114,35 @@ declare module "../context" {
|
|
|
99
114
|
* Absent → the card shows the host's snapshot where the place shows exactly the component, else its values.
|
|
100
115
|
*/
|
|
101
116
|
ComponentPreview?: import("react").ComponentType<KitComponentPreviewProps>;
|
|
117
|
+
/**
|
|
118
|
+
* The per-placement settings form an embedded instance's panel shows (V2 instance panel): inherited values muted,
|
|
119
|
+
* fields edited here with a Reset, the Layout variant. Absent → the card offers no "Edit properties".
|
|
120
|
+
*/
|
|
121
|
+
ComponentSettings?: import("react").ComponentType<KitComponentSettingsProps>;
|
|
122
|
+
/** "Edit for all N places": open the shared component itself. Absent → the item is not offered. */
|
|
123
|
+
openComponent?: (ref: string) => void;
|
|
124
|
+
/** "Copy link" to this place. Undefined → the item is not offered. */
|
|
125
|
+
componentHref?: (ref: string, instanceId?: string) => string | undefined;
|
|
102
126
|
}
|
|
103
127
|
}
|
|
128
|
+
/** What the host's settings form edits for ONE place of a shared component. */
|
|
129
|
+
export interface KitComponentSettingsProps {
|
|
130
|
+
componentId: string;
|
|
131
|
+
/** Only the fields this place changed (everything else follows the component). */
|
|
132
|
+
overrides: Record<string, unknown>;
|
|
133
|
+
variant?: string;
|
|
134
|
+
/** A separate copy: its own full props, no longer following the component. */
|
|
135
|
+
detached?: {
|
|
136
|
+
props: Record<string, unknown>;
|
|
137
|
+
};
|
|
138
|
+
readOnly?: boolean;
|
|
139
|
+
/** Focus this field when the panel opens (a click on it in the preview). */
|
|
140
|
+
focusKey?: string | null;
|
|
141
|
+
onOverrides: (next: Record<string, unknown>) => void;
|
|
142
|
+
onVariant?: (variant: string | undefined) => void;
|
|
143
|
+
}
|
|
144
|
+
/** V2's insert toast: an embedded component is shared, edits here change only this place. */
|
|
145
|
+
export declare const COMPONENT_INSERT_TOAST = "Shared: it follows the block. Fields you edit here change only this place.";
|
|
104
146
|
/**
|
|
105
147
|
* One step of the host's history (KitServices.historyStep). The host's toolbar can undo and redo it too, so `next`
|
|
106
148
|
* says where it stands NOW: the host's next undo, its next redo, or neither (other changes come first, or it is gone).
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
//#region src/controls/component-services.ts
|
|
2
|
+
/** V2's insert toast: an embedded component is shared, edits here change only this place. */
|
|
3
|
+
var COMPONENT_INSERT_TOAST = "Shared: it follows the block. Fields you edit here change only this place.";
|
|
4
|
+
//#endregion
|
|
5
|
+
export { COMPONENT_INSERT_TOAST };
|
|
6
|
+
|
|
7
|
+
//# sourceMappingURL=component-services.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"component-services.js","names":[],"sources":["../../src/controls/component-services.ts"],"sourcesContent":["/**\n * The component lookup a rich-text body's embedded component card reads (V2 instance-card.tsx), declared as an\n * augmentation of KitServices. The host answers from its own components library:\n *\n * the dock → the project's components (GET /components) and its usage map (GET /projects/:id/component-usage)\n * the sandbox → V2's demo component library (/style-guide/kit fixtures)\n *\n * Absent → the card stays the compact \"Linked component\" row: no state, no count, no preview is ever made up.\n */\nimport type { RichTextAt } from \"./rich-text/codec\";\n\nexport interface KitComponentField {\n key: string;\n label: string;\n /** the component's own value for it (its default), before this place's overrides */\n value?: unknown;\n /** a choice field's options: the card lists the chosen option's LABEL, never its stored value (an id) */\n options?: { value: string; label: string }[];\n /** the component expects every place to fill it (an editor hint): an empty one marks the card's scope chip */\n required?: boolean;\n}\n\nexport interface KitComponentInfo {\n /** the component's current name */\n name: string;\n /** true: the library has no component with this id (it was deleted) */\n missing?: boolean;\n /** how many places link to it; absent → not measured, and the card says \"Shared\" without a number */\n places?: number;\n /** its content fields in order; an override counts as \"Edited here\" only when its key is one of these */\n fields?: KitComponentField[];\n /** its block icon (V2 instance card BlockIcon), a name the host's IconGlyph draws; absent → the components glyph */\n icon?: string;\n /** a picture of the component as readers see it (the host's snapshot of it) */\n image?: string | null;\n /**\n * the version readers see now (the component's last publish); a separate copy taken from an older one shows\n * \"Shared version changed\". Absent → not known, and no copy is ever called out of date.\n */\n publishedAt?: string | null;\n}\n\n/** A separate copy of a component (V2 instances.ts `detach`): what this place keeps when it stops following it. */\nexport interface KitComponentCopy {\n /** the values readers see, now this place's own (V2 `props`) */\n props: Record<string, unknown>;\n /** whatever the host stores beside them to draw the copy (production: the frozen block tree, as JSON) */\n blocks?: string;\n /** the version of the component it was taken from */\n sourcePublishedAt?: string;\n}\n\n/**\n * The component drawn live in its card (V2 instance card), with THIS place's values: a linked place's defaults with its\n * overrides, a separate copy's own values. Read-only, the card's width. `fallback(reason)` is what the card shows when\n * the host cannot draw it (not validated, no runtime here, an error), with the reason in words.\n */\nexport interface KitComponentPreviewProps {\n componentId: string;\n title: string;\n props: Record<string, unknown>;\n fallback: (reason: string) => import(\"react\").ReactNode;\n}\n\n/** A component a rich-text body can embed (the \"/\" menu's More components). */\nexport interface KitInsertableComponent {\n id: string;\n name: string;\n description?: string;\n}\n\ndeclare module \"../context\" {\n interface KitServices {\n /**\n * A React HOOK (called on every render of a component card, so the host passes one function for the life of the\n * form): what the library knows about the component an embedded instance links to. `info` undefined while it\n * loads; `error` is a whole sentence (\"Components couldn't be loaded: …\").\n */\n useComponentInfo?: (ref: string) => { info?: KitComponentInfo; loading?: boolean; error?: string };\n /**\n * Make this place a separate copy (V2 \"Keep as a separate copy\" / \"Make a separate copy\"): what readers see now,\n * with this place's overrides. Rejects with a whole sentence the card shows (\"“Card” has never been published…\").\n * Absent → the card offers no separate copy.\n */\n copyComponent?: (ref: string, input: { overrides: Record<string, unknown>; variant?: string }) => Promise<KitComponentCopy>;\n /**\n * The component that IS `variant` of `ref`'s section family (a variant is its own component): an embedded instance\n * with a per-instance layout reads as that member, so the card draws the variant itself (V2 instance card draws\n * `r.variant`). Undefined → `ref` has no family member for it, and the card names the layout instead.\n */\n componentVariantMember?: (ref: string, variant: string) => string | undefined;\n /**\n * A React HOOK (one identity for the life of the form): the components the rich-text field at `at` may embed,\n * already narrowed to the ones its config accepts. `error` is a whole sentence. Absent → the \"/\" menu offers no\n * components.\n */\n useInsertableComponents?: (at: RichTextAt) => { components: KitInsertableComponent[]; loading?: boolean; error?: string };\n /**\n * The host's own undo history (the dock: the Visual Editor's toolbar Undo). Runs `write` (synchronously) as ONE\n * step of it and answers that step (KitHistoryStep). Null: the host recorded no step (it keeps no history here),\n * so the editor's own history takes the step.\n */\n historyStep?: (write: () => void) => KitHistoryStep | null;\n /**\n * Draws an embedded component live in its card (KitComponentPreviewProps). Mounted only once the card is on screen.\n * Absent → the card shows the host's snapshot where the place shows exactly the component, else its values.\n */\n ComponentPreview?: import(\"react\").ComponentType<KitComponentPreviewProps>;\n /**\n * The per-placement settings form an embedded instance's panel shows (V2 instance panel): inherited values muted,\n * fields edited here with a Reset, the Layout variant. Absent → the card offers no \"Edit properties\".\n */\n ComponentSettings?: import(\"react\").ComponentType<KitComponentSettingsProps>;\n /** \"Edit for all N places\": open the shared component itself. Absent → the item is not offered. */\n openComponent?: (ref: string) => void;\n /** \"Copy link\" to this place. Undefined → the item is not offered. */\n componentHref?: (ref: string, instanceId?: string) => string | undefined;\n }\n}\n\n/** What the host's settings form edits for ONE place of a shared component. */\nexport interface KitComponentSettingsProps {\n componentId: string;\n /** Only the fields this place changed (everything else follows the component). */\n overrides: Record<string, unknown>;\n variant?: string;\n /** A separate copy: its own full props, no longer following the component. */\n detached?: { props: Record<string, unknown> };\n readOnly?: boolean;\n /** Focus this field when the panel opens (a click on it in the preview). */\n focusKey?: string | null;\n onOverrides: (next: Record<string, unknown>) => void;\n onVariant?: (variant: string | undefined) => void;\n}\n\n/** V2's insert toast: an embedded component is shared, edits here change only this place. */\nexport const COMPONENT_INSERT_TOAST = \"Shared: it follows the block. Fields you edit here change only this place.\";\n\n/**\n * One step of the host's history (KitServices.historyStep). The host's toolbar can undo and redo it too, so `next`\n * says where it stands NOW: the host's next undo, its next redo, or neither (other changes come first, or it is gone).\n * `undo` / `redo` answer true or the sentence saying why nothing changed.\n */\nexport interface KitHistoryStep {\n undo: () => true | string;\n redo: () => true | string;\n next: () => \"undo\" | \"redo\" | null;\n}\n\nexport {};\n"],"mappings":";;AAwIA,IAAa,yBAAyB"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CONTROLS } from "../engine/kit-field.js";
|
|
2
2
|
import { DateControl } from "./date.js";
|
|
3
|
-
//#region src/
|
|
3
|
+
//#region src/controls/date-register.ts
|
|
4
4
|
/** Lane C3: date and datetime in the engine's dispatch table (one line per type; merge with other lanes by line). */
|
|
5
5
|
CONTROLS.date = DateControl;
|
|
6
6
|
CONTROLS.datetime = DateControl;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"date-register.js","names":[],"sources":["../../src/controls/date-register.ts"],"sourcesContent":["/** Lane C3: date and datetime in the engine's dispatch table (one line per type; merge with other lanes by line). */\nimport { CONTROLS } from \"../engine/kit-field\";\nimport { DateControl } from \"./date\";\n\nCONTROLS.date = DateControl;\nCONTROLS.datetime = DateControl;\n"],"mappings":";;;;AAIA,SAAS,OAAO;AAChB,SAAS,WAAW"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useKitServices } from "../context.js";
|
|
2
2
|
import * as React from "react";
|
|
3
|
-
//#region src/
|
|
3
|
+
//#region src/controls/date-zone.ts
|
|
4
4
|
/**
|
|
5
5
|
* DATE / DATETIME values and time zones (DESIGN 6.4, D43), ported from V2 controls/date.tsx and fitted to what the
|
|
6
6
|
* backend and the value adapters keep (adapters/values.ts datetimeToProd / datetimeFromProd, backend
|
|
@@ -186,6 +186,12 @@ function parseStored(v) {
|
|
|
186
186
|
readable: true
|
|
187
187
|
};
|
|
188
188
|
}
|
|
189
|
+
/** A stored value as a JS Date (drops the [Zone] annotation, which `new Date()` can't read). */
|
|
190
|
+
function storedToDate(v) {
|
|
191
|
+
if (typeof v !== "string" || !v) return null;
|
|
192
|
+
const d = new Date(v.replace(/\[[^\]]*\]$/, ""));
|
|
193
|
+
return Number.isNaN(d.getTime()) ? null : d;
|
|
194
|
+
}
|
|
189
195
|
/** Every IANA zone this runtime knows, UTC included. */
|
|
190
196
|
var ALL_ZONES = (() => {
|
|
191
197
|
const list = typeof Intl.supportedValuesOf === "function" ? Intl.supportedValuesOf("timeZone").map(modernZone) : [];
|
|
@@ -267,6 +273,6 @@ function todayIn(zone, now = /* @__PURE__ */ new Date()) {
|
|
|
267
273
|
return `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}`;
|
|
268
274
|
}
|
|
269
275
|
//#endregion
|
|
270
|
-
export { ALL_ZONES, browserZone, parseStored, resolveShown, todayIn, useDefaultZone, validZone, wallInstant, writeValue, zoneCity, zoneLabel, zonePolicy, zoneShortOffset };
|
|
276
|
+
export { ALL_ZONES, browserZone, instantToWall, modernZone, offsetIso, offsetMinutes, parseStored, resolveShown, storedToDate, todayIn, useDefaultZone, validZone, wallInstant, wallOffset, writeValue, zoneCity, zoneLabel, zonePolicy, zoneShortOffset, zoneWithOffset };
|
|
271
277
|
|
|
272
278
|
//# sourceMappingURL=date-zone.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"date-zone.js","names":[],"sources":["../../src/controls/date-zone.ts"],"sourcesContent":["/**\n * DATE / DATETIME values and time zones (DESIGN 6.4, D43), ported from V2 controls/date.tsx and fitted to what the\n * backend and the value adapters keep (adapters/values.ts datetimeToProd / datetimeFromProd, backend\n * parseDateField / parseDatetimeField).\n *\n * What the control writes, per field (`zonePolicy`):\n *\n * date (any timezone) \"2026-10-14\" a prod `date` without includeTime refuses a \"T\"\n * datetime, timezone false \"2026-10-14T09:00:00\" floating wall time\n * datetime, true / unset \"2026-10-14T09:00:00+05:30\" the zone the editor picked lives in the offset:\n * datetime, \"site\" \"2026-10-14T09:00:00-07:00\" prod keeps no [Zone] (the adapter names a kept\n * one as lost and the dock refuses the write)\n * datetime, \"fixed:<IANA>\" \"2026-10-14T09:00:00-04:00[America/New_York]\" the adapter checks the zone against\n * config.timezone, stores the instant, and\n * reads it back with the same [Zone]\n *\n * Seconds are always written (prod refuses a seconds-less datetime; the adapter names it \"format\"). The offset is the\n * zone's offset AT the wall time the author typed (two passes, so it is right on both sides of a clock change), and a\n * wall time that a clock change skips is refused with a named reason, never shifted silently.\n */\nimport * as React from \"react\";\nimport { useKitServices } from \"../context\";\nimport type { FieldSchema } from \"../schema/types\";\n\n/* ── The site zone (a host service) ───────────────────────────────────── */\ndeclare module \"../context\" {\n interface KitServices {\n /**\n * The site's IANA zone (Project.localeConfig.timeZone, Settings › General): where a new date/time value starts and\n * what timezone \"site\" locks to. The dock passes `useSiteTimeZone().zone` when its source is \"site\". Absent or not\n * a zone → the viewer's browser zone, which the picker names \"Your time zone\".\n */\n siteTimeZone?: string;\n }\n}\n\nexport type ZoneSource = \"site\" | \"browser\";\n\nexport function validZone(z: unknown): z is string {\n if (typeof z !== \"string\" || !z) return false;\n try {\n new Intl.DateTimeFormat(\"en-US\", { timeZone: z });\n return true;\n } catch {\n return false;\n }\n}\n\n/** ICU still lists some zones under their old names; people read the current ones (Kolkata, not Calcutta). */\nconst MODERN: Readonly<Record<string, string>> = {\n \"Asia/Calcutta\": \"Asia/Kolkata\",\n \"Asia/Katmandu\": \"Asia/Kathmandu\",\n \"Asia/Saigon\": \"Asia/Ho_Chi_Minh\",\n \"Asia/Rangoon\": \"Asia/Yangon\",\n \"Europe/Kiev\": \"Europe/Kyiv\",\n \"America/Godthab\": \"America/Nuuk\",\n \"Atlantic/Faeroe\": \"Atlantic/Faroe\",\n \"America/Buenos_Aires\": \"America/Argentina/Buenos_Aires\",\n};\nexport const modernZone = (z: string) => (MODERN[z] && validZone(MODERN[z]) ? MODERN[z] : z);\n\nexport function browserZone(): string {\n try {\n return modernZone(Intl.DateTimeFormat().resolvedOptions().timeZone || \"UTC\");\n } catch {\n return \"UTC\";\n }\n}\n\n/** The zone a new value starts in: the site's, else the browser's. `source` names which one. */\nexport function useDefaultZone(): { zone: string; source: ZoneSource } {\n const site = useKitServices().siteTimeZone;\n return React.useMemo(() => (validZone(site) ? { zone: site, source: \"site\" as const } : { zone: browserZone(), source: \"browser\" as const }), [site]);\n}\n\n/* ── Policy ───────────────────────────────────────────────────────────── */\nexport type ZoneMode = \"pick\" | \"site\" | \"fixed\" | \"none\";\n/**\n * What the schema allows. A `date` never carries a zone here: prod stores a date as \"YYYY-MM-DD\" and refuses a time on\n * a date field without includeTime, so a zoned date (V2 allowed one) would be refused at save.\n */\nexport function zonePolicy(field: Pick<FieldSchema, \"type\" | \"timezone\">): { mode: ZoneMode; zone?: string } {\n if (field.type !== \"datetime\") return { mode: \"none\" };\n const t = field.timezone ?? true;\n if (t === false) return { mode: \"none\" };\n if (t === \"site\") return { mode: \"site\" };\n if (typeof t === \"string\" && t.startsWith(\"fixed:\")) {\n const z = t.slice(6);\n return validZone(z) ? { mode: \"fixed\", zone: z } : { mode: \"site\" };\n }\n return { mode: \"pick\" };\n}\n\n/* ── Offsets ──────────────────────────────────────────────────────────── */\nconst pad = (n: number) => String(Math.abs(Math.trunc(n))).padStart(2, \"0\");\n\n/** The zone's UTC offset in minutes at an instant (+330 for Kolkata). */\nexport function offsetMinutes(zone: string, at: Date): number {\n try {\n const name = new Intl.DateTimeFormat(\"en-US\", { timeZone: zone, timeZoneName: \"longOffset\" }).formatToParts(at).find((p) => p.type === \"timeZoneName\")?.value ?? \"GMT\";\n const m = /GMT([+\\-−])(\\d{1,2})(?::?(\\d{2}))?/.exec(name);\n if (!m) return 0;\n const sign = m[1] === \"+\" ? 1 : -1;\n return sign * (Number(m[2]) * 60 + Number(m[3] ?? 0));\n } catch {\n return 0;\n }\n}\n\n/** +330 → \"+05:30\"; 0 → \"+00:00\". */\nexport const offsetIso = (min: number) => `${min < 0 ? \"-\" : \"+\"}${pad(Math.floor(Math.abs(min) / 60))}:${pad(Math.abs(min) % 60)}`;\n\n/** \"GMT+5:30\", \"GMT−7\", \"GMT\" — the short form people read (with a true minus sign). */\nexport function zoneShortOffset(zone: string, at = new Date()): string {\n const min = offsetMinutes(zone, at);\n if (min === 0) return \"GMT\";\n const h = Math.floor(Math.abs(min) / 60);\n const m = Math.abs(min) % 60;\n return `GMT${min < 0 ? \"−\" : \"+\"}${h}${m ? `:${pad(m)}` : \"\"}`;\n}\n\nexport const zoneCity = (z: string) => (z === \"UTC\" || z === \"Etc/UTC\" ? \"UTC\" : (z.split(\"/\").pop() ?? z).replace(/_/g, \" \"));\n/** \"GMT+5:30 · Kolkata\" */\nexport const zoneLabel = (zone: string, at?: Date) => `${zoneShortOffset(zone, at)} · ${zoneCity(zone)}`;\n\n/* ── Wall time ↔ instant ──────────────────────────────────────────────── */\nexport interface Wall {\n /** \"YYYY-MM-DD\" */\n ymd: string;\n /** \"HH:mm\" */\n time: string;\n}\nconst ymdParts = (ymd: string) => ymd.split(\"-\").map(Number) as [number, number, number];\nconst hmParts = (time: string) => time.split(\":\").map(Number) as [number, number];\nconst wallUtc = ({ ymd, time }: Wall) => {\n const [y, mo, d] = ymdParts(ymd);\n const [h, mi] = hmParts(time);\n return Date.UTC(y, mo - 1, d, h, mi);\n};\n\n/** The wall clock an instant shows in a zone. */\nexport function instantToWall(instant: Date, zone: string): Wall {\n const parts = new Intl.DateTimeFormat(\"en-CA\", { timeZone: zone, year: \"numeric\", month: \"2-digit\", day: \"2-digit\", hour: \"2-digit\", minute: \"2-digit\", hourCycle: \"h23\" }).formatToParts(instant);\n const get = (t: string) => parts.find((p) => p.type === t)?.value ?? \"00\";\n return { ymd: `${get(\"year\")}-${get(\"month\")}-${get(\"day\")}`, time: `${get(\"hour\")}:${get(\"minute\")}` };\n}\n\n/**\n * The offset of a wall time in a zone, or null when a clock change skips that wall time (it names no instant there).\n * Two passes: the offset at the naive instant, then at the instant that offset gives.\n */\nexport function wallOffset(zone: string, wall: Wall): number | null {\n const naive = wallUtc(wall);\n const first = offsetMinutes(zone, new Date(naive));\n const second = offsetMinutes(zone, new Date(naive - first * 60_000));\n for (const off of second === first ? [first] : [second, first]) {\n const back = instantToWall(new Date(naive - off * 60_000), zone);\n if (back.ymd === wall.ymd && back.time === wall.time) return off;\n }\n return null;\n}\n\n/** The instant a wall time names in a zone (the earlier one when a clock change skips it). */\nexport const wallInstant = (zone: string, wall: Wall) => new Date(wallUtc(wall) - (wallOffset(zone, wall) ?? offsetMinutes(zone, new Date(wallUtc(wall)))) * 60_000);\n\n/* ── Stored value → parts ─────────────────────────────────────────────── */\nexport interface ParsedValue {\n /** the day as stored (wall clock), or null when empty */\n wall: Wall | null;\n hasTime: boolean;\n /** the stated offset in minutes (\"Z\" → 0); undefined for a floating time */\n offset?: number;\n /** an RFC 9557 [Zone] suffix, when valid */\n zone?: string;\n /** false: a value this control cannot read (an object, a word); it is shown and never overwritten by accident */\n readable: boolean;\n}\n\nconst STORED = /^(\\d{4})-(\\d{2})-(\\d{2})(?:[T ](\\d{2}):(\\d{2})(?::\\d{2}(?:\\.\\d+)?)?(Z|[+-]\\d{2}:?\\d{2})?)?(?:\\[([^\\]]+)\\])?$/;\nconst EMPTY: ParsedValue = { wall: null, hasTime: false, readable: true };\n\nexport function parseStored(v: unknown): ParsedValue {\n if (v == null || v === \"\") return EMPTY;\n if (typeof v !== \"string\") return { ...EMPTY, readable: false };\n const m = STORED.exec(v.trim());\n if (!m) return { ...EMPTY, readable: false };\n const [, y, mo, d, h, mi, off, zone] = m;\n const date = new Date(Date.UTC(Number(y), Number(mo) - 1, Number(d)));\n if (date.getUTCMonth() !== Number(mo) - 1 || date.getUTCDate() !== Number(d)) return { ...EMPTY, readable: false };\n let offset: number | undefined;\n if (off === \"Z\") offset = 0;\n else if (off) {\n const om = /([+-])(\\d{2}):?(\\d{2})/.exec(off)!;\n offset = (om[1] === \"-\" ? -1 : 1) * (Number(om[2]) * 60 + Number(om[3]));\n }\n return { wall: { ymd: `${y}-${mo}-${d}`, time: h ? `${h}:${mi}` : \"09:00\" }, hasTime: !!h, offset, zone: validZone(zone) ? zone : undefined, readable: true };\n}\n\n/** A stored value as a JS Date (drops the [Zone] annotation, which `new Date()` can't read). */\nexport function storedToDate(v: unknown): Date | null {\n if (typeof v !== \"string\" || !v) return null;\n const d = new Date(v.replace(/\\[[^\\]]*\\]$/, \"\"));\n return Number.isNaN(d.getTime()) ? null : d;\n}\n\n/* ── Zones ────────────────────────────────────────────────────────────── */\n/** Every IANA zone this runtime knows, UTC included. */\nexport const ALL_ZONES: readonly string[] = (() => {\n const list = typeof Intl.supportedValuesOf === \"function\" ? Intl.supportedValuesOf(\"timeZone\").map(modernZone) : [];\n return Array.from(new Set(list.includes(\"UTC\") ? list : [...list, \"UTC\"]));\n})();\n\n/** The first zone (in order) whose offset at the instant is `offset`; undefined when none is. */\nexport function zoneWithOffset(offset: number, instant: Date, candidates: readonly (string | undefined)[]): string | undefined {\n for (const z of candidates) if (z && validZone(z) && offsetMinutes(z, instant) === offset) return z;\n return undefined;\n}\n\n/**\n * What the control shows for a stored value: the wall time and the zone it lives in.\n *\n * - none: the stored wall time, as typed.\n * - site / fixed: that zone. A stored instant with another offset is shown as THAT instant's wall time in the zone,\n * so the shown and the saved time never disagree.\n * - pick: the stored [Zone]; else the zone the editor picked this session, the default, the browser's, then any\n * zone whose offset matches the stored one (a \"+05:30\" reads back as Kolkata). A floating time reads in the default.\n */\nexport function resolveShown(parsed: ParsedValue, mode: ZoneMode, zones: { fixed?: string; def: string; picked?: string }): { wall: Wall | null; zone: string } {\n const lockedZone = mode === \"fixed\" ? zones.fixed! : zones.def;\n if (!parsed.wall) return { wall: null, zone: mode === \"pick\" ? (zones.picked ?? zones.def) : lockedZone };\n if (mode === \"none\" || parsed.offset === undefined) {\n const zone = mode === \"pick\" ? (parsed.zone ?? zones.picked ?? zones.def) : lockedZone;\n return { wall: parsed.wall, zone };\n }\n const instant = new Date(wallUtc(parsed.wall) - parsed.offset * 60_000);\n if (mode === \"pick\") {\n const zone = (parsed.zone && offsetMinutes(parsed.zone, instant) === parsed.offset ? parsed.zone : undefined) ?? zoneWithOffset(parsed.offset, instant, [zones.picked, zones.def, browserZone(), ...ALL_ZONES]);\n if (zone) return { wall: parsed.wall, zone };\n return { wall: instantToWall(instant, zones.def), zone: zones.def };\n }\n return { wall: offsetMinutes(lockedZone, instant) === parsed.offset ? parsed.wall : instantToWall(instant, lockedZone), zone: lockedZone };\n}\n\n/* ── Parts → stored value ─────────────────────────────────────────────── */\nexport type WriteResult = { ok: true; value: string } | { ok: false; reason: string };\n\n/** The stored string for a wall time under the field's policy (file header). */\nexport function writeValue(o: { withTime: boolean; mode: ZoneMode; wall: Wall; zone: string }): WriteResult {\n const { withTime, mode, wall, zone } = o;\n if (!withTime) return { ok: true, value: wall.ymd };\n const local = `${wall.ymd}T${wall.time}:00`;\n if (mode === \"none\") return { ok: true, value: local };\n const off = wallOffset(zone, wall);\n if (off === null) return { ok: false, reason: `That local time doesn't exist in ${zoneCity(zone)} (clocks change). Pick another time.` };\n return { ok: true, value: `${local}${offsetIso(off)}${mode === \"fixed\" ? `[${zone}]` : \"\"}` };\n}\n\n/** Today in a zone (the browser's local day for a floating field). */\nexport function todayIn(zone: string | undefined, now = new Date()): string {\n if (zone) return instantToWall(now, zone).ymd;\n return `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}`;\n}\n"],"mappings":"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"}
|