import { type DragEvent, useMemo } from 'react'; import Box from '@mui/material/Box'; import TableCell, { type TableCellProps } from '@mui/material/TableCell'; import { useTheme } from '@mui/material/styles'; import { type Theme } from '@mui/material/styles'; import { MRT_TableHeadCellColumnActionsButton } from './MRT_TableHeadCellColumnActionsButton'; import { MRT_TableHeadCellFilterContainer } from './MRT_TableHeadCellFilterContainer'; import { MRT_TableHeadCellFilterLabel } from './MRT_TableHeadCellFilterLabel'; import { MRT_TableHeadCellGrabHandle } from './MRT_TableHeadCellGrabHandle'; import { MRT_TableHeadCellResizeHandle } from './MRT_TableHeadCellResizeHandle'; import { MRT_TableHeadCellSortLabel } from './MRT_TableHeadCellSortLabel'; import { type MRT_ColumnVirtualizer, type MRT_Header, type MRT_RowData, type MRT_TableInstance, } from '../../types'; import { getCommonMRTCellStyles } from '../../utils/style.utils'; import { parseFromValuesOrFunc } from '../../utils/utils'; import { cellKeyboardShortcuts } from '../../utils/cell.utils'; export interface MRT_TableHeadCellProps extends TableCellProps { columnVirtualizer?: MRT_ColumnVirtualizer; header: MRT_Header; staticColumnIndex?: number; table: MRT_TableInstance; } export const MRT_TableHeadCell = ({ columnVirtualizer, header, staticColumnIndex, table, ...rest }: MRT_TableHeadCellProps) => { const theme = useTheme(); const { getState, options: { columnFilterDisplayMode, columnResizeDirection, columnResizeMode, enableKeyboardShortcuts, enableColumnActions, enableColumnDragging, enableColumnOrdering, enableColumnPinning, enableGrouping, enableMultiSort, layoutMode, mrtTheme: { draggingBorderColor }, muiTableHeadCellProps, }, refs: { tableHeadCellRefs }, setHoveredColumn, } = table; const { columnSizingInfo, density, draggingColumn, grouping, hoveredColumn, showColumnFilters, } = getState(); const { column } = header; const { columnDef } = column; const { columnDefType } = columnDef; const tableCellProps = { ...parseFromValuesOrFunc(muiTableHeadCellProps, { column, table }), ...parseFromValuesOrFunc(columnDef.muiTableHeadCellProps, { column, table, }), ...rest, }; const isColumnPinned = enableColumnPinning && columnDef.columnDefType !== 'group' && column.getIsPinned(); const showColumnActions = (enableColumnActions || columnDef.enableColumnActions) && columnDef.enableColumnActions !== false; const showDragHandle = enableColumnDragging !== false && columnDef.enableColumnDragging !== false && (enableColumnDragging || (enableColumnOrdering && columnDef.enableColumnOrdering !== false) || (enableGrouping && columnDef.enableGrouping !== false && !grouping.includes(column.id))); const headerPL = useMemo(() => { let pl = 0; if (column.getCanSort()) pl += 1; if (showColumnActions) pl += 1.75; if (showDragHandle) pl += 1.5; return pl; }, [showColumnActions, showDragHandle]); const draggingBorders = useMemo(() => { const showResizeBorder = columnSizingInfo.isResizingColumn === column.id && columnResizeMode === 'onChange' && !header.subHeaders.length; const borderStyle = showResizeBorder ? `2px solid ${draggingBorderColor} !important` : draggingColumn?.id === column.id ? `1px dashed ${theme.palette.grey[500]}` : hoveredColumn?.id === column.id ? `2px dashed ${draggingBorderColor}` : undefined; if (showResizeBorder) { return columnResizeDirection === 'ltr' ? { borderRight: borderStyle } : { borderLeft: borderStyle }; } const draggingBorders = borderStyle ? { borderLeft: borderStyle, borderRight: borderStyle, borderTop: borderStyle, } : undefined; return draggingBorders; }, [draggingColumn, hoveredColumn, columnSizingInfo.isResizingColumn]); const handleDragEnter = (_e: DragEvent) => { if (enableGrouping && hoveredColumn?.id === 'drop-zone') { setHoveredColumn(null); } if (enableColumnOrdering && draggingColumn && columnDefType !== 'group') { setHoveredColumn( columnDef.enableColumnOrdering !== false ? column : null, ); } }; const handleDragOver = (e: DragEvent) => { if (columnDef.enableColumnOrdering !== false) { e.preventDefault(); } }; const handleKeyDown = (event: React.KeyboardEvent) => { tableCellProps?.onKeyDown?.(event); cellKeyboardShortcuts({ event, cellValue: header.column.columnDef.header, table, header, }); }; const HeaderElement = parseFromValuesOrFunc(columnDef.Header, { column, header, table, }) ?? columnDef.header; return ( { if (node) { tableHeadCellRefs.current![column.id] = node; if (columnDefType !== 'group') { columnVirtualizer?.measureElement?.(node); } } }} tabIndex={enableKeyboardShortcuts ? 0 : undefined} {...tableCellProps} onKeyDown={handleKeyDown} sx={(theme: Theme) => ({ '& :hover': { '.MuiButtonBase-root': { opacity: 1, }, }, flexDirection: layoutMode?.startsWith('grid') ? 'column' : undefined, fontWeight: 'bold', overflow: 'visible', p: density === 'compact' ? '0.5rem' : density === 'comfortable' ? columnDefType === 'display' ? '0.75rem' : '1rem' : columnDefType === 'display' ? '1rem 1.25rem' : '1.5rem', pb: columnDefType === 'display' ? 0 : showColumnFilters || density === 'compact' ? '0.4rem' : '0.6rem', pt: columnDefType === 'group' || density === 'compact' ? '0.25rem' : density === 'comfortable' ? '.75rem' : '1.25rem', userSelect: enableMultiSort && column.getCanSort() ? 'none' : undefined, verticalAlign: 'top', ...getCommonMRTCellStyles({ column, header, table, tableCellProps, theme, }), ...draggingBorders, })} > {header.isPlaceholder ? null : (tableCellProps.children ?? ( {HeaderElement} {column.getCanFilter() && ( )} {column.getCanSort() && ( )} {columnDefType !== 'group' && ( {showDragHandle && ( )} {showColumnActions && ( )} )} {column.getCanResize() && ( )} ))} {columnFilterDisplayMode === 'subheader' && column.getCanFilter() && ( )} ); };