@wordpress/block-library 8.13.0 → 8.14.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 (366) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/build/archives/index.js +5 -1
  3. package/build/archives/index.js.map +1 -1
  4. package/build/audio/index.js +5 -1
  5. package/build/audio/index.js.map +1 -1
  6. package/build/avatar/index.js +1 -1
  7. package/build/block/edit.js +1 -1
  8. package/build/block/edit.js.map +1 -1
  9. package/build/block/edit.native.js +6 -9
  10. package/build/block/edit.native.js.map +1 -1
  11. package/build/buttons/edit.js +5 -1
  12. package/build/buttons/edit.js.map +1 -1
  13. package/build/categories/index.js +5 -1
  14. package/build/categories/index.js.map +1 -1
  15. package/build/code/index.js +5 -1
  16. package/build/code/index.js.map +1 -1
  17. package/build/column/index.js +1 -0
  18. package/build/column/index.js.map +1 -1
  19. package/build/comments/index.js +1 -0
  20. package/build/comments/index.js.map +1 -1
  21. package/build/cover/edit/inspector-controls.js +2 -1
  22. package/build/cover/edit/inspector-controls.js.map +1 -1
  23. package/build/cover/index.js +1 -0
  24. package/build/cover/index.js.map +1 -1
  25. package/build/details/index.js +5 -1
  26. package/build/details/index.js.map +1 -1
  27. package/build/embed/util.js +9 -8
  28. package/build/embed/util.js.map +1 -1
  29. package/build/file/index.js +2 -1
  30. package/build/file/index.js.map +1 -1
  31. package/build/file/view.js +15 -1
  32. package/build/file/view.js.map +1 -1
  33. package/build/gallery/index.js +3 -1
  34. package/build/gallery/index.js.map +1 -1
  35. package/build/group/index.js +1 -0
  36. package/build/group/index.js.map +1 -1
  37. package/build/heading/index.js +5 -1
  38. package/build/heading/index.js.map +1 -1
  39. package/build/heading/transforms.js +5 -1
  40. package/build/heading/transforms.js.map +1 -1
  41. package/build/image/deprecated.js +453 -175
  42. package/build/image/deprecated.js.map +1 -1
  43. package/build/image/edit.js +0 -4
  44. package/build/image/edit.js.map +1 -1
  45. package/build/image/image.js +96 -43
  46. package/build/image/image.js.map +1 -1
  47. package/build/image/index.js +6 -0
  48. package/build/image/index.js.map +1 -1
  49. package/build/image/save.js +8 -1
  50. package/build/image/save.js.map +1 -1
  51. package/build/image/utils.js +18 -0
  52. package/build/image/utils.js.map +1 -1
  53. package/build/image/{interactivity.js → view-interactivity.js} +86 -44
  54. package/build/image/view-interactivity.js.map +1 -0
  55. package/build/index.js +12 -3
  56. package/build/index.js.map +1 -1
  57. package/build/list/index.js +5 -1
  58. package/build/list/index.js.map +1 -1
  59. package/build/list-item/utils.js +6 -1
  60. package/build/list-item/utils.js.map +1 -1
  61. package/build/media-text/index.js +1 -0
  62. package/build/media-text/index.js.map +1 -1
  63. package/build/missing/edit.js +22 -8
  64. package/build/missing/edit.js.map +1 -1
  65. package/build/navigation/edit/index.js +1 -1
  66. package/build/navigation/edit/index.js.map +1 -1
  67. package/build/navigation/edit/menu-inspector-controls.js +0 -1
  68. package/build/navigation/edit/menu-inspector-controls.js.map +1 -1
  69. package/build/navigation/index.js +3 -2
  70. package/build/navigation/index.js.map +1 -1
  71. package/build/navigation/view.js +174 -50
  72. package/build/navigation/view.js.map +1 -1
  73. package/build/navigation-link/edit.js +0 -11
  74. package/build/navigation-link/edit.js.map +1 -1
  75. package/build/navigation-link/link-ui.js +12 -2
  76. package/build/navigation-link/link-ui.js.map +1 -1
  77. package/build/page-list/convert-to-links-modal.js +3 -3
  78. package/build/page-list/convert-to-links-modal.js.map +1 -1
  79. package/build/page-list/edit.js +34 -39
  80. package/build/page-list/edit.js.map +1 -1
  81. package/build/page-list/use-convert-to-navigation-links.js +2 -15
  82. package/build/page-list/use-convert-to-navigation-links.js.map +1 -1
  83. package/build/paragraph/index.js +1 -0
  84. package/build/paragraph/index.js.map +1 -1
  85. package/build/paragraph/transforms.js +1 -0
  86. package/build/paragraph/transforms.js.map +1 -1
  87. package/build/post-comments-form/index.js +1 -0
  88. package/build/post-comments-form/index.js.map +1 -1
  89. package/build/post-navigation-link/index.js +1 -0
  90. package/build/post-navigation-link/index.js.map +1 -1
  91. package/build/post-time-to-read/index.js +5 -1
  92. package/build/post-time-to-read/index.js.map +1 -1
  93. package/build/query-pagination-numbers/index.js +1 -1
  94. package/build/quote/index.js +1 -0
  95. package/build/quote/index.js.map +1 -1
  96. package/build/site-logo/index.js +5 -1
  97. package/build/site-logo/index.js.map +1 -1
  98. package/build/site-tagline/icon.js +1 -1
  99. package/build/site-tagline/icon.js.map +1 -1
  100. package/build/site-tagline/index.js +5 -1
  101. package/build/site-tagline/index.js.map +1 -1
  102. package/build/site-title/index.js +5 -1
  103. package/build/site-title/index.js.map +1 -1
  104. package/build/social-links/index.js +3 -1
  105. package/build/social-links/index.js.map +1 -1
  106. package/build/table/index.js +5 -1
  107. package/build/table/index.js.map +1 -1
  108. package/build/term-description/index.js +1 -0
  109. package/build/term-description/index.js.map +1 -1
  110. package/build/verse/index.js +5 -1
  111. package/build/verse/index.js.map +1 -1
  112. package/build/video/deprecated.js +5 -1
  113. package/build/video/deprecated.js.map +1 -1
  114. package/build/video/index.js +5 -1
  115. package/build/video/index.js.map +1 -1
  116. package/build-module/archives/index.js +5 -1
  117. package/build-module/archives/index.js.map +1 -1
  118. package/build-module/audio/index.js +5 -1
  119. package/build-module/audio/index.js.map +1 -1
  120. package/build-module/avatar/index.js +1 -1
  121. package/build-module/block/edit.js +1 -1
  122. package/build-module/block/edit.js.map +1 -1
  123. package/build-module/block/edit.native.js +7 -9
  124. package/build-module/block/edit.native.js.map +1 -1
  125. package/build-module/buttons/edit.js +5 -1
  126. package/build-module/buttons/edit.js.map +1 -1
  127. package/build-module/categories/index.js +5 -1
  128. package/build-module/categories/index.js.map +1 -1
  129. package/build-module/code/index.js +5 -1
  130. package/build-module/code/index.js.map +1 -1
  131. package/build-module/column/index.js +1 -0
  132. package/build-module/column/index.js.map +1 -1
  133. package/build-module/comments/index.js +1 -0
  134. package/build-module/comments/index.js.map +1 -1
  135. package/build-module/cover/edit/inspector-controls.js +2 -1
  136. package/build-module/cover/edit/inspector-controls.js.map +1 -1
  137. package/build-module/cover/index.js +1 -0
  138. package/build-module/cover/index.js.map +1 -1
  139. package/build-module/details/index.js +5 -1
  140. package/build-module/details/index.js.map +1 -1
  141. package/build-module/embed/util.js +6 -6
  142. package/build-module/embed/util.js.map +1 -1
  143. package/build-module/file/index.js +2 -1
  144. package/build-module/file/index.js.map +1 -1
  145. package/build-module/file/view.js +15 -2
  146. package/build-module/file/view.js.map +1 -1
  147. package/build-module/gallery/index.js +3 -1
  148. package/build-module/gallery/index.js.map +1 -1
  149. package/build-module/group/index.js +1 -0
  150. package/build-module/group/index.js.map +1 -1
  151. package/build-module/heading/index.js +5 -1
  152. package/build-module/heading/index.js.map +1 -1
  153. package/build-module/heading/transforms.js +5 -1
  154. package/build-module/heading/transforms.js.map +1 -1
  155. package/build-module/image/deprecated.js +454 -176
  156. package/build-module/image/deprecated.js.map +1 -1
  157. package/build-module/image/edit.js +0 -4
  158. package/build-module/image/edit.js.map +1 -1
  159. package/build-module/image/image.js +96 -46
  160. package/build-module/image/image.js.map +1 -1
  161. package/build-module/image/index.js +6 -0
  162. package/build-module/image/index.js.map +1 -1
  163. package/build-module/image/save.js +8 -1
  164. package/build-module/image/save.js.map +1 -1
  165. package/build-module/image/utils.js +16 -0
  166. package/build-module/image/utils.js.map +1 -1
  167. package/build-module/image/{interactivity.js → view-interactivity.js} +86 -44
  168. package/build-module/image/view-interactivity.js.map +1 -0
  169. package/build-module/index.js +12 -3
  170. package/build-module/index.js.map +1 -1
  171. package/build-module/list/index.js +5 -1
  172. package/build-module/list/index.js.map +1 -1
  173. package/build-module/list-item/utils.js +6 -1
  174. package/build-module/list-item/utils.js.map +1 -1
  175. package/build-module/media-text/index.js +1 -0
  176. package/build-module/media-text/index.js.map +1 -1
  177. package/build-module/missing/edit.js +22 -8
  178. package/build-module/missing/edit.js.map +1 -1
  179. package/build-module/navigation/edit/index.js +1 -1
  180. package/build-module/navigation/edit/index.js.map +1 -1
  181. package/build-module/navigation/edit/menu-inspector-controls.js +0 -1
  182. package/build-module/navigation/edit/menu-inspector-controls.js.map +1 -1
  183. package/build-module/navigation/index.js +3 -2
  184. package/build-module/navigation/index.js.map +1 -1
  185. package/build-module/navigation/view.js +173 -50
  186. package/build-module/navigation/view.js.map +1 -1
  187. package/build-module/navigation-link/edit.js +1 -12
  188. package/build-module/navigation-link/edit.js.map +1 -1
  189. package/build-module/navigation-link/link-ui.js +13 -3
  190. package/build-module/navigation-link/link-ui.js.map +1 -1
  191. package/build-module/page-list/convert-to-links-modal.js +3 -3
  192. package/build-module/page-list/convert-to-links-modal.js.map +1 -1
  193. package/build-module/page-list/edit.js +34 -39
  194. package/build-module/page-list/edit.js.map +1 -1
  195. package/build-module/page-list/use-convert-to-navigation-links.js +3 -16
  196. package/build-module/page-list/use-convert-to-navigation-links.js.map +1 -1
  197. package/build-module/paragraph/index.js +1 -0
  198. package/build-module/paragraph/index.js.map +1 -1
  199. package/build-module/paragraph/transforms.js +1 -0
  200. package/build-module/paragraph/transforms.js.map +1 -1
  201. package/build-module/post-comments-form/index.js +1 -0
  202. package/build-module/post-comments-form/index.js.map +1 -1
  203. package/build-module/post-navigation-link/index.js +1 -0
  204. package/build-module/post-navigation-link/index.js.map +1 -1
  205. package/build-module/post-time-to-read/index.js +5 -1
  206. package/build-module/post-time-to-read/index.js.map +1 -1
  207. package/build-module/query-pagination-numbers/index.js +1 -1
  208. package/build-module/quote/index.js +1 -0
  209. package/build-module/quote/index.js.map +1 -1
  210. package/build-module/site-logo/index.js +5 -1
  211. package/build-module/site-logo/index.js.map +1 -1
  212. package/build-module/site-tagline/icon.js +1 -1
  213. package/build-module/site-tagline/icon.js.map +1 -1
  214. package/build-module/site-tagline/index.js +5 -1
  215. package/build-module/site-tagline/index.js.map +1 -1
  216. package/build-module/site-title/index.js +5 -1
  217. package/build-module/site-title/index.js.map +1 -1
  218. package/build-module/social-links/index.js +3 -1
  219. package/build-module/social-links/index.js.map +1 -1
  220. package/build-module/table/index.js +5 -1
  221. package/build-module/table/index.js.map +1 -1
  222. package/build-module/term-description/index.js +1 -0
  223. package/build-module/term-description/index.js.map +1 -1
  224. package/build-module/verse/index.js +5 -1
  225. package/build-module/verse/index.js.map +1 -1
  226. package/build-module/video/deprecated.js +5 -1
  227. package/build-module/video/deprecated.js.map +1 -1
  228. package/build-module/video/index.js +5 -1
  229. package/build-module/video/index.js.map +1 -1
  230. package/build-style/footnotes/style-rtl.css +2 -2
  231. package/build-style/footnotes/style.css +2 -2
  232. package/build-style/image/style-rtl.css +16 -2
  233. package/build-style/image/style.css +16 -2
  234. package/build-style/style-rtl.css +18 -4
  235. package/build-style/style.css +18 -4
  236. package/package.json +33 -38
  237. package/src/archives/block.json +5 -1
  238. package/src/audio/block.json +5 -1
  239. package/src/avatar/block.json +1 -1
  240. package/src/block/edit.js +2 -2
  241. package/src/block/edit.native.js +8 -12
  242. package/src/block/test/edit.native.js +4 -4
  243. package/src/buttons/edit.js +2 -2
  244. package/src/categories/block.json +5 -1
  245. package/src/code/block.json +5 -1
  246. package/src/column/block.json +1 -0
  247. package/src/comments/block.json +1 -0
  248. package/src/cover/block.json +1 -0
  249. package/src/cover/edit/inspector-controls.js +1 -0
  250. package/src/details/block.json +5 -1
  251. package/src/embed/util.js +4 -6
  252. package/src/file/block.json +2 -1
  253. package/src/file/index.php +0 -17
  254. package/src/file/view.js +14 -5
  255. package/src/footnotes/index.php +11 -9
  256. package/src/footnotes/style.scss +2 -2
  257. package/src/gallery/block.json +3 -1
  258. package/src/group/block.json +1 -0
  259. package/src/heading/block.json +5 -1
  260. package/src/heading/test/index.native.js +18 -0
  261. package/src/image/block.json +6 -0
  262. package/src/image/deprecated.js +597 -320
  263. package/src/image/edit.js +0 -4
  264. package/src/image/image.js +131 -62
  265. package/src/image/save.js +9 -1
  266. package/src/image/style.scss +15 -2
  267. package/src/image/utils.js +16 -0
  268. package/src/image/{interactivity.js → view-interactivity.js} +99 -50
  269. package/src/index.js +18 -1
  270. package/src/latest-posts/index.php +1 -1
  271. package/src/list/block.json +5 -1
  272. package/src/media-text/block.json +1 -0
  273. package/src/missing/edit.js +31 -11
  274. package/src/navigation/block.json +3 -2
  275. package/src/navigation/edit/index.js +1 -2
  276. package/src/navigation/edit/menu-inspector-controls.js +0 -1
  277. package/src/navigation/index.php +39 -30
  278. package/src/navigation/view.js +189 -67
  279. package/src/navigation-link/edit.js +1 -15
  280. package/src/navigation-link/link-ui.js +14 -2
  281. package/src/navigation-submenu/index.php +2 -12
  282. package/src/page-list/convert-to-links-modal.js +3 -3
  283. package/src/page-list/edit.js +65 -62
  284. package/src/page-list/use-convert-to-navigation-links.js +3 -20
  285. package/src/paragraph/block.json +1 -0
  286. package/src/post-comments-form/block.json +1 -0
  287. package/src/post-navigation-link/block.json +1 -0
  288. package/src/post-time-to-read/block.json +5 -1
  289. package/src/query-pagination-numbers/block.json +1 -1
  290. package/src/quote/block.json +1 -0
  291. package/src/site-logo/block.json +5 -1
  292. package/src/site-tagline/block.json +5 -1
  293. package/src/site-tagline/icon.js +1 -1
  294. package/src/site-title/block.json +5 -1
  295. package/src/social-links/block.json +3 -1
  296. package/src/table/block.json +5 -1
  297. package/src/term-description/block.json +1 -0
  298. package/src/verse/block.json +5 -1
  299. package/src/video/block.json +5 -1
  300. package/build/file/interactivity.js +0 -19
  301. package/build/file/interactivity.js.map +0 -1
  302. package/build/heading/heading-level-icon.js +0 -61
  303. package/build/heading/heading-level-icon.js.map +0 -1
  304. package/build/image/interactivity.js.map +0 -1
  305. package/build/navigation/interactivity.js +0 -167
  306. package/build/navigation/interactivity.js.map +0 -1
  307. package/build/navigation/view-modal.js +0 -64
  308. package/build/navigation/view-modal.js.map +0 -1
  309. package/build/utils/interactivity/constants.js +0 -9
  310. package/build/utils/interactivity/constants.js.map +0 -1
  311. package/build/utils/interactivity/directives.js +0 -222
  312. package/build/utils/interactivity/directives.js.map +0 -1
  313. package/build/utils/interactivity/hooks.js +0 -159
  314. package/build/utils/interactivity/hooks.js.map +0 -1
  315. package/build/utils/interactivity/hydration.js +0 -34
  316. package/build/utils/interactivity/hydration.js.map +0 -1
  317. package/build/utils/interactivity/index.js +0 -32
  318. package/build/utils/interactivity/index.js.map +0 -1
  319. package/build/utils/interactivity/portals.js +0 -108
  320. package/build/utils/interactivity/portals.js.map +0 -1
  321. package/build/utils/interactivity/store.js +0 -66
  322. package/build/utils/interactivity/store.js.map +0 -1
  323. package/build/utils/interactivity/utils.js +0 -87
  324. package/build/utils/interactivity/utils.js.map +0 -1
  325. package/build/utils/interactivity/vdom.js +0 -119
  326. package/build/utils/interactivity/vdom.js.map +0 -1
  327. package/build-module/file/interactivity.js +0 -15
  328. package/build-module/file/interactivity.js.map +0 -1
  329. package/build-module/heading/heading-level-icon.js +0 -53
  330. package/build-module/heading/heading-level-icon.js.map +0 -1
  331. package/build-module/image/interactivity.js.map +0 -1
  332. package/build-module/navigation/interactivity.js +0 -164
  333. package/build-module/navigation/interactivity.js.map +0 -1
  334. package/build-module/navigation/view-modal.js +0 -58
  335. package/build-module/navigation/view-modal.js.map +0 -1
  336. package/build-module/utils/interactivity/constants.js +0 -2
  337. package/build-module/utils/interactivity/constants.js.map +0 -1
  338. package/build-module/utils/interactivity/directives.js +0 -209
  339. package/build-module/utils/interactivity/directives.js.map +0 -1
  340. package/build-module/utils/interactivity/hooks.js +0 -145
  341. package/build-module/utils/interactivity/hooks.js.map +0 -1
  342. package/build-module/utils/interactivity/hydration.js +0 -21
  343. package/build-module/utils/interactivity/hydration.js.map +0 -1
  344. package/build-module/utils/interactivity/index.js +0 -15
  345. package/build-module/utils/interactivity/index.js.map +0 -1
  346. package/build-module/utils/interactivity/portals.js +0 -100
  347. package/build-module/utils/interactivity/portals.js.map +0 -1
  348. package/build-module/utils/interactivity/store.js +0 -55
  349. package/build-module/utils/interactivity/store.js.map +0 -1
  350. package/build-module/utils/interactivity/utils.js +0 -75
  351. package/build-module/utils/interactivity/utils.js.map +0 -1
  352. package/build-module/utils/interactivity/vdom.js +0 -107
  353. package/build-module/utils/interactivity/vdom.js.map +0 -1
  354. package/src/file/interactivity.js +0 -15
  355. package/src/heading/heading-level-icon.js +0 -48
  356. package/src/navigation/interactivity.js +0 -169
  357. package/src/navigation/view-modal.js +0 -78
  358. package/src/utils/interactivity/constants.js +0 -1
  359. package/src/utils/interactivity/directives.js +0 -200
  360. package/src/utils/interactivity/hooks.js +0 -145
  361. package/src/utils/interactivity/hydration.js +0 -22
  362. package/src/utils/interactivity/index.js +0 -15
  363. package/src/utils/interactivity/portals.js +0 -98
  364. package/src/utils/interactivity/store.js +0 -45
  365. package/src/utils/interactivity/utils.js +0 -66
  366. package/src/utils/interactivity/vdom.js +0 -111
@@ -51,7 +51,7 @@ function render_block_core_latest_posts( $attributes ) {
51
51
  $filter_latest_posts_excerpt_more = static function( $more ) use ( $attributes ) {
52
52
  $use_excerpt = 'excerpt' === $attributes['displayPostContentRadio'];
53
53
  /* translators: %1$s is a URL to a post, excerpt truncation character, default … */
54
- return $use_excerpt ? sprintf( __( ' … <a href="%1$s" rel="noopener noreferrer">Read more</a>', 'gutenberg' ), esc_url( get_permalink() ) ) : $more;
54
+ return $use_excerpt ? sprintf( __( ' … <a href="%1$s" rel="noopener noreferrer">Read more</a>' ), esc_url( get_permalink() ) ) : $more;
55
55
  };
56
56
 
57
57
  add_filter( 'excerpt_more', $filter_latest_posts_excerpt_more );
@@ -61,7 +61,11 @@
61
61
  },
62
62
  "spacing": {
63
63
  "margin": true,
64
- "padding": true
64
+ "padding": true,
65
+ "__experimentalDefaultControls": {
66
+ "margin": false,
67
+ "padding": false
68
+ }
65
69
  },
66
70
  "__unstablePasteTextInline": true,
67
71
  "__experimentalSelector": "ol,ul",
@@ -100,6 +100,7 @@
100
100
  "html": false,
101
101
  "color": {
102
102
  "gradients": true,
103
+ "heading": true,
103
104
  "link": true,
104
105
  "__experimentalDefaultControls": {
105
106
  "background": true,
@@ -16,22 +16,46 @@ import { safeHTML } from '@wordpress/dom';
16
16
  function MissingBlockWarning( { attributes, convertToHTML, clientId } ) {
17
17
  const { originalName, originalUndelimitedContent } = attributes;
18
18
  const hasContent = !! originalUndelimitedContent;
19
- const hasHTMLBlock = useSelect(
19
+ const { hasFreeformBlock, hasHTMLBlock } = useSelect(
20
20
  ( select ) => {
21
21
  const { canInsertBlockType, getBlockRootClientId } =
22
22
  select( blockEditorStore );
23
23
 
24
- return canInsertBlockType(
25
- 'core/html',
26
- getBlockRootClientId( clientId )
27
- );
24
+ return {
25
+ hasFreeformBlock: canInsertBlockType(
26
+ 'core/freeform',
27
+ getBlockRootClientId( clientId )
28
+ ),
29
+ hasHTMLBlock: canInsertBlockType(
30
+ 'core/html',
31
+ getBlockRootClientId( clientId )
32
+ ),
33
+ };
28
34
  },
29
35
  [ clientId ]
30
36
  );
31
37
 
32
38
  const actions = [];
33
39
  let messageHTML;
34
- if ( hasContent && hasHTMLBlock ) {
40
+
41
+ const convertToHtmlButton = (
42
+ <Button key="convert" onClick={ convertToHTML } variant="primary">
43
+ { __( 'Keep as HTML' ) }
44
+ </Button>
45
+ );
46
+
47
+ if ( hasContent && ! hasFreeformBlock && ! originalName ) {
48
+ if ( hasHTMLBlock ) {
49
+ messageHTML = __(
50
+ 'It appears you are trying to use the deprecated Classic block. You can leave this block intact, convert its content to a Custom HTML block, or remove it entirely. Alternatively, you can refresh the page to use the Classic block.'
51
+ );
52
+ actions.push( convertToHtmlButton );
53
+ } else {
54
+ messageHTML = __(
55
+ 'It appears you are trying to use the deprecated Classic block. You can leave this block intact, or remove it entirely. Alternatively, you can refresh the page to use the Classic block.'
56
+ );
57
+ }
58
+ } else if ( hasContent && hasHTMLBlock ) {
35
59
  messageHTML = sprintf(
36
60
  /* translators: %s: block name */
37
61
  __(
@@ -39,11 +63,7 @@ function MissingBlockWarning( { attributes, convertToHTML, clientId } ) {
39
63
  ),
40
64
  originalName
41
65
  );
42
- actions.push(
43
- <Button key="convert" onClick={ convertToHTML } variant="primary">
44
- { __( 'Keep as HTML' ) }
45
- </Button>
46
- );
66
+ actions.push( convertToHtmlButton );
47
67
  } else {
48
68
  messageHTML = sprintf(
49
69
  /* translators: %s: block name */
@@ -131,9 +131,10 @@
131
131
  }
132
132
  }
133
133
  }
134
- }
134
+ },
135
+ "interactivity": true
135
136
  },
136
- "viewScript": [ "file:./view.min.js", "file:./view-modal.min.js" ],
137
+ "viewScript": "file:./view.min.js",
137
138
  "editorStyle": "wp-block-navigation-editor",
138
139
  "style": "wp-block-navigation"
139
140
  }
@@ -69,7 +69,6 @@ import ManageMenusButton from './manage-menus-button';
69
69
  import MenuInspectorControls from './menu-inspector-controls';
70
70
  import DeletedNavigationWarning from './deleted-navigation-warning';
71
71
  import { unlock } from '../../lock-unlock';
72
-
73
72
  const { useBlockEditingMode } = unlock( blockEditorPrivateApis );
74
73
 
75
74
  function Navigation( {
@@ -224,7 +223,7 @@ function Navigation( {
224
223
  // that automatically saves the menu as an entity when changes are made to the inner blocks.
225
224
  const hasUnsavedBlocks = hasUncontrolledInnerBlocks && ! isEntityAvailable;
226
225
 
227
- const { getNavigationFallbackId } = useSelect( coreStore );
226
+ const { getNavigationFallbackId } = unlock( useSelect( coreStore ) );
228
227
 
229
228
  const navigationFallbackId = ! ( ref || hasUnsavedBlocks )
230
229
  ? getNavigationFallbackId()
@@ -60,7 +60,6 @@ function AdditionalBlockContent( { block, insertedBlock, setInsertedBlock } ) {
60
60
  onClose={ () => {
61
61
  setInsertedBlock( null );
62
62
  } }
63
- hasCreateSuggestion={ false }
64
63
  onChange={ ( updatedValue ) => {
65
64
  updateAttributes(
66
65
  updatedValue,
@@ -94,7 +94,7 @@ if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ) {
94
94
  *
95
95
  * @return string Submenu markup with the directives injected.
96
96
  */
97
- function gutenberg_block_core_navigation_add_directives_to_submenu( $w, $block_attributes ) {
97
+ function block_core_navigation_add_directives_to_submenu( $w, $block_attributes ) {
98
98
  while ( $w->next_tag(
99
99
  array(
100
100
  'tag_name' => 'LI',
@@ -103,7 +103,7 @@ if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ) {
103
103
  ) ) {
104
104
  // Add directives to the parent `<li>`.
105
105
  $w->set_attribute( 'data-wp-interactive', true );
106
- $w->set_attribute( 'data-wp-context', '{ "core": { "navigation": { "isMenuOpen": { "click": false, "hover": false }, "overlay": false } } }' );
106
+ $w->set_attribute( 'data-wp-context', '{ "core": { "navigation": { "submenuOpenedBy": {}, "type": "submenu" } } }' );
107
107
  $w->set_attribute( 'data-wp-effect', 'effects.core.navigation.initMenu' );
108
108
  $w->set_attribute( 'data-wp-on--focusout', 'actions.core.navigation.handleMenuFocusout' );
109
109
  $w->set_attribute( 'data-wp-on--keydown', 'actions.core.navigation.handleMenuKeydown' );
@@ -123,26 +123,21 @@ if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ) {
123
123
  $w->set_attribute( 'data-wp-bind--aria-expanded', 'selectors.core.navigation.isMenuOpen' );
124
124
  };
125
125
 
126
+ // Add directives to the submenu.
127
+ if ( $w->next_tag(
128
+ array(
129
+ 'tag_name' => 'UL',
130
+ 'class_name' => 'wp-block-navigation__submenu-container',
131
+ )
132
+ ) ) {
133
+ $w->set_attribute( 'data-wp-on--focusin', 'actions.core.navigation.openMenuOnFocus' );
134
+ }
135
+
126
136
  // Iterate through subitems if exist.
127
- gutenberg_block_core_navigation_add_directives_to_submenu( $w, $block_attributes );
137
+ block_core_navigation_add_directives_to_submenu( $w, $block_attributes );
128
138
  }
129
139
  return $w->get_updated_html();
130
140
  };
131
-
132
- /**
133
- * Replaces view script for the Navigation block with version using Interactivity API.
134
- *
135
- * @param array $metadata Block metadata as read in via block.json.
136
- *
137
- * @return array Filtered block type metadata.
138
- */
139
- function gutenberg_block_core_navigation_update_interactive_view_script( $metadata ) {
140
- if ( 'core/navigation' === $metadata['name'] ) {
141
- $metadata['viewScript'] = array( 'file:./interactivity.min.js' );
142
- }
143
- return $metadata;
144
- }
145
- add_filter( 'block_type_metadata', 'gutenberg_block_core_navigation_update_interactive_view_script', 10, 1 );
146
141
  }
147
142
 
148
143
 
@@ -341,7 +336,11 @@ function block_core_navigation_get_fallback_blocks() {
341
336
  // If `core/page-list` is not registered then return empty blocks.
342
337
  $fallback_blocks = $registry->is_registered( 'core/page-list' ) ? $page_list_fallback : array();
343
338
 
344
- $navigation_post = WP_Navigation_Fallback_Gutenberg::get_fallback();
339
+ if ( class_exists( 'WP_Navigation_Fallback' ) ) {
340
+ $navigation_post = WP_Navigation_Fallback::get_fallback();
341
+ } else {
342
+ $navigation_post = Gutenberg_Navigation_Fallback::get_fallback();
343
+ }
345
344
 
346
345
  // Use the first non-empty Navigation as fallback if available.
347
346
  if ( $navigation_post ) {
@@ -673,7 +672,7 @@ function render_block_core_navigation( $attributes, $content, $block ) {
673
672
  // Add directives to the submenu if needed.
674
673
  if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN && $has_submenus && $should_load_view_script ) {
675
674
  $w = new WP_HTML_Tag_Processor( $inner_blocks_html );
676
- $inner_blocks_html = gutenberg_block_core_navigation_add_directives_to_submenu( $w, $attributes );
675
+ $inner_blocks_html = block_core_navigation_add_directives_to_submenu( $w, $attributes );
677
676
  }
678
677
 
679
678
  $modal_unique_id = wp_unique_id( 'modal-' );
@@ -722,7 +721,7 @@ function render_block_core_navigation( $attributes, $content, $block ) {
722
721
  if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN && $should_load_view_script ) {
723
722
  $nav_element_directives = '
724
723
  data-wp-interactive
725
- data-wp-context=\'{ "core": { "navigation": { "isMenuOpen": { "click": false, "hover": false }, "overlay": true, "roleAttribute": "" } } }\'
724
+ data-wp-context=\'{ "core": { "navigation": { "overlayOpenedBy": {}, "type": "overlay", "roleAttribute": "" } } }\'
726
725
  ';
727
726
  $open_button_directives = '
728
727
  data-wp-on--click="actions.core.navigation.openMenuOnClick"
@@ -747,11 +746,11 @@ function render_block_core_navigation( $attributes, $content, $block ) {
747
746
  }
748
747
 
749
748
  $responsive_container_markup = sprintf(
750
- '<button aria-haspopup="true" %3$s class="%6$s" data-micromodal-trigger="%1$s" %11$s>%9$s</button>
749
+ '<button aria-haspopup="true" %3$s class="%6$s" %11$s>%9$s</button>
751
750
  <div class="%5$s" style="%7$s" id="%1$s" %12$s>
752
- <div class="wp-block-navigation__responsive-close" tabindex="-1" data-micromodal-close>
751
+ <div class="wp-block-navigation__responsive-close" tabindex="-1">
753
752
  <div class="wp-block-navigation__responsive-dialog" aria-label="%8$s" %13$s>
754
- <button %4$s data-micromodal-close class="wp-block-navigation__responsive-container-close" %14$s>%10$s</button>
753
+ <button %4$s class="wp-block-navigation__responsive-container-close" %14$s>%10$s</button>
755
754
  <div class="wp-block-navigation__responsive-container-content" id="%1$s-content">
756
755
  %2$s
757
756
  </div>
@@ -836,6 +835,8 @@ add_filter( 'render_block_data', 'block_core_navigation_typographic_presets_back
836
835
  /**
837
836
  * Turns menu item data into a nested array of parsed blocks
838
837
  *
838
+ * @deprecated 6.3.0 Use WP_Navigation_Fallback::parse_blocks_from_menu_items() instead.
839
+ *
839
840
  * @param array $menu_items An array of menu items that represent
840
841
  * an individual level of a menu.
841
842
  * @param array $menu_items_by_parent_id An array keyed by the id of the
@@ -846,7 +847,7 @@ add_filter( 'render_block_data', 'block_core_navigation_typographic_presets_back
846
847
  */
847
848
  function block_core_navigation_parse_blocks_from_menu_items( $menu_items, $menu_items_by_parent_id ) {
848
849
 
849
- _deprecated_function( __FUNCTION__, '6.3.0', 'WP_Navigation_Fallback_Gutenberg::parse_blocks_from_menu_items' );
850
+ _deprecated_function( __FUNCTION__, '6.3.0', 'WP_Navigation_Fallback::parse_blocks_from_menu_items' );
850
851
 
851
852
  if ( empty( $menu_items ) ) {
852
853
  return array();
@@ -891,11 +892,13 @@ function block_core_navigation_parse_blocks_from_menu_items( $menu_items, $menu_
891
892
  /**
892
893
  * Get the classic navigation menu to use as a fallback.
893
894
  *
895
+ * @deprecated 6.3.0 Use WP_Navigation_Fallback::get_classic_menu_fallback() instead.
896
+ *
894
897
  * @return object WP_Term The classic navigation.
895
898
  */
896
899
  function block_core_navigation_get_classic_menu_fallback() {
897
900
 
898
- _deprecated_function( __FUNCTION__, '6.3.0', 'WP_Navigation_Fallback_Gutenberg::get_classic_menu_fallback' );
901
+ _deprecated_function( __FUNCTION__, '6.3.0', 'WP_Navigation_Fallback::get_classic_menu_fallback' );
899
902
 
900
903
  $classic_nav_menus = wp_get_nav_menus();
901
904
 
@@ -933,12 +936,14 @@ function block_core_navigation_get_classic_menu_fallback() {
933
936
  /**
934
937
  * Converts a classic navigation to blocks.
935
938
  *
939
+ * @deprecated 6.3.0 Use WP_Navigation_Fallback::get_classic_menu_fallback_blocks() instead.
940
+ *
936
941
  * @param object $classic_nav_menu WP_Term The classic navigation object to convert.
937
942
  * @return array the normalized parsed blocks.
938
943
  */
939
944
  function block_core_navigation_get_classic_menu_fallback_blocks( $classic_nav_menu ) {
940
945
 
941
- _deprecated_function( __FUNCTION__, '6.3.0', 'WP_Navigation_Fallback_Gutenberg::get_classic_menu_fallback_blocks' );
946
+ _deprecated_function( __FUNCTION__, '6.3.0', 'WP_Navigation_Fallback::get_classic_menu_fallback_blocks' );
942
947
 
943
948
  // BEGIN: Code that already exists in wp_nav_menu().
944
949
  $menu_items = wp_get_nav_menu_items( $classic_nav_menu->term_id, array( 'update_post_term_cache' => false ) );
@@ -971,13 +976,15 @@ function block_core_navigation_get_classic_menu_fallback_blocks( $classic_nav_me
971
976
  }
972
977
 
973
978
  /**
974
- * If there's a the classic menu then use it as a fallback.
979
+ * If there's a classic menu then use it as a fallback.
980
+ *
981
+ * @deprecated 6.3.0 Use WP_Navigation_Fallback::create_classic_menu_fallback() instead.
975
982
  *
976
983
  * @return array the normalized parsed blocks.
977
984
  */
978
985
  function block_core_navigation_maybe_use_classic_menu_fallback() {
979
986
 
980
- _deprecated_function( __FUNCTION__, '6.3.0', 'WP_Navigation_Fallback_Gutenberg::create_classic_menu_fallback' );
987
+ _deprecated_function( __FUNCTION__, '6.3.0', 'WP_Navigation_Fallback::create_classic_menu_fallback' );
981
988
 
982
989
  // See if we have a classic menu.
983
990
  $classic_nav_menu = block_core_navigation_get_classic_menu_fallback();
@@ -1016,11 +1023,13 @@ function block_core_navigation_maybe_use_classic_menu_fallback() {
1016
1023
  /**
1017
1024
  * Finds the most recently published `wp_navigation` Post.
1018
1025
  *
1026
+ * @deprecated 6.3.0 Use WP_Navigation_Fallback::get_most_recently_published_navigation() instead.
1027
+ *
1019
1028
  * @return WP_Post|null the first non-empty Navigation or null.
1020
1029
  */
1021
1030
  function block_core_navigation_get_most_recently_published_navigation() {
1022
1031
 
1023
- _deprecated_function( __FUNCTION__, '6.3.0', 'WP_Navigation_Fallback_Gutenberg::get_most_recently_published_navigation' );
1032
+ _deprecated_function( __FUNCTION__, '6.3.0', 'WP_Navigation_Fallback::get_most_recently_published_navigation' );
1024
1033
 
1025
1034
  // Default to the most recently created menu.
1026
1035
  $parsed_args = array(
@@ -1,74 +1,196 @@
1
- // Open on click functionality.
2
- function closeSubmenus( element ) {
3
- element
4
- .querySelectorAll( '[aria-expanded="true"]' )
5
- .forEach( function ( toggle ) {
6
- toggle.setAttribute( 'aria-expanded', 'false' );
7
- } );
8
- }
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { store as wpStore } from '@wordpress/interactivity';
9
5
 
10
- function toggleSubmenuOnClick( event ) {
11
- const buttonToggle = event.target.closest( '[aria-expanded]' );
12
- const isSubmenuOpen = buttonToggle.getAttribute( 'aria-expanded' );
6
+ const focusableSelectors = [
7
+ 'a[href]',
8
+ 'input:not([disabled]):not([type="hidden"]):not([aria-hidden])',
9
+ 'select:not([disabled]):not([aria-hidden])',
10
+ 'textarea:not([disabled]):not([aria-hidden])',
11
+ 'button:not([disabled]):not([aria-hidden])',
12
+ '[contenteditable]',
13
+ '[tabindex]:not([tabindex^="-"])',
14
+ ];
13
15
 
14
- if ( isSubmenuOpen === 'true' ) {
15
- closeSubmenus( buttonToggle.closest( '.wp-block-navigation-item' ) );
16
- } else {
17
- // Close all sibling submenus.
18
- const parentElement = buttonToggle.closest(
19
- '.wp-block-navigation-item'
20
- );
21
- const navigationParent = buttonToggle.closest(
22
- '.wp-block-navigation__submenu-container, .wp-block-navigation__container, .wp-block-page-list'
23
- );
24
- navigationParent
25
- .querySelectorAll( '.wp-block-navigation-item' )
26
- .forEach( function ( child ) {
27
- if ( child !== parentElement ) {
28
- closeSubmenus( child );
29
- }
30
- } );
31
- // Open submenu.
32
- buttonToggle.setAttribute( 'aria-expanded', 'true' );
16
+ const openMenu = ( store, menuOpenedOn ) => {
17
+ const { context, ref, selectors } = store;
18
+ selectors.core.navigation.menuOpenedBy( store )[ menuOpenedOn ] = true;
19
+ context.core.navigation.previousFocus = ref;
20
+ if ( context.core.navigation.type === 'overlay' ) {
21
+ // Add a `has-modal-open` class to the <html> root.
22
+ document.documentElement.classList.add( 'has-modal-open' );
33
23
  }
34
- }
24
+ };
35
25
 
36
- // Necessary for some themes such as TT1 Blocks, where
37
- // scripts could be loaded before the body.
38
- window.addEventListener( 'load', () => {
39
- const submenuButtons = document.querySelectorAll(
40
- '.wp-block-navigation-submenu__toggle'
41
- );
26
+ const closeMenu = ( store, menuClosedOn ) => {
27
+ const { context, selectors } = store;
28
+ selectors.core.navigation.menuOpenedBy( store )[ menuClosedOn ] = false;
29
+ // Check if the menu is still open or not.
30
+ if ( ! selectors.core.navigation.isMenuOpen( store ) ) {
31
+ if (
32
+ context.core.navigation.modal?.contains(
33
+ window.document.activeElement
34
+ )
35
+ ) {
36
+ context.core.navigation.previousFocus.focus();
37
+ }
38
+ context.core.navigation.modal = null;
39
+ context.core.navigation.previousFocus = null;
40
+ if ( context.core.navigation.type === 'overlay' ) {
41
+ document.documentElement.classList.remove( 'has-modal-open' );
42
+ }
43
+ }
44
+ };
42
45
 
43
- submenuButtons.forEach( function ( button ) {
44
- button.addEventListener( 'click', toggleSubmenuOnClick );
45
- } );
46
+ wpStore( {
47
+ effects: {
48
+ core: {
49
+ navigation: {
50
+ initMenu: ( store ) => {
51
+ const { context, selectors, ref } = store;
52
+ if ( selectors.core.navigation.isMenuOpen( store ) ) {
53
+ const focusableElements =
54
+ ref.querySelectorAll( focusableSelectors );
55
+ context.core.navigation.modal = ref;
56
+ context.core.navigation.firstFocusableElement =
57
+ focusableElements[ 0 ];
58
+ context.core.navigation.lastFocusableElement =
59
+ focusableElements[ focusableElements.length - 1 ];
60
+ }
61
+ },
62
+ focusFirstElement: ( store ) => {
63
+ const { selectors, ref } = store;
64
+ if ( selectors.core.navigation.isMenuOpen( store ) ) {
65
+ ref.querySelector(
66
+ '.wp-block-navigation-item > *:first-child'
67
+ ).focus();
68
+ }
69
+ },
70
+ },
71
+ },
72
+ },
73
+ selectors: {
74
+ core: {
75
+ navigation: {
76
+ roleAttribute: ( store ) => {
77
+ const { context, selectors } = store;
78
+ return context.core.navigation.type === 'overlay' &&
79
+ selectors.core.navigation.isMenuOpen( store )
80
+ ? 'dialog'
81
+ : '';
82
+ },
83
+ isMenuOpen: ( { context } ) =>
84
+ // The menu is opened if either `click`, `hover` or `focus` is true.
85
+ Object.values(
86
+ context.core.navigation[
87
+ context.core.navigation.type === 'overlay'
88
+ ? 'overlayOpenedBy'
89
+ : 'submenuOpenedBy'
90
+ ]
91
+ ).filter( Boolean ).length > 0,
92
+ menuOpenedBy: ( { context } ) =>
93
+ context.core.navigation[
94
+ context.core.navigation.type === 'overlay'
95
+ ? 'overlayOpenedBy'
96
+ : 'submenuOpenedBy'
97
+ ],
98
+ },
99
+ },
100
+ },
101
+ actions: {
102
+ core: {
103
+ navigation: {
104
+ openMenuOnHover( store ) {
105
+ const { navigation } = store.context.core;
106
+ if (
107
+ navigation.type === 'submenu' &&
108
+ // Only open on hover if the overlay is closed.
109
+ Object.values(
110
+ navigation.overlayOpenedBy || {}
111
+ ).filter( Boolean ).length === 0
112
+ )
113
+ openMenu( store, 'hover' );
114
+ },
115
+ closeMenuOnHover( store ) {
116
+ closeMenu( store, 'hover' );
117
+ },
118
+ openMenuOnClick( store ) {
119
+ openMenu( store, 'click' );
120
+ },
121
+ closeMenuOnClick( store ) {
122
+ closeMenu( store, 'click' );
123
+ closeMenu( store, 'focus' );
124
+ },
125
+ openMenuOnFocus( store ) {
126
+ openMenu( store, 'focus' );
127
+ },
128
+ toggleMenuOnClick: ( store ) => {
129
+ const { selectors } = store;
130
+ const menuOpenedBy =
131
+ selectors.core.navigation.menuOpenedBy( store );
132
+ if ( menuOpenedBy.click || menuOpenedBy.focus ) {
133
+ closeMenu( store, 'click' );
134
+ closeMenu( store, 'focus' );
135
+ } else {
136
+ openMenu( store, 'click' );
137
+ }
138
+ },
139
+ handleMenuKeydown: ( store ) => {
140
+ const { context, selectors, event } = store;
141
+ if (
142
+ selectors.core.navigation.menuOpenedBy( store ).click
143
+ ) {
144
+ // If Escape close the menu.
145
+ if ( event?.key === 'Escape' ) {
146
+ closeMenu( store, 'click' );
147
+ closeMenu( store, 'focus' );
148
+ return;
149
+ }
46
150
 
47
- // Close on click outside.
48
- document.addEventListener( 'click', function ( event ) {
49
- const navigationBlocks = document.querySelectorAll(
50
- '.wp-block-navigation'
51
- );
52
- navigationBlocks.forEach( function ( block ) {
53
- if ( ! block.contains( event.target ) ) {
54
- closeSubmenus( block );
55
- }
56
- } );
57
- } );
58
- // Close on focus outside or escape key.
59
- document.addEventListener( 'keyup', function ( event ) {
60
- const submenuBlocks = document.querySelectorAll(
61
- '.wp-block-navigation-item.has-child'
62
- );
63
- submenuBlocks.forEach( function ( block ) {
64
- if ( ! block.contains( event.target ) ) {
65
- closeSubmenus( block );
66
- } else if ( event.key === 'Escape' ) {
67
- const toggle = block.querySelector( '[aria-expanded="true"]' );
68
- closeSubmenus( block );
69
- // Focus the submenu trigger so focus does not get trapped in the closed submenu.
70
- toggle?.focus();
71
- }
72
- } );
73
- } );
151
+ // Trap focus if it is an overlay (main menu).
152
+ if (
153
+ context.core.navigation.type === 'overlay' &&
154
+ event.key === 'Tab'
155
+ ) {
156
+ // If shift + tab it change the direction.
157
+ if (
158
+ event.shiftKey &&
159
+ window.document.activeElement ===
160
+ context.core.navigation
161
+ .firstFocusableElement
162
+ ) {
163
+ event.preventDefault();
164
+ context.core.navigation.lastFocusableElement.focus();
165
+ } else if (
166
+ ! event.shiftKey &&
167
+ window.document.activeElement ===
168
+ context.core.navigation.lastFocusableElement
169
+ ) {
170
+ event.preventDefault();
171
+ context.core.navigation.firstFocusableElement.focus();
172
+ }
173
+ }
174
+ }
175
+ },
176
+ handleMenuFocusout: ( store ) => {
177
+ const { context, event } = store;
178
+ // If focus is outside modal, and in the document, close menu
179
+ // event.target === The element losing focus
180
+ // event.relatedTarget === The element receiving focus (if any)
181
+ // When focusout is outsite the document,
182
+ // `window.document.activeElement` doesn't change.
183
+ if (
184
+ ! context.core.navigation.modal?.contains(
185
+ event.relatedTarget
186
+ ) &&
187
+ event.target !== window.document.activeElement
188
+ ) {
189
+ closeMenu( store, 'click' );
190
+ closeMenu( store, 'focus' );
191
+ }
192
+ },
193
+ },
194
+ },
195
+ },
74
196
  } );
@@ -35,10 +35,7 @@ import {
35
35
  } from '@wordpress/dom';
36
36
  import { decodeEntities } from '@wordpress/html-entities';
37
37
  import { link as linkIcon, addSubmenu } from '@wordpress/icons';
38
- import {
39
- store as coreStore,
40
- useResourcePermissions,
41
- } from '@wordpress/core-data';
38
+ import { store as coreStore } from '@wordpress/core-data';
42
39
  import { useMergeRefs } from '@wordpress/compose';
43
40
 
44
41
  /**
@@ -184,9 +181,6 @@ export default function NavigationLinkEdit( {
184
181
  const itemLabelPlaceholder = __( 'Add label…' );
185
182
  const ref = useRef();
186
183
 
187
- const pagesPermissions = useResourcePermissions( 'pages' );
188
- const postsPermissions = useResourcePermissions( 'posts' );
189
-
190
184
  const {
191
185
  innerBlocks,
192
186
  isAtMaxNesting,
@@ -322,13 +316,6 @@ export default function NavigationLinkEdit( {
322
316
  setIsLinkOpen( false );
323
317
  }
324
318
 
325
- let userCanCreate = false;
326
- if ( ! type || type === 'page' ) {
327
- userCanCreate = pagesPermissions.canCreate;
328
- } else if ( type === 'post' ) {
329
- userCanCreate = postsPermissions.canCreate;
330
- }
331
-
332
319
  const {
333
320
  textColor,
334
321
  customTextColor,
@@ -589,7 +576,6 @@ export default function NavigationLinkEdit( {
589
576
  link={ attributes }
590
577
  onClose={ () => setIsLinkOpen( false ) }
591
578
  anchor={ popoverAnchor }
592
- hasCreateSuggestion={ userCanCreate }
593
579
  onRemove={ removeLink }
594
580
  onChange={ ( updatedValue ) => {
595
581
  updateAttributes(
@@ -10,7 +10,10 @@ import {
10
10
  store as blockEditorStore,
11
11
  } from '@wordpress/block-editor';
12
12
  import { createInterpolateElement, useMemo } from '@wordpress/element';
13
- import { store as coreStore } from '@wordpress/core-data';
13
+ import {
14
+ store as coreStore,
15
+ useResourcePermissions,
16
+ } from '@wordpress/core-data';
14
17
  import { decodeEntities } from '@wordpress/html-entities';
15
18
  import { switchToBlockType } from '@wordpress/blocks';
16
19
  import { useSelect, useDispatch } from '@wordpress/data';
@@ -125,6 +128,8 @@ function LinkControlTransforms( { clientId } ) {
125
128
 
126
129
  export function LinkUI( props ) {
127
130
  const { saveEntityRecord } = useDispatch( coreStore );
131
+ const pagesPermissions = useResourcePermissions( 'pages' );
132
+ const postsPermissions = useResourcePermissions( 'posts' );
128
133
 
129
134
  async function handleCreate( pageTitle ) {
130
135
  const postType = props.link.type || 'page';
@@ -155,6 +160,13 @@ export function LinkUI( props ) {
155
160
 
156
161
  const { label, url, opensInNewTab, type, kind } = props.link;
157
162
 
163
+ let userCanCreate = false;
164
+ if ( ! type || type === 'page' ) {
165
+ userCanCreate = pagesPermissions.canCreate;
166
+ } else if ( type === 'post' ) {
167
+ userCanCreate = postsPermissions.canCreate;
168
+ }
169
+
158
170
  // Memoize link value to avoid overriding the LinkControl's internal state.
159
171
  // This is a temporary fix. See https://github.com/WordPress/gutenberg/issues/50976#issuecomment-1568226407.
160
172
  const link = useMemo(
@@ -179,7 +191,7 @@ export function LinkUI( props ) {
179
191
  className={ props.className }
180
192
  value={ link }
181
193
  showInitialSuggestions={ true }
182
- withCreateSuggestion={ props.hasCreateSuggestion }
194
+ withCreateSuggestion={ userCanCreate }
183
195
  createSuggestion={ handleCreate }
184
196
  createSuggestionButtonText={ ( searchTerm ) => {
185
197
  let format;