@heartlandone/vega 2.102.0 → 2.103.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/{app-globals-49c2a999.js → app-globals-85986306.js} +10 -10
- package/dist/cjs/{code-block-06e6591f.js → code-block-72de6c4d.js} +80 -1
- package/dist/cjs/{component-value-history-controller-slimmer.abstract-f29908f8.js → component-value-history-controller-slimmer.abstract-23d2b3d8.js} +3 -3
- package/dist/cjs/{content-state-8c862e5e.js → content-state-ff40bdc6.js} +38 -5
- package/dist/cjs/{date-required-rule-b672c432.js → date-required-rule-608e704b.js} +1 -1
- package/dist/cjs/{design-token-351ffd2c.js → design-token-a101a8d0.js} +3 -3
- package/dist/cjs/{element-appender-slimmer-f932b166.js → element-appender-slimmer-b93cc564.js} +2 -2
- package/dist/cjs/{form-field-controller-slimmer-5adb86ae.js → form-field-controller-slimmer-124d54ea.js} +1 -1
- package/dist/cjs/{image-annotation-action-25907d6b.js → image-annotation-action-1ee41bc7.js} +2 -2
- package/dist/cjs/{image-extension-1cf84f27.js → image-extension-6a92c524.js} +247 -5
- package/dist/cjs/index.cjs.js +17 -17
- package/dist/cjs/{inject-keyboard-manager-84d33920.js → inject-keyboard-manager-32d7dd0e.js} +1 -1
- package/dist/cjs/{internal-calendar-period-factory-3c5236be.js → internal-calendar-period-factory-c3198ea7.js} +1 -1
- package/dist/cjs/{internal-translation-controller-eae8a8de.js → internal-translation-controller-0d67ca4d.js} +1 -0
- package/dist/cjs/{keyboard-manager-baa83a61.js → keyboard-manager-332eec89.js} +1 -1
- package/dist/cjs/{keyboard-manager-slimmer-d1974b28.js → keyboard-manager-slimmer-a2872981.js} +1 -1
- package/dist/cjs/{link-extension-2a6133b7.js → link-extension-1b4ed437.js} +3 -3
- package/dist/cjs/loader.cjs.js +12 -12
- package/dist/cjs/{month-view-generator-a6827548.js → month-view-generator-b6a2b8be.js} +1 -1
- package/dist/cjs/{public-rules-7f26e0ae.js → public-rules-2066613c.js} +7 -7
- package/dist/cjs/{range-518b95a2.js → range-712fe703.js} +1 -1
- package/dist/cjs/{responsive-format-facade-95c54444.js → responsive-format-facade-44d33457.js} +1 -1
- package/dist/cjs/{rich-text-editor-required-rule-5d0c76ec.js → rich-text-editor-required-rule-1aa75d22.js} +1 -1
- package/dist/cjs/{split-cell-operation-28f6f8d9.js → split-cell-operation-afc82323.js} +3 -3
- package/dist/cjs/{state-border-formatter-6c284859.js → state-border-formatter-49984fd6.js} +1 -1
- package/dist/cjs/{string-format-strategy.abstract-f15b6196.js → string-format-strategy.abstract-bd563c01.js} +1 -1
- package/dist/cjs/{string-input-formatter-slimmer-5a3f1b55.js → string-input-formatter-slimmer-4faebac9.js} +1 -1
- package/dist/cjs/{string-mask-strategy-af6f3ba0.js → string-mask-strategy-624c4398.js} +2 -2
- package/dist/cjs/{style-formatter-324211fd.js → style-formatter-151d89a3.js} +2 -2
- package/dist/cjs/{time-required-rule-9e714442.js → time-required-rule-8cd8f9b9.js} +1 -1
- package/dist/cjs/{token-extension-86723cad.js → token-extension-72d0cb08.js} +1011 -767
- package/dist/cjs/{translation-slimmer-0227ee24.js → translation-slimmer-1771d01f.js} +1 -1
- package/dist/cjs/{type-guard-29e01bd4.js → type-guard-cce6fe1f.js} +1 -1
- package/dist/cjs/{valid-credit-card-number-rule-4ec364af.js → valid-credit-card-number-rule-b13c2fc4.js} +1 -1
- package/dist/cjs/vega-accordion.cjs.entry.js +6 -6
- package/dist/cjs/vega-app-header-button.cjs.entry.js +5 -5
- package/dist/cjs/vega-box.cjs.entry.js +6 -6
- package/dist/cjs/vega-button-circle.cjs.entry.js +5 -5
- package/dist/cjs/vega-button.cjs.entry.js +3 -3
- package/dist/cjs/vega-calendar_5.cjs.entry.js +7 -7
- package/dist/cjs/vega-card.cjs.entry.js +5 -5
- package/dist/cjs/vega-carousel.cjs.entry.js +3 -3
- package/dist/cjs/vega-checkbox_2.cjs.entry.js +2 -2
- package/dist/cjs/vega-chip.cjs.entry.js +5 -5
- package/dist/cjs/vega-code-block.cjs.entry.js +8 -8
- package/dist/cjs/vega-color-picker.cjs.entry.js +2 -2
- package/dist/cjs/vega-color-swatch-picker.cjs.entry.js +3 -3
- package/dist/cjs/vega-color-swatch.cjs.entry.js +2 -2
- package/dist/cjs/vega-combo-box.cjs.entry.js +8 -8
- package/dist/cjs/vega-date-picker_2.cjs.entry.js +13 -13
- package/dist/cjs/vega-dialog_2.cjs.entry.js +3 -3
- package/dist/cjs/vega-divider.cjs.entry.js +5 -5
- package/dist/cjs/vega-dropdown_5.cjs.entry.js +7 -7
- package/dist/cjs/vega-env-manager-23b8b23c.js +2 -2
- package/dist/cjs/vega-field-label.cjs.entry.js +2 -2
- package/dist/cjs/vega-file-uploader.cjs.entry.js +3 -3
- package/dist/cjs/vega-flag-icon.cjs.entry.js +5 -5
- package/dist/cjs/vega-flex.cjs.entry.js +6 -6
- package/dist/cjs/vega-font.cjs.entry.js +5 -5
- package/dist/cjs/vega-form.cjs.entry.js +2 -2
- package/dist/cjs/vega-grid.cjs.entry.js +5 -5
- package/dist/cjs/vega-icon.cjs.entry.js +5 -5
- package/dist/cjs/vega-image-uploader.cjs.entry.js +5 -5
- package/dist/cjs/vega-input-credit-card.cjs.entry.js +6 -6
- package/dist/cjs/vega-input-numeric.cjs.entry.js +12 -14
- package/dist/cjs/vega-input-passcode.cjs.entry.js +5 -5
- package/dist/cjs/vega-input-phone-number.cjs.entry.js +4 -4
- package/dist/cjs/vega-input-range.cjs.entry.js +3 -3
- package/dist/cjs/vega-input-select.cjs.entry.js +5 -5
- package/dist/cjs/vega-input.cjs.entry.js +31 -27
- package/dist/cjs/vega-left-nav_5.cjs.entry.js +7 -7
- package/dist/cjs/vega-loader-wrapper_2.cjs.entry.js +3 -3
- package/dist/cjs/vega-pagination-page-size-selector-mobile.cjs.entry.js +2 -2
- package/dist/cjs/vega-pagination.cjs.entry.js +4 -4
- package/dist/cjs/vega-popover_2.cjs.entry.js +8 -8
- package/dist/cjs/vega-progress-tracker_2.cjs.entry.js +3 -3
- package/dist/cjs/vega-radio_2.cjs.entry.js +5 -5
- package/dist/cjs/vega-rich-text-bookmark-editor.cjs.entry.js +2 -2
- package/dist/cjs/vega-rich-text-content.cjs.entry.js +6 -6
- package/dist/cjs/vega-rich-text-editor_4.cjs.entry.js +474 -207
- package/dist/cjs/vega-rich-text-find-replace-panel.cjs.entry.js +1 -1
- package/dist/cjs/vega-rich-text-special-characters-panel.cjs.entry.js +5 -5
- package/dist/cjs/vega-rich-text-table-properties_3.cjs.entry.js +8 -8
- package/dist/cjs/vega-selection-chip_2.cjs.entry.js +4 -4
- package/dist/cjs/vega-selection-tile_2.cjs.entry.js +2 -2
- package/dist/cjs/vega-sidenav_3.cjs.entry.js +3 -3
- package/dist/cjs/vega-signature-capture.cjs.entry.js +7 -7
- package/dist/cjs/vega-stepper.cjs.entry.js +2 -2
- package/dist/cjs/vega-tab-group_2.cjs.entry.js +6 -6
- package/dist/cjs/vega-table_11.cjs.entry.js +4 -4
- package/dist/cjs/vega-textarea.cjs.entry.js +2 -2
- package/dist/cjs/vega-time-picker_2.cjs.entry.js +9 -9
- package/dist/cjs/vega-toggle-switch.cjs.entry.js +2 -2
- package/dist/cjs/vega-tooltip_2.cjs.entry.js +6 -6
- package/dist/cjs/vega.cjs.js +12 -12
- package/dist/collection/components/vega-input/slimmers/controllers/vega-input-state-controller.js +0 -14
- package/dist/collection/components/vega-input/slimmers/renderers/vega-input-input-container-renderer.js +11 -2
- package/dist/collection/components/vega-input/slimmers/renderers/vega-input-input-renderer.js +11 -1
- package/dist/collection/components/vega-input/vega-input.js +52 -8
- package/dist/collection/components/vega-input-numeric/slimmers/renderers/vega-input-numeric-renderer.js +7 -1
- package/dist/collection/components/vega-input-numeric/vega-input-numeric.js +0 -8
- package/dist/collection/components/vega-rich-text-editor/constants/constant.js +4 -0
- package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/sequential-composition-strategy.js +31 -0
- package/dist/collection/components/vega-rich-text-editor/dto/actions/modify-content-action.abstract.js +1 -0
- package/dist/collection/components/vega-rich-text-editor/dto/actions/sequential-composition-action.js +14 -0
- package/dist/collection/components/vega-rich-text-editor/dto/content-state.js +4 -1
- package/dist/collection/components/vega-rich-text-editor/dto/flush-changes-payload.js +1 -0
- package/dist/collection/components/vega-rich-text-editor/dto/nodes/image-node.js +3 -2
- package/dist/collection/components/vega-rich-text-editor/extensions/functions/dto/function-block.js +30 -0
- package/dist/collection/components/vega-rich-text-editor/extensions/functions/element-to-dto-strategies/div-to-function-block-strategy.js +1 -0
- package/dist/collection/components/vega-rich-text-editor/extensions/paste/controllers/chooser-positioner.js +107 -0
- package/dist/collection/components/vega-rich-text-editor/extensions/paste/controllers/paste-chooser-controller.js +91 -0
- package/dist/collection/components/vega-rich-text-editor/extensions/paste/controllers/paste-event-interceptor.js +47 -0
- package/dist/collection/components/vega-rich-text-editor/extensions/paste/controllers/selection-snapshot-service.js +54 -0
- package/dist/collection/components/vega-rich-text-editor/extensions/paste/parse-local-images-helper/image-extractor.js +17 -0
- package/dist/collection/components/vega-rich-text-editor/extensions/paste/paste-chooser-ui.js +3 -1
- package/dist/collection/components/vega-rich-text-editor/extensions/paste/paste-extension.js +41 -354
- package/dist/collection/components/vega-rich-text-editor/extensions/paste/pipeline/data-transfer-builder.js +36 -0
- package/dist/collection/components/vega-rich-text-editor/extensions/paste/pipeline/paste-dispatcher.js +23 -0
- package/dist/collection/components/vega-rich-text-editor/extensions/paste/pipeline/paste-processing-pipeline.js +30 -0
- package/dist/collection/components/vega-rich-text-editor/extensions/paste/strategies/paste-processing-strategy.abstract.js +34 -0
- package/dist/collection/components/vega-rich-text-editor/extensions/paste/strategies/paste-strategy-selector.js +19 -0
- package/dist/collection/components/vega-rich-text-editor/extensions/paste/strategies/plain-paste-strategy.js +74 -0
- package/dist/collection/components/vega-rich-text-editor/extensions/paste/type.js +1 -0
- package/dist/collection/components/vega-rich-text-editor/helpers/utils.js +67 -0
- package/dist/collection/components/vega-rich-text-editor/slimmers/controllers/helper/input-event-handler/abstract-delete-content-handler.js +67 -11
- package/dist/collection/components/vega-rich-text-editor/slimmers/controllers/helper/input-event-handler/backward-delete-content-handler.js +4 -17
- package/dist/collection/components/vega-rich-text-editor/slimmers/controllers/helper/input-event-handler/base-handler.js +34 -1
- package/dist/collection/components/vega-rich-text-editor/slimmers/controllers/helper/input-event-handler/forward-delete-content-handler.js +13 -32
- package/dist/collection/components/vega-rich-text-editor/slimmers/controllers/helper/input-event-handler/insert-line-break-handler.js +60 -25
- package/dist/collection/components/vega-rich-text-editor/slimmers/controllers/helper/input-event-handler/insert-paragraph-handler.js +55 -19
- package/dist/collection/components/vega-rich-text-editor/slimmers/controllers/helper/input-event-handler/insert-paste-handler.js +165 -59
- package/dist/collection/components/vega-rich-text-editor/slimmers/controllers/helper/input-event-handler/insert-text-handler.js +55 -21
- package/dist/collection/components/vega-rich-text-editor/slimmers/controllers/user-input-controller.js +2 -16
- package/dist/collection/components/vega-rich-text-editor/slimmers/controllers/value-controller.js +11 -1
- package/dist/collection/components/vega-rich-text-editor/utils/html-to-plain-text-utils.js +240 -0
- package/dist/collection/helpers/translation/locales/en.js +1 -0
- package/dist/esm/{app-globals-da5c83c2.js → app-globals-8cdfc5c9.js} +10 -10
- package/dist/esm/{code-block-d8f83d85.js → code-block-9360c331.js} +74 -2
- package/dist/esm/{component-value-history-controller-slimmer.abstract-642e7147.js → component-value-history-controller-slimmer.abstract-9ea58806.js} +3 -3
- package/dist/esm/{content-state-486eae1d.js → content-state-67a12e74.js} +38 -5
- package/dist/esm/{date-required-rule-08695d25.js → date-required-rule-66b5bf02.js} +1 -1
- package/dist/esm/{design-token-df3331d9.js → design-token-acd1efeb.js} +3 -3
- package/dist/esm/{element-appender-slimmer-f02a227f.js → element-appender-slimmer-7e5bc1e9.js} +2 -2
- package/dist/esm/{form-field-controller-slimmer-a7c0a0f8.js → form-field-controller-slimmer-d653c494.js} +1 -1
- package/dist/esm/{image-annotation-action-df744ba5.js → image-annotation-action-9525be48.js} +2 -2
- package/dist/esm/{image-extension-20b39140.js → image-extension-aea75132.js} +246 -6
- package/dist/esm/index.js +17 -17
- package/dist/esm/{inject-keyboard-manager-399ed867.js → inject-keyboard-manager-f6522d2f.js} +1 -1
- package/dist/esm/{internal-calendar-period-factory-7b866c3b.js → internal-calendar-period-factory-261df2f2.js} +1 -1
- package/dist/esm/{internal-translation-controller-4a7ee4d5.js → internal-translation-controller-3637e47e.js} +1 -0
- package/dist/esm/{keyboard-manager-f5d13a34.js → keyboard-manager-53e8d8d0.js} +1 -1
- package/dist/esm/{keyboard-manager-slimmer-f40dcb54.js → keyboard-manager-slimmer-b3de042d.js} +1 -1
- package/dist/esm/{link-extension-3f93d70d.js → link-extension-57ba9520.js} +3 -3
- package/dist/esm/loader.js +12 -12
- package/dist/esm/{month-view-generator-0c665987.js → month-view-generator-15215a09.js} +1 -1
- package/dist/esm/{public-rules-470a1dac.js → public-rules-c77a1550.js} +7 -7
- package/dist/esm/{range-8e89fb54.js → range-3c74e1c8.js} +1 -1
- package/dist/esm/{responsive-format-facade-55131a33.js → responsive-format-facade-1b325d06.js} +1 -1
- package/dist/esm/{rich-text-editor-required-rule-06caf383.js → rich-text-editor-required-rule-cfd32ba2.js} +1 -1
- package/dist/esm/{split-cell-operation-e158366a.js → split-cell-operation-85a036f9.js} +3 -3
- package/dist/esm/{state-border-formatter-2b73fa08.js → state-border-formatter-ce3495b0.js} +1 -1
- package/dist/esm/{string-format-strategy.abstract-8c7937e3.js → string-format-strategy.abstract-8ce04558.js} +1 -1
- package/dist/esm/{string-input-formatter-slimmer-681c6b71.js → string-input-formatter-slimmer-0d60ba7d.js} +1 -1
- package/dist/esm/{string-mask-strategy-b8cceee6.js → string-mask-strategy-cabc1d50.js} +2 -2
- package/dist/esm/{style-formatter-fcd70869.js → style-formatter-00fe4f1c.js} +2 -2
- package/dist/esm/{time-required-rule-ce50859b.js → time-required-rule-57ceeae9.js} +1 -1
- package/dist/esm/{token-extension-2401e753.js → token-extension-645a9520.js} +1011 -767
- package/dist/esm/{translation-slimmer-b3f3cf65.js → translation-slimmer-b69057eb.js} +1 -1
- package/dist/esm/{type-guard-08c82e08.js → type-guard-204094c6.js} +1 -1
- package/dist/esm/{valid-credit-card-number-rule-66bad519.js → valid-credit-card-number-rule-0874e19f.js} +1 -1
- package/dist/esm/vega-accordion.entry.js +6 -6
- package/dist/esm/vega-app-header-button.entry.js +5 -5
- package/dist/esm/vega-box.entry.js +6 -6
- package/dist/esm/vega-button-circle.entry.js +5 -5
- package/dist/esm/vega-button.entry.js +3 -3
- package/dist/esm/vega-calendar_5.entry.js +7 -7
- package/dist/esm/vega-card.entry.js +5 -5
- package/dist/esm/vega-carousel.entry.js +3 -3
- package/dist/esm/vega-checkbox_2.entry.js +2 -2
- package/dist/esm/vega-chip.entry.js +5 -5
- package/dist/esm/vega-code-block.entry.js +8 -8
- package/dist/esm/vega-color-picker.entry.js +2 -2
- package/dist/esm/vega-color-swatch-picker.entry.js +3 -3
- package/dist/esm/vega-color-swatch.entry.js +2 -2
- package/dist/esm/vega-combo-box.entry.js +8 -8
- package/dist/esm/vega-date-picker_2.entry.js +13 -13
- package/dist/esm/vega-dialog_2.entry.js +3 -3
- package/dist/esm/vega-divider.entry.js +5 -5
- package/dist/esm/vega-dropdown_5.entry.js +7 -7
- package/dist/esm/vega-env-manager-8f8dc473.js +2 -2
- package/dist/esm/vega-field-label.entry.js +2 -2
- package/dist/esm/vega-file-uploader.entry.js +3 -3
- package/dist/esm/vega-flag-icon.entry.js +5 -5
- package/dist/esm/vega-flex.entry.js +6 -6
- package/dist/esm/vega-font.entry.js +5 -5
- package/dist/esm/vega-form.entry.js +2 -2
- package/dist/esm/vega-grid.entry.js +5 -5
- package/dist/esm/vega-icon.entry.js +5 -5
- package/dist/esm/vega-image-uploader.entry.js +5 -5
- package/dist/esm/vega-input-credit-card.entry.js +6 -6
- package/dist/esm/vega-input-numeric.entry.js +12 -14
- package/dist/esm/vega-input-passcode.entry.js +5 -5
- package/dist/esm/vega-input-phone-number.entry.js +4 -4
- package/dist/esm/vega-input-range.entry.js +3 -3
- package/dist/esm/vega-input-select.entry.js +5 -5
- package/dist/esm/vega-input.entry.js +31 -27
- package/dist/esm/vega-left-nav_5.entry.js +7 -7
- package/dist/esm/vega-loader-wrapper_2.entry.js +3 -3
- package/dist/esm/vega-pagination-page-size-selector-mobile.entry.js +2 -2
- package/dist/esm/vega-pagination.entry.js +4 -4
- package/dist/esm/vega-popover_2.entry.js +8 -8
- package/dist/esm/vega-progress-tracker_2.entry.js +3 -3
- package/dist/esm/vega-radio_2.entry.js +5 -5
- package/dist/esm/vega-rich-text-bookmark-editor.entry.js +2 -2
- package/dist/esm/vega-rich-text-content.entry.js +6 -6
- package/dist/esm/vega-rich-text-editor_4.entry.js +474 -207
- package/dist/esm/vega-rich-text-find-replace-panel.entry.js +1 -1
- package/dist/esm/vega-rich-text-special-characters-panel.entry.js +5 -5
- package/dist/esm/vega-rich-text-table-properties_3.entry.js +8 -8
- package/dist/esm/vega-selection-chip_2.entry.js +4 -4
- package/dist/esm/vega-selection-tile_2.entry.js +2 -2
- package/dist/esm/vega-sidenav_3.entry.js +3 -3
- package/dist/esm/vega-signature-capture.entry.js +7 -7
- package/dist/esm/vega-stepper.entry.js +2 -2
- package/dist/esm/vega-tab-group_2.entry.js +6 -6
- package/dist/esm/vega-table_11.entry.js +4 -4
- package/dist/esm/vega-textarea.entry.js +2 -2
- package/dist/esm/vega-time-picker_2.entry.js +9 -9
- package/dist/esm/vega-toggle-switch.entry.js +2 -2
- package/dist/esm/vega-tooltip_2.entry.js +6 -6
- package/dist/esm/vega.js +12 -12
- package/dist/sri/vega-sri-manifest.json +321 -321
- package/dist/types/components/vega-input/slimmers/controllers/vega-input-state-controller.d.ts +0 -2
- package/dist/types/components/vega-input/slimmers/renderers/vega-input-input-container-renderer.d.ts +4 -0
- package/dist/types/components/vega-input/slimmers/renderers/vega-input-input-renderer.d.ts +2 -0
- package/dist/types/components/vega-input/vega-input.d.ts +15 -3
- package/dist/types/components/vega-input-numeric/slimmers/renderers/vega-input-numeric-renderer.d.ts +2 -0
- package/dist/types/components/vega-input-numeric/vega-input-numeric.d.ts +0 -2
- package/dist/types/components/vega-rich-text-editor/constants/constant.d.ts +4 -0
- package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/sequential-composition-strategy.d.ts +14 -0
- package/dist/types/components/vega-rich-text-editor/dto/actions/modify-content-action.abstract.d.ts +4 -1
- package/dist/types/components/vega-rich-text-editor/dto/actions/sequential-composition-action.d.ts +30 -0
- package/dist/types/components/vega-rich-text-editor/dto/flush-changes-payload.d.ts +16 -0
- package/dist/types/components/vega-rich-text-editor/extensions/functions/dto/function-block.d.ts +7 -0
- package/dist/types/components/vega-rich-text-editor/extensions/paste/controllers/chooser-positioner.d.ts +33 -0
- package/dist/types/components/vega-rich-text-editor/extensions/paste/controllers/paste-chooser-controller.d.ts +43 -0
- package/dist/types/components/vega-rich-text-editor/extensions/paste/controllers/paste-event-interceptor.d.ts +22 -0
- package/dist/types/components/vega-rich-text-editor/extensions/paste/controllers/selection-snapshot-service.d.ts +29 -0
- package/dist/types/components/vega-rich-text-editor/extensions/paste/parse-local-images-helper/image-extractor.d.ts +13 -0
- package/dist/types/components/vega-rich-text-editor/extensions/paste/parse-local-images-helper/paste-image-parser.d.ts +1 -1
- package/dist/types/components/vega-rich-text-editor/extensions/paste/parse-local-images-helper/pending-image-registry.d.ts +1 -1
- package/dist/types/components/vega-rich-text-editor/extensions/paste/paste-chooser-ui.d.ts +1 -0
- package/dist/types/components/vega-rich-text-editor/extensions/paste/paste-extension.d.ts +28 -93
- package/dist/types/components/vega-rich-text-editor/extensions/paste/pipeline/data-transfer-builder.d.ts +10 -0
- package/dist/types/components/vega-rich-text-editor/extensions/paste/pipeline/paste-dispatcher.d.ts +8 -0
- package/dist/types/components/vega-rich-text-editor/extensions/paste/pipeline/paste-processing-pipeline.d.ts +18 -0
- package/dist/types/components/vega-rich-text-editor/extensions/paste/strategies/paste-processing-strategy.abstract.d.ts +28 -6
- package/dist/types/components/vega-rich-text-editor/extensions/paste/strategies/paste-strategy-selector.d.ts +13 -0
- package/dist/types/components/vega-rich-text-editor/extensions/paste/strategies/plain-paste-strategy.d.ts +29 -0
- package/dist/types/components/vega-rich-text-editor/extensions/paste/type.d.ts +35 -0
- package/dist/types/components/vega-rich-text-editor/helpers/utils.d.ts +47 -0
- package/dist/types/components/vega-rich-text-editor/slimmers/controllers/helper/input-event-handler/abstract-delete-content-handler.d.ts +17 -6
- package/dist/types/components/vega-rich-text-editor/slimmers/controllers/helper/input-event-handler/backward-delete-content-handler.d.ts +5 -1
- package/dist/types/components/vega-rich-text-editor/slimmers/controllers/helper/input-event-handler/base-handler.d.ts +30 -1
- package/dist/types/components/vega-rich-text-editor/slimmers/controllers/helper/input-event-handler/forward-delete-content-handler.d.ts +5 -1
- package/dist/types/components/vega-rich-text-editor/slimmers/controllers/helper/input-event-handler/insert-line-break-handler.d.ts +21 -4
- package/dist/types/components/vega-rich-text-editor/slimmers/controllers/helper/input-event-handler/insert-paragraph-handler.d.ts +12 -4
- package/dist/types/components/vega-rich-text-editor/slimmers/controllers/helper/input-event-handler/insert-paste-handler.d.ts +38 -5
- package/dist/types/components/vega-rich-text-editor/slimmers/controllers/helper/input-event-handler/insert-text-handler.d.ts +7 -2
- package/dist/types/components/vega-rich-text-editor/slimmers/controllers/user-input-controller.d.ts +2 -0
- package/dist/types/components/vega-rich-text-editor/utils/html-to-plain-text-utils.d.ts +31 -0
- package/dist/types/components.d.ts +24 -0
- package/dist/types/helpers/translation/interface.d.ts +1 -0
- package/dist/types/types/public-api.d.ts +2 -1
- package/dist/vega/index.esm.js +1 -1
- package/dist/vega/{p-8a4cc7c2.entry.js → p-0169f71c.entry.js} +1 -1
- package/dist/vega/p-018bb83b.entry.js +1 -0
- package/dist/vega/{p-25e51acb.js → p-08bf08d2.js} +1 -1
- package/dist/vega/{p-85a940c0.entry.js → p-0b33753f.entry.js} +1 -1
- package/dist/vega/{p-a5fa260b.js → p-1537b1e4.js} +1 -1
- package/dist/vega/{p-7dfb1481.entry.js → p-17f6dc94.entry.js} +1 -1
- package/dist/vega/{p-dd673eb4.entry.js → p-1a4d1991.entry.js} +1 -1
- package/dist/vega/{p-557b64bd.js → p-1b2e5898.js} +1 -1
- package/dist/vega/{p-2256eb09.entry.js → p-1f1f93bf.entry.js} +1 -1
- package/dist/vega/{p-d86e0b01.js → p-1fb953f8.js} +1 -1
- package/dist/vega/{p-03efc67a.entry.js → p-2171b571.entry.js} +1 -1
- package/dist/vega/p-255fe20b.js +1 -0
- package/dist/vega/{p-cf5c5515.js → p-261cf764.js} +1 -1
- package/dist/vega/{p-f0b49ae4.entry.js → p-27e77ea1.entry.js} +1 -1
- package/dist/vega/{p-109f0e33.entry.js → p-28acbe42.entry.js} +1 -1
- package/dist/vega/{p-27c9c2a5.entry.js → p-2acc600a.entry.js} +1 -1
- package/dist/vega/p-2fc2299f.js +1 -0
- package/dist/vega/{p-b48caf90.entry.js → p-2ff659a1.entry.js} +1 -1
- package/dist/vega/{p-527c3211.entry.js → p-322da1eb.entry.js} +1 -1
- package/dist/vega/{p-dffe47db.js → p-3283fa2f.js} +1 -1
- package/dist/vega/p-3567dc55.entry.js +1 -0
- package/dist/vega/{p-c6419eb3.entry.js → p-36b795c6.entry.js} +1 -1
- package/dist/vega/p-37714a3a.js +1 -0
- package/dist/vega/{p-d7e59f31.js → p-3b4e2ba0.js} +1 -1
- package/dist/vega/{p-3d060d2f.entry.js → p-3b911043.entry.js} +1 -1
- package/dist/vega/{p-5c6d36ef.entry.js → p-3e270b65.entry.js} +1 -1
- package/dist/vega/{p-b68f55e2.js → p-4043508a.js} +1 -1
- package/dist/vega/p-4151d4a8.js +1 -0
- package/dist/vega/{p-c6b6987e.js → p-45af801f.js} +1 -1
- package/dist/vega/p-48c2150b.entry.js +1 -0
- package/dist/vega/p-4b253f74.entry.js +1 -0
- package/dist/vega/{p-75c7f8ea.entry.js → p-4cdc064d.entry.js} +1 -1
- package/dist/vega/{p-1d8a8507.entry.js → p-4e4b50f3.entry.js} +1 -1
- package/dist/vega/{p-d8fa2f19.entry.js → p-564110ba.entry.js} +1 -1
- package/dist/vega/p-5f377954.js +1 -1
- package/dist/vega/{p-bec31ffc.entry.js → p-608d3559.entry.js} +1 -1
- package/dist/vega/{p-3ce7521e.entry.js → p-64eb05d3.entry.js} +1 -1
- package/dist/vega/{p-2f5c4b61.entry.js → p-66bf209b.entry.js} +1 -1
- package/dist/vega/{p-83f5ef3a.entry.js → p-69eadbd8.entry.js} +1 -1
- package/dist/vega/{p-c66c6fd2.entry.js → p-6c4edee8.entry.js} +1 -1
- package/dist/vega/p-6e16bb3a.js +1 -0
- package/dist/vega/{p-7d748545.entry.js → p-76f4fdba.entry.js} +1 -1
- package/dist/vega/{p-4c6989ae.entry.js → p-7874055b.entry.js} +1 -1
- package/dist/vega/{p-ca60a74b.entry.js → p-7d3d24f6.entry.js} +1 -1
- package/dist/vega/{p-3bfb53e3.js → p-7f9ad7bc.js} +1 -1
- package/dist/vega/{p-18ddc6a4.entry.js → p-8193f4ef.entry.js} +1 -1
- package/dist/vega/{p-816064f2.entry.js → p-8197d172.entry.js} +1 -1
- package/dist/vega/{p-634b138c.entry.js → p-8ac0b1b2.entry.js} +1 -1
- package/dist/vega/{p-553510d8.entry.js → p-8c61db9d.entry.js} +1 -1
- package/dist/vega/{p-061a76c3.entry.js → p-8de29082.entry.js} +1 -1
- package/dist/vega/{p-325b804d.entry.js → p-8e59606f.entry.js} +1 -1
- package/dist/vega/p-8ea41806.js +1 -0
- package/dist/vega/{p-ff9090af.entry.js → p-9153c2f5.entry.js} +1 -1
- package/dist/vega/{p-a0c87e88.entry.js → p-92411f56.entry.js} +1 -1
- package/dist/vega/{p-049e64b1.entry.js → p-94d65dcf.entry.js} +1 -1
- package/dist/vega/{p-a261a675.entry.js → p-9a96fb05.entry.js} +1 -1
- package/dist/vega/{p-7044bb48.js → p-9fcfd738.js} +1 -1
- package/dist/vega/{p-b1e1c7d0.js → p-a2c7a3bc.js} +1 -1
- package/dist/vega/p-a2dcde12.js +1 -0
- package/dist/vega/{p-be0eb72f.js → p-a60d75d9.js} +1 -1
- package/dist/vega/{p-5a347a15.js → p-a9fc4043.js} +1 -1
- package/dist/vega/{p-efef0dfe.entry.js → p-abe5f7f0.entry.js} +1 -1
- package/dist/vega/{p-197388a5.entry.js → p-ac98c189.entry.js} +1 -1
- package/dist/vega/{p-dd273d89.entry.js → p-ade903b3.entry.js} +1 -1
- package/dist/vega/{p-c0eb8c58.js → p-affb40e8.js} +1 -1
- package/dist/vega/{p-277aab9b.js → p-b3a1cd22.js} +1 -1
- package/dist/vega/p-b63a90b3.entry.js +1 -0
- package/dist/vega/{p-f9f96030.entry.js → p-ba050d63.entry.js} +1 -1
- package/dist/vega/{p-bf0b46c1.js → p-ba67eb96.js} +1 -1
- package/dist/vega/{p-f0c6e9c5.entry.js → p-c08ac33f.entry.js} +1 -1
- package/dist/vega/{p-46be74fc.entry.js → p-c7ec97d1.entry.js} +1 -1
- package/dist/vega/{p-effbfc50.entry.js → p-ca1fe571.entry.js} +1 -1
- package/dist/vega/{p-408c3ad4.entry.js → p-cc9fc36a.entry.js} +1 -1
- package/dist/vega/{p-741e064e.entry.js → p-d044d54f.entry.js} +1 -1
- package/dist/vega/{p-0e0e66c9.entry.js → p-d3a9355c.entry.js} +1 -1
- package/dist/vega/p-d5a75228.js +1 -0
- package/dist/vega/{p-76135e80.entry.js → p-dc83fa6b.entry.js} +1 -1
- package/dist/vega/{p-92efdbf0.entry.js → p-dcfce26e.entry.js} +1 -1
- package/dist/vega/p-df9585f6.js +3 -0
- package/dist/vega/{p-f5f26b44.entry.js → p-e2c8a470.entry.js} +1 -1
- package/dist/vega/{p-23781e76.js → p-e33a954f.js} +1 -1
- package/dist/vega/{p-e577dda8.entry.js → p-e5fc6583.entry.js} +1 -1
- package/dist/vega/p-e668cf11.js +1 -0
- package/dist/vega/{p-0338f621.entry.js → p-e6b0a292.entry.js} +1 -1
- package/dist/vega/{p-381d8781.js → p-e84c2589.js} +1 -1
- package/dist/vega/{p-1b97e751.entry.js → p-eb945d34.entry.js} +1 -1
- package/dist/vega/{p-d8a0e3e0.entry.js → p-ebe1dd2b.entry.js} +1 -1
- package/dist/vega/{p-6beaf1c8.entry.js → p-f818bb20.entry.js} +1 -1
- package/dist/vega/p-f981cf2c.js +1 -0
- package/dist/vega/p-f9d09b0c.js +1 -0
- package/dist/vega/{p-4d20a56f.js → p-fdbdf12f.js} +1 -1
- package/dist/vega/{p-48100d38.entry.js → p-fee080b9.entry.js} +1 -1
- package/dist/vega/vega.esm.js +1 -1
- package/package.json +1 -1
- package/dist/vega/p-040bd9ca.js +0 -1
- package/dist/vega/p-087240db.js +0 -1
- package/dist/vega/p-15052b2e.entry.js +0 -1
- package/dist/vega/p-28c16885.js +0 -1
- package/dist/vega/p-30cc31dd.entry.js +0 -1
- package/dist/vega/p-3ec4d710.js +0 -1
- package/dist/vega/p-43ea1e86.js +0 -1
- package/dist/vega/p-7228088b.entry.js +0 -1
- package/dist/vega/p-7f711049.js +0 -1
- package/dist/vega/p-7fd15dd1.js +0 -1
- package/dist/vega/p-85695819.js +0 -1
- package/dist/vega/p-8e1f30ec.entry.js +0 -1
- package/dist/vega/p-9680dfe6.js +0 -1
- package/dist/vega/p-ae12cc3f.js +0 -3
- package/dist/vega/p-c0823f32.js +0 -1
- package/dist/vega/p-c5af2ecc.entry.js +0 -1
- package/dist/vega/p-fa43272c.js +0 -1
|
@@ -7,28 +7,28 @@ import { C as ChangeManager } from './change-manager-6a7eb88c.js';
|
|
|
7
7
|
import { d as domNodeSubjectFactory, D as DomNodeSubjectObserverFactory } from './dom-node-subject-observer-factory-bb7e68a0.js';
|
|
8
8
|
import { s as VegaInternalComponentDidRender, e as VegaInternalRichTextEditorFlushChanges, d as VegaInternalRichTextEditDeleteSelectedNodes, G as VegaInternalRichTextImageClick, H as VegaInternalRichTextImageDeleteButtonClicked, y as VegaInternalCodeBlockBlur, a as VegaInternalPopoverUpdateTarget } from './vega-internal-event-id-02093067.js';
|
|
9
9
|
import { S as SHADOW_ROOT_ELEMENT_SCROLLING, F as FORM_ELEMENT_VALUE_CHANGE } from './static-subject-title-1c86e974.js';
|
|
10
|
-
import {
|
|
11
|
-
import { i as isNonNullable } from './type-guard-
|
|
12
|
-
import { R as RTEDTORendererManager, e as extensionContextManager, V as VegaRTELinkExtension } from './link-extension-
|
|
10
|
+
import { ar as ZERO_WIDTH_SPACE, aw as VegaRTEOneRowHeightPx, R as RTETextNode, ai as BoldAnnotationAction, N as NodeAnnotationTypeEnum, ax as ItalicAnnotationAction, ay as UnderlineAnnotationAction, c as RTETextBlock, az as TextStyleAnnotationAction, a6 as TextStyleAnnotation, aA as BoldAnnotation, aB as BlockAnnotationTypeEnum, aC as ClearFormattingAnnotationAction, aD as CodeAnnotationAction, aE as StrikethroughAnnotationAction, au as SelectionChangeAction, as as LinkAnnotationAction, aF as IndentAnnotationAction, M as ModifyContentAction, j as ModifyContentActionType, r as RTEListItemBlock, a7 as RTEHtmlBlock, aG as TransformParagraphAction, t as RTECodeBlockNode, A as ActionHandleStrategyRegistry, P as HorizontalAlignmentAnnotationAction, aH as RTEUpdateSource, s as stateEntityRenderingRegistry, g as AppendChildrenAction, aI as RTE_UPDATE_SOURCE_KEY, U as UpdateTextAction, h as InsertChildrenBeforeAction, S as SplitBlockWithNodeAction, a as RTENode, b as RTEBlock, l as RemoveChildrenAction, K as ReplaceChildNodesAction, aJ as RTE_PASTE_MODE_PLAIN, ak as normalizePlainTextLines, x as toPlainPasteLines, J as escapeHtml, z as RTE_PASTE_MODE_DATA_TYPE, y as RTE_PRESERVED_WHITESPACE_DATA_TYPE, aK as RTE_PASTE_MODE_WORD, q as RTECodeBlock, I as InsertChildrenAfterAction, D as RTE_WORD_COUNT_KEY, V as VegaRTEPresetToolbarItems, aq as VegaRTEDefaultTextStyleItems, aL as RTE_EMAIL_LINK_TYPE_KEY, aM as RTE_DEFAULT_LINK_TYPE_KEY, aN as RTE_SUPPORTED_LINK_TYPE_KEYS } from './code-block-9360c331.js';
|
|
11
|
+
import { i as isNonNullable } from './type-guard-204094c6.js';
|
|
12
|
+
import { R as RTEDTORendererManager, e as extensionContextManager, V as VegaRTELinkExtension } from './link-extension-57ba9520.js';
|
|
13
13
|
import { V as VegaInternalIconManager } from './internal-icon-manager-d4d534d2.js';
|
|
14
|
-
import { V as VisualModeToolbarButtonSlimmer, I as ImageAnnotationAction, a as ToolbarButtonSlimmer, T as TextColorToolbarButtonSlimmer, n as normalizeUrlByDefaultProtocol } from './image-annotation-action-
|
|
14
|
+
import { V as VisualModeToolbarButtonSlimmer, I as ImageAnnotationAction, a as ToolbarButtonSlimmer, T as TextColorToolbarButtonSlimmer, n as normalizeUrlByDefaultProtocol } from './image-annotation-action-9525be48.js';
|
|
15
15
|
import { d as VegaDropdownClick, c as VegaChange, b as VegaClick, a2 as VegaImageInserted, a3 as VegaSourceCodeChange, a as VegaPopoverShow, V as VegaPopoverHide, T as VegaShow, U as VegaHide } from './vega-event-id-6b4db259.js';
|
|
16
16
|
import { g as generateUUID } from './misc-9fdbcfbb.js';
|
|
17
17
|
import { w as waitForComponentDidRender } from './wait-for-component-did-render-9e84d92d.js';
|
|
18
|
-
import { a as VegaRTEImageExtension, R as ReplaceSelectedTextAction, c as
|
|
19
|
-
import { F as FormFieldControllerSlimmer } from './form-field-controller-slimmer-
|
|
18
|
+
import { a as VegaRTEImageExtension, R as ReplaceSelectedTextAction, h as htmlContainsTable, c as htmlToPlainText, d as bookmarkIcon, e as collectBookmarkNames, V as VegaRTEBookmarkExtension } from './image-extension-aea75132.js';
|
|
19
|
+
import { F as FormFieldControllerSlimmer } from './form-field-controller-slimmer-d653c494.js';
|
|
20
20
|
import { c as createEventEmitSlimmer } from './event-emit-slimmer-aa7f4c6e.js';
|
|
21
21
|
import { c as createSubStateNotifySlimmer } from './sub-state-notify-slimmer-ba72f30b.js';
|
|
22
|
-
import { V as VegaRTEContent, b as RTEImageNode, f as CommitValueAction, M as MergeTwoBlocksNodesAction, I as InsertNewParagraphAction, S as StylePreservator, g as ElementToDtoStrategyProcessor, R as RTEImageBlock } from './content-state-
|
|
22
|
+
import { V as VegaRTEContent, b as RTEImageNode, f as CommitValueAction, U as UpdateCursorPositionAction, M as MergeTwoBlocksNodesAction, I as InsertNewParagraphAction, S as StylePreservator, g as ElementToDtoStrategyProcessor, R as RTEImageBlock } from './content-state-67a12e74.js';
|
|
23
23
|
import { b as AlignLeft, A as AlignCenter, c as AlignRight, a as AlignJustify } from './align-left-7f959adf.js';
|
|
24
|
-
import { R as RTESelectionState, C as ComponentValueHistoryControllerSlimmer, a as SelectionController } from './component-value-history-controller-slimmer.abstract-
|
|
24
|
+
import { R as RTESelectionState, C as ComponentValueHistoryControllerSlimmer, a as SelectionController } from './component-value-history-controller-slimmer.abstract-9ea58806.js';
|
|
25
25
|
import { O as Observer } from './observer-3959f9dd.js';
|
|
26
26
|
import { d as debounce } from './timer-9321173b.js';
|
|
27
27
|
import { D as DarkModeStateControllerSlimmer } from './dark-mode-state-controller-slimmer-778dd929.js';
|
|
28
28
|
import { f as findParent, b as getDeepActiveElementInShadow, j as checkIsVoiceOverClick, k as getFirstFocusableElement } from './ui-80e610f4.js';
|
|
29
|
-
import { R as RichTextEditorRequiredRule } from './rich-text-editor-required-rule-
|
|
29
|
+
import { R as RichTextEditorRequiredRule } from './rich-text-editor-required-rule-cfd32ba2.js';
|
|
30
30
|
import { C as ChildNodesEventPreventSlimmer } from './child-nodes-event-prevent-slimmer-3ae5c7db.js';
|
|
31
|
-
import { T as TranslationSlimmer } from './translation-slimmer-
|
|
31
|
+
import { T as TranslationSlimmer } from './translation-slimmer-b69057eb.js';
|
|
32
32
|
import { V as VegaInternalThemeManager } from './dark-mode-style-controller-4e04a2d3.js';
|
|
33
33
|
import { A as AutoRunWhenReRenderTaskQueueSlimmer } from './auto-run-when-re-render-task-queue-slimmer.abstract-27820d4c.js';
|
|
34
34
|
import { i as isArrayEqual } from './array-7888f339.js';
|
|
@@ -44,7 +44,7 @@ import './discriminated-fe5bf3c8.js';
|
|
|
44
44
|
import './dynamic-slimmer-90b8af32.js';
|
|
45
45
|
import './breakpoints-d9faf11c.js';
|
|
46
46
|
import './ui-93922c59.js';
|
|
47
|
-
import './internal-translation-controller-
|
|
47
|
+
import './internal-translation-controller-3637e47e.js';
|
|
48
48
|
import './icon-manager-236d6c23.js';
|
|
49
49
|
import './try-get-document-bef0f526.js';
|
|
50
50
|
import './vega-nonce-manager-497e5eb5.js';
|
|
@@ -57,9 +57,9 @@ import './mutation-observer-slimmer-58ebc13c.js';
|
|
|
57
57
|
import './mutation-observer-filters-1a054fb0.js';
|
|
58
58
|
import './sub-state-observer-slimmer-bee1c7fa.js';
|
|
59
59
|
import './internal-vega-event-manager-6eebe8f8.js';
|
|
60
|
-
import './range-
|
|
61
|
-
import './keyboard-manager-slimmer-
|
|
62
|
-
import './keyboard-manager-
|
|
60
|
+
import './range-3c74e1c8.js';
|
|
61
|
+
import './keyboard-manager-slimmer-b3de042d.js';
|
|
62
|
+
import './keyboard-manager-53e8d8d0.js';
|
|
63
63
|
import './vega-env-manager-8f8dc473.js';
|
|
64
64
|
import './feature-flag-controller-3fd04ea9.js';
|
|
65
65
|
import './index-9c9865c0.js';
|
|
@@ -2461,7 +2461,17 @@ class ValueController extends VegaSlimmer {
|
|
|
2461
2461
|
const flushChangesWithDebounce = debounce(() => {
|
|
2462
2462
|
void this.valueController.flushChanges(this.value);
|
|
2463
2463
|
}, ValueController.VALUE_CHANGE_DEBOUNCE_TIME, this);
|
|
2464
|
-
this.flushChangeObserver = new Observer(this.isAcceptableFlushChange.bind(this),
|
|
2464
|
+
this.flushChangeObserver = new Observer(this.isAcceptableFlushChange.bind(this), (payload) => {
|
|
2465
|
+
// When a handler asks to bypass the debounce (direct user gestures like `beforeinput`),
|
|
2466
|
+
// invoke `flushChanges` immediately with the payload as-is. Defaults live on the emitter
|
|
2467
|
+
// side (`BaseHandler.flushOptions`) — the observer trusts the payload and does not
|
|
2468
|
+
// re-apply fallback values, so there is a single source of truth.
|
|
2469
|
+
if (payload && payload.bypassDebounce) {
|
|
2470
|
+
void this.valueController.flushChanges(this.value, payload.recordHistory, payload.updateSource);
|
|
2471
|
+
return;
|
|
2472
|
+
}
|
|
2473
|
+
flushChangesWithDebounce();
|
|
2474
|
+
});
|
|
2465
2475
|
ChangeManager.register(domNodeSubjectFactory.getSubject(this.host, VegaInternalRichTextEditorFlushChanges), this.flushChangeObserver);
|
|
2466
2476
|
}
|
|
2467
2477
|
/**
|
|
@@ -2622,12 +2632,44 @@ class RichTextContentController {
|
|
|
2622
2632
|
}
|
|
2623
2633
|
}
|
|
2624
2634
|
|
|
2635
|
+
/**
|
|
2636
|
+
* Applies an ordered list of leaf content actions as one flushable unit, so a `beforeinput` handler
|
|
2637
|
+
* emits a single flush through the shared action pipeline instead of marking each leaf action flushable.
|
|
2638
|
+
*/
|
|
2639
|
+
class SequentialCompositionAction extends ModifyContentAction {
|
|
2640
|
+
constructor(steps, flushPayload = {}) {
|
|
2641
|
+
super();
|
|
2642
|
+
this.steps = steps;
|
|
2643
|
+
this.isFlushable = true;
|
|
2644
|
+
this.type = ModifyContentActionType.SEQUENTIAL_COMPOSITION;
|
|
2645
|
+
this.flushPayload = flushPayload;
|
|
2646
|
+
}
|
|
2647
|
+
}
|
|
2648
|
+
|
|
2625
2649
|
const ROOT_CONTAINER_CLASS_NAME = 'rich-text-content';
|
|
2626
2650
|
/** This code snippet is defining an abstract class named `BaseHandler` with an abstract method `execute`. */
|
|
2627
2651
|
class BaseHandler {
|
|
2652
|
+
constructor() {
|
|
2653
|
+
/**
|
|
2654
|
+
* Default flush payload emitted after `handleEvent` completes. This is the single source of
|
|
2655
|
+
* truth for the defaults — the observer does not re-apply any fallback values. Subclasses may override
|
|
2656
|
+
* this field to opt out of flushing (assign `undefined`) or to change the defaults. Each instance
|
|
2657
|
+
* owns its own copy so mutations from within `handleEvent` (e.g. `InsertTextHandler` updating
|
|
2658
|
+
* `updateSource`) never leak across handler instances.
|
|
2659
|
+
*/
|
|
2660
|
+
this.flushOptions = {
|
|
2661
|
+
bypassDebounce: true,
|
|
2662
|
+
recordHistory: true,
|
|
2663
|
+
updateSource: RTEUpdateSource.Default,
|
|
2664
|
+
};
|
|
2665
|
+
}
|
|
2628
2666
|
/**
|
|
2629
2667
|
* The function `execute` initializes the current state and selection, and then handles an event if provided.
|
|
2630
2668
|
*
|
|
2669
|
+
* Contract: `handleEvent` MUST be synchronous. A handler that mutates the value returns the
|
|
2670
|
+
* `CompositionStep[]` it applied through `applyComposition`; the flush is then routed through the
|
|
2671
|
+
* shared action pipeline. Handlers that do not mutate the value return nothing
|
|
2672
|
+
*
|
|
2631
2673
|
* @param {VegaRTEContent} currentState - The current state of the VegaRTE content.
|
|
2632
2674
|
* @param {SelectionController} selectionController - Manages the selection of items in the user interface.
|
|
2633
2675
|
* @param {HTMLElement} richTextEditor - The current rich text editor component
|
|
@@ -2636,7 +2678,20 @@ class BaseHandler {
|
|
|
2636
2678
|
execute(currentState, selectionController, richTextEditor, event) {
|
|
2637
2679
|
this.initCurrentStateAndSelection(currentState, selectionController);
|
|
2638
2680
|
this.setCurrentRichTextEditor(richTextEditor);
|
|
2639
|
-
this.handleEvent(event);
|
|
2681
|
+
const steps = this.handleEvent(event);
|
|
2682
|
+
this.applyComposition(steps);
|
|
2683
|
+
}
|
|
2684
|
+
/**
|
|
2685
|
+
* Applies the collected leaf actions as a single flushable `SequentialCompositionAction`, so the value
|
|
2686
|
+
* update and its flush run through the same action pipeline used by every other flushable operation.
|
|
2687
|
+
* Handlers call this before enqueuing selection so caret math reads post-apply node state.
|
|
2688
|
+
*
|
|
2689
|
+
* @param {CompositionStep[]} steps - The ordered leaf actions to apply against their own targets.
|
|
2690
|
+
*/
|
|
2691
|
+
applyComposition(steps) {
|
|
2692
|
+
if (Array.isArray(steps)) {
|
|
2693
|
+
this.currentState.apply(new SequentialCompositionAction(steps, this.flushOptions));
|
|
2694
|
+
}
|
|
2640
2695
|
}
|
|
2641
2696
|
/**
|
|
2642
2697
|
* The function `isRootContainer` checks if an HTML element is a root container with a class of 'rich-text-content'.
|
|
@@ -2725,25 +2780,40 @@ class InsertTextHandler extends BaseHandler {
|
|
|
2725
2780
|
* Update the state value when user type character
|
|
2726
2781
|
*
|
|
2727
2782
|
* @param {InputEvent} event - The input event object
|
|
2783
|
+
* @returns {Nullable<CompositionStep[]>} The content actions the base handler applies as one flushable unit.
|
|
2728
2784
|
*/
|
|
2729
2785
|
handleEvent(event) {
|
|
2786
|
+
// The composition input controller stamps its synthesized `beforeinput` events with the
|
|
2787
|
+
// composition update source; pick that up so the flush notification carries the right
|
|
2788
|
+
// source without the caller having to inspect the event.
|
|
2789
|
+
if (this.flushOptions) {
|
|
2790
|
+
this.flushOptions.updateSource =
|
|
2791
|
+
event[RTE_UPDATE_SOURCE_KEY] === RTEUpdateSource.Composition
|
|
2792
|
+
? RTEUpdateSource.Composition
|
|
2793
|
+
: RTEUpdateSource.Default;
|
|
2794
|
+
}
|
|
2730
2795
|
const text = event.data;
|
|
2731
2796
|
const currentRange = this.selectionController.getCurrentRange();
|
|
2732
2797
|
const { startContainer, startOffset } = currentRange;
|
|
2733
2798
|
const selectedNodes = this.selectionController.getSelectedNodes();
|
|
2799
|
+
const steps = [];
|
|
2800
|
+
// The caret move is appended as the final composition step so content + caret apply and flush atomically.
|
|
2801
|
+
let caretNode = null;
|
|
2802
|
+
let caretOffset = 0;
|
|
2803
|
+
let updateFlag = false;
|
|
2734
2804
|
if (selectedNodes.length < 2) {
|
|
2735
2805
|
if (!selectedNodes.length && this.isRootContainer(startContainer)) {
|
|
2736
|
-
|
|
2737
|
-
|
|
2806
|
+
caretNode = this.insertTextToRoot(text, steps);
|
|
2807
|
+
caretOffset = text.length;
|
|
2738
2808
|
}
|
|
2739
2809
|
else if (selectedNodes[0] instanceof RTETextNode) {
|
|
2740
2810
|
if (selectedNodes[0].isContentEditable()) {
|
|
2741
2811
|
let nextOffset = startOffset + text.length;
|
|
2742
|
-
let updateFlag = false;
|
|
2743
2812
|
let cursorNode = selectedNodes[0];
|
|
2744
2813
|
if (cursorNode.text === '\n') {
|
|
2745
|
-
cursorNode = this.insertTextToLineBreakNode(cursorNode, text);
|
|
2746
|
-
|
|
2814
|
+
cursorNode = this.insertTextToLineBreakNode(cursorNode, text, steps);
|
|
2815
|
+
// UpdateTextAction replaces the \n with the input, so the caret lands at the text end.
|
|
2816
|
+
nextOffset = text.length;
|
|
2747
2817
|
}
|
|
2748
2818
|
else {
|
|
2749
2819
|
if (startContainer.nodeValue === ZERO_WIDTH_SPACE &&
|
|
@@ -2752,40 +2822,54 @@ class InsertTextHandler extends BaseHandler {
|
|
|
2752
2822
|
startContainer.nodeValue = '';
|
|
2753
2823
|
nextOffset = nextOffset - ZERO_WIDTH_SPACE.length;
|
|
2754
2824
|
}
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
}
|
|
2825
|
+
steps.push({
|
|
2826
|
+
target: cursorNode,
|
|
2827
|
+
action: new ReplaceSelectedTextAction(text, currentRange),
|
|
2828
|
+
});
|
|
2759
2829
|
}
|
|
2760
|
-
|
|
2761
|
-
|
|
2830
|
+
caretNode = cursorNode;
|
|
2831
|
+
// Content applies later via the composition, so use the post-apply offset directly (no pre-apply clamp).
|
|
2832
|
+
caretOffset = nextOffset;
|
|
2762
2833
|
}
|
|
2763
2834
|
else {
|
|
2764
|
-
|
|
2835
|
+
steps.push({
|
|
2836
|
+
target: selectedNodes[0].parent,
|
|
2837
|
+
action: new InsertTextToDecoratorNodeAction(selectedNodes[0], text, startOffset),
|
|
2838
|
+
});
|
|
2765
2839
|
}
|
|
2766
2840
|
}
|
|
2767
2841
|
}
|
|
2768
2842
|
else {
|
|
2769
2843
|
// The selected nodes is multiple nodes
|
|
2770
2844
|
const cursorNode = this.removeSelectionRange(true);
|
|
2845
|
+
updateFlag = true;
|
|
2771
2846
|
if (cursorNode instanceof RTETextNode) {
|
|
2772
|
-
|
|
2773
|
-
|
|
2847
|
+
steps.push({ target: cursorNode, action: new ReplaceSelectedTextAction(text, currentRange) });
|
|
2848
|
+
caretNode = cursorNode;
|
|
2849
|
+
caretOffset = startOffset + text.length;
|
|
2774
2850
|
}
|
|
2775
2851
|
}
|
|
2852
|
+
if (caretNode) {
|
|
2853
|
+
steps.push({
|
|
2854
|
+
target: this.currentState,
|
|
2855
|
+
action: new UpdateCursorPositionAction(caretNode, caretOffset),
|
|
2856
|
+
});
|
|
2857
|
+
}
|
|
2858
|
+
return updateFlag || steps.length > 0 ? steps : undefined;
|
|
2776
2859
|
}
|
|
2777
2860
|
/**
|
|
2778
2861
|
* Insert the text in root element when root container is empty, should create text block and text node
|
|
2779
2862
|
*
|
|
2780
2863
|
* @param {string} text The insert text
|
|
2781
|
-
* @
|
|
2864
|
+
* @param {CompositionStep[]} steps The composition steps collector to append the update action to
|
|
2865
|
+
* @returns {Nullable<RTETextNode>} The new create text node
|
|
2782
2866
|
*/
|
|
2783
|
-
insertTextToRoot(text) {
|
|
2867
|
+
insertTextToRoot(text, steps) {
|
|
2784
2868
|
if (this.currentState &&
|
|
2785
2869
|
this.currentState.children[0] &&
|
|
2786
2870
|
this.currentState.children[0] instanceof RTETextBlock) {
|
|
2787
2871
|
const firstNode = this.currentState.children[0].children[0];
|
|
2788
|
-
|
|
2872
|
+
steps.push({ target: firstNode, action: new UpdateTextAction(text) });
|
|
2789
2873
|
return firstNode;
|
|
2790
2874
|
}
|
|
2791
2875
|
}
|
|
@@ -2794,20 +2878,24 @@ class InsertTextHandler extends BaseHandler {
|
|
|
2794
2878
|
*
|
|
2795
2879
|
* @param {RTETextNode} lineBreakNode The current line break node, the text value is \n
|
|
2796
2880
|
* @param {string} text The text need to insert
|
|
2881
|
+
* @param {CompositionStep[]} steps The composition steps collector to append the resulting action to
|
|
2797
2882
|
* @returns {Nullable<RTETextNode>} The new text node or the current line break node
|
|
2798
2883
|
*/
|
|
2799
|
-
insertTextToLineBreakNode(lineBreakNode, text) {
|
|
2884
|
+
insertTextToLineBreakNode(lineBreakNode, text, steps) {
|
|
2800
2885
|
const { startOffset, endOffset } = this.selectionController.getCurrentRange();
|
|
2801
2886
|
const textBlock = lineBreakNode.parent;
|
|
2802
2887
|
if (textBlock instanceof RTETextBlock) {
|
|
2803
2888
|
const index = textBlock.children.indexOf(lineBreakNode);
|
|
2804
2889
|
if (startOffset === 0 && startOffset === endOffset && textBlock.children[index + 1]) {
|
|
2805
2890
|
const newTextNode = lineBreakNode.cloneWithText(text);
|
|
2806
|
-
|
|
2891
|
+
steps.push({
|
|
2892
|
+
target: textBlock,
|
|
2893
|
+
action: new InsertChildrenBeforeAction(lineBreakNode, newTextNode),
|
|
2894
|
+
});
|
|
2807
2895
|
return newTextNode;
|
|
2808
2896
|
}
|
|
2809
2897
|
else {
|
|
2810
|
-
|
|
2898
|
+
steps.push({ target: lineBreakNode, action: new UpdateTextAction(text) });
|
|
2811
2899
|
return lineBreakNode;
|
|
2812
2900
|
}
|
|
2813
2901
|
}
|
|
@@ -2818,20 +2906,19 @@ class InsertTextHandler extends BaseHandler {
|
|
|
2818
2906
|
class InsertParagraphHandler extends BaseHandler {
|
|
2819
2907
|
/**
|
|
2820
2908
|
* Create new paragraph node and add node to state value
|
|
2909
|
+
*
|
|
2910
|
+
* @returns {CompositionStep[] | void} The content + caret steps applied atomically as one flushable composition.
|
|
2821
2911
|
*/
|
|
2822
2912
|
handleEvent() {
|
|
2823
2913
|
const selectedBlocks = this.selectionController.getSelectedBlocks();
|
|
2824
2914
|
if (selectedBlocks.length) {
|
|
2825
|
-
|
|
2826
|
-
this.breakSingleBlock();
|
|
2827
|
-
}
|
|
2828
|
-
else {
|
|
2829
|
-
this.breakMultipleBlocks();
|
|
2830
|
-
}
|
|
2915
|
+
return selectedBlocks.length < 2 ? this.breakSingleBlock() : this.breakMultipleBlocks();
|
|
2831
2916
|
}
|
|
2832
2917
|
}
|
|
2833
2918
|
/**
|
|
2834
2919
|
* Handles breaking blocks in an RTE editor based on the current selection and position.
|
|
2920
|
+
*
|
|
2921
|
+
* @returns {CompositionStep[]} The content + caret steps for the multi-block break.
|
|
2835
2922
|
*/
|
|
2836
2923
|
breakMultipleBlocks() {
|
|
2837
2924
|
const selectedBlocks = this.selectionController.getSelectedBlocks();
|
|
@@ -2869,36 +2956,71 @@ class InsertParagraphHandler extends BaseHandler {
|
|
|
2869
2956
|
*/
|
|
2870
2957
|
if (firstBlock.type !== lastBlock.type &&
|
|
2871
2958
|
range.startContainer.nodeType === range.endContainer.nodeType) {
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2959
|
+
const mergeStep = {
|
|
2960
|
+
target: firstBlock,
|
|
2961
|
+
action: new MergeTwoBlocksNodesAction(lastBlock),
|
|
2962
|
+
};
|
|
2963
|
+
// Split offset is read at apply time, after the merge step has run.
|
|
2964
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
2965
|
+
const splitStep = () => ({
|
|
2966
|
+
target: firstBlock,
|
|
2967
|
+
action: new SplitBlockWithNodeAction(cursorNode, cursorNode['text'].length),
|
|
2968
|
+
});
|
|
2969
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
2970
|
+
const caretStep = (context) => {
|
|
2971
|
+
const splitAction = context.getAction(ModifyContentActionType.SPLIT_BLOCK_WITH_NODE);
|
|
2972
|
+
if (splitAction) {
|
|
2973
|
+
return this.caretToNextElement(splitAction.newBlock);
|
|
2974
|
+
}
|
|
2975
|
+
};
|
|
2976
|
+
return [mergeStep, splitStep, caretStep];
|
|
2877
2977
|
}
|
|
2878
2978
|
}
|
|
2879
|
-
|
|
2979
|
+
return [
|
|
2980
|
+
{
|
|
2981
|
+
target: this.currentState,
|
|
2982
|
+
action: new UpdateCursorPositionAction(cursorNode, range.startOffset),
|
|
2983
|
+
},
|
|
2984
|
+
];
|
|
2880
2985
|
}
|
|
2881
2986
|
/**
|
|
2882
2987
|
* Handles breaking a single block in an RTE editor based on the current selection and position.
|
|
2988
|
+
*
|
|
2989
|
+
* @returns {CompositionStep[]} The content + caret steps for the single-block break.
|
|
2883
2990
|
*/
|
|
2884
2991
|
breakSingleBlock() {
|
|
2885
2992
|
const cursorNode = this.removeSelectionRange();
|
|
2886
2993
|
const currentBlock = cursorNode instanceof RTENode ? cursorNode.parent : cursorNode;
|
|
2887
2994
|
const { startOffset } = this.selectionController.getCurrentRange();
|
|
2995
|
+
let result = [];
|
|
2888
2996
|
if (currentBlock) {
|
|
2889
|
-
const
|
|
2890
|
-
|
|
2891
|
-
|
|
2997
|
+
const breakStep = {
|
|
2998
|
+
target: currentBlock,
|
|
2999
|
+
action: new InsertNewParagraphAction(cursorNode, startOffset),
|
|
3000
|
+
};
|
|
3001
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
3002
|
+
const caretStep = (context) => {
|
|
3003
|
+
const breakAction = context.getAction(ModifyContentActionType.INSERT_NEW_PARAGRAPH);
|
|
3004
|
+
if (breakAction) {
|
|
3005
|
+
return this.caretToNextElement(breakAction.newBlock);
|
|
3006
|
+
}
|
|
3007
|
+
};
|
|
3008
|
+
result = [breakStep, caretStep];
|
|
2892
3009
|
}
|
|
3010
|
+
return result;
|
|
2893
3011
|
}
|
|
2894
3012
|
/**
|
|
2895
|
-
*
|
|
3013
|
+
* Builds the caret operation that moves onto the first child of the newly created block.
|
|
2896
3014
|
*
|
|
2897
|
-
* @param {RTEBlock} newBlock -
|
|
3015
|
+
* @param {Nullable<RTEBlock>} newBlock - The block created by the break, or null when none was created.
|
|
3016
|
+
* @returns {CompositionOperation | void} The caret operation, or nothing when there is no target block.
|
|
2898
3017
|
*/
|
|
2899
|
-
|
|
3018
|
+
caretToNextElement(newBlock) {
|
|
2900
3019
|
if (newBlock && newBlock.children) {
|
|
2901
|
-
|
|
3020
|
+
return {
|
|
3021
|
+
target: this.currentState,
|
|
3022
|
+
action: new UpdateCursorPositionAction(newBlock.children[0], 0),
|
|
3023
|
+
};
|
|
2902
3024
|
}
|
|
2903
3025
|
}
|
|
2904
3026
|
}
|
|
@@ -2934,20 +3056,16 @@ class lineBreakMultipleBlocksAction extends ModifyContentAction {
|
|
|
2934
3056
|
class InsertLineBreakHandler extends BaseHandler {
|
|
2935
3057
|
/**
|
|
2936
3058
|
* Create new line break node and add node to state value
|
|
3059
|
+
*
|
|
3060
|
+
* @returns {Nullable<CompositionStep[]>} The content + caret steps applied atomically as one flushable composition.
|
|
2937
3061
|
*/
|
|
2938
3062
|
handleEvent() {
|
|
2939
|
-
const range = this.selectionController.getCurrentRange();
|
|
2940
3063
|
const selectedBlocks = this.selectionController.getSelectedBlocks();
|
|
2941
|
-
if (this.isRootContainer(range.startContainer)) {
|
|
2942
|
-
this.breakNewBlock();
|
|
2943
|
-
}
|
|
2944
3064
|
if (selectedBlocks.length) {
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
this.breakMultipleBlocks();
|
|
2950
|
-
}
|
|
3065
|
+
return selectedBlocks.length < 2 ? this.breakSingleBlock() : this.breakMultipleBlocks();
|
|
3066
|
+
}
|
|
3067
|
+
else if (this.isRootContainer(this.selectionController.getCurrentRange().startContainer)) {
|
|
3068
|
+
return this.breakNewBlock();
|
|
2951
3069
|
}
|
|
2952
3070
|
}
|
|
2953
3071
|
/**
|
|
@@ -2956,14 +3074,19 @@ class InsertLineBreakHandler extends BaseHandler {
|
|
|
2956
3074
|
* <span></span>
|
|
2957
3075
|
* <span></span>
|
|
2958
3076
|
* </p>
|
|
3077
|
+
*
|
|
3078
|
+
* @returns {Nullable<CompositionStep[]>} The content + caret steps for the empty root break.
|
|
2959
3079
|
*/
|
|
2960
3080
|
breakNewBlock() {
|
|
2961
3081
|
if (this.currentState &&
|
|
2962
3082
|
this.currentState.children[0] &&
|
|
2963
3083
|
this.currentState.children[0] instanceof RTETextBlock) {
|
|
2964
|
-
const
|
|
2965
|
-
|
|
2966
|
-
|
|
3084
|
+
const targetBlock = this.currentState.children[0];
|
|
3085
|
+
const lineBreakStep = {
|
|
3086
|
+
target: targetBlock,
|
|
3087
|
+
action: new LineBreakSingleBlockAction(targetBlock.children[0], 0),
|
|
3088
|
+
};
|
|
3089
|
+
return [lineBreakStep, this.caretToSingleBlockNextNode()];
|
|
2967
3090
|
}
|
|
2968
3091
|
}
|
|
2969
3092
|
/**
|
|
@@ -2977,36 +3100,68 @@ class InsertLineBreakHandler extends BaseHandler {
|
|
|
2977
3100
|
* <br>
|
|
2978
3101
|
* <span>xt</span>
|
|
2979
3102
|
* </p>
|
|
3103
|
+
*
|
|
3104
|
+
* @returns {CompositionStep[]} The content + caret steps for the single-block break.
|
|
2980
3105
|
*/
|
|
2981
3106
|
breakSingleBlock() {
|
|
2982
3107
|
const range = this.selectionController.getCurrentRange();
|
|
2983
3108
|
const cursorNode = this.removeSelectionRange();
|
|
2984
3109
|
const currentBlock = cursorNode.parent;
|
|
3110
|
+
let result = [];
|
|
2985
3111
|
if (currentBlock) {
|
|
2986
|
-
const
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
3112
|
+
const contentStep = {
|
|
3113
|
+
target: currentBlock,
|
|
3114
|
+
action: new LineBreakSingleBlockAction(cursorNode, range.startOffset),
|
|
3115
|
+
};
|
|
3116
|
+
result = [contentStep, this.caretToSingleBlockNextNode()];
|
|
2991
3117
|
}
|
|
3118
|
+
return result;
|
|
2992
3119
|
}
|
|
2993
3120
|
/**
|
|
2994
3121
|
* Handles breaking blocks in an RTE editor based on the current selection and position.
|
|
3122
|
+
*
|
|
3123
|
+
* @returns {CompositionStep[]} The content + caret steps for the multi-block break.
|
|
2995
3124
|
*/
|
|
2996
3125
|
breakMultipleBlocks() {
|
|
2997
3126
|
const selectedBlocks = this.selectionController.getSelectedBlocks();
|
|
2998
3127
|
const cursorNode = this.removeSelectionRange();
|
|
2999
|
-
const
|
|
3000
|
-
|
|
3001
|
-
|
|
3128
|
+
const contentStep = {
|
|
3129
|
+
target: cursorNode.parent,
|
|
3130
|
+
action: new lineBreakMultipleBlocksAction(selectedBlocks),
|
|
3131
|
+
};
|
|
3132
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
3133
|
+
const caretStep = (context) => {
|
|
3134
|
+
const lineBreakAction = context.getAction(ModifyContentActionType.LINE_BREAK_MULTIPLE_BLOCKS);
|
|
3135
|
+
if (lineBreakAction && lineBreakAction.lineBreakNode) {
|
|
3136
|
+
return this.caretOperationToNextNode(lineBreakAction.lineBreakNode);
|
|
3137
|
+
}
|
|
3138
|
+
};
|
|
3139
|
+
return [contentStep, caretStep];
|
|
3140
|
+
}
|
|
3141
|
+
/**
|
|
3142
|
+
* Builds the caret step that reads the applied single-block line break to place the caret after it.
|
|
3143
|
+
*
|
|
3144
|
+
* @returns {CompositionStep} The dependent caret step.
|
|
3145
|
+
*/
|
|
3146
|
+
caretToSingleBlockNextNode() {
|
|
3147
|
+
return (context) => {
|
|
3148
|
+
const lineBreakAction = context.getAction(ModifyContentActionType.LINE_BREAK_SINGLE_BLOCK);
|
|
3149
|
+
if (lineBreakAction && lineBreakAction.lineBreakNode) {
|
|
3150
|
+
return this.caretOperationToNextNode(lineBreakAction.lineBreakNode);
|
|
3151
|
+
}
|
|
3152
|
+
};
|
|
3002
3153
|
}
|
|
3003
3154
|
/**
|
|
3004
|
-
*
|
|
3155
|
+
* Builds the caret operation that moves onto the node following the inserted line break.
|
|
3005
3156
|
*
|
|
3006
|
-
* @param {RTENode} lineBreakNode -
|
|
3157
|
+
* @param {RTENode} lineBreakNode - The inserted line break node.
|
|
3158
|
+
* @returns {CompositionOperation} The caret operation.
|
|
3007
3159
|
*/
|
|
3008
|
-
|
|
3009
|
-
|
|
3160
|
+
caretOperationToNextNode(lineBreakNode) {
|
|
3161
|
+
return {
|
|
3162
|
+
target: this.currentState,
|
|
3163
|
+
action: new UpdateCursorPositionAction(this.getNextRTENode(lineBreakNode), 0),
|
|
3164
|
+
};
|
|
3010
3165
|
}
|
|
3011
3166
|
/**
|
|
3012
3167
|
* Returns the next sibling node of a given block element in a rich text editor.
|
|
@@ -3043,15 +3198,76 @@ class DeleteBlockContentAction extends ModifyContentAction {
|
|
|
3043
3198
|
class AbstractDeleteContentHandler extends BaseHandler {
|
|
3044
3199
|
/**
|
|
3045
3200
|
* Delete the selected node(s) from the current state.
|
|
3201
|
+
*
|
|
3202
|
+
* @returns {CompositionStep[]} The content + caret steps applied atomically as one flushable composition.
|
|
3046
3203
|
*/
|
|
3047
3204
|
handleEvent() {
|
|
3048
3205
|
const selectedBlocks = this.selectionController.getSelectedBlocks();
|
|
3049
3206
|
if (selectedBlocks.length >= 2) {
|
|
3050
3207
|
this.deleteContentWithMultipleNodes();
|
|
3208
|
+
return [];
|
|
3051
3209
|
}
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3210
|
+
return this.deleteContentWithSingleBlock();
|
|
3211
|
+
}
|
|
3212
|
+
/**
|
|
3213
|
+
* Builds the ordered steps for a single-block deletion: the delete runs first, then a caret step
|
|
3214
|
+
* reads the delete action's post-apply `previousNode`/`nextNode` to decide where the caret lands.
|
|
3215
|
+
*
|
|
3216
|
+
* @param {RTENode} resolvedNode - The node the deletion is anchored on.
|
|
3217
|
+
* @param {number} resolvedOffset - The caret offset within `resolvedNode` at deletion time.
|
|
3218
|
+
* @param {Nullable<RTENode>} caretAnchor - A node the caret must stay on regardless of the delete result.
|
|
3219
|
+
* @returns {CompositionStep[]} The delete step followed by the dependent caret step.
|
|
3220
|
+
*/
|
|
3221
|
+
buildDeleteSteps(resolvedNode, resolvedOffset, caretAnchor) {
|
|
3222
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
3223
|
+
const deleteStep = () => ({
|
|
3224
|
+
target: resolvedNode.parent,
|
|
3225
|
+
action: new DeleteBlockContentAction(resolvedNode, resolvedOffset),
|
|
3226
|
+
});
|
|
3227
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
3228
|
+
const caretStep = (context) => {
|
|
3229
|
+
if (caretAnchor) {
|
|
3230
|
+
// A non-editable anchor (e.g. a token) expresses its caret position at the parent-block
|
|
3231
|
+
// level, so use its index within the parent to land right before it instead of jumping
|
|
3232
|
+
// to the block start.
|
|
3233
|
+
const caretOffset = caretAnchor.isContentEditable()
|
|
3234
|
+
? 0
|
|
3235
|
+
: caretAnchor.parent.children.indexOf(caretAnchor);
|
|
3236
|
+
return {
|
|
3237
|
+
target: this.currentState,
|
|
3238
|
+
action: new UpdateCursorPositionAction(caretAnchor, caretOffset),
|
|
3239
|
+
};
|
|
3240
|
+
}
|
|
3241
|
+
const deleteAction = context.getAction(ModifyContentActionType.DELETE_BLOCK_CONTENT);
|
|
3242
|
+
if (deleteAction && deleteAction.previousNode) {
|
|
3243
|
+
const nextOffset = deleteAction.previousNode === resolvedNode
|
|
3244
|
+
? Math.max(0, resolvedOffset - 1)
|
|
3245
|
+
: deleteAction.previousNode.getRangeEndOffset();
|
|
3246
|
+
return {
|
|
3247
|
+
target: this.currentState,
|
|
3248
|
+
action: new UpdateCursorPositionAction(deleteAction.previousNode, nextOffset),
|
|
3249
|
+
};
|
|
3250
|
+
}
|
|
3251
|
+
if (deleteAction && deleteAction.nextNode) {
|
|
3252
|
+
return {
|
|
3253
|
+
target: this.currentState,
|
|
3254
|
+
action: new UpdateCursorPositionAction(deleteAction.nextNode, 0),
|
|
3255
|
+
};
|
|
3256
|
+
}
|
|
3257
|
+
if (this.currentState.children.length === 0) {
|
|
3258
|
+
// Add an empty paragraph if the delete removed all content to keep a valid caret position.
|
|
3259
|
+
const paragraph = this.createEmptyParagraph();
|
|
3260
|
+
return [
|
|
3261
|
+
{ target: this.currentState, action: new AppendChildrenAction([paragraph]) },
|
|
3262
|
+
{
|
|
3263
|
+
target: this.currentState,
|
|
3264
|
+
action: new UpdateCursorPositionAction(paragraph.children[0], 1),
|
|
3265
|
+
},
|
|
3266
|
+
];
|
|
3267
|
+
}
|
|
3268
|
+
return undefined;
|
|
3269
|
+
};
|
|
3270
|
+
return [deleteStep, caretStep];
|
|
3055
3271
|
}
|
|
3056
3272
|
/**
|
|
3057
3273
|
* Computes the caret position one step to the right, used to translate a forward delete into a backspace.
|
|
@@ -3180,27 +3396,21 @@ class AbstractDeleteContentHandler extends BaseHandler {
|
|
|
3180
3396
|
block.parent.apply(new RemoveChildrenAction(block));
|
|
3181
3397
|
}
|
|
3182
3398
|
}
|
|
3183
|
-
/**
|
|
3184
|
-
* Creates a new paragraph element with a text node and appends it to the current state.
|
|
3185
|
-
*/
|
|
3186
|
-
insertDefaultParagraph() {
|
|
3187
|
-
const paragraph = this.createEmptyParagraph();
|
|
3188
|
-
this.currentState.apply(new AppendChildrenAction([paragraph]));
|
|
3189
|
-
this.selectionController.enqueueSelectionRangeFutureState(paragraph.children[0], 1);
|
|
3190
|
-
}
|
|
3191
3399
|
}
|
|
3192
3400
|
|
|
3193
3401
|
/** Handles a delete (rightward) deletion of content within a VegaRTE editor. User press delete will trigger this method */
|
|
3194
3402
|
class ForwardDeleteContentHandler extends AbstractDeleteContentHandler {
|
|
3195
3403
|
/**
|
|
3196
3404
|
* Handles a delete (rightward) deletion of content within a single block in an RTE editor.
|
|
3405
|
+
*
|
|
3406
|
+
* @returns {Nullable<CompositionStep[]>} The delete + caret steps, empty when the deletion is delegated or a no-op.
|
|
3197
3407
|
*/
|
|
3198
3408
|
deleteContentWithSingleBlock() {
|
|
3199
3409
|
const range = this.selectionController.getCurrentRange();
|
|
3200
3410
|
const { startOffset, endOffset, startContainer, endContainer } = range;
|
|
3201
3411
|
if (startOffset !== endOffset || startContainer !== endContainer) {
|
|
3202
3412
|
this.deleteContentWithMultipleNodes();
|
|
3203
|
-
return;
|
|
3413
|
+
return [];
|
|
3204
3414
|
}
|
|
3205
3415
|
const targetNode = this.selectionController.getSelectedNodes()[0];
|
|
3206
3416
|
// The node that should hold the caret after a forward delete removes a non-editable
|
|
@@ -3224,7 +3434,8 @@ class ForwardDeleteContentHandler extends AbstractDeleteContentHandler {
|
|
|
3224
3434
|
const forwardPosition = this.getForwardDeletePosition(targetNode, startOffset);
|
|
3225
3435
|
// The caret is at the very end of the content, there is nothing to delete forward.
|
|
3226
3436
|
if (!forwardPosition) {
|
|
3227
|
-
return
|
|
3437
|
+
// Nothing changes, so we return undefined to indicate no composition steps are needed.
|
|
3438
|
+
return undefined;
|
|
3228
3439
|
}
|
|
3229
3440
|
// Mirror backspace at heterogeneous block boundaries: a forward delete that crosses
|
|
3230
3441
|
// into a following block of a different type (e.g. paragraph → list-item, or into an
|
|
@@ -3235,8 +3446,11 @@ class ForwardDeleteContentHandler extends AbstractDeleteContentHandler {
|
|
|
3235
3446
|
if (targetNode &&
|
|
3236
3447
|
forwardPosition.node.parent !== targetNode.parent &&
|
|
3237
3448
|
forwardPosition.node.parent.type !== targetNode.parent.type) {
|
|
3238
|
-
|
|
3239
|
-
|
|
3449
|
+
const caretOperation = {
|
|
3450
|
+
target: this.currentState,
|
|
3451
|
+
action: new UpdateCursorPositionAction(forwardPosition.node, 0),
|
|
3452
|
+
};
|
|
3453
|
+
return [caretOperation];
|
|
3240
3454
|
}
|
|
3241
3455
|
// When the caret sits at the start of a non-editable leading node (e.g. a function
|
|
3242
3456
|
// keyword or a token), a forward delete removes that node. Visually the caret stays
|
|
@@ -3251,34 +3465,9 @@ class ForwardDeleteContentHandler extends AbstractDeleteContentHandler {
|
|
|
3251
3465
|
}
|
|
3252
3466
|
/* istanbul ignore next */
|
|
3253
3467
|
if (!resolvedNode) {
|
|
3254
|
-
return;
|
|
3255
|
-
}
|
|
3256
|
-
const deleteAction = new DeleteBlockContentAction(resolvedNode, resolvedOffset);
|
|
3257
|
-
resolvedNode.parent.apply(deleteAction);
|
|
3258
|
-
if (forwardCaretAnchor) {
|
|
3259
|
-
// A non-editable anchor (e.g. a token) expresses its caret position at the
|
|
3260
|
-
// parent-block level: its range container is the parent element, so an offset of
|
|
3261
|
-
// 0 would put the caret at the very start of the block (jumping to the far left)
|
|
3262
|
-
// instead of just before the anchor. Use the anchor's index within its parent so
|
|
3263
|
-
// the caret lands right before it, on the spot the deleted node used to occupy.
|
|
3264
|
-
const forwardCaretOffset = forwardCaretAnchor.isContentEditable()
|
|
3265
|
-
? 0
|
|
3266
|
-
: forwardCaretAnchor.parent.children.indexOf(forwardCaretAnchor);
|
|
3267
|
-
this.selectionController.enqueueSelectionRangeFutureState(forwardCaretAnchor, forwardCaretOffset);
|
|
3268
|
-
}
|
|
3269
|
-
else if (deleteAction.previousNode) {
|
|
3270
|
-
const nextOffset = deleteAction.previousNode === resolvedNode
|
|
3271
|
-
? Math.max(0, resolvedOffset - 1)
|
|
3272
|
-
: deleteAction.previousNode.getRangeEndOffset();
|
|
3273
|
-
this.selectionController.enqueueSelectionRangeFutureState(deleteAction.previousNode, nextOffset);
|
|
3274
|
-
}
|
|
3275
|
-
else if (deleteAction.nextNode) {
|
|
3276
|
-
this.selectionController.enqueueSelectionRangeFutureState(deleteAction.nextNode, 0);
|
|
3277
|
-
}
|
|
3278
|
-
else if (this.currentState.children.length === 0) {
|
|
3279
|
-
// Add a empty paragraph if delete all content to make sure the caret position
|
|
3280
|
-
this.insertDefaultParagraph();
|
|
3468
|
+
return [];
|
|
3281
3469
|
}
|
|
3470
|
+
return this.buildDeleteSteps(resolvedNode, resolvedOffset, forwardCaretAnchor);
|
|
3282
3471
|
}
|
|
3283
3472
|
}
|
|
3284
3473
|
|
|
@@ -3286,33 +3475,21 @@ class ForwardDeleteContentHandler extends AbstractDeleteContentHandler {
|
|
|
3286
3475
|
class BackwardDeleteContentHandler extends AbstractDeleteContentHandler {
|
|
3287
3476
|
/**
|
|
3288
3477
|
* Handles a backspace (leftward) deletion of content within a single block in an RTE editor.
|
|
3478
|
+
*
|
|
3479
|
+
* @returns {Nullable<CompositionStep[]>} The delete + caret steps, empty when the deletion is delegated or a no-op.
|
|
3289
3480
|
*/
|
|
3290
3481
|
deleteContentWithSingleBlock() {
|
|
3291
3482
|
const range = this.selectionController.getCurrentRange();
|
|
3292
3483
|
const { startOffset, endOffset, startContainer, endContainer } = range;
|
|
3293
3484
|
if (startOffset !== endOffset || startContainer !== endContainer) {
|
|
3294
3485
|
this.deleteContentWithMultipleNodes();
|
|
3295
|
-
return;
|
|
3486
|
+
return [];
|
|
3296
3487
|
}
|
|
3297
3488
|
const targetNode = this.selectionController.getSelectedNodes()[0];
|
|
3298
3489
|
if (!targetNode) {
|
|
3299
3490
|
return;
|
|
3300
3491
|
}
|
|
3301
|
-
|
|
3302
|
-
targetNode.parent.apply(deleteAction);
|
|
3303
|
-
if (deleteAction.previousNode) {
|
|
3304
|
-
const nextOffset = deleteAction.previousNode === targetNode
|
|
3305
|
-
? Math.max(0, startOffset - 1)
|
|
3306
|
-
: deleteAction.previousNode.getRangeEndOffset();
|
|
3307
|
-
this.selectionController.enqueueSelectionRangeFutureState(deleteAction.previousNode, nextOffset);
|
|
3308
|
-
}
|
|
3309
|
-
else if (deleteAction.nextNode) {
|
|
3310
|
-
this.selectionController.enqueueSelectionRangeFutureState(deleteAction.nextNode, 0);
|
|
3311
|
-
}
|
|
3312
|
-
else if (this.currentState.children.length === 0) {
|
|
3313
|
-
// Add a empty paragraph if delete all content to make sure the caret position
|
|
3314
|
-
this.insertDefaultParagraph();
|
|
3315
|
-
}
|
|
3492
|
+
return this.buildDeleteSteps(targetNode, startOffset, null);
|
|
3316
3493
|
}
|
|
3317
3494
|
}
|
|
3318
3495
|
|
|
@@ -3342,53 +3519,57 @@ class InsertPasteHandler extends BaseHandler {
|
|
|
3342
3519
|
* Update the state value when user paste html elements.
|
|
3343
3520
|
*
|
|
3344
3521
|
* @param {InputEvent} event - Paste event.
|
|
3522
|
+
* @returns {CompositionStep[]} The content + caret steps applied atomically as one flushable composition.
|
|
3345
3523
|
*/
|
|
3346
3524
|
handleEvent(event) {
|
|
3347
3525
|
const currentRange = this.selectionController.getCurrentRange();
|
|
3348
3526
|
const payload = this.getPastePayload(event);
|
|
3349
|
-
|
|
3350
|
-
|
|
3527
|
+
const inlineSteps = this.insertPlainTextInline(payload, currentRange);
|
|
3528
|
+
if (inlineSteps) {
|
|
3529
|
+
return inlineSteps;
|
|
3351
3530
|
}
|
|
3352
|
-
const blocks = this.parsePastedElements(event);
|
|
3531
|
+
const blocks = this.parsePastedElements(event, currentRange);
|
|
3353
3532
|
const startContainer = (currentRange === null || currentRange === void 0 ? void 0 : currentRange.startContainer) || undefined;
|
|
3354
3533
|
if (!startContainer) {
|
|
3355
3534
|
// When the selection/range is unavailable (e.g. the caret was lost while
|
|
3356
3535
|
// the paste-mode chooser had focus), still append the pasted content to
|
|
3357
3536
|
// the root so the paste is never silently dropped.
|
|
3358
|
-
this.insertBlocksToRoot(blocks);
|
|
3537
|
+
return this.insertBlocksToRoot(blocks);
|
|
3359
3538
|
}
|
|
3360
|
-
|
|
3361
|
-
this.insertBlocksToRoot(blocks);
|
|
3539
|
+
if (this.isRootContainer(startContainer)) {
|
|
3362
3540
|
// TODO: Need to check below logic, it seems not correct https://gethired.atlassian.net/browse/VD-7779
|
|
3541
|
+
return this.insertBlocksToRoot(blocks);
|
|
3363
3542
|
}
|
|
3364
|
-
|
|
3365
|
-
this.insertBlocksBeforeEmptyBlock(blocks, currentRange);
|
|
3366
|
-
}
|
|
3367
|
-
else {
|
|
3368
|
-
this.insertBlocksToContent(blocks, currentRange);
|
|
3543
|
+
if (this.isEmptyParagraph(startContainer)) {
|
|
3544
|
+
return this.insertBlocksBeforeEmptyBlock(blocks, currentRange);
|
|
3369
3545
|
}
|
|
3546
|
+
return this.insertBlocksToContent(blocks, currentRange);
|
|
3370
3547
|
}
|
|
3371
3548
|
/**
|
|
3372
3549
|
* Inserts plain-text paste content into the current text node at caret position.
|
|
3373
3550
|
*
|
|
3374
3551
|
* @param {RTEPastePayload} payload - Clipboard payload.
|
|
3375
3552
|
* @param {RTERange} currentRange - Current selection range.
|
|
3376
|
-
* @returns {
|
|
3553
|
+
* @returns {CompositionStep[] | undefined} The content + caret steps when inline insertion applies, otherwise undefined.
|
|
3377
3554
|
*/
|
|
3378
3555
|
insertPlainTextInline(payload, currentRange) {
|
|
3379
3556
|
var _a, _b;
|
|
3380
3557
|
const selectedNodes = ((_b = (_a = this.selectionController).getSelectedNodes) === null || _b === void 0 ? void 0 : _b.call(_a)) || [];
|
|
3381
3558
|
if (!this.shouldPasteAsInlinePlainText(payload, currentRange, selectedNodes)) {
|
|
3382
|
-
return
|
|
3559
|
+
return undefined;
|
|
3383
3560
|
}
|
|
3384
3561
|
const text = payload.text.replace(/\r\n?/g, '\n');
|
|
3385
3562
|
const cursorNode = selectedNodes.find((node) => node instanceof RTETextNode) || currentRange.startNode;
|
|
3386
3563
|
if (!(cursorNode instanceof RTETextNode)) {
|
|
3387
|
-
return
|
|
3564
|
+
return undefined;
|
|
3388
3565
|
}
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3566
|
+
return [
|
|
3567
|
+
{ target: cursorNode, action: new ReplaceSelectedTextAction(text, currentRange) },
|
|
3568
|
+
{
|
|
3569
|
+
target: this.currentState,
|
|
3570
|
+
action: new UpdateCursorPositionAction(cursorNode, currentRange.startOffset + text.length),
|
|
3571
|
+
},
|
|
3572
|
+
];
|
|
3392
3573
|
}
|
|
3393
3574
|
/**
|
|
3394
3575
|
* Determines whether the payload should be inserted as inline plain text.
|
|
@@ -3453,68 +3634,116 @@ class InsertPasteHandler extends BaseHandler {
|
|
|
3453
3634
|
* Insert the blocks to root
|
|
3454
3635
|
*
|
|
3455
3636
|
* @param { RTEContentBlock[]} blocks - blocks
|
|
3637
|
+
* @returns {CompositionStep[]} The append step for the root.
|
|
3456
3638
|
*/
|
|
3457
3639
|
insertBlocksToRoot(blocks) {
|
|
3458
|
-
this.currentState
|
|
3640
|
+
return [{ target: this.currentState, action: new AppendChildrenAction(blocks) }];
|
|
3459
3641
|
}
|
|
3460
3642
|
/**
|
|
3461
3643
|
* Insert the blocks into the current content block at the specified range.
|
|
3462
3644
|
*
|
|
3463
3645
|
* @param { RTEContentBlock[]} blocks - blocks
|
|
3464
3646
|
* @param { RTERange } rteRange - rteRange
|
|
3647
|
+
* @returns {CompositionStep[]} The content + caret steps for the content branch.
|
|
3465
3648
|
*/
|
|
3466
3649
|
insertBlocksToContent(blocks, rteRange) {
|
|
3467
|
-
var _a;
|
|
3468
3650
|
const isCollapsedRange = rteRange.startNode === rteRange.endNode && rteRange.startOffset === rteRange.endOffset;
|
|
3469
3651
|
const cursorNode = isCollapsedRange
|
|
3470
3652
|
? rteRange.startNode
|
|
3471
3653
|
: this.removeSelectionRange();
|
|
3472
3654
|
if (cursorNode && cursorNode.parent) {
|
|
3473
|
-
const
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3655
|
+
const contentStep = {
|
|
3656
|
+
target: cursorNode.parent,
|
|
3657
|
+
action: new PasteContentAction(blocks, cursorNode, rteRange.startOffset, rteRange),
|
|
3658
|
+
};
|
|
3659
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
3660
|
+
const caretStep = (context) => {
|
|
3661
|
+
var _a;
|
|
3662
|
+
const pasteAction = context.getAction(ModifyContentActionType.PASTE_CONTENT);
|
|
3663
|
+
if (pasteAction && pasteAction.futureFocusNode) {
|
|
3664
|
+
return {
|
|
3665
|
+
target: this.currentState,
|
|
3666
|
+
action: new UpdateCursorPositionAction(pasteAction.futureFocusNode, (_a = pasteAction.futureFocusNodeOffset) !== null && _a !== void 0 ? _a : 0),
|
|
3667
|
+
};
|
|
3668
|
+
}
|
|
3669
|
+
if (pasteAction && pasteAction.futureFocusBlock) {
|
|
3670
|
+
return this.caretToBlockOperation(pasteAction.futureFocusBlock, pasteAction.futureFocusAtEnd);
|
|
3671
|
+
}
|
|
3672
|
+
};
|
|
3673
|
+
return [contentStep, caretStep];
|
|
3486
3674
|
}
|
|
3675
|
+
// No resolvable cursor position: fall back to appending at the root so
|
|
3676
|
+
// the pasted content is preserved instead of being discarded.
|
|
3677
|
+
return this.insertBlocksToRoot(blocks);
|
|
3487
3678
|
}
|
|
3488
3679
|
/**
|
|
3489
3680
|
* Insert the blocks before to current block
|
|
3490
3681
|
*
|
|
3491
3682
|
* @param { RTEContentBlock[]} blocks - blocks
|
|
3492
3683
|
* @param { RTERange } rteRange - rteRange
|
|
3684
|
+
* @returns {CompositionStep[]} The content + caret steps for the empty-paragraph branch.
|
|
3493
3685
|
*/
|
|
3494
3686
|
insertBlocksBeforeEmptyBlock(blocks, rteRange) {
|
|
3495
3687
|
const cursorNode = this.removeSelectionRange();
|
|
3496
3688
|
const currentBlock = cursorNode === null || cursorNode === void 0 ? void 0 : cursorNode.parent;
|
|
3497
3689
|
if (currentBlock) {
|
|
3498
|
-
const
|
|
3499
|
-
|
|
3500
|
-
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
|
|
3507
|
-
|
|
3690
|
+
const contentStep = {
|
|
3691
|
+
target: currentBlock,
|
|
3692
|
+
action: new PasteContentAction(blocks, cursorNode, 0, rteRange),
|
|
3693
|
+
};
|
|
3694
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
3695
|
+
const caretStep = (context) => {
|
|
3696
|
+
const pasteAction = context.getAction(ModifyContentActionType.PASTE_CONTENT);
|
|
3697
|
+
if (pasteAction && pasteAction.futureFocusBlock) {
|
|
3698
|
+
return this.caretToBlockOperation(pasteAction.futureFocusBlock, pasteAction.futureFocusAtEnd);
|
|
3699
|
+
}
|
|
3700
|
+
};
|
|
3701
|
+
return [contentStep, caretStep];
|
|
3508
3702
|
}
|
|
3703
|
+
// No resolvable empty block: fall back to appending at the root so the
|
|
3704
|
+
// pasted content is preserved instead of being discarded.
|
|
3705
|
+
return this.insertBlocksToRoot(blocks);
|
|
3509
3706
|
}
|
|
3510
3707
|
/**
|
|
3511
3708
|
* Format and parse elements from user paste with simple style preservation.
|
|
3512
3709
|
*
|
|
3513
3710
|
* @param {InputEvent} event - Paste event.
|
|
3711
|
+
* @param {RTERange} [currentRange] - Optional range used to resolve the paste location.
|
|
3514
3712
|
* @returns {RTEContentBlock[]} - RTEContentBlock.
|
|
3515
3713
|
*/
|
|
3516
|
-
parsePastedElements(event) {
|
|
3714
|
+
parsePastedElements(event, currentRange) {
|
|
3715
|
+
var _a;
|
|
3517
3716
|
const payload = this.getPastePayload(event);
|
|
3717
|
+
if (payload.type === RTE_PASTE_MODE_PLAIN) {
|
|
3718
|
+
// Native tables encode their layout as tab-separated cells (one row per line) in
|
|
3719
|
+
// text/plain, so pasting that verbatim keeps the rows/columns. Non-native tables (rich text
|
|
3720
|
+
// editor tables) put a blank line between cells in text/plain, so they derive from HTML
|
|
3721
|
+
// instead: htmlToPlainText puts each cell on its own line with no gaps while keeping in-cell breaks.
|
|
3722
|
+
let plainText;
|
|
3723
|
+
let hasEncodedWhitespace = (_a = payload.hasEncodedWhitespace) !== null && _a !== void 0 ? _a : false;
|
|
3724
|
+
if (payload.html &&
|
|
3725
|
+
payload.text &&
|
|
3726
|
+
payload.text.includes('\t') &&
|
|
3727
|
+
htmlContainsTable(payload.html)) {
|
|
3728
|
+
plainText = payload.text;
|
|
3729
|
+
}
|
|
3730
|
+
else if (payload.html && htmlContainsTable(payload.html)) {
|
|
3731
|
+
plainText = this.extractPlainTextFromHtml(payload.html, true);
|
|
3732
|
+
hasEncodedWhitespace = true;
|
|
3733
|
+
}
|
|
3734
|
+
else {
|
|
3735
|
+
plainText = '';
|
|
3736
|
+
if (payload.text) {
|
|
3737
|
+
plainText = payload.text;
|
|
3738
|
+
}
|
|
3739
|
+
else if (payload.html) {
|
|
3740
|
+
plainText = this.extractPlainTextFromHtml(payload.html, true);
|
|
3741
|
+
hasEncodedWhitespace = true;
|
|
3742
|
+
}
|
|
3743
|
+
}
|
|
3744
|
+
const styleSource = (currentRange === null || currentRange === void 0 ? void 0 : currentRange.startNode) instanceof RTETextNode ? currentRange.startNode : undefined;
|
|
3745
|
+
return this.buildPlainTextParagraph(plainText, styleSource, hasEncodedWhitespace);
|
|
3746
|
+
}
|
|
3518
3747
|
let pastedHTML = payload.html || '';
|
|
3519
3748
|
if (!pastedHTML) {
|
|
3520
3749
|
pastedHTML = this.parsePlainText(payload.text || '');
|
|
@@ -3552,16 +3781,21 @@ class InsertPasteHandler extends BaseHandler {
|
|
|
3552
3781
|
return resultBlocks;
|
|
3553
3782
|
}
|
|
3554
3783
|
/**
|
|
3555
|
-
* Extracts
|
|
3784
|
+
* Extracts plain text from HTML when clipboard lacks `text/plain`.
|
|
3556
3785
|
*
|
|
3557
3786
|
* @param {string} html - Clipboard text/html payload.
|
|
3787
|
+
* @param {boolean} keepPreservedWhitespaceMarkers - Keep code-block indentation as sentinels so
|
|
3788
|
+
* the plain-mode boundary collapse in `toPlainPasteLines` does not strip it (that helper decodes
|
|
3789
|
+
* the sentinels). Must stay `false` for the rich path, which feeds `parsePlainText` directly.
|
|
3558
3790
|
* @returns {string} - Plain text extracted from HTML.
|
|
3559
3791
|
*/
|
|
3560
|
-
extractPlainTextFromHtml(html) {
|
|
3792
|
+
extractPlainTextFromHtml(html, keepPreservedWhitespaceMarkers = false) {
|
|
3561
3793
|
// Preserve inline styles before parsing to avoid style-src-attr CSP violations.
|
|
3562
3794
|
const safeHtml = StylePreservator.preserve(html).getProcessedHtml();
|
|
3563
|
-
|
|
3564
|
-
|
|
3795
|
+
return htmlToPlainText(safeHtml, {
|
|
3796
|
+
preserveBoundaryBlankLines: true,
|
|
3797
|
+
keepPreservedWhitespaceMarkers,
|
|
3798
|
+
});
|
|
3565
3799
|
}
|
|
3566
3800
|
/**
|
|
3567
3801
|
* Builds plain-text paragraph blocks when element strategy parsing returns no output.
|
|
@@ -3570,7 +3804,7 @@ class InsertPasteHandler extends BaseHandler {
|
|
|
3570
3804
|
* @returns {RTEContentBlock[]} Fallback text blocks.
|
|
3571
3805
|
*/
|
|
3572
3806
|
buildPlainTextFallbackBlocks(text) {
|
|
3573
|
-
return text
|
|
3807
|
+
return normalizePlainTextLines(text).map((line) => {
|
|
3574
3808
|
const paragraph = new RTETextBlock(generateUUID(), 'paragraph');
|
|
3575
3809
|
const textNode = new RTETextNode(`${paragraph.id}1`, line, paragraph);
|
|
3576
3810
|
paragraph.apply(new AppendChildrenAction([textNode]));
|
|
@@ -3578,21 +3812,66 @@ class InsertPasteHandler extends BaseHandler {
|
|
|
3578
3812
|
});
|
|
3579
3813
|
}
|
|
3580
3814
|
/**
|
|
3581
|
-
*
|
|
3815
|
+
* Builds plain-text paragraphs by splitting on `\n`.
|
|
3816
|
+
*
|
|
3817
|
+
* Shares `toPlainPasteLines` with `PlainPasteProcessingStrategy` so both
|
|
3818
|
+
* representations of plain-mode content (HTML and RTE nodes) agree on line
|
|
3819
|
+
* boundaries and boundary whitespace.
|
|
3820
|
+
*
|
|
3821
|
+
* @param {string} text - Plain text clipboard content.
|
|
3822
|
+
* @param {RTETextNode} [styleSource] - Optional style to preserve in all nodes.
|
|
3823
|
+
* @param {boolean} decodeEncodedWhitespace - Decode HTML-derived whitespace markers.
|
|
3824
|
+
* @returns {RTEContentBlock[]} Paragraph-per-line blocks.
|
|
3825
|
+
*/
|
|
3826
|
+
buildPlainTextParagraph(text, styleSource, decodeEncodedWhitespace = false) {
|
|
3827
|
+
const lines = toPlainPasteLines(text, decodeEncodedWhitespace);
|
|
3828
|
+
return lines.map((line, lineIndex) => {
|
|
3829
|
+
const paragraph = new RTETextBlock(generateUUID(), 'paragraph');
|
|
3830
|
+
// Always attach a text node (empty for blank lines) so empty paragraphs
|
|
3831
|
+
// render with a zero-width space and keep their visible line height,
|
|
3832
|
+
// instead of collapsing to an invisible zero-height `<p></p>`.
|
|
3833
|
+
const node = this.createPlainTextNode(paragraph, lineIndex, line, styleSource);
|
|
3834
|
+
paragraph.apply(new AppendChildrenAction([node]));
|
|
3835
|
+
return paragraph;
|
|
3836
|
+
});
|
|
3837
|
+
}
|
|
3838
|
+
/**
|
|
3839
|
+
* Creates a text node for plain paste; optionally inherits style from source node.
|
|
3840
|
+
*
|
|
3841
|
+
* @param {RTETextBlock} paragraph - Parent paragraph.
|
|
3842
|
+
* @param {number} index - Character index for node ID generation.
|
|
3843
|
+
* @param {string} text - Text content.
|
|
3844
|
+
* @param {RTETextNode} [styleSource] - Optional style to inherit.
|
|
3845
|
+
* @returns {RTETextNode} Created text node.
|
|
3846
|
+
*/
|
|
3847
|
+
createPlainTextNode(paragraph, index, text, styleSource) {
|
|
3848
|
+
const node = styleSource
|
|
3849
|
+
? styleSource.cloneWithText(text)
|
|
3850
|
+
: new RTETextNode(`${paragraph.id}-${index}`, text, paragraph);
|
|
3851
|
+
node.parent = paragraph;
|
|
3852
|
+
return node;
|
|
3853
|
+
}
|
|
3854
|
+
/**
|
|
3855
|
+
* Builds the caret operation that moves onto a block element in a rich text editor after paste.
|
|
3582
3856
|
*
|
|
3583
3857
|
* @param {RTEBlock} newBlock - Block element to move the caret to.
|
|
3584
3858
|
* @param {boolean} atEnd - When true, places the caret after the last character of the block's last node; otherwise at offset 0 of the first node.
|
|
3859
|
+
* @returns {CompositionOperation | void} The caret operation, or nothing when the block has no children.
|
|
3585
3860
|
*/
|
|
3586
|
-
|
|
3861
|
+
caretToBlockOperation(newBlock, atEnd = false) {
|
|
3587
3862
|
var _a, _b;
|
|
3588
3863
|
if (newBlock && newBlock.children) {
|
|
3589
3864
|
if (atEnd) {
|
|
3590
3865
|
const lastNode = newBlock.children[newBlock.children.length - 1];
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
|
|
3866
|
+
return {
|
|
3867
|
+
target: this.currentState,
|
|
3868
|
+
action: new UpdateCursorPositionAction(lastNode, (_b = (_a = lastNode.text) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0),
|
|
3869
|
+
};
|
|
3595
3870
|
}
|
|
3871
|
+
return {
|
|
3872
|
+
target: this.currentState,
|
|
3873
|
+
action: new UpdateCursorPositionAction(newBlock.children[0], 0),
|
|
3874
|
+
};
|
|
3596
3875
|
}
|
|
3597
3876
|
}
|
|
3598
3877
|
/**
|
|
@@ -3812,6 +4091,7 @@ class InsertPasteHandler extends BaseHandler {
|
|
|
3812
4091
|
html: event.dataTransfer.getData('text/html') || eventPayload.html || '',
|
|
3813
4092
|
text: event.dataTransfer.getData('text/plain') || eventPayload.text || '',
|
|
3814
4093
|
type: event.dataTransfer.getData(RTE_PASTE_MODE_DATA_TYPE) || '',
|
|
4094
|
+
hasEncodedWhitespace: event.dataTransfer.getData(RTE_PRESERVED_WHITESPACE_DATA_TYPE) === 'true',
|
|
3815
4095
|
};
|
|
3816
4096
|
}
|
|
3817
4097
|
}
|
|
@@ -4136,6 +4416,8 @@ class UserInputController extends VegaSlimmer {
|
|
|
4136
4416
|
};
|
|
4137
4417
|
/**
|
|
4138
4418
|
* When a user performs an input action within the editable element, this function is triggered.
|
|
4419
|
+
* Each handler owns its own `flushOptions` on `BaseHandler`, so the value update flows through
|
|
4420
|
+
* the shared flush-changes action pipeline without this method having to construct or forward it.
|
|
4139
4421
|
*
|
|
4140
4422
|
* @param {InputEvent} e the before input event object
|
|
4141
4423
|
*/
|
|
@@ -4149,41 +4431,26 @@ class UserInputController extends VegaSlimmer {
|
|
|
4149
4431
|
return;
|
|
4150
4432
|
}
|
|
4151
4433
|
this.insertCompositionTextController.removeObserver();
|
|
4152
|
-
let updateFlag = false;
|
|
4153
|
-
let updateSource = RTEUpdateSource.Default;
|
|
4154
4434
|
switch (inputType) {
|
|
4155
4435
|
case 'insertParagraph':
|
|
4156
|
-
updateFlag = true;
|
|
4157
4436
|
this.insertParagraphHandler.execute(this.value, this.selectionController, this.host, e);
|
|
4158
4437
|
break;
|
|
4159
4438
|
case 'insertText':
|
|
4160
|
-
updateFlag = true;
|
|
4161
|
-
updateSource =
|
|
4162
|
-
e[RTE_UPDATE_SOURCE_KEY] === RTEUpdateSource.Composition
|
|
4163
|
-
? RTEUpdateSource.Composition
|
|
4164
|
-
: RTEUpdateSource.Default;
|
|
4165
4439
|
this.insertTextHandler.execute(this.value, this.selectionController, this.host, e);
|
|
4166
4440
|
break;
|
|
4167
4441
|
case 'insertLineBreak':
|
|
4168
|
-
updateFlag = true;
|
|
4169
4442
|
this.insertLineBreakHandler.execute(this.value, this.selectionController, this.host, e);
|
|
4170
4443
|
break;
|
|
4171
4444
|
case 'deleteContentForward':
|
|
4172
|
-
updateFlag = true;
|
|
4173
4445
|
this.forwardDeleteContentHandler.execute(this.value, this.selectionController, this.host, e);
|
|
4174
4446
|
break;
|
|
4175
4447
|
case 'deleteContentBackward':
|
|
4176
|
-
updateFlag = true;
|
|
4177
4448
|
this.backwardDeleteContentHandler.execute(this.value, this.selectionController, this.host, e);
|
|
4178
4449
|
break;
|
|
4179
4450
|
case 'insertFromPaste':
|
|
4180
|
-
updateFlag = true;
|
|
4181
4451
|
this.insertPasteHandler.execute(this.value, this.selectionController, this.host, e);
|
|
4182
4452
|
break;
|
|
4183
4453
|
}
|
|
4184
|
-
if (updateFlag) {
|
|
4185
|
-
void this.valueController.flushChanges(this.value, true, updateSource);
|
|
4186
|
-
}
|
|
4187
4454
|
};
|
|
4188
4455
|
}
|
|
4189
4456
|
/**
|