-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathTable.tsx
More file actions
119 lines (110 loc) · 4.42 KB
/
Table.tsx
File metadata and controls
119 lines (110 loc) · 4.42 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
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
117
118
119
"use client";
import type { PaginatedDocs } from "payload";
import { ChevronIcon, SelectAll, SelectRow } from "@payloadcms/ui";
import * as Collapsible from "@radix-ui/react-collapsible";
import React, { Suspense, useMemo, useState } from "react";
import { generateTreeList } from "./generateTreeList.js";
const baseClass = "table";
export type Props = {
readonly columns?: any;
readonly data: PaginatedDocs["docs"];
readonly enableRowSelections?: boolean;
readonly isChildren?: number;
};
export const Table: React.FC<Props> = ({ columns, data, enableRowSelections, isChildren = 0 }) => {
const [openIndexes, setOpenIndexes] = useState<boolean[]>(Array(data.length).fill(false));
const activeColumns = columns?.filter((col) => col?.active);
const docs = useMemo(() => (isChildren ? data : generateTreeList(data)), [data, isChildren]);
if (!activeColumns || activeColumns.length === 0) {
return <div>No columns selected</div>;
}
const gridRowClass = {
gridTemplateColumns: `46px repeat(${activeColumns.length}, minmax(100px, 1fr)) 46px`,
};
const toggleCollapsible = (index) => {
setOpenIndexes((prev) => {
const newState = [...prev];
newState[index] = !newState[index];
return newState;
});
};
return (
<div className={`${baseClass} ${baseClass}--tree-list`}>
<div className="table-collapsible" role="table">
<div
className={`table-collapsible__header ${isChildren > 0 ? "sr-only" : ""}`}
role="row"
style={gridRowClass}
>
{enableRowSelections ? (
<div id="heading-_select" role="columnheader">
<SelectAll />
</div>
) : (
<div aria-hidden="true" role="columnheader" />
)}
{activeColumns.map((col, i) => (
<div id={`heading-${col.accessor}`} key={`table-header-${i}`} role="columnheader">
{col.Heading}
</div>
))}
<div aria-hidden="true" role="columnheader" />
</div>
{docs &&
docs.map((row, rowIndex) => {
const hasChildren = !!(row.children as Record<string, unknown>[])?.length;
const lastChild = rowIndex === docs.length - 1;
return (
<Collapsible.Root
key={`table-cell-${row.originalIndex}`}
onOpenChange={() => toggleCollapsible(row.originalIndex)}
open={openIndexes[row.originalIndex]}
>
<div
className={`row-${row.originalIndex + 1}${(row.originalIndex + 1) % 2 !== 0 ? " odd" : ""}${isChildren ? " table-collapsible__row-child" : ""}${lastChild ? " table-collapsible__row-last" : ""}`}
role="row"
style={gridRowClass}
>
{enableRowSelections ? (
<div className="cell-_select" role="cell">
<SelectRow rowData={row} />
</div>
) : (
<div aria-hidden="true" role="cell" />
)}
{activeColumns.map((col, colIndex) => (
<Suspense key={colIndex} fallback={<span />}>
<div className={`cell-${col.accessor}`} role="cell">
{col.renderedCells[row.originalIndex]}
</div>
</Suspense>
))}
<div className="cell-trigger" role="cell">
<Collapsible.Trigger asChild>
{hasChildren && (
<button
aria-label="toggle children elements"
className="table-collapsible__trigger"
type="button"
>
<ChevronIcon direction={openIndexes[row.originalIndex] ? "up" : "down"} />
</button>
)}
</Collapsible.Trigger>
</div>
</div>
<Collapsible.Content>
<Table
columns={columns}
data={row.children as Record<string, unknown>[]}
enableRowSelections={enableRowSelections}
isChildren={isChildren + 1}
/>
</Collapsible.Content>
</Collapsible.Root>
);
})}
</div>
</div>
);
};