@wordpress/components 19.7.0-next.e230fbab09.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 (178) 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/number-control/README.md +14 -0
  159. package/src/number-control/index.js +13 -12
  160. package/src/number-control/stories/index.js +14 -7
  161. package/src/number-control/test/index.js +79 -1
  162. package/src/range-control/stories/index.js +91 -119
  163. package/src/resizable-box/resize-tooltip/styles/resize-tooltip.styles.js +1 -0
  164. package/src/toggle-group-control/test/__snapshots__/index.js.snap +0 -27
  165. package/src/toggle-group-control/toggle-group-control-option/component.tsx +1 -4
  166. package/src/toggle-group-control/toggle-group-control-option/styles.ts +0 -12
  167. package/src/toolbar-group/style.scss +0 -73
  168. package/src/tree-grid/README.md +1 -1
  169. package/src/tree-grid/index.js +4 -0
  170. package/src/tree-grid/test/index.js +61 -17
  171. package/src/unit-control/README.md +1 -3
  172. package/src/unit-control/index.tsx +59 -30
  173. package/src/unit-control/stories/index.tsx +170 -0
  174. package/src/unit-control/test/index.js +143 -100
  175. package/src/unit-control/types.ts +60 -41
  176. package/src/unit-control/unit-select-control.tsx +2 -3
  177. package/tsconfig.tsbuildinfo +1 -1
  178. package/src/unit-control/stories/index.js +0 -127
@@ -1,12 +1,12 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import { render, fireEvent, screen } from '@testing-library/react';
4
+ import { render as RTLrender, screen, waitFor } from '@testing-library/react';
5
+ import userEvent from '@testing-library/user-event';
5
6
 
6
7
  /**
7
8
  * WordPress dependencies
8
9
  */
9
- import { UP, DOWN, ENTER, ESCAPE } from '@wordpress/keycodes';
10
10
  import { useState } from '@wordpress/element';
11
11
 
12
12
  /**
@@ -15,6 +15,16 @@ import { useState } from '@wordpress/element';
15
15
  import UnitControl from '../';
16
16
  import { parseQuantityAndUnitFromRawValue } from '../utils';
17
17
 
18
+ function render( jsx ) {
19
+ return {
20
+ user: userEvent.setup( {
21
+ // Avoids timeout errors (https://github.com/testing-library/user-event/issues/565#issuecomment-1064579531).
22
+ delay: null,
23
+ } ),
24
+ ...RTLrender( jsx ),
25
+ };
26
+ }
27
+
18
28
  const getComponent = () =>
19
29
  document.body.querySelector( '.components-unit-control' );
20
30
  const getInput = () =>
@@ -24,9 +34,6 @@ const getSelect = () =>
24
34
  const getUnitLabel = () =>
25
35
  document.body.querySelector( '.components-unit-control__unit-label' );
26
36
 
27
- const fireKeyDown = ( data ) =>
28
- fireEvent.keyDown( document.activeElement || document.body, data );
29
-
30
37
  const ControlledSyncUnits = () => {
31
38
  const [ state, setState ] = useState( { valueA: '', valueB: '' } );
32
39
 
@@ -93,7 +100,7 @@ describe( 'UnitControl', () => {
93
100
  } );
94
101
 
95
102
  it( 'should not render select, if units are disabled', () => {
96
- render( <UnitControl unit="em" units={ [] } /> );
103
+ render( <UnitControl value="3em" units={ [] } /> );
97
104
  const input = getInput();
98
105
  const select = getSelect();
99
106
 
@@ -113,73 +120,87 @@ describe( 'UnitControl', () => {
113
120
  } );
114
121
 
115
122
  describe( 'Value', () => {
116
- it( 'should update value on change', () => {
123
+ it( 'should update value on change', async () => {
117
124
  let state = '50px';
118
125
  const setState = jest.fn( ( value ) => ( state = value ) );
119
126
 
120
- render( <UnitControl value={ state } onChange={ setState } /> );
127
+ const { user } = render(
128
+ <UnitControl value={ state } onChange={ setState } />
129
+ );
121
130
 
122
131
  const input = getInput();
123
- input.focus();
124
- fireEvent.change( input, { target: { value: 62 } } );
125
-
126
- expect( setState ).toHaveBeenCalledTimes( 1 );
132
+ await user.clear( input );
133
+ await user.type( input, '62' );
134
+
135
+ // 3 times:
136
+ // - 1: clear
137
+ // - 2: type '6'
138
+ // - 3: type '62'
139
+ expect( setState ).toHaveBeenCalledTimes( 3 );
127
140
  expect( state ).toBe( '62px' );
128
141
  } );
129
142
 
130
- it( 'should increment value on UP press', () => {
143
+ it( 'should increment value on UP press', async () => {
131
144
  let state = '50px';
132
145
  const setState = ( nextState ) => ( state = nextState );
133
146
 
134
- render( <UnitControl value={ state } onChange={ setState } /> );
147
+ const { user } = render(
148
+ <UnitControl value={ state } onChange={ setState } />
149
+ );
135
150
 
136
- getInput().focus();
137
- fireKeyDown( { keyCode: UP } );
151
+ const input = getInput();
152
+ await user.type( input, '{ArrowUp}' );
138
153
 
139
154
  expect( state ).toBe( '51px' );
140
155
  } );
141
156
 
142
- it( 'should increment value on UP + SHIFT press, with step', () => {
157
+ it( 'should increment value on UP + SHIFT press, with step', async () => {
143
158
  let state = '50px';
144
159
  const setState = ( nextState ) => ( state = nextState );
145
160
 
146
- render( <UnitControl value={ state } onChange={ setState } /> );
161
+ const { user } = render(
162
+ <UnitControl value={ state } onChange={ setState } />
163
+ );
147
164
 
148
- getInput().focus();
149
- fireKeyDown( { keyCode: UP, shiftKey: true } );
165
+ const input = getInput();
166
+ await user.type( input, '{Shift>}{ArrowUp}{/Shift}' );
150
167
 
151
168
  expect( state ).toBe( '60px' );
152
169
  } );
153
170
 
154
- it( 'should decrement value on DOWN press', () => {
171
+ it( 'should decrement value on DOWN press', async () => {
155
172
  let state = 50;
156
173
  const setState = ( nextState ) => ( state = nextState );
157
174
 
158
- render( <UnitControl value={ state } onChange={ setState } /> );
175
+ const { user } = render(
176
+ <UnitControl value={ state } onChange={ setState } />
177
+ );
159
178
 
160
- getInput().focus();
161
- fireKeyDown( { keyCode: DOWN } );
179
+ const input = getInput();
180
+ await user.type( input, '{ArrowDown}' );
162
181
 
163
182
  expect( state ).toBe( '49px' );
164
183
  } );
165
184
 
166
- it( 'should decrement value on DOWN + SHIFT press, with step', () => {
185
+ it( 'should decrement value on DOWN + SHIFT press, with step', async () => {
167
186
  let state = 50;
168
187
  const setState = ( nextState ) => ( state = nextState );
169
188
 
170
- render( <UnitControl value={ state } onChange={ setState } /> );
189
+ const { user } = render(
190
+ <UnitControl value={ state } onChange={ setState } />
191
+ );
171
192
 
172
- getInput().focus();
173
- fireKeyDown( { keyCode: DOWN, shiftKey: true } );
193
+ const input = getInput();
194
+ await user.type( input, '{Shift>}{ArrowDown}{/Shift}' );
174
195
 
175
196
  expect( state ).toBe( '40px' );
176
197
  } );
177
198
 
178
- it( 'should cancel change when ESCAPE key is pressed', () => {
199
+ it( 'should cancel change when ESCAPE key is pressed', async () => {
179
200
  let state = 50;
180
201
  const setState = ( nextState ) => ( state = nextState );
181
202
 
182
- render(
203
+ const { user } = render(
183
204
  <UnitControl
184
205
  value={ state }
185
206
  onChange={ setState }
@@ -188,14 +209,13 @@ describe( 'UnitControl', () => {
188
209
  );
189
210
 
190
211
  const input = getInput();
191
- input.focus();
192
-
193
- fireEvent.change( input, { target: { value: '300px' } } );
212
+ await user.clear( input );
213
+ await user.type( input, '300px' );
194
214
 
195
215
  expect( input.value ).toBe( '300px' );
196
216
  expect( state ).toBe( 50 );
197
217
 
198
- fireKeyDown( { keyCode: ESCAPE } );
218
+ user.keyboard( '{Escape}' );
199
219
 
200
220
  expect( input.value ).toBe( '50' );
201
221
  expect( state ).toBe( 50 );
@@ -203,17 +223,25 @@ describe( 'UnitControl', () => {
203
223
  } );
204
224
 
205
225
  describe( 'Unit', () => {
206
- it( 'should update unit value on change', () => {
207
- let state = 'px';
226
+ it( 'should update unit value on change', async () => {
227
+ let state = '14rem';
208
228
  const setState = ( nextState ) => ( state = nextState );
209
229
 
210
- render( <UnitControl unit={ state } onUnitChange={ setState } /> );
230
+ const spy = jest.fn();
231
+
232
+ const { user } = render(
233
+ <UnitControl
234
+ value={ state }
235
+ onChange={ setState }
236
+ onUnitChange={ spy }
237
+ />
238
+ );
211
239
 
212
240
  const select = getSelect();
213
- select.focus();
214
- fireEvent.change( select, { target: { value: 'em' } } );
241
+ await user.selectOptions( select, [ 'px' ] );
215
242
 
216
- expect( state ).toBe( 'em' );
243
+ expect( spy ).toHaveBeenCalledWith( 'px', expect.anything() );
244
+ expect( state ).toBe( '14px' );
217
245
  } );
218
246
 
219
247
  it( 'should render customized units, if defined', () => {
@@ -235,7 +263,7 @@ describe( 'UnitControl', () => {
235
263
  expect( vmax.value ).toBe( 'vmax' );
236
264
  } );
237
265
 
238
- it( 'should reset value on unit change, if unit has default value', () => {
266
+ it( 'should reset value on unit change, if unit has default value', async () => {
239
267
  let state = 50;
240
268
  const setState = ( nextState ) => ( state = nextState );
241
269
 
@@ -244,7 +272,7 @@ describe( 'UnitControl', () => {
244
272
  { value: 'vmax', label: 'vmax', default: 75 },
245
273
  ];
246
274
 
247
- render(
275
+ const { user } = render(
248
276
  <UnitControl
249
277
  isResetValueOnUnitChange
250
278
  units={ units }
@@ -254,18 +282,16 @@ describe( 'UnitControl', () => {
254
282
  );
255
283
 
256
284
  const select = getSelect();
257
- select.focus();
258
-
259
- fireEvent.change( select, { target: { value: 'vmax' } } );
285
+ await user.selectOptions( select, [ 'vmax' ] );
260
286
 
261
287
  expect( state ).toBe( '75vmax' );
262
288
 
263
- fireEvent.change( select, { target: { value: 'pt' } } );
289
+ await user.selectOptions( select, [ 'pt' ] );
264
290
 
265
291
  expect( state ).toBe( '25pt' );
266
292
  } );
267
293
 
268
- it( 'should not reset value on unit change, if disabled', () => {
294
+ it( 'should not reset value on unit change, if disabled', async () => {
269
295
  let state = 50;
270
296
  const setState = ( nextState ) => ( state = nextState );
271
297
 
@@ -274,7 +300,7 @@ describe( 'UnitControl', () => {
274
300
  { value: 'vmax', label: 'vmax', default: 75 },
275
301
  ];
276
302
 
277
- render(
303
+ const { user } = render(
278
304
  <UnitControl
279
305
  isResetValueOnUnitChange={ false }
280
306
  value={ state }
@@ -284,69 +310,88 @@ describe( 'UnitControl', () => {
284
310
  );
285
311
 
286
312
  const select = getSelect();
287
- select.focus();
288
-
289
- fireEvent.change( select, { target: { value: 'vmax' } } );
313
+ await user.selectOptions( select, [ 'vmax' ] );
290
314
 
291
315
  expect( state ).toBe( '50vmax' );
292
316
 
293
- fireEvent.change( select, { target: { value: 'pt' } } );
317
+ await user.selectOptions( select, [ 'pt' ] );
294
318
 
295
319
  expect( state ).toBe( '50pt' );
296
320
  } );
297
321
 
298
- it( 'should set correct unit if single units', () => {
322
+ it( 'should set correct unit if single units', async () => {
299
323
  let state = '50%';
300
324
  const setState = ( value ) => ( state = value );
301
325
 
302
- render(
326
+ const { user } = render(
303
327
  <UnitControl
304
328
  value={ state }
305
- unit="%"
306
329
  units={ [ { value: '%', label: '%' } ] }
307
330
  onChange={ setState }
308
331
  />
309
332
  );
310
333
 
311
334
  const input = getInput();
312
- input.focus();
313
- fireEvent.change( input, { target: { value: 62 } } );
335
+ await user.clear( input );
336
+ await user.type( input, '62' );
314
337
 
315
- expect( state ).toBe( '62%' );
338
+ await waitFor( () => expect( state ).toBe( '62%' ) );
316
339
  } );
317
340
 
318
- it( 'should update unit value when a new raw value is passed', () => {
319
- render( <ControlledSyncUnits /> );
341
+ it( 'should update unit value when a new raw value is passed', async () => {
342
+ const { user } = render( <ControlledSyncUnits /> );
320
343
 
321
344
  const [ inputA, inputB ] = screen.getAllByRole( 'spinbutton' );
322
345
  const [ selectA, selectB ] = screen.getAllByRole( 'combobox' );
323
346
 
324
- inputA.focus();
325
- fireEvent.change( inputA, { target: { value: '55' } } );
347
+ const [ remOptionA ] = screen.getAllByRole( 'option', {
348
+ name: 'rem',
349
+ } );
350
+ const [ , vwOptionB ] = screen.getAllByRole( 'option', {
351
+ name: 'vw',
352
+ } );
353
+
354
+ await user.type( inputA, '55' );
326
355
 
327
- inputB.focus();
328
- fireEvent.change( inputB, { target: { value: '14' } } );
356
+ await user.type( inputB, '14' );
329
357
 
330
- selectA.focus();
331
- fireEvent.change( selectA, { target: { value: 'rem' } } );
358
+ await user.selectOptions( selectA, remOptionA );
332
359
 
360
+ await waitFor( () => expect( selectB ).toHaveValue( 'rem' ) );
333
361
  expect( selectA ).toHaveValue( 'rem' );
334
- expect( selectB ).toHaveValue( 'rem' );
335
362
 
336
- selectB.focus();
337
- fireEvent.change( selectB, { target: { value: 'vw' } } );
363
+ await user.selectOptions( selectB, vwOptionB );
338
364
 
339
- expect( selectA ).toHaveValue( 'vw' );
365
+ await waitFor( () => expect( selectA ).toHaveValue( 'vw' ) );
340
366
  expect( selectB ).toHaveValue( 'vw' );
341
367
  } );
368
+
369
+ it( 'should maintain the chosen non-default unit when value is cleared', async () => {
370
+ const units = [
371
+ { value: 'pt', label: 'pt' },
372
+ { value: 'vmax', label: 'vmax' },
373
+ ];
374
+
375
+ const { user } = render(
376
+ <UnitControl units={ units } value="5" />
377
+ );
378
+
379
+ const select = getSelect();
380
+ await user.selectOptions( select, [ 'vmax' ] );
381
+
382
+ const input = getInput();
383
+ await user.clear( input );
384
+
385
+ expect( select ).toHaveValue( 'vmax' );
386
+ } );
342
387
  } );
343
388
 
344
389
  describe( 'Unit Parser', () => {
345
390
  let state = '10px';
346
391
  const setState = jest.fn( ( nextState ) => ( state = nextState ) );
347
392
 
348
- it( 'should parse unit from input', () => {
349
- render(
393
+ it( 'should parse unit from input', async () => {
394
+ const { user } = render(
350
395
  <UnitControl
351
396
  value={ state }
352
397
  onChange={ setState }
@@ -355,15 +400,15 @@ describe( 'UnitControl', () => {
355
400
  );
356
401
 
357
402
  const input = getInput();
358
- input.focus();
359
- fireEvent.change( input, { target: { value: '55 em' } } );
360
- fireKeyDown( { keyCode: ENTER } );
403
+ await user.clear( input );
404
+ await user.type( input, '55 em' );
405
+ user.keyboard( '{Enter}' );
361
406
 
362
407
  expect( state ).toBe( '55em' );
363
408
  } );
364
409
 
365
- it( 'should parse PX unit from input', () => {
366
- render(
410
+ it( 'should parse PX unit from input', async () => {
411
+ const { user } = render(
367
412
  <UnitControl
368
413
  value={ state }
369
414
  onChange={ setState }
@@ -372,15 +417,15 @@ describe( 'UnitControl', () => {
372
417
  );
373
418
 
374
419
  const input = getInput();
375
- input.focus();
376
- fireEvent.change( input, { target: { value: '61 PX' } } );
377
- fireKeyDown( { keyCode: ENTER } );
420
+ await user.clear( input );
421
+ await user.type( input, '61 PX' );
422
+ user.keyboard( '{Enter}' );
378
423
 
379
424
  expect( state ).toBe( '61px' );
380
425
  } );
381
426
 
382
- it( 'should parse EM unit from input', () => {
383
- render(
427
+ it( 'should parse EM unit from input', async () => {
428
+ const { user } = render(
384
429
  <UnitControl
385
430
  value={ state }
386
431
  onChange={ setState }
@@ -389,15 +434,15 @@ describe( 'UnitControl', () => {
389
434
  );
390
435
 
391
436
  const input = getInput();
392
- input.focus();
393
- fireEvent.change( input, { target: { value: '55 em' } } );
394
- fireKeyDown( { keyCode: ENTER } );
437
+ await user.clear( input );
438
+ await user.type( input, '55 em' );
439
+ user.keyboard( '{Enter}' );
395
440
 
396
441
  expect( state ).toBe( '55em' );
397
442
  } );
398
443
 
399
- it( 'should parse % unit from input', () => {
400
- render(
444
+ it( 'should parse % unit from input', async () => {
445
+ const { user } = render(
401
446
  <UnitControl
402
447
  value={ state }
403
448
  onChange={ setState }
@@ -406,15 +451,15 @@ describe( 'UnitControl', () => {
406
451
  );
407
452
 
408
453
  const input = getInput();
409
- input.focus();
410
- fireEvent.change( input, { target: { value: '-10 %' } } );
411
- fireKeyDown( { keyCode: ENTER } );
454
+ await user.clear( input );
455
+ await user.type( input, '-10 %' );
456
+ user.keyboard( '{Enter}' );
412
457
 
413
458
  expect( state ).toBe( '-10%' );
414
459
  } );
415
460
 
416
- it( 'should parse REM unit from input', () => {
417
- render(
461
+ it( 'should parse REM unit from input', async () => {
462
+ const { user } = render(
418
463
  <UnitControl
419
464
  value={ state }
420
465
  onChange={ setState }
@@ -423,25 +468,23 @@ describe( 'UnitControl', () => {
423
468
  );
424
469
 
425
470
  const input = getInput();
426
- input.focus();
427
- fireEvent.change( input, {
428
- target: { value: '123 rEm ' },
429
- } );
430
- fireKeyDown( { keyCode: ENTER } );
471
+ await user.clear( input );
472
+ await user.type( input, '123 rEm ' );
473
+ user.keyboard( '{Enter}' );
431
474
 
432
475
  expect( state ).toBe( '123rem' );
433
476
  } );
434
477
 
435
- it( 'should update unit after initial render and with new unit prop', () => {
478
+ it( 'should update unit after initial render and with new unit prop', async () => {
436
479
  const { rerender } = render( <UnitControl value={ '10%' } /> );
437
480
 
438
481
  const select = getSelect();
439
482
 
440
483
  expect( select.value ).toBe( '%' );
441
484
 
442
- rerender( <UnitControl value={ '20' } unit="em" /> );
485
+ rerender( <UnitControl value={ '20vh' } /> );
443
486
 
444
- expect( select.value ).toBe( 'em' );
487
+ await waitFor( () => expect( select.value ).toBe( 'vh' ) );
445
488
  } );
446
489
 
447
490
  it( 'should fallback to default unit if parsed unit is invalid', () => {
@@ -9,6 +9,7 @@ import type { CSSProperties, SyntheticEvent } from 'react';
9
9
  import type { StateReducer } from '../input-control/reducer/state';
10
10
  import type {
11
11
  InputChangeCallback,
12
+ InputControlProps,
12
13
  Size as InputSize,
13
14
  } from '../input-control/types';
14
15
 
@@ -51,8 +52,6 @@ export type UnitSelectControlProps = {
51
52
  isUnitSelectTabbable?: boolean;
52
53
  /**
53
54
  * A callback function invoked when the value is changed.
54
- *
55
- * @default noop
56
55
  */
57
56
  onChange?: UnitControlOnChangeCallback;
58
57
  /**
@@ -74,42 +73,62 @@ export type UnitSelectControlProps = {
74
73
  };
75
74
 
76
75
  // TODO: when available, should (partially) extend `NumberControl` props.
77
- export type UnitControlProps = UnitSelectControlProps & {
78
- __unstableStateReducer?: StateReducer;
79
- __unstableInputWidth?: CSSProperties[ 'width' ];
80
- /**
81
- * If `true`, the unit `<select>` is hidden.
82
- *
83
- * @default false
84
- */
85
- disableUnits?: boolean;
86
- /**
87
- * If `true`, the `ENTER` key press is required in order to trigger an `onChange`.
88
- * If enabled, a change is also triggered when tabbing away (`onBlur`).
89
- *
90
- * @default false
91
- */
92
- isPressEnterToChange?: boolean;
93
- /**
94
- * If `true`, and the selected unit provides a `default` value, this value is set
95
- * when changing units.
96
- *
97
- * @default false
98
- */
99
- isResetValueOnUnitChange?: boolean;
100
- /**
101
- * If this property is added, a label will be generated using label property as the content.
102
- */
103
- label?: string;
104
- /**
105
- * Callback when the `unit` changes.
106
- *
107
- * @default noop
108
- */
109
- onUnitChange?: UnitControlOnChangeCallback;
110
- /**
111
- * Current value. If passed as a string, the current unit will be inferred from this value.
112
- * For example, a `value` of "50%" will set the current unit to `%`.
113
- */
114
- value?: string | number;
115
- };
76
+ export type UnitControlProps = Omit< UnitSelectControlProps, 'unit' > &
77
+ Pick< InputControlProps, 'hideLabelFromVision' > & {
78
+ __unstableStateReducer?: StateReducer;
79
+ __unstableInputWidth?: CSSProperties[ 'width' ];
80
+ /**
81
+ * If `true`, the unit `<select>` is hidden.
82
+ *
83
+ * @default false
84
+ */
85
+ disableUnits?: boolean;
86
+ /**
87
+ * If `true`, the `ENTER` key press is required in order to trigger an `onChange`.
88
+ * If enabled, a change is also triggered when tabbing away (`onBlur`).
89
+ *
90
+ * @default false
91
+ */
92
+ isPressEnterToChange?: boolean;
93
+ /**
94
+ * If `true`, and the selected unit provides a `default` value, this value is set
95
+ * when changing units.
96
+ *
97
+ * @default false
98
+ */
99
+ isResetValueOnUnitChange?: boolean;
100
+ /**
101
+ * If this property is added, a label will be generated using label property as the content.
102
+ */
103
+ label?: string;
104
+ /**
105
+ * Callback when the `unit` changes.
106
+ */
107
+ onUnitChange?: UnitControlOnChangeCallback;
108
+ /**
109
+ * Current unit. _Note: this prop is deprecated. Instead, provide a unit with a value through the `value` prop._
110
+ *
111
+ * @deprecated
112
+ */
113
+ unit?: string;
114
+ /**
115
+ * Current value. If passed as a string, the current unit will be inferred from this value.
116
+ * For example, a `value` of "50%" will set the current unit to `%`.
117
+ */
118
+ value?: string | number;
119
+ /**
120
+ * If true, pressing `UP` or `DOWN` along with the `SHIFT` key will increment
121
+ * the value by the `shiftStep` value.
122
+ *
123
+ * @default true
124
+ */
125
+ isShiftStepEnabled?: boolean;
126
+ /**
127
+ * Amount to increment by when the `SHIFT` key is held down. This shift value
128
+ * is a multiplier to the `step` value. For example, if the `step` value is `5`,
129
+ * and `shiftStep` is `10`, each jump would increment/decrement by `50`.
130
+ *
131
+ * @default 10
132
+ */
133
+ shiftStep?: number;
134
+ };
@@ -1,7 +1,6 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import { noop } from 'lodash';
5
4
  import classnames from 'classnames';
6
5
  import type { ChangeEvent } from 'react';
7
6
 
@@ -16,7 +15,7 @@ import type { UnitSelectControlProps } from './types';
16
15
  export default function UnitSelectControl( {
17
16
  className,
18
17
  isUnitSelectTabbable: isTabbable = true,
19
- onChange = noop,
18
+ onChange,
20
19
  size = 'default',
21
20
  unit = 'px',
22
21
  units = CSS_UNITS,
@@ -37,7 +36,7 @@ export default function UnitSelectControl( {
37
36
  const { value: unitValue } = event.target;
38
37
  const data = units.find( ( option ) => option.value === unitValue );
39
38
 
40
- onChange( unitValue, { event, data } );
39
+ onChange?.( unitValue, { event, data } );
41
40
  };
42
41
 
43
42
  const classes = classnames( 'components-unit-control__select', className );