@limetech/lime-elements 37.76.1 → 37.76.3

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.
Files changed (46) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/cjs/limel-prosemirror-adapter.cjs.entry.js +93 -117
  3. package/dist/cjs/limel-prosemirror-adapter.cjs.entry.js.map +1 -1
  4. package/dist/cjs/limel-text-editor.cjs.entry.js.map +1 -1
  5. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/link-plugin.js +1 -1
  6. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/link-plugin.js.map +1 -1
  7. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/trigger/factory-helpers/append-transaction-handler.js +18 -0
  8. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/trigger/factory-helpers/append-transaction-handler.js.map +1 -0
  9. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/trigger/factory-helpers/detect-trigger-removal.js +26 -0
  10. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/trigger/factory-helpers/detect-trigger-removal.js.map +1 -0
  11. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/trigger/factory-helpers/get-trigger-event-detail.js +10 -0
  12. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/trigger/factory-helpers/get-trigger-event-detail.js.map +1 -0
  13. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/trigger/factory-helpers/monitor-triggered-text.js +11 -0
  14. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/trigger/factory-helpers/monitor-triggered-text.js.map +1 -0
  15. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/trigger/factory-helpers/send-trigger-event.js +10 -0
  16. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/trigger/factory-helpers/send-trigger-event.js.map +1 -0
  17. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/trigger/factory-helpers/text-input-handler.js +20 -0
  18. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/trigger/factory-helpers/text-input-handler.js.map +1 -0
  19. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/trigger/factory.js +18 -123
  20. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/trigger/factory.js.map +1 -1
  21. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/trigger/inserter.js +6 -11
  22. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/trigger/inserter.js.map +1 -1
  23. package/dist/collection/components/text-editor/prosemirror-adapter/prosemirror-adapter.js +1 -1
  24. package/dist/collection/components/text-editor/prosemirror-adapter/prosemirror-adapter.js.map +1 -1
  25. package/dist/collection/components/text-editor/text-editor.js +1 -1
  26. package/dist/collection/components/text-editor/text-editor.js.map +1 -1
  27. package/dist/collection/components/text-editor/text-editor.types.js.map +1 -1
  28. package/dist/esm/limel-prosemirror-adapter.entry.js +93 -117
  29. package/dist/esm/limel-prosemirror-adapter.entry.js.map +1 -1
  30. package/dist/esm/limel-text-editor.entry.js.map +1 -1
  31. package/dist/lime-elements/lime-elements.esm.js +1 -1
  32. package/dist/lime-elements/{p-4c79b891.entry.js → p-1db8aa67.entry.js} +2 -2
  33. package/dist/lime-elements/p-1db8aa67.entry.js.map +1 -0
  34. package/dist/lime-elements/p-9fae6488.entry.js.map +1 -1
  35. package/dist/types/components/text-editor/prosemirror-adapter/plugins/trigger/factory-helpers/append-transaction-handler.d.ts +6 -0
  36. package/dist/types/components/text-editor/prosemirror-adapter/plugins/trigger/factory-helpers/detect-trigger-removal.d.ts +6 -0
  37. package/dist/types/components/text-editor/prosemirror-adapter/plugins/trigger/factory-helpers/get-trigger-event-detail.d.ts +5 -0
  38. package/dist/types/components/text-editor/prosemirror-adapter/plugins/trigger/factory-helpers/monitor-triggered-text.d.ts +5 -0
  39. package/dist/types/components/text-editor/prosemirror-adapter/plugins/trigger/factory-helpers/send-trigger-event.d.ts +5 -0
  40. package/dist/types/components/text-editor/prosemirror-adapter/plugins/trigger/factory-helpers/text-input-handler.d.ts +5 -0
  41. package/dist/types/components/text-editor/prosemirror-adapter/plugins/trigger/inserter.d.ts +2 -2
  42. package/dist/types/components/text-editor/text-editor.d.ts +1 -1
  43. package/dist/types/components/text-editor/text-editor.types.d.ts +11 -0
  44. package/dist/types/components.d.ts +4 -4
  45. package/package.json +6 -6
  46. package/dist/lime-elements/p-4c79b891.entry.js.map +0 -1
@@ -1 +1 @@
1
- {"file":"limel-text-editor.entry.cjs.js","mappings":"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","names":["h","createRandomString","Host"],"sources":["./src/components/text-editor/text-editor.scss?tag=limel-text-editor&encapsulation=shadow","./src/components/text-editor/text-editor.tsx"],"sourcesContent":["@use '../../style/internal/shared_input-select-picker';\n@use '../../style/mixins.scss';\n\n/**\n * @prop --text-editor-max-height: the tallest height the text editor can become when auto-resizing itself. Defaults to `calc(100vh - (env(safe-area-inset-top) + env(safe-area-inset-bottom)) - 4rem)`.\n * @prop --text-editor-fade-out-background-color: the color of the fade-out effect at the top and bottom of the text editor, when the text-editor is in readonly state. Defaults to rgb(var(--contrast-100)).\n */\n\n@include shared_input-select-picker.lime-looks-like-input-value;\n.lime-looks-like-input-value {\n padding: var(--limel-text-editor-padding);\n}\n\n* {\n box-sizing: border-box;\n}\n\n:host(limel-text-editor) {\n --limel-text-editor-outline-color: #{shared_input-select-picker.$lime-text-field-outline-color};\n --limel-text-editor-background-color: #{shared_input-select-picker.$background-color-normal};\n --limel-text-editor-label-color: #{shared_input-select-picker.$label-color};\n --limel-prosemirror-adapter-toolbar-opacity: 0.6;\n --limel-text-editor-padding: 0.25rem 1rem 0.75rem 1rem;\n --limel-prosemirror-adapter-toolbar-grid-template-rows: 1fr;\n --limel-prosemirror-adapter-toolbar-grid-template-rows-transition-duration: 0.3s;\n --limel-prosemirror-adapter-toolbar-transition-timing-function: cubic-bezier(\n 0.19,\n 0.23,\n 0.26,\n 0.89\n );\n\n position: relative;\n isolation: isolate;\n display: flex;\n flex-direction: column;\n\n width: 100%;\n min-width: 5rem;\n min-height: 5rem;\n height: 100%;\n max-height: var(\n --text-editor-max-height,\n calc(\n 100vh - (env(safe-area-inset-top) + env(safe-area-inset-bottom)) -\n 4rem\n )\n );\n padding: 1px; // prevents visual defects that can appear due to the backdrop-filter and closeness to borders\n}\n\n:host(limel-text-editor:focus-within),\n:host(limel-text-editor:not([ui='minimal']):hover) {\n --limel-prosemirror-adapter-toolbar-opacity: 1;\n}\n\n:host(limel-text-editor[ui='minimal']:not(:focus-within)) {\n --limel-text-editor-padding: 0.75rem 1rem 0.75rem 1rem;\n --limel-prosemirror-adapter-toolbar-grid-template-rows: 0fr;\n --limel-prosemirror-adapter-toolbar-grid-template-rows-transition-duration: 0.46s;\n --limel-prosemirror-adapter-action-bar-padding-top-bottom: 0;\n --limel-prosemirror-adapter-toolbar-opacity: 0;\n --limel-text-editor-placeholder-top: 0;\n min-height: 2.5rem;\n}\n\n:host(limel-text-editor:hover) {\n --limel-text-editor-outline-color: #{shared_input-select-picker.$lime-text-field-outline-color--hovered};\n}\n\n:host(limel-text-editor:focus-within) {\n --limel-text-editor-outline-color: #{shared_input-select-picker.$lime-text-field-outline-color--focused};\n}\n\n:host(limel-text-editor:focus-within),\n:host(limel-text-editor:focus) {\n .placeholder {\n opacity: 0;\n }\n}\n\n:host(limel-text-editor[disabled]:not([disabled='false'])) {\n @include shared_input-select-picker.looks-disabled;\n\n limel-prosemirror-adapter {\n pointer-events: none;\n }\n}\n\n:host(limel-text-editor[invalid]:not([invalid='false'])) {\n --limel-text-editor-outline-color: var(--lime-error-text-color);\n}\n\n:host(limel-text-editor[readonly]:not([readonly='false'])) {\n --limel-text-editor-padding: 0.75rem 1rem 0.75rem 1rem;\n --limel-text-editor-placeholder-top: 0;\n --limel-text-editor-outline-color: transparent;\n --limel-text-editor-background-color: transparent;\n\n limel-markdown {\n // displayed when `readonly` instead of the adapter\n display: block;\n padding: var(--limel-text-editor-padding);\n overflow-y: auto;\n\n &:before,\n &:after {\n z-index: 1;\n pointer-events: none;\n content: '';\n display: block;\n position: absolute;\n width: 100%;\n }\n &:after {\n height: 1.75rem;\n top: 0;\n background: linear-gradient(\n var(\n --text-editor-fade-out-background-color,\n rgb(var(--contrast-100))\n ),\n transparent\n );\n }\n\n &:before {\n height: 2rem;\n bottom: -0.25rem;\n background: linear-gradient(\n transparent,\n var(\n --text-editor-fade-out-background-color,\n rgb(var(--contrast-100))\n )\n );\n }\n }\n}\n\n.notched-outline {\n transition: bottom\n var(--limel-h-l-grid-template-rows-transition-speed, 0.46s)\n cubic-bezier(1, 0.09, 0, 0.89);\n pointer-events: none;\n position: absolute;\n inset: 0;\n bottom: var(--limel-text-editor-notched-outline-bottom, 0);\n\n display: flex;\n background-color: var(--limel-text-editor-background-color);\n}\n\n.leading-outline,\n.notch,\n.trailing-outline {\n transition: border-color 0.2s ease;\n border-width: 1px;\n border-style: solid;\n border-color: var(--limel-text-editor-outline-color);\n}\n\n.leading-outline {\n flex-shrink: 0;\n width: 0.75rem;\n border-right-width: 0;\n border-top-left-radius: 0.25rem;\n border-bottom-left-radius: 0.25rem;\n}\n\n.notch {\n flex-shrink: 0;\n\n position: relative;\n z-index: 2;\n\n border-top-width: 0;\n border-right-width: 0;\n border-left-width: 0;\n\n max-width: calc(100% - 1.5rem);\n}\n\n.trailing-outline {\n flex-grow: 1;\n border-left-width: 0;\n border-top-right-radius: 0.25rem;\n border-bottom-right-radius: 0.25rem;\n}\n\nlabel {\n transform: translateY(-50%);\n\n @include mixins.truncate-text;\n display: block;\n padding: 0 0.25rem;\n\n color: var(--limel-text-editor-label-color);\n font-size: 0.65rem; // `10.4px` similar to MDC's floating label\n letter-spacing: var(--mdc-typography-subtitle1-letter-spacing, 0.009375em);\n\n :host(limel-text-editor[required]) & {\n &::after {\n content: '*';\n }\n }\n}\n\n.placeholder {\n transition-property: top, padding;\n transition-duration: var(\n --limel-prosemirror-adapter-toolbar-grid-template-rows-transition-duration\n );\n transition-timing-function: var(\n --limel-prosemirror-adapter-toolbar-transition-timing-function\n );\n @include mixins.truncate-text;\n pointer-events: none;\n position: absolute;\n top: var(--limel-text-editor-placeholder-top, 2.25rem);\n left: 0;\n right: 0;\n\n padding: var(--limel-text-editor-padding);\n font-style: italic;\n font-size: 0.875rem;\n color: shared_input-select-picker.$input-placeholder-color;\n}\n\nlimel-prosemirror-adapter {\n flex-grow: 1;\n\n min-width: 0;\n min-height: 0;\n height: 100%;\n overflow: hidden auto;\n}\n\n@include mixins.hide-helper-line-when-not-needed(limel-text-editor);\n:host(limel-text-editor.has-helper-text:focus-within),\n:host(limel-text-editor.has-helper-text[invalid]:not([invalid='false'])) {\n .notched-outline {\n --limel-text-editor-notched-outline-bottom: 1rem;\n }\n}\n\n:host(limel-text-editor[allow-resize]) {\n limel-prosemirror-adapter {\n resize: vertical;\n }\n}\n","import { Component, Event, EventEmitter, Host, Prop, h } from '@stencil/core';\nimport { FormComponent } from '../form/form.types';\nimport { Languages } from '../date-picker/date.types';\nimport { createRandomString } from '../../util/random-string';\nimport { CustomElementDefinition } from '../../global/shared-types/custom-element.types';\nimport { TriggerCharacter, TriggerEventDetail } from './text-editor.types';\nimport { EditorUiType } from './types';\n\n/**\n * A rich text editor that offers a rich text editing experience with markdown support,\n * in the sense that you can easily type markdown syntax and see the rendered\n * result as rich text in real-time. For instance, you can type `# Hello, world!`\n * and see it directly turning to a heading 1 (an `<h1>` HTML element).\n *\n * Naturally, you can use standard keyboard hotkeys such as <kbd>Ctrl</kbd> + <kbd>B</kbd>\n * to toggle bold text, <kbd>Ctrl</kbd> + <kbd>I</kbd> to toggle italic text, and so on.\n *\n * @exampleComponent limel-example-text-editor-basic\n * @exampleComponent limel-example-text-editor-as-form-component\n * @exampleComponent limel-example-text-editor-with-markdown\n * @exampleComponent limel-example-text-editor-with-html\n * @exampleComponent limel-example-text-editor-with-tables\n * @exampleComponent limel-example-text-editor-allow-resize\n * @exampleComponent limel-example-text-editor-size\n * @exampleComponent limel-example-text-editor-ui\n * @exampleComponent limel-example-text-editor-composite\n * @exampleComponent limel-example-text-editor-custom-element\n * @exampleComponent limel-example-text-editor-triggers\n * @beta\n */\n@Component({\n tag: 'limel-text-editor',\n shadow: { delegatesFocus: true },\n styleUrl: 'text-editor.scss',\n})\nexport class TextEditor implements FormComponent<string> {\n /** The type of content that the editor should handle and emit, defaults to `markdown`\n *\n * Assumed to be set only once, so not reactive to changes\n */\n @Prop()\n public contentType: 'markdown' | 'html' = 'markdown';\n\n /**\n * Defines the language for translations.\n */\n @Prop({ reflect: true })\n public language: Languages = 'en';\n\n /**\n * Set to `true` to disable the field.\n * Use `disabled` to indicate that the field can normally be interacted\n * with, but is currently disabled. This tells the user that if certain\n * requirements are met, the field may become enabled again.\n */\n @Prop({ reflect: true })\n public disabled?: boolean = false;\n\n /**\n * Set to `true` to make the component read-only.\n * Use `readonly` when the field is only there to present the data it holds,\n * and will not become possible for the current user to edit.\n * :::note\n * Consider that it might be better to use `limel-markdown`\n * instead of `limel-text-editor` when the goal is visualizing data.\n * :::\n */\n @Prop({ reflect: true })\n public readonly?: boolean = false;\n\n /**\n * Optional helper text to display below the input field when it has focus\n */\n @Prop({ reflect: true })\n public helperText?: string;\n\n /**\n * The placeholder text shown inside the input field,\n * when the field is empty.\n */\n @Prop({ reflect: true })\n public placeholder?: string;\n\n /**\n * The label of the editor\n */\n @Prop({ reflect: true })\n public label?: string;\n\n /**\n * Set to `true` to indicate that the current value of the editor is\n * invalid.\n */\n @Prop({ reflect: true })\n public invalid?: boolean = false;\n\n /**\n * Description of the text inside the editor as markdown\n */\n @Prop({ reflect: true })\n public value: string;\n\n /**\n * A list of custom elements\n *\n * Any `CustomElement` that should be used inside the text editor needs\n * to be defined here.\n *\n * @private\n * @alpha\n */\n @Prop()\n public customElements: CustomElementDefinition[] = [];\n\n /**\n * A set of trigger characters\n *\n * Defining a character here will enable trigger events to be sent if the\n * character is detected in the editor.\n *\n * @private\n * @alpha\n */\n @Prop()\n public triggers: TriggerCharacter[] = [];\n\n /**\n * Set to `true` to indicate that the field is required.\n *\n * :::important\n * An empty but required field is not automatically considered invalid.\n * You must make sure to check the validity of the field on your own,\n * and properly handle the `invalid` state.\n * :::\n */\n @Prop({ reflect: true })\n public required?: boolean = false;\n\n /**\n * Set to `true` to allow the user to vertically resize the editor.\n * Set to `false` to disable the resize functionality.\n */\n @Prop({ reflect: true })\n public allowResize: boolean = true;\n\n /**\n * Specifies the visual appearance of the editor.\n *\n * - `standard`: The default editor appearance with a full toolbar and\n * standard layout.\n * - `minimal`: A compact editor appearance, ideal for limited space\n * scenarios such as mobile devices. In this mode, the toolbar is hidden\n * until the editor is focused.\n */\n @Prop({ reflect: true })\n public ui?: EditorUiType = 'standard';\n\n /**\n * Dispatched when a change is made to the editor\n */\n @Event()\n public change: EventEmitter<string>;\n\n /**\n * Dispatched if a trigger character is detected.\n *\n * @private\n * @alpha\n */\n @Event()\n public triggerStart: EventEmitter<TriggerEventDetail>;\n\n /**\n * Dispatched if a trigger session is ended. That is if the selection\n * goes outside the trigger input or if something is inserted using the\n * supplied `TextEditor` insert function.\n *\n * @private\n * @alpha\n */\n @Event()\n public triggerStop: EventEmitter<TriggerEventDetail>;\n\n /**\n * Dispatched if a input is changed during an active trigger.\n *\n * @private\n * @alpha\n */\n @Event()\n public triggerChange: EventEmitter<TriggerEventDetail>;\n\n private helperTextId: string;\n private editorId: string;\n\n public constructor() {\n this.helperTextId = createRandomString();\n this.editorId = createRandomString();\n }\n\n public render() {\n return (\n <Host\n class={{\n 'has-helper-text': !!this.helperText,\n }}\n >\n <span class=\"notched-outline\">\n <span class=\"leading-outline\" />\n {this.renderLabel()}\n <span class=\"trailing-outline\" />\n </span>\n {this.renderEditor()}\n </Host>\n );\n }\n\n private renderEditor() {\n if (this.readonly && !this.value) {\n return [\n <span class=\"lime-looks-like-input-value\">–</span>,\n this.renderHelperLine(),\n ];\n }\n\n if (this.readonly) {\n return [\n <limel-markdown\n value={this.value}\n aria-controls={this.helperTextId}\n id={this.editorId}\n />,\n this.renderPlaceholder(),\n this.renderHelperLine(),\n ];\n }\n\n return [\n <limel-prosemirror-adapter\n aria-placeholder={this.placeholder}\n contentType={this.contentType}\n onChange={this.handleChange}\n customElements={this.customElements}\n value={this.value}\n aria-controls={this.helperTextId}\n id={this.editorId}\n aria-disabled={this.disabled}\n language={this.language}\n triggerCharacters={this.triggers}\n disabled={this.disabled}\n />,\n this.renderPlaceholder(),\n this.renderHelperLine(),\n ];\n }\n\n private renderLabel() {\n if (!this.label) {\n return;\n }\n\n return (\n <span class=\"notch\">\n <label htmlFor={this.editorId}>{this.label}</label>\n </span>\n );\n }\n\n private renderPlaceholder() {\n if (!this.placeholder || this.value) {\n return;\n }\n\n return (\n <span class=\"placeholder\" aria-hidden=\"true\">\n {this.placeholder}\n </span>\n );\n }\n\n private renderHelperLine = () => {\n if (!this.helperText) {\n return;\n }\n\n return (\n <limel-helper-line\n helperText={this.helperText}\n helperTextId={this.helperTextId}\n invalid={this.isInvalid()}\n />\n );\n };\n\n private isInvalid = () => {\n if (this.readonly) {\n // A readonly field can never be invalid.\n return false;\n }\n\n if (this.invalid) {\n return true;\n }\n };\n\n private handleChange = (event: CustomEvent<string>) => {\n event.stopPropagation();\n this.change.emit(event.detail);\n };\n}\n"],"version":3}
1
+ {"file":"limel-text-editor.entry.cjs.js","mappings":"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","names":["h","createRandomString","Host"],"sources":["./src/components/text-editor/text-editor.scss?tag=limel-text-editor&encapsulation=shadow","./src/components/text-editor/text-editor.tsx"],"sourcesContent":["@use '../../style/internal/shared_input-select-picker';\n@use '../../style/mixins.scss';\n\n/**\n * @prop --text-editor-max-height: the tallest height the text editor can become when auto-resizing itself. Defaults to `calc(100vh - (env(safe-area-inset-top) + env(safe-area-inset-bottom)) - 4rem)`.\n * @prop --text-editor-fade-out-background-color: the color of the fade-out effect at the top and bottom of the text editor, when the text-editor is in readonly state. Defaults to rgb(var(--contrast-100)).\n */\n\n@include shared_input-select-picker.lime-looks-like-input-value;\n.lime-looks-like-input-value {\n padding: var(--limel-text-editor-padding);\n}\n\n* {\n box-sizing: border-box;\n}\n\n:host(limel-text-editor) {\n --limel-text-editor-outline-color: #{shared_input-select-picker.$lime-text-field-outline-color};\n --limel-text-editor-background-color: #{shared_input-select-picker.$background-color-normal};\n --limel-text-editor-label-color: #{shared_input-select-picker.$label-color};\n --limel-prosemirror-adapter-toolbar-opacity: 0.6;\n --limel-text-editor-padding: 0.25rem 1rem 0.75rem 1rem;\n --limel-prosemirror-adapter-toolbar-grid-template-rows: 1fr;\n --limel-prosemirror-adapter-toolbar-grid-template-rows-transition-duration: 0.3s;\n --limel-prosemirror-adapter-toolbar-transition-timing-function: cubic-bezier(\n 0.19,\n 0.23,\n 0.26,\n 0.89\n );\n\n position: relative;\n isolation: isolate;\n display: flex;\n flex-direction: column;\n\n width: 100%;\n min-width: 5rem;\n min-height: 5rem;\n height: 100%;\n max-height: var(\n --text-editor-max-height,\n calc(\n 100vh - (env(safe-area-inset-top) + env(safe-area-inset-bottom)) -\n 4rem\n )\n );\n padding: 1px; // prevents visual defects that can appear due to the backdrop-filter and closeness to borders\n}\n\n:host(limel-text-editor:focus-within),\n:host(limel-text-editor:not([ui='minimal']):hover) {\n --limel-prosemirror-adapter-toolbar-opacity: 1;\n}\n\n:host(limel-text-editor[ui='minimal']:not(:focus-within)) {\n --limel-text-editor-padding: 0.75rem 1rem 0.75rem 1rem;\n --limel-prosemirror-adapter-toolbar-grid-template-rows: 0fr;\n --limel-prosemirror-adapter-toolbar-grid-template-rows-transition-duration: 0.46s;\n --limel-prosemirror-adapter-action-bar-padding-top-bottom: 0;\n --limel-prosemirror-adapter-toolbar-opacity: 0;\n --limel-text-editor-placeholder-top: 0;\n min-height: 2.5rem;\n}\n\n:host(limel-text-editor:hover) {\n --limel-text-editor-outline-color: #{shared_input-select-picker.$lime-text-field-outline-color--hovered};\n}\n\n:host(limel-text-editor:focus-within) {\n --limel-text-editor-outline-color: #{shared_input-select-picker.$lime-text-field-outline-color--focused};\n}\n\n:host(limel-text-editor:focus-within),\n:host(limel-text-editor:focus) {\n .placeholder {\n opacity: 0;\n }\n}\n\n:host(limel-text-editor[disabled]:not([disabled='false'])) {\n @include shared_input-select-picker.looks-disabled;\n\n limel-prosemirror-adapter {\n pointer-events: none;\n }\n}\n\n:host(limel-text-editor[invalid]:not([invalid='false'])) {\n --limel-text-editor-outline-color: var(--lime-error-text-color);\n}\n\n:host(limel-text-editor[readonly]:not([readonly='false'])) {\n --limel-text-editor-padding: 0.75rem 1rem 0.75rem 1rem;\n --limel-text-editor-placeholder-top: 0;\n --limel-text-editor-outline-color: transparent;\n --limel-text-editor-background-color: transparent;\n\n limel-markdown {\n // displayed when `readonly` instead of the adapter\n display: block;\n padding: var(--limel-text-editor-padding);\n overflow-y: auto;\n\n &:before,\n &:after {\n z-index: 1;\n pointer-events: none;\n content: '';\n display: block;\n position: absolute;\n width: 100%;\n }\n &:after {\n height: 1.75rem;\n top: 0;\n background: linear-gradient(\n var(\n --text-editor-fade-out-background-color,\n rgb(var(--contrast-100))\n ),\n transparent\n );\n }\n\n &:before {\n height: 2rem;\n bottom: -0.25rem;\n background: linear-gradient(\n transparent,\n var(\n --text-editor-fade-out-background-color,\n rgb(var(--contrast-100))\n )\n );\n }\n }\n}\n\n.notched-outline {\n transition: bottom\n var(--limel-h-l-grid-template-rows-transition-speed, 0.46s)\n cubic-bezier(1, 0.09, 0, 0.89);\n pointer-events: none;\n position: absolute;\n inset: 0;\n bottom: var(--limel-text-editor-notched-outline-bottom, 0);\n\n display: flex;\n background-color: var(--limel-text-editor-background-color);\n}\n\n.leading-outline,\n.notch,\n.trailing-outline {\n transition: border-color 0.2s ease;\n border-width: 1px;\n border-style: solid;\n border-color: var(--limel-text-editor-outline-color);\n}\n\n.leading-outline {\n flex-shrink: 0;\n width: 0.75rem;\n border-right-width: 0;\n border-top-left-radius: 0.25rem;\n border-bottom-left-radius: 0.25rem;\n}\n\n.notch {\n flex-shrink: 0;\n\n position: relative;\n z-index: 2;\n\n border-top-width: 0;\n border-right-width: 0;\n border-left-width: 0;\n\n max-width: calc(100% - 1.5rem);\n}\n\n.trailing-outline {\n flex-grow: 1;\n border-left-width: 0;\n border-top-right-radius: 0.25rem;\n border-bottom-right-radius: 0.25rem;\n}\n\nlabel {\n transform: translateY(-50%);\n\n @include mixins.truncate-text;\n display: block;\n padding: 0 0.25rem;\n\n color: var(--limel-text-editor-label-color);\n font-size: 0.65rem; // `10.4px` similar to MDC's floating label\n letter-spacing: var(--mdc-typography-subtitle1-letter-spacing, 0.009375em);\n\n :host(limel-text-editor[required]) & {\n &::after {\n content: '*';\n }\n }\n}\n\n.placeholder {\n transition-property: top, padding;\n transition-duration: var(\n --limel-prosemirror-adapter-toolbar-grid-template-rows-transition-duration\n );\n transition-timing-function: var(\n --limel-prosemirror-adapter-toolbar-transition-timing-function\n );\n @include mixins.truncate-text;\n pointer-events: none;\n position: absolute;\n top: var(--limel-text-editor-placeholder-top, 2.25rem);\n left: 0;\n right: 0;\n\n padding: var(--limel-text-editor-padding);\n font-style: italic;\n font-size: 0.875rem;\n color: shared_input-select-picker.$input-placeholder-color;\n}\n\nlimel-prosemirror-adapter {\n flex-grow: 1;\n\n min-width: 0;\n min-height: 0;\n height: 100%;\n overflow: hidden auto;\n}\n\n@include mixins.hide-helper-line-when-not-needed(limel-text-editor);\n:host(limel-text-editor.has-helper-text:focus-within),\n:host(limel-text-editor.has-helper-text[invalid]:not([invalid='false'])) {\n .notched-outline {\n --limel-text-editor-notched-outline-bottom: 1rem;\n }\n}\n\n:host(limel-text-editor[allow-resize]) {\n limel-prosemirror-adapter {\n resize: vertical;\n }\n}\n","import { Component, Event, EventEmitter, Host, Prop, h } from '@stencil/core';\nimport { FormComponent } from '../form/form.types';\nimport { Languages } from '../date-picker/date.types';\nimport { createRandomString } from '../../util/random-string';\nimport { CustomElementDefinition } from '../../global/shared-types/custom-element.types';\nimport { TriggerCharacter, TriggerEventDetail } from './text-editor.types';\nimport { EditorUiType } from './types';\n\n/**\n * A rich text editor that offers a rich text editing experience with markdown support,\n * in the sense that you can easily type markdown syntax and see the rendered\n * result as rich text in real-time. For instance, you can type `# Hello, world!`\n * and see it directly turning to a heading 1 (an `<h1>` HTML element).\n *\n * Naturally, you can use standard keyboard hotkeys such as <kbd>Ctrl</kbd> + <kbd>B</kbd>\n * to toggle bold text, <kbd>Ctrl</kbd> + <kbd>I</kbd> to toggle italic text, and so on.\n *\n * @exampleComponent limel-example-text-editor-basic\n * @exampleComponent limel-example-text-editor-as-form-component\n * @exampleComponent limel-example-text-editor-with-markdown\n * @exampleComponent limel-example-text-editor-with-html\n * @exampleComponent limel-example-text-editor-with-tables\n * @exampleComponent limel-example-text-editor-allow-resize\n * @exampleComponent limel-example-text-editor-size\n * @exampleComponent limel-example-text-editor-ui\n * @exampleComponent limel-example-text-editor-custom-element\n * @exampleComponent limel-example-text-editor-triggers\n * @exampleComponent limel-example-text-editor-composite\n * @beta\n */\n@Component({\n tag: 'limel-text-editor',\n shadow: { delegatesFocus: true },\n styleUrl: 'text-editor.scss',\n})\nexport class TextEditor implements FormComponent<string> {\n /** The type of content that the editor should handle and emit, defaults to `markdown`\n *\n * Assumed to be set only once, so not reactive to changes\n */\n @Prop()\n public contentType: 'markdown' | 'html' = 'markdown';\n\n /**\n * Defines the language for translations.\n */\n @Prop({ reflect: true })\n public language: Languages = 'en';\n\n /**\n * Set to `true` to disable the field.\n * Use `disabled` to indicate that the field can normally be interacted\n * with, but is currently disabled. This tells the user that if certain\n * requirements are met, the field may become enabled again.\n */\n @Prop({ reflect: true })\n public disabled?: boolean = false;\n\n /**\n * Set to `true` to make the component read-only.\n * Use `readonly` when the field is only there to present the data it holds,\n * and will not become possible for the current user to edit.\n * :::note\n * Consider that it might be better to use `limel-markdown`\n * instead of `limel-text-editor` when the goal is visualizing data.\n * :::\n */\n @Prop({ reflect: true })\n public readonly?: boolean = false;\n\n /**\n * Optional helper text to display below the input field when it has focus\n */\n @Prop({ reflect: true })\n public helperText?: string;\n\n /**\n * The placeholder text shown inside the input field,\n * when the field is empty.\n */\n @Prop({ reflect: true })\n public placeholder?: string;\n\n /**\n * The label of the editor\n */\n @Prop({ reflect: true })\n public label?: string;\n\n /**\n * Set to `true` to indicate that the current value of the editor is\n * invalid.\n */\n @Prop({ reflect: true })\n public invalid?: boolean = false;\n\n /**\n * Description of the text inside the editor as markdown\n */\n @Prop({ reflect: true })\n public value: string;\n\n /**\n * A list of custom elements\n *\n * Any `CustomElement` that should be used inside the text editor needs\n * to be defined here.\n *\n * @private\n * @alpha\n */\n @Prop()\n public customElements: CustomElementDefinition[] = [];\n\n /**\n * A set of trigger characters\n *\n * Defining a character here will enable trigger events to be sent if the\n * character is detected in the editor.\n *\n * @private\n * @alpha\n */\n @Prop()\n public triggers: TriggerCharacter[] = [];\n\n /**\n * Set to `true` to indicate that the field is required.\n *\n * :::important\n * An empty but required field is not automatically considered invalid.\n * You must make sure to check the validity of the field on your own,\n * and properly handle the `invalid` state.\n * :::\n */\n @Prop({ reflect: true })\n public required?: boolean = false;\n\n /**\n * Set to `true` to allow the user to vertically resize the editor.\n * Set to `false` to disable the resize functionality.\n */\n @Prop({ reflect: true })\n public allowResize: boolean = true;\n\n /**\n * Specifies the visual appearance of the editor.\n *\n * - `standard`: The default editor appearance with a full toolbar and\n * standard layout.\n * - `minimal`: A compact editor appearance, ideal for limited space\n * scenarios such as mobile devices. In this mode, the toolbar is hidden\n * until the editor is focused.\n */\n @Prop({ reflect: true })\n public ui?: EditorUiType = 'standard';\n\n /**\n * Dispatched when a change is made to the editor\n */\n @Event()\n public change: EventEmitter<string>;\n\n /**\n * Dispatched if a trigger character is detected.\n *\n * @private\n * @alpha\n */\n @Event()\n public triggerStart: EventEmitter<TriggerEventDetail>;\n\n /**\n * Dispatched if a trigger session is ended. That is if the selection\n * goes outside the trigger input or if something is inserted using the\n * supplied `TextEditor` insert function.\n *\n * @private\n * @alpha\n */\n @Event()\n public triggerStop: EventEmitter<TriggerEventDetail>;\n\n /**\n * Dispatched if a input is changed during an active trigger.\n *\n * @private\n * @alpha\n */\n @Event()\n public triggerChange: EventEmitter<TriggerEventDetail>;\n\n private helperTextId: string;\n private editorId: string;\n\n public constructor() {\n this.helperTextId = createRandomString();\n this.editorId = createRandomString();\n }\n\n public render() {\n return (\n <Host\n class={{\n 'has-helper-text': !!this.helperText,\n }}\n >\n <span class=\"notched-outline\">\n <span class=\"leading-outline\" />\n {this.renderLabel()}\n <span class=\"trailing-outline\" />\n </span>\n {this.renderEditor()}\n </Host>\n );\n }\n\n private renderEditor() {\n if (this.readonly && !this.value) {\n return [\n <span class=\"lime-looks-like-input-value\">–</span>,\n this.renderHelperLine(),\n ];\n }\n\n if (this.readonly) {\n return [\n <limel-markdown\n value={this.value}\n aria-controls={this.helperTextId}\n id={this.editorId}\n />,\n this.renderPlaceholder(),\n this.renderHelperLine(),\n ];\n }\n\n return [\n <limel-prosemirror-adapter\n aria-placeholder={this.placeholder}\n contentType={this.contentType}\n onChange={this.handleChange}\n customElements={this.customElements}\n value={this.value}\n aria-controls={this.helperTextId}\n id={this.editorId}\n aria-disabled={this.disabled}\n language={this.language}\n triggerCharacters={this.triggers}\n disabled={this.disabled}\n />,\n this.renderPlaceholder(),\n this.renderHelperLine(),\n ];\n }\n\n private renderLabel() {\n if (!this.label) {\n return;\n }\n\n return (\n <span class=\"notch\">\n <label htmlFor={this.editorId}>{this.label}</label>\n </span>\n );\n }\n\n private renderPlaceholder() {\n if (!this.placeholder || this.value) {\n return;\n }\n\n return (\n <span class=\"placeholder\" aria-hidden=\"true\">\n {this.placeholder}\n </span>\n );\n }\n\n private renderHelperLine = () => {\n if (!this.helperText) {\n return;\n }\n\n return (\n <limel-helper-line\n helperText={this.helperText}\n helperTextId={this.helperTextId}\n invalid={this.isInvalid()}\n />\n );\n };\n\n private isInvalid = () => {\n if (this.readonly) {\n // A readonly field can never be invalid.\n return false;\n }\n\n if (this.invalid) {\n return true;\n }\n };\n\n private handleChange = (event: CustomEvent<string>) => {\n event.stopPropagation();\n this.change.emit(event.detail);\n };\n}\n"],"version":3}
@@ -70,7 +70,7 @@ const findEnd = (doc, pos, href) => {
70
70
  */
71
71
  const getLinkDataAtPosition = (view, event) => {
72
72
  const pos = view.posAtCoords({ left: event.clientX, top: event.clientY });
73
- const node = view.state.doc.nodeAt(pos.pos);
73
+ const node = view.state.doc.nodeAt(pos === null || pos === void 0 ? void 0 : pos.pos);
74
74
  if (!node) {
75
75
  return null;
76
76
  }
@@ -1 +1 @@
1
- {"version":3,"file":"link-plugin.js","sourceRoot":"","sources":["../../../../../src/components/text-editor/prosemirror-adapter/plugins/link-plugin.ts"],"names":[],"mappings":"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","sourcesContent":["import { Plugin, PluginKey, TextSelection } from 'prosemirror-state';\nimport { EditorView } from 'prosemirror-view';\nimport { schema } from 'prosemirror-schema-basic';\nimport { Mark } from 'prosemirror-model';\nimport { isExternalLink, isValidUrl } from '../menu/menu-commands';\nimport { EditorMenuTypes, MouseButtons } from '../menu/types';\n\nexport const linkPluginKey = new PluginKey('linkPlugin');\n\nexport type UpdateLinkCallback = (text: string, href: string) => void;\n\nexport interface EditorLinkMenuEventDetail {\n href: string;\n text: string;\n}\n\nconst updateLink = (\n view: EditorView,\n updateLinkCallback?: UpdateLinkCallback,\n) => {\n const { from, to } = view.state.selection;\n\n let text = '';\n let href = '';\n view.state.doc.nodesBetween(from, to, (node, pos) => {\n if (node.type.name !== 'text') {\n return;\n }\n\n const fromInNode = Math.max(0, from - pos);\n const toInNode = Math.min(node.text.length, to - pos);\n\n text += node.text.slice(fromInNode, toInNode);\n\n node.marks.forEach((mark: Mark) => {\n if (mark.type.name === 'link') {\n href = mark.attrs.href;\n }\n });\n });\n\n if (updateLinkCallback) {\n updateLinkCallback(text, href);\n }\n};\n\n/**\n * Finds the start position of the link node ensuring the href matches the original link's href.\n * @param doc - The ProseMirror document.\n * @param pos - The position to start searching from.\n * @param href - The href attribute of the original link mark.\n * @returns The start position of the link node.\n */\nconst findStart = (doc, pos, href) => {\n while (pos > 0) {\n const node = doc.nodeAt(pos - 1);\n if (\n !node?.isText ||\n !node.marks.some(\n (mark: Mark) =>\n mark.type.name === EditorMenuTypes.Link &&\n mark.attrs.href === href,\n )\n ) {\n break;\n }\n\n pos--;\n }\n\n return pos;\n};\n\n/**\n * Finds the end position of the link node ensuring the href matches the original link's href.\n * @param doc - The ProseMirror document.\n * @param pos - The position to start searching from.\n * @param href - The href attribute of the original link mark.\n * @returns The end position of the link node.\n */\nconst findEnd = (doc, pos, href) => {\n while (pos < doc.content.size) {\n const node = doc.nodeAt(pos);\n if (\n !node?.isText ||\n !node.marks.some(\n (mark) =>\n mark.type.name === EditorMenuTypes.Link &&\n mark.attrs.href === href,\n )\n ) {\n break;\n }\n\n pos++;\n }\n\n return pos;\n};\n\n/**\n * Gets the link data at the specified position.\n * @param view - The ProseMirror editor view.\n * @param event - The mouse event.\n * @returns An object containing the link data or null if no link is found.\n */\nconst getLinkDataAtPosition = (view: EditorView, event: MouseEvent) => {\n const pos = view.posAtCoords({ left: event.clientX, top: event.clientY });\n const node = view.state.doc.nodeAt(pos.pos);\n if (!node) {\n return null;\n }\n\n const linkMark = node.marks.find(\n (mark) => mark.type.name === EditorMenuTypes.Link,\n );\n if (!linkMark) {\n return null;\n }\n\n const href = linkMark.attrs.href;\n const from = findStart(view.state.doc, pos.pos, href);\n const to = findEnd(view.state.doc, pos.pos, href);\n const text = view.state.doc.textBetween(from, to, ' ');\n\n return { href: href, text: text, from: from, to: to };\n};\n\nconst processModClickEvent = (view: EditorView, event: MouseEvent): boolean => {\n const { href } = getLinkDataAtPosition(view, event);\n if (href) {\n window.open(href, '_blank');\n\n return true;\n }\n\n return false;\n};\n\nconst openLinkMenu = (view: EditorView, href: string, text: string) => {\n const event = new CustomEvent<EditorLinkMenuEventDetail>(\n 'open-editor-link-menu',\n {\n detail: { href: href, text: text },\n bubbles: true,\n composed: true,\n },\n );\n view.dom.dispatchEvent(event);\n};\n\nlet lastClickTime = 0;\nconst DOUBLE_CLICK_DELAY = 200;\nlet clickTimeout;\n\nconst processClickEvent = (view: EditorView, event: MouseEvent): boolean => {\n const now = Date.now();\n\n if (now - lastClickTime < DOUBLE_CLICK_DELAY) {\n clearTimeout(clickTimeout);\n lastClickTime = now; // Reset lastClickTime to prevent single-click action\n\n return false;\n }\n\n lastClickTime = now;\n\n clickTimeout = setTimeout(() => {\n const linkData = getLinkDataAtPosition(view, event);\n if (linkData) {\n const { href, text, from, to } = linkData;\n const transaction = view.state.tr.setSelection(\n TextSelection.create(view.state.doc, from, to),\n );\n view.dispatch(transaction);\n openLinkMenu(view, href, text);\n }\n }, DOUBLE_CLICK_DELAY);\n\n return true;\n};\n\nconst processPasteEvent = (\n view: EditorView,\n event: ClipboardEvent,\n): boolean => {\n const clipboardData = event.clipboardData;\n if (!clipboardData) {\n return false;\n }\n\n const text = clipboardData.getData('text/plain');\n\n // Process as a link if the text is a valid URL\n if (isValidUrl(text)) {\n pasteAsLink(view, text);\n\n return true;\n }\n\n return false;\n};\n\nconst pasteAsLink = (view: EditorView, href: string) => {\n const { state, dispatch } = view;\n const { from, to } = state.selection;\n const linkMark = schema.marks.link.create({\n href: href,\n title: href,\n target: isExternalLink(href) ? '_blank' : null,\n });\n const selectedText = state.doc.textBetween(from, to, ' ') || href;\n const transaction = state.tr\n .insertText(selectedText, from, to)\n .addMark(from, from + selectedText.length, linkMark);\n\n dispatch(transaction);\n};\n\nexport const createLinkPlugin = (updateLinkCallback?: UpdateLinkCallback) => {\n return new Plugin({\n key: linkPluginKey,\n props: {\n handlePaste: (view, event) => {\n return processPasteEvent(view, event);\n },\n handleDOMEvents: {\n mousedown: (view, event) => {\n if (\n (event.metaKey || event.ctrlKey) &&\n event.button === 0\n ) {\n return processModClickEvent(view, event);\n }\n\n if (event.button !== MouseButtons.Right) {\n // We want to ignore right-clicks\n return processClickEvent(view, event);\n }\n\n return true;\n },\n click: (_view, event) => {\n if (!(event.target instanceof HTMLElement)) {\n return;\n }\n\n // Prevent unhandled navigation and bubbling for link clicks\n const link = event.target.closest('a');\n if (link) {\n event.preventDefault();\n event.stopPropagation();\n }\n },\n },\n },\n view: () => ({\n update: (view) => {\n updateLink(view, updateLinkCallback);\n },\n }),\n });\n};\n"]}
1
+ {"version":3,"file":"link-plugin.js","sourceRoot":"","sources":["../../../../../src/components/text-editor/prosemirror-adapter/plugins/link-plugin.ts"],"names":[],"mappings":"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","sourcesContent":["import { Plugin, PluginKey, TextSelection } from 'prosemirror-state';\nimport { EditorView } from 'prosemirror-view';\nimport { schema } from 'prosemirror-schema-basic';\nimport { Mark } from 'prosemirror-model';\nimport { isExternalLink, isValidUrl } from '../menu/menu-commands';\nimport { EditorMenuTypes, MouseButtons } from '../menu/types';\n\nexport const linkPluginKey = new PluginKey('linkPlugin');\n\nexport type UpdateLinkCallback = (text: string, href: string) => void;\n\nexport interface EditorLinkMenuEventDetail {\n href: string;\n text: string;\n}\n\nconst updateLink = (\n view: EditorView,\n updateLinkCallback?: UpdateLinkCallback,\n) => {\n const { from, to } = view.state.selection;\n\n let text = '';\n let href = '';\n view.state.doc.nodesBetween(from, to, (node, pos) => {\n if (node.type.name !== 'text') {\n return;\n }\n\n const fromInNode = Math.max(0, from - pos);\n const toInNode = Math.min(node.text.length, to - pos);\n\n text += node.text.slice(fromInNode, toInNode);\n\n node.marks.forEach((mark: Mark) => {\n if (mark.type.name === 'link') {\n href = mark.attrs.href;\n }\n });\n });\n\n if (updateLinkCallback) {\n updateLinkCallback(text, href);\n }\n};\n\n/**\n * Finds the start position of the link node ensuring the href matches the original link's href.\n * @param doc - The ProseMirror document.\n * @param pos - The position to start searching from.\n * @param href - The href attribute of the original link mark.\n * @returns The start position of the link node.\n */\nconst findStart = (doc, pos, href) => {\n while (pos > 0) {\n const node = doc.nodeAt(pos - 1);\n if (\n !node?.isText ||\n !node.marks.some(\n (mark: Mark) =>\n mark.type.name === EditorMenuTypes.Link &&\n mark.attrs.href === href,\n )\n ) {\n break;\n }\n\n pos--;\n }\n\n return pos;\n};\n\n/**\n * Finds the end position of the link node ensuring the href matches the original link's href.\n * @param doc - The ProseMirror document.\n * @param pos - The position to start searching from.\n * @param href - The href attribute of the original link mark.\n * @returns The end position of the link node.\n */\nconst findEnd = (doc, pos, href) => {\n while (pos < doc.content.size) {\n const node = doc.nodeAt(pos);\n if (\n !node?.isText ||\n !node.marks.some(\n (mark) =>\n mark.type.name === EditorMenuTypes.Link &&\n mark.attrs.href === href,\n )\n ) {\n break;\n }\n\n pos++;\n }\n\n return pos;\n};\n\n/**\n * Gets the link data at the specified position.\n * @param view - The ProseMirror editor view.\n * @param event - The mouse event.\n * @returns An object containing the link data or null if no link is found.\n */\nconst getLinkDataAtPosition = (view: EditorView, event: MouseEvent) => {\n const pos = view.posAtCoords({ left: event.clientX, top: event.clientY });\n const node = view.state.doc.nodeAt(pos?.pos);\n if (!node) {\n return null;\n }\n\n const linkMark = node.marks.find(\n (mark) => mark.type.name === EditorMenuTypes.Link,\n );\n if (!linkMark) {\n return null;\n }\n\n const href = linkMark.attrs.href;\n const from = findStart(view.state.doc, pos.pos, href);\n const to = findEnd(view.state.doc, pos.pos, href);\n const text = view.state.doc.textBetween(from, to, ' ');\n\n return { href: href, text: text, from: from, to: to };\n};\n\nconst processModClickEvent = (view: EditorView, event: MouseEvent): boolean => {\n const { href } = getLinkDataAtPosition(view, event);\n if (href) {\n window.open(href, '_blank');\n\n return true;\n }\n\n return false;\n};\n\nconst openLinkMenu = (view: EditorView, href: string, text: string) => {\n const event = new CustomEvent<EditorLinkMenuEventDetail>(\n 'open-editor-link-menu',\n {\n detail: { href: href, text: text },\n bubbles: true,\n composed: true,\n },\n );\n view.dom.dispatchEvent(event);\n};\n\nlet lastClickTime = 0;\nconst DOUBLE_CLICK_DELAY = 200;\nlet clickTimeout;\n\nconst processClickEvent = (view: EditorView, event: MouseEvent): boolean => {\n const now = Date.now();\n\n if (now - lastClickTime < DOUBLE_CLICK_DELAY) {\n clearTimeout(clickTimeout);\n lastClickTime = now; // Reset lastClickTime to prevent single-click action\n\n return false;\n }\n\n lastClickTime = now;\n\n clickTimeout = setTimeout(() => {\n const linkData = getLinkDataAtPosition(view, event);\n if (linkData) {\n const { href, text, from, to } = linkData;\n const transaction = view.state.tr.setSelection(\n TextSelection.create(view.state.doc, from, to),\n );\n view.dispatch(transaction);\n openLinkMenu(view, href, text);\n }\n }, DOUBLE_CLICK_DELAY);\n\n return true;\n};\n\nconst processPasteEvent = (\n view: EditorView,\n event: ClipboardEvent,\n): boolean => {\n const clipboardData = event.clipboardData;\n if (!clipboardData) {\n return false;\n }\n\n const text = clipboardData.getData('text/plain');\n\n // Process as a link if the text is a valid URL\n if (isValidUrl(text)) {\n pasteAsLink(view, text);\n\n return true;\n }\n\n return false;\n};\n\nconst pasteAsLink = (view: EditorView, href: string) => {\n const { state, dispatch } = view;\n const { from, to } = state.selection;\n const linkMark = schema.marks.link.create({\n href: href,\n title: href,\n target: isExternalLink(href) ? '_blank' : null,\n });\n const selectedText = state.doc.textBetween(from, to, ' ') || href;\n const transaction = state.tr\n .insertText(selectedText, from, to)\n .addMark(from, from + selectedText.length, linkMark);\n\n dispatch(transaction);\n};\n\nexport const createLinkPlugin = (updateLinkCallback?: UpdateLinkCallback) => {\n return new Plugin({\n key: linkPluginKey,\n props: {\n handlePaste: (view, event) => {\n return processPasteEvent(view, event);\n },\n handleDOMEvents: {\n mousedown: (view, event) => {\n if (\n (event.metaKey || event.ctrlKey) &&\n event.button === 0\n ) {\n return processModClickEvent(view, event);\n }\n\n if (event.button !== MouseButtons.Right) {\n // We want to ignore right-clicks\n return processClickEvent(view, event);\n }\n\n return true;\n },\n click: (_view, event) => {\n if (!(event.target instanceof HTMLElement)) {\n return;\n }\n\n // Prevent unhandled navigation and bubbling for link clicks\n const link = event.target.closest('a');\n if (link) {\n event.preventDefault();\n event.stopPropagation();\n }\n },\n },\n },\n view: () => ({\n update: (view) => {\n updateLink(view, updateLinkCallback);\n },\n }),\n });\n};\n"]}
@@ -0,0 +1,18 @@
1
+ import { detectTriggerRemoval } from './detect-trigger-removal';
2
+ import { monitorTriggeredText } from './monitor-triggered-text';
3
+ export const getAppendTransactionHandler = (getCurrentView, getActiveTrigger, resetActiveTrigger, contentConverter) => {
4
+ return (transactions, _oldState, newState) => {
5
+ const activeTrigger = getActiveTrigger();
6
+ if (!activeTrigger) {
7
+ return;
8
+ }
9
+ const triggerRemoved = detectTriggerRemoval(transactions[0], // Pass the first transaction
10
+ activeTrigger, resetActiveTrigger, contentConverter, getCurrentView());
11
+ if (triggerRemoved) {
12
+ resetActiveTrigger();
13
+ return;
14
+ }
15
+ monitorTriggeredText(newState.doc, activeTrigger, newState.selection.from, contentConverter, getCurrentView());
16
+ };
17
+ };
18
+ //# sourceMappingURL=append-transaction-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"append-transaction-handler.js","sourceRoot":"","sources":["../../../../../../../src/components/text-editor/prosemirror-adapter/plugins/trigger/factory-helpers/append-transaction-handler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAMhE,MAAM,CAAC,MAAM,2BAA2B,GAAG,CACvC,cAAuC,EACvC,gBAAsC,EACtC,kBAA8B,EAC9B,gBAAsC,EACxC,EAAE;EACA,OAAO,CACH,YAA2B,EAC3B,SAAsB,EACtB,QAAqB,EACV,EAAE;IACb,MAAM,aAAa,GAAG,gBAAgB,EAAE,CAAC;IAEzC,IAAI,CAAC,aAAa,EAAE;MAChB,OAAO;KACV;IAED,MAAM,cAAc,GAAG,oBAAoB,CACvC,YAAY,CAAC,CAAC,CAAC,EAAE,6BAA6B;IAC9C,aAAa,EACb,kBAAkB,EAClB,gBAAgB,EAChB,cAAc,EAAE,CACnB,CAAC;IAEF,IAAI,cAAc,EAAE;MAChB,kBAAkB,EAAE,CAAC;MAErB,OAAO;KACV;IAED,oBAAoB,CAChB,QAAQ,CAAC,GAAG,EACZ,aAAa,EACb,QAAQ,CAAC,SAAS,CAAC,IAAI,EACvB,gBAAgB,EAChB,cAAc,EAAE,CACnB,CAAC;EACN,CAAC,CAAC;AACN,CAAC,CAAC","sourcesContent":["import { detectTriggerRemoval } from './detect-trigger-removal';\nimport { monitorTriggeredText } from './monitor-triggered-text';\nimport { EditorState, Transaction } from 'prosemirror-state';\nimport { EditorView } from 'prosemirror-view';\nimport { ContentTypeConverter } from '../../../../utils/content-type-converter';\nimport { Trigger } from 'src/components/text-editor/text-editor.types';\n\nexport const getAppendTransactionHandler = (\n getCurrentView: () => EditorView | null,\n getActiveTrigger: () => Trigger | null,\n resetActiveTrigger: () => void,\n contentConverter: ContentTypeConverter,\n) => {\n return (\n transactions: Transaction[],\n _oldState: EditorState,\n newState: EditorState,\n ): Transaction => {\n const activeTrigger = getActiveTrigger();\n\n if (!activeTrigger) {\n return;\n }\n\n const triggerRemoved = detectTriggerRemoval(\n transactions[0], // Pass the first transaction\n activeTrigger,\n resetActiveTrigger,\n contentConverter,\n getCurrentView(),\n );\n\n if (triggerRemoved) {\n resetActiveTrigger();\n\n return;\n }\n\n monitorTriggeredText(\n newState.doc,\n activeTrigger,\n newState.selection.from,\n contentConverter,\n getCurrentView(),\n );\n };\n};\n"]}
@@ -0,0 +1,26 @@
1
+ import { sendTriggerEvent } from './send-trigger-event';
2
+ import { ReplaceStep } from 'prosemirror-transform'; // Import specific step types
3
+ export const detectTriggerRemoval = (transaction, activeTrigger, resetActiveTrigger, contentConverter, view) => {
4
+ if (!activeTrigger || activeTrigger.position < 1) {
5
+ return false;
6
+ }
7
+ for (const step of transaction.steps) {
8
+ if (step instanceof ReplaceStep) {
9
+ const { from, to, slice } = step; // Access properties specific to ReplaceStep
10
+ // Check if the step affects the trigger position
11
+ if (from <= activeTrigger.position &&
12
+ to >= activeTrigger.position) {
13
+ const text = slice.content.textBetween(0, slice.content.size, '');
14
+ // Check if the trigger character has been removed
15
+ // `text` is the text after the step has been applied
16
+ if (!text.includes(activeTrigger.character)) {
17
+ resetActiveTrigger();
18
+ sendTriggerEvent('triggerStop', view, contentConverter, activeTrigger, '');
19
+ return true;
20
+ }
21
+ }
22
+ }
23
+ }
24
+ return false;
25
+ };
26
+ //# sourceMappingURL=detect-trigger-removal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect-trigger-removal.js","sourceRoot":"","sources":["../../../../../../../src/components/text-editor/prosemirror-adapter/plugins/trigger/factory-helpers/detect-trigger-removal.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAGxD,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC,CAAC,6BAA6B;AAElF,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAChC,WAAwB,EACxB,aAA6B,EAC7B,kBAA8B,EAC9B,gBAAsC,EACtC,IAAgB,EACT,EAAE;EACT,IAAI,CAAC,aAAa,IAAI,aAAa,CAAC,QAAQ,GAAG,CAAC,EAAE;IAC9C,OAAO,KAAK,CAAC;GAChB;EAED,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,KAAK,EAAE;IAClC,IAAI,IAAI,YAAY,WAAW,EAAE;MAC7B,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,CAAC,4CAA4C;MAE9E,iDAAiD;MACjD,IACI,IAAI,IAAI,aAAa,CAAC,QAAQ;QAC9B,EAAE,IAAI,aAAa,CAAC,QAAQ,EAC9B;QACE,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,WAAW,CAClC,CAAC,EACD,KAAK,CAAC,OAAO,CAAC,IAAI,EAClB,EAAE,CACL,CAAC;QAEF,kDAAkD;QAClD,qDAAqD;QACrD,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,SAAS,CAAC,EAAE;UACzC,kBAAkB,EAAE,CAAC;UACrB,gBAAgB,CACZ,aAAa,EACb,IAAI,EACJ,gBAAgB,EAChB,aAAa,EACb,EAAE,CACL,CAAC;UAEF,OAAO,IAAI,CAAC;SACf;OACJ;KACJ;GACJ;EAED,OAAO,KAAK,CAAC;AACjB,CAAC,CAAC","sourcesContent":["import { Transaction } from 'prosemirror-state';\nimport { EditorView } from 'prosemirror-view';\nimport { sendTriggerEvent } from './send-trigger-event';\nimport { ContentTypeConverter } from '../../../../utils/content-type-converter';\nimport { Trigger } from 'src/components/text-editor/text-editor.types';\nimport { ReplaceStep } from 'prosemirror-transform'; // Import specific step types\n\nexport const detectTriggerRemoval = (\n transaction: Transaction,\n activeTrigger: Trigger | null,\n resetActiveTrigger: () => void,\n contentConverter: ContentTypeConverter,\n view: EditorView,\n): boolean => {\n if (!activeTrigger || activeTrigger.position < 1) {\n return false;\n }\n\n for (const step of transaction.steps) {\n if (step instanceof ReplaceStep) {\n const { from, to, slice } = step; // Access properties specific to ReplaceStep\n\n // Check if the step affects the trigger position\n if (\n from <= activeTrigger.position &&\n to >= activeTrigger.position\n ) {\n const text = slice.content.textBetween(\n 0,\n slice.content.size,\n '',\n );\n\n // Check if the trigger character has been removed\n // `text` is the text after the step has been applied\n if (!text.includes(activeTrigger.character)) {\n resetActiveTrigger();\n sendTriggerEvent(\n 'triggerStop',\n view,\n contentConverter,\n activeTrigger,\n '',\n );\n\n return true;\n }\n }\n }\n }\n\n return false;\n};\n"]}
@@ -0,0 +1,10 @@
1
+ import { inserterFactory } from '../inserter';
2
+ export const getTriggerEventDetail = (view, contentConverter, trigger, value) => {
3
+ const returnValue = {
4
+ trigger: trigger.character,
5
+ textEditor: inserterFactory(view, contentConverter, trigger),
6
+ value: value,
7
+ };
8
+ return returnValue;
9
+ };
10
+ //# sourceMappingURL=get-trigger-event-detail.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-trigger-event-detail.js","sourceRoot":"","sources":["../../../../../../../src/components/text-editor/prosemirror-adapter/plugins/trigger/factory-helpers/get-trigger-event-detail.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,MAAM,CAAC,MAAM,qBAAqB,GAAG,CACjC,IAAgB,EAChB,gBAAsC,EACtC,OAAgB,EAChB,KAAa,EACK,EAAE;EACpB,MAAM,WAAW,GAAG;IAChB,OAAO,EAAE,OAAO,CAAC,SAAS;IAC1B,UAAU,EAAE,eAAe,CAAC,IAAI,EAAE,gBAAgB,EAAE,OAAO,CAAC;IAC5D,KAAK,EAAE,KAAK;GACf,CAAC;EAEF,OAAO,WAAW,CAAC;AACvB,CAAC,CAAC","sourcesContent":["import { EditorView } from 'prosemirror-view';\nimport {\n Trigger,\n TriggerEventDetail,\n} from 'src/components/text-editor/text-editor.types';\nimport { ContentTypeConverter } from 'src/components/text-editor/utils/content-type-converter';\nimport { inserterFactory } from '../inserter';\n\nexport const getTriggerEventDetail = (\n view: EditorView,\n contentConverter: ContentTypeConverter,\n trigger: Trigger,\n value: string,\n): TriggerEventDetail => {\n const returnValue = {\n trigger: trigger.character,\n textEditor: inserterFactory(view, contentConverter, trigger),\n value: value,\n };\n\n return returnValue;\n};\n"]}
@@ -0,0 +1,11 @@
1
+ import { sendTriggerEvent } from './send-trigger-event';
2
+ export const monitorTriggeredText = (doc, activeTrigger, cursorPosition, contentConverter, view) => {
3
+ let newValue = '';
4
+ if (cursorPosition > activeTrigger.position) {
5
+ // Start extracting text after the trigger character
6
+ newValue = doc.textBetween(activeTrigger.position + 1, cursorPosition, '');
7
+ }
8
+ sendTriggerEvent('triggerChange', view, contentConverter, activeTrigger, newValue);
9
+ return newValue;
10
+ };
11
+ //# sourceMappingURL=monitor-triggered-text.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"monitor-triggered-text.js","sourceRoot":"","sources":["../../../../../../../src/components/text-editor/prosemirror-adapter/plugins/trigger/factory-helpers/monitor-triggered-text.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAExD,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAChC,GAAQ,EACR,aAAsB,EACtB,cAAsB,EACtB,gBAAsC,EACtC,IAAgB,EACV,EAAE;EACR,IAAI,QAAQ,GAAG,EAAE,CAAC;EAClB,IAAI,cAAc,GAAG,aAAa,CAAC,QAAQ,EAAE;IACzC,oDAAoD;IACpD,QAAQ,GAAG,GAAG,CAAC,WAAW,CACtB,aAAa,CAAC,QAAQ,GAAG,CAAC,EAC1B,cAAc,EACd,EAAE,CACL,CAAC;GACL;EAED,gBAAgB,CACZ,eAAe,EACf,IAAI,EACJ,gBAAgB,EAChB,aAAa,EACb,QAAQ,CACX,CAAC;EAEF,OAAO,QAAQ,CAAC;AACpB,CAAC,CAAC","sourcesContent":["import { EditorView } from 'prosemirror-view';\nimport { Trigger } from 'src/components/text-editor/text-editor.types';\nimport { ContentTypeConverter } from 'src/components/text-editor/utils/content-type-converter';\nimport { sendTriggerEvent } from './send-trigger-event';\n\nexport const monitorTriggeredText = (\n doc: any,\n activeTrigger: Trigger,\n cursorPosition: number,\n contentConverter: ContentTypeConverter,\n view: EditorView,\n): string => {\n let newValue = '';\n if (cursorPosition > activeTrigger.position) {\n // Start extracting text after the trigger character\n newValue = doc.textBetween(\n activeTrigger.position + 1,\n cursorPosition,\n '',\n );\n }\n\n sendTriggerEvent(\n 'triggerChange',\n view,\n contentConverter,\n activeTrigger,\n newValue,\n );\n\n return newValue;\n};\n"]}
@@ -0,0 +1,10 @@
1
+ import { getTriggerEventDetail } from './get-trigger-event-detail';
2
+ export const sendTriggerEvent = (type, view, contentConverter, trigger, value) => {
3
+ const event = new CustomEvent(type, {
4
+ detail: getTriggerEventDetail(view, contentConverter, trigger, value),
5
+ bubbles: true,
6
+ composed: true,
7
+ });
8
+ view.dom.dispatchEvent(event);
9
+ };
10
+ //# sourceMappingURL=send-trigger-event.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"send-trigger-event.js","sourceRoot":"","sources":["../../../../../../../src/components/text-editor/prosemirror-adapter/plugins/trigger/factory-helpers/send-trigger-event.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAEnE,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAC5B,IAAsD,EACtD,IAAgB,EAChB,gBAAsC,EACtC,OAAgB,EAChB,KAAa,EACf,EAAE;EACA,MAAM,KAAK,GAAG,IAAI,WAAW,CAAqB,IAAI,EAAE;IACpD,MAAM,EAAE,qBAAqB,CAAC,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,KAAK,CAAC;IACrE,OAAO,EAAE,IAAI;IACb,QAAQ,EAAE,IAAI;GACjB,CAAC,CAAC;EACH,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;AAClC,CAAC,CAAC","sourcesContent":["import { EditorView } from 'prosemirror-view';\nimport {\n Trigger,\n TriggerEventDetail,\n} from 'src/components/text-editor/text-editor.types';\nimport { ContentTypeConverter } from '../../../../utils/content-type-converter';\nimport { getTriggerEventDetail } from './get-trigger-event-detail';\n\nexport const sendTriggerEvent = (\n type: 'triggerStart' | 'triggerStop' | 'triggerChange',\n view: EditorView,\n contentConverter: ContentTypeConverter,\n trigger: Trigger,\n value: string,\n) => {\n const event = new CustomEvent<TriggerEventDetail>(type, {\n detail: getTriggerEventDetail(view, contentConverter, trigger, value),\n bubbles: true,\n composed: true,\n });\n view.dom.dispatchEvent(event);\n};\n"]}
@@ -0,0 +1,20 @@
1
+ import { sendTriggerEvent } from './send-trigger-event';
2
+ export const getTextInputHandler = (contentConverter, triggerCharacters, updateActiveTrigger) => {
3
+ return (view, _from, _to, text) => {
4
+ if (!triggerCharacters.includes(text)) {
5
+ return false;
6
+ }
7
+ const doc = view.state.doc;
8
+ const precedingText = doc.textBetween(_from - 1, _from, '');
9
+ if (/\s/.test(precedingText) || precedingText === '') {
10
+ const trigger = {
11
+ character: text,
12
+ position: _from,
13
+ };
14
+ updateActiveTrigger(trigger);
15
+ sendTriggerEvent('triggerStart', view, contentConverter, trigger, text);
16
+ }
17
+ return false;
18
+ };
19
+ };
20
+ //# sourceMappingURL=text-input-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text-input-handler.js","sourceRoot":"","sources":["../../../../../../../src/components/text-editor/prosemirror-adapter/plugins/trigger/factory-helpers/text-input-handler.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAOxD,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAC/B,gBAAsC,EACtC,iBAAqC,EACrC,mBAAsD,EACxD,EAAE;EACA,OAAO,CACH,IAAgB,EAChB,KAAa,EACb,GAAW,EACX,IAAY,EACL,EAAE;IACT,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,IAAwB,CAAC,EAAE;MACvD,OAAO,KAAK,CAAC;KAChB;IAED,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC;IAC3B,MAAM,aAAa,GAAG,GAAG,CAAC,WAAW,CAAC,KAAK,GAAG,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;IAE5D,IAAI,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,aAAa,KAAK,EAAE,EAAE;MAClD,MAAM,OAAO,GAAG;QACZ,SAAS,EAAE,IAAwB;QACnC,QAAQ,EAAE,KAAK;OAClB,CAAC;MAEF,mBAAmB,CAAC,OAAO,CAAC,CAAC;MAC7B,gBAAgB,CACZ,cAAc,EACd,IAAI,EACJ,gBAAgB,EAChB,OAAO,EACP,IAAI,CACP,CAAC;KACL;IAED,OAAO,KAAK,CAAC;EACjB,CAAC,CAAC;AACN,CAAC,CAAC","sourcesContent":["/* eslint-disable sonarjs/no-invariant-returns */\nimport { EditorView } from 'prosemirror-view';\nimport { sendTriggerEvent } from './send-trigger-event';\nimport {\n Trigger,\n TriggerCharacter,\n} from 'src/components/text-editor/text-editor.types';\nimport { ContentTypeConverter } from '../../../../utils/content-type-converter';\n\nexport const getTextInputHandler = (\n contentConverter: ContentTypeConverter,\n triggerCharacters: TriggerCharacter[],\n updateActiveTrigger: (trigger: Trigger | null) => void,\n) => {\n return (\n view: EditorView,\n _from: number,\n _to: number,\n text: string,\n ): boolean => {\n if (!triggerCharacters.includes(text as TriggerCharacter)) {\n return false;\n }\n\n const doc = view.state.doc;\n const precedingText = doc.textBetween(_from - 1, _from, '');\n\n if (/\\s/.test(precedingText) || precedingText === '') {\n const trigger = {\n character: text as TriggerCharacter,\n position: _from,\n };\n\n updateActiveTrigger(trigger);\n sendTriggerEvent(\n 'triggerStart',\n view,\n contentConverter,\n trigger,\n text,\n );\n }\n\n return false;\n };\n};\n"]}
@@ -1,127 +1,24 @@
1
1
  import { Plugin, PluginKey } from 'prosemirror-state';
2
- import { ReplaceStep, ReplaceAroundStep } from 'prosemirror-transform';
3
- import { inserterFactory } from './inserter';
4
- const isTrigger = (key, validTriggers) => {
5
- return key.length === 1 && validTriggers.includes(key);
6
- };
7
- const shouldTrigger = (state) => {
8
- const { $from } = state.selection;
9
- if ($from.pos === 1) {
10
- return true;
11
- }
12
- // Getting the position immediately before the current selection
13
- const prevPos = $from.pos - 1;
14
- if (prevPos > 0) {
15
- // allow trigger if the cursor is at the start of a new paragraph
16
- if ($from.parentOffset === 0) {
17
- return true;
18
- }
19
- const prevChar = state.doc.textBetween(prevPos, $from.pos);
20
- return prevChar === ' ' || prevChar === '\n';
21
- }
22
- return false;
23
- };
24
- const stillHasTrigger = (state, activeTrigger, triggerPosition, triggerLength) => {
25
- const cursorPosition = state.selection.$from.pos;
26
- if (cursorPosition < triggerPosition ||
27
- cursorPosition > triggerPosition + triggerLength + 1) {
28
- return false;
29
- }
30
- return (state.doc.textBetween(triggerPosition, triggerPosition + 1) ===
31
- activeTrigger);
32
- };
33
- const getTriggerEventDetail = (view, contentConverter, trigger, value) => {
34
- return {
35
- trigger: trigger,
36
- textEditor: inserterFactory(view, contentConverter),
37
- value: value,
38
- };
39
- };
40
- const sendTriggerEvent = (type, view, contentConverter, trigger, value) => {
41
- const event = new CustomEvent(type, {
42
- detail: getTriggerEventDetail(view, contentConverter, trigger, value),
43
- bubbles: true,
44
- composed: true,
45
- });
46
- view.dom.dispatchEvent(event);
47
- };
48
- const processTransactions = (text, transactions, oldState) => {
49
- let textAdded = '';
50
- let textRemoved = '';
51
- transactions.forEach((transaction) => {
52
- if (transaction.docChanged) {
53
- transaction.steps.forEach((step) => {
54
- if (step instanceof ReplaceStep ||
55
- step instanceof ReplaceAroundStep) {
56
- const slice = step.slice;
57
- const fromPos = step.from;
58
- const toPos = step.to;
59
- if (slice === null || slice === void 0 ? void 0 : slice.size) {
60
- // Text added
61
- textAdded += slice.content.textBetween(0, slice.size);
62
- }
63
- else if (fromPos !== toPos) {
64
- // Text removed
65
- const removedText = oldState.doc.textBetween(fromPos, toPos);
66
- textRemoved += removedText;
67
- }
68
- }
69
- });
70
- }
71
- });
72
- if (textAdded) {
73
- text += textAdded;
74
- }
75
- else if (textRemoved) {
76
- text = text.slice(0, -textRemoved.length);
77
- }
78
- return text;
79
- };
2
+ import { getTextInputHandler } from './factory-helpers/text-input-handler';
3
+ import { getAppendTransactionHandler } from './factory-helpers/append-transaction-handler';
4
+ import { sendTriggerEvent } from './factory-helpers/send-trigger-event';
80
5
  export const createTriggerPlugin = (triggerCharacters, contentConverter) => {
81
- let activeTrigger = null;
82
- let triggerText = '';
83
6
  let pluginView = null;
84
- let triggerPosition = null;
85
- const stopTrigger = () => {
86
- triggerText = '';
87
- sendTriggerEvent('triggerStop', pluginView, contentConverter, activeTrigger, triggerText);
88
- triggerPosition = null;
89
- activeTrigger = null;
7
+ let activeTrigger = null;
8
+ const getCurrentView = () => {
9
+ return pluginView;
90
10
  };
91
- const handleKeyDown = (_, event) => {
92
- if (event.key === 'Escape') {
93
- stopTrigger();
94
- return true;
95
- }
96
- return false;
11
+ const getActiveTrigger = () => {
12
+ return activeTrigger;
97
13
  };
98
- const handleInput = (view, event) => {
99
- const { state } = view;
100
- if (event.inputType === 'insertText' &&
101
- isTrigger(event.data, triggerCharacters) &&
102
- shouldTrigger(state)) {
103
- activeTrigger = event.data;
104
- triggerText = '';
105
- triggerPosition = state.selection.$from.pos - triggerText.length;
106
- sendTriggerEvent('triggerStart', view, contentConverter, activeTrigger, triggerText);
107
- return false;
108
- }
109
- return false;
14
+ const resetActiveTrigger = () => {
15
+ activeTrigger = null;
110
16
  };
111
- const appendTransactions = (transactions, oldState, newState) => {
112
- if (!activeTrigger || !triggerPosition || !pluginView) {
113
- return;
114
- }
115
- if (!stillHasTrigger(newState, activeTrigger, triggerPosition, triggerText.length)) {
116
- stopTrigger();
117
- return;
118
- }
119
- const updatedText = processTransactions(triggerText, transactions, oldState);
120
- if (updatedText !== triggerText) {
121
- triggerText = updatedText;
122
- sendTriggerEvent('triggerChange', pluginView, contentConverter, activeTrigger, triggerText.slice(1));
123
- }
17
+ const updateActiveTrigger = (trigger) => {
18
+ activeTrigger = trigger;
124
19
  };
20
+ const textInputHandler = getTextInputHandler(contentConverter, triggerCharacters, updateActiveTrigger);
21
+ const appendTransactionHandler = getAppendTransactionHandler(getCurrentView, getActiveTrigger, resetActiveTrigger, contentConverter);
125
22
  return new Plugin({
126
23
  key: new PluginKey('triggerPlugin'),
127
24
  view: (view) => {
@@ -134,18 +31,16 @@ export const createTriggerPlugin = (triggerCharacters, contentConverter) => {
134
31
  },
135
32
  apply: (transaction) => {
136
33
  if (transaction.getMeta('stopTrigger')) {
137
- stopTrigger();
34
+ sendTriggerEvent('triggerStop', pluginView, contentConverter, activeTrigger, '');
35
+ resetActiveTrigger();
138
36
  }
139
37
  return {};
140
38
  },
141
39
  },
142
40
  props: {
143
- handleKeyDown: handleKeyDown,
144
- handleDOMEvents: {
145
- input: handleInput,
146
- },
41
+ handleTextInput: textInputHandler,
147
42
  },
148
- appendTransaction: appendTransactions,
43
+ appendTransaction: appendTransactionHandler,
149
44
  });
150
45
  };
151
46
  //# sourceMappingURL=factory.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"factory.js","sourceRoot":"","sources":["../../../../../../src/components/text-editor/prosemirror-adapter/plugins/trigger/factory.ts"],"names":[],"mappings":"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","sourcesContent":["import { Plugin, PluginKey, EditorState, Transaction } from 'prosemirror-state';\nimport { ReplaceStep, ReplaceAroundStep } from 'prosemirror-transform';\nimport { EditorView } from 'prosemirror-view';\nimport { inserterFactory } from './inserter';\nimport {\n TriggerCharacter,\n TriggerEventDetail,\n} from 'src/components/text-editor/text-editor.types';\nimport { ContentTypeConverter } from '../../../utils/content-type-converter';\n\nconst isTrigger = (\n key: string,\n validTriggers: TriggerCharacter[],\n): key is TriggerCharacter => {\n return key.length === 1 && validTriggers.includes(key as TriggerCharacter);\n};\n\nconst shouldTrigger = (state: EditorState): boolean => {\n const { $from } = state.selection;\n\n if ($from.pos === 1) {\n return true;\n }\n\n // Getting the position immediately before the current selection\n const prevPos = $from.pos - 1;\n\n if (prevPos > 0) {\n // allow trigger if the cursor is at the start of a new paragraph\n if ($from.parentOffset === 0) {\n return true;\n }\n\n const prevChar = state.doc.textBetween(prevPos, $from.pos);\n\n return prevChar === ' ' || prevChar === '\\n';\n }\n\n return false;\n};\n\nconst stillHasTrigger = (\n state: EditorState,\n activeTrigger: string,\n triggerPosition: number,\n triggerLength: number,\n): boolean => {\n const cursorPosition = state.selection.$from.pos;\n\n if (\n cursorPosition < triggerPosition ||\n cursorPosition > triggerPosition + triggerLength + 1\n ) {\n return false;\n }\n\n return (\n state.doc.textBetween(triggerPosition, triggerPosition + 1) ===\n activeTrigger\n );\n};\n\nconst getTriggerEventDetail = (\n view: EditorView,\n contentConverter: ContentTypeConverter,\n trigger: TriggerCharacter,\n value: string,\n): TriggerEventDetail => {\n return {\n trigger: trigger,\n textEditor: inserterFactory(view, contentConverter),\n value: value,\n };\n};\n\nconst sendTriggerEvent = (\n type: 'triggerStart' | 'triggerStop' | 'triggerChange',\n view: EditorView,\n contentConverter: ContentTypeConverter,\n trigger: TriggerCharacter,\n value: string,\n) => {\n const event = new CustomEvent<TriggerEventDetail>(type, {\n detail: getTriggerEventDetail(view, contentConverter, trigger, value),\n bubbles: true,\n composed: true,\n });\n view.dom.dispatchEvent(event);\n};\n\nconst processTransactions = (\n text: string,\n transactions: Transaction[],\n oldState: EditorState,\n): string => {\n let textAdded = '';\n let textRemoved = '';\n\n transactions.forEach((transaction) => {\n if (transaction.docChanged) {\n transaction.steps.forEach((step) => {\n if (\n step instanceof ReplaceStep ||\n step instanceof ReplaceAroundStep\n ) {\n const slice = step.slice;\n const fromPos = step.from;\n const toPos = step.to;\n\n if (slice?.size) {\n // Text added\n textAdded += slice.content.textBetween(0, slice.size);\n } else if (fromPos !== toPos) {\n // Text removed\n const removedText = oldState.doc.textBetween(\n fromPos,\n toPos,\n );\n textRemoved += removedText;\n }\n }\n });\n }\n });\n\n if (textAdded) {\n text += textAdded;\n } else if (textRemoved) {\n text = text.slice(0, -textRemoved.length);\n }\n\n return text;\n};\n\nexport const createTriggerPlugin = (\n triggerCharacters: TriggerCharacter[],\n contentConverter: ContentTypeConverter,\n) => {\n let activeTrigger: TriggerCharacter | null = null;\n let triggerText = '';\n let pluginView: EditorView | null = null;\n let triggerPosition: number | null = null;\n\n const stopTrigger = () => {\n triggerText = '';\n sendTriggerEvent(\n 'triggerStop',\n pluginView,\n contentConverter,\n activeTrigger,\n triggerText,\n );\n triggerPosition = null;\n activeTrigger = null;\n };\n\n const handleKeyDown = (_: EditorView, event: any) => {\n if (event.key === 'Escape') {\n stopTrigger();\n\n return true;\n }\n\n return false;\n };\n\n const handleInput = (view: EditorView, event: any) => {\n const { state } = view;\n\n if (\n event.inputType === 'insertText' &&\n isTrigger(event.data, triggerCharacters) &&\n shouldTrigger(state)\n ) {\n activeTrigger = event.data;\n triggerText = '';\n triggerPosition = state.selection.$from.pos - triggerText.length;\n sendTriggerEvent(\n 'triggerStart',\n view,\n contentConverter,\n activeTrigger,\n triggerText,\n );\n\n return false;\n }\n\n return false;\n };\n\n const appendTransactions = (\n transactions: Transaction[],\n oldState: EditorState,\n newState: EditorState,\n ): Transaction => {\n if (!activeTrigger || !triggerPosition || !pluginView) {\n return;\n }\n\n if (\n !stillHasTrigger(\n newState,\n activeTrigger,\n triggerPosition,\n triggerText.length,\n )\n ) {\n stopTrigger();\n\n return;\n }\n\n const updatedText = processTransactions(\n triggerText,\n transactions,\n oldState,\n );\n\n if (updatedText !== triggerText) {\n triggerText = updatedText;\n sendTriggerEvent(\n 'triggerChange',\n pluginView,\n contentConverter,\n activeTrigger,\n triggerText.slice(1),\n );\n }\n };\n\n return new Plugin({\n key: new PluginKey('triggerPlugin'),\n view: (view: EditorView) => {\n pluginView = view;\n\n return {};\n },\n state: {\n init: () => {\n return {};\n },\n apply: (transaction: Transaction) => {\n if (transaction.getMeta('stopTrigger')) {\n stopTrigger();\n }\n\n return {};\n },\n },\n props: {\n handleKeyDown: handleKeyDown,\n handleDOMEvents: {\n input: handleInput,\n },\n },\n appendTransaction: appendTransactions,\n });\n};\n"]}
1
+ {"version":3,"file":"factory.js","sourceRoot":"","sources":["../../../../../../src/components/text-editor/prosemirror-adapter/plugins/trigger/factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,SAAS,EAAe,MAAM,mBAAmB,CAAC;AAOnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAC3E,OAAO,EAAE,2BAA2B,EAAE,MAAM,8CAA8C,CAAC;AAC3F,OAAO,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAExE,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAC/B,iBAAqC,EACrC,gBAAsC,EACxC,EAAE;EACA,IAAI,UAAU,GAAsB,IAAI,CAAC;EACzC,IAAI,aAAa,GAAmB,IAAI,CAAC;EAEzC,MAAM,cAAc,GAAG,GAAG,EAAE;IACxB,OAAO,UAAU,CAAC;EACtB,CAAC,CAAC;EAEF,MAAM,gBAAgB,GAAG,GAAG,EAAE;IAC1B,OAAO,aAAa,CAAC;EACzB,CAAC,CAAC;EAEF,MAAM,kBAAkB,GAAG,GAAG,EAAE;IAC5B,aAAa,GAAG,IAAI,CAAC;EACzB,CAAC,CAAC;EAEF,MAAM,mBAAmB,GAAG,CAAC,OAAgB,EAAE,EAAE;IAC7C,aAAa,GAAG,OAAO,CAAC;EAC5B,CAAC,CAAC;EAEF,MAAM,gBAAgB,GAAG,mBAAmB,CACxC,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,CACtB,CAAC;EAEF,MAAM,wBAAwB,GAAG,2BAA2B,CACxD,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,CACnB,CAAC;EAEF,OAAO,IAAI,MAAM,CAAC;IACd,GAAG,EAAE,IAAI,SAAS,CAAC,eAAe,CAAC;IACnC,IAAI,EAAE,CAAC,IAAgB,EAAE,EAAE;MACvB,UAAU,GAAG,IAAI,CAAC;MAElB,OAAO,EAAE,CAAC;IACd,CAAC;IACD,KAAK,EAAE;MACH,IAAI,EAAE,GAAG,EAAE;QACP,OAAO,EAAE,CAAC;MACd,CAAC;MACD,KAAK,EAAE,CAAC,WAAwB,EAAE,EAAE;QAChC,IAAI,WAAW,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE;UACpC,gBAAgB,CACZ,aAAa,EACb,UAAU,EACV,gBAAgB,EAChB,aAAa,EACb,EAAE,CACL,CAAC;UACF,kBAAkB,EAAE,CAAC;SACxB;QAED,OAAO,EAAE,CAAC;MACd,CAAC;KACJ;IACD,KAAK,EAAE;MACH,eAAe,EAAE,gBAAgB;KACpC;IACD,iBAAiB,EAAE,wBAAwB;GAC9C,CAAC,CAAC;AACP,CAAC,CAAC","sourcesContent":["import { Plugin, PluginKey, Transaction } from 'prosemirror-state';\nimport { EditorView } from 'prosemirror-view';\nimport {\n Trigger,\n TriggerCharacter,\n} from 'src/components/text-editor/text-editor.types';\nimport { ContentTypeConverter } from '../../../utils/content-type-converter';\nimport { getTextInputHandler } from './factory-helpers/text-input-handler';\nimport { getAppendTransactionHandler } from './factory-helpers/append-transaction-handler';\nimport { sendTriggerEvent } from './factory-helpers/send-trigger-event';\n\nexport const createTriggerPlugin = (\n triggerCharacters: TriggerCharacter[],\n contentConverter: ContentTypeConverter,\n) => {\n let pluginView: EditorView | null = null;\n let activeTrigger: Trigger | null = null;\n\n const getCurrentView = () => {\n return pluginView;\n };\n\n const getActiveTrigger = () => {\n return activeTrigger;\n };\n\n const resetActiveTrigger = () => {\n activeTrigger = null;\n };\n\n const updateActiveTrigger = (trigger: Trigger) => {\n activeTrigger = trigger;\n };\n\n const textInputHandler = getTextInputHandler(\n contentConverter,\n triggerCharacters,\n updateActiveTrigger,\n );\n\n const appendTransactionHandler = getAppendTransactionHandler(\n getCurrentView,\n getActiveTrigger,\n resetActiveTrigger,\n contentConverter,\n );\n\n return new Plugin({\n key: new PluginKey('triggerPlugin'),\n view: (view: EditorView) => {\n pluginView = view;\n\n return {};\n },\n state: {\n init: () => {\n return {};\n },\n apply: (transaction: Transaction) => {\n if (transaction.getMeta('stopTrigger')) {\n sendTriggerEvent(\n 'triggerStop',\n pluginView,\n contentConverter,\n activeTrigger,\n '',\n );\n resetActiveTrigger();\n }\n\n return {};\n },\n },\n props: {\n handleTextInput: textInputHandler,\n },\n appendTransaction: appendTransactionHandler,\n });\n};\n"]}
@@ -1,13 +1,12 @@
1
1
  import { createHtmlInserter } from './create-html-inserter';
2
- export const inserterFactory = (view, contentConverter) => {
3
- const startPos = getTriggerStartPosition(view);
2
+ export const inserterFactory = (view, contentConverter, trigger) => {
4
3
  return {
5
- insert: createNodeAndTextInserter(view, startPos),
6
- insertHtml: createHtmlInserter(view, contentConverter, startPos, dispatchTransaction),
4
+ insert: createNodeAndTextInserter(view, trigger),
5
+ insertHtml: createHtmlInserter(view, contentConverter, trigger.position, dispatchTransaction),
7
6
  stopTrigger: () => stopTriggerTransaction(view),
8
7
  };
9
8
  };
10
- const createNodeAndTextInserter = (view, startPos) => (input) => {
9
+ const createNodeAndTextInserter = (view, trigger) => (input) => {
11
10
  const schema = view.state.schema;
12
11
  let node;
13
12
  try {
@@ -20,7 +19,7 @@ const createNodeAndTextInserter = (view, startPos) => (input) => {
20
19
  }
21
20
  const spaceNode = schema.text(' ');
22
21
  const fragment = schema.nodes.doc.create(null, [node, spaceNode]);
23
- dispatchTransaction(view, startPos, fragment);
22
+ dispatchTransaction(view, trigger.position, fragment);
24
23
  };
25
24
  const stopTriggerTransaction = (view) => {
26
25
  const { state, dispatch } = view;
@@ -30,8 +29,8 @@ const stopTriggerTransaction = (view) => {
30
29
  };
31
30
  const dispatchTransaction = (view, startPos, fragment) => {
32
31
  const state = view.state;
33
- const dispatch = view.dispatch;
34
32
  const fromPos = state.selection.$from.pos;
33
+ const dispatch = view.dispatch;
35
34
  const transaction = state.tr.replaceWith(startPos, fromPos, fragment);
36
35
  transaction.setMeta('stopTrigger', true);
37
36
  dispatch(transaction);
@@ -58,8 +57,4 @@ const getCustomNode = (name, schema) => {
58
57
  }
59
58
  return customNode;
60
59
  };
61
- const getTriggerStartPosition = (view) => {
62
- var _a, _b, _c;
63
- return (_c = (_b = (_a = view.state) === null || _a === void 0 ? void 0 : _a.selection) === null || _b === void 0 ? void 0 : _b.$from) === null || _c === void 0 ? void 0 : _c.pos;
64
- };
65
60
  //# sourceMappingURL=inserter.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"inserter.js","sourceRoot":"","sources":["../../../../../../src/components/text-editor/prosemirror-adapter/plugins/trigger/inserter.ts"],"names":[],"mappings":"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","sourcesContent":["import { Node, NodeType, Schema, Fragment } from 'prosemirror-model';\nimport { EditorView } from 'prosemirror-view';\nimport {\n TextEditor,\n TextEditorNode,\n} from 'src/components/text-editor/text-editor.types';\nimport { ContentTypeConverter } from '../../../utils/content-type-converter';\nimport { createHtmlInserter } from './create-html-inserter';\n\nexport const inserterFactory = (\n view: EditorView,\n contentConverter: ContentTypeConverter,\n): TextEditor => {\n const startPos = getTriggerStartPosition(view);\n\n return {\n insert: createNodeAndTextInserter(view, startPos),\n insertHtml: createHtmlInserter(\n view,\n contentConverter,\n startPos,\n dispatchTransaction,\n ),\n stopTrigger: () => stopTriggerTransaction(view),\n };\n};\n\nconst createNodeAndTextInserter =\n (view: EditorView, startPos: number) =>\n (input: TextEditorNode | string): void => {\n const schema = view.state.schema;\n let node: Node;\n\n try {\n node = createNode(input, schema);\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error(error.message);\n\n return;\n }\n\n const spaceNode = schema.text(' ');\n\n const fragment = schema.nodes.doc.create(null, [node, spaceNode]);\n\n dispatchTransaction(view, startPos, fragment);\n };\n\nconst stopTriggerTransaction = (view: EditorView): void => {\n const { state, dispatch } = view;\n\n const transaction = state.tr;\n transaction.setMeta('stopTrigger', true);\n\n dispatch(transaction);\n};\n\nconst dispatchTransaction = (\n view: EditorView,\n startPos: number,\n fragment: Fragment | Node,\n): void => {\n const state = view.state;\n const dispatch = view.dispatch;\n const fromPos = state.selection.$from.pos;\n\n const transaction = state.tr.replaceWith(startPos, fromPos, fragment);\n transaction.setMeta('stopTrigger', true);\n dispatch(transaction);\n};\n\nconst createNode = (input: TextEditorNode | string, schema: Schema): Node => {\n if (typeof input === 'string') {\n return schema.text(input);\n }\n\n const node = input.node;\n\n if (typeof node === 'string') {\n return schema.text(node);\n }\n\n const customNode = getCustomNode(node.tagName, schema);\n\n const childNodes: Node[] = (input.children ?? [])\n .map((child) => createNode(child, schema))\n .filter(Boolean);\n\n return customNode.create(node.attributes, childNodes);\n};\n\nconst getCustomNode = (name: string, schema: Schema): NodeType => {\n const customNode = Object.values(schema.nodes).find(\n (prosemirrorNode) => prosemirrorNode.name === name,\n );\n\n if (!customNode) {\n throw new Error(\n `No custom element has been registered for node ${name}`,\n );\n }\n\n return customNode;\n};\n\nconst getTriggerStartPosition = (view: EditorView): number => {\n return view.state?.selection?.$from?.pos;\n};\n"]}
1
+ {"version":3,"file":"inserter.js","sourceRoot":"","sources":["../../../../../../src/components/text-editor/prosemirror-adapter/plugins/trigger/inserter.ts"],"names":[],"mappings":"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","sourcesContent":["import { Node, NodeType, Schema, Fragment } from 'prosemirror-model';\nimport { EditorView } from 'prosemirror-view';\nimport {\n TextEditor,\n TextEditorNode,\n Trigger,\n} from 'src/components/text-editor/text-editor.types';\nimport { ContentTypeConverter } from '../../../utils/content-type-converter';\nimport { createHtmlInserter } from './create-html-inserter';\n\nexport const inserterFactory = (\n view: EditorView,\n contentConverter: ContentTypeConverter,\n trigger: Trigger,\n): TextEditor => {\n return {\n insert: createNodeAndTextInserter(view, trigger),\n insertHtml: createHtmlInserter(\n view,\n contentConverter,\n trigger.position,\n dispatchTransaction,\n ),\n stopTrigger: () => stopTriggerTransaction(view),\n };\n};\n\nconst createNodeAndTextInserter =\n (view: EditorView, trigger: Trigger) =>\n (input: TextEditorNode | string): void => {\n const schema = view.state.schema;\n let node: Node;\n\n try {\n node = createNode(input, schema);\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error(error.message);\n\n return;\n }\n\n const spaceNode = schema.text(' ');\n const fragment = schema.nodes.doc.create(null, [node, spaceNode]);\n\n dispatchTransaction(view, trigger.position, fragment);\n };\n\nconst stopTriggerTransaction = (view: EditorView): void => {\n const { state, dispatch } = view;\n\n const transaction = state.tr;\n transaction.setMeta('stopTrigger', true);\n\n dispatch(transaction);\n};\n\nconst dispatchTransaction = (\n view: EditorView,\n startPos: number,\n fragment: Fragment | Node,\n): void => {\n const state = view.state;\n const fromPos = state.selection.$from.pos;\n const dispatch = view.dispatch;\n const transaction = state.tr.replaceWith(startPos, fromPos, fragment);\n\n transaction.setMeta('stopTrigger', true);\n\n dispatch(transaction);\n};\n\nconst createNode = (input: TextEditorNode | string, schema: Schema): Node => {\n if (typeof input === 'string') {\n return schema.text(input);\n }\n\n const node = input.node;\n\n if (typeof node === 'string') {\n return schema.text(node);\n }\n\n const customNode = getCustomNode(node.tagName, schema);\n\n const childNodes: Node[] = (input.children ?? [])\n .map((child) => createNode(child, schema))\n .filter(Boolean);\n\n return customNode.create(node.attributes, childNodes);\n};\n\nconst getCustomNode = (name: string, schema: Schema): NodeType => {\n const customNode = Object.values(schema.nodes).find(\n (prosemirrorNode) => prosemirrorNode.name === name,\n );\n\n if (!customNode) {\n throw new Error(\n `No custom element has been registered for node ${name}`,\n );\n }\n\n return customNode;\n};\n"]}