Skip to content

Commit 4ed1c11

Browse files
authored
List v2: merge with nested items (#42551)
1 parent b5fce3f commit 4ed1c11

File tree

3 files changed

+76
-2
lines changed

3 files changed

+76
-2
lines changed

packages/block-library/src/list-item/edit.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import {
2727
useIndentListItem,
2828
useOutdentListItem,
2929
useSplit,
30+
useMerge,
3031
} from './hooks';
3132
import { convertToListItems } from './utils';
3233

@@ -57,7 +58,6 @@ function IndentUI( { clientId } ) {
5758
export default function ListItemEdit( {
5859
attributes,
5960
setAttributes,
60-
mergeBlocks,
6161
onReplace,
6262
clientId,
6363
} ) {
@@ -70,6 +70,7 @@ export default function ListItemEdit( {
7070
const useBackspaceRef = useBackspace( { clientId } );
7171
const useSpaceRef = useSpace( clientId );
7272
const onSplit = useSplit( clientId );
73+
const onMerge = useMerge( clientId );
7374
return (
7475
<>
7576
<li { ...innerBlocksProps }>
@@ -88,7 +89,7 @@ export default function ListItemEdit( {
8889
aria-label={ __( 'List text' ) }
8990
placeholder={ placeholder || __( 'List' ) }
9091
onSplit={ onSplit }
91-
onMerge={ mergeBlocks }
92+
onMerge={ onMerge }
9293
onReplace={ ( blocks, ...args ) => {
9394
onReplace( convertToListItems( blocks ), ...args );
9495
} }

packages/block-library/src/list-item/hooks/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ export { default as useEnter } from './use-enter';
44
export { default as useBackspace } from './use-backspace';
55
export { default as useSpace } from './use-space';
66
export { default as useSplit } from './use-split';
7+
export { default as useMerge } from './use-merge';
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/**
2+
* WordPress dependencies
3+
*/
4+
import { useRegistry, useDispatch, useSelect } from '@wordpress/data';
5+
import { store as blockEditorStore } from '@wordpress/block-editor';
6+
7+
export default function useMerge( clientId ) {
8+
const registry = useRegistry();
9+
const {
10+
getPreviousBlockClientId,
11+
getNextBlockClientId,
12+
getBlockOrder,
13+
getBlockRootClientId,
14+
} = useSelect( blockEditorStore );
15+
const { mergeBlocks, moveBlocksToPosition } =
16+
useDispatch( blockEditorStore );
17+
18+
function getTrailing( id ) {
19+
const order = getBlockOrder( id );
20+
21+
if ( ! order.length ) {
22+
return id;
23+
}
24+
25+
return getTrailing( order[ order.length - 1 ] );
26+
}
27+
28+
function getNext( id ) {
29+
return (
30+
getNextBlockClientId( id ) || getNext( getBlockRootClientId( id ) )
31+
);
32+
}
33+
34+
return ( forward ) => {
35+
if ( forward ) {
36+
// Forward "merging" (forward delete) should be equal pressing
37+
// Backspace from the next item. If the next item is not at the top
38+
// level, the item should be outdented instead of merged.
39+
if ( getBlockOrder( clientId ).length ) {
40+
// Should be implemented in `./use-backspace`.
41+
return;
42+
}
43+
44+
const nextBlockClientId = getNext( clientId );
45+
if ( nextBlockClientId ) {
46+
registry.batch( () => {
47+
moveBlocksToPosition(
48+
getBlockOrder( nextBlockClientId ),
49+
nextBlockClientId,
50+
getPreviousBlockClientId( nextBlockClientId )
51+
);
52+
mergeBlocks( clientId, nextBlockClientId );
53+
} );
54+
}
55+
} else {
56+
// Merging is only done from the top level. For lowel levels, the
57+
// list item is outdented instead.
58+
const previousBlockClientId = getPreviousBlockClientId( clientId );
59+
if ( previousBlockClientId ) {
60+
const trailingClientId = getTrailing( previousBlockClientId );
61+
registry.batch( () => {
62+
moveBlocksToPosition(
63+
getBlockOrder( clientId ),
64+
clientId,
65+
previousBlockClientId
66+
);
67+
mergeBlocks( trailingClientId, clientId );
68+
} );
69+
}
70+
}
71+
};
72+
}

0 commit comments

Comments
 (0)