@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
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
} from 'lucide-react';
|
|
14
14
|
import { cn } from '../../../utils/cn';
|
|
15
15
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../../Select/Select';
|
|
16
|
+
import { getPaginationBinding, getPageSizeOptions } from '../utils/paginationUtils';
|
|
16
17
|
import type { PaginationMode, ServerSideResponse, DataRecord } from '../types';
|
|
17
18
|
|
|
18
19
|
interface PaginationControlsProps<TData extends DataRecord> {
|
|
@@ -39,30 +40,15 @@ export function PaginationControls<TData extends DataRecord>({
|
|
|
39
40
|
totalCount
|
|
40
41
|
}: PaginationControlsProps<TData>) {
|
|
41
42
|
|
|
42
|
-
//
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
canNextPage: serverData.hasNextPage,
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// Client or hybrid mode
|
|
56
|
-
const state = table.getState().pagination;
|
|
57
|
-
return {
|
|
58
|
-
currentPageSize: state.pageSize,
|
|
59
|
-
currentPageIndex: state.pageIndex,
|
|
60
|
-
pageCount: table.getPageCount(),
|
|
61
|
-
totalRows: totalCount ?? table.getRowCount(),
|
|
62
|
-
canPreviousPage: table.getCanPreviousPage(),
|
|
63
|
-
canNextPage: table.getCanNextPage(),
|
|
64
|
-
};
|
|
65
|
-
};
|
|
43
|
+
// Use unified pagination binding for consistent behavior across modes
|
|
44
|
+
const pagination = getPaginationBinding({
|
|
45
|
+
mode: paginationMode,
|
|
46
|
+
table,
|
|
47
|
+
serverData,
|
|
48
|
+
totalCount,
|
|
49
|
+
onPageChange,
|
|
50
|
+
onPageSizeChange,
|
|
51
|
+
});
|
|
66
52
|
|
|
67
53
|
const {
|
|
68
54
|
currentPageSize,
|
|
@@ -71,67 +57,20 @@ export function PaginationControls<TData extends DataRecord>({
|
|
|
71
57
|
totalRows,
|
|
72
58
|
canPreviousPage,
|
|
73
59
|
canNextPage,
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
const handlePageSizeChange = (newPageSize: number) => {
|
|
78
|
-
if (paginationMode === 'server') {
|
|
79
|
-
onPageSizeChange?.(newPageSize);
|
|
80
|
-
} else {
|
|
81
|
-
table.setPageSize(newPageSize);
|
|
82
|
-
}
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
// Handle page navigation
|
|
86
|
-
const handleFirstPage = () => {
|
|
87
|
-
if (paginationMode === 'server') {
|
|
88
|
-
onPageChange?.(0);
|
|
89
|
-
} else {
|
|
90
|
-
table.setPageIndex(0);
|
|
91
|
-
}
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
const handlePreviousPage = () => {
|
|
95
|
-
if (paginationMode === 'server') {
|
|
96
|
-
onPageChange?.(Math.max(0, currentPageIndex - 1));
|
|
97
|
-
} else {
|
|
98
|
-
table.previousPage();
|
|
99
|
-
}
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
const handleNextPage = () => {
|
|
103
|
-
if (paginationMode === 'server') {
|
|
104
|
-
onPageChange?.(Math.min(pageCount - 1, currentPageIndex + 1));
|
|
105
|
-
} else {
|
|
106
|
-
table.nextPage();
|
|
107
|
-
}
|
|
108
|
-
};
|
|
60
|
+
startRow,
|
|
61
|
+
endRow,
|
|
62
|
+
} = pagination.state;
|
|
109
63
|
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
};
|
|
117
|
-
|
|
118
|
-
// Calculate display range
|
|
119
|
-
const startRow = currentPageIndex * currentPageSize + 1;
|
|
120
|
-
const endRow = Math.min((currentPageIndex + 1) * currentPageSize, totalRows);
|
|
64
|
+
const {
|
|
65
|
+
goToFirstPage,
|
|
66
|
+
goToPreviousPage,
|
|
67
|
+
goToNextPage,
|
|
68
|
+
goToLastPage,
|
|
69
|
+
setPageSize,
|
|
70
|
+
} = pagination.actions;
|
|
121
71
|
|
|
122
72
|
// Get mode-specific page size options
|
|
123
|
-
const
|
|
124
|
-
switch (paginationMode) {
|
|
125
|
-
case 'server':
|
|
126
|
-
return pageSizeOptions.filter(size => size <= 250); // Limit server-side page sizes
|
|
127
|
-
case 'hybrid':
|
|
128
|
-
return pageSizeOptions.filter(size => size >= 50); // Hybrid mode prefers larger pages
|
|
129
|
-
default:
|
|
130
|
-
return pageSizeOptions;
|
|
131
|
-
}
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
const availablePageSizes = getPageSizeOptions();
|
|
73
|
+
const availablePageSizes = getPageSizeOptions(paginationMode, pageSizeOptions);
|
|
135
74
|
|
|
136
75
|
// Performance mode indicator
|
|
137
76
|
const getModeIcon = () => {
|
|
@@ -168,7 +107,7 @@ export function PaginationControls<TData extends DataRecord>({
|
|
|
168
107
|
<Select
|
|
169
108
|
value={currentPageSize?.toString() || '10'}
|
|
170
109
|
selectedText={currentPageSize?.toString() || '10'}
|
|
171
|
-
onValueChange={(value) =>
|
|
110
|
+
onValueChange={(value) => setPageSize(Number(value))}
|
|
172
111
|
disabled={isLoading}
|
|
173
112
|
className="w-36 h-8"
|
|
174
113
|
>
|
|
@@ -182,7 +121,7 @@ export function PaginationControls<TData extends DataRecord>({
|
|
|
182
121
|
<SelectValue />
|
|
183
122
|
</SelectTrigger>
|
|
184
123
|
<SelectContent>
|
|
185
|
-
{
|
|
124
|
+
{availablePageSizes.map((pageSize) => (
|
|
186
125
|
<SelectItem key={pageSize} value={pageSize?.toString() || '10'}>
|
|
187
126
|
{pageSize}
|
|
188
127
|
</SelectItem>
|
|
@@ -217,7 +156,7 @@ export function PaginationControls<TData extends DataRecord>({
|
|
|
217
156
|
variant="outline"
|
|
218
157
|
size="sm"
|
|
219
158
|
className="h-8 w-8 p-0"
|
|
220
|
-
onClick={
|
|
159
|
+
onClick={goToFirstPage}
|
|
221
160
|
disabled={!canPreviousPage || isLoading}
|
|
222
161
|
aria-label="Go to first page"
|
|
223
162
|
tabIndex={0}
|
|
@@ -229,7 +168,7 @@ export function PaginationControls<TData extends DataRecord>({
|
|
|
229
168
|
variant="outline"
|
|
230
169
|
size="sm"
|
|
231
170
|
className="h-8 w-8 p-0"
|
|
232
|
-
onClick={
|
|
171
|
+
onClick={goToPreviousPage}
|
|
233
172
|
disabled={!canPreviousPage || isLoading}
|
|
234
173
|
aria-label="Go to previous page"
|
|
235
174
|
tabIndex={0}
|
|
@@ -241,7 +180,7 @@ export function PaginationControls<TData extends DataRecord>({
|
|
|
241
180
|
variant="outline"
|
|
242
181
|
size="sm"
|
|
243
182
|
className="h-8 w-8 p-0"
|
|
244
|
-
onClick={
|
|
183
|
+
onClick={goToNextPage}
|
|
245
184
|
disabled={!canNextPage || isLoading}
|
|
246
185
|
aria-label="Go to next page"
|
|
247
186
|
tabIndex={0}
|
|
@@ -253,7 +192,7 @@ export function PaginationControls<TData extends DataRecord>({
|
|
|
253
192
|
variant="outline"
|
|
254
193
|
size="sm"
|
|
255
194
|
className="h-8 w-8 p-0"
|
|
256
|
-
onClick={
|
|
195
|
+
onClick={goToLastPage}
|
|
257
196
|
disabled={!canNextPage || isLoading}
|
|
258
197
|
aria-label="Go to last page"
|
|
259
198
|
tabIndex={0}
|
|
@@ -279,25 +218,26 @@ export function EnhancedPaginationControls<TData extends DataRecord>({
|
|
|
279
218
|
}: EnhancedPaginationControlsProps<TData>) {
|
|
280
219
|
const [jumpToPage, setJumpToPage] = React.useState('');
|
|
281
220
|
|
|
282
|
-
const { table, paginationMode = 'client', serverData, onPageChange } = props;
|
|
221
|
+
const { table, paginationMode = 'client', serverData, onPageChange, totalCount } = props;
|
|
283
222
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
223
|
+
// Use unified pagination binding for consistent behavior
|
|
224
|
+
const pagination = getPaginationBinding({
|
|
225
|
+
mode: paginationMode,
|
|
226
|
+
table,
|
|
227
|
+
serverData,
|
|
228
|
+
totalCount,
|
|
229
|
+
onPageChange,
|
|
230
|
+
onPageSizeChange: props.onPageSizeChange,
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
const { pageCount } = pagination.state;
|
|
290
234
|
|
|
291
235
|
const handleJumpToPage = (e: React.FormEvent) => {
|
|
292
236
|
e.preventDefault();
|
|
293
237
|
const pageNumber = parseInt(jumpToPage, 10);
|
|
294
238
|
if (pageNumber >= 1 && pageNumber <= pageCount) {
|
|
295
239
|
const pageIndex = pageNumber - 1;
|
|
296
|
-
|
|
297
|
-
onPageChange?.(pageIndex);
|
|
298
|
-
} else {
|
|
299
|
-
table.setPageIndex(pageIndex);
|
|
300
|
-
}
|
|
240
|
+
pagination.actions.goToPage(pageIndex);
|
|
301
241
|
setJumpToPage('');
|
|
302
242
|
}
|
|
303
243
|
};
|
|
@@ -22,7 +22,16 @@ import { EditableRow } from './EditableRow';
|
|
|
22
22
|
import { getTableCellClasses, getTableHeadClasses, getTableRowClasses } from '../styles';
|
|
23
23
|
import { Input } from '../../Input/Input';
|
|
24
24
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../../Select/Select';
|
|
25
|
-
import type {
|
|
25
|
+
import type {
|
|
26
|
+
AggregateConfig,
|
|
27
|
+
DataRecord,
|
|
28
|
+
DataTableAction,
|
|
29
|
+
EditableColumnDef,
|
|
30
|
+
EmptyStateConfig,
|
|
31
|
+
HierarchicalConfig,
|
|
32
|
+
HierarchicalDataRow,
|
|
33
|
+
CellValue
|
|
34
|
+
} from '../types';
|
|
26
35
|
import { calculateIndentation } from '../utils/hierarchicalUtils';
|
|
27
36
|
import { getRowIdSafe } from '../utils/rowUtils';
|
|
28
37
|
|
|
@@ -34,15 +43,15 @@ const MEMORY_OPTIMIZATION_THRESHOLD = 100000;
|
|
|
34
43
|
/**
|
|
35
44
|
* Props for the unified table body component
|
|
36
45
|
*/
|
|
37
|
-
interface UnifiedTableBodyProps<TData extends
|
|
46
|
+
interface UnifiedTableBodyProps<TData extends DataRecord> {
|
|
38
47
|
/** TanStack table instance */
|
|
39
48
|
table: Table<TData>;
|
|
40
49
|
/** Whether a new row is being created */
|
|
41
50
|
isCreating: boolean;
|
|
42
51
|
/** Data for the row being created */
|
|
43
|
-
creationData: Record<string,
|
|
52
|
+
creationData: Record<string, CellValue>;
|
|
44
53
|
/** Callback when creation data changes */
|
|
45
|
-
onCreationDataChange: (data: Record<string,
|
|
54
|
+
onCreationDataChange: (data: Record<string, CellValue>) => void;
|
|
46
55
|
/** Callback to save the new row */
|
|
47
56
|
onSaveCreation: () => void;
|
|
48
57
|
/** Callback to cancel row creation */
|
|
@@ -50,9 +59,9 @@ interface UnifiedTableBodyProps<TData extends Record<string, any>> {
|
|
|
50
59
|
/** ID of the row currently being edited */
|
|
51
60
|
editingRowId: string | null;
|
|
52
61
|
/** Data for the row being edited */
|
|
53
|
-
editingData: Record<string,
|
|
62
|
+
editingData: Record<string, CellValue>;
|
|
54
63
|
/** Callback when editing data changes */
|
|
55
|
-
onEditingDataChange: (data: Record<string,
|
|
64
|
+
onEditingDataChange: (data: Record<string, CellValue>) => void;
|
|
56
65
|
/** Callback to save the edited row */
|
|
57
66
|
onSaveEditing?: () => void;
|
|
58
67
|
/** Callback to cancel row editing */
|
|
@@ -64,15 +73,7 @@ interface UnifiedTableBodyProps<TData extends Record<string, any>> {
|
|
|
64
73
|
/** Function to get unique row ID */
|
|
65
74
|
getRowId?: (row: TData, index: number) => string;
|
|
66
75
|
/** Custom empty state configuration */
|
|
67
|
-
emptyState?:
|
|
68
|
-
title?: string;
|
|
69
|
-
description?: string;
|
|
70
|
-
icon?: React.ComponentType<{ className?: string }>;
|
|
71
|
-
action?: {
|
|
72
|
-
label: string;
|
|
73
|
-
onClick: () => void;
|
|
74
|
-
};
|
|
75
|
-
};
|
|
76
|
+
emptyState?: EmptyStateConfig;
|
|
76
77
|
/** Whether the table is currently filtered */
|
|
77
78
|
isFiltered?: boolean;
|
|
78
79
|
/** Callback to clear all filters */
|
|
@@ -103,25 +104,7 @@ interface UnifiedTableBodyProps<TData extends Record<string, any>> {
|
|
|
103
104
|
hasAnyChildren?: boolean;
|
|
104
105
|
};
|
|
105
106
|
/** Actions for action buttons */
|
|
106
|
-
actions?:
|
|
107
|
-
label: string;
|
|
108
|
-
onClick: (row: any) => void;
|
|
109
|
-
icon?: any;
|
|
110
|
-
variant?: 'default' | 'destructive' | 'outline' | 'secondary' | 'ghost';
|
|
111
|
-
disabled?: boolean | ((row?: any) => boolean);
|
|
112
|
-
visible?: boolean | ((row?: any) => boolean);
|
|
113
|
-
testId?: string;
|
|
114
|
-
showInEditMode?: boolean;
|
|
115
|
-
hideInViewMode?: boolean;
|
|
116
|
-
showInViewMode?: boolean;
|
|
117
|
-
hidden?: boolean;
|
|
118
|
-
showForParent?: boolean;
|
|
119
|
-
showForChild?: boolean;
|
|
120
|
-
parentIcon?: any;
|
|
121
|
-
childIcon?: any;
|
|
122
|
-
parentLabel?: string;
|
|
123
|
-
childLabel?: string;
|
|
124
|
-
}>;
|
|
107
|
+
actions?: DataTableAction<TData>[];
|
|
125
108
|
// MANDATORY RBAC
|
|
126
109
|
rbac?: {
|
|
127
110
|
pageId?: string;
|
|
@@ -138,38 +121,37 @@ interface UnifiedTableBodyProps<TData extends Record<string, any>> {
|
|
|
138
121
|
}
|
|
139
122
|
|
|
140
123
|
// Helper function to render the appropriate input type based on column configuration
|
|
141
|
-
const renderEditField = <TData extends
|
|
124
|
+
const renderEditField = <TData extends DataRecord>(
|
|
142
125
|
column: Column<TData, unknown>,
|
|
143
|
-
value:
|
|
144
|
-
onChange: (value:
|
|
145
|
-
editingData: Record<string,
|
|
126
|
+
value: CellValue,
|
|
127
|
+
onChange: (value: CellValue | Record<string, CellValue>) => void,
|
|
128
|
+
editingData: Record<string, CellValue> = {},
|
|
146
129
|
placeholder?: string
|
|
147
130
|
) => {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
131
|
+
const columnDef = column.columnDef as EditableColumnDef<TData>;
|
|
132
|
+
|
|
151
133
|
// Check if column is editable (default: true)
|
|
152
134
|
if (columnDef.editable === false) {
|
|
153
135
|
// Return the original value as text if column is not editable
|
|
154
|
-
return <span className="text-sm text-gray-600">{String(value
|
|
136
|
+
return <span className="text-sm text-gray-600">{String(value ?? '')}</span>;
|
|
155
137
|
}
|
|
156
|
-
|
|
138
|
+
|
|
157
139
|
// Check for custom field type
|
|
158
140
|
if (columnDef.fieldType === 'select' && columnDef.fieldOptions) {
|
|
159
141
|
// Use editAccessorKey if specified, otherwise use the column id
|
|
160
142
|
const accessorKey = columnDef.editAccessorKey || column.id;
|
|
161
|
-
const currentValue = editingData[accessorKey]
|
|
162
|
-
|
|
143
|
+
const currentValue = editingData[accessorKey] ?? value ?? '';
|
|
144
|
+
|
|
163
145
|
return (
|
|
164
146
|
<Select
|
|
165
147
|
value={String(currentValue)}
|
|
166
|
-
onValueChange={(newValue) => onChange({ [accessorKey]: newValue })}
|
|
148
|
+
onValueChange={(newValue) => onChange({ [accessorKey]: newValue as CellValue })}
|
|
167
149
|
>
|
|
168
150
|
<SelectTrigger className="h-8">
|
|
169
151
|
<SelectValue placeholder={placeholder || `Select ${columnDef.header || column.id}...`} />
|
|
170
152
|
</SelectTrigger>
|
|
171
153
|
<SelectContent>
|
|
172
|
-
{columnDef.fieldOptions.map(
|
|
154
|
+
{columnDef.fieldOptions.map(option => (
|
|
173
155
|
<SelectItem key={option.value} value={String(option.value)}>
|
|
174
156
|
{option.label}
|
|
175
157
|
</SelectItem>
|
|
@@ -184,32 +166,32 @@ const renderEditField = <TData extends Record<string, any>>(
|
|
|
184
166
|
return (
|
|
185
167
|
<Input
|
|
186
168
|
type="number"
|
|
187
|
-
value={String(value
|
|
188
|
-
onChange={(e) => onChange(e.target.value)}
|
|
169
|
+
value={String(value ?? '')}
|
|
170
|
+
onChange={(e) => onChange(e.target.value as unknown as CellValue)}
|
|
189
171
|
placeholder={placeholder || `Enter ${columnDef.header || column.id}...`}
|
|
190
172
|
className="h-8"
|
|
191
173
|
/>
|
|
192
174
|
);
|
|
193
175
|
}
|
|
194
|
-
|
|
176
|
+
|
|
195
177
|
// Check for date type
|
|
196
178
|
if (columnDef.fieldType === 'date') {
|
|
197
179
|
return (
|
|
198
180
|
<Input
|
|
199
181
|
type="date"
|
|
200
|
-
value={String(value
|
|
201
|
-
onChange={(e) => onChange(e.target.value)}
|
|
182
|
+
value={String(value ?? '')}
|
|
183
|
+
onChange={(e) => onChange(e.target.value as unknown as CellValue)}
|
|
202
184
|
className="h-8"
|
|
203
185
|
/>
|
|
204
186
|
);
|
|
205
187
|
}
|
|
206
|
-
|
|
188
|
+
|
|
207
189
|
// Default to text input
|
|
208
190
|
return (
|
|
209
191
|
<Input
|
|
210
192
|
type="text"
|
|
211
|
-
value={String(value
|
|
212
|
-
onChange={(e) => onChange(e.target.value)}
|
|
193
|
+
value={String(value ?? '')}
|
|
194
|
+
onChange={(e) => onChange(e.target.value as unknown as CellValue)}
|
|
213
195
|
placeholder={placeholder || `Enter ${columnDef.header || column.id}...`}
|
|
214
196
|
className="h-8"
|
|
215
197
|
/>
|
|
@@ -378,52 +360,12 @@ const RowComponent = React.memo(({
|
|
|
378
360
|
key={cell.id}
|
|
379
361
|
className={getTableCellClasses({
|
|
380
362
|
isCompact: true,
|
|
381
|
-
className:
|
|
363
|
+
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' : ''}`
|
|
382
364
|
})}
|
|
383
365
|
>
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
cell.column.columnDef.cell ? (
|
|
388
|
-
flexRender(cell.column.columnDef.cell, {
|
|
389
|
-
...cell.getContext(),
|
|
390
|
-
hierarchical: hierarchical,
|
|
391
|
-
isParent: false,
|
|
392
|
-
isChild: true,
|
|
393
|
-
isHierarchical: false,
|
|
394
|
-
rowId: subRowId,
|
|
395
|
-
isExpanded: false,
|
|
396
|
-
hasChildren: false,
|
|
397
|
-
getIsEditing: () => true, // Always true in edit mode
|
|
398
|
-
setValue: (value: any) => {
|
|
399
|
-
if (typeof value === 'object' && value !== null) {
|
|
400
|
-
onEditingDataChange?.({ ...editingData, ...value });
|
|
401
|
-
} else {
|
|
402
|
-
onEditingDataChange?.({ ...editingData, [cell.column.id]: value });
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
})
|
|
406
|
-
) : (
|
|
407
|
-
// Fall back to default edit field rendering when no custom cell renderer
|
|
408
|
-
renderEditField(cell.column, editingData?.[cell.column.id], (value) => {
|
|
409
|
-
if (typeof value === 'object' && value !== null) {
|
|
410
|
-
onEditingDataChange?.({ ...editingData, ...value });
|
|
411
|
-
} else {
|
|
412
|
-
onEditingDataChange?.({ ...editingData, [cell.column.id]: value });
|
|
413
|
-
}
|
|
414
|
-
}, editingData)
|
|
415
|
-
)
|
|
416
|
-
) : cell.column.id === 'actions' ? (
|
|
417
|
-
<ActionButtons
|
|
418
|
-
row={row}
|
|
419
|
-
actions={actions}
|
|
420
|
-
isEditing={isEditing}
|
|
421
|
-
isParent={isParent}
|
|
422
|
-
hierarchical={!!hierarchical}
|
|
423
|
-
rbac={rbac}
|
|
424
|
-
permissions={permissions}
|
|
425
|
-
/>
|
|
426
|
-
) : (
|
|
366
|
+
{isSubRowEditing && cell.column.id !== 'actions' ? (
|
|
367
|
+
// Check if column has a custom cell renderer - if so, use it in edit mode
|
|
368
|
+
cell.column.columnDef.cell ? (
|
|
427
369
|
flexRender(cell.column.columnDef.cell, {
|
|
428
370
|
...cell.getContext(),
|
|
429
371
|
hierarchical: hierarchical,
|
|
@@ -432,10 +374,48 @@ const RowComponent = React.memo(({
|
|
|
432
374
|
isHierarchical: false,
|
|
433
375
|
rowId: subRowId,
|
|
434
376
|
isExpanded: false,
|
|
435
|
-
hasChildren: false
|
|
377
|
+
hasChildren: false,
|
|
378
|
+
getIsEditing: () => true, // Always true in edit mode
|
|
379
|
+
setValue: (value: any) => {
|
|
380
|
+
if (typeof value === 'object' && value !== null) {
|
|
381
|
+
onEditingDataChange?.({ ...editingData, ...value });
|
|
382
|
+
} else {
|
|
383
|
+
onEditingDataChange?.({ ...editingData, [cell.column.id]: value });
|
|
384
|
+
}
|
|
385
|
+
}
|
|
436
386
|
})
|
|
437
|
-
)
|
|
438
|
-
|
|
387
|
+
) : (
|
|
388
|
+
// Fall back to default edit field rendering when no custom cell renderer
|
|
389
|
+
renderEditField(cell.column, editingData?.[cell.column.id], (value) => {
|
|
390
|
+
if (typeof value === 'object' && value !== null) {
|
|
391
|
+
onEditingDataChange?.({ ...editingData, ...value });
|
|
392
|
+
} else {
|
|
393
|
+
onEditingDataChange?.({ ...editingData, [cell.column.id]: value });
|
|
394
|
+
}
|
|
395
|
+
}, editingData)
|
|
396
|
+
)
|
|
397
|
+
) : cell.column.id === 'actions' ? (
|
|
398
|
+
<ActionButtons
|
|
399
|
+
row={row}
|
|
400
|
+
actions={actions}
|
|
401
|
+
isEditing={isEditing}
|
|
402
|
+
isParent={isParent}
|
|
403
|
+
hierarchical={!!hierarchical}
|
|
404
|
+
rbac={rbac}
|
|
405
|
+
permissions={permissions}
|
|
406
|
+
/>
|
|
407
|
+
) : (
|
|
408
|
+
flexRender(cell.column.columnDef.cell, {
|
|
409
|
+
...cell.getContext(),
|
|
410
|
+
hierarchical: hierarchical,
|
|
411
|
+
isParent: false,
|
|
412
|
+
isChild: true,
|
|
413
|
+
isHierarchical: false,
|
|
414
|
+
rowId: subRowId,
|
|
415
|
+
isExpanded: false,
|
|
416
|
+
hasChildren: false
|
|
417
|
+
})
|
|
418
|
+
)}
|
|
439
419
|
</td>
|
|
440
420
|
))}
|
|
441
421
|
</tr>
|
|
@@ -459,7 +439,7 @@ const RowComponent = React.memo(({
|
|
|
459
439
|
onEditingDataChange={onEditingDataChange}
|
|
460
440
|
onSave={onSaveEditing}
|
|
461
441
|
onCancel={onCancelEditing}
|
|
462
|
-
actions={
|
|
442
|
+
actions={actions ?? []}
|
|
463
443
|
getRowId={getRowId}
|
|
464
444
|
isParent={isParent}
|
|
465
445
|
hierarchical={!!hierarchical}
|
|
@@ -487,11 +467,13 @@ const RowComponent = React.memo(({
|
|
|
487
467
|
<tr
|
|
488
468
|
ref={rowRef}
|
|
489
469
|
key={row.id}
|
|
470
|
+
role="row"
|
|
490
471
|
style={{
|
|
491
472
|
...style,
|
|
492
473
|
...(isChild && indentation > 0 ? { paddingLeft: `${indentation}px` } : {})
|
|
493
474
|
}}
|
|
494
475
|
className={rowClassName}
|
|
476
|
+
aria-selected={typeof row.getIsSelected === 'function' ? (row.getIsSelected() ? 'true' : 'false') : 'false'}
|
|
495
477
|
>
|
|
496
478
|
{visibleCells.map((cell: any, cellIndex: number) => {
|
|
497
479
|
const isFirstCell = cellIndex === 0;
|
|
@@ -504,52 +486,47 @@ const RowComponent = React.memo(({
|
|
|
504
486
|
key={cell.id}
|
|
505
487
|
className={getTableCellClasses({
|
|
506
488
|
isCompact: true,
|
|
507
|
-
className:
|
|
489
|
+
className: `px-3 py-2 ${cell.column.id === 'actions' ? 'whitespace-nowrap' : 'whitespace-normal break-words'} ${cell.column.columnDef.meta?.align === 'right' ? 'text-right' : ''}`
|
|
508
490
|
})}
|
|
509
491
|
>
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
<ChevronDown className="h-4 w-4" />
|
|
522
|
-
) : (
|
|
523
|
-
<ChevronRight className="h-4 w-4" />
|
|
524
|
-
)}
|
|
525
|
-
</Button>
|
|
526
|
-
)}
|
|
527
|
-
|
|
528
|
-
<div className={`flex-1 ${cell.column.columnDef.meta?.align === 'right' ? 'text-right' : ''}`}>
|
|
529
|
-
{cell.column.id === 'actions' ? (
|
|
530
|
-
<ActionButtons
|
|
531
|
-
row={row}
|
|
532
|
-
actions={actions}
|
|
533
|
-
isEditing={isEditing}
|
|
534
|
-
isParent={isParent}
|
|
535
|
-
hierarchical={!!hierarchical}
|
|
536
|
-
rbac={rbac}
|
|
537
|
-
permissions={permissions}
|
|
538
|
-
/>
|
|
492
|
+
{shouldShowExpansionButton && hasChildren && (
|
|
493
|
+
<Button
|
|
494
|
+
variant="ghost"
|
|
495
|
+
size="sm"
|
|
496
|
+
onClick={() => hierarchical?.state?.toggleRow(rowId)}
|
|
497
|
+
className="h-6 w-6 p-0 flex-shrink-0"
|
|
498
|
+
aria-label={isExpanded ? 'Collapse row' : 'Expand row'}
|
|
499
|
+
title={isExpanded ? 'Collapse row' : 'Expand row'}
|
|
500
|
+
>
|
|
501
|
+
{isExpanded ? (
|
|
502
|
+
<ChevronDown className="h-4 w-4" />
|
|
539
503
|
) : (
|
|
540
|
-
|
|
541
|
-
...cell.getContext(),
|
|
542
|
-
hierarchical: hierarchical,
|
|
543
|
-
isParent: isParent,
|
|
544
|
-
isChild: isChild,
|
|
545
|
-
isHierarchical: isHierarchical,
|
|
546
|
-
rowId: rowId,
|
|
547
|
-
isExpanded: isExpanded,
|
|
548
|
-
hasChildren: hasChildren,
|
|
549
|
-
})
|
|
504
|
+
<ChevronRight className="h-4 w-4" />
|
|
550
505
|
)}
|
|
551
|
-
</
|
|
552
|
-
|
|
506
|
+
</Button>
|
|
507
|
+
)}
|
|
508
|
+
{cell.column.id === 'actions' ? (
|
|
509
|
+
<ActionButtons
|
|
510
|
+
row={row}
|
|
511
|
+
actions={actions}
|
|
512
|
+
isEditing={isEditing}
|
|
513
|
+
isParent={isParent}
|
|
514
|
+
hierarchical={!!hierarchical}
|
|
515
|
+
rbac={rbac}
|
|
516
|
+
permissions={permissions}
|
|
517
|
+
/>
|
|
518
|
+
) : (
|
|
519
|
+
flexRender(cell.column.columnDef.cell, {
|
|
520
|
+
...cell.getContext(),
|
|
521
|
+
hierarchical: hierarchical,
|
|
522
|
+
isParent: isParent,
|
|
523
|
+
isChild: isChild,
|
|
524
|
+
isHierarchical: isHierarchical,
|
|
525
|
+
rowId: rowId,
|
|
526
|
+
isExpanded: isExpanded,
|
|
527
|
+
hasChildren: hasChildren,
|
|
528
|
+
})
|
|
529
|
+
)}
|
|
553
530
|
</td>
|
|
554
531
|
);
|
|
555
532
|
})}
|
|
@@ -728,10 +705,10 @@ export function UnifiedTableBody<TData extends Record<string, any>>({
|
|
|
728
705
|
})}
|
|
729
706
|
>
|
|
730
707
|
{renderEditField(header.column, creationData[header.column.id], (value) => {
|
|
731
|
-
if (typeof value === 'object' && value !== null) {
|
|
732
|
-
onCreationDataChange({ ...creationData, ...value });
|
|
708
|
+
if (typeof value === 'object' && value !== null && !Array.isArray(value) && !(value instanceof Date)) {
|
|
709
|
+
onCreationDataChange({ ...creationData, ...(value as Record<string, CellValue>) });
|
|
733
710
|
} else {
|
|
734
|
-
onCreationDataChange({ ...creationData, [header.column.id]: value });
|
|
711
|
+
onCreationDataChange({ ...creationData, [header.column.id]: value as CellValue });
|
|
735
712
|
}
|
|
736
713
|
}, creationData)}
|
|
737
714
|
</td>
|
|
@@ -31,7 +31,7 @@ export interface DataTableContextValue<TData extends DataRecord> {
|
|
|
31
31
|
// CONTEXT CREATION
|
|
32
32
|
// ============================================================================
|
|
33
33
|
|
|
34
|
-
const DataTableContext = createContext<DataTableContextValue<
|
|
34
|
+
const DataTableContext = createContext<DataTableContextValue<DataRecord> | null>(null);
|
|
35
35
|
|
|
36
36
|
// ============================================================================
|
|
37
37
|
// PROVIDER COMPONENT
|
|
@@ -45,6 +45,10 @@ export interface ActionColumnOptions {
|
|
|
45
45
|
size?: number;
|
|
46
46
|
minSize?: number;
|
|
47
47
|
maxSize?: number;
|
|
48
|
+
meta?: {
|
|
49
|
+
align?: 'left' | 'right' | 'center';
|
|
50
|
+
[key: string]: any;
|
|
51
|
+
};
|
|
48
52
|
}
|
|
49
53
|
|
|
50
54
|
export interface CustomColumnOptions<TData extends DataRecord> {
|
|
@@ -220,6 +224,7 @@ export class ColumnFactory<TData extends DataRecord = DataRecord> {
|
|
|
220
224
|
size: options.size || 150,
|
|
221
225
|
minSize: options.minSize || 100,
|
|
222
226
|
maxSize: options.maxSize || 200,
|
|
227
|
+
meta: options.meta,
|
|
223
228
|
} as ColumnDef<TData>;
|
|
224
229
|
}
|
|
225
230
|
|