@simpleapps-com/augur-web 2.2.24 → 2.2.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/checkbox.cjs +4 -21
- package/dist/checkbox.cjs.map +1 -1
- package/dist/checkbox.js +3 -20
- package/dist/checkbox.js.map +1 -1
- package/dist/chunk-3UFEQSTN.js +26 -0
- package/dist/chunk-3UFEQSTN.js.map +1 -0
- package/dist/chunk-3VN3FX2Q.js +165 -0
- package/dist/chunk-3VN3FX2Q.js.map +1 -0
- package/dist/chunk-JXW4XE2P.cjs +143 -0
- package/dist/chunk-JXW4XE2P.cjs.map +1 -0
- package/dist/chunk-MOC5N2N4.js +143 -0
- package/dist/chunk-MOC5N2N4.js.map +1 -0
- package/dist/chunk-NSSX7USQ.cjs +165 -0
- package/dist/chunk-NSSX7USQ.cjs.map +1 -0
- package/dist/chunk-XGKBDPGD.cjs +26 -0
- package/dist/chunk-XGKBDPGD.cjs.map +1 -0
- package/dist/data-table.cjs +353 -81
- package/dist/data-table.cjs.map +1 -1
- package/dist/data-table.d.cts +29 -32
- package/dist/data-table.d.ts +29 -32
- package/dist/data-table.js +355 -83
- package/dist/data-table.js.map +1 -1
- package/dist/dropdown-menu.cjs +34 -140
- package/dist/dropdown-menu.cjs.map +1 -1
- package/dist/dropdown-menu.js +17 -123
- package/dist/dropdown-menu.js.map +1 -1
- package/dist/pagination.cjs +22 -161
- package/dist/pagination.cjs.map +1 -1
- package/dist/pagination.js +10 -149
- package/dist/pagination.js.map +1 -1
- package/package.json +6 -6
package/dist/data-table.d.ts
CHANGED
|
@@ -1,58 +1,55 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import * as React from 'react';
|
|
3
|
+
import { SortingState, RowSelectionState } from '@tanstack/react-table';
|
|
4
|
+
export { RowSelectionState, SortingState, VisibilityState } from '@tanstack/react-table';
|
|
3
5
|
|
|
4
6
|
interface ColumnDef<T> {
|
|
5
|
-
/** Property key on the data object. */
|
|
6
7
|
key: keyof T & string;
|
|
7
|
-
/** Column header label. */
|
|
8
8
|
header: string;
|
|
9
|
-
/** Enable sorting on this column. */
|
|
10
9
|
sortable?: boolean;
|
|
11
|
-
/** Custom cell renderer. Receives the row data object. */
|
|
12
10
|
render?: (row: T) => React.ReactNode;
|
|
13
|
-
/** Text alignment. */
|
|
14
11
|
align?: "left" | "center" | "right";
|
|
12
|
+
hideable?: boolean;
|
|
13
|
+
}
|
|
14
|
+
interface DataTablePagination {
|
|
15
|
+
page: number;
|
|
16
|
+
totalPages: number;
|
|
17
|
+
getHref: (page: number) => string;
|
|
18
|
+
onPageChange?: (page: number) => void;
|
|
19
|
+
/** Current page size. Required when pageSizeOptions is set. */
|
|
20
|
+
pageSize?: number;
|
|
21
|
+
/** Available page size options. Renders a dropdown when provided. */
|
|
22
|
+
pageSizeOptions?: number[];
|
|
23
|
+
/** Called when the user selects a different page size. */
|
|
24
|
+
onPageSizeChange?: (size: number) => void;
|
|
15
25
|
}
|
|
16
26
|
interface DataTableProps<T> {
|
|
17
|
-
/** Column definitions describing each table column. */
|
|
18
27
|
columns: ColumnDef<T>[];
|
|
19
|
-
/** Data rows to display. */
|
|
20
28
|
data: T[];
|
|
21
|
-
/** Show a search input above the table. */
|
|
22
29
|
searchable?: boolean;
|
|
23
|
-
/** Placeholder text for the search input. */
|
|
24
30
|
searchPlaceholder?: string;
|
|
25
|
-
/** Callback when a row is clicked. Receives the row data. */
|
|
26
31
|
onRowClick?: (row: T) => void;
|
|
27
|
-
/** Show a loading spinner instead of data. */
|
|
28
32
|
loading?: boolean;
|
|
29
|
-
/** Message shown when data is empty. */
|
|
30
33
|
emptyMessage?: string;
|
|
31
|
-
/** Additional toolbar content rendered between search and table. */
|
|
32
34
|
toolbar?: React.ReactNode;
|
|
33
|
-
/** Additional class name for the root container. */
|
|
34
35
|
className?: string;
|
|
35
|
-
/** Row key extractor. Defaults to the row index. */
|
|
36
36
|
getRowId?: (row: T) => string;
|
|
37
|
+
pagination?: DataTablePagination;
|
|
38
|
+
globalFilter?: string;
|
|
39
|
+
onGlobalFilterChange?: (value: string) => void;
|
|
40
|
+
sortingState?: SortingState;
|
|
41
|
+
onSortingChange?: (state: SortingState) => void;
|
|
42
|
+
selectable?: boolean;
|
|
43
|
+
rowSelection?: RowSelectionState;
|
|
44
|
+
onRowSelectionChange?: (state: RowSelectionState) => void;
|
|
45
|
+
bulkActions?: (selectedRows: T[]) => React.ReactNode;
|
|
46
|
+
columnToggle?: boolean;
|
|
47
|
+
exportCsv?: boolean;
|
|
48
|
+
csvFilename?: string;
|
|
37
49
|
}
|
|
38
|
-
|
|
39
|
-
* Data-driven table with sorting and search. Wraps TanStack Table with
|
|
40
|
-
* the augur-web Table primitives.
|
|
41
|
-
*
|
|
42
|
-
* @example
|
|
43
|
-
* ```tsx
|
|
44
|
-
* const columns: ColumnDef<Brand>[] = [
|
|
45
|
-
* { key: "brandsUid", header: "UID", sortable: true },
|
|
46
|
-
* { key: "brandsName", header: "Name", sortable: true },
|
|
47
|
-
* { key: "brandsDesc", header: "Description" },
|
|
48
|
-
* ];
|
|
49
|
-
*
|
|
50
|
-
* <DataTable columns={columns} data={brands} searchable onRowClick={selectBrand} />
|
|
51
|
-
* ```
|
|
52
|
-
*/
|
|
53
|
-
declare function DataTable<T>({ columns, data, searchable, searchPlaceholder, onRowClick, loading, emptyMessage, toolbar, className, getRowId, }: DataTableProps<T>): react_jsx_runtime.JSX.Element;
|
|
50
|
+
declare function DataTable<T>({ columns, data, searchable, searchPlaceholder, onRowClick, loading, emptyMessage, toolbar, className, getRowId, pagination, globalFilter: externalGlobalFilter, onGlobalFilterChange, sortingState, onSortingChange, selectable, rowSelection, onRowSelectionChange, bulkActions, columnToggle, exportCsv, csvFilename, }: DataTableProps<T>): react_jsx_runtime.JSX.Element;
|
|
54
51
|
declare namespace DataTable {
|
|
55
52
|
var displayName: string;
|
|
56
53
|
}
|
|
57
54
|
|
|
58
|
-
export { type ColumnDef, DataTable, type DataTableProps };
|
|
55
|
+
export { type ColumnDef, DataTable, type DataTablePagination, type DataTableProps };
|
package/dist/data-table.js
CHANGED
|
@@ -8,12 +8,36 @@ import {
|
|
|
8
8
|
TableHeader,
|
|
9
9
|
TableRow
|
|
10
10
|
} from "./chunk-XIKSI7NY.js";
|
|
11
|
+
import {
|
|
12
|
+
ListPagination
|
|
13
|
+
} from "./chunk-3VN3FX2Q.js";
|
|
14
|
+
import {
|
|
15
|
+
Select,
|
|
16
|
+
SelectContent,
|
|
17
|
+
SelectItem,
|
|
18
|
+
SelectTrigger,
|
|
19
|
+
SelectValue
|
|
20
|
+
} from "./chunk-RCUKSVMF.js";
|
|
21
|
+
import {
|
|
22
|
+
DropdownMenu,
|
|
23
|
+
DropdownMenuCheckboxItem,
|
|
24
|
+
DropdownMenuContent,
|
|
25
|
+
DropdownMenuLabel,
|
|
26
|
+
DropdownMenuSeparator,
|
|
27
|
+
DropdownMenuTrigger
|
|
28
|
+
} from "./chunk-MOC5N2N4.js";
|
|
11
29
|
import {
|
|
12
30
|
Input
|
|
13
31
|
} from "./chunk-HXQF6XTL.js";
|
|
14
32
|
import {
|
|
15
33
|
Spinner
|
|
16
34
|
} from "./chunk-UMNTUD2P.js";
|
|
35
|
+
import {
|
|
36
|
+
Button
|
|
37
|
+
} from "./chunk-QICSGVX3.js";
|
|
38
|
+
import {
|
|
39
|
+
Checkbox
|
|
40
|
+
} from "./chunk-3UFEQSTN.js";
|
|
17
41
|
|
|
18
42
|
// src/data-table.tsx
|
|
19
43
|
import * as React from "react";
|
|
@@ -25,23 +49,283 @@ import {
|
|
|
25
49
|
useReactTable
|
|
26
50
|
} from "@tanstack/react-table";
|
|
27
51
|
import { cn } from "@simpleapps-com/augur-utils/web";
|
|
28
|
-
import { LuArrowDown, LuArrowUp, LuArrowUpDown } from "react-icons/lu";
|
|
29
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
52
|
+
import { LuArrowDown, LuArrowUp, LuArrowUpDown, LuDownload, LuSettings2 } from "react-icons/lu";
|
|
53
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
54
|
+
var ALIGN_CLASS = { left: "text-left", center: "text-center", right: "text-right" };
|
|
55
|
+
function getAlignCn(meta) {
|
|
56
|
+
const align = meta?.align ?? "left";
|
|
57
|
+
return ALIGN_CLASS[align];
|
|
58
|
+
}
|
|
59
|
+
function buildTanstackColumns(columns, selectable) {
|
|
60
|
+
const cols = [];
|
|
61
|
+
if (selectable) {
|
|
62
|
+
cols.push({
|
|
63
|
+
id: "_select",
|
|
64
|
+
header: ({ table }) => /* @__PURE__ */ jsx(
|
|
65
|
+
Checkbox,
|
|
66
|
+
{
|
|
67
|
+
checked: table.getIsAllPageRowsSelected(),
|
|
68
|
+
onCheckedChange: (v) => table.toggleAllPageRowsSelected(!!v),
|
|
69
|
+
"aria-label": "Select all"
|
|
70
|
+
}
|
|
71
|
+
),
|
|
72
|
+
cell: ({ row }) => /* @__PURE__ */ jsx(
|
|
73
|
+
Checkbox,
|
|
74
|
+
{
|
|
75
|
+
checked: row.getIsSelected(),
|
|
76
|
+
onCheckedChange: (v) => row.toggleSelected(!!v),
|
|
77
|
+
"aria-label": "Select row",
|
|
78
|
+
onClick: (e) => e.stopPropagation()
|
|
79
|
+
}
|
|
80
|
+
),
|
|
81
|
+
enableSorting: false,
|
|
82
|
+
enableHiding: false,
|
|
83
|
+
meta: { align: "center" }
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
for (const col of columns) {
|
|
87
|
+
cols.push({
|
|
88
|
+
id: col.key,
|
|
89
|
+
accessorKey: col.key,
|
|
90
|
+
header: col.header,
|
|
91
|
+
enableSorting: col.sortable ?? false,
|
|
92
|
+
enableHiding: col.hideable !== false,
|
|
93
|
+
cell: col.render ? (info) => col.render(info.row.original) : (info) => String(info.getValue() ?? ""),
|
|
94
|
+
meta: { align: col.align }
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
return cols;
|
|
98
|
+
}
|
|
99
|
+
function exportToCsv(columns, data, filename) {
|
|
100
|
+
const headers = columns.map((c) => c.header);
|
|
101
|
+
const rows = data.map(
|
|
102
|
+
(row) => columns.map((col) => {
|
|
103
|
+
const str = String(row[col.key] ?? "");
|
|
104
|
+
return str.includes(",") || str.includes('"') || str.includes("\n") ? `"${str.replace(/"/g, '""')}"` : str;
|
|
105
|
+
})
|
|
106
|
+
);
|
|
107
|
+
const csv = [headers.join(","), ...rows.map((r) => r.join(","))].join("\n");
|
|
108
|
+
const blob = new Blob([csv], { type: "text/csv;charset=utf-8;" });
|
|
109
|
+
const url = URL.createObjectURL(blob);
|
|
110
|
+
const link = document.createElement("a");
|
|
111
|
+
link.href = url;
|
|
112
|
+
link.download = `${filename}.csv`;
|
|
113
|
+
link.click();
|
|
114
|
+
URL.revokeObjectURL(url);
|
|
115
|
+
}
|
|
116
|
+
function SortIndicator({ direction }) {
|
|
117
|
+
if (direction === "asc") return /* @__PURE__ */ jsx(LuArrowUp, { className: "h-4 w-4" });
|
|
118
|
+
if (direction === "desc") return /* @__PURE__ */ jsx(LuArrowDown, { className: "h-4 w-4" });
|
|
119
|
+
return /* @__PURE__ */ jsx(LuArrowUpDown, { className: "text-muted-foreground/50 h-4 w-4" });
|
|
120
|
+
}
|
|
121
|
+
function ColumnToggle({ table }) {
|
|
122
|
+
return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
|
|
123
|
+
/* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(Button, { variant: "outline", size: "sm", children: [
|
|
124
|
+
/* @__PURE__ */ jsx(LuSettings2, { className: "mr-2 h-4 w-4" }),
|
|
125
|
+
"Columns"
|
|
126
|
+
] }) }),
|
|
127
|
+
/* @__PURE__ */ jsxs(DropdownMenuContent, { align: "end", children: [
|
|
128
|
+
/* @__PURE__ */ jsx(DropdownMenuLabel, { children: "Toggle columns" }),
|
|
129
|
+
/* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
|
|
130
|
+
table.getAllColumns().filter((col) => col.getCanHide()).map((col) => /* @__PURE__ */ jsx(
|
|
131
|
+
DropdownMenuCheckboxItem,
|
|
132
|
+
{
|
|
133
|
+
checked: col.getIsVisible(),
|
|
134
|
+
onCheckedChange: (v) => col.toggleVisibility(!!v),
|
|
135
|
+
children: col.columnDef.header
|
|
136
|
+
},
|
|
137
|
+
col.id
|
|
138
|
+
))
|
|
139
|
+
] })
|
|
140
|
+
] });
|
|
141
|
+
}
|
|
142
|
+
function HeaderCell({ header }) {
|
|
143
|
+
return /* @__PURE__ */ jsx(
|
|
144
|
+
TableHead,
|
|
145
|
+
{
|
|
146
|
+
className: cn(
|
|
147
|
+
getAlignCn(header.column.columnDef.meta),
|
|
148
|
+
header.column.getCanSort() && "cursor-pointer select-none"
|
|
149
|
+
),
|
|
150
|
+
onClick: header.column.getToggleSortingHandler(),
|
|
151
|
+
children: /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1", children: [
|
|
152
|
+
flexRender(header.column.columnDef.header, header.getContext()),
|
|
153
|
+
header.column.getCanSort() && /* @__PURE__ */ jsx(SortIndicator, { direction: header.column.getIsSorted() })
|
|
154
|
+
] })
|
|
155
|
+
}
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
function DataCell({ cell }) {
|
|
159
|
+
return /* @__PURE__ */ jsx(TableCell, { className: getAlignCn(cell.column.columnDef.meta), children: flexRender(cell.column.columnDef.cell, cell.getContext()) });
|
|
160
|
+
}
|
|
161
|
+
function DataRow({ row, onRowClick }) {
|
|
162
|
+
return /* @__PURE__ */ jsx(
|
|
163
|
+
TableRow,
|
|
164
|
+
{
|
|
165
|
+
"data-state": row.getIsSelected() ? "selected" : void 0,
|
|
166
|
+
className: cn(onRowClick && "cursor-pointer"),
|
|
167
|
+
onClick: onRowClick ? () => onRowClick(row.original) : void 0,
|
|
168
|
+
children: row.getVisibleCells().map((cell) => /* @__PURE__ */ jsx(DataCell, { cell }, cell.id))
|
|
169
|
+
}
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
function ExportButton({
|
|
173
|
+
columns,
|
|
174
|
+
data,
|
|
175
|
+
csvFilename
|
|
176
|
+
}) {
|
|
177
|
+
return /* @__PURE__ */ jsxs(Button, { variant: "outline", size: "sm", onClick: () => exportToCsv(columns, data, csvFilename), children: [
|
|
178
|
+
/* @__PURE__ */ jsx(LuDownload, { className: "mr-2 h-4 w-4" }),
|
|
179
|
+
"Export"
|
|
180
|
+
] });
|
|
181
|
+
}
|
|
182
|
+
function BulkActionsBar({
|
|
183
|
+
selectedRows,
|
|
184
|
+
bulkActions
|
|
185
|
+
}) {
|
|
186
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
187
|
+
/* @__PURE__ */ jsxs("span", { className: "text-muted-foreground text-sm", children: [
|
|
188
|
+
selectedRows.length,
|
|
189
|
+
" selected"
|
|
190
|
+
] }),
|
|
191
|
+
bulkActions(selectedRows)
|
|
192
|
+
] });
|
|
193
|
+
}
|
|
194
|
+
function Toolbar({
|
|
195
|
+
searchable,
|
|
196
|
+
searchPlaceholder,
|
|
197
|
+
globalFilter,
|
|
198
|
+
onGlobalFilterChange,
|
|
199
|
+
selectedRows,
|
|
200
|
+
bulkActions,
|
|
201
|
+
toolbar,
|
|
202
|
+
exportCsv,
|
|
203
|
+
columns,
|
|
204
|
+
data,
|
|
205
|
+
csvFilename,
|
|
206
|
+
columnToggle,
|
|
207
|
+
table
|
|
208
|
+
}) {
|
|
209
|
+
const hasSelection = selectedRows.length > 0;
|
|
210
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4", children: [
|
|
211
|
+
searchable && /* @__PURE__ */ jsx(
|
|
212
|
+
Input,
|
|
213
|
+
{
|
|
214
|
+
placeholder: searchPlaceholder,
|
|
215
|
+
value: globalFilter,
|
|
216
|
+
onChange: (e) => onGlobalFilterChange(e.target.value),
|
|
217
|
+
className: "max-w-sm"
|
|
218
|
+
}
|
|
219
|
+
),
|
|
220
|
+
hasSelection && bulkActions && /* @__PURE__ */ jsx(BulkActionsBar, { selectedRows, bulkActions }),
|
|
221
|
+
/* @__PURE__ */ jsxs("div", { className: "ml-auto flex items-center gap-2", children: [
|
|
222
|
+
toolbar,
|
|
223
|
+
exportCsv && /* @__PURE__ */ jsx(ExportButton, { columns, data, csvFilename }),
|
|
224
|
+
columnToggle && /* @__PURE__ */ jsx(ColumnToggle, { table })
|
|
225
|
+
] })
|
|
226
|
+
] });
|
|
227
|
+
}
|
|
228
|
+
function TableBodyContent({
|
|
229
|
+
loading,
|
|
230
|
+
colSpan,
|
|
231
|
+
emptyMessage,
|
|
232
|
+
rows,
|
|
233
|
+
onRowClick
|
|
234
|
+
}) {
|
|
235
|
+
if (loading) {
|
|
236
|
+
return /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(TableCell, { colSpan, className: "h-24 text-center", children: /* @__PURE__ */ jsx(Spinner, { size: "lg", className: "mx-auto" }) }) });
|
|
237
|
+
}
|
|
238
|
+
if (rows.length === 0) {
|
|
239
|
+
return /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(TableCell, { colSpan, className: "h-24 text-center", children: emptyMessage }) });
|
|
240
|
+
}
|
|
241
|
+
return /* @__PURE__ */ jsx(Fragment, { children: rows.map((row) => /* @__PURE__ */ jsx(DataRow, { row, onRowClick }, row.id)) });
|
|
242
|
+
}
|
|
243
|
+
function PageSizeSelector({
|
|
244
|
+
pageSize,
|
|
245
|
+
options,
|
|
246
|
+
onChange
|
|
247
|
+
}) {
|
|
248
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
249
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-sm", children: "Rows per page" }),
|
|
250
|
+
/* @__PURE__ */ jsxs(Select, { value: String(pageSize), onValueChange: (v) => onChange(Number(v)), children: [
|
|
251
|
+
/* @__PURE__ */ jsx(SelectTrigger, { className: "h-8 w-[70px]", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
|
|
252
|
+
/* @__PURE__ */ jsx(SelectContent, { children: options.map((size) => /* @__PURE__ */ jsx(SelectItem, { value: String(size), children: size }, size)) })
|
|
253
|
+
] })
|
|
254
|
+
] });
|
|
255
|
+
}
|
|
256
|
+
function PaginationFooter({ pagination }) {
|
|
257
|
+
if (!pagination) return null;
|
|
258
|
+
const showPageSize = pagination.pageSizeOptions && pagination.pageSize !== void 0 && pagination.onPageSizeChange;
|
|
259
|
+
const showPages = pagination.totalPages > 1;
|
|
260
|
+
if (!showPageSize && !showPages) return null;
|
|
261
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
262
|
+
showPageSize ? /* @__PURE__ */ jsx(
|
|
263
|
+
PageSizeSelector,
|
|
264
|
+
{
|
|
265
|
+
pageSize: pagination.pageSize,
|
|
266
|
+
options: pagination.pageSizeOptions,
|
|
267
|
+
onChange: pagination.onPageSizeChange
|
|
268
|
+
}
|
|
269
|
+
) : /* @__PURE__ */ jsx("div", {}),
|
|
270
|
+
showPages && /* @__PURE__ */ jsx(
|
|
271
|
+
ListPagination,
|
|
272
|
+
{
|
|
273
|
+
page: pagination.page,
|
|
274
|
+
totalPages: pagination.totalPages,
|
|
275
|
+
getHref: pagination.getHref,
|
|
276
|
+
onPageChange: pagination.onPageChange
|
|
277
|
+
}
|
|
278
|
+
)
|
|
279
|
+
] });
|
|
280
|
+
}
|
|
281
|
+
function useDataTable(opts) {
|
|
282
|
+
const isManualFiltering = opts.externalGlobalFilter !== void 0;
|
|
283
|
+
const isManualSorting = opts.externalSorting !== void 0;
|
|
284
|
+
const [internalSorting, setInternalSorting] = React.useState([]);
|
|
285
|
+
const [internalGlobalFilter, setInternalGlobalFilter] = React.useState("");
|
|
286
|
+
const [internalRowSelection, setInternalRowSelection] = React.useState({});
|
|
287
|
+
const [columnVisibility, setColumnVisibility] = React.useState({});
|
|
288
|
+
const sorting = opts.externalSorting ?? internalSorting;
|
|
289
|
+
const globalFilter = opts.externalGlobalFilter ?? internalGlobalFilter;
|
|
290
|
+
const rowSelectionState = opts.externalRowSelection ?? internalRowSelection;
|
|
291
|
+
const handleSortingChange = opts.onSortingChange ? (updater) => {
|
|
292
|
+
opts.onSortingChange(updater(sorting));
|
|
293
|
+
} : setInternalSorting;
|
|
294
|
+
const handleGlobalFilterChange = opts.onGlobalFilterChange ?? setInternalGlobalFilter;
|
|
295
|
+
const handleRowSelectionChange = opts.onRowSelectionChange ? (updater) => {
|
|
296
|
+
opts.onRowSelectionChange(
|
|
297
|
+
updater(rowSelectionState)
|
|
298
|
+
);
|
|
299
|
+
} : setInternalRowSelection;
|
|
300
|
+
const tanstackColumns = React.useMemo(
|
|
301
|
+
() => buildTanstackColumns(opts.columns, opts.selectable),
|
|
302
|
+
[opts.columns, opts.selectable]
|
|
303
|
+
);
|
|
304
|
+
const table = useReactTable({
|
|
305
|
+
data: opts.data,
|
|
306
|
+
columns: tanstackColumns,
|
|
307
|
+
state: {
|
|
308
|
+
sorting,
|
|
309
|
+
globalFilter: isManualFiltering ? void 0 : globalFilter,
|
|
310
|
+
rowSelection: rowSelectionState,
|
|
311
|
+
columnVisibility
|
|
312
|
+
},
|
|
313
|
+
onSortingChange: handleSortingChange,
|
|
314
|
+
onGlobalFilterChange: isManualFiltering ? void 0 : setInternalGlobalFilter,
|
|
315
|
+
onRowSelectionChange: handleRowSelectionChange,
|
|
316
|
+
onColumnVisibilityChange: setColumnVisibility,
|
|
317
|
+
getCoreRowModel: getCoreRowModel(),
|
|
318
|
+
getSortedRowModel: isManualSorting ? void 0 : getSortedRowModel(),
|
|
319
|
+
getFilteredRowModel: isManualFiltering ? void 0 : getFilteredRowModel(),
|
|
320
|
+
manualSorting: isManualSorting,
|
|
321
|
+
manualFiltering: isManualFiltering,
|
|
322
|
+
manualPagination: opts.pagination !== void 0,
|
|
323
|
+
enableRowSelection: opts.selectable,
|
|
324
|
+
getRowId: opts.getRowId ? (row) => opts.getRowId(row) : void 0
|
|
325
|
+
});
|
|
326
|
+
const selectedRows = opts.selectable ? table.getSelectedRowModel().rows.map((r) => r.original) : [];
|
|
327
|
+
return { table, tanstackColumns, globalFilter, handleGlobalFilterChange, selectedRows };
|
|
328
|
+
}
|
|
45
329
|
function DataTable({
|
|
46
330
|
columns,
|
|
47
331
|
data,
|
|
@@ -52,82 +336,70 @@ function DataTable({
|
|
|
52
336
|
emptyMessage = "No results.",
|
|
53
337
|
toolbar,
|
|
54
338
|
className,
|
|
55
|
-
getRowId
|
|
339
|
+
getRowId,
|
|
340
|
+
pagination,
|
|
341
|
+
globalFilter: externalGlobalFilter,
|
|
342
|
+
onGlobalFilterChange,
|
|
343
|
+
sortingState,
|
|
344
|
+
onSortingChange,
|
|
345
|
+
selectable = false,
|
|
346
|
+
rowSelection,
|
|
347
|
+
onRowSelectionChange,
|
|
348
|
+
bulkActions,
|
|
349
|
+
columnToggle = false,
|
|
350
|
+
exportCsv = false,
|
|
351
|
+
csvFilename = "export"
|
|
56
352
|
}) {
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
const tanstackColumns = React.useMemo(() => buildTanstackColumns(columns), [columns]);
|
|
60
|
-
const table = useReactTable({
|
|
353
|
+
const { table, tanstackColumns, globalFilter, handleGlobalFilterChange, selectedRows } = useDataTable({
|
|
354
|
+
columns,
|
|
61
355
|
data,
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
356
|
+
selectable,
|
|
357
|
+
getRowId,
|
|
358
|
+
pagination,
|
|
359
|
+
externalGlobalFilter,
|
|
360
|
+
onGlobalFilterChange,
|
|
361
|
+
externalSorting: sortingState,
|
|
362
|
+
onSortingChange,
|
|
363
|
+
externalRowSelection: rowSelection,
|
|
364
|
+
onRowSelectionChange
|
|
70
365
|
});
|
|
366
|
+
const showToolbar = searchable || toolbar || columnToggle || exportCsv || selectedRows.length > 0;
|
|
71
367
|
return /* @__PURE__ */ jsxs("div", { className: cn("space-y-4", className), children: [
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
368
|
+
showToolbar && /* @__PURE__ */ jsx(
|
|
369
|
+
Toolbar,
|
|
370
|
+
{
|
|
371
|
+
searchable,
|
|
372
|
+
searchPlaceholder,
|
|
373
|
+
globalFilter,
|
|
374
|
+
onGlobalFilterChange: handleGlobalFilterChange,
|
|
375
|
+
selectedRows,
|
|
376
|
+
bulkActions,
|
|
377
|
+
toolbar,
|
|
378
|
+
exportCsv,
|
|
379
|
+
columns,
|
|
380
|
+
data,
|
|
381
|
+
csvFilename,
|
|
382
|
+
columnToggle,
|
|
383
|
+
table
|
|
384
|
+
}
|
|
385
|
+
),
|
|
386
|
+
/* @__PURE__ */ jsxs(Table, { children: [
|
|
387
|
+
/* @__PURE__ */ jsx(TableHeader, { className: "bg-background sticky top-0 z-10", children: table.getHeaderGroups().map((hg) => /* @__PURE__ */ jsx(TableRow, { children: hg.headers.map((h) => /* @__PURE__ */ jsx(HeaderCell, { header: h }, h.id)) }, hg.id)) }),
|
|
388
|
+
/* @__PURE__ */ jsx(TableBody, { children: /* @__PURE__ */ jsx(
|
|
389
|
+
TableBodyContent,
|
|
75
390
|
{
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
391
|
+
loading,
|
|
392
|
+
colSpan: tanstackColumns.length,
|
|
393
|
+
emptyMessage,
|
|
394
|
+
rows: table.getRowModel().rows,
|
|
395
|
+
onRowClick
|
|
80
396
|
}
|
|
81
|
-
)
|
|
82
|
-
toolbar
|
|
397
|
+
) })
|
|
83
398
|
] }),
|
|
84
|
-
/* @__PURE__ */
|
|
85
|
-
/* @__PURE__ */ jsx(TableHeader, { children: table.getHeaderGroups().map((headerGroup) => /* @__PURE__ */ jsx(TableRow, { children: headerGroup.headers.map((header) => {
|
|
86
|
-
const align = header.column.columnDef.meta?.align ?? "left";
|
|
87
|
-
return /* @__PURE__ */ jsx(
|
|
88
|
-
TableHead,
|
|
89
|
-
{
|
|
90
|
-
className: cn(
|
|
91
|
-
alignClass[align],
|
|
92
|
-
header.column.getCanSort() && "cursor-pointer select-none"
|
|
93
|
-
),
|
|
94
|
-
onClick: header.column.getToggleSortingHandler(),
|
|
95
|
-
children: /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1", children: [
|
|
96
|
-
flexRender(header.column.columnDef.header, header.getContext()),
|
|
97
|
-
header.column.getCanSort() && /* @__PURE__ */ jsx(SortIndicator, { direction: header.column.getIsSorted() })
|
|
98
|
-
] })
|
|
99
|
-
},
|
|
100
|
-
header.id
|
|
101
|
-
);
|
|
102
|
-
}) }, headerGroup.id)) }),
|
|
103
|
-
/* @__PURE__ */ jsx(TableBody, { children: loading ? /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(TableCell, { colSpan: columns.length, className: "h-24 text-center", children: /* @__PURE__ */ jsx(Spinner, { size: "lg", className: "mx-auto" }) }) }) : table.getRowModel().rows.length === 0 ? /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(TableCell, { colSpan: columns.length, className: "h-24 text-center", children: emptyMessage }) }) : table.getRowModel().rows.map((row) => /* @__PURE__ */ jsx(
|
|
104
|
-
TableRow,
|
|
105
|
-
{
|
|
106
|
-
className: cn(onRowClick && "cursor-pointer"),
|
|
107
|
-
onClick: onRowClick ? () => onRowClick(row.original) : void 0,
|
|
108
|
-
children: row.getVisibleCells().map((cell) => {
|
|
109
|
-
const align = cell.column.columnDef.meta?.align ?? "left";
|
|
110
|
-
return /* @__PURE__ */ jsx(
|
|
111
|
-
TableCell,
|
|
112
|
-
{
|
|
113
|
-
className: alignClass[align],
|
|
114
|
-
children: flexRender(cell.column.columnDef.cell, cell.getContext())
|
|
115
|
-
},
|
|
116
|
-
cell.id
|
|
117
|
-
);
|
|
118
|
-
})
|
|
119
|
-
},
|
|
120
|
-
row.id
|
|
121
|
-
)) })
|
|
122
|
-
] })
|
|
399
|
+
/* @__PURE__ */ jsx(PaginationFooter, { pagination })
|
|
123
400
|
] });
|
|
124
401
|
}
|
|
125
402
|
DataTable.displayName = "DataTable";
|
|
126
|
-
function SortIndicator({ direction }) {
|
|
127
|
-
if (direction === "asc") return /* @__PURE__ */ jsx(LuArrowUp, { className: "h-4 w-4" });
|
|
128
|
-
if (direction === "desc") return /* @__PURE__ */ jsx(LuArrowDown, { className: "h-4 w-4" });
|
|
129
|
-
return /* @__PURE__ */ jsx(LuArrowUpDown, { className: "text-muted-foreground/50 h-4 w-4" });
|
|
130
|
-
}
|
|
131
403
|
export {
|
|
132
404
|
DataTable
|
|
133
405
|
};
|
package/dist/data-table.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/data-table.tsx"],"sourcesContent":["/** Sortable, searchable data table built on TanStack Table. */\n\"use client\";\n\nimport * as React from \"react\";\nimport {\n flexRender,\n getCoreRowModel,\n getSortedRowModel,\n getFilteredRowModel,\n useReactTable,\n type ColumnDef as TanstackColumnDef,\n type SortingState,\n} from \"@tanstack/react-table\";\nimport { cn } from \"@simpleapps-com/augur-utils/web\";\nimport { LuArrowDown, LuArrowUp, LuArrowUpDown } from \"react-icons/lu\";\nimport { Table, TableHeader, TableBody, TableRow, TableHead, TableCell } from \"./table\";\nimport { Input } from \"./input\";\nimport { Spinner } from \"./spinner\";\n\nexport interface ColumnDef<T> {\n /** Property key on the data object. */\n key: keyof T & string;\n /** Column header label. */\n header: string;\n /** Enable sorting on this column. */\n sortable?: boolean;\n /** Custom cell renderer. Receives the row data object. */\n render?: (row: T) => React.ReactNode;\n /** Text alignment. */\n align?: \"left\" | \"center\" | \"right\";\n}\n\nexport interface DataTableProps<T> {\n /** Column definitions describing each table column. */\n columns: ColumnDef<T>[];\n /** Data rows to display. */\n data: T[];\n /** Show a search input above the table. */\n searchable?: boolean;\n /** Placeholder text for the search input. */\n searchPlaceholder?: string;\n /** Callback when a row is clicked. Receives the row data. */\n onRowClick?: (row: T) => void;\n /** Show a loading spinner instead of data. */\n loading?: boolean;\n /** Message shown when data is empty. */\n emptyMessage?: string;\n /** Additional toolbar content rendered between search and table. */\n toolbar?: React.ReactNode;\n /** Additional class name for the root container. */\n className?: string;\n /** Row key extractor. Defaults to the row index. */\n getRowId?: (row: T) => string;\n}\n\nfunction buildTanstackColumns<T>(columns: ColumnDef<T>[]): TanstackColumnDef<T, unknown>[] {\n return columns.map((col) => ({\n id: col.key,\n accessorKey: col.key,\n header: col.header,\n enableSorting: col.sortable ?? false,\n cell: col.render\n ? (info) => col.render!(info.row.original)\n : (info) => String(info.getValue() ?? \"\"),\n meta: { align: col.align },\n }));\n}\n\nconst alignClass = {\n left: \"text-left\",\n center: \"text-center\",\n right: \"text-right\",\n} as const;\n\n/**\n * Data-driven table with sorting and search. Wraps TanStack Table with\n * the augur-web Table primitives.\n *\n * @example\n * ```tsx\n * const columns: ColumnDef<Brand>[] = [\n * { key: \"brandsUid\", header: \"UID\", sortable: true },\n * { key: \"brandsName\", header: \"Name\", sortable: true },\n * { key: \"brandsDesc\", header: \"Description\" },\n * ];\n *\n * <DataTable columns={columns} data={brands} searchable onRowClick={selectBrand} />\n * ```\n */\nfunction DataTable<T>({\n columns,\n data,\n searchable = false,\n searchPlaceholder = \"Search...\",\n onRowClick,\n loading = false,\n emptyMessage = \"No results.\",\n toolbar,\n className,\n getRowId,\n}: DataTableProps<T>) {\n const [sorting, setSorting] = React.useState<SortingState>([]);\n const [globalFilter, setGlobalFilter] = React.useState(\"\");\n\n const tanstackColumns = React.useMemo(() => buildTanstackColumns(columns), [columns]);\n\n const table = useReactTable({\n data,\n columns: tanstackColumns,\n state: { sorting, globalFilter },\n onSortingChange: setSorting,\n onGlobalFilterChange: setGlobalFilter,\n getCoreRowModel: getCoreRowModel(),\n getSortedRowModel: getSortedRowModel(),\n getFilteredRowModel: getFilteredRowModel(),\n getRowId: getRowId ? (row) => getRowId(row) : undefined,\n });\n\n return (\n <div className={cn(\"space-y-4\", className)}>\n {(searchable || toolbar) && (\n <div className=\"flex items-center gap-4\">\n {searchable && (\n <Input\n placeholder={searchPlaceholder}\n value={globalFilter}\n onChange={(e) => setGlobalFilter(e.target.value)}\n className=\"max-w-sm\"\n />\n )}\n {toolbar}\n </div>\n )}\n <Table>\n <TableHeader>\n {table.getHeaderGroups().map((headerGroup) => (\n <TableRow key={headerGroup.id}>\n {headerGroup.headers.map((header) => {\n const align =\n (header.column.columnDef.meta as { align?: string } | undefined)?.align ?? \"left\";\n return (\n <TableHead\n key={header.id}\n className={cn(\n alignClass[align as keyof typeof alignClass],\n header.column.getCanSort() && \"cursor-pointer select-none\",\n )}\n onClick={header.column.getToggleSortingHandler()}\n >\n <span className=\"inline-flex items-center gap-1\">\n {flexRender(header.column.columnDef.header, header.getContext())}\n {header.column.getCanSort() && (\n <SortIndicator direction={header.column.getIsSorted()} />\n )}\n </span>\n </TableHead>\n );\n })}\n </TableRow>\n ))}\n </TableHeader>\n <TableBody>\n {loading ? (\n <TableRow>\n <TableCell colSpan={columns.length} className=\"h-24 text-center\">\n <Spinner size=\"lg\" className=\"mx-auto\" />\n </TableCell>\n </TableRow>\n ) : table.getRowModel().rows.length === 0 ? (\n <TableRow>\n <TableCell colSpan={columns.length} className=\"h-24 text-center\">\n {emptyMessage}\n </TableCell>\n </TableRow>\n ) : (\n table.getRowModel().rows.map((row) => (\n <TableRow\n key={row.id}\n className={cn(onRowClick && \"cursor-pointer\")}\n onClick={onRowClick ? () => onRowClick(row.original) : undefined}\n >\n {row.getVisibleCells().map((cell) => {\n const align =\n (cell.column.columnDef.meta as { align?: string } | undefined)?.align ?? \"left\";\n return (\n <TableCell\n key={cell.id}\n className={alignClass[align as keyof typeof alignClass]}\n >\n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n </TableCell>\n );\n })}\n </TableRow>\n ))\n )}\n </TableBody>\n </Table>\n </div>\n );\n}\nDataTable.displayName = \"DataTable\";\n\nfunction SortIndicator({ direction }: { direction: false | \"asc\" | \"desc\" }) {\n if (direction === \"asc\") return <LuArrowUp className=\"h-4 w-4\" />;\n if (direction === \"desc\") return <LuArrowDown className=\"h-4 w-4\" />;\n return <LuArrowUpDown className=\"text-muted-foreground/50 h-4 w-4\" />;\n}\n\nexport { DataTable };\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/data-table.tsx"],"sourcesContent":["/** Feature-complete admin data table built on TanStack Table. */\n\"use client\";\n\nimport * as React from \"react\";\nimport {\n flexRender,\n getCoreRowModel,\n getSortedRowModel,\n getFilteredRowModel,\n useReactTable,\n type ColumnDef as TanstackColumnDef,\n type SortingState,\n type RowSelectionState,\n type VisibilityState,\n type Table as TanstackTable,\n type Header,\n type Row,\n type Cell,\n} from \"@tanstack/react-table\";\nimport { cn } from \"@simpleapps-com/augur-utils/web\";\nimport { LuArrowDown, LuArrowUp, LuArrowUpDown, LuDownload, LuSettings2 } from \"react-icons/lu\";\nimport { Table, TableHeader, TableBody, TableRow, TableHead, TableCell } from \"./table\";\nimport { Input } from \"./input\";\nimport { Spinner } from \"./spinner\";\nimport { Checkbox } from \"./checkbox\";\nimport { Button } from \"./button\";\nimport { ListPagination } from \"./pagination\";\nimport { Select, SelectTrigger, SelectValue, SelectContent, SelectItem } from \"./select\";\nimport {\n DropdownMenu,\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuCheckboxItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n} from \"./dropdown-menu\";\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\nexport interface ColumnDef<T> {\n key: keyof T & string;\n header: string;\n sortable?: boolean;\n render?: (row: T) => React.ReactNode;\n align?: \"left\" | \"center\" | \"right\";\n hideable?: boolean;\n}\n\nexport interface DataTablePagination {\n page: number;\n totalPages: number;\n getHref: (page: number) => string;\n onPageChange?: (page: number) => void;\n /** Current page size. Required when pageSizeOptions is set. */\n pageSize?: number;\n /** Available page size options. Renders a dropdown when provided. */\n pageSizeOptions?: number[];\n /** Called when the user selects a different page size. */\n onPageSizeChange?: (size: number) => void;\n}\n\nexport interface DataTableProps<T> {\n columns: ColumnDef<T>[];\n data: T[];\n searchable?: boolean;\n searchPlaceholder?: string;\n onRowClick?: (row: T) => void;\n loading?: boolean;\n emptyMessage?: string;\n toolbar?: React.ReactNode;\n className?: string;\n getRowId?: (row: T) => string;\n pagination?: DataTablePagination;\n globalFilter?: string;\n onGlobalFilterChange?: (value: string) => void;\n sortingState?: SortingState;\n onSortingChange?: (state: SortingState) => void;\n selectable?: boolean;\n rowSelection?: RowSelectionState;\n onRowSelectionChange?: (state: RowSelectionState) => void;\n bulkActions?: (selectedRows: T[]) => React.ReactNode;\n columnToggle?: boolean;\n exportCsv?: boolean;\n csvFilename?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nconst ALIGN_CLASS = { left: \"text-left\", center: \"text-center\", right: \"text-right\" } as const;\n\nfunction getAlignCn(meta: unknown): string {\n const align = (meta as { align?: string } | undefined)?.align ?? \"left\";\n return ALIGN_CLASS[align as keyof typeof ALIGN_CLASS];\n}\n\nfunction buildTanstackColumns<T>(\n columns: ColumnDef<T>[],\n selectable: boolean,\n): TanstackColumnDef<T, unknown>[] {\n const cols: TanstackColumnDef<T, unknown>[] = [];\n if (selectable) {\n cols.push({\n id: \"_select\",\n header: ({ table }) => (\n <Checkbox\n checked={table.getIsAllPageRowsSelected()}\n onCheckedChange={(v) => table.toggleAllPageRowsSelected(!!v)}\n aria-label=\"Select all\"\n />\n ),\n cell: ({ row }) => (\n <Checkbox\n checked={row.getIsSelected()}\n onCheckedChange={(v) => row.toggleSelected(!!v)}\n aria-label=\"Select row\"\n onClick={(e) => e.stopPropagation()}\n />\n ),\n enableSorting: false,\n enableHiding: false,\n meta: { align: \"center\" },\n });\n }\n for (const col of columns) {\n cols.push({\n id: col.key,\n accessorKey: col.key,\n header: col.header,\n enableSorting: col.sortable ?? false,\n enableHiding: col.hideable !== false,\n cell: col.render\n ? (info) => col.render!(info.row.original)\n : (info) => String(info.getValue() ?? \"\"),\n meta: { align: col.align },\n });\n }\n return cols;\n}\n\nfunction exportToCsv<T>(columns: ColumnDef<T>[], data: T[], filename: string) {\n const headers = columns.map((c) => c.header);\n const rows = data.map((row) =>\n columns.map((col) => {\n const str = String(row[col.key] ?? \"\");\n return str.includes(\",\") || str.includes('\"') || str.includes(\"\\n\")\n ? `\"${str.replace(/\"/g, '\"\"')}\"`\n : str;\n }),\n );\n const csv = [headers.join(\",\"), ...rows.map((r) => r.join(\",\"))].join(\"\\n\");\n const blob = new Blob([csv], { type: \"text/csv;charset=utf-8;\" });\n const url = URL.createObjectURL(blob);\n const link = document.createElement(\"a\");\n link.href = url;\n link.download = `${filename}.csv`;\n link.click();\n URL.revokeObjectURL(url);\n}\n\n// ---------------------------------------------------------------------------\n// Sub-components\n// ---------------------------------------------------------------------------\n\nfunction SortIndicator({ direction }: { direction: false | \"asc\" | \"desc\" }) {\n if (direction === \"asc\") return <LuArrowUp className=\"h-4 w-4\" />;\n if (direction === \"desc\") return <LuArrowDown className=\"h-4 w-4\" />;\n return <LuArrowUpDown className=\"text-muted-foreground/50 h-4 w-4\" />;\n}\n\nfunction ColumnToggle<T>({ table }: { table: TanstackTable<T> }) {\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button variant=\"outline\" size=\"sm\">\n <LuSettings2 className=\"mr-2 h-4 w-4\" />\n Columns\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuLabel>Toggle columns</DropdownMenuLabel>\n <DropdownMenuSeparator />\n {table\n .getAllColumns()\n .filter((col) => col.getCanHide())\n .map((col) => (\n <DropdownMenuCheckboxItem\n key={col.id}\n checked={col.getIsVisible()}\n onCheckedChange={(v) => col.toggleVisibility(!!v)}\n >\n {col.columnDef.header as string}\n </DropdownMenuCheckboxItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n\nfunction HeaderCell<T>({ header }: { header: Header<T, unknown> }) {\n return (\n <TableHead\n className={cn(\n getAlignCn(header.column.columnDef.meta),\n header.column.getCanSort() && \"cursor-pointer select-none\",\n )}\n onClick={header.column.getToggleSortingHandler()}\n >\n <span className=\"inline-flex items-center gap-1\">\n {flexRender(header.column.columnDef.header, header.getContext())}\n {header.column.getCanSort() && <SortIndicator direction={header.column.getIsSorted()} />}\n </span>\n </TableHead>\n );\n}\n\nfunction DataCell<T>({ cell }: { cell: Cell<T, unknown> }) {\n return (\n <TableCell className={getAlignCn(cell.column.columnDef.meta)}>\n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n </TableCell>\n );\n}\n\nfunction DataRow<T>({ row, onRowClick }: { row: Row<T>; onRowClick?: (r: T) => void }) {\n return (\n <TableRow\n data-state={row.getIsSelected() ? \"selected\" : undefined}\n className={cn(onRowClick && \"cursor-pointer\")}\n onClick={onRowClick ? () => onRowClick(row.original) : undefined}\n >\n {row.getVisibleCells().map((cell) => (\n <DataCell key={cell.id} cell={cell} />\n ))}\n </TableRow>\n );\n}\n\nfunction ExportButton<T>({\n columns,\n data,\n csvFilename,\n}: {\n columns: ColumnDef<T>[];\n data: T[];\n csvFilename: string;\n}) {\n return (\n <Button variant=\"outline\" size=\"sm\" onClick={() => exportToCsv(columns, data, csvFilename)}>\n <LuDownload className=\"mr-2 h-4 w-4\" />\n Export\n </Button>\n );\n}\n\nfunction BulkActionsBar<T>({\n selectedRows,\n bulkActions,\n}: {\n selectedRows: T[];\n bulkActions: (rows: T[]) => React.ReactNode;\n}) {\n return (\n <div className=\"flex items-center gap-2\">\n <span className=\"text-muted-foreground text-sm\">{selectedRows.length} selected</span>\n {bulkActions(selectedRows)}\n </div>\n );\n}\n\nfunction Toolbar<T>({\n searchable,\n searchPlaceholder,\n globalFilter,\n onGlobalFilterChange,\n selectedRows,\n bulkActions,\n toolbar,\n exportCsv,\n columns,\n data,\n csvFilename,\n columnToggle,\n table,\n}: {\n searchable: boolean;\n searchPlaceholder: string;\n globalFilter: string;\n onGlobalFilterChange: (value: string) => void;\n selectedRows: T[];\n bulkActions?: (rows: T[]) => React.ReactNode;\n toolbar?: React.ReactNode;\n exportCsv: boolean;\n columns: ColumnDef<T>[];\n data: T[];\n csvFilename: string;\n columnToggle: boolean;\n table: TanstackTable<T>;\n}) {\n const hasSelection = selectedRows.length > 0;\n return (\n <div className=\"flex items-center gap-4\">\n {searchable && (\n <Input\n placeholder={searchPlaceholder}\n value={globalFilter}\n onChange={(e) => onGlobalFilterChange(e.target.value)}\n className=\"max-w-sm\"\n />\n )}\n {hasSelection && bulkActions && (\n <BulkActionsBar selectedRows={selectedRows} bulkActions={bulkActions} />\n )}\n <div className=\"ml-auto flex items-center gap-2\">\n {toolbar}\n {exportCsv && <ExportButton columns={columns} data={data} csvFilename={csvFilename} />}\n {columnToggle && <ColumnToggle table={table} />}\n </div>\n </div>\n );\n}\n\nfunction TableBodyContent<T>({\n loading,\n colSpan,\n emptyMessage,\n rows,\n onRowClick,\n}: {\n loading: boolean;\n colSpan: number;\n emptyMessage: string;\n rows: Row<T>[];\n onRowClick?: (r: T) => void;\n}) {\n if (loading) {\n return (\n <TableRow>\n <TableCell colSpan={colSpan} className=\"h-24 text-center\">\n <Spinner size=\"lg\" className=\"mx-auto\" />\n </TableCell>\n </TableRow>\n );\n }\n if (rows.length === 0) {\n return (\n <TableRow>\n <TableCell colSpan={colSpan} className=\"h-24 text-center\">\n {emptyMessage}\n </TableCell>\n </TableRow>\n );\n }\n return (\n <>\n {rows.map((row) => (\n <DataRow key={row.id} row={row} onRowClick={onRowClick} />\n ))}\n </>\n );\n}\n\nfunction PageSizeSelector({\n pageSize,\n options,\n onChange,\n}: {\n pageSize: number;\n options: number[];\n onChange: (size: number) => void;\n}) {\n return (\n <div className=\"flex items-center gap-2\">\n <span className=\"text-muted-foreground text-sm\">Rows per page</span>\n <Select value={String(pageSize)} onValueChange={(v) => onChange(Number(v))}>\n <SelectTrigger className=\"h-8 w-[70px]\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {options.map((size) => (\n <SelectItem key={size} value={String(size)}>\n {size}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n );\n}\n\nfunction PaginationFooter({ pagination }: { pagination?: DataTablePagination }) {\n if (!pagination) return null;\n const showPageSize =\n pagination.pageSizeOptions && pagination.pageSize !== undefined && pagination.onPageSizeChange;\n const showPages = pagination.totalPages > 1;\n if (!showPageSize && !showPages) return null;\n return (\n <div className=\"flex items-center justify-between\">\n {showPageSize ? (\n <PageSizeSelector\n pageSize={pagination.pageSize!}\n options={pagination.pageSizeOptions!}\n onChange={pagination.onPageSizeChange!}\n />\n ) : (\n <div />\n )}\n {showPages && (\n <ListPagination\n page={pagination.page}\n totalPages={pagination.totalPages}\n getHref={pagination.getHref}\n onPageChange={pagination.onPageChange}\n />\n )}\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Hook: encapsulates all state management and TanStack Table configuration\n// ---------------------------------------------------------------------------\n\ninterface UseDataTableOptions<T> {\n columns: ColumnDef<T>[];\n data: T[];\n selectable: boolean;\n getRowId?: (row: T) => string;\n pagination?: DataTablePagination;\n externalGlobalFilter?: string;\n onGlobalFilterChange?: (value: string) => void;\n externalSorting?: SortingState;\n onSortingChange?: (state: SortingState) => void;\n externalRowSelection?: RowSelectionState;\n onRowSelectionChange?: (state: RowSelectionState) => void;\n}\n\nfunction useDataTable<T>(opts: UseDataTableOptions<T>) {\n const isManualFiltering = opts.externalGlobalFilter !== undefined;\n const isManualSorting = opts.externalSorting !== undefined;\n\n const [internalSorting, setInternalSorting] = React.useState<SortingState>([]);\n const [internalGlobalFilter, setInternalGlobalFilter] = React.useState(\"\");\n const [internalRowSelection, setInternalRowSelection] = React.useState<RowSelectionState>({});\n const [columnVisibility, setColumnVisibility] = React.useState<VisibilityState>({});\n\n const sorting = opts.externalSorting ?? internalSorting;\n const globalFilter = opts.externalGlobalFilter ?? internalGlobalFilter;\n const rowSelectionState = opts.externalRowSelection ?? internalRowSelection;\n\n const handleSortingChange = opts.onSortingChange\n ? (updater: SortingState | ((prev: SortingState) => SortingState)) => {\n opts.onSortingChange!((updater as (prev: SortingState) => SortingState)(sorting));\n }\n : setInternalSorting;\n\n const handleGlobalFilterChange = opts.onGlobalFilterChange ?? setInternalGlobalFilter;\n\n const handleRowSelectionChange = opts.onRowSelectionChange\n ? (updater: RowSelectionState | ((prev: RowSelectionState) => RowSelectionState)) => {\n opts.onRowSelectionChange!(\n (updater as (prev: RowSelectionState) => RowSelectionState)(rowSelectionState),\n );\n }\n : setInternalRowSelection;\n\n const tanstackColumns = React.useMemo(\n () => buildTanstackColumns(opts.columns, opts.selectable),\n [opts.columns, opts.selectable],\n );\n\n const table = useReactTable({\n data: opts.data,\n columns: tanstackColumns,\n state: {\n sorting,\n globalFilter: isManualFiltering ? undefined : globalFilter,\n rowSelection: rowSelectionState,\n columnVisibility,\n },\n onSortingChange: handleSortingChange,\n onGlobalFilterChange: isManualFiltering ? undefined : setInternalGlobalFilter,\n onRowSelectionChange: handleRowSelectionChange,\n onColumnVisibilityChange: setColumnVisibility,\n getCoreRowModel: getCoreRowModel(),\n getSortedRowModel: isManualSorting ? undefined : getSortedRowModel(),\n getFilteredRowModel: isManualFiltering ? undefined : getFilteredRowModel(),\n manualSorting: isManualSorting,\n manualFiltering: isManualFiltering,\n manualPagination: opts.pagination !== undefined,\n enableRowSelection: opts.selectable,\n getRowId: opts.getRowId ? (row) => opts.getRowId!(row) : undefined,\n });\n\n const selectedRows = opts.selectable\n ? table.getSelectedRowModel().rows.map((r) => r.original)\n : [];\n\n return { table, tanstackColumns, globalFilter, handleGlobalFilterChange, selectedRows };\n}\n\n// ---------------------------------------------------------------------------\n// Main component\n// ---------------------------------------------------------------------------\n\nfunction DataTable<T>({\n columns,\n data,\n searchable = false,\n searchPlaceholder = \"Search...\",\n onRowClick,\n loading = false,\n emptyMessage = \"No results.\",\n toolbar,\n className,\n getRowId,\n pagination,\n globalFilter: externalGlobalFilter,\n onGlobalFilterChange,\n sortingState,\n onSortingChange,\n selectable = false,\n rowSelection,\n onRowSelectionChange,\n bulkActions,\n columnToggle = false,\n exportCsv = false,\n csvFilename = \"export\",\n}: DataTableProps<T>) {\n const { table, tanstackColumns, globalFilter, handleGlobalFilterChange, selectedRows } =\n useDataTable({\n columns,\n data,\n selectable,\n getRowId,\n pagination,\n externalGlobalFilter,\n onGlobalFilterChange,\n externalSorting: sortingState,\n onSortingChange,\n externalRowSelection: rowSelection,\n onRowSelectionChange,\n });\n\n const showToolbar = searchable || toolbar || columnToggle || exportCsv || selectedRows.length > 0;\n\n return (\n <div className={cn(\"space-y-4\", className)}>\n {showToolbar && (\n <Toolbar\n searchable={searchable}\n searchPlaceholder={searchPlaceholder}\n globalFilter={globalFilter}\n onGlobalFilterChange={handleGlobalFilterChange}\n selectedRows={selectedRows}\n bulkActions={bulkActions}\n toolbar={toolbar}\n exportCsv={exportCsv}\n columns={columns}\n data={data}\n csvFilename={csvFilename}\n columnToggle={columnToggle}\n table={table}\n />\n )}\n <Table>\n <TableHeader className=\"bg-background sticky top-0 z-10\">\n {table.getHeaderGroups().map((hg) => (\n <TableRow key={hg.id}>\n {hg.headers.map((h) => (\n <HeaderCell key={h.id} header={h} />\n ))}\n </TableRow>\n ))}\n </TableHeader>\n <TableBody>\n <TableBodyContent\n loading={loading}\n colSpan={tanstackColumns.length}\n emptyMessage={emptyMessage}\n rows={table.getRowModel().rows}\n onRowClick={onRowClick}\n />\n </TableBody>\n </Table>\n <PaginationFooter pagination={pagination} />\n </div>\n );\n}\nDataTable.displayName = \"DataTable\";\n\nexport { DataTable };\nexport type { SortingState, RowSelectionState, VisibilityState };\n"],"mappings":"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","names":[]}
|