@bettercms-ai/kit 1.0.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +33 -0
- package/dist/adapters/dock-values.d.ts +28 -0
- package/dist/adapters/dock-values.js +41 -0
- package/dist/adapters/dock-values.js.map +1 -0
- package/{adapters → dist/adapters}/icons.js +2 -2
- package/dist/adapters/icons.js.map +1 -0
- package/{adapters → dist/adapters}/lossy.d.ts +90 -31
- package/dist/adapters/lossy.js +414 -0
- package/dist/adapters/lossy.js.map +1 -0
- package/{adapters → dist/adapters}/prod-types.d.ts +82 -4
- package/{adapters → dist/adapters}/prod-types.js +71 -3
- package/dist/adapters/prod-types.js.map +1 -0
- package/{adapters → dist/adapters}/schema.d.ts +40 -1
- package/{adapters → dist/adapters}/schema.js +996 -179
- package/dist/adapters/schema.js.map +1 -0
- package/{adapters → dist/adapters}/values.d.ts +26 -5
- package/{adapters → dist/adapters}/values.js +87 -17
- package/dist/adapters/values.js.map +1 -0
- package/dist/brand/logo.js +96 -0
- package/dist/brand/logo.js.map +1 -0
- package/{context.d.ts → dist/context.d.ts} +92 -2
- package/{context.js → dist/context.js} +5 -2
- package/dist/context.js.map +1 -0
- package/{controls → dist/controls}/button.d.ts +19 -5
- package/{controls → dist/controls}/button.js +125 -54
- package/dist/controls/button.js.map +1 -0
- package/{controls → dist/controls}/c1.js +1 -1
- package/dist/controls/c1.js.map +1 -0
- package/{controls → dist/controls}/c2.js +1 -1
- package/dist/controls/c2.js.map +1 -0
- package/{controls → dist/controls}/choice.d.ts +7 -2
- package/{controls → dist/controls}/choice.js +71 -18
- package/dist/controls/choice.js.map +1 -0
- package/{controls → dist/controls}/code-register.js +1 -1
- package/dist/controls/code-register.js.map +1 -0
- package/{controls → dist/controls}/code.js +10 -9
- package/dist/controls/code.js.map +1 -0
- package/{controls → dist/controls}/color.js +8 -8
- package/dist/controls/color.js.map +1 -0
- package/{controls → dist/controls}/component-services.d.ts +42 -0
- package/dist/controls/component-services.js +7 -0
- package/dist/controls/component-services.js.map +1 -0
- package/{controls → dist/controls}/date-register.js +1 -1
- package/dist/controls/date-register.js.map +1 -0
- package/{controls → dist/controls}/date-zone.js +8 -2
- package/dist/controls/date-zone.js.map +1 -0
- package/{controls → dist/controls}/date.js +32 -24
- package/dist/controls/date.js.map +1 -0
- package/{controls → dist/controls}/form-picker-register.js +1 -1
- package/dist/controls/form-picker-register.js.map +1 -0
- package/{controls → dist/controls}/form-picker.js +11 -9
- package/dist/controls/form-picker.js.map +1 -0
- package/{controls → dist/controls}/icon-register.js +1 -1
- package/dist/controls/icon-register.js.map +1 -0
- package/{controls → dist/controls}/icon.d.ts +4 -2
- package/{controls → dist/controls}/icon.js +32 -27
- package/dist/controls/icon.js.map +1 -0
- package/{controls → dist/controls}/index.d.ts +1 -1
- package/{controls → dist/controls}/index.js +4 -3
- package/dist/controls/index.js.map +1 -0
- package/{controls → dist/controls}/json-register.js +1 -1
- package/dist/controls/json-register.js.map +1 -0
- package/{controls → dist/controls}/json.js +13 -3
- package/dist/controls/json.js.map +1 -0
- package/{controls → dist/controls}/link.js +6 -6
- package/dist/controls/link.js.map +1 -0
- package/{controls → dist/controls}/location-register.js +1 -1
- package/dist/controls/location-register.js.map +1 -0
- package/{controls → dist/controls}/location.js +64 -40
- package/dist/controls/location.js.map +1 -0
- package/{controls → dist/controls}/media-register.js +1 -1
- package/dist/controls/media-register.js.map +1 -0
- package/{controls → dist/controls}/media-services.d.ts +6 -0
- package/dist/controls/media-services.js +0 -0
- package/{controls → dist/controls}/media.d.ts +35 -4
- package/{controls → dist/controls}/media.js +491 -171
- package/dist/controls/media.js.map +1 -0
- package/{controls → dist/controls}/number.js +10 -9
- package/dist/controls/number.js.map +1 -0
- package/{controls → dist/controls}/reference-register.js +1 -1
- package/dist/controls/reference-register.js.map +1 -0
- package/{controls → dist/controls}/reference-services.d.ts +4 -0
- package/dist/controls/reference-services.js +0 -0
- package/{controls → dist/controls}/reference.d.ts +1 -1
- package/{controls → dist/controls}/reference.js +93 -77
- package/dist/controls/reference.js.map +1 -0
- package/dist/controls/rich-text/blocks.d.ts +49 -0
- package/{controls → dist/controls}/rich-text/blocks.js +471 -144
- package/dist/controls/rich-text/blocks.js.map +1 -0
- package/{controls → dist/controls}/rich-text/catalog.d.ts +4 -1
- package/{controls → dist/controls}/rich-text/catalog.js +75 -65
- package/dist/controls/rich-text/catalog.js.map +1 -0
- package/{controls → dist/controls}/rich-text/codec.d.ts +9 -1
- package/{controls → dist/controls}/rich-text/codec.js +3 -1
- package/dist/controls/rich-text/codec.js.map +1 -0
- package/{controls → dist/controls}/rich-text/component-card.d.ts +1 -1
- package/{controls → dist/controls}/rich-text/component-card.js +417 -99
- package/dist/controls/rich-text/component-card.js.map +1 -0
- package/dist/controls/rich-text/component-panel.d.ts +47 -0
- package/dist/controls/rich-text/component-panel.js +141 -0
- package/dist/controls/rich-text/component-panel.js.map +1 -0
- package/{controls → dist/controls}/rich-text/control.d.ts +1 -2
- package/{controls → dist/controls}/rich-text/control.js +84 -42
- package/dist/controls/rich-text/control.js.map +1 -0
- package/{controls → dist/controls}/rich-text/dom.d.ts +52 -9
- package/{controls → dist/controls}/rich-text/dom.js +379 -50
- package/dist/controls/rich-text/dom.js.map +1 -0
- package/{controls → dist/controls}/rich-text/editor.d.ts +7 -0
- package/{controls → dist/controls}/rich-text/editor.js +148 -48
- package/dist/controls/rich-text/editor.js.map +1 -0
- package/{controls → dist/controls}/rich-text/floating.d.ts +6 -1
- package/{controls → dist/controls}/rich-text/floating.js +35 -18
- package/dist/controls/rich-text/floating.js.map +1 -0
- package/{controls → dist/controls}/rich-text/index.js +1 -1
- package/dist/controls/rich-text/index.js.map +1 -0
- package/dist/controls/rich-text/link-form.js +147 -0
- package/dist/controls/rich-text/link-form.js.map +1 -0
- package/{controls → dist/controls}/rich-text/markdown.js +4 -2
- package/dist/controls/rich-text/markdown.js.map +1 -0
- package/{controls → dist/controls}/rich-text/ops.js +17 -15
- package/dist/controls/rich-text/ops.js.map +1 -0
- package/dist/controls/rich-text/plain.d.ts +17 -0
- package/dist/controls/rich-text/plain.js +44 -0
- package/dist/controls/rich-text/plain.js.map +1 -0
- package/{controls → dist/controls}/rich-text/toolbar.d.ts +6 -2
- package/{controls → dist/controls}/rich-text/toolbar.js +12 -7
- package/dist/controls/rich-text/toolbar.js.map +1 -0
- package/{controls → dist/controls}/scale.js +5 -5
- package/dist/controls/scale.js.map +1 -0
- package/{controls → dist/controls}/slot-register.js +1 -1
- package/dist/controls/slot-register.js.map +1 -0
- package/{controls → dist/controls}/slot-services.d.ts +25 -0
- package/dist/controls/slot-services.js +155 -0
- package/dist/controls/slot-services.js.map +1 -0
- package/{controls → dist/controls}/slot.js +42 -24
- package/dist/controls/slot.js.map +1 -0
- package/{controls → dist/controls}/table/index.js +1 -1
- package/dist/controls/table/index.js.map +1 -0
- package/{controls → dist/controls}/table/prod.js +3 -3
- package/dist/controls/table/prod.js.map +1 -0
- package/{controls → dist/controls}/table/refs.js +13 -2
- package/dist/controls/table/refs.js.map +1 -0
- package/{controls → dist/controls}/table/stored.js +1 -1
- package/dist/controls/table/stored.js.map +1 -0
- package/{controls → dist/controls}/table/table-editor.js +51 -48
- package/dist/controls/table/table-editor.js.map +1 -0
- package/{controls → dist/controls}/table/table-link.js +3 -3
- package/dist/controls/table/table-link.js.map +1 -0
- package/{controls → dist/controls}/table/table.js +3 -3
- package/dist/controls/table/table.js.map +1 -0
- package/{controls → dist/controls}/text.d.ts +2 -2
- package/{controls → dist/controls}/text.js +78 -43
- package/dist/controls/text.js.map +1 -0
- package/dist/controls/unknown-value.d.ts +17 -0
- package/dist/controls/unknown-value.js +66 -0
- package/dist/controls/unknown-value.js.map +1 -0
- package/dist/core/core.d.ts +63 -0
- package/dist/core/core.js +171 -0
- package/dist/core/core.js.map +1 -0
- package/dist/core/facets.d.ts +347 -0
- package/dist/core/facets.js +334 -0
- package/dist/core/facets.js.map +1 -0
- package/dist/core/index.d.ts +3 -0
- package/dist/core/index.js +3 -0
- package/{engine → dist/engine}/array.js +34 -21
- package/dist/engine/array.js.map +1 -0
- package/{engine → dist/engine}/bits.js +1 -1
- package/dist/engine/bits.js.map +1 -0
- package/{engine → dist/engine}/breadcrumb.d.ts +3 -3
- package/{engine → dist/engine}/breadcrumb.js +12 -36
- package/dist/engine/breadcrumb.js.map +1 -0
- package/{engine → dist/engine}/expand.d.ts +2 -4
- package/{engine → dist/engine}/expand.js +5 -22
- package/dist/engine/expand.js.map +1 -0
- package/{engine → dist/engine}/field-list.js +1 -1
- package/dist/engine/field-list.js.map +1 -0
- package/{engine → dist/engine}/field-shell.js +249 -121
- package/dist/engine/field-shell.js.map +1 -0
- package/{engine → dist/engine}/frame.d.ts +3 -1
- package/{engine → dist/engine}/frame.js +16 -14
- package/dist/engine/frame.js.map +1 -0
- package/{engine → dist/engine}/group-summary.d.ts +2 -1
- package/{engine → dist/engine}/group-summary.js +7 -3
- package/dist/engine/group-summary.js.map +1 -0
- package/{engine → dist/engine}/grouping.d.ts +19 -5
- package/{engine → dist/engine}/grouping.js +193 -21
- package/dist/engine/grouping.js.map +1 -0
- package/{engine → dist/engine}/item-list.d.ts +11 -1
- package/{engine → dist/engine}/item-list.js +35 -13
- package/dist/engine/item-list.js.map +1 -0
- package/{engine → dist/engine}/kit-field.js +45 -10
- package/dist/engine/kit-field.js.map +1 -0
- package/{engine → dist/engine}/schema-form.d.ts +27 -2
- package/{engine → dist/engine}/schema-form.js +182 -40
- package/dist/engine/schema-form.js.map +1 -0
- package/{engine → dist/engine}/slot.js +5 -15
- package/dist/engine/slot.js.map +1 -0
- package/dist/index.js +47 -0
- package/dist/index.js.map +1 -0
- package/{kit.css → dist/kit.css} +19 -0
- package/{lib → dist/lib}/cn.js +7 -4
- package/dist/lib/cn.js.map +1 -0
- package/{lib → dist/lib}/columns.js +4 -1
- package/dist/lib/columns.js.map +1 -0
- package/{lib → dist/lib}/frames.js +2 -2
- package/dist/lib/frames.js.map +1 -0
- package/dist/lib/icon-image.d.ts +10 -0
- package/dist/lib/icon-image.js +8 -0
- package/dist/lib/icon-image.js.map +1 -0
- package/{lib → dist/lib}/icons.js +4 -3
- package/dist/lib/icons.js.map +1 -0
- package/dist/lib/input-modality.d.ts +11 -0
- package/dist/lib/input-modality.js +47 -0
- package/dist/lib/input-modality.js.map +1 -0
- package/dist/lib/key-event.d.ts +11 -0
- package/dist/lib/key-event.js +16 -0
- package/dist/lib/key-event.js.map +1 -0
- package/{lib → dist/lib}/path.js +4 -2
- package/dist/lib/path.js.map +1 -0
- package/{lib → dist/lib}/schema.d.ts +34 -3
- package/{lib → dist/lib}/schema.js +110 -13
- package/dist/lib/schema.js.map +1 -0
- package/{lib → dist/lib}/utils.js +1 -1
- package/dist/lib/utils.js.map +1 -0
- package/{lib → dist/lib}/validate.d.ts +11 -1
- package/{lib → dist/lib}/validate.js +85 -11
- package/dist/lib/validate.js.map +1 -0
- package/dist/library/analysis.d.ts +23 -0
- package/dist/library/analysis.js +160 -0
- package/dist/library/analysis.js.map +1 -0
- package/dist/library/catalog.d.ts +57 -0
- package/dist/library/catalog.js +307 -0
- package/dist/library/catalog.js.map +1 -0
- package/dist/library/coreNotes.d.ts +8 -0
- package/dist/library/coreNotes.js +111 -0
- package/dist/library/coreNotes.js.map +1 -0
- package/dist/library/coverage.d.ts +40 -0
- package/dist/library/coverage.js +59 -0
- package/dist/library/coverage.js.map +1 -0
- package/dist/library/entries/advanced.entries.d.ts +2 -0
- package/dist/library/entries/advanced.entries.js +6579 -0
- package/dist/library/entries/advanced.entries.js.map +1 -0
- package/dist/library/entries/commerce.entries.d.ts +2 -0
- package/dist/library/entries/commerce.entries.js +4140 -0
- package/dist/library/entries/commerce.entries.js.map +1 -0
- package/dist/library/entries/company.entries.d.ts +2 -0
- package/dist/library/entries/company.entries.js +2731 -0
- package/dist/library/entries/company.entries.js.map +1 -0
- package/dist/library/entries/conversion.entries.d.ts +2 -0
- package/dist/library/entries/conversion.entries.js +3707 -0
- package/dist/library/entries/conversion.entries.js.map +1 -0
- package/dist/library/entries/data.entries.d.ts +7 -0
- package/dist/library/entries/data.entries.js +4613 -0
- package/dist/library/entries/data.entries.js.map +1 -0
- package/dist/library/entries/events.entries.d.ts +2 -0
- package/dist/library/entries/events.entries.js +3428 -0
- package/dist/library/entries/events.entries.js.map +1 -0
- package/dist/library/entries/features.entries.d.ts +2 -0
- package/dist/library/entries/features.entries.js +3157 -0
- package/dist/library/entries/features.entries.js.map +1 -0
- package/dist/library/entries/heroes.entries.d.ts +2 -0
- package/dist/library/entries/heroes.entries.js +3401 -0
- package/dist/library/entries/heroes.entries.js.map +1 -0
- package/dist/library/entries/index.d.ts +3 -0
- package/dist/library/entries/index.js +35 -0
- package/dist/library/entries/index.js.map +1 -0
- package/dist/library/entries/listings.entries.d.ts +2 -0
- package/dist/library/entries/listings.entries.js +2976 -0
- package/dist/library/entries/listings.entries.js.map +1 -0
- package/dist/library/entries/longform.entries.d.ts +2 -0
- package/dist/library/entries/longform.entries.js +4227 -0
- package/dist/library/entries/longform.entries.js.map +1 -0
- package/dist/library/entries/media.entries.d.ts +2 -0
- package/dist/library/entries/media.entries.js +2781 -0
- package/dist/library/entries/media.entries.js.map +1 -0
- package/dist/library/entries/navigation.entries.d.ts +2 -0
- package/dist/library/entries/navigation.entries.js +4011 -0
- package/dist/library/entries/navigation.entries.js.map +1 -0
- package/dist/library/entries/pricing.entries.d.ts +2 -0
- package/dist/library/entries/pricing.entries.js +2383 -0
- package/dist/library/entries/pricing.entries.js.map +1 -0
- package/dist/library/entries/social-proof.entries.d.ts +2 -0
- package/dist/library/entries/social-proof.entries.js +2297 -0
- package/dist/library/entries/social-proof.entries.js.map +1 -0
- package/dist/library/examples/bento.d.ts +92 -0
- package/dist/library/examples/bento.js +201 -0
- package/dist/library/examples/bento.js.map +1 -0
- package/dist/library/examples/blocks.d.ts +14 -0
- package/dist/library/examples/blocks.js +313 -0
- package/dist/library/examples/blocks.js.map +1 -0
- package/dist/library/examples/faq.d.ts +28 -0
- package/dist/library/examples/faq.js +230 -0
- package/dist/library/examples/faq.js.map +1 -0
- package/dist/library/examples/hero.d.ts +43 -0
- package/dist/library/examples/hero.js +222 -0
- package/dist/library/examples/hero.js.map +1 -0
- package/dist/library/examples/index.d.ts +36 -0
- package/dist/library/examples/index.js +109 -0
- package/dist/library/examples/index.js.map +1 -0
- package/dist/library/examples/journalStory.d.ts +93 -0
- package/dist/library/examples/journalStory.js +338 -0
- package/dist/library/examples/journalStory.js.map +1 -0
- package/dist/library/examples/megaMenu.d.ts +134 -0
- package/dist/library/examples/megaMenu.js +442 -0
- package/dist/library/examples/megaMenu.js.map +1 -0
- package/dist/library/examples/pricing.d.ts +103 -0
- package/dist/library/examples/pricing.js +479 -0
- package/dist/library/examples/pricing.js.map +1 -0
- package/dist/library/examples/tabs.d.ts +87 -0
- package/dist/library/examples/tabs.js +180 -0
- package/dist/library/examples/tabs.js.map +1 -0
- package/dist/library/export.d.ts +42 -0
- package/dist/library/export.js +80 -0
- package/dist/library/export.js.map +1 -0
- package/dist/library/index.d.ts +13 -0
- package/dist/library/index.js +6 -0
- package/dist/library/kit-catalog.json +1510 -0
- package/dist/library/types.d.ts +42 -0
- package/dist/library/types.js +0 -0
- package/{schema → dist/schema}/adapters.js +1 -2
- package/dist/schema/adapters.js.map +1 -0
- package/{schema → dist/schema}/help.d.ts +2 -0
- package/{schema → dist/schema}/help.js +6 -4
- package/dist/schema/help.js.map +1 -0
- package/{schema → dist/schema}/scale.js +1 -1
- package/dist/schema/scale.js.map +1 -0
- package/{schema → dist/schema}/sources.js +1 -1
- package/dist/schema/sources.js.map +1 -0
- package/{schema → dist/schema}/table.js +11 -10
- package/dist/schema/table.js.map +1 -0
- package/{schema → dist/schema}/types.d.ts +29 -1
- package/{schema → dist/schema}/types.js +1 -1
- package/dist/schema/types.js.map +1 -0
- package/dist/styles.css +2 -0
- package/dist/table/table-view.d.ts +14 -0
- package/dist/table/table-view.js +140 -0
- package/dist/table/table-view.js.map +1 -0
- package/dist/table/table.css +73 -0
- package/dist/testing/corpus.d.ts +63 -0
- package/dist/testing/corpus.js +129 -0
- package/dist/testing/corpus.js.map +1 -0
- package/dist/testing/test-form.d.ts +11 -0
- package/dist/testing/test-form.js +38 -0
- package/dist/testing/test-form.js.map +1 -0
- package/dist/theme.css +345 -0
- package/dist/theme.d.ts +22 -0
- package/dist/theme.js +43 -0
- package/dist/theme.js.map +1 -0
- package/dist/tokens.css +542 -0
- package/dist/types.js +0 -0
- package/{ui → dist/ui}/action-tray.d.ts +1 -1
- package/{ui → dist/ui}/action-tray.js +20 -19
- package/dist/ui/action-tray.js.map +1 -0
- package/dist/ui/autocomplete.d.ts +30 -0
- package/dist/ui/autocomplete.js +139 -0
- package/dist/ui/autocomplete.js.map +1 -0
- package/{ui → dist/ui}/button.d.ts +3 -3
- package/{ui → dist/ui}/button.js +6 -7
- package/dist/ui/button.js.map +1 -0
- package/{ui → dist/ui}/choice-switch.js +1 -1
- package/dist/ui/choice-switch.js.map +1 -0
- package/{ui → dist/ui}/controls.js +51 -39
- package/dist/ui/controls.js.map +1 -0
- package/{ui → dist/ui}/display.d.ts +10 -3
- package/{ui → dist/ui}/display.js +57 -46
- package/dist/ui/display.js.map +1 -0
- package/{ui → dist/ui}/expanded-editor-modal.d.ts +2 -2
- package/{ui → dist/ui}/expanded-editor-modal.js +6 -6
- package/dist/ui/expanded-editor-modal.js.map +1 -0
- package/{ui → dist/ui}/field-context.js +1 -1
- package/dist/ui/field-context.js.map +1 -0
- package/{ui → dist/ui}/floating-panel.d.ts +1 -1
- package/{ui → dist/ui}/floating-panel.js +28 -12
- package/dist/ui/floating-panel.js.map +1 -0
- package/{ui → dist/ui}/index.d.ts +4 -0
- package/dist/ui/index.js +18 -0
- package/{ui → dist/ui}/input.d.ts +1 -1
- package/{ui → dist/ui}/input.js +9 -9
- package/dist/ui/input.js.map +1 -0
- package/{ui → dist/ui}/mode-bar.js +3 -3
- package/dist/ui/mode-bar.js.map +1 -0
- package/{ui → dist/ui}/overlay.d.ts +77 -5
- package/dist/ui/overlay.js +697 -0
- package/dist/ui/overlay.js.map +1 -0
- package/{ui → dist/ui}/path-crumbs.js +37 -3
- package/dist/ui/path-crumbs.js.map +1 -0
- package/{ui → dist/ui}/presence.js +2 -2
- package/dist/ui/presence.js.map +1 -0
- package/{ui → dist/ui}/select.js +89 -87
- package/dist/ui/select.js.map +1 -0
- package/{ui → dist/ui}/shortcut-hint.js +1 -1
- package/dist/ui/shortcut-hint.js.map +1 -0
- package/dist/ui/spinner.d.ts +24 -0
- package/dist/ui/spinner.js +42 -0
- package/dist/ui/spinner.js.map +1 -0
- package/dist/ui/split-button.d.ts +32 -0
- package/dist/ui/split-button.js +60 -0
- package/dist/ui/split-button.js.map +1 -0
- package/{ui → dist/ui}/surfaces.js +1 -1
- package/dist/ui/surfaces.js.map +1 -0
- package/dist/ui/tab.d.ts +38 -0
- package/dist/ui/tab.js +87 -0
- package/dist/ui/tab.js.map +1 -0
- package/dist/ui/toast.d.ts +20 -0
- package/dist/ui/toast.js +115 -0
- package/dist/ui/toast.js.map +1 -0
- package/{ui → dist/ui}/tooltip-root.d.ts +4 -3
- package/{ui → dist/ui}/tooltip-root.js +9 -8
- package/dist/ui/tooltip-root.js.map +1 -0
- package/{ui → dist/ui}/variants.js +1 -1
- package/dist/ui/variants.js.map +1 -0
- package/package.json +77 -23
- package/adapters/icons.js.map +0 -1
- package/adapters/lossy.js +0 -233
- package/adapters/lossy.js.map +0 -1
- package/adapters/prod-types.js.map +0 -1
- package/adapters/schema.js.map +0 -1
- package/adapters/values.js.map +0 -1
- package/brand/logo.js +0 -9
- package/brand/logo.js.map +0 -1
- package/context.js.map +0 -1
- package/controls/button.js.map +0 -1
- package/controls/c1.js.map +0 -1
- package/controls/c2.js.map +0 -1
- package/controls/choice.js.map +0 -1
- package/controls/code-register.js.map +0 -1
- package/controls/code.js.map +0 -1
- package/controls/color.js.map +0 -1
- package/controls/date-register.js.map +0 -1
- package/controls/date-zone.js.map +0 -1
- package/controls/date.js.map +0 -1
- package/controls/form-picker-register.js.map +0 -1
- package/controls/form-picker.js.map +0 -1
- package/controls/icon-register.js.map +0 -1
- package/controls/icon.js.map +0 -1
- package/controls/index.js.map +0 -1
- package/controls/json-register.js.map +0 -1
- package/controls/json.js.map +0 -1
- package/controls/link.js.map +0 -1
- package/controls/location-register.js.map +0 -1
- package/controls/location.js.map +0 -1
- package/controls/media-register.js.map +0 -1
- package/controls/media.js.map +0 -1
- package/controls/number.js.map +0 -1
- package/controls/reference-register.js.map +0 -1
- package/controls/reference.js.map +0 -1
- package/controls/rich-text/blocks.d.ts +0 -28
- package/controls/rich-text/blocks.js.map +0 -1
- package/controls/rich-text/catalog.js.map +0 -1
- package/controls/rich-text/codec.js.map +0 -1
- package/controls/rich-text/component-card.js.map +0 -1
- package/controls/rich-text/control.js.map +0 -1
- package/controls/rich-text/dom.js.map +0 -1
- package/controls/rich-text/editor.js.map +0 -1
- package/controls/rich-text/floating.js.map +0 -1
- package/controls/rich-text/index.js.map +0 -1
- package/controls/rich-text/link-form.js +0 -111
- package/controls/rich-text/link-form.js.map +0 -1
- package/controls/rich-text/markdown.js.map +0 -1
- package/controls/rich-text/ops.js.map +0 -1
- package/controls/rich-text/toolbar.js.map +0 -1
- package/controls/scale.js.map +0 -1
- package/controls/slot-register.js.map +0 -1
- package/controls/slot-services.js +0 -38
- package/controls/slot-services.js.map +0 -1
- package/controls/slot.js.map +0 -1
- package/controls/table/index.js.map +0 -1
- package/controls/table/prod.js.map +0 -1
- package/controls/table/refs.js.map +0 -1
- package/controls/table/stored.js.map +0 -1
- package/controls/table/table-editor.js.map +0 -1
- package/controls/table/table-link.js.map +0 -1
- package/controls/table/table.js.map +0 -1
- package/controls/text.js.map +0 -1
- package/engine/array.js.map +0 -1
- package/engine/bits.js.map +0 -1
- package/engine/breadcrumb.js.map +0 -1
- package/engine/expand.js.map +0 -1
- package/engine/field-list.js.map +0 -1
- package/engine/field-shell.js.map +0 -1
- package/engine/frame.js.map +0 -1
- package/engine/group-summary.js.map +0 -1
- package/engine/grouping.js.map +0 -1
- package/engine/item-list.js.map +0 -1
- package/engine/kit-field.js.map +0 -1
- package/engine/schema-form.js.map +0 -1
- package/engine/slot.js.map +0 -1
- package/index.js +0 -55
- package/index.js.map +0 -1
- package/lib/cn.js.map +0 -1
- package/lib/columns.js.map +0 -1
- package/lib/frames.js.map +0 -1
- package/lib/icons.js.map +0 -1
- package/lib/path.js.map +0 -1
- package/lib/schema.js.map +0 -1
- package/lib/utils.js.map +0 -1
- package/lib/validate.js.map +0 -1
- package/schema/adapters.js.map +0 -1
- package/schema/help.js.map +0 -1
- package/schema/scale.js.map +0 -1
- package/schema/sources.js.map +0 -1
- package/schema/table.js.map +0 -1
- package/schema/types.js.map +0 -1
- package/ui/action-tray.js.map +0 -1
- package/ui/button.js.map +0 -1
- package/ui/choice-switch.js.map +0 -1
- package/ui/controls.js.map +0 -1
- package/ui/display.js.map +0 -1
- package/ui/expanded-editor-modal.js.map +0 -1
- package/ui/field-context.js.map +0 -1
- package/ui/floating-panel.js.map +0 -1
- package/ui/index.js +0 -13
- package/ui/input.js.map +0 -1
- package/ui/mode-bar.js.map +0 -1
- package/ui/overlay.js +0 -378
- package/ui/overlay.js.map +0 -1
- package/ui/path-crumbs.js.map +0 -1
- package/ui/presence.js.map +0 -1
- package/ui/select.js.map +0 -1
- package/ui/shortcut-hint.js.map +0 -1
- package/ui/surfaces.js.map +0 -1
- package/ui/tooltip-root.js.map +0 -1
- package/ui/variants.js.map +0 -1
- /package/{_virtual → dist/_virtual}/_rolldown/runtime.js +0 -0
- /package/{adapters → dist/adapters}/icons.d.ts +0 -0
- /package/{brand → dist/brand}/logo.d.ts +0 -0
- /package/{controls → dist/controls}/c1.d.ts +0 -0
- /package/{controls → dist/controls}/c2.d.ts +0 -0
- /package/{controls → dist/controls}/code-register.d.ts +0 -0
- /package/{controls → dist/controls}/code.d.ts +0 -0
- /package/{controls → dist/controls}/color.d.ts +0 -0
- /package/{controls → dist/controls}/date-register.d.ts +0 -0
- /package/{controls → dist/controls}/date-zone.d.ts +0 -0
- /package/{controls → dist/controls}/date.d.ts +0 -0
- /package/{controls → dist/controls}/form-picker-register.d.ts +0 -0
- /package/{controls → dist/controls}/form-picker.d.ts +0 -0
- /package/{controls → dist/controls}/icon-register.d.ts +0 -0
- /package/{controls → dist/controls}/json-register.d.ts +0 -0
- /package/{controls → dist/controls}/json.d.ts +0 -0
- /package/{controls → dist/controls}/link.d.ts +0 -0
- /package/{controls → dist/controls}/location-register.d.ts +0 -0
- /package/{controls → dist/controls}/location.d.ts +0 -0
- /package/{controls → dist/controls}/media-register.d.ts +0 -0
- /package/{controls → dist/controls}/number.d.ts +0 -0
- /package/{controls → dist/controls}/reference-register.d.ts +0 -0
- /package/{controls → dist/controls}/rich-text/index.d.ts +0 -0
- /package/{controls → dist/controls}/rich-text/link-form.d.ts +0 -0
- /package/{controls → dist/controls}/rich-text/markdown.d.ts +0 -0
- /package/{controls → dist/controls}/rich-text/ops.d.ts +0 -0
- /package/{controls → dist/controls}/scale.d.ts +0 -0
- /package/{controls → dist/controls}/slot-register.d.ts +0 -0
- /package/{controls → dist/controls}/slot.d.ts +0 -0
- /package/{controls → dist/controls}/table/index.d.ts +0 -0
- /package/{controls → dist/controls}/table/prod.d.ts +0 -0
- /package/{controls → dist/controls}/table/refs.d.ts +0 -0
- /package/{controls → dist/controls}/table/stored.d.ts +0 -0
- /package/{controls → dist/controls}/table/table-editor.d.ts +0 -0
- /package/{controls → dist/controls}/table/table-link.d.ts +0 -0
- /package/{controls → dist/controls}/table/table.d.ts +0 -0
- /package/{engine → dist/engine}/array.d.ts +0 -0
- /package/{engine → dist/engine}/bits.d.ts +0 -0
- /package/{engine → dist/engine}/field-list.d.ts +0 -0
- /package/{engine → dist/engine}/field-shell.d.ts +0 -0
- /package/{engine → dist/engine}/kit-field.d.ts +0 -0
- /package/{engine → dist/engine}/slot.d.ts +0 -0
- /package/{index.d.ts → dist/index.d.ts} +0 -0
- /package/{lib → dist/lib}/cn.d.ts +0 -0
- /package/{lib → dist/lib}/columns.d.ts +0 -0
- /package/{lib → dist/lib}/frames.d.ts +0 -0
- /package/{lib → dist/lib}/icons.d.ts +0 -0
- /package/{lib → dist/lib}/path.d.ts +0 -0
- /package/{lib → dist/lib}/utils.d.ts +0 -0
- /package/{schema → dist/schema}/adapters.d.ts +0 -0
- /package/{schema → dist/schema}/scale.d.ts +0 -0
- /package/{schema → dist/schema}/sources.d.ts +0 -0
- /package/{schema → dist/schema}/table.d.ts +0 -0
- /package/{types.d.ts → dist/types.d.ts} +0 -0
- /package/{ui → dist/ui}/choice-switch.d.ts +0 -0
- /package/{ui → dist/ui}/controls.d.ts +0 -0
- /package/{ui → dist/ui}/field-context.d.ts +0 -0
- /package/{ui → dist/ui}/mode-bar.d.ts +0 -0
- /package/{ui → dist/ui}/path-crumbs.d.ts +0 -0
- /package/{ui → dist/ui}/presence.d.ts +0 -0
- /package/{ui → dist/ui}/select.d.ts +0 -0
- /package/{ui → dist/ui}/shortcut-hint.d.ts +0 -0
- /package/{ui → dist/ui}/surfaces.d.ts +0 -0
- /package/{ui → dist/ui}/variants.d.ts +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"field-shell.js","names":[],"sources":["../../src/engine/field-shell.tsx"],"sourcesContent":["/**\n * FIELD SHELL — the one field chrome (V2 HEAD 9829bf1 kit/engine/field-shell.tsx; production FieldShell + CPO D8).\n *\n * [Label *] [ⓘ] [override dot] [changed dot] [synced] [EN] …… [42 / 60] [action] [Reset] [undo] [comments] [presence] [⋯]\n * help text (CPO D39: 12/16 --fg-3, 4px under the label, 1–2 lines; hidden while an error shows)\n * ┌ control ───────────────────────────────┐ ← peer editing: the control's border in their colour\n * └────────────────────────────────────────┘\n * error / warning message ……………………… meta (42 / 60)\n *\n * Accessories (add-comment, ⋯) take NO space at rest; they appear on hover/focus (always on touch). A comment\n * COUNT chip is always visible. AI lives in ⋯ (\"Rewrite with AI\"), never as a label sparkle (CPO-142).\n *\n * Services (toast, AI rewrite, in-place comments) come from KitServices; a missing service hides its surface.\n */\nimport * as React from \"react\";\nimport { createPortal } from \"react-dom\";\nimport {\n IconAlertCircle, IconAlertTriangle, IconArrowBackUp, IconBraces, IconClipboard, IconCopy, IconDots, IconHistory, IconInfoCircle,\n IconLock, IconMessage, IconMessagePlus, IconRefresh, IconRotate, IconWorld,\n} from \"@tabler/icons-react\";\nimport { AnimatePresence, motion } from \"framer-motion\";\nimport { Button, Sparkle } from \"../ui/button\";\nimport { Avatar, avatarRingSpread } from \"../ui/display\";\nimport { Menu, MenuContent, MenuItem, MenuSeparator, MenuTrigger, Popover, PopoverAnchor, PopoverContent, Tooltip } from \"../ui/overlay\";\nimport { presenceColor } from \"../ui/presence\";\nimport { cn } from \"../lib/cn\";\nimport { HISTORY_SEGMENT, type FieldPath, type FieldSchema } from \"../schema/types\";\nimport { resolveHelp } from \"../schema/help\";\nimport { AI_PRESETS, FieldHeaderSlot, KitSectionTitle, seesDevSurfaces, useForm, useKitEnv, useKitServices, type AiPreset, type KitPeer } from \"../context\";\nimport { pathKey, same } from \"../lib/path\";\nimport { isTextual, plainText } from \"../lib/schema\";\nimport { textLength, type KitIssue } from \"../lib/validate\";\nimport { RowChrome } from \"./bits\";\n\n/* ── Clipboard shared by every field (typed, so Paste can refuse with a reason) ── */\n/** `html`: a rich text value as its editor html (read through the host's codec), so Paste re-stores it for the target field. */\nlet clip: { type: string; value: unknown; label: string; html?: string } | null = null;\n/** Test seam: forget the shared field clipboard. */\nexport const resetFieldClipboard = () => {\n clip = null;\n};\nconst KIND: Record<string, string> = { image: \"an image\", file: \"a file\", video: \"a video\", reference: \"a reference\", link: \"a link\", button: \"a button\", array: \"a list\", slot: \"blocks\", object: \"a group of fields\", boolean: \"an on/off value\", number: \"a number\", color: \"a colour\" };\nconst kindOf = (t: string) => (isTextual(t as FieldSchema[\"type\"]) ? \"text\" : KIND[t] ?? t);\n\ntype RichTextCodec = NonNullable<ReturnType<typeof useKitServices>[\"richText\"]>;\nconst escHtml = (s: string) => s.replace(/&/g, \"&\").replace(/</g, \"<\").replace(/>/g, \">\");\n/** Plain text as editor html: one escaped paragraph per line. */\nconst paragraphs = (text: string) =>\n text\n .split(/\\n+/)\n .map((l) => l.trim())\n .filter(Boolean)\n .map((l) => `<p>${escHtml(l)}</p>`)\n .join(\"\");\n/**\n * Html into a rich text field, stored in the field's own shape through the host's codec. A write that would drop\n * something is refused with the words the codec names; nothing is stored.\n */\nfunction richTextWrite(codec: RichTextCodec, field: FieldSchema, path: FieldPath, html: string, prev: unknown): { value: unknown } | { refused: string } {\n try {\n const out = codec.write(html, { field, path }, prev);\n return out.losses.length ? { refused: `${field.title} can't keep ${out.losses.join(\", \")}` } : { value: out.value };\n } catch (err) {\n return { refused: `${field.title} could not store this text (${err instanceof Error ? err.message : String(err)})` };\n }\n}\n/** A rich text value as editor html, when the host's codec reads it. */\nfunction richTextHtml(codec: RichTextCodec | undefined, field: FieldSchema, path: FieldPath, value: unknown): string | undefined {\n if (!codec || field.type !== \"richtext\") return undefined;\n try {\n return codec.read(value, { field, path }).html;\n } catch {\n return undefined; // Paste falls back to the value's words\n }\n}\n\nexport const apiName = (schemaName: string, path: FieldPath) =>\n [schemaName, ...path.filter((s) => s !== HISTORY_SEGMENT)].reduce<string>((a, s) => (typeof s === \"number\" ? `${a}[${s}]` : a ? `${a}.${s}` : String(s)), \"\");\n\n/** A long label truncates on one line; past this many characters a native `title` carries the full label (DESIGN 4.4). */\nexport const LABEL_HINT_AT = 28;\n\nconst REVEAL =\n \"hidden group-hover/field:inline-flex group-focus-within/field:inline-flex data-[state=open]:inline-flex data-[popup-open]:inline-flex [@media(pointer:coarse)]:inline-flex\";\n\nexport interface FieldShellProps {\n field: FieldSchema;\n path: FieldPath;\n id: string;\n value: unknown;\n onChange: (v: unknown) => void;\n readOnly?: boolean;\n issue?: KitIssue;\n /** label-row action (e.g. slug \"Generate\") */\n action?: React.ReactNode;\n /** \"card\" = the boolean switch card · \"row\" = the control IS a labelled row (a drill-in object, CPO D45): no label row,\n * the chrome goes into the row through `RowChrome` */\n layout?: \"stack\" | \"card\" | \"row\";\n /** layout fields get no comment control */\n noComments?: boolean;\n /** right side of the message line (counters, \"3 items · max 6\") */\n meta?: React.ReactNode;\n className?: string;\n children: React.ReactNode;\n}\n\nexport function FieldShell({ field, path, id, value, onChange, readOnly, issue, action, layout = \"stack\", noComments, meta, className, children }: FieldShellProps) {\n const env = useKitEnv();\n const form = useForm();\n const services = useKitServices();\n const key = pathKey(path);\n /* A host can lift this field's chrome into its own header (All fields: a block whose only field is \"Stats\" under a\n \"Stats\" section) — then there is no label row at all; the label stays for screen readers. */\n const slot = React.useContext(FieldHeaderSlot);\n const lifted = slot && slot.key === key && layout === \"stack\" ? slot.el : null;\n const [ai, setAi] = React.useState(false);\n const [commentsOpen, setCommentsOpen] = React.useState(false);\n /* V2 fieldPopoverCollision: the comments popover stays inside the scrolling area the field sits in */\n const [commentArea, setCommentArea] = React.useState<CommentCollision>({ collisionPadding: 12 });\n const peers = env.presence[key] ?? [];\n const editor = peers.find((p) => p.status !== \"viewing\");\n const InPlaceComments = services.FieldComments;\n /* a meta-form (the schema editor's field settings) shows no comment, ⋯ or per-field undo chrome (KitEnv.fieldChrome) */\n const quiet = env.fieldChrome === \"quiet\";\n const bare = quiet || env.fieldChrome === \"preview\";\n const canComment = !noComments && !bare && (!!env.onComment || !!InPlaceComments);\n const openCount = env.comments[key] ?? 0; // with no env.onComment and a count hook, CommentButton reads the store\n const useStoreCount = env.onComment ? undefined : services.useFieldCommentCount;\n const changed = !!form?.hasPublished && !same(value, form.publishedAt(path));\n /* component instance (D28): a top-level field either inherits the component's value or overrides it */\n const inh = form?.inherited && path.length === 1 ? form.inherited : undefined;\n const overridden = !!inh && inh.isOverridden(key);\n /* D61: while the host's History is open, a changed field gets the host's 2px author-colour bar at its left edge\n (with its hover card) instead of the quiet \"changed\" dot. At rest (History closed) the dot stays. */\n const reviewing = !!env.review;\n const bar = env.review && env.review.count(path) > 0 ? env.review.bar(path, field) : null;\n const sectionTitle = React.useContext(KitSectionTitle);\n /* \"Options\" in a section called \"Options\": the section heading already names the field (the label stays for readers) */\n const repeatsSection = quiet && layout === \"stack\" && !!sectionTitle && sectionTitle.trim().toLowerCase() === field.title.trim().toLowerCase();\n const canUndo = !bare && !!form?.canUndo(key) && !readOnly;\n const synced = field.synced?.from; // a whole synced form shows one notice at its root, not a chip per field\n const limit = field.validation?.max ?? field.validation?.recommendedMax;\n const len = textLength(value);\n /* counters stay quiet: shown while the field has focus, or when the value nears its limit */\n const near = !!limit && len >= limit * 0.8;\n const counter =\n limit && (field.type === \"string\" || field.type === \"text\" || field.type === \"richtext\") ? (\n <span\n data-slot=\"field-counter\"\n className={cn(\n \"tabular-nums text-kit-xs\",\n !near && \"hidden group-focus-within/field:inline\",\n field.validation?.max && len > field.validation.max ? \"text-kit-danger-fg\" : field.validation?.recommendedMax && len > field.validation.recommendedMax ? \"text-kit-warning-fg\" : \"text-kit-fg-3\",\n )}\n >\n {len} / {limit}\n </span>\n ) : null;\n\n /* ── Help (CPO D39) ── one line under the label; longer text behind ⓘ. Dense hosts (env.helpDisplay \"tooltip\")\n move the line into the ⓘ too. An error REPLACES the help (warnings keep it: they're advice, not a block). */\n const dense = env.helpDisplay === \"tooltip\";\n /* D70: a field locked for this person (its own edit cap, in a form they can otherwise change) says so: a small lock glyph\n before the reason. A whole read-only form (Viewer, view as) stays plain text with no glyphs (D58). */\n const lockedHere = !!readOnly && !!field.access?.edit && !env.readOnly && !env.can(field.access.edit);\n const help = lockedHere ? (field.lockReason?.trim() || \"Set by developers\").replace(/\\.?$/, \".\") : resolveHelp(field); // arrays / slots / objects reach the shell without KitField: conventions apply here too\n const helpNode = lockedHere ? (\n <span data-locked=\"\" className=\"inline-flex items-start gap-1\">\n <IconLock className=\"mt-px size-3 shrink-0\" stroke={1.75} aria-hidden />\n <span>\n <span className=\"sr-only\">Locked. </span>\n {help}\n </span>\n </span>\n ) : (\n help\n );\n const more = field.helpMore || undefined;\n const erroring = issue?.level === \"error\";\n // a lock's reason stays on the field even in a dense host: it says why the value can't change\n const helpInline = !!help && (!dense || lockedHere) && !erroring;\n const tip = dense && !lockedHere ? [help, more].filter(Boolean).join(\" \") : more;\n const helpId = `${id}-help`;\n const moreId = `${id}-more`;\n const msgId = `${id}-msg`;\n const describedBy = [helpInline && helpId, tip && moreId, issue && msgId].filter(Boolean).join(\" \");\n /* Controls are many (input, textarea, contenteditable, pickers); the shell owns the ids, so it wires\n aria-describedby onto whatever element carries the field id, keeping any ids the control set itself. */\n React.useEffect(() => {\n const el = document.getElementById(id);\n if (!el) return;\n const own = (el.getAttribute(\"aria-describedby\") ?? \"\").split(\" \").filter((t) => t && !t.startsWith(`${id}-`));\n const next = [...own, ...describedBy.split(\" \").filter(Boolean)].join(\" \");\n if (next) el.setAttribute(\"aria-describedby\", next);\n else el.removeAttribute(\"aria-describedby\");\n }, [id, describedBy]);\n const info = tip ? (\n <Tooltip content={<span className=\"block max-w-[260px] whitespace-normal font-normal leading-4\">{tip}</span>}>\n <button type=\"button\" aria-label={`About ${field.title}`} className=\"-my-0.5 inline-flex size-4 shrink-0 items-center justify-center rounded-kit-sm text-kit-fg-4 hover:text-kit-fg-2\">\n <IconInfoCircle className=\"size-3.5\" stroke={1.5} aria-hidden />\n <span id={moreId} className=\"sr-only\">{tip}</span>\n </button>\n </Tooltip>\n ) : null;\n\n const label = (\n <>\n <span className=\"truncate\">{field.title}</span>\n {field.validation?.required ? (\n <>\n <span aria-hidden className=\"text-kit-fg-2\">*</span>\n <span className=\"sr-only\">(required)</span>\n </>\n ) : null}\n </>\n );\n const badges = (\n <>\n {overridden ? (\n <Tooltip content={`Overrides ${inh!.from}. Changes to the block no longer reach this field.`}>\n <span role=\"img\" className=\"size-1.5 shrink-0 rounded-full bg-kit-accent\" aria-label={`Overrides ${inh!.from}`} />\n </Tooltip>\n ) : null}\n {changed && !reviewing ? (\n <Tooltip content=\"Changed since publish\">\n <span role=\"img\" className=\"size-1.5 shrink-0 rounded-full bg-kit-warning\" aria-label=\"Changed since publish\" />\n </Tooltip>\n ) : null}\n {synced ? (\n <Tooltip content={`Synced from ${synced}. Changes apply on every page that uses it.`}>\n <span className=\"inline-flex h-4 shrink-0 items-center gap-0.5 rounded-kit-md bg-kit-info-soft px-1 text-kit-2xs font-medium text-kit-info-fg\">\n <IconRefresh className=\"size-2.5\" stroke={2} aria-hidden />\n Synced\n </span>\n </Tooltip>\n ) : null}\n {field.localized ? (\n <Tooltip content=\"Translatable: this field can hold a value for each of the site's languages.\">\n <span className=\"inline-flex h-4 shrink-0 items-center gap-0.5 rounded-kit-md bg-kit-muted px-1 text-kit-2xs font-medium text-kit-fg-3\">\n <IconWorld className=\"size-2.5\" stroke={2} aria-hidden />\n EN\n </span>\n </Tooltip>\n ) : null}\n </>\n );\n const accessories = (\n <>\n {action}\n {overridden && !readOnly ? (\n <Tooltip content={`Use ${inh!.from}'s value again`}>\n <button\n type=\"button\"\n onClick={(e) => {\n const box = (e.currentTarget as HTMLElement).closest<HTMLElement>(\"[data-field-key]\");\n inh!.reset(key);\n // the button goes away with the override: keep focus in the field, never on <body>\n requestAnimationFrame(() => (document.getElementById(id) ?? box?.querySelector<HTMLElement>(\"textarea, input, [contenteditable=true], button\"))?.focus({ preventScroll: true }));\n }}\n aria-label={`Reset ${field.title} to ${inh!.from}`}\n className=\"inline-flex h-5 items-center rounded-kit-md px-1 text-kit-xs text-kit-fg-3 hover:bg-kit-hover hover:text-kit-fg\"\n >\n Reset\n </button>\n </Tooltip>\n ) : null}\n {canUndo ? (\n <Tooltip content={`Undo last change to ${field.title}`}>\n <button type=\"button\" aria-label={`Undo last change to ${field.title}`} onClick={() => form?.undo(key)} className=\"inline-flex size-5 items-center justify-center rounded-kit-md text-kit-fg-3 hover:bg-kit-hover hover:text-kit-fg\">\n <IconArrowBackUp className=\"size-3.5\" stroke={1.5} aria-hidden />\n </button>\n </Tooltip>\n ) : null}\n {canComment ? (\n <CommentButton\n count={openCount}\n useCount={useStoreCount ? () => useStoreCount(env.docId, key) : undefined}\n label={field.title}\n open={commentsOpen}\n onOpen={(el) => {\n if (env.onComment) return env.onComment(path, field); // the host owns comments (e.g. the document editor)\n setCommentArea(fieldPopoverCollision(el.closest(\"[data-field-key]\")));\n setCommentsOpen(true);\n }}\n />\n ) : null}\n <PeerStack peers={peers} />\n {bare ? null : <FieldMenu field={field} path={path} value={value} onChange={onChange} readOnly={!!readOnly} changed={changed} onAi={() => setAi(true)} />}\n </>\n );\n\n // Peer editing (Figma / Notion / Sanity): only the field's own input border takes their --presence-n colour (full strength:\n // the old 70% mix read as a validation error at 1.96:1) —\n // no outline around the input + preview, no name tag over the border, no layout shift. Who it is: the face in the label row.\n const control = (\n <div\n className={cn(\"relative\", editor && \"[&_.border-kit-field-border]:border-[var(--peer)]\")}\n style={editor ? ({ \"--peer\": editor.color ?? presenceColor(editor.id ?? editor.name) } as React.CSSProperties) : undefined}\n >\n {children}\n </div>\n );\n\n const message =\n issue || meta ? (\n <div className=\"flex min-h-4 items-start justify-between gap-3\">\n <AnimatePresence initial={false}>\n {issue ? (\n <motion.p\n key={issue.message}\n id={msgId}\n initial={{ opacity: 0, y: -2 }}\n animate={{ opacity: 1, y: 0 }}\n role={issue.level === \"error\" ? \"alert\" : \"status\"}\n className={cn(\"flex min-w-0 items-start gap-1 text-kit-xs\", issue.level === \"error\" ? \"text-kit-danger-fg\" : \"text-kit-warning-fg\")}\n >\n {issue.level === \"error\" ? <IconAlertCircle className=\"mt-px size-3.5 shrink-0\" stroke={1.5} aria-hidden /> : <IconAlertTriangle className=\"mt-px size-3.5 shrink-0\" stroke={1.5} aria-hidden />}\n <span className=\"min-w-0\">\n {issue.message}\n {issue.fix && !readOnly ? (\n <>\n {\" \"}\n <button type=\"button\" onClick={issue.fix.apply} className=\"font-medium text-kit-fg underline-offset-2 hover:underline\">\n {issue.fix.label}\n </button>\n </>\n ) : null}\n </span>\n </motion.p>\n ) : (\n <span />\n )}\n </AnimatePresence>\n {meta ? <span className=\"flex shrink-0 items-center gap-2\">{meta}</span> : null}\n </div>\n ) : null;\n\n const labelEl = (\n <label\n htmlFor={id}\n id={`${id}-label`}\n className=\"flex min-w-0 items-center gap-1 text-kit-sm font-medium text-kit-fg-2 transition-colors group-focus-within/field:text-kit-fg\"\n title={field.title.length > LABEL_HINT_AT ? field.title : undefined}\n >\n {label}\n </label>\n );\n\n const body =\n layout === \"row\" ? (\n <div className={cn(\"group/field relative flex min-w-0 flex-col gap-1.5\", className)} data-field-key={key} data-field={path.length === 1 ? key : undefined} data-slot=\"kit-field\">\n {bar}\n <RowChrome.Provider value={<>{info}{badges}{accessories}</>}>{control}</RowChrome.Provider>\n {message}\n </div>\n ) : layout === \"card\" && quiet ? (\n /* the inspector's PRow: label left, switch right, no card (a meta-form's Required, Unique, Tuck into Advanced) */\n <div className={cn(\"group/field relative flex flex-col gap-1\", className)} data-field-key={key} data-field={path.length === 1 ? key : undefined} data-slot=\"kit-field\">\n {bar}\n <div data-field-head=\"\" className=\"flex min-h-8 items-center gap-3\">\n <label htmlFor={id} id={`${id}-label`} className=\"min-w-0 flex-1 cursor-pointer\">\n <span className=\"flex min-w-0 items-center gap-1 text-kit-sm font-medium text-kit-fg-2 transition-colors group-focus-within/field:text-kit-fg\">\n {label}\n {info}\n {badges}\n </span>\n {helpInline ? (\n <span id={helpId} data-slot=\"field-help\" className=\"mt-0.5 block text-kit-xs leading-4 text-kit-fg-3\">\n {helpNode}\n </span>\n ) : null}\n </label>\n <span className=\"flex shrink-0 items-center gap-0.5 empty:hidden\">{accessories}</span>\n <span className=\"flex shrink-0 items-center\">{readOnly ? <span className=\"text-kit-sm text-kit-fg-2\">{value ? \"On\" : \"Off\"}</span> : control}</span>\n </div>\n {message}\n </div>\n ) : layout === \"card\" ? (\n <div className={cn(\"group/field relative flex flex-col gap-1.5\", className)} data-field-key={key} data-field={path.length === 1 ? key : undefined} data-slot=\"kit-field\">\n {bar}\n <div data-field-head=\"\" className={cn(\"flex items-center gap-3 rounded-kit-lg border bg-kit-surface px-3 py-2.5 transition-colors\", issue?.level === \"error\" ? \"border-[var(--kit-field-invalid)]\" : \"border-kit-line hover:border-kit-line-strong\")}>\n {control}\n <label htmlFor={id} id={`${id}-label`} className=\"min-w-0 flex-1 cursor-pointer\">\n <span className=\"flex min-w-0 items-center gap-1.5 text-kit-sm font-medium text-kit-fg\">\n {label}\n {info}\n {badges}\n </span>\n {helpInline ? (\n <span id={helpId} data-slot=\"field-help\" className=\"block text-kit-xs leading-4 text-kit-fg-3\">\n {helpNode}\n </span>\n ) : null}\n </label>\n <span className=\"shrink-0 text-kit-xs text-kit-fg-3\">{value ? \"On\" : \"Off\"}</span>\n <span className=\"flex shrink-0 items-center gap-0.5 empty:hidden\">{accessories}</span>\n </div>\n {message}\n </div>\n ) : (\n <div\n className={cn(\"group/field relative flex min-w-0 flex-col gap-1.5\", className)}\n data-field-key={key}\n data-field={path.length === 1 ? key : undefined}\n data-slot=\"kit-field\"\n data-inherited={inh && !overridden ? \"\" : undefined}\n data-overridden={overridden ? \"\" : undefined}\n >\n {bar}\n {repeatsSection ? (\n <label htmlFor={id} id={`${id}-label`} className=\"sr-only\">\n {label}\n </label>\n ) : lifted ? (\n <>\n <label htmlFor={id} id={`${id}-label`} className=\"sr-only\">\n {label}\n </label>\n {createPortal(\n <span className=\"flex items-center gap-0.5 [&>button]:!inline-flex\">\n {info}\n {badges}\n {counter}\n {accessories}\n </span>,\n lifted,\n )}\n </>\n ) : (\n <div data-slot=\"field-label-row\" data-field-head=\"\" className=\"flex min-h-5 min-w-0 items-center gap-1.5\">\n {labelEl}\n {info}\n {badges}\n <span className=\"flex-1\" />\n {counter}\n <span className=\"flex shrink-0 items-center gap-0.5\">{accessories}</span>\n </div>\n )}\n {helpInline ? (\n <p id={helpId} data-slot=\"field-help\" className=\"-mt-0.5 text-kit-xs leading-4 text-kit-fg-3\">\n {helpNode}\n </p>\n ) : null}\n {control}\n {message}\n </div>\n );\n\n /* The AI popover and the comments popover both anchor to the field (two stacked anchor divs). */\n return (\n <Popover open={ai} onOpenChange={setAi}>\n <PopoverAnchor className=\"min-w-0\">\n <Popover\n open={commentsOpen}\n onOpenChange={(open, d) => {\n /* V2 guardEscape: Escape inside the composer (data-esc-owner) belongs to the draft, not the popover */\n if (!open && d.reason === \"escape-key\" && (document.activeElement as HTMLElement | null)?.hasAttribute(\"data-esc-owner\")) return d.cancel();\n setCommentsOpen(open);\n }}\n >\n <PopoverAnchor className=\"min-w-0\">{body}</PopoverAnchor>\n {commentsOpen && InPlaceComments ? (\n <PopoverContent align=\"start\" sideOffset={8} {...commentArea} initialFocus={false} className=\"w-[clamp(280px,var(--anchor-width),420px)] p-0\">\n <InPlaceComments\n docId={env.docId}\n fieldKey={key}\n label={field.title}\n quote={plainText(value).slice(0, 80) || undefined}\n onClose={() => setCommentsOpen(false)}\n onOpenPanel={\n env.onComment\n ? () => {\n env.onComment?.(path, field);\n setCommentsOpen(false);\n }\n : undefined\n }\n />\n </PopoverContent>\n ) : null}\n </Popover>\n </PopoverAnchor>\n {ai ? (\n <PopoverContent align=\"start\" sideOffset={8} className=\"w-[clamp(300px,var(--anchor-width),440px)] p-0\">\n <AiRewrite field={field} path={path} value={value} onChange={onChange} onClose={() => setAi(false)} />\n </PopoverContent>\n ) : null}\n </Popover>\n );\n}\n\ntype CommentCollision = { collisionBoundary?: Element; collisionPadding: number | Partial<Record<\"top\" | \"right\" | \"bottom\" | \"left\", number>> };\n/** V2 features/comments fieldPopoverCollision: inside a scrolling panel, collide with that panel below its sticky header. */\nfunction fieldPopoverCollision(anchor: Element | null): CommentCollision {\n let area = anchor?.parentElement ?? null;\n while (area && !/(auto|scroll)/.test(getComputedStyle(area).overflowY)) area = area.parentElement;\n if (!area || area === document.scrollingElement) return { collisionPadding: 12 };\n const sticky = parseFloat(getComputedStyle(area).getPropertyValue(\"--kit-sticky-top\")) || 0;\n return { collisionBoundary: area, collisionPadding: { top: sticky + 8, right: 8, bottom: 8, left: 8 } };\n}\n\n/** Comment count chip (always visible) or the hover-revealed \"Add comment\" icon. `useCount` (the host's store hook)\n * replaces `count` when the kit draws the comments in place. */\nfunction CommentButton({ useCount, ...props }: CommentButtonProps & { useCount?: () => number }) {\n return useCount ? <StoreCommentButton useCount={useCount} {...props} /> : <CountedCommentButton {...props} />;\n}\ninterface CommentButtonProps {\n count: number;\n label: string;\n open: boolean;\n onOpen: (el: HTMLElement) => void;\n}\nfunction StoreCommentButton({ useCount, ...props }: CommentButtonProps & { useCount: () => number }) {\n return <CountedCommentButton {...props} count={useCount()} />;\n}\nfunction CountedCommentButton({ count, label, open, onOpen }: CommentButtonProps) {\n if (count > 0)\n return (\n <Tooltip content={`${count} open comment${count === 1 ? \"\" : \"s\"} on ${label}`}>\n <button\n type=\"button\"\n onClick={(e) => onOpen(e.currentTarget)}\n data-state={open ? \"open\" : \"closed\"}\n aria-label={`${count} open comments on ${label}`}\n className=\"-my-0.5 inline-flex h-5 items-center gap-0.5 rounded-kit-md px-1 text-kit-2xs font-medium text-kit-fg-3 hover:bg-kit-hover hover:text-kit-fg data-[state=open]:bg-kit-hover data-[state=open]:text-kit-fg\"\n >\n <IconMessage className=\"size-3.5\" stroke={1.5} aria-hidden />\n <span className=\"tabular-nums\">{count}</span>\n </button>\n </Tooltip>\n );\n return (\n <Tooltip content=\"Add comment\">\n <button\n type=\"button\"\n onClick={(e) => onOpen(e.currentTarget)}\n data-state={open ? \"open\" : \"closed\"}\n aria-label={`Add comment to ${label}`}\n className={cn(REVEAL, \"-my-0.5 size-6 items-center justify-center rounded-kit-md text-kit-fg-3 hover:bg-kit-hover hover:text-kit-fg\")}\n >\n <IconMessagePlus className=\"size-3.5\" stroke={1.5} aria-hidden />\n </button>\n </Tooltip>\n );\n}\n\n/** Who is in this field: 16px faces in the label row's action slot (no overlap with the label or the input), name on hover. */\nexport function PeerStack({ peers, size = 16 }: { peers: KitPeer[]; size?: number }) {\n const shown = peers.slice(0, 3);\n const rest = peers.length - shown.length;\n // Each slot reserves the ring band (1px surface gap + 1px presence colour) on every side, so the ring sits inside\n // the slot: a clipping ancestor or the row's edge can never shave it. Faces still overlap by 25% of their size.\n const ring = \"var(--kit-avatar-ring, var(--kit-surface))\";\n const band = avatarRingSpread({ ring, ringWidth: 1, ringAccent: \"x\" });\n const box = size + band * 2;\n const overlap = -(Math.round(size * 0.25) + band * 2);\n return (\n <AnimatePresence initial={false}>\n {shown.length ? (\n <motion.span key=\"peers\" initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} transition={{ duration: 0.25 }} className=\"flex h-5 items-center\" data-slot=\"field-presence\">\n {/* D34 stack rules: same size, 25% overlap, first face on top; the ring is box-shadow (surface gap + the\n peer's presence colour) so the photo keeps its full size. */}\n {shown.map((p, i) => (\n <Tooltip key={p.name + i} content={`${p.name} · ${p.status === \"viewing\" ? \"Viewing\" : \"Editing\"} this field`}>\n <span\n style={{ marginLeft: i ? overlap : 0, zIndex: shown.length - i + 1, width: box, height: box }}\n className={cn(\"relative inline-flex shrink-0 rounded-full transition-transform duration-150 hover:!z-30 hover:-translate-y-px\", p.status === \"viewing\" && \"opacity-60\")}\n >\n <Avatar name={p.name} src={p.avatar} size={size} ring={ring} ringWidth={1} ringAccent={p.color ?? presenceColor(p.id ?? p.name)} decorative />\n </span>\n </Tooltip>\n ))}\n {rest > 0 ? (\n <Tooltip content={peers.slice(shown.length).map((p) => p.name).join(\", \")}>\n <span style={{ marginLeft: overlap, width: box, height: box, padding: band }} className=\"relative z-[1] inline-flex shrink-0\">\n <span\n style={{ width: size, height: size, boxShadow: `0 0 0 ${band}px var(--kit-surface)`, fontSize: Math.max(8, Math.round(size * 0.5)) }}\n className=\"inline-flex items-center justify-center rounded-full bg-kit-muted font-medium leading-none tabular-nums text-kit-fg-2\"\n >\n +{rest}\n </span>\n </span>\n </Tooltip>\n ) : null}\n </motion.span>\n ) : null}\n </AnimatePresence>\n );\n}\n\n/* ── ⋯ Field actions (DESIGN 8.25) ─────────────────────────────────── */\nfunction FieldMenu({ field, path, value, onChange, readOnly, changed, onAi }: { field: FieldSchema; path: FieldPath; value: unknown; onChange: (v: unknown) => void; readOnly: boolean; changed: boolean; onAi: () => void }) {\n const form = useForm();\n const env = useKitEnv();\n const { toast, aiRewrite, richText, FieldMenuExtras } = useKitServices();\n const key = pathKey(path);\n const api = apiName(form?.schema.name ?? \"doc\", path);\n const textual = isTextual(field.type);\n // rich text is rewritten only where the host's codec can store the result in the field's own shape\n const prose = field.type === \"string\" || field.type === \"text\" || (field.type === \"richtext\" && !!richText);\n const editable = !readOnly;\n const dev = seesDevSurfaces(env);\n return (\n <Menu>\n <Tooltip content=\"Field actions\">\n <MenuTrigger\n aria-label={`${field.title} actions`}\n className={cn(REVEAL, \"-my-0.5 size-6 items-center justify-center rounded-kit-md text-kit-fg-3 hover:bg-kit-hover hover:text-kit-fg data-[popup-open]:bg-kit-hover data-[popup-open]:text-kit-fg\")}\n >\n <IconDots className=\"size-3.5\" stroke={1.5} aria-hidden />\n </MenuTrigger>\n </Tooltip>\n <MenuContent align=\"end\" className=\"w-60\">\n <MenuItem\n icon={<IconCopy stroke={1.5} />}\n onClick={() => {\n const html = richTextHtml(richText, field, path, value);\n clip = { type: field.type, value: structuredCloneish(value), label: field.title, ...(html !== undefined ? { html } : {}) };\n const text = textual ? plainText(value) || \"\" : typeof value === \"string\" ? value : JSON.stringify(value ?? null, null, 2);\n void navigator.clipboard?.writeText(text).catch(() => {});\n toast?.success(`${field.title} copied`);\n }}\n >\n Copy value\n </MenuItem>\n {editable ? <PasteItem field={field} path={path} value={value} onChange={onChange} /> : null}\n {editable && form?.hasPublished && changed ? (\n <MenuItem\n icon={<IconRotate stroke={1.5} />}\n onClick={() => {\n const prev = value;\n onChange(form.publishedAt(path));\n toast?.(`${field.title} reset to published`, { action: { label: \"Undo\", onClick: () => onChange(prev) }, duration: 10_000 });\n }}\n >\n Reset to published\n </MenuItem>\n ) : null}\n {form?.canNavigate ? (\n <MenuItem icon={<IconHistory stroke={1.5} />} onClick={() => form.navigate([...path, HISTORY_SEGMENT])}>\n History\n </MenuItem>\n ) : null}\n {FieldMenuExtras ? <FieldMenuExtras field={field} path={path} readOnly={readOnly} /> : null}\n {editable && prose && aiRewrite ? (\n <>\n <MenuSeparator />\n {form?.aiKeys.has(key) ? (\n <MenuItem\n icon={<IconArrowBackUp stroke={1.5} />}\n onClick={() => {\n form.undo(key);\n form.markAi(key, false);\n }}\n >\n Undo AI change\n </MenuItem>\n ) : null}\n <MenuItem icon={<Sparkle size={16} />} onClick={() => window.setTimeout(onAi, 0)}>\n Rewrite with AI\n </MenuItem>\n </>\n ) : null}\n {dev ? <MenuSeparator /> : null}\n {dev ? (\n <MenuItem\n icon={<IconBraces stroke={1.5} />}\n onClick={() => {\n void navigator.clipboard?.writeText(api).catch(() => {});\n toast?.success(`Copied ${api}`);\n }}\n >\n <span className=\"flex w-full items-center justify-between gap-3\">\n Copy API name\n <span className=\"truncate font-kit-mono text-kit-2xs text-kit-fg-3\">{api.length > 22 ? `…${api.slice(-20)}` : api}</span>\n </span>\n </MenuItem>\n ) : null}\n </MenuContent>\n </Menu>\n );\n}\n/** Reads the shared clipboard when the menu opens (it mounts with the popup), so a copy in another field is seen. */\nfunction PasteItem({ field, path, value, onChange }: { field: FieldSchema; path: FieldPath; value: unknown; onChange: (v: unknown) => void }) {\n const { toast, richText } = useKitServices();\n const textual = isTextual(field.type);\n // text into rich text needs the host's codec to store it in the field's shape\n const needsCodec = !!clip && field.type === \"richtext\" && clip.type !== \"richtext\" && !richText;\n const pasteOk = clip && !needsCodec && (clip.type === field.type || (textual && isTextual(clip.type as FieldSchema[\"type\"])));\n const pasteReason = !clip\n ? \"Copy a value from a field first.\"\n : needsCodec\n ? \"This rich text field takes a copied rich text value only.\"\n : pasteOk\n ? null\n : `Clipboard holds ${kindOf(clip.type)}. This field takes ${kindOf(field.type)}.`;\n return (\n <MenuItem\n icon={<IconClipboard stroke={1.5} />}\n disabled={!pasteOk}\n className={cn(pasteReason && \"h-auto py-1.5\")}\n onClick={() => {\n if (!clip) return;\n const prev = value;\n let next: unknown;\n if (field.type === \"richtext\" && richText && (clip.type !== \"richtext\" || clip.html !== undefined)) {\n // through the codec: the target field's own shape and Accept list, refused by name when it would drop something\n const out = richTextWrite(richText, field, path, clip.html ?? paragraphs(plainText(clip.value)), prev);\n if (\"refused\" in out) {\n toast?.(`Not pasted: ${out.refused}.`);\n return;\n }\n next = out.value;\n } else next = textual && clip.type === \"richtext\" && field.type !== \"richtext\" ? plainText(clip.value) : structuredCloneish(clip.value);\n onChange(next);\n toast?.(`Pasted into ${field.title}`, { action: { label: \"Undo\", onClick: () => onChange(prev) }, duration: 10_000 });\n }}\n >\n <span className=\"flex flex-col\">\n Paste value\n {pasteReason ? <span className=\"whitespace-normal text-kit-xs text-kit-fg-3\">{pasteReason}</span> : null}\n </span>\n </MenuItem>\n );\n}\nfunction structuredCloneish<T>(v: T): T {\n try {\n return structuredClone(v);\n } catch {\n return v;\n }\n}\n\n/* ── Rewrite with AI (preview before apply) ────────────────────────── */\nfunction AiRewrite({ field, path, value, onChange, onClose }: { field: FieldSchema; path: FieldPath; value: unknown; onChange: (v: unknown) => void; onClose: () => void }) {\n const form = useForm();\n const { toast, aiRewrite, richText } = useKitServices();\n const key = pathKey(path);\n const [preset, setPreset] = React.useState<AiPreset | null>(null);\n const [out, setOut] = React.useState<string | null>(null);\n const [failed, setFailed] = React.useState(false);\n const attempt = React.useRef(0);\n const latest = React.useRef(0);\n const source = plainText(value);\n const run = (p: AiPreset) => {\n if (!aiRewrite) return;\n setPreset(p);\n setOut(null);\n setFailed(false);\n const ticket = ++latest.current;\n Promise.resolve()\n .then(() => aiRewrite(source, p, attempt.current++))\n .then(\n (result) => {\n if (latest.current === ticket) setOut(result);\n },\n () => {\n if (latest.current === ticket) setFailed(true);\n },\n );\n };\n const apply = () => {\n if (!out) return;\n const prev = value;\n let next: unknown = out;\n if (field.type === \"richtext\") {\n const stored = richText ? richTextWrite(richText, field, path, paragraphs(out), prev) : { refused: `${field.title} has no rich text storage here` };\n if (\"refused\" in stored) {\n toast?.(`Not applied: ${stored.refused}.`);\n return;\n }\n next = stored.value;\n }\n onChange(next);\n form?.markAi(key, true);\n toast?.(\"Rewritten with AI\", {\n icon: <Sparkle size={14} />,\n action: {\n label: \"Undo\",\n onClick: () => {\n onChange(prev);\n form?.markAi(key, false);\n },\n },\n duration: 10_000,\n });\n onClose();\n };\n return (\n <div className=\"flex flex-col\">\n <div className=\"flex items-center gap-2 border-b border-kit-line px-3 py-2.5\">\n <Sparkle size={16} />\n <span className=\"text-kit-sm font-medium text-kit-fg\">Rewrite {field.title.toLowerCase()}</span>\n </div>\n <div className=\"flex flex-wrap gap-1 px-3 pt-2.5\">\n {AI_PRESETS.map((p) => (\n <button\n key={p.id}\n type=\"button\"\n onClick={() => run(p.id)}\n className={cn(\"h-6 rounded-full border px-2 text-kit-xs transition-colors\", preset === p.id ? \"border-[var(--kit-emphasis-line)] bg-kit-surface text-kit-fg\" : \"border-kit-line text-kit-fg-2 hover:border-kit-line-strong hover:text-kit-fg\")}\n >\n {p.label}\n </button>\n ))}\n </div>\n <div className=\"px-3 py-3\">\n {!preset ? (\n <p className=\"text-kit-xs text-kit-fg-3\">Pick a direction. You'll see the suggestion before anything changes.</p>\n ) : failed ? (\n <p role=\"alert\" className=\"text-kit-xs text-kit-danger-fg\">\n Couldn't rewrite {field.title.toLowerCase()}. Try again.\n </p>\n ) : out == null ? (\n <p className=\"text-kit-sm\">\n <Shimmer>Rewriting {field.title.toLowerCase()}…</Shimmer>\n </p>\n ) : (\n <div className=\"rounded-kit-lg bg-kit-subtle p-2.5 text-kit-sm leading-5 text-kit-fg\">\n <TypeOut text={out} />\n </div>\n )}\n </div>\n <div className=\"flex items-center justify-between gap-2 border-t border-kit-line px-3 py-2\">\n <Button size=\"xs\" variant=\"ghost\" onClick={onClose}>\n Discard\n </Button>\n <div className=\"flex gap-1\">\n {out || failed ? (\n <Button size=\"xs\" variant=\"ghost\" leftIcon={<IconRefresh stroke={1.5} />} onClick={() => preset && run(preset)}>\n Try again\n </Button>\n ) : null}\n <Button size=\"xs\" variant=\"primary\" disabled={!out} onClick={apply}>\n Apply\n </Button>\n </div>\n </div>\n </div>\n );\n}\n\n/* V2 components/motion.tsx Shimmer + TypeOut, kept local to the AI popover (their only kit user). */\nfunction Shimmer({ children }: { children: React.ReactNode }) {\n return (\n <span className=\"bg-[linear-gradient(90deg,var(--kit-fg-3)_0%,var(--kit-fg)_45%,var(--kit-fg-3)_90%)] bg-[length:200%_100%] bg-clip-text text-transparent [animation:kit-shimmer-text_1.6s_linear_infinite] motion-reduce:[animation:none]\">\n {children}\n </span>\n );\n}\n/**\n * Reduced motion as the app reads it: the OS query or the in-app preference (which stamps `data-reduce-motion` on\n * <html>; the kit cannot import the app's hook). Read per render, so a toggle applies to the next answer.\n */\nfunction motionReduced(): boolean {\n if (typeof window === \"undefined\") return false;\n return document.documentElement.hasAttribute(\"data-reduce-motion\") || !!window.matchMedia?.(\"(prefers-reduced-motion: reduce)\").matches;\n}\n\n/** Reduced: the whole answer at once, with no caret (canvas revamp V701, lib/motion TypeOut semantics). */\nfunction TypeOut({ text, speed = 14 }: { text: string; speed?: number }) {\n const reduce = motionReduced();\n const [n, setN] = React.useState(reduce ? text.length : 0);\n React.useEffect(() => {\n if (reduce) {\n setN(text.length);\n return;\n }\n setN(0);\n const id = setInterval(() => {\n setN((x) => {\n const next = Math.min(text.length, x + Math.max(1, Math.round(text.length / 120)));\n if (next >= text.length) clearInterval(id);\n return next;\n });\n }, speed);\n return () => clearInterval(id);\n }, [text, speed, reduce]);\n return (\n <span>\n {text.slice(0, n)}\n {n < text.length ? <span data-typeout-caret className=\"ml-0.5 inline-block h-[1em] w-[2px] translate-y-[2px] bg-kit-fg motion-safe:animate-pulse\" /> : null}\n </span>\n );\n}\n"],"mappings":"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"}
|
|
@@ -109,12 +109,14 @@ export declare function useFrameNavigation({ frames, navigate, root, scroller, }
|
|
|
109
109
|
* The frame body with V2's slide: 24px along the travel direction + fade, 220ms, ease [0.22, 1, 0.36, 1]; reduced
|
|
110
110
|
* motion keeps only the fade. `before` renders inside the root frame above its fields (the synced-from note).
|
|
111
111
|
*/
|
|
112
|
-
export declare function FrameStage({ frames, frameKey, dir, rootLabel, variant, before, }: {
|
|
112
|
+
export declare function FrameStage({ frames, frameKey, dir, rootLabel, variant, before, review, }: {
|
|
113
113
|
frames: Frame[];
|
|
114
114
|
frameKey: string;
|
|
115
115
|
dir: number;
|
|
116
116
|
rootLabel: string;
|
|
117
117
|
variant: "panel" | "document";
|
|
118
118
|
before?: React.ReactNode;
|
|
119
|
+
/** D61 Review changes is on: the clip leaves 16px on the left for the change bars */
|
|
120
|
+
review?: boolean;
|
|
119
121
|
}): import("react/jsx-runtime").JSX.Element;
|
|
120
122
|
export { HISTORY_SEGMENT };
|
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
import { cn } from "../lib/cn.js";
|
|
2
|
-
import { frameKeyOf, isObj, newKey, pathKey, same } from "../lib/path.js";
|
|
3
2
|
import { resolveFieldAccess, seesDevSurfaces, useForm, useKitEnv, useKitServices } from "../context.js";
|
|
3
|
+
import { frameKeyOf, isObj, newKey, pathKey, same } from "../lib/path.js";
|
|
4
4
|
import { Button, IconButton } from "../ui/button.js";
|
|
5
5
|
import { Segmented } from "../ui/controls.js";
|
|
6
6
|
import { Menu, MenuContent, MenuItem, MenuSeparator, MenuTrigger, Tooltip } from "../ui/overlay.js";
|
|
7
|
-
import { isHidden, isTextual, plainText, previewOf, summarize } from "../lib/schema.js";
|
|
7
|
+
import { condCtx, isHidden, isTextual, plainText, previewOf, summarize } from "../lib/schema.js";
|
|
8
8
|
import { Thumb } from "./bits.js";
|
|
9
9
|
import { Avatar } from "../ui/display.js";
|
|
10
|
-
import "../schema/types.js";
|
|
10
|
+
import { HISTORY_SEGMENT } from "../schema/types.js";
|
|
11
11
|
import { apiName } from "./field-shell.js";
|
|
12
12
|
import { Select } from "../ui/select.js";
|
|
13
13
|
import { fitsSegmented } from "../ui/choice-switch.js";
|
|
14
14
|
import { relTime } from "../lib/utils.js";
|
|
15
15
|
import { FallbackControl, KitField } from "./kit-field.js";
|
|
16
16
|
import * as React from "react";
|
|
17
|
-
import { IconArrowBackUp, IconArrowDown, IconArrowUp, IconCopy, IconDots, IconTrash } from "@tabler/icons-react";
|
|
18
17
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
18
|
+
import { IconArrowBackUp, IconArrowDown, IconArrowUp, IconCopy, IconDots, IconTrash } from "@tabler/icons-react";
|
|
19
19
|
import { AnimatePresence, motion, useReducedMotion } from "framer-motion";
|
|
20
|
-
//#region src/
|
|
20
|
+
//#region src/engine/frame.tsx
|
|
21
21
|
/**
|
|
22
22
|
* FrameView — what the panel shows for the current breadcrumb: the root fields, a drilled object / array item /
|
|
23
23
|
* slot block (with "2 of 4" stepper, variant switcher and per-slot layout settings), the one button screen,
|
|
@@ -39,7 +39,8 @@ function PlainFieldList({ fields, basePath }) {
|
|
|
39
39
|
const form = useForm();
|
|
40
40
|
const raw = basePath.length ? form.getAt(basePath) : form.value;
|
|
41
41
|
const parent = isObj(raw) ? raw : {};
|
|
42
|
-
const
|
|
42
|
+
const cc = condCtx(form, basePath);
|
|
43
|
+
const shown = fields.filter((f) => !isHidden(f, parent, cc));
|
|
43
44
|
return /* @__PURE__ */ jsxs("div", {
|
|
44
45
|
className: "flex flex-col gap-5",
|
|
45
46
|
children: [shown.map((f) => /* @__PURE__ */ jsx("div", {
|
|
@@ -59,12 +60,13 @@ function PlainFieldList({ fields, basePath }) {
|
|
|
59
60
|
function RawButtonScreen({ frame }) {
|
|
60
61
|
const form = useForm();
|
|
61
62
|
const id = React.useId();
|
|
63
|
+
const field = frame.field ?? {
|
|
64
|
+
name: String(frame.path.at(-1) ?? "button"),
|
|
65
|
+
title: frame.title,
|
|
66
|
+
type: "button"
|
|
67
|
+
};
|
|
62
68
|
return /* @__PURE__ */ jsx(FallbackControl, {
|
|
63
|
-
field
|
|
64
|
-
name: String(frame.path.at(-1) ?? "button"),
|
|
65
|
-
title: frame.title,
|
|
66
|
-
type: "button"
|
|
67
|
-
},
|
|
69
|
+
field,
|
|
68
70
|
value: form.getAt(frame.path),
|
|
69
71
|
onChange: (n) => form.setAt(frame.path, n),
|
|
70
72
|
id,
|
|
@@ -549,12 +551,12 @@ var EASE = [
|
|
|
549
551
|
* The frame body with V2's slide: 24px along the travel direction + fade, 220ms, ease [0.22, 1, 0.36, 1]; reduced
|
|
550
552
|
* motion keeps only the fade. `before` renders inside the root frame above its fields (the synced-from note).
|
|
551
553
|
*/
|
|
552
|
-
function FrameStage({ frames, frameKey, dir, rootLabel, variant, before }) {
|
|
554
|
+
function FrameStage({ frames, frameKey, dir, rootLabel, variant, before, review }) {
|
|
553
555
|
const reduce = useReducedMotion();
|
|
554
556
|
const current = frames[frames.length - 1];
|
|
555
557
|
return /* @__PURE__ */ jsx("div", {
|
|
556
558
|
className: "relative",
|
|
557
|
-
style: { overflowX: "clip" },
|
|
559
|
+
style: review ? { clipPath: "inset(-100vh 0 -100vh -16px)" } : { overflowX: "clip" },
|
|
558
560
|
children: /* @__PURE__ */ jsx(AnimatePresence, {
|
|
559
561
|
mode: "popLayout",
|
|
560
562
|
initial: false,
|
|
@@ -594,6 +596,6 @@ function FrameStage({ frames, frameKey, dir, rootLabel, variant, before }) {
|
|
|
594
596
|
});
|
|
595
597
|
}
|
|
596
598
|
//#endregion
|
|
597
|
-
export { FrameHeader, FrameSlotsProvider, FrameStage, FrameView, HistoryView, frameContext, frameDirection, parentOfField, parentTitleOf, useFrameNavigation, useFrameSlots };
|
|
599
|
+
export { FrameHeader, FrameSlotsProvider, FrameStage, FrameView, HISTORY_SEGMENT, HistoryView, frameContext, frameDirection, parentOfField, parentTitleOf, useFrameNavigation, useFrameSlots };
|
|
598
600
|
|
|
599
601
|
//# sourceMappingURL=frame.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frame.js","names":[],"sources":["../../src/engine/frame.tsx"],"sourcesContent":["/**\n * FrameView — what the panel shows for the current breadcrumb: the root fields, a drilled object / array item /\n * slot block (with \"2 of 4\" stepper, variant switcher and per-slot layout settings), the one button screen,\n * or a field's history as a stacked panel. Port of V2 engine/frame.tsx.\n *\n * FrameStage + useFrameNavigation — V2 schema-form's drill-in stage (direction-aware slide, scroll memory per frame,\n * focus on the entering frame, Esc / ⌥↑↓). Exported here so SchemaForm wires them without re-deriving the motion.\n *\n * FrameSlots — the frame draws other lanes' pieces (FieldList / FieldSection from grouping, ButtonScreen from link,\n * TableFrame from table). They arrive through context so this file never imports a module that does not exist yet;\n * a missing slot falls back to a plain field list (FieldList), the raw value (ButtonScreen, through\n * FallbackControl), a named note (TableFrame) or nothing (FieldSection). SchemaForm always hands ButtonScreen and TableFrame.\n */\nimport * as React from \"react\";\nimport { AnimatePresence, motion, useReducedMotion } from \"framer-motion\";\nimport { IconArrowBackUp, IconArrowDown, IconArrowUp, IconCopy, IconDots, IconTrash } from \"@tabler/icons-react\";\nimport { Button, IconButton } from \"../ui/button\";\nimport { Avatar } from \"../ui/display\";\nimport { Menu, MenuContent, MenuItem, MenuSeparator, MenuTrigger, Tooltip } from \"../ui/overlay\";\nimport { Segmented } from \"../ui/controls\";\nimport { fitsSegmented } from \"../ui/choice-switch\";\nimport { Select } from \"../ui/select\";\nimport { resolveFieldAccess, seesDevSurfaces, useForm, useKitEnv, useKitServices } from \"../context\";\nimport { cn } from \"../lib/cn\";\nimport { relTime } from \"../lib/utils\";\nimport { HISTORY_SEGMENT, type FieldGroup, type FieldPath, type FieldSchema, type Fieldset } from \"../schema/types\";\nimport type { Frame } from \"../lib/frames\";\nimport { frameKeyOf, isObj, newKey, pathKey, same } from \"../lib/path\";\nimport { condCtx, isHidden, isTextual, plainText, previewOf, summarize } from \"../lib/schema\";\nimport { Thumb } from \"./bits\";\nimport { FallbackControl, KitField } from \"./kit-field\";\nimport { apiName } from \"./field-shell\";\n\n/* ── Slots (other lanes) ───────────────────────────────────────────── */\nexport interface FrameFieldListProps {\n fields: FieldSchema[];\n fieldsets?: Fieldset[];\n groups?: FieldGroup[];\n basePath: FieldPath;\n memoryKey: string;\n}\nexport interface FrameSlots {\n /** grouping lane: engine/field-list.tsx `FieldList` */\n FieldList?: React.ComponentType<FrameFieldListProps>;\n /** grouping lane: engine/grouping.tsx `FieldSection` (the slot-settings section of a slot block) */\n FieldSection?: React.ComponentType<{ title: string; description?: string; collapsible?: boolean; children: React.ReactNode }>;\n /** link lane: controls/link.tsx `ButtonScreen` + `normLink` (the \"button\" frame) */\n ButtonScreen?: React.ComponentType<{ value: unknown; onChange: (v: unknown) => void; title: string; readOnly?: boolean }>;\n normLink?: (v: unknown) => { label?: string };\n /** table lane: controls/table.tsx `TableFrame` (tableRow / tableColumn frames) */\n TableFrame?: React.ComponentType<{ frame: Frame }>;\n}\nconst SlotsCtx = React.createContext<FrameSlots>({});\nexport const FrameSlotsProvider = SlotsCtx.Provider;\nexport const useFrameSlots = () => React.useContext(SlotsCtx);\n\n/** Stand-in until the grouping lane's FieldList lands: the frame's visible fields in schema order. */\nfunction PlainFieldList({ fields, basePath }: FrameFieldListProps) {\n const form = useForm()!;\n const raw = basePath.length ? form.getAt(basePath) : form.value;\n const parent = isObj(raw) ? raw : {};\n const cc = condCtx(form, basePath);\n const shown = fields.filter((f) => !isHidden(f, parent, cc));\n return (\n <div className=\"flex flex-col gap-5\">\n {shown.map((f) => (\n <div key={f.name} className=\"min-w-0\">\n <KitField field={f} path={[...basePath, f.name]} parent={parent} />\n </div>\n ))}\n {shown.length === 0 ? <p className=\"py-6 text-center text-kit-sm text-kit-fg-3\">No fields here yet.</p> : null}\n </div>\n );\n}\n\n/** A button frame outside SchemaForm (no ButtonScreen slot) edits the button's raw value (FallbackControl), never an empty body. */\nfunction RawButtonScreen({ frame }: { frame: Frame }) {\n const form = useForm()!;\n const id = React.useId();\n const field = frame.field ?? { name: String(frame.path.at(-1) ?? \"button\"), title: frame.title, type: \"button\" as const };\n return <FallbackControl field={field} value={form.getAt(frame.path)} onChange={(n) => form.setAt(frame.path, n)} id={id} path={frame.path} />;\n}\n\n/** The button frame: header (the button's label) + the kit ButtonScreen, read-only when the lens can't edit the field. */\nfunction ButtonFrame({ frame, parentTitle }: { frame: Frame; parentTitle?: string }) {\n const form = useForm()!;\n const env = useKitEnv();\n const slots = useFrameSlots();\n const v = form.getAt(frame.path);\n const ButtonScreen = slots.ButtonScreen;\n const readOnly = frame.field ? resolveFieldAccess(frame.field, env).readOnly : !!env.readOnly;\n return (\n <div className=\"flex flex-col gap-5\">\n <FrameHeader frame={frame} context={parentTitle ? `${frame.title} in ${parentTitle}` : frame.title} title={slots.normLink?.(v).label || frame.title} />\n {ButtonScreen ? <ButtonScreen value={v} onChange={(n) => form.setAt(frame.path, n)} title={frame.title} readOnly={readOnly} /> : <RawButtonScreen frame={frame} />}\n </div>\n );\n}\n\n/* ── FrameView ─────────────────────────────────────────────────────── */\nexport function FrameView({ frame, parentTitle }: { frame: Frame; parentTitle?: string }) {\n const form = useForm()!;\n const slots = useFrameSlots();\n const FieldList = slots.FieldList ?? PlainFieldList;\n if (frame.kind === \"history\") return <HistoryView field={frame.field!} path={frame.path.slice(0, -1)} />;\n if (frame.kind === \"button\") return <ButtonFrame frame={frame} parentTitle={parentTitle} />;\n // D50: a table row or column drills exactly like an array item: the same header (title, n of N, ↑ ↓ ⋯), its cells below\n if (frame.kind === \"tableRow\" || frame.kind === \"tableColumn\") {\n const it = frame.item!;\n const TableFrame = slots.TableFrame;\n return (\n <div className=\"flex flex-col gap-5\">\n <FrameHeader frame={frame} context={`${it.itemSchema?.title} ${it.index + 1} of ${it.count} in ${frame.field?.title ?? \"the table\"}`} title={frame.title} />\n {TableFrame ? (\n <TableFrame frame={frame} />\n ) : (\n /* Only the kit table control opens a row or column frame; until it is ported the table is the host's control,\n which edits rows in place. A path restored into one says so instead of drawing an empty body. */\n <p role=\"note\" data-kit-legacy=\"table\" className=\"text-kit-sm text-kit-fg-3\">\n This table's rows and columns are edited in the table itself.\n </p>\n )}\n </div>\n );\n }\n if (frame.kind === \"root\") return <FieldList fields={frame.fields} fieldsets={frame.fieldsets} groups={frame.groups} basePath={[]} memoryKey=\"root\" />;\n const it = frame.item;\n const block = it?.block;\n const variants = block?.variants ?? [];\n const raw = form.getAt(frame.path);\n const cur = isObj(raw) ? raw : {};\n const FieldSection = slots.FieldSection;\n return (\n <div className=\"flex flex-col gap-5\">\n <FrameHeader frame={frame} context={frameContext(frame, parentTitle)} title={frame.title} />\n {block && variants.length > 1 ? (\n <div className=\"flex flex-col gap-1.5\">\n <span className=\"text-kit-sm font-medium text-kit-fg-2\">Layout</span>\n {fitsSegmented(variants.map((v) => v.name)) ? (\n <Segmented\n aria-label=\"Layout\"\n value={String(cur._variant ?? variants[0].id)}\n onChange={(v) => form.setAt([...frame.path, \"_variant\"], v)}\n items={variants.map((v) => ({ value: v.id, label: v.name }))}\n className=\"w-full [&>button]:flex-1\"\n />\n ) : (\n <Select\n aria-label=\"Variant\"\n value={String(cur._variant ?? variants[0].id)}\n onValueChange={(v) => form.setAt([...frame.path, \"_variant\"], v)}\n options={variants.map((v) => ({ value: v.id, label: v.name, description: v.description }))}\n />\n )}\n </div>\n ) : null}\n <FieldList fields={frame.fields} fieldsets={frame.fieldsets} groups={frame.groups} basePath={frame.path} memoryKey={`f:${frame.kind}:${it?.block?.name ?? it?.itemSchema?.name ?? frame.field?.name ?? \"\"}`} />\n {it?.slotField?.slotSettings?.length && FieldSection ? (\n <FieldSection title={`Layout in ${it.slotField.title.toLowerCase()}`} description=\"How this block sits in its parent. The block's own content is above.\" collapsible={false}>\n <FieldList fields={it.slotField.slotSettings} basePath={[...frame.path, \"_settings\"]} memoryKey={`slotset:${it.slotField.name}`} />\n </FieldSection>\n ) : null}\n </div>\n );\n}\n\n/**\n * The context line under a drilled frame's title: \"Tier 1 of 3 in Tiers\" for an item (the item noun is the item\n * schema's title, which the adapter reads back from prod `ui.itemLabel`), \"Address in Author\" for an object.\n */\nexport function frameContext(frame: Frame, parentTitle?: string): string {\n const it = frame.item;\n if (it) {\n const noun = (frame.kind === \"block\" ? it.block?.title : it.itemSchema?.title) ?? \"Item\";\n const owner = (frame.kind === \"block\" ? it.slotField?.title : frame.field?.title) ?? \"the list\";\n return `${noun} ${it.index + 1} of ${it.count} in ${owner}`;\n }\n return parentTitle ? `${frame.field?.title ?? \"Group\"} in ${parentTitle}` : \"Group\";\n}\n\n/**\n * CPO D43 — the drilled frame's header answers \"what am I editing, and where does it live?\":\n * [media?] Starter [↑] [↓] [⋯]\n * Tier 1 of 3 in Tiers\n * The big title lives HERE only; the breadcrumb above is the path (its current crumb is small, D38). Prev / next are\n * labelled icon buttons whose tooltips name the sibling (\"Previous tier: Starter\"). No eyebrow, no duplicate counter.\n * Title 14/24 semibold (owner call). The native title= on the truncating h2 is V2 parity (kit-engine deviation from\n * the dashboard's no-title rule, see run ledger #32).\n */\nexport function FrameHeader({ frame, context, title }: { frame: Frame; context: string; title: string }) {\n const form = useForm()!;\n const { toast } = useKitServices();\n const it = frame.item;\n const media = it ? previewOf(it.block ?? it.itemSchema, form.getAt(frame.path), it.index).media : undefined;\n const step = (d: -1 | 1) => {\n if (!it) return;\n const n = it.index + d;\n if (n < 0 || n >= it.count) return;\n form.navigate([...it.arrayPath, n]);\n };\n const listRaw = it ? form.getAt(it.arrayPath) : undefined;\n const list = Array.isArray(listRaw) ? listRaw : [];\n const noun = (it?.block?.title ?? it?.itemSchema?.title ?? \"item\").toLowerCase();\n const sibling = (i: number) =>\n it && i >= 0 && i < it.count ? (it.titleAt ? it.titleAt(i) : previewOf(it.block ?? it.itemSchema, list[i], i, it.block?.title ?? it.itemSchema?.title).title) : \"\";\n const prev = it ? sibling(it.index - 1) : \"\";\n const next = it ? sibling(it.index + 1) : \"\";\n /* Duplicate / Remove move to another frame: the menu must not hand focus back to its trigger in the exiting frame\n (it unmounts, focus would drop to <body>); the stage focuses the entering frame instead */\n const moved = React.useRef(false);\n return (\n <div className=\"flex items-start gap-2.5 outline-none\" data-frame-header tabIndex={-1}>\n {media ? <Thumb media={media} size={36} /> : null}\n <div className=\"min-w-0 flex-1\">\n <h2 className=\"truncate text-kit-base font-semibold leading-6 text-kit-fg\" title={title}>\n {title}\n </h2>\n <p className=\"truncate text-kit-xs leading-4 text-kit-fg-3\">{context}</p>\n </div>\n {it ? (\n <div className=\"-mr-1 flex shrink-0 items-center gap-0.5 pt-0.5\">\n <IconButton\n label={prev ? `Previous ${noun}: ${prev}` : `No previous ${noun}`}\n tooltip={prev ? `Previous ${noun}: ${prev}` : `First ${noun}`}\n size=\"sm\"\n disabled={it.index === 0}\n onClick={() => step(-1)}\n >\n <IconArrowUp stroke={1.5} />\n </IconButton>\n <IconButton\n label={next ? `Next ${noun}: ${next}` : `No next ${noun}`}\n tooltip={next ? `Next ${noun}: ${next}` : `Last ${noun}`}\n size=\"sm\"\n disabled={it.index >= it.count - 1}\n onClick={() => step(1)}\n >\n <IconArrowDown stroke={1.5} />\n </IconButton>\n <Menu>\n <Tooltip content={`${title} actions`}>\n <MenuTrigger\n render={\n <IconButton label={`${title} actions`} tooltip={false} size=\"sm\">\n <IconDots stroke={1.5} />\n </IconButton>\n }\n />\n </Tooltip>\n <MenuContent align=\"end\" className=\"w-48\" finalFocus={() => !moved.current}>\n <MenuItem\n icon={<IconCopy stroke={1.5} />}\n onClick={() => {\n moved.current = true;\n const copy = isObj(list[it.index]) ? { ...(structuredClone(list[it.index]) as object), _key: newKey() } : list[it.index];\n form.setAt(it.arrayPath, [...list.slice(0, it.index + 1), copy, ...list.slice(it.index + 1)]);\n form.navigate([...it.arrayPath, it.index + 1]);\n toast?.success(\"Duplicated\", { description: \"You're now editing the copy.\" });\n }}\n >\n Duplicate\n </MenuItem>\n <MenuSeparator />\n <MenuItem\n danger\n icon={<IconTrash stroke={1.5} />}\n onClick={() => {\n moved.current = true;\n const prevList = list;\n form.navigate(parentFramePath(it.arrayPath));\n form.setAt(it.arrayPath, list.filter((_, j) => j !== it.index));\n toast?.(`“${title}” removed`, { action: { label: \"Undo\", onClick: () => form.setAt(it.arrayPath, prevList) }, duration: 10_000 });\n }}\n >\n Remove\n </MenuItem>\n </MenuContent>\n </Menu>\n </div>\n ) : null}\n </div>\n );\n}\n/** The frame that owns an array: drop the array field name (and the item index above it, if any). */\nconst parentFramePath = (arrayPath: FieldPath): FieldPath => arrayPath.slice(0, -1);\n\n/* ── History (stacked panel) ───────────────────────────────────────── */\n/**\n * V2 drew demo people (seed `currentUser` / `members`, a fixed \"26 hours ago\" / \"3 days ago\"). The kit has no seed:\n * session versions carry their own `by` and `at`; the opened and published baselines have no author or time here, so\n * their row says only what they are.\n */\nexport function HistoryView({ field, path }: { field: FieldSchema; path: FieldPath }) {\n const env = useKitEnv();\n const form = useForm()!;\n const { toast } = useKitServices();\n const key = pathKey(path);\n const now = form.getAt(path);\n const session = form.history(key);\n const baseline = form.baselineAt(path);\n const published = form.hasPublished ? form.publishedAt(path) : undefined;\n type V = { id: string; label: string; by?: string; at?: number; value: unknown; current?: boolean };\n const versions: V[] = [];\n versions.push({ id: \"now\", label: \"Current draft\", by: session[0]?.by ?? \"You\", at: Date.now(), value: now, current: true });\n session.slice(1).forEach((h, i) => versions.push({ id: `s${i}`, label: h.label ?? \"Edit\", by: h.by, at: h.at, value: h.value }));\n if (!same(baseline, now) && !session.some((h) => same(h.value, baseline))) versions.push({ id: \"open\", label: \"When you opened it\", value: baseline });\n if (published !== undefined) versions.push({ id: \"pub\", label: \"Published\", value: published });\n const show = (v: unknown) => {\n if (isTextual(field.type)) return plainText(v) || \"Empty\";\n if (Array.isArray(v)) return `${v.length} ${v.length === 1 ? \"item\" : \"items\"}`;\n if (isObj(v)) return summarize(field.fields ?? [], v) || plainText(v) || \"Set\";\n if (typeof v === \"boolean\") return v ? \"On\" : \"Off\";\n return v == null || v === \"\" ? \"Empty\" : String(v);\n };\n const meta = (v: V) => {\n if (v.current) return `Now · ${v.by}`;\n if (v.at === undefined) return v.label;\n return `${relTime(v.at)}${v.by ? ` · ${v.by}` : \"\"}${v.label ? ` · ${v.label}` : \"\"}`;\n };\n return (\n <div className=\"flex flex-col gap-4\">\n <div>\n {seesDevSurfaces(env) ? <div className=\"text-kit-2xs font-medium text-kit-fg-3\">{apiName(form.schema.name, path)}</div> : null}\n <h2 className=\"text-kit-base font-semibold text-kit-fg\">History of {field.title.toLowerCase()}</h2>\n <p className=\"mt-1 text-kit-xs text-kit-fg-3\">Restoring lands in the draft and doesn't publish. Publish afterwards to go live.</p>\n </div>\n <ul className=\"overflow-hidden rounded-kit-lg border border-kit-line\">\n {versions.map((v, i) => (\n <li key={v.id} data-version={v.id} className=\"group/ver flex items-start gap-2.5 border-b border-kit-line-subtle px-3 py-2.5 last:border-b-0\">\n {v.by ? <Avatar name={v.by} size={22} /> : <span aria-hidden className=\"size-[22px] shrink-0 rounded-full bg-kit-muted\" />}\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-center gap-1.5 text-kit-sm\">\n <span className=\"font-medium text-kit-fg\">{v.current ? \"Current draft\" : `Version ${versions.length - i}`}</span>\n {v.id === \"pub\" ? <span className=\"rounded-kit-md bg-kit-success-soft px-1 text-kit-2xs text-kit-success-fg\">Published</span> : null}\n </div>\n <div className=\"text-kit-xs text-kit-fg-3\">{meta(v)}</div>\n <div className={cn(\"mt-1 line-clamp-2 rounded-kit-md bg-kit-subtle px-2 py-1 text-kit-xs text-kit-fg-2\", field.type === \"color\" && \"flex items-center gap-1.5\")}>\n {field.type === \"color\" && typeof v.value === \"string\" ? <span className=\"size-3 rounded-kit-md\" style={{ background: v.value }} /> : null}\n {show(v.value)}\n </div>\n </div>\n {v.current ? null : (\n <Button\n size=\"xs\"\n variant=\"secondary\"\n className=\"opacity-0 transition-opacity focus-visible:opacity-100 group-hover/ver:opacity-100 [@media(pointer:coarse)]:opacity-100\"\n leftIcon={<IconArrowBackUp stroke={1.5} />}\n onClick={() => {\n const prev = now;\n form.setAt(path, v.value, { label: \"Restored\" });\n form.navigate(parentOfField(path));\n toast?.(\"Restored as a draft\", { description: field.title, action: { label: \"Undo\", onClick: () => form.setAt(path, prev) }, duration: 10_000 });\n }}\n >\n Restore\n </Button>\n )}\n </li>\n ))}\n </ul>\n </div>\n );\n}\n/** Navigate back from a field's history to the frame that shows the field. */\nexport function parentOfField(path: FieldPath): FieldPath {\n // walk up to the nearest drillable frame boundary: an array index or the root\n for (let i = path.length - 1; i >= 0; i--) if (typeof path[i] === \"number\") return path.slice(0, i + 1);\n return path.length > 1 ? path.slice(0, -1) : [];\n}\n\n/* ── Stage: direction-aware slide, scroll memory, focus, keys (V2 schema-form) ───────────────── */\n/** The title shown as `parentTitle` for the current frame (the root crumb's label for depth 1). */\nexport function parentTitleOf(frames: Frame[], rootLabel: string): string | undefined {\n if (frames.length < 2) return undefined;\n return frames.length === 2 ? rootLabel : frames[frames.length - 2].title;\n}\n\n/** Floating layers (Base UI popups carry these roles); keys and focus coming from one belong to that layer. */\nconst LAYER = \"[role=dialog],[role=menu],[role=listbox]\";\n\n/** Slide direction for a frame change: deeper → 1, shallower → −1, a sibling step → by index. */\nexport function frameDirection(prev: { depth: number; index: number; key: string }, frames: Frame[], key: string): 0 | 1 | -1 {\n if (prev.key === key) return 0;\n const cur = frames[frames.length - 1];\n if (frames.length > prev.depth) return 1;\n if (frames.length < prev.depth) return -1;\n return (cur.item?.index ?? 0) >= prev.index ? 1 : -1;\n}\n\n/**\n * The drill-in stack's behaviour. `root` wraps the form (keys bubble to it), `scroller` is the scrolling element (or\n * null when the host scrolls). Returns the current frame, its key, the slide direction and the form's onKeyDown.\n */\nexport function useFrameNavigation({\n frames,\n navigate,\n root,\n scroller,\n}: {\n frames: Frame[];\n navigate: (path: FieldPath) => void;\n root: React.RefObject<HTMLElement | null>;\n scroller: React.RefObject<HTMLElement | null>;\n}) {\n const current = frames[frames.length - 1];\n const frameKey = frameKeyOf(current.path);\n const prev = React.useRef({ depth: frames.length, index: current.item?.index ?? 0, key: frameKey });\n const dir = frameDirection(prev.current, frames, frameKey);\n const dirRef = React.useRef<number>(1);\n if (dir) dirRef.current = dir;\n\n const scrollMem = React.useRef(new Map<string, number>());\n React.useLayoutEffect(() => {\n const was = prev.current.key;\n if (was === frameKey) return;\n if (scroller.current) scrollMem.current.set(was, scroller.current.scrollTop);\n prev.current = { depth: frames.length, index: current.item?.index ?? 0, key: frameKey };\n const el = scroller.current;\n if (el) el.scrollTop = scrollMem.current.get(frameKey) ?? 0;\n const active = document.activeElement;\n /* a move started from a portalled menu (FrameHeader ⋯ → Duplicate / Remove) leaves focus in that layer, outside root */\n const layer = active && active !== document.body ? active.closest(LAYER) : null;\n const fromLayer = !!layer && !layer.contains(root.current);\n if (root.current && (active === document.body || root.current.contains(active) || fromLayer)) {\n // the exiting frame is still mounted during its exit animation — focus the ENTERING one\n const target = root.current.querySelector<HTMLElement>(`[data-frame-body=\"${CSS.escape(frameKey)}\"]`);\n target?.focus({ preventScroll: true });\n }\n });\n\n const onKeyDown = (e: React.KeyboardEvent) => {\n if (e.defaultPrevented) return;\n const t = e.target as HTMLElement;\n // ignore keys from floating layers opened by this form; a form INSIDE a dialog still handles its own keys\n // (V2 also listed Radix's popper wrapper; Base UI popups carry these roles themselves)\n const layer = t.closest(LAYER);\n if (layer && root.current && !layer.contains(root.current)) return;\n if (e.key === \"Escape\" && frames.length > 1 && !t.isContentEditable) {\n e.preventDefault();\n e.stopPropagation();\n navigate(frames[frames.length - 2].path);\n return;\n }\n const it = current.item;\n if (it && (e.key === \"ArrowUp\" || e.key === \"ArrowDown\")) {\n const typing = t.matches(\"input,textarea,select\") || t.isContentEditable;\n if (e.altKey || (!typing && t.matches(\"[data-frame-body],[data-frame-header]\"))) {\n const n = it.index + (e.key === \"ArrowUp\" ? -1 : 1);\n if (n >= 0 && n < it.count) {\n e.preventDefault();\n navigate([...it.arrayPath, n]);\n }\n }\n }\n };\n\n return { current, frameKey, dir: dirRef.current, onKeyDown };\n}\n\nconst EASE: [number, number, number, number] = [0.22, 1, 0.36, 1];\n\n/**\n * The frame body with V2's slide: 24px along the travel direction + fade, 220ms, ease [0.22, 1, 0.36, 1]; reduced\n * motion keeps only the fade. `before` renders inside the root frame above its fields (the synced-from note).\n */\nexport function FrameStage({\n frames,\n frameKey,\n dir,\n rootLabel,\n variant,\n before,\n review,\n}: {\n frames: Frame[];\n frameKey: string;\n dir: number;\n rootLabel: string;\n variant: \"panel\" | \"document\";\n before?: React.ReactNode;\n /** D61 Review changes is on: the clip leaves 16px on the left for the change bars */\n review?: boolean;\n}) {\n const reduce = useReducedMotion();\n const current = frames[frames.length - 1];\n return (\n // the drill slide is clipped sideways; with Review changes on (D61) the clip leaves 16px on the left for the change bars\n <div className=\"relative\" style={review ? { clipPath: \"inset(-100vh 0 -100vh -16px)\" } : { overflowX: \"clip\" }}>\n <AnimatePresence mode=\"popLayout\" initial={false} custom={dir}>\n <motion.div\n key={frameKey}\n custom={dir}\n variants={{\n enter: (d: number) => ({ x: reduce ? 0 : d * 24, opacity: 0 }),\n center: { x: 0, opacity: 1 },\n exit: (d: number) => ({ x: reduce ? 0 : d * -24, opacity: 0 }),\n }}\n initial=\"enter\"\n animate=\"center\"\n exit=\"exit\"\n transition={{ duration: 0.22, ease: EASE }}\n data-frame-body={frameKey}\n tabIndex={-1}\n className={cn(\"outline-none focus-visible:shadow-none\", variant === \"document\" ? \"py-1\" : \"px-4 py-4\")}\n >\n {current.kind === \"root\" ? before : null}\n <FrameView frame={current} parentTitle={parentTitleOf(frames, rootLabel)} />\n </motion.div>\n </AnimatePresence>\n </div>\n );\n}\n\nexport { HISTORY_SEGMENT };\n"],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { FieldSchema } from "../schema/types";
|
|
2
2
|
/** "Top 56 · Bottom 88 · Sides M". Short values (numbers, scales, 1–4 letter options, on-switches) get their field's
|
|
3
|
-
* name in front so they mean something; text speaks for itself. Media, references and code are skipped
|
|
3
|
+
* name in front so they mean something; text speaks for itself. Media, references and code are skipped, unless
|
|
4
|
+
* nothing else is set: a group of set icons then reads as their names, never as "Nothing set yet". */
|
|
4
5
|
export declare function groupSummary(fields: FieldSchema[], value: unknown, max?: number): string;
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import { isObj } from "../lib/path.js";
|
|
2
2
|
import { isEmptyValue, isHidden, plainText } from "../lib/schema.js";
|
|
3
3
|
import { resolveScale } from "../schema/scale.js";
|
|
4
|
-
//#region src/
|
|
4
|
+
//#region src/engine/group-summary.ts
|
|
5
5
|
/**
|
|
6
6
|
* groupSummary (V2 HEAD 9829bf1 kit/engine/grouping.tsx): what a collapsed group holds, in one line. Lives on its own
|
|
7
7
|
* until the grouping lane ports grouping.tsx, which then re-exports it from there.
|
|
8
8
|
*/
|
|
9
9
|
/** "Top 56 · Bottom 88 · Sides M". Short values (numbers, scales, 1–4 letter options, on-switches) get their field's
|
|
10
|
-
* name in front so they mean something; text speaks for itself. Media, references and code are skipped
|
|
10
|
+
* name in front so they mean something; text speaks for itself. Media, references and code are skipped, unless
|
|
11
|
+
* nothing else is set: a group of set icons then reads as their names, never as "Nothing set yet". */
|
|
11
12
|
function groupSummary(fields, value, max = 3) {
|
|
12
13
|
if (!isObj(value)) return "";
|
|
13
14
|
const parts = [];
|
|
15
|
+
const media = [];
|
|
14
16
|
for (const f of fields) {
|
|
15
17
|
if (parts.length >= max) break;
|
|
16
18
|
if (isHidden(f, value)) continue;
|
|
@@ -20,6 +22,8 @@ function groupSummary(fields, value, max = 3) {
|
|
|
20
22
|
case "image":
|
|
21
23
|
case "file":
|
|
22
24
|
case "video":
|
|
25
|
+
media.push(f.title);
|
|
26
|
+
continue;
|
|
23
27
|
case "reference":
|
|
24
28
|
case "json":
|
|
25
29
|
case "code":
|
|
@@ -58,7 +62,7 @@ function groupSummary(fields, value, max = 3) {
|
|
|
58
62
|
}
|
|
59
63
|
}
|
|
60
64
|
}
|
|
61
|
-
return parts.join(" · ");
|
|
65
|
+
return (parts.length ? parts : media.slice(0, max)).join(" · ");
|
|
62
66
|
}
|
|
63
67
|
//#endregion
|
|
64
68
|
export { groupSummary };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"group-summary.js","names":[],"sources":["../../src/engine/group-summary.ts"],"sourcesContent":["/**\n * groupSummary (V2 HEAD 9829bf1 kit/engine/grouping.tsx): what a collapsed group holds, in one line. Lives on its own\n * until the grouping lane ports grouping.tsx, which then re-exports it from there.\n */\nimport { isHidden, isEmptyValue, plainText } from \"../lib/schema\";\nimport { isObj } from \"../lib/path\";\nimport { resolveScale } from \"../schema/scale\";\nimport type { FieldSchema } from \"../schema/types\";\n\n/** \"Top 56 · Bottom 88 · Sides M\". Short values (numbers, scales, 1–4 letter options, on-switches) get their field's\n * name in front so they mean something; text speaks for itself. Media, references and code are skipped, unless\n * nothing else is set: a group of set icons then reads as their names, never as \"Nothing set yet\". */\nexport function groupSummary(fields: FieldSchema[], value: unknown, max = 3): string {\n if (!isObj(value)) return \"\";\n const parts: string[] = [];\n const media: string[] = [];\n for (const f of fields) {\n if (parts.length >= max) break;\n if (isHidden(f, value)) continue;\n const x = value[f.name];\n if (isEmptyValue(x)) continue;\n switch (f.type) {\n case \"image\": case \"file\": case \"video\":\n media.push(f.title);\n continue;\n case \"reference\": case \"json\": case \"code\": case \"object\": case \"slot\": case \"geopoint\":\n continue;\n case \"boolean\":\n if (x === true) parts.push(f.title);\n continue;\n case \"number\": {\n const label = f.scale ? resolveScale(f.scale, x).label : `${x}${f.numeric?.unit ? ` ${f.numeric.unit}` : \"\"}`;\n parts.push(`${f.title} ${label}`);\n continue;\n }\n case \"rating\":\n parts.push(`${f.title} ${x} / 5`);\n continue;\n case \"select\": {\n const label = f.options?.find((o) => o.value === x)?.label ?? String(x);\n parts.push(label.length <= 4 ? `${f.title} ${label}` : label);\n continue;\n }\n case \"multiselect\": case \"tags\":\n if (Array.isArray(x)) parts.push(x.length <= 2 ? x.map((v) => f.options?.find((o) => o.value === v)?.label ?? String(v)).join(\", \") : `${x.length} ${f.title.toLowerCase()}`);\n continue;\n case \"array\":\n if (Array.isArray(x)) parts.push(`${x.length} ${f.title.toLowerCase()}`);\n continue;\n case \"color\":\n parts.push(`${f.title} ${String(x)}`);\n continue;\n default: {\n const t = plainText(x);\n if (t) parts.push(t.length > 32 ? `${t.slice(0, 30)}…` : t);\n }\n }\n }\n return (parts.length ? parts : media.slice(0, max)).join(\" · \");\n}\n"],"mappings":";;;;;;;;;;;AAYA,SAAgB,aAAa,QAAuB,OAAgB,MAAM,GAAW;CACnF,IAAI,CAAC,MAAM,KAAK,GAAG,OAAO;CAC1B,MAAM,QAAkB,CAAC;CACzB,MAAM,QAAkB,CAAC;CACzB,KAAK,MAAM,KAAK,QAAQ;EACtB,IAAI,MAAM,UAAU,KAAK;EACzB,IAAI,SAAS,GAAG,KAAK,GAAG;EACxB,MAAM,IAAI,MAAM,EAAE;EAClB,IAAI,aAAa,CAAC,GAAG;EACrB,QAAQ,EAAE,MAAV;GACE,KAAK;GAAS,KAAK;GAAQ,KAAK;IAC9B,MAAM,KAAK,EAAE,KAAK;IAClB;GACF,KAAK;GAAa,KAAK;GAAQ,KAAK;GAAQ,KAAK;GAAU,KAAK;GAAQ,KAAK,YAC3E;GACF,KAAK;IACH,IAAI,MAAM,MAAM,MAAM,KAAK,EAAE,KAAK;IAClC;GACF,KAAK,UAAU;IACb,MAAM,QAAQ,EAAE,QAAQ,aAAa,EAAE,OAAO,CAAC,CAAC,CAAC,QAAQ,GAAG,IAAI,EAAE,SAAS,OAAO,IAAI,EAAE,QAAQ,SAAS;IACzG,MAAM,KAAK,GAAG,EAAE,MAAM,GAAG,OAAO;IAChC;GACF;GACA,KAAK;IACH,MAAM,KAAK,GAAG,EAAE,MAAM,GAAG,EAAE,KAAK;IAChC;GACF,KAAK,UAAU;IACb,MAAM,QAAQ,EAAE,SAAS,MAAM,MAAM,EAAE,UAAU,CAAC,CAAC,EAAE,SAAS,OAAO,CAAC;IACtE,MAAM,KAAK,MAAM,UAAU,IAAI,GAAG,EAAE,MAAM,GAAG,UAAU,KAAK;IAC5D;GACF;GACA,KAAK;GAAe,KAAK;IACvB,IAAI,MAAM,QAAQ,CAAC,GAAG,MAAM,KAAK,EAAE,UAAU,IAAI,EAAE,KAAK,MAAM,EAAE,SAAS,MAAM,MAAM,EAAE,UAAU,CAAC,CAAC,EAAE,SAAS,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,GAAG,EAAE,OAAO,GAAG,EAAE,MAAM,YAAY,GAAG;IAC5K;GACF,KAAK;IACH,IAAI,MAAM,QAAQ,CAAC,GAAG,MAAM,KAAK,GAAG,EAAE,OAAO,GAAG,EAAE,MAAM,YAAY,GAAG;IACvE;GACF,KAAK;IACH,MAAM,KAAK,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG;IACpC;GACF,SAAS;IACP,MAAM,IAAI,UAAU,CAAC;IACrB,IAAI,GAAG,MAAM,KAAK,EAAE,SAAS,KAAK,GAAG,EAAE,MAAM,GAAG,EAAE,EAAE,KAAK,CAAC;GAC5D;EACF;CACF;CACA,QAAQ,MAAM,SAAS,QAAQ,MAAM,MAAM,GAAG,GAAG,EAAA,CAAG,KAAK,KAAK;AAChE"}
|
|
@@ -92,10 +92,24 @@ export declare function AnimatedFields({ fields, render, gapless, space }: {
|
|
|
92
92
|
* Sibling fields, laid out by the D63 rule: a plain animated stack, or (when `columns` and at least one pair of short
|
|
93
93
|
* neighbours) a grid that turns two-up only when the form is ≥ 420px wide. Used by sections, insets and array rows.
|
|
94
94
|
*/
|
|
95
|
-
export declare function FieldRun({ fields, render, columns }: {
|
|
95
|
+
export declare function FieldRun({ fields, render, columns, values }: {
|
|
96
96
|
fields: FieldSchema[];
|
|
97
97
|
render: (f: FieldSchema) => React.ReactNode;
|
|
98
98
|
columns?: boolean;
|
|
99
|
+
values?: Record<string, unknown>;
|
|
100
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
101
|
+
/**
|
|
102
|
+
* A header with eight social icons would otherwise stack eight rows between its texts. A lone icon is just its row:
|
|
103
|
+
* no heading for one. `isIconImage` is the same rule the image control draws the row by.
|
|
104
|
+
*/
|
|
105
|
+
export declare function splitIcons(fields: FieldSchema[], values: Record<string, unknown>): {
|
|
106
|
+
before: FieldSchema[];
|
|
107
|
+
icons: FieldSchema[];
|
|
108
|
+
after: FieldSchema[];
|
|
109
|
+
} | null;
|
|
110
|
+
export declare function IconGroup({ fields, render }: {
|
|
111
|
+
fields: FieldSchema[];
|
|
112
|
+
render: (f: FieldSchema) => React.ReactNode;
|
|
99
113
|
}): import("react/jsx-runtime").JSX.Element;
|
|
100
114
|
export interface FieldSectionProps {
|
|
101
115
|
title: string;
|
|
@@ -106,8 +120,8 @@ export interface FieldSectionProps {
|
|
|
106
120
|
/** controlled */
|
|
107
121
|
open?: boolean;
|
|
108
122
|
onOpenChange?: (open: boolean) => void;
|
|
109
|
-
/** one-line summary shown while collapsed ("Top 56 · Bottom 88") */
|
|
110
|
-
summary?:
|
|
123
|
+
/** one-line summary shown while collapsed ("Top 56 · Bottom 88"); a string list renders as neutral chips */
|
|
124
|
+
summary?: React.ReactNode;
|
|
111
125
|
/** roll-up shown on the header while collapsed */
|
|
112
126
|
status?: Partial<GroupStatus>;
|
|
113
127
|
/** hairline above (off for the first item of a frame) */
|
|
@@ -168,7 +182,7 @@ export declare function BreakpointGroup({ set, members, basePath, memoryKey, div
|
|
|
168
182
|
divider?: boolean;
|
|
169
183
|
renderField: RenderField;
|
|
170
184
|
}): import("react/jsx-runtime").JSX.Element;
|
|
171
|
-
type
|
|
185
|
+
type ArrangedItem = {
|
|
172
186
|
kind: "field";
|
|
173
187
|
field: FieldSchema;
|
|
174
188
|
} | {
|
|
@@ -177,7 +191,7 @@ type Item = {
|
|
|
177
191
|
fields: FieldSchema[];
|
|
178
192
|
};
|
|
179
193
|
/** Fields in schema order, with each fieldset (and the auto "Advanced" / "Screen sizes" sets) placed at its first member. */
|
|
180
|
-
export declare function arrangeFields(fields: FieldSchema[], fieldsets?: Fieldset[]):
|
|
194
|
+
export declare function arrangeFields(fields: FieldSchema[], fieldsets?: Fieldset[]): ArrangedItem[];
|
|
181
195
|
/** The group a field without `group` belongs to: the one marked `default`, else the first. */
|
|
182
196
|
export declare const defaultGroup: (groups?: FieldGroup[]) => FieldGroup | undefined;
|
|
183
197
|
/**
|