@wordpress/block-editor 12.9.0 → 12.10.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 (463) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +33 -3
  3. package/build/components/block-canvas/index.js +107 -0
  4. package/build/components/block-canvas/index.js.map +1 -0
  5. package/build/components/block-inspector/index.js +4 -1
  6. package/build/components/block-inspector/index.js.map +1 -1
  7. package/build/components/block-patterns-list/index.js +19 -4
  8. package/build/components/block-patterns-list/index.js.map +1 -1
  9. package/build/components/block-patterns-paging/index.js +66 -0
  10. package/build/components/block-patterns-paging/index.js.map +1 -0
  11. package/build/components/block-settings-menu/block-settings-dropdown.js +28 -0
  12. package/build/components/block-settings-menu/block-settings-dropdown.js.map +1 -1
  13. package/build/components/block-settings-menu-controls/index.js +4 -7
  14. package/build/components/block-settings-menu-controls/index.js.map +1 -1
  15. package/build/components/block-styles/index.js +1 -0
  16. package/build/components/block-styles/index.js.map +1 -1
  17. package/build/components/block-toolbar/block-toolbar-menu.native.js +3 -7
  18. package/build/components/block-toolbar/block-toolbar-menu.native.js.map +1 -1
  19. package/build/components/block-tools/block-contextual-toolbar.js +18 -7
  20. package/build/components/block-tools/block-contextual-toolbar.js.map +1 -1
  21. package/build/components/block-tools/block-selection-button.js +5 -1
  22. package/build/components/block-tools/block-selection-button.js.map +1 -1
  23. package/build/components/border-radius-control/input-controls.js +1 -1
  24. package/build/components/border-radius-control/input-controls.js.map +1 -1
  25. package/build/components/border-radius-control/linked-button.js +2 -4
  26. package/build/components/border-radius-control/linked-button.js.map +1 -1
  27. package/build/components/colors/with-colors.js.map +1 -1
  28. package/build/components/convert-to-group-buttons/use-convert-to-group-button-props.js +8 -21
  29. package/build/components/convert-to-group-buttons/use-convert-to-group-button-props.js.map +1 -1
  30. package/build/components/default-block-appender/index.native.js +20 -1
  31. package/build/components/default-block-appender/index.native.js.map +1 -1
  32. package/build/components/duotone/utils.js +68 -0
  33. package/build/components/duotone/utils.js.map +1 -1
  34. package/build/components/editor-styles/index.js +28 -9
  35. package/build/components/editor-styles/index.js.map +1 -1
  36. package/build/components/global-styles/hooks.js +2 -101
  37. package/build/components/global-styles/hooks.js.map +1 -1
  38. package/build/components/global-styles/image-settings-panel.js +61 -0
  39. package/build/components/global-styles/image-settings-panel.js.map +1 -0
  40. package/build/components/global-styles/index.js +11 -17
  41. package/build/components/global-styles/index.js.map +1 -1
  42. package/build/components/global-styles/use-global-styles-output.js +19 -15
  43. package/build/components/global-styles/use-global-styles-output.js.map +1 -1
  44. package/build/components/global-styles/utils.js +1 -1
  45. package/build/components/global-styles/utils.js.map +1 -1
  46. package/build/components/iframe/index.js +67 -33
  47. package/build/components/iframe/index.js.map +1 -1
  48. package/build/components/image-editor/use-save-image.js +2 -5
  49. package/build/components/image-editor/use-save-image.js.map +1 -1
  50. package/build/components/image-editor/use-transform-image.js +9 -9
  51. package/build/components/image-editor/use-transform-image.js.map +1 -1
  52. package/build/components/index.js +8 -12
  53. package/build/components/index.js.map +1 -1
  54. package/build/components/index.native.js +6 -5
  55. package/build/components/index.native.js.map +1 -1
  56. package/build/components/inner-blocks/use-nested-settings-update.js +13 -7
  57. package/build/components/inner-blocks/use-nested-settings-update.js.map +1 -1
  58. package/build/components/inserter/block-patterns-explorer/explorer.js +12 -6
  59. package/build/components/inserter/block-patterns-explorer/explorer.js.map +1 -1
  60. package/build/components/inserter/block-patterns-explorer/patterns-list.js +57 -23
  61. package/build/components/inserter/block-patterns-explorer/patterns-list.js.map +1 -1
  62. package/build/components/inserter/block-patterns-explorer/sidebar.js +24 -9
  63. package/build/components/inserter/block-patterns-explorer/sidebar.js.map +1 -1
  64. package/build/components/inserter/block-patterns-source-filter.js +54 -0
  65. package/build/components/inserter/block-patterns-source-filter.js.map +1 -0
  66. package/build/components/inserter/block-patterns-sync-filter.js +46 -0
  67. package/build/components/inserter/block-patterns-sync-filter.js.map +1 -0
  68. package/build/components/inserter/block-patterns-tab.js +91 -45
  69. package/build/components/inserter/block-patterns-tab.js.map +1 -1
  70. package/build/components/inserter/hooks/use-patterns-paging.js +57 -0
  71. package/build/components/inserter/hooks/use-patterns-paging.js.map +1 -0
  72. package/build/components/inserter/hooks/use-patterns-state.js +21 -10
  73. package/build/components/inserter/hooks/use-patterns-state.js.map +1 -1
  74. package/build/components/inserter/menu.js +13 -11
  75. package/build/components/inserter/menu.js.map +1 -1
  76. package/build/components/inserter/search-results.js +4 -3
  77. package/build/components/inserter/search-results.js.map +1 -1
  78. package/build/components/inserter/tabs.js +1 -12
  79. package/build/components/inserter/tabs.js.map +1 -1
  80. package/build/components/inspector-controls/block-support-slot-container.js +12 -1
  81. package/build/components/inspector-controls/block-support-slot-container.js.map +1 -1
  82. package/build/components/inspector-controls/fill.js +24 -13
  83. package/build/components/inspector-controls/fill.js.map +1 -1
  84. package/build/components/inspector-controls/groups.js +5 -3
  85. package/build/components/inspector-controls/groups.js.map +1 -1
  86. package/build/components/inspector-controls/slot.js +13 -0
  87. package/build/components/inspector-controls/slot.js.map +1 -1
  88. package/build/components/inspector-controls-tabs/styles-tab.js +3 -0
  89. package/build/components/inspector-controls-tabs/styles-tab.js.map +1 -1
  90. package/build/components/link-control/index.js +13 -2
  91. package/build/components/link-control/index.js.map +1 -1
  92. package/build/components/link-control/settings.js +2 -1
  93. package/build/components/link-control/settings.js.map +1 -1
  94. package/build/components/list-view/block-select-button.js +1 -3
  95. package/build/components/list-view/block-select-button.js.map +1 -1
  96. package/build/components/list-view/block.js +13 -1
  97. package/build/components/list-view/block.js.map +1 -1
  98. package/build/components/list-view/use-block-selection.js +29 -24
  99. package/build/components/list-view/use-block-selection.js.map +1 -1
  100. package/build/components/media-placeholder/index.js +2 -2
  101. package/build/components/media-placeholder/index.js.map +1 -1
  102. package/build/components/media-placeholder/index.native.js +11 -11
  103. package/build/components/media-placeholder/index.native.js.map +1 -1
  104. package/build/components/media-replace-flow/index.js +2 -3
  105. package/build/components/media-replace-flow/index.js.map +1 -1
  106. package/build/components/media-upload/constants.js +30 -0
  107. package/build/components/media-upload/constants.js.map +1 -0
  108. package/build/components/media-upload/index.native.js +63 -53
  109. package/build/components/media-upload/index.native.js.map +1 -1
  110. package/build/components/preview-options/index.js +1 -1
  111. package/build/components/preview-options/index.js.map +1 -1
  112. package/build/components/rich-text/index.js +34 -35
  113. package/build/components/rich-text/index.js.map +1 -1
  114. package/build/components/rich-text/index.native.js +14 -32
  115. package/build/components/rich-text/index.native.js.map +1 -1
  116. package/build/components/rich-text/multiline.js +95 -0
  117. package/build/components/rich-text/multiline.js.map +1 -0
  118. package/build/components/rich-text/split-value.js +10 -16
  119. package/build/components/rich-text/split-value.js.map +1 -1
  120. package/build/components/rich-text/use-enter.js +31 -40
  121. package/build/components/rich-text/use-enter.js.map +1 -1
  122. package/build/components/rich-text/use-paste-handler.js +18 -33
  123. package/build/components/rich-text/use-paste-handler.js.map +1 -1
  124. package/build/components/spacing-sizes-control/utils.js +1 -1
  125. package/build/components/spacing-sizes-control/utils.js.map +1 -1
  126. package/build/components/use-block-commands/index.js +30 -18
  127. package/build/components/use-block-commands/index.js.map +1 -1
  128. package/build/components/use-block-display-information/index.js +5 -2
  129. package/build/components/use-block-display-information/index.js.map +1 -1
  130. package/build/hooks/background.js +258 -0
  131. package/build/hooks/background.js.map +1 -0
  132. package/build/hooks/block-hooks.js +188 -0
  133. package/build/hooks/block-hooks.js.map +1 -0
  134. package/build/hooks/block-rename-ui.js +160 -0
  135. package/build/hooks/block-rename-ui.js.map +1 -0
  136. package/build/hooks/duotone.js +29 -42
  137. package/build/hooks/duotone.js.map +1 -1
  138. package/build/hooks/index.js +2 -2
  139. package/build/hooks/index.js.map +1 -1
  140. package/build/hooks/layout.js +31 -14
  141. package/build/hooks/layout.js.map +1 -1
  142. package/build/hooks/position.js +4 -2
  143. package/build/hooks/position.js.map +1 -1
  144. package/build/hooks/style.js +74 -25
  145. package/build/hooks/style.js.map +1 -1
  146. package/build/hooks/utils.js +4 -0
  147. package/build/hooks/utils.js.map +1 -1
  148. package/build/private-apis.js +2 -0
  149. package/build/private-apis.js.map +1 -1
  150. package/build/store/actions.js +33 -10
  151. package/build/store/actions.js.map +1 -1
  152. package/build/store/private-actions.js +42 -8
  153. package/build/store/private-actions.js.map +1 -1
  154. package/build/store/private-selectors.js +23 -0
  155. package/build/store/private-selectors.js.map +1 -1
  156. package/build/store/reducer.js +43 -1
  157. package/build/store/reducer.js.map +1 -1
  158. package/build/store/selectors.js +84 -23
  159. package/build/store/selectors.js.map +1 -1
  160. package/build/store/utils.js +0 -4
  161. package/build/store/utils.js.map +1 -1
  162. package/build-module/components/block-canvas/index.js +97 -0
  163. package/build-module/components/block-canvas/index.js.map +1 -0
  164. package/build-module/components/block-inspector/index.js +4 -1
  165. package/build-module/components/block-inspector/index.js.map +1 -1
  166. package/build-module/components/block-patterns-list/index.js +20 -5
  167. package/build-module/components/block-patterns-list/index.js.map +1 -1
  168. package/build-module/components/block-patterns-paging/index.js +59 -0
  169. package/build-module/components/block-patterns-paging/index.js.map +1 -0
  170. package/build-module/components/block-settings-menu/block-settings-dropdown.js +28 -0
  171. package/build-module/components/block-settings-menu/block-settings-dropdown.js.map +1 -1
  172. package/build-module/components/block-settings-menu-controls/index.js +4 -7
  173. package/build-module/components/block-settings-menu-controls/index.js.map +1 -1
  174. package/build-module/components/block-styles/index.js +1 -0
  175. package/build-module/components/block-styles/index.js.map +1 -1
  176. package/build-module/components/block-toolbar/block-toolbar-menu.native.js +3 -7
  177. package/build-module/components/block-toolbar/block-toolbar-menu.native.js.map +1 -1
  178. package/build-module/components/block-tools/block-contextual-toolbar.js +18 -7
  179. package/build-module/components/block-tools/block-contextual-toolbar.js.map +1 -1
  180. package/build-module/components/block-tools/block-selection-button.js +5 -1
  181. package/build-module/components/block-tools/block-selection-button.js.map +1 -1
  182. package/build-module/components/border-radius-control/input-controls.js +1 -1
  183. package/build-module/components/border-radius-control/input-controls.js.map +1 -1
  184. package/build-module/components/border-radius-control/linked-button.js +2 -4
  185. package/build-module/components/border-radius-control/linked-button.js.map +1 -1
  186. package/build-module/components/colors/with-colors.js.map +1 -1
  187. package/build-module/components/convert-to-group-buttons/use-convert-to-group-button-props.js +8 -21
  188. package/build-module/components/convert-to-group-buttons/use-convert-to-group-button-props.js.map +1 -1
  189. package/build-module/components/default-block-appender/index.native.js +20 -1
  190. package/build-module/components/default-block-appender/index.native.js.map +1 -1
  191. package/build-module/components/duotone/utils.js +65 -0
  192. package/build-module/components/duotone/utils.js.map +1 -1
  193. package/build-module/components/editor-styles/index.js +28 -9
  194. package/build-module/components/editor-styles/index.js.map +1 -1
  195. package/build-module/components/global-styles/hooks.js +3 -100
  196. package/build-module/components/global-styles/hooks.js.map +1 -1
  197. package/build-module/components/global-styles/image-settings-panel.js +53 -0
  198. package/build-module/components/global-styles/image-settings-panel.js.map +1 -0
  199. package/build-module/components/global-styles/index.js +2 -2
  200. package/build-module/components/global-styles/index.js.map +1 -1
  201. package/build-module/components/global-styles/use-global-styles-output.js +18 -16
  202. package/build-module/components/global-styles/use-global-styles-output.js.map +1 -1
  203. package/build-module/components/global-styles/utils.js +1 -1
  204. package/build-module/components/global-styles/utils.js.map +1 -1
  205. package/build-module/components/iframe/index.js +66 -33
  206. package/build-module/components/iframe/index.js.map +1 -1
  207. package/build-module/components/image-editor/use-save-image.js +2 -5
  208. package/build-module/components/image-editor/use-save-image.js.map +1 -1
  209. package/build-module/components/image-editor/use-transform-image.js +9 -9
  210. package/build-module/components/image-editor/use-transform-image.js.map +1 -1
  211. package/build-module/components/index.js +1 -1
  212. package/build-module/components/index.js.map +1 -1
  213. package/build-module/components/index.native.js +2 -1
  214. package/build-module/components/index.native.js.map +1 -1
  215. package/build-module/components/inner-blocks/use-nested-settings-update.js +14 -8
  216. package/build-module/components/inner-blocks/use-nested-settings-update.js.map +1 -1
  217. package/build-module/components/inserter/block-patterns-explorer/explorer.js +12 -6
  218. package/build-module/components/inserter/block-patterns-explorer/explorer.js.map +1 -1
  219. package/build-module/components/inserter/block-patterns-explorer/patterns-list.js +59 -25
  220. package/build-module/components/inserter/block-patterns-explorer/patterns-list.js.map +1 -1
  221. package/build-module/components/inserter/block-patterns-explorer/sidebar.js +23 -9
  222. package/build-module/components/inserter/block-patterns-explorer/sidebar.js.map +1 -1
  223. package/build-module/components/inserter/block-patterns-source-filter.js +44 -0
  224. package/build-module/components/inserter/block-patterns-source-filter.js.map +1 -0
  225. package/build-module/components/inserter/block-patterns-sync-filter.js +38 -0
  226. package/build-module/components/inserter/block-patterns-sync-filter.js.map +1 -0
  227. package/build-module/components/inserter/block-patterns-tab.js +87 -46
  228. package/build-module/components/inserter/block-patterns-tab.js.map +1 -1
  229. package/build-module/components/inserter/hooks/use-patterns-paging.js +50 -0
  230. package/build-module/components/inserter/hooks/use-patterns-paging.js.map +1 -0
  231. package/build-module/components/inserter/hooks/use-patterns-state.js +22 -10
  232. package/build-module/components/inserter/hooks/use-patterns-state.js.map +1 -1
  233. package/build-module/components/inserter/menu.js +13 -11
  234. package/build-module/components/inserter/menu.js.map +1 -1
  235. package/build-module/components/inserter/search-results.js +4 -3
  236. package/build-module/components/inserter/search-results.js.map +1 -1
  237. package/build-module/components/inserter/tabs.js +1 -12
  238. package/build-module/components/inserter/tabs.js.map +1 -1
  239. package/build-module/components/inspector-controls/block-support-slot-container.js +13 -2
  240. package/build-module/components/inspector-controls/block-support-slot-container.js.map +1 -1
  241. package/build-module/components/inspector-controls/fill.js +25 -14
  242. package/build-module/components/inspector-controls/fill.js.map +1 -1
  243. package/build-module/components/inspector-controls/groups.js +5 -3
  244. package/build-module/components/inspector-controls/groups.js.map +1 -1
  245. package/build-module/components/inspector-controls/slot.js +15 -1
  246. package/build-module/components/inspector-controls/slot.js.map +1 -1
  247. package/build-module/components/inspector-controls-tabs/styles-tab.js +3 -0
  248. package/build-module/components/inspector-controls-tabs/styles-tab.js.map +1 -1
  249. package/build-module/components/link-control/index.js +13 -2
  250. package/build-module/components/link-control/index.js.map +1 -1
  251. package/build-module/components/link-control/settings.js +2 -1
  252. package/build-module/components/link-control/settings.js.map +1 -1
  253. package/build-module/components/list-view/block-select-button.js +1 -3
  254. package/build-module/components/list-view/block-select-button.js.map +1 -1
  255. package/build-module/components/list-view/block.js +13 -1
  256. package/build-module/components/list-view/block.js.map +1 -1
  257. package/build-module/components/list-view/use-block-selection.js +30 -25
  258. package/build-module/components/list-view/use-block-selection.js.map +1 -1
  259. package/build-module/components/media-placeholder/index.js +2 -2
  260. package/build-module/components/media-placeholder/index.js.map +1 -1
  261. package/build-module/components/media-placeholder/index.native.js +7 -7
  262. package/build-module/components/media-placeholder/index.native.js.map +1 -1
  263. package/build-module/components/media-replace-flow/index.js +2 -3
  264. package/build-module/components/media-replace-flow/index.js.map +1 -1
  265. package/build-module/components/media-upload/constants.js +14 -0
  266. package/build-module/components/media-upload/constants.js.map +1 -0
  267. package/build-module/components/media-upload/index.native.js +53 -34
  268. package/build-module/components/media-upload/index.native.js.map +1 -1
  269. package/build-module/components/preview-options/index.js +1 -1
  270. package/build-module/components/preview-options/index.js.map +1 -1
  271. package/build-module/components/rich-text/index.js +35 -37
  272. package/build-module/components/rich-text/index.js.map +1 -1
  273. package/build-module/components/rich-text/index.native.js +15 -33
  274. package/build-module/components/rich-text/index.native.js.map +1 -1
  275. package/build-module/components/rich-text/multiline.js +87 -0
  276. package/build-module/components/rich-text/multiline.js.map +1 -0
  277. package/build-module/components/rich-text/split-value.js +10 -16
  278. package/build-module/components/rich-text/split-value.js.map +1 -1
  279. package/build-module/components/rich-text/use-enter.js +33 -42
  280. package/build-module/components/rich-text/use-enter.js.map +1 -1
  281. package/build-module/components/rich-text/use-paste-handler.js +19 -34
  282. package/build-module/components/rich-text/use-paste-handler.js.map +1 -1
  283. package/build-module/components/spacing-sizes-control/utils.js +2 -2
  284. package/build-module/components/spacing-sizes-control/utils.js.map +1 -1
  285. package/build-module/components/use-block-commands/index.js +28 -16
  286. package/build-module/components/use-block-commands/index.js.map +1 -1
  287. package/build-module/components/use-block-display-information/index.js +5 -2
  288. package/build-module/components/use-block-display-information/index.js.map +1 -1
  289. package/build-module/hooks/background.js +244 -0
  290. package/build-module/hooks/background.js.map +1 -0
  291. package/build-module/hooks/block-hooks.js +181 -0
  292. package/build-module/hooks/block-hooks.js.map +1 -0
  293. package/build-module/hooks/block-rename-ui.js +153 -0
  294. package/build-module/hooks/block-rename-ui.js.map +1 -0
  295. package/build-module/hooks/duotone.js +26 -39
  296. package/build-module/hooks/duotone.js.map +1 -1
  297. package/build-module/hooks/index.js +2 -2
  298. package/build-module/hooks/index.js.map +1 -1
  299. package/build-module/hooks/layout.js +33 -16
  300. package/build-module/hooks/layout.js.map +1 -1
  301. package/build-module/hooks/position.js +4 -2
  302. package/build-module/hooks/position.js.map +1 -1
  303. package/build-module/hooks/style.js +73 -24
  304. package/build-module/hooks/style.js.map +1 -1
  305. package/build-module/hooks/utils.js +4 -0
  306. package/build-module/hooks/utils.js.map +1 -1
  307. package/build-module/private-apis.js +2 -0
  308. package/build-module/private-apis.js.map +1 -1
  309. package/build-module/store/actions.js +33 -10
  310. package/build-module/store/actions.js.map +1 -1
  311. package/build-module/store/private-actions.js +39 -8
  312. package/build-module/store/private-actions.js.map +1 -1
  313. package/build-module/store/private-selectors.js +21 -0
  314. package/build-module/store/private-selectors.js.map +1 -1
  315. package/build-module/store/reducer.js +41 -1
  316. package/build-module/store/reducer.js.map +1 -1
  317. package/build-module/store/selectors.js +78 -22
  318. package/build-module/store/selectors.js.map +1 -1
  319. package/build-module/store/utils.js +0 -4
  320. package/build-module/store/utils.js.map +1 -1
  321. package/build-style/content-rtl.css +0 -1
  322. package/build-style/content.css +0 -1
  323. package/build-style/style-rtl.css +174 -131
  324. package/build-style/style.css +174 -131
  325. package/package.json +32 -32
  326. package/src/components/block-canvas/index.js +108 -0
  327. package/src/components/block-inspector/index.js +5 -1
  328. package/src/components/block-list/content.scss +0 -1
  329. package/src/components/block-patterns-list/index.js +32 -7
  330. package/src/components/block-patterns-list/style.scss +26 -9
  331. package/src/components/block-patterns-paging/index.js +92 -0
  332. package/src/components/block-patterns-paging/style.scss +42 -0
  333. package/src/components/block-settings-menu/block-settings-dropdown.js +44 -0
  334. package/src/components/block-settings-menu-controls/index.js +4 -9
  335. package/src/components/block-styles/index.js +1 -0
  336. package/src/components/block-styles/style.scss +3 -3
  337. package/src/components/block-toolbar/block-toolbar-menu.native.js +1 -6
  338. package/src/components/block-tools/block-contextual-toolbar.js +16 -5
  339. package/src/components/block-tools/block-selection-button.js +9 -1
  340. package/src/components/block-tools/style.scss +0 -98
  341. package/src/components/border-radius-control/input-controls.js +1 -1
  342. package/src/components/border-radius-control/linked-button.js +8 -11
  343. package/src/components/color-palette/test/__snapshots__/control.js.snap +34 -21
  344. package/src/components/colors/with-colors.js +3 -2
  345. package/src/components/convert-to-group-buttons/use-convert-to-group-button-props.js +8 -35
  346. package/src/components/default-block-appender/index.native.js +26 -3
  347. package/src/components/duotone/utils.js +65 -0
  348. package/src/components/editor-styles/index.js +32 -23
  349. package/src/components/global-styles/hooks.js +4 -112
  350. package/src/components/global-styles/image-settings-panel.js +71 -0
  351. package/src/components/global-styles/index.js +4 -3
  352. package/src/components/global-styles/use-global-styles-output.js +25 -16
  353. package/src/components/global-styles/utils.js +1 -2
  354. package/src/components/iframe/index.js +72 -33
  355. package/src/components/image-editor/use-save-image.js +2 -9
  356. package/src/components/image-editor/use-transform-image.js +9 -9
  357. package/src/components/index.js +1 -1
  358. package/src/components/index.native.js +2 -2
  359. package/src/components/inner-blocks/use-nested-settings-update.js +15 -10
  360. package/src/components/inserter/block-patterns-explorer/explorer.js +17 -5
  361. package/src/components/inserter/block-patterns-explorer/patterns-list.js +109 -40
  362. package/src/components/inserter/block-patterns-explorer/sidebar.js +23 -8
  363. package/src/components/inserter/block-patterns-source-filter.js +40 -0
  364. package/src/components/inserter/block-patterns-sync-filter.js +35 -0
  365. package/src/components/inserter/block-patterns-tab.js +168 -57
  366. package/src/components/inserter/hooks/use-patterns-paging.js +65 -0
  367. package/src/components/inserter/hooks/use-patterns-state.js +27 -16
  368. package/src/components/inserter/menu.js +15 -17
  369. package/src/components/inserter/search-results.js +6 -4
  370. package/src/components/inserter/style.scss +23 -2
  371. package/src/components/inserter/tabs.js +2 -12
  372. package/src/components/inserter/test/index.native.js +8 -12
  373. package/src/components/inspector-controls/block-support-slot-container.js +19 -3
  374. package/src/components/inspector-controls/fill.js +28 -14
  375. package/src/components/inspector-controls/groups.js +6 -2
  376. package/src/components/inspector-controls/slot.js +28 -3
  377. package/src/components/inspector-controls-tabs/styles-tab.js +4 -0
  378. package/src/components/link-control/index.js +14 -0
  379. package/src/components/link-control/settings.js +1 -0
  380. package/src/components/link-control/style.scss +28 -7
  381. package/src/components/link-control/test/index.js +88 -6
  382. package/src/components/list-view/block-select-button.js +1 -3
  383. package/src/components/list-view/block.js +19 -1
  384. package/src/components/list-view/style.scss +1 -2
  385. package/src/components/list-view/use-block-selection.js +38 -32
  386. package/src/components/media-placeholder/README.md +2 -2
  387. package/src/components/media-placeholder/index.js +2 -2
  388. package/src/components/media-placeholder/index.native.js +11 -12
  389. package/src/components/media-replace-flow/index.js +2 -2
  390. package/src/components/media-replace-flow/test/index.js +5 -23
  391. package/src/components/media-upload/README.md +3 -2
  392. package/src/components/media-upload/constants.js +15 -0
  393. package/src/components/media-upload/index.native.js +66 -40
  394. package/src/components/media-upload/style.native.scss +4 -0
  395. package/src/components/media-upload/test/index.native.js +2 -2
  396. package/src/components/preview-options/README.md +7 -0
  397. package/src/components/preview-options/index.js +1 -1
  398. package/src/components/rich-text/index.js +48 -44
  399. package/src/components/rich-text/index.native.js +14 -42
  400. package/src/components/rich-text/multiline.js +121 -0
  401. package/src/components/rich-text/split-value.js +10 -35
  402. package/src/components/rich-text/use-enter.js +32 -42
  403. package/src/components/rich-text/use-paste-handler.js +16 -40
  404. package/src/components/spacing-sizes-control/style.scss +5 -7
  405. package/src/components/spacing-sizes-control/utils.js +1 -2
  406. package/src/components/use-block-commands/index.js +28 -20
  407. package/src/components/use-block-display-information/index.js +3 -0
  408. package/src/hooks/background.js +288 -0
  409. package/src/hooks/background.scss +57 -0
  410. package/src/hooks/block-hooks.js +257 -0
  411. package/src/hooks/block-hooks.scss +16 -0
  412. package/src/hooks/block-rename-ui.js +230 -0
  413. package/src/hooks/block-rename-ui.scss +3 -0
  414. package/src/hooks/duotone.js +42 -43
  415. package/src/hooks/index.js +2 -2
  416. package/src/hooks/layout.js +31 -33
  417. package/src/hooks/position.js +4 -3
  418. package/src/hooks/style.js +96 -37
  419. package/src/hooks/test/align.native.js +4 -3
  420. package/src/hooks/utils.js +4 -0
  421. package/src/private-apis.js +2 -0
  422. package/src/store/actions.js +52 -10
  423. package/src/store/private-actions.js +37 -6
  424. package/src/store/private-selectors.js +21 -0
  425. package/src/store/reducer.js +38 -0
  426. package/src/store/selectors.js +107 -26
  427. package/src/store/test/actions.js +19 -8
  428. package/src/store/test/private-actions.js +17 -0
  429. package/src/store/test/reducer.js +25 -0
  430. package/src/store/test/selectors.js +130 -123
  431. package/src/store/utils.js +3 -10
  432. package/src/style.scss +4 -0
  433. package/build/components/duotone/components.js +0 -135
  434. package/build/components/duotone/components.js.map +0 -1
  435. package/build/components/duotone/index.js +0 -38
  436. package/build/components/duotone/index.js.map +0 -1
  437. package/build/components/global-styles/behaviors-panel.js +0 -64
  438. package/build/components/global-styles/behaviors-panel.js.map +0 -1
  439. package/build/components/inserter/reusable-blocks-tab.js +0 -85
  440. package/build/components/inserter/reusable-blocks-tab.js.map +0 -1
  441. package/build/hooks/auto-inserting-blocks.js +0 -174
  442. package/build/hooks/auto-inserting-blocks.js.map +0 -1
  443. package/build/hooks/behaviors.js +0 -173
  444. package/build/hooks/behaviors.js.map +0 -1
  445. package/build-module/components/duotone/components.js +0 -126
  446. package/build-module/components/duotone/components.js.map +0 -1
  447. package/build-module/components/duotone/index.js +0 -3
  448. package/build-module/components/duotone/index.js.map +0 -1
  449. package/build-module/components/global-styles/behaviors-panel.js +0 -57
  450. package/build-module/components/global-styles/behaviors-panel.js.map +0 -1
  451. package/build-module/components/inserter/reusable-blocks-tab.js +0 -76
  452. package/build-module/components/inserter/reusable-blocks-tab.js.map +0 -1
  453. package/build-module/hooks/auto-inserting-blocks.js +0 -167
  454. package/build-module/hooks/auto-inserting-blocks.js.map +0 -1
  455. package/build-module/hooks/behaviors.js +0 -166
  456. package/build-module/hooks/behaviors.js.map +0 -1
  457. package/src/components/duotone/components.js +0 -133
  458. package/src/components/duotone/index.js +0 -7
  459. package/src/components/global-styles/behaviors-panel.js +0 -71
  460. package/src/components/inserter/reusable-blocks-tab.js +0 -84
  461. package/src/components/inserter/test/reusable-blocks-tab.js +0 -73
  462. package/src/hooks/auto-inserting-blocks.js +0 -232
  463. package/src/hooks/behaviors.js +0 -206
@@ -20,6 +20,7 @@ import { getCSSRules, compileCSS } from '@wordpress/style-engine';
20
20
  * Internal dependencies
21
21
  */
22
22
  import BlockList from '../components/block-list';
23
+ import { BACKGROUND_SUPPORT_KEY, BackgroundImagePanel } from './background';
23
24
  import { BORDER_SUPPORT_KEY, BorderPanel } from './border';
24
25
  import { COLOR_SUPPORT_KEY, ColorEdit } from './color';
25
26
  import {
@@ -34,6 +35,7 @@ import {
34
35
  } from './dimensions';
35
36
  import useDisplayBlockControls from '../components/use-display-block-controls';
36
37
  import { shouldSkipSerialization } from './utils';
38
+ import { scopeSelector } from '../components/global-styles/utils';
37
39
  import { useBlockEditingMode } from '../components/block-editing-mode';
38
40
 
39
41
  const styleSupportKeys = [
@@ -41,6 +43,7 @@ const styleSupportKeys = [
41
43
  BORDER_SUPPORT_KEY,
42
44
  COLOR_SUPPORT_KEY,
43
45
  DIMENSIONS_SUPPORT_KEY,
46
+ BACKGROUND_SUPPORT_KEY,
44
47
  SPACING_SUPPORT_KEY,
45
48
  ];
46
49
 
@@ -126,7 +129,11 @@ const skipSerializationPathsEdit = {
126
129
  */
127
130
  const skipSerializationPathsSave = {
128
131
  ...skipSerializationPathsEdit,
129
- [ `${ SPACING_SUPPORT_KEY }` ]: [ 'spacing.blockGap' ],
132
+ [ `${ BACKGROUND_SUPPORT_KEY }` ]: [ BACKGROUND_SUPPORT_KEY ], // Skip serialization of background support in save mode.
133
+ };
134
+
135
+ const skipSerializationPathsSaveChecks = {
136
+ [ `${ BACKGROUND_SUPPORT_KEY }` ]: true,
130
137
  };
131
138
 
132
139
  /**
@@ -284,7 +291,9 @@ export function addSaveProps(
284
291
 
285
292
  let { style } = attributes;
286
293
  Object.entries( skipPaths ).forEach( ( [ indicator, path ] ) => {
287
- const skipSerialization = getBlockSupport( blockType, indicator );
294
+ const skipSerialization =
295
+ skipSerializationPathsSaveChecks[ indicator ] ||
296
+ getBlockSupport( blockType, indicator );
288
297
 
289
298
  if ( skipSerialization === true ) {
290
299
  style = omitStyle( style, path );
@@ -359,6 +368,7 @@ export const withBlockControls = createHigherOrderComponent(
359
368
  { shouldDisplayControls && blockEditingMode === 'default' && (
360
369
  <>
361
370
  <ColorEdit { ...props } />
371
+ <BackgroundImagePanel { ...props } />
362
372
  <TypographyPanel { ...props } />
363
373
  <BorderPanel { ...props } />
364
374
  <DimensionsPanel { ...props } />
@@ -371,6 +381,18 @@ export const withBlockControls = createHigherOrderComponent(
371
381
  'withToolbarControls'
372
382
  );
373
383
 
384
+ // Defines which element types are supported, including their hover styles or
385
+ // any other elements that have been included under a single element type
386
+ // e.g. heading and h1-h6.
387
+ const elementTypes = [
388
+ { elementType: 'button' },
389
+ { elementType: 'link', pseudo: [ ':hover' ] },
390
+ {
391
+ elementType: 'heading',
392
+ elements: [ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6' ],
393
+ },
394
+ ];
395
+
374
396
  /**
375
397
  * Override the default block element to include elements styles.
376
398
  *
@@ -383,47 +405,84 @@ const withElementsStyles = createHigherOrderComponent(
383
405
  BlockListBlock
384
406
  ) }`;
385
407
 
386
- const skipLinkColorSerialization = shouldSkipSerialization(
387
- props.name,
388
- COLOR_SUPPORT_KEY,
389
- 'link'
390
- );
408
+ // The .editor-styles-wrapper selector is required on elements styles. As it is
409
+ // added to all other editor styles, not providing it causes reset and global
410
+ // styles to override element styles because of higher specificity.
411
+ const baseElementSelector = `.editor-styles-wrapper .${ blockElementsContainerIdentifier }`;
412
+ const blockElementStyles = props.attributes.style?.elements;
391
413
 
392
414
  const styles = useMemo( () => {
393
- // The .editor-styles-wrapper selector is required on elements styles. As it is
394
- // added to all other editor styles, not providing it causes reset and global
395
- // styles to override element styles because of higher specificity.
396
- const elements = [
397
- {
398
- styles: ! skipLinkColorSerialization
399
- ? props.attributes.style?.elements?.link
400
- : undefined,
401
- selector: `.editor-styles-wrapper .${ blockElementsContainerIdentifier } ${ ELEMENTS.link }`,
402
- },
403
- {
404
- styles: ! skipLinkColorSerialization
405
- ? props.attributes.style?.elements?.link?.[ ':hover' ]
406
- : undefined,
407
- selector: `.editor-styles-wrapper .${ blockElementsContainerIdentifier } ${ ELEMENTS.link }:hover`,
408
- },
409
- ];
410
- const elementCssRules = [];
411
- for ( const { styles: elementStyles, selector } of elements ) {
415
+ if ( ! blockElementStyles ) {
416
+ return;
417
+ }
418
+
419
+ const elementCSSRules = [];
420
+
421
+ elementTypes.forEach( ( { elementType, pseudo, elements } ) => {
422
+ const skipSerialization = shouldSkipSerialization(
423
+ props.name,
424
+ COLOR_SUPPORT_KEY,
425
+ elementType
426
+ );
427
+
428
+ if ( skipSerialization ) {
429
+ return;
430
+ }
431
+
432
+ const elementStyles = blockElementStyles?.[ elementType ];
433
+
434
+ // Process primary element type styles.
412
435
  if ( elementStyles ) {
413
- const cssRule = compileCSS( elementStyles, {
414
- selector,
436
+ const selector = scopeSelector(
437
+ baseElementSelector,
438
+ ELEMENTS[ elementType ]
439
+ );
440
+
441
+ elementCSSRules.push(
442
+ compileCSS( elementStyles, { selector } )
443
+ );
444
+
445
+ // Process any interactive states for the element type.
446
+ if ( pseudo ) {
447
+ pseudo.forEach( ( pseudoSelector ) => {
448
+ if ( elementStyles[ pseudoSelector ] ) {
449
+ elementCSSRules.push(
450
+ compileCSS(
451
+ elementStyles[ pseudoSelector ],
452
+ {
453
+ selector: scopeSelector(
454
+ baseElementSelector,
455
+ `${ ELEMENTS[ elementType ] }${ pseudoSelector }`
456
+ ),
457
+ }
458
+ )
459
+ );
460
+ }
461
+ } );
462
+ }
463
+ }
464
+
465
+ // Process related elements e.g. h1-h6 for headings
466
+ if ( elements ) {
467
+ elements.forEach( ( element ) => {
468
+ if ( blockElementStyles[ element ] ) {
469
+ elementCSSRules.push(
470
+ compileCSS( blockElementStyles[ element ], {
471
+ selector: scopeSelector(
472
+ baseElementSelector,
473
+ ELEMENTS[ element ]
474
+ ),
475
+ } )
476
+ );
477
+ }
415
478
  } );
416
- elementCssRules.push( cssRule );
417
479
  }
418
- }
419
- return elementCssRules.length > 0
420
- ? elementCssRules.join( '' )
480
+ } );
481
+
482
+ return elementCSSRules.length > 0
483
+ ? elementCSSRules.join( '' )
421
484
  : undefined;
422
- }, [
423
- props.attributes.style?.elements,
424
- blockElementsContainerIdentifier,
425
- skipLinkColorSerialization,
426
- ] );
485
+ }, [ baseElementSelector, blockElementStyles, props.name ] );
427
486
 
428
487
  const element = useContext( BlockList.__unstableElementContext );
429
488
 
@@ -108,9 +108,10 @@ describe( 'Align options', () => {
108
108
  expect( groupBlock ).toBeVisible();
109
109
 
110
110
  // Trigger inner blocks layout
111
- const innerBlockListWrapper = await within(
112
- groupBlock
113
- ).findByTestId( 'block-list-wrapper' );
111
+ const innerBlockListWrapper =
112
+ await within( groupBlock ).findByTestId(
113
+ 'block-list-wrapper'
114
+ );
114
115
  fireEvent( innerBlockListWrapper, 'layout', {
115
116
  nativeEvent: {
116
117
  layout: {
@@ -166,6 +166,8 @@ export function useBlockSettings( name, parentLayout ) {
166
166
  const isBackgroundEnabled = useSetting( 'color.background' );
167
167
  const isLinkEnabled = useSetting( 'color.link' );
168
168
  const isTextEnabled = useSetting( 'color.text' );
169
+ const isHeadingEnabled = useSetting( 'color.heading' );
170
+ const isButtonEnabled = useSetting( 'color.button' );
169
171
 
170
172
  const rawSettings = useMemo( () => {
171
173
  return {
@@ -193,6 +195,8 @@ export function useBlockSettings( name, parentLayout ) {
193
195
  customDuotone,
194
196
  background: isBackgroundEnabled,
195
197
  link: isLinkEnabled,
198
+ heading: isHeadingEnabled,
199
+ button: isButtonEnabled,
196
200
  text: isTextEnabled,
197
201
  },
198
202
  typography: {
@@ -23,6 +23,7 @@ import {
23
23
  useReusableBlocksRenameHint,
24
24
  } from './components/inserter/reusable-block-rename-hint';
25
25
  import { usesContextKey } from './components/rich-text/format-edit';
26
+ import { ExperimentalBlockCanvas } from './components/block-canvas';
26
27
 
27
28
  /**
28
29
  * Private @wordpress/block-editor APIs.
@@ -30,6 +31,7 @@ import { usesContextKey } from './components/rich-text/format-edit';
30
31
  export const privateApis = {};
31
32
  lock( privateApis, {
32
33
  ...globalStyles,
34
+ ExperimentalBlockCanvas,
33
35
  ExperimentalBlockEditorProvider,
34
36
  getRichTextValues,
35
37
  kebabCase,
@@ -375,7 +375,7 @@ function getBlocksWithDefaultStylesApplied( blocks, blockEditorSettings ) {
375
375
  */
376
376
  export const replaceBlocks =
377
377
  ( clientIds, blocks, indexToSelect, initialPosition = 0, meta ) =>
378
- ( { select, dispatch } ) => {
378
+ ( { select, dispatch, registry } ) => {
379
379
  /* eslint-enable jsdoc/valid-types */
380
380
  clientIds = castArray( clientIds );
381
381
  blocks = getBlocksWithDefaultStylesApplied(
@@ -394,16 +394,22 @@ export const replaceBlocks =
394
394
  return;
395
395
  }
396
396
  }
397
- dispatch( {
398
- type: 'REPLACE_BLOCKS',
399
- clientIds,
400
- blocks,
401
- time: Date.now(),
402
- indexToSelect,
403
- initialPosition,
404
- meta,
397
+ // We're batching these two actions because an extra `undo/redo` step can
398
+ // be created, based on whether we insert a default block or not.
399
+ registry.batch( () => {
400
+ dispatch( {
401
+ type: 'REPLACE_BLOCKS',
402
+ clientIds,
403
+ blocks,
404
+ time: Date.now(),
405
+ indexToSelect,
406
+ initialPosition,
407
+ meta,
408
+ } );
409
+ // To avoid a focus loss when removing the last block, assure there is
410
+ // always a default block if the last of the blocks have been removed.
411
+ dispatch.ensureDefaultBlock();
405
412
  } );
406
- dispatch.ensureDefaultBlock();
407
413
  };
408
414
 
409
415
  /**
@@ -1034,6 +1040,7 @@ export const mergeBlocks =
1034
1040
  dispatch.selectBlock( blockA.clientId );
1035
1041
  return;
1036
1042
  }
1043
+
1037
1044
  registry.batch( () => {
1038
1045
  dispatch.insertBlocks(
1039
1046
  blockWithSameType.innerBlocks,
@@ -1044,6 +1051,41 @@ export const mergeBlocks =
1044
1051
  dispatch.selectBlock(
1045
1052
  blockWithSameType.innerBlocks[ 0 ].clientId
1046
1053
  );
1054
+
1055
+ // Attempt to merge the next block if it's the same type and
1056
+ // same attributes. This is useful when merging a paragraph into
1057
+ // a list, and the next block is also a list. If we don't merge,
1058
+ // it looks like one list, but it's actually two lists. The same
1059
+ // applies to other blocks such as a group with the same
1060
+ // attributes.
1061
+ const nextBlockClientId =
1062
+ select.getNextBlockClientId( clientIdA );
1063
+
1064
+ if (
1065
+ nextBlockClientId &&
1066
+ select.getBlockName( clientIdA ) ===
1067
+ select.getBlockName( nextBlockClientId )
1068
+ ) {
1069
+ const rootAttributes =
1070
+ select.getBlockAttributes( clientIdA );
1071
+ const previousRootAttributes =
1072
+ select.getBlockAttributes( nextBlockClientId );
1073
+
1074
+ if (
1075
+ Object.keys( rootAttributes ).every(
1076
+ ( key ) =>
1077
+ rootAttributes[ key ] ===
1078
+ previousRootAttributes[ key ]
1079
+ )
1080
+ ) {
1081
+ dispatch.moveBlocksToPosition(
1082
+ select.getBlockOrder( nextBlockClientId ),
1083
+ nextBlockClientId,
1084
+ clientIdA
1085
+ );
1086
+ dispatch.removeBlock( nextBlockClientId, false );
1087
+ }
1088
+ }
1047
1089
  } );
1048
1090
  return;
1049
1091
  }
@@ -92,7 +92,7 @@ export function showBlockInterface() {
92
92
  */
93
93
  export const privateRemoveBlocks =
94
94
  ( clientIds, selectPrevious = true, forceRemove = false ) =>
95
- ( { select, dispatch } ) => {
95
+ ( { select, dispatch, registry } ) => {
96
96
  if ( ! clientIds || ! clientIds.length ) {
97
97
  return;
98
98
  }
@@ -154,11 +154,14 @@ export const privateRemoveBlocks =
154
154
  dispatch.selectPreviousBlock( clientIds[ 0 ], selectPrevious );
155
155
  }
156
156
 
157
- dispatch( { type: 'REMOVE_BLOCKS', clientIds } );
158
-
159
- // To avoid a focus loss when removing the last block, assure there is
160
- // always a default block if the last of the blocks have been removed.
161
- dispatch( ensureDefaultBlock() );
157
+ // We're batching these two actions because an extra `undo/redo` step can
158
+ // be created, based on whether we insert a default block or not.
159
+ registry.batch( () => {
160
+ dispatch( { type: 'REMOVE_BLOCKS', clientIds } );
161
+ // To avoid a focus loss when removing the last block, assure there is
162
+ // always a default block if the last of the blocks have been removed.
163
+ dispatch( ensureDefaultBlock() );
164
+ } );
162
165
  };
163
166
 
164
167
  /**
@@ -259,3 +262,31 @@ export function setBlockRemovalRules( rules = false ) {
259
262
  rules,
260
263
  };
261
264
  }
265
+
266
+ /**
267
+ * Sets the client ID of the block settings menu that is currently open.
268
+ *
269
+ * @param {?string} clientId The block client ID.
270
+ * @return {Object} Action object.
271
+ */
272
+ export function setOpenedBlockSettingsMenu( clientId ) {
273
+ return {
274
+ type: 'SET_OPENED_BLOCK_SETTINGS_MENU',
275
+ clientId,
276
+ };
277
+ }
278
+
279
+ export function setStyleOverride( id, style ) {
280
+ return {
281
+ type: 'SET_STYLE_OVERRIDE',
282
+ id,
283
+ style,
284
+ };
285
+ }
286
+
287
+ export function deleteStyleOverride( id ) {
288
+ return {
289
+ type: 'DELETE_STYLE_OVERRIDE',
290
+ id,
291
+ };
292
+ }
@@ -139,3 +139,24 @@ export function getRemovalPromptData( state ) {
139
139
  export function getBlockRemovalRules( state ) {
140
140
  return state.blockRemovalRules;
141
141
  }
142
+
143
+ /**
144
+ * Returns the client ID of the block settings menu that is currently open.
145
+ *
146
+ * @param {Object} state Global application state.
147
+ * @return {string|null} The client ID of the block menu that is currently open.
148
+ */
149
+ export function getOpenedBlockSettingsMenu( state ) {
150
+ return state.openedBlockSettingsMenu;
151
+ }
152
+
153
+ /**
154
+ * Returns all style overrides, intended to be merged with global editor styles.
155
+ *
156
+ * @param {Object} state Global application state.
157
+ *
158
+ * @return {Map} A map of style IDs to style overrides.
159
+ */
160
+ export function getStyleOverrides( state ) {
161
+ return state.styleOverrides;
162
+ }
@@ -1913,6 +1913,42 @@ export function blockEditingModes( state = new Map(), action ) {
1913
1913
  return state;
1914
1914
  }
1915
1915
 
1916
+ /**
1917
+ * Reducer returning the clientId of the block settings menu that is currently open.
1918
+ *
1919
+ * @param {string|null} state Current state.
1920
+ * @param {Object} action Dispatched action.
1921
+ *
1922
+ * @return {string|null} Updated state.
1923
+ */
1924
+ export function openedBlockSettingsMenu( state = null, action ) {
1925
+ if ( 'SET_OPENED_BLOCK_SETTINGS_MENU' === action.type ) {
1926
+ return action?.clientId ?? null;
1927
+ }
1928
+ return state;
1929
+ }
1930
+
1931
+ /**
1932
+ * Reducer returning a map of style IDs to style overrides.
1933
+ *
1934
+ * @param {Map} state Current state.
1935
+ * @param {Object} action Dispatched action.
1936
+ *
1937
+ * @return {Map} Updated state.
1938
+ */
1939
+ export function styleOverrides( state = new Map(), action ) {
1940
+ switch ( action.type ) {
1941
+ case 'SET_STYLE_OVERRIDE':
1942
+ return new Map( state ).set( action.id, action.style );
1943
+ case 'DELETE_STYLE_OVERRIDE': {
1944
+ const newState = new Map( state );
1945
+ newState.delete( action.id );
1946
+ return newState;
1947
+ }
1948
+ }
1949
+ return state;
1950
+ }
1951
+
1916
1952
  const combinedReducers = combineReducers( {
1917
1953
  blocks,
1918
1954
  isTyping,
@@ -1936,8 +1972,10 @@ const combinedReducers = combineReducers( {
1936
1972
  temporarilyEditingAsBlocks,
1937
1973
  blockVisibility,
1938
1974
  blockEditingModes,
1975
+ styleOverrides,
1939
1976
  removalPromptData,
1940
1977
  blockRemovalRules,
1978
+ openedBlockSettingsMenu,
1941
1979
  } );
1942
1980
 
1943
1981
  function withAutomaticChangeReset( reducer ) {
@@ -245,19 +245,20 @@ export const __unstableGetClientIdsTree = createSelector(
245
245
  * given. Returned ids are ordered first by the order of the ids given, then
246
246
  * by the order that they appear in the editor.
247
247
  *
248
- * @param {Object} state Global application state.
249
- * @param {Array} clientIds Array of blocks to inspect.
248
+ * @param {Object} state Global application state.
249
+ * @param {string|string[]} clientIds Client ID(s) for which descendant blocks are to be returned.
250
250
  *
251
- * @return {Array} ids of descendants.
251
+ * @return {Array} Client IDs of descendants.
252
252
  */
253
253
  export const getClientIdsOfDescendants = createSelector(
254
254
  ( state, clientIds ) => {
255
+ const givenIds = Array.isArray( clientIds ) ? clientIds : [ clientIds ];
255
256
  const collectedIds = [];
256
- for ( const givenId of clientIds ) {
257
+ for ( const givenId of givenIds ) {
257
258
  for ( const descendantId of getBlockOrder( state, givenId ) ) {
258
259
  collectedIds.push(
259
260
  descendantId,
260
- ...getClientIdsOfDescendants( state, [ descendantId ] )
261
+ ...getClientIdsOfDescendants( state, descendantId )
261
262
  );
262
263
  }
263
264
  }
@@ -281,7 +282,7 @@ export const getClientIdsWithDescendants = createSelector(
281
282
  for ( const topLevelId of getBlockOrder( state ) ) {
282
283
  collectedIds.push(
283
284
  topLevelId,
284
- ...getClientIdsOfDescendants( state, [ topLevelId ] )
285
+ ...getClientIdsOfDescendants( state, topLevelId )
285
286
  );
286
287
  }
287
288
  return collectedIds;
@@ -2290,31 +2291,44 @@ const checkAllowListRecursive = ( blocks, allowedBlockTypes ) => {
2290
2291
  return true;
2291
2292
  };
2292
2293
 
2293
- function getUnsyncedPatterns( state ) {
2294
- const reusableBlocks =
2294
+ function getUserPatterns( state ) {
2295
+ const userPatterns =
2295
2296
  state?.settings?.__experimentalReusableBlocks ?? EMPTY_ARRAY;
2296
-
2297
- return reusableBlocks
2298
- .filter(
2299
- ( reusableBlock ) =>
2300
- reusableBlock.wp_pattern_sync_status === 'unsynced'
2301
- )
2302
- .map( ( reusableBlock ) => {
2303
- return {
2304
- name: `core/block/${ reusableBlock.id }`,
2305
- title: reusableBlock.title.raw,
2306
- categories: [ 'custom' ],
2307
- content: reusableBlock.content.raw,
2308
- };
2309
- } );
2297
+ const userPatternCategories =
2298
+ state?.settings?.__experimentalUserPatternCategories ?? [];
2299
+ const categories = new Map();
2300
+ userPatternCategories.forEach( ( userCategory ) =>
2301
+ categories.set( userCategory.id, userCategory )
2302
+ );
2303
+ return userPatterns.map( ( userPattern ) => {
2304
+ return {
2305
+ name: `core/block/${ userPattern.id }`,
2306
+ id: userPattern.id,
2307
+ title: userPattern.title.raw,
2308
+ categories: userPattern.wp_pattern_category.map( ( catId ) =>
2309
+ categories && categories.get( catId )
2310
+ ? categories.get( catId ).slug
2311
+ : catId
2312
+ ),
2313
+ content: userPattern.content.raw,
2314
+ syncStatus: userPattern.wp_pattern_sync_status,
2315
+ };
2316
+ } );
2310
2317
  }
2311
2318
 
2319
+ export const __experimentalUserPatternCategories = createSelector(
2320
+ ( state ) => {
2321
+ return state?.settings?.__experimentalUserPatternCategories;
2322
+ },
2323
+ ( state ) => [ state.settings.__experimentalUserPatternCategories ]
2324
+ );
2325
+
2312
2326
  export const __experimentalGetParsedPattern = createSelector(
2313
2327
  ( state, patternName ) => {
2314
2328
  const patterns = state.settings.__experimentalBlockPatterns;
2315
- const unsyncedPatterns = getUnsyncedPatterns( state );
2329
+ const userPatterns = getUserPatterns( state );
2316
2330
 
2317
- const pattern = [ ...patterns, ...unsyncedPatterns ].find(
2331
+ const pattern = [ ...patterns, ...userPatterns ].find(
2318
2332
  ( { name } ) => name === patternName
2319
2333
  );
2320
2334
  if ( ! pattern ) {
@@ -2330,17 +2344,18 @@ export const __experimentalGetParsedPattern = createSelector(
2330
2344
  ( state ) => [
2331
2345
  state.settings.__experimentalBlockPatterns,
2332
2346
  state.settings.__experimentalReusableBlocks,
2347
+ state?.settings?.__experimentalUserPatternCategories,
2333
2348
  ]
2334
2349
  );
2335
2350
 
2336
2351
  const getAllAllowedPatterns = createSelector(
2337
2352
  ( state ) => {
2338
2353
  const patterns = state.settings.__experimentalBlockPatterns;
2339
- const unsyncedPatterns = getUnsyncedPatterns( state );
2354
+ const userPatterns = getUserPatterns( state );
2340
2355
 
2341
2356
  const { allowedBlockTypes } = getSettings( state );
2342
2357
 
2343
- const parsedPatterns = [ ...patterns, ...unsyncedPatterns ]
2358
+ const parsedPatterns = [ ...userPatterns, ...patterns ]
2344
2359
  .filter( ( { inserter = true } ) => !! inserter )
2345
2360
  .map( ( { name } ) =>
2346
2361
  __experimentalGetParsedPattern( state, name )
@@ -2354,6 +2369,7 @@ const getAllAllowedPatterns = createSelector(
2354
2369
  state.settings.__experimentalBlockPatterns,
2355
2370
  state.settings.__experimentalReusableBlocks,
2356
2371
  state.settings.allowedBlockTypes,
2372
+ state?.settings?.__experimentalUserPatternCategories,
2357
2373
  ]
2358
2374
  );
2359
2375
 
@@ -2941,3 +2957,68 @@ export const getBlockEditingMode = createRegistrySelector(
2941
2957
  return parentMode === 'contentOnly' ? 'default' : parentMode;
2942
2958
  }
2943
2959
  );
2960
+
2961
+ /**
2962
+ * Indicates if a block is ungroupable.
2963
+ * A block is ungroupable if it is a single grouping block with inner blocks.
2964
+ * If a block has an `ungroup` transform, it is also ungroupable, without the
2965
+ * requirement of being the default grouping block.
2966
+ * Additionally a block can only be ungrouped if it has inner blocks and can
2967
+ * be removed.
2968
+ *
2969
+ * @param {Object} state Global application state.
2970
+ * @param {string} clientId Client Id of the block. If not passed the selected block's client id will be used.
2971
+ * @return {boolean} True if the block is ungroupable.
2972
+ */
2973
+ export const isUngroupable = createRegistrySelector(
2974
+ ( select ) =>
2975
+ ( state, clientId = '' ) => {
2976
+ const _clientId = clientId || getSelectedBlockClientId( state );
2977
+ if ( ! _clientId ) {
2978
+ return false;
2979
+ }
2980
+ const { getGroupingBlockName } = select( blocksStore );
2981
+ const block = getBlock( state, _clientId );
2982
+ const groupingBlockName = getGroupingBlockName();
2983
+ const _isUngroupable =
2984
+ block &&
2985
+ ( block.name === groupingBlockName ||
2986
+ getBlockType( block.name )?.transforms?.ungroup ) &&
2987
+ !! block.innerBlocks.length;
2988
+
2989
+ return _isUngroupable && canRemoveBlock( state, _clientId );
2990
+ }
2991
+ );
2992
+
2993
+ /**
2994
+ * Indicates if the provided blocks(by client ids) are groupable.
2995
+ * We need to have at least one block, have a grouping block name set and
2996
+ * be able to remove these blocks.
2997
+ *
2998
+ * @param {Object} state Global application state.
2999
+ * @param {string[]} clientIds Block client ids. If not passed the selected blocks client ids will be used.
3000
+ * @return {boolean} True if the blocks are groupable.
3001
+ */
3002
+ export const isGroupable = createRegistrySelector(
3003
+ ( select ) =>
3004
+ ( state, clientIds = EMPTY_ARRAY ) => {
3005
+ const { getGroupingBlockName } = select( blocksStore );
3006
+ const groupingBlockName = getGroupingBlockName();
3007
+ const _clientIds = clientIds?.length
3008
+ ? clientIds
3009
+ : getSelectedBlockClientIds( state );
3010
+ const rootClientId = _clientIds?.length
3011
+ ? getBlockRootClientId( state, _clientIds[ 0 ] )
3012
+ : undefined;
3013
+ const groupingBlockAvailable = canInsertBlockType(
3014
+ state,
3015
+ groupingBlockName,
3016
+ rootClientId
3017
+ );
3018
+ const _isGroupable = groupingBlockAvailable && _clientIds.length;
3019
+ return (
3020
+ _isGroupable &&
3021
+ canRemoveBlocks( state, _clientIds, rootClientId )
3022
+ );
3023
+ }
3024
+ );