@wordpress/components 30.7.2-next.2f1c7c01b.0 → 30.8.1-next.16d95556a.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.
- package/CHANGELOG.md +13 -1
- package/build/color-picker/component.js +24 -0
- package/build/color-picker/component.js.map +2 -2
- package/build/confirm-dialog/component.js +6 -0
- package/build/confirm-dialog/component.js.map +2 -2
- package/build/custom-select-control/index.js +18 -14
- package/build/custom-select-control/index.js.map +2 -2
- package/build/modal/index.js +1 -0
- package/build/modal/index.js.map +2 -2
- package/build/utils/math.js +2 -2
- package/build/utils/math.js.map +2 -2
- package/build-module/color-picker/component.js +25 -1
- package/build-module/color-picker/component.js.map +2 -2
- package/build-module/confirm-dialog/component.js +6 -0
- package/build-module/confirm-dialog/component.js.map +2 -2
- package/build-module/custom-select-control/index.js +18 -14
- package/build-module/custom-select-control/index.js.map +2 -2
- package/build-module/modal/index.js +1 -0
- package/build-module/modal/index.js.map +2 -2
- package/build-module/utils/math.js +2 -2
- package/build-module/utils/math.js.map +2 -2
- package/build-style/style-rtl.css +3 -3
- package/build-style/style.css +3 -3
- package/build-types/alignment-matrix-control/styles.d.ts.map +1 -1
- package/build-types/angle-picker-control/styles/angle-picker-control-styles.d.ts.map +1 -1
- package/build-types/autocomplete/get-default-use-items.d.ts.map +1 -1
- package/build-types/base-control/styles/base-control-styles.d.ts.map +1 -1
- package/build-types/border-box-control/styles.d.ts.map +1 -1
- package/build-types/border-box-control/utils.d.ts.map +1 -1
- package/build-types/border-control/styles.d.ts.map +1 -1
- package/build-types/box-control/styles/box-control-icon-styles.d.ts.map +1 -1
- package/build-types/box-control/styles/box-control-styles.d.ts.map +1 -1
- package/build-types/calendar/date-calendar/index.d.ts.map +1 -1
- package/build-types/calendar/date-range-calendar/index.d.ts.map +1 -1
- package/build-types/calendar/test/__utils__/index.d.ts.map +1 -1
- package/build-types/calendar/utils/use-localization-props.d.ts.map +1 -1
- package/build-types/card/card/hook.d.ts.map +1 -1
- package/build-types/card/card-body/component.d.ts.map +1 -1
- package/build-types/card/card-body/hook.d.ts.map +1 -1
- package/build-types/card/card-footer/component.d.ts.map +1 -1
- package/build-types/card/card-footer/hook.d.ts.map +1 -1
- package/build-types/card/card-header/component.d.ts.map +1 -1
- package/build-types/card/card-header/hook.d.ts.map +1 -1
- package/build-types/card/card-media/hook.d.ts.map +1 -1
- package/build-types/card/get-padding-by-size.d.ts.map +1 -1
- package/build-types/color-palette/utils.d.ts.map +1 -1
- package/build-types/color-picker/color-copy-button.d.ts.map +1 -1
- package/build-types/color-picker/color-input.d.ts.map +1 -1
- package/build-types/color-picker/component.d.ts.map +1 -1
- package/build-types/color-picker/hex-input.d.ts.map +1 -1
- package/build-types/color-picker/hsl-input.d.ts.map +1 -1
- package/build-types/color-picker/input-with-slider.d.ts.map +1 -1
- package/build-types/color-picker/legacy-adapter.d.ts.map +1 -1
- package/build-types/color-picker/picker.d.ts.map +1 -1
- package/build-types/color-picker/rgb-input.d.ts.map +1 -1
- package/build-types/color-picker/styles.d.ts.map +1 -1
- package/build-types/combobox-control/stories/index.story.d.ts.map +1 -1
- package/build-types/composite/index.d.ts.map +1 -1
- package/build-types/confirm-dialog/component.d.ts.map +1 -1
- package/build-types/confirm-dialog/types.d.ts +6 -0
- package/build-types/confirm-dialog/types.d.ts.map +1 -1
- package/build-types/custom-select-control/index.d.ts.map +1 -1
- package/build-types/custom-select-control-v2/stories/index.story.d.ts.map +1 -1
- package/build-types/custom-select-control-v2/styles.d.ts.map +1 -1
- package/build-types/date-time/date/styles.d.ts.map +1 -1
- package/build-types/date-time/date/use-lilius/index.d.ts.map +1 -1
- package/build-types/date-time/time/styles.d.ts.map +1 -1
- package/build-types/date-time/utils.d.ts.map +1 -1
- package/build-types/dimension-control/sizes.d.ts.map +1 -1
- package/build-types/divider/styles.d.ts.map +1 -1
- package/build-types/dropdown/styles.d.ts.map +1 -1
- package/build-types/focal-point-picker/stories/index.story.d.ts.map +1 -1
- package/build-types/focal-point-picker/styles/focal-point-picker-style.d.ts.map +1 -1
- package/build-types/focal-point-picker/styles/focal-point-style.d.ts.map +1 -1
- package/build-types/font-size-picker/font-size-picker-select.d.ts.map +1 -1
- package/build-types/font-size-picker/font-size-picker-toggle-group.d.ts.map +1 -1
- package/build-types/font-size-picker/styles.d.ts.map +1 -1
- package/build-types/higher-order/with-fallback-styles/index.d.ts.map +1 -1
- package/build-types/higher-order/with-focus-return/index.d.ts.map +1 -1
- package/build-types/input-control/styles/input-control-styles.d.ts.map +1 -1
- package/build-types/item-group/item/hook.d.ts.map +1 -1
- package/build-types/item-group/item-group/hook.d.ts.map +1 -1
- package/build-types/item-group/styles.d.ts.map +1 -1
- package/build-types/menu/index.d.ts.map +1 -1
- package/build-types/menu/styles.d.ts.map +1 -1
- package/build-types/menu-item/index.d.ts.map +1 -1
- package/build-types/menu-item/stories/index.story.d.ts.map +1 -1
- package/build-types/modal/index.d.ts.map +1 -1
- package/build-types/navigation/item/use-navigation-tree-item.d.ts.map +1 -1
- package/build-types/navigation/menu/use-navigation-tree-menu.d.ts.map +1 -1
- package/build-types/navigation/styles/navigation-styles.d.ts.map +1 -1
- package/build-types/navigation/utils.d.ts.map +1 -1
- package/build-types/palette-edit/styles.d.ts.map +1 -1
- package/build-types/popover/test/utils/index.d.ts.map +1 -1
- package/build-types/popover/utils.d.ts.map +1 -1
- package/build-types/progress-bar/styles.d.ts.map +1 -1
- package/build-types/radio-group/radio.d.ts.map +1 -1
- package/build-types/range-control/styles/range-control-styles.d.ts.map +1 -1
- package/build-types/resizable-box/resize-tooltip/styles/resize-tooltip.styles.d.ts.map +1 -1
- package/build-types/resizable-box/stories/index.story.d.ts.map +1 -1
- package/build-types/select-control/stories/index.story.d.ts.map +1 -1
- package/build-types/select-control/styles/select-control-styles.d.ts.map +1 -1
- package/build-types/spinner/styles.d.ts.map +1 -1
- package/build-types/surface/hook.d.ts.map +1 -1
- package/build-types/surface/styles.d.ts.map +1 -1
- package/build-types/tabs/styles.d.ts.map +1 -1
- package/build-types/text-highlight/index.d.ts.map +1 -1
- package/build-types/textarea-control/styles/textarea-control-styles.d.ts.map +1 -1
- package/build-types/theme/styles.d.ts.map +1 -1
- package/build-types/toggle-group-control/toggle-group-control/styles.d.ts.map +1 -1
- package/build-types/toggle-group-control/toggle-group-control-option-base/styles.d.ts.map +1 -1
- package/build-types/toggle-group-control/toggle-group-control-option-icon/component.d.ts.map +1 -1
- package/build-types/toolbar/toolbar-button/toolbar-button-container.d.ts.map +1 -1
- package/build-types/toolbar/toolbar-group/toolbar-group-container.d.ts.map +1 -1
- package/build-types/tools-panel/styles.d.ts.map +1 -1
- package/build-types/tools-panel/tools-panel/hook.d.ts.map +1 -1
- package/build-types/tools-panel/tools-panel-header/hook.d.ts.map +1 -1
- package/build-types/unit-control/styles/unit-control-styles.d.ts.map +1 -1
- package/build-types/unit-control/utils.d.ts.map +1 -1
- package/build-types/utils/get-node-text.d.ts.map +1 -1
- package/build-types/utils/strings.d.ts.map +1 -1
- package/build-types/utils/use-responsive-value.d.ts.map +1 -1
- package/build-types/utils/with-ignore-ime-events.d.ts.map +1 -1
- package/build-types/validated-form-controls/components/combobox-control.d.ts.map +1 -1
- package/build-types/validated-form-controls/components/select-control.d.ts.map +1 -1
- package/build-types/z-stack/styles.d.ts.map +1 -1
- package/package.json +20 -20
- package/src/button/style.scss +3 -3
- package/src/color-picker/component.tsx +52 -3
- package/src/confirm-dialog/component.tsx +6 -0
- package/src/confirm-dialog/test/index.tsx +66 -0
- package/src/confirm-dialog/types.ts +6 -0
- package/src/custom-select-control/index.tsx +23 -22
- package/src/modal/index.tsx +1 -0
- package/src/utils/math.js +2 -2
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* External dependencies
|
|
3
3
|
*/
|
|
4
|
-
import type { ForwardedRef } from 'react';
|
|
4
|
+
import type { ClipboardEvent, ForwardedRef } from 'react';
|
|
5
5
|
import type { Colord } from 'colord';
|
|
6
|
-
import { colord, extend } from 'colord';
|
|
6
|
+
import { colord, extend, getFormat } from 'colord';
|
|
7
7
|
import namesPlugin from 'colord/plugins/names';
|
|
8
8
|
|
|
9
9
|
/**
|
|
@@ -76,8 +76,57 @@ const UnconnectedColorPicker = (
|
|
|
76
76
|
copyFormat || 'hex'
|
|
77
77
|
);
|
|
78
78
|
|
|
79
|
+
/*
|
|
80
|
+
* ! Listener intended for the CAPTURE phase
|
|
81
|
+
*
|
|
82
|
+
* Capture paste events over the entire color picker, looking for clipboard
|
|
83
|
+
* data that could be parsed as a color. If not, let the paste event
|
|
84
|
+
* propagate normally, so that individual input controls within the
|
|
85
|
+
* component have a chance to handle it.
|
|
86
|
+
*/
|
|
87
|
+
const maybeHandlePaste = useCallback(
|
|
88
|
+
( event: ClipboardEvent ) => {
|
|
89
|
+
const pastedText = event.clipboardData?.getData( 'text' )?.trim();
|
|
90
|
+
if ( ! pastedText ) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const parsedColor = colord( pastedText );
|
|
95
|
+
if ( ! parsedColor.isValid() ) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Apply all valid colors, even if the format isn't supported in
|
|
100
|
+
// the UI (e.g. names like "cyan" or, in the future color spaces
|
|
101
|
+
// like "lch" if we add the right colord plugins)
|
|
102
|
+
handleChange( parsedColor );
|
|
103
|
+
|
|
104
|
+
// This redundancy helps TypeScript and is safer than assertions
|
|
105
|
+
const supportedFormats: Record< string, ColorType | undefined > = {
|
|
106
|
+
hex: 'hex',
|
|
107
|
+
rgb: 'rgb',
|
|
108
|
+
hsl: 'hsl',
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const detectedFormat = String( getFormat( pastedText ) );
|
|
112
|
+
const newColorType = supportedFormats[ detectedFormat ];
|
|
113
|
+
if ( newColorType ) {
|
|
114
|
+
setColorType( newColorType );
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Stop at capture phase; no bubbling
|
|
118
|
+
event.stopPropagation();
|
|
119
|
+
event.preventDefault();
|
|
120
|
+
},
|
|
121
|
+
[ handleChange, setColorType ]
|
|
122
|
+
);
|
|
123
|
+
|
|
79
124
|
return (
|
|
80
|
-
<ColorfulWrapper
|
|
125
|
+
<ColorfulWrapper
|
|
126
|
+
ref={ forwardedRef }
|
|
127
|
+
{ ...divProps }
|
|
128
|
+
onPasteCapture={ maybeHandlePaste }
|
|
129
|
+
>
|
|
81
130
|
<Picker
|
|
82
131
|
onChange={ handleChange }
|
|
83
132
|
color={ safeColordColor }
|
|
@@ -29,6 +29,7 @@ const UnconnectedConfirmDialog = (
|
|
|
29
29
|
children,
|
|
30
30
|
confirmButtonText,
|
|
31
31
|
cancelButtonText,
|
|
32
|
+
isBusy,
|
|
32
33
|
...otherProps
|
|
33
34
|
} = useContextSystem( props, 'ConfirmDialog' );
|
|
34
35
|
|
|
@@ -100,6 +101,8 @@ const UnconnectedConfirmDialog = (
|
|
|
100
101
|
ref={ cancelButtonRef }
|
|
101
102
|
variant="tertiary"
|
|
102
103
|
onClick={ handleEvent( onCancel ) }
|
|
104
|
+
accessibleWhenDisabled
|
|
105
|
+
disabled={ isBusy }
|
|
103
106
|
>
|
|
104
107
|
{ cancelLabel }
|
|
105
108
|
</Button>
|
|
@@ -108,6 +111,9 @@ const UnconnectedConfirmDialog = (
|
|
|
108
111
|
ref={ confirmButtonRef }
|
|
109
112
|
variant="primary"
|
|
110
113
|
onClick={ handleEvent( onConfirm ) }
|
|
114
|
+
accessibleWhenDisabled
|
|
115
|
+
disabled={ isBusy }
|
|
116
|
+
isBusy={ isBusy }
|
|
111
117
|
>
|
|
112
118
|
{ confirmLabel }
|
|
113
119
|
</Button>
|
|
@@ -349,5 +349,71 @@ describe( 'Confirm', () => {
|
|
|
349
349
|
|
|
350
350
|
expect( onConfirm ).toHaveBeenCalled();
|
|
351
351
|
} );
|
|
352
|
+
|
|
353
|
+
it( 'should handle `isBusy` prop with different combinations', () => {
|
|
354
|
+
const { rerender } = render(
|
|
355
|
+
<ConfirmDialog
|
|
356
|
+
isOpen
|
|
357
|
+
onConfirm={ noop }
|
|
358
|
+
onCancel={ noop }
|
|
359
|
+
isBusy
|
|
360
|
+
>
|
|
361
|
+
Are you sure?
|
|
362
|
+
</ConfirmDialog>
|
|
363
|
+
);
|
|
364
|
+
|
|
365
|
+
let cancelButton = screen.getByRole( 'button', {
|
|
366
|
+
name: 'Cancel',
|
|
367
|
+
} );
|
|
368
|
+
let confirmButton = screen.getByRole( 'button', { name: 'OK' } );
|
|
369
|
+
|
|
370
|
+
// Only confirm button shows busy spinner
|
|
371
|
+
expect( cancelButton ).not.toHaveClass( 'is-busy' );
|
|
372
|
+
expect( confirmButton ).toHaveClass( 'is-busy' );
|
|
373
|
+
|
|
374
|
+
// Both buttons are disabled (exposed via aria-disabled due to accessibleWhenDisabled)
|
|
375
|
+
// Intentionally rely on aria-disabled rather than disabled attribute
|
|
376
|
+
expect( cancelButton ).toHaveAttribute( 'aria-disabled', 'true' );
|
|
377
|
+
expect( confirmButton ).toHaveAttribute( 'aria-disabled', 'true' );
|
|
378
|
+
|
|
379
|
+
// Test when isBusy is false
|
|
380
|
+
rerender(
|
|
381
|
+
<ConfirmDialog
|
|
382
|
+
isOpen
|
|
383
|
+
onConfirm={ noop }
|
|
384
|
+
onCancel={ noop }
|
|
385
|
+
isBusy={ false }
|
|
386
|
+
>
|
|
387
|
+
Are you sure?
|
|
388
|
+
</ConfirmDialog>
|
|
389
|
+
);
|
|
390
|
+
|
|
391
|
+
cancelButton = screen.getByRole( 'button', {
|
|
392
|
+
name: 'Cancel',
|
|
393
|
+
} );
|
|
394
|
+
confirmButton = screen.getByRole( 'button', { name: 'OK' } );
|
|
395
|
+
|
|
396
|
+
expect( cancelButton ).not.toHaveClass( 'is-busy' );
|
|
397
|
+
expect( confirmButton ).not.toHaveClass( 'is-busy' );
|
|
398
|
+
expect( cancelButton ).toBeEnabled();
|
|
399
|
+
expect( confirmButton ).toBeEnabled();
|
|
400
|
+
|
|
401
|
+
// Test when isBusy is undefined
|
|
402
|
+
rerender(
|
|
403
|
+
<ConfirmDialog isOpen onConfirm={ noop } onCancel={ noop }>
|
|
404
|
+
Are you sure?
|
|
405
|
+
</ConfirmDialog>
|
|
406
|
+
);
|
|
407
|
+
|
|
408
|
+
cancelButton = screen.getByRole( 'button', {
|
|
409
|
+
name: 'Cancel',
|
|
410
|
+
} );
|
|
411
|
+
confirmButton = screen.getByRole( 'button', { name: 'OK' } );
|
|
412
|
+
|
|
413
|
+
expect( cancelButton ).not.toHaveClass( 'is-busy' );
|
|
414
|
+
expect( confirmButton ).not.toHaveClass( 'is-busy' );
|
|
415
|
+
expect( cancelButton ).toBeEnabled();
|
|
416
|
+
expect( confirmButton ).toBeEnabled();
|
|
417
|
+
} );
|
|
352
418
|
} );
|
|
353
419
|
} );
|
|
@@ -50,4 +50,10 @@ export type ConfirmDialogProps = {
|
|
|
50
50
|
* It also implicitly toggles the controlled mode if set or the uncontrolled mode if it's not set.
|
|
51
51
|
*/
|
|
52
52
|
isOpen?: boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Indicates activity while an action is being performed.
|
|
55
|
+
* When `true`, the confirm button will show a busy state.
|
|
56
|
+
* Both buttons will be disabled.
|
|
57
|
+
*/
|
|
58
|
+
isBusy?: boolean;
|
|
53
59
|
};
|
|
@@ -43,13 +43,13 @@ function applyOptionDeprecations( {
|
|
|
43
43
|
};
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
function getDescribedBy(
|
|
46
|
+
function getDescribedBy( currentName: string, describedBy?: string ) {
|
|
47
47
|
if ( describedBy ) {
|
|
48
48
|
return describedBy;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
// translators: %s: The selected option.
|
|
52
|
-
return sprintf( __( 'Currently selected: %s' ),
|
|
52
|
+
return sprintf( __( 'Currently selected: %s' ), currentName );
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
function CustomSelectControl< T extends CustomSelectOption >(
|
|
@@ -84,7 +84,7 @@ function CustomSelectControl< T extends CustomSelectOption >(
|
|
|
84
84
|
const store = Ariakit.useSelectStore< string >( {
|
|
85
85
|
async setValue( nextValue ) {
|
|
86
86
|
const nextOption = options.find(
|
|
87
|
-
( item ) => item.
|
|
87
|
+
( item ) => item.key === nextValue
|
|
88
88
|
);
|
|
89
89
|
|
|
90
90
|
if ( ! onChange || ! nextOption ) {
|
|
@@ -108,12 +108,12 @@ function CustomSelectControl< T extends CustomSelectOption >(
|
|
|
108
108
|
};
|
|
109
109
|
onChange( changeObject );
|
|
110
110
|
},
|
|
111
|
-
value: value?.
|
|
111
|
+
value: value?.key,
|
|
112
112
|
// Setting the first option as a default value when no value is provided
|
|
113
113
|
// is already done natively by the underlying Ariakit component,
|
|
114
114
|
// but doing this explicitly avoids the `onChange` callback from firing
|
|
115
115
|
// on initial render, thus making this implementation closer to the v1.
|
|
116
|
-
defaultValue: options[ 0 ]?.
|
|
116
|
+
defaultValue: options[ 0 ]?.key,
|
|
117
117
|
} );
|
|
118
118
|
|
|
119
119
|
const children = options
|
|
@@ -134,7 +134,7 @@ function CustomSelectControl< T extends CustomSelectOption >(
|
|
|
134
134
|
return (
|
|
135
135
|
<CustomSelectItem
|
|
136
136
|
key={ key }
|
|
137
|
-
value={
|
|
137
|
+
value={ key }
|
|
138
138
|
children={ hint ? withHint : name }
|
|
139
139
|
style={ style }
|
|
140
140
|
className={ clsx(
|
|
@@ -151,22 +151,25 @@ function CustomSelectControl< T extends CustomSelectOption >(
|
|
|
151
151
|
|
|
152
152
|
const currentValue = Ariakit.useStoreState( store, 'value' );
|
|
153
153
|
|
|
154
|
-
const
|
|
155
|
-
|
|
154
|
+
const selectedOption =
|
|
155
|
+
options
|
|
156
156
|
?.map( applyOptionDeprecations )
|
|
157
|
-
?.find( ( {
|
|
157
|
+
?.find( ( { key } ) => currentValue === key ) ?? options[ 0 ];
|
|
158
|
+
|
|
159
|
+
const renderSelectedValue = () => {
|
|
160
|
+
if ( ! showSelectedHint || ! selectedOption.hint ) {
|
|
161
|
+
return selectedOption?.name;
|
|
162
|
+
}
|
|
158
163
|
|
|
159
164
|
return (
|
|
160
165
|
<Styled.SelectedExperimentalHintWrapper>
|
|
161
|
-
{
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
</Styled.SelectedExperimentalHintItem>
|
|
169
|
-
) }
|
|
166
|
+
{ selectedOption?.name }
|
|
167
|
+
<Styled.SelectedExperimentalHintItem
|
|
168
|
+
// Keeping the classname for legacy reasons
|
|
169
|
+
className="components-custom-select-control__hint"
|
|
170
|
+
>
|
|
171
|
+
{ selectedOption?.hint }
|
|
172
|
+
</Styled.SelectedExperimentalHintItem>
|
|
170
173
|
</Styled.SelectedExperimentalHintWrapper>
|
|
171
174
|
);
|
|
172
175
|
};
|
|
@@ -188,9 +191,7 @@ function CustomSelectControl< T extends CustomSelectOption >(
|
|
|
188
191
|
<>
|
|
189
192
|
<_CustomSelect
|
|
190
193
|
aria-describedby={ descriptionId }
|
|
191
|
-
renderSelectedValue={
|
|
192
|
-
showSelectedHint ? renderSelectedValueHint : undefined
|
|
193
|
-
}
|
|
194
|
+
renderSelectedValue={ renderSelectedValue }
|
|
194
195
|
size={ translatedSize }
|
|
195
196
|
store={ store }
|
|
196
197
|
className={ clsx(
|
|
@@ -205,7 +206,7 @@ function CustomSelectControl< T extends CustomSelectOption >(
|
|
|
205
206
|
</_CustomSelect>
|
|
206
207
|
<VisuallyHidden>
|
|
207
208
|
<span id={ descriptionId }>
|
|
208
|
-
{ getDescribedBy(
|
|
209
|
+
{ getDescribedBy( selectedOption?.name, describedBy ) }
|
|
209
210
|
</span>
|
|
210
211
|
</VisuallyHidden>
|
|
211
212
|
</>
|
package/src/modal/index.tsx
CHANGED
package/src/utils/math.js
CHANGED
|
@@ -81,12 +81,12 @@ export function clamp( value, min, max ) {
|
|
|
81
81
|
*/
|
|
82
82
|
export function ensureValidStep( value, min, step ) {
|
|
83
83
|
const baseValue = getNumber( value );
|
|
84
|
+
const minValue = getNumber( min );
|
|
84
85
|
const stepValue = getNumber( step );
|
|
85
86
|
const precision = Math.max( getPrecision( step ), getPrecision( min ) );
|
|
86
|
-
const realMin = Math.abs( min ) === Infinity ? 0 : min;
|
|
87
87
|
// If the step is not a factor of the minimum then the step must be
|
|
88
88
|
// offset by the minimum.
|
|
89
|
-
const tare =
|
|
89
|
+
const tare = minValue % stepValue ? minValue : 0;
|
|
90
90
|
const rounded = Math.round( ( baseValue - tare ) / stepValue ) * stepValue;
|
|
91
91
|
const fromMin = rounded + tare;
|
|
92
92
|
return precision ? getNumber( fromMin.toFixed( precision ) ) : fromMin;
|