@wordpress/edit-site 4.17.0 → 4.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/build/components/add-new-template/add-custom-template-modal.js +3 -1
  3. package/build/components/add-new-template/add-custom-template-modal.js.map +1 -1
  4. package/build/components/app/index.js +8 -3
  5. package/build/components/app/index.js.map +1 -1
  6. package/build/components/block-editor/resizable-editor.js +9 -47
  7. package/build/components/block-editor/resizable-editor.js.map +1 -1
  8. package/build/components/editor/index.js +9 -13
  9. package/build/components/editor/index.js.map +1 -1
  10. package/build/components/global-styles/border-panel.js +2 -1
  11. package/build/components/global-styles/border-panel.js.map +1 -1
  12. package/build/components/global-styles/dimensions-panel.js +46 -2
  13. package/build/components/global-styles/dimensions-panel.js.map +1 -1
  14. package/build/components/global-styles/global-styles-provider.js +6 -5
  15. package/build/components/global-styles/global-styles-provider.js.map +1 -1
  16. package/build/components/global-styles/hooks.js +32 -0
  17. package/build/components/global-styles/hooks.js.map +1 -1
  18. package/build/components/global-styles/palette.js +8 -1
  19. package/build/components/global-styles/palette.js.map +1 -1
  20. package/build/components/global-styles/typography-panel.js +53 -16
  21. package/build/components/global-styles/typography-panel.js.map +1 -1
  22. package/build/components/global-styles/use-global-styles-output.js +43 -8
  23. package/build/components/global-styles/use-global-styles-output.js.map +1 -1
  24. package/build/components/header-edit-mode/document-actions/index.js +3 -1
  25. package/build/components/header-edit-mode/document-actions/index.js.map +1 -1
  26. package/build/components/header-edit-mode/index.js +15 -13
  27. package/build/components/header-edit-mode/index.js.map +1 -1
  28. package/build/components/keyboard-shortcut-help-modal/shortcut.js +1 -7
  29. package/build/components/keyboard-shortcut-help-modal/shortcut.js.map +1 -1
  30. package/build/components/keyboard-shortcuts/index.js +8 -5
  31. package/build/components/keyboard-shortcuts/index.js.map +1 -1
  32. package/build/components/list/table.js +1 -1
  33. package/build/components/list/table.js.map +1 -1
  34. package/build/components/list/use-register-shortcuts.js +3 -0
  35. package/build/components/list/use-register-shortcuts.js.map +1 -1
  36. package/build/components/navigation-sidebar/navigation-panel/index.js +9 -8
  37. package/build/components/navigation-sidebar/navigation-panel/index.js.map +1 -1
  38. package/build/components/save-button/index.js +36 -14
  39. package/build/components/save-button/index.js.map +1 -1
  40. package/build/components/sidebar-edit-mode/template-card/index.js +4 -2
  41. package/build/components/sidebar-edit-mode/template-card/index.js.map +1 -1
  42. package/build/components/template-details/index.js +4 -2
  43. package/build/components/template-details/index.js.map +1 -1
  44. package/build/index.js +5 -10
  45. package/build/index.js.map +1 -1
  46. package/build/store/actions.js +15 -0
  47. package/build/store/actions.js.map +1 -1
  48. package/build/store/reducer.js +28 -1
  49. package/build/store/reducer.js.map +1 -1
  50. package/build/store/selectors.js +13 -0
  51. package/build/store/selectors.js.map +1 -1
  52. package/build-module/components/add-new-template/add-custom-template-modal.js +2 -1
  53. package/build-module/components/add-new-template/add-custom-template-modal.js.map +1 -1
  54. package/build-module/components/app/index.js +8 -3
  55. package/build-module/components/app/index.js.map +1 -1
  56. package/build-module/components/block-editor/resizable-editor.js +11 -49
  57. package/build-module/components/block-editor/resizable-editor.js.map +1 -1
  58. package/build-module/components/editor/index.js +10 -14
  59. package/build-module/components/editor/index.js.map +1 -1
  60. package/build-module/components/global-styles/border-panel.js +2 -1
  61. package/build-module/components/global-styles/border-panel.js.map +1 -1
  62. package/build-module/components/global-styles/dimensions-panel.js +46 -2
  63. package/build-module/components/global-styles/dimensions-panel.js.map +1 -1
  64. package/build-module/components/global-styles/global-styles-provider.js +7 -6
  65. package/build-module/components/global-styles/global-styles-provider.js.map +1 -1
  66. package/build-module/components/global-styles/hooks.js +27 -1
  67. package/build-module/components/global-styles/hooks.js.map +1 -1
  68. package/build-module/components/global-styles/palette.js +9 -3
  69. package/build-module/components/global-styles/palette.js.map +1 -1
  70. package/build-module/components/global-styles/typography-panel.js +54 -16
  71. package/build-module/components/global-styles/typography-panel.js.map +1 -1
  72. package/build-module/components/global-styles/use-global-styles-output.js +44 -9
  73. package/build-module/components/global-styles/use-global-styles-output.js.map +1 -1
  74. package/build-module/components/header-edit-mode/document-actions/index.js +2 -1
  75. package/build-module/components/header-edit-mode/document-actions/index.js.map +1 -1
  76. package/build-module/components/header-edit-mode/index.js +14 -13
  77. package/build-module/components/header-edit-mode/index.js.map +1 -1
  78. package/build-module/components/keyboard-shortcut-help-modal/shortcut.js +1 -6
  79. package/build-module/components/keyboard-shortcut-help-modal/shortcut.js.map +1 -1
  80. package/build-module/components/keyboard-shortcuts/index.js +8 -5
  81. package/build-module/components/keyboard-shortcuts/index.js.map +1 -1
  82. package/build-module/components/list/table.js +1 -1
  83. package/build-module/components/list/table.js.map +1 -1
  84. package/build-module/components/list/use-register-shortcuts.js +3 -0
  85. package/build-module/components/list/use-register-shortcuts.js.map +1 -1
  86. package/build-module/components/navigation-sidebar/navigation-panel/index.js +9 -7
  87. package/build-module/components/navigation-sidebar/navigation-panel/index.js.map +1 -1
  88. package/build-module/components/save-button/index.js +39 -16
  89. package/build-module/components/save-button/index.js.map +1 -1
  90. package/build-module/components/sidebar-edit-mode/template-card/index.js +3 -2
  91. package/build-module/components/sidebar-edit-mode/template-card/index.js.map +1 -1
  92. package/build-module/components/template-details/index.js +3 -2
  93. package/build-module/components/template-details/index.js.map +1 -1
  94. package/build-module/index.js +5 -3
  95. package/build-module/index.js.map +1 -1
  96. package/build-module/store/actions.js +13 -0
  97. package/build-module/store/actions.js.map +1 -1
  98. package/build-module/store/reducer.js +26 -1
  99. package/build-module/store/reducer.js.map +1 -1
  100. package/build-module/store/selectors.js +11 -0
  101. package/build-module/store/selectors.js.map +1 -1
  102. package/build-style/style-rtl.css +17 -15
  103. package/build-style/style.css +17 -15
  104. package/package.json +30 -29
  105. package/src/components/add-new-template/add-custom-template-modal.js +5 -1
  106. package/src/components/app/index.js +11 -2
  107. package/src/components/block-editor/resizable-editor.js +10 -55
  108. package/src/components/block-editor/style.scss +1 -0
  109. package/src/components/editor/index.js +16 -25
  110. package/src/components/editor/style.scss +1 -7
  111. package/src/components/global-styles/border-panel.js +1 -0
  112. package/src/components/global-styles/dimensions-panel.js +59 -1
  113. package/src/components/global-styles/global-styles-provider.js +5 -6
  114. package/src/components/global-styles/hooks.js +36 -0
  115. package/src/components/global-styles/palette.js +15 -1
  116. package/src/components/global-styles/style.scss +1 -0
  117. package/src/components/global-styles/test/typography-utils.js +82 -98
  118. package/src/components/global-styles/test/use-global-styles-output.js +6 -6
  119. package/src/components/global-styles/typography-panel.js +58 -15
  120. package/src/components/global-styles/use-global-styles-output.js +47 -10
  121. package/src/components/header-edit-mode/document-actions/index.js +2 -1
  122. package/src/components/header-edit-mode/index.js +10 -13
  123. package/src/components/keyboard-shortcut-help-modal/shortcut.js +15 -18
  124. package/src/components/keyboard-shortcuts/index.js +7 -2
  125. package/src/components/list/table.js +1 -1
  126. package/src/components/list/use-register-shortcuts.js +4 -0
  127. package/src/components/navigation-sidebar/navigation-panel/index.js +30 -24
  128. package/src/components/navigation-sidebar/navigation-panel/style.scss +0 -7
  129. package/src/components/navigation-sidebar/navigation-toggle/test/index.js +24 -30
  130. package/src/components/save-button/index.js +31 -15
  131. package/src/components/sidebar-edit-mode/template-card/index.js +3 -2
  132. package/src/components/template-details/index.js +3 -2
  133. package/src/index.js +10 -3
  134. package/src/store/actions.js +13 -0
  135. package/src/store/reducer.js +19 -0
  136. package/src/store/selectors.js +11 -0
  137. package/build/components/main-dashboard-button/index.js +0 -41
  138. package/build/components/main-dashboard-button/index.js.map +0 -1
  139. package/build-module/components/main-dashboard-button/index.js +0 -32
  140. package/build-module/components/main-dashboard-button/index.js.map +0 -1
  141. package/src/components/main-dashboard-button/index.js +0 -28
@@ -17,7 +17,7 @@ import List from '../list';
17
17
  import NavigationSidebar from '../navigation-sidebar';
18
18
  import getIsListPage from '../../utils/get-is-list-page';
19
19
 
20
- export default function EditSiteApp( { reboot } ) {
20
+ export default function EditSiteApp( { reboot, homeTemplate } ) {
21
21
  const { createErrorNotice } = useDispatch( noticesStore );
22
22
 
23
23
  function onPluginAreaError( name ) {
@@ -40,6 +40,13 @@ export default function EditSiteApp( { reboot } ) {
40
40
  { ( { params } ) => {
41
41
  const isListPage = getIsListPage( params );
42
42
 
43
+ // The existence of a 'front-page' supersedes every other setting.
44
+ const homeTemplateType =
45
+ params.postId?.includes( 'front-page' ) ||
46
+ params.postId === homeTemplate?.postId
47
+ ? 'site-editor'
48
+ : undefined;
49
+
43
50
  return (
44
51
  <>
45
52
  { isListPage ? (
@@ -54,7 +61,9 @@ export default function EditSiteApp( { reboot } ) {
54
61
  // Open the navigation sidebar by default when in the list page.
55
62
  isDefaultOpen={ !! isListPage }
56
63
  activeTemplateType={
57
- isListPage ? params.postType : undefined
64
+ isListPage
65
+ ? params.postType
66
+ : homeTemplateType
58
67
  }
59
68
  />
60
69
  </>
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { useState, useEffect, useRef, useCallback } from '@wordpress/element';
4
+ import { useState, useRef, useCallback } from '@wordpress/element';
5
5
  import { ResizableBox } from '@wordpress/components';
6
6
  import {
7
7
  __experimentalUseResizeCanvas as useResizeCanvas,
@@ -11,7 +11,7 @@ import {
11
11
  store as blockEditorStore,
12
12
  } from '@wordpress/block-editor';
13
13
  import { useSelect } from '@wordpress/data';
14
- import { useMergeRefs } from '@wordpress/compose';
14
+ import { useMergeRefs, useResizeObserver } from '@wordpress/compose';
15
15
 
16
16
  /**
17
17
  * Internal dependencies
@@ -19,11 +19,6 @@ import { useMergeRefs } from '@wordpress/compose';
19
19
  import { store as editSiteStore } from '../../store';
20
20
  import ResizeHandle from './resize-handle';
21
21
 
22
- const DEFAULT_STYLES = {
23
- width: '100%',
24
- height: '100%',
25
- };
26
-
27
22
  // Removes the inline styles in the drag handles.
28
23
  const HANDLE_STYLES_OVERRIDE = {
29
24
  position: undefined,
@@ -38,6 +33,7 @@ const HANDLE_STYLES_OVERRIDE = {
38
33
  };
39
34
 
40
35
  function ResizableEditor( { enableResizing, settings, children, ...props } ) {
36
+ const [ resizeObserver, sizes ] = useResizeObserver();
41
37
  const { deviceType, isZoomOutMode } = useSelect(
42
38
  ( select ) => ( {
43
39
  deviceType:
@@ -49,60 +45,21 @@ function ResizableEditor( { enableResizing, settings, children, ...props } ) {
49
45
  []
50
46
  );
51
47
  const deviceStyles = useResizeCanvas( deviceType );
52
- const [ width, setWidth ] = useState( DEFAULT_STYLES.width );
53
- const [ height, setHeight ] = useState( DEFAULT_STYLES.height );
48
+ const [ width, setWidth ] = useState( '100%' );
54
49
  const iframeRef = useRef();
55
50
  const mouseMoveTypingResetRef = useMouseMoveTypingReset();
56
51
  const ref = useMergeRefs( [ iframeRef, mouseMoveTypingResetRef ] );
57
52
 
58
- useEffect(
59
- function autoResizeIframeHeight() {
60
- if ( ! iframeRef.current || ! enableResizing ) {
61
- return;
62
- }
63
-
64
- const iframe = iframeRef.current;
65
-
66
- function setFrameHeight() {
67
- setHeight( iframe.contentDocument.body.scrollHeight );
68
- }
69
-
70
- let resizeObserver;
71
-
72
- function registerObserver() {
73
- resizeObserver?.disconnect();
74
-
75
- resizeObserver = new iframe.contentWindow.ResizeObserver(
76
- setFrameHeight
77
- );
78
-
79
- // Observe the body, since the `html` element seems to always
80
- // have a height of `100%`.
81
- resizeObserver.observe( iframe.contentDocument.body );
82
- setFrameHeight();
83
- }
84
-
85
- iframe.addEventListener( 'load', registerObserver );
86
-
87
- return () => {
88
- resizeObserver?.disconnect();
89
- iframe.removeEventListener( 'load', registerObserver );
90
- };
91
- },
92
- [ enableResizing, iframeRef.current ]
93
- );
94
-
95
53
  const resizeWidthBy = useCallback( ( deltaPixels ) => {
96
54
  if ( iframeRef.current ) {
97
55
  setWidth( iframeRef.current.offsetWidth + deltaPixels );
98
56
  }
99
57
  }, [] );
100
-
101
58
  return (
102
59
  <ResizableBox
103
60
  size={ {
104
- width,
105
- height,
61
+ width: enableResizing ? width : '100%',
62
+ height: enableResizing && sizes.height ? sizes.height : '100%',
106
63
  } }
107
64
  onResizeStop={ ( event, direction, element ) => {
108
65
  setWidth( element.style.width );
@@ -141,21 +98,18 @@ function ResizableEditor( { enableResizing, settings, children, ...props } ) {
141
98
  >
142
99
  <Iframe
143
100
  isZoomedOut={ isZoomOutMode }
144
- style={ enableResizing ? { height } : deviceStyles }
101
+ style={ enableResizing ? {} : deviceStyles }
145
102
  head={
146
103
  <>
147
104
  <EditorStyles styles={ settings.styles } />
148
105
  <style>{
149
106
  // Forming a "block formatting context" to prevent margin collapsing.
150
107
  // @see https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Block_formatting_context
151
- `.is-root-container { display: flow-root; }`
108
+ `.is-root-container { display: flow-root; }
109
+ body { position: relative; }`
152
110
  }</style>
153
111
  { enableResizing && (
154
112
  <style>
155
- {
156
- // Force the <html> and <body>'s heights to fit the content.
157
- `html, body { height: -moz-fit-content !important; height: fit-content !important; min-height: 0 !important; }`
158
- }
159
113
  {
160
114
  // Some themes will have `min-height: 100vh` for the root container,
161
115
  // which isn't a requirement in auto resize mode.
@@ -173,6 +127,7 @@ function ResizableEditor( { enableResizing, settings, children, ...props } ) {
173
127
  >
174
128
  { /* Filters need to be rendered before children to avoid Safari rendering issues. */ }
175
129
  { settings.svgFilters }
130
+ { resizeObserver }
176
131
  { children }
177
132
  </Iframe>
178
133
  </ResizableBox>
@@ -23,6 +23,7 @@
23
23
 
24
24
  .edit-site-visual-editor__editor-canvas {
25
25
  border-radius: $radius-block-ui;
26
+ max-height: 100%;
26
27
  }
27
28
 
28
29
  // To hide the horizontal scrollbar and show the drag handle on the
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { useEffect, useState, useMemo, useCallback } from '@wordpress/element';
4
+ import { useEffect, useMemo } from '@wordpress/element';
5
5
  import { useSelect, useDispatch } from '@wordpress/data';
6
6
  import { Popover, Button, Notice } from '@wordpress/components';
7
7
  import { EntityProvider, store as coreStore } from '@wordpress/core-data';
@@ -65,6 +65,7 @@ function Editor( { onError } ) {
65
65
  const {
66
66
  isInserterOpen,
67
67
  isListViewOpen,
68
+ isSaveViewOpen,
68
69
  sidebarIsOpened,
69
70
  settings,
70
71
  entityId,
@@ -82,6 +83,7 @@ function Editor( { onError } ) {
82
83
  const {
83
84
  isInserterOpened,
84
85
  isListViewOpened,
86
+ isSaveViewOpened,
85
87
  getSettings,
86
88
  getEditedPostType,
87
89
  getEditedPostId,
@@ -98,6 +100,7 @@ function Editor( { onError } ) {
98
100
  return {
99
101
  isInserterOpen: isInserterOpened(),
100
102
  isListViewOpen: isListViewOpened(),
103
+ isSaveViewOpen: isSaveViewOpened(),
101
104
  sidebarIsOpened: !! select(
102
105
  interfaceStore
103
106
  ).getActiveComplementaryArea( editSiteStore.name ),
@@ -130,19 +133,10 @@ function Editor( { onError } ) {
130
133
  blockEditorMode: __unstableGetEditorMode(),
131
134
  };
132
135
  }, [] );
133
- const { setPage, setIsInserterOpened } = useDispatch( editSiteStore );
136
+ const { setPage, setIsInserterOpened, setIsSaveViewOpened } =
137
+ useDispatch( editSiteStore );
134
138
  const { enableComplementaryArea } = useDispatch( interfaceStore );
135
139
 
136
- const [ isEntitiesSavedStatesOpen, setIsEntitiesSavedStatesOpen ] =
137
- useState( false );
138
- const openEntitiesSavedStates = useCallback(
139
- () => setIsEntitiesSavedStatesOpen( true ),
140
- []
141
- );
142
- const closeEntitiesSavedStates = useCallback( () => {
143
- setIsEntitiesSavedStatesOpen( false );
144
- }, [] );
145
-
146
140
  const blockContext = useMemo(
147
141
  () => ( {
148
142
  ...page?.context,
@@ -247,9 +241,6 @@ function Editor( { onError } ) {
247
241
  }
248
242
  header={
249
243
  <Header
250
- openEntitiesSavedStates={
251
- openEntitiesSavedStates
252
- }
253
244
  showIconLabels={
254
245
  showIconLabels
255
246
  }
@@ -286,19 +277,17 @@ function Editor( { onError } ) {
286
277
  ) }
287
278
  </Notice>
288
279
  ) }
289
- <KeyboardShortcuts
290
- openEntitiesSavedStates={
291
- openEntitiesSavedStates
292
- }
293
- />
280
+ <KeyboardShortcuts />
294
281
  </>
295
282
  }
296
283
  actions={
297
284
  <>
298
- { isEntitiesSavedStatesOpen ? (
285
+ { isSaveViewOpen ? (
299
286
  <EntitiesSavedStates
300
- close={
301
- closeEntitiesSavedStates
287
+ close={ () =>
288
+ setIsSaveViewOpened(
289
+ false
290
+ )
302
291
  }
303
292
  />
304
293
  ) : (
@@ -306,8 +295,10 @@ function Editor( { onError } ) {
306
295
  <Button
307
296
  variant="secondary"
308
297
  className="edit-site-editor__toggle-save-panel-button"
309
- onClick={
310
- openEntitiesSavedStates
298
+ onClick={ () =>
299
+ setIsSaveViewOpened(
300
+ true
301
+ )
311
302
  }
312
303
  aria-expanded={
313
304
  false
@@ -7,16 +7,10 @@ html.wp-toolbar {
7
7
  }
8
8
 
9
9
  .edit-site-editor__toggle-save-panel {
10
- z-index: z-index(".edit-site-editor__toggle-save-panel");
11
- position: fixed !important; // Need to override the default relative positioning
12
- top: -9999em;
13
- bottom: auto;
14
- left: auto;
15
- right: 0;
10
+ box-sizing: border-box;
16
11
  width: $sidebar-width;
17
12
  background-color: $white;
18
13
  border: 1px dotted $gray-300;
19
- height: auto !important; // Need to override the default sidebar positioning
20
14
  padding: $grid-unit-30;
21
15
  display: flex;
22
16
  justify-content: center;
@@ -186,6 +186,7 @@ export default function BorderPanel( { name } ) {
186
186
  value={ border }
187
187
  __experimentalHasMultipleOrigins={ true }
188
188
  __experimentalIsRenderedInSidebar={ true }
189
+ size={ '__unstable-large' }
189
190
  />
190
191
  </ToolsPanelItem>
191
192
  ) }
@@ -35,8 +35,16 @@ export function useHasDimensionsPanel( name ) {
35
35
  const hasPadding = useHasPadding( name );
36
36
  const hasMargin = useHasMargin( name );
37
37
  const hasGap = useHasGap( name );
38
+ const hasMinHeight = useHasMinHeight( name );
38
39
 
39
- return hasContentSize || hasWideSize || hasPadding || hasMargin || hasGap;
40
+ return (
41
+ hasContentSize ||
42
+ hasWideSize ||
43
+ hasPadding ||
44
+ hasMargin ||
45
+ hasGap ||
46
+ hasMinHeight
47
+ );
40
48
  }
41
49
 
42
50
  function useHasContentSize( name ) {
@@ -74,6 +82,13 @@ function useHasGap( name ) {
74
82
  return settings && supports.includes( 'blockGap' );
75
83
  }
76
84
 
85
+ function useHasMinHeight( name ) {
86
+ const supports = getSupportedGlobalStylesPanels( name );
87
+ const [ settings ] = useSetting( 'dimensions.minHeight', name );
88
+
89
+ return settings && supports.includes( 'minHeight' );
90
+ }
91
+
77
92
  function useHasSpacingPresets() {
78
93
  const [ settings ] = useSetting( 'spacing.spacingSizes' );
79
94
 
@@ -271,12 +286,29 @@ function useBlockGapProps( name ) {
271
286
  };
272
287
  }
273
288
 
289
+ // Props for managing `dimensions.minHeight`.
290
+ function useMinHeightProps( name ) {
291
+ const [ minHeightValue, setMinHeightValue ] = useStyle(
292
+ 'dimensions.minHeight',
293
+ name
294
+ );
295
+ const resetMinHeightValue = () => setMinHeightValue( undefined );
296
+ const hasMinHeightValue = () => !! minHeightValue;
297
+ return {
298
+ minHeightValue,
299
+ setMinHeightValue,
300
+ resetMinHeightValue,
301
+ hasMinHeightValue,
302
+ };
303
+ }
304
+
274
305
  export default function DimensionsPanel( { name } ) {
275
306
  const showContentSizeControl = useHasContentSize( name );
276
307
  const showWideSizeControl = useHasWideSize( name );
277
308
  const showPaddingControl = useHasPadding( name );
278
309
  const showMarginControl = useHasMargin( name );
279
310
  const showGapControl = useHasGap( name );
311
+ const showMinHeightControl = useHasMinHeight( name );
280
312
  const showSpacingPresetsControl = useHasSpacingPresets();
281
313
  const units = useCustomUnits( {
282
314
  availableUnits: useSetting( 'spacing.units', name )[ 0 ] || [
@@ -336,6 +368,14 @@ export default function DimensionsPanel( { name } ) {
336
368
  hasGapValue,
337
369
  } = useBlockGapProps( name );
338
370
 
371
+ // Props for managing `dimensions.minHeight`.
372
+ const {
373
+ minHeightValue,
374
+ setMinHeightValue,
375
+ resetMinHeightValue,
376
+ hasMinHeightValue,
377
+ } = useMinHeightProps( name );
378
+
339
379
  const resetAll = () => {
340
380
  resetPaddingValue();
341
381
  resetMarginValue();
@@ -514,6 +554,24 @@ export default function DimensionsPanel( { name } ) {
514
554
  ) }
515
555
  </ToolsPanelItem>
516
556
  ) }
557
+ { showMinHeightControl && (
558
+ <ToolsPanelItem
559
+ className="single-column"
560
+ hasValue={ hasMinHeightValue }
561
+ label={ __( 'Min. height' ) }
562
+ onDeselect={ resetMinHeightValue }
563
+ isShownByDefault={ true }
564
+ >
565
+ <UnitControl
566
+ label={ __( 'Min. height' ) }
567
+ value={ minHeightValue }
568
+ onChange={ setMinHeightValue }
569
+ units={ units }
570
+ min={ 0 }
571
+ size={ '__unstable-large' }
572
+ />
573
+ </ToolsPanelItem>
574
+ ) }
517
575
  </ToolsPanel>
518
576
  );
519
577
  }
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import { mergeWith, pickBy, isEmpty, mapValues } from 'lodash';
4
+ import { mergeWith, isEmpty, mapValues } from 'lodash';
5
5
 
6
6
  /**
7
7
  * WordPress dependencies
@@ -15,8 +15,6 @@ import { store as coreStore } from '@wordpress/core-data';
15
15
  */
16
16
  import { GlobalStylesContext } from './context';
17
17
 
18
- const identity = ( x ) => x;
19
-
20
18
  function mergeTreesCustomizer( _, srcValue ) {
21
19
  // We only pass as arrays the presets,
22
20
  // in which case we want the new array of values
@@ -38,9 +36,10 @@ const cleanEmptyObject = ( object ) => {
38
36
  ) {
39
37
  return object;
40
38
  }
41
- const cleanedNestedObjects = pickBy(
42
- mapValues( object, cleanEmptyObject ),
43
- identity
39
+ const cleanedNestedObjects = Object.fromEntries(
40
+ Object.entries( mapValues( object, cleanEmptyObject ) ).filter(
41
+ ( [ , value ] ) => Boolean( value )
42
+ )
44
43
  );
45
44
  return isEmpty( cleanedNestedObjects ) ? undefined : cleanedNestedObjects;
46
45
  };
@@ -2,6 +2,8 @@
2
2
  * External dependencies
3
3
  */
4
4
  import { get, set, isEqual } from 'lodash';
5
+ import { colord, extend } from 'colord';
6
+ import a11yPlugin from 'colord/plugins/a11y';
5
7
 
6
8
  /**
7
9
  * WordPress dependencies
@@ -20,6 +22,9 @@ import {
20
22
  import { getValueFromVariable, getPresetVariableFromValue } from './utils';
21
23
  import { GlobalStylesContext } from './context';
22
24
 
25
+ // Enable colord's a11y plugin.
26
+ extend( [ a11yPlugin ] );
27
+
23
28
  const EMPTY_CONFIG = { settings: {}, styles: {} };
24
29
 
25
30
  export const useGlobalStylesReset = () => {
@@ -323,3 +328,34 @@ export function useGradientsPerOrigin( name ) {
323
328
  return result;
324
329
  }, [ customGradients, themeGradients, defaultGradients ] );
325
330
  }
331
+
332
+ export function useColorRandomizer( name ) {
333
+ const [ themeColors, setThemeColors ] = useSetting(
334
+ 'color.palette.theme',
335
+ name
336
+ );
337
+
338
+ function randomizeColors() {
339
+ /* eslint-disable no-restricted-syntax */
340
+ const randomRotationValue = Math.floor( Math.random() * 225 );
341
+ /* eslint-enable no-restricted-syntax */
342
+
343
+ const newColors = themeColors.map( ( colorObject ) => {
344
+ const { color } = colorObject;
345
+ const newColor = colord( color )
346
+ .rotate( randomRotationValue )
347
+ .toHex();
348
+
349
+ return {
350
+ ...colorObject,
351
+ color: newColor,
352
+ };
353
+ } );
354
+
355
+ setThemeColors( newColors );
356
+ }
357
+
358
+ return window.__experimentalEnableColorRandomizer
359
+ ? [ randomizeColors ]
360
+ : [];
361
+ }
@@ -8,8 +8,10 @@ import {
8
8
  __experimentalZStack as ZStack,
9
9
  __experimentalVStack as VStack,
10
10
  ColorIndicator,
11
+ Button,
11
12
  } from '@wordpress/components';
12
13
  import { __, _n, sprintf } from '@wordpress/i18n';
14
+ import { shuffle } from '@wordpress/icons';
13
15
  import { useMemo } from '@wordpress/element';
14
16
 
15
17
  /**
@@ -17,7 +19,7 @@ import { useMemo } from '@wordpress/element';
17
19
  */
18
20
  import Subtitle from './subtitle';
19
21
  import { NavigationButtonAsItem } from './navigation-button';
20
- import { useSetting } from './hooks';
22
+ import { useColorRandomizer, useSetting } from './hooks';
21
23
  import ColorIndicatorWrapper from './color-indicator-wrapper';
22
24
 
23
25
  const EMPTY_COLORS = [];
@@ -31,6 +33,9 @@ function Palette( { name } ) {
31
33
  'color.defaultPalette',
32
34
  name
33
35
  );
36
+
37
+ const [ randomizeThemeColors ] = useColorRandomizer();
38
+
34
39
  const colors = useMemo(
35
40
  () => [
36
41
  ...( customColors || EMPTY_COLORS ),
@@ -82,6 +87,15 @@ function Palette( { name } ) {
82
87
  </HStack>
83
88
  </NavigationButtonAsItem>
84
89
  </ItemGroup>
90
+ { randomizeThemeColors && (
91
+ <Button
92
+ variant="secondary"
93
+ icon={ shuffle }
94
+ onClick={ randomizeThemeColors }
95
+ >
96
+ { __( 'Randomize colors' ) }
97
+ </Button>
98
+ ) }
85
99
  </VStack>
86
100
  );
87
101
  }
@@ -19,6 +19,7 @@
19
19
  margin-bottom: $grid-unit-20;
20
20
  background: $gray-100;
21
21
  border-radius: $radius-block-ui;
22
+ overflow: hidden;
22
23
  }
23
24
 
24
25
  .edit-site-typography-panel__full-width-control {