'use client'; import { Cell, ColumnSort, createColumnHelper, flexRender, getCoreRowModel, getPaginationRowModel, getSortedRowModel, Header, HeaderGroup, PaginationState, Row, RowData, type RowSelectionState, SortingState, TableOptions, useReactTable, type VisibilityState } from '@tanstack/react-table'; import { useState } from 'react'; import DefaultNoData from './DefaultNoData'; import PaginationTools from './PaginationTools'; import SelectAll from './SelectAll'; import SelectRow from './SelectRow'; import SortingIcon from './SortingIcon'; export { createColumnHelper, type ColumnSort, type RowSelectionState, type VisibilityState }; export interface IConditionalStyle { when: (rowData: TData) => boolean style: React.CSSProperties } export interface DataTableProps extends Pick, 'data' | 'columns' | 'onRowSelectionChange' | 'onColumnVisibilityChange' > { dense?: boolean headPosition?: string noHeader?: boolean noFooter?: boolean conditionalRowStyles?: IConditionalStyle[] onRowClicked?: (rowData: TData, event: React.MouseEvent) => void onRowDoubleClicked?: (rowData: TData, event: React.MouseEvent) => void noDataComponent?: React.ReactNode enableRowSelection?: boolean rowSelection?: RowSelectionState enableHiding?: boolean columnVisibility?: VisibilityState enablePagination?: boolean paginationPerPage?: number paginationOptions?: number[] onChangePaginationOption?: (newValue: number) => void enableSorting?: boolean initialSorting?: ColumnSort } /** * UI element: data representation as a table. * * @param headPosition - Top position of sticky header (0 if no other sticky elements are present). * No sticky header if omitted */ function DataTable({ dense, headPosition, conditionalRowStyles, noFooter, noHeader, onRowClicked, onRowDoubleClicked, noDataComponent, enableRowSelection, rowSelection, enableHiding, columnVisibility, enableSorting, initialSorting, enablePagination, paginationPerPage=10, paginationOptions=[10, 20, 30, 40, 50], onChangePaginationOption, ...restProps }: DataTableProps) { const [sorting, setSorting] = useState(initialSorting ? [initialSorting] : []); const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: paginationPerPage, }); const tableImpl = useReactTable({ getCoreRowModel: getCoreRowModel(), getSortedRowModel: enableSorting ? getSortedRowModel() : undefined, getPaginationRowModel: enablePagination ? getPaginationRowModel() : undefined, state: { pagination: pagination, sorting: sorting, rowSelection: rowSelection ?? {}, columnVisibility: columnVisibility ?? {} }, enableHiding: enableHiding, onPaginationChange: enablePagination ? setPagination : undefined, onSortingChange: enableSorting ? setSorting : undefined, enableMultiRowSelection: enableRowSelection, ...restProps }); const isEmpty = tableImpl.getRowModel().rows.length === 0; function getRowStyles(row: Row) { return ({...conditionalRowStyles! .filter(item => item.when(row.original)) .reduce((prev, item) => ({...prev, ...item.style}), {}) }); } return (
{!noHeader ? {tableImpl.getHeaderGroups().map( (headerGroup: HeaderGroup) => ( {enableRowSelection ? : null} {headerGroup.headers.map( (header: Header) => ( ))} ))} : null} {tableImpl.getRowModel().rows.map( (row: Row, index) => ( {enableRowSelection ? : null} {row.getVisibleCells().map( (cell: Cell) => ( ))} ))} {!noFooter ? {tableImpl.getFooterGroups().map( (footerGroup: HeaderGroup) => ( {footerGroup.headers.map( (header: Header) => ( ))} ))} : null}
100 ? 'left': 'center', width: header.getSize(), cursor: enableSorting && header.column.getCanSort() ? 'pointer': 'auto', }} onClick={enableSorting ? header.column.getToggleSortingHandler() : undefined} > {!header.isPlaceholder ? (
{flexRender(header.column.columnDef.header, header.getContext())} {(enableSorting && header.column.getCanSort()) ? : null}
) : null}
onRowClicked ? onRowClicked(row.original, event) : undefined} onDoubleClick={event => onRowDoubleClicked ? onRowDoubleClicked(row.original, event) : undefined} > {flexRender(cell.column.columnDef.cell, cell.getContext())}
{!header.isPlaceholder ? flexRender(header.column.columnDef.footer, header.getContext()) : null}
{(enablePagination && !isEmpty) ? : null}
{isEmpty ? (noDataComponent ?? ) : null}
); } export default DataTable;