@kadconsulting/dry
Version:
KAD Reusable Component Library
101 lines • 5.78 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { createElement as _createElement } from "react";
// TableHeader.tsx
import { useMemo, useCallback, useState, useEffect } from 'react';
// TODO-DRY: icon needs to be easer to use
import Icon from '../../Icons/Icon/Icon';
import { ArrowNarrowUp, ArrowNarrowDown, ChevronSelectorVertical, } from '../../Icons/paths';
import { IconSizes } from '../../Icons/Icon/IconTypes';
import { FilterType } from '../DataTableTypes';
import './TableHeader.scss';
const TableHeader = ({ headerGroups, onSortChange, columnOrder, columnWidths, onColumnOrderChange, onColumnResize, sortedColumn, hasResize, isDraggable, }) => {
// State for tracking drag source
const [draggedColumnIndex, setDraggedColumnIndex] = useState(null);
// State for tracking initial position and size for resizing
const [startX, setStartX] = useState(null);
const [startWidth, setStartWidth] = useState(null);
// Create a memoized version of headerGroups
const memoizedHeaderGroups = useMemo(() => headerGroups, [headerGroups]);
// Handle column sorting
const handleSort = useCallback((column) => {
// This is broken up so if in the future we want to make this logic better we can start here
switch (column.filterType) {
case FilterType.Text:
let textNewSortBy = [
{ id: column.id, desc: sortedColumn?.direction === 'asc' },
];
onSortChange(textNewSortBy);
case FilterType.Number:
const numberNewSortBy = [
{ id: column.id, desc: sortedColumn?.direction === 'asc' },
];
onSortChange(numberNewSortBy);
case FilterType.DateRange:
const dateNewSortBy = [
{ id: column.id, desc: sortedColumn?.direction === 'asc' },
];
onSortChange(dateNewSortBy);
default:
return true;
}
}, [onSortChange, sortedColumn]);
// Handle column reordering
const handleColumnReorder = useCallback((sourceIndex, destinationIndex) => {
const newOrder = [...columnOrder];
const [removed] = newOrder.splice(sourceIndex, 1);
newOrder.splice(destinationIndex, 0, removed);
onColumnOrderChange(newOrder);
}, [columnOrder, onColumnOrderChange]);
// Handle drag start
const handleDragStart = useCallback((e, columnIndex) => {
e.dataTransfer.effectAllowed = 'move';
setDraggedColumnIndex(columnIndex);
}, []);
// Handle drag over
const handleDragOver = useCallback((e) => {
e.preventDefault();
}, []);
// Handle drop
const handleDrop = useCallback((e, columnIndex) => {
e.preventDefault();
if (draggedColumnIndex !== null && draggedColumnIndex !== columnIndex) {
handleColumnReorder(draggedColumnIndex, columnIndex);
}
setDraggedColumnIndex(null);
}, [draggedColumnIndex, handleColumnReorder]);
// Handle mouse down for resizing
const handleMouseDown = useCallback((e, colIndex) => {
setStartX(e.pageX);
setStartWidth(columnWidths[headerGroups[0].headers[colIndex].id]);
}, [columnWidths, headerGroups]);
// Handle mouse move for resizing
const handleMouseMove = useCallback((e) => {
if (startX === null || startWidth === null)
return;
const newWidth = startWidth + (e.pageX - startX);
const columnId = headerGroups[0].headers[draggedColumnIndex]
.id;
onColumnResize({ [columnId]: newWidth });
}, [startX, startWidth, draggedColumnIndex, headerGroups, onColumnResize]);
// Handle mouse up for resizing
const handleMouseUp = useCallback(() => {
document.removeEventListener('mousemove', handleMouseMove);
document.removeEventListener('mouseup', handleMouseUp);
setStartX(null);
setStartWidth(null);
}, [handleMouseMove]);
useEffect(() => {
if (startX !== null) {
document.addEventListener('mousemove', handleMouseMove);
document.addEventListener('mouseup', handleMouseUp);
}
return () => {
document.removeEventListener('mousemove', handleMouseMove);
document.removeEventListener('mouseup', handleMouseUp);
};
}, [startX, handleMouseMove, handleMouseUp]);
return (_jsx("thead", { children: memoizedHeaderGroups.map((headerGroup, index) => (_createElement("tr", { ...headerGroup.getHeaderGroupProps(), key: index }, headerGroup.headers.map((column, colIndex) => (_createElement("th", { ...column.getHeaderProps(), key: colIndex, style: { width: `${columnWidths[column.id]}px` } },
_jsxs("div", { className: 'header-container', children: [_jsxs("div", { className: 'header-content', onClick: () => handleSort(column), children: [column.render('Header'), _jsx("span", { className: 'sort-indicator', children: sortedColumn?.id === column.id ? (sortedColumn?.direction === 'asc' ? (_jsx(Icon, { color: 'black', Path: ArrowNarrowUp, size: IconSizes.SMALL })) : (_jsx(Icon, { color: 'black', Path: ArrowNarrowDown, size: IconSizes.SMALL }))) : (_jsx(Icon, { color: 'black', Path: ChevronSelectorVertical, size: IconSizes.SMALL })) })] }), isDraggable && (_jsx("div", { className: 'drag-handle', draggable: true, onDragStart: (e) => handleDragStart(e, colIndex), onDragOver: handleDragOver, onDrop: (e) => handleDrop(e, colIndex), children: "\u2630" })), hasResize && (_jsx("div", { className: 'resize-handle', onMouseDown: (e) => handleMouseDown(e, colIndex), children: "\u2500" }))] }))))))) }));
};
export default TableHeader;
//# sourceMappingURL=TableHeader.js.map