"use client" import * as React from "react" import { Header } from "@tanstack/react-table" import { useSortable } from "@dnd-kit/sortable" import { CSS } from "@dnd-kit/utilities" import { flexRender } from "@tanstack/react-table" import { ContextMenu, ContextMenuContent, ContextMenuItem, ContextMenuSeparator, ContextMenuTrigger, } from "@/components/ui/context-menu" import { ArrowDown, ArrowUp, ChevronsUpDown, EyeOff, PinOff, MoveLeft, MoveRight, } from "lucide-react" import { cn } from "@/lib/utils" import { ClientTableFilter } from "./client-table-filter" interface ClientTableColumnHeaderProps extends React.HTMLAttributes { header: Header enableReordering?: boolean } export function ClientTableColumnHeader({ header, enableReordering = true, className, ...props }: ClientTableColumnHeaderProps) { const column = header.column const { attributes, listeners, setNodeRef, transform, transition, isDragging, } = useSortable({ id: header.id, disabled: !enableReordering, }) // -- Styles -- const style: React.CSSProperties = { // Apply transform only if reordering is enabled and active transform: enableReordering ? CSS.Translate.toString(transform) : undefined, transition: enableReordering ? transition : undefined, width: header.getSize(), zIndex: isDragging ? 100 : 0, position: "relative", ...props.style, } // Pinning Styles const isPinned = column.getIsPinned() if (isPinned === "left") { style.left = `${column.getStart("left")}px` style.position = "sticky" style.zIndex = 20 } else if (isPinned === "right") { style.right = `${column.getAfter("right")}px` style.position = "sticky" style.zIndex = 20 } // -- Handlers -- const handleHide = () => column.toggleVisibility(false) const handlePinLeft = () => column.pin("left") const handlePinRight = () => column.pin("right") const handleUnpin = () => column.pin(false) // -- Content -- const content = ( <>
{flexRender(column.columnDef.header, header.getContext())} {column.getCanSort() && ( {column.getIsSorted() === "desc" ? ( ) : column.getIsSorted() === "asc" ? ( ) : ( )} )}
{/* Resize Handle */}
e.stopPropagation()} // Prevent sort trigger className={cn( "absolute right-0 top-0 h-full w-2 cursor-col-resize select-none touch-none z-10", "after:absolute after:right-0 after:top-0 after:h-full after:w-[1px] after:bg-border", // 시각적 구분선 "hover:bg-primary/20 hover:w-4 hover:-right-2", // 호버 시 클릭 영역 확장 header.column.getIsResizing() ? "bg-primary/50 w-1" : "bg-transparent" )} /> {/* Filter */} {column.getCanFilter() && } ) if (header.isPlaceholder) { return ( {null} ) } return ( {content} Hide Column Pin Left Pin Right {isPinned && ( Unpin )} ) }