@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
|
@@ -11,28 +11,28 @@ const changeManager = require('./change-manager-a297e4d2.js');
|
|
|
11
11
|
const domNodeSubjectObserverFactory = require('./dom-node-subject-observer-factory-c82df135.js');
|
|
12
12
|
const vegaInternalEventId = require('./vega-internal-event-id-98d499d7.js');
|
|
13
13
|
const staticSubjectTitle = require('./static-subject-title-70c73b16.js');
|
|
14
|
-
const codeBlock = require('./code-block-
|
|
15
|
-
const typeGuard = require('./type-guard-
|
|
16
|
-
const linkExtension = require('./link-extension-
|
|
14
|
+
const codeBlock = require('./code-block-72de6c4d.js');
|
|
15
|
+
const typeGuard = require('./type-guard-cce6fe1f.js');
|
|
16
|
+
const linkExtension = require('./link-extension-1b4ed437.js');
|
|
17
17
|
const internalIconManager = require('./internal-icon-manager-b9702049.js');
|
|
18
|
-
const imageAnnotationAction = require('./image-annotation-action-
|
|
18
|
+
const imageAnnotationAction = require('./image-annotation-action-1ee41bc7.js');
|
|
19
19
|
const vegaEventId = require('./vega-event-id-b5abf7c9.js');
|
|
20
20
|
const misc = require('./misc-3d30df91.js');
|
|
21
21
|
const waitForComponentDidRender = require('./wait-for-component-did-render-90edbc1a.js');
|
|
22
|
-
const imageExtension = require('./image-extension-
|
|
23
|
-
const formFieldControllerSlimmer = require('./form-field-controller-slimmer-
|
|
22
|
+
const imageExtension = require('./image-extension-6a92c524.js');
|
|
23
|
+
const formFieldControllerSlimmer = require('./form-field-controller-slimmer-124d54ea.js');
|
|
24
24
|
const eventEmitSlimmer = require('./event-emit-slimmer-6bc675f6.js');
|
|
25
25
|
const subStateNotifySlimmer = require('./sub-state-notify-slimmer-3b33e31c.js');
|
|
26
|
-
const contentState = require('./content-state-
|
|
26
|
+
const contentState = require('./content-state-ff40bdc6.js');
|
|
27
27
|
const alignLeft = require('./align-left-4a76df69.js');
|
|
28
|
-
const componentValueHistoryControllerSlimmer_abstract = require('./component-value-history-controller-slimmer.abstract-
|
|
28
|
+
const componentValueHistoryControllerSlimmer_abstract = require('./component-value-history-controller-slimmer.abstract-23d2b3d8.js');
|
|
29
29
|
const observer = require('./observer-f49483e8.js');
|
|
30
30
|
const timer = require('./timer-5f33058b.js');
|
|
31
31
|
const darkModeStateControllerSlimmer = require('./dark-mode-state-controller-slimmer-b454645a.js');
|
|
32
32
|
const ui = require('./ui-c91c37a7.js');
|
|
33
|
-
const richTextEditorRequiredRule = require('./rich-text-editor-required-rule-
|
|
33
|
+
const richTextEditorRequiredRule = require('./rich-text-editor-required-rule-1aa75d22.js');
|
|
34
34
|
const childNodesEventPreventSlimmer = require('./child-nodes-event-prevent-slimmer-574a6a1a.js');
|
|
35
|
-
const translationSlimmer = require('./translation-slimmer-
|
|
35
|
+
const translationSlimmer = require('./translation-slimmer-1771d01f.js');
|
|
36
36
|
const darkModeStyleController = require('./dark-mode-style-controller-ec04ece9.js');
|
|
37
37
|
const autoRunWhenReRenderTaskQueueSlimmer_abstract = require('./auto-run-when-re-render-task-queue-slimmer.abstract-5734634d.js');
|
|
38
38
|
const array = require('./array-249289f2.js');
|
|
@@ -48,7 +48,7 @@ require('./discriminated-3b8e72d5.js');
|
|
|
48
48
|
require('./dynamic-slimmer-f31fdfd7.js');
|
|
49
49
|
require('./breakpoints-ebde4837.js');
|
|
50
50
|
require('./ui-32120990.js');
|
|
51
|
-
require('./internal-translation-controller-
|
|
51
|
+
require('./internal-translation-controller-0d67ca4d.js');
|
|
52
52
|
require('./icon-manager-7d20b0ab.js');
|
|
53
53
|
require('./try-get-document-c0ebd39a.js');
|
|
54
54
|
require('./vega-nonce-manager-df69d3ed.js');
|
|
@@ -61,9 +61,9 @@ require('./mutation-observer-slimmer-749d5020.js');
|
|
|
61
61
|
require('./mutation-observer-filters-38cebc6d.js');
|
|
62
62
|
require('./sub-state-observer-slimmer-5b68ba3f.js');
|
|
63
63
|
require('./internal-vega-event-manager-0c256d63.js');
|
|
64
|
-
require('./range-
|
|
65
|
-
require('./keyboard-manager-slimmer-
|
|
66
|
-
require('./keyboard-manager-
|
|
64
|
+
require('./range-712fe703.js');
|
|
65
|
+
require('./keyboard-manager-slimmer-a2872981.js');
|
|
66
|
+
require('./keyboard-manager-332eec89.js');
|
|
67
67
|
require('./vega-env-manager-23b8b23c.js');
|
|
68
68
|
require('./feature-flag-controller-c19d0b58.js');
|
|
69
69
|
require('./index-3ca118c4.js');
|
|
@@ -2465,7 +2465,17 @@ class ValueController extends globalSlimmerRegistry.VegaSlimmer {
|
|
|
2465
2465
|
const flushChangesWithDebounce = timer.debounce(() => {
|
|
2466
2466
|
void this.valueController.flushChanges(this.value);
|
|
2467
2467
|
}, ValueController.VALUE_CHANGE_DEBOUNCE_TIME, this);
|
|
2468
|
-
this.flushChangeObserver = new observer.Observer(this.isAcceptableFlushChange.bind(this),
|
|
2468
|
+
this.flushChangeObserver = new observer.Observer(this.isAcceptableFlushChange.bind(this), (payload) => {
|
|
2469
|
+
// When a handler asks to bypass the debounce (direct user gestures like `beforeinput`),
|
|
2470
|
+
// invoke `flushChanges` immediately with the payload as-is. Defaults live on the emitter
|
|
2471
|
+
// side (`BaseHandler.flushOptions`) — the observer trusts the payload and does not
|
|
2472
|
+
// re-apply fallback values, so there is a single source of truth.
|
|
2473
|
+
if (payload && payload.bypassDebounce) {
|
|
2474
|
+
void this.valueController.flushChanges(this.value, payload.recordHistory, payload.updateSource);
|
|
2475
|
+
return;
|
|
2476
|
+
}
|
|
2477
|
+
flushChangesWithDebounce();
|
|
2478
|
+
});
|
|
2469
2479
|
changeManager.ChangeManager.register(domNodeSubjectObserverFactory.domNodeSubjectFactory.getSubject(this.host, vegaInternalEventId.VegaInternalRichTextEditorFlushChanges), this.flushChangeObserver);
|
|
2470
2480
|
}
|
|
2471
2481
|
/**
|
|
@@ -2626,12 +2636,44 @@ class RichTextContentController {
|
|
|
2626
2636
|
}
|
|
2627
2637
|
}
|
|
2628
2638
|
|
|
2639
|
+
/**
|
|
2640
|
+
* Applies an ordered list of leaf content actions as one flushable unit, so a `beforeinput` handler
|
|
2641
|
+
* emits a single flush through the shared action pipeline instead of marking each leaf action flushable.
|
|
2642
|
+
*/
|
|
2643
|
+
class SequentialCompositionAction extends codeBlock.ModifyContentAction {
|
|
2644
|
+
constructor(steps, flushPayload = {}) {
|
|
2645
|
+
super();
|
|
2646
|
+
this.steps = steps;
|
|
2647
|
+
this.isFlushable = true;
|
|
2648
|
+
this.type = codeBlock.ModifyContentActionType.SEQUENTIAL_COMPOSITION;
|
|
2649
|
+
this.flushPayload = flushPayload;
|
|
2650
|
+
}
|
|
2651
|
+
}
|
|
2652
|
+
|
|
2629
2653
|
const ROOT_CONTAINER_CLASS_NAME = 'rich-text-content';
|
|
2630
2654
|
/** This code snippet is defining an abstract class named `BaseHandler` with an abstract method `execute`. */
|
|
2631
2655
|
class BaseHandler {
|
|
2656
|
+
constructor() {
|
|
2657
|
+
/**
|
|
2658
|
+
* Default flush payload emitted after `handleEvent` completes. This is the single source of
|
|
2659
|
+
* truth for the defaults — the observer does not re-apply any fallback values. Subclasses may override
|
|
2660
|
+
* this field to opt out of flushing (assign `undefined`) or to change the defaults. Each instance
|
|
2661
|
+
* owns its own copy so mutations from within `handleEvent` (e.g. `InsertTextHandler` updating
|
|
2662
|
+
* `updateSource`) never leak across handler instances.
|
|
2663
|
+
*/
|
|
2664
|
+
this.flushOptions = {
|
|
2665
|
+
bypassDebounce: true,
|
|
2666
|
+
recordHistory: true,
|
|
2667
|
+
updateSource: codeBlock.RTEUpdateSource.Default,
|
|
2668
|
+
};
|
|
2669
|
+
}
|
|
2632
2670
|
/**
|
|
2633
2671
|
* The function `execute` initializes the current state and selection, and then handles an event if provided.
|
|
2634
2672
|
*
|
|
2673
|
+
* Contract: `handleEvent` MUST be synchronous. A handler that mutates the value returns the
|
|
2674
|
+
* `CompositionStep[]` it applied through `applyComposition`; the flush is then routed through the
|
|
2675
|
+
* shared action pipeline. Handlers that do not mutate the value return nothing
|
|
2676
|
+
*
|
|
2635
2677
|
* @param {VegaRTEContent} currentState - The current state of the VegaRTE content.
|
|
2636
2678
|
* @param {SelectionController} selectionController - Manages the selection of items in the user interface.
|
|
2637
2679
|
* @param {HTMLElement} richTextEditor - The current rich text editor component
|
|
@@ -2640,7 +2682,20 @@ class BaseHandler {
|
|
|
2640
2682
|
execute(currentState, selectionController, richTextEditor, event) {
|
|
2641
2683
|
this.initCurrentStateAndSelection(currentState, selectionController);
|
|
2642
2684
|
this.setCurrentRichTextEditor(richTextEditor);
|
|
2643
|
-
this.handleEvent(event);
|
|
2685
|
+
const steps = this.handleEvent(event);
|
|
2686
|
+
this.applyComposition(steps);
|
|
2687
|
+
}
|
|
2688
|
+
/**
|
|
2689
|
+
* Applies the collected leaf actions as a single flushable `SequentialCompositionAction`, so the value
|
|
2690
|
+
* update and its flush run through the same action pipeline used by every other flushable operation.
|
|
2691
|
+
* Handlers call this before enqueuing selection so caret math reads post-apply node state.
|
|
2692
|
+
*
|
|
2693
|
+
* @param {CompositionStep[]} steps - The ordered leaf actions to apply against their own targets.
|
|
2694
|
+
*/
|
|
2695
|
+
applyComposition(steps) {
|
|
2696
|
+
if (Array.isArray(steps)) {
|
|
2697
|
+
this.currentState.apply(new SequentialCompositionAction(steps, this.flushOptions));
|
|
2698
|
+
}
|
|
2644
2699
|
}
|
|
2645
2700
|
/**
|
|
2646
2701
|
* The function `isRootContainer` checks if an HTML element is a root container with a class of 'rich-text-content'.
|
|
@@ -2729,25 +2784,40 @@ class InsertTextHandler extends BaseHandler {
|
|
|
2729
2784
|
* Update the state value when user type character
|
|
2730
2785
|
*
|
|
2731
2786
|
* @param {InputEvent} event - The input event object
|
|
2787
|
+
* @returns {Nullable<CompositionStep[]>} The content actions the base handler applies as one flushable unit.
|
|
2732
2788
|
*/
|
|
2733
2789
|
handleEvent(event) {
|
|
2790
|
+
// The composition input controller stamps its synthesized `beforeinput` events with the
|
|
2791
|
+
// composition update source; pick that up so the flush notification carries the right
|
|
2792
|
+
// source without the caller having to inspect the event.
|
|
2793
|
+
if (this.flushOptions) {
|
|
2794
|
+
this.flushOptions.updateSource =
|
|
2795
|
+
event[codeBlock.RTE_UPDATE_SOURCE_KEY] === codeBlock.RTEUpdateSource.Composition
|
|
2796
|
+
? codeBlock.RTEUpdateSource.Composition
|
|
2797
|
+
: codeBlock.RTEUpdateSource.Default;
|
|
2798
|
+
}
|
|
2734
2799
|
const text = event.data;
|
|
2735
2800
|
const currentRange = this.selectionController.getCurrentRange();
|
|
2736
2801
|
const { startContainer, startOffset } = currentRange;
|
|
2737
2802
|
const selectedNodes = this.selectionController.getSelectedNodes();
|
|
2803
|
+
const steps = [];
|
|
2804
|
+
// The caret move is appended as the final composition step so content + caret apply and flush atomically.
|
|
2805
|
+
let caretNode = null;
|
|
2806
|
+
let caretOffset = 0;
|
|
2807
|
+
let updateFlag = false;
|
|
2738
2808
|
if (selectedNodes.length < 2) {
|
|
2739
2809
|
if (!selectedNodes.length && this.isRootContainer(startContainer)) {
|
|
2740
|
-
|
|
2741
|
-
|
|
2810
|
+
caretNode = this.insertTextToRoot(text, steps);
|
|
2811
|
+
caretOffset = text.length;
|
|
2742
2812
|
}
|
|
2743
2813
|
else if (selectedNodes[0] instanceof codeBlock.RTETextNode) {
|
|
2744
2814
|
if (selectedNodes[0].isContentEditable()) {
|
|
2745
2815
|
let nextOffset = startOffset + text.length;
|
|
2746
|
-
let updateFlag = false;
|
|
2747
2816
|
let cursorNode = selectedNodes[0];
|
|
2748
2817
|
if (cursorNode.text === '\n') {
|
|
2749
|
-
cursorNode = this.insertTextToLineBreakNode(cursorNode, text);
|
|
2750
|
-
|
|
2818
|
+
cursorNode = this.insertTextToLineBreakNode(cursorNode, text, steps);
|
|
2819
|
+
// UpdateTextAction replaces the \n with the input, so the caret lands at the text end.
|
|
2820
|
+
nextOffset = text.length;
|
|
2751
2821
|
}
|
|
2752
2822
|
else {
|
|
2753
2823
|
if (startContainer.nodeValue === codeBlock.ZERO_WIDTH_SPACE &&
|
|
@@ -2756,40 +2826,54 @@ class InsertTextHandler extends BaseHandler {
|
|
|
2756
2826
|
startContainer.nodeValue = '';
|
|
2757
2827
|
nextOffset = nextOffset - codeBlock.ZERO_WIDTH_SPACE.length;
|
|
2758
2828
|
}
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
}
|
|
2829
|
+
steps.push({
|
|
2830
|
+
target: cursorNode,
|
|
2831
|
+
action: new imageExtension.ReplaceSelectedTextAction(text, currentRange),
|
|
2832
|
+
});
|
|
2763
2833
|
}
|
|
2764
|
-
|
|
2765
|
-
|
|
2834
|
+
caretNode = cursorNode;
|
|
2835
|
+
// Content applies later via the composition, so use the post-apply offset directly (no pre-apply clamp).
|
|
2836
|
+
caretOffset = nextOffset;
|
|
2766
2837
|
}
|
|
2767
2838
|
else {
|
|
2768
|
-
|
|
2839
|
+
steps.push({
|
|
2840
|
+
target: selectedNodes[0].parent,
|
|
2841
|
+
action: new InsertTextToDecoratorNodeAction(selectedNodes[0], text, startOffset),
|
|
2842
|
+
});
|
|
2769
2843
|
}
|
|
2770
2844
|
}
|
|
2771
2845
|
}
|
|
2772
2846
|
else {
|
|
2773
2847
|
// The selected nodes is multiple nodes
|
|
2774
2848
|
const cursorNode = this.removeSelectionRange(true);
|
|
2849
|
+
updateFlag = true;
|
|
2775
2850
|
if (cursorNode instanceof codeBlock.RTETextNode) {
|
|
2776
|
-
|
|
2777
|
-
|
|
2851
|
+
steps.push({ target: cursorNode, action: new imageExtension.ReplaceSelectedTextAction(text, currentRange) });
|
|
2852
|
+
caretNode = cursorNode;
|
|
2853
|
+
caretOffset = startOffset + text.length;
|
|
2778
2854
|
}
|
|
2779
2855
|
}
|
|
2856
|
+
if (caretNode) {
|
|
2857
|
+
steps.push({
|
|
2858
|
+
target: this.currentState,
|
|
2859
|
+
action: new contentState.UpdateCursorPositionAction(caretNode, caretOffset),
|
|
2860
|
+
});
|
|
2861
|
+
}
|
|
2862
|
+
return updateFlag || steps.length > 0 ? steps : undefined;
|
|
2780
2863
|
}
|
|
2781
2864
|
/**
|
|
2782
2865
|
* Insert the text in root element when root container is empty, should create text block and text node
|
|
2783
2866
|
*
|
|
2784
2867
|
* @param {string} text The insert text
|
|
2785
|
-
* @
|
|
2868
|
+
* @param {CompositionStep[]} steps The composition steps collector to append the update action to
|
|
2869
|
+
* @returns {Nullable<RTETextNode>} The new create text node
|
|
2786
2870
|
*/
|
|
2787
|
-
insertTextToRoot(text) {
|
|
2871
|
+
insertTextToRoot(text, steps) {
|
|
2788
2872
|
if (this.currentState &&
|
|
2789
2873
|
this.currentState.children[0] &&
|
|
2790
2874
|
this.currentState.children[0] instanceof codeBlock.RTETextBlock) {
|
|
2791
2875
|
const firstNode = this.currentState.children[0].children[0];
|
|
2792
|
-
|
|
2876
|
+
steps.push({ target: firstNode, action: new codeBlock.UpdateTextAction(text) });
|
|
2793
2877
|
return firstNode;
|
|
2794
2878
|
}
|
|
2795
2879
|
}
|
|
@@ -2798,20 +2882,24 @@ class InsertTextHandler extends BaseHandler {
|
|
|
2798
2882
|
*
|
|
2799
2883
|
* @param {RTETextNode} lineBreakNode The current line break node, the text value is \n
|
|
2800
2884
|
* @param {string} text The text need to insert
|
|
2885
|
+
* @param {CompositionStep[]} steps The composition steps collector to append the resulting action to
|
|
2801
2886
|
* @returns {Nullable<RTETextNode>} The new text node or the current line break node
|
|
2802
2887
|
*/
|
|
2803
|
-
insertTextToLineBreakNode(lineBreakNode, text) {
|
|
2888
|
+
insertTextToLineBreakNode(lineBreakNode, text, steps) {
|
|
2804
2889
|
const { startOffset, endOffset } = this.selectionController.getCurrentRange();
|
|
2805
2890
|
const textBlock = lineBreakNode.parent;
|
|
2806
2891
|
if (textBlock instanceof codeBlock.RTETextBlock) {
|
|
2807
2892
|
const index = textBlock.children.indexOf(lineBreakNode);
|
|
2808
2893
|
if (startOffset === 0 && startOffset === endOffset && textBlock.children[index + 1]) {
|
|
2809
2894
|
const newTextNode = lineBreakNode.cloneWithText(text);
|
|
2810
|
-
|
|
2895
|
+
steps.push({
|
|
2896
|
+
target: textBlock,
|
|
2897
|
+
action: new codeBlock.InsertChildrenBeforeAction(lineBreakNode, newTextNode),
|
|
2898
|
+
});
|
|
2811
2899
|
return newTextNode;
|
|
2812
2900
|
}
|
|
2813
2901
|
else {
|
|
2814
|
-
|
|
2902
|
+
steps.push({ target: lineBreakNode, action: new codeBlock.UpdateTextAction(text) });
|
|
2815
2903
|
return lineBreakNode;
|
|
2816
2904
|
}
|
|
2817
2905
|
}
|
|
@@ -2822,20 +2910,19 @@ class InsertTextHandler extends BaseHandler {
|
|
|
2822
2910
|
class InsertParagraphHandler extends BaseHandler {
|
|
2823
2911
|
/**
|
|
2824
2912
|
* Create new paragraph node and add node to state value
|
|
2913
|
+
*
|
|
2914
|
+
* @returns {CompositionStep[] | void} The content + caret steps applied atomically as one flushable composition.
|
|
2825
2915
|
*/
|
|
2826
2916
|
handleEvent() {
|
|
2827
2917
|
const selectedBlocks = this.selectionController.getSelectedBlocks();
|
|
2828
2918
|
if (selectedBlocks.length) {
|
|
2829
|
-
|
|
2830
|
-
this.breakSingleBlock();
|
|
2831
|
-
}
|
|
2832
|
-
else {
|
|
2833
|
-
this.breakMultipleBlocks();
|
|
2834
|
-
}
|
|
2919
|
+
return selectedBlocks.length < 2 ? this.breakSingleBlock() : this.breakMultipleBlocks();
|
|
2835
2920
|
}
|
|
2836
2921
|
}
|
|
2837
2922
|
/**
|
|
2838
2923
|
* Handles breaking blocks in an RTE editor based on the current selection and position.
|
|
2924
|
+
*
|
|
2925
|
+
* @returns {CompositionStep[]} The content + caret steps for the multi-block break.
|
|
2839
2926
|
*/
|
|
2840
2927
|
breakMultipleBlocks() {
|
|
2841
2928
|
const selectedBlocks = this.selectionController.getSelectedBlocks();
|
|
@@ -2873,36 +2960,71 @@ class InsertParagraphHandler extends BaseHandler {
|
|
|
2873
2960
|
*/
|
|
2874
2961
|
if (firstBlock.type !== lastBlock.type &&
|
|
2875
2962
|
range.startContainer.nodeType === range.endContainer.nodeType) {
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2963
|
+
const mergeStep = {
|
|
2964
|
+
target: firstBlock,
|
|
2965
|
+
action: new contentState.MergeTwoBlocksNodesAction(lastBlock),
|
|
2966
|
+
};
|
|
2967
|
+
// Split offset is read at apply time, after the merge step has run.
|
|
2968
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
2969
|
+
const splitStep = () => ({
|
|
2970
|
+
target: firstBlock,
|
|
2971
|
+
action: new codeBlock.SplitBlockWithNodeAction(cursorNode, cursorNode['text'].length),
|
|
2972
|
+
});
|
|
2973
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
2974
|
+
const caretStep = (context) => {
|
|
2975
|
+
const splitAction = context.getAction(codeBlock.ModifyContentActionType.SPLIT_BLOCK_WITH_NODE);
|
|
2976
|
+
if (splitAction) {
|
|
2977
|
+
return this.caretToNextElement(splitAction.newBlock);
|
|
2978
|
+
}
|
|
2979
|
+
};
|
|
2980
|
+
return [mergeStep, splitStep, caretStep];
|
|
2881
2981
|
}
|
|
2882
2982
|
}
|
|
2883
|
-
|
|
2983
|
+
return [
|
|
2984
|
+
{
|
|
2985
|
+
target: this.currentState,
|
|
2986
|
+
action: new contentState.UpdateCursorPositionAction(cursorNode, range.startOffset),
|
|
2987
|
+
},
|
|
2988
|
+
];
|
|
2884
2989
|
}
|
|
2885
2990
|
/**
|
|
2886
2991
|
* Handles breaking a single block in an RTE editor based on the current selection and position.
|
|
2992
|
+
*
|
|
2993
|
+
* @returns {CompositionStep[]} The content + caret steps for the single-block break.
|
|
2887
2994
|
*/
|
|
2888
2995
|
breakSingleBlock() {
|
|
2889
2996
|
const cursorNode = this.removeSelectionRange();
|
|
2890
2997
|
const currentBlock = cursorNode instanceof codeBlock.RTENode ? cursorNode.parent : cursorNode;
|
|
2891
2998
|
const { startOffset } = this.selectionController.getCurrentRange();
|
|
2999
|
+
let result = [];
|
|
2892
3000
|
if (currentBlock) {
|
|
2893
|
-
const
|
|
2894
|
-
|
|
2895
|
-
|
|
3001
|
+
const breakStep = {
|
|
3002
|
+
target: currentBlock,
|
|
3003
|
+
action: new contentState.InsertNewParagraphAction(cursorNode, startOffset),
|
|
3004
|
+
};
|
|
3005
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
3006
|
+
const caretStep = (context) => {
|
|
3007
|
+
const breakAction = context.getAction(codeBlock.ModifyContentActionType.INSERT_NEW_PARAGRAPH);
|
|
3008
|
+
if (breakAction) {
|
|
3009
|
+
return this.caretToNextElement(breakAction.newBlock);
|
|
3010
|
+
}
|
|
3011
|
+
};
|
|
3012
|
+
result = [breakStep, caretStep];
|
|
2896
3013
|
}
|
|
3014
|
+
return result;
|
|
2897
3015
|
}
|
|
2898
3016
|
/**
|
|
2899
|
-
*
|
|
3017
|
+
* Builds the caret operation that moves onto the first child of the newly created block.
|
|
2900
3018
|
*
|
|
2901
|
-
* @param {RTEBlock} newBlock -
|
|
3019
|
+
* @param {Nullable<RTEBlock>} newBlock - The block created by the break, or null when none was created.
|
|
3020
|
+
* @returns {CompositionOperation | void} The caret operation, or nothing when there is no target block.
|
|
2902
3021
|
*/
|
|
2903
|
-
|
|
3022
|
+
caretToNextElement(newBlock) {
|
|
2904
3023
|
if (newBlock && newBlock.children) {
|
|
2905
|
-
|
|
3024
|
+
return {
|
|
3025
|
+
target: this.currentState,
|
|
3026
|
+
action: new contentState.UpdateCursorPositionAction(newBlock.children[0], 0),
|
|
3027
|
+
};
|
|
2906
3028
|
}
|
|
2907
3029
|
}
|
|
2908
3030
|
}
|
|
@@ -2938,20 +3060,16 @@ class lineBreakMultipleBlocksAction extends codeBlock.ModifyContentAction {
|
|
|
2938
3060
|
class InsertLineBreakHandler extends BaseHandler {
|
|
2939
3061
|
/**
|
|
2940
3062
|
* Create new line break node and add node to state value
|
|
3063
|
+
*
|
|
3064
|
+
* @returns {Nullable<CompositionStep[]>} The content + caret steps applied atomically as one flushable composition.
|
|
2941
3065
|
*/
|
|
2942
3066
|
handleEvent() {
|
|
2943
|
-
const range = this.selectionController.getCurrentRange();
|
|
2944
3067
|
const selectedBlocks = this.selectionController.getSelectedBlocks();
|
|
2945
|
-
if (this.isRootContainer(range.startContainer)) {
|
|
2946
|
-
this.breakNewBlock();
|
|
2947
|
-
}
|
|
2948
3068
|
if (selectedBlocks.length) {
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
this.breakMultipleBlocks();
|
|
2954
|
-
}
|
|
3069
|
+
return selectedBlocks.length < 2 ? this.breakSingleBlock() : this.breakMultipleBlocks();
|
|
3070
|
+
}
|
|
3071
|
+
else if (this.isRootContainer(this.selectionController.getCurrentRange().startContainer)) {
|
|
3072
|
+
return this.breakNewBlock();
|
|
2955
3073
|
}
|
|
2956
3074
|
}
|
|
2957
3075
|
/**
|
|
@@ -2960,14 +3078,19 @@ class InsertLineBreakHandler extends BaseHandler {
|
|
|
2960
3078
|
* <span></span>
|
|
2961
3079
|
* <span></span>
|
|
2962
3080
|
* </p>
|
|
3081
|
+
*
|
|
3082
|
+
* @returns {Nullable<CompositionStep[]>} The content + caret steps for the empty root break.
|
|
2963
3083
|
*/
|
|
2964
3084
|
breakNewBlock() {
|
|
2965
3085
|
if (this.currentState &&
|
|
2966
3086
|
this.currentState.children[0] &&
|
|
2967
3087
|
this.currentState.children[0] instanceof codeBlock.RTETextBlock) {
|
|
2968
|
-
const
|
|
2969
|
-
|
|
2970
|
-
|
|
3088
|
+
const targetBlock = this.currentState.children[0];
|
|
3089
|
+
const lineBreakStep = {
|
|
3090
|
+
target: targetBlock,
|
|
3091
|
+
action: new LineBreakSingleBlockAction(targetBlock.children[0], 0),
|
|
3092
|
+
};
|
|
3093
|
+
return [lineBreakStep, this.caretToSingleBlockNextNode()];
|
|
2971
3094
|
}
|
|
2972
3095
|
}
|
|
2973
3096
|
/**
|
|
@@ -2981,36 +3104,68 @@ class InsertLineBreakHandler extends BaseHandler {
|
|
|
2981
3104
|
* <br>
|
|
2982
3105
|
* <span>xt</span>
|
|
2983
3106
|
* </p>
|
|
3107
|
+
*
|
|
3108
|
+
* @returns {CompositionStep[]} The content + caret steps for the single-block break.
|
|
2984
3109
|
*/
|
|
2985
3110
|
breakSingleBlock() {
|
|
2986
3111
|
const range = this.selectionController.getCurrentRange();
|
|
2987
3112
|
const cursorNode = this.removeSelectionRange();
|
|
2988
3113
|
const currentBlock = cursorNode.parent;
|
|
3114
|
+
let result = [];
|
|
2989
3115
|
if (currentBlock) {
|
|
2990
|
-
const
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
3116
|
+
const contentStep = {
|
|
3117
|
+
target: currentBlock,
|
|
3118
|
+
action: new LineBreakSingleBlockAction(cursorNode, range.startOffset),
|
|
3119
|
+
};
|
|
3120
|
+
result = [contentStep, this.caretToSingleBlockNextNode()];
|
|
2995
3121
|
}
|
|
3122
|
+
return result;
|
|
2996
3123
|
}
|
|
2997
3124
|
/**
|
|
2998
3125
|
* Handles breaking blocks in an RTE editor based on the current selection and position.
|
|
3126
|
+
*
|
|
3127
|
+
* @returns {CompositionStep[]} The content + caret steps for the multi-block break.
|
|
2999
3128
|
*/
|
|
3000
3129
|
breakMultipleBlocks() {
|
|
3001
3130
|
const selectedBlocks = this.selectionController.getSelectedBlocks();
|
|
3002
3131
|
const cursorNode = this.removeSelectionRange();
|
|
3003
|
-
const
|
|
3004
|
-
|
|
3005
|
-
|
|
3132
|
+
const contentStep = {
|
|
3133
|
+
target: cursorNode.parent,
|
|
3134
|
+
action: new lineBreakMultipleBlocksAction(selectedBlocks),
|
|
3135
|
+
};
|
|
3136
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
3137
|
+
const caretStep = (context) => {
|
|
3138
|
+
const lineBreakAction = context.getAction(codeBlock.ModifyContentActionType.LINE_BREAK_MULTIPLE_BLOCKS);
|
|
3139
|
+
if (lineBreakAction && lineBreakAction.lineBreakNode) {
|
|
3140
|
+
return this.caretOperationToNextNode(lineBreakAction.lineBreakNode);
|
|
3141
|
+
}
|
|
3142
|
+
};
|
|
3143
|
+
return [contentStep, caretStep];
|
|
3144
|
+
}
|
|
3145
|
+
/**
|
|
3146
|
+
* Builds the caret step that reads the applied single-block line break to place the caret after it.
|
|
3147
|
+
*
|
|
3148
|
+
* @returns {CompositionStep} The dependent caret step.
|
|
3149
|
+
*/
|
|
3150
|
+
caretToSingleBlockNextNode() {
|
|
3151
|
+
return (context) => {
|
|
3152
|
+
const lineBreakAction = context.getAction(codeBlock.ModifyContentActionType.LINE_BREAK_SINGLE_BLOCK);
|
|
3153
|
+
if (lineBreakAction && lineBreakAction.lineBreakNode) {
|
|
3154
|
+
return this.caretOperationToNextNode(lineBreakAction.lineBreakNode);
|
|
3155
|
+
}
|
|
3156
|
+
};
|
|
3006
3157
|
}
|
|
3007
3158
|
/**
|
|
3008
|
-
*
|
|
3159
|
+
* Builds the caret operation that moves onto the node following the inserted line break.
|
|
3009
3160
|
*
|
|
3010
|
-
* @param {RTENode} lineBreakNode -
|
|
3161
|
+
* @param {RTENode} lineBreakNode - The inserted line break node.
|
|
3162
|
+
* @returns {CompositionOperation} The caret operation.
|
|
3011
3163
|
*/
|
|
3012
|
-
|
|
3013
|
-
|
|
3164
|
+
caretOperationToNextNode(lineBreakNode) {
|
|
3165
|
+
return {
|
|
3166
|
+
target: this.currentState,
|
|
3167
|
+
action: new contentState.UpdateCursorPositionAction(this.getNextRTENode(lineBreakNode), 0),
|
|
3168
|
+
};
|
|
3014
3169
|
}
|
|
3015
3170
|
/**
|
|
3016
3171
|
* Returns the next sibling node of a given block element in a rich text editor.
|
|
@@ -3047,15 +3202,76 @@ class DeleteBlockContentAction extends codeBlock.ModifyContentAction {
|
|
|
3047
3202
|
class AbstractDeleteContentHandler extends BaseHandler {
|
|
3048
3203
|
/**
|
|
3049
3204
|
* Delete the selected node(s) from the current state.
|
|
3205
|
+
*
|
|
3206
|
+
* @returns {CompositionStep[]} The content + caret steps applied atomically as one flushable composition.
|
|
3050
3207
|
*/
|
|
3051
3208
|
handleEvent() {
|
|
3052
3209
|
const selectedBlocks = this.selectionController.getSelectedBlocks();
|
|
3053
3210
|
if (selectedBlocks.length >= 2) {
|
|
3054
3211
|
this.deleteContentWithMultipleNodes();
|
|
3212
|
+
return [];
|
|
3055
3213
|
}
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3214
|
+
return this.deleteContentWithSingleBlock();
|
|
3215
|
+
}
|
|
3216
|
+
/**
|
|
3217
|
+
* Builds the ordered steps for a single-block deletion: the delete runs first, then a caret step
|
|
3218
|
+
* reads the delete action's post-apply `previousNode`/`nextNode` to decide where the caret lands.
|
|
3219
|
+
*
|
|
3220
|
+
* @param {RTENode} resolvedNode - The node the deletion is anchored on.
|
|
3221
|
+
* @param {number} resolvedOffset - The caret offset within `resolvedNode` at deletion time.
|
|
3222
|
+
* @param {Nullable<RTENode>} caretAnchor - A node the caret must stay on regardless of the delete result.
|
|
3223
|
+
* @returns {CompositionStep[]} The delete step followed by the dependent caret step.
|
|
3224
|
+
*/
|
|
3225
|
+
buildDeleteSteps(resolvedNode, resolvedOffset, caretAnchor) {
|
|
3226
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
3227
|
+
const deleteStep = () => ({
|
|
3228
|
+
target: resolvedNode.parent,
|
|
3229
|
+
action: new DeleteBlockContentAction(resolvedNode, resolvedOffset),
|
|
3230
|
+
});
|
|
3231
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
3232
|
+
const caretStep = (context) => {
|
|
3233
|
+
if (caretAnchor) {
|
|
3234
|
+
// A non-editable anchor (e.g. a token) expresses its caret position at the parent-block
|
|
3235
|
+
// level, so use its index within the parent to land right before it instead of jumping
|
|
3236
|
+
// to the block start.
|
|
3237
|
+
const caretOffset = caretAnchor.isContentEditable()
|
|
3238
|
+
? 0
|
|
3239
|
+
: caretAnchor.parent.children.indexOf(caretAnchor);
|
|
3240
|
+
return {
|
|
3241
|
+
target: this.currentState,
|
|
3242
|
+
action: new contentState.UpdateCursorPositionAction(caretAnchor, caretOffset),
|
|
3243
|
+
};
|
|
3244
|
+
}
|
|
3245
|
+
const deleteAction = context.getAction(codeBlock.ModifyContentActionType.DELETE_BLOCK_CONTENT);
|
|
3246
|
+
if (deleteAction && deleteAction.previousNode) {
|
|
3247
|
+
const nextOffset = deleteAction.previousNode === resolvedNode
|
|
3248
|
+
? Math.max(0, resolvedOffset - 1)
|
|
3249
|
+
: deleteAction.previousNode.getRangeEndOffset();
|
|
3250
|
+
return {
|
|
3251
|
+
target: this.currentState,
|
|
3252
|
+
action: new contentState.UpdateCursorPositionAction(deleteAction.previousNode, nextOffset),
|
|
3253
|
+
};
|
|
3254
|
+
}
|
|
3255
|
+
if (deleteAction && deleteAction.nextNode) {
|
|
3256
|
+
return {
|
|
3257
|
+
target: this.currentState,
|
|
3258
|
+
action: new contentState.UpdateCursorPositionAction(deleteAction.nextNode, 0),
|
|
3259
|
+
};
|
|
3260
|
+
}
|
|
3261
|
+
if (this.currentState.children.length === 0) {
|
|
3262
|
+
// Add an empty paragraph if the delete removed all content to keep a valid caret position.
|
|
3263
|
+
const paragraph = this.createEmptyParagraph();
|
|
3264
|
+
return [
|
|
3265
|
+
{ target: this.currentState, action: new codeBlock.AppendChildrenAction([paragraph]) },
|
|
3266
|
+
{
|
|
3267
|
+
target: this.currentState,
|
|
3268
|
+
action: new contentState.UpdateCursorPositionAction(paragraph.children[0], 1),
|
|
3269
|
+
},
|
|
3270
|
+
];
|
|
3271
|
+
}
|
|
3272
|
+
return undefined;
|
|
3273
|
+
};
|
|
3274
|
+
return [deleteStep, caretStep];
|
|
3059
3275
|
}
|
|
3060
3276
|
/**
|
|
3061
3277
|
* Computes the caret position one step to the right, used to translate a forward delete into a backspace.
|
|
@@ -3184,27 +3400,21 @@ class AbstractDeleteContentHandler extends BaseHandler {
|
|
|
3184
3400
|
block.parent.apply(new codeBlock.RemoveChildrenAction(block));
|
|
3185
3401
|
}
|
|
3186
3402
|
}
|
|
3187
|
-
/**
|
|
3188
|
-
* Creates a new paragraph element with a text node and appends it to the current state.
|
|
3189
|
-
*/
|
|
3190
|
-
insertDefaultParagraph() {
|
|
3191
|
-
const paragraph = this.createEmptyParagraph();
|
|
3192
|
-
this.currentState.apply(new codeBlock.AppendChildrenAction([paragraph]));
|
|
3193
|
-
this.selectionController.enqueueSelectionRangeFutureState(paragraph.children[0], 1);
|
|
3194
|
-
}
|
|
3195
3403
|
}
|
|
3196
3404
|
|
|
3197
3405
|
/** Handles a delete (rightward) deletion of content within a VegaRTE editor. User press delete will trigger this method */
|
|
3198
3406
|
class ForwardDeleteContentHandler extends AbstractDeleteContentHandler {
|
|
3199
3407
|
/**
|
|
3200
3408
|
* Handles a delete (rightward) deletion of content within a single block in an RTE editor.
|
|
3409
|
+
*
|
|
3410
|
+
* @returns {Nullable<CompositionStep[]>} The delete + caret steps, empty when the deletion is delegated or a no-op.
|
|
3201
3411
|
*/
|
|
3202
3412
|
deleteContentWithSingleBlock() {
|
|
3203
3413
|
const range = this.selectionController.getCurrentRange();
|
|
3204
3414
|
const { startOffset, endOffset, startContainer, endContainer } = range;
|
|
3205
3415
|
if (startOffset !== endOffset || startContainer !== endContainer) {
|
|
3206
3416
|
this.deleteContentWithMultipleNodes();
|
|
3207
|
-
return;
|
|
3417
|
+
return [];
|
|
3208
3418
|
}
|
|
3209
3419
|
const targetNode = this.selectionController.getSelectedNodes()[0];
|
|
3210
3420
|
// The node that should hold the caret after a forward delete removes a non-editable
|
|
@@ -3228,7 +3438,8 @@ class ForwardDeleteContentHandler extends AbstractDeleteContentHandler {
|
|
|
3228
3438
|
const forwardPosition = this.getForwardDeletePosition(targetNode, startOffset);
|
|
3229
3439
|
// The caret is at the very end of the content, there is nothing to delete forward.
|
|
3230
3440
|
if (!forwardPosition) {
|
|
3231
|
-
return
|
|
3441
|
+
// Nothing changes, so we return undefined to indicate no composition steps are needed.
|
|
3442
|
+
return undefined;
|
|
3232
3443
|
}
|
|
3233
3444
|
// Mirror backspace at heterogeneous block boundaries: a forward delete that crosses
|
|
3234
3445
|
// into a following block of a different type (e.g. paragraph → list-item, or into an
|
|
@@ -3239,8 +3450,11 @@ class ForwardDeleteContentHandler extends AbstractDeleteContentHandler {
|
|
|
3239
3450
|
if (targetNode &&
|
|
3240
3451
|
forwardPosition.node.parent !== targetNode.parent &&
|
|
3241
3452
|
forwardPosition.node.parent.type !== targetNode.parent.type) {
|
|
3242
|
-
|
|
3243
|
-
|
|
3453
|
+
const caretOperation = {
|
|
3454
|
+
target: this.currentState,
|
|
3455
|
+
action: new contentState.UpdateCursorPositionAction(forwardPosition.node, 0),
|
|
3456
|
+
};
|
|
3457
|
+
return [caretOperation];
|
|
3244
3458
|
}
|
|
3245
3459
|
// When the caret sits at the start of a non-editable leading node (e.g. a function
|
|
3246
3460
|
// keyword or a token), a forward delete removes that node. Visually the caret stays
|
|
@@ -3255,34 +3469,9 @@ class ForwardDeleteContentHandler extends AbstractDeleteContentHandler {
|
|
|
3255
3469
|
}
|
|
3256
3470
|
/* istanbul ignore next */
|
|
3257
3471
|
if (!resolvedNode) {
|
|
3258
|
-
return;
|
|
3259
|
-
}
|
|
3260
|
-
const deleteAction = new DeleteBlockContentAction(resolvedNode, resolvedOffset);
|
|
3261
|
-
resolvedNode.parent.apply(deleteAction);
|
|
3262
|
-
if (forwardCaretAnchor) {
|
|
3263
|
-
// A non-editable anchor (e.g. a token) expresses its caret position at the
|
|
3264
|
-
// parent-block level: its range container is the parent element, so an offset of
|
|
3265
|
-
// 0 would put the caret at the very start of the block (jumping to the far left)
|
|
3266
|
-
// instead of just before the anchor. Use the anchor's index within its parent so
|
|
3267
|
-
// the caret lands right before it, on the spot the deleted node used to occupy.
|
|
3268
|
-
const forwardCaretOffset = forwardCaretAnchor.isContentEditable()
|
|
3269
|
-
? 0
|
|
3270
|
-
: forwardCaretAnchor.parent.children.indexOf(forwardCaretAnchor);
|
|
3271
|
-
this.selectionController.enqueueSelectionRangeFutureState(forwardCaretAnchor, forwardCaretOffset);
|
|
3272
|
-
}
|
|
3273
|
-
else if (deleteAction.previousNode) {
|
|
3274
|
-
const nextOffset = deleteAction.previousNode === resolvedNode
|
|
3275
|
-
? Math.max(0, resolvedOffset - 1)
|
|
3276
|
-
: deleteAction.previousNode.getRangeEndOffset();
|
|
3277
|
-
this.selectionController.enqueueSelectionRangeFutureState(deleteAction.previousNode, nextOffset);
|
|
3278
|
-
}
|
|
3279
|
-
else if (deleteAction.nextNode) {
|
|
3280
|
-
this.selectionController.enqueueSelectionRangeFutureState(deleteAction.nextNode, 0);
|
|
3281
|
-
}
|
|
3282
|
-
else if (this.currentState.children.length === 0) {
|
|
3283
|
-
// Add a empty paragraph if delete all content to make sure the caret position
|
|
3284
|
-
this.insertDefaultParagraph();
|
|
3472
|
+
return [];
|
|
3285
3473
|
}
|
|
3474
|
+
return this.buildDeleteSteps(resolvedNode, resolvedOffset, forwardCaretAnchor);
|
|
3286
3475
|
}
|
|
3287
3476
|
}
|
|
3288
3477
|
|
|
@@ -3290,33 +3479,21 @@ class ForwardDeleteContentHandler extends AbstractDeleteContentHandler {
|
|
|
3290
3479
|
class BackwardDeleteContentHandler extends AbstractDeleteContentHandler {
|
|
3291
3480
|
/**
|
|
3292
3481
|
* Handles a backspace (leftward) deletion of content within a single block in an RTE editor.
|
|
3482
|
+
*
|
|
3483
|
+
* @returns {Nullable<CompositionStep[]>} The delete + caret steps, empty when the deletion is delegated or a no-op.
|
|
3293
3484
|
*/
|
|
3294
3485
|
deleteContentWithSingleBlock() {
|
|
3295
3486
|
const range = this.selectionController.getCurrentRange();
|
|
3296
3487
|
const { startOffset, endOffset, startContainer, endContainer } = range;
|
|
3297
3488
|
if (startOffset !== endOffset || startContainer !== endContainer) {
|
|
3298
3489
|
this.deleteContentWithMultipleNodes();
|
|
3299
|
-
return;
|
|
3490
|
+
return [];
|
|
3300
3491
|
}
|
|
3301
3492
|
const targetNode = this.selectionController.getSelectedNodes()[0];
|
|
3302
3493
|
if (!targetNode) {
|
|
3303
3494
|
return;
|
|
3304
3495
|
}
|
|
3305
|
-
|
|
3306
|
-
targetNode.parent.apply(deleteAction);
|
|
3307
|
-
if (deleteAction.previousNode) {
|
|
3308
|
-
const nextOffset = deleteAction.previousNode === targetNode
|
|
3309
|
-
? Math.max(0, startOffset - 1)
|
|
3310
|
-
: deleteAction.previousNode.getRangeEndOffset();
|
|
3311
|
-
this.selectionController.enqueueSelectionRangeFutureState(deleteAction.previousNode, nextOffset);
|
|
3312
|
-
}
|
|
3313
|
-
else if (deleteAction.nextNode) {
|
|
3314
|
-
this.selectionController.enqueueSelectionRangeFutureState(deleteAction.nextNode, 0);
|
|
3315
|
-
}
|
|
3316
|
-
else if (this.currentState.children.length === 0) {
|
|
3317
|
-
// Add a empty paragraph if delete all content to make sure the caret position
|
|
3318
|
-
this.insertDefaultParagraph();
|
|
3319
|
-
}
|
|
3496
|
+
return this.buildDeleteSteps(targetNode, startOffset, null);
|
|
3320
3497
|
}
|
|
3321
3498
|
}
|
|
3322
3499
|
|
|
@@ -3346,53 +3523,57 @@ class InsertPasteHandler extends BaseHandler {
|
|
|
3346
3523
|
* Update the state value when user paste html elements.
|
|
3347
3524
|
*
|
|
3348
3525
|
* @param {InputEvent} event - Paste event.
|
|
3526
|
+
* @returns {CompositionStep[]} The content + caret steps applied atomically as one flushable composition.
|
|
3349
3527
|
*/
|
|
3350
3528
|
handleEvent(event) {
|
|
3351
3529
|
const currentRange = this.selectionController.getCurrentRange();
|
|
3352
3530
|
const payload = this.getPastePayload(event);
|
|
3353
|
-
|
|
3354
|
-
|
|
3531
|
+
const inlineSteps = this.insertPlainTextInline(payload, currentRange);
|
|
3532
|
+
if (inlineSteps) {
|
|
3533
|
+
return inlineSteps;
|
|
3355
3534
|
}
|
|
3356
|
-
const blocks = this.parsePastedElements(event);
|
|
3535
|
+
const blocks = this.parsePastedElements(event, currentRange);
|
|
3357
3536
|
const startContainer = (currentRange === null || currentRange === void 0 ? void 0 : currentRange.startContainer) || undefined;
|
|
3358
3537
|
if (!startContainer) {
|
|
3359
3538
|
// When the selection/range is unavailable (e.g. the caret was lost while
|
|
3360
3539
|
// the paste-mode chooser had focus), still append the pasted content to
|
|
3361
3540
|
// the root so the paste is never silently dropped.
|
|
3362
|
-
this.insertBlocksToRoot(blocks);
|
|
3541
|
+
return this.insertBlocksToRoot(blocks);
|
|
3363
3542
|
}
|
|
3364
|
-
|
|
3365
|
-
this.insertBlocksToRoot(blocks);
|
|
3543
|
+
if (this.isRootContainer(startContainer)) {
|
|
3366
3544
|
// TODO: Need to check below logic, it seems not correct https://gethired.atlassian.net/browse/VD-7779
|
|
3545
|
+
return this.insertBlocksToRoot(blocks);
|
|
3367
3546
|
}
|
|
3368
|
-
|
|
3369
|
-
this.insertBlocksBeforeEmptyBlock(blocks, currentRange);
|
|
3370
|
-
}
|
|
3371
|
-
else {
|
|
3372
|
-
this.insertBlocksToContent(blocks, currentRange);
|
|
3547
|
+
if (this.isEmptyParagraph(startContainer)) {
|
|
3548
|
+
return this.insertBlocksBeforeEmptyBlock(blocks, currentRange);
|
|
3373
3549
|
}
|
|
3550
|
+
return this.insertBlocksToContent(blocks, currentRange);
|
|
3374
3551
|
}
|
|
3375
3552
|
/**
|
|
3376
3553
|
* Inserts plain-text paste content into the current text node at caret position.
|
|
3377
3554
|
*
|
|
3378
3555
|
* @param {RTEPastePayload} payload - Clipboard payload.
|
|
3379
3556
|
* @param {RTERange} currentRange - Current selection range.
|
|
3380
|
-
* @returns {
|
|
3557
|
+
* @returns {CompositionStep[] | undefined} The content + caret steps when inline insertion applies, otherwise undefined.
|
|
3381
3558
|
*/
|
|
3382
3559
|
insertPlainTextInline(payload, currentRange) {
|
|
3383
3560
|
var _a, _b;
|
|
3384
3561
|
const selectedNodes = ((_b = (_a = this.selectionController).getSelectedNodes) === null || _b === void 0 ? void 0 : _b.call(_a)) || [];
|
|
3385
3562
|
if (!this.shouldPasteAsInlinePlainText(payload, currentRange, selectedNodes)) {
|
|
3386
|
-
return
|
|
3563
|
+
return undefined;
|
|
3387
3564
|
}
|
|
3388
3565
|
const text = payload.text.replace(/\r\n?/g, '\n');
|
|
3389
3566
|
const cursorNode = selectedNodes.find((node) => node instanceof codeBlock.RTETextNode) || currentRange.startNode;
|
|
3390
3567
|
if (!(cursorNode instanceof codeBlock.RTETextNode)) {
|
|
3391
|
-
return
|
|
3568
|
+
return undefined;
|
|
3392
3569
|
}
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3570
|
+
return [
|
|
3571
|
+
{ target: cursorNode, action: new imageExtension.ReplaceSelectedTextAction(text, currentRange) },
|
|
3572
|
+
{
|
|
3573
|
+
target: this.currentState,
|
|
3574
|
+
action: new contentState.UpdateCursorPositionAction(cursorNode, currentRange.startOffset + text.length),
|
|
3575
|
+
},
|
|
3576
|
+
];
|
|
3396
3577
|
}
|
|
3397
3578
|
/**
|
|
3398
3579
|
* Determines whether the payload should be inserted as inline plain text.
|
|
@@ -3457,68 +3638,116 @@ class InsertPasteHandler extends BaseHandler {
|
|
|
3457
3638
|
* Insert the blocks to root
|
|
3458
3639
|
*
|
|
3459
3640
|
* @param { RTEContentBlock[]} blocks - blocks
|
|
3641
|
+
* @returns {CompositionStep[]} The append step for the root.
|
|
3460
3642
|
*/
|
|
3461
3643
|
insertBlocksToRoot(blocks) {
|
|
3462
|
-
this.currentState
|
|
3644
|
+
return [{ target: this.currentState, action: new codeBlock.AppendChildrenAction(blocks) }];
|
|
3463
3645
|
}
|
|
3464
3646
|
/**
|
|
3465
3647
|
* Insert the blocks into the current content block at the specified range.
|
|
3466
3648
|
*
|
|
3467
3649
|
* @param { RTEContentBlock[]} blocks - blocks
|
|
3468
3650
|
* @param { RTERange } rteRange - rteRange
|
|
3651
|
+
* @returns {CompositionStep[]} The content + caret steps for the content branch.
|
|
3469
3652
|
*/
|
|
3470
3653
|
insertBlocksToContent(blocks, rteRange) {
|
|
3471
|
-
var _a;
|
|
3472
3654
|
const isCollapsedRange = rteRange.startNode === rteRange.endNode && rteRange.startOffset === rteRange.endOffset;
|
|
3473
3655
|
const cursorNode = isCollapsedRange
|
|
3474
3656
|
? rteRange.startNode
|
|
3475
3657
|
: this.removeSelectionRange();
|
|
3476
3658
|
if (cursorNode && cursorNode.parent) {
|
|
3477
|
-
const
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
|
|
3659
|
+
const contentStep = {
|
|
3660
|
+
target: cursorNode.parent,
|
|
3661
|
+
action: new PasteContentAction(blocks, cursorNode, rteRange.startOffset, rteRange),
|
|
3662
|
+
};
|
|
3663
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
3664
|
+
const caretStep = (context) => {
|
|
3665
|
+
var _a;
|
|
3666
|
+
const pasteAction = context.getAction(codeBlock.ModifyContentActionType.PASTE_CONTENT);
|
|
3667
|
+
if (pasteAction && pasteAction.futureFocusNode) {
|
|
3668
|
+
return {
|
|
3669
|
+
target: this.currentState,
|
|
3670
|
+
action: new contentState.UpdateCursorPositionAction(pasteAction.futureFocusNode, (_a = pasteAction.futureFocusNodeOffset) !== null && _a !== void 0 ? _a : 0),
|
|
3671
|
+
};
|
|
3672
|
+
}
|
|
3673
|
+
if (pasteAction && pasteAction.futureFocusBlock) {
|
|
3674
|
+
return this.caretToBlockOperation(pasteAction.futureFocusBlock, pasteAction.futureFocusAtEnd);
|
|
3675
|
+
}
|
|
3676
|
+
};
|
|
3677
|
+
return [contentStep, caretStep];
|
|
3490
3678
|
}
|
|
3679
|
+
// No resolvable cursor position: fall back to appending at the root so
|
|
3680
|
+
// the pasted content is preserved instead of being discarded.
|
|
3681
|
+
return this.insertBlocksToRoot(blocks);
|
|
3491
3682
|
}
|
|
3492
3683
|
/**
|
|
3493
3684
|
* Insert the blocks before to current block
|
|
3494
3685
|
*
|
|
3495
3686
|
* @param { RTEContentBlock[]} blocks - blocks
|
|
3496
3687
|
* @param { RTERange } rteRange - rteRange
|
|
3688
|
+
* @returns {CompositionStep[]} The content + caret steps for the empty-paragraph branch.
|
|
3497
3689
|
*/
|
|
3498
3690
|
insertBlocksBeforeEmptyBlock(blocks, rteRange) {
|
|
3499
3691
|
const cursorNode = this.removeSelectionRange();
|
|
3500
3692
|
const currentBlock = cursorNode === null || cursorNode === void 0 ? void 0 : cursorNode.parent;
|
|
3501
3693
|
if (currentBlock) {
|
|
3502
|
-
const
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
|
|
3694
|
+
const contentStep = {
|
|
3695
|
+
target: currentBlock,
|
|
3696
|
+
action: new PasteContentAction(blocks, cursorNode, 0, rteRange),
|
|
3697
|
+
};
|
|
3698
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
3699
|
+
const caretStep = (context) => {
|
|
3700
|
+
const pasteAction = context.getAction(codeBlock.ModifyContentActionType.PASTE_CONTENT);
|
|
3701
|
+
if (pasteAction && pasteAction.futureFocusBlock) {
|
|
3702
|
+
return this.caretToBlockOperation(pasteAction.futureFocusBlock, pasteAction.futureFocusAtEnd);
|
|
3703
|
+
}
|
|
3704
|
+
};
|
|
3705
|
+
return [contentStep, caretStep];
|
|
3512
3706
|
}
|
|
3707
|
+
// No resolvable empty block: fall back to appending at the root so the
|
|
3708
|
+
// pasted content is preserved instead of being discarded.
|
|
3709
|
+
return this.insertBlocksToRoot(blocks);
|
|
3513
3710
|
}
|
|
3514
3711
|
/**
|
|
3515
3712
|
* Format and parse elements from user paste with simple style preservation.
|
|
3516
3713
|
*
|
|
3517
3714
|
* @param {InputEvent} event - Paste event.
|
|
3715
|
+
* @param {RTERange} [currentRange] - Optional range used to resolve the paste location.
|
|
3518
3716
|
* @returns {RTEContentBlock[]} - RTEContentBlock.
|
|
3519
3717
|
*/
|
|
3520
|
-
parsePastedElements(event) {
|
|
3718
|
+
parsePastedElements(event, currentRange) {
|
|
3719
|
+
var _a;
|
|
3521
3720
|
const payload = this.getPastePayload(event);
|
|
3721
|
+
if (payload.type === codeBlock.RTE_PASTE_MODE_PLAIN) {
|
|
3722
|
+
// Native tables encode their layout as tab-separated cells (one row per line) in
|
|
3723
|
+
// text/plain, so pasting that verbatim keeps the rows/columns. Non-native tables (rich text
|
|
3724
|
+
// editor tables) put a blank line between cells in text/plain, so they derive from HTML
|
|
3725
|
+
// instead: htmlToPlainText puts each cell on its own line with no gaps while keeping in-cell breaks.
|
|
3726
|
+
let plainText;
|
|
3727
|
+
let hasEncodedWhitespace = (_a = payload.hasEncodedWhitespace) !== null && _a !== void 0 ? _a : false;
|
|
3728
|
+
if (payload.html &&
|
|
3729
|
+
payload.text &&
|
|
3730
|
+
payload.text.includes('\t') &&
|
|
3731
|
+
imageExtension.htmlContainsTable(payload.html)) {
|
|
3732
|
+
plainText = payload.text;
|
|
3733
|
+
}
|
|
3734
|
+
else if (payload.html && imageExtension.htmlContainsTable(payload.html)) {
|
|
3735
|
+
plainText = this.extractPlainTextFromHtml(payload.html, true);
|
|
3736
|
+
hasEncodedWhitespace = true;
|
|
3737
|
+
}
|
|
3738
|
+
else {
|
|
3739
|
+
plainText = '';
|
|
3740
|
+
if (payload.text) {
|
|
3741
|
+
plainText = payload.text;
|
|
3742
|
+
}
|
|
3743
|
+
else if (payload.html) {
|
|
3744
|
+
plainText = this.extractPlainTextFromHtml(payload.html, true);
|
|
3745
|
+
hasEncodedWhitespace = true;
|
|
3746
|
+
}
|
|
3747
|
+
}
|
|
3748
|
+
const styleSource = (currentRange === null || currentRange === void 0 ? void 0 : currentRange.startNode) instanceof codeBlock.RTETextNode ? currentRange.startNode : undefined;
|
|
3749
|
+
return this.buildPlainTextParagraph(plainText, styleSource, hasEncodedWhitespace);
|
|
3750
|
+
}
|
|
3522
3751
|
let pastedHTML = payload.html || '';
|
|
3523
3752
|
if (!pastedHTML) {
|
|
3524
3753
|
pastedHTML = this.parsePlainText(payload.text || '');
|
|
@@ -3556,16 +3785,21 @@ class InsertPasteHandler extends BaseHandler {
|
|
|
3556
3785
|
return resultBlocks;
|
|
3557
3786
|
}
|
|
3558
3787
|
/**
|
|
3559
|
-
* Extracts
|
|
3788
|
+
* Extracts plain text from HTML when clipboard lacks `text/plain`.
|
|
3560
3789
|
*
|
|
3561
3790
|
* @param {string} html - Clipboard text/html payload.
|
|
3791
|
+
* @param {boolean} keepPreservedWhitespaceMarkers - Keep code-block indentation as sentinels so
|
|
3792
|
+
* the plain-mode boundary collapse in `toPlainPasteLines` does not strip it (that helper decodes
|
|
3793
|
+
* the sentinels). Must stay `false` for the rich path, which feeds `parsePlainText` directly.
|
|
3562
3794
|
* @returns {string} - Plain text extracted from HTML.
|
|
3563
3795
|
*/
|
|
3564
|
-
extractPlainTextFromHtml(html) {
|
|
3796
|
+
extractPlainTextFromHtml(html, keepPreservedWhitespaceMarkers = false) {
|
|
3565
3797
|
// Preserve inline styles before parsing to avoid style-src-attr CSP violations.
|
|
3566
3798
|
const safeHtml = contentState.StylePreservator.preserve(html).getProcessedHtml();
|
|
3567
|
-
|
|
3568
|
-
|
|
3799
|
+
return imageExtension.htmlToPlainText(safeHtml, {
|
|
3800
|
+
preserveBoundaryBlankLines: true,
|
|
3801
|
+
keepPreservedWhitespaceMarkers,
|
|
3802
|
+
});
|
|
3569
3803
|
}
|
|
3570
3804
|
/**
|
|
3571
3805
|
* Builds plain-text paragraph blocks when element strategy parsing returns no output.
|
|
@@ -3574,7 +3808,7 @@ class InsertPasteHandler extends BaseHandler {
|
|
|
3574
3808
|
* @returns {RTEContentBlock[]} Fallback text blocks.
|
|
3575
3809
|
*/
|
|
3576
3810
|
buildPlainTextFallbackBlocks(text) {
|
|
3577
|
-
return
|
|
3811
|
+
return codeBlock.normalizePlainTextLines(text).map((line) => {
|
|
3578
3812
|
const paragraph = new codeBlock.RTETextBlock(misc.generateUUID(), 'paragraph');
|
|
3579
3813
|
const textNode = new codeBlock.RTETextNode(`${paragraph.id}1`, line, paragraph);
|
|
3580
3814
|
paragraph.apply(new codeBlock.AppendChildrenAction([textNode]));
|
|
@@ -3582,21 +3816,66 @@ class InsertPasteHandler extends BaseHandler {
|
|
|
3582
3816
|
});
|
|
3583
3817
|
}
|
|
3584
3818
|
/**
|
|
3585
|
-
*
|
|
3819
|
+
* Builds plain-text paragraphs by splitting on `\n`.
|
|
3820
|
+
*
|
|
3821
|
+
* Shares `toPlainPasteLines` with `PlainPasteProcessingStrategy` so both
|
|
3822
|
+
* representations of plain-mode content (HTML and RTE nodes) agree on line
|
|
3823
|
+
* boundaries and boundary whitespace.
|
|
3824
|
+
*
|
|
3825
|
+
* @param {string} text - Plain text clipboard content.
|
|
3826
|
+
* @param {RTETextNode} [styleSource] - Optional style to preserve in all nodes.
|
|
3827
|
+
* @param {boolean} decodeEncodedWhitespace - Decode HTML-derived whitespace markers.
|
|
3828
|
+
* @returns {RTEContentBlock[]} Paragraph-per-line blocks.
|
|
3829
|
+
*/
|
|
3830
|
+
buildPlainTextParagraph(text, styleSource, decodeEncodedWhitespace = false) {
|
|
3831
|
+
const lines = codeBlock.toPlainPasteLines(text, decodeEncodedWhitespace);
|
|
3832
|
+
return lines.map((line, lineIndex) => {
|
|
3833
|
+
const paragraph = new codeBlock.RTETextBlock(misc.generateUUID(), 'paragraph');
|
|
3834
|
+
// Always attach a text node (empty for blank lines) so empty paragraphs
|
|
3835
|
+
// render with a zero-width space and keep their visible line height,
|
|
3836
|
+
// instead of collapsing to an invisible zero-height `<p></p>`.
|
|
3837
|
+
const node = this.createPlainTextNode(paragraph, lineIndex, line, styleSource);
|
|
3838
|
+
paragraph.apply(new codeBlock.AppendChildrenAction([node]));
|
|
3839
|
+
return paragraph;
|
|
3840
|
+
});
|
|
3841
|
+
}
|
|
3842
|
+
/**
|
|
3843
|
+
* Creates a text node for plain paste; optionally inherits style from source node.
|
|
3844
|
+
*
|
|
3845
|
+
* @param {RTETextBlock} paragraph - Parent paragraph.
|
|
3846
|
+
* @param {number} index - Character index for node ID generation.
|
|
3847
|
+
* @param {string} text - Text content.
|
|
3848
|
+
* @param {RTETextNode} [styleSource] - Optional style to inherit.
|
|
3849
|
+
* @returns {RTETextNode} Created text node.
|
|
3850
|
+
*/
|
|
3851
|
+
createPlainTextNode(paragraph, index, text, styleSource) {
|
|
3852
|
+
const node = styleSource
|
|
3853
|
+
? styleSource.cloneWithText(text)
|
|
3854
|
+
: new codeBlock.RTETextNode(`${paragraph.id}-${index}`, text, paragraph);
|
|
3855
|
+
node.parent = paragraph;
|
|
3856
|
+
return node;
|
|
3857
|
+
}
|
|
3858
|
+
/**
|
|
3859
|
+
* Builds the caret operation that moves onto a block element in a rich text editor after paste.
|
|
3586
3860
|
*
|
|
3587
3861
|
* @param {RTEBlock} newBlock - Block element to move the caret to.
|
|
3588
3862
|
* @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.
|
|
3863
|
+
* @returns {CompositionOperation | void} The caret operation, or nothing when the block has no children.
|
|
3589
3864
|
*/
|
|
3590
|
-
|
|
3865
|
+
caretToBlockOperation(newBlock, atEnd = false) {
|
|
3591
3866
|
var _a, _b;
|
|
3592
3867
|
if (newBlock && newBlock.children) {
|
|
3593
3868
|
if (atEnd) {
|
|
3594
3869
|
const lastNode = newBlock.children[newBlock.children.length - 1];
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3870
|
+
return {
|
|
3871
|
+
target: this.currentState,
|
|
3872
|
+
action: new contentState.UpdateCursorPositionAction(lastNode, (_b = (_a = lastNode.text) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0),
|
|
3873
|
+
};
|
|
3599
3874
|
}
|
|
3875
|
+
return {
|
|
3876
|
+
target: this.currentState,
|
|
3877
|
+
action: new contentState.UpdateCursorPositionAction(newBlock.children[0], 0),
|
|
3878
|
+
};
|
|
3600
3879
|
}
|
|
3601
3880
|
}
|
|
3602
3881
|
/**
|
|
@@ -3816,6 +4095,7 @@ class InsertPasteHandler extends BaseHandler {
|
|
|
3816
4095
|
html: event.dataTransfer.getData('text/html') || eventPayload.html || '',
|
|
3817
4096
|
text: event.dataTransfer.getData('text/plain') || eventPayload.text || '',
|
|
3818
4097
|
type: event.dataTransfer.getData(codeBlock.RTE_PASTE_MODE_DATA_TYPE) || '',
|
|
4098
|
+
hasEncodedWhitespace: event.dataTransfer.getData(codeBlock.RTE_PRESERVED_WHITESPACE_DATA_TYPE) === 'true',
|
|
3819
4099
|
};
|
|
3820
4100
|
}
|
|
3821
4101
|
}
|
|
@@ -4140,6 +4420,8 @@ class UserInputController extends globalSlimmerRegistry.VegaSlimmer {
|
|
|
4140
4420
|
};
|
|
4141
4421
|
/**
|
|
4142
4422
|
* When a user performs an input action within the editable element, this function is triggered.
|
|
4423
|
+
* Each handler owns its own `flushOptions` on `BaseHandler`, so the value update flows through
|
|
4424
|
+
* the shared flush-changes action pipeline without this method having to construct or forward it.
|
|
4143
4425
|
*
|
|
4144
4426
|
* @param {InputEvent} e the before input event object
|
|
4145
4427
|
*/
|
|
@@ -4153,41 +4435,26 @@ class UserInputController extends globalSlimmerRegistry.VegaSlimmer {
|
|
|
4153
4435
|
return;
|
|
4154
4436
|
}
|
|
4155
4437
|
this.insertCompositionTextController.removeObserver();
|
|
4156
|
-
let updateFlag = false;
|
|
4157
|
-
let updateSource = codeBlock.RTEUpdateSource.Default;
|
|
4158
4438
|
switch (inputType) {
|
|
4159
4439
|
case 'insertParagraph':
|
|
4160
|
-
updateFlag = true;
|
|
4161
4440
|
this.insertParagraphHandler.execute(this.value, this.selectionController, this.host, e);
|
|
4162
4441
|
break;
|
|
4163
4442
|
case 'insertText':
|
|
4164
|
-
updateFlag = true;
|
|
4165
|
-
updateSource =
|
|
4166
|
-
e[codeBlock.RTE_UPDATE_SOURCE_KEY] === codeBlock.RTEUpdateSource.Composition
|
|
4167
|
-
? codeBlock.RTEUpdateSource.Composition
|
|
4168
|
-
: codeBlock.RTEUpdateSource.Default;
|
|
4169
4443
|
this.insertTextHandler.execute(this.value, this.selectionController, this.host, e);
|
|
4170
4444
|
break;
|
|
4171
4445
|
case 'insertLineBreak':
|
|
4172
|
-
updateFlag = true;
|
|
4173
4446
|
this.insertLineBreakHandler.execute(this.value, this.selectionController, this.host, e);
|
|
4174
4447
|
break;
|
|
4175
4448
|
case 'deleteContentForward':
|
|
4176
|
-
updateFlag = true;
|
|
4177
4449
|
this.forwardDeleteContentHandler.execute(this.value, this.selectionController, this.host, e);
|
|
4178
4450
|
break;
|
|
4179
4451
|
case 'deleteContentBackward':
|
|
4180
|
-
updateFlag = true;
|
|
4181
4452
|
this.backwardDeleteContentHandler.execute(this.value, this.selectionController, this.host, e);
|
|
4182
4453
|
break;
|
|
4183
4454
|
case 'insertFromPaste':
|
|
4184
|
-
updateFlag = true;
|
|
4185
4455
|
this.insertPasteHandler.execute(this.value, this.selectionController, this.host, e);
|
|
4186
4456
|
break;
|
|
4187
4457
|
}
|
|
4188
|
-
if (updateFlag) {
|
|
4189
|
-
void this.valueController.flushChanges(this.value, true, updateSource);
|
|
4190
|
-
}
|
|
4191
4458
|
};
|
|
4192
4459
|
}
|
|
4193
4460
|
/**
|