UNPKG

react-fluid-table

Version:

A React table inspired by @tanstack/react-virtual

370 lines (356 loc) 9.94 kB
import { CSSProperties, JSX, ReactNode } from "react"; export type SortDirection = "ASC" | "DESC"; export type ScrollAlignment = "start" | "center" | "end" | "auto"; export type ExpanderProps<T> = { /** * the data for the row */ row: T; /** * the index of the row */ index: number; /** * whether or not the row is expanded */ isExpanded: boolean; /** * handler for clicking the expansion button * @param event mouse event * @returns void */ onClick: (event?: React.MouseEvent<Element, MouseEvent>) => void; /** * required style for the expander */ style: CSSProperties; }; export type CellProps<T> = { /** * the data for the row */ row: T; /** * the index of the row */ index: number; /** * optional custom styles for each cell */ style?: CSSProperties; }; export type HeaderProps = { /** * the onclick handler for the header cell * @param e mouse event * @returns void */ onClick: (e: React.MouseEvent<Element, MouseEvent>) => void; /** * required style for the header */ style: CSSProperties; /** * the direction of the sort, if applicable */ sortDirection: SortDirection | null; }; export type SubComponentProps<T> = { /** * the data for the row */ row: T; /** * the index of the row */ index: number; /** * whether or not the row is expanded */ isExpanded: boolean; /** * exposes the widths of each column to the sub component */ widths: number[]; }; export type FooterProps<T> = { /** * exposes the widths of each column to the footer */ widths: number[]; /** * the rows in the table */ rows: T[]; }; export type FooterCellProps<T> = { /** * the column that the current footer cell is pulling from */ column: ColumnProps<T>; /** * the calculated width of the cell */ width: number; /** * all the rows in the table. this can be useful for aggregation */ rows: T[]; }; export type ColumnProps<T> = { /** * The unique identifier for a particular column. This is also used as an index * to get the particular value out of the row in order to display. */ key: string; /** * The name of the header column, or a component to return a customized header cell. */ header?: string | ((props: HeaderProps) => JSX.Element); /** * specify a custom className for the header. If `header` is NOT a string, this is ignored. */ headerClassname?: string; /** * specify a custom style for the header. If `header` is NOT a string, this is ignored. */ headerStyle?: CSSProperties; /** * The width of a column in pixels. If this is set, the column will not resize. */ width?: number; /** * The minimum width of a column in pixels. On resize, the column will never * dip below this width. */ minWidth?: number; /** * The maximum width of a column in pixels. On resize, the column will never * grow beyond this width. */ maxWidth?: number; /** * Determines whether or not a column is sortable. */ sortable?: boolean; /** * Determines whether or not the column is frozen during horizontal scrolling. */ frozen?: boolean; /** * Marks this cell as an expansion cell. The style is pre-determined, and does the * functionalitty of collapsing/expanding a row. */ expander?: boolean | ((props: ExpanderProps<T>) => ReactNode); /** * Used to render custom content inside of a cell. This is useful for rendering different * things inside of the react-fluid-table cell container. */ content?: string | number | ((props: CellProps<T>) => ReactNode | JSX.Element); /** * specify a custom className for the content. If `cell` is specified, this is ignored. */ contentClassname?: string | ((props: { row: T; index: number }) => string | undefined); /** * specify a custom style for the content. If `cell` is specified, this is ignored. */ contentStyle?: CSSProperties | ((props: { row: T; index: number }) => CSSProperties | undefined); /** * An advanced feature, this is used to render an entire cell, including the cell container. * The `content` prop is ignored if this property is enabled. */ cell?: (props: CellProps<T>) => JSX.Element; /** * specifies whether or not to display a footer cell */ footer?: (props: FooterCellProps<T>) => ReactNode | JSX.Element; }; export type TableRef = { /** * scrolls to a specific pixel offset * @param scrollOffset pixel offset */ scrollTo: (scrollOffset: number) => void; /** * * @param index the index of the row to scroll to * @param align where to align the row after scrolling * @returns */ scrollToItem: (index: number, align?: ScrollAlignment) => void; }; export type TableProps<T> = { // required props /** * A list of rows that are to be displayed in the table. */ data: T[]; /** * This property determines how each cell is going to be rendered. */ columns: ColumnProps<T>[]; // optional props /** * The id of the table. */ id?: string; /** * Optional className to override CSS styles. */ className?: string; /** * Function that is called when a header cell is sorted. */ onSort?: (col: string, dir: SortDirection | null) => void; /** * The column that is sorted by default. */ sortColumn?: string; /** * The direction that is sorted by default. */ sortDirection?: SortDirection | null; /** * Specify the height of the table in pixels. */ tableHeight?: number; /** * Specify the minimum height of the table in pixels. */ minTableHeight?: number; /** * Specify the maximum height of the table in pixels. */ maxTableHeight?: number; /** * Specify the width of the table in pixels. */ tableWidth?: number; /** * Specify the minimum width of any column. Default: `80`. */ minColumnWidth?: number; /** * The fixed height of each row in pixels. If `subComponent` is specified, * then this will be the fixed height of the portion of the row that is * NOT the subComponent. */ rowHeight?: number; /** * The estimated height of each row in pixels. This can be used to help mitigate any * "jank" in initial renders, as well as help calculate the table height when * `tableHeight` is not specified. */ estimatedRowHeight?: number; /** * specify a fixed header height */ headerHeight?: number; /** * specify a fixed footer height */ footerHeight?: number; /** * React styles used for customizing the table. */ style?: CSSProperties; /** * React styles used for customizing the header. */ headerStyle?: CSSProperties; /** * a className used to customize the header */ headerClassname?: string; /** * React styles used for customizing each row. Could be an object or * a function that takes the index or the row and returns an object. */ rowStyle?: CSSProperties | ((value: { row: T; index: number }) => CSSProperties | undefined); /** * React className used for customizing each row. Could be an object or * a function that takes the index or the row and returns an object. */ rowClassname?: string | ((value: { row: T; index: number }) => string); /** * React styles used for customizing the footer. */ footerStyle?: CSSProperties; /** * a className used to customize the footer */ footerClassname?: string; /** * an object that contains the expanded rows. can also be a function that takes the index * or row and returns a boolean. */ expandedRows?: | { [x: string | number]: boolean } | ((value: { row: T; index: number }) => boolean); /** * called when a row is expanded * @param value information about the row that is expanded/shrunk * @returns */ onExpandRow?: (value: { row: T; index: number; isExpanded: boolean; event?: React.MouseEvent<Element, MouseEvent>; }) => void; /** * generates a unique identifier for the row * @param row the row * @returns string or number representing the item key */ itemKey?: (row: T) => string | number; /** * controlls whether or not the footer is sticky. this is only used if * `footerComponent` is specified. */ stickyFooter?: boolean; /** * optionally add a footer. NOTE: this overrides the `footer` prop of a * column, so use wisely. This gives the user more control over how the * footer is rendered. Can return any value. */ footerComponent?: (props: FooterProps<T>) => ReactNode; /** * When a column has `expander`, this component will be rendered under the row. */ subComponent?: (props: SubComponentProps<T>) => ReactNode | JSX.Element; /** * The callback that gets called every time a row is clicked. */ onRowClick?: (data: { row: T; index: number; event?: React.MouseEvent<Element, MouseEvent>; }) => void; /** * Function to get more data when you reach the bottom of the table. If this returns * true, then when it reaches the bottom this function will run. If it returns false, then * we have exhausted all remaining data. */ onLoadRows?: () => Promise<boolean>; /** * boolean to determine if there is more data to be loaded. If omitted, then the * result of `onLoadRows` determines this. */ hasMoreData?: boolean; /** * Number of rows from the bottom to trigger loading more rows. This is ignored if * onLoadRows is not specified (default: 1). */ asyncOverscan?: number; /** * optional component that gets rendered at the bottom of the table */ endComponent?: (data: { isLoading: boolean; hasMoreData: boolean }) => ReactNode; }; /** * A virtualized table built on top of `@tanstack/react-virtual`. */ export const Table: <T>( props: TableProps<T> & { ref?: React.RefObject<TableRef | null> } ) => JSX.Element;