@@ -299,12 +299,6 @@ export interface SliderProps
299299 warnText ?: React . ReactNode ;
300300}
301301
302- interface CalcValueProps {
303- clientX ?: number ;
304- value ?: number ;
305- useRawValue ?: boolean ;
306- }
307-
308302interface CalcLeftPercentProps {
309303 clientX ?: number ;
310304 value ?: number ;
@@ -1042,65 +1036,67 @@ class Slider extends PureComponent<SliderProps> {
10421036 return 0 ;
10431037 } ;
10441038
1045- calcSteppedValuePercent = ( { leftPercent, range } ) => {
1046- const { step = 1 } = this . props ;
1047- const totalSteps = range / step ;
1048-
1049- let steppedValue = Math . round ( leftPercent * totalSteps ) * step ;
1050- const steppedPercent = this . clamp ( steppedValue / range , 0 , 1 ) ;
1051-
1052- steppedValue = this . clamp (
1053- steppedValue + this . props . min ,
1054- this . props . min ,
1055- this . props . max
1056- ) ;
1057-
1058- return [ steppedValue , steppedPercent ] ;
1039+ /**
1040+ * Calculates the discrete value (snapped to the nearest step) along
1041+ * with the corresponding handle position percentage.
1042+ */
1043+ calcDiscreteValueAndPercent = ( {
1044+ leftPercent,
1045+ } : {
1046+ /** The percentage representing the position on the track. */
1047+ leftPercent : number ;
1048+ } ) => {
1049+ const { step = 1 , min, max } = this . props ;
1050+ const numSteps =
1051+ Math . floor ( ( max - min ) / step ) + ( ( max - min ) % step === 0 ? 1 : 2 ) ;
1052+ /** Index of the step that corresponds to `leftPercent`. */
1053+ const stepIndex = Math . round ( leftPercent * ( numSteps - 1 ) ) ;
1054+ const discreteValue =
1055+ stepIndex === numSteps - 1 ? max : min + step * stepIndex ;
1056+ /** Percentage corresponding to the step index. */
1057+ const discretePercent = stepIndex / ( numSteps - 1 ) ;
1058+
1059+ return { discreteValue, discretePercent } ;
10591060 } ;
10601061
10611062 /**
1062- * Calculates a new Slider `value` and `left` (thumb offset) given a `clientX`,
1063- * `value`, or neither of those.
1064- * - If `clientX` is specified, it will be used in
1065- * conjunction with the Slider's bounding rectangle to calculate the new
1066- * values.
1067- * - If `clientX` is not specified and `value` is, it will be used to
1068- * calculate new values as though it were the current value of the Slider.
1069- * - If neither `clientX` nor `value` are specified, `this.props.value` will
1070- * be used to calculate the new values as though it were the current value
1071- * of the Slider.
1072- *
1073- * @param {object } params
1074- * @param {number } [params.clientX] Optional clientX value expected to be from
1075- * an event fired by one of the Slider's `DRAG_EVENT_TYPES` events.
1076- * @param {number } [params.value] Optional value use during calculations if
1077- * clientX is not provided.
1078- * @param {boolean } [params.useRawValue=false] `true` to use the given value as-is.
1063+ * Calculates the slider's value and handle position based on either a
1064+ * mouse/touch event or an explicit value.
10791065 */
1080- calcValue = ( { clientX, value, useRawValue = false } : CalcValueProps ) => {
1066+ calcValue = ( {
1067+ clientX,
1068+ value,
1069+ useRawValue,
1070+ } : {
1071+ /** The x-coordinate from a mouse/touch event. */
1072+ clientX ?: number ;
1073+ /** Value to base the calculations on (if no `clientX`). */
1074+ value ?: number ;
1075+ /** Whether to bypass the stepping logic and use the raw value. */
1076+ useRawValue ?: boolean ;
1077+ } ) => {
10811078 const range = this . props . max - this . props . min ;
1082-
1083- // @todo solve for rtl.
1084- const leftPercent = this . calcLeftPercent ( {
1079+ const leftPercentRaw = this . calcLeftPercent ( {
10851080 clientX,
10861081 value,
10871082 range,
10881083 } ) ;
1084+ /** `leftPercentRaw` clamped between 0 and 1. */
1085+ const leftPercent = Math . min ( 1 , Math . max ( 0 , leftPercentRaw ) ) ;
10891086
10901087 if ( useRawValue ) {
1091- // Adjusts only for min/max of thumb position
10921088 return {
10931089 value,
1094- left : Math . min ( 1 , Math . max ( 0 , leftPercent ) ) * 100 ,
1090+ left : leftPercent * 100 ,
10951091 } ;
10961092 }
10971093
1098- const [ steppedValue , steppedPercent ] = this . calcSteppedValuePercent ( {
1099- leftPercent ,
1100- range ,
1101- } ) ;
1094+ // Use the discrete value and percentage for snapping.
1095+ const { discreteValue , discretePercent } = this . calcDiscreteValueAndPercent (
1096+ { leftPercent }
1097+ ) ;
11021098
1103- return { value : steppedValue , left : steppedPercent * 100 } ;
1099+ return { value : discreteValue , left : discretePercent * 100 } ;
11041100 } ;
11051101
11061102 calcDistanceToHandle = ( handle : HandlePosition , clientX ) => {
0 commit comments