@wordpress/edit-site 4.12.1-next.d6164808d3.0 → 4.14.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 (92) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/build/components/add-new-template/new-template.js +1 -1
  3. package/build/components/add-new-template/new-template.js.map +1 -1
  4. package/build/components/add-new-template/utils.js +90 -52
  5. package/build/components/add-new-template/utils.js.map +1 -1
  6. package/build/components/block-editor/index.js +20 -10
  7. package/build/components/block-editor/index.js.map +1 -1
  8. package/build/components/block-editor/resizable-editor.js +8 -1
  9. package/build/components/block-editor/resizable-editor.js.map +1 -1
  10. package/build/components/editor/index.js +9 -4
  11. package/build/components/editor/index.js.map +1 -1
  12. package/build/components/global-styles/dimensions-panel.js +40 -23
  13. package/build/components/global-styles/dimensions-panel.js.map +1 -1
  14. package/build/components/global-styles/gradients-palette-panel.js +6 -2
  15. package/build/components/global-styles/gradients-palette-panel.js.map +1 -1
  16. package/build/components/global-styles/hooks.js +5 -3
  17. package/build/components/global-styles/hooks.js.map +1 -1
  18. package/build/components/global-styles/preview.js +2 -2
  19. package/build/components/global-styles/preview.js.map +1 -1
  20. package/build/components/global-styles/use-global-styles-output.js +41 -29
  21. package/build/components/global-styles/use-global-styles-output.js.map +1 -1
  22. package/build/components/global-styles/utils.js +1 -1
  23. package/build/components/global-styles/utils.js.map +1 -1
  24. package/build/components/header/index.js +41 -5
  25. package/build/components/header/index.js.map +1 -1
  26. package/build/components/list/header.js +15 -2
  27. package/build/components/list/header.js.map +1 -1
  28. package/build/components/navigation-sidebar/navigation-panel/index.js +10 -4
  29. package/build/components/navigation-sidebar/navigation-panel/index.js.map +1 -1
  30. package/build/components/sidebar/index.js +8 -3
  31. package/build/components/sidebar/index.js.map +1 -1
  32. package/build/components/template-part-converter/convert-to-template-part.js +16 -0
  33. package/build/components/template-part-converter/convert-to-template-part.js.map +1 -1
  34. package/build/index.js +4 -1
  35. package/build/index.js.map +1 -1
  36. package/build-module/components/add-new-template/new-template.js +2 -2
  37. package/build-module/components/add-new-template/new-template.js.map +1 -1
  38. package/build-module/components/add-new-template/utils.js +87 -52
  39. package/build-module/components/add-new-template/utils.js.map +1 -1
  40. package/build-module/components/block-editor/index.js +20 -9
  41. package/build-module/components/block-editor/index.js.map +1 -1
  42. package/build-module/components/block-editor/resizable-editor.js +9 -2
  43. package/build-module/components/block-editor/resizable-editor.js.map +1 -1
  44. package/build-module/components/editor/index.js +10 -5
  45. package/build-module/components/editor/index.js.map +1 -1
  46. package/build-module/components/global-styles/dimensions-panel.js +40 -23
  47. package/build-module/components/global-styles/dimensions-panel.js.map +1 -1
  48. package/build-module/components/global-styles/gradients-palette-panel.js +6 -2
  49. package/build-module/components/global-styles/gradients-palette-panel.js.map +1 -1
  50. package/build-module/components/global-styles/hooks.js +6 -4
  51. package/build-module/components/global-styles/hooks.js.map +1 -1
  52. package/build-module/components/global-styles/preview.js +2 -2
  53. package/build-module/components/global-styles/preview.js.map +1 -1
  54. package/build-module/components/global-styles/use-global-styles-output.js +42 -30
  55. package/build-module/components/global-styles/use-global-styles-output.js.map +1 -1
  56. package/build-module/components/global-styles/utils.js +1 -1
  57. package/build-module/components/global-styles/utils.js.map +1 -1
  58. package/build-module/components/header/index.js +42 -7
  59. package/build-module/components/header/index.js.map +1 -1
  60. package/build-module/components/list/header.js +14 -2
  61. package/build-module/components/list/header.js.map +1 -1
  62. package/build-module/components/navigation-sidebar/navigation-panel/index.js +11 -5
  63. package/build-module/components/navigation-sidebar/navigation-panel/index.js.map +1 -1
  64. package/build-module/components/sidebar/index.js +7 -3
  65. package/build-module/components/sidebar/index.js.map +1 -1
  66. package/build-module/components/template-part-converter/convert-to-template-part.js +16 -1
  67. package/build-module/components/template-part-converter/convert-to-template-part.js.map +1 -1
  68. package/build-module/index.js +4 -1
  69. package/build-module/index.js.map +1 -1
  70. package/build-style/style-rtl.css +28 -16
  71. package/build-style/style.css +28 -16
  72. package/package.json +29 -29
  73. package/src/components/add-new-template/new-template.js +2 -0
  74. package/src/components/add-new-template/utils.js +82 -20
  75. package/src/components/block-editor/index.js +34 -16
  76. package/src/components/block-editor/resizable-editor.js +10 -3
  77. package/src/components/code-editor/style.scss +2 -3
  78. package/src/components/editor/index.js +12 -5
  79. package/src/components/global-styles/dimensions-panel.js +52 -31
  80. package/src/components/global-styles/gradients-palette-panel.js +25 -12
  81. package/src/components/global-styles/hooks.js +7 -7
  82. package/src/components/global-styles/preview.js +2 -2
  83. package/src/components/global-styles/use-global-styles-output.js +66 -57
  84. package/src/components/global-styles/utils.js +1 -1
  85. package/src/components/header/index.js +61 -21
  86. package/src/components/header/style.scss +9 -0
  87. package/src/components/list/header.js +15 -5
  88. package/src/components/navigation-sidebar/navigation-panel/index.js +30 -24
  89. package/src/components/sidebar/index.js +23 -20
  90. package/src/components/template-part-converter/convert-to-template-part.js +14 -1
  91. package/src/index.js +4 -0
  92. package/src/style.scss +1 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wordpress/edit-site",
3
- "version": "4.12.1-next.d6164808d3.0",
3
+ "version": "4.14.0",
4
4
  "description": "Edit Site Page module for WordPress.",
5
5
  "author": "The WordPress Contributors",
6
6
  "license": "GPL-2.0-or-later",
@@ -27,33 +27,33 @@
27
27
  "react-native": "src/index",
28
28
  "dependencies": {
29
29
  "@babel/runtime": "^7.16.0",
30
- "@wordpress/a11y": "^3.15.1-next.d6164808d3.0",
31
- "@wordpress/api-fetch": "^6.12.1-next.d6164808d3.0",
32
- "@wordpress/block-editor": "^9.7.1-next.d6164808d3.0",
33
- "@wordpress/block-library": "^7.12.2-next.d6164808d3.0",
34
- "@wordpress/blocks": "^11.14.1-next.d6164808d3.0",
35
- "@wordpress/components": "^20.0.1-next.d6164808d3.0",
36
- "@wordpress/compose": "^5.13.1-next.d6164808d3.0",
37
- "@wordpress/core-data": "^4.14.1-next.d6164808d3.0",
38
- "@wordpress/data": "^7.0.1-next.d6164808d3.0",
39
- "@wordpress/deprecated": "^3.15.1-next.d6164808d3.0",
40
- "@wordpress/editor": "^12.14.1-next.d6164808d3.0",
41
- "@wordpress/element": "^4.13.1-next.d6164808d3.0",
42
- "@wordpress/hooks": "^3.15.1-next.d6164808d3.0",
43
- "@wordpress/html-entities": "^3.15.1-next.d6164808d3.0",
44
- "@wordpress/i18n": "^4.15.1-next.d6164808d3.0",
45
- "@wordpress/icons": "^9.6.1-next.d6164808d3.0",
46
- "@wordpress/interface": "^4.14.1-next.d6164808d3.0",
47
- "@wordpress/keyboard-shortcuts": "^3.13.1-next.d6164808d3.0",
48
- "@wordpress/keycodes": "^3.15.1-next.d6164808d3.0",
49
- "@wordpress/media-utils": "^4.6.1-next.d6164808d3.0",
50
- "@wordpress/notices": "^3.15.1-next.d6164808d3.0",
51
- "@wordpress/plugins": "^4.13.1-next.d6164808d3.0",
52
- "@wordpress/preferences": "^2.7.1-next.d6164808d3.0",
53
- "@wordpress/reusable-blocks": "^3.13.1-next.d6164808d3.0",
54
- "@wordpress/style-engine": "^0.14.1-next.d6164808d3.0",
55
- "@wordpress/url": "^3.16.1-next.d6164808d3.0",
56
- "@wordpress/viewport": "^4.13.1-next.d6164808d3.0",
30
+ "@wordpress/a11y": "^3.17.0",
31
+ "@wordpress/api-fetch": "^6.14.0",
32
+ "@wordpress/block-editor": "^10.0.0",
33
+ "@wordpress/block-library": "^7.14.0",
34
+ "@wordpress/blocks": "^11.16.0",
35
+ "@wordpress/components": "^21.0.0",
36
+ "@wordpress/compose": "^5.15.0",
37
+ "@wordpress/core-data": "^5.0.0",
38
+ "@wordpress/data": "^7.1.0",
39
+ "@wordpress/deprecated": "^3.17.0",
40
+ "@wordpress/editor": "^12.16.0",
41
+ "@wordpress/element": "^4.15.0",
42
+ "@wordpress/hooks": "^3.17.0",
43
+ "@wordpress/html-entities": "^3.17.0",
44
+ "@wordpress/i18n": "^4.17.0",
45
+ "@wordpress/icons": "^9.8.0",
46
+ "@wordpress/interface": "^4.16.0",
47
+ "@wordpress/keyboard-shortcuts": "^3.15.0",
48
+ "@wordpress/keycodes": "^3.17.0",
49
+ "@wordpress/media-utils": "^4.8.0",
50
+ "@wordpress/notices": "^3.17.0",
51
+ "@wordpress/plugins": "^4.15.0",
52
+ "@wordpress/preferences": "^2.9.0",
53
+ "@wordpress/reusable-blocks": "^3.15.0",
54
+ "@wordpress/style-engine": "^0.16.0",
55
+ "@wordpress/url": "^3.18.0",
56
+ "@wordpress/viewport": "^4.15.0",
57
57
  "classnames": "^2.3.1",
58
58
  "downloadjs": "^1.4.7",
59
59
  "history": "^5.1.0",
@@ -68,5 +68,5 @@
68
68
  "publishConfig": {
69
69
  "access": "public"
70
70
  },
71
- "gitHead": "ba8a396d2f418e53a6c4c50575582f3f3eb11ff7"
71
+ "gitHead": "0d732d4b184adcb28cc83087603e81b764390d4b"
72
72
  }
@@ -41,6 +41,7 @@ import {
41
41
  useTaxonomiesMenuItems,
42
42
  usePostTypeMenuItems,
43
43
  useAuthorMenuItem,
44
+ usePostTypeArchiveMenuItems,
44
45
  } from './utils';
45
46
  import AddCustomGenericTemplateModal from './add-custom-generic-template-modal';
46
47
  import { useHistory } from '../routes';
@@ -301,6 +302,7 @@ function useMissingTemplates(
301
302
  } );
302
303
  const missingTemplates = [
303
304
  ...enhancedMissingDefaultTemplateTypes,
305
+ ...usePostTypeArchiveMenuItems(),
304
306
  ...postTypesMenuItems,
305
307
  ...taxonomiesMenuItems,
306
308
  ];
@@ -12,7 +12,7 @@ import { store as editorStore } from '@wordpress/editor';
12
12
  import { decodeEntities } from '@wordpress/html-entities';
13
13
  import { useMemo, useCallback } from '@wordpress/element';
14
14
  import { __, sprintf } from '@wordpress/i18n';
15
- import { blockMeta, post } from '@wordpress/icons';
15
+ import { blockMeta, post, archive } from '@wordpress/icons';
16
16
 
17
17
  /**
18
18
  * @typedef IHasNameAndId
@@ -86,10 +86,90 @@ const usePublicTaxonomies = () => {
86
86
  }, [ taxonomies ] );
87
87
  };
88
88
 
89
+ function usePostTypeNeedsUniqueIdentifier( publicPostTypes ) {
90
+ const postTypeLabels = useMemo( () =>
91
+ publicPostTypes?.reduce( ( accumulator, { labels } ) => {
92
+ const singularName = labels.singular_name.toLowerCase();
93
+ accumulator[ singularName ] =
94
+ ( accumulator[ singularName ] || 0 ) + 1;
95
+ return accumulator;
96
+ }, {} )
97
+ );
98
+ return useCallback(
99
+ ( { labels, slug } ) => {
100
+ const singularName = labels.singular_name.toLowerCase();
101
+ return postTypeLabels[ singularName ] > 1 && singularName !== slug;
102
+ },
103
+ [ postTypeLabels ]
104
+ );
105
+ }
106
+
107
+ export function usePostTypeArchiveMenuItems() {
108
+ const publicPostTypes = usePublicPostTypes();
109
+ const postTypesWithArchives = useMemo(
110
+ () => publicPostTypes?.filter( ( postType ) => postType.has_archive ),
111
+ [ publicPostTypes ]
112
+ );
113
+ const existingTemplates = useExistingTemplates();
114
+ const needsUniqueIdentifier = usePostTypeNeedsUniqueIdentifier(
115
+ postTypesWithArchives
116
+ );
117
+ return useMemo(
118
+ () =>
119
+ postTypesWithArchives
120
+ ?.filter(
121
+ ( postType ) =>
122
+ ! ( existingTemplates || [] ).some(
123
+ ( existingTemplate ) =>
124
+ existingTemplate.slug ===
125
+ 'archive-' + postType.slug
126
+ )
127
+ )
128
+ .map( ( postType ) => {
129
+ let title;
130
+ if ( needsUniqueIdentifier( postType ) ) {
131
+ title = sprintf(
132
+ // translators: %1s: Name of the post type e.g: "Post"; %2s: Slug of the post type e.g: "book".
133
+ __( 'Archive: %1$s (%2$s)' ),
134
+ postType.labels.singular_name,
135
+ postType.slug
136
+ );
137
+ } else {
138
+ title = sprintf(
139
+ // translators: %s: Name of the post type e.g: "Post".
140
+ __( 'Archive: %s' ),
141
+ postType.labels.singular_name
142
+ );
143
+ }
144
+ return {
145
+ slug: 'archive-' + postType.slug,
146
+ description: sprintf(
147
+ // translators: %s: Name of the post type e.g: "Post".
148
+ __(
149
+ 'Displays an archive with the latests posts of type: %s.'
150
+ ),
151
+ postType.labels.singular_name
152
+ ),
153
+ title,
154
+ // `icon` is the `menu_icon` property of a post type. We
155
+ // only handle `dashicons` for now, even if the `menu_icon`
156
+ // also supports urls and svg as values.
157
+ icon: postType.icon?.startsWith( 'dashicons-' )
158
+ ? postType.icon.slice( 10 )
159
+ : archive,
160
+ templatePrefix: 'archive',
161
+ };
162
+ } ) || [],
163
+ [ postTypesWithArchives, existingTemplates, needsUniqueIdentifier ]
164
+ );
165
+ }
166
+
89
167
  export const usePostTypeMenuItems = ( onClickMenuItem ) => {
90
168
  const publicPostTypes = usePublicPostTypes();
91
169
  const existingTemplates = useExistingTemplates();
92
170
  const defaultTemplateTypes = useDefaultTemplateTypes();
171
+ const needsUniqueIdentifier =
172
+ usePostTypeNeedsUniqueIdentifier( publicPostTypes );
93
173
  // `page`is a special case in template hierarchy.
94
174
  const templatePrefixes = useMemo(
95
175
  () =>
@@ -103,21 +183,6 @@ export const usePostTypeMenuItems = ( onClickMenuItem ) => {
103
183
  }, {} ),
104
184
  [ publicPostTypes ]
105
185
  );
106
- // We need to keep track of naming conflicts. If a conflict
107
- // occurs, we need to add slug.
108
- const postTypeLabels = publicPostTypes?.reduce(
109
- ( accumulator, { labels } ) => {
110
- const singularName = labels.singular_name.toLowerCase();
111
- accumulator[ singularName ] =
112
- ( accumulator[ singularName ] || 0 ) + 1;
113
- return accumulator;
114
- },
115
- {}
116
- );
117
- const needsUniqueIdentifier = ( labels, slug ) => {
118
- const singularName = labels.singular_name.toLowerCase();
119
- return postTypeLabels[ singularName ] > 1 && singularName !== slug;
120
- };
121
186
  const postTypesInfo = useEntitiesInfo( 'postType', templatePrefixes );
122
187
  const existingTemplateSlugs = ( existingTemplates || [] ).map(
123
188
  ( { slug } ) => slug
@@ -134,10 +199,7 @@ export const usePostTypeMenuItems = ( onClickMenuItem ) => {
134
199
  );
135
200
  const hasGeneralTemplate =
136
201
  existingTemplateSlugs?.includes( generalTemplateSlug );
137
- const _needsUniqueIdentifier = needsUniqueIdentifier(
138
- labels,
139
- slug
140
- );
202
+ const _needsUniqueIdentifier = needsUniqueIdentifier( postType );
141
203
  let menuItemTitle = sprintf(
142
204
  // translators: %s: Name of the post type e.g: "Post".
143
205
  __( 'Single item: %s' ),
@@ -2,7 +2,6 @@
2
2
  * External dependencies
3
3
  */
4
4
  import classnames from 'classnames';
5
- import { omit, unionBy } from 'lodash';
6
5
 
7
6
  /**
8
7
  * WordPress dependencies
@@ -80,31 +79,50 @@ export default function BlockEditor( { setIsInserterOpen } ) {
80
79
  );
81
80
 
82
81
  const blockPatterns = useMemo(
83
- () => unionBy( settingsBlockPatterns, restBlockPatterns, 'name' ),
84
- [ settingsBlockPatterns, restBlockPatterns ]
82
+ () =>
83
+ [
84
+ ...( settingsBlockPatterns || [] ),
85
+ ...( restBlockPatterns || [] ),
86
+ ]
87
+ .filter(
88
+ ( x, index, arr ) =>
89
+ index === arr.findIndex( ( y ) => x.name === y.name )
90
+ )
91
+ .filter( ( { postTypes } ) => {
92
+ return (
93
+ ! postTypes ||
94
+ ( Array.isArray( postTypes ) &&
95
+ postTypes.includes( templateType ) )
96
+ );
97
+ } ),
98
+ [ settingsBlockPatterns, restBlockPatterns, templateType ]
85
99
  );
86
100
 
87
101
  const blockPatternCategories = useMemo(
88
102
  () =>
89
- unionBy(
90
- settingsBlockPatternCategories,
91
- restBlockPatternCategories,
92
- 'name'
103
+ [
104
+ ...( settingsBlockPatternCategories || [] ),
105
+ ...( restBlockPatternCategories || [] ),
106
+ ].filter(
107
+ ( x, index, arr ) =>
108
+ index === arr.findIndex( ( y ) => x.name === y.name )
93
109
  ),
94
110
  [ settingsBlockPatternCategories, restBlockPatternCategories ]
95
111
  );
96
112
 
97
- const settings = useMemo(
98
- () => ( {
99
- ...omit( storedSettings, [
100
- '__experimentalAdditionalBlockPatterns',
101
- '__experimentalAdditionalBlockPatternCategories',
102
- ] ),
113
+ const settings = useMemo( () => {
114
+ const {
115
+ __experimentalAdditionalBlockPatterns,
116
+ __experimentalAdditionalBlockPatternCategories,
117
+ ...restStoredSettings
118
+ } = storedSettings;
119
+
120
+ return {
121
+ ...restStoredSettings,
103
122
  __experimentalBlockPatterns: blockPatterns,
104
123
  __experimentalBlockPatternCategories: blockPatternCategories,
105
- } ),
106
- [ storedSettings, blockPatterns, blockPatternCategories ]
107
- );
124
+ };
125
+ }, [ storedSettings, blockPatterns, blockPatternCategories ] );
108
126
 
109
127
  const [ blocks, onInput, onChange ] = useEntityBlockEditor(
110
128
  'postType',
@@ -8,6 +8,7 @@ import {
8
8
  __unstableEditorStyles as EditorStyles,
9
9
  __unstableIframe as Iframe,
10
10
  __unstableUseMouseMoveTypingReset as useMouseMoveTypingReset,
11
+ store as blockEditorStore,
11
12
  } from '@wordpress/block-editor';
12
13
  import { useSelect } from '@wordpress/data';
13
14
  import { useMergeRefs } from '@wordpress/compose';
@@ -37,9 +38,14 @@ const HANDLE_STYLES_OVERRIDE = {
37
38
  };
38
39
 
39
40
  function ResizableEditor( { enableResizing, settings, children, ...props } ) {
40
- const deviceType = useSelect(
41
- ( select ) =>
42
- select( editSiteStore ).__experimentalGetPreviewDeviceType(),
41
+ const { deviceType, isZoomOutMode } = useSelect(
42
+ ( select ) => ( {
43
+ deviceType:
44
+ select( editSiteStore ).__experimentalGetPreviewDeviceType(),
45
+ isZoomOutMode:
46
+ select( blockEditorStore ).__unstableGetEditorMode() ===
47
+ 'zoom-out',
48
+ } ),
43
49
  []
44
50
  );
45
51
  const deviceStyles = useResizeCanvas( deviceType );
@@ -163,6 +169,7 @@ function ResizableEditor( { enableResizing, settings, children, ...props } ) {
163
169
  } }
164
170
  >
165
171
  <Iframe
172
+ isZoomedOut={ isZoomOutMode }
166
173
  style={ enableResizing ? { height } : deviceStyles }
167
174
  head={
168
175
  <>
@@ -6,14 +6,13 @@
6
6
 
7
7
  &__body {
8
8
  width: 100%;
9
- padding: 0 $grid-unit-15 $grid-unit-15 $grid-unit-15;
9
+ padding: $grid-unit-15;
10
10
  max-width: $break-xlarge;
11
11
  margin-left: auto;
12
12
  margin-right: auto;
13
13
 
14
14
  @include break-large() {
15
- padding: $grid-unit-20 $grid-unit-30 #{ $grid-unit-60 * 2 } $grid-unit-30;
16
- padding: 0 $grid-unit-30 $grid-unit-30 $grid-unit-30;
15
+ padding: $grid-unit-30;
17
16
  }
18
17
  }
19
18
 
@@ -9,6 +9,7 @@ import {
9
9
  BlockContextProvider,
10
10
  BlockBreadcrumb,
11
11
  BlockStyles,
12
+ store as blockEditorStore,
12
13
  } from '@wordpress/block-editor';
13
14
  import {
14
15
  InterfaceSkeleton,
@@ -77,6 +78,7 @@ function Editor( { onError } ) {
77
78
  nextShortcut,
78
79
  editorMode,
79
80
  showIconLabels,
81
+ blockEditorMode,
80
82
  } = useSelect( ( select ) => {
81
83
  const {
82
84
  isInserterOpened,
@@ -89,6 +91,7 @@ function Editor( { onError } ) {
89
91
  getEditorMode,
90
92
  } = select( editSiteStore );
91
93
  const { hasFinishedResolution, getEntityRecord } = select( coreStore );
94
+ const { __unstableGetEditorMode } = select( blockEditorStore );
92
95
  const postType = getEditedPostType();
93
96
  const postId = getEditedPostId();
94
97
 
@@ -125,6 +128,7 @@ function Editor( { onError } ) {
125
128
  'core/edit-site',
126
129
  'showIconLabels'
127
130
  ),
131
+ blockEditorMode: __unstableGetEditorMode(),
128
132
  };
129
133
  }, [] );
130
134
  const { setPage, setIsInserterOpened } = useDispatch( editSiteStore );
@@ -320,11 +324,14 @@ function Editor( { onError } ) {
320
324
  </>
321
325
  }
322
326
  footer={
323
- <BlockBreadcrumb
324
- rootLabelText={ __(
325
- 'Template'
326
- ) }
327
- />
327
+ blockEditorMode !==
328
+ 'zoom-out' ? (
329
+ <BlockBreadcrumb
330
+ rootLabelText={ __(
331
+ 'Template'
332
+ ) }
333
+ />
334
+ ) : undefined
328
335
  }
329
336
  shortcuts={ {
330
337
  previous: previousShortcut,
@@ -121,20 +121,21 @@ function splitStyleValue( value ) {
121
121
  function splitGapValue( value ) {
122
122
  // Check for shorthand value (a string value).
123
123
  if ( value && typeof value === 'string' ) {
124
- // Convert to value for individual sides for BoxControl.
124
+ // If the value is a string, treat it as a single side (top) for the spacing controls.
125
125
  return {
126
126
  top: value,
127
- right: value,
128
- bottom: value,
129
- left: value,
130
127
  };
131
128
  }
132
129
 
133
- return {
134
- ...value,
135
- right: value?.left,
136
- bottom: value?.top,
137
- };
130
+ if ( value ) {
131
+ return {
132
+ ...value,
133
+ right: value?.left,
134
+ bottom: value?.top,
135
+ };
136
+ }
137
+
138
+ return value;
138
139
  }
139
140
 
140
141
  // Props for managing `layout.contentSize`.
@@ -238,21 +239,26 @@ function useMarginProps( name ) {
238
239
  function useBlockGapProps( name ) {
239
240
  const [ gapValue, setGapValue ] = useStyle( 'spacing.blockGap', name );
240
241
  const gapValues = splitGapValue( gapValue );
241
- const setGapValues = ( nextBoxGapValue ) => {
242
- if ( ! nextBoxGapValue ) {
243
- setGapValue( null );
244
- }
245
- setGapValue( {
246
- top: nextBoxGapValue?.top,
247
- left: nextBoxGapValue?.left,
248
- } );
249
- };
250
242
  const gapSides = useCustomSides( name, 'blockGap' );
251
243
  const isAxialGap =
252
244
  gapSides && gapSides.some( ( side ) => AXIAL_SIDES.includes( side ) );
253
245
  const resetGapValue = () => setGapValue( undefined );
254
246
  const [ userSetGapValue ] = useStyle( 'spacing.blockGap', name, 'user' );
255
247
  const hasGapValue = () => !! userSetGapValue;
248
+ const setGapValues = ( nextBoxGapValue ) => {
249
+ if ( ! nextBoxGapValue ) {
250
+ setGapValue( null );
251
+ }
252
+ // If axial gap is not enabled, treat the 'top' value as the shorthand gap value.
253
+ if ( ! isAxialGap && nextBoxGapValue?.hasOwnProperty( 'top' ) ) {
254
+ setGapValue( nextBoxGapValue.top );
255
+ } else {
256
+ setGapValue( {
257
+ top: nextBoxGapValue?.top,
258
+ left: nextBoxGapValue?.left,
259
+ } );
260
+ }
261
+ };
256
262
  return {
257
263
  gapValue,
258
264
  gapValues,
@@ -469,27 +475,42 @@ export default function DimensionsPanel( { name } ) {
469
475
  label={ __( 'Block spacing' ) }
470
476
  onDeselect={ resetGapValue }
471
477
  isShownByDefault={ true }
478
+ className={ classnames( {
479
+ 'tools-panel-item-spacing': showSpacingPresetsControl,
480
+ } ) }
472
481
  >
473
- { isAxialGap ? (
474
- <BoxControl
482
+ { ! showSpacingPresetsControl &&
483
+ ( isAxialGap ? (
484
+ <BoxControl
485
+ label={ __( 'Block spacing' ) }
486
+ min={ 0 }
487
+ onChange={ setGapValues }
488
+ units={ units }
489
+ sides={ gapSides }
490
+ values={ gapValues }
491
+ allowReset={ false }
492
+ splitOnAxis={ isAxialGap }
493
+ />
494
+ ) : (
495
+ <UnitControl
496
+ label={ __( 'Block spacing' ) }
497
+ __unstableInputWidth="80px"
498
+ min={ 0 }
499
+ onChange={ setGapValue }
500
+ units={ units }
501
+ value={ gapValue }
502
+ />
503
+ ) ) }
504
+ { showSpacingPresetsControl && (
505
+ <SpacingSizesControl
475
506
  label={ __( 'Block spacing' ) }
476
507
  min={ 0 }
477
508
  onChange={ setGapValues }
478
- units={ units }
479
- sides={ gapSides }
509
+ sides={ isAxialGap ? gapSides : [ 'top' ] } // Use 'top' as the shorthand property in non-axial configurations.
480
510
  values={ gapValues }
481
511
  allowReset={ false }
482
512
  splitOnAxis={ isAxialGap }
483
513
  />
484
- ) : (
485
- <UnitControl
486
- label={ __( 'Block spacing' ) }
487
- __unstableInputWidth="80px"
488
- min={ 0 }
489
- onChange={ setGapValue }
490
- units={ units }
491
- value={ gapValue }
492
- />
493
514
  ) }
494
515
  </ToolsPanelItem>
495
516
  ) }
@@ -45,7 +45,18 @@ export default function GradientPalettePanel( { name } ) {
45
45
  'color.defaultGradients',
46
46
  name
47
47
  );
48
- const [ duotonePalette ] = useSetting( 'color.duotone' ) || [];
48
+
49
+ const [ customDuotone ] = useSetting( 'color.duotone.custom' ) || [];
50
+ const [ defaultDuotone ] = useSetting( 'color.duotone.default' ) || [];
51
+ const [ themeDuotone ] = useSetting( 'color.duotone.theme' ) || [];
52
+ const [ defaultDuotoneEnabled ] = useSetting( 'color.defaultDuotone' );
53
+
54
+ const duotonePalette = [
55
+ ...( customDuotone || [] ),
56
+ ...( themeDuotone || [] ),
57
+ ...( defaultDuotone && defaultDuotoneEnabled ? defaultDuotone : [] ),
58
+ ];
59
+
49
60
  return (
50
61
  <VStack
51
62
  className="edit-site-global-styles-gradient-palette-panel"
@@ -80,17 +91,19 @@ export default function GradientPalettePanel( { name } ) {
80
91
  ) }
81
92
  slugPrefix="custom-"
82
93
  />
83
- <div>
84
- <Subtitle>{ __( 'Duotone' ) }</Subtitle>
85
- <Spacer margin={ 3 } />
86
- <DuotonePicker
87
- duotonePalette={ duotonePalette }
88
- disableCustomDuotone={ true }
89
- disableCustomColors={ true }
90
- clearable={ false }
91
- onChange={ noop }
92
- />
93
- </div>
94
+ { !! duotonePalette && !! duotonePalette.length && (
95
+ <div>
96
+ <Subtitle>{ __( 'Duotone' ) }</Subtitle>
97
+ <Spacer margin={ 3 } />
98
+ <DuotonePicker
99
+ duotonePalette={ duotonePalette }
100
+ disableCustomDuotone={ true }
101
+ disableCustomColors={ true }
102
+ clearable={ false }
103
+ onChange={ noop }
104
+ />
105
+ </div>
106
+ ) }
94
107
  </VStack>
95
108
  );
96
109
  }
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import { get, cloneDeep, set, isEqual, has } from 'lodash';
4
+ import { get, set, isEqual } from 'lodash';
5
5
 
6
6
  /**
7
7
  * WordPress dependencies
@@ -48,7 +48,8 @@ export function useSetting( path, blockName, source = 'all' ) {
48
48
 
49
49
  const setSetting = ( newValue ) => {
50
50
  setUserConfig( ( currentConfig ) => {
51
- const newUserConfig = cloneDeep( currentConfig );
51
+ // Deep clone `currentConfig` to avoid mutating it later.
52
+ const newUserConfig = JSON.parse( JSON.stringify( currentConfig ) );
52
53
  const pathToSet = PATHS_WITH_MERGE[ path ]
53
54
  ? fullPath + '.custom'
54
55
  : fullPath;
@@ -109,7 +110,8 @@ export function useStyle( path, blockName, source = 'all' ) {
109
110
 
110
111
  const setStyle = ( newValue ) => {
111
112
  setUserConfig( ( currentConfig ) => {
112
- const newUserConfig = cloneDeep( currentConfig );
113
+ // Deep clone `currentConfig` to avoid mutating it later.
114
+ const newUserConfig = JSON.parse( JSON.stringify( currentConfig ) );
113
115
  set(
114
116
  newUserConfig,
115
117
  finalPath,
@@ -210,10 +212,8 @@ export function getSupportedGlobalStylesPanels( name ) {
210
212
  // unset, we still enable it.
211
213
  if ( STYLE_PROPERTY[ styleName ].requiresOptOut ) {
212
214
  if (
213
- has(
214
- blockType.supports,
215
- STYLE_PROPERTY[ styleName ].support[ 0 ]
216
- ) &&
215
+ STYLE_PROPERTY[ styleName ].support[ 0 ] in
216
+ blockType.supports &&
217
217
  get(
218
218
  blockType.supports,
219
219
  STYLE_PROPERTY[ styleName ].support
@@ -79,13 +79,13 @@ const StylesPreview = ( { label, isFocused } ) => {
79
79
  )
80
80
  .slice( 0, 2 );
81
81
 
82
- // Reset leaked styles from WP common.css.
82
+ // Reset leaked styles from WP common.css and remove main content layout padding.
83
83
  const editorStyles = useMemo( () => {
84
84
  if ( styles ) {
85
85
  return [
86
86
  ...styles,
87
87
  {
88
- css: 'body{min-width: 0;}',
88
+ css: 'body{min-width: 0;padding: 0;}',
89
89
  isGlobalStyles: true,
90
90
  },
91
91
  ];