@jmruthers/pace-core 0.5.76 → 0.5.78
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/CHANGELOG.md +8 -0
- package/dist/{RBACService-C4udt_Zp.d.ts → AuthService-Df3IozMG.d.ts} +10 -118
- package/dist/{DataTable-ntgmhO2W.d.ts → DataTable-BE0OXZKQ.d.ts} +9 -2
- package/dist/{DataTable-4GAVPIEG.js → DataTable-ETGVF4Y5.js} +50 -13
- package/dist/{PublicLoadingSpinner-BiNER8F5.d.ts → PublicLoadingSpinner-CnUaz0vG.d.ts} +5 -2
- package/dist/{UnifiedAuthProvider-Bj6YCf7c.d.ts → UnifiedAuthProvider-B391Aqum.d.ts} +42 -45
- package/dist/{UnifiedAuthProvider-3NKDOSOK.js → UnifiedAuthProvider-P5SOJAQ6.js} +4 -5
- package/dist/{api-DDMUKIUD.js → api-KG4A2X7P.js} +9 -3
- package/dist/{audit-6TOCAMKO.js → audit-65VNHEV2.js} +2 -2
- package/dist/{chunk-K34IM5CT.js → chunk-2OGV6IRV.js} +196 -626
- package/dist/chunk-2OGV6IRV.js.map +1 -0
- package/dist/{chunk-NTNILOBC.js → chunk-5BO3MI5Y.js} +4 -4
- package/dist/{chunk-XLZ7U46Z.js → chunk-CVMVPYAL.js} +9 -60
- package/dist/chunk-CVMVPYAL.js.map +1 -0
- package/dist/{chunk-URUTVZ7N.js → chunk-FL4ZCQLD.js} +2 -2
- package/dist/{chunk-LW7MMEAQ.js → chunk-FT2M4R4F.js} +2 -2
- package/dist/{chunk-5BSLGBYI.js → chunk-JCQZ6LA7.js} +2 -8
- package/dist/{chunk-5BSLGBYI.js.map → chunk-JCQZ6LA7.js.map} +1 -1
- package/dist/{chunk-KHJS6VIA.js → chunk-LRQ6RBJC.js} +157 -112
- package/dist/chunk-LRQ6RBJC.js.map +1 -0
- package/dist/{chunk-WN6XJWOS.js → chunk-MNJXXD6C.js} +274 -743
- package/dist/chunk-MNJXXD6C.js.map +1 -0
- package/dist/{chunk-KK73ZB4E.js → chunk-PTR5PMPE.js} +153 -132
- package/dist/chunk-PTR5PMPE.js.map +1 -0
- package/dist/{chunk-B2WTCLCV.js → chunk-Q7APDV6H.js} +18 -8
- package/dist/chunk-Q7APDV6H.js.map +1 -0
- package/dist/{chunk-A4FUBC7B.js → chunk-QGVSOUJ2.js} +2 -4
- package/dist/{chunk-A4FUBC7B.js.map → chunk-QGVSOUJ2.js.map} +1 -1
- package/dist/{chunk-FGMFQSHX.js → chunk-S63MFSY6.js} +500 -551
- package/dist/chunk-S63MFSY6.js.map +1 -0
- package/dist/{chunk-AFGTSUAD.js → chunk-VSOKOFRF.js} +4 -4
- package/dist/chunk-WUXCWRL6.js +20 -0
- package/dist/chunk-WUXCWRL6.js.map +1 -0
- package/dist/{chunk-Y6TXWPJO.js → chunk-YVVGHRGI.js} +105 -31
- package/dist/chunk-YVVGHRGI.js.map +1 -0
- package/dist/{chunk-M5IWZRBT.js → chunk-ZMNXIJP4.js} +2187 -981
- package/dist/chunk-ZMNXIJP4.js.map +1 -0
- package/dist/components.d.ts +6 -6
- package/dist/components.js +14 -18
- package/dist/components.js.map +1 -1
- package/dist/{database-C3Szpi5J.d.ts → database-BXAfr2Y_.d.ts} +18 -0
- package/dist/hooks.d.ts +5 -5
- package/dist/hooks.js +8 -9
- package/dist/hooks.js.map +1 -1
- package/dist/index.d.ts +19 -27
- package/dist/index.js +21 -29
- package/dist/index.js.map +1 -1
- package/dist/{organisation-BtshODVF.d.ts → organisation-D6qRDtbF.d.ts} +1 -1
- package/dist/providers.d.ts +7 -21
- package/dist/providers.js +3 -10
- package/dist/rbac/index.d.ts +71 -221
- package/dist/rbac/index.js +15 -16
- package/dist/{types-CGX9Vyf5.d.ts → types-BDg1mAGG.d.ts} +36 -6
- package/dist/types.d.ts +3 -3
- package/dist/types.js +61 -18
- package/dist/types.js.map +1 -1
- package/dist/{unified-CM7T0aTK.d.ts → unified-DQ4VcT7H.d.ts} +1 -1
- package/dist/{usePublicRouteParams-B-CumWRc.d.ts → usePublicRouteParams-BlgwXweB.d.ts} +3 -3
- package/dist/utils.d.ts +2 -2
- package/dist/utils.js +52 -9
- package/dist/utils.js.map +1 -1
- package/docs/CONTENT_AUDIT_REPORT.md +253 -0
- package/docs/DOCUMENTATION_AUDIT.md +172 -0
- package/docs/README.md +142 -147
- package/docs/STYLE_GUIDE.md +37 -0
- package/docs/api/classes/ColumnFactory.md +17 -17
- package/docs/api/classes/ErrorBoundary.md +1 -1
- package/docs/api/classes/InvalidScopeError.md +4 -4
- package/docs/api/classes/MissingUserContextError.md +4 -4
- package/docs/api/classes/OrganisationContextRequiredError.md +4 -4
- package/docs/api/classes/PermissionDeniedError.md +5 -5
- package/docs/api/classes/PublicErrorBoundary.md +1 -1
- package/docs/api/classes/RBACAuditManager.md +8 -8
- package/docs/api/classes/RBACCache.md +35 -5
- package/docs/api/classes/RBACEngine.md +49 -20
- package/docs/api/classes/RBACError.md +4 -4
- package/docs/api/classes/RBACNotInitializedError.md +4 -4
- 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 +4 -4
- 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/DataAccessRecord.md +1 -1
- package/docs/api/interfaces/DataRecord.md +11 -0
- package/docs/api/interfaces/DataTableAction.md +65 -29
- package/docs/api/interfaces/DataTableColumn.md +36 -23
- package/docs/api/interfaces/DataTableProps.md +80 -38
- package/docs/api/interfaces/DataTableToolbarButton.md +7 -7
- package/docs/api/interfaces/EmptyStateConfig.md +5 -5
- package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
- package/docs/api/interfaces/EventLogoProps.md +1 -1
- 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 +1 -1
- package/docs/api/interfaces/LabelProps.md +1 -1
- package/docs/api/interfaces/LoginFormProps.md +1 -1
- package/docs/api/interfaces/NavigationAccessRecord.md +11 -11
- package/docs/api/interfaces/NavigationContextType.md +9 -9
- 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 +7 -7
- 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 +16 -3
- package/docs/api/interfaces/PageAccessRecord.md +1 -1
- package/docs/api/interfaces/PagePermissionContextType.md +1 -1
- package/docs/api/interfaces/PagePermissionGuardProps.md +2 -2
- package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
- package/docs/api/interfaces/PaletteData.md +1 -1
- package/docs/api/interfaces/PermissionEnforcerProps.md +4 -4
- 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/RBACConfig.md +1 -1
- package/docs/api/interfaces/RBACLogger.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 +2 -2
- package/docs/api/interfaces/RouteConfig.md +2 -2
- 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 +94 -521
- package/docs/api/interfaces/UnifiedAuthProviderProps.md +16 -16
- 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 +1 -1
- package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
- 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 +251 -269
- package/docs/api-reference/components.md +193 -0
- package/docs/api-reference/hooks.md +265 -0
- package/docs/api-reference/providers.md +6 -0
- package/docs/api-reference/types.md +6 -0
- package/docs/api-reference/utilities.md +207 -0
- package/docs/architecture/README.md +6 -0
- package/docs/{database-schema-requirements.md → architecture/database-schema-requirements.md} +6 -0
- package/docs/architecture/rbac-security-architecture.md +258 -0
- package/docs/architecture/services.md +9 -1
- package/docs/best-practices/README.md +6 -0
- package/docs/best-practices/accessibility.md +6 -0
- package/docs/{common-patterns.md → best-practices/common-patterns.md} +6 -0
- package/docs/best-practices/deployment.md +6 -0
- package/docs/best-practices/performance.md +475 -2
- package/docs/best-practices/security.md +6 -0
- package/docs/best-practices/testing.md +6 -0
- package/docs/core-concepts/authentication.md +6 -0
- package/docs/core-concepts/events.md +6 -0
- package/docs/core-concepts/organisations.md +6 -0
- package/docs/core-concepts/permissions.md +6 -0
- package/docs/core-concepts/rbac-system.md +8 -0
- package/docs/documentation-index.md +121 -182
- package/docs/{consuming-app-vite-config.md → getting-started/consuming-app-vite-config.md} +6 -0
- package/docs/getting-started/documentation-index.md +40 -0
- package/docs/getting-started/examples/README.md +878 -35
- package/docs/{faq.md → getting-started/faq.md} +7 -1
- package/docs/getting-started/installation-guide.md +6 -0
- package/docs/{quick-reference.md → getting-started/quick-reference.md} +6 -0
- package/docs/implementation-guides/app-layout.md +6 -0
- package/docs/implementation-guides/authentication.md +1021 -0
- package/docs/implementation-guides/component-styling.md +6 -0
- package/docs/implementation-guides/data-tables.md +1264 -2076
- package/docs/implementation-guides/dynamic-colors.md +6 -0
- package/docs/implementation-guides/event-theming-summary.md +6 -0
- package/docs/{file-reference-system.md → implementation-guides/file-reference-system.md} +6 -0
- package/docs/implementation-guides/file-upload-storage.md +6 -0
- package/docs/implementation-guides/forms.md +6 -0
- package/docs/implementation-guides/inactivity-tracking.md +6 -0
- package/docs/implementation-guides/navigation.md +6 -0
- package/docs/implementation-guides/organisation-security.md +6 -0
- package/docs/implementation-guides/permission-enforcement.md +6 -0
- package/docs/implementation-guides/public-pages-advanced.md +6 -0
- package/docs/implementation-guides/public-pages.md +6 -0
- package/docs/migration/MIGRATION_GUIDE.md +827 -351
- package/docs/migration/README.md +7 -1
- package/docs/migration/organisation-context-timing-fix.md +6 -0
- package/docs/migration/rbac-migration.md +44 -1
- package/docs/migration/service-architecture.md +6 -0
- package/docs/migration/v0.4.15-tailwind-scanning.md +6 -0
- package/docs/migration/v0.4.16-css-first-approach.md +6 -0
- package/docs/migration/v0.4.17-source-path-fix.md +6 -0
- package/docs/rbac/README-rbac-rls-integration.md +6 -0
- package/docs/rbac/README.md +6 -0
- package/docs/rbac/advanced-patterns.md +6 -0
- package/docs/rbac/api-reference.md +7 -1
- package/docs/rbac/breaking-changes-v3.md +222 -0
- package/docs/rbac/examples/rbac-rls-integration-example.md +6 -0
- package/docs/rbac/examples.md +6 -0
- package/docs/rbac/getting-started.md +6 -0
- package/docs/rbac/migration-guide.md +260 -0
- package/docs/rbac/quick-start.md +70 -13
- package/docs/rbac/rbac-rls-integration.md +6 -0
- package/docs/rbac/super-admin-guide.md +6 -0
- package/docs/rbac/troubleshooting.md +6 -0
- package/docs/security/README.md +6 -0
- package/docs/security/checklist.md +6 -0
- package/docs/styles/README.md +7 -1
- package/docs/{usage.md → styles/usage.md} +6 -0
- package/docs/testing/README.md +6 -0
- package/docs/{visual-testing.md → testing/visual-testing.md} +6 -0
- package/docs/troubleshooting/README.md +387 -5
- package/docs/troubleshooting/cake-page-permission-guard-issue-summary.md +6 -0
- package/docs/troubleshooting/common-issues.md +6 -0
- package/docs/troubleshooting/database-view-compatibility.md +6 -0
- package/docs/troubleshooting/organisation-context-setup.md +6 -0
- package/docs/troubleshooting/react-hooks-issue-analysis.md +6 -0
- package/docs/troubleshooting/styling-issues.md +6 -0
- package/docs/troubleshooting/tailwind-content-scanning.md +6 -0
- package/package.json +1 -1
- package/src/__tests__/helpers/__tests__/test-providers.test.tsx +2 -1
- package/src/__tests__/helpers/test-providers.tsx +3 -53
- package/src/components/DataTable/DataTable.test.tsx +319 -0
- package/src/components/DataTable/DataTable.tsx +32 -11
- package/src/components/DataTable/__tests__/{DataTable.comprehensive.test.tsx → DataTable.comprehensive.test.tsx.skip} +6 -4
- package/src/components/DataTable/__tests__/{DataTable.test.tsx → DataTable.test.tsx.skip} +6 -4
- package/src/components/DataTable/__tests__/DataTableCore.test.tsx +31 -9
- package/src/components/DataTable/__tests__/a11y.basic.test.tsx +601 -0
- package/src/components/DataTable/__tests__/keyboard.test.tsx +615 -0
- package/src/components/DataTable/__tests__/pagination.modes.test.tsx +639 -0
- package/src/components/DataTable/__tests__/ssr.strict-mode.test.tsx.skip +330 -0
- package/src/components/DataTable/components/AccessDeniedPage.tsx +2 -2
- package/src/components/DataTable/components/ActionButtons.tsx +88 -104
- package/src/components/DataTable/components/DataTableCore.tsx +309 -337
- package/src/components/DataTable/components/DataTableErrorBoundary.tsx +4 -2
- package/src/components/DataTable/components/DataTableModals.tsx +22 -1
- package/src/components/DataTable/components/EditableRow.tsx +69 -84
- package/src/components/DataTable/components/EmptyState.tsx +5 -1
- package/src/components/DataTable/components/ImportModal.tsx +65 -36
- package/src/components/DataTable/components/PaginationControls.tsx +40 -100
- package/src/components/DataTable/components/UnifiedTableBody.tsx +125 -148
- package/src/components/DataTable/context/DataTableContext.tsx +1 -1
- package/src/components/DataTable/core/ColumnFactory.ts +5 -0
- package/src/components/DataTable/examples/HierarchicalActionsExample.tsx +12 -10
- package/src/components/DataTable/examples/HierarchicalExample.tsx +1 -1
- package/src/components/DataTable/examples/InitialPageSizeExample.tsx +1 -0
- package/src/components/DataTable/examples/PerformanceExample.tsx +1 -0
- package/src/components/DataTable/hooks/__tests__/useColumnOrderPersistence.test.ts +1 -5
- package/src/components/DataTable/hooks/__tests__/useColumnVisibilityPersistence.test.ts +167 -0
- package/src/components/DataTable/hooks/index.ts +7 -0
- package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +32 -15
- package/src/components/DataTable/hooks/useColumnVisibilityPersistence.ts +102 -0
- package/src/components/DataTable/hooks/useDataTableConfiguration.ts +89 -0
- package/src/components/DataTable/hooks/useDataTableDataPipeline.ts +117 -0
- package/src/components/DataTable/hooks/useDataTablePermissions.ts +71 -27
- package/src/components/DataTable/hooks/useDataTableState.ts +39 -11
- package/src/components/DataTable/hooks/useEffectiveColumnOrder.ts +33 -0
- package/src/components/DataTable/hooks/useHierarchicalState.ts +15 -1
- package/src/components/DataTable/hooks/useKeyboardNavigation.ts +447 -0
- package/src/components/DataTable/hooks/useServerSideDataEffect.ts +94 -0
- package/src/components/DataTable/hooks/useTableColumns.ts +10 -7
- package/src/components/DataTable/hooks/useTableHandlers.ts +174 -0
- package/src/components/DataTable/index.ts +12 -3
- package/src/components/DataTable/types.ts +129 -9
- package/src/components/DataTable/utils/__tests__/exportUtils.test.ts +159 -22
- package/src/components/DataTable/utils/__tests__/flexibleImport.test.ts +111 -0
- package/src/components/DataTable/utils/__tests__/rowUtils.test.ts +15 -29
- package/src/components/DataTable/utils/a11yUtils.ts +244 -0
- package/src/components/DataTable/utils/debugTools.ts +609 -0
- package/src/components/DataTable/utils/exportUtils.ts +114 -16
- package/src/components/DataTable/utils/flexibleImport.ts +202 -32
- package/src/components/DataTable/utils/hierarchicalUtils.ts +1 -1
- package/src/components/DataTable/utils/index.ts +2 -0
- package/src/components/DataTable/utils/paginationUtils.ts +350 -0
- package/src/components/DataTable/utils/rowUtils.ts +6 -5
- package/src/components/NavigationMenu/NavigationMenu.test.tsx +19 -24
- package/src/components/NavigationMenu/NavigationMenu.tsx +19 -8
- package/src/components/PaceAppLayout/__tests__/PaceAppLayout.security.test.tsx +1 -23
- package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +56 -6
- package/src/components/PaceLoginPage/PaceLoginPage.tsx +137 -13
- package/src/components/PublicLayout/__tests__/PublicPageHeader.test.tsx +1 -1
- package/src/components/Select/Select.tsx +1 -0
- package/src/components/examples/PermissionExample.tsx +173 -0
- package/src/examples/CorrectPublicPageImplementation.tsx +301 -0
- package/src/examples/PublicEventPage.tsx +274 -0
- package/src/examples/PublicPageApp.tsx +308 -0
- package/src/examples/PublicPageUsageExample.tsx +216 -0
- package/src/hooks/__tests__/useOrganisationPermissions.unit.test.tsx +12 -1
- package/src/hooks/__tests__/useOrganisationSecurity.unit.test.tsx +129 -17
- package/src/hooks/__tests__/useRBAC.unit.test.ts +151 -846
- package/src/hooks/useOrganisationPermissions.test.ts +42 -18
- package/src/hooks/useOrganisationPermissions.ts +12 -6
- package/src/hooks/useOrganisationSecurity.test.ts +138 -85
- package/src/hooks/useOrganisationSecurity.ts +41 -10
- package/src/index.ts +0 -1
- package/src/providers/AuthProvider.simplified.tsx +880 -0
- package/src/providers/UnifiedAuthProvider.test.simple.tsx +8 -8
- package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +29 -19
- package/src/providers/index.ts +0 -1
- package/src/providers/services/EventServiceProvider.tsx +19 -15
- package/src/providers/services/InactivityServiceProvider.tsx +19 -15
- package/src/providers/services/OrganisationServiceProvider.tsx +19 -15
- package/src/providers/services/UnifiedAuthProvider.tsx +156 -127
- package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +1 -1
- package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +3 -3
- package/src/rbac/README.md +1 -1
- package/src/rbac/__tests__/adapters.comprehensive.test.tsx +25 -27
- package/src/rbac/__tests__/auth-rbac-security.integration.test.tsx +313 -0
- package/src/rbac/__tests__/engine.comprehensive.test.ts +114 -348
- package/src/rbac/__tests__/rbac-engine-core-logic.test.ts +28 -110
- package/src/rbac/__tests__/rbac-engine-simplified.test.ts +33 -85
- package/src/rbac/__tests__/scenarios.user-role.test.tsx +2 -2
- package/src/rbac/adapters.tsx +26 -69
- package/src/rbac/api.test.ts +90 -27
- package/src/rbac/api.ts +61 -10
- package/src/rbac/audit.test.ts +33 -38
- package/src/rbac/audit.ts +21 -6
- package/src/rbac/cache.ts +33 -1
- package/src/rbac/components/NavigationGuard.tsx +11 -11
- package/src/rbac/components/NavigationProvider.test.tsx +11 -5
- package/src/rbac/components/NavigationProvider.tsx +37 -13
- package/src/rbac/components/PagePermissionGuard.tsx +111 -50
- package/src/rbac/components/PagePermissionProvider.tsx +5 -5
- package/src/rbac/components/PermissionEnforcer.tsx +11 -11
- package/src/rbac/components/RoleBasedRouter.tsx +5 -5
- package/src/rbac/components/SecureDataProvider.tsx +5 -5
- package/src/rbac/components/__tests__/NavigationGuard.test.tsx +8 -8
- package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +14 -14
- package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +12 -12
- package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +6 -6
- package/src/rbac/engine.test.simple.ts +19 -13
- package/src/rbac/engine.test.ts +1 -0
- package/src/rbac/engine.ts +330 -766
- package/src/rbac/errors.ts +156 -0
- package/src/rbac/hooks/usePermissions.ts +32 -10
- package/src/rbac/hooks/useRBAC.test.ts +126 -512
- package/src/rbac/hooks/useRBAC.ts +147 -193
- package/src/rbac/hooks/useResolvedScope.ts +12 -0
- package/src/rbac/index.ts +7 -4
- package/src/rbac/security.ts +109 -18
- package/src/rbac/types.ts +12 -1
- package/src/services/AuthService.ts +2 -15
- package/src/services/EventService.ts +43 -46
- package/src/services/OrganisationService.ts +51 -31
- package/src/services/__tests__/AuthService.test.ts +1 -1
- package/src/services/__tests__/EventService.test.ts +1 -1
- package/src/services/__tests__/OrganisationService.test.ts +1 -1
- package/src/services/base/BaseService.ts +8 -0
- package/src/styles/base.css +208 -0
- package/src/styles/semantic.css +24 -0
- package/src/types/database.generated.ts +7347 -0
- package/src/types/database.ts +20 -0
- package/src/utils/logger.ts +179 -0
- package/src/utils/organisationContext.ts +11 -4
- package/src/utils/storage/__tests__/helpers.unit.test.ts +6 -2
- package/dist/appNameResolver-UURKN7NF.js +0 -22
- package/dist/audit-6TOCAMKO.js.map +0 -1
- package/dist/chunk-B2WTCLCV.js.map +0 -1
- package/dist/chunk-FGMFQSHX.js.map +0 -1
- package/dist/chunk-K34IM5CT.js.map +0 -1
- package/dist/chunk-KHJS6VIA.js.map +0 -1
- package/dist/chunk-KK73ZB4E.js.map +0 -1
- package/dist/chunk-M5IWZRBT.js.map +0 -1
- package/dist/chunk-ULBI5JGB.js +0 -109
- package/dist/chunk-ULBI5JGB.js.map +0 -1
- package/dist/chunk-WN6XJWOS.js.map +0 -1
- package/dist/chunk-XLZ7U46Z.js.map +0 -1
- package/dist/chunk-Y6TXWPJO.js.map +0 -1
- package/docs/DOCUMENTATION_CHECKLIST.md +0 -281
- package/docs/TERMINOLOGY.md +0 -231
- package/docs/api/interfaces/RBACContextType.md +0 -468
- package/docs/api/interfaces/RBACProviderProps.md +0 -107
- package/docs/best-practices/performance-expansion.md +0 -473
- package/docs/breaking-changes.md +0 -179
- package/docs/consuming-app-example.md +0 -290
- package/docs/documentation-templates.md +0 -539
- package/docs/examples/navigation-menu-auth-fix.md +0 -344
- package/docs/getting-started/examples/basic-auth-app.md +0 -520
- package/docs/getting-started/examples/full-featured-app.md +0 -616
- package/docs/getting-started/quick-start.md +0 -376
- package/docs/implementation-guides/datatable-filtering.md +0 -313
- package/docs/implementation-guides/datatable-rbac-usage.md +0 -317
- package/docs/implementation-guides/hierarchical-datatable.md +0 -850
- package/docs/implementation-guides/large-datasets.md +0 -281
- package/docs/implementation-guides/performance.md +0 -403
- package/docs/migration/quick-migration-guide.md +0 -320
- package/docs/migration-guide.md +0 -193
- package/docs/migration-guides/unified-auth-provider-mandatory-timeouts.md +0 -226
- package/docs/performance/README.md +0 -551
- package/docs/style-guide.md +0 -964
- package/docs/troubleshooting/authentication-issues.md +0 -334
- package/docs/troubleshooting/debugging.md +0 -1117
- package/docs/troubleshooting/migration.md +0 -918
- package/src/__tests__/hooks/usePermissions.test.ts +0 -261
- package/src/components/PaceAppLayout/__tests__/PaceAppLayout.rbac.test.tsx +0 -574
- package/src/hooks/__tests__/ServiceHooks.test.tsx +0 -613
- package/src/hooks/services/__tests__/useServiceHooks.test.tsx +0 -137
- package/src/hooks/services/usePermissions.ts +0 -70
- package/src/hooks/services/useRBACService.ts +0 -30
- package/src/hooks/usePermissionCheck.ts +0 -150
- package/src/providers/__tests__/ServiceProviders.test.tsx +0 -477
- package/src/providers/services/RBACServiceProvider.tsx +0 -79
- package/src/rbac/__tests__/integration.authflow.test.tsx +0 -119
- package/src/rbac/__tests__/integration.navigation.test.tsx +0 -69
- package/src/rbac/__tests__/integration.securedata.test.tsx +0 -92
- package/src/rbac/__tests__/integration.smoke.test.tsx +0 -73
- package/src/rbac/providers/RBACProvider.tsx +0 -645
- package/src/rbac/providers/__tests__/RBACProvider.integration.test.tsx +0 -688
- package/src/rbac/providers/__tests__/RBACProvider.test.tsx +0 -1186
- package/src/rbac/providers/index.ts +0 -11
- package/src/services/RBACService.ts +0 -522
- package/src/services/__tests__/RBACService.test.ts +0 -492
- package/src/services/interfaces/IRBACService.ts +0 -62
- package/src/utils/appNameResolver.test 2.ts +0 -494
- /package/dist/{DataTable-4GAVPIEG.js.map → DataTable-ETGVF4Y5.js.map} +0 -0
- /package/dist/{UnifiedAuthProvider-3NKDOSOK.js.map → UnifiedAuthProvider-P5SOJAQ6.js.map} +0 -0
- /package/dist/{api-DDMUKIUD.js.map → api-KG4A2X7P.js.map} +0 -0
- /package/dist/{appNameResolver-UURKN7NF.js.map → audit-65VNHEV2.js.map} +0 -0
- /package/dist/{chunk-NTNILOBC.js.map → chunk-5BO3MI5Y.js.map} +0 -0
- /package/dist/{chunk-URUTVZ7N.js.map → chunk-FL4ZCQLD.js.map} +0 -0
- /package/dist/{chunk-LW7MMEAQ.js.map → chunk-FT2M4R4F.js.map} +0 -0
- /package/dist/{chunk-AFGTSUAD.js.map → chunk-VSOKOFRF.js.map} +0 -0
- /package/docs/{app.css.example → styles/app.css.example} +0 -0
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
2
|
useCan,
|
|
3
3
|
useResolvedScope
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-LRQ6RBJC.js";
|
|
5
5
|
import {
|
|
6
6
|
toast,
|
|
7
7
|
useDataTablePerformance
|
|
8
8
|
} from "./chunk-YCKPEMJA.js";
|
|
9
9
|
import {
|
|
10
10
|
init_UnifiedAuthProvider
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-FL4ZCQLD.js";
|
|
12
12
|
import {
|
|
13
13
|
useUnifiedAuth
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-MNJXXD6C.js";
|
|
15
15
|
import {
|
|
16
16
|
cn
|
|
17
17
|
} from "./chunk-PYUXFQJ3.js";
|
|
@@ -5502,19 +5502,11 @@ var require_lodash = __commonJS({
|
|
|
5502
5502
|
});
|
|
5503
5503
|
|
|
5504
5504
|
// src/components/DataTable/DataTable.tsx
|
|
5505
|
-
import
|
|
5505
|
+
import React18 from "react";
|
|
5506
5506
|
|
|
5507
5507
|
// src/components/DataTable/components/DataTableCore.tsx
|
|
5508
|
-
import
|
|
5509
|
-
import {
|
|
5510
|
-
useReactTable,
|
|
5511
|
-
getCoreRowModel,
|
|
5512
|
-
getFilteredRowModel,
|
|
5513
|
-
getSortedRowModel,
|
|
5514
|
-
getPaginationRowModel,
|
|
5515
|
-
getGroupedRowModel,
|
|
5516
|
-
getExpandedRowModel
|
|
5517
|
-
} from "@tanstack/react-table";
|
|
5508
|
+
import React17, { useMemo as useMemo14, useCallback as useCallback10, useEffect as useEffect12, useRef as useRef7 } from "react";
|
|
5509
|
+
import { useReactTable } from "@tanstack/react-table";
|
|
5518
5510
|
import { Edit, Trash, ChevronUp as ChevronUp2, ChevronDown as ChevronDown3, ChevronsUpDown } from "lucide-react";
|
|
5519
5511
|
|
|
5520
5512
|
// src/components/Button/Button.tsx
|
|
@@ -6226,6 +6218,7 @@ var SelectItem = React5.forwardRef(
|
|
|
6226
6218
|
"data-disabled": disabled ? "true" : void 0,
|
|
6227
6219
|
role: "option",
|
|
6228
6220
|
"aria-selected": isSelected,
|
|
6221
|
+
tabIndex: disabled ? -1 : 0,
|
|
6229
6222
|
children: [
|
|
6230
6223
|
children,
|
|
6231
6224
|
isSelected && /* @__PURE__ */ jsx4(Check, { className: "absolute right-2 h-4 w-4 flex-shrink-0 mt-0.5" })
|
|
@@ -6566,7 +6559,7 @@ function DataTableToolbar({
|
|
|
6566
6559
|
}
|
|
6567
6560
|
|
|
6568
6561
|
// src/components/DataTable/components/UnifiedTableBody.tsx
|
|
6569
|
-
import
|
|
6562
|
+
import React8, { useRef as useRef3, useEffect as useEffect3 } from "react";
|
|
6570
6563
|
import { flexRender as flexRender2 } from "@tanstack/react-table";
|
|
6571
6564
|
import { useVirtualizer } from "@tanstack/react-virtual";
|
|
6572
6565
|
import { ChevronDown as ChevronDown2, ChevronRight } from "lucide-react";
|
|
@@ -6584,29 +6577,37 @@ function EmptyState({
|
|
|
6584
6577
|
}) {
|
|
6585
6578
|
const defaultTitle = isFiltered ? "No results found" : "No data available";
|
|
6586
6579
|
const defaultDescription = isFiltered ? "Try adjusting your search or filter criteria" : "Get started by adding your first entry";
|
|
6587
|
-
return /* @__PURE__ */ jsxs6(
|
|
6588
|
-
|
|
6589
|
-
|
|
6590
|
-
|
|
6591
|
-
|
|
6592
|
-
|
|
6593
|
-
|
|
6594
|
-
|
|
6595
|
-
|
|
6596
|
-
|
|
6597
|
-
|
|
6598
|
-
|
|
6599
|
-
|
|
6600
|
-
|
|
6601
|
-
|
|
6602
|
-
|
|
6603
|
-
|
|
6604
|
-
|
|
6605
|
-
/* @__PURE__ */
|
|
6606
|
-
|
|
6607
|
-
|
|
6608
|
-
|
|
6609
|
-
|
|
6580
|
+
return /* @__PURE__ */ jsxs6(
|
|
6581
|
+
"div",
|
|
6582
|
+
{
|
|
6583
|
+
role: "status",
|
|
6584
|
+
"aria-live": "polite",
|
|
6585
|
+
className: "flex flex-col items-center justify-center p-8 text-center",
|
|
6586
|
+
children: [
|
|
6587
|
+
/* @__PURE__ */ jsx9(
|
|
6588
|
+
Icon,
|
|
6589
|
+
{
|
|
6590
|
+
role: "img",
|
|
6591
|
+
"aria-hidden": "true",
|
|
6592
|
+
className: "h-12 w-12 text-muted-foreground mb-4",
|
|
6593
|
+
"data-testid": Icon === Database ? "lucide-database" : Icon === User ? "lucide-user" : "custom-icon"
|
|
6594
|
+
}
|
|
6595
|
+
),
|
|
6596
|
+
/* @__PURE__ */ jsx9("h3", { className: "text-lg font-semibold mb-2", children: title || defaultTitle }),
|
|
6597
|
+
/* @__PURE__ */ jsx9("p", { className: "text-sm text-muted-foreground mb-4 max-w-sm", children: description || defaultDescription }),
|
|
6598
|
+
isFiltered && onClearFilters || action ? /* @__PURE__ */ jsxs6("div", { className: "flex gap-2", children: [
|
|
6599
|
+
isFiltered && onClearFilters && /* @__PURE__ */ jsxs6(Button, { variant: "outline", onClick: onClearFilters, children: [
|
|
6600
|
+
/* @__PURE__ */ jsx9(Search3, { className: "h-4 w-4 mr-2" }),
|
|
6601
|
+
"Clear filters"
|
|
6602
|
+
] }),
|
|
6603
|
+
action && /* @__PURE__ */ jsxs6(Button, { onClick: action.onClick, children: [
|
|
6604
|
+
/* @__PURE__ */ jsx9(Plus2, { className: "h-4 w-4 mr-2" }),
|
|
6605
|
+
action.label
|
|
6606
|
+
] })
|
|
6607
|
+
] }) : null
|
|
6608
|
+
]
|
|
6609
|
+
}
|
|
6610
|
+
);
|
|
6610
6611
|
}
|
|
6611
6612
|
|
|
6612
6613
|
// src/components/DataTable/components/ColumnFilter.tsx
|
|
@@ -6771,22 +6772,144 @@ function FilterRow({ table, visibleColumns }) {
|
|
|
6771
6772
|
}
|
|
6772
6773
|
|
|
6773
6774
|
// src/components/DataTable/components/ActionButtons.tsx
|
|
6775
|
+
import React7, { useMemo as useMemo2 } from "react";
|
|
6774
6776
|
import { MoreHorizontal } from "lucide-react";
|
|
6777
|
+
|
|
6778
|
+
// src/utils/logger.ts
|
|
6779
|
+
var LogLevel = /* @__PURE__ */ ((LogLevel2) => {
|
|
6780
|
+
LogLevel2[LogLevel2["DEBUG"] = 0] = "DEBUG";
|
|
6781
|
+
LogLevel2[LogLevel2["INFO"] = 1] = "INFO";
|
|
6782
|
+
LogLevel2[LogLevel2["WARN"] = 2] = "WARN";
|
|
6783
|
+
LogLevel2[LogLevel2["ERROR"] = 3] = "ERROR";
|
|
6784
|
+
return LogLevel2;
|
|
6785
|
+
})(LogLevel || {});
|
|
6786
|
+
var Logger = class {
|
|
6787
|
+
/**
|
|
6788
|
+
* Check if we're in development mode
|
|
6789
|
+
*/
|
|
6790
|
+
static get isDevelopment() {
|
|
6791
|
+
return import.meta.env.MODE === "development";
|
|
6792
|
+
}
|
|
6793
|
+
/**
|
|
6794
|
+
* Configure the logger
|
|
6795
|
+
*/
|
|
6796
|
+
static configure(config) {
|
|
6797
|
+
this.config = { ...this.config, ...config };
|
|
6798
|
+
}
|
|
6799
|
+
/**
|
|
6800
|
+
* Format a log message with optional timestamp and component
|
|
6801
|
+
*/
|
|
6802
|
+
static formatMessage(level, component, message) {
|
|
6803
|
+
const parts = [];
|
|
6804
|
+
if (this.config.prefix) {
|
|
6805
|
+
parts.push(`[${this.config.prefix}]`);
|
|
6806
|
+
}
|
|
6807
|
+
if (this.config.includeTimestamp) {
|
|
6808
|
+
parts.push(`[${(/* @__PURE__ */ new Date()).toISOString()}]`);
|
|
6809
|
+
}
|
|
6810
|
+
parts.push(`[${LogLevel[level]}]`);
|
|
6811
|
+
if (this.config.includeComponent && component) {
|
|
6812
|
+
parts.push(`[${component}]`);
|
|
6813
|
+
}
|
|
6814
|
+
parts.push(message);
|
|
6815
|
+
return parts.join(" ");
|
|
6816
|
+
}
|
|
6817
|
+
/**
|
|
6818
|
+
* Check if a log level should be output
|
|
6819
|
+
*/
|
|
6820
|
+
static shouldLog(level) {
|
|
6821
|
+
return this.isDevelopment && level >= this.config.level;
|
|
6822
|
+
}
|
|
6823
|
+
/**
|
|
6824
|
+
* Log debug information (development only)
|
|
6825
|
+
*/
|
|
6826
|
+
static debug(component, message, ...args) {
|
|
6827
|
+
if (this.shouldLog(0 /* DEBUG */)) {
|
|
6828
|
+
try {
|
|
6829
|
+
console.debug(this.formatMessage(0 /* DEBUG */, component, message), ...args);
|
|
6830
|
+
} catch (e) {
|
|
6831
|
+
}
|
|
6832
|
+
}
|
|
6833
|
+
}
|
|
6834
|
+
/**
|
|
6835
|
+
* Log info information (development only)
|
|
6836
|
+
*/
|
|
6837
|
+
static info(component, message, ...args) {
|
|
6838
|
+
if (this.shouldLog(1 /* INFO */)) {
|
|
6839
|
+
try {
|
|
6840
|
+
console.info(this.formatMessage(1 /* INFO */, component, message), ...args);
|
|
6841
|
+
} catch (e) {
|
|
6842
|
+
}
|
|
6843
|
+
}
|
|
6844
|
+
}
|
|
6845
|
+
/**
|
|
6846
|
+
* Log warning information (development only)
|
|
6847
|
+
*/
|
|
6848
|
+
static warn(component, message, ...args) {
|
|
6849
|
+
if (this.shouldLog(2 /* WARN */)) {
|
|
6850
|
+
try {
|
|
6851
|
+
console.warn(this.formatMessage(2 /* WARN */, component, message), ...args);
|
|
6852
|
+
} catch (e) {
|
|
6853
|
+
}
|
|
6854
|
+
}
|
|
6855
|
+
}
|
|
6856
|
+
/**
|
|
6857
|
+
* Log error information (development only)
|
|
6858
|
+
*/
|
|
6859
|
+
static error(component, message, ...args) {
|
|
6860
|
+
if (this.shouldLog(3 /* ERROR */)) {
|
|
6861
|
+
try {
|
|
6862
|
+
console.error(this.formatMessage(3 /* ERROR */, component, message), ...args);
|
|
6863
|
+
} catch (e) {
|
|
6864
|
+
}
|
|
6865
|
+
}
|
|
6866
|
+
}
|
|
6867
|
+
/**
|
|
6868
|
+
* Create a scoped logger for a specific component
|
|
6869
|
+
*/
|
|
6870
|
+
static createScopedLogger(component) {
|
|
6871
|
+
return {
|
|
6872
|
+
debug: (message, ...args) => this.debug(component, message, ...args),
|
|
6873
|
+
info: (message, ...args) => this.info(component, message, ...args),
|
|
6874
|
+
warn: (message, ...args) => this.warn(component, message, ...args),
|
|
6875
|
+
error: (message, ...args) => this.error(component, message, ...args)
|
|
6876
|
+
};
|
|
6877
|
+
}
|
|
6878
|
+
};
|
|
6879
|
+
Logger.config = {
|
|
6880
|
+
level: 0 /* DEBUG */,
|
|
6881
|
+
includeTimestamp: false,
|
|
6882
|
+
includeComponent: true
|
|
6883
|
+
};
|
|
6884
|
+
function createLogger(component) {
|
|
6885
|
+
return Logger.createScopedLogger(component);
|
|
6886
|
+
}
|
|
6887
|
+
|
|
6888
|
+
// src/components/DataTable/components/ActionButtons.tsx
|
|
6775
6889
|
import { Fragment, jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
6776
|
-
|
|
6890
|
+
var evaluateCondition = (condition, row, defaultValue) => {
|
|
6891
|
+
if (typeof condition === "boolean") {
|
|
6892
|
+
return condition;
|
|
6893
|
+
}
|
|
6894
|
+
if (typeof condition === "function") {
|
|
6895
|
+
return condition(row);
|
|
6896
|
+
}
|
|
6897
|
+
return defaultValue;
|
|
6898
|
+
};
|
|
6899
|
+
function ActionButtonsComponent({
|
|
6777
6900
|
row,
|
|
6778
6901
|
actions = [],
|
|
6779
6902
|
isEditing = false,
|
|
6780
6903
|
isParent = false,
|
|
6781
6904
|
hierarchical = false,
|
|
6782
|
-
rbac,
|
|
6783
6905
|
permissions
|
|
6784
6906
|
}) {
|
|
6907
|
+
const logger = createLogger("ActionButtons");
|
|
6908
|
+
const rowData = row.original;
|
|
6785
6909
|
if (actions.length === 0) {
|
|
6786
6910
|
return null;
|
|
6787
6911
|
}
|
|
6788
|
-
const
|
|
6789
|
-
const visibleActions = allActions.filter((action) => {
|
|
6912
|
+
const visibleActions = useMemo2(() => actions.filter((action) => {
|
|
6790
6913
|
if (action.hidden) return false;
|
|
6791
6914
|
if (permissions) {
|
|
6792
6915
|
if (action.label === "Edit" && !permissions.canUpdate.can) return false;
|
|
@@ -6796,51 +6919,54 @@ function ActionButtons({
|
|
|
6796
6919
|
if (action.showForParent && !isParent) return false;
|
|
6797
6920
|
if (action.showForChild && isParent) return false;
|
|
6798
6921
|
}
|
|
6799
|
-
if (
|
|
6800
|
-
return
|
|
6801
|
-
} else if (typeof action.visible === "boolean") {
|
|
6802
|
-
return action.visible;
|
|
6922
|
+
if (!evaluateCondition(action.visible, rowData, true)) {
|
|
6923
|
+
return false;
|
|
6803
6924
|
}
|
|
6804
6925
|
if (isEditing) {
|
|
6805
6926
|
return action.showInEditMode !== false;
|
|
6806
|
-
} else {
|
|
6807
|
-
return action.hideInViewMode !== true && action.showInViewMode !== false;
|
|
6808
6927
|
}
|
|
6809
|
-
|
|
6928
|
+
return action.hideInViewMode !== true && action.showInViewMode !== false;
|
|
6929
|
+
}), [actions, permissions, hierarchical, isParent, rowData, isEditing]);
|
|
6810
6930
|
if (visibleActions.length === 0) {
|
|
6811
6931
|
return null;
|
|
6812
6932
|
}
|
|
6933
|
+
const renderAction = (action, actionIndex) => {
|
|
6934
|
+
let Icon = action.icon;
|
|
6935
|
+
let label = action.label;
|
|
6936
|
+
if (hierarchical) {
|
|
6937
|
+
if (isParent && action.parentIcon) {
|
|
6938
|
+
Icon = action.parentIcon;
|
|
6939
|
+
} else if (!isParent && action.childIcon) {
|
|
6940
|
+
Icon = action.childIcon;
|
|
6941
|
+
}
|
|
6942
|
+
if (isParent && action.parentLabel) {
|
|
6943
|
+
label = action.parentLabel;
|
|
6944
|
+
} else if (!isParent && action.childLabel) {
|
|
6945
|
+
label = action.childLabel;
|
|
6946
|
+
}
|
|
6947
|
+
}
|
|
6948
|
+
return { Icon, label };
|
|
6949
|
+
};
|
|
6813
6950
|
if (visibleActions.length <= 6) {
|
|
6814
6951
|
return /* @__PURE__ */ jsx12(Fragment, { children: visibleActions.map((action, actionIndex) => {
|
|
6815
|
-
|
|
6816
|
-
|
|
6817
|
-
if (hierarchical) {
|
|
6818
|
-
if (isParent && action.parentIcon) {
|
|
6819
|
-
Icon = action.parentIcon;
|
|
6820
|
-
} else if (!isParent && action.childIcon) {
|
|
6821
|
-
Icon = action.childIcon;
|
|
6822
|
-
}
|
|
6823
|
-
if (isParent && action.parentLabel) {
|
|
6824
|
-
label = action.parentLabel;
|
|
6825
|
-
} else if (!isParent && action.childLabel) {
|
|
6826
|
-
label = action.childLabel;
|
|
6827
|
-
}
|
|
6828
|
-
}
|
|
6829
|
-
const isDisabled = typeof action.disabled === "function" ? action.disabled(row) : action.disabled;
|
|
6952
|
+
const { Icon, label } = renderAction(action, actionIndex);
|
|
6953
|
+
const isDisabled = evaluateCondition(action.disabled, rowData, false);
|
|
6830
6954
|
return /* @__PURE__ */ jsx12(
|
|
6831
6955
|
Button,
|
|
6832
6956
|
{
|
|
6833
6957
|
variant: action.variant === "destructive" ? "destructive" : "ghost",
|
|
6834
6958
|
size: "sm",
|
|
6835
6959
|
onClick: () => {
|
|
6836
|
-
if (import.meta.env.MODE === "development") {
|
|
6837
|
-
|
|
6960
|
+
if (import.meta.env.MODE === "development" && !isDisabled) {
|
|
6961
|
+
logger.debug("Action clicked:", {
|
|
6838
6962
|
actionLabel: action.label,
|
|
6839
|
-
rowOriginal:
|
|
6963
|
+
rowOriginal: rowData,
|
|
6840
6964
|
actionOnClick: typeof action.onClick
|
|
6841
6965
|
});
|
|
6842
6966
|
}
|
|
6843
|
-
|
|
6967
|
+
if (!isDisabled) {
|
|
6968
|
+
action.onClick(rowData);
|
|
6969
|
+
}
|
|
6844
6970
|
},
|
|
6845
6971
|
disabled: isDisabled,
|
|
6846
6972
|
"aria-disabled": isDisabled,
|
|
@@ -6859,38 +6985,29 @@ function ActionButtons({
|
|
|
6859
6985
|
/* @__PURE__ */ jsx12(MoreHorizontal, { className: "h-4 w-4" })
|
|
6860
6986
|
] }) }),
|
|
6861
6987
|
/* @__PURE__ */ jsx12(SelectContent, { className: "!bg-main-50 border border-sec-200 shadow-lg z-[9999]", style: { backgroundColor: "white" }, children: visibleActions.map((action, actionIndex) => {
|
|
6862
|
-
|
|
6863
|
-
|
|
6864
|
-
if (hierarchical) {
|
|
6865
|
-
if (isParent && action.parentIcon) {
|
|
6866
|
-
Icon = action.parentIcon;
|
|
6867
|
-
} else if (!isParent && action.childIcon) {
|
|
6868
|
-
Icon = action.childIcon;
|
|
6869
|
-
}
|
|
6870
|
-
if (isParent && action.parentLabel) {
|
|
6871
|
-
label = action.parentLabel;
|
|
6872
|
-
} else if (!isParent && action.childLabel) {
|
|
6873
|
-
label = action.childLabel;
|
|
6874
|
-
}
|
|
6875
|
-
}
|
|
6988
|
+
const { Icon, label } = renderAction(action, actionIndex);
|
|
6989
|
+
const isDisabled = evaluateCondition(action.disabled, rowData, false);
|
|
6876
6990
|
return /* @__PURE__ */ jsxs8(
|
|
6877
6991
|
SelectItem,
|
|
6878
6992
|
{
|
|
6879
6993
|
value: `action-${actionIndex}`,
|
|
6880
6994
|
onClick: () => {
|
|
6881
|
-
if (import.meta.env.MODE === "development") {
|
|
6882
|
-
|
|
6995
|
+
if (import.meta.env.MODE === "development" && !isDisabled) {
|
|
6996
|
+
logger.debug("Action clicked from dropdown:", {
|
|
6883
6997
|
actionLabel: action.label,
|
|
6884
|
-
rowOriginal:
|
|
6885
|
-
actionOnClick: typeof action.onClick
|
|
6998
|
+
rowOriginal: rowData
|
|
6886
6999
|
});
|
|
6887
7000
|
}
|
|
6888
|
-
|
|
7001
|
+
if (!isDisabled) {
|
|
7002
|
+
action.onClick(rowData);
|
|
7003
|
+
}
|
|
6889
7004
|
},
|
|
6890
|
-
|
|
7005
|
+
"data-testid": action.testId,
|
|
7006
|
+
className: "flex items-center gap-2",
|
|
7007
|
+
"aria-disabled": isDisabled,
|
|
6891
7008
|
children: [
|
|
6892
|
-
Icon && /* @__PURE__ */ jsx12(Icon, { className: "
|
|
6893
|
-
label
|
|
7009
|
+
Icon && /* @__PURE__ */ jsx12(Icon, { className: "h-4 w-4" }),
|
|
7010
|
+
/* @__PURE__ */ jsx12("span", { children: label })
|
|
6894
7011
|
]
|
|
6895
7012
|
},
|
|
6896
7013
|
actionIndex
|
|
@@ -6898,31 +7015,26 @@ function ActionButtons({
|
|
|
6898
7015
|
}) })
|
|
6899
7016
|
] });
|
|
6900
7017
|
}
|
|
7018
|
+
var ActionButtons = React7.memo(ActionButtonsComponent);
|
|
6901
7019
|
|
|
6902
7020
|
// src/components/DataTable/components/EditableRow.tsx
|
|
6903
7021
|
import { flexRender } from "@tanstack/react-table";
|
|
6904
7022
|
import { jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
6905
|
-
var renderEditField = (column, value, onChange, editingData = {}
|
|
7023
|
+
var renderEditField = (column, value, onChange, editingData = {}) => {
|
|
6906
7024
|
const columnDef = column.columnDef;
|
|
6907
7025
|
if (columnDef.editable === false) {
|
|
6908
|
-
return /* @__PURE__ */ jsx13("span", { className: "text-sm text-gray-600", children: value
|
|
7026
|
+
return /* @__PURE__ */ jsx13("span", { className: "text-sm text-gray-600", children: String(value ?? "") });
|
|
6909
7027
|
}
|
|
6910
7028
|
if (columnDef.fieldType === "select" && columnDef.fieldOptions) {
|
|
6911
|
-
const
|
|
6912
|
-
const
|
|
7029
|
+
const accessorKey = columnDef.editAccessorKey || column.id;
|
|
7030
|
+
const currentValue = editingData[accessorKey] ?? value ?? "";
|
|
6913
7031
|
return /* @__PURE__ */ jsxs9(
|
|
6914
7032
|
Select,
|
|
6915
7033
|
{
|
|
6916
|
-
value: String(
|
|
6917
|
-
onValueChange: (newValue) => {
|
|
6918
|
-
if (columnDef.editAccessorKey) {
|
|
6919
|
-
onChange({ [columnDef.editAccessorKey]: Number(newValue) });
|
|
6920
|
-
} else {
|
|
6921
|
-
onChange(newValue);
|
|
6922
|
-
}
|
|
6923
|
-
},
|
|
7034
|
+
value: String(currentValue),
|
|
7035
|
+
onValueChange: (newValue) => onChange({ [accessorKey]: newValue }),
|
|
6924
7036
|
children: [
|
|
6925
|
-
/* @__PURE__ */ jsx13(SelectTrigger, { className: "w-full h-7", children: /* @__PURE__ */ jsx13(SelectValue, { placeholder:
|
|
7037
|
+
/* @__PURE__ */ jsx13(SelectTrigger, { className: "w-full h-7", children: /* @__PURE__ */ jsx13(SelectValue, { placeholder: `Select ${column.id}` }) }),
|
|
6926
7038
|
/* @__PURE__ */ jsx13(SelectContent, { children: columnDef.fieldOptions.map((option) => /* @__PURE__ */ jsx13(SelectItem, { value: String(option.value), children: option.label }, option.value)) })
|
|
6927
7039
|
]
|
|
6928
7040
|
}
|
|
@@ -6933,7 +7045,18 @@ var renderEditField = (column, value, onChange, editingData = {}, placeholder) =
|
|
|
6933
7045
|
Input,
|
|
6934
7046
|
{
|
|
6935
7047
|
type: "date",
|
|
6936
|
-
value: value
|
|
7048
|
+
value: String(value ?? ""),
|
|
7049
|
+
onChange: (e) => onChange(e.target.value),
|
|
7050
|
+
className: "w-full h-7"
|
|
7051
|
+
}
|
|
7052
|
+
);
|
|
7053
|
+
}
|
|
7054
|
+
if (columnDef.fieldType === "number") {
|
|
7055
|
+
return /* @__PURE__ */ jsx13(
|
|
7056
|
+
Input,
|
|
7057
|
+
{
|
|
7058
|
+
type: "number",
|
|
7059
|
+
value: String(value ?? ""),
|
|
6937
7060
|
onChange: (e) => onChange(e.target.value),
|
|
6938
7061
|
className: "w-full h-7"
|
|
6939
7062
|
}
|
|
@@ -6943,10 +7066,10 @@ var renderEditField = (column, value, onChange, editingData = {}, placeholder) =
|
|
|
6943
7066
|
Input,
|
|
6944
7067
|
{
|
|
6945
7068
|
type: "text",
|
|
6946
|
-
value: value
|
|
7069
|
+
value: String(value ?? ""),
|
|
6947
7070
|
onChange: (e) => onChange(e.target.value),
|
|
6948
7071
|
className: "w-full h-7",
|
|
6949
|
-
placeholder:
|
|
7072
|
+
placeholder: `Enter ${column.id}`
|
|
6950
7073
|
}
|
|
6951
7074
|
);
|
|
6952
7075
|
};
|
|
@@ -6962,72 +7085,48 @@ function EditableRow({
|
|
|
6962
7085
|
hierarchical = false
|
|
6963
7086
|
}) {
|
|
6964
7087
|
const rowId = getRowId ? getRowId(row.original, row.index) : String(row.id);
|
|
6965
|
-
|
|
6966
|
-
|
|
6967
|
-
|
|
6968
|
-
|
|
6969
|
-
|
|
6970
|
-
|
|
6971
|
-
|
|
6972
|
-
|
|
6973
|
-
|
|
6974
|
-
|
|
6975
|
-
|
|
6976
|
-
|
|
6977
|
-
|
|
6978
|
-
|
|
6979
|
-
|
|
6980
|
-
|
|
6981
|
-
setValue: (value) => {
|
|
6982
|
-
if (typeof value === "object" && value !== null) {
|
|
6983
|
-
onEditingDataChange({ ...editingData, ...value });
|
|
6984
|
-
} else {
|
|
6985
|
-
onEditingDataChange({ ...editingData, [cell.column.id]: value });
|
|
7088
|
+
return /* @__PURE__ */ jsxs9(
|
|
7089
|
+
"tr",
|
|
7090
|
+
{
|
|
7091
|
+
role: "row",
|
|
7092
|
+
"aria-selected": typeof row.getIsSelected === "function" ? row.getIsSelected() ? "true" : "false" : "false",
|
|
7093
|
+
"aria-rowindex": row.index + 1,
|
|
7094
|
+
children: [
|
|
7095
|
+
row.getVisibleCells().map((cell) => /* @__PURE__ */ jsx13("td", { role: "cell", children: /* @__PURE__ */ jsx13("div", { className: cell.column.columnDef.meta?.align === "right" ? "text-right" : "", children: cell.column.id !== "actions" ? cell.column.columnDef.cell ? flexRender(cell.column.columnDef.cell, {
|
|
7096
|
+
...cell.getContext(),
|
|
7097
|
+
getIsEditing: () => true,
|
|
7098
|
+
setValue: (value) => {
|
|
7099
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value) && !(value instanceof Date)) {
|
|
7100
|
+
onEditingDataChange({ ...editingData, ...value });
|
|
7101
|
+
} else {
|
|
7102
|
+
onEditingDataChange({ ...editingData, [cell.column.id]: value });
|
|
7103
|
+
}
|
|
6986
7104
|
}
|
|
6987
|
-
}
|
|
6988
|
-
|
|
6989
|
-
// Fall back to default edit field rendering when no custom cell renderer
|
|
6990
|
-
renderEditField(cell.column, editingData[cell.column.id], (value) => {
|
|
6991
|
-
if (typeof value === "object" && value !== null) {
|
|
7105
|
+
}) : renderEditField(cell.column, editingData[cell.column.id], (value) => {
|
|
7106
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value) && !(value instanceof Date)) {
|
|
6992
7107
|
onEditingDataChange({ ...editingData, ...value });
|
|
6993
7108
|
} else {
|
|
6994
7109
|
onEditingDataChange({ ...editingData, [cell.column.id]: value });
|
|
6995
7110
|
}
|
|
6996
|
-
}, editingData)
|
|
6997
|
-
|
|
6998
|
-
|
|
6999
|
-
|
|
7000
|
-
|
|
7001
|
-
|
|
7002
|
-
|
|
7003
|
-
|
|
7004
|
-
|
|
7005
|
-
|
|
7006
|
-
|
|
7007
|
-
|
|
7008
|
-
|
|
7009
|
-
|
|
7010
|
-
|
|
7011
|
-
|
|
7012
|
-
|
|
7013
|
-
|
|
7014
|
-
|
|
7015
|
-
}
|
|
7016
|
-
)
|
|
7017
|
-
] }) }) }, cell.id)),
|
|
7018
|
-
actions.length > 0 && /* @__PURE__ */ jsx13("td", { children: /* @__PURE__ */ jsx13(
|
|
7019
|
-
ActionButtons,
|
|
7020
|
-
{
|
|
7021
|
-
row: row.original,
|
|
7022
|
-
rowId,
|
|
7023
|
-
index: row.index,
|
|
7024
|
-
actions: convertedActions,
|
|
7025
|
-
isEditing: true,
|
|
7026
|
-
isParent,
|
|
7027
|
-
hierarchical
|
|
7028
|
-
}
|
|
7029
|
-
) })
|
|
7030
|
-
] });
|
|
7111
|
+
}, editingData) : /* @__PURE__ */ jsxs9("div", { className: "flex gap-1", children: [
|
|
7112
|
+
/* @__PURE__ */ jsx13(Button, { onClick: onSave, size: "sm", variant: "default", children: "Save" }),
|
|
7113
|
+
/* @__PURE__ */ jsx13(Button, { onClick: onCancel, size: "sm", variant: "outline", children: "Cancel" })
|
|
7114
|
+
] }) }) }, cell.id)),
|
|
7115
|
+
actions.length > 0 && /* @__PURE__ */ jsx13("td", { children: /* @__PURE__ */ jsx13(
|
|
7116
|
+
ActionButtons,
|
|
7117
|
+
{
|
|
7118
|
+
row,
|
|
7119
|
+
rowId,
|
|
7120
|
+
index: row.index,
|
|
7121
|
+
actions,
|
|
7122
|
+
isEditing: true,
|
|
7123
|
+
isParent,
|
|
7124
|
+
hierarchical
|
|
7125
|
+
}
|
|
7126
|
+
) })
|
|
7127
|
+
]
|
|
7128
|
+
}
|
|
7129
|
+
);
|
|
7031
7130
|
}
|
|
7032
7131
|
|
|
7033
7132
|
// src/components/DataTable/utils/hierarchicalUtils.ts
|
|
@@ -7214,10 +7313,12 @@ function getRowIdSafe(row, index, getRowId) {
|
|
|
7214
7313
|
return String(customId);
|
|
7215
7314
|
}
|
|
7216
7315
|
}
|
|
7217
|
-
if (row.id !== void 0 && row.id !== null) {
|
|
7316
|
+
if ("id" in row && row.id !== void 0 && row.id !== null) {
|
|
7218
7317
|
return String(row.id);
|
|
7219
7318
|
}
|
|
7220
|
-
|
|
7319
|
+
throw new Error(
|
|
7320
|
+
'[DataTable] Unable to determine a stable row id. Provide a getRowId prop or ensure each record exposes an "id" field.'
|
|
7321
|
+
);
|
|
7221
7322
|
}
|
|
7222
7323
|
function hasValidRowId(row, getRowId) {
|
|
7223
7324
|
try {
|
|
@@ -7234,11 +7335,11 @@ var VIRTUALIZATION_THRESHOLD = 1e3;
|
|
|
7234
7335
|
var renderEditField2 = (column, value, onChange, editingData = {}, placeholder) => {
|
|
7235
7336
|
const columnDef = column.columnDef;
|
|
7236
7337
|
if (columnDef.editable === false) {
|
|
7237
|
-
return /* @__PURE__ */ jsx14("span", { className: "text-sm text-gray-600", children: String(value
|
|
7338
|
+
return /* @__PURE__ */ jsx14("span", { className: "text-sm text-gray-600", children: String(value ?? "") });
|
|
7238
7339
|
}
|
|
7239
7340
|
if (columnDef.fieldType === "select" && columnDef.fieldOptions) {
|
|
7240
7341
|
const accessorKey = columnDef.editAccessorKey || column.id;
|
|
7241
|
-
const currentValue = editingData[accessorKey]
|
|
7342
|
+
const currentValue = editingData[accessorKey] ?? value ?? "";
|
|
7242
7343
|
return /* @__PURE__ */ jsxs10(
|
|
7243
7344
|
Select,
|
|
7244
7345
|
{
|
|
@@ -7256,7 +7357,7 @@ var renderEditField2 = (column, value, onChange, editingData = {}, placeholder)
|
|
|
7256
7357
|
Input,
|
|
7257
7358
|
{
|
|
7258
7359
|
type: "number",
|
|
7259
|
-
value: String(value
|
|
7360
|
+
value: String(value ?? ""),
|
|
7260
7361
|
onChange: (e) => onChange(e.target.value),
|
|
7261
7362
|
placeholder: placeholder || `Enter ${columnDef.header || column.id}...`,
|
|
7262
7363
|
className: "h-8"
|
|
@@ -7268,7 +7369,7 @@ var renderEditField2 = (column, value, onChange, editingData = {}, placeholder)
|
|
|
7268
7369
|
Input,
|
|
7269
7370
|
{
|
|
7270
7371
|
type: "date",
|
|
7271
|
-
value: String(value
|
|
7372
|
+
value: String(value ?? ""),
|
|
7272
7373
|
onChange: (e) => onChange(e.target.value),
|
|
7273
7374
|
className: "h-8"
|
|
7274
7375
|
}
|
|
@@ -7278,14 +7379,14 @@ var renderEditField2 = (column, value, onChange, editingData = {}, placeholder)
|
|
|
7278
7379
|
Input,
|
|
7279
7380
|
{
|
|
7280
7381
|
type: "text",
|
|
7281
|
-
value: String(value
|
|
7382
|
+
value: String(value ?? ""),
|
|
7282
7383
|
onChange: (e) => onChange(e.target.value),
|
|
7283
7384
|
placeholder: placeholder || `Enter ${columnDef.header || column.id}...`,
|
|
7284
7385
|
className: "h-8"
|
|
7285
7386
|
}
|
|
7286
7387
|
);
|
|
7287
7388
|
};
|
|
7288
|
-
var RowComponent =
|
|
7389
|
+
var RowComponent = React8.memo(({
|
|
7289
7390
|
row,
|
|
7290
7391
|
style,
|
|
7291
7392
|
isEditing,
|
|
@@ -7340,7 +7441,7 @@ var RowComponent = React7.memo(({
|
|
|
7340
7441
|
const groupValue = row.getValue(grouping[0]);
|
|
7341
7442
|
const subRowsCount = row.subRows?.length || 0;
|
|
7342
7443
|
const isExpanded = row.getIsExpanded();
|
|
7343
|
-
return /* @__PURE__ */ jsxs10(
|
|
7444
|
+
return /* @__PURE__ */ jsxs10(React8.Fragment, { children: [
|
|
7344
7445
|
/* @__PURE__ */ jsx14("tr", { className: "bg-sec-50 hover:bg-sec-100", style, children: /* @__PURE__ */ jsxs10(
|
|
7345
7446
|
"td",
|
|
7346
7447
|
{
|
|
@@ -7377,9 +7478,9 @@ var RowComponent = React7.memo(({
|
|
|
7377
7478
|
{
|
|
7378
7479
|
className: getTableCellClasses({
|
|
7379
7480
|
isCompact: true,
|
|
7380
|
-
className:
|
|
7481
|
+
className: `px-3 py-2 pl-8 ${cell.column.id === "actions" ? "whitespace-nowrap" : "whitespace-normal break-words"} ${cell.column.columnDef.meta?.align === "right" ? "text-right" : ""}`
|
|
7381
7482
|
}),
|
|
7382
|
-
children:
|
|
7483
|
+
children: isSubRowEditing && cell.column.id !== "actions" ? (
|
|
7383
7484
|
// Check if column has a custom cell renderer - if so, use it in edit mode
|
|
7384
7485
|
cell.column.columnDef.cell ? flexRender2(cell.column.columnDef.cell, {
|
|
7385
7486
|
...cell.getContext(),
|
|
@@ -7429,7 +7530,7 @@ var RowComponent = React7.memo(({
|
|
|
7429
7530
|
rowId: subRowId,
|
|
7430
7531
|
isExpanded: false,
|
|
7431
7532
|
hasChildren: false
|
|
7432
|
-
})
|
|
7533
|
+
})
|
|
7433
7534
|
},
|
|
7434
7535
|
cell.id
|
|
7435
7536
|
)) }, subRow.id);
|
|
@@ -7448,7 +7549,7 @@ var RowComponent = React7.memo(({
|
|
|
7448
7549
|
onEditingDataChange,
|
|
7449
7550
|
onSave: onSaveEditing,
|
|
7450
7551
|
onCancel: onCancelEditing,
|
|
7451
|
-
actions:
|
|
7552
|
+
actions: actions ?? [],
|
|
7452
7553
|
getRowId,
|
|
7453
7554
|
isParent,
|
|
7454
7555
|
hierarchical: !!hierarchical
|
|
@@ -7464,24 +7565,26 @@ var RowComponent = React7.memo(({
|
|
|
7464
7565
|
"tr",
|
|
7465
7566
|
{
|
|
7466
7567
|
ref: rowRef,
|
|
7568
|
+
role: "row",
|
|
7467
7569
|
style: {
|
|
7468
7570
|
...style,
|
|
7469
7571
|
...isChild && indentation > 0 ? { paddingLeft: `${indentation}px` } : {}
|
|
7470
7572
|
},
|
|
7471
7573
|
className: rowClassName,
|
|
7574
|
+
"aria-selected": typeof row.getIsSelected === "function" ? row.getIsSelected() ? "true" : "false" : "false",
|
|
7472
7575
|
children: visibleCells.map((cell, cellIndex) => {
|
|
7473
7576
|
const isFirstCell = cellIndex === 0;
|
|
7474
7577
|
const shouldShowExpansionButton = isHierarchical && isParent && isFirstCell && hierarchical?.state;
|
|
7475
7578
|
const isExpanded = shouldShowExpansionButton ? hierarchical?.state?.isExpanded(rowId) : false;
|
|
7476
7579
|
const hasChildren = shouldShowExpansionButton ? hierarchical?.state?.hasChildren(rowId) : false;
|
|
7477
|
-
return /* @__PURE__ */
|
|
7580
|
+
return /* @__PURE__ */ jsxs10(
|
|
7478
7581
|
"td",
|
|
7479
7582
|
{
|
|
7480
7583
|
className: getTableCellClasses({
|
|
7481
7584
|
isCompact: true,
|
|
7482
|
-
className:
|
|
7585
|
+
className: `px-3 py-2 ${cell.column.id === "actions" ? "whitespace-nowrap" : "whitespace-normal break-words"} ${cell.column.columnDef.meta?.align === "right" ? "text-right" : ""}`
|
|
7483
7586
|
}),
|
|
7484
|
-
children:
|
|
7587
|
+
children: [
|
|
7485
7588
|
shouldShowExpansionButton && hasChildren && /* @__PURE__ */ jsx14(
|
|
7486
7589
|
Button,
|
|
7487
7590
|
{
|
|
@@ -7494,7 +7597,7 @@ var RowComponent = React7.memo(({
|
|
|
7494
7597
|
children: isExpanded ? /* @__PURE__ */ jsx14(ChevronDown2, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx14(ChevronRight, { className: "h-4 w-4" })
|
|
7495
7598
|
}
|
|
7496
7599
|
),
|
|
7497
|
-
|
|
7600
|
+
cell.column.id === "actions" ? /* @__PURE__ */ jsx14(
|
|
7498
7601
|
ActionButtons,
|
|
7499
7602
|
{
|
|
7500
7603
|
row,
|
|
@@ -7514,8 +7617,8 @@ var RowComponent = React7.memo(({
|
|
|
7514
7617
|
rowId,
|
|
7515
7618
|
isExpanded,
|
|
7516
7619
|
hasChildren
|
|
7517
|
-
})
|
|
7518
|
-
]
|
|
7620
|
+
})
|
|
7621
|
+
]
|
|
7519
7622
|
},
|
|
7520
7623
|
cell.id
|
|
7521
7624
|
);
|
|
@@ -7662,7 +7765,7 @@ function UnifiedTableBody({
|
|
|
7662
7765
|
className: "px-3 py-2"
|
|
7663
7766
|
}),
|
|
7664
7767
|
children: renderEditField2(header.column, creationData[header.column.id], (value) => {
|
|
7665
|
-
if (typeof value === "object" && value !== null) {
|
|
7768
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value) && !(value instanceof Date)) {
|
|
7666
7769
|
onCreationDataChange({ ...creationData, ...value });
|
|
7667
7770
|
} else {
|
|
7668
7771
|
onCreationDataChange({ ...creationData, [header.column.id]: value });
|
|
@@ -7713,7 +7816,7 @@ function UnifiedTableBody({
|
|
|
7713
7816
|
}
|
|
7714
7817
|
|
|
7715
7818
|
// src/components/DataTable/components/PaginationControls.tsx
|
|
7716
|
-
import
|
|
7819
|
+
import React9 from "react";
|
|
7717
7820
|
import {
|
|
7718
7821
|
ChevronLeft,
|
|
7719
7822
|
ChevronRight as ChevronRight2,
|
|
@@ -7723,6 +7826,161 @@ import {
|
|
|
7723
7826
|
Database as Database2,
|
|
7724
7827
|
Zap
|
|
7725
7828
|
} from "lucide-react";
|
|
7829
|
+
|
|
7830
|
+
// src/components/DataTable/utils/paginationUtils.ts
|
|
7831
|
+
function getPaginationBinding(config) {
|
|
7832
|
+
const { mode, table, serverData, totalCount, onPageChange, onPageSizeChange } = config;
|
|
7833
|
+
const state = calculatePaginationState(config);
|
|
7834
|
+
const actions = {
|
|
7835
|
+
goToFirstPage: () => {
|
|
7836
|
+
if (mode === "server") {
|
|
7837
|
+
onPageChange?.(0);
|
|
7838
|
+
} else if (table) {
|
|
7839
|
+
table.setPageIndex(0);
|
|
7840
|
+
}
|
|
7841
|
+
},
|
|
7842
|
+
goToPreviousPage: () => {
|
|
7843
|
+
const targetPage = Math.max(0, state.currentPageIndex - 1);
|
|
7844
|
+
if (mode === "server") {
|
|
7845
|
+
onPageChange?.(targetPage);
|
|
7846
|
+
} else if (table) {
|
|
7847
|
+
table.previousPage();
|
|
7848
|
+
}
|
|
7849
|
+
},
|
|
7850
|
+
goToNextPage: () => {
|
|
7851
|
+
const targetPage = Math.min(state.pageCount - 1, state.currentPageIndex + 1);
|
|
7852
|
+
if (mode === "server") {
|
|
7853
|
+
onPageChange?.(targetPage);
|
|
7854
|
+
} else if (table) {
|
|
7855
|
+
table.nextPage();
|
|
7856
|
+
}
|
|
7857
|
+
},
|
|
7858
|
+
goToLastPage: () => {
|
|
7859
|
+
const lastPage = state.pageCount - 1;
|
|
7860
|
+
if (mode === "server") {
|
|
7861
|
+
onPageChange?.(lastPage);
|
|
7862
|
+
} else if (table) {
|
|
7863
|
+
table.setPageIndex(lastPage);
|
|
7864
|
+
}
|
|
7865
|
+
},
|
|
7866
|
+
goToPage: (pageIndex) => {
|
|
7867
|
+
const clampedIndex = Math.max(0, Math.min(state.pageCount - 1, pageIndex));
|
|
7868
|
+
if (mode === "server") {
|
|
7869
|
+
onPageChange?.(clampedIndex);
|
|
7870
|
+
} else if (table) {
|
|
7871
|
+
table.setPageIndex(clampedIndex);
|
|
7872
|
+
}
|
|
7873
|
+
},
|
|
7874
|
+
setPageSize: (pageSize) => {
|
|
7875
|
+
if (mode === "server") {
|
|
7876
|
+
onPageSizeChange?.(pageSize);
|
|
7877
|
+
} else if (table) {
|
|
7878
|
+
table.setPageSize(pageSize);
|
|
7879
|
+
}
|
|
7880
|
+
}
|
|
7881
|
+
};
|
|
7882
|
+
return { state, actions };
|
|
7883
|
+
}
|
|
7884
|
+
function calculatePaginationState(config) {
|
|
7885
|
+
const { mode, table, serverData, totalCount } = config;
|
|
7886
|
+
if (mode === "server" && serverData) {
|
|
7887
|
+
const startRow = serverData.pageIndex * serverData.pageSize + 1;
|
|
7888
|
+
const endRow = Math.min((serverData.pageIndex + 1) * serverData.pageSize, serverData.totalCount);
|
|
7889
|
+
return {
|
|
7890
|
+
currentPageIndex: serverData.pageIndex,
|
|
7891
|
+
currentPageSize: serverData.pageSize,
|
|
7892
|
+
pageCount: serverData.pageCount,
|
|
7893
|
+
totalRows: serverData.totalCount,
|
|
7894
|
+
canPreviousPage: serverData.hasPreviousPage,
|
|
7895
|
+
canNextPage: serverData.hasNextPage,
|
|
7896
|
+
startRow,
|
|
7897
|
+
endRow
|
|
7898
|
+
};
|
|
7899
|
+
}
|
|
7900
|
+
if (table) {
|
|
7901
|
+
const paginationState = table.getState().pagination;
|
|
7902
|
+
const rowCount = totalCount ?? table.getRowCount();
|
|
7903
|
+
const pageCount = Math.ceil(rowCount / paginationState.pageSize);
|
|
7904
|
+
const startRow = paginationState.pageIndex * paginationState.pageSize + 1;
|
|
7905
|
+
const endRow = Math.min((paginationState.pageIndex + 1) * paginationState.pageSize, rowCount);
|
|
7906
|
+
return {
|
|
7907
|
+
currentPageIndex: paginationState.pageIndex,
|
|
7908
|
+
currentPageSize: paginationState.pageSize,
|
|
7909
|
+
pageCount,
|
|
7910
|
+
totalRows: rowCount,
|
|
7911
|
+
canPreviousPage: table.getCanPreviousPage(),
|
|
7912
|
+
canNextPage: table.getCanNextPage(),
|
|
7913
|
+
startRow,
|
|
7914
|
+
endRow
|
|
7915
|
+
};
|
|
7916
|
+
}
|
|
7917
|
+
return {
|
|
7918
|
+
currentPageIndex: 0,
|
|
7919
|
+
currentPageSize: 10,
|
|
7920
|
+
pageCount: 1,
|
|
7921
|
+
totalRows: 0,
|
|
7922
|
+
canPreviousPage: false,
|
|
7923
|
+
canNextPage: false,
|
|
7924
|
+
startRow: 0,
|
|
7925
|
+
endRow: 0
|
|
7926
|
+
};
|
|
7927
|
+
}
|
|
7928
|
+
function validatePaginationConfig(config) {
|
|
7929
|
+
const { mode, table, serverData, onPageChange, onPageSizeChange } = config;
|
|
7930
|
+
const logger = createLogger("PaginationUtils");
|
|
7931
|
+
let isValid = true;
|
|
7932
|
+
if (mode === "server") {
|
|
7933
|
+
if (!serverData) {
|
|
7934
|
+
logger.warn("Server mode requires serverData");
|
|
7935
|
+
isValid = false;
|
|
7936
|
+
}
|
|
7937
|
+
if (!onPageChange) {
|
|
7938
|
+
logger.warn("Server mode requires onPageChange callback");
|
|
7939
|
+
isValid = false;
|
|
7940
|
+
}
|
|
7941
|
+
if (!onPageSizeChange) {
|
|
7942
|
+
logger.warn("Server mode requires onPageSizeChange callback");
|
|
7943
|
+
isValid = false;
|
|
7944
|
+
}
|
|
7945
|
+
}
|
|
7946
|
+
if ((mode === "client" || mode === "hybrid") && !table) {
|
|
7947
|
+
logger.warn(`${mode} mode requires table instance`);
|
|
7948
|
+
isValid = false;
|
|
7949
|
+
}
|
|
7950
|
+
if (mode === "hybrid") {
|
|
7951
|
+
if (!onPageChange) {
|
|
7952
|
+
logger.warn("Hybrid mode requires onPageChange callback for server pagination");
|
|
7953
|
+
isValid = false;
|
|
7954
|
+
}
|
|
7955
|
+
}
|
|
7956
|
+
return isValid;
|
|
7957
|
+
}
|
|
7958
|
+
function getPageSizeOptions(mode, defaultOptions = [10, 20, 30, 40, 50]) {
|
|
7959
|
+
switch (mode) {
|
|
7960
|
+
case "server":
|
|
7961
|
+
return defaultOptions.filter((size) => size <= 250);
|
|
7962
|
+
case "hybrid":
|
|
7963
|
+
return defaultOptions.filter((size) => size >= 50);
|
|
7964
|
+
default:
|
|
7965
|
+
return defaultOptions;
|
|
7966
|
+
}
|
|
7967
|
+
}
|
|
7968
|
+
function calculateOptimalPageSize(dataSize, mode, availableOptions = [10, 20, 30, 40, 50]) {
|
|
7969
|
+
const filteredOptions = getPageSizeOptions(mode, availableOptions);
|
|
7970
|
+
if (mode === "client" && dataSize <= 100) {
|
|
7971
|
+
return Math.max(dataSize, filteredOptions[0]);
|
|
7972
|
+
}
|
|
7973
|
+
if (mode === "server" && dataSize > 1e4) {
|
|
7974
|
+
return Math.min(...filteredOptions);
|
|
7975
|
+
}
|
|
7976
|
+
if (mode === "hybrid") {
|
|
7977
|
+
const sortedOptions = [...filteredOptions].sort((a, b) => a - b);
|
|
7978
|
+
return sortedOptions[0] || 50;
|
|
7979
|
+
}
|
|
7980
|
+
return filteredOptions[0] || 10;
|
|
7981
|
+
}
|
|
7982
|
+
|
|
7983
|
+
// src/components/DataTable/components/PaginationControls.tsx
|
|
7726
7984
|
import { Fragment as Fragment2, jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
7727
7985
|
function PaginationControls({
|
|
7728
7986
|
table,
|
|
@@ -7735,85 +7993,32 @@ function PaginationControls({
|
|
|
7735
7993
|
showPerformanceInfo = false,
|
|
7736
7994
|
totalCount
|
|
7737
7995
|
}) {
|
|
7738
|
-
const
|
|
7739
|
-
|
|
7740
|
-
|
|
7741
|
-
|
|
7742
|
-
|
|
7743
|
-
|
|
7744
|
-
|
|
7745
|
-
|
|
7746
|
-
canNextPage: serverData.hasNextPage
|
|
7747
|
-
};
|
|
7748
|
-
}
|
|
7749
|
-
const state = table.getState().pagination;
|
|
7750
|
-
return {
|
|
7751
|
-
currentPageSize: state.pageSize,
|
|
7752
|
-
currentPageIndex: state.pageIndex,
|
|
7753
|
-
pageCount: table.getPageCount(),
|
|
7754
|
-
totalRows: totalCount ?? table.getRowCount(),
|
|
7755
|
-
canPreviousPage: table.getCanPreviousPage(),
|
|
7756
|
-
canNextPage: table.getCanNextPage()
|
|
7757
|
-
};
|
|
7758
|
-
};
|
|
7996
|
+
const pagination = getPaginationBinding({
|
|
7997
|
+
mode: paginationMode,
|
|
7998
|
+
table,
|
|
7999
|
+
serverData,
|
|
8000
|
+
totalCount,
|
|
8001
|
+
onPageChange,
|
|
8002
|
+
onPageSizeChange
|
|
8003
|
+
});
|
|
7759
8004
|
const {
|
|
7760
8005
|
currentPageSize,
|
|
7761
8006
|
currentPageIndex,
|
|
7762
8007
|
pageCount,
|
|
7763
8008
|
totalRows,
|
|
7764
8009
|
canPreviousPage,
|
|
7765
|
-
canNextPage
|
|
7766
|
-
|
|
7767
|
-
|
|
7768
|
-
|
|
7769
|
-
|
|
7770
|
-
|
|
7771
|
-
|
|
7772
|
-
|
|
7773
|
-
|
|
7774
|
-
|
|
7775
|
-
|
|
7776
|
-
|
|
7777
|
-
} else {
|
|
7778
|
-
table.setPageIndex(0);
|
|
7779
|
-
}
|
|
7780
|
-
};
|
|
7781
|
-
const handlePreviousPage = () => {
|
|
7782
|
-
if (paginationMode === "server") {
|
|
7783
|
-
onPageChange?.(Math.max(0, currentPageIndex - 1));
|
|
7784
|
-
} else {
|
|
7785
|
-
table.previousPage();
|
|
7786
|
-
}
|
|
7787
|
-
};
|
|
7788
|
-
const handleNextPage = () => {
|
|
7789
|
-
if (paginationMode === "server") {
|
|
7790
|
-
onPageChange?.(Math.min(pageCount - 1, currentPageIndex + 1));
|
|
7791
|
-
} else {
|
|
7792
|
-
table.nextPage();
|
|
7793
|
-
}
|
|
7794
|
-
};
|
|
7795
|
-
const handleLastPage = () => {
|
|
7796
|
-
if (paginationMode === "server") {
|
|
7797
|
-
onPageChange?.(pageCount - 1);
|
|
7798
|
-
} else {
|
|
7799
|
-
table.setPageIndex(pageCount - 1);
|
|
7800
|
-
}
|
|
7801
|
-
};
|
|
7802
|
-
const startRow = currentPageIndex * currentPageSize + 1;
|
|
7803
|
-
const endRow = Math.min((currentPageIndex + 1) * currentPageSize, totalRows);
|
|
7804
|
-
const getPageSizeOptions = () => {
|
|
7805
|
-
switch (paginationMode) {
|
|
7806
|
-
case "server":
|
|
7807
|
-
return pageSizeOptions.filter((size) => size <= 250);
|
|
7808
|
-
// Limit server-side page sizes
|
|
7809
|
-
case "hybrid":
|
|
7810
|
-
return pageSizeOptions.filter((size) => size >= 50);
|
|
7811
|
-
// Hybrid mode prefers larger pages
|
|
7812
|
-
default:
|
|
7813
|
-
return pageSizeOptions;
|
|
7814
|
-
}
|
|
7815
|
-
};
|
|
7816
|
-
const availablePageSizes = getPageSizeOptions();
|
|
8010
|
+
canNextPage,
|
|
8011
|
+
startRow,
|
|
8012
|
+
endRow
|
|
8013
|
+
} = pagination.state;
|
|
8014
|
+
const {
|
|
8015
|
+
goToFirstPage,
|
|
8016
|
+
goToPreviousPage,
|
|
8017
|
+
goToNextPage,
|
|
8018
|
+
goToLastPage,
|
|
8019
|
+
setPageSize
|
|
8020
|
+
} = pagination.actions;
|
|
8021
|
+
const availablePageSizes = getPageSizeOptions(paginationMode, pageSizeOptions);
|
|
7817
8022
|
const getModeIcon = () => {
|
|
7818
8023
|
switch (paginationMode) {
|
|
7819
8024
|
case "server":
|
|
@@ -7846,7 +8051,7 @@ function PaginationControls({
|
|
|
7846
8051
|
{
|
|
7847
8052
|
value: currentPageSize?.toString() || "10",
|
|
7848
8053
|
selectedText: currentPageSize?.toString() || "10",
|
|
7849
|
-
onValueChange: (value) =>
|
|
8054
|
+
onValueChange: (value) => setPageSize(Number(value)),
|
|
7850
8055
|
disabled: isLoading,
|
|
7851
8056
|
className: "w-36 h-8",
|
|
7852
8057
|
children: [
|
|
@@ -7860,7 +8065,7 @@ function PaginationControls({
|
|
|
7860
8065
|
children: /* @__PURE__ */ jsx15(SelectValue, {})
|
|
7861
8066
|
}
|
|
7862
8067
|
),
|
|
7863
|
-
/* @__PURE__ */ jsx15(SelectContent, { children:
|
|
8068
|
+
/* @__PURE__ */ jsx15(SelectContent, { children: availablePageSizes.map((pageSize) => /* @__PURE__ */ jsx15(SelectItem, { value: pageSize?.toString() || "10", children: pageSize }, pageSize)) })
|
|
7864
8069
|
]
|
|
7865
8070
|
}
|
|
7866
8071
|
),
|
|
@@ -7880,7 +8085,7 @@ function PaginationControls({
|
|
|
7880
8085
|
variant: "outline",
|
|
7881
8086
|
size: "sm",
|
|
7882
8087
|
className: "h-8 w-8 p-0",
|
|
7883
|
-
onClick:
|
|
8088
|
+
onClick: goToFirstPage,
|
|
7884
8089
|
disabled: !canPreviousPage || isLoading,
|
|
7885
8090
|
"aria-label": "Go to first page",
|
|
7886
8091
|
tabIndex: 0,
|
|
@@ -7893,7 +8098,7 @@ function PaginationControls({
|
|
|
7893
8098
|
variant: "outline",
|
|
7894
8099
|
size: "sm",
|
|
7895
8100
|
className: "h-8 w-8 p-0",
|
|
7896
|
-
onClick:
|
|
8101
|
+
onClick: goToPreviousPage,
|
|
7897
8102
|
disabled: !canPreviousPage || isLoading,
|
|
7898
8103
|
"aria-label": "Go to previous page",
|
|
7899
8104
|
tabIndex: 0,
|
|
@@ -7906,7 +8111,7 @@ function PaginationControls({
|
|
|
7906
8111
|
variant: "outline",
|
|
7907
8112
|
size: "sm",
|
|
7908
8113
|
className: "h-8 w-8 p-0",
|
|
7909
|
-
onClick:
|
|
8114
|
+
onClick: goToNextPage,
|
|
7910
8115
|
disabled: !canNextPage || isLoading,
|
|
7911
8116
|
"aria-label": "Go to next page",
|
|
7912
8117
|
tabIndex: 0,
|
|
@@ -7919,7 +8124,7 @@ function PaginationControls({
|
|
|
7919
8124
|
variant: "outline",
|
|
7920
8125
|
size: "sm",
|
|
7921
8126
|
className: "h-8 w-8 p-0",
|
|
7922
|
-
onClick:
|
|
8127
|
+
onClick: goToLastPage,
|
|
7923
8128
|
disabled: !canNextPage || isLoading,
|
|
7924
8129
|
"aria-label": "Go to last page",
|
|
7925
8130
|
tabIndex: 0,
|
|
@@ -7934,24 +8139,23 @@ function EnhancedPaginationControls({
|
|
|
7934
8139
|
showJumpToPage = false,
|
|
7935
8140
|
...props
|
|
7936
8141
|
}) {
|
|
7937
|
-
const [jumpToPage, setJumpToPage] =
|
|
7938
|
-
const { table, paginationMode = "client", serverData, onPageChange } = props;
|
|
7939
|
-
const
|
|
7940
|
-
|
|
7941
|
-
|
|
7942
|
-
|
|
7943
|
-
|
|
7944
|
-
|
|
8142
|
+
const [jumpToPage, setJumpToPage] = React9.useState("");
|
|
8143
|
+
const { table, paginationMode = "client", serverData, onPageChange, totalCount } = props;
|
|
8144
|
+
const pagination = getPaginationBinding({
|
|
8145
|
+
mode: paginationMode,
|
|
8146
|
+
table,
|
|
8147
|
+
serverData,
|
|
8148
|
+
totalCount,
|
|
8149
|
+
onPageChange,
|
|
8150
|
+
onPageSizeChange: props.onPageSizeChange
|
|
8151
|
+
});
|
|
8152
|
+
const { pageCount } = pagination.state;
|
|
7945
8153
|
const handleJumpToPage = (e) => {
|
|
7946
8154
|
e.preventDefault();
|
|
7947
8155
|
const pageNumber = parseInt(jumpToPage, 10);
|
|
7948
8156
|
if (pageNumber >= 1 && pageNumber <= pageCount) {
|
|
7949
8157
|
const pageIndex = pageNumber - 1;
|
|
7950
|
-
|
|
7951
|
-
onPageChange?.(pageIndex);
|
|
7952
|
-
} else {
|
|
7953
|
-
table.setPageIndex(pageIndex);
|
|
7954
|
-
}
|
|
8158
|
+
pagination.actions.goToPage(pageIndex);
|
|
7955
8159
|
setJumpToPage("");
|
|
7956
8160
|
}
|
|
7957
8161
|
};
|
|
@@ -7985,11 +8189,14 @@ function LoadingState() {
|
|
|
7985
8189
|
] }) });
|
|
7986
8190
|
}
|
|
7987
8191
|
|
|
8192
|
+
// src/components/DataTable/components/DataTableModals.tsx
|
|
8193
|
+
import { useEffect as useEffect6 } from "react";
|
|
8194
|
+
|
|
7988
8195
|
// src/components/DataTable/components/ImportModal.tsx
|
|
7989
8196
|
import { useState as useState4, useRef as useRef4, useEffect as useEffect5 } from "react";
|
|
7990
8197
|
|
|
7991
8198
|
// src/components/Dialog/Dialog.tsx
|
|
7992
|
-
import * as
|
|
8199
|
+
import * as React10 from "react";
|
|
7993
8200
|
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
|
7994
8201
|
import { X as X3 } from "lucide-react";
|
|
7995
8202
|
|
|
@@ -8065,7 +8272,7 @@ var Dialog = DialogPrimitive.Root;
|
|
|
8065
8272
|
var DialogTrigger = DialogPrimitive.Trigger;
|
|
8066
8273
|
var DialogPortal = DialogPrimitive.Portal;
|
|
8067
8274
|
var DialogClose = DialogPrimitive.Close;
|
|
8068
|
-
var DialogOverlay =
|
|
8275
|
+
var DialogOverlay = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx17(
|
|
8069
8276
|
DialogPrimitive.Overlay,
|
|
8070
8277
|
{
|
|
8071
8278
|
ref,
|
|
@@ -8142,7 +8349,7 @@ var useSmartDimensions = ({
|
|
|
8142
8349
|
}
|
|
8143
8350
|
return result;
|
|
8144
8351
|
};
|
|
8145
|
-
var DialogContent =
|
|
8352
|
+
var DialogContent = React10.forwardRef(({
|
|
8146
8353
|
className,
|
|
8147
8354
|
children,
|
|
8148
8355
|
size = "md",
|
|
@@ -8169,17 +8376,17 @@ var DialogContent = React9.forwardRef(({
|
|
|
8169
8376
|
minWidth,
|
|
8170
8377
|
enableScrolling
|
|
8171
8378
|
});
|
|
8172
|
-
const handleEscapeKeyDown =
|
|
8379
|
+
const handleEscapeKeyDown = React10.useCallback((event) => {
|
|
8173
8380
|
if (preventCloseOnEscape) {
|
|
8174
8381
|
event.preventDefault();
|
|
8175
8382
|
}
|
|
8176
8383
|
}, [preventCloseOnEscape]);
|
|
8177
|
-
const handlePointerDownOutside =
|
|
8384
|
+
const handlePointerDownOutside = React10.useCallback((event) => {
|
|
8178
8385
|
if (preventCloseOnOutsideClick) {
|
|
8179
8386
|
event.preventDefault();
|
|
8180
8387
|
}
|
|
8181
8388
|
}, [preventCloseOnOutsideClick]);
|
|
8182
|
-
const mergedStyle =
|
|
8389
|
+
const mergedStyle = React10.useMemo(() => {
|
|
8183
8390
|
if (Object.keys(smartDimensions).length === 0) {
|
|
8184
8391
|
return style;
|
|
8185
8392
|
}
|
|
@@ -8257,13 +8464,13 @@ var DialogBody = ({
|
|
|
8257
8464
|
children,
|
|
8258
8465
|
...props
|
|
8259
8466
|
}) => {
|
|
8260
|
-
const mergedStyle =
|
|
8467
|
+
const mergedStyle = React10.useMemo(() => {
|
|
8261
8468
|
return {
|
|
8262
8469
|
...maxHeight && { maxHeight },
|
|
8263
8470
|
...style
|
|
8264
8471
|
};
|
|
8265
8472
|
}, [maxHeight, style]);
|
|
8266
|
-
const processedHtmlContent =
|
|
8473
|
+
const processedHtmlContent = React10.useMemo(() => {
|
|
8267
8474
|
if (!htmlContent || !allowHtml) {
|
|
8268
8475
|
return null;
|
|
8269
8476
|
}
|
|
@@ -8325,8 +8532,8 @@ var DialogFooter = ({
|
|
|
8325
8532
|
}
|
|
8326
8533
|
);
|
|
8327
8534
|
DialogFooter.displayName = "DialogFooter";
|
|
8328
|
-
var DialogTitle =
|
|
8329
|
-
const processedHtmlContent =
|
|
8535
|
+
var DialogTitle = React10.forwardRef(({ className, htmlContent, allowHtml = true, children, ...props }, ref) => {
|
|
8536
|
+
const processedHtmlContent = React10.useMemo(() => {
|
|
8330
8537
|
if (!htmlContent || !allowHtml) {
|
|
8331
8538
|
return null;
|
|
8332
8539
|
}
|
|
@@ -8350,8 +8557,8 @@ var DialogTitle = React9.forwardRef(({ className, htmlContent, allowHtml = true,
|
|
|
8350
8557
|
);
|
|
8351
8558
|
});
|
|
8352
8559
|
DialogTitle.displayName = DialogPrimitive.Title.displayName;
|
|
8353
|
-
var DialogDescription =
|
|
8354
|
-
const processedHtmlContent =
|
|
8560
|
+
var DialogDescription = React10.forwardRef(({ className, htmlContent, allowHtml = true, children, ...props }, ref) => {
|
|
8561
|
+
const processedHtmlContent = React10.useMemo(() => {
|
|
8355
8562
|
if (!htmlContent || !allowHtml) {
|
|
8356
8563
|
return null;
|
|
8357
8564
|
}
|
|
@@ -8377,11 +8584,13 @@ DialogDescription.displayName = DialogPrimitive.Description.displayName;
|
|
|
8377
8584
|
import { Upload as Upload2, FileText, AlertCircle } from "lucide-react";
|
|
8378
8585
|
import { jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
8379
8586
|
function ImportModal({ isOpen, onClose, onImport, config = {} }) {
|
|
8587
|
+
const logger = createLogger("ImportModal");
|
|
8380
8588
|
const [file, setFile] = useState4(null);
|
|
8381
8589
|
const [isProcessing, setIsProcessing] = useState4(false);
|
|
8382
8590
|
const [error, setError] = useState4(null);
|
|
8383
8591
|
const [previewData, setPreviewData] = useState4(null);
|
|
8384
8592
|
const [totalCount, setTotalCount] = useState4(0);
|
|
8593
|
+
const [validationErrors, setValidationErrors] = useState4([]);
|
|
8385
8594
|
const fileInputRef = useRef4(null);
|
|
8386
8595
|
const isMountedRef = useRef4(true);
|
|
8387
8596
|
useEffect5(() => {
|
|
@@ -8400,34 +8609,11 @@ function ImportModal({ isOpen, onClose, onImport, config = {} }) {
|
|
|
8400
8609
|
previewHeaderText = "Preview (first 5 rows)",
|
|
8401
8610
|
totalRowsText = "Total rows to import: {count}"
|
|
8402
8611
|
} = config;
|
|
8403
|
-
const handleFileSelect = async (event) => {
|
|
8404
|
-
const selectedFile = event.target.files?.[0];
|
|
8405
|
-
console.log("\u{1F4C1} File selected:", selectedFile?.name);
|
|
8406
|
-
if (selectedFile) {
|
|
8407
|
-
setFile(selectedFile);
|
|
8408
|
-
setError(null);
|
|
8409
|
-
try {
|
|
8410
|
-
const text = await selectedFile.text();
|
|
8411
|
-
console.log("\u{1F4C4} File content length:", text.length);
|
|
8412
|
-
const data = processCSV(text);
|
|
8413
|
-
console.log("\u{1F4CA} Parsed CSV data:", data.length, "rows");
|
|
8414
|
-
console.log("\u{1F440} Setting preview data:", data.slice(0, 5));
|
|
8415
|
-
setPreviewData(data.slice(0, 5));
|
|
8416
|
-
setTotalCount(data.length);
|
|
8417
|
-
console.log("\u{1F440} Preview data state should be updated");
|
|
8418
|
-
} catch (err) {
|
|
8419
|
-
console.error("\u274C CSV parsing error:", err);
|
|
8420
|
-
setError(err instanceof Error ? err.message : "Failed to preview file");
|
|
8421
|
-
setPreviewData(null);
|
|
8422
|
-
setTotalCount(0);
|
|
8423
|
-
}
|
|
8424
|
-
}
|
|
8425
|
-
};
|
|
8426
8612
|
const processCSV = (csvText) => {
|
|
8427
|
-
|
|
8613
|
+
logger.debug("Raw CSV text:", csvText.substring(0, 200) + "...");
|
|
8428
8614
|
const lines = csvText.split("\n").filter((line) => line.trim());
|
|
8429
|
-
|
|
8430
|
-
|
|
8615
|
+
logger.debug("CSV lines count:", lines.length);
|
|
8616
|
+
logger.debug("First few lines:", lines.slice(0, 3));
|
|
8431
8617
|
if (lines.length < 2) {
|
|
8432
8618
|
throw new Error("CSV must have at least a header row and one data row");
|
|
8433
8619
|
}
|
|
@@ -8450,17 +8636,17 @@ function ImportModal({ isOpen, onClose, onImport, config = {} }) {
|
|
|
8450
8636
|
return result;
|
|
8451
8637
|
};
|
|
8452
8638
|
const headers = parseCSVLine(lines[0]).map((h) => h.replace(/"/g, "").trim());
|
|
8453
|
-
|
|
8639
|
+
logger.debug("Parsed headers:", headers);
|
|
8454
8640
|
const data = lines.slice(1).map((line, index) => {
|
|
8455
8641
|
const values = parseCSVLine(line).map((v) => v.replace(/"/g, "").trim());
|
|
8456
8642
|
const row = {};
|
|
8457
8643
|
headers.forEach((header, colIndex) => {
|
|
8458
8644
|
row[header] = values[colIndex] || "";
|
|
8459
8645
|
});
|
|
8460
|
-
|
|
8646
|
+
logger.debug(`Row ${index + 1}:`, row);
|
|
8461
8647
|
return row;
|
|
8462
8648
|
});
|
|
8463
|
-
|
|
8649
|
+
logger.debug("Final parsed data:", data);
|
|
8464
8650
|
return data;
|
|
8465
8651
|
};
|
|
8466
8652
|
const handleImport = async () => {
|
|
@@ -8489,16 +8675,41 @@ function ImportModal({ isOpen, onClose, onImport, config = {} }) {
|
|
|
8489
8675
|
setError(null);
|
|
8490
8676
|
setPreviewData(null);
|
|
8491
8677
|
setTotalCount(0);
|
|
8678
|
+
setValidationErrors([]);
|
|
8492
8679
|
onClose();
|
|
8493
8680
|
};
|
|
8494
|
-
|
|
8495
|
-
|
|
8496
|
-
|
|
8497
|
-
|
|
8498
|
-
|
|
8499
|
-
|
|
8500
|
-
|
|
8501
|
-
|
|
8681
|
+
const handleFileSelect = async (event) => {
|
|
8682
|
+
const selectedFile = event.target.files?.[0];
|
|
8683
|
+
logger.debug("File selected:", selectedFile?.name);
|
|
8684
|
+
if (selectedFile) {
|
|
8685
|
+
setFile(selectedFile);
|
|
8686
|
+
setError(null);
|
|
8687
|
+
setValidationErrors([]);
|
|
8688
|
+
try {
|
|
8689
|
+
const text = await selectedFile.text();
|
|
8690
|
+
logger.debug("File content length:", text.length);
|
|
8691
|
+
const data = processCSV(text);
|
|
8692
|
+
logger.debug("Parsed CSV data:", data.length, "rows");
|
|
8693
|
+
logger.debug("Setting preview data:", data.slice(0, 5));
|
|
8694
|
+
setPreviewData(data.slice(0, 5));
|
|
8695
|
+
setTotalCount(data.length);
|
|
8696
|
+
logger.debug("Preview data state should be updated");
|
|
8697
|
+
} catch (err) {
|
|
8698
|
+
logger.error("CSV parsing error:", err);
|
|
8699
|
+
setError(err instanceof Error ? err.message : "Failed to preview file");
|
|
8700
|
+
setPreviewData(null);
|
|
8701
|
+
setTotalCount(0);
|
|
8702
|
+
}
|
|
8703
|
+
}
|
|
8704
|
+
};
|
|
8705
|
+
return /* @__PURE__ */ jsx18(Dialog, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs14(DialogContent, { className: "sm:max-w-2xl bg-main-50", children: [
|
|
8706
|
+
/* @__PURE__ */ jsxs14(DialogHeader, { children: [
|
|
8707
|
+
/* @__PURE__ */ jsx18(DialogTitle, { children: title }),
|
|
8708
|
+
/* @__PURE__ */ jsx18(DialogDescription, { children: description })
|
|
8709
|
+
] }),
|
|
8710
|
+
/* @__PURE__ */ jsxs14("div", { className: "space-y-4", children: [
|
|
8711
|
+
/* @__PURE__ */ jsxs14("div", { className: "border-2 border-dashed border-sec-200 rounded-lg p-6 text-center", children: [
|
|
8712
|
+
/* @__PURE__ */ jsx18(FileText, { className: "h-8 w-8 mx-auto text-sec-400 mb-2" }),
|
|
8502
8713
|
/* @__PURE__ */ jsx18("p", { className: "text-sec-600 mb-2", children: file ? `Selected: ${file.name}` : uploadText }),
|
|
8503
8714
|
file && /* @__PURE__ */ jsx18("p", { className: "text-xs text-sec-500", children: "File selected, processing preview..." }),
|
|
8504
8715
|
/* @__PURE__ */ jsxs14(
|
|
@@ -8528,6 +8739,34 @@ function ImportModal({ isOpen, onClose, onImport, config = {} }) {
|
|
|
8528
8739
|
/* @__PURE__ */ jsx18(AlertCircle, { className: "h-4 w-4" }),
|
|
8529
8740
|
/* @__PURE__ */ jsx18("span", { className: "text-sm", children: error })
|
|
8530
8741
|
] }),
|
|
8742
|
+
validationErrors.length > 0 && /* @__PURE__ */ jsxs14("div", { className: "space-y-2", children: [
|
|
8743
|
+
/* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-2 p-3 bg-acc-50 border border-acc-200 rounded text-acc-700", children: [
|
|
8744
|
+
/* @__PURE__ */ jsx18(AlertCircle, { className: "h-4 w-4" }),
|
|
8745
|
+
/* @__PURE__ */ jsxs14("span", { className: "text-sm font-medium", children: [
|
|
8746
|
+
validationErrors.length,
|
|
8747
|
+
" validation error",
|
|
8748
|
+
validationErrors.length !== 1 ? "s" : "",
|
|
8749
|
+
" found"
|
|
8750
|
+
] })
|
|
8751
|
+
] }),
|
|
8752
|
+
/* @__PURE__ */ jsxs14("div", { className: "max-h-32 overflow-y-auto space-y-1", children: [
|
|
8753
|
+
validationErrors.slice(0, 10).map((err, idx) => /* @__PURE__ */ jsxs14("div", { className: "text-xs text-acc-600 p-2 bg-acc-50 border border-acc-200 rounded", children: [
|
|
8754
|
+
/* @__PURE__ */ jsxs14("span", { className: "font-medium", children: [
|
|
8755
|
+
"Row ",
|
|
8756
|
+
err.row
|
|
8757
|
+
] }),
|
|
8758
|
+
" \u2022 ",
|
|
8759
|
+
err.field,
|
|
8760
|
+
": ",
|
|
8761
|
+
err.message
|
|
8762
|
+
] }, idx)),
|
|
8763
|
+
validationErrors.length > 10 && /* @__PURE__ */ jsxs14("div", { className: "text-xs text-sec-500 italic", children: [
|
|
8764
|
+
"... and ",
|
|
8765
|
+
validationErrors.length - 10,
|
|
8766
|
+
" more errors"
|
|
8767
|
+
] })
|
|
8768
|
+
] })
|
|
8769
|
+
] }),
|
|
8531
8770
|
previewData && previewData.length > 0 && /* @__PURE__ */ jsxs14("div", { className: "space-y-3", children: [
|
|
8532
8771
|
/* @__PURE__ */ jsx18("h4", { className: "text-sec-900", children: previewHeaderText }),
|
|
8533
8772
|
/* @__PURE__ */ jsx18("div", { className: "border rounded-lg overflow-hidden", children: /* @__PURE__ */ jsx18("div", { className: "overflow-x-auto max-h-48", children: /* @__PURE__ */ jsxs14("table", { className: "min-w-full text-xs", children: [
|
|
@@ -8557,8 +8796,20 @@ function DataTableModals({
|
|
|
8557
8796
|
showImportModal,
|
|
8558
8797
|
onCloseImportModal,
|
|
8559
8798
|
onImport,
|
|
8560
|
-
importModalConfig
|
|
8799
|
+
importModalConfig,
|
|
8800
|
+
onStoreFocus,
|
|
8801
|
+
onRestoreFocus
|
|
8561
8802
|
}) {
|
|
8803
|
+
useEffect6(() => {
|
|
8804
|
+
if (showImportModal) {
|
|
8805
|
+
onStoreFocus?.();
|
|
8806
|
+
} else {
|
|
8807
|
+
const timeoutId = setTimeout(() => {
|
|
8808
|
+
onRestoreFocus?.();
|
|
8809
|
+
}, 100);
|
|
8810
|
+
return () => clearTimeout(timeoutId);
|
|
8811
|
+
}
|
|
8812
|
+
}, [showImportModal, onStoreFocus, onRestoreFocus]);
|
|
8562
8813
|
return /* @__PURE__ */ jsx19(Fragment3, { children: /* @__PURE__ */ jsx19(
|
|
8563
8814
|
ImportModal,
|
|
8564
8815
|
{
|
|
@@ -8571,12 +8822,12 @@ function DataTableModals({
|
|
|
8571
8822
|
}
|
|
8572
8823
|
|
|
8573
8824
|
// src/components/DataTable/components/DataTableErrorBoundary.tsx
|
|
8574
|
-
import
|
|
8825
|
+
import React14, { Component } from "react";
|
|
8575
8826
|
|
|
8576
8827
|
// src/components/Alert/Alert.tsx
|
|
8577
|
-
import * as
|
|
8828
|
+
import * as React13 from "react";
|
|
8578
8829
|
import { jsx as jsx20 } from "react/jsx-runtime";
|
|
8579
|
-
var AlertContext =
|
|
8830
|
+
var AlertContext = React13.createContext({ variant: "default" });
|
|
8580
8831
|
var getAlertClasses = (variant = "default") => {
|
|
8581
8832
|
const baseClasses = "relative w-full rounded-lg border p-4";
|
|
8582
8833
|
const variantClasses = {
|
|
@@ -8587,10 +8838,10 @@ var getAlertClasses = (variant = "default") => {
|
|
|
8587
8838
|
};
|
|
8588
8839
|
return `${baseClasses} ${variantClasses[variant]}`;
|
|
8589
8840
|
};
|
|
8590
|
-
var Alert =
|
|
8591
|
-
const contextValue =
|
|
8841
|
+
var Alert = React13.forwardRef(({ className, variant = "default", ...props }, ref) => {
|
|
8842
|
+
const contextValue = React13.useMemo(() => ({ variant }), [variant]);
|
|
8592
8843
|
if (variant === "inline") {
|
|
8593
|
-
return /* @__PURE__ */ jsx20(AlertContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx20(
|
|
8844
|
+
return /* @__PURE__ */ jsx20(AlertContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx20(React13.Fragment, { ...props }) });
|
|
8594
8845
|
}
|
|
8595
8846
|
return /* @__PURE__ */ jsx20(AlertContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx20(
|
|
8596
8847
|
"div",
|
|
@@ -8603,8 +8854,8 @@ var Alert = React11.forwardRef(({ className, variant = "default", ...props }, re
|
|
|
8603
8854
|
) });
|
|
8604
8855
|
});
|
|
8605
8856
|
Alert.displayName = "Alert";
|
|
8606
|
-
var AlertTitle =
|
|
8607
|
-
const { variant } =
|
|
8857
|
+
var AlertTitle = React13.forwardRef(({ className, ...props }, ref) => {
|
|
8858
|
+
const { variant } = React13.useContext(AlertContext);
|
|
8608
8859
|
if (variant === "inline") {
|
|
8609
8860
|
return /* @__PURE__ */ jsx20("strong", { ...props });
|
|
8610
8861
|
}
|
|
@@ -8618,8 +8869,8 @@ var AlertTitle = React11.forwardRef(({ className, ...props }, ref) => {
|
|
|
8618
8869
|
);
|
|
8619
8870
|
});
|
|
8620
8871
|
AlertTitle.displayName = "AlertTitle";
|
|
8621
|
-
var AlertDescription =
|
|
8622
|
-
const { variant } =
|
|
8872
|
+
var AlertDescription = React13.forwardRef(({ className, ...props }, ref) => {
|
|
8873
|
+
const { variant } = React13.useContext(AlertContext);
|
|
8623
8874
|
if (variant === "inline") {
|
|
8624
8875
|
return /* @__PURE__ */ jsx20("span", { ...props });
|
|
8625
8876
|
}
|
|
@@ -8639,12 +8890,13 @@ import { Fragment as Fragment5, jsx as jsx21, jsxs as jsxs15 } from "react/jsx-r
|
|
|
8639
8890
|
var DataTableErrorBoundary = class extends Component {
|
|
8640
8891
|
constructor(props) {
|
|
8641
8892
|
super(props);
|
|
8893
|
+
this.logger = createLogger("DataTableErrorBoundary");
|
|
8642
8894
|
this.retryTimeoutId = null;
|
|
8643
8895
|
this.handleRetry = () => {
|
|
8644
8896
|
const { onRetry, maxRetries = 3 } = this.props;
|
|
8645
8897
|
const { retryCount } = this.state;
|
|
8646
8898
|
if (retryCount >= maxRetries) {
|
|
8647
|
-
|
|
8899
|
+
this.logger.warn("Error Boundary: Maximum retry attempts reached");
|
|
8648
8900
|
return;
|
|
8649
8901
|
}
|
|
8650
8902
|
if (onRetry) {
|
|
@@ -8686,7 +8938,7 @@ var DataTableErrorBoundary = class extends Component {
|
|
|
8686
8938
|
errorInfo
|
|
8687
8939
|
});
|
|
8688
8940
|
this.props.onError?.(error, errorInfo);
|
|
8689
|
-
|
|
8941
|
+
this.logger.error("Error Boundary caught an error:", error, errorInfo);
|
|
8690
8942
|
}
|
|
8691
8943
|
componentWillUnmount() {
|
|
8692
8944
|
if (this.retryTimeoutId) {
|
|
@@ -8753,22 +9005,28 @@ var DataTableErrorBoundary = class extends Component {
|
|
|
8753
9005
|
};
|
|
8754
9006
|
|
|
8755
9007
|
// src/components/DataTable/hooks/useColumnOrderPersistence.ts
|
|
8756
|
-
import { useState as useState5, useEffect as
|
|
9008
|
+
import { useState as useState5, useEffect as useEffect7, useCallback as useCallback3 } from "react";
|
|
8757
9009
|
function useColumnOrderPersistence({
|
|
8758
9010
|
tableId,
|
|
8759
9011
|
defaultOrder = [],
|
|
8760
|
-
enablePersistence = false
|
|
9012
|
+
enablePersistence = false,
|
|
9013
|
+
storageKey
|
|
8761
9014
|
}) {
|
|
9015
|
+
const logger = createLogger("ColumnOrderPersistence");
|
|
8762
9016
|
const [columnOrder, setColumnOrder] = useState5(defaultOrder);
|
|
8763
9017
|
const [isLoaded, setIsLoaded] = useState5(false);
|
|
8764
|
-
const
|
|
8765
|
-
|
|
8766
|
-
if (!enablePersistence ||
|
|
9018
|
+
const finalStorageKey = storageKey ? `${storageKey}-column-order` : tableId ? `datatable-column-order-${tableId}` : "datatable-column-order";
|
|
9019
|
+
useEffect7(() => {
|
|
9020
|
+
if (!enablePersistence || typeof window === "undefined") {
|
|
9021
|
+
setIsLoaded(true);
|
|
9022
|
+
return;
|
|
9023
|
+
}
|
|
9024
|
+
if (!storageKey && !tableId) {
|
|
8767
9025
|
setIsLoaded(true);
|
|
8768
9026
|
return;
|
|
8769
9027
|
}
|
|
8770
9028
|
try {
|
|
8771
|
-
const savedOrder = localStorage.getItem(
|
|
9029
|
+
const savedOrder = localStorage.getItem(finalStorageKey);
|
|
8772
9030
|
if (savedOrder) {
|
|
8773
9031
|
const parsedOrder = JSON.parse(savedOrder);
|
|
8774
9032
|
if (Array.isArray(parsedOrder)) {
|
|
@@ -8776,35 +9034,36 @@ function useColumnOrderPersistence({
|
|
|
8776
9034
|
}
|
|
8777
9035
|
}
|
|
8778
9036
|
} catch (error) {
|
|
8779
|
-
|
|
9037
|
+
logger.warn("Failed to load column order from localStorage:", error);
|
|
8780
9038
|
} finally {
|
|
8781
9039
|
setIsLoaded(true);
|
|
8782
9040
|
}
|
|
8783
|
-
}, [enablePersistence,
|
|
9041
|
+
}, [enablePersistence, finalStorageKey, storageKey, tableId]);
|
|
8784
9042
|
const saveColumnOrder = useCallback3((newOrder) => {
|
|
8785
|
-
if (!enablePersistence ||
|
|
9043
|
+
if (!enablePersistence || typeof window === "undefined") return;
|
|
9044
|
+
if (!storageKey && !tableId) return;
|
|
8786
9045
|
try {
|
|
8787
|
-
localStorage.setItem(
|
|
9046
|
+
localStorage.setItem(finalStorageKey, JSON.stringify(newOrder));
|
|
8788
9047
|
} catch (error) {
|
|
8789
|
-
|
|
9048
|
+
logger.warn("Failed to save column order to localStorage:", error);
|
|
8790
9049
|
}
|
|
8791
|
-
}, [enablePersistence,
|
|
9050
|
+
}, [enablePersistence, finalStorageKey, storageKey, tableId]);
|
|
8792
9051
|
const updateColumnOrder = useCallback3((newOrder) => {
|
|
8793
9052
|
setColumnOrder(newOrder);
|
|
8794
9053
|
saveColumnOrder(newOrder);
|
|
8795
9054
|
}, [saveColumnOrder]);
|
|
8796
9055
|
const resetColumnOrder = useCallback3(() => {
|
|
8797
9056
|
setColumnOrder(defaultOrder);
|
|
8798
|
-
if (enablePersistence && tableId) {
|
|
9057
|
+
if (enablePersistence && (storageKey || tableId) && typeof window !== "undefined") {
|
|
8799
9058
|
try {
|
|
8800
|
-
localStorage.removeItem(
|
|
9059
|
+
localStorage.removeItem(finalStorageKey);
|
|
8801
9060
|
} catch (error) {
|
|
8802
|
-
|
|
9061
|
+
logger.warn("Failed to remove column order from localStorage:", error);
|
|
8803
9062
|
}
|
|
8804
9063
|
}
|
|
8805
|
-
}, [defaultOrder, enablePersistence,
|
|
9064
|
+
}, [defaultOrder, enablePersistence, finalStorageKey, storageKey, tableId]);
|
|
8806
9065
|
const clearAllPreferences = useCallback3(() => {
|
|
8807
|
-
if (!enablePersistence) return;
|
|
9066
|
+
if (!enablePersistence || typeof window === "undefined") return;
|
|
8808
9067
|
try {
|
|
8809
9068
|
const keys = Object.keys(localStorage);
|
|
8810
9069
|
keys.forEach((key) => {
|
|
@@ -8813,7 +9072,7 @@ function useColumnOrderPersistence({
|
|
|
8813
9072
|
}
|
|
8814
9073
|
});
|
|
8815
9074
|
} catch (error) {
|
|
8816
|
-
|
|
9075
|
+
logger.warn("Failed to clear datatable preferences:", error);
|
|
8817
9076
|
}
|
|
8818
9077
|
}, [enablePersistence]);
|
|
8819
9078
|
return {
|
|
@@ -8825,127 +9084,78 @@ function useColumnOrderPersistence({
|
|
|
8825
9084
|
};
|
|
8826
9085
|
}
|
|
8827
9086
|
|
|
8828
|
-
// src/components/DataTable/hooks/
|
|
8829
|
-
import { useState as useState6,
|
|
8830
|
-
function
|
|
8831
|
-
|
|
8832
|
-
|
|
8833
|
-
|
|
9087
|
+
// src/components/DataTable/hooks/useColumnVisibilityPersistence.ts
|
|
9088
|
+
import { useState as useState6, useEffect as useEffect8, useCallback as useCallback4 } from "react";
|
|
9089
|
+
function useColumnVisibilityPersistence({
|
|
9090
|
+
tableId,
|
|
9091
|
+
defaultVisibility = {},
|
|
9092
|
+
enablePersistence = false,
|
|
9093
|
+
storageKey
|
|
9094
|
+
}) {
|
|
9095
|
+
const logger = createLogger("ColumnVisibilityPersistence");
|
|
9096
|
+
const [columnVisibility, setColumnVisibility] = useState6(defaultVisibility);
|
|
9097
|
+
const [isLoaded, setIsLoaded] = useState6(false);
|
|
9098
|
+
const finalStorageKey = storageKey ? `${storageKey}-column-visibility` : tableId ? `datatable-column-visibility-${tableId}` : "datatable-column-visibility";
|
|
9099
|
+
useEffect8(() => {
|
|
9100
|
+
if (!enablePersistence || typeof window === "undefined") {
|
|
9101
|
+
setIsLoaded(true);
|
|
9102
|
+
return;
|
|
8834
9103
|
}
|
|
8835
|
-
|
|
8836
|
-
|
|
9104
|
+
try {
|
|
9105
|
+
const savedVisibility = localStorage.getItem(finalStorageKey);
|
|
9106
|
+
if (savedVisibility) {
|
|
9107
|
+
const parsedVisibility = JSON.parse(savedVisibility);
|
|
9108
|
+
if (typeof parsedVisibility === "object" && parsedVisibility !== null) {
|
|
9109
|
+
setColumnVisibility(parsedVisibility);
|
|
9110
|
+
}
|
|
9111
|
+
}
|
|
9112
|
+
} catch (error) {
|
|
9113
|
+
logger.warn("Failed to load column visibility from localStorage:", error);
|
|
9114
|
+
} finally {
|
|
9115
|
+
setIsLoaded(true);
|
|
8837
9116
|
}
|
|
8838
|
-
|
|
8839
|
-
|
|
9117
|
+
}, [enablePersistence, finalStorageKey]);
|
|
9118
|
+
const saveColumnVisibility = useCallback4((newVisibility) => {
|
|
9119
|
+
if (!enablePersistence || typeof window === "undefined") return;
|
|
9120
|
+
try {
|
|
9121
|
+
localStorage.setItem(finalStorageKey, JSON.stringify(newVisibility));
|
|
9122
|
+
} catch (error) {
|
|
9123
|
+
logger.warn("Failed to save column visibility to localStorage:", error);
|
|
8840
9124
|
}
|
|
8841
|
-
|
|
8842
|
-
|
|
8843
|
-
|
|
8844
|
-
|
|
8845
|
-
|
|
8846
|
-
|
|
8847
|
-
|
|
8848
|
-
|
|
8849
|
-
|
|
8850
|
-
|
|
8851
|
-
|
|
8852
|
-
|
|
8853
|
-
setExpandedRows(new Set(data.filter((row) => row.isParent).map((row) => row.id)));
|
|
8854
|
-
} else if (Array.isArray(config.defaultExpanded)) {
|
|
8855
|
-
setExpandedRows(new Set(config.defaultExpanded));
|
|
9125
|
+
}, [enablePersistence, finalStorageKey]);
|
|
9126
|
+
const updateColumnVisibility = useCallback4((newVisibility) => {
|
|
9127
|
+
setColumnVisibility(newVisibility);
|
|
9128
|
+
saveColumnVisibility(newVisibility);
|
|
9129
|
+
}, [saveColumnVisibility]);
|
|
9130
|
+
const resetColumnVisibility = useCallback4(() => {
|
|
9131
|
+
setColumnVisibility(defaultVisibility);
|
|
9132
|
+
if (enablePersistence && typeof window !== "undefined") {
|
|
9133
|
+
try {
|
|
9134
|
+
localStorage.removeItem(finalStorageKey);
|
|
9135
|
+
} catch (error) {
|
|
9136
|
+
logger.warn("Failed to remove column visibility from localStorage:", error);
|
|
8856
9137
|
}
|
|
8857
|
-
setPrevDataLength(data.length);
|
|
8858
|
-
setPrevDefaultExpanded(config?.defaultExpanded);
|
|
8859
|
-
}
|
|
8860
|
-
}, [data, config?.defaultExpanded, prevDataLength, prevDefaultExpanded]);
|
|
8861
|
-
const parentChildMap = useMemo5(() => {
|
|
8862
|
-
const map = /* @__PURE__ */ new Map();
|
|
8863
|
-
if (Array.isArray(data)) {
|
|
8864
|
-
data.forEach((row) => {
|
|
8865
|
-
if (row.isParent) {
|
|
8866
|
-
map.set(row.id, []);
|
|
8867
|
-
} else if (row.parentId) {
|
|
8868
|
-
const children = map.get(row.parentId) || [];
|
|
8869
|
-
children.push(row);
|
|
8870
|
-
map.set(row.parentId, children);
|
|
8871
|
-
}
|
|
8872
|
-
});
|
|
8873
9138
|
}
|
|
8874
|
-
|
|
8875
|
-
|
|
8876
|
-
|
|
8877
|
-
|
|
8878
|
-
|
|
8879
|
-
|
|
8880
|
-
if (
|
|
8881
|
-
|
|
8882
|
-
if (expandedRows.has(row.id)) {
|
|
8883
|
-
const children = parentChildMap.get(row.id) || [];
|
|
8884
|
-
visible.push(...children);
|
|
8885
|
-
}
|
|
9139
|
+
}, [defaultVisibility, enablePersistence, finalStorageKey]);
|
|
9140
|
+
const clearAllPreferences = useCallback4(() => {
|
|
9141
|
+
if (!enablePersistence || typeof window === "undefined") return;
|
|
9142
|
+
try {
|
|
9143
|
+
const keys = Object.keys(localStorage);
|
|
9144
|
+
keys.forEach((key) => {
|
|
9145
|
+
if (key.startsWith("datatable-")) {
|
|
9146
|
+
localStorage.removeItem(key);
|
|
8886
9147
|
}
|
|
8887
9148
|
});
|
|
9149
|
+
} catch (error) {
|
|
9150
|
+
logger.warn("Failed to clear datatable preferences:", error);
|
|
8888
9151
|
}
|
|
8889
|
-
|
|
8890
|
-
}, [data, expandedRows, parentChildMap]);
|
|
8891
|
-
const toggleRow = useCallback4((rowId) => {
|
|
8892
|
-
setExpandedRows((prev) => {
|
|
8893
|
-
const newSet = new Set(prev);
|
|
8894
|
-
if (newSet.has(rowId)) {
|
|
8895
|
-
newSet.delete(rowId);
|
|
8896
|
-
} else {
|
|
8897
|
-
newSet.add(rowId);
|
|
8898
|
-
}
|
|
8899
|
-
if (config?.onExpandedChange) {
|
|
8900
|
-
config.onExpandedChange(Array.from(newSet));
|
|
8901
|
-
}
|
|
8902
|
-
return newSet;
|
|
8903
|
-
});
|
|
8904
|
-
}, [config]);
|
|
8905
|
-
const expandAll = useCallback4(() => {
|
|
8906
|
-
const parentIds = data.filter((row) => row.isParent).map((row) => row.id);
|
|
8907
|
-
setExpandedRows(new Set(parentIds));
|
|
8908
|
-
if (config?.onExpandedChange) {
|
|
8909
|
-
config.onExpandedChange(parentIds);
|
|
8910
|
-
}
|
|
8911
|
-
}, [data, config]);
|
|
8912
|
-
const collapseAll = useCallback4(() => {
|
|
8913
|
-
setExpandedRows(/* @__PURE__ */ new Set());
|
|
8914
|
-
if (config?.onExpandedChange) {
|
|
8915
|
-
config.onExpandedChange([]);
|
|
8916
|
-
}
|
|
8917
|
-
}, [config]);
|
|
8918
|
-
const isExpanded = useCallback4((rowId) => {
|
|
8919
|
-
return expandedRows.has(rowId);
|
|
8920
|
-
}, [expandedRows]);
|
|
8921
|
-
const hasChildren = useCallback4((rowId) => {
|
|
8922
|
-
return parentChildMap.has(rowId) && (parentChildMap.get(rowId)?.length || 0) > 0;
|
|
8923
|
-
}, [parentChildMap]);
|
|
8924
|
-
const getChildrenCount = useCallback4((rowId) => {
|
|
8925
|
-
return parentChildMap.get(rowId)?.length || 0;
|
|
8926
|
-
}, [parentChildMap]);
|
|
8927
|
-
const getExpandedIds = useCallback4(() => {
|
|
8928
|
-
return Array.from(expandedRows);
|
|
8929
|
-
}, [expandedRows]);
|
|
8930
|
-
const setExpandedIds = useCallback4((ids) => {
|
|
8931
|
-
setExpandedRows(new Set(ids));
|
|
8932
|
-
}, []);
|
|
9152
|
+
}, [enablePersistence]);
|
|
8933
9153
|
return {
|
|
8934
|
-
|
|
8935
|
-
|
|
8936
|
-
|
|
8937
|
-
|
|
8938
|
-
|
|
8939
|
-
expandAll,
|
|
8940
|
-
collapseAll,
|
|
8941
|
-
setExpandedIds,
|
|
8942
|
-
// Getters
|
|
8943
|
-
isExpanded,
|
|
8944
|
-
hasChildren,
|
|
8945
|
-
getChildrenCount,
|
|
8946
|
-
getExpandedIds,
|
|
8947
|
-
// Utilities
|
|
8948
|
-
parentChildMap
|
|
9154
|
+
columnVisibility,
|
|
9155
|
+
isLoaded,
|
|
9156
|
+
updateColumnVisibility,
|
|
9157
|
+
resetColumnVisibility,
|
|
9158
|
+
clearAllPreferences
|
|
8949
9159
|
};
|
|
8950
9160
|
}
|
|
8951
9161
|
|
|
@@ -9098,80 +9308,207 @@ function useDataTableState({
|
|
|
9098
9308
|
};
|
|
9099
9309
|
}
|
|
9100
9310
|
|
|
9101
|
-
// src/components/DataTable/
|
|
9102
|
-
|
|
9103
|
-
|
|
9104
|
-
|
|
9105
|
-
|
|
9106
|
-
|
|
9107
|
-
|
|
9108
|
-
|
|
9311
|
+
// src/components/DataTable/hooks/useDataTableDataPipeline.ts
|
|
9312
|
+
import { useMemo as useMemo8 } from "react";
|
|
9313
|
+
|
|
9314
|
+
// src/components/DataTable/hooks/useHierarchicalState.ts
|
|
9315
|
+
import { useState as useState7, useCallback as useCallback6, useMemo as useMemo7, useEffect as useEffect9 } from "react";
|
|
9316
|
+
function useHierarchicalState(data, config) {
|
|
9317
|
+
const initialExpandedState = useMemo7(() => {
|
|
9318
|
+
if (!config?.defaultExpanded) {
|
|
9319
|
+
return /* @__PURE__ */ new Set();
|
|
9109
9320
|
}
|
|
9110
|
-
|
|
9111
|
-
|
|
9112
|
-
if (!row.isParent && !processed.has(row.id)) {
|
|
9113
|
-
sorted.push(row);
|
|
9114
|
-
processed.add(row.id);
|
|
9321
|
+
if (config.defaultExpanded === true) {
|
|
9322
|
+
return new Set(data.filter((row) => row.isParent).map((row) => row.id));
|
|
9115
9323
|
}
|
|
9116
|
-
|
|
9117
|
-
|
|
9118
|
-
}
|
|
9119
|
-
function sortHierarchicalDataWithSorting(data, sorting) {
|
|
9120
|
-
if (sorting.length === 0) {
|
|
9121
|
-
return data;
|
|
9122
|
-
}
|
|
9123
|
-
const [sortConfig] = sorting;
|
|
9124
|
-
const { id: columnId, desc } = sortConfig;
|
|
9125
|
-
const parentGroups = /* @__PURE__ */ new Map();
|
|
9126
|
-
data.forEach((row) => {
|
|
9127
|
-
if (row.isParent) {
|
|
9128
|
-
parentGroups.set(row.id, { parent: row, children: [] });
|
|
9129
|
-
} else if (row.parentId) {
|
|
9130
|
-
const group = parentGroups.get(row.parentId);
|
|
9131
|
-
if (group) {
|
|
9132
|
-
group.children.push(row);
|
|
9133
|
-
}
|
|
9324
|
+
if (Array.isArray(config.defaultExpanded)) {
|
|
9325
|
+
return new Set(config.defaultExpanded);
|
|
9134
9326
|
}
|
|
9135
|
-
|
|
9136
|
-
|
|
9137
|
-
|
|
9138
|
-
|
|
9139
|
-
|
|
9140
|
-
|
|
9141
|
-
|
|
9142
|
-
|
|
9143
|
-
|
|
9144
|
-
|
|
9145
|
-
|
|
9146
|
-
|
|
9147
|
-
|
|
9148
|
-
|
|
9149
|
-
|
|
9150
|
-
|
|
9151
|
-
|
|
9152
|
-
|
|
9153
|
-
});
|
|
9154
|
-
return sortedData;
|
|
9155
|
-
}
|
|
9156
|
-
function getSortValue(row, columnId) {
|
|
9157
|
-
const keys = columnId.split(".");
|
|
9158
|
-
let value = row;
|
|
9159
|
-
for (const key of keys) {
|
|
9160
|
-
if (value && typeof value === "object" && key in value) {
|
|
9161
|
-
value = value[key];
|
|
9162
|
-
} else {
|
|
9163
|
-
return null;
|
|
9327
|
+
return /* @__PURE__ */ new Set();
|
|
9328
|
+
}, [data, config?.defaultExpanded]);
|
|
9329
|
+
const [expandedRows, setExpandedRows] = useState7(initialExpandedState);
|
|
9330
|
+
const [prevDataLength, setPrevDataLength] = useState7(data.length);
|
|
9331
|
+
const [prevDefaultExpanded, setPrevDefaultExpanded] = useState7(config?.defaultExpanded);
|
|
9332
|
+
useEffect9(() => {
|
|
9333
|
+
const dataLengthChanged = data.length !== prevDataLength;
|
|
9334
|
+
const configChanged = config?.defaultExpanded !== prevDefaultExpanded;
|
|
9335
|
+
if (configChanged || dataLengthChanged) {
|
|
9336
|
+
if (!config?.defaultExpanded) {
|
|
9337
|
+
setExpandedRows(/* @__PURE__ */ new Set());
|
|
9338
|
+
} else if (config.defaultExpanded === true) {
|
|
9339
|
+
setExpandedRows(new Set(data.filter((row) => row.isParent).map((row) => row.id)));
|
|
9340
|
+
} else if (Array.isArray(config.defaultExpanded)) {
|
|
9341
|
+
setExpandedRows(new Set(config.defaultExpanded));
|
|
9342
|
+
}
|
|
9343
|
+
setPrevDataLength(data.length);
|
|
9344
|
+
setPrevDefaultExpanded(config?.defaultExpanded);
|
|
9164
9345
|
}
|
|
9165
|
-
}
|
|
9166
|
-
|
|
9167
|
-
|
|
9168
|
-
|
|
9169
|
-
|
|
9170
|
-
|
|
9171
|
-
|
|
9172
|
-
|
|
9173
|
-
|
|
9174
|
-
|
|
9346
|
+
}, [data, config?.defaultExpanded, prevDataLength, prevDefaultExpanded]);
|
|
9347
|
+
const parentChildMap = useMemo7(() => {
|
|
9348
|
+
const map = /* @__PURE__ */ new Map();
|
|
9349
|
+
if (Array.isArray(data)) {
|
|
9350
|
+
data.forEach((row) => {
|
|
9351
|
+
if (row.isParent) {
|
|
9352
|
+
map.set(row.id, []);
|
|
9353
|
+
} else if (row.parentId) {
|
|
9354
|
+
const children = map.get(row.parentId) || [];
|
|
9355
|
+
children.push(row);
|
|
9356
|
+
map.set(row.parentId, children);
|
|
9357
|
+
}
|
|
9358
|
+
});
|
|
9359
|
+
}
|
|
9360
|
+
return map;
|
|
9361
|
+
}, [data]);
|
|
9362
|
+
const visibleRows = useMemo7(() => {
|
|
9363
|
+
const visible = [];
|
|
9364
|
+
if (Array.isArray(data)) {
|
|
9365
|
+
data.forEach((row) => {
|
|
9366
|
+
if (row.isParent) {
|
|
9367
|
+
visible.push(row);
|
|
9368
|
+
if (expandedRows.has(row.id)) {
|
|
9369
|
+
const children = parentChildMap.get(row.id) || [];
|
|
9370
|
+
visible.push(...children);
|
|
9371
|
+
}
|
|
9372
|
+
}
|
|
9373
|
+
});
|
|
9374
|
+
}
|
|
9375
|
+
return visible;
|
|
9376
|
+
}, [data, expandedRows, parentChildMap]);
|
|
9377
|
+
const toggleRow = useCallback6((rowId) => {
|
|
9378
|
+
setExpandedRows((prev) => {
|
|
9379
|
+
const newSet = new Set(prev);
|
|
9380
|
+
if (newSet.has(rowId)) {
|
|
9381
|
+
newSet.delete(rowId);
|
|
9382
|
+
} else {
|
|
9383
|
+
newSet.add(rowId);
|
|
9384
|
+
}
|
|
9385
|
+
if (config?.onExpandedChange) {
|
|
9386
|
+
config.onExpandedChange(Array.from(newSet));
|
|
9387
|
+
}
|
|
9388
|
+
return newSet;
|
|
9389
|
+
});
|
|
9390
|
+
}, [config]);
|
|
9391
|
+
const expandAll = useCallback6(() => {
|
|
9392
|
+
const parentIds = data.filter((row) => row.isParent).map((row) => row.id);
|
|
9393
|
+
setExpandedRows(new Set(parentIds));
|
|
9394
|
+
if (config?.onExpandedChange) {
|
|
9395
|
+
config.onExpandedChange(parentIds);
|
|
9396
|
+
}
|
|
9397
|
+
}, [data, config]);
|
|
9398
|
+
const collapseAll = useCallback6(() => {
|
|
9399
|
+
setExpandedRows(/* @__PURE__ */ new Set());
|
|
9400
|
+
if (config?.onExpandedChange) {
|
|
9401
|
+
config.onExpandedChange([]);
|
|
9402
|
+
}
|
|
9403
|
+
}, [config]);
|
|
9404
|
+
const isExpanded = useCallback6((rowId) => {
|
|
9405
|
+
return expandedRows.has(rowId);
|
|
9406
|
+
}, [expandedRows]);
|
|
9407
|
+
const hasChildren = useCallback6((rowId) => {
|
|
9408
|
+
return parentChildMap.has(rowId) && (parentChildMap.get(rowId)?.length || 0) > 0;
|
|
9409
|
+
}, [parentChildMap]);
|
|
9410
|
+
const getChildrenCount = useCallback6((rowId) => {
|
|
9411
|
+
return parentChildMap.get(rowId)?.length || 0;
|
|
9412
|
+
}, [parentChildMap]);
|
|
9413
|
+
const getExpandedIds = useCallback6(() => {
|
|
9414
|
+
return Array.from(expandedRows);
|
|
9415
|
+
}, [expandedRows]);
|
|
9416
|
+
const setExpandedIds = useCallback6((ids) => {
|
|
9417
|
+
setExpandedRows(new Set(ids));
|
|
9418
|
+
}, []);
|
|
9419
|
+
return {
|
|
9420
|
+
// State
|
|
9421
|
+
expandedRows,
|
|
9422
|
+
visibleRows,
|
|
9423
|
+
// Actions
|
|
9424
|
+
toggleRow,
|
|
9425
|
+
expandAll,
|
|
9426
|
+
collapseAll,
|
|
9427
|
+
setExpandedIds,
|
|
9428
|
+
// Getters
|
|
9429
|
+
isExpanded,
|
|
9430
|
+
hasChildren,
|
|
9431
|
+
getChildrenCount,
|
|
9432
|
+
getExpandedIds,
|
|
9433
|
+
// Utilities
|
|
9434
|
+
parentChildMap
|
|
9435
|
+
};
|
|
9436
|
+
}
|
|
9437
|
+
|
|
9438
|
+
// src/components/DataTable/utils/hierarchicalSorting.ts
|
|
9439
|
+
function sortHierarchicalDataByStructure(data) {
|
|
9440
|
+
const sorted = [];
|
|
9441
|
+
const processed = /* @__PURE__ */ new Set();
|
|
9442
|
+
data.forEach((row) => {
|
|
9443
|
+
if (row.isParent && !processed.has(row.id)) {
|
|
9444
|
+
sorted.push(row);
|
|
9445
|
+
processed.add(row.id);
|
|
9446
|
+
}
|
|
9447
|
+
});
|
|
9448
|
+
data.forEach((row) => {
|
|
9449
|
+
if (!row.isParent && !processed.has(row.id)) {
|
|
9450
|
+
sorted.push(row);
|
|
9451
|
+
processed.add(row.id);
|
|
9452
|
+
}
|
|
9453
|
+
});
|
|
9454
|
+
return sorted;
|
|
9455
|
+
}
|
|
9456
|
+
function sortHierarchicalDataWithSorting(data, sorting) {
|
|
9457
|
+
if (sorting.length === 0) {
|
|
9458
|
+
return data;
|
|
9459
|
+
}
|
|
9460
|
+
const [sortConfig] = sorting;
|
|
9461
|
+
const { id: columnId, desc } = sortConfig;
|
|
9462
|
+
const parentGroups = /* @__PURE__ */ new Map();
|
|
9463
|
+
data.forEach((row) => {
|
|
9464
|
+
if (row.isParent) {
|
|
9465
|
+
parentGroups.set(row.id, { parent: row, children: [] });
|
|
9466
|
+
} else if (row.parentId) {
|
|
9467
|
+
const group = parentGroups.get(row.parentId);
|
|
9468
|
+
if (group) {
|
|
9469
|
+
group.children.push(row);
|
|
9470
|
+
}
|
|
9471
|
+
}
|
|
9472
|
+
});
|
|
9473
|
+
const sortedGroups = Array.from(parentGroups.values()).map((group) => {
|
|
9474
|
+
const sortedChildren = [...group.children].sort((a, b) => {
|
|
9475
|
+
const aValue = getSortValue(a, columnId);
|
|
9476
|
+
const bValue = getSortValue(b, columnId);
|
|
9477
|
+
if (aValue === bValue) return 0;
|
|
9478
|
+
const comparison = compareValues(aValue, bValue);
|
|
9479
|
+
return desc ? -comparison : comparison;
|
|
9480
|
+
});
|
|
9481
|
+
return {
|
|
9482
|
+
parent: group.parent,
|
|
9483
|
+
children: sortedChildren
|
|
9484
|
+
};
|
|
9485
|
+
});
|
|
9486
|
+
const sortedData = [];
|
|
9487
|
+
sortedGroups.forEach((group) => {
|
|
9488
|
+
sortedData.push(group.parent);
|
|
9489
|
+
sortedData.push(...group.children);
|
|
9490
|
+
});
|
|
9491
|
+
return sortedData;
|
|
9492
|
+
}
|
|
9493
|
+
function getSortValue(row, columnId) {
|
|
9494
|
+
const keys = columnId.split(".");
|
|
9495
|
+
let value = row;
|
|
9496
|
+
for (const key of keys) {
|
|
9497
|
+
if (value && typeof value === "object" && key in value) {
|
|
9498
|
+
value = value[key];
|
|
9499
|
+
} else {
|
|
9500
|
+
return null;
|
|
9501
|
+
}
|
|
9502
|
+
}
|
|
9503
|
+
return value;
|
|
9504
|
+
}
|
|
9505
|
+
function compareValues(a, b) {
|
|
9506
|
+
if (a == null && b == null) return 0;
|
|
9507
|
+
if (a == null) return -1;
|
|
9508
|
+
if (b == null) return 1;
|
|
9509
|
+
if (typeof a === "number" && typeof b === "number") {
|
|
9510
|
+
return a - b;
|
|
9511
|
+
}
|
|
9175
9512
|
if (a instanceof Date && b instanceof Date) {
|
|
9176
9513
|
return a.getTime() - b.getTime();
|
|
9177
9514
|
}
|
|
@@ -9193,8 +9530,301 @@ function getHierarchicalSortConfig(sorting, columns) {
|
|
|
9193
9530
|
return sorting;
|
|
9194
9531
|
}
|
|
9195
9532
|
|
|
9533
|
+
// src/components/DataTable/hooks/useDataTableDataPipeline.ts
|
|
9534
|
+
function useDataTableDataPipeline({
|
|
9535
|
+
data,
|
|
9536
|
+
features,
|
|
9537
|
+
hierarchical,
|
|
9538
|
+
sorting,
|
|
9539
|
+
finalPaginationMode,
|
|
9540
|
+
serverData
|
|
9541
|
+
}) {
|
|
9542
|
+
const hierarchicalEnabled = Boolean(features.hierarchical && hierarchical?.enabled);
|
|
9543
|
+
const hierarchicalValidation = useMemo8(() => {
|
|
9544
|
+
if (!hierarchicalEnabled) {
|
|
9545
|
+
return { isValid: true, errors: [] };
|
|
9546
|
+
}
|
|
9547
|
+
return validateHierarchicalData(data);
|
|
9548
|
+
}, [data, hierarchicalEnabled]);
|
|
9549
|
+
const structuredHierarchicalData = useMemo8(() => {
|
|
9550
|
+
if (!hierarchicalEnabled || !hierarchicalValidation.isValid) {
|
|
9551
|
+
return data;
|
|
9552
|
+
}
|
|
9553
|
+
return sortHierarchicalDataByStructure(data);
|
|
9554
|
+
}, [data, hierarchicalEnabled, hierarchicalValidation.isValid]);
|
|
9555
|
+
const hierarchicalState = useHierarchicalState(
|
|
9556
|
+
hierarchicalEnabled && hierarchicalValidation.isValid ? structuredHierarchicalData : [],
|
|
9557
|
+
hierarchicalEnabled ? hierarchical : void 0
|
|
9558
|
+
);
|
|
9559
|
+
const baseData = useMemo8(() => {
|
|
9560
|
+
if (finalPaginationMode === "server") {
|
|
9561
|
+
return serverData?.data ?? [];
|
|
9562
|
+
}
|
|
9563
|
+
return structuredHierarchicalData;
|
|
9564
|
+
}, [finalPaginationMode, serverData?.data, structuredHierarchicalData]);
|
|
9565
|
+
const tableData = useMemo8(() => {
|
|
9566
|
+
if (!hierarchicalEnabled) {
|
|
9567
|
+
return baseData;
|
|
9568
|
+
}
|
|
9569
|
+
return hierarchicalState.visibleRows ?? [];
|
|
9570
|
+
}, [baseData, hierarchicalEnabled, hierarchicalState.visibleRows]);
|
|
9571
|
+
const sortedHierarchicalData = useMemo8(() => {
|
|
9572
|
+
if (!hierarchicalEnabled || sorting.length === 0) {
|
|
9573
|
+
return tableData;
|
|
9574
|
+
}
|
|
9575
|
+
const visibleRows = hierarchicalState.visibleRows;
|
|
9576
|
+
return sortHierarchicalDataWithSorting(visibleRows, sorting);
|
|
9577
|
+
}, [hierarchicalEnabled, hierarchicalState.visibleRows, sorting, tableData]);
|
|
9578
|
+
const finalTableData = hierarchicalEnabled && sorting.length > 0 ? sortedHierarchicalData : tableData;
|
|
9579
|
+
const dataCount = useMemo8(() => {
|
|
9580
|
+
if (finalPaginationMode === "server") {
|
|
9581
|
+
return serverData?.totalCount ?? 0;
|
|
9582
|
+
}
|
|
9583
|
+
return finalTableData?.length ?? 0;
|
|
9584
|
+
}, [finalPaginationMode, finalTableData?.length, serverData?.totalCount]);
|
|
9585
|
+
return {
|
|
9586
|
+
finalTableData,
|
|
9587
|
+
dataCount,
|
|
9588
|
+
hierarchicalState: hierarchicalEnabled ? hierarchicalState : void 0,
|
|
9589
|
+
hierarchicalValidation
|
|
9590
|
+
};
|
|
9591
|
+
}
|
|
9592
|
+
|
|
9593
|
+
// src/components/DataTable/hooks/useServerSideDataEffect.ts
|
|
9594
|
+
import { useCallback as useCallback7, useEffect as useEffect10 } from "react";
|
|
9595
|
+
function useServerSideDataEffect({
|
|
9596
|
+
finalPaginationMode,
|
|
9597
|
+
serverSide,
|
|
9598
|
+
pagination,
|
|
9599
|
+
sorting,
|
|
9600
|
+
columnFilters,
|
|
9601
|
+
grouping,
|
|
9602
|
+
searchQuery,
|
|
9603
|
+
tableDataLength,
|
|
9604
|
+
fetchServerData,
|
|
9605
|
+
cleanup
|
|
9606
|
+
}) {
|
|
9607
|
+
const handleServerSideChange = useCallback7(async () => {
|
|
9608
|
+
if (finalPaginationMode !== "server" || !serverSide) {
|
|
9609
|
+
return;
|
|
9610
|
+
}
|
|
9611
|
+
const params = {
|
|
9612
|
+
pageIndex: pagination.pageIndex,
|
|
9613
|
+
pageSize: pagination.pageSize,
|
|
9614
|
+
sorting,
|
|
9615
|
+
columnFilters,
|
|
9616
|
+
globalFilter: searchQuery,
|
|
9617
|
+
grouping
|
|
9618
|
+
};
|
|
9619
|
+
await fetchServerData(params);
|
|
9620
|
+
}, [
|
|
9621
|
+
finalPaginationMode,
|
|
9622
|
+
serverSide,
|
|
9623
|
+
pagination.pageIndex,
|
|
9624
|
+
pagination.pageSize,
|
|
9625
|
+
sorting,
|
|
9626
|
+
columnFilters,
|
|
9627
|
+
searchQuery,
|
|
9628
|
+
grouping,
|
|
9629
|
+
fetchServerData
|
|
9630
|
+
]);
|
|
9631
|
+
useEffect10(() => {
|
|
9632
|
+
if (finalPaginationMode !== "server" || !serverSide) {
|
|
9633
|
+
return;
|
|
9634
|
+
}
|
|
9635
|
+
if (tableDataLength > 0) {
|
|
9636
|
+
return;
|
|
9637
|
+
}
|
|
9638
|
+
handleServerSideChange();
|
|
9639
|
+
}, [
|
|
9640
|
+
finalPaginationMode,
|
|
9641
|
+
serverSide,
|
|
9642
|
+
tableDataLength,
|
|
9643
|
+
handleServerSideChange
|
|
9644
|
+
]);
|
|
9645
|
+
useEffect10(() => () => {
|
|
9646
|
+
cleanup?.();
|
|
9647
|
+
}, [cleanup]);
|
|
9648
|
+
return handleServerSideChange;
|
|
9649
|
+
}
|
|
9650
|
+
|
|
9651
|
+
// src/components/DataTable/hooks/useEffectiveColumnOrder.ts
|
|
9652
|
+
import { useMemo as useMemo9 } from "react";
|
|
9653
|
+
function useEffectiveColumnOrder({
|
|
9654
|
+
columns,
|
|
9655
|
+
externalColumnOrder,
|
|
9656
|
+
selectionEnabled
|
|
9657
|
+
}) {
|
|
9658
|
+
const baseOrder = useMemo9(() => {
|
|
9659
|
+
if (externalColumnOrder && externalColumnOrder.length > 0) {
|
|
9660
|
+
return externalColumnOrder;
|
|
9661
|
+
}
|
|
9662
|
+
return columns.map((column) => column.id || column.accessorKey || "").filter((identifier) => Boolean(identifier));
|
|
9663
|
+
}, [columns, externalColumnOrder]);
|
|
9664
|
+
return useMemo9(() => {
|
|
9665
|
+
if (selectionEnabled && !baseOrder.includes("select")) {
|
|
9666
|
+
return ["select", ...baseOrder];
|
|
9667
|
+
}
|
|
9668
|
+
return baseOrder;
|
|
9669
|
+
}, [baseOrder, selectionEnabled]);
|
|
9670
|
+
}
|
|
9671
|
+
|
|
9672
|
+
// src/components/DataTable/hooks/useTableHandlers.ts
|
|
9673
|
+
import { useCallback as useCallback8, useMemo as useMemo10 } from "react";
|
|
9674
|
+
function useTableHandlers({
|
|
9675
|
+
state,
|
|
9676
|
+
stateSnapshot,
|
|
9677
|
+
actions,
|
|
9678
|
+
selection,
|
|
9679
|
+
onRowSelectionChange,
|
|
9680
|
+
effectiveColumnOrder,
|
|
9681
|
+
canPersistVisibility,
|
|
9682
|
+
canPersistOrder,
|
|
9683
|
+
updateSavedColumnVisibility,
|
|
9684
|
+
updateColumnOrder,
|
|
9685
|
+
onLayoutChange
|
|
9686
|
+
}) {
|
|
9687
|
+
const handleSortingChange = useCallback8((updaterOrValue) => {
|
|
9688
|
+
const nextValue = typeof updaterOrValue === "function" ? updaterOrValue(stateSnapshot.sorting) : updaterOrValue;
|
|
9689
|
+
actions.setSorting(nextValue);
|
|
9690
|
+
}, [actions, stateSnapshot.sorting]);
|
|
9691
|
+
const handleColumnFiltersChange = useCallback8((updaterOrValue) => {
|
|
9692
|
+
const nextValue = typeof updaterOrValue === "function" ? updaterOrValue(stateSnapshot.columnFilters) : updaterOrValue;
|
|
9693
|
+
actions.setColumnFilters(nextValue);
|
|
9694
|
+
}, [actions, stateSnapshot.columnFilters]);
|
|
9695
|
+
const handleColumnVisibilityChange = useCallback8((updaterOrValue) => {
|
|
9696
|
+
const nextValue = typeof updaterOrValue === "function" ? updaterOrValue(stateSnapshot.columnVisibility) : updaterOrValue;
|
|
9697
|
+
actions.setColumnVisibility(nextValue);
|
|
9698
|
+
if (canPersistVisibility) {
|
|
9699
|
+
updateSavedColumnVisibility(nextValue);
|
|
9700
|
+
}
|
|
9701
|
+
onLayoutChange?.({
|
|
9702
|
+
columnOrder: effectiveColumnOrder,
|
|
9703
|
+
columnVisibility: nextValue
|
|
9704
|
+
});
|
|
9705
|
+
}, [actions, stateSnapshot.columnVisibility, canPersistVisibility, updateSavedColumnVisibility, onLayoutChange, effectiveColumnOrder]);
|
|
9706
|
+
const handleRowSelectionChange = useCallback8((updaterOrValue) => {
|
|
9707
|
+
const currentSelection = selection ?? state.rowSelection;
|
|
9708
|
+
const nextSelection = typeof updaterOrValue === "function" ? updaterOrValue(currentSelection) : updaterOrValue;
|
|
9709
|
+
if (selection === void 0) {
|
|
9710
|
+
actions.setRowSelection(nextSelection);
|
|
9711
|
+
return;
|
|
9712
|
+
}
|
|
9713
|
+
onRowSelectionChange?.(nextSelection);
|
|
9714
|
+
}, [actions, selection, state.rowSelection, onRowSelectionChange]);
|
|
9715
|
+
const handleGroupingChange = useCallback8((updaterOrValue) => {
|
|
9716
|
+
const nextValue = typeof updaterOrValue === "function" ? updaterOrValue(stateSnapshot.grouping) : updaterOrValue;
|
|
9717
|
+
actions.setGrouping(nextValue);
|
|
9718
|
+
}, [actions, stateSnapshot.grouping]);
|
|
9719
|
+
const handleExpandedChange = useCallback8((updaterOrValue) => {
|
|
9720
|
+
const nextValue = typeof updaterOrValue === "function" ? updaterOrValue(stateSnapshot.expanded) : updaterOrValue;
|
|
9721
|
+
actions.setExpanded(nextValue);
|
|
9722
|
+
}, [actions, stateSnapshot.expanded]);
|
|
9723
|
+
const handlePaginationChange = useCallback8((updaterOrValue) => {
|
|
9724
|
+
const nextValue = typeof updaterOrValue === "function" ? updaterOrValue(stateSnapshot.pagination) : updaterOrValue;
|
|
9725
|
+
actions.setPagination(nextValue);
|
|
9726
|
+
}, [actions, stateSnapshot.pagination]);
|
|
9727
|
+
const handleColumnOrderChange = useCallback8((updaterOrValue) => {
|
|
9728
|
+
const nextValue = typeof updaterOrValue === "function" ? updaterOrValue(stateSnapshot.columnOrder) : updaterOrValue;
|
|
9729
|
+
actions.setColumnOrder(nextValue);
|
|
9730
|
+
if (canPersistOrder) {
|
|
9731
|
+
updateColumnOrder(nextValue);
|
|
9732
|
+
}
|
|
9733
|
+
onLayoutChange?.({
|
|
9734
|
+
columnOrder: nextValue,
|
|
9735
|
+
columnVisibility: stateSnapshot.columnVisibility
|
|
9736
|
+
});
|
|
9737
|
+
}, [actions, stateSnapshot.columnOrder, stateSnapshot.columnVisibility, canPersistOrder, updateColumnOrder, onLayoutChange]);
|
|
9738
|
+
return useMemo10(() => ({
|
|
9739
|
+
onSortingChange: handleSortingChange,
|
|
9740
|
+
onColumnFiltersChange: handleColumnFiltersChange,
|
|
9741
|
+
onColumnVisibilityChange: handleColumnVisibilityChange,
|
|
9742
|
+
onRowSelectionChange: handleRowSelectionChange,
|
|
9743
|
+
onGroupingChange: handleGroupingChange,
|
|
9744
|
+
onExpandedChange: handleExpandedChange,
|
|
9745
|
+
onPaginationChange: handlePaginationChange,
|
|
9746
|
+
onColumnOrderChange: handleColumnOrderChange
|
|
9747
|
+
}), [
|
|
9748
|
+
handleSortingChange,
|
|
9749
|
+
handleColumnFiltersChange,
|
|
9750
|
+
handleColumnVisibilityChange,
|
|
9751
|
+
handleRowSelectionChange,
|
|
9752
|
+
handleGroupingChange,
|
|
9753
|
+
handleExpandedChange,
|
|
9754
|
+
handlePaginationChange,
|
|
9755
|
+
handleColumnOrderChange
|
|
9756
|
+
]);
|
|
9757
|
+
}
|
|
9758
|
+
|
|
9759
|
+
// src/components/DataTable/hooks/useDataTableConfiguration.ts
|
|
9760
|
+
import { useMemo as useMemo11 } from "react";
|
|
9761
|
+
import {
|
|
9762
|
+
getCoreRowModel,
|
|
9763
|
+
getExpandedRowModel,
|
|
9764
|
+
getFilteredRowModel,
|
|
9765
|
+
getGroupedRowModel,
|
|
9766
|
+
getPaginationRowModel,
|
|
9767
|
+
getSortedRowModel
|
|
9768
|
+
} from "@tanstack/react-table";
|
|
9769
|
+
function useDataTableConfiguration({
|
|
9770
|
+
data,
|
|
9771
|
+
columns,
|
|
9772
|
+
stateSnapshot,
|
|
9773
|
+
handlers,
|
|
9774
|
+
features,
|
|
9775
|
+
getRowId,
|
|
9776
|
+
finalPaginationMode,
|
|
9777
|
+
finalDataCount,
|
|
9778
|
+
pageSize
|
|
9779
|
+
}) {
|
|
9780
|
+
return useMemo11(() => ({
|
|
9781
|
+
data,
|
|
9782
|
+
columns,
|
|
9783
|
+
state: {
|
|
9784
|
+
sorting: stateSnapshot.sorting,
|
|
9785
|
+
columnFilters: stateSnapshot.columnFilters,
|
|
9786
|
+
columnVisibility: stateSnapshot.columnVisibility,
|
|
9787
|
+
rowSelection: stateSnapshot.rowSelection,
|
|
9788
|
+
grouping: stateSnapshot.grouping,
|
|
9789
|
+
expanded: stateSnapshot.expanded,
|
|
9790
|
+
pagination: stateSnapshot.pagination,
|
|
9791
|
+
globalFilter: stateSnapshot.globalFilter,
|
|
9792
|
+
columnOrder: stateSnapshot.columnOrder
|
|
9793
|
+
},
|
|
9794
|
+
initialState: {
|
|
9795
|
+
expanded: features.grouping ? {} : void 0
|
|
9796
|
+
},
|
|
9797
|
+
enableRowSelection: features.selection,
|
|
9798
|
+
enableGrouping: features.grouping,
|
|
9799
|
+
getRowId,
|
|
9800
|
+
...handlers,
|
|
9801
|
+
getCoreRowModel: getCoreRowModel(),
|
|
9802
|
+
getFilteredRowModel: finalPaginationMode === "client" ? getFilteredRowModel() : void 0,
|
|
9803
|
+
getSortedRowModel: finalPaginationMode === "client" ? getSortedRowModel() : void 0,
|
|
9804
|
+
getPaginationRowModel: features.pagination ? getPaginationRowModel() : void 0,
|
|
9805
|
+
getGroupedRowModel: features.grouping ? getGroupedRowModel() : void 0,
|
|
9806
|
+
getExpandedRowModel: features.grouping ? getExpandedRowModel() : void 0,
|
|
9807
|
+
manualSorting: finalPaginationMode === "server",
|
|
9808
|
+
manualFiltering: finalPaginationMode === "server",
|
|
9809
|
+
manualPagination: finalPaginationMode === "server",
|
|
9810
|
+
pageCount: finalPaginationMode === "server" ? Math.ceil(finalDataCount / pageSize) : void 0
|
|
9811
|
+
}), [
|
|
9812
|
+
data,
|
|
9813
|
+
columns,
|
|
9814
|
+
stateSnapshot,
|
|
9815
|
+
handlers,
|
|
9816
|
+
features.selection,
|
|
9817
|
+
features.grouping,
|
|
9818
|
+
features.pagination,
|
|
9819
|
+
getRowId,
|
|
9820
|
+
finalPaginationMode,
|
|
9821
|
+
finalDataCount,
|
|
9822
|
+
pageSize
|
|
9823
|
+
]);
|
|
9824
|
+
}
|
|
9825
|
+
|
|
9196
9826
|
// src/components/Card/Card.tsx
|
|
9197
|
-
import * as
|
|
9827
|
+
import * as React15 from "react";
|
|
9198
9828
|
import { jsx as jsx22 } from "react/jsx-runtime";
|
|
9199
9829
|
function getCardClasses(variant = "default", size = "default") {
|
|
9200
9830
|
const baseClasses = "rounded-lg border bg-card text-card-foreground shadow-sm";
|
|
@@ -9210,7 +9840,7 @@ function getCardClasses(variant = "default", size = "default") {
|
|
|
9210
9840
|
};
|
|
9211
9841
|
return `${baseClasses} ${variantClasses[variant]} ${sizeClasses2[size]}`;
|
|
9212
9842
|
}
|
|
9213
|
-
var Card =
|
|
9843
|
+
var Card = React15.forwardRef(({ className, variant, size, ...props }, ref) => /* @__PURE__ */ jsx22(
|
|
9214
9844
|
"article",
|
|
9215
9845
|
{
|
|
9216
9846
|
ref,
|
|
@@ -9223,7 +9853,7 @@ var Card = React13.forwardRef(({ className, variant, size, ...props }, ref) => /
|
|
|
9223
9853
|
}
|
|
9224
9854
|
));
|
|
9225
9855
|
Card.displayName = "Card";
|
|
9226
|
-
var CardHeader =
|
|
9856
|
+
var CardHeader = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx22(
|
|
9227
9857
|
"header",
|
|
9228
9858
|
{
|
|
9229
9859
|
ref,
|
|
@@ -9232,7 +9862,7 @@ var CardHeader = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE
|
|
|
9232
9862
|
}
|
|
9233
9863
|
));
|
|
9234
9864
|
CardHeader.displayName = "CardHeader";
|
|
9235
|
-
var CardTitle =
|
|
9865
|
+
var CardTitle = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx22(
|
|
9236
9866
|
"h3",
|
|
9237
9867
|
{
|
|
9238
9868
|
ref,
|
|
@@ -9244,7 +9874,7 @@ var CardTitle = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE_
|
|
|
9244
9874
|
}
|
|
9245
9875
|
));
|
|
9246
9876
|
CardTitle.displayName = "CardTitle";
|
|
9247
|
-
var CardDescription =
|
|
9877
|
+
var CardDescription = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx22(
|
|
9248
9878
|
"p",
|
|
9249
9879
|
{
|
|
9250
9880
|
ref,
|
|
@@ -9253,7 +9883,7 @@ var CardDescription = React13.forwardRef(({ className, ...props }, ref) => /* @_
|
|
|
9253
9883
|
}
|
|
9254
9884
|
));
|
|
9255
9885
|
CardDescription.displayName = "CardDescription";
|
|
9256
|
-
var CardContent =
|
|
9886
|
+
var CardContent = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx22(
|
|
9257
9887
|
"main",
|
|
9258
9888
|
{
|
|
9259
9889
|
ref,
|
|
@@ -9262,7 +9892,7 @@ var CardContent = React13.forwardRef(({ className, ...props }, ref) => /* @__PUR
|
|
|
9262
9892
|
}
|
|
9263
9893
|
));
|
|
9264
9894
|
CardContent.displayName = "CardContent";
|
|
9265
|
-
var CardFooter =
|
|
9895
|
+
var CardFooter = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx22(
|
|
9266
9896
|
"footer",
|
|
9267
9897
|
{
|
|
9268
9898
|
ref,
|
|
@@ -9271,7 +9901,7 @@ var CardFooter = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE
|
|
|
9271
9901
|
}
|
|
9272
9902
|
));
|
|
9273
9903
|
CardFooter.displayName = "CardFooter";
|
|
9274
|
-
var CardActions =
|
|
9904
|
+
var CardActions = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx22(
|
|
9275
9905
|
"nav",
|
|
9276
9906
|
{
|
|
9277
9907
|
ref,
|
|
@@ -9282,7 +9912,7 @@ var CardActions = React13.forwardRef(({ className, ...props }, ref) => /* @__PUR
|
|
|
9282
9912
|
}
|
|
9283
9913
|
));
|
|
9284
9914
|
CardActions.displayName = "CardActions";
|
|
9285
|
-
var HoverCard =
|
|
9915
|
+
var HoverCard = React15.forwardRef(({ children, className, ...props }, ref) => {
|
|
9286
9916
|
return /* @__PURE__ */ jsx22(
|
|
9287
9917
|
"section",
|
|
9288
9918
|
{
|
|
@@ -9294,7 +9924,7 @@ var HoverCard = React13.forwardRef(({ children, className, ...props }, ref) => {
|
|
|
9294
9924
|
);
|
|
9295
9925
|
});
|
|
9296
9926
|
HoverCard.displayName = "HoverCard";
|
|
9297
|
-
var HoverCardTrigger =
|
|
9927
|
+
var HoverCardTrigger = React15.forwardRef(({ className, asChild, children, ...props }, ref) => {
|
|
9298
9928
|
if (asChild) {
|
|
9299
9929
|
return /* @__PURE__ */ jsx22("span", { className: cn("cursor-pointer", className), children });
|
|
9300
9930
|
}
|
|
@@ -9313,7 +9943,7 @@ var HoverCardTrigger = React13.forwardRef(({ className, asChild, children, ...pr
|
|
|
9313
9943
|
);
|
|
9314
9944
|
});
|
|
9315
9945
|
HoverCardTrigger.displayName = "HoverCardTrigger";
|
|
9316
|
-
var HoverCardContent =
|
|
9946
|
+
var HoverCardContent = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx22(
|
|
9317
9947
|
"aside",
|
|
9318
9948
|
{
|
|
9319
9949
|
ref,
|
|
@@ -9342,14 +9972,14 @@ function AccessDeniedPage({
|
|
|
9342
9972
|
const handleRetry = () => {
|
|
9343
9973
|
if (onRetry) {
|
|
9344
9974
|
onRetry();
|
|
9345
|
-
} else {
|
|
9975
|
+
} else if (typeof window !== "undefined") {
|
|
9346
9976
|
window.location.reload();
|
|
9347
9977
|
}
|
|
9348
9978
|
};
|
|
9349
9979
|
const handleBack = () => {
|
|
9350
9980
|
if (onBack) {
|
|
9351
9981
|
onBack();
|
|
9352
|
-
} else {
|
|
9982
|
+
} else if (typeof window !== "undefined") {
|
|
9353
9983
|
window.history.back();
|
|
9354
9984
|
}
|
|
9355
9985
|
};
|
|
@@ -9401,31 +10031,76 @@ function AccessDeniedPage({
|
|
|
9401
10031
|
}
|
|
9402
10032
|
|
|
9403
10033
|
// src/components/DataTable/utils/exportUtils.ts
|
|
10034
|
+
function escapeCSVValue(value, sanitizeForSecurity = true) {
|
|
10035
|
+
if (value === null || value === void 0) {
|
|
10036
|
+
return sanitizeForSecurity ? '""' : "";
|
|
10037
|
+
}
|
|
10038
|
+
let stringValue = String(value);
|
|
10039
|
+
if (sanitizeForSecurity) {
|
|
10040
|
+
if (/^[=+\-@]/.test(stringValue) || stringValue.startsWith(" ")) {
|
|
10041
|
+
stringValue = "'" + stringValue;
|
|
10042
|
+
}
|
|
10043
|
+
stringValue = stringValue.replace(/[\x00-\x08\x0B-\x0C\x0E-\x1F]/g, "");
|
|
10044
|
+
const escaped = stringValue.replace(/"/g, '""');
|
|
10045
|
+
return `"${escaped}"`;
|
|
10046
|
+
} else {
|
|
10047
|
+
const escaped = stringValue.replace(/"/g, '""');
|
|
10048
|
+
return `"${escaped}"`;
|
|
10049
|
+
}
|
|
10050
|
+
}
|
|
10051
|
+
function formatLocaleValue(value, locale) {
|
|
10052
|
+
if (value === null || value === void 0) {
|
|
10053
|
+
return "";
|
|
10054
|
+
}
|
|
10055
|
+
if (typeof value === "number") {
|
|
10056
|
+
return new Intl.NumberFormat(locale).format(value);
|
|
10057
|
+
}
|
|
10058
|
+
if (value instanceof Date) {
|
|
10059
|
+
return new Intl.DateTimeFormat(locale).format(value);
|
|
10060
|
+
}
|
|
10061
|
+
if (typeof value === "boolean") {
|
|
10062
|
+
return "";
|
|
10063
|
+
}
|
|
10064
|
+
return String(value);
|
|
10065
|
+
}
|
|
9404
10066
|
function generateCSVContent(data, columns, options = {}) {
|
|
9405
10067
|
if (!data.length) return "";
|
|
9406
|
-
const {
|
|
9407
|
-
|
|
10068
|
+
const {
|
|
10069
|
+
includeHeaders = true,
|
|
10070
|
+
locale,
|
|
10071
|
+
sanitizeForSecurity = true
|
|
10072
|
+
} = options;
|
|
10073
|
+
const headers = columns.map((col) => {
|
|
10074
|
+
const headerValue = col.header || col.id || "Column";
|
|
10075
|
+
return escapeCSVValue(headerValue, sanitizeForSecurity);
|
|
10076
|
+
});
|
|
9408
10077
|
const csvData = data.map((row) => {
|
|
9409
10078
|
return columns.map((col) => {
|
|
9410
10079
|
const key = col.accessorKey || col.id;
|
|
9411
|
-
|
|
9412
|
-
|
|
9413
|
-
|
|
10080
|
+
let value = key ? row[key] : void 0;
|
|
10081
|
+
if (locale && (typeof value === "number" || value instanceof Date || typeof value === "boolean")) {
|
|
10082
|
+
value = formatLocaleValue(value, locale);
|
|
10083
|
+
}
|
|
10084
|
+
return escapeCSVValue(value, sanitizeForSecurity);
|
|
9414
10085
|
}).join(",");
|
|
9415
10086
|
});
|
|
9416
10087
|
const csvContent = includeHeaders ? [headers.join(","), ...csvData].join("\n") : csvData.join("\n");
|
|
9417
10088
|
return csvContent;
|
|
9418
10089
|
}
|
|
9419
|
-
function exportToCSV(data, columns, filename = "download.csv") {
|
|
10090
|
+
function exportToCSV(data, columns, filename = "download.csv", options = {}) {
|
|
10091
|
+
const logger = createLogger("ExportUtils");
|
|
9420
10092
|
return new Promise((resolve, reject) => {
|
|
9421
10093
|
try {
|
|
10094
|
+
if (typeof window === "undefined") {
|
|
10095
|
+
throw new Error("CSV export is only available in browser environments");
|
|
10096
|
+
}
|
|
9422
10097
|
if (!data || data.length === 0) {
|
|
9423
10098
|
throw new Error("No data to export");
|
|
9424
10099
|
}
|
|
9425
10100
|
if (!columns || columns.length === 0) {
|
|
9426
10101
|
throw new Error("No columns defined for export");
|
|
9427
10102
|
}
|
|
9428
|
-
const csvContent = generateCSVContent(data, columns);
|
|
10103
|
+
const csvContent = generateCSVContent(data, columns, options);
|
|
9429
10104
|
const blob = new Blob([csvContent], { type: "text/csv;charset=utf-8;" });
|
|
9430
10105
|
const link = document.createElement("a");
|
|
9431
10106
|
const url = URL.createObjectURL(blob);
|
|
@@ -9442,7 +10117,7 @@ function exportToCSV(data, columns, filename = "download.csv") {
|
|
|
9442
10117
|
link.click();
|
|
9443
10118
|
document.body.removeChild(link);
|
|
9444
10119
|
} catch (error) {
|
|
9445
|
-
|
|
10120
|
+
logger.error("Failed to export data to CSV:", error);
|
|
9446
10121
|
reject(error);
|
|
9447
10122
|
}
|
|
9448
10123
|
});
|
|
@@ -9453,8 +10128,36 @@ init_UnifiedAuthProvider();
|
|
|
9453
10128
|
|
|
9454
10129
|
// src/components/DataTable/hooks/useDataTablePermissions.ts
|
|
9455
10130
|
init_UnifiedAuthProvider();
|
|
9456
|
-
import { useMemo as
|
|
9457
|
-
|
|
10131
|
+
import { useMemo as useMemo12, useRef as useRef5 } from "react";
|
|
10132
|
+
|
|
10133
|
+
// src/components/DataTable/types.ts
|
|
10134
|
+
var defaultDataTableFeatures = {
|
|
10135
|
+
search: false,
|
|
10136
|
+
pagination: false,
|
|
10137
|
+
sorting: false,
|
|
10138
|
+
filtering: false,
|
|
10139
|
+
import: false,
|
|
10140
|
+
export: false,
|
|
10141
|
+
selection: false,
|
|
10142
|
+
creation: false,
|
|
10143
|
+
editing: false,
|
|
10144
|
+
deletion: false,
|
|
10145
|
+
deleteSelected: false,
|
|
10146
|
+
grouping: false,
|
|
10147
|
+
columnVisibility: false,
|
|
10148
|
+
columnReordering: false,
|
|
10149
|
+
hierarchical: false
|
|
10150
|
+
};
|
|
10151
|
+
function normalizeDataTableFeatures(features) {
|
|
10152
|
+
return {
|
|
10153
|
+
...defaultDataTableFeatures,
|
|
10154
|
+
...features ?? {}
|
|
10155
|
+
};
|
|
10156
|
+
}
|
|
10157
|
+
|
|
10158
|
+
// src/components/DataTable/hooks/useDataTablePermissions.ts
|
|
10159
|
+
function useDataTablePermissions(rbac, features = {}) {
|
|
10160
|
+
const logger = createLogger("DataTablePermissions");
|
|
9458
10161
|
const authResult = useUnifiedAuth();
|
|
9459
10162
|
const user = authResult.user;
|
|
9460
10163
|
const pageId = rbac?.pageId;
|
|
@@ -9463,11 +10166,18 @@ function useDataTablePermissions(rbac, features) {
|
|
|
9463
10166
|
throw new Error("DataTable requires either rbac.pageId or rbac.pageName for permission checking");
|
|
9464
10167
|
}
|
|
9465
10168
|
const effectivePageId = pageId || pageName;
|
|
9466
|
-
const {
|
|
9467
|
-
|
|
10169
|
+
const { selectedOrganisation, selectedEvent, supabase, organisations } = useUnifiedAuth();
|
|
10170
|
+
logger.debug("Organisation context:", {
|
|
10171
|
+
hasSelectedOrg: !!selectedOrganisation,
|
|
10172
|
+
selectedOrgId: selectedOrganisation?.id,
|
|
10173
|
+
hasOrganisations: organisations?.length > 0,
|
|
10174
|
+
organisationCount: organisations?.length,
|
|
10175
|
+
selectedEvent: selectedEvent?.event_id
|
|
10176
|
+
});
|
|
10177
|
+
const { resolvedScope: rawResolvedScope, isLoading: scopeLoading } = useResolvedScope({
|
|
9468
10178
|
supabase,
|
|
9469
|
-
selectedOrganisationId,
|
|
9470
|
-
selectedEventId
|
|
10179
|
+
selectedOrganisationId: selectedOrganisation?.id || null,
|
|
10180
|
+
selectedEventId: selectedEvent?.event_id || null
|
|
9471
10181
|
});
|
|
9472
10182
|
const stableScopeRef = useRef5({
|
|
9473
10183
|
organisationId: "",
|
|
@@ -9491,26 +10201,46 @@ function useDataTablePermissions(rbac, features) {
|
|
|
9491
10201
|
stableScopeRef.current = { organisationId: "", appId: "", eventId: void 0 };
|
|
9492
10202
|
}
|
|
9493
10203
|
const stableScope = stableScopeRef.current;
|
|
9494
|
-
const effectiveScope = stableScope.organisationId ? stableScope :
|
|
10204
|
+
const effectiveScope = !scopeLoading && stableScope.organisationId ? stableScope : null;
|
|
10205
|
+
const userId = user?.id || "";
|
|
10206
|
+
const readPermission = `read:page.${effectivePageId}`;
|
|
10207
|
+
const createPermission = `create:page.${effectivePageId}`;
|
|
10208
|
+
const updatePermission = `update:page.${effectivePageId}`;
|
|
10209
|
+
const deletePermission = `delete:page.${effectivePageId}`;
|
|
10210
|
+
const consistentScope = effectiveScope || { organisationId: "", eventId: void 0, appId: void 0 };
|
|
9495
10211
|
const permissions = {
|
|
9496
|
-
canRead: useCan(
|
|
9497
|
-
canCreate: useCan(
|
|
9498
|
-
canUpdate: useCan(
|
|
9499
|
-
canDelete: useCan(
|
|
9500
|
-
canExport: useCan(
|
|
10212
|
+
canRead: useCan(userId, consistentScope, readPermission, effectivePageId, true),
|
|
10213
|
+
canCreate: useCan(userId, consistentScope, createPermission, effectivePageId, true),
|
|
10214
|
+
canUpdate: useCan(userId, consistentScope, updatePermission, effectivePageId, true),
|
|
10215
|
+
canDelete: useCan(userId, consistentScope, deletePermission, effectivePageId, true),
|
|
10216
|
+
canExport: useCan(userId, consistentScope, readPermission, effectivePageId, true),
|
|
9501
10217
|
// Use read permission for export
|
|
9502
|
-
canImport: useCan(
|
|
10218
|
+
canImport: useCan(userId, consistentScope, createPermission, effectivePageId, true)
|
|
9503
10219
|
// Use create permission for import
|
|
9504
10220
|
};
|
|
9505
|
-
|
|
9506
|
-
|
|
9507
|
-
|
|
9508
|
-
|
|
9509
|
-
|
|
9510
|
-
|
|
9511
|
-
|
|
9512
|
-
|
|
9513
|
-
|
|
10221
|
+
logger.debug("Permission check results:", {
|
|
10222
|
+
canRead: permissions.canRead.can,
|
|
10223
|
+
canReadLoading: permissions.canRead.isLoading,
|
|
10224
|
+
canReadError: permissions.canRead.error?.message,
|
|
10225
|
+
canCreate: permissions.canCreate.can,
|
|
10226
|
+
pageName: effectivePageId,
|
|
10227
|
+
scope: consistentScope,
|
|
10228
|
+
hasValidScope: !!effectiveScope,
|
|
10229
|
+
scopeLoading
|
|
10230
|
+
});
|
|
10231
|
+
const normalizedFeatures = useMemo12(
|
|
10232
|
+
() => normalizeDataTableFeatures(features),
|
|
10233
|
+
[features]
|
|
10234
|
+
);
|
|
10235
|
+
const secureFeatures = useMemo12(() => ({
|
|
10236
|
+
...normalizedFeatures,
|
|
10237
|
+
creation: normalizedFeatures.creation && permissions.canCreate.can,
|
|
10238
|
+
editing: normalizedFeatures.editing && permissions.canUpdate.can,
|
|
10239
|
+
deletion: normalizedFeatures.deletion && permissions.canDelete.can,
|
|
10240
|
+
deleteSelected: normalizedFeatures.deleteSelected && permissions.canDelete.can,
|
|
10241
|
+
export: normalizedFeatures.export && permissions.canExport.can,
|
|
10242
|
+
import: normalizedFeatures.import && permissions.canImport.can
|
|
10243
|
+
}), [normalizedFeatures, permissions.canCreate.can, permissions.canUpdate.can, permissions.canDelete.can, permissions.canExport.can, permissions.canImport.can]);
|
|
9514
10244
|
return {
|
|
9515
10245
|
permissions,
|
|
9516
10246
|
secureFeatures,
|
|
@@ -9519,7 +10249,7 @@ function useDataTablePermissions(rbac, features) {
|
|
|
9519
10249
|
}
|
|
9520
10250
|
|
|
9521
10251
|
// src/components/DataTable/hooks/useTableColumns.ts
|
|
9522
|
-
import
|
|
10252
|
+
import React16, { useMemo as useMemo13 } from "react";
|
|
9523
10253
|
|
|
9524
10254
|
// src/components/DataTable/core/ColumnFactory.ts
|
|
9525
10255
|
var ColumnFactory = class {
|
|
@@ -9647,7 +10377,8 @@ var ColumnFactory = class {
|
|
|
9647
10377
|
},
|
|
9648
10378
|
size: options.size || 150,
|
|
9649
10379
|
minSize: options.minSize || 100,
|
|
9650
|
-
maxSize: options.maxSize || 200
|
|
10380
|
+
maxSize: options.maxSize || 200,
|
|
10381
|
+
meta: options.meta
|
|
9651
10382
|
};
|
|
9652
10383
|
}
|
|
9653
10384
|
/**
|
|
@@ -9699,7 +10430,7 @@ function useTableColumns({
|
|
|
9699
10430
|
effectiveActions,
|
|
9700
10431
|
columnOrder
|
|
9701
10432
|
}) {
|
|
9702
|
-
const enhancedColumns =
|
|
10433
|
+
const enhancedColumns = useMemo13(() => {
|
|
9703
10434
|
const baseColumns = [...columns].map((column) => ({
|
|
9704
10435
|
...column,
|
|
9705
10436
|
enableSorting: features.sorting && column.enableSorting !== false,
|
|
@@ -9711,14 +10442,14 @@ function useTableColumns({
|
|
|
9711
10442
|
header: ({ table }) => {
|
|
9712
10443
|
const isAllSelected = table.getIsAllPageRowsSelected();
|
|
9713
10444
|
const isSomeSelected = table.getIsSomePageRowsSelected();
|
|
9714
|
-
return
|
|
10445
|
+
return React16.createElement(Checkbox, {
|
|
9715
10446
|
checked: isAllSelected ? true : isSomeSelected ? "indeterminate" : false,
|
|
9716
10447
|
onCheckedChange: (value) => table.toggleAllPageRowsSelected(!!value),
|
|
9717
10448
|
"aria-label": "Select all"
|
|
9718
10449
|
});
|
|
9719
10450
|
},
|
|
9720
10451
|
cell: ({ row }) => {
|
|
9721
|
-
return
|
|
10452
|
+
return React16.createElement(Checkbox, {
|
|
9722
10453
|
checked: row.getIsSelected(),
|
|
9723
10454
|
onCheckedChange: (value) => row.toggleSelected(!!value),
|
|
9724
10455
|
"aria-label": "Select row"
|
|
@@ -9734,7 +10465,11 @@ function useTableColumns({
|
|
|
9734
10465
|
} : null;
|
|
9735
10466
|
const actionsColumn = effectiveActions.length > 0 ? ColumnFactory.createActionColumn(effectiveActions, {
|
|
9736
10467
|
header: "Actions",
|
|
9737
|
-
size:
|
|
10468
|
+
size: 1,
|
|
10469
|
+
// Shrink to fit content
|
|
10470
|
+
minSize: 0,
|
|
10471
|
+
maxSize: 0,
|
|
10472
|
+
meta: { align: "right" }
|
|
9738
10473
|
}) : null;
|
|
9739
10474
|
const finalColumns = [];
|
|
9740
10475
|
if (columnOrder && columnOrder.length > 0) {
|
|
@@ -9754,34 +10489,471 @@ function useTableColumns({
|
|
|
9754
10489
|
if (dataColumn) {
|
|
9755
10490
|
finalColumns.push(dataColumn);
|
|
9756
10491
|
}
|
|
9757
|
-
}
|
|
9758
|
-
}
|
|
9759
|
-
const remainingDataColumns = baseColumns.filter((col) => {
|
|
9760
|
-
const colId = col.id ? String(col.id) : "accessorKey" in col ? String(col.accessorKey) : "";
|
|
9761
|
-
return !usedColumnIds.has(colId);
|
|
9762
|
-
});
|
|
9763
|
-
finalColumns.push(...remainingDataColumns);
|
|
9764
|
-
if (actionsColumn && !usedColumnIds.has("actions")) {
|
|
9765
|
-
finalColumns.push(actionsColumn);
|
|
9766
|
-
}
|
|
9767
|
-
} else {
|
|
9768
|
-
if (selectionColumn) {
|
|
9769
|
-
finalColumns.push(selectionColumn);
|
|
10492
|
+
}
|
|
10493
|
+
}
|
|
10494
|
+
const remainingDataColumns = baseColumns.filter((col) => {
|
|
10495
|
+
const colId = col.id ? String(col.id) : "accessorKey" in col ? String(col.accessorKey) : "";
|
|
10496
|
+
return !usedColumnIds.has(colId);
|
|
10497
|
+
});
|
|
10498
|
+
finalColumns.push(...remainingDataColumns);
|
|
10499
|
+
if (actionsColumn && !usedColumnIds.has("actions")) {
|
|
10500
|
+
finalColumns.push(actionsColumn);
|
|
10501
|
+
}
|
|
10502
|
+
} else {
|
|
10503
|
+
if (selectionColumn) {
|
|
10504
|
+
finalColumns.push(selectionColumn);
|
|
10505
|
+
}
|
|
10506
|
+
finalColumns.push(...baseColumns);
|
|
10507
|
+
if (actionsColumn) {
|
|
10508
|
+
finalColumns.push(actionsColumn);
|
|
10509
|
+
}
|
|
10510
|
+
}
|
|
10511
|
+
return finalColumns;
|
|
10512
|
+
}, [columns, features, effectiveActions, columnOrder]);
|
|
10513
|
+
return {
|
|
10514
|
+
enhancedColumns
|
|
10515
|
+
};
|
|
10516
|
+
}
|
|
10517
|
+
|
|
10518
|
+
// src/components/DataTable/utils/a11yUtils.ts
|
|
10519
|
+
var liveRegion = null;
|
|
10520
|
+
function initializeLiveRegion() {
|
|
10521
|
+
if (typeof window === "undefined") return null;
|
|
10522
|
+
if (liveRegion && document.contains(liveRegion)) {
|
|
10523
|
+
return liveRegion;
|
|
10524
|
+
}
|
|
10525
|
+
liveRegion = document.createElement("div");
|
|
10526
|
+
liveRegion.setAttribute("aria-live", "polite");
|
|
10527
|
+
liveRegion.setAttribute("aria-atomic", "true");
|
|
10528
|
+
liveRegion.setAttribute("class", "sr-only");
|
|
10529
|
+
liveRegion.style.position = "absolute";
|
|
10530
|
+
liveRegion.style.left = "-10000px";
|
|
10531
|
+
liveRegion.style.width = "1px";
|
|
10532
|
+
liveRegion.style.height = "1px";
|
|
10533
|
+
liveRegion.style.overflow = "hidden";
|
|
10534
|
+
document.body.appendChild(liveRegion);
|
|
10535
|
+
return liveRegion;
|
|
10536
|
+
}
|
|
10537
|
+
function cleanupLiveRegion() {
|
|
10538
|
+
if (typeof window === "undefined") return;
|
|
10539
|
+
if (liveRegion && document.contains(liveRegion)) {
|
|
10540
|
+
document.body.removeChild(liveRegion);
|
|
10541
|
+
liveRegion = null;
|
|
10542
|
+
}
|
|
10543
|
+
}
|
|
10544
|
+
function announce(message, priority = "polite") {
|
|
10545
|
+
if (!message.trim() || typeof window === "undefined") return;
|
|
10546
|
+
const region = liveRegion || initializeLiveRegion();
|
|
10547
|
+
if (!region) return;
|
|
10548
|
+
if (region.getAttribute("aria-live") !== priority) {
|
|
10549
|
+
region.setAttribute("aria-live", priority);
|
|
10550
|
+
}
|
|
10551
|
+
region.textContent = "";
|
|
10552
|
+
setTimeout(() => {
|
|
10553
|
+
region.textContent = message;
|
|
10554
|
+
}, 100);
|
|
10555
|
+
setTimeout(() => {
|
|
10556
|
+
if (region.textContent === message) {
|
|
10557
|
+
region.textContent = "";
|
|
10558
|
+
}
|
|
10559
|
+
}, 1e3);
|
|
10560
|
+
}
|
|
10561
|
+
function getSortButtonLabel(columnName, currentSort) {
|
|
10562
|
+
if (currentSort === "asc") {
|
|
10563
|
+
return `Sort ${columnName} descending`;
|
|
10564
|
+
} else if (currentSort === "desc") {
|
|
10565
|
+
return `Remove sort from ${columnName}`;
|
|
10566
|
+
} else {
|
|
10567
|
+
return `Sort ${columnName} ascending`;
|
|
10568
|
+
}
|
|
10569
|
+
}
|
|
10570
|
+
function announceSortChange(columnName, sortDirection) {
|
|
10571
|
+
let message;
|
|
10572
|
+
if (sortDirection === "asc") {
|
|
10573
|
+
message = `Table sorted by ${columnName} in ascending order`;
|
|
10574
|
+
} else if (sortDirection === "desc") {
|
|
10575
|
+
message = `Table sorted by ${columnName} in descending order`;
|
|
10576
|
+
} else {
|
|
10577
|
+
message = `Sort removed from ${columnName}`;
|
|
10578
|
+
}
|
|
10579
|
+
announce(message);
|
|
10580
|
+
}
|
|
10581
|
+
function announceFilterChange(columnName, filterValue, resultCount) {
|
|
10582
|
+
if (filterValue.trim()) {
|
|
10583
|
+
const message = `Filtered ${columnName} by "${filterValue}". ${resultCount} ${resultCount === 1 ? "result" : "results"} found.`;
|
|
10584
|
+
announce(message);
|
|
10585
|
+
} else {
|
|
10586
|
+
announce(`Filter removed from ${columnName}`);
|
|
10587
|
+
}
|
|
10588
|
+
}
|
|
10589
|
+
function announceSearchResults(query, resultCount) {
|
|
10590
|
+
if (query.trim()) {
|
|
10591
|
+
const message = `Search for "${query}" returned ${resultCount} ${resultCount === 1 ? "result" : "results"}.`;
|
|
10592
|
+
announce(message);
|
|
10593
|
+
} else {
|
|
10594
|
+
announce("Search cleared");
|
|
10595
|
+
}
|
|
10596
|
+
}
|
|
10597
|
+
function announcePaginationChange(currentPage, totalPages, pageSize, totalItems) {
|
|
10598
|
+
const startItem = (currentPage - 1) * pageSize + 1;
|
|
10599
|
+
const endItem = Math.min(currentPage * pageSize, totalItems);
|
|
10600
|
+
const message = `Page ${currentPage} of ${totalPages}. Showing items ${startItem} to ${endItem} of ${totalItems}.`;
|
|
10601
|
+
announce(message);
|
|
10602
|
+
}
|
|
10603
|
+
function announceSelectionChange(selectedCount, totalCount) {
|
|
10604
|
+
if (selectedCount === 0) {
|
|
10605
|
+
announce("All rows deselected");
|
|
10606
|
+
} else if (selectedCount === totalCount) {
|
|
10607
|
+
announce(`All ${totalCount} rows selected`);
|
|
10608
|
+
} else {
|
|
10609
|
+
announce(`${selectedCount} of ${totalCount} rows selected`);
|
|
10610
|
+
}
|
|
10611
|
+
}
|
|
10612
|
+
function announceLoadingState(isLoading, hasError = false) {
|
|
10613
|
+
if (hasError) {
|
|
10614
|
+
announce("Error loading data", "assertive");
|
|
10615
|
+
} else if (isLoading) {
|
|
10616
|
+
announce("Loading data...");
|
|
10617
|
+
} else {
|
|
10618
|
+
announce("Data loaded");
|
|
10619
|
+
}
|
|
10620
|
+
}
|
|
10621
|
+
function announceBulkOperation(operation, count) {
|
|
10622
|
+
const message = `${operation} completed for ${count} ${count === 1 ? "item" : "items"}`;
|
|
10623
|
+
announce(message);
|
|
10624
|
+
}
|
|
10625
|
+
function getAriaSortValue(sortDirection) {
|
|
10626
|
+
if (sortDirection === "asc") return "ascending";
|
|
10627
|
+
if (sortDirection === "desc") return "descending";
|
|
10628
|
+
return "none";
|
|
10629
|
+
}
|
|
10630
|
+
function getRowDescription(rowIndex, totalRows, isSelected = false, isEditing = false) {
|
|
10631
|
+
let description = `Row ${rowIndex + 1} of ${totalRows}`;
|
|
10632
|
+
if (isSelected) {
|
|
10633
|
+
description += ", selected";
|
|
10634
|
+
}
|
|
10635
|
+
if (isEditing) {
|
|
10636
|
+
description += ", editing mode";
|
|
10637
|
+
}
|
|
10638
|
+
return description;
|
|
10639
|
+
}
|
|
10640
|
+
|
|
10641
|
+
// src/components/DataTable/hooks/useKeyboardNavigation.ts
|
|
10642
|
+
import { useCallback as useCallback9, useEffect as useEffect11, useRef as useRef6, useState as useState8 } from "react";
|
|
10643
|
+
function useKeyboardNavigation(rowCount, columnCount, options = {}) {
|
|
10644
|
+
const {
|
|
10645
|
+
enabled = true,
|
|
10646
|
+
announceNavigation = true,
|
|
10647
|
+
supportsColumnReorder = false,
|
|
10648
|
+
supportsColumnResize = false,
|
|
10649
|
+
onFocusChange,
|
|
10650
|
+
tableRef: externalTableRef
|
|
10651
|
+
} = options;
|
|
10652
|
+
const [state, setState] = useState8({
|
|
10653
|
+
focusedRowIndex: 0,
|
|
10654
|
+
focusedColumnIndex: 0,
|
|
10655
|
+
isNavigating: false
|
|
10656
|
+
});
|
|
10657
|
+
const internalTableRef = useRef6(null);
|
|
10658
|
+
const tableRef = externalTableRef || internalTableRef;
|
|
10659
|
+
const storedFocusRef = useRef6(null);
|
|
10660
|
+
const navigationTimeoutRef = useRef6();
|
|
10661
|
+
const getCellElement = useCallback9((rowIndex, columnIndex) => {
|
|
10662
|
+
if (!tableRef.current) return null;
|
|
10663
|
+
const tbody = tableRef.current.querySelector("tbody");
|
|
10664
|
+
if (!tbody) return null;
|
|
10665
|
+
const rows = tbody.querySelectorAll('tr[role="row"]');
|
|
10666
|
+
const row = rows[rowIndex];
|
|
10667
|
+
if (!row) return null;
|
|
10668
|
+
const cells = row.querySelectorAll('td[role="cell"], th[role="columnheader"]');
|
|
10669
|
+
return cells[columnIndex] || null;
|
|
10670
|
+
}, []);
|
|
10671
|
+
const getHeaderElement = useCallback9((columnIndex) => {
|
|
10672
|
+
if (!tableRef.current) return null;
|
|
10673
|
+
const thead = tableRef.current.querySelector("thead");
|
|
10674
|
+
if (!thead) return null;
|
|
10675
|
+
const headerRow = thead.querySelector('tr[role="row"]');
|
|
10676
|
+
if (!headerRow) return null;
|
|
10677
|
+
const headers = headerRow.querySelectorAll('th[role="columnheader"]');
|
|
10678
|
+
return headers[columnIndex] || null;
|
|
10679
|
+
}, []);
|
|
10680
|
+
const focusCell = useCallback9((rowIndex, columnIndex) => {
|
|
10681
|
+
if (!enabled) return;
|
|
10682
|
+
const clampedRowIndex = Math.max(0, Math.min(rowIndex, rowCount - 1));
|
|
10683
|
+
const clampedColumnIndex = Math.max(0, Math.min(columnIndex, columnCount - 1));
|
|
10684
|
+
setState((prev) => ({
|
|
10685
|
+
...prev,
|
|
10686
|
+
focusedRowIndex: clampedRowIndex,
|
|
10687
|
+
focusedColumnIndex: clampedColumnIndex,
|
|
10688
|
+
isNavigating: true
|
|
10689
|
+
}));
|
|
10690
|
+
const cellElement = getCellElement(clampedRowIndex, clampedColumnIndex);
|
|
10691
|
+
if (cellElement) {
|
|
10692
|
+
cellElement.focus();
|
|
10693
|
+
}
|
|
10694
|
+
onFocusChange?.(clampedRowIndex, clampedColumnIndex);
|
|
10695
|
+
if (announceNavigation) {
|
|
10696
|
+
announce(`Row ${clampedRowIndex + 1}, Column ${clampedColumnIndex + 1}`);
|
|
10697
|
+
}
|
|
10698
|
+
}, [enabled, rowCount, columnCount, getCellElement, onFocusChange, announceNavigation]);
|
|
10699
|
+
const focusNext = useCallback9(() => {
|
|
10700
|
+
const { focusedRowIndex, focusedColumnIndex } = state;
|
|
10701
|
+
if (focusedColumnIndex < columnCount - 1) {
|
|
10702
|
+
focusCell(focusedRowIndex, focusedColumnIndex + 1);
|
|
10703
|
+
} else if (focusedRowIndex < rowCount - 1) {
|
|
10704
|
+
focusCell(focusedRowIndex + 1, 0);
|
|
10705
|
+
}
|
|
10706
|
+
}, [state, columnCount, rowCount, focusCell]);
|
|
10707
|
+
const focusPrevious = useCallback9(() => {
|
|
10708
|
+
const { focusedRowIndex, focusedColumnIndex } = state;
|
|
10709
|
+
if (focusedColumnIndex > 0) {
|
|
10710
|
+
focusCell(focusedRowIndex, focusedColumnIndex - 1);
|
|
10711
|
+
} else if (focusedRowIndex > 0) {
|
|
10712
|
+
focusCell(focusedRowIndex - 1, columnCount - 1);
|
|
10713
|
+
}
|
|
10714
|
+
}, [state, columnCount, focusCell]);
|
|
10715
|
+
const focusUp = useCallback9(() => {
|
|
10716
|
+
const { focusedRowIndex, focusedColumnIndex } = state;
|
|
10717
|
+
if (focusedRowIndex > 0) {
|
|
10718
|
+
focusCell(focusedRowIndex - 1, focusedColumnIndex);
|
|
10719
|
+
}
|
|
10720
|
+
}, [state, focusCell]);
|
|
10721
|
+
const focusDown = useCallback9(() => {
|
|
10722
|
+
const { focusedRowIndex, focusedColumnIndex } = state;
|
|
10723
|
+
if (focusedRowIndex < rowCount - 1) {
|
|
10724
|
+
focusCell(focusedRowIndex + 1, focusedColumnIndex);
|
|
10725
|
+
}
|
|
10726
|
+
}, [state, rowCount, focusCell]);
|
|
10727
|
+
const focusRowStart = useCallback9(() => {
|
|
10728
|
+
const { focusedRowIndex } = state;
|
|
10729
|
+
focusCell(focusedRowIndex, 0);
|
|
10730
|
+
}, [state, focusCell]);
|
|
10731
|
+
const focusRowEnd = useCallback9(() => {
|
|
10732
|
+
const { focusedRowIndex } = state;
|
|
10733
|
+
focusCell(focusedRowIndex, columnCount - 1);
|
|
10734
|
+
}, [state, columnCount, focusCell]);
|
|
10735
|
+
const focusTableStart = useCallback9(() => {
|
|
10736
|
+
focusCell(0, 0);
|
|
10737
|
+
}, [focusCell]);
|
|
10738
|
+
const focusTableEnd = useCallback9(() => {
|
|
10739
|
+
focusCell(rowCount - 1, columnCount - 1);
|
|
10740
|
+
}, [rowCount, columnCount, focusCell]);
|
|
10741
|
+
const getCellTabIndex = useCallback9((rowIndex, columnIndex) => {
|
|
10742
|
+
if (!enabled) return -1;
|
|
10743
|
+
return state.focusedRowIndex === rowIndex && state.focusedColumnIndex === columnIndex ? 0 : -1;
|
|
10744
|
+
}, [enabled, state.focusedRowIndex, state.focusedColumnIndex]);
|
|
10745
|
+
const getCellKeyboardHandlers = useCallback9((rowIndex, columnIndex) => {
|
|
10746
|
+
const onKeyDown = (event) => {
|
|
10747
|
+
if (!enabled) return;
|
|
10748
|
+
switch (event.key) {
|
|
10749
|
+
case "ArrowRight":
|
|
10750
|
+
event.preventDefault();
|
|
10751
|
+
if (event.ctrlKey || event.metaKey) {
|
|
10752
|
+
focusRowEnd();
|
|
10753
|
+
} else {
|
|
10754
|
+
focusNext();
|
|
10755
|
+
}
|
|
10756
|
+
break;
|
|
10757
|
+
case "ArrowLeft":
|
|
10758
|
+
event.preventDefault();
|
|
10759
|
+
if (event.ctrlKey || event.metaKey) {
|
|
10760
|
+
focusRowStart();
|
|
10761
|
+
} else {
|
|
10762
|
+
focusPrevious();
|
|
10763
|
+
}
|
|
10764
|
+
break;
|
|
10765
|
+
case "ArrowDown":
|
|
10766
|
+
event.preventDefault();
|
|
10767
|
+
if (event.ctrlKey || event.metaKey) {
|
|
10768
|
+
focusTableEnd();
|
|
10769
|
+
} else {
|
|
10770
|
+
focusDown();
|
|
10771
|
+
}
|
|
10772
|
+
break;
|
|
10773
|
+
case "ArrowUp":
|
|
10774
|
+
event.preventDefault();
|
|
10775
|
+
if (event.ctrlKey || event.metaKey) {
|
|
10776
|
+
focusTableStart();
|
|
10777
|
+
} else {
|
|
10778
|
+
focusUp();
|
|
10779
|
+
}
|
|
10780
|
+
break;
|
|
10781
|
+
case "Home":
|
|
10782
|
+
event.preventDefault();
|
|
10783
|
+
if (event.ctrlKey || event.metaKey) {
|
|
10784
|
+
focusTableStart();
|
|
10785
|
+
} else {
|
|
10786
|
+
focusRowStart();
|
|
10787
|
+
}
|
|
10788
|
+
break;
|
|
10789
|
+
case "End":
|
|
10790
|
+
event.preventDefault();
|
|
10791
|
+
if (event.ctrlKey || event.metaKey) {
|
|
10792
|
+
focusTableEnd();
|
|
10793
|
+
} else {
|
|
10794
|
+
focusRowEnd();
|
|
10795
|
+
}
|
|
10796
|
+
break;
|
|
10797
|
+
case "Tab":
|
|
10798
|
+
break;
|
|
10799
|
+
default:
|
|
10800
|
+
break;
|
|
9770
10801
|
}
|
|
9771
|
-
|
|
9772
|
-
|
|
9773
|
-
|
|
10802
|
+
};
|
|
10803
|
+
const onFocus = (event) => {
|
|
10804
|
+
setState((prev) => ({
|
|
10805
|
+
...prev,
|
|
10806
|
+
focusedRowIndex: rowIndex,
|
|
10807
|
+
focusedColumnIndex: columnIndex,
|
|
10808
|
+
isNavigating: true
|
|
10809
|
+
}));
|
|
10810
|
+
onFocusChange?.(rowIndex, columnIndex);
|
|
10811
|
+
};
|
|
10812
|
+
const onBlur = (event) => {
|
|
10813
|
+
if (navigationTimeoutRef.current) {
|
|
10814
|
+
clearTimeout(navigationTimeoutRef.current);
|
|
10815
|
+
}
|
|
10816
|
+
navigationTimeoutRef.current = setTimeout(() => {
|
|
10817
|
+
setState((prev) => ({
|
|
10818
|
+
...prev,
|
|
10819
|
+
isNavigating: false
|
|
10820
|
+
}));
|
|
10821
|
+
}, 100);
|
|
10822
|
+
};
|
|
10823
|
+
return { onKeyDown, onFocus, onBlur };
|
|
10824
|
+
}, [enabled, focusNext, focusPrevious, focusUp, focusDown, focusRowStart, focusRowEnd, focusTableStart, focusTableEnd, onFocusChange]);
|
|
10825
|
+
const getHeaderKeyboardHandlers = useCallback9((columnIndex, onSort) => {
|
|
10826
|
+
const onKeyDown = (event) => {
|
|
10827
|
+
if (!enabled) return;
|
|
10828
|
+
switch (event.key) {
|
|
10829
|
+
case "Enter":
|
|
10830
|
+
case " ":
|
|
10831
|
+
event.preventDefault();
|
|
10832
|
+
onSort?.();
|
|
10833
|
+
break;
|
|
10834
|
+
case "ArrowRight":
|
|
10835
|
+
event.preventDefault();
|
|
10836
|
+
const nextHeader = getHeaderElement(columnIndex + 1);
|
|
10837
|
+
if (nextHeader) {
|
|
10838
|
+
nextHeader.focus();
|
|
10839
|
+
}
|
|
10840
|
+
break;
|
|
10841
|
+
case "ArrowLeft":
|
|
10842
|
+
event.preventDefault();
|
|
10843
|
+
const prevHeader = getHeaderElement(columnIndex - 1);
|
|
10844
|
+
if (prevHeader) {
|
|
10845
|
+
prevHeader.focus();
|
|
10846
|
+
}
|
|
10847
|
+
break;
|
|
10848
|
+
case "Home":
|
|
10849
|
+
event.preventDefault();
|
|
10850
|
+
const firstHeader = getHeaderElement(0);
|
|
10851
|
+
if (firstHeader) {
|
|
10852
|
+
firstHeader.focus();
|
|
10853
|
+
}
|
|
10854
|
+
break;
|
|
10855
|
+
case "End":
|
|
10856
|
+
event.preventDefault();
|
|
10857
|
+
const lastHeader = getHeaderElement(columnCount - 1);
|
|
10858
|
+
if (lastHeader) {
|
|
10859
|
+
lastHeader.focus();
|
|
10860
|
+
}
|
|
10861
|
+
break;
|
|
10862
|
+
// Disable unsupported keyboard operations
|
|
10863
|
+
case "r":
|
|
10864
|
+
if (!supportsColumnReorder && (event.ctrlKey || event.metaKey)) {
|
|
10865
|
+
event.preventDefault();
|
|
10866
|
+
announce("Column reordering is not supported");
|
|
10867
|
+
}
|
|
10868
|
+
break;
|
|
10869
|
+
case "=":
|
|
10870
|
+
case "+":
|
|
10871
|
+
case "-":
|
|
10872
|
+
if (!supportsColumnResize && (event.ctrlKey || event.metaKey)) {
|
|
10873
|
+
event.preventDefault();
|
|
10874
|
+
announce("Column resizing is not supported");
|
|
10875
|
+
}
|
|
10876
|
+
break;
|
|
9774
10877
|
}
|
|
10878
|
+
};
|
|
10879
|
+
const onFocus = (event) => {
|
|
10880
|
+
};
|
|
10881
|
+
return { onKeyDown, onFocus };
|
|
10882
|
+
}, [enabled, getHeaderElement, columnCount, supportsColumnReorder, supportsColumnResize]);
|
|
10883
|
+
const resetFocus = useCallback9(() => {
|
|
10884
|
+
setState({
|
|
10885
|
+
focusedRowIndex: 0,
|
|
10886
|
+
focusedColumnIndex: 0,
|
|
10887
|
+
isNavigating: false
|
|
10888
|
+
});
|
|
10889
|
+
}, []);
|
|
10890
|
+
const storeFocus = useCallback9(() => {
|
|
10891
|
+
storedFocusRef.current = {
|
|
10892
|
+
rowIndex: state.focusedRowIndex,
|
|
10893
|
+
columnIndex: state.focusedColumnIndex
|
|
10894
|
+
};
|
|
10895
|
+
}, [state.focusedRowIndex, state.focusedColumnIndex]);
|
|
10896
|
+
const restoreFocus = useCallback9(() => {
|
|
10897
|
+
if (storedFocusRef.current) {
|
|
10898
|
+
const { rowIndex, columnIndex } = storedFocusRef.current;
|
|
10899
|
+
focusCell(rowIndex, columnIndex);
|
|
10900
|
+
storedFocusRef.current = null;
|
|
9775
10901
|
}
|
|
9776
|
-
|
|
9777
|
-
|
|
10902
|
+
}, [focusCell]);
|
|
10903
|
+
useEffect11(() => {
|
|
10904
|
+
return () => {
|
|
10905
|
+
if (navigationTimeoutRef.current) {
|
|
10906
|
+
clearTimeout(navigationTimeoutRef.current);
|
|
10907
|
+
}
|
|
10908
|
+
};
|
|
10909
|
+
}, []);
|
|
9778
10910
|
return {
|
|
9779
|
-
|
|
10911
|
+
state,
|
|
10912
|
+
focusCell,
|
|
10913
|
+
focusNext,
|
|
10914
|
+
focusPrevious,
|
|
10915
|
+
focusUp,
|
|
10916
|
+
focusDown,
|
|
10917
|
+
focusRowStart,
|
|
10918
|
+
focusRowEnd,
|
|
10919
|
+
focusTableStart,
|
|
10920
|
+
focusTableEnd,
|
|
10921
|
+
getCellTabIndex,
|
|
10922
|
+
getCellKeyboardHandlers,
|
|
10923
|
+
getHeaderKeyboardHandlers,
|
|
10924
|
+
resetFocus,
|
|
10925
|
+
storeFocus,
|
|
10926
|
+
restoreFocus
|
|
9780
10927
|
};
|
|
9781
10928
|
}
|
|
9782
10929
|
|
|
9783
10930
|
// src/components/DataTable/components/DataTableCore.tsx
|
|
9784
10931
|
import { Fragment as Fragment7, jsx as jsx24, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
10932
|
+
var isCellValue = (value) => {
|
|
10933
|
+
if (value === null || value === void 0) {
|
|
10934
|
+
return true;
|
|
10935
|
+
}
|
|
10936
|
+
if (value instanceof Date) {
|
|
10937
|
+
return true;
|
|
10938
|
+
}
|
|
10939
|
+
const valueType = typeof value;
|
|
10940
|
+
return valueType === "string" || valueType === "number" || valueType === "boolean";
|
|
10941
|
+
};
|
|
10942
|
+
var toCellValueRecord = (row) => {
|
|
10943
|
+
if (typeof row !== "object" || row === null) {
|
|
10944
|
+
return {};
|
|
10945
|
+
}
|
|
10946
|
+
return Object.entries(row).reduce((accumulator, [key, entryValue]) => {
|
|
10947
|
+
if (isCellValue(entryValue)) {
|
|
10948
|
+
accumulator[key] = entryValue;
|
|
10949
|
+
} else if (entryValue && typeof entryValue === "object" && "toString" in entryValue) {
|
|
10950
|
+
accumulator[key] = String(entryValue);
|
|
10951
|
+
} else {
|
|
10952
|
+
accumulator[key] = entryValue;
|
|
10953
|
+
}
|
|
10954
|
+
return accumulator;
|
|
10955
|
+
}, {});
|
|
10956
|
+
};
|
|
9785
10957
|
function DataTableInternal({
|
|
9786
10958
|
data,
|
|
9787
10959
|
columns,
|
|
@@ -9791,7 +10963,7 @@ function DataTableInternal({
|
|
|
9791
10963
|
description,
|
|
9792
10964
|
variant = "default",
|
|
9793
10965
|
className,
|
|
9794
|
-
features,
|
|
10966
|
+
features: incomingFeatures = {},
|
|
9795
10967
|
hierarchical,
|
|
9796
10968
|
performance = {},
|
|
9797
10969
|
serverSide,
|
|
@@ -9819,23 +10991,38 @@ function DataTableInternal({
|
|
|
9819
10991
|
actions = [],
|
|
9820
10992
|
columnOrder: externalColumnOrder,
|
|
9821
10993
|
defaultGrouping,
|
|
9822
|
-
defaultSorting
|
|
10994
|
+
defaultSorting,
|
|
10995
|
+
storageKey,
|
|
10996
|
+
onLayoutChange
|
|
9823
10997
|
}) {
|
|
9824
10998
|
const authResult = useUnifiedAuth();
|
|
9825
10999
|
const user = authResult.user;
|
|
9826
|
-
const
|
|
9827
|
-
|
|
9828
|
-
|
|
9829
|
-
|
|
9830
|
-
|
|
9831
|
-
|
|
9832
|
-
|
|
9833
|
-
|
|
9834
|
-
|
|
9835
|
-
|
|
11000
|
+
const requestedFeatures = useMemo14(
|
|
11001
|
+
() => normalizeDataTableFeatures(incomingFeatures),
|
|
11002
|
+
[incomingFeatures]
|
|
11003
|
+
);
|
|
11004
|
+
const { permissions, secureFeatures, effectivePageId } = useDataTablePermissions(rbac, requestedFeatures);
|
|
11005
|
+
const effectiveColumnOrder = useEffectiveColumnOrder({
|
|
11006
|
+
columns,
|
|
11007
|
+
externalColumnOrder,
|
|
11008
|
+
selectionEnabled: secureFeatures.selection
|
|
11009
|
+
});
|
|
11010
|
+
const {
|
|
11011
|
+
columnVisibility: savedColumnVisibility,
|
|
11012
|
+
isLoaded: isColumnVisibilityLoaded,
|
|
11013
|
+
updateColumnVisibility: updateSavedColumnVisibility
|
|
11014
|
+
} = useColumnVisibilityPersistence({
|
|
11015
|
+
tableId: title ? `datatable-${title.toLowerCase().replace(/\s+/g, "-")}` : void 0,
|
|
11016
|
+
defaultVisibility: {},
|
|
11017
|
+
enablePersistence: secureFeatures.columnVisibility,
|
|
11018
|
+
storageKey
|
|
11019
|
+
});
|
|
11020
|
+
const initialColumnVisibility = useMemo14(() => {
|
|
11021
|
+
if (secureFeatures.columnVisibility && savedColumnVisibility && Object.keys(savedColumnVisibility).length > 0) {
|
|
11022
|
+
return savedColumnVisibility;
|
|
9836
11023
|
}
|
|
9837
|
-
return
|
|
9838
|
-
}, [
|
|
11024
|
+
return {};
|
|
11025
|
+
}, [secureFeatures.columnVisibility, savedColumnVisibility]);
|
|
9839
11026
|
const { state, actions: stateActions } = useDataTableState({
|
|
9840
11027
|
initialPageSize,
|
|
9841
11028
|
columnIds: effectiveColumnOrder,
|
|
@@ -9844,9 +11031,21 @@ function DataTableInternal({
|
|
|
9844
11031
|
defaultSorting: defaultSorting || [],
|
|
9845
11032
|
defaultGrouping: defaultGrouping || []
|
|
9846
11033
|
});
|
|
11034
|
+
useEffect12(() => {
|
|
11035
|
+
if (secureFeatures.columnVisibility && isColumnVisibilityLoaded && Object.keys(initialColumnVisibility).length > 0) {
|
|
11036
|
+
stateActions.setColumnVisibility(initialColumnVisibility);
|
|
11037
|
+
}
|
|
11038
|
+
}, [secureFeatures.columnVisibility, isColumnVisibilityLoaded, initialColumnVisibility, stateActions]);
|
|
11039
|
+
useEffect12(() => {
|
|
11040
|
+
initializeLiveRegion();
|
|
11041
|
+
}, []);
|
|
9847
11042
|
const rowSelection = selection !== void 0 ? selection : state.rowSelection;
|
|
9848
|
-
const
|
|
9849
|
-
|
|
11043
|
+
const resolvedGetRowId = useCallback10(
|
|
11044
|
+
(row, index) => getRowIdSafe(row, index, getRowId),
|
|
11045
|
+
[getRowId]
|
|
11046
|
+
);
|
|
11047
|
+
const hasInitializedExpansion = useRef7(false);
|
|
11048
|
+
useEffect12(() => {
|
|
9850
11049
|
if (!hasInitializedExpansion.current && defaultGrouping && defaultGrouping.length > 0) {
|
|
9851
11050
|
stateActions.setExpanded(true);
|
|
9852
11051
|
hasInitializedExpansion.current = true;
|
|
@@ -9878,8 +11077,6 @@ function DataTableInternal({
|
|
|
9878
11077
|
paginationMode: detectedMode,
|
|
9879
11078
|
isVirtualized,
|
|
9880
11079
|
pageSizeOptions: optimizedPageSizeOptions,
|
|
9881
|
-
processedData,
|
|
9882
|
-
totalCount,
|
|
9883
11080
|
isLoading: performanceLoading,
|
|
9884
11081
|
searchQuery,
|
|
9885
11082
|
setSearchQuery,
|
|
@@ -9887,22 +11084,48 @@ function DataTableInternal({
|
|
|
9887
11084
|
serverData,
|
|
9888
11085
|
cleanup
|
|
9889
11086
|
} = performanceHook;
|
|
9890
|
-
const
|
|
9891
|
-
|
|
9892
|
-
|
|
9893
|
-
|
|
9894
|
-
|
|
9895
|
-
|
|
9896
|
-
|
|
9897
|
-
|
|
9898
|
-
|
|
11087
|
+
const finalPaginationMode = paginationMode || detectedMode;
|
|
11088
|
+
const keyboardNavigation = useKeyboardNavigation(
|
|
11089
|
+
data.length,
|
|
11090
|
+
columns.length,
|
|
11091
|
+
{
|
|
11092
|
+
enabled: true,
|
|
11093
|
+
announceNavigation: true,
|
|
11094
|
+
supportsColumnReorder: secureFeatures.columnReordering,
|
|
11095
|
+
supportsColumnResize: false
|
|
11096
|
+
// Column resizing is not currently supported
|
|
9899
11097
|
}
|
|
9900
|
-
return data;
|
|
9901
|
-
}, [features.hierarchical, hierarchical?.enabled, hierarchicalValidation.isValid, data]);
|
|
9902
|
-
const hierarchicalState = useHierarchicalState(
|
|
9903
|
-
processedHierarchicalData,
|
|
9904
|
-
hierarchical
|
|
9905
11098
|
);
|
|
11099
|
+
useEffect12(() => {
|
|
11100
|
+
if (state.showImportModal) {
|
|
11101
|
+
keyboardNavigation.storeFocus();
|
|
11102
|
+
}
|
|
11103
|
+
}, [state.showImportModal, keyboardNavigation]);
|
|
11104
|
+
useEffect12(() => {
|
|
11105
|
+
if (!state.showImportModal) {
|
|
11106
|
+
setTimeout(() => {
|
|
11107
|
+
keyboardNavigation.restoreFocus();
|
|
11108
|
+
}, 100);
|
|
11109
|
+
}
|
|
11110
|
+
}, [state.showImportModal, keyboardNavigation]);
|
|
11111
|
+
const {
|
|
11112
|
+
finalTableData,
|
|
11113
|
+
dataCount: finalDataCount,
|
|
11114
|
+
hierarchicalState,
|
|
11115
|
+
hierarchicalValidation
|
|
11116
|
+
} = useDataTableDataPipeline({
|
|
11117
|
+
data,
|
|
11118
|
+
features: secureFeatures,
|
|
11119
|
+
hierarchical,
|
|
11120
|
+
sorting: state.sorting,
|
|
11121
|
+
finalPaginationMode,
|
|
11122
|
+
serverData
|
|
11123
|
+
});
|
|
11124
|
+
useEffect12(() => {
|
|
11125
|
+
if (!hierarchicalValidation.isValid && import.meta.env?.MODE === "development") {
|
|
11126
|
+
console.error("[DataTable] Hierarchical data validation failed:", hierarchicalValidation.errors);
|
|
11127
|
+
}
|
|
11128
|
+
}, [hierarchicalValidation]);
|
|
9906
11129
|
const {
|
|
9907
11130
|
columnOrder: savedColumnOrder,
|
|
9908
11131
|
isLoaded: isColumnOrderLoaded,
|
|
@@ -9910,12 +11133,17 @@ function DataTableInternal({
|
|
|
9910
11133
|
} = useColumnOrderPersistence({
|
|
9911
11134
|
tableId: title ? `datatable-${title.toLowerCase().replace(/\s+/g, "-")}` : void 0,
|
|
9912
11135
|
defaultOrder: columns.map((col) => col.id || col.accessorKey || ""),
|
|
9913
|
-
enablePersistence:
|
|
11136
|
+
enablePersistence: secureFeatures.columnReordering,
|
|
11137
|
+
storageKey
|
|
9914
11138
|
});
|
|
9915
|
-
|
|
11139
|
+
useEffect12(() => {
|
|
11140
|
+
if (secureFeatures.columnReordering && isColumnOrderLoaded && savedColumnOrder && savedColumnOrder.length > 0) {
|
|
11141
|
+
stateActions.setColumnOrder(savedColumnOrder);
|
|
11142
|
+
}
|
|
11143
|
+
}, [secureFeatures.columnReordering, isColumnOrderLoaded, savedColumnOrder, stateActions]);
|
|
9916
11144
|
const finalPageSizeOptions = optimizedPageSizeOptions;
|
|
9917
|
-
const validatedInitialPageSize =
|
|
9918
|
-
if (!
|
|
11145
|
+
const validatedInitialPageSize = useMemo14(() => {
|
|
11146
|
+
if (!secureFeatures.pagination || !finalPageSizeOptions.length) {
|
|
9919
11147
|
return initialPageSize;
|
|
9920
11148
|
}
|
|
9921
11149
|
if (finalPageSizeOptions.includes(initialPageSize)) {
|
|
@@ -9925,73 +11153,33 @@ function DataTableInternal({
|
|
|
9925
11153
|
const closestOption = sortedOptions.reduce(
|
|
9926
11154
|
(prev, curr) => Math.abs(curr - initialPageSize) < Math.abs(prev - initialPageSize) ? curr : prev
|
|
9927
11155
|
);
|
|
9928
|
-
|
|
9929
|
-
|
|
9930
|
-
|
|
11156
|
+
if (import.meta.env?.MODE === "development") {
|
|
11157
|
+
console.warn(
|
|
11158
|
+
`DataTable: initialPageSize ${initialPageSize} is not available in page size options [${finalPageSizeOptions.join(", ")}]. Using closest option: ${closestOption}`
|
|
11159
|
+
);
|
|
11160
|
+
}
|
|
9931
11161
|
return closestOption;
|
|
9932
|
-
}, [initialPageSize, finalPageSizeOptions,
|
|
11162
|
+
}, [initialPageSize, finalPageSizeOptions, secureFeatures.pagination]);
|
|
9933
11163
|
const isLoading = externalIsLoading || performanceLoading;
|
|
9934
|
-
const
|
|
9935
|
-
return finalPaginationMode === "server" ? serverData?.data || [] : processedHierarchicalData;
|
|
9936
|
-
}, [finalPaginationMode, serverData?.data, processedHierarchicalData]);
|
|
9937
|
-
const tableData = useMemo9(() => {
|
|
9938
|
-
return features.hierarchical && hierarchical?.enabled ? hierarchicalState.visibleRows : baseData;
|
|
9939
|
-
}, [features.hierarchical, hierarchical?.enabled, hierarchicalState.visibleRows, baseData]);
|
|
9940
|
-
const dataCount = useMemo9(() => {
|
|
9941
|
-
return finalPaginationMode === "server" ? serverData?.totalCount || 0 : data?.length || 0;
|
|
9942
|
-
}, [finalPaginationMode, serverData?.totalCount, data?.length]);
|
|
9943
|
-
const sortedTableData = useMemo9(() => {
|
|
9944
|
-
if (features.hierarchical && hierarchical?.enabled && sorting.length > 0) {
|
|
9945
|
-
const hierarchicalVisibleRows = hierarchicalState.visibleRows;
|
|
9946
|
-
return sortHierarchicalDataWithSorting(hierarchicalVisibleRows, sorting);
|
|
9947
|
-
}
|
|
9948
|
-
return tableData;
|
|
9949
|
-
}, [features.hierarchical, hierarchical?.enabled, hierarchicalState.visibleRows, sorting, tableData]);
|
|
9950
|
-
const finalTableData = useMemo9(() => {
|
|
9951
|
-
return features.hierarchical && hierarchical?.enabled && sorting.length > 0 ? sortedTableData : tableData;
|
|
9952
|
-
}, [features.hierarchical, hierarchical?.enabled, sorting.length, sortedTableData, tableData]);
|
|
9953
|
-
const finalDataCount = finalPaginationMode === "server" ? serverData?.totalCount || 0 : finalTableData?.length || 0;
|
|
9954
|
-
const handleSearch = useCallback6((value) => {
|
|
11164
|
+
const handleSearch = useCallback10((value) => {
|
|
9955
11165
|
stateActions.setSearchQuery(value);
|
|
9956
|
-
if (
|
|
11166
|
+
if (secureFeatures.pagination) {
|
|
9957
11167
|
stateActions.setPagination({ ...state.pagination, pageIndex: 0 });
|
|
9958
11168
|
}
|
|
9959
|
-
}, [stateActions,
|
|
9960
|
-
|
|
9961
|
-
if (finalPaginationMode !== "server" || !serverSide) return;
|
|
9962
|
-
const params = {
|
|
9963
|
-
pageIndex: state.pagination.pageIndex,
|
|
9964
|
-
pageSize: state.pagination.pageSize,
|
|
9965
|
-
sorting: state.sorting,
|
|
9966
|
-
columnFilters: state.columnFilters,
|
|
9967
|
-
globalFilter: searchQuery,
|
|
9968
|
-
grouping: state.grouping
|
|
9969
|
-
};
|
|
9970
|
-
await fetchServerData(params);
|
|
9971
|
-
}, [
|
|
11169
|
+
}, [stateActions, secureFeatures.pagination, state.pagination]);
|
|
11170
|
+
useServerSideDataEffect({
|
|
9972
11171
|
finalPaginationMode,
|
|
9973
11172
|
serverSide,
|
|
9974
|
-
state.pagination,
|
|
9975
|
-
state.sorting,
|
|
9976
|
-
state.columnFilters,
|
|
11173
|
+
pagination: state.pagination,
|
|
11174
|
+
sorting: state.sorting,
|
|
11175
|
+
columnFilters: state.columnFilters,
|
|
11176
|
+
grouping: state.grouping,
|
|
9977
11177
|
searchQuery,
|
|
9978
|
-
|
|
9979
|
-
fetchServerData
|
|
9980
|
-
|
|
9981
|
-
|
|
9982
|
-
|
|
9983
|
-
if (!serverSide) return;
|
|
9984
|
-
if (tableData && tableData.length > 0 && finalPaginationMode !== "server") return;
|
|
9985
|
-
handleServerSideChange();
|
|
9986
|
-
}, [handleServerSideChange, tableData, finalPaginationMode, serverSide]);
|
|
9987
|
-
useEffect8(() => {
|
|
9988
|
-
return () => {
|
|
9989
|
-
if (typeof cleanup === "function") {
|
|
9990
|
-
cleanup();
|
|
9991
|
-
}
|
|
9992
|
-
};
|
|
9993
|
-
}, [cleanup]);
|
|
9994
|
-
const secureHandlers = useMemo9(() => ({
|
|
11178
|
+
tableDataLength: finalTableData.length,
|
|
11179
|
+
fetchServerData,
|
|
11180
|
+
cleanup
|
|
11181
|
+
});
|
|
11182
|
+
const secureHandlers = useMemo14(() => ({
|
|
9995
11183
|
onEditRow: permissions.canUpdate.can ? onEditRow : void 0,
|
|
9996
11184
|
onDeleteRow: permissions.canDelete.can ? onDeleteRow : void 0,
|
|
9997
11185
|
onCreateRow: permissions.canCreate.can ? onCreateRow : void 0,
|
|
@@ -9999,7 +11187,7 @@ function DataTableInternal({
|
|
|
9999
11187
|
onExport: permissions.canExport.can ? onExport : void 0,
|
|
10000
11188
|
onDeleteSelected: permissions.canDelete.can ? onDeleteSelected : void 0
|
|
10001
11189
|
}), [permissions.canUpdate.can, permissions.canDelete.can, permissions.canCreate.can, permissions.canImport.can, permissions.canExport.can, onEditRow, onDeleteRow, onCreateRow, onImport, onExport, onDeleteSelected]);
|
|
10002
|
-
const effectiveActions =
|
|
11190
|
+
const effectiveActions = useMemo14(() => {
|
|
10003
11191
|
const result = [...actions];
|
|
10004
11192
|
if (import.meta.env.MODE === "development") {
|
|
10005
11193
|
console.log("[DataTable] Action Configuration Debug:", {
|
|
@@ -10025,18 +11213,9 @@ function DataTableInternal({
|
|
|
10025
11213
|
if (!permissions.canUpdate.can) {
|
|
10026
11214
|
throw new Error("Insufficient permissions to edit this resource");
|
|
10027
11215
|
}
|
|
10028
|
-
|
|
10029
|
-
|
|
10030
|
-
|
|
10031
|
-
rowId = getRowId(row, rowIndex);
|
|
10032
|
-
} else {
|
|
10033
|
-
rowId = row.id;
|
|
10034
|
-
}
|
|
10035
|
-
if (!rowId) {
|
|
10036
|
-
console.error("[DataTable] Cannot edit row: no id found. Make sure to provide getRowId or ensure row data has an id property.");
|
|
10037
|
-
return;
|
|
10038
|
-
}
|
|
10039
|
-
stateActions.setEditingRow(rowId, { ...row });
|
|
11216
|
+
const rowIndex = data.findIndex((r) => r === row);
|
|
11217
|
+
const rowId = resolvedGetRowId(row, rowIndex >= 0 ? rowIndex : 0);
|
|
11218
|
+
stateActions.setEditingRow(rowId, toCellValueRecord(row));
|
|
10040
11219
|
},
|
|
10041
11220
|
icon: Edit,
|
|
10042
11221
|
testId: "edit",
|
|
@@ -10066,81 +11245,24 @@ function DataTableInternal({
|
|
|
10066
11245
|
});
|
|
10067
11246
|
}
|
|
10068
11247
|
return result;
|
|
10069
|
-
}, [actions, secureFeatures, permissions, secureHandlers,
|
|
11248
|
+
}, [actions, secureFeatures, permissions, secureHandlers, resolvedGetRowId, stateActions, data]);
|
|
10070
11249
|
const { enhancedColumns } = useTableColumns({
|
|
10071
11250
|
columns,
|
|
10072
11251
|
features: secureFeatures,
|
|
10073
11252
|
effectiveActions,
|
|
10074
11253
|
columnOrder: state.columnOrder
|
|
10075
11254
|
});
|
|
10076
|
-
const
|
|
10077
|
-
|
|
10078
|
-
|
|
10079
|
-
|
|
10080
|
-
|
|
10081
|
-
|
|
10082
|
-
|
|
10083
|
-
|
|
10084
|
-
|
|
10085
|
-
|
|
10086
|
-
pagination: state.pagination,
|
|
10087
|
-
globalFilter: searchQuery,
|
|
10088
|
-
columnOrder: effectiveColumnOrder
|
|
10089
|
-
},
|
|
10090
|
-
initialState: {
|
|
10091
|
-
expanded: features.grouping ? {} : void 0
|
|
10092
|
-
},
|
|
10093
|
-
enableRowSelection: features.selection,
|
|
10094
|
-
enableGrouping: features.grouping,
|
|
10095
|
-
getRowId: getRowId || ((row) => row?.id || row?.toString() || "unknown"),
|
|
10096
|
-
onSortingChange: (updaterOrValue) => {
|
|
10097
|
-
const newSorting = typeof updaterOrValue === "function" ? updaterOrValue(state.sorting) : updaterOrValue;
|
|
10098
|
-
stateActions.setSorting(newSorting);
|
|
10099
|
-
},
|
|
10100
|
-
onColumnFiltersChange: (updaterOrValue) => {
|
|
10101
|
-
const newFilters = typeof updaterOrValue === "function" ? updaterOrValue(state.columnFilters) : updaterOrValue;
|
|
10102
|
-
stateActions.setColumnFilters(newFilters);
|
|
10103
|
-
},
|
|
10104
|
-
onColumnVisibilityChange: (updaterOrValue) => {
|
|
10105
|
-
const newVisibility = typeof updaterOrValue === "function" ? updaterOrValue(state.columnVisibility) : updaterOrValue;
|
|
10106
|
-
stateActions.setColumnVisibility(newVisibility);
|
|
10107
|
-
},
|
|
10108
|
-
onRowSelectionChange: (updaterOrValue) => {
|
|
10109
|
-
const newSelection = typeof updaterOrValue === "function" ? updaterOrValue(selection !== void 0 ? selection : state.rowSelection) : updaterOrValue;
|
|
10110
|
-
if (selection === void 0) {
|
|
10111
|
-
stateActions.setRowSelection(newSelection);
|
|
10112
|
-
}
|
|
10113
|
-
onRowSelectionChange?.(newSelection);
|
|
10114
|
-
},
|
|
10115
|
-
onGroupingChange: (updaterOrValue) => {
|
|
10116
|
-
const newGrouping = typeof updaterOrValue === "function" ? updaterOrValue(state.grouping) : updaterOrValue;
|
|
10117
|
-
stateActions.setGrouping(newGrouping);
|
|
10118
|
-
},
|
|
10119
|
-
onExpandedChange: (updaterOrValue) => {
|
|
10120
|
-
const newExpanded = typeof updaterOrValue === "function" ? updaterOrValue(state.expanded) : updaterOrValue;
|
|
10121
|
-
stateActions.setExpanded(newExpanded);
|
|
10122
|
-
},
|
|
10123
|
-
onPaginationChange: (updaterOrValue) => {
|
|
10124
|
-
const newPagination = typeof updaterOrValue === "function" ? updaterOrValue(state.pagination) : updaterOrValue;
|
|
10125
|
-
stateActions.setPagination(newPagination);
|
|
10126
|
-
},
|
|
10127
|
-
onColumnOrderChange: (updaterOrValue) => {
|
|
10128
|
-
const newOrder = typeof updaterOrValue === "function" ? updaterOrValue(state.columnOrder) : updaterOrValue;
|
|
10129
|
-
stateActions.setColumnOrder(newOrder);
|
|
10130
|
-
},
|
|
10131
|
-
getCoreRowModel: getCoreRowModel(),
|
|
10132
|
-
getFilteredRowModel: finalPaginationMode === "client" ? getFilteredRowModel() : void 0,
|
|
10133
|
-
getSortedRowModel: finalPaginationMode === "client" ? getSortedRowModel() : void 0,
|
|
10134
|
-
getPaginationRowModel: features.pagination ? getPaginationRowModel() : void 0,
|
|
10135
|
-
getGroupedRowModel: features.grouping ? getGroupedRowModel() : void 0,
|
|
10136
|
-
getExpandedRowModel: features.grouping ? getExpandedRowModel() : void 0,
|
|
10137
|
-
manualSorting: finalPaginationMode === "server",
|
|
10138
|
-
manualFiltering: finalPaginationMode === "server",
|
|
10139
|
-
manualPagination: finalPaginationMode === "server",
|
|
10140
|
-
pageCount: finalPaginationMode === "server" ? Math.ceil(dataCount / state.pagination.pageSize) : void 0
|
|
11255
|
+
const tableStateSnapshot = useMemo14(() => ({
|
|
11256
|
+
sorting: state.sorting,
|
|
11257
|
+
columnFilters: state.columnFilters,
|
|
11258
|
+
columnVisibility: state.columnVisibility,
|
|
11259
|
+
rowSelection,
|
|
11260
|
+
grouping: state.grouping,
|
|
11261
|
+
expanded: state.expanded,
|
|
11262
|
+
pagination: state.pagination,
|
|
11263
|
+
globalFilter: searchQuery,
|
|
11264
|
+
columnOrder: state.columnOrder
|
|
10141
11265
|
}), [
|
|
10142
|
-
finalTableData,
|
|
10143
|
-
enhancedColumns,
|
|
10144
11266
|
state.sorting,
|
|
10145
11267
|
state.columnFilters,
|
|
10146
11268
|
state.columnVisibility,
|
|
@@ -10149,16 +11271,32 @@ function DataTableInternal({
|
|
|
10149
11271
|
state.expanded,
|
|
10150
11272
|
state.pagination,
|
|
10151
11273
|
searchQuery,
|
|
10152
|
-
|
|
10153
|
-
|
|
10154
|
-
|
|
10155
|
-
|
|
11274
|
+
state.columnOrder
|
|
11275
|
+
]);
|
|
11276
|
+
const tableHandlers = useTableHandlers({
|
|
11277
|
+
state,
|
|
11278
|
+
stateSnapshot: tableStateSnapshot,
|
|
11279
|
+
actions: stateActions,
|
|
11280
|
+
selection,
|
|
10156
11281
|
onRowSelectionChange,
|
|
11282
|
+
effectiveColumnOrder,
|
|
11283
|
+
canPersistVisibility: secureFeatures.columnVisibility && Boolean(storageKey),
|
|
11284
|
+
canPersistOrder: secureFeatures.columnReordering && Boolean(storageKey),
|
|
11285
|
+
updateSavedColumnVisibility,
|
|
11286
|
+
updateColumnOrder,
|
|
11287
|
+
onLayoutChange
|
|
11288
|
+
});
|
|
11289
|
+
const tableConfig = useDataTableConfiguration({
|
|
11290
|
+
data: finalTableData,
|
|
11291
|
+
columns: enhancedColumns,
|
|
11292
|
+
stateSnapshot: tableStateSnapshot,
|
|
11293
|
+
handlers: tableHandlers,
|
|
11294
|
+
features: secureFeatures,
|
|
11295
|
+
getRowId: resolvedGetRowId,
|
|
10157
11296
|
finalPaginationMode,
|
|
10158
|
-
|
|
10159
|
-
|
|
10160
|
-
|
|
10161
|
-
]);
|
|
11297
|
+
finalDataCount,
|
|
11298
|
+
pageSize: state.pagination.pageSize
|
|
11299
|
+
});
|
|
10162
11300
|
const table = useReactTable(tableConfig);
|
|
10163
11301
|
if (!user) {
|
|
10164
11302
|
throw new Error("DataTable requires authenticated user for RBAC");
|
|
@@ -10177,189 +11315,228 @@ function DataTableInternal({
|
|
|
10177
11315
|
const hasSelectColumn = visibleColumns.some((col) => col.id === "select");
|
|
10178
11316
|
const hasActionsColumn = visibleColumns.some((col) => col.id === "actions");
|
|
10179
11317
|
return /* @__PURE__ */ jsxs17(Fragment7, { children: [
|
|
10180
|
-
/* @__PURE__ */ jsxs17(
|
|
10181
|
-
|
|
10182
|
-
|
|
10183
|
-
|
|
10184
|
-
|
|
10185
|
-
|
|
10186
|
-
|
|
10187
|
-
|
|
10188
|
-
|
|
10189
|
-
|
|
10190
|
-
|
|
10191
|
-
|
|
10192
|
-
|
|
10193
|
-
|
|
10194
|
-
|
|
10195
|
-
|
|
10196
|
-
|
|
10197
|
-
|
|
10198
|
-
|
|
10199
|
-
|
|
10200
|
-
|
|
10201
|
-
|
|
10202
|
-
|
|
10203
|
-
|
|
10204
|
-
|
|
10205
|
-
|
|
10206
|
-
|
|
10207
|
-
|
|
10208
|
-
|
|
10209
|
-
|
|
10210
|
-
|
|
10211
|
-
|
|
10212
|
-
|
|
10213
|
-
|
|
10214
|
-
|
|
10215
|
-
|
|
10216
|
-
|
|
10217
|
-
|
|
10218
|
-
|
|
10219
|
-
|
|
10220
|
-
|
|
10221
|
-
|
|
10222
|
-
|
|
10223
|
-
|
|
10224
|
-
|
|
10225
|
-
|
|
10226
|
-
|
|
10227
|
-
|
|
10228
|
-
|
|
10229
|
-
|
|
10230
|
-
|
|
10231
|
-
|
|
10232
|
-
|
|
10233
|
-
|
|
10234
|
-
|
|
10235
|
-
|
|
10236
|
-
|
|
10237
|
-
|
|
10238
|
-
|
|
10239
|
-
|
|
10240
|
-
|
|
11318
|
+
/* @__PURE__ */ jsxs17(
|
|
11319
|
+
"table",
|
|
11320
|
+
{
|
|
11321
|
+
className: getTableClasses({
|
|
11322
|
+
isFixed: true,
|
|
11323
|
+
variant,
|
|
11324
|
+
className: cn("border-collapse relative w-full", className)
|
|
11325
|
+
}),
|
|
11326
|
+
"aria-label": title,
|
|
11327
|
+
"aria-describedby": description ? "table-description" : void 0,
|
|
11328
|
+
"aria-busy": isLoading ? "true" : "false",
|
|
11329
|
+
children: [
|
|
11330
|
+
/* @__PURE__ */ jsxs17("caption", { className: "text-left pb-2", children: [
|
|
11331
|
+
(title || description) && /* @__PURE__ */ jsxs17(Fragment7, { children: [
|
|
11332
|
+
title && /* @__PURE__ */ jsx24("h2", { children: title }),
|
|
11333
|
+
description && /* @__PURE__ */ jsx24("p", { id: "table-description", children: description })
|
|
11334
|
+
] }),
|
|
11335
|
+
/* @__PURE__ */ jsx24(Fragment7, { children: /* @__PURE__ */ jsx24(
|
|
11336
|
+
DataTableToolbar,
|
|
11337
|
+
{
|
|
11338
|
+
features: secureFeatures,
|
|
11339
|
+
globalFilter: searchQuery,
|
|
11340
|
+
onGlobalFilterChange: handleSearch,
|
|
11341
|
+
columns,
|
|
11342
|
+
grouping: state.grouping,
|
|
11343
|
+
onGroupByChange: (columnId) => {
|
|
11344
|
+
stateActions.setGrouping(columnId ? [columnId] : []);
|
|
11345
|
+
},
|
|
11346
|
+
tableColumns: table?.getAllColumns() || [],
|
|
11347
|
+
onColumnVisibilityChange: (columnId, visible) => {
|
|
11348
|
+
stateActions.setColumnVisibility({ ...state.columnVisibility, [columnId]: visible });
|
|
11349
|
+
},
|
|
11350
|
+
onCreateRow: secureFeatures.creation && secureHandlers.onCreateRow ? () => stateActions.setCreating(true) : void 0,
|
|
11351
|
+
onImportClick: () => stateActions.setImportModal(true),
|
|
11352
|
+
onExport: secureHandlers.onExport || (async () => {
|
|
11353
|
+
try {
|
|
11354
|
+
const currentData = table.getFilteredRowModel().rows.map((row) => row.original);
|
|
11355
|
+
const visibleColumns2 = columns.filter((col) => {
|
|
11356
|
+
const column = table.getColumn(col.accessorKey);
|
|
11357
|
+
return column && column.getIsVisible();
|
|
11358
|
+
}).map((col) => ({
|
|
11359
|
+
...col,
|
|
11360
|
+
header: typeof col.header === "string" ? col.header : col.accessorKey || "Column"
|
|
11361
|
+
}));
|
|
11362
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
11363
|
+
const filename = title ? `${title.replace(/[^a-z0-9]/gi, "_").toLowerCase()}_${timestamp}.csv` : `data_export_${timestamp}.csv`;
|
|
11364
|
+
await exportToCSV(currentData, visibleColumns2, filename);
|
|
11365
|
+
toast({
|
|
11366
|
+
title: "Export Successful",
|
|
11367
|
+
description: `Data exported to ${filename}`,
|
|
11368
|
+
variant: "default"
|
|
11369
|
+
});
|
|
11370
|
+
if (import.meta.env.MODE === "development") {
|
|
11371
|
+
console.log("DataTable: Export completed successfully");
|
|
11372
|
+
}
|
|
11373
|
+
} catch (error) {
|
|
11374
|
+
console.error("DataTable: Failed to export data:", error);
|
|
11375
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
|
|
11376
|
+
toast({
|
|
11377
|
+
title: "Export Failed",
|
|
11378
|
+
description: `Failed to export data: ${errorMessage}`,
|
|
11379
|
+
variant: "destructive"
|
|
11380
|
+
});
|
|
11381
|
+
if (import.meta.env.MODE === "development") {
|
|
11382
|
+
console.error("DataTable: Export error details:", error);
|
|
11383
|
+
}
|
|
11384
|
+
}
|
|
11385
|
+
}),
|
|
11386
|
+
rowSelection,
|
|
11387
|
+
onDeleteSelected: secureHandlers.onDeleteSelected,
|
|
11388
|
+
onToggleFilterRow: () => stateActions.setFilterRow(!state.showFilterRow),
|
|
11389
|
+
showFilterRow: state.showFilterRow,
|
|
11390
|
+
rbac,
|
|
11391
|
+
permissions
|
|
11392
|
+
}
|
|
11393
|
+
) })
|
|
11394
|
+
] }),
|
|
11395
|
+
/* @__PURE__ */ jsxs17("colgroup", { children: [
|
|
11396
|
+
hasSelectColumn && /* @__PURE__ */ jsx24("col", { span: 1, "data-col-type": "select", className: "w-12" }),
|
|
11397
|
+
/* @__PURE__ */ jsx24("col", { span: dataColumns, "data-col-type": "data" }),
|
|
11398
|
+
hasActionsColumn && /* @__PURE__ */ jsx24("col", { span: 1, "data-col-type": "actions" })
|
|
11399
|
+
] }),
|
|
11400
|
+
/* @__PURE__ */ jsx24("thead", { children: table?.getHeaderGroups().map((headerGroup) => /* @__PURE__ */ jsx24("tr", { children: headerGroup.headers.filter((header) => {
|
|
11401
|
+
return typeof header.column.getIsVisible === "function" ? header.column.getIsVisible() : true;
|
|
11402
|
+
}).map((header) => {
|
|
11403
|
+
const isSortable = header.column.getCanSort();
|
|
11404
|
+
const ariaSort = isSortable ? header.column.getIsSorted() === "asc" ? "ascending" : header.column.getIsSorted() === "desc" ? "descending" : "none" : void 0;
|
|
11405
|
+
const isRightAligned = header.column.columnDef.meta?.align === "right";
|
|
11406
|
+
const handleSortClick = (event) => {
|
|
11407
|
+
const originalHandler = header.column.getToggleSortingHandler();
|
|
11408
|
+
if (originalHandler) {
|
|
11409
|
+
originalHandler(event);
|
|
11410
|
+
}
|
|
11411
|
+
const columnName = typeof header.column.columnDef.header === "string" ? header.column.columnDef.header : "column";
|
|
11412
|
+
const currentSort = header.column.getIsSorted();
|
|
11413
|
+
const newSort = currentSort === "asc" ? "desc" : currentSort === "desc" ? null : "asc";
|
|
11414
|
+
announceSortChange(columnName, newSort);
|
|
11415
|
+
};
|
|
11416
|
+
const headerKeyboardHandlers = keyboardNavigation.getHeaderKeyboardHandlers(
|
|
11417
|
+
header.index,
|
|
11418
|
+
() => {
|
|
11419
|
+
const originalHandler = header.column.getToggleSortingHandler();
|
|
11420
|
+
if (originalHandler) {
|
|
11421
|
+
originalHandler({});
|
|
10241
11422
|
}
|
|
11423
|
+
const columnName = typeof header.column.columnDef.header === "string" ? header.column.columnDef.header : "column";
|
|
11424
|
+
const currentSort = header.column.getIsSorted();
|
|
11425
|
+
const newSort = currentSort === "asc" ? "desc" : currentSort === "desc" ? null : "asc";
|
|
11426
|
+
announceSortChange(columnName, newSort);
|
|
10242
11427
|
}
|
|
10243
|
-
|
|
10244
|
-
|
|
10245
|
-
|
|
10246
|
-
onToggleFilterRow: () => stateActions.setFilterRow(!state.showFilterRow),
|
|
10247
|
-
showFilterRow: state.showFilterRow,
|
|
10248
|
-
rbac,
|
|
10249
|
-
permissions
|
|
10250
|
-
}
|
|
10251
|
-
) })
|
|
10252
|
-
] }),
|
|
10253
|
-
/* @__PURE__ */ jsxs17("colgroup", { children: [
|
|
10254
|
-
hasSelectColumn && /* @__PURE__ */ jsx24("col", { span: 1, "data-col-type": "select" }),
|
|
10255
|
-
/* @__PURE__ */ jsx24("col", { span: dataColumns, "data-col-type": "data" }),
|
|
10256
|
-
hasActionsColumn && /* @__PURE__ */ jsx24("col", { span: 1, "data-col-type": "actions" })
|
|
10257
|
-
] }),
|
|
10258
|
-
/* @__PURE__ */ jsx24("thead", { children: table?.getHeaderGroups().map((headerGroup) => /* @__PURE__ */ jsx24("tr", { children: headerGroup.headers.filter((header) => {
|
|
10259
|
-
return typeof header.column.getIsVisible === "function" ? header.column.getIsVisible() : true;
|
|
10260
|
-
}).map((header) => {
|
|
10261
|
-
const isSortable = header.column.getCanSort();
|
|
10262
|
-
const ariaSort = isSortable ? header.column.getIsSorted() === "asc" ? "ascending" : header.column.getIsSorted() === "desc" ? "descending" : "none" : void 0;
|
|
10263
|
-
return /* @__PURE__ */ jsx24(
|
|
10264
|
-
"th",
|
|
10265
|
-
{
|
|
10266
|
-
...isSortable ? { "aria-sort": ariaSort } : {},
|
|
10267
|
-
children: header.isPlaceholder ? null : isSortable ? /* @__PURE__ */ jsx24(
|
|
10268
|
-
Button,
|
|
11428
|
+
);
|
|
11429
|
+
return /* @__PURE__ */ jsx24(
|
|
11430
|
+
"th",
|
|
10269
11431
|
{
|
|
10270
|
-
|
|
10271
|
-
|
|
10272
|
-
|
|
10273
|
-
|
|
10274
|
-
|
|
10275
|
-
children:
|
|
10276
|
-
|
|
10277
|
-
|
|
10278
|
-
|
|
10279
|
-
|
|
10280
|
-
|
|
10281
|
-
|
|
10282
|
-
|
|
10283
|
-
|
|
10284
|
-
|
|
10285
|
-
|
|
10286
|
-
|
|
10287
|
-
|
|
10288
|
-
|
|
10289
|
-
|
|
10290
|
-
|
|
10291
|
-
|
|
10292
|
-
|
|
10293
|
-
|
|
10294
|
-
|
|
10295
|
-
|
|
10296
|
-
|
|
10297
|
-
|
|
10298
|
-
|
|
10299
|
-
|
|
10300
|
-
|
|
10301
|
-
|
|
10302
|
-
|
|
10303
|
-
|
|
10304
|
-
|
|
10305
|
-
|
|
10306
|
-
|
|
10307
|
-
|
|
11432
|
+
className: `px-3 py-2 ${isRightAligned ? "text-right" : "text-left"}`,
|
|
11433
|
+
scope: "col",
|
|
11434
|
+
role: "columnheader",
|
|
11435
|
+
...isSortable ? { "aria-sort": ariaSort } : {},
|
|
11436
|
+
...isSortable ? headerKeyboardHandlers : {},
|
|
11437
|
+
children: header.isPlaceholder ? null : isSortable ? /* @__PURE__ */ jsxs17(
|
|
11438
|
+
Button,
|
|
11439
|
+
{
|
|
11440
|
+
variant: "ghost",
|
|
11441
|
+
className: `h-auto p-0 font-medium hover:bg-transparent ${isRightAligned ? "justify-end" : "justify-start"}`,
|
|
11442
|
+
onClick: handleSortClick,
|
|
11443
|
+
...headerKeyboardHandlers,
|
|
11444
|
+
"aria-label": `Sort by ${typeof header.column.columnDef.header === "string" ? header.column.columnDef.header : "column"}`,
|
|
11445
|
+
tabIndex: 0,
|
|
11446
|
+
children: [
|
|
11447
|
+
typeof header.column.columnDef.header === "function" ? header.column.columnDef.header(header.getContext()) : header.column.columnDef.header,
|
|
11448
|
+
header.column.getIsSorted() === "asc" ? /* @__PURE__ */ jsx24(ChevronUp2, { className: "h-4 w-4" }) : header.column.getIsSorted() === "desc" ? /* @__PURE__ */ jsx24(ChevronDown3, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx24(ChevronsUpDown, { className: "h-4 w-4" })
|
|
11449
|
+
]
|
|
11450
|
+
}
|
|
11451
|
+
) : typeof header.column.columnDef.header === "function" ? header.column.columnDef.header(header.getContext()) : header.column.columnDef.header
|
|
11452
|
+
},
|
|
11453
|
+
header.id
|
|
11454
|
+
);
|
|
11455
|
+
}) }, headerGroup.id)) }),
|
|
11456
|
+
/* @__PURE__ */ jsx24(
|
|
11457
|
+
UnifiedTableBody,
|
|
11458
|
+
{
|
|
11459
|
+
table,
|
|
11460
|
+
isCreating,
|
|
11461
|
+
creationData,
|
|
11462
|
+
onCreationDataChange: stateActions.setCreationData,
|
|
11463
|
+
onSaveCreation: () => {
|
|
11464
|
+
if (onCreateRow) {
|
|
11465
|
+
onCreateRow(creationData);
|
|
11466
|
+
stateActions.clearCreationData();
|
|
11467
|
+
stateActions.setCreating(false);
|
|
11468
|
+
}
|
|
11469
|
+
},
|
|
11470
|
+
onCancelCreation: () => {
|
|
11471
|
+
stateActions.clearCreationData();
|
|
11472
|
+
stateActions.setCreating(false);
|
|
11473
|
+
},
|
|
11474
|
+
editingRowId,
|
|
11475
|
+
editingData,
|
|
11476
|
+
onEditingDataChange: (data2) => {
|
|
11477
|
+
if (editingRowId) {
|
|
11478
|
+
stateActions.setEditingRow(editingRowId, data2);
|
|
11479
|
+
}
|
|
11480
|
+
},
|
|
11481
|
+
onSaveEditing: () => {
|
|
11482
|
+
if (onEditRow && editingRowId) {
|
|
11483
|
+
const originalRow = data.find((row) => {
|
|
11484
|
+
try {
|
|
11485
|
+
const rowId = resolvedGetRowId(row, 0);
|
|
11486
|
+
return rowId === editingRowId;
|
|
11487
|
+
} catch {
|
|
11488
|
+
return false;
|
|
11489
|
+
}
|
|
11490
|
+
});
|
|
11491
|
+
if (originalRow) {
|
|
11492
|
+
onEditRow(originalRow, editingData);
|
|
11493
|
+
}
|
|
11494
|
+
}
|
|
11495
|
+
stateActions.clearEditing();
|
|
11496
|
+
},
|
|
11497
|
+
onCancelEditing: () => {
|
|
11498
|
+
stateActions.clearEditing();
|
|
11499
|
+
},
|
|
11500
|
+
grouping: state.grouping,
|
|
11501
|
+
aggregates,
|
|
11502
|
+
getRowId: resolvedGetRowId,
|
|
11503
|
+
emptyState: React17.isValidElement(emptyState) ? void 0 : emptyState,
|
|
11504
|
+
isFiltered: searchQuery !== "" || state.columnFilters.length > 0,
|
|
11505
|
+
onClearFilters: () => {
|
|
11506
|
+
stateActions.setSearchQuery("");
|
|
11507
|
+
stateActions.setColumnFilters([]);
|
|
11508
|
+
},
|
|
11509
|
+
enableFiltering: secureFeatures.filtering,
|
|
11510
|
+
showFilterRow,
|
|
11511
|
+
dataLength: finalTableData?.length || 0,
|
|
11512
|
+
virtualHeight,
|
|
11513
|
+
forceVirtualization: false,
|
|
11514
|
+
hierarchical: secureFeatures.hierarchical && hierarchical?.enabled && hierarchicalState ? {
|
|
11515
|
+
...hierarchical,
|
|
11516
|
+
state: hierarchicalState,
|
|
11517
|
+
expandAll: hierarchicalState.expandAll,
|
|
11518
|
+
collapseAll: hierarchicalState.collapseAll,
|
|
11519
|
+
isAllExpanded: hierarchicalState.getExpandedIds().length > 0 && hierarchicalState.getExpandedIds().length === finalTableData.filter((row) => row.isParent).length,
|
|
11520
|
+
hasAnyChildren: finalTableData.some((row) => row.isParent)
|
|
11521
|
+
} : void 0,
|
|
11522
|
+
actions: effectiveActions,
|
|
11523
|
+
rbac,
|
|
11524
|
+
permissions
|
|
10308
11525
|
}
|
|
10309
|
-
|
|
10310
|
-
|
|
10311
|
-
|
|
10312
|
-
|
|
10313
|
-
|
|
10314
|
-
|
|
10315
|
-
|
|
10316
|
-
|
|
10317
|
-
|
|
10318
|
-
}
|
|
11526
|
+
),
|
|
11527
|
+
secureFeatures.pagination && /* @__PURE__ */ jsx24("tfoot", { children: /* @__PURE__ */ jsx24("tr", { children: /* @__PURE__ */ jsx24("td", { colSpan: visibleColumns.length, children: /* @__PURE__ */ jsx24(
|
|
11528
|
+
PaginationComponent,
|
|
11529
|
+
{
|
|
11530
|
+
table,
|
|
11531
|
+
pageSizeOptions: finalPageSizeOptions,
|
|
11532
|
+
paginationMode: finalPaginationMode,
|
|
11533
|
+
totalCount: finalDataCount,
|
|
11534
|
+
isLoading
|
|
10319
11535
|
}
|
|
10320
|
-
|
|
10321
|
-
|
|
10322
|
-
|
|
10323
|
-
|
|
10324
|
-
},
|
|
10325
|
-
grouping: state.grouping,
|
|
10326
|
-
aggregates,
|
|
10327
|
-
getRowId,
|
|
10328
|
-
emptyState: React15.isValidElement(emptyState) ? void 0 : emptyState,
|
|
10329
|
-
isFiltered: searchQuery !== "" || state.columnFilters.length > 0,
|
|
10330
|
-
onClearFilters: () => {
|
|
10331
|
-
stateActions.setSearchQuery("");
|
|
10332
|
-
stateActions.setColumnFilters([]);
|
|
10333
|
-
},
|
|
10334
|
-
enableFiltering: features.filtering,
|
|
10335
|
-
showFilterRow,
|
|
10336
|
-
dataLength: finalTableData?.length || 0,
|
|
10337
|
-
virtualHeight,
|
|
10338
|
-
forceVirtualization: false,
|
|
10339
|
-
hierarchical: features.hierarchical && hierarchical?.enabled ? {
|
|
10340
|
-
...hierarchical,
|
|
10341
|
-
state: hierarchicalState,
|
|
10342
|
-
expandAll: hierarchicalState.expandAll,
|
|
10343
|
-
collapseAll: hierarchicalState.collapseAll,
|
|
10344
|
-
isAllExpanded: hierarchicalState.getExpandedIds().length > 0 && hierarchicalState.getExpandedIds().length === finalTableData.filter((row) => row.isParent).length,
|
|
10345
|
-
hasAnyChildren: finalTableData.some((row) => row.isParent)
|
|
10346
|
-
} : void 0,
|
|
10347
|
-
actions: effectiveActions,
|
|
10348
|
-
rbac,
|
|
10349
|
-
permissions
|
|
10350
|
-
}
|
|
10351
|
-
),
|
|
10352
|
-
features.pagination && /* @__PURE__ */ jsx24("tfoot", { children: /* @__PURE__ */ jsx24("tr", { children: /* @__PURE__ */ jsx24("td", { colSpan: visibleColumns.length, children: /* @__PURE__ */ jsx24(
|
|
10353
|
-
PaginationComponent,
|
|
10354
|
-
{
|
|
10355
|
-
table,
|
|
10356
|
-
pageSizeOptions: finalPageSizeOptions,
|
|
10357
|
-
paginationMode: finalPaginationMode,
|
|
10358
|
-
totalCount: finalDataCount,
|
|
10359
|
-
isLoading
|
|
10360
|
-
}
|
|
10361
|
-
) }) }) })
|
|
10362
|
-
] }),
|
|
11536
|
+
) }) }) })
|
|
11537
|
+
]
|
|
11538
|
+
}
|
|
11539
|
+
),
|
|
10363
11540
|
/* @__PURE__ */ jsx24(
|
|
10364
11541
|
DataTableModals,
|
|
10365
11542
|
{
|
|
@@ -10386,15 +11563,25 @@ function DataTableCore(props) {
|
|
|
10386
11563
|
// src/components/DataTable/DataTable.tsx
|
|
10387
11564
|
import { jsx as jsx25 } from "react/jsx-runtime";
|
|
10388
11565
|
function DataTable(props) {
|
|
10389
|
-
|
|
10390
|
-
|
|
10391
|
-
|
|
10392
|
-
|
|
10393
|
-
|
|
10394
|
-
|
|
10395
|
-
|
|
11566
|
+
const logger = React18.useMemo(() => createLogger("DataTable"), []);
|
|
11567
|
+
const { features, ...rest } = props;
|
|
11568
|
+
const normalizedFeatures = React18.useMemo(
|
|
11569
|
+
() => normalizeDataTableFeatures(features),
|
|
11570
|
+
[features]
|
|
11571
|
+
);
|
|
11572
|
+
React18.useEffect(() => {
|
|
11573
|
+
if (!features && import.meta.env?.MODE === "development") {
|
|
11574
|
+
logger.info("DataTable: no features provided; all capabilities default to disabled. Pass a features object to enable functionality.");
|
|
11575
|
+
}
|
|
11576
|
+
}, [features, logger]);
|
|
11577
|
+
React18.useEffect(() => {
|
|
11578
|
+
if (normalizedFeatures.deleteSelected && !normalizedFeatures.deletion) {
|
|
11579
|
+
logger.warn("deleteSelected requires deletion to be enabled");
|
|
11580
|
+
}
|
|
11581
|
+
}, [normalizedFeatures.deleteSelected, normalizedFeatures.deletion, logger]);
|
|
11582
|
+
return /* @__PURE__ */ jsx25(DataTableCore, { ...rest, features: normalizedFeatures });
|
|
10396
11583
|
}
|
|
10397
|
-
var DataTableComponent =
|
|
11584
|
+
var DataTableComponent = React18.memo(DataTable);
|
|
10398
11585
|
|
|
10399
11586
|
// src/components/DataTable/components/BulkOperationsDropdown.tsx
|
|
10400
11587
|
import {
|
|
@@ -10557,6 +11744,10 @@ export {
|
|
|
10557
11744
|
getRowIdSafe,
|
|
10558
11745
|
hasValidRowId,
|
|
10559
11746
|
UnifiedTableBody,
|
|
11747
|
+
getPaginationBinding,
|
|
11748
|
+
validatePaginationConfig,
|
|
11749
|
+
getPageSizeOptions,
|
|
11750
|
+
calculateOptimalPageSize,
|
|
10560
11751
|
PaginationControls,
|
|
10561
11752
|
EnhancedPaginationControls,
|
|
10562
11753
|
LoadingState,
|
|
@@ -10569,7 +11760,22 @@ export {
|
|
|
10569
11760
|
getHierarchicalSortConfig,
|
|
10570
11761
|
generateCSVContent,
|
|
10571
11762
|
exportToCSV,
|
|
11763
|
+
defaultDataTableFeatures,
|
|
11764
|
+
normalizeDataTableFeatures,
|
|
10572
11765
|
ColumnFactory,
|
|
11766
|
+
initializeLiveRegion,
|
|
11767
|
+
cleanupLiveRegion,
|
|
11768
|
+
announce,
|
|
11769
|
+
getSortButtonLabel,
|
|
11770
|
+
announceSortChange,
|
|
11771
|
+
announceFilterChange,
|
|
11772
|
+
announceSearchResults,
|
|
11773
|
+
announcePaginationChange,
|
|
11774
|
+
announceSelectionChange,
|
|
11775
|
+
announceLoadingState,
|
|
11776
|
+
announceBulkOperation,
|
|
11777
|
+
getAriaSortValue,
|
|
11778
|
+
getRowDescription,
|
|
10573
11779
|
DataTableCore,
|
|
10574
11780
|
DataTable,
|
|
10575
11781
|
BulkOperationsDropdown,
|
|
@@ -10587,4 +11793,4 @@ lodash/lodash.js:
|
|
|
10587
11793
|
* Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
|
|
10588
11794
|
*)
|
|
10589
11795
|
*/
|
|
10590
|
-
//# sourceMappingURL=chunk-
|
|
11796
|
+
//# sourceMappingURL=chunk-ZMNXIJP4.js.map
|