@wordpress/block-editor 10.0.2 → 10.1.1-next.4d3b314fd5.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 +2 -0
- package/build/components/block-draggable/index.js +1 -1
- package/build/components/block-draggable/index.js.map +1 -1
- package/build/components/block-list/index.js +19 -5
- package/build/components/block-list/index.js.map +1 -1
- package/build/components/block-list/use-block-props/index.js +7 -1
- package/build/components/block-list/use-block-props/index.js.map +1 -1
- package/build/components/block-list/use-in-between-inserter.js +14 -5
- package/build/components/block-list/use-in-between-inserter.js.map +1 -1
- package/build/components/block-popover/inbetween.js +24 -9
- package/build/components/block-popover/inbetween.js.map +1 -1
- package/build/components/block-popover/index.js +29 -3
- package/build/components/block-popover/index.js.map +1 -1
- package/build/components/block-preview/auto.js +23 -11
- package/build/components/block-preview/auto.js.map +1 -1
- package/build/components/block-styles/index.js +1 -3
- package/build/components/block-styles/index.js.map +1 -1
- package/build/components/block-tools/index.js +18 -13
- package/build/components/block-tools/index.js.map +1 -1
- package/build/components/block-tools/insertion-point.js +5 -3
- package/build/components/block-tools/insertion-point.js.map +1 -1
- package/build/components/block-tools/use-block-toolbar-popover-props.js +6 -3
- package/build/components/block-tools/use-block-toolbar-popover-props.js.map +1 -1
- package/build/components/block-variation-picker/index.native.js +2 -1
- package/build/components/block-variation-picker/index.native.js.map +1 -1
- package/build/components/button-block-appender/index.native.js +1 -0
- package/build/components/button-block-appender/index.native.js.map +1 -1
- package/build/components/index.js +9 -0
- package/build/components/index.js.map +1 -1
- package/build/components/list-view/index.js +2 -1
- package/build/components/list-view/index.js.map +1 -1
- package/build/components/rich-text/format-toolbar-container.js +8 -1
- package/build/components/rich-text/format-toolbar-container.js.map +1 -1
- package/build/components/rich-text/index.js +12 -0
- package/build/components/rich-text/index.js.map +1 -1
- package/build/components/url-input/index.js +1 -3
- package/build/components/url-input/index.js.map +1 -1
- package/build/components/url-popover/image-url-input-ui.js +1 -1
- package/build/components/url-popover/image-url-input-ui.js.map +1 -1
- package/build/components/use-block-drop-zone/index.js +19 -1
- package/build/components/use-block-drop-zone/index.js.map +1 -1
- package/build/components/use-on-block-drop/index.js +62 -20
- package/build/components/use-on-block-drop/index.js.map +1 -1
- package/build/components/use-setting/index.js +16 -12
- package/build/components/use-setting/index.js.map +1 -1
- package/build/components/writing-flow/use-arrow-nav.js +21 -8
- package/build/components/writing-flow/use-arrow-nav.js.map +1 -1
- package/build/hooks/index.js +13 -1
- package/build/hooks/index.js.map +1 -1
- package/build/hooks/layout.js +76 -23
- package/build/hooks/layout.js.map +1 -1
- package/build/index.js +14 -0
- package/build/index.js.map +1 -1
- package/build/store/reducer.js +33 -19
- package/build/store/reducer.js.map +1 -1
- package/build/store/selectors.js +5 -5
- package/build/store/selectors.js.map +1 -1
- package/build-module/components/block-draggable/index.js +1 -1
- package/build-module/components/block-draggable/index.js.map +1 -1
- package/build-module/components/block-list/index.js +22 -8
- package/build-module/components/block-list/index.js.map +1 -1
- package/build-module/components/block-list/use-block-props/index.js +8 -2
- 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 +15 -6
- package/build-module/components/block-list/use-in-between-inserter.js.map +1 -1
- package/build-module/components/block-popover/inbetween.js +24 -9
- package/build-module/components/block-popover/inbetween.js.map +1 -1
- package/build-module/components/block-popover/index.js +29 -4
- package/build-module/components/block-popover/index.js.map +1 -1
- package/build-module/components/block-preview/auto.js +22 -10
- package/build-module/components/block-preview/auto.js.map +1 -1
- package/build-module/components/block-styles/index.js +1 -2
- package/build-module/components/block-styles/index.js.map +1 -1
- package/build-module/components/block-tools/index.js +18 -12
- package/build-module/components/block-tools/index.js.map +1 -1
- package/build-module/components/block-tools/insertion-point.js +5 -3
- package/build-module/components/block-tools/insertion-point.js.map +1 -1
- package/build-module/components/block-tools/use-block-toolbar-popover-props.js +6 -3
- package/build-module/components/block-tools/use-block-toolbar-popover-props.js.map +1 -1
- package/build-module/components/block-variation-picker/index.native.js +2 -1
- package/build-module/components/block-variation-picker/index.native.js.map +1 -1
- package/build-module/components/button-block-appender/index.native.js +1 -0
- package/build-module/components/button-block-appender/index.native.js.map +1 -1
- package/build-module/components/index.js +1 -0
- package/build-module/components/index.js.map +1 -1
- package/build-module/components/list-view/index.js +2 -1
- package/build-module/components/list-view/index.js.map +1 -1
- package/build-module/components/rich-text/format-toolbar-container.js +6 -1
- package/build-module/components/rich-text/format-toolbar-container.js.map +1 -1
- package/build-module/components/rich-text/index.js +12 -0
- package/build-module/components/rich-text/index.js.map +1 -1
- package/build-module/components/url-input/index.js +1 -2
- package/build-module/components/url-input/index.js.map +1 -1
- package/build-module/components/url-popover/image-url-input-ui.js +1 -1
- package/build-module/components/url-popover/image-url-input-ui.js.map +1 -1
- package/build-module/components/use-block-drop-zone/index.js +19 -1
- package/build-module/components/use-block-drop-zone/index.js.map +1 -1
- package/build-module/components/use-on-block-drop/index.js +62 -21
- package/build-module/components/use-on-block-drop/index.js.map +1 -1
- package/build-module/components/use-setting/index.js +16 -12
- package/build-module/components/use-setting/index.js.map +1 -1
- package/build-module/components/writing-flow/use-arrow-nav.js +22 -9
- package/build-module/components/writing-flow/use-arrow-nav.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/layout.js +73 -23
- package/build-module/hooks/layout.js.map +1 -1
- package/build-module/index.js +1 -1
- package/build-module/index.js.map +1 -1
- package/build-module/store/reducer.js +29 -18
- package/build-module/store/reducer.js.map +1 -1
- package/build-module/store/selectors.js +5 -5
- package/build-module/store/selectors.js.map +1 -1
- package/build-style/style-rtl.css +24 -6
- package/build-style/style.css +24 -6
- package/package.json +29 -29
- package/src/components/block-controls/test/index.js +84 -8
- package/src/components/block-draggable/index.js +1 -1
- package/src/components/block-draggable/test/index.native.js +0 -9
- package/src/components/block-list/index.js +42 -6
- package/src/components/block-list/use-block-props/index.js +6 -1
- package/src/components/block-list/use-in-between-inserter.js +14 -8
- package/src/components/block-mover/style.scss +2 -7
- package/src/components/block-popover/inbetween.js +34 -10
- package/src/components/block-popover/index.js +47 -3
- package/src/components/block-preview/auto.js +77 -65
- package/src/components/block-preview/style.scss +13 -0
- package/src/components/block-styles/index.js +1 -2
- package/src/components/block-tools/index.js +16 -10
- package/src/components/block-tools/insertion-point.js +3 -3
- package/src/components/block-tools/use-block-toolbar-popover-props.js +6 -0
- package/src/components/block-variation-picker/index.native.js +1 -0
- package/src/components/button-block-appender/index.native.js +1 -0
- package/src/components/index.js +1 -0
- package/src/components/link-control/test/index.js +1 -2
- package/src/components/list-view/index.js +1 -0
- package/src/components/rich-text/format-toolbar-container.js +8 -2
- package/src/components/rich-text/index.js +14 -0
- package/src/components/url-input/index.js +6 -2
- package/src/components/url-popover/image-url-input-ui.js +1 -1
- package/src/components/use-block-drop-zone/index.js +26 -1
- package/src/components/use-on-block-drop/index.js +110 -35
- package/src/components/use-on-block-drop/test/index.js +33 -43
- package/src/components/use-setting/index.js +18 -16
- package/src/components/warning/style.scss +1 -0
- package/src/components/writing-flow/use-arrow-nav.js +23 -9
- package/src/hooks/index.js +1 -0
- package/src/hooks/layout.js +64 -21
- package/src/index.js +2 -0
- package/src/store/reducer.js +22 -14
- package/src/store/selectors.js +5 -4
- package/src/store/test/reducer.js +0 -17
- package/src/components/block-controls/test/__snapshots__/index.js.snap +0 -64
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* WordPress dependencies
|
|
3
3
|
*/
|
|
4
|
+
import { useCallback } from '@wordpress/element';
|
|
4
5
|
import {
|
|
5
6
|
cloneBlock,
|
|
6
7
|
findTransform,
|
|
7
8
|
getBlockTransforms,
|
|
8
9
|
pasteHandler,
|
|
9
10
|
} from '@wordpress/blocks';
|
|
10
|
-
import { useDispatch, useSelect } from '@wordpress/data';
|
|
11
|
+
import { useDispatch, useSelect, useRegistry } from '@wordpress/data';
|
|
11
12
|
import { getFilesFromDataTransfer } from '@wordpress/dom';
|
|
12
13
|
|
|
13
14
|
/**
|
|
@@ -56,8 +57,8 @@ export function parseDropEvent( event ) {
|
|
|
56
57
|
* @param {number} targetBlockIndex The index where the block(s) will be inserted.
|
|
57
58
|
* @param {Function} getBlockIndex A function that gets the index of a block.
|
|
58
59
|
* @param {Function} getClientIdsOfDescendants A function that gets the client ids of descendant blocks.
|
|
59
|
-
* @param {Function}
|
|
60
|
-
* @param {Function}
|
|
60
|
+
* @param {Function} moveBlocks A function that moves blocks.
|
|
61
|
+
* @param {Function} insertOrReplaceBlocks A function that inserts or replaces blocks.
|
|
61
62
|
* @param {Function} clearSelectedBlock A function that clears block selection.
|
|
62
63
|
* @return {Function} The event handler for a block drop event.
|
|
63
64
|
*/
|
|
@@ -66,8 +67,8 @@ export function onBlockDrop(
|
|
|
66
67
|
targetBlockIndex,
|
|
67
68
|
getBlockIndex,
|
|
68
69
|
getClientIdsOfDescendants,
|
|
69
|
-
|
|
70
|
-
|
|
70
|
+
moveBlocks,
|
|
71
|
+
insertOrReplaceBlocks,
|
|
71
72
|
clearSelectedBlock
|
|
72
73
|
) {
|
|
73
74
|
return ( event ) => {
|
|
@@ -84,13 +85,7 @@ export function onBlockDrop(
|
|
|
84
85
|
const blocksToInsert = blocks.map( ( block ) =>
|
|
85
86
|
cloneBlock( block )
|
|
86
87
|
);
|
|
87
|
-
|
|
88
|
-
blocksToInsert,
|
|
89
|
-
targetBlockIndex,
|
|
90
|
-
targetRootClientId,
|
|
91
|
-
true,
|
|
92
|
-
null
|
|
93
|
-
);
|
|
88
|
+
insertOrReplaceBlocks( blocksToInsert, true, null );
|
|
94
89
|
}
|
|
95
90
|
|
|
96
91
|
// If the user is moving a block.
|
|
@@ -128,12 +123,7 @@ export function onBlockDrop(
|
|
|
128
123
|
? targetBlockIndex - draggedBlockCount
|
|
129
124
|
: targetBlockIndex;
|
|
130
125
|
|
|
131
|
-
|
|
132
|
-
sourceClientIds,
|
|
133
|
-
sourceRootClientId,
|
|
134
|
-
targetRootClientId,
|
|
135
|
-
insertIndex
|
|
136
|
-
);
|
|
126
|
+
moveBlocks( sourceClientIds, sourceRootClientId, insertIndex );
|
|
137
127
|
}
|
|
138
128
|
};
|
|
139
129
|
}
|
|
@@ -146,7 +136,7 @@ export function onBlockDrop(
|
|
|
146
136
|
* @param {boolean} hasUploadPermissions Whether the user has upload permissions.
|
|
147
137
|
* @param {Function} updateBlockAttributes A function that updates a block's attributes.
|
|
148
138
|
* @param {Function} canInsertBlockType A function that returns checks whether a block type can be inserted.
|
|
149
|
-
* @param {Function}
|
|
139
|
+
* @param {Function} insertOrReplaceBlocks A function that inserts or replaces blocks.
|
|
150
140
|
*
|
|
151
141
|
* @return {Function} The event handler for a block-related file drop event.
|
|
152
142
|
*/
|
|
@@ -156,7 +146,7 @@ export function onFilesDrop(
|
|
|
156
146
|
hasUploadPermissions,
|
|
157
147
|
updateBlockAttributes,
|
|
158
148
|
canInsertBlockType,
|
|
159
|
-
|
|
149
|
+
insertOrReplaceBlocks
|
|
160
150
|
) {
|
|
161
151
|
return ( files ) => {
|
|
162
152
|
if ( ! hasUploadPermissions ) {
|
|
@@ -176,7 +166,7 @@ export function onFilesDrop(
|
|
|
176
166
|
files,
|
|
177
167
|
updateBlockAttributes
|
|
178
168
|
);
|
|
179
|
-
|
|
169
|
+
insertOrReplaceBlocks( blocks );
|
|
180
170
|
}
|
|
181
171
|
};
|
|
182
172
|
}
|
|
@@ -184,22 +174,22 @@ export function onFilesDrop(
|
|
|
184
174
|
/**
|
|
185
175
|
* A function that returns an event handler function for block-related HTML drop events.
|
|
186
176
|
*
|
|
187
|
-
* @param {string} targetRootClientId
|
|
188
|
-
* @param {number} targetBlockIndex
|
|
189
|
-
* @param {Function}
|
|
177
|
+
* @param {string} targetRootClientId The root client id where the block(s) will be inserted.
|
|
178
|
+
* @param {number} targetBlockIndex The index where the block(s) will be inserted.
|
|
179
|
+
* @param {Function} insertOrReplaceBlocks A function that inserts or replaces blocks.
|
|
190
180
|
*
|
|
191
181
|
* @return {Function} The event handler for a block-related HTML drop event.
|
|
192
182
|
*/
|
|
193
183
|
export function onHTMLDrop(
|
|
194
184
|
targetRootClientId,
|
|
195
185
|
targetBlockIndex,
|
|
196
|
-
|
|
186
|
+
insertOrReplaceBlocks
|
|
197
187
|
) {
|
|
198
188
|
return ( HTML ) => {
|
|
199
189
|
const blocks = pasteHandler( { HTML, mode: 'BLOCKS' } );
|
|
200
190
|
|
|
201
191
|
if ( blocks.length ) {
|
|
202
|
-
|
|
192
|
+
insertOrReplaceBlocks( blocks );
|
|
203
193
|
}
|
|
204
194
|
};
|
|
205
195
|
}
|
|
@@ -207,32 +197,117 @@ export function onHTMLDrop(
|
|
|
207
197
|
/**
|
|
208
198
|
* A React hook for handling block drop events.
|
|
209
199
|
*
|
|
210
|
-
* @
|
|
211
|
-
*
|
|
200
|
+
* @typedef {'insert'|'replace'} DropAction The type of action to perform on drop.
|
|
201
|
+
*
|
|
202
|
+
* @param {string} targetRootClientId The root client id where the block(s) will be inserted.
|
|
203
|
+
* @param {number} targetBlockIndex The index where the block(s) will be inserted.
|
|
204
|
+
* @param {Object} options The optional options.
|
|
205
|
+
* @param {DropAction} options.action The type of action to perform on drop. Could be `insert` or `replace` for now.
|
|
212
206
|
*
|
|
213
207
|
* @return {Object} An object that contains the event handlers `onDrop`, `onFilesDrop` and `onHTMLDrop`.
|
|
214
208
|
*/
|
|
215
|
-
export default function useOnBlockDrop(
|
|
209
|
+
export default function useOnBlockDrop(
|
|
210
|
+
targetRootClientId,
|
|
211
|
+
targetBlockIndex,
|
|
212
|
+
options = {}
|
|
213
|
+
) {
|
|
214
|
+
const { action = 'insert' } = options;
|
|
216
215
|
const hasUploadPermissions = useSelect(
|
|
217
216
|
( select ) => select( blockEditorStore ).getSettings().mediaUpload,
|
|
218
217
|
[]
|
|
219
218
|
);
|
|
220
|
-
const {
|
|
221
|
-
|
|
219
|
+
const {
|
|
220
|
+
canInsertBlockType,
|
|
221
|
+
getBlockIndex,
|
|
222
|
+
getClientIdsOfDescendants,
|
|
223
|
+
getBlockOrder,
|
|
224
|
+
getBlocksByClientId,
|
|
225
|
+
} = useSelect( blockEditorStore );
|
|
222
226
|
const {
|
|
223
227
|
insertBlocks,
|
|
224
228
|
moveBlocksToPosition,
|
|
225
229
|
updateBlockAttributes,
|
|
226
230
|
clearSelectedBlock,
|
|
231
|
+
replaceBlocks,
|
|
232
|
+
removeBlocks,
|
|
227
233
|
} = useDispatch( blockEditorStore );
|
|
234
|
+
const registry = useRegistry();
|
|
235
|
+
|
|
236
|
+
const insertOrReplaceBlocks = useCallback(
|
|
237
|
+
( blocks, updateSelection = true, initialPosition = 0 ) => {
|
|
238
|
+
if ( action === 'replace' ) {
|
|
239
|
+
const clientIds = getBlockOrder( targetRootClientId );
|
|
240
|
+
const clientId = clientIds[ targetBlockIndex ];
|
|
241
|
+
|
|
242
|
+
replaceBlocks( clientId, blocks, undefined, initialPosition );
|
|
243
|
+
} else {
|
|
244
|
+
insertBlocks(
|
|
245
|
+
blocks,
|
|
246
|
+
targetBlockIndex,
|
|
247
|
+
targetRootClientId,
|
|
248
|
+
updateSelection,
|
|
249
|
+
initialPosition
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
},
|
|
253
|
+
[
|
|
254
|
+
action,
|
|
255
|
+
getBlockOrder,
|
|
256
|
+
insertBlocks,
|
|
257
|
+
replaceBlocks,
|
|
258
|
+
targetBlockIndex,
|
|
259
|
+
targetRootClientId,
|
|
260
|
+
]
|
|
261
|
+
);
|
|
262
|
+
|
|
263
|
+
const moveBlocks = useCallback(
|
|
264
|
+
( sourceClientIds, sourceRootClientId, insertIndex ) => {
|
|
265
|
+
if ( action === 'replace' ) {
|
|
266
|
+
const sourceBlocks = getBlocksByClientId( sourceClientIds );
|
|
267
|
+
const targetBlockClientIds =
|
|
268
|
+
getBlockOrder( targetRootClientId );
|
|
269
|
+
const targetBlockClientId =
|
|
270
|
+
targetBlockClientIds[ targetBlockIndex ];
|
|
271
|
+
|
|
272
|
+
registry.batch( () => {
|
|
273
|
+
// Remove the source blocks.
|
|
274
|
+
removeBlocks( sourceClientIds, false );
|
|
275
|
+
// Replace the target block with the source blocks.
|
|
276
|
+
replaceBlocks(
|
|
277
|
+
targetBlockClientId,
|
|
278
|
+
sourceBlocks,
|
|
279
|
+
undefined,
|
|
280
|
+
0
|
|
281
|
+
);
|
|
282
|
+
} );
|
|
283
|
+
} else {
|
|
284
|
+
moveBlocksToPosition(
|
|
285
|
+
sourceClientIds,
|
|
286
|
+
sourceRootClientId,
|
|
287
|
+
targetRootClientId,
|
|
288
|
+
insertIndex
|
|
289
|
+
);
|
|
290
|
+
}
|
|
291
|
+
},
|
|
292
|
+
[
|
|
293
|
+
action,
|
|
294
|
+
getBlockOrder,
|
|
295
|
+
getBlocksByClientId,
|
|
296
|
+
insertBlocks,
|
|
297
|
+
moveBlocksToPosition,
|
|
298
|
+
removeBlocks,
|
|
299
|
+
targetBlockIndex,
|
|
300
|
+
targetRootClientId,
|
|
301
|
+
]
|
|
302
|
+
);
|
|
228
303
|
|
|
229
304
|
const _onDrop = onBlockDrop(
|
|
230
305
|
targetRootClientId,
|
|
231
306
|
targetBlockIndex,
|
|
232
307
|
getBlockIndex,
|
|
233
308
|
getClientIdsOfDescendants,
|
|
234
|
-
|
|
235
|
-
|
|
309
|
+
moveBlocks,
|
|
310
|
+
insertOrReplaceBlocks,
|
|
236
311
|
clearSelectedBlock
|
|
237
312
|
);
|
|
238
313
|
const _onFilesDrop = onFilesDrop(
|
|
@@ -241,12 +316,12 @@ export default function useOnBlockDrop( targetRootClientId, targetBlockIndex ) {
|
|
|
241
316
|
hasUploadPermissions,
|
|
242
317
|
updateBlockAttributes,
|
|
243
318
|
canInsertBlockType,
|
|
244
|
-
|
|
319
|
+
insertOrReplaceBlocks
|
|
245
320
|
);
|
|
246
321
|
const _onHTMLDrop = onHTMLDrop(
|
|
247
322
|
targetRootClientId,
|
|
248
323
|
targetBlockIndex,
|
|
249
|
-
|
|
324
|
+
insertOrReplaceBlocks
|
|
250
325
|
);
|
|
251
326
|
|
|
252
327
|
return ( event ) => {
|
|
@@ -98,7 +98,7 @@ describe( 'onBlockDrop', () => {
|
|
|
98
98
|
const targetBlockIndex = 0;
|
|
99
99
|
const getBlockIndex = noop;
|
|
100
100
|
const getClientIdsOfDescendants = noop;
|
|
101
|
-
const
|
|
101
|
+
const moveBlocks = jest.fn();
|
|
102
102
|
|
|
103
103
|
const event = {
|
|
104
104
|
dataTransfer: {
|
|
@@ -115,11 +115,11 @@ describe( 'onBlockDrop', () => {
|
|
|
115
115
|
targetBlockIndex,
|
|
116
116
|
getBlockIndex,
|
|
117
117
|
getClientIdsOfDescendants,
|
|
118
|
-
|
|
118
|
+
moveBlocks
|
|
119
119
|
);
|
|
120
120
|
eventHandler( event );
|
|
121
121
|
|
|
122
|
-
expect(
|
|
122
|
+
expect( moveBlocks ).not.toHaveBeenCalled();
|
|
123
123
|
} );
|
|
124
124
|
|
|
125
125
|
it( 'does nothing if the block is dropped to the same place it was dragged from', () => {
|
|
@@ -128,7 +128,7 @@ describe( 'onBlockDrop', () => {
|
|
|
128
128
|
// Target and source block index is the same.
|
|
129
129
|
const getBlockIndex = jest.fn( () => targetBlockIndex );
|
|
130
130
|
const getClientIdsOfDescendants = noop;
|
|
131
|
-
const
|
|
131
|
+
const moveBlocks = jest.fn();
|
|
132
132
|
|
|
133
133
|
const event = {
|
|
134
134
|
dataTransfer: {
|
|
@@ -148,11 +148,11 @@ describe( 'onBlockDrop', () => {
|
|
|
148
148
|
targetBlockIndex,
|
|
149
149
|
getBlockIndex,
|
|
150
150
|
getClientIdsOfDescendants,
|
|
151
|
-
|
|
151
|
+
moveBlocks
|
|
152
152
|
);
|
|
153
153
|
eventHandler( event );
|
|
154
154
|
|
|
155
|
-
expect(
|
|
155
|
+
expect( moveBlocks ).not.toHaveBeenCalled();
|
|
156
156
|
} );
|
|
157
157
|
|
|
158
158
|
it( 'does nothing if the block is dropped as a child of itself', () => {
|
|
@@ -160,7 +160,7 @@ describe( 'onBlockDrop', () => {
|
|
|
160
160
|
const targetBlockIndex = 0;
|
|
161
161
|
const getBlockIndex = jest.fn( () => 6 );
|
|
162
162
|
const getClientIdsOfDescendants = noop;
|
|
163
|
-
const
|
|
163
|
+
const moveBlocks = jest.fn();
|
|
164
164
|
|
|
165
165
|
const event = {
|
|
166
166
|
dataTransfer: {
|
|
@@ -180,11 +180,11 @@ describe( 'onBlockDrop', () => {
|
|
|
180
180
|
targetBlockIndex,
|
|
181
181
|
getBlockIndex,
|
|
182
182
|
getClientIdsOfDescendants,
|
|
183
|
-
|
|
183
|
+
moveBlocks
|
|
184
184
|
);
|
|
185
185
|
eventHandler( event );
|
|
186
186
|
|
|
187
|
-
expect(
|
|
187
|
+
expect( moveBlocks ).not.toHaveBeenCalled();
|
|
188
188
|
} );
|
|
189
189
|
|
|
190
190
|
it( 'does nothing if the block is dropped as a descendant of itself', () => {
|
|
@@ -195,7 +195,7 @@ describe( 'onBlockDrop', () => {
|
|
|
195
195
|
const getClientIdsOfDescendants = jest.fn( () => [
|
|
196
196
|
targetRootClientId,
|
|
197
197
|
] );
|
|
198
|
-
const
|
|
198
|
+
const moveBlocks = jest.fn();
|
|
199
199
|
|
|
200
200
|
const event = {
|
|
201
201
|
dataTransfer: {
|
|
@@ -214,11 +214,11 @@ describe( 'onBlockDrop', () => {
|
|
|
214
214
|
targetBlockIndex,
|
|
215
215
|
getBlockIndex,
|
|
216
216
|
getClientIdsOfDescendants,
|
|
217
|
-
|
|
217
|
+
moveBlocks
|
|
218
218
|
);
|
|
219
219
|
eventHandler( event );
|
|
220
220
|
|
|
221
|
-
expect(
|
|
221
|
+
expect( moveBlocks ).not.toHaveBeenCalled();
|
|
222
222
|
} );
|
|
223
223
|
|
|
224
224
|
it( 'inserts blocks if the drop is valid', () => {
|
|
@@ -228,7 +228,7 @@ describe( 'onBlockDrop', () => {
|
|
|
228
228
|
const targetBlockIndex = 0;
|
|
229
229
|
const getBlockIndex = jest.fn( () => 1 );
|
|
230
230
|
const getClientIdsOfDescendants = () => [];
|
|
231
|
-
const
|
|
231
|
+
const moveBlocks = jest.fn();
|
|
232
232
|
|
|
233
233
|
const event = {
|
|
234
234
|
dataTransfer: {
|
|
@@ -247,14 +247,13 @@ describe( 'onBlockDrop', () => {
|
|
|
247
247
|
targetBlockIndex,
|
|
248
248
|
getBlockIndex,
|
|
249
249
|
getClientIdsOfDescendants,
|
|
250
|
-
|
|
250
|
+
moveBlocks
|
|
251
251
|
);
|
|
252
252
|
eventHandler( event );
|
|
253
253
|
|
|
254
|
-
expect(
|
|
254
|
+
expect( moveBlocks ).toHaveBeenCalledWith(
|
|
255
255
|
sourceClientIds,
|
|
256
256
|
sourceRootClientId,
|
|
257
|
-
targetRootClientId,
|
|
258
257
|
targetBlockIndex
|
|
259
258
|
);
|
|
260
259
|
} );
|
|
@@ -267,7 +266,7 @@ describe( 'onBlockDrop', () => {
|
|
|
267
266
|
const getBlockIndex = jest.fn( () => 1 );
|
|
268
267
|
// Dragged block is being dropped as a descendant of itself.
|
|
269
268
|
const getClientIdsOfDescendants = () => [];
|
|
270
|
-
const
|
|
269
|
+
const moveBlocks = jest.fn();
|
|
271
270
|
|
|
272
271
|
const event = {
|
|
273
272
|
dataTransfer: {
|
|
@@ -289,14 +288,13 @@ describe( 'onBlockDrop', () => {
|
|
|
289
288
|
targetBlockIndex,
|
|
290
289
|
getBlockIndex,
|
|
291
290
|
getClientIdsOfDescendants,
|
|
292
|
-
|
|
291
|
+
moveBlocks
|
|
293
292
|
);
|
|
294
293
|
eventHandler( event );
|
|
295
294
|
|
|
296
|
-
expect(
|
|
295
|
+
expect( moveBlocks ).toHaveBeenCalledWith(
|
|
297
296
|
sourceClientIds,
|
|
298
297
|
sourceRootClientId,
|
|
299
|
-
targetRootClientId,
|
|
300
298
|
insertIndex
|
|
301
299
|
);
|
|
302
300
|
} );
|
|
@@ -306,7 +304,7 @@ describe( 'onFilesDrop', () => {
|
|
|
306
304
|
it( 'does nothing if hasUploadPermissions is false', () => {
|
|
307
305
|
const updateBlockAttributes = jest.fn();
|
|
308
306
|
const canInsertBlockType = noop;
|
|
309
|
-
const
|
|
307
|
+
const insertOrReplaceBlocks = jest.fn();
|
|
310
308
|
const targetRootClientId = '1';
|
|
311
309
|
const targetBlockIndex = 0;
|
|
312
310
|
const uploadPermissions = false;
|
|
@@ -317,12 +315,12 @@ describe( 'onFilesDrop', () => {
|
|
|
317
315
|
uploadPermissions,
|
|
318
316
|
updateBlockAttributes,
|
|
319
317
|
canInsertBlockType,
|
|
320
|
-
|
|
318
|
+
insertOrReplaceBlocks
|
|
321
319
|
);
|
|
322
320
|
onFileDropHandler();
|
|
323
321
|
|
|
324
322
|
expect( findTransform ).not.toHaveBeenCalled();
|
|
325
|
-
expect(
|
|
323
|
+
expect( insertOrReplaceBlocks ).not.toHaveBeenCalled();
|
|
326
324
|
} );
|
|
327
325
|
|
|
328
326
|
it( 'does nothing if the block has no matching file transforms', () => {
|
|
@@ -330,7 +328,7 @@ describe( 'onFilesDrop', () => {
|
|
|
330
328
|
// to have no return value.
|
|
331
329
|
findTransform.mockImplementation( noop );
|
|
332
330
|
const updateBlockAttributes = noop;
|
|
333
|
-
const
|
|
331
|
+
const insertOrReplaceBlocks = jest.fn();
|
|
334
332
|
const canInsertBlockType = noop;
|
|
335
333
|
const targetRootClientId = '1';
|
|
336
334
|
const targetBlockIndex = 0;
|
|
@@ -342,12 +340,12 @@ describe( 'onFilesDrop', () => {
|
|
|
342
340
|
uploadPermissions,
|
|
343
341
|
updateBlockAttributes,
|
|
344
342
|
canInsertBlockType,
|
|
345
|
-
|
|
343
|
+
insertOrReplaceBlocks
|
|
346
344
|
);
|
|
347
345
|
onFileDropHandler();
|
|
348
346
|
|
|
349
347
|
expect( findTransform ).toHaveBeenCalled();
|
|
350
|
-
expect(
|
|
348
|
+
expect( insertOrReplaceBlocks ).not.toHaveBeenCalled();
|
|
351
349
|
} );
|
|
352
350
|
|
|
353
351
|
it( 'inserts blocks if a valid transform can be found', () => {
|
|
@@ -359,7 +357,7 @@ describe( 'onFilesDrop', () => {
|
|
|
359
357
|
findTransform.mockImplementation( () => transformation );
|
|
360
358
|
const updateBlockAttributes = noop;
|
|
361
359
|
const canInsertBlockType = noop;
|
|
362
|
-
const
|
|
360
|
+
const insertOrReplaceBlocks = jest.fn();
|
|
363
361
|
const targetRootClientId = '1';
|
|
364
362
|
const targetBlockIndex = 0;
|
|
365
363
|
const uploadPermissions = true;
|
|
@@ -370,7 +368,7 @@ describe( 'onFilesDrop', () => {
|
|
|
370
368
|
uploadPermissions,
|
|
371
369
|
updateBlockAttributes,
|
|
372
370
|
canInsertBlockType,
|
|
373
|
-
|
|
371
|
+
insertOrReplaceBlocks
|
|
374
372
|
);
|
|
375
373
|
const files = 'test';
|
|
376
374
|
onFileDropHandler( files );
|
|
@@ -380,11 +378,7 @@ describe( 'onFilesDrop', () => {
|
|
|
380
378
|
files,
|
|
381
379
|
updateBlockAttributes
|
|
382
380
|
);
|
|
383
|
-
expect(
|
|
384
|
-
blocks,
|
|
385
|
-
targetBlockIndex,
|
|
386
|
-
targetRootClientId
|
|
387
|
-
);
|
|
381
|
+
expect( insertOrReplaceBlocks ).toHaveBeenCalledWith( blocks );
|
|
388
382
|
} );
|
|
389
383
|
} );
|
|
390
384
|
|
|
@@ -393,16 +387,16 @@ describe( 'onHTMLDrop', () => {
|
|
|
393
387
|
pasteHandler.mockImplementation( () => [] );
|
|
394
388
|
const targetRootClientId = '1';
|
|
395
389
|
const targetBlockIndex = 0;
|
|
396
|
-
const
|
|
390
|
+
const insertOrReplaceBlocks = jest.fn();
|
|
397
391
|
|
|
398
392
|
const eventHandler = onHTMLDrop(
|
|
399
393
|
targetRootClientId,
|
|
400
394
|
targetBlockIndex,
|
|
401
|
-
|
|
395
|
+
insertOrReplaceBlocks
|
|
402
396
|
);
|
|
403
397
|
eventHandler();
|
|
404
398
|
|
|
405
|
-
expect(
|
|
399
|
+
expect( insertOrReplaceBlocks ).not.toHaveBeenCalled();
|
|
406
400
|
} );
|
|
407
401
|
|
|
408
402
|
it( 'inserts blocks if the HTML can be converted into blocks', () => {
|
|
@@ -410,19 +404,15 @@ describe( 'onHTMLDrop', () => {
|
|
|
410
404
|
pasteHandler.mockImplementation( () => blocks );
|
|
411
405
|
const targetRootClientId = '1';
|
|
412
406
|
const targetBlockIndex = 0;
|
|
413
|
-
const
|
|
407
|
+
const insertOrReplaceBlocks = jest.fn();
|
|
414
408
|
|
|
415
409
|
const eventHandler = onHTMLDrop(
|
|
416
410
|
targetRootClientId,
|
|
417
411
|
targetBlockIndex,
|
|
418
|
-
|
|
412
|
+
insertOrReplaceBlocks
|
|
419
413
|
);
|
|
420
414
|
eventHandler();
|
|
421
415
|
|
|
422
|
-
expect(
|
|
423
|
-
blocks,
|
|
424
|
-
targetBlockIndex,
|
|
425
|
-
targetRootClientId
|
|
426
|
-
);
|
|
416
|
+
expect( insertOrReplaceBlocks ).toHaveBeenCalledWith( blocks );
|
|
427
417
|
} );
|
|
428
418
|
} );
|
|
@@ -21,10 +21,8 @@ import { store as blockEditorStore } from '../../store';
|
|
|
21
21
|
const blockedPaths = [ 'color', 'border', 'typography', 'spacing' ];
|
|
22
22
|
|
|
23
23
|
const deprecatedFlags = {
|
|
24
|
-
'color.palette': ( settings ) =>
|
|
25
|
-
|
|
26
|
-
'color.gradients': ( settings ) =>
|
|
27
|
-
settings.gradients === undefined ? undefined : settings.gradients,
|
|
24
|
+
'color.palette': ( settings ) => settings.colors,
|
|
25
|
+
'color.gradients': ( settings ) => settings.gradients,
|
|
28
26
|
'color.custom': ( settings ) =>
|
|
29
27
|
settings.disableCustomColors === undefined
|
|
30
28
|
? undefined
|
|
@@ -33,8 +31,7 @@ const deprecatedFlags = {
|
|
|
33
31
|
settings.disableCustomGradients === undefined
|
|
34
32
|
? undefined
|
|
35
33
|
: ! settings.disableCustomGradients,
|
|
36
|
-
'typography.fontSizes': ( settings ) =>
|
|
37
|
-
settings.fontSizes === undefined ? undefined : settings.fontSizes,
|
|
34
|
+
'typography.fontSizes': ( settings ) => settings.fontSizes,
|
|
38
35
|
'typography.customFontSize': ( settings ) =>
|
|
39
36
|
settings.disableCustomFontSizes === undefined
|
|
40
37
|
? undefined
|
|
@@ -109,7 +106,7 @@ const removeCustomPrefixes = ( path ) => {
|
|
|
109
106
|
export default function useSetting( path ) {
|
|
110
107
|
const { name: blockName, clientId } = useBlockEditContext();
|
|
111
108
|
|
|
112
|
-
|
|
109
|
+
return useSelect(
|
|
113
110
|
( select ) => {
|
|
114
111
|
if ( blockedPaths.includes( path ) ) {
|
|
115
112
|
// eslint-disable-next-line no-console
|
|
@@ -120,14 +117,20 @@ export default function useSetting( path ) {
|
|
|
120
117
|
}
|
|
121
118
|
|
|
122
119
|
let result;
|
|
120
|
+
|
|
123
121
|
const normalizedPath = removeCustomPrefixes( path );
|
|
124
122
|
|
|
125
123
|
// 1. Take settings from the block instance or its ancestors.
|
|
124
|
+
// Start from the current block and work our way up the ancestors.
|
|
126
125
|
const candidates = [
|
|
127
|
-
|
|
128
|
-
|
|
126
|
+
clientId,
|
|
127
|
+
...select( blockEditorStore ).getBlockParents(
|
|
128
|
+
clientId,
|
|
129
|
+
/* ascending */ true
|
|
130
|
+
),
|
|
129
131
|
];
|
|
130
|
-
|
|
132
|
+
|
|
133
|
+
for ( const candidateClientId of candidates ) {
|
|
131
134
|
const candidateBlockName =
|
|
132
135
|
select( blockEditorStore ).getBlockName(
|
|
133
136
|
candidateClientId
|
|
@@ -143,17 +146,18 @@ export default function useSetting( path ) {
|
|
|
143
146
|
select( blockEditorStore ).getBlockAttributes(
|
|
144
147
|
candidateClientId
|
|
145
148
|
);
|
|
146
|
-
|
|
149
|
+
result =
|
|
147
150
|
get(
|
|
148
151
|
candidateAtts,
|
|
149
152
|
`settings.blocks.${ blockName }.${ normalizedPath }`
|
|
150
153
|
) ??
|
|
151
154
|
get( candidateAtts, `settings.${ normalizedPath }` );
|
|
152
|
-
if (
|
|
153
|
-
|
|
155
|
+
if ( result !== undefined ) {
|
|
156
|
+
// Stop the search for more distant ancestors and move on.
|
|
157
|
+
break;
|
|
154
158
|
}
|
|
155
159
|
}
|
|
156
|
-
}
|
|
160
|
+
}
|
|
157
161
|
|
|
158
162
|
// 2. Fall back to the settings from the block editor store (__experimentalFeatures).
|
|
159
163
|
const settings = select( blockEditorStore ).getSettings();
|
|
@@ -188,6 +192,4 @@ export default function useSetting( path ) {
|
|
|
188
192
|
},
|
|
189
193
|
[ blockName, clientId, path ]
|
|
190
194
|
);
|
|
191
|
-
|
|
192
|
-
return setting;
|
|
193
195
|
}
|
|
@@ -17,7 +17,7 @@ import { useRefEffect } from '@wordpress/compose';
|
|
|
17
17
|
/**
|
|
18
18
|
* Internal dependencies
|
|
19
19
|
*/
|
|
20
|
-
import { getBlockClientId } from '../../utils/dom';
|
|
20
|
+
import { getBlockClientId, isInSameBlock } from '../../utils/dom';
|
|
21
21
|
import { store as blockEditorStore } from '../../store';
|
|
22
22
|
|
|
23
23
|
/**
|
|
@@ -101,6 +101,16 @@ export function getClosestTabbable(
|
|
|
101
101
|
}
|
|
102
102
|
|
|
103
103
|
function isTabCandidate( node ) {
|
|
104
|
+
// Skip if there's only one child that is content editable (and thus a
|
|
105
|
+
// better candidate).
|
|
106
|
+
if (
|
|
107
|
+
node.children.length === 1 &&
|
|
108
|
+
isInSameBlock( node, node.firstElementChild ) &&
|
|
109
|
+
node.firstElementChild.getAttribute( 'contenteditable' ) === 'true'
|
|
110
|
+
) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
|
|
104
114
|
// Not a candidate if the node is not tabbable.
|
|
105
115
|
if ( ! focus.tabbable.isTabbableIndex( node ) ) {
|
|
106
116
|
return false;
|
|
@@ -157,7 +167,8 @@ export default function useArrowNav() {
|
|
|
157
167
|
}
|
|
158
168
|
|
|
159
169
|
function onKeyDown( event ) {
|
|
160
|
-
const { keyCode, target } =
|
|
170
|
+
const { keyCode, target, shiftKey, ctrlKey, altKey, metaKey } =
|
|
171
|
+
event;
|
|
161
172
|
const isUp = keyCode === UP;
|
|
162
173
|
const isDown = keyCode === DOWN;
|
|
163
174
|
const isLeft = keyCode === LEFT;
|
|
@@ -166,9 +177,7 @@ export default function useArrowNav() {
|
|
|
166
177
|
const isHorizontal = isLeft || isRight;
|
|
167
178
|
const isVertical = isUp || isDown;
|
|
168
179
|
const isNav = isHorizontal || isVertical;
|
|
169
|
-
const
|
|
170
|
-
const hasModifier =
|
|
171
|
-
isShift || event.ctrlKey || event.altKey || event.metaKey;
|
|
180
|
+
const hasModifier = shiftKey || ctrlKey || altKey || metaKey;
|
|
172
181
|
const isNavEdge = isVertical ? isVerticalEdge : isHorizontalEdge;
|
|
173
182
|
const { ownerDocument } = node;
|
|
174
183
|
const { defaultView } = ownerDocument;
|
|
@@ -190,7 +199,7 @@ export default function useArrowNav() {
|
|
|
190
199
|
return;
|
|
191
200
|
}
|
|
192
201
|
|
|
193
|
-
if (
|
|
202
|
+
if ( shiftKey ) {
|
|
194
203
|
return;
|
|
195
204
|
}
|
|
196
205
|
|
|
@@ -239,7 +248,7 @@ export default function useArrowNav() {
|
|
|
239
248
|
const isReverseDir = isRTL( target ) ? ! isReverse : isReverse;
|
|
240
249
|
const { keepCaretInsideBlock } = getSettings();
|
|
241
250
|
|
|
242
|
-
if (
|
|
251
|
+
if ( shiftKey ) {
|
|
243
252
|
if (
|
|
244
253
|
isClosestTabbableABlock( target, isReverse ) &&
|
|
245
254
|
isNavEdge( target, isReverse )
|
|
@@ -251,6 +260,9 @@ export default function useArrowNav() {
|
|
|
251
260
|
} else if (
|
|
252
261
|
isVertical &&
|
|
253
262
|
isVerticalEdge( target, isReverse ) &&
|
|
263
|
+
// When Alt is pressed, only intercept if the caret is also at
|
|
264
|
+
// the horizontal edge.
|
|
265
|
+
( altKey ? isHorizontalEdge( target, isReverseDir ) : true ) &&
|
|
254
266
|
! keepCaretInsideBlock
|
|
255
267
|
) {
|
|
256
268
|
const closestTabbable = getClosestTabbable(
|
|
@@ -263,8 +275,10 @@ export default function useArrowNav() {
|
|
|
263
275
|
if ( closestTabbable ) {
|
|
264
276
|
placeCaretAtVerticalEdge(
|
|
265
277
|
closestTabbable,
|
|
266
|
-
|
|
267
|
-
|
|
278
|
+
// When Alt is pressed, place the caret at the furthest
|
|
279
|
+
// horizontal edge and the furthest vertical edge.
|
|
280
|
+
altKey ? ! isReverse : isReverse,
|
|
281
|
+
altKey ? undefined : verticalRect
|
|
268
282
|
);
|
|
269
283
|
event.preventDefault();
|
|
270
284
|
}
|