@wordpress/edit-site 4.9.0 → 4.12.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 (199) 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 +82 -61
  5. package/build/components/add-new-template/add-custom-template-modal.js.map +1 -1
  6. package/build/components/add-new-template/new-template.js +94 -81
  7. package/build/components/add-new-template/new-template.js.map +1 -1
  8. package/build/components/add-new-template/utils.js +574 -57
  9. package/build/components/add-new-template/utils.js.map +1 -1
  10. package/build/components/block-editor/index.js +1 -3
  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/editor/index.js +16 -0
  15. package/build/components/editor/index.js.map +1 -1
  16. package/build/components/error-boundary/index.js +6 -0
  17. package/build/components/error-boundary/index.js.map +1 -1
  18. package/build/components/global-styles/dimensions-panel.js +191 -21
  19. package/build/components/global-styles/dimensions-panel.js.map +1 -1
  20. package/build/components/global-styles/global-styles-provider.js +4 -2
  21. package/build/components/global-styles/global-styles-provider.js.map +1 -1
  22. package/build/components/global-styles/hooks.js +11 -2
  23. package/build/components/global-styles/hooks.js.map +1 -1
  24. package/build/components/global-styles/screen-color-palette.js +13 -17
  25. package/build/components/global-styles/screen-color-palette.js.map +1 -1
  26. package/build/components/global-styles/screen-colors.js +59 -7
  27. package/build/components/global-styles/screen-colors.js.map +1 -1
  28. package/build/components/global-styles/screen-heading-color.js +157 -0
  29. package/build/components/global-styles/screen-heading-color.js.map +1 -0
  30. package/build/components/global-styles/screen-link-color.js +48 -14
  31. package/build/components/global-styles/screen-link-color.js.map +1 -1
  32. package/build/components/global-styles/screen-typography-element.js +4 -0
  33. package/build/components/global-styles/screen-typography-element.js.map +1 -1
  34. package/build/components/global-styles/screen-typography.js +5 -0
  35. package/build/components/global-styles/screen-typography.js.map +1 -1
  36. package/build/components/global-styles/typography-panel.js +73 -12
  37. package/build/components/global-styles/typography-panel.js.map +1 -1
  38. package/build/components/global-styles/typography-utils.js +217 -0
  39. package/build/components/global-styles/typography-utils.js.map +1 -0
  40. package/build/components/global-styles/ui.js +11 -0
  41. package/build/components/global-styles/ui.js.map +1 -1
  42. package/build/components/global-styles/use-global-styles-output.js +298 -61
  43. package/build/components/global-styles/use-global-styles-output.js.map +1 -1
  44. package/build/components/global-styles/utils.js +49 -3
  45. package/build/components/global-styles/utils.js.map +1 -1
  46. package/build/components/header/index.js +22 -10
  47. package/build/components/header/index.js.map +1 -1
  48. package/build/components/header/undo-redo/redo.js +2 -1
  49. package/build/components/header/undo-redo/redo.js.map +1 -1
  50. package/build/components/keyboard-shortcut-help-modal/index.js +1 -3
  51. package/build/components/keyboard-shortcut-help-modal/index.js.map +1 -1
  52. package/build/components/list/actions/index.js +1 -1
  53. package/build/components/list/actions/index.js.map +1 -1
  54. package/build/components/save-button/index.js +2 -3
  55. package/build/components/save-button/index.js.map +1 -1
  56. package/build/components/sidebar/navigation-menu-sidebar/navigation-menu.js +2 -2
  57. package/build/components/sidebar/navigation-menu-sidebar/navigation-menu.js.map +1 -1
  58. package/build/components/sidebar/template-card/template-actions.js +1 -1
  59. package/build/components/sidebar/template-card/template-actions.js.map +1 -1
  60. package/build/components/template-details/edit-template-title.js +11 -3
  61. package/build/components/template-details/edit-template-title.js.map +1 -1
  62. package/build/components/template-details/index.js +2 -21
  63. package/build/components/template-details/index.js.map +1 -1
  64. package/build/components/template-details/template-areas.js +1 -1
  65. package/build/components/template-details/template-areas.js.map +1 -1
  66. package/build/components/template-part-converter/convert-to-template-part.js +4 -1
  67. package/build/components/template-part-converter/convert-to-template-part.js.map +1 -1
  68. package/build/hooks/index.js +2 -0
  69. package/build/hooks/index.js.map +1 -1
  70. package/build/hooks/template-part-edit.js +86 -0
  71. package/build/hooks/template-part-edit.js.map +1 -0
  72. package/build/store/selectors.js +4 -1
  73. package/build/store/selectors.js.map +1 -1
  74. package/build-module/components/add-new-template/add-custom-generic-template-modal.js +77 -0
  75. package/build-module/components/add-new-template/add-custom-generic-template-modal.js.map +1 -0
  76. package/build-module/components/add-new-template/add-custom-template-modal.js +82 -61
  77. package/build-module/components/add-new-template/add-custom-template-modal.js.map +1 -1
  78. package/build-module/components/add-new-template/new-template.js +96 -84
  79. package/build-module/components/add-new-template/new-template.js.map +1 -1
  80. package/build-module/components/add-new-template/utils.js +555 -50
  81. package/build-module/components/add-new-template/utils.js.map +1 -1
  82. package/build-module/components/block-editor/index.js +1 -2
  83. package/build-module/components/block-editor/index.js.map +1 -1
  84. package/build-module/components/code-editor/index.js +18 -5
  85. package/build-module/components/code-editor/index.js.map +1 -1
  86. package/build-module/components/editor/index.js +16 -0
  87. package/build-module/components/editor/index.js.map +1 -1
  88. package/build-module/components/error-boundary/index.js +5 -0
  89. package/build-module/components/error-boundary/index.js.map +1 -1
  90. package/build-module/components/global-styles/dimensions-panel.js +191 -22
  91. package/build-module/components/global-styles/dimensions-panel.js.map +1 -1
  92. package/build-module/components/global-styles/global-styles-provider.js +4 -2
  93. package/build-module/components/global-styles/global-styles-provider.js.map +1 -1
  94. package/build-module/components/global-styles/hooks.js +11 -2
  95. package/build-module/components/global-styles/hooks.js.map +1 -1
  96. package/build-module/components/global-styles/screen-color-palette.js +14 -19
  97. package/build-module/components/global-styles/screen-color-palette.js.map +1 -1
  98. package/build-module/components/global-styles/screen-colors.js +59 -7
  99. package/build-module/components/global-styles/screen-colors.js.map +1 -1
  100. package/build-module/components/global-styles/screen-heading-color.js +143 -0
  101. package/build-module/components/global-styles/screen-heading-color.js.map +1 -0
  102. package/build-module/components/global-styles/screen-link-color.js +47 -14
  103. package/build-module/components/global-styles/screen-link-color.js.map +1 -1
  104. package/build-module/components/global-styles/screen-typography-element.js +4 -0
  105. package/build-module/components/global-styles/screen-typography-element.js.map +1 -1
  106. package/build-module/components/global-styles/screen-typography.js +5 -0
  107. package/build-module/components/global-styles/screen-typography.js.map +1 -1
  108. package/build-module/components/global-styles/typography-panel.js +74 -13
  109. package/build-module/components/global-styles/typography-panel.js.map +1 -1
  110. package/build-module/components/global-styles/typography-utils.js +204 -0
  111. package/build-module/components/global-styles/typography-utils.js.map +1 -0
  112. package/build-module/components/global-styles/ui.js +10 -0
  113. package/build-module/components/global-styles/ui.js.map +1 -1
  114. package/build-module/components/global-styles/use-global-styles-output.js +294 -69
  115. package/build-module/components/global-styles/use-global-styles-output.js.map +1 -1
  116. package/build-module/components/global-styles/utils.js +47 -4
  117. package/build-module/components/global-styles/utils.js.map +1 -1
  118. package/build-module/components/header/index.js +25 -12
  119. package/build-module/components/header/index.js.map +1 -1
  120. package/build-module/components/header/undo-redo/redo.js +3 -2
  121. package/build-module/components/header/undo-redo/redo.js.map +1 -1
  122. package/build-module/components/keyboard-shortcut-help-modal/index.js +1 -2
  123. package/build-module/components/keyboard-shortcut-help-modal/index.js.map +1 -1
  124. package/build-module/components/list/actions/index.js +1 -1
  125. package/build-module/components/list/actions/index.js.map +1 -1
  126. package/build-module/components/save-button/index.js +3 -4
  127. package/build-module/components/save-button/index.js.map +1 -1
  128. package/build-module/components/sidebar/navigation-menu-sidebar/navigation-menu.js +3 -3
  129. package/build-module/components/sidebar/navigation-menu-sidebar/navigation-menu.js.map +1 -1
  130. package/build-module/components/sidebar/template-card/template-actions.js +1 -1
  131. package/build-module/components/sidebar/template-card/template-actions.js.map +1 -1
  132. package/build-module/components/template-details/edit-template-title.js +12 -3
  133. package/build-module/components/template-details/edit-template-title.js.map +1 -1
  134. package/build-module/components/template-details/index.js +3 -22
  135. package/build-module/components/template-details/index.js.map +1 -1
  136. package/build-module/components/template-details/template-areas.js +1 -1
  137. package/build-module/components/template-details/template-areas.js.map +1 -1
  138. package/build-module/components/template-part-converter/convert-to-template-part.js +3 -1
  139. package/build-module/components/template-part-converter/convert-to-template-part.js.map +1 -1
  140. package/build-module/hooks/index.js +1 -0
  141. package/build-module/hooks/index.js.map +1 -1
  142. package/build-module/hooks/template-part-edit.js +67 -0
  143. package/build-module/hooks/template-part-edit.js.map +1 -0
  144. package/build-module/store/selectors.js +5 -2
  145. package/build-module/store/selectors.js.map +1 -1
  146. package/build-style/style-rtl.css +55 -48
  147. package/build-style/style.css +55 -48
  148. package/package.json +29 -29
  149. package/src/components/add-new-template/add-custom-generic-template-modal.js +97 -0
  150. package/src/components/add-new-template/add-custom-template-modal.js +93 -68
  151. package/src/components/add-new-template/new-template.js +126 -95
  152. package/src/components/add-new-template/style.scss +41 -8
  153. package/src/components/add-new-template/utils.js +622 -80
  154. package/src/components/block-editor/index.js +0 -2
  155. package/src/components/code-editor/index.js +15 -5
  156. package/src/components/editor/index.js +11 -0
  157. package/src/components/error-boundary/index.js +5 -0
  158. package/src/components/global-styles/dimensions-panel.js +214 -24
  159. package/src/components/global-styles/global-styles-provider.js +8 -9
  160. package/src/components/global-styles/hooks.js +18 -0
  161. package/src/components/global-styles/screen-color-palette.js +25 -27
  162. package/src/components/global-styles/screen-colors.js +55 -7
  163. package/src/components/global-styles/screen-heading-color.js +201 -0
  164. package/src/components/global-styles/screen-link-color.js +65 -23
  165. package/src/components/global-styles/screen-typography-element.js +4 -0
  166. package/src/components/global-styles/screen-typography.js +6 -0
  167. package/src/components/global-styles/style.scss +14 -11
  168. package/src/components/global-styles/test/typography-utils.js +130 -0
  169. package/src/components/global-styles/test/use-global-styles-output.js +296 -2
  170. package/src/components/global-styles/typography-panel.js +85 -16
  171. package/src/components/global-styles/typography-utils.js +228 -0
  172. package/src/components/global-styles/ui.js +13 -0
  173. package/src/components/global-styles/use-global-styles-output.js +387 -89
  174. package/src/components/global-styles/utils.js +43 -2
  175. package/src/components/header/index.js +37 -13
  176. package/src/components/header/style.scss +5 -3
  177. package/src/components/header/undo-redo/redo.js +6 -2
  178. package/src/components/keyboard-shortcut-help-modal/index.js +1 -2
  179. package/src/components/keyboard-shortcut-help-modal/style.scss +0 -5
  180. package/src/components/list/actions/index.js +3 -1
  181. package/src/components/list/style.scss +0 -8
  182. package/src/components/save-button/index.js +10 -13
  183. package/src/components/sidebar/navigation-menu-sidebar/navigation-menu.js +1 -5
  184. package/src/components/sidebar/style.scss +4 -0
  185. package/src/components/sidebar/template-card/template-actions.js +3 -1
  186. package/src/components/template-details/edit-template-title.js +10 -2
  187. package/src/components/template-details/index.js +7 -22
  188. package/src/components/template-details/template-areas.js +3 -1
  189. package/src/components/template-part-converter/convert-to-template-part.js +3 -1
  190. package/src/components/test/error-boundary.js +38 -0
  191. package/src/hooks/index.js +1 -0
  192. package/src/hooks/template-part-edit.js +82 -0
  193. package/src/store/selectors.js +11 -5
  194. package/src/style.scss +0 -1
  195. package/build/components/edit-template-part-menu-button/index.js +0 -90
  196. package/build/components/edit-template-part-menu-button/index.js.map +0 -1
  197. package/build-module/components/edit-template-part-menu-button/index.js +0 -72
  198. package/build-module/components/edit-template-part-menu-button/index.js.map +0 -1
  199. package/src/components/edit-template-part-menu-button/index.js +0 -82
@@ -38,7 +38,6 @@ import NavigateToLink from '../navigate-to-link';
38
38
  import { SidebarInspectorFill } from '../sidebar';
39
39
  import { store as editSiteStore } from '../../store';
40
40
  import BlockInspectorButton from './block-inspector-button';
41
- import EditTemplatePartMenuButton from '../edit-template-part-menu-button';
42
41
  import BackButton from './back-button';
43
42
  import ResizableEditor from './resizable-editor';
44
43
 
@@ -155,7 +154,6 @@ export default function BlockEditor( { setIsInserterOpen } ) {
155
154
  onChange={ onChange }
156
155
  useSubRegistry={ false }
157
156
  >
158
- <EditTemplatePartMenuButton />
159
157
  <TemplatePartConverter />
160
158
  <__experimentalLinkControl.ViewerFill>
161
159
  { useCallback(
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { parse } from '@wordpress/blocks';
4
+ import { parse, __unstableSerializeAndClean } from '@wordpress/blocks';
5
5
  import { useEntityBlockEditor, useEntityProp } from '@wordpress/core-data';
6
6
  import { useSelect, useDispatch } from '@wordpress/data';
7
7
  import { store as keyboardShortcutsStore } from '@wordpress/keyboard-shortcuts';
@@ -32,10 +32,20 @@ export default function CodeEditor() {
32
32
  'postType',
33
33
  templateType
34
34
  );
35
- const content =
36
- contentStructure instanceof Function
37
- ? contentStructure( { blocks } )
38
- : contentStructure;
35
+
36
+ // Replicates the logic found in getEditedPostContent().
37
+ let content;
38
+ if ( contentStructure instanceof Function ) {
39
+ content = contentStructure( { blocks } );
40
+ } else if ( blocks ) {
41
+ // If we have parsed blocks already, they should be our source of truth.
42
+ // Parsing applies block deprecations and legacy block conversions that
43
+ // unparsed content will not have.
44
+ content = __unstableSerializeAndClean( blocks );
45
+ } else {
46
+ content = contentStructure;
47
+ }
48
+
39
49
  const { switchEditorMode } = useDispatch( editSiteStore );
40
50
  return (
41
51
  <div className="edit-site-code-editor">
@@ -47,6 +47,17 @@ import { GlobalStylesProvider } from '../global-styles/global-styles-provider';
47
47
  import useTitle from '../routes/use-title';
48
48
 
49
49
  const interfaceLabels = {
50
+ /* translators: accessibility text for the editor top bar landmark region. */
51
+ header: __( 'Editor top bar' ),
52
+ /* translators: accessibility text for the editor content landmark region. */
53
+ body: __( 'Editor content' ),
54
+ /* translators: accessibility text for the editor settings landmark region. */
55
+ sidebar: __( 'Editor settings' ),
56
+ /* translators: accessibility text for the editor publish landmark region. */
57
+ actions: __( 'Editor publish' ),
58
+ /* translators: accessibility text for the editor footer landmark region. */
59
+ footer: __( 'Editor footer' ),
60
+ /* translators: accessibility text for the navigation sidebar landmark region. */
50
61
  drawer: __( 'Navigation Sidebar' ),
51
62
  };
52
63
 
@@ -3,6 +3,7 @@
3
3
  */
4
4
  import { Component } from '@wordpress/element';
5
5
  import { __ } from '@wordpress/i18n';
6
+ import { doAction } from '@wordpress/hooks';
6
7
 
7
8
  /**
8
9
  * Internal dependencies
@@ -20,6 +21,10 @@ export default class ErrorBoundary extends Component {
20
21
  };
21
22
  }
22
23
 
24
+ componentDidCatch( error ) {
25
+ doAction( 'editor.ErrorBoundary.errorLogged', error );
26
+ }
27
+
23
28
  static getDerivedStateFromError( error ) {
24
29
  return { error };
25
30
  }
@@ -6,10 +6,13 @@ import {
6
6
  __experimentalToolsPanel as ToolsPanel,
7
7
  __experimentalToolsPanelItem as ToolsPanelItem,
8
8
  __experimentalBoxControl as BoxControl,
9
+ __experimentalHStack as HStack,
9
10
  __experimentalUnitControl as UnitControl,
10
11
  __experimentalUseCustomUnits as useCustomUnits,
12
+ __experimentalView as View,
11
13
  } from '@wordpress/components';
12
14
  import { __experimentalUseCustomSides as useCustomSides } from '@wordpress/block-editor';
15
+ import { Icon, positionCenter, stretchWide } from '@wordpress/icons';
13
16
 
14
17
  /**
15
18
  * Internal dependencies
@@ -19,11 +22,27 @@ import { getSupportedGlobalStylesPanels, useSetting, useStyle } from './hooks';
19
22
  const AXIAL_SIDES = [ 'horizontal', 'vertical' ];
20
23
 
21
24
  export function useHasDimensionsPanel( name ) {
25
+ const hasContentSize = useHasContentSize( name );
26
+ const hasWideSize = useHasWideSize( name );
22
27
  const hasPadding = useHasPadding( name );
23
28
  const hasMargin = useHasMargin( name );
24
29
  const hasGap = useHasGap( name );
25
30
 
26
- return hasPadding || hasMargin || hasGap;
31
+ return hasContentSize || hasWideSize || hasPadding || hasMargin || hasGap;
32
+ }
33
+
34
+ function useHasContentSize( name ) {
35
+ const supports = getSupportedGlobalStylesPanels( name );
36
+ const [ settings ] = useSetting( 'layout.contentSize', name );
37
+
38
+ return settings && supports.includes( 'contentSize' );
39
+ }
40
+
41
+ function useHasWideSize( name ) {
42
+ const supports = getSupportedGlobalStylesPanels( name );
43
+ const [ settings ] = useSetting( 'layout.wideSize', name );
44
+
45
+ return settings && supports.includes( 'wideSize' );
27
46
  }
28
47
 
29
48
  function useHasPadding( name ) {
@@ -43,13 +62,8 @@ function useHasMargin( name ) {
43
62
  function useHasGap( name ) {
44
63
  const supports = getSupportedGlobalStylesPanels( name );
45
64
  const [ settings ] = useSetting( 'spacing.blockGap', name );
46
- // Do not show the gap control panel for block-level global styles
47
- // as they do not work on the frontend.
48
- // See: https://github.com/WordPress/gutenberg/pull/39845.
49
- // We can revert this condition when they're working again.
50
- return !! name
51
- ? false
52
- : settings && supports.includes( '--wp--style--block-gap' );
65
+
66
+ return settings && supports.includes( 'blockGap' );
53
67
  }
54
68
 
55
69
  function filterValuesBySides( values, sides ) {
@@ -90,20 +104,50 @@ function splitStyleValue( value ) {
90
104
  return value;
91
105
  }
92
106
 
93
- export default function DimensionsPanel( { name } ) {
94
- const showPaddingControl = useHasPadding( name );
95
- const showMarginControl = useHasMargin( name );
96
- const showGapControl = useHasGap( name );
97
- const units = useCustomUnits( {
98
- availableUnits: useSetting( 'spacing.units', name )[ 0 ] || [
99
- '%',
100
- 'px',
101
- 'em',
102
- 'rem',
103
- 'vw',
104
- ],
105
- } );
107
+ // Props for managing `layout.contentSize`.
108
+ function useContentSizeProps( name ) {
109
+ const [ contentSizeValue, setContentSizeValue ] = useSetting(
110
+ 'layout.contentSize',
111
+ name
112
+ );
113
+ const [ userSetContentSizeValue ] = useSetting(
114
+ 'layout.contentSize',
115
+ name,
116
+ 'user'
117
+ );
118
+ const hasUserSetContentSizeValue = () => !! userSetContentSizeValue;
119
+ const resetContentSizeValue = () => setContentSizeValue( '' );
120
+ return {
121
+ contentSizeValue,
122
+ setContentSizeValue,
123
+ hasUserSetContentSizeValue,
124
+ resetContentSizeValue,
125
+ };
126
+ }
106
127
 
128
+ // Props for managing `layout.wideSize`.
129
+ function useWideSizeProps( name ) {
130
+ const [ wideSizeValue, setWideSizeValue ] = useSetting(
131
+ 'layout.wideSize',
132
+ name
133
+ );
134
+ const [ userSetWideSizeValue ] = useSetting(
135
+ 'layout.wideSize',
136
+ name,
137
+ 'user'
138
+ );
139
+ const hasUserSetWideSizeValue = () => !! userSetWideSizeValue;
140
+ const resetWideSizeValue = () => setWideSizeValue( '' );
141
+ return {
142
+ wideSizeValue,
143
+ setWideSizeValue,
144
+ hasUserSetWideSizeValue,
145
+ resetWideSizeValue,
146
+ };
147
+ }
148
+
149
+ // Props for managing `spacing.padding`.
150
+ function usePaddingProps( name ) {
107
151
  const [ rawPadding, setRawPadding ] = useStyle( 'spacing.padding', name );
108
152
  const paddingValues = splitStyleValue( rawPadding );
109
153
  const paddingSides = useCustomSides( name, 'padding' );
@@ -116,9 +160,22 @@ export default function DimensionsPanel( { name } ) {
116
160
  setRawPadding( padding );
117
161
  };
118
162
  const resetPaddingValue = () => setPaddingValues( {} );
119
- const hasPaddingValue = () =>
120
- !! paddingValues && Object.keys( paddingValues ).length;
163
+ const [ userSetPaddingValue ] = useStyle( 'spacing.padding', name, 'user' );
164
+ // The `hasPaddingValue` check does not need a parsed value, as `userSetPaddingValue` will be `undefined` if not set.
165
+ const hasPaddingValue = () => !! userSetPaddingValue;
121
166
 
167
+ return {
168
+ paddingValues,
169
+ paddingSides,
170
+ isAxialPadding,
171
+ setPaddingValues,
172
+ resetPaddingValue,
173
+ hasPaddingValue,
174
+ };
175
+ }
176
+
177
+ // Props for managing `spacing.margin`.
178
+ function useMarginProps( name ) {
122
179
  const [ rawMargin, setRawMargin ] = useStyle( 'spacing.margin', name );
123
180
  const marginValues = splitStyleValue( rawMargin );
124
181
  const marginSides = useCustomSides( name, 'margin' );
@@ -134,18 +191,151 @@ export default function DimensionsPanel( { name } ) {
134
191
  const hasMarginValue = () =>
135
192
  !! marginValues && Object.keys( marginValues ).length;
136
193
 
194
+ return {
195
+ marginValues,
196
+ marginSides,
197
+ isAxialMargin,
198
+ setMarginValues,
199
+ resetMarginValue,
200
+ hasMarginValue,
201
+ };
202
+ }
203
+
204
+ // Props for managing `spacing.blockGap`.
205
+ function useBlockGapProps( name ) {
137
206
  const [ gapValue, setGapValue ] = useStyle( 'spacing.blockGap', name );
138
207
  const resetGapValue = () => setGapValue( undefined );
139
- const hasGapValue = () => !! gapValue;
208
+ const [ userSetGapValue ] = useStyle( 'spacing.blockGap', name, 'user' );
209
+ const hasGapValue = () => !! userSetGapValue;
210
+ return {
211
+ gapValue,
212
+ setGapValue,
213
+ resetGapValue,
214
+ hasGapValue,
215
+ };
216
+ }
217
+
218
+ export default function DimensionsPanel( { name } ) {
219
+ const showContentSizeControl = useHasContentSize( name );
220
+ const showWideSizeControl = useHasWideSize( name );
221
+ const showPaddingControl = useHasPadding( name );
222
+ const showMarginControl = useHasMargin( name );
223
+ const showGapControl = useHasGap( name );
224
+ const units = useCustomUnits( {
225
+ availableUnits: useSetting( 'spacing.units', name )[ 0 ] || [
226
+ '%',
227
+ 'px',
228
+ 'em',
229
+ 'rem',
230
+ 'vw',
231
+ ],
232
+ } );
233
+
234
+ // Props for managing `layout.contentSize`.
235
+ const {
236
+ contentSizeValue,
237
+ setContentSizeValue,
238
+ hasUserSetContentSizeValue,
239
+ resetContentSizeValue,
240
+ } = useContentSizeProps( name );
241
+
242
+ // Props for managing `layout.wideSize`.
243
+ const {
244
+ wideSizeValue,
245
+ setWideSizeValue,
246
+ hasUserSetWideSizeValue,
247
+ resetWideSizeValue,
248
+ } = useWideSizeProps( name );
249
+
250
+ // Props for managing `spacing.padding`.
251
+ const {
252
+ paddingValues,
253
+ paddingSides,
254
+ isAxialPadding,
255
+ setPaddingValues,
256
+ resetPaddingValue,
257
+ hasPaddingValue,
258
+ } = usePaddingProps( name );
259
+
260
+ // Props for managing `spacing.margin`.
261
+ const {
262
+ marginValues,
263
+ marginSides,
264
+ isAxialMargin,
265
+ setMarginValues,
266
+ resetMarginValue,
267
+ hasMarginValue,
268
+ } = useMarginProps( name );
269
+
270
+ // Props for managing `spacing.blockGap`.
271
+ const { gapValue, setGapValue, resetGapValue, hasGapValue } =
272
+ useBlockGapProps( name );
140
273
 
141
274
  const resetAll = () => {
142
275
  resetPaddingValue();
143
276
  resetMarginValue();
144
277
  resetGapValue();
278
+ resetContentSizeValue();
279
+ resetWideSizeValue();
145
280
  };
146
281
 
147
282
  return (
148
283
  <ToolsPanel label={ __( 'Dimensions' ) } resetAll={ resetAll }>
284
+ { ( showContentSizeControl || showWideSizeControl ) && (
285
+ <span className="span-columns">
286
+ { __( 'Set the width of the main content area.' ) }
287
+ </span>
288
+ ) }
289
+ { showContentSizeControl && (
290
+ <ToolsPanelItem
291
+ className="single-column"
292
+ label={ __( 'Content size' ) }
293
+ hasValue={ hasUserSetContentSizeValue }
294
+ onDeselect={ resetContentSizeValue }
295
+ isShownByDefault={ true }
296
+ >
297
+ <HStack alignment="flex-end" justify="flex-start">
298
+ <UnitControl
299
+ label={ __( 'Content' ) }
300
+ labelPosition="top"
301
+ __unstableInputWidth="80px"
302
+ value={ contentSizeValue || '' }
303
+ onChange={ ( nextContentSize ) => {
304
+ setContentSizeValue( nextContentSize );
305
+ } }
306
+ units={ units }
307
+ />
308
+ <View>
309
+ <Icon icon={ positionCenter } />
310
+ </View>
311
+ </HStack>
312
+ </ToolsPanelItem>
313
+ ) }
314
+ { showWideSizeControl && (
315
+ <ToolsPanelItem
316
+ className="single-column"
317
+ label={ __( 'Wide size' ) }
318
+ hasValue={ hasUserSetWideSizeValue }
319
+ onDeselect={ resetWideSizeValue }
320
+ isShownByDefault={ true }
321
+ >
322
+ <HStack alignment="flex-end" justify="flex-start">
323
+ <UnitControl
324
+ label={ __( 'Wide' ) }
325
+ labelPosition="top"
326
+ __unstableInputWidth="80px"
327
+ value={ wideSizeValue || '' }
328
+ onChange={ ( nextWideSize ) => {
329
+ setWideSizeValue( nextWideSize );
330
+ } }
331
+ units={ units }
332
+ />
333
+ <View>
334
+ <Icon icon={ stretchWide } />
335
+ </View>
336
+ </HStack>
337
+ </ToolsPanelItem>
338
+ ) }
149
339
  { showPaddingControl && (
150
340
  <ToolsPanelItem
151
341
  hasValue={ hasPaddingValue }
@@ -1,14 +1,7 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import {
5
- mergeWith,
6
- pickBy,
7
- isEmpty,
8
- isObject,
9
- identity,
10
- mapValues,
11
- } from 'lodash';
4
+ import { mergeWith, pickBy, isEmpty, mapValues } from 'lodash';
12
5
 
13
6
  /**
14
7
  * WordPress dependencies
@@ -22,6 +15,8 @@ import { store as coreStore } from '@wordpress/core-data';
22
15
  */
23
16
  import { GlobalStylesContext } from './context';
24
17
 
18
+ const identity = ( x ) => x;
19
+
25
20
  function mergeTreesCustomizer( _, srcValue ) {
26
21
  // We only pass as arrays the presets,
27
22
  // in which case we want the new array of values
@@ -36,7 +31,11 @@ export function mergeBaseAndUserConfigs( base, user ) {
36
31
  }
37
32
 
38
33
  const cleanEmptyObject = ( object ) => {
39
- if ( ! isObject( object ) || Array.isArray( object ) ) {
34
+ if (
35
+ object === null ||
36
+ typeof object !== 'object' ||
37
+ Array.isArray( object )
38
+ ) {
40
39
  return object;
41
40
  }
42
41
  const cleanedNestedObjects = pickBy(
@@ -168,6 +168,9 @@ const ROOT_BLOCK_SUPPORTS = [
168
168
  'textDecoration',
169
169
  'textTransform',
170
170
  'padding',
171
+ 'contentSize',
172
+ 'wideSize',
173
+ 'blockGap',
171
174
  ];
172
175
 
173
176
  export function getSupportedGlobalStylesPanels( name ) {
@@ -182,6 +185,21 @@ export function getSupportedGlobalStylesPanels( name ) {
182
185
  }
183
186
 
184
187
  const supportKeys = [];
188
+
189
+ // Check for blockGap support.
190
+ // Block spacing support doesn't map directly to a single style property, so needs to be handled separately.
191
+ // Also, only allow `blockGap` support if serialization has not been skipped, to be sure global spacing can be applied.
192
+ if (
193
+ blockType?.supports?.spacing?.blockGap &&
194
+ blockType?.supports?.spacing?.__experimentalSkipSerialization !==
195
+ true &&
196
+ ! blockType?.supports?.spacing?.__experimentalSkipSerialization?.some?.(
197
+ ( spacingType ) => spacingType === 'blockGap'
198
+ )
199
+ ) {
200
+ supportKeys.push( 'blockGap' );
201
+ }
202
+
185
203
  Object.keys( STYLE_PROPERTY ).forEach( ( styleName ) => {
186
204
  if ( ! STYLE_PROPERTY[ styleName ].support ) {
187
205
  return;
@@ -2,11 +2,7 @@
2
2
  * WordPress dependencies
3
3
  */
4
4
  import { __ } from '@wordpress/i18n';
5
- import {
6
- __experimentalToggleGroupControl as ToggleGroupControl,
7
- __experimentalToggleGroupControlOption as ToggleGroupControlOption,
8
- } from '@wordpress/components';
9
- import { useState } from '@wordpress/element';
5
+ import { TabPanel } from '@wordpress/components';
10
6
 
11
7
  /**
12
8
  * Internal dependencies
@@ -16,8 +12,6 @@ import GradientPalettePanel from './gradients-palette-panel';
16
12
  import ScreenHeader from './header';
17
13
 
18
14
  function ScreenColorPalette( { name } ) {
19
- const [ currentTab, setCurrentTab ] = useState( 'solid' );
20
-
21
15
  return (
22
16
  <>
23
17
  <ScreenHeader
@@ -26,27 +20,31 @@ function ScreenColorPalette( { name } ) {
26
20
  'Palettes are used to provide default color options for blocks and various design tools. Here you can edit the colors with their labels.'
27
21
  ) }
28
22
  />
29
- <ToggleGroupControl
30
- className="edit-site-screen-color-palette-toggle"
31
- value={ currentTab }
32
- onChange={ setCurrentTab }
33
- label={ __( 'Select palette type' ) }
34
- hideLabelFromVision
35
- isBlock
23
+ <TabPanel
24
+ tabs={ [
25
+ {
26
+ name: 'solid',
27
+ title: 'Solid',
28
+ value: 'solid',
29
+ },
30
+ {
31
+ name: 'gradient',
32
+ title: 'Gradient',
33
+ value: 'gradient',
34
+ },
35
+ ] }
36
36
  >
37
- <ToggleGroupControlOption
38
- value="solid"
39
- label={ __( 'Solid' ) }
40
- />
41
- <ToggleGroupControlOption
42
- value="gradient"
43
- label={ __( 'Gradient' ) }
44
- />
45
- </ToggleGroupControl>
46
- { currentTab === 'solid' && <ColorPalettePanel name={ name } /> }
47
- { currentTab === 'gradient' && (
48
- <GradientPalettePanel name={ name } />
49
- ) }
37
+ { ( tab ) => (
38
+ <>
39
+ { tab.value === 'solid' && (
40
+ <ColorPalettePanel name={ name } />
41
+ ) }
42
+ { tab.value === 'gradient' && (
43
+ <GradientPalettePanel name={ name } />
44
+ ) }
45
+ </>
46
+ ) }
47
+ </TabPanel>
50
48
  </>
51
49
  );
52
50
  }
@@ -45,7 +45,9 @@ function BackgroundColorItem( { name, parentMenu } ) {
45
45
  data-testid="background-color-indicator"
46
46
  />
47
47
  </ColorIndicatorWrapper>
48
- <FlexItem>{ __( 'Background' ) }</FlexItem>
48
+ <FlexItem className="edit-site-global-styles__color-label">
49
+ { __( 'Background' ) }
50
+ </FlexItem>
49
51
  </HStack>
50
52
  </NavigationButtonAsItem>
51
53
  );
@@ -72,7 +74,9 @@ function TextColorItem( { name, parentMenu } ) {
72
74
  data-testid="text-color-indicator"
73
75
  />
74
76
  </ColorIndicatorWrapper>
75
- <FlexItem>{ __( 'Text' ) }</FlexItem>
77
+ <FlexItem className="edit-site-global-styles__color-label">
78
+ { __( 'Text' ) }
79
+ </FlexItem>
76
80
  </HStack>
77
81
  </NavigationButtonAsItem>
78
82
  );
@@ -82,6 +86,7 @@ function LinkColorItem( { name, parentMenu } ) {
82
86
  const supports = getSupportedGlobalStylesPanels( name );
83
87
  const hasSupport = supports.includes( 'linkColor' );
84
88
  const [ color ] = useStyle( 'elements.link.color.text', name );
89
+ const [ colorHover ] = useStyle( 'elements.link.:hover.color.text', name );
85
90
 
86
91
  if ( ! hasSupport ) {
87
92
  return null;
@@ -93,10 +98,47 @@ function LinkColorItem( { name, parentMenu } ) {
93
98
  aria-label={ __( 'Colors link styles' ) }
94
99
  >
95
100
  <HStack justify="flex-start">
96
- <ColorIndicatorWrapper expanded={ false }>
97
- <ColorIndicator colorValue={ color } />
98
- </ColorIndicatorWrapper>
99
- <FlexItem>{ __( 'Links' ) }</FlexItem>
101
+ <ZStack isLayered={ false } offset={ -8 }>
102
+ <ColorIndicatorWrapper expanded={ false }>
103
+ <ColorIndicator colorValue={ color } />
104
+ </ColorIndicatorWrapper>
105
+ <ColorIndicatorWrapper expanded={ false }>
106
+ <ColorIndicator colorValue={ colorHover } />
107
+ </ColorIndicatorWrapper>
108
+ </ZStack>
109
+ <FlexItem className="edit-site-global-styles__color-label">
110
+ { __( 'Links' ) }
111
+ </FlexItem>
112
+ </HStack>
113
+ </NavigationButtonAsItem>
114
+ );
115
+ }
116
+
117
+ function HeadingColorItem( { name, parentMenu } ) {
118
+ const supports = getSupportedGlobalStylesPanels( name );
119
+ const hasSupport = supports.includes( 'color' );
120
+ const [ color ] = useStyle( 'elements.heading.color.text', name );
121
+ const [ bgColor ] = useStyle( 'elements.heading.color.background', name );
122
+
123
+ if ( ! hasSupport ) {
124
+ return null;
125
+ }
126
+
127
+ return (
128
+ <NavigationButtonAsItem
129
+ path={ parentMenu + '/colors/heading' }
130
+ aria-label={ __( 'Colors heading styles' ) }
131
+ >
132
+ <HStack justify="flex-start">
133
+ <ZStack isLayered={ false } offset={ -8 }>
134
+ <ColorIndicatorWrapper expanded={ false }>
135
+ <ColorIndicator colorValue={ bgColor } />
136
+ </ColorIndicatorWrapper>
137
+ <ColorIndicatorWrapper expanded={ false }>
138
+ <ColorIndicator colorValue={ color } />
139
+ </ColorIndicatorWrapper>
140
+ </ZStack>
141
+ <FlexItem>{ __( 'Headings' ) }</FlexItem>
100
142
  </HStack>
101
143
  </NavigationButtonAsItem>
102
144
  );
@@ -123,7 +165,9 @@ function ButtonColorItem( { name, parentMenu } ) {
123
165
  <ColorIndicator colorValue={ color } />
124
166
  </ColorIndicatorWrapper>
125
167
  </ZStack>
126
- <FlexItem>{ __( 'Buttons' ) }</FlexItem>
168
+ <FlexItem className="edit-site-global-styles__color-label">
169
+ { __( 'Buttons' ) }
170
+ </FlexItem>
127
171
  </HStack>
128
172
  </NavigationButtonAsItem>
129
173
  );
@@ -160,6 +204,10 @@ function ScreenColors( { name } ) {
160
204
  name={ name }
161
205
  parentMenu={ parentMenu }
162
206
  />
207
+ <HeadingColorItem
208
+ name={ name }
209
+ parentMenu={ parentMenu }
210
+ />
163
211
  <ButtonColorItem
164
212
  name={ name }
165
213
  parentMenu={ parentMenu }