feat: implement excel-style drag-to-select and shift-click in Dimensions and filters

This commit is contained in:
Christian Vidal Wolf
2026-04-16 12:01:59 +02:00
parent 19ca75c1b9
commit cbfd5f573d
2 changed files with 113 additions and 12 deletions
+17 -3
View File
@@ -27,6 +27,7 @@ export function ColumnFilterPopover({
const [isDragging, setIsDragging] = useState(false);
const [dragStart, setDragStart] = useState<number | null>(null);
const [hoveredIndex, setHoveredIndex] = useState<number | null>(null);
const [lastClickedIndex, setLastClickedIndex] = useState<number | null>(null);
const listRef = React.useRef<HTMLDivElement>(null);
const filteredValues = useMemo(() => {
@@ -134,10 +135,23 @@ export function ColumnFilterPopover({
tabIndex={0}
onMouseDown={(e) => { e.preventDefault(); handleMouseDown(idx); }}
onMouseEnter={() => handleMouseEnter(idx)}
onClick={(e) => { if (!isDragging) onToggle(val); }}
onKeyDown={(e) => { if (e.key === ' ' || e.key === 'Enter') { e.preventDefault(); onToggle(val); } }}
onClick={(e) => {
if (isDragging) return;
if (e.shiftKey && lastClickedIndex !== null) {
const start = Math.min(lastClickedIndex, idx);
const end = Math.max(lastClickedIndex, idx);
const itemsToSelect = filteredValues.slice(start, end + 1);
const newSelected = new Set([...selectedValues, ...itemsToSelect]);
onSelectAll(Array.from(newSelected));
} else {
onToggle(val);
}
setLastClickedIndex(idx);
}}
onKeyDown={(e) => { if (e.key === ' ' || e.key === 'Enter') { e.preventDefault(); onToggle(val); setLastClickedIndex(idx); } }}
className={cn(
"flex items-center gap-2 p-1.5 rounded cursor-pointer group transition-colors",
"flex items-center gap-2 p-1.5 rounded cursor-pointer group transition-colors select-none",
isDragSelected ? "bg-blue-600/40" : "hover:bg-slate-700/50"
)}
>