@jmruthers/pace-core 0.6.1 → 0.6.3
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 +88 -10
- package/cursor-rules/00-pace-core-compliance.mdc +46 -87
- package/cursor-rules/01-standards-compliance.mdc +16 -47
- package/cursor-rules/02-project-structure.mdc +4 -4
- package/cursor-rules/03-solid-principles.mdc +45 -164
- package/cursor-rules/04-testing-standards.mdc +22 -69
- package/cursor-rules/05-bug-reports-and-features.mdc +2 -2
- package/cursor-rules/06-code-quality.mdc +42 -125
- package/cursor-rules/07-tech-stack-compliance.mdc +33 -128
- package/cursor-rules/08-markup-quality.mdc +452 -0
- package/cursor-rules/CHANGELOG.md +18 -0
- package/cursor-rules/README.md +2 -1
- package/dist/{AuthService-DjnJHDtC.d.ts → AuthService-Cb34EQs3.d.ts} +63 -1
- package/dist/{DataTable-CH1U5Tpy.d.ts → DataTable-BMRU8a1j.d.ts} +33 -1
- package/dist/{DataTable-DQ7RSOHE.js → DataTable-THFPBKTP.js} +12 -10
- package/dist/{PublicPageProvider-ce4xlHYA.d.ts → PublicPageProvider-DEMpysFR.d.ts} +394 -171
- package/dist/{UnifiedAuthProvider-185Ih4dj.d.ts → UnifiedAuthProvider-CKvHP1MK.d.ts} +30 -8
- package/dist/{UnifiedAuthProvider-ATAP5UTR.js → UnifiedAuthProvider-KAGUYQ4J.js} +5 -4
- package/dist/{api-N774RPUA.js → api-IAGWF3ZG.js} +10 -10
- package/dist/{audit-B5P6FFIR.js → audit-V53FV5AG.js} +2 -2
- package/dist/{chunk-JBKQ3SAO.js → chunk-2T2IG7T7.js} +107 -57
- package/dist/chunk-2T2IG7T7.js.map +1 -0
- package/dist/{chunk-3QRJFVBR.js → chunk-6SOIHG6Z.js} +1 -1
- package/dist/chunk-6SOIHG6Z.js.map +1 -0
- package/dist/{chunk-3XTALGJF.js → chunk-6Z7LTB3D.js} +69 -240
- package/dist/chunk-6Z7LTB3D.js.map +1 -0
- package/dist/{chunk-4ZC4GX36.js → chunk-CNCQDFLN.js} +199 -46
- package/dist/chunk-CNCQDFLN.js.map +1 -0
- package/dist/chunk-DGUM43GV.js +11 -0
- package/dist/{chunk-BYFSK72L.js → chunk-DWUBLJJM.js} +361 -187
- package/dist/chunk-DWUBLJJM.js.map +1 -0
- package/dist/{chunk-LXQLPRQ2.js → chunk-FFQEQTNW.js} +6 -8
- 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-4N5C5XZU.js → chunk-HFZBI76P.js} +4 -4
- package/dist/chunk-HFZBI76P.js.map +1 -0
- package/dist/{chunk-SQGMNID3.js → chunk-L4OXEN46.js} +4 -5
- package/dist/chunk-L4OXEN46.js.map +1 -0
- package/dist/{chunk-R77UEZ4E.js → chunk-M43Y4SSO.js} +1 -1
- package/dist/chunk-M43Y4SSO.js.map +1 -0
- package/dist/{chunk-I7PSE6JW.js → chunk-M7MPQISP.js} +3 -76
- package/dist/chunk-M7MPQISP.js.map +1 -0
- package/dist/chunk-PQBSKX33.js +7793 -0
- package/dist/chunk-PQBSKX33.js.map +1 -0
- package/dist/chunk-QRPVRXYT.js +226 -0
- package/dist/chunk-QRPVRXYT.js.map +1 -0
- package/dist/{chunk-KNC55RTG.js → chunk-RWEBCB47.js} +194 -416
- package/dist/chunk-RWEBCB47.js.map +1 -0
- package/dist/{chunk-XM25TVIE.js → chunk-YDQHOZNA.js} +843 -388
- package/dist/chunk-YDQHOZNA.js.map +1 -0
- package/dist/{chunk-GLK6VM3F.js → chunk-ZNIWI3UC.js} +739 -737
- package/dist/chunk-ZNIWI3UC.js.map +1 -0
- package/dist/components.d.ts +5 -5
- package/dist/components.js +18 -16
- package/dist/components.js.map +1 -1
- package/dist/contextValidator-3JNZKUTX.js +9 -0
- package/dist/contextValidator-3JNZKUTX.js.map +1 -0
- package/dist/eslint-rules/pace-core-compliance.cjs +106 -0
- package/dist/{functions-D_kgHktt.d.ts → functions-DHebl8-F.d.ts} +1 -1
- package/dist/hooks.d.ts +55 -122
- package/dist/hooks.js +10 -13
- package/dist/hooks.js.map +1 -1
- package/dist/index.d.ts +60 -13
- package/dist/index.js +30 -25
- package/dist/index.js.map +1 -1
- package/dist/providers.d.ts +21 -3
- package/dist/providers.js +4 -3
- package/dist/rbac/index.d.ts +210 -139
- package/dist/rbac/index.js +17 -13
- package/dist/styles/index.js +1 -1
- package/dist/theming/runtime.d.ts +1 -13
- package/dist/theming/runtime.js +2 -2
- 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/types.js +1 -1
- package/dist/{usePublicRouteParams-BJAlWfuJ.d.ts → usePublicRouteParams-i3qtoBgg.d.ts} +38 -17
- package/dist/utils.d.ts +4 -5
- package/dist/utils.js +17 -19
- package/dist/utils.js.map +1 -1
- package/docs/api/README.md +21 -17
- package/docs/api/modules.md +4191 -2967
- package/docs/architecture/database-schema-requirements.md +161 -0
- package/docs/components/context-selector.md +126 -0
- package/docs/core-concepts/rbac-system.md +3 -3
- package/docs/documentation-index.md +2 -4
- package/docs/getting-started/cursor-rules.md +2 -1
- package/docs/migration/DOCUMENTATION_STRUCTURE.md +441 -0
- package/docs/migration/MIGRATION_GUIDE.md +2 -24
- package/docs/migration/RBAC_SCOPE_MIGRATION.md +385 -0
- package/docs/migration/README.md +52 -6
- package/docs/migration/V0.5.190_TO_V0.6.1_MIGRATION.md +1153 -0
- package/docs/migration/database-changes-december-2025.md +3 -3
- package/docs/pace-mint-fix-auto-selection.md +218 -0
- package/docs/pace-mint-rbac-setup.md +391 -0
- 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/rbac/secure-client-protection.md +330 -0
- package/docs/standards/README.md +1 -0
- package/package.json +4 -3
- 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} +784 -685
- 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 +985 -0
- package/scripts/audit/core/checks/documentation.cjs +268 -0
- package/scripts/audit/core/checks/environment.cjs +116 -0
- package/scripts/audit/core/checks/error-handling.cjs +340 -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 +61 -936
- 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/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__/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 +14 -0
- package/src/components/Button/Button.tsx +22 -0
- package/src/components/Calendar/Calendar.tsx +8 -2
- 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/ContextSelector/ContextSelector.tsx +384 -0
- package/src/components/ContextSelector/index.ts +3 -0
- package/src/components/DataTable/DataTable.tsx +38 -4
- package/src/components/DataTable/__tests__/DataTableCore.test-setup.ts +5 -6
- package/src/components/DataTable/__tests__/pagination.modes.test.tsx +18 -4
- package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +2 -3
- package/src/components/DataTable/components/AccessDeniedPage.tsx +16 -25
- package/src/components/DataTable/components/ActionButtons.tsx +10 -7
- package/src/components/DataTable/components/BulkOperationsDropdown.tsx +1 -1
- 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 +196 -554
- 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 +8 -0
- 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 +8 -0
- 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 +63 -851
- 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/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 +12 -0
- 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 +127 -33
- package/src/components/DataTable/hooks/useDataTableState.ts +35 -1
- package/src/components/DataTable/hooks/useEffectiveColumnOrder.ts +12 -0
- 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/Dialog/Dialog.tsx +31 -3
- package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +180 -1
- package/src/components/ErrorBoundary/ErrorBoundary.tsx +45 -5
- package/src/components/ErrorBoundary/ErrorBoundaryContext.tsx +129 -0
- package/src/components/ErrorBoundary/index.ts +27 -2
- package/src/components/FileDisplay/FileDisplay.tsx +74 -28
- package/src/components/FileUpload/FileUpload.tsx +22 -2
- package/src/components/Footer/Footer.test.tsx +16 -16
- package/src/components/Footer/Footer.tsx +14 -11
- package/src/components/Form/Form.tsx +1 -0
- package/src/components/Header/Header.test.tsx +43 -73
- package/src/components/Header/Header.tsx +59 -49
- package/src/components/Input/Input.test.tsx +2 -2
- package/src/components/Input/Input.tsx +8 -4
- package/src/components/LoadingSpinner/LoadingSpinner.test.tsx +4 -4
- package/src/components/LoginForm/LoginForm.tsx +4 -0
- package/src/components/NavigationMenu/NavigationMenu.tsx +14 -513
- package/src/components/NavigationMenu/types.ts +56 -0
- package/src/components/NavigationMenu/useNavigationFiltering.ts +390 -0
- package/src/components/PaceAppLayout/PaceAppLayout.integration.test.tsx +10 -19
- package/src/components/PaceAppLayout/PaceAppLayout.performance.test.tsx +2 -2
- package/src/components/PaceAppLayout/PaceAppLayout.security.test.tsx +5 -5
- package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +13 -11
- package/src/components/PaceAppLayout/PaceAppLayout.tsx +167 -44
- package/src/components/PaceAppLayout/README.md +14 -17
- package/src/components/PaceAppLayout/test-setup.tsx +3 -4
- package/src/components/PaceLoginPage/PaceLoginPage.tsx +3 -0
- package/src/components/PasswordChange/PasswordChangeForm.tsx +9 -0
- package/src/components/ProtectedRoute/ProtectedRoute.tsx +3 -9
- package/src/components/PublicLayout/PublicPageLayout.tsx +2 -5
- package/src/components/PublicLayout/PublicPageProvider.tsx +4 -0
- package/src/components/Select/Select.tsx +80 -434
- 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 +4 -5
- package/src/components/Switch/Switch.tsx +4 -4
- package/src/components/Tabs/Tabs.tsx +1 -1
- package/src/components/Toast/Toast.tsx +4 -0
- package/src/components/Tooltip/Tooltip.tsx +2 -2
- package/src/components/UserMenu/UserMenu.test.tsx +24 -11
- package/src/components/UserMenu/UserMenu.tsx +21 -18
- package/src/components/index.ts +7 -7
- package/src/eslint-rules/pace-core-compliance.cjs +106 -0
- package/src/hooks/__tests__/index.unit.test.ts +2 -5
- package/src/hooks/__tests__/useAppConfig.unit.test.ts +4 -98
- package/src/hooks/index.ts +1 -2
- package/src/hooks/public/usePublicEvent.ts +4 -0
- package/src/hooks/public/usePublicEventLogo.ts +4 -0
- package/src/hooks/public/usePublicFileDisplay.ts +4 -0
- package/src/hooks/public/usePublicRouteParams.ts +4 -0
- 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/useAppConfig.ts +15 -30
- package/src/hooks/useDebounce.ts +9 -0
- package/src/hooks/useEventTheme.ts +6 -0
- package/src/hooks/useFileDisplay.ts +81 -50
- package/src/hooks/useFileReference.ts +25 -7
- package/src/hooks/useFileUrl.ts +11 -1
- package/src/hooks/useFocusManagement.ts +14 -0
- package/src/hooks/useFocusTrap.ts +3 -0
- package/src/hooks/useInactivityTracker.ts +3 -0
- 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 +7 -0
- 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 +1 -1
- package/src/index.ts +6 -6
- package/src/providers/__tests__/OrganisationProvider.test.tsx +92 -70
- package/src/providers/services/AuthServiceProvider.tsx +35 -7
- package/src/providers/services/EventServiceProvider.tsx +51 -5
- package/src/providers/services/InactivityServiceProvider.tsx +18 -0
- package/src/providers/services/OrganisationServiceProvider.tsx +18 -0
- package/src/providers/services/UnifiedAuthProvider.tsx +126 -134
- package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +29 -13
- package/src/rbac/README.md +1 -1
- package/src/rbac/__tests__/adapters.comprehensive.test.tsx +1 -1
- package/src/rbac/__tests__/scenarios.user-role.test.tsx +4 -5
- package/src/rbac/adapters.tsx +12 -3
- package/src/rbac/api.test.ts +59 -51
- package/src/rbac/api.ts +246 -167
- package/src/rbac/components/NavigationProvider.tsx +4 -1
- package/src/rbac/components/PagePermissionGuard.tsx +185 -17
- package/src/rbac/components/RoleBasedRouter.tsx +5 -1
- package/src/rbac/components/SecureDataProvider.test.tsx +84 -49
- package/src/rbac/components/SecureDataProvider.tsx +20 -5
- 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/__tests__/useSecureSupabase.test.ts +32 -21
- 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 +377 -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 +64 -66
- package/src/rbac/hooks/usePermissions.ts +14 -995
- package/src/rbac/hooks/useRBAC.test.ts +1 -5
- package/src/rbac/hooks/useRBAC.ts +36 -37
- package/src/rbac/hooks/useResolvedScope.test.ts +120 -35
- package/src/rbac/hooks/useResolvedScope.ts +35 -40
- package/src/rbac/hooks/useResourcePermissions.test.ts +54 -18
- package/src/rbac/hooks/useResourcePermissions.ts +14 -4
- package/src/rbac/hooks/useSecureSupabase.ts +27 -7
- package/src/rbac/index.ts +7 -0
- package/src/rbac/permissions.ts +0 -30
- package/src/rbac/secureClient.test.ts +22 -18
- package/src/rbac/secureClient.ts +294 -68
- package/src/rbac/security.ts +0 -17
- package/src/rbac/types.ts +9 -0
- package/src/rbac/utils/__tests__/contextValidator.test.ts +64 -86
- package/src/rbac/utils/clientSecurity.ts +93 -0
- package/src/rbac/utils/contextValidator.ts +77 -168
- package/src/services/AuthService.ts +39 -7
- package/src/services/EventService.ts +186 -54
- package/src/services/OrganisationService.ts +81 -14
- package/src/services/__tests__/EventService.test.ts +1 -2
- package/src/services/base/BaseService.ts +3 -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/dynamic/dynamicUtils.ts +7 -4
- 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/dist/chunk-3QRJFVBR.js.map +0 -1
- package/dist/chunk-3XTALGJF.js.map +0 -1
- package/dist/chunk-4N5C5XZU.js.map +0 -1
- package/dist/chunk-4ZC4GX36.js.map +0 -1
- package/dist/chunk-7D4SUZUM.js +0 -38
- package/dist/chunk-BYFSK72L.js.map +0 -1
- package/dist/chunk-EXUD6RNJ.js +0 -451
- package/dist/chunk-EXUD6RNJ.js.map +0 -1
- package/dist/chunk-GLK6VM3F.js.map +0 -1
- package/dist/chunk-I7PSE6JW.js.map +0 -1
- package/dist/chunk-JBKQ3SAO.js.map +0 -1
- package/dist/chunk-KNC55RTG.js.map +0 -1
- package/dist/chunk-LXQLPRQ2.js.map +0 -1
- package/dist/chunk-R77UEZ4E.js.map +0 -1
- package/dist/chunk-SQGMNID3.js.map +0 -1
- package/dist/chunk-T33XF5ZC.js +0 -12922
- package/dist/chunk-T33XF5ZC.js.map +0 -1
- package/dist/chunk-XM25TVIE.js.map +0 -1
- package/docs/api/classes/ColumnFactory.md +0 -243
- package/docs/api/classes/ErrorBoundary.md +0 -144
- package/docs/api/classes/InvalidScopeError.md +0 -73
- package/docs/api/classes/Logger.md +0 -178
- package/docs/api/classes/MissingUserContextError.md +0 -66
- package/docs/api/classes/OrganisationContextRequiredError.md +0 -66
- package/docs/api/classes/PermissionDeniedError.md +0 -73
- package/docs/api/classes/RBACAuditManager.md +0 -297
- package/docs/api/classes/RBACCache.md +0 -322
- package/docs/api/classes/RBACEngine.md +0 -171
- package/docs/api/classes/RBACError.md +0 -76
- package/docs/api/classes/RBACNotInitializedError.md +0 -66
- package/docs/api/classes/SecureSupabaseClient.md +0 -160
- package/docs/api/classes/StorageUtils.md +0 -328
- package/docs/api/enums/FileCategory.md +0 -184
- package/docs/api/enums/LogLevel.md +0 -54
- package/docs/api/enums/RBACErrorCode.md +0 -228
- package/docs/api/enums/RPCFunction.md +0 -118
- package/docs/api/interfaces/AddressFieldProps.md +0 -241
- package/docs/api/interfaces/AddressFieldRef.md +0 -94
- package/docs/api/interfaces/AggregateConfig.md +0 -43
- package/docs/api/interfaces/AutocompleteOptions.md +0 -75
- package/docs/api/interfaces/AvatarProps.md +0 -128
- package/docs/api/interfaces/BadgeProps.md +0 -27
- package/docs/api/interfaces/ButtonProps.md +0 -53
- package/docs/api/interfaces/CalendarProps.md +0 -70
- package/docs/api/interfaces/CardProps.md +0 -66
- package/docs/api/interfaces/ColorPalette.md +0 -7
- package/docs/api/interfaces/ColorShade.md +0 -66
- package/docs/api/interfaces/ComplianceResult.md +0 -30
- package/docs/api/interfaces/DataAccessRecord.md +0 -96
- package/docs/api/interfaces/DataRecord.md +0 -11
- package/docs/api/interfaces/DataTableAction.md +0 -249
- package/docs/api/interfaces/DataTableColumn.md +0 -504
- package/docs/api/interfaces/DataTableProps.md +0 -625
- package/docs/api/interfaces/DataTableToolbarButton.md +0 -96
- package/docs/api/interfaces/DatabaseComplianceResult.md +0 -85
- package/docs/api/interfaces/DatabaseIssue.md +0 -41
- package/docs/api/interfaces/EmptyStateConfig.md +0 -61
- package/docs/api/interfaces/EnhancedNavigationMenuProps.md +0 -235
- package/docs/api/interfaces/EventAppRoleData.md +0 -71
- package/docs/api/interfaces/ExportColumn.md +0 -90
- package/docs/api/interfaces/ExportOptions.md +0 -126
- package/docs/api/interfaces/FileDisplayProps.md +0 -249
- package/docs/api/interfaces/FileMetadata.md +0 -129
- package/docs/api/interfaces/FileReference.md +0 -118
- package/docs/api/interfaces/FileSizeLimits.md +0 -7
- package/docs/api/interfaces/FileUploadOptions.md +0 -139
- package/docs/api/interfaces/FileUploadProps.md +0 -293
- package/docs/api/interfaces/FooterProps.md +0 -105
- package/docs/api/interfaces/FormFieldProps.md +0 -166
- package/docs/api/interfaces/FormProps.md +0 -113
- package/docs/api/interfaces/GrantEventAppRoleParams.md +0 -122
- package/docs/api/interfaces/InactivityWarningModalProps.md +0 -115
- package/docs/api/interfaces/InputProps.md +0 -53
- package/docs/api/interfaces/LabelProps.md +0 -107
- package/docs/api/interfaces/LoggerConfig.md +0 -62
- package/docs/api/interfaces/LoginFormProps.md +0 -184
- package/docs/api/interfaces/NavigationAccessRecord.md +0 -107
- package/docs/api/interfaces/NavigationContextType.md +0 -164
- package/docs/api/interfaces/NavigationGuardProps.md +0 -139
- package/docs/api/interfaces/NavigationItem.md +0 -120
- package/docs/api/interfaces/NavigationMenuProps.md +0 -221
- package/docs/api/interfaces/NavigationProviderProps.md +0 -117
- package/docs/api/interfaces/Organisation.md +0 -140
- package/docs/api/interfaces/OrganisationContextType.md +0 -388
- package/docs/api/interfaces/OrganisationMembership.md +0 -140
- package/docs/api/interfaces/OrganisationProviderProps.md +0 -76
- package/docs/api/interfaces/OrganisationSecurityError.md +0 -62
- package/docs/api/interfaces/PaceAppLayoutProps.md +0 -406
- package/docs/api/interfaces/PaceLoginPageProps.md +0 -47
- package/docs/api/interfaces/PageAccessRecord.md +0 -85
- package/docs/api/interfaces/PagePermissionContextType.md +0 -140
- package/docs/api/interfaces/PagePermissionGuardProps.md +0 -153
- package/docs/api/interfaces/PagePermissionProviderProps.md +0 -119
- package/docs/api/interfaces/PaletteData.md +0 -41
- package/docs/api/interfaces/ParsedAddress.md +0 -120
- package/docs/api/interfaces/PermissionEnforcerProps.md +0 -153
- package/docs/api/interfaces/ProgressProps.md +0 -42
- package/docs/api/interfaces/ProtectedRouteProps.md +0 -97
- package/docs/api/interfaces/PublicPageFooterProps.md +0 -112
- package/docs/api/interfaces/PublicPageHeaderProps.md +0 -125
- package/docs/api/interfaces/PublicPageLayoutProps.md +0 -198
- package/docs/api/interfaces/QuickFix.md +0 -52
- package/docs/api/interfaces/RBACAccessValidateParams.md +0 -52
- package/docs/api/interfaces/RBACAccessValidateResult.md +0 -41
- package/docs/api/interfaces/RBACAuditLogParams.md +0 -85
- package/docs/api/interfaces/RBACAuditLogResult.md +0 -52
- package/docs/api/interfaces/RBACConfig.md +0 -133
- package/docs/api/interfaces/RBACContext.md +0 -52
- package/docs/api/interfaces/RBACLogger.md +0 -112
- package/docs/api/interfaces/RBACPageAccessCheckParams.md +0 -74
- package/docs/api/interfaces/RBACPerformanceMetrics.md +0 -138
- package/docs/api/interfaces/RBACPermissionCheckParams.md +0 -74
- package/docs/api/interfaces/RBACPermissionCheckResult.md +0 -52
- package/docs/api/interfaces/RBACPermissionsGetParams.md +0 -63
- package/docs/api/interfaces/RBACPermissionsGetResult.md +0 -63
- package/docs/api/interfaces/RBACResult.md +0 -58
- package/docs/api/interfaces/RBACRoleGrantParams.md +0 -63
- package/docs/api/interfaces/RBACRoleGrantResult.md +0 -52
- package/docs/api/interfaces/RBACRoleRevokeParams.md +0 -63
- package/docs/api/interfaces/RBACRoleRevokeResult.md +0 -52
- package/docs/api/interfaces/RBACRoleValidateParams.md +0 -52
- package/docs/api/interfaces/RBACRoleValidateResult.md +0 -63
- package/docs/api/interfaces/RBACRolesListParams.md +0 -52
- package/docs/api/interfaces/RBACRolesListResult.md +0 -74
- package/docs/api/interfaces/RBACSessionTrackParams.md +0 -74
- package/docs/api/interfaces/RBACSessionTrackResult.md +0 -52
- package/docs/api/interfaces/ResourcePermissions.md +0 -155
- package/docs/api/interfaces/RevokeEventAppRoleParams.md +0 -100
- package/docs/api/interfaces/RoleBasedRouterContextType.md +0 -151
- package/docs/api/interfaces/RoleBasedRouterProps.md +0 -156
- package/docs/api/interfaces/RoleManagementResult.md +0 -52
- package/docs/api/interfaces/RouteAccessRecord.md +0 -107
- package/docs/api/interfaces/RouteConfig.md +0 -134
- package/docs/api/interfaces/RuntimeComplianceResult.md +0 -55
- package/docs/api/interfaces/SecureDataContextType.md +0 -168
- package/docs/api/interfaces/SecureDataProviderProps.md +0 -132
- package/docs/api/interfaces/SessionRestorationLoaderProps.md +0 -34
- package/docs/api/interfaces/SetupIssue.md +0 -41
- package/docs/api/interfaces/StorageConfig.md +0 -41
- package/docs/api/interfaces/StorageFileInfo.md +0 -74
- package/docs/api/interfaces/StorageFileMetadata.md +0 -151
- package/docs/api/interfaces/StorageListOptions.md +0 -99
- package/docs/api/interfaces/StorageListResult.md +0 -41
- package/docs/api/interfaces/StorageUploadOptions.md +0 -101
- package/docs/api/interfaces/StorageUploadResult.md +0 -63
- package/docs/api/interfaces/StorageUrlOptions.md +0 -60
- package/docs/api/interfaces/StyleImport.md +0 -19
- package/docs/api/interfaces/SwitchProps.md +0 -34
- package/docs/api/interfaces/TabsContentProps.md +0 -9
- package/docs/api/interfaces/TabsListProps.md +0 -9
- package/docs/api/interfaces/TabsProps.md +0 -9
- package/docs/api/interfaces/TabsTriggerProps.md +0 -50
- package/docs/api/interfaces/TextareaProps.md +0 -53
- package/docs/api/interfaces/ToastActionElement.md +0 -9
- package/docs/api/interfaces/ToastProps.md +0 -9
- package/docs/api/interfaces/UnifiedAuthContextType.md +0 -820
- package/docs/api/interfaces/UnifiedAuthProviderProps.md +0 -171
- package/docs/api/interfaces/UseFormDialogOptions.md +0 -62
- package/docs/api/interfaces/UseFormDialogReturn.md +0 -117
- package/docs/api/interfaces/UseInactivityTrackerOptions.md +0 -136
- package/docs/api/interfaces/UseInactivityTrackerReturn.md +0 -123
- package/docs/api/interfaces/UsePublicEventLogoOptions.md +0 -87
- package/docs/api/interfaces/UsePublicEventLogoReturn.md +0 -81
- package/docs/api/interfaces/UsePublicEventOptions.md +0 -34
- package/docs/api/interfaces/UsePublicEventReturn.md +0 -68
- package/docs/api/interfaces/UsePublicFileDisplayOptions.md +0 -47
- package/docs/api/interfaces/UsePublicFileDisplayReturn.md +0 -120
- package/docs/api/interfaces/UsePublicRouteParamsReturn.md +0 -94
- package/docs/api/interfaces/UseResolvedScopeOptions.md +0 -47
- package/docs/api/interfaces/UseResolvedScopeReturn.md +0 -47
- package/docs/api/interfaces/UseResourcePermissionsOptions.md +0 -34
- package/docs/api/interfaces/UserEventAccess.md +0 -118
- package/docs/api/interfaces/UserMenuProps.md +0 -86
- package/docs/api/interfaces/UserProfile.md +0 -63
- package/docs/migration/quick-migration-guide.md +0 -356
- package/docs/migration/service-architecture.md +0 -281
- package/src/components/EventSelector/EventSelector.test.tsx +0 -720
- package/src/components/EventSelector/EventSelector.tsx +0 -420
- package/src/components/EventSelector/index.ts +0 -3
- package/src/components/OrganisationSelector/OrganisationSelector.test.tsx +0 -784
- package/src/components/OrganisationSelector/OrganisationSelector.tsx +0 -324
- package/src/components/OrganisationSelector/index.ts +0 -9
- package/src/hooks/__tests__/useSecureDataAccess.unit.test.tsx +0 -680
- package/src/hooks/useSecureDataAccess.test.ts +0 -559
- package/src/hooks/useSecureDataAccess.ts +0 -681
- /package/dist/{DataTable-DQ7RSOHE.js.map → DataTable-THFPBKTP.js.map} +0 -0
- /package/dist/{UnifiedAuthProvider-ATAP5UTR.js.map → UnifiedAuthProvider-KAGUYQ4J.js.map} +0 -0
- /package/dist/{api-N774RPUA.js.map → api-IAGWF3ZG.js.map} +0 -0
- /package/dist/{audit-B5P6FFIR.js.map → audit-V53FV5AG.js.map} +0 -0
- /package/dist/{chunk-7D4SUZUM.js.map → chunk-DGUM43GV.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/docs/migration/{REACT_19_MIGRATION.md → V0.6.0_REACT_19_MIGRATION.md} +0 -0
|
@@ -47,28 +47,28 @@
|
|
|
47
47
|
*
|
|
48
48
|
* // Footer with custom content
|
|
49
49
|
* <Footer companyName="My Company">
|
|
50
|
-
* <
|
|
51
|
-
* <
|
|
50
|
+
* <section className="grid grid-cols-1 md:grid-cols-3 gap-8 mb-8">
|
|
51
|
+
* <section>
|
|
52
52
|
* <h3 className="font-semibold mb-2">About Us</h3>
|
|
53
53
|
* <p className="text-sm text-muted-foreground">
|
|
54
54
|
* We provide innovative solutions for modern businesses.
|
|
55
55
|
* </p>
|
|
56
|
-
* </
|
|
57
|
-
* <
|
|
56
|
+
* </section>
|
|
57
|
+
* <section>
|
|
58
58
|
* <h3 className="font-semibold mb-2">Contact</h3>
|
|
59
59
|
* <p className="text-sm text-muted-foreground">
|
|
60
60
|
* Email: info@mycompany.com<br />
|
|
61
61
|
* Phone: (555) 123-4567
|
|
62
62
|
* </p>
|
|
63
|
-
* </
|
|
64
|
-
* <
|
|
63
|
+
* </section>
|
|
64
|
+
* <section>
|
|
65
65
|
* <h3 className="font-semibold mb-2">Follow Us</h3>
|
|
66
|
-
* <
|
|
66
|
+
* <nav className="flex gap-2">
|
|
67
67
|
* <a href="#" className="text-muted-foreground hover:text-foreground">Twitter</a>
|
|
68
68
|
* <a href="#" className="text-muted-foreground hover:text-foreground">LinkedIn</a>
|
|
69
|
-
* </
|
|
70
|
-
* </
|
|
71
|
-
* </
|
|
69
|
+
* </nav>
|
|
70
|
+
* </section>
|
|
71
|
+
* </section>
|
|
72
72
|
* </Footer>
|
|
73
73
|
* ```
|
|
74
74
|
*
|
|
@@ -87,6 +87,9 @@
|
|
|
87
87
|
import React from 'react';
|
|
88
88
|
import { cn } from '../../utils/core/cn';
|
|
89
89
|
|
|
90
|
+
/**
|
|
91
|
+
* Props for the Footer component.
|
|
92
|
+
*/
|
|
90
93
|
export interface FooterProps {
|
|
91
94
|
/**
|
|
92
95
|
* Company or organization name
|
|
@@ -138,7 +141,7 @@ export interface FooterProps {
|
|
|
138
141
|
*
|
|
139
142
|
* // With children
|
|
140
143
|
* <Footer>
|
|
141
|
-
* <
|
|
144
|
+
* <section>Custom footer content</section>
|
|
142
145
|
* </Footer>
|
|
143
146
|
*
|
|
144
147
|
* // With logo and copyright
|
|
@@ -359,6 +359,7 @@ export function FormField<
|
|
|
359
359
|
type={type}
|
|
360
360
|
placeholder={placeholder}
|
|
361
361
|
data-testid={testId}
|
|
362
|
+
aria-label={label || placeholder || name}
|
|
362
363
|
className={cn(
|
|
363
364
|
"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
365
|
fieldError && "border-destructive focus-visible:ring-destructive"
|
|
@@ -52,20 +52,24 @@ vi.mock('../UserMenu', () => ({
|
|
|
52
52
|
),
|
|
53
53
|
}));
|
|
54
54
|
|
|
55
|
-
vi.mock('../
|
|
56
|
-
|
|
57
|
-
<div data-testid={testId || '
|
|
58
|
-
<button>{placeholder}</button>
|
|
55
|
+
vi.mock('../ContextSelector', () => ({
|
|
56
|
+
ContextSelector: ({ placeholder, className, 'data-testid': testId }: any) => (
|
|
57
|
+
<div data-testid={testId || 'context-selector'} className={className}>
|
|
58
|
+
<button>{placeholder || 'Select organisation or event'}</button>
|
|
59
59
|
</div>
|
|
60
60
|
),
|
|
61
61
|
}));
|
|
62
62
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
63
|
+
// Mock useEventService to prevent provider requirement
|
|
64
|
+
vi.mock('../../hooks/services/useEventService', () => ({
|
|
65
|
+
useEventService: vi.fn(() => ({
|
|
66
|
+
getEvents: vi.fn(() => []),
|
|
67
|
+
getSelectedEvent: vi.fn(() => null),
|
|
68
|
+
isLoading: vi.fn(() => false),
|
|
69
|
+
getError: vi.fn(() => null),
|
|
70
|
+
setSelectedEvent: vi.fn(),
|
|
71
|
+
refreshEvents: vi.fn()
|
|
72
|
+
}))
|
|
69
73
|
}));
|
|
70
74
|
|
|
71
75
|
// Mock useOrganisations hook
|
|
@@ -90,7 +94,7 @@ vi.mock('../../hooks/useOrganisations', () => ({
|
|
|
90
94
|
isContextReady: true,
|
|
91
95
|
isLoading: false,
|
|
92
96
|
error: null,
|
|
93
|
-
|
|
97
|
+
switchOrganisation: vi.fn(),
|
|
94
98
|
refreshOrganisations: vi.fn(),
|
|
95
99
|
userMemberships: []
|
|
96
100
|
}))
|
|
@@ -314,44 +318,44 @@ describe('Header Component', () => {
|
|
|
314
318
|
});
|
|
315
319
|
});
|
|
316
320
|
|
|
317
|
-
//
|
|
318
|
-
describe('
|
|
319
|
-
it('renders
|
|
320
|
-
renderWithProviders(<Header
|
|
321
|
+
// Context selector tests
|
|
322
|
+
describe('Context Selector', () => {
|
|
323
|
+
it('renders context selector by default', () => {
|
|
324
|
+
renderWithProviders(<Header />);
|
|
321
325
|
|
|
322
|
-
expect(screen.getByTestId('
|
|
326
|
+
expect(screen.getByTestId('context-selector')).toBeInTheDocument();
|
|
323
327
|
});
|
|
324
328
|
|
|
325
|
-
it('does not render
|
|
326
|
-
renderWithProviders(<Header
|
|
329
|
+
it('does not render context selector when showContextSelector is false', () => {
|
|
330
|
+
renderWithProviders(<Header showContextSelector={false} />);
|
|
327
331
|
|
|
328
|
-
expect(screen.queryByTestId('
|
|
332
|
+
expect(screen.queryByTestId('context-selector')).not.toBeInTheDocument();
|
|
329
333
|
});
|
|
330
334
|
|
|
331
|
-
it('renders
|
|
332
|
-
renderWithProviders(<Header />);
|
|
335
|
+
it('renders context selector when showContextSelector is explicitly true', () => {
|
|
336
|
+
renderWithProviders(<Header showContextSelector={true} />);
|
|
333
337
|
|
|
334
|
-
expect(screen.getByTestId('
|
|
338
|
+
expect(screen.getByTestId('context-selector')).toBeInTheDocument();
|
|
335
339
|
});
|
|
336
340
|
|
|
337
|
-
it('applies correct className to
|
|
338
|
-
renderWithProviders(<Header
|
|
341
|
+
it('applies correct className to context selector', () => {
|
|
342
|
+
renderWithProviders(<Header showContextSelector={true} />);
|
|
339
343
|
|
|
340
|
-
const
|
|
341
|
-
expect(
|
|
342
|
-
expect(
|
|
344
|
+
const contextSelector = screen.getByTestId('context-selector');
|
|
345
|
+
expect(contextSelector).toBeInTheDocument();
|
|
346
|
+
expect(contextSelector).toBeVisible();
|
|
343
347
|
});
|
|
344
348
|
|
|
345
349
|
it('shows correct placeholder text', () => {
|
|
346
|
-
renderWithProviders(<Header
|
|
350
|
+
renderWithProviders(<Header showContextSelector={true} />);
|
|
347
351
|
|
|
348
|
-
expect(screen.getByRole('button', { name: 'Select event' })).toBeInTheDocument();
|
|
352
|
+
expect(screen.getByRole('button', { name: 'Select organisation or event' })).toBeInTheDocument();
|
|
349
353
|
});
|
|
350
354
|
|
|
351
|
-
it('preserves layout when
|
|
355
|
+
it('preserves layout when context selector is hidden', () => {
|
|
352
356
|
renderWithProviders(
|
|
353
357
|
<Header
|
|
354
|
-
|
|
358
|
+
showContextSelector={false}
|
|
355
359
|
user={mockUser}
|
|
356
360
|
showUserMenu={true}
|
|
357
361
|
/>
|
|
@@ -361,47 +365,14 @@ describe('Header Component', () => {
|
|
|
361
365
|
expect(nav).toBeInTheDocument();
|
|
362
366
|
expect(nav).toBeVisible();
|
|
363
367
|
|
|
364
|
-
//
|
|
365
|
-
expect(screen.queryByTestId('
|
|
368
|
+
// Context selector should not be rendered
|
|
369
|
+
expect(screen.queryByTestId('context-selector')).not.toBeInTheDocument();
|
|
366
370
|
|
|
367
371
|
// User menu should still be present and positioned correctly
|
|
368
372
|
expect(screen.getByTestId('user-menu')).toBeInTheDocument();
|
|
369
373
|
});
|
|
370
374
|
});
|
|
371
375
|
|
|
372
|
-
// Organisation Selector tests
|
|
373
|
-
describe('Organisation Selector', () => {
|
|
374
|
-
it('does not render organisation selector by default', () => {
|
|
375
|
-
renderWithProviders(<Header />);
|
|
376
|
-
|
|
377
|
-
expect(screen.queryByTestId('org-selector')).not.toBeInTheDocument();
|
|
378
|
-
});
|
|
379
|
-
|
|
380
|
-
it('renders organisation selector when showOrgSelector is true', () => {
|
|
381
|
-
renderWithProviders(<Header showOrgSelector={true} />);
|
|
382
|
-
|
|
383
|
-
expect(screen.getByTestId('org-selector')).toBeInTheDocument();
|
|
384
|
-
});
|
|
385
|
-
|
|
386
|
-
it('does not render organisation selector when showOrgSelector is false', () => {
|
|
387
|
-
renderWithProviders(<Header showOrgSelector={false} />);
|
|
388
|
-
|
|
389
|
-
expect(screen.queryByTestId('org-selector')).not.toBeInTheDocument();
|
|
390
|
-
});
|
|
391
|
-
|
|
392
|
-
it('can render both organisation and event selectors together', () => {
|
|
393
|
-
renderWithProviders(
|
|
394
|
-
<Header
|
|
395
|
-
showOrgSelector={true}
|
|
396
|
-
showEventSelector={true}
|
|
397
|
-
/>
|
|
398
|
-
);
|
|
399
|
-
|
|
400
|
-
expect(screen.getByTestId('org-selector')).toBeInTheDocument();
|
|
401
|
-
expect(screen.getByTestId('event-selector')).toBeInTheDocument();
|
|
402
|
-
});
|
|
403
|
-
});
|
|
404
|
-
|
|
405
376
|
// Custom actions tests
|
|
406
377
|
describe('Custom Actions', () => {
|
|
407
378
|
it('renders custom actions when provided', () => {
|
|
@@ -598,7 +569,7 @@ describe('Header Component', () => {
|
|
|
598
569
|
navItems={mockNavItems}
|
|
599
570
|
user={mockUser}
|
|
600
571
|
actions={customActions}
|
|
601
|
-
|
|
572
|
+
showContextSelector={true}
|
|
602
573
|
showUserMenu={true}
|
|
603
574
|
/>
|
|
604
575
|
);
|
|
@@ -609,8 +580,8 @@ describe('Header Component', () => {
|
|
|
609
580
|
// Navigation
|
|
610
581
|
expect(screen.getByTestId('navigation-menu')).toBeInTheDocument();
|
|
611
582
|
|
|
612
|
-
//
|
|
613
|
-
expect(screen.getByTestId('
|
|
583
|
+
// Context Selector
|
|
584
|
+
expect(screen.getByTestId('context-selector')).toBeInTheDocument();
|
|
614
585
|
|
|
615
586
|
// Custom Actions
|
|
616
587
|
expect(screen.getByTestId('custom-actions')).toBeInTheDocument();
|
|
@@ -622,7 +593,7 @@ describe('Header Component', () => {
|
|
|
622
593
|
it('renders minimal configuration', () => {
|
|
623
594
|
renderWithProviders(
|
|
624
595
|
<Header
|
|
625
|
-
|
|
596
|
+
showContextSelector={false}
|
|
626
597
|
showUserMenu={false}
|
|
627
598
|
/>
|
|
628
599
|
);
|
|
@@ -631,9 +602,8 @@ describe('Header Component', () => {
|
|
|
631
602
|
expect(screen.getByRole('banner')).toBeInTheDocument();
|
|
632
603
|
expect(screen.getByRole('img', { name: 'Logo' })).toBeInTheDocument();
|
|
633
604
|
expect(screen.queryByTestId('navigation-menu')).not.toBeInTheDocument();
|
|
634
|
-
expect(screen.queryByTestId('
|
|
605
|
+
expect(screen.queryByTestId('context-selector')).not.toBeInTheDocument();
|
|
635
606
|
expect(screen.queryByTestId('user-menu')).not.toBeInTheDocument();
|
|
636
|
-
expect(screen.queryByTestId('org-selector')).not.toBeInTheDocument();
|
|
637
607
|
});
|
|
638
608
|
});
|
|
639
609
|
|
|
@@ -649,7 +619,7 @@ describe('Header Component', () => {
|
|
|
649
619
|
navItems={mockNavItems}
|
|
650
620
|
user={mockUser}
|
|
651
621
|
actions={<div>Actions</div>}
|
|
652
|
-
|
|
622
|
+
showContextSelector={true}
|
|
653
623
|
showUserMenu={true}
|
|
654
624
|
/>
|
|
655
625
|
);
|
|
@@ -42,20 +42,20 @@
|
|
|
42
42
|
* ]}
|
|
43
43
|
* currentPath="/dashboard"
|
|
44
44
|
* actions={
|
|
45
|
-
*
|
|
45
|
+
* <>
|
|
46
46
|
* <Button variant="outline">Export</Button>
|
|
47
47
|
* <Button>New Item</Button>
|
|
48
|
-
*
|
|
48
|
+
* </>
|
|
49
49
|
* }
|
|
50
50
|
* user={currentUser}
|
|
51
51
|
* onSignOut={handleSignOut}
|
|
52
52
|
* />
|
|
53
53
|
*
|
|
54
|
-
* // Header without
|
|
54
|
+
* // Header without context selector
|
|
55
55
|
* <Header
|
|
56
56
|
* logoUrl="/logo.svg"
|
|
57
57
|
* logoHref="/dashboard"
|
|
58
|
-
*
|
|
58
|
+
* showContextSelector={false}
|
|
59
59
|
* user={currentUser}
|
|
60
60
|
* onSignOut={handleSignOut}
|
|
61
61
|
* />
|
|
@@ -83,21 +83,21 @@
|
|
|
83
83
|
* - Tailwind CSS - Styling
|
|
84
84
|
* - NavigationMenu component
|
|
85
85
|
* - UserMenu component
|
|
86
|
-
* -
|
|
87
|
-
* - EventSelector component
|
|
86
|
+
* - ContextSelector component (unified org/event selector)
|
|
88
87
|
*/
|
|
89
88
|
|
|
90
89
|
import React from 'react';
|
|
91
90
|
import { Link } from 'react-router-dom';
|
|
92
91
|
import { User } from '@supabase/supabase-js';
|
|
93
92
|
import { cn } from '../../utils/core/cn';
|
|
94
|
-
import {
|
|
95
|
-
import { OrganisationSelector } from '../OrganisationSelector';
|
|
93
|
+
import { ContextSelector } from '../ContextSelector';
|
|
96
94
|
import { UserMenu } from '../UserMenu';
|
|
97
95
|
import { NavigationMenu } from '../NavigationMenu';
|
|
98
96
|
import type { NavigationItem } from '../NavigationMenu';
|
|
99
97
|
import type { PasswordChangeFormError } from '../PasswordChange/PasswordChangeForm';
|
|
100
98
|
import { useOrganisations } from '../../hooks/useOrganisations';
|
|
99
|
+
import { useEvents } from '../../hooks/useEvents';
|
|
100
|
+
import type { Event } from '../../types/event';
|
|
101
101
|
|
|
102
102
|
/**
|
|
103
103
|
* Props for the Header component
|
|
@@ -123,10 +123,12 @@ export interface HeaderProps {
|
|
|
123
123
|
userMenu?: React.ReactNode;
|
|
124
124
|
/** Custom className */
|
|
125
125
|
className?: string;
|
|
126
|
-
/** Show/hide event selector */
|
|
127
|
-
|
|
128
|
-
/** Show
|
|
129
|
-
|
|
126
|
+
/** Show/hide context selector (unified org/event selector) - default: true */
|
|
127
|
+
showContextSelector?: boolean;
|
|
128
|
+
/** Show organisations in context selector - default: true */
|
|
129
|
+
showOrganisations?: boolean;
|
|
130
|
+
/** Show events in context selector - default: true */
|
|
131
|
+
showEvents?: boolean;
|
|
130
132
|
/** Show/hide user menu */
|
|
131
133
|
showUserMenu?: boolean;
|
|
132
134
|
/** Current path for navigation highlighting */
|
|
@@ -199,10 +201,10 @@ export interface HeaderProps {
|
|
|
199
201
|
*
|
|
200
202
|
* function HeaderWithActions() {
|
|
201
203
|
* const customActions = (
|
|
202
|
-
*
|
|
204
|
+
* <>
|
|
203
205
|
* <Button variant="outline" size="sm">Export</Button>
|
|
204
206
|
* <Button size="sm">New Item</Button>
|
|
205
|
-
*
|
|
207
|
+
* </>
|
|
206
208
|
* );
|
|
207
209
|
*
|
|
208
210
|
* return (
|
|
@@ -225,7 +227,7 @@ export interface HeaderProps {
|
|
|
225
227
|
* <Header
|
|
226
228
|
* logoUrl="/simple-logo.svg"
|
|
227
229
|
* logoAlt="Simple App"
|
|
228
|
-
*
|
|
230
|
+
* showContextSelector={false}
|
|
229
231
|
* user={currentUser}
|
|
230
232
|
* onSignOut={handleSignOut}
|
|
231
233
|
* />
|
|
@@ -238,6 +240,13 @@ export interface HeaderProps {
|
|
|
238
240
|
*
|
|
239
241
|
* @since 0.1.0
|
|
240
242
|
*/
|
|
243
|
+
/**
|
|
244
|
+
* Header component for application layouts.
|
|
245
|
+
* Provides navigation, user menu, organisation/event selectors, and customizable branding.
|
|
246
|
+
*
|
|
247
|
+
* @param props - Header configuration
|
|
248
|
+
* @returns The rendered header
|
|
249
|
+
*/
|
|
241
250
|
export function Header({
|
|
242
251
|
logoUrl,
|
|
243
252
|
logoAlt = 'Logo',
|
|
@@ -249,36 +258,27 @@ export function Header({
|
|
|
249
258
|
actions,
|
|
250
259
|
userMenu,
|
|
251
260
|
className,
|
|
252
|
-
|
|
253
|
-
|
|
261
|
+
showContextSelector = true,
|
|
262
|
+
showOrganisations = true,
|
|
263
|
+
showEvents = true,
|
|
254
264
|
showUserMenu = true,
|
|
255
265
|
currentPath,
|
|
256
266
|
onNavigate,
|
|
257
267
|
logoHref
|
|
258
268
|
}: HeaderProps) {
|
|
259
|
-
//
|
|
260
|
-
const
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
}
|
|
266
|
-
return (
|
|
267
|
-
<OrganisationSelector
|
|
268
|
-
placeholder="Select organisation"
|
|
269
|
-
className="w-64"
|
|
270
|
-
data-testid="org-selector"
|
|
271
|
-
compact={true}
|
|
272
|
-
/>
|
|
273
|
-
);
|
|
274
|
-
};
|
|
269
|
+
// Determine if context selector should be shown
|
|
270
|
+
const shouldShowContextSelector = showContextSelector !== false;
|
|
271
|
+
|
|
272
|
+
// Get hooks for context selector
|
|
273
|
+
const { switchOrganisation } = useOrganisations();
|
|
274
|
+
const { events, setSelectedEvent } = useEvents();
|
|
275
275
|
|
|
276
276
|
return (
|
|
277
277
|
<header className={cn(
|
|
278
278
|
"w-full border-b border-main-200 h-16 shadow-sm bg-main-100 ",
|
|
279
279
|
className
|
|
280
280
|
)} role="banner">
|
|
281
|
-
<nav className="px-4 w-[min(var(--app-width),100%)] mx-auto
|
|
281
|
+
<nav className="px-4 w-[min(var(--app-width),100%)] mx-auto grid grid-cols-[auto_1fr_auto_auto_auto_auto] items-center gap-4 h-full">
|
|
282
282
|
{/* Logo */}
|
|
283
283
|
{logo ? (
|
|
284
284
|
logoHref ? (
|
|
@@ -333,21 +333,32 @@ export function Header({
|
|
|
333
333
|
itemsPreFiltered={true}
|
|
334
334
|
/>
|
|
335
335
|
)}
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
{/* Right side: Organisation Selector, Event Selector, Actions, and User Menu */}
|
|
339
|
-
<div className="flex items-center gap-4 ml-auto">
|
|
340
|
-
{/* Organisation Selector - Only show if user has organisations */}
|
|
341
|
-
{showOrgSelector ? (
|
|
342
|
-
<OrganisationSelectorConditional />
|
|
343
|
-
) : null}
|
|
344
336
|
|
|
345
|
-
{/*
|
|
346
|
-
{
|
|
347
|
-
<
|
|
348
|
-
placeholder="Select event"
|
|
349
|
-
className=
|
|
350
|
-
|
|
337
|
+
{/* Unified Context Selector - Shows all accessible orgs and events */}
|
|
338
|
+
{shouldShowContextSelector ? (
|
|
339
|
+
<ContextSelector
|
|
340
|
+
placeholder="Select organisation or event"
|
|
341
|
+
className={cn(
|
|
342
|
+
"w-96",
|
|
343
|
+
// Adjust width based on whether actions exist
|
|
344
|
+
actions ? "col-span-1" : "col-span-2"
|
|
345
|
+
)}
|
|
346
|
+
showOrganisations={showOrganisations}
|
|
347
|
+
showEvents={showEvents}
|
|
348
|
+
onOrganisationSelect={async (org) => {
|
|
349
|
+
// When switching to an organisation, clear event selection FIRST
|
|
350
|
+
// This ensures the userClearedEventRef flag is set before any event refresh
|
|
351
|
+
// This prevents auto-selection from re-selecting the event
|
|
352
|
+
setSelectedEvent(null);
|
|
353
|
+
// Then switch organisation (this may trigger event refresh, but flag is already set)
|
|
354
|
+
await switchOrganisation(org.id);
|
|
355
|
+
}}
|
|
356
|
+
onEventSelect={(event) => {
|
|
357
|
+
// Find the full event object from the events list
|
|
358
|
+
const fullEvent = events.find((e: Event) => (e.event_id || e.id) === (event.event_id || event.id));
|
|
359
|
+
setSelectedEvent(fullEvent || event);
|
|
360
|
+
}}
|
|
361
|
+
compact={true}
|
|
351
362
|
/>
|
|
352
363
|
) : null}
|
|
353
364
|
|
|
@@ -367,7 +378,6 @@ export function Header({
|
|
|
367
378
|
/>
|
|
368
379
|
)
|
|
369
380
|
)}
|
|
370
|
-
</div>
|
|
371
381
|
|
|
372
382
|
</nav>
|
|
373
383
|
</header>
|
|
@@ -420,14 +420,14 @@ describe('InputGroup Component', () => {
|
|
|
420
420
|
// Accessibility tests
|
|
421
421
|
describe('Accessibility', () => {
|
|
422
422
|
it('forwards ref correctly', () => {
|
|
423
|
-
const ref = React.createRef<
|
|
423
|
+
const ref = React.createRef<HTMLFieldSetElement>();
|
|
424
424
|
renderWithProviders(
|
|
425
425
|
<InputGroup ref={ref}>
|
|
426
426
|
<Input placeholder="Input 1" />
|
|
427
427
|
</InputGroup>
|
|
428
428
|
);
|
|
429
429
|
|
|
430
|
-
expect(ref.current).toBeInstanceOf(
|
|
430
|
+
expect(ref.current).toBeInstanceOf(HTMLFieldSetElement);
|
|
431
431
|
});
|
|
432
432
|
|
|
433
433
|
it('maintains proper focus order', async () => {
|
|
@@ -55,6 +55,10 @@ import { cn } from '../../utils/core/cn';
|
|
|
55
55
|
// BASE INPUT COMPONENT
|
|
56
56
|
// ============================================================================
|
|
57
57
|
|
|
58
|
+
/**
|
|
59
|
+
* Props for the Input component.
|
|
60
|
+
* Extends standard input HTML attributes.
|
|
61
|
+
*/
|
|
58
62
|
export interface InputProps
|
|
59
63
|
extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size'> {
|
|
60
64
|
/**
|
|
@@ -136,7 +140,7 @@ Input.displayName = 'Input';
|
|
|
136
140
|
// INPUT GROUP COMPONENT
|
|
137
141
|
// ============================================================================
|
|
138
142
|
|
|
139
|
-
export interface InputGroupProps extends React.HTMLAttributes<
|
|
143
|
+
export interface InputGroupProps extends React.HTMLAttributes<HTMLFieldSetElement> {
|
|
140
144
|
/** Child elements to be rendered in the group */
|
|
141
145
|
children: React.ReactNode;
|
|
142
146
|
/** Layout orientation of the input group */
|
|
@@ -165,7 +169,7 @@ export interface InputGroupProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
165
169
|
* </InputGroup>
|
|
166
170
|
* ```
|
|
167
171
|
*/
|
|
168
|
-
export const InputGroup = React.forwardRef<
|
|
172
|
+
export const InputGroup = React.forwardRef<HTMLFieldSetElement, InputGroupProps>(
|
|
169
173
|
({ className, children, orientation = 'vertical', spacing = 'md', ...props }, ref) => {
|
|
170
174
|
const spacingClasses = {
|
|
171
175
|
sm: orientation === 'horizontal' ? 'space-x-2' : 'space-y-2',
|
|
@@ -174,7 +178,7 @@ export const InputGroup = React.forwardRef<HTMLDivElement, InputGroupProps>(
|
|
|
174
178
|
};
|
|
175
179
|
|
|
176
180
|
return (
|
|
177
|
-
<
|
|
181
|
+
<fieldset
|
|
178
182
|
ref={ref}
|
|
179
183
|
className={cn(
|
|
180
184
|
'flex',
|
|
@@ -185,7 +189,7 @@ export const InputGroup = React.forwardRef<HTMLDivElement, InputGroupProps>(
|
|
|
185
189
|
{...props}
|
|
186
190
|
>
|
|
187
191
|
{children}
|
|
188
|
-
</
|
|
192
|
+
</fieldset>
|
|
189
193
|
);
|
|
190
194
|
}
|
|
191
195
|
);
|
|
@@ -382,10 +382,10 @@ describe('LoadingSpinner Component', () => {
|
|
|
382
382
|
|
|
383
383
|
it('works within a card or container', () => {
|
|
384
384
|
renderWithProviders(
|
|
385
|
-
<
|
|
385
|
+
<section className="card">
|
|
386
386
|
<h2>Loading Content</h2>
|
|
387
387
|
<LoadingSpinner size="lg" />
|
|
388
|
-
</
|
|
388
|
+
</section>
|
|
389
389
|
);
|
|
390
390
|
|
|
391
391
|
const spinner = screen.getByRole('status');
|
|
@@ -397,11 +397,11 @@ describe('LoadingSpinner Component', () => {
|
|
|
397
397
|
|
|
398
398
|
it('works with multiple instances', () => {
|
|
399
399
|
renderWithProviders(
|
|
400
|
-
|
|
400
|
+
<>
|
|
401
401
|
<LoadingSpinner size="sm" />
|
|
402
402
|
<LoadingSpinner size="md" />
|
|
403
403
|
<LoadingSpinner size="lg" />
|
|
404
|
-
|
|
404
|
+
</>
|
|
405
405
|
);
|
|
406
406
|
|
|
407
407
|
const spinners = screen.getAllByRole('status');
|
|
@@ -106,6 +106,10 @@ import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle }
|
|
|
106
106
|
import { Alert, AlertDescription } from '../Alert/Alert';
|
|
107
107
|
import { cn } from '../../utils/core/cn';
|
|
108
108
|
|
|
109
|
+
/**
|
|
110
|
+
* Props for the LoginForm component.
|
|
111
|
+
* Configures login form behavior, validation, and callbacks.
|
|
112
|
+
*/
|
|
109
113
|
export interface LoginFormProps {
|
|
110
114
|
/** Callback invoked when the form is submitted */
|
|
111
115
|
onSignIn: (data: { email: string; password: string }) => Promise<void>;
|