diff --git a/packages/react/src/components/Slider/Slider-test.js b/packages/react/src/components/Slider/Slider-test.js index 875261640870..381880306b71 100644 --- a/packages/react/src/components/Slider/Slider-test.js +++ b/packages/react/src/components/Slider/Slider-test.js @@ -228,8 +228,8 @@ describe('Slider', () => { }, }; wrapper.instance().onChange(evt); - expect(wrapper.state().value).toEqual(100); - expect(handleChange).lastCalledWith({ value: 100 }); + expect(wrapper.state().value).toEqual(999); + expect(handleChange).lastCalledWith({ value: 999 }); }); }); diff --git a/packages/react/src/components/Slider/Slider.js b/packages/react/src/components/Slider/Slider.js index c1c29fd1d573..97160e8a649b 100644 --- a/packages/react/src/components/Slider/Slider.js +++ b/packages/react/src/components/Slider/Slider.js @@ -171,7 +171,7 @@ export default class Slider extends PureComponent { * Sets up initial slider position and value in response to component mount. */ componentDidMount() { - const { value, left } = this.calcValue({}); + const { value, left } = this.calcValue({ useRawValue: true }); this.setState({ value, left }); } @@ -339,8 +339,14 @@ export default class Slider extends PureComponent { delta *= stepMultiplier; } + Math.floor(this.state.value / this.props.step) * this.props.step; const { value, left } = this.calcValue({ - value: this.state.value + delta, + // Ensures custom value from `` won't cause skipping next stepping point with right arrow key, + // e.g. Typing 51 in ``, moving focus onto the thumb and the hitting right arrow key should yield 52 instead of 54 + value: + (delta > 0 + ? Math.floor(this.state.value / this.props.step) * this.props.step + : this.state.value) + delta, }); this.setState({ value, left }); }; @@ -369,10 +375,11 @@ export default class Slider extends PureComponent { if (isNaN(targetValue)) { this.setState({ value: evt.target.value }); } else { - targetValue = this.clamp(targetValue, this.props.min, this.props.max); - // Recalculate the state's value and update the Slider - const { value, left } = this.calcValue({ value: targetValue }); + const { value, left } = this.calcValue({ + value: targetValue, + useRawValue: true, + }); this.setState({ value, left, needsOnRelease: true }); } }; @@ -394,8 +401,9 @@ export default class Slider extends PureComponent { * an event fired by one of the Slider's `DRAG_EVENT_TYPES` events. * @param {number} [params.value] Optional value use during calculations if * clientX is not provided. + * @param {boolean} [params.useRawValue=false] `true` to use the given value as-is. */ - calcValue = ({ clientX = null, value = null }) => { + calcValue = ({ clientX = null, value = null, useRawValue = false }) => { const range = this.props.max - this.props.min; const boundingRect = this.element.getBoundingClientRect(); const totalSteps = range / this.props.step; @@ -419,6 +427,11 @@ export default class Slider extends PureComponent { leftPercent = value / (range - this.props.min); } + if (useRawValue) { + // Adjusts only for min/max of thumb position + return { value, left: Math.min(1, Math.max(0, leftPercent)) * 100 }; + } + let steppedValue = Math.round(leftPercent * totalSteps) * this.props.step; let steppedPercent = this.clamp(steppedValue / range, 0, 1);