Presupuestador_web/client/src/components/DataTable/DataTableColumnHeader.tsx

124 lines
4.0 KiB
TypeScript
Raw Normal View History

2024-06-11 16:48:09 +00:00
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>
);
}