@wordpress/block-library 9.40.1 → 9.40.2-next.v.202602271551.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/build/accordion/view.cjs +0 -34
- package/build/accordion/view.cjs.map +2 -2
- package/build/icon/block.json +9 -1
- package/build/icon/components/custom-inserter/icon-grid.cjs +1 -1
- package/build/icon/components/custom-inserter/icon-grid.cjs.map +2 -2
- package/build/icon/components/custom-inserter/index.cjs +1 -1
- package/build/icon/components/custom-inserter/index.cjs.map +2 -2
- package/build/icon/edit.cjs +15 -7
- package/build/icon/edit.cjs.map +2 -2
- package/build/image/edit.cjs +1 -1
- package/build/image/edit.cjs.map +2 -2
- package/build/navigation/edit/index.cjs +4 -2
- package/build/navigation/edit/index.cjs.map +3 -3
- package/build/navigation/edit/leaf-more-menu.cjs +68 -6
- package/build/navigation/edit/leaf-more-menu.cjs.map +3 -3
- package/build/navigation/edit/menu-inspector-controls.cjs +20 -91
- package/build/navigation/edit/menu-inspector-controls.cjs.map +3 -3
- package/build/navigation/edit/navigation-link-ui.cjs +97 -0
- package/build/navigation/edit/navigation-link-ui.cjs.map +7 -0
- package/build/navigation/edit/navigation-list-view-header.cjs +86 -0
- package/build/navigation/edit/navigation-list-view-header.cjs.map +7 -0
- package/build/navigation/edit/navigation-menu-selector.cjs +4 -2
- package/build/navigation/edit/navigation-menu-selector.cjs.map +3 -3
- package/build/navigation/edit/placeholder/index.cjs +2 -2
- package/build/navigation/edit/placeholder/index.cjs.map +3 -3
- package/build/navigation-link/shared/controls.cjs +29 -52
- package/build/navigation-link/shared/controls.cjs.map +3 -3
- package/build/navigation-link/shared/use-link-preview.cjs +7 -8
- package/build/navigation-link/shared/use-link-preview.cjs.map +2 -2
- package/build/navigation-overlay-close/edit.cjs +2 -3
- package/build/navigation-overlay-close/edit.cjs.map +2 -2
- package/build/page-list-item/edit.cjs +6 -3
- package/build/page-list-item/edit.cjs.map +2 -2
- package/build/post-navigation-link/block.json +1 -3
- package/build/post-navigation-link/deprecated.cjs +100 -0
- package/build/post-navigation-link/deprecated.cjs.map +7 -0
- package/build/post-navigation-link/edit.cjs +2 -36
- package/build/post-navigation-link/edit.cjs.map +3 -3
- package/build/post-navigation-link/index.cjs +2 -0
- package/build/post-navigation-link/index.cjs.map +3 -3
- package/build/post-title/block.json +1 -3
- package/build/post-title/deprecated.cjs +82 -1
- package/build/post-title/deprecated.cjs.map +3 -3
- package/build/post-title/edit.cjs +10 -36
- package/build/post-title/edit.cjs.map +3 -3
- package/build/pullquote/deprecated.cjs +6 -6
- package/build/pullquote/deprecated.cjs.map +2 -2
- package/build/query/block.json +1 -2
- package/build/query-title/block.json +1 -3
- package/build/query-title/deprecated.cjs +70 -1
- package/build/query-title/deprecated.cjs.map +3 -3
- package/build/query-title/edit.cjs +17 -35
- package/build/query-title/edit.cjs.map +3 -3
- package/build/site-tagline/block.json +6 -4
- package/build/site-tagline/deprecated.cjs +66 -1
- package/build/site-tagline/deprecated.cjs.map +3 -3
- package/build/site-tagline/edit.cjs +14 -28
- package/build/site-tagline/edit.cjs.map +3 -3
- package/build/site-title/block.json +1 -3
- package/build/site-title/deprecated.cjs +79 -1
- package/build/site-title/deprecated.cjs.map +3 -3
- package/build/site-title/edit.cjs +14 -30
- package/build/site-title/edit.cjs.map +3 -3
- package/build/tabs-menu-item/block.json +1 -26
- package/build/tabs-menu-item/controls.cjs +2 -100
- package/build/tabs-menu-item/controls.cjs.map +3 -3
- package/build/tabs-menu-item/edit.cjs +6 -65
- package/build/tabs-menu-item/edit.cjs.map +2 -2
- package/build/tabs-menu-item/save.cjs +1 -15
- package/build/tabs-menu-item/save.cjs.map +2 -2
- package/build-module/accordion/view.mjs +1 -35
- package/build-module/accordion/view.mjs.map +2 -2
- package/build-module/icon/block.json +9 -1
- package/build-module/icon/components/custom-inserter/icon-grid.mjs +1 -1
- package/build-module/icon/components/custom-inserter/icon-grid.mjs.map +2 -2
- package/build-module/icon/components/custom-inserter/index.mjs +1 -1
- package/build-module/icon/components/custom-inserter/index.mjs.map +2 -2
- package/build-module/icon/edit.mjs +15 -7
- package/build-module/icon/edit.mjs.map +2 -2
- package/build-module/image/edit.mjs +1 -1
- package/build-module/image/edit.mjs.map +2 -2
- package/build-module/navigation/edit/index.mjs +4 -2
- package/build-module/navigation/edit/index.mjs.map +2 -2
- package/build-module/navigation/edit/leaf-more-menu.mjs +73 -7
- package/build-module/navigation/edit/leaf-more-menu.mjs.map +2 -2
- package/build-module/navigation/edit/menu-inspector-controls.mjs +21 -101
- package/build-module/navigation/edit/menu-inspector-controls.mjs.map +2 -2
- package/build-module/navigation/edit/navigation-link-ui.mjs +76 -0
- package/build-module/navigation/edit/navigation-link-ui.mjs.map +7 -0
- package/build-module/navigation/edit/navigation-list-view-header.mjs +58 -0
- package/build-module/navigation/edit/navigation-list-view-header.mjs.map +7 -0
- package/build-module/navigation/edit/navigation-menu-selector.mjs +5 -3
- package/build-module/navigation/edit/navigation-menu-selector.mjs.map +2 -2
- package/build-module/navigation/edit/placeholder/index.mjs +2 -2
- package/build-module/navigation/edit/placeholder/index.mjs.map +2 -2
- package/build-module/navigation-link/shared/controls.mjs +29 -53
- package/build-module/navigation-link/shared/controls.mjs.map +2 -2
- package/build-module/navigation-link/shared/use-link-preview.mjs +7 -8
- package/build-module/navigation-link/shared/use-link-preview.mjs.map +2 -2
- package/build-module/navigation-overlay-close/edit.mjs +2 -3
- package/build-module/navigation-overlay-close/edit.mjs.map +2 -2
- package/build-module/page-list-item/edit.mjs +6 -3
- package/build-module/page-list-item/edit.mjs.map +2 -2
- package/build-module/post-navigation-link/block.json +1 -3
- package/build-module/post-navigation-link/deprecated.mjs +69 -0
- package/build-module/post-navigation-link/deprecated.mjs.map +7 -0
- package/build-module/post-navigation-link/edit.mjs +3 -30
- package/build-module/post-navigation-link/edit.mjs.map +2 -2
- package/build-module/post-navigation-link/index.mjs +2 -0
- package/build-module/post-navigation-link/index.mjs.map +2 -2
- package/build-module/post-title/block.json +1 -3
- package/build-module/post-title/deprecated.mjs +82 -1
- package/build-module/post-title/deprecated.mjs.map +2 -2
- package/build-module/post-title/edit.mjs +10 -27
- package/build-module/post-title/edit.mjs.map +2 -2
- package/build-module/pullquote/deprecated.mjs +6 -6
- package/build-module/pullquote/deprecated.mjs.map +2 -2
- package/build-module/query/block.json +1 -2
- package/build-module/query-title/block.json +1 -3
- package/build-module/query-title/deprecated.mjs +70 -1
- package/build-module/query-title/deprecated.mjs.map +2 -2
- package/build-module/query-title/edit.mjs +17 -36
- package/build-module/query-title/edit.mjs.map +2 -2
- package/build-module/site-tagline/block.json +6 -4
- package/build-module/site-tagline/deprecated.mjs +66 -1
- package/build-module/site-tagline/deprecated.mjs.map +2 -2
- package/build-module/site-tagline/edit.mjs +14 -29
- package/build-module/site-tagline/edit.mjs.map +2 -2
- package/build-module/site-title/block.json +1 -3
- package/build-module/site-title/deprecated.mjs +79 -1
- package/build-module/site-title/deprecated.mjs.map +2 -2
- package/build-module/site-title/edit.mjs +14 -31
- package/build-module/site-title/edit.mjs.map +2 -2
- package/build-module/tabs-menu-item/block.json +1 -26
- package/build-module/tabs-menu-item/controls.mjs +3 -104
- package/build-module/tabs-menu-item/controls.mjs.map +2 -2
- package/build-module/tabs-menu-item/edit.mjs +6 -66
- package/build-module/tabs-menu-item/edit.mjs.map +2 -2
- package/build-module/tabs-menu-item/save.mjs +1 -15
- package/build-module/tabs-menu-item/save.mjs.map +2 -2
- package/build-style/editor-rtl.css +10 -5
- package/build-style/editor.css +10 -5
- package/build-style/navigation-link/editor-rtl.css +10 -0
- package/build-style/navigation-link/editor.css +10 -0
- package/build-style/style-rtl.css +3 -12
- package/build-style/style.css +3 -12
- package/build-style/tabs-menu-item/editor-rtl.css +0 -5
- package/build-style/tabs-menu-item/editor.css +0 -5
- package/build-style/tabs-menu-item/style-rtl.css +3 -12
- package/build-style/tabs-menu-item/style.css +3 -12
- package/package.json +38 -38
- package/src/accordion/view.js +1 -44
- package/src/accordion-item/index.php +0 -1
- package/src/cover/index.php +4 -4
- package/src/icon/block.json +9 -1
- package/src/icon/components/custom-inserter/icon-grid.js +1 -1
- package/src/icon/components/custom-inserter/index.js +1 -1
- package/src/icon/edit.js +20 -10
- package/src/icon/index.php +1 -3
- package/src/image/edit.js +1 -1
- package/src/image/index.php +1 -4
- package/src/navigation/edit/index.js +4 -2
- package/src/navigation/edit/leaf-more-menu.js +86 -11
- package/src/navigation/edit/menu-inspector-controls.js +23 -142
- package/src/navigation/edit/navigation-link-ui.js +115 -0
- package/src/navigation/edit/navigation-list-view-header.js +62 -0
- package/src/navigation/edit/navigation-menu-selector.js +5 -3
- package/src/navigation/edit/placeholder/index.js +3 -2
- package/src/navigation/edit/test/navigation-menu-selector.js +23 -20
- package/src/navigation-link/editor.scss +18 -0
- package/src/navigation-link/shared/controls.js +35 -62
- package/src/navigation-link/shared/test/controls.js +5 -5
- package/src/navigation-link/shared/test/use-link-preview.test.js +10 -1
- package/src/navigation-link/shared/use-link-preview.js +13 -11
- package/src/navigation-overlay-close/edit.js +4 -3
- package/src/page-list/index.php +1 -1
- package/src/page-list-item/edit.js +8 -7
- package/src/post-featured-image/index.php +2 -4
- package/src/post-navigation-link/block.json +1 -3
- package/src/post-navigation-link/deprecated.js +72 -0
- package/src/post-navigation-link/edit.js +2 -35
- package/src/post-navigation-link/index.js +2 -0
- package/src/post-title/block.json +1 -3
- package/src/post-title/deprecated.js +86 -1
- package/src/post-title/edit.js +2 -18
- package/src/pullquote/deprecated.js +3 -3
- package/src/query/block.json +1 -2
- package/src/query-title/block.json +1 -3
- package/src/query-title/deprecated.js +74 -1
- package/src/query-title/edit.js +11 -27
- package/src/query-title/index.php +1 -1
- package/src/site-tagline/block.json +6 -4
- package/src/site-tagline/deprecated.js +70 -1
- package/src/site-tagline/edit.js +9 -22
- package/src/site-title/block.json +1 -3
- package/src/site-title/deprecated.js +83 -1
- package/src/site-title/edit.js +9 -22
- package/src/tabs-menu-item/block.json +1 -26
- package/src/tabs-menu-item/controls.js +0 -108
- package/src/tabs-menu-item/edit.js +6 -79
- package/src/tabs-menu-item/editor.scss +0 -6
- package/src/tabs-menu-item/save.js +1 -26
- package/src/tabs-menu-item/style.scss +3 -14
- package/build/navigation/use-navigation-entities.cjs +0 -67
- package/build/navigation/use-navigation-entities.cjs.map +0 -7
- package/build-module/navigation/use-navigation-entities.mjs +0 -46
- package/build-module/navigation/use-navigation-entities.mjs.map +0 -7
- package/src/navigation/use-navigation-entities.js +0 -72
|
@@ -6,12 +6,7 @@ import {
|
|
|
6
6
|
InspectorControls,
|
|
7
7
|
store as blockEditorStore,
|
|
8
8
|
} from '@wordpress/block-editor';
|
|
9
|
-
import {
|
|
10
|
-
PanelBody,
|
|
11
|
-
Spinner,
|
|
12
|
-
__experimentalHStack as HStack,
|
|
13
|
-
__experimentalHeading as Heading,
|
|
14
|
-
} from '@wordpress/components';
|
|
9
|
+
import { PanelBody, Spinner } from '@wordpress/components';
|
|
15
10
|
import { useSelect, useDispatch } from '@wordpress/data';
|
|
16
11
|
import { __, sprintf } from '@wordpress/i18n';
|
|
17
12
|
import { useContext } from '@wordpress/element';
|
|
@@ -24,121 +19,18 @@ import { unlock } from '../../lock-unlock';
|
|
|
24
19
|
import DeletedNavigationWarning from './deleted-navigation-warning';
|
|
25
20
|
import useNavigationMenu from '../use-navigation-menu';
|
|
26
21
|
import LeafMoreMenu from './leaf-more-menu';
|
|
27
|
-
import {
|
|
28
|
-
|
|
29
|
-
updateAttributes,
|
|
30
|
-
useEntityBinding,
|
|
31
|
-
} from '../../navigation-link/shared';
|
|
22
|
+
import { NavigationLinkUI } from './navigation-link-ui';
|
|
23
|
+
import NavigationListViewHeader from './navigation-list-view-header';
|
|
32
24
|
|
|
33
25
|
const actionLabel =
|
|
34
26
|
/* translators: %s: The name of a menu. */ __( "Switch to '%s'" );
|
|
35
|
-
const BLOCKS_WITH_LINK_UI_SUPPORT = [
|
|
36
|
-
'core/navigation-link',
|
|
37
|
-
'core/navigation-submenu',
|
|
38
|
-
];
|
|
39
27
|
const {
|
|
40
28
|
PrivateListView,
|
|
41
|
-
useBlockDisplayTitle,
|
|
42
29
|
PrivateBlockContext,
|
|
43
30
|
useListViewPanelState,
|
|
31
|
+
useBlockDisplayTitle,
|
|
44
32
|
} = unlock( blockEditorPrivateApis );
|
|
45
33
|
|
|
46
|
-
function AdditionalBlockContent( { block, insertedBlock, setInsertedBlock } ) {
|
|
47
|
-
const { updateBlockAttributes, removeBlock } =
|
|
48
|
-
useDispatch( blockEditorStore );
|
|
49
|
-
|
|
50
|
-
const supportsLinkControls = BLOCKS_WITH_LINK_UI_SUPPORT?.includes(
|
|
51
|
-
insertedBlock?.name
|
|
52
|
-
);
|
|
53
|
-
const blockWasJustInserted = insertedBlock?.clientId === block.clientId;
|
|
54
|
-
const showLinkControls = supportsLinkControls && blockWasJustInserted;
|
|
55
|
-
|
|
56
|
-
// Get binding utilities for the inserted block
|
|
57
|
-
const { createBinding, clearBinding } = useEntityBinding( {
|
|
58
|
-
clientId: insertedBlock?.clientId,
|
|
59
|
-
attributes: insertedBlock?.attributes || {},
|
|
60
|
-
} );
|
|
61
|
-
|
|
62
|
-
if ( ! showLinkControls ) {
|
|
63
|
-
return null;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Cleanup function for auto-inserted Navigation Link blocks.
|
|
68
|
-
*
|
|
69
|
-
* Removes the block if it has no URL and clears the inserted block state.
|
|
70
|
-
* This ensures consistent cleanup behavior across different contexts.
|
|
71
|
-
*/
|
|
72
|
-
const cleanupInsertedBlock = () => {
|
|
73
|
-
// Prevent automatic block selection when removing blocks in list view context
|
|
74
|
-
// This avoids focus stealing that would close the list view and switch to canvas
|
|
75
|
-
const shouldAutoSelectBlock = false;
|
|
76
|
-
|
|
77
|
-
// Follows the exact same pattern as Navigation Link block's onClose handler
|
|
78
|
-
// If there is no URL then remove the auto-inserted block to avoid empty blocks
|
|
79
|
-
if ( ! insertedBlock?.attributes?.url && insertedBlock?.clientId ) {
|
|
80
|
-
// Remove the block entirely to avoid poor UX
|
|
81
|
-
// This matches the Navigation Link block's behavior
|
|
82
|
-
removeBlock( insertedBlock.clientId, shouldAutoSelectBlock );
|
|
83
|
-
}
|
|
84
|
-
setInsertedBlock( null );
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
const setInsertedBlockAttributes =
|
|
88
|
-
( _insertedBlockClientId ) => ( _updatedAttributes ) => {
|
|
89
|
-
if ( ! _insertedBlockClientId ) {
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
updateBlockAttributes( _insertedBlockClientId, _updatedAttributes );
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
// Wrapper function to clean up original block when a new block is selected
|
|
96
|
-
const handleSetInsertedBlock = ( newBlock ) => {
|
|
97
|
-
// Prevent automatic block selection when removing blocks in list view context
|
|
98
|
-
// This avoids focus stealing that would close the list view and switch to canvas
|
|
99
|
-
const shouldAutoSelectBlock = false;
|
|
100
|
-
|
|
101
|
-
// If we have an existing inserted block and a new block is being set,
|
|
102
|
-
// remove the original block to avoid duplicates
|
|
103
|
-
if ( insertedBlock?.clientId && newBlock ) {
|
|
104
|
-
removeBlock( insertedBlock.clientId, shouldAutoSelectBlock );
|
|
105
|
-
}
|
|
106
|
-
setInsertedBlock( newBlock );
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
return (
|
|
110
|
-
<LinkUI
|
|
111
|
-
clientId={ insertedBlock?.clientId }
|
|
112
|
-
link={ insertedBlock?.attributes }
|
|
113
|
-
onBlockInsert={ handleSetInsertedBlock }
|
|
114
|
-
onClose={ () => {
|
|
115
|
-
// Use cleanup function
|
|
116
|
-
cleanupInsertedBlock();
|
|
117
|
-
} }
|
|
118
|
-
onChange={ ( updatedValue ) => {
|
|
119
|
-
// updateAttributes determines the final state and returns metadata
|
|
120
|
-
const { isEntityLink, attributes: updatedAttributes } =
|
|
121
|
-
updateAttributes(
|
|
122
|
-
updatedValue,
|
|
123
|
-
setInsertedBlockAttributes( insertedBlock?.clientId ),
|
|
124
|
-
insertedBlock?.attributes
|
|
125
|
-
);
|
|
126
|
-
|
|
127
|
-
// Handle URL binding based on the final computed state
|
|
128
|
-
// Only create bindings for entity links (posts, pages, taxonomies)
|
|
129
|
-
// Never create bindings for custom links (manual URLs)
|
|
130
|
-
if ( isEntityLink ) {
|
|
131
|
-
createBinding( updatedAttributes );
|
|
132
|
-
} else {
|
|
133
|
-
clearBinding();
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
setInsertedBlock( null );
|
|
137
|
-
} }
|
|
138
|
-
/>
|
|
139
|
-
);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
34
|
const MainContent = ( {
|
|
143
35
|
clientId,
|
|
144
36
|
currentMenuId,
|
|
@@ -194,7 +86,7 @@ const MainContent = ( {
|
|
|
194
86
|
description={ description }
|
|
195
87
|
showAppender
|
|
196
88
|
blockSettingsMenu={ LeafMoreMenu }
|
|
197
|
-
additionalBlockContent={
|
|
89
|
+
additionalBlockContent={ NavigationLinkUI }
|
|
198
90
|
onSelect={ openListViewContentPanel }
|
|
199
91
|
/>
|
|
200
92
|
</div>
|
|
@@ -232,34 +124,23 @@ const MenuInspectorControls = ( props ) => {
|
|
|
232
124
|
return (
|
|
233
125
|
<InspectorControls group="list">
|
|
234
126
|
<PanelBody title={ null }>
|
|
235
|
-
<
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
{
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
}
|
|
253
|
-
createNavigationMenuIsError={
|
|
254
|
-
createNavigationMenuIsError
|
|
255
|
-
}
|
|
256
|
-
actionLabel={ actionLabel }
|
|
257
|
-
isManageMenusButtonDisabled={
|
|
258
|
-
isManageMenusButtonDisabled
|
|
259
|
-
}
|
|
260
|
-
/>
|
|
261
|
-
) }
|
|
262
|
-
</HStack>
|
|
127
|
+
<NavigationListViewHeader
|
|
128
|
+
clientId={ clientId }
|
|
129
|
+
blockEditingMode={ blockEditingMode }
|
|
130
|
+
currentMenuId={ currentMenuId }
|
|
131
|
+
onSelectClassicMenu={ onSelectClassicMenu }
|
|
132
|
+
onSelectNavigationMenu={ onSelectNavigationMenu }
|
|
133
|
+
onCreateNew={ onCreateNew }
|
|
134
|
+
createNavigationMenuIsSuccess={
|
|
135
|
+
createNavigationMenuIsSuccess
|
|
136
|
+
}
|
|
137
|
+
createNavigationMenuIsError={
|
|
138
|
+
createNavigationMenuIsError
|
|
139
|
+
}
|
|
140
|
+
isManageMenusButtonDisabled={
|
|
141
|
+
isManageMenusButtonDisabled
|
|
142
|
+
}
|
|
143
|
+
/>
|
|
263
144
|
<MainContent
|
|
264
145
|
{ ...props }
|
|
265
146
|
expandRevision={ expandRevision }
|
|
@@ -273,7 +154,7 @@ const MenuInspectorControls = ( props ) => {
|
|
|
273
154
|
return (
|
|
274
155
|
<InspectorControls group="list">
|
|
275
156
|
<PanelBody
|
|
276
|
-
title={
|
|
157
|
+
title={ blockTitle }
|
|
277
158
|
opened={ isOpened }
|
|
278
159
|
onToggle={ handleToggle }
|
|
279
160
|
>
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WordPress dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { store as blockEditorStore } from '@wordpress/block-editor';
|
|
5
|
+
import { useDispatch } from '@wordpress/data';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Internal dependencies
|
|
9
|
+
*/
|
|
10
|
+
import {
|
|
11
|
+
LinkUI,
|
|
12
|
+
updateAttributes,
|
|
13
|
+
useEntityBinding,
|
|
14
|
+
} from '../../navigation-link/shared';
|
|
15
|
+
|
|
16
|
+
const BLOCKS_WITH_LINK_UI_SUPPORT = [
|
|
17
|
+
'core/navigation-link',
|
|
18
|
+
'core/navigation-submenu',
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
export function NavigationLinkUI( { block, insertedBlock, setInsertedBlock } ) {
|
|
22
|
+
const { updateBlockAttributes, removeBlock } =
|
|
23
|
+
useDispatch( blockEditorStore );
|
|
24
|
+
|
|
25
|
+
const supportsLinkControls = BLOCKS_WITH_LINK_UI_SUPPORT?.includes(
|
|
26
|
+
insertedBlock?.name
|
|
27
|
+
);
|
|
28
|
+
const blockWasJustInserted = insertedBlock?.clientId === block.clientId;
|
|
29
|
+
const showLinkControls = supportsLinkControls && blockWasJustInserted;
|
|
30
|
+
|
|
31
|
+
// Get binding utilities for the inserted block
|
|
32
|
+
const { createBinding, clearBinding } = useEntityBinding( {
|
|
33
|
+
clientId: insertedBlock?.clientId,
|
|
34
|
+
attributes: insertedBlock?.attributes || {},
|
|
35
|
+
} );
|
|
36
|
+
|
|
37
|
+
if ( ! showLinkControls ) {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Cleanup function for auto-inserted Navigation Link blocks.
|
|
43
|
+
*
|
|
44
|
+
* Removes the block if it has no URL and clears the inserted block state.
|
|
45
|
+
* This ensures consistent cleanup behavior across different contexts.
|
|
46
|
+
*/
|
|
47
|
+
const cleanupInsertedBlock = () => {
|
|
48
|
+
// Prevent automatic block selection when removing blocks in list view context
|
|
49
|
+
// This avoids focus stealing that would close the list view and switch to canvas
|
|
50
|
+
const shouldAutoSelectBlock = false;
|
|
51
|
+
|
|
52
|
+
// Follows the exact same pattern as Navigation Link block's onClose handler
|
|
53
|
+
// If there is no URL then remove the auto-inserted block to avoid empty blocks
|
|
54
|
+
if ( ! insertedBlock?.attributes?.url && insertedBlock?.clientId ) {
|
|
55
|
+
// Remove the block entirely to avoid poor UX
|
|
56
|
+
// This matches the Navigation Link block's behavior
|
|
57
|
+
removeBlock( insertedBlock.clientId, shouldAutoSelectBlock );
|
|
58
|
+
}
|
|
59
|
+
setInsertedBlock( null );
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const setInsertedBlockAttributes =
|
|
63
|
+
( _insertedBlockClientId ) => ( _updatedAttributes ) => {
|
|
64
|
+
if ( ! _insertedBlockClientId ) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
updateBlockAttributes( _insertedBlockClientId, _updatedAttributes );
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
// Wrapper function to clean up original block when a new block is selected
|
|
71
|
+
const handleSetInsertedBlock = ( newBlock ) => {
|
|
72
|
+
// Prevent automatic block selection when removing blocks in list view context
|
|
73
|
+
// This avoids focus stealing that would close the list view and switch to canvas
|
|
74
|
+
const shouldAutoSelectBlock = false;
|
|
75
|
+
|
|
76
|
+
// If we have an existing inserted block and a new block is being set,
|
|
77
|
+
// remove the original block to avoid duplicates
|
|
78
|
+
if ( insertedBlock?.clientId && newBlock ) {
|
|
79
|
+
removeBlock( insertedBlock.clientId, shouldAutoSelectBlock );
|
|
80
|
+
}
|
|
81
|
+
setInsertedBlock( newBlock );
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
return (
|
|
85
|
+
<LinkUI
|
|
86
|
+
clientId={ insertedBlock?.clientId }
|
|
87
|
+
link={ insertedBlock?.attributes }
|
|
88
|
+
onBlockInsert={ handleSetInsertedBlock }
|
|
89
|
+
onClose={ () => {
|
|
90
|
+
// Use cleanup function
|
|
91
|
+
cleanupInsertedBlock();
|
|
92
|
+
} }
|
|
93
|
+
onChange={ ( updatedValue ) => {
|
|
94
|
+
// updateAttributes determines the final state and returns metadata
|
|
95
|
+
const { isEntityLink, attributes: updatedAttributes } =
|
|
96
|
+
updateAttributes(
|
|
97
|
+
updatedValue,
|
|
98
|
+
setInsertedBlockAttributes( insertedBlock?.clientId ),
|
|
99
|
+
insertedBlock?.attributes
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
// Handle URL binding based on the final computed state
|
|
103
|
+
// Only create bindings for entity links (posts, pages, taxonomies)
|
|
104
|
+
// Never create bindings for custom links (manual URLs)
|
|
105
|
+
if ( isEntityLink ) {
|
|
106
|
+
createBinding( updatedAttributes );
|
|
107
|
+
} else {
|
|
108
|
+
clearBinding();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
setInsertedBlock( null );
|
|
112
|
+
} }
|
|
113
|
+
/>
|
|
114
|
+
);
|
|
115
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WordPress dependencies
|
|
3
|
+
*/
|
|
4
|
+
import {
|
|
5
|
+
__experimentalHStack as HStack,
|
|
6
|
+
__experimentalHeading as Heading,
|
|
7
|
+
} from '@wordpress/components';
|
|
8
|
+
import { __ } from '@wordpress/i18n';
|
|
9
|
+
import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Internal dependencies
|
|
13
|
+
*/
|
|
14
|
+
import NavigationMenuSelector from './navigation-menu-selector';
|
|
15
|
+
import { unlock } from '../../lock-unlock';
|
|
16
|
+
|
|
17
|
+
const { useBlockDisplayTitle } = unlock( blockEditorPrivateApis );
|
|
18
|
+
|
|
19
|
+
const actionLabel =
|
|
20
|
+
/* translators: %s: The name of a menu. */ __( "Switch to '%s'" );
|
|
21
|
+
|
|
22
|
+
export default function NavigationListViewHeader( {
|
|
23
|
+
clientId,
|
|
24
|
+
blockEditingMode,
|
|
25
|
+
currentMenuId,
|
|
26
|
+
onSelectClassicMenu,
|
|
27
|
+
onSelectNavigationMenu,
|
|
28
|
+
onCreateNew,
|
|
29
|
+
createNavigationMenuIsSuccess,
|
|
30
|
+
createNavigationMenuIsError,
|
|
31
|
+
isManageMenusButtonDisabled,
|
|
32
|
+
} ) {
|
|
33
|
+
const blockTitle = useBlockDisplayTitle( {
|
|
34
|
+
clientId,
|
|
35
|
+
context: 'list-view',
|
|
36
|
+
} );
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<HStack className="wp-block-navigation-off-canvas-editor__header">
|
|
40
|
+
<Heading
|
|
41
|
+
className="wp-block-navigation-off-canvas-editor__title"
|
|
42
|
+
level={ 2 }
|
|
43
|
+
>
|
|
44
|
+
{ blockTitle }
|
|
45
|
+
</Heading>
|
|
46
|
+
{ blockEditingMode === 'default' && (
|
|
47
|
+
<NavigationMenuSelector
|
|
48
|
+
currentMenuId={ currentMenuId }
|
|
49
|
+
onSelectClassicMenu={ onSelectClassicMenu }
|
|
50
|
+
onSelectNavigationMenu={ onSelectNavigationMenu }
|
|
51
|
+
onCreateNew={ onCreateNew }
|
|
52
|
+
createNavigationMenuIsSuccess={
|
|
53
|
+
createNavigationMenuIsSuccess
|
|
54
|
+
}
|
|
55
|
+
createNavigationMenuIsError={ createNavigationMenuIsError }
|
|
56
|
+
actionLabel={ actionLabel }
|
|
57
|
+
isManageMenusButtonDisabled={ isManageMenusButtonDisabled }
|
|
58
|
+
/>
|
|
59
|
+
) }
|
|
60
|
+
</HStack>
|
|
61
|
+
);
|
|
62
|
+
}
|
|
@@ -11,13 +11,12 @@ import { moreVertical } from '@wordpress/icons';
|
|
|
11
11
|
import { __, sprintf } from '@wordpress/i18n';
|
|
12
12
|
import { decodeEntities } from '@wordpress/html-entities';
|
|
13
13
|
import { useEffect, useMemo, useState } from '@wordpress/element';
|
|
14
|
-
import { useEntityProp } from '@wordpress/core-data';
|
|
14
|
+
import { useEntityRecords, useEntityProp } from '@wordpress/core-data';
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* Internal dependencies
|
|
18
18
|
*/
|
|
19
19
|
import useNavigationMenu from '../use-navigation-menu';
|
|
20
|
-
import useNavigationEntities from '../use-navigation-entities';
|
|
21
20
|
|
|
22
21
|
function buildMenuLabel( title, id, status ) {
|
|
23
22
|
if ( ! title ) {
|
|
@@ -53,7 +52,10 @@ function NavigationMenuSelector( {
|
|
|
53
52
|
|
|
54
53
|
actionLabel = actionLabel || createActionLabel;
|
|
55
54
|
|
|
56
|
-
const {
|
|
55
|
+
const { records: classicMenus } = useEntityRecords( 'root', 'menu', {
|
|
56
|
+
per_page: -1,
|
|
57
|
+
context: 'view',
|
|
58
|
+
} );
|
|
57
59
|
|
|
58
60
|
const {
|
|
59
61
|
navigationMenus,
|
|
@@ -6,11 +6,11 @@ import { __ } from '@wordpress/i18n';
|
|
|
6
6
|
import { navigation, Icon } from '@wordpress/icons';
|
|
7
7
|
import { speak } from '@wordpress/a11y';
|
|
8
8
|
import { useEffect } from '@wordpress/element';
|
|
9
|
+
import { useEntityRecords } from '@wordpress/core-data';
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* Internal dependencies
|
|
12
13
|
*/
|
|
13
|
-
import useNavigationEntities from '../../use-navigation-entities';
|
|
14
14
|
import PlaceholderPreview from './placeholder-preview';
|
|
15
15
|
import NavigationMenuSelector from '../navigation-menu-selector';
|
|
16
16
|
|
|
@@ -24,7 +24,8 @@ export default function NavigationPlaceholder( {
|
|
|
24
24
|
onSelectClassicMenu,
|
|
25
25
|
onCreateEmpty,
|
|
26
26
|
} ) {
|
|
27
|
-
const { isResolvingMenus, hasResolvedMenus } =
|
|
27
|
+
const { isResolving: isResolvingMenus, hasResolved: hasResolvedMenus } =
|
|
28
|
+
useEntityRecords( 'root', 'menu', { per_page: -1, context: 'view' } );
|
|
28
29
|
|
|
29
30
|
useEffect( () => {
|
|
30
31
|
if ( ! isSelected ) {
|
|
@@ -4,12 +4,16 @@
|
|
|
4
4
|
import { render, screen } from '@testing-library/react';
|
|
5
5
|
import userEvent from '@testing-library/user-event';
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* WordPress dependencies
|
|
9
|
+
*/
|
|
10
|
+
import { useEntityRecords } from '@wordpress/core-data';
|
|
11
|
+
|
|
7
12
|
/**
|
|
8
13
|
* Internal dependencies
|
|
9
14
|
*/
|
|
10
15
|
import NavigationMenuSelector from '../navigation-menu-selector';
|
|
11
16
|
import useNavigationMenu from '../../use-navigation-menu';
|
|
12
|
-
import useNavigationEntities from '../../use-navigation-entities';
|
|
13
17
|
|
|
14
18
|
jest.mock( '../../use-navigation-menu', () => {
|
|
15
19
|
// This allows us to tweak the returned value on each test.
|
|
@@ -17,14 +21,13 @@ jest.mock( '../../use-navigation-menu', () => {
|
|
|
17
21
|
return mock;
|
|
18
22
|
} );
|
|
19
23
|
|
|
20
|
-
jest.mock( '
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
} );
|
|
24
|
+
jest.mock( '@wordpress/core-data', () => ( {
|
|
25
|
+
...jest.requireActual( '@wordpress/core-data' ),
|
|
26
|
+
useEntityRecords: jest.fn(),
|
|
27
|
+
} ) );
|
|
25
28
|
|
|
26
|
-
|
|
27
|
-
|
|
29
|
+
useEntityRecords.mockReturnValue( {
|
|
30
|
+
records: [],
|
|
28
31
|
} );
|
|
29
32
|
|
|
30
33
|
const navigationMenu1 = {
|
|
@@ -485,8 +488,8 @@ describe( 'NavigationMenuSelector', () => {
|
|
|
485
488
|
it( 'should not show classic menus if there are no classic menus', async () => {
|
|
486
489
|
const user = userEvent.setup();
|
|
487
490
|
|
|
488
|
-
|
|
489
|
-
|
|
491
|
+
useEntityRecords.mockReturnValue( {
|
|
492
|
+
records: [],
|
|
490
493
|
} );
|
|
491
494
|
|
|
492
495
|
render( <NavigationMenuSelector /> );
|
|
@@ -507,8 +510,8 @@ describe( 'NavigationMenuSelector', () => {
|
|
|
507
510
|
canUserCreateNavigationMenus: false,
|
|
508
511
|
} );
|
|
509
512
|
|
|
510
|
-
|
|
511
|
-
|
|
513
|
+
useEntityRecords.mockReturnValue( {
|
|
514
|
+
records: classicMenusFixture,
|
|
512
515
|
} );
|
|
513
516
|
|
|
514
517
|
render( <NavigationMenuSelector /> );
|
|
@@ -529,8 +532,8 @@ describe( 'NavigationMenuSelector', () => {
|
|
|
529
532
|
canUserCreateNavigationMenus: true,
|
|
530
533
|
} );
|
|
531
534
|
|
|
532
|
-
|
|
533
|
-
|
|
535
|
+
useEntityRecords.mockReturnValue( {
|
|
536
|
+
records: classicMenusFixture,
|
|
534
537
|
} );
|
|
535
538
|
|
|
536
539
|
render( <NavigationMenuSelector /> );
|
|
@@ -566,8 +569,8 @@ describe( 'NavigationMenuSelector', () => {
|
|
|
566
569
|
canUserCreateNavigationMenus: true,
|
|
567
570
|
} );
|
|
568
571
|
|
|
569
|
-
|
|
570
|
-
|
|
572
|
+
useEntityRecords.mockReturnValue( {
|
|
573
|
+
records: classicMenusFixture,
|
|
571
574
|
} );
|
|
572
575
|
|
|
573
576
|
const { rerender } = render(
|
|
@@ -598,8 +601,8 @@ describe( 'NavigationMenuSelector', () => {
|
|
|
598
601
|
canUserCreateNavigationMenus: true,
|
|
599
602
|
} );
|
|
600
603
|
|
|
601
|
-
|
|
602
|
-
|
|
604
|
+
useEntityRecords.mockReturnValue( {
|
|
605
|
+
records: classicMenusFixture,
|
|
603
606
|
} );
|
|
604
607
|
|
|
605
608
|
rerender(
|
|
@@ -631,8 +634,8 @@ describe( 'NavigationMenuSelector', () => {
|
|
|
631
634
|
canUserCreateNavigationMenus: true,
|
|
632
635
|
} );
|
|
633
636
|
|
|
634
|
-
|
|
635
|
-
|
|
637
|
+
useEntityRecords.mockReturnValue( {
|
|
638
|
+
records: classicMenusFixture,
|
|
636
639
|
} );
|
|
637
640
|
|
|
638
641
|
// Simulate the menu being created and component being re-rendered.
|
|
@@ -150,3 +150,21 @@
|
|
|
150
150
|
.navigation-link-control__error-text {
|
|
151
151
|
color: $alert-red;
|
|
152
152
|
}
|
|
153
|
+
|
|
154
|
+
.navigation-link-to__action-button {
|
|
155
|
+
grid-column: auto;
|
|
156
|
+
// When this is the last button AND in an odd position among its class
|
|
157
|
+
// siblings, it's unpaired — span the full grid row.
|
|
158
|
+
&:nth-last-child(1 of #{&}):nth-child(odd of #{&}) {
|
|
159
|
+
grid-column: 1 / -1;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Artificially increase specificity to override `justify-content` styles.
|
|
163
|
+
// Not ideal, but it shouldn't be necessary once switching to the new `Button`
|
|
164
|
+
// component from `@wordpress/ui`.
|
|
165
|
+
&#{&}#{&} {
|
|
166
|
+
justify-content: center;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
}
|
|
170
|
+
|
|
@@ -5,7 +5,6 @@ import {
|
|
|
5
5
|
Button,
|
|
6
6
|
__experimentalToolsPanel as ToolsPanel,
|
|
7
7
|
__experimentalToolsPanelItem as ToolsPanelItem,
|
|
8
|
-
__experimentalHStack as HStack,
|
|
9
8
|
CheckboxControl,
|
|
10
9
|
TextControl,
|
|
11
10
|
TextareaControl,
|
|
@@ -150,7 +149,7 @@ export function Controls( {
|
|
|
150
149
|
|
|
151
150
|
// Check if URL is viewable (not hash link or other relative path like ./ or ../)
|
|
152
151
|
const isViewableUrl =
|
|
153
|
-
url &&
|
|
152
|
+
!! url &&
|
|
154
153
|
( ! isHashLink( url ) ||
|
|
155
154
|
( isRelativePath( url ) && ! url.startsWith( '/' ) ) );
|
|
156
155
|
|
|
@@ -158,11 +157,6 @@ export function Controls( {
|
|
|
158
157
|
const viewUrl =
|
|
159
158
|
isViewableUrl && url.startsWith( '/' ) && homeUrl ? homeUrl + url : url;
|
|
160
159
|
|
|
161
|
-
const entityTypeName = getEntityTypeName(
|
|
162
|
-
attributes.type,
|
|
163
|
-
attributes.kind
|
|
164
|
-
);
|
|
165
|
-
|
|
166
160
|
return (
|
|
167
161
|
<ToolsPanel
|
|
168
162
|
label={ __( 'Settings' ) }
|
|
@@ -220,61 +214,6 @@ export function Controls( {
|
|
|
220
214
|
help={ helpText ? helpText : undefined }
|
|
221
215
|
/>
|
|
222
216
|
</ToolsPanelItem>
|
|
223
|
-
|
|
224
|
-
{ url && (
|
|
225
|
-
<HStack
|
|
226
|
-
className="navigation-link-to__actions"
|
|
227
|
-
alignment="left"
|
|
228
|
-
justify="left"
|
|
229
|
-
style={ { gridColumn: '1 / -1' } }
|
|
230
|
-
>
|
|
231
|
-
{ hasUrlBinding &&
|
|
232
|
-
isBoundEntityAvailable &&
|
|
233
|
-
entityRecord?.id &&
|
|
234
|
-
attributes.kind === 'post-type' &&
|
|
235
|
-
onNavigateToEntityRecord && (
|
|
236
|
-
<Button
|
|
237
|
-
size="compact"
|
|
238
|
-
variant="secondary"
|
|
239
|
-
onClick={ () => {
|
|
240
|
-
onNavigateToEntityRecord( {
|
|
241
|
-
postId: entityRecord.id,
|
|
242
|
-
postType: attributes.type,
|
|
243
|
-
} );
|
|
244
|
-
} }
|
|
245
|
-
__next40pxDefaultSize
|
|
246
|
-
>
|
|
247
|
-
{ sprintf(
|
|
248
|
-
/* translators: %s: entity type (e.g., "page", "post", "category") */
|
|
249
|
-
__( 'Edit %s' ),
|
|
250
|
-
entityTypeName
|
|
251
|
-
) }
|
|
252
|
-
</Button>
|
|
253
|
-
) }
|
|
254
|
-
{ isViewableUrl && (
|
|
255
|
-
<Button
|
|
256
|
-
size="compact"
|
|
257
|
-
variant="secondary"
|
|
258
|
-
href={ viewUrl }
|
|
259
|
-
target="_blank"
|
|
260
|
-
icon={ external }
|
|
261
|
-
iconPosition="right"
|
|
262
|
-
__next40pxDefaultSize
|
|
263
|
-
>
|
|
264
|
-
{ sprintf(
|
|
265
|
-
/* translators: %s: entity type (e.g., "page", "post", "category") or "link" for external links */
|
|
266
|
-
__( 'View %s' ),
|
|
267
|
-
attributes.kind &&
|
|
268
|
-
attributes.type &&
|
|
269
|
-
attributes.kind !== 'custom'
|
|
270
|
-
? entityTypeName
|
|
271
|
-
: __( 'link' )
|
|
272
|
-
) }
|
|
273
|
-
</Button>
|
|
274
|
-
) }
|
|
275
|
-
</HStack>
|
|
276
|
-
) }
|
|
277
|
-
|
|
278
217
|
<ToolsPanelItem
|
|
279
218
|
hasValue={ () => !! opensInNewTab }
|
|
280
219
|
label={ __( 'Open in new tab' ) }
|
|
@@ -291,6 +230,40 @@ export function Controls( {
|
|
|
291
230
|
}
|
|
292
231
|
/>
|
|
293
232
|
</ToolsPanelItem>
|
|
233
|
+
|
|
234
|
+
{ !! url &&
|
|
235
|
+
hasUrlBinding &&
|
|
236
|
+
isBoundEntityAvailable &&
|
|
237
|
+
entityRecord?.id &&
|
|
238
|
+
attributes.kind === 'post-type' &&
|
|
239
|
+
onNavigateToEntityRecord && (
|
|
240
|
+
<Button
|
|
241
|
+
variant="secondary"
|
|
242
|
+
onClick={ () => {
|
|
243
|
+
onNavigateToEntityRecord( {
|
|
244
|
+
postId: entityRecord.id,
|
|
245
|
+
postType: attributes.type,
|
|
246
|
+
} );
|
|
247
|
+
} }
|
|
248
|
+
__next40pxDefaultSize
|
|
249
|
+
className="navigation-link-to__action-button"
|
|
250
|
+
>
|
|
251
|
+
{ __( 'Edit' ) }
|
|
252
|
+
</Button>
|
|
253
|
+
) }
|
|
254
|
+
{ isViewableUrl && (
|
|
255
|
+
<Button
|
|
256
|
+
variant="secondary"
|
|
257
|
+
href={ viewUrl }
|
|
258
|
+
target="_blank"
|
|
259
|
+
icon={ external }
|
|
260
|
+
iconPosition="right"
|
|
261
|
+
__next40pxDefaultSize
|
|
262
|
+
className="navigation-link-to__action-button"
|
|
263
|
+
>
|
|
264
|
+
{ __( 'View' ) }
|
|
265
|
+
</Button>
|
|
266
|
+
) }
|
|
294
267
|
</>
|
|
295
268
|
) }
|
|
296
269
|
|