@wordpress/block-library 8.30.0 → 8.32.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 (362) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/build/block/edit.js +22 -16
  3. package/build/block/edit.js.map +1 -1
  4. package/build/button/edit.native.js +1 -1
  5. package/build/button/edit.native.js.map +1 -1
  6. package/build/code/save.js +3 -1
  7. package/build/code/save.js.map +1 -1
  8. package/build/cover/edit/index.js +2 -1
  9. package/build/cover/edit/index.js.map +1 -1
  10. package/build/details/edit.js +1 -0
  11. package/build/details/edit.js.map +1 -1
  12. package/build/file/edit.js +2 -0
  13. package/build/file/edit.js.map +1 -1
  14. package/build/heading/index.js +4 -3
  15. package/build/heading/index.js.map +1 -1
  16. package/build/image/edit.js +10 -39
  17. package/build/image/edit.js.map +1 -1
  18. package/build/image/image.js +27 -6
  19. package/build/image/image.js.map +1 -1
  20. package/build/media-text/edit.js +33 -9
  21. package/build/media-text/edit.js.map +1 -1
  22. package/build/media-text/index.js +5 -0
  23. package/build/media-text/index.js.map +1 -1
  24. package/build/media-text/media-container.js +30 -11
  25. package/build/media-text/media-container.js.map +1 -1
  26. package/build/media-text/save.js +2 -2
  27. package/build/media-text/save.js.map +1 -1
  28. package/build/navigation/edit/index.js +23 -29
  29. package/build/navigation/edit/index.js.map +1 -1
  30. package/build/navigation/edit/navigation-menu-delete-control.js +12 -20
  31. package/build/navigation/edit/navigation-menu-delete-control.js.map +1 -1
  32. package/build/navigation/edit/navigation-menu-selector.js +24 -23
  33. package/build/navigation/edit/navigation-menu-selector.js.map +1 -1
  34. package/build/navigation/edit/placeholder/index.js +4 -4
  35. package/build/navigation/edit/placeholder/index.js.map +1 -1
  36. package/build/navigation/use-navigation-menu.js +15 -12
  37. package/build/navigation/use-navigation-menu.js.map +1 -1
  38. package/build/navigation/view.js +12 -2
  39. package/build/navigation/view.js.map +1 -1
  40. package/build/navigation-link/edit.js +52 -27
  41. package/build/navigation-link/edit.js.map +1 -1
  42. package/build/navigation-submenu/edit.js +31 -9
  43. package/build/navigation-submenu/edit.js.map +1 -1
  44. package/build/pattern/edit.js +3 -1
  45. package/build/pattern/edit.js.map +1 -1
  46. package/build/post-author/edit.js +1 -0
  47. package/build/post-author/edit.js.map +1 -1
  48. package/build/post-excerpt/edit.js +1 -0
  49. package/build/post-excerpt/edit.js.map +1 -1
  50. package/build/post-featured-image/edit.js +16 -4
  51. package/build/post-featured-image/edit.js.map +1 -1
  52. package/build/post-featured-image/index.js +13 -2
  53. package/build/post-featured-image/index.js.map +1 -1
  54. package/build/post-featured-image/overlay-controls.js +82 -0
  55. package/build/post-featured-image/overlay-controls.js.map +1 -0
  56. package/build/post-featured-image/overlay.js +5 -54
  57. package/build/post-featured-image/overlay.js.map +1 -1
  58. package/build/post-navigation-link/edit.js +1 -0
  59. package/build/post-navigation-link/edit.js.map +1 -1
  60. package/build/post-terms/edit.js +2 -0
  61. package/build/post-terms/edit.js.map +1 -1
  62. package/build/quote/edit.js +18 -23
  63. package/build/quote/edit.js.map +1 -1
  64. package/build/read-more/edit.js +1 -0
  65. package/build/read-more/edit.js.map +1 -1
  66. package/build/search/edit.js +2 -0
  67. package/build/search/edit.js.map +1 -1
  68. package/build/search/edit.native.js +2 -2
  69. package/build/search/edit.native.js.map +1 -1
  70. package/build/site-tagline/edit.js +13 -4
  71. package/build/site-tagline/edit.js.map +1 -1
  72. package/build/site-tagline/index.js +4 -0
  73. package/build/site-tagline/index.js.map +1 -1
  74. package/build/social-link/edit.js +1 -1
  75. package/build/social-link/edit.js.map +1 -1
  76. package/build/social-link/icons/medium.js +1 -1
  77. package/build/social-link/icons/medium.js.map +1 -1
  78. package/build/social-link/icons/reddit.js +1 -1
  79. package/build/social-link/icons/reddit.js.map +1 -1
  80. package/build/table/deprecated.js +285 -175
  81. package/build/table/deprecated.js.map +1 -1
  82. package/build/table/index.js +1 -1
  83. package/build/template-part/edit/index.js +55 -47
  84. package/build/template-part/edit/index.js.map +1 -1
  85. package/build/template-part/edit/inner-blocks.js +106 -10
  86. package/build/template-part/edit/inner-blocks.js.map +1 -1
  87. package/build/template-part/edit/selection-modal.js +1 -9
  88. package/build/template-part/edit/selection-modal.js.map +1 -1
  89. package/build/utils/caption.js +19 -13
  90. package/build/utils/caption.js.map +1 -1
  91. package/build/utils/hooks.js +1 -0
  92. package/build/utils/hooks.js.map +1 -1
  93. package/build/video/edit.native.js +1 -1
  94. package/build/video/edit.native.js.map +1 -1
  95. package/build-module/block/edit.js +23 -17
  96. package/build-module/block/edit.js.map +1 -1
  97. package/build-module/button/edit.native.js +1 -1
  98. package/build-module/button/edit.native.js.map +1 -1
  99. package/build-module/code/save.js +3 -1
  100. package/build-module/code/save.js.map +1 -1
  101. package/build-module/cover/edit/index.js +2 -1
  102. package/build-module/cover/edit/index.js.map +1 -1
  103. package/build-module/details/edit.js +1 -0
  104. package/build-module/details/edit.js.map +1 -1
  105. package/build-module/file/edit.js +2 -0
  106. package/build-module/file/edit.js.map +1 -1
  107. package/build-module/heading/index.js +4 -3
  108. package/build-module/heading/index.js.map +1 -1
  109. package/build-module/image/edit.js +11 -40
  110. package/build-module/image/edit.js.map +1 -1
  111. package/build-module/image/image.js +27 -6
  112. package/build-module/image/image.js.map +1 -1
  113. package/build-module/media-text/edit.js +34 -10
  114. package/build-module/media-text/edit.js.map +1 -1
  115. package/build-module/media-text/index.js +5 -0
  116. package/build-module/media-text/index.js.map +1 -1
  117. package/build-module/media-text/media-container.js +31 -12
  118. package/build-module/media-text/media-container.js.map +1 -1
  119. package/build-module/media-text/save.js +2 -2
  120. package/build-module/media-text/save.js.map +1 -1
  121. package/build-module/navigation/edit/index.js +24 -30
  122. package/build-module/navigation/edit/index.js.map +1 -1
  123. package/build-module/navigation/edit/navigation-menu-delete-control.js +15 -23
  124. package/build-module/navigation/edit/navigation-menu-delete-control.js.map +1 -1
  125. package/build-module/navigation/edit/navigation-menu-selector.js +24 -23
  126. package/build-module/navigation/edit/navigation-menu-selector.js.map +1 -1
  127. package/build-module/navigation/edit/placeholder/index.js +4 -4
  128. package/build-module/navigation/edit/placeholder/index.js.map +1 -1
  129. package/build-module/navigation/use-navigation-menu.js +15 -12
  130. package/build-module/navigation/use-navigation-menu.js.map +1 -1
  131. package/build-module/navigation/view.js +12 -2
  132. package/build-module/navigation/view.js.map +1 -1
  133. package/build-module/navigation-link/edit.js +55 -30
  134. package/build-module/navigation-link/edit.js.map +1 -1
  135. package/build-module/navigation-submenu/edit.js +31 -9
  136. package/build-module/navigation-submenu/edit.js.map +1 -1
  137. package/build-module/pattern/edit.js +3 -1
  138. package/build-module/pattern/edit.js.map +1 -1
  139. package/build-module/post-author/edit.js +1 -0
  140. package/build-module/post-author/edit.js.map +1 -1
  141. package/build-module/post-excerpt/edit.js +1 -0
  142. package/build-module/post-excerpt/edit.js.map +1 -1
  143. package/build-module/post-featured-image/edit.js +17 -5
  144. package/build-module/post-featured-image/edit.js.map +1 -1
  145. package/build-module/post-featured-image/index.js +13 -2
  146. package/build-module/post-featured-image/index.js.map +1 -1
  147. package/build-module/post-featured-image/overlay-controls.js +75 -0
  148. package/build-module/post-featured-image/overlay-controls.js.map +1 -0
  149. package/build-module/post-featured-image/overlay.js +7 -56
  150. package/build-module/post-featured-image/overlay.js.map +1 -1
  151. package/build-module/post-navigation-link/edit.js +1 -0
  152. package/build-module/post-navigation-link/edit.js.map +1 -1
  153. package/build-module/post-terms/edit.js +2 -0
  154. package/build-module/post-terms/edit.js.map +1 -1
  155. package/build-module/quote/edit.js +20 -25
  156. package/build-module/quote/edit.js.map +1 -1
  157. package/build-module/read-more/edit.js +1 -0
  158. package/build-module/read-more/edit.js.map +1 -1
  159. package/build-module/search/edit.js +2 -0
  160. package/build-module/search/edit.js.map +1 -1
  161. package/build-module/search/edit.native.js +2 -2
  162. package/build-module/search/edit.native.js.map +1 -1
  163. package/build-module/site-tagline/edit.js +14 -5
  164. package/build-module/site-tagline/edit.js.map +1 -1
  165. package/build-module/site-tagline/index.js +4 -0
  166. package/build-module/site-tagline/index.js.map +1 -1
  167. package/build-module/social-link/edit.js +1 -1
  168. package/build-module/social-link/edit.js.map +1 -1
  169. package/build-module/social-link/icons/medium.js +1 -1
  170. package/build-module/social-link/icons/medium.js.map +1 -1
  171. package/build-module/social-link/icons/reddit.js +1 -1
  172. package/build-module/social-link/icons/reddit.js.map +1 -1
  173. package/build-module/table/deprecated.js +286 -176
  174. package/build-module/table/deprecated.js.map +1 -1
  175. package/build-module/table/index.js +1 -1
  176. package/build-module/template-part/edit/index.js +58 -50
  177. package/build-module/template-part/edit/index.js.map +1 -1
  178. package/build-module/template-part/edit/inner-blocks.js +108 -12
  179. package/build-module/template-part/edit/inner-blocks.js.map +1 -1
  180. package/build-module/template-part/edit/selection-modal.js +2 -10
  181. package/build-module/template-part/edit/selection-modal.js.map +1 -1
  182. package/build-module/utils/caption.js +19 -13
  183. package/build-module/utils/caption.js.map +1 -1
  184. package/build-module/utils/hooks.js +1 -0
  185. package/build-module/utils/hooks.js.map +1 -1
  186. package/build-module/video/edit.native.js +1 -1
  187. package/build-module/video/edit.native.js.map +1 -1
  188. package/build-style/audio/theme-rtl.css +1 -1
  189. package/build-style/audio/theme.css +1 -1
  190. package/build-style/cover/style-rtl.css +5 -2
  191. package/build-style/cover/style.css +5 -2
  192. package/build-style/editor-rtl.css +22 -12
  193. package/build-style/editor.css +22 -12
  194. package/build-style/embed/theme-rtl.css +1 -1
  195. package/build-style/embed/theme.css +1 -1
  196. package/build-style/file/editor-rtl.css +3 -0
  197. package/build-style/file/editor.css +3 -0
  198. package/build-style/image/editor-rtl.css +0 -3
  199. package/build-style/image/editor.css +0 -3
  200. package/build-style/image/theme-rtl.css +1 -1
  201. package/build-style/image/theme.css +1 -1
  202. package/build-style/media-text/editor-rtl.css +7 -1
  203. package/build-style/media-text/editor.css +7 -1
  204. package/build-style/pullquote/theme-rtl.css +2 -1
  205. package/build-style/pullquote/theme.css +2 -1
  206. package/build-style/quote/theme-rtl.css +6 -6
  207. package/build-style/quote/theme.css +6 -6
  208. package/build-style/search/style-rtl.css +10 -0
  209. package/build-style/search/style.css +10 -0
  210. package/build-style/social-links/editor-rtl.css +0 -4
  211. package/build-style/social-links/editor.css +0 -4
  212. package/build-style/social-links/style-rtl.css +2 -2
  213. package/build-style/social-links/style.css +2 -2
  214. package/build-style/style-rtl.css +17 -4
  215. package/build-style/style.css +17 -4
  216. package/build-style/table/theme-rtl.css +4 -3
  217. package/build-style/table/theme.css +4 -3
  218. package/build-style/template-part/editor-rtl.css +12 -4
  219. package/build-style/template-part/editor.css +12 -4
  220. package/build-style/template-part/theme-rtl.css +1 -1
  221. package/build-style/template-part/theme.css +1 -1
  222. package/build-style/theme-rtl.css +17 -15
  223. package/build-style/theme.css +17 -15
  224. package/build-style/video/theme-rtl.css +1 -1
  225. package/build-style/video/theme.css +1 -1
  226. package/package.json +34 -34
  227. package/src/archives/index.php +4 -0
  228. package/src/audio/theme.scss +1 -1
  229. package/src/avatar/index.php +6 -0
  230. package/src/block/edit.js +43 -32
  231. package/src/block/index.php +4 -0
  232. package/src/block/test/edit.native.js +67 -0
  233. package/src/button/edit.native.js +1 -1
  234. package/src/calendar/index.php +12 -0
  235. package/src/categories/index.php +6 -0
  236. package/src/code/save.js +7 -1
  237. package/src/comment-author-name/index.php +4 -0
  238. package/src/comment-content/index.php +4 -0
  239. package/src/comment-date/index.php +4 -0
  240. package/src/comment-edit-link/index.php +4 -0
  241. package/src/comment-reply-link/index.php +4 -0
  242. package/src/comment-template/index.php +4 -0
  243. package/src/comments/index.php +10 -0
  244. package/src/comments-pagination/index.php +4 -0
  245. package/src/comments-pagination-next/index.php +4 -0
  246. package/src/comments-pagination-numbers/index.php +4 -0
  247. package/src/comments-pagination-previous/index.php +4 -0
  248. package/src/comments-title/index.php +4 -0
  249. package/src/cover/edit/index.js +4 -1
  250. package/src/cover/index.php +4 -0
  251. package/src/cover/style.scss +6 -2
  252. package/src/details/edit.js +1 -0
  253. package/src/embed/theme.scss +1 -1
  254. package/src/file/edit.js +2 -0
  255. package/src/file/editor.scss +3 -0
  256. package/src/file/index.php +4 -0
  257. package/src/gallery/editor.scss +1 -1
  258. package/src/gallery/index.php +7 -1
  259. package/src/heading/index.js +4 -3
  260. package/src/heading/index.php +4 -0
  261. package/src/home-link/index.php +10 -0
  262. package/src/image/edit.js +11 -40
  263. package/src/image/editor.scss +2 -7
  264. package/src/image/image.js +25 -7
  265. package/src/image/index.php +12 -1
  266. package/src/image/theme.scss +1 -1
  267. package/src/latest-comments/index.php +4 -0
  268. package/src/latest-posts/index.php +8 -0
  269. package/src/loginout/index.php +4 -0
  270. package/src/media-text/block.json +5 -0
  271. package/src/media-text/edit.js +70 -19
  272. package/src/media-text/editor.scss +7 -1
  273. package/src/media-text/index.php +70 -0
  274. package/src/media-text/media-container.js +49 -9
  275. package/src/media-text/save.js +2 -2
  276. package/src/navigation/edit/index.js +67 -71
  277. package/src/navigation/edit/navigation-menu-delete-control.js +22 -49
  278. package/src/navigation/edit/navigation-menu-selector.js +39 -21
  279. package/src/navigation/edit/placeholder/index.js +4 -4
  280. package/src/navigation/edit/test/navigation-menu-selector.js +75 -53
  281. package/src/navigation/index.php +109 -26
  282. package/src/navigation/test/use-navigation-menu.js +21 -21
  283. package/src/navigation/use-navigation-menu.js +23 -9
  284. package/src/navigation/view.js +11 -2
  285. package/src/navigation-link/edit.js +64 -39
  286. package/src/navigation-link/index.php +14 -0
  287. package/src/navigation-submenu/edit.js +34 -10
  288. package/src/navigation-submenu/index.php +8 -0
  289. package/src/page-list/index.php +12 -0
  290. package/src/page-list-item/index.php +2 -0
  291. package/src/pattern/edit.js +4 -0
  292. package/src/pattern/index.php +2 -0
  293. package/src/post-author/edit.js +1 -0
  294. package/src/post-author/index.php +4 -0
  295. package/src/post-author-biography/index.php +4 -0
  296. package/src/post-author-name/index.php +4 -0
  297. package/src/post-comments-form/index.php +6 -0
  298. package/src/post-content/index.php +4 -0
  299. package/src/post-date/index.php +4 -0
  300. package/src/post-excerpt/edit.js +1 -0
  301. package/src/post-excerpt/index.php +4 -0
  302. package/src/post-featured-image/block.json +13 -2
  303. package/src/post-featured-image/edit.js +16 -1
  304. package/src/post-featured-image/editor.scss +1 -1
  305. package/src/post-featured-image/index.php +15 -0
  306. package/src/post-featured-image/overlay-controls.js +88 -0
  307. package/src/post-featured-image/overlay.js +17 -84
  308. package/src/post-navigation-link/edit.js +1 -0
  309. package/src/post-navigation-link/index.php +4 -0
  310. package/src/post-template/index.php +4 -0
  311. package/src/post-terms/edit.js +2 -0
  312. package/src/post-terms/index.php +6 -0
  313. package/src/post-title/index.php +2 -0
  314. package/src/pullquote/theme.scss +3 -1
  315. package/src/query/index.php +2 -0
  316. package/src/query-no-results/index.php +6 -0
  317. package/src/query-pagination/index.php +4 -0
  318. package/src/query-pagination-next/index.php +6 -0
  319. package/src/query-pagination-numbers/index.php +6 -0
  320. package/src/query-pagination-previous/index.php +4 -0
  321. package/src/query-title/index.php +4 -0
  322. package/src/quote/edit.js +27 -37
  323. package/src/quote/test/edit.native.js +4 -6
  324. package/src/quote/theme.scss +1 -2
  325. package/src/read-more/edit.js +1 -0
  326. package/src/read-more/index.php +4 -0
  327. package/src/rss/index.php +4 -0
  328. package/src/search/edit.js +2 -0
  329. package/src/search/edit.native.js +2 -2
  330. package/src/search/index.php +19 -1
  331. package/src/search/style.scss +11 -0
  332. package/src/shortcode/index.php +4 -0
  333. package/src/site-logo/editor.scss +2 -2
  334. package/src/site-logo/index.php +20 -0
  335. package/src/site-tagline/block.json +4 -0
  336. package/src/site-tagline/edit.js +16 -3
  337. package/src/site-tagline/index.php +13 -1
  338. package/src/site-title/index.php +4 -0
  339. package/src/social-link/edit.js +1 -1
  340. package/src/social-link/icons/medium.js +1 -1
  341. package/src/social-link/icons/reddit.js +1 -1
  342. package/src/social-link/index.php +22 -9
  343. package/src/social-link/socials-with-bg.scss +1 -1
  344. package/src/social-link/socials-without-bg.scss +1 -1
  345. package/src/social-links/editor.scss +1 -9
  346. package/src/table/block.json +1 -1
  347. package/src/table/deprecated.js +308 -175
  348. package/src/table/theme.scss +4 -2
  349. package/src/tag-cloud/index.php +4 -0
  350. package/src/template-part/edit/index.js +87 -79
  351. package/src/template-part/edit/inner-blocks.js +126 -13
  352. package/src/template-part/edit/selection-modal.js +1 -22
  353. package/src/template-part/editor.scss +11 -3
  354. package/src/template-part/index.php +12 -0
  355. package/src/template-part/theme.scss +1 -1
  356. package/src/term-description/index.php +4 -0
  357. package/src/utils/caption.js +19 -16
  358. package/src/utils/hooks.js +1 -0
  359. package/src/video/edit.native.js +2 -0
  360. package/src/video/editor.scss +2 -2
  361. package/src/video/theme.scss +1 -1
  362. package/tsconfig.json +1 -0
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
+ import { serialize } from '@wordpress/blocks';
4
5
  import { useSelect, useDispatch } from '@wordpress/data';
5
6
  import {
6
7
  BlockSettingsMenuControls,
@@ -11,8 +12,15 @@ import {
11
12
  useHasRecursion,
12
13
  InspectorControls,
13
14
  __experimentalBlockPatternsList as BlockPatternsList,
15
+ BlockControls,
14
16
  } from '@wordpress/block-editor';
15
- import { PanelBody, Spinner, Modal, MenuItem } from '@wordpress/components';
17
+ import {
18
+ PanelBody,
19
+ Spinner,
20
+ Modal,
21
+ MenuItem,
22
+ ToolbarButton,
23
+ } from '@wordpress/components';
16
24
  import { useAsyncList } from '@wordpress/compose';
17
25
  import { __, sprintf } from '@wordpress/i18n';
18
26
  import { store as coreStore } from '@wordpress/core-data';
@@ -27,28 +35,26 @@ import TemplatePartSelectionModal from './selection-modal';
27
35
  import { TemplatePartAdvancedControls } from './advanced-controls';
28
36
  import TemplatePartInnerBlocks from './inner-blocks';
29
37
  import { createTemplatePartId } from './utils/create-template-part-id';
30
- import { mapTemplatePartToBlockPattern } from './utils/map-template-part-to-block-pattern';
31
38
  import {
32
39
  useAlternativeBlockPatterns,
33
40
  useAlternativeTemplateParts,
34
41
  useTemplatePartArea,
35
- useCreateTemplatePartFromBlocks,
36
42
  } from './utils/hooks';
37
43
 
38
44
  function ReplaceButton( {
39
45
  isEntityAvailable,
40
46
  area,
41
- clientId,
42
47
  templatePartId,
43
48
  isTemplatePartSelectionOpen,
44
49
  setIsTemplatePartSelectionOpen,
45
50
  } ) {
51
+ // This hook fetches patterns, so don't run it unconditionally in the main
52
+ // edit function!
46
53
  const { templateParts } = useAlternativeTemplateParts(
47
54
  area,
48
55
  templatePartId
49
56
  );
50
- const blockPatterns = useAlternativeBlockPatterns( area, clientId );
51
- const hasReplacements = !! templateParts.length || !! blockPatterns.length;
57
+ const hasReplacements = !! templateParts.length;
52
58
  const canReplace =
53
59
  isEntityAvailable &&
54
60
  hasReplacements &&
@@ -71,20 +77,30 @@ function ReplaceButton( {
71
77
  );
72
78
  }
73
79
 
74
- function TemplatesList( { availableTemplates, onSelect } ) {
75
- const shownTemplates = useAsyncList( availableTemplates );
80
+ function TemplatesList( { area, clientId, isEntityAvailable, onSelect } ) {
81
+ // This hook fetches patterns, so don't run it unconditionally in the main
82
+ // edit function!
83
+ const blockPatterns = useAlternativeBlockPatterns( area, clientId );
84
+ const canReplace =
85
+ isEntityAvailable &&
86
+ !! blockPatterns.length &&
87
+ ( area === 'header' || area === 'footer' );
88
+ const shownTemplates = useAsyncList( blockPatterns );
76
89
 
77
- if ( ! availableTemplates ) {
90
+ if ( ! canReplace ) {
78
91
  return null;
79
92
  }
80
93
 
81
94
  return (
82
- <BlockPatternsList
83
- label={ __( 'Templates' ) }
84
- blockPatterns={ availableTemplates }
85
- shownPatterns={ shownTemplates }
86
- onClickPattern={ onSelect }
87
- />
95
+ <PanelBody title={ __( 'Design' ) }>
96
+ <BlockPatternsList
97
+ label={ __( 'Templates' ) }
98
+ blockPatterns={ blockPatterns }
99
+ shownPatterns={ shownTemplates }
100
+ onClickPattern={ onSelect }
101
+ showTitle={ false }
102
+ />
103
+ </PanelBody>
88
104
  );
89
105
  }
90
106
 
@@ -94,6 +110,7 @@ export default function TemplatePartEdit( {
94
110
  clientId,
95
111
  } ) {
96
112
  const { createSuccessNotice } = useDispatch( noticesStore );
113
+ const { editEntityRecord } = useDispatch( coreStore );
97
114
  const currentTheme = useSelect(
98
115
  ( select ) => select( coreStore ).getCurrentTheme()?.stylesheet,
99
116
  []
@@ -104,11 +121,18 @@ export default function TemplatePartEdit( {
104
121
  const [ isTemplatePartSelectionOpen, setIsTemplatePartSelectionOpen ] =
105
122
  useState( false );
106
123
 
107
- const { isResolved, hasInnerBlocks, isMissing, area } = useSelect(
124
+ const {
125
+ isResolved,
126
+ hasInnerBlocks,
127
+ isMissing,
128
+ area,
129
+ onNavigateToEntityRecord,
130
+ title,
131
+ } = useSelect(
108
132
  ( select ) => {
109
133
  const { getEditedEntityRecord, hasFinishedResolution } =
110
134
  select( coreStore );
111
- const { getBlockCount } = select( blockEditorStore );
135
+ const { getBlockCount, getSettings } = select( blockEditorStore );
112
136
 
113
137
  const getEntityArgs = [
114
138
  'postType',
@@ -134,32 +158,41 @@ export default function TemplatePartEdit( {
134
158
  ( ! entityRecord ||
135
159
  Object.keys( entityRecord ).length === 0 ),
136
160
  area: _area,
161
+ onNavigateToEntityRecord:
162
+ getSettings().onNavigateToEntityRecord,
163
+ title: entityRecord?.title,
137
164
  };
138
165
  },
139
166
  [ templatePartId, attributes.area, clientId ]
140
167
  );
141
168
 
142
- const { templateParts } = useAlternativeTemplateParts(
143
- area,
144
- templatePartId
145
- );
146
- const blockPatterns = useAlternativeBlockPatterns( area, clientId );
147
- const hasReplacements = !! templateParts.length || !! blockPatterns.length;
148
169
  const areaObject = useTemplatePartArea( area );
149
170
  const blockProps = useBlockProps();
150
171
  const isPlaceholder = ! slug;
151
172
  const isEntityAvailable = ! isPlaceholder && ! isMissing && isResolved;
152
173
  const TagName = tagName || areaObject.tagName;
153
174
 
154
- const canReplace =
155
- isEntityAvailable &&
156
- hasReplacements &&
157
- ( area === 'header' || area === 'footer' );
158
-
159
- const createFromBlocks = useCreateTemplatePartFromBlocks(
160
- area,
161
- setAttributes
162
- );
175
+ const onPatternSelect = async ( pattern ) => {
176
+ await editEntityRecord(
177
+ 'postType',
178
+ 'wp_template_part',
179
+ templatePartId,
180
+ {
181
+ blocks: pattern.blocks,
182
+ content: serialize( pattern.blocks ),
183
+ }
184
+ );
185
+ createSuccessNotice(
186
+ sprintf(
187
+ /* translators: %s: template part title. */
188
+ __( 'Template Part "%s" updated.' ),
189
+ title || slug
190
+ ),
191
+ {
192
+ type: 'snackbar',
193
+ }
194
+ );
195
+ };
163
196
 
164
197
  // We don't want to render a missing state if we have any inner blocks.
165
198
  // A new template part is automatically created if we have any inner blocks but no entity.
@@ -192,31 +225,23 @@ export default function TemplatePartEdit( {
192
225
  );
193
226
  }
194
227
 
195
- const partsAsPatterns = templateParts.map( ( templatePart ) =>
196
- mapTemplatePartToBlockPattern( templatePart )
197
- );
198
-
199
- const onTemplatePartSelect = ( templatePart ) => {
200
- setAttributes( {
201
- slug: templatePart.slug,
202
- theme: templatePart.theme,
203
- area: undefined,
204
- } );
205
- createSuccessNotice(
206
- sprintf(
207
- /* translators: %s: template part title. */
208
- __( 'Template Part "%s" replaceed.' ),
209
- templatePart.title?.rendered || templatePart.slug
210
- ),
211
- {
212
- type: 'snackbar',
213
- }
214
- );
215
- };
216
-
217
228
  return (
218
229
  <>
219
230
  <RecursionProvider uniqueId={ templatePartId }>
231
+ { isEntityAvailable && onNavigateToEntityRecord && (
232
+ <BlockControls group="other">
233
+ <ToolbarButton
234
+ onClick={ () =>
235
+ onNavigateToEntityRecord( {
236
+ postId: templatePartId,
237
+ postType: 'wp_template_part',
238
+ } )
239
+ }
240
+ >
241
+ { __( 'Edit' ) }
242
+ </ToolbarButton>
243
+ </BlockControls>
244
+ ) }
220
245
  <InspectorControls group="advanced">
221
246
  <TemplatePartAdvancedControls
222
247
  tagName={ tagName }
@@ -268,31 +293,14 @@ export default function TemplatePartEdit( {
268
293
  } }
269
294
  </BlockSettingsMenuControls>
270
295
 
271
- { canReplace &&
272
- ( partsAsPatterns.length > 0 ||
273
- blockPatterns.length > 0 ) && (
274
- <InspectorControls>
275
- <PanelBody title={ __( 'Replace' ) }>
276
- <TemplatesList
277
- availableTemplates={ partsAsPatterns }
278
- onSelect={ ( pattern ) => {
279
- onTemplatePartSelect(
280
- pattern.templatePart
281
- );
282
- } }
283
- />
284
- <TemplatesList
285
- availableTemplates={ blockPatterns }
286
- onSelect={ ( pattern, blocks ) => {
287
- createFromBlocks(
288
- blocks,
289
- pattern.title
290
- );
291
- } }
292
- />
293
- </PanelBody>
294
- </InspectorControls>
295
- ) }
296
+ <InspectorControls>
297
+ <TemplatesList
298
+ area={ area }
299
+ clientId={ clientId }
300
+ isEntityAvailable={ isEntityAvailable }
301
+ onSelect={ ( pattern ) => onPatternSelect( pattern ) }
302
+ />
303
+ </InspectorControls>
296
304
 
297
305
  { isEntityAvailable && (
298
306
  <TemplatePartInnerBlocks
@@ -1,29 +1,105 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { useEntityBlockEditor } from '@wordpress/core-data';
4
+ import { useEntityBlockEditor, store as coreStore } from '@wordpress/core-data';
5
5
  import {
6
6
  InnerBlocks,
7
7
  useInnerBlocksProps,
8
8
  useSettings,
9
9
  store as blockEditorStore,
10
+ useBlockEditingMode,
10
11
  } from '@wordpress/block-editor';
11
12
  import { useSelect } from '@wordpress/data';
13
+ import { useMemo } from '@wordpress/element';
14
+ import { parse } from '@wordpress/blocks';
12
15
 
13
- export default function TemplatePartInnerBlocks( {
14
- postId: id,
15
- hasInnerBlocks,
16
- layout,
17
- tagName: TagName,
18
- blockProps,
19
- } ) {
16
+ function useRenderAppender( hasInnerBlocks ) {
17
+ const blockEditingMode = useBlockEditingMode();
18
+ // Disable appending when the editing mode is 'contentOnly'. This is so that the user can't
19
+ // append into a template part when editing a page in the site editor. See
20
+ // DisableNonPageContentBlocks. Ideally instead of (mis)using editing mode there would be a
21
+ // block editor API for achieving this.
22
+ if ( blockEditingMode === 'contentOnly' ) {
23
+ return false;
24
+ }
25
+ if ( ! hasInnerBlocks ) {
26
+ return InnerBlocks.ButtonBlockAppender;
27
+ }
28
+ }
29
+
30
+ function useLayout( layout ) {
20
31
  const themeSupportsLayout = useSelect( ( select ) => {
21
32
  const { getSettings } = select( blockEditorStore );
22
33
  return getSettings()?.supportsLayout;
23
34
  }, [] );
24
35
  const [ defaultLayout ] = useSettings( 'layout' );
25
- const usedLayout = layout?.inherit ? defaultLayout || {} : layout;
36
+ if ( themeSupportsLayout ) {
37
+ return layout?.inherit ? defaultLayout || {} : layout;
38
+ }
39
+ }
26
40
 
41
+ function NonEditableTemplatePartPreview( {
42
+ postId: id,
43
+ layout,
44
+ tagName: TagName,
45
+ blockProps,
46
+ } ) {
47
+ useBlockEditingMode( 'disabled' );
48
+
49
+ const { content, editedBlocks } = useSelect(
50
+ ( select ) => {
51
+ if ( ! id ) {
52
+ return {};
53
+ }
54
+ const { getEditedEntityRecord } = select( coreStore );
55
+ const editedRecord = getEditedEntityRecord(
56
+ 'postType',
57
+ 'wp_template_part',
58
+ id,
59
+ { context: 'view' }
60
+ );
61
+ return {
62
+ editedBlocks: editedRecord.blocks,
63
+ content: editedRecord.content,
64
+ };
65
+ },
66
+ [ id ]
67
+ );
68
+
69
+ const blocks = useMemo( () => {
70
+ if ( ! id ) {
71
+ return undefined;
72
+ }
73
+
74
+ if ( editedBlocks ) {
75
+ return editedBlocks;
76
+ }
77
+
78
+ if ( ! content || typeof content !== 'string' ) {
79
+ return [];
80
+ }
81
+
82
+ return parse( content );
83
+ }, [ id, editedBlocks, content ] );
84
+
85
+ const innerBlocksProps = useInnerBlocksProps( blockProps, {
86
+ value: blocks,
87
+ onInput: () => {},
88
+ onChange: () => {},
89
+ renderAppender: false,
90
+ layout: useLayout( layout ),
91
+ } );
92
+
93
+ return <TagName { ...innerBlocksProps } />;
94
+ }
95
+
96
+ function EditableTemplatePartInnerBlocks( {
97
+ postId: id,
98
+ hasInnerBlocks,
99
+ layout,
100
+ tagName: TagName,
101
+ blockProps,
102
+ } ) {
27
103
  const [ blocks, onInput, onChange ] = useEntityBlockEditor(
28
104
  'postType',
29
105
  'wp_template_part',
@@ -34,11 +110,48 @@ export default function TemplatePartInnerBlocks( {
34
110
  value: blocks,
35
111
  onInput,
36
112
  onChange,
37
- renderAppender: hasInnerBlocks
38
- ? undefined
39
- : InnerBlocks.ButtonBlockAppender,
40
- layout: themeSupportsLayout ? usedLayout : undefined,
113
+ renderAppender: useRenderAppender( hasInnerBlocks ),
114
+ layout: useLayout( layout ),
41
115
  } );
42
116
 
43
117
  return <TagName { ...innerBlocksProps } />;
44
118
  }
119
+
120
+ export default function TemplatePartInnerBlocks( {
121
+ postId: id,
122
+ hasInnerBlocks,
123
+ layout,
124
+ tagName: TagName,
125
+ blockProps,
126
+ } ) {
127
+ const { canViewTemplatePart, canEditTemplatePart } = useSelect(
128
+ ( select ) => {
129
+ return {
130
+ canViewTemplatePart:
131
+ select( coreStore ).canUser( 'read', 'templates' ) ?? false,
132
+ canEditTemplatePart:
133
+ select( coreStore ).canUser( 'create', 'templates' ) ??
134
+ false,
135
+ };
136
+ },
137
+ []
138
+ );
139
+
140
+ if ( ! canViewTemplatePart ) {
141
+ return null;
142
+ }
143
+
144
+ const TemplatePartInnerBlocksComponent = canEditTemplatePart
145
+ ? EditableTemplatePartInnerBlocks
146
+ : NonEditableTemplatePartPreview;
147
+
148
+ return (
149
+ <TemplatePartInnerBlocksComponent
150
+ postId={ id }
151
+ hasInnerBlocks={ hasInnerBlocks }
152
+ layout={ layout }
153
+ tagName={ TagName }
154
+ blockProps={ blockProps }
155
+ />
156
+ );
157
+ }
@@ -18,7 +18,6 @@ import {
18
18
  import {
19
19
  useAlternativeBlockPatterns,
20
20
  useAlternativeTemplateParts,
21
- useCreateTemplatePartFromBlocks,
22
21
  } from './utils/hooks';
23
22
  import { mapTemplatePartToBlockPattern } from './utils/map-template-part-to-block-pattern';
24
23
  import { searchPatterns } from '../../utils/search-patterns';
@@ -31,11 +30,11 @@ export default function TemplatePartSelectionModal( {
31
30
  clientId,
32
31
  } ) {
33
32
  const [ searchValue, setSearchValue ] = useState( '' );
34
-
35
33
  const { templateParts } = useAlternativeTemplateParts(
36
34
  area,
37
35
  templatePartId
38
36
  );
37
+
39
38
  // We can map template parts to block patters to reuse the BlockPatternsList UI
40
39
  const filteredTemplateParts = useMemo( () => {
41
40
  const partsAsPatterns = templateParts.map( ( templatePart ) =>
@@ -49,7 +48,6 @@ export default function TemplatePartSelectionModal( {
49
48
  const filteredBlockPatterns = useMemo( () => {
50
49
  return searchPatterns( blockPatterns, searchValue );
51
50
  }, [ blockPatterns, searchValue ] );
52
- const shownBlockPatterns = useAsyncList( filteredBlockPatterns );
53
51
 
54
52
  const { createSuccessNotice } = useDispatch( noticesStore );
55
53
 
@@ -72,11 +70,6 @@ export default function TemplatePartSelectionModal( {
72
70
  onClose();
73
71
  };
74
72
 
75
- const createFromBlocks = useCreateTemplatePartFromBlocks(
76
- area,
77
- setAttributes
78
- );
79
-
80
73
  const hasTemplateParts = !! filteredTemplateParts.length;
81
74
  const hasBlockPatterns = !! filteredBlockPatterns.length;
82
75
 
@@ -104,20 +97,6 @@ export default function TemplatePartSelectionModal( {
104
97
  </div>
105
98
  ) }
106
99
 
107
- { hasBlockPatterns && (
108
- <div>
109
- <h2>{ __( 'Patterns' ) }</h2>
110
- <BlockPatternsList
111
- blockPatterns={ filteredBlockPatterns }
112
- shownPatterns={ shownBlockPatterns }
113
- onClickPattern={ ( pattern, blocks ) => {
114
- createFromBlocks( blocks, pattern.title );
115
- onClose();
116
- } }
117
- />
118
- </div>
119
- ) }
120
-
121
100
  { ! hasTemplateParts && ! hasBlockPatterns && (
122
101
  <HStack alignment="center">
123
102
  <p>{ __( 'No results found.' ) }</p>
@@ -25,9 +25,13 @@
25
25
 
26
26
  .is-outline-mode .block-editor-block-list__block:not(.remove-outline).wp-block-template-part,
27
27
  .is-outline-mode .block-editor-block-list__block:not(.remove-outline).is-reusable {
28
- &.is-highlighted,
29
- &.is-selected {
30
- box-shadow: inset 0 0 0 var(--wp-admin-border-width-focus) var(--wp-block-synced-color);
28
+ &.is-highlighted::after,
29
+ &.is-selected::after {
30
+ box-shadow: 0 0 0 var(--wp-admin-border-width-focus) var(--wp-block-synced-color);
31
+ }
32
+
33
+ &.is-hovered::after {
34
+ box-shadow: 0 0 0 $border-width var(--wp-block-synced-color);
31
35
  }
32
36
 
33
37
  &.block-editor-block-list__block:not([contenteditable]):focus {
@@ -40,3 +44,7 @@
40
44
  }
41
45
  }
42
46
  }
47
+
48
+ .is-outline-mode .block-editor-block-list__block:not(.remove-outline).wp-block-template-part.has-editable-outline::after {
49
+ border: none;
50
+ }
@@ -8,6 +8,10 @@
8
8
  /**
9
9
  * Renders the `core/template-part` block on the server.
10
10
  *
11
+ * @since 5.9.0
12
+ *
13
+ * @global WP_Embed $wp_embed WordPress Embed object.
14
+ *
11
15
  * @param array $attributes The block attributes.
12
16
  *
13
17
  * @return string The render.
@@ -174,6 +178,8 @@ function render_block_core_template_part( $attributes ) {
174
178
  /**
175
179
  * Returns an array of area variation objects for the template part block.
176
180
  *
181
+ * @since 6.1.0
182
+ *
177
183
  * @param array $instance_variations The variations for instances.
178
184
  *
179
185
  * @return array Array containing the block variation objects.
@@ -212,6 +218,8 @@ function build_template_part_block_area_variations( $instance_variations ) {
212
218
  /**
213
219
  * Returns an array of instance variation objects for the template part block
214
220
  *
221
+ * @since 6.1.0
222
+ *
215
223
  * @return array Array containing the block variation objects.
216
224
  */
217
225
  function build_template_part_block_instance_variations() {
@@ -266,6 +274,8 @@ function build_template_part_block_instance_variations() {
266
274
  /**
267
275
  * Returns an array of all template part block variations.
268
276
  *
277
+ * @since 5.9.0
278
+ *
269
279
  * @return array Array containing the block variation objects.
270
280
  */
271
281
  function build_template_part_block_variations() {
@@ -276,6 +286,8 @@ function build_template_part_block_variations() {
276
286
 
277
287
  /**
278
288
  * Registers the `core/template-part` block on the server.
289
+ *
290
+ * @since 5.9.0
279
291
  */
280
292
  function register_block_core_template_part() {
281
293
  register_block_type_from_metadata(
@@ -1,5 +1,5 @@
1
1
  // Same as the group block styles.
2
- .wp-block-template-part {
2
+ :where(.wp-block-template-part) {
3
3
  &.has-background {
4
4
  // Matches paragraph Block padding
5
5
  padding: $block-bg-padding--v $block-bg-padding--h;
@@ -8,6 +8,8 @@
8
8
  /**
9
9
  * Renders the `core/term-description` block on the server.
10
10
  *
11
+ * @since 5.9.0
12
+ *
11
13
  * @param array $attributes Block attributes.
12
14
  *
13
15
  * @return string Returns the description of the current taxonomy term, if available
@@ -37,6 +39,8 @@ function render_block_core_term_description( $attributes ) {
37
39
 
38
40
  /**
39
41
  * Registers the `core/term-description` block on the server.
42
+ *
43
+ * @since 5.9.0
40
44
  */
41
45
  function register_block_core_term_description() {
42
46
  register_block_type_from_metadata(
@@ -23,10 +23,8 @@ import { createBlock, getDefaultBlockName } from '@wordpress/blocks';
23
23
  */
24
24
  import { unlock } from '../lock-unlock';
25
25
 
26
- const { PrivateRichText: RichText } = unlock( blockEditorPrivateApis );
27
-
28
26
  export function Caption( {
29
- key = 'caption',
27
+ attributeKey = 'caption',
30
28
  attributes,
31
29
  setAttributes,
32
30
  isSelected,
@@ -35,10 +33,16 @@ export function Caption( {
35
33
  label = __( 'Caption text' ),
36
34
  showToolbarButton = true,
37
35
  className,
38
- disableEditing,
36
+ readOnly,
37
+ tagName = 'figcaption',
38
+ addLabel = __( 'Add caption' ),
39
+ removeLabel = __( 'Remove caption' ),
40
+ icon = captionIcon,
41
+ ...props
39
42
  } ) {
40
- const caption = attributes[ key ];
43
+ const caption = attributes[ attributeKey ];
41
44
  const prevCaption = usePrevious( caption );
45
+ const { PrivateRichText: RichText } = unlock( blockEditorPrivateApis );
42
46
  const isCaptionEmpty = RichText.isEmpty( caption );
43
47
  const isPrevCaptionEmpty = RichText.isEmpty( prevCaption );
44
48
  const [ showCaption, setShowCaption ] = useState( ! isCaptionEmpty );
@@ -74,24 +78,22 @@ export function Caption( {
74
78
  onClick={ () => {
75
79
  setShowCaption( ! showCaption );
76
80
  if ( showCaption && caption ) {
77
- setAttributes( { caption: undefined } );
81
+ setAttributes( {
82
+ [ attributeKey ]: undefined,
83
+ } );
78
84
  }
79
85
  } }
80
- icon={ captionIcon }
86
+ icon={ icon }
81
87
  isPressed={ showCaption }
82
- label={
83
- showCaption
84
- ? __( 'Remove caption' )
85
- : __( 'Add caption' )
86
- }
88
+ label={ showCaption ? removeLabel : addLabel }
87
89
  />
88
90
  </BlockControls>
89
91
  ) }
90
92
  { showCaption &&
91
93
  ( ! RichText.isEmpty( caption ) || isSelected ) && (
92
94
  <RichText
93
- identifier={ key }
94
- tagName="figcaption"
95
+ identifier={ attributeKey }
96
+ tagName={ tagName }
95
97
  className={ classnames(
96
98
  className,
97
99
  __experimentalGetElementClassName( 'caption' )
@@ -101,7 +103,7 @@ export function Caption( {
101
103
  placeholder={ placeholder }
102
104
  value={ caption }
103
105
  onChange={ ( value ) =>
104
- setAttributes( { caption: value } )
106
+ setAttributes( { [ attributeKey ]: value } )
105
107
  }
106
108
  inlineToolbar
107
109
  __unstableOnSplitAtEnd={ () =>
@@ -109,7 +111,8 @@ export function Caption( {
109
111
  createBlock( getDefaultBlockName() )
110
112
  )
111
113
  }
112
- disableEditing={ disableEditing }
114
+ readOnly={ readOnly }
115
+ { ...props }
113
116
  />
114
117
  ) }
115
118
  </>
@@ -67,6 +67,7 @@ export function useUploadMediaFromBlobURL( args = {} ) {
67
67
  onChange( media );
68
68
  },
69
69
  onError: ( message ) => {
70
+ revokeBlobURL( url );
70
71
  onError( message );
71
72
  },
72
73
  } );
@@ -290,8 +290,10 @@ class VideoEdit extends Component {
290
290
  } ) => {
291
291
  const showVideo =
292
292
  isURL( src ) &&
293
+ getProtocol( attributes.src ) !== 'file:' &&
293
294
  ! isUploadInProgress &&
294
295
  ! isUploadFailed;
296
+
295
297
  const icon = this.getIcon(
296
298
  isUploadFailed
297
299
  ? ICON_TYPE.RETRY