@bettercms-ai/kit 1.0.0 → 2.0.0-next.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +33 -0
- package/dist/adapters/dock-values.d.ts +28 -0
- package/dist/adapters/dock-values.js +41 -0
- package/dist/adapters/dock-values.js.map +1 -0
- package/{adapters → dist/adapters}/icons.js +2 -2
- package/dist/adapters/icons.js.map +1 -0
- package/{adapters → dist/adapters}/lossy.d.ts +94 -31
- package/dist/adapters/lossy.js +419 -0
- package/dist/adapters/lossy.js.map +1 -0
- package/{adapters → dist/adapters}/prod-types.d.ts +91 -26
- package/{adapters → dist/adapters}/prod-types.js +82 -13
- package/dist/adapters/prod-types.js.map +1 -0
- package/{adapters → dist/adapters}/schema.d.ts +40 -1
- package/{adapters → dist/adapters}/schema.js +1038 -204
- package/dist/adapters/schema.js.map +1 -0
- package/{adapters → dist/adapters}/values.d.ts +26 -5
- package/{adapters → dist/adapters}/values.js +87 -17
- package/dist/adapters/values.js.map +1 -0
- package/dist/brand/logo.js +96 -0
- package/dist/brand/logo.js.map +1 -0
- package/{context.d.ts → dist/context.d.ts} +131 -2
- package/{context.js → dist/context.js} +44 -2
- package/dist/context.js.map +1 -0
- package/{controls → dist/controls}/button.d.ts +19 -5
- package/{controls → dist/controls}/button.js +125 -54
- package/dist/controls/button.js.map +1 -0
- package/{controls → dist/controls}/c1.js +1 -1
- package/dist/controls/c1.js.map +1 -0
- package/{controls → dist/controls}/c2.js +1 -1
- package/dist/controls/c2.js.map +1 -0
- package/{controls → dist/controls}/choice.d.ts +7 -2
- package/{controls → dist/controls}/choice.js +71 -18
- package/dist/controls/choice.js.map +1 -0
- package/{controls → dist/controls}/code-register.js +1 -1
- package/dist/controls/code-register.js.map +1 -0
- package/{controls → dist/controls}/code.js +10 -9
- package/dist/controls/code.js.map +1 -0
- package/{controls → dist/controls}/color.js +8 -8
- package/dist/controls/color.js.map +1 -0
- package/{controls → dist/controls}/component-services.d.ts +42 -0
- package/dist/controls/component-services.js +7 -0
- package/dist/controls/component-services.js.map +1 -0
- package/{controls → dist/controls}/date-register.js +1 -1
- package/dist/controls/date-register.js.map +1 -0
- package/{controls → dist/controls}/date-zone.js +8 -2
- package/dist/controls/date-zone.js.map +1 -0
- package/{controls → dist/controls}/date.js +32 -24
- package/dist/controls/date.js.map +1 -0
- package/dist/controls/form-picker-register.d.ts +7 -0
- package/{controls → dist/controls}/form-picker-register.js +2 -6
- package/dist/controls/form-picker-register.js.map +1 -0
- package/{controls → dist/controls}/form-picker.js +11 -9
- package/dist/controls/form-picker.js.map +1 -0
- package/{controls → dist/controls}/icon-register.js +1 -1
- package/dist/controls/icon-register.js.map +1 -0
- package/{controls → dist/controls}/icon.d.ts +4 -2
- package/{controls → dist/controls}/icon.js +32 -27
- package/dist/controls/icon.js.map +1 -0
- package/{controls → dist/controls}/index.d.ts +1 -1
- package/{controls → dist/controls}/index.js +4 -3
- package/dist/controls/index.js.map +1 -0
- package/{controls → dist/controls}/json-register.js +1 -1
- package/dist/controls/json-register.js.map +1 -0
- package/{controls → dist/controls}/json.js +13 -3
- package/dist/controls/json.js.map +1 -0
- package/{controls → dist/controls}/link.js +116 -200
- package/dist/controls/link.js.map +1 -0
- package/{controls → dist/controls}/location-register.js +1 -1
- package/dist/controls/location-register.js.map +1 -0
- package/{controls → dist/controls}/location.js +59 -40
- package/dist/controls/location.js.map +1 -0
- package/{controls → dist/controls}/media-register.js +1 -1
- package/dist/controls/media-register.js.map +1 -0
- package/{controls → dist/controls}/media-services.d.ts +6 -0
- package/dist/controls/media-services.js +0 -0
- package/{controls → dist/controls}/media.d.ts +21 -4
- package/{controls → dist/controls}/media.js +407 -130
- package/dist/controls/media.js.map +1 -0
- package/{controls → dist/controls}/number.js +10 -9
- package/dist/controls/number.js.map +1 -0
- package/{controls → dist/controls}/reference-register.js +1 -1
- package/dist/controls/reference-register.js.map +1 -0
- package/{controls → dist/controls}/reference-services.d.ts +4 -0
- package/dist/controls/reference-services.js +0 -0
- package/{controls → dist/controls}/reference.d.ts +1 -1
- package/{controls → dist/controls}/reference.js +93 -77
- package/dist/controls/reference.js.map +1 -0
- package/dist/controls/rich-text/article-shell.d.ts +145 -0
- package/dist/controls/rich-text/article-shell.js +510 -0
- package/dist/controls/rich-text/article-shell.js.map +1 -0
- package/dist/controls/rich-text/author.d.ts +25 -0
- package/dist/controls/rich-text/author.js +104 -0
- package/dist/controls/rich-text/author.js.map +1 -0
- package/dist/controls/rich-text/blocks.d.ts +60 -0
- package/{controls → dist/controls}/rich-text/blocks.js +164 -389
- package/dist/controls/rich-text/blocks.js.map +1 -0
- package/dist/controls/rich-text/button.d.ts +23 -0
- package/dist/controls/rich-text/button.js +85 -0
- package/dist/controls/rich-text/button.js.map +1 -0
- package/{controls → dist/controls}/rich-text/catalog.d.ts +7 -4
- package/{controls → dist/controls}/rich-text/catalog.js +94 -68
- package/dist/controls/rich-text/catalog.js.map +1 -0
- package/dist/controls/rich-text/checklist.d.ts +24 -0
- package/dist/controls/rich-text/checklist.js +115 -0
- package/dist/controls/rich-text/checklist.js.map +1 -0
- package/{controls → dist/controls}/rich-text/codec.d.ts +9 -1
- package/{controls → dist/controls}/rich-text/codec.js +7 -2
- package/dist/controls/rich-text/codec.js.map +1 -0
- package/dist/controls/rich-text/columns.d.ts +41 -0
- package/dist/controls/rich-text/columns.js +181 -0
- package/dist/controls/rich-text/columns.js.map +1 -0
- package/{controls → dist/controls}/rich-text/component-card.d.ts +1 -1
- package/{controls → dist/controls}/rich-text/component-card.js +417 -99
- package/dist/controls/rich-text/component-card.js.map +1 -0
- package/dist/controls/rich-text/component-panel.d.ts +47 -0
- package/dist/controls/rich-text/component-panel.js +141 -0
- package/dist/controls/rich-text/component-panel.js.map +1 -0
- package/{controls → dist/controls}/rich-text/control.d.ts +1 -2
- package/{controls → dist/controls}/rich-text/control.js +84 -42
- package/dist/controls/rich-text/control.js.map +1 -0
- package/{controls → dist/controls}/rich-text/dom.d.ts +53 -9
- package/{controls → dist/controls}/rich-text/dom.js +388 -50
- package/dist/controls/rich-text/dom.js.map +1 -0
- package/{controls → dist/controls}/rich-text/editor.d.ts +7 -0
- package/{controls → dist/controls}/rich-text/editor.js +226 -44
- package/dist/controls/rich-text/editor.js.map +1 -0
- package/dist/controls/rich-text/embed.d.ts +28 -0
- package/dist/controls/rich-text/embed.js +210 -0
- package/dist/controls/rich-text/embed.js.map +1 -0
- package/{controls → dist/controls}/rich-text/floating.d.ts +6 -1
- package/{controls → dist/controls}/rich-text/floating.js +35 -18
- package/dist/controls/rich-text/floating.js.map +1 -0
- package/dist/controls/rich-text/footnote.d.ts +41 -0
- package/dist/controls/rich-text/footnote.js +185 -0
- package/dist/controls/rich-text/footnote.js.map +1 -0
- package/dist/controls/rich-text/gallery.d.ts +28 -0
- package/dist/controls/rich-text/gallery.js +167 -0
- package/dist/controls/rich-text/gallery.js.map +1 -0
- package/{controls → dist/controls}/rich-text/index.js +1 -1
- package/dist/controls/rich-text/index.js.map +1 -0
- package/{controls → dist/controls}/rich-text/link-form.d.ts +3 -1
- package/dist/controls/rich-text/link-form.js +147 -0
- package/dist/controls/rich-text/link-form.js.map +1 -0
- package/{controls → dist/controls}/rich-text/markdown.js +4 -2
- package/dist/controls/rich-text/markdown.js.map +1 -0
- package/{controls → dist/controls}/rich-text/ops.js +17 -15
- package/dist/controls/rich-text/ops.js.map +1 -0
- package/dist/controls/rich-text/plain.d.ts +17 -0
- package/dist/controls/rich-text/plain.js +44 -0
- package/dist/controls/rich-text/plain.js.map +1 -0
- package/dist/controls/rich-text/related.d.ts +36 -0
- package/dist/controls/rich-text/related.js +213 -0
- package/dist/controls/rich-text/related.js.map +1 -0
- package/dist/controls/rich-text/toc.d.ts +46 -0
- package/dist/controls/rich-text/toc.js +161 -0
- package/dist/controls/rich-text/toc.js.map +1 -0
- package/{controls → dist/controls}/rich-text/toolbar.d.ts +6 -2
- package/{controls → dist/controls}/rich-text/toolbar.js +12 -7
- package/dist/controls/rich-text/toolbar.js.map +1 -0
- package/{controls → dist/controls}/scale.js +5 -5
- package/dist/controls/scale.js.map +1 -0
- package/dist/controls/slot-register.d.ts +6 -0
- package/{controls → dist/controls}/slot-register.js +2 -5
- package/dist/controls/slot-register.js.map +1 -0
- package/{controls → dist/controls}/slot-services.d.ts +25 -0
- package/dist/controls/slot-services.js +155 -0
- package/dist/controls/slot-services.js.map +1 -0
- package/{controls → dist/controls}/slot.js +42 -24
- package/dist/controls/slot.js.map +1 -0
- package/{controls → dist/controls}/table/index.js +1 -1
- package/dist/controls/table/index.js.map +1 -0
- package/{controls → dist/controls}/table/prod.js +3 -3
- package/dist/controls/table/prod.js.map +1 -0
- package/{controls → dist/controls}/table/refs.js +13 -2
- package/dist/controls/table/refs.js.map +1 -0
- package/{controls → dist/controls}/table/stored.js +1 -1
- package/dist/controls/table/stored.js.map +1 -0
- package/{controls → dist/controls}/table/table-editor.js +51 -48
- package/dist/controls/table/table-editor.js.map +1 -0
- package/{controls → dist/controls}/table/table-link.js +3 -3
- package/dist/controls/table/table-link.js.map +1 -0
- package/{controls → dist/controls}/table/table.js +3 -3
- package/dist/controls/table/table.js.map +1 -0
- package/{controls → dist/controls}/text.d.ts +2 -2
- package/{controls → dist/controls}/text.js +78 -43
- package/dist/controls/text.js.map +1 -0
- package/dist/controls/unknown-value.d.ts +17 -0
- package/dist/controls/unknown-value.js +66 -0
- package/dist/controls/unknown-value.js.map +1 -0
- package/dist/core/core.d.ts +70 -0
- package/dist/core/core.js +187 -0
- package/dist/core/core.js.map +1 -0
- package/dist/core/facets.d.ts +355 -0
- package/dist/core/facets.js +342 -0
- package/dist/core/facets.js.map +1 -0
- package/dist/core/index.d.ts +3 -0
- package/dist/core/index.js +3 -0
- package/{engine → dist/engine}/array.js +34 -21
- package/dist/engine/array.js.map +1 -0
- package/{engine → dist/engine}/bits.js +1 -1
- package/dist/engine/bits.js.map +1 -0
- package/{engine → dist/engine}/breadcrumb.d.ts +3 -3
- package/{engine → dist/engine}/breadcrumb.js +12 -36
- package/dist/engine/breadcrumb.js.map +1 -0
- package/{engine → dist/engine}/expand.d.ts +2 -4
- package/{engine → dist/engine}/expand.js +5 -22
- package/dist/engine/expand.js.map +1 -0
- package/{engine → dist/engine}/field-list.js +1 -1
- package/dist/engine/field-list.js.map +1 -0
- package/{engine → dist/engine}/field-shell.js +249 -121
- package/dist/engine/field-shell.js.map +1 -0
- package/{engine → dist/engine}/frame.d.ts +3 -1
- package/{engine → dist/engine}/frame.js +16 -14
- package/dist/engine/frame.js.map +1 -0
- package/{engine → dist/engine}/group-summary.d.ts +2 -1
- package/{engine → dist/engine}/group-summary.js +7 -3
- package/dist/engine/group-summary.js.map +1 -0
- package/{engine → dist/engine}/grouping.d.ts +19 -5
- package/{engine → dist/engine}/grouping.js +193 -21
- package/dist/engine/grouping.js.map +1 -0
- package/{engine → dist/engine}/item-list.d.ts +11 -1
- package/{engine → dist/engine}/item-list.js +35 -13
- package/dist/engine/item-list.js.map +1 -0
- package/{engine → dist/engine}/kit-field.js +45 -10
- package/dist/engine/kit-field.js.map +1 -0
- package/{engine → dist/engine}/schema-form.d.ts +27 -2
- package/{engine → dist/engine}/schema-form.js +182 -40
- package/dist/engine/schema-form.js.map +1 -0
- package/{engine → dist/engine}/slot.js +5 -15
- package/dist/engine/slot.js.map +1 -0
- package/dist/index.js +58 -0
- package/dist/index.js.map +1 -0
- package/{kit.css → dist/kit.css} +19 -0
- package/{lib → dist/lib}/cn.js +7 -4
- package/dist/lib/cn.js.map +1 -0
- package/{lib → dist/lib}/columns.js +4 -1
- package/dist/lib/columns.js.map +1 -0
- package/{lib → dist/lib}/frames.js +2 -2
- package/dist/lib/frames.js.map +1 -0
- package/dist/lib/icon-image.d.ts +10 -0
- package/dist/lib/icon-image.js +8 -0
- package/dist/lib/icon-image.js.map +1 -0
- package/{lib → dist/lib}/icons.js +4 -3
- package/dist/lib/icons.js.map +1 -0
- package/dist/lib/input-modality.d.ts +11 -0
- package/dist/lib/input-modality.js +47 -0
- package/dist/lib/input-modality.js.map +1 -0
- package/dist/lib/key-event.d.ts +11 -0
- package/dist/lib/key-event.js +16 -0
- package/dist/lib/key-event.js.map +1 -0
- package/{lib → dist/lib}/path.js +4 -2
- package/dist/lib/path.js.map +1 -0
- package/{lib → dist/lib}/schema.d.ts +34 -3
- package/{lib → dist/lib}/schema.js +110 -13
- package/dist/lib/schema.js.map +1 -0
- package/{lib → dist/lib}/utils.js +1 -1
- package/dist/lib/utils.js.map +1 -0
- package/{lib → dist/lib}/validate.d.ts +11 -1
- package/{lib → dist/lib}/validate.js +85 -11
- package/dist/lib/validate.js.map +1 -0
- package/dist/library/analysis.d.ts +23 -0
- package/dist/library/analysis.js +160 -0
- package/dist/library/analysis.js.map +1 -0
- package/dist/library/catalog.d.ts +57 -0
- package/dist/library/catalog.js +307 -0
- package/dist/library/catalog.js.map +1 -0
- package/dist/library/coreNotes.d.ts +8 -0
- package/dist/library/coreNotes.js +111 -0
- package/dist/library/coreNotes.js.map +1 -0
- package/dist/library/coverage.d.ts +40 -0
- package/dist/library/coverage.js +59 -0
- package/dist/library/coverage.js.map +1 -0
- package/dist/library/entries/advanced.entries.d.ts +2 -0
- package/dist/library/entries/advanced.entries.js +6579 -0
- package/dist/library/entries/advanced.entries.js.map +1 -0
- package/dist/library/entries/commerce.entries.d.ts +2 -0
- package/dist/library/entries/commerce.entries.js +4140 -0
- package/dist/library/entries/commerce.entries.js.map +1 -0
- package/dist/library/entries/company.entries.d.ts +2 -0
- package/dist/library/entries/company.entries.js +2731 -0
- package/dist/library/entries/company.entries.js.map +1 -0
- package/dist/library/entries/conversion.entries.d.ts +2 -0
- package/dist/library/entries/conversion.entries.js +3707 -0
- package/dist/library/entries/conversion.entries.js.map +1 -0
- package/dist/library/entries/data.entries.d.ts +7 -0
- package/dist/library/entries/data.entries.js +4613 -0
- package/dist/library/entries/data.entries.js.map +1 -0
- package/dist/library/entries/events.entries.d.ts +2 -0
- package/dist/library/entries/events.entries.js +3428 -0
- package/dist/library/entries/events.entries.js.map +1 -0
- package/dist/library/entries/features.entries.d.ts +2 -0
- package/dist/library/entries/features.entries.js +3157 -0
- package/dist/library/entries/features.entries.js.map +1 -0
- package/dist/library/entries/heroes.entries.d.ts +2 -0
- package/dist/library/entries/heroes.entries.js +3401 -0
- package/dist/library/entries/heroes.entries.js.map +1 -0
- package/dist/library/entries/index.d.ts +3 -0
- package/dist/library/entries/index.js +35 -0
- package/dist/library/entries/index.js.map +1 -0
- package/dist/library/entries/listings.entries.d.ts +2 -0
- package/dist/library/entries/listings.entries.js +2976 -0
- package/dist/library/entries/listings.entries.js.map +1 -0
- package/dist/library/entries/longform.entries.d.ts +2 -0
- package/dist/library/entries/longform.entries.js +4227 -0
- package/dist/library/entries/longform.entries.js.map +1 -0
- package/dist/library/entries/media.entries.d.ts +2 -0
- package/dist/library/entries/media.entries.js +2781 -0
- package/dist/library/entries/media.entries.js.map +1 -0
- package/dist/library/entries/navigation.entries.d.ts +2 -0
- package/dist/library/entries/navigation.entries.js +4011 -0
- package/dist/library/entries/navigation.entries.js.map +1 -0
- package/dist/library/entries/pricing.entries.d.ts +2 -0
- package/dist/library/entries/pricing.entries.js +2383 -0
- package/dist/library/entries/pricing.entries.js.map +1 -0
- package/dist/library/entries/social-proof.entries.d.ts +2 -0
- package/dist/library/entries/social-proof.entries.js +2297 -0
- package/dist/library/entries/social-proof.entries.js.map +1 -0
- package/dist/library/examples/bento.d.ts +92 -0
- package/dist/library/examples/bento.js +201 -0
- package/dist/library/examples/bento.js.map +1 -0
- package/dist/library/examples/blocks.d.ts +14 -0
- package/dist/library/examples/blocks.js +313 -0
- package/dist/library/examples/blocks.js.map +1 -0
- package/dist/library/examples/faq.d.ts +28 -0
- package/dist/library/examples/faq.js +230 -0
- package/dist/library/examples/faq.js.map +1 -0
- package/dist/library/examples/hero.d.ts +43 -0
- package/dist/library/examples/hero.js +222 -0
- package/dist/library/examples/hero.js.map +1 -0
- package/dist/library/examples/index.d.ts +36 -0
- package/dist/library/examples/index.js +109 -0
- package/dist/library/examples/index.js.map +1 -0
- package/dist/library/examples/journalStory.d.ts +93 -0
- package/dist/library/examples/journalStory.js +338 -0
- package/dist/library/examples/journalStory.js.map +1 -0
- package/dist/library/examples/megaMenu.d.ts +134 -0
- package/dist/library/examples/megaMenu.js +442 -0
- package/dist/library/examples/megaMenu.js.map +1 -0
- package/dist/library/examples/pricing.d.ts +103 -0
- package/dist/library/examples/pricing.js +479 -0
- package/dist/library/examples/pricing.js.map +1 -0
- package/dist/library/examples/tabs.d.ts +87 -0
- package/dist/library/examples/tabs.js +180 -0
- package/dist/library/examples/tabs.js.map +1 -0
- package/dist/library/export.d.ts +42 -0
- package/dist/library/export.js +80 -0
- package/dist/library/export.js.map +1 -0
- package/dist/library/index.d.ts +13 -0
- package/dist/library/index.js +6 -0
- package/dist/library/kit-catalog.json +1511 -0
- package/dist/library/types.d.ts +42 -0
- package/dist/library/types.js +0 -0
- package/{schema → dist/schema}/adapters.js +1 -2
- package/dist/schema/adapters.js.map +1 -0
- package/{schema → dist/schema}/help.d.ts +2 -0
- package/{schema → dist/schema}/help.js +6 -4
- package/dist/schema/help.js.map +1 -0
- package/{schema → dist/schema}/scale.js +1 -1
- package/dist/schema/scale.js.map +1 -0
- package/{schema → dist/schema}/sources.js +1 -1
- package/dist/schema/sources.js.map +1 -0
- package/{schema → dist/schema}/table.js +11 -10
- package/dist/schema/table.js.map +1 -0
- package/{schema → dist/schema}/types.d.ts +36 -1
- package/{schema → dist/schema}/types.js +1 -1
- package/dist/schema/types.js.map +1 -0
- package/dist/styles.css +2 -0
- package/dist/table/table-view.d.ts +14 -0
- package/dist/table/table-view.js +140 -0
- package/dist/table/table-view.js.map +1 -0
- package/dist/table/table.css +73 -0
- package/dist/testing/corpus.d.ts +63 -0
- package/dist/testing/corpus.js +129 -0
- package/dist/testing/corpus.js.map +1 -0
- package/dist/testing/test-form.d.ts +11 -0
- package/dist/testing/test-form.js +38 -0
- package/dist/testing/test-form.js.map +1 -0
- package/dist/theme.css +345 -0
- package/dist/theme.d.ts +22 -0
- package/dist/theme.js +43 -0
- package/dist/theme.js.map +1 -0
- package/dist/tokens.css +542 -0
- package/dist/types.js +0 -0
- package/{ui → dist/ui}/action-tray.d.ts +1 -1
- package/{ui → dist/ui}/action-tray.js +20 -19
- package/dist/ui/action-tray.js.map +1 -0
- package/dist/ui/autocomplete.d.ts +58 -0
- package/dist/ui/autocomplete.js +194 -0
- package/dist/ui/autocomplete.js.map +1 -0
- package/{ui → dist/ui}/button.d.ts +3 -3
- package/{ui → dist/ui}/button.js +8 -11
- package/dist/ui/button.js.map +1 -0
- package/{ui → dist/ui}/choice-switch.js +1 -1
- package/dist/ui/choice-switch.js.map +1 -0
- package/{ui → dist/ui}/controls.js +51 -39
- package/dist/ui/controls.js.map +1 -0
- package/{ui → dist/ui}/display.d.ts +10 -3
- package/{ui → dist/ui}/display.js +57 -46
- package/dist/ui/display.js.map +1 -0
- package/{ui → dist/ui}/expanded-editor-modal.d.ts +2 -2
- package/{ui → dist/ui}/expanded-editor-modal.js +6 -6
- package/dist/ui/expanded-editor-modal.js.map +1 -0
- package/{ui → dist/ui}/field-context.js +1 -1
- package/dist/ui/field-context.js.map +1 -0
- package/{ui → dist/ui}/floating-panel.d.ts +1 -1
- package/{ui → dist/ui}/floating-panel.js +28 -12
- package/dist/ui/floating-panel.js.map +1 -0
- package/{ui → dist/ui}/index.d.ts +4 -0
- package/dist/ui/index.js +18 -0
- package/{ui → dist/ui}/input.d.ts +1 -1
- package/{ui → dist/ui}/input.js +9 -9
- package/dist/ui/input.js.map +1 -0
- package/{ui → dist/ui}/mode-bar.js +3 -3
- package/dist/ui/mode-bar.js.map +1 -0
- package/{ui → dist/ui}/overlay.d.ts +77 -5
- package/dist/ui/overlay.js +697 -0
- package/dist/ui/overlay.js.map +1 -0
- package/{ui → dist/ui}/path-crumbs.js +37 -3
- package/dist/ui/path-crumbs.js.map +1 -0
- package/{ui → dist/ui}/presence.js +2 -2
- package/dist/ui/presence.js.map +1 -0
- package/{ui → dist/ui}/select.js +89 -87
- package/dist/ui/select.js.map +1 -0
- package/{ui → dist/ui}/shortcut-hint.js +1 -1
- package/dist/ui/shortcut-hint.js.map +1 -0
- package/dist/ui/spinner.d.ts +24 -0
- package/dist/ui/spinner.js +42 -0
- package/dist/ui/spinner.js.map +1 -0
- package/dist/ui/split-button.d.ts +32 -0
- package/dist/ui/split-button.js +60 -0
- package/dist/ui/split-button.js.map +1 -0
- package/{ui → dist/ui}/surfaces.js +1 -1
- package/dist/ui/surfaces.js.map +1 -0
- package/dist/ui/tab.d.ts +38 -0
- package/dist/ui/tab.js +87 -0
- package/dist/ui/tab.js.map +1 -0
- package/dist/ui/toast.d.ts +20 -0
- package/dist/ui/toast.js +115 -0
- package/dist/ui/toast.js.map +1 -0
- package/{ui → dist/ui}/tooltip-root.d.ts +4 -3
- package/{ui → dist/ui}/tooltip-root.js +9 -8
- package/dist/ui/tooltip-root.js.map +1 -0
- package/{ui → dist/ui}/variants.js +1 -1
- package/dist/ui/variants.js.map +1 -0
- package/package.json +83 -23
- package/adapters/icons.js.map +0 -1
- package/adapters/lossy.js +0 -233
- package/adapters/lossy.js.map +0 -1
- package/adapters/prod-types.js.map +0 -1
- package/adapters/schema.js.map +0 -1
- package/adapters/values.js.map +0 -1
- package/brand/logo.js +0 -9
- package/brand/logo.js.map +0 -1
- package/context.js.map +0 -1
- package/controls/button.js.map +0 -1
- package/controls/c1.js.map +0 -1
- package/controls/c2.js.map +0 -1
- package/controls/choice.js.map +0 -1
- package/controls/code-register.js.map +0 -1
- package/controls/code.js.map +0 -1
- package/controls/color.js.map +0 -1
- package/controls/date-register.js.map +0 -1
- package/controls/date-zone.js.map +0 -1
- package/controls/date.js.map +0 -1
- package/controls/form-picker-register.d.ts +0 -1
- package/controls/form-picker-register.js.map +0 -1
- package/controls/form-picker.js.map +0 -1
- package/controls/icon-register.js.map +0 -1
- package/controls/icon.js.map +0 -1
- package/controls/index.js.map +0 -1
- package/controls/json-register.js.map +0 -1
- package/controls/json.js.map +0 -1
- package/controls/link.js.map +0 -1
- package/controls/location-register.js.map +0 -1
- package/controls/location.js.map +0 -1
- package/controls/media-register.js.map +0 -1
- package/controls/media.js.map +0 -1
- package/controls/number.js.map +0 -1
- package/controls/reference-register.js.map +0 -1
- package/controls/reference.js.map +0 -1
- package/controls/rich-text/blocks.d.ts +0 -28
- package/controls/rich-text/blocks.js.map +0 -1
- package/controls/rich-text/catalog.js.map +0 -1
- package/controls/rich-text/codec.js.map +0 -1
- package/controls/rich-text/component-card.js.map +0 -1
- package/controls/rich-text/control.js.map +0 -1
- package/controls/rich-text/dom.js.map +0 -1
- package/controls/rich-text/editor.js.map +0 -1
- package/controls/rich-text/floating.js.map +0 -1
- package/controls/rich-text/index.js.map +0 -1
- package/controls/rich-text/link-form.js +0 -111
- package/controls/rich-text/link-form.js.map +0 -1
- package/controls/rich-text/markdown.js.map +0 -1
- package/controls/rich-text/ops.js.map +0 -1
- package/controls/rich-text/toolbar.js.map +0 -1
- package/controls/scale.js.map +0 -1
- package/controls/slot-register.d.ts +0 -1
- package/controls/slot-register.js.map +0 -1
- package/controls/slot-services.js +0 -38
- package/controls/slot-services.js.map +0 -1
- package/controls/slot.js.map +0 -1
- package/controls/table/index.js.map +0 -1
- package/controls/table/prod.js.map +0 -1
- package/controls/table/refs.js.map +0 -1
- package/controls/table/stored.js.map +0 -1
- package/controls/table/table-editor.js.map +0 -1
- package/controls/table/table-link.js.map +0 -1
- package/controls/table/table.js.map +0 -1
- package/controls/text.js.map +0 -1
- package/engine/array.js.map +0 -1
- package/engine/bits.js.map +0 -1
- package/engine/breadcrumb.js.map +0 -1
- package/engine/expand.js.map +0 -1
- package/engine/field-list.js.map +0 -1
- package/engine/field-shell.js.map +0 -1
- package/engine/frame.js.map +0 -1
- package/engine/group-summary.js.map +0 -1
- package/engine/grouping.js.map +0 -1
- package/engine/item-list.js.map +0 -1
- package/engine/kit-field.js.map +0 -1
- package/engine/schema-form.js.map +0 -1
- package/engine/slot.js.map +0 -1
- package/index.js +0 -55
- package/index.js.map +0 -1
- package/lib/cn.js.map +0 -1
- package/lib/columns.js.map +0 -1
- package/lib/frames.js.map +0 -1
- package/lib/icons.js.map +0 -1
- package/lib/path.js.map +0 -1
- package/lib/schema.js.map +0 -1
- package/lib/utils.js.map +0 -1
- package/lib/validate.js.map +0 -1
- package/schema/adapters.js.map +0 -1
- package/schema/help.js.map +0 -1
- package/schema/scale.js.map +0 -1
- package/schema/sources.js.map +0 -1
- package/schema/table.js.map +0 -1
- package/schema/types.js.map +0 -1
- package/ui/action-tray.js.map +0 -1
- package/ui/button.js.map +0 -1
- package/ui/choice-switch.js.map +0 -1
- package/ui/controls.js.map +0 -1
- package/ui/display.js.map +0 -1
- package/ui/expanded-editor-modal.js.map +0 -1
- package/ui/field-context.js.map +0 -1
- package/ui/floating-panel.js.map +0 -1
- package/ui/index.js +0 -13
- package/ui/input.js.map +0 -1
- package/ui/mode-bar.js.map +0 -1
- package/ui/overlay.js +0 -378
- package/ui/overlay.js.map +0 -1
- package/ui/path-crumbs.js.map +0 -1
- package/ui/presence.js.map +0 -1
- package/ui/select.js.map +0 -1
- package/ui/shortcut-hint.js.map +0 -1
- package/ui/surfaces.js.map +0 -1
- package/ui/tooltip-root.js.map +0 -1
- package/ui/variants.js.map +0 -1
- /package/{_virtual → dist/_virtual}/_rolldown/runtime.js +0 -0
- /package/{adapters → dist/adapters}/icons.d.ts +0 -0
- /package/{brand → dist/brand}/logo.d.ts +0 -0
- /package/{controls → dist/controls}/c1.d.ts +0 -0
- /package/{controls → dist/controls}/c2.d.ts +0 -0
- /package/{controls → dist/controls}/code-register.d.ts +0 -0
- /package/{controls → dist/controls}/code.d.ts +0 -0
- /package/{controls → dist/controls}/color.d.ts +0 -0
- /package/{controls → dist/controls}/date-register.d.ts +0 -0
- /package/{controls → dist/controls}/date-zone.d.ts +0 -0
- /package/{controls → dist/controls}/date.d.ts +0 -0
- /package/{controls → dist/controls}/form-picker.d.ts +0 -0
- /package/{controls → dist/controls}/icon-register.d.ts +0 -0
- /package/{controls → dist/controls}/json-register.d.ts +0 -0
- /package/{controls → dist/controls}/json.d.ts +0 -0
- /package/{controls → dist/controls}/link.d.ts +0 -0
- /package/{controls → dist/controls}/location-register.d.ts +0 -0
- /package/{controls → dist/controls}/location.d.ts +0 -0
- /package/{controls → dist/controls}/media-register.d.ts +0 -0
- /package/{controls → dist/controls}/number.d.ts +0 -0
- /package/{controls → dist/controls}/reference-register.d.ts +0 -0
- /package/{controls → dist/controls}/rich-text/index.d.ts +0 -0
- /package/{controls → dist/controls}/rich-text/markdown.d.ts +0 -0
- /package/{controls → dist/controls}/rich-text/ops.d.ts +0 -0
- /package/{controls → dist/controls}/scale.d.ts +0 -0
- /package/{controls → dist/controls}/slot.d.ts +0 -0
- /package/{controls → dist/controls}/table/index.d.ts +0 -0
- /package/{controls → dist/controls}/table/prod.d.ts +0 -0
- /package/{controls → dist/controls}/table/refs.d.ts +0 -0
- /package/{controls → dist/controls}/table/stored.d.ts +0 -0
- /package/{controls → dist/controls}/table/table-editor.d.ts +0 -0
- /package/{controls → dist/controls}/table/table-link.d.ts +0 -0
- /package/{controls → dist/controls}/table/table.d.ts +0 -0
- /package/{engine → dist/engine}/array.d.ts +0 -0
- /package/{engine → dist/engine}/bits.d.ts +0 -0
- /package/{engine → dist/engine}/field-list.d.ts +0 -0
- /package/{engine → dist/engine}/field-shell.d.ts +0 -0
- /package/{engine → dist/engine}/kit-field.d.ts +0 -0
- /package/{engine → dist/engine}/slot.d.ts +0 -0
- /package/{index.d.ts → dist/index.d.ts} +0 -0
- /package/{lib → dist/lib}/cn.d.ts +0 -0
- /package/{lib → dist/lib}/columns.d.ts +0 -0
- /package/{lib → dist/lib}/frames.d.ts +0 -0
- /package/{lib → dist/lib}/icons.d.ts +0 -0
- /package/{lib → dist/lib}/path.d.ts +0 -0
- /package/{lib → dist/lib}/utils.d.ts +0 -0
- /package/{schema → dist/schema}/adapters.d.ts +0 -0
- /package/{schema → dist/schema}/scale.d.ts +0 -0
- /package/{schema → dist/schema}/sources.d.ts +0 -0
- /package/{schema → dist/schema}/table.d.ts +0 -0
- /package/{types.d.ts → dist/types.d.ts} +0 -0
- /package/{ui → dist/ui}/choice-switch.d.ts +0 -0
- /package/{ui → dist/ui}/controls.d.ts +0 -0
- /package/{ui → dist/ui}/field-context.d.ts +0 -0
- /package/{ui → dist/ui}/mode-bar.d.ts +0 -0
- /package/{ui → dist/ui}/path-crumbs.d.ts +0 -0
- /package/{ui → dist/ui}/presence.d.ts +0 -0
- /package/{ui → dist/ui}/select.d.ts +0 -0
- /package/{ui → dist/ui}/shortcut-hint.d.ts +0 -0
- /package/{ui → dist/ui}/surfaces.d.ts +0 -0
- /package/{ui → dist/ui}/variants.d.ts +0 -0
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { Sparkle } from "../../ui/button.js";
|
|
2
2
|
import { Menu, MenuContent, MenuItem, MenuTrigger } from "../../ui/overlay.js";
|
|
3
3
|
import { StyleMenu, ToolButton, stylesFor } from "./toolbar.js";
|
|
4
|
-
import
|
|
4
|
+
import * as React from "react";
|
|
5
5
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
-
import {
|
|
6
|
+
import { IconBold, IconCode, IconItalic, IconLink, IconMessage, IconStrikethrough, IconSubscript, IconSuperscript, IconUnderline } from "@tabler/icons-react";
|
|
7
7
|
import { createPortal } from "react-dom";
|
|
8
|
-
//#region src/
|
|
8
|
+
//#region src/controls/rich-text/floating.tsx
|
|
9
9
|
/**
|
|
10
10
|
* RICH TEXT · the selection bubble: AI rewrite, style, marks, link (V2 HEAD controls/rich-text/floating.tsx).
|
|
11
11
|
* V2's inline "Ask AI" prompt took free text; the host's AI service rewrites by preset only, so it is not drawn.
|
|
@@ -33,26 +33,28 @@ function SelectionBubble({ rect, fmt, allows, saveSel, onAi, onStyle, onMark, on
|
|
|
33
33
|
const above = rect.top - 44;
|
|
34
34
|
const top = above < 8 || !!avoid && above < avoid.bottom + 4 && above + 36 > avoid.top ? rect.bottom + 8 : above;
|
|
35
35
|
const styles = stylesFor(allows);
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
36
|
+
const ref = React.useRef(null);
|
|
37
|
+
const [w, setW] = React.useState(460);
|
|
38
|
+
React.useLayoutEffect(() => {
|
|
39
|
+
if (ref.current) setW(ref.current.offsetWidth);
|
|
40
|
+
}, [
|
|
41
|
+
fmt.block,
|
|
42
|
+
!!onAi,
|
|
43
|
+
!!onComment
|
|
44
|
+
]);
|
|
45
|
+
return createPortal(/* @__PURE__ */ jsxs("div", {
|
|
46
46
|
onMouseDown: (e) => {
|
|
47
47
|
if (!e.target.closest("button")) e.preventDefault();
|
|
48
48
|
},
|
|
49
|
+
ref,
|
|
49
50
|
style: {
|
|
50
51
|
top,
|
|
51
|
-
|
|
52
|
+
boxShadow: "var(--kit-shadow-sm)",
|
|
53
|
+
left: Math.min(window.innerWidth - w - 8, Math.max(8, rect.left + rect.width / 2 - w / 2))
|
|
52
54
|
},
|
|
53
55
|
"data-floating-layer": "",
|
|
54
56
|
"data-kit-scope": "",
|
|
55
|
-
className: "pointer-events-auto fixed z-[
|
|
57
|
+
className: "glass-strong pointer-events-auto fixed z-[calc(var(--kit-z-popover,84)_+_1)] flex h-9 items-center gap-0.5 rounded-kit-lg border border-kit-line px-1",
|
|
56
58
|
role: "toolbar",
|
|
57
59
|
"aria-label": "Selection formatting",
|
|
58
60
|
children: [
|
|
@@ -110,6 +112,18 @@ function SelectionBubble({ rect, fmt, allows, saveSel, onAi, onStyle, onMark, on
|
|
|
110
112
|
active: fmt.strike,
|
|
111
113
|
onClick: () => onMark("strikeThrough")
|
|
112
114
|
}) : null,
|
|
115
|
+
allows("sup") ? /* @__PURE__ */ jsx(ToolButton, {
|
|
116
|
+
label: "Superscript",
|
|
117
|
+
icon: /* @__PURE__ */ jsx(IconSuperscript, { stroke: 1.5 }),
|
|
118
|
+
active: fmt.sup,
|
|
119
|
+
onClick: () => onMark("superscript")
|
|
120
|
+
}) : null,
|
|
121
|
+
allows("sub") ? /* @__PURE__ */ jsx(ToolButton, {
|
|
122
|
+
label: "Subscript",
|
|
123
|
+
icon: /* @__PURE__ */ jsx(IconSubscript, { stroke: 1.5 }),
|
|
124
|
+
active: fmt.sub,
|
|
125
|
+
onClick: () => onMark("subscript")
|
|
126
|
+
}) : null,
|
|
113
127
|
allows("code") ? /* @__PURE__ */ jsx(ToolButton, {
|
|
114
128
|
label: "Inline code",
|
|
115
129
|
icon: /* @__PURE__ */ jsx(IconCode, { stroke: 1.5 }),
|
|
@@ -123,15 +137,18 @@ function SelectionBubble({ rect, fmt, allows, saveSel, onAi, onStyle, onMark, on
|
|
|
123
137
|
active: fmt.onLink,
|
|
124
138
|
onClick: onLink
|
|
125
139
|
}) : null,
|
|
126
|
-
onComment ? /* @__PURE__ */ jsx(
|
|
140
|
+
onComment ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", {
|
|
141
|
+
"aria-hidden": true,
|
|
142
|
+
className: "mx-0.5 h-4 w-px bg-kit-line"
|
|
143
|
+
}), /* @__PURE__ */ jsx(ToolButton, {
|
|
127
144
|
label: "Comment",
|
|
128
145
|
icon: /* @__PURE__ */ jsx(IconMessage, { stroke: 1.5 }),
|
|
129
146
|
onClick: onComment
|
|
130
|
-
}) : null
|
|
147
|
+
})] }) : null
|
|
131
148
|
]
|
|
132
149
|
}), document.body);
|
|
133
150
|
}
|
|
134
151
|
//#endregion
|
|
135
|
-
export { SelectionBubble };
|
|
152
|
+
export { BUBBLE_AI, SelectionBubble };
|
|
136
153
|
|
|
137
154
|
//# sourceMappingURL=floating.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"floating.js","names":[],"sources":["../../../src/controls/rich-text/floating.tsx"],"sourcesContent":["/**\n * RICH TEXT · the selection bubble: AI rewrite, style, marks, link (V2 HEAD controls/rich-text/floating.tsx).\n * V2's inline \"Ask AI\" prompt took free text; the host's AI service rewrites by preset only, so it is not drawn.\n */\nimport * as React from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { IconBold, IconCode, IconItalic, IconLink, IconMessage, IconStrikethrough, IconSubscript, IconSuperscript, IconUnderline } from \"@tabler/icons-react\";\nimport { Sparkle } from \"../../ui/button\";\nimport { Menu, MenuContent, MenuItem, MenuTrigger } from \"../../ui/overlay\";\nimport type { AiPreset } from \"../../context\";\nimport type { RichTextFeature } from \"./codec\";\nimport { StyleMenu, ToolButton, stylesFor, type Fmt, type MarkCmd } from \"./toolbar\";\n\n/** The bubble's rewrite directions (V2: improve, shorter, punchier, grammar), as the host service's presets. */\nexport const BUBBLE_AI: { id: AiPreset; label: string }[] = [\n { id: \"improve\", label: \"Improve writing\" },\n { id: \"shorter\", label: \"Make shorter\" },\n { id: \"simplify\", label: \"Simplify\" },\n { id: \"grammar\", label: \"Fix spelling and grammar\" },\n];\n\nexport function SelectionBubble({\n rect,\n fmt,\n allows,\n saveSel,\n onAi,\n onStyle,\n onMark,\n onInlineCode,\n onLink,\n onComment,\n avoid,\n}: {\n rect: DOMRect;\n /** The editor's own toolbar row (when it is open): the bubble never sits on top of it. */\n avoid?: DOMRect | null;\n fmt: Fmt;\n allows: (f: RichTextFeature) => boolean;\n saveSel: () => void;\n /** Absent when the person has no AI (D58: ai.use) or the host has no AI service: the AI menu and its divider are not drawn. */\n onAi?: (preset: AiPreset) => void;\n onStyle: (tag: string) => void;\n onMark: (cmd: MarkCmd) => void;\n onInlineCode: () => void;\n onLink: () => void;\n onComment?: () => void;\n}) {\n // Above the selection by default; flips below it when above would cover the editor's toolbar or leave the viewport.\n const above = rect.top - 44;\n const blocked = above < 8 || (!!avoid && above < avoid.bottom + 4 && above + 36 > avoid.top);\n const top = blocked ? rect.bottom + 8 : above;\n const styles = stylesFor(allows);\n // centre on the selection with the bubble's real width (it grows with AI, style and comment), never past either edge\n const ref = React.useRef<HTMLDivElement>(null);\n const [w, setW] = React.useState(460);\n React.useLayoutEffect(() => {\n if (ref.current) setW(ref.current.offsetWidth);\n }, [fmt.block, !!onAi, !!onComment]);\n return createPortal(\n // No entrance motion: the bubble shows on every text selection, a 100+/day action.\n <div\n onMouseDown={(e) => {\n if (!(e.target as HTMLElement).closest(\"button\")) e.preventDefault();\n }}\n ref={ref}\n style={{ top, boxShadow: \"var(--kit-shadow-sm)\", left: Math.min(window.innerWidth - w - 8, Math.max(8, rect.left + rect.width / 2 - w / 2)) }}\n data-floating-layer=\"\"\n data-kit-scope=\"\"\n /* V2 floating.tsx:57-59: glass-strong for the raised fill and hairline; the tight shadow-sm (inline, so it beats the\n glass drop) keeps the shadow off the selected text right under the bubble */\n className=\"glass-strong pointer-events-auto fixed z-[calc(var(--kit-z-popover,84)_+_1)] flex h-9 items-center gap-0.5 rounded-kit-lg border border-kit-line px-1\"\n role=\"toolbar\"\n aria-label=\"Selection formatting\"\n >\n {onAi ? (\n <>\n <Menu>\n <MenuTrigger\n onMouseDown={(e) => {\n e.preventDefault();\n saveSel();\n }}\n className=\"flex h-7 items-center gap-1.5 rounded-kit-md px-2 text-kit-sm text-kit-fg hover:bg-kit-hover data-[popup-open]:bg-kit-hover\"\n >\n <Sparkle size={14} /> Improve writing\n </MenuTrigger>\n <MenuContent className=\"w-52\" finalFocus={false}>\n {BUBBLE_AI.map((p) => (\n <MenuItem key={p.id} icon={<Sparkle size={16} />} onClick={() => onAi(p.id)}>\n {p.label}\n </MenuItem>\n ))}\n </MenuContent>\n </Menu>\n <span aria-hidden className=\"mx-0.5 h-4 w-px bg-kit-line\" />\n </>\n ) : null}\n {fmt.block !== \"island\" && styles.length > 1 ? (\n <>\n <StyleMenu block={fmt.block} styles={styles} onPick={onStyle} />\n <span aria-hidden className=\"mx-0.5 h-4 w-px bg-kit-line\" />\n </>\n ) : null}\n {allows(\"bold\") ? <ToolButton label=\"Bold\" icon={<IconBold stroke={1.5} />} shortcut=\"⌘B\" active={fmt.bold} onClick={() => onMark(\"bold\")} /> : null}\n {allows(\"italic\") ? <ToolButton label=\"Italic\" icon={<IconItalic stroke={1.5} />} shortcut=\"⌘I\" active={fmt.italic} onClick={() => onMark(\"italic\")} /> : null}\n {allows(\"underline\") ? <ToolButton label=\"Underline\" icon={<IconUnderline stroke={1.5} />} shortcut=\"⌘U\" active={fmt.underline} onClick={() => onMark(\"underline\")} /> : null}\n {allows(\"strike\") ? <ToolButton label=\"Strikethrough\" icon={<IconStrikethrough stroke={1.5} />} active={fmt.strike} onClick={() => onMark(\"strikeThrough\")} /> : null}\n {/* x² and x₂: one at a time (picking one inside the other swaps them) */}\n {allows(\"sup\") ? <ToolButton label=\"Superscript\" icon={<IconSuperscript stroke={1.5} />} active={fmt.sup} onClick={() => onMark(\"superscript\")} /> : null}\n {allows(\"sub\") ? <ToolButton label=\"Subscript\" icon={<IconSubscript stroke={1.5} />} active={fmt.sub} onClick={() => onMark(\"subscript\")} /> : null}\n {allows(\"code\") ? <ToolButton label=\"Inline code\" icon={<IconCode stroke={1.5} />} shortcut=\"⌘E\" onClick={onInlineCode} /> : null}\n {allows(\"link\") ? <ToolButton label=\"Link\" icon={<IconLink stroke={1.5} />} shortcut=\"⌘K\" active={fmt.onLink} onClick={onLink} /> : null}\n {onComment ? (\n <>\n <span aria-hidden className=\"mx-0.5 h-4 w-px bg-kit-line\" />\n <ToolButton label=\"Comment\" icon={<IconMessage stroke={1.5} />} onClick={onComment} />\n </>\n ) : null}\n </div>,\n document.body,\n );\n}\n"],"mappings":";;;;;;;;;;;;;AAcA,IAAa,YAA+C;CAC1D;EAAE,IAAI;EAAW,OAAO;CAAkB;CAC1C;EAAE,IAAI;EAAW,OAAO;CAAe;CACvC;EAAE,IAAI;EAAY,OAAO;CAAW;CACpC;EAAE,IAAI;EAAW,OAAO;CAA2B;AACrD;AAEA,SAAgB,gBAAgB,EAC9B,MACA,KACA,QACA,SACA,MACA,SACA,QACA,cACA,QACA,WACA,SAeC;CAED,MAAM,QAAQ,KAAK,MAAM;CAEzB,MAAM,MADU,QAAQ,KAAM,CAAC,CAAC,SAAS,QAAQ,MAAM,SAAS,KAAK,QAAQ,KAAK,MAAM,MAClE,KAAK,SAAS,IAAI;CACxC,MAAM,SAAS,UAAU,MAAM;CAE/B,MAAM,MAAM,MAAM,OAAuB,IAAI;CAC7C,MAAM,CAAC,GAAG,QAAQ,MAAM,SAAS,GAAG;CACpC,MAAM,sBAAsB;EAC1B,IAAI,IAAI,SAAS,KAAK,IAAI,QAAQ,WAAW;CAC/C,GAAG;EAAC,IAAI;EAAO,CAAC,CAAC;EAAM,CAAC,CAAC;CAAS,CAAC;CACnC,OAAO,aAEL,qBAAC,OAAD;EACE,cAAc,MAAM;GAClB,IAAI,CAAE,EAAE,OAAuB,QAAQ,QAAQ,GAAG,EAAE,eAAe;EACrE;EACK;EACL,OAAO;GAAE;GAAK,WAAW;GAAwB,MAAM,KAAK,IAAI,OAAO,aAAa,IAAI,GAAG,KAAK,IAAI,GAAG,KAAK,OAAO,KAAK,QAAQ,IAAI,IAAI,CAAC,CAAC;EAAE;EAC5I,uBAAoB;EACpB,kBAAe;EAGf,WAAU;EACV,MAAK;EACL,cAAW;EAZb,UAAA;GAcG,OACC,qBAAA,UAAA,EAAA,UAAA,CACE,qBAAC,MAAD,EAAA,UAAA,CACE,qBAAC,aAAD;IACE,cAAc,MAAM;KAClB,EAAE,eAAe;KACjB,QAAQ;IACV;IACA,WAAU;IALZ,UAAA,CAOE,oBAAC,SAAD,EAAS,MAAM,GAAK,CAAA,GAAC,kBACV;GACb,CAAA,GAAA,oBAAC,aAAD;IAAa,WAAU;IAAO,YAAY;IACvC,UAAA,UAAU,KAAK,MACd,oBAAC,UAAD;KAAqB,MAAM,oBAAC,SAAD,EAAS,MAAM,GAAK,CAAA;KAAG,eAAe,KAAK,EAAE,EAAE;KACvE,UAAA,EAAE;IACK,GAFK,EAAE,EAEP,CACX;GACU,CAAA,CACT,EAAA,CAAA,GACN,oBAAC,QAAD;IAAM,eAAA;IAAY,WAAU;GAA+B,CAAA,CAC3D,EAAA,CAAA,IACA;GACH,IAAI,UAAU,YAAY,OAAO,SAAS,IACzC,qBAAA,UAAA,EAAA,UAAA,CACE,oBAAC,WAAD;IAAW,OAAO,IAAI;IAAe;IAAQ,QAAQ;GAAU,CAAA,GAC/D,oBAAC,QAAD;IAAM,eAAA;IAAY,WAAU;GAA+B,CAAA,CAC3D,EAAA,CAAA,IACA;GACH,OAAO,MAAM,IAAI,oBAAC,YAAD;IAAY,OAAM;IAAO,MAAM,oBAAC,UAAD,EAAU,QAAQ,IAAM,CAAA;IAAG,UAAS;IAAK,QAAQ,IAAI;IAAM,eAAe,OAAO,MAAM;GAAI,CAAA,IAAI;GAC/I,OAAO,QAAQ,IAAI,oBAAC,YAAD;IAAY,OAAM;IAAS,MAAM,oBAAC,YAAD,EAAY,QAAQ,IAAM,CAAA;IAAG,UAAS;IAAK,QAAQ,IAAI;IAAQ,eAAe,OAAO,QAAQ;GAAI,CAAA,IAAI;GACzJ,OAAO,WAAW,IAAI,oBAAC,YAAD;IAAY,OAAM;IAAY,MAAM,oBAAC,eAAD,EAAe,QAAQ,IAAM,CAAA;IAAG,UAAS;IAAK,QAAQ,IAAI;IAAW,eAAe,OAAO,WAAW;GAAI,CAAA,IAAI;GACxK,OAAO,QAAQ,IAAI,oBAAC,YAAD;IAAY,OAAM;IAAgB,MAAM,oBAAC,mBAAD,EAAmB,QAAQ,IAAM,CAAA;IAAG,QAAQ,IAAI;IAAQ,eAAe,OAAO,eAAe;GAAI,CAAA,IAAI;GAEhK,OAAO,KAAK,IAAI,oBAAC,YAAD;IAAY,OAAM;IAAc,MAAM,oBAAC,iBAAD,EAAiB,QAAQ,IAAM,CAAA;IAAG,QAAQ,IAAI;IAAK,eAAe,OAAO,aAAa;GAAI,CAAA,IAAI;GACpJ,OAAO,KAAK,IAAI,oBAAC,YAAD;IAAY,OAAM;IAAY,MAAM,oBAAC,eAAD,EAAe,QAAQ,IAAM,CAAA;IAAG,QAAQ,IAAI;IAAK,eAAe,OAAO,WAAW;GAAI,CAAA,IAAI;GAC9I,OAAO,MAAM,IAAI,oBAAC,YAAD;IAAY,OAAM;IAAc,MAAM,oBAAC,UAAD,EAAU,QAAQ,IAAM,CAAA;IAAG,UAAS;IAAK,SAAS;GAAe,CAAA,IAAI;GAC5H,OAAO,MAAM,IAAI,oBAAC,YAAD;IAAY,OAAM;IAAO,MAAM,oBAAC,UAAD,EAAU,QAAQ,IAAM,CAAA;IAAG,UAAS;IAAK,QAAQ,IAAI;IAAQ,SAAS;GAAS,CAAA,IAAI;GACnI,YACC,qBAAA,UAAA,EAAA,UAAA,CACE,oBAAC,QAAD;IAAM,eAAA;IAAY,WAAU;GAA+B,CAAA,GAC3D,oBAAC,YAAD;IAAY,OAAM;IAAU,MAAM,oBAAC,aAAD,EAAa,QAAQ,IAAM,CAAA;IAAG,SAAS;GAAY,CAAA,CACrF,EAAA,CAAA,IACA;EACD;CACL,CAAA,GAAA,SAAS,IACX;AACF"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export declare const FN_MARK = "sup[data-rt=fn]";
|
|
2
|
+
/** The toast when a footnote cannot go where the caret is (V2 rich-text-editor.tsx:613). */
|
|
3
|
+
export declare const FOOTNOTE_REFUSED: {
|
|
4
|
+
readonly title: "Put the caret in the text first";
|
|
5
|
+
readonly description: "Footnotes number the story's own text, not text inside a block.";
|
|
6
|
+
};
|
|
7
|
+
/** The popover's chrome (V2 rich-text-editor.tsx:1650). */
|
|
8
|
+
export declare const FOOTNOTE_POPOVER_CLASS = "w-[320px] rounded-kit-lg p-3";
|
|
9
|
+
/** The body's own markers in text order (markers inside a rich block are not the body's). */
|
|
10
|
+
export declare const footnoteMarkers: (root: HTMLElement) => HTMLElement[];
|
|
11
|
+
/** Numbers the markers 1…n in text order; returns them with their notes, for the list. */
|
|
12
|
+
export declare function renumberFootnotes(root: HTMLElement): {
|
|
13
|
+
el: HTMLElement;
|
|
14
|
+
note: string;
|
|
15
|
+
}[];
|
|
16
|
+
/** A new, empty marker at the caret. Null when the caret is outside the body's text (a rich block, code, elsewhere). */
|
|
17
|
+
export declare function insertFootnote(root: HTMLElement): HTMLElement | null;
|
|
18
|
+
/** The caret right after a marker, in the body. */
|
|
19
|
+
export declare function caretAfterMarker(root: HTMLElement, m: HTMLElement): void;
|
|
20
|
+
/** "Back to the text": scroll the marker to the centre, caret after it, and flash it (1200ms). */
|
|
21
|
+
export declare function backToMarker(root: HTMLElement, m: HTMLElement): void;
|
|
22
|
+
/** The note of one footnote: one setting, edited in a popover at its marker (V2 D54 / D55). */
|
|
23
|
+
export declare function FootnoteEditor({ n, note, onChange, onRemove, onDone }: {
|
|
24
|
+
n: number;
|
|
25
|
+
note: string;
|
|
26
|
+
onChange: (v: string) => void;
|
|
27
|
+
onRemove: () => void;
|
|
28
|
+
onDone: () => void;
|
|
29
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
30
|
+
/** The notes under the body, numbered in text order, each with a way back to its marker. Renders nothing when empty. */
|
|
31
|
+
export declare function FootnotesList({ notes, readOnly, density, onEdit, onBack, }: {
|
|
32
|
+
notes: {
|
|
33
|
+
el: HTMLElement;
|
|
34
|
+
note: string;
|
|
35
|
+
}[];
|
|
36
|
+
readOnly?: boolean;
|
|
37
|
+
/** the editor's spacing: bare (no chrome), dense (panel), default */
|
|
38
|
+
density?: "bare" | "dense" | "default";
|
|
39
|
+
onEdit: (el: HTMLElement) => void;
|
|
40
|
+
onBack: (el: HTMLElement) => void;
|
|
41
|
+
}): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { cn } from "../../lib/cn.js";
|
|
2
|
+
import { Button } from "../../ui/button.js";
|
|
3
|
+
import { Tooltip } from "../../ui/overlay.js";
|
|
4
|
+
import { Textarea } from "../../ui/input.js";
|
|
5
|
+
import * as React from "react";
|
|
6
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
import { IconTrash } from "@tabler/icons-react";
|
|
8
|
+
//#region src/controls/rich-text/footnote.tsx
|
|
9
|
+
/**
|
|
10
|
+
* RICH TEXT · Footnotes (kit-richtext-ui-spec.md §1): V2's inline footnote, stored as the PT inline object
|
|
11
|
+
* `{ _type: "footnote", note }`, written in the editor as `<sup data-rt="fn" data-note contenteditable="false">N</sup>`.
|
|
12
|
+
* The number, the notes list and the way back are derived from the markers' text order, never stored.
|
|
13
|
+
*
|
|
14
|
+
* Editor chrome, not an island: the editor owns the clicks and the popover's anchor; this module is the V2 parts.
|
|
15
|
+
* insert V2 ops.ts:182-205: at the caret through the browser's insert (⌘Z takes it back), never inside a rich
|
|
16
|
+
* block or code; null then, and the editor toasts FOOTNOTE_REFUSED (V2 rich-text-editor.tsx:610-615)
|
|
17
|
+
* numbers V2 dom.ts:429-436: the body's own markers in text order, 1…n
|
|
18
|
+
* popover V2 FootnoteEditor (rich-text-editor.tsx:1736-1777) at the marker, w-[320px] rounded p-3
|
|
19
|
+
* list V2 notes section (rich-text-editor.tsx:1533-1560): each note a button that edits it, and ↩ back to it
|
|
20
|
+
* back V2 backToMarker (rich-text-editor.tsx:1095-1100): scroll to it, caret after it, a 1200ms accent flash
|
|
21
|
+
*/
|
|
22
|
+
var FN_MARK = "sup[data-rt=fn]";
|
|
23
|
+
/** The toast when a footnote cannot go where the caret is (V2 rich-text-editor.tsx:613). */
|
|
24
|
+
var FOOTNOTE_REFUSED = {
|
|
25
|
+
title: "Put the caret in the text first",
|
|
26
|
+
description: "Footnotes number the story's own text, not text inside a block."
|
|
27
|
+
};
|
|
28
|
+
/** The popover's chrome (V2 rich-text-editor.tsx:1650). */
|
|
29
|
+
var FOOTNOTE_POPOVER_CLASS = "w-[320px] rounded-kit-lg p-3";
|
|
30
|
+
/** The body's own markers in text order (markers inside a rich block are not the body's). */
|
|
31
|
+
var footnoteMarkers = (root) => Array.from(root.querySelectorAll(FN_MARK)).filter((m) => !m.closest("[data-rt-island],[data-rt-isolate]"));
|
|
32
|
+
/** Numbers the markers 1…n in text order; returns them with their notes, for the list. */
|
|
33
|
+
function renumberFootnotes(root) {
|
|
34
|
+
return footnoteMarkers(root).map((m, i) => {
|
|
35
|
+
if (m.textContent !== String(i + 1)) m.textContent = String(i + 1);
|
|
36
|
+
return {
|
|
37
|
+
el: m,
|
|
38
|
+
note: m.getAttribute("data-note") ?? ""
|
|
39
|
+
};
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
/** A new, empty marker at the caret. Null when the caret is outside the body's text (a rich block, code, elsewhere). */
|
|
43
|
+
function insertFootnote(root) {
|
|
44
|
+
const s = window.getSelection();
|
|
45
|
+
if (!s || !s.rangeCount || !root.contains(s.anchorNode)) return null;
|
|
46
|
+
const at = s.anchorNode?.nodeType === 1 ? s.anchorNode : s.anchorNode?.parentElement;
|
|
47
|
+
if (!at || at.closest("[data-rt-island],[data-rt-isolate]") || at.closest("pre")) return null;
|
|
48
|
+
root.focus({ preventScroll: true });
|
|
49
|
+
if (typeof document.execCommand === "function") document.execCommand("insertHTML", false, `<sup data-rt="fn" data-note="" contenteditable="false" data-fn-new="">1</sup>`);
|
|
50
|
+
let sup = root.querySelector("sup[data-fn-new]");
|
|
51
|
+
if (!sup) {
|
|
52
|
+
sup = document.createElement("sup");
|
|
53
|
+
sup.setAttribute("data-rt", "fn");
|
|
54
|
+
sup.setAttribute("data-note", "");
|
|
55
|
+
sup.setAttribute("contenteditable", "false");
|
|
56
|
+
sup.textContent = "1";
|
|
57
|
+
const r = s.getRangeAt(0);
|
|
58
|
+
r.collapse(false);
|
|
59
|
+
r.insertNode(sup);
|
|
60
|
+
const after = document.createTextNode("");
|
|
61
|
+
sup.after(after);
|
|
62
|
+
const c = document.createRange();
|
|
63
|
+
c.setStart(after, after.length);
|
|
64
|
+
c.collapse(true);
|
|
65
|
+
s.removeAllRanges();
|
|
66
|
+
s.addRange(c);
|
|
67
|
+
}
|
|
68
|
+
sup.removeAttribute("data-fn-new");
|
|
69
|
+
renumberFootnotes(root);
|
|
70
|
+
return sup;
|
|
71
|
+
}
|
|
72
|
+
/** The caret right after a marker, in the body. */
|
|
73
|
+
function caretAfterMarker(root, m) {
|
|
74
|
+
const s = window.getSelection();
|
|
75
|
+
if (!s || !m.isConnected) return;
|
|
76
|
+
root.focus({ preventScroll: true });
|
|
77
|
+
const r = document.createRange();
|
|
78
|
+
r.setStartAfter(m);
|
|
79
|
+
r.collapse(true);
|
|
80
|
+
s.removeAllRanges();
|
|
81
|
+
s.addRange(r);
|
|
82
|
+
}
|
|
83
|
+
/** "Back to the text": scroll the marker to the centre, caret after it, and flash it (1200ms). */
|
|
84
|
+
function backToMarker(root, m) {
|
|
85
|
+
if (!m.isConnected) return;
|
|
86
|
+
m.scrollIntoView?.({
|
|
87
|
+
block: "center",
|
|
88
|
+
behavior: "smooth"
|
|
89
|
+
});
|
|
90
|
+
caretAfterMarker(root, m);
|
|
91
|
+
m.animate?.([{ boxShadow: "0 0 0 3px var(--kit-accent-soft)" }, { boxShadow: "0 0 0 0 transparent" }], { duration: 1200 });
|
|
92
|
+
}
|
|
93
|
+
/** The note of one footnote: one setting, edited in a popover at its marker (V2 D54 / D55). */
|
|
94
|
+
function FootnoteEditor({ n, note, onChange, onRemove, onDone }) {
|
|
95
|
+
const [v, setV] = React.useState(note);
|
|
96
|
+
const id = React.useId();
|
|
97
|
+
return /* @__PURE__ */ jsxs("form", {
|
|
98
|
+
className: "flex flex-col gap-2",
|
|
99
|
+
onSubmit: (e) => {
|
|
100
|
+
e.preventDefault();
|
|
101
|
+
onDone();
|
|
102
|
+
},
|
|
103
|
+
children: [
|
|
104
|
+
/* @__PURE__ */ jsxs("label", {
|
|
105
|
+
htmlFor: id,
|
|
106
|
+
className: "text-kit-xs font-medium text-kit-fg-2",
|
|
107
|
+
children: ["Footnote ", n]
|
|
108
|
+
}),
|
|
109
|
+
/* @__PURE__ */ jsx(Textarea, {
|
|
110
|
+
id,
|
|
111
|
+
autoFocus: true,
|
|
112
|
+
rows: 3,
|
|
113
|
+
value: v,
|
|
114
|
+
placeholder: "Write the note",
|
|
115
|
+
onChange: (e) => {
|
|
116
|
+
setV(e.target.value);
|
|
117
|
+
onChange(e.target.value);
|
|
118
|
+
},
|
|
119
|
+
onKeyDown: (e) => {
|
|
120
|
+
if (e.key === "Enter" && !e.shiftKey) {
|
|
121
|
+
e.preventDefault();
|
|
122
|
+
onDone();
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}),
|
|
126
|
+
/* @__PURE__ */ jsxs("div", {
|
|
127
|
+
className: "flex items-center justify-between",
|
|
128
|
+
children: [/* @__PURE__ */ jsx(Button, {
|
|
129
|
+
size: "xs",
|
|
130
|
+
variant: "ghost",
|
|
131
|
+
leftIcon: /* @__PURE__ */ jsx(IconTrash, { stroke: 1.5 }),
|
|
132
|
+
onClick: onRemove,
|
|
133
|
+
className: "hover:text-kit-danger-fg",
|
|
134
|
+
children: "Remove"
|
|
135
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
136
|
+
size: "xs",
|
|
137
|
+
variant: "primary",
|
|
138
|
+
type: "submit",
|
|
139
|
+
children: "Done"
|
|
140
|
+
})]
|
|
141
|
+
})
|
|
142
|
+
]
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
/** The notes under the body, numbered in text order, each with a way back to its marker. Renders nothing when empty. */
|
|
146
|
+
function FootnotesList({ notes, readOnly, density = "default", onEdit, onBack }) {
|
|
147
|
+
if (!notes.length) return null;
|
|
148
|
+
return /* @__PURE__ */ jsx("section", {
|
|
149
|
+
"aria-label": "Footnotes",
|
|
150
|
+
className: cn("border-t border-kit-line-subtle text-kit-sm text-kit-fg-2", density === "bare" ? "mt-4 pt-2" : density === "dense" ? "mx-2.5 mb-2 pt-2" : "mx-4 mb-3 pt-2.5"),
|
|
151
|
+
children: /* @__PURE__ */ jsx("ol", {
|
|
152
|
+
className: "m-0 flex list-decimal flex-col gap-1 pl-5 marker:text-kit-fg-3",
|
|
153
|
+
children: notes.map((n, i) => /* @__PURE__ */ jsx("li", {
|
|
154
|
+
className: "pl-1",
|
|
155
|
+
children: /* @__PURE__ */ jsxs("span", {
|
|
156
|
+
className: "flex items-start gap-1",
|
|
157
|
+
children: [/* @__PURE__ */ jsx("button", {
|
|
158
|
+
type: "button",
|
|
159
|
+
disabled: readOnly,
|
|
160
|
+
"aria-label": `Footnote ${i + 1}: ${n.note || "empty"}. Edit`,
|
|
161
|
+
onClick: () => onEdit(n.el),
|
|
162
|
+
className: "min-w-0 flex-1 rounded-kit-sm text-left leading-relaxed enabled:hover:text-kit-fg",
|
|
163
|
+
children: n.note || /* @__PURE__ */ jsx("span", {
|
|
164
|
+
className: "text-kit-warning-fg",
|
|
165
|
+
children: "Empty note"
|
|
166
|
+
})
|
|
167
|
+
}), /* @__PURE__ */ jsx(Tooltip, {
|
|
168
|
+
content: "Back to the text",
|
|
169
|
+
children: /* @__PURE__ */ jsx("button", {
|
|
170
|
+
type: "button",
|
|
171
|
+
"aria-label": `Back to reference ${i + 1}`,
|
|
172
|
+
onClick: () => onBack(n.el),
|
|
173
|
+
className: "shrink-0 rounded-kit-sm px-1 text-kit-fg-3 hover:bg-kit-hover hover:text-kit-fg",
|
|
174
|
+
children: "↩"
|
|
175
|
+
})
|
|
176
|
+
})]
|
|
177
|
+
})
|
|
178
|
+
}, i))
|
|
179
|
+
})
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
//#endregion
|
|
183
|
+
export { FN_MARK, FOOTNOTE_POPOVER_CLASS, FOOTNOTE_REFUSED, FootnoteEditor, FootnotesList, backToMarker, caretAfterMarker, footnoteMarkers, insertFootnote, renumberFootnotes };
|
|
184
|
+
|
|
185
|
+
//# sourceMappingURL=footnote.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"footnote.js","names":[],"sources":["../../../src/controls/rich-text/footnote.tsx"],"sourcesContent":["/**\n * RICH TEXT · Footnotes (kit-richtext-ui-spec.md §1): V2's inline footnote, stored as the PT inline object\n * `{ _type: \"footnote\", note }`, written in the editor as `<sup data-rt=\"fn\" data-note contenteditable=\"false\">N</sup>`.\n * The number, the notes list and the way back are derived from the markers' text order, never stored.\n *\n * Editor chrome, not an island: the editor owns the clicks and the popover's anchor; this module is the V2 parts.\n * insert V2 ops.ts:182-205: at the caret through the browser's insert (⌘Z takes it back), never inside a rich\n * block or code; null then, and the editor toasts FOOTNOTE_REFUSED (V2 rich-text-editor.tsx:610-615)\n * numbers V2 dom.ts:429-436: the body's own markers in text order, 1…n\n * popover V2 FootnoteEditor (rich-text-editor.tsx:1736-1777) at the marker, w-[320px] rounded p-3\n * list V2 notes section (rich-text-editor.tsx:1533-1560): each note a button that edits it, and ↩ back to it\n * back V2 backToMarker (rich-text-editor.tsx:1095-1100): scroll to it, caret after it, a 1200ms accent flash\n */\nimport * as React from \"react\";\nimport { IconTrash } from \"@tabler/icons-react\";\nimport { cn } from \"../../lib/cn\";\nimport { Button } from \"../../ui/button\";\nimport { Textarea } from \"../../ui/input\";\nimport { Tooltip } from \"../../ui/overlay\";\n\nexport const FN_MARK = \"sup[data-rt=fn]\";\n/** The toast when a footnote cannot go where the caret is (V2 rich-text-editor.tsx:613). */\nexport const FOOTNOTE_REFUSED = {\n title: \"Put the caret in the text first\",\n description: \"Footnotes number the story's own text, not text inside a block.\",\n} as const;\n/** The popover's chrome (V2 rich-text-editor.tsx:1650). */\nexport const FOOTNOTE_POPOVER_CLASS = \"w-[320px] rounded-kit-lg p-3\";\n\n/** The body's own markers in text order (markers inside a rich block are not the body's). */\nexport const footnoteMarkers = (root: HTMLElement): HTMLElement[] =>\n Array.from(root.querySelectorAll<HTMLElement>(FN_MARK)).filter((m) => !m.closest(\"[data-rt-island],[data-rt-isolate]\"));\n\n/** Numbers the markers 1…n in text order; returns them with their notes, for the list. */\nexport function renumberFootnotes(root: HTMLElement): { el: HTMLElement; note: string }[] {\n return footnoteMarkers(root).map((m, i) => {\n if (m.textContent !== String(i + 1)) m.textContent = String(i + 1);\n return { el: m, note: m.getAttribute(\"data-note\") ?? \"\" };\n });\n}\n\n/** A new, empty marker at the caret. Null when the caret is outside the body's text (a rich block, code, elsewhere). */\nexport function insertFootnote(root: HTMLElement): HTMLElement | null {\n const s = window.getSelection();\n if (!s || !s.rangeCount || !root.contains(s.anchorNode)) return null;\n const at = s.anchorNode?.nodeType === 1 ? (s.anchorNode as HTMLElement) : s.anchorNode?.parentElement;\n if (!at || at.closest(\"[data-rt-island],[data-rt-isolate]\") || at.closest(\"pre\")) return null;\n root.focus({ preventScroll: true });\n if (typeof document.execCommand === \"function\") document.execCommand(\"insertHTML\", false, `<sup data-rt=\"fn\" data-note=\"\" contenteditable=\"false\" data-fn-new=\"\">1</sup>`);\n let sup = root.querySelector<HTMLElement>(\"sup[data-fn-new]\");\n if (!sup) {\n // the browser dropped the marker (or has no execCommand): place it by hand\n sup = document.createElement(\"sup\");\n sup.setAttribute(\"data-rt\", \"fn\");\n sup.setAttribute(\"data-note\", \"\");\n sup.setAttribute(\"contenteditable\", \"false\");\n sup.textContent = \"1\";\n const r = s.getRangeAt(0);\n r.collapse(false);\n r.insertNode(sup);\n const after = document.createTextNode(\"\");\n sup.after(after);\n const c = document.createRange();\n c.setStart(after, after.length);\n c.collapse(true);\n s.removeAllRanges();\n s.addRange(c);\n }\n sup.removeAttribute(\"data-fn-new\");\n renumberFootnotes(root);\n return sup;\n}\n\n/** The caret right after a marker, in the body. */\nexport function caretAfterMarker(root: HTMLElement, m: HTMLElement) {\n const s = window.getSelection();\n if (!s || !m.isConnected) return;\n root.focus({ preventScroll: true });\n const r = document.createRange();\n r.setStartAfter(m);\n r.collapse(true);\n s.removeAllRanges();\n s.addRange(r);\n}\n\n/** \"Back to the text\": scroll the marker to the centre, caret after it, and flash it (1200ms). */\nexport function backToMarker(root: HTMLElement, m: HTMLElement) {\n if (!m.isConnected) return;\n m.scrollIntoView?.({ block: \"center\", behavior: \"smooth\" });\n caretAfterMarker(root, m);\n m.animate?.([{ boxShadow: \"0 0 0 3px var(--kit-accent-soft)\" }, { boxShadow: \"0 0 0 0 transparent\" }], { duration: 1200 });\n}\n\n/** The note of one footnote: one setting, edited in a popover at its marker (V2 D54 / D55). */\nexport function FootnoteEditor({ n, note, onChange, onRemove, onDone }: { n: number; note: string; onChange: (v: string) => void; onRemove: () => void; onDone: () => void }) {\n const [v, setV] = React.useState(note);\n const id = React.useId();\n return (\n <form\n className=\"flex flex-col gap-2\"\n onSubmit={(e) => {\n e.preventDefault();\n onDone();\n }}\n >\n <label htmlFor={id} className=\"text-kit-xs font-medium text-kit-fg-2\">\n Footnote {n}\n </label>\n <Textarea\n id={id}\n autoFocus\n rows={3}\n value={v}\n placeholder=\"Write the note\"\n onChange={(e) => {\n setV(e.target.value);\n onChange(e.target.value);\n }}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault();\n onDone();\n }\n }}\n />\n <div className=\"flex items-center justify-between\">\n <Button size=\"xs\" variant=\"ghost\" leftIcon={<IconTrash stroke={1.5} />} onClick={onRemove} className=\"hover:text-kit-danger-fg\">\n Remove\n </Button>\n <Button size=\"xs\" variant=\"primary\" type=\"submit\">\n Done\n </Button>\n </div>\n </form>\n );\n}\n\n/** The notes under the body, numbered in text order, each with a way back to its marker. Renders nothing when empty. */\nexport function FootnotesList({\n notes,\n readOnly,\n density = \"default\",\n onEdit,\n onBack,\n}: {\n notes: { el: HTMLElement; note: string }[];\n readOnly?: boolean;\n /** the editor's spacing: bare (no chrome), dense (panel), default */\n density?: \"bare\" | \"dense\" | \"default\";\n onEdit: (el: HTMLElement) => void;\n onBack: (el: HTMLElement) => void;\n}) {\n if (!notes.length) return null;\n return (\n <section\n aria-label=\"Footnotes\"\n className={cn(\"border-t border-kit-line-subtle text-kit-sm text-kit-fg-2\", density === \"bare\" ? \"mt-4 pt-2\" : density === \"dense\" ? \"mx-2.5 mb-2 pt-2\" : \"mx-4 mb-3 pt-2.5\")}\n >\n <ol className=\"m-0 flex list-decimal flex-col gap-1 pl-5 marker:text-kit-fg-3\">\n {notes.map((n, i) => (\n <li key={i} className=\"pl-1\">\n <span className=\"flex items-start gap-1\">\n <button\n type=\"button\"\n disabled={readOnly}\n aria-label={`Footnote ${i + 1}: ${n.note || \"empty\"}. Edit`}\n onClick={() => onEdit(n.el)}\n className=\"min-w-0 flex-1 rounded-kit-sm text-left leading-relaxed enabled:hover:text-kit-fg\"\n >\n {n.note || <span className=\"text-kit-warning-fg\">Empty note</span>}\n </button>\n <Tooltip content=\"Back to the text\">\n <button type=\"button\" aria-label={`Back to reference ${i + 1}`} onClick={() => onBack(n.el)} className=\"shrink-0 rounded-kit-sm px-1 text-kit-fg-3 hover:bg-kit-hover hover:text-kit-fg\">\n ↩\n </button>\n </Tooltip>\n </span>\n </li>\n ))}\n </ol>\n </section>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { TypeSchema } from "../../schema/types";
|
|
2
|
+
import type { ImageValue } from "../media";
|
|
3
|
+
import type { IslandCtx } from "./blocks";
|
|
4
|
+
import type { IslandEl } from "./dom";
|
|
5
|
+
export interface GalleryImage {
|
|
6
|
+
_key: string;
|
|
7
|
+
image: ImageValue | null;
|
|
8
|
+
caption: string;
|
|
9
|
+
}
|
|
10
|
+
export interface GalleryModel {
|
|
11
|
+
layout: "grid" | "carousel";
|
|
12
|
+
images: GalleryImage[];
|
|
13
|
+
}
|
|
14
|
+
export declare const GALLERY_LABEL = "Gallery";
|
|
15
|
+
export declare const galleryDefault: () => GalleryModel;
|
|
16
|
+
export declare const GALLERY_SCHEMA: TypeSchema;
|
|
17
|
+
export declare function GalleryPreview({ m, onAdd, ro }: {
|
|
18
|
+
m: GalleryModel;
|
|
19
|
+
onAdd: () => void;
|
|
20
|
+
ro: boolean;
|
|
21
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
22
|
+
export declare function GalleryBlock({ m, set, el, ctx, autoFocus, }: {
|
|
23
|
+
m: GalleryModel;
|
|
24
|
+
set: (fn: (m: GalleryModel) => GalleryModel, label?: string) => void;
|
|
25
|
+
el: IslandEl;
|
|
26
|
+
ctx: IslandCtx;
|
|
27
|
+
autoFocus: boolean;
|
|
28
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { cn } from "../../lib/cn.js";
|
|
2
|
+
import { ArticleEmpty, ArticlePanelBlock } from "./article-shell.js";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
import { IconPhoto } from "@tabler/icons-react";
|
|
5
|
+
//#region src/controls/rich-text/gallery.tsx
|
|
6
|
+
/**
|
|
7
|
+
* RICH TEXT · Gallery (kit-richtext-ui-spec.md §2): V2's article block, stored as the PT block object
|
|
8
|
+
* `{ _type: "gallery", layout: "grid" | "carousel", images: { _key, image, caption? }[] }`; each image is the rich-text
|
|
9
|
+
* image's own shape (src/alt + media id), so media rewrites and alt audits reach it.
|
|
10
|
+
*
|
|
11
|
+
* form V2 article.ts:75-114: Images (a grid list, 2–24, each a required image + caption ≤160), Layout
|
|
12
|
+
* (Grid | Carousel, segmented). A list of objects → the floating properties panel (D54); a fresh insert opens it.
|
|
13
|
+
* preview V2 article-blocks.tsx:451-480: Grid in 2 columns for 2 or 4 images, else 3, square crops; Carousel a
|
|
14
|
+
* 72%-wide scroll-snap row of 4:3 crops with "N images · carousel"; "Add images" when there are none.
|
|
15
|
+
*/
|
|
16
|
+
var GALLERY_LABEL = "Gallery";
|
|
17
|
+
var galleryDefault = () => ({
|
|
18
|
+
layout: "grid",
|
|
19
|
+
images: []
|
|
20
|
+
});
|
|
21
|
+
var GALLERY_SCHEMA = {
|
|
22
|
+
name: "gallery",
|
|
23
|
+
title: GALLERY_LABEL,
|
|
24
|
+
kind: "object",
|
|
25
|
+
icon: "photo",
|
|
26
|
+
fields: [{
|
|
27
|
+
name: "images",
|
|
28
|
+
title: "Images",
|
|
29
|
+
type: "array",
|
|
30
|
+
itemNoun: "image",
|
|
31
|
+
arrayLayout: "grid",
|
|
32
|
+
validation: {
|
|
33
|
+
min: 2,
|
|
34
|
+
max: 24
|
|
35
|
+
},
|
|
36
|
+
of: [{
|
|
37
|
+
name: "photo",
|
|
38
|
+
title: "Image",
|
|
39
|
+
type: "object",
|
|
40
|
+
icon: "photo",
|
|
41
|
+
preview: {
|
|
42
|
+
title: "caption",
|
|
43
|
+
media: "image",
|
|
44
|
+
fallback: "Untitled image"
|
|
45
|
+
},
|
|
46
|
+
fields: [{
|
|
47
|
+
name: "image",
|
|
48
|
+
title: "Image",
|
|
49
|
+
type: "image",
|
|
50
|
+
validation: { required: true }
|
|
51
|
+
}, {
|
|
52
|
+
name: "caption",
|
|
53
|
+
title: "Caption",
|
|
54
|
+
type: "string",
|
|
55
|
+
validation: { max: 160 }
|
|
56
|
+
}]
|
|
57
|
+
}]
|
|
58
|
+
}, {
|
|
59
|
+
name: "layout",
|
|
60
|
+
title: "Layout",
|
|
61
|
+
type: "select",
|
|
62
|
+
layout: "segmented",
|
|
63
|
+
initialValue: "grid",
|
|
64
|
+
options: [{
|
|
65
|
+
value: "grid",
|
|
66
|
+
label: "Grid"
|
|
67
|
+
}, {
|
|
68
|
+
value: "carousel",
|
|
69
|
+
label: "Carousel"
|
|
70
|
+
}]
|
|
71
|
+
}]
|
|
72
|
+
};
|
|
73
|
+
function GalleryPreview({ m, onAdd, ro }) {
|
|
74
|
+
const imgs = m.images.filter((x) => x.image?.url);
|
|
75
|
+
if (!imgs.length) return /* @__PURE__ */ jsx(ArticleEmpty, {
|
|
76
|
+
icon: /* @__PURE__ */ jsx(IconPhoto, { stroke: 1.5 }),
|
|
77
|
+
title: GALLERY_LABEL,
|
|
78
|
+
action: "Add images",
|
|
79
|
+
onAction: onAdd,
|
|
80
|
+
ro
|
|
81
|
+
});
|
|
82
|
+
if (m.layout === "carousel") return /* @__PURE__ */ jsxs("figure", {
|
|
83
|
+
className: "m-0",
|
|
84
|
+
"data-field": "images",
|
|
85
|
+
children: [/* @__PURE__ */ jsx("ul", {
|
|
86
|
+
className: "m-0 flex snap-x gap-2 overflow-x-auto p-0 pb-1",
|
|
87
|
+
"aria-label": GALLERY_LABEL,
|
|
88
|
+
children: imgs.map((x) => /* @__PURE__ */ jsxs("li", {
|
|
89
|
+
className: "w-[72%] shrink-0 snap-start list-none",
|
|
90
|
+
children: [/* @__PURE__ */ jsx("img", {
|
|
91
|
+
src: x.image.url,
|
|
92
|
+
alt: x.image.alt ?? "",
|
|
93
|
+
draggable: false,
|
|
94
|
+
className: "block aspect-[4/3] w-full rounded-kit-lg border border-kit-line object-cover"
|
|
95
|
+
}), x.caption ? /* @__PURE__ */ jsx("p", {
|
|
96
|
+
className: "mt-1 truncate text-kit-xs text-kit-fg-3",
|
|
97
|
+
children: x.caption
|
|
98
|
+
}) : null]
|
|
99
|
+
}, x._key))
|
|
100
|
+
}), /* @__PURE__ */ jsxs("figcaption", {
|
|
101
|
+
className: "mt-1 text-kit-2xs text-kit-fg-3",
|
|
102
|
+
children: [
|
|
103
|
+
imgs.length,
|
|
104
|
+
" ",
|
|
105
|
+
imgs.length === 1 ? "image" : "images",
|
|
106
|
+
" · carousel"
|
|
107
|
+
]
|
|
108
|
+
})]
|
|
109
|
+
});
|
|
110
|
+
return /* @__PURE__ */ jsx("figure", {
|
|
111
|
+
className: "m-0",
|
|
112
|
+
"data-field": "images",
|
|
113
|
+
children: /* @__PURE__ */ jsx("ul", {
|
|
114
|
+
className: cn("m-0 grid gap-2 p-0", imgs.length === 2 || imgs.length === 4 ? "grid-cols-2" : "grid-cols-3"),
|
|
115
|
+
"aria-label": GALLERY_LABEL,
|
|
116
|
+
children: imgs.map((x) => /* @__PURE__ */ jsxs("li", {
|
|
117
|
+
className: "list-none",
|
|
118
|
+
children: [/* @__PURE__ */ jsx("img", {
|
|
119
|
+
src: x.image.url,
|
|
120
|
+
alt: x.image.alt ?? "",
|
|
121
|
+
draggable: false,
|
|
122
|
+
className: "block aspect-square w-full rounded-kit-lg border border-kit-line object-cover"
|
|
123
|
+
}), x.caption ? /* @__PURE__ */ jsx("p", {
|
|
124
|
+
className: "mt-1 truncate text-kit-xs text-kit-fg-3",
|
|
125
|
+
children: x.caption
|
|
126
|
+
}) : null]
|
|
127
|
+
}, x._key))
|
|
128
|
+
})
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
var asImages = (v) => Array.isArray(v) ? v.map((x, i) => {
|
|
132
|
+
const o = x ?? {};
|
|
133
|
+
return {
|
|
134
|
+
_key: typeof o._key === "string" ? o._key : `g${i}`,
|
|
135
|
+
image: o.image ?? null,
|
|
136
|
+
caption: typeof o.caption === "string" ? o.caption : ""
|
|
137
|
+
};
|
|
138
|
+
}) : [];
|
|
139
|
+
function GalleryBlock({ m, set, el, ctx, autoFocus }) {
|
|
140
|
+
return /* @__PURE__ */ jsx(ArticlePanelBlock, {
|
|
141
|
+
label: GALLERY_LABEL,
|
|
142
|
+
kind: "gallery",
|
|
143
|
+
schema: GALLERY_SCHEMA,
|
|
144
|
+
m,
|
|
145
|
+
set,
|
|
146
|
+
el,
|
|
147
|
+
ctx,
|
|
148
|
+
autoFocus,
|
|
149
|
+
toForm: (x) => ({
|
|
150
|
+
images: x.images,
|
|
151
|
+
layout: x.layout
|
|
152
|
+
}),
|
|
153
|
+
fromForm: (v) => ({
|
|
154
|
+
images: asImages(v.images),
|
|
155
|
+
layout: v.layout === "carousel" ? "carousel" : "grid"
|
|
156
|
+
}),
|
|
157
|
+
children: (open, ro) => /* @__PURE__ */ jsx(GalleryPreview, {
|
|
158
|
+
m,
|
|
159
|
+
onAdd: () => open("images"),
|
|
160
|
+
ro
|
|
161
|
+
})
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
//#endregion
|
|
165
|
+
export { GALLERY_LABEL, GALLERY_SCHEMA, GalleryBlock, GalleryPreview, galleryDefault };
|
|
166
|
+
|
|
167
|
+
//# sourceMappingURL=gallery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gallery.js","names":[],"sources":["../../../src/controls/rich-text/gallery.tsx"],"sourcesContent":["/**\n * RICH TEXT · Gallery (kit-richtext-ui-spec.md §2): V2's article block, stored as the PT block object\n * `{ _type: \"gallery\", layout: \"grid\" | \"carousel\", images: { _key, image, caption? }[] }`; each image is the rich-text\n * image's own shape (src/alt + media id), so media rewrites and alt audits reach it.\n *\n * form V2 article.ts:75-114: Images (a grid list, 2–24, each a required image + caption ≤160), Layout\n * (Grid | Carousel, segmented). A list of objects → the floating properties panel (D54); a fresh insert opens it.\n * preview V2 article-blocks.tsx:451-480: Grid in 2 columns for 2 or 4 images, else 3, square crops; Carousel a\n * 72%-wide scroll-snap row of 4:3 crops with \"N images · carousel\"; \"Add images\" when there are none.\n */\nimport { IconPhoto } from \"@tabler/icons-react\";\nimport { cn } from \"../../lib/cn\";\nimport type { TypeSchema } from \"../../schema/types\";\nimport type { ImageValue } from \"../media\";\nimport { ArticleEmpty, ArticlePanelBlock } from \"./article-shell\";\nimport type { IslandCtx } from \"./blocks\";\nimport type { IslandEl } from \"./dom\";\n\nexport interface GalleryImage {\n _key: string;\n image: ImageValue | null;\n caption: string;\n}\nexport interface GalleryModel {\n layout: \"grid\" | \"carousel\";\n images: GalleryImage[];\n}\nexport const GALLERY_LABEL = \"Gallery\";\nexport const galleryDefault = (): GalleryModel => ({ layout: \"grid\", images: [] });\n\nexport const GALLERY_SCHEMA: TypeSchema = {\n name: \"gallery\",\n title: GALLERY_LABEL,\n kind: \"object\",\n icon: \"photo\",\n fields: [\n {\n name: \"images\",\n title: \"Images\",\n type: \"array\",\n itemNoun: \"image\",\n arrayLayout: \"grid\",\n validation: { min: 2, max: 24 },\n of: [\n {\n name: \"photo\",\n title: \"Image\",\n type: \"object\",\n icon: \"photo\",\n preview: { title: \"caption\", media: \"image\", fallback: \"Untitled image\" },\n fields: [\n { name: \"image\", title: \"Image\", type: \"image\", validation: { required: true } },\n { name: \"caption\", title: \"Caption\", type: \"string\", validation: { max: 160 } },\n ],\n },\n ],\n },\n {\n name: \"layout\",\n title: \"Layout\",\n type: \"select\",\n layout: \"segmented\",\n initialValue: \"grid\",\n options: [\n { value: \"grid\", label: \"Grid\" },\n { value: \"carousel\", label: \"Carousel\" },\n ],\n },\n ],\n};\n\nexport function GalleryPreview({ m, onAdd, ro }: { m: GalleryModel; onAdd: () => void; ro: boolean }) {\n const imgs = m.images.filter((x) => x.image?.url);\n if (!imgs.length) return <ArticleEmpty icon={<IconPhoto stroke={1.5} />} title={GALLERY_LABEL} action=\"Add images\" onAction={onAdd} ro={ro} />;\n if (m.layout === \"carousel\")\n return (\n <figure className=\"m-0\" data-field=\"images\">\n <ul className=\"m-0 flex snap-x gap-2 overflow-x-auto p-0 pb-1\" aria-label={GALLERY_LABEL}>\n {imgs.map((x) => (\n <li key={x._key} className=\"w-[72%] shrink-0 snap-start list-none\">\n <img src={x.image!.url} alt={x.image!.alt ?? \"\"} draggable={false} className=\"block aspect-[4/3] w-full rounded-kit-lg border border-kit-line object-cover\" />\n {x.caption ? <p className=\"mt-1 truncate text-kit-xs text-kit-fg-3\">{x.caption}</p> : null}\n </li>\n ))}\n </ul>\n <figcaption className=\"mt-1 text-kit-2xs text-kit-fg-3\">\n {imgs.length} {imgs.length === 1 ? \"image\" : \"images\"} · carousel\n </figcaption>\n </figure>\n );\n return (\n <figure className=\"m-0\" data-field=\"images\">\n <ul className={cn(\"m-0 grid gap-2 p-0\", imgs.length === 2 || imgs.length === 4 ? \"grid-cols-2\" : \"grid-cols-3\")} aria-label={GALLERY_LABEL}>\n {imgs.map((x) => (\n <li key={x._key} className=\"list-none\">\n <img src={x.image!.url} alt={x.image!.alt ?? \"\"} draggable={false} className=\"block aspect-square w-full rounded-kit-lg border border-kit-line object-cover\" />\n {x.caption ? <p className=\"mt-1 truncate text-kit-xs text-kit-fg-3\">{x.caption}</p> : null}\n </li>\n ))}\n </ul>\n </figure>\n );\n}\n\nconst asImages = (v: unknown): GalleryImage[] =>\n Array.isArray(v)\n ? v.map((x, i) => {\n const o = (x ?? {}) as Record<string, unknown>;\n return { _key: typeof o._key === \"string\" ? o._key : `g${i}`, image: (o.image as ImageValue | null) ?? null, caption: typeof o.caption === \"string\" ? o.caption : \"\" };\n })\n : [];\n\nexport function GalleryBlock({\n m, set, el, ctx, autoFocus,\n}: {\n m: GalleryModel;\n set: (fn: (m: GalleryModel) => GalleryModel, label?: string) => void;\n el: IslandEl;\n ctx: IslandCtx;\n autoFocus: boolean;\n}) {\n return (\n <ArticlePanelBlock<GalleryModel>\n label={GALLERY_LABEL}\n kind=\"gallery\"\n schema={GALLERY_SCHEMA}\n m={m}\n set={set}\n el={el}\n ctx={ctx}\n autoFocus={autoFocus}\n toForm={(x) => ({ images: x.images, layout: x.layout })}\n fromForm={(v) => ({ images: asImages(v.images), layout: v.layout === \"carousel\" ? \"carousel\" : \"grid\" })}\n >\n {(open, ro) => <GalleryPreview m={m} onAdd={() => open(\"images\")} ro={ro} />}\n </ArticlePanelBlock>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ACTIONS, CONTROLS } from "../../engine/kit-field.js";
|
|
2
2
|
import { RichTextControl, RichTextExpandAction } from "./control.js";
|
|
3
|
-
//#region src/
|
|
3
|
+
//#region src/controls/rich-text/index.ts
|
|
4
4
|
/**
|
|
5
5
|
* Rich text: registers the control and its label-row action (one line each, so lanes merge cleanly).
|
|
6
6
|
* Imported for its side effect by whatever loads the kit's controls; import the parts themselves by path.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/controls/rich-text/index.ts"],"sourcesContent":["/**\n * Rich text: registers the control and its label-row action (one line each, so lanes merge cleanly).\n * Imported for its side effect by whatever loads the kit's controls; import the parts themselves by path.\n */\nimport { ACTIONS, CONTROLS } from \"../../engine/kit-field\";\nimport { RichTextControl, RichTextExpandAction } from \"./control\";\n\nCONTROLS.richtext = RichTextControl;\nACTIONS.richtext = RichTextExpandAction;\n"],"mappings":";;;;;;;AAOA,SAAS,WAAW;AACpB,QAAQ,WAAW"}
|
|
@@ -4,10 +4,12 @@ export interface TextLink {
|
|
|
4
4
|
}
|
|
5
5
|
/** An address a link may carry: http(s), mailto, tel, a site path or an in-page anchor. */
|
|
6
6
|
export declare function linkProblem(href: string): string | null;
|
|
7
|
-
export declare function LinkForm({ initial, allowNewTab, onSave, onCancel, onDetach, }: {
|
|
7
|
+
export declare function LinkForm({ initial, allowNewTab, onSave, onCancel, onDetach, dirty, }: {
|
|
8
8
|
initial: TextLink;
|
|
9
9
|
allowNewTab: boolean;
|
|
10
10
|
onSave: (v: TextLink) => void;
|
|
11
11
|
onCancel: () => void;
|
|
12
12
|
onDetach?: () => void;
|
|
13
|
+
/** something the host draws beside the form changed (a button's label), so Apply has something to save */
|
|
14
|
+
dirty?: boolean;
|
|
13
15
|
}): import("react/jsx-runtime").JSX.Element;
|