import { memo, useMemo } from 'react'; import { type VirtualItem } from '@tanstack/react-virtual'; import TableBody, { type TableBodyProps } from '@mui/material/TableBody'; import Typography from '@mui/material/Typography'; import { MRT_TableBodyRow, Memo_MRT_TableBodyRow } from './MRT_TableBodyRow'; import { useMRT_RowVirtualizer } from '../../hooks/useMRT_RowVirtualizer'; import { useMRT_Rows } from '../../hooks/useMRT_Rows'; import { type MRT_ColumnVirtualizer, type MRT_Row, type MRT_RowData, type MRT_TableInstance, } from '../../types'; import { parseFromValuesOrFunc } from '../../utils/utils'; export interface MRT_TableBodyProps extends TableBodyProps { columnVirtualizer?: MRT_ColumnVirtualizer; table: MRT_TableInstance; } export const MRT_TableBody = ({ columnVirtualizer, table, ...rest }: MRT_TableBodyProps) => { const { getBottomRows, getIsSomeRowsPinned, getRowModel, getState, getTopRows, options: { enableStickyFooter, enableStickyHeader, layoutMode, localization, memoMode, muiTableBodyProps, renderDetailPanel, renderEmptyRowsFallback, rowPinningDisplayMode, }, refs: { tableFooterRef, tableHeadRef, tablePaperRef }, } = table; const { columnFilters, globalFilter, isFullScreen, rowPinning } = getState(); const tableBodyProps = { ...parseFromValuesOrFunc(muiTableBodyProps, { table }), ...rest, }; const tableHeadHeight = ((enableStickyHeader || isFullScreen) && tableHeadRef.current?.clientHeight) || 0; const tableFooterHeight = (enableStickyFooter && tableFooterRef.current?.clientHeight) || 0; const pinnedRowIds = useMemo(() => { if (!rowPinning.bottom?.length && !rowPinning.top?.length) return []; return getRowModel() .rows.filter((row) => row.getIsPinned()) .map((r) => r.id); }, [rowPinning, getRowModel().rows]); const rows = useMRT_Rows(table); const rowVirtualizer = useMRT_RowVirtualizer(table, rows); const { virtualRows } = rowVirtualizer ?? {}; const commonRowProps = { columnVirtualizer, numRows: rows.length, table, }; return ( <> {!rowPinningDisplayMode?.includes('sticky') && getIsSomeRowsPinned('top') && ( ({ display: layoutMode?.startsWith('grid') ? 'grid' : undefined, position: 'sticky', top: tableHeadHeight - 1, zIndex: 1, ...(parseFromValuesOrFunc(tableBodyProps?.sx, theme) as any), })} > {getTopRows().map((row, staticRowIndex) => { const props = { ...commonRowProps, row, staticRowIndex, }; return memoMode === 'rows' ? ( ) : ( ); })} )} ({ display: layoutMode?.startsWith('grid') ? 'grid' : undefined, height: rowVirtualizer ? `${rowVirtualizer.getTotalSize()}px` : undefined, minHeight: !rows.length ? '100px' : undefined, position: 'relative', ...(parseFromValuesOrFunc(tableBodyProps?.sx, theme) as any), })} > {tableBodyProps?.children ?? (!rows.length ? ( {renderEmptyRowsFallback?.({ table }) ?? ( {globalFilter || columnFilters.length ? localization.noResultsFound : localization.noRecordsToDisplay} )} ) : ( <> {(virtualRows ?? rows).map((rowOrVirtualRow, staticRowIndex) => { let row = rowOrVirtualRow as MRT_Row; if (rowVirtualizer) { if (renderDetailPanel) { if (rowOrVirtualRow.index % 2 === 1) { return null; } else { staticRowIndex = rowOrVirtualRow.index / 2; } } else { staticRowIndex = rowOrVirtualRow.index; } row = rows[staticRowIndex]; } const props = { ...commonRowProps, pinnedRowIds, row, rowVirtualizer, staticRowIndex, virtualRow: rowVirtualizer ? (rowOrVirtualRow as VirtualItem) : undefined, }; const key = `${row.id}-${row.index}`; return memoMode === 'rows' ? ( ) : ( ); })} ))} {!rowPinningDisplayMode?.includes('sticky') && getIsSomeRowsPinned('bottom') && ( ({ bottom: tableFooterHeight - 1, display: layoutMode?.startsWith('grid') ? 'grid' : undefined, position: 'sticky', zIndex: 1, ...(parseFromValuesOrFunc(tableBodyProps?.sx, theme) as any), })} > {getBottomRows().map((row, staticRowIndex) => { const props = { ...commonRowProps, row, staticRowIndex, }; 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;