@wordpress/block-editor 16.0.0 → 16.1.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/CHANGELOG.md +18 -0
- package/README.md +8 -0
- package/build/components/alignment-control/ui.cjs +2 -4
- package/build/components/alignment-control/ui.cjs.map +2 -2
- package/build/components/background-image-control/index.cjs +40 -10
- package/build/components/background-image-control/index.cjs.map +2 -2
- package/build/components/block-alignment-control/ui.cjs +5 -3
- package/build/components/block-alignment-control/ui.cjs.map +2 -2
- package/build/components/block-inspector/index.cjs +73 -46
- package/build/components/block-inspector/index.cjs.map +2 -2
- package/build/components/block-list/block-html.cjs +4 -1
- package/build/components/block-list/block-html.cjs.map +2 -2
- package/build/components/block-list/use-block-props/index.cjs +5 -2
- package/build/components/block-list/use-block-props/index.cjs.map +2 -2
- package/build/components/block-list/use-block-props/use-focus-handler.cjs +2 -3
- package/build/components/block-list/use-block-props/use-focus-handler.cjs.map +2 -2
- package/build/components/block-list/use-block-props/use-register-block-event-handlers.cjs +48 -0
- package/build/components/block-list/use-block-props/use-register-block-event-handlers.cjs.map +7 -0
- package/build/components/block-parent-selector/index.cjs +2 -2
- package/build/components/block-parent-selector/index.cjs.map +2 -2
- package/build/components/block-toolbar/switch-section-style.cjs +4 -2
- package/build/components/block-toolbar/switch-section-style.cjs.map +3 -3
- package/build/components/block-tools/empty-block-inserter.cjs +2 -7
- package/build/components/block-tools/empty-block-inserter.cjs.map +2 -2
- package/build/components/block-vertical-alignment-control/ui.cjs +3 -5
- package/build/components/block-vertical-alignment-control/ui.cjs.map +2 -2
- package/build/components/border-radius-control/utils.cjs +8 -58
- package/build/components/border-radius-control/utils.cjs.map +2 -2
- package/build/components/colors-gradients/control.cjs +5 -3
- package/build/components/colors-gradients/control.cjs.map +2 -2
- package/build/components/dimension-control/index.cjs +30 -20
- package/build/components/dimension-control/index.cjs.map +3 -3
- package/build/components/dimensions-tool/aspect-ratio-tool.cjs +9 -2
- package/build/components/dimensions-tool/aspect-ratio-tool.cjs.map +3 -3
- package/build/components/editor-styles/index.cjs +9 -1
- package/build/components/editor-styles/index.cjs.map +2 -2
- package/build/components/global-styles/background-panel.cjs +66 -25
- package/build/components/global-styles/background-panel.cjs.map +3 -3
- package/build/components/global-styles/border-panel.cjs +153 -55
- package/build/components/global-styles/border-panel.cjs.map +3 -3
- package/build/components/global-styles/color-gradient-dropdown-item.cjs +46 -14
- package/build/components/global-styles/color-gradient-dropdown-item.cjs.map +3 -3
- package/build/components/global-styles/color-panel.cjs +63 -17
- package/build/components/global-styles/color-panel.cjs.map +2 -2
- package/build/components/global-styles/dimensions-panel.cjs +242 -64
- package/build/components/global-styles/dimensions-panel.cjs.map +3 -3
- package/build/components/global-styles/filters-panel.cjs +59 -20
- package/build/components/global-styles/filters-panel.cjs.map +3 -3
- package/build/components/global-styles/hooks.cjs +4 -1
- package/build/components/global-styles/hooks.cjs.map +2 -2
- package/build/components/global-styles/inheritance/index.cjs +142 -0
- package/build/components/global-styles/inheritance/index.cjs.map +7 -0
- package/build/components/global-styles/inherited-value-context.cjs +173 -0
- package/build/components/global-styles/inherited-value-context.cjs.map +7 -0
- package/build/components/global-styles/shadow-panel-components.cjs +38 -20
- package/build/components/global-styles/shadow-panel-components.cjs.map +2 -2
- package/build/components/global-styles/state-control.cjs +1 -1
- package/build/components/global-styles/state-control.cjs.map +2 -2
- package/build/components/global-styles/typography-panel.cjs +271 -78
- package/build/components/global-styles/typography-panel.cjs.map +3 -3
- package/build/components/inspector-controls-tabs/styles-tab.cjs +10 -1
- package/build/components/inspector-controls-tabs/styles-tab.cjs.map +2 -2
- package/build/components/line-height-control/index.cjs +1 -1
- package/build/components/line-height-control/index.cjs.map +2 -2
- package/build/components/link-control/index.cjs +3 -1
- package/build/components/link-control/index.cjs.map +2 -2
- package/build/components/preset-input-control/index.cjs +2 -1
- package/build/components/preset-input-control/index.cjs.map +2 -2
- package/build/components/provider/block-refs-provider.cjs +8 -2
- package/build/components/provider/block-refs-provider.cjs.map +2 -2
- package/build/components/provider/index.cjs +1 -1
- package/build/components/provider/index.cjs.map +2 -2
- package/build/components/provider/use-block-sync.cjs +18 -6
- package/build/components/provider/use-block-sync.cjs.map +2 -2
- package/build/components/provider/use-media-upload-settings.cjs +3 -1
- package/build/components/provider/use-media-upload-settings.cjs.map +2 -2
- package/build/components/rich-text/index.cjs +23 -13
- package/build/components/rich-text/index.cjs.map +2 -2
- package/build/components/spacing-sizes-control/utils.cjs +6 -19
- package/build/components/spacing-sizes-control/utils.cjs.map +2 -2
- package/build/components/text-indent-control/index.cjs +8 -2
- package/build/components/text-indent-control/index.cjs.map +2 -2
- package/build/components/url-input/index.cjs +303 -344
- package/build/components/url-input/index.cjs.map +3 -3
- package/build/components/writing-flow/index.cjs +2 -0
- package/build/components/writing-flow/index.cjs.map +3 -3
- package/build/components/writing-flow/use-arrow-nav.cjs +24 -1
- package/build/components/writing-flow/use-arrow-nav.cjs.map +2 -2
- package/build/components/writing-flow/use-click-selection.cjs +28 -2
- package/build/components/writing-flow/use-click-selection.cjs.map +2 -2
- package/build/components/writing-flow/use-editable-root-event-handlers.cjs +179 -0
- package/build/components/writing-flow/use-editable-root-event-handlers.cjs.map +7 -0
- package/build/components/writing-flow/use-editable-root.cjs +5 -42
- package/build/components/writing-flow/use-editable-root.cjs.map +2 -2
- package/build/components/writing-flow/use-home-end.cjs +1 -1
- package/build/components/writing-flow/use-home-end.cjs.map +2 -2
- package/build/components/writing-flow/use-selection-observer.cjs +17 -13
- package/build/components/writing-flow/use-selection-observer.cjs.map +2 -2
- package/build/components/writing-flow/utils.cjs +3 -14
- package/build/components/writing-flow/utils.cjs.map +2 -2
- package/build/hooks/background.cjs +13 -10
- package/build/hooks/background.cjs.map +2 -2
- package/build/hooks/block-style-variation.cjs +4 -45
- package/build/hooks/block-style-variation.cjs.map +3 -3
- package/build/hooks/border.cjs +19 -4
- package/build/hooks/border.cjs.map +2 -2
- package/build/hooks/custom-css.cjs +6 -2
- package/build/hooks/custom-css.cjs.map +2 -2
- package/build/hooks/dimensions.cjs +15 -4
- package/build/hooks/dimensions.cjs.map +2 -2
- package/build/hooks/duotone.cjs +26 -14
- package/build/hooks/duotone.cjs.map +3 -3
- package/build/hooks/elements.cjs +14 -4
- package/build/hooks/elements.cjs.map +2 -2
- package/build/hooks/line-height.cjs +1 -2
- package/build/hooks/line-height.cjs.map +2 -2
- package/build/hooks/typography.cjs +13 -4
- package/build/hooks/typography.cjs.map +2 -2
- package/build/private-apis.cjs +9 -5
- package/build/private-apis.cjs.map +3 -3
- package/build/store/actions.cjs +9 -4
- package/build/store/actions.cjs.map +2 -2
- package/build/store/private-selectors.cjs +28 -1
- package/build/store/private-selectors.cjs.map +2 -2
- package/build/store/reducer.cjs +6 -6
- package/build/store/reducer.cjs.map +2 -2
- package/build/store/selectors.cjs +23 -0
- package/build/store/selectors.cjs.map +2 -2
- package/build/utils/native-undo.cjs +55 -0
- package/build/utils/native-undo.cjs.map +7 -0
- package/build-module/components/alignment-control/ui.mjs +2 -4
- package/build-module/components/alignment-control/ui.mjs.map +2 -2
- package/build-module/components/background-image-control/index.mjs +43 -10
- package/build-module/components/background-image-control/index.mjs.map +2 -2
- package/build-module/components/block-alignment-control/ui.mjs +5 -3
- package/build-module/components/block-alignment-control/ui.mjs.map +2 -2
- package/build-module/components/block-inspector/index.mjs +74 -46
- package/build-module/components/block-inspector/index.mjs.map +2 -2
- package/build-module/components/block-list/block-html.mjs +4 -1
- package/build-module/components/block-list/block-html.mjs.map +2 -2
- package/build-module/components/block-list/use-block-props/index.mjs +5 -2
- package/build-module/components/block-list/use-block-props/index.mjs.map +2 -2
- package/build-module/components/block-list/use-block-props/use-focus-handler.mjs +2 -3
- package/build-module/components/block-list/use-block-props/use-focus-handler.mjs.map +2 -2
- package/build-module/components/block-list/use-block-props/use-register-block-event-handlers.mjs +28 -0
- package/build-module/components/block-list/use-block-props/use-register-block-event-handlers.mjs.map +7 -0
- package/build-module/components/block-parent-selector/index.mjs +2 -2
- package/build-module/components/block-parent-selector/index.mjs.map +2 -2
- package/build-module/components/block-toolbar/switch-section-style.mjs +4 -2
- package/build-module/components/block-toolbar/switch-section-style.mjs.map +2 -2
- package/build-module/components/block-tools/empty-block-inserter.mjs +2 -7
- package/build-module/components/block-tools/empty-block-inserter.mjs.map +2 -2
- package/build-module/components/block-vertical-alignment-control/ui.mjs +4 -6
- package/build-module/components/block-vertical-alignment-control/ui.mjs.map +2 -2
- package/build-module/components/border-radius-control/utils.mjs +11 -53
- package/build-module/components/border-radius-control/utils.mjs.map +2 -2
- package/build-module/components/colors-gradients/control.mjs +5 -3
- package/build-module/components/colors-gradients/control.mjs.map +2 -2
- package/build-module/components/dimension-control/index.mjs +30 -20
- package/build-module/components/dimension-control/index.mjs.map +2 -2
- package/build-module/components/dimensions-tool/aspect-ratio-tool.mjs +10 -6
- package/build-module/components/dimensions-tool/aspect-ratio-tool.mjs.map +2 -2
- package/build-module/components/editor-styles/index.mjs +9 -1
- package/build-module/components/editor-styles/index.mjs.map +2 -2
- package/build-module/components/global-styles/background-panel.mjs +71 -29
- package/build-module/components/global-styles/background-panel.mjs.map +2 -2
- package/build-module/components/global-styles/border-panel.mjs +157 -56
- package/build-module/components/global-styles/border-panel.mjs.map +2 -2
- package/build-module/components/global-styles/color-gradient-dropdown-item.mjs +51 -15
- package/build-module/components/global-styles/color-gradient-dropdown-item.mjs.map +2 -2
- package/build-module/components/global-styles/color-panel.mjs +63 -17
- package/build-module/components/global-styles/color-panel.mjs.map +2 -2
- package/build-module/components/global-styles/dimensions-panel.mjs +248 -66
- package/build-module/components/global-styles/dimensions-panel.mjs.map +2 -2
- package/build-module/components/global-styles/filters-panel.mjs +64 -21
- package/build-module/components/global-styles/filters-panel.mjs.map +2 -2
- package/build-module/components/global-styles/hooks.mjs +4 -1
- package/build-module/components/global-styles/hooks.mjs.map +2 -2
- package/build-module/components/global-styles/inheritance/index.mjs +108 -0
- package/build-module/components/global-styles/inheritance/index.mjs.map +7 -0
- package/build-module/components/global-styles/inherited-value-context.mjs +141 -0
- package/build-module/components/global-styles/inherited-value-context.mjs.map +7 -0
- package/build-module/components/global-styles/shadow-panel-components.mjs +38 -20
- package/build-module/components/global-styles/shadow-panel-components.mjs.map +2 -2
- package/build-module/components/global-styles/state-control.mjs +1 -1
- package/build-module/components/global-styles/state-control.mjs.map +2 -2
- package/build-module/components/global-styles/typography-panel.mjs +276 -79
- package/build-module/components/global-styles/typography-panel.mjs.map +2 -2
- package/build-module/components/inspector-controls-tabs/styles-tab.mjs +6 -1
- package/build-module/components/inspector-controls-tabs/styles-tab.mjs.map +2 -2
- package/build-module/components/line-height-control/index.mjs +1 -1
- package/build-module/components/line-height-control/index.mjs.map +2 -2
- package/build-module/components/link-control/index.mjs +4 -2
- package/build-module/components/link-control/index.mjs.map +2 -2
- package/build-module/components/preset-input-control/index.mjs +2 -1
- package/build-module/components/preset-input-control/index.mjs.map +2 -2
- package/build-module/components/provider/block-refs-provider.mjs +8 -2
- package/build-module/components/provider/block-refs-provider.mjs.map +2 -2
- package/build-module/components/provider/index.mjs +1 -1
- package/build-module/components/provider/index.mjs.map +2 -2
- package/build-module/components/provider/use-block-sync.mjs +18 -6
- package/build-module/components/provider/use-block-sync.mjs.map +2 -2
- package/build-module/components/provider/use-media-upload-settings.mjs +3 -1
- package/build-module/components/provider/use-media-upload-settings.mjs.map +2 -2
- package/build-module/components/rich-text/index.mjs +28 -14
- package/build-module/components/rich-text/index.mjs.map +2 -2
- package/build-module/components/spacing-sizes-control/utils.mjs +6 -18
- package/build-module/components/spacing-sizes-control/utils.mjs.map +2 -2
- package/build-module/components/text-indent-control/index.mjs +8 -2
- package/build-module/components/text-indent-control/index.mjs.map +2 -2
- package/build-module/components/url-input/index.mjs +306 -353
- package/build-module/components/url-input/index.mjs.map +2 -2
- package/build-module/components/writing-flow/index.mjs +2 -0
- package/build-module/components/writing-flow/index.mjs.map +2 -2
- package/build-module/components/writing-flow/use-arrow-nav.mjs +24 -1
- package/build-module/components/writing-flow/use-arrow-nav.mjs.map +2 -2
- package/build-module/components/writing-flow/use-click-selection.mjs +28 -2
- package/build-module/components/writing-flow/use-click-selection.mjs.map +2 -2
- package/build-module/components/writing-flow/use-editable-root-event-handlers.mjs +154 -0
- package/build-module/components/writing-flow/use-editable-root-event-handlers.mjs.map +7 -0
- package/build-module/components/writing-flow/use-editable-root.mjs +5 -37
- package/build-module/components/writing-flow/use-editable-root.mjs.map +2 -2
- package/build-module/components/writing-flow/use-home-end.mjs +1 -1
- package/build-module/components/writing-flow/use-home-end.mjs.map +2 -2
- package/build-module/components/writing-flow/use-selection-observer.mjs +18 -14
- package/build-module/components/writing-flow/use-selection-observer.mjs.map +2 -2
- package/build-module/components/writing-flow/utils.mjs +2 -11
- package/build-module/components/writing-flow/utils.mjs.map +2 -2
- package/build-module/hooks/background.mjs +13 -10
- package/build-module/hooks/background.mjs.map +2 -2
- package/build-module/hooks/block-style-variation.mjs +8 -44
- package/build-module/hooks/block-style-variation.mjs.map +2 -2
- package/build-module/hooks/border.mjs +19 -4
- package/build-module/hooks/border.mjs.map +2 -2
- package/build-module/hooks/custom-css.mjs +7 -3
- package/build-module/hooks/custom-css.mjs.map +2 -2
- package/build-module/hooks/dimensions.mjs +15 -4
- package/build-module/hooks/dimensions.mjs.map +2 -2
- package/build-module/hooks/duotone.mjs +20 -9
- package/build-module/hooks/duotone.mjs.map +2 -2
- package/build-module/hooks/elements.mjs +14 -4
- package/build-module/hooks/elements.mjs.map +2 -2
- package/build-module/hooks/line-height.mjs +1 -2
- package/build-module/hooks/line-height.mjs.map +2 -2
- package/build-module/hooks/typography.mjs +13 -4
- package/build-module/hooks/typography.mjs.map +2 -2
- package/build-module/private-apis.mjs +7 -3
- package/build-module/private-apis.mjs.map +2 -2
- package/build-module/store/actions.mjs +9 -4
- package/build-module/store/actions.mjs.map +2 -2
- package/build-module/store/private-selectors.mjs +29 -1
- package/build-module/store/private-selectors.mjs.map +2 -2
- package/build-module/store/reducer.mjs +6 -6
- package/build-module/store/reducer.mjs.map +2 -2
- package/build-module/store/selectors.mjs +23 -0
- package/build-module/store/selectors.mjs.map +2 -2
- package/build-module/utils/native-undo.mjs +29 -0
- package/build-module/utils/native-undo.mjs.map +7 -0
- package/build-style/content-rtl.css +10 -18
- package/build-style/content.css +10 -18
- package/build-style/style-rtl.css +150 -7
- package/build-style/style.css +150 -7
- package/package.json +40 -41
- package/src/components/alignment-control/test/__snapshots__/index.js.snap +1 -1
- package/src/components/alignment-control/ui.js +2 -4
- package/src/components/background-image-control/index.js +74 -37
- package/src/components/background-image-control/style.scss +13 -4
- package/src/components/block-alignment-control/test/__snapshots__/index.js.snap +3 -3
- package/src/components/block-alignment-control/test/index.js +1 -1
- package/src/components/block-alignment-control/ui.js +4 -2
- package/src/components/block-breadcrumb/test/__snapshots__/index.js.snap +1 -1
- package/src/components/block-compare/test/__snapshots__/block-view.js.snap +1 -1
- package/src/components/block-icon/test/__snapshots__/index.js.snap +1 -1
- package/src/components/block-inspector/index.js +60 -31
- package/src/components/block-list/block-html.js +5 -0
- package/src/components/block-list/content.scss +1 -11
- package/src/components/block-list/use-block-props/index.js +5 -1
- package/src/components/block-list/use-block-props/use-focus-handler.js +9 -8
- package/src/components/block-list/use-block-props/use-register-block-event-handlers.js +45 -0
- package/src/components/block-parent-selector/index.js +5 -2
- package/src/components/block-toolbar/switch-section-style.js +5 -2
- package/src/components/block-tools/empty-block-inserter.js +3 -7
- package/src/components/block-vertical-alignment-control/test/__snapshots__/index.js.snap +3 -3
- package/src/components/block-vertical-alignment-control/test/index.js +18 -2
- package/src/components/block-vertical-alignment-control/ui.js +3 -5
- package/src/components/border-radius-control/test/utils.js +0 -41
- package/src/components/border-radius-control/utils.js +16 -107
- package/src/components/button-block-appender/content.scss +6 -2
- package/src/components/color-palette/test/__snapshots__/control.js.snap +1 -1
- package/src/components/colors-gradients/control.js +6 -3
- package/src/components/default-block-appender/test/__snapshots__/index.js.snap +1 -1
- package/src/components/dimension-control/index.js +13 -1
- package/src/components/dimensions-tool/aspect-ratio-tool.js +13 -6
- package/src/components/editor-styles/index.js +16 -1
- package/src/components/global-styles/background-panel.js +107 -34
- package/src/components/global-styles/border-panel.js +219 -48
- package/src/components/global-styles/color-gradient-dropdown-item.js +93 -28
- package/src/components/global-styles/color-panel.js +92 -11
- package/src/components/global-styles/dimensions-panel.js +422 -71
- package/src/components/global-styles/filters-panel.js +88 -28
- package/src/components/global-styles/hooks.js +8 -1
- package/src/components/global-styles/inheritance/index.js +204 -0
- package/src/components/global-styles/inheritance/style.scss +184 -0
- package/src/components/global-styles/inheritance/test/index.js +281 -0
- package/src/components/global-styles/inherited-value-context.js +271 -0
- package/src/components/global-styles/shadow-panel-components.js +48 -26
- package/src/components/global-styles/state-control.js +2 -2
- package/src/components/global-styles/test/background-panel.js +338 -1
- package/src/components/global-styles/test/border-panel.js +441 -0
- package/src/components/global-styles/test/color-panel.js +182 -2
- package/src/components/global-styles/test/dimensions-panel.js +753 -0
- package/src/components/global-styles/test/filters-panel.js +194 -0
- package/src/components/global-styles/test/inherited-value-context-core.js +98 -0
- package/src/components/global-styles/test/inherited-value-context.js +454 -0
- package/src/components/global-styles/test/typography-panel-core.js +185 -0
- package/src/components/global-styles/test/typography-panel.js +849 -12
- package/src/components/global-styles/typography-panel.js +449 -100
- package/src/components/image-editor/style.scss +33 -0
- package/src/components/inner-blocks/test/__snapshots__/index.js.snap +1 -1
- package/src/components/inspector-controls-tabs/styles-tab.js +5 -1
- package/src/components/line-height-control/index.js +1 -1
- package/src/components/link-control/index.js +7 -2
- package/src/components/preset-input-control/index.js +4 -1
- package/src/components/provider/block-refs-provider.js +12 -2
- package/src/components/provider/index.js +2 -2
- package/src/components/provider/use-block-sync.js +18 -6
- package/src/components/provider/use-media-upload-settings.js +2 -0
- package/src/components/rich-text/index.js +37 -16
- package/src/components/spacing-sizes-control/test/utils.js +16 -5
- package/src/components/spacing-sizes-control/utils.js +11 -28
- package/src/components/text-indent-control/index.js +8 -0
- package/src/components/url-input/index.js +363 -431
- package/src/components/url-input/test/index.js +592 -0
- package/src/components/warning/test/__snapshots__/index.js.snap +1 -1
- package/src/components/writing-flow/index.js +2 -0
- package/src/components/writing-flow/use-arrow-nav.js +51 -1
- package/src/components/writing-flow/use-click-selection.js +54 -3
- package/src/components/writing-flow/use-editable-root-event-handlers.js +266 -0
- package/src/components/writing-flow/use-editable-root.js +7 -77
- package/src/components/writing-flow/use-home-end.js +17 -9
- package/src/components/writing-flow/use-selection-observer.js +32 -15
- package/src/components/writing-flow/utils.js +3 -24
- package/src/hooks/background.js +26 -21
- package/src/hooks/block-fields/rich-text/styles.scss +1 -1
- package/src/hooks/block-style-variation.js +8 -74
- package/src/hooks/border.js +19 -4
- package/src/hooks/custom-css.js +15 -6
- package/src/hooks/dimensions.js +17 -4
- package/src/hooks/duotone.js +26 -8
- package/src/hooks/elements.js +14 -3
- package/src/hooks/line-height.js +0 -1
- package/src/hooks/test/inherited-value-wiring.js +411 -0
- package/src/hooks/test/preset-round-trip.js +456 -0
- package/src/hooks/typography.js +35 -23
- package/src/private-apis.js +11 -2
- package/src/store/actions.js +10 -4
- package/src/store/private-selectors.js +57 -1
- package/src/store/reducer.js +9 -9
- package/src/store/selectors.js +56 -8
- package/src/store/test/private-selectors.js +160 -1
- package/src/style.scss +2 -0
- package/src/utils/native-undo.js +56 -0
- package/build/components/duotone/utils.cjs +0 -87
- package/build/components/duotone/utils.cjs.map +0 -7
- package/build-module/components/duotone/utils.mjs +0 -59
- package/build-module/components/duotone/utils.mjs.map +0 -7
- package/src/components/duotone/utils.js +0 -90
- package/src/hooks/test/get-variation-styles-with-ref-values.js +0 -91
|
@@ -13,8 +13,12 @@ import { getBlockClientId } from '../../utils/dom';
|
|
|
13
13
|
|
|
14
14
|
export default function useClickSelection() {
|
|
15
15
|
const { selectBlock } = useDispatch( blockEditorStore );
|
|
16
|
-
const {
|
|
17
|
-
|
|
16
|
+
const {
|
|
17
|
+
isSelectionEnabled,
|
|
18
|
+
getBlockSelectionStart,
|
|
19
|
+
getSelectionStart,
|
|
20
|
+
hasMultiSelection,
|
|
21
|
+
} = useSelect( blockEditorStore );
|
|
18
22
|
return useRefEffect(
|
|
19
23
|
( node ) => {
|
|
20
24
|
function onMouseDown( event ) {
|
|
@@ -31,7 +35,53 @@ export default function useClickSelection() {
|
|
|
31
35
|
// When selecting a single block in a document by holding the shift key,
|
|
32
36
|
// don't mark this action as multiselection.
|
|
33
37
|
if ( startClientId && startClientId !== clickedClientId ) {
|
|
34
|
-
|
|
38
|
+
// When the selected block has no text selection
|
|
39
|
+
// within it (e.g. an image or spacer), there is no
|
|
40
|
+
// native selection for the wrapper to adopt when it
|
|
41
|
+
// is focused, so Safari inserts a caret at the start
|
|
42
|
+
// of the wrapper and asynchronously reveals it,
|
|
43
|
+
// scrolling a scrolled-down viewport back up, which
|
|
44
|
+
// `preventScroll` does not cover. Leave focus alone
|
|
45
|
+
// in that case: the click moves it.
|
|
46
|
+
const { clientId, attributeKey } = getSelectionStart();
|
|
47
|
+
setContentEditableWrapper( node, true, {
|
|
48
|
+
focus: !! attributeKey,
|
|
49
|
+
} );
|
|
50
|
+
|
|
51
|
+
// The browser extends the selection from the native
|
|
52
|
+
// anchor. When a block is selected without a text
|
|
53
|
+
// selection within it, there is no native anchor,
|
|
54
|
+
// and browsers synthesize one at the nearest text
|
|
55
|
+
// instead, excluding the block itself. Give the
|
|
56
|
+
// browser the right anchor before it acts on the
|
|
57
|
+
// click: the near edge of the selected block, so the
|
|
58
|
+
// whole block ends up within the extended selection.
|
|
59
|
+
const { ownerDocument } = node;
|
|
60
|
+
const selection =
|
|
61
|
+
ownerDocument.defaultView.getSelection();
|
|
62
|
+
const blockElement =
|
|
63
|
+
! attributeKey &&
|
|
64
|
+
ownerDocument.getElementById(
|
|
65
|
+
`block-${ clientId }`
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
if (
|
|
69
|
+
blockElement &&
|
|
70
|
+
! (
|
|
71
|
+
selection.anchorNode &&
|
|
72
|
+
blockElement.contains( selection.anchorNode )
|
|
73
|
+
)
|
|
74
|
+
) {
|
|
75
|
+
const isForward =
|
|
76
|
+
// eslint-disable-next-line no-bitwise
|
|
77
|
+
blockElement.compareDocumentPosition(
|
|
78
|
+
event.target
|
|
79
|
+
) & node.DOCUMENT_POSITION_FOLLOWING;
|
|
80
|
+
selection.setPosition(
|
|
81
|
+
blockElement,
|
|
82
|
+
isForward ? 0 : blockElement.childNodes.length
|
|
83
|
+
);
|
|
84
|
+
}
|
|
35
85
|
}
|
|
36
86
|
} else if ( hasMultiSelection() ) {
|
|
37
87
|
// Allow user to escape out of a multi-selection to a
|
|
@@ -54,6 +104,7 @@ export default function useClickSelection() {
|
|
|
54
104
|
selectBlock,
|
|
55
105
|
isSelectionEnabled,
|
|
56
106
|
getBlockSelectionStart,
|
|
107
|
+
getSelectionStart,
|
|
57
108
|
hasMultiSelection,
|
|
58
109
|
]
|
|
59
110
|
);
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WordPress dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { useSelect } from '@wordpress/data';
|
|
5
|
+
import { useRefEffect } from '@wordpress/compose';
|
|
6
|
+
import { useContext } from '@wordpress/element';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Internal dependencies
|
|
10
|
+
*/
|
|
11
|
+
import { store as blockEditorStore } from '../../store';
|
|
12
|
+
import { getBlockClientId, getSelectionEditableElement } from '../../utils/dom';
|
|
13
|
+
import { BlockRefs } from '../provider/block-refs-provider';
|
|
14
|
+
|
|
15
|
+
// The React `on*` props the host bridges, mapped to their DOM event type. Only
|
|
16
|
+
// editing events are redirected under `editableRoot` (the wrapper becomes the
|
|
17
|
+
// editing host, so keyboard, input and composition events target it instead of
|
|
18
|
+
// the block); pointer and other events still reach the block and need no
|
|
19
|
+
// bridging. React prop names don't map to DOM types by lowercasing in general
|
|
20
|
+
// (onChange is `input`, onDoubleClick is `dblclick`), so the mapping is
|
|
21
|
+
// explicit, which also locks the bridged surface to events React actually fires.
|
|
22
|
+
const SUPPORTED_EVENTS = {
|
|
23
|
+
onKeyDown: 'keydown',
|
|
24
|
+
onKeyUp: 'keyup',
|
|
25
|
+
onBeforeInput: 'beforeinput',
|
|
26
|
+
onInput: 'input',
|
|
27
|
+
onCompositionStart: 'compositionstart',
|
|
28
|
+
onCompositionUpdate: 'compositionupdate',
|
|
29
|
+
onCompositionEnd: 'compositionend',
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
// The DOM event types the host listens for. Fixed, so the host attaches these
|
|
33
|
+
// listeners once rather than tracking which types are in use.
|
|
34
|
+
const EVENT_TYPES = Object.values( SUPPORTED_EVENTS );
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Collects the supported `on*` event handlers from a set of props, e.g. a
|
|
38
|
+
* block's merged `wrapperProps`, keyed by DOM event type. Used by the block to
|
|
39
|
+
* register them (see `useRegisterBlockEventHandlers`).
|
|
40
|
+
*
|
|
41
|
+
* @param {Object} props Props to read handlers from.
|
|
42
|
+
*
|
|
43
|
+
* @return {Object|undefined} The handlers by event type, or undefined when
|
|
44
|
+
* there are none.
|
|
45
|
+
*/
|
|
46
|
+
export function getEventHandlers( props ) {
|
|
47
|
+
let handlers;
|
|
48
|
+
|
|
49
|
+
for ( const name in SUPPORTED_EVENTS ) {
|
|
50
|
+
if ( typeof props[ name ] === 'function' ) {
|
|
51
|
+
handlers = handlers || {};
|
|
52
|
+
handlers[ SUPPORTED_EVENTS[ name ] ] = props[ name ];
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return handlers;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// The native properties React copies onto its SyntheticEvent for each event
|
|
60
|
+
// type (the *EventInterface tables in react-dom), so the wrapper exposes exactly
|
|
61
|
+
// what a React handler would see and nothing more. Values are copied straight
|
|
62
|
+
// from the native event; React's normalizers only paper over browsers we don't
|
|
63
|
+
// support, and anything omitted stays reachable through `nativeEvent`, as in
|
|
64
|
+
// React (e.g. `getTargetRanges` on a `beforeinput`).
|
|
65
|
+
const EVENT_INTERFACE = [
|
|
66
|
+
'eventPhase',
|
|
67
|
+
'bubbles',
|
|
68
|
+
'cancelable',
|
|
69
|
+
'timeStamp',
|
|
70
|
+
'defaultPrevented',
|
|
71
|
+
'isTrusted',
|
|
72
|
+
];
|
|
73
|
+
const KEYBOARD_EVENT_INTERFACE = [
|
|
74
|
+
...EVENT_INTERFACE,
|
|
75
|
+
'view',
|
|
76
|
+
'detail',
|
|
77
|
+
'key',
|
|
78
|
+
'code',
|
|
79
|
+
'location',
|
|
80
|
+
'ctrlKey',
|
|
81
|
+
'shiftKey',
|
|
82
|
+
'altKey',
|
|
83
|
+
'metaKey',
|
|
84
|
+
'repeat',
|
|
85
|
+
'locale',
|
|
86
|
+
'getModifierState',
|
|
87
|
+
'charCode',
|
|
88
|
+
'keyCode',
|
|
89
|
+
'which',
|
|
90
|
+
];
|
|
91
|
+
const INPUT_EVENT_INTERFACE = [ ...EVENT_INTERFACE, 'data' ];
|
|
92
|
+
const EVENT_INTERFACES = {
|
|
93
|
+
keydown: KEYBOARD_EVENT_INTERFACE,
|
|
94
|
+
keyup: KEYBOARD_EVENT_INTERFACE,
|
|
95
|
+
beforeinput: INPUT_EVENT_INTERFACE,
|
|
96
|
+
input: INPUT_EVENT_INTERFACE,
|
|
97
|
+
compositionstart: INPUT_EVENT_INTERFACE,
|
|
98
|
+
compositionupdate: INPUT_EVENT_INTERFACE,
|
|
99
|
+
compositionend: INPUT_EVENT_INTERFACE,
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Builds a React `SyntheticEvent`-like object for an extension handler, which
|
|
104
|
+
* expects one. It mirrors what react-dom does: a plain object wrapping the real
|
|
105
|
+
* native event, eagerly copying the same interface properties React exposes for
|
|
106
|
+
* the event type, so a handler sees exactly React's surface and nothing more.
|
|
107
|
+
*
|
|
108
|
+
* `preventDefault` and `stopPropagation` forward to the native event, so they
|
|
109
|
+
* behave as through React; `stopPropagation` also flags the walk through block
|
|
110
|
+
* ancestors to stop. `target` is the editable inside the block rather than the
|
|
111
|
+
* real target (the editing host above it), and `currentTarget` is reassigned as
|
|
112
|
+
* the event bubbles from block to block.
|
|
113
|
+
*
|
|
114
|
+
* @param {Event} nativeEvent The event to wrap.
|
|
115
|
+
* @param {HTMLElement} target The element to report as the target.
|
|
116
|
+
*
|
|
117
|
+
* @return {Object} The synthetic event.
|
|
118
|
+
*/
|
|
119
|
+
function createBlockSyntheticEvent( nativeEvent, target ) {
|
|
120
|
+
let propagationStopped = false;
|
|
121
|
+
|
|
122
|
+
const syntheticEvent = {
|
|
123
|
+
nativeEvent,
|
|
124
|
+
type: nativeEvent.type,
|
|
125
|
+
target,
|
|
126
|
+
currentTarget: null,
|
|
127
|
+
preventDefault() {
|
|
128
|
+
nativeEvent.preventDefault();
|
|
129
|
+
syntheticEvent.defaultPrevented = true;
|
|
130
|
+
},
|
|
131
|
+
isDefaultPrevented() {
|
|
132
|
+
return syntheticEvent.defaultPrevented;
|
|
133
|
+
},
|
|
134
|
+
stopPropagation() {
|
|
135
|
+
nativeEvent.stopPropagation();
|
|
136
|
+
propagationStopped = true;
|
|
137
|
+
},
|
|
138
|
+
isPropagationStopped() {
|
|
139
|
+
return propagationStopped;
|
|
140
|
+
},
|
|
141
|
+
// The modern event system doesn't pool, so persistence is a no-op.
|
|
142
|
+
persist() {},
|
|
143
|
+
isPersistent() {
|
|
144
|
+
return true;
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
for ( const property of EVENT_INTERFACES[ nativeEvent.type ] ) {
|
|
149
|
+
const value = nativeEvent[ property ];
|
|
150
|
+
syntheticEvent[ property ] =
|
|
151
|
+
typeof value === 'function' ? value.bind( nativeEvent ) : value;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return syntheticEvent;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Backwards compatibility for block event handlers under `editableRoot`.
|
|
159
|
+
*
|
|
160
|
+
* When a block supports `editableRoot`, the writing flow wrapper is the
|
|
161
|
+
* contentEditable editing host, so keyboard, input and composition events
|
|
162
|
+
* target the wrapper instead of the block. React `on*` handlers a third party
|
|
163
|
+
* added to a block through `wrapperProps` (e.g. via an `editor.BlockListBlock`
|
|
164
|
+
* filter) are on the block element, below the target, so they stop firing.
|
|
165
|
+
*
|
|
166
|
+
* The block registers those handlers (see `useBlockProps`), and this hook
|
|
167
|
+
* calls them from the host: it resolves the block that owns the selection and
|
|
168
|
+
* every block ancestor, and invokes each registered handler with a synthetic
|
|
169
|
+
* event, innermost first, like a bubbling event. The listeners are attached
|
|
170
|
+
* where React attaches its own (the portal container, the iframe's document
|
|
171
|
+
* element), so a block's handler runs and its `preventDefault` /
|
|
172
|
+
* `stopPropagation` behave as they would through React, without editableRoot.
|
|
173
|
+
*
|
|
174
|
+
* This does not cover handlers a filter puts on its own wrapping element rather
|
|
175
|
+
* than the block's `wrapperProps`; the block element is the supported event
|
|
176
|
+
* surface. It can be removed once input handling is lifted to the host.
|
|
177
|
+
*/
|
|
178
|
+
export default function useEditableRootEventHandlers() {
|
|
179
|
+
const { hasMultiSelection, getBlockParents } =
|
|
180
|
+
useSelect( blockEditorStore );
|
|
181
|
+
const { refsMap, eventHandlers } = useContext( BlockRefs );
|
|
182
|
+
return useRefEffect(
|
|
183
|
+
( node ) => {
|
|
184
|
+
function onEvent( event ) {
|
|
185
|
+
// Only act on real events targeting the host itself, while it
|
|
186
|
+
// is the editing host for a single block and some block has a
|
|
187
|
+
// handler to call.
|
|
188
|
+
if (
|
|
189
|
+
! eventHandlers.size ||
|
|
190
|
+
event.target !== node ||
|
|
191
|
+
! event.isTrusted ||
|
|
192
|
+
node.contentEditable !== 'true' ||
|
|
193
|
+
hasMultiSelection()
|
|
194
|
+
) {
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const selection = node.ownerDocument.defaultView.getSelection();
|
|
199
|
+
|
|
200
|
+
if ( ! selection.rangeCount ) {
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const editable = getSelectionEditableElement( selection, node );
|
|
205
|
+
const clientId = getBlockClientId( editable );
|
|
206
|
+
|
|
207
|
+
if ( ! clientId ) {
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Call the handler on the block that owns the selection and each
|
|
212
|
+
// of its block ancestors, innermost first, like a bubbling
|
|
213
|
+
// event. The hierarchy comes from the store rather than the DOM,
|
|
214
|
+
// and one synthetic event, wrapping the real event, is reused
|
|
215
|
+
// for the whole chain, its currentTarget moved from block to
|
|
216
|
+
// block. The element is only resolved for blocks with a handler.
|
|
217
|
+
const clientIds = [
|
|
218
|
+
clientId,
|
|
219
|
+
...getBlockParents( clientId, true ),
|
|
220
|
+
];
|
|
221
|
+
|
|
222
|
+
let syntheticEvent;
|
|
223
|
+
for ( const ancestorClientId of clientIds ) {
|
|
224
|
+
const handler =
|
|
225
|
+
eventHandlers.get( ancestorClientId )?.current?.[
|
|
226
|
+
event.type
|
|
227
|
+
];
|
|
228
|
+
const element = handler && refsMap.get( ancestorClientId );
|
|
229
|
+
|
|
230
|
+
if ( ! element ) {
|
|
231
|
+
continue;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
if ( ! syntheticEvent ) {
|
|
235
|
+
syntheticEvent = createBlockSyntheticEvent(
|
|
236
|
+
event,
|
|
237
|
+
editable
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
syntheticEvent.currentTarget = element;
|
|
242
|
+
handler( syntheticEvent );
|
|
243
|
+
|
|
244
|
+
if ( syntheticEvent.isPropagationStopped() ) {
|
|
245
|
+
break;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Attach where React attaches its own event system: the portal
|
|
251
|
+
// container, which for the iframed canvas is the document element
|
|
252
|
+
// (see `preparePortalMount` in react-dom). Listening at the same
|
|
253
|
+
// node, non-capture, means a block's handler runs in the bubbling
|
|
254
|
+
// phase after core, and its stopPropagation stops at the same point
|
|
255
|
+
// React's would, as its `on*` handler would without editableRoot.
|
|
256
|
+
const root = node.ownerDocument.documentElement;
|
|
257
|
+
const unsubscribers = EVENT_TYPES.map( ( type ) => {
|
|
258
|
+
root.addEventListener( type, onEvent );
|
|
259
|
+
return () => root.removeEventListener( type, onEvent );
|
|
260
|
+
} );
|
|
261
|
+
return () =>
|
|
262
|
+
unsubscribers.forEach( ( unsubscribe ) => unsubscribe() );
|
|
263
|
+
},
|
|
264
|
+
[ hasMultiSelection, getBlockParents, refsMap, eventHandlers ]
|
|
265
|
+
);
|
|
266
|
+
}
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { useRegistry, useSelect } from '@wordpress/data';
|
|
5
5
|
import { useRefEffect } from '@wordpress/compose';
|
|
6
|
-
import { hasBlockSupport } from '@wordpress/blocks';
|
|
7
6
|
|
|
8
7
|
/**
|
|
9
8
|
* Internal dependencies
|
|
@@ -13,77 +12,6 @@ import { setContentEditableWrapper } from './utils';
|
|
|
13
12
|
import { getBlockClientId, getSelectionEditableElement } from '../../utils/dom';
|
|
14
13
|
import { unlock } from '../../lock-unlock';
|
|
15
14
|
|
|
16
|
-
/**
|
|
17
|
-
* Returns true when the writing flow wrapper can host editing for the given
|
|
18
|
-
* block: it supports `editableRoot`, is edited visually in the default
|
|
19
|
-
* editing mode, and has sibling blocks for a native selection to extend
|
|
20
|
-
* into, all of them editable.
|
|
21
|
-
*
|
|
22
|
-
* @param {Object} select Bound block editor store selectors.
|
|
23
|
-
* @param {string} clientId Block client ID.
|
|
24
|
-
*
|
|
25
|
-
* @return {boolean} Whether an editing host can host the block.
|
|
26
|
-
*/
|
|
27
|
-
export function canHostEditableRoot( select, clientId ) {
|
|
28
|
-
const {
|
|
29
|
-
getBlockName,
|
|
30
|
-
getBlockEditingMode,
|
|
31
|
-
getBlockMode,
|
|
32
|
-
getBlockRootClientId,
|
|
33
|
-
getBlockOrder,
|
|
34
|
-
} = select;
|
|
35
|
-
|
|
36
|
-
if (
|
|
37
|
-
! clientId ||
|
|
38
|
-
getBlockEditingMode( clientId ) !== 'default' ||
|
|
39
|
-
// Not when the block is edited as HTML: there is no rich text to
|
|
40
|
-
// host then, only a textarea, which the editing host would
|
|
41
|
-
// interfere with.
|
|
42
|
-
getBlockMode( clientId ) !== 'visual' ||
|
|
43
|
-
! hasBlockSupport( getBlockName( clientId ), 'editableRoot', false )
|
|
44
|
-
) {
|
|
45
|
-
return false;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// Only host when the block has sibling blocks for a native selection to
|
|
49
|
-
// extend into, all of them editable. A lone block (e.g. a single
|
|
50
|
-
// paragraph nested in an HTML block) is edited on its own element, and
|
|
51
|
-
// read-only siblings (e.g. pattern content without overrides enabled)
|
|
52
|
-
// must not become editable by inheriting from the host.
|
|
53
|
-
const siblings = getBlockOrder( getBlockRootClientId( clientId ) );
|
|
54
|
-
return (
|
|
55
|
-
siblings.length > 1 &&
|
|
56
|
-
siblings.every(
|
|
57
|
-
( siblingClientId ) =>
|
|
58
|
-
getBlockEditingMode( siblingClientId ) === 'default'
|
|
59
|
-
)
|
|
60
|
-
);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Returns true when the writing flow wrapper should be contentEditable: the
|
|
65
|
-
* selected block supports `editableRoot`.
|
|
66
|
-
*
|
|
67
|
-
* @return {boolean} Whether the wrapper should be editable.
|
|
68
|
-
*/
|
|
69
|
-
export function useHasEditableRoot() {
|
|
70
|
-
return useSelect( ( select ) => {
|
|
71
|
-
const selectors = select( blockEditorStore );
|
|
72
|
-
return canHostEditableRoot(
|
|
73
|
-
selectors,
|
|
74
|
-
selectors.getSelectedBlockClientId()
|
|
75
|
-
);
|
|
76
|
-
}, [] );
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Keeps the writing flow wrapper contentEditable while the selected block
|
|
81
|
-
* supports `editableRoot`, so the native selection can extend across blocks.
|
|
82
|
-
* While the wrapper is editable it must also hold focus: a nested editable
|
|
83
|
-
* element cannot retain focus once an ancestor becomes an editing host (the
|
|
84
|
-
* first DOM mutation moves focus to the host, inconsistently across
|
|
85
|
-
* browsers).
|
|
86
|
-
*/
|
|
87
15
|
/**
|
|
88
16
|
* Keeps the writing flow wrapper contentEditable while the selected block
|
|
89
17
|
* supports `editableRoot`, so the native selection can extend across blocks.
|
|
@@ -94,11 +22,13 @@ export function useHasEditableRoot() {
|
|
|
94
22
|
*/
|
|
95
23
|
export default function useEditableRoot() {
|
|
96
24
|
const registry = useRegistry();
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
25
|
+
const enabled = useSelect( ( select ) => {
|
|
26
|
+
const { getSelectedBlockClientId, canHostEditableRoot, isZoomOut } =
|
|
27
|
+
unlock( select( blockEditorStore ) );
|
|
28
|
+
return (
|
|
29
|
+
! isZoomOut() && canHostEditableRoot( getSelectedBlockClientId() )
|
|
30
|
+
);
|
|
31
|
+
}, [] );
|
|
102
32
|
|
|
103
33
|
return useRefEffect(
|
|
104
34
|
( node ) => {
|
|
@@ -12,10 +12,16 @@ import { getSelectionEditableElement } from '../../utils/dom';
|
|
|
12
12
|
import { store as blockEditorStore } from '../../store';
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
15
|
+
* Moves the caret to the start or end of the visual line for Home and End
|
|
16
|
+
* with `Selection.modify()`, because the browser's default caret movement
|
|
17
|
+
* cannot be relied on in two cases:
|
|
18
|
+
*
|
|
19
|
+
* - While the wrapper is the contentEditable editing host (a selected block
|
|
20
|
+
* supports `editableRoot`), browsers don't perform the default caret
|
|
21
|
+
* movement for Home and End.
|
|
22
|
+
* - Chromium on macOS maps Home and End to scroll commands, so it never
|
|
23
|
+
* moves the caret in editable content on that platform, including nested
|
|
24
|
+
* editable elements like the tab labels in the tab-list block.
|
|
19
25
|
*/
|
|
20
26
|
export default function useHomeEnd() {
|
|
21
27
|
const { hasMultiSelection } = useSelect( blockEditorStore );
|
|
@@ -33,11 +39,13 @@ export default function useHomeEnd() {
|
|
|
33
39
|
return;
|
|
34
40
|
}
|
|
35
41
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
42
|
+
// Only handle keys pressed in editable content, in both of the
|
|
43
|
+
// cases mentioned above: `event.target` is the focused element,
|
|
44
|
+
// and `isContentEditable` is true both for the wrapper as the
|
|
45
|
+
// editing host and for a nested editable element like a tab label.
|
|
46
|
+
// Anything else that takes focus like inputs and textareas keep
|
|
47
|
+
// default behavior.
|
|
48
|
+
if ( ! event.target.isContentEditable || hasMultiSelection() ) {
|
|
41
49
|
return;
|
|
42
50
|
}
|
|
43
51
|
|
|
@@ -14,8 +14,7 @@ import { isSelectionForward } from '@wordpress/dom';
|
|
|
14
14
|
*/
|
|
15
15
|
import { store as blockEditorStore } from '../../store';
|
|
16
16
|
import { getBlockClientId } from '../../utils/dom';
|
|
17
|
-
import {
|
|
18
|
-
import { setContentEditableWrapper, setShiftClickInProgress } from './utils';
|
|
17
|
+
import { setContentEditableWrapper } from './utils';
|
|
19
18
|
import { unlock } from '../../lock-unlock';
|
|
20
19
|
|
|
21
20
|
const { ownsSelection } = unlock( richTextPrivateApis );
|
|
@@ -102,9 +101,13 @@ function getRichTextElement( node ) {
|
|
|
102
101
|
* Sets a multi-selection based on the native selection across blocks.
|
|
103
102
|
*/
|
|
104
103
|
export default function useSelectionObserver() {
|
|
105
|
-
const {
|
|
106
|
-
|
|
107
|
-
|
|
104
|
+
const {
|
|
105
|
+
multiSelect,
|
|
106
|
+
selectBlock,
|
|
107
|
+
selectionChange,
|
|
108
|
+
startMultiSelect,
|
|
109
|
+
stopMultiSelect,
|
|
110
|
+
} = useDispatch( blockEditorStore );
|
|
108
111
|
const {
|
|
109
112
|
getBlockParents,
|
|
110
113
|
getBlockSelectionStart,
|
|
@@ -112,7 +115,8 @@ export default function useSelectionObserver() {
|
|
|
112
115
|
getSelectionStart,
|
|
113
116
|
getSelectionEnd,
|
|
114
117
|
getSelectedBlockClientId,
|
|
115
|
-
|
|
118
|
+
canHostEditableRoot,
|
|
119
|
+
} = unlock( useSelect( blockEditorStore ) );
|
|
116
120
|
return useRefEffect(
|
|
117
121
|
( node ) => {
|
|
118
122
|
const { ownerDocument } = node;
|
|
@@ -122,12 +126,18 @@ export default function useSelectionObserver() {
|
|
|
122
126
|
|
|
123
127
|
function onMouseDown( event ) {
|
|
124
128
|
isTripleClick = event.detail === 3;
|
|
125
|
-
|
|
129
|
+
// A shift+click makes a multi-selection: mark the gesture as
|
|
130
|
+
// in progress so the clicked block's focus handler does not
|
|
131
|
+
// select it (collapsing the native range being made), and so
|
|
132
|
+
// use-multi-selection does not clear the native selection.
|
|
133
|
+
// The selection is built on mouseup.
|
|
134
|
+
if ( event.shiftKey ) {
|
|
135
|
+
startMultiSelect();
|
|
136
|
+
}
|
|
126
137
|
}
|
|
127
138
|
|
|
128
139
|
function onKeyDown() {
|
|
129
140
|
isTripleClick = false;
|
|
130
|
-
setShiftClickInProgress( false );
|
|
131
141
|
}
|
|
132
142
|
|
|
133
143
|
function onSelectionChange( event ) {
|
|
@@ -174,10 +184,7 @@ export default function useSelectionObserver() {
|
|
|
174
184
|
// always move it), which must not re-enable the wrapper
|
|
175
185
|
// after another block has been selected.
|
|
176
186
|
collapsedClientId === getSelectedBlockClientId() &&
|
|
177
|
-
canHostEditableRoot(
|
|
178
|
-
blockEditorSelectors,
|
|
179
|
-
collapsedClientId
|
|
180
|
-
)
|
|
187
|
+
canHostEditableRoot( collapsedClientId )
|
|
181
188
|
) {
|
|
182
189
|
setContentEditableWrapper( node, true );
|
|
183
190
|
|
|
@@ -362,9 +369,19 @@ export default function useSelectionObserver() {
|
|
|
362
369
|
];
|
|
363
370
|
const depth = findDepth( startPath, endPath );
|
|
364
371
|
|
|
372
|
+
// If one path ends before they diverge, one block
|
|
373
|
+
// contains the other, so there are no sibling blocks
|
|
374
|
+
// to promote the selection to. Record the selection as
|
|
375
|
+
// is: it resolves to the outer block, which is treated
|
|
376
|
+
// as fully selected. See `getSelectionNestingAncestor`
|
|
377
|
+
// in the store.
|
|
378
|
+
const isAncestorDescendant =
|
|
379
|
+
depth >= startPath.length || depth >= endPath.length;
|
|
380
|
+
|
|
365
381
|
if (
|
|
366
|
-
|
|
367
|
-
|
|
382
|
+
! isAncestorDescendant &&
|
|
383
|
+
( startPath[ depth ] !== startClientId ||
|
|
384
|
+
endPath[ depth ] !== endClientId )
|
|
368
385
|
) {
|
|
369
386
|
multiSelect( startPath[ depth ], endPath[ depth ] );
|
|
370
387
|
return;
|
|
@@ -444,7 +461,7 @@ export default function useSelectionObserver() {
|
|
|
444
461
|
);
|
|
445
462
|
function onMouseUp( event ) {
|
|
446
463
|
onSelectionChange( event );
|
|
447
|
-
|
|
464
|
+
stopMultiSelect();
|
|
448
465
|
}
|
|
449
466
|
|
|
450
467
|
defaultView.addEventListener( 'mouseup', onMouseUp );
|
|
@@ -118,29 +118,6 @@ function toPlainText( html ) {
|
|
|
118
118
|
return plainText.replace( /\n\n+/g, '\n\n' );
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
-
let shiftClickInProgress = false;
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Tracks whether a shift+click gesture is in progress, from the shift held
|
|
125
|
-
* mousedown until its mouseup. Maintained by the selection observer; read by
|
|
126
|
-
* the block focus handler, since the focus event fired between the two
|
|
127
|
-
* carries no modifier keys.
|
|
128
|
-
*
|
|
129
|
-
* @param {boolean} value Whether a shift+click gesture is in progress.
|
|
130
|
-
*/
|
|
131
|
-
export function setShiftClickInProgress( value ) {
|
|
132
|
-
shiftClickInProgress = value;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* Returns whether a shift+click gesture is in progress.
|
|
137
|
-
*
|
|
138
|
-
* @return {boolean} Whether a shift+click gesture is in progress.
|
|
139
|
-
*/
|
|
140
|
-
export function isShiftClickInProgress() {
|
|
141
|
-
return shiftClickInProgress;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
121
|
/**
|
|
145
122
|
* Makes the wrapper element an editing host, or stops it from being one. The
|
|
146
123
|
* ARIA attributes travel with the editability: while the wrapper is the
|
|
@@ -194,7 +171,9 @@ export function setContentEditableWrapper(
|
|
|
194
171
|
node.setAttribute( 'aria-label', __( 'Editor canvas' ) );
|
|
195
172
|
|
|
196
173
|
if ( focus ) {
|
|
197
|
-
|
|
174
|
+
// Without preventScroll, focusing the wrapper scrolls the
|
|
175
|
+
// viewport to the top of the wrapper.
|
|
176
|
+
node.focus( { preventScroll: true } );
|
|
198
177
|
}
|
|
199
178
|
|
|
200
179
|
return true;
|