64 lines
1.6 KiB
TypeScript
64 lines
1.6 KiB
TypeScript
import { useState, useCallback } from "react";
|
|
|
|
export interface UseSelectionReturn {
|
|
selectedIds: Set<string>;
|
|
toggle: (id: string) => void;
|
|
toggleAll: (ids: string[]) => void;
|
|
clear: () => void;
|
|
isAllSelected: (ids: string[]) => boolean;
|
|
isIndeterminate: (ids: string[]) => boolean;
|
|
count: number;
|
|
selectedArray: string[];
|
|
}
|
|
|
|
export function useSelection(): UseSelectionReturn {
|
|
const [selectedIds, setSelectedIds] = useState<Set<string>>(new Set());
|
|
|
|
const toggle = useCallback((id: string) => {
|
|
setSelectedIds((prev) => {
|
|
const next = new Set(prev);
|
|
if (next.has(id)) next.delete(id);
|
|
else next.add(id);
|
|
return next;
|
|
});
|
|
}, []);
|
|
|
|
const toggleAll = useCallback((ids: string[]) => {
|
|
setSelectedIds((prev) => {
|
|
const allSelected = ids.every((id) => prev.has(id));
|
|
if (allSelected) {
|
|
const next = new Set(prev);
|
|
ids.forEach((id) => next.delete(id));
|
|
return next;
|
|
} else {
|
|
const next = new Set(prev);
|
|
ids.forEach((id) => next.add(id));
|
|
return next;
|
|
}
|
|
});
|
|
}, []);
|
|
|
|
const clear = useCallback(() => setSelectedIds(new Set()), []);
|
|
|
|
const isAllSelected = useCallback(
|
|
(ids: string[]) => ids.length > 0 && ids.every((id) => selectedIds.has(id)),
|
|
[selectedIds],
|
|
);
|
|
|
|
const isIndeterminate = useCallback(
|
|
(ids: string[]) => ids.some((id) => selectedIds.has(id)) && !ids.every((id) => selectedIds.has(id)),
|
|
[selectedIds],
|
|
);
|
|
|
|
return {
|
|
selectedIds,
|
|
toggle,
|
|
toggleAll,
|
|
clear,
|
|
isAllSelected,
|
|
isIndeterminate,
|
|
count: selectedIds.size,
|
|
selectedArray: [...selectedIds],
|
|
};
|
|
}
|