@wordpress/block-editor 9.8.0 → 9.8.1-next.957ca95e4c.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 (149) hide show
  1. package/build/components/block-list/block-list-compact.native.js +73 -0
  2. package/build/components/block-list/block-list-compact.native.js.map +1 -0
  3. package/build/components/block-list/use-block-props/use-focus-first-element.js +1 -1
  4. package/build/components/block-list/use-block-props/use-focus-first-element.js.map +1 -1
  5. package/build/components/block-popover/index.js +1 -3
  6. package/build/components/block-popover/index.js.map +1 -1
  7. package/build/components/colors-gradients/control.js +1 -0
  8. package/build/components/colors-gradients/control.js.map +1 -1
  9. package/build/components/inner-blocks/index.native.js +6 -2
  10. package/build/components/inner-blocks/index.native.js.map +1 -1
  11. package/build/components/rich-text/index.js +10 -0
  12. package/build/components/rich-text/index.js.map +1 -1
  13. package/build/components/spacing-sizes-control/spacing-input-control.js +6 -1
  14. package/build/components/spacing-sizes-control/spacing-input-control.js.map +1 -1
  15. package/build/components/spacing-sizes-control/utils.js +32 -1
  16. package/build/components/spacing-sizes-control/utils.js.map +1 -1
  17. package/build/components/text-decoration-control/index.js +28 -17
  18. package/build/components/text-decoration-control/index.js.map +1 -1
  19. package/build/components/text-transform-control/index.js +21 -14
  20. package/build/components/text-transform-control/index.js.map +1 -1
  21. package/build/components/writing-flow/index.js +2 -0
  22. package/build/components/writing-flow/index.js.map +1 -1
  23. package/build/components/writing-flow/use-select-all.js +7 -10
  24. package/build/components/writing-flow/use-select-all.js.map +1 -1
  25. package/build/hooks/align.js +3 -1
  26. package/build/hooks/align.js.map +1 -1
  27. package/build/hooks/anchor.js +3 -7
  28. package/build/hooks/anchor.js.map +1 -1
  29. package/build/hooks/dimensions.js +6 -6
  30. package/build/hooks/dimensions.js.map +1 -1
  31. package/build/hooks/font-appearance.js +2 -1
  32. package/build/hooks/font-appearance.js.map +1 -1
  33. package/build/hooks/font-family.js +3 -1
  34. package/build/hooks/font-family.js.map +1 -1
  35. package/build/hooks/font-size.js +3 -1
  36. package/build/hooks/font-size.js.map +1 -1
  37. package/build/hooks/gap.js +23 -6
  38. package/build/hooks/gap.js.map +1 -1
  39. package/build/hooks/layout.js +3 -1
  40. package/build/hooks/layout.js.map +1 -1
  41. package/build/hooks/letter-spacing.js +2 -1
  42. package/build/hooks/letter-spacing.js.map +1 -1
  43. package/build/hooks/line-height.js +2 -1
  44. package/build/hooks/line-height.js.map +1 -1
  45. package/build/hooks/lock.js +3 -7
  46. package/build/hooks/lock.js.map +1 -1
  47. package/build/hooks/text-decoration.js +2 -1
  48. package/build/hooks/text-decoration.js.map +1 -1
  49. package/build/hooks/text-transform.js +2 -1
  50. package/build/hooks/text-transform.js.map +1 -1
  51. package/build/layouts/constrained.js +12 -2
  52. package/build/layouts/constrained.js.map +1 -1
  53. package/build/layouts/flow.js +12 -2
  54. package/build/layouts/flow.js.map +1 -1
  55. package/build-module/components/block-list/block-list-compact.native.js +58 -0
  56. package/build-module/components/block-list/block-list-compact.native.js.map +1 -0
  57. package/build-module/components/block-list/use-block-props/use-focus-first-element.js +1 -1
  58. package/build-module/components/block-list/use-block-props/use-focus-first-element.js.map +1 -1
  59. package/build-module/components/block-popover/index.js +1 -3
  60. package/build-module/components/block-popover/index.js.map +1 -1
  61. package/build-module/components/colors-gradients/control.js +1 -0
  62. package/build-module/components/colors-gradients/control.js.map +1 -1
  63. package/build-module/components/inner-blocks/index.native.js +5 -2
  64. package/build-module/components/inner-blocks/index.native.js.map +1 -1
  65. package/build-module/components/rich-text/index.js +10 -0
  66. package/build-module/components/rich-text/index.js.map +1 -1
  67. package/build-module/components/spacing-sizes-control/spacing-input-control.js +7 -2
  68. package/build-module/components/spacing-sizes-control/spacing-input-control.js.map +1 -1
  69. package/build-module/components/spacing-sizes-control/utils.js +30 -1
  70. package/build-module/components/spacing-sizes-control/utils.js.map +1 -1
  71. package/build-module/components/text-decoration-control/index.js +25 -18
  72. package/build-module/components/text-decoration-control/index.js.map +1 -1
  73. package/build-module/components/text-transform-control/index.js +19 -15
  74. package/build-module/components/text-transform-control/index.js.map +1 -1
  75. package/build-module/components/writing-flow/index.js +2 -0
  76. package/build-module/components/writing-flow/index.js.map +1 -1
  77. package/build-module/components/writing-flow/use-select-all.js +7 -10
  78. package/build-module/components/writing-flow/use-select-all.js.map +1 -1
  79. package/build-module/hooks/align.js +4 -2
  80. package/build-module/hooks/align.js.map +1 -1
  81. package/build-module/hooks/anchor.js +3 -6
  82. package/build-module/hooks/anchor.js.map +1 -1
  83. package/build-module/hooks/dimensions.js +6 -6
  84. package/build-module/hooks/dimensions.js.map +1 -1
  85. package/build-module/hooks/font-appearance.js +2 -1
  86. package/build-module/hooks/font-appearance.js.map +1 -1
  87. package/build-module/hooks/font-family.js +3 -1
  88. package/build-module/hooks/font-family.js.map +1 -1
  89. package/build-module/hooks/font-size.js +3 -1
  90. package/build-module/hooks/font-size.js.map +1 -1
  91. package/build-module/hooks/gap.js +22 -6
  92. package/build-module/hooks/gap.js.map +1 -1
  93. package/build-module/hooks/layout.js +4 -2
  94. package/build-module/hooks/layout.js.map +1 -1
  95. package/build-module/hooks/letter-spacing.js +2 -1
  96. package/build-module/hooks/letter-spacing.js.map +1 -1
  97. package/build-module/hooks/line-height.js +2 -1
  98. package/build-module/hooks/line-height.js.map +1 -1
  99. package/build-module/hooks/lock.js +3 -6
  100. package/build-module/hooks/lock.js.map +1 -1
  101. package/build-module/hooks/text-decoration.js +2 -1
  102. package/build-module/hooks/text-decoration.js.map +1 -1
  103. package/build-module/hooks/text-transform.js +2 -1
  104. package/build-module/hooks/text-transform.js.map +1 -1
  105. package/build-module/layouts/constrained.js +13 -3
  106. package/build-module/layouts/constrained.js.map +1 -1
  107. package/build-module/layouts/flow.js +13 -3
  108. package/build-module/layouts/flow.js.map +1 -1
  109. package/build-style/style-rtl.css +42 -41
  110. package/build-style/style.css +42 -41
  111. package/package.json +28 -28
  112. package/src/components/block-list/block-list-compact.native.js +62 -0
  113. package/src/components/block-list/style.scss +29 -6
  114. package/src/components/block-list/use-block-props/use-focus-first-element.js +1 -1
  115. package/src/components/block-popover/index.js +0 -2
  116. package/src/components/block-switcher/test/index.js +1 -2
  117. package/src/components/button-block-appender/style.scss +23 -0
  118. package/src/components/colors-gradients/control.js +1 -0
  119. package/src/components/inner-blocks/index.native.js +5 -1
  120. package/src/components/rich-text/index.js +9 -0
  121. package/src/components/spacing-sizes-control/spacing-input-control.js +5 -0
  122. package/src/components/spacing-sizes-control/test/utils.js +26 -0
  123. package/src/components/spacing-sizes-control/utils.js +36 -9
  124. package/src/components/text-decoration-control/index.js +41 -30
  125. package/src/components/text-decoration-control/stories/index.js +37 -0
  126. package/src/components/text-transform-control/index.js +27 -27
  127. package/src/components/text-transform-control/stories/index.js +37 -0
  128. package/src/components/writing-flow/index.js +2 -0
  129. package/src/components/writing-flow/use-select-all.js +10 -13
  130. package/src/hooks/align.js +2 -2
  131. package/src/hooks/anchor.js +1 -6
  132. package/src/hooks/dimensions.js +7 -8
  133. package/src/hooks/font-appearance.js +1 -0
  134. package/src/hooks/font-family.js +2 -0
  135. package/src/hooks/font-size.js +2 -0
  136. package/src/hooks/gap.js +43 -25
  137. package/src/hooks/layout.js +2 -2
  138. package/src/hooks/letter-spacing.js +1 -0
  139. package/src/hooks/line-height.js +1 -0
  140. package/src/hooks/lock.js +1 -6
  141. package/src/hooks/test/gap.js +16 -22
  142. package/src/hooks/text-decoration.js +1 -0
  143. package/src/hooks/text-transform.js +1 -0
  144. package/src/hooks/typography.scss +0 -6
  145. package/src/layouts/constrained.js +12 -9
  146. package/src/layouts/flow.js +12 -10
  147. package/src/style.scss +0 -2
  148. package/src/components/text-decoration-control/style.scss +0 -18
  149. package/src/components/text-transform-control/style.scss +0 -18
@@ -43,6 +43,33 @@ export function getCustomValueFromPreset( value, spacingSizes ) {
43
43
  return spacingSize?.size;
44
44
  }
45
45
 
46
+ /**
47
+ * Converts a custom value to preset value if one can be found.
48
+ *
49
+ * Returns value as-is if no match is found.
50
+ *
51
+ * @param {string} value Value to convert
52
+ * @param {Array} spacingSizes Array of the current spacing preset objects
53
+ *
54
+ * @return {string} The preset value if it can be found.
55
+ */
56
+ export function getPresetValueFromCustomValue( value, spacingSizes ) {
57
+ // Return value as-is if it is already a preset;
58
+ if ( isValueSpacingPreset( value ) ) {
59
+ return value;
60
+ }
61
+
62
+ const spacingMatch = spacingSizes.find(
63
+ ( size ) => String( size.size ) === String( value )
64
+ );
65
+
66
+ if ( spacingMatch?.slug ) {
67
+ return `var:preset|spacing|${ spacingMatch.slug }`;
68
+ }
69
+
70
+ return value;
71
+ }
72
+
46
73
  /**
47
74
  * Converts a spacing preset into a custom value.
48
75
  *
@@ -181,15 +208,15 @@ export function isValuesMixed( values = {}, sides = ALL_SIDES ) {
181
208
  * @return {boolean} Whether values are defined.
182
209
  */
183
210
  export function isValuesDefined( values ) {
184
- return (
185
- values !== undefined &&
186
- ! isEmpty(
187
- Object.values( values ).filter(
188
- // Switching units when input is empty causes values only
189
- // containing units. This gives false positive on mixed values
190
- // unless filtered.
191
- ( value ) => !! value && /\d/.test( value )
192
- )
211
+ if ( values === undefined || values === null ) {
212
+ return false;
213
+ }
214
+ return ! isEmpty(
215
+ Object.values( values ).filter(
216
+ // Switching units when input is empty causes values only
217
+ // containing units. This gives false positive on mixed values
218
+ // unless filtered.
219
+ ( value ) => !! value && /\d/.test( value )
193
220
  )
194
221
  );
195
222
  }
@@ -1,7 +1,15 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import classnames from 'classnames';
5
+
1
6
  /**
2
7
  * WordPress dependencies
3
8
  */
4
- import { BaseControl, Button } from '@wordpress/components';
9
+ import {
10
+ __experimentalToggleGroupControl as ToggleGroupControl,
11
+ __experimentalToggleGroupControlOptionIcon as ToggleGroupControlOptionIcon,
12
+ } from '@wordpress/components';
5
13
  import { formatStrikethrough, formatUnderline } from '@wordpress/icons';
6
14
  import { __ } from '@wordpress/i18n';
7
15
 
@@ -21,38 +29,41 @@ const TEXT_DECORATIONS = [
21
29
  /**
22
30
  * Control to facilitate text decoration selections.
23
31
  *
24
- * @param {Object} props Component props.
25
- * @param {string} props.value Currently selected text decoration.
26
- * @param {Function} props.onChange Handles change in text decoration selection.
32
+ * @param {Object} props Component props.
33
+ * @param {string} props.value Currently selected text decoration.
34
+ * @param {Function} props.onChange Handles change in text decoration selection.
35
+ * @param {string} [props.className] Additional class name to apply.
27
36
  *
28
37
  * @return {WPElement} Text decoration control.
29
38
  */
30
- export default function TextDecorationControl( { value, onChange } ) {
39
+ export default function TextDecorationControl( {
40
+ value,
41
+ onChange,
42
+ className,
43
+ ...props
44
+ } ) {
31
45
  return (
32
- <fieldset className="block-editor-text-decoration-control">
33
- <BaseControl.VisualLabel as="legend">
34
- { __( 'Decoration' ) }
35
- </BaseControl.VisualLabel>
36
- <div className="block-editor-text-decoration-control__buttons">
37
- { TEXT_DECORATIONS.map( ( textDecoration ) => {
38
- return (
39
- <Button
40
- key={ textDecoration.value }
41
- icon={ textDecoration.icon }
42
- isSmall
43
- isPressed={ textDecoration.value === value }
44
- onClick={ () =>
45
- onChange(
46
- textDecoration.value === value
47
- ? undefined
48
- : textDecoration.value
49
- )
50
- }
51
- aria-label={ textDecoration.name }
52
- />
53
- );
54
- } ) }
55
- </div>
56
- </fieldset>
46
+ <ToggleGroupControl
47
+ { ...props }
48
+ className={ classnames(
49
+ 'block-editor-text-decoration-control',
50
+ className
51
+ ) }
52
+ __experimentalIsIconGroup
53
+ label={ __( 'Decoration' ) }
54
+ value={ value }
55
+ onChange={ onChange }
56
+ >
57
+ { TEXT_DECORATIONS.map( ( textDecoration ) => {
58
+ return (
59
+ <ToggleGroupControlOptionIcon
60
+ key={ textDecoration.value }
61
+ value={ textDecoration.value }
62
+ icon={ textDecoration.icon }
63
+ label={ textDecoration.name }
64
+ />
65
+ );
66
+ } ) }
67
+ </ToggleGroupControl>
57
68
  );
58
69
  }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { useState } from '@wordpress/element';
5
+
6
+ /**
7
+ * Internal dependencies
8
+ */
9
+ import TextDecorationControl from '../';
10
+
11
+ export default {
12
+ title: 'BlockEditor/TextDecorationControl',
13
+ component: TextDecorationControl,
14
+ argTypes: {
15
+ onChange: { action: 'onChange' },
16
+ size: {
17
+ options: [ 'default', '__unstable-large' ],
18
+ control: { type: 'radio' },
19
+ },
20
+ },
21
+ };
22
+
23
+ const Template = ( { onChange, ...args } ) => {
24
+ const [ value, setValue ] = useState();
25
+ return (
26
+ <TextDecorationControl
27
+ { ...args }
28
+ onChange={ ( ...changeArgs ) => {
29
+ onChange( ...changeArgs );
30
+ setValue( ...changeArgs );
31
+ } }
32
+ value={ value }
33
+ />
34
+ );
35
+ };
36
+
37
+ export const Default = Template.bind( {} );
@@ -1,7 +1,13 @@
1
+ /**
2
+ * External dependencies
3
+ */
1
4
  /**
2
5
  * WordPress dependencies
3
6
  */
4
- import { BaseControl, Button } from '@wordpress/components';
7
+ import {
8
+ __experimentalToggleGroupControl as ToggleGroupControl,
9
+ __experimentalToggleGroupControlOptionIcon as ToggleGroupControlOptionIcon,
10
+ } from '@wordpress/components';
5
11
  import { __ } from '@wordpress/i18n';
6
12
  import {
7
13
  formatCapitalize,
@@ -36,32 +42,26 @@ const TEXT_TRANSFORMS = [
36
42
  *
37
43
  * @return {WPElement} Text transform control.
38
44
  */
39
- export default function TextTransformControl( { value, onChange } ) {
45
+ export default function TextTransformControl( { value, onChange, ...props } ) {
40
46
  return (
41
- <fieldset className="block-editor-text-transform-control">
42
- <BaseControl.VisualLabel as="legend">
43
- { __( 'Letter case' ) }
44
- </BaseControl.VisualLabel>
45
- <div className="block-editor-text-transform-control__buttons">
46
- { TEXT_TRANSFORMS.map( ( textTransform ) => {
47
- return (
48
- <Button
49
- key={ textTransform.value }
50
- icon={ textTransform.icon }
51
- isSmall
52
- isPressed={ value === textTransform.value }
53
- aria-label={ textTransform.name }
54
- onClick={ () =>
55
- onChange(
56
- value === textTransform.value
57
- ? undefined
58
- : textTransform.value
59
- )
60
- }
61
- />
62
- );
63
- } ) }
64
- </div>
65
- </fieldset>
47
+ <ToggleGroupControl
48
+ { ...props }
49
+ className="block-editor-text-transform-control"
50
+ __experimentalIsIconGroup
51
+ label={ __( 'Letter case' ) }
52
+ value={ value }
53
+ onChange={ onChange }
54
+ >
55
+ { TEXT_TRANSFORMS.map( ( textTransform ) => {
56
+ return (
57
+ <ToggleGroupControlOptionIcon
58
+ key={ textTransform.value }
59
+ value={ textTransform.value }
60
+ icon={ textTransform.icon }
61
+ label={ textTransform.name }
62
+ />
63
+ );
64
+ } ) }
65
+ </ToggleGroupControl>
66
66
  );
67
67
  }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { useState } from '@wordpress/element';
5
+
6
+ /**
7
+ * Internal dependencies
8
+ */
9
+ import TextTransformControl from '../';
10
+
11
+ export default {
12
+ title: 'BlockEditor/TextTransformControl',
13
+ component: TextTransformControl,
14
+ argTypes: {
15
+ onChange: { action: 'onChange' },
16
+ size: {
17
+ options: [ 'default', '__unstable-large' ],
18
+ control: { type: 'radio' },
19
+ },
20
+ },
21
+ };
22
+
23
+ const Template = ( { onChange, ...args } ) => {
24
+ const [ value, setValue ] = useState();
25
+ return (
26
+ <TextTransformControl
27
+ { ...args }
28
+ onChange={ ( ...changeArgs ) => {
29
+ onChange( ...changeArgs );
30
+ setValue( ...changeArgs );
31
+ } }
32
+ value={ value }
33
+ />
34
+ );
35
+ };
36
+
37
+ export const Default = Template.bind( {} );
@@ -51,12 +51,14 @@ export function useWritingFlow() {
51
51
  return;
52
52
  }
53
53
 
54
+ node.classList.add( 'has-multi-selection' );
54
55
  node.setAttribute(
55
56
  'aria-label',
56
57
  __( 'Multiple selected blocks' )
57
58
  );
58
59
 
59
60
  return () => {
61
+ node.classList.remove( 'has-multi-selection' );
60
62
  node.removeAttribute( 'aria-label' );
61
63
  };
62
64
  },
@@ -37,28 +37,25 @@ export default function useSelectAll() {
37
37
  return;
38
38
  }
39
39
 
40
+ event.preventDefault();
41
+
40
42
  const [ firstSelectedClientId ] = selectedClientIds;
41
43
  const rootClientId = getBlockRootClientId( firstSelectedClientId );
42
- let blockClientIds = getBlockOrder( rootClientId );
44
+ const blockClientIds = getBlockOrder( rootClientId );
43
45
 
44
46
  // If we have selected all sibling nested blocks, try selecting up a
45
47
  // level. See: https://github.com/WordPress/gutenberg/pull/31859/
46
48
  if ( selectedClientIds.length === blockClientIds.length ) {
47
- blockClientIds = getBlockOrder(
48
- getBlockRootClientId( rootClientId )
49
- );
50
- }
51
-
52
- const firstClientId = first( blockClientIds );
53
- const lastClientId = last( blockClientIds );
54
-
55
- if ( firstClientId === lastClientId ) {
56
- selectBlock( firstClientId );
49
+ if ( rootClientId ) {
50
+ node.ownerDocument.defaultView
51
+ .getSelection()
52
+ .removeAllRanges();
53
+ selectBlock( rootClientId );
54
+ }
57
55
  return;
58
56
  }
59
57
 
60
- multiSelect( firstClientId, lastClientId );
61
- event.preventDefault();
58
+ multiSelect( first( blockClientIds ), last( blockClientIds ) );
62
59
  }
63
60
 
64
61
  node.addEventListener( 'keydown', onKeyDown );
@@ -2,7 +2,7 @@
2
2
  * External dependencies
3
3
  */
4
4
  import classnames from 'classnames';
5
- import { has, without } from 'lodash';
5
+ import { without } from 'lodash';
6
6
 
7
7
  /**
8
8
  * WordPress dependencies
@@ -87,7 +87,7 @@ export function getValidAlignments(
87
87
  */
88
88
  export function addAttribute( settings ) {
89
89
  // Allow blocks to specify their own attribute definition with default values if needed.
90
- if ( has( settings.attributes, [ 'align', 'type' ] ) ) {
90
+ if ( 'type' in ( settings.attributes?.align ?? {} ) ) {
91
91
  return settings;
92
92
  }
93
93
  if ( hasBlockSupport( settings, 'align' ) ) {
@@ -1,8 +1,3 @@
1
- /**
2
- * External dependencies
3
- */
4
- import { has } from 'lodash';
5
-
6
1
  /**
7
2
  * WordPress dependencies
8
3
  */
@@ -42,7 +37,7 @@ const ANCHOR_SCHEMA = {
42
37
  */
43
38
  export function addAttribute( settings ) {
44
39
  // Allow blocks to specify their own attribute definition with default values if needed.
45
- if ( has( settings.attributes, [ 'anchor', 'type' ] ) ) {
40
+ if ( 'type' in ( settings.attributes?.anchor ?? {} ) ) {
46
41
  return settings;
47
42
  }
48
43
  if ( hasBlockSupport( settings, 'anchor' ) ) {
@@ -79,15 +79,16 @@ export function DimensionsPanel( props ) {
79
79
  },
80
80
  } );
81
81
 
82
+ const spacingClassnames = classnames( {
83
+ 'tools-panel-item-spacing': spacingSizes && spacingSizes.length > 0,
84
+ } );
85
+
82
86
  return (
83
87
  <>
84
88
  <InspectorControls __experimentalGroup="dimensions">
85
89
  { ! isPaddingDisabled && (
86
90
  <ToolsPanelItem
87
- className={ classnames( {
88
- 'tools-panel-item-spacing':
89
- spacingSizes && spacingSizes.length > 0,
90
- } ) }
91
+ className={ spacingClassnames }
91
92
  hasValue={ () => hasPaddingValue( props ) }
92
93
  label={ __( 'Padding' ) }
93
94
  onDeselect={ () => resetPadding( props ) }
@@ -100,10 +101,7 @@ export function DimensionsPanel( props ) {
100
101
  ) }
101
102
  { ! isMarginDisabled && (
102
103
  <ToolsPanelItem
103
- className={ classnames( {
104
- 'tools-panel-item-spacing':
105
- spacingSizes && spacingSizes.length > 0,
106
- } ) }
104
+ className={ spacingClassnames }
107
105
  hasValue={ () => hasMarginValue( props ) }
108
106
  label={ __( 'Margin' ) }
109
107
  onDeselect={ () => resetMargin( props ) }
@@ -116,6 +114,7 @@ export function DimensionsPanel( props ) {
116
114
  ) }
117
115
  { ! isGapDisabled && (
118
116
  <ToolsPanelItem
117
+ className={ spacingClassnames }
119
118
  hasValue={ () => hasGapValue( props ) }
120
119
  label={ __( 'Block spacing' ) }
121
120
  onDeselect={ () => resetGap( props ) }
@@ -58,6 +58,7 @@ export function FontAppearanceEdit( props ) {
58
58
  hasFontStyles={ hasFontStyles }
59
59
  hasFontWeights={ hasFontWeights }
60
60
  value={ { fontStyle, fontWeight } }
61
+ size="__unstable-large"
61
62
  />
62
63
  );
63
64
  }
@@ -132,6 +132,8 @@ export function FontFamilyEdit( {
132
132
  fontFamilies={ fontFamilies }
133
133
  value={ value }
134
134
  onChange={ onChange }
135
+ size="__unstable-large"
136
+ __nextHasNoMarginBottom
135
137
  />
136
138
  );
137
139
  }
@@ -147,6 +147,8 @@ export function FontSizeEdit( props ) {
147
147
  onChange={ onChange }
148
148
  value={ fontSizeValue }
149
149
  withReset={ false }
150
+ size="__unstable-large"
151
+ __nextHasNoMarginBottom
150
152
  />
151
153
  );
152
154
  }
package/src/hooks/gap.js CHANGED
@@ -15,6 +15,7 @@ import {
15
15
  */
16
16
  import { __unstableUseBlockRef as useBlockRef } from '../components/block-list/use-block-props/use-block-refs';
17
17
  import { getSpacingPresetCssVar } from '../components/spacing-sizes-control/utils';
18
+ import SpacingSizesControl from '../components/spacing-sizes-control';
18
19
  import useSetting from '../components/use-setting';
19
20
  import { AXIAL_SIDES, SPACING_SUPPORT_KEY, useCustomSides } from './dimensions';
20
21
  import { cleanEmptyObject } from './utils';
@@ -55,12 +56,8 @@ export function getGapBoxControlValueFromStyle( blockGapValue ) {
55
56
 
56
57
  const isValueString = typeof blockGapValue === 'string';
57
58
  return {
58
- top: isValueString
59
- ? getSpacingPresetCssVar( blockGapValue )
60
- : getSpacingPresetCssVar( blockGapValue?.top ),
61
- left: isValueString
62
- ? getSpacingPresetCssVar( blockGapValue )
63
- : getSpacingPresetCssVar( blockGapValue?.left ),
59
+ top: isValueString ? blockGapValue : blockGapValue?.top,
60
+ left: isValueString ? blockGapValue : blockGapValue?.left,
64
61
  };
65
62
  }
66
63
 
@@ -78,8 +75,10 @@ export function getGapCSSValue( blockGapValue, defaultValue = '0' ) {
78
75
  return null;
79
76
  }
80
77
 
81
- const row = blockGapBoxControlValue?.top || defaultValue;
82
- const column = blockGapBoxControlValue?.left || defaultValue;
78
+ const row =
79
+ getSpacingPresetCssVar( blockGapBoxControlValue?.top ) || defaultValue;
80
+ const column =
81
+ getSpacingPresetCssVar( blockGapBoxControlValue?.left ) || defaultValue;
83
82
 
84
83
  return row === column ? row : `${ row } ${ column }`;
85
84
  }
@@ -132,6 +131,8 @@ export function GapEdit( props ) {
132
131
  setAttributes,
133
132
  } = props;
134
133
 
134
+ const spacingSizes = useSetting( 'spacing.spacingSizes' );
135
+
135
136
  const units = useCustomUnits( {
136
137
  availableUnits: useSetting( 'spacing.units' ) || [
137
138
  '%',
@@ -157,6 +158,9 @@ export function GapEdit( props ) {
157
158
  // If splitOnAxis activated we need to return a BoxControl object to the BoxControl component.
158
159
  if ( !! next && splitOnAxis ) {
159
160
  blockGap = { ...getGapBoxControlValueFromStyle( next ) };
161
+ } else if ( next?.hasOwnProperty( 'top' ) ) {
162
+ // If splitOnAxis is not enabled, treat the 'top' value as the shorthand gap value.
163
+ blockGap = next.top;
160
164
  }
161
165
 
162
166
  const newStyle = {
@@ -195,32 +199,46 @@ export function GapEdit( props ) {
195
199
  right: gapValue?.left,
196
200
  bottom: gapValue?.top,
197
201
  }
198
- : gapValue?.top;
202
+ : {
203
+ top: gapValue?.top,
204
+ };
199
205
 
200
206
  return Platform.select( {
201
207
  web: (
202
208
  <>
203
- { splitOnAxis ? (
204
- <BoxControl
205
- label={ __( 'Block spacing' ) }
206
- min={ 0 }
209
+ { ( ! spacingSizes || spacingSizes?.length === 0 ) &&
210
+ ( splitOnAxis ? (
211
+ <BoxControl
212
+ label={ __( 'Block spacing' ) }
213
+ min={ 0 }
214
+ onChange={ onChange }
215
+ units={ units }
216
+ sides={ sides }
217
+ values={ boxControlGapValue }
218
+ allowReset={ false }
219
+ splitOnAxis={ splitOnAxis }
220
+ />
221
+ ) : (
222
+ <UnitControl
223
+ label={ __( 'Block spacing' ) }
224
+ __unstableInputWidth="80px"
225
+ min={ 0 }
226
+ onChange={ onChange }
227
+ units={ units }
228
+ // Default to `row` for combined values.
229
+ value={ boxControlGapValue }
230
+ />
231
+ ) ) }
232
+ { spacingSizes?.length > 0 && (
233
+ <SpacingSizesControl
234
+ values={ boxControlGapValue }
207
235
  onChange={ onChange }
236
+ label={ __( 'Block spacing' ) }
237
+ sides={ splitOnAxis ? sides : [ 'top' ] } // Use 'top' as the shorthand property in non-axial configurations.
208
238
  units={ units }
209
- sides={ sides }
210
- values={ boxControlGapValue }
211
239
  allowReset={ false }
212
240
  splitOnAxis={ splitOnAxis }
213
241
  />
214
- ) : (
215
- <UnitControl
216
- label={ __( 'Block spacing' ) }
217
- __unstableInputWidth="80px"
218
- min={ 0 }
219
- onChange={ onChange }
220
- units={ units }
221
- // Default to `row` for combined values.
222
- value={ boxControlGapValue }
223
- />
224
242
  ) }
225
243
  </>
226
244
  ),
@@ -2,7 +2,7 @@
2
2
  * External dependencies
3
3
  */
4
4
  import classnames from 'classnames';
5
- import { has, kebabCase } from 'lodash';
5
+ import { kebabCase } from 'lodash';
6
6
 
7
7
  /**
8
8
  * WordPress dependencies
@@ -246,7 +246,7 @@ function LayoutTypeSwitcher( { type, onChange } ) {
246
246
  * @return {Object} Filtered block settings.
247
247
  */
248
248
  export function addAttribute( settings ) {
249
- if ( has( settings.attributes, [ 'layout', 'type' ] ) ) {
249
+ if ( 'type' in ( settings.attributes?.layout ?? {} ) ) {
250
250
  return settings;
251
251
  }
252
252
  if ( hasBlockSupport( settings, layoutBlockSupportKey ) ) {
@@ -46,6 +46,7 @@ export function LetterSpacingEdit( props ) {
46
46
  value={ style?.typography?.letterSpacing }
47
47
  onChange={ onChange }
48
48
  __unstableInputWidth={ '100%' }
49
+ size="__unstable-large"
49
50
  />
50
51
  );
51
52
  }
@@ -42,6 +42,7 @@ export function LineHeightEdit( props ) {
42
42
  __nextHasNoMarginBottom={ true }
43
43
  value={ style?.typography?.lineHeight }
44
44
  onChange={ onChange }
45
+ size="__unstable-large"
45
46
  />
46
47
  );
47
48
  }
package/src/hooks/lock.js CHANGED
@@ -1,8 +1,3 @@
1
- /**
2
- * External dependencies
3
- */
4
- import { has } from 'lodash';
5
-
6
1
  /**
7
2
  * WordPress dependencies
8
3
  */
@@ -17,7 +12,7 @@ import { addFilter } from '@wordpress/hooks';
17
12
  */
18
13
  export function addAttribute( settings ) {
19
14
  // Allow blocks to specify their own attribute definition with default values if needed.
20
- if ( has( settings.attributes, [ 'lock', 'type' ] ) ) {
15
+ if ( 'type' in ( settings.attributes?.lock ?? {} ) ) {
21
16
  return settings;
22
17
  }
23
18
  // Gracefully handle if settings.attributes is undefined.
@@ -27,28 +27,6 @@ describe( 'gap', () => {
27
27
  ...blockGapValue,
28
28
  } );
29
29
  } );
30
- it( 'should unwrap var: values from a string into a CSS var() function', () => {
31
- const expectedValue = {
32
- top: 'var(--wp--preset--spacing--60)',
33
- left: 'var(--wp--preset--spacing--60)',
34
- };
35
- expect(
36
- getGapBoxControlValueFromStyle( 'var:preset|spacing|60' )
37
- ).toEqual( expectedValue );
38
- } );
39
- it( 'should unwrap var: values from an object into a CSS var() function', () => {
40
- const expectedValue = {
41
- top: 'var(--wp--preset--spacing--20)',
42
- left: 'var(--wp--preset--spacing--60)',
43
- };
44
- const blockGapValue = {
45
- top: 'var:preset|spacing|20',
46
- left: 'var:preset|spacing|60',
47
- };
48
- expect( getGapBoxControlValueFromStyle( blockGapValue ) ).toEqual(
49
- expectedValue
50
- );
51
- } );
52
30
  } );
53
31
  describe( 'getGapCSSValue()', () => {
54
32
  it( 'should return `null` if argument is falsey', () => {
@@ -84,5 +62,21 @@ describe( 'gap', () => {
84
62
  '88px 1px'
85
63
  );
86
64
  } );
65
+
66
+ it( 'should unwrap var: values from a string into a CSS var() function', () => {
67
+ expect( getGapCSSValue( 'var:preset|spacing|60' ) ).toEqual(
68
+ 'var(--wp--preset--spacing--60)'
69
+ );
70
+ } );
71
+
72
+ it( 'should unwrap var: values from an object into a CSS var() function and return shorthand values', () => {
73
+ const blockGapValue = {
74
+ top: 'var:preset|spacing|20',
75
+ left: 'var:preset|spacing|60',
76
+ };
77
+ expect( getGapCSSValue( blockGapValue ) ).toEqual(
78
+ 'var(--wp--preset--spacing--20) var(--wp--preset--spacing--60)'
79
+ );
80
+ } );
87
81
  } );
88
82
  } );