import React, { type ReactNode } from 'react'; import type { NextSortDirection, SortState, TableColumn, TableVariant, } from './types'; type Context = { columns: TableColumn[]; data: T[]; selectedRowIds?: string[]; rowIds: string[]; rowHeight: 'normal' | 'compact'; sortState: SortState; setSortState(sortState: SortState): void; nextSortDirection: NextSortDirection; getRowId?(row: T): string; getIsRowActive?(row: T): boolean; getIsRowDisabled?(row: T): boolean; getIsRowCheckable?(row: T): boolean; getRowVariant?(row: T): TableVariant | undefined; onRowClick?(row: T): void; onRowSelectionChange?: (row: T, rowId: string, isChecked: boolean) => void; onAllRowsSelectionChange?: ( rows: T[], rowIds: string[], isChecked: boolean, ) => void; }; // eslint-disable-next-line @typescript-eslint/no-explicit-any export const TableContext = React.createContext | null>(null); export type TableProviderProps = { children: ReactNode; } & Context; export function TableProvider({ children, ...contextProps }: TableProviderProps) { return ( {children} ); } function useTableContext() { const context = React.useContext(TableContext); if (context === null) { throw new Error('useTableContext should be within a TableContext'); } return context; } export function useTableHeaderCellContext() { const { sortState, setSortState, nextSortDirection } = useTableContext(); return { sortState, setSortState, nextSortDirection, }; } export function useTableHeaderCheckboxContext() { const { selectedRowIds, rowIds, data, onAllRowsSelectionChange } = useTableContext(); if (!selectedRowIds) { throw new Error('selectedRowIds is undefined. '); } const onChange = (event: React.ChangeEvent) => { onAllRowsSelectionChange?.(data, rowIds, event.currentTarget.checked); }; const isDisabled = rowIds.length === 0; const isChecked = selectedRowIds.length > 0 && rowIds.every((id) => selectedRowIds.includes(id)); const isIndeterminate = !isChecked && selectedRowIds.length > 0; return { isChecked, isDisabled, isIndeterminate, hasCheckbox: true, onChange, }; } export function useTableRowContext(row: T) { const { columns, getRowId, getIsRowDisabled, getIsRowCheckable, getIsRowActive, getRowVariant, onRowClick, } = useTableContext(); return { columns, isRowActive: getIsRowActive ? getIsRowActive(row) : false, isRowDisabled: getIsRowDisabled ? getIsRowDisabled(row) : false, isCheckboxDisabled: getIsRowCheckable ? !getIsRowCheckable(row) : false, rowVariant: getRowVariant ? getRowVariant(row) : undefined, getRowId, onRowClick, }; } export function useTableCellContext(row: T) { const { rowHeight, getRowId, getIsRowDisabled } = useTableContext(); return { rowHeight, isRowDisabled: getIsRowDisabled ? getIsRowDisabled(row) : false, getRowId, }; } export function useTableRowCheckboxContext(row: T) { const { selectedRowIds, getRowId, getIsRowDisabled, getIsRowCheckable, onRowSelectionChange, } = useTableContext(); const rowId = getRowId?.(row); return { isChecked: selectedRowIds && rowId ? selectedRowIds.includes(rowId) : false, isDisabled: getIsRowDisabled?.(row) ?? false, isCheckboxDisabled: getIsRowCheckable ? !getIsRowCheckable(row) : false, onChange: (event: React.ChangeEvent) => rowId && onRowSelectionChange?.(row, rowId, event.target.checked), }; }