From bab61da5d4a2934f6295c5677077ec88b5a0ad76 Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Fri, 11 Feb 2022 18:56:43 +0100 Subject: [PATCH 01/26] Rename index and styles --- packages/components/src/number-control/{index.js => index.tsx} | 0 .../styles/{number-control-styles.js => number-control-styles.ts} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename packages/components/src/number-control/{index.js => index.tsx} (100%) rename packages/components/src/number-control/styles/{number-control-styles.js => number-control-styles.ts} (100%) diff --git a/packages/components/src/number-control/index.js b/packages/components/src/number-control/index.tsx similarity index 100% rename from packages/components/src/number-control/index.js rename to packages/components/src/number-control/index.tsx diff --git a/packages/components/src/number-control/styles/number-control-styles.js b/packages/components/src/number-control/styles/number-control-styles.ts similarity index 100% rename from packages/components/src/number-control/styles/number-control-styles.js rename to packages/components/src/number-control/styles/number-control-styles.ts From 7f500849197529a031747dbcfb3c9ea2bcf181da Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Fri, 11 Feb 2022 18:58:58 +0100 Subject: [PATCH 02/26] Add prop types --- .../components/src/number-control/types.ts | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 packages/components/src/number-control/types.ts diff --git a/packages/components/src/number-control/types.ts b/packages/components/src/number-control/types.ts new file mode 100644 index 00000000000000..0ed85f0048ac77 --- /dev/null +++ b/packages/components/src/number-control/types.ts @@ -0,0 +1,28 @@ +/** + * Internal dependencies + */ +import type { InputControlProps } from '../input-control/types'; + +export type Props = InputControlProps & { + /** + * If `true`, the default `input` HTML arrows will be hidden. + * + * @default false + */ + hideHTMLArrows?: boolean; + /** + * If `true`, pressing `UP` or `DOWN` along with the `SHIFT` key will + * increment the value by the `shiftStep` value. + * + * @default true + */ + isShiftStepEnabled?: boolean; + /** + * Amount to increment by when the `SHIFT` key is held down. This value is a + * multiplier to the `step` value. For example, if the `step` value is `5`, + * and `shiftStep` is `10`, each jump would increment/decrement by `50`. + * + * @default 10 + */ + shiftStep?: number; +}; From bb7befb40be4b9645fbbf31c626af2f62ca3fd79 Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Fri, 11 Feb 2022 18:59:24 +0100 Subject: [PATCH 03/26] Fix styles --- .../src/number-control/styles/number-control-styles.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/components/src/number-control/styles/number-control-styles.ts b/packages/components/src/number-control/styles/number-control-styles.ts index a27784497b018d..bddddae4c66942 100644 --- a/packages/components/src/number-control/styles/number-control-styles.ts +++ b/packages/components/src/number-control/styles/number-control-styles.ts @@ -1,17 +1,21 @@ -// @ts-nocheck /** * External dependencies */ import { css } from '@emotion/react'; import styled from '@emotion/styled'; + /** * Internal dependencies */ import InputControl from '../../input-control'; +import type { Props } from '../types'; -const htmlArrowStyles = ( { hideHTMLArrows } ) => { +const htmlArrowStyles = ( { + hideHTMLArrows, +}: Pick< Props, 'hideHTMLArrows' > ) => { if ( ! hideHTMLArrows ) return ``; + // TODO: rewrite using Emotion selection from `InputControl` component return css` input[type='number']::-webkit-outer-spin-button, input[type='number']::-webkit-inner-spin-button { From 1072a51d94fd759ac9aab2c79bf7f50e14d20a88 Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Fri, 11 Feb 2022 19:03:05 +0100 Subject: [PATCH 04/26] Type component signature --- packages/components/src/number-control/index.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/components/src/number-control/index.tsx b/packages/components/src/number-control/index.tsx index 00ea6756a1ebab..33115838935744 100644 --- a/packages/components/src/number-control/index.tsx +++ b/packages/components/src/number-control/index.tsx @@ -1,8 +1,8 @@ -// @ts-nocheck /** * External dependencies */ import classNames from 'classnames'; +import type { Ref } from 'react'; /** * WordPress dependencies @@ -18,6 +18,7 @@ import * as inputControlActionTypes from '../input-control/reducer/actions'; import { composeStateReducers } from '../input-control/reducer/reducer'; import { add, subtract, roundClamp } from '../utils/math'; import { isValueEmpty } from '../utils/values'; +import type { Props } from './types'; export function NumberControl( { @@ -36,8 +37,8 @@ export function NumberControl( type: typeProp = 'number', value: valueProp, ...props - }, - ref + }: Props, + ref: Ref< any > ) { const isStepAny = step === 'any'; const baseStep = isStepAny ? 1 : parseFloat( step ); From ee9e3850dc30208ac37d3d46db4c2e74b64b42b6 Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Fri, 11 Feb 2022 19:07:35 +0100 Subject: [PATCH 05/26] Ensure `min`, `max` amd `step` are converted to numbers for internal calculations --- .../components/src/number-control/index.tsx | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/packages/components/src/number-control/index.tsx b/packages/components/src/number-control/index.tsx index 33115838935744..3add71e6531ba5 100644 --- a/packages/components/src/number-control/index.tsx +++ b/packages/components/src/number-control/index.tsx @@ -20,6 +20,10 @@ import { add, subtract, roundClamp } from '../utils/math'; import { isValueEmpty } from '../utils/values'; import type { Props } from './types'; +// TODO: is there a "safer" version? Should we strip white space, etc? +const ensureNumber = ( n: string | number ) => + typeof n === 'string' ? parseFloat( n ) : n; + export function NumberControl( { __unstableStateReducer: stateReducer = ( state ) => state, @@ -29,19 +33,22 @@ export function NumberControl( isDragEnabled = true, isShiftStepEnabled = true, label, - max = Infinity, - min = -Infinity, + max: maxProp = Infinity, + min: minProp = -Infinity, required = false, shiftStep = 10, - step = 1, + step: stepProp = 1, type: typeProp = 'number', value: valueProp, ...props }: Props, ref: Ref< any > ) { - const isStepAny = step === 'any'; - const baseStep = isStepAny ? 1 : parseFloat( step ); + const min = ensureNumber( minProp ); + const max = ensureNumber( maxProp ); + + const isStepAny = stepProp === 'any'; + const baseStep = isStepAny ? 1 : ensureNumber( stepProp ); const baseValue = roundClamp( 0, min, max, baseStep ); const constrainValue = ( value, stepOverride ) => { // When step is "any" clamp the value, otherwise round and clamp it @@ -178,7 +185,7 @@ export function NumberControl( min={ min } ref={ ref } required={ required } - step={ step } + step={ stepProp } type={ typeProp } value={ valueProp } __unstableStateReducer={ composeStateReducers( From 91cb750e46b58119e9a83d21b9dcd5e717e8558b Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Fri, 11 Feb 2022 19:09:09 +0100 Subject: [PATCH 06/26] Remove unnecessary `parseFloat`, since `shiftStep` is a `number` --- packages/components/src/number-control/index.tsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/components/src/number-control/index.tsx b/packages/components/src/number-control/index.tsx index 3add71e6531ba5..4742c444c57c27 100644 --- a/packages/components/src/number-control/index.tsx +++ b/packages/components/src/number-control/index.tsx @@ -84,7 +84,7 @@ export function NumberControl( const enableShift = event.shiftKey && isShiftStepEnabled; const incrementalValue = enableShift - ? parseFloat( shiftStep ) * baseStep + ? shiftStep * baseStep : baseStep; let nextValue = isValueEmpty( currentValue ) ? baseValue @@ -114,9 +114,7 @@ export function NumberControl( if ( type === inputControlActionTypes.DRAG && isDragEnabled ) { const [ x, y ] = payload.delta; const enableShift = payload.shiftKey && isShiftStepEnabled; - const modifier = enableShift - ? parseFloat( shiftStep ) * baseStep - : baseStep; + const modifier = enableShift ? shiftStep * baseStep : baseStep; let directionModifier; let delta; From 126bdc7081a87956312aaa95f3a190c3711ca614 Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Fri, 11 Feb 2022 19:11:07 +0100 Subject: [PATCH 07/26] Type `numberControlStateReducer` using the `Props` type --- .../components/src/number-control/index.tsx | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/packages/components/src/number-control/index.tsx b/packages/components/src/number-control/index.tsx index 4742c444c57c27..338a02954b6e68 100644 --- a/packages/components/src/number-control/index.tsx +++ b/packages/components/src/number-control/index.tsx @@ -60,16 +60,13 @@ export function NumberControl( const autoComplete = typeProp === 'number' ? 'off' : null; const classes = classNames( 'components-number-control', className ); - /** - * "Middleware" function that intercepts updates from InputControl. - * This allows us to tap into actions to transform the (next) state for - * InputControl. - * - * @param {Object} state State from InputControl - * @param {Object} action Action triggering state change - * @return {Object} The updated state to apply to InputControl - */ - const numberControlStateReducer = ( state, action ) => { + // "Middleware" function that intercepts updates from InputControl. + // This allows us to tap into actions to transform the (next) state for + // `InputControl`. + const numberControlStateReducer: Props[ '__unstableStateReducer' ] = ( + state, + action + ) => { const { type, payload } = action; const event = payload?.event; const currentValue = state.value; From 44b503f21d12a2c08650b8913c801d101ae2893e Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Fri, 11 Feb 2022 19:13:47 +0100 Subject: [PATCH 08/26] Type `contrainValue` --- packages/components/src/number-control/index.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/components/src/number-control/index.tsx b/packages/components/src/number-control/index.tsx index 338a02954b6e68..bf2c0c15697431 100644 --- a/packages/components/src/number-control/index.tsx +++ b/packages/components/src/number-control/index.tsx @@ -50,14 +50,14 @@ export function NumberControl( const isStepAny = stepProp === 'any'; const baseStep = isStepAny ? 1 : ensureNumber( stepProp ); const baseValue = roundClamp( 0, min, max, baseStep ); - const constrainValue = ( value, stepOverride ) => { + const constrainValue = ( value: number, stepOverride?: number ) => { // When step is "any" clamp the value, otherwise round and clamp it return isStepAny ? Math.min( max, Math.max( min, value ) ) : roundClamp( value, min, max, stepOverride ?? baseStep ); }; - const autoComplete = typeProp === 'number' ? 'off' : null; + const autoComplete = typeProp === 'number' ? 'off' : undefined; const classes = classNames( 'components-number-control', className ); // "Middleware" function that intercepts updates from InputControl. @@ -101,7 +101,7 @@ export function NumberControl( state.value = constrainValue( nextValue, - enableShift ? incrementalValue : null + enableShift ? incrementalValue : undefined ); } @@ -144,7 +144,7 @@ export function NumberControl( state.value = constrainValue( add( currentValue, distance ), - enableShift ? modifier : null + enableShift ? modifier : undefined ); } } From b56da693b907d1712e22b96831be1a29aa68aa31 Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Fri, 11 Feb 2022 19:16:56 +0100 Subject: [PATCH 09/26] Default to `0` if `currentValue` is `undefined`, convert to number --- packages/components/src/number-control/index.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/components/src/number-control/index.tsx b/packages/components/src/number-control/index.tsx index bf2c0c15697431..41abedcfdf2770 100644 --- a/packages/components/src/number-control/index.tsx +++ b/packages/components/src/number-control/index.tsx @@ -85,7 +85,7 @@ export function NumberControl( : baseStep; let nextValue = isValueEmpty( currentValue ) ? baseValue - : currentValue; + : ensureNumber( ( currentValue as unknown ) as string ); if ( event?.preventDefault ) { event.preventDefault(); @@ -143,7 +143,7 @@ export function NumberControl( const distance = delta * modifier * directionModifier; state.value = constrainValue( - add( currentValue, distance ), + add( currentValue ?? 0, distance ), enableShift ? modifier : undefined ); } @@ -160,7 +160,7 @@ export function NumberControl( state.value = applyEmptyValue ? currentValue - : constrainValue( currentValue ); + : constrainValue( ensureNumber( currentValue ?? 0 ) ); } return state; From f6a2df03629ebade659c27721c4d0d1d74cdb5db Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Fri, 11 Feb 2022 19:19:24 +0100 Subject: [PATCH 10/26] Commit and forward `value` as a `string` --- packages/components/src/number-control/index.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/components/src/number-control/index.tsx b/packages/components/src/number-control/index.tsx index 41abedcfdf2770..9d7d88195aaa15 100644 --- a/packages/components/src/number-control/index.tsx +++ b/packages/components/src/number-control/index.tsx @@ -99,10 +99,10 @@ export function NumberControl( nextValue = subtract( nextValue, incrementalValue ); } - state.value = constrainValue( + state.value = `${ constrainValue( nextValue, enableShift ? incrementalValue : undefined - ); + ) }`; } /** @@ -142,10 +142,10 @@ export function NumberControl( delta = Math.ceil( Math.abs( delta ) ) * Math.sign( delta ); const distance = delta * modifier * directionModifier; - state.value = constrainValue( + state.value = `${ constrainValue( add( currentValue ?? 0, distance ), enableShift ? modifier : undefined - ); + ) }`; } } @@ -160,7 +160,7 @@ export function NumberControl( state.value = applyEmptyValue ? currentValue - : constrainValue( ensureNumber( currentValue ?? 0 ) ); + : `${ constrainValue( ensureNumber( currentValue ?? 0 ) ) }`; } return state; @@ -182,7 +182,7 @@ export function NumberControl( required={ required } step={ stepProp } type={ typeProp } - value={ valueProp } + value={ `${ valueProp }` } __unstableStateReducer={ composeStateReducers( numberControlStateReducer, stateReducer From 800b8be2d1397599b3374cbc5490fe4f63991103 Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Fri, 11 Feb 2022 19:22:00 +0100 Subject: [PATCH 11/26] Cast even to `KeyboardEvent` when reacting to key up/down events --- packages/components/src/number-control/index.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/components/src/number-control/index.tsx b/packages/components/src/number-control/index.tsx index 9d7d88195aaa15..caf05f75449cea 100644 --- a/packages/components/src/number-control/index.tsx +++ b/packages/components/src/number-control/index.tsx @@ -78,7 +78,9 @@ export function NumberControl( type === inputControlActionTypes.PRESS_UP || type === inputControlActionTypes.PRESS_DOWN ) { - const enableShift = event.shiftKey && isShiftStepEnabled; + const enableShift = + ( event as KeyboardEvent | undefined )?.shiftKey && + isShiftStepEnabled; const incrementalValue = enableShift ? shiftStep * baseStep From 0167076e7f3e73e303bfd7763cf88de50eeea711 Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Fri, 11 Feb 2022 19:28:57 +0100 Subject: [PATCH 12/26] WIP README --- .../components/src/number-control/README.md | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/packages/components/src/number-control/README.md b/packages/components/src/number-control/README.md index 2e57f69fbc36c4..af47c30c0a4055 100644 --- a/packages/components/src/number-control/README.md +++ b/packages/components/src/number-control/README.md @@ -27,18 +27,19 @@ const Example = () => { ## Props +TODO: Should point at `InputControl` for overlapping props + ### dragDirection Determines the drag axis to increment/decrement the value. -Directions: `n` | `e` | `s` | `w` -- Type: `String` +- Type: `n` | `e` | `s` | `w` - Required: No - Default: `n` ### dragThreshold -If `isDragEnabled` is true, this controls the amount of `px` to have been dragged before the value changes. +If `isDragEnabled` is `true`, this controls the amount of `px` to have been dragged before the value changes. - Type: `Number` - Required: No @@ -46,39 +47,40 @@ If `isDragEnabled` is true, this controls the amount of `px` to have been dragge ### hideHTMLArrows -If true, the default `input` HTML arrows will be hidden. +If `true`, the default `input` HTML arrows will be hidden. -- Type: `Boolean` +- Type: `boolean` - Required: No - Default: `false` ### isDragEnabled -If true, enables mouse drag gesture to increment/decrement the number value. Holding `SHIFT` while dragging will increase the value by the `shiftStep`. +If `true`, enables mouse drag gesture to increment/decrement the value. Holding `SHIFT` while dragging will increase the value by the `shiftStep`. -- Type: `Boolean` +- Type: `boolean` - Required: No +- Default: `true` ### isShiftStepEnabled -If true, pressing `UP` or `DOWN` along with the `SHIFT` key will increment the value by the `shiftStep` value. +If `true`, pressing `UP` or `DOWN` along with the `SHIFT` key will increment the value by the `shiftStep` value. -- Type: `Boolean` +- Type: `boolean` - Required: No - Default: `true` ### label -If this property is added, a label will be generated using label property as the content. +The text content of the label. If not specified, a label won't be displayed. -- Type: `String` +- Type: `string` // It's actually a React.Node - Required: No ### labelPosition -The position of the label (`top`, `side`, `bottom`, or `edge`). +The position of the label. -- Type: `String` +- Type: `top` | `side` | `bottom` | `edge` - Required: No ### max From b47c76967bce9465be97737b47e0018a78fa35b7 Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Fri, 11 Feb 2022 19:31:35 +0100 Subject: [PATCH 13/26] Ignore remaining TS errors --- packages/components/src/color-picker/input-with-slider.tsx | 2 ++ packages/components/src/number-control/index.tsx | 2 ++ packages/components/src/unit-control/index.tsx | 1 + 3 files changed, 5 insertions(+) diff --git a/packages/components/src/color-picker/input-with-slider.tsx b/packages/components/src/color-picker/input-with-slider.tsx index fb45238ec5016d..351fe0b798c4e9 100644 --- a/packages/components/src/color-picker/input-with-slider.tsx +++ b/packages/components/src/color-picker/input-with-slider.tsx @@ -32,7 +32,9 @@ export const InputWithSlider = ( { max={ max } label={ label } hideLabelFromVision + // @ts-ignore value={ value } + // @ts-ignore onChange={ onChange } prefix={ Date: Wed, 16 Feb 2022 17:42:27 +0100 Subject: [PATCH 14/26] ShiftStep also as a string --- packages/components/src/number-control/index.tsx | 3 ++- packages/components/src/number-control/types.ts | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/components/src/number-control/index.tsx b/packages/components/src/number-control/index.tsx index c65b7ce1ea9522..2cdcb1a214bd57 100644 --- a/packages/components/src/number-control/index.tsx +++ b/packages/components/src/number-control/index.tsx @@ -36,7 +36,7 @@ export function NumberControl( max: maxProp = Infinity, min: minProp = -Infinity, required = false, - shiftStep = 10, + shiftStep: shiftStepProp = 10, step: stepProp = 1, type: typeProp = 'number', value: valueProp, @@ -46,6 +46,7 @@ export function NumberControl( ) { const min = ensureNumber( minProp ); const max = ensureNumber( maxProp ); + const shiftStep = ensureNumber( shiftStepProp ); const isStepAny = stepProp === 'any'; const baseStep = isStepAny ? 1 : ensureNumber( stepProp ); diff --git a/packages/components/src/number-control/types.ts b/packages/components/src/number-control/types.ts index 0ed85f0048ac77..57fda50bdf8c86 100644 --- a/packages/components/src/number-control/types.ts +++ b/packages/components/src/number-control/types.ts @@ -24,5 +24,5 @@ export type Props = InputControlProps & { * * @default 10 */ - shiftStep?: number; + shiftStep?: string | number; }; From 8f20af53a0af2917d852211931adc07565317fd2 Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Wed, 16 Feb 2022 17:46:42 +0100 Subject: [PATCH 15/26] Add `ensureString` utility function --- .../components/src/number-control/index.tsx | 33 +++++++++++++------ 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/packages/components/src/number-control/index.tsx b/packages/components/src/number-control/index.tsx index 2cdcb1a214bd57..f210f8b8f1e2cd 100644 --- a/packages/components/src/number-control/index.tsx +++ b/packages/components/src/number-control/index.tsx @@ -24,6 +24,9 @@ import type { Props } from './types'; const ensureNumber = ( n: string | number ) => typeof n === 'string' ? parseFloat( n ) : n; +const ensureString = ( s: string | number ) => + typeof s === 'string' ? s : `${ s }`; + export function NumberControl( { __unstableStateReducer: stateReducer = ( state ) => state, @@ -102,10 +105,12 @@ export function NumberControl( nextValue = subtract( nextValue, incrementalValue ); } - state.value = `${ constrainValue( - nextValue, - enableShift ? incrementalValue : undefined - ) }`; + state.value = ensureString( + constrainValue( + nextValue, + enableShift ? incrementalValue : undefined + ) + ); } /** @@ -147,10 +152,12 @@ export function NumberControl( delta = Math.ceil( Math.abs( delta ) ) * Math.sign( delta ); const distance = delta * modifier * directionModifier; - state.value = `${ constrainValue( - add( currentValue ?? 0, distance ), - enableShift ? modifier : undefined - ) }`; + state.value = ensureString( + constrainValue( + add( currentValue ?? 0, distance ), + enableShift ? modifier : undefined + ) + ); } } @@ -165,7 +172,9 @@ export function NumberControl( state.value = applyEmptyValue ? currentValue - : `${ constrainValue( ensureNumber( currentValue ?? 0 ) ) }`; + : ensureString( + constrainValue( ensureNumber( currentValue ?? 0 ) ) + ); } return state; @@ -187,7 +196,11 @@ export function NumberControl( required={ required } step={ stepProp } type={ typeProp } - value={ `${ valueProp }` } + value={ + typeof valueProp !== 'undefined' + ? ensureString( valueProp ) + : undefined + } __unstableStateReducer={ composeStateReducers( numberControlStateReducer, stateReducer From 62a3e270305972dde9fe940457f5ee019b58694e Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Wed, 16 Feb 2022 18:52:12 +0100 Subject: [PATCH 16/26] Add `onDrag`, `onDragStart` and `onDragEnd` props from `InputControl` to `UnitControl` --- packages/components/src/unit-control/types.ts | 80 ++++++++++--------- 1 file changed, 41 insertions(+), 39 deletions(-) diff --git a/packages/components/src/unit-control/types.ts b/packages/components/src/unit-control/types.ts index 0cbebf4dd2ce03..1adc8cbd1de738 100644 --- a/packages/components/src/unit-control/types.ts +++ b/packages/components/src/unit-control/types.ts @@ -10,6 +10,7 @@ import type { StateReducer } from '../input-control/reducer/state'; import type { InputChangeCallback, Size as InputSize, + InputFieldProps, } from '../input-control/types'; export type Value = number | string; @@ -77,42 +78,43 @@ export type UnitSelectControlProps = { units?: WPUnitControlUnitList; }; -export type UnitControlProps = UnitSelectControlProps & { - __unstableStateReducer?: StateReducer; - __unstableInputWidth?: CSSProperties[ 'width' ]; - /** - * If `true`, the unit `` is hidden. + * + * @default false + */ + disableUnits?: boolean; + /** + * If `true`, the `ENTER` key press is required in order to trigger an `onChange`. + * If enabled, a change is also triggered when tabbing away (`onBlur`). + * + * @default false + */ + isPressEnterToChange?: boolean; + /** + * If `true`, and the selected unit provides a `default` value, this value is set + * when changing units. + * + * @default false + */ + isResetValueOnUnitChange?: boolean; + /** + * If this property is added, a label will be generated using label property as the content. + */ + label?: string; + /** + * Callback when the `unit` changes. + * + * @default noop + */ + onUnitChange?: UnitControlOnChangeCallback; + /** + * Current value. If passed as a string, the current unit will be inferred from this value. + * For example, a `value` of "50%" will set the current unit to `%`. + */ + value: Value; + }; From ace5d44ddc91758c0b538c5e1c7615aab9e95f8f Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Wed, 16 Feb 2022 18:52:56 +0100 Subject: [PATCH 17/26] Force `nextValue` to be alway a string in the `UnitControl` onChange callback --- packages/components/src/unit-control/index.tsx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/components/src/unit-control/index.tsx b/packages/components/src/unit-control/index.tsx index 9d346dd95bf9eb..e44af4750be789 100644 --- a/packages/components/src/unit-control/index.tsx +++ b/packages/components/src/unit-control/index.tsx @@ -209,7 +209,14 @@ function UnitControl( label={ label } onBlur={ handleOnBlur } onKeyDown={ handleOnKeyDown } - onChange={ handleOnChange } + onChange={ ( nextValue, extra ) => { + let v; + + if ( typeof v !== 'undefined' ) { + v = `${ nextValue }`; + } + handleOnChange?.( v, extra ); + } } ref={ forwardedRef } size={ size } suffix={ inputSuffix } From bd7491f64005007eb7e87c27996f01d576d17e3e Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Wed, 16 Feb 2022 19:00:08 +0100 Subject: [PATCH 18/26] Tweak `value` and `onChange` so that they can accept also `number` inputs --- .../components/src/number-control/index.tsx | 10 ++++++++++ .../components/src/number-control/types.ts | 18 +++++++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/packages/components/src/number-control/index.tsx b/packages/components/src/number-control/index.tsx index f210f8b8f1e2cd..b7433520088953 100644 --- a/packages/components/src/number-control/index.tsx +++ b/packages/components/src/number-control/index.tsx @@ -43,6 +43,7 @@ export function NumberControl( step: stepProp = 1, type: typeProp = 'number', value: valueProp, + onChange: onChangeProp, ...props }: Props, ref: Ref< any > @@ -205,6 +206,15 @@ export function NumberControl( numberControlStateReducer, stateReducer ) } + onChange={ ( nextValue, extra ) => { + let v; + + if ( typeof nextValue !== 'undefined' ) { + v = ensureNumber( nextValue ); + } + + onChangeProp?.( v, extra ); + } } /> ); } diff --git a/packages/components/src/number-control/types.ts b/packages/components/src/number-control/types.ts index 57fda50bdf8c86..952f175d1d9273 100644 --- a/packages/components/src/number-control/types.ts +++ b/packages/components/src/number-control/types.ts @@ -1,9 +1,19 @@ +/** + * External dependencies + */ +import type { ChangeEvent } from 'react'; + /** * Internal dependencies */ import type { InputControlProps } from '../input-control/types'; -export type Props = InputControlProps & { +export type InputChangeCallback< + E = ChangeEvent< HTMLInputElement >, + P = {} +> = ( nextValue: number | undefined, extra: { event: E } & P ) => void; + +export type Props = Omit< InputControlProps, 'value' | 'onChange' > & { /** * If `true`, the default `input` HTML arrows will be hidden. * @@ -25,4 +35,10 @@ export type Props = InputControlProps & { * @default 10 */ shiftStep?: string | number; + + // Override `InputControl`'s `value` and `onChange` props: + // - `value` can also be a `number` (instead of only a `string`) + // - `onChange` passes the `nextValue` as a `number` (instead of a `string`) + value?: string | number; + onChange?: InputChangeCallback; }; From 7d282d7aaab70ccba94fe8d179a958d035c9bf1e Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Wed, 16 Feb 2022 19:00:46 +0100 Subject: [PATCH 19/26] Update `InputControl` README to reflect that `value` can only be a `string` --- packages/components/src/input-control/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/src/input-control/README.md b/packages/components/src/input-control/README.md index 63a0c509010144..e1c4fa13521cb2 100644 --- a/packages/components/src/input-control/README.md +++ b/packages/components/src/input-control/README.md @@ -105,5 +105,5 @@ Type of the input element to render. Defaults to "text". The current value of the input. -- Type: `String | Number` +- Type: `String` - Required: Yes From 486b099b8dbdb690657f9e4a1078827e5f13ac4c Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Wed, 16 Feb 2022 19:11:55 +0100 Subject: [PATCH 20/26] Fix `ColorPicker` s TS errors --- .../components/src/color-picker/input-with-slider.tsx | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/components/src/color-picker/input-with-slider.tsx b/packages/components/src/color-picker/input-with-slider.tsx index 351fe0b798c4e9..9c8575fc68fb1d 100644 --- a/packages/components/src/color-picker/input-with-slider.tsx +++ b/packages/components/src/color-picker/input-with-slider.tsx @@ -32,10 +32,14 @@ export const InputWithSlider = ( { max={ max } label={ label } hideLabelFromVision - // @ts-ignore value={ value } - // @ts-ignore - onChange={ onChange } + onChange={ ( nextValue?: number ) => { + if ( typeof nextValue === 'undefined' ) { + return; + } + + onChange?.( nextValue ); + } } prefix={ Date: Wed, 16 Feb 2022 20:08:50 +0100 Subject: [PATCH 21/26] Tweak Storybook values --- packages/components/src/number-control/stories/index.js | 6 +++--- packages/components/src/unit-control/stories/index.js | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/components/src/number-control/stories/index.js b/packages/components/src/number-control/stories/index.js index 25106b0c364b83..20501be38b41f3 100644 --- a/packages/components/src/number-control/stories/index.js +++ b/packages/components/src/number-control/stories/index.js @@ -22,7 +22,7 @@ export default { }; function Example() { - const [ value, setValue ] = useState( '0' ); + const [ value, setValue ] = useState( 0 ); const props = { disabled: boolean( 'disabled', false ), @@ -32,10 +32,10 @@ function Example() { label: text( 'label', 'Number' ), min: number( 'min', 0 ), max: number( 'max', 100 ), - placeholder: text( 'placeholder', 0 ), + placeholder: text( 'placeholder', '0' ), required: boolean( 'required', false ), shiftStep: number( 'shiftStep', 10 ), - step: text( 'step', 1 ), + step: text( 'step', '1' ), }; return ( diff --git a/packages/components/src/unit-control/stories/index.js b/packages/components/src/unit-control/stories/index.js index 9603a05e3941a1..58d81a110f829a 100644 --- a/packages/components/src/unit-control/stories/index.js +++ b/packages/components/src/unit-control/stories/index.js @@ -49,7 +49,7 @@ function Example() { }, 'default' ), - step: number( 'step', 1 ), + step: text( 'step', '1' ), units: object( 'units', CSS_UNITS ), }; From 367c59d151856f6e8931a7fd94a3d0547ec29ea9 Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Fri, 18 Feb 2022 15:20:04 +0100 Subject: [PATCH 22/26] `NumberControl` s value as a `string` --- .../src/color-picker/input-with-slider.tsx | 15 +++++++++++--- .../components/src/number-control/index.tsx | 20 +++---------------- .../components/src/number-control/types.ts | 18 +---------------- .../components/src/unit-control/index.tsx | 15 +++++--------- packages/components/src/utils/values.js | 2 +- 5 files changed, 22 insertions(+), 48 deletions(-) diff --git a/packages/components/src/color-picker/input-with-slider.tsx b/packages/components/src/color-picker/input-with-slider.tsx index 9c8575fc68fb1d..b78826a15bf2da 100644 --- a/packages/components/src/color-picker/input-with-slider.tsx +++ b/packages/components/src/color-picker/input-with-slider.tsx @@ -17,6 +17,15 @@ interface InputWithSliderProps { onChange: ( value: number ) => void; } +// TODO: +// - look for edge cases, make more robust +// - move to shared util +const ensureNumber = ( n: string | number ) => + typeof n === 'string' ? parseFloat( n ) : n; + +const ensureString = ( s: string | number ) => + typeof s === 'string' ? s : `${ s }`; + export const InputWithSlider = ( { min, max, @@ -32,13 +41,13 @@ export const InputWithSlider = ( { max={ max } label={ label } hideLabelFromVision - value={ value } - onChange={ ( nextValue?: number ) => { + value={ ensureString( value ) } + onChange={ ( nextValue?: string ) => { if ( typeof nextValue === 'undefined' ) { return; } - onChange?.( nextValue ); + onChange?.( ensureNumber( nextValue ) ); } } prefix={ @@ -92,7 +91,7 @@ export function NumberControl( : baseStep; let nextValue = isValueEmpty( currentValue ) ? baseValue - : ensureNumber( ( currentValue as unknown ) as string ); + : ensureNumber( currentValue ); if ( event?.preventDefault ) { event.preventDefault(); @@ -155,7 +154,7 @@ export function NumberControl( state.value = ensureString( constrainValue( - add( currentValue ?? 0, distance ), + add( ensureNumber( currentValue ?? 0 ), distance ), enableShift ? modifier : undefined ) ); @@ -197,24 +196,11 @@ export function NumberControl( required={ required } step={ stepProp } type={ typeProp } - value={ - typeof valueProp !== 'undefined' - ? ensureString( valueProp ) - : undefined - } + value={ valueProp } __unstableStateReducer={ composeStateReducers( numberControlStateReducer, stateReducer ) } - onChange={ ( nextValue, extra ) => { - let v; - - if ( typeof nextValue !== 'undefined' ) { - v = ensureNumber( nextValue ); - } - - onChangeProp?.( v, extra ); - } } /> ); } diff --git a/packages/components/src/number-control/types.ts b/packages/components/src/number-control/types.ts index 952f175d1d9273..57fda50bdf8c86 100644 --- a/packages/components/src/number-control/types.ts +++ b/packages/components/src/number-control/types.ts @@ -1,19 +1,9 @@ -/** - * External dependencies - */ -import type { ChangeEvent } from 'react'; - /** * Internal dependencies */ import type { InputControlProps } from '../input-control/types'; -export type InputChangeCallback< - E = ChangeEvent< HTMLInputElement >, - P = {} -> = ( nextValue: number | undefined, extra: { event: E } & P ) => void; - -export type Props = Omit< InputControlProps, 'value' | 'onChange' > & { +export type Props = InputControlProps & { /** * If `true`, the default `input` HTML arrows will be hidden. * @@ -35,10 +25,4 @@ export type Props = Omit< InputControlProps, 'value' | 'onChange' > & { * @default 10 */ shiftStep?: string | number; - - // Override `InputControl`'s `value` and `onChange` props: - // - `value` can also be a `number` (instead of only a `string`) - // - `onChange` passes the `nextValue` as a `number` (instead of a `string`) - value?: string | number; - onChange?: InputChangeCallback; }; diff --git a/packages/components/src/unit-control/index.tsx b/packages/components/src/unit-control/index.tsx index e44af4750be789..a2f0fb9f3f5e0b 100644 --- a/packages/components/src/unit-control/index.tsx +++ b/packages/components/src/unit-control/index.tsx @@ -35,6 +35,9 @@ import { useControlledState } from '../utils/hooks'; import type { UnitControlProps, UnitControlOnChangeCallback } from './types'; import type { StateReducer } from '../input-control/reducer/state'; +const ensureString = ( s: string | number ) => + typeof s === 'string' ? s : `${ s }`; + function UnitControl( { __unstableStateReducer: stateReducer = ( state ) => state, @@ -209,19 +212,11 @@ function UnitControl( label={ label } onBlur={ handleOnBlur } onKeyDown={ handleOnKeyDown } - onChange={ ( nextValue, extra ) => { - let v; - - if ( typeof v !== 'undefined' ) { - v = `${ nextValue }`; - } - handleOnChange?.( v, extra ); - } } + onChange={ handleOnChange } ref={ forwardedRef } size={ size } suffix={ inputSuffix } - // @ts-ignore - value={ value } + value={ ensureString( value ) } step={ step } __unstableStateReducer={ composeStateReducers( unitControlStateReducer, diff --git a/packages/components/src/utils/values.js b/packages/components/src/utils/values.js index 8a3c73bb05add1..dcb55b744bb35f 100644 --- a/packages/components/src/utils/values.js +++ b/packages/components/src/utils/values.js @@ -19,7 +19,7 @@ export function isValueDefined( value ) { * @template T * * @param {T | "" | null | undefined} value The value to check. - * @return {value is T} Whether value is empty. + * @return {value is "" | null | undefined} Whether value is empty. */ export function isValueEmpty( value ) { const isEmptyString = value === ''; From a9fa8a1b5ed3e06b70af92aa91113f1d6d3346c9 Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Fri, 18 Feb 2022 15:30:49 +0100 Subject: [PATCH 23/26] Fix story --- packages/components/src/number-control/stories/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/src/number-control/stories/index.js b/packages/components/src/number-control/stories/index.js index 20501be38b41f3..e6826db503a8be 100644 --- a/packages/components/src/number-control/stories/index.js +++ b/packages/components/src/number-control/stories/index.js @@ -22,7 +22,7 @@ export default { }; function Example() { - const [ value, setValue ] = useState( 0 ); + const [ value, setValue ] = useState( '0' ); const props = { disabled: boolean( 'disabled', false ), From 8ecd990e2d91e1df999201679e65682fb199e00c Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Fri, 18 Feb 2022 15:53:07 +0100 Subject: [PATCH 24/26] Type reducer s DRAG action --- packages/components/src/number-control/index.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/components/src/number-control/index.tsx b/packages/components/src/number-control/index.tsx index 8343fdbe6b793e..cb0dbc37df3ed8 100644 --- a/packages/components/src/number-control/index.tsx +++ b/packages/components/src/number-control/index.tsx @@ -19,6 +19,7 @@ import { composeStateReducers } from '../input-control/reducer/reducer'; import { add, subtract, roundClamp } from '../utils/math'; import { isValueEmpty } from '../utils/values'; import type { Props } from './types'; +import type { DragAction } from '../input-control/reducer/actions'; // TODO: is there a "safer" version? Should we strip white space, etc? const ensureNumber = ( n: string | number ) => @@ -117,10 +118,9 @@ export function NumberControl( * Handles drag to update events */ if ( type === inputControlActionTypes.DRAG && isDragEnabled ) { - // @ts-ignore - const [ x, y ] = payload.delta; - // @ts-ignore - const enableShift = payload.shiftKey && isShiftStepEnabled; + const { payload: dragPayload } = action as DragAction; + const [ x, y ] = dragPayload.delta; + const enableShift = dragPayload.shiftKey && isShiftStepEnabled; const modifier = enableShift ? shiftStep * baseStep : baseStep; let directionModifier; From 0f9fc2d1db7f07cd36c2e246d2211a836c60dad3 Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Fri, 18 Feb 2022 17:45:41 +0100 Subject: [PATCH 25/26] Refactor common number/string utils --- .../src/color-picker/input-with-slider.tsx | 10 +---- .../components/src/number-control/index.tsx | 9 +--- .../components/src/unit-control/index.tsx | 4 +- packages/components/src/utils/values.js | 44 +++++++++++++++++++ 4 files changed, 47 insertions(+), 20 deletions(-) diff --git a/packages/components/src/color-picker/input-with-slider.tsx b/packages/components/src/color-picker/input-with-slider.tsx index b78826a15bf2da..a61552af888bd1 100644 --- a/packages/components/src/color-picker/input-with-slider.tsx +++ b/packages/components/src/color-picker/input-with-slider.tsx @@ -7,6 +7,7 @@ import { Spacer } from '../spacer'; import { space } from '../ui/utils/space'; import { RangeControl, NumberControlWrapper } from './styles'; import { COLORS } from '../utils/colors-values'; +import { ensureNumber, ensureString } from '../utils/values'; interface InputWithSliderProps { min: number; @@ -17,15 +18,6 @@ interface InputWithSliderProps { onChange: ( value: number ) => void; } -// TODO: -// - look for edge cases, make more robust -// - move to shared util -const ensureNumber = ( n: string | number ) => - typeof n === 'string' ? parseFloat( n ) : n; - -const ensureString = ( s: string | number ) => - typeof s === 'string' ? s : `${ s }`; - export const InputWithSlider = ( { min, max, diff --git a/packages/components/src/number-control/index.tsx b/packages/components/src/number-control/index.tsx index cb0dbc37df3ed8..ec065b22ba7eed 100644 --- a/packages/components/src/number-control/index.tsx +++ b/packages/components/src/number-control/index.tsx @@ -17,17 +17,10 @@ import { Input } from './styles/number-control-styles'; import * as inputControlActionTypes from '../input-control/reducer/actions'; import { composeStateReducers } from '../input-control/reducer/reducer'; import { add, subtract, roundClamp } from '../utils/math'; -import { isValueEmpty } from '../utils/values'; +import { isValueEmpty, ensureNumber, ensureString } from '../utils/values'; import type { Props } from './types'; import type { DragAction } from '../input-control/reducer/actions'; -// TODO: is there a "safer" version? Should we strip white space, etc? -const ensureNumber = ( n: string | number ) => - typeof n === 'string' ? parseFloat( n ) : n; - -const ensureString = ( s: string | number ) => - typeof s === 'string' ? s : `${ s }`; - export function NumberControl( { __unstableStateReducer: stateReducer = ( state ) => state, diff --git a/packages/components/src/unit-control/index.tsx b/packages/components/src/unit-control/index.tsx index a2f0fb9f3f5e0b..12e072ab5283bc 100644 --- a/packages/components/src/unit-control/index.tsx +++ b/packages/components/src/unit-control/index.tsx @@ -32,12 +32,10 @@ import { getValidParsedUnit, } from './utils'; import { useControlledState } from '../utils/hooks'; +import { ensureString } from '../utils/values'; import type { UnitControlProps, UnitControlOnChangeCallback } from './types'; import type { StateReducer } from '../input-control/reducer/state'; -const ensureString = ( s: string | number ) => - typeof s === 'string' ? s : `${ s }`; - function UnitControl( { __unstableStateReducer: stateReducer = ( state ) => state, diff --git a/packages/components/src/utils/values.js b/packages/components/src/utils/values.js index dcb55b744bb35f..1354a693d926c8 100644 --- a/packages/components/src/utils/values.js +++ b/packages/components/src/utils/values.js @@ -100,3 +100,47 @@ export function isValueNumeric( value, locale = window.navigator.language ) { : value; return ! isNaN( parseFloat( valueToCheck ) ) && isFinite( valueToCheck ); } + +/** + * Converts a string to a number. + * + * @param {string} value + * @return {number} String as a number. + */ +export const stringToNumber = ( value ) => { + return parseFloat( value ); +}; + +/** + * Converts a number to a string. + * + * @param {number} value + * @return {string} Number as a string. + */ +export const numberToString = ( value ) => { + return `${ value }`; +}; + +/** + * Regardless of the input being a string or a number, returns a number. + * + * Returns `undefined` in case the string is `undefined` or not a valid numeric value. + * + * @param {string | number} value + * @return {number} The parsed number. + */ +export const ensureNumber = ( value ) => { + return typeof value === 'string' ? stringToNumber( value ) : value; +}; + +/** + * Regardless of the input being a string or a number, returns a number. + * + * Returns `undefined` in case the string is `undefined` or not a valid numeric value. + * + * @param {string | number} value + * @return {string} The converted string, or `undefined` in case the input is `undefined` or `NaN`. + */ +export const ensureString = ( value ) => { + return typeof value === 'string' ? value : numberToString( value ); +}; From d507a8f756b51ae950c0f9b4885629b85bc4b122 Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Fri, 18 Feb 2022 17:50:11 +0100 Subject: [PATCH 26/26] Update styles to assume `value` is a `string` --- .../src/number-control/test/index.js | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/packages/components/src/number-control/test/index.js b/packages/components/src/number-control/test/index.js index db51a66681c670..55e5c659b6351f 100644 --- a/packages/components/src/number-control/test/index.js +++ b/packages/components/src/number-control/test/index.js @@ -54,7 +54,7 @@ describe( 'NumberControl', () => { const spy = jest.fn(); render( - spy( v ) } /> + spy( v ) } /> ); const input = getInput(); @@ -67,7 +67,7 @@ describe( 'NumberControl', () => { describe( 'Validation', () => { it( 'should clamp value within range on ENTER keypress', () => { - render( ); + render( ); const input = getInput(); input.focus(); @@ -83,7 +83,7 @@ describe( 'NumberControl', () => { } ); it( 'should parse to number value on ENTER keypress when required', () => { - render( ); + render( ); const input = getInput(); input.focus(); @@ -94,7 +94,7 @@ describe( 'NumberControl', () => { } ); it( 'should parse to empty string on ENTER keypress when not required', () => { - render( ); + render( ); const input = getInput(); input.focus(); @@ -105,7 +105,7 @@ describe( 'NumberControl', () => { } ); it( 'should accept empty string on ENTER keypress for optional field', () => { - render( ); + render( ); const input = getInput(); input.focus(); @@ -116,7 +116,7 @@ describe( 'NumberControl', () => { } ); it( 'should not enforce numerical value for empty string when required is omitted', () => { - render( ); + render( ); const input = getInput(); input.focus(); @@ -127,7 +127,7 @@ describe( 'NumberControl', () => { } ); it( 'should enforce numerical value for empty string when required', () => { - render( ); + render( ); const input = getInput(); input.focus(); @@ -142,7 +142,7 @@ describe( 'NumberControl', () => { it( 'should fire onKeyDown callback', () => { const spy = jest.fn(); - render( ); + render( ); getInput().focus(); fireKeyDown( { keyCode: UP } ); @@ -151,7 +151,7 @@ describe( 'NumberControl', () => { } ); it( 'should increment by step on key UP press', () => { - render( ); + render( ); const input = getInput(); input.focus(); @@ -161,7 +161,7 @@ describe( 'NumberControl', () => { } ); it( 'should increment from a negative value', () => { - render( ); + render( ); const input = getInput(); input.focus(); @@ -171,7 +171,7 @@ describe( 'NumberControl', () => { } ); it( 'should increment while preserving the decimal value when `step` is “any”', () => { - render( ); + render( ); const input = getInput(); input.focus(); @@ -181,7 +181,7 @@ describe( 'NumberControl', () => { } ); it( 'should increment by shiftStep on key UP + shift press', () => { - render( ); + render( ); const input = getInput(); input.focus(); @@ -191,7 +191,7 @@ describe( 'NumberControl', () => { } ); it( 'should increment by shiftStep while preserving the decimal value when `step` is “any”', () => { - render( ); + render( ); const input = getInput(); input.focus(); @@ -201,7 +201,7 @@ describe( 'NumberControl', () => { } ); it( 'should increment by custom shiftStep on key UP + shift press', () => { - render( ); + render( ); const input = getInput(); input.focus(); @@ -213,7 +213,7 @@ describe( 'NumberControl', () => { it( 'should increment but be limited by max on shiftStep', () => { render( @@ -229,7 +229,7 @@ describe( 'NumberControl', () => { it( 'should not increment by shiftStep if disabled', () => { render( @@ -246,7 +246,7 @@ describe( 'NumberControl', () => { describe( 'Key DOWN interactions', () => { it( 'should fire onKeyDown callback', () => { const spy = jest.fn(); - render( ); + render( ); getInput().focus(); fireKeyDown( { keyCode: DOWN } ); @@ -255,7 +255,7 @@ describe( 'NumberControl', () => { } ); it( 'should decrement by step on key DOWN press', () => { - render( ); + render( ); const input = getInput(); input.focus(); @@ -265,7 +265,7 @@ describe( 'NumberControl', () => { } ); it( 'should decrement from a negative value', () => { - render( ); + render( ); const input = getInput(); input.focus(); @@ -275,7 +275,7 @@ describe( 'NumberControl', () => { } ); it( 'should decrement while preserving the decimal value when `step` is “any”', () => { - render( ); + render( ); const input = getInput(); input.focus(); @@ -285,7 +285,7 @@ describe( 'NumberControl', () => { } ); it( 'should decrement by shiftStep on key DOWN + shift press', () => { - render( ); + render( ); const input = getInput(); input.focus(); @@ -295,7 +295,7 @@ describe( 'NumberControl', () => { } ); it( 'should decrement by shiftStep while preserving the decimal value when `step` is “any”', () => { - render( ); + render( ); const input = getInput(); input.focus(); @@ -305,7 +305,7 @@ describe( 'NumberControl', () => { } ); it( 'should decrement by custom shiftStep on key DOWN + shift press', () => { - render( ); + render( ); const input = getInput(); input.focus(); @@ -317,7 +317,7 @@ describe( 'NumberControl', () => { it( 'should decrement but be limited by min on shiftStep', () => { render( @@ -333,7 +333,7 @@ describe( 'NumberControl', () => { it( 'should not decrement by shiftStep if disabled', () => { render(