Skip to content

Commit 40985bc

Browse files
author
刘欢
committed
feat: enhance disabled handle logic and improve boundary checks
1 parent 604d94e commit 40985bc

1 file changed

Lines changed: 58 additions & 17 deletions

File tree

src/Slider.tsx

Lines changed: 58 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -191,25 +191,34 @@ const Slider = React.forwardRef<SliderRef, SliderProps<number | number[]>>((prop
191191
const containerRef = React.useRef<HTMLDivElement>(null);
192192

193193
// ============================ Disabled ============================
194-
const disabled = React.useMemo(() => {
194+
const normalizedDisabled = React.useMemo(() => {
195195
if (typeof rawDisabled === 'boolean') {
196196
return rawDisabled;
197197
}
198-
if (Array.isArray(rawDisabled)) {
199-
const values = Array.isArray(value) ? value : [value];
200-
return values.every((_, index) => rawDisabled[index]);
198+
return Array.from(rawDisabled, (d) => d ?? false);
199+
}, [rawDisabled]);
200+
201+
const disabled = React.useMemo(() => {
202+
if (typeof normalizedDisabled === 'boolean') {
203+
return normalizedDisabled;
201204
}
202-
return false;
203-
}, [rawDisabled, value]);
205+
return normalizedDisabled.length > 0 && normalizedDisabled.every((d) => d);
206+
}, [normalizedDisabled]);
204207

205208
const isHandleDisabled = React.useCallback(
206209
(index: number) => {
207-
if (typeof rawDisabled === 'boolean') {
208-
return rawDisabled;
210+
if (typeof normalizedDisabled === 'boolean') {
211+
return normalizedDisabled;
209212
}
210-
return rawDisabled[index] || false;
213+
if (process.env.NODE_ENV !== 'production' && index >= normalizedDisabled.length) {
214+
warning(
215+
false,
216+
`[rc-slider] \`disabled\` array length (${normalizedDisabled.length}) is shorter than handle count.`,
217+
);
218+
}
219+
return normalizedDisabled[index] || false;
211220
},
212-
[rawDisabled],
221+
[normalizedDisabled],
213222
);
214223

215224
const direction = React.useMemo<Direction>(() => {
@@ -329,13 +338,24 @@ const Slider = React.forwardRef<SliderRef, SliderProps<number | number[]>>((prop
329338
) {
330339
const newDisabled = [...rawDisabled];
331340

341+
// Find the first index where arrays differ (handles duplicate values correctly)
342+
const findDiffIndex = (longer: number[], shorter: number[]) => {
343+
for (let i = 0; i < longer.length; i++) {
344+
if (longer[i] !== shorter[i]) {
345+
return i;
346+
}
347+
}
348+
return longer.length;
349+
};
350+
332351
if (cloneNextValues.length > rawValues.length) {
333-
const index = cloneNextValues.findIndex((item, i) => item !== rawValues[i]);
334-
const insertIndex = index === -1 ? rawValues.length : index;
352+
// Handle added
353+
const insertIndex = findDiffIndex(cloneNextValues, rawValues);
335354
newDisabled.splice(insertIndex, 0, false);
336-
} else if (cloneNextValues.length < rawValues.length) {
337-
const index = rawValues.findIndex((item) => !cloneNextValues.includes(item));
338-
newDisabled.splice(index, 1);
355+
} else {
356+
// Handle removed
357+
const removeIndex = findDiffIndex(rawValues, cloneNextValues);
358+
newDisabled.splice(removeIndex, 1);
339359
}
340360

341361
onDisabledChange?.(newDisabled);
@@ -425,7 +445,8 @@ const Slider = React.forwardRef<SliderRef, SliderProps<number | number[]>>((prop
425445

426446
if (rangeEditable && valueDist !== 0 && (!maxCount || rawValues.length < maxCount)) {
427447
const leftDisabled = isHandleDisabled(valueBeforeIndex);
428-
const rightDisabled = isHandleDisabled(valueBeforeIndex + 1);
448+
const rightDisabled =
449+
valueBeforeIndex + 1 < rawValues.length && isHandleDisabled(valueBeforeIndex + 1);
429450

430451
if (leftDisabled && rightDisabled) {
431452
return;
@@ -455,7 +476,27 @@ const Slider = React.forwardRef<SliderRef, SliderProps<number | number[]>>((prop
455476

456477
valueIndex = nearestIndex;
457478
}
458-
cloneNextValues[valueIndex] = newValue;
479+
480+
// Check boundaries: cannot cross disabled handles
481+
let minBound = mergedMin;
482+
let maxBound = mergedMax;
483+
484+
for (let i = valueIndex - 1; i >= 0; i--) {
485+
if (isHandleDisabled(i)) {
486+
minBound = rawValues[i];
487+
break;
488+
}
489+
}
490+
for (let i = valueIndex + 1; i < rawValues.length; i++) {
491+
if (isHandleDisabled(i)) {
492+
maxBound = rawValues[i];
493+
break;
494+
}
495+
}
496+
497+
// Clamp new value within bounds
498+
const clampedValue = Math.max(minBound, Math.min(maxBound, newValue));
499+
cloneNextValues[valueIndex] = clampedValue;
459500
focusIndex = valueIndex;
460501
}
461502

0 commit comments

Comments
 (0)