@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
|
@@ -0,0 +1,456 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regression coverage for preset round-trip and explicit-empty behavior.
|
|
3
|
+
*
|
|
4
|
+
* The tests verify that supported preset domains decode each serialization
|
|
5
|
+
* form to the same display value, encode resolved overrides back to canonical
|
|
6
|
+
* preset references, clear the relevant reset surfaces, and treat explicit
|
|
7
|
+
* empty values as non-contributing layers.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Internal dependencies
|
|
12
|
+
*/
|
|
13
|
+
import {
|
|
14
|
+
getValueFromVariable,
|
|
15
|
+
getPresetVariableFromValue,
|
|
16
|
+
} from '@wordpress/global-styles-engine';
|
|
17
|
+
|
|
18
|
+
import {
|
|
19
|
+
getCustomValueFromPreset as getCustomSpacingValue,
|
|
20
|
+
getPresetValueFromCustomValue as getSpacingPresetFromCustom,
|
|
21
|
+
isValueSpacingPreset,
|
|
22
|
+
} from '../../components/spacing-sizes-control/utils';
|
|
23
|
+
|
|
24
|
+
import {
|
|
25
|
+
getCustomValueFromPreset,
|
|
26
|
+
getPresetValueFromCustomValue,
|
|
27
|
+
isValuePreset,
|
|
28
|
+
} from '../../components/preset-input-control/utils';
|
|
29
|
+
|
|
30
|
+
// Border-radius equivalents of the spacing helpers above. The per-domain
|
|
31
|
+
// implementations were consolidated into the generic preset-input-control
|
|
32
|
+
// helpers, which take the preset type as an extra argument.
|
|
33
|
+
const BORDER_RADIUS_PRESET_TYPE = 'border-radius';
|
|
34
|
+
const getCustomRadiusValue = ( value, presets ) =>
|
|
35
|
+
getCustomValueFromPreset( value, presets, BORDER_RADIUS_PRESET_TYPE );
|
|
36
|
+
const getRadiusPresetFromCustom = ( value, presets ) =>
|
|
37
|
+
getPresetValueFromCustomValue( value, presets, BORDER_RADIUS_PRESET_TYPE );
|
|
38
|
+
const isValueRadiusPreset = ( value ) =>
|
|
39
|
+
isValuePreset( value, BORDER_RADIUS_PRESET_TYPE );
|
|
40
|
+
|
|
41
|
+
// Fixture: a minimal merged GlobalStylesConfig sized just large enough
|
|
42
|
+
// to exercise every (form × domain) cell. Mirrors the two-branch shape
|
|
43
|
+
// real Global Styles payloads use ({ settings, styles }).
|
|
44
|
+
//
|
|
45
|
+
// Note on preset shape: `findInPresetsBy()` (engine-internal) iterates
|
|
46
|
+
// presets by origin in priority order [ 'custom', 'theme', 'default' ].
|
|
47
|
+
// A flat array does NOT match. Real GS payloads are origin-keyed; the
|
|
48
|
+
// fixture mirrors that exactly. The per-domain block-editor helpers
|
|
49
|
+
// (spacing-sizes-control, preset-input-control) take the FLAT preset
|
|
50
|
+
// list, so we keep both shapes (RAW_PRESETS for the helpers,
|
|
51
|
+
// origin-keyed wrappers for the engine).
|
|
52
|
+
const RAW_PRESETS = {
|
|
53
|
+
color: [
|
|
54
|
+
{ slug: 'vivid-red', color: '#cf2e2e', name: 'Vivid red' },
|
|
55
|
+
{ slug: 'pale-blue', color: '#a5e3ff', name: 'Pale blue' },
|
|
56
|
+
],
|
|
57
|
+
fontSizes: [
|
|
58
|
+
{ slug: 'large', size: '24px', name: 'Large' },
|
|
59
|
+
{ slug: 'small', size: '14px', name: 'Small' },
|
|
60
|
+
],
|
|
61
|
+
spacingSizes: [
|
|
62
|
+
{ slug: '40', size: '32px', name: 'Large' },
|
|
63
|
+
{ slug: '20', size: '8px', name: 'Small' },
|
|
64
|
+
],
|
|
65
|
+
radiusSizes: [
|
|
66
|
+
{ slug: 'rounded', size: '8px', name: 'Rounded' },
|
|
67
|
+
{ slug: 'pill', size: '999px', name: 'Pill' },
|
|
68
|
+
],
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const FEATURES = {
|
|
72
|
+
settings: {
|
|
73
|
+
color: {
|
|
74
|
+
palette: { theme: RAW_PRESETS.color },
|
|
75
|
+
},
|
|
76
|
+
typography: {
|
|
77
|
+
fontSizes: { theme: RAW_PRESETS.fontSizes },
|
|
78
|
+
},
|
|
79
|
+
spacing: {
|
|
80
|
+
spacingSizes: { theme: RAW_PRESETS.spacingSizes },
|
|
81
|
+
},
|
|
82
|
+
border: {
|
|
83
|
+
radiusSizes: { theme: RAW_PRESETS.radiusSizes },
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
styles: {
|
|
87
|
+
// Targets for the `{ ref }` decode leg.
|
|
88
|
+
color: {
|
|
89
|
+
text: '#cf2e2e',
|
|
90
|
+
background: '#a5e3ff',
|
|
91
|
+
},
|
|
92
|
+
typography: {
|
|
93
|
+
fontSize: '24px',
|
|
94
|
+
},
|
|
95
|
+
spacing: {
|
|
96
|
+
padding: { top: '32px' },
|
|
97
|
+
},
|
|
98
|
+
border: {
|
|
99
|
+
radius: '8px',
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
const PRESETS = {
|
|
105
|
+
spacing: RAW_PRESETS.spacingSizes,
|
|
106
|
+
'border-radius': RAW_PRESETS.radiusSizes,
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Simulate the panel's "reset all" path against a block's attributes.
|
|
111
|
+
* Returns a new attributes object with every reset surface cleared for
|
|
112
|
+
* the given style path. The reset surfaces are:
|
|
113
|
+
*
|
|
114
|
+
* 1. The per-domain slug attribute (e.g. attributes.textColor, .fontSize)
|
|
115
|
+
* 2. The serialized style-path var (e.g. attributes.style.color.text)
|
|
116
|
+
*
|
|
117
|
+
* The auto-generated CSS class (e.g. `has-vivid-red-color`) is derived
|
|
118
|
+
* from (1) at save() time, so clearing (1) clears the class downstream —
|
|
119
|
+
* verified indirectly by asserting (1) is undefined after reset.
|
|
120
|
+
*
|
|
121
|
+
* @param {Object} attributes Block attributes object.
|
|
122
|
+
* @param {?string} slugAttrName Per-domain slug attribute key, or null.
|
|
123
|
+
* @param {string} stylePath Dotted style sub-path to clear.
|
|
124
|
+
* @return {Object} New attributes with the reset surfaces cleared.
|
|
125
|
+
*/
|
|
126
|
+
function simulateResetAll( attributes, slugAttrName, stylePath ) {
|
|
127
|
+
const next = { ...attributes };
|
|
128
|
+
if ( slugAttrName ) {
|
|
129
|
+
next[ slugAttrName ] = undefined;
|
|
130
|
+
}
|
|
131
|
+
if ( stylePath ) {
|
|
132
|
+
const segments = stylePath.split( '.' );
|
|
133
|
+
next.style = JSON.parse( JSON.stringify( next.style || {} ) );
|
|
134
|
+
let node = next.style;
|
|
135
|
+
for ( let i = 0; i < segments.length - 1; i++ ) {
|
|
136
|
+
if ( ! node[ segments[ i ] ] ) {
|
|
137
|
+
return next;
|
|
138
|
+
}
|
|
139
|
+
node = node[ segments[ i ] ];
|
|
140
|
+
}
|
|
141
|
+
node[ segments[ segments.length - 1 ] ] = undefined;
|
|
142
|
+
}
|
|
143
|
+
return next;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// ---------------------------------------------------------------------------
|
|
147
|
+
// COLOR — has STYLE_PATH_TO_CSS_VAR_INFIX entry → uses GS engine helpers.
|
|
148
|
+
// ---------------------------------------------------------------------------
|
|
149
|
+
describe( 'color preset round-trip', () => {
|
|
150
|
+
const stylePath = 'color.text';
|
|
151
|
+
const slugAttr = 'textColor';
|
|
152
|
+
const expectedResolved = '#cf2e2e';
|
|
153
|
+
const expectedPresetVar = 'var:preset|color|vivid-red';
|
|
154
|
+
|
|
155
|
+
it.each( [
|
|
156
|
+
[ 'var:preset|<infix>|<slug>', 'var:preset|color|vivid-red' ],
|
|
157
|
+
[
|
|
158
|
+
'var(--wp--preset--<infix>--<slug>)',
|
|
159
|
+
'var(--wp--preset--color--vivid-red)',
|
|
160
|
+
],
|
|
161
|
+
[ 'raw resolved', '#cf2e2e' ],
|
|
162
|
+
[ '{ ref }', { ref: 'styles.color.text' } ],
|
|
163
|
+
] )( 'decodes [%s] for display', ( _label, input ) => {
|
|
164
|
+
const decoded = getValueFromVariable( FEATURES, undefined, input );
|
|
165
|
+
expect( decoded ).toBe( expectedResolved );
|
|
166
|
+
} );
|
|
167
|
+
|
|
168
|
+
it( 'encodes a resolved override back to var:preset|color|<slug>', () => {
|
|
169
|
+
const encoded = getPresetVariableFromValue(
|
|
170
|
+
FEATURES.settings,
|
|
171
|
+
undefined,
|
|
172
|
+
stylePath,
|
|
173
|
+
expectedResolved
|
|
174
|
+
);
|
|
175
|
+
expect( encoded ).toBe( expectedPresetVar );
|
|
176
|
+
} );
|
|
177
|
+
|
|
178
|
+
it( 'encodes a non-preset color through unchanged (custom value)', () => {
|
|
179
|
+
const encoded = getPresetVariableFromValue(
|
|
180
|
+
FEATURES.settings,
|
|
181
|
+
undefined,
|
|
182
|
+
stylePath,
|
|
183
|
+
'#000000'
|
|
184
|
+
);
|
|
185
|
+
expect( encoded ).toBe( '#000000' );
|
|
186
|
+
} );
|
|
187
|
+
|
|
188
|
+
it( 'full-reset clears slug attribute + style path', () => {
|
|
189
|
+
const before = {
|
|
190
|
+
textColor: 'vivid-red',
|
|
191
|
+
style: { color: { text: 'var:preset|color|vivid-red' } },
|
|
192
|
+
};
|
|
193
|
+
const after = simulateResetAll( before, slugAttr, stylePath );
|
|
194
|
+
expect( after.textColor ).toBeUndefined();
|
|
195
|
+
expect( after.style.color.text ).toBeUndefined();
|
|
196
|
+
} );
|
|
197
|
+
} );
|
|
198
|
+
|
|
199
|
+
// ---------------------------------------------------------------------------
|
|
200
|
+
// FONT-SIZE — has STYLE_PATH_TO_CSS_VAR_INFIX entry; valueFunc may run
|
|
201
|
+
// getTypographyFontSizeValue but here our preset already has a plain `size`.
|
|
202
|
+
// ---------------------------------------------------------------------------
|
|
203
|
+
describe( 'font-size preset round-trip', () => {
|
|
204
|
+
const stylePath = 'typography.fontSize';
|
|
205
|
+
const slugAttr = 'fontSize';
|
|
206
|
+
const expectedResolved = '24px';
|
|
207
|
+
const expectedPresetVar = 'var:preset|font-size|large';
|
|
208
|
+
|
|
209
|
+
it.each( [
|
|
210
|
+
[ 'var:preset|<infix>|<slug>', 'var:preset|font-size|large' ],
|
|
211
|
+
[
|
|
212
|
+
'var(--wp--preset--<infix>--<slug>)',
|
|
213
|
+
'var(--wp--preset--font-size--large)',
|
|
214
|
+
],
|
|
215
|
+
[ 'raw resolved', '24px' ],
|
|
216
|
+
[ '{ ref }', { ref: 'styles.typography.fontSize' } ],
|
|
217
|
+
] )( 'decodes [%s] for display', ( _label, input ) => {
|
|
218
|
+
const decoded = getValueFromVariable( FEATURES, undefined, input );
|
|
219
|
+
expect( decoded ).toBe( expectedResolved );
|
|
220
|
+
} );
|
|
221
|
+
|
|
222
|
+
it( 'encodes a resolved override back to var:preset|font-size|<slug>', () => {
|
|
223
|
+
const encoded = getPresetVariableFromValue(
|
|
224
|
+
FEATURES.settings,
|
|
225
|
+
undefined,
|
|
226
|
+
stylePath,
|
|
227
|
+
expectedResolved
|
|
228
|
+
);
|
|
229
|
+
expect( encoded ).toBe( expectedPresetVar );
|
|
230
|
+
} );
|
|
231
|
+
|
|
232
|
+
it( 'encodes a non-preset size through unchanged (custom value)', () => {
|
|
233
|
+
const encoded = getPresetVariableFromValue(
|
|
234
|
+
FEATURES.settings,
|
|
235
|
+
undefined,
|
|
236
|
+
stylePath,
|
|
237
|
+
'19px'
|
|
238
|
+
);
|
|
239
|
+
expect( encoded ).toBe( '19px' );
|
|
240
|
+
} );
|
|
241
|
+
|
|
242
|
+
it( 'full-reset clears slug attribute + style path', () => {
|
|
243
|
+
const before = {
|
|
244
|
+
fontSize: 'large',
|
|
245
|
+
style: { typography: { fontSize: 'var:preset|font-size|large' } },
|
|
246
|
+
};
|
|
247
|
+
const after = simulateResetAll( before, slugAttr, stylePath );
|
|
248
|
+
expect( after.fontSize ).toBeUndefined();
|
|
249
|
+
expect( after.style.typography.fontSize ).toBeUndefined();
|
|
250
|
+
} );
|
|
251
|
+
} );
|
|
252
|
+
|
|
253
|
+
// ---------------------------------------------------------------------------
|
|
254
|
+
// SPACING — NOT in STYLE_PATH_TO_CSS_VAR_INFIX. Uses the per-domain
|
|
255
|
+
// helpers in spacing-sizes-control/utils.js, keyed against spacingSizes
|
|
256
|
+
// presets. No slug attribute exists; spacing lives only in
|
|
257
|
+
// style.spacing.*.
|
|
258
|
+
// ---------------------------------------------------------------------------
|
|
259
|
+
describe( 'spacing preset round-trip', () => {
|
|
260
|
+
const stylePath = 'spacing.padding.top';
|
|
261
|
+
const slugAttr = null; // no slug-attribute leg for spacing
|
|
262
|
+
const expectedResolved = '32px';
|
|
263
|
+
const expectedPresetVar = 'var:preset|spacing|40';
|
|
264
|
+
const presets = PRESETS.spacing;
|
|
265
|
+
|
|
266
|
+
// Decode leg.
|
|
267
|
+
it( 'decodes var:preset|spacing|<slug> via getCustomValueFromPreset', () => {
|
|
268
|
+
expect( getCustomSpacingValue( expectedPresetVar, presets ) ).toBe(
|
|
269
|
+
expectedResolved
|
|
270
|
+
);
|
|
271
|
+
} );
|
|
272
|
+
|
|
273
|
+
it( 'decodes var(--wp--preset--spacing--<slug>) via getValueFromVariable', () => {
|
|
274
|
+
// The block-editor spacing helper is regex-based and only
|
|
275
|
+
// matches `var:preset|…` form. The engine's
|
|
276
|
+
// `getValueFromVariable` handles the CSS-custom-property form
|
|
277
|
+
// via the same PRESET_METADATA. Both paths must reach the same
|
|
278
|
+
// display value or the panel has to choose one.
|
|
279
|
+
const decoded = getValueFromVariable(
|
|
280
|
+
FEATURES,
|
|
281
|
+
undefined,
|
|
282
|
+
'var(--wp--preset--spacing--40)'
|
|
283
|
+
);
|
|
284
|
+
expect( decoded ).toBe( expectedResolved );
|
|
285
|
+
} );
|
|
286
|
+
|
|
287
|
+
it( 'decodes raw resolved value as-is (passthrough)', () => {
|
|
288
|
+
expect( getCustomSpacingValue( '32px', presets ) ).toBe( '32px' );
|
|
289
|
+
} );
|
|
290
|
+
|
|
291
|
+
it( 'decodes { ref: … } via getValueFromVariable', () => {
|
|
292
|
+
const decoded = getValueFromVariable( FEATURES, undefined, {
|
|
293
|
+
ref: 'styles.spacing.padding.top',
|
|
294
|
+
} );
|
|
295
|
+
expect( decoded ).toBe( expectedResolved );
|
|
296
|
+
} );
|
|
297
|
+
|
|
298
|
+
// Encode leg.
|
|
299
|
+
it( 'encodes a resolved override back to var:preset|spacing|<slug>', () => {
|
|
300
|
+
expect( getSpacingPresetFromCustom( expectedResolved, presets ) ).toBe(
|
|
301
|
+
expectedPresetVar
|
|
302
|
+
);
|
|
303
|
+
} );
|
|
304
|
+
|
|
305
|
+
it( 'encodes a non-preset value through unchanged (custom value)', () => {
|
|
306
|
+
expect( getSpacingPresetFromCustom( '17px', presets ) ).toBe( '17px' );
|
|
307
|
+
} );
|
|
308
|
+
|
|
309
|
+
// Reset leg.
|
|
310
|
+
it( 'full-reset clears style.spacing.padding.top (no slug attribute)', () => {
|
|
311
|
+
const before = {
|
|
312
|
+
style: { spacing: { padding: { top: 'var:preset|spacing|40' } } },
|
|
313
|
+
};
|
|
314
|
+
const after = simulateResetAll( before, slugAttr, stylePath );
|
|
315
|
+
expect( after.style.spacing.padding.top ).toBeUndefined();
|
|
316
|
+
} );
|
|
317
|
+
|
|
318
|
+
it( 'isValueSpacingPreset recognises the canonical form', () => {
|
|
319
|
+
expect( isValueSpacingPreset( expectedPresetVar ) ).toBe( true );
|
|
320
|
+
expect( isValueSpacingPreset( '32px' ) ).toBe( false );
|
|
321
|
+
} );
|
|
322
|
+
} );
|
|
323
|
+
|
|
324
|
+
// ---------------------------------------------------------------------------
|
|
325
|
+
// BORDER-RADIUS — NOT in STYLE_PATH_TO_CSS_VAR_INFIX. Uses the generic
|
|
326
|
+
// helpers in preset-input-control/utils.js with the 'border-radius' preset
|
|
327
|
+
// type. No slug attribute exists; border-radius lives only in
|
|
328
|
+
// style.border.radius.
|
|
329
|
+
// ---------------------------------------------------------------------------
|
|
330
|
+
describe( 'border-radius preset round-trip', () => {
|
|
331
|
+
const stylePath = 'border.radius';
|
|
332
|
+
const slugAttr = null;
|
|
333
|
+
const expectedResolved = '8px';
|
|
334
|
+
const expectedPresetVar = 'var:preset|border-radius|rounded';
|
|
335
|
+
const presets = PRESETS[ 'border-radius' ];
|
|
336
|
+
|
|
337
|
+
// Decode leg.
|
|
338
|
+
it( 'decodes var:preset|border-radius|<slug> via getCustomValueFromPreset', () => {
|
|
339
|
+
expect( getCustomRadiusValue( expectedPresetVar, presets ) ).toBe(
|
|
340
|
+
expectedResolved
|
|
341
|
+
);
|
|
342
|
+
} );
|
|
343
|
+
|
|
344
|
+
it( 'decodes var(--wp--preset--border-radius--<slug>) via getValueFromVariable', () => {
|
|
345
|
+
const decoded = getValueFromVariable(
|
|
346
|
+
FEATURES,
|
|
347
|
+
undefined,
|
|
348
|
+
'var(--wp--preset--border-radius--rounded)'
|
|
349
|
+
);
|
|
350
|
+
expect( decoded ).toBe( expectedResolved );
|
|
351
|
+
} );
|
|
352
|
+
|
|
353
|
+
it( 'decodes raw resolved value as-is (passthrough)', () => {
|
|
354
|
+
expect( getCustomRadiusValue( '8px', presets ) ).toBe( '8px' );
|
|
355
|
+
} );
|
|
356
|
+
|
|
357
|
+
it( 'decodes { ref: … } via getValueFromVariable', () => {
|
|
358
|
+
const decoded = getValueFromVariable( FEATURES, undefined, {
|
|
359
|
+
ref: 'styles.border.radius',
|
|
360
|
+
} );
|
|
361
|
+
expect( decoded ).toBe( expectedResolved );
|
|
362
|
+
} );
|
|
363
|
+
|
|
364
|
+
// Encode leg.
|
|
365
|
+
it( 'encodes a resolved override back to var:preset|border-radius|<slug>', () => {
|
|
366
|
+
expect( getRadiusPresetFromCustom( expectedResolved, presets ) ).toBe(
|
|
367
|
+
expectedPresetVar
|
|
368
|
+
);
|
|
369
|
+
} );
|
|
370
|
+
|
|
371
|
+
it( 'encodes a non-preset value through unchanged (custom value)', () => {
|
|
372
|
+
expect( getRadiusPresetFromCustom( '12px', presets ) ).toBe( '12px' );
|
|
373
|
+
} );
|
|
374
|
+
|
|
375
|
+
// Reset leg.
|
|
376
|
+
it( 'full-reset clears style.border.radius (no slug attribute)', () => {
|
|
377
|
+
const before = {
|
|
378
|
+
style: {
|
|
379
|
+
border: { radius: 'var:preset|border-radius|rounded' },
|
|
380
|
+
},
|
|
381
|
+
};
|
|
382
|
+
const after = simulateResetAll( before, slugAttr, stylePath );
|
|
383
|
+
expect( after.style.border.radius ).toBeUndefined();
|
|
384
|
+
} );
|
|
385
|
+
|
|
386
|
+
it( 'isValuePreset recognises the canonical form', () => {
|
|
387
|
+
expect( isValueRadiusPreset( expectedPresetVar ) ).toBe( true );
|
|
388
|
+
expect( isValueRadiusPreset( '8px' ) ).toBe( false );
|
|
389
|
+
} );
|
|
390
|
+
} );
|
|
391
|
+
|
|
392
|
+
// ---------------------------------------------------------------------------
|
|
393
|
+
// Explicit-empty handling per domain.
|
|
394
|
+
//
|
|
395
|
+
// Empty leaves must be treated as non-contributing layers so controls can
|
|
396
|
+
// fall back to the next layer instead of rendering an empty placeholder.
|
|
397
|
+
// ---------------------------------------------------------------------------
|
|
398
|
+
describe( 'explicit-empty handling per domain', () => {
|
|
399
|
+
// Reproduce `resolveStyle`'s emptiness predicate verbatim.
|
|
400
|
+
function isEmpty( v ) {
|
|
401
|
+
if ( v === '' || v === null || v === undefined ) {
|
|
402
|
+
return true;
|
|
403
|
+
}
|
|
404
|
+
if (
|
|
405
|
+
typeof v === 'object' &&
|
|
406
|
+
! Array.isArray( v ) &&
|
|
407
|
+
Object.keys( v ).length === 0
|
|
408
|
+
) {
|
|
409
|
+
return true;
|
|
410
|
+
}
|
|
411
|
+
return false;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
it.each( [
|
|
415
|
+
[ 'color (text)', '' ],
|
|
416
|
+
[ 'color (text)', null ],
|
|
417
|
+
[ 'color (text)', {} ],
|
|
418
|
+
[ 'font-size', '' ],
|
|
419
|
+
[ 'font-size', null ],
|
|
420
|
+
[ 'font-size', {} ],
|
|
421
|
+
[ 'spacing (padding.top)', '' ],
|
|
422
|
+
[ 'spacing (padding.top)', null ],
|
|
423
|
+
[ 'spacing (padding.top)', {} ],
|
|
424
|
+
[ 'border-radius', '' ],
|
|
425
|
+
[ 'border-radius', null ],
|
|
426
|
+
[ 'border-radius', {} ],
|
|
427
|
+
] )(
|
|
428
|
+
'%s with value %p is recognised as a non-contributing layer',
|
|
429
|
+
( _domain, value ) => {
|
|
430
|
+
expect( isEmpty( value ) ).toBe( true );
|
|
431
|
+
}
|
|
432
|
+
);
|
|
433
|
+
|
|
434
|
+
// Sanity: zero-valued (but meaningful) leaves are NOT empty. A
|
|
435
|
+
// spacing of '0' or a border radius of '0' is a real, contributing
|
|
436
|
+
// value.
|
|
437
|
+
it.each( [
|
|
438
|
+
[ 'color', '#000000' ],
|
|
439
|
+
[ 'font-size', '0px' ],
|
|
440
|
+
[ 'spacing', '0' ],
|
|
441
|
+
[ 'border-radius', '0' ],
|
|
442
|
+
] )(
|
|
443
|
+
'%s with concrete value %p is NOT an empty layer',
|
|
444
|
+
( _domain, value ) => {
|
|
445
|
+
expect( isEmpty( value ) ).toBe( false );
|
|
446
|
+
}
|
|
447
|
+
);
|
|
448
|
+
|
|
449
|
+
// Cross-check against the engine's `getValueFromVariable`: an
|
|
450
|
+
// empty-string input round-trips to itself (the resolver's job is
|
|
451
|
+
// to drop the layer; the engine's job is just to leave non-variables
|
|
452
|
+
// alone).
|
|
453
|
+
it( 'getValueFromVariable returns empty string unchanged (resolver drops the layer downstream)', () => {
|
|
454
|
+
expect( getValueFromVariable( FEATURES, undefined, '' ) ).toBe( '' );
|
|
455
|
+
} );
|
|
456
|
+
} );
|
package/src/hooks/typography.js
CHANGED
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
default as StylesTypographyPanel,
|
|
15
15
|
useHasTypographyPanel,
|
|
16
16
|
} from '../components/global-styles/typography-panel';
|
|
17
|
+
import { useResolvedStyle } from '../components/global-styles/inherited-value-context';
|
|
17
18
|
|
|
18
19
|
import { LINE_HEIGHT_SUPPORT_KEY } from './line-height';
|
|
19
20
|
import { FONT_FAMILY_SUPPORT_KEY } from './font-family';
|
|
@@ -151,32 +152,42 @@ export function TypographyPanel( {
|
|
|
151
152
|
const selectedState = useBlockStyleState();
|
|
152
153
|
const isEnabled = useHasTypographyPanel( settings );
|
|
153
154
|
|
|
154
|
-
const { style, fontFamily, fontSize, fitText, textColor } =
|
|
155
|
-
(
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
155
|
+
const { style, fontFamily, fontSize, fitText, textColor, className } =
|
|
156
|
+
useSelect(
|
|
157
|
+
( select ) => {
|
|
158
|
+
// Early return to avoid subscription when disabled.
|
|
159
|
+
if ( ! isEnabled ) {
|
|
160
|
+
return {};
|
|
161
|
+
}
|
|
162
|
+
const {
|
|
163
|
+
style: _style,
|
|
164
|
+
fontFamily: _fontFamily,
|
|
165
|
+
fontSize: _fontSize,
|
|
166
|
+
fitText: _fitText,
|
|
167
|
+
textColor: _textColor,
|
|
168
|
+
className: _className,
|
|
169
|
+
} = select( blockEditorStore ).getBlockAttributes( clientId ) ||
|
|
170
|
+
{};
|
|
171
|
+
return {
|
|
172
|
+
style: _style,
|
|
173
|
+
fontFamily: _fontFamily,
|
|
174
|
+
fontSize: _fontSize,
|
|
175
|
+
fitText: _fitText,
|
|
176
|
+
textColor: _textColor,
|
|
177
|
+
className: _className,
|
|
178
|
+
};
|
|
179
|
+
},
|
|
180
|
+
[ clientId, isEnabled ]
|
|
181
|
+
);
|
|
177
182
|
|
|
178
183
|
const isStateSelected = ! isDefaultBlockStyleState( selectedState );
|
|
179
184
|
|
|
185
|
+
const { value: inheritedValue } = useResolvedStyle(
|
|
186
|
+
name,
|
|
187
|
+
className,
|
|
188
|
+
selectedState
|
|
189
|
+
);
|
|
190
|
+
|
|
180
191
|
const value = useMemo( () => {
|
|
181
192
|
if ( isStateSelected ) {
|
|
182
193
|
return getStyleForState( style, selectedState );
|
|
@@ -257,6 +268,7 @@ export function TypographyPanel( {
|
|
|
257
268
|
onChange={ onChange }
|
|
258
269
|
defaultControls={ defaultControls }
|
|
259
270
|
contrastWarning={ contrastWarning }
|
|
271
|
+
inheritedValue={ inheritedValue }
|
|
260
272
|
/>
|
|
261
273
|
);
|
|
262
274
|
}
|
package/src/private-apis.js
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WordPress dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { privateApis as globalStylesEnginePrivateApis } from '@wordpress/global-styles-engine';
|
|
5
|
+
|
|
1
6
|
/**
|
|
2
7
|
* Internal dependencies
|
|
3
8
|
*/
|
|
4
9
|
import * as globalStyles from './components/global-styles';
|
|
5
10
|
import { ExperimentalBlockEditorProvider } from './components/provider';
|
|
6
|
-
import { lock } from './lock-unlock';
|
|
11
|
+
import { lock, unlock } from './lock-unlock';
|
|
7
12
|
import { getRichTextValues } from './components/rich-text/get-rich-text-values';
|
|
8
13
|
import ResizableBoxPopover from './components/resizable-box-popover';
|
|
9
14
|
import { default as PrivateQuickInserter } from './components/inserter/quick-inserter';
|
|
@@ -40,7 +45,6 @@ import {
|
|
|
40
45
|
ExperimentalBlockCanvas,
|
|
41
46
|
BlockCanvasCover,
|
|
42
47
|
} from './components/block-canvas';
|
|
43
|
-
import { getDuotoneFilter } from './components/duotone/utils';
|
|
44
48
|
import { useFlashEditableBlocks } from './components/use-flash-editable-blocks';
|
|
45
49
|
import {
|
|
46
50
|
selectBlockPatternsKey,
|
|
@@ -79,11 +83,14 @@ import useRemoteUrlData from './components/link-control/use-rich-url-data';
|
|
|
79
83
|
import { PrivateBlockContext } from './components/block-list/private-block-context';
|
|
80
84
|
import useListViewPanelState from './components/use-list-view-panel-state';
|
|
81
85
|
import InnerContent from './components/inner-content';
|
|
86
|
+
import { useNativeUndo, usesNativeUndo } from './utils/native-undo';
|
|
82
87
|
import {
|
|
83
88
|
isHashLink,
|
|
84
89
|
isRelativePath,
|
|
85
90
|
} from './components/link-control/is-url-like';
|
|
86
91
|
|
|
92
|
+
const { getDuotoneFilter } = unlock( globalStylesEnginePrivateApis );
|
|
93
|
+
|
|
87
94
|
/**
|
|
88
95
|
* Private @wordpress/block-editor APIs.
|
|
89
96
|
*/
|
|
@@ -157,4 +164,6 @@ lock( privateApis, {
|
|
|
157
164
|
isHashLink,
|
|
158
165
|
isRelativePath,
|
|
159
166
|
InnerContent,
|
|
167
|
+
useNativeUndo,
|
|
168
|
+
usesNativeUndo,
|
|
160
169
|
} );
|
package/src/store/actions.js
CHANGED
|
@@ -1253,10 +1253,16 @@ export const mergeBlocks =
|
|
|
1253
1253
|
}
|
|
1254
1254
|
|
|
1255
1255
|
if ( isUnmodifiedDefaultBlock( blockA ) ) {
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1256
|
+
const isASelected = select.isBlockSelected( clientIdA );
|
|
1257
|
+
|
|
1258
|
+
if ( isASelected ) {
|
|
1259
|
+
registry.batch( () => {
|
|
1260
|
+
dispatch.removeBlock( clientIdA, false );
|
|
1261
|
+
dispatch.selectBlock( clientIdB, 0 );
|
|
1262
|
+
} );
|
|
1263
|
+
} else {
|
|
1264
|
+
dispatch.removeBlock( clientIdA, false );
|
|
1265
|
+
}
|
|
1260
1266
|
return;
|
|
1261
1267
|
}
|
|
1262
1268
|
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { createSelector, createRegistrySelector } from '@wordpress/data';
|
|
5
5
|
import {
|
|
6
|
+
getBlockType,
|
|
6
7
|
hasBlockSupport,
|
|
7
8
|
privateApis as blocksPrivateApis,
|
|
8
9
|
} from '@wordpress/blocks';
|
|
@@ -15,6 +16,7 @@ import {
|
|
|
15
16
|
getBlockOrder,
|
|
16
17
|
getBlockParents,
|
|
17
18
|
getBlockEditingMode,
|
|
19
|
+
getBlockMode,
|
|
18
20
|
getBlockListSettings,
|
|
19
21
|
getSettings,
|
|
20
22
|
canInsertBlockType,
|
|
@@ -42,7 +44,7 @@ import {
|
|
|
42
44
|
} from './private-keys';
|
|
43
45
|
import { BLOCK_VISIBILITY_VIEWPORTS } from '../components/block-visibility/constants';
|
|
44
46
|
|
|
45
|
-
const { isContentBlock } = unlock( blocksPrivateApis );
|
|
47
|
+
const { isContentBlock, editableRootKey } = unlock( blocksPrivateApis );
|
|
46
48
|
const { getViewportBreakpoints } = unlock( globalStylesEnginePrivateApis );
|
|
47
49
|
|
|
48
50
|
export { getBlockSettings } from './get-block-settings';
|
|
@@ -243,6 +245,60 @@ function hasExplicitDisabledParent( state, clientId ) {
|
|
|
243
245
|
return false;
|
|
244
246
|
}
|
|
245
247
|
|
|
248
|
+
/**
|
|
249
|
+
* Returns true when the writing flow wrapper can host editing for the given
|
|
250
|
+
* block: it supports `editableRoot`, is edited visually in the default
|
|
251
|
+
* editing mode, and has sibling blocks for a native selection to extend
|
|
252
|
+
* into, all of them editable.
|
|
253
|
+
*
|
|
254
|
+
* @param {Object} state Global application state.
|
|
255
|
+
* @param {string} clientId Block client ID.
|
|
256
|
+
*
|
|
257
|
+
* @return {boolean} Whether an editing host can host the block.
|
|
258
|
+
*/
|
|
259
|
+
export const canHostEditableRoot = createSelector(
|
|
260
|
+
( state, clientId ) => {
|
|
261
|
+
if (
|
|
262
|
+
! clientId ||
|
|
263
|
+
getBlockEditingMode( state, clientId ) !== 'default' ||
|
|
264
|
+
// Not when the block is edited as HTML: there is no rich text to
|
|
265
|
+
// host then, only a textarea, which the editing host would
|
|
266
|
+
// interfere with.
|
|
267
|
+
getBlockMode( state, clientId ) !== 'visual' ||
|
|
268
|
+
! getBlockType( getBlockName( state, clientId ) )?.[
|
|
269
|
+
editableRootKey
|
|
270
|
+
]
|
|
271
|
+
) {
|
|
272
|
+
return false;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// Only host when the block has sibling blocks for a native selection to
|
|
276
|
+
// extend into, all of them editable. A lone block (e.g. a single
|
|
277
|
+
// paragraph nested in an HTML block) is edited on its own element, and
|
|
278
|
+
// read-only siblings (e.g. pattern content without overrides enabled)
|
|
279
|
+
// must not become editable by inheriting from the host.
|
|
280
|
+
const siblings = getBlockOrder(
|
|
281
|
+
state,
|
|
282
|
+
getBlockRootClientId( state, clientId )
|
|
283
|
+
);
|
|
284
|
+
return (
|
|
285
|
+
siblings.length > 1 &&
|
|
286
|
+
siblings.every(
|
|
287
|
+
( siblingClientId ) =>
|
|
288
|
+
getBlockEditingMode( state, siblingClientId ) === 'default'
|
|
289
|
+
)
|
|
290
|
+
);
|
|
291
|
+
},
|
|
292
|
+
( state ) => [
|
|
293
|
+
state.blocks.order,
|
|
294
|
+
state.blocks.parents,
|
|
295
|
+
state.blocks.byClientId,
|
|
296
|
+
state.blocks.blockEditingModes,
|
|
297
|
+
state.derivedBlockEditingModes,
|
|
298
|
+
state.blocksMode,
|
|
299
|
+
]
|
|
300
|
+
);
|
|
301
|
+
|
|
246
302
|
/**
|
|
247
303
|
* Returns the block tree displayed by List View.
|
|
248
304
|
*
|