import { useTable, useFilters, useGlobalFilter, useSortBy, usePagination, Column, Row, TableInstance, TableState, TableRowProps, useExpanded, } from 'react-table'; import { ReactNode } from 'react'; import { useRowSelectColumn } from '@lineup-lite/hooks'; import clsx from 'clsx'; import { IconProps } from '@@/Icon'; import { Table } from './Table'; import { multiple } from './filter-types'; import { useRowSelect } from './useRowSelect'; import { BasicTableSettings } from './types'; import { DatatableHeader } from './DatatableHeader'; import { DatatableFooter } from './DatatableFooter'; import { DatatableContent } from './DatatableContent'; import { defaultGetRowId } from './defaultGetRowId'; import { emptyPlugin } from './emptyReactTablePlugin'; import { useGoToHighlightedRow } from './useGoToHighlightedRow'; export interface Props> { dataset: D[]; columns: readonly Column[]; renderTableSettings?(instance: TableInstance): ReactNode; renderTableActions?(selectedRows: D[]): ReactNode; disableSelect?: boolean; getRowId?(row: D): string; isRowSelectable?(row: Row): boolean; emptyContentLabel?: string; title?: string; titleIcon?: IconProps['icon']; initialTableState?: Partial>; isLoading?: boolean; totalCount?: number; description?: ReactNode; pageCount?: number; initialSortBy?: BasicTableSettings['sortBy']; initialPageSize?: BasicTableSettings['pageSize']; highlightedItemId?: string; searchValue: string; onSearchChange(search: string): void; onSortByChange(colId: string, desc: boolean): void; onPageSizeChange(pageSize: number): void; // send state up onPageChange?(page: number): void; renderRow?( row: Row, rowProps: TableRowProps, highlightedItemId?: string ): ReactNode; expandable?: boolean; noWidget?: boolean; } export function Datatable>({ columns, dataset, renderTableSettings = () => null, renderTableActions = () => null, disableSelect, getRowId = defaultGetRowId, isRowSelectable = () => true, title, titleIcon, emptyContentLabel, initialTableState = {}, isLoading, totalCount = dataset.length, description, pageCount, initialSortBy, initialPageSize = 10, onPageChange = () => {}, onPageSizeChange, onSortByChange, searchValue, onSearchChange, renderRow = defaultRenderRow, expandable = false, highlightedItemId, noWidget, }: Props) { const isServerSidePagination = typeof pageCount !== 'undefined'; const tableInstance = useTable( { defaultCanFilter: false, columns, data: dataset, filterTypes: { multiple }, initialState: { pageSize: initialPageSize, sortBy: initialSortBy ? [initialSortBy] : [], globalFilter: searchValue, ...initialTableState, }, isRowSelectable, autoResetExpanded: false, autoResetSelectedRows: false, getRowId, ...(isServerSidePagination ? { manualPagination: true, pageCount } : {}), }, useFilters, useGlobalFilter, useSortBy, expandable ? useExpanded : emptyPlugin, usePagination, useRowSelect, !disableSelect ? useRowSelectColumn : emptyPlugin ); useGoToHighlightedRow( isServerSidePagination, tableInstance.state.pageSize, tableInstance.rows, handlePageChange, highlightedItemId ); const selectedItems = tableInstance.selectedFlatRows.map( (row) => row.original ); return ( renderTableActions(selectedItems)} renderTableSettings={() => renderTableSettings(tableInstance)} description={description} /> tableInstance={tableInstance} renderRow={(row, rowProps) => renderRow(row, rowProps, highlightedItemId) } emptyContentLabel={emptyContentLabel} isLoading={isLoading} onSortChange={handleSortChange} /> ); function handleSearchBarChange(value: string) { tableInstance.setGlobalFilter(value); onSearchChange(value); } function handlePageChange(page: number) { tableInstance.gotoPage(page); onPageChange(page); } function handleSortChange(colId: string, desc: boolean) { onSortByChange(colId, desc); } function handlePageSizeChange(pageSize: number) { tableInstance.setPageSize(pageSize); onPageSizeChange(pageSize); } } function defaultRenderRow>( row: Row, rowProps: TableRowProps, highlightedItemId?: string ) { return ( key={rowProps.key} cells={row.cells} className={clsx(rowProps.className, { active: highlightedItemId === row.id, })} role={rowProps.role} style={rowProps.style} /> ); }