UNPKG

@sinchsmb/ui-kit

Version:

UI kit for SinchSMB frontend

141 lines (125 loc) 4.39 kB
import { useCallback, useMemo } from 'react'; import { useTranslation } from '../../../core/hooks/useTranslation'; import { useToast } from '../../../core/managers/ToastManager/hooks/useToast'; import { assertUnreachable } from '../../../utils/assertUnreachable'; import { ToastAppearance } from '../../Toast/constants'; import { TableSelectionType } from '../constants'; import { useTablePropsContext } from '../contexts/TablePropsContext'; import { useTableSelectionContext } from '../contexts/TableSelectionContext'; /** Result of {@link useAllPageRowsSelection} hook. */ export interface UseAllPageRowsSelectionResult { /** Flag indicating whether all page rows are selected. */ isAllPageRowsSelected: boolean | null; /** Function that will toggle all page rows selection. */ onAllPageRowsSelectionChange: (selected: boolean) => void; } /** Hook that returns information about all page rows selection. */ export function useAllPageRowsSelection(): UseAllPageRowsSelectionResult { const { t } = useTranslation(); const showToast = useToast(); const { selection, onSelectionChanged } = useTableSelectionContext(); const { rowSelectionName, rows, rowIdProvider, rowSelectionIncludeLimit } = useTablePropsContext(); const onAllPageRowsSelectionChange = useCallback( (selected: boolean) => { if (!onSelectionChanged) { return; } if (selection?.type === TableSelectionType.Exclude) { const unselectedIds = new Set(selection.unselectedIds); if (selected) { rows.forEach((row) => { const rowId = rowIdProvider(row); unselectedIds.delete(rowId); }); } else { rows.forEach((row) => { const rowId = rowIdProvider(row); unselectedIds.add(rowId); }); } onSelectionChanged({ type: TableSelectionType.Exclude, unselectedIds: Array.from(unselectedIds), }); } else { const selectedIds = new Set(selection?.selectedIds); if (selected) { rows.forEach((row) => { const rowId = rowIdProvider(row); selectedIds.add(rowId); }); } else { rows.forEach((row) => { const rowId = rowIdProvider(row); selectedIds.delete(rowId); }); } if (rowSelectionIncludeLimit && selectedIds.size > rowSelectionIncludeLimit) { const message = t('ui.table.selectionIncludeLimit', { count: rowSelectionIncludeLimit, actionText: t('ui.table.selectAll'), name: rowSelectionName, }); showToast(message, { appearance: ToastAppearance.Warning }); } onSelectionChanged({ type: TableSelectionType.Include, selectedIds: Array.from(selectedIds).slice(0, rowSelectionIncludeLimit), }); } }, [ onSelectionChanged, rowIdProvider, rowSelectionIncludeLimit, rowSelectionName, rows, selection, showToast, t, ], ); const isAllPageRowsSelected = useMemo(() => { if (!selection) { return false; } let allRowsSelected = false; let someRowSelected = false; let countIncluded = 0; let countExcluded = 0; rows.forEach((row) => { const rowId = rowIdProvider(row); switch (selection.type) { case TableSelectionType.Include: if (selection.selectedIds.has(rowId)) { someRowSelected = true; countIncluded++; if (rows.length === countIncluded || selection.selectedIds.size === rowSelectionIncludeLimit) { allRowsSelected = true; } } break; case TableSelectionType.Exclude: if (!selection.unselectedIds.has(rowId)) { someRowSelected = true; countExcluded++; if (rows.length === countExcluded) { allRowsSelected = true; } } break; /* istanbul ignore next */ default: assertUnreachable(selection); } }); if (allRowsSelected) { return true; } return someRowSelected ? null : false; }, [rowIdProvider, rowSelectionIncludeLimit, rows, selection]); return { onAllPageRowsSelectionChange, isAllPageRowsSelected, }; }