@wordpress/block-library 7.8.0 → 7.9.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 (292) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/build/audio/edit.js +1 -0
  3. package/build/audio/edit.js.map +1 -1
  4. package/build/audio/save.js +2 -1
  5. package/build/audio/save.js.map +1 -1
  6. package/build/avatar/hooks.js +2 -2
  7. package/build/avatar/hooks.js.map +1 -1
  8. package/build/button/edit.js +1 -1
  9. package/build/button/edit.js.map +1 -1
  10. package/build/button/index.js +1 -24
  11. package/build/button/index.js.map +1 -1
  12. package/build/button/save.js +1 -1
  13. package/build/button/save.js.map +1 -1
  14. package/build/columns/variations.js +2 -2
  15. package/build/columns/variations.js.map +1 -1
  16. package/build/comment-author-name/edit.js +3 -5
  17. package/build/comment-author-name/edit.js.map +1 -1
  18. package/build/comment-author-name/index.js +0 -4
  19. package/build/comment-author-name/index.js.map +1 -1
  20. package/build/comment-date/edit.js +4 -4
  21. package/build/comment-date/edit.js.map +1 -1
  22. package/build/comment-date/index.js +0 -4
  23. package/build/comment-date/index.js.map +1 -1
  24. package/build/comment-edit-link/index.js +0 -4
  25. package/build/comment-edit-link/index.js.map +1 -1
  26. package/build/comment-reply-link/index.js +0 -4
  27. package/build/comment-reply-link/index.js.map +1 -1
  28. package/build/comments/edit.js +10 -2
  29. package/build/comments/edit.js.map +1 -1
  30. package/build/comments-title/deprecated.js +0 -3
  31. package/build/comments-title/deprecated.js.map +1 -1
  32. package/build/cover/index.js +1 -0
  33. package/build/cover/index.js.map +1 -1
  34. package/build/embed/embed-preview.js +1 -0
  35. package/build/embed/embed-preview.js.map +1 -1
  36. package/build/embed/icons.js +21 -1
  37. package/build/embed/icons.js.map +1 -1
  38. package/build/embed/save.js +1 -0
  39. package/build/embed/save.js.map +1 -1
  40. package/build/embed/variations.js +11 -0
  41. package/build/embed/variations.js.map +1 -1
  42. package/build/file/edit.js +1 -1
  43. package/build/file/edit.js.map +1 -1
  44. package/build/file/save.js +1 -1
  45. package/build/file/save.js.map +1 -1
  46. package/build/gallery/gallery.js +1 -1
  47. package/build/gallery/gallery.js.map +1 -1
  48. package/build/gallery/save.js +1 -1
  49. package/build/gallery/save.js.map +1 -1
  50. package/build/gallery/transforms.js +2 -2
  51. package/build/gallery/transforms.js.map +1 -1
  52. package/build/gallery/v1/edit.js +3 -3
  53. package/build/gallery/v1/edit.js.map +1 -1
  54. package/build/gallery/v1/gallery-image.js +1 -0
  55. package/build/gallery/v1/gallery-image.js.map +1 -1
  56. package/build/gallery/v1/gallery.js +1 -1
  57. package/build/gallery/v1/gallery.js.map +1 -1
  58. package/build/gallery/v1/save.js +10 -2
  59. package/build/gallery/v1/save.js.map +1 -1
  60. package/build/group/index.js +1 -0
  61. package/build/group/index.js.map +1 -1
  62. package/build/html/edit.js +11 -20
  63. package/build/html/edit.js.map +1 -1
  64. package/build/html/preview.js +48 -0
  65. package/build/html/preview.js.map +1 -0
  66. package/build/image/edit.native.js +2 -1
  67. package/build/image/edit.native.js.map +1 -1
  68. package/build/image/image.js +1 -0
  69. package/build/image/image.js.map +1 -1
  70. package/build/image/save.js +1 -0
  71. package/build/image/save.js.map +1 -1
  72. package/build/list/v2/transforms.js +33 -17
  73. package/build/list/v2/transforms.js.map +1 -1
  74. package/build/list-item/hooks/use-enter.js +7 -4
  75. package/build/list-item/hooks/use-enter.js.map +1 -1
  76. package/build/list-item/hooks/use-outdent-list-item.js +36 -15
  77. package/build/list-item/hooks/use-outdent-list-item.js.map +1 -1
  78. package/build/navigation/edit/index.js +1 -1
  79. package/build/navigation/edit/index.js.map +1 -1
  80. package/build/navigation/index.js +9 -0
  81. package/build/navigation/index.js.map +1 -1
  82. package/build/navigation/use-navigation-menu.js +16 -74
  83. package/build/navigation/use-navigation-menu.js.map +1 -1
  84. package/build/navigation/view.js +5 -3
  85. package/build/navigation/view.js.map +1 -1
  86. package/build/navigation-submenu/view.js +5 -3
  87. package/build/navigation-submenu/view.js.map +1 -1
  88. package/build/post-comments-form/edit.js +12 -2
  89. package/build/post-comments-form/edit.js.map +1 -1
  90. package/build/post-comments-form/form.js +1 -1
  91. package/build/post-comments-form/form.js.map +1 -1
  92. package/build/search/edit.js +1 -1
  93. package/build/search/edit.js.map +1 -1
  94. package/build/table/edit.js +1 -0
  95. package/build/table/edit.js.map +1 -1
  96. package/build/table/save.js +2 -1
  97. package/build/table/save.js.map +1 -1
  98. package/build/video/edit.js +1 -0
  99. package/build/video/edit.js.map +1 -1
  100. package/build/video/save.js +1 -0
  101. package/build/video/save.js.map +1 -1
  102. package/build-module/audio/edit.js +2 -1
  103. package/build-module/audio/edit.js.map +1 -1
  104. package/build-module/audio/save.js +3 -2
  105. package/build-module/audio/save.js.map +1 -1
  106. package/build-module/avatar/hooks.js +2 -2
  107. package/build-module/avatar/hooks.js.map +1 -1
  108. package/build-module/button/edit.js +2 -2
  109. package/build-module/button/edit.js.map +1 -1
  110. package/build-module/button/index.js +1 -24
  111. package/build-module/button/index.js.map +1 -1
  112. package/build-module/button/save.js +2 -2
  113. package/build-module/button/save.js.map +1 -1
  114. package/build-module/columns/variations.js +2 -2
  115. package/build-module/columns/variations.js.map +1 -1
  116. package/build-module/comment-author-name/edit.js +3 -5
  117. package/build-module/comment-author-name/edit.js.map +1 -1
  118. package/build-module/comment-author-name/index.js +0 -4
  119. package/build-module/comment-author-name/index.js.map +1 -1
  120. package/build-module/comment-date/edit.js +4 -4
  121. package/build-module/comment-date/edit.js.map +1 -1
  122. package/build-module/comment-date/index.js +0 -4
  123. package/build-module/comment-date/index.js.map +1 -1
  124. package/build-module/comment-edit-link/index.js +0 -4
  125. package/build-module/comment-edit-link/index.js.map +1 -1
  126. package/build-module/comment-reply-link/index.js +0 -4
  127. package/build-module/comment-reply-link/index.js.map +1 -1
  128. package/build-module/comments/edit.js +10 -2
  129. package/build-module/comments/edit.js.map +1 -1
  130. package/build-module/comments-title/deprecated.js +0 -3
  131. package/build-module/comments-title/deprecated.js.map +1 -1
  132. package/build-module/cover/index.js +1 -0
  133. package/build-module/cover/index.js.map +1 -1
  134. package/build-module/embed/embed-preview.js +2 -1
  135. package/build-module/embed/embed-preview.js.map +1 -1
  136. package/build-module/embed/icons.js +19 -0
  137. package/build-module/embed/icons.js.map +1 -1
  138. package/build-module/embed/save.js +2 -1
  139. package/build-module/embed/save.js.map +1 -1
  140. package/build-module/embed/variations.js +12 -1
  141. package/build-module/embed/variations.js.map +1 -1
  142. package/build-module/file/edit.js +2 -2
  143. package/build-module/file/edit.js.map +1 -1
  144. package/build-module/file/save.js +2 -2
  145. package/build-module/file/save.js.map +1 -1
  146. package/build-module/gallery/gallery.js +2 -2
  147. package/build-module/gallery/gallery.js.map +1 -1
  148. package/build-module/gallery/save.js +2 -2
  149. package/build-module/gallery/save.js.map +1 -1
  150. package/build-module/gallery/transforms.js +3 -3
  151. package/build-module/gallery/transforms.js.map +1 -1
  152. package/build-module/gallery/v1/edit.js +4 -4
  153. package/build-module/gallery/v1/edit.js.map +1 -1
  154. package/build-module/gallery/v1/gallery-image.js +2 -1
  155. package/build-module/gallery/v1/gallery-image.js.map +1 -1
  156. package/build-module/gallery/v1/gallery.js +2 -2
  157. package/build-module/gallery/v1/gallery.js.map +1 -1
  158. package/build-module/gallery/v1/save.js +8 -3
  159. package/build-module/gallery/v1/save.js.map +1 -1
  160. package/build-module/group/index.js +1 -0
  161. package/build-module/group/index.js.map +1 -1
  162. package/build-module/html/edit.js +12 -23
  163. package/build-module/html/edit.js.map +1 -1
  164. package/build-module/html/preview.js +38 -0
  165. package/build-module/html/preview.js.map +1 -0
  166. package/build-module/image/edit.native.js +2 -1
  167. package/build-module/image/edit.native.js.map +1 -1
  168. package/build-module/image/image.js +2 -1
  169. package/build-module/image/image.js.map +1 -1
  170. package/build-module/image/save.js +2 -1
  171. package/build-module/image/save.js.map +1 -1
  172. package/build-module/list/v2/transforms.js +32 -17
  173. package/build-module/list/v2/transforms.js.map +1 -1
  174. package/build-module/list-item/hooks/use-enter.js +7 -4
  175. package/build-module/list-item/hooks/use-enter.js.map +1 -1
  176. package/build-module/list-item/hooks/use-outdent-list-item.js +34 -15
  177. package/build-module/list-item/hooks/use-outdent-list-item.js.map +1 -1
  178. package/build-module/navigation/edit/index.js +1 -1
  179. package/build-module/navigation/edit/index.js.map +1 -1
  180. package/build-module/navigation/index.js +9 -0
  181. package/build-module/navigation/index.js.map +1 -1
  182. package/build-module/navigation/use-navigation-menu.js +17 -75
  183. package/build-module/navigation/use-navigation-menu.js.map +1 -1
  184. package/build-module/navigation/view.js +5 -3
  185. package/build-module/navigation/view.js.map +1 -1
  186. package/build-module/navigation-submenu/view.js +5 -3
  187. package/build-module/navigation-submenu/view.js.map +1 -1
  188. package/build-module/post-comments-form/edit.js +12 -3
  189. package/build-module/post-comments-form/edit.js.map +1 -1
  190. package/build-module/post-comments-form/form.js +2 -2
  191. package/build-module/post-comments-form/form.js.map +1 -1
  192. package/build-module/search/edit.js +2 -2
  193. package/build-module/search/edit.js.map +1 -1
  194. package/build-module/table/edit.js +2 -1
  195. package/build-module/table/edit.js.map +1 -1
  196. package/build-module/table/save.js +3 -2
  197. package/build-module/table/save.js.map +1 -1
  198. package/build-module/video/edit.js +2 -1
  199. package/build-module/video/edit.js.map +1 -1
  200. package/build-module/video/save.js +2 -1
  201. package/build-module/video/save.js.map +1 -1
  202. package/build-style/button/style-rtl.css +5 -0
  203. package/build-style/button/style.css +5 -0
  204. package/build-style/editor-rtl.css +3 -0
  205. package/build-style/editor.css +3 -0
  206. package/build-style/file/style-rtl.css +5 -8
  207. package/build-style/file/style.css +5 -8
  208. package/build-style/navigation/style-rtl.css +9 -1
  209. package/build-style/navigation/style.css +9 -1
  210. package/build-style/post-comments/style-rtl.css +2 -1
  211. package/build-style/post-comments/style.css +2 -1
  212. package/build-style/post-comments-form/editor-rtl.css +3 -0
  213. package/build-style/post-comments-form/editor.css +3 -0
  214. package/build-style/post-template/style-rtl.css +9 -18
  215. package/build-style/post-template/style.css +9 -18
  216. package/build-style/search/style-rtl.css +6 -8
  217. package/build-style/search/style.css +6 -8
  218. package/build-style/style-rtl.css +36 -36
  219. package/build-style/style.css +36 -36
  220. package/package.json +28 -28
  221. package/src/audio/edit.js +4 -0
  222. package/src/audio/save.js +12 -2
  223. package/src/avatar/hooks.js +6 -9
  224. package/src/button/block.json +1 -24
  225. package/src/button/edit.js +2 -2
  226. package/src/button/save.js +2 -2
  227. package/src/button/style.scss +10 -0
  228. package/src/columns/variations.js +2 -2
  229. package/src/comment-author-name/block.json +0 -4
  230. package/src/comment-author-name/edit.js +3 -12
  231. package/src/comment-date/block.json +0 -4
  232. package/src/comment-date/edit.js +10 -14
  233. package/src/comment-date/index.php +0 -3
  234. package/src/comment-edit-link/block.json +0 -4
  235. package/src/comment-reply-link/block.json +0 -4
  236. package/src/comments/edit.js +24 -4
  237. package/src/comments-title/deprecated.js +0 -2
  238. package/src/cover/block.json +1 -0
  239. package/src/cover/index.php +21 -8
  240. package/src/embed/embed-preview.js +8 -1
  241. package/src/embed/icons.js +25 -0
  242. package/src/embed/save.js +10 -2
  243. package/src/embed/test/__snapshots__/index.native.js.snap +1 -1
  244. package/src/embed/variations.js +10 -0
  245. package/src/file/edit.js +4 -2
  246. package/src/file/save.js +2 -2
  247. package/src/file/style.scss +5 -5
  248. package/src/freeform/editor.scss +0 -2
  249. package/src/gallery/gallery.js +9 -2
  250. package/src/gallery/index.php +4 -0
  251. package/src/gallery/save.js +5 -1
  252. package/src/gallery/test/__snapshots__/index.native.js.snap +2 -2
  253. package/src/gallery/test/helpers.native.js +11 -198
  254. package/src/gallery/test/index.native.js +19 -29
  255. package/src/gallery/transforms.js +3 -3
  256. package/src/gallery/v1/edit.js +3 -4
  257. package/src/gallery/v1/gallery-image.js +4 -0
  258. package/src/gallery/v1/gallery.js +8 -2
  259. package/src/gallery/v1/save.js +20 -3
  260. package/src/group/block.json +1 -0
  261. package/src/html/edit.js +10 -40
  262. package/src/html/preview.js +46 -0
  263. package/src/image/edit.native.js +1 -0
  264. package/src/image/image.js +2 -0
  265. package/src/image/save.js +10 -2
  266. package/src/image/test/edit.native.js +51 -19
  267. package/src/list/v2/transforms.js +22 -7
  268. package/src/list-item/hooks/use-enter.js +9 -6
  269. package/src/list-item/hooks/use-outdent-list-item.js +48 -21
  270. package/src/navigation/block.json +9 -0
  271. package/src/navigation/edit/index.js +1 -0
  272. package/src/navigation/style.scss +10 -1
  273. package/src/navigation/test/use-navigation-menu.js +16 -11
  274. package/src/navigation/use-navigation-menu.js +26 -83
  275. package/src/navigation/view.js +7 -2
  276. package/src/navigation-submenu/view.js +7 -2
  277. package/src/post-comments/index.php +1 -1
  278. package/src/post-comments/style.scss +7 -3
  279. package/src/post-comments-form/edit.js +20 -3
  280. package/src/post-comments-form/editor.scss +4 -0
  281. package/src/post-comments-form/form.js +2 -2
  282. package/src/post-comments-form/index.php +1 -1
  283. package/src/post-featured-image/index.php +4 -2
  284. package/src/post-template/index.php +15 -3
  285. package/src/post-template/style.scss +1 -7
  286. package/src/search/edit.js +2 -2
  287. package/src/search/index.php +12 -10
  288. package/src/search/style.scss +9 -8
  289. package/src/table/edit.js +2 -0
  290. package/src/table/save.js +6 -1
  291. package/src/video/edit.js +4 -0
  292. package/src/video/save.js +10 -2
@@ -1,9 +1,15 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import { first, last } from 'lodash';
5
+
1
6
  /**
2
7
  * WordPress dependencies
3
8
  */
4
9
  import { useCallback } from '@wordpress/element';
5
10
  import { useSelect, useDispatch } from '@wordpress/data';
6
11
  import { store as blockEditorStore } from '@wordpress/block-editor';
12
+ import { cloneBlock } from '@wordpress/blocks';
7
13
 
8
14
  /**
9
15
  * Internal dependencies
@@ -23,7 +29,8 @@ export default function useOutdentListItem( clientId ) {
23
29
  },
24
30
  [ clientId ]
25
31
  );
26
- const { replaceBlocks, selectionChange } = useDispatch( blockEditorStore );
32
+ const { replaceBlocks, selectionChange, multiSelect } =
33
+ useDispatch( blockEditorStore );
27
34
  const {
28
35
  getBlockRootClientId,
29
36
  getBlockAttributes,
@@ -31,11 +38,18 @@ export default function useOutdentListItem( clientId ) {
31
38
  getBlockIndex,
32
39
  getSelectionStart,
33
40
  getSelectionEnd,
41
+ hasMultiSelection,
42
+ getMultiSelectedBlockClientIds,
34
43
  } = useSelect( blockEditorStore );
35
44
 
36
45
  return [
37
46
  canOutdent,
38
47
  useCallback( () => {
48
+ const _hasMultiSelection = hasMultiSelection();
49
+ const clientIds = _hasMultiSelection
50
+ ? getMultiSelectedBlockClientIds()
51
+ : [ clientId ];
52
+
39
53
  const selectionStart = getSelectionStart();
40
54
  const selectionEnd = getSelectionEnd();
41
55
 
@@ -45,50 +59,63 @@ export default function useOutdentListItem( clientId ) {
45
59
  const listItemParentAttributes =
46
60
  getBlockAttributes( listItemParentId );
47
61
 
48
- const index = getBlockIndex( clientId );
62
+ const firstIndex = getBlockIndex( first( clientIds ) );
63
+ const lastIndex = getBlockIndex( last( clientIds ) );
49
64
  const siblingBlocks = getBlock( listParentId ).innerBlocks;
50
- const previousSiblings = siblingBlocks.slice( 0, index );
51
- const afterSiblings = siblingBlocks.slice( index + 1 );
65
+ const previousSiblings = siblingBlocks.slice( 0, firstIndex );
66
+ const afterSiblings = siblingBlocks.slice( lastIndex + 1 );
52
67
 
53
68
  // Create a new parent list item block with just the siblings
54
- // that existed before the child item being outdent.
69
+ // that existed before the first child item being outdent.
55
70
  const newListItemParent = createListItem(
56
71
  listItemParentAttributes,
57
72
  listAttributes,
58
73
  previousSiblings
59
74
  );
60
75
 
61
- const block = getBlock( clientId );
62
- const childList = block.innerBlocks[ 0 ];
76
+ const lastBlock = getBlock( last( clientIds ) );
77
+ const childList = lastBlock.innerBlocks[ 0 ];
63
78
  const childItems = childList?.innerBlocks || [];
64
79
  const hasChildItems = !! childItems.length;
65
80
 
81
+ const newBlocksExcludingLast = clientIds
82
+ .slice( 0, -1 )
83
+ .map( ( _clientId ) => cloneBlock( getBlock( _clientId ) ) );
84
+
66
85
  // Create a new list item block whose attributes are equal to the
67
- // block being outdent and whose children are the children that it had (if any)
86
+ // last block being outdent and whose children are the children that it had (if any)
68
87
  // followed by the siblings that existed after it.
69
- const newItem = createListItem(
70
- block.attributes,
88
+ const newLastItem = createListItem(
89
+ lastBlock.attributes,
71
90
  hasChildItems ? childList.attributes : listAttributes,
72
91
  [ ...childItems, ...afterSiblings ]
73
92
  );
74
93
 
75
94
  // Replace the parent list item block, with a new block containing
76
- // the previous siblings, followed by another block containing after siblings
77
- // in relation to the block being outdent.
95
+ // the previous siblings before the first block being outdent,
96
+ // followed by the blocks being outdent with the after siblings added
97
+ // as children of the last block.
78
98
  replaceBlocks(
79
99
  [ listItemParentId ],
80
- [ newListItemParent, newItem ]
100
+ [ newListItemParent, ...newBlocksExcludingLast, newLastItem ]
81
101
  );
82
102
 
83
103
  // Restore the selection state.
84
- selectionChange(
85
- newItem.clientId,
86
- selectionEnd.attributeKey,
87
- selectionEnd.clientId === selectionStart.clientId
88
- ? selectionStart.offset
89
- : selectionEnd.offset,
90
- selectionEnd.offset
91
- );
104
+ if ( ! _hasMultiSelection ) {
105
+ selectionChange(
106
+ newLastItem.clientId,
107
+ selectionEnd.attributeKey,
108
+ selectionEnd.clientId === selectionStart.clientId
109
+ ? selectionStart.offset
110
+ : selectionEnd.offset,
111
+ selectionEnd.offset
112
+ );
113
+ } else {
114
+ multiSelect(
115
+ first( newBlocksExcludingLast ).clientId,
116
+ newLastItem.clientId
117
+ );
118
+ }
92
119
  }, [ clientId ] ),
93
120
  ];
94
121
  }
@@ -114,6 +114,15 @@
114
114
  "default": {
115
115
  "type": "flex"
116
116
  }
117
+ },
118
+ "__experimentalStyle": {
119
+ "elements": {
120
+ "link": {
121
+ "color": {
122
+ "text": "inherit"
123
+ }
124
+ }
125
+ }
117
126
  }
118
127
  },
119
128
  "viewScript": [ "file:./view.min.js", "file:./view-modal.min.js" ],
@@ -472,6 +472,7 @@ function Navigation( {
472
472
 
473
473
  if ( isSelected || isInnerBlockSelected ) {
474
474
  if (
475
+ ref &&
475
476
  hasResolvedCanUserUpdateNavigationMenu &&
476
477
  ! canUserUpdateNavigationMenu
477
478
  ) {
@@ -44,7 +44,6 @@ $navigation-icon-size: 24px;
44
44
  // By adding low specificity, we enable compatibility with link colors set in theme.json,
45
45
  // but still allow them to be overridden by user-set colors.
46
46
  .wp-block-navigation-item__content {
47
- color: inherit;
48
47
  display: block;
49
48
 
50
49
  // Set the default menu item padding to zero, to allow text-only buttons.
@@ -675,6 +674,16 @@ button.wp-block-navigation-item__content {
675
674
  position: relative;
676
675
  }
677
676
 
677
+ // Adjust open dialog top margin when admin-bar is visible.
678
+ .has-modal-open .admin-bar .wp-block-navigation__responsive-dialog {
679
+ margin-top: $admin-bar-height-big;
680
+
681
+ // Handle smaller admin-bar.
682
+ @include break-medium() {
683
+ margin-top: $admin-bar-height;
684
+ }
685
+ }
686
+
678
687
  // Prevent scrolling of the parent content when the modal is open.
679
688
  html.has-modal-open {
680
689
  overflow: hidden;
@@ -89,13 +89,14 @@ describe( 'useNavigationMenus', () => {
89
89
  it( 'Should return no information when no data is resolved', () => {
90
90
  expect( useNavigationMenu() ).toEqual( {
91
91
  navigationMenus: null,
92
+ navigationMenu: undefined,
92
93
  canSwitchNavigationMenu: false,
93
94
  canUserCreateNavigationMenu: false,
94
- canUserDeleteNavigationMenu: false,
95
- canUserUpdateNavigationMenu: false,
95
+ canUserDeleteNavigationMenu: undefined,
96
+ canUserUpdateNavigationMenu: undefined,
96
97
  hasResolvedCanUserCreateNavigationMenu: false,
97
- hasResolvedCanUserDeleteNavigationMenu: false,
98
- hasResolvedCanUserUpdateNavigationMenu: false,
98
+ hasResolvedCanUserDeleteNavigationMenu: undefined,
99
+ hasResolvedCanUserUpdateNavigationMenu: undefined,
99
100
  hasResolvedNavigationMenus: false,
100
101
  isNavigationMenuMissing: true,
101
102
  isNavigationMenuResolved: false,
@@ -109,13 +110,14 @@ describe( 'useNavigationMenus', () => {
109
110
  resolveCreatePermission( registry, true );
110
111
  expect( useNavigationMenu() ).toEqual( {
111
112
  navigationMenus,
113
+ navigationMenu: undefined,
112
114
  canSwitchNavigationMenu: true,
113
115
  canUserCreateNavigationMenu: true,
114
- canUserDeleteNavigationMenu: false,
115
- canUserUpdateNavigationMenu: false,
116
+ canUserDeleteNavigationMenu: undefined,
117
+ canUserUpdateNavigationMenu: undefined,
116
118
  hasResolvedCanUserCreateNavigationMenu: true,
117
- hasResolvedCanUserDeleteNavigationMenu: false,
118
- hasResolvedCanUserUpdateNavigationMenu: false,
119
+ hasResolvedCanUserDeleteNavigationMenu: undefined,
120
+ hasResolvedCanUserUpdateNavigationMenu: undefined,
119
121
  hasResolvedNavigationMenus: true,
120
122
  isNavigationMenuMissing: true,
121
123
  isNavigationMenuResolved: false,
@@ -170,6 +172,7 @@ describe( 'useNavigationMenus', () => {
170
172
  resolveRecords( registry, navigationMenus );
171
173
  resolveCreatePermission( registry, true );
172
174
  resolveUpdatePermission( registry, 1, true );
175
+ resolveDeletePermission( registry, 1, false );
173
176
  expect( useNavigationMenu( 1 ) ).toEqual( {
174
177
  navigationMenu: navigationMenu1,
175
178
  navigationMenus,
@@ -178,7 +181,7 @@ describe( 'useNavigationMenus', () => {
178
181
  canUserDeleteNavigationMenu: false,
179
182
  canUserUpdateNavigationMenu: true,
180
183
  hasResolvedCanUserCreateNavigationMenu: true,
181
- hasResolvedCanUserDeleteNavigationMenu: false,
184
+ hasResolvedCanUserDeleteNavigationMenu: true,
182
185
  hasResolvedCanUserUpdateNavigationMenu: true,
183
186
  hasResolvedNavigationMenus: true,
184
187
  isNavigationMenuMissing: false,
@@ -190,6 +193,8 @@ describe( 'useNavigationMenus', () => {
190
193
 
191
194
  it( 'Should return correct permissions (delete only)', () => {
192
195
  resolveRecords( registry, navigationMenus );
196
+ resolveCreatePermission( registry, false );
197
+ resolveUpdatePermission( registry, 1, false );
193
198
  resolveDeletePermission( registry, 1, true );
194
199
  expect( useNavigationMenu( 1 ) ).toEqual( {
195
200
  navigationMenu: navigationMenu1,
@@ -198,9 +203,9 @@ describe( 'useNavigationMenus', () => {
198
203
  canUserCreateNavigationMenu: false,
199
204
  canUserDeleteNavigationMenu: true,
200
205
  canUserUpdateNavigationMenu: false,
201
- hasResolvedCanUserCreateNavigationMenu: false,
206
+ hasResolvedCanUserCreateNavigationMenu: true,
202
207
  hasResolvedCanUserDeleteNavigationMenu: true,
203
- hasResolvedCanUserUpdateNavigationMenu: false,
208
+ hasResolvedCanUserUpdateNavigationMenu: true,
204
209
  hasResolvedNavigationMenus: true,
205
210
  isNavigationMenuMissing: false,
206
211
  isNavigationMenuResolved: false,
@@ -1,12 +1,22 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { store as coreStore } from '@wordpress/core-data';
4
+ import {
5
+ store as coreStore,
6
+ __experimentalUseResourcePermissions as useResourcePermissions,
7
+ } from '@wordpress/core-data';
5
8
  import { useSelect } from '@wordpress/data';
6
9
 
7
10
  export default function useNavigationMenu( ref ) {
11
+ const permissions = useResourcePermissions( 'navigation', ref );
12
+
8
13
  return useSelect(
9
14
  ( select ) => {
15
+ const [
16
+ hasResolvedPermissions,
17
+ { canCreate, canUpdate, canDelete, isResolving },
18
+ ] = permissions;
19
+
10
20
  const {
11
21
  navigationMenus,
12
22
  isResolvingNavigationMenus,
@@ -19,22 +29,6 @@ export default function useNavigationMenu( ref ) {
19
29
  isNavigationMenuMissing,
20
30
  } = selectExistingMenu( select, ref );
21
31
 
22
- const {
23
- canUserCreateNavigationMenu,
24
- isResolvingCanUserCreateNavigationMenu,
25
- hasResolvedCanUserCreateNavigationMenu,
26
- } = selectMenuCreatePermissions( select );
27
-
28
- const {
29
- canUserUpdateNavigationMenu,
30
- hasResolvedCanUserUpdateNavigationMenu,
31
- } = selectMenuUpdatePermissions( select, ref );
32
-
33
- const {
34
- canUserDeleteNavigationMenu,
35
- hasResolvedCanUserDeleteNavigationMenu,
36
- } = selectMenuDeletePermissions( select, ref );
37
-
38
32
  return {
39
33
  navigationMenus,
40
34
  isResolvingNavigationMenus,
@@ -44,22 +38,26 @@ export default function useNavigationMenu( ref ) {
44
38
  isNavigationMenuResolved,
45
39
  isNavigationMenuMissing,
46
40
 
47
- canUserCreateNavigationMenu,
48
- isResolvingCanUserCreateNavigationMenu,
49
- hasResolvedCanUserCreateNavigationMenu,
50
-
51
- canUserUpdateNavigationMenu,
52
- hasResolvedCanUserUpdateNavigationMenu,
53
-
54
- canUserDeleteNavigationMenu,
55
- hasResolvedCanUserDeleteNavigationMenu,
56
-
57
41
  canSwitchNavigationMenu: ref
58
42
  ? navigationMenus?.length > 1
59
43
  : navigationMenus?.length > 0,
44
+
45
+ canUserCreateNavigationMenu: canCreate,
46
+ isResolvingCanUserCreateNavigationMenu: isResolving,
47
+ hasResolvedCanUserCreateNavigationMenu: hasResolvedPermissions,
48
+
49
+ canUserUpdateNavigationMenu: canUpdate,
50
+ hasResolvedCanUserUpdateNavigationMenu: ref
51
+ ? hasResolvedPermissions
52
+ : undefined,
53
+
54
+ canUserDeleteNavigationMenu: canDelete,
55
+ hasResolvedCanUserDeleteNavigationMenu: ref
56
+ ? hasResolvedPermissions
57
+ : undefined,
60
58
  };
61
59
  },
62
- [ ref ]
60
+ [ ref, permissions ]
63
61
  );
64
62
  }
65
63
 
@@ -113,58 +111,3 @@ function selectExistingMenu( select, ref ) {
113
111
  : null,
114
112
  };
115
113
  }
116
-
117
- function selectMenuCreatePermissions( select ) {
118
- const { hasFinishedResolution, isResolving, canUser } = select( coreStore );
119
-
120
- const args = [ 'create', 'navigation' ];
121
- return {
122
- canUserCreateNavigationMenu: !! canUser( ...args ),
123
- isResolvingCanUserCreateNavigationMenu: !! isResolving(
124
- 'canUser',
125
- args
126
- ),
127
- hasResolvedCanUserCreateNavigationMenu: !! hasFinishedResolution(
128
- 'canUser',
129
- args
130
- ),
131
- };
132
- }
133
-
134
- function selectMenuUpdatePermissions( select, ref ) {
135
- if ( ! ref ) {
136
- return {
137
- canUserUpdateNavigationMenu: false,
138
- hasResolvedCanUserUpdateNavigationMenu: false,
139
- };
140
- }
141
-
142
- const { hasFinishedResolution, canUser } = select( coreStore );
143
- const args = [ 'update', 'navigation', ref ];
144
- return {
145
- canUserUpdateNavigationMenu: !! canUser( ...args ),
146
- hasResolvedCanUserUpdateNavigationMenu: !! hasFinishedResolution(
147
- 'canUser',
148
- args
149
- ),
150
- };
151
- }
152
-
153
- function selectMenuDeletePermissions( select, ref ) {
154
- if ( ! ref ) {
155
- return {
156
- canUserDeleteNavigationMenu: false,
157
- hasResolvedCanUserDeleteNavigationMenu: false,
158
- };
159
- }
160
-
161
- const { hasFinishedResolution, canUser } = select( coreStore );
162
- const args = [ 'delete', 'navigation', ref ];
163
- return {
164
- canUserDeleteNavigationMenu: !! canUser( ...args ),
165
- hasResolvedCanUserDeleteNavigationMenu: !! hasFinishedResolution(
166
- 'canUser',
167
- args
168
- ),
169
- };
170
- }
@@ -4,6 +4,8 @@ function closeSubmenus( element ) {
4
4
  .querySelectorAll( '[aria-expanded="true"]' )
5
5
  .forEach( function ( toggle ) {
6
6
  toggle.setAttribute( 'aria-expanded', 'false' );
7
+ // Always focus the trigger, this becomes especially useful in closing submenus with escape key to ensure focus doesn't get trapped.
8
+ toggle.focus();
7
9
  } );
8
10
  }
9
11
 
@@ -55,13 +57,16 @@ window.addEventListener( 'load', () => {
55
57
  }
56
58
  } );
57
59
  } );
58
- // Close on focus outside.
60
+ // Close on focus outside or escape key.
59
61
  document.addEventListener( 'keyup', function ( event ) {
60
62
  const submenuBlocks = document.querySelectorAll(
61
63
  '.wp-block-navigation-item.has-child'
62
64
  );
63
65
  submenuBlocks.forEach( function ( block ) {
64
- if ( ! block.contains( event.target ) ) {
66
+ if (
67
+ ! block.contains( event.target ) ||
68
+ ( block.contains( event.target ) && event.key === 'Escape' )
69
+ ) {
65
70
  closeSubmenus( block );
66
71
  }
67
72
  } );
@@ -3,6 +3,8 @@ const closeSubmenus = ( element ) => {
3
3
  .querySelectorAll( '[aria-expanded="true"]' )
4
4
  .forEach( ( toggle ) => {
5
5
  toggle.setAttribute( 'aria-expanded', 'false' );
6
+ // Always focus the trigger, this becomes especially useful in closing submenus with escape key to ensure focus doesn't get trapped.
7
+ toggle.focus();
6
8
  } );
7
9
  };
8
10
 
@@ -49,13 +51,16 @@ document.addEventListener( 'click', function ( event ) {
49
51
  }
50
52
  } );
51
53
  } );
52
- // Close on focus outside.
54
+ // Close on focus outside or escape key.
53
55
  document.addEventListener( 'keyup', function ( event ) {
54
56
  const submenuBlocks = document.querySelectorAll(
55
57
  '.wp-block-navigation-submenu'
56
58
  );
57
59
  submenuBlocks.forEach( ( block ) => {
58
- if ( ! block.contains( event.target ) ) {
60
+ if (
61
+ ! block.contains( event.target ) ||
62
+ ( block.contains( event.target ) && event.key === 'Escape' )
63
+ ) {
59
64
  closeSubmenus( block );
60
65
  }
61
66
  } );
@@ -78,7 +78,7 @@ add_action( 'init', 'register_block_core_post_comments' );
78
78
  */
79
79
  function post_comments_block_form_defaults( $fields ) {
80
80
  if ( wp_is_block_theme() ) {
81
- $fields['submit_button'] = '<input name="%1$s" type="submit" id="%2$s" class="%3$s wp-block-button__link ' . WP_Theme_JSON_Gutenberg::__EXPERIMENTAL_ELEMENT_BUTTON_CLASS_NAME . '" value="%4$s" />';
81
+ $fields['submit_button'] = '<input name="%1$s" type="submit" id="%2$s" class="%3$s wp-block-button__link ' . WP_Theme_JSON_Gutenberg::get_element_class_name( 'button' ) . '" value="%4$s" />';
82
82
  $fields['submit_field'] = '<p class="form-submit wp-block-button">%1$s %2$s</p>';
83
83
  }
84
84
 
@@ -128,8 +128,12 @@
128
128
  input:not([type="submit"]):not([type="checkbox"]) {
129
129
  padding: calc(0.667em + 2px); // The extra 2px is added to match outline buttons.
130
130
  }
131
+ }
131
132
 
132
- input[type="submit"] {
133
- border: none;
134
- }
133
+
134
+ // Using :where to give this a low specificity so that element styles take precedence.
135
+ // Needed for backwards compatibility.
136
+ // Styles copied from button block styles.
137
+ :where(.wp-block-post-comments input[type="submit"]) {
138
+ border: none;
135
139
  }
@@ -13,9 +13,11 @@ import {
13
13
  useBlockProps,
14
14
  store as blockEditorStore,
15
15
  } from '@wordpress/block-editor';
16
+ import { Button } from '@wordpress/components';
16
17
  import { useEntityProp, store as coreStore } from '@wordpress/core-data';
17
- import { __, sprintf } from '@wordpress/i18n';
18
+ import { __, _x, sprintf } from '@wordpress/i18n';
18
19
  import { useSelect } from '@wordpress/data';
20
+
19
21
  /**
20
22
  * Internal dependencies
21
23
  */
@@ -28,7 +30,7 @@ export default function PostCommentsFormEdit( {
28
30
  } ) {
29
31
  const { textAlign } = attributes;
30
32
  const { postId, postType } = context;
31
- const [ commentStatus ] = useEntityProp(
33
+ const [ commentStatus, setCommentStatus ] = useEntityProp(
32
34
  'postType',
33
35
  postType,
34
36
  'comment_status',
@@ -55,6 +57,7 @@ export default function PostCommentsFormEdit( {
55
57
  );
56
58
 
57
59
  let warning = false;
60
+ let actions;
58
61
  let showPlaceholder = true;
59
62
 
60
63
  if ( ! isSiteEditor && 'open' !== commentStatus ) {
@@ -66,6 +69,18 @@ export default function PostCommentsFormEdit( {
66
69
  ),
67
70
  postType
68
71
  );
72
+ actions = [
73
+ <Button
74
+ key="enableComments"
75
+ onClick={ () => setCommentStatus( 'open' ) }
76
+ variant="primary"
77
+ >
78
+ { _x(
79
+ 'Enable comments',
80
+ 'action that affects the current post'
81
+ ) }
82
+ </Button>,
83
+ ];
69
84
  showPlaceholder = false;
70
85
  } else if ( ! postTypeSupportsComments ) {
71
86
  warning = sprintf(
@@ -95,7 +110,9 @@ export default function PostCommentsFormEdit( {
95
110
  />
96
111
  </BlockControls>
97
112
  <div { ...blockProps }>
98
- { warning && <Warning>{ warning }</Warning> }
113
+ { warning && (
114
+ <Warning actions={ actions }>{ warning }</Warning>
115
+ ) }
99
116
 
100
117
  { showPlaceholder ? <CommentsForm /> : null }
101
118
  </div>
@@ -1,3 +1,7 @@
1
1
  .wp-block-post-comments-form * {
2
2
  pointer-events: none;
3
+
4
+ &.block-editor-warning * {
5
+ pointer-events: auto;
6
+ }
3
7
  }
@@ -7,7 +7,7 @@ import classnames from 'classnames';
7
7
  * WordPress dependencies
8
8
  */
9
9
  import { __ } from '@wordpress/i18n';
10
- import { __experimentalElementButtonClassName } from '@wordpress/block-editor';
10
+ import { __experimentalGetElementClassName } from '@wordpress/block-editor';
11
11
  import { useDisabled, useInstanceId } from '@wordpress/compose';
12
12
 
13
13
  const CommentsForm = () => {
@@ -36,7 +36,7 @@ const CommentsForm = () => {
36
36
  className={ classnames(
37
37
  'submit',
38
38
  'wp-block-button__link',
39
- __experimentalElementButtonClassName
39
+ __experimentalGetElementClassName( 'button' )
40
40
  ) }
41
41
  label={ __( 'Post Comment' ) }
42
42
  value={ __( 'Post Comment' ) }
@@ -72,7 +72,7 @@ add_action( 'init', 'register_block_core_post_comments_form' );
72
72
  */
73
73
  function post_comments_form_block_form_defaults( $fields ) {
74
74
  if ( wp_is_block_theme() ) {
75
- $fields['submit_button'] = '<input name="%1$s" type="submit" id="%2$s" class="%3$s wp-block-button__link ' . WP_Theme_JSON_Gutenberg::__EXPERIMENTAL_ELEMENT_BUTTON_CLASS_NAME . '" value="%4$s" />';
75
+ $fields['submit_button'] = '<input name="%1$s" type="submit" id="%2$s" class="%3$s wp-block-button__link ' . WP_Theme_JSON_Gutenberg::get_element_class_name( 'button' ) . '" value="%4$s" />';
76
76
  $fields['submit_field'] = '<p class="form-submit wp-block-button">%1$s %2$s</p>';
77
77
  }
78
78
 
@@ -19,14 +19,16 @@ function render_block_core_post_featured_image( $attributes, $content, $block )
19
19
  }
20
20
  $post_ID = $block->context['postId'];
21
21
 
22
+ $is_link = isset( $attributes['isLink'] ) && $attributes['isLink'];
22
23
  $size_slug = isset( $attributes['sizeSlug'] ) ? $attributes['sizeSlug'] : 'post-thumbnail';
23
24
  $post_title = trim( strip_tags( get_the_title( $post_ID ) ) );
24
- $featured_image = get_the_post_thumbnail( $post_ID, $size_slug, array( 'alt' => $post_title ) );
25
+ $attr = $is_link ? array( 'alt' => $post_title ) : array();
26
+ $featured_image = get_the_post_thumbnail( $post_ID, $size_slug, $attr );
25
27
  if ( ! $featured_image ) {
26
28
  return '';
27
29
  }
28
30
  $wrapper_attributes = get_block_wrapper_attributes();
29
- if ( isset( $attributes['isLink'] ) && $attributes['isLink'] ) {
31
+ if ( $is_link ) {
30
32
  $featured_image = sprintf( '<a href="%1s">%2s</a>', get_the_permalink( $post_ID ), $featured_image );
31
33
  }
32
34
 
@@ -82,17 +82,29 @@ function render_block_core_post_template( $attributes, $content, $block ) {
82
82
  $content = '';
83
83
  while ( $query->have_posts() ) {
84
84
  $query->the_post();
85
+
86
+ // Get an instance of the current Post Template block.
87
+ $block_instance = $block->parsed_block;
88
+
89
+ // Set the block name to one that does not correspond to an existing registered block.
90
+ // This ensures that for the inner instances of the Post Template block, we do not render any block supports.
91
+ $block_instance['blockName'] = 'core/null';
92
+
93
+ // Render the inner blocks of the Post Template block with `dynamic` set to `false` to prevent calling
94
+ // `render_callback` and ensure that no wrapper markup is included.
85
95
  $block_content = (
86
96
  new WP_Block(
87
- $block->parsed_block,
97
+ $block_instance,
88
98
  array(
89
99
  'postType' => get_post_type(),
90
100
  'postId' => get_the_ID(),
91
101
  )
92
102
  )
93
103
  )->render( array( 'dynamic' => false ) );
94
- $post_classes = implode( ' ', get_post_class( 'wp-block-post' ) );
95
- $content .= '<li class="' . esc_attr( $post_classes ) . '">' . $block_content . '</li>';
104
+
105
+ // Wrap the render inner blocks in a `li` element with the appropriate post classes.
106
+ $post_classes = implode( ' ', get_post_class( 'wp-block-post' ) );
107
+ $content .= '<li class="' . esc_attr( $post_classes ) . '">' . $block_content . '</li>';
96
108
  }
97
109
 
98
110
  wp_reset_postdata();
@@ -1,10 +1,4 @@
1
- .wp-block-post-template,
2
- // We have kept `wp-block-query-loop` class as well for backwards
3
- // compatibility with existing `QueryLoop` blocks that haven't been
4
- // updated, after the renaming of the block to `Post Template`.
5
- // See: https://github.com/WordPress/gutenberg/pull/32514.
6
- // TODO: Remove this class when WordPress 5.9 is released.
7
- .wp-block-query-loop {
1
+ .wp-block-post-template {
8
2
  margin-top: 0;
9
3
  margin-bottom: 0;
10
4
  max-width: 100%;
@@ -14,7 +14,7 @@ import {
14
14
  __experimentalUseBorderProps as useBorderProps,
15
15
  __experimentalUseColorProps as useColorProps,
16
16
  store as blockEditorStore,
17
- __experimentalElementButtonClassName,
17
+ __experimentalGetElementClassName,
18
18
  } from '@wordpress/block-editor';
19
19
  import { useDispatch, useSelect } from '@wordpress/data';
20
20
  import { useEffect } from '@wordpress/element';
@@ -241,7 +241,7 @@ export default function SearchEdit( {
241
241
  colorProps.className,
242
242
  isButtonPositionInside ? undefined : borderProps.className,
243
243
  buttonUseIcon ? 'has-icon' : undefined,
244
- __experimentalElementButtonClassName
244
+ __experimentalGetElementClassName( 'button' )
245
245
  );
246
246
  const buttonStyles = {
247
247
  ...colorProps.style,