124 lines
4.0 KiB
TypeScript
124 lines
4.0 KiB
TypeScript
|
|
import { Header, Table, flexRender } from "@tanstack/react-table";
|
||
|
|
|
||
|
|
import { cn } from "@/lib/utils";
|
||
|
|
import {
|
||
|
|
Button,
|
||
|
|
DropdownMenu,
|
||
|
|
DropdownMenuContent,
|
||
|
|
DropdownMenuItem,
|
||
|
|
DropdownMenuSeparator,
|
||
|
|
DropdownMenuTrigger,
|
||
|
|
Separator,
|
||
|
|
} from "@/ui";
|
||
|
|
import {
|
||
|
|
ArrowDownIcon,
|
||
|
|
ArrowDownUpIcon,
|
||
|
|
ArrowUpIcon,
|
||
|
|
EyeOffIcon,
|
||
|
|
} from "lucide-react";
|
||
|
|
|
||
|
|
interface DataTableColumnHeaderProps<TData, TValue>
|
||
|
|
extends React.HTMLAttributes<HTMLDivElement> {
|
||
|
|
table: Table<TData>;
|
||
|
|
header: Header<TData, TValue>;
|
||
|
|
}
|
||
|
|
|
||
|
|
export function DataTableColumnHeader<TData, TValue>({
|
||
|
|
table,
|
||
|
|
header,
|
||
|
|
className,
|
||
|
|
}: DataTableColumnHeaderProps<TData, TValue>) {
|
||
|
|
if (!header.column.getCanSort()) {
|
||
|
|
return (
|
||
|
|
<>
|
||
|
|
<div
|
||
|
|
className={cn(
|
||
|
|
"data-[state=open]:bg-accent font-semiboldw text-muted-foreground uppercase",
|
||
|
|
className,
|
||
|
|
)}
|
||
|
|
>
|
||
|
|
{header.isPlaceholder
|
||
|
|
? null
|
||
|
|
: flexRender(header.column.columnDef.header, header.getContext())}
|
||
|
|
</div>
|
||
|
|
{header.column.getCanResize() && (
|
||
|
|
<Separator
|
||
|
|
orientation="vertical"
|
||
|
|
className={cn(
|
||
|
|
"absolute top-0 h-full w-[5px] bg-black/10 cursor-col-resize",
|
||
|
|
table.options.columnResizeDirection,
|
||
|
|
header.column.getIsResizing() ? "bg-primary opacity-100" : "",
|
||
|
|
)}
|
||
|
|
{...{
|
||
|
|
onDoubleClick: () => header.column.resetSize(),
|
||
|
|
onMouseDown: header.getResizeHandler(),
|
||
|
|
onTouchStart: header.getResizeHandler(),
|
||
|
|
style: {
|
||
|
|
transform:
|
||
|
|
table.options.columnResizeMode === "onEnd" &&
|
||
|
|
header.column.getIsResizing()
|
||
|
|
? `translateX(${
|
||
|
|
(table.options.columnResizeDirection === "rtl"
|
||
|
|
? -1
|
||
|
|
: 1) *
|
||
|
|
(table.getState().columnSizingInfo.deltaOffset ?? 0)
|
||
|
|
}px)`
|
||
|
|
: "",
|
||
|
|
},
|
||
|
|
}}
|
||
|
|
/>
|
||
|
|
)}
|
||
|
|
</>
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
return (
|
||
|
|
<div className={cn("flex items-center space-x-2", className)}>
|
||
|
|
<DropdownMenu>
|
||
|
|
<DropdownMenuTrigger asChild>
|
||
|
|
<Button
|
||
|
|
aria-label={
|
||
|
|
header.column.getIsSorted() === "desc"
|
||
|
|
? "En orden descendente. Click para ordenar ascendentemente."
|
||
|
|
: header.column.getIsSorted() === "asc"
|
||
|
|
? "En order ascendente. Click para ordenar descendentemente."
|
||
|
|
: "Sin orden. Click para ordenar ascendentemente."
|
||
|
|
}
|
||
|
|
size="sm"
|
||
|
|
variant="ghost"
|
||
|
|
className="-ml-3 h-8 data-[state=open]:bg-accent font-bold text-muted-foreground"
|
||
|
|
>
|
||
|
|
{flexRender(header.column.columnDef.header, header.getContext())}
|
||
|
|
{header.column.getIsSorted() === "desc" ? (
|
||
|
|
<ArrowDownIcon className="w-4 h-4 ml-2" />
|
||
|
|
) : header.column.getIsSorted() === "asc" ? (
|
||
|
|
<ArrowUpIcon className="w-4 h-4 ml-2" />
|
||
|
|
) : (
|
||
|
|
<ArrowDownUpIcon className="w-4 h-4 ml-2 text-muted-foreground/30" />
|
||
|
|
)}
|
||
|
|
</Button>
|
||
|
|
</DropdownMenuTrigger>
|
||
|
|
<DropdownMenuContent align="start">
|
||
|
|
<DropdownMenuItem onClick={() => header.column.toggleSorting(false)}>
|
||
|
|
<ArrowUpIcon className="mr-2 h-3.5 w-3.5 text-muted-foreground/70" />
|
||
|
|
Ascendente
|
||
|
|
</DropdownMenuItem>
|
||
|
|
<DropdownMenuItem onClick={() => header.column.toggleSorting(true)}>
|
||
|
|
<ArrowDownIcon className="mr-2 h-3.5 w-3.5 text-muted-foreground/70" />
|
||
|
|
Descendente
|
||
|
|
</DropdownMenuItem>
|
||
|
|
<DropdownMenuSeparator />
|
||
|
|
{header.column.getCanHide() && (
|
||
|
|
<DropdownMenuItem
|
||
|
|
onClick={() => header.column.toggleVisibility(false)}
|
||
|
|
>
|
||
|
|
<EyeOffIcon className="mr-2 h-3.5 w-3.5 text-muted-foreground/70" />
|
||
|
|
Ocultar
|
||
|
|
</DropdownMenuItem>
|
||
|
|
)}
|
||
|
|
</DropdownMenuContent>
|
||
|
|
</DropdownMenu>
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
}
|