import React, { ChangeEvent, useEffect, useState } from 'react'; interface MultiRangeFilterProps { min: number; max: number; selectedMin: number; selectedMax: number; valueFormatter: (value: number) => string; onChange: (min: number, max: number) => void; } const MultiRangeFilter: React.FC = ({ min, max, selectedMin, selectedMax, valueFormatter, onChange }) => { const [isDragging, setIsDragging] = useState(false); const [leftPercentage, setLeftPercentage] = useState(0); const [rightPercentage, setRightPercentage] = useState(0); const [minVal, setMinVal] = useState(selectedMin ?? min); const [maxVal, setMaxVal] = useState(selectedMax ?? max); const minGap = 5; // Sync internal state with external selectedMin/selectedMax changes useEffect(() => { setMinVal(selectedMin ?? min); setMaxVal(selectedMax ?? max); }, [min, max, selectedMin, selectedMax]); // Recalculate slider track whenever values change useEffect(() => { const range = max - min || 1; const minPercent = ((minVal - min) / range) * 100; const maxPercent = ((maxVal - min) / range) * 100; setLeftPercentage(minPercent); setRightPercentage(100 - maxPercent); }, [minVal, maxVal, min, max]); const slideMin = (e: ChangeEvent) => { const value = parseInt(e.target.value, 10); // Ensure the thumbs don’t cross and enforce minGap if (value <= maxVal - minGap) { setMinVal(value); } }; const slideMax = (e: ChangeEvent) => { const value = parseInt(e.target.value, 10); // Ensure the thumbs don’t cross and enforce minGap if (value >= minVal + minGap) { setMaxVal(value); } }; const startDrag = () => { setIsDragging(true); }; const stopDrag = () => { setIsDragging(false); // Notify parent with the final values onChange(minVal, maxVal); }; return (
{/* Show currently selected range */}
{valueFormatter(minVal)}
{valueFormatter(maxVal)}
{isDragging &&
{valueFormatter(minVal)}
} {isDragging &&
{valueFormatter(maxVal)}
}
); }; export default MultiRangeFilter;