UNPKG

@payfit/unity-components

Version:

310 lines (309 loc) 13.2 kB
import { default as React, ReactNode } from 'react'; import { Row, RowData, Table as TableType } from '@tanstack/react-table'; import { TablePaginationProps } from '../table/parts/TablePagination.js'; import { TableProps, TableRootProps } from '../table/Table.js'; declare module '@tanstack/react-table' { interface ColumnMeta<TData extends RowData, TValue> { /** * Marks the cell as a row header. When true, the cell renders as `<th scope="row">` instead of `<td>`. * Use this for the first column that identifies each row (e.g., ID, name). Important for accessibility. * @default false * @example * ```ts * { * meta: { * isRowHeader: true * } * } * ``` */ isRowHeader?: boolean; /** * CSS classes to apply to table cells (`TableCell`) in this column. * Use this to control cell styling such as width, truncation, or alignment. * @example * ```ts * { * meta: { * className: 'uy:w-1/4 uy:truncate' * } * } * ``` */ className?: string; /** * Helper text to display as a tooltip icon next to the column header. * Use this to provide additional context or explanations for the column. * @example * ```ts * { * meta: { * helperText: 'This column shows the employee ID' * } * } * ``` */ helperText?: string; /** * Controls whether the column cells can receive keyboard focus during table navigation. * Set to false for cells containing interactive elements like buttons or checkboxes. * @default true * @example * ```ts * { * meta: { * isFocusable: false // For cells with buttons or checkboxes * } * } * ``` */ isFocusable?: boolean; /** * CSS classes to apply to the column header (`TableColumnHeader`). * Use this to set explicit widths when using `layout="fixed"`. * @example * ```ts * { * meta: { * headerClassName: 'uy:w-[200px]' // Fixed pixel width * // or * headerClassName: 'uy:w-1/4' // Percentage width * // or * headerClassName: 'uy:w-[20ch]' // Character-based width * } * } * ``` */ headerClassName?: string; } } export interface DataTablePaginationLabels { /** Label for the "rows per page" and pagination label dropdown */ itemLabel?: string; } export interface DataTablePaginationOptions { /** * Available options in the "rows per page" dropdown, see {@link TablePaginationProps['pageSizeOptions']} * @default [ * { value: '10', label: '10' }, * { value: '50', label: '50' }, * { value: '100', label: '100' }, * { value: '200', label: '200' }, * ] */ pageSizeOptions?: TablePaginationProps['pageSizeOptions']; /** * Custom labels for pagination, see {@link DataTablePaginationLabels} * @default { * itemLabel: 'unity:component:table:pagination:item', * } */ labels?: DataTablePaginationLabels; } export interface DataTableProps<TData> extends Omit<TableRootProps, 'children'>, Omit<TableProps, 'children'> { /** The table instance from @tanstack/react-table */ table: TableType<TData>; /** * Optional loading state * @default false */ isLoading?: boolean; /** * Optional error state * @default null */ error?: Error | null; /** * Custom empty state when there's no data. Use it to override the default empty state. * @default <TableEmptyStateNoData /> */ emptyState?: React.ReactNode; /** * Custom loading state to show when `isLoading` is true. Use it to override the default loading state. * @default <TableEmptyStateLoading /> */ loadingState?: React.ReactNode; /** * Custom error state to show when `error` prop is not null. Use it to override the default error state. * @default <TableEmptyStateError /> */ errorState?: React.ReactNode; /** * Pagination customization options, including page size options and labels * @default { * pageSizeOptions: [ * { value: '10', label: '10' }, * { value: '50', label: '50' }, * { value: '100', label: '100' }, * { value: '200', label: '200' }, * ], * labels: { * itemLabel: 'unity:component:table:pagination:item', * }, * } */ pagination?: DataTablePaginationOptions; /** * Callback fired when the current tablepage changes * @param page - The new page number * @param previous - The previous page number * @param direction - The direction of navigation (1 for forward, -1 for backward) */ onPageChange?: TablePaginationProps['onPageChange']; /** * A callback function that is triggered when a page is hovered over in the pagination component. * * This function is intended for handling hover events on individual pagination controls or elements. * It is derived from the `onPageHover` property in the `Pagination` component. */ onPageHover?: TablePaginationProps['onPageHover']; /** * Callback fired when the number of rows per page changes * @param pageSize - The new number of rows per page */ onPageSizeChange?: TablePaginationProps['onPageSizeChange']; /** * Render function for table rows * @param row - The row data of a given row in the table */ children: (row: Row<TData>) => React.ReactNode; /** * Optional callback fired when the button is clicked in the error state. * Used to navigate away or retry when data loading fails. * If not provided, the button won't be rendered. */ onErrorButtonPress?: () => void; /** * Optional callback fired when the button is clicked in the no data state. * Typically used to help users configure settings when no data is available. * If not provided, the button won't be rendered. */ onNoDataButtonPress?: () => void; /** * Optional description text displayed in the no data empty state. * This should explain to users why there is no data and what they can do about it. * If not provided, a default empty state will be shown. */ noDataDescription?: ReactNode; /** * Optional callback fired when the button is clicked in the no search results state. * Typically used to reset filters when a search returns no results. * If provided and filters are active with 0 results, TableNoSearchResults will be shown instead of the default empty state. */ onNoSearchResultsButtonPress?: () => void; } /** * A powerful and flexible data table component that integrates Unity's Table with @tanstack/react-table * * The DataTable component provides a standardized way to display tabular data with built-in support for * pagination, sorting, filtering, and row selection. It handles common table patterns like loading states, * empty states, and consistent table heights. * * The component supports two layout modes via the `layout` prop: * - **Auto layout** (default): Columns adapt to content with horizontal scrolling * - **Fixed layout**: Explicit column widths that fit the container. Set widths using `headerClassName` in column meta. * @param props - The props for the `DataTable` component * @param props.table - The table instance from @tanstack/react-table * @param props.minRows - The minimum number of rows to display, affecting the minimum height * @param props.maxRows - The maximum number of rows to display, affecting the maximum height * @param props.layout - Table layout algorithm: 'auto' (default) or 'fixed'. See {@link TableProps['layout']} * @param props.isLoading - Custom loading state to show when isLoading is true * @param props.error - Custom error state * @param props.emptyState - Custom empty state to show when there's no data * @param props.loadingState - Custom loading state to show when `isLoading` is true * @param props.errorState - Custom error state to show when `error` is not null * @param props.pagination - Optional pagination customization, see {@link DataTablePaginationOptions} * @param props.onPageChange - Optional callback for pagination change * @param props.onPageHover - Optional callback for pagination hover * @param props.onPageSizeChange - Optional callback for pagination size change * @param props.enableVirtualization - Enable internal scroll virtualization for large datasets * @param props.estimatedRowHeight - Estimated row height in pixels for the virtualizer * @param props.overscan - Number of extra rows rendered above/below viewport for virtualization * @param props.onErrorButtonPress - Callback for the button in error state * @param props.onNoDataButtonPress - Callback for the button in no data state * @param props.noDataDescription - Description text shown in the no data empty state * @param props.onNoSearchResultsButtonPress - Callback for the button in no search results state * @param props.children - Render function that takes care of rendering the table rows * @see {@link DataTableProps} for all available props * @example * ```tsx * import { DataTableRoot, DataTable, DataTableBulkActions, TableRow, TableCell } from '@payfit/unity-components' * import { flexRender, useReactTable, getCoreRowModel, getPaginationRowModel, createColumnHelper } from '@tanstack/react-table' * import { useState, useMemo } from 'react' * * function EmployeeTable() { * const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: 10 }) * const [rowSelection, setRowSelection] = useState({}) * * const columnHelper = createColumnHelper<Employee>() * * // Define columns with optional width control for fixed layout * const columns = useMemo(() => [ * columnHelper.accessor('name', { * header: 'Name', * meta: { * isRowHeader: true, * headerClassName: 'uy:w-[200px]' // Set explicit width for fixed layout * } * }), * columnHelper.accessor('position', { * header: 'Position', * meta: { * headerClassName: 'uy:w-1/3' // Use percentage for proportional width * } * }), * columnHelper.accessor('department', { * header: 'Department' * // No headerClassName: will share remaining space * }) * ], []) * * const table = useReactTable({ * data: employees, * columns, * getRowId: (row) => row.id, * state: { pagination, rowSelection }, * onPaginationChange: setPagination, * onRowSelectionChange: setRowSelection, * getCoreRowModel: getCoreRowModel(), * getPaginationRowModel: getPaginationRowModel(), * enableRowSelection: true, * enableMultiRowSelection: true, * }) * * return ( * <DataTableRoot> * <DataTable * table={table} * minRows={5} * maxRows={10} * layout="fixed" // Use fixed layout with explicit column widths * > * {row => ( * <TableRow key={row.id} isSelected={row.getIsSelected()}> * {row.getVisibleCells().map(cell => ( * <TableCell key={cell.id}> * {flexRender(cell.column.columnDef.cell, cell.getContext())} * </TableCell> * ))} * </TableRow> * )} * </DataTable> * <DataTableBulkActions table={table} actions={actions} /> * </DataTableRoot> * ) * } * ``` * @remarks * - For bulk actions, use DataTableBulkActions component alongside DataTable within DataTableRoot * - DataTableBulkActions provides the F6 keyboard shortcut for accessibility * - **Layout modes**: Use `layout="auto"` (default) for content-driven columns with scrolling, or `layout="fixed"` for predictable widths that fit the container * - **Setting column widths**: Add `headerClassName` to column meta with width classes (e.g., `'uy:w-[200px]'`, `'uy:w-1/3'`) * - **Fixed layout best practices**: Set explicit widths on column headers and use truncation for overflow content * - [API](https://unity-components.payfit.io/?path=/docs/data-datatable--docs) • [Demo](https://unity-components.payfit.io/?path=/docs/data-datatable--docs) */ declare function DataTable<TData extends object>({ table, isLoading, error, emptyState, loadingState, errorState, pagination, minRows, maxRows, onPageChange: onPaginationChange, onPageHover: onPaginationPageHover, onPageSizeChange: onPaginationSizeChange, children, enableVirtualization, estimatedRowHeight, overscan, onErrorButtonPress, onNoDataButtonPress, noDataDescription, onNoSearchResultsButtonPress, ...rest }: DataTableProps<TData>): import("react/jsx-runtime").JSX.Element; declare namespace DataTable { var displayName: string; } export { DataTable };