import { memo, useMemo } from 'react'; import { useVirtualizer } from '@tanstack/react-virtual'; import { Box, Text } from '@mantine/core'; import { Memo_MRT_TableBodyRow, MRT_TableBodyRow } from './MRT_TableBodyRow'; import { rankGlobalFuzzy } from '../sortingFns'; import { getCanRankRows } from '../column.utils'; import { type MRT_Row, type MRT_TableInstance, type MRT_VirtualItem, type MRT_Virtualizer, } from '../types'; interface Props = {}> { columnVirtualizer?: MRT_Virtualizer; enableHover?: boolean; isStriped?: boolean; table: MRT_TableInstance; virtualColumns?: MRT_VirtualItem[]; virtualPaddingLeft?: number; virtualPaddingRight?: number; } export const MRT_TableBody = = {}>({ columnVirtualizer, enableHover, isStriped, table, virtualColumns, virtualPaddingLeft, virtualPaddingRight, }: Props) => { const { getRowModel, getPrePaginationRowModel, getState, options: { createDisplayMode, enableGlobalFilterRankedResults, enablePagination, enableRowVirtualization, layoutMode, localization, mantineTableBodyProps, manualExpanding, manualFiltering, manualGrouping, manualPagination, manualSorting, memoMode, renderEmptyRowsFallback, rowVirtualizerInstanceRef, rowVirtualizerProps, }, refs: { tableContainerRef, tablePaperRef }, } = table; const { creatingRow, columnFilters, density, expanded, globalFilter, pagination, sorting, } = getState(); const tableBodyProps = mantineTableBodyProps instanceof Function ? mantineTableBodyProps({ table }) : mantineTableBodyProps; const vProps = rowVirtualizerProps instanceof Function ? rowVirtualizerProps({ table }) : rowVirtualizerProps; const shouldRankRows = useMemo( () => getCanRankRows(table) && !Object.values(sorting).some(Boolean) && globalFilter, [ enableGlobalFilterRankedResults, expanded, globalFilter, manualExpanding, manualFiltering, manualGrouping, manualSorting, sorting, ], ); const rows = useMemo(() => { if (!shouldRankRows) return getRowModel().rows; const rankedRows = getPrePaginationRowModel().rows.sort((a, b) => rankGlobalFuzzy(a, b), ); if (enablePagination && !manualPagination) { const start = pagination.pageIndex * pagination.pageSize; return rankedRows.slice(start, start + pagination.pageSize); } return rankedRows; }, [ shouldRankRows, shouldRankRows ? getPrePaginationRowModel().rows : getRowModel().rows, pagination.pageIndex, pagination.pageSize, ]); const rowVirtualizer: | MRT_Virtualizer | undefined = enableRowVirtualization ? useVirtualizer({ count: rows.length, estimateSize: () => density === 'xs' ? 42.7 : density === 'md' ? 54.7 : 70.7, getScrollElement: () => tableContainerRef.current, measureElement: typeof window !== 'undefined' && navigator.userAgent.indexOf('Firefox') === -1 ? (element) => element?.getBoundingClientRect().height : undefined, overscan: 4, ...vProps, }) : undefined; if (rowVirtualizerInstanceRef && rowVirtualizer) { rowVirtualizerInstanceRef.current = rowVirtualizer; } const virtualRows = rowVirtualizer ? rowVirtualizer.getVirtualItems() : undefined; return ( ({ display: layoutMode === 'grid' ? 'grid' : 'table-row-group', height: rowVirtualizer ? `${rowVirtualizer.getTotalSize()}px` : 'inherit', minHeight: !rows.length ? '100px' : undefined, position: 'relative', ...(tableBodyProps?.sx instanceof Function ? tableBodyProps?.sx(theme) : (tableBodyProps?.sx as any)), })} > {creatingRow && createDisplayMode === 'row' && ( )} {!rows.length ? ( {renderEmptyRowsFallback?.({ table }) ?? ( {globalFilter || columnFilters.length ? localization.noResultsFound : localization.noRecordsToDisplay} )} ) : ( <> {(virtualRows ?? rows).map((rowOrVirtualRow, rowIndex) => { const row = rowVirtualizer ? rows[rowOrVirtualRow.index] : (rowOrVirtualRow as MRT_Row); const props = { columnVirtualizer, enableHover, isStriped, measureElement: rowVirtualizer?.measureElement, numRows: rows.length, row, rowIndex: rowVirtualizer ? rowOrVirtualRow.index : rowIndex, table, virtualColumns, virtualPaddingLeft, virtualPaddingRight, virtualRow: rowVirtualizer ? (rowOrVirtualRow as MRT_VirtualItem) : undefined, }; return memoMode === 'rows' ? ( ) : ( ); })} )} ); }; export const Memo_MRT_TableBody = memo( MRT_TableBody, (prev, next) => prev.table.options.data === next.table.options.data, ) as typeof MRT_TableBody;