@wordpress/components 29.6.0 → 29.7.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 (71) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/build/angle-picker-control/index.js +1 -1
  3. package/build/angle-picker-control/index.js.map +1 -1
  4. package/build/autocomplete/index.js +5 -30
  5. package/build/autocomplete/index.js.map +1 -1
  6. package/build/custom-select-control-v2/styles.js +9 -9
  7. package/build/custom-select-control-v2/styles.js.map +1 -1
  8. package/build/number-control/index.js +6 -4
  9. package/build/number-control/index.js.map +1 -1
  10. package/build/range-control/index.js +6 -5
  11. package/build/range-control/index.js.map +1 -1
  12. package/build/toolbar/toolbar-dropdown-menu/index.js +4 -3
  13. package/build/toolbar/toolbar-dropdown-menu/index.js.map +1 -1
  14. package/build/toolbar/toolbar-item/index.js +4 -3
  15. package/build/toolbar/toolbar-item/index.js.map +1 -1
  16. package/build/utils/get-node-text.js +30 -0
  17. package/build/utils/get-node-text.js.map +1 -0
  18. package/build/utils/math.js +18 -15
  19. package/build/utils/math.js.map +1 -1
  20. package/build-module/angle-picker-control/index.js +1 -1
  21. package/build-module/angle-picker-control/index.js.map +1 -1
  22. package/build-module/autocomplete/index.js +3 -28
  23. package/build-module/autocomplete/index.js.map +1 -1
  24. package/build-module/custom-select-control-v2/styles.js +9 -9
  25. package/build-module/custom-select-control-v2/styles.js.map +1 -1
  26. package/build-module/number-control/index.js +7 -5
  27. package/build-module/number-control/index.js.map +1 -1
  28. package/build-module/range-control/index.js +6 -5
  29. package/build-module/range-control/index.js.map +1 -1
  30. package/build-module/toolbar/toolbar-dropdown-menu/index.js +3 -2
  31. package/build-module/toolbar/toolbar-dropdown-menu/index.js.map +1 -1
  32. package/build-module/toolbar/toolbar-item/index.js +3 -2
  33. package/build-module/toolbar/toolbar-item/index.js.map +1 -1
  34. package/build-module/utils/get-node-text.js +24 -0
  35. package/build-module/utils/get-node-text.js.map +1 -0
  36. package/build-module/utils/math.js +17 -14
  37. package/build-module/utils/math.js.map +1 -1
  38. package/build-style/style-rtl.css +1 -1
  39. package/build-style/style.css +1 -1
  40. package/build-types/angle-picker-control/index.d.ts +1 -1
  41. package/build-types/autocomplete/index.d.ts +2 -2
  42. package/build-types/autocomplete/index.d.ts.map +1 -1
  43. package/build-types/custom-select-control-v2/styles.d.ts.map +1 -1
  44. package/build-types/number-control/index.d.ts.map +1 -1
  45. package/build-types/range-control/index.d.ts +6 -5
  46. package/build-types/range-control/index.d.ts.map +1 -1
  47. package/build-types/toolbar/toolbar-dropdown-menu/index.d.ts +2 -2
  48. package/build-types/toolbar/toolbar-dropdown-menu/index.d.ts.map +1 -1
  49. package/build-types/toolbar/toolbar-item/index.d.ts +2 -2
  50. package/build-types/toolbar/toolbar-item/index.d.ts.map +1 -1
  51. package/build-types/utils/get-node-text.d.ts +3 -0
  52. package/build-types/utils/get-node-text.d.ts.map +1 -0
  53. package/build-types/utils/math.d.ts +10 -11
  54. package/build-types/utils/math.d.ts.map +1 -1
  55. package/package.json +19 -19
  56. package/src/angle-picker-control/README.md +1 -1
  57. package/src/angle-picker-control/index.tsx +1 -1
  58. package/src/autocomplete/index.tsx +3 -30
  59. package/src/custom-select-control-v2/styles.ts +1 -0
  60. package/src/form-token-field/style.scss +1 -1
  61. package/src/number-control/index.tsx +8 -7
  62. package/src/number-control/test/index.tsx +15 -2
  63. package/src/range-control/index.tsx +6 -5
  64. package/src/toolbar/toolbar-dropdown-menu/index.tsx +3 -2
  65. package/src/toolbar/toolbar-item/index.tsx +3 -2
  66. package/src/utils/get-node-text.ts +24 -0
  67. package/src/utils/math.js +17 -22
  68. package/src/utils/test/get-node-text.js +37 -0
  69. package/src/utils/test/math.js +28 -32
  70. package/src/utils/theme-variables.scss +0 -4
  71. package/tsconfig.tsbuildinfo +1 -1
@@ -6,17 +6,18 @@
6
6
  * import { useState } from '@wordpress/element';
7
7
  *
8
8
  * const MyRangeControl = () => {
9
- * const [ isChecked, setChecked ] = useState( true );
9
+ * const [ value, setValue ] = useState();
10
10
  * return (
11
11
  * <RangeControl
12
12
  * __nextHasNoMarginBottom
13
13
  * __next40pxDefaultSize
14
14
  * help="Please select how transparent you would like this."
15
- * initialPosition={50}
15
+ * initialPosition={ 50 }
16
16
  * label="Opacity"
17
- * max={100}
18
- * min={0}
19
- * onChange={() => {}}
17
+ * max={ 100 }
18
+ * min={ 0 }
19
+ * value={ value }
20
+ * onChange={ setValue }
20
21
  * />
21
22
  * );
22
23
  * };
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/range-control/index.tsx"],"names":[],"mappings":"AAiYA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,YAAY;;;;aAjXuB,CAAC;;;;;;;;;;;;;;qBAiHmB,CAAC;;;;;iCAwBzC,CAAA;;;;;;;;;;8uBAwOqC,CAAC;AAElE,eAAe,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/range-control/index.tsx"],"names":[],"mappings":"AAiYA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,YAAY;;;;aAlXuB,CAAC;;;;;;;;;;;;;;qBAiHmB,CAAC;;;;;iCAwBzC,CAAA;;;;;;;;;;8uBAyOqC,CAAC;AAElE,eAAe,YAAY,CAAC"}
@@ -1,4 +1,4 @@
1
1
  import type { DropdownMenuProps } from '../../dropdown-menu/types';
2
- declare const _default: import("react").ForwardRefExoticComponent<DropdownMenuProps & import("react").RefAttributes<any>>;
3
- export default _default;
2
+ export declare const ToolbarDropdownMenu: import("react").ForwardRefExoticComponent<DropdownMenuProps & import("react").RefAttributes<any>>;
3
+ export default ToolbarDropdownMenu;
4
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/toolbar/toolbar-dropdown-menu/index.tsx"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;;AA8BnE,wBAAiD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/toolbar/toolbar-dropdown-menu/index.tsx"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AA8BnE,eAAO,MAAM,mBAAmB,mGAA+C,CAAC;AAChF,eAAe,mBAAmB,CAAC"}
@@ -1,6 +1,6 @@
1
- declare const _default: import("react").ForwardRefExoticComponent<Omit<import("react").HTMLAttributes<any>, "children"> & {
1
+ export declare const ToolbarItem: import("react").ForwardRefExoticComponent<Omit<import("react").HTMLAttributes<any>, "children"> & {
2
2
  as?: import("react").ElementType;
3
3
  children?: import("react").ReactNode | ((props: import("react").HTMLAttributes<any> & import("react").RefAttributes<any>) => import("react").ReactElement | null);
4
4
  } & import("react").RefAttributes<any>>;
5
- export default _default;
5
+ export default ToolbarItem;
6
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/toolbar/toolbar-item/index.tsx"],"names":[],"mappings":";;;;AA2DA,wBAAyC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/toolbar/toolbar-item/index.tsx"],"names":[],"mappings":"AA2DA,eAAO,MAAM,WAAW;;;uCAAuC,CAAC;AAChE,eAAe,WAAW,CAAC"}
@@ -0,0 +1,3 @@
1
+ declare const getNodeText: (node: React.ReactNode) => string;
2
+ export default getNodeText;
3
+ //# sourceMappingURL=get-node-text.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-node-text.d.ts","sourceRoot":"","sources":["../../src/utils/get-node-text.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,WAAW,SAAW,KAAK,CAAC,SAAS,KAAI,MAqB9C,CAAC;AAEF,eAAe,WAAW,CAAC"}
@@ -25,22 +25,21 @@ export function subtract(...args: Array<number | string>): number;
25
25
  /**
26
26
  * Clamps a value based on a min/max range.
27
27
  *
28
- * @param {number} value The value.
29
- * @param {number} min The minimum range.
30
- * @param {number} max The maximum range.
28
+ * @param {number|string} value The value.
29
+ * @param {number} min The minimum range.
30
+ * @param {number} max The maximum range.
31
31
  *
32
32
  * @return {number} The clamped value.
33
33
  */
34
- export function clamp(value: number, min: number, max: number): number;
34
+ export function clamp(value: number | string, min: number, max: number): number;
35
35
  /**
36
- * Clamps a value based on a min/max range with rounding
36
+ * Rounds a value to the nearest step offset by a minimum.
37
37
  *
38
- * @param {number | string} value The value.
39
- * @param {number} min The minimum range.
40
- * @param {number} max The maximum range.
41
- * @param {number} step A multiplier for the value.
38
+ * @param {number|string} value The value.
39
+ * @param {number} min The minimum range.
40
+ * @param {number} step The increment for the value.
42
41
  *
43
- * @return {number} The rounded and clamped value.
42
+ * @return {number} The value as a valid step.
44
43
  */
45
- export function roundClamp(value?: number | string, min?: number, max?: number, step?: number): number;
44
+ export function ensureValidStep(value: number | string, min: number, step: number): number;
46
45
  //# sourceMappingURL=math.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"math.d.ts","sourceRoot":"","sources":["../../src/utils/math.js"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,iCAJW,OAAO,GAEN,MAAM,CAMjB;AAED;;;;;;GAMG;AACH,6BAJW,KAAK,CAAC,MAAM,GAAC,MAAM,CAAC,GAEnB,MAAM,CAQjB;AAED;;;;;;GAMG;AACH,kCAJW,KAAK,CAAC,MAAM,GAAC,MAAM,CAAC,GAEnB,MAAM,CAWjB;AAcD;;;;;;;;GAQG;AACH,6BANW,MAAM,OACN,MAAM,OACN,MAAM,GAEL,MAAM,CAKjB;AAED;;;;;;;;;GASG;AACH,mCAPW,MAAM,GAAG,MAAM,QACf,MAAM,QACN,MAAM,SACN,MAAM,GAEL,MAAM,CAiBjB"}
1
+ {"version":3,"file":"math.d.ts","sourceRoot":"","sources":["../../src/utils/math.js"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,iCAJW,OAAO,GAEN,MAAM,CAMjB;AAED;;;;;;GAMG;AACH,6BAJW,KAAK,CAAC,MAAM,GAAC,MAAM,CAAC,GAEnB,MAAM,CAQjB;AAED;;;;;;GAMG;AACH,kCAJW,KAAK,CAAC,MAAM,GAAC,MAAM,CAAC,GAEnB,MAAM,CAWjB;AAcD;;;;;;;;GAQG;AACH,6BANW,MAAM,GAAC,MAAM,OACb,MAAM,OACN,MAAM,GAEL,MAAM,CAKjB;AAED;;;;;;;;GAQG;AACH,uCANW,MAAM,GAAC,MAAM,OACb,MAAM,QACN,MAAM,GAEL,MAAM,CAajB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wordpress/components",
3
- "version": "29.6.0",
3
+ "version": "29.7.0",
4
4
  "description": "UI components for WordPress.",
5
5
  "author": "The WordPress Contributors",
6
6
  "license": "GPL-2.0-or-later",
@@ -44,23 +44,23 @@
44
44
  "@types/gradient-parser": "0.1.3",
45
45
  "@types/highlight-words-core": "1.2.1",
46
46
  "@use-gesture/react": "^10.3.1",
47
- "@wordpress/a11y": "^4.20.0",
48
- "@wordpress/compose": "^7.20.0",
49
- "@wordpress/date": "^5.20.0",
50
- "@wordpress/deprecated": "^4.20.0",
51
- "@wordpress/dom": "^4.20.0",
52
- "@wordpress/element": "^6.20.0",
53
- "@wordpress/escape-html": "^3.20.0",
54
- "@wordpress/hooks": "^4.20.0",
55
- "@wordpress/html-entities": "^4.20.0",
56
- "@wordpress/i18n": "^5.20.0",
57
- "@wordpress/icons": "^10.20.0",
58
- "@wordpress/is-shallow-equal": "^5.20.0",
59
- "@wordpress/keycodes": "^4.20.0",
60
- "@wordpress/primitives": "^4.20.0",
61
- "@wordpress/private-apis": "^1.20.0",
62
- "@wordpress/rich-text": "^7.20.0",
63
- "@wordpress/warning": "^3.20.0",
47
+ "@wordpress/a11y": "^4.21.0",
48
+ "@wordpress/compose": "^7.21.0",
49
+ "@wordpress/date": "^5.21.0",
50
+ "@wordpress/deprecated": "^4.21.0",
51
+ "@wordpress/dom": "^4.21.0",
52
+ "@wordpress/element": "^6.21.0",
53
+ "@wordpress/escape-html": "^3.21.0",
54
+ "@wordpress/hooks": "^4.21.0",
55
+ "@wordpress/html-entities": "^4.21.0",
56
+ "@wordpress/i18n": "^5.21.0",
57
+ "@wordpress/icons": "^10.21.0",
58
+ "@wordpress/is-shallow-equal": "^5.21.0",
59
+ "@wordpress/keycodes": "^4.21.0",
60
+ "@wordpress/primitives": "^4.21.0",
61
+ "@wordpress/private-apis": "^1.21.0",
62
+ "@wordpress/rich-text": "^7.21.0",
63
+ "@wordpress/warning": "^3.21.0",
64
64
  "change-case": "^4.1.2",
65
65
  "clsx": "^2.1.1",
66
66
  "colord": "^2.7.0",
@@ -85,5 +85,5 @@
85
85
  "publishConfig": {
86
86
  "access": "public"
87
87
  },
88
- "gitHead": "72476970386146d450c375e5c71a96dda7c9aaa8"
88
+ "gitHead": "104af00f9abcd7a4d36b87e648f148c72cc4ea5f"
89
89
  }
@@ -19,7 +19,7 @@ function Example() {
19
19
  <AnglePickerControl
20
20
  value={ angle }
21
21
  onChange={ setAngle }
22
- </>
22
+ />
23
23
  );
24
24
  }
25
25
  ```
@@ -97,7 +97,7 @@ function UnforwardedAnglePickerControl(
97
97
  * <AnglePickerControl
98
98
  * value={ angle }
99
99
  * onChange={ setAngle }
100
- * </>
100
+ * />
101
101
  * );
102
102
  * }
103
103
  * ```
@@ -40,35 +40,7 @@ import type {
40
40
  UseAutocompleteProps,
41
41
  WPCompleter,
42
42
  } from './types';
43
-
44
- const getNodeText = ( node: React.ReactNode ): string => {
45
- if ( node === null ) {
46
- return '';
47
- }
48
-
49
- switch ( typeof node ) {
50
- case 'string':
51
- case 'number':
52
- return node.toString();
53
- break;
54
- case 'boolean':
55
- return '';
56
- break;
57
- case 'object': {
58
- if ( node instanceof Array ) {
59
- return node.map( getNodeText ).join( '' );
60
- }
61
- if ( 'props' in node ) {
62
- return getNodeText( node.props.children );
63
- }
64
- break;
65
- }
66
- default:
67
- return '';
68
- }
69
-
70
- return '';
71
- };
43
+ import getNodeText from '../utils/get-node-text';
72
44
 
73
45
  const EMPTY_FILTERED_OPTIONS: KeyedOption[] = [];
74
46
 
@@ -394,12 +366,13 @@ export function useAutocomplete( {
394
366
  ? `components-autocomplete-item-${ instanceId }-${ selectedKey }`
395
367
  : null;
396
368
  const hasSelection = record.start !== undefined;
369
+ const showPopover = !! textContent && hasSelection && !! AutocompleterUI;
397
370
 
398
371
  return {
399
372
  listBoxId,
400
373
  activeId,
401
374
  onKeyDown: withIgnoreIMEEvents( handleKeyDown ),
402
- popover: hasSelection && AutocompleterUI && (
375
+ popover: showPopover && (
403
376
  <AutocompleterUI
404
377
  className={ className }
405
378
  filterValue={ filterValue }
@@ -213,6 +213,7 @@ export const SelectedItemCheck = styled( Ariakit.SelectItemCheck )`
213
213
  display: flex;
214
214
  align-items: center;
215
215
  margin-inline-start: ${ space( 2 ) };
216
+ fill: currentColor;
216
217
 
217
218
  // Keep the checkmark vertically aligned at the top. Since the item text has a
218
219
  // 28px line height and the checkmark is 24px tall, a (28-24)/2 = 2px margin
@@ -186,7 +186,7 @@
186
186
  color: $gray-600;
187
187
 
188
188
  &.is-selected {
189
- background-color: $components-color-accent-transparent-40;
189
+ background: color-mix(in srgb, $components-color-accent 4%, transparent);
190
190
  }
191
191
  }
192
192
 
@@ -18,7 +18,7 @@ import deprecated from '@wordpress/deprecated';
18
18
  */
19
19
  import { Input, SpinButton, styles } from './styles/number-control-styles';
20
20
  import * as inputControlActionTypes from '../input-control/reducer/actions';
21
- import { add, subtract, roundClamp } from '../utils/math';
21
+ import { add, subtract, clamp, ensureValidStep } from '../utils/math';
22
22
  import { ensureNumber, isValueEmpty } from '../utils/values';
23
23
  import type { WordPressComponentProps } from '../context/wordpress-component';
24
24
  import type { NumberControlProps } from './types';
@@ -78,17 +78,18 @@ function UnforwardedNumberControl(
78
78
  const isStepAny = step === 'any';
79
79
  const baseStep = isStepAny ? 1 : ensureNumber( step );
80
80
  const baseSpin = ensureNumber( spinFactor ) * baseStep;
81
- const baseValue = roundClamp( 0, min, max, baseStep );
82
81
  const constrainValue = (
83
82
  value: number | string,
84
83
  stepOverride?: number
85
84
  ) => {
86
- // When step is "any" clamp the value, otherwise round and clamp it.
87
- // Use '' + to convert to string for use in input value attribute.
88
- return isStepAny
89
- ? '' + Math.min( max, Math.max( min, ensureNumber( value ) ) )
90
- : '' + roundClamp( value, min, max, stepOverride ?? baseStep );
85
+ // When step is not "any" the value must be a valid step.
86
+ if ( ! isStepAny ) {
87
+ value = ensureValidStep( value, min, stepOverride ?? baseStep );
88
+ }
89
+
90
+ return `${ clamp( value, min, max ) }`;
91
91
  };
92
+ const baseValue = constrainValue( 0 );
92
93
 
93
94
  const autoComplete = typeProp === 'number' ? 'off' : undefined;
94
95
  const classes = clsx( 'components-number-control', className );
@@ -40,8 +40,21 @@ describe( 'NumberControl', () => {
40
40
  } );
41
41
 
42
42
  it( 'should render custom className', () => {
43
- render( <NumberControl className="hello" /> );
44
- expect( screen.getByRole( 'spinbutton' ) ).toBeVisible();
43
+ const { container: withoutClassName } = render( <NumberControl /> );
44
+
45
+ const { container: withClassName } = render(
46
+ <NumberControl className="hello" />
47
+ );
48
+
49
+ expect(
50
+ // eslint-disable-next-line testing-library/no-container, testing-library/no-node-access
51
+ withoutClassName.querySelector( '.components-number-control' )
52
+ ).not.toHaveClass( 'hello' );
53
+
54
+ expect(
55
+ // eslint-disable-next-line testing-library/no-container, testing-library/no-node-access
56
+ withClassName.querySelector( '.components-number-control' )
57
+ ).toHaveClass( 'hello' );
45
58
  } );
46
59
  } );
47
60
 
@@ -391,17 +391,18 @@ function UnforwardedRangeControl(
391
391
  * import { useState } from '@wordpress/element';
392
392
  *
393
393
  * const MyRangeControl = () => {
394
- * const [ isChecked, setChecked ] = useState( true );
394
+ * const [ value, setValue ] = useState();
395
395
  * return (
396
396
  * <RangeControl
397
397
  * __nextHasNoMarginBottom
398
398
  * __next40pxDefaultSize
399
399
  * help="Please select how transparent you would like this."
400
- * initialPosition={50}
400
+ * initialPosition={ 50 }
401
401
  * label="Opacity"
402
- * max={100}
403
- * min={0}
404
- * onChange={() => {}}
402
+ * max={ 100 }
403
+ * min={ 0 }
404
+ * value={ value }
405
+ * onChange={ setValue }
405
406
  * />
406
407
  * );
407
408
  * };
@@ -16,7 +16,7 @@ import ToolbarContext from '../toolbar-context';
16
16
  import DropdownMenu from '../../dropdown-menu';
17
17
  import type { DropdownMenuProps } from '../../dropdown-menu/types';
18
18
 
19
- function ToolbarDropdownMenu(
19
+ function UnforwardedToolbarDropdownMenu(
20
20
  props: DropdownMenuProps,
21
21
  ref: ForwardedRef< any >
22
22
  ) {
@@ -44,4 +44,5 @@ function ToolbarDropdownMenu(
44
44
  );
45
45
  }
46
46
 
47
- export default forwardRef( ToolbarDropdownMenu );
47
+ export const ToolbarDropdownMenu = forwardRef( UnforwardedToolbarDropdownMenu );
48
+ export default ToolbarDropdownMenu;
@@ -16,7 +16,7 @@ import warning from '@wordpress/warning';
16
16
  import ToolbarContext from '../toolbar-context';
17
17
  import type { ToolbarItemProps } from './types';
18
18
 
19
- function ToolbarItem(
19
+ function UnforwardedToolbarItem(
20
20
  { children, as: Component, ...props }: ToolbarItemProps,
21
21
  ref: ForwardedRef< any >
22
22
  ) {
@@ -57,4 +57,5 @@ function ToolbarItem(
57
57
  );
58
58
  }
59
59
 
60
- export default forwardRef( ToolbarItem );
60
+ export const ToolbarItem = forwardRef( UnforwardedToolbarItem );
61
+ export default ToolbarItem;
@@ -0,0 +1,24 @@
1
+ const getNodeText = ( node: React.ReactNode ): string => {
2
+ if ( node === null ) {
3
+ return '';
4
+ }
5
+
6
+ switch ( typeof node ) {
7
+ case 'string':
8
+ case 'number':
9
+ return node.toString();
10
+ case 'object': {
11
+ if ( node instanceof Array ) {
12
+ return node.map( getNodeText ).join( '' );
13
+ }
14
+ if ( 'props' in node ) {
15
+ return getNodeText( node.props.children );
16
+ }
17
+ return '';
18
+ }
19
+ default:
20
+ return '';
21
+ }
22
+ };
23
+
24
+ export default getNodeText;
package/src/utils/math.js CHANGED
@@ -59,9 +59,9 @@ function getPrecision( value ) {
59
59
  /**
60
60
  * Clamps a value based on a min/max range.
61
61
  *
62
- * @param {number} value The value.
63
- * @param {number} min The minimum range.
64
- * @param {number} max The maximum range.
62
+ * @param {number|string} value The value.
63
+ * @param {number} min The minimum range.
64
+ * @param {number} max The maximum range.
65
65
  *
66
66
  * @return {number} The clamped value.
67
67
  */
@@ -71,28 +71,23 @@ export function clamp( value, min, max ) {
71
71
  }
72
72
 
73
73
  /**
74
- * Clamps a value based on a min/max range with rounding
74
+ * Rounds a value to the nearest step offset by a minimum.
75
75
  *
76
- * @param {number | string} value The value.
77
- * @param {number} min The minimum range.
78
- * @param {number} max The maximum range.
79
- * @param {number} step A multiplier for the value.
76
+ * @param {number|string} value The value.
77
+ * @param {number} min The minimum range.
78
+ * @param {number} step The increment for the value.
80
79
  *
81
- * @return {number} The rounded and clamped value.
80
+ * @return {number} The value as a valid step.
82
81
  */
83
- export function roundClamp(
84
- value = 0,
85
- min = Infinity,
86
- max = Infinity,
87
- step = 1
88
- ) {
82
+ export function ensureValidStep( value, min, step ) {
89
83
  const baseValue = getNumber( value );
90
84
  const stepValue = getNumber( step );
91
- const precision = getPrecision( step );
92
- const rounded = Math.round( baseValue / stepValue ) * stepValue;
93
- const clampedValue = clamp( rounded, min, max );
94
-
95
- return precision
96
- ? getNumber( clampedValue.toFixed( precision ) )
97
- : clampedValue;
85
+ const precision = Math.max( getPrecision( step ), getPrecision( min ) );
86
+ const realMin = Math.abs( min ) === Infinity ? 0 : min;
87
+ // If the step is not a factor of the minimum then the step must be
88
+ // offset by the minimum.
89
+ const tare = realMin % stepValue ? realMin : 0;
90
+ const rounded = Math.round( ( baseValue - tare ) / stepValue ) * stepValue;
91
+ const fromMin = rounded + tare;
92
+ return precision ? getNumber( fromMin.toFixed( precision ) ) : fromMin;
98
93
  }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Internal dependencies
3
+ */
4
+ import getNodeText from '../get-node-text';
5
+
6
+ describe( 'getNodeText', () => {
7
+ it( 'should return an empty string for null', () => {
8
+ expect( getNodeText( null ) ).toBe( '' );
9
+ } );
10
+
11
+ it( 'should return the string representation of a string node', () => {
12
+ expect( getNodeText( 'Hello' ) ).toBe( 'Hello' );
13
+ } );
14
+
15
+ it( 'should return the string representation of a number node', () => {
16
+ expect( getNodeText( 123 ) ).toBe( '123' );
17
+ } );
18
+
19
+ it( 'should return an empty string for a boolean node', () => {
20
+ expect( getNodeText( true ) ).toBe( '' );
21
+ } );
22
+
23
+ it( 'should concatenate text from an array of nodes', () => {
24
+ expect( getNodeText( [ 'Hello', ' ', 'World' ] ) ).toBe(
25
+ 'Hello World'
26
+ );
27
+ } );
28
+
29
+ it( 'should return text from a React element with children', () => {
30
+ const element = (
31
+ <div>
32
+ Hello <span>World</span>
33
+ </div>
34
+ );
35
+ expect( getNodeText( element ) ).toBe( 'Hello World' );
36
+ } );
37
+ } );
@@ -1,7 +1,8 @@
1
1
  /**
2
2
  * Internal dependencies
3
3
  */
4
- import { add, clamp, subtract, roundClamp } from '../math';
4
+
5
+ import { add, subtract, clamp, ensureValidStep } from '../math';
5
6
 
6
7
  describe( 'add', () => {
7
8
  it( 'should add string and number values', () => {
@@ -58,44 +59,39 @@ describe( 'clamp', () => {
58
59
  } );
59
60
  } );
60
61
 
61
- describe( 'roundClamp', () => {
62
- it( 'should clamp a value between min and max', () => {
63
- expect( roundClamp( 10, 1, 10 ) ).toBe( 10 );
64
- expect( roundClamp( 1, 1, 10 ) ).toBe( 1 );
65
- expect( roundClamp( 0, 1, 10 ) ).toBe( 1 );
62
+ describe( 'ensureValidStep', () => {
63
+ it( 'should work with number or string values', () => {
64
+ expect( ensureValidStep( '49', 0, 10 ) ).toBe( 50 );
65
+ expect( ensureValidStep( 49, '0', 10 ) ).toBe( 50 );
66
+ expect( ensureValidStep( 49, 0, '10' ) ).toBe( 50 );
67
+ } );
66
68
 
67
- expect( roundClamp( 50, 1, 10 ) ).toBe( 10 );
68
- expect( roundClamp( 50, -10, 10 ) ).toBe( 10 );
69
- expect( roundClamp( -50, -10, 10 ) ).toBe( -10 );
69
+ it( 'should round to step', () => {
70
+ expect( ensureValidStep( 40, 0, 10 ) ).toBe( 40 );
71
+ expect( ensureValidStep( 42, 0, 10 ) ).toBe( 40 );
72
+ expect( ensureValidStep( 45, 0, 10 ) ).toBe( 50 );
73
+ expect( ensureValidStep( 49, 0, 10 ) ).toBe( 50 );
70
74
 
71
- expect( roundClamp( '50', 1, 10 ) ).toBe( 10 );
72
- expect( roundClamp( '50', -10, 10 ) ).toBe( 10 );
73
- expect( roundClamp( -50, -10, '10' ) ).toBe( -10 );
75
+ expect( ensureValidStep( 50, 0, 15 ) ).toBe( 45 );
76
+ expect( ensureValidStep( 50, 0, 11 ) ).toBe( 55 );
74
77
  } );
75
78
 
76
- it( 'should clamp number or string values', () => {
77
- expect( roundClamp( '50', 1, 10 ) ).toBe( 10 );
78
- expect( roundClamp( '50', -10, 10 ) ).toBe( 10 );
79
- expect( roundClamp( -50, -10, '10' ) ).toBe( -10 );
79
+ it( 'should round with float in step', () => {
80
+ expect( ensureValidStep( 40.5, 1, 0.1 ) ).toBe( 40.5 );
81
+ expect( ensureValidStep( 40.05, 1, 0.01 ) ).toBe( 40.05 );
82
+ expect( ensureValidStep( 40.06, 1, 0.1 ) ).toBe( 40.1 );
83
+ expect( ensureValidStep( 40.123005, 1, 0.001 ) ).toBe( 40.123 );
80
84
  } );
81
85
 
82
- it( 'should clamp with step', () => {
83
- expect( roundClamp( 40, 1, 100, 10 ) ).toBe( 40 );
84
- expect( roundClamp( 42, 1, 100, 10 ) ).toBe( 40 );
85
- expect( roundClamp( 45, 1, 100, 10 ) ).toBe( 50 );
86
- expect( roundClamp( 49, 1, 100, 10 ) ).toBe( 50 );
87
- expect( roundClamp( 50, 1, 100, 10 ) ).toBe( 50 );
88
-
89
- expect( roundClamp( 50, 1, 100, 15 ) ).toBe( 45 );
90
- expect( roundClamp( 50, 1, 100, '15' ) ).toBe( 45 );
91
- expect( roundClamp( 50, 1, 100, 11 ) ).toBe( 55 );
86
+ it( 'should round to steps starting from min', () => {
87
+ expect( ensureValidStep( 10, 0.25, 1 ) ).toBe( 10.25 );
88
+ expect( ensureValidStep( 10, -20.25, 1 ) ).toBe( 9.75 );
89
+ expect( ensureValidStep( 10.5, 0.05, 0.1 ) ).toBe( 10.45 );
90
+ expect( ensureValidStep( 10.51, 0.05, 0.1 ) ).toBe( 10.55 );
92
91
  } );
93
92
 
94
- it( 'should clamp with float in step', () => {
95
- expect( roundClamp( 40, 1, 100, 1 ) ).toBe( 40 );
96
- expect( roundClamp( 40.5, 1, 100, 0.1 ) ).toBe( 40.5 );
97
- expect( roundClamp( 40.05, 1, 100, 0.01 ) ).toBe( 40.05 );
98
- expect( roundClamp( 40.06, 1, 100, 0.1 ) ).toBe( 40.1 );
99
- expect( roundClamp( 40.123005, 1, 100, 0.001 ) ).toBe( 40.123 );
93
+ it( 'should round with a precision that’s the greater of min and step', () => {
94
+ expect( ensureValidStep( 10.061, 0.01, 0.1 ) ).toBe( 10.11 );
95
+ expect( ensureValidStep( 10.105, 0.1, 0.01 ) ).toBe( 10.11 );
100
96
  } );
101
97
  } );
@@ -4,10 +4,6 @@
4
4
  // `--wp-admin-theme-color`. If the `--wp-admin-theme-color` variable is not
5
5
  // defined, fallback to the default theme color (WP blueberry).
6
6
  $components-color-accent: var(--wp-components-color-accent, var(--wp-admin-theme-color, #3858e9));
7
-
8
- // Define accent color transparent variants.
9
- $components-color-accent-transparent-40: rgba(var(--wp-components-color-accent--rgb, var(--wp-admin-theme-color--rgb)), 0.04);
10
-
11
7
  $components-color-accent-darker-10: var(--wp-components-color-accent-darker-10, var(--wp-admin-theme-color-darker-10, #2145e6));
12
8
  $components-color-accent-darker-20: var(--wp-components-color-accent-darker-20, var(--wp-admin-theme-color-darker-20, #183ad6));
13
9