@wordpress/block-editor 16.2.0 → 17.0.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 (328) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/build/components/block-inspector/index.cjs +9 -6
  3. package/build/components/block-inspector/index.cjs.map +2 -2
  4. package/build/components/block-keyboard-shortcuts/index.cjs +201 -0
  5. package/build/components/block-keyboard-shortcuts/index.cjs.map +7 -0
  6. package/build/components/block-list/block.cjs +10 -3
  7. package/build/components/block-list/block.cjs.map +2 -2
  8. package/build/components/block-list/index.cjs +6 -1
  9. package/build/components/block-list/index.cjs.map +2 -2
  10. package/build/components/block-list/use-block-props/use-focus-first-element.cjs +4 -0
  11. package/build/components/block-list/use-block-props/use-focus-first-element.cjs.map +2 -2
  12. package/build/components/block-list/use-block-props/use-selected-block-event-handlers.cjs +6 -7
  13. package/build/components/block-list/use-block-props/use-selected-block-event-handlers.cjs.map +2 -2
  14. package/build/components/block-parent-selector/index.cjs +98 -29
  15. package/build/components/block-parent-selector/index.cjs.map +3 -3
  16. package/build/components/block-popover/inbetween.cjs +2 -2
  17. package/build/components/block-popover/inbetween.cjs.map +2 -2
  18. package/build/components/block-preview/index.cjs +0 -4
  19. package/build/components/block-preview/index.cjs.map +2 -2
  20. package/build/components/block-styles/index.cjs +77 -33
  21. package/build/components/block-styles/index.cjs.map +3 -3
  22. package/build/components/block-visibility/constants.cjs.map +2 -2
  23. package/build/components/child-layout-control/index.cjs.map +2 -2
  24. package/build/components/colors/with-colors.cjs +55 -71
  25. package/build/components/colors/with-colors.cjs.map +2 -2
  26. package/build/components/dimensions-tool/aspect-ratio-tool.cjs +4 -2
  27. package/build/components/dimensions-tool/aspect-ratio-tool.cjs.map +2 -2
  28. package/build/components/dimensions-tool/index.cjs +18 -16
  29. package/build/components/dimensions-tool/index.cjs.map +2 -2
  30. package/build/components/dimensions-tool/utils.cjs +61 -0
  31. package/build/components/dimensions-tool/utils.cjs.map +7 -0
  32. package/build/components/duotone-control/index.cjs +2 -0
  33. package/build/components/duotone-control/index.cjs.map +2 -2
  34. package/build/components/global-styles/advanced-panel.cjs.map +3 -3
  35. package/build/components/global-styles/border-panel.cjs +2 -5
  36. package/build/components/global-styles/border-panel.cjs.map +2 -2
  37. package/build/components/global-styles/color-panel.cjs +14 -2
  38. package/build/components/global-styles/color-panel.cjs.map +2 -2
  39. package/build/components/global-styles/dimensions-panel.cjs +9 -5
  40. package/build/components/global-styles/dimensions-panel.cjs.map +2 -2
  41. package/build/components/global-styles/filters-panel.cjs +12 -8
  42. package/build/components/global-styles/filters-panel.cjs.map +2 -2
  43. package/build/components/global-styles/shadow-panel-components.cjs +16 -11
  44. package/build/components/global-styles/shadow-panel-components.cjs.map +2 -2
  45. package/build/components/global-styles/utils.cjs +9 -0
  46. package/build/components/global-styles/utils.cjs.map +2 -2
  47. package/build/components/inner-blocks/index.cjs +5 -3
  48. package/build/components/inner-blocks/index.cjs.map +2 -2
  49. package/build/components/inserter/block-patterns-explorer/index.cjs +39 -22
  50. package/build/components/inserter/block-patterns-explorer/index.cjs.map +2 -2
  51. package/build/components/inserter/block-patterns-explorer/pattern-explorer-sidebar.cjs +21 -55
  52. package/build/components/inserter/block-patterns-explorer/pattern-explorer-sidebar.cjs.map +2 -2
  53. package/build/components/inserter/block-patterns-explorer/pattern-list.cjs +19 -44
  54. package/build/components/inserter/block-patterns-explorer/pattern-list.cjs.map +3 -3
  55. package/build/components/inserter/hooks/use-insertion-point.cjs +4 -4
  56. package/build/components/inserter/hooks/use-insertion-point.cjs.map +2 -2
  57. package/build/components/inserter/menu.cjs +18 -7
  58. package/build/components/inserter/menu.cjs.map +2 -2
  59. package/build/components/inserter/quick-inserter.cjs +30 -27
  60. package/build/components/inserter/quick-inserter.cjs.map +2 -2
  61. package/build/components/inspector-controls-tabs/styles-tab.cjs +1 -1
  62. package/build/components/inspector-controls-tabs/styles-tab.cjs.map +2 -2
  63. package/build/components/list-view/index.cjs +31 -5
  64. package/build/components/list-view/index.cjs.map +3 -3
  65. package/build/components/list-view/utils.cjs +13 -1
  66. package/build/components/list-view/utils.cjs.map +2 -2
  67. package/build/components/media-placeholder/index.cjs +1 -1
  68. package/build/components/media-placeholder/index.cjs.map +3 -3
  69. package/build/components/provider/index.cjs +5 -1
  70. package/build/components/provider/index.cjs.map +3 -3
  71. package/build/components/publish-date-time-picker/index.cjs +3 -2
  72. package/build/components/publish-date-time-picker/index.cjs.map +2 -2
  73. package/build/components/rich-text/event-listeners/enter.cjs +46 -39
  74. package/build/components/rich-text/event-listeners/enter.cjs.map +2 -2
  75. package/build/components/rich-text/index.cjs +7 -5
  76. package/build/components/rich-text/index.cjs.map +2 -2
  77. package/build/components/rich-text/multiline.cjs +105 -70
  78. package/build/components/rich-text/multiline.cjs.map +3 -3
  79. package/build/components/url-input/index.cjs.map +2 -2
  80. package/build/components/writing-flow/use-input.cjs +65 -13
  81. package/build/components/writing-flow/use-input.cjs.map +3 -3
  82. package/build/hooks/border.cjs +25 -3
  83. package/build/hooks/border.cjs.map +2 -2
  84. package/build/hooks/dimensions.cjs +9 -2
  85. package/build/hooks/dimensions.cjs.map +2 -2
  86. package/build/hooks/duotone.cjs +4 -3
  87. package/build/hooks/duotone.cjs.map +2 -2
  88. package/build/hooks/gap.cjs +8 -2
  89. package/build/hooks/gap.cjs.map +2 -2
  90. package/build/hooks/layout-child.cjs +35 -13
  91. package/build/hooks/layout-child.cjs.map +2 -2
  92. package/build/hooks/layout.cjs +23 -1
  93. package/build/hooks/layout.cjs.map +2 -2
  94. package/build/hooks/states.cjs +7 -4
  95. package/build/hooks/states.cjs.map +2 -2
  96. package/build/layouts/constrained.cjs +8 -1
  97. package/build/layouts/constrained.cjs.map +2 -2
  98. package/build/layouts/flex.cjs +9 -0
  99. package/build/layouts/flex.cjs.map +2 -2
  100. package/build/layouts/flow.cjs +4 -1
  101. package/build/layouts/flow.cjs.map +2 -2
  102. package/build/layouts/grid.cjs +5 -1
  103. package/build/layouts/grid.cjs.map +2 -2
  104. package/build/private-apis.cjs +3 -1
  105. package/build/private-apis.cjs.map +2 -2
  106. package/build/store/actions.cjs +1 -1
  107. package/build/store/actions.cjs.map +2 -2
  108. package/build-module/components/block-inspector/index.mjs +9 -6
  109. package/build-module/components/block-inspector/index.mjs.map +2 -2
  110. package/build-module/components/block-keyboard-shortcuts/index.mjs +173 -0
  111. package/build-module/components/block-keyboard-shortcuts/index.mjs.map +7 -0
  112. package/build-module/components/block-list/block.mjs +10 -3
  113. package/build-module/components/block-list/block.mjs.map +2 -2
  114. package/build-module/components/block-list/index.mjs +6 -1
  115. package/build-module/components/block-list/index.mjs.map +2 -2
  116. package/build-module/components/block-list/use-block-props/use-focus-first-element.mjs +4 -0
  117. package/build-module/components/block-list/use-block-props/use-focus-first-element.mjs.map +2 -2
  118. package/build-module/components/block-list/use-block-props/use-selected-block-event-handlers.mjs +6 -7
  119. package/build-module/components/block-list/use-block-props/use-selected-block-event-handlers.mjs.map +2 -2
  120. package/build-module/components/block-parent-selector/index.mjs +101 -32
  121. package/build-module/components/block-parent-selector/index.mjs.map +2 -2
  122. package/build-module/components/block-popover/inbetween.mjs +2 -2
  123. package/build-module/components/block-popover/inbetween.mjs.map +2 -2
  124. package/build-module/components/block-preview/index.mjs +0 -4
  125. package/build-module/components/block-preview/index.mjs.map +2 -2
  126. package/build-module/components/block-styles/index.mjs +79 -35
  127. package/build-module/components/block-styles/index.mjs.map +2 -2
  128. package/build-module/components/block-visibility/constants.mjs.map +2 -2
  129. package/build-module/components/child-layout-control/index.mjs +5 -5
  130. package/build-module/components/child-layout-control/index.mjs.map +1 -1
  131. package/build-module/components/colors/with-colors.mjs +56 -72
  132. package/build-module/components/colors/with-colors.mjs.map +2 -2
  133. package/build-module/components/dimensions-tool/aspect-ratio-tool.mjs +4 -2
  134. package/build-module/components/dimensions-tool/aspect-ratio-tool.mjs.map +2 -2
  135. package/build-module/components/dimensions-tool/index.mjs +19 -17
  136. package/build-module/components/dimensions-tool/index.mjs.map +2 -2
  137. package/build-module/components/dimensions-tool/utils.mjs +35 -0
  138. package/build-module/components/dimensions-tool/utils.mjs.map +7 -0
  139. package/build-module/components/duotone-control/index.mjs +2 -0
  140. package/build-module/components/duotone-control/index.mjs.map +2 -2
  141. package/build-module/components/global-styles/advanced-panel.mjs +5 -2
  142. package/build-module/components/global-styles/advanced-panel.mjs.map +2 -2
  143. package/build-module/components/global-styles/border-panel.mjs +2 -5
  144. package/build-module/components/global-styles/border-panel.mjs.map +2 -2
  145. package/build-module/components/global-styles/color-panel.mjs +14 -2
  146. package/build-module/components/global-styles/color-panel.mjs.map +2 -2
  147. package/build-module/components/global-styles/dimensions-panel.mjs +9 -5
  148. package/build-module/components/global-styles/dimensions-panel.mjs.map +2 -2
  149. package/build-module/components/global-styles/filters-panel.mjs +16 -9
  150. package/build-module/components/global-styles/filters-panel.mjs.map +2 -2
  151. package/build-module/components/global-styles/shadow-panel-components.mjs +16 -11
  152. package/build-module/components/global-styles/shadow-panel-components.mjs.map +2 -2
  153. package/build-module/components/global-styles/utils.mjs +8 -0
  154. package/build-module/components/global-styles/utils.mjs.map +2 -2
  155. package/build-module/components/inner-blocks/index.mjs +5 -3
  156. package/build-module/components/inner-blocks/index.mjs.map +2 -2
  157. package/build-module/components/inserter/block-patterns-explorer/index.mjs +39 -22
  158. package/build-module/components/inserter/block-patterns-explorer/index.mjs.map +2 -2
  159. package/build-module/components/inserter/block-patterns-explorer/pattern-explorer-sidebar.mjs +22 -56
  160. package/build-module/components/inserter/block-patterns-explorer/pattern-explorer-sidebar.mjs.map +2 -2
  161. package/build-module/components/inserter/block-patterns-explorer/pattern-list.mjs +20 -45
  162. package/build-module/components/inserter/block-patterns-explorer/pattern-list.mjs.map +2 -2
  163. package/build-module/components/inserter/hooks/use-insertion-point.mjs +4 -4
  164. package/build-module/components/inserter/hooks/use-insertion-point.mjs.map +2 -2
  165. package/build-module/components/inserter/menu.mjs +19 -8
  166. package/build-module/components/inserter/menu.mjs.map +2 -2
  167. package/build-module/components/inserter/quick-inserter.mjs +30 -27
  168. package/build-module/components/inserter/quick-inserter.mjs.map +2 -2
  169. package/build-module/components/inspector-controls-tabs/styles-tab.mjs +1 -1
  170. package/build-module/components/inspector-controls-tabs/styles-tab.mjs.map +2 -2
  171. package/build-module/components/list-view/index.mjs +32 -5
  172. package/build-module/components/list-view/index.mjs.map +3 -3
  173. package/build-module/components/list-view/utils.mjs +13 -1
  174. package/build-module/components/list-view/utils.mjs.map +2 -2
  175. package/build-module/components/media-placeholder/index.mjs +3 -3
  176. package/build-module/components/media-placeholder/index.mjs.map +2 -2
  177. package/build-module/components/provider/index.mjs +6 -2
  178. package/build-module/components/provider/index.mjs.map +2 -2
  179. package/build-module/components/publish-date-time-picker/index.mjs +3 -2
  180. package/build-module/components/publish-date-time-picker/index.mjs.map +2 -2
  181. package/build-module/components/rich-text/event-listeners/enter.mjs +46 -39
  182. package/build-module/components/rich-text/event-listeners/enter.mjs.map +2 -2
  183. package/build-module/components/rich-text/index.mjs +7 -5
  184. package/build-module/components/rich-text/index.mjs.map +2 -2
  185. package/build-module/components/rich-text/multiline.mjs +112 -72
  186. package/build-module/components/rich-text/multiline.mjs.map +2 -2
  187. package/build-module/components/url-input/index.mjs +2 -2
  188. package/build-module/components/url-input/index.mjs.map +1 -1
  189. package/build-module/components/writing-flow/use-input.mjs +66 -14
  190. package/build-module/components/writing-flow/use-input.mjs.map +3 -3
  191. package/build-module/hooks/border.mjs +26 -8
  192. package/build-module/hooks/border.mjs.map +2 -2
  193. package/build-module/hooks/dimensions.mjs +9 -2
  194. package/build-module/hooks/dimensions.mjs.map +2 -2
  195. package/build-module/hooks/duotone.mjs +8 -4
  196. package/build-module/hooks/duotone.mjs.map +2 -2
  197. package/build-module/hooks/gap.mjs +6 -1
  198. package/build-module/hooks/gap.mjs.map +2 -2
  199. package/build-module/hooks/layout-child.mjs +36 -13
  200. package/build-module/hooks/layout-child.mjs.map +2 -2
  201. package/build-module/hooks/layout.mjs +22 -1
  202. package/build-module/hooks/layout.mjs.map +2 -2
  203. package/build-module/hooks/states.mjs +8 -5
  204. package/build-module/hooks/states.mjs.map +2 -2
  205. package/build-module/layouts/constrained.mjs +8 -1
  206. package/build-module/layouts/constrained.mjs.map +2 -2
  207. package/build-module/layouts/flex.mjs +9 -0
  208. package/build-module/layouts/flex.mjs.map +2 -2
  209. package/build-module/layouts/flow.mjs +4 -1
  210. package/build-module/layouts/flow.mjs.map +2 -2
  211. package/build-module/layouts/grid.mjs +5 -1
  212. package/build-module/layouts/grid.mjs.map +2 -2
  213. package/build-module/private-apis.mjs +3 -1
  214. package/build-module/private-apis.mjs.map +2 -2
  215. package/build-module/store/actions.mjs +1 -1
  216. package/build-module/store/actions.mjs.map +2 -2
  217. package/build-style/style-rtl.css +108 -71
  218. package/build-style/style.css +108 -71
  219. package/build-types/components/block-visibility/constants.d.ts +4 -3
  220. package/build-types/components/block-visibility/constants.d.ts.map +1 -1
  221. package/package.json +43 -43
  222. package/src/components/background-image-control/README.md +122 -0
  223. package/src/components/block-edit-visually-button/README.md +39 -0
  224. package/src/components/block-editing-mode/README.md +72 -0
  225. package/src/components/block-inspector/index.js +6 -6
  226. package/src/components/block-keyboard-shortcuts/index.js +256 -0
  227. package/src/components/block-list/block.js +7 -0
  228. package/src/components/block-list/index.js +7 -1
  229. package/src/components/block-list/use-block-props/use-focus-first-element.js +5 -0
  230. package/src/components/block-list/use-block-props/use-selected-block-event-handlers.js +6 -8
  231. package/src/components/block-parent-selector/index.js +111 -30
  232. package/src/components/block-popover/README.md +10 -3
  233. package/src/components/block-popover/inbetween.js +8 -2
  234. package/src/components/block-popover/stories/index.story.jsx +143 -0
  235. package/src/components/block-preview/index.js +0 -2
  236. package/src/components/block-styles/index.js +95 -43
  237. package/src/components/block-styles/style.scss +5 -34
  238. package/src/components/block-tools/style.scss +94 -0
  239. package/src/components/block-visibility/constants.ts +4 -3
  240. package/src/components/child-layout-control/index.js +5 -5
  241. package/src/components/color-palette/test/__snapshots__/control.js.snap +3 -29
  242. package/src/components/colors/test/with-colors.js +6 -7
  243. package/src/components/colors/with-colors.js +79 -105
  244. package/src/components/dimensions-tool/aspect-ratio-tool.js +16 -4
  245. package/src/components/dimensions-tool/index.js +34 -22
  246. package/src/components/dimensions-tool/test/index.js +166 -2
  247. package/src/components/dimensions-tool/test/utils.js +51 -0
  248. package/src/components/dimensions-tool/utils.js +67 -0
  249. package/src/components/duotone-control/index.js +2 -0
  250. package/src/components/duotone-control/test/index.js +100 -0
  251. package/src/components/global-styles/advanced-panel.js +5 -2
  252. package/src/components/global-styles/border-panel.js +11 -9
  253. package/src/components/global-styles/color-panel.js +13 -1
  254. package/src/components/global-styles/dimensions-panel.js +17 -5
  255. package/src/components/global-styles/filters-panel.js +24 -10
  256. package/src/components/global-styles/shadow-panel-components.js +38 -11
  257. package/src/components/global-styles/test/border-panel.js +230 -0
  258. package/src/components/global-styles/test/color-panel.js +24 -0
  259. package/src/components/global-styles/test/dimensions-panel.js +98 -7
  260. package/src/components/global-styles/test/filters-panel.js +84 -0
  261. package/src/components/global-styles/test/utils.js +30 -0
  262. package/src/components/global-styles/utils.js +23 -0
  263. package/src/components/inner-blocks/index.js +11 -2
  264. package/src/components/inner-blocks/stories/index.story.jsx +246 -0
  265. package/src/components/inserter/block-patterns-explorer/index.js +24 -11
  266. package/src/components/inserter/block-patterns-explorer/pattern-explorer-sidebar.js +18 -56
  267. package/src/components/inserter/block-patterns-explorer/pattern-list.js +22 -47
  268. package/src/components/inserter/hooks/use-insertion-point.js +9 -4
  269. package/src/components/inserter/menu.js +23 -10
  270. package/src/components/inserter/quick-inserter.js +15 -13
  271. package/src/components/inserter/style.scss +44 -62
  272. package/src/components/inspector-controls-tabs/README.md +92 -0
  273. package/src/components/inspector-controls-tabs/styles-tab.js +1 -1
  274. package/src/components/link-control/test/index.js +5 -0
  275. package/src/components/list-view/index.js +50 -7
  276. package/src/components/list-view/utils.js +16 -1
  277. package/src/components/media-placeholder/index.js +9 -4
  278. package/src/components/plain-text/stories/index.story.jsx +3 -0
  279. package/src/components/provider/index.js +7 -1
  280. package/src/components/publish-date-time-picker/README.md +10 -0
  281. package/src/components/publish-date-time-picker/index.js +17 -14
  282. package/src/components/rich-text/event-listeners/enter.js +58 -45
  283. package/src/components/rich-text/index.js +9 -4
  284. package/src/components/rich-text/multiline.js +126 -86
  285. package/src/components/url-input/index.js +2 -2
  286. package/src/components/url-input/test/fixtures/validated-input-control-deprecation.js +27 -0
  287. package/src/components/url-input/test/index.js +5 -0
  288. package/src/components/url-popover/README.md +7 -0
  289. package/src/components/url-popover/stories/index.story.jsx +133 -47
  290. package/src/components/writing-flow/use-input.js +105 -15
  291. package/src/hooks/border.js +27 -8
  292. package/src/hooks/dimensions.js +8 -1
  293. package/src/hooks/duotone.js +23 -7
  294. package/src/hooks/gap.js +16 -0
  295. package/src/hooks/layout-child.js +41 -9
  296. package/src/hooks/layout.js +117 -71
  297. package/src/hooks/states.js +8 -5
  298. package/src/hooks/test/gap.js +31 -1
  299. package/src/hooks/test/layout-child.js +60 -1
  300. package/src/hooks/test/layout.js +27 -0
  301. package/src/layouts/constrained.js +9 -1
  302. package/src/layouts/flex.js +15 -0
  303. package/src/layouts/flow.js +4 -1
  304. package/src/layouts/grid.js +9 -1
  305. package/src/layouts/test/constrained.js +26 -0
  306. package/src/layouts/test/flow.js +26 -0
  307. package/src/layouts/test/grid.js +46 -0
  308. package/src/private-apis.js +2 -0
  309. package/src/store/actions.js +14 -1
  310. package/build/components/floating-toolbar/nav-up-icon.cjs +0 -52
  311. package/build/components/floating-toolbar/nav-up-icon.cjs.map +0 -7
  312. package/build/components/gradients/with-gradient.cjs +0 -36
  313. package/build/components/gradients/with-gradient.cjs.map +0 -7
  314. package/build/components/inserter-button/sparkles.cjs +0 -36
  315. package/build/components/inserter-button/sparkles.cjs.map +0 -7
  316. package/build-module/components/floating-toolbar/nav-up-icon.mjs +0 -31
  317. package/build-module/components/floating-toolbar/nav-up-icon.mjs.map +0 -7
  318. package/build-module/components/gradients/with-gradient.mjs +0 -11
  319. package/build-module/components/gradients/with-gradient.mjs.map +0 -7
  320. package/build-module/components/inserter-button/sparkles.mjs +0 -15
  321. package/build-module/components/inserter-button/sparkles.mjs.map +0 -7
  322. package/build-style/default-editor-styles-rtl.css +0 -68
  323. package/build-style/default-editor-styles.css +0 -68
  324. package/src/components/floating-toolbar/nav-up-icon.js +0 -22
  325. package/src/components/gradients/with-gradient.js +0 -9
  326. package/src/components/inserter-button/README.md +0 -62
  327. package/src/components/inserter-button/sparkles.js +0 -12
  328. package/src/default-editor-styles.scss +0 -25
@@ -1,9 +1,12 @@
1
- import { ToolbarButton } from '@wordpress/components';
1
+ import { ToolbarButton, ToolbarGroup } from '@wordpress/components';
2
2
  import { useSelect, useDispatch } from '@wordpress/data';
3
- import { __, sprintf } from '@wordpress/i18n';
3
+ import { __, _x, sprintf } from '@wordpress/i18n';
4
4
  import { useRef } from '@wordpress/element';
5
+ import { getBlockType, hasBlockSupport } from '@wordpress/blocks';
6
+ import { plus } from '@wordpress/icons';
5
7
  import useBlockDisplayInformation from '../use-block-display-information';
6
8
  import BlockIcon from '../block-icon';
9
+ import Inserter from '../inserter';
7
10
  import { useShowHoveredOrFocusedGestures } from '../block-toolbar/utils';
8
11
  import { store as blockEditorStore } from '../../store';
9
12
  import { unlock } from '../../lock-unlock';
@@ -16,23 +19,51 @@ import { unlock } from '../../lock-unlock';
16
19
  */
17
20
  export default function BlockParentSelector() {
18
21
  const { selectBlock } = useDispatch( blockEditorStore );
19
- const { parentClientId } = useSelect( ( select ) => {
20
- const {
21
- getBlockParents,
22
- getSelectedBlockClientIds,
23
- getParentSectionBlock,
24
- } = unlock( select( blockEditorStore ) );
25
- // Not getSelectedBlockClientId: a text selection crossing into a
26
- // nested block resolves to the ancestor alone, but its selection
27
- // start and end differ.
28
- const [ selectedBlockClientId ] = getSelectedBlockClientIds();
29
- const parentSection = getParentSectionBlock( selectedBlockClientId );
30
- const parents = getBlockParents( selectedBlockClientId );
31
- const _parentClientId = parentSection ?? parents[ parents.length - 1 ];
32
- return {
33
- parentClientId: _parentClientId,
34
- };
35
- }, [] );
22
+ const { parentClientId, nextSiblingClientId, showInserter } = useSelect(
23
+ ( select ) => {
24
+ const {
25
+ getBlockParents,
26
+ getSelectedBlockClientIds,
27
+ getParentSectionBlock,
28
+ getBlockName,
29
+ getNextBlockClientId,
30
+ } = unlock( select( blockEditorStore ) );
31
+ // Not getSelectedBlockClientId: a text selection crossing into a
32
+ // nested block resolves to the ancestor alone, but its selection
33
+ // start and end differ.
34
+ const [ selectedBlockClientId ] = getSelectedBlockClientIds();
35
+ const parentSection = getParentSectionBlock(
36
+ selectedBlockClientId
37
+ );
38
+ const parents = getBlockParents( selectedBlockClientId );
39
+ const immediateParentClientId = parents[ parents.length - 1 ];
40
+ const _parentClientId = parentSection ?? immediateParentClientId;
41
+ const parentBlockType = getBlockType(
42
+ getBlockName( _parentClientId )
43
+ );
44
+ // A wrapper that merges with the text flow (list, quote) grows
45
+ // by typing: Enter continues it, and users know that. Any
46
+ // other parent gets a plus button to add a child; the Inserter
47
+ // hides itself when nothing is insertable.
48
+ const isTextFlowWrapper =
49
+ parentBlockType?.merge ||
50
+ hasBlockSupport( parentBlockType, '__experimentalOnMerge' );
51
+ return {
52
+ parentClientId: _parentClientId,
53
+ nextSiblingClientId: getNextBlockClientId(
54
+ selectedBlockClientId
55
+ ),
56
+ // When the shown parent is a section further up the tree
57
+ // rather than the direct parent, its content is locked and
58
+ // nothing can be inserted, so no button.
59
+ showInserter:
60
+ !! _parentClientId &&
61
+ _parentClientId === immediateParentClientId &&
62
+ ! isTextFlowWrapper,
63
+ };
64
+ },
65
+ []
66
+ );
36
67
  const blockInformation = useBlockDisplayInformation( parentClientId );
37
68
 
38
69
  // Allows highlighting the parent block outline when focusing or hovering
@@ -43,6 +74,20 @@ export default function BlockParentSelector() {
43
74
  highlightParent: true,
44
75
  } );
45
76
 
77
+ const parentButton = (
78
+ <ToolbarButton
79
+ className="block-editor-block-parent-selector__button"
80
+ onClick={ () => selectBlock( parentClientId ) }
81
+ label={ sprintf(
82
+ /* translators: %s: Name of the block's parent. */
83
+ __( 'Select parent block: %s' ),
84
+ blockInformation?.title
85
+ ) }
86
+ showTooltip
87
+ icon={ <BlockIcon icon={ blockInformation?.icon } /> }
88
+ />
89
+ );
90
+
46
91
  return (
47
92
  <div
48
93
  className="block-editor-block-parent-selector"
@@ -50,17 +95,53 @@ export default function BlockParentSelector() {
50
95
  ref={ nodeRef }
51
96
  { ...showHoveredOrFocusedGestures }
52
97
  >
53
- <ToolbarButton
54
- className="block-editor-block-parent-selector__button"
55
- onClick={ () => selectBlock( parentClientId ) }
56
- label={ sprintf(
57
- /* translators: %s: Name of the block's parent. */
58
- __( 'Select parent block: %s' ),
59
- blockInformation?.title
60
- ) }
61
- showTooltip
62
- icon={ <BlockIcon icon={ blockInformation?.icon } /> }
63
- />
98
+ { ! showInserter && parentButton }
99
+ { showInserter && (
100
+ // A real toolbar group, so the buttons get the standard
101
+ // toolbar sizing, and the group overlaps the container
102
+ // border the way toolbar groups overlap the toolbar box.
103
+ <ToolbarGroup>
104
+ { parentButton }
105
+ <Inserter
106
+ position="bottom right"
107
+ rootClientId={ parentClientId }
108
+ clientId={ nextSiblingClientId }
109
+ isAppender={ ! nextSiblingClientId }
110
+ __experimentalIsQuick
111
+ renderToggle={ ( {
112
+ onToggle,
113
+ isOpen,
114
+ disabled,
115
+ blockTitle,
116
+ hasSingleBlockType,
117
+ } ) => (
118
+ <ToolbarButton
119
+ className="block-editor-block-parent-selector__inserter"
120
+ onClick={ onToggle }
121
+ aria-expanded={ isOpen }
122
+ disabled={ disabled }
123
+ label={
124
+ hasSingleBlockType
125
+ ? sprintf(
126
+ // translators: %s: the name of the block when there is only one
127
+ _x(
128
+ 'Add %s',
129
+ 'directly add the only allowed block'
130
+ ),
131
+ blockTitle.toLowerCase()
132
+ )
133
+ : _x(
134
+ 'Add block',
135
+ 'Generic label for block inserter button'
136
+ )
137
+ }
138
+ showTooltip
139
+ icon={ plus }
140
+ />
141
+ ) }
142
+ />
143
+ </ToolbarGroup>
144
+ ) }
64
145
  </div>
65
146
  );
66
147
  }
@@ -26,9 +26,16 @@ The client ID of the block representing the bottom position of the popover.
26
26
 
27
27
  This determines whether the block popover always shifts into the viewport or remains at its original position. See FloatingUI for more details on shift.
28
28
 
29
- - Type: `Boolean`
30
- - Required: No
31
- - Default: `true`
29
+ - Type: `Boolean`
30
+ - Required: No
31
+ - Default: `true`
32
+
33
+ #### children
34
+
35
+ The content rendered inside the popover.
36
+
37
+ - Type: `ReactNode`
38
+ - Required: No
32
39
 
33
40
  ## BlockPopoverInbetween - Private Component
34
41
 
@@ -101,12 +101,18 @@ function BlockPopoverInbetween( {
101
101
  } else if ( isVertical ) {
102
102
  // vertical
103
103
  top = previousRect ? previousRect.bottom : nextRect.top;
104
- width = previousRect ? previousRect.width : nextRect.width;
104
+ width =
105
+ nextRect && previousRect
106
+ ? ( previousRect.width + nextRect.width ) / 2
107
+ : ( previousRect || nextRect ).width;
105
108
  height =
106
109
  nextRect && previousRect
107
110
  ? nextRect.top - previousRect.bottom
108
111
  : 0;
109
- left = previousRect ? previousRect.left : nextRect.left;
112
+ left =
113
+ nextRect && previousRect
114
+ ? ( previousRect.left + nextRect.left ) / 2
115
+ : ( previousRect || nextRect ).left;
110
116
  } else {
111
117
  top = previousRect ? previousRect.top : nextRect.top;
112
118
  height = previousRect
@@ -0,0 +1,143 @@
1
+ import {
2
+ createBlock,
3
+ registerBlockType,
4
+ getBlockType,
5
+ } from '@wordpress/blocks';
6
+ import { useMemo } from '@wordpress/element';
7
+ import BlockPopover from '../';
8
+ import BlockList from '../../block-list';
9
+ import { ExperimentalBlockEditorProvider } from '../../provider';
10
+
11
+ // A minimal block type, so that the story doesn't depend on the block library.
12
+ const BLOCK_NAME = 'storybook/example';
13
+ const BLOCK_LABELS = [ 'First', 'Second', 'Third' ];
14
+
15
+ // The client IDs are hardcoded instead of using the generated ones, so that a
16
+ // client ID picked in the controls is still valid after a page reload.
17
+ const clientIds = BLOCK_LABELS.map(
18
+ ( label, index ) => `example-block-${ index + 1 }`
19
+ );
20
+
21
+ // Registered when the story renders rather than when this file loads, so that
22
+ // the example block type doesn't leak into the registry shared with the other
23
+ // stories.
24
+ function useExampleBlocks() {
25
+ return useMemo( () => {
26
+ if ( ! getBlockType( BLOCK_NAME ) ) {
27
+ registerBlockType( BLOCK_NAME, {
28
+ title: 'Example',
29
+ category: 'text',
30
+ attributes: {
31
+ content: { type: 'string' },
32
+ },
33
+ edit: ( { attributes } ) => attributes.content,
34
+ save: () => null,
35
+ } );
36
+ }
37
+
38
+ return BLOCK_LABELS.map( ( label, index ) => ( {
39
+ ...createBlock( BLOCK_NAME, {
40
+ content: `${ label } example block.`,
41
+ } ),
42
+ clientId: clientIds[ index ],
43
+ } ) );
44
+ }, [] );
45
+ }
46
+
47
+ // Makes the blocks and the popover distinguishable from each other, so that it
48
+ // is easier to see which block the popover is anchored to.
49
+ const storyStyles = `
50
+ .block-popover-story {
51
+ position: relative;
52
+ padding: 48px 0;
53
+ }
54
+ .block-popover-story .block-editor-block-list__block {
55
+ border: 1px dashed #949494;
56
+ padding: 8px;
57
+ margin-bottom: 16px;
58
+ }
59
+ .block-popover-story .block-editor-block-popover .components-popover__content {
60
+ background: #fff;
61
+ border: 1px solid #1e1e1e;
62
+ padding: 8px;
63
+ }
64
+ `;
65
+
66
+ const clientIdLabels = Object.fromEntries(
67
+ clientIds.map( ( clientId, index ) => [ clientId, `Block ${ index + 1 }` ] )
68
+ );
69
+
70
+ const meta = {
71
+ title: 'BlockEditor/BlockPopover',
72
+ component: BlockPopover,
73
+ parameters: {
74
+ docs: {
75
+ canvas: { sourceState: 'shown' },
76
+ description: {
77
+ component:
78
+ "BlockPopover renders editor UI by the block in a popover, positioned outside the canvas so that it doesn't interfere with the block list layout. The popover is anchored to the block matching `clientId`, so that block has to be rendered by a block list within a block editor provider. When a `bottomClientId` is passed as well, the popover is anchored to the area covered by both blocks.",
79
+ },
80
+ },
81
+ },
82
+ decorators: [
83
+ ( Story ) => {
84
+ const blocks = useExampleBlocks();
85
+
86
+ return (
87
+ <ExperimentalBlockEditorProvider value={ blocks }>
88
+ <style>{ storyStyles }</style>
89
+ <div className="block-popover-story">
90
+ <BlockList />
91
+ <Story />
92
+ </div>
93
+ </ExperimentalBlockEditorProvider>
94
+ );
95
+ },
96
+ ],
97
+ argTypes: {
98
+ clientId: {
99
+ control: { type: 'select', labels: clientIdLabels },
100
+ options: clientIds,
101
+ description:
102
+ 'The client ID of the block representing the top position of the popover.',
103
+ type: { name: 'string', required: true },
104
+ table: {
105
+ type: { summary: 'string' },
106
+ },
107
+ },
108
+ bottomClientId: {
109
+ control: { type: 'select', labels: clientIdLabels },
110
+ options: clientIds,
111
+ description:
112
+ 'The client ID of the block representing the bottom position of the popover.',
113
+ table: {
114
+ type: { summary: 'string' },
115
+ },
116
+ },
117
+ shift: {
118
+ control: { type: 'boolean' },
119
+ description:
120
+ 'Determines whether the block popover always shifts into the viewport or remains at its original position.',
121
+ table: {
122
+ type: { summary: 'boolean' },
123
+ defaultValue: { summary: 'true' },
124
+ },
125
+ },
126
+ children: {
127
+ control: { type: 'text' },
128
+ description: 'The content rendered inside the popover.',
129
+ table: {
130
+ type: { summary: 'ReactNode' },
131
+ },
132
+ },
133
+ },
134
+ };
135
+
136
+ export default meta;
137
+
138
+ export const Default = {
139
+ args: {
140
+ clientId: clientIds[ 1 ],
141
+ children: 'This is a block popover example.',
142
+ },
143
+ };
@@ -48,7 +48,6 @@ export function BlockPreview( {
48
48
  const settings = useMemo(
49
49
  () => ( {
50
50
  ...originalSettings,
51
- focusMode: false, // Disable "Spotlight mode".
52
51
  isPreviewMode: true,
53
52
  } ),
54
53
  [ originalSettings ]
@@ -117,7 +116,6 @@ export function useBlockPreview( { blocks, props = {}, layout } ) {
117
116
  () => ( {
118
117
  ...originalSettings,
119
118
  styles: undefined, // Clear styles included by the parent settings, as they are already output by the parent's EditorStyles.
120
- focusMode: false, // Disable "Spotlight mode".
121
119
  isPreviewMode: true,
122
120
  } ),
123
121
  [ originalSettings ]
@@ -1,13 +1,14 @@
1
- import clsx from 'clsx';
2
1
  import { useState, useMemo } from '@wordpress/element';
3
2
  import { useSelect } from '@wordpress/data';
4
- import { debounce } from '@wordpress/compose';
3
+ import { debounce, useInstanceId } from '@wordpress/compose';
5
4
  import {
6
- Button,
5
+ Composite,
7
6
  __experimentalTruncate as Truncate,
8
7
  __experimentalToolsPanel as ToolsPanel,
9
8
  __experimentalToolsPanelItem as ToolsPanelItem,
10
9
  } from '@wordpress/components';
10
+ // eslint-disable-next-line @wordpress/use-recommended-components
11
+ import { Button } from '@wordpress/ui';
11
12
  import { __ } from '@wordpress/i18n';
12
13
  import PreviewBlockPopover from '../block-switcher/preview-block-popover';
13
14
  import useStylesForBlocks from './use-styles-for-block';
@@ -17,6 +18,9 @@ import { store as blockEditorStore } from '../../store';
17
18
 
18
19
  const noop = () => {};
19
20
 
21
+ const getCompositeItemId = ( instanceId, style ) =>
22
+ `${ instanceId }-${ style.name }`;
23
+
20
24
  // Block Styles component for the Settings Sidebar.
21
25
  function BlockStyles( { clientId, onSwitch = noop, onHoverClassName = noop } ) {
22
26
  const canEdit = useSelect(
@@ -36,6 +40,18 @@ function BlockStyles( { clientId, onSwitch = noop, onHoverClassName = noop } ) {
36
40
  const [ hoveredStyle, setHoveredStyle ] = useState( null );
37
41
  const [ blockStylesAnchor, setBlockStylesAnchor ] = useState( null );
38
42
  const dropdownMenuProps = useToolsPanelDropdownMenuProps();
43
+ const instanceId = useInstanceId(
44
+ BlockStyles,
45
+ 'block-editor-block-styles'
46
+ );
47
+
48
+ const styleRows = useMemo( () => {
49
+ const rows = [];
50
+ for ( let i = 0; i < ( stylesToRender?.length ?? 0 ); i += 2 ) {
51
+ rows.push( stylesToRender.slice( i, i + 2 ) );
52
+ }
53
+ return rows;
54
+ }, [ stylesToRender ] );
39
55
 
40
56
  const previewBlocks = useMemo( () => {
41
57
  if ( ! hoveredStyle || ! genericPreviewBlock ) {
@@ -79,6 +95,16 @@ function BlockStyles( { clientId, onSwitch = noop, onHoverClassName = noop } ) {
79
95
  onHoverClassName( item?.name ?? null );
80
96
  };
81
97
 
98
+ const onSetActiveId = ( nextActiveId ) => {
99
+ const nextStyle = stylesToRender.find(
100
+ ( style ) =>
101
+ getCompositeItemId( instanceId, style ) === nextActiveId
102
+ );
103
+ if ( nextStyle && nextStyle.name !== activeStyle.name ) {
104
+ onSelectStylePreview( nextStyle );
105
+ }
106
+ };
107
+
82
108
  const defaultStyle = getDefaultStyle( stylesToRender );
83
109
 
84
110
  const hasValue = () => {
@@ -108,48 +134,74 @@ function BlockStyles( { clientId, onSwitch = noop, onHoverClassName = noop } ) {
108
134
  ref={ setBlockStylesAnchor }
109
135
  className="block-editor-block-styles"
110
136
  >
111
- <div className="block-editor-block-styles__variants">
112
- { stylesToRender.map( ( style ) => {
113
- const buttonText = style.label || style.name;
114
-
115
- return (
116
- <Button
117
- __next40pxDefaultSize
118
- className={ clsx(
119
- 'block-editor-block-styles__item',
120
- {
121
- 'is-active':
122
- activeStyle.name === style.name,
137
+ <Composite
138
+ role="radiogroup"
139
+ aria-label={ __( 'Styles' ) }
140
+ className="block-editor-block-styles__variants"
141
+ activeId={ getCompositeItemId(
142
+ instanceId,
143
+ activeStyle
144
+ ) }
145
+ setActiveId={ onSetActiveId }
146
+ focusLoop
147
+ focusWrap
148
+ focusShift
149
+ >
150
+ { styleRows.map( ( row, rowIndex ) => (
151
+ <Composite.Row
152
+ key={ rowIndex }
153
+ className="block-editor-block-styles__row"
154
+ >
155
+ { row.map( ( style ) => (
156
+ <Composite.Item
157
+ key={ style.name }
158
+ id={ getCompositeItemId(
159
+ instanceId,
160
+ style
161
+ ) }
162
+ render={
163
+ <Button
164
+ className="block-editor-block-styles__item"
165
+ tone="neutral"
166
+ variant={
167
+ activeStyle.name ===
168
+ style.name
169
+ ? 'solid'
170
+ : 'outline'
171
+ }
172
+ />
173
+ }
174
+ role="radio"
175
+ aria-checked={
176
+ activeStyle.name === style.name
177
+ }
178
+ onMouseEnter={ () =>
179
+ styleItemHandler( style )
180
+ }
181
+ onFocus={ () =>
182
+ styleItemHandler( style )
183
+ }
184
+ onMouseLeave={ () =>
185
+ styleItemHandler( null )
186
+ }
187
+ onBlur={ () =>
188
+ styleItemHandler( null )
189
+ }
190
+ onClick={ () =>
191
+ onSelectStylePreview( style )
123
192
  }
124
- ) }
125
- key={ style.name }
126
- variant="secondary"
127
- label={ buttonText }
128
- onMouseEnter={ () =>
129
- styleItemHandler( style )
130
- }
131
- onFocus={ () => styleItemHandler( style ) }
132
- onMouseLeave={ () =>
133
- styleItemHandler( null )
134
- }
135
- onBlur={ () => styleItemHandler( null ) }
136
- onClick={ () =>
137
- onSelectStylePreview( style )
138
- }
139
- aria-current={
140
- activeStyle.name === style.name
141
- }
142
- >
143
- <Truncate
144
- numberOfLines={ 1 }
145
- className="block-editor-block-styles__item-text"
146
193
  >
147
- { buttonText }
148
- </Truncate>
149
- </Button>
150
- );
151
- } ) }
152
- </div>
194
+ <Truncate
195
+ numberOfLines={ 3 }
196
+ className="block-editor-block-styles__item-text"
197
+ >
198
+ { style.label || style.name }
199
+ </Truncate>
200
+ </Composite.Item>
201
+ ) ) }
202
+ </Composite.Row>
203
+ ) ) }
204
+ </Composite>
153
205
  { previewBlocks && (
154
206
  <PreviewBlockPopover
155
207
  blocks={ previewBlocks }
@@ -1,6 +1,5 @@
1
1
  @use "@wordpress/base-styles/mixins" as *;
2
2
  @use "@wordpress/base-styles/variables" as *;
3
- @use "@wordpress/base-styles/colors" as *;
4
3
  @use "@wordpress/base-styles/z-index" as *;
5
4
 
6
5
  .block-editor-block-styles__preview-panel {
@@ -23,44 +22,16 @@
23
22
  }
24
23
 
25
24
  .block-editor-block-styles__variants {
26
- display: flex;
27
- flex-wrap: wrap;
28
- justify-content: space-between;
25
+ display: grid;
29
26
  gap: $grid-unit-10;
30
27
 
31
- button.components-button.block-editor-block-styles__item {
32
- color: $gray-900;
33
- border-color: $gray-300;
34
- display: inline-block;
35
- width: calc(50% - #{$grid-unit-05});
36
-
37
- &:hover {
38
- color: var(--wp-admin-theme-color);
39
- box-shadow: inset 0 0 0 $border-width $gray-300;
40
- }
41
-
42
- &.is-active,
43
- &.is-active:hover {
44
- background-color: $gray-900;
45
- box-shadow: none;
46
- }
47
-
48
- &.is-active .block-editor-block-styles__item-text,
49
- &.is-active:hover .block-editor-block-styles__item-text {
50
- color: $white;
51
- }
52
-
53
- &:focus,
54
- &.is-active:focus {
55
- @include outset-ring__focus();
56
- }
28
+ .block-editor-block-styles__row {
29
+ display: grid;
30
+ grid-template-columns: repeat(2, minmax(0, 1fr));
31
+ gap: $grid-unit-10;
57
32
  }
58
33
 
59
34
  .block-editor-block-styles__item-text {
60
- word-break: break-all;
61
- // The Button component is white-space: nowrap, and that won't work with line-clamp.
62
- white-space: normal;
63
-
64
35
  // Without this, the ellipsis can sometimes be partially hidden by the Button padding.
65
36
  text-align: start;
66
37
  text-align-last: center;