@wordpress/block-library 7.17.0 → 7.19.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 (374) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/build/audio/edit.js +44 -4
  3. package/build/audio/edit.js.map +1 -1
  4. package/build/button/deprecated.js +16 -2
  5. package/build/button/deprecated.js.map +1 -1
  6. package/build/button/edit.js +14 -8
  7. package/build/button/edit.js.map +1 -1
  8. package/build/button/index.js +4 -1
  9. package/build/button/index.js.map +1 -1
  10. package/build/button/save.js +2 -0
  11. package/build/button/save.js.map +1 -1
  12. package/build/buttons/edit.native.js +1 -1
  13. package/build/buttons/edit.native.js.map +1 -1
  14. package/build/columns/transforms.js +5 -0
  15. package/build/columns/transforms.js.map +1 -1
  16. package/build/comment-template/index.js +6 -2
  17. package/build/comment-template/index.js.map +1 -1
  18. package/build/cover/edit/index.js +3 -1
  19. package/build/cover/edit/index.js.map +1 -1
  20. package/build/cover/edit/inspector-controls.js +3 -7
  21. package/build/cover/edit/inspector-controls.js.map +1 -1
  22. package/build/embed/deprecated.js +43 -4
  23. package/build/embed/deprecated.js.map +1 -1
  24. package/build/file/deprecated.js +108 -4
  25. package/build/file/deprecated.js.map +1 -1
  26. package/build/file/transforms.js +3 -9
  27. package/build/file/transforms.js.map +1 -1
  28. package/build/gallery/deprecated.js +148 -23
  29. package/build/gallery/deprecated.js.map +1 -1
  30. package/build/gallery/gallery.js +3 -2
  31. package/build/gallery/gallery.js.map +1 -1
  32. package/build/gallery/use-image-sizes.js +2 -1
  33. package/build/gallery/use-image-sizes.js.map +1 -1
  34. package/build/gallery/v1/edit.js +6 -3
  35. package/build/gallery/v1/edit.js.map +1 -1
  36. package/build/group/edit.js +105 -48
  37. package/build/group/edit.js.map +1 -1
  38. package/build/group/index.js +3 -0
  39. package/build/group/index.js.map +1 -1
  40. package/build/group/placeholder.js +168 -0
  41. package/build/group/placeholder.js.map +1 -0
  42. package/build/group/variations.js +3 -3
  43. package/build/group/variations.js.map +1 -1
  44. package/build/image/edit.native.js +1 -1
  45. package/build/image/edit.native.js.map +1 -1
  46. package/build/image/image.js +6 -9
  47. package/build/image/image.js.map +1 -1
  48. package/build/latest-comments/edit.js +2 -1
  49. package/build/latest-comments/edit.js.map +1 -1
  50. package/build/latest-comments/index.js +5 -1
  51. package/build/latest-comments/index.js.map +1 -1
  52. package/build/latest-posts/deprecated.js +13 -0
  53. package/build/latest-posts/deprecated.js.map +1 -1
  54. package/build/latest-posts/edit.js +1 -1
  55. package/build/latest-posts/edit.js.map +1 -1
  56. package/build/latest-posts/index.js +13 -0
  57. package/build/latest-posts/index.js.map +1 -1
  58. package/build/list/utils.js +4 -8
  59. package/build/list/utils.js.map +1 -1
  60. package/build/list-item/edit.js +2 -1
  61. package/build/list-item/edit.js.map +1 -1
  62. package/build/list-item/hooks/use-outdent-list-item.js +5 -7
  63. package/build/list-item/hooks/use-outdent-list-item.js.map +1 -1
  64. package/build/navigation/edit/index.js +94 -103
  65. package/build/navigation/edit/index.js.map +1 -1
  66. package/build/navigation/edit/manage-menus-button.js +36 -0
  67. package/build/navigation/edit/manage-menus-button.js.map +1 -0
  68. package/build/navigation/edit/navigation-menu-selector.js +12 -5
  69. package/build/navigation/edit/navigation-menu-selector.js.map +1 -1
  70. package/build/navigation/edit/responsive-wrapper.js +2 -6
  71. package/build/navigation/edit/responsive-wrapper.js.map +1 -1
  72. package/build/navigation/edit/unsaved-inner-blocks.js +5 -17
  73. package/build/navigation/edit/unsaved-inner-blocks.js.map +1 -1
  74. package/build/navigation-link/edit.js +14 -3
  75. package/build/navigation-link/edit.js.map +1 -1
  76. package/build/navigation-submenu/edit.js +4 -4
  77. package/build/navigation-submenu/edit.js.map +1 -1
  78. package/build/page-list/edit.js +29 -10
  79. package/build/page-list/edit.js.map +1 -1
  80. package/build/post-author/edit.js +35 -20
  81. package/build/post-author/edit.js.map +1 -1
  82. package/build/post-comments-count/index.js +4 -0
  83. package/build/post-comments-count/index.js.map +1 -1
  84. package/build/post-comments-form/index.js +4 -0
  85. package/build/post-comments-form/index.js.map +1 -1
  86. package/build/post-comments-link/index.js +4 -0
  87. package/build/post-comments-link/index.js.map +1 -1
  88. package/build/post-content/edit.js +14 -6
  89. package/build/post-content/edit.js.map +1 -1
  90. package/build/post-content/index.js +3 -0
  91. package/build/post-content/index.js.map +1 -1
  92. package/build/pullquote/deprecated.js +6 -6
  93. package/build/pullquote/deprecated.js.map +1 -1
  94. package/build/search/edit.js +1 -3
  95. package/build/search/edit.js.map +1 -1
  96. package/build/site-logo/edit.js +2 -2
  97. package/build/site-logo/edit.js.map +1 -1
  98. package/build/site-tagline/edit.js +21 -9
  99. package/build/site-tagline/edit.js.map +1 -1
  100. package/build/site-title/edit/index.js +20 -8
  101. package/build/site-title/edit/index.js.map +1 -1
  102. package/build/social-link/edit.js +11 -2
  103. package/build/social-link/edit.js.map +1 -1
  104. package/build/social-link/index.js +3 -0
  105. package/build/social-link/index.js.map +1 -1
  106. package/build/spacer/controls.js +3 -7
  107. package/build/spacer/controls.js.map +1 -1
  108. package/build/table/deprecated.js +282 -27
  109. package/build/table/deprecated.js.map +1 -1
  110. package/build/table/state.js +1 -1
  111. package/build/table/state.js.map +1 -1
  112. package/build/template-part/variations.js +5 -0
  113. package/build/template-part/variations.js.map +1 -1
  114. package/build/utils/clean-empty-object.js +5 -4
  115. package/build/utils/clean-empty-object.js.map +1 -1
  116. package/build/video/deprecated.js +159 -0
  117. package/build/video/deprecated.js.map +1 -0
  118. package/build/video/edit.js +41 -5
  119. package/build/video/edit.js.map +1 -1
  120. package/build/video/index.js +3 -0
  121. package/build/video/index.js.map +1 -1
  122. package/build/video/tracks-editor.js +3 -28
  123. package/build/video/tracks-editor.js.map +1 -1
  124. package/build-module/audio/edit.js +46 -7
  125. package/build-module/audio/edit.js.map +1 -1
  126. package/build-module/button/deprecated.js +16 -2
  127. package/build-module/button/deprecated.js.map +1 -1
  128. package/build-module/button/edit.js +16 -10
  129. package/build-module/button/edit.js.map +1 -1
  130. package/build-module/button/index.js +4 -1
  131. package/build-module/button/index.js.map +1 -1
  132. package/build-module/button/save.js +2 -0
  133. package/build-module/button/save.js.map +1 -1
  134. package/build-module/buttons/edit.native.js +1 -1
  135. package/build-module/buttons/edit.native.js.map +1 -1
  136. package/build-module/columns/transforms.js +5 -0
  137. package/build-module/columns/transforms.js.map +1 -1
  138. package/build-module/comment-template/index.js +6 -2
  139. package/build-module/comment-template/index.js.map +1 -1
  140. package/build-module/cover/edit/index.js +3 -1
  141. package/build-module/cover/edit/index.js.map +1 -1
  142. package/build-module/cover/edit/inspector-controls.js +4 -8
  143. package/build-module/cover/edit/inspector-controls.js.map +1 -1
  144. package/build-module/embed/deprecated.js +44 -5
  145. package/build-module/embed/deprecated.js.map +1 -1
  146. package/build-module/file/deprecated.js +108 -4
  147. package/build-module/file/deprecated.js.map +1 -1
  148. package/build-module/file/transforms.js +3 -8
  149. package/build-module/file/transforms.js.map +1 -1
  150. package/build-module/gallery/deprecated.js +147 -25
  151. package/build-module/gallery/deprecated.js.map +1 -1
  152. package/build-module/gallery/gallery.js +3 -2
  153. package/build-module/gallery/gallery.js.map +1 -1
  154. package/build-module/gallery/use-image-sizes.js +3 -2
  155. package/build-module/gallery/use-image-sizes.js.map +1 -1
  156. package/build-module/gallery/v1/edit.js +7 -4
  157. package/build-module/gallery/v1/edit.js.map +1 -1
  158. package/build-module/group/edit.js +101 -48
  159. package/build-module/group/edit.js.map +1 -1
  160. package/build-module/group/index.js +3 -0
  161. package/build-module/group/index.js.map +1 -1
  162. package/build-module/group/placeholder.js +154 -0
  163. package/build-module/group/placeholder.js.map +1 -0
  164. package/build-module/group/variations.js +3 -3
  165. package/build-module/group/variations.js.map +1 -1
  166. package/build-module/image/edit.native.js +1 -1
  167. package/build-module/image/edit.native.js.map +1 -1
  168. package/build-module/image/image.js +8 -11
  169. package/build-module/image/image.js.map +1 -1
  170. package/build-module/latest-comments/edit.js +2 -1
  171. package/build-module/latest-comments/edit.js.map +1 -1
  172. package/build-module/latest-comments/index.js +5 -1
  173. package/build-module/latest-comments/index.js.map +1 -1
  174. package/build-module/latest-posts/deprecated.js +13 -0
  175. package/build-module/latest-posts/deprecated.js.map +1 -1
  176. package/build-module/latest-posts/edit.js +2 -2
  177. package/build-module/latest-posts/edit.js.map +1 -1
  178. package/build-module/latest-posts/index.js +13 -0
  179. package/build-module/latest-posts/index.js.map +1 -1
  180. package/build-module/list/utils.js +5 -9
  181. package/build-module/list/utils.js.map +1 -1
  182. package/build-module/list-item/edit.js +2 -1
  183. package/build-module/list-item/edit.js.map +1 -1
  184. package/build-module/list-item/hooks/use-outdent-list-item.js +5 -6
  185. package/build-module/list-item/hooks/use-outdent-list-item.js.map +1 -1
  186. package/build-module/navigation/edit/index.js +96 -105
  187. package/build-module/navigation/edit/index.js.map +1 -1
  188. package/build-module/navigation/edit/manage-menus-button.js +26 -0
  189. package/build-module/navigation/edit/manage-menus-button.js.map +1 -0
  190. package/build-module/navigation/edit/navigation-menu-selector.js +13 -6
  191. package/build-module/navigation/edit/navigation-menu-selector.js.map +1 -1
  192. package/build-module/navigation/edit/responsive-wrapper.js +2 -6
  193. package/build-module/navigation/edit/responsive-wrapper.js.map +1 -1
  194. package/build-module/navigation/edit/unsaved-inner-blocks.js +7 -18
  195. package/build-module/navigation/edit/unsaved-inner-blocks.js.map +1 -1
  196. package/build-module/navigation-link/edit.js +14 -4
  197. package/build-module/navigation-link/edit.js.map +1 -1
  198. package/build-module/navigation-submenu/edit.js +4 -4
  199. package/build-module/navigation-submenu/edit.js.map +1 -1
  200. package/build-module/page-list/edit.js +29 -10
  201. package/build-module/page-list/edit.js.map +1 -1
  202. package/build-module/post-author/edit.js +35 -21
  203. package/build-module/post-author/edit.js.map +1 -1
  204. package/build-module/post-comments-count/index.js +4 -0
  205. package/build-module/post-comments-count/index.js.map +1 -1
  206. package/build-module/post-comments-form/index.js +4 -0
  207. package/build-module/post-comments-form/index.js.map +1 -1
  208. package/build-module/post-comments-link/index.js +4 -0
  209. package/build-module/post-comments-link/index.js.map +1 -1
  210. package/build-module/post-content/edit.js +14 -6
  211. package/build-module/post-content/edit.js.map +1 -1
  212. package/build-module/post-content/index.js +3 -0
  213. package/build-module/post-content/index.js.map +1 -1
  214. package/build-module/pullquote/deprecated.js +7 -7
  215. package/build-module/pullquote/deprecated.js.map +1 -1
  216. package/build-module/search/edit.js +1 -3
  217. package/build-module/search/edit.js.map +1 -1
  218. package/build-module/site-logo/edit.js +3 -3
  219. package/build-module/site-logo/edit.js.map +1 -1
  220. package/build-module/site-tagline/edit.js +23 -11
  221. package/build-module/site-tagline/edit.js.map +1 -1
  222. package/build-module/site-title/edit/index.js +22 -10
  223. package/build-module/site-title/edit/index.js.map +1 -1
  224. package/build-module/social-link/edit.js +11 -2
  225. package/build-module/social-link/edit.js.map +1 -1
  226. package/build-module/social-link/index.js +3 -0
  227. package/build-module/social-link/index.js.map +1 -1
  228. package/build-module/spacer/controls.js +4 -8
  229. package/build-module/spacer/controls.js.map +1 -1
  230. package/build-module/table/deprecated.js +282 -27
  231. package/build-module/table/deprecated.js.map +1 -1
  232. package/build-module/table/state.js +1 -1
  233. package/build-module/table/state.js.map +1 -1
  234. package/build-module/template-part/variations.js +5 -0
  235. package/build-module/template-part/variations.js.map +1 -1
  236. package/build-module/utils/clean-empty-object.js +5 -5
  237. package/build-module/utils/clean-empty-object.js.map +1 -1
  238. package/build-module/video/deprecated.js +147 -0
  239. package/build-module/video/deprecated.js.map +1 -0
  240. package/build-module/video/edit.js +45 -9
  241. package/build-module/video/edit.js.map +1 -1
  242. package/build-module/video/index.js +2 -0
  243. package/build-module/video/index.js.map +1 -1
  244. package/build-module/video/tracks-editor.js +4 -29
  245. package/build-module/video/tracks-editor.js.map +1 -1
  246. package/build-style/button/style-rtl.css +1 -0
  247. package/build-style/button/style.css +1 -0
  248. package/build-style/comment-template/style-rtl.css +1 -0
  249. package/build-style/comment-template/style.css +1 -0
  250. package/build-style/editor-rtl.css +80 -5
  251. package/build-style/editor.css +80 -5
  252. package/build-style/group/editor-rtl.css +44 -0
  253. package/build-style/group/editor.css +44 -0
  254. package/build-style/latest-comments/style-rtl.css +1 -0
  255. package/build-style/latest-comments/style.css +1 -0
  256. package/build-style/latest-posts/style-rtl.css +3 -0
  257. package/build-style/latest-posts/style.css +3 -0
  258. package/build-style/navigation/editor-rtl.css +27 -4
  259. package/build-style/navigation/editor.css +27 -4
  260. package/build-style/navigation/style-rtl.css +13 -1
  261. package/build-style/navigation/style.css +13 -1
  262. package/build-style/navigation-link/editor-rtl.css +8 -1
  263. package/build-style/navigation-link/editor.css +8 -1
  264. package/build-style/post-comments-form/style-rtl.css +3 -0
  265. package/build-style/post-comments-form/style.css +3 -0
  266. package/build-style/query/editor-rtl.css +1 -1
  267. package/build-style/query/editor.css +1 -1
  268. package/build-style/query-pagination/style-rtl.css +1 -1
  269. package/build-style/query-pagination/style.css +1 -1
  270. package/build-style/style-rtl.css +28 -2
  271. package/build-style/style.css +28 -2
  272. package/build-style/table/editor-rtl.css +1 -0
  273. package/build-style/table/editor.css +1 -0
  274. package/build-style/table/style-rtl.css +5 -0
  275. package/build-style/table/style.css +5 -0
  276. package/build-style/table/theme-rtl.css +1 -3
  277. package/build-style/table/theme.css +1 -3
  278. package/build-style/theme-rtl.css +1 -3
  279. package/build-style/theme.css +1 -3
  280. package/package.json +29 -28
  281. package/src/audio/edit.js +79 -24
  282. package/src/avatar/index.php +1 -1
  283. package/src/block/test/edit.native.js +8 -8
  284. package/src/button/block.json +4 -1
  285. package/src/button/deprecated.js +18 -2
  286. package/src/button/edit.js +12 -10
  287. package/src/button/save.js +12 -2
  288. package/src/button/style.scss +2 -0
  289. package/src/buttons/edit.native.js +1 -1
  290. package/src/buttons/test/edit.native.js +19 -19
  291. package/src/columns/test/edit.native.js +32 -32
  292. package/src/columns/transforms.js +8 -0
  293. package/src/comment-template/block.json +6 -2
  294. package/src/comment-template/style.scss +2 -0
  295. package/src/cover/edit/index.js +3 -1
  296. package/src/cover/edit/inspector-controls.js +11 -13
  297. package/src/cover/test/edit.native.js +26 -26
  298. package/src/embed/deprecated.js +53 -26
  299. package/src/embed/test/index.native.js +43 -43
  300. package/src/file/deprecated.js +130 -2
  301. package/src/file/transforms.js +3 -8
  302. package/src/gallery/deprecated.js +129 -4
  303. package/src/gallery/gallery.js +2 -0
  304. package/src/gallery/index.php +19 -10
  305. package/src/gallery/test/index.native.js +11 -11
  306. package/src/gallery/use-image-sizes.js +3 -2
  307. package/src/gallery/v1/edit.js +21 -25
  308. package/src/group/block.json +3 -0
  309. package/src/group/edit.js +105 -46
  310. package/src/group/editor.scss +48 -0
  311. package/src/group/placeholder.js +187 -0
  312. package/src/group/test/edit.native.js +3 -3
  313. package/src/group/test/placeholder.js +78 -0
  314. package/src/group/variations.js +3 -3
  315. package/src/image/edit.native.js +1 -1
  316. package/src/image/image.js +22 -10
  317. package/src/image/test/edit.native.js +17 -17
  318. package/src/latest-comments/block.json +5 -1
  319. package/src/latest-comments/edit.js +1 -0
  320. package/src/latest-comments/style.scss +3 -0
  321. package/src/latest-posts/block.json +13 -0
  322. package/src/latest-posts/edit.js +2 -2
  323. package/src/latest-posts/style.scss +3 -0
  324. package/src/list/test/edit.native.js +36 -36
  325. package/src/list/utils.js +3 -11
  326. package/src/list-item/edit.js +1 -0
  327. package/src/list-item/hooks/use-outdent-list-item.js +3 -6
  328. package/src/missing/test/edit-integration.native.js +5 -5
  329. package/src/navigation/edit/index.js +186 -161
  330. package/src/navigation/edit/manage-menus-button.js +21 -0
  331. package/src/navigation/edit/navigation-menu-selector.js +20 -5
  332. package/src/navigation/edit/responsive-wrapper.js +2 -10
  333. package/src/navigation/edit/unsaved-inner-blocks.js +5 -22
  334. package/src/navigation/editor.scss +29 -4
  335. package/src/navigation/style.scss +19 -1
  336. package/src/navigation-link/edit.js +13 -4
  337. package/src/navigation-link/editor.scss +8 -0
  338. package/src/navigation-submenu/edit.js +7 -5
  339. package/src/page-list/edit.js +36 -22
  340. package/src/post-author/edit.js +44 -20
  341. package/src/post-comments-count/block.json +4 -0
  342. package/src/post-comments-form/block.json +4 -0
  343. package/src/post-comments-form/style.scss +3 -0
  344. package/src/post-comments-link/block.json +4 -0
  345. package/src/post-content/block.json +3 -0
  346. package/src/post-content/edit.js +8 -4
  347. package/src/pullquote/deprecated.js +7 -7
  348. package/src/query/editor.scss +1 -1
  349. package/src/query-pagination/style.scss +1 -1
  350. package/src/read-more/index.php +9 -2
  351. package/src/search/edit.js +1 -1
  352. package/src/shortcode/test/edit.native.js +5 -5
  353. package/src/site-logo/edit.js +3 -3
  354. package/src/site-tagline/edit.js +25 -18
  355. package/src/site-title/edit/index.js +26 -12
  356. package/src/social-link/block.json +3 -0
  357. package/src/social-link/edit.js +8 -1
  358. package/src/social-link/index.php +11 -7
  359. package/src/social-link/test/index.native.js +10 -10
  360. package/src/social-links/test/edit.native.js +4 -4
  361. package/src/spacer/controls.js +10 -12
  362. package/src/spacer/test/index.native.js +17 -17
  363. package/src/table/deprecated.js +587 -348
  364. package/src/table/editor.scss +1 -0
  365. package/src/table/state.js +1 -1
  366. package/src/table/style.scss +7 -0
  367. package/src/table/theme.scss +1 -3
  368. package/src/template-part/index.php +5 -0
  369. package/src/template-part/variations.js +4 -0
  370. package/src/utils/clean-empty-object.js +5 -6
  371. package/src/video/deprecated.js +57 -0
  372. package/src/video/edit.js +71 -23
  373. package/src/video/index.js +2 -0
  374. package/src/video/tracks-editor.js +12 -28
@@ -26,6 +26,7 @@ export const Gallery = ( props ) => {
26
26
  mediaPlaceholder,
27
27
  insertBlocksAfter,
28
28
  blockProps,
29
+ __unstableLayoutClassNames: layoutClassNames,
29
30
  } = props;
30
31
 
31
32
  const { align, columns, caption, imageCrop } = attributes;
@@ -42,6 +43,7 @@ export const Gallery = ( props ) => {
42
43
  { ...innerBlocksProps }
43
44
  className={ classnames(
44
45
  blockProps.className,
46
+ layoutClassNames,
45
47
  'blocks-gallery-grid',
46
48
  {
47
49
  [ `align${ align }` ]: align,
@@ -76,13 +76,10 @@ function block_core_gallery_render( $attributes, $content ) {
76
76
  }
77
77
  }
78
78
 
79
- $class = wp_unique_id( 'wp-block-gallery-' );
80
- $content = preg_replace(
81
- '/' . preg_quote( 'class="', '/' ) . '/',
82
- 'class="' . $class . ' ',
83
- $content,
84
- 1
85
- );
79
+ $unique_gallery_classname = wp_unique_id( 'wp-block-gallery-' );
80
+ $processed_content = new WP_HTML_Tag_Processor( $content );
81
+ $processed_content->next_tag();
82
+ $processed_content->add_class( $unique_gallery_classname );
86
83
 
87
84
  // --gallery-block--gutter-size is deprecated. --wp--style--gallery-gap-default should be used by themes that want to set a default
88
85
  // gap on the gallery.
@@ -102,10 +99,22 @@ function block_core_gallery_render( $attributes, $content ) {
102
99
  }
103
100
 
104
101
  // Set the CSS variable to the column value, and the `gap` property to the combined gap value.
105
- $style = '.wp-block-gallery.' . $class . '{ --wp--style--unstable-gallery-gap: ' . $gap_column . '; gap: ' . $gap_value . '}';
102
+ $gallery_styles = array();
103
+ $gallery_styles[] = array(
104
+ 'selector' => ".wp-block-gallery.{$unique_gallery_classname}",
105
+ 'declarations' => array(
106
+ '--wp--style--unstable-gallery-gap' => $gap_column,
107
+ 'gap' => $gap_value,
108
+ ),
109
+ );
106
110
 
107
- wp_enqueue_block_support_styles( $style, 11 );
108
- return $content;
111
+ gutenberg_style_engine_get_stylesheet_from_css_rules(
112
+ $gallery_styles,
113
+ array(
114
+ 'context' => 'block-supports',
115
+ )
116
+ );
117
+ return (string) $processed_content;
109
118
  }
110
119
  /**
111
120
  * Registers the `core/gallery` block on server.
@@ -100,7 +100,7 @@ describe( 'Gallery block', () => {
100
100
  // is addressed.
101
101
  it.skip( 'displays media options picker when selecting the block', async () => {
102
102
  // Initialize with an empty gallery
103
- const { getByA11yLabel, getByText, getByTestId } =
103
+ const { getByLabelText, getByText, getByTestId } =
104
104
  await initializeEditor( {
105
105
  initialHtml: generateGalleryBlock( 0 ),
106
106
  } );
@@ -121,7 +121,7 @@ describe( 'Gallery block', () => {
121
121
 
122
122
  // Observe that the block is selected, this is done by checking if the block settings
123
123
  // button is visible
124
- const blockActionsButton = getByA11yLabel( /Open Block Actions Menu/ );
124
+ const blockActionsButton = getByLabelText( /Open Block Actions Menu/ );
125
125
  expect( blockActionsButton ).toBeVisible();
126
126
  } );
127
127
 
@@ -160,18 +160,18 @@ describe( 'Gallery block', () => {
160
160
  // Reference: https://github.com/wordpress-mobile/test-cases/blob/trunk/test-cases/gutenberg/gallery.md#tc003
161
161
  it( 'sets caption to gallery', async () => {
162
162
  // Initialize with a gallery that contains one item
163
- const { getByA11yLabel } = await initializeWithGalleryBlock( {
163
+ const { getByLabelText } = await initializeWithGalleryBlock( {
164
164
  numberOfItems: 1,
165
165
  media,
166
166
  } );
167
167
 
168
168
  // Check gallery item caption is not visible
169
- const galleryItemCaption = getByA11yLabel( /Image caption. Empty/ );
169
+ const galleryItemCaption = getByLabelText( /Image caption. Empty/ );
170
170
  expect( galleryItemCaption ).not.toBeVisible();
171
171
 
172
172
  // Set gallery caption
173
173
  const captionField = within(
174
- getByA11yLabel( /Gallery caption. Empty/ )
174
+ getByLabelText( /Gallery caption. Empty/ )
175
175
  ).getByPlaceholderText( 'Add caption' );
176
176
  changeTextOfRichText(
177
177
  captionField,
@@ -456,7 +456,7 @@ describe( 'Gallery block', () => {
456
456
  fireEvent.press( galleryItem3 );
457
457
  await act( () =>
458
458
  fireEvent.press(
459
- within( galleryItem3 ).getByA11yLabel(
459
+ within( galleryItem3 ).getByLabelText(
460
460
  /Move block left from position 3 to position 2/
461
461
  )
462
462
  )
@@ -465,7 +465,7 @@ describe( 'Gallery block', () => {
465
465
  fireEvent.press( galleryItem1 );
466
466
  await act( () =>
467
467
  fireEvent.press(
468
- within( galleryItem1 ).getByA11yLabel(
468
+ within( galleryItem1 ).getByLabelText(
469
469
  /Move block right from position 1 to position 2/
470
470
  )
471
471
  )
@@ -563,14 +563,14 @@ describe( 'Gallery block', () => {
563
563
  numberOfItems: 3,
564
564
  media,
565
565
  } );
566
- const { getByA11yLabel } = screen;
566
+ const { getByLabelText } = screen;
567
567
 
568
568
  await openBlockSettings( screen );
569
569
 
570
570
  // Can't increment due to maximum value
571
571
  // NOTE: Default columns value is 3
572
572
  fireEvent(
573
- getByA11yLabel( /Columns\. Value is 3/ ),
573
+ getByLabelText( /Columns\. Value is 3/ ),
574
574
  'accessibilityAction',
575
575
  {
576
576
  nativeEvent: { actionName: 'increment' },
@@ -585,13 +585,13 @@ describe( 'Gallery block', () => {
585
585
  numberOfItems: 3,
586
586
  media,
587
587
  } );
588
- const { getByA11yLabel } = screen;
588
+ const { getByLabelText } = screen;
589
589
 
590
590
  await openBlockSettings( screen );
591
591
 
592
592
  // Decrement columns
593
593
  fireEvent(
594
- getByA11yLabel( /Columns\. Value is 3/ ),
594
+ getByLabelText( /Columns\. Value is 3/ ),
595
595
  'accessibilityAction',
596
596
  {
597
597
  nativeEvent: { actionName: 'decrement' },
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import { get, some } from 'lodash';
4
+ import { get } from 'lodash';
5
5
 
6
6
  /**
7
7
  * WordPress dependencies
@@ -57,9 +57,10 @@ export default function useImageSizes( images, isSelected, getSettings ) {
57
57
  };
58
58
  }, {} );
59
59
  }
60
+ const resizedImageSizes = Object.values( resizedImages );
60
61
  return imageSizes
61
62
  .filter( ( { slug } ) =>
62
- some( resizedImages, ( sizes ) => sizes[ slug ] )
63
+ resizedImageSizes.some( ( sizes ) => sizes[ slug ] )
63
64
  )
64
65
  .map( ( { name, slug } ) => ( { value: slug, label: name } ) );
65
66
  }
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import { filter, find, get, isEmpty, map, reduce, some } from 'lodash';
4
+ import { filter, find, get, isEmpty, map } from 'lodash';
5
5
 
6
6
  /**
7
7
  * WordPress dependencies
@@ -98,34 +98,29 @@ function GalleryEdit( props ) {
98
98
 
99
99
  const resizedImages = useMemo( () => {
100
100
  if ( isSelected ) {
101
- return reduce(
102
- attributes.ids,
101
+ return ( attributes.ids ?? [] ).reduce(
103
102
  ( currentResizedImages, id ) => {
104
103
  if ( ! id ) {
105
104
  return currentResizedImages;
106
105
  }
107
106
  const image = getMedia( id );
108
- const sizes = reduce(
109
- imageSizes,
110
- ( currentSizes, size ) => {
111
- const defaultUrl = get( image, [
112
- 'sizes',
113
- size.slug,
114
- 'url',
115
- ] );
116
- const mediaDetailsUrl = get( image, [
117
- 'media_details',
118
- 'sizes',
119
- size.slug,
120
- 'source_url',
121
- ] );
122
- return {
123
- ...currentSizes,
124
- [ size.slug ]: defaultUrl || mediaDetailsUrl,
125
- };
126
- },
127
- {}
128
- );
107
+ const sizes = imageSizes.reduce( ( currentSizes, size ) => {
108
+ const defaultUrl = get( image, [
109
+ 'sizes',
110
+ size.slug,
111
+ 'url',
112
+ ] );
113
+ const mediaDetailsUrl = get( image, [
114
+ 'media_details',
115
+ 'sizes',
116
+ size.slug,
117
+ 'source_url',
118
+ ] );
119
+ return {
120
+ ...currentSizes,
121
+ [ size.slug ]: defaultUrl || mediaDetailsUrl,
122
+ };
123
+ }, {} );
129
124
  return {
130
125
  ...currentResizedImages,
131
126
  [ parseInt( id, 10 ) ]: sizes,
@@ -302,9 +297,10 @@ function GalleryEdit( props ) {
302
297
  }
303
298
 
304
299
  function getImagesSizeOptions() {
300
+ const resizedImageSizes = Object.values( resizedImages );
305
301
  return map(
306
302
  filter( imageSizes, ( { slug } ) =>
307
- some( resizedImages, ( sizes ) => sizes[ slug ] )
303
+ resizedImageSizes.some( ( sizes ) => sizes[ slug ] )
308
304
  ),
309
305
  ( { name, slug } ) => ( { value: slug, label: name } )
310
306
  );
@@ -41,6 +41,9 @@
41
41
  "blockGap": true
42
42
  }
43
43
  },
44
+ "dimensions": {
45
+ "minHeight": true
46
+ },
44
47
  "__experimentalBorder": {
45
48
  "color": true,
46
49
  "radius": true,
package/src/group/edit.js CHANGED
@@ -1,8 +1,7 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { useSelect } from '@wordpress/data';
5
-
4
+ import { useDispatch, useSelect } from '@wordpress/data';
6
5
  import {
7
6
  InnerBlocks,
8
7
  useBlockProps,
@@ -13,29 +12,71 @@ import {
13
12
  } from '@wordpress/block-editor';
14
13
  import { SelectControl } from '@wordpress/components';
15
14
  import { __ } from '@wordpress/i18n';
15
+ import { useCallback } from '@wordpress/element';
16
16
 
17
- const htmlElementMessages = {
18
- header: __(
19
- 'The <header> element should represent introductory content, typically a group of introductory or navigational aids.'
20
- ),
21
- main: __(
22
- 'The <main> element should be used for the primary content of your document only. '
23
- ),
24
- section: __(
25
- "The <section> element should represent a standalone portion of the document that can't be better represented by another element."
26
- ),
27
- article: __(
28
- 'The <article> element should represent a self contained, syndicatable portion of the document.'
29
- ),
30
- aside: __(
31
- "The <aside> element should represent a portion of a document whose content is only indirectly related to the document's main content."
32
- ),
33
- footer: __(
34
- 'The <footer> element should represent a footer for its nearest sectioning element (e.g.: <section>, <article>, <main> etc.).'
35
- ),
36
- };
17
+ /**
18
+ * Internal dependencies
19
+ */
20
+ import GroupPlaceHolder, { useShouldShowPlaceHolder } from './placeholder';
21
+
22
+ /**
23
+ * Render inspector controls for the Group block.
24
+ *
25
+ * @param {Object} props Component props.
26
+ * @param {string} props.tagName The HTML tag name.
27
+ * @param {Function} props.onSelectTagName onChange function for the SelectControl.
28
+ *
29
+ * @return {JSX.Element} The control group.
30
+ */
31
+ function GroupEditControls( { tagName, onSelectTagName } ) {
32
+ const htmlElementMessages = {
33
+ header: __(
34
+ 'The <header> element should represent introductory content, typically a group of introductory or navigational aids.'
35
+ ),
36
+ main: __(
37
+ 'The <main> element should be used for the primary content of your document only. '
38
+ ),
39
+ section: __(
40
+ "The <section> element should represent a standalone portion of the document that can't be better represented by another element."
41
+ ),
42
+ article: __(
43
+ 'The <article> element should represent a self-contained, syndicatable portion of the document.'
44
+ ),
45
+ aside: __(
46
+ "The <aside> element should represent a portion of a document whose content is only indirectly related to the document's main content."
47
+ ),
48
+ footer: __(
49
+ 'The <footer> element should represent a footer for its nearest sectioning element (e.g.: <section>, <article>, <main> etc.).'
50
+ ),
51
+ };
52
+ return (
53
+ <InspectorControls __experimentalGroup="advanced">
54
+ <SelectControl
55
+ label={ __( 'HTML element' ) }
56
+ options={ [
57
+ { label: __( 'Default (<div>)' ), value: 'div' },
58
+ { label: '<header>', value: 'header' },
59
+ { label: '<main>', value: 'main' },
60
+ { label: '<section>', value: 'section' },
61
+ { label: '<article>', value: 'article' },
62
+ { label: '<aside>', value: 'aside' },
63
+ { label: '<footer>', value: 'footer' },
64
+ ] }
65
+ value={ tagName }
66
+ onChange={ onSelectTagName }
67
+ help={ htmlElementMessages[ tagName ] }
68
+ />
69
+ </InspectorControls>
70
+ );
71
+ }
37
72
 
38
- function GroupEdit( { attributes, setAttributes, clientId } ) {
73
+ function GroupEdit( {
74
+ attributes,
75
+ name,
76
+ setAttributes,
77
+ clientId,
78
+ __unstableLayoutClassNames: layoutClassNames,
79
+ } ) {
39
80
  const { hasInnerBlocks, themeSupportsLayout } = useSelect(
40
81
  ( select ) => {
41
82
  const { getBlock, getSettings } = select( blockEditorStore );
@@ -47,16 +88,26 @@ function GroupEdit( { attributes, setAttributes, clientId } ) {
47
88
  },
48
89
  [ clientId ]
49
90
  );
50
- const defaultLayout = useSetting( 'layout' ) || {};
91
+
51
92
  const { tagName: TagName = 'div', templateLock, layout = {} } = attributes;
93
+
94
+ // Layout settings.
95
+ const defaultLayout = useSetting( 'layout' ) || {};
52
96
  const usedLayout = ! layout?.type
53
97
  ? { ...defaultLayout, ...layout, type: 'default' }
54
98
  : { ...defaultLayout, ...layout };
55
99
  const { type = 'default' } = usedLayout;
56
100
  const layoutSupportEnabled = themeSupportsLayout || type === 'flex';
57
101
 
58
- const blockProps = useBlockProps();
59
-
102
+ // Hooks.
103
+ const blockProps = useBlockProps( {
104
+ className: ! layoutSupportEnabled ? layoutClassNames : null,
105
+ } );
106
+ const [ showPlaceholder, setShowPlaceholder ] = useShouldShowPlaceHolder( {
107
+ attributes,
108
+ usedLayoutType: usedLayout?.type,
109
+ hasInnerBlocks,
110
+ } );
60
111
  const innerBlocksProps = useInnerBlocksProps(
61
112
  layoutSupportEnabled
62
113
  ? blockProps
@@ -67,34 +118,42 @@ function GroupEdit( { attributes, setAttributes, clientId } ) {
67
118
  ? undefined
68
119
  : InnerBlocks.ButtonBlockAppender,
69
120
  __experimentalLayout: layoutSupportEnabled ? usedLayout : undefined,
121
+ __unstableDisableLayoutClassNames: ! layoutSupportEnabled,
70
122
  }
71
123
  );
72
124
 
125
+ const { selectBlock } = useDispatch( blockEditorStore );
126
+ const updateSelection = useCallback(
127
+ ( newClientId ) => selectBlock( newClientId, -1 ),
128
+ [ selectBlock ]
129
+ );
130
+ const selectVariation = ( nextVariation ) => {
131
+ setAttributes( nextVariation.attributes );
132
+ updateSelection( clientId );
133
+ setShowPlaceholder( false );
134
+ };
135
+
73
136
  return (
74
137
  <>
75
- <InspectorControls __experimentalGroup="advanced">
76
- <SelectControl
77
- label={ __( 'HTML element' ) }
78
- options={ [
79
- { label: __( 'Default (<div>)' ), value: 'div' },
80
- { label: '<header>', value: 'header' },
81
- { label: '<main>', value: 'main' },
82
- { label: '<section>', value: 'section' },
83
- { label: '<article>', value: 'article' },
84
- { label: '<aside>', value: 'aside' },
85
- { label: '<footer>', value: 'footer' },
86
- ] }
87
- value={ TagName }
88
- onChange={ ( value ) =>
89
- setAttributes( { tagName: value } )
90
- }
91
- help={ htmlElementMessages[ TagName ] }
138
+ <GroupEditControls
139
+ tagName={ TagName }
140
+ onSelectTagName={ ( value ) =>
141
+ setAttributes( { tagName: value } )
142
+ }
143
+ />
144
+ { showPlaceholder && (
145
+ <GroupPlaceHolder
146
+ clientId={ clientId }
147
+ name={ name }
148
+ onSelect={ selectVariation }
92
149
  />
93
- </InspectorControls>
94
- { layoutSupportEnabled && <TagName { ...innerBlocksProps } /> }
150
+ ) }
151
+ { layoutSupportEnabled && ! showPlaceholder && (
152
+ <TagName { ...innerBlocksProps } />
153
+ ) }
95
154
  { /* Ideally this is not needed but it's there for backward compatibility reason
96
155
  to keep this div for themes that might rely on its presence */ }
97
- { ! layoutSupportEnabled && (
156
+ { ! layoutSupportEnabled && ! showPlaceholder && (
98
157
  <TagName { ...blockProps }>
99
158
  <div { ...innerBlocksProps } />
100
159
  </TagName>
@@ -52,3 +52,51 @@
52
52
  pointer-events: all;
53
53
  }
54
54
  }
55
+
56
+ .wp-block-group__placeholder {
57
+ .wp-block-group-placeholder__variations {
58
+ list-style: none;
59
+ display: flex;
60
+ justify-content: center;
61
+ flex-direction: row;
62
+ flex-wrap: wrap;
63
+ width: 100%;
64
+ padding: 0;
65
+ margin: 0;
66
+ }
67
+ .components-placeholder__instructions {
68
+ text-align: center;
69
+ margin-bottom: 18px;
70
+ }
71
+ .wp-block-group-placeholder__variations svg {
72
+ fill: $gray-400 !important;
73
+ }
74
+ .wp-block-group-placeholder__variations svg:hover {
75
+ fill: var(--wp-admin-theme-color) !important;
76
+ }
77
+ .wp-block-group-placeholder__variations > li {
78
+ margin: 0 $grid-unit-15 $grid-unit-15 $grid-unit-15;
79
+ width: auto;
80
+ display: flex;
81
+ flex-direction: column;
82
+ align-items: center;
83
+ }
84
+ .wp-block-group-placeholder__variations li > .wp-block-group-placeholder__variation-button {
85
+ width: 44px;
86
+ height: 32px;
87
+ padding: 0;
88
+ &:hover {
89
+ box-shadow: none;
90
+ }
91
+ }
92
+ .components-placeholder {
93
+ min-height: auto;
94
+ padding: $grid-unit-30;
95
+ }
96
+ .is-small,
97
+ .is-medium {
98
+ .wp-block-group-placeholder__variations > li {
99
+ margin: $grid-unit-15;
100
+ }
101
+ }
102
+ }
@@ -0,0 +1,187 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { useSelect } from '@wordpress/data';
5
+ import { useBlockProps } from '@wordpress/block-editor';
6
+ import { __ } from '@wordpress/i18n';
7
+ import { store as blocksStore } from '@wordpress/blocks';
8
+ import { Path, SVG, Button, Placeholder } from '@wordpress/components';
9
+ import { useState, useEffect } from '@wordpress/element';
10
+
11
+ /**
12
+ * Returns a custom variation icon.
13
+ *
14
+ * @param {string} name The block variation name.
15
+ *
16
+ * @return {JSX.Element} The SVG element.
17
+ */
18
+ const getGroupPlaceholderIcons = ( name = 'group' ) => {
19
+ const icons = {
20
+ group: (
21
+ <SVG
22
+ xmlns="http://www.w3.org/2000/svg"
23
+ width="44"
24
+ height="32"
25
+ viewBox="0 0 44 32"
26
+ >
27
+ <Path
28
+ d="M42 0H2C.9 0 0 .9 0 2v28c0 1.1.9 2 2 2h40c1.1 0 2-.9 2-2V2c0-1.1-.9-2-2-2z"
29
+ // style="fill:#ccc"
30
+ />
31
+ </SVG>
32
+ ),
33
+ 'group-row': (
34
+ <SVG
35
+ xmlns="http://www.w3.org/2000/svg"
36
+ width="44"
37
+ height="32"
38
+ viewBox="0 0 44 32"
39
+ >
40
+ <Path
41
+ d="M42 0H23.5c-.6 0-1 .4-1 1v30c0 .6.4 1 1 1H42c1.1 0 2-.9 2-2V2c0-1.1-.9-2-2-2zM20.5 0H2C.9 0 0 .9 0 2v28c0 1.1.9 2 2 2h18.5c.6 0 1-.4 1-1V1c0-.6-.4-1-1-1z"
42
+ // style="fill:#ccc"
43
+ />
44
+ </SVG>
45
+ ),
46
+ 'group-stack': (
47
+ <SVG
48
+ xmlns="http://www.w3.org/2000/svg"
49
+ width="44"
50
+ height="32"
51
+ viewBox="0 0 44 32"
52
+ >
53
+ <Path
54
+ d="M42 0H2C.9 0 0 .9 0 2v12.5c0 .6.4 1 1 1h42c.6 0 1-.4 1-1V2c0-1.1-.9-2-2-2zm1 16.5H1c-.6 0-1 .4-1 1V30c0 1.1.9 2 2 2h40c1.1 0 2-.9 2-2V17.5c0-.6-.4-1-1-1z"
55
+ // style="fill:#ccc"
56
+ />
57
+ </SVG>
58
+ ),
59
+ };
60
+ return icons?.[ name ];
61
+ };
62
+
63
+ /**
64
+ * A custom hook to tell the Group block whether to show the variation placeholder.
65
+ *
66
+ * @param {Object} props Arguments to pass to hook.
67
+ * @param {Object} [props.attributes] The block's attributes.
68
+ * @param {string} [props.usedLayoutType] The block's current layout type.
69
+ * @param {boolean} [props.hasInnerBlocks] Whether the block has inner blocks.
70
+ *
71
+ * @return {[boolean, Function]} A state value and setter function.
72
+ */
73
+ export function useShouldShowPlaceHolder( {
74
+ attributes = {
75
+ style: undefined,
76
+ backgroundColor: undefined,
77
+ textColor: undefined,
78
+ fontSize: undefined,
79
+ },
80
+ usedLayoutType = '',
81
+ hasInnerBlocks = false,
82
+ } ) {
83
+ const { style, backgroundColor, textColor, fontSize } = attributes;
84
+ /*
85
+ * Shows the placeholder when no known styles are set,
86
+ * or when a non-default layout has been selected.
87
+ * Should the Group block support more style presets in the
88
+ * future, e.g., attributes.spacingSize, we can add them to the
89
+ * condition.
90
+ */
91
+ const [ showPlaceholder, setShowPlaceholder ] = useState(
92
+ ! hasInnerBlocks &&
93
+ ! backgroundColor &&
94
+ ! fontSize &&
95
+ ! textColor &&
96
+ ! style &&
97
+ usedLayoutType !== 'flex'
98
+ );
99
+
100
+ useEffect( () => {
101
+ if (
102
+ !! hasInnerBlocks ||
103
+ !! backgroundColor ||
104
+ !! fontSize ||
105
+ !! textColor ||
106
+ !! style ||
107
+ usedLayoutType === 'flex'
108
+ ) {
109
+ setShowPlaceholder( false );
110
+ }
111
+ }, [
112
+ backgroundColor,
113
+ fontSize,
114
+ textColor,
115
+ style,
116
+ usedLayoutType,
117
+ hasInnerBlocks,
118
+ ] );
119
+
120
+ return [ showPlaceholder, setShowPlaceholder ];
121
+ }
122
+
123
+ /**
124
+ * Display group variations if none is selected.
125
+ *
126
+ * @param {Object} props Component props.
127
+ * @param {string} props.name The block's name.
128
+ * @param {Function} props.onSelect Function to set block's attributes.
129
+ *
130
+ * @return {JSX.Element} The placeholder.
131
+ */
132
+ function GroupPlaceHolder( { name, onSelect } ) {
133
+ const { defaultVariation, variations } = useSelect(
134
+ ( select ) => {
135
+ const { getBlockVariations, getDefaultBlockVariation } =
136
+ select( blocksStore );
137
+ return {
138
+ defaultVariation: getDefaultBlockVariation( name, 'block' ),
139
+ variations: getBlockVariations( name, 'block' ) || [],
140
+ };
141
+ },
142
+ [ name ]
143
+ );
144
+ const blockProps = useBlockProps( {
145
+ className: 'wp-block-group__placeholder',
146
+ } );
147
+ const selectVariation = ( nextVariation = defaultVariation ) =>
148
+ onSelect( nextVariation );
149
+
150
+ return (
151
+ <div { ...blockProps }>
152
+ <Placeholder
153
+ instructions={ __( 'Group blocks together. Select a layout:' ) }
154
+ >
155
+ { /*
156
+ * Taken from BlockVariationPicker component.
157
+ * Disable reason: The `list` ARIA role is redundant but
158
+ * Safari+VoiceOver won't announce the list otherwise.
159
+ */
160
+ /* eslint-disable jsx-a11y/no-redundant-roles */ }
161
+ <ul
162
+ role="list"
163
+ className="wp-block-group-placeholder__variations"
164
+ aria-label={ __( 'Block variations' ) }
165
+ >
166
+ { variations.map( ( variation ) => (
167
+ <li key={ variation.name }>
168
+ <Button
169
+ variant="tertiary"
170
+ icon={ getGroupPlaceholderIcons(
171
+ variation.name
172
+ ) }
173
+ iconSize={ 44 }
174
+ onClick={ () => selectVariation( variation ) }
175
+ className="wp-block-group-placeholder__variation-button"
176
+ label={ `${ variation.title }: ${ variation.description }` }
177
+ />
178
+ </li>
179
+ ) ) }
180
+ </ul>
181
+ { /* eslint-enable jsx-a11y/no-redundant-roles */ }
182
+ </Placeholder>
183
+ </div>
184
+ );
185
+ }
186
+
187
+ export default GroupPlaceHolder;