@bettercms-ai/kit 1.0.0 → 2.0.0-next.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +33 -0
- package/dist/adapters/dock-values.d.ts +28 -0
- package/dist/adapters/dock-values.js +41 -0
- package/dist/adapters/dock-values.js.map +1 -0
- package/{adapters → dist/adapters}/icons.js +2 -2
- package/dist/adapters/icons.js.map +1 -0
- package/{adapters → dist/adapters}/lossy.d.ts +94 -31
- package/dist/adapters/lossy.js +419 -0
- package/dist/adapters/lossy.js.map +1 -0
- package/{adapters → dist/adapters}/prod-types.d.ts +91 -26
- package/{adapters → dist/adapters}/prod-types.js +82 -13
- package/dist/adapters/prod-types.js.map +1 -0
- package/{adapters → dist/adapters}/schema.d.ts +40 -1
- package/{adapters → dist/adapters}/schema.js +1038 -204
- package/dist/adapters/schema.js.map +1 -0
- package/{adapters → dist/adapters}/values.d.ts +26 -5
- package/{adapters → dist/adapters}/values.js +87 -17
- package/dist/adapters/values.js.map +1 -0
- package/dist/brand/logo.js +96 -0
- package/dist/brand/logo.js.map +1 -0
- package/{context.d.ts → dist/context.d.ts} +131 -2
- package/{context.js → dist/context.js} +44 -2
- package/dist/context.js.map +1 -0
- package/{controls → dist/controls}/button.d.ts +19 -5
- package/{controls → dist/controls}/button.js +125 -54
- package/dist/controls/button.js.map +1 -0
- package/{controls → dist/controls}/c1.js +1 -1
- package/dist/controls/c1.js.map +1 -0
- package/{controls → dist/controls}/c2.js +1 -1
- package/dist/controls/c2.js.map +1 -0
- package/{controls → dist/controls}/choice.d.ts +7 -2
- package/{controls → dist/controls}/choice.js +71 -18
- package/dist/controls/choice.js.map +1 -0
- package/{controls → dist/controls}/code-register.js +1 -1
- package/dist/controls/code-register.js.map +1 -0
- package/{controls → dist/controls}/code.js +10 -9
- package/dist/controls/code.js.map +1 -0
- package/{controls → dist/controls}/color.js +8 -8
- package/dist/controls/color.js.map +1 -0
- package/{controls → dist/controls}/component-services.d.ts +42 -0
- package/dist/controls/component-services.js +7 -0
- package/dist/controls/component-services.js.map +1 -0
- package/{controls → dist/controls}/date-register.js +1 -1
- package/dist/controls/date-register.js.map +1 -0
- package/{controls → dist/controls}/date-zone.js +8 -2
- package/dist/controls/date-zone.js.map +1 -0
- package/{controls → dist/controls}/date.js +32 -24
- package/dist/controls/date.js.map +1 -0
- package/dist/controls/form-picker-register.d.ts +7 -0
- package/{controls → dist/controls}/form-picker-register.js +2 -6
- package/dist/controls/form-picker-register.js.map +1 -0
- package/{controls → dist/controls}/form-picker.js +11 -9
- package/dist/controls/form-picker.js.map +1 -0
- package/{controls → dist/controls}/icon-register.js +1 -1
- package/dist/controls/icon-register.js.map +1 -0
- package/{controls → dist/controls}/icon.d.ts +4 -2
- package/{controls → dist/controls}/icon.js +32 -27
- package/dist/controls/icon.js.map +1 -0
- package/{controls → dist/controls}/index.d.ts +1 -1
- package/{controls → dist/controls}/index.js +4 -3
- package/dist/controls/index.js.map +1 -0
- package/{controls → dist/controls}/json-register.js +1 -1
- package/dist/controls/json-register.js.map +1 -0
- package/{controls → dist/controls}/json.js +13 -3
- package/dist/controls/json.js.map +1 -0
- package/{controls → dist/controls}/link.js +116 -200
- package/dist/controls/link.js.map +1 -0
- package/{controls → dist/controls}/location-register.js +1 -1
- package/dist/controls/location-register.js.map +1 -0
- package/{controls → dist/controls}/location.js +59 -40
- package/dist/controls/location.js.map +1 -0
- package/{controls → dist/controls}/media-register.js +1 -1
- package/dist/controls/media-register.js.map +1 -0
- package/{controls → dist/controls}/media-services.d.ts +6 -0
- package/dist/controls/media-services.js +0 -0
- package/{controls → dist/controls}/media.d.ts +21 -4
- package/{controls → dist/controls}/media.js +407 -130
- package/dist/controls/media.js.map +1 -0
- package/{controls → dist/controls}/number.js +10 -9
- package/dist/controls/number.js.map +1 -0
- package/{controls → dist/controls}/reference-register.js +1 -1
- package/dist/controls/reference-register.js.map +1 -0
- package/{controls → dist/controls}/reference-services.d.ts +4 -0
- package/dist/controls/reference-services.js +0 -0
- package/{controls → dist/controls}/reference.d.ts +1 -1
- package/{controls → dist/controls}/reference.js +93 -77
- package/dist/controls/reference.js.map +1 -0
- package/dist/controls/rich-text/article-shell.d.ts +145 -0
- package/dist/controls/rich-text/article-shell.js +510 -0
- package/dist/controls/rich-text/article-shell.js.map +1 -0
- package/dist/controls/rich-text/author.d.ts +25 -0
- package/dist/controls/rich-text/author.js +104 -0
- package/dist/controls/rich-text/author.js.map +1 -0
- package/dist/controls/rich-text/blocks.d.ts +60 -0
- package/{controls → dist/controls}/rich-text/blocks.js +164 -389
- package/dist/controls/rich-text/blocks.js.map +1 -0
- package/dist/controls/rich-text/button.d.ts +23 -0
- package/dist/controls/rich-text/button.js +85 -0
- package/dist/controls/rich-text/button.js.map +1 -0
- package/{controls → dist/controls}/rich-text/catalog.d.ts +7 -4
- package/{controls → dist/controls}/rich-text/catalog.js +94 -68
- package/dist/controls/rich-text/catalog.js.map +1 -0
- package/dist/controls/rich-text/checklist.d.ts +24 -0
- package/dist/controls/rich-text/checklist.js +115 -0
- package/dist/controls/rich-text/checklist.js.map +1 -0
- package/{controls → dist/controls}/rich-text/codec.d.ts +9 -1
- package/{controls → dist/controls}/rich-text/codec.js +7 -2
- package/dist/controls/rich-text/codec.js.map +1 -0
- package/dist/controls/rich-text/columns.d.ts +41 -0
- package/dist/controls/rich-text/columns.js +181 -0
- package/dist/controls/rich-text/columns.js.map +1 -0
- package/{controls → dist/controls}/rich-text/component-card.d.ts +1 -1
- package/{controls → dist/controls}/rich-text/component-card.js +417 -99
- package/dist/controls/rich-text/component-card.js.map +1 -0
- package/dist/controls/rich-text/component-panel.d.ts +47 -0
- package/dist/controls/rich-text/component-panel.js +141 -0
- package/dist/controls/rich-text/component-panel.js.map +1 -0
- package/{controls → dist/controls}/rich-text/control.d.ts +1 -2
- package/{controls → dist/controls}/rich-text/control.js +84 -42
- package/dist/controls/rich-text/control.js.map +1 -0
- package/{controls → dist/controls}/rich-text/dom.d.ts +53 -9
- package/{controls → dist/controls}/rich-text/dom.js +388 -50
- package/dist/controls/rich-text/dom.js.map +1 -0
- package/{controls → dist/controls}/rich-text/editor.d.ts +7 -0
- package/{controls → dist/controls}/rich-text/editor.js +226 -44
- package/dist/controls/rich-text/editor.js.map +1 -0
- package/dist/controls/rich-text/embed.d.ts +28 -0
- package/dist/controls/rich-text/embed.js +210 -0
- package/dist/controls/rich-text/embed.js.map +1 -0
- package/{controls → dist/controls}/rich-text/floating.d.ts +6 -1
- package/{controls → dist/controls}/rich-text/floating.js +35 -18
- package/dist/controls/rich-text/floating.js.map +1 -0
- package/dist/controls/rich-text/footnote.d.ts +41 -0
- package/dist/controls/rich-text/footnote.js +185 -0
- package/dist/controls/rich-text/footnote.js.map +1 -0
- package/dist/controls/rich-text/gallery.d.ts +28 -0
- package/dist/controls/rich-text/gallery.js +167 -0
- package/dist/controls/rich-text/gallery.js.map +1 -0
- package/{controls → dist/controls}/rich-text/index.js +1 -1
- package/dist/controls/rich-text/index.js.map +1 -0
- package/{controls → dist/controls}/rich-text/link-form.d.ts +3 -1
- package/dist/controls/rich-text/link-form.js +147 -0
- package/dist/controls/rich-text/link-form.js.map +1 -0
- package/{controls → dist/controls}/rich-text/markdown.js +4 -2
- package/dist/controls/rich-text/markdown.js.map +1 -0
- package/{controls → dist/controls}/rich-text/ops.js +17 -15
- package/dist/controls/rich-text/ops.js.map +1 -0
- package/dist/controls/rich-text/plain.d.ts +17 -0
- package/dist/controls/rich-text/plain.js +44 -0
- package/dist/controls/rich-text/plain.js.map +1 -0
- package/dist/controls/rich-text/related.d.ts +36 -0
- package/dist/controls/rich-text/related.js +213 -0
- package/dist/controls/rich-text/related.js.map +1 -0
- package/dist/controls/rich-text/toc.d.ts +46 -0
- package/dist/controls/rich-text/toc.js +161 -0
- package/dist/controls/rich-text/toc.js.map +1 -0
- package/{controls → dist/controls}/rich-text/toolbar.d.ts +6 -2
- package/{controls → dist/controls}/rich-text/toolbar.js +12 -7
- package/dist/controls/rich-text/toolbar.js.map +1 -0
- package/{controls → dist/controls}/scale.js +5 -5
- package/dist/controls/scale.js.map +1 -0
- package/dist/controls/slot-register.d.ts +6 -0
- package/{controls → dist/controls}/slot-register.js +2 -5
- package/dist/controls/slot-register.js.map +1 -0
- package/{controls → dist/controls}/slot-services.d.ts +25 -0
- package/dist/controls/slot-services.js +155 -0
- package/dist/controls/slot-services.js.map +1 -0
- package/{controls → dist/controls}/slot.js +42 -24
- package/dist/controls/slot.js.map +1 -0
- package/{controls → dist/controls}/table/index.js +1 -1
- package/dist/controls/table/index.js.map +1 -0
- package/{controls → dist/controls}/table/prod.js +3 -3
- package/dist/controls/table/prod.js.map +1 -0
- package/{controls → dist/controls}/table/refs.js +13 -2
- package/dist/controls/table/refs.js.map +1 -0
- package/{controls → dist/controls}/table/stored.js +1 -1
- package/dist/controls/table/stored.js.map +1 -0
- package/{controls → dist/controls}/table/table-editor.js +51 -48
- package/dist/controls/table/table-editor.js.map +1 -0
- package/{controls → dist/controls}/table/table-link.js +3 -3
- package/dist/controls/table/table-link.js.map +1 -0
- package/{controls → dist/controls}/table/table.js +3 -3
- package/dist/controls/table/table.js.map +1 -0
- package/{controls → dist/controls}/text.d.ts +2 -2
- package/{controls → dist/controls}/text.js +78 -43
- package/dist/controls/text.js.map +1 -0
- package/dist/controls/unknown-value.d.ts +17 -0
- package/dist/controls/unknown-value.js +66 -0
- package/dist/controls/unknown-value.js.map +1 -0
- package/dist/core/core.d.ts +70 -0
- package/dist/core/core.js +187 -0
- package/dist/core/core.js.map +1 -0
- package/dist/core/facets.d.ts +355 -0
- package/dist/core/facets.js +342 -0
- package/dist/core/facets.js.map +1 -0
- package/dist/core/index.d.ts +3 -0
- package/dist/core/index.js +3 -0
- package/{engine → dist/engine}/array.js +34 -21
- package/dist/engine/array.js.map +1 -0
- package/{engine → dist/engine}/bits.js +1 -1
- package/dist/engine/bits.js.map +1 -0
- package/{engine → dist/engine}/breadcrumb.d.ts +3 -3
- package/{engine → dist/engine}/breadcrumb.js +12 -36
- package/dist/engine/breadcrumb.js.map +1 -0
- package/{engine → dist/engine}/expand.d.ts +2 -4
- package/{engine → dist/engine}/expand.js +5 -22
- package/dist/engine/expand.js.map +1 -0
- package/{engine → dist/engine}/field-list.js +1 -1
- package/dist/engine/field-list.js.map +1 -0
- package/{engine → dist/engine}/field-shell.js +249 -121
- package/dist/engine/field-shell.js.map +1 -0
- package/{engine → dist/engine}/frame.d.ts +3 -1
- package/{engine → dist/engine}/frame.js +16 -14
- package/dist/engine/frame.js.map +1 -0
- package/{engine → dist/engine}/group-summary.d.ts +2 -1
- package/{engine → dist/engine}/group-summary.js +7 -3
- package/dist/engine/group-summary.js.map +1 -0
- package/{engine → dist/engine}/grouping.d.ts +19 -5
- package/{engine → dist/engine}/grouping.js +193 -21
- package/dist/engine/grouping.js.map +1 -0
- package/{engine → dist/engine}/item-list.d.ts +11 -1
- package/{engine → dist/engine}/item-list.js +35 -13
- package/dist/engine/item-list.js.map +1 -0
- package/{engine → dist/engine}/kit-field.js +45 -10
- package/dist/engine/kit-field.js.map +1 -0
- package/{engine → dist/engine}/schema-form.d.ts +27 -2
- package/{engine → dist/engine}/schema-form.js +182 -40
- package/dist/engine/schema-form.js.map +1 -0
- package/{engine → dist/engine}/slot.js +5 -15
- package/dist/engine/slot.js.map +1 -0
- package/dist/index.js +58 -0
- package/dist/index.js.map +1 -0
- package/{kit.css → dist/kit.css} +19 -0
- package/{lib → dist/lib}/cn.js +7 -4
- package/dist/lib/cn.js.map +1 -0
- package/{lib → dist/lib}/columns.js +4 -1
- package/dist/lib/columns.js.map +1 -0
- package/{lib → dist/lib}/frames.js +2 -2
- package/dist/lib/frames.js.map +1 -0
- package/dist/lib/icon-image.d.ts +10 -0
- package/dist/lib/icon-image.js +8 -0
- package/dist/lib/icon-image.js.map +1 -0
- package/{lib → dist/lib}/icons.js +4 -3
- package/dist/lib/icons.js.map +1 -0
- package/dist/lib/input-modality.d.ts +11 -0
- package/dist/lib/input-modality.js +47 -0
- package/dist/lib/input-modality.js.map +1 -0
- package/dist/lib/key-event.d.ts +11 -0
- package/dist/lib/key-event.js +16 -0
- package/dist/lib/key-event.js.map +1 -0
- package/{lib → dist/lib}/path.js +4 -2
- package/dist/lib/path.js.map +1 -0
- package/{lib → dist/lib}/schema.d.ts +34 -3
- package/{lib → dist/lib}/schema.js +110 -13
- package/dist/lib/schema.js.map +1 -0
- package/{lib → dist/lib}/utils.js +1 -1
- package/dist/lib/utils.js.map +1 -0
- package/{lib → dist/lib}/validate.d.ts +11 -1
- package/{lib → dist/lib}/validate.js +85 -11
- package/dist/lib/validate.js.map +1 -0
- package/dist/library/analysis.d.ts +23 -0
- package/dist/library/analysis.js +160 -0
- package/dist/library/analysis.js.map +1 -0
- package/dist/library/catalog.d.ts +57 -0
- package/dist/library/catalog.js +307 -0
- package/dist/library/catalog.js.map +1 -0
- package/dist/library/coreNotes.d.ts +8 -0
- package/dist/library/coreNotes.js +111 -0
- package/dist/library/coreNotes.js.map +1 -0
- package/dist/library/coverage.d.ts +40 -0
- package/dist/library/coverage.js +59 -0
- package/dist/library/coverage.js.map +1 -0
- package/dist/library/entries/advanced.entries.d.ts +2 -0
- package/dist/library/entries/advanced.entries.js +6579 -0
- package/dist/library/entries/advanced.entries.js.map +1 -0
- package/dist/library/entries/commerce.entries.d.ts +2 -0
- package/dist/library/entries/commerce.entries.js +4140 -0
- package/dist/library/entries/commerce.entries.js.map +1 -0
- package/dist/library/entries/company.entries.d.ts +2 -0
- package/dist/library/entries/company.entries.js +2731 -0
- package/dist/library/entries/company.entries.js.map +1 -0
- package/dist/library/entries/conversion.entries.d.ts +2 -0
- package/dist/library/entries/conversion.entries.js +3707 -0
- package/dist/library/entries/conversion.entries.js.map +1 -0
- package/dist/library/entries/data.entries.d.ts +7 -0
- package/dist/library/entries/data.entries.js +4613 -0
- package/dist/library/entries/data.entries.js.map +1 -0
- package/dist/library/entries/events.entries.d.ts +2 -0
- package/dist/library/entries/events.entries.js +3428 -0
- package/dist/library/entries/events.entries.js.map +1 -0
- package/dist/library/entries/features.entries.d.ts +2 -0
- package/dist/library/entries/features.entries.js +3157 -0
- package/dist/library/entries/features.entries.js.map +1 -0
- package/dist/library/entries/heroes.entries.d.ts +2 -0
- package/dist/library/entries/heroes.entries.js +3401 -0
- package/dist/library/entries/heroes.entries.js.map +1 -0
- package/dist/library/entries/index.d.ts +3 -0
- package/dist/library/entries/index.js +35 -0
- package/dist/library/entries/index.js.map +1 -0
- package/dist/library/entries/listings.entries.d.ts +2 -0
- package/dist/library/entries/listings.entries.js +2976 -0
- package/dist/library/entries/listings.entries.js.map +1 -0
- package/dist/library/entries/longform.entries.d.ts +2 -0
- package/dist/library/entries/longform.entries.js +4227 -0
- package/dist/library/entries/longform.entries.js.map +1 -0
- package/dist/library/entries/media.entries.d.ts +2 -0
- package/dist/library/entries/media.entries.js +2781 -0
- package/dist/library/entries/media.entries.js.map +1 -0
- package/dist/library/entries/navigation.entries.d.ts +2 -0
- package/dist/library/entries/navigation.entries.js +4011 -0
- package/dist/library/entries/navigation.entries.js.map +1 -0
- package/dist/library/entries/pricing.entries.d.ts +2 -0
- package/dist/library/entries/pricing.entries.js +2383 -0
- package/dist/library/entries/pricing.entries.js.map +1 -0
- package/dist/library/entries/social-proof.entries.d.ts +2 -0
- package/dist/library/entries/social-proof.entries.js +2297 -0
- package/dist/library/entries/social-proof.entries.js.map +1 -0
- package/dist/library/examples/bento.d.ts +92 -0
- package/dist/library/examples/bento.js +201 -0
- package/dist/library/examples/bento.js.map +1 -0
- package/dist/library/examples/blocks.d.ts +14 -0
- package/dist/library/examples/blocks.js +313 -0
- package/dist/library/examples/blocks.js.map +1 -0
- package/dist/library/examples/faq.d.ts +28 -0
- package/dist/library/examples/faq.js +230 -0
- package/dist/library/examples/faq.js.map +1 -0
- package/dist/library/examples/hero.d.ts +43 -0
- package/dist/library/examples/hero.js +222 -0
- package/dist/library/examples/hero.js.map +1 -0
- package/dist/library/examples/index.d.ts +36 -0
- package/dist/library/examples/index.js +109 -0
- package/dist/library/examples/index.js.map +1 -0
- package/dist/library/examples/journalStory.d.ts +93 -0
- package/dist/library/examples/journalStory.js +338 -0
- package/dist/library/examples/journalStory.js.map +1 -0
- package/dist/library/examples/megaMenu.d.ts +134 -0
- package/dist/library/examples/megaMenu.js +442 -0
- package/dist/library/examples/megaMenu.js.map +1 -0
- package/dist/library/examples/pricing.d.ts +103 -0
- package/dist/library/examples/pricing.js +479 -0
- package/dist/library/examples/pricing.js.map +1 -0
- package/dist/library/examples/tabs.d.ts +87 -0
- package/dist/library/examples/tabs.js +180 -0
- package/dist/library/examples/tabs.js.map +1 -0
- package/dist/library/export.d.ts +42 -0
- package/dist/library/export.js +80 -0
- package/dist/library/export.js.map +1 -0
- package/dist/library/index.d.ts +13 -0
- package/dist/library/index.js +6 -0
- package/dist/library/kit-catalog.json +1511 -0
- package/dist/library/types.d.ts +42 -0
- package/dist/library/types.js +0 -0
- package/{schema → dist/schema}/adapters.js +1 -2
- package/dist/schema/adapters.js.map +1 -0
- package/{schema → dist/schema}/help.d.ts +2 -0
- package/{schema → dist/schema}/help.js +6 -4
- package/dist/schema/help.js.map +1 -0
- package/{schema → dist/schema}/scale.js +1 -1
- package/dist/schema/scale.js.map +1 -0
- package/{schema → dist/schema}/sources.js +1 -1
- package/dist/schema/sources.js.map +1 -0
- package/{schema → dist/schema}/table.js +11 -10
- package/dist/schema/table.js.map +1 -0
- package/{schema → dist/schema}/types.d.ts +36 -1
- package/{schema → dist/schema}/types.js +1 -1
- package/dist/schema/types.js.map +1 -0
- package/dist/styles.css +2 -0
- package/dist/table/table-view.d.ts +14 -0
- package/dist/table/table-view.js +140 -0
- package/dist/table/table-view.js.map +1 -0
- package/dist/table/table.css +73 -0
- package/dist/testing/corpus.d.ts +63 -0
- package/dist/testing/corpus.js +129 -0
- package/dist/testing/corpus.js.map +1 -0
- package/dist/testing/test-form.d.ts +11 -0
- package/dist/testing/test-form.js +38 -0
- package/dist/testing/test-form.js.map +1 -0
- package/dist/theme.css +345 -0
- package/dist/theme.d.ts +22 -0
- package/dist/theme.js +43 -0
- package/dist/theme.js.map +1 -0
- package/dist/tokens.css +542 -0
- package/dist/types.js +0 -0
- package/{ui → dist/ui}/action-tray.d.ts +1 -1
- package/{ui → dist/ui}/action-tray.js +20 -19
- package/dist/ui/action-tray.js.map +1 -0
- package/dist/ui/autocomplete.d.ts +58 -0
- package/dist/ui/autocomplete.js +194 -0
- package/dist/ui/autocomplete.js.map +1 -0
- package/{ui → dist/ui}/button.d.ts +3 -3
- package/{ui → dist/ui}/button.js +8 -11
- package/dist/ui/button.js.map +1 -0
- package/{ui → dist/ui}/choice-switch.js +1 -1
- package/dist/ui/choice-switch.js.map +1 -0
- package/{ui → dist/ui}/controls.js +51 -39
- package/dist/ui/controls.js.map +1 -0
- package/{ui → dist/ui}/display.d.ts +10 -3
- package/{ui → dist/ui}/display.js +57 -46
- package/dist/ui/display.js.map +1 -0
- package/{ui → dist/ui}/expanded-editor-modal.d.ts +2 -2
- package/{ui → dist/ui}/expanded-editor-modal.js +6 -6
- package/dist/ui/expanded-editor-modal.js.map +1 -0
- package/{ui → dist/ui}/field-context.js +1 -1
- package/dist/ui/field-context.js.map +1 -0
- package/{ui → dist/ui}/floating-panel.d.ts +1 -1
- package/{ui → dist/ui}/floating-panel.js +28 -12
- package/dist/ui/floating-panel.js.map +1 -0
- package/{ui → dist/ui}/index.d.ts +4 -0
- package/dist/ui/index.js +18 -0
- package/{ui → dist/ui}/input.d.ts +1 -1
- package/{ui → dist/ui}/input.js +9 -9
- package/dist/ui/input.js.map +1 -0
- package/{ui → dist/ui}/mode-bar.js +3 -3
- package/dist/ui/mode-bar.js.map +1 -0
- package/{ui → dist/ui}/overlay.d.ts +77 -5
- package/dist/ui/overlay.js +697 -0
- package/dist/ui/overlay.js.map +1 -0
- package/{ui → dist/ui}/path-crumbs.js +37 -3
- package/dist/ui/path-crumbs.js.map +1 -0
- package/{ui → dist/ui}/presence.js +2 -2
- package/dist/ui/presence.js.map +1 -0
- package/{ui → dist/ui}/select.js +89 -87
- package/dist/ui/select.js.map +1 -0
- package/{ui → dist/ui}/shortcut-hint.js +1 -1
- package/dist/ui/shortcut-hint.js.map +1 -0
- package/dist/ui/spinner.d.ts +24 -0
- package/dist/ui/spinner.js +42 -0
- package/dist/ui/spinner.js.map +1 -0
- package/dist/ui/split-button.d.ts +32 -0
- package/dist/ui/split-button.js +60 -0
- package/dist/ui/split-button.js.map +1 -0
- package/{ui → dist/ui}/surfaces.js +1 -1
- package/dist/ui/surfaces.js.map +1 -0
- package/dist/ui/tab.d.ts +38 -0
- package/dist/ui/tab.js +87 -0
- package/dist/ui/tab.js.map +1 -0
- package/dist/ui/toast.d.ts +20 -0
- package/dist/ui/toast.js +115 -0
- package/dist/ui/toast.js.map +1 -0
- package/{ui → dist/ui}/tooltip-root.d.ts +4 -3
- package/{ui → dist/ui}/tooltip-root.js +9 -8
- package/dist/ui/tooltip-root.js.map +1 -0
- package/{ui → dist/ui}/variants.js +1 -1
- package/dist/ui/variants.js.map +1 -0
- package/package.json +83 -23
- package/adapters/icons.js.map +0 -1
- package/adapters/lossy.js +0 -233
- package/adapters/lossy.js.map +0 -1
- package/adapters/prod-types.js.map +0 -1
- package/adapters/schema.js.map +0 -1
- package/adapters/values.js.map +0 -1
- package/brand/logo.js +0 -9
- package/brand/logo.js.map +0 -1
- package/context.js.map +0 -1
- package/controls/button.js.map +0 -1
- package/controls/c1.js.map +0 -1
- package/controls/c2.js.map +0 -1
- package/controls/choice.js.map +0 -1
- package/controls/code-register.js.map +0 -1
- package/controls/code.js.map +0 -1
- package/controls/color.js.map +0 -1
- package/controls/date-register.js.map +0 -1
- package/controls/date-zone.js.map +0 -1
- package/controls/date.js.map +0 -1
- package/controls/form-picker-register.d.ts +0 -1
- package/controls/form-picker-register.js.map +0 -1
- package/controls/form-picker.js.map +0 -1
- package/controls/icon-register.js.map +0 -1
- package/controls/icon.js.map +0 -1
- package/controls/index.js.map +0 -1
- package/controls/json-register.js.map +0 -1
- package/controls/json.js.map +0 -1
- package/controls/link.js.map +0 -1
- package/controls/location-register.js.map +0 -1
- package/controls/location.js.map +0 -1
- package/controls/media-register.js.map +0 -1
- package/controls/media.js.map +0 -1
- package/controls/number.js.map +0 -1
- package/controls/reference-register.js.map +0 -1
- package/controls/reference.js.map +0 -1
- package/controls/rich-text/blocks.d.ts +0 -28
- package/controls/rich-text/blocks.js.map +0 -1
- package/controls/rich-text/catalog.js.map +0 -1
- package/controls/rich-text/codec.js.map +0 -1
- package/controls/rich-text/component-card.js.map +0 -1
- package/controls/rich-text/control.js.map +0 -1
- package/controls/rich-text/dom.js.map +0 -1
- package/controls/rich-text/editor.js.map +0 -1
- package/controls/rich-text/floating.js.map +0 -1
- package/controls/rich-text/index.js.map +0 -1
- package/controls/rich-text/link-form.js +0 -111
- package/controls/rich-text/link-form.js.map +0 -1
- package/controls/rich-text/markdown.js.map +0 -1
- package/controls/rich-text/ops.js.map +0 -1
- package/controls/rich-text/toolbar.js.map +0 -1
- package/controls/scale.js.map +0 -1
- package/controls/slot-register.d.ts +0 -1
- package/controls/slot-register.js.map +0 -1
- package/controls/slot-services.js +0 -38
- package/controls/slot-services.js.map +0 -1
- package/controls/slot.js.map +0 -1
- package/controls/table/index.js.map +0 -1
- package/controls/table/prod.js.map +0 -1
- package/controls/table/refs.js.map +0 -1
- package/controls/table/stored.js.map +0 -1
- package/controls/table/table-editor.js.map +0 -1
- package/controls/table/table-link.js.map +0 -1
- package/controls/table/table.js.map +0 -1
- package/controls/text.js.map +0 -1
- package/engine/array.js.map +0 -1
- package/engine/bits.js.map +0 -1
- package/engine/breadcrumb.js.map +0 -1
- package/engine/expand.js.map +0 -1
- package/engine/field-list.js.map +0 -1
- package/engine/field-shell.js.map +0 -1
- package/engine/frame.js.map +0 -1
- package/engine/group-summary.js.map +0 -1
- package/engine/grouping.js.map +0 -1
- package/engine/item-list.js.map +0 -1
- package/engine/kit-field.js.map +0 -1
- package/engine/schema-form.js.map +0 -1
- package/engine/slot.js.map +0 -1
- package/index.js +0 -55
- package/index.js.map +0 -1
- package/lib/cn.js.map +0 -1
- package/lib/columns.js.map +0 -1
- package/lib/frames.js.map +0 -1
- package/lib/icons.js.map +0 -1
- package/lib/path.js.map +0 -1
- package/lib/schema.js.map +0 -1
- package/lib/utils.js.map +0 -1
- package/lib/validate.js.map +0 -1
- package/schema/adapters.js.map +0 -1
- package/schema/help.js.map +0 -1
- package/schema/scale.js.map +0 -1
- package/schema/sources.js.map +0 -1
- package/schema/table.js.map +0 -1
- package/schema/types.js.map +0 -1
- package/ui/action-tray.js.map +0 -1
- package/ui/button.js.map +0 -1
- package/ui/choice-switch.js.map +0 -1
- package/ui/controls.js.map +0 -1
- package/ui/display.js.map +0 -1
- package/ui/expanded-editor-modal.js.map +0 -1
- package/ui/field-context.js.map +0 -1
- package/ui/floating-panel.js.map +0 -1
- package/ui/index.js +0 -13
- package/ui/input.js.map +0 -1
- package/ui/mode-bar.js.map +0 -1
- package/ui/overlay.js +0 -378
- package/ui/overlay.js.map +0 -1
- package/ui/path-crumbs.js.map +0 -1
- package/ui/presence.js.map +0 -1
- package/ui/select.js.map +0 -1
- package/ui/shortcut-hint.js.map +0 -1
- package/ui/surfaces.js.map +0 -1
- package/ui/tooltip-root.js.map +0 -1
- package/ui/variants.js.map +0 -1
- /package/{_virtual → dist/_virtual}/_rolldown/runtime.js +0 -0
- /package/{adapters → dist/adapters}/icons.d.ts +0 -0
- /package/{brand → dist/brand}/logo.d.ts +0 -0
- /package/{controls → dist/controls}/c1.d.ts +0 -0
- /package/{controls → dist/controls}/c2.d.ts +0 -0
- /package/{controls → dist/controls}/code-register.d.ts +0 -0
- /package/{controls → dist/controls}/code.d.ts +0 -0
- /package/{controls → dist/controls}/color.d.ts +0 -0
- /package/{controls → dist/controls}/date-register.d.ts +0 -0
- /package/{controls → dist/controls}/date-zone.d.ts +0 -0
- /package/{controls → dist/controls}/date.d.ts +0 -0
- /package/{controls → dist/controls}/form-picker.d.ts +0 -0
- /package/{controls → dist/controls}/icon-register.d.ts +0 -0
- /package/{controls → dist/controls}/json-register.d.ts +0 -0
- /package/{controls → dist/controls}/json.d.ts +0 -0
- /package/{controls → dist/controls}/link.d.ts +0 -0
- /package/{controls → dist/controls}/location-register.d.ts +0 -0
- /package/{controls → dist/controls}/location.d.ts +0 -0
- /package/{controls → dist/controls}/media-register.d.ts +0 -0
- /package/{controls → dist/controls}/number.d.ts +0 -0
- /package/{controls → dist/controls}/reference-register.d.ts +0 -0
- /package/{controls → dist/controls}/rich-text/index.d.ts +0 -0
- /package/{controls → dist/controls}/rich-text/markdown.d.ts +0 -0
- /package/{controls → dist/controls}/rich-text/ops.d.ts +0 -0
- /package/{controls → dist/controls}/scale.d.ts +0 -0
- /package/{controls → dist/controls}/slot.d.ts +0 -0
- /package/{controls → dist/controls}/table/index.d.ts +0 -0
- /package/{controls → dist/controls}/table/prod.d.ts +0 -0
- /package/{controls → dist/controls}/table/refs.d.ts +0 -0
- /package/{controls → dist/controls}/table/stored.d.ts +0 -0
- /package/{controls → dist/controls}/table/table-editor.d.ts +0 -0
- /package/{controls → dist/controls}/table/table-link.d.ts +0 -0
- /package/{controls → dist/controls}/table/table.d.ts +0 -0
- /package/{engine → dist/engine}/array.d.ts +0 -0
- /package/{engine → dist/engine}/bits.d.ts +0 -0
- /package/{engine → dist/engine}/field-list.d.ts +0 -0
- /package/{engine → dist/engine}/field-shell.d.ts +0 -0
- /package/{engine → dist/engine}/kit-field.d.ts +0 -0
- /package/{engine → dist/engine}/slot.d.ts +0 -0
- /package/{index.d.ts → dist/index.d.ts} +0 -0
- /package/{lib → dist/lib}/cn.d.ts +0 -0
- /package/{lib → dist/lib}/columns.d.ts +0 -0
- /package/{lib → dist/lib}/frames.d.ts +0 -0
- /package/{lib → dist/lib}/icons.d.ts +0 -0
- /package/{lib → dist/lib}/path.d.ts +0 -0
- /package/{lib → dist/lib}/utils.d.ts +0 -0
- /package/{schema → dist/schema}/adapters.d.ts +0 -0
- /package/{schema → dist/schema}/scale.d.ts +0 -0
- /package/{schema → dist/schema}/sources.d.ts +0 -0
- /package/{schema → dist/schema}/table.d.ts +0 -0
- /package/{types.d.ts → dist/types.d.ts} +0 -0
- /package/{ui → dist/ui}/choice-switch.d.ts +0 -0
- /package/{ui → dist/ui}/controls.d.ts +0 -0
- /package/{ui → dist/ui}/field-context.d.ts +0 -0
- /package/{ui → dist/ui}/mode-bar.d.ts +0 -0
- /package/{ui → dist/ui}/path-crumbs.d.ts +0 -0
- /package/{ui → dist/ui}/presence.d.ts +0 -0
- /package/{ui → dist/ui}/select.d.ts +0 -0
- /package/{ui → dist/ui}/shortcut-hint.d.ts +0 -0
- /package/{ui → dist/ui}/surfaces.d.ts +0 -0
- /package/{ui → dist/ui}/variants.d.ts +0 -0
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { Button } from "../../ui/button.js";
|
|
2
|
+
import { Switch } from "../../ui/controls.js";
|
|
3
|
+
import { Input } from "../../ui/input.js";
|
|
4
|
+
import { LinkLine, normLink } from "../link.js";
|
|
5
|
+
import * as React from "react";
|
|
6
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
import { IconLink } from "@tabler/icons-react";
|
|
8
|
+
//#region src/controls/rich-text/link-form.tsx
|
|
9
|
+
/**
|
|
10
|
+
* RICH TEXT · the link popover's body for a link inside the text, in V2's link panel chrome (controls/link.tsx
|
|
11
|
+
* LinkPopoverBody: what it links to now · the address · Remove link · Cancel · Apply): the address, and "Open in new tab"
|
|
12
|
+
* when the field allows it. A text link stores its address and target only (production's link mark), so V2's link type
|
|
13
|
+
* select and rel choice, which belong to the link FIELD, are not offered here.
|
|
14
|
+
*/
|
|
15
|
+
/** An address a link may carry: http(s), mailto, tel, a site path or an in-page anchor. */
|
|
16
|
+
function linkProblem(href) {
|
|
17
|
+
const h = href.trim();
|
|
18
|
+
if (!h) return "Add an address first.";
|
|
19
|
+
if (/^(https?:\/\/[^\s]+|mailto:[^\s]+|tel:[+\d][\d\s()-]*|\/(?!\/)[^\s]*|#[^\s]+)$/i.test(h)) return null;
|
|
20
|
+
if (/^[a-z][a-z0-9+.-]*:/i.test(h)) return "Use an address that starts with https://, mailto: or tel:.";
|
|
21
|
+
if (/^[^\s/]+\.[^\s]+$/.test(h)) return `Add https:// in front: https://${h}`;
|
|
22
|
+
return "Use a full address (https://…), a page path (/about) or an anchor (#section).";
|
|
23
|
+
}
|
|
24
|
+
function LinkForm({ initial, allowNewTab, onSave, onCancel, onDetach, dirty = false }) {
|
|
25
|
+
const [href, setHref] = React.useState(initial.href);
|
|
26
|
+
const [newTab, setNewTab] = React.useState(!!initial.newTab);
|
|
27
|
+
const [problem, setProblem] = React.useState(null);
|
|
28
|
+
const urlId = React.useId();
|
|
29
|
+
const tabId = React.useId();
|
|
30
|
+
const errId = React.useId();
|
|
31
|
+
const start = initial.href.trim();
|
|
32
|
+
const changed = dirty || href.trim() !== start || allowNewTab && newTab !== !!initial.newTab;
|
|
33
|
+
const ok = !linkProblem(href);
|
|
34
|
+
return /* @__PURE__ */ jsxs("form", {
|
|
35
|
+
className: "flex flex-col gap-3",
|
|
36
|
+
onSubmit: (e) => {
|
|
37
|
+
e.preventDefault();
|
|
38
|
+
const p = linkProblem(href);
|
|
39
|
+
setProblem(p);
|
|
40
|
+
if (!p) onSave({
|
|
41
|
+
href: href.trim(),
|
|
42
|
+
newTab: allowNewTab && newTab
|
|
43
|
+
});
|
|
44
|
+
},
|
|
45
|
+
children: [
|
|
46
|
+
/* @__PURE__ */ jsxs("div", {
|
|
47
|
+
className: "flex min-w-0 flex-col gap-1",
|
|
48
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
49
|
+
className: "text-kit-sm font-medium text-kit-fg",
|
|
50
|
+
children: "Link"
|
|
51
|
+
}), start ? /* @__PURE__ */ jsx("span", {
|
|
52
|
+
className: "flex min-w-0 text-kit-fg-2",
|
|
53
|
+
children: /* @__PURE__ */ jsx(LinkLine, { v: normLink({
|
|
54
|
+
href: start,
|
|
55
|
+
newTab: !!initial.newTab
|
|
56
|
+
}) })
|
|
57
|
+
}) : /* @__PURE__ */ jsx("span", {
|
|
58
|
+
className: "text-kit-xs text-kit-fg-3",
|
|
59
|
+
children: "No link yet"
|
|
60
|
+
})]
|
|
61
|
+
}),
|
|
62
|
+
/* @__PURE__ */ jsxs("div", {
|
|
63
|
+
className: "flex flex-col gap-1.5",
|
|
64
|
+
onBlur: (e) => {
|
|
65
|
+
if (!e.currentTarget.contains(e.relatedTarget) && href.trim()) setProblem(linkProblem(href));
|
|
66
|
+
},
|
|
67
|
+
children: [
|
|
68
|
+
/* @__PURE__ */ jsx("label", {
|
|
69
|
+
htmlFor: urlId,
|
|
70
|
+
className: "text-kit-xs text-kit-fg-2",
|
|
71
|
+
children: "Link to"
|
|
72
|
+
}),
|
|
73
|
+
/* @__PURE__ */ jsx(Input, {
|
|
74
|
+
id: urlId,
|
|
75
|
+
autoFocus: true,
|
|
76
|
+
size: "sm",
|
|
77
|
+
value: href,
|
|
78
|
+
onChange: (e) => {
|
|
79
|
+
setHref(e.target.value);
|
|
80
|
+
if (problem) setProblem(null);
|
|
81
|
+
},
|
|
82
|
+
onKeyDown: (e) => {
|
|
83
|
+
if (e.key === "Enter" && !ok) {
|
|
84
|
+
e.preventDefault();
|
|
85
|
+
setProblem(linkProblem(href));
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
placeholder: "https://… or /page",
|
|
89
|
+
leading: /* @__PURE__ */ jsx(IconLink, { stroke: 1.5 }),
|
|
90
|
+
"aria-invalid": problem ? true : void 0,
|
|
91
|
+
"aria-describedby": problem ? errId : void 0
|
|
92
|
+
}),
|
|
93
|
+
problem ? /* @__PURE__ */ jsx("p", {
|
|
94
|
+
id: errId,
|
|
95
|
+
role: "alert",
|
|
96
|
+
className: "text-kit-xs text-kit-danger-fg",
|
|
97
|
+
children: problem
|
|
98
|
+
}) : null
|
|
99
|
+
]
|
|
100
|
+
}),
|
|
101
|
+
allowNewTab ? /* @__PURE__ */ jsxs("label", {
|
|
102
|
+
htmlFor: tabId,
|
|
103
|
+
className: "flex min-h-7 items-center justify-between gap-3",
|
|
104
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
105
|
+
className: "text-kit-xs text-kit-fg-2",
|
|
106
|
+
children: "Open in new tab"
|
|
107
|
+
}), /* @__PURE__ */ jsx(Switch, {
|
|
108
|
+
id: tabId,
|
|
109
|
+
size: "sm",
|
|
110
|
+
checked: newTab,
|
|
111
|
+
onCheckedChange: setNewTab
|
|
112
|
+
})]
|
|
113
|
+
}) : null,
|
|
114
|
+
/* @__PURE__ */ jsxs("div", {
|
|
115
|
+
className: "flex items-center gap-2 border-t border-kit-line pt-2.5",
|
|
116
|
+
children: [
|
|
117
|
+
onDetach ? /* @__PURE__ */ jsx(Button, {
|
|
118
|
+
type: "button",
|
|
119
|
+
size: "xs",
|
|
120
|
+
variant: "danger-ghost",
|
|
121
|
+
onClick: onDetach,
|
|
122
|
+
children: "Remove link"
|
|
123
|
+
}) : null,
|
|
124
|
+
/* @__PURE__ */ jsx("span", { className: "flex-1" }),
|
|
125
|
+
/* @__PURE__ */ jsx(Button, {
|
|
126
|
+
type: "button",
|
|
127
|
+
size: "xs",
|
|
128
|
+
variant: "ghost",
|
|
129
|
+
onClick: onCancel,
|
|
130
|
+
children: "Cancel"
|
|
131
|
+
}),
|
|
132
|
+
/* @__PURE__ */ jsx(Button, {
|
|
133
|
+
type: "submit",
|
|
134
|
+
size: "xs",
|
|
135
|
+
variant: "primary",
|
|
136
|
+
disabled: !changed || !ok,
|
|
137
|
+
children: "Apply"
|
|
138
|
+
})
|
|
139
|
+
]
|
|
140
|
+
})
|
|
141
|
+
]
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
//#endregion
|
|
145
|
+
export { LinkForm, linkProblem };
|
|
146
|
+
|
|
147
|
+
//# sourceMappingURL=link-form.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"link-form.js","names":[],"sources":["../../../src/controls/rich-text/link-form.tsx"],"sourcesContent":["/**\n * RICH TEXT · the link popover's body for a link inside the text, in V2's link panel chrome (controls/link.tsx\n * LinkPopoverBody: what it links to now · the address · Remove link · Cancel · Apply): the address, and \"Open in new tab\"\n * when the field allows it. A text link stores its address and target only (production's link mark), so V2's link type\n * select and rel choice, which belong to the link FIELD, are not offered here.\n */\nimport * as React from \"react\";\nimport { IconLink } from \"@tabler/icons-react\";\nimport { Button } from \"../../ui/button\";\nimport { Switch } from \"../../ui/controls\";\nimport { Input } from \"../../ui/input\";\nimport { LinkLine, normLink } from \"../link\";\n\nexport interface TextLink {\n href: string;\n newTab?: boolean;\n}\n\n/** An address a link may carry: http(s), mailto, tel, a site path or an in-page anchor. */\nexport function linkProblem(href: string): string | null {\n const h = href.trim();\n if (!h) return \"Add an address first.\";\n if (/^(https?:\\/\\/[^\\s]+|mailto:[^\\s]+|tel:[+\\d][\\d\\s()-]*|\\/(?!\\/)[^\\s]*|#[^\\s]+)$/i.test(h)) return null;\n if (/^[a-z][a-z0-9+.-]*:/i.test(h)) return \"Use an address that starts with https://, mailto: or tel:.\";\n if (/^[^\\s/]+\\.[^\\s]+$/.test(h)) return `Add https:// in front: https://${h}`;\n return \"Use a full address (https://…), a page path (/about) or an anchor (#section).\";\n}\n\nexport function LinkForm({\n initial,\n allowNewTab,\n onSave,\n onCancel,\n onDetach,\n dirty = false,\n}: {\n initial: TextLink;\n allowNewTab: boolean;\n onSave: (v: TextLink) => void;\n onCancel: () => void;\n onDetach?: () => void;\n /** something the host draws beside the form changed (a button's label), so Apply has something to save */\n dirty?: boolean;\n}) {\n const [href, setHref] = React.useState(initial.href);\n const [newTab, setNewTab] = React.useState(!!initial.newTab);\n const [problem, setProblem] = React.useState<string | null>(null);\n const urlId = React.useId();\n const tabId = React.useId();\n const errId = React.useId();\n const start = initial.href.trim();\n // V2 LinkPopoverBody (controls/link.tsx): Apply only when something changed and the link can be saved\n const changed = dirty || href.trim() !== start || (allowNewTab && newTab !== !!initial.newTab);\n const ok = !linkProblem(href);\n return (\n <form\n className=\"flex flex-col gap-3\"\n onSubmit={(e) => {\n e.preventDefault();\n const p = linkProblem(href);\n setProblem(p);\n if (!p) onSave({ href: href.trim(), newTab: allowNewTab && newTab });\n }}\n >\n <div className=\"flex min-w-0 flex-col gap-1\">\n <span className=\"text-kit-sm font-medium text-kit-fg\">Link</span>\n {start ? (\n <span className=\"flex min-w-0 text-kit-fg-2\">\n <LinkLine v={normLink({ href: start, newTab: !!initial.newTab })} />\n </span>\n ) : (\n <span className=\"text-kit-xs text-kit-fg-3\">No link yet</span>\n )}\n </div>\n <div\n className=\"flex flex-col gap-1.5\"\n onBlur={(e) => {\n if (!e.currentTarget.contains(e.relatedTarget as Node) && href.trim()) setProblem(linkProblem(href));\n }}\n >\n <label htmlFor={urlId} className=\"text-kit-xs text-kit-fg-2\">\n Link to\n </label>\n <Input\n id={urlId}\n autoFocus\n size=\"sm\"\n value={href}\n onChange={(e) => {\n setHref(e.target.value);\n if (problem) setProblem(null);\n }}\n onKeyDown={(e) => {\n // Apply is disabled while the address cannot be saved, so Enter says why instead of doing nothing\n if (e.key === \"Enter\" && !ok) {\n e.preventDefault();\n setProblem(linkProblem(href));\n }\n }}\n placeholder=\"https://… or /page\"\n leading={<IconLink stroke={1.5} />}\n aria-invalid={problem ? true : undefined}\n aria-describedby={problem ? errId : undefined}\n />\n {problem ? (\n <p id={errId} role=\"alert\" className=\"text-kit-xs text-kit-danger-fg\">\n {problem}\n </p>\n ) : null}\n </div>\n {allowNewTab ? (\n <label htmlFor={tabId} className=\"flex min-h-7 items-center justify-between gap-3\">\n <span className=\"text-kit-xs text-kit-fg-2\">Open in new tab</span>\n <Switch id={tabId} size=\"sm\" checked={newTab} onCheckedChange={setNewTab} />\n </label>\n ) : null}\n <div className=\"flex items-center gap-2 border-t border-kit-line pt-2.5\">\n {onDetach ? (\n <Button type=\"button\" size=\"xs\" variant=\"danger-ghost\" onClick={onDetach}>\n Remove link\n </Button>\n ) : null}\n <span className=\"flex-1\" />\n <Button type=\"button\" size=\"xs\" variant=\"ghost\" onClick={onCancel}>\n Cancel\n </Button>\n <Button type=\"submit\" size=\"xs\" variant=\"primary\" disabled={!changed || !ok}>\n Apply\n </Button>\n </div>\n </form>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { esc, escAttr, sanitize } from "./dom.js";
|
|
2
|
-
//#region src/
|
|
2
|
+
//#region src/controls/rich-text/markdown.ts
|
|
3
3
|
/**
|
|
4
4
|
* RICH TEXT · a small HTML ⇄ Markdown converter for the field's Markdown mode and for pasting (V2 HEAD
|
|
5
5
|
* controls/rich-text/markdown.ts). Covers headings, bold/italic/strike/underline, inline code, links, images, lists,
|
|
@@ -31,6 +31,8 @@ function inline(node, inCode = false) {
|
|
|
31
31
|
case "STRIKE":
|
|
32
32
|
case "DEL": return wrap("~~");
|
|
33
33
|
case "U": return `<u>${kids()}</u>`;
|
|
34
|
+
case "SUP": return el.matches("[data-footnote]") || el.querySelector(":scope > a[href*='-fn-']") ? kids() : `<sup>${kids()}</sup>`;
|
|
35
|
+
case "SUB": return `<sub>${kids()}</sub>`;
|
|
34
36
|
case "CODE": return "`" + (el.textContent ?? "").replace(/`/g, "") + "`";
|
|
35
37
|
case "BR": return " \n";
|
|
36
38
|
case "IMG": return ` ?? ""})`;
|
|
@@ -174,6 +176,6 @@ function markdownToHtml(md) {
|
|
|
174
176
|
/** Does pasted plain text look like Markdown worth converting into blocks? */
|
|
175
177
|
var looksLikeMarkdown = (t) => /\n\s*\n/.test(t) || /^(#{1,6}\s|[-*+]\s|\d+[.)]\s|>\s|```|---)/m.test(t) || /\*\*[^*]+\*\*|\[[^\]]+\]\([^)]+\)/.test(t);
|
|
176
178
|
//#endregion
|
|
177
|
-
export { htmlToMarkdown, looksLikeMarkdown, markdownToHtml };
|
|
179
|
+
export { htmlToMarkdown, inlineMd, looksLikeMarkdown, markdownToHtml };
|
|
178
180
|
|
|
179
181
|
//# sourceMappingURL=markdown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown.js","names":[],"sources":["../../../src/controls/rich-text/markdown.ts"],"sourcesContent":["/**\n * RICH TEXT · a small HTML ⇄ Markdown converter for the field's Markdown mode and for pasting (V2 HEAD\n * controls/rich-text/markdown.ts). Covers headings, bold/italic/strike/underline, inline code, links, images, lists,\n * quotes, code blocks, rules and paragraphs. Anything else is kept as one line of raw HTML, which the reverse direction\n * passes through untouched (and the field's own rules then decide whether it may stay).\n */\nimport { esc, escAttr, sanitize } from \"./dom\";\n\n/* ── HTML → Markdown ───────────────────────────────────────────────── */\nconst escText = (s: string) => s.replace(/([\\\\`*[\\]~])/g, \"\\\\$1\");\n\nfunction inline(node: Node, inCode = false): string {\n if (node.nodeType === 3) {\n const t = (node.textContent ?? \"\").replace(/ /g, \" \");\n return inCode ? t : escText(t.replace(/\\s+/g, \" \"));\n }\n if (node.nodeType !== 1) return \"\";\n const el = node as HTMLElement;\n const kids = () => Array.from(el.childNodes).map((c) => inline(c, inCode)).join(\"\");\n const wrap = (mark: string) => {\n const inner = kids();\n if (!inner.trim()) return inner;\n const lead = inner.match(/^\\s*/)![0];\n const trail = inner.match(/\\s*$/)![0];\n return `${lead}${mark}${inner.trim()}${mark}${trail}`;\n };\n switch (el.tagName) {\n case \"STRONG\":\n case \"B\":\n return wrap(\"**\");\n case \"EM\":\n case \"I\":\n return wrap(\"_\");\n case \"S\":\n case \"STRIKE\":\n case \"DEL\":\n return wrap(\"~~\");\n case \"U\":\n return `<u>${kids()}</u>`;\n // footnote markers are written elsewhere; a plain x² / x₂ stays inline HTML, which Markdown allows\n case \"SUP\":\n return el.matches(\"[data-footnote]\") || el.querySelector(\":scope > a[href*='-fn-']\") ? kids() : `<sup>${kids()}</sup>`;\n case \"SUB\":\n return `<sub>${kids()}</sub>`;\n case \"CODE\":\n return \"`\" + (el.textContent ?? \"\").replace(/`/g, \"\") + \"`\";\n case \"BR\":\n return \" \\n\";\n case \"IMG\":\n return ` ?? \"\"})`;\n case \"A\":\n // a link that carries more than its address (opens in a new tab) keeps its markup, so Markdown mode drops nothing\n if (el.hasAttribute(\"target\")) return el.outerHTML;\n return `[${kids()}](${el.getAttribute(\"href\") ?? \"\"})`;\n default:\n return kids();\n }\n}\n\nfunction list(el: HTMLElement): string | null {\n if (el.querySelector(\"ul ul, ul ol, ol ol, ol ul, li > p + p\")) return null;\n return Array.from(el.children)\n .filter((li) => li.tagName === \"LI\")\n .map((li, i) => (el.tagName === \"OL\" ? `${i + 1}. ` : \"- \") + inline(li).trim().replace(/ {2}\\n/g, \" \"))\n .join(\"\\n\");\n}\n\nexport function htmlToMarkdown(html: string): string {\n const doc = new DOMParser().parseFromString(`<body>${html}</body>`, \"text/html\");\n const out: string[] = [];\n for (const node of Array.from(doc.body.childNodes)) {\n if (node.nodeType === 3) {\n const t = inline(node).trim();\n if (t) out.push(t);\n continue;\n }\n if (node.nodeType !== 1) continue;\n const el = node as HTMLElement;\n const tag = el.tagName;\n const raw = () => out.push(el.outerHTML.replace(/\\n+/g, \" \"));\n if (/^H[1-6]$/.test(tag)) out.push(`${\"#\".repeat(Number(tag[1]))} ${inline(el).trim()}`);\n else if (tag === \"P\") {\n const s = inline(el).trim().replace(/^([#>]|\\d+\\.|[-+] |-{3})/, \"\\\\$1\");\n if (s) out.push(s);\n } else if (tag === \"UL\" || tag === \"OL\") {\n const l = list(el);\n if (l === null) raw();\n else out.push(l);\n } else if (tag === \"BLOCKQUOTE\") {\n const paras = el.querySelector(\"p,div\") ? Array.from(el.children).map((c) => inline(c).trim()) : [inline(el).trim()];\n out.push(paras.filter(Boolean).map((p) => p.split(\"\\n\").map((l) => `> ${l}`).join(\"\\n\")).join(\"\\n>\\n\"));\n } else if (tag === \"PRE\") out.push(\"```\\n\" + (el.textContent ?? \"\").replace(/\\n$/, \"\") + \"\\n```\");\n else if (tag === \"HR\") out.push(\"---\");\n else if (tag === \"FIGURE\" && el.querySelector(\":scope > img\")) {\n const img = el.querySelector(\"img\")!;\n const cap = el.querySelector(\"figcaption\")?.textContent?.trim();\n out.push(` ?? \"\"}${cap ? ` \"${cap.replace(/\"/g, \"'\")}\"` : \"\"})`);\n } else raw();\n }\n return out.join(\"\\n\\n\") + (out.length ? \"\\n\" : \"\");\n}\n\n/* ── Markdown → HTML ───────────────────────────────────────────────── */\nconst safeHref = (h: string) => (/^\\s*(javascript|vbscript|data:text)/i.test(h) ? \"#\" : h);\n\nexport function inlineMd(src: string): string {\n const slots: string[] = [];\n const hold = (html: string) => `\\u0000${slots.push(html) - 1}\\u0000`;\n let s = src.replace(/\\\\([\\\\`*_[\\]~#>+\\-.!])/g, (_, c: string) => hold(esc(c)));\n s = s.replace(/`([^`]+)`/g, (_, c: string) => hold(`<code>${esc(c)}</code>`));\n s = s.replace(/<a [^>]*>.*?<\\/a>/g, (m) => hold(m));\n s = esc(s);\n s = s.replace(/<(\\/?)u>/g, \"<$1u>\");\n s = s.replace(/!\\[([^\\]]*)\\]\\(([^)\\s]+)\\)/g, (_, a: string, u: string) => hold(`<img src=\"${escAttr(safeHref(u))}\" alt=\"${escAttr(a)}\">`));\n s = s.replace(/\\[([^\\]]+)\\]\\(([^)\\s]+)\\)/g, (_, t: string, u: string) => `<a href=\"${escAttr(safeHref(u))}\">${t}</a>`);\n s = s.replace(/\\*\\*([^*]+?)\\*\\*/g, \"<strong>$1</strong>\");\n s = s.replace(/__([^_]+?)__/g, \"<strong>$1</strong>\");\n s = s.replace(/(^|[^\\w*])\\*([^*\\s][^*]*?)\\*(?!\\*)/g, \"$1<em>$2</em>\");\n s = s.replace(/(^|[^\\w])_([^_\\s][^_]*?)_(?!\\w)/g, \"$1<em>$2</em>\");\n s = s.replace(/~~([^~]+?)~~/g, \"<s>$1</s>\");\n s = s.replace(/ {2,}\\n/g, \"<br>\").replace(/\\n/g, \" \");\n return s.replace(/\\u0000(\\d+)\\u0000/g, (_, i: string) => slots[Number(i)]);\n}\n\nconst RAW_BLOCK = /^<\\/?(div|table|figure|details|ul|ol|p|h[1-6]|blockquote|pre|hr|section|aside)\\b/i;\nconst RE = {\n fence: /^\\s*```/,\n heading: /^(#{1,6})\\s+(.*?)\\s*#*\\s*$/,\n hr: /^\\s*(-{3,}|\\*{3,}|_{3,})\\s*$/,\n image: /^!\\[([^\\]]*)\\]\\(([^)\\s]+)(?:\\s+\"([^\"]*)\")?\\)\\s*$/,\n quote: /^\\s*>/,\n ul: /^\\s*[-*+]\\s+(.*)$/,\n ol: /^\\s*\\d+[.)]\\s+(.*)$/,\n};\nconst startsBlock = (l: string) => RE.fence.test(l) || RE.heading.test(l) || RE.hr.test(l) || RE.quote.test(l) || RE.ul.test(l) || RE.ol.test(l) || RAW_BLOCK.test(l.trim());\n\n/** Throws on Markdown it cannot read (e.g. an unclosed code fence). */\nexport function markdownToHtml(md: string): string {\n const lines = md.replace(/\\r\\n?/g, \"\\n\").split(\"\\n\");\n const out: string[] = [];\n let i = 0;\n while (i < lines.length) {\n const line = lines[i];\n if (!line.trim()) {\n i++;\n continue;\n }\n if (RE.fence.test(line)) {\n const code: string[] = [];\n i++;\n while (i < lines.length && !RE.fence.test(lines[i])) code.push(lines[i++]);\n if (i >= lines.length) throw new Error(\"Unclosed code block\");\n i++;\n out.push(`<pre>${esc(code.join(\"\\n\"))}</pre>`);\n continue;\n }\n if (RAW_BLOCK.test(line.trim())) {\n const raw: string[] = [];\n while (i < lines.length && lines[i].trim()) raw.push(lines[i++]);\n out.push(raw.join(\" \"));\n continue;\n }\n let m = line.match(RE.heading);\n if (m) {\n out.push(`<h${m[1].length}>${inlineMd(m[2])}</h${m[1].length}>`);\n i++;\n continue;\n }\n if (RE.hr.test(line)) {\n out.push(\"<hr>\");\n i++;\n continue;\n }\n m = line.match(RE.image);\n if (m) {\n // an image keeps no caption in production rich text: a title becomes the line under it, never dropped\n out.push(`<figure><img src=\"${escAttr(safeHref(m[2]))}\" alt=\"${escAttr(m[1])}\"></figure>${m[3] ? `<p>${esc(m[3])}</p>` : \"\"}`);\n i++;\n continue;\n }\n if (RE.quote.test(line)) {\n const q: string[] = [];\n while (i < lines.length && RE.quote.test(lines[i])) q.push(lines[i++].replace(/^\\s*> ?/, \"\"));\n out.push(`<blockquote>${q.join(\"\\n\").split(/\\n\\s*\\n/).map(inlineMd).join(\"<br><br>\")}</blockquote>`);\n continue;\n }\n if (RE.ul.test(line) || RE.ol.test(line)) {\n const ordered = !RE.ul.test(line);\n const re = ordered ? RE.ol : RE.ul;\n const items: string[] = [];\n while (i < lines.length && re.test(lines[i])) items.push(`<li>${inlineMd(lines[i++].match(re)![1])}</li>`);\n out.push(ordered ? `<ol>${items.join(\"\")}</ol>` : `<ul>${items.join(\"\")}</ul>`);\n continue;\n }\n const para: string[] = [];\n while (i < lines.length && lines[i].trim() && (para.length === 0 || !startsBlock(lines[i]))) para.push(lines[i++]);\n out.push(`<p>${inlineMd(para.join(\"\\n\"))}</p>`);\n }\n return sanitize(out.join(\"\"));\n}\n\n/** Does pasted plain text look like Markdown worth converting into blocks? */\nexport const looksLikeMarkdown = (t: string) => /\\n\\s*\\n/.test(t) || /^(#{1,6}\\s|[-*+]\\s|\\d+[.)]\\s|>\\s|```|---)/m.test(t) || /\\*\\*[^*]+\\*\\*|\\[[^\\]]+\\]\\([^)]+\\)/.test(t);\n"],"mappings":";;;;;;;;AASA,IAAM,WAAW,MAAc,EAAE,QAAQ,iBAAiB,MAAM;AAEhE,SAAS,OAAO,MAAY,SAAS,OAAe;CAClD,IAAI,KAAK,aAAa,GAAG;EACvB,MAAM,KAAK,KAAK,eAAe,GAAA,CAAI,QAAQ,MAAM,GAAG;EACpD,OAAO,SAAS,IAAI,QAAQ,EAAE,QAAQ,QAAQ,GAAG,CAAC;CACpD;CACA,IAAI,KAAK,aAAa,GAAG,OAAO;CAChC,MAAM,KAAK;CACX,MAAM,aAAa,MAAM,KAAK,GAAG,UAAU,CAAC,CAAC,KAAK,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,EAAE;CAClF,MAAM,QAAQ,SAAiB;EAC7B,MAAM,QAAQ,KAAK;EACnB,IAAI,CAAC,MAAM,KAAK,GAAG,OAAO;EAC1B,MAAM,OAAO,MAAM,MAAM,MAAM,CAAC,CAAE;EAClC,MAAM,QAAQ,MAAM,MAAM,MAAM,CAAC,CAAE;EACnC,OAAO,GAAG,OAAO,OAAO,MAAM,KAAK,IAAI,OAAO;CAChD;CACA,QAAQ,GAAG,SAAX;EACE,KAAK;EACL,KAAK,KACH,OAAO,KAAK,IAAI;EAClB,KAAK;EACL,KAAK,KACH,OAAO,KAAK,GAAG;EACjB,KAAK;EACL,KAAK;EACL,KAAK,OACH,OAAO,KAAK,IAAI;EAClB,KAAK,KACH,OAAO,MAAM,KAAK,EAAE;EAEtB,KAAK,OACH,OAAO,GAAG,QAAQ,iBAAiB,KAAK,GAAG,cAAc,0BAA0B,IAAI,KAAK,IAAI,QAAQ,KAAK,EAAE;EACjH,KAAK,OACH,OAAO,QAAQ,KAAK,EAAE;EACxB,KAAK,QACH,OAAO,OAAO,GAAG,eAAe,GAAA,CAAI,QAAQ,MAAM,EAAE,IAAI;EAC1D,KAAK,MACH,OAAO;EACT,KAAK,OACH,OAAO,KAAK,GAAG,aAAa,KAAK,KAAK,GAAG,IAAI,GAAG,aAAa,KAAK,KAAK,GAAG;EAC5E,KAAK;GAEH,IAAI,GAAG,aAAa,QAAQ,GAAG,OAAO,GAAG;GACzC,OAAO,IAAI,KAAK,EAAE,IAAI,GAAG,aAAa,MAAM,KAAK,GAAG;EACtD,SACE,OAAO,KAAK;CAChB;AACF;AAEA,SAAS,KAAK,IAAgC;CAC5C,IAAI,GAAG,cAAc,wCAAwC,GAAG,OAAO;CACvE,OAAO,MAAM,KAAK,GAAG,QAAQ,CAAC,CAC3B,QAAQ,OAAO,GAAG,YAAY,IAAI,CAAC,CACnC,KAAK,IAAI,OAAO,GAAG,YAAY,OAAO,GAAG,IAAI,EAAE,MAAM,QAAQ,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,QAAQ,WAAW,GAAG,CAAC,CAAC,CACvG,KAAK,IAAI;AACd;AAEA,SAAgB,eAAe,MAAsB;CACnD,MAAM,MAAM,IAAI,UAAU,CAAC,CAAC,gBAAgB,SAAS,KAAK,UAAU,WAAW;CAC/E,MAAM,MAAgB,CAAC;CACvB,KAAK,MAAM,QAAQ,MAAM,KAAK,IAAI,KAAK,UAAU,GAAG;EAClD,IAAI,KAAK,aAAa,GAAG;GACvB,MAAM,IAAI,OAAO,IAAI,CAAC,CAAC,KAAK;GAC5B,IAAI,GAAG,IAAI,KAAK,CAAC;GACjB;EACF;EACA,IAAI,KAAK,aAAa,GAAG;EACzB,MAAM,KAAK;EACX,MAAM,MAAM,GAAG;EACf,MAAM,YAAY,IAAI,KAAK,GAAG,UAAU,QAAQ,QAAQ,GAAG,CAAC;EAC5D,IAAI,WAAW,KAAK,GAAG,GAAG,IAAI,KAAK,GAAG,IAAI,OAAO,OAAO,IAAI,EAAE,CAAC,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC,KAAK,GAAG;OAClF,IAAI,QAAQ,KAAK;GACpB,MAAM,IAAI,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,QAAQ,4BAA4B,MAAM;GACtE,IAAI,GAAG,IAAI,KAAK,CAAC;EACnB,OAAO,IAAI,QAAQ,QAAQ,QAAQ,MAAM;GACvC,MAAM,IAAI,KAAK,EAAE;GACjB,IAAI,MAAM,MAAM,IAAI;QACf,IAAI,KAAK,CAAC;EACjB,OAAO,IAAI,QAAQ,cAAc;GAC/B,MAAM,QAAQ,GAAG,cAAc,OAAO,IAAI,MAAM,KAAK,GAAG,QAAQ,CAAC,CAAC,KAAK,MAAM,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC;GACnH,IAAI,KAAK,MAAM,OAAO,OAAO,CAAC,CAAC,KAAK,MAAM,EAAE,MAAM,IAAI,CAAC,CAAC,KAAK,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC;EACxG,OAAO,IAAI,QAAQ,OAAO,IAAI,KAAK,WAAW,GAAG,eAAe,GAAA,CAAI,QAAQ,OAAO,EAAE,IAAI,OAAO;OAC3F,IAAI,QAAQ,MAAM,IAAI,KAAK,KAAK;OAChC,IAAI,QAAQ,YAAY,GAAG,cAAc,cAAc,GAAG;GAC7D,MAAM,MAAM,GAAG,cAAc,KAAK;GAClC,MAAM,MAAM,GAAG,cAAc,YAAY,CAAC,EAAE,aAAa,KAAK;GAC9D,IAAI,KAAK,KAAK,IAAI,aAAa,KAAK,KAAK,GAAG,IAAI,IAAI,aAAa,KAAK,KAAK,KAAK,MAAM,KAAK,IAAI,QAAQ,MAAM,GAAG,EAAE,KAAK,GAAG,EAAE;EAC9H,OAAO,IAAI;CACb;CACA,OAAO,IAAI,KAAK,MAAM,KAAK,IAAI,SAAS,OAAO;AACjD;AAGA,IAAM,YAAY,MAAe,uCAAuC,KAAK,CAAC,IAAI,MAAM;AAExF,SAAgB,SAAS,KAAqB;CAC5C,MAAM,QAAkB,CAAC;CACzB,MAAM,QAAQ,SAAiB,SAAS,MAAM,KAAK,IAAI,IAAI,EAAE;CAC7D,IAAI,IAAI,IAAI,QAAQ,4BAA4B,GAAG,MAAc,KAAK,IAAI,CAAC,CAAC,CAAC;CAC7E,IAAI,EAAE,QAAQ,eAAe,GAAG,MAAc,KAAK,SAAS,IAAI,CAAC,EAAE,QAAQ,CAAC;CAC5E,IAAI,EAAE,QAAQ,uBAAuB,MAAM,KAAK,CAAC,CAAC;CAClD,IAAI,IAAI,CAAC;CACT,IAAI,EAAE,QAAQ,mBAAmB,OAAO;CACxC,IAAI,EAAE,QAAQ,gCAAgC,GAAG,GAAW,MAAc,KAAK,aAAa,QAAQ,SAAS,CAAC,CAAC,EAAE,SAAS,QAAQ,CAAC,EAAE,GAAG,CAAC;CACzI,IAAI,EAAE,QAAQ,+BAA+B,GAAG,GAAW,MAAc,YAAY,QAAQ,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK;CACrH,IAAI,EAAE,QAAQ,qBAAqB,qBAAqB;CACxD,IAAI,EAAE,QAAQ,iBAAiB,qBAAqB;CACpD,IAAI,EAAE,QAAQ,uCAAuC,eAAe;CACpE,IAAI,EAAE,QAAQ,oCAAoC,eAAe;CACjE,IAAI,EAAE,QAAQ,iBAAiB,WAAW;CAC1C,IAAI,EAAE,QAAQ,YAAY,MAAM,CAAC,CAAC,QAAQ,OAAO,GAAG;CACpD,OAAO,EAAE,QAAQ,uBAAuB,GAAG,MAAc,MAAM,OAAO,CAAC,EAAE;AAC3E;AAEA,IAAM,YAAY;AAClB,IAAM,KAAK;CACT,OAAO;CACP,SAAS;CACT,IAAI;CACJ,OAAO;CACP,OAAO;CACP,IAAI;CACJ,IAAI;AACN;AACA,IAAM,eAAe,MAAc,GAAG,MAAM,KAAK,CAAC,KAAK,GAAG,QAAQ,KAAK,CAAC,KAAK,GAAG,GAAG,KAAK,CAAC,KAAK,GAAG,MAAM,KAAK,CAAC,KAAK,GAAG,GAAG,KAAK,CAAC,KAAK,GAAG,GAAG,KAAK,CAAC,KAAK,UAAU,KAAK,EAAE,KAAK,CAAC;;AAG3K,SAAgB,eAAe,IAAoB;CACjD,MAAM,QAAQ,GAAG,QAAQ,UAAU,IAAI,CAAC,CAAC,MAAM,IAAI;CACnD,MAAM,MAAgB,CAAC;CACvB,IAAI,IAAI;CACR,OAAO,IAAI,MAAM,QAAQ;EACvB,MAAM,OAAO,MAAM;EACnB,IAAI,CAAC,KAAK,KAAK,GAAG;GAChB;GACA;EACF;EACA,IAAI,GAAG,MAAM,KAAK,IAAI,GAAG;GACvB,MAAM,OAAiB,CAAC;GACxB;GACA,OAAO,IAAI,MAAM,UAAU,CAAC,GAAG,MAAM,KAAK,MAAM,EAAE,GAAG,KAAK,KAAK,MAAM,IAAI;GACzE,IAAI,KAAK,MAAM,QAAQ,MAAM,IAAI,MAAM,qBAAqB;GAC5D;GACA,IAAI,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC,EAAE,OAAO;GAC7C;EACF;EACA,IAAI,UAAU,KAAK,KAAK,KAAK,CAAC,GAAG;GAC/B,MAAM,MAAgB,CAAC;GACvB,OAAO,IAAI,MAAM,UAAU,MAAM,EAAE,CAAC,KAAK,GAAG,IAAI,KAAK,MAAM,IAAI;GAC/D,IAAI,KAAK,IAAI,KAAK,GAAG,CAAC;GACtB;EACF;EACA,IAAI,IAAI,KAAK,MAAM,GAAG,OAAO;EAC7B,IAAI,GAAG;GACL,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC,OAAO,GAAG,SAAS,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,OAAO,EAAE;GAC/D;GACA;EACF;EACA,IAAI,GAAG,GAAG,KAAK,IAAI,GAAG;GACpB,IAAI,KAAK,MAAM;GACf;GACA;EACF;EACA,IAAI,KAAK,MAAM,GAAG,KAAK;EACvB,IAAI,GAAG;GAEL,IAAI,KAAK,qBAAqB,QAAQ,SAAS,EAAE,EAAE,CAAC,EAAE,SAAS,QAAQ,EAAE,EAAE,EAAE,aAAa,EAAE,KAAK,MAAM,IAAI,EAAE,EAAE,EAAE,QAAQ,IAAI;GAC7H;GACA;EACF;EACA,IAAI,GAAG,MAAM,KAAK,IAAI,GAAG;GACvB,MAAM,IAAc,CAAC;GACrB,OAAO,IAAI,MAAM,UAAU,GAAG,MAAM,KAAK,MAAM,EAAE,GAAG,EAAE,KAAK,MAAM,IAAI,CAAC,QAAQ,WAAW,EAAE,CAAC;GAC5F,IAAI,KAAK,eAAe,EAAE,KAAK,IAAI,CAAC,CAAC,MAAM,SAAS,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,KAAK,UAAU,EAAE,cAAc;GACnG;EACF;EACA,IAAI,GAAG,GAAG,KAAK,IAAI,KAAK,GAAG,GAAG,KAAK,IAAI,GAAG;GACxC,MAAM,UAAU,CAAC,GAAG,GAAG,KAAK,IAAI;GAChC,MAAM,KAAK,UAAU,GAAG,KAAK,GAAG;GAChC,MAAM,QAAkB,CAAC;GACzB,OAAO,IAAI,MAAM,UAAU,GAAG,KAAK,MAAM,EAAE,GAAG,MAAM,KAAK,OAAO,SAAS,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC,CAAE,EAAE,EAAE,MAAM;GACzG,IAAI,KAAK,UAAU,OAAO,MAAM,KAAK,EAAE,EAAE,SAAS,OAAO,MAAM,KAAK,EAAE,EAAE,MAAM;GAC9E;EACF;EACA,MAAM,OAAiB,CAAC;EACxB,OAAO,IAAI,MAAM,UAAU,MAAM,EAAE,CAAC,KAAK,MAAM,KAAK,WAAW,KAAK,CAAC,YAAY,MAAM,EAAE,IAAI,KAAK,KAAK,MAAM,IAAI;EACjH,IAAI,KAAK,MAAM,SAAS,KAAK,KAAK,IAAI,CAAC,EAAE,KAAK;CAChD;CACA,OAAO,SAAS,IAAI,KAAK,EAAE,CAAC;AAC9B;;AAGA,IAAa,qBAAqB,MAAc,UAAU,KAAK,CAAC,KAAK,6CAA6C,KAAK,CAAC,KAAK,oCAAoC,KAAK,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { cloneModel, closestBlock, createIsland, defaultModel, esc, placeCaret, textBeforeCaret, topBlock } from "./dom.js";
|
|
2
|
-
//#region src/
|
|
2
|
+
//#region src/controls/rich-text/ops.ts
|
|
3
3
|
/**
|
|
4
4
|
* RICH TEXT · pure DOM block operations on the editor surface (V2 HEAD controls/rich-text/ops.ts; no React, no
|
|
5
5
|
* emitting). The editor wraps each one, then serializes and emits the new value.
|
|
@@ -285,20 +285,22 @@ function restrictHtml(html, allows) {
|
|
|
285
285
|
const mark = MARK_FEATURE[ch.tagName];
|
|
286
286
|
const block = BLOCK_FEATURE[ch.tagName];
|
|
287
287
|
if (mark && !allows(mark)) ch.replaceWith(...Array.from(ch.childNodes));
|
|
288
|
-
else if (block && !allows(block))
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
288
|
+
else if (block && !allows(block)) {
|
|
289
|
+
if (block === "hr" || block === "image") {
|
|
290
|
+
dropped.add(FEATURE_WORD[block]);
|
|
291
|
+
ch.remove();
|
|
292
|
+
} else if (block === "ul" || block === "ol") {
|
|
293
|
+
const ps = Array.from(ch.children).map((li) => {
|
|
294
|
+
const p = doc.createElement("p");
|
|
295
|
+
p.innerHTML = li.innerHTML;
|
|
296
|
+
return p;
|
|
297
|
+
});
|
|
298
|
+
ch.replaceWith(...ps);
|
|
299
|
+
} else {
|
|
293
300
|
const p = doc.createElement("p");
|
|
294
|
-
p.innerHTML =
|
|
295
|
-
|
|
296
|
-
}
|
|
297
|
-
ch.replaceWith(...ps);
|
|
298
|
-
} else {
|
|
299
|
-
const p = doc.createElement("p");
|
|
300
|
-
p.innerHTML = block === "pre" ? esc(ch.textContent ?? "").replace(/\n/g, "<br>") : ch.innerHTML;
|
|
301
|
-
ch.replaceWith(p);
|
|
301
|
+
p.innerHTML = block === "pre" ? esc(ch.textContent ?? "").replace(/\n/g, "<br>") : ch.innerHTML;
|
|
302
|
+
ch.replaceWith(p);
|
|
303
|
+
}
|
|
302
304
|
}
|
|
303
305
|
}
|
|
304
306
|
};
|
|
@@ -309,6 +311,6 @@ function restrictHtml(html, allows) {
|
|
|
309
311
|
};
|
|
310
312
|
}
|
|
311
313
|
//#endregion
|
|
312
|
-
export { duplicateBlock, ensureLineAfter, insertBasic, insertIsland, liveInlineCode, liveMarkdown, moveBlock, restrictHtml, turnInto };
|
|
314
|
+
export { duplicateBlock, ensureLineAfter, insertBasic, insertIsland, liveInlineCode, liveMarkdown, moveBlock, restrictHtml, takeEmptyBlock, turnInto };
|
|
313
315
|
|
|
314
316
|
//# sourceMappingURL=ops.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ops.js","names":[],"sources":["../../../src/controls/rich-text/ops.ts"],"sourcesContent":["/**\n * RICH TEXT · pure DOM block operations on the editor surface (V2 HEAD controls/rich-text/ops.ts; no React, no\n * emitting). The editor wraps each one, then serializes and emits the new value.\n */\nimport { closestBlock, cloneModel, createIsland, defaultModel, esc, placeCaret, textBeforeCaret, topBlock, type IslandEl, type IslandKind, type IslandModels } from \"./dom\";\nimport type { RichTextFeature } from \"./codec\";\nimport type { BasicId } from \"./catalog\";\n\nconst emptyP = () => {\n const p = document.createElement(\"p\");\n p.innerHTML = \"<br>\";\n return p;\n};\nconst isWritable = (el: Element | null): el is HTMLElement => !!el && !el.hasAttribute(\"data-rt-island\") && el.tagName !== \"HR\";\n\n/** The writable line after a block, created when the block is last or followed by another rich block. */\nexport function ensureLineAfter(b: Element): HTMLElement {\n const next = b.nextElementSibling;\n if (isWritable(next)) return next;\n const p = emptyP();\n b.after(p);\n return p;\n}\n\nexport function duplicateBlock(b: HTMLElement): HTMLElement {\n let c: HTMLElement;\n if (b.hasAttribute(\"data-rt-island\")) {\n const k = b.getAttribute(\"data-rt-island\") as IslandKind;\n c = createIsland(k, cloneModel(k, (b as IslandEl).__rt as never));\n } else {\n c = b.cloneNode(true) as HTMLElement;\n c.removeAttribute(\"data-hint\");\n }\n b.after(c);\n return c;\n}\n\n/** Moves a block one step, keeping the caret where it was. Returns false at the edge. */\nexport function moveBlock(b: HTMLElement, dir: -1 | 1): boolean {\n const sib = dir < 0 ? b.previousElementSibling : b.nextElementSibling;\n if (!sib) return false;\n const s = window.getSelection();\n // ranges are live (a move collapses them), so keep the raw caret position\n const at = s && s.rangeCount ? { n: s.getRangeAt(0).startContainer, o: s.getRangeAt(0).startOffset } : null;\n const host = document.activeElement as HTMLElement | null;\n if (dir < 0) sib.before(b);\n else sib.after(b);\n if (at && s && b.contains(at.n)) {\n host?.focus({ preventScroll: true });\n const r = document.createRange();\n r.setStart(at.n, Math.min(at.o, at.n.nodeType === 3 ? (at.n as Text).length : at.n.childNodes.length));\n r.collapse(true);\n s.removeAllRanges();\n s.addRange(r);\n }\n return true;\n}\n\n/** Text / Heading / Quote / Code. Returns the new element, or null when nothing changed. */\nexport function turnInto(root: HTMLElement, b: HTMLElement | null, tag: string): HTMLElement | null {\n if (!b || b.parentNode !== root || b.hasAttribute(\"data-rt-island\") || b.tagName === \"HR\") return null;\n if (b.tagName.toLowerCase() === tag) return null;\n const inner =\n b.tagName === \"UL\" || b.tagName === \"OL\"\n ? Array.from(b.children).map((c) => c.innerHTML).join(\"<br>\")\n : b.tagName === \"PRE\"\n ? esc(b.textContent ?? \"\").replace(/\\n/g, \"<br>\")\n : b.innerHTML;\n const n = document.createElement(tag);\n n.innerHTML = tag === \"pre\" ? esc((b.textContent ?? \"\").replace(//g, \"\")) || \"<br>\" : inner || \"<br>\";\n b.replaceWith(n);\n root.focus({ preventScroll: true });\n placeCaret(n);\n return n;\n}\n\n/** An empty paragraph at the caret to build a block from (reuses the current one when it is empty). */\nexport function takeEmptyBlock(root: HTMLElement): HTMLElement {\n const s = window.getSelection();\n const anchor = s && s.rangeCount && root.contains(s.anchorNode) ? s.anchorNode : null;\n const li = anchor ? closestBlock(root, anchor) : null;\n let b = topBlock(root, anchor);\n if (li && li.tagName === \"LI\" && !li.textContent?.trim()) {\n const list = li.parentElement!;\n li.remove();\n if (!list.children.length) {\n const p = emptyP();\n list.replaceWith(p);\n b = p;\n } else b = list;\n }\n root.focus({ preventScroll: true });\n if (b && b.tagName === \"P\" && !b.textContent?.replace(//g, \"\").trim() && !b.querySelector(\"img\")) {\n b.innerHTML = \"<br>\";\n placeCaret(b);\n return b;\n }\n // an empty heading, quote or code line (e.g. \"/\" typed on one) is reused too, so no empty block is left behind\n if (b && /^(H[1-6]|BLOCKQUOTE|PRE)$/.test(b.tagName) && !b.textContent?.replace(//g, \"\").trim()) {\n const p = emptyP();\n b.replaceWith(p);\n placeCaret(p);\n return p;\n }\n const p = emptyP();\n if (b) b.after(p);\n else root.append(p);\n placeCaret(p);\n return p;\n}\n\nexport function insertIsland<K extends IslandKind>(root: HTMLElement, kind: K, model: IslandModels[K] = defaultModel(kind)): IslandEl {\n const target = takeEmptyBlock(root);\n const isl = createIsland(kind, model);\n isl.__rtFocus = true;\n target.before(isl);\n // keep the document tidy: reuse the line that already follows instead of leaving an empty one\n const next = target.nextElementSibling;\n if (isWritable(next)) {\n target.remove();\n placeCaret(next, false);\n } else placeCaret(target);\n return isl;\n}\n\n/** Inserts a basic block at the caret. */\nexport function insertBasic(root: HTMLElement, id: BasicId) {\n switch (id) {\n case \"p\":\n takeEmptyBlock(root);\n return;\n case \"h1\": case \"h2\": case \"h3\": case \"h4\": case \"h5\": case \"h6\":\n turnInto(root, takeEmptyBlock(root), id);\n return;\n case \"quote\":\n turnInto(root, takeEmptyBlock(root), \"blockquote\");\n return;\n case \"code\":\n turnInto(root, takeEmptyBlock(root), \"pre\");\n return;\n case \"ul\": case \"ol\": {\n const t = takeEmptyBlock(root);\n const l = document.createElement(id);\n l.innerHTML = \"<li><br></li>\";\n t.replaceWith(l);\n placeCaret(l.firstElementChild!);\n return;\n }\n case \"hr\": {\n const t = takeEmptyBlock(root);\n t.before(document.createElement(\"hr\"));\n placeCaret(t);\n return;\n }\n case \"image\": case \"table\": case \"pullquote\": case \"takeaways\": case \"callout\": case \"toggle\": case \"video\": case \"file\":\n insertIsland(root, id);\n return;\n }\n}\n\n/**\n * \"# \", \"> \", \"- \", \"1. \" and \"---\" at the start of a paragraph, each only when the field accepts what it makes.\n * Returns true when it converted.\n */\nexport function liveMarkdown(root: HTMLElement, data: string | null, allows: (f: RichTextFeature) => boolean = () => true): boolean {\n const s = window.getSelection();\n if (!s || !s.rangeCount || !s.isCollapsed) return false;\n const blk = topBlock(root, s.anchorNode);\n if (!blk || blk.tagName !== \"P\") return false;\n const before = textBeforeCaret(blk)?.replace(/ /g, \" \");\n if (before == null) return false;\n if (data === \"-\" && before === \"---\" && (blk.textContent ?? \"\").replace(/ /g, \" \") === \"---\") {\n if (!allows(\"hr\")) return false;\n const p = emptyP();\n blk.replaceWith(document.createElement(\"hr\"), p);\n placeCaret(p);\n return true;\n }\n if (data !== \" \") return false;\n const h = before.match(/^(#{1,6}) $/);\n let tag = h ? `h${h[1].length}` : before === \"> \" ? \"blockquote\" : null;\n let list = before === \"- \" || before === \"* \" ? \"ul\" : /^1[.)] $/.test(before) ? \"ol\" : null;\n if (tag && !allows(tag as RichTextFeature)) tag = null;\n if (list && !allows(list as RichTextFeature)) list = null;\n if (!tag && !list) return false;\n const r = document.createRange();\n r.selectNodeContents(blk);\n r.setEnd(s.anchorNode!, s.anchorOffset);\n r.deleteContents();\n const html = blk.textContent || blk.querySelector(\"img\") ? blk.innerHTML : \"<br>\";\n let target: HTMLElement;\n if (tag) {\n target = document.createElement(tag);\n target.innerHTML = html;\n blk.replaceWith(target);\n } else {\n const l = document.createElement(list!);\n target = document.createElement(\"li\");\n target.innerHTML = html;\n l.append(target);\n blk.replaceWith(l);\n }\n placeCaret(target, false);\n return true;\n}\n\n/** `text` typed between backticks becomes inline code. */\nexport function liveInlineCode(): boolean {\n const s = window.getSelection();\n if (!s || !s.rangeCount || !s.isCollapsed) return false;\n const r = s.getRangeAt(0);\n if (r.startContainer.nodeType !== 3 || r.startContainer.parentElement?.closest(\"code,pre\")) return false;\n const node = r.startContainer as Text;\n const m = node.data.slice(0, r.startOffset).match(/`([^`\\n]+)`$/);\n if (!m) return false;\n const del = document.createRange();\n del.setStart(node, r.startOffset - m[0].length);\n del.setEnd(node, r.startOffset);\n del.deleteContents();\n const code = document.createElement(\"code\");\n code.textContent = m[1];\n del.insertNode(code);\n const next = code.nextSibling;\n if (next && next.nodeType === 3 && next.textContent) {\n const c = document.createRange();\n c.setStart(next, 0);\n c.collapse(true);\n s.removeAllRanges();\n s.addRange(c);\n } else {\n const after = document.createTextNode(\"\");\n code.after(after);\n placeCaret(after);\n }\n return true;\n}\n\n/* ── What a field accepts, applied to HTML that arrives from outside (paste, Markdown) ── */\nconst MARK_FEATURE: Record<string, RichTextFeature> = {\n STRONG: \"bold\", B: \"bold\", EM: \"italic\", I: \"italic\", U: \"underline\", S: \"strike\", STRIKE: \"strike\", DEL: \"strike\", CODE: \"code\", A: \"link\",\n};\nconst BLOCK_FEATURE: Record<string, RichTextFeature> = {\n H1: \"h1\", H2: \"h2\", H3: \"h3\", H4: \"h4\", H5: \"h5\", H6: \"h6\", BLOCKQUOTE: \"blockquote\", UL: \"ul\", OL: \"ol\", PRE: \"pre\", HR: \"hr\", FIGURE: \"image\", IMG: \"image\",\n};\nconst FEATURE_WORD: Partial<Record<RichTextFeature, string>> = {\n image: \"images\", hr: \"dividers\", pre: \"code blocks\", ul: \"bulleted lists\", ol: \"numbered lists\", blockquote: \"quotes\", link: \"links\",\n};\n\n/**\n * HTML with every element the field does not accept turned into what it does: a heading / quote / code block becomes a\n * paragraph, a list becomes one paragraph per item, a mark or link is unwrapped to its text, a divider or image is\n * removed. `dropped` names what was taken out entirely (said to the author, never silent).\n */\nexport function restrictHtml(html: string, allows: (f: RichTextFeature) => boolean): { html: string; dropped: string[] } {\n if (!html) return { html, dropped: [] };\n const doc = new DOMParser().parseFromString(`<body>${html}</body>`, \"text/html\");\n const dropped = new Set<string>();\n const walk = (el: Element) => {\n for (const ch of Array.from(el.children)) {\n walk(ch);\n const mark = MARK_FEATURE[ch.tagName];\n const block = BLOCK_FEATURE[ch.tagName];\n if (mark && !allows(mark)) ch.replaceWith(...Array.from(ch.childNodes));\n else if (block && !allows(block)) {\n if (block === \"hr\" || block === \"image\") {\n dropped.add(FEATURE_WORD[block]!);\n ch.remove();\n } else if (block === \"ul\" || block === \"ol\") {\n const ps = Array.from(ch.children).map((li) => {\n const p = doc.createElement(\"p\");\n p.innerHTML = li.innerHTML;\n return p;\n });\n ch.replaceWith(...ps);\n } else {\n const p = doc.createElement(\"p\");\n p.innerHTML = block === \"pre\" ? esc(ch.textContent ?? \"\").replace(/\\n/g, \"<br>\") : ch.innerHTML;\n ch.replaceWith(p);\n }\n }\n }\n };\n walk(doc.body);\n return { html: doc.body.innerHTML, dropped: [...dropped] };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plain paragraphs as a growing textarea (V2's `text` control), for hosts where V2 shows long text as a textarea
|
|
3
|
+
* rather than the rich editor: the canvas Values popover. A rich-text value whose html is only plain paragraphs
|
|
4
|
+
* reads as one line per `<p>`; one that carries marks, links, line breaks, lists or attributes returns null and
|
|
5
|
+
* keeps the rich editor, so editing never strips them. The textarea's text goes back as one `<p>` per line through
|
|
6
|
+
* the field's own codec, so the stored shape is the field's as before.
|
|
7
|
+
*/
|
|
8
|
+
import * as React from "react";
|
|
9
|
+
/** The html as textarea text — one line per `<p>` — or null when a textarea cannot carry it back unchanged. */
|
|
10
|
+
export declare function plainParagraphs(html: unknown): string | null;
|
|
11
|
+
/** Textarea text back to the paragraph html `plainParagraphs` reads: one `<p>` per line. */
|
|
12
|
+
export declare function paragraphsHtml(text: string): string;
|
|
13
|
+
/** Inside this scope a rich-text field holding plain paragraphs is drawn as V2's growing textarea. */
|
|
14
|
+
export declare function PlainRichTextScope({ children }: {
|
|
15
|
+
children: React.ReactNode;
|
|
16
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
17
|
+
export declare const usePlainRichText: () => boolean;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
//#region src/controls/rich-text/plain.tsx
|
|
4
|
+
/**
|
|
5
|
+
* Plain paragraphs as a growing textarea (V2's `text` control), for hosts where V2 shows long text as a textarea
|
|
6
|
+
* rather than the rich editor: the canvas Values popover. A rich-text value whose html is only plain paragraphs
|
|
7
|
+
* reads as one line per `<p>`; one that carries marks, links, line breaks, lists or attributes returns null and
|
|
8
|
+
* keeps the rich editor, so editing never strips them. The textarea's text goes back as one `<p>` per line through
|
|
9
|
+
* the field's own codec, so the stored shape is the field's as before.
|
|
10
|
+
*/
|
|
11
|
+
/** The html as textarea text — one line per `<p>` — or null when a textarea cannot carry it back unchanged. */
|
|
12
|
+
function plainParagraphs(html) {
|
|
13
|
+
if (html === void 0 || html === null || html === "") return "";
|
|
14
|
+
if (typeof html !== "string") return null;
|
|
15
|
+
const body = new DOMParser().parseFromString(html, "text/html").body;
|
|
16
|
+
const lines = [];
|
|
17
|
+
for (const node of Array.from(body.childNodes)) {
|
|
18
|
+
if (node.nodeType === Node.TEXT_NODE && !node.textContent?.trim()) continue;
|
|
19
|
+
if (node.nodeType !== Node.ELEMENT_NODE) return null;
|
|
20
|
+
const el = node;
|
|
21
|
+
if (el.tagName !== "P" || el.attributes.length || Array.from(el.childNodes).some((c) => c.nodeType !== Node.TEXT_NODE)) return null;
|
|
22
|
+
if (el.textContent?.includes("\n")) return null;
|
|
23
|
+
lines.push(el.textContent ?? "");
|
|
24
|
+
}
|
|
25
|
+
return lines.join("\n");
|
|
26
|
+
}
|
|
27
|
+
var escapeHtml = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
28
|
+
/** Textarea text back to the paragraph html `plainParagraphs` reads: one `<p>` per line. */
|
|
29
|
+
function paragraphsHtml(text) {
|
|
30
|
+
return text.split(/\r?\n/).map((line) => `<p>${escapeHtml(line)}</p>`).join("");
|
|
31
|
+
}
|
|
32
|
+
var PlainRichText = React.createContext(false);
|
|
33
|
+
/** Inside this scope a rich-text field holding plain paragraphs is drawn as V2's growing textarea. */
|
|
34
|
+
function PlainRichTextScope({ children }) {
|
|
35
|
+
return /* @__PURE__ */ jsx(PlainRichText.Provider, {
|
|
36
|
+
value: true,
|
|
37
|
+
children
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
var usePlainRichText = () => React.useContext(PlainRichText);
|
|
41
|
+
//#endregion
|
|
42
|
+
export { PlainRichTextScope, paragraphsHtml, plainParagraphs, usePlainRichText };
|
|
43
|
+
|
|
44
|
+
//# sourceMappingURL=plain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plain.js","names":[],"sources":["../../../src/controls/rich-text/plain.tsx"],"sourcesContent":["/**\n * Plain paragraphs as a growing textarea (V2's `text` control), for hosts where V2 shows long text as a textarea\n * rather than the rich editor: the canvas Values popover. A rich-text value whose html is only plain paragraphs\n * reads as one line per `<p>`; one that carries marks, links, line breaks, lists or attributes returns null and\n * keeps the rich editor, so editing never strips them. The textarea's text goes back as one `<p>` per line through\n * the field's own codec, so the stored shape is the field's as before.\n */\nimport * as React from \"react\";\n\n/** The html as textarea text — one line per `<p>` — or null when a textarea cannot carry it back unchanged. */\nexport function plainParagraphs(html: unknown): string | null {\n if (html === undefined || html === null || html === \"\") return \"\";\n if (typeof html !== \"string\") return null;\n const body = new DOMParser().parseFromString(html, \"text/html\").body;\n const lines: string[] = [];\n for (const node of Array.from(body.childNodes)) {\n if (node.nodeType === Node.TEXT_NODE && !node.textContent?.trim()) continue;\n if (node.nodeType !== Node.ELEMENT_NODE) return null;\n const el = node as Element;\n if (el.tagName !== \"P\" || el.attributes.length || Array.from(el.childNodes).some((c) => c.nodeType !== Node.TEXT_NODE)) return null;\n if (el.textContent?.includes(\"\\n\")) return null;\n lines.push(el.textContent ?? \"\");\n }\n return lines.join(\"\\n\");\n}\n\nconst escapeHtml = (s: string) => s.replace(/&/g, \"&\").replace(/</g, \"<\").replace(/>/g, \">\");\n\n/** Textarea text back to the paragraph html `plainParagraphs` reads: one `<p>` per line. */\nexport function paragraphsHtml(text: string): string {\n return text.split(/\\r?\\n/).map((line) => `<p>${escapeHtml(line)}</p>`).join(\"\");\n}\n\nconst PlainRichText = React.createContext(false);\n\n/** Inside this scope a rich-text field holding plain paragraphs is drawn as V2's growing textarea. */\nexport function PlainRichTextScope({ children }: { children: React.ReactNode }) {\n return <PlainRichText.Provider value>{children}</PlainRichText.Provider>;\n}\n\nexport const usePlainRichText = () => React.useContext(PlainRichText);\n"],"mappings":";;;;;;;;;;;AAUA,SAAgB,gBAAgB,MAA8B;CAC5D,IAAI,SAAS,KAAA,KAAa,SAAS,QAAQ,SAAS,IAAI,OAAO;CAC/D,IAAI,OAAO,SAAS,UAAU,OAAO;CACrC,MAAM,OAAO,IAAI,UAAU,CAAC,CAAC,gBAAgB,MAAM,WAAW,CAAC,CAAC;CAChE,MAAM,QAAkB,CAAC;CACzB,KAAK,MAAM,QAAQ,MAAM,KAAK,KAAK,UAAU,GAAG;EAC9C,IAAI,KAAK,aAAa,KAAK,aAAa,CAAC,KAAK,aAAa,KAAK,GAAG;EACnE,IAAI,KAAK,aAAa,KAAK,cAAc,OAAO;EAChD,MAAM,KAAK;EACX,IAAI,GAAG,YAAY,OAAO,GAAG,WAAW,UAAU,MAAM,KAAK,GAAG,UAAU,CAAC,CAAC,MAAM,MAAM,EAAE,aAAa,KAAK,SAAS,GAAG,OAAO;EAC/H,IAAI,GAAG,aAAa,SAAS,IAAI,GAAG,OAAO;EAC3C,MAAM,KAAK,GAAG,eAAe,EAAE;CACjC;CACA,OAAO,MAAM,KAAK,IAAI;AACxB;AAEA,IAAM,cAAc,MAAc,EAAE,QAAQ,MAAM,OAAO,CAAC,CAAC,QAAQ,MAAM,MAAM,CAAC,CAAC,QAAQ,MAAM,MAAM;;AAGrG,SAAgB,eAAe,MAAsB;CACnD,OAAO,KAAK,MAAM,OAAO,CAAC,CAAC,KAAK,SAAS,MAAM,WAAW,IAAI,EAAE,KAAK,CAAC,CAAC,KAAK,EAAE;AAChF;AAEA,IAAM,gBAAgB,MAAM,cAAc,KAAK;;AAG/C,SAAgB,mBAAmB,EAAE,YAA2C;CAC9E,OAAO,oBAAC,cAAc,UAAf;EAAwB,OAAA;EAAO;CAAiC,CAAA;AACzE;AAEA,IAAa,yBAAyB,MAAM,WAAW,aAAa"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { type KitRichTextRefRequest } from "../../context";
|
|
2
|
+
import type { TypeSchema } from "../../schema/types";
|
|
3
|
+
import type { IslandCtx } from "./blocks";
|
|
4
|
+
import type { IslandEl } from "./dom";
|
|
5
|
+
export type RelatedMode = "topic" | "newest" | "manual";
|
|
6
|
+
export interface RelatedModel {
|
|
7
|
+
title: string;
|
|
8
|
+
mode: RelatedMode;
|
|
9
|
+
count: number;
|
|
10
|
+
/** entry ids, Hand-picked only; the PT form wraps each as `{ _key, _ref }` */
|
|
11
|
+
posts: string[];
|
|
12
|
+
}
|
|
13
|
+
export declare const RELATED_LABEL = "Related posts";
|
|
14
|
+
export declare const relatedDefault: () => RelatedModel;
|
|
15
|
+
/** The panel form; `to` is the field's collection. "How many" explains the chosen automatic mode. */
|
|
16
|
+
export declare const relatedSchema: (to: string[], mode: RelatedMode) => TypeSchema;
|
|
17
|
+
/** What the preview asks the host for: the picked ids, or the automatic mode's query. */
|
|
18
|
+
export declare function relatedRequest(m: RelatedModel, collection?: string, excludeId?: string): KitRichTextRefRequest | null;
|
|
19
|
+
export declare function RelatedPreview({ m, onPick, ro, collection, excludeId }: {
|
|
20
|
+
m: RelatedModel;
|
|
21
|
+
onPick: () => void;
|
|
22
|
+
ro: boolean;
|
|
23
|
+
collection?: string;
|
|
24
|
+
excludeId?: string;
|
|
25
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
26
|
+
export declare function RelatedBlock({ m, set, el, ctx, autoFocus, collection, excludeId, }: {
|
|
27
|
+
m: RelatedModel;
|
|
28
|
+
set: (fn: (m: RelatedModel) => RelatedModel, label?: string) => void;
|
|
29
|
+
el: IslandEl;
|
|
30
|
+
ctx: IslandCtx;
|
|
31
|
+
autoFocus: boolean;
|
|
32
|
+
/** the posts collection (the field's config) */
|
|
33
|
+
collection: string;
|
|
34
|
+
/** the entry being edited, left out of the automatic modes */
|
|
35
|
+
excludeId?: string;
|
|
36
|
+
}): import("react/jsx-runtime").JSX.Element;
|