import clsx from 'clsx'; import classes from './MRT_TableHeadCell.module.css'; import { type CSSProperties, type DragEventHandler, type ReactNode, type RefObject, useMemo, useState, } from 'react'; import { Flex, TableTh, type TableThProps, useDirection } from '@mantine/core'; import { useHover } from '@mantine/hooks'; 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 { parseCSSVarId } from '../../utils/style.utils'; import { parseFromValuesOrFunc } from '../../utils/utils'; import { MRT_ColumnActionMenu } from '../menus/MRT_ColumnActionMenu'; interface Props extends TableThProps { columnVirtualizer?: MRT_ColumnVirtualizer; header: MRT_Header; renderedHeaderIndex?: number; table: MRT_TableInstance; } export const MRT_TableHeadCell = ({ columnVirtualizer, header, renderedHeaderIndex = 0, table, ...rest }: Props) => { 'use no memo'; const direction = useDirection(); const { getState, options: { columnFilterDisplayMode, columnResizeDirection, columnResizeMode, enableColumnActions, enableColumnDragging, enableColumnOrdering, enableColumnPinning, enableGrouping, enableHeaderActionsHoverReveal, enableMultiSort, layoutMode, mantineTableHeadCellProps, }, refs: { tableHeadCellRefs }, setHoveredColumn, } = table; const { columnSizingInfo, draggingColumn, grouping, hoveredColumn } = getState(); const { column } = header; const { columnDef } = column; const { columnDefType } = columnDef; const arg = { column, table }; const tableCellProps = { ...parseFromValuesOrFunc(mantineTableHeadCellProps, arg), ...parseFromValuesOrFunc(columnDef.mantineTableHeadCellProps, arg), ...rest, }; const widthStyles: CSSProperties = { minWidth: `max(calc(var(--header-${parseCSSVarId( header?.id, )}-size) * 1px), ${columnDef.minSize ?? 30}px)`, width: `calc(var(--header-${parseCSSVarId(header.id)}-size) * 1px)`, }; if (layoutMode === 'grid') { widthStyles.flex = `${ [0, false].includes(columnDef.grow!) ? 0 : `var(--header-${parseCSSVarId(header.id)}-size)` } 0 auto`; } else if (layoutMode === 'grid-no-grow') { widthStyles.flex = `${+(columnDef.grow || 0)} 0 auto`; } const isColumnPinned = enableColumnPinning && columnDef.columnDefType !== 'group' && column.getIsPinned(); const isDraggingColumn = draggingColumn?.id === column.id; const isHoveredColumn = hoveredColumn?.id === column.id; const { hovered: isHoveredHeadCell, ref: isHoveredHeadCellRef } = useHover(); const [isOpenedColumnActions, setIsOpenedColumnActions] = useState(false); const columnActionsEnabled = (enableColumnActions || columnDef.enableColumnActions) && columnDef.enableColumnActions !== false; const showColumnButtons = !enableHeaderActionsHoverReveal || isOpenedColumnActions || (isHoveredHeadCell && !table.getVisibleFlatColumns().find((column) => column.getIsResizing())); const showDragHandle = enableColumnDragging !== false && columnDef.enableColumnDragging !== false && (enableColumnDragging || (enableColumnOrdering && columnDef.enableColumnOrdering !== false) || (enableGrouping && columnDef.enableGrouping !== false && !grouping.includes(column.id))) && showColumnButtons; const headerPL = useMemo(() => { let pl = 0; if (column.getCanSort()) pl++; // Only add padding for buttons if they will actually be displayed if (showColumnButtons && (columnActionsEnabled || showDragHandle)) pl += 1.75; if (showDragHandle) pl += 1.25; return pl; }, [showColumnButtons, showDragHandle, columnActionsEnabled]); const handleDragEnter: DragEventHandler = (_e) => { if (enableGrouping && hoveredColumn?.id === 'drop-zone') { setHoveredColumn(null); } if (enableColumnOrdering && draggingColumn && columnDefType !== 'group') { setHoveredColumn( columnDef.enableColumnOrdering !== false ? column : null, ); } }; const headerElement = columnDef?.Header instanceof Function ? columnDef?.Header?.({ column, header, table, }) : (columnDef?.Header ?? (columnDef.header as ReactNode)); return ( { if (node) { tableHeadCellRefs.current[column.id] = node; if (typeof isHoveredHeadCellRef === 'function') { isHoveredHeadCellRef(node); } else if (isHoveredHeadCellRef) { ( isHoveredHeadCellRef as RefObject ).current = node; } if (columnDefType !== 'group') { columnVirtualizer?.measureElement?.(node); } } }} style={(theme) => ({ ...widthStyles, ...parseFromValuesOrFunc(tableCellProps?.style, theme), })} > {header.isPlaceholder ? null : (tableCellProps.children ?? ( {headerElement} {column.getCanFilter() && (column.getIsFiltered() || showColumnButtons) && ( )} {column.getCanSort() && (column.getIsSorted() || showColumnButtons) && ( )} {columnDefType !== 'group' && ( {showDragHandle && ( )} {columnActionsEnabled && showColumnButtons && ( )} )} {column.getCanResize() && ( )} ))} {columnFilterDisplayMode === 'subheader' && column.getCanFilter() && ( )} ); };