@jmruthers/pace-core 0.2.4 → 0.2.6
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/{DataTable-BHlzyKZP.d.ts → DataTable-C1AEm9Cx.d.ts} +1 -1
- package/dist/{DataTable-GEY5U7OI.js → DataTable-EEUDXPE5.js} +2 -8
- package/dist/{api-GZHIDA4X.js → api-ETQ6YJ3C.js} +2 -2
- package/dist/{chunk-DY5E3AT7.js → chunk-BEZRLNK3.js} +13 -3
- package/dist/chunk-BEZRLNK3.js.map +1 -0
- package/dist/{chunk-6ZQVSHKL.js → chunk-C5G2A4PO.js} +7 -3
- package/dist/chunk-C5G2A4PO.js.map +1 -0
- package/dist/{chunk-WYB6MBZA.js → chunk-EWKPTNPO.js} +579 -973
- package/dist/chunk-EWKPTNPO.js.map +1 -0
- package/dist/{chunk-TMRLB2LA.js → chunk-HEMJ4SUJ.js} +2 -2
- package/dist/{chunk-OKXMUYIB.js → chunk-HNDFPXUU.js} +5 -5
- package/dist/{chunk-7JL3T7BO.js → chunk-RRUYHORU.js} +161 -74
- package/dist/chunk-RRUYHORU.js.map +1 -0
- package/dist/{chunk-PFRRIDYA.js → chunk-TIVL4UQ7.js} +2 -2
- package/dist/{chunk-2MKP6IYD.js → chunk-VYG4AXYW.js} +2 -2
- package/dist/components.d.ts +2 -2
- package/dist/components.js +15 -15
- package/dist/hooks.d.ts +1 -1
- package/dist/hooks.js +4 -4
- package/dist/index.d.ts +2 -2
- package/dist/index.js +16 -16
- package/dist/providers.js +2 -2
- package/dist/rbac/index.d.ts +2 -0
- package/dist/rbac/index.js +22 -10
- package/dist/rbac/index.js.map +1 -1
- package/dist/{types-CInEi-ng.d.ts → types-DiRQsGJs.d.ts} +0 -2
- package/dist/utils.d.ts +2 -2
- package/dist/utils.js +1 -1
- package/docs/api/classes/ErrorBoundary.md +1 -1
- package/docs/api/classes/PublicErrorBoundary.md +1 -1
- package/docs/api/interfaces/AggregateConfig.md +1 -1
- package/docs/api/interfaces/ButtonProps.md +1 -1
- package/docs/api/interfaces/CardProps.md +1 -1
- package/docs/api/interfaces/ColorPalette.md +1 -1
- package/docs/api/interfaces/ColorShade.md +1 -1
- package/docs/api/interfaces/DataTableAction.md +1 -1
- package/docs/api/interfaces/DataTableColumn.md +1 -1
- package/docs/api/interfaces/DataTableProps.md +33 -33
- package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
- package/docs/api/interfaces/EmptyStateConfig.md +1 -1
- package/docs/api/interfaces/EventContextType.md +1 -1
- package/docs/api/interfaces/EventLogoProps.md +1 -1
- package/docs/api/interfaces/EventProviderProps.md +1 -1
- package/docs/api/interfaces/FileSizeLimits.md +1 -1
- package/docs/api/interfaces/FileUploadProps.md +1 -1
- package/docs/api/interfaces/FooterProps.md +1 -1
- package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
- package/docs/api/interfaces/InputProps.md +1 -1
- package/docs/api/interfaces/LabelProps.md +1 -1
- package/docs/api/interfaces/LoginFormProps.md +1 -1
- package/docs/api/interfaces/NavigationItem.md +1 -1
- package/docs/api/interfaces/NavigationMenuProps.md +1 -1
- package/docs/api/interfaces/Organisation.md +1 -1
- package/docs/api/interfaces/OrganisationContextType.md +1 -1
- package/docs/api/interfaces/OrganisationMembership.md +1 -1
- package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
- package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
- package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
- package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
- package/docs/api/interfaces/PaletteData.md +1 -1
- package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
- package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
- package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
- package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
- package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
- package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
- package/docs/api/interfaces/StorageConfig.md +1 -1
- package/docs/api/interfaces/StorageFileInfo.md +1 -1
- package/docs/api/interfaces/StorageFileMetadata.md +1 -1
- package/docs/api/interfaces/StorageListOptions.md +1 -1
- package/docs/api/interfaces/StorageListResult.md +1 -1
- package/docs/api/interfaces/StorageUploadOptions.md +1 -1
- package/docs/api/interfaces/StorageUploadResult.md +1 -1
- package/docs/api/interfaces/StorageUrlOptions.md +1 -1
- package/docs/api/interfaces/StyleImport.md +1 -1
- package/docs/api/interfaces/ToastActionElement.md +1 -1
- package/docs/api/interfaces/ToastProps.md +1 -1
- package/docs/api/interfaces/UnifiedAuthContextType.md +1 -1
- package/docs/api/interfaces/UnifiedAuthProviderProps.md +1 -1
- package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
- package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
- package/docs/api/interfaces/UsePublicEventLogoOptions.md +1 -1
- package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
- package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
- package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
- package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
- package/docs/api/interfaces/UserEventAccess.md +1 -1
- package/docs/api/interfaces/UserMenuProps.md +1 -1
- package/docs/api/interfaces/UserProfile.md +1 -1
- package/docs/api/modules.md +10 -10
- package/docs/architecture/README.md +1 -1
- package/package.json +1 -1
- package/src/__tests__/shared/testUtils.optimized.tsx +65 -7
- package/src/components/DataTable/DataTable.tsx +1 -3
- package/src/components/DataTable/__tests__/DataTable.errorHandling.test.tsx +0 -8
- package/src/components/DataTable/__tests__/DataTable.hierarchical.test.tsx +17 -12
- package/src/components/DataTable/__tests__/DataTable.infinite-loop.test.tsx +0 -1
- package/src/components/DataTable/__tests__/DataTable.integration.test.tsx +4 -12
- package/src/components/DataTable/__tests__/DataTable.performance.test.tsx +0 -8
- package/src/components/DataTable/__tests__/DataTable.permissions.test.tsx +21 -11
- package/src/components/DataTable/__tests__/DataTable.sorting.test.tsx +321 -0
- package/src/components/DataTable/__tests__/DataTable.userWorkflows.test.tsx +21 -11
- package/src/components/DataTable/__tests__/DataTable.workflowValidation.test.tsx +94 -0
- package/src/components/DataTable/__tests__/DataTable.workflows.test.tsx +25 -15
- package/src/components/DataTable/__tests__/README.md +11 -2
- package/src/components/DataTable/__tests__/performance-regression.test.tsx +0 -11
- package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +0 -1
- package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +2 -2
- package/src/components/DataTable/components/DataTableBody.tsx +34 -35
- package/src/components/DataTable/components/DataTableCore.tsx +205 -133
- package/src/components/DataTable/components/DataTableToolbar.tsx +9 -10
- package/src/components/DataTable/components/DraggableColumnHeader.tsx +3 -7
- package/src/components/DataTable/components/EditableRow.tsx +6 -7
- package/src/components/DataTable/components/FilterRow.tsx +0 -1
- package/src/components/DataTable/components/GroupingDropdown.tsx +2 -2
- package/src/components/DataTable/components/UnifiedTableBody.tsx +83 -281
- package/src/components/DataTable/components/VirtualizedDataTable.tsx +9 -89
- package/src/components/DataTable/components/__tests__/DataTable.accessibility.test.tsx +111 -5
- package/src/components/DataTable/components/__tests__/DataTable.integration.test.tsx +82 -13
- package/src/components/DataTable/components/__tests__/DataTable.performance.test.tsx +0 -1
- package/src/components/DataTable/components/__tests__/DataTable.real.test.tsx +2 -2
- package/src/components/DataTable/components/__tests__/DataTable.security.test.tsx +0 -1
- package/src/components/DataTable/components/__tests__/DataTable.unit.test.tsx +2 -2
- package/src/components/DataTable/components/__tests__/FilteringToggle.unit.test.tsx +3 -0
- package/src/components/DataTable/components/index.ts +0 -1
- package/src/components/DataTable/core/DataTableContext.tsx +0 -1
- package/src/components/DataTable/index.ts +0 -2
- package/src/components/DataTable/types.ts +0 -2
- package/src/components/Input/Input.tsx +2 -2
- package/src/components/Input/__tests__/Input.unit.test.tsx +4 -4
- package/src/components/PaceAppLayout/__tests__/PaceAppLayout.integration.test.tsx +6 -2
- package/src/components/RBAC/PagePermissionGuard.tsx +13 -0
- package/src/components/RBAC/__tests__/PagePermissionGuard.unit.test.tsx +10 -1
- package/src/components/Select/Select.tsx +7 -1
- package/src/components/__tests__/EdgeCaseTesting.enhanced.test.tsx +2 -1
- package/src/hooks/__tests__/useRBAC.unit.test.ts +32 -24
- package/src/providers/RBACProvider.tsx +14 -2
- package/src/providers/__tests__/UnifiedAuthProvider.unit.test.tsx +11 -3
- package/src/rbac/__tests__/cache-invalidation.test.ts +2 -2
- package/src/rbac/__tests__/cache.test.ts +3 -3
- package/src/rbac/api.ts +2 -0
- package/src/rbac/cache.ts +2 -0
- package/src/rbac/hooks.ts +15 -0
- package/src/rbac/types.ts +2 -0
- package/src/utils/__tests__/lazyLoad.unit.test.tsx +13 -18
- package/src/utils/storage/__tests__/helpers.unit.test.ts +9 -7
- package/dist/chunk-6ZQVSHKL.js.map +0 -1
- package/dist/chunk-7JL3T7BO.js.map +0 -1
- package/dist/chunk-DY5E3AT7.js.map +0 -1
- package/dist/chunk-WYB6MBZA.js.map +0 -1
- package/src/components/DataTable/__tests__/DataTable.autoSizing.test.tsx +0 -526
- package/src/components/DataTable/components/DataTableHeader.tsx +0 -31
- package/src/components/DataTable/components/__tests__/DataTableHeader.unit.test.tsx +0 -143
- package/src/components/DataTable/examples/AutoSizingExample.tsx +0 -180
- package/src/components/DataTable/examples/ColumnSizingComparison.tsx +0 -235
- package/src/components/DataTable/utils/__tests__/columnSizing.test.ts +0 -237
- package/src/components/DataTable/utils/columnSizing.ts +0 -125
- /package/dist/{DataTable-GEY5U7OI.js.map → DataTable-EEUDXPE5.js.map} +0 -0
- /package/dist/{api-GZHIDA4X.js.map → api-ETQ6YJ3C.js.map} +0 -0
- /package/dist/{chunk-TMRLB2LA.js.map → chunk-HEMJ4SUJ.js.map} +0 -0
- /package/dist/{chunk-OKXMUYIB.js.map → chunk-HNDFPXUU.js.map} +0 -0
- /package/dist/{chunk-PFRRIDYA.js.map → chunk-TIVL4UQ7.js.map} +0 -0
- /package/dist/{chunk-2MKP6IYD.js.map → chunk-VYG4AXYW.js.map} +0 -0
|
@@ -58,9 +58,8 @@
|
|
|
58
58
|
|
|
59
59
|
import React from 'react';
|
|
60
60
|
import { type Table, flexRender } from '@tanstack/react-table';
|
|
61
|
-
import { TableBody, TableHead, TableHeader, TableRow, TableCell } from '../../Table/Table';
|
|
62
61
|
import { Button } from '../../Button/Button';
|
|
63
|
-
import { ChevronUp, ChevronDown, ChevronRight } from 'lucide-react';
|
|
62
|
+
import { ChevronUp, ChevronDown, ChevronRight, ChevronsUpDown } from 'lucide-react';
|
|
64
63
|
import { EmptyState } from './EmptyState';
|
|
65
64
|
import { Input } from '../../Input/Input';
|
|
66
65
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../../Select/Select';
|
|
@@ -228,12 +227,12 @@ export function DataTableBody<TData extends Record<string, any>>({
|
|
|
228
227
|
return (
|
|
229
228
|
<>
|
|
230
229
|
{/* Table Header */}
|
|
231
|
-
<
|
|
230
|
+
<thead>
|
|
232
231
|
{table.getHeaderGroups().map((headerGroup) => (
|
|
233
|
-
<
|
|
232
|
+
<tr key={headerGroup.id}>
|
|
234
233
|
{/* Expand/Collapse All Button - Only show for hierarchical tables */}
|
|
235
234
|
{hierarchical?.enabled && hierarchical?.hasAnyChildren && (
|
|
236
|
-
<
|
|
235
|
+
<th className="w-12">
|
|
237
236
|
<Button
|
|
238
237
|
variant="ghost"
|
|
239
238
|
size="sm"
|
|
@@ -248,7 +247,7 @@ export function DataTableBody<TData extends Record<string, any>>({
|
|
|
248
247
|
<ChevronRight className="h-4 w-4" />
|
|
249
248
|
)}
|
|
250
249
|
</Button>
|
|
251
|
-
</
|
|
250
|
+
</th>
|
|
252
251
|
)}
|
|
253
252
|
|
|
254
253
|
{headerGroup.headers.map((header) => {
|
|
@@ -261,7 +260,7 @@ export function DataTableBody<TData extends Record<string, any>>({
|
|
|
261
260
|
: 'none')
|
|
262
261
|
: undefined;
|
|
263
262
|
return (
|
|
264
|
-
<
|
|
263
|
+
<th
|
|
265
264
|
key={header.id}
|
|
266
265
|
{...(isSortable ? { 'aria-sort': ariaSort } : {})}
|
|
267
266
|
>
|
|
@@ -283,7 +282,7 @@ export function DataTableBody<TData extends Record<string, any>>({
|
|
|
283
282
|
) : header.column.getIsSorted() === 'desc' ? (
|
|
284
283
|
<ChevronDown className="h-4 w-4" />
|
|
285
284
|
) : (
|
|
286
|
-
<
|
|
285
|
+
<ChevronsUpDown className="h-4 w-4" />
|
|
287
286
|
)}
|
|
288
287
|
</div>
|
|
289
288
|
</Button>
|
|
@@ -295,20 +294,20 @@ export function DataTableBody<TData extends Record<string, any>>({
|
|
|
295
294
|
</div>
|
|
296
295
|
)
|
|
297
296
|
)}
|
|
298
|
-
</
|
|
297
|
+
</th>
|
|
299
298
|
);
|
|
300
299
|
})}
|
|
301
|
-
</
|
|
300
|
+
</tr>
|
|
302
301
|
))}
|
|
303
|
-
</
|
|
302
|
+
</thead>
|
|
304
303
|
|
|
305
304
|
{/* Table Body */}
|
|
306
|
-
<
|
|
305
|
+
<tbody>
|
|
307
306
|
{/* Creation Row */}
|
|
308
307
|
{isCreating && (
|
|
309
|
-
<
|
|
308
|
+
<tr>
|
|
310
309
|
{table.getVisibleFlatColumns().map((column) => (
|
|
311
|
-
<
|
|
310
|
+
<td key={column.id}>
|
|
312
311
|
{renderEditField(column, creationData[column.id], (value) => {
|
|
313
312
|
if (typeof value === 'object' && value !== null) {
|
|
314
313
|
// Handle editAccessorKey case
|
|
@@ -318,9 +317,9 @@ export function DataTableBody<TData extends Record<string, any>>({
|
|
|
318
317
|
onCreationDataChange({ ...creationData, [column.id]: value });
|
|
319
318
|
}
|
|
320
319
|
}, creationData)}
|
|
321
|
-
</
|
|
320
|
+
</td>
|
|
322
321
|
))}
|
|
323
|
-
<
|
|
322
|
+
<td className="flex gap-1">
|
|
324
323
|
<>
|
|
325
324
|
<button
|
|
326
325
|
onClick={onSaveCreation}
|
|
@@ -341,14 +340,14 @@ export function DataTableBody<TData extends Record<string, any>>({
|
|
|
341
340
|
</svg>
|
|
342
341
|
</button>
|
|
343
342
|
</>
|
|
344
|
-
</
|
|
345
|
-
</
|
|
343
|
+
</td>
|
|
344
|
+
</tr>
|
|
346
345
|
)}
|
|
347
346
|
|
|
348
347
|
{/* Table Rows */}
|
|
349
348
|
{table.getRowModel().rows.length === 0 && (
|
|
350
|
-
<
|
|
351
|
-
<
|
|
349
|
+
<tr>
|
|
350
|
+
<td colSpan={table.getVisibleFlatColumns().length} role="status">
|
|
352
351
|
<EmptyState
|
|
353
352
|
title={emptyState?.title}
|
|
354
353
|
description={emptyState?.description}
|
|
@@ -357,8 +356,8 @@ export function DataTableBody<TData extends Record<string, any>>({
|
|
|
357
356
|
isFiltered={isFiltered}
|
|
358
357
|
onClearFilters={onClearFilters}
|
|
359
358
|
/>
|
|
360
|
-
</
|
|
361
|
-
</
|
|
359
|
+
</td>
|
|
360
|
+
</tr>
|
|
362
361
|
)}
|
|
363
362
|
|
|
364
363
|
{table.getRowModel().rows.map((row) => {
|
|
@@ -374,8 +373,8 @@ export function DataTableBody<TData extends Record<string, any>>({
|
|
|
374
373
|
return (
|
|
375
374
|
<React.Fragment key={row.id}>
|
|
376
375
|
{/* Group Header Row */}
|
|
377
|
-
<
|
|
378
|
-
<
|
|
376
|
+
<tr className="bg-app-sec-50 hover:bg-app-sec-100">
|
|
377
|
+
<td className="flex items-center py-2 font-medium" colSpan={table.getAllColumns().length}>
|
|
379
378
|
<>
|
|
380
379
|
<Button
|
|
381
380
|
variant="ghost"
|
|
@@ -393,8 +392,8 @@ export function DataTableBody<TData extends Record<string, any>>({
|
|
|
393
392
|
{String(groupValue)} ({subRowsCount} items)
|
|
394
393
|
</span>
|
|
395
394
|
</>
|
|
396
|
-
</
|
|
397
|
-
</
|
|
395
|
+
</td>
|
|
396
|
+
</tr>
|
|
398
397
|
|
|
399
398
|
{/* Render sub-rows if expanded */}
|
|
400
399
|
{isExpanded && row.subRows?.map((subRow) => {
|
|
@@ -402,9 +401,9 @@ export function DataTableBody<TData extends Record<string, any>>({
|
|
|
402
401
|
const isSubRowEditing = editingRowId === subRowId;
|
|
403
402
|
|
|
404
403
|
return (
|
|
405
|
-
<
|
|
404
|
+
<tr key={subRow.id} className="border-l-2 border-l-blue-200">
|
|
406
405
|
{subRow.getVisibleCells().map((cell) => (
|
|
407
|
-
<
|
|
406
|
+
<td key={cell.id} className="pl-8">
|
|
408
407
|
{isSubRowEditing && cell.column.id !== 'actions' ? (
|
|
409
408
|
renderEditField(cell.column, editingData[cell.column.id], (value) => {
|
|
410
409
|
if (typeof value === 'object' && value !== null) {
|
|
@@ -418,9 +417,9 @@ export function DataTableBody<TData extends Record<string, any>>({
|
|
|
418
417
|
) : (
|
|
419
418
|
flexRender(cell.column.columnDef.cell, cell.getContext())
|
|
420
419
|
)}
|
|
421
|
-
</
|
|
420
|
+
</td>
|
|
422
421
|
))}
|
|
423
|
-
</
|
|
422
|
+
</tr>
|
|
424
423
|
);
|
|
425
424
|
})}
|
|
426
425
|
</React.Fragment>
|
|
@@ -435,9 +434,9 @@ export function DataTableBody<TData extends Record<string, any>>({
|
|
|
435
434
|
|
|
436
435
|
// Regular row (non-grouped or when grouping is disabled)
|
|
437
436
|
return (
|
|
438
|
-
<
|
|
437
|
+
<tr key={row.id}>
|
|
439
438
|
{row.getVisibleCells().map((cell) => (
|
|
440
|
-
<
|
|
439
|
+
<td key={cell.id}>
|
|
441
440
|
{isEditing && cell.column.id !== 'actions' ? (
|
|
442
441
|
renderEditField(cell.column, editingData[cell.column.id], (value) => {
|
|
443
442
|
if (typeof value === 'object' && value !== null) {
|
|
@@ -451,12 +450,12 @@ export function DataTableBody<TData extends Record<string, any>>({
|
|
|
451
450
|
) : (
|
|
452
451
|
flexRender(cell.column.columnDef.cell, cell.getContext())
|
|
453
452
|
)}
|
|
454
|
-
</
|
|
453
|
+
</td>
|
|
455
454
|
))}
|
|
456
|
-
</
|
|
455
|
+
</tr>
|
|
457
456
|
);
|
|
458
457
|
})}
|
|
459
|
-
</
|
|
458
|
+
</tbody>
|
|
460
459
|
</>
|
|
461
460
|
);
|
|
462
461
|
}
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
getPaginationRowModel,
|
|
18
18
|
getGroupedRowModel,
|
|
19
19
|
getExpandedRowModel,
|
|
20
|
+
flexRender,
|
|
20
21
|
type SortingState,
|
|
21
22
|
type ColumnDef,
|
|
22
23
|
type ColumnFiltersState,
|
|
@@ -27,12 +28,12 @@ import {
|
|
|
27
28
|
type HeaderContext,
|
|
28
29
|
type CellContext,
|
|
29
30
|
} from '@tanstack/react-table';
|
|
30
|
-
import { Edit, Trash } from 'lucide-react';
|
|
31
|
+
import { Edit, Trash, ChevronUp, ChevronDown, ChevronsUpDown } from 'lucide-react';
|
|
31
32
|
import { cn } from '../../../utils/cn';
|
|
32
33
|
import { Checkbox } from '../../Checkbox/Checkbox';
|
|
34
|
+
import { Button } from '../../Button/Button';
|
|
33
35
|
import { getTableClasses, getMainContainerClasses } from '../styles';
|
|
34
36
|
import { useDataTablePerformance } from '../../../hooks/useDataTablePerformance';
|
|
35
|
-
import { DataTableHeader } from './DataTableHeader';
|
|
36
37
|
import { DataTableToolbar } from './DataTableToolbar';
|
|
37
38
|
import { UnifiedTableBody } from './UnifiedTableBody';
|
|
38
39
|
import { PaginationControls, EnhancedPaginationControls } from './PaginationControls';
|
|
@@ -44,7 +45,6 @@ import { useHierarchicalState } from '../hooks/useHierarchicalState';
|
|
|
44
45
|
import { useDataTableState } from '../hooks/useDataTableState';
|
|
45
46
|
import { validateHierarchicalData, sortHierarchicalData } from '../utils/hierarchicalUtils';
|
|
46
47
|
import { sortHierarchicalData as sortHierarchicalDataWithSorting } from '../utils/hierarchicalSorting';
|
|
47
|
-
import { calculateColumnWidths, getColumnSizingConfig } from '../utils/columnSizing';
|
|
48
48
|
import { ColumnFactory } from '../core/ColumnFactory';
|
|
49
49
|
|
|
50
50
|
import type {
|
|
@@ -551,17 +551,6 @@ function DataTableInternal<TData extends DataRecord>({
|
|
|
551
551
|
// COLUMN WIDTHS
|
|
552
552
|
// ============================================================================
|
|
553
553
|
|
|
554
|
-
const columnWidths = useMemo(() => {
|
|
555
|
-
if (features.autoColumnSizing) {
|
|
556
|
-
return calculateColumnWidths(data, enhancedColumns, {
|
|
557
|
-
minWidth: 80,
|
|
558
|
-
maxWidth: 400,
|
|
559
|
-
padding: 32,
|
|
560
|
-
sampleSize: Math.min(100, data.length)
|
|
561
|
-
});
|
|
562
|
-
}
|
|
563
|
-
return undefined;
|
|
564
|
-
}, [data, enhancedColumns, features.autoColumnSizing]);
|
|
565
554
|
|
|
566
555
|
// ============================================================================
|
|
567
556
|
// TABLE CONFIGURATION
|
|
@@ -610,7 +599,6 @@ function DataTableInternal<TData extends DataRecord>({
|
|
|
610
599
|
manualFiltering: finalPaginationMode === 'server',
|
|
611
600
|
manualPagination: finalPaginationMode === 'server',
|
|
612
601
|
pageCount: finalPaginationMode === 'server' ? Math.ceil(dataCount / pagination.pageSize) : undefined,
|
|
613
|
-
...getColumnSizingConfig(features.autoColumnSizing || false, columnWidths),
|
|
614
602
|
}), [
|
|
615
603
|
finalTableData,
|
|
616
604
|
enhancedColumns,
|
|
@@ -629,8 +617,6 @@ function DataTableInternal<TData extends DataRecord>({
|
|
|
629
617
|
onRowSelectionChange,
|
|
630
618
|
finalPaginationMode,
|
|
631
619
|
features.pagination,
|
|
632
|
-
features.autoColumnSizing,
|
|
633
|
-
columnWidths,
|
|
634
620
|
dataCount,
|
|
635
621
|
pagination.pageSize
|
|
636
622
|
]);
|
|
@@ -707,135 +693,221 @@ function DataTableInternal<TData extends DataRecord>({
|
|
|
707
693
|
? EnhancedPaginationControls
|
|
708
694
|
: PaginationControls;
|
|
709
695
|
|
|
696
|
+
// Calculate column counts for colgroup
|
|
697
|
+
const visibleColumns = table?.getVisibleFlatColumns() || [];
|
|
698
|
+
const dataColumns = visibleColumns.filter(col =>
|
|
699
|
+
col.id !== 'select' && col.id !== 'actions'
|
|
700
|
+
).length;
|
|
701
|
+
const hasSelectColumn = visibleColumns.some(col => col.id === 'select');
|
|
702
|
+
const hasActionsColumn = visibleColumns.some(col => col.id === 'actions');
|
|
703
|
+
|
|
710
704
|
return (
|
|
711
705
|
<>
|
|
712
|
-
{/*
|
|
713
|
-
{(title || description) && (
|
|
714
|
-
<DataTableHeader
|
|
715
|
-
title={title}
|
|
716
|
-
description={description}
|
|
717
|
-
/>
|
|
718
|
-
)}
|
|
719
|
-
|
|
720
|
-
{/* Toolbar */}
|
|
721
|
-
<DataTableToolbar
|
|
722
|
-
features={features}
|
|
723
|
-
globalFilter={searchQuery}
|
|
724
|
-
onGlobalFilterChange={handleSearch}
|
|
725
|
-
columns={columns}
|
|
726
|
-
grouping={grouping}
|
|
727
|
-
onGroupByChange={(columnId) => {
|
|
728
|
-
setGrouping(columnId ? [columnId] : []);
|
|
729
|
-
}}
|
|
730
|
-
tableColumns={table?.getAllColumns() || []}
|
|
731
|
-
onColumnVisibilityChange={(columnId, visible) => {
|
|
732
|
-
setColumnVisibility(prev => ({ ...prev, [columnId]: visible }));
|
|
733
|
-
}}
|
|
734
|
-
onCreateRow={features.creation && onCreateRow ? () => tableActions.setCreating(true) : undefined}
|
|
735
|
-
onImportClick={() => setShowImportModal(true)}
|
|
736
|
-
onExport={() => {
|
|
737
|
-
// Export logic here
|
|
738
|
-
}}
|
|
739
|
-
rowSelection={rowSelection}
|
|
740
|
-
onDeleteSelected={onDeleteSelected}
|
|
741
|
-
onToggleFilterRow={() => setShowFilterRow(!showFilterRow)}
|
|
742
|
-
showFilterRow={showFilterRow}
|
|
743
|
-
/>
|
|
744
|
-
|
|
745
|
-
{/* Table */}
|
|
706
|
+
{/* Table with semantic HTML structure */}
|
|
746
707
|
<table className={getTableClasses({
|
|
747
|
-
isFixed:
|
|
708
|
+
isFixed: true,
|
|
748
709
|
variant,
|
|
749
710
|
className: cn('border-collapse relative w-full', className)
|
|
750
711
|
})} style={{
|
|
751
|
-
tableLayout:
|
|
712
|
+
tableLayout: 'fixed',
|
|
752
713
|
width: '100%'
|
|
753
714
|
}}>
|
|
715
|
+
{/* Caption with title, description, and toolbar */}
|
|
716
|
+
<caption className="text-left pb-2">
|
|
717
|
+
{(title || description) && (
|
|
718
|
+
<>
|
|
719
|
+
{title && <h2 >{title}</h2>}
|
|
720
|
+
{description && <p>{description}</p>}
|
|
721
|
+
</>
|
|
722
|
+
)}
|
|
723
|
+
<>
|
|
724
|
+
<DataTableToolbar
|
|
725
|
+
features={features}
|
|
726
|
+
globalFilter={searchQuery}
|
|
727
|
+
onGlobalFilterChange={handleSearch}
|
|
728
|
+
columns={columns}
|
|
729
|
+
grouping={grouping}
|
|
730
|
+
onGroupByChange={(columnId) => {
|
|
731
|
+
setGrouping(columnId ? [columnId] : []);
|
|
732
|
+
}}
|
|
733
|
+
tableColumns={table?.getAllColumns() || []}
|
|
734
|
+
onColumnVisibilityChange={(columnId, visible) => {
|
|
735
|
+
setColumnVisibility(prev => ({ ...prev, [columnId]: visible }));
|
|
736
|
+
}}
|
|
737
|
+
onCreateRow={features.creation && onCreateRow ? () => tableActions.setCreating(true) : undefined}
|
|
738
|
+
onImportClick={() => setShowImportModal(true)}
|
|
739
|
+
onExport={() => {
|
|
740
|
+
// Export logic here
|
|
741
|
+
}}
|
|
742
|
+
rowSelection={rowSelection}
|
|
743
|
+
onDeleteSelected={onDeleteSelected}
|
|
744
|
+
onToggleFilterRow={() => setShowFilterRow(!showFilterRow)}
|
|
745
|
+
showFilterRow={showFilterRow}
|
|
746
|
+
/>
|
|
747
|
+
</>
|
|
748
|
+
</caption>
|
|
749
|
+
|
|
750
|
+
{/* Column groups */}
|
|
751
|
+
<colgroup>
|
|
752
|
+
{hasSelectColumn && <col span={1} data-col-type="select" />}
|
|
753
|
+
<col span={dataColumns} data-col-type="data" />
|
|
754
|
+
{hasActionsColumn && <col span={1} data-col-type="actions" />}
|
|
755
|
+
</colgroup>
|
|
756
|
+
|
|
757
|
+
{/* Table header */}
|
|
758
|
+
<thead>
|
|
759
|
+
{table?.getHeaderGroups().map((headerGroup) => (
|
|
760
|
+
<tr key={headerGroup.id}>
|
|
761
|
+
{headerGroup.headers
|
|
762
|
+
.filter(header => {
|
|
763
|
+
return typeof header.column.getIsVisible === 'function'
|
|
764
|
+
? header.column.getIsVisible()
|
|
765
|
+
: true;
|
|
766
|
+
})
|
|
767
|
+
.map((header) => {
|
|
768
|
+
const isSortable = header.column.getCanSort();
|
|
769
|
+
const ariaSort = isSortable
|
|
770
|
+
? (header.column.getIsSorted() === 'asc'
|
|
771
|
+
? 'ascending'
|
|
772
|
+
: header.column.getIsSorted() === 'desc'
|
|
773
|
+
? 'descending'
|
|
774
|
+
: 'none')
|
|
775
|
+
: undefined;
|
|
776
|
+
return (
|
|
777
|
+
<th
|
|
778
|
+
key={header.id}
|
|
779
|
+
{...(isSortable ? { 'aria-sort': ariaSort } : {})}
|
|
780
|
+
>
|
|
781
|
+
{header.isPlaceholder ? null : (
|
|
782
|
+
isSortable ? (
|
|
783
|
+
<Button
|
|
784
|
+
variant="ghost"
|
|
785
|
+
className="h-auto p-0 font-medium hover:bg-transparent"
|
|
786
|
+
onClick={header.column.getToggleSortingHandler()}
|
|
787
|
+
aria-label={`Sort by ${typeof header.column.columnDef.header === 'string' ? header.column.columnDef.header : 'column'}`}
|
|
788
|
+
tabIndex={0}
|
|
789
|
+
>
|
|
790
|
+
<div className="flex items-center gap-1">
|
|
791
|
+
{typeof header.column.columnDef.header === 'function'
|
|
792
|
+
? header.column.columnDef.header(header.getContext())
|
|
793
|
+
: header.column.columnDef.header}
|
|
794
|
+
{header.column.getIsSorted() === 'asc' ? (
|
|
795
|
+
<ChevronUp className="h-4 w-4" />
|
|
796
|
+
) : header.column.getIsSorted() === 'desc' ? (
|
|
797
|
+
<ChevronDown className="h-4 w-4" />
|
|
798
|
+
) : (
|
|
799
|
+
<ChevronsUpDown className="h-4 w-4" />
|
|
800
|
+
)}
|
|
801
|
+
</div>
|
|
802
|
+
</Button>
|
|
803
|
+
) : (
|
|
804
|
+
<div>
|
|
805
|
+
{typeof header.column.columnDef.header === 'function'
|
|
806
|
+
? header.column.columnDef.header(header.getContext())
|
|
807
|
+
: header.column.columnDef.header}
|
|
808
|
+
</div>
|
|
809
|
+
)
|
|
810
|
+
)}
|
|
811
|
+
</th>
|
|
812
|
+
);
|
|
813
|
+
})}
|
|
814
|
+
</tr>
|
|
815
|
+
))}
|
|
816
|
+
</thead>
|
|
817
|
+
|
|
818
|
+
{/* Table body */}
|
|
754
819
|
<UnifiedTableBody
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
820
|
+
table={table}
|
|
821
|
+
isCreating={isCreating}
|
|
822
|
+
creationData={creationData}
|
|
823
|
+
onCreationDataChange={tableActions.setCreationData}
|
|
824
|
+
onSaveCreation={() => {
|
|
825
|
+
if (onCreateRow) {
|
|
826
|
+
onCreateRow(creationData as Partial<TData>);
|
|
827
|
+
tableActions.clearCreationData();
|
|
828
|
+
tableActions.setCreating(false);
|
|
829
|
+
}
|
|
830
|
+
}}
|
|
831
|
+
onCancelCreation={() => {
|
|
762
832
|
tableActions.clearCreationData();
|
|
763
833
|
tableActions.setCreating(false);
|
|
764
|
-
}
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
editingData={editingData}
|
|
772
|
-
onEditingDataChange={(data) => {
|
|
773
|
-
// Update the editing data in the centralized state
|
|
774
|
-
if (editingRowId) {
|
|
775
|
-
tableActions.setEditingRow(editingRowId, data);
|
|
776
|
-
}
|
|
777
|
-
}}
|
|
778
|
-
onSaveEditing={() => {
|
|
779
|
-
if (onEditRow && editingRowId) {
|
|
780
|
-
// Find the original row data
|
|
781
|
-
const originalRow = data.find(row => {
|
|
782
|
-
const rowId = getRowId ? getRowId(row, 0) : (row as any).id || String(0);
|
|
783
|
-
return rowId === editingRowId;
|
|
784
|
-
});
|
|
785
|
-
if (originalRow) {
|
|
786
|
-
onEditRow(originalRow, editingData as Partial<TData>);
|
|
834
|
+
}}
|
|
835
|
+
editingRowId={editingRowId}
|
|
836
|
+
editingData={editingData}
|
|
837
|
+
onEditingDataChange={(data) => {
|
|
838
|
+
// Update the editing data in the centralized state
|
|
839
|
+
if (editingRowId) {
|
|
840
|
+
tableActions.setEditingRow(editingRowId, data);
|
|
787
841
|
}
|
|
788
|
-
}
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
842
|
+
}}
|
|
843
|
+
onSaveEditing={() => {
|
|
844
|
+
if (onEditRow && editingRowId) {
|
|
845
|
+
// Find the original row data
|
|
846
|
+
const originalRow = data.find(row => {
|
|
847
|
+
const rowId = getRowId ? getRowId(row, 0) : (row as any).id || String(0);
|
|
848
|
+
return rowId === editingRowId;
|
|
849
|
+
});
|
|
850
|
+
if (originalRow) {
|
|
851
|
+
onEditRow(originalRow, editingData as Partial<TData>);
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
tableActions.clearEditing();
|
|
855
|
+
}}
|
|
856
|
+
onCancelEditing={() => {
|
|
857
|
+
tableActions.clearEditing();
|
|
858
|
+
}}
|
|
859
|
+
grouping={grouping}
|
|
860
|
+
aggregates={aggregates}
|
|
861
|
+
getRowId={getRowId}
|
|
862
|
+
emptyState={React.isValidElement(emptyState) ? undefined : emptyState as any}
|
|
863
|
+
isFiltered={searchQuery !== '' || columnFilters.length > 0}
|
|
864
|
+
onClearFilters={() => {
|
|
865
|
+
setSearchQuery('');
|
|
866
|
+
setColumnFilters([]);
|
|
867
|
+
}}
|
|
868
|
+
enableFiltering={features.filtering}
|
|
869
|
+
showFilterRow={showFilterRow}
|
|
870
|
+
enableColumnReordering={features.columnReordering}
|
|
871
|
+
onColumnOrderChange={setColumnOrder}
|
|
872
|
+
onColumnDrop={(draggedColumnId, targetColumnId) => {
|
|
873
|
+
// Handle column drop
|
|
874
|
+
}}
|
|
875
|
+
savedColumnOrder={savedColumnOrder}
|
|
876
|
+
enablePersistence={features.columnReordering}
|
|
877
|
+
tableId={title ? `datatable-${title.toLowerCase().replace(/\s+/g, '-')}` : undefined}
|
|
878
|
+
dataLength={finalTableData?.length || 0}
|
|
879
|
+
virtualHeight={virtualHeight}
|
|
880
|
+
forceVirtualization={false}
|
|
881
|
+
hierarchical={features.hierarchical && hierarchical?.enabled ? {
|
|
882
|
+
...hierarchical,
|
|
883
|
+
state: hierarchicalState,
|
|
884
|
+
expandAll: hierarchicalState.expandAll,
|
|
885
|
+
collapseAll: hierarchicalState.collapseAll,
|
|
886
|
+
isAllExpanded: hierarchicalState.getExpandedIds().length > 0 &&
|
|
887
|
+
hierarchicalState.getExpandedIds().length === (finalTableData as any[]).filter(row => row.isParent).length,
|
|
888
|
+
hasAnyChildren: (finalTableData as any[]).some(row => row.isParent),
|
|
889
|
+
} : undefined}
|
|
890
|
+
actions={effectiveActions}
|
|
891
|
+
/>
|
|
828
892
|
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
893
|
+
{/* Table footer with pagination */}
|
|
894
|
+
{features.pagination && (
|
|
895
|
+
<tfoot>
|
|
896
|
+
<tr>
|
|
897
|
+
<td colSpan={visibleColumns.length}>
|
|
898
|
+
<PaginationComponent
|
|
899
|
+
table={table}
|
|
900
|
+
pageSizeOptions={finalPageSizeOptions}
|
|
901
|
+
paginationMode={finalPaginationMode}
|
|
902
|
+
totalCount={finalDataCount}
|
|
903
|
+
isLoading={isLoading}
|
|
904
|
+
/>
|
|
905
|
+
</td>
|
|
906
|
+
</tr>
|
|
907
|
+
</tfoot>
|
|
908
|
+
)}
|
|
909
|
+
|
|
910
|
+
</table>
|
|
839
911
|
|
|
840
912
|
{/* Modal Dialogs */}
|
|
841
913
|
<DataTableModals
|
|
@@ -150,11 +150,10 @@ export function DataTableToolbar<TData extends DataRecord>({
|
|
|
150
150
|
const currentGroupBy = grouping.length > 0 ? grouping[0] : null;
|
|
151
151
|
|
|
152
152
|
return (
|
|
153
|
-
|
|
154
|
-
|
|
153
|
+
|
|
154
|
+
<nav className="flex justify-end flex-wrap gap-2">
|
|
155
155
|
{features.search && (
|
|
156
|
-
|
|
157
|
-
<Search className="h-4 w-4 text-sec-500 flex-shrink-0" />
|
|
156
|
+
|
|
158
157
|
<Input
|
|
159
158
|
id="table-search"
|
|
160
159
|
placeholder="Search..."
|
|
@@ -162,13 +161,13 @@ export function DataTableToolbar<TData extends DataRecord>({
|
|
|
162
161
|
onChange={(e) => onGlobalFilterChange(e.target.value)}
|
|
163
162
|
aria-label="Search table"
|
|
164
163
|
tabIndex={0}
|
|
165
|
-
className="flex-1"
|
|
164
|
+
className="justify-self-start w-50 flex-1"
|
|
166
165
|
/>
|
|
167
|
-
|
|
166
|
+
|
|
168
167
|
)}
|
|
169
168
|
|
|
170
|
-
|
|
171
|
-
|
|
169
|
+
|
|
170
|
+
|
|
172
171
|
{/* Grouping */}
|
|
173
172
|
{features.grouping && (
|
|
174
173
|
<GroupingDropdown
|
|
@@ -245,7 +244,7 @@ export function DataTableToolbar<TData extends DataRecord>({
|
|
|
245
244
|
</Button>
|
|
246
245
|
)}
|
|
247
246
|
|
|
248
|
-
</
|
|
249
|
-
|
|
247
|
+
</nav>
|
|
248
|
+
|
|
250
249
|
);
|
|
251
250
|
}
|