@wordpress/block-editor 15.17.0 → 15.18.1-next.v.202604201441.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 (79) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/build/components/block-visibility/viewport-visibility-info.cjs +2 -2
  3. package/build/components/block-visibility/viewport-visibility-info.cjs.map +1 -1
  4. package/build/components/global-styles/color-panel.cjs.map +2 -2
  5. package/build/components/global-styles/dimensions-panel.cjs +87 -62
  6. package/build/components/global-styles/dimensions-panel.cjs.map +2 -2
  7. package/build/components/global-styles/filters-panel.cjs.map +2 -2
  8. package/build/components/global-styles/hooks.cjs +9 -7
  9. package/build/components/global-styles/hooks.cjs.map +2 -2
  10. package/build/components/url-popover/image-url-input-ui.cjs +1 -1
  11. package/build/components/url-popover/image-url-input-ui.cjs.map +2 -2
  12. package/build/components/writing-flow/use-arrow-nav.cjs +1 -1
  13. package/build/components/writing-flow/use-arrow-nav.cjs.map +2 -2
  14. package/build/hooks/block-fields/link/index.cjs +1 -1
  15. package/build/hooks/block-fields/link/index.cjs.map +1 -1
  16. package/build/hooks/custom-css.cjs +21 -0
  17. package/build/hooks/custom-css.cjs.map +3 -3
  18. package/build/hooks/dimensions.cjs +5 -1
  19. package/build/hooks/dimensions.cjs.map +2 -2
  20. package/build/hooks/grid-visualizer.cjs +1 -1
  21. package/build/hooks/grid-visualizer.cjs.map +1 -1
  22. package/build/hooks/layout-child.cjs +1 -1
  23. package/build/hooks/layout-child.cjs.map +1 -1
  24. package/build/hooks/utils.cjs +4 -0
  25. package/build/hooks/utils.cjs.map +2 -2
  26. package/build-module/components/block-visibility/viewport-visibility-info.mjs +2 -2
  27. package/build-module/components/block-visibility/viewport-visibility-info.mjs.map +1 -1
  28. package/build-module/components/global-styles/color-panel.mjs.map +2 -2
  29. package/build-module/components/global-styles/dimensions-panel.mjs +87 -62
  30. package/build-module/components/global-styles/dimensions-panel.mjs.map +2 -2
  31. package/build-module/components/global-styles/filters-panel.mjs.map +2 -2
  32. package/build-module/components/global-styles/hooks.mjs +9 -7
  33. package/build-module/components/global-styles/hooks.mjs.map +2 -2
  34. package/build-module/components/url-popover/image-url-input-ui.mjs +1 -1
  35. package/build-module/components/url-popover/image-url-input-ui.mjs.map +2 -2
  36. package/build-module/components/writing-flow/use-arrow-nav.mjs +1 -1
  37. package/build-module/components/writing-flow/use-arrow-nav.mjs.map +2 -2
  38. package/build-module/hooks/block-fields/link/index.mjs +1 -1
  39. package/build-module/hooks/block-fields/link/index.mjs.map +1 -1
  40. package/build-module/hooks/custom-css.mjs +23 -2
  41. package/build-module/hooks/custom-css.mjs.map +2 -2
  42. package/build-module/hooks/dimensions.mjs +5 -1
  43. package/build-module/hooks/dimensions.mjs.map +2 -2
  44. package/build-module/hooks/grid-visualizer.mjs +1 -1
  45. package/build-module/hooks/grid-visualizer.mjs.map +1 -1
  46. package/build-module/hooks/layout-child.mjs +1 -1
  47. package/build-module/hooks/layout-child.mjs.map +1 -1
  48. package/build-module/hooks/utils.mjs +4 -0
  49. package/build-module/hooks/utils.mjs.map +2 -2
  50. package/build-style/content-rtl.css +1 -1
  51. package/build-style/content.css +1 -1
  52. package/build-style/style-rtl.css +12 -12
  53. package/build-style/style.css +12 -12
  54. package/package.json +38 -38
  55. package/src/components/background-image-control/style.scss +1 -1
  56. package/src/components/block-pattern-setup/style.scss +2 -2
  57. package/src/components/block-patterns-list/style.scss +1 -1
  58. package/src/components/block-switcher/style.scss +2 -2
  59. package/src/components/block-visibility/viewport-visibility-info.js +2 -2
  60. package/src/components/global-styles/color-panel.js +0 -2
  61. package/src/components/global-styles/dimensions-panel.js +100 -73
  62. package/src/components/global-styles/filters-panel.js +0 -2
  63. package/src/components/global-styles/hooks.js +9 -7
  64. package/src/components/global-styles/style.scss +1 -1
  65. package/src/components/inserter/style.scss +2 -2
  66. package/src/components/inserter-list-item/style.scss +1 -1
  67. package/src/components/list-view/style.scss +1 -1
  68. package/src/components/media-placeholder/content.scss +1 -1
  69. package/src/components/url-input/style.scss +1 -1
  70. package/src/components/url-popover/image-url-input-ui.js +1 -1
  71. package/src/components/writing-flow/use-arrow-nav.js +9 -2
  72. package/src/hooks/block-fields/link/index.js +1 -1
  73. package/src/hooks/custom-css.js +30 -2
  74. package/src/hooks/dimensions.js +6 -1
  75. package/src/hooks/grid-visualizer.js +1 -1
  76. package/src/hooks/layout-child.js +1 -1
  77. package/src/hooks/test/dimensions.js +16 -0
  78. package/src/hooks/test/style.js +2 -0
  79. package/src/hooks/utils.js +4 -0
@@ -33,69 +33,63 @@ import { setImmutably } from '../../utils/object';
33
33
  const AXIAL_SIDES = [ 'horizontal', 'vertical' ];
34
34
 
35
35
  export function useHasDimensionsPanel( settings ) {
36
- const hasContentSize = useHasContentSize( settings );
37
- const hasWideSize = useHasWideSize( settings );
38
- const hasPadding = useHasPadding( settings );
39
- const hasMargin = useHasMargin( settings );
40
- const hasGap = useHasGap( settings );
41
- const hasHeight = useHasHeight( settings );
42
- const hasMinHeight = useHasMinHeight( settings );
43
- const hasWidth = useHasWidth( settings );
44
- const hasAspectRatio = useHasAspectRatio( settings );
45
- const hasChildLayout = useHasChildLayout( settings );
46
-
47
36
  return (
48
37
  Platform.OS === 'web' &&
49
- ( hasContentSize ||
50
- hasWideSize ||
51
- hasPadding ||
52
- hasMargin ||
53
- hasGap ||
54
- hasHeight ||
55
- hasMinHeight ||
56
- hasWidth ||
57
- hasAspectRatio ||
58
- hasChildLayout )
38
+ ( hasContentSize( settings ) ||
39
+ hasWideSize( settings ) ||
40
+ hasPadding( settings ) ||
41
+ hasMargin( settings ) ||
42
+ hasGap( settings ) ||
43
+ hasHeight( settings ) ||
44
+ hasMinHeight( settings ) ||
45
+ hasMinWidth( settings ) ||
46
+ hasWidth( settings ) ||
47
+ hasAspectRatio( settings ) ||
48
+ hasChildLayout( settings ) )
59
49
  );
60
50
  }
61
51
 
62
- function useHasContentSize( settings ) {
52
+ function hasContentSize( settings ) {
63
53
  return settings?.layout?.contentSize;
64
54
  }
65
55
 
66
- function useHasWideSize( settings ) {
56
+ function hasWideSize( settings ) {
67
57
  return settings?.layout?.wideSize;
68
58
  }
69
59
 
70
- function useHasPadding( settings ) {
60
+ function hasPadding( settings ) {
71
61
  return settings?.spacing?.padding;
72
62
  }
73
63
 
74
- function useHasMargin( settings ) {
64
+ function hasMargin( settings ) {
75
65
  return settings?.spacing?.margin;
76
66
  }
77
67
 
78
- function useHasGap( settings ) {
68
+ function hasGap( settings ) {
79
69
  return settings?.spacing?.blockGap;
80
70
  }
81
71
 
82
- function useHasHeight( settings ) {
72
+ function hasHeight( settings ) {
83
73
  return settings?.dimensions?.height;
84
74
  }
85
75
 
86
- function useHasMinHeight( settings ) {
76
+ function hasMinHeight( settings ) {
87
77
  return settings?.dimensions?.minHeight;
88
78
  }
89
79
 
90
- function useHasWidth( settings ) {
80
+ function hasMinWidth( settings ) {
81
+ return settings?.dimensions?.minWidth;
82
+ }
83
+
84
+ function hasWidth( settings ) {
91
85
  return settings?.dimensions?.width;
92
86
  }
93
87
 
94
- function useHasAspectRatio( settings ) {
88
+ function hasAspectRatio( settings ) {
95
89
  return settings?.dimensions?.aspectRatio;
96
90
  }
97
91
 
98
- function useHasChildLayout( settings ) {
92
+ function hasChildLayout( settings ) {
99
93
  const {
100
94
  type: parentLayoutType = 'default',
101
95
  default: { type: defaultParentLayoutType = 'default' } = {},
@@ -111,7 +105,7 @@ function useHasChildLayout( settings ) {
111
105
  return !! settings?.layout && support;
112
106
  }
113
107
 
114
- function useHasSpacingPresets( settings ) {
108
+ function hasSpacingPresets( settings ) {
115
109
  const { defaultSpacingSizes, spacingSizes } = settings?.spacing || {};
116
110
  return (
117
111
  ( defaultSpacingSizes !== false &&
@@ -219,6 +213,7 @@ const DEFAULT_CONTROLS = {
219
213
  blockGap: true,
220
214
  height: true,
221
215
  minHeight: true,
216
+ minWidth: true,
222
217
  width: true,
223
218
  aspectRatio: true,
224
219
  childLayout: true,
@@ -257,7 +252,7 @@ export default function DimensionsPanel( {
257
252
  );
258
253
  };
259
254
 
260
- const showSpacingPresetsControl = useHasSpacingPresets( settings );
255
+ const showSpacingPresetsControl = hasSpacingPresets( settings );
261
256
  const units = useCustomUnits( {
262
257
  availableUnits: settings?.spacing?.units || [
263
258
  '%',
@@ -272,9 +267,40 @@ export default function DimensionsPanel( {
272
267
  const minimumMargin = -Infinity;
273
268
  const [ minMarginValue, setMinMarginValue ] = useState( minimumMargin );
274
269
 
270
+ const resetAllFilter = useCallback( ( previousValue ) => {
271
+ return {
272
+ ...previousValue,
273
+ layout: cleanEmptyObject( {
274
+ ...previousValue?.layout,
275
+ contentSize: undefined,
276
+ wideSize: undefined,
277
+ selfStretch: undefined,
278
+ flexSize: undefined,
279
+ columnStart: undefined,
280
+ rowStart: undefined,
281
+ columnSpan: undefined,
282
+ rowSpan: undefined,
283
+ } ),
284
+ spacing: {
285
+ ...previousValue?.spacing,
286
+ padding: undefined,
287
+ margin: undefined,
288
+ blockGap: undefined,
289
+ },
290
+ dimensions: {
291
+ ...previousValue?.dimensions,
292
+ height: undefined,
293
+ minHeight: undefined,
294
+ minWidth: undefined,
295
+ aspectRatio: undefined,
296
+ width: undefined,
297
+ },
298
+ };
299
+ }, [] );
300
+
275
301
  // Content Width
276
302
  const showContentSizeControl =
277
- useHasContentSize( settings ) && includeLayoutControls;
303
+ hasContentSize( settings ) && includeLayoutControls;
278
304
  const contentSizeValue = decodeValue( inheritedValue?.layout?.contentSize );
279
305
  const setContentSizeValue = ( newValue ) => {
280
306
  onChange(
@@ -290,7 +316,7 @@ export default function DimensionsPanel( {
290
316
 
291
317
  // Wide Width
292
318
  const showWideSizeControl =
293
- useHasWideSize( settings ) && includeLayoutControls;
319
+ hasWideSize( settings ) && includeLayoutControls;
294
320
  const wideSizeValue = decodeValue( inheritedValue?.layout?.wideSize );
295
321
  const setWideSizeValue = ( newValue ) => {
296
322
  onChange(
@@ -305,7 +331,7 @@ export default function DimensionsPanel( {
305
331
  const resetWideSizeValue = () => setWideSizeValue( undefined );
306
332
 
307
333
  // Padding
308
- const showPaddingControl = useHasPadding( settings );
334
+ const showPaddingControl = hasPadding( settings );
309
335
  const rawPadding = decodeValue( inheritedValue?.spacing?.padding );
310
336
  const paddingValues = splitStyleValue( rawPadding );
311
337
  const paddingSides = Array.isArray( settings?.spacing?.padding )
@@ -325,7 +351,7 @@ export default function DimensionsPanel( {
325
351
  const onMouseOverPadding = () => onVisualize( 'padding' );
326
352
 
327
353
  // Margin
328
- const showMarginControl = useHasMargin( settings );
354
+ const showMarginControl = hasMargin( settings );
329
355
  const rawMargin = decodeValue( inheritedValue?.spacing?.margin );
330
356
  const marginValues = splitStyleValue( rawMargin );
331
357
  const marginSides = Array.isArray( settings?.spacing?.margin )
@@ -345,7 +371,7 @@ export default function DimensionsPanel( {
345
371
  const onMouseOverMargin = () => onVisualize( 'margin' );
346
372
 
347
373
  // Block Gap
348
- const showGapControl = useHasGap( settings );
374
+ const showGapControl = hasGap( settings );
349
375
  const gapSides = Array.isArray( settings?.spacing?.blockGap )
350
376
  ? settings?.spacing?.blockGap
351
377
  : settings?.spacing?.blockGap?.sides;
@@ -376,7 +402,7 @@ export default function DimensionsPanel( {
376
402
  const hasGapValue = () => !! value?.spacing?.blockGap;
377
403
 
378
404
  // Min Height
379
- const showMinHeightControl = useHasMinHeight( settings );
405
+ const showMinHeightControl = hasMinHeight( settings );
380
406
  const minHeightValue = decodeValue( inheritedValue?.dimensions?.minHeight );
381
407
  const setMinHeightValue = ( newValue ) => {
382
408
  const tempValue = setImmutably(
@@ -399,7 +425,7 @@ export default function DimensionsPanel( {
399
425
  const hasMinHeightValue = () => !! value?.dimensions?.minHeight;
400
426
 
401
427
  // Height
402
- const showHeightControl = useHasHeight( settings );
428
+ const showHeightControl = hasHeight( settings );
403
429
  const heightValue = decodeValue( inheritedValue?.dimensions?.height );
404
430
  const setHeightValue = ( newValue ) => {
405
431
  const tempValue = setImmutably(
@@ -421,8 +447,21 @@ export default function DimensionsPanel( {
421
447
  };
422
448
  const hasHeightValue = () => !! value?.dimensions?.height;
423
449
 
450
+ // Min Width
451
+ const showMinWidthControl = hasMinWidth( settings );
452
+ const minWidthValue = decodeValue( inheritedValue?.dimensions?.minWidth );
453
+ const setMinWidthValue = ( newValue ) => {
454
+ onChange(
455
+ setImmutably( value, [ 'dimensions', 'minWidth' ], newValue )
456
+ );
457
+ };
458
+ const resetMinWidthValue = () => {
459
+ setMinWidthValue( undefined );
460
+ };
461
+ const hasMinWidthValue = () => !! value?.dimensions?.minWidth;
462
+
424
463
  // Width
425
- const showWidthControl = useHasWidth( settings );
464
+ const showWidthControl = hasWidth( settings );
426
465
  const widthValue = decodeValue( inheritedValue?.dimensions?.width );
427
466
  const setWidthValue = ( newValue ) => {
428
467
  onChange( setImmutably( value, [ 'dimensions', 'width' ], newValue ) );
@@ -433,7 +472,7 @@ export default function DimensionsPanel( {
433
472
  const hasWidthValue = () => !! value?.dimensions?.width;
434
473
 
435
474
  // Aspect Ratio
436
- const showAspectRatioControl = useHasAspectRatio( settings );
475
+ const showAspectRatioControl = hasAspectRatio( settings );
437
476
  const aspectRatioValue = decodeValue(
438
477
  inheritedValue?.dimensions?.aspectRatio
439
478
  );
@@ -451,7 +490,7 @@ export default function DimensionsPanel( {
451
490
  const hasAspectRatioValue = () => !! value?.dimensions?.aspectRatio;
452
491
 
453
492
  // Child Layout
454
- const showChildLayoutControl = useHasChildLayout( settings );
493
+ const showChildLayoutControl = hasChildLayout( settings );
455
494
  const childLayout = inheritedValue?.layout;
456
495
 
457
496
  const setChildLayout = ( newChildLayout ) => {
@@ -463,36 +502,6 @@ export default function DimensionsPanel( {
463
502
  } );
464
503
  };
465
504
 
466
- const resetAllFilter = useCallback( ( previousValue ) => {
467
- return {
468
- ...previousValue,
469
- layout: cleanEmptyObject( {
470
- ...previousValue?.layout,
471
- contentSize: undefined,
472
- wideSize: undefined,
473
- selfStretch: undefined,
474
- flexSize: undefined,
475
- columnStart: undefined,
476
- rowStart: undefined,
477
- columnSpan: undefined,
478
- rowSpan: undefined,
479
- } ),
480
- spacing: {
481
- ...previousValue?.spacing,
482
- padding: undefined,
483
- margin: undefined,
484
- blockGap: undefined,
485
- },
486
- dimensions: {
487
- ...previousValue?.dimensions,
488
- height: undefined,
489
- minHeight: undefined,
490
- aspectRatio: undefined,
491
- width: undefined,
492
- },
493
- };
494
- }, [] );
495
-
496
505
  const onMouseLeaveControls = () => onVisualize( false );
497
506
 
498
507
  return (
@@ -739,6 +748,24 @@ export default function DimensionsPanel( {
739
748
  />
740
749
  </ToolsPanelItem>
741
750
  ) }
751
+ { showMinWidthControl && (
752
+ <ToolsPanelItem
753
+ hasValue={ hasMinWidthValue }
754
+ label={ __( 'Minimum width' ) }
755
+ onDeselect={ resetMinWidthValue }
756
+ isShownByDefault={
757
+ defaultControls.minWidth ?? DEFAULT_CONTROLS.minWidth
758
+ }
759
+ panelId={ panelId }
760
+ >
761
+ <DimensionControl
762
+ label={ __( 'Minimum width' ) }
763
+ value={ minWidthValue }
764
+ onChange={ setMinWidthValue }
765
+ dimensionSizes={ dimensions?.dimensionSizes }
766
+ />
767
+ </ToolsPanelItem>
768
+ ) }
742
769
  { showHeightControl && (
743
770
  <ToolsPanelItem
744
771
  hasValue={ hasHeightValue }
@@ -10,8 +10,6 @@ import {
10
10
  __experimentalToolsPanel as ToolsPanel,
11
11
  __experimentalToolsPanelItem as ToolsPanelItem,
12
12
  __experimentalHStack as HStack,
13
- // TODO: Replace this ZStack with ad hoc CSS.
14
- // eslint-disable-next-line @wordpress/use-recommended-components
15
13
  __experimentalZStack as ZStack,
16
14
  __experimentalDropdownContentWrapper as DropdownContentWrapper,
17
15
  MenuGroup,
@@ -166,14 +166,16 @@ export function useSettingsForBlockElement(
166
166
  }
167
167
  } );
168
168
 
169
- [ 'aspectRatio', 'height', 'minHeight', 'width' ].forEach( ( key ) => {
170
- if ( ! supportedStyles.includes( key ) ) {
171
- updatedSettings.dimensions = {
172
- ...updatedSettings.dimensions,
173
- [ key ]: false,
174
- };
169
+ [ 'aspectRatio', 'height', 'minHeight', 'minWidth', 'width' ].forEach(
170
+ ( key ) => {
171
+ if ( ! supportedStyles.includes( key ) ) {
172
+ updatedSettings.dimensions = {
173
+ ...updatedSettings.dimensions,
174
+ [ key ]: false,
175
+ };
176
+ }
175
177
  }
176
- } );
178
+ );
177
179
 
178
180
  [ 'radius', 'color', 'style', 'width' ].forEach( ( key ) => {
179
181
  if (
@@ -71,7 +71,7 @@
71
71
  color: $gray-800;
72
72
  border: $gray-200 $border-width solid;
73
73
  border-radius: $radius-small;
74
- cursor: pointer;
74
+ cursor: var(--wpds-cursor-control);
75
75
  display: inline-flex;
76
76
  align-items: center;
77
77
 
@@ -85,7 +85,7 @@ $block-inserter-tabs-height: 44px;
85
85
  .block-editor-inserter__toggle.components-button {
86
86
  display: inline-flex;
87
87
  align-items: center;
88
- cursor: pointer;
88
+ cursor: var(--wpds-cursor-control);
89
89
  border: none;
90
90
  outline: none;
91
91
  padding: 0;
@@ -482,7 +482,7 @@ $block-inserter-tabs-height: 44px;
482
482
 
483
483
  .block-editor-inserter__media-list__list-item {
484
484
  position: relative;
485
- cursor: pointer;
485
+ cursor: var(--wpds-cursor-control);
486
486
  margin-bottom: $grid-unit-30;
487
487
 
488
488
  &.is-placeholder {
@@ -42,7 +42,7 @@
42
42
  padding: $grid-unit-10;
43
43
  align-items: stretch;
44
44
  justify-content: center;
45
- cursor: pointer;
45
+ cursor: var(--wpds-cursor-control);
46
46
  background: transparent;
47
47
  word-break: break-word;
48
48
  @media not ( prefers-reduced-motion ) {
@@ -469,7 +469,7 @@ $block-navigation-max-indent: 8;
469
469
  .block-editor-list-view__expander {
470
470
  height: $icon-size;
471
471
  width: $icon-size;
472
- cursor: pointer;
472
+ cursor: var(--wpds-cursor-control);
473
473
  }
474
474
 
475
475
  .block-editor-list-view-leaf[aria-level] .block-editor-list-view__expander {
@@ -7,7 +7,7 @@
7
7
  min-height: 0;
8
8
 
9
9
  &:hover {
10
- cursor: pointer;
10
+ cursor: var(--wpds-cursor-control);
11
11
  box-shadow: 0 0 0 1px var(--wp-admin-theme-color);
12
12
  }
13
13
  }
@@ -61,7 +61,7 @@ $input-size: 300px;
61
61
  color: $gray-700;
62
62
  display: block;
63
63
  font-size: $default-font-size;
64
- cursor: pointer;
64
+ cursor: var(--wpds-cursor-control);
65
65
  background: $white;
66
66
  width: 100%;
67
67
  border: none;
@@ -38,7 +38,7 @@ const LINK_DESTINATION_NONE = 'none';
38
38
  const LINK_DESTINATION_CUSTOM = 'custom';
39
39
  const LINK_DESTINATION_MEDIA = 'media';
40
40
  const LINK_DESTINATION_ATTACHMENT = 'attachment';
41
- const NEW_TAB_REL = [ 'noreferrer', 'noopener' ];
41
+ const NEW_TAB_REL = [ 'noopener' ];
42
42
 
43
43
  const ImageURLInputUI = ( {
44
44
  linkDestination,
@@ -115,9 +115,16 @@ export function getClosestTabbable(
115
115
  }
116
116
 
117
117
  function isTabCandidate( node ) {
118
- // If it's a block and there are nested focusable nodes, skip because
119
- // there are better candidates.
118
+ // If it's a block wrapper (not itself a contenteditable editing surface)
119
+ // and there are nested focusable nodes, skip because there are better
120
+ // candidates. We must not skip contenteditable nodes that happen to
121
+ // contain links or other focusable inline elements, since those are the
122
+ // correct navigation targets.
123
+ //
124
+ // See https://github.com/WordPress/gutenberg/pull/77474
125
+ // TODO: Consider fixing focus.tabbable
120
126
  if (
127
+ node.contentEditable !== 'true' &&
121
128
  getBlockClientId( node ) &&
122
129
  focus.focusable
123
130
  .find( node )
@@ -18,7 +18,7 @@ import { prependHTTP } from '@wordpress/url';
18
18
  import LinkControl from '../../../components/link-control';
19
19
  import { useInspectorPopoverPlacement } from '../use-inspector-popover-placement';
20
20
 
21
- export const NEW_TAB_REL = 'noreferrer noopener';
21
+ export const NEW_TAB_REL = 'noopener';
22
22
  export const NEW_TAB_TARGET = '_blank';
23
23
  export const NOFOLLOW_REL = 'nofollow';
24
24
 
@@ -1,13 +1,14 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { useMemo } from '@wordpress/element';
5
- import { useSelect } from '@wordpress/data';
4
+ import { useEffect, useMemo } from '@wordpress/element';
5
+ import { useDispatch, useSelect } from '@wordpress/data';
6
6
  import { useInstanceId } from '@wordpress/compose';
7
7
  import { getBlockType, hasBlockSupport } from '@wordpress/blocks';
8
8
  import { __, sprintf } from '@wordpress/i18n';
9
9
  import { processCSSNesting } from '@wordpress/global-styles-engine';
10
10
  import { useBlockEditingMode } from '../components/block-editing-mode';
11
+ import { store as noticesStore } from '@wordpress/notices';
11
12
 
12
13
  /**
13
14
  * Internal dependencies
@@ -69,6 +70,8 @@ function CustomCSSControl( { blockName, setAttributes, style } ) {
69
70
  );
70
71
  }
71
72
 
73
+ const CUSTOM_CSS_WARNING_NOTICE_ID = 'custom-css-edit-warning';
74
+
72
75
  function CustomCSSEdit( { clientId, name, setAttributes } ) {
73
76
  const { style, canEditCSS } = useSelect(
74
77
  ( select ) => {
@@ -113,6 +116,31 @@ function useBlockProps( { style } ) {
113
116
  customCSS.trim().length > 0 &&
114
117
  validateCSS( customCSS );
115
118
 
119
+ const canEditCSS = useSelect(
120
+ ( select ) => select( blockEditorStore ).getSettings().canEditCSS,
121
+ []
122
+ );
123
+
124
+ const { createWarningNotice } = useDispatch( noticesStore );
125
+
126
+ // Show a warning notice when the user lacks edit_css and a block has
127
+ // custom CSS. The fixed notice ID ensures only one notice is shown
128
+ // regardless of how many blocks have CSS.
129
+ const hasCustomCSS = !! customCSS?.trim();
130
+ useEffect( () => {
131
+ if ( ! canEditCSS && hasCustomCSS ) {
132
+ createWarningNotice(
133
+ __(
134
+ 'This post contains blocks with custom CSS. You do not have permission to edit CSS. If you save this post, the custom CSS will be removed.'
135
+ ),
136
+ {
137
+ id: CUSTOM_CSS_WARNING_NOTICE_ID,
138
+ isDismissible: true,
139
+ }
140
+ );
141
+ }
142
+ }, [ canEditCSS, hasCustomCSS, createWarningNotice ] );
143
+
116
144
  const customCSSIdentifier = useInstanceId(
117
145
  CUSTOM_CSS_INSTANCE_REFERENCE,
118
146
  'wp-custom-css'
@@ -102,6 +102,10 @@ export function DimensionsPanel( { clientId, name, setAttributes, settings } ) {
102
102
  '__experimentalDefaultControls',
103
103
  ] );
104
104
  const defaultControls = {
105
+ // In the block inspector, minHeight and minWidth should not
106
+ // be shown by default unless the block explicitly opts in.
107
+ minHeight: false,
108
+ minWidth: false,
105
109
  ...defaultDimensionsControls,
106
110
  ...defaultSpacingControls,
107
111
  };
@@ -161,7 +165,8 @@ export function hasDimensionsSupport( blockName, feature = 'any' ) {
161
165
  support?.aspectRatio ||
162
166
  !! support?.height ||
163
167
  !! support?.minHeight ||
164
- !! support?.width
168
+ !! support?.width ||
169
+ !! support?.minWidth
165
170
  );
166
171
  }
167
172
 
@@ -54,7 +54,7 @@ function GridTools( { clientId, layout } ) {
54
54
  const settings = getSettings();
55
55
  const currentDeviceType =
56
56
  settings?.[ deviceTypeKey ]?.toLowerCase() ||
57
- BLOCK_VISIBILITY_VIEWPORTS.desktop.value;
57
+ BLOCK_VISIBILITY_VIEWPORTS.desktop.key;
58
58
 
59
59
  return {
60
60
  isVisible: true,
@@ -244,7 +244,7 @@ function GridTools( {
244
244
  blockAttributes?.metadata?.blockVisibility,
245
245
  deviceType:
246
246
  settings?.[ deviceTypeKey ]?.toLowerCase() ||
247
- BLOCK_VISIBILITY_VIEWPORTS.desktop.value,
247
+ BLOCK_VISIBILITY_VIEWPORTS.desktop.key,
248
248
  // Check if the selected child block is itself a grid.
249
249
  isChildBlockAGrid: blockAttributes?.layout?.type === 'grid',
250
250
  };
@@ -76,6 +76,22 @@ describe( 'getDimensionsClassesAndStyles', () => {
76
76
  } );
77
77
  } );
78
78
 
79
+ it( 'should return minWidth style', () => {
80
+ const attributes = {
81
+ style: {
82
+ dimensions: {
83
+ minWidth: '200px',
84
+ },
85
+ },
86
+ };
87
+ expect( getDimensionsClassesAndStyles( attributes ) ).toEqual( {
88
+ className: undefined,
89
+ style: {
90
+ minWidth: '200px',
91
+ },
92
+ } );
93
+ } );
94
+
79
95
  it( 'should return all dimension styles when multiple are provided', () => {
80
96
  const attributes = {
81
97
  style: {
@@ -25,6 +25,7 @@ describe( 'getInlineStyles', () => {
25
25
  },
26
26
  dimensions: {
27
27
  minHeight: '50vh',
28
+ minWidth: '200px',
28
29
  },
29
30
  spacing: {
30
31
  blockGap: '1em',
@@ -44,6 +45,7 @@ describe( 'getInlineStyles', () => {
44
45
  fontSize: 10,
45
46
  marginBottom: '15px',
46
47
  minHeight: '50vh',
48
+ minWidth: '200px',
47
49
  paddingTop: '10px',
48
50
  } );
49
51
  } );
@@ -269,6 +269,7 @@ export function useBlockSettings( name, parentLayout ) {
269
269
  aspectRatio,
270
270
  height,
271
271
  minHeight,
272
+ minWidth,
272
273
  width,
273
274
  dimensionSizes,
274
275
  layout,
@@ -332,6 +333,7 @@ export function useBlockSettings( name, parentLayout ) {
332
333
  'dimensions.aspectRatio',
333
334
  'dimensions.height',
334
335
  'dimensions.minHeight',
336
+ 'dimensions.minWidth',
335
337
  'dimensions.width',
336
338
  'dimensions.dimensionSizes',
337
339
  'layout',
@@ -446,6 +448,7 @@ export function useBlockSettings( name, parentLayout ) {
446
448
  aspectRatio,
447
449
  height,
448
450
  minHeight,
451
+ minWidth,
449
452
  width,
450
453
  dimensionSizes,
451
454
  },
@@ -487,6 +490,7 @@ export function useBlockSettings( name, parentLayout ) {
487
490
  aspectRatio,
488
491
  height,
489
492
  minHeight,
493
+ minWidth,
490
494
  width,
491
495
  dimensionSizes,
492
496
  layout,