@wordpress/edit-site 4.7.0 → 4.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 (248) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/build/components/add-new-template/add-custom-generic-template-modal.js +84 -0
  3. package/build/components/add-new-template/add-custom-generic-template-modal.js.map +1 -0
  4. package/build/components/add-new-template/add-custom-template-modal.js +224 -0
  5. package/build/components/add-new-template/add-custom-template-modal.js.map +1 -0
  6. package/build/components/add-new-template/new-template.js +94 -33
  7. package/build/components/add-new-template/new-template.js.map +1 -1
  8. package/build/components/add-new-template/utils.js +405 -0
  9. package/build/components/add-new-template/utils.js.map +1 -0
  10. package/build/components/block-editor/block-inspector-button.js.map +1 -1
  11. package/build/components/block-editor/index.js.map +1 -1
  12. package/build/components/code-editor/index.js +17 -4
  13. package/build/components/code-editor/index.js.map +1 -1
  14. package/build/components/edit-template-part-menu-button/index.js.map +1 -1
  15. package/build/components/editor/index.js +16 -0
  16. package/build/components/editor/index.js.map +1 -1
  17. package/build/components/error-boundary/index.js +6 -0
  18. package/build/components/error-boundary/index.js.map +1 -1
  19. package/build/components/global-styles/context-menu.js +6 -3
  20. package/build/components/global-styles/context-menu.js.map +1 -1
  21. package/build/components/global-styles/dimensions-panel.js +2 -6
  22. package/build/components/global-styles/dimensions-panel.js.map +1 -1
  23. package/build/components/global-styles/global-styles-provider.js +4 -2
  24. package/build/components/global-styles/global-styles-provider.js.map +1 -1
  25. package/build/components/global-styles/gradients-palette-panel.js +3 -7
  26. package/build/components/global-styles/gradients-palette-panel.js.map +1 -1
  27. package/build/components/global-styles/hooks.js +11 -2
  28. package/build/components/global-styles/hooks.js.map +1 -1
  29. package/build/components/global-styles/palette.js +2 -1
  30. package/build/components/global-styles/palette.js.map +1 -1
  31. package/build/components/global-styles/screen-block-list.js +4 -1
  32. package/build/components/global-styles/screen-block-list.js.map +1 -1
  33. package/build/components/global-styles/screen-button-color.js +80 -0
  34. package/build/components/global-styles/screen-button-color.js.map +1 -0
  35. package/build/components/global-styles/screen-color-palette.js +13 -17
  36. package/build/components/global-styles/screen-color-palette.js.map +1 -1
  37. package/build/components/global-styles/screen-colors.js +56 -8
  38. package/build/components/global-styles/screen-colors.js.map +1 -1
  39. package/build/components/global-styles/screen-link-color.js +48 -14
  40. package/build/components/global-styles/screen-link-color.js.map +1 -1
  41. package/build/components/global-styles/screen-root.js +4 -2
  42. package/build/components/global-styles/screen-root.js.map +1 -1
  43. package/build/components/global-styles/screen-style-variations.js +9 -1
  44. package/build/components/global-styles/screen-style-variations.js.map +1 -1
  45. package/build/components/global-styles/screen-typography-element.js +4 -0
  46. package/build/components/global-styles/screen-typography-element.js.map +1 -1
  47. package/build/components/global-styles/screen-typography.js +9 -1
  48. package/build/components/global-styles/screen-typography.js.map +1 -1
  49. package/build/components/global-styles/ui.js +11 -0
  50. package/build/components/global-styles/ui.js.map +1 -1
  51. package/build/components/global-styles/use-global-styles-output.js +199 -30
  52. package/build/components/global-styles/use-global-styles-output.js.map +1 -1
  53. package/build/components/global-styles/utils.js +4 -2
  54. package/build/components/global-styles/utils.js.map +1 -1
  55. package/build/components/header/index.js +28 -10
  56. package/build/components/header/index.js.map +1 -1
  57. package/build/components/header/mode-switcher/index.js.map +1 -1
  58. package/build/components/header/more-menu/copy-content-menu-item.js +1 -1
  59. package/build/components/header/more-menu/copy-content-menu-item.js.map +1 -1
  60. package/build/components/header/more-menu/site-export.js +4 -1
  61. package/build/components/header/more-menu/site-export.js.map +1 -1
  62. package/build/components/header/undo-redo/redo.js +13 -4
  63. package/build/components/header/undo-redo/redo.js.map +1 -1
  64. package/build/components/header/undo-redo/undo.js +13 -4
  65. package/build/components/header/undo-redo/undo.js.map +1 -1
  66. package/build/components/keyboard-shortcut-help-modal/config.js +17 -0
  67. package/build/components/keyboard-shortcut-help-modal/config.js.map +1 -1
  68. package/build/components/keyboard-shortcut-help-modal/index.js +1 -3
  69. package/build/components/keyboard-shortcut-help-modal/index.js.map +1 -1
  70. package/build/components/keyboard-shortcuts/index.js.map +1 -1
  71. package/build/components/list/actions/index.js.map +1 -1
  72. package/build/components/list/actions/rename-menu-item.js.map +1 -1
  73. package/build/components/list/added-by.js.map +1 -1
  74. package/build/components/navigation-sidebar/index.js.map +1 -1
  75. package/build/components/save-button/index.js.map +1 -1
  76. package/build/components/sidebar/index.js.map +1 -1
  77. package/build/components/sidebar/navigation-menu-sidebar/navigation-inspector.js.map +1 -1
  78. package/build/components/sidebar/template-card/index.js +19 -7
  79. package/build/components/sidebar/template-card/index.js.map +1 -1
  80. package/build/components/sidebar/template-card/template-actions.js +64 -0
  81. package/build/components/sidebar/template-card/template-actions.js.map +1 -0
  82. package/build/components/sidebar/template-card/template-areas.js.map +1 -1
  83. package/build/components/template-details/edit-template-title.js +11 -3
  84. package/build/components/template-details/edit-template-title.js.map +1 -1
  85. package/build/components/template-details/index.js +1 -20
  86. package/build/components/template-details/index.js.map +1 -1
  87. package/build/components/template-details/template-areas.js.map +1 -1
  88. package/build/components/template-part-converter/index.js.map +1 -1
  89. package/build/components/url-query-controller/index.js.map +1 -1
  90. package/build/store/actions.js.map +1 -1
  91. package/build/store/selectors.js +4 -1
  92. package/build/store/selectors.js.map +1 -1
  93. package/build-module/components/add-new-template/add-custom-generic-template-modal.js +77 -0
  94. package/build-module/components/add-new-template/add-custom-generic-template-modal.js.map +1 -0
  95. package/build-module/components/add-new-template/add-custom-template-modal.js +209 -0
  96. package/build-module/components/add-new-template/add-custom-template-modal.js.map +1 -0
  97. package/build-module/components/add-new-template/new-template.js +93 -34
  98. package/build-module/components/add-new-template/new-template.js.map +1 -1
  99. package/build-module/components/add-new-template/utils.js +365 -0
  100. package/build-module/components/add-new-template/utils.js.map +1 -0
  101. package/build-module/components/block-editor/block-inspector-button.js.map +1 -1
  102. package/build-module/components/block-editor/index.js.map +1 -1
  103. package/build-module/components/code-editor/index.js +18 -5
  104. package/build-module/components/code-editor/index.js.map +1 -1
  105. package/build-module/components/edit-template-part-menu-button/index.js.map +1 -1
  106. package/build-module/components/editor/index.js +16 -0
  107. package/build-module/components/editor/index.js.map +1 -1
  108. package/build-module/components/error-boundary/index.js +5 -0
  109. package/build-module/components/error-boundary/index.js.map +1 -1
  110. package/build-module/components/global-styles/context-menu.js +6 -3
  111. package/build-module/components/global-styles/context-menu.js.map +1 -1
  112. package/build-module/components/global-styles/dimensions-panel.js +2 -6
  113. package/build-module/components/global-styles/dimensions-panel.js.map +1 -1
  114. package/build-module/components/global-styles/global-styles-provider.js +4 -2
  115. package/build-module/components/global-styles/global-styles-provider.js.map +1 -1
  116. package/build-module/components/global-styles/gradients-palette-panel.js +3 -5
  117. package/build-module/components/global-styles/gradients-palette-panel.js.map +1 -1
  118. package/build-module/components/global-styles/hooks.js +11 -2
  119. package/build-module/components/global-styles/hooks.js.map +1 -1
  120. package/build-module/components/global-styles/palette.js +2 -1
  121. package/build-module/components/global-styles/palette.js.map +1 -1
  122. package/build-module/components/global-styles/screen-block-list.js +4 -1
  123. package/build-module/components/global-styles/screen-block-list.js.map +1 -1
  124. package/build-module/components/global-styles/screen-button-color.js +67 -0
  125. package/build-module/components/global-styles/screen-button-color.js.map +1 -0
  126. package/build-module/components/global-styles/screen-color-palette.js +14 -19
  127. package/build-module/components/global-styles/screen-color-palette.js.map +1 -1
  128. package/build-module/components/global-styles/screen-colors.js +57 -9
  129. package/build-module/components/global-styles/screen-colors.js.map +1 -1
  130. package/build-module/components/global-styles/screen-link-color.js +47 -14
  131. package/build-module/components/global-styles/screen-link-color.js.map +1 -1
  132. package/build-module/components/global-styles/screen-root.js +4 -2
  133. package/build-module/components/global-styles/screen-root.js.map +1 -1
  134. package/build-module/components/global-styles/screen-style-variations.js +9 -1
  135. package/build-module/components/global-styles/screen-style-variations.js.map +1 -1
  136. package/build-module/components/global-styles/screen-typography-element.js +4 -0
  137. package/build-module/components/global-styles/screen-typography-element.js.map +1 -1
  138. package/build-module/components/global-styles/screen-typography.js +10 -2
  139. package/build-module/components/global-styles/screen-typography.js.map +1 -1
  140. package/build-module/components/global-styles/ui.js +10 -0
  141. package/build-module/components/global-styles/ui.js.map +1 -1
  142. package/build-module/components/global-styles/use-global-styles-output.js +198 -32
  143. package/build-module/components/global-styles/use-global-styles-output.js.map +1 -1
  144. package/build-module/components/global-styles/utils.js +5 -3
  145. package/build-module/components/global-styles/utils.js.map +1 -1
  146. package/build-module/components/header/index.js +29 -11
  147. package/build-module/components/header/index.js.map +1 -1
  148. package/build-module/components/header/mode-switcher/index.js.map +1 -1
  149. package/build-module/components/header/more-menu/copy-content-menu-item.js +1 -1
  150. package/build-module/components/header/more-menu/copy-content-menu-item.js.map +1 -1
  151. package/build-module/components/header/more-menu/site-export.js +4 -1
  152. package/build-module/components/header/more-menu/site-export.js.map +1 -1
  153. package/build-module/components/header/undo-redo/redo.js +9 -3
  154. package/build-module/components/header/undo-redo/redo.js.map +1 -1
  155. package/build-module/components/header/undo-redo/undo.js +9 -3
  156. package/build-module/components/header/undo-redo/undo.js.map +1 -1
  157. package/build-module/components/keyboard-shortcut-help-modal/config.js +17 -0
  158. package/build-module/components/keyboard-shortcut-help-modal/config.js.map +1 -1
  159. package/build-module/components/keyboard-shortcut-help-modal/index.js +1 -2
  160. package/build-module/components/keyboard-shortcut-help-modal/index.js.map +1 -1
  161. package/build-module/components/keyboard-shortcuts/index.js.map +1 -1
  162. package/build-module/components/list/actions/index.js.map +1 -1
  163. package/build-module/components/list/actions/rename-menu-item.js.map +1 -1
  164. package/build-module/components/list/added-by.js.map +1 -1
  165. package/build-module/components/navigation-sidebar/index.js.map +1 -1
  166. package/build-module/components/save-button/index.js.map +1 -1
  167. package/build-module/components/sidebar/index.js.map +1 -1
  168. package/build-module/components/sidebar/navigation-menu-sidebar/navigation-inspector.js.map +1 -1
  169. package/build-module/components/sidebar/template-card/index.js +18 -7
  170. package/build-module/components/sidebar/template-card/index.js.map +1 -1
  171. package/build-module/components/sidebar/template-card/template-actions.js +49 -0
  172. package/build-module/components/sidebar/template-card/template-actions.js.map +1 -0
  173. package/build-module/components/sidebar/template-card/template-areas.js.map +1 -1
  174. package/build-module/components/template-details/edit-template-title.js +12 -3
  175. package/build-module/components/template-details/edit-template-title.js.map +1 -1
  176. package/build-module/components/template-details/index.js +2 -21
  177. package/build-module/components/template-details/index.js.map +1 -1
  178. package/build-module/components/template-details/template-areas.js.map +1 -1
  179. package/build-module/components/template-part-converter/index.js.map +1 -1
  180. package/build-module/components/url-query-controller/index.js.map +1 -1
  181. package/build-module/store/actions.js.map +1 -1
  182. package/build-module/store/selectors.js +5 -2
  183. package/build-module/store/selectors.js.map +1 -1
  184. package/build-style/style-rtl.css +188 -42
  185. package/build-style/style.css +188 -42
  186. package/package.json +29 -29
  187. package/src/components/add-new-template/add-custom-generic-template-modal.js +97 -0
  188. package/src/components/add-new-template/add-custom-template-modal.js +265 -0
  189. package/src/components/add-new-template/new-template.js +194 -70
  190. package/src/components/add-new-template/style.scss +137 -0
  191. package/src/components/add-new-template/utils.js +369 -0
  192. package/src/components/block-editor/block-inspector-button.js +2 -3
  193. package/src/components/block-editor/index.js +4 -9
  194. package/src/components/code-editor/index.js +15 -5
  195. package/src/components/edit-template-part-menu-button/index.js +2 -3
  196. package/src/components/editor/index.js +15 -5
  197. package/src/components/error-boundary/index.js +5 -0
  198. package/src/components/global-styles/context-menu.js +3 -0
  199. package/src/components/global-styles/dimensions-panel.js +2 -7
  200. package/src/components/global-styles/global-styles-provider.js +12 -17
  201. package/src/components/global-styles/gradients-palette-panel.js +2 -5
  202. package/src/components/global-styles/hooks.js +20 -3
  203. package/src/components/global-styles/palette.js +4 -1
  204. package/src/components/global-styles/screen-block-list.js +14 -5
  205. package/src/components/global-styles/screen-button-color.js +102 -0
  206. package/src/components/global-styles/screen-color-palette.js +25 -27
  207. package/src/components/global-styles/screen-colors.js +58 -7
  208. package/src/components/global-styles/screen-link-color.js +65 -23
  209. package/src/components/global-styles/screen-root.js +12 -5
  210. package/src/components/global-styles/screen-style-variations.js +10 -4
  211. package/src/components/global-styles/screen-typography-element.js +4 -0
  212. package/src/components/global-styles/screen-typography.js +17 -2
  213. package/src/components/global-styles/style.scss +14 -8
  214. package/src/components/global-styles/test/use-global-styles-output.js +250 -16
  215. package/src/components/global-styles/ui.js +13 -0
  216. package/src/components/global-styles/use-global-styles-output.js +246 -32
  217. package/src/components/global-styles/utils.js +5 -2
  218. package/src/components/header/index.js +38 -13
  219. package/src/components/header/mode-switcher/index.js +4 -4
  220. package/src/components/header/more-menu/copy-content-menu-item.js +3 -4
  221. package/src/components/header/more-menu/site-export.js +5 -3
  222. package/src/components/header/style.scss +53 -5
  223. package/src/components/header/undo-redo/redo.js +6 -1
  224. package/src/components/header/undo-redo/undo.js +6 -1
  225. package/src/components/keyboard-shortcut-help-modal/config.js +12 -0
  226. package/src/components/keyboard-shortcut-help-modal/index.js +1 -2
  227. package/src/components/keyboard-shortcut-help-modal/style.scss +0 -5
  228. package/src/components/keyboard-shortcuts/index.js +6 -10
  229. package/src/components/list/actions/index.js +2 -3
  230. package/src/components/list/actions/rename-menu-item.js +4 -6
  231. package/src/components/list/added-by.js +4 -3
  232. package/src/components/list/style.scss +0 -8
  233. package/src/components/navigation-sidebar/index.js +2 -4
  234. package/src/components/save-button/index.js +2 -4
  235. package/src/components/sidebar/index.js +6 -6
  236. package/src/components/sidebar/navigation-menu-sidebar/navigation-inspector.js +6 -9
  237. package/src/components/sidebar/template-card/index.js +17 -9
  238. package/src/components/sidebar/template-card/style.scss +49 -35
  239. package/src/components/sidebar/template-card/template-actions.js +43 -0
  240. package/src/components/sidebar/template-card/template-areas.js +6 -6
  241. package/src/components/template-details/edit-template-title.js +10 -2
  242. package/src/components/template-details/index.js +4 -21
  243. package/src/components/template-details/template-areas.js +6 -6
  244. package/src/components/template-part-converter/index.js +2 -3
  245. package/src/components/test/error-boundary.js +38 -0
  246. package/src/components/url-query-controller/index.js +2 -3
  247. package/src/store/actions.js +257 -233
  248. package/src/store/selectors.js +19 -14
@@ -6,7 +6,6 @@ import {
6
6
  forEach,
7
7
  get,
8
8
  isEmpty,
9
- isString,
10
9
  kebabCase,
11
10
  pickBy,
12
11
  reduce,
@@ -24,7 +23,10 @@ import {
24
23
  } from '@wordpress/blocks';
25
24
  import { useEffect, useState, useContext } from '@wordpress/element';
26
25
  import { getCSSRules } from '@wordpress/style-engine';
27
- import { __unstablePresetDuotoneFilter as PresetDuotoneFilter } from '@wordpress/block-editor';
26
+ import {
27
+ __unstablePresetDuotoneFilter as PresetDuotoneFilter,
28
+ __experimentalGetGapCSSValue as getGapCSSValue,
29
+ } from '@wordpress/block-editor';
28
30
 
29
31
  /**
30
32
  * Internal dependencies
@@ -185,7 +187,7 @@ function getStylesDeclarations( blockStyles = {} ) {
185
187
 
186
188
  const styleValue = get( blockStyles, pathToValue );
187
189
 
188
- if ( !! properties && ! isString( styleValue ) ) {
190
+ if ( !! properties && typeof styleValue !== 'string' ) {
189
191
  Object.entries( properties ).forEach( ( entry ) => {
190
192
  const [ name, prop ] = entry;
191
193
 
@@ -231,6 +233,135 @@ function getStylesDeclarations( blockStyles = {} ) {
231
233
  return output;
232
234
  }
233
235
 
236
+ /**
237
+ * Get generated CSS for layout styles by looking up layout definitions provided
238
+ * in theme.json, and outputting common layout styles, and specific blockGap values.
239
+ *
240
+ * @param {Object} props
241
+ * @param {Object} props.tree A theme.json tree containing layout definitions.
242
+ * @param {Object} props.style A style object containing spacing values.
243
+ * @param {string} props.selector Selector used to group together layout styling rules.
244
+ * @param {boolean} props.hasBlockGapSupport Whether or not the theme opts-in to blockGap support.
245
+ * @param {boolean} props.hasFallbackGapSupport Whether or not the theme allows fallback gap styles.
246
+ * @param {?string} props.fallbackGapValue An optional fallback gap value if no real gap value is available.
247
+ * @return {string} Generated CSS rules for the layout styles.
248
+ */
249
+ export function getLayoutStyles( {
250
+ tree,
251
+ style,
252
+ selector,
253
+ hasBlockGapSupport,
254
+ hasFallbackGapSupport,
255
+ fallbackGapValue,
256
+ } ) {
257
+ let ruleset = '';
258
+ let gapValue = hasBlockGapSupport
259
+ ? getGapCSSValue( style?.spacing?.blockGap )
260
+ : '';
261
+
262
+ // Ensure a fallback gap value for the root layout definitions,
263
+ // and use a fallback value if one is provided for the current block.
264
+ if ( hasFallbackGapSupport ) {
265
+ if ( selector === ROOT_BLOCK_SELECTOR ) {
266
+ gapValue = ! gapValue ? '0.5em' : gapValue;
267
+ } else if ( ! hasBlockGapSupport && fallbackGapValue ) {
268
+ gapValue = fallbackGapValue;
269
+ }
270
+ }
271
+
272
+ if ( gapValue && tree?.settings?.layout?.definitions ) {
273
+ Object.values( tree.settings.layout.definitions ).forEach(
274
+ ( { className, name, spacingStyles } ) => {
275
+ // Allow skipping default layout for themes that opt-in to block styles, but opt-out of blockGap.
276
+ if ( ! hasBlockGapSupport && 'default' === name ) {
277
+ return;
278
+ }
279
+
280
+ if ( spacingStyles?.length ) {
281
+ spacingStyles.forEach( ( spacingStyle ) => {
282
+ const declarations = [];
283
+
284
+ if ( spacingStyle.rules ) {
285
+ Object.entries( spacingStyle.rules ).forEach(
286
+ ( [ cssProperty, cssValue ] ) => {
287
+ declarations.push(
288
+ `${ cssProperty }: ${
289
+ cssValue ? cssValue : gapValue
290
+ }`
291
+ );
292
+ }
293
+ );
294
+ }
295
+
296
+ if ( declarations.length ) {
297
+ const combinedSelector =
298
+ selector === ROOT_BLOCK_SELECTOR
299
+ ? `${ selector } .${ className }${
300
+ spacingStyle?.selector || ''
301
+ }`
302
+ : `${ selector }.${ className }${
303
+ spacingStyle?.selector || ''
304
+ }`;
305
+ ruleset += `${ combinedSelector } { ${ declarations.join(
306
+ '; '
307
+ ) }; }`;
308
+ }
309
+ } );
310
+ }
311
+ }
312
+ );
313
+ // For backwards compatibility, ensure the legacy block gap CSS variable is still available.
314
+ if ( selector === ROOT_BLOCK_SELECTOR && hasBlockGapSupport ) {
315
+ ruleset += `${ selector } { --wp--style--block-gap: ${ gapValue }; }`;
316
+ }
317
+ }
318
+
319
+ // Output base styles
320
+ if (
321
+ selector === ROOT_BLOCK_SELECTOR &&
322
+ tree?.settings?.layout?.definitions
323
+ ) {
324
+ const validDisplayModes = [ 'block', 'flex', 'grid' ];
325
+ Object.values( tree.settings.layout.definitions ).forEach(
326
+ ( { className, displayMode, baseStyles } ) => {
327
+ if (
328
+ displayMode &&
329
+ validDisplayModes.includes( displayMode )
330
+ ) {
331
+ ruleset += `${ selector } .${ className } { display:${ displayMode }; }`;
332
+ }
333
+
334
+ if ( baseStyles?.length ) {
335
+ baseStyles.forEach( ( baseStyle ) => {
336
+ const declarations = [];
337
+
338
+ if ( baseStyle.rules ) {
339
+ Object.entries( baseStyle.rules ).forEach(
340
+ ( [ cssProperty, cssValue ] ) => {
341
+ declarations.push(
342
+ `${ cssProperty }: ${ cssValue }`
343
+ );
344
+ }
345
+ );
346
+ }
347
+
348
+ if ( declarations.length ) {
349
+ const combinedSelector = `${ selector } .${ className }${
350
+ baseStyle?.selector || ''
351
+ }`;
352
+ ruleset += `${ combinedSelector } { ${ declarations.join(
353
+ '; '
354
+ ) }; }`;
355
+ }
356
+ } );
357
+ }
358
+ }
359
+ );
360
+ }
361
+
362
+ return ruleset;
363
+ }
364
+
234
365
  export const getNodesWithStyles = ( tree, blockSelectors ) => {
235
366
  const nodes = [];
236
367
 
@@ -267,9 +398,11 @@ export const getNodesWithStyles = ( tree, blockSelectors ) => {
267
398
  const blockStyles = pickStyleKeys( node );
268
399
  if ( !! blockStyles && !! blockSelectors?.[ blockName ]?.selector ) {
269
400
  nodes.push( {
270
- styles: blockStyles,
271
- selector: blockSelectors[ blockName ].selector,
272
401
  duotoneSelector: blockSelectors[ blockName ].duotoneSelector,
402
+ fallbackGapValue: blockSelectors[ blockName ].fallbackGapValue,
403
+ hasLayoutSupport: blockSelectors[ blockName ].hasLayoutSupport,
404
+ selector: blockSelectors[ blockName ].selector,
405
+ styles: blockStyles,
273
406
  } );
274
407
  }
275
408
 
@@ -283,7 +416,14 @@ export const getNodesWithStyles = ( tree, blockSelectors ) => {
283
416
  styles: value,
284
417
  selector: blockSelectors[ blockName ].selector
285
418
  .split( ',' )
286
- .map( ( sel ) => sel + ' ' + ELEMENTS[ elementName ] )
419
+ .map( ( sel ) => {
420
+ const elementSelectors =
421
+ ELEMENTS[ elementName ].split( ',' );
422
+ return elementSelectors.map(
423
+ ( elementSelector ) =>
424
+ sel + ' ' + elementSelector
425
+ );
426
+ } )
287
427
  .join( ',' ),
288
428
  } );
289
429
  }
@@ -357,7 +497,12 @@ export const toCustomProperties = ( tree, blockSelectors ) => {
357
497
  return ruleset;
358
498
  };
359
499
 
360
- export const toStyles = ( tree, blockSelectors, hasBlockGapSupport ) => {
500
+ export const toStyles = (
501
+ tree,
502
+ blockSelectors,
503
+ hasBlockGapSupport,
504
+ hasFallbackGapSupport
505
+ ) => {
361
506
  const nodesWithStyles = getNodesWithStyles( tree, blockSelectors );
362
507
  const nodesWithSettings = getNodesWithSettings( tree, blockSelectors );
363
508
 
@@ -370,31 +515,90 @@ export const toStyles = ( tree, blockSelectors, hasBlockGapSupport ) => {
370
515
  * @link https://github.com/WordPress/gutenberg/issues/36147.
371
516
  */
372
517
  let ruleset = 'body {margin: 0;}';
373
- nodesWithStyles.forEach( ( { selector, duotoneSelector, styles } ) => {
374
- const duotoneStyles = {};
375
- if ( styles?.filter ) {
376
- duotoneStyles.filter = styles.filter;
377
- delete styles.filter;
378
- }
518
+ nodesWithStyles.forEach(
519
+ ( {
520
+ selector,
521
+ duotoneSelector,
522
+ styles,
523
+ fallbackGapValue,
524
+ hasLayoutSupport,
525
+ } ) => {
526
+ const duotoneStyles = {};
527
+ if ( styles?.filter ) {
528
+ duotoneStyles.filter = styles.filter;
529
+ delete styles.filter;
530
+ }
379
531
 
380
- // Process duotone styles (they use color.__experimentalDuotone selector).
381
- if ( duotoneSelector ) {
382
- const duotoneDeclarations = getStylesDeclarations( duotoneStyles );
383
- if ( duotoneDeclarations.length === 0 ) {
384
- return;
532
+ // Process duotone styles (they use color.__experimentalDuotone selector).
533
+ if ( duotoneSelector ) {
534
+ const duotoneDeclarations =
535
+ getStylesDeclarations( duotoneStyles );
536
+ if ( duotoneDeclarations.length === 0 ) {
537
+ return;
538
+ }
539
+ ruleset =
540
+ ruleset +
541
+ `${ duotoneSelector }{${ duotoneDeclarations.join(
542
+ ';'
543
+ ) };}`;
385
544
  }
386
- ruleset =
387
- ruleset +
388
- `${ duotoneSelector }{${ duotoneDeclarations.join( ';' ) };}`;
389
- }
390
545
 
391
- // Process the remaning block styles (they use either normal block class or __experimentalSelector).
392
- const declarations = getStylesDeclarations( styles );
393
- if ( declarations.length === 0 ) {
394
- return;
546
+ // Process blockGap and layout styles.
547
+ if ( ROOT_BLOCK_SELECTOR === selector || hasLayoutSupport ) {
548
+ ruleset += getLayoutStyles( {
549
+ tree,
550
+ style: styles,
551
+ selector,
552
+ hasBlockGapSupport,
553
+ hasFallbackGapSupport,
554
+ fallbackGapValue,
555
+ } );
556
+ }
557
+
558
+ // Process the remaining block styles (they use either normal block class or __experimentalSelector).
559
+ const declarations = getStylesDeclarations( styles );
560
+ if ( declarations?.length ) {
561
+ ruleset =
562
+ ruleset + `${ selector }{${ declarations.join( ';' ) };}`;
563
+ }
564
+
565
+ // Check for pseudo selector in `styles` and handle separately.
566
+ const pseudoSelectorStyles = Object.entries( styles ).filter(
567
+ ( [ key ] ) => key.startsWith( ':' )
568
+ );
569
+
570
+ if ( pseudoSelectorStyles?.length ) {
571
+ pseudoSelectorStyles.forEach(
572
+ ( [ pseudoKey, pseudoStyle ] ) => {
573
+ const pseudoDeclarations =
574
+ getStylesDeclarations( pseudoStyle );
575
+
576
+ if ( ! pseudoDeclarations?.length ) {
577
+ return;
578
+ }
579
+
580
+ // `selector` maybe provided in a form
581
+ // where block level selectors have sub element
582
+ // selectors appended to them as a comma seperated
583
+ // string.
584
+ // e.g. `h1 a,h2 a,h3 a,h4 a,h5 a,h6 a`;
585
+ // Split and append pseudo selector to create
586
+ // the proper rules to target the elements.
587
+ const _selector = selector
588
+ .split( ',' )
589
+ .map( ( sel ) => sel + pseudoKey )
590
+ .join( ',' );
591
+
592
+ const pseudoRule = `${ _selector }{${ pseudoDeclarations.join(
593
+ ';'
594
+ ) };}`;
595
+
596
+ ruleset = ruleset + pseudoRule;
597
+ }
598
+ );
599
+ }
395
600
  }
396
- ruleset = ruleset + `${ selector }{${ declarations.join( ';' ) };}`;
397
- } );
601
+ );
398
602
 
399
603
  /* Add alignment / layout styles */
400
604
  ruleset =
@@ -408,12 +612,15 @@ export const toStyles = ( tree, blockSelectors, hasBlockGapSupport ) => {
408
612
  '.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }';
409
613
 
410
614
  if ( hasBlockGapSupport ) {
615
+ // Use fallback of `0.5em` just in case, however if there is blockGap support, there should nearly always be a real value.
616
+ const gapValue =
617
+ getGapCSSValue( tree?.styles?.spacing?.blockGap ) || '0.5em';
411
618
  ruleset =
412
619
  ruleset +
413
620
  '.wp-site-blocks > * { margin-block-start: 0; margin-block-end: 0; }';
414
621
  ruleset =
415
622
  ruleset +
416
- '.wp-site-blocks > * + * { margin-block-start: var( --wp--style--block-gap ); }';
623
+ `.wp-site-blocks > * + * { margin-block-start: ${ gapValue }; }`;
417
624
  }
418
625
 
419
626
  nodesWithSettings.forEach( ( { selector, presets } ) => {
@@ -447,10 +654,15 @@ const getBlockSelectors = ( blockTypes ) => {
447
654
  '.wp-block-' + name.replace( 'core/', '' ).replace( '/', '-' );
448
655
  const duotoneSelector =
449
656
  blockType?.supports?.color?.__experimentalDuotone ?? null;
657
+ const hasLayoutSupport = !! blockType?.supports?.__experimentalLayout;
658
+ const fallbackGapValue =
659
+ blockType?.supports?.spacing?.blockGap?.__experimentalDefault;
450
660
  result[ name ] = {
661
+ duotoneSelector,
662
+ fallbackGapValue,
663
+ hasLayoutSupport,
451
664
  name,
452
665
  selector,
453
- duotoneSelector,
454
666
  };
455
667
  } );
456
668
 
@@ -464,6 +676,7 @@ export function useGlobalStylesOutput() {
464
676
  const { merged: mergedConfig } = useContext( GlobalStylesContext );
465
677
  const [ blockGap ] = useSetting( 'spacing.blockGap' );
466
678
  const hasBlockGapSupport = blockGap !== null;
679
+ const hasFallbackGapSupport = ! hasBlockGapSupport; // This setting isn't useful yet: it exists as a placeholder for a future explicit fallback styles support.
467
680
 
468
681
  useEffect( () => {
469
682
  if ( ! mergedConfig?.styles || ! mergedConfig?.settings ) {
@@ -478,7 +691,8 @@ export function useGlobalStylesOutput() {
478
691
  const globalStyles = toStyles(
479
692
  mergedConfig,
480
693
  blockSelectors,
481
- hasBlockGapSupport
694
+ hasBlockGapSupport,
695
+ hasFallbackGapSupport
482
696
  );
483
697
  const filters = toSvgFilters( mergedConfig, blockSelectors );
484
698
  setStylesheets( [
@@ -493,7 +707,7 @@ export function useGlobalStylesOutput() {
493
707
  ] );
494
708
  setSettings( mergedConfig.settings );
495
709
  setSvgFilters( filters );
496
- }, [ mergedConfig ] );
710
+ }, [ hasBlockGapSupport, hasFallbackGapSupport, mergedConfig ] );
497
711
 
498
712
  return [ stylesheets, settings, svgFilters, hasBlockGapSupport ];
499
713
  }
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import { get, find, isString } from 'lodash';
4
+ import { get, find } from 'lodash';
5
5
 
6
6
  /* Supporting data. */
7
7
  export const ROOT_BLOCK_NAME = 'root';
@@ -11,6 +11,7 @@ export const ROOT_BLOCK_SUPPORTS = [
11
11
  'backgroundColor',
12
12
  'color',
13
13
  'linkColor',
14
+ 'buttonColor',
14
15
  'fontFamily',
15
16
  'fontSize',
16
17
  'fontStyle',
@@ -75,6 +76,8 @@ const STYLE_PATH_TO_CSS_VAR_INFIX = {
75
76
  'color.background': 'color',
76
77
  'color.text': 'color',
77
78
  'elements.link.color.text': 'color',
79
+ 'elements.button.color.text': 'color',
80
+ 'elements.button.backgroundColor': 'background-color',
78
81
  'color.gradient': 'gradient',
79
82
  'typography.fontSize': 'font-size',
80
83
  'typography.fontFamily': 'font-family',
@@ -210,7 +213,7 @@ function getValueFromCustomVariable( features, blockName, variable, path ) {
210
213
  }
211
214
 
212
215
  export function getValueFromVariable( features, blockName, variable ) {
213
- if ( ! variable || ! isString( variable ) ) {
216
+ if ( ! variable || typeof variable !== 'string' ) {
214
217
  return variable;
215
218
  }
216
219
  const USER_VALUE_PREFIX = 'var:';
@@ -6,6 +6,7 @@ import { useViewportMatch } from '@wordpress/compose';
6
6
  import {
7
7
  ToolSelector,
8
8
  __experimentalPreviewOptions as PreviewOptions,
9
+ NavigableToolbar,
9
10
  } from '@wordpress/block-editor';
10
11
  import { useSelect, useDispatch } from '@wordpress/data';
11
12
  import { PinnedItems } from '@wordpress/interface';
@@ -57,9 +58,8 @@ export default function Header( {
57
58
  getEditorMode,
58
59
  } = select( editSiteStore );
59
60
  const { getEditedEntityRecord } = select( coreStore );
60
- const { __experimentalGetTemplateInfo: getTemplateInfo } = select(
61
- editorStore
62
- );
61
+ const { __experimentalGetTemplateInfo: getTemplateInfo } =
62
+ select( editorStore );
63
63
  const { getShortcutRepresentation } = select( keyboardShortcutsStore );
64
64
 
65
65
  const postType = getEditedPostType();
@@ -108,47 +108,72 @@ export default function Header( {
108
108
 
109
109
  return (
110
110
  <div className="edit-site-header">
111
- <div className="edit-site-header_start">
111
+ <NavigableToolbar
112
+ className="edit-site-header_start"
113
+ aria-label={ __( 'Document tools' ) }
114
+ >
112
115
  <div className="edit-site-header__toolbar">
113
- <Button
116
+ <ToolbarItem
114
117
  ref={ inserterButton }
118
+ as={ Button }
119
+ className="edit-site-header-toolbar__inserter-toggle"
115
120
  variant="primary"
116
121
  isPressed={ isInserterOpen }
117
- className="edit-site-header-toolbar__inserter-toggle"
118
- disabled={ ! isVisualMode }
119
122
  onMouseDown={ preventDefault }
120
123
  onClick={ openInserter }
124
+ disabled={ ! isVisualMode }
121
125
  icon={ plus }
126
+ /* translators: button label text should, if possible, be under 16
127
+ characters. */
122
128
  label={ _x(
123
129
  'Toggle block inserter',
124
130
  'Generic label for block inserter button'
125
131
  ) }
132
+ showTooltip={ ! showIconLabels }
126
133
  >
127
134
  { showIconLabels &&
128
135
  ( ! isInserterOpen ? __( 'Add' ) : __( 'Close' ) ) }
129
- </Button>
136
+ </ToolbarItem>
130
137
  { isLargeViewport && (
131
138
  <>
132
139
  <ToolbarItem
133
140
  as={ ToolSelector }
141
+ showTooltip={ ! showIconLabels }
142
+ variant={
143
+ showIconLabels ? 'tertiary' : undefined
144
+ }
134
145
  disabled={ ! isVisualMode }
135
146
  />
136
- <UndoButton />
137
- <RedoButton />
138
- <Button
147
+ <ToolbarItem
148
+ as={ UndoButton }
149
+ showTooltip={ ! showIconLabels }
150
+ variant={
151
+ showIconLabels ? 'tertiary' : undefined
152
+ }
153
+ />
154
+ <ToolbarItem
155
+ as={ RedoButton }
156
+ showTooltip={ ! showIconLabels }
157
+ variant={
158
+ showIconLabels ? 'tertiary' : undefined
159
+ }
160
+ />
161
+ <ToolbarItem
162
+ as={ Button }
139
163
  className="edit-site-header-toolbar__list-view-toggle"
140
- disabled={ ! isVisualMode }
141
164
  icon={ listView }
165
+ disabled={ ! isVisualMode }
142
166
  isPressed={ isListViewOpen }
143
167
  /* translators: button label text should, if possible, be under 16 characters. */
144
168
  label={ __( 'List View' ) }
145
169
  onClick={ toggleListView }
146
170
  shortcut={ listViewShortcut }
171
+ showTooltip={ ! showIconLabels }
147
172
  />
148
173
  </>
149
174
  ) }
150
175
  </div>
151
- </div>
176
+ </NavigableToolbar>
152
177
 
153
178
  <div className="edit-site-header_center">
154
179
  <DocumentActions
@@ -36,10 +36,10 @@ function ModeSwitcher() {
36
36
  shortcut: select(
37
37
  keyboardShortcutsStore
38
38
  ).getShortcutRepresentation( 'core/edit-site/toggle-mode' ),
39
- isRichEditingEnabled: select( editSiteStore ).getSettings()
40
- .richEditingEnabled,
41
- isCodeEditingEnabled: select( editSiteStore ).getSettings()
42
- .codeEditingEnabled,
39
+ isRichEditingEnabled:
40
+ select( editSiteStore ).getSettings().richEditingEnabled,
41
+ isCodeEditingEnabled:
42
+ select( editSiteStore ).getSettings().codeEditingEnabled,
43
43
  mode: select( editSiteStore ).getEditorMode(),
44
44
  } ),
45
45
  []
@@ -18,9 +18,8 @@ export default function CopyContentMenuItem() {
18
18
  const { createNotice } = useDispatch( noticesStore );
19
19
  const getText = useSelect( ( select ) => {
20
20
  return () => {
21
- const { getEditedPostId, getEditedPostType } = select(
22
- editSiteStore
23
- );
21
+ const { getEditedPostId, getEditedPostType } =
22
+ select( editSiteStore );
24
23
  const { getEditedEntityRecord } = select( coreStore );
25
24
  const record = getEditedEntityRecord(
26
25
  'postType',
@@ -49,5 +48,5 @@ export default function CopyContentMenuItem() {
49
48
 
50
49
  const ref = useCopyToClipboard( getText, onSuccess );
51
50
 
52
- return <MenuItem ref={ ref }>{ __( 'Copy all content' ) }</MenuItem>;
51
+ return <MenuItem ref={ ref }>{ __( 'Copy all blocks' ) }</MenuItem>;
53
52
  }
@@ -21,14 +21,16 @@ export default function SiteExport() {
21
21
  const response = await apiFetch( {
22
22
  path: '/wp-block-editor/v1/export',
23
23
  parse: false,
24
+ headers: {
25
+ Accept: 'application/zip',
26
+ },
24
27
  } );
25
28
  const blob = await response.blob();
26
29
  const contentDisposition = response.headers.get(
27
30
  'content-disposition'
28
31
  );
29
- const contentDispositionMatches = contentDisposition.match(
30
- /=(.+)\.zip/
31
- );
32
+ const contentDispositionMatches =
33
+ contentDisposition.match( /=(.+)\.zip/ );
32
34
  const fileName = contentDispositionMatches[ 1 ]
33
35
  ? contentDispositionMatches[ 1 ]
34
36
  : 'edit-site-export';
@@ -16,9 +16,14 @@ $header-toolbar-min-width: 335px;
16
16
  @include reduce-motion("transition");
17
17
  }
18
18
 
19
- .edit-site-header_start,
19
+ .edit-site-header_start {
20
+ display: flex;
21
+ border: none;
22
+ }
23
+
20
24
  .edit-site-header_end {
21
25
  display: flex;
26
+ justify-content: flex-end;
22
27
  }
23
28
 
24
29
  .edit-site-header_center {
@@ -33,10 +38,6 @@ $header-toolbar-min-width: 335px;
33
38
  // See https://dev.w3.org/csswg/css-flexbox/#min-size-auto
34
39
  min-width: 0;
35
40
  }
36
-
37
- .edit-site-header_end {
38
- justify-content: flex-end;
39
- }
40
41
  }
41
42
 
42
43
  // Keeps the document title centered when the sidebar is open
@@ -152,6 +153,49 @@ body.is-navigation-sidebar-open {
152
153
  }
153
154
  }
154
155
 
156
+ .edit-site-header_start {
157
+ display: flex;
158
+ border: none;
159
+
160
+ // The Toolbar component adds different styles to buttons, so we reset them
161
+ // here to the original button styles
162
+ .edit-site-header__toolbar > .components-button.has-icon,
163
+ .edit-site-header__toolbar > .components-dropdown > .components-button.has-icon {
164
+ height: $button-size;
165
+ min-width: $button-size;
166
+ padding: 6px;
167
+
168
+ &.is-pressed {
169
+ background: $gray-900;
170
+ }
171
+
172
+ &:focus:not(:disabled) {
173
+ box-shadow: 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color), inset 0 0 0 $border-width $white;
174
+ outline: 1px solid transparent;
175
+ }
176
+
177
+ &::before {
178
+ display: none;
179
+ }
180
+ }
181
+
182
+ .edit-site-header__toolbar > .edit-site-header-toolbar__inserter-toggle.has-icon {
183
+ margin-right: $grid-unit-10;
184
+ // Special dimensions for this button.
185
+ min-width: 32px;
186
+ width: 32px;
187
+ height: 32px;
188
+ padding: 0;
189
+ }
190
+
191
+ .edit-site-header__toolbar > .edit-site-header-toolbar__inserter-toggle.has-text.has-icon {
192
+ width: auto;
193
+ padding: 0 $grid-unit-10;
194
+ }
195
+
196
+
197
+ }
198
+
155
199
  // Button text label styles
156
200
 
157
201
  .show-icon-labels .edit-site-header {
@@ -192,4 +236,8 @@ body.is-navigation-sidebar-open {
192
236
  height: 36px;
193
237
  padding: 0 6px;
194
238
  }
239
+
240
+ .edit-site-header_start .edit-site-header__toolbar > * + * {
241
+ margin-left: $grid-unit-10;
242
+ }
195
243
  }
@@ -7,8 +7,9 @@ import { useSelect, useDispatch } from '@wordpress/data';
7
7
  import { redo as redoIcon, undo as undoIcon } from '@wordpress/icons';
8
8
  import { displayShortcut } from '@wordpress/keycodes';
9
9
  import { store as coreStore } from '@wordpress/core-data';
10
+ import { forwardRef } from '@wordpress/element';
10
11
 
11
- export default function RedoButton() {
12
+ function RedoButton( props, ref ) {
12
13
  const hasRedo = useSelect(
13
14
  ( select ) => select( coreStore ).hasRedo(),
14
15
  []
@@ -16,6 +17,8 @@ export default function RedoButton() {
16
17
  const { redo } = useDispatch( coreStore );
17
18
  return (
18
19
  <Button
20
+ { ...props }
21
+ ref={ ref }
19
22
  icon={ ! isRTL() ? redoIcon : undoIcon }
20
23
  label={ __( 'Redo' ) }
21
24
  shortcut={ displayShortcut.primaryShift( 'z' ) }
@@ -27,3 +30,5 @@ export default function RedoButton() {
27
30
  />
28
31
  );
29
32
  }
33
+
34
+ export default forwardRef( RedoButton );