@shakibdshy/react-tablegrid
Version:
A modern, flexible, headless and advanced table component for React with grid layout
317 lines (312 loc) • 9.88 kB
text/typescript
import { ReactNode } from 'react';
/**
* Defines the structure of a table column
* @template T - Type of data being displayed in the table
*/
interface Column<T> {
/** Unique identifier for the column */
id: keyof T;
/** Header content or function to render header */
header: ReactNode | (() => ReactNode);
/** Key to access data in row object */
accessorKey: keyof T;
/** Whether the column is sortable */
sortable?: boolean;
/** Additional CSS classes for the column */
className?: string;
/** Width of the column */
width?: string;
/** Group name for the column */
group?: string;
/** Pin position for the column */
pinned?: 'left' | 'right' | false;
/** Custom cell renderer */
cell?: (props: {
value: T[keyof T];
row: T;
onChange?: (value: T[keyof T]) => void;
onDelete?: () => void;
table?: {
options: {
meta: {
updateData: UpdateDataFn<T>;
};
};
};
}) => ReactNode;
}
interface HeaderGroup<T> {
id: string;
name: string;
columns: Column<T>[];
}
/**
* Configuration for column resizing functionality
*/
interface ColumnResizeInfoState {
/** Starting X coordinate of resize operation */
startX: number | null;
/** Current X coordinate during resize */
currentX: number | null;
/** Change in X coordinate from start */
deltaX: number | null;
/** ID of column being resized or false if none */
isResizingColumn: string | false;
/** Initial widths of columns when resize started */
columnSizingStart: {
[key: string]: number;
};
}
type ColumnResizeMode = 'onChange' | 'onResize';
/**
* Type definitions for table events
*/
interface TableEventMap<T> {
/** Called when a column is sorted */
onSort: (column: Column<T>, direction: SortDirection) => void;
/** Called when the filter value changes */
onFilter: (value: string, filteredData: T[]) => void;
/** Called when a column is resized */
onColumnResize: (columnId: keyof T, width: number) => void;
/** Called when a column's visibility changes */
onColumnVisibilityChange: (columnId: keyof T, isVisible: boolean) => void;
/** Called when a column is pinned/unpinned */
onColumnPin: (columnId: keyof T, position: 'left' | 'right' | false) => void;
/** Called when a row is selected */
onRowSelect: (row: T, index: number) => void;
/** Called when the table state changes */
onStateChange: (state: TableState<T>) => void;
}
/**
* Configuration for server-side operations
*/
interface ServerSideConfig<T> {
enabled: boolean;
totalRows: number;
pageSize: number;
currentPage: number;
loading: boolean;
onFetch: (options: {
page: number;
pageSize: number;
sortColumn?: keyof T;
sortDirection?: SortDirection;
filters?: Record<string, unknown>;
}) => Promise<T[]>;
onPageChange?: (page: number) => void;
}
/**
* Configuration for virtualization
*/
interface VirtualizationConfig {
enabled: boolean;
rowHeight: number;
overscan: number;
scrollingDelay?: number;
initialScrollOffset?: number;
onEndReached?: () => void;
}
type TableVariant = "modern" | "minimal" | "classic";
type SortDirection = "asc" | "desc";
type UpdateDataFn<T> = (index: number, field: keyof T, value: T[keyof T]) => void;
interface TableState<T> {
data: T[];
sortColumn: keyof T;
sortDirection: SortDirection;
filterValue?: string;
visibleColumns: Array<keyof T>;
pinnedColumns: {
left: Array<keyof T>;
right: Array<keyof T>;
};
columnSizing: {
columnSizes: {
[key: string]: number;
};
};
columnResizeMode: ColumnResizeMode;
loading?: boolean;
}
interface TableCustomComponents<T> {
Header?: React.ComponentType<{
column: Column<T>;
sortIcon?: React.ReactNode;
onSort?: () => void;
}>;
Cell?: React.ComponentType<{
column: Column<T>;
row: T;
value: T[keyof T];
}>;
EmptyState?: React.ComponentType;
LoadingState?: React.ComponentType;
SearchInput?: React.ComponentType<{
value: string;
onChange: (value: string) => void;
placeholder?: string;
}>;
renderCell?: (row: T, rowIndex: number, value: unknown) => React.ReactNode;
renderLoading?: () => React.ReactNode;
renderEmpty?: () => React.ReactNode;
renderError?: (error: Error) => React.ReactNode;
}
interface TableStyleConfig {
container?: {
className?: string;
style?: React.CSSProperties;
wrapperClassName?: string;
scrollContainerClassName?: string;
tableClassName?: string;
};
header?: {
className?: string;
style?: React.CSSProperties;
headerRowClassName?: string;
TableColumnClassName?: string;
headerGroupClassName?: string;
};
body?: {
style?: React.CSSProperties;
className?: string;
rowClassName?: string;
cellClassName?: string;
};
resizer?: {
className?: string;
style?: React.CSSProperties;
};
resizerIndicator?: {
className?: string;
style?: React.CSSProperties;
};
sortButton?: {
className?: string;
style?: React.CSSProperties;
};
utilityStyles?: {
emptyClassName?: string;
searchContainerClassName?: string;
searchInputClassName?: string;
loadingClassName?: string;
style?: React.CSSProperties;
};
}
type FuseKeys<T> = Array<keyof T | string>;
interface TableCustomRender<T> {
renderHeader?: (column: Column<T>) => ReactNode;
renderCell?: (row: T, rowIndex: number, value: T[keyof T]) => ReactNode;
renderEmpty?: () => ReactNode;
renderLoading?: () => ReactNode;
renderSearch?: (props: {
value: string;
onChange: (value: string) => void;
placeholder?: string;
}) => ReactNode;
}
interface TableProps<T> {
columns: Column<T>[];
data: T[];
variant?: TableVariant;
className?: string;
sortColumn?: keyof T;
sortDirection?: SortDirection;
gridTemplateColumns?: string;
maxHeight?: string;
onRowChange?: UpdateDataFn<T>;
onRowDelete?: (index: number) => void;
meta?: {
updateData?: UpdateDataFn<T>;
};
filterValue?: string;
onFilterChange?: (value: string) => void;
filterPlaceholder?: string;
enableFiltering?: boolean;
headerGroups?: boolean;
enableFuzzySearch?: boolean;
fuzzySearchKeys?: FuseKeys<T>;
fuzzySearchThreshold?: number;
/** Whether column resizing is enabled. Defaults to false. */
enableColumnResize?: boolean;
components?: TableCustomComponents<T>;
styleConfig?: TableStyleConfig;
renderHeader?: (column: Column<T>) => ReactNode;
renderCell?: (column: Column<T>, row: T, value: T[keyof T]) => ReactNode;
renderEmpty?: () => ReactNode;
renderLoading?: () => ReactNode;
renderSearch?: (props: {
value: string;
onChange: (value: string) => void;
placeholder?: string;
}) => ReactNode;
isLoading?: boolean;
columnResizeMode?: ColumnResizeMode;
onColumnSizingChange?: (columnSizing: {
columnSizes: {
[key: string]: number;
};
}) => void;
columnResizeDirection?: "ltr" | "rtl";
columnResizeInfo?: ColumnResizeInfoState;
columnSizing?: {
columnSizes: {
[key: string]: number;
};
};
virtualization?: VirtualizationConfig;
serverSide?: ServerSideConfig<T>;
events?: Partial<TableEventMap<T>>;
}
interface TableGridReturn<T> {
data: T[];
setData: (data: T[]) => void;
sortColumn: keyof T;
sortDirection: SortDirection;
handleSort: (column: Column<T>) => void;
filterValue: string;
setFilterValue: (value: string) => void;
filteredData: T[];
state: TableState<T>;
resetState: () => void;
visibleColumns: Array<keyof T>;
toggleColumnVisibility: (columnId: keyof T) => void;
pinnedColumns: {
left: Array<keyof T>;
right: Array<keyof T>;
};
toggleColumnPin: (columnId: keyof T, position: "left" | "right" | false) => void;
}
interface TableContextValue<T> {
state: TableState<T>;
columns: Column<T>[];
data: T[];
filteredData: T[];
visibleColumns: Array<keyof T>;
toggleColumnVisibility: (columnId: keyof T) => void;
pinnedColumns: {
left: Array<keyof T>;
right: Array<keyof T>;
};
toggleColumnPin: (columnId: keyof T, position: "left" | "right" | false) => void;
sortColumn: keyof T;
sortDirection: SortDirection;
handleSort: (column: Column<T>) => void;
filterValue: string;
setFilterValue: (value: string) => void;
columnSizing: {
columnSizes: {
[key: string]: number;
};
};
columnResizeInfo: ColumnResizeInfoState;
columnResizeMode: "onChange" | "onResize";
columnResizeDirection: "ltr" | "rtl";
handleColumnResize: (columnId: string, width: number) => void;
handleColumnResizeStart: (columnId: string, startX: number) => void;
handleColumnResizeMove: (currentX: number) => void;
handleColumnResizeEnd: () => void;
handleRowSelect: (row: T, index: number) => void;
resetState: () => void;
setData: (data: T[]) => void;
handleStateChange: (state: TableState<T>) => void;
}
export type { Column, ColumnResizeInfoState, ColumnResizeMode, HeaderGroup, ServerSideConfig, SortDirection, TableContextValue, TableCustomComponents, TableCustomRender, TableEventMap, TableGridReturn, TableProps, TableState, TableStyleConfig, TableVariant, UpdateDataFn, VirtualizationConfig };