56 lines
1.5 KiB
TypeScript
56 lines
1.5 KiB
TypeScript
import * as React from "react";
|
|
|
|
export type CheckedState = boolean | "indeterminate";
|
|
|
|
/**
|
|
* Hook para manejar selección múltiple con estado "seleccionar todo".
|
|
*/
|
|
export function useRowSelection(totalRows: number) {
|
|
const [selectedRows, setSelection] = React.useState<Set<number>>(new Set());
|
|
|
|
// Deriva array de índices seleccionados
|
|
const selectedIndexes = React.useMemo(
|
|
() => [...selectedRows].sort((a, b) => a - b),
|
|
[selectedRows]
|
|
);
|
|
|
|
// Estado visual del checkbox maestro
|
|
const selectAllState: CheckedState = React.useMemo(() => {
|
|
if (totalRows === 0 || selectedRows.size === 0) return false;
|
|
if (selectedRows.size === totalRows) return true;
|
|
return "indeterminate";
|
|
}, [selectedRows, totalRows]);
|
|
|
|
// Seleccionar/deseleccionar una fila
|
|
const toggleRow = React.useCallback((index: number) => {
|
|
setSelection((prev) => {
|
|
const next = new Set(prev);
|
|
next.has(index) ? next.delete(index) : next.add(index);
|
|
return next;
|
|
});
|
|
}, []);
|
|
|
|
// Seleccionar todas o limpiar
|
|
const setSelectAll = React.useCallback(
|
|
(checked: CheckedState) => {
|
|
if (checked === false) {
|
|
setSelection(new Set());
|
|
} else {
|
|
setSelection(new Set(Array.from({ length: totalRows }, (_, i) => i)));
|
|
}
|
|
},
|
|
[totalRows]
|
|
);
|
|
|
|
const clearSelection = React.useCallback(() => setSelection(new Set()), []);
|
|
|
|
return {
|
|
selectedRows,
|
|
selectedIndexes,
|
|
selectAllState,
|
|
toggleRow,
|
|
setSelectAll,
|
|
clearSelection,
|
|
};
|
|
}
|