@jmruthers/pace-core 0.5.193 → 0.6.2
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 +62 -0
- package/README.md +7 -1
- package/cursor-rules/00-pace-core-compliance.mdc +299 -0
- package/cursor-rules/01-standards-compliance.mdc +244 -0
- package/cursor-rules/02-project-structure.mdc +200 -0
- package/cursor-rules/03-solid-principles.mdc +222 -0
- package/cursor-rules/04-testing-standards.mdc +268 -0
- package/cursor-rules/05-bug-reports-and-features.mdc +246 -0
- package/cursor-rules/06-code-quality.mdc +309 -0
- package/cursor-rules/07-tech-stack-compliance.mdc +214 -0
- package/cursor-rules/08-markup-quality.mdc +452 -0
- package/cursor-rules/CHANGELOG.md +119 -0
- package/cursor-rules/README.md +192 -0
- package/dist/{AuthService-DjnJHDtC.d.ts → AuthService-BPvc3Ka0.d.ts} +54 -0
- package/dist/{DataTable-Be6dH_dR.d.ts → DataTable-BMRU8a1j.d.ts} +34 -2
- package/dist/{DataTable-5FU7IESH.js → DataTable-TPTKCX4D.js} +10 -9
- package/dist/{PublicPageProvider-C0Sm_e5k.d.ts → PublicPageProvider-DC6kCaqf.d.ts} +385 -261
- package/dist/{UnifiedAuthProvider-RGJTDE2C.js → UnifiedAuthProvider-CH6Z342H.js} +3 -3
- package/dist/{UnifiedAuthProvider-185Ih4dj.d.ts → UnifiedAuthProvider-CVcTjx-d.d.ts} +29 -0
- package/dist/{api-N774RPUA.js → api-MVVQZLJI.js} +2 -2
- package/dist/{chunk-KNC55RTG.js → chunk-24UVZUZG.js} +90 -54
- package/dist/chunk-24UVZUZG.js.map +1 -0
- package/dist/{chunk-HWIIPPNI.js → chunk-2UOI2FG5.js} +20 -20
- package/dist/chunk-2UOI2FG5.js.map +1 -0
- package/dist/{chunk-E3SPN4VZ 5.js → chunk-3XC4CPTD.js} +4345 -3986
- package/dist/chunk-3XC4CPTD.js.map +1 -0
- package/dist/{chunk-7EQTDTTJ.js → chunk-6J4GEEJR.js} +172 -45
- package/dist/chunk-6J4GEEJR.js.map +1 -0
- package/dist/{chunk-6C4YBBJM 5.js → chunk-6SOIHG6Z.js} +1 -1
- package/dist/chunk-6SOIHG6Z.js.map +1 -0
- package/dist/{chunk-7FLMSG37.js → chunk-EHMR7VYL.js} +25 -25
- package/dist/chunk-EHMR7VYL.js.map +1 -0
- package/dist/{chunk-I7PSE6JW.js → chunk-F2IMUDXZ.js} +2 -75
- package/dist/chunk-F2IMUDXZ.js.map +1 -0
- package/dist/{chunk-QWWZ5CAQ.js → chunk-FFQEQTNW.js} +7 -9
- package/dist/chunk-FFQEQTNW.js.map +1 -0
- package/dist/chunk-FMUCXFII.js +76 -0
- package/dist/chunk-FMUCXFII.js.map +1 -0
- package/dist/{chunk-HW3OVDUF.js → chunk-J36DSWQK.js} +1 -1
- package/dist/{chunk-HW3OVDUF.js.map → chunk-J36DSWQK.js.map} +1 -1
- package/dist/{chunk-SQGMNID3.js → chunk-L4OXEN46.js} +4 -5
- package/dist/chunk-L4OXEN46.js.map +1 -0
- package/dist/{chunk-R77UEZ4E 3.js → chunk-M43Y4SSO.js} +1 -1
- package/dist/chunk-M43Y4SSO.js.map +1 -0
- package/dist/{chunk-IIELH4DL.js → chunk-MMZ7JXPU.js} +60 -223
- package/dist/chunk-MMZ7JXPU.js.map +1 -0
- package/dist/{chunk-NOAYCWCX 5.js → chunk-NECFR5MM.js} +394 -312
- package/dist/chunk-NECFR5MM.js.map +1 -0
- package/dist/{chunk-BC4IJKSL.js → chunk-SFZUDBL5.js} +40 -4
- package/dist/chunk-SFZUDBL5.js.map +1 -0
- package/dist/{chunk-XNXXZ43G.js → chunk-XWQCNGTQ.js} +748 -364
- package/dist/chunk-XWQCNGTQ.js.map +1 -0
- package/dist/components.d.ts +6 -6
- package/dist/components.js +15 -12
- package/dist/components.js.map +1 -1
- package/dist/{functions-D_kgHktt.d.ts → functions-DHebl8-F.d.ts} +1 -1
- package/dist/hooks.d.ts +59 -126
- package/dist/hooks.js +19 -28
- package/dist/hooks.js.map +1 -1
- package/dist/index.d.ts +63 -16
- package/dist/index.js +23 -24
- package/dist/index.js.map +1 -1
- package/dist/providers.d.ts +21 -3
- package/dist/providers.js +2 -2
- package/dist/rbac/index.d.ts +146 -115
- package/dist/rbac/index.js +8 -11
- package/dist/theming/runtime.d.ts +1 -13
- package/dist/theming/runtime.js +1 -1
- package/dist/{timezone-_pgH8qrY.d.ts → timezone-CHhWg6b4.d.ts} +3 -10
- package/dist/{types-UU913iLA.d.ts → types-BeoeWV5I.d.ts} +8 -0
- package/dist/{types-CEpcvwwF.d.ts → types-CkbwOr4Y.d.ts} +6 -0
- package/dist/types.d.ts +2 -2
- package/dist/{usePublicRouteParams-TZe0gy-4.d.ts → usePublicRouteParams-1oMokgLF.d.ts} +34 -4
- package/dist/{useToast-C8gR5ir4.d.ts → useToast-AyaT-x7p.d.ts} +2 -2
- package/dist/utils.d.ts +4 -5
- package/dist/utils.js +15 -15
- package/dist/utils.js.map +1 -1
- package/docs/api/README.md +7 -1
- package/docs/api/classes/ColumnFactory.md +8 -8
- package/docs/api/classes/InvalidScopeError.md +4 -4
- package/docs/api/classes/Logger.md +1 -1
- package/docs/api/classes/MissingUserContextError.md +4 -4
- package/docs/api/classes/OrganisationContextRequiredError.md +4 -4
- package/docs/api/classes/PermissionDeniedError.md +4 -4
- package/docs/api/classes/RBACAuditManager.md +1 -1
- package/docs/api/classes/RBACCache.md +1 -1
- package/docs/api/classes/RBACEngine.md +1 -1
- package/docs/api/classes/RBACError.md +4 -4
- package/docs/api/classes/RBACNotInitializedError.md +4 -4
- package/docs/api/classes/SecureSupabaseClient.md +18 -15
- package/docs/api/classes/StorageUtils.md +1 -1
- package/docs/api/enums/FileCategory.md +1 -1
- package/docs/api/enums/LogLevel.md +1 -1
- package/docs/api/enums/RBACErrorCode.md +1 -1
- package/docs/api/enums/RPCFunction.md +1 -1
- package/docs/api/interfaces/AddressFieldProps.md +1 -1
- package/docs/api/interfaces/AddressFieldRef.md +1 -1
- package/docs/api/interfaces/AggregateConfig.md +4 -4
- package/docs/api/interfaces/AutocompleteOptions.md +1 -1
- package/docs/api/interfaces/AvatarProps.md +1 -1
- package/docs/api/interfaces/BadgeProps.md +9 -2
- package/docs/api/interfaces/ButtonProps.md +7 -4
- package/docs/api/interfaces/CalendarProps.md +8 -5
- package/docs/api/interfaces/CardProps.md +8 -5
- package/docs/api/interfaces/ColorPalette.md +1 -1
- package/docs/api/interfaces/ColorShade.md +1 -1
- package/docs/api/interfaces/ComplianceResult.md +1 -1
- package/docs/api/interfaces/DataAccessRecord.md +9 -9
- package/docs/api/interfaces/DataRecord.md +1 -1
- package/docs/api/interfaces/DataTableAction.md +24 -21
- package/docs/api/interfaces/DataTableColumn.md +31 -31
- package/docs/api/interfaces/DataTableProps.md +1 -1
- package/docs/api/interfaces/DataTableToolbarButton.md +7 -7
- package/docs/api/interfaces/DatabaseComplianceResult.md +1 -1
- package/docs/api/interfaces/DatabaseIssue.md +1 -1
- package/docs/api/interfaces/EmptyStateConfig.md +5 -5
- package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
- package/docs/api/interfaces/ErrorBoundaryProps.md +147 -0
- package/docs/api/interfaces/ErrorBoundaryProviderProps.md +36 -0
- package/docs/api/interfaces/ErrorBoundaryState.md +75 -0
- package/docs/api/interfaces/EventAppRoleData.md +1 -1
- package/docs/api/interfaces/ExportColumn.md +1 -1
- package/docs/api/interfaces/ExportOptions.md +8 -8
- 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 +26 -23
- package/docs/api/interfaces/FooterProps.md +10 -8
- package/docs/api/interfaces/FormFieldProps.md +10 -10
- package/docs/api/interfaces/FormProps.md +1 -1
- package/docs/api/interfaces/GrantEventAppRoleParams.md +1 -1
- package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
- package/docs/api/interfaces/InputProps.md +7 -4
- package/docs/api/interfaces/LabelProps.md +1 -1
- package/docs/api/interfaces/LoggerConfig.md +1 -1
- package/docs/api/interfaces/LoginFormProps.md +14 -11
- package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
- package/docs/api/interfaces/NavigationContextType.md +1 -1
- package/docs/api/interfaces/NavigationGuardProps.md +1 -1
- package/docs/api/interfaces/NavigationItem.md +11 -11
- package/docs/api/interfaces/NavigationMenuProps.md +15 -15
- package/docs/api/interfaces/NavigationProviderProps.md +1 -1
- package/docs/api/interfaces/Organisation.md +1 -1
- package/docs/api/interfaces/OrganisationContextType.md +1 -1
- package/docs/api/interfaces/OrganisationMembership.md +1 -1
- package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
- package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
- package/docs/api/interfaces/PaceAppLayoutProps.md +30 -27
- package/docs/api/interfaces/PaceLoginPageProps.md +6 -4
- package/docs/api/interfaces/PageAccessRecord.md +1 -1
- package/docs/api/interfaces/PagePermissionContextType.md +1 -1
- package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
- package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
- package/docs/api/interfaces/PaletteData.md +1 -1
- package/docs/api/interfaces/ParsedAddress.md +1 -1
- package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
- package/docs/api/interfaces/ProgressProps.md +1 -1
- package/docs/api/interfaces/ProtectedRouteProps.md +7 -26
- package/docs/api/interfaces/PublicPageFooterProps.md +9 -9
- package/docs/api/interfaces/PublicPageHeaderProps.md +10 -10
- package/docs/api/interfaces/PublicPageLayoutProps.md +7 -20
- package/docs/api/interfaces/QuickFix.md +1 -1
- package/docs/api/interfaces/RBACAccessValidateParams.md +1 -1
- package/docs/api/interfaces/RBACAccessValidateResult.md +1 -1
- package/docs/api/interfaces/RBACAuditLogParams.md +1 -1
- package/docs/api/interfaces/RBACAuditLogResult.md +1 -1
- package/docs/api/interfaces/RBACConfig.md +1 -1
- package/docs/api/interfaces/RBACContext.md +1 -1
- package/docs/api/interfaces/RBACLogger.md +1 -1
- package/docs/api/interfaces/RBACPageAccessCheckParams.md +1 -1
- package/docs/api/interfaces/RBACPerformanceMetrics.md +1 -1
- package/docs/api/interfaces/RBACPermissionCheckParams.md +1 -1
- package/docs/api/interfaces/RBACPermissionCheckResult.md +1 -1
- package/docs/api/interfaces/RBACPermissionsGetParams.md +1 -1
- package/docs/api/interfaces/RBACPermissionsGetResult.md +1 -1
- package/docs/api/interfaces/RBACResult.md +1 -1
- package/docs/api/interfaces/RBACRoleGrantParams.md +1 -1
- package/docs/api/interfaces/RBACRoleGrantResult.md +1 -1
- package/docs/api/interfaces/RBACRoleRevokeParams.md +1 -1
- package/docs/api/interfaces/RBACRoleRevokeResult.md +1 -1
- package/docs/api/interfaces/RBACRoleValidateParams.md +1 -1
- package/docs/api/interfaces/RBACRoleValidateResult.md +1 -1
- package/docs/api/interfaces/RBACRolesListParams.md +1 -1
- package/docs/api/interfaces/RBACRolesListResult.md +1 -1
- package/docs/api/interfaces/RBACSessionTrackParams.md +1 -1
- package/docs/api/interfaces/RBACSessionTrackResult.md +1 -1
- package/docs/api/interfaces/ResourcePermissions.md +1 -1
- package/docs/api/interfaces/RevokeEventAppRoleParams.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
- package/docs/api/interfaces/RoleManagementResult.md +1 -1
- package/docs/api/interfaces/RouteAccessRecord.md +1 -1
- package/docs/api/interfaces/RouteConfig.md +1 -1
- package/docs/api/interfaces/RuntimeComplianceResult.md +1 -1
- package/docs/api/interfaces/SecureDataContextType.md +9 -9
- package/docs/api/interfaces/SecureDataProviderProps.md +8 -8
- package/docs/api/interfaces/SessionRestorationLoaderProps.md +3 -3
- package/docs/api/interfaces/SetupIssue.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/TabsContentProps.md +1 -1
- package/docs/api/interfaces/TabsListProps.md +1 -1
- package/docs/api/interfaces/TabsProps.md +1 -1
- package/docs/api/interfaces/TabsTriggerProps.md +3 -3
- package/docs/api/interfaces/TextareaProps.md +1 -1
- package/docs/api/interfaces/ToastActionElement.md +4 -1
- package/docs/api/interfaces/ToastProps.md +1 -1
- package/docs/api/interfaces/UnifiedAuthContextType.md +58 -55
- package/docs/api/interfaces/UnifiedAuthProviderProps.md +15 -13
- package/docs/api/interfaces/UseFormDialogOptions.md +1 -1
- package/docs/api/interfaces/UseFormDialogReturn.md +1 -1
- package/docs/api/interfaces/UseInactivityTrackerOptions.md +11 -9
- package/docs/api/interfaces/UseInactivityTrackerReturn.md +8 -8
- package/docs/api/interfaces/UsePublicEventLogoOptions.md +6 -6
- package/docs/api/interfaces/UsePublicEventLogoReturn.md +9 -6
- package/docs/api/interfaces/UsePublicEventOptions.md +3 -3
- package/docs/api/interfaces/UsePublicEventReturn.md +8 -5
- package/docs/api/interfaces/UsePublicFileDisplayOptions.md +4 -4
- package/docs/api/interfaces/UsePublicFileDisplayReturn.md +12 -9
- package/docs/api/interfaces/UsePublicRouteParamsReturn.md +10 -7
- package/docs/api/interfaces/UseResolvedScopeOptions.md +1 -1
- package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
- package/docs/api/interfaces/UseResourcePermissionsOptions.md +1 -1
- package/docs/api/interfaces/UserEventAccess.md +14 -11
- package/docs/api/interfaces/UserMenuProps.md +8 -6
- package/docs/api/interfaces/UserProfile.md +1 -1
- package/docs/api/modules.md +575 -634
- package/docs/architecture/database-schema-requirements.md +161 -0
- package/docs/core-concepts/rbac-system.md +3 -3
- package/docs/documentation-index.md +2 -4
- package/docs/getting-started/cursor-rules.md +263 -0
- package/docs/getting-started/installation-guide.md +6 -1
- package/docs/getting-started/quick-start.md +6 -1
- package/docs/migration/DOCUMENTATION_STRUCTURE.md +441 -0
- package/docs/migration/MIGRATION_GUIDE.md +6 -28
- package/docs/migration/README.md +52 -6
- package/docs/migration/V0.5.190_TO_V0.6.1_MIGRATION.md +1153 -0
- package/docs/migration/V0.6.0_REACT_19_MIGRATION.md +227 -0
- package/docs/migration/database-changes-december-2025.md +3 -3
- package/docs/rbac/event-based-apps.md +1 -1
- package/docs/rbac/getting-started.md +1 -1
- package/docs/rbac/quick-start.md +1 -1
- package/docs/standards/README.md +40 -0
- package/docs/troubleshooting/migration.md +4 -4
- package/examples/PublicPages/PublicEventPage.tsx +1 -1
- package/package.json +12 -6
- package/scripts/audit/core/checks/accessibility.cjs +197 -0
- package/scripts/audit/core/checks/api-usage.cjs +191 -0
- package/scripts/audit/core/checks/bundle.cjs +142 -0
- package/scripts/{check-pace-core-compliance.cjs → audit/core/checks/compliance.cjs} +737 -691
- package/scripts/audit/core/checks/config.cjs +54 -0
- package/scripts/audit/core/checks/coverage.cjs +84 -0
- package/scripts/audit/core/checks/dependencies.cjs +454 -0
- package/scripts/audit/core/checks/documentation.cjs +203 -0
- package/scripts/audit/core/checks/environment.cjs +128 -0
- package/scripts/audit/core/checks/error-handling.cjs +299 -0
- package/scripts/audit/core/checks/forms.cjs +172 -0
- package/scripts/audit/core/checks/heuristics.cjs +68 -0
- package/scripts/audit/core/checks/hooks.cjs +334 -0
- package/scripts/audit/core/checks/imports.cjs +244 -0
- package/scripts/audit/core/checks/performance.cjs +325 -0
- package/scripts/audit/core/checks/routes.cjs +117 -0
- package/scripts/audit/core/checks/state.cjs +130 -0
- package/scripts/audit/core/checks/structure.cjs +65 -0
- package/scripts/audit/core/checks/style.cjs +584 -0
- package/scripts/audit/core/checks/testing.cjs +122 -0
- package/scripts/audit/core/checks/typescript.cjs +61 -0
- package/scripts/audit/core/scanner.cjs +199 -0
- package/scripts/audit/core/utils.cjs +137 -0
- package/scripts/audit/index.cjs +223 -0
- package/scripts/audit/reporters/console.cjs +151 -0
- package/scripts/audit/reporters/json.cjs +54 -0
- package/scripts/audit/reporters/markdown.cjs +124 -0
- package/scripts/audit-consuming-app.cjs +86 -0
- package/scripts/build-docs/build-decision.js +240 -0
- package/scripts/build-docs/cache-utils.js +105 -0
- package/scripts/build-docs/content-normalization.js +150 -0
- package/scripts/build-docs/file-utils.js +105 -0
- package/scripts/build-docs/git-utils.js +86 -0
- package/scripts/build-docs/hash-utils.js +116 -0
- package/scripts/build-docs/typedoc-runner.js +220 -0
- package/scripts/build-docs-incremental.js +77 -913
- package/scripts/install-cursor-rules.cjs +236 -0
- package/scripts/utils/command-runner.js +16 -11
- package/scripts/validate-formats.js +61 -56
- package/scripts/validate-master.js +74 -69
- package/scripts/validate-pre-publish.js +70 -65
- package/src/__tests__/helpers/test-providers.tsx +1 -1
- package/src/__tests__/helpers/test-utils.tsx +1 -1
- package/src/__tests__/hooks/usePermissions.test.ts +2 -2
- package/src/components/Alert/Alert.test.tsx +12 -18
- package/src/components/Alert/Alert.tsx +5 -7
- package/src/components/Avatar/Avatar.test.tsx +4 -4
- package/src/components/Badge/Badge.tsx +16 -4
- package/src/components/Button/Button.tsx +27 -4
- package/src/components/Calendar/Calendar.tsx +9 -3
- package/src/components/Card/Card.tsx +4 -0
- package/src/components/Checkbox/Checkbox.test.tsx +12 -12
- package/src/components/Checkbox/Checkbox.tsx +2 -2
- package/src/components/DataTable/DataTable.test.tsx +57 -93
- package/src/components/DataTable/DataTable.tsx +40 -6
- package/src/components/DataTable/__tests__/DataTableCore.test-setup.ts +5 -6
- package/src/components/DataTable/__tests__/pagination.modes.test.tsx +29 -7
- package/src/components/DataTable/__tests__/ssr.strict-mode.test.tsx +12 -12
- package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +2 -3
- package/src/components/DataTable/components/AccessDeniedPage.tsx +17 -26
- package/src/components/DataTable/components/ActionButtons.tsx +10 -7
- package/src/components/DataTable/components/BulkOperationsDropdown.tsx +2 -2
- package/src/components/DataTable/components/ColumnFilter.tsx +10 -0
- package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +12 -0
- package/src/components/DataTable/components/DataTableBody.tsx +8 -0
- package/src/components/DataTable/components/DataTableCore.tsx +200 -561
- package/src/components/DataTable/components/DataTableErrorBoundary.tsx +11 -0
- package/src/components/DataTable/components/DataTableLayout.tsx +559 -0
- package/src/components/DataTable/components/DataTableModals.tsx +9 -1
- package/src/components/DataTable/components/DataTableToolbar.tsx +8 -0
- package/src/components/DataTable/components/DraggableColumnHeader.tsx +12 -0
- package/src/components/DataTable/components/EditFields.tsx +307 -0
- package/src/components/DataTable/components/EditableRow.tsx +9 -1
- package/src/components/DataTable/components/EmptyState.tsx +10 -0
- package/src/components/DataTable/components/FilterRow.tsx +12 -0
- package/src/components/DataTable/components/GroupHeader.tsx +12 -0
- package/src/components/DataTable/components/GroupingDropdown.tsx +12 -0
- package/src/components/DataTable/components/ImportModal.tsx +7 -0
- package/src/components/DataTable/components/LoadingState.tsx +6 -0
- package/src/components/DataTable/components/PaginationControls.tsx +16 -1
- package/src/components/DataTable/components/RowComponent.tsx +391 -0
- package/src/components/DataTable/components/UnifiedTableBody.tsx +62 -852
- package/src/components/DataTable/components/VirtualizedDataTable.tsx +16 -4
- package/src/components/DataTable/components/__tests__/AccessDeniedPage.test.tsx +4 -2
- package/src/components/DataTable/components/__tests__/DataTableModals.test.tsx +23 -23
- package/src/components/DataTable/components/__tests__/EditableRow.test.tsx +11 -11
- package/src/components/DataTable/components/__tests__/ExpandButton.test.tsx +36 -36
- package/src/components/DataTable/components/__tests__/GroupHeader.test.tsx +27 -27
- package/src/components/DataTable/components/__tests__/ImportModal.test.tsx +39 -39
- package/src/components/DataTable/components/__tests__/UnifiedTableBody.test.tsx +33 -33
- package/src/components/DataTable/components/__tests__/ViewRowModal.test.tsx +29 -29
- package/src/components/DataTable/components/cellValueUtils.ts +40 -0
- package/src/components/DataTable/components/hooks/useImportModalFocus.ts +53 -0
- package/src/components/DataTable/components/hooks/usePermissionTracking.ts +126 -0
- package/src/components/DataTable/context/DataTableContext.tsx +50 -0
- package/src/components/DataTable/core/ColumnFactory.ts +31 -0
- package/src/components/DataTable/core/DataTableContext.tsx +32 -1
- package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +10 -0
- package/src/components/DataTable/hooks/useColumnReordering.ts +14 -2
- package/src/components/DataTable/hooks/useColumnVisibilityPersistence.ts +10 -0
- package/src/components/DataTable/hooks/useDataTableDataPipeline.ts +16 -0
- package/src/components/DataTable/hooks/useDataTablePermissions.ts +124 -32
- package/src/components/DataTable/hooks/useDataTableState.ts +35 -1
- package/src/components/DataTable/hooks/useEffectiveColumnOrder.ts +12 -0
- package/src/components/DataTable/hooks/useKeyboardNavigation.ts +2 -2
- package/src/components/DataTable/hooks/useServerSideDataEffect.ts +11 -0
- package/src/components/DataTable/hooks/useTableColumns.ts +8 -0
- package/src/components/DataTable/hooks/useTableHandlers.ts +14 -0
- package/src/components/DataTable/styles.ts +6 -6
- package/src/components/DataTable/types.ts +6 -10
- package/src/components/DataTable/utils/a11yUtils.ts +7 -0
- package/src/components/DataTable/utils/debugTools.ts +18 -113
- package/src/components/DataTable/utils/errorHandling.ts +12 -0
- package/src/components/DataTable/utils/exportUtils.ts +9 -0
- package/src/components/DataTable/utils/flexibleImport.ts +12 -48
- package/src/components/DataTable/utils/paginationUtils.ts +8 -0
- package/src/components/DataTable/utils/performanceUtils.ts +5 -1
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +8 -14
- package/src/components/Dialog/Dialog.tsx +8 -7
- package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +180 -1
- package/src/components/ErrorBoundary/ErrorBoundary.tsx +46 -6
- package/src/components/ErrorBoundary/ErrorBoundaryContext.tsx +129 -0
- package/src/components/ErrorBoundary/index.ts +27 -2
- package/src/components/EventSelector/EventSelector.tsx +4 -1
- package/src/components/FileDisplay/FileDisplay.test.tsx +2 -2
- package/src/components/FileDisplay/FileDisplay.tsx +32 -18
- package/src/components/FileUpload/FileUpload.tsx +22 -2
- package/src/components/Footer/Footer.test.tsx +16 -16
- package/src/components/Footer/Footer.tsx +15 -12
- package/src/components/Form/Form.test.tsx +36 -15
- package/src/components/Form/Form.tsx +31 -26
- package/src/components/Header/Header.tsx +22 -11
- package/src/components/InactivityWarningModal/InactivityWarningModal.test.tsx +40 -40
- package/src/components/InactivityWarningModal/InactivityWarningModal.tsx +1 -1
- package/src/components/Input/Input.test.tsx +2 -2
- package/src/components/Input/Input.tsx +36 -34
- package/src/components/Label/Label.tsx +1 -1
- package/src/components/LoadingSpinner/LoadingSpinner.test.tsx +4 -4
- package/src/components/LoadingSpinner/LoadingSpinner.tsx +1 -1
- package/src/components/LoginForm/LoginForm.test.tsx +42 -42
- package/src/components/LoginForm/LoginForm.tsx +12 -8
- package/src/components/NavigationMenu/NavigationMenu.tsx +15 -514
- package/src/components/NavigationMenu/types.ts +56 -0
- package/src/components/NavigationMenu/useNavigationFiltering.ts +390 -0
- package/src/components/OrganisationSelector/OrganisationSelector.tsx +3 -0
- package/src/components/PaceAppLayout/PaceAppLayout.performance.test.tsx +1 -1
- package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +54 -52
- package/src/components/PaceAppLayout/PaceAppLayout.tsx +33 -12
- package/src/components/PaceAppLayout/README.md +1 -1
- package/src/components/PaceAppLayout/test-setup.tsx +1 -2
- package/src/components/PaceLoginPage/PaceLoginPage.tsx +4 -1
- package/src/components/PasswordChange/PasswordChangeForm.test.tsx +33 -33
- package/src/components/PasswordChange/PasswordChangeForm.tsx +10 -1
- package/src/components/Progress/Progress.tsx +1 -1
- package/src/components/ProtectedRoute/ProtectedRoute.tsx +3 -9
- package/src/components/PublicLayout/PublicPageLayout.tsx +3 -6
- package/src/components/PublicLayout/PublicPageProvider.tsx +4 -0
- package/src/components/Select/Select.tsx +95 -438
- package/src/components/Select/context.ts +23 -0
- package/src/components/Select/hooks/useSelectEvents.ts +87 -0
- package/src/components/Select/hooks/useSelectSearch.ts +91 -0
- package/src/components/Select/hooks/useSelectState.ts +104 -0
- package/src/components/Select/index.ts +9 -1
- package/src/components/Select/types.ts +123 -0
- package/src/components/Select/utils/text.ts +26 -0
- package/src/components/SessionRestorationLoader/SessionRestorationLoader.tsx +5 -6
- package/src/components/Switch/Switch.tsx +4 -4
- package/src/components/Table/Table.tsx +1 -1
- package/src/components/Tabs/Tabs.tsx +1 -1
- package/src/components/Textarea/Textarea.tsx +27 -29
- package/src/components/Toast/Toast.tsx +5 -1
- package/src/components/Tooltip/Tooltip.tsx +3 -3
- package/src/components/UserMenu/UserMenu.test.tsx +24 -11
- package/src/components/UserMenu/UserMenu.tsx +22 -19
- package/src/components/index.ts +2 -2
- package/src/hooks/__tests__/hooks.integration.test.tsx +80 -55
- package/src/hooks/__tests__/index.unit.test.ts +2 -5
- package/src/hooks/__tests__/useStorage.unit.test.ts +36 -36
- package/src/hooks/index.ts +1 -2
- package/src/hooks/public/usePublicEvent.ts +5 -1
- package/src/hooks/public/usePublicEventLogo.ts +5 -1
- package/src/hooks/public/usePublicFileDisplay.ts +4 -0
- package/src/hooks/public/usePublicRouteParams.ts +5 -1
- package/src/hooks/services/useAuth.ts +32 -0
- package/src/hooks/services/useCurrentEvent.ts +6 -0
- package/src/hooks/services/useCurrentOrganisation.ts +6 -0
- package/src/hooks/useDataTableState.ts +8 -18
- package/src/hooks/useDebounce.ts +9 -0
- package/src/hooks/useEventTheme.ts +6 -0
- package/src/hooks/useFileDisplay.ts +4 -0
- package/src/hooks/useFileReference.ts +25 -7
- package/src/hooks/useFileUrl.ts +11 -1
- package/src/hooks/useFocusManagement.ts +16 -2
- package/src/hooks/useFocusTrap.ts +7 -4
- package/src/hooks/useFormDialog.ts +8 -7
- package/src/hooks/useInactivityTracker.ts +4 -1
- package/src/hooks/useKeyboardShortcuts.ts +4 -0
- package/src/hooks/useOrganisationPermissions.ts +4 -0
- package/src/hooks/useOrganisationSecurity.ts +4 -0
- package/src/hooks/usePerformanceMonitor.ts +4 -0
- package/src/hooks/usePermissionCache.ts +8 -1
- package/src/hooks/useQueryCache.ts +12 -1
- package/src/hooks/useSessionRestoration.ts +4 -0
- package/src/hooks/useStorage.ts +4 -0
- package/src/hooks/useToast.ts +3 -3
- package/src/index.ts +2 -1
- package/src/providers/__tests__/OrganisationProvider.test.tsx +115 -49
- package/src/providers/__tests__/ProviderLifecycle.test.tsx +21 -6
- package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +10 -10
- package/src/providers/services/AuthServiceProvider.tsx +18 -0
- package/src/providers/services/EventServiceProvider.tsx +18 -0
- package/src/providers/services/InactivityServiceProvider.tsx +18 -0
- package/src/providers/services/OrganisationServiceProvider.tsx +18 -0
- package/src/providers/services/UnifiedAuthProvider.tsx +58 -22
- package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +33 -7
- package/src/rbac/README.md +1 -1
- package/src/rbac/__tests__/adapters.comprehensive.test.tsx +26 -26
- package/src/rbac/__tests__/scenarios.user-role.test.tsx +4 -5
- package/src/rbac/adapters.tsx +14 -5
- package/src/rbac/api.ts +100 -67
- package/src/rbac/components/EnhancedNavigationMenu.tsx +1 -1
- package/src/rbac/components/NavigationGuard.tsx +1 -1
- package/src/rbac/components/NavigationProvider.tsx +5 -2
- package/src/rbac/components/PagePermissionGuard.tsx +158 -18
- package/src/rbac/components/PagePermissionProvider.tsx +1 -1
- package/src/rbac/components/PermissionEnforcer.tsx +1 -1
- package/src/rbac/components/RoleBasedRouter.tsx +6 -2
- package/src/rbac/components/SecureDataProvider.test.tsx +84 -49
- package/src/rbac/components/SecureDataProvider.tsx +21 -6
- package/src/rbac/components/__tests__/PagePermissionGuard.race-condition.test.tsx +24 -14
- package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +7 -0
- package/src/rbac/components/__tests__/PagePermissionGuard.verification.test.tsx +14 -6
- package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +15 -4
- package/src/rbac/components/__tests__/SecureDataProvider.fixed.test.tsx +148 -24
- package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +81 -15
- package/src/rbac/engine.ts +38 -14
- package/src/rbac/hooks/permissions/index.ts +7 -0
- package/src/rbac/hooks/permissions/useAccessLevel.ts +105 -0
- package/src/rbac/hooks/permissions/useCachedPermissions.ts +79 -0
- package/src/rbac/hooks/permissions/useCan.ts +347 -0
- package/src/rbac/hooks/permissions/useHasAllPermissions.ts +90 -0
- package/src/rbac/hooks/permissions/useHasAnyPermission.ts +90 -0
- package/src/rbac/hooks/permissions/useMultiplePermissions.ts +93 -0
- package/src/rbac/hooks/permissions/usePermissions.ts +253 -0
- package/src/rbac/hooks/useCan.test.ts +71 -64
- package/src/rbac/hooks/usePermissions.ts +14 -995
- package/src/rbac/hooks/useResourcePermissions.test.ts +54 -18
- package/src/rbac/hooks/useResourcePermissions.ts +14 -4
- package/src/rbac/hooks/useSecureSupabase.ts +33 -13
- package/src/rbac/permissions.ts +0 -30
- package/src/rbac/secureClient.ts +212 -61
- package/src/rbac/types.ts +8 -0
- package/src/theming/__tests__/parseEventColours.test.ts +6 -9
- package/src/theming/parseEventColours.ts +5 -19
- package/src/types/vitest-globals.d.ts +51 -26
- package/src/utils/__mocks__/supabaseMock.ts +1 -3
- package/src/utils/__tests__/formatting.unit.test.ts +4 -4
- package/src/utils/__tests__/index.unit.test.ts +2 -2
- package/src/utils/audit/audit.ts +0 -3
- package/src/utils/core/cn.ts +1 -1
- package/src/utils/file-reference/index.ts +53 -1
- package/src/utils/formatting/formatting.ts +8 -18
- package/src/utils/index.ts +0 -1
- package/src/utils/security/secureDataAccess.test.ts +31 -20
- package/src/utils/security/secureDataAccess.ts +4 -3
- package/dist/chunk-6C4YBBJM.js +0 -628
- package/dist/chunk-6C4YBBJM.js.map +0 -1
- package/dist/chunk-7D4SUZUM.js 2.map +0 -1
- package/dist/chunk-7EQTDTTJ.js 2.map +0 -1
- package/dist/chunk-7EQTDTTJ.js.map +0 -1
- package/dist/chunk-7FLMSG37.js 2.map +0 -1
- package/dist/chunk-7FLMSG37.js.map +0 -1
- package/dist/chunk-BC4IJKSL.js.map +0 -1
- package/dist/chunk-E3SPN4VZ.js +0 -12917
- package/dist/chunk-E3SPN4VZ.js.map +0 -1
- package/dist/chunk-E66EQZE6 5.js +0 -37
- package/dist/chunk-E66EQZE6.js 2.map +0 -1
- package/dist/chunk-HWIIPPNI.js.map +0 -1
- package/dist/chunk-I7PSE6JW 5.js +0 -191
- package/dist/chunk-I7PSE6JW.js 2.map +0 -1
- package/dist/chunk-I7PSE6JW.js.map +0 -1
- package/dist/chunk-IIELH4DL.js.map +0 -1
- package/dist/chunk-KNC55RTG.js 5.map +0 -1
- package/dist/chunk-KNC55RTG.js.map +0 -1
- package/dist/chunk-KQCRWDSA.js 5.map +0 -1
- package/dist/chunk-LFNCN2SP.js +0 -412
- package/dist/chunk-LFNCN2SP.js 2.map +0 -1
- package/dist/chunk-LFNCN2SP.js.map +0 -1
- package/dist/chunk-LMC26NLJ 2.js +0 -84
- package/dist/chunk-NOAYCWCX.js +0 -4993
- package/dist/chunk-NOAYCWCX.js.map +0 -1
- package/dist/chunk-QWWZ5CAQ.js 3.map +0 -1
- package/dist/chunk-QWWZ5CAQ.js.map +0 -1
- package/dist/chunk-QXHPKYJV 3.js +0 -113
- package/dist/chunk-R77UEZ4E.js +0 -68
- package/dist/chunk-R77UEZ4E.js.map +0 -1
- package/dist/chunk-SQGMNID3.js.map +0 -1
- package/dist/chunk-VBXEHIUJ.js 6.map +0 -1
- package/dist/chunk-XNXXZ43G.js.map +0 -1
- package/dist/chunk-ZSAAAMVR 6.js +0 -25
- package/dist/components.js 5.map +0 -1
- package/dist/styles/index 2.js +0 -12
- package/dist/styles/index.js 5.map +0 -1
- package/dist/theming/runtime 5.js +0 -19
- package/dist/theming/runtime.js 5.map +0 -1
- package/docs/api/classes/ErrorBoundary.md +0 -144
- package/docs/migration/quick-migration-guide.md +0 -356
- package/docs/migration/service-architecture.md +0 -281
- package/src/hooks/__tests__/useSecureDataAccess.unit.test.tsx +0 -680
- package/src/hooks/useSecureDataAccess.test.ts +0 -559
- package/src/hooks/useSecureDataAccess.ts +0 -666
- /package/dist/{DataTable-5FU7IESH.js.map → DataTable-TPTKCX4D.js.map} +0 -0
- /package/dist/{UnifiedAuthProvider-RGJTDE2C.js.map → UnifiedAuthProvider-CH6Z342H.js.map} +0 -0
- /package/dist/{api-N774RPUA.js.map → api-MVVQZLJI.js.map} +0 -0
- /package/docs/migration/{organisation-context-timing-fix.md → V0.3.44_organisation-context-timing-fix.md} +0 -0
- /package/docs/migration/{rbac-migration.md → V0.4.0_rbac-migration.md} +0 -0
- /package/docs/migration/{person-scoped-profiles-migration-guide.md → V0.5.190_person-scoped-profiles-migration-guide.md} +0 -0
- /package/examples/{rbac → RBAC}/CompleteRBACExample.tsx +0 -0
- /package/examples/{rbac → RBAC}/EventBasedApp.tsx +0 -0
- /package/examples/{rbac → RBAC}/PermissionExample.tsx +0 -0
- /package/examples/{rbac → RBAC}/index.ts +0 -0
|
@@ -22,6 +22,10 @@ import {
|
|
|
22
22
|
} from '../types';
|
|
23
23
|
import type { Permission } from '../../../rbac/types';
|
|
24
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Return value of the useDataTablePermissions hook.
|
|
27
|
+
* Contains permission checks and secure feature configuration.
|
|
28
|
+
*/
|
|
25
29
|
export interface UseDataTablePermissionsReturn {
|
|
26
30
|
permissions: {
|
|
27
31
|
canRead: ReturnType<typeof useCan>;
|
|
@@ -35,6 +39,15 @@ export interface UseDataTablePermissionsReturn {
|
|
|
35
39
|
effectivePageId: string | undefined;
|
|
36
40
|
}
|
|
37
41
|
|
|
42
|
+
/**
|
|
43
|
+
* Hook for managing RBAC permissions in DataTable components.
|
|
44
|
+
* Handles scope resolution, permission checks, and secure feature configuration.
|
|
45
|
+
*
|
|
46
|
+
* @template TData - The type of data records in the table
|
|
47
|
+
* @param rbac - RBAC configuration for the DataTable
|
|
48
|
+
* @param features - Feature configuration to secure
|
|
49
|
+
* @returns Permission checks and secure feature configuration
|
|
50
|
+
*/
|
|
38
51
|
export function useDataTablePermissions<TData extends DataRecord>(
|
|
39
52
|
rbac: DataTableRBACConfig,
|
|
40
53
|
features: DataTableFeatureConfig = {}
|
|
@@ -45,26 +58,69 @@ export function useDataTablePermissions<TData extends DataRecord>(
|
|
|
45
58
|
|
|
46
59
|
// Super admin status - check if user has super admin privileges
|
|
47
60
|
// Super admins bypass all permission checks (similar to PaceAppLayout)
|
|
48
|
-
|
|
49
|
-
|
|
61
|
+
// PERFORMANCE OPTIMIZATION: Check super admin once and share with all useCan hooks to avoid duplicate queries
|
|
62
|
+
// Use null to indicate "not checked yet" vs false which means "checked and not super admin"
|
|
63
|
+
const [isSuperAdminUser, setIsSuperAdminUser] = useState<boolean | null>(null);
|
|
64
|
+
const [isCheckingSuperAdmin, setIsCheckingSuperAdmin] = useState<boolean>(() => !!user?.id);
|
|
65
|
+
const lastCheckedUserIdRef = useRef<string | null>(null);
|
|
66
|
+
const isCheckingRef = useRef<boolean>(false);
|
|
50
67
|
|
|
51
68
|
useEffect(() => {
|
|
69
|
+
// Skip if already checked for this user ID
|
|
70
|
+
if (lastCheckedUserIdRef.current === user?.id && isSuperAdminUser !== null) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Skip if already checking
|
|
75
|
+
if (isCheckingRef.current) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
52
79
|
const checkSuperAdminStatus = async () => {
|
|
53
80
|
if (!user?.id) {
|
|
54
|
-
setIsSuperAdminUser(false);
|
|
81
|
+
setIsSuperAdminUser(false); // No user = not super admin
|
|
55
82
|
setIsCheckingSuperAdmin(false);
|
|
83
|
+
lastCheckedUserIdRef.current = null;
|
|
56
84
|
return;
|
|
57
85
|
}
|
|
58
86
|
|
|
87
|
+
// Mark as checking and track user ID
|
|
88
|
+
isCheckingRef.current = true;
|
|
89
|
+
lastCheckedUserIdRef.current = user.id;
|
|
90
|
+
|
|
91
|
+
const startTime = Date.now();
|
|
59
92
|
setIsCheckingSuperAdmin(true);
|
|
93
|
+
|
|
94
|
+
// Add timeout to prevent infinite hanging
|
|
95
|
+
const timeoutId = setTimeout(() => {
|
|
96
|
+
logger.warn('useDataTablePermissions', 'Super admin check taking longer than 5 seconds', {
|
|
97
|
+
userId: user?.id,
|
|
98
|
+
elapsedMs: Date.now() - startTime,
|
|
99
|
+
});
|
|
100
|
+
}, 5000);
|
|
101
|
+
|
|
60
102
|
try {
|
|
103
|
+
logger.debug('useDataTablePermissions', 'Starting super admin check', { userId: user?.id });
|
|
61
104
|
const superAdminStatus = await isSuperAdmin(user.id);
|
|
105
|
+
const elapsed = Date.now() - startTime;
|
|
106
|
+
logger.debug('useDataTablePermissions', 'Super admin check completed', {
|
|
107
|
+
userId: user?.id,
|
|
108
|
+
isSuperAdmin: superAdminStatus,
|
|
109
|
+
elapsedMs: elapsed,
|
|
110
|
+
});
|
|
62
111
|
setIsSuperAdminUser(superAdminStatus);
|
|
63
112
|
} catch (error) {
|
|
64
|
-
|
|
65
|
-
|
|
113
|
+
const elapsed = Date.now() - startTime;
|
|
114
|
+
logger.error('useDataTablePermissions', 'Error checking super admin status', {
|
|
115
|
+
userId: user?.id,
|
|
116
|
+
error,
|
|
117
|
+
elapsedMs: elapsed,
|
|
118
|
+
});
|
|
119
|
+
setIsSuperAdminUser(false); // Error = assume not super admin for security
|
|
66
120
|
} finally {
|
|
121
|
+
clearTimeout(timeoutId);
|
|
67
122
|
setIsCheckingSuperAdmin(false);
|
|
123
|
+
isCheckingRef.current = false;
|
|
68
124
|
}
|
|
69
125
|
};
|
|
70
126
|
|
|
@@ -156,24 +212,36 @@ export function useDataTablePermissions<TData extends DataRecord>(
|
|
|
156
212
|
* This allows permission checks for users without organisations (e.g., profile pages).
|
|
157
213
|
* The database function rbac_check_permission_simplified can handle NULL organisation_id.
|
|
158
214
|
*
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
-
*
|
|
215
|
+
* PERFORMANCE OPTIMIZATION: For page-level permissions with pageId (UUID), we don't need to wait
|
|
216
|
+
* for full scope resolution. The database function can handle page-level permissions without
|
|
217
|
+
* organisationId or appId. We only need to wait if:
|
|
218
|
+
* 1. We're using pageName (not UUID) and need appId to resolve it, OR
|
|
219
|
+
* 2. We need organisationId for resource-level permissions (but we're using page-level here)
|
|
162
220
|
*
|
|
163
|
-
*
|
|
164
|
-
* the pageName to a pageId, which causes permission checks to fail initially, showing
|
|
165
|
-
* "Access Denied" before the scope resolves and permissions are re-checked.
|
|
221
|
+
* This allows permission checks to proceed in parallel with scope resolution, reducing load time.
|
|
166
222
|
*/
|
|
167
223
|
const isPageName = !pageId && !!pageName; // We're using pageName, not a UUID pageId
|
|
168
224
|
const needsAppIdForResolution = isPageName; // Only need appId if we're resolving a pageName
|
|
169
225
|
|
|
170
|
-
//
|
|
171
|
-
//
|
|
172
|
-
//
|
|
173
|
-
//
|
|
174
|
-
const
|
|
226
|
+
// PERFORMANCE FIX: For page-level permissions with UUID pageId, we can proceed immediately
|
|
227
|
+
// The database function handles page-level permissions without requiring full scope
|
|
228
|
+
// Only wait if we're using pageName (which needs appId to resolve) or if scope is critical
|
|
229
|
+
// For page-level permissions, organisationId and appId are optional
|
|
230
|
+
const hasPageId = !!pageId && typeof pageId === 'string';
|
|
231
|
+
const canProceedWithoutFullScope = hasPageId && !isPageName; // UUID pageId doesn't need appId
|
|
232
|
+
|
|
233
|
+
// Wait for scope resolution only if:
|
|
234
|
+
// 1. We're using pageName and don't have appId yet (needed to resolve pageName to pageId), OR
|
|
235
|
+
// 2. Scope is loading AND we don't have a UUID pageId (can't proceed without scope)
|
|
236
|
+
// This allows permission checks to start earlier for UUID pageIds, reducing load time
|
|
237
|
+
const shouldWaitForScope = (needsAppIdForResolution && !stableScope.appId) ||
|
|
238
|
+
(scopeLoading && !canProceedWithoutFullScope);
|
|
175
239
|
|
|
176
|
-
|
|
240
|
+
// Use available scope immediately if we can proceed, otherwise wait
|
|
241
|
+
// For page-level permissions, empty scope is acceptable (database handles it)
|
|
242
|
+
const effectiveScope = (!shouldWaitForScope && (stableScope.organisationId || stableScope.appId || stableScope.eventId || canProceedWithoutFullScope))
|
|
243
|
+
? stableScope
|
|
244
|
+
: (canProceedWithoutFullScope ? { organisationId: undefined, eventId: undefined, appId: undefined } : null);
|
|
177
245
|
|
|
178
246
|
// Always call hooks with consistent parameters to avoid React hooks order violations
|
|
179
247
|
const userId = user?.id || '';
|
|
@@ -189,28 +257,39 @@ export function useDataTablePermissions<TData extends DataRecord>(
|
|
|
189
257
|
const consistentScope = effectiveScope || { organisationId: undefined, eventId: undefined, appId: undefined };
|
|
190
258
|
|
|
191
259
|
// Check permissions using useCan hooks
|
|
260
|
+
// PERFORMANCE OPTIMIZATION: Pass precomputed super admin status to avoid duplicate checks
|
|
261
|
+
// Each useCan hook would normally check super admin separately (6+ queries), but we check once here
|
|
262
|
+
// and share the result. Pass null if not checked yet (hooks will check), false/true if checked.
|
|
192
263
|
// Note: The database function already handles super admin bypass, but we check here
|
|
193
264
|
// as an additional safety layer to prevent unnecessary permission checks and ensure
|
|
194
265
|
// super admins never see "Access Denied" even if useCan hasn't completed
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
const
|
|
198
|
-
const
|
|
199
|
-
const
|
|
200
|
-
const
|
|
266
|
+
// Pass super admin status directly - null means not checked yet, false/true means checked
|
|
267
|
+
// This eliminates duplicate super admin checks across all 6 permission hooks
|
|
268
|
+
const canReadResult = useCan(userId, consistentScope, readPermission, effectivePageId, true, isSuperAdminUser);
|
|
269
|
+
const canCreateResult = useCan(userId, consistentScope, createPermission, effectivePageId, true, isSuperAdminUser);
|
|
270
|
+
const canUpdateResult = useCan(userId, consistentScope, updatePermission, effectivePageId, true, isSuperAdminUser);
|
|
271
|
+
const canDeleteResult = useCan(userId, consistentScope, deletePermission, effectivePageId, true, isSuperAdminUser);
|
|
272
|
+
const canExportResult = useCan(userId, consistentScope, readPermission, effectivePageId, true, isSuperAdminUser); // Use read permission for export
|
|
273
|
+
const canImportResult = useCan(userId, consistentScope, createPermission, effectivePageId, true, isSuperAdminUser); // Use create permission for import
|
|
201
274
|
|
|
202
275
|
// Create permission wrappers that bypass checks for super admins
|
|
203
276
|
// Super admins get can: true for all permissions, but we preserve isLoading and error states
|
|
204
277
|
// to maintain consistent API with useCan return type
|
|
278
|
+
// React 19 fix: Read isLoading directly from result objects to ensure we get the latest state
|
|
279
|
+
// instead of relying on memoized object references which may not update properly in React 19
|
|
205
280
|
const permissions = useMemo(() => {
|
|
206
281
|
// Helper to create a permission result that bypasses for super admins
|
|
207
282
|
// If super admin check is still loading, we show loading state to prevent premature "Access Denied"
|
|
208
283
|
// Once super admin check completes, if user is super admin, all permissions are true
|
|
209
284
|
// Otherwise, use the normal permission check results
|
|
210
285
|
const createSuperAdminAwarePermission = (result: ReturnType<typeof useCan>) => ({
|
|
211
|
-
|
|
212
|
-
//
|
|
213
|
-
|
|
286
|
+
// If super admin check completed and user is super admin, grant all permissions
|
|
287
|
+
// Otherwise use the normal permission check result
|
|
288
|
+
// Use === true to distinguish between null (not checked) and false (checked, not super admin)
|
|
289
|
+
can: isSuperAdminUser === true ? true : result.can,
|
|
290
|
+
// Show loading if super admin check is in progress (null and checking) OR if the underlying permission check is loading
|
|
291
|
+
// React 19 fix: Read isLoading directly from the result object to ensure we get the latest state
|
|
292
|
+
isLoading: (isSuperAdminUser === null && isCheckingSuperAdmin) || result.isLoading,
|
|
214
293
|
error: result.error,
|
|
215
294
|
refetch: result.refetch,
|
|
216
295
|
});
|
|
@@ -226,12 +305,25 @@ export function useDataTablePermissions<TData extends DataRecord>(
|
|
|
226
305
|
}, [
|
|
227
306
|
isSuperAdminUser,
|
|
228
307
|
isCheckingSuperAdmin,
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
308
|
+
// React 19 fix: Include individual properties instead of entire objects to ensure proper dependency tracking
|
|
309
|
+
canReadResult.can,
|
|
310
|
+
canReadResult.isLoading,
|
|
311
|
+
canReadResult.error,
|
|
312
|
+
canCreateResult.can,
|
|
313
|
+
canCreateResult.isLoading,
|
|
314
|
+
canCreateResult.error,
|
|
315
|
+
canUpdateResult.can,
|
|
316
|
+
canUpdateResult.isLoading,
|
|
317
|
+
canUpdateResult.error,
|
|
318
|
+
canDeleteResult.can,
|
|
319
|
+
canDeleteResult.isLoading,
|
|
320
|
+
canDeleteResult.error,
|
|
321
|
+
canExportResult.can,
|
|
322
|
+
canExportResult.isLoading,
|
|
323
|
+
canExportResult.error,
|
|
324
|
+
canImportResult.can,
|
|
325
|
+
canImportResult.isLoading,
|
|
326
|
+
canImportResult.error,
|
|
235
327
|
]);
|
|
236
328
|
|
|
237
329
|
// MANDATORY: Features are automatically filtered by permissions
|
|
@@ -26,6 +26,12 @@ export type { DataRecord, CellValue, RowId };
|
|
|
26
26
|
// STATE INTERFACE
|
|
27
27
|
// ============================================================================
|
|
28
28
|
|
|
29
|
+
/**
|
|
30
|
+
* DataTable state interface.
|
|
31
|
+
* Contains all state for table operations including sorting, filtering, pagination, and editing.
|
|
32
|
+
*
|
|
33
|
+
* @template TData - The type of data records in the table
|
|
34
|
+
*/
|
|
29
35
|
export interface DataTableState<TData extends DataRecord> {
|
|
30
36
|
// Table state
|
|
31
37
|
sorting: SortingState;
|
|
@@ -53,6 +59,12 @@ export interface DataTableState<TData extends DataRecord> {
|
|
|
53
59
|
searchQuery: string;
|
|
54
60
|
}
|
|
55
61
|
|
|
62
|
+
/**
|
|
63
|
+
* Actions interface for DataTable state management.
|
|
64
|
+
* Provides functions to update all aspects of table state.
|
|
65
|
+
*
|
|
66
|
+
* @template TData - The type of data records in the table
|
|
67
|
+
*/
|
|
56
68
|
export interface DataTableStateActions<TData extends DataRecord> {
|
|
57
69
|
setSorting: (sorting: SortingState) => void;
|
|
58
70
|
setColumnFilters: (filters: ColumnFiltersState) => void;
|
|
@@ -78,6 +90,19 @@ export interface DataTableStateActions<TData extends DataRecord> {
|
|
|
78
90
|
initializeState: (partialState: Partial<DataTableState<TData>>) => void;
|
|
79
91
|
}
|
|
80
92
|
|
|
93
|
+
/**
|
|
94
|
+
* Computed values interface for DataTable.
|
|
95
|
+
* Provides derived state values that are computed from the table state.
|
|
96
|
+
*/
|
|
97
|
+
export interface DataTableComputed {
|
|
98
|
+
hasSelection: boolean;
|
|
99
|
+
selectedRowIds: string[];
|
|
100
|
+
isEditing: boolean;
|
|
101
|
+
isCreating: boolean;
|
|
102
|
+
hasFilters: boolean;
|
|
103
|
+
canClearFilters: boolean;
|
|
104
|
+
}
|
|
105
|
+
|
|
81
106
|
// ============================================================================
|
|
82
107
|
// ACTION TYPES
|
|
83
108
|
// ============================================================================
|
|
@@ -108,6 +133,15 @@ export type DataTableAction<TData extends DataRecord> =
|
|
|
108
133
|
// REDUCER
|
|
109
134
|
// ============================================================================
|
|
110
135
|
|
|
136
|
+
/**
|
|
137
|
+
* Reducer function for DataTable state management.
|
|
138
|
+
* Handles all state updates for the DataTable component.
|
|
139
|
+
*
|
|
140
|
+
* @template TData - The type of data records in the table
|
|
141
|
+
* @param state - Current table state
|
|
142
|
+
* @param action - Action to perform
|
|
143
|
+
* @returns New table state
|
|
144
|
+
*/
|
|
111
145
|
export function dataTableReducer<TData extends DataRecord>(
|
|
112
146
|
state: DataTableState<TData>,
|
|
113
147
|
action: DataTableAction<TData>
|
|
@@ -330,7 +364,7 @@ export function useDataTableState<TData extends DataRecord>({
|
|
|
330
364
|
// COMPUTED VALUES
|
|
331
365
|
// ============================================================================
|
|
332
366
|
|
|
333
|
-
const computed = useMemo(() => ({
|
|
367
|
+
const computed = useMemo<DataTableComputed>(() => ({
|
|
334
368
|
hasSelection: Object.values(state.rowSelection).some(Boolean),
|
|
335
369
|
selectedRowIds: Object.entries(state.rowSelection)
|
|
336
370
|
.filter(([_, selected]) => selected)
|
|
@@ -2,12 +2,24 @@ import { useMemo } from 'react';
|
|
|
2
2
|
|
|
3
3
|
import type { DataRecord, DataTableColumn } from '../types';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Options for the useEffectiveColumnOrder hook.
|
|
7
|
+
* @template TData - The type of data records in the table
|
|
8
|
+
*/
|
|
5
9
|
interface UseEffectiveColumnOrderOptions<TData extends DataRecord> {
|
|
6
10
|
columns: DataTableColumn<TData>[];
|
|
7
11
|
externalColumnOrder?: string[];
|
|
8
12
|
selectionEnabled: boolean;
|
|
9
13
|
}
|
|
10
14
|
|
|
15
|
+
/**
|
|
16
|
+
* Hook to compute effective column order.
|
|
17
|
+
* Handles external column order and ensures selection column is first when enabled.
|
|
18
|
+
*
|
|
19
|
+
* @template TData - The type of data records in the table
|
|
20
|
+
* @param options - Column order configuration
|
|
21
|
+
* @returns Effective column order array
|
|
22
|
+
*/
|
|
11
23
|
export function useEffectiveColumnOrder<TData extends DataRecord>({
|
|
12
24
|
columns,
|
|
13
25
|
externalColumnOrder,
|
|
@@ -23,7 +23,7 @@ export interface KeyboardNavigationOptions {
|
|
|
23
23
|
/** Callback when focus moves to a new cell */
|
|
24
24
|
onFocusChange?: (rowIndex: number, columnIndex: number) => void;
|
|
25
25
|
/** Table ref for DOM queries */
|
|
26
|
-
tableRef?: React.RefObject<HTMLTableElement>;
|
|
26
|
+
tableRef?: React.RefObject<HTMLTableElement | null>;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
export interface KeyboardNavigationState {
|
|
@@ -105,7 +105,7 @@ export function useKeyboardNavigation(
|
|
|
105
105
|
const internalTableRef = useRef<HTMLTableElement>(null);
|
|
106
106
|
const tableRef = externalTableRef || internalTableRef;
|
|
107
107
|
const storedFocusRef = useRef<{ rowIndex: number; columnIndex: number } | null>(null);
|
|
108
|
-
const navigationTimeoutRef = useRef<NodeJS.Timeout>();
|
|
108
|
+
const navigationTimeoutRef = useRef<NodeJS.Timeout>(undefined);
|
|
109
109
|
|
|
110
110
|
// Helper to get cell element
|
|
111
111
|
const getCellElement = useCallback((rowIndex: number, columnIndex: number): HTMLElement | null => {
|
|
@@ -16,6 +16,10 @@ import type {
|
|
|
16
16
|
PaginationState,
|
|
17
17
|
} from '@tanstack/react-table';
|
|
18
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Parameters for the useServerSideDataEffect hook.
|
|
21
|
+
* @template TData - The type of data records in the table
|
|
22
|
+
*/
|
|
19
23
|
export interface UseServerSideDataEffectParams<TData extends DataRecord> {
|
|
20
24
|
finalPaginationMode: PaginationMode;
|
|
21
25
|
serverSide?: ServerSideConfig<TData>;
|
|
@@ -29,6 +33,13 @@ export interface UseServerSideDataEffectParams<TData extends DataRecord> {
|
|
|
29
33
|
cleanup?: () => void;
|
|
30
34
|
}
|
|
31
35
|
|
|
36
|
+
/**
|
|
37
|
+
* Hook for coordinating server-side data fetching.
|
|
38
|
+
* Triggers data fetches when table state changes in server-side pagination mode.
|
|
39
|
+
*
|
|
40
|
+
* @template TData - The type of data records in the table
|
|
41
|
+
* @param params - Server-side data effect configuration
|
|
42
|
+
*/
|
|
32
43
|
export function useServerSideDataEffect<TData extends DataRecord>({
|
|
33
44
|
finalPaginationMode,
|
|
34
45
|
serverSide,
|
|
@@ -21,6 +21,10 @@ import type {
|
|
|
21
21
|
import type { ColumnDef } from '@tanstack/react-table';
|
|
22
22
|
import type { HeaderContext, CellContext } from '@tanstack/react-table';
|
|
23
23
|
|
|
24
|
+
/**
|
|
25
|
+
* Options for the useTableColumns hook.
|
|
26
|
+
* @template TData - The type of data records in the table
|
|
27
|
+
*/
|
|
24
28
|
export interface UseTableColumnsOptions<TData extends DataRecord> {
|
|
25
29
|
columns: DataTableColumn<TData>[];
|
|
26
30
|
features: NormalizedDataTableFeatureConfig;
|
|
@@ -28,6 +32,10 @@ export interface UseTableColumnsOptions<TData extends DataRecord> {
|
|
|
28
32
|
columnOrder: string[];
|
|
29
33
|
}
|
|
30
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Return value of the useTableColumns hook.
|
|
37
|
+
* @template TData - The type of data records in the table
|
|
38
|
+
*/
|
|
31
39
|
export interface UseTableColumnsReturn<TData extends DataRecord> {
|
|
32
40
|
enhancedColumns: ColumnDef<TData>[];
|
|
33
41
|
}
|
|
@@ -14,11 +14,21 @@ import type {
|
|
|
14
14
|
DataTableStateActions,
|
|
15
15
|
} from './useDataTableState';
|
|
16
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Table layout change interface.
|
|
19
|
+
* Represents changes to column order and visibility.
|
|
20
|
+
*/
|
|
17
21
|
export interface TableLayoutChange {
|
|
18
22
|
columnOrder: string[];
|
|
19
23
|
columnVisibility: VisibilityState;
|
|
20
24
|
}
|
|
21
25
|
|
|
26
|
+
/**
|
|
27
|
+
* Snapshot of table state at a point in time.
|
|
28
|
+
* Used for state persistence and restoration.
|
|
29
|
+
*
|
|
30
|
+
* @template TData - The type of data records in the table
|
|
31
|
+
*/
|
|
22
32
|
export interface TableStateSnapshot<TData extends DataRecord> {
|
|
23
33
|
sorting: SortingState;
|
|
24
34
|
columnFilters: ColumnFiltersState;
|
|
@@ -31,6 +41,10 @@ export interface TableStateSnapshot<TData extends DataRecord> {
|
|
|
31
41
|
columnOrder: string[];
|
|
32
42
|
}
|
|
33
43
|
|
|
44
|
+
/**
|
|
45
|
+
* Table event handlers interface.
|
|
46
|
+
* Provides handlers for all table state changes.
|
|
47
|
+
*/
|
|
34
48
|
export interface TableHandlers {
|
|
35
49
|
onSortingChange: (updaterOrValue: unknown) => void;
|
|
36
50
|
onColumnFiltersChange: (updaterOrValue: unknown) => void;
|
|
@@ -64,7 +64,7 @@ export const getTableCellClasses = (options: {
|
|
|
64
64
|
isCompact?: boolean;
|
|
65
65
|
isSortable?: boolean;
|
|
66
66
|
className?: string;
|
|
67
|
-
} = {}) => {
|
|
67
|
+
} = {}): string => {
|
|
68
68
|
const { isVirtualized = false, isCompact = false, isSortable = false, className } = options;
|
|
69
69
|
|
|
70
70
|
if (isVirtualized) {
|
|
@@ -88,7 +88,7 @@ export const getTableCellClasses = (options: {
|
|
|
88
88
|
export const getTableHeadClasses = (options: {
|
|
89
89
|
isSortable?: boolean;
|
|
90
90
|
className?: string;
|
|
91
|
-
} = {}) => {
|
|
91
|
+
} = {}): string => {
|
|
92
92
|
const { isSortable = false, className } = options;
|
|
93
93
|
|
|
94
94
|
return cn(
|
|
@@ -105,7 +105,7 @@ export const getTableRowClasses = (options: {
|
|
|
105
105
|
isSelected?: boolean;
|
|
106
106
|
isVirtualized?: boolean;
|
|
107
107
|
className?: string;
|
|
108
|
-
} = {}) => {
|
|
108
|
+
} = {}): string => {
|
|
109
109
|
const { isSelected = false, isVirtualized = false, className } = options;
|
|
110
110
|
|
|
111
111
|
if (isVirtualized) {
|
|
@@ -129,7 +129,7 @@ export const getTableRowClasses = (options: {
|
|
|
129
129
|
export const getTableContainerClasses = (options: {
|
|
130
130
|
isVirtualized?: boolean;
|
|
131
131
|
className?: string;
|
|
132
|
-
} = {}) => {
|
|
132
|
+
} = {}): string => {
|
|
133
133
|
const { isVirtualized = false, className } = options;
|
|
134
134
|
|
|
135
135
|
return cn(
|
|
@@ -145,7 +145,7 @@ export const getTableClasses = (options: {
|
|
|
145
145
|
isFixed?: boolean;
|
|
146
146
|
variant?: 'default' | 'compact' | 'spacious';
|
|
147
147
|
className?: string;
|
|
148
|
-
} = {}) => {
|
|
148
|
+
} = {}): string => {
|
|
149
149
|
const { isFixed = false, variant = 'default', className } = options;
|
|
150
150
|
|
|
151
151
|
if (isFixed) {
|
|
@@ -182,7 +182,7 @@ export const getTableClasses = (options: {
|
|
|
182
182
|
*/
|
|
183
183
|
export const getMainContainerClasses = (options: {
|
|
184
184
|
className?: string;
|
|
185
|
-
} = {}) => {
|
|
185
|
+
} = {}): string => {
|
|
186
186
|
const { className } = options;
|
|
187
187
|
|
|
188
188
|
return cn(
|
|
@@ -55,16 +55,6 @@ export type RowId = string;
|
|
|
55
55
|
*/
|
|
56
56
|
export type GetRowId<TData extends DataRecord> = (row: TData, index: number) => RowId;
|
|
57
57
|
|
|
58
|
-
/**
|
|
59
|
-
* Generic type for partial data updates
|
|
60
|
-
*/
|
|
61
|
-
export type PartialDataRecord<TData extends DataRecord> = Partial<TData>;
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Generic type for complete data records
|
|
65
|
-
*/
|
|
66
|
-
export type CompleteDataRecord<TData extends DataRecord> = TData;
|
|
67
|
-
|
|
68
58
|
// ============================================================================
|
|
69
59
|
// HIERARCHICAL DATA TYPES
|
|
70
60
|
// ============================================================================
|
|
@@ -393,6 +383,12 @@ export interface SimpleColumn<TData extends DataRecord = DataRecord> {
|
|
|
393
383
|
*/
|
|
394
384
|
export type ActionCondition<TData extends DataRecord> = boolean | ((row: TData) => boolean);
|
|
395
385
|
|
|
386
|
+
/**
|
|
387
|
+
* Action definition for DataTable rows.
|
|
388
|
+
* Defines custom actions that can be performed on table rows.
|
|
389
|
+
*
|
|
390
|
+
* @template TData - The type of data records in the table
|
|
391
|
+
*/
|
|
396
392
|
export interface DataTableAction<TData extends DataRecord> {
|
|
397
393
|
/** Display label for the action */
|
|
398
394
|
label: string;
|
|
@@ -211,6 +211,13 @@ export function announceBulkOperation(operation: string, count: number): void {
|
|
|
211
211
|
* Get ARIA sort value for column headers
|
|
212
212
|
* @param sortDirection - Current sort direction
|
|
213
213
|
*/
|
|
214
|
+
/**
|
|
215
|
+
* Converts TanStack Table sort direction to ARIA sort value.
|
|
216
|
+
* Maps table sort states to accessible ARIA attributes.
|
|
217
|
+
*
|
|
218
|
+
* @param sortDirection - Sort direction from TanStack Table
|
|
219
|
+
* @returns ARIA sort value for accessibility
|
|
220
|
+
*/
|
|
214
221
|
export function getAriaSortValue(sortDirection: 'asc' | 'desc' | false): 'ascending' | 'descending' | 'none' {
|
|
215
222
|
if (sortDirection === 'asc') return 'ascending';
|
|
216
223
|
if (sortDirection === 'desc') return 'descending';
|