@wordpress/block-editor 8.6.0 → 9.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 +7 -0
- package/README.md +4 -2
- package/build/components/block-alignment-control/constants.js +48 -0
- package/build/components/block-alignment-control/constants.js.map +1 -0
- package/build/components/block-alignment-control/ui.js +9 -40
- package/build/components/block-alignment-control/ui.js.map +1 -1
- package/build/components/block-alignment-control/ui.native.js +92 -0
- package/build/components/block-alignment-control/ui.native.js.map +1 -0
- package/build/components/block-list/use-block-props/use-block-class-names.js +1 -7
- package/build/components/block-list/use-block-props/use-block-class-names.js.map +1 -1
- package/build/components/block-navigation/dropdown.js +11 -5
- package/build/components/block-navigation/dropdown.js.map +1 -1
- package/build/components/block-popover/index.js +20 -5
- package/build/components/block-popover/index.js.map +1 -1
- package/build/components/color-style-selector/index.js +9 -0
- package/build/components/color-style-selector/index.js.map +1 -1
- package/build/components/index.js +0 -9
- package/build/components/index.js.map +1 -1
- package/build/components/inserter/index.js +21 -7
- package/build/components/inserter/index.js.map +1 -1
- package/build/components/inserter/index.native.js +1 -1
- package/build/components/inserter/index.native.js.map +1 -1
- package/build/components/inserter/quick-inserter.js +4 -5
- package/build/components/inserter/quick-inserter.js.map +1 -1
- package/build/components/list-view/block.js +15 -15
- package/build/components/list-view/block.js.map +1 -1
- package/build/components/list-view/branch.js +9 -13
- package/build/components/list-view/branch.js.map +1 -1
- package/build/components/list-view/context.js +1 -4
- package/build/components/list-view/context.js.map +1 -1
- package/build/components/list-view/index.js +15 -32
- package/build/components/list-view/index.js.map +1 -1
- package/build/components/url-input/index.js +7 -3
- package/build/components/url-input/index.js.map +1 -1
- package/build/components/use-setting/index.js +42 -18
- package/build/components/use-setting/index.js.map +1 -1
- package/build/components/writing-flow/use-click-selection.js +1 -3
- package/build/components/writing-flow/use-click-selection.js.map +1 -1
- package/build/components/writing-flow/use-selection-observer.js +49 -8
- package/build/components/writing-flow/use-selection-observer.js.map +1 -1
- package/build/hooks/dimensions.js +2 -2
- package/build/hooks/dimensions.js.map +1 -1
- package/build/hooks/index.js +2 -0
- package/build/hooks/index.js.map +1 -1
- package/build/hooks/margin.js +64 -12
- package/build/hooks/margin.js.map +1 -1
- package/build/hooks/padding.js +60 -12
- package/build/hooks/padding.js.map +1 -1
- package/build/hooks/settings.js +32 -0
- package/build/hooks/settings.js.map +1 -0
- package/build/store/defaults.js +0 -1
- package/build/store/defaults.js.map +1 -1
- package/build/store/selectors.js +14 -12
- package/build/store/selectors.js.map +1 -1
- package/build-module/components/block-alignment-control/constants.js +36 -0
- package/build-module/components/block-alignment-control/constants.js.map +1 -0
- package/build-module/components/block-alignment-control/ui.js +4 -35
- package/build-module/components/block-alignment-control/ui.js.map +1 -1
- package/build-module/components/block-alignment-control/ui.native.js +78 -0
- package/build-module/components/block-alignment-control/ui.native.js.map +1 -0
- package/build-module/components/block-list/use-block-props/use-block-class-names.js +1 -7
- package/build-module/components/block-list/use-block-props/use-block-class-names.js.map +1 -1
- package/build-module/components/block-navigation/dropdown.js +10 -5
- package/build-module/components/block-navigation/dropdown.js.map +1 -1
- package/build-module/components/block-popover/index.js +21 -5
- package/build-module/components/block-popover/index.js.map +1 -1
- package/build-module/components/color-style-selector/index.js +6 -0
- package/build-module/components/color-style-selector/index.js.map +1 -1
- package/build-module/components/index.js +0 -1
- package/build-module/components/index.js.map +1 -1
- package/build-module/components/inserter/index.js +21 -7
- package/build-module/components/inserter/index.js.map +1 -1
- package/build-module/components/inserter/index.native.js +1 -1
- package/build-module/components/inserter/index.native.js.map +1 -1
- package/build-module/components/inserter/quick-inserter.js +4 -5
- package/build-module/components/inserter/quick-inserter.js.map +1 -1
- package/build-module/components/list-view/block.js +15 -16
- package/build-module/components/list-view/block.js.map +1 -1
- package/build-module/components/list-view/branch.js +9 -13
- package/build-module/components/list-view/branch.js.map +1 -1
- package/build-module/components/list-view/context.js +1 -4
- package/build-module/components/list-view/context.js.map +1 -1
- package/build-module/components/list-view/index.js +15 -31
- package/build-module/components/list-view/index.js.map +1 -1
- package/build-module/components/url-input/index.js +7 -3
- package/build-module/components/url-input/index.js.map +1 -1
- package/build-module/components/use-setting/index.js +43 -19
- package/build-module/components/use-setting/index.js.map +1 -1
- package/build-module/components/writing-flow/use-click-selection.js +1 -3
- package/build-module/components/writing-flow/use-click-selection.js.map +1 -1
- package/build-module/components/writing-flow/use-selection-observer.js +49 -8
- package/build-module/components/writing-flow/use-selection-observer.js.map +1 -1
- package/build-module/hooks/dimensions.js +5 -5
- package/build-module/hooks/dimensions.js.map +1 -1
- package/build-module/hooks/index.js +1 -0
- package/build-module/hooks/index.js.map +1 -1
- package/build-module/hooks/margin.js +61 -13
- package/build-module/hooks/margin.js.map +1 -1
- package/build-module/hooks/padding.js +57 -13
- package/build-module/hooks/padding.js.map +1 -1
- package/build-module/hooks/settings.js +29 -0
- package/build-module/hooks/settings.js.map +1 -0
- package/build-module/store/defaults.js +0 -1
- package/build-module/store/defaults.js.map +1 -1
- package/build-module/store/selectors.js +14 -12
- package/build-module/store/selectors.js.map +1 -1
- package/build-style/style-rtl.css +17 -31
- package/build-style/style.css +17 -31
- package/package.json +28 -28
- package/src/components/block-alignment-control/constants.js +45 -0
- package/src/components/block-alignment-control/ui.js +69 -109
- package/src/components/block-alignment-control/ui.native.js +86 -0
- package/src/components/block-content-overlay/style.scss +0 -1
- package/src/components/block-list/style.scss +7 -18
- package/src/components/block-list/use-block-props/use-block-class-names.js +1 -11
- package/src/components/block-navigation/dropdown.js +12 -8
- package/src/components/block-popover/index.js +20 -3
- package/src/components/block-popover/style.scss +3 -0
- package/src/components/color-palette/test/__snapshots__/control.js.snap +1 -1
- package/src/components/color-style-selector/index.js +18 -9
- package/src/components/image-size-control/README.md +1 -1
- package/src/components/index.js +0 -1
- package/src/components/inserter/index.js +20 -0
- package/src/components/inserter/index.native.js +1 -1
- package/src/components/inserter/quick-inserter.js +3 -11
- package/src/components/inserter/style.native.scss +1 -0
- package/src/components/list-view/block.js +24 -34
- package/src/components/list-view/branch.js +10 -20
- package/src/components/list-view/context.js +1 -4
- package/src/components/list-view/index.js +11 -41
- package/src/components/url-input/index.js +6 -3
- package/src/components/use-setting/index.js +57 -21
- package/src/components/writing-flow/use-click-selection.js +1 -4
- package/src/components/writing-flow/use-selection-observer.js +55 -10
- package/src/hooks/dimensions.js +44 -38
- package/src/hooks/index.js +1 -0
- package/src/hooks/margin.js +64 -15
- package/src/hooks/padding.js +60 -15
- package/src/hooks/padding.scss +12 -0
- package/src/hooks/settings.js +32 -0
- package/src/hooks/test/settings.js +48 -0
- package/src/store/defaults.js +0 -1
- package/src/store/selectors.js +14 -12
- package/src/store/test/selectors.js +17 -0
- package/src/style.scss +1 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/build/components/border-style-control/index.js +0 -60
- package/build/components/border-style-control/index.js.map +0 -1
- package/build-module/components/border-style-control/index.js +0 -50
- package/build-module/components/border-style-control/index.js.map +0 -1
- package/src/components/border-style-control/index.js +0 -47
- package/src/components/border-style-control/style.scss +0 -18
|
@@ -7,7 +7,10 @@ import { get } from 'lodash';
|
|
|
7
7
|
* WordPress dependencies
|
|
8
8
|
*/
|
|
9
9
|
import { useSelect } from '@wordpress/data';
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
__EXPERIMENTAL_PATHS_WITH_MERGE as PATHS_WITH_MERGE,
|
|
12
|
+
hasBlockSupport,
|
|
13
|
+
} from '@wordpress/blocks';
|
|
11
14
|
|
|
12
15
|
/**
|
|
13
16
|
* Internal dependencies
|
|
@@ -91,8 +94,10 @@ const removeCustomPrefixes = ( path ) => {
|
|
|
91
94
|
};
|
|
92
95
|
|
|
93
96
|
/**
|
|
94
|
-
* Hook that retrieves the
|
|
95
|
-
*
|
|
97
|
+
* Hook that retrieves the given setting for the block instance in use.
|
|
98
|
+
*
|
|
99
|
+
* It looks up the settings first in the block instance hierarchy.
|
|
100
|
+
* If none is found, it'll look it up in the block editor store.
|
|
96
101
|
*
|
|
97
102
|
* @param {string} path The path to the setting.
|
|
98
103
|
* @return {any} Returns the value defined for the setting.
|
|
@@ -102,7 +107,7 @@ const removeCustomPrefixes = ( path ) => {
|
|
|
102
107
|
* ```
|
|
103
108
|
*/
|
|
104
109
|
export default function useSetting( path ) {
|
|
105
|
-
const { name: blockName } = useBlockEditContext();
|
|
110
|
+
const { name: blockName, clientId } = useBlockEditContext();
|
|
106
111
|
|
|
107
112
|
const setting = useSelect(
|
|
108
113
|
( select ) => {
|
|
@@ -113,28 +118,59 @@ export default function useSetting( path ) {
|
|
|
113
118
|
);
|
|
114
119
|
return undefined;
|
|
115
120
|
}
|
|
116
|
-
const settings = select( blockEditorStore ).getSettings();
|
|
117
121
|
|
|
118
|
-
|
|
119
|
-
// We cascade to the all value if the block one is not available.
|
|
122
|
+
let result;
|
|
120
123
|
const normalizedPath = removeCustomPrefixes( path );
|
|
121
|
-
const defaultsPath = `__experimentalFeatures.${ normalizedPath }`;
|
|
122
|
-
const blockPath = `__experimentalFeatures.blocks.${ blockName }.${ normalizedPath }`;
|
|
123
|
-
const experimentalFeaturesResult =
|
|
124
|
-
get( settings, blockPath ) ?? get( settings, defaultsPath );
|
|
125
124
|
|
|
126
|
-
|
|
125
|
+
// 1. Take settings from the block instance or its ancestors.
|
|
126
|
+
const candidates = [
|
|
127
|
+
...select( blockEditorStore ).getBlockParents( clientId ),
|
|
128
|
+
clientId, // The current block is added last, so it overwrites any ancestor.
|
|
129
|
+
];
|
|
130
|
+
candidates.forEach( ( candidateClientId ) => {
|
|
131
|
+
const candidateBlockName = select(
|
|
132
|
+
blockEditorStore
|
|
133
|
+
).getBlockName( candidateClientId );
|
|
134
|
+
if (
|
|
135
|
+
hasBlockSupport(
|
|
136
|
+
candidateBlockName,
|
|
137
|
+
'__experimentalSettings',
|
|
138
|
+
false
|
|
139
|
+
)
|
|
140
|
+
) {
|
|
141
|
+
const candidateAtts = select(
|
|
142
|
+
blockEditorStore
|
|
143
|
+
).getBlockAttributes( candidateClientId );
|
|
144
|
+
const candidateResult =
|
|
145
|
+
get(
|
|
146
|
+
candidateAtts,
|
|
147
|
+
`settings.blocks.${ blockName }.${ normalizedPath }`
|
|
148
|
+
) ??
|
|
149
|
+
get( candidateAtts, `settings.${ normalizedPath }` );
|
|
150
|
+
if ( candidateResult !== undefined ) {
|
|
151
|
+
result = candidateResult;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
} );
|
|
155
|
+
|
|
156
|
+
// 2. Fall back to the settings from the block editor store (__experimentalFeatures).
|
|
157
|
+
const settings = select( blockEditorStore ).getSettings();
|
|
158
|
+
if ( result === undefined ) {
|
|
159
|
+
const defaultsPath = `__experimentalFeatures.${ normalizedPath }`;
|
|
160
|
+
const blockPath = `__experimentalFeatures.blocks.${ blockName }.${ normalizedPath }`;
|
|
161
|
+
result =
|
|
162
|
+
get( settings, blockPath ) ?? get( settings, defaultsPath );
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Return if the setting was found in either the block instance or the store.
|
|
166
|
+
if ( result !== undefined ) {
|
|
127
167
|
if ( PATHS_WITH_MERGE[ normalizedPath ] ) {
|
|
128
|
-
return
|
|
129
|
-
experimentalFeaturesResult.custom ??
|
|
130
|
-
experimentalFeaturesResult.theme ??
|
|
131
|
-
experimentalFeaturesResult.default
|
|
132
|
-
);
|
|
168
|
+
return result.custom ?? result.theme ?? result.default;
|
|
133
169
|
}
|
|
134
|
-
return
|
|
170
|
+
return result;
|
|
135
171
|
}
|
|
136
172
|
|
|
137
|
-
//
|
|
173
|
+
// 3. Otherwise, use deprecated settings.
|
|
138
174
|
const deprecatedSettingsValue = deprecatedFlags[ normalizedPath ]
|
|
139
175
|
? deprecatedFlags[ normalizedPath ]( settings )
|
|
140
176
|
: undefined;
|
|
@@ -142,13 +178,13 @@ export default function useSetting( path ) {
|
|
|
142
178
|
return deprecatedSettingsValue;
|
|
143
179
|
}
|
|
144
180
|
|
|
145
|
-
//
|
|
181
|
+
// 4. Fallback for typography.dropCap:
|
|
146
182
|
// This is only necessary to support typography.dropCap.
|
|
147
183
|
// when __experimentalFeatures are not present (core without plugin).
|
|
148
184
|
// To remove when __experimentalFeatures are ported to core.
|
|
149
185
|
return normalizedPath === 'typography.dropCap' ? true : undefined;
|
|
150
186
|
},
|
|
151
|
-
[ blockName, path ]
|
|
187
|
+
[ blockName, clientId, path ]
|
|
152
188
|
);
|
|
153
189
|
|
|
154
190
|
return setting;
|
|
@@ -11,10 +11,9 @@ import { store as blockEditorStore } from '../../store';
|
|
|
11
11
|
import { getBlockClientId } from '../../utils/dom';
|
|
12
12
|
|
|
13
13
|
export default function useClickSelection() {
|
|
14
|
-
const {
|
|
14
|
+
const { selectBlock } = useDispatch( blockEditorStore );
|
|
15
15
|
const {
|
|
16
16
|
isSelectionEnabled,
|
|
17
|
-
getBlockParents,
|
|
18
17
|
getBlockSelectionStart,
|
|
19
18
|
hasMultiSelection,
|
|
20
19
|
} = useSelect( blockEditorStore );
|
|
@@ -54,10 +53,8 @@ export default function useClickSelection() {
|
|
|
54
53
|
};
|
|
55
54
|
},
|
|
56
55
|
[
|
|
57
|
-
multiSelect,
|
|
58
56
|
selectBlock,
|
|
59
57
|
isSelectionEnabled,
|
|
60
|
-
getBlockParents,
|
|
61
58
|
getBlockSelectionStart,
|
|
62
59
|
hasMultiSelection,
|
|
63
60
|
]
|
|
@@ -76,36 +76,81 @@ export default function useSelectionObserver() {
|
|
|
76
76
|
const { multiSelect, selectBlock, selectionChange } = useDispatch(
|
|
77
77
|
blockEditorStore
|
|
78
78
|
);
|
|
79
|
-
const { getBlockParents } = useSelect(
|
|
79
|
+
const { getBlockParents, getBlockSelectionStart } = useSelect(
|
|
80
|
+
blockEditorStore
|
|
81
|
+
);
|
|
80
82
|
return useRefEffect(
|
|
81
83
|
( node ) => {
|
|
82
84
|
const { ownerDocument } = node;
|
|
83
85
|
const { defaultView } = ownerDocument;
|
|
84
86
|
|
|
85
|
-
function onSelectionChange() {
|
|
87
|
+
function onSelectionChange( event ) {
|
|
86
88
|
const selection = defaultView.getSelection();
|
|
87
|
-
|
|
88
89
|
// If no selection is found, end multi selection and disable the
|
|
89
90
|
// contentEditable wrapper.
|
|
90
|
-
if ( ! selection.rangeCount
|
|
91
|
+
if ( ! selection.rangeCount ) {
|
|
92
|
+
setContentEditableWrapper( node, false );
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
// If selection is collapsed and we haven't used `shift+click`,
|
|
96
|
+
// end multi selection and disable the contentEditable wrapper.
|
|
97
|
+
// We have to check about `shift+click` case because elements
|
|
98
|
+
// that don't support text selection might be involved, and we might
|
|
99
|
+
// update the clientIds to multi-select blocks.
|
|
100
|
+
// For now we check if the event is a `mouse` event.
|
|
101
|
+
const isClickShift = event.shiftKey && event.type === 'mouseup';
|
|
102
|
+
if ( selection.isCollapsed && ! isClickShift ) {
|
|
91
103
|
setContentEditableWrapper( node, false );
|
|
92
104
|
return;
|
|
93
105
|
}
|
|
94
106
|
|
|
95
|
-
|
|
107
|
+
let startClientId = getBlockClientId(
|
|
96
108
|
extractSelectionStartNode( selection )
|
|
97
109
|
);
|
|
98
|
-
|
|
110
|
+
let endClientId = getBlockClientId(
|
|
99
111
|
extractSelectionEndNode( selection )
|
|
100
112
|
);
|
|
101
|
-
|
|
113
|
+
// If the selection has changed and we had pressed `shift+click`,
|
|
114
|
+
// we need to check if in an element that doesn't support
|
|
115
|
+
// text selection has been clicked.
|
|
116
|
+
if ( isClickShift ) {
|
|
117
|
+
const selectedClientId = getBlockSelectionStart();
|
|
118
|
+
const clickedClientId = getBlockClientId( event.target );
|
|
119
|
+
// `endClientId` is not defined if we end the selection by clicking a non-selectable block.
|
|
120
|
+
// We need to check if there was already a selection with a non-selectable focusNode.
|
|
121
|
+
const focusNodeIsNonSelectable =
|
|
122
|
+
clickedClientId !== endClientId;
|
|
123
|
+
if (
|
|
124
|
+
( startClientId === endClientId &&
|
|
125
|
+
selection.isCollapsed ) ||
|
|
126
|
+
! endClientId ||
|
|
127
|
+
focusNodeIsNonSelectable
|
|
128
|
+
) {
|
|
129
|
+
endClientId = clickedClientId;
|
|
130
|
+
}
|
|
131
|
+
// Handle the case when we have a non-selectable block
|
|
132
|
+
// selected and click another one.
|
|
133
|
+
if ( startClientId !== selectedClientId ) {
|
|
134
|
+
startClientId = selectedClientId;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// If the selection did not involve a block, return.
|
|
139
|
+
if (
|
|
140
|
+
startClientId === undefined &&
|
|
141
|
+
endClientId === undefined
|
|
142
|
+
) {
|
|
143
|
+
setContentEditableWrapper( node, false );
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
102
146
|
|
|
147
|
+
const isSingularSelection = startClientId === endClientId;
|
|
103
148
|
if ( isSingularSelection ) {
|
|
104
|
-
selectBlock(
|
|
149
|
+
selectBlock( startClientId );
|
|
105
150
|
} else {
|
|
106
151
|
const startPath = [
|
|
107
|
-
...getBlockParents(
|
|
108
|
-
|
|
152
|
+
...getBlockParents( startClientId ),
|
|
153
|
+
startClientId,
|
|
109
154
|
];
|
|
110
155
|
const endPath = [
|
|
111
156
|
...getBlockParents( endClientId ),
|
package/src/hooks/dimensions.js
CHANGED
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
} from './gap';
|
|
20
20
|
import {
|
|
21
21
|
MarginEdit,
|
|
22
|
+
MarginVisualizer,
|
|
22
23
|
hasMarginSupport,
|
|
23
24
|
hasMarginValue,
|
|
24
25
|
resetMargin,
|
|
@@ -26,6 +27,7 @@ import {
|
|
|
26
27
|
} from './margin';
|
|
27
28
|
import {
|
|
28
29
|
PaddingEdit,
|
|
30
|
+
PaddingVisualizer,
|
|
29
31
|
hasPaddingSupport,
|
|
30
32
|
hasPaddingValue,
|
|
31
33
|
resetPadding,
|
|
@@ -71,44 +73,48 @@ export function DimensionsPanel( props ) {
|
|
|
71
73
|
} );
|
|
72
74
|
|
|
73
75
|
return (
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
76
|
+
<>
|
|
77
|
+
<InspectorControls __experimentalGroup="dimensions">
|
|
78
|
+
{ ! isPaddingDisabled && (
|
|
79
|
+
<ToolsPanelItem
|
|
80
|
+
hasValue={ () => hasPaddingValue( props ) }
|
|
81
|
+
label={ __( 'Padding' ) }
|
|
82
|
+
onDeselect={ () => resetPadding( props ) }
|
|
83
|
+
resetAllFilter={ createResetAllFilter( 'padding' ) }
|
|
84
|
+
isShownByDefault={ defaultSpacingControls?.padding }
|
|
85
|
+
panelId={ props.clientId }
|
|
86
|
+
>
|
|
87
|
+
<PaddingEdit { ...props } />
|
|
88
|
+
</ToolsPanelItem>
|
|
89
|
+
) }
|
|
90
|
+
{ ! isMarginDisabled && (
|
|
91
|
+
<ToolsPanelItem
|
|
92
|
+
hasValue={ () => hasMarginValue( props ) }
|
|
93
|
+
label={ __( 'Margin' ) }
|
|
94
|
+
onDeselect={ () => resetMargin( props ) }
|
|
95
|
+
resetAllFilter={ createResetAllFilter( 'margin' ) }
|
|
96
|
+
isShownByDefault={ defaultSpacingControls?.margin }
|
|
97
|
+
panelId={ props.clientId }
|
|
98
|
+
>
|
|
99
|
+
<MarginEdit { ...props } />
|
|
100
|
+
</ToolsPanelItem>
|
|
101
|
+
) }
|
|
102
|
+
{ ! isGapDisabled && (
|
|
103
|
+
<ToolsPanelItem
|
|
104
|
+
hasValue={ () => hasGapValue( props ) }
|
|
105
|
+
label={ __( 'Block spacing' ) }
|
|
106
|
+
onDeselect={ () => resetGap( props ) }
|
|
107
|
+
resetAllFilter={ createResetAllFilter( 'blockGap' ) }
|
|
108
|
+
isShownByDefault={ defaultSpacingControls?.blockGap }
|
|
109
|
+
panelId={ props.clientId }
|
|
110
|
+
>
|
|
111
|
+
<GapEdit { ...props } />
|
|
112
|
+
</ToolsPanelItem>
|
|
113
|
+
) }
|
|
114
|
+
</InspectorControls>
|
|
115
|
+
{ ! isPaddingDisabled && <PaddingVisualizer { ...props } /> }
|
|
116
|
+
{ ! isMarginDisabled && <MarginVisualizer { ...props } /> }
|
|
117
|
+
</>
|
|
112
118
|
);
|
|
113
119
|
}
|
|
114
120
|
|
package/src/hooks/index.js
CHANGED
package/src/hooks/margin.js
CHANGED
|
@@ -2,12 +2,19 @@
|
|
|
2
2
|
* WordPress dependencies
|
|
3
3
|
*/
|
|
4
4
|
import { __ } from '@wordpress/i18n';
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
Platform,
|
|
7
|
+
useMemo,
|
|
8
|
+
useRef,
|
|
9
|
+
useState,
|
|
10
|
+
useEffect,
|
|
11
|
+
} from '@wordpress/element';
|
|
6
12
|
import { getBlockSupport } from '@wordpress/blocks';
|
|
7
13
|
import {
|
|
8
14
|
__experimentalUseCustomUnits as useCustomUnits,
|
|
9
15
|
__experimentalBoxControl as BoxControl,
|
|
10
16
|
} from '@wordpress/components';
|
|
17
|
+
import isShallowEqual from '@wordpress/is-shallow-equal';
|
|
11
18
|
|
|
12
19
|
/**
|
|
13
20
|
* Internal dependencies
|
|
@@ -20,6 +27,7 @@ import {
|
|
|
20
27
|
useIsDimensionsSupportValid,
|
|
21
28
|
} from './dimensions';
|
|
22
29
|
import { cleanEmptyObject } from './utils';
|
|
30
|
+
import BlockPopover from '../components/block-popover';
|
|
23
31
|
|
|
24
32
|
/**
|
|
25
33
|
* Determines if there is margin support.
|
|
@@ -124,26 +132,12 @@ export function MarginEdit( props ) {
|
|
|
124
132
|
} );
|
|
125
133
|
};
|
|
126
134
|
|
|
127
|
-
const onChangeShowVisualizer = ( next ) => {
|
|
128
|
-
const newStyle = {
|
|
129
|
-
...style,
|
|
130
|
-
visualizers: {
|
|
131
|
-
margin: next,
|
|
132
|
-
},
|
|
133
|
-
};
|
|
134
|
-
|
|
135
|
-
setAttributes( {
|
|
136
|
-
style: cleanEmptyObject( newStyle ),
|
|
137
|
-
} );
|
|
138
|
-
};
|
|
139
|
-
|
|
140
135
|
return Platform.select( {
|
|
141
136
|
web: (
|
|
142
137
|
<>
|
|
143
138
|
<BoxControl
|
|
144
139
|
values={ style?.spacing?.margin }
|
|
145
140
|
onChange={ onChange }
|
|
146
|
-
onChangeShowVisualizer={ onChangeShowVisualizer }
|
|
147
141
|
label={ __( 'Margin' ) }
|
|
148
142
|
sides={ sides }
|
|
149
143
|
units={ units }
|
|
@@ -155,3 +149,58 @@ export function MarginEdit( props ) {
|
|
|
155
149
|
native: null,
|
|
156
150
|
} );
|
|
157
151
|
}
|
|
152
|
+
|
|
153
|
+
export function MarginVisualizer( { clientId, attributes } ) {
|
|
154
|
+
const margin = attributes?.style?.spacing?.margin;
|
|
155
|
+
const style = useMemo( () => {
|
|
156
|
+
return {
|
|
157
|
+
borderTopWidth: margin?.top ?? 0,
|
|
158
|
+
borderRightWidth: margin?.right ?? 0,
|
|
159
|
+
borderBottomWidth: margin?.bottom ?? 0,
|
|
160
|
+
borderLeftWidth: margin?.left ?? 0,
|
|
161
|
+
top: margin?.top ? `-${ margin.top }` : 0,
|
|
162
|
+
right: margin?.right ? `-${ margin.right }` : 0,
|
|
163
|
+
bottom: margin?.bottom ? `-${ margin.bottom }` : 0,
|
|
164
|
+
left: margin?.left ? `-${ margin.left }` : 0,
|
|
165
|
+
};
|
|
166
|
+
}, [ margin ] );
|
|
167
|
+
|
|
168
|
+
const [ isActive, setIsActive ] = useState( false );
|
|
169
|
+
const valueRef = useRef( margin );
|
|
170
|
+
const timeoutRef = useRef();
|
|
171
|
+
|
|
172
|
+
const clearTimer = () => {
|
|
173
|
+
if ( timeoutRef.current ) {
|
|
174
|
+
window.clearTimeout( timeoutRef.current );
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
useEffect( () => {
|
|
179
|
+
if ( ! isShallowEqual( margin, valueRef.current ) ) {
|
|
180
|
+
setIsActive( true );
|
|
181
|
+
valueRef.current = margin;
|
|
182
|
+
|
|
183
|
+
clearTimer();
|
|
184
|
+
|
|
185
|
+
timeoutRef.current = setTimeout( () => {
|
|
186
|
+
setIsActive( false );
|
|
187
|
+
}, 400 );
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return () => clearTimer();
|
|
191
|
+
}, [ margin ] );
|
|
192
|
+
|
|
193
|
+
if ( ! isActive ) {
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return (
|
|
198
|
+
<BlockPopover
|
|
199
|
+
clientId={ clientId }
|
|
200
|
+
__unstableCoverTarget
|
|
201
|
+
__unstableRefreshSize={ margin }
|
|
202
|
+
>
|
|
203
|
+
<div className="block-editor__padding-visualizer" style={ style } />
|
|
204
|
+
</BlockPopover>
|
|
205
|
+
);
|
|
206
|
+
}
|
package/src/hooks/padding.js
CHANGED
|
@@ -2,12 +2,19 @@
|
|
|
2
2
|
* WordPress dependencies
|
|
3
3
|
*/
|
|
4
4
|
import { __ } from '@wordpress/i18n';
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
Platform,
|
|
7
|
+
useState,
|
|
8
|
+
useRef,
|
|
9
|
+
useEffect,
|
|
10
|
+
useMemo,
|
|
11
|
+
} from '@wordpress/element';
|
|
6
12
|
import { getBlockSupport } from '@wordpress/blocks';
|
|
7
13
|
import {
|
|
8
14
|
__experimentalUseCustomUnits as useCustomUnits,
|
|
9
15
|
__experimentalBoxControl as BoxControl,
|
|
10
16
|
} from '@wordpress/components';
|
|
17
|
+
import isShallowEqual from '@wordpress/is-shallow-equal';
|
|
11
18
|
|
|
12
19
|
/**
|
|
13
20
|
* Internal dependencies
|
|
@@ -20,6 +27,7 @@ import {
|
|
|
20
27
|
useIsDimensionsSupportValid,
|
|
21
28
|
} from './dimensions';
|
|
22
29
|
import { cleanEmptyObject } from './utils';
|
|
30
|
+
import BlockPopover from '../components/block-popover';
|
|
23
31
|
|
|
24
32
|
/**
|
|
25
33
|
* Determines if there is padding support.
|
|
@@ -124,26 +132,12 @@ export function PaddingEdit( props ) {
|
|
|
124
132
|
} );
|
|
125
133
|
};
|
|
126
134
|
|
|
127
|
-
const onChangeShowVisualizer = ( next ) => {
|
|
128
|
-
const newStyle = {
|
|
129
|
-
...style,
|
|
130
|
-
visualizers: {
|
|
131
|
-
padding: next,
|
|
132
|
-
},
|
|
133
|
-
};
|
|
134
|
-
|
|
135
|
-
setAttributes( {
|
|
136
|
-
style: cleanEmptyObject( newStyle ),
|
|
137
|
-
} );
|
|
138
|
-
};
|
|
139
|
-
|
|
140
135
|
return Platform.select( {
|
|
141
136
|
web: (
|
|
142
137
|
<>
|
|
143
138
|
<BoxControl
|
|
144
139
|
values={ style?.spacing?.padding }
|
|
145
140
|
onChange={ onChange }
|
|
146
|
-
onChangeShowVisualizer={ onChangeShowVisualizer }
|
|
147
141
|
label={ __( 'Padding' ) }
|
|
148
142
|
sides={ sides }
|
|
149
143
|
units={ units }
|
|
@@ -155,3 +149,54 @@ export function PaddingEdit( props ) {
|
|
|
155
149
|
native: null,
|
|
156
150
|
} );
|
|
157
151
|
}
|
|
152
|
+
|
|
153
|
+
export function PaddingVisualizer( { clientId, attributes } ) {
|
|
154
|
+
const padding = attributes?.style?.spacing?.padding;
|
|
155
|
+
const style = useMemo( () => {
|
|
156
|
+
return {
|
|
157
|
+
borderTopWidth: padding?.top ?? 0,
|
|
158
|
+
borderRightWidth: padding?.right ?? 0,
|
|
159
|
+
borderBottomWidth: padding?.bottom ?? 0,
|
|
160
|
+
borderLeftWidth: padding?.left ?? 0,
|
|
161
|
+
};
|
|
162
|
+
}, [ padding ] );
|
|
163
|
+
|
|
164
|
+
const [ isActive, setIsActive ] = useState( false );
|
|
165
|
+
const valueRef = useRef( padding );
|
|
166
|
+
const timeoutRef = useRef();
|
|
167
|
+
|
|
168
|
+
const clearTimer = () => {
|
|
169
|
+
if ( timeoutRef.current ) {
|
|
170
|
+
window.clearTimeout( timeoutRef.current );
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
useEffect( () => {
|
|
175
|
+
if ( ! isShallowEqual( padding, valueRef.current ) ) {
|
|
176
|
+
setIsActive( true );
|
|
177
|
+
valueRef.current = padding;
|
|
178
|
+
|
|
179
|
+
clearTimer();
|
|
180
|
+
|
|
181
|
+
timeoutRef.current = setTimeout( () => {
|
|
182
|
+
setIsActive( false );
|
|
183
|
+
}, 400 );
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return () => clearTimer();
|
|
187
|
+
}, [ padding ] );
|
|
188
|
+
|
|
189
|
+
if ( ! isActive ) {
|
|
190
|
+
return null;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
return (
|
|
194
|
+
<BlockPopover
|
|
195
|
+
clientId={ clientId }
|
|
196
|
+
__unstableCoverTarget
|
|
197
|
+
__unstableRefreshSize={ padding }
|
|
198
|
+
>
|
|
199
|
+
<div className="block-editor__padding-visualizer" style={ style } />
|
|
200
|
+
</BlockPopover>
|
|
201
|
+
);
|
|
202
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WordPress dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { addFilter } from '@wordpress/hooks';
|
|
5
|
+
import { hasBlockSupport } from '@wordpress/blocks';
|
|
6
|
+
|
|
7
|
+
const hasSettingsSupport = ( blockType ) =>
|
|
8
|
+
hasBlockSupport( blockType, '__experimentalSettings', false );
|
|
9
|
+
|
|
10
|
+
function addAttribute( settings ) {
|
|
11
|
+
if ( ! hasSettingsSupport( settings ) ) {
|
|
12
|
+
return settings;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// Allow blocks to specify their own attribute definition with default values if needed.
|
|
16
|
+
if ( ! settings?.attributes?.settings ) {
|
|
17
|
+
settings.attributes = {
|
|
18
|
+
...settings.attributes,
|
|
19
|
+
settings: {
|
|
20
|
+
type: 'object',
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return settings;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
addFilter(
|
|
29
|
+
'blocks.registerBlockType',
|
|
30
|
+
'core/settings/addAttribute',
|
|
31
|
+
addAttribute
|
|
32
|
+
);
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WordPress dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { applyFilters } from '@wordpress/hooks';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Internal dependencies
|
|
8
|
+
*/
|
|
9
|
+
import '../settings';
|
|
10
|
+
|
|
11
|
+
describe( 'with settings', () => {
|
|
12
|
+
const blockSettings = {
|
|
13
|
+
save: () => <div className="default" />,
|
|
14
|
+
category: 'text',
|
|
15
|
+
title: 'block title',
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
describe( 'addAttribute', () => {
|
|
19
|
+
const addAttribute = applyFilters.bind(
|
|
20
|
+
null,
|
|
21
|
+
'blocks.registerBlockType'
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
it( 'does not have settings att if settings block support is not enabled', () => {
|
|
25
|
+
const settings = addAttribute( {
|
|
26
|
+
...blockSettings,
|
|
27
|
+
supports: {
|
|
28
|
+
__experimentalSettings: false,
|
|
29
|
+
},
|
|
30
|
+
} );
|
|
31
|
+
|
|
32
|
+
expect( settings.attributes ).toBe( undefined );
|
|
33
|
+
} );
|
|
34
|
+
|
|
35
|
+
it( 'has settings att if settings block supports is enabled', () => {
|
|
36
|
+
const settings = addAttribute( {
|
|
37
|
+
...blockSettings,
|
|
38
|
+
supports: {
|
|
39
|
+
__experimentalSettings: true,
|
|
40
|
+
},
|
|
41
|
+
} );
|
|
42
|
+
|
|
43
|
+
expect( settings.attributes ).toStrictEqual( {
|
|
44
|
+
settings: { type: 'object' },
|
|
45
|
+
} );
|
|
46
|
+
} );
|
|
47
|
+
} );
|
|
48
|
+
} );
|
package/src/store/defaults.js
CHANGED
|
@@ -160,7 +160,6 @@ export const SETTINGS_DEFAULTS = {
|
|
|
160
160
|
__mobileEnablePageTemplates: false,
|
|
161
161
|
__experimentalBlockPatterns: [],
|
|
162
162
|
__experimentalBlockPatternCategories: [],
|
|
163
|
-
__experimentalSpotlightEntityBlocks: [],
|
|
164
163
|
__unstableGalleryWithImageBlocks: false,
|
|
165
164
|
|
|
166
165
|
generateAnchors: false,
|