@payfit/unity-components
Version:
310 lines (309 loc) • 13.2 kB
TypeScript
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 };