@wordpress/block-editor 8.0.9 → 8.0.12
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/build/components/block-inspector/index.js +12 -2
- package/build/components/block-inspector/index.js.map +1 -1
- package/build/components/block-list/block.js +1 -1
- package/build/components/block-list/block.js.map +1 -1
- package/build/components/block-list/block.native.js +2 -3
- package/build/components/block-list/block.native.js.map +1 -1
- package/build/components/block-list/use-block-props/index.js +1 -3
- package/build/components/block-list/use-block-props/index.js.map +1 -1
- package/build/components/block-list/use-in-between-inserter.js +1 -1
- package/build/components/block-list/use-in-between-inserter.js.map +1 -1
- package/build/components/block-mobile-toolbar/block-actions-menu.native.js +2 -2
- package/build/components/block-mobile-toolbar/block-actions-menu.native.js.map +1 -1
- package/build/components/block-mover/button.js +2 -2
- package/build/components/block-mover/button.js.map +1 -1
- package/build/components/block-mover/index.js +2 -2
- package/build/components/block-mover/index.js.map +1 -1
- package/build/components/block-mover/index.native.js +2 -2
- package/build/components/block-mover/index.native.js.map +1 -1
- package/build/components/block-preview/index.js +51 -0
- package/build/components/block-preview/index.js.map +1 -1
- package/build/components/block-tools/block-selection-button.js +3 -3
- package/build/components/block-tools/block-selection-button.js.map +1 -1
- package/build/components/colors-gradients/control.js +1 -0
- package/build/components/colors-gradients/control.js.map +1 -1
- package/build/components/index.js +8 -1
- package/build/components/index.js.map +1 -1
- package/build/components/inserter/hooks/use-insertion-point.js +2 -2
- package/build/components/inserter/hooks/use-insertion-point.js.map +1 -1
- package/build/components/inserter/index.js +2 -2
- package/build/components/inserter/index.js.map +1 -1
- package/build/components/inserter/index.native.js +2 -2
- package/build/components/inserter/index.native.js.map +1 -1
- package/build/components/inserter/quick-inserter.js +1 -1
- package/build/components/inserter/quick-inserter.js.map +1 -1
- package/build/components/inspector-controls/block-support-tools-panel.js +50 -22
- package/build/components/inspector-controls/block-support-tools-panel.js.map +1 -1
- package/build/components/list-view/use-list-view-drop-zone.js +1 -1
- package/build/components/list-view/use-list-view-drop-zone.js.map +1 -1
- package/build/components/provider/use-block-sync.js +37 -10
- package/build/components/provider/use-block-sync.js.map +1 -1
- package/build/components/use-on-block-drop/index.js +1 -1
- package/build/components/use-on-block-drop/index.js.map +1 -1
- package/build/components/use-setting/index.js +7 -0
- package/build/components/use-setting/index.js.map +1 -1
- package/build/layouts/flex.js +3 -27
- package/build/layouts/flex.js.map +1 -1
- package/build/store/actions.js +3 -3
- package/build/store/actions.js.map +1 -1
- package/build/store/reducer.js +34 -83
- package/build/store/reducer.js.map +1 -1
- package/build/store/selectors.js +2 -2
- package/build/store/selectors.js.map +1 -1
- package/build/utils/transform-styles/index.js +2 -3
- package/build/utils/transform-styles/index.js.map +1 -1
- package/build-module/components/block-inspector/index.js +12 -2
- package/build-module/components/block-inspector/index.js.map +1 -1
- package/build-module/components/block-list/block.js +1 -1
- package/build-module/components/block-list/block.js.map +1 -1
- package/build-module/components/block-list/block.native.js +2 -3
- package/build-module/components/block-list/block.native.js.map +1 -1
- package/build-module/components/block-list/use-block-props/index.js +1 -3
- package/build-module/components/block-list/use-block-props/index.js.map +1 -1
- package/build-module/components/block-list/use-in-between-inserter.js +1 -1
- package/build-module/components/block-list/use-in-between-inserter.js.map +1 -1
- package/build-module/components/block-mobile-toolbar/block-actions-menu.native.js +2 -2
- package/build-module/components/block-mobile-toolbar/block-actions-menu.native.js.map +1 -1
- package/build-module/components/block-mover/button.js +2 -2
- package/build-module/components/block-mover/button.js.map +1 -1
- package/build-module/components/block-mover/index.js +2 -2
- package/build-module/components/block-mover/index.js.map +1 -1
- package/build-module/components/block-mover/index.native.js +2 -2
- package/build-module/components/block-mover/index.native.js.map +1 -1
- package/build-module/components/block-preview/index.js +46 -0
- package/build-module/components/block-preview/index.js.map +1 -1
- package/build-module/components/block-tools/block-selection-button.js +3 -3
- package/build-module/components/block-tools/block-selection-button.js.map +1 -1
- package/build-module/components/colors-gradients/control.js +1 -0
- package/build-module/components/colors-gradients/control.js.map +1 -1
- package/build-module/components/index.js +1 -1
- package/build-module/components/index.js.map +1 -1
- package/build-module/components/inserter/hooks/use-insertion-point.js +2 -2
- package/build-module/components/inserter/hooks/use-insertion-point.js.map +1 -1
- package/build-module/components/inserter/index.js +2 -2
- package/build-module/components/inserter/index.js.map +1 -1
- package/build-module/components/inserter/index.native.js +2 -2
- package/build-module/components/inserter/index.native.js.map +1 -1
- package/build-module/components/inserter/quick-inserter.js +1 -1
- package/build-module/components/inserter/quick-inserter.js.map +1 -1
- package/build-module/components/inspector-controls/block-support-tools-panel.js +50 -22
- package/build-module/components/inspector-controls/block-support-tools-panel.js.map +1 -1
- package/build-module/components/list-view/use-list-view-drop-zone.js +1 -1
- package/build-module/components/list-view/use-list-view-drop-zone.js.map +1 -1
- package/build-module/components/provider/use-block-sync.js +41 -14
- package/build-module/components/provider/use-block-sync.js.map +1 -1
- package/build-module/components/use-on-block-drop/index.js +1 -1
- package/build-module/components/use-on-block-drop/index.js.map +1 -1
- package/build-module/components/use-setting/index.js +7 -0
- package/build-module/components/use-setting/index.js.map +1 -1
- package/build-module/layouts/flex.js +3 -27
- package/build-module/layouts/flex.js.map +1 -1
- package/build-module/store/actions.js +3 -3
- package/build-module/store/actions.js.map +1 -1
- package/build-module/store/reducer.js +35 -84
- package/build-module/store/reducer.js.map +1 -1
- package/build-module/store/selectors.js +2 -2
- package/build-module/store/selectors.js.map +1 -1
- package/build-module/utils/transform-styles/index.js +2 -3
- package/build-module/utils/transform-styles/index.js.map +1 -1
- package/build-style/style-rtl.css +17 -2
- package/build-style/style.css +17 -2
- package/package.json +9 -9
- package/src/components/block-inspector/index.js +17 -1
- package/src/components/block-list/block.js +1 -1
- package/src/components/block-list/block.native.js +2 -2
- package/src/components/block-list/use-block-props/index.js +1 -3
- package/src/components/block-list/use-in-between-inserter.js +1 -1
- package/src/components/block-mobile-toolbar/block-actions-menu.native.js +2 -5
- package/src/components/block-mover/button.js +2 -6
- package/src/components/block-mover/index.js +2 -5
- package/src/components/block-mover/index.native.js +2 -5
- package/src/components/block-preview/index.js +60 -0
- package/src/components/block-preview/style.scss +23 -0
- package/src/components/block-preview/test/index.js +114 -0
- package/src/components/block-tools/block-selection-button.js +3 -9
- package/src/components/border-style-control/style.scss +3 -2
- package/src/components/color-palette/test/__snapshots__/control.js.snap +1 -0
- package/src/components/colors-gradients/control.js +3 -0
- package/src/components/index.js +4 -1
- package/src/components/inserter/hooks/use-insertion-point.js +2 -9
- package/src/components/inserter/index.js +2 -2
- package/src/components/inserter/index.native.js +2 -5
- package/src/components/inserter/quick-inserter.js +1 -1
- package/src/components/inspector-controls/block-support-tools-panel.js +57 -21
- package/src/components/list-view/use-list-view-drop-zone.js +1 -1
- package/src/components/provider/use-block-sync.js +45 -11
- package/src/components/use-on-block-drop/index.js +1 -4
- package/src/components/use-setting/index.js +9 -0
- package/src/layouts/flex.js +4 -25
- package/src/store/actions.js +3 -4
- package/src/store/reducer.js +36 -105
- package/src/store/selectors.js +2 -2
- package/src/store/test/reducer.js +35 -0
- package/src/store/test/selectors.js +1 -1
- package/src/utils/transform-styles/index.js +13 -16
|
@@ -11,37 +11,73 @@ import { store as blockEditorStore } from '../../store';
|
|
|
11
11
|
import { cleanEmptyObject } from '../../hooks/utils';
|
|
12
12
|
|
|
13
13
|
export default function BlockSupportToolsPanel( { children, group, label } ) {
|
|
14
|
-
const {
|
|
15
|
-
const {
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
const { attributes, clientIds, panelId } = useSelect( ( select ) => {
|
|
15
|
+
const {
|
|
16
|
+
getBlockAttributes,
|
|
17
|
+
getMultiSelectedBlockClientIds,
|
|
18
|
+
getSelectedBlockClientId,
|
|
19
|
+
hasMultiSelection,
|
|
20
|
+
} = select( blockEditorStore );
|
|
21
|
+
|
|
22
|
+
// When we currently have a multi-selection, the value returned from
|
|
23
|
+
// `getSelectedBlockClientId()` is `null`. When a `null` value is used
|
|
24
|
+
// for the `panelId`, a `ToolsPanel` will still allow panel items to
|
|
25
|
+
// register themselves despite their panelIds not matching.
|
|
18
26
|
const selectedBlockClientId = getSelectedBlockClientId();
|
|
19
27
|
|
|
28
|
+
if ( hasMultiSelection() ) {
|
|
29
|
+
const selectedBlockClientIds = getMultiSelectedBlockClientIds();
|
|
30
|
+
const selectedBlockAttributes = selectedBlockClientIds.reduce(
|
|
31
|
+
( blockAttributes, blockId ) => {
|
|
32
|
+
blockAttributes[ blockId ] = getBlockAttributes( blockId );
|
|
33
|
+
return blockAttributes;
|
|
34
|
+
},
|
|
35
|
+
{}
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
panelId: selectedBlockClientId,
|
|
40
|
+
clientIds: selectedBlockClientIds,
|
|
41
|
+
attributes: selectedBlockAttributes,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
20
45
|
return {
|
|
21
|
-
|
|
22
|
-
|
|
46
|
+
panelId: selectedBlockClientId,
|
|
47
|
+
clientIds: [ selectedBlockClientId ],
|
|
48
|
+
attributes: {
|
|
49
|
+
[ selectedBlockClientId ]: getBlockAttributes(
|
|
50
|
+
selectedBlockClientId
|
|
51
|
+
),
|
|
52
|
+
},
|
|
23
53
|
};
|
|
24
54
|
}, [] );
|
|
25
55
|
const { updateBlockAttributes } = useDispatch( blockEditorStore );
|
|
26
56
|
|
|
27
57
|
const resetAll = ( resetFilters = [] ) => {
|
|
28
|
-
const
|
|
29
|
-
|
|
58
|
+
const newAttributes = {};
|
|
59
|
+
|
|
60
|
+
clientIds.forEach( ( clientId ) => {
|
|
61
|
+
const { style } = attributes[ clientId ];
|
|
62
|
+
let newBlockAttributes = { style };
|
|
30
63
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
64
|
+
resetFilters.forEach( ( resetFilter ) => {
|
|
65
|
+
newBlockAttributes = {
|
|
66
|
+
...newBlockAttributes,
|
|
67
|
+
...resetFilter( newBlockAttributes ),
|
|
68
|
+
};
|
|
69
|
+
} );
|
|
70
|
+
|
|
71
|
+
// Enforce a cleaned style object.
|
|
72
|
+
newBlockAttributes = {
|
|
73
|
+
...newBlockAttributes,
|
|
74
|
+
style: cleanEmptyObject( newBlockAttributes.style ),
|
|
35
75
|
};
|
|
36
|
-
} );
|
|
37
76
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
...newAttributes,
|
|
41
|
-
style: cleanEmptyObject( newAttributes.style ),
|
|
42
|
-
};
|
|
77
|
+
newAttributes[ clientId ] = newBlockAttributes;
|
|
78
|
+
} );
|
|
43
79
|
|
|
44
|
-
updateBlockAttributes(
|
|
80
|
+
updateBlockAttributes( clientIds, newAttributes, true );
|
|
45
81
|
};
|
|
46
82
|
|
|
47
83
|
return (
|
|
@@ -49,8 +85,8 @@ export default function BlockSupportToolsPanel( { children, group, label } ) {
|
|
|
49
85
|
className={ `${ group }-block-support-panel` }
|
|
50
86
|
label={ label }
|
|
51
87
|
resetAll={ resetAll }
|
|
52
|
-
key={
|
|
53
|
-
panelId={
|
|
88
|
+
key={ panelId }
|
|
89
|
+
panelId={ panelId }
|
|
54
90
|
hasInnerWrapper={ true }
|
|
55
91
|
shouldRenderPlaceholderItems={ true } // Required to maintain fills ordering.
|
|
56
92
|
>
|
|
@@ -226,7 +226,7 @@ export default function useListViewDropZone() {
|
|
|
226
226
|
return {
|
|
227
227
|
clientId,
|
|
228
228
|
rootClientId,
|
|
229
|
-
blockIndex: getBlockIndex( clientId
|
|
229
|
+
blockIndex: getBlockIndex( clientId ),
|
|
230
230
|
element: blockElement,
|
|
231
231
|
isDraggedBlock: isBlockDrag
|
|
232
232
|
? draggedBlockClientIds.includes( clientId )
|
|
@@ -7,7 +7,7 @@ import { last, noop } from 'lodash';
|
|
|
7
7
|
* WordPress dependencies
|
|
8
8
|
*/
|
|
9
9
|
import { useEffect, useRef } from '@wordpress/element';
|
|
10
|
-
import { useRegistry } from '@wordpress/data';
|
|
10
|
+
import { useRegistry, useSelect } from '@wordpress/data';
|
|
11
11
|
import { cloneBlock } from '@wordpress/blocks';
|
|
12
12
|
|
|
13
13
|
/**
|
|
@@ -83,6 +83,15 @@ export default function useBlockSync( {
|
|
|
83
83
|
__unstableMarkNextChangeAsNotPersistent,
|
|
84
84
|
} = registry.dispatch( blockEditorStore );
|
|
85
85
|
const { getBlockName, getBlocks } = registry.select( blockEditorStore );
|
|
86
|
+
const isControlled = useSelect(
|
|
87
|
+
( select ) => {
|
|
88
|
+
return (
|
|
89
|
+
! clientId ||
|
|
90
|
+
select( blockEditorStore ).areInnerBlocksControlled( clientId )
|
|
91
|
+
);
|
|
92
|
+
},
|
|
93
|
+
[ clientId ]
|
|
94
|
+
);
|
|
86
95
|
|
|
87
96
|
const pendingChanges = useRef( { incoming: null, outgoing: [] } );
|
|
88
97
|
const subscribed = useRef( false );
|
|
@@ -97,15 +106,21 @@ export default function useBlockSync( {
|
|
|
97
106
|
// and so it would already be persisted.
|
|
98
107
|
__unstableMarkNextChangeAsNotPersistent();
|
|
99
108
|
if ( clientId ) {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
)
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
+
// It is important to batch here because otherwise,
|
|
110
|
+
// as soon as `setHasControlledInnerBlocks` is called
|
|
111
|
+
// the effect to restore might be triggered
|
|
112
|
+
// before the actual blocks get set properly in state.
|
|
113
|
+
registry.batch( () => {
|
|
114
|
+
setHasControlledInnerBlocks( clientId, true );
|
|
115
|
+
const storeBlocks = controlledBlocks.map( ( block ) =>
|
|
116
|
+
cloneBlock( block )
|
|
117
|
+
);
|
|
118
|
+
if ( subscribed.current ) {
|
|
119
|
+
pendingChanges.current.incoming = storeBlocks;
|
|
120
|
+
}
|
|
121
|
+
__unstableMarkNextChangeAsNotPersistent();
|
|
122
|
+
replaceInnerBlocks( clientId, storeBlocks );
|
|
123
|
+
} );
|
|
109
124
|
} else {
|
|
110
125
|
if ( subscribed.current ) {
|
|
111
126
|
pendingChanges.current.incoming = controlledBlocks;
|
|
@@ -157,6 +172,15 @@ export default function useBlockSync( {
|
|
|
157
172
|
}
|
|
158
173
|
}, [ controlledBlocks, clientId ] );
|
|
159
174
|
|
|
175
|
+
useEffect( () => {
|
|
176
|
+
// When the block becomes uncontrolled, it means its inner state has been reset
|
|
177
|
+
// we need to take the blocks again from the external value property.
|
|
178
|
+
if ( ! isControlled ) {
|
|
179
|
+
pendingChanges.current.outgoing = [];
|
|
180
|
+
setControlledBlocks();
|
|
181
|
+
}
|
|
182
|
+
}, [ isControlled ] );
|
|
183
|
+
|
|
160
184
|
useEffect( () => {
|
|
161
185
|
const {
|
|
162
186
|
getSelectionStart,
|
|
@@ -164,6 +188,7 @@ export default function useBlockSync( {
|
|
|
164
188
|
getSelectedBlocksInitialCaretPosition,
|
|
165
189
|
isLastBlockChangePersistent,
|
|
166
190
|
__unstableIsLastBlockChangeIgnored,
|
|
191
|
+
areInnerBlocksControlled,
|
|
167
192
|
} = registry.select( blockEditorStore );
|
|
168
193
|
|
|
169
194
|
let blocks = getBlocks( clientId );
|
|
@@ -182,8 +207,17 @@ export default function useBlockSync( {
|
|
|
182
207
|
if ( clientId !== null && getBlockName( clientId ) === null )
|
|
183
208
|
return;
|
|
184
209
|
|
|
185
|
-
|
|
210
|
+
// When RESET_BLOCKS on parent blocks get called, the controlled blocks
|
|
211
|
+
// can reset to uncontrolled, in these situations, it means we need to populate
|
|
212
|
+
// the blocks again from the external blocks (the value property here)
|
|
213
|
+
// and we should stop triggering onChange
|
|
214
|
+
const isStillControlled =
|
|
215
|
+
! clientId || areInnerBlocksControlled( clientId );
|
|
216
|
+
if ( ! isStillControlled ) {
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
186
219
|
|
|
220
|
+
const newIsPersistent = isLastBlockChangePersistent();
|
|
187
221
|
const newBlocks = getBlocks( clientId );
|
|
188
222
|
const areBlocksDifferent = newBlocks !== blocks;
|
|
189
223
|
blocks = newBlocks;
|
|
@@ -95,10 +95,7 @@ export function onBlockDrop(
|
|
|
95
95
|
|
|
96
96
|
// If the user is moving a block
|
|
97
97
|
if ( dropType === 'block' ) {
|
|
98
|
-
const sourceBlockIndex = getBlockIndex(
|
|
99
|
-
sourceClientIds[ 0 ],
|
|
100
|
-
sourceRootClientId
|
|
101
|
-
);
|
|
98
|
+
const sourceBlockIndex = getBlockIndex( sourceClientIds[ 0 ] );
|
|
102
99
|
|
|
103
100
|
// If the user is dropping to the same position, return early.
|
|
104
101
|
if (
|
|
@@ -15,6 +15,8 @@ import { __EXPERIMENTAL_PATHS_WITH_MERGE as PATHS_WITH_MERGE } from '@wordpress/
|
|
|
15
15
|
import { useBlockEditContext } from '../block-edit';
|
|
16
16
|
import { store as blockEditorStore } from '../../store';
|
|
17
17
|
|
|
18
|
+
const blockedPaths = [ 'color', 'border', 'typography', 'spacing' ];
|
|
19
|
+
|
|
18
20
|
const deprecatedFlags = {
|
|
19
21
|
'color.palette': ( settings ) =>
|
|
20
22
|
settings.colors === undefined ? undefined : settings.colors,
|
|
@@ -104,6 +106,13 @@ export default function useSetting( path ) {
|
|
|
104
106
|
|
|
105
107
|
const setting = useSelect(
|
|
106
108
|
( select ) => {
|
|
109
|
+
if ( blockedPaths.includes( path ) ) {
|
|
110
|
+
// eslint-disable-next-line no-console
|
|
111
|
+
console.warn(
|
|
112
|
+
'Top level useSetting paths are disabled. Please use a subpath to query the information needed.'
|
|
113
|
+
);
|
|
114
|
+
return undefined;
|
|
115
|
+
}
|
|
107
116
|
const settings = select( blockEditorStore ).getSettings();
|
|
108
117
|
|
|
109
118
|
// 1 - Use __experimental features, if available.
|
package/src/layouts/flex.js
CHANGED
|
@@ -85,10 +85,7 @@ export default {
|
|
|
85
85
|
);
|
|
86
86
|
},
|
|
87
87
|
save: function FlexLayoutStyle( { selector, layout } ) {
|
|
88
|
-
const {
|
|
89
|
-
orientation = 'horizontal',
|
|
90
|
-
setCascadingProperties = false,
|
|
91
|
-
} = layout;
|
|
88
|
+
const { orientation = 'horizontal' } = layout;
|
|
92
89
|
const blockGapSupport = useSetting( 'spacing.blockGap' );
|
|
93
90
|
const hasBlockGapStylesSupport = blockGapSupport !== null;
|
|
94
91
|
const justifyContent =
|
|
@@ -97,36 +94,18 @@ export default {
|
|
|
97
94
|
const flexWrap = flexWrapOptions.includes( layout.flexWrap )
|
|
98
95
|
? layout.flexWrap
|
|
99
96
|
: 'wrap';
|
|
100
|
-
|
|
97
|
+
const rowOrientation = `
|
|
101
98
|
flex-direction: row;
|
|
102
99
|
align-items: center;
|
|
103
100
|
justify-content: ${ justifyContent };
|
|
104
101
|
`;
|
|
105
|
-
if ( setCascadingProperties ) {
|
|
106
|
-
// --layout-justification-setting allows children to inherit the value
|
|
107
|
-
// regardless or row or column direction.
|
|
108
|
-
rowOrientation += `
|
|
109
|
-
--layout-justification-setting: ${ justifyContent };
|
|
110
|
-
--layout-direction: row;
|
|
111
|
-
--layout-wrap: ${ flexWrap };
|
|
112
|
-
--layout-justify: ${ justifyContent };
|
|
113
|
-
--layout-align: center;
|
|
114
|
-
`;
|
|
115
|
-
}
|
|
116
102
|
const alignItems =
|
|
117
103
|
alignItemsMap[ layout.justifyContent ] || alignItemsMap.left;
|
|
118
|
-
|
|
104
|
+
const columnOrientation = `
|
|
119
105
|
flex-direction: column;
|
|
120
106
|
align-items: ${ alignItems };
|
|
121
107
|
`;
|
|
122
|
-
|
|
123
|
-
columnOrientation += `
|
|
124
|
-
--layout-justification-setting: ${ alignItems };
|
|
125
|
-
--layout-direction: column;
|
|
126
|
-
--layout-justify: initial;
|
|
127
|
-
--layout-align: ${ alignItems };
|
|
128
|
-
`;
|
|
129
|
-
}
|
|
108
|
+
|
|
130
109
|
return (
|
|
131
110
|
<style>{ `
|
|
132
111
|
${ appendSelectors( selector ) } {
|
package/src/store/actions.js
CHANGED
|
@@ -1170,8 +1170,7 @@ export const duplicateBlocks = ( clientIds, updateSelection = true ) => ( {
|
|
|
1170
1170
|
|
|
1171
1171
|
const rootClientId = select.getBlockRootClientId( clientIds[ 0 ] );
|
|
1172
1172
|
const lastSelectedIndex = select.getBlockIndex(
|
|
1173
|
-
last( castArray( clientIds ) )
|
|
1174
|
-
rootClientId
|
|
1173
|
+
last( castArray( clientIds ) )
|
|
1175
1174
|
);
|
|
1176
1175
|
const clonedBlocks = blocks.map( ( block ) =>
|
|
1177
1176
|
__experimentalCloneSanitizedBlock( block )
|
|
@@ -1206,7 +1205,7 @@ export const insertBeforeBlock = ( clientId ) => ( { select, dispatch } ) => {
|
|
|
1206
1205
|
return;
|
|
1207
1206
|
}
|
|
1208
1207
|
|
|
1209
|
-
const firstSelectedIndex = select.getBlockIndex( clientId
|
|
1208
|
+
const firstSelectedIndex = select.getBlockIndex( clientId );
|
|
1210
1209
|
return dispatch.insertDefaultBlock( {}, rootClientId, firstSelectedIndex );
|
|
1211
1210
|
};
|
|
1212
1211
|
|
|
@@ -1225,7 +1224,7 @@ export const insertAfterBlock = ( clientId ) => ( { select, dispatch } ) => {
|
|
|
1225
1224
|
return;
|
|
1226
1225
|
}
|
|
1227
1226
|
|
|
1228
|
-
const firstSelectedIndex = select.getBlockIndex( clientId
|
|
1227
|
+
const firstSelectedIndex = select.getBlockIndex( clientId );
|
|
1229
1228
|
return dispatch.insertDefaultBlock(
|
|
1230
1229
|
{},
|
|
1231
1230
|
rootClientId,
|
package/src/store/reducer.js
CHANGED
|
@@ -14,7 +14,6 @@ import {
|
|
|
14
14
|
isEmpty,
|
|
15
15
|
identity,
|
|
16
16
|
omitBy,
|
|
17
|
-
pickBy,
|
|
18
17
|
} from 'lodash';
|
|
19
18
|
|
|
20
19
|
/**
|
|
@@ -122,48 +121,6 @@ function getFlattenedBlockAttributes( blocks ) {
|
|
|
122
121
|
return flattenBlocks( blocks, ( block ) => block.attributes );
|
|
123
122
|
}
|
|
124
123
|
|
|
125
|
-
/**
|
|
126
|
-
* Given a block order map object, returns *all* of the block client IDs that are
|
|
127
|
-
* a descendant of the given root client ID.
|
|
128
|
-
*
|
|
129
|
-
* Calling this with `rootClientId` set to `''` results in a list of client IDs
|
|
130
|
-
* that are in the post. That is, it excludes blocks like fetched reusable
|
|
131
|
-
* blocks which are stored into state but not visible. It also excludes
|
|
132
|
-
* InnerBlocks controllers, like template parts.
|
|
133
|
-
*
|
|
134
|
-
* It is important to exclude the full inner block controller and not just the
|
|
135
|
-
* inner blocks because in many cases, we need to persist the previous value of
|
|
136
|
-
* an inner block controller. To do so, it must be excluded from the list of
|
|
137
|
-
* client IDs which are considered to be part of the top-level entity.
|
|
138
|
-
*
|
|
139
|
-
* @param {Object} blocksOrder Object that maps block client IDs to a list of
|
|
140
|
-
* nested block client IDs.
|
|
141
|
-
* @param {?string} rootClientId The root client ID to search. Defaults to ''.
|
|
142
|
-
* @param {?Object} controlledInnerBlocks The InnerBlocks controller state.
|
|
143
|
-
*
|
|
144
|
-
* @return {Array} List of descendant client IDs.
|
|
145
|
-
*/
|
|
146
|
-
function getNestedBlockClientIds(
|
|
147
|
-
blocksOrder,
|
|
148
|
-
rootClientId = '',
|
|
149
|
-
controlledInnerBlocks = {}
|
|
150
|
-
) {
|
|
151
|
-
return reduce(
|
|
152
|
-
blocksOrder[ rootClientId ],
|
|
153
|
-
( result, clientId ) => {
|
|
154
|
-
if ( !! controlledInnerBlocks[ clientId ] ) {
|
|
155
|
-
return result;
|
|
156
|
-
}
|
|
157
|
-
return [
|
|
158
|
-
...result,
|
|
159
|
-
clientId,
|
|
160
|
-
...getNestedBlockClientIds( blocksOrder, clientId ),
|
|
161
|
-
];
|
|
162
|
-
},
|
|
163
|
-
[]
|
|
164
|
-
);
|
|
165
|
-
}
|
|
166
|
-
|
|
167
124
|
/**
|
|
168
125
|
* Returns an object against which it is safe to perform mutating operations,
|
|
169
126
|
* given the original object and its current working copy.
|
|
@@ -369,9 +326,14 @@ const withBlockTree = ( reducer ) => ( state = {}, action ) => {
|
|
|
369
326
|
...omit(
|
|
370
327
|
newState.tree,
|
|
371
328
|
action.replacedClientIds.concat(
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
329
|
+
// Controlled inner blocks are only removed
|
|
330
|
+
// if the block doesn't move to another position
|
|
331
|
+
// otherwise their content will be lost.
|
|
332
|
+
action.replacedClientIds
|
|
333
|
+
.filter( ( clientId ) => ! subTree[ clientId ] )
|
|
334
|
+
.map(
|
|
335
|
+
( clientId ) => 'controlled||' + clientId
|
|
336
|
+
)
|
|
375
337
|
)
|
|
376
338
|
),
|
|
377
339
|
...subTree,
|
|
@@ -637,70 +599,17 @@ const withInnerBlocksRemoveCascade = ( reducer ) => ( state, action ) => {
|
|
|
637
599
|
*/
|
|
638
600
|
const withBlockReset = ( reducer ) => ( state, action ) => {
|
|
639
601
|
if ( action.type === 'RESET_BLOCKS' ) {
|
|
640
|
-
/**
|
|
641
|
-
* A list of client IDs associated with the top level entity (like a
|
|
642
|
-
* post or template). It excludes the client IDs of blocks associated
|
|
643
|
-
* with other entities, like inner block controllers or reusable blocks.
|
|
644
|
-
*/
|
|
645
|
-
const visibleClientIds = getNestedBlockClientIds(
|
|
646
|
-
state?.order ?? {},
|
|
647
|
-
'',
|
|
648
|
-
state?.controlledInnerBlocks ?? {}
|
|
649
|
-
);
|
|
650
|
-
|
|
651
|
-
// pickBy returns only the truthy values from controlledInnerBlocks
|
|
652
|
-
const controlledInnerBlocks = Object.keys(
|
|
653
|
-
pickBy( state?.controlledInnerBlocks ?? {} )
|
|
654
|
-
);
|
|
655
|
-
|
|
656
|
-
/**
|
|
657
|
-
* Each update operation consists of a few parts:
|
|
658
|
-
* 1. First, the client IDs associated with the top level entity are
|
|
659
|
-
* removed from the existing state key, leaving in place controlled
|
|
660
|
-
* blocks (like reusable blocks and inner block controllers).
|
|
661
|
-
* 2. Second, the blocks from the reset action are used to calculate the
|
|
662
|
-
* individual state keys. This will re-populate the clientIDs which
|
|
663
|
-
* were removed in step 1.
|
|
664
|
-
* 3. In some cases, we remove the recalculated inner block controllers,
|
|
665
|
-
* letting their old values persist. We need to do this because the
|
|
666
|
-
* reset block action from a top-level entity is not aware of any
|
|
667
|
-
* inner blocks inside InnerBlock controllers. So if the new values
|
|
668
|
-
* were used, it would not take into account the existing InnerBlocks
|
|
669
|
-
* which already exist in the state for inner block controllers. For
|
|
670
|
-
* example, `attributes` uses the newly computed value for controllers
|
|
671
|
-
* since attributes are stored in the top-level entity. But `order`
|
|
672
|
-
* uses the previous value for the controllers since the new value
|
|
673
|
-
* does not include the order of controlled inner blocks. So if the
|
|
674
|
-
* new value was used, template parts would disappear from the editor
|
|
675
|
-
* whenever you try to undo a change in the top level entity.
|
|
676
|
-
*/
|
|
677
602
|
const newState = {
|
|
678
603
|
...state,
|
|
679
|
-
byClientId:
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
...omit( state?.attributes, visibleClientIds ),
|
|
685
|
-
...getFlattenedBlockAttributes( action.blocks ),
|
|
686
|
-
},
|
|
687
|
-
order: {
|
|
688
|
-
...omit( state?.order, visibleClientIds ),
|
|
689
|
-
...omit(
|
|
690
|
-
mapBlockOrder( action.blocks ),
|
|
691
|
-
controlledInnerBlocks
|
|
692
|
-
),
|
|
693
|
-
},
|
|
694
|
-
parents: {
|
|
695
|
-
...omit( state?.parents, visibleClientIds ),
|
|
696
|
-
...mapBlockParents( action.blocks ),
|
|
697
|
-
},
|
|
698
|
-
controlledInnerBlocks: state?.controlledInnerBlocks || {},
|
|
604
|
+
byClientId: getFlattenedBlocksWithoutAttributes( action.blocks ),
|
|
605
|
+
attributes: getFlattenedBlockAttributes( action.blocks ),
|
|
606
|
+
order: mapBlockOrder( action.blocks ),
|
|
607
|
+
parents: mapBlockParents( action.blocks ),
|
|
608
|
+
controlledInnerBlocks: {},
|
|
699
609
|
};
|
|
700
610
|
|
|
701
611
|
const subTree = buildBlockTree( newState, action.blocks );
|
|
702
612
|
newState.tree = {
|
|
703
|
-
...omit( state?.tree, visibleClientIds ),
|
|
704
613
|
...subTree,
|
|
705
614
|
// Root
|
|
706
615
|
'': {
|
|
@@ -828,6 +737,27 @@ const withSaveReusableBlock = ( reducer ) => ( state, action ) => {
|
|
|
828
737
|
|
|
829
738
|
return reducer( state, action );
|
|
830
739
|
};
|
|
740
|
+
/**
|
|
741
|
+
* Higher-order reducer which removes blocks from state when switching parent block controlled state.
|
|
742
|
+
*
|
|
743
|
+
* @param {Function} reducer Original reducer function.
|
|
744
|
+
*
|
|
745
|
+
* @return {Function} Enhanced reducer function.
|
|
746
|
+
*/
|
|
747
|
+
const withResetControlledBlocks = ( reducer ) => ( state, action ) => {
|
|
748
|
+
if ( action.type === 'SET_HAS_CONTROLLED_INNER_BLOCKS' ) {
|
|
749
|
+
// when switching a block from controlled to uncontrolled or inverse,
|
|
750
|
+
// we need to remove its content first.
|
|
751
|
+
const tempState = reducer( state, {
|
|
752
|
+
type: 'REPLACE_INNER_BLOCKS',
|
|
753
|
+
rootClientId: action.clientId,
|
|
754
|
+
blocks: [],
|
|
755
|
+
} );
|
|
756
|
+
return reducer( tempState, action );
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
return reducer( state, action );
|
|
760
|
+
};
|
|
831
761
|
|
|
832
762
|
/**
|
|
833
763
|
* Reducer returning the blocks state.
|
|
@@ -845,7 +775,8 @@ export const blocks = flow(
|
|
|
845
775
|
withReplaceInnerBlocks, // needs to be after withInnerBlocksRemoveCascade
|
|
846
776
|
withBlockReset,
|
|
847
777
|
withPersistentBlockChange,
|
|
848
|
-
withIgnoredBlockChange
|
|
778
|
+
withIgnoredBlockChange,
|
|
779
|
+
withResetControlledBlocks
|
|
849
780
|
)( {
|
|
850
781
|
byClientId( state = {}, action ) {
|
|
851
782
|
switch ( action.type ) {
|
package/src/store/selectors.js
CHANGED
|
@@ -890,11 +890,11 @@ export function getBlockOrder( state, rootClientId ) {
|
|
|
890
890
|
*
|
|
891
891
|
* @param {Object} state Editor state.
|
|
892
892
|
* @param {string} clientId Block client ID.
|
|
893
|
-
* @param {?string} rootClientId Optional root client ID of block list.
|
|
894
893
|
*
|
|
895
894
|
* @return {number} Index at which block exists in order.
|
|
896
895
|
*/
|
|
897
|
-
export function getBlockIndex( state, clientId
|
|
896
|
+
export function getBlockIndex( state, clientId ) {
|
|
897
|
+
const rootClientId = getBlockRootClientId( state, clientId );
|
|
898
898
|
return getBlockOrder( state, rootClientId ).indexOf( clientId );
|
|
899
899
|
}
|
|
900
900
|
|
|
@@ -2050,6 +2050,41 @@ describe( 'state', () => {
|
|
|
2050
2050
|
expect( state.isIgnoredChange ).toBe( true );
|
|
2051
2051
|
} );
|
|
2052
2052
|
} );
|
|
2053
|
+
|
|
2054
|
+
describe( 'controlledInnerBlocks', () => {
|
|
2055
|
+
it( 'should remove the content of the block if it switches from controlled to uncontrolled or opposite', () => {
|
|
2056
|
+
const original = blocks( undefined, {
|
|
2057
|
+
type: 'RESET_BLOCKS',
|
|
2058
|
+
blocks: [
|
|
2059
|
+
{
|
|
2060
|
+
clientId: 'chicken',
|
|
2061
|
+
name: 'core/test-block',
|
|
2062
|
+
attributes: {},
|
|
2063
|
+
innerBlocks: [
|
|
2064
|
+
{
|
|
2065
|
+
clientId: 'child',
|
|
2066
|
+
name: 'core/test-block',
|
|
2067
|
+
attributes: {},
|
|
2068
|
+
innerBlocks: [],
|
|
2069
|
+
},
|
|
2070
|
+
],
|
|
2071
|
+
},
|
|
2072
|
+
],
|
|
2073
|
+
} );
|
|
2074
|
+
|
|
2075
|
+
const state = blocks( original, {
|
|
2076
|
+
type: 'SET_HAS_CONTROLLED_INNER_BLOCKS',
|
|
2077
|
+
clientId: 'chicken',
|
|
2078
|
+
hasControlledInnerBlocks: true,
|
|
2079
|
+
} );
|
|
2080
|
+
|
|
2081
|
+
expect( state.controlledInnerBlocks.chicken ).toBe( true );
|
|
2082
|
+
// The previous content of the block should be removed
|
|
2083
|
+
expect( state.byClientId.child ).toBeUndefined();
|
|
2084
|
+
expect( state.tree.child ).toBeUndefined();
|
|
2085
|
+
expect( state.tree.chicken.innerBlocks ).toEqual( [] );
|
|
2086
|
+
} );
|
|
2087
|
+
} );
|
|
2053
2088
|
} );
|
|
2054
2089
|
} );
|
|
2055
2090
|
|
|
@@ -23,23 +23,20 @@ import wrap from './transforms/wrap';
|
|
|
23
23
|
* @return {Array} converted rules.
|
|
24
24
|
*/
|
|
25
25
|
const transformStyles = ( styles, wrapperClassName = '' ) => {
|
|
26
|
-
return map(
|
|
27
|
-
|
|
28
|
-
(
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
if ( baseURL ) {
|
|
34
|
-
transforms.push( urlRewrite( baseURL ) );
|
|
35
|
-
}
|
|
36
|
-
if ( transforms.length ) {
|
|
37
|
-
return traverse( css, compose( transforms ) );
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return css;
|
|
26
|
+
return map( styles, ( { css, baseURL } ) => {
|
|
27
|
+
const transforms = [];
|
|
28
|
+
if ( wrapperClassName ) {
|
|
29
|
+
transforms.push( wrap( wrapperClassName ) );
|
|
30
|
+
}
|
|
31
|
+
if ( baseURL ) {
|
|
32
|
+
transforms.push( urlRewrite( baseURL ) );
|
|
41
33
|
}
|
|
42
|
-
|
|
34
|
+
if ( transforms.length ) {
|
|
35
|
+
return traverse( css, compose( transforms ) );
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return css;
|
|
39
|
+
} );
|
|
43
40
|
};
|
|
44
41
|
|
|
45
42
|
export default transformStyles;
|