@wordpress/block-library 8.10.0 → 8.11.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.
Files changed (278) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/build/block/edit.native.js +17 -10
  3. package/build/block/edit.native.js.map +1 -1
  4. package/build/code/index.js +1 -0
  5. package/build/code/index.js.map +1 -1
  6. package/build/column/index.js +1 -1
  7. package/build/columns/transforms.js +1 -5
  8. package/build/columns/transforms.js.map +1 -1
  9. package/build/cover/edit/resizable-cover-popover.js +3 -3
  10. package/build/cover/edit/resizable-cover-popover.js.map +1 -1
  11. package/build/file/interactivity.js +19 -0
  12. package/build/file/interactivity.js.map +1 -0
  13. package/build/file/{utils.js → utils/index.js} +1 -1
  14. package/build/file/utils/index.js.map +1 -0
  15. package/build/freeform/modal.js +20 -17
  16. package/build/freeform/modal.js.map +1 -1
  17. package/build/gallery/v1/edit.js +1 -7
  18. package/build/gallery/v1/edit.js.map +1 -1
  19. package/build/gallery/v1/gallery-image.native.js +1 -3
  20. package/build/gallery/v1/gallery-image.native.js.map +1 -1
  21. package/build/group/transforms.js +0 -5
  22. package/build/group/transforms.js.map +1 -1
  23. package/build/image/deprecated.js +2 -4
  24. package/build/image/deprecated.js.map +1 -1
  25. package/build/image/edit.js +13 -11
  26. package/build/image/edit.js.map +1 -1
  27. package/build/image/image.js +7 -12
  28. package/build/image/image.js.map +1 -1
  29. package/build/image/index.js +3 -0
  30. package/build/image/index.js.map +1 -1
  31. package/build/image/interactivity.js +102 -0
  32. package/build/image/interactivity.js.map +1 -0
  33. package/build/image/save.js +2 -4
  34. package/build/image/save.js.map +1 -1
  35. package/build/image/utils.js +10 -18
  36. package/build/image/utils.js.map +1 -1
  37. package/build/latest-posts/edit.native.js +1 -3
  38. package/build/latest-posts/edit.native.js.map +1 -1
  39. package/build/list/edit.js +1 -1
  40. package/build/list/edit.js.map +1 -1
  41. package/build/list-item/edit.native.js +1 -1
  42. package/build/list-item/edit.native.js.map +1 -1
  43. package/build/list-item/transforms.js +4 -1
  44. package/build/list-item/transforms.js.map +1 -1
  45. package/build/media-text/deprecated.js +4 -6
  46. package/build/media-text/deprecated.js.map +1 -1
  47. package/build/media-text/edit.js +13 -11
  48. package/build/media-text/edit.js.map +1 -1
  49. package/build/media-text/media-container.js +3 -3
  50. package/build/media-text/media-container.js.map +1 -1
  51. package/build/media-text/save.js +1 -3
  52. package/build/media-text/save.js.map +1 -1
  53. package/build/navigation/constants.js +3 -1
  54. package/build/navigation/constants.js.map +1 -1
  55. package/build/navigation/edit/inner-blocks.js +1 -0
  56. package/build/navigation/edit/inner-blocks.js.map +1 -1
  57. package/build/navigation/edit/leaf-more-menu.js +148 -0
  58. package/build/navigation/edit/leaf-more-menu.js.map +1 -0
  59. package/build/navigation/edit/menu-inspector-controls.js +53 -8
  60. package/build/navigation/edit/menu-inspector-controls.js.map +1 -1
  61. package/build/navigation/edit/navigation-menu-delete-control.js +6 -6
  62. package/build/navigation/edit/navigation-menu-delete-control.js.map +1 -1
  63. package/build/navigation/edit/unsaved-inner-blocks.js +8 -19
  64. package/build/navigation/edit/unsaved-inner-blocks.js.map +1 -1
  65. package/build/navigation/interactivity.js +24 -6
  66. package/build/navigation/interactivity.js.map +1 -1
  67. package/build/navigation-link/edit.js +6 -4
  68. package/build/navigation-link/edit.js.map +1 -1
  69. package/build/navigation-link/update-attributes.js +5 -5
  70. package/build/navigation-link/update-attributes.js.map +1 -1
  71. package/build/navigation-submenu/edit.js +6 -4
  72. package/build/navigation-submenu/edit.js.map +1 -1
  73. package/build/pattern/edit.js +42 -8
  74. package/build/pattern/edit.js.map +1 -1
  75. package/build/pattern/index.js +12 -5
  76. package/build/pattern/index.js.map +1 -1
  77. package/build/pattern/v1/edit.js +57 -0
  78. package/build/pattern/v1/edit.js.map +1 -0
  79. package/build/post-title/edit.js +10 -3
  80. package/build/post-title/edit.js.map +1 -1
  81. package/build/quote/transforms.js +9 -12
  82. package/build/quote/transforms.js.map +1 -1
  83. package/build/social-link/edit.js +21 -4
  84. package/build/social-link/edit.js.map +1 -1
  85. package/build/template-part/edit/index.js +1 -7
  86. package/build/template-part/edit/index.js.map +1 -1
  87. package/build/template-part/edit/utils/hooks.js +2 -2
  88. package/build/template-part/edit/utils/hooks.js.map +1 -1
  89. package/build/utils/interactivity/directives.js +50 -22
  90. package/build/utils/interactivity/directives.js.map +1 -1
  91. package/build/utils/interactivity/hooks.js +76 -12
  92. package/build/utils/interactivity/hooks.js.map +1 -1
  93. package/build/utils/interactivity/portals.js +108 -0
  94. package/build/utils/interactivity/portals.js.map +1 -0
  95. package/build-module/block/edit.native.js +7 -1
  96. package/build-module/block/edit.native.js.map +1 -1
  97. package/build-module/code/index.js +1 -0
  98. package/build-module/code/index.js.map +1 -1
  99. package/build-module/column/index.js +1 -1
  100. package/build-module/columns/transforms.js +1 -5
  101. package/build-module/columns/transforms.js.map +1 -1
  102. package/build-module/cover/edit/resizable-cover-popover.js +3 -3
  103. package/build-module/cover/edit/resizable-cover-popover.js.map +1 -1
  104. package/build-module/file/interactivity.js +15 -0
  105. package/build-module/file/interactivity.js.map +1 -0
  106. package/build-module/file/{utils.js → utils/index.js} +1 -1
  107. package/build-module/file/utils/index.js.map +1 -0
  108. package/build-module/freeform/modal.js +19 -18
  109. package/build-module/freeform/modal.js.map +1 -1
  110. package/build-module/gallery/v1/edit.js +1 -6
  111. package/build-module/gallery/v1/edit.js.map +1 -1
  112. package/build-module/gallery/v1/gallery-image.native.js +1 -2
  113. package/build-module/gallery/v1/gallery-image.native.js.map +1 -1
  114. package/build-module/group/transforms.js +0 -5
  115. package/build-module/group/transforms.js.map +1 -1
  116. package/build-module/image/deprecated.js +2 -3
  117. package/build-module/image/deprecated.js.map +1 -1
  118. package/build-module/image/edit.js +12 -11
  119. package/build-module/image/edit.js.map +1 -1
  120. package/build-module/image/image.js +7 -11
  121. package/build-module/image/image.js.map +1 -1
  122. package/build-module/image/index.js +3 -0
  123. package/build-module/image/index.js.map +1 -1
  124. package/build-module/image/interactivity.js +99 -0
  125. package/build-module/image/interactivity.js.map +1 -0
  126. package/build-module/image/save.js +2 -3
  127. package/build-module/image/save.js.map +1 -1
  128. package/build-module/image/utils.js +10 -17
  129. package/build-module/image/utils.js.map +1 -1
  130. package/build-module/latest-posts/edit.native.js +1 -2
  131. package/build-module/latest-posts/edit.native.js.map +1 -1
  132. package/build-module/list/edit.js +1 -1
  133. package/build-module/list/edit.js.map +1 -1
  134. package/build-module/list-item/edit.native.js +1 -1
  135. package/build-module/list-item/edit.native.js.map +1 -1
  136. package/build-module/list-item/transforms.js +5 -2
  137. package/build-module/list-item/transforms.js.map +1 -1
  138. package/build-module/media-text/deprecated.js +4 -5
  139. package/build-module/media-text/deprecated.js.map +1 -1
  140. package/build-module/media-text/edit.js +13 -12
  141. package/build-module/media-text/edit.js.map +1 -1
  142. package/build-module/media-text/media-container.js +3 -3
  143. package/build-module/media-text/media-container.js.map +1 -1
  144. package/build-module/media-text/save.js +1 -2
  145. package/build-module/media-text/save.js.map +1 -1
  146. package/build-module/navigation/constants.js +1 -0
  147. package/build-module/navigation/constants.js.map +1 -1
  148. package/build-module/navigation/edit/inner-blocks.js +2 -1
  149. package/build-module/navigation/edit/inner-blocks.js.map +1 -1
  150. package/build-module/navigation/edit/leaf-more-menu.js +132 -0
  151. package/build-module/navigation/edit/leaf-more-menu.js.map +1 -0
  152. package/build-module/navigation/edit/menu-inspector-controls.js +52 -9
  153. package/build-module/navigation/edit/menu-inspector-controls.js.map +1 -1
  154. package/build-module/navigation/edit/navigation-menu-delete-control.js +7 -7
  155. package/build-module/navigation/edit/navigation-menu-delete-control.js.map +1 -1
  156. package/build-module/navigation/edit/unsaved-inner-blocks.js +8 -16
  157. package/build-module/navigation/edit/unsaved-inner-blocks.js.map +1 -1
  158. package/build-module/navigation/interactivity.js +24 -6
  159. package/build-module/navigation/interactivity.js.map +1 -1
  160. package/build-module/navigation-link/edit.js +6 -4
  161. package/build-module/navigation-link/edit.js.map +1 -1
  162. package/build-module/navigation-link/update-attributes.js +4 -4
  163. package/build-module/navigation-link/update-attributes.js.map +1 -1
  164. package/build-module/navigation-submenu/edit.js +6 -4
  165. package/build-module/navigation-submenu/edit.js.map +1 -1
  166. package/build-module/pattern/edit.js +42 -9
  167. package/build-module/pattern/edit.js.map +1 -1
  168. package/build-module/pattern/index.js +12 -3
  169. package/build-module/pattern/index.js.map +1 -1
  170. package/build-module/pattern/v1/edit.js +48 -0
  171. package/build-module/pattern/v1/edit.js.map +1 -0
  172. package/build-module/post-title/edit.js +10 -3
  173. package/build-module/post-title/edit.js.map +1 -1
  174. package/build-module/quote/transforms.js +9 -12
  175. package/build-module/quote/transforms.js.map +1 -1
  176. package/build-module/social-link/edit.js +20 -5
  177. package/build-module/social-link/edit.js.map +1 -1
  178. package/build-module/template-part/edit/index.js +1 -6
  179. package/build-module/template-part/edit/index.js.map +1 -1
  180. package/build-module/template-part/edit/utils/hooks.js +1 -1
  181. package/build-module/template-part/edit/utils/hooks.js.map +1 -1
  182. package/build-module/utils/interactivity/directives.js +49 -22
  183. package/build-module/utils/interactivity/directives.js.map +1 -1
  184. package/build-module/utils/interactivity/hooks.js +77 -13
  185. package/build-module/utils/interactivity/hooks.js.map +1 -1
  186. package/build-module/utils/interactivity/portals.js +100 -0
  187. package/build-module/utils/interactivity/portals.js.map +1 -0
  188. package/build-style/common-rtl.css +1 -1
  189. package/build-style/common.css +1 -1
  190. package/build-style/cover/style-rtl.css +1 -2
  191. package/build-style/cover/style.css +1 -2
  192. package/build-style/editor-rtl.css +68 -0
  193. package/build-style/editor.css +68 -0
  194. package/build-style/file/editor-rtl.css +3 -0
  195. package/build-style/file/editor.css +3 -0
  196. package/build-style/freeform/editor-rtl.css +29 -0
  197. package/build-style/freeform/editor.css +29 -0
  198. package/build-style/gallery/style-rtl.css +2 -4
  199. package/build-style/gallery/style.css +2 -4
  200. package/build-style/image/style-rtl.css +98 -0
  201. package/build-style/image/style.css +98 -0
  202. package/build-style/navigation/editor-rtl.css +36 -0
  203. package/build-style/navigation/editor.css +36 -0
  204. package/build-style/post-comments-form/style-rtl.css +1 -1
  205. package/build-style/post-comments-form/style.css +1 -1
  206. package/build-style/style-rtl.css +103 -9
  207. package/build-style/style.css +103 -9
  208. package/build-style/video/style-rtl.css +1 -2
  209. package/build-style/video/style.css +1 -2
  210. package/package.json +32 -32
  211. package/src/block/edit.native.js +18 -4
  212. package/src/buttons/test/edit.native.js +0 -9
  213. package/src/code/block.json +1 -0
  214. package/src/column/block.json +1 -1
  215. package/src/columns/test/__snapshots__/transforms.native.js.snap +1 -1
  216. package/src/columns/test/transforms.native.js +3 -5
  217. package/src/columns/transforms.js +2 -8
  218. package/src/comments/index.php +1 -6
  219. package/src/cover/edit/resizable-cover-popover.js +2 -1
  220. package/src/file/editor.scss +4 -0
  221. package/src/file/interactivity.js +15 -0
  222. package/src/freeform/editor.scss +45 -0
  223. package/src/freeform/modal.js +22 -19
  224. package/src/gallery/v1/edit.js +1 -6
  225. package/src/gallery/v1/gallery-image.native.js +1 -2
  226. package/src/group/test/__snapshots__/transforms.native.js.snap +1 -1
  227. package/src/group/test/transforms.native.js +3 -5
  228. package/src/group/transforms.js +0 -7
  229. package/src/image/block.json +3 -0
  230. package/src/image/deprecated.js +2 -3
  231. package/src/image/edit.js +18 -18
  232. package/src/image/image.js +8 -11
  233. package/src/image/index.php +75 -2
  234. package/src/image/interactivity.js +113 -0
  235. package/src/image/save.js +4 -3
  236. package/src/image/style.scss +113 -0
  237. package/src/image/utils.js +11 -18
  238. package/src/latest-posts/edit.native.js +1 -4
  239. package/src/list/edit.js +1 -1
  240. package/src/list/test/edit.native.js +80 -1
  241. package/src/list-item/edit.native.js +1 -1
  242. package/src/list-item/transforms.js +4 -2
  243. package/src/media-text/deprecated.js +4 -5
  244. package/src/media-text/edit.js +12 -10
  245. package/src/media-text/media-container.js +3 -3
  246. package/src/media-text/save.js +1 -2
  247. package/src/navigation/constants.js +5 -0
  248. package/src/navigation/edit/inner-blocks.js +6 -1
  249. package/src/navigation/edit/leaf-more-menu.js +170 -0
  250. package/src/navigation/edit/menu-inspector-controls.js +78 -10
  251. package/src/navigation/edit/navigation-menu-delete-control.js +29 -29
  252. package/src/navigation/edit/unsaved-inner-blocks.js +11 -24
  253. package/src/navigation/editor.scss +10 -0
  254. package/src/navigation/index.php +4 -1
  255. package/src/navigation/interactivity.js +9 -2
  256. package/src/navigation-link/edit.js +8 -2
  257. package/src/navigation-link/update-attributes.js +2 -2
  258. package/src/navigation-submenu/edit.js +8 -2
  259. package/src/pattern/block.json +4 -0
  260. package/src/pattern/edit.js +53 -16
  261. package/src/pattern/index.js +5 -4
  262. package/src/pattern/index.php +14 -1
  263. package/src/pattern/v1/edit.js +57 -0
  264. package/src/post-comments-form/style.scss +3 -1
  265. package/src/post-title/edit.js +50 -44
  266. package/src/quote/test/__snapshots__/transforms.native.js.snap +1 -1
  267. package/src/quote/test/transforms.native.js +3 -5
  268. package/src/quote/transforms.js +9 -13
  269. package/src/social-link/edit.js +51 -26
  270. package/src/template-part/edit/index.js +4 -6
  271. package/src/template-part/edit/utils/hooks.js +1 -1
  272. package/src/template-part/index.php +2 -2
  273. package/src/utils/interactivity/directives.js +27 -6
  274. package/src/utils/interactivity/hooks.js +83 -14
  275. package/src/utils/interactivity/portals.js +98 -0
  276. package/build/file/utils.js.map +0 -1
  277. package/build-module/file/utils.js.map +0 -1
  278. /package/src/file/{utils.js → utils/index.js} +0 -0
@@ -0,0 +1,170 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { createBlock } from '@wordpress/blocks';
5
+ import {
6
+ addSubmenu,
7
+ chevronUp,
8
+ chevronDown,
9
+ moreVertical,
10
+ } from '@wordpress/icons';
11
+ import { DropdownMenu, MenuItem, MenuGroup } from '@wordpress/components';
12
+ import { useDispatch, useSelect } from '@wordpress/data';
13
+ import { __, sprintf } from '@wordpress/i18n';
14
+ import { BlockTitle, store as blockEditorStore } from '@wordpress/block-editor';
15
+
16
+ const POPOVER_PROPS = {
17
+ className: 'block-editor-block-settings-menu__popover',
18
+ position: 'bottom right',
19
+ variant: 'toolbar',
20
+ };
21
+
22
+ const BLOCKS_THAT_CAN_BE_CONVERTED_TO_SUBMENU = [
23
+ 'core/navigation-link',
24
+ 'core/navigation-submenu',
25
+ ];
26
+
27
+ function AddSubmenuItem( {
28
+ block,
29
+ onClose,
30
+ expandedState,
31
+ expand,
32
+ setInsertedBlock,
33
+ } ) {
34
+ const { insertBlock, replaceBlock, replaceInnerBlocks } =
35
+ useDispatch( blockEditorStore );
36
+
37
+ const clientId = block.clientId;
38
+ const isDisabled = ! BLOCKS_THAT_CAN_BE_CONVERTED_TO_SUBMENU.includes(
39
+ block.name
40
+ );
41
+ return (
42
+ <MenuItem
43
+ icon={ addSubmenu }
44
+ disabled={ isDisabled }
45
+ onClick={ () => {
46
+ const updateSelectionOnInsert = false;
47
+ const newLink = createBlock( 'core/navigation-link' );
48
+
49
+ if ( block.name === 'core/navigation-submenu' ) {
50
+ insertBlock(
51
+ newLink,
52
+ block.innerBlocks.length,
53
+ clientId,
54
+ updateSelectionOnInsert
55
+ );
56
+ } else {
57
+ // Convert to a submenu if the block currently isn't one.
58
+ const newSubmenu = createBlock(
59
+ 'core/navigation-submenu',
60
+ block.attributes,
61
+ block.innerBlocks
62
+ );
63
+
64
+ // The following must happen as two independent actions.
65
+ // Why? Because the offcanvas editor relies on the getLastInsertedBlocksClientIds
66
+ // selector to determine which block is "active". As the UX needs the newLink to be
67
+ // the "active" block it must be the last block to be inserted.
68
+ // Therefore the Submenu is first created and **then** the newLink is inserted
69
+ // thus ensuring it is the last inserted block.
70
+ replaceBlock( clientId, newSubmenu );
71
+
72
+ replaceInnerBlocks(
73
+ newSubmenu.clientId,
74
+ [ newLink ],
75
+ updateSelectionOnInsert
76
+ );
77
+ }
78
+
79
+ // This call sets the local List View state for the "last inserted block".
80
+ // This is required for the Nav Block to determine whether or not to display
81
+ // the Link UI for this new block.
82
+ setInsertedBlock( newLink );
83
+
84
+ if ( ! expandedState[ block.clientId ] ) {
85
+ expand( block.clientId );
86
+ }
87
+ onClose();
88
+ } }
89
+ >
90
+ { __( 'Add submenu link' ) }
91
+ </MenuItem>
92
+ );
93
+ }
94
+
95
+ export default function LeafMoreMenu( props ) {
96
+ const { block } = props;
97
+ const { clientId } = block;
98
+
99
+ const { moveBlocksDown, moveBlocksUp, removeBlocks } =
100
+ useDispatch( blockEditorStore );
101
+
102
+ const removeLabel = sprintf(
103
+ /* translators: %s: block name */
104
+ __( 'Remove %s' ),
105
+ BlockTitle( { clientId, maximumLength: 25 } )
106
+ );
107
+
108
+ const rootClientId = useSelect(
109
+ ( select ) => {
110
+ const { getBlockRootClientId } = select( blockEditorStore );
111
+
112
+ return getBlockRootClientId( clientId );
113
+ },
114
+ [ clientId ]
115
+ );
116
+
117
+ return (
118
+ <DropdownMenu
119
+ icon={ moreVertical }
120
+ label={ __( 'Options' ) }
121
+ className="block-editor-block-settings-menu"
122
+ popoverProps={ POPOVER_PROPS }
123
+ noIcons
124
+ { ...props }
125
+ >
126
+ { ( { onClose } ) => (
127
+ <>
128
+ <MenuGroup>
129
+ <MenuItem
130
+ icon={ chevronUp }
131
+ onClick={ () => {
132
+ moveBlocksUp( [ clientId ], rootClientId );
133
+ onClose();
134
+ } }
135
+ >
136
+ { __( 'Move up' ) }
137
+ </MenuItem>
138
+ <MenuItem
139
+ icon={ chevronDown }
140
+ onClick={ () => {
141
+ moveBlocksDown( [ clientId ], rootClientId );
142
+ onClose();
143
+ } }
144
+ >
145
+ { __( 'Move down' ) }
146
+ </MenuItem>
147
+ <AddSubmenuItem
148
+ block={ block }
149
+ onClose={ onClose }
150
+ expanded
151
+ expandedState={ props.expandedState }
152
+ expand={ props.expand }
153
+ setInsertedBlock={ props.setInsertedBlock }
154
+ />
155
+ </MenuGroup>
156
+ <MenuGroup>
157
+ <MenuItem
158
+ onClick={ () => {
159
+ removeBlocks( [ clientId ], false );
160
+ onClose();
161
+ } }
162
+ >
163
+ { removeLabel }
164
+ </MenuItem>
165
+ </MenuGroup>
166
+ </>
167
+ ) }
168
+ </DropdownMenu>
169
+ );
170
+ }
@@ -12,7 +12,7 @@ import {
12
12
  __experimentalHeading as Heading,
13
13
  Spinner,
14
14
  } from '@wordpress/components';
15
- import { useSelect } from '@wordpress/data';
15
+ import { useSelect, useDispatch } from '@wordpress/data';
16
16
  import { __, sprintf } from '@wordpress/i18n';
17
17
 
18
18
  /**
@@ -22,9 +22,16 @@ import NavigationMenuSelector from './navigation-menu-selector';
22
22
  import { unlock } from '../../private-apis';
23
23
  import DeletedNavigationWarning from './deleted-navigation-warning';
24
24
  import useNavigationMenu from '../use-navigation-menu';
25
+ import LeafMoreMenu from './leaf-more-menu';
26
+ import { updateAttributes } from '../../navigation-link/update-attributes';
27
+ import { LinkUI } from '../../navigation-link/link-ui';
25
28
 
26
29
  /* translators: %s: The name of a menu. */
27
30
  const actionLabel = __( "Switch to '%s'" );
31
+ const BLOCKS_WITH_LINK_UI_SUPPORT = [
32
+ 'core/navigation-link',
33
+ 'core/navigation-submenu',
34
+ ];
28
35
 
29
36
  const MainContent = ( {
30
37
  clientId,
@@ -33,7 +40,8 @@ const MainContent = ( {
33
40
  isNavigationMenuMissing,
34
41
  onCreateNew,
35
42
  } ) => {
36
- const { OffCanvasEditor, LeafMoreMenu } = unlock( blockEditorPrivateApis );
43
+ const { PrivateListView } = unlock( blockEditorPrivateApis );
44
+
37
45
  // Provide a hierarchy of clientIds for the given Navigation block (clientId).
38
46
  // This is required else the list view will display the entire block tree.
39
47
  const clientIdsTree = useSelect(
@@ -43,6 +51,15 @@ const MainContent = ( {
43
51
  },
44
52
  [ clientId ]
45
53
  );
54
+
55
+ const { updateBlockAttributes } = useDispatch( blockEditorStore );
56
+
57
+ const setInsertedBlockAttributes =
58
+ ( _insertedBlockClientId ) => ( _updatedAttributes ) => {
59
+ if ( ! _insertedBlockClientId ) return;
60
+ updateBlockAttributes( _insertedBlockClientId, _updatedAttributes );
61
+ };
62
+
46
63
  const { navigationMenu } = useNavigationMenu( currentMenuId );
47
64
 
48
65
  if ( currentMenuId && isNavigationMenuMissing ) {
@@ -57,19 +74,70 @@ const MainContent = ( {
57
74
  ? sprintf(
58
75
  /* translators: %s: The name of a menu. */
59
76
  __( 'Structure for navigation menu: %s' ),
60
- navigationMenu?.title || __( 'Untitled menu' )
77
+ navigationMenu?.title?.rendered || __( 'Untitled menu' )
61
78
  )
62
79
  : __(
63
80
  'You have not yet created any menus. Displaying a list of your Pages'
64
81
  );
82
+
83
+ const renderLinkUI = (
84
+ currentBlock,
85
+ lastInsertedBlock,
86
+ setLastInsertedBlock
87
+ ) => {
88
+ const blockSupportsLinkUI = BLOCKS_WITH_LINK_UI_SUPPORT?.includes(
89
+ lastInsertedBlock?.name
90
+ );
91
+ const currentBlockWasJustInserted =
92
+ lastInsertedBlock?.clientId === currentBlock.clientId;
93
+
94
+ const shouldShowLinkUIForBlock =
95
+ blockSupportsLinkUI && currentBlockWasJustInserted;
96
+
97
+ return (
98
+ shouldShowLinkUIForBlock && (
99
+ <LinkUI
100
+ clientId={ lastInsertedBlock?.clientId }
101
+ link={ lastInsertedBlock?.attributes }
102
+ onClose={ () => {
103
+ setLastInsertedBlock( null );
104
+ } }
105
+ hasCreateSuggestion={ false }
106
+ onChange={ ( updatedValue ) => {
107
+ updateAttributes(
108
+ updatedValue,
109
+ setInsertedBlockAttributes(
110
+ lastInsertedBlock?.clientId
111
+ ),
112
+ lastInsertedBlock?.attributes
113
+ );
114
+ setLastInsertedBlock( null );
115
+ } }
116
+ onCancel={ () => {
117
+ setLastInsertedBlock( null );
118
+ } }
119
+ />
120
+ )
121
+ );
122
+ };
123
+
65
124
  return (
66
- <OffCanvasEditor
67
- blocks={ clientIdsTree }
68
- parentClientId={ clientId }
69
- isExpanded={ true }
70
- LeafMoreMenu={ LeafMoreMenu }
71
- description={ description }
72
- />
125
+ <div className="wp-block-navigation__menu-inspector-controls">
126
+ { clientIdsTree.length === 0 && (
127
+ <p className="wp-block-navigation__menu-inspector-controls__empty-message">
128
+ { __( 'This navigation menu is empty.' ) }
129
+ </p>
130
+ ) }
131
+ <PrivateListView
132
+ blocks={ clientIdsTree }
133
+ rootClientId={ clientId }
134
+ isExpanded
135
+ description={ description }
136
+ showAppender
137
+ blockSettingsMenu={ LeafMoreMenu }
138
+ renderAdditionalBlockUI={ renderLinkUI }
139
+ />
140
+ </div>
73
141
  );
74
142
  };
75
143
 
@@ -1,7 +1,11 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { Button, Flex, FlexItem, Modal } from '@wordpress/components';
4
+ import {
5
+ Button,
6
+ Modal,
7
+ __experimentalHStack as HStack,
8
+ } from '@wordpress/components';
5
9
  import {
6
10
  store as coreStore,
7
11
  useEntityId,
@@ -44,34 +48,30 @@ export default function NavigationMenuDeleteControl( { onDelete } ) {
44
48
  'Are you sure you want to delete this navigation menu?'
45
49
  ) }
46
50
  </p>
47
- <Flex justify="flex-end">
48
- <FlexItem>
49
- <Button
50
- variant="secondary"
51
- onClick={ () => {
52
- setIsConfirmModalVisible( false );
53
- } }
54
- >
55
- { __( 'Cancel' ) }
56
- </Button>
57
- </FlexItem>
58
- <FlexItem>
59
- <Button
60
- variant="primary"
61
- onClick={ () => {
62
- deleteEntityRecord(
63
- 'postType',
64
- 'wp_navigation',
65
- id,
66
- { force: true }
67
- );
68
- onDelete( title );
69
- } }
70
- >
71
- { __( 'Confirm' ) }
72
- </Button>
73
- </FlexItem>
74
- </Flex>
51
+ <HStack justify="right">
52
+ <Button
53
+ variant="tertiary"
54
+ onClick={ () => {
55
+ setIsConfirmModalVisible( false );
56
+ } }
57
+ >
58
+ { __( 'Cancel' ) }
59
+ </Button>
60
+ <Button
61
+ variant="primary"
62
+ onClick={ () => {
63
+ deleteEntityRecord(
64
+ 'postType',
65
+ 'wp_navigation',
66
+ id,
67
+ { force: true }
68
+ );
69
+ onDelete( title );
70
+ } }
71
+ >
72
+ { __( 'Confirm' ) }
73
+ </Button>
74
+ </HStack>
75
75
  </Modal>
76
76
  ) }
77
77
  </>
@@ -10,16 +10,10 @@ import { useContext, useEffect, useRef, useMemo } from '@wordpress/element';
10
10
  /**
11
11
  * Internal dependencies
12
12
  */
13
- import useNavigationMenu from '../use-navigation-menu';
14
13
  import { areBlocksDirty } from './are-blocks-dirty';
15
14
  import { DEFAULT_BLOCK, ALLOWED_BLOCKS } from '../constants';
16
15
 
17
16
  const EMPTY_OBJECT = {};
18
- const DRAFT_MENU_PARAMS = [
19
- 'postType',
20
- 'wp_navigation',
21
- { status: 'draft', per_page: -1 },
22
- ];
23
17
 
24
18
  export default function UnsavedInnerBlocks( {
25
19
  blocks,
@@ -75,35 +69,30 @@ export default function UnsavedInnerBlocks( {
75
69
  }
76
70
  );
77
71
 
78
- const { isSaving, hasResolvedDraftNavigationMenus } = useSelect(
72
+ const { isSaving, hasResolvedAllNavigationMenus } = useSelect(
79
73
  ( select ) => {
80
74
  if ( isDisabled ) {
81
75
  return EMPTY_OBJECT;
82
76
  }
83
77
 
84
- const {
85
- getEntityRecords,
86
- hasFinishedResolution,
87
- isSavingEntityRecord,
88
- } = select( coreStore );
78
+ const { hasFinishedResolution, isSavingEntityRecord } =
79
+ select( coreStore );
89
80
 
90
81
  return {
91
82
  isSaving: isSavingEntityRecord( 'postType', 'wp_navigation' ),
92
- draftNavigationMenus: getEntityRecords(
93
- // This is needed so that hasResolvedDraftNavigationMenus gives the correct status.
94
- ...DRAFT_MENU_PARAMS
95
- ),
96
- hasResolvedDraftNavigationMenus: hasFinishedResolution(
83
+ hasResolvedAllNavigationMenus: hasFinishedResolution(
97
84
  'getEntityRecords',
98
- DRAFT_MENU_PARAMS
85
+ [
86
+ 'postType',
87
+ 'wp_navigation',
88
+ { per_page: -1, status: [ 'publish', 'draft' ] },
89
+ ]
99
90
  ),
100
91
  };
101
92
  },
102
93
  [ isDisabled ]
103
94
  );
104
95
 
105
- const { hasResolvedNavigationMenus } = useNavigationMenu();
106
-
107
96
  // Automatically save the uncontrolled blocks.
108
97
  useEffect( () => {
109
98
  // The block will be disabled when used in a BlockPreview.
@@ -121,8 +110,7 @@ export default function UnsavedInnerBlocks( {
121
110
  if (
122
111
  isDisabled ||
123
112
  isSaving ||
124
- ! hasResolvedDraftNavigationMenus ||
125
- ! hasResolvedNavigationMenus ||
113
+ ! hasResolvedAllNavigationMenus ||
126
114
  ! hasSelection ||
127
115
  ! innerBlocksAreDirty
128
116
  ) {
@@ -135,8 +123,7 @@ export default function UnsavedInnerBlocks( {
135
123
  createNavigationMenu,
136
124
  isDisabled,
137
125
  isSaving,
138
- hasResolvedDraftNavigationMenus,
139
- hasResolvedNavigationMenus,
126
+ hasResolvedAllNavigationMenus,
140
127
  innerBlocksAreDirty,
141
128
  hasSelection,
142
129
  ] );
@@ -657,3 +657,13 @@ body.editor-styles-wrapper .wp-block-navigation__responsive-container.is-menu-op
657
657
  .wp-block-navigation__responsive-container-open.components-button {
658
658
  opacity: 1;
659
659
  }
660
+
661
+ .wp-block-navigation__menu-inspector-controls {
662
+ overflow-x: auto;
663
+
664
+ @include custom-scrollbars-on-hover(transparent, $gray-600);
665
+ }
666
+
667
+ .wp-block-navigation__menu-inspector-controls__empty-message {
668
+ margin-left: 24px;
669
+ }
@@ -470,7 +470,10 @@ function render_block_core_navigation( $attributes, $content, $block ) {
470
470
 
471
471
  // Restore legacy classnames for submenu positioning.
472
472
  $layout_class = '';
473
- if ( isset( $attributes['layout']['justifyContent'] ) ) {
473
+ if (
474
+ isset( $attributes['layout']['justifyContent'] ) &&
475
+ isset( $layout_justification[ $attributes['layout']['justifyContent'] ] )
476
+ ) {
474
477
  $layout_class .= $layout_justification[ $attributes['layout']['justifyContent'] ];
475
478
  }
476
479
  if ( isset( $attributes['layout']['orientation'] ) && 'vertical' === $attributes['layout']['orientation'] ) {
@@ -21,7 +21,7 @@ store( {
21
21
  effects: {
22
22
  core: {
23
23
  navigation: {
24
- initModal: async ( { context, ref } ) => {
24
+ initMenu: ( { context, ref } ) => {
25
25
  if ( context.core.navigation.isMenuOpen ) {
26
26
  const focusableElements =
27
27
  ref.querySelectorAll( focusableSelectors );
@@ -32,7 +32,7 @@ store( {
32
32
  focusableElements[ focusableElements.length - 1 ];
33
33
  }
34
34
  },
35
- focusFirstElement: async ( { context, ref } ) => {
35
+ focusFirstElement: ( { context, ref } ) => {
36
36
  if ( context.core.navigation.isMenuOpen ) {
37
37
  ref.querySelector(
38
38
  '.wp-block-navigation-item > *:first-child'
@@ -86,6 +86,13 @@ store( {
86
86
  }
87
87
  }
88
88
  },
89
+ toggleMenu: ( { context, actions, ref } ) => {
90
+ if ( context.core.navigation.isMenuOpen ) {
91
+ actions.core.navigation.closeMenu( { context } );
92
+ } else {
93
+ actions.core.navigation.openMenu( { context, ref } );
94
+ }
95
+ },
89
96
  handleMenuKeydown: ( { actions, context, event } ) => {
90
97
  if ( context.core.navigation.isMenuOpen ) {
91
98
  // If Escape close the menu
@@ -469,8 +469,11 @@ export default function NavigationLinkEdit( {
469
469
  onChange={ ( titleValue ) => {
470
470
  setAttributes( { title: titleValue } );
471
471
  } }
472
- label={ __( 'Link title' ) }
472
+ label={ __( 'Title attribute' ) }
473
473
  autoComplete="off"
474
+ help={ __(
475
+ 'Additional information to help clarify the purpose of the link.'
476
+ ) }
474
477
  />
475
478
  <TextControl
476
479
  __nextHasNoMarginBottom
@@ -478,8 +481,11 @@ export default function NavigationLinkEdit( {
478
481
  onChange={ ( relValue ) => {
479
482
  setAttributes( { rel: relValue } );
480
483
  } }
481
- label={ __( 'Link rel' ) }
484
+ label={ __( 'Rel attribute' ) }
482
485
  autoComplete="off"
486
+ help={ __(
487
+ 'The relationship of the linked URL as space-separated link types.'
488
+ ) }
483
489
  />
484
490
  </PanelBody>
485
491
  </InspectorControls>
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { safeDecodeURI } from '@wordpress/url';
5
4
  import { escapeHTML } from '@wordpress/escape-html';
5
+ import { safeDecodeURI } from '@wordpress/url';
6
6
 
7
7
  /**
8
8
  * @typedef {'post-type'|'custom'|'taxonomy'|'post-type-archive'} WPNavigationLinkKind
@@ -89,7 +89,7 @@ export const updateAttributes = (
89
89
 
90
90
  setAttributes( {
91
91
  // Passed `url` may already be encoded. To prevent double encoding, decodeURI is executed to revert to the original string.
92
- ...{ url: newUrl ? encodeURI( safeDecodeURI( newUrl ) ) : newUrl },
92
+ ...( newUrl && { url: encodeURI( safeDecodeURI( newUrl ) ) } ),
93
93
  ...( label && { label } ),
94
94
  ...( undefined !== opensInNewTab && { opensInNewTab } ),
95
95
  ...( id && Number.isInteger( id ) && { id } ),
@@ -422,8 +422,11 @@ export default function NavigationSubmenuEdit( {
422
422
  onChange={ ( titleValue ) => {
423
423
  setAttributes( { title: titleValue } );
424
424
  } }
425
- label={ __( 'Link title' ) }
425
+ label={ __( 'Title attribute' ) }
426
426
  autoComplete="off"
427
+ help={ __(
428
+ 'Additional information to help clarify the purpose of the link.'
429
+ ) }
427
430
  />
428
431
  <TextControl
429
432
  __nextHasNoMarginBottom
@@ -431,8 +434,11 @@ export default function NavigationSubmenuEdit( {
431
434
  onChange={ ( relValue ) => {
432
435
  setAttributes( { rel: relValue } );
433
436
  } }
434
- label={ __( 'Link rel' ) }
437
+ label={ __( 'Rel attribute' ) }
435
438
  autoComplete="off"
439
+ help={ __(
440
+ 'The relationship of the linked URL as space-separated link types.'
441
+ ) }
436
442
  />
437
443
  </PanelBody>
438
444
  </InspectorControls>
@@ -13,6 +13,10 @@
13
13
  "attributes": {
14
14
  "slug": {
15
15
  "type": "string"
16
+ },
17
+ "syncStatus": {
18
+ "type": [ "string", "boolean" ],
19
+ "enum": [ "full", "partial" ]
16
20
  }
17
21
  }
18
22
  }