@jmruthers/pace-core 0.5.191 → 0.6.1
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 +29 -0
- package/README.md +7 -1
- package/cursor-rules/00-pace-core-compliance.mdc +372 -0
- package/cursor-rules/01-standards-compliance.mdc +275 -0
- package/cursor-rules/02-project-structure.mdc +200 -0
- package/cursor-rules/03-solid-principles.mdc +341 -0
- package/cursor-rules/04-testing-standards.mdc +315 -0
- package/cursor-rules/05-bug-reports-and-features.mdc +246 -0
- package/cursor-rules/06-code-quality.mdc +392 -0
- package/cursor-rules/07-tech-stack-compliance.mdc +309 -0
- package/cursor-rules/CHANGELOG.md +101 -0
- package/cursor-rules/README.md +191 -0
- package/dist/{AuthService-CbP_utw2.d.ts → AuthService-DjnJHDtC.d.ts} +1 -0
- package/dist/{DataTable-Be6dH_dR.d.ts → DataTable-CH1U5Tpy.d.ts} +1 -1
- package/dist/{DataTable-WKRZD47S.js → DataTable-DQ7RSOHE.js} +8 -7
- package/dist/{PublicPageProvider-ULXC_u6U.d.ts → PublicPageProvider-ce4xlHYA.d.ts} +37 -156
- package/dist/{UnifiedAuthProvider-BYA9qB-o.d.ts → UnifiedAuthProvider-185Ih4dj.d.ts} +2 -0
- package/dist/{UnifiedAuthProvider-FTSG5XH7.js → UnifiedAuthProvider-ATAP5UTR.js} +3 -3
- package/dist/{api-IHKALJZD.js → api-N774RPUA.js} +2 -2
- package/dist/{chunk-6C4YBBJM.js → chunk-3QRJFVBR.js} +1 -1
- package/dist/chunk-3QRJFVBR.js.map +1 -0
- package/dist/{chunk-OETXORNB.js → chunk-3XTALGJF.js} +211 -136
- package/dist/chunk-3XTALGJF.js.map +1 -0
- package/dist/{chunk-6TQDD426.js → chunk-4N5C5XZU.js} +47 -228
- package/dist/chunk-4N5C5XZU.js.map +1 -0
- package/dist/{chunk-LOMZXPSN.js → chunk-4ZC4GX36.js} +47 -74
- package/dist/chunk-4ZC4GX36.js.map +1 -0
- package/dist/{chunk-6LTQQAT6.js → chunk-BYFSK72L.js} +357 -158
- package/dist/chunk-BYFSK72L.js.map +1 -0
- package/dist/{chunk-XYXSXPUK.js → chunk-EXUD6RNJ.js} +50 -10
- package/dist/chunk-EXUD6RNJ.js.map +1 -0
- package/dist/{chunk-VKB2CO4Z.js → chunk-GLK6VM3F.js} +244 -249
- package/dist/chunk-GLK6VM3F.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-XNYQOL3Z.js → chunk-JBKQ3SAO.js} +9 -18
- package/dist/chunk-JBKQ3SAO.js.map +1 -0
- package/dist/{chunk-ROXMHMY2.js → chunk-KNC55RTG.js} +13 -3
- package/dist/{chunk-ROXMHMY2.js.map → chunk-KNC55RTG.js.map} +1 -1
- package/dist/{chunk-QWWZ5CAQ.js → chunk-LXQLPRQ2.js} +2 -2
- package/dist/{chunk-ULHIJK66.js → chunk-T33XF5ZC.js} +255 -140
- package/dist/chunk-T33XF5ZC.js.map +1 -0
- package/dist/{chunk-VRGWKHDB.js → chunk-XM25TVIE.js} +100 -33
- package/dist/chunk-XM25TVIE.js.map +1 -0
- package/dist/components.d.ts +4 -4
- package/dist/components.js +9 -9
- package/dist/hooks.d.ts +6 -6
- package/dist/hooks.js +20 -25
- package/dist/hooks.js.map +1 -1
- package/dist/index.d.ts +11 -11
- package/dist/index.js +18 -21
- package/dist/index.js.map +1 -1
- package/dist/providers.d.ts +3 -3
- package/dist/providers.js +2 -2
- package/dist/rbac/index.d.ts +2 -20
- package/dist/rbac/index.js +7 -9
- package/dist/{usePublicRouteParams-TZe0gy-4.d.ts → usePublicRouteParams-BJAlWfuJ.d.ts} +3 -3
- package/dist/{useToast-C8gR5ir4.d.ts → useToast-AyaT-x7p.d.ts} +2 -2
- package/dist/utils.d.ts +1 -1
- package/dist/utils.js +3 -3
- package/docs/api/classes/ColumnFactory.md +1 -1
- package/docs/api/classes/ErrorBoundary.md +1 -1
- package/docs/api/classes/InvalidScopeError.md +1 -1
- package/docs/api/classes/Logger.md +1 -1
- package/docs/api/classes/MissingUserContextError.md +1 -1
- package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
- package/docs/api/classes/PermissionDeniedError.md +2 -2
- package/docs/api/classes/RBACAuditManager.md +2 -2
- package/docs/api/classes/RBACCache.md +1 -1
- package/docs/api/classes/RBACEngine.md +2 -2
- package/docs/api/classes/RBACError.md +1 -1
- package/docs/api/classes/RBACNotInitializedError.md +1 -1
- package/docs/api/classes/SecureSupabaseClient.md +10 -10
- 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 +1 -1
- package/docs/api/interfaces/AutocompleteOptions.md +1 -1
- package/docs/api/interfaces/AvatarProps.md +1 -1
- package/docs/api/interfaces/BadgeProps.md +1 -1
- package/docs/api/interfaces/ButtonProps.md +1 -1
- package/docs/api/interfaces/CalendarProps.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/ComplianceResult.md +1 -1
- package/docs/api/interfaces/DataAccessRecord.md +1 -1
- package/docs/api/interfaces/DataRecord.md +1 -1
- package/docs/api/interfaces/DataTableAction.md +1 -1
- package/docs/api/interfaces/DataTableColumn.md +1 -1
- package/docs/api/interfaces/DataTableProps.md +1 -1
- package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
- package/docs/api/interfaces/DatabaseComplianceResult.md +1 -1
- package/docs/api/interfaces/DatabaseIssue.md +1 -1
- package/docs/api/interfaces/EmptyStateConfig.md +1 -1
- package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
- package/docs/api/interfaces/EventAppRoleData.md +1 -1
- package/docs/api/interfaces/ExportColumn.md +1 -1
- package/docs/api/interfaces/ExportOptions.md +1 -1
- package/docs/api/interfaces/FileDisplayProps.md +24 -11
- 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/FormFieldProps.md +1 -1
- 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 +1 -1
- package/docs/api/interfaces/LabelProps.md +1 -1
- package/docs/api/interfaces/LoggerConfig.md +1 -1
- package/docs/api/interfaces/LoginFormProps.md +1 -1
- package/docs/api/interfaces/NavigationAccessRecord.md +2 -2
- package/docs/api/interfaces/NavigationContextType.md +1 -1
- package/docs/api/interfaces/NavigationGuardProps.md +1 -1
- package/docs/api/interfaces/NavigationItem.md +1 -1
- package/docs/api/interfaces/NavigationMenuProps.md +1 -1
- package/docs/api/interfaces/NavigationProviderProps.md +1 -1
- package/docs/api/interfaces/Organisation.md +1 -1
- package/docs/api/interfaces/OrganisationContextType.md +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 +1 -1
- 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/ParsedAddress.md +1 -1
- package/docs/api/interfaces/PermissionEnforcerProps.md +4 -4
- package/docs/api/interfaces/ProgressProps.md +1 -1
- package/docs/api/interfaces/ProtectedRouteProps.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/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 +2 -2
- 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 +2 -2
- 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 +2 -2
- package/docs/api/interfaces/RBACRoleGrantResult.md +1 -1
- package/docs/api/interfaces/RBACRoleRevokeParams.md +2 -2
- package/docs/api/interfaces/RBACRoleRevokeResult.md +1 -1
- package/docs/api/interfaces/RBACRoleValidateParams.md +2 -2
- package/docs/api/interfaces/RBACRoleValidateResult.md +1 -1
- package/docs/api/interfaces/RBACRolesListParams.md +1 -1
- package/docs/api/interfaces/RBACRolesListResult.md +2 -2
- 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 +2 -2
- package/docs/api/interfaces/RouteConfig.md +2 -2
- package/docs/api/interfaces/RuntimeComplianceResult.md +1 -1
- package/docs/api/interfaces/SecureDataContextType.md +1 -1
- package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
- package/docs/api/interfaces/SessionRestorationLoaderProps.md +1 -1
- 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 +1 -1
- package/docs/api/interfaces/TextareaProps.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 +60 -38
- package/docs/api/interfaces/UnifiedAuthProviderProps.md +13 -13
- package/docs/api/interfaces/UseFormDialogOptions.md +1 -1
- package/docs/api/interfaces/UseFormDialogReturn.md +1 -1
- package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
- package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
- package/docs/api/interfaces/UsePublicEventLogoOptions.md +2 -2
- 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/UsePublicFileDisplayOptions.md +2 -2
- package/docs/api/interfaces/UsePublicFileDisplayReturn.md +1 -1
- package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
- package/docs/api/interfaces/UseResolvedScopeOptions.md +2 -2
- package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
- package/docs/api/interfaces/UseResourcePermissionsOptions.md +1 -1
- package/docs/api/interfaces/UserEventAccess.md +1 -1
- package/docs/api/interfaces/UserMenuProps.md +1 -1
- package/docs/api/interfaces/UserProfile.md +1 -1
- package/docs/api/modules.md +194 -209
- package/docs/getting-started/cursor-rules.md +262 -0
- package/docs/getting-started/installation-guide.md +6 -1
- package/docs/getting-started/quick-start.md +6 -1
- package/docs/migration/MIGRATION_GUIDE.md +4 -4
- package/docs/migration/REACT_19_MIGRATION.md +227 -0
- package/docs/migration/database-changes-december-2025.md +2 -1
- package/docs/rbac/event-based-apps.md +124 -6
- package/docs/standards/README.md +39 -0
- package/docs/troubleshooting/migration.md +4 -4
- package/examples/PublicPages/PublicEventPage.tsx +1 -1
- package/package.json +11 -6
- package/scripts/audit-consuming-app.cjs +961 -0
- package/scripts/check-pace-core-compliance.cjs +315 -61
- package/scripts/install-cursor-rules.cjs +236 -0
- package/src/__tests__/helpers/test-providers.tsx +1 -1
- package/src/__tests__/helpers/test-utils.tsx +1 -1
- package/src/__tests__/rls-policies.test.ts +3 -1
- package/src/components/Badge/Badge.tsx +2 -4
- package/src/components/Button/Button.tsx +5 -4
- package/src/components/Calendar/Calendar.tsx +1 -1
- package/src/components/DataTable/DataTable.test.tsx +57 -93
- package/src/components/DataTable/DataTable.tsx +2 -2
- package/src/components/DataTable/__tests__/DataTable.default-state.test.tsx +172 -45
- package/src/components/DataTable/__tests__/DataTable.grouping-aggregation.test.tsx +121 -28
- package/src/components/DataTable/__tests__/DataTableCore.test-setup.ts +9 -8
- package/src/components/DataTable/__tests__/DataTableCore.test.tsx +20 -52
- package/src/components/DataTable/__tests__/a11y.basic.test.tsx +170 -34
- package/src/components/DataTable/__tests__/keyboard.test.tsx +75 -12
- package/src/components/DataTable/__tests__/pagination.modes.test.tsx +88 -16
- package/src/components/DataTable/__tests__/ssr.strict-mode.test.tsx +12 -12
- package/src/components/DataTable/components/AccessDeniedPage.tsx +1 -1
- package/src/components/DataTable/components/BulkOperationsDropdown.tsx +1 -1
- package/src/components/DataTable/components/DataTableCore.tsx +4 -7
- package/src/components/DataTable/components/DataTableModals.tsx +1 -1
- package/src/components/DataTable/components/EditableRow.tsx +1 -1
- package/src/components/DataTable/components/UnifiedTableBody.tsx +86 -17
- 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/hooks/useColumnReordering.ts +2 -2
- package/src/components/DataTable/hooks/useDataTablePermissions.ts +75 -10
- package/src/components/DataTable/hooks/useKeyboardNavigation.ts +2 -2
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +8 -14
- package/src/components/Dialog/Dialog.tsx +6 -5
- package/src/components/ErrorBoundary/ErrorBoundary.tsx +1 -1
- package/src/components/EventSelector/EventSelector.tsx +1 -1
- package/src/components/FileDisplay/FileDisplay.test.tsx +4 -3
- package/src/components/FileDisplay/FileDisplay.tsx +16 -4
- package/src/components/Footer/Footer.tsx +1 -1
- package/src/components/Form/Form.test.tsx +36 -15
- package/src/components/Form/Form.tsx +30 -26
- package/src/components/Header/Header.tsx +1 -1
- package/src/components/InactivityWarningModal/InactivityWarningModal.test.tsx +40 -40
- package/src/components/InactivityWarningModal/InactivityWarningModal.tsx +1 -1
- package/src/components/Input/Input.tsx +28 -30
- package/src/components/Label/Label.tsx +1 -1
- package/src/components/LoadingSpinner/LoadingSpinner.tsx +1 -1
- package/src/components/LoginForm/LoginForm.test.tsx +42 -42
- package/src/components/LoginForm/LoginForm.tsx +8 -8
- package/src/components/NavigationMenu/NavigationMenu.test.tsx +6 -4
- package/src/components/NavigationMenu/NavigationMenu.tsx +2 -11
- package/src/components/OrganisationSelector/OrganisationSelector.tsx +0 -1
- package/src/components/PaceAppLayout/PaceAppLayout.performance.test.tsx +1 -1
- package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +75 -52
- package/src/components/PaceAppLayout/PaceAppLayout.tsx +98 -69
- package/src/components/PaceAppLayout/README.md +1 -1
- package/src/components/PaceLoginPage/PaceLoginPage.tsx +1 -8
- package/src/components/PasswordChange/PasswordChangeForm.test.tsx +33 -33
- package/src/components/PasswordChange/PasswordChangeForm.tsx +1 -1
- package/src/components/Progress/Progress.tsx +1 -1
- package/src/components/ProtectedRoute/ProtectedRoute.test.tsx +5 -9
- package/src/components/ProtectedRoute/ProtectedRoute.tsx +0 -1
- package/src/components/PublicLayout/PublicPageLayout.tsx +1 -1
- package/src/components/PublicLayout/PublicPageProvider.tsx +0 -1
- package/src/components/Select/Select.tsx +33 -22
- package/src/components/SessionRestorationLoader/SessionRestorationLoader.tsx +1 -1
- package/src/components/Table/Table.tsx +1 -1
- package/src/components/Textarea/Textarea.tsx +27 -29
- package/src/components/Toast/Toast.tsx +1 -1
- package/src/components/Tooltip/Tooltip.tsx +1 -1
- package/src/components/UserMenu/UserMenu.tsx +1 -1
- package/src/hooks/__tests__/hooks.integration.test.tsx +80 -55
- package/src/hooks/__tests__/useSecureDataAccess.unit.test.tsx +14 -7
- package/src/hooks/__tests__/useStorage.unit.test.ts +36 -36
- package/src/hooks/public/usePublicEvent.ts +1 -1
- package/src/hooks/public/usePublicEventLogo.ts +1 -1
- package/src/hooks/public/usePublicRouteParams.ts +1 -1
- package/src/hooks/services/useAuthService.ts +21 -3
- package/src/hooks/services/useEventService.ts +21 -3
- package/src/hooks/services/useInactivityService.ts +21 -3
- package/src/hooks/services/useOrganisationService.ts +21 -3
- package/src/hooks/useDataTableState.ts +8 -18
- package/src/hooks/useFileDisplay.ts +10 -17
- package/src/hooks/useFocusManagement.ts +2 -2
- package/src/hooks/useFocusTrap.ts +4 -4
- package/src/hooks/useFormDialog.ts +8 -7
- package/src/hooks/useInactivityTracker.ts +1 -1
- package/src/hooks/usePermissionCache.ts +1 -1
- package/src/hooks/useSecureDataAccess.test.ts +16 -9
- package/src/hooks/useSecureDataAccess.ts +22 -6
- package/src/hooks/useToast.ts +2 -2
- package/src/providers/__tests__/OrganisationProvider.test.tsx +57 -13
- package/src/providers/__tests__/ProviderLifecycle.test.tsx +21 -6
- package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +10 -10
- package/src/providers/services/EventServiceProvider.tsx +0 -8
- package/src/providers/services/UnifiedAuthProvider.tsx +196 -46
- package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +13 -3
- package/src/rbac/__tests__/adapters.comprehensive.test.tsx +34 -40
- package/src/rbac/__tests__/isSuperAdmin.real.test.ts +82 -0
- package/src/rbac/adapters.tsx +3 -22
- package/src/rbac/api.test.ts +2 -2
- package/src/rbac/api.ts +7 -1
- package/src/rbac/components/EnhancedNavigationMenu.tsx +3 -16
- package/src/rbac/components/NavigationGuard.tsx +2 -11
- package/src/rbac/components/NavigationProvider.tsx +1 -2
- package/src/rbac/components/PagePermissionGuard.tsx +1 -1
- package/src/rbac/components/PagePermissionProvider.tsx +1 -1
- package/src/rbac/components/PermissionEnforcer.tsx +46 -13
- package/src/rbac/components/RoleBasedRouter.tsx +1 -1
- package/src/rbac/components/SecureDataProvider.tsx +1 -2
- package/src/rbac/components/__tests__/EnhancedNavigationMenu.test.tsx +7 -43
- package/src/rbac/components/__tests__/NavigationGuard.test.tsx +4 -11
- package/src/rbac/components/__tests__/NavigationProvider.test.tsx +3 -3
- package/src/rbac/components/__tests__/SecureDataProvider.fixed.test.tsx +1 -1
- package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +1 -1
- package/src/rbac/engine.ts +14 -2
- package/src/rbac/hooks/index.ts +0 -3
- package/src/rbac/hooks/usePermissions.ts +51 -11
- package/src/rbac/hooks/useRBAC.ts +3 -13
- package/src/rbac/hooks/useResolvedScope.test.ts +75 -54
- package/src/rbac/hooks/useResolvedScope.ts +58 -33
- package/src/rbac/hooks/useSecureSupabase.ts +4 -9
- package/src/rbac/secureClient.ts +43 -0
- package/src/services/EventService.ts +4 -57
- package/src/services/InactivityService.ts +127 -34
- package/src/services/OrganisationService.ts +68 -10
- package/src/utils/security/secureDataAccess.test.ts +31 -20
- package/src/utils/security/secureDataAccess.ts +4 -3
- package/dist/chunk-6C4YBBJM.js.map +0 -1
- package/dist/chunk-6LTQQAT6.js.map +0 -1
- package/dist/chunk-6TQDD426.js.map +0 -1
- package/dist/chunk-LOMZXPSN.js.map +0 -1
- package/dist/chunk-OETXORNB.js.map +0 -1
- package/dist/chunk-ULHIJK66.js.map +0 -1
- package/dist/chunk-VKB2CO4Z.js.map +0 -1
- package/dist/chunk-VRGWKHDB.js.map +0 -1
- package/dist/chunk-XNYQOL3Z.js.map +0 -1
- package/dist/chunk-XYXSXPUK.js.map +0 -1
- package/scripts/check-pace-core-compliance.js +0 -512
- package/src/rbac/hooks/useSuperAdminBypass.ts +0 -126
- package/src/utils/context/superAdminOverride.ts +0 -58
- /package/dist/{DataTable-WKRZD47S.js.map → DataTable-DQ7RSOHE.js.map} +0 -0
- /package/dist/{UnifiedAuthProvider-FTSG5XH7.js.map → UnifiedAuthProvider-ATAP5UTR.js.map} +0 -0
- /package/dist/{api-IHKALJZD.js.map → api-N774RPUA.js.map} +0 -0
- /package/dist/{chunk-QWWZ5CAQ.js.map → chunk-LXQLPRQ2.js.map} +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
|
@@ -295,24 +295,18 @@ describe('DatePickerWithTimezone Component', () => {
|
|
|
295
295
|
|
|
296
296
|
render(<DatePickerWithTimezone selected={selected} onSelect={onSelect} />);
|
|
297
297
|
|
|
298
|
-
expect(MockedCalendar).
|
|
299
|
-
expect.objectContaining({
|
|
300
|
-
mode: 'single',
|
|
301
|
-
selected: selected,
|
|
302
|
-
onSelect: onSelect,
|
|
303
|
-
initialFocus: true,
|
|
304
|
-
captionLayout: 'dropdown',
|
|
305
|
-
startMonth: expect.any(Date),
|
|
306
|
-
endMonth: expect.any(Date),
|
|
307
|
-
className: 'p-0'
|
|
308
|
-
}),
|
|
309
|
-
expect.anything()
|
|
310
|
-
);
|
|
298
|
+
expect(MockedCalendar).toHaveBeenCalled();
|
|
311
299
|
|
|
312
|
-
// Verify the
|
|
300
|
+
// Verify the props are correct
|
|
313
301
|
const callArgs = MockedCalendar.mock.calls[0][0];
|
|
302
|
+
expect(callArgs.mode).toBe('single');
|
|
303
|
+
expect(callArgs.selected).toEqual(selected);
|
|
304
|
+
expect(callArgs.onSelect).toBe(onSelect);
|
|
305
|
+
expect(callArgs.initialFocus).toBe(true);
|
|
306
|
+
expect(callArgs.captionLayout).toBe('dropdown');
|
|
314
307
|
expect(callArgs.startMonth).toEqual(new Date(1900, 0));
|
|
315
308
|
expect(callArgs.endMonth).toEqual(new Date(2100, 11));
|
|
309
|
+
expect(callArgs.className).toBe('p-0');
|
|
316
310
|
});
|
|
317
311
|
});
|
|
318
312
|
});
|
|
@@ -149,7 +149,7 @@
|
|
|
149
149
|
* @dependencies
|
|
150
150
|
* - @radix-ui/react-dialog - Core dialog functionality
|
|
151
151
|
* - lucide-react - Icons
|
|
152
|
-
* - React
|
|
152
|
+
* - React 19+ - Hooks and refs
|
|
153
153
|
* - Tailwind CSS - Styling and animations
|
|
154
154
|
*/
|
|
155
155
|
|
|
@@ -465,17 +465,18 @@ const DialogContent = React.forwardRef<
|
|
|
465
465
|
enableScrolling
|
|
466
466
|
});
|
|
467
467
|
|
|
468
|
-
|
|
468
|
+
// React Compiler handles memoization automatically
|
|
469
|
+
const handleEscapeKeyDown = (event: KeyboardEvent) => {
|
|
469
470
|
if (preventCloseOnEscape) {
|
|
470
471
|
event.preventDefault();
|
|
471
472
|
}
|
|
472
|
-
}
|
|
473
|
+
};
|
|
473
474
|
|
|
474
|
-
const handlePointerDownOutside =
|
|
475
|
+
const handlePointerDownOutside = (event: Event) => {
|
|
475
476
|
if (preventCloseOnOutsideClick) {
|
|
476
477
|
event.preventDefault();
|
|
477
478
|
}
|
|
478
|
-
}
|
|
479
|
+
};
|
|
479
480
|
|
|
480
481
|
// Merge smart dimensions with provided style
|
|
481
482
|
const mergedStyle = React.useMemo(() => {
|
|
@@ -49,7 +49,7 @@ vi.mock('../../utils/storage/helpers', () => ({
|
|
|
49
49
|
}));
|
|
50
50
|
|
|
51
51
|
// Helper to render with UnifiedAuthProvider
|
|
52
|
-
const renderWithUnifiedAuth = (ui: React.ReactElement) => {
|
|
52
|
+
const renderWithUnifiedAuth = (ui: React.ReactElement<any>) => {
|
|
53
53
|
return renderWithProviders(
|
|
54
54
|
<UnifiedAuthProvider
|
|
55
55
|
supabaseClient={supabase}
|
|
@@ -64,7 +64,7 @@ const renderWithUnifiedAuth = (ui: React.ReactElement) => {
|
|
|
64
64
|
);
|
|
65
65
|
};
|
|
66
66
|
|
|
67
|
-
const renderWithPublicContext = (ui: React.ReactElement
|
|
67
|
+
const renderWithPublicContext = (ui: React.ReactElement<any>, value: any = null) => {
|
|
68
68
|
const Context = publicPageContextStore.value ?? React.createContext(null);
|
|
69
69
|
|
|
70
70
|
return renderWithProviders(
|
|
@@ -334,7 +334,8 @@ describe('[component] FileDisplay', () => {
|
|
|
334
334
|
// The image should not be inside a wrapper div with "space-y-2" class
|
|
335
335
|
const parentDiv = image.parentElement;
|
|
336
336
|
expect(parentDiv?.className).not.toContain('space-y-2');
|
|
337
|
-
|
|
337
|
+
// The image uses imgClassName or default "object-cover size-full", not "max-w-full"
|
|
338
|
+
expect(image.className).toContain('object-cover');
|
|
338
339
|
});
|
|
339
340
|
|
|
340
341
|
it('renders with wrapper when displayOnly is true but showDelete is also true', async () => {
|
|
@@ -69,6 +69,8 @@ export interface FileDisplayProps {
|
|
|
69
69
|
displayOnly?: boolean;
|
|
70
70
|
showDelete?: boolean;
|
|
71
71
|
className?: string;
|
|
72
|
+
/** Classes to apply to the first child element of <figure> (img, p, or other elements) */
|
|
73
|
+
imgClassName?: string;
|
|
72
74
|
children?: React.ReactNode;
|
|
73
75
|
/** Custom loading component to render during data fetching */
|
|
74
76
|
loadingComponent?: React.ComponentType;
|
|
@@ -107,6 +109,7 @@ interface FileDisplayContentProps {
|
|
|
107
109
|
displayOnly: boolean;
|
|
108
110
|
showDelete: boolean;
|
|
109
111
|
className: string;
|
|
112
|
+
imgClassName?: string;
|
|
110
113
|
children?: React.ReactNode;
|
|
111
114
|
onDelete?: () => Promise<void>;
|
|
112
115
|
clearError?: () => void;
|
|
@@ -134,6 +137,7 @@ function FileDisplayContent({
|
|
|
134
137
|
displayOnly,
|
|
135
138
|
showDelete,
|
|
136
139
|
className,
|
|
140
|
+
imgClassName,
|
|
137
141
|
children,
|
|
138
142
|
onDelete,
|
|
139
143
|
clearError,
|
|
@@ -330,11 +334,11 @@ function FileDisplayContent({
|
|
|
330
334
|
}
|
|
331
335
|
|
|
332
336
|
return (
|
|
333
|
-
<figure className={className || "
|
|
337
|
+
<figure className={className || ""}>
|
|
334
338
|
<img
|
|
335
339
|
src={fileUrl}
|
|
336
340
|
alt={fileReference.file_metadata.fileName || 'File'}
|
|
337
|
-
className="
|
|
341
|
+
className={imgClassName || "object-cover size-full"}
|
|
338
342
|
onError={handleImageError}
|
|
339
343
|
/>
|
|
340
344
|
</figure>
|
|
@@ -393,7 +397,7 @@ function FileDisplayContent({
|
|
|
393
397
|
<img
|
|
394
398
|
src={fileUrl}
|
|
395
399
|
alt={fileReference.file_metadata.fileName || 'File'}
|
|
396
|
-
className="
|
|
400
|
+
className={imgClassName || "object-cover size-full"}
|
|
397
401
|
onError={handleImageError}
|
|
398
402
|
/>
|
|
399
403
|
{showDelete && (
|
|
@@ -534,7 +538,7 @@ function FileDisplayContent({
|
|
|
534
538
|
<img
|
|
535
539
|
src={fileUrl}
|
|
536
540
|
alt={fileRef.file_metadata.fileName || 'File'}
|
|
537
|
-
className=
|
|
541
|
+
className={imgClassName || "object-cover size-full"}
|
|
538
542
|
onError={handleImageError}
|
|
539
543
|
/>
|
|
540
544
|
) : (
|
|
@@ -601,6 +605,7 @@ function FileDisplayPublic({
|
|
|
601
605
|
displayOnly = false,
|
|
602
606
|
showDelete = false,
|
|
603
607
|
className = '',
|
|
608
|
+
imgClassName,
|
|
604
609
|
children,
|
|
605
610
|
loadingComponent,
|
|
606
611
|
errorComponent,
|
|
@@ -631,6 +636,7 @@ function FileDisplayPublic({
|
|
|
631
636
|
displayOnly={displayOnly}
|
|
632
637
|
showDelete={false}
|
|
633
638
|
className={className}
|
|
639
|
+
imgClassName={imgClassName}
|
|
634
640
|
children={children}
|
|
635
641
|
onDelete={undefined}
|
|
636
642
|
organisation_id={organisation_id}
|
|
@@ -724,6 +730,7 @@ function FileDisplayPublic({
|
|
|
724
730
|
displayOnly={displayOnly}
|
|
725
731
|
showDelete={false} // Never show delete in public context
|
|
726
732
|
className={className}
|
|
733
|
+
imgClassName={imgClassName}
|
|
727
734
|
children={children}
|
|
728
735
|
onDelete={showDelete ? handleDelete : undefined}
|
|
729
736
|
organisation_id={organisation_id}
|
|
@@ -752,6 +759,7 @@ function FileDisplayAuthenticated({
|
|
|
752
759
|
displayOnly = false,
|
|
753
760
|
showDelete = false,
|
|
754
761
|
className = '',
|
|
762
|
+
imgClassName,
|
|
755
763
|
children,
|
|
756
764
|
loadingComponent,
|
|
757
765
|
errorComponent,
|
|
@@ -862,6 +870,7 @@ function FileDisplayAuthenticated({
|
|
|
862
870
|
displayOnly={displayOnly}
|
|
863
871
|
showDelete={showDelete}
|
|
864
872
|
className={className}
|
|
873
|
+
imgClassName={imgClassName}
|
|
865
874
|
children={children}
|
|
866
875
|
onDelete={showDelete ? handleDelete : undefined}
|
|
867
876
|
clearError={refetch}
|
|
@@ -905,6 +914,7 @@ export function FileDisplay({
|
|
|
905
914
|
displayOnly = false,
|
|
906
915
|
showDelete = false,
|
|
907
916
|
className = '',
|
|
917
|
+
imgClassName,
|
|
908
918
|
children,
|
|
909
919
|
loadingComponent,
|
|
910
920
|
errorComponent,
|
|
@@ -930,6 +940,7 @@ export function FileDisplay({
|
|
|
930
940
|
displayOnly={displayOnly}
|
|
931
941
|
showDelete={showDelete}
|
|
932
942
|
className={className}
|
|
943
|
+
imgClassName={imgClassName}
|
|
933
944
|
children={children}
|
|
934
945
|
loadingComponent={loadingComponent}
|
|
935
946
|
errorComponent={errorComponent}
|
|
@@ -955,6 +966,7 @@ export function FileDisplay({
|
|
|
955
966
|
displayOnly={displayOnly}
|
|
956
967
|
showDelete={showDelete}
|
|
957
968
|
className={className}
|
|
969
|
+
imgClassName={imgClassName}
|
|
958
970
|
children={children}
|
|
959
971
|
loadingComponent={loadingComponent}
|
|
960
972
|
errorComponent={errorComponent}
|
|
@@ -8,10 +8,12 @@
|
|
|
8
8
|
* Tests form rendering, validation, submission, and accessibility.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
+
import React from 'react';
|
|
11
12
|
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
12
13
|
import { render, screen, waitFor, act } from '@testing-library/react';
|
|
13
14
|
import userEvent from '@testing-library/user-event';
|
|
14
15
|
import { z } from 'zod';
|
|
16
|
+
import { useWatch, useFormState, useFormContext } from 'react-hook-form';
|
|
15
17
|
import { Form, FormField } from './index';
|
|
16
18
|
import { renderWithProviders } from '../../__tests__/helpers/test-utils';
|
|
17
19
|
|
|
@@ -108,27 +110,46 @@ describe('Form Component', () => {
|
|
|
108
110
|
|
|
109
111
|
it('shares live form state with render prop children', async () => {
|
|
110
112
|
const onSubmit = vi.fn();
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
113
|
+
const InnerComponent = () => {
|
|
114
|
+
// useWatch and useFormState must be called inside FormProvider context
|
|
115
|
+
// useFormState subscribes to form state changes and triggers re-renders
|
|
116
|
+
const { control } = useFormContext();
|
|
117
|
+
const nameValue = useWatch({ name: 'name', control });
|
|
118
|
+
const { isDirty } = useFormState({ control });
|
|
119
|
+
|
|
120
|
+
return (
|
|
121
|
+
<>
|
|
122
|
+
<span data-testid="dirty-flag">{isDirty ? 'dirty' : 'pristine'}</span>
|
|
123
|
+
<span data-testid="watched-value">{nameValue || ''}</span>
|
|
124
|
+
<FormField name="name" label="Name" />
|
|
125
|
+
</>
|
|
126
|
+
);
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
const TestComponent = () => {
|
|
130
|
+
return (
|
|
131
|
+
<Form onSubmit={onSubmit} defaultValues={{ name: '' }}>
|
|
132
|
+
<InnerComponent />
|
|
133
|
+
</Form>
|
|
134
|
+
);
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
renderWithProviders(<TestComponent />);
|
|
123
138
|
|
|
124
139
|
const input = screen.getByLabelText('Name');
|
|
125
140
|
expect(screen.getByTestId('dirty-flag')).toHaveTextContent('pristine');
|
|
141
|
+
|
|
142
|
+
// Type into the input field
|
|
143
|
+
await user.clear(input);
|
|
126
144
|
await user.type(input, 'Jane');
|
|
127
145
|
|
|
146
|
+
// Wait for both the watched value and dirty state to update
|
|
128
147
|
await waitFor(() => {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
148
|
+
const watchedValue = screen.getByTestId('watched-value');
|
|
149
|
+
const dirtyFlag = screen.getByTestId('dirty-flag');
|
|
150
|
+
expect(watchedValue).toHaveTextContent('Jane');
|
|
151
|
+
expect(dirtyFlag).toHaveTextContent('dirty');
|
|
152
|
+
}, { timeout: 5000 });
|
|
132
153
|
});
|
|
133
154
|
});
|
|
134
155
|
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
* - react-hook-form - Form state management
|
|
69
69
|
* - @hookform/resolvers/zod - Zod validation integration
|
|
70
70
|
* - zod - Schema validation
|
|
71
|
-
* - React
|
|
71
|
+
* - React 19+ - Hooks and context
|
|
72
72
|
*/
|
|
73
73
|
|
|
74
74
|
import React from 'react';
|
|
@@ -153,6 +153,7 @@ export function Form<TFieldValues extends FieldValues = FieldValues>({
|
|
|
153
153
|
resolver: schema ? zodResolver(schema) : undefined,
|
|
154
154
|
defaultValues,
|
|
155
155
|
mode,
|
|
156
|
+
shouldUnregister: false,
|
|
156
157
|
});
|
|
157
158
|
|
|
158
159
|
const handleSubmit = methods.handleSubmit(onSubmit, onError);
|
|
@@ -224,7 +225,7 @@ export interface FormFieldProps<
|
|
|
224
225
|
field: ControllerRenderProps<TFieldValues, TName>;
|
|
225
226
|
fieldState: ControllerFieldState;
|
|
226
227
|
formState: UseFormStateReturn<TFieldValues>;
|
|
227
|
-
}) => React.ReactElement
|
|
228
|
+
}) => React.ReactElement<any>;
|
|
228
229
|
|
|
229
230
|
/**
|
|
230
231
|
* Test ID
|
|
@@ -318,13 +319,7 @@ export function FormField<
|
|
|
318
319
|
'data-testid': testId,
|
|
319
320
|
className,
|
|
320
321
|
}: FormFieldProps<TFieldValues, TName>) {
|
|
321
|
-
const { control
|
|
322
|
-
const fieldError = errors[name];
|
|
323
|
-
|
|
324
|
-
// Safely extract error message
|
|
325
|
-
const errorMessage = fieldError && typeof fieldError === 'object' && 'message' in fieldError
|
|
326
|
-
? String(fieldError.message)
|
|
327
|
-
: undefined;
|
|
322
|
+
const { control } = useFormContext<TFieldValues>();
|
|
328
323
|
|
|
329
324
|
return (
|
|
330
325
|
<div className={cn("space-y-2", className)}>
|
|
@@ -344,32 +339,41 @@ export function FormField<
|
|
|
344
339
|
control={control}
|
|
345
340
|
rules={validation}
|
|
346
341
|
render={(props) => {
|
|
342
|
+
const { field, fieldState } = props;
|
|
343
|
+
const fieldError = fieldState.error;
|
|
344
|
+
|
|
345
|
+
// Safely extract error message
|
|
346
|
+
const errorMessage = fieldError && typeof fieldError === 'object' && 'message' in fieldError
|
|
347
|
+
? String(fieldError.message)
|
|
348
|
+
: undefined;
|
|
349
|
+
|
|
347
350
|
if (render) {
|
|
348
351
|
return render(props);
|
|
349
352
|
}
|
|
350
353
|
|
|
351
354
|
return (
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
355
|
+
<>
|
|
356
|
+
<input
|
|
357
|
+
{...field}
|
|
358
|
+
id={name}
|
|
359
|
+
type={type}
|
|
360
|
+
placeholder={placeholder}
|
|
361
|
+
data-testid={testId}
|
|
362
|
+
className={cn(
|
|
363
|
+
"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
|
364
|
+
fieldError && "border-destructive focus-visible:ring-destructive"
|
|
365
|
+
)}
|
|
366
|
+
{...inputProps}
|
|
367
|
+
/>
|
|
368
|
+
{errorMessage && (
|
|
369
|
+
<p className="text-destructive" role="alert">
|
|
370
|
+
{errorMessage}
|
|
371
|
+
</p>
|
|
361
372
|
)}
|
|
362
|
-
|
|
363
|
-
/>
|
|
373
|
+
</>
|
|
364
374
|
);
|
|
365
375
|
}}
|
|
366
376
|
/>
|
|
367
|
-
|
|
368
|
-
{errorMessage && (
|
|
369
|
-
<p className="text-destructive" role="alert">
|
|
370
|
-
{errorMessage}
|
|
371
|
-
</p>
|
|
372
|
-
)}
|
|
373
377
|
</div>
|
|
374
378
|
);
|
|
375
379
|
}
|