@wordpress/block-editor 16.2.0 → 17.0.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 +39 -0
- package/build/components/block-inspector/index.cjs +9 -6
- package/build/components/block-inspector/index.cjs.map +2 -2
- package/build/components/block-keyboard-shortcuts/index.cjs +201 -0
- package/build/components/block-keyboard-shortcuts/index.cjs.map +7 -0
- package/build/components/block-list/block.cjs +10 -3
- package/build/components/block-list/block.cjs.map +2 -2
- package/build/components/block-list/index.cjs +6 -1
- package/build/components/block-list/index.cjs.map +2 -2
- package/build/components/block-list/use-block-props/use-focus-first-element.cjs +4 -0
- package/build/components/block-list/use-block-props/use-focus-first-element.cjs.map +2 -2
- package/build/components/block-list/use-block-props/use-selected-block-event-handlers.cjs +6 -7
- package/build/components/block-list/use-block-props/use-selected-block-event-handlers.cjs.map +2 -2
- package/build/components/block-parent-selector/index.cjs +98 -29
- package/build/components/block-parent-selector/index.cjs.map +3 -3
- package/build/components/block-popover/inbetween.cjs +2 -2
- package/build/components/block-popover/inbetween.cjs.map +2 -2
- package/build/components/block-preview/index.cjs +0 -4
- package/build/components/block-preview/index.cjs.map +2 -2
- package/build/components/block-styles/index.cjs +77 -33
- package/build/components/block-styles/index.cjs.map +3 -3
- package/build/components/block-visibility/constants.cjs.map +2 -2
- package/build/components/child-layout-control/index.cjs.map +2 -2
- package/build/components/colors/with-colors.cjs +55 -71
- package/build/components/colors/with-colors.cjs.map +2 -2
- package/build/components/dimensions-tool/aspect-ratio-tool.cjs +4 -2
- package/build/components/dimensions-tool/aspect-ratio-tool.cjs.map +2 -2
- package/build/components/dimensions-tool/index.cjs +18 -16
- package/build/components/dimensions-tool/index.cjs.map +2 -2
- package/build/components/dimensions-tool/utils.cjs +61 -0
- package/build/components/dimensions-tool/utils.cjs.map +7 -0
- package/build/components/duotone-control/index.cjs +2 -0
- package/build/components/duotone-control/index.cjs.map +2 -2
- package/build/components/global-styles/advanced-panel.cjs.map +3 -3
- package/build/components/global-styles/border-panel.cjs +2 -5
- package/build/components/global-styles/border-panel.cjs.map +2 -2
- package/build/components/global-styles/color-panel.cjs +14 -2
- package/build/components/global-styles/color-panel.cjs.map +2 -2
- package/build/components/global-styles/dimensions-panel.cjs +9 -5
- package/build/components/global-styles/dimensions-panel.cjs.map +2 -2
- package/build/components/global-styles/filters-panel.cjs +12 -8
- package/build/components/global-styles/filters-panel.cjs.map +2 -2
- package/build/components/global-styles/shadow-panel-components.cjs +16 -11
- package/build/components/global-styles/shadow-panel-components.cjs.map +2 -2
- package/build/components/global-styles/utils.cjs +9 -0
- package/build/components/global-styles/utils.cjs.map +2 -2
- package/build/components/inner-blocks/index.cjs +5 -3
- package/build/components/inner-blocks/index.cjs.map +2 -2
- package/build/components/inserter/block-patterns-explorer/index.cjs +39 -22
- package/build/components/inserter/block-patterns-explorer/index.cjs.map +2 -2
- package/build/components/inserter/block-patterns-explorer/pattern-explorer-sidebar.cjs +21 -55
- package/build/components/inserter/block-patterns-explorer/pattern-explorer-sidebar.cjs.map +2 -2
- package/build/components/inserter/block-patterns-explorer/pattern-list.cjs +19 -44
- package/build/components/inserter/block-patterns-explorer/pattern-list.cjs.map +3 -3
- package/build/components/inserter/hooks/use-insertion-point.cjs +4 -4
- package/build/components/inserter/hooks/use-insertion-point.cjs.map +2 -2
- package/build/components/inserter/menu.cjs +18 -7
- package/build/components/inserter/menu.cjs.map +2 -2
- package/build/components/inserter/quick-inserter.cjs +30 -27
- package/build/components/inserter/quick-inserter.cjs.map +2 -2
- package/build/components/inspector-controls-tabs/styles-tab.cjs +1 -1
- package/build/components/inspector-controls-tabs/styles-tab.cjs.map +2 -2
- package/build/components/list-view/index.cjs +31 -5
- package/build/components/list-view/index.cjs.map +3 -3
- package/build/components/list-view/utils.cjs +13 -1
- package/build/components/list-view/utils.cjs.map +2 -2
- package/build/components/media-placeholder/index.cjs +1 -1
- package/build/components/media-placeholder/index.cjs.map +3 -3
- package/build/components/provider/index.cjs +5 -1
- package/build/components/provider/index.cjs.map +3 -3
- package/build/components/publish-date-time-picker/index.cjs +3 -2
- package/build/components/publish-date-time-picker/index.cjs.map +2 -2
- package/build/components/rich-text/event-listeners/enter.cjs +46 -39
- package/build/components/rich-text/event-listeners/enter.cjs.map +2 -2
- package/build/components/rich-text/index.cjs +7 -5
- package/build/components/rich-text/index.cjs.map +2 -2
- package/build/components/rich-text/multiline.cjs +105 -70
- package/build/components/rich-text/multiline.cjs.map +3 -3
- package/build/components/url-input/index.cjs.map +2 -2
- package/build/components/writing-flow/use-input.cjs +65 -13
- package/build/components/writing-flow/use-input.cjs.map +3 -3
- package/build/hooks/border.cjs +25 -3
- package/build/hooks/border.cjs.map +2 -2
- package/build/hooks/dimensions.cjs +9 -2
- package/build/hooks/dimensions.cjs.map +2 -2
- package/build/hooks/duotone.cjs +4 -3
- package/build/hooks/duotone.cjs.map +2 -2
- package/build/hooks/gap.cjs +8 -2
- package/build/hooks/gap.cjs.map +2 -2
- package/build/hooks/layout-child.cjs +35 -13
- package/build/hooks/layout-child.cjs.map +2 -2
- package/build/hooks/layout.cjs +23 -1
- package/build/hooks/layout.cjs.map +2 -2
- package/build/hooks/states.cjs +7 -4
- package/build/hooks/states.cjs.map +2 -2
- package/build/layouts/constrained.cjs +8 -1
- package/build/layouts/constrained.cjs.map +2 -2
- package/build/layouts/flex.cjs +9 -0
- package/build/layouts/flex.cjs.map +2 -2
- package/build/layouts/flow.cjs +4 -1
- package/build/layouts/flow.cjs.map +2 -2
- package/build/layouts/grid.cjs +5 -1
- package/build/layouts/grid.cjs.map +2 -2
- package/build/private-apis.cjs +3 -1
- package/build/private-apis.cjs.map +2 -2
- package/build/store/actions.cjs +1 -1
- package/build/store/actions.cjs.map +2 -2
- package/build-module/components/block-inspector/index.mjs +9 -6
- package/build-module/components/block-inspector/index.mjs.map +2 -2
- package/build-module/components/block-keyboard-shortcuts/index.mjs +173 -0
- package/build-module/components/block-keyboard-shortcuts/index.mjs.map +7 -0
- package/build-module/components/block-list/block.mjs +10 -3
- package/build-module/components/block-list/block.mjs.map +2 -2
- package/build-module/components/block-list/index.mjs +6 -1
- package/build-module/components/block-list/index.mjs.map +2 -2
- package/build-module/components/block-list/use-block-props/use-focus-first-element.mjs +4 -0
- package/build-module/components/block-list/use-block-props/use-focus-first-element.mjs.map +2 -2
- package/build-module/components/block-list/use-block-props/use-selected-block-event-handlers.mjs +6 -7
- package/build-module/components/block-list/use-block-props/use-selected-block-event-handlers.mjs.map +2 -2
- package/build-module/components/block-parent-selector/index.mjs +101 -32
- package/build-module/components/block-parent-selector/index.mjs.map +2 -2
- package/build-module/components/block-popover/inbetween.mjs +2 -2
- package/build-module/components/block-popover/inbetween.mjs.map +2 -2
- package/build-module/components/block-preview/index.mjs +0 -4
- package/build-module/components/block-preview/index.mjs.map +2 -2
- package/build-module/components/block-styles/index.mjs +79 -35
- package/build-module/components/block-styles/index.mjs.map +2 -2
- package/build-module/components/block-visibility/constants.mjs.map +2 -2
- package/build-module/components/child-layout-control/index.mjs +5 -5
- package/build-module/components/child-layout-control/index.mjs.map +1 -1
- package/build-module/components/colors/with-colors.mjs +56 -72
- package/build-module/components/colors/with-colors.mjs.map +2 -2
- package/build-module/components/dimensions-tool/aspect-ratio-tool.mjs +4 -2
- package/build-module/components/dimensions-tool/aspect-ratio-tool.mjs.map +2 -2
- package/build-module/components/dimensions-tool/index.mjs +19 -17
- package/build-module/components/dimensions-tool/index.mjs.map +2 -2
- package/build-module/components/dimensions-tool/utils.mjs +35 -0
- package/build-module/components/dimensions-tool/utils.mjs.map +7 -0
- package/build-module/components/duotone-control/index.mjs +2 -0
- package/build-module/components/duotone-control/index.mjs.map +2 -2
- package/build-module/components/global-styles/advanced-panel.mjs +5 -2
- package/build-module/components/global-styles/advanced-panel.mjs.map +2 -2
- package/build-module/components/global-styles/border-panel.mjs +2 -5
- package/build-module/components/global-styles/border-panel.mjs.map +2 -2
- package/build-module/components/global-styles/color-panel.mjs +14 -2
- package/build-module/components/global-styles/color-panel.mjs.map +2 -2
- package/build-module/components/global-styles/dimensions-panel.mjs +9 -5
- package/build-module/components/global-styles/dimensions-panel.mjs.map +2 -2
- package/build-module/components/global-styles/filters-panel.mjs +16 -9
- package/build-module/components/global-styles/filters-panel.mjs.map +2 -2
- package/build-module/components/global-styles/shadow-panel-components.mjs +16 -11
- package/build-module/components/global-styles/shadow-panel-components.mjs.map +2 -2
- package/build-module/components/global-styles/utils.mjs +8 -0
- package/build-module/components/global-styles/utils.mjs.map +2 -2
- package/build-module/components/inner-blocks/index.mjs +5 -3
- package/build-module/components/inner-blocks/index.mjs.map +2 -2
- package/build-module/components/inserter/block-patterns-explorer/index.mjs +39 -22
- package/build-module/components/inserter/block-patterns-explorer/index.mjs.map +2 -2
- package/build-module/components/inserter/block-patterns-explorer/pattern-explorer-sidebar.mjs +22 -56
- package/build-module/components/inserter/block-patterns-explorer/pattern-explorer-sidebar.mjs.map +2 -2
- package/build-module/components/inserter/block-patterns-explorer/pattern-list.mjs +20 -45
- package/build-module/components/inserter/block-patterns-explorer/pattern-list.mjs.map +2 -2
- package/build-module/components/inserter/hooks/use-insertion-point.mjs +4 -4
- package/build-module/components/inserter/hooks/use-insertion-point.mjs.map +2 -2
- package/build-module/components/inserter/menu.mjs +19 -8
- package/build-module/components/inserter/menu.mjs.map +2 -2
- package/build-module/components/inserter/quick-inserter.mjs +30 -27
- package/build-module/components/inserter/quick-inserter.mjs.map +2 -2
- package/build-module/components/inspector-controls-tabs/styles-tab.mjs +1 -1
- package/build-module/components/inspector-controls-tabs/styles-tab.mjs.map +2 -2
- package/build-module/components/list-view/index.mjs +32 -5
- package/build-module/components/list-view/index.mjs.map +3 -3
- package/build-module/components/list-view/utils.mjs +13 -1
- package/build-module/components/list-view/utils.mjs.map +2 -2
- package/build-module/components/media-placeholder/index.mjs +3 -3
- package/build-module/components/media-placeholder/index.mjs.map +2 -2
- package/build-module/components/provider/index.mjs +6 -2
- package/build-module/components/provider/index.mjs.map +2 -2
- package/build-module/components/publish-date-time-picker/index.mjs +3 -2
- package/build-module/components/publish-date-time-picker/index.mjs.map +2 -2
- package/build-module/components/rich-text/event-listeners/enter.mjs +46 -39
- package/build-module/components/rich-text/event-listeners/enter.mjs.map +2 -2
- package/build-module/components/rich-text/index.mjs +7 -5
- package/build-module/components/rich-text/index.mjs.map +2 -2
- package/build-module/components/rich-text/multiline.mjs +112 -72
- package/build-module/components/rich-text/multiline.mjs.map +2 -2
- package/build-module/components/url-input/index.mjs +2 -2
- package/build-module/components/url-input/index.mjs.map +1 -1
- package/build-module/components/writing-flow/use-input.mjs +66 -14
- package/build-module/components/writing-flow/use-input.mjs.map +3 -3
- package/build-module/hooks/border.mjs +26 -8
- package/build-module/hooks/border.mjs.map +2 -2
- package/build-module/hooks/dimensions.mjs +9 -2
- package/build-module/hooks/dimensions.mjs.map +2 -2
- package/build-module/hooks/duotone.mjs +8 -4
- package/build-module/hooks/duotone.mjs.map +2 -2
- package/build-module/hooks/gap.mjs +6 -1
- package/build-module/hooks/gap.mjs.map +2 -2
- package/build-module/hooks/layout-child.mjs +36 -13
- package/build-module/hooks/layout-child.mjs.map +2 -2
- package/build-module/hooks/layout.mjs +22 -1
- package/build-module/hooks/layout.mjs.map +2 -2
- package/build-module/hooks/states.mjs +8 -5
- package/build-module/hooks/states.mjs.map +2 -2
- package/build-module/layouts/constrained.mjs +8 -1
- package/build-module/layouts/constrained.mjs.map +2 -2
- package/build-module/layouts/flex.mjs +9 -0
- package/build-module/layouts/flex.mjs.map +2 -2
- package/build-module/layouts/flow.mjs +4 -1
- package/build-module/layouts/flow.mjs.map +2 -2
- package/build-module/layouts/grid.mjs +5 -1
- package/build-module/layouts/grid.mjs.map +2 -2
- package/build-module/private-apis.mjs +3 -1
- package/build-module/private-apis.mjs.map +2 -2
- package/build-module/store/actions.mjs +1 -1
- package/build-module/store/actions.mjs.map +2 -2
- package/build-style/style-rtl.css +108 -71
- package/build-style/style.css +108 -71
- package/build-types/components/block-visibility/constants.d.ts +4 -3
- package/build-types/components/block-visibility/constants.d.ts.map +1 -1
- package/package.json +43 -43
- package/src/components/background-image-control/README.md +122 -0
- package/src/components/block-edit-visually-button/README.md +39 -0
- package/src/components/block-editing-mode/README.md +72 -0
- package/src/components/block-inspector/index.js +6 -6
- package/src/components/block-keyboard-shortcuts/index.js +256 -0
- package/src/components/block-list/block.js +7 -0
- package/src/components/block-list/index.js +7 -1
- package/src/components/block-list/use-block-props/use-focus-first-element.js +5 -0
- package/src/components/block-list/use-block-props/use-selected-block-event-handlers.js +6 -8
- package/src/components/block-parent-selector/index.js +111 -30
- package/src/components/block-popover/README.md +10 -3
- package/src/components/block-popover/inbetween.js +8 -2
- package/src/components/block-popover/stories/index.story.jsx +143 -0
- package/src/components/block-preview/index.js +0 -2
- package/src/components/block-styles/index.js +95 -43
- package/src/components/block-styles/style.scss +5 -34
- package/src/components/block-tools/style.scss +94 -0
- package/src/components/block-visibility/constants.ts +4 -3
- package/src/components/child-layout-control/index.js +5 -5
- package/src/components/color-palette/test/__snapshots__/control.js.snap +3 -29
- package/src/components/colors/test/with-colors.js +6 -7
- package/src/components/colors/with-colors.js +79 -105
- package/src/components/dimensions-tool/aspect-ratio-tool.js +16 -4
- package/src/components/dimensions-tool/index.js +34 -22
- package/src/components/dimensions-tool/test/index.js +166 -2
- package/src/components/dimensions-tool/test/utils.js +51 -0
- package/src/components/dimensions-tool/utils.js +67 -0
- package/src/components/duotone-control/index.js +2 -0
- package/src/components/duotone-control/test/index.js +100 -0
- package/src/components/global-styles/advanced-panel.js +5 -2
- package/src/components/global-styles/border-panel.js +11 -9
- package/src/components/global-styles/color-panel.js +13 -1
- package/src/components/global-styles/dimensions-panel.js +17 -5
- package/src/components/global-styles/filters-panel.js +24 -10
- package/src/components/global-styles/shadow-panel-components.js +38 -11
- package/src/components/global-styles/test/border-panel.js +230 -0
- package/src/components/global-styles/test/color-panel.js +24 -0
- package/src/components/global-styles/test/dimensions-panel.js +98 -7
- package/src/components/global-styles/test/filters-panel.js +84 -0
- package/src/components/global-styles/test/utils.js +30 -0
- package/src/components/global-styles/utils.js +23 -0
- package/src/components/inner-blocks/index.js +11 -2
- package/src/components/inner-blocks/stories/index.story.jsx +246 -0
- package/src/components/inserter/block-patterns-explorer/index.js +24 -11
- package/src/components/inserter/block-patterns-explorer/pattern-explorer-sidebar.js +18 -56
- package/src/components/inserter/block-patterns-explorer/pattern-list.js +22 -47
- package/src/components/inserter/hooks/use-insertion-point.js +9 -4
- package/src/components/inserter/menu.js +23 -10
- package/src/components/inserter/quick-inserter.js +15 -13
- package/src/components/inserter/style.scss +44 -62
- package/src/components/inspector-controls-tabs/README.md +92 -0
- package/src/components/inspector-controls-tabs/styles-tab.js +1 -1
- package/src/components/link-control/test/index.js +5 -0
- package/src/components/list-view/index.js +50 -7
- package/src/components/list-view/utils.js +16 -1
- package/src/components/media-placeholder/index.js +9 -4
- package/src/components/plain-text/stories/index.story.jsx +3 -0
- package/src/components/provider/index.js +7 -1
- package/src/components/publish-date-time-picker/README.md +10 -0
- package/src/components/publish-date-time-picker/index.js +17 -14
- package/src/components/rich-text/event-listeners/enter.js +58 -45
- package/src/components/rich-text/index.js +9 -4
- package/src/components/rich-text/multiline.js +126 -86
- package/src/components/url-input/index.js +2 -2
- package/src/components/url-input/test/fixtures/validated-input-control-deprecation.js +27 -0
- package/src/components/url-input/test/index.js +5 -0
- package/src/components/url-popover/README.md +7 -0
- package/src/components/url-popover/stories/index.story.jsx +133 -47
- package/src/components/writing-flow/use-input.js +105 -15
- package/src/hooks/border.js +27 -8
- package/src/hooks/dimensions.js +8 -1
- package/src/hooks/duotone.js +23 -7
- package/src/hooks/gap.js +16 -0
- package/src/hooks/layout-child.js +41 -9
- package/src/hooks/layout.js +117 -71
- package/src/hooks/states.js +8 -5
- package/src/hooks/test/gap.js +31 -1
- package/src/hooks/test/layout-child.js +60 -1
- package/src/hooks/test/layout.js +27 -0
- package/src/layouts/constrained.js +9 -1
- package/src/layouts/flex.js +15 -0
- package/src/layouts/flow.js +4 -1
- package/src/layouts/grid.js +9 -1
- package/src/layouts/test/constrained.js +26 -0
- package/src/layouts/test/flow.js +26 -0
- package/src/layouts/test/grid.js +46 -0
- package/src/private-apis.js +2 -0
- package/src/store/actions.js +14 -1
- package/build/components/floating-toolbar/nav-up-icon.cjs +0 -52
- package/build/components/floating-toolbar/nav-up-icon.cjs.map +0 -7
- package/build/components/gradients/with-gradient.cjs +0 -36
- package/build/components/gradients/with-gradient.cjs.map +0 -7
- package/build/components/inserter-button/sparkles.cjs +0 -36
- package/build/components/inserter-button/sparkles.cjs.map +0 -7
- package/build-module/components/floating-toolbar/nav-up-icon.mjs +0 -31
- package/build-module/components/floating-toolbar/nav-up-icon.mjs.map +0 -7
- package/build-module/components/gradients/with-gradient.mjs +0 -11
- package/build-module/components/gradients/with-gradient.mjs.map +0 -7
- package/build-module/components/inserter-button/sparkles.mjs +0 -15
- package/build-module/components/inserter-button/sparkles.mjs.map +0 -7
- package/build-style/default-editor-styles-rtl.css +0 -68
- package/build-style/default-editor-styles.css +0 -68
- package/src/components/floating-toolbar/nav-up-icon.js +0 -22
- package/src/components/gradients/with-gradient.js +0 -9
- package/src/components/inserter-button/README.md +0 -62
- package/src/components/inserter-button/sparkles.js +0 -12
- package/src/default-editor-styles.scss +0 -25
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { render, screen } from '@testing-library/react';
|
|
1
|
+
import { act, render, screen } from '@testing-library/react';
|
|
2
2
|
import userEvent from '@testing-library/user-event';
|
|
3
3
|
import { __experimentalToolsPanel as ToolsPanel } from '@wordpress/components';
|
|
4
|
-
import { useState } from '@wordpress/element';
|
|
4
|
+
import { useEffect, useState } from '@wordpress/element';
|
|
5
5
|
import DimensionsTool from '../';
|
|
6
6
|
|
|
7
7
|
const EMPTY_OBJECT = {};
|
|
@@ -9,6 +9,9 @@ const ASPECT_RATIO_OPTIONS = [
|
|
|
9
9
|
{ label: 'Original', value: 'auto' },
|
|
10
10
|
{ label: '16/9', value: '16/9' },
|
|
11
11
|
{ label: '4/3', value: '4/3' },
|
|
12
|
+
// Matches the core preset for a square, which is written as a single
|
|
13
|
+
// number rather than a ratio.
|
|
14
|
+
{ label: 'Square', value: '1' },
|
|
12
15
|
{
|
|
13
16
|
label: 'Custom',
|
|
14
17
|
value: 'custom',
|
|
@@ -41,6 +44,30 @@ function Example( { initialValue, onChange, ...props } ) {
|
|
|
41
44
|
);
|
|
42
45
|
}
|
|
43
46
|
|
|
47
|
+
// Holds the value like `Example`, but also lets a test update it from the
|
|
48
|
+
// outside, the way `updateBlockAttributes`, undo, or another client would.
|
|
49
|
+
function ExternallyUpdatedExample( { initialValue, onChange, updateRef } ) {
|
|
50
|
+
const [ value, setValue ] = useState( initialValue );
|
|
51
|
+
useEffect( () => {
|
|
52
|
+
updateRef.current = setValue;
|
|
53
|
+
}, [ updateRef ] );
|
|
54
|
+
return (
|
|
55
|
+
<ToolsPanel label="Dimensions" panelId="panel-id" resetAll={ () => {} }>
|
|
56
|
+
<DimensionsTool
|
|
57
|
+
panelId="panel-id"
|
|
58
|
+
onChange={ ( nextValue ) => {
|
|
59
|
+
setValue( nextValue );
|
|
60
|
+
onChange( nextValue );
|
|
61
|
+
} }
|
|
62
|
+
defaultScale="cover"
|
|
63
|
+
defaultAspectRatio="auto"
|
|
64
|
+
aspectRatioOptions={ ASPECT_RATIO_OPTIONS }
|
|
65
|
+
value={ value }
|
|
66
|
+
/>
|
|
67
|
+
</ToolsPanel>
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
44
71
|
function ControlledExample( { value, onChange, ...props } ) {
|
|
45
72
|
return (
|
|
46
73
|
<ToolsPanel
|
|
@@ -102,6 +129,143 @@ describe( 'DimensionsTool', () => {
|
|
|
102
129
|
);
|
|
103
130
|
expect( aspectRatioSelect ).toHaveValue( 'auto' );
|
|
104
131
|
} );
|
|
132
|
+
|
|
133
|
+
it( 'displays an aspect ratio that is written differently to the option with the same ratio', () => {
|
|
134
|
+
const onChange = jest.fn();
|
|
135
|
+
const { rerender } = render(
|
|
136
|
+
<ControlledExample
|
|
137
|
+
value={ { aspectRatio: '1/1' } }
|
|
138
|
+
onChange={ onChange }
|
|
139
|
+
/>
|
|
140
|
+
);
|
|
141
|
+
const aspectRatioSelect = screen.getByRole( 'combobox', {
|
|
142
|
+
name: 'Aspect ratio',
|
|
143
|
+
} );
|
|
144
|
+
|
|
145
|
+
expect( aspectRatioSelect ).toHaveValue( '1' );
|
|
146
|
+
|
|
147
|
+
rerender(
|
|
148
|
+
<ControlledExample
|
|
149
|
+
value={ { aspectRatio: '16 / 9' } }
|
|
150
|
+
onChange={ onChange }
|
|
151
|
+
/>
|
|
152
|
+
);
|
|
153
|
+
expect( aspectRatioSelect ).toHaveValue( '16/9' );
|
|
154
|
+
} );
|
|
155
|
+
|
|
156
|
+
it( 'displays an aspect ratio without a matching option as custom', () => {
|
|
157
|
+
const onChange = jest.fn();
|
|
158
|
+
render(
|
|
159
|
+
<ControlledExample
|
|
160
|
+
value={ { aspectRatio: '7/5' } }
|
|
161
|
+
onChange={ onChange }
|
|
162
|
+
/>
|
|
163
|
+
);
|
|
164
|
+
|
|
165
|
+
expect(
|
|
166
|
+
screen.getByRole( 'combobox', { name: 'Aspect ratio' } )
|
|
167
|
+
).toHaveValue( 'custom' );
|
|
168
|
+
} );
|
|
169
|
+
|
|
170
|
+
it( 'updates the scale control when the value prop changes', () => {
|
|
171
|
+
const onChange = jest.fn();
|
|
172
|
+
const { rerender } = render(
|
|
173
|
+
<ControlledExample
|
|
174
|
+
value={ { aspectRatio: '16/9', scale: 'cover' } }
|
|
175
|
+
onChange={ onChange }
|
|
176
|
+
/>
|
|
177
|
+
);
|
|
178
|
+
|
|
179
|
+
expect(
|
|
180
|
+
screen.getByRole( 'radio', { name: 'Cover' } )
|
|
181
|
+
).toBeChecked();
|
|
182
|
+
|
|
183
|
+
rerender(
|
|
184
|
+
<ControlledExample
|
|
185
|
+
value={ { aspectRatio: '16/9', scale: 'contain' } }
|
|
186
|
+
onChange={ onChange }
|
|
187
|
+
/>
|
|
188
|
+
);
|
|
189
|
+
|
|
190
|
+
expect(
|
|
191
|
+
screen.getByRole( 'radio', { name: 'Contain' } )
|
|
192
|
+
).toBeChecked();
|
|
193
|
+
} );
|
|
194
|
+
} );
|
|
195
|
+
|
|
196
|
+
describe( 'external updates', () => {
|
|
197
|
+
it( 'restores the scale that was set externally', async () => {
|
|
198
|
+
const user = userEvent.setup();
|
|
199
|
+
const onChange = jest.fn();
|
|
200
|
+
const updateRef = { current: null };
|
|
201
|
+
|
|
202
|
+
render(
|
|
203
|
+
<ExternallyUpdatedExample
|
|
204
|
+
initialValue={ { aspectRatio: '16/9', scale: 'cover' } }
|
|
205
|
+
onChange={ onChange }
|
|
206
|
+
updateRef={ updateRef }
|
|
207
|
+
/>
|
|
208
|
+
);
|
|
209
|
+
|
|
210
|
+
// Update the scale from outside the component.
|
|
211
|
+
await act( async () =>
|
|
212
|
+
updateRef.current( { aspectRatio: '16/9', scale: 'contain' } )
|
|
213
|
+
);
|
|
214
|
+
|
|
215
|
+
// Clearing and setting the aspect ratio again restores the scale.
|
|
216
|
+
await user.selectOptions(
|
|
217
|
+
screen.getByRole( 'combobox', { name: 'Aspect ratio' } ),
|
|
218
|
+
'auto'
|
|
219
|
+
);
|
|
220
|
+
await user.selectOptions(
|
|
221
|
+
screen.getByRole( 'combobox', { name: 'Aspect ratio' } ),
|
|
222
|
+
'4/3'
|
|
223
|
+
);
|
|
224
|
+
|
|
225
|
+
expect( onChange ).toHaveBeenLastCalledWith( {
|
|
226
|
+
aspectRatio: '4/3',
|
|
227
|
+
scale: 'contain',
|
|
228
|
+
} );
|
|
229
|
+
} );
|
|
230
|
+
|
|
231
|
+
it( 'restores the aspect ratio that was set externally', async () => {
|
|
232
|
+
const user = userEvent.setup();
|
|
233
|
+
const onChange = jest.fn();
|
|
234
|
+
const updateRef = { current: null };
|
|
235
|
+
|
|
236
|
+
render(
|
|
237
|
+
<ExternallyUpdatedExample
|
|
238
|
+
initialValue={ { aspectRatio: '16/9', scale: 'cover' } }
|
|
239
|
+
onChange={ onChange }
|
|
240
|
+
updateRef={ updateRef }
|
|
241
|
+
/>
|
|
242
|
+
);
|
|
243
|
+
|
|
244
|
+
// Update the aspect ratio from outside the component.
|
|
245
|
+
await act( async () =>
|
|
246
|
+
updateRef.current( { aspectRatio: '4/3', scale: 'cover' } )
|
|
247
|
+
);
|
|
248
|
+
|
|
249
|
+
// Setting both a width and a height replaces the aspect ratio with
|
|
250
|
+
// a custom one, and clearing the width restores the previous one.
|
|
251
|
+
await user.type(
|
|
252
|
+
screen.getByRole( 'spinbutton', { name: 'Width' } ),
|
|
253
|
+
'100'
|
|
254
|
+
);
|
|
255
|
+
await user.type(
|
|
256
|
+
screen.getByRole( 'spinbutton', { name: 'Height' } ),
|
|
257
|
+
'100'
|
|
258
|
+
);
|
|
259
|
+
await user.clear(
|
|
260
|
+
screen.getByRole( 'spinbutton', { name: 'Width' } )
|
|
261
|
+
);
|
|
262
|
+
|
|
263
|
+
expect( onChange ).toHaveBeenLastCalledWith( {
|
|
264
|
+
aspectRatio: '4/3',
|
|
265
|
+
scale: 'cover',
|
|
266
|
+
height: '100px',
|
|
267
|
+
} );
|
|
268
|
+
} );
|
|
105
269
|
} );
|
|
106
270
|
|
|
107
271
|
describe( 'updating aspectRatio', () => {
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { findAspectRatioOption, parseAspectRatio } from '../utils';
|
|
2
|
+
|
|
3
|
+
describe( 'parseAspectRatio', () => {
|
|
4
|
+
it.each( [
|
|
5
|
+
[ '1', 1 ],
|
|
6
|
+
[ '1/1', 1 ],
|
|
7
|
+
[ '16/9', 16 / 9 ],
|
|
8
|
+
[ '16 / 9', 16 / 9 ],
|
|
9
|
+
[ '1.5', 1.5 ],
|
|
10
|
+
[ '3/2', 1.5 ],
|
|
11
|
+
] )( 'parses %s', ( value, expected ) => {
|
|
12
|
+
expect( parseAspectRatio( value ) ).toBe( expected );
|
|
13
|
+
} );
|
|
14
|
+
|
|
15
|
+
it.each( [
|
|
16
|
+
[ 'auto' ],
|
|
17
|
+
[ '' ],
|
|
18
|
+
[ '16/9/2' ],
|
|
19
|
+
[ '0' ],
|
|
20
|
+
[ '1/0' ],
|
|
21
|
+
[ '-16/9' ],
|
|
22
|
+
[ undefined ],
|
|
23
|
+
[ null ],
|
|
24
|
+
] )( 'returns null for %s', ( value ) => {
|
|
25
|
+
expect( parseAspectRatio( value ) ).toBeNull();
|
|
26
|
+
} );
|
|
27
|
+
} );
|
|
28
|
+
|
|
29
|
+
describe( 'findAspectRatioOption', () => {
|
|
30
|
+
const options = [
|
|
31
|
+
{ label: 'Original', value: 'auto' },
|
|
32
|
+
{ label: 'Square', value: '1' },
|
|
33
|
+
{ label: 'Wide', value: '16/9' },
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
it( 'matches an option by value', () => {
|
|
37
|
+
expect( findAspectRatioOption( '16/9', options ) ).toBe( options[ 2 ] );
|
|
38
|
+
} );
|
|
39
|
+
|
|
40
|
+
it( 'matches an option describing the same ratio', () => {
|
|
41
|
+
expect( findAspectRatioOption( '1/1', options ) ).toBe( options[ 1 ] );
|
|
42
|
+
expect( findAspectRatioOption( '16 / 9', options ) ).toBe(
|
|
43
|
+
options[ 2 ]
|
|
44
|
+
);
|
|
45
|
+
} );
|
|
46
|
+
|
|
47
|
+
it( 'returns null when no option describes the ratio', () => {
|
|
48
|
+
expect( findAspectRatioOption( '7/5', options ) ).toBeNull();
|
|
49
|
+
expect( findAspectRatioOption( 'nonsense', options ) ).toBeNull();
|
|
50
|
+
} );
|
|
51
|
+
} );
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parses a CSS `aspect-ratio` value into a number so that values that are
|
|
3
|
+
* written differently but describe the same ratio, e.g. `1` and `1/1`, can be
|
|
4
|
+
* compared.
|
|
5
|
+
*
|
|
6
|
+
* @param {string} [value] CSS aspect-ratio value, e.g. '16/9' or '1.5'.
|
|
7
|
+
*
|
|
8
|
+
* @return {?number} The ratio as a number, or null when it cannot be parsed.
|
|
9
|
+
*/
|
|
10
|
+
export function parseAspectRatio( value ) {
|
|
11
|
+
if ( typeof value !== 'string' ) {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const parts = value.split( '/' );
|
|
16
|
+
|
|
17
|
+
if ( parts.length > 2 ) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const [ width, height = '1' ] = parts;
|
|
22
|
+
const numericWidth = Number( width.trim() );
|
|
23
|
+
const numericHeight = Number( height.trim() );
|
|
24
|
+
|
|
25
|
+
if (
|
|
26
|
+
! Number.isFinite( numericWidth ) ||
|
|
27
|
+
! Number.isFinite( numericHeight ) ||
|
|
28
|
+
numericWidth <= 0 ||
|
|
29
|
+
numericHeight <= 0
|
|
30
|
+
) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return numericWidth / numericHeight;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Finds the option that represents the given CSS `aspect-ratio` value.
|
|
39
|
+
*
|
|
40
|
+
* Aspect ratio values are free-form CSS, while the options are a fixed list of
|
|
41
|
+
* presets, so an exact string match isn't enough: `1/1` and `1` describe the
|
|
42
|
+
* same ratio but only one of them is a preset value.
|
|
43
|
+
*
|
|
44
|
+
* @param {string} value CSS aspect-ratio value.
|
|
45
|
+
* @param {Object[]} options Aspect ratio options.
|
|
46
|
+
*
|
|
47
|
+
* @return {?Object} The matching option, or null when there is none.
|
|
48
|
+
*/
|
|
49
|
+
export function findAspectRatioOption( value, options ) {
|
|
50
|
+
const exactMatch = options.find( ( option ) => option.value === value );
|
|
51
|
+
|
|
52
|
+
if ( exactMatch ) {
|
|
53
|
+
return exactMatch;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const ratio = parseAspectRatio( value );
|
|
57
|
+
|
|
58
|
+
if ( ratio === null ) {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return (
|
|
63
|
+
options.find(
|
|
64
|
+
( option ) => parseAspectRatio( option.value ) === ratio
|
|
65
|
+
) ?? null
|
|
66
|
+
);
|
|
67
|
+
}
|
|
@@ -18,6 +18,7 @@ function DuotoneControl( {
|
|
|
18
18
|
disableCustomColors,
|
|
19
19
|
disableCustomDuotone,
|
|
20
20
|
value,
|
|
21
|
+
selectedSlug,
|
|
21
22
|
onChange,
|
|
22
23
|
} ) {
|
|
23
24
|
let toolbarIcon;
|
|
@@ -75,6 +76,7 @@ function DuotoneControl( {
|
|
|
75
76
|
disableCustomColors={ disableCustomColors }
|
|
76
77
|
disableCustomDuotone={ disableCustomDuotone }
|
|
77
78
|
value={ value }
|
|
79
|
+
selectedSlug={ selectedSlug }
|
|
78
80
|
onChange={ onChange }
|
|
79
81
|
/>
|
|
80
82
|
</MenuGroup>
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { render, screen } from '@testing-library/react';
|
|
2
|
+
import userEvent from '@testing-library/user-event';
|
|
3
|
+
import DuotoneControl from '../';
|
|
4
|
+
|
|
5
|
+
// Adding two custom duotones in Global Styles seeds both from the palette's
|
|
6
|
+
// darkest and lightest colors, so two presets holding the same pair is the
|
|
7
|
+
// ordinary case. Only the slug tells them apart.
|
|
8
|
+
const DUPLICATE_PALETTE = [
|
|
9
|
+
{
|
|
10
|
+
name: 'Duotone 1',
|
|
11
|
+
slug: 'custom-duotone-1',
|
|
12
|
+
colors: [ '#000000', '#ffffff' ],
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
name: 'Duotone 2',
|
|
16
|
+
slug: 'custom-duotone-2',
|
|
17
|
+
colors: [ '#000000', '#ffffff' ],
|
|
18
|
+
},
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
const COLOR_PALETTE = [
|
|
22
|
+
{ color: '#000000', name: 'Black', slug: 'black' },
|
|
23
|
+
{ color: '#ffffff', name: 'White', slug: 'white' },
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
async function openControl( user ) {
|
|
27
|
+
await user.click(
|
|
28
|
+
screen.getByRole( 'button', { name: 'Apply duotone filter' } )
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
describe( 'DuotoneControl', () => {
|
|
33
|
+
it( 'reports the slug of the duplicate that was picked', async () => {
|
|
34
|
+
const user = userEvent.setup();
|
|
35
|
+
const onChange = jest.fn();
|
|
36
|
+
|
|
37
|
+
render(
|
|
38
|
+
<DuotoneControl
|
|
39
|
+
duotonePalette={ DUPLICATE_PALETTE }
|
|
40
|
+
colorPalette={ COLOR_PALETTE }
|
|
41
|
+
value={ undefined }
|
|
42
|
+
onChange={ onChange }
|
|
43
|
+
/>
|
|
44
|
+
);
|
|
45
|
+
await openControl( user );
|
|
46
|
+
|
|
47
|
+
await user.click(
|
|
48
|
+
screen.getByRole( 'option', { name: 'Duotone: Duotone 2' } )
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
expect( onChange ).toHaveBeenCalledWith(
|
|
52
|
+
[ '#000000', '#ffffff' ],
|
|
53
|
+
1,
|
|
54
|
+
'custom-duotone-2'
|
|
55
|
+
);
|
|
56
|
+
} );
|
|
57
|
+
|
|
58
|
+
it( 'marks only the stored preset as selected when two share colors', async () => {
|
|
59
|
+
const user = userEvent.setup();
|
|
60
|
+
|
|
61
|
+
render(
|
|
62
|
+
<DuotoneControl
|
|
63
|
+
duotonePalette={ DUPLICATE_PALETTE }
|
|
64
|
+
colorPalette={ COLOR_PALETTE }
|
|
65
|
+
value={ [ '#000000', '#ffffff' ] }
|
|
66
|
+
selectedSlug="custom-duotone-2"
|
|
67
|
+
onChange={ jest.fn() }
|
|
68
|
+
/>
|
|
69
|
+
);
|
|
70
|
+
await openControl( user );
|
|
71
|
+
|
|
72
|
+
expect(
|
|
73
|
+
screen.getByRole( 'option', { name: 'Duotone: Duotone 1' } )
|
|
74
|
+
).toHaveAttribute( 'aria-selected', 'false' );
|
|
75
|
+
expect(
|
|
76
|
+
screen.getByRole( 'option', { name: 'Duotone: Duotone 2' } )
|
|
77
|
+
).toHaveAttribute( 'aria-selected', 'true' );
|
|
78
|
+
} );
|
|
79
|
+
|
|
80
|
+
it( 'falls back to color matching when no slug is stored', async () => {
|
|
81
|
+
const user = userEvent.setup();
|
|
82
|
+
|
|
83
|
+
render(
|
|
84
|
+
<DuotoneControl
|
|
85
|
+
duotonePalette={ DUPLICATE_PALETTE }
|
|
86
|
+
colorPalette={ COLOR_PALETTE }
|
|
87
|
+
value={ [ '#000000', '#ffffff' ] }
|
|
88
|
+
onChange={ jest.fn() }
|
|
89
|
+
/>
|
|
90
|
+
);
|
|
91
|
+
await openControl( user );
|
|
92
|
+
|
|
93
|
+
expect(
|
|
94
|
+
screen.getByRole( 'option', { name: 'Duotone: Duotone 1' } )
|
|
95
|
+
).toHaveAttribute( 'aria-selected', 'true' );
|
|
96
|
+
expect(
|
|
97
|
+
screen.getByRole( 'option', { name: 'Duotone: Duotone 2' } )
|
|
98
|
+
).toHaveAttribute( 'aria-selected', 'true' );
|
|
99
|
+
} );
|
|
100
|
+
} );
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
TextareaControl as WCTextareaControl,
|
|
3
|
+
Notice,
|
|
4
|
+
} from '@wordpress/components';
|
|
2
5
|
import { Stack } from '@wordpress/ui';
|
|
3
6
|
import { useState } from '@wordpress/element';
|
|
4
7
|
import { __ } from '@wordpress/i18n';
|
|
@@ -88,7 +91,7 @@ export default function AdvancedPanel( {
|
|
|
88
91
|
{ cssError }
|
|
89
92
|
</Notice>
|
|
90
93
|
) }
|
|
91
|
-
<
|
|
94
|
+
<WCTextareaControl
|
|
92
95
|
label={ __( 'Additional CSS' ) }
|
|
93
96
|
value={ customCSS }
|
|
94
97
|
onChange={ ( newValue ) => handleOnChange( newValue ) }
|
|
@@ -98,7 +98,6 @@ export default function BorderPanel( {
|
|
|
98
98
|
inheritedValue = value,
|
|
99
99
|
settings,
|
|
100
100
|
panelId,
|
|
101
|
-
name,
|
|
102
101
|
defaultControls = DEFAULT_CONTROLS,
|
|
103
102
|
showInheritanceLabelIndicators = isGlobalStylesInheritanceEnabled(),
|
|
104
103
|
} ) {
|
|
@@ -262,14 +261,18 @@ export default function BorderPanel( {
|
|
|
262
261
|
inheritedShadow !== undefined &&
|
|
263
262
|
inheritedShadow !== '';
|
|
264
263
|
const shadow = isShadowPlaceholder ? inheritedShadow : localShadow;
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
264
|
+
// The presets the popover offers, from every origin. A preset the user
|
|
265
|
+
// picked has to be stored as a reference to its CSS variable rather than as
|
|
266
|
+
// the value it resolves to today, otherwise it stops tracking later edits
|
|
267
|
+
// to the preset. Reading the same list the popover renders is what keeps
|
|
268
|
+
// the two in step.
|
|
269
|
+
const shadowPresets = useShadowPresets( settings );
|
|
271
270
|
const setShadow = ( newValue ) => {
|
|
272
|
-
|
|
271
|
+
// The list runs default, theme, custom, so searching backwards picks
|
|
272
|
+
// the most specific origin when more than one defines the same shadow
|
|
273
|
+
// value — a newly added custom preset starts out identical to the
|
|
274
|
+
// `natural` default one, and it is the custom slug the user means.
|
|
275
|
+
const slug = shadowPresets.findLast(
|
|
273
276
|
( { shadow: shadowName } ) => shadowName === newValue
|
|
274
277
|
)?.slug;
|
|
275
278
|
|
|
@@ -369,7 +372,6 @@ export default function BorderPanel( {
|
|
|
369
372
|
showBorderRadius;
|
|
370
373
|
|
|
371
374
|
const label = useBorderPanelLabel( {
|
|
372
|
-
blockName: name,
|
|
373
375
|
hasShadowControl,
|
|
374
376
|
hasBorderControl,
|
|
375
377
|
} );
|
|
@@ -142,6 +142,7 @@ export default function ColorPanel( {
|
|
|
142
142
|
label,
|
|
143
143
|
children,
|
|
144
144
|
contrastWarning,
|
|
145
|
+
additionalElements,
|
|
145
146
|
showInheritanceLabelIndicators = isGlobalStylesInheritanceEnabled(),
|
|
146
147
|
} ) {
|
|
147
148
|
const {
|
|
@@ -259,8 +260,19 @@ export default function ColorPanel( {
|
|
|
259
260
|
label: __( 'H6' ),
|
|
260
261
|
showPanel: showHeadingPanel,
|
|
261
262
|
},
|
|
263
|
+
...( additionalElements?.map( ( element ) => ( {
|
|
264
|
+
...element,
|
|
265
|
+
showPanel: hasSolidColors || hasGradientColors,
|
|
266
|
+
} ) ) ?? [] ),
|
|
262
267
|
],
|
|
263
|
-
[
|
|
268
|
+
[
|
|
269
|
+
additionalElements,
|
|
270
|
+
hasGradientColors,
|
|
271
|
+
hasSolidColors,
|
|
272
|
+
showCaptionPanel,
|
|
273
|
+
showButtonPanel,
|
|
274
|
+
showHeadingPanel,
|
|
275
|
+
]
|
|
264
276
|
);
|
|
265
277
|
|
|
266
278
|
const resetAllFilter = useCallback(
|
|
@@ -347,6 +347,7 @@ export default function DimensionsPanel( {
|
|
|
347
347
|
// Special case because the layout controls are not part of the dimensions panel
|
|
348
348
|
// in global styles but not in block inspector.
|
|
349
349
|
includeLayoutControls = false,
|
|
350
|
+
allowAxialBlockGap = true,
|
|
350
351
|
styleState = DEFAULT_BLOCK_STYLE_STATE,
|
|
351
352
|
showInheritanceLabelIndicators = isGlobalStylesInheritanceEnabled(),
|
|
352
353
|
} ) {
|
|
@@ -556,9 +557,19 @@ export default function DimensionsPanel( {
|
|
|
556
557
|
? settings?.spacing?.blockGap
|
|
557
558
|
: settings?.spacing?.blockGap?.sides;
|
|
558
559
|
const isAxialGap =
|
|
559
|
-
|
|
560
|
+
allowAxialBlockGap &&
|
|
561
|
+
gapSides &&
|
|
562
|
+
gapSides.some( ( side ) => AXIAL_SIDES.includes( side ) );
|
|
560
563
|
const localGapRaw = decodeValue( value?.spacing?.blockGap );
|
|
561
564
|
const inheritedGapRaw = decodeValue( inheritedValue?.spacing?.blockGap );
|
|
565
|
+
const localGapForSingleInput =
|
|
566
|
+
! isAxialGap && typeof localGapRaw === 'object'
|
|
567
|
+
? localGapRaw?.top
|
|
568
|
+
: localGapRaw;
|
|
569
|
+
const inheritedGapForSingleInput =
|
|
570
|
+
! isAxialGap && typeof inheritedGapRaw === 'object'
|
|
571
|
+
? inheritedGapRaw?.top
|
|
572
|
+
: inheritedGapRaw;
|
|
562
573
|
// Merge local-then-inherited so SpacingSizesControl's chip slider and
|
|
563
574
|
// the axial-gap BoxControl reflect the local value when set and fall
|
|
564
575
|
// back to the inherited value at rest.
|
|
@@ -572,8 +583,8 @@ export default function DimensionsPanel( {
|
|
|
572
583
|
// at-rest cue for those.
|
|
573
584
|
const isGapPlaceholder =
|
|
574
585
|
! hasValue( value?.spacing?.blockGap ) &&
|
|
575
|
-
typeof
|
|
576
|
-
|
|
586
|
+
typeof inheritedGapForSingleInput === 'string' &&
|
|
587
|
+
inheritedGapForSingleInput !== '';
|
|
577
588
|
const setGapValue = ( newGapValue ) => {
|
|
578
589
|
onChange(
|
|
579
590
|
setImmutably( value, [ 'spacing', 'blockGap' ], newGapValue )
|
|
@@ -993,16 +1004,17 @@ export default function DimensionsPanel( {
|
|
|
993
1004
|
min={ 0 }
|
|
994
1005
|
onChange={ setGapValue }
|
|
995
1006
|
units={ units }
|
|
996
|
-
value={
|
|
1007
|
+
value={ localGapForSingleInput ?? undefined }
|
|
997
1008
|
placeholder={
|
|
998
1009
|
isGapPlaceholder
|
|
999
|
-
?
|
|
1010
|
+
? inheritedGapForSingleInput
|
|
1000
1011
|
: undefined
|
|
1001
1012
|
}
|
|
1002
1013
|
/>
|
|
1003
1014
|
) ) }
|
|
1004
1015
|
{ showSpacingPresetsControl && (
|
|
1005
1016
|
<SpacingSizesControl
|
|
1017
|
+
key={ isAxialGap ? 'axial-gap' : 'single-gap' }
|
|
1006
1018
|
label={ __( 'Block spacing' ) }
|
|
1007
1019
|
min={ 0 }
|
|
1008
1020
|
onChange={ setGapValues }
|
|
@@ -17,7 +17,10 @@ import { __, _x } from '@wordpress/i18n';
|
|
|
17
17
|
import { useCallback, useMemo, useRef } from '@wordpress/element';
|
|
18
18
|
import { reset as resetIcon } from '@wordpress/icons';
|
|
19
19
|
import { getValueFromVariable } from '@wordpress/global-styles-engine';
|
|
20
|
-
import {
|
|
20
|
+
import {
|
|
21
|
+
useToolsPanelDropdownMenuProps,
|
|
22
|
+
getDuotoneSlugFromPreset,
|
|
23
|
+
} from './utils';
|
|
21
24
|
import { setImmutably } from '../../utils/object';
|
|
22
25
|
import {
|
|
23
26
|
getInheritanceProps,
|
|
@@ -202,14 +205,24 @@ export default function FiltersPanel( {
|
|
|
202
205
|
const localDuotone = decodeValue( value?.filter?.duotone );
|
|
203
206
|
const inheritedDuotone = decodeValue( inheritedValue?.filter?.duotone );
|
|
204
207
|
const duotone = localDuotone ?? inheritedDuotone;
|
|
208
|
+
// Read from the raw value, since decoding resolves a preset reference to
|
|
209
|
+
// its colors and two presets can hold the same pair.
|
|
210
|
+
const localDuotoneSlug = getDuotoneSlugFromPreset( value?.filter?.duotone );
|
|
211
|
+
const inheritedDuotoneSlug = getDuotoneSlugFromPreset(
|
|
212
|
+
inheritedValue?.filter?.duotone
|
|
213
|
+
);
|
|
214
|
+
const duotoneSlug =
|
|
215
|
+
localDuotone !== undefined ? localDuotoneSlug : inheritedDuotoneSlug;
|
|
205
216
|
const isDuotonePlaceholder =
|
|
206
217
|
localDuotone === undefined && inheritedDuotone !== undefined;
|
|
207
|
-
const setDuotone = ( newValue ) => {
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
218
|
+
const setDuotone = ( newValue, slug ) => {
|
|
219
|
+
// A slug identifies the picked preset exactly. Falling back to a value
|
|
220
|
+
// match cannot tell two presets holding the same colors apart.
|
|
221
|
+
const presetSlug =
|
|
222
|
+
slug ??
|
|
223
|
+
duotonePalette.find( ( { colors } ) => colors === newValue )?.slug;
|
|
224
|
+
const duotoneValue = presetSlug
|
|
225
|
+
? `var:preset|duotone|${ presetSlug }`
|
|
213
226
|
: newValue;
|
|
214
227
|
onChange(
|
|
215
228
|
setImmutably( value, [ 'filter', 'duotone' ], duotoneValue )
|
|
@@ -217,16 +230,16 @@ export default function FiltersPanel( {
|
|
|
217
230
|
};
|
|
218
231
|
// Commit the inherited value when the user clicks the active preset
|
|
219
232
|
// while the picker is showing inherited duotone at rest.
|
|
220
|
-
const setDuotoneWithInheritedCommit = ( newValue ) => {
|
|
233
|
+
const setDuotoneWithInheritedCommit = ( newValue, index, slug ) => {
|
|
221
234
|
if (
|
|
222
235
|
newValue === undefined &&
|
|
223
236
|
isDuotonePlaceholder &&
|
|
224
237
|
inheritedDuotone !== undefined
|
|
225
238
|
) {
|
|
226
|
-
setDuotone( inheritedDuotone );
|
|
239
|
+
setDuotone( inheritedDuotone, inheritedDuotoneSlug );
|
|
227
240
|
return;
|
|
228
241
|
}
|
|
229
|
-
setDuotone( newValue );
|
|
242
|
+
setDuotone( newValue, slug );
|
|
230
243
|
};
|
|
231
244
|
const hasDuotone = () => !! value?.filter?.duotone;
|
|
232
245
|
const resetDuotone = () => setDuotone( undefined );
|
|
@@ -292,6 +305,7 @@ export default function FiltersPanel( {
|
|
|
292
305
|
disableCustomColors
|
|
293
306
|
disableCustomDuotone
|
|
294
307
|
value={ duotone }
|
|
308
|
+
selectedSlug={ duotoneSlug }
|
|
295
309
|
onChange={
|
|
296
310
|
setDuotoneWithInheritedCommit
|
|
297
311
|
}
|