@jmruthers/pace-core 0.2.5 → 0.2.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.
Files changed (167) hide show
  1. package/dist/{DataTable-BHlzyKZP.d.ts → DataTable-C1AEm9Cx.d.ts} +1 -1
  2. package/dist/{DataTable-GEY5U7OI.js → DataTable-EEUDXPE5.js} +2 -8
  3. package/dist/{api-T6CBS7IO.js → api-ETQ6YJ3C.js} +2 -3
  4. package/dist/{chunk-DY5E3AT7.js → chunk-BEZRLNK3.js} +13 -3
  5. package/dist/chunk-BEZRLNK3.js.map +1 -0
  6. package/dist/{chunk-ANE4PDC2.js → chunk-C5G2A4PO.js} +159 -6
  7. package/dist/chunk-C5G2A4PO.js.map +1 -0
  8. package/dist/{chunk-WYB6MBZA.js → chunk-EWKPTNPO.js} +579 -973
  9. package/dist/chunk-EWKPTNPO.js.map +1 -0
  10. package/dist/{chunk-TMRLB2LA.js → chunk-HEMJ4SUJ.js} +2 -2
  11. package/dist/{chunk-O4T53L7X.js → chunk-HNDFPXUU.js} +5 -5
  12. package/dist/{chunk-UY7AM4QG.js → chunk-RRUYHORU.js} +161 -74
  13. package/dist/chunk-RRUYHORU.js.map +1 -0
  14. package/dist/{chunk-PFRRIDYA.js → chunk-TIVL4UQ7.js} +2 -2
  15. package/dist/{chunk-2MKP6IYD.js → chunk-VYG4AXYW.js} +2 -2
  16. package/dist/components.d.ts +2 -2
  17. package/dist/components.js +15 -16
  18. package/dist/components.js.map +1 -1
  19. package/dist/hooks.d.ts +1 -1
  20. package/dist/hooks.js +4 -4
  21. package/dist/index.d.ts +2 -2
  22. package/dist/index.js +16 -17
  23. package/dist/index.js.map +1 -1
  24. package/dist/providers.js +2 -2
  25. package/dist/rbac/index.js +25 -20
  26. package/dist/rbac/index.js.map +1 -1
  27. package/dist/styles/core.css +83 -62
  28. package/dist/{types-CInEi-ng.d.ts → types-DiRQsGJs.d.ts} +0 -2
  29. package/dist/utils.d.ts +2 -2
  30. package/dist/utils.js +1 -1
  31. package/docs/api/classes/ErrorBoundary.md +1 -1
  32. package/docs/api/classes/PublicErrorBoundary.md +1 -1
  33. package/docs/api/interfaces/AggregateConfig.md +1 -1
  34. package/docs/api/interfaces/ButtonProps.md +1 -1
  35. package/docs/api/interfaces/CardProps.md +1 -1
  36. package/docs/api/interfaces/ColorPalette.md +1 -1
  37. package/docs/api/interfaces/ColorShade.md +1 -1
  38. package/docs/api/interfaces/DataTableAction.md +1 -1
  39. package/docs/api/interfaces/DataTableColumn.md +1 -1
  40. package/docs/api/interfaces/DataTableProps.md +33 -33
  41. package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
  42. package/docs/api/interfaces/EmptyStateConfig.md +1 -1
  43. package/docs/api/interfaces/EventContextType.md +1 -1
  44. package/docs/api/interfaces/EventLogoProps.md +1 -1
  45. package/docs/api/interfaces/EventProviderProps.md +1 -1
  46. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  47. package/docs/api/interfaces/FileUploadProps.md +1 -1
  48. package/docs/api/interfaces/FooterProps.md +1 -1
  49. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  50. package/docs/api/interfaces/InputProps.md +1 -1
  51. package/docs/api/interfaces/LabelProps.md +1 -1
  52. package/docs/api/interfaces/LoginFormProps.md +1 -1
  53. package/docs/api/interfaces/NavigationItem.md +1 -1
  54. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  55. package/docs/api/interfaces/Organisation.md +1 -1
  56. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  57. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  58. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  59. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  60. package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
  61. package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
  62. package/docs/api/interfaces/PaletteData.md +1 -1
  63. package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
  64. package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
  65. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
  66. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  67. package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
  68. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  69. package/docs/api/interfaces/StorageConfig.md +1 -1
  70. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  71. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  72. package/docs/api/interfaces/StorageListOptions.md +1 -1
  73. package/docs/api/interfaces/StorageListResult.md +1 -1
  74. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  75. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  76. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  77. package/docs/api/interfaces/StyleImport.md +1 -1
  78. package/docs/api/interfaces/ToastActionElement.md +1 -1
  79. package/docs/api/interfaces/ToastProps.md +1 -1
  80. package/docs/api/interfaces/UnifiedAuthContextType.md +1 -1
  81. package/docs/api/interfaces/UnifiedAuthProviderProps.md +1 -1
  82. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  83. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  84. package/docs/api/interfaces/UsePublicEventLogoOptions.md +1 -1
  85. package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
  86. package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
  87. package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
  88. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  89. package/docs/api/interfaces/UserEventAccess.md +1 -1
  90. package/docs/api/interfaces/UserMenuProps.md +1 -1
  91. package/docs/api/interfaces/UserProfile.md +1 -1
  92. package/docs/api/modules.md +10 -10
  93. package/docs/architecture/README.md +1 -1
  94. package/package.json +1 -1
  95. package/src/__tests__/shared/testUtils.optimized.tsx +65 -7
  96. package/src/components/DataTable/DataTable.tsx +1 -3
  97. package/src/components/DataTable/__tests__/DataTable.errorHandling.test.tsx +0 -8
  98. package/src/components/DataTable/__tests__/DataTable.hierarchical.test.tsx +17 -12
  99. package/src/components/DataTable/__tests__/DataTable.infinite-loop.test.tsx +0 -1
  100. package/src/components/DataTable/__tests__/DataTable.integration.test.tsx +4 -12
  101. package/src/components/DataTable/__tests__/DataTable.performance.test.tsx +0 -8
  102. package/src/components/DataTable/__tests__/DataTable.permissions.test.tsx +21 -11
  103. package/src/components/DataTable/__tests__/DataTable.sorting.test.tsx +321 -0
  104. package/src/components/DataTable/__tests__/DataTable.userWorkflows.test.tsx +21 -11
  105. package/src/components/DataTable/__tests__/DataTable.workflowValidation.test.tsx +94 -0
  106. package/src/components/DataTable/__tests__/DataTable.workflows.test.tsx +25 -15
  107. package/src/components/DataTable/__tests__/README.md +11 -2
  108. package/src/components/DataTable/__tests__/performance-regression.test.tsx +0 -11
  109. package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +0 -1
  110. package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +2 -2
  111. package/src/components/DataTable/components/DataTableBody.tsx +34 -35
  112. package/src/components/DataTable/components/DataTableCore.tsx +205 -133
  113. package/src/components/DataTable/components/DataTableToolbar.tsx +9 -10
  114. package/src/components/DataTable/components/DraggableColumnHeader.tsx +3 -7
  115. package/src/components/DataTable/components/EditableRow.tsx +6 -7
  116. package/src/components/DataTable/components/FilterRow.tsx +0 -1
  117. package/src/components/DataTable/components/GroupingDropdown.tsx +2 -2
  118. package/src/components/DataTable/components/UnifiedTableBody.tsx +83 -281
  119. package/src/components/DataTable/components/VirtualizedDataTable.tsx +9 -89
  120. package/src/components/DataTable/components/__tests__/DataTable.accessibility.test.tsx +111 -5
  121. package/src/components/DataTable/components/__tests__/DataTable.integration.test.tsx +82 -13
  122. package/src/components/DataTable/components/__tests__/DataTable.performance.test.tsx +0 -1
  123. package/src/components/DataTable/components/__tests__/DataTable.real.test.tsx +2 -2
  124. package/src/components/DataTable/components/__tests__/DataTable.security.test.tsx +0 -1
  125. package/src/components/DataTable/components/__tests__/DataTable.unit.test.tsx +2 -2
  126. package/src/components/DataTable/components/__tests__/FilteringToggle.unit.test.tsx +3 -0
  127. package/src/components/DataTable/components/index.ts +0 -1
  128. package/src/components/DataTable/core/DataTableContext.tsx +0 -1
  129. package/src/components/DataTable/index.ts +0 -2
  130. package/src/components/DataTable/types.ts +0 -2
  131. package/src/components/Input/Input.tsx +2 -2
  132. package/src/components/Input/__tests__/Input.unit.test.tsx +4 -4
  133. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.integration.test.tsx +6 -2
  134. package/src/components/RBAC/PagePermissionGuard.tsx +13 -0
  135. package/src/components/RBAC/__tests__/PagePermissionGuard.unit.test.tsx +10 -1
  136. package/src/components/Select/Select.tsx +7 -1
  137. package/src/components/__tests__/EdgeCaseTesting.enhanced.test.tsx +2 -1
  138. package/src/hooks/__tests__/useRBAC.unit.test.ts +32 -24
  139. package/src/providers/RBACProvider.tsx +14 -2
  140. package/src/providers/__tests__/UnifiedAuthProvider.unit.test.tsx +11 -3
  141. package/src/rbac/__tests__/cache-invalidation.test.ts +2 -2
  142. package/src/rbac/__tests__/cache.test.ts +3 -3
  143. package/src/rbac/hooks.ts +15 -7
  144. package/src/styles/core.css +83 -62
  145. package/src/utils/__tests__/lazyLoad.unit.test.tsx +13 -18
  146. package/src/utils/storage/__tests__/helpers.unit.test.ts +9 -7
  147. package/dist/cache-I72HKDOA.js +0 -12
  148. package/dist/cache-I72HKDOA.js.map +0 -1
  149. package/dist/chunk-ANE4PDC2.js.map +0 -1
  150. package/dist/chunk-DY5E3AT7.js.map +0 -1
  151. package/dist/chunk-MRRFJ6SA.js +0 -161
  152. package/dist/chunk-MRRFJ6SA.js.map +0 -1
  153. package/dist/chunk-UY7AM4QG.js.map +0 -1
  154. package/dist/chunk-WYB6MBZA.js.map +0 -1
  155. package/src/components/DataTable/__tests__/DataTable.autoSizing.test.tsx +0 -526
  156. package/src/components/DataTable/components/DataTableHeader.tsx +0 -31
  157. package/src/components/DataTable/components/__tests__/DataTableHeader.unit.test.tsx +0 -143
  158. package/src/components/DataTable/examples/AutoSizingExample.tsx +0 -180
  159. package/src/components/DataTable/examples/ColumnSizingComparison.tsx +0 -235
  160. package/src/components/DataTable/utils/__tests__/columnSizing.test.ts +0 -237
  161. package/src/components/DataTable/utils/columnSizing.ts +0 -125
  162. /package/dist/{DataTable-GEY5U7OI.js.map → DataTable-EEUDXPE5.js.map} +0 -0
  163. /package/dist/{api-T6CBS7IO.js.map → api-ETQ6YJ3C.js.map} +0 -0
  164. /package/dist/{chunk-TMRLB2LA.js.map → chunk-HEMJ4SUJ.js.map} +0 -0
  165. /package/dist/{chunk-O4T53L7X.js.map → chunk-HNDFPXUU.js.map} +0 -0
  166. /package/dist/{chunk-PFRRIDYA.js.map → chunk-TIVL4UQ7.js.map} +0 -0
  167. /package/dist/{chunk-2MKP6IYD.js.map → chunk-VYG4AXYW.js.map} +0 -0
@@ -12,7 +12,7 @@
12
12
  import React, { useLayoutEffect, useState, useRef, useMemo } from 'react';
13
13
  import { type Table, flexRender } from '@tanstack/react-table';
14
14
  import { useVirtualizer } from '@tanstack/react-virtual';
15
- import { TableBody, TableHead, TableHeader, TableRow, TableCell } from '../../Table/Table';
15
+ // Removed Table component imports - using native HTML elements
16
16
  import { Button } from '../../Button/Button';
17
17
  import { ChevronUp, ChevronDown, ChevronRight } from 'lucide-react';
18
18
  import { EmptyState } from './EmptyState';
@@ -209,7 +209,6 @@ const renderEditField = (
209
209
  const MemoizedRow = ({
210
210
  row,
211
211
  style,
212
- columnSizes,
213
212
  isEditing,
214
213
  editingData,
215
214
  onEditingDataChange,
@@ -223,7 +222,6 @@ const MemoizedRow = ({
223
222
  }: {
224
223
  row: any;
225
224
  style?: React.CSSProperties;
226
- columnSizes: Record<string, number>;
227
225
  isEditing?: boolean;
228
226
  editingData?: Record<string, any>;
229
227
  onEditingDataChange?: (data: Record<string, any>) => void;
@@ -262,6 +260,12 @@ const MemoizedRow = ({
262
260
  }) => {
263
261
  const rowId = getRowId ? getRowId(row.original, row.index) : String(row.index);
264
262
 
263
+ // Hierarchical row styling - moved to top to avoid hoisting issues
264
+ const hierarchicalRow = row.original as HierarchicalDataRow;
265
+ const isHierarchical = hierarchical?.enabled && hierarchicalRow?.isParent !== undefined;
266
+ const isParent = isHierarchical && hierarchicalRow.isParent;
267
+ const isChild = isHierarchical && !hierarchicalRow.isParent;
268
+
265
269
  // Handle grouped rows
266
270
  if (row.getIsGrouped && row.getIsGrouped()) {
267
271
  const groupValue = row.getValue(grouping[0]);
@@ -271,17 +275,13 @@ const MemoizedRow = ({
271
275
  return (
272
276
  <React.Fragment>
273
277
  {/* Group Header Row */}
274
- <TableRow className="bg-sec-50 hover:bg-sec-100" style={style}>
275
- <TableCell
278
+ <tr className="bg-sec-50 hover:bg-sec-100" style={style}>
279
+ <td
276
280
  className={getTableCellClasses({
277
281
  isCompact: true,
278
282
  className: "px-3 py-2 flex items-center font-medium"
279
283
  })}
280
284
  colSpan={row.getAllCells().length}
281
- style={{
282
- width: '100%',
283
- minWidth: '100%',
284
- }}
285
285
  >
286
286
  <Button
287
287
  variant="ghost"
@@ -298,8 +298,8 @@ const MemoizedRow = ({
298
298
  <span className="text-sm">
299
299
  {String(groupValue)} ({subRowsCount} items)
300
300
  </span>
301
- </TableCell>
302
- </TableRow>
301
+ </td>
302
+ </tr>
303
303
 
304
304
  {/* Render sub-rows if expanded */}
305
305
  {isExpanded && row.subRows?.map((subRow: any) => {
@@ -307,17 +307,14 @@ const MemoizedRow = ({
307
307
  const isSubRowEditing = editingRowId === subRowId;
308
308
 
309
309
  return (
310
- <TableRow key={subRow.id} className="border-l-2 border-l-blue-200" style={style}>
310
+ <tr key={subRow.id} className="border-l-2 border-l-blue-200" style={style}>
311
311
  {subRow.getVisibleCells().map((cell: any) => (
312
- <TableCell
312
+ <td
313
313
  key={cell.id}
314
314
  className={getTableCellClasses({
315
315
  isCompact: true,
316
316
  className: "px-3 py-2 pl-8 whitespace-normal break-words"
317
317
  })}
318
- style={{
319
- width: columnSizes[cell.column.id] || (cell.column?.getSize ? cell.column.getSize() : 120),
320
- }}
321
318
  >
322
319
  {isSubRowEditing && cell.column.id !== 'actions' ? (
323
320
  renderEditField(cell.column, editingData?.[cell.column.id], (value) => {
@@ -347,9 +344,9 @@ const MemoizedRow = ({
347
344
  hasChildren: false
348
345
  })
349
346
  )}
350
- </TableCell>
347
+ </td>
351
348
  ))}
352
- </TableRow>
349
+ </tr>
353
350
  );
354
351
  })}
355
352
  </React.Fragment>
@@ -365,12 +362,6 @@ const MemoizedRow = ({
365
362
  const visibleCells = row.getVisibleCells();
366
363
  const allCells = row.getAllCells ? row.getAllCells() : [];
367
364
 
368
- // Hierarchical row styling
369
- const hierarchicalRow = row.original as HierarchicalDataRow;
370
- const isHierarchical = hierarchical?.enabled && hierarchicalRow?.isParent !== undefined;
371
- const isParent = isHierarchical && hierarchicalRow.isParent;
372
- const isChild = isHierarchical && !hierarchicalRow.isParent;
373
-
374
365
  // Calculate indentation for child rows
375
366
  const indentSize = hierarchical?.indentSize || 24;
376
367
  const indentation = isChild && hierarchical?.state ?
@@ -384,7 +375,7 @@ const MemoizedRow = ({
384
375
  ) : '';
385
376
 
386
377
  return (
387
- <TableRow
378
+ <tr
388
379
  key={row.id}
389
380
  style={{
390
381
  ...style,
@@ -415,16 +406,12 @@ const MemoizedRow = ({
415
406
 
416
407
 
417
408
  return (
418
- <TableCell
409
+ <td
419
410
  key={cell.id}
420
411
  className={getTableCellClasses({
421
412
  isCompact: true,
422
413
  className: "px-3 py-2 whitespace-normal break-words"
423
414
  })}
424
- style={{
425
- width: columnSizes[cell.column.id] || (cell.column?.getSize ? cell.column.getSize() : 120),
426
- minWidth: columnSizes[cell.column.id] ? undefined : 120,
427
- }}
428
415
  >
429
416
  <div className="flex items-center gap-2">
430
417
  {/* Individual expansion button for hierarchical parent rows */}
@@ -500,10 +487,10 @@ const MemoizedRow = ({
500
487
  )}
501
488
  </div>
502
489
  </div>
503
- </TableCell>
490
+ </td>
504
491
  );
505
492
  })}
506
- </TableRow>
493
+ </tr>
507
494
  );
508
495
  };
509
496
 
@@ -549,7 +536,6 @@ export function UnifiedTableBody<TData extends Record<string, any>>({
549
536
  const headerRef = useRef<HTMLTableSectionElement>(null);
550
537
  const bodyRef = useRef<HTMLTableSectionElement>(null);
551
538
  const parentRef = useRef<HTMLDivElement>(null);
552
- const [columnSizes, setColumnSizes] = useState<Record<string, number>>({});
553
539
 
554
540
  // Determine if virtualization should be used
555
541
  const shouldVirtualize = forceVirtualization || dataLength > VIRTUALIZATION_THRESHOLD;
@@ -569,56 +555,16 @@ export function UnifiedTableBody<TData extends Record<string, any>>({
569
555
  const virtualRows = virtualizer.getVirtualItems();
570
556
  const totalSize = virtualizer.getTotalSize();
571
557
 
572
- // Calculate column sizes and sync between header and body
573
- useLayoutEffect(() => {
574
- if (headerRef.current && bodyRef.current) {
575
- const headerCells = headerRef.current.querySelectorAll('th');
576
- const newColumnSizes: Record<string, number> = {};
577
- const tableWidth = headerRef.current.closest('table')?.getBoundingClientRect().width || 0;
578
- const totalColumns = table.getHeaderGroups()[0]?.headers.length || 0;
579
-
580
- // Calculate column sizes with proper distribution
581
- table.getHeaderGroups()[0]?.headers.forEach((header, index) => {
582
- const headerCell = headerCells[index];
583
- if (headerCell) {
584
- const columnSize = header.column?.getSize ? header.column.getSize() : 150;
585
- const computedWidth = headerCell.getBoundingClientRect().width;
586
-
587
- // For fewer columns, ensure proper width distribution
588
- if (totalColumns > 0) {
589
- const availableWidth = tableWidth / totalColumns;
590
- const minWidth = Math.max(columnSize, 80); // Reduced minimum column width
591
- newColumnSizes[header.id] = Math.max(computedWidth, availableWidth, minWidth);
592
- } else {
593
- newColumnSizes[header.id] = Math.max(computedWidth, columnSize);
594
- }
595
- }
596
- });
597
-
598
- // Only update if sizes have actually changed
599
- const hasChanged = Object.keys(newColumnSizes).some(
600
- key => newColumnSizes[key] !== columnSizes[key]
601
- ) || Object.keys(columnSizes).length !== Object.keys(newColumnSizes).length;
602
-
603
- if (hasChanged) {
604
- setColumnSizes(newColumnSizes);
605
- }
606
- }
607
- }, [table, columnSizes]);
608
558
 
609
559
  // Render table content
610
560
  const renderTableContent = () => {
611
561
  if (rows.length === 0) {
612
562
  return (
613
- <TableRow>
614
- <TableCell
563
+ <tr>
564
+ <td
615
565
  colSpan={table.getVisibleFlatColumns().length}
616
566
  className="px-3 py-2"
617
567
  role="status"
618
- style={{
619
- width: '100%',
620
- minWidth: '100%',
621
- }}
622
568
  >
623
569
  <EmptyState
624
570
  title={emptyState?.title}
@@ -628,8 +574,8 @@ export function UnifiedTableBody<TData extends Record<string, any>>({
628
574
  isFiltered={isFiltered}
629
575
  onClearFilters={onClearFilters}
630
576
  />
631
- </TableCell>
632
- </TableRow>
577
+ </td>
578
+ </tr>
633
579
  );
634
580
  }
635
581
 
@@ -646,7 +592,6 @@ export function UnifiedTableBody<TData extends Record<string, any>>({
646
592
  <MemoizedRow
647
593
  key={row.id}
648
594
  row={row}
649
- columnSizes={columnSizes}
650
595
  isEditing={isEditing}
651
596
  editingData={editingData}
652
597
  onEditingDataChange={onEditingDataChange}
@@ -678,7 +623,6 @@ export function UnifiedTableBody<TData extends Record<string, any>>({
678
623
  <MemoizedRow
679
624
  key={row.id}
680
625
  row={row}
681
- columnSizes={columnSizes}
682
626
  isEditing={isEditing}
683
627
  editingData={editingData}
684
628
  onEditingDataChange={onEditingDataChange}
@@ -696,216 +640,74 @@ export function UnifiedTableBody<TData extends Record<string, any>>({
696
640
  };
697
641
 
698
642
  return (
699
- <>
700
- {/* Table Header */}
701
- <TableHeader ref={headerRef}>
702
- {headerGroups.map((headerGroup) => (
703
- <TableRow key={headerGroup.id}>
704
- {/* Expand/Collapse All Button - Only show for hierarchical tables */}
705
- {hierarchical?.enabled && hierarchical?.hasAnyChildren && (
706
- <TableHead className="w-12">
707
- <Button
708
- variant="ghost"
709
- size="sm"
710
- onClick={hierarchical.isAllExpanded ? hierarchical.collapseAll : hierarchical.expandAll}
711
- className="h-8 w-8 p-0"
712
- aria-label={hierarchical.isAllExpanded ? 'Collapse all' : 'Expand all'}
713
- title={hierarchical.isAllExpanded ? 'Collapse all' : 'Expand all'}
714
- >
715
- {hierarchical.isAllExpanded ? (
716
- <ChevronDown className="h-4 w-4" />
717
- ) : (
718
- <ChevronRight className="h-4 w-4" />
719
- )}
720
- </Button>
721
- </TableHead>
722
- )}
723
-
724
- {headerGroup.headers
725
- .filter(header => {
726
- // Check if getIsVisible method exists and call it, otherwise assume visible
727
- return typeof header.column.getIsVisible === 'function'
728
- ? header.column.getIsVisible()
729
- : true;
730
- })
731
- .map((header) => (
732
- <DraggableColumnHeader
733
- key={header.id}
734
- header={header}
735
- enableReordering={enableColumnReordering}
736
- onColumnDrop={onColumnDrop}
737
- />
738
- ))}
739
- </TableRow>
740
- ))}
741
- </TableHeader>
742
-
743
- {/* Filter Row */}
744
- {enableFiltering && showFilterRow && (
745
- <TableHeader>
746
- <FilterRow
747
- table={table}
748
- visibleColumns={headerGroups[0]?.headers?.filter(header => {
643
+ <tbody ref={bodyRef}>
644
+ {/* Unified Table Body - Same structure for both virtualized and standard */}
645
+ {/* Creation Row */}
646
+ {isCreating && (
647
+ <tr>
648
+ {headerGroups[0]?.headers
649
+ ?.filter(header => {
749
650
  // Check if getIsVisible method exists and call it, otherwise assume visible
750
651
  return typeof header.column.getIsVisible === 'function'
751
652
  ? header.column.getIsVisible()
752
653
  : true;
753
- }) || []}
754
- />
755
- </TableHeader>
756
- )}
757
-
758
- {/* Unified Table Body - Same structure for both virtualized and standard */}
759
- {shouldVirtualize ? (
760
- <div
761
- ref={parentRef}
762
- className="overflow-auto"
763
- style={{ height: `${virtualHeight}px` }}
764
- >
765
- <div
766
- style={{
767
- height: `${totalSize}px`,
768
- width: '100%',
769
- position: 'relative',
770
- }}
771
- >
772
- <table className="w-full" style={{ tableLayout: 'fixed', width: '100%' }}>
773
- <TableBody ref={bodyRef}>
774
- {/* Creation Row */}
775
- {isCreating && (
776
- <TableRow>
777
- {headerGroups[0]?.headers
778
- ?.filter(header => {
779
- // Check if getIsVisible method exists and call it, otherwise assume visible
780
- return typeof header.column.getIsVisible === 'function'
781
- ? header.column.getIsVisible()
782
- : true;
783
- })
784
- ?.filter(header => header.column.id !== 'actions' && header.column.id !== 'select')
785
- ?.map((header) => (
786
- <TableCell
787
- key={header.column.id}
788
- className={getTableCellClasses({
789
- isCompact: true,
790
- className: "px-3 py-2"
791
- })}
792
- style={{
793
- width: columnSizes[header.column.id] || (header.column?.getSize ? header.column.getSize() : 120),
794
- }}
795
- >
796
- {renderEditField(header.column, creationData[header.column.id], (value) => {
797
- if (typeof value === 'object' && value !== null) {
798
- onCreationDataChange({ ...creationData, ...value });
799
- } else {
800
- onCreationDataChange({ ...creationData, [header.column.id]: value });
801
- }
802
- }, creationData)}
803
- </TableCell>
804
- ))}
805
- <TableCell
806
- className={getTableCellClasses({
807
- isCompact: true,
808
- className: "px-3 py-2 flex gap-1"
809
- })}
810
- style={{
811
- width: columnSizes['actions'] || 100,
812
- }}
813
- >
814
- <button
815
- onClick={onSaveCreation}
816
- className="h-8 w-8 p-0 hover:bg-muted/50 flex items-center justify-center"
817
- title="Save new row"
818
- >
819
- <svg className="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
820
- <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
821
- </svg>
822
- </button>
823
- <button
824
- onClick={onCancelCreation}
825
- className="h-8 w-8 p-0 hover:bg-muted/50 flex items-center justify-center"
826
- title="Cancel new row"
827
- >
828
- <svg className="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
829
- <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
830
- </svg>
831
- </button>
832
- </TableCell>
833
- </TableRow>
834
- )}
835
-
836
- {renderTableContent()}
837
- </TableBody>
838
- </table>
839
- </div>
840
- </div>
841
- ) : (
842
- <TableBody ref={bodyRef}>
843
- {/* Creation Row */}
844
- {isCreating && (
845
- <TableRow>
846
- {headerGroups[0]?.headers
847
- ?.filter(header => {
848
- // Check if getIsVisible method exists and call it, otherwise assume visible
849
- return typeof header.column.getIsVisible === 'function'
850
- ? header.column.getIsVisible()
851
- : true;
852
- })
853
- ?.filter(header => header.column.id !== 'actions' && header.column.id !== 'select')
854
- ?.map((header) => (
855
- <TableCell
856
- key={header.column.id}
857
- className={getTableCellClasses({
858
- isCompact: true,
859
- className: "px-3 py-2"
860
- })}
861
- style={{
862
- width: columnSizes[header.column.id] || (header.column?.getSize ? header.column.getSize() : 120),
863
- }}
864
- >
865
- {renderEditField(header.column, creationData[header.column.id], (value) => {
866
- if (typeof value === 'object' && value !== null) {
867
- onCreationDataChange({ ...creationData, ...value });
868
- } else {
869
- onCreationDataChange({ ...creationData, [header.column.id]: value });
870
- }
871
- }, creationData)}
872
- </TableCell>
873
- ))}
874
- <TableCell
654
+ })
655
+ ?.filter(header => header.column.id !== 'actions' && header.column.id !== 'select')
656
+ ?.map((header) => (
657
+ <td
658
+ key={header.column.id}
875
659
  className={getTableCellClasses({
876
660
  isCompact: true,
877
- className: "px-3 py-2 flex gap-1"
661
+ className: "px-3 py-2"
878
662
  })}
879
- style={{
880
- width: columnSizes['actions'] || 100,
881
- }}
882
663
  >
883
- <button
884
- onClick={onSaveCreation}
885
- className="h-8 w-8 p-0 hover:bg-muted/50 flex items-center justify-center"
886
- title="Save new row"
887
- >
888
- <svg className="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
889
- <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
890
- </svg>
891
- </button>
892
- <button
893
- onClick={onCancelCreation}
894
- className="h-8 w-8 p-0 hover:bg-muted/50 flex items-center justify-center"
895
- title="Cancel new row"
896
- >
897
- <svg className="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
898
- <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
899
- </svg>
900
- </button>
901
- </TableCell>
902
- </TableRow>
903
- )}
904
-
905
- {renderTableContent()}
906
- </TableBody>
664
+ {renderEditField(header.column, creationData[header.column.id], (value) => {
665
+ if (typeof value === 'object' && value !== null) {
666
+ onCreationDataChange({ ...creationData, ...value });
667
+ } else {
668
+ onCreationDataChange({ ...creationData, [header.column.id]: value });
669
+ }
670
+ }, creationData)}
671
+ </td>
672
+ ))}
673
+ <td
674
+ className={getTableCellClasses({
675
+ isCompact: true,
676
+ className: "px-3 py-2 flex gap-1"
677
+ })}
678
+ >
679
+ <button
680
+ onClick={onSaveCreation}
681
+ className="h-8 w-8 p-0 hover:bg-muted/50 flex items-center justify-center"
682
+ title="Save new row"
683
+ >
684
+ <svg className="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
685
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
686
+ </svg>
687
+ </button>
688
+ <button
689
+ onClick={onCancelCreation}
690
+ className="h-8 w-8 p-0 hover:bg-muted/50 flex items-center justify-center"
691
+ title="Cancel new row"
692
+ >
693
+ <svg className="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
694
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
695
+ </svg>
696
+ </button>
697
+ </td>
698
+ </tr>
907
699
  )}
908
-
909
- </>
700
+
701
+ {/* Filter Row */}
702
+ {showFilterRow && enableFiltering && (
703
+ <FilterRow
704
+ table={table}
705
+ visibleColumns={table.getHeaderGroups()[0]?.headers || []}
706
+ />
707
+ )}
708
+
709
+ {/* Table Content */}
710
+ {renderTableContent()}
711
+ </tbody>
910
712
  );
911
713
  }