Skip to content

Commit 4b232b7

Browse files
author
刘欢
committed
feat: prevent handle movement across disabled boundaries in range slider
1 parent 5303584 commit 4b232b7

2 files changed

Lines changed: 55 additions & 1 deletion

File tree

src/Slider.tsx

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,14 @@ const Slider = React.forwardRef<SliderRef, SliderProps<number | number[]>>((prop
430430
return;
431431
}
432432

433+
if (leftDisabled && newValue < rawValues[valueBeforeIndex]) {
434+
return;
435+
}
436+
437+
if (rightDisabled && newValue > rawValues[valueBeforeIndex + 1]) {
438+
return;
439+
}
440+
433441
cloneNextValues.splice(valueBeforeIndex + 1, 0, newValue);
434442
focusIndex = valueBeforeIndex + 1;
435443
} else {
@@ -454,7 +462,25 @@ const Slider = React.forwardRef<SliderRef, SliderProps<number | number[]>>((prop
454462

455463
valueIndex = nearestIndex;
456464
}
457-
cloneNextValues[valueIndex] = newValue;
465+
466+
let minBound = mergedMin;
467+
let maxBound = mergedMax;
468+
469+
for (let i = valueIndex - 1; i >= 0; i--) {
470+
if (isHandleDisabled(i)) {
471+
minBound = rawValues[i];
472+
break;
473+
}
474+
}
475+
for (let i = valueIndex + 1; i < rawValues.length; i++) {
476+
if (isHandleDisabled(i)) {
477+
maxBound = rawValues[i];
478+
break;
479+
}
480+
}
481+
482+
const clampedValue = Math.max(minBound, Math.min(maxBound, newValue));
483+
cloneNextValues[valueIndex] = clampedValue;
458484
focusIndex = valueIndex;
459485
}
460486

tests/Range.test.tsx

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1064,5 +1064,33 @@ describe('Range', () => {
10641064
expect(onChange).not.toHaveBeenCalled();
10651065
expect(onDisabledChange).not.toHaveBeenCalled();
10661066
});
1067+
1068+
it('click to move cannot cross disabled handle boundary', () => {
1069+
const onChange = jest.fn();
1070+
const { container } = render(
1071+
<Slider range value={[20, 50, 80]} disabled={[true, false, false]} onChange={onChange} />,
1072+
);
1073+
1074+
// Click at position 10, which is left of disabled handle at 20
1075+
// Nearest enabled handle is 50, but it cannot cross below 20
1076+
doMouseDown(container, 10, 'rc-slider', true);
1077+
1078+
// Should move handle to 20 (boundary), not 10
1079+
expect(onChange).toHaveBeenCalledWith([20, 20, 80]);
1080+
});
1081+
1082+
it('click to move cannot cross disabled handle on right side', () => {
1083+
const onChange = jest.fn();
1084+
const { container } = render(
1085+
<Slider range value={[20, 50, 80]} disabled={[false, false, true]} onChange={onChange} />,
1086+
);
1087+
1088+
// Click at position 90, which is right of disabled handle at 80
1089+
// Nearest enabled handle is 50, but it cannot cross above 80
1090+
doMouseDown(container, 90, 'rc-slider', true);
1091+
1092+
// Should move handle to 80 (boundary), not 90
1093+
expect(onChange).toHaveBeenCalledWith([20, 80, 80]);
1094+
});
10671095
});
10681096
});

0 commit comments

Comments
 (0)