UNPKG

@shakibdshy/react-tablegrid

Version:

A modern, flexible, headless and advanced table component for React with grid layout

317 lines (312 loc) 9.88 kB
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 };