-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDataTable.tsx
More file actions
74 lines (67 loc) · 1.96 KB
/
Copy pathDataTable.tsx
File metadata and controls
74 lines (67 loc) · 1.96 KB
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
import React, { useState } from "react"
type SortDir = "asc" | "desc"
type Column<T> = {
key: keyof T
label: string
sortable?: boolean
}
type Props<T extends Record<string, unknown>> = {
data: T[]
columns: Column<T>[]
}
/**
* DataTable with client-side sorting.
*
* The direction toggle uses the functional form of setState so it reads the
* current value rather than the one captured when the handler was created.
*
* (Note: the `sortKey === key` guard still reads `sortKey` from the render
* closure. This is correct for all real user interaction, where each click is a
* separate render pass; it only matters for synthetic same-batch double clicks.)
*/
export function DataTable<T extends Record<string, unknown>>({ data, columns }: Props<T>) {
const [sortKey, setSortKey] = useState<keyof T | null>(null)
const [sortDir, setSortDir] = useState<SortDir>("asc")
const handleSort = (key: keyof T) => {
if (sortKey === key) {
setSortDir((prev) => (prev === "asc" ? "desc" : "asc"))
} else {
setSortKey(key)
setSortDir("asc")
}
}
const sorted = sortKey
? [...data].sort((a, b) => {
const av = a[sortKey]
const bv = b[sortKey]
const cmp = av < bv ? -1 : av > bv ? 1 : 0
return sortDir === "asc" ? cmp : -cmp
})
: data
return (
<table>
<thead>
<tr>
{columns.map((col) => (
<th
key={String(col.key)}
onClick={col.sortable ? () => handleSort(col.key) : undefined}
aria-sort={sortKey === col.key ? (sortDir === "asc" ? "ascending" : "descending") : undefined}
>
{col.label}
</th>
))}
</tr>
</thead>
<tbody>
{sorted.map((row, i) => (
<tr key={i}>
{columns.map((col) => (
<td key={String(col.key)}>{String(row[col.key])}</td>
))}
</tr>
))}
</tbody>
</table>
)
}