-
Notifications
You must be signed in to change notification settings - Fork 4.3k
/
Copy pathinner-blocks.js
124 lines (111 loc) · 3.32 KB
/
inner-blocks.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
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
112
113
114
115
116
117
118
119
120
121
122
123
124
/**
* WordPress dependencies
*/
import { useEntityBlockEditor } from '@wordpress/core-data';
import {
useInnerBlocksProps,
InnerBlocks,
store as blockEditorStore,
} from '@wordpress/block-editor';
import { useSelect } from '@wordpress/data';
import { useMemo } from '@wordpress/element';
/**
* Internal dependencies
*/
import PlaceholderPreview from './placeholder/placeholder-preview';
import {
DEFAULT_BLOCK,
ALLOWED_BLOCKS,
PRIORITIZED_INSERTER_BLOCKS,
} from '../constants';
export default function NavigationInnerBlocks( {
clientId,
hasCustomPlaceholder,
orientation,
templateLock,
} ) {
const {
isImmediateParentOfSelectedBlock,
selectedBlockHasChildren,
isSelected,
} = useSelect(
( select ) => {
const {
getBlockCount,
hasSelectedInnerBlock,
getSelectedBlockClientId,
} = select( blockEditorStore );
const selectedBlockId = getSelectedBlockClientId();
return {
isImmediateParentOfSelectedBlock: hasSelectedInnerBlock(
clientId,
false
),
selectedBlockHasChildren: !! getBlockCount( selectedBlockId ),
// This prop is already available but computing it here ensures it's
// fresh compared to isImmediateParentOfSelectedBlock.
isSelected: selectedBlockId === clientId,
};
},
[ clientId ]
);
const [ blocks, onInput, onChange ] = useEntityBlockEditor(
'postType',
'wp_navigation'
);
const shouldDirectInsert = useMemo(
() =>
blocks.every(
( { name } ) =>
name === 'core/navigation-link' ||
name === 'core/navigation-submenu' ||
name === 'core/page-list'
),
[ blocks ]
);
// When the block is selected itself or has a top level item selected that
// doesn't itself have children, show the standard appender. Else show no
// appender.
const parentOrChildHasSelection =
isSelected ||
( isImmediateParentOfSelectedBlock && ! selectedBlockHasChildren );
const placeholder = useMemo( () => <PlaceholderPreview />, [] );
const hasMenuItems = !! blocks?.length;
// If there is a `ref` attribute pointing to a `wp_navigation` but
// that menu has no **items** (i.e. empty) then show a placeholder.
// The block must also be selected else the placeholder will display
// alongside the appender.
const showPlaceholder =
! hasCustomPlaceholder && ! hasMenuItems && ! isSelected;
const innerBlocksProps = useInnerBlocksProps(
{
className: 'wp-block-navigation__container',
},
{
value: blocks,
onInput,
onChange,
allowedBlocks: ALLOWED_BLOCKS,
prioritizedInserterBlocks: PRIORITIZED_INSERTER_BLOCKS,
__experimentalDefaultBlock: DEFAULT_BLOCK,
__experimentalDirectInsert: shouldDirectInsert,
orientation,
templateLock,
// As an exception to other blocks which feature nesting, show
// the block appender even when a child block is selected.
// This should be a temporary fix, to be replaced by improvements to
// the sibling inserter.
// See https://github.com/WordPress/gutenberg/issues/37572.
renderAppender:
isSelected ||
( isImmediateParentOfSelectedBlock &&
! selectedBlockHasChildren ) ||
// Show the appender while dragging to allow inserting element between item and the appender.
parentOrChildHasSelection
? InnerBlocks.ButtonBlockAppender
: false,
placeholder: showPlaceholder ? placeholder : undefined,
}
);
return <div { ...innerBlocksProps } />;
}