datool 0.0.5 → 0.0.7
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 +15 -1
- package/client-dist/assets/index-BJjc4NKE.css +1 -0
- package/client-dist/assets/index-C6-ONVzY.js +164 -0
- package/client-dist/index.html +2 -2
- package/package.json +1 -1
- package/src/client/App.tsx +11 -40
- package/src/client/components/data-table-cell.tsx +19 -6
- package/src/client/components/data-table.tsx +487 -69
- package/src/node/config.ts +22 -0
- package/src/node/server.ts +96 -56
- package/src/shared/types.ts +4 -0
- package/client-dist/assets/index-DUkIilaZ.css +0 -1
- package/client-dist/assets/index-OdNyDkx7.js +0 -164
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
/* eslint-disable react-hooks/incompatible-library, react-refresh/only-export-components */
|
|
2
2
|
import {
|
|
3
|
+
getExpandedRowModel,
|
|
4
|
+
getGroupedRowModel,
|
|
3
5
|
functionalUpdate,
|
|
4
6
|
getCoreRowModel,
|
|
5
7
|
getFilteredRowModel,
|
|
6
8
|
getSortedRowModel,
|
|
7
9
|
useReactTable,
|
|
10
|
+
type AggregationFnOption,
|
|
8
11
|
type ColumnDef,
|
|
9
12
|
type ColumnFiltersState,
|
|
13
|
+
type ExpandedState,
|
|
10
14
|
type FilterFn,
|
|
15
|
+
type GroupingState,
|
|
11
16
|
type OnChangeFn,
|
|
12
17
|
type Row,
|
|
13
18
|
type RowData,
|
|
@@ -19,6 +24,8 @@ import {
|
|
|
19
24
|
import { useVirtualizer } from "@tanstack/react-virtual"
|
|
20
25
|
import {
|
|
21
26
|
Check,
|
|
27
|
+
ChevronDown,
|
|
28
|
+
ChevronRight,
|
|
22
29
|
CircleAlert,
|
|
23
30
|
EyeOff,
|
|
24
31
|
LayoutGrid,
|
|
@@ -46,7 +53,10 @@ import {
|
|
|
46
53
|
inferDataTableColumnKind,
|
|
47
54
|
type DataTableColumnKind,
|
|
48
55
|
} from "./data-table-col-icon"
|
|
49
|
-
import type {
|
|
56
|
+
import type {
|
|
57
|
+
DatoolDateFormat,
|
|
58
|
+
DatoolEnumColorMap,
|
|
59
|
+
} from "../../shared/types"
|
|
50
60
|
import { Button } from "@/components/ui/button"
|
|
51
61
|
import {
|
|
52
62
|
ContextMenu,
|
|
@@ -142,10 +152,13 @@ export type DataTableRowAction<TData extends DataTableRow> = {
|
|
|
142
152
|
export type DataTableColumnConfig<TData extends DataTableRow> = {
|
|
143
153
|
accessorFn?: (row: TData) => unknown
|
|
144
154
|
accessorKey?: Extract<keyof TData, string>
|
|
155
|
+
aggregatedCell?: ColumnDef<TData>["aggregatedCell"]
|
|
156
|
+
aggregationFn?: AggregationFnOption<TData>
|
|
145
157
|
align?: DataTableAlign
|
|
146
158
|
cell?: (args: { row: TData; value: unknown }) => React.ReactNode
|
|
147
159
|
cellClassName?: string
|
|
148
160
|
enableFiltering?: boolean
|
|
161
|
+
enableGrouping?: boolean
|
|
149
162
|
enableHiding?: boolean
|
|
150
163
|
enableResizing?: boolean
|
|
151
164
|
enableSorting?: boolean
|
|
@@ -161,6 +174,7 @@ export type DataTableColumnConfig<TData extends DataTableRow> = {
|
|
|
161
174
|
minWidth?: number
|
|
162
175
|
truncate?: boolean
|
|
163
176
|
width?: number
|
|
177
|
+
getGroupingValue?: (row: TData) => unknown
|
|
164
178
|
}
|
|
165
179
|
|
|
166
180
|
export type DataTableProps<TData extends DataTableRow> = {
|
|
@@ -170,10 +184,12 @@ export type DataTableProps<TData extends DataTableRow> = {
|
|
|
170
184
|
columnVisibility?: VisibilityState
|
|
171
185
|
columns?: DataTableColumnConfig<TData>[]
|
|
172
186
|
data: TData[]
|
|
187
|
+
dateFormat?: DatoolDateFormat
|
|
173
188
|
edgeHorizontalPadding?: React.CSSProperties["paddingLeft"]
|
|
174
189
|
enableRowSelection?: boolean
|
|
175
190
|
filterPlaceholder?: string
|
|
176
191
|
globalFilter?: string
|
|
192
|
+
grouping?: GroupingState
|
|
177
193
|
getRowId?: (row: TData, index: number) => string
|
|
178
194
|
height?: React.CSSProperties["height"]
|
|
179
195
|
highlightQuery?: string
|
|
@@ -181,6 +197,7 @@ export type DataTableProps<TData extends DataTableRow> = {
|
|
|
181
197
|
onColumnFiltersChange?: (value: ColumnFiltersState) => void
|
|
182
198
|
onColumnVisibilityChange?: (value: VisibilityState) => void
|
|
183
199
|
onGlobalFilterChange?: (value: string) => void
|
|
200
|
+
onGroupingChange?: (value: GroupingState) => void
|
|
184
201
|
resolveColumnHighlightTerms?: (columnId: string, query: string) => string[]
|
|
185
202
|
rowActions?: DataTableRowAction<TData>[]
|
|
186
203
|
rowClassName?: (row: TData) => string | undefined
|
|
@@ -227,6 +244,7 @@ type PersistedTableState = {
|
|
|
227
244
|
highlightedColumns?: Record<string, boolean>
|
|
228
245
|
columnVisibility?: VisibilityState
|
|
229
246
|
globalFilter?: string
|
|
247
|
+
grouping?: GroupingState
|
|
230
248
|
sorting?: SortingState
|
|
231
249
|
}
|
|
232
250
|
|
|
@@ -402,6 +420,7 @@ function getPersistedUrlParam(id: string) {
|
|
|
402
420
|
function isPersistedStateEmpty(state: PersistedTableState) {
|
|
403
421
|
return (
|
|
404
422
|
(state.sorting?.length ?? 0) === 0 &&
|
|
423
|
+
(state.grouping?.length ?? 0) === 0 &&
|
|
405
424
|
(state.columnFilters?.length ?? 0) === 0 &&
|
|
406
425
|
Object.keys(state.highlightedColumns ?? {}).length === 0 &&
|
|
407
426
|
Object.keys(state.columnVisibility ?? {}).length === 0 &&
|
|
@@ -496,6 +515,111 @@ function inferWidth(kind: DataTableColumnKind) {
|
|
|
496
515
|
}
|
|
497
516
|
}
|
|
498
517
|
|
|
518
|
+
type DateRangeAggregate = {
|
|
519
|
+
durationMs: number
|
|
520
|
+
endMs: number
|
|
521
|
+
startMs: number
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
function toTimestamp(value: unknown) {
|
|
525
|
+
if (value instanceof Date) {
|
|
526
|
+
return Number.isNaN(value.getTime()) ? null : value.getTime()
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
if (typeof value === "number") {
|
|
530
|
+
return Number.isFinite(value) ? value : null
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
if (typeof value === "string") {
|
|
534
|
+
const timestamp = Date.parse(value)
|
|
535
|
+
|
|
536
|
+
return Number.isNaN(timestamp) ? null : timestamp
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
return null
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
function buildDateRangeAggregate<TData extends DataTableRow>(
|
|
543
|
+
columnId: string,
|
|
544
|
+
leafRows: Row<TData>[]
|
|
545
|
+
) {
|
|
546
|
+
let startMs = Number.POSITIVE_INFINITY
|
|
547
|
+
let endMs = Number.NEGATIVE_INFINITY
|
|
548
|
+
|
|
549
|
+
for (const row of leafRows) {
|
|
550
|
+
const timestamp = toTimestamp(row.getValue(columnId))
|
|
551
|
+
|
|
552
|
+
if (timestamp === null) {
|
|
553
|
+
continue
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
startMs = Math.min(startMs, timestamp)
|
|
557
|
+
endMs = Math.max(endMs, timestamp)
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
if (
|
|
561
|
+
startMs === Number.POSITIVE_INFINITY ||
|
|
562
|
+
endMs === Number.NEGATIVE_INFINITY
|
|
563
|
+
) {
|
|
564
|
+
return null
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
return {
|
|
568
|
+
durationMs: Math.max(0, endMs - startMs),
|
|
569
|
+
endMs,
|
|
570
|
+
startMs,
|
|
571
|
+
} satisfies DateRangeAggregate
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
function isDateRangeAggregate(value: unknown): value is DateRangeAggregate {
|
|
575
|
+
return (
|
|
576
|
+
value !== null &&
|
|
577
|
+
typeof value === "object" &&
|
|
578
|
+
"durationMs" in value &&
|
|
579
|
+
"endMs" in value &&
|
|
580
|
+
"startMs" in value
|
|
581
|
+
)
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
function formatSummaryNumber(value: number) {
|
|
585
|
+
return new Intl.NumberFormat(undefined, {
|
|
586
|
+
maximumFractionDigits: Number.isInteger(value) ? 0 : 2,
|
|
587
|
+
}).format(value)
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
function formatDuration(durationMs: number) {
|
|
591
|
+
const totalSeconds = Math.max(0, Math.floor(durationMs / 1000))
|
|
592
|
+
const days = Math.floor(totalSeconds / 86_400)
|
|
593
|
+
const hours = Math.floor((totalSeconds % 86_400) / 3_600)
|
|
594
|
+
const minutes = Math.floor((totalSeconds % 3_600) / 60)
|
|
595
|
+
const seconds = totalSeconds % 60
|
|
596
|
+
const parts = [
|
|
597
|
+
days > 0 ? `${days}d` : null,
|
|
598
|
+
hours > 0 ? `${hours}h` : null,
|
|
599
|
+
minutes > 0 ? `${minutes}m` : null,
|
|
600
|
+
seconds > 0 || totalSeconds === 0 ? `${seconds}s` : null,
|
|
601
|
+
].filter(Boolean)
|
|
602
|
+
|
|
603
|
+
return parts.join(" ")
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
function resolveGroupedPadding(
|
|
607
|
+
padding: React.CSSProperties["paddingLeft"],
|
|
608
|
+
depth: number
|
|
609
|
+
) {
|
|
610
|
+
const indent = depth * 16
|
|
611
|
+
|
|
612
|
+
if (typeof padding === "number") {
|
|
613
|
+
return padding + indent
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
if (typeof padding === "string") {
|
|
617
|
+
return `calc(${padding} + ${indent}px)`
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
return indent
|
|
621
|
+
}
|
|
622
|
+
|
|
499
623
|
function resolveColumnId<TData extends DataTableRow>(
|
|
500
624
|
column: DataTableColumnConfig<TData>,
|
|
501
625
|
index: number
|
|
@@ -512,6 +636,7 @@ function resolveColumnId<TData extends DataTableRow>(
|
|
|
512
636
|
function buildColumns<TData extends DataTableRow>(
|
|
513
637
|
data: TData[],
|
|
514
638
|
columns?: DataTableColumnConfig<TData>[],
|
|
639
|
+
dateFormat?: DatoolDateFormat,
|
|
515
640
|
showRowSelectionColumn?: boolean,
|
|
516
641
|
showRowActionButtonsColumn?: boolean,
|
|
517
642
|
rowActionsColumnSize?: number
|
|
@@ -553,18 +678,29 @@ function buildColumns<TData extends DataTableRow>(
|
|
|
553
678
|
return {
|
|
554
679
|
accessorFn: column.accessorFn,
|
|
555
680
|
accessorKey: column.accessorKey,
|
|
681
|
+
aggregatedCell: column.aggregatedCell,
|
|
682
|
+
aggregationFn:
|
|
683
|
+
column.aggregationFn ??
|
|
684
|
+
(kind === "date"
|
|
685
|
+
? buildDateRangeAggregate
|
|
686
|
+
: kind === "number"
|
|
687
|
+
? "sum"
|
|
688
|
+
: undefined),
|
|
556
689
|
cell: ({ getValue, row }) =>
|
|
557
690
|
column.cell
|
|
558
691
|
? column.cell({ row: row.original, value: getValue() })
|
|
559
692
|
: fallbackCellValue(getValue(), kind, {
|
|
693
|
+
dateFormat,
|
|
560
694
|
enumColors: kind === "enum" ? column.enumColors : undefined,
|
|
561
695
|
enumOptions: kind === "enum" ? column.enumOptions : undefined,
|
|
562
696
|
}),
|
|
563
697
|
enableGlobalFilter: column.enableFiltering ?? true,
|
|
698
|
+
enableGrouping: column.enableGrouping ?? true,
|
|
564
699
|
filterFn: column.filterFn,
|
|
565
700
|
enableHiding: column.enableHiding ?? true,
|
|
566
701
|
enableResizing: column.enableResizing ?? true,
|
|
567
702
|
enableSorting: column.enableSorting ?? true,
|
|
703
|
+
getGroupingValue: column.getGroupingValue,
|
|
568
704
|
header: column.header ?? formatHeaderLabel(id),
|
|
569
705
|
id,
|
|
570
706
|
maxSize: column.maxWidth ?? 420,
|
|
@@ -583,6 +719,7 @@ function buildColumns<TData extends DataTableRow>(
|
|
|
583
719
|
...builtColumns,
|
|
584
720
|
{
|
|
585
721
|
cell: () => null,
|
|
722
|
+
enableGrouping: false,
|
|
586
723
|
enableGlobalFilter: false,
|
|
587
724
|
enableHiding: false,
|
|
588
725
|
enableResizing: false,
|
|
@@ -604,13 +741,16 @@ function buildColumns<TData extends DataTableRow>(
|
|
|
604
741
|
{
|
|
605
742
|
cell: ({ row }) => (
|
|
606
743
|
<div className="flex items-center justify-center">
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
744
|
+
{row.getCanSelect() ? (
|
|
745
|
+
<DataTableCheckbox
|
|
746
|
+
ariaLabel={`Select row ${row.index + 1}`}
|
|
747
|
+
checked={row.getIsSelected()}
|
|
748
|
+
onCheckedChange={(checked) => row.toggleSelected(checked)}
|
|
749
|
+
/>
|
|
750
|
+
) : null}
|
|
612
751
|
</div>
|
|
613
752
|
),
|
|
753
|
+
enableGrouping: false,
|
|
614
754
|
enableGlobalFilter: false,
|
|
615
755
|
enableHiding: false,
|
|
616
756
|
enableResizing: false,
|
|
@@ -649,6 +789,7 @@ function buildColumns<TData extends DataTableRow>(
|
|
|
649
789
|
...withSelectionColumn,
|
|
650
790
|
{
|
|
651
791
|
cell: () => null,
|
|
792
|
+
enableGrouping: false,
|
|
652
793
|
enableGlobalFilter: false,
|
|
653
794
|
enableHiding: false,
|
|
654
795
|
enableResizing: false,
|
|
@@ -704,6 +845,31 @@ function shouldIgnoreRowSelectionTarget(target: EventTarget | null) {
|
|
|
704
845
|
)
|
|
705
846
|
}
|
|
706
847
|
|
|
848
|
+
function shouldIgnoreSelectionShortcutTarget(target: EventTarget | null) {
|
|
849
|
+
return (
|
|
850
|
+
target instanceof Element &&
|
|
851
|
+
Boolean(
|
|
852
|
+
target.closest(
|
|
853
|
+
[
|
|
854
|
+
"a",
|
|
855
|
+
"button",
|
|
856
|
+
"input",
|
|
857
|
+
"select",
|
|
858
|
+
"textarea",
|
|
859
|
+
"[contenteditable=true]",
|
|
860
|
+
'[role="button"]',
|
|
861
|
+
'[role="combobox"]',
|
|
862
|
+
'[role="dialog"]',
|
|
863
|
+
'[role="menu"]',
|
|
864
|
+
'[role="menuitem"]',
|
|
865
|
+
'[role="searchbox"]',
|
|
866
|
+
'[role="textbox"]',
|
|
867
|
+
].join(",")
|
|
868
|
+
)
|
|
869
|
+
)
|
|
870
|
+
)
|
|
871
|
+
}
|
|
872
|
+
|
|
707
873
|
function resolveRowActionRows<TData extends DataTableRow>(
|
|
708
874
|
action: DataTableRowAction<TData>,
|
|
709
875
|
row: Row<TData>,
|
|
@@ -1126,10 +1292,12 @@ function DataTableView<TData extends DataTableRow>({
|
|
|
1126
1292
|
columnVisibility: controlledColumnVisibility,
|
|
1127
1293
|
columns,
|
|
1128
1294
|
data,
|
|
1295
|
+
dateFormat,
|
|
1129
1296
|
edgeHorizontalPadding = "16px",
|
|
1130
1297
|
enableRowSelection = false,
|
|
1131
1298
|
filterPlaceholder = "Search across visible columns",
|
|
1132
1299
|
globalFilter,
|
|
1300
|
+
grouping: controlledGrouping,
|
|
1133
1301
|
getRowId,
|
|
1134
1302
|
height = 620,
|
|
1135
1303
|
highlightQuery = "",
|
|
@@ -1137,6 +1305,7 @@ function DataTableView<TData extends DataTableRow>({
|
|
|
1137
1305
|
onColumnFiltersChange,
|
|
1138
1306
|
onColumnVisibilityChange,
|
|
1139
1307
|
onGlobalFilterChange,
|
|
1308
|
+
onGroupingChange,
|
|
1140
1309
|
resolveColumnHighlightTerms,
|
|
1141
1310
|
rowActions,
|
|
1142
1311
|
rowClassName,
|
|
@@ -1163,6 +1332,12 @@ function DataTableView<TData extends DataTableRow>({
|
|
|
1163
1332
|
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
|
|
1164
1333
|
() => persistedState.columnFilters ?? []
|
|
1165
1334
|
)
|
|
1335
|
+
const [grouping, setGrouping] = React.useState<GroupingState>(
|
|
1336
|
+
() => persistedState.grouping ?? []
|
|
1337
|
+
)
|
|
1338
|
+
const [expanded, setExpanded] = React.useState<ExpandedState>(() =>
|
|
1339
|
+
(controlledGrouping ?? persistedState.grouping ?? []).length > 0 ? true : {}
|
|
1340
|
+
)
|
|
1166
1341
|
const [rowSelection, setRowSelection] = React.useState<RowSelectionState>({})
|
|
1167
1342
|
const [rowActionStatuses, setRowActionStatuses] = React.useState<
|
|
1168
1343
|
Record<string, RowActionStatus>
|
|
@@ -1185,9 +1360,15 @@ function DataTableView<TData extends DataTableRow>({
|
|
|
1185
1360
|
const isColumnFiltersControlled = controlledColumnFilters !== undefined
|
|
1186
1361
|
const isColumnVisibilityControlled = controlledColumnVisibility !== undefined
|
|
1187
1362
|
const isGlobalFilterControlled = globalFilter !== undefined
|
|
1363
|
+
const isGroupingControlled = controlledGrouping !== undefined
|
|
1188
1364
|
const resolvedColumnFilters = controlledColumnFilters ?? columnFilters
|
|
1189
1365
|
const resolvedColumnVisibility =
|
|
1190
1366
|
controlledColumnVisibility ?? columnVisibility
|
|
1367
|
+
const resolvedGrouping = controlledGrouping ?? grouping
|
|
1368
|
+
const groupingKey = React.useMemo(
|
|
1369
|
+
() => resolvedGrouping.join("\u001f"),
|
|
1370
|
+
[resolvedGrouping]
|
|
1371
|
+
)
|
|
1191
1372
|
const hasSelectionActions = rowActions
|
|
1192
1373
|
? hasSelectionScopedAction(rowActions)
|
|
1193
1374
|
: false
|
|
@@ -1234,6 +1415,7 @@ function DataTableView<TData extends DataTableRow>({
|
|
|
1234
1415
|
buildColumns(
|
|
1235
1416
|
data,
|
|
1236
1417
|
columnsWithEnumOptions,
|
|
1418
|
+
dateFormat,
|
|
1237
1419
|
showRowSelectionColumn,
|
|
1238
1420
|
showRowActionButtonsColumn,
|
|
1239
1421
|
rowActionsColumnSize
|
|
@@ -1241,6 +1423,7 @@ function DataTableView<TData extends DataTableRow>({
|
|
|
1241
1423
|
[
|
|
1242
1424
|
columnsWithEnumOptions,
|
|
1243
1425
|
data,
|
|
1426
|
+
dateFormat,
|
|
1244
1427
|
rowActionsColumnSize,
|
|
1245
1428
|
showRowActionButtonsColumn,
|
|
1246
1429
|
showRowSelectionColumn,
|
|
@@ -1314,28 +1497,50 @@ function DataTableView<TData extends DataTableRow>({
|
|
|
1314
1497
|
resolvedColumnVisibility,
|
|
1315
1498
|
]
|
|
1316
1499
|
)
|
|
1500
|
+
const handleGroupingChange = React.useCallback<OnChangeFn<GroupingState>>(
|
|
1501
|
+
(updater) => {
|
|
1502
|
+
const nextValue = functionalUpdate(updater, resolvedGrouping)
|
|
1503
|
+
|
|
1504
|
+
if (!isGroupingControlled) {
|
|
1505
|
+
setGrouping(nextValue)
|
|
1506
|
+
}
|
|
1507
|
+
|
|
1508
|
+
onGroupingChange?.(nextValue)
|
|
1509
|
+
},
|
|
1510
|
+
[isGroupingControlled, onGroupingChange, resolvedGrouping]
|
|
1511
|
+
)
|
|
1317
1512
|
|
|
1318
1513
|
const table = useReactTable({
|
|
1514
|
+
autoResetExpanded: false,
|
|
1319
1515
|
columnResizeMode: "onChange",
|
|
1320
1516
|
columns: tableColumns,
|
|
1321
1517
|
data,
|
|
1322
1518
|
enableColumnResizing: true,
|
|
1323
|
-
|
|
1519
|
+
enableGrouping: true,
|
|
1520
|
+
enableRowSelection: canSelectRows ? (row) => !row.getIsGrouped() : false,
|
|
1521
|
+
enableSubRowSelection: false,
|
|
1324
1522
|
getCoreRowModel: getCoreRowModel(),
|
|
1523
|
+
getExpandedRowModel: getExpandedRowModel(),
|
|
1325
1524
|
getFilteredRowModel: getFilteredRowModel(),
|
|
1525
|
+
getGroupedRowModel: getGroupedRowModel(),
|
|
1326
1526
|
getRowId,
|
|
1327
1527
|
getSortedRowModel: getSortedRowModel(),
|
|
1528
|
+
groupedColumnMode: false,
|
|
1328
1529
|
globalFilterFn: globalFilterFn as FilterFn<TData>,
|
|
1329
1530
|
onColumnFiltersChange: handleColumnFiltersChange,
|
|
1330
1531
|
onColumnSizingChange: handleColumnSizingChange,
|
|
1331
1532
|
onColumnVisibilityChange: handleColumnVisibilityChange,
|
|
1533
|
+
onExpandedChange: setExpanded,
|
|
1534
|
+
onGroupingChange: handleGroupingChange,
|
|
1332
1535
|
onRowSelectionChange: setRowSelection,
|
|
1333
1536
|
onSortingChange: setSorting,
|
|
1334
1537
|
state: {
|
|
1335
1538
|
columnFilters: resolvedColumnFilters,
|
|
1336
1539
|
columnSizing,
|
|
1337
1540
|
columnVisibility: resolvedColumnVisibility,
|
|
1541
|
+
expanded,
|
|
1338
1542
|
globalFilter: deferredSearch.trim(),
|
|
1543
|
+
grouping: resolvedGrouping,
|
|
1339
1544
|
rowSelection,
|
|
1340
1545
|
sorting,
|
|
1341
1546
|
},
|
|
@@ -1346,6 +1551,10 @@ function DataTableView<TData extends DataTableRow>({
|
|
|
1346
1551
|
const hasAutoScrolledOnMountRef = React.useRef(false)
|
|
1347
1552
|
const previousDataLengthRef = React.useRef(0)
|
|
1348
1553
|
const rows = table.getRowModel().rows
|
|
1554
|
+
const selectableRows = React.useMemo(
|
|
1555
|
+
() => rows.filter((row) => row.getCanSelect()),
|
|
1556
|
+
[rows]
|
|
1557
|
+
)
|
|
1349
1558
|
const selectedTableRows = table.getSelectedRowModel().rows
|
|
1350
1559
|
const resolvedHeight = typeof height === "number" ? height : 0
|
|
1351
1560
|
const initialOffsetRef = React.useRef(
|
|
@@ -1387,6 +1596,15 @@ function DataTableView<TData extends DataTableRow>({
|
|
|
1387
1596
|
}
|
|
1388
1597
|
setHighlightedColumns(nextState.highlightedColumns ?? {})
|
|
1389
1598
|
setColumnFilters(nextState.columnFilters ?? [])
|
|
1599
|
+
if (!isGroupingControlled) {
|
|
1600
|
+
setGrouping(nextState.grouping ?? [])
|
|
1601
|
+
}
|
|
1602
|
+
setExpanded(
|
|
1603
|
+
(isGroupingControlled ? controlledGrouping : nextState.grouping ?? [])
|
|
1604
|
+
.length > 0
|
|
1605
|
+
? true
|
|
1606
|
+
: {}
|
|
1607
|
+
)
|
|
1390
1608
|
setSearchDraft(nextState.globalFilter ?? "")
|
|
1391
1609
|
setRowSelection({})
|
|
1392
1610
|
dragSelectionRef.current = null
|
|
@@ -1398,7 +1616,14 @@ function DataTableView<TData extends DataTableRow>({
|
|
|
1398
1616
|
}
|
|
1399
1617
|
rowActionStatusTimersRef.current = {}
|
|
1400
1618
|
setRowActionStatuses({})
|
|
1401
|
-
}, [
|
|
1619
|
+
}, [
|
|
1620
|
+
controlledGrouping,
|
|
1621
|
+
id,
|
|
1622
|
+
isColumnFiltersControlled,
|
|
1623
|
+
isColumnVisibilityControlled,
|
|
1624
|
+
isGroupingControlled,
|
|
1625
|
+
statePersistence,
|
|
1626
|
+
])
|
|
1402
1627
|
|
|
1403
1628
|
React.useEffect(() => {
|
|
1404
1629
|
if (!isColumnFiltersControlled) {
|
|
@@ -1416,6 +1641,14 @@ function DataTableView<TData extends DataTableRow>({
|
|
|
1416
1641
|
setColumnVisibility(controlledColumnVisibility)
|
|
1417
1642
|
}, [controlledColumnVisibility, isColumnVisibilityControlled])
|
|
1418
1643
|
|
|
1644
|
+
React.useEffect(() => {
|
|
1645
|
+
if (!isGroupingControlled) {
|
|
1646
|
+
return
|
|
1647
|
+
}
|
|
1648
|
+
|
|
1649
|
+
setGrouping(controlledGrouping)
|
|
1650
|
+
}, [controlledGrouping, isGroupingControlled])
|
|
1651
|
+
|
|
1419
1652
|
React.useEffect(() => {
|
|
1420
1653
|
if (!isGlobalFilterControlled) {
|
|
1421
1654
|
return
|
|
@@ -1439,6 +1672,15 @@ function DataTableView<TData extends DataTableRow>({
|
|
|
1439
1672
|
}
|
|
1440
1673
|
setHighlightedColumns(nextState.highlightedColumns ?? {})
|
|
1441
1674
|
setColumnFilters(nextState.columnFilters ?? [])
|
|
1675
|
+
if (!isGroupingControlled) {
|
|
1676
|
+
setGrouping(nextState.grouping ?? [])
|
|
1677
|
+
}
|
|
1678
|
+
setExpanded(
|
|
1679
|
+
(isGroupingControlled ? controlledGrouping : nextState.grouping ?? [])
|
|
1680
|
+
.length > 0
|
|
1681
|
+
? true
|
|
1682
|
+
: {}
|
|
1683
|
+
)
|
|
1442
1684
|
setSearchDraft(nextState.globalFilter ?? "")
|
|
1443
1685
|
setRowSelection({})
|
|
1444
1686
|
dragSelectionRef.current = null
|
|
@@ -1450,7 +1692,13 @@ function DataTableView<TData extends DataTableRow>({
|
|
|
1450
1692
|
window.addEventListener("popstate", syncFromUrl)
|
|
1451
1693
|
|
|
1452
1694
|
return () => window.removeEventListener("popstate", syncFromUrl)
|
|
1453
|
-
}, [
|
|
1695
|
+
}, [
|
|
1696
|
+
controlledGrouping,
|
|
1697
|
+
id,
|
|
1698
|
+
isColumnVisibilityControlled,
|
|
1699
|
+
isGroupingControlled,
|
|
1700
|
+
statePersistence,
|
|
1701
|
+
])
|
|
1454
1702
|
|
|
1455
1703
|
React.useEffect(() => {
|
|
1456
1704
|
if (isGlobalFilterControlled || isColumnFiltersControlled) {
|
|
@@ -1463,6 +1711,7 @@ function DataTableView<TData extends DataTableRow>({
|
|
|
1463
1711
|
highlightedColumns,
|
|
1464
1712
|
columnVisibility: resolvedColumnVisibility,
|
|
1465
1713
|
globalFilter: deferredSearch.trim(),
|
|
1714
|
+
grouping: resolvedGrouping,
|
|
1466
1715
|
sorting,
|
|
1467
1716
|
})
|
|
1468
1717
|
}, [
|
|
@@ -1473,11 +1722,17 @@ function DataTableView<TData extends DataTableRow>({
|
|
|
1473
1722
|
id,
|
|
1474
1723
|
isColumnFiltersControlled,
|
|
1475
1724
|
isGlobalFilterControlled,
|
|
1725
|
+
isGroupingControlled,
|
|
1476
1726
|
resolvedColumnVisibility,
|
|
1727
|
+
resolvedGrouping,
|
|
1477
1728
|
sorting,
|
|
1478
1729
|
statePersistence,
|
|
1479
1730
|
])
|
|
1480
1731
|
|
|
1732
|
+
React.useEffect(() => {
|
|
1733
|
+
setExpanded(resolvedGrouping.length > 0 ? true : {})
|
|
1734
|
+
}, [groupingKey, resolvedGrouping.length])
|
|
1735
|
+
|
|
1481
1736
|
React.useEffect(() => {
|
|
1482
1737
|
const container = containerRef.current
|
|
1483
1738
|
|
|
@@ -1579,6 +1834,13 @@ function DataTableView<TData extends DataTableRow>({
|
|
|
1579
1834
|
|
|
1580
1835
|
onGlobalFilterChange?.(value)
|
|
1581
1836
|
}
|
|
1837
|
+
const clearRowSelection = React.useCallback(() => {
|
|
1838
|
+
setRowSelection({})
|
|
1839
|
+
dragSelectionRef.current = null
|
|
1840
|
+
dragPointerRef.current = null
|
|
1841
|
+
setIsDragSelecting(false)
|
|
1842
|
+
selectionAnchorIdRef.current = null
|
|
1843
|
+
}, [])
|
|
1582
1844
|
|
|
1583
1845
|
const isColumnHighlightEnabled = React.useCallback(
|
|
1584
1846
|
(columnId: string, meta: DataTableColumnMeta) =>
|
|
@@ -1591,10 +1853,10 @@ function DataTableView<TData extends DataTableRow>({
|
|
|
1591
1853
|
rowId: string,
|
|
1592
1854
|
baseSelection: RowSelectionState = {}
|
|
1593
1855
|
) => {
|
|
1594
|
-
const anchorIndex =
|
|
1856
|
+
const anchorIndex = selectableRows.findIndex(
|
|
1595
1857
|
(candidateRow) => candidateRow.id === anchorId
|
|
1596
1858
|
)
|
|
1597
|
-
const rowIndex =
|
|
1859
|
+
const rowIndex = selectableRows.findIndex(
|
|
1598
1860
|
(candidateRow) => candidateRow.id === rowId
|
|
1599
1861
|
)
|
|
1600
1862
|
|
|
@@ -1610,13 +1872,13 @@ function DataTableView<TData extends DataTableRow>({
|
|
|
1610
1872
|
setRowSelection({
|
|
1611
1873
|
...baseSelection,
|
|
1612
1874
|
...Object.fromEntries(
|
|
1613
|
-
|
|
1875
|
+
selectableRows
|
|
1614
1876
|
.slice(start, end + 1)
|
|
1615
1877
|
.map((candidateRow) => [candidateRow.id, true])
|
|
1616
1878
|
),
|
|
1617
1879
|
})
|
|
1618
1880
|
},
|
|
1619
|
-
[
|
|
1881
|
+
[selectableRows]
|
|
1620
1882
|
)
|
|
1621
1883
|
const selectSingleRow = React.useCallback((rowId: string) => {
|
|
1622
1884
|
selectionAnchorIdRef.current = rowId
|
|
@@ -1663,6 +1925,7 @@ function DataTableView<TData extends DataTableRow>({
|
|
|
1663
1925
|
if (
|
|
1664
1926
|
event.button !== 0 ||
|
|
1665
1927
|
!canSelectRows ||
|
|
1928
|
+
!row.getCanSelect() ||
|
|
1666
1929
|
shouldIgnoreRowSelectionTarget(event.target)
|
|
1667
1930
|
) {
|
|
1668
1931
|
return
|
|
@@ -1724,6 +1987,7 @@ function DataTableView<TData extends DataTableRow>({
|
|
|
1724
1987
|
(event: React.MouseEvent<HTMLTableRowElement>, row: Row<TData>) => {
|
|
1725
1988
|
if (
|
|
1726
1989
|
!canSelectRows ||
|
|
1990
|
+
!row.getCanSelect() ||
|
|
1727
1991
|
event.buttons !== 1 ||
|
|
1728
1992
|
shouldIgnoreRowSelectionTarget(event.target) ||
|
|
1729
1993
|
!dragSelectionRef.current
|
|
@@ -1739,7 +2003,7 @@ function DataTableView<TData extends DataTableRow>({
|
|
|
1739
2003
|
)
|
|
1740
2004
|
const handleRowContextMenu = React.useCallback(
|
|
1741
2005
|
(row: Row<TData>) => {
|
|
1742
|
-
if (!canSelectRows) {
|
|
2006
|
+
if (!canSelectRows || !row.getCanSelect()) {
|
|
1743
2007
|
return
|
|
1744
2008
|
}
|
|
1745
2009
|
|
|
@@ -1819,6 +2083,27 @@ function DataTableView<TData extends DataTableRow>({
|
|
|
1819
2083
|
window.cancelAnimationFrame(frameId)
|
|
1820
2084
|
}
|
|
1821
2085
|
}, [isDragSelecting, updateDragSelectionFromPointer])
|
|
2086
|
+
React.useEffect(() => {
|
|
2087
|
+
if (!canSelectRows) {
|
|
2088
|
+
return
|
|
2089
|
+
}
|
|
2090
|
+
|
|
2091
|
+
const handleWindowKeyDown = (event: KeyboardEvent) => {
|
|
2092
|
+
if (
|
|
2093
|
+
event.key !== "Escape" ||
|
|
2094
|
+
Object.keys(rowSelection).length === 0 ||
|
|
2095
|
+
shouldIgnoreSelectionShortcutTarget(event.target)
|
|
2096
|
+
) {
|
|
2097
|
+
return
|
|
2098
|
+
}
|
|
2099
|
+
|
|
2100
|
+
clearRowSelection()
|
|
2101
|
+
}
|
|
2102
|
+
|
|
2103
|
+
window.addEventListener("keydown", handleWindowKeyDown)
|
|
2104
|
+
|
|
2105
|
+
return () => window.removeEventListener("keydown", handleWindowKeyDown)
|
|
2106
|
+
}, [canSelectRows, clearRowSelection, rowSelection])
|
|
1822
2107
|
|
|
1823
2108
|
return (
|
|
1824
2109
|
<section
|
|
@@ -1896,66 +2181,160 @@ function DataTableView<TData extends DataTableRow>({
|
|
|
1896
2181
|
) : (
|
|
1897
2182
|
virtualRows.map((virtualRow) => {
|
|
1898
2183
|
const row = rows[virtualRow.index]
|
|
1899
|
-
const
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
2184
|
+
const isGroupRow = row.getIsGrouped()
|
|
2185
|
+
const visibleRowActions = isGroupRow
|
|
2186
|
+
? []
|
|
2187
|
+
: resolveVisibleRowActions(
|
|
2188
|
+
rowActions ?? [],
|
|
2189
|
+
row,
|
|
2190
|
+
selectedTableRows
|
|
2191
|
+
)
|
|
1904
2192
|
const isSelected = row.getIsSelected()
|
|
2193
|
+
const groupVisibleCells = row.getVisibleCells()
|
|
2194
|
+
const groupingColumn = row.groupingColumnId
|
|
2195
|
+
? table.getColumn(row.groupingColumnId)
|
|
2196
|
+
: undefined
|
|
2197
|
+
const groupingMeta = groupingColumn?.columnDef.meta as
|
|
2198
|
+
| DataTableColumnMeta
|
|
2199
|
+
| undefined
|
|
2200
|
+
const groupingValue = groupingColumn
|
|
2201
|
+
? fallbackCellValue(row.groupingValue, groupingMeta?.kind, {
|
|
2202
|
+
dateFormat,
|
|
2203
|
+
enumColors: groupingMeta?.enumColors,
|
|
2204
|
+
enumOptions: groupingMeta?.enumOptions,
|
|
2205
|
+
})
|
|
2206
|
+
: null
|
|
2207
|
+
const hasVisibleGroupedCell = groupVisibleCells.some((cell) =>
|
|
2208
|
+
cell.getIsGrouped()
|
|
2209
|
+
)
|
|
2210
|
+
const primaryGroupCellId = groupVisibleCells.find(
|
|
2211
|
+
(cell) =>
|
|
2212
|
+
cell.column.id !== "__select" && cell.column.id !== "__actions"
|
|
2213
|
+
)?.id
|
|
1905
2214
|
const rowContent = (
|
|
1906
2215
|
<tr
|
|
1907
2216
|
aria-selected={isSelected}
|
|
1908
2217
|
className={cn(
|
|
1909
|
-
"absolute left-0 flex w-full
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
2218
|
+
"absolute left-0 flex w-full transition-colors",
|
|
2219
|
+
isGroupRow
|
|
2220
|
+
? "bg-transparent"
|
|
2221
|
+
: "bg-card",
|
|
2222
|
+
canSelectRows &&
|
|
2223
|
+
row.getCanSelect() &&
|
|
2224
|
+
"cursor-pointer",
|
|
2225
|
+
!isGroupRow && rowClassName?.(row.original),
|
|
2226
|
+
!isGroupRow &&
|
|
2227
|
+
isSelected &&
|
|
1913
2228
|
"bg-primary/10 before:absolute before:-top-px before:left-0 before:h-px before:w-full before:bg-primary before:content-[''] after:absolute after:bottom-0 after:left-0 after:h-px after:w-full after:bg-primary after:content-['']"
|
|
1914
2229
|
)}
|
|
1915
2230
|
data-index={virtualRow.index}
|
|
1916
2231
|
data-row-id={row.id}
|
|
1917
|
-
data-state={isSelected ? "selected" : undefined}
|
|
2232
|
+
data-state={!isGroupRow && isSelected ? "selected" : undefined}
|
|
1918
2233
|
key={row.id}
|
|
1919
|
-
onContextMenu={
|
|
1920
|
-
|
|
1921
|
-
|
|
2234
|
+
onContextMenu={
|
|
2235
|
+
isGroupRow ? undefined : () => handleRowContextMenu(row)
|
|
2236
|
+
}
|
|
2237
|
+
onMouseDown={
|
|
2238
|
+
isGroupRow
|
|
2239
|
+
? undefined
|
|
2240
|
+
: (event) => handleRowMouseDown(event, row)
|
|
2241
|
+
}
|
|
2242
|
+
onMouseEnter={
|
|
2243
|
+
isGroupRow
|
|
2244
|
+
? undefined
|
|
2245
|
+
: (event) => handleRowMouseEnter(event, row)
|
|
2246
|
+
}
|
|
1922
2247
|
ref={(node) => {
|
|
1923
2248
|
if (node) {
|
|
1924
2249
|
rowVirtualizer.measureElement(node)
|
|
1925
2250
|
}
|
|
1926
2251
|
}}
|
|
1927
2252
|
style={{
|
|
1928
|
-
...rowStyle?.(row.original),
|
|
1929
|
-
minHeight: rowHeight,
|
|
2253
|
+
...(!isGroupRow ? rowStyle?.(row.original) : undefined),
|
|
2254
|
+
minHeight: isGroupRow ? Math.max(rowHeight, 44) : rowHeight,
|
|
1930
2255
|
transform: `translateY(${virtualRow.start}px)`,
|
|
1931
2256
|
width: table.getTotalSize(),
|
|
1932
2257
|
}}
|
|
1933
2258
|
>
|
|
1934
|
-
{
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
meta.kind === "
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
2259
|
+
{isGroupRow ? (
|
|
2260
|
+
groupVisibleCells.map((cell, index, visibleCells) => {
|
|
2261
|
+
const meta = (cell.column.columnDef.meta ??
|
|
2262
|
+
{}) as DataTableColumnMeta
|
|
2263
|
+
const isActionsCell = cell.column.id === "__actions"
|
|
2264
|
+
const isSelectionCell = meta.kind === "selection"
|
|
2265
|
+
const shouldRenderGroupLabel =
|
|
2266
|
+
cell.getIsGrouped() ||
|
|
2267
|
+
(!hasVisibleGroupedCell && cell.id === primaryGroupCellId)
|
|
2268
|
+
const value = cell.getValue()
|
|
2269
|
+
let content: React.ReactNode = null
|
|
2270
|
+
|
|
2271
|
+
if (!isActionsCell && !isSelectionCell) {
|
|
2272
|
+
if (shouldRenderGroupLabel) {
|
|
2273
|
+
content = (
|
|
2274
|
+
<div className="flex min-w-0 items-center gap-0.5">
|
|
2275
|
+
{row.getCanExpand() ? (
|
|
2276
|
+
<button
|
|
2277
|
+
aria-label={
|
|
2278
|
+
row.getIsExpanded()
|
|
2279
|
+
? "Collapse group"
|
|
2280
|
+
: "Expand group"
|
|
2281
|
+
}
|
|
2282
|
+
className="-ml-4"
|
|
2283
|
+
onClick={() => row.toggleExpanded()}
|
|
2284
|
+
type="button"
|
|
2285
|
+
>
|
|
2286
|
+
{row.getIsExpanded() ? (
|
|
2287
|
+
<ChevronDown className="size-3.5" />
|
|
2288
|
+
) : (
|
|
2289
|
+
<ChevronRight className="size-3.5" />
|
|
2290
|
+
)}
|
|
2291
|
+
</button>
|
|
2292
|
+
) : null}
|
|
2293
|
+
<div className="min-w-0 truncate font-medium text-foreground">
|
|
2294
|
+
{groupingColumn ? groupingValue : "Group"}
|
|
2295
|
+
</div>
|
|
2296
|
+
</div>
|
|
1945
2297
|
)
|
|
1946
|
-
|
|
2298
|
+
} else if (meta.kind === "date" && isDateRangeAggregate(value)) {
|
|
2299
|
+
content = (
|
|
2300
|
+
<div className="min-w-0 truncate">
|
|
2301
|
+
<span className="font-medium text-foreground">
|
|
2302
|
+
{formatDuration(value.durationMs)}
|
|
2303
|
+
</span>
|
|
2304
|
+
<span className="ml-2 text-[11px] text-muted-foreground">
|
|
2305
|
+
span
|
|
2306
|
+
</span>
|
|
2307
|
+
</div>
|
|
2308
|
+
)
|
|
2309
|
+
} else if (meta.kind === "number" && typeof value === "number") {
|
|
2310
|
+
content = (
|
|
2311
|
+
<div className="min-w-0 truncate font-medium text-foreground">
|
|
2312
|
+
{formatSummaryNumber(value)}
|
|
2313
|
+
</div>
|
|
2314
|
+
)
|
|
2315
|
+
}
|
|
2316
|
+
}
|
|
1947
2317
|
|
|
1948
|
-
if (isActionsCell) {
|
|
1949
2318
|
return (
|
|
1950
2319
|
<td
|
|
1951
2320
|
className={cn(
|
|
1952
|
-
"flex shrink-0 border-
|
|
1953
|
-
meta.
|
|
2321
|
+
"flex shrink-0 items-center border-y border-border/70 px-2 py-2 align-middle text-xs text-muted-foreground",
|
|
2322
|
+
meta.align === "center" && "justify-center text-center",
|
|
2323
|
+
meta.align === "right" && "justify-end text-right",
|
|
2324
|
+
meta.sticky === "left" &&
|
|
2325
|
+
"sticky left-0 z-10 border-r border-r-border"
|
|
1954
2326
|
)}
|
|
1955
2327
|
key={cell.id}
|
|
1956
2328
|
style={{
|
|
2329
|
+
background:
|
|
2330
|
+
"var(--color-table-gap, color-mix(in oklab, var(--color-muted) 84%, transparent))",
|
|
1957
2331
|
paddingLeft:
|
|
1958
|
-
index === 0
|
|
2332
|
+
index === 0
|
|
2333
|
+
? resolveGroupedPadding(
|
|
2334
|
+
edgeHorizontalPadding,
|
|
2335
|
+
row.depth
|
|
2336
|
+
)
|
|
2337
|
+
: undefined,
|
|
1959
2338
|
paddingRight:
|
|
1960
2339
|
index === visibleCells.length - 1
|
|
1961
2340
|
? edgeHorizontalPadding
|
|
@@ -1963,33 +2342,72 @@ function DataTableView<TData extends DataTableRow>({
|
|
|
1963
2342
|
width: cell.column.getSize(),
|
|
1964
2343
|
}}
|
|
1965
2344
|
>
|
|
1966
|
-
<div className="w-full min-w-0">
|
|
1967
|
-
<RowActionButtonGroup
|
|
1968
|
-
resolvedActions={visibleRowActions}
|
|
1969
|
-
setStatus={setRowActionStatus}
|
|
1970
|
-
statuses={rowActionStatuses}
|
|
1971
|
-
/>
|
|
1972
|
-
</div>
|
|
2345
|
+
<div className="w-full min-w-0">{content}</div>
|
|
1973
2346
|
</td>
|
|
1974
2347
|
)
|
|
1975
|
-
}
|
|
2348
|
+
})
|
|
2349
|
+
) : (
|
|
2350
|
+
row.getVisibleCells().map((cell, index, visibleCells) => {
|
|
2351
|
+
const meta = (cell.column.columnDef.meta ??
|
|
2352
|
+
{}) as DataTableColumnMeta
|
|
2353
|
+
const isActionsCell = cell.column.id === "__actions"
|
|
2354
|
+
const highlightTerms =
|
|
2355
|
+
meta.kind === "text" &&
|
|
2356
|
+
resolveColumnHighlightTerms &&
|
|
2357
|
+
isColumnHighlightEnabled(cell.column.id, meta)
|
|
2358
|
+
? resolveColumnHighlightTerms(
|
|
2359
|
+
cell.column.id,
|
|
2360
|
+
highlightQuery
|
|
2361
|
+
)
|
|
2362
|
+
: []
|
|
2363
|
+
|
|
2364
|
+
if (isActionsCell) {
|
|
2365
|
+
return (
|
|
2366
|
+
<td
|
|
2367
|
+
className={cn(
|
|
2368
|
+
"flex shrink-0 border-b border-border px-2 py-1.5 align-middle text-sm text-foreground justify-end text-right",
|
|
2369
|
+
meta.cellClassName
|
|
2370
|
+
)}
|
|
2371
|
+
key={cell.id}
|
|
2372
|
+
style={{
|
|
2373
|
+
paddingLeft:
|
|
2374
|
+
index === 0 ? edgeHorizontalPadding : undefined,
|
|
2375
|
+
paddingRight:
|
|
2376
|
+
index === visibleCells.length - 1
|
|
2377
|
+
? edgeHorizontalPadding
|
|
2378
|
+
: undefined,
|
|
2379
|
+
width: cell.column.getSize(),
|
|
2380
|
+
}}
|
|
2381
|
+
>
|
|
2382
|
+
<div className="w-full min-w-0">
|
|
2383
|
+
<RowActionButtonGroup
|
|
2384
|
+
resolvedActions={visibleRowActions}
|
|
2385
|
+
setStatus={setRowActionStatus}
|
|
2386
|
+
statuses={rowActionStatuses}
|
|
2387
|
+
/>
|
|
2388
|
+
</div>
|
|
2389
|
+
</td>
|
|
2390
|
+
)
|
|
2391
|
+
}
|
|
1976
2392
|
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
2393
|
+
return (
|
|
2394
|
+
<DataTableBodyCell
|
|
2395
|
+
cell={cell}
|
|
2396
|
+
dateFormat={dateFormat}
|
|
2397
|
+
highlightTerms={highlightTerms}
|
|
2398
|
+
key={cell.id}
|
|
2399
|
+
paddingLeft={
|
|
2400
|
+
index === 0 ? edgeHorizontalPadding : undefined
|
|
2401
|
+
}
|
|
2402
|
+
paddingRight={
|
|
2403
|
+
index === visibleCells.length - 1
|
|
2404
|
+
? edgeHorizontalPadding
|
|
2405
|
+
: undefined
|
|
2406
|
+
}
|
|
2407
|
+
/>
|
|
2408
|
+
)
|
|
2409
|
+
})
|
|
2410
|
+
)}
|
|
1993
2411
|
</tr>
|
|
1994
2412
|
)
|
|
1995
2413
|
|