CRMTableHeader.tsx3.6 KBView on GitHub import { SortableColumnHeader } from './sortable-column-header';
import type { CRMColumn } from '../store/crmSlice';
import { Reorder } from 'motion/react';
import { memo } from 'react';
const DEFAULT_COLUMN_WIDTH = 200;
interface CRMTableHeaderProps {
columnsConfig: CRMColumn[];
columnWidths: Record<string, number>;
totalSize: number;
onReorder: (newOrder: CRMColumn[]) => void;
onUpdateColumn?: (column: CRMColumn) => void;
onDeleteColumn?: (columnId: string) => void;
onResizeStart?: (columnId: string, startX: number, startWidth: number) => void;
}
export const CRMTableHeader = memo(
function CRMTableHeader({
columnsConfig,
columnWidths,
totalSize,
onReorder,
onUpdateColumn,
onDeleteColumn,
onResizeStart,
}: CRMTableHeaderProps) {
const handleResizeStart = (columnId: string) => (e: React.MouseEvent | React.TouchEvent) => {
e.preventDefault();
const startX = 'touches' in e ? e.touches[0].clientX : e.clientX;
const startWidth = columnWidths[columnId] || DEFAULT_COLUMN_WIDTH;
onResizeStart?.(columnId, startX, startWidth);
};
return (
<thead
className="bg-background border-border sticky top-0 !z-[10] grid border-b"
style={{
width: totalSize,
}}
>
<Reorder.Group
as="tr"
axis="x"
values={columnsConfig}
onReorder={onReorder}
className="group hover:bg-transparent"
style={{ display: 'flex', width: '100%' }}
>
{columnsConfig.map((colConfig) => {
// Check if this is the company column (should always be pinned left)
const isCompanyColumn = colConfig.id === 'primaryCompany';
const currentSize = columnWidths[colConfig.id] || DEFAULT_COLUMN_WIDTH;
return (
<Reorder.Item
key=[redacted]
as="th"
value={colConfig}
dragListener={!colConfig.isFixed}
className={`bg-background text-muted-foreground group flex shrink-0 items-center justify-center overflow-visible px-1 py-3 text-center align-middle [&:has([role=checkbox])]:pr-0 ${
isCompanyColumn ? 'sticky left-0 !z-[20]' : 'relative !z-[5]'
} ${!colConfig.isFixed ? 'cursor-grab active:cursor-grabbing' : ''}`}
style={{
width: currentSize,
flexBasis: currentSize,
minWidth: 0,
maxWidth: currentSize,
}}
>
<SortableColumnHeader
colConfig={colConfig}
onUpdate={onUpdateColumn}
onDelete={onDeleteColumn}
/>
<div
onMouseDown={handleResizeStart(colConfig.id)}
onTouchStart={handleResizeStart(colConfig.id)}
className="group/resizer absolute right-0 top-0 !z-[25] -mr-2 flex h-full w-4 cursor-col-resize touch-none select-none items-center justify-center"
>
<div className="h-full w-[2px] bg-border transition-colors group-hover/resizer:bg-primary/50" />
</div>
</Reorder.Item>
);
})}
</Reorder.Group>
</thead>
);
},
(prev, next) => {
// 1. Check total size
if (prev.totalSize !== next.totalSize) return false;
// 2. Check columns config (order, new columns, etc)
if (prev.columnsConfig !== next.columnsConfig) return false;
// 3. Check column widths
if (prev.columnWidths !== next.columnWidths) return false;
return true;
},
);