1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
"use client"
import { SelectIcon } from "@radix-ui/react-select"
import { type Column } from "@tanstack/react-table"
import { ArrowDown, ArrowUp, ChevronsUpDown, EyeOff } from "lucide-react"
import { cn } from "@/lib/utils"
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
} from "@/components/ui/select"
interface DataTableColumnHeaderProps<TData, TValue>
extends React.HTMLAttributes<HTMLDivElement> {
column: Column<TData, TValue>
title: string
}
export function DataTableColumnHeader<TData, TValue>({
column,
title,
className,
}: DataTableColumnHeaderProps<TData, TValue>) {
if (!column.getCanSort() && !column.getCanHide()) {
return <div className={cn("w-full", className)}>{title}</div>
}
const ascValue = `${column.id}-asc`
const descValue = `${column.id}-desc`
const hideValue = `${column.id}-hide`
// 현재 컬럼 pinned 상태
const isPinned = column.getIsPinned();
return (
<div className={cn("flex items-center gap-2 w-full", className)}>
<Select
value={
column.getIsSorted() === "desc"
? descValue
: column.getIsSorted() === "asc"
? ascValue
: undefined
}
onValueChange={(value) => {
if (value === ascValue) column.toggleSorting(false)
else if (value === descValue) column.toggleSorting(true)
else if (value === hideValue) column.toggleVisibility(false)
}}
>
<SelectTrigger
aria-label={
column.getIsSorted() === "desc"
? "Sorted descending. Click to sort ascending."
: column.getIsSorted() === "asc"
? "Sorted ascending. Click to sort descending."
: "Not sorted. Click to sort ascending."
}
className={cn(
"-ml-3 h-8 w-full border-none text-xs hover:bg-accent hover:text-accent-foreground data-[state=open]:bg-accent [&>svg:last-child]:hidden",
// 고정된 상태일 때 추가 스타일
isPinned && "sticky-content"
)}
>
{title}
<SelectIcon asChild>
{column.getCanSort() && column.getIsSorted() === "desc" ? (
<ArrowDown className="ml-2.5 size-4" aria-hidden="true" />
) : column.getIsSorted() === "asc" ? (
<ArrowUp className="ml-2.5 size-4" aria-hidden="true" />
) : (
<ChevronsUpDown className="ml-2.5 size-4" aria-hidden="true" />
)}
</SelectIcon>
</SelectTrigger>
<SelectContent align="start">
{column.getCanSort() && (
<>
<SelectItem value={ascValue}>
<span className="flex items-center">
<ArrowUp
className="mr-2 size-3.5 text-muted-foreground/70"
aria-hidden="true"
/>
Asc
</span>
</SelectItem>
<SelectItem value={descValue}>
<span className="flex items-center">
<ArrowDown
className="mr-2 size-3.5 text-muted-foreground/70"
aria-hidden="true"
/>
Desc
</span>
</SelectItem>
</>
)}
{column.getCanHide() && (
<SelectItem value={hideValue}>
<span className="flex items-center">
<EyeOff
className="mr-2 size-3.5 text-muted-foreground/70"
aria-hidden="true"
/>
Hide
</span>
</SelectItem>
)}
</SelectContent>
</Select>
</div>
)
}
|