@godxjp/ui 14.0.1 → 15.0.0
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/README.md +30 -27
- package/dist/components/admin/index.d.ts +0 -2
- package/dist/components/admin/index.js +0 -2
- package/dist/components/data-display/data-table.d.ts +58 -5
- package/dist/components/data-display/data-table.js +332 -78
- package/dist/components/data-display/index.d.ts +1 -1
- package/dist/components/data-display/index.js +2 -1
- package/dist/components/data-entry/search-input.d.ts +2 -1
- package/dist/components/data-entry/search-input.js +1 -1
- package/dist/components/general/index.d.ts +0 -2
- package/dist/components/general/index.js +1 -4
- package/dist/components/layout/topbar.d.ts +4 -4
- package/dist/props/components/layout.prop.d.ts +2 -2
- package/dist/props/vocabulary/data.prop.d.ts +6 -0
- package/dist/tokens/base.css +0 -1
- package/package.json +4 -11
- package/scripts/ui-audit.mjs +6 -1
- package/dist/components/data-grid/data-grid.d.ts +0 -67
- package/dist/components/data-grid/data-grid.js +0 -402
- package/dist/components/data-grid/index.d.ts +0 -2
- package/dist/components/data-grid/index.js +0 -4
- package/dist/components/general/logo.d.ts +0 -28
- package/dist/components/general/logo.js +0 -45
- package/dist/tokens/components/logo.css +0 -11
|
@@ -1,11 +1,45 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import * as React from "react";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
flexRender,
|
|
5
|
+
getCoreRowModel,
|
|
6
|
+
getFilteredRowModel,
|
|
7
|
+
getPaginationRowModel,
|
|
8
|
+
getSortedRowModel,
|
|
9
|
+
useReactTable
|
|
10
|
+
} from "@tanstack/react-table";
|
|
11
|
+
import {
|
|
12
|
+
ArrowDown,
|
|
13
|
+
ArrowUp,
|
|
14
|
+
ChevronLeft,
|
|
15
|
+
ChevronRight,
|
|
16
|
+
ChevronsUpDown,
|
|
17
|
+
Layers,
|
|
18
|
+
Layers2,
|
|
19
|
+
MoreHorizontal,
|
|
20
|
+
SlidersHorizontal
|
|
21
|
+
} from "lucide-react";
|
|
4
22
|
import { useTranslation } from "../../i18n/use-translation";
|
|
5
23
|
import { Flex } from "../layout/flex";
|
|
6
24
|
import { Button } from "../general/button";
|
|
7
25
|
import { EmptyState } from "./empty-state";
|
|
8
26
|
import { Checkbox } from "../data-entry/checkbox";
|
|
27
|
+
import { SearchInput } from "../data-entry/search-input";
|
|
28
|
+
import {
|
|
29
|
+
Select,
|
|
30
|
+
SelectContent,
|
|
31
|
+
SelectItem,
|
|
32
|
+
SelectTrigger,
|
|
33
|
+
SelectValue
|
|
34
|
+
} from "../data-entry/select";
|
|
35
|
+
import {
|
|
36
|
+
DropdownMenu,
|
|
37
|
+
DropdownMenuCheckboxItem,
|
|
38
|
+
DropdownMenuContent,
|
|
39
|
+
DropdownMenuLabel,
|
|
40
|
+
DropdownMenuSeparator,
|
|
41
|
+
DropdownMenuTrigger
|
|
42
|
+
} from "../navigation/dropdown-menu";
|
|
9
43
|
import {
|
|
10
44
|
Table,
|
|
11
45
|
TableBody,
|
|
@@ -21,6 +55,17 @@ import {
|
|
|
21
55
|
tableCellPaddingClass,
|
|
22
56
|
tableRowHeightClass
|
|
23
57
|
} from "../../lib/control-styles";
|
|
58
|
+
function toTanstackColumns(columns) {
|
|
59
|
+
return columns.map((col) => ({
|
|
60
|
+
id: col.key,
|
|
61
|
+
accessorFn: (row) => row[col.key],
|
|
62
|
+
header: () => col.header,
|
|
63
|
+
enableSorting: !!col.sortable,
|
|
64
|
+
enableHiding: col.enableHiding ?? true,
|
|
65
|
+
enableGlobalFilter: true,
|
|
66
|
+
meta: { lean: col }
|
|
67
|
+
}));
|
|
68
|
+
}
|
|
24
69
|
const DataTableContext = React.createContext(null);
|
|
25
70
|
function useDataTableContext() {
|
|
26
71
|
const ctx = React.useContext(DataTableContext);
|
|
@@ -36,6 +81,13 @@ const noopGetRowId = (row) => {
|
|
|
36
81
|
if (typeof id === "number") return String(id);
|
|
37
82
|
return "";
|
|
38
83
|
};
|
|
84
|
+
function sortToSortingState(sort) {
|
|
85
|
+
return sort ? [{ id: sort.key, desc: sort.direction === "desc" }] : [];
|
|
86
|
+
}
|
|
87
|
+
function sortingStateToSort(state) {
|
|
88
|
+
const first = state[0];
|
|
89
|
+
return first ? { key: first.id, direction: first.desc ? "desc" : "asc" } : void 0;
|
|
90
|
+
}
|
|
39
91
|
function DataTable({
|
|
40
92
|
data,
|
|
41
93
|
columns,
|
|
@@ -48,6 +100,16 @@ function DataTable({
|
|
|
48
100
|
onDensityChange,
|
|
49
101
|
sort,
|
|
50
102
|
onSortChange,
|
|
103
|
+
globalFilter: controlledGlobalFilter,
|
|
104
|
+
onGlobalFilterChange,
|
|
105
|
+
pagination: controlledPagination,
|
|
106
|
+
onPaginationChange,
|
|
107
|
+
rowCount,
|
|
108
|
+
columnVisibility: controlledVisibility,
|
|
109
|
+
onColumnVisibilityChange,
|
|
110
|
+
manualSorting = false,
|
|
111
|
+
manualFiltering = false,
|
|
112
|
+
manualPagination = false,
|
|
51
113
|
loading = false,
|
|
52
114
|
empty,
|
|
53
115
|
striped = false,
|
|
@@ -63,43 +125,87 @@ function DataTable({
|
|
|
63
125
|
setInternalDensity(d);
|
|
64
126
|
onDensityChange?.(d);
|
|
65
127
|
};
|
|
66
|
-
const [
|
|
67
|
-
const
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
128
|
+
const [internalSorting, setInternalSorting] = React.useState([]);
|
|
129
|
+
const [internalFilters] = React.useState([]);
|
|
130
|
+
const [internalGlobal, setInternalGlobal] = React.useState("");
|
|
131
|
+
const [internalPagination, setInternalPagination] = React.useState({
|
|
132
|
+
pageIndex: 0,
|
|
133
|
+
pageSize: 10
|
|
134
|
+
});
|
|
135
|
+
const [internalSelection, setInternalSelection] = React.useState({});
|
|
136
|
+
const [internalVisibility, setInternalVisibility] = React.useState({});
|
|
137
|
+
const selectionFromSet = React.useCallback(
|
|
138
|
+
(set) => Object.fromEntries([...set].map((id) => [id, true])),
|
|
139
|
+
[]
|
|
140
|
+
);
|
|
141
|
+
const sortingState = sort !== void 0 ? sortToSortingState(sort) : internalSorting;
|
|
142
|
+
const rowSelection = controlledSelected !== void 0 ? selectionFromSet(controlledSelected) : internalSelection;
|
|
143
|
+
const onSortingChange = (updater) => {
|
|
144
|
+
const next = typeof updater === "function" ? updater(sortingState) : updater;
|
|
145
|
+
if (sort !== void 0 || onSortChange) {
|
|
146
|
+
onSortChange?.(sortingStateToSort(next));
|
|
147
|
+
} else {
|
|
148
|
+
setInternalSorting(next);
|
|
149
|
+
}
|
|
71
150
|
};
|
|
72
|
-
const
|
|
73
|
-
const next =
|
|
74
|
-
if (
|
|
75
|
-
|
|
76
|
-
|
|
151
|
+
const onRowSelectionChange = (updater) => {
|
|
152
|
+
const next = typeof updater === "function" ? updater(rowSelection) : updater;
|
|
153
|
+
if (controlledSelected !== void 0 || onSelectChange) {
|
|
154
|
+
const set = new Set(Object.keys(next).filter((id) => next[id]));
|
|
155
|
+
onSelectChange?.(set);
|
|
156
|
+
if (controlledSelected === void 0) setInternalSelection(next);
|
|
157
|
+
} else {
|
|
158
|
+
setInternalSelection(next);
|
|
159
|
+
}
|
|
77
160
|
};
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
161
|
+
const onGlobalFilterChangeFn = (updater) => {
|
|
162
|
+
const current = controlledGlobalFilter ?? internalGlobal;
|
|
163
|
+
const next = typeof updater === "function" ? updater(current) : updater;
|
|
164
|
+
if (controlledGlobalFilter !== void 0 || onGlobalFilterChange) {
|
|
165
|
+
onGlobalFilterChange?.(next);
|
|
166
|
+
if (controlledGlobalFilter === void 0) setInternalGlobal(next);
|
|
167
|
+
} else {
|
|
168
|
+
setInternalGlobal(next);
|
|
169
|
+
}
|
|
84
170
|
};
|
|
85
|
-
const
|
|
171
|
+
const tanstackColumns = React.useMemo(() => toTanstackColumns(columns), [columns]);
|
|
172
|
+
const table = useReactTable({
|
|
86
173
|
data,
|
|
87
|
-
columns,
|
|
174
|
+
columns: tanstackColumns,
|
|
175
|
+
getRowId,
|
|
176
|
+
getCoreRowModel: getCoreRowModel(),
|
|
177
|
+
...manualSorting ? {} : { getSortedRowModel: getSortedRowModel() },
|
|
178
|
+
...manualFiltering ? {} : { getFilteredRowModel: getFilteredRowModel() },
|
|
179
|
+
...manualPagination ? {} : { getPaginationRowModel: getPaginationRowModel() },
|
|
180
|
+
manualSorting,
|
|
181
|
+
manualFiltering,
|
|
182
|
+
manualPagination,
|
|
183
|
+
rowCount,
|
|
184
|
+
enableRowSelection: selectable,
|
|
185
|
+
state: {
|
|
186
|
+
sorting: sortingState,
|
|
187
|
+
columnFilters: internalFilters,
|
|
188
|
+
globalFilter: controlledGlobalFilter ?? internalGlobal,
|
|
189
|
+
pagination: controlledPagination ?? internalPagination,
|
|
190
|
+
rowSelection,
|
|
191
|
+
columnVisibility: controlledVisibility ?? internalVisibility
|
|
192
|
+
},
|
|
193
|
+
onSortingChange,
|
|
194
|
+
onGlobalFilterChange: onGlobalFilterChangeFn,
|
|
195
|
+
onPaginationChange: onPaginationChange ?? setInternalPagination,
|
|
196
|
+
onRowSelectionChange,
|
|
197
|
+
onColumnVisibilityChange: onColumnVisibilityChange ?? setInternalVisibility
|
|
198
|
+
});
|
|
199
|
+
const ctx = {
|
|
200
|
+
table,
|
|
88
201
|
density,
|
|
89
202
|
setDensity,
|
|
90
|
-
selected,
|
|
91
|
-
toggleSelect,
|
|
92
|
-
toggleSelectAll,
|
|
93
|
-
allSelected,
|
|
94
|
-
someSelected,
|
|
95
203
|
selectable,
|
|
96
|
-
getRowId,
|
|
97
|
-
onRowClick,
|
|
98
204
|
sort,
|
|
99
205
|
onSortChange,
|
|
206
|
+
onRowClick,
|
|
100
207
|
loading,
|
|
101
208
|
empty,
|
|
102
|
-
emptyColSpan,
|
|
103
209
|
striped,
|
|
104
210
|
hoverable,
|
|
105
211
|
stickyHeader,
|
|
@@ -117,18 +223,82 @@ DataTable.Toolbar = function DataTableToolbar({
|
|
|
117
223
|
children,
|
|
118
224
|
className
|
|
119
225
|
}) {
|
|
120
|
-
return /* @__PURE__ */ jsx(
|
|
226
|
+
return /* @__PURE__ */ jsx(
|
|
227
|
+
Flex,
|
|
228
|
+
{
|
|
229
|
+
direction: "row",
|
|
230
|
+
align: "center",
|
|
231
|
+
justify: "between",
|
|
232
|
+
gap: "sm",
|
|
233
|
+
wrap: true,
|
|
234
|
+
className: cn("ui-data-table-toolbar", className),
|
|
235
|
+
children
|
|
236
|
+
}
|
|
237
|
+
);
|
|
121
238
|
};
|
|
122
239
|
DataTable.Toolbar.displayName = "DataTable.Toolbar";
|
|
240
|
+
DataTable.Search = function DataTableSearch({
|
|
241
|
+
placeholder,
|
|
242
|
+
className
|
|
243
|
+
}) {
|
|
244
|
+
const { table } = useDataTableContext();
|
|
245
|
+
const { t } = useTranslation();
|
|
246
|
+
const value = table.getState().globalFilter ?? "";
|
|
247
|
+
return /* @__PURE__ */ jsx(
|
|
248
|
+
SearchInput,
|
|
249
|
+
{
|
|
250
|
+
value,
|
|
251
|
+
onValueChange: (q) => table.setGlobalFilter(q),
|
|
252
|
+
onSearch: (q) => table.setGlobalFilter(q),
|
|
253
|
+
placeholder: placeholder ?? t("dataGrid.searchPlaceholder"),
|
|
254
|
+
ariaLabel: t("dataGrid.search"),
|
|
255
|
+
className
|
|
256
|
+
}
|
|
257
|
+
);
|
|
258
|
+
};
|
|
259
|
+
DataTable.Search.displayName = "DataTable.Search";
|
|
260
|
+
DataTable.ViewOptions = function DataTableViewOptions({ className }) {
|
|
261
|
+
const { table } = useDataTableContext();
|
|
262
|
+
const { t } = useTranslation();
|
|
263
|
+
const hideable = table.getAllLeafColumns().filter((c) => c.getCanHide());
|
|
264
|
+
if (hideable.length === 0) return null;
|
|
265
|
+
return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
|
|
266
|
+
/* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(Button, { variant: "outline", size: "sm", className, children: [
|
|
267
|
+
/* @__PURE__ */ jsx(SlidersHorizontal, { className: "size-4 shrink-0", "aria-hidden": "true" }),
|
|
268
|
+
t("dataGrid.view")
|
|
269
|
+
] }) }),
|
|
270
|
+
/* @__PURE__ */ jsxs(DropdownMenuContent, { align: "end", children: [
|
|
271
|
+
/* @__PURE__ */ jsx(DropdownMenuLabel, { children: t("dataGrid.toggleColumns") }),
|
|
272
|
+
/* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
|
|
273
|
+
hideable.map((column) => /* @__PURE__ */ jsx(
|
|
274
|
+
DropdownMenuCheckboxItem,
|
|
275
|
+
{
|
|
276
|
+
checked: column.getIsVisible(),
|
|
277
|
+
onCheckedChange: (v) => column.toggleVisibility(!!v),
|
|
278
|
+
children: columnLabel(column)
|
|
279
|
+
},
|
|
280
|
+
column.id
|
|
281
|
+
))
|
|
282
|
+
] })
|
|
283
|
+
] });
|
|
284
|
+
};
|
|
285
|
+
DataTable.ViewOptions.displayName = "DataTable.ViewOptions";
|
|
286
|
+
function columnLabel(column) {
|
|
287
|
+
const header = column.columnDef.meta?.lean?.header;
|
|
288
|
+
if (typeof header === "string" && header.length > 0) return header;
|
|
289
|
+
return column.id;
|
|
290
|
+
}
|
|
123
291
|
DataTable.SelectAll = function DataTableSelectAll() {
|
|
124
|
-
const {
|
|
292
|
+
const { table, selectable } = useDataTableContext();
|
|
125
293
|
const { t } = useTranslation();
|
|
126
294
|
if (!selectable) return null;
|
|
295
|
+
const allSelected = table.getIsAllPageRowsSelected();
|
|
296
|
+
const someSelected = table.getIsSomePageRowsSelected();
|
|
127
297
|
return /* @__PURE__ */ jsx(
|
|
128
298
|
Checkbox,
|
|
129
299
|
{
|
|
130
300
|
checked: allSelected ? true : someSelected ? "indeterminate" : false,
|
|
131
|
-
onCheckedChange:
|
|
301
|
+
onCheckedChange: (v) => table.toggleAllPageRowsSelected(!!v),
|
|
132
302
|
"aria-label": t("dataTable.selectAll")
|
|
133
303
|
}
|
|
134
304
|
);
|
|
@@ -141,8 +311,23 @@ DataTable.BulkActions = function DataTableBulkActions({
|
|
|
141
311
|
}) {
|
|
142
312
|
const ctx = useOptionalDataTableContext();
|
|
143
313
|
const { t } = useTranslation();
|
|
144
|
-
const
|
|
314
|
+
const selectedCount = ctx?.table.getSelectedRowModel().rows.length ?? 0;
|
|
315
|
+
const c = count ?? selectedCount;
|
|
145
316
|
if (c === 0) return null;
|
|
317
|
+
if (typeof children === "function") {
|
|
318
|
+
return /* @__PURE__ */ jsx(
|
|
319
|
+
Flex,
|
|
320
|
+
{
|
|
321
|
+
direction: "row",
|
|
322
|
+
align: "center",
|
|
323
|
+
gap: "sm",
|
|
324
|
+
role: "region",
|
|
325
|
+
"aria-label": t("dataTable.bulkActions"),
|
|
326
|
+
className,
|
|
327
|
+
children: children(c)
|
|
328
|
+
}
|
|
329
|
+
);
|
|
330
|
+
}
|
|
146
331
|
return /* @__PURE__ */ jsxs(
|
|
147
332
|
"div",
|
|
148
333
|
{
|
|
@@ -182,19 +367,13 @@ DataTable.DensityToggle = function DataTableDensityToggle() {
|
|
|
182
367
|
DataTable.DensityToggle.displayName = "DataTable.DensityToggle";
|
|
183
368
|
DataTable.Content = function DataTableContent() {
|
|
184
369
|
const {
|
|
185
|
-
|
|
186
|
-
columns,
|
|
187
|
-
density: _density,
|
|
370
|
+
table,
|
|
188
371
|
selectable,
|
|
189
|
-
selected,
|
|
190
|
-
toggleSelect,
|
|
191
|
-
getRowId,
|
|
192
|
-
onRowClick,
|
|
193
372
|
sort,
|
|
194
373
|
onSortChange,
|
|
374
|
+
onRowClick,
|
|
195
375
|
loading,
|
|
196
376
|
empty,
|
|
197
|
-
emptyColSpan,
|
|
198
377
|
striped,
|
|
199
378
|
hoverable,
|
|
200
379
|
stickyHeader,
|
|
@@ -203,17 +382,27 @@ DataTable.Content = function DataTableContent() {
|
|
|
203
382
|
const { t } = useTranslation();
|
|
204
383
|
const rowPadding = tableRowHeightClass;
|
|
205
384
|
const cellPadding = tableCellPaddingClass;
|
|
206
|
-
const
|
|
385
|
+
const visibleColumns = table.getVisibleLeafColumns().map((c) => c.columnDef.meta?.lean).filter((c) => !!c);
|
|
386
|
+
const emptyColSpan = visibleColumns.length + (selectable ? 1 : 0);
|
|
387
|
+
const hasPinEnd = visibleColumns.some((col) => col.pin === "end");
|
|
388
|
+
const activeSort = sort ?? sortingStateToSort(table.getState().sorting);
|
|
389
|
+
const isControlledSort = sort !== void 0 || !!onSortChange;
|
|
207
390
|
const onHeaderClick = (col) => {
|
|
208
|
-
if (!col.sortable
|
|
209
|
-
if (
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
391
|
+
if (!col.sortable) return;
|
|
392
|
+
if (isControlledSort) {
|
|
393
|
+
if (activeSort?.key !== col.key) {
|
|
394
|
+
onSortChange?.({ key: col.key, direction: "asc" });
|
|
395
|
+
} else if (activeSort.direction === "asc") {
|
|
396
|
+
onSortChange?.({ key: col.key, direction: "desc" });
|
|
397
|
+
} else {
|
|
398
|
+
onSortChange?.(void 0);
|
|
399
|
+
}
|
|
400
|
+
return;
|
|
215
401
|
}
|
|
402
|
+
table.getColumn(col.key)?.toggleSorting();
|
|
216
403
|
};
|
|
404
|
+
const dataRows = table.getRowModel().rows;
|
|
405
|
+
const rowCount = dataRows.length;
|
|
217
406
|
return /* @__PURE__ */ jsx(
|
|
218
407
|
"div",
|
|
219
408
|
{
|
|
@@ -228,10 +417,10 @@ DataTable.Content = function DataTableContent() {
|
|
|
228
417
|
children: /* @__PURE__ */ jsxs(Table, { children: [
|
|
229
418
|
/* @__PURE__ */ jsx(TableHeader, { className: cn("bg-secondary", stickyHeader && "sticky top-0 z-10"), children: /* @__PURE__ */ jsxs(TableRow, { children: [
|
|
230
419
|
selectable && /* @__PURE__ */ jsx(TableHead, { className: "w-10", children: /* @__PURE__ */ jsx(DataTable.SelectAll, {}) }),
|
|
231
|
-
|
|
232
|
-
const isSortable = !!col.sortable
|
|
233
|
-
const isActiveSort = isSortable &&
|
|
234
|
-
const sortIndicator = isSortable ? isActiveSort ?
|
|
420
|
+
visibleColumns.map((col) => {
|
|
421
|
+
const isSortable = !!col.sortable;
|
|
422
|
+
const isActiveSort = isSortable && activeSort?.key === col.key;
|
|
423
|
+
const sortIndicator = isSortable ? isActiveSort ? activeSort?.direction === "asc" ? /* @__PURE__ */ jsx(ArrowUp, { className: "size-3", "aria-hidden": "true" }) : /* @__PURE__ */ jsx(ArrowDown, { className: "size-3", "aria-hidden": "true" }) : /* @__PURE__ */ jsx(ChevronsUpDown, { className: "text-muted-foreground size-3", "aria-hidden": "true" }) : null;
|
|
235
424
|
const label = /* @__PURE__ */ jsxs("span", { className: "ui-data-table-sort-label", children: [
|
|
236
425
|
col.header,
|
|
237
426
|
sortIndicator
|
|
@@ -240,7 +429,7 @@ DataTable.Content = function DataTableContent() {
|
|
|
240
429
|
TableHead,
|
|
241
430
|
{
|
|
242
431
|
"data-empty": !col.header || void 0,
|
|
243
|
-
"aria-sort": isSortable ? isActiveSort ?
|
|
432
|
+
"aria-sort": isSortable ? isActiveSort ? activeSort?.direction === "asc" ? "ascending" : "descending" : "none" : void 0,
|
|
244
433
|
className: cn(
|
|
245
434
|
col.width,
|
|
246
435
|
col.align === "right" && "text-end",
|
|
@@ -270,9 +459,9 @@ DataTable.Content = function DataTableContent() {
|
|
|
270
459
|
// share its borders + column widths — no second framed container
|
|
271
460
|
// (which double-borders when the table sits in a Card). Count is
|
|
272
461
|
// bounded to the previous page so the height barely shifts.
|
|
273
|
-
Array.from({ length: Math.min(Math.max(
|
|
462
|
+
Array.from({ length: Math.min(Math.max(rowCount, 6), 10) }).map((_, i) => /* @__PURE__ */ jsxs(TableRow, { className: cn(rowPadding, "hover:bg-transparent"), children: [
|
|
274
463
|
selectable && /* @__PURE__ */ jsx(TableCell, { className: cellPadding, children: /* @__PURE__ */ jsx("div", { className: "ui-skeleton-block size-4 rounded-sm" }) }),
|
|
275
|
-
|
|
464
|
+
visibleColumns.map((col, j) => /* @__PURE__ */ jsx(
|
|
276
465
|
TableCell,
|
|
277
466
|
{
|
|
278
467
|
className: cn(
|
|
@@ -298,7 +487,7 @@ DataTable.Content = function DataTableContent() {
|
|
|
298
487
|
col.key
|
|
299
488
|
))
|
|
300
489
|
] }, `skeleton-${i}`))
|
|
301
|
-
) :
|
|
490
|
+
) : rowCount === 0 ? /* @__PURE__ */ jsx(TableRow, { className: "hover:bg-transparent", children: /* @__PURE__ */ jsx(
|
|
302
491
|
TableCell,
|
|
303
492
|
{
|
|
304
493
|
colSpan: emptyColSpan,
|
|
@@ -306,10 +495,12 @@ DataTable.Content = function DataTableContent() {
|
|
|
306
495
|
"aria-live": "polite",
|
|
307
496
|
children: empty ?? /* @__PURE__ */ jsx(EmptyState, { title: t("dataTable.empty") })
|
|
308
497
|
}
|
|
309
|
-
) }) :
|
|
310
|
-
const
|
|
311
|
-
const isSelected =
|
|
312
|
-
const isInteractiveTarget = (target) => !!target.closest(
|
|
498
|
+
) }) : dataRows.map((row) => {
|
|
499
|
+
const original = row.original;
|
|
500
|
+
const isSelected = row.getIsSelected();
|
|
501
|
+
const isInteractiveTarget = (target) => !!target.closest(
|
|
502
|
+
"button, a, input, select, textarea, [role=menuitem], [role=checkbox]"
|
|
503
|
+
);
|
|
313
504
|
return /* @__PURE__ */ jsxs(
|
|
314
505
|
TableRow,
|
|
315
506
|
{
|
|
@@ -318,13 +509,13 @@ DataTable.Content = function DataTableContent() {
|
|
|
318
509
|
onClick: (e) => {
|
|
319
510
|
const target = e.target;
|
|
320
511
|
if (isInteractiveTarget(target)) return;
|
|
321
|
-
onRowClick?.(
|
|
512
|
+
onRowClick?.(original);
|
|
322
513
|
},
|
|
323
514
|
onKeyDown: onRowClick ? (e) => {
|
|
324
515
|
if (e.key !== "Enter" && e.key !== " ") return;
|
|
325
516
|
if (e.target !== e.currentTarget) return;
|
|
326
517
|
e.preventDefault();
|
|
327
|
-
onRowClick?.(
|
|
518
|
+
onRowClick?.(original);
|
|
328
519
|
} : void 0,
|
|
329
520
|
className: cn(
|
|
330
521
|
rowPadding,
|
|
@@ -333,23 +524,23 @@ DataTable.Content = function DataTableContent() {
|
|
|
333
524
|
// …but the affordance (cursor + focus ring) only when clickable.
|
|
334
525
|
onRowClick && "focus-visible:ring-ring cursor-pointer focus-visible:ring-2 focus-visible:outline-none focus-visible:ring-inset",
|
|
335
526
|
isSelected && "bg-muted/30",
|
|
336
|
-
rowClassName?.(
|
|
527
|
+
rowClassName?.(original)
|
|
337
528
|
),
|
|
338
529
|
children: [
|
|
339
530
|
selectable && /* @__PURE__ */ jsx(TableCell, { className: cellPadding, children: /* @__PURE__ */ jsx(
|
|
340
531
|
Checkbox,
|
|
341
532
|
{
|
|
342
533
|
checked: isSelected,
|
|
343
|
-
onCheckedChange: () => {
|
|
344
|
-
|
|
534
|
+
onCheckedChange: (v) => {
|
|
535
|
+
row.toggleSelected(!!v);
|
|
345
536
|
},
|
|
346
|
-
"aria-label": t("dataTable.selectRow", { id }),
|
|
537
|
+
"aria-label": t("dataTable.selectRow", { id: row.id }),
|
|
347
538
|
onClick: (e) => {
|
|
348
539
|
e.stopPropagation();
|
|
349
540
|
}
|
|
350
541
|
}
|
|
351
542
|
) }),
|
|
352
|
-
|
|
543
|
+
visibleColumns.map((col) => /* @__PURE__ */ jsx(
|
|
353
544
|
TableCell,
|
|
354
545
|
{
|
|
355
546
|
className: cn(
|
|
@@ -360,8 +551,8 @@ DataTable.Content = function DataTableContent() {
|
|
|
360
551
|
col.hiddenOnMobile && "hidden md:table-cell",
|
|
361
552
|
col.pin === "end" && "ui-data-table-pin-end"
|
|
362
553
|
),
|
|
363
|
-
children: col.render ? col.render(
|
|
364
|
-
const v =
|
|
554
|
+
children: col.render ? col.render(original) : (() => {
|
|
555
|
+
const v = original[col.key];
|
|
365
556
|
if (v == null) return "\u2014";
|
|
366
557
|
if (typeof v === "string" || typeof v === "number") return String(v);
|
|
367
558
|
return "\u2014";
|
|
@@ -371,7 +562,7 @@ DataTable.Content = function DataTableContent() {
|
|
|
371
562
|
))
|
|
372
563
|
]
|
|
373
564
|
},
|
|
374
|
-
id
|
|
565
|
+
row.id
|
|
375
566
|
);
|
|
376
567
|
}) })
|
|
377
568
|
] })
|
|
@@ -381,12 +572,14 @@ DataTable.Content = function DataTableContent() {
|
|
|
381
572
|
);
|
|
382
573
|
};
|
|
383
574
|
DataTable.Content.displayName = "DataTable.Content";
|
|
384
|
-
DataTable.Pagination = function DataTablePagination({
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
}
|
|
575
|
+
DataTable.Pagination = function DataTablePagination(props) {
|
|
576
|
+
if ("onChange" in props && typeof props.onChange === "function") {
|
|
577
|
+
return /* @__PURE__ */ jsx(CursorPagination, { ...props });
|
|
578
|
+
}
|
|
579
|
+
return /* @__PURE__ */ jsx(NumberedPagination, { ...props });
|
|
580
|
+
};
|
|
581
|
+
DataTable.Pagination.displayName = "DataTable.Pagination";
|
|
582
|
+
function CursorPagination({ cursor, hasMore, onChange, className }) {
|
|
390
583
|
const { t } = useTranslation();
|
|
391
584
|
return /* @__PURE__ */ jsxs("div", { className: cn("ui-data-table-pagination", className), children: [
|
|
392
585
|
/* @__PURE__ */ jsx(
|
|
@@ -414,8 +607,68 @@ DataTable.Pagination = function DataTablePagination({
|
|
|
414
607
|
}
|
|
415
608
|
)
|
|
416
609
|
] });
|
|
417
|
-
}
|
|
418
|
-
|
|
610
|
+
}
|
|
611
|
+
function NumberedPagination({
|
|
612
|
+
pageSizeOptions = [10, 20, 50, 100],
|
|
613
|
+
className
|
|
614
|
+
}) {
|
|
615
|
+
const { table } = useDataTableContext();
|
|
616
|
+
const { t } = useTranslation();
|
|
617
|
+
const { pageIndex, pageSize } = table.getState().pagination;
|
|
618
|
+
const pageCount = table.getPageCount();
|
|
619
|
+
return /* @__PURE__ */ jsxs(
|
|
620
|
+
Flex,
|
|
621
|
+
{
|
|
622
|
+
direction: "row",
|
|
623
|
+
align: "center",
|
|
624
|
+
justify: "between",
|
|
625
|
+
gap: "md",
|
|
626
|
+
wrap: true,
|
|
627
|
+
className: cn("ui-data-table-pagination", className),
|
|
628
|
+
children: [
|
|
629
|
+
/* @__PURE__ */ jsxs(Flex, { direction: "row", align: "center", gap: "sm", children: [
|
|
630
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-sm", children: t("dataGrid.rowsPerPage") }),
|
|
631
|
+
/* @__PURE__ */ jsxs(
|
|
632
|
+
Select,
|
|
633
|
+
{
|
|
634
|
+
value: String(pageSize),
|
|
635
|
+
onValueChange: (v) => table.setPageSize(Number(v)),
|
|
636
|
+
children: [
|
|
637
|
+
/* @__PURE__ */ jsx(SelectTrigger, { size: "sm", "aria-label": t("dataGrid.rowsPerPage"), className: "tabular-nums", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
|
|
638
|
+
/* @__PURE__ */ jsx(SelectContent, { children: pageSizeOptions.map((n) => /* @__PURE__ */ jsx(SelectItem, { value: String(n), className: "tabular-nums", children: n }, n)) })
|
|
639
|
+
]
|
|
640
|
+
}
|
|
641
|
+
)
|
|
642
|
+
] }),
|
|
643
|
+
/* @__PURE__ */ jsxs(Flex, { direction: "row", align: "center", gap: "sm", children: [
|
|
644
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-sm tabular-nums", children: t("dataGrid.pageOf", { page: pageIndex + 1, total: Math.max(1, pageCount) }) }),
|
|
645
|
+
/* @__PURE__ */ jsx(
|
|
646
|
+
Button,
|
|
647
|
+
{
|
|
648
|
+
variant: "outline",
|
|
649
|
+
size: "icon",
|
|
650
|
+
disabled: !table.getCanPreviousPage(),
|
|
651
|
+
onClick: () => table.previousPage(),
|
|
652
|
+
"aria-label": t("common.previous") ?? "Previous",
|
|
653
|
+
children: /* @__PURE__ */ jsx(ChevronLeft, { className: "size-4", "aria-hidden": "true" })
|
|
654
|
+
}
|
|
655
|
+
),
|
|
656
|
+
/* @__PURE__ */ jsx(
|
|
657
|
+
Button,
|
|
658
|
+
{
|
|
659
|
+
variant: "outline",
|
|
660
|
+
size: "icon",
|
|
661
|
+
disabled: !table.getCanNextPage(),
|
|
662
|
+
onClick: () => table.nextPage(),
|
|
663
|
+
"aria-label": t("common.next") ?? "Next",
|
|
664
|
+
children: /* @__PURE__ */ jsx(ChevronRight, { className: "size-4", "aria-hidden": "true" })
|
|
665
|
+
}
|
|
666
|
+
)
|
|
667
|
+
] })
|
|
668
|
+
]
|
|
669
|
+
}
|
|
670
|
+
);
|
|
671
|
+
}
|
|
419
672
|
DataTable.RowActions = function DataTableRowActions({ ariaLabel, children }) {
|
|
420
673
|
const { t } = useTranslation();
|
|
421
674
|
return /* @__PURE__ */ jsxs(
|
|
@@ -434,5 +687,6 @@ DataTable.RowActions = function DataTableRowActions({ ariaLabel, children }) {
|
|
|
434
687
|
};
|
|
435
688
|
DataTable.RowActions.displayName = "DataTable.RowActions";
|
|
436
689
|
export {
|
|
437
|
-
DataTable
|
|
690
|
+
DataTable,
|
|
691
|
+
flexRender
|
|
438
692
|
};
|
|
@@ -7,7 +7,7 @@ export { Card, CardBar, CardContent, CardCover, CardDescription, CardFooter, Car
|
|
|
7
7
|
export type { StatCardProps, CardBarProps } from "./card";
|
|
8
8
|
export { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "./table";
|
|
9
9
|
export { Descriptions } from "./descriptions";
|
|
10
|
-
export { DataTable } from "./data-table";
|
|
10
|
+
export { DataTable, flexRender } from "./data-table";
|
|
11
11
|
export type { ColumnDef, Density as TableDensity } from "./data-table";
|
|
12
12
|
export type { SortStateProp } from "../../props/vocabulary";
|
|
13
13
|
export { EmptyState } from "./empty-state";
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
} from "./card";
|
|
16
16
|
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "./table";
|
|
17
17
|
import { Descriptions } from "./descriptions";
|
|
18
|
-
import { DataTable } from "./data-table";
|
|
18
|
+
import { DataTable, flexRender } from "./data-table";
|
|
19
19
|
import { EmptyState } from "./empty-state";
|
|
20
20
|
import { Progress } from "./progress";
|
|
21
21
|
import { TreeList } from "./tree-list";
|
|
@@ -95,5 +95,6 @@ export {
|
|
|
95
95
|
TableRow,
|
|
96
96
|
Timeline,
|
|
97
97
|
TreeList,
|
|
98
|
+
flexRender,
|
|
98
99
|
useCarousel
|
|
99
100
|
};
|
|
@@ -6,7 +6,8 @@ interface SearchInputProps {
|
|
|
6
6
|
debounce?: number;
|
|
7
7
|
/** Fires on EVERY keystroke (immediate) — required to keep a controlled `value` responsive. */
|
|
8
8
|
onValueChange?: (q: string) => void;
|
|
9
|
-
|
|
9
|
+
/** Fires with the DEBOUNCED term. Optional — omit it when you drive filtering off `onValueChange`. */
|
|
10
|
+
onSearch?: (q: string) => void;
|
|
10
11
|
label?: React.ReactNode;
|
|
11
12
|
ariaLabel?: string;
|
|
12
13
|
className?: string;
|
|
@@ -2,5 +2,3 @@ export { Button, buttonVariants } from "./button";
|
|
|
2
2
|
export type { ButtonProps } from "./button";
|
|
3
3
|
export { Text, Heading } from "./typography";
|
|
4
4
|
export type { TextProps, HeadingProps, TextProp, HeadingProp } from "./typography";
|
|
5
|
-
export { Logo, logoVariants } from "./logo";
|
|
6
|
-
export type { LogoProps } from "./logo";
|