@wordpress/components 19.6.1-next.a55ed9455a.0 → 19.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 (179) hide show
  1. package/CHANGELOG.md +31 -1
  2. package/build/base-control/index.js +19 -14
  3. package/build/base-control/index.js.map +1 -1
  4. package/build/base-control/styles/base-control-styles.js +33 -12
  5. package/build/base-control/styles/base-control-styles.js.map +1 -1
  6. package/build/box-control/all-input-control.js +3 -7
  7. package/build/box-control/all-input-control.js.map +1 -1
  8. package/build/box-control/axial-input-controls.js +20 -15
  9. package/build/box-control/axial-input-controls.js.map +1 -1
  10. package/build/box-control/input-controls.js +21 -16
  11. package/build/box-control/input-controls.js.map +1 -1
  12. package/build/box-control/utils.js +25 -11
  13. package/build/box-control/utils.js.map +1 -1
  14. package/build/checkbox-control/index.js +21 -1
  15. package/build/checkbox-control/index.js.map +1 -1
  16. package/build/color-palette/index.js +53 -4
  17. package/build/color-palette/index.js.map +1 -1
  18. package/build/custom-select-control/index.js +8 -3
  19. package/build/custom-select-control/index.js.map +1 -1
  20. package/build/divider/styles.js +28 -16
  21. package/build/divider/styles.js.map +1 -1
  22. package/build/focal-point-picker/controls.js +2 -3
  23. package/build/focal-point-picker/controls.js.map +1 -1
  24. package/build/form-file-upload/index.js +4 -1
  25. package/build/form-file-upload/index.js.map +1 -1
  26. package/build/input-control/input-field.js +21 -14
  27. package/build/input-control/input-field.js.map +1 -1
  28. package/build/input-control/reducer/actions.js +1 -3
  29. package/build/input-control/reducer/actions.js.map +1 -1
  30. package/build/input-control/reducer/reducer.js +1 -43
  31. package/build/input-control/reducer/reducer.js.map +1 -1
  32. package/build/number-control/index.js +15 -10
  33. package/build/number-control/index.js.map +1 -1
  34. package/build/resizable-box/resize-tooltip/styles/resize-tooltip.styles.js +4 -4
  35. package/build/resizable-box/resize-tooltip/styles/resize-tooltip.styles.js.map +1 -1
  36. package/build/toggle-group-control/toggle-group-control-option/component.js +1 -4
  37. package/build/toggle-group-control/toggle-group-control-option/component.js.map +1 -1
  38. package/build/toggle-group-control/toggle-group-control-option/styles.js +12 -19
  39. package/build/toggle-group-control/toggle-group-control-option/styles.js.map +1 -1
  40. package/build/tree-grid/index.js +4 -1
  41. package/build/tree-grid/index.js.map +1 -1
  42. package/build/unit-control/index.js +49 -27
  43. package/build/unit-control/index.js.map +1 -1
  44. package/build/unit-control/unit-select-control.js +2 -4
  45. package/build/unit-control/unit-select-control.js.map +1 -1
  46. package/build-module/base-control/index.js +19 -14
  47. package/build-module/base-control/index.js.map +1 -1
  48. package/build-module/base-control/styles/base-control-styles.js +34 -6
  49. package/build-module/base-control/styles/base-control-styles.js.map +1 -1
  50. package/build-module/box-control/all-input-control.js +4 -8
  51. package/build-module/box-control/all-input-control.js.map +1 -1
  52. package/build-module/box-control/axial-input-controls.js +18 -14
  53. package/build-module/box-control/axial-input-controls.js.map +1 -1
  54. package/build-module/box-control/input-controls.js +18 -14
  55. package/build-module/box-control/input-controls.js.map +1 -1
  56. package/build-module/box-control/utils.js +25 -11
  57. package/build-module/box-control/utils.js.map +1 -1
  58. package/build-module/checkbox-control/index.js +24 -3
  59. package/build-module/checkbox-control/index.js.map +1 -1
  60. package/build-module/color-palette/index.js +52 -4
  61. package/build-module/color-palette/index.js.map +1 -1
  62. package/build-module/custom-select-control/index.js +8 -3
  63. package/build-module/custom-select-control/index.js.map +1 -1
  64. package/build-module/divider/styles.js +29 -10
  65. package/build-module/divider/styles.js.map +1 -1
  66. package/build-module/focal-point-picker/controls.js +2 -3
  67. package/build-module/focal-point-picker/controls.js.map +1 -1
  68. package/build-module/form-file-upload/index.js +4 -1
  69. package/build-module/form-file-upload/index.js.map +1 -1
  70. package/build-module/input-control/input-field.js +21 -13
  71. package/build-module/input-control/input-field.js.map +1 -1
  72. package/build-module/input-control/reducer/actions.js +0 -1
  73. package/build-module/input-control/reducer/actions.js.map +1 -1
  74. package/build-module/input-control/reducer/reducer.js +2 -39
  75. package/build-module/input-control/reducer/reducer.js.map +1 -1
  76. package/build-module/number-control/index.js +15 -9
  77. package/build-module/number-control/index.js.map +1 -1
  78. package/build-module/resizable-box/resize-tooltip/styles/resize-tooltip.styles.js +4 -4
  79. package/build-module/resizable-box/resize-tooltip/styles/resize-tooltip.styles.js.map +1 -1
  80. package/build-module/toggle-group-control/toggle-group-control-option/component.js +1 -4
  81. package/build-module/toggle-group-control/toggle-group-control-option/component.js.map +1 -1
  82. package/build-module/toggle-group-control/toggle-group-control-option/styles.js +11 -17
  83. package/build-module/toggle-group-control/toggle-group-control-option/styles.js.map +1 -1
  84. package/build-module/tree-grid/index.js +4 -1
  85. package/build-module/tree-grid/index.js.map +1 -1
  86. package/build-module/unit-control/index.js +47 -25
  87. package/build-module/unit-control/index.js.map +1 -1
  88. package/build-module/unit-control/unit-select-control.js +2 -3
  89. package/build-module/unit-control/unit-select-control.js.map +1 -1
  90. package/build-style/style-rtl.css +29 -181
  91. package/build-style/style.css +29 -181
  92. package/build-types/base-control/index.d.ts +23 -18
  93. package/build-types/base-control/index.d.ts.map +1 -1
  94. package/build-types/base-control/styles/base-control-styles.d.ts +4 -0
  95. package/build-types/base-control/styles/base-control-styles.d.ts.map +1 -1
  96. package/build-types/card/card-divider/hook.d.ts +1 -1
  97. package/build-types/color-palette/index.d.ts.map +1 -1
  98. package/build-types/color-picker/styles.d.ts +1 -1
  99. package/build-types/divider/stories/index.d.ts +1 -0
  100. package/build-types/divider/stories/index.d.ts.map +1 -1
  101. package/build-types/divider/styles.d.ts.map +1 -1
  102. package/build-types/divider/types.d.ts +8 -1
  103. package/build-types/divider/types.d.ts.map +1 -1
  104. package/build-types/input-control/input-field.d.ts.map +1 -1
  105. package/build-types/input-control/reducer/actions.d.ts +1 -3
  106. package/build-types/input-control/reducer/actions.d.ts.map +1 -1
  107. package/build-types/input-control/reducer/reducer.d.ts +3 -9
  108. package/build-types/input-control/reducer/reducer.d.ts.map +1 -1
  109. package/build-types/input-control/types.d.ts +2 -2
  110. package/build-types/input-control/types.d.ts.map +1 -1
  111. package/build-types/number-control/index.d.ts +3 -3
  112. package/build-types/number-control/index.d.ts.map +1 -1
  113. package/build-types/range-control/styles/range-control-styles.d.ts +1 -1
  114. package/build-types/resizable-box/resize-tooltip/styles/resize-tooltip.styles.d.ts.map +1 -1
  115. package/build-types/toggle-group-control/toggle-group-control-option/component.d.ts.map +1 -1
  116. package/build-types/toggle-group-control/toggle-group-control-option/styles.d.ts +0 -4
  117. package/build-types/toggle-group-control/toggle-group-control-option/styles.d.ts.map +1 -1
  118. package/build-types/unit-control/index.d.ts +7 -4
  119. package/build-types/unit-control/index.d.ts.map +1 -1
  120. package/build-types/unit-control/stories/index.d.ts +33 -0
  121. package/build-types/unit-control/stories/index.d.ts.map +1 -0
  122. package/build-types/unit-control/styles/unit-control-styles.d.ts +1 -1
  123. package/build-types/unit-control/types.d.ts +23 -6
  124. package/build-types/unit-control/types.d.ts.map +1 -1
  125. package/build-types/unit-control/unit-select-control.d.ts.map +1 -1
  126. package/package.json +17 -17
  127. package/src/base-control/README.md +9 -1
  128. package/src/base-control/index.js +20 -13
  129. package/src/base-control/stories/index.js +2 -2
  130. package/src/base-control/styles/base-control-styles.js +23 -1
  131. package/src/box-control/all-input-control.js +2 -10
  132. package/src/box-control/axial-input-controls.js +32 -21
  133. package/src/box-control/input-controls.js +30 -19
  134. package/src/box-control/utils.js +29 -12
  135. package/src/checkbox-control/index.js +34 -3
  136. package/src/checkbox-control/stories/index.js +44 -0
  137. package/src/checkbox-control/style.scss +4 -2
  138. package/src/color-palette/index.js +73 -8
  139. package/src/color-palette/stories/index.js +62 -26
  140. package/src/color-palette/style.scss +11 -3
  141. package/src/color-palette/test/__snapshots__/index.js.snap +662 -12
  142. package/src/color-palette/test/index.js +1 -1
  143. package/src/custom-select-control/index.js +8 -2
  144. package/src/custom-select-control/stories/index.js +77 -74
  145. package/src/custom-select-control/style.scss +18 -3
  146. package/src/divider/stories/index.tsx +26 -23
  147. package/src/divider/styles.ts +9 -0
  148. package/src/divider/types.ts +11 -1
  149. package/src/focal-point-picker/controls.js +2 -3
  150. package/src/font-size-picker/test/index.js +0 -2
  151. package/src/form-file-upload/README.md +18 -0
  152. package/src/form-file-upload/index.js +3 -0
  153. package/src/form-file-upload/test/index.js +73 -11
  154. package/src/input-control/input-field.tsx +23 -12
  155. package/src/input-control/reducer/actions.ts +1 -7
  156. package/src/input-control/reducer/reducer.ts +0 -29
  157. package/src/input-control/types.ts +2 -1
  158. package/src/mobile/image/style.native.scss +1 -0
  159. package/src/number-control/README.md +14 -0
  160. package/src/number-control/index.js +13 -12
  161. package/src/number-control/stories/index.js +14 -7
  162. package/src/number-control/test/index.js +79 -1
  163. package/src/range-control/stories/index.js +91 -119
  164. package/src/resizable-box/resize-tooltip/styles/resize-tooltip.styles.js +1 -0
  165. package/src/toggle-group-control/test/__snapshots__/index.js.snap +0 -27
  166. package/src/toggle-group-control/toggle-group-control-option/component.tsx +1 -4
  167. package/src/toggle-group-control/toggle-group-control-option/styles.ts +0 -12
  168. package/src/toolbar-group/style.scss +0 -73
  169. package/src/tree-grid/README.md +1 -1
  170. package/src/tree-grid/index.js +4 -0
  171. package/src/tree-grid/test/index.js +61 -17
  172. package/src/unit-control/README.md +1 -3
  173. package/src/unit-control/index.tsx +59 -30
  174. package/src/unit-control/stories/index.tsx +170 -0
  175. package/src/unit-control/test/index.js +143 -100
  176. package/src/unit-control/types.ts +60 -41
  177. package/src/unit-control/unit-select-control.tsx +2 -3
  178. package/tsconfig.tsbuildinfo +1 -1
  179. package/src/unit-control/stories/index.js +0 -127
@@ -1,7 +1,6 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import { isEmpty } from 'lodash';
5
4
  import type { SyntheticEvent } from 'react';
6
5
 
7
6
  /**
@@ -38,27 +37,6 @@ function mergeInitialState(
38
37
  } as InputState;
39
38
  }
40
39
 
41
- /**
42
- * Composes multiple stateReducers into a single stateReducer, building
43
- * the pipeline to control the flow for state and actions.
44
- *
45
- * @param fns State reducers.
46
- * @return The single composed stateReducer.
47
- */
48
- export const composeStateReducers = (
49
- ...fns: StateReducer[]
50
- ): StateReducer => {
51
- return ( ...args ) => {
52
- return fns.reduceRight( ( state, fn ) => {
53
- // TODO: Assess whether this can be replaced with a more standard `compose` implementation
54
- // like wp.data.compose() (aka lodash flowRight) or Redux compose().
55
- // The current implementation only works by functions mutating the original state object.
56
- const fnState = fn( ...args );
57
- return isEmpty( fnState ) ? state : { ...state, ...fnState };
58
- }, {} as InputState );
59
- };
60
- };
61
-
62
40
  /**
63
41
  * Creates a reducer that opens the channel for external state subscription
64
42
  * and modification.
@@ -122,11 +100,6 @@ function inputControlStateReducer(
122
100
  nextState.value = action.payload.value || state.initialValue;
123
101
  break;
124
102
 
125
- case actions.UPDATE:
126
- nextState.value = action.payload.value;
127
- nextState.isDirty = false;
128
- break;
129
-
130
103
  /**
131
104
  * Validation
132
105
  */
@@ -219,7 +192,6 @@ export function useInputControlStateReducer(
219
192
  dispatch( { type: actions.INVALIDATE, payload: { error, event } } );
220
193
  const reset = createChangeEvent( actions.RESET );
221
194
  const commit = createChangeEvent( actions.COMMIT );
222
- const update = createChangeEvent( actions.UPDATE );
223
195
 
224
196
  const dragStart = createDragEvent( actions.DRAG_START );
225
197
  const drag = createDragEvent( actions.DRAG );
@@ -242,6 +214,5 @@ export function useInputControlStateReducer(
242
214
  pressUp,
243
215
  reset,
244
216
  state,
245
- update,
246
217
  } as const;
247
218
  }
@@ -6,6 +6,7 @@ import type {
6
6
  ReactNode,
7
7
  ChangeEvent,
8
8
  SyntheticEvent,
9
+ PointerEvent,
9
10
  } from 'react';
10
11
  import type { useDrag } from '@use-gesture/react';
11
12
 
@@ -33,7 +34,7 @@ interface BaseProps {
33
34
  }
34
35
 
35
36
  export type InputChangeCallback<
36
- E = ChangeEvent< HTMLInputElement >,
37
+ E = ChangeEvent< HTMLInputElement > | PointerEvent< HTMLInputElement >,
37
38
  P = {}
38
39
  > = ( nextValue: string | undefined, extra: { event: E } & P ) => void;
39
40
 
@@ -89,6 +89,7 @@
89
89
  color: #fff;
90
90
  font-size: 14;
91
91
  margin-top: 5;
92
+ text-align: center;
92
93
  }
93
94
 
94
95
  .editContainer {
@@ -97,6 +97,20 @@ The minimum `value` allowed.
97
97
  - Required: No
98
98
  - Default: `-Infinity`
99
99
 
100
+ ### onChange
101
+
102
+ Callback fired whenever the value of the input changes.
103
+
104
+ The callback receives two arguments:
105
+
106
+ 1. `newValue`: the new value of the input
107
+ 2. `extra`: an object containing, under the `event` key, the original browser event.
108
+
109
+ Note that the value received as the first argument of the callback is _not_ guaranteed to be a valid value (e.g. it could be outside of the range defined by the [`min`, `max`] props, or it could not match the `step`). In order to check the value's validity, check the `event.target?.validity.valid` property from the callback's second argument.
110
+
111
+ - Type: `(newValue, extra) => void`
112
+ - Required: No
113
+
100
114
  ### required
101
115
 
102
116
  If `true` enforces a valid number within the control's min/max range. If `false` allows an empty string as a valid value.
@@ -15,13 +15,12 @@ import { isRTL } from '@wordpress/i18n';
15
15
  */
16
16
  import { Input } from './styles/number-control-styles';
17
17
  import * as inputControlActionTypes from '../input-control/reducer/actions';
18
- import { composeStateReducers } from '../input-control/reducer/reducer';
19
18
  import { add, subtract, roundClamp } from '../utils/math';
20
19
  import { isValueEmpty } from '../utils/values';
21
20
 
22
21
  export function NumberControl(
23
22
  {
24
- __unstableStateReducer: stateReducer = ( state ) => state,
23
+ __unstableStateReducer: stateReducerProp,
25
24
  className,
26
25
  dragDirection = 'n',
27
26
  hideHTMLArrows = false,
@@ -62,9 +61,11 @@ export function NumberControl(
62
61
  * @return {Object} The updated state to apply to InputControl
63
62
  */
64
63
  const numberControlStateReducer = ( state, action ) => {
64
+ const nextState = { ...state };
65
+
65
66
  const { type, payload } = action;
66
67
  const event = payload?.event;
67
- const currentValue = state.value;
68
+ const currentValue = nextState.value;
68
69
 
69
70
  /**
70
71
  * Handles custom UP and DOWN Keyboard events
@@ -94,7 +95,7 @@ export function NumberControl(
94
95
  nextValue = subtract( nextValue, incrementalValue );
95
96
  }
96
97
 
97
- state.value = constrainValue(
98
+ nextState.value = constrainValue(
98
99
  nextValue,
99
100
  enableShift ? incrementalValue : null
100
101
  );
@@ -139,7 +140,7 @@ export function NumberControl(
139
140
  delta = Math.ceil( Math.abs( delta ) ) * Math.sign( delta );
140
141
  const distance = delta * modifier * directionModifier;
141
142
 
142
- state.value = constrainValue(
143
+ nextState.value = constrainValue(
143
144
  add( currentValue, distance ),
144
145
  enableShift ? modifier : null
145
146
  );
@@ -147,7 +148,7 @@ export function NumberControl(
147
148
  }
148
149
 
149
150
  /**
150
- * Handles commit (ENTER key press or on blur if isPressEnterToChange)
151
+ * Handles commit (ENTER key press or blur)
151
152
  */
152
153
  if (
153
154
  type === inputControlActionTypes.PRESS_ENTER ||
@@ -155,12 +156,12 @@ export function NumberControl(
155
156
  ) {
156
157
  const applyEmptyValue = required === false && currentValue === '';
157
158
 
158
- state.value = applyEmptyValue
159
+ nextState.value = applyEmptyValue
159
160
  ? currentValue
160
161
  : constrainValue( currentValue );
161
162
  }
162
163
 
163
- return state;
164
+ return nextState;
164
165
  };
165
166
 
166
167
  return (
@@ -180,10 +181,10 @@ export function NumberControl(
180
181
  step={ step }
181
182
  type={ typeProp }
182
183
  value={ valueProp }
183
- __unstableStateReducer={ composeStateReducers(
184
- numberControlStateReducer,
185
- stateReducer
186
- ) }
184
+ __unstableStateReducer={ ( state, action ) => {
185
+ const baseState = numberControlStateReducer( state, action );
186
+ return stateReducerProp?.( baseState, action ) ?? baseState;
187
+ } }
187
188
  />
188
189
  );
189
190
  }
@@ -23,6 +23,7 @@ export default {
23
23
 
24
24
  function Example() {
25
25
  const [ value, setValue ] = useState( '0' );
26
+ const [ isValidValue, setIsValidValue ] = useState( true );
26
27
 
27
28
  const props = {
28
29
  disabled: boolean( 'disabled', false ),
@@ -32,18 +33,24 @@ function Example() {
32
33
  label: text( 'label', 'Number' ),
33
34
  min: number( 'min', 0 ),
34
35
  max: number( 'max', 100 ),
35
- placeholder: text( 'placeholder', 0 ),
36
+ placeholder: text( 'placeholder', '0' ),
36
37
  required: boolean( 'required', false ),
37
38
  shiftStep: number( 'shiftStep', 10 ),
38
- step: text( 'step', 1 ),
39
+ step: text( 'step', '1' ),
39
40
  };
40
41
 
41
42
  return (
42
- <NumberControl
43
- { ...props }
44
- value={ value }
45
- onChange={ ( v ) => setValue( v ) }
46
- />
43
+ <>
44
+ <NumberControl
45
+ { ...props }
46
+ value={ value }
47
+ onChange={ ( v, extra ) => {
48
+ setValue( v );
49
+ setIsValidValue( extra.event.target.validity.valid );
50
+ } }
51
+ />
52
+ <p>Is valid? { isValidValue ? 'Yes' : 'No' }</p>
53
+ </>
47
54
  );
48
55
  }
49
56
 
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import { render, screen, fireEvent } from '@testing-library/react';
4
+ import { render, screen, fireEvent, waitFor } from '@testing-library/react';
5
5
 
6
6
  /**
7
7
  * WordPress dependencies
@@ -63,6 +63,68 @@ describe( 'NumberControl', () => {
63
63
 
64
64
  expect( spy ).toHaveBeenCalledWith( '10' );
65
65
  } );
66
+
67
+ it( 'should call onChange callback when value is clamped on blur', async () => {
68
+ const spy = jest.fn();
69
+ render(
70
+ <NumberControl
71
+ value={ 5 }
72
+ min={ 4 }
73
+ max={ 10 }
74
+ onChange={ ( v ) => spy( v ) }
75
+ />
76
+ );
77
+
78
+ const input = getInput();
79
+ input.focus();
80
+ fireEvent.change( input, { target: { value: 1 } } );
81
+
82
+ // Before blurring, the value is still un-clamped
83
+ expect( input.value ).toBe( '1' );
84
+
85
+ input.blur();
86
+
87
+ // After blur, value is clamped
88
+ expect( input.value ).toBe( '4' );
89
+
90
+ // After the blur, the `onChange` callback fires asynchronously.
91
+ await waitFor( () => {
92
+ expect( spy ).toHaveBeenCalledTimes( 2 );
93
+ expect( spy ).toHaveBeenNthCalledWith( 1, '1' );
94
+ expect( spy ).toHaveBeenNthCalledWith( 2, 4 );
95
+ } );
96
+ } );
97
+
98
+ it( 'should call onChange callback when value is not valid', () => {
99
+ const spy = jest.fn();
100
+ render(
101
+ <NumberControl
102
+ value={ 5 }
103
+ min={ 1 }
104
+ max={ 10 }
105
+ onChange={ ( v, extra ) =>
106
+ spy( v, extra.event.target.validity.valid )
107
+ }
108
+ />
109
+ );
110
+
111
+ const input = getInput();
112
+ input.focus();
113
+ fireEvent.change( input, { target: { value: 14 } } );
114
+
115
+ expect( input.value ).toBe( '14' );
116
+
117
+ fireKeyDown( { keyCode: ENTER } );
118
+
119
+ expect( input.value ).toBe( '10' );
120
+
121
+ expect( spy ).toHaveBeenCalledTimes( 2 );
122
+
123
+ // First call: invalid, unclamped value
124
+ expect( spy ).toHaveBeenNthCalledWith( 1, '14', false );
125
+ // Second call: valid, clamped value
126
+ expect( spy ).toHaveBeenNthCalledWith( 2, 10, true );
127
+ } );
66
128
  } );
67
129
 
68
130
  describe( 'Validation', () => {
@@ -82,6 +144,22 @@ describe( 'NumberControl', () => {
82
144
  expect( input.value ).toBe( '0' );
83
145
  } );
84
146
 
147
+ it( 'should clamp value within range on blur', () => {
148
+ render( <NumberControl value={ 5 } min={ 0 } max={ 10 } /> );
149
+
150
+ const input = getInput();
151
+ input.focus();
152
+ fireEvent.change( input, { target: { value: 41 } } );
153
+
154
+ // Before blurring, the value is still un-clamped
155
+ expect( input.value ).toBe( '41' );
156
+
157
+ input.blur();
158
+
159
+ // After blur, value is clamped
160
+ expect( input.value ).toBe( '10' );
161
+ } );
162
+
85
163
  it( 'should parse to number value on ENTER keypress when required', () => {
86
164
  render( <NumberControl value={ 5 } required={ true } /> );
87
165
 
@@ -1,145 +1,128 @@
1
- /**
2
- * External dependencies
3
- */
4
- import styled from '@emotion/styled';
5
- import { boolean, number, text } from '@storybook/addon-knobs';
6
-
7
1
  /**
8
2
  * WordPress dependencies
9
3
  */
10
4
  import { useState } from '@wordpress/element';
11
- import { wordpress } from '@wordpress/icons';
5
+ import { styles, wordpress } from '@wordpress/icons';
12
6
 
13
7
  /**
14
8
  * Internal dependencies
15
9
  */
16
10
  import RangeControl from '../index';
17
- import { COLORS } from '../../utils';
11
+
12
+ const ICONS = { styles, wordpress };
18
13
 
19
14
  export default {
20
15
  title: 'Components/RangeControl',
21
16
  component: RangeControl,
17
+ argTypes: {
18
+ afterIcon: {
19
+ control: { type: 'select' },
20
+ options: Object.keys( ICONS ),
21
+ mapping: ICONS,
22
+ },
23
+ allowReset: { control: { type: 'boolean' } },
24
+ beforeIcon: {
25
+ control: { type: 'select' },
26
+ options: Object.keys( ICONS ),
27
+ mapping: ICONS,
28
+ },
29
+ color: { control: { type: 'color' } },
30
+ disabled: { control: { type: 'boolean' } },
31
+ help: { control: { type: 'text' } },
32
+ initialPosition: { control: { type: 'number' } },
33
+ marks: { control: { type: 'object' } },
34
+ min: { control: { type: 'number' } },
35
+ max: { control: { type: 'number' } },
36
+ railColor: { control: { type: 'color' } },
37
+ showTooltip: { control: { type: 'boolean' } },
38
+ step: { control: { type: 'number' } },
39
+ trackColor: { control: { type: 'color' } },
40
+ withInputField: { control: { type: 'boolean' } },
41
+ },
22
42
  parameters: {
23
- knobs: { disable: false },
43
+ docs: { source: { state: 'open' } },
24
44
  },
25
45
  };
26
46
 
27
47
  const RangeControlWithState = ( props ) => {
28
- const initialValue = props.value === undefined ? 5 : props.value;
29
- const [ value, setValue ] = useState( initialValue );
48
+ const [ value, setValue ] = useState();
30
49
 
31
50
  return <RangeControl { ...props } value={ value } onChange={ setValue } />;
32
51
  };
33
52
 
34
- const DefaultExample = () => {
35
- const [ value, setValue ] = useState( undefined );
36
-
37
- const showBeforeIcon = boolean( 'beforeIcon', false );
38
- const showAfterIcon = boolean( 'afterIcon', false );
39
-
40
- const props = {
41
- afterIcon: showAfterIcon ? wordpress : undefined,
42
- allowReset: boolean( 'allowReset', false ),
43
- beforeIcon: showBeforeIcon ? wordpress : undefined,
44
- color: text( 'color', COLORS.ui.theme ),
45
- disabled: boolean( 'disabled', false ),
46
- help: text( 'help', '' ),
47
- label: text( 'label', 'Range Label' ),
48
- marks: boolean( 'marks', false ),
49
- max: number( 'max', 100 ),
50
- min: number( 'min', 0 ),
51
- showTooltip: boolean( 'showTooltip', false ),
52
- step: text( 'step', 1 ),
53
- railColor: text( 'railColor', null ),
54
- trackColor: text( 'trackColor', null ),
55
- withInputField: boolean( 'withInputField', true ),
56
- value,
57
- onChange: setValue,
58
- };
59
-
60
- return (
61
- <Wrapper>
62
- <RangeControl { ...props } />
63
- </Wrapper>
64
- );
65
- };
66
-
67
- const RangeControlLabeledByMarksType = ( props ) => {
68
- const label = Array.isArray( props.marks ) ? 'Custom' : 'Automatic';
69
- return <RangeControl { ...{ ...props, label } } />;
53
+ export const Default = RangeControlWithState.bind( {} );
54
+ Default.args = {
55
+ label: 'Range label',
70
56
  };
71
57
 
72
- export const _default = () => {
73
- return <DefaultExample />;
58
+ /**
59
+ * The `initialPosition` prop sets the starting position of the slider when no `value` is provided.
60
+ */
61
+ export const InitialValueZero = RangeControlWithState.bind( {} );
62
+ InitialValueZero.args = {
63
+ ...Default.args,
64
+ initialPosition: 0,
65
+ max: 20,
74
66
  };
75
67
 
76
- export const InitialValueZero = () => {
77
- const label = text( 'Label', 'How many columns should this use?' );
68
+ /**
69
+ * Setting the `step` prop to `"any"` will allow users to select non-integer values.
70
+ * This also overrides both `withInputField` and `showTooltip` props to `false`.
71
+ */
72
+ export const WithAnyStep = ( props ) => {
73
+ const [ value, setValue ] = useState( 1.2345 );
78
74
 
79
75
  return (
80
- <RangeControlWithState
81
- initialPosition={ 0 }
82
- label={ label }
83
- max={ 20 }
84
- min={ 0 }
85
- value={ null }
86
- />
76
+ <>
77
+ <RangeControl value={ value } onChange={ setValue } { ...props } />
78
+ <p>Current value: { value }</p>
79
+ </>
87
80
  );
88
81
  };
89
-
90
- export const withAnyStep = () => {
91
- return <RangeControlWithState label="Brightness" step="any" />;
82
+ WithAnyStep.args = {
83
+ label: 'Brightness',
84
+ step: 'any',
92
85
  };
93
86
 
94
- export const withHelp = () => {
95
- const label = text( 'Label', 'How many columns should this use?' );
96
- const help = text(
97
- 'Help Text',
98
- 'Please select the number of columns you would like this to contain.'
99
- );
100
-
101
- return <RangeControlWithState label={ label } help={ help } />;
87
+ export const WithHelp = RangeControlWithState.bind( {} );
88
+ WithHelp.args = {
89
+ ...Default.args,
90
+ label: 'How many columns should this use?',
91
+ help: 'Please select the number of columns you would like this to contain.',
102
92
  };
103
93
 
104
- export const withMinimumAndMaximumLimits = () => {
105
- const label = text( 'Label', 'How many columns should this use?' );
106
- const min = number( 'Min Value', 2 );
107
- const max = number( 'Max Value', 10 );
108
-
109
- return <RangeControlWithState label={ label } min={ min } max={ max } />;
94
+ /**
95
+ * Set `min` and `max` values to constrain the range of allowed values.
96
+ */
97
+ export const WithMinimumAndMaximumLimits = RangeControlWithState.bind( {} );
98
+ WithMinimumAndMaximumLimits.args = {
99
+ ...Default.args,
100
+ min: 2,
101
+ max: 10,
110
102
  };
111
103
 
112
- export const withIconBefore = () => {
113
- const label = text( 'Label', 'How many columns should this use?' );
114
- const showIcon = boolean( 'icon', true );
115
-
116
- return (
117
- <RangeControlWithState
118
- label={ label }
119
- beforeIcon={ showIcon ? wordpress : undefined }
120
- />
121
- );
104
+ export const WithIconBefore = RangeControlWithState.bind( {} );
105
+ WithIconBefore.args = {
106
+ ...Default.args,
107
+ beforeIcon: wordpress,
122
108
  };
123
109
 
124
- export const withIconAfter = () => {
125
- const label = text( 'Label', 'How many columns should this use?' );
126
- const showIcon = boolean( 'icon', true );
127
-
128
- return (
129
- <RangeControlWithState
130
- label={ label }
131
- afterIcon={ showIcon ? wordpress : undefined }
132
- />
133
- );
110
+ export const WithIconAfter = RangeControlWithState.bind( {} );
111
+ WithIconAfter.args = {
112
+ ...Default.args,
113
+ afterIcon: wordpress,
134
114
  };
135
115
 
136
- export const withReset = () => {
137
- const label = text( 'Label', 'How many columns should this use?' );
138
-
139
- return <RangeControlWithState label={ label } allowReset />;
116
+ export const WithReset = RangeControlWithState.bind( {} );
117
+ WithReset.args = {
118
+ ...Default.args,
119
+ allowReset: true,
140
120
  };
141
121
 
142
- export const marks = () => {
122
+ /**
123
+ * Use `marks` to render a visual representation of `step` ticks. Custom mark indicators can be provided by an `Array`.
124
+ */
125
+ export const WithMarks = ( props ) => {
143
126
  const marksBase = [
144
127
  { value: 0, label: '0' },
145
128
  { value: 1, label: '1' },
@@ -164,11 +147,15 @@ export const marks = () => {
164
147
  const minNegative = { min: -10, max: 10, step: 1 };
165
148
  const rangeNegative = { min: -10, max: -1, step: 1 };
166
149
 
167
- // Use a short alias to keep formatting to fewer lines.
168
- const Range = RangeControlLabeledByMarksType;
150
+ const Range = ( localProps ) => {
151
+ const label = Array.isArray( localProps.marks )
152
+ ? 'Custom'
153
+ : 'Automatic';
154
+ return <RangeControl { ...{ ...localProps, ...props, label } } />;
155
+ };
169
156
 
170
157
  return (
171
- <Wrapper>
158
+ <>
172
159
  <h2>Integer Step</h2>
173
160
  <Range marks { ...stepInteger } />
174
161
  <Range marks={ marksBase } { ...stepInteger } />
@@ -188,21 +175,6 @@ export const marks = () => {
188
175
  <h2>Any Step</h2>
189
176
  <Range marks { ...{ ...stepInteger, step: 'any' } } />
190
177
  <Range marks={ marksBase } { ...{ ...stepInteger, step: 'any' } } />
191
- </Wrapper>
178
+ </>
192
179
  );
193
180
  };
194
-
195
- export const multiple = () => {
196
- return (
197
- <Wrapper>
198
- <RangeControlWithState />
199
- <RangeControlWithState />
200
- <RangeControlWithState />
201
- <RangeControlWithState />
202
- </Wrapper>
203
- );
204
- };
205
-
206
- const Wrapper = styled.div`
207
- padding: 60px 40px;
208
- `;
@@ -48,5 +48,6 @@ export const LabelText = styled( Text )`
48
48
  display: block;
49
49
  font-size: 13px;
50
50
  line-height: 1.4;
51
+ white-space: nowrap;
51
52
  }
52
53
  `;
@@ -122,21 +122,6 @@ exports[`ToggleGroupControl should render correctly 1`] = `
122
122
  .emotion-11 {
123
123
  font-size: 13px;
124
124
  line-height: 1;
125
- position: absolute;
126
- top: 50%;
127
- left: 50%;
128
- -webkit-transform: translate( -50%, -50% );
129
- -moz-transform: translate( -50%, -50% );
130
- -ms-transform: translate( -50%, -50% );
131
- transform: translate( -50%, -50% );
132
- }
133
-
134
- .emotion-13 {
135
- font-size: 13px;
136
- font-weight: bold;
137
- height: 0;
138
- overflow: hidden;
139
- visibility: hidden;
140
125
  }
141
126
 
142
127
  <div
@@ -180,12 +165,6 @@ exports[`ToggleGroupControl should render correctly 1`] = `
180
165
  >
181
166
  R
182
167
  </div>
183
- <div
184
- aria-hidden="true"
185
- class="emotion-13 emotion-14"
186
- >
187
- R
188
- </div>
189
168
  </button>
190
169
  </div>
191
170
  <div
@@ -208,12 +187,6 @@ exports[`ToggleGroupControl should render correctly 1`] = `
208
187
  >
209
188
  J
210
189
  </div>
211
- <div
212
- aria-hidden="true"
213
- class="emotion-13 emotion-14"
214
- >
215
- J
216
- </div>
217
190
  </button>
218
191
  </div>
219
192
  </div>
@@ -24,7 +24,7 @@ import * as styles from './styles';
24
24
  import { useCx } from '../../utils/hooks';
25
25
  import Tooltip from '../../tooltip';
26
26
 
27
- const { ButtonContentView, LabelPlaceholderView, LabelView } = styles;
27
+ const { ButtonContentView, LabelView } = styles;
28
28
 
29
29
  const WithToolTip = ( { showTooltip, text, children }: WithToolTipProps ) => {
30
30
  if ( showTooltip && text ) {
@@ -88,9 +88,6 @@ function ToggleGroupControlOption(
88
88
  value={ value }
89
89
  >
90
90
  <ButtonContentView>{ label }</ButtonContentView>
91
- <LabelPlaceholderView aria-hidden>
92
- { label }
93
- </LabelPlaceholderView>
94
91
  </Radio>
95
92
  </WithToolTip>
96
93
  </LabelView>