@jmruthers/pace-core 0.5.74 → 0.5.76
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-4GAVPIEG.js +120 -0
- package/dist/{PublicLoadingSpinner-DLpF5bbs.d.ts → PublicLoadingSpinner-BiNER8F5.d.ts} +30 -19
- package/dist/RBACService-C4udt_Zp.d.ts +528 -0
- package/dist/{UnifiedAuthProvider-K4NRGXL4.js → UnifiedAuthProvider-3NKDOSOK.js} +6 -4
- package/dist/UnifiedAuthProvider-Bj6YCf7c.d.ts +113 -0
- package/dist/chunk-5F3NDPJV.js +232 -0
- package/dist/chunk-5F3NDPJV.js.map +1 -0
- package/dist/chunk-A4FUBC7B.js +17 -0
- package/dist/chunk-A4FUBC7B.js.map +1 -0
- package/dist/{chunk-SMJZMKYN.js → chunk-A6HBIY5P.js} +2 -11
- package/dist/{chunk-SMJZMKYN.js.map → chunk-A6HBIY5P.js.map} +1 -1
- package/dist/{chunk-LVQ26TCN.js → chunk-AFGTSUAD.js} +43 -127
- package/dist/chunk-AFGTSUAD.js.map +1 -0
- package/dist/{chunk-BKVGJVUR.js → chunk-K34IM5CT.js} +497 -33
- package/dist/chunk-K34IM5CT.js.map +1 -0
- package/dist/{chunk-UJMCGBLS.js → chunk-KHJS6VIA.js} +203 -41
- package/dist/chunk-KHJS6VIA.js.map +1 -0
- package/dist/{chunk-ORSMVXO2.js → chunk-KK73ZB4E.js} +9 -14
- package/dist/chunk-KK73ZB4E.js.map +1 -0
- package/dist/{chunk-VKOCWWVY.js → chunk-L3RV2ALE.js} +1 -6
- package/dist/{chunk-VKOCWWVY.js.map → chunk-L3RV2ALE.js.map} +1 -1
- package/dist/chunk-LW7MMEAQ.js +59 -0
- package/dist/chunk-LW7MMEAQ.js.map +1 -0
- package/dist/{chunk-IHMMNKNA.js → chunk-M5IWZRBT.js} +5118 -1864
- package/dist/chunk-M5IWZRBT.js.map +1 -0
- package/dist/{chunk-DG5Z55HH.js → chunk-NTNILOBC.js} +7 -9
- package/dist/chunk-NTNILOBC.js.map +1 -0
- package/dist/chunk-PYUXFQJ3.js +11 -0
- package/dist/chunk-PYUXFQJ3.js.map +1 -0
- package/dist/chunk-URUTVZ7N.js +27 -0
- package/dist/chunk-URUTVZ7N.js.map +1 -0
- package/dist/chunk-WN6XJWOS.js +2468 -0
- package/dist/chunk-WN6XJWOS.js.map +1 -0
- package/dist/{chunk-3SP4P7NS.js → chunk-XLZ7U46Z.js} +59 -1
- package/dist/chunk-XLZ7U46Z.js.map +1 -0
- package/dist/{chunk-H2TNUICK.js → chunk-Y6TXWPJO.js} +50 -50
- package/dist/chunk-Y6TXWPJO.js.map +1 -0
- package/dist/{chunk-YNUBMSMV.js → chunk-YCKPEMJA.js} +186 -263
- package/dist/chunk-YCKPEMJA.js.map +1 -0
- package/dist/components.d.ts +4 -5
- package/dist/components.js +35 -41
- package/dist/components.js.map +1 -1
- package/dist/hooks.d.ts +20 -43
- package/dist/hooks.js +13 -12
- package/dist/hooks.js.map +1 -1
- package/dist/index.d.ts +156 -10
- package/dist/index.js +193 -96
- package/dist/index.js.map +1 -1
- package/dist/{organisation-t-vvQC3g.d.ts → organisation-BtshODVF.d.ts} +4 -3
- package/dist/providers.d.ts +27 -38
- package/dist/providers.js +33 -23
- package/dist/rbac/index.d.ts +114 -5
- package/dist/rbac/index.js +15 -15
- package/dist/styles/index.js +2 -2
- package/dist/theming/runtime.js +1 -3
- package/dist/types.d.ts +3 -3
- package/dist/types.js +1 -1
- package/dist/types.js.map +1 -1
- package/dist/{unified-CMPjE_fv.d.ts → unified-CM7T0aTK.d.ts} +1 -1
- package/dist/useInactivityTracker-MRUU55XI.js +10 -0
- package/dist/{usePublicRouteParams-Ua1Vz-HG.d.ts → usePublicRouteParams-B-CumWRc.d.ts} +3 -3
- package/dist/utils.js +7 -9
- package/dist/utils.js.map +1 -1
- package/dist/validation.d.ts +1 -1
- package/docs/TERMINOLOGY.md +231 -0
- package/docs/api/classes/ColumnFactory.md +1 -1
- package/docs/api/classes/ErrorBoundary.md +1 -1
- package/docs/api/classes/InvalidScopeError.md +1 -1
- package/docs/api/classes/MissingUserContextError.md +1 -1
- package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
- package/docs/api/classes/PermissionDeniedError.md +1 -1
- package/docs/api/classes/PublicErrorBoundary.md +1 -1
- package/docs/api/classes/RBACAuditManager.md +1 -1
- package/docs/api/classes/RBACCache.md +1 -1
- package/docs/api/classes/RBACEngine.md +1 -1
- package/docs/api/classes/RBACError.md +1 -1
- package/docs/api/classes/RBACNotInitializedError.md +1 -1
- package/docs/api/classes/SecureSupabaseClient.md +1 -1
- package/docs/api/classes/StorageUtils.md +1 -1
- package/docs/api/enums/FileCategory.md +1 -1
- package/docs/api/interfaces/AggregateConfig.md +1 -1
- package/docs/api/interfaces/ButtonProps.md +3 -3
- package/docs/api/interfaces/CardProps.md +2 -2
- package/docs/api/interfaces/ColorPalette.md +1 -1
- package/docs/api/interfaces/ColorShade.md +1 -1
- package/docs/api/interfaces/DataAccessRecord.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 +1 -1
- package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
- package/docs/api/interfaces/EmptyStateConfig.md +1 -1
- package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
- package/docs/api/interfaces/EventLogoProps.md +2 -2
- package/docs/api/interfaces/FileDisplayProps.md +1 -1
- package/docs/api/interfaces/FileMetadata.md +1 -1
- package/docs/api/interfaces/FileReference.md +1 -1
- package/docs/api/interfaces/FileSizeLimits.md +1 -1
- package/docs/api/interfaces/FileUploadOptions.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 +2 -2
- package/docs/api/interfaces/LabelProps.md +1 -1
- package/docs/api/interfaces/LoginFormProps.md +1 -1
- package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
- package/docs/api/interfaces/NavigationContextType.md +1 -1
- package/docs/api/interfaces/NavigationGuardProps.md +1 -1
- package/docs/api/interfaces/NavigationItem.md +1 -1
- package/docs/api/interfaces/NavigationMenuProps.md +1 -1
- package/docs/api/interfaces/NavigationProviderProps.md +1 -1
- package/docs/api/interfaces/Organisation.md +1 -1
- package/docs/api/interfaces/OrganisationContextType.md +28 -17
- package/docs/api/interfaces/OrganisationMembership.md +1 -1
- package/docs/api/interfaces/OrganisationProviderProps.md +2 -2
- 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/PageAccessRecord.md +1 -1
- package/docs/api/interfaces/PagePermissionContextType.md +1 -1
- package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
- package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
- package/docs/api/interfaces/PaletteData.md +1 -1
- package/docs/api/interfaces/PermissionEnforcerProps.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 +2 -2
- 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/RBACConfig.md +1 -1
- package/docs/api/interfaces/RBACContextType.md +5 -11
- package/docs/api/interfaces/RBACLogger.md +1 -1
- package/docs/api/interfaces/RBACProviderProps.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
- package/docs/api/interfaces/RouteAccessRecord.md +1 -1
- package/docs/api/interfaces/RouteConfig.md +1 -1
- package/docs/api/interfaces/SecureDataContextType.md +1 -1
- package/docs/api/interfaces/SecureDataProviderProps.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/SwitchProps.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 +524 -440
- package/docs/api/interfaces/UnifiedAuthProviderProps.md +14 -14
- 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/UseResolvedScopeOptions.md +47 -0
- package/docs/api/interfaces/UseResolvedScopeReturn.md +47 -0
- package/docs/api/interfaces/UserEventAccess.md +11 -11
- package/docs/api/interfaces/UserMenuProps.md +1 -1
- package/docs/api/interfaces/UserProfile.md +1 -1
- package/docs/api/modules.md +234 -61
- package/docs/api-reference/providers.md +26 -7
- package/docs/architecture/services.md +30 -32
- package/docs/best-practices/README.md +20 -0
- package/docs/best-practices/accessibility.md +566 -0
- package/docs/best-practices/performance-expansion.md +473 -0
- package/docs/breaking-changes.md +2 -5
- package/docs/core-concepts/authentication.md +15 -7
- package/docs/documentation-index.md +1 -1
- package/docs/documentation-templates.md +539 -0
- package/docs/getting-started/quick-start.md +16 -66
- package/docs/implementation-guides/component-styling.md +410 -0
- package/docs/implementation-guides/data-tables.md +1 -1
- package/docs/migration/service-architecture.md +121 -260
- package/docs/rbac/README-rbac-rls-integration.md +48 -38
- package/docs/style-guide.md +39 -0
- package/{src/rbac/examples → examples/RBAC}/CompleteRBACExample.tsx +3 -2
- package/{src/rbac/examples → examples/RBAC}/EventBasedApp.tsx +5 -4
- package/{src/components/examples → examples/RBAC}/PermissionExample.tsx +7 -6
- package/examples/RBAC/__tests__/PermissionExample.test.tsx +150 -0
- package/examples/RBAC/index.ts +13 -0
- package/examples/README.md +37 -0
- package/examples/index.ts +22 -0
- package/{src/examples → examples/public-pages}/CorrectPublicPageImplementation.tsx +1 -1
- package/{src/examples → examples/public-pages}/PublicEventPage.tsx +1 -1
- package/{src/examples → examples/public-pages}/PublicPageApp.tsx +1 -1
- package/{src/examples → examples/public-pages}/PublicPageUsageExample.tsx +1 -1
- package/examples/public-pages/__tests__/PublicPageUsageExample.test.tsx +159 -0
- package/examples/public-pages/index.ts +14 -0
- package/package.json +22 -18
- package/src/__tests__/TEST_GUIDE_CURSOR.md +940 -9
- package/src/__tests__/helpers/README.md +255 -0
- package/src/__tests__/helpers/index.ts +62 -0
- package/src/__tests__/helpers/supabaseMock.ts +75 -5
- package/src/__tests__/rbac/PagePermissionGuard.test.tsx +6 -8
- package/src/components/DataTable/__tests__/DataTable.default-state.test.tsx +17 -6
- package/src/components/DataTable/__tests__/DataTableCore.test.tsx +73 -9
- package/src/components/DataTable/components/DataTableCore.tsx +280 -475
- package/src/components/DataTable/components/UnifiedTableBody.tsx +120 -153
- package/src/components/DataTable/components/__tests__/COVERAGE_NOTE.md +55 -0
- package/src/components/DataTable/components/index.ts +1 -2
- package/src/components/DataTable/context/__tests__/DataTableContext.test.tsx +208 -275
- package/src/components/DataTable/core/__tests__/ColumnFactory.test.ts +254 -0
- package/src/components/DataTable/core/index.ts +1 -8
- package/src/components/DataTable/examples/__tests__/HierarchicalExample.test.tsx +45 -0
- package/src/components/DataTable/examples/__tests__/PerformanceExample.test.tsx +117 -0
- package/src/components/DataTable/hooks/__tests__/useColumnOrderPersistence.test.ts +525 -0
- package/src/components/DataTable/hooks/__tests__/useColumnReordering.test.ts +570 -0
- package/src/components/DataTable/hooks/__tests__/useHierarchicalState.test.ts +214 -0
- package/src/components/DataTable/hooks/__tests__/useTableColumns.test.ts +224 -0
- package/src/components/DataTable/hooks/index.ts +6 -0
- package/src/components/DataTable/hooks/useColumnReordering.ts +1 -0
- package/src/components/DataTable/hooks/useDataTablePermissions.ts +149 -0
- package/src/components/DataTable/hooks/useDataTableState.ts +12 -6
- package/src/components/DataTable/hooks/useHierarchicalState.ts +26 -8
- package/src/components/DataTable/hooks/useTableColumns.ts +153 -0
- package/src/components/DataTable/index.ts +1 -9
- package/src/components/DataTable/utils/__tests__/COVERAGE_NOTE.md +89 -0
- package/src/components/DataTable/utils/__tests__/exportUtils.test.ts +3 -6
- package/src/components/DataTable/utils/__tests__/flexibleImport.test.ts +462 -0
- package/src/components/DataTable/utils/__tests__/hierarchicalSorting.test.ts +247 -0
- package/src/components/DataTable/utils/__tests__/hierarchicalUtils.test.ts +8 -6
- package/src/components/DataTable/utils/__tests__/performanceUtils.test.ts +466 -0
- package/src/components/DataTable/utils/__tests__/rowUtils.test.ts +265 -0
- package/src/components/DataTable/utils/errorHandling.ts +52 -460
- package/src/components/DataTable/utils/exportUtils.ts +46 -15
- package/src/components/DataTable/utils/hierarchicalSorting.ts +50 -3
- package/src/components/DataTable/utils/hierarchicalUtils.ts +167 -34
- package/src/components/DataTable/utils/index.ts +5 -0
- package/src/components/DataTable/utils/rowUtils.ts +68 -0
- package/src/components/Dialog/examples/__tests__/HtmlDialogExample.test.tsx +71 -0
- package/src/components/Dialog/examples/__tests__/SimpleHtmlTest.test.tsx +122 -0
- package/src/components/EventSelector/EventSelector.test.tsx +672 -0
- package/src/components/EventSelector/EventSelector.tsx +1 -1
- package/src/components/Header/Header.test.tsx +35 -1
- package/src/components/Header/Header.tsx +3 -1
- package/src/components/Label/__tests__/Label.test.tsx +434 -0
- package/src/components/OrganisationSelector/OrganisationSelector.tsx +3 -3
- package/src/components/PaceAppLayout/__tests__/PaceAppLayout.rbac.test.tsx +24 -4
- package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +3 -2
- package/src/components/PublicLayout/__tests__/PublicPageContextChecker.test.tsx +190 -0
- package/src/components/PublicLayout/__tests__/PublicPageDebugger.test.tsx +185 -0
- package/src/components/PublicLayout/__tests__/PublicPageProvider.test.tsx +313 -0
- package/src/components/Select/Select.test.tsx +143 -120
- package/src/components/Select/Select.tsx +47 -212
- package/src/components/Select/hooks.ts +36 -1
- package/src/components/Select/index.ts +2 -1
- package/src/hooks/__tests__/useFocusManagement.unit.test.ts +220 -0
- package/src/hooks/__tests__/useIsMobile.unit.test.ts +117 -0
- package/src/hooks/__tests__/useKeyboardShortcuts.unit.test.ts +295 -0
- package/src/hooks/__tests__/useOrganisationSecurity.unit.test.tsx +29 -19
- package/src/hooks/__tests__/useRBAC.unit.test.ts +7 -3
- package/src/hooks/__tests__/useSecureDataAccess.unit.test.tsx +115 -19
- package/src/hooks/services/__tests__/useServiceHooks.test.tsx +137 -0
- package/src/hooks/useEventTheme.test.ts +350 -0
- package/src/hooks/useEventTheme.ts +1 -1
- package/src/hooks/useEvents.ts +61 -0
- package/src/hooks/useOrganisationSecurity.test.ts +4 -4
- package/src/hooks/useOrganisationSecurity.ts +2 -2
- package/src/hooks/useOrganisations.ts +64 -0
- package/src/hooks/useSecureDataAccess.test.ts +37 -30
- package/src/hooks/useSecureDataAccess.ts +2 -2
- package/src/index.ts +18 -3
- package/src/providers/AuthProvider.tsx +8 -292
- package/src/providers/EventProvider.tsx +15 -425
- package/src/providers/InactivityProvider.tsx +8 -231
- package/src/providers/OrganisationProvider.test.simple.tsx +3 -2
- package/src/providers/OrganisationProvider.tsx +11 -890
- package/src/providers/UnifiedAuthProvider.tsx +8 -320
- package/src/providers/__tests__/AuthProvider.test.tsx +18 -17
- package/src/providers/__tests__/EventProvider.test.tsx +253 -2
- package/src/providers/__tests__/InactivityProvider.test-helper.tsx +65 -0
- package/src/providers/__tests__/InactivityProvider.test.tsx +46 -114
- package/src/providers/__tests__/OrganisationProvider.test.tsx +313 -3
- package/src/providers/__tests__/ProviderLifecycle.test.tsx +341 -0
- package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +383 -2
- package/src/providers/index.ts +8 -7
- package/src/providers/services/EventServiceProvider.tsx +3 -0
- package/src/providers/services/UnifiedAuthProvider.tsx +3 -0
- package/src/rbac/hooks/__tests__/usePermissions.integration.test.ts +437 -0
- package/src/rbac/hooks/index.ts +2 -0
- package/src/rbac/hooks/usePermissions.test.ts +296 -0
- package/src/rbac/hooks/useRBAC.test.ts +9 -5
- package/src/rbac/hooks/useRBAC.ts +3 -3
- package/src/rbac/hooks/useResolvedScope.ts +232 -0
- package/src/rbac/providers/__tests__/RBACProvider.integration.test.tsx +688 -0
- package/src/rbac/providers/__tests__/RBACProvider.test.tsx +507 -0
- package/src/services/AuthService.ts +19 -4
- package/src/services/__tests__/AuthService.test.ts +288 -0
- package/src/services/__tests__/InactivityService.lifecycle.test.ts +411 -0
- package/src/services/__tests__/OrganisationService.pagination.test.ts +375 -0
- package/src/styles/core.css +2 -0
- package/src/types/__tests__/README.md +114 -0
- package/src/types/__tests__/guards.test.ts +246 -0
- package/src/types/__tests__/validation.test.ts +731 -0
- package/src/types/guards.ts +1 -0
- package/src/types/organisation.ts +3 -2
- package/src/utils/__tests__/file-reference.test.ts +383 -0
- package/src/utils/__tests__/performanceBenchmark.test.ts +175 -0
- package/src/utils/appNameResolver.test.ts +54 -0
- package/src/validation/__tests__/csrf.unit.test.ts +63 -0
- package/src/validation/__tests__/passwordSchema.unit.test.ts +105 -0
- package/src/validation/__tests__/sanitization.unit.test.ts +250 -0
- package/src/validation/__tests__/schemaUtils.unit.test.ts +451 -0
- package/src/validation/__tests__/user.unit.test.ts +440 -0
- package/dist/DataTable-2QR5TER5.js +0 -102
- package/dist/RBACProvider-BO4ilsQB.d.ts +0 -63
- package/dist/UnifiedAuthProvider-D02AMXgO.d.ts +0 -103
- package/dist/chunk-3SP4P7NS.js.map +0 -1
- package/dist/chunk-B5LK25HV.js +0 -953
- package/dist/chunk-B5LK25HV.js.map +0 -1
- package/dist/chunk-BKVGJVUR.js.map +0 -1
- package/dist/chunk-C5Q5LRU5.js +0 -5691
- package/dist/chunk-C5Q5LRU5.js.map +0 -1
- package/dist/chunk-CDDYJCYU.js +0 -79
- package/dist/chunk-CDDYJCYU.js.map +0 -1
- package/dist/chunk-DG5Z55HH.js.map +0 -1
- package/dist/chunk-H2TNUICK.js.map +0 -1
- package/dist/chunk-IHMMNKNA.js.map +0 -1
- package/dist/chunk-LVQ26TCN.js.map +0 -1
- package/dist/chunk-ORSMVXO2.js.map +0 -1
- package/dist/chunk-TYHR5X4W.js +0 -33
- package/dist/chunk-TYHR5X4W.js.map +0 -1
- package/dist/chunk-UJMCGBLS.js.map +0 -1
- package/dist/chunk-V6BHACCH.js +0 -17
- package/dist/chunk-V6BHACCH.js.map +0 -1
- package/dist/chunk-YNUBMSMV.js.map +0 -1
- package/dist/eventContext-BBA42P6G.js +0 -14
- package/dist/rbac/cli/policy-manager.js +0 -278
- package/dist/rbac/cli/policy-manager.js.map +0 -1
- package/docs/api/interfaces/EventContextType.md +0 -96
- package/docs/api/interfaces/EventProviderProps.md +0 -19
- package/docs/documentation-style-checklist.md +0 -294
- package/src/components/DataTable/components/DataTableBody.tsx +0 -488
- package/src/components/DataTable/components/DraggableColumnHeader.tsx +0 -144
- package/src/components/DataTable/components/VirtualizedDataTable.tsx +0 -515
- package/src/components/DataTable/core/ActionManager.ts +0 -235
- package/src/components/DataTable/core/ColumnManager.ts +0 -205
- package/src/components/DataTable/core/DataManager.ts +0 -188
- package/src/components/DataTable/core/DataTableContext.tsx +0 -181
- package/src/components/DataTable/core/LocalDataAdapter.ts +0 -264
- package/src/components/DataTable/core/PluginRegistry.ts +0 -229
- package/src/components/DataTable/core/StateManager.ts +0 -311
- package/src/components/DataTable/core/__tests__/ActionManager.test.ts +0 -634
- package/src/components/DataTable/core/__tests__/DataManager.test.ts +0 -519
- package/src/components/DataTable/core/__tests__/StateManager.test.ts +0 -714
- package/src/components/DataTable/core/interfaces.ts +0 -338
- package/src/components/DataTable/utils/debugTools.ts +0 -583
- package/src/components/Select/Select.bug-test.tsx +0 -69
- package/src/components/Select/Select.refactored.tsx +0 -497
- package/src/providers/OrganisationProvider.test.tsx +0 -164
- package/src/providers/UnifiedAuthProvider.test.tsx +0 -124
- package/src/providers/__tests__/AuthProvider.test.tsx.backup +0 -771
- package/src/providers/__tests__/EventProvider.test.tsx.backup +0 -824
- package/src/providers/__tests__/OrganisationProvider.test.tsx.backup +0 -820
- package/src/providers/__tests__/UnifiedAuthProvider.test.tsx.backup +0 -911
- package/src/providers/__tests__/UnifiedAuthProvider.test.tsx.backup2 +0 -166
- package/src/rbac/cli/__tests__/policy-manager.test.ts +0 -339
- package/src/rbac/cli/policy-manager.ts +0 -443
- package/dist/{DataTable-2QR5TER5.js.map → DataTable-4GAVPIEG.js.map} +0 -0
- package/dist/{UnifiedAuthProvider-K4NRGXL4.js.map → UnifiedAuthProvider-3NKDOSOK.js.map} +0 -0
- package/dist/{eventContext-BBA42P6G.js.map → useInactivityTracker-MRUU55XI.js.map} +0 -0
- package/dist/{validation-PM_iOaTI.d.ts → validation-D8VcbTzC.d.ts} +2 -2
- /package/src/utils/{appNameResolver.test.ts.backup → appNameResolver.test 2.ts} +0 -0
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
* while maintaining all features consistently.
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import React, { useLayoutEffect, useState, useRef, useMemo } from 'react';
|
|
13
|
-
import { type Table, flexRender } from '@tanstack/react-table';
|
|
12
|
+
import React, { useLayoutEffect, useState, useRef, useMemo, useEffect } from 'react';
|
|
13
|
+
import { type Table, flexRender, type Column, type Row } from '@tanstack/react-table';
|
|
14
14
|
import { useVirtualizer } from '@tanstack/react-virtual';
|
|
15
15
|
// Removed Table component imports - using native HTML elements
|
|
16
16
|
import { Button } from '../../Button/Button';
|
|
@@ -18,12 +18,13 @@ import { ChevronUp, ChevronDown, ChevronRight } from 'lucide-react';
|
|
|
18
18
|
import { EmptyState } from './EmptyState';
|
|
19
19
|
import { FilterRow } from './FilterRow';
|
|
20
20
|
import { ActionButtons } from './ActionButtons';
|
|
21
|
-
import {
|
|
21
|
+
import { EditableRow } from './EditableRow';
|
|
22
22
|
import { getTableCellClasses, getTableHeadClasses, getTableRowClasses } from '../styles';
|
|
23
23
|
import { Input } from '../../Input/Input';
|
|
24
24
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../../Select/Select';
|
|
25
25
|
import type { AggregateConfig, HierarchicalConfig, HierarchicalDataRow } from '../types';
|
|
26
26
|
import { calculateIndentation } from '../utils/hierarchicalUtils';
|
|
27
|
+
import { getRowIdSafe } from '../utils/rowUtils';
|
|
27
28
|
|
|
28
29
|
// Performance thresholds
|
|
29
30
|
const VIRTUALIZATION_THRESHOLD = 1000;
|
|
@@ -80,16 +81,6 @@ interface UnifiedTableBodyProps<TData extends Record<string, any>> {
|
|
|
80
81
|
enableFiltering?: boolean;
|
|
81
82
|
/** Whether the filter row should be visible */
|
|
82
83
|
showFilterRow?: boolean;
|
|
83
|
-
/** Whether column reordering is enabled */
|
|
84
|
-
enableColumnReordering?: boolean;
|
|
85
|
-
/** Callback when column order changes */
|
|
86
|
-
onColumnOrderChange?: (columnOrder: string[]) => void;
|
|
87
|
-
/** Callback when a column is dropped on another column */
|
|
88
|
-
onColumnDrop?: (draggedColumnId: string, targetColumnId: string) => void;
|
|
89
|
-
/** Saved column order from persistence */
|
|
90
|
-
savedColumnOrder?: string[];
|
|
91
|
-
/** Whether persistence is enabled */
|
|
92
|
-
enablePersistence?: boolean;
|
|
93
84
|
/** Table ID for persistence */
|
|
94
85
|
tableId?: string;
|
|
95
86
|
/** Data length for virtualization decision */
|
|
@@ -147,19 +138,20 @@ interface UnifiedTableBodyProps<TData extends Record<string, any>> {
|
|
|
147
138
|
}
|
|
148
139
|
|
|
149
140
|
// Helper function to render the appropriate input type based on column configuration
|
|
150
|
-
const renderEditField = (
|
|
151
|
-
column:
|
|
152
|
-
value:
|
|
153
|
-
onChange: (value:
|
|
154
|
-
editingData: Record<string,
|
|
141
|
+
const renderEditField = <TData extends Record<string, any>>(
|
|
142
|
+
column: Column<TData, unknown>,
|
|
143
|
+
value: unknown,
|
|
144
|
+
onChange: (value: unknown) => void,
|
|
145
|
+
editingData: Record<string, unknown> = {},
|
|
155
146
|
placeholder?: string
|
|
156
147
|
) => {
|
|
157
|
-
|
|
148
|
+
// Cast to DataTableColumn to access extended properties
|
|
149
|
+
const columnDef = column.columnDef as any;
|
|
158
150
|
|
|
159
151
|
// Check if column is editable (default: true)
|
|
160
152
|
if (columnDef.editable === false) {
|
|
161
153
|
// Return the original value as text if column is not editable
|
|
162
|
-
return <span className="text-sm text-gray-600">{value || ''}</span>;
|
|
154
|
+
return <span className="text-sm text-gray-600">{String(value || '')}</span>;
|
|
163
155
|
}
|
|
164
156
|
|
|
165
157
|
// Check for custom field type
|
|
@@ -170,7 +162,7 @@ const renderEditField = (
|
|
|
170
162
|
|
|
171
163
|
return (
|
|
172
164
|
<Select
|
|
173
|
-
value={currentValue}
|
|
165
|
+
value={String(currentValue)}
|
|
174
166
|
onValueChange={(newValue) => onChange({ [accessorKey]: newValue })}
|
|
175
167
|
>
|
|
176
168
|
<SelectTrigger className="h-8">
|
|
@@ -178,7 +170,7 @@ const renderEditField = (
|
|
|
178
170
|
</SelectTrigger>
|
|
179
171
|
<SelectContent>
|
|
180
172
|
{columnDef.fieldOptions.map((option: any) => (
|
|
181
|
-
<SelectItem key={option.value} value={option.value}>
|
|
173
|
+
<SelectItem key={option.value} value={String(option.value)}>
|
|
182
174
|
{option.label}
|
|
183
175
|
</SelectItem>
|
|
184
176
|
))}
|
|
@@ -192,7 +184,7 @@ const renderEditField = (
|
|
|
192
184
|
return (
|
|
193
185
|
<Input
|
|
194
186
|
type="number"
|
|
195
|
-
value={value || ''}
|
|
187
|
+
value={String(value || '')}
|
|
196
188
|
onChange={(e) => onChange(e.target.value)}
|
|
197
189
|
placeholder={placeholder || `Enter ${columnDef.header || column.id}...`}
|
|
198
190
|
className="h-8"
|
|
@@ -205,7 +197,7 @@ const renderEditField = (
|
|
|
205
197
|
return (
|
|
206
198
|
<Input
|
|
207
199
|
type="date"
|
|
208
|
-
value={value || ''}
|
|
200
|
+
value={String(value || '')}
|
|
209
201
|
onChange={(e) => onChange(e.target.value)}
|
|
210
202
|
className="h-8"
|
|
211
203
|
/>
|
|
@@ -216,7 +208,7 @@ const renderEditField = (
|
|
|
216
208
|
return (
|
|
217
209
|
<Input
|
|
218
210
|
type="text"
|
|
219
|
-
value={value || ''}
|
|
211
|
+
value={String(value || '')}
|
|
220
212
|
onChange={(e) => onChange(e.target.value)}
|
|
221
213
|
placeholder={placeholder || `Enter ${columnDef.header || column.id}...`}
|
|
222
214
|
className="h-8"
|
|
@@ -224,23 +216,8 @@ const renderEditField = (
|
|
|
224
216
|
);
|
|
225
217
|
};
|
|
226
218
|
|
|
227
|
-
// Row component
|
|
228
|
-
|
|
229
|
-
row,
|
|
230
|
-
style,
|
|
231
|
-
isEditing,
|
|
232
|
-
editingData,
|
|
233
|
-
onEditingDataChange,
|
|
234
|
-
onSaveEditing,
|
|
235
|
-
onCancelEditing,
|
|
236
|
-
getRowId,
|
|
237
|
-
grouping,
|
|
238
|
-
editingRowId,
|
|
239
|
-
hierarchical,
|
|
240
|
-
actions,
|
|
241
|
-
rbac,
|
|
242
|
-
permissions
|
|
243
|
-
}: {
|
|
219
|
+
// Row component props interface
|
|
220
|
+
interface RowProps {
|
|
244
221
|
row: any;
|
|
245
222
|
style?: React.CSSProperties;
|
|
246
223
|
isEditing?: boolean;
|
|
@@ -290,8 +267,29 @@ const MemoizedRow = ({
|
|
|
290
267
|
canExport: { can: boolean; isLoading: boolean };
|
|
291
268
|
canImport: { can: boolean; isLoading: boolean };
|
|
292
269
|
};
|
|
293
|
-
}
|
|
294
|
-
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// Row component with proper memoization
|
|
273
|
+
const RowComponent = React.memo(({
|
|
274
|
+
row,
|
|
275
|
+
style,
|
|
276
|
+
isEditing,
|
|
277
|
+
editingData,
|
|
278
|
+
onEditingDataChange,
|
|
279
|
+
onSaveEditing,
|
|
280
|
+
onCancelEditing,
|
|
281
|
+
getRowId,
|
|
282
|
+
grouping,
|
|
283
|
+
editingRowId,
|
|
284
|
+
hierarchical,
|
|
285
|
+
actions,
|
|
286
|
+
rbac,
|
|
287
|
+
permissions
|
|
288
|
+
}: RowProps) => {
|
|
289
|
+
const rowRef = useRef<HTMLTableRowElement>(null);
|
|
290
|
+
const firstInputRef = useRef<HTMLInputElement>(null);
|
|
291
|
+
|
|
292
|
+
const rowId = getRowIdSafe(row.original, row.index, getRowId);
|
|
295
293
|
|
|
296
294
|
// Hierarchical row styling - moved to top to avoid hoisting issues
|
|
297
295
|
const hierarchicalRow = row.original as HierarchicalDataRow;
|
|
@@ -299,6 +297,40 @@ const MemoizedRow = ({
|
|
|
299
297
|
const isParent = isHierarchical && hierarchicalRow.isParent;
|
|
300
298
|
const isChild = isHierarchical && !hierarchicalRow.isParent;
|
|
301
299
|
|
|
300
|
+
// Auto-focus first editable field when entering edit mode
|
|
301
|
+
useEffect(() => {
|
|
302
|
+
if (isEditing && firstInputRef.current) {
|
|
303
|
+
firstInputRef.current.focus();
|
|
304
|
+
firstInputRef.current.select();
|
|
305
|
+
}
|
|
306
|
+
}, [isEditing]);
|
|
307
|
+
|
|
308
|
+
// Keyboard navigation (Enter to save, Escape to cancel)
|
|
309
|
+
useEffect(() => {
|
|
310
|
+
if (!isEditing) return;
|
|
311
|
+
|
|
312
|
+
const handleKeyDown = (event: KeyboardEvent) => {
|
|
313
|
+
const target = event.target as HTMLElement;
|
|
314
|
+
if (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA') {
|
|
315
|
+
if (event.key === 'Enter' && !event.shiftKey && target.tagName === 'INPUT') {
|
|
316
|
+
event.preventDefault();
|
|
317
|
+
onSaveEditing?.();
|
|
318
|
+
} else if (event.key === 'Escape') {
|
|
319
|
+
event.preventDefault();
|
|
320
|
+
onCancelEditing?.();
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
const currentRow = rowRef.current;
|
|
326
|
+
if (currentRow) {
|
|
327
|
+
currentRow.addEventListener('keydown', handleKeyDown);
|
|
328
|
+
return () => {
|
|
329
|
+
currentRow.removeEventListener('keydown', handleKeyDown);
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
}, [isEditing, onSaveEditing, onCancelEditing]);
|
|
333
|
+
|
|
302
334
|
// Handle grouped rows
|
|
303
335
|
if (row.getIsGrouped && row.getIsGrouped()) {
|
|
304
336
|
const groupValue = row.getValue(grouping[0]);
|
|
@@ -418,7 +450,24 @@ const MemoizedRow = ({
|
|
|
418
450
|
return null;
|
|
419
451
|
}
|
|
420
452
|
|
|
421
|
-
//
|
|
453
|
+
// If we're in edit mode, use EditableRow for better UX (auto-focus, keyboard shortcuts)
|
|
454
|
+
if (isEditing && editingData && onEditingDataChange && onSaveEditing && onCancelEditing) {
|
|
455
|
+
return (
|
|
456
|
+
<EditableRow
|
|
457
|
+
row={row}
|
|
458
|
+
editingData={editingData}
|
|
459
|
+
onEditingDataChange={onEditingDataChange}
|
|
460
|
+
onSave={onSaveEditing}
|
|
461
|
+
onCancel={onCancelEditing}
|
|
462
|
+
actions={((actions || []) as any[]).filter((a: any) => !a.disabled) as any}
|
|
463
|
+
getRowId={getRowId}
|
|
464
|
+
isParent={isParent}
|
|
465
|
+
hierarchical={!!hierarchical}
|
|
466
|
+
/>
|
|
467
|
+
);
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
// Regular row (not in edit mode)
|
|
422
471
|
const visibleCells = row.getVisibleCells();
|
|
423
472
|
const allCells = row.getAllCells ? row.getAllCells() : [];
|
|
424
473
|
|
|
@@ -436,6 +485,7 @@ const MemoizedRow = ({
|
|
|
436
485
|
|
|
437
486
|
return (
|
|
438
487
|
<tr
|
|
488
|
+
ref={rowRef}
|
|
439
489
|
key={row.id}
|
|
440
490
|
style={{
|
|
441
491
|
...style,
|
|
@@ -444,27 +494,11 @@ const MemoizedRow = ({
|
|
|
444
494
|
className={rowClassName}
|
|
445
495
|
>
|
|
446
496
|
{visibleCells.map((cell: any, cellIndex: number) => {
|
|
447
|
-
// For hierarchical parent rows, add expansion button to the first cell
|
|
448
497
|
const isFirstCell = cellIndex === 0;
|
|
449
498
|
const shouldShowExpansionButton = isHierarchical && isParent && isFirstCell && hierarchical?.state;
|
|
450
499
|
const isExpanded = shouldShowExpansionButton ? hierarchical?.state?.isExpanded(rowId) : false;
|
|
451
500
|
const hasChildren = shouldShowExpansionButton ? hierarchical?.state?.hasChildren(rowId) : false;
|
|
452
501
|
|
|
453
|
-
// Debug logging for expander button conditions (development only)
|
|
454
|
-
if (import.meta.env.MODE === 'development' && isParent && isFirstCell) {
|
|
455
|
-
console.log('🔍 Expander Button Debug:', {
|
|
456
|
-
rowId,
|
|
457
|
-
isHierarchical,
|
|
458
|
-
isParent,
|
|
459
|
-
isFirstCell,
|
|
460
|
-
hasHierarchicalState: !!hierarchical?.state,
|
|
461
|
-
shouldShowExpansionButton,
|
|
462
|
-
hasChildren,
|
|
463
|
-
isExpanded
|
|
464
|
-
});
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
|
|
468
502
|
return (
|
|
469
503
|
<td
|
|
470
504
|
key={cell.id}
|
|
@@ -474,7 +508,6 @@ const MemoizedRow = ({
|
|
|
474
508
|
})}
|
|
475
509
|
>
|
|
476
510
|
<div className="flex items-center gap-2">
|
|
477
|
-
{/* Individual expansion button for hierarchical parent rows */}
|
|
478
511
|
{shouldShowExpansionButton && hasChildren && (
|
|
479
512
|
<Button
|
|
480
513
|
variant="ghost"
|
|
@@ -492,82 +525,19 @@ const MemoizedRow = ({
|
|
|
492
525
|
</Button>
|
|
493
526
|
)}
|
|
494
527
|
|
|
495
|
-
{/* Cell content */}
|
|
496
528
|
<div className={`flex-1 ${cell.column.columnDef.meta?.align === 'right' ? 'text-right' : ''}`}>
|
|
497
|
-
{
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
isChild: isChild,
|
|
510
|
-
isHierarchical: isHierarchical,
|
|
511
|
-
rowId: rowId,
|
|
512
|
-
isExpanded: isExpanded,
|
|
513
|
-
hasChildren: hasChildren,
|
|
514
|
-
getIsEditing: () => true, // Always true in edit mode
|
|
515
|
-
setValue: (value: any) => {
|
|
516
|
-
if (typeof value === 'object' && value !== null) {
|
|
517
|
-
onEditingDataChange?.({ ...editingData, ...value });
|
|
518
|
-
} else {
|
|
519
|
-
onEditingDataChange?.({ ...editingData, [cell.column.id]: value });
|
|
520
|
-
}
|
|
521
|
-
}
|
|
522
|
-
})
|
|
523
|
-
) : (
|
|
524
|
-
renderEditField(cell.column, editingData?.[cell.column.id], (value) => {
|
|
525
|
-
if (typeof value === 'object' && value !== null) {
|
|
526
|
-
onEditingDataChange?.({ ...editingData, ...value });
|
|
527
|
-
} else {
|
|
528
|
-
onEditingDataChange?.({ ...editingData, [cell.column.id]: value });
|
|
529
|
-
}
|
|
530
|
-
}, editingData)
|
|
531
|
-
);
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
// Render normal cell (not in edit mode, or column not editable, or is actions column)
|
|
535
|
-
if (cell.column.id === 'actions') {
|
|
536
|
-
return isEditing ? (
|
|
537
|
-
<div className="flex gap-1">
|
|
538
|
-
<button
|
|
539
|
-
onClick={onSaveEditing}
|
|
540
|
-
className="h-8 w-8 p-0 hover:bg-muted/50 flex items-center justify-center"
|
|
541
|
-
title="Save changes"
|
|
542
|
-
>
|
|
543
|
-
<svg className="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
544
|
-
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
|
|
545
|
-
</svg>
|
|
546
|
-
</button>
|
|
547
|
-
<button
|
|
548
|
-
onClick={onCancelEditing}
|
|
549
|
-
className="h-8 w-8 p-0 hover:bg-muted/50 flex items-center justify-center"
|
|
550
|
-
title="Cancel changes"
|
|
551
|
-
>
|
|
552
|
-
<svg className="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
553
|
-
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
|
|
554
|
-
</svg>
|
|
555
|
-
</button>
|
|
556
|
-
</div>
|
|
557
|
-
) : (
|
|
558
|
-
<ActionButtons
|
|
559
|
-
row={row}
|
|
560
|
-
actions={actions}
|
|
561
|
-
isEditing={isEditing}
|
|
562
|
-
isParent={isParent}
|
|
563
|
-
hierarchical={!!hierarchical}
|
|
564
|
-
rbac={rbac}
|
|
565
|
-
permissions={permissions}
|
|
566
|
-
/>
|
|
567
|
-
);
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
return flexRender(cell.column.columnDef.cell, {
|
|
529
|
+
{cell.column.id === 'actions' ? (
|
|
530
|
+
<ActionButtons
|
|
531
|
+
row={row}
|
|
532
|
+
actions={actions}
|
|
533
|
+
isEditing={isEditing}
|
|
534
|
+
isParent={isParent}
|
|
535
|
+
hierarchical={!!hierarchical}
|
|
536
|
+
rbac={rbac}
|
|
537
|
+
permissions={permissions}
|
|
538
|
+
/>
|
|
539
|
+
) : (
|
|
540
|
+
flexRender(cell.column.columnDef.cell, {
|
|
571
541
|
...cell.getContext(),
|
|
572
542
|
hierarchical: hierarchical,
|
|
573
543
|
isParent: isParent,
|
|
@@ -576,8 +546,8 @@ const MemoizedRow = ({
|
|
|
576
546
|
rowId: rowId,
|
|
577
547
|
isExpanded: isExpanded,
|
|
578
548
|
hasChildren: hasChildren,
|
|
579
|
-
})
|
|
580
|
-
|
|
549
|
+
})
|
|
550
|
+
)}
|
|
581
551
|
</div>
|
|
582
552
|
</div>
|
|
583
553
|
</td>
|
|
@@ -585,9 +555,12 @@ const MemoizedRow = ({
|
|
|
585
555
|
})}
|
|
586
556
|
</tr>
|
|
587
557
|
);
|
|
588
|
-
};
|
|
558
|
+
});
|
|
559
|
+
|
|
560
|
+
RowComponent.displayName = 'RowComponent';
|
|
589
561
|
|
|
590
|
-
|
|
562
|
+
// Use the already memoized RowComponent
|
|
563
|
+
const MemoizedRow = RowComponent;
|
|
591
564
|
|
|
592
565
|
/**
|
|
593
566
|
* Unified table body component with intelligent virtualization
|
|
@@ -612,12 +585,6 @@ export function UnifiedTableBody<TData extends Record<string, any>>({
|
|
|
612
585
|
onClearFilters,
|
|
613
586
|
enableFiltering = false,
|
|
614
587
|
showFilterRow = false,
|
|
615
|
-
enableColumnReordering = false,
|
|
616
|
-
onColumnOrderChange,
|
|
617
|
-
onColumnDrop,
|
|
618
|
-
savedColumnOrder,
|
|
619
|
-
enablePersistence = false,
|
|
620
|
-
tableId,
|
|
621
588
|
dataLength,
|
|
622
589
|
virtualHeight = 600,
|
|
623
590
|
forceVirtualization = false,
|
|
@@ -639,16 +606,16 @@ export function UnifiedTableBody<TData extends Record<string, any>>({
|
|
|
639
606
|
const rows = table.getRowModel().rows;
|
|
640
607
|
const headerGroups = table.getHeaderGroups();
|
|
641
608
|
|
|
642
|
-
// Virtual scrolling setup
|
|
609
|
+
// Virtual scrolling setup - only create virtualizer when needed
|
|
643
610
|
const virtualizer = useVirtualizer({
|
|
644
|
-
count: rows.length,
|
|
611
|
+
count: shouldVirtualize ? rows.length : 0,
|
|
645
612
|
getScrollElement: () => parentRef.current,
|
|
646
613
|
estimateSize: () => 40,
|
|
647
614
|
overscan: 5,
|
|
648
615
|
});
|
|
649
616
|
|
|
650
|
-
const virtualRows = virtualizer.getVirtualItems();
|
|
651
|
-
const totalSize = virtualizer.getTotalSize();
|
|
617
|
+
const virtualRows = shouldVirtualize ? virtualizer.getVirtualItems() : [];
|
|
618
|
+
const totalSize = shouldVirtualize ? virtualizer.getTotalSize() : 0;
|
|
652
619
|
|
|
653
620
|
|
|
654
621
|
// Render table content
|
|
@@ -680,7 +647,7 @@ export function UnifiedTableBody<TData extends Record<string, any>>({
|
|
|
680
647
|
const row = rows[virtualRow.index];
|
|
681
648
|
if (!row) return null;
|
|
682
649
|
|
|
683
|
-
const rowId =
|
|
650
|
+
const rowId = getRowIdSafe(row.original, row.index, getRowId);
|
|
684
651
|
const isEditing = editingRowId === rowId;
|
|
685
652
|
|
|
686
653
|
return (
|
|
@@ -713,7 +680,7 @@ export function UnifiedTableBody<TData extends Record<string, any>>({
|
|
|
713
680
|
} else {
|
|
714
681
|
// Standard rendering
|
|
715
682
|
return rows.map((row) => {
|
|
716
|
-
const rowId =
|
|
683
|
+
const rowId = getRowIdSafe(row.original, row.index, getRowId);
|
|
717
684
|
const isEditing = editingRowId === rowId;
|
|
718
685
|
|
|
719
686
|
return (
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# DataTable Subcomponent Testing Strategy
|
|
2
|
+
|
|
3
|
+
## Summary
|
|
4
|
+
|
|
5
|
+
The DataTable subcomponents (FilterRow, EditableRow, ColumnFilter, GroupHeader, ViewRowModal, etc.) are **intentionally not tested in isolation** because:
|
|
6
|
+
|
|
7
|
+
1. They are tightly integrated with TanStack React Table
|
|
8
|
+
2. They are extensively tested through DataTable integration tests
|
|
9
|
+
3. Isolated unit tests would require extensive mocking that tests implementation, not behavior
|
|
10
|
+
|
|
11
|
+
## Coverage via Integration Tests
|
|
12
|
+
|
|
13
|
+
The following DataTable integration tests provide comprehensive coverage:
|
|
14
|
+
|
|
15
|
+
### Workflow Validation (23 tests)
|
|
16
|
+
- ✅ Basic rendering workflows
|
|
17
|
+
- ✅ Editing workflow validation
|
|
18
|
+
- ✅ Deletion workflow validation
|
|
19
|
+
- ✅ Combined features validation
|
|
20
|
+
- ✅ Search workflow validation
|
|
21
|
+
- ✅ Sorting workflow validation
|
|
22
|
+
- ✅ Data integrity validation
|
|
23
|
+
- ✅ Accessibility validation
|
|
24
|
+
|
|
25
|
+
### Regression Fixes (13 tests)
|
|
26
|
+
- ✅ Save/Cancel action handling
|
|
27
|
+
- ✅ Action button icons and behavior
|
|
28
|
+
- ✅ Handler requirement enforcement
|
|
29
|
+
- ✅ Data integrity prevention
|
|
30
|
+
|
|
31
|
+
## Subcomponent Coverage Mapping
|
|
32
|
+
|
|
33
|
+
| Subcomponent | Coverage | Testing Method |
|
|
34
|
+
|-------------|----------|---------------|
|
|
35
|
+
| **ColumnFilter** | ✅ | Integration tests validate filter input behavior |
|
|
36
|
+
| **FilterRow** | ✅ | Integration tests validate filtering across columns |
|
|
37
|
+
| **EditableRow** | ✅ | Integration tests validate editing workflows |
|
|
38
|
+
| **GroupHeader** | ✅ | Integration tests validate grouping functionality |
|
|
39
|
+
| **ViewRowModal** | ✅ | Integration tests validate modal display |
|
|
40
|
+
| **DraggableColumnHeader** | ✅ | Integration tests validate column reordering |
|
|
41
|
+
| **ActionButtons** | ✅ | Integration tests validate action buttons |
|
|
42
|
+
|
|
43
|
+
## Why This Approach Works
|
|
44
|
+
|
|
45
|
+
Following TEST_GUIDE_CURSOR.md principles:
|
|
46
|
+
|
|
47
|
+
1. **Test Observable Behavior** - Integration tests verify actual user interactions
|
|
48
|
+
2. **Avoid Implementation Testing** - Don't mock TanStack table internals
|
|
49
|
+
3. **Focus on User Value** - Users use DataTable, not individual subcomponents
|
|
50
|
+
4. **Prevent Brittle Tests** - Integration tests are more maintainable
|
|
51
|
+
|
|
52
|
+
## Conclusion
|
|
53
|
+
|
|
54
|
+
DataTable subcomponents achieve **effective coverage** through integration tests that validate the complete user experience. No additional isolated unit tests are recommended.
|
|
55
|
+
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export { ActionButtons } from './ActionButtons';
|
|
2
2
|
export { BulkOperationsDropdown } from './BulkOperationsDropdown';
|
|
3
3
|
export { ColumnVisibilityDropdown } from './ColumnVisibilityDropdown';
|
|
4
|
-
// DataTableBody functionality is now consolidated into UnifiedTableBody
|
|
5
4
|
export { UnifiedTableBody } from './UnifiedTableBody';
|
|
5
|
+
export { EditableRow } from './EditableRow';
|
|
6
6
|
export { DataTableToolbar } from './DataTableToolbar';
|
|
7
7
|
export { DataTableModals } from './DataTableModals';
|
|
8
8
|
export { ImportModal } from './ImportModal';
|
|
@@ -10,7 +10,6 @@ export type { ImportModalConfig } from './ImportModal';
|
|
|
10
10
|
export { GroupHeader } from './GroupHeader';
|
|
11
11
|
export { GroupingDropdown } from './GroupingDropdown';
|
|
12
12
|
export { DataTableErrorBoundary } from './DataTableErrorBoundary';
|
|
13
|
-
export { EditableRow } from './EditableRow';
|
|
14
13
|
export { PaginationControls } from './PaginationControls';
|
|
15
14
|
export { LoadingState } from './LoadingState';
|
|
16
15
|
export { EmptyState } from './EmptyState';
|