import React, { forwardRef, useState } from "react"; import { cl } from "../../../utils/helpers"; import { useMergeRefs } from "../../../utils/hooks"; import { DataTableCaption, type DataTableCaptionProps, } from "../caption/DataTableCaption"; import { DataTableEmptyState, type DataTableEmptyStateProps, } from "../empty-state/DataTableEmptyState"; import { useTableKeyboardNav } from "../hooks/useTableKeyboardNav"; import { type SelectionProps } from "../hooks/useTableSelection"; import { DataTableLoadingState, type DataTableLoadingStateProps, } from "../loading-state/DataTableLoadingState"; import { DataTableTbody, type DataTableTbodyProps, } from "../tbody/DataTableTbody"; import { DataTableTd, type DataTableTdProps } from "../td/DataTableTd"; import { DataTableTfoot, type DataTableTfootProps, } from "../tfoot/DataTableTfoot"; import { DataTableTh, type DataTableThProps } from "../th/DataTableTh"; import { DataTableThead, type DataTableTheadProps, } from "../thead/DataTableThead"; import { DataTableTr, type DataTableTrProps } from "../tr/DataTableTr"; import { DataTableContextProvider } from "./DataTableRoot.context"; interface DataTableProps extends React.HTMLAttributes, SelectionProps { children: React.ReactNode; /** * Controls vertical cell padding. * @default "normal" */ rowDensity?: "condensed" | "normal" | "spacious"; /** * Zebra striped table * @default false */ zebraStripes?: boolean; /** * Truncate content in cells and show ellipsis for overflowed text. * * **NB:** When using `layout="auto"`, you have to manually set a `maxWidth` on columns that should be truncated. * @default true */ truncateContent?: boolean; // TODO: Consider making this default false when layout=auto, and maybe disallow it but add a wrap prop on the td-comp. /** * Enables keyboard navigation for table rows and cells. * @default false */ withKeyboardNav?: boolean; /** * Custom callback to determine if navigation should be blocked. * Called before default blocking logic. * Requires `withKeyboardNav` to be `true`. */ shouldBlockNavigation?: (event: KeyboardEvent) => boolean; /** * Controls table layout. * * ### fixed * Gives you full control of column widths. This is required for resizable columns. * * ### auto * Makes the columns resize automatically based on the content. * The table will take up at least 100% of available width. * * **NB:** When using this with `truncateContent`, you have to manually * set a `contentMaxWidth` on cells that should be truncated. * @default "fixed" */ layout?: "fixed" | "auto"; } interface DataTableRootComponent extends React.ForwardRefExoticComponent< DataTableProps & React.RefAttributes > { /** * @see 🏷️ {@link DataTableCaptionProps} * @example * ```jsx * * * Lorem ipsum * * ``` */ Caption: typeof DataTableCaption; /** * @see 🏷️ {@link DataTableTheadProps} * @example * ```jsx * * * ... TODO * * * ``` */ Thead: typeof DataTableThead; /** * @see 🏷️ {@link DataTableTbodyProps} * @example * ```jsx * * * ... TODO * * * ``` */ Tbody: typeof DataTableTbody; /** * @see 🏷️ {@link DataTableTrProps} * @example * ```jsx * * * ... TODO * * ``` */ Tr: typeof DataTableTr; /** * @see 🏷️ {@link DataTableThProps} * @example * ```jsx * * * Header 1 * Header 2 * * * ``` */ Th: typeof DataTableTh; /** * @see 🏷️ {@link DataTableTdProps} * @example * ```jsx * * * * Lorem ipsum * * * Dolor sit amet * * * * ``` */ Td: typeof DataTableTd; /** * @see 🏷️ {@link DataTableTfootProps} * @example * ```jsx * * * ... * * * ``` */ Tfoot: typeof DataTableTfoot; /** * @see 🏷️ {@link DataTableEmptyStateProps} * @example * ```jsx * * * * * * ``` */ EmptyState: typeof DataTableEmptyState; /** * @see 🏷️ {@link DataTableEmptyStateProps} * @example * ```jsx * * * * * * ``` */ LoadingState: typeof DataTableLoadingState; } /** * TODO Component description etc. * * **NB:** To get sticky headers, you have to set a height restriction on the table container. You can use VStack for this: * TODO example */ const DataTable = forwardRef( ( { className, rowDensity = "normal", withKeyboardNav = false, zebraStripes = false, truncateContent = true, shouldBlockNavigation, layout = "fixed", ...rest }, forwardedRef, ) => { const [tableRef, setTableRef] = useState(null); const mergedRef = useMergeRefs(forwardedRef, setTableRef); const { tabIndex } = useTableKeyboardNav(tableRef, { enabled: withKeyboardNav, shouldBlockNavigation, }); return (
); }, ) as DataTableRootComponent; DataTable.Caption = DataTableCaption; DataTable.Thead = DataTableThead; DataTable.Tbody = DataTableTbody; DataTable.Th = DataTableTh; DataTable.Tr = DataTableTr; DataTable.Td = DataTableTd; DataTable.Tfoot = DataTableTfoot; DataTable.EmptyState = DataTableEmptyState; DataTable.LoadingState = DataTableLoadingState; export { DataTable, DataTableCaption, DataTableEmptyState, DataTableLoadingState, DataTableTbody, DataTableTd, DataTableTfoot, DataTableTh, DataTableThead, DataTableTr, }; export default DataTable; export type { DataTableCaptionProps, DataTableEmptyStateProps, DataTableLoadingStateProps, DataTableProps, DataTableTbodyProps, DataTableTdProps, DataTableTfootProps, DataTableTheadProps, DataTableThProps, DataTableTrProps, };