@jmruthers/pace-core 0.5.68 → 0.5.69
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/dist/{DataTable-4IUY7BXB.js → DataTable-MPBSXUC6.js} +5 -6
- package/dist/{PublicLoadingSpinner-DdKXTkCZ.d.ts → PublicLoadingSpinner-BOdyU3u-.d.ts} +1 -1
- package/dist/{chunk-PXWEDX7Y.js → chunk-2ARQW6VX.js} +3 -3
- package/dist/{chunk-MOJXHWDE.js → chunk-6JILXFEA.js} +335 -5
- package/dist/chunk-6JILXFEA.js.map +1 -0
- package/dist/{chunk-D7ARGIA3.js → chunk-6RBH67W7.js} +23 -6
- package/dist/chunk-6RBH67W7.js.map +1 -0
- package/dist/{chunk-ZMS23NS5.js → chunk-FJTAWPAQ.js} +3 -5
- package/dist/{chunk-ZMS23NS5.js.map → chunk-FJTAWPAQ.js.map} +1 -1
- package/dist/{chunk-OPCWH3A4.js → chunk-NO5QHMDX.js} +7 -6
- package/dist/chunk-NO5QHMDX.js.map +1 -0
- package/dist/{chunk-ZPK5656W.js → chunk-O3NWNXDY.js} +4 -5
- package/dist/chunk-O3NWNXDY.js.map +1 -0
- package/dist/{chunk-UYA6U6H7.js → chunk-Q2UP3ZWQ.js} +4 -4
- package/dist/{chunk-KRCRNXPD.js → chunk-RVYGJPOD.js} +79 -18
- package/dist/chunk-RVYGJPOD.js.map +1 -0
- package/dist/{chunk-NN45OBIS.js → chunk-UCMHBF7Y.js} +3 -5
- package/dist/{chunk-NN45OBIS.js.map → chunk-UCMHBF7Y.js.map} +1 -1
- package/dist/{chunk-ZPG4XPV5.js → chunk-V3QO3LL7.js} +5 -7
- package/dist/chunk-V3QO3LL7.js.map +1 -0
- package/dist/{chunk-U6GPOF6J.js → chunk-ZXJGZLLO.js} +17 -17
- package/dist/{chunk-U6GPOF6J.js.map → chunk-ZXJGZLLO.js.map} +1 -1
- package/dist/components.d.ts +1 -1
- package/dist/components.js +8 -9
- package/dist/components.js.map +1 -1
- package/dist/hooks.d.ts +1 -1
- package/dist/hooks.js +9 -6
- package/dist/hooks.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +16 -16
- package/dist/index.js.map +1 -1
- package/dist/providers.js +5 -7
- package/dist/rbac/index.js +5 -6
- package/dist/{usePublicRouteParams-CdoFxnJK.d.ts → usePublicRouteParams-Ua1Vz-HG.d.ts} +35 -1
- package/dist/utils.d.ts +4 -1
- package/dist/utils.js +3 -3
- package/docs/DOCUMENTATION_CHECKLIST.md +281 -0
- package/docs/README.md +22 -10
- 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/MissingUserContextError.md +1 -1
- package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
- package/docs/api/classes/PermissionDeniedError.md +1 -1
- package/docs/api/classes/PublicErrorBoundary.md +1 -1
- 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 +1 -1
- package/docs/api/classes/RBACNotInitializedError.md +1 -1
- package/docs/api/classes/SecureSupabaseClient.md +1 -1
- package/docs/api/classes/StorageUtils.md +1 -1
- package/docs/api/interfaces/AggregateConfig.md +1 -1
- package/docs/api/interfaces/ButtonProps.md +1 -1
- package/docs/api/interfaces/CardProps.md +1 -1
- package/docs/api/interfaces/ColorPalette.md +1 -1
- package/docs/api/interfaces/ColorShade.md +1 -1
- package/docs/api/interfaces/DataAccessRecord.md +1 -1
- package/docs/api/interfaces/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/EmptyStateConfig.md +1 -1
- package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
- package/docs/api/interfaces/EventContextType.md +1 -1
- package/docs/api/interfaces/EventLogoProps.md +1 -1
- package/docs/api/interfaces/EventProviderProps.md +1 -1
- package/docs/api/interfaces/FileSizeLimits.md +1 -1
- package/docs/api/interfaces/FileUploadProps.md +1 -1
- package/docs/api/interfaces/FooterProps.md +1 -1
- package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
- package/docs/api/interfaces/InputProps.md +1 -1
- package/docs/api/interfaces/LabelProps.md +1 -1
- package/docs/api/interfaces/LoginFormProps.md +1 -1
- package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
- 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 +1 -1
- package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
- package/docs/api/interfaces/PaletteData.md +1 -1
- package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
- package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
- package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
- package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
- package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
- package/docs/api/interfaces/PublicPageHeaderProps.md +2 -2
- package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
- package/docs/api/interfaces/RBACConfig.md +1 -1
- package/docs/api/interfaces/RBACContextType.md +1 -1
- package/docs/api/interfaces/RBACLogger.md +1 -1
- package/docs/api/interfaces/RBACProviderProps.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
- package/docs/api/interfaces/RouteAccessRecord.md +1 -1
- package/docs/api/interfaces/RouteConfig.md +1 -1
- package/docs/api/interfaces/SecureDataContextType.md +1 -1
- package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
- package/docs/api/interfaces/StorageConfig.md +1 -1
- package/docs/api/interfaces/StorageFileInfo.md +1 -1
- package/docs/api/interfaces/StorageFileMetadata.md +1 -1
- package/docs/api/interfaces/StorageListOptions.md +1 -1
- package/docs/api/interfaces/StorageListResult.md +1 -1
- package/docs/api/interfaces/StorageUploadOptions.md +1 -1
- package/docs/api/interfaces/StorageUploadResult.md +1 -1
- package/docs/api/interfaces/StorageUrlOptions.md +1 -1
- package/docs/api/interfaces/StyleImport.md +1 -1
- package/docs/api/interfaces/SwitchProps.md +1 -1
- package/docs/api/interfaces/ToastActionElement.md +1 -1
- package/docs/api/interfaces/ToastProps.md +1 -1
- package/docs/api/interfaces/UnifiedAuthContextType.md +1 -1
- package/docs/api/interfaces/UnifiedAuthProviderProps.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 +1 -1
- package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
- package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
- package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
- package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
- package/docs/api/interfaces/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 +39 -14
- package/docs/architecture/services.md +374 -0
- package/docs/best-practices/README.md +1 -1
- package/docs/best-practices/testing.md +1 -1
- package/docs/breaking-changes.md +182 -0
- package/docs/common-patterns.md +445 -0
- package/docs/core-concepts/authentication.md +26 -11
- package/docs/core-concepts/events.md +2 -0
- package/docs/core-concepts/organisations.md +2 -0
- package/docs/core-concepts/permissions.md +2 -0
- package/docs/{INDEX.md → documentation-index.md} +26 -38
- package/docs/faq.md +286 -0
- package/docs/{FILE_REFERENCE_SYSTEM.md → file-reference-system.md} +1 -1
- package/docs/getting-started/installation-guide.md +284 -0
- package/docs/getting-started/quick-start.md +8 -1
- package/docs/implementation-guides/app-layout.md +3 -1
- package/docs/implementation-guides/data-tables.md +2 -0
- package/docs/implementation-guides/dynamic-colors.md +47 -2
- package/docs/implementation-guides/event-theming-summary.md +220 -0
- package/docs/implementation-guides/forms.md +9 -7
- package/docs/implementation-guides/navigation.md +2 -0
- package/docs/migration/service-architecture.md +351 -0
- package/docs/rbac/README-rbac-rls-integration.md +2 -2
- package/docs/rbac/README.md +1 -1
- package/docs/rbac/examples/rbac-rls-integration-example.md +3 -3
- package/docs/rbac/quick-start.md +2 -0
- package/docs/rbac/rbac-rls-integration.md +2 -2
- package/docs/style-guide.md +136 -1
- package/docs/testing/README.md +1 -1
- package/docs/troubleshooting/authentication-issues.md +334 -0
- package/docs/troubleshooting/common-issues.md +2 -0
- package/docs/troubleshooting/styling-issues.md +199 -144
- package/docs/usage.md +23 -2
- package/package.json +1 -1
- package/src/__tests__/{TESTING_GUIDELINES.md → TEST_GUIDE_CURSOR.md} +20 -0
- package/src/__tests__/TEST_GUIDE_HUMAN.md +103 -0
- package/src/__tests__/fixtures/test-data.ts +90 -0
- package/src/__tests__/helpers/__tests__/component-test-utils.test.tsx +260 -0
- package/src/__tests__/helpers/__tests__/optimized-test-setup.test.ts +224 -0
- package/src/__tests__/helpers/__tests__/supabaseMock.test.ts +273 -0
- package/src/__tests__/helpers/__tests__/test-providers.test.tsx +98 -0
- package/src/__tests__/helpers/__tests__/test-utils.test.tsx +436 -0
- package/src/__tests__/helpers/__tests__/timer-utils.test.ts +371 -0
- package/src/__tests__/helpers/component-test-utils.tsx +14 -4
- package/src/__tests__/helpers/optimized-test-setup.ts +68 -0
- package/src/__tests__/helpers/test-providers.tsx +329 -0
- package/src/__tests__/helpers/test-utils.tsx +91 -45
- package/src/__tests__/helpers/timer-utils.ts +71 -0
- package/src/__tests__/hooks/usePermissions.test.ts +1 -5
- package/src/__tests__/integration/UserProfile.test.tsx +1 -5
- package/src/__tests__/rbac/PagePermissionGuard.test.tsx +42 -12
- package/src/__tests__/setup.ts +34 -28
- package/src/components/Alert/Alert.test.tsx +1 -5
- package/src/components/Avatar/Avatar.test.tsx +1 -5
- package/src/components/Button/Button.test.tsx +4 -20
- package/src/components/Card/Card.test.tsx +1 -5
- package/src/components/Checkbox/Checkbox.test.tsx +1 -5
- package/src/components/DataTable/__tests__/DataTable.comprehensive.test.tsx +1 -5
- package/src/components/DataTable/__tests__/DataTable.test.tsx +45 -49
- package/src/components/DataTable/__tests__/DataTableCore.test.tsx +1 -5
- package/src/components/DataTable/__tests__/styles.test.ts +382 -0
- package/src/components/DataTable/context/__tests__/DataTableContext.test.tsx +409 -0
- package/src/components/DataTable/core/__tests__/ActionManager.test.ts +634 -0
- package/src/components/DataTable/core/__tests__/DataManager.test.ts +519 -0
- package/src/components/DataTable/core/__tests__/StateManager.test.ts +714 -0
- package/src/components/DataTable/hooks/__tests__/useDataTableState.test.ts +592 -0
- package/src/components/DataTable/utils/__tests__/exportUtils.test.ts +354 -0
- package/src/components/DataTable/utils/__tests__/hierarchicalUtils.test.ts +539 -0
- package/src/components/Dialog/examples/__tests__/SmartDialogExample.unit.test.tsx +1 -5
- package/src/components/Dialog/utils/__tests__/safeHtml.unit.test.ts +1 -8
- package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +34 -38
- package/src/components/Footer/Footer.test.tsx +1 -5
- package/src/components/Form/Form.test.tsx +22 -35
- package/src/components/Header/Header.test.tsx +1 -9
- package/src/components/InactivityWarningModal/InactivityWarningModal.test.tsx +1 -5
- package/src/components/Input/Input.test.tsx +2 -10
- package/src/components/LoginForm/LoginForm.test.tsx +1 -5
- package/src/components/NavigationMenu/NavigationMenu.test.tsx +24 -24
- package/src/components/PaceAppLayout/__tests__/PaceAppLayout.accessibility.test.tsx +1 -6
- package/src/components/PaceAppLayout/__tests__/PaceAppLayout.integration.test.tsx +6 -16
- package/src/components/PaceAppLayout/__tests__/PaceAppLayout.performance.test.tsx +1 -5
- package/src/components/PaceAppLayout/__tests__/PaceAppLayout.rbac.test.tsx +1 -5
- package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +1 -7
- package/src/components/PasswordReset/PasswordChangeForm.test.tsx +1 -9
- package/src/components/PasswordReset/PasswordResetForm.test.tsx +1 -9
- package/src/components/PublicLayout/PublicErrorBoundary.tsx +4 -5
- package/src/components/PublicLayout/PublicPageHeader.tsx +13 -9
- package/src/components/PublicLayout/__tests__/EventLogo.test.tsx +666 -0
- package/src/components/PublicLayout/__tests__/PublicErrorBoundary.test.tsx +457 -0
- package/src/components/PublicLayout/__tests__/PublicLoadingSpinner.test.tsx +393 -0
- package/src/components/PublicLayout/__tests__/PublicPageFooter.test.tsx +351 -0
- package/src/components/PublicLayout/__tests__/PublicPageHeader.test.tsx +374 -0
- package/src/components/PublicLayout/__tests__/PublicPageLayout.test.tsx +388 -0
- package/src/components/Select/Select.bug-test.tsx +69 -0
- package/src/components/Select/Select.refactored.tsx +497 -0
- package/src/components/Select/Select.test.tsx +42 -49
- package/src/components/Select/Select.tsx +5 -2
- package/src/components/Select/hooks.ts +254 -0
- package/src/components/Switch/Switch.test.tsx +1 -5
- package/src/components/Table/__tests__/Table.test.tsx +775 -0
- package/src/components/Toast/Toast.test.tsx +15 -8
- package/src/components/Tooltip/Tooltip.test.tsx +1 -5
- package/src/components/UserMenu/UserMenu.test.tsx +3 -15
- package/src/components/__tests__/FileDisplay.test.tsx +575 -0
- package/src/components/__tests__/FileUpload.test.tsx +446 -0
- package/src/components/__tests__/SuperAdminGuard.test.tsx +422 -354
- package/src/hooks/__tests__/ServiceHooks.test.tsx +613 -0
- package/src/hooks/__tests__/hooks.integration.test.tsx +1 -10
- package/src/hooks/__tests__/useApiFetch.unit.test.ts +10 -14
- package/src/hooks/__tests__/useAppConfig.unit.test.ts +307 -0
- package/src/hooks/__tests__/useComponentPerformance.unit.test.tsx +1 -6
- package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +1 -5
- package/src/hooks/__tests__/useOrganisationPermissions.unit.test.tsx +6 -9
- package/src/hooks/__tests__/usePublicEvent.simple.test.ts +321 -0
- package/src/hooks/__tests__/usePublicEvent.unit.test.ts +583 -0
- package/src/hooks/__tests__/usePublicEventLogo.unit.test.ts +640 -0
- package/src/hooks/__tests__/usePublicRouteParams.unit.test.ts +435 -0
- package/src/hooks/__tests__/useRBAC.unit.test.ts +10 -10
- package/src/hooks/__tests__/useStorage.unit.test.ts +751 -0
- package/src/hooks/index.ts +3 -0
- package/src/hooks/public/usePublicEvent.ts +30 -9
- package/src/hooks/public/usePublicRouteParams.ts +13 -3
- package/src/hooks/services/useAuth.ts +50 -0
- package/src/hooks/services/useAuthService.ts +30 -0
- package/src/hooks/services/useCurrentEvent.ts +36 -0
- package/src/hooks/services/useCurrentOrganisation.ts +52 -0
- package/src/hooks/services/useEventService.ts +30 -0
- package/src/hooks/services/useInactivityService.ts +30 -0
- package/src/hooks/services/useOrganisationService.ts +30 -0
- package/src/hooks/services/usePermissions.ts +70 -0
- package/src/hooks/services/useRBACService.ts +30 -0
- package/src/hooks/useCounter.test.ts +1 -5
- package/src/hooks/useEventTheme.ts +86 -0
- package/src/hooks/useOrganisationPermissions.test.ts +2 -5
- package/src/hooks/useOrganisationSecurity.test.ts +1 -5
- package/src/hooks/usePermissionCache.test.ts +1 -5
- package/src/hooks/usePermissionCheck.ts +150 -0
- package/src/hooks/useSecureDataAccess.test.ts +1 -5
- package/src/index.ts +1 -0
- package/src/providers/OrganisationProvider.test.tsx +1 -5
- package/src/providers/OrganisationProvider.tsx +56 -4
- package/src/providers/UnifiedAuthProvider.test.tsx +1 -5
- package/src/providers/__tests__/AuthProvider.test.tsx +105 -439
- package/src/providers/__tests__/AuthProvider.test.tsx.backup +771 -0
- package/src/providers/__tests__/EventProvider.test.tsx +211 -110
- package/src/providers/__tests__/EventProvider.test.tsx.backup +824 -0
- package/src/providers/__tests__/InactivityProvider.test.tsx +1 -5
- package/src/providers/__tests__/OrganisationProvider.test.tsx +97 -261
- package/src/providers/__tests__/OrganisationProvider.test.tsx.backup +820 -0
- package/src/providers/__tests__/ServiceProviders.test.tsx +477 -0
- package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +72 -504
- package/src/providers/__tests__/UnifiedAuthProvider.test.tsx.backup +911 -0
- package/src/providers/__tests__/UnifiedAuthProvider.test.tsx.backup2 +166 -0
- package/src/providers/services/AuthServiceProvider.tsx +65 -0
- package/src/providers/services/EventServiceProvider.tsx +83 -0
- package/src/providers/services/InactivityServiceProvider.tsx +83 -0
- package/src/providers/services/OrganisationServiceProvider.tsx +77 -0
- package/src/providers/services/RBACServiceProvider.tsx +79 -0
- package/src/providers/services/UnifiedAuthProvider.tsx +368 -0
- package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +210 -0
- package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +269 -0
- package/src/rbac/__tests__/adapters.comprehensive.test.tsx +892 -0
- package/src/rbac/__tests__/engine.comprehensive.test.ts +954 -0
- package/src/rbac/__tests__/integration.authflow.test.tsx +1 -5
- package/src/rbac/__tests__/integration.navigation.test.tsx +1 -4
- package/src/rbac/__tests__/rbac-core.test.tsx +2 -7
- package/src/rbac/__tests__/rbac-functions.test.ts +1 -9
- package/src/rbac/__tests__/rbac-integration.test.ts +1 -9
- package/src/rbac/api.test.ts +1 -9
- package/src/rbac/cache.test.ts +10 -8
- package/src/rbac/cli/__tests__/policy-manager.test.ts +339 -0
- package/src/rbac/components/EnhancedNavigationMenu.test.tsx +1 -5
- package/src/rbac/components/NavigationProvider.test.tsx +1 -5
- package/src/rbac/components/PagePermissionProvider.test.tsx +1 -5
- package/src/rbac/components/SecureDataProvider.test.tsx +1 -5
- package/src/rbac/components/__tests__/NavigationGuard.test.tsx +25 -29
- package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +27 -30
- package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +23 -27
- package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +18 -22
- package/src/rbac/config.test.ts +1 -5
- package/src/rbac/hooks/useCan.test.ts +262 -9
- package/src/rbac/hooks/usePermissions.test.ts +246 -6
- package/src/rbac/hooks/useRBAC.simple.test.ts +1 -5
- package/src/rbac/hooks/useRBAC.test.ts +472 -198
- package/src/rbac/providers/__tests__/RBACProvider.test.tsx +1 -9
- package/src/services/AuthService.ts +416 -0
- package/src/services/EventService.ts +366 -0
- package/src/services/InactivityService.ts +388 -0
- package/src/services/OrganisationService.ts +592 -0
- package/src/services/RBACService.ts +522 -0
- package/src/services/__tests__/AuthService.test.ts +356 -0
- package/src/services/__tests__/BaseService.test.ts +314 -0
- package/src/services/__tests__/EventService.test.ts +489 -0
- package/src/services/__tests__/InactivityService.test.ts +403 -0
- package/src/services/__tests__/OrganisationService.test.ts +660 -0
- package/src/services/__tests__/RBACService.test.ts +492 -0
- package/src/services/base/BaseService.ts +87 -0
- package/src/services/interfaces/IAuthService.ts +39 -0
- package/src/services/interfaces/IEventService.ts +30 -0
- package/src/services/interfaces/IInactivityService.ts +31 -0
- package/src/services/interfaces/IOrganisationService.ts +41 -0
- package/src/services/interfaces/IRBACService.ts +62 -0
- package/src/theming/__tests__/runtime.test.ts +540 -0
- package/src/types/__tests__/file-reference.test.ts +447 -0
- package/src/types/__tests__/organisation.test.ts +1133 -0
- package/src/types/__tests__/theme.test.ts +830 -0
- package/src/types/__tests__/type-validation.test.ts +527 -0
- package/src/utils/__tests__/bundleAnalysis.unit.test.ts +1 -5
- package/src/utils/__tests__/debugLogger.test.ts +417 -0
- package/src/utils/__tests__/deviceFingerprint.unit.test.ts +1 -6
- package/src/utils/__tests__/dynamicUtils.unit.test.ts +1 -5
- package/src/utils/__tests__/lazyLoad.unit.test.tsx +35 -35
- package/src/utils/__tests__/organisationContext.unit.test.ts +1 -5
- package/src/utils/__tests__/performanceBudgets.unit.test.ts +5 -11
- package/src/utils/__tests__/secureErrors.unit.test.ts +1 -6
- package/src/utils/__tests__/secureStorage.unit.test.ts +1 -5
- package/src/utils/__tests__/securityMonitor.unit.test.ts +1 -5
- package/src/utils/__tests__/sessionTracking.unit.test.ts +1 -5
- package/src/utils/appIdResolver.test.ts +6 -10
- package/src/utils/appNameResolver.simple.test.ts +142 -0
- package/src/utils/appNameResolver.test.ts +31 -458
- package/src/utils/appNameResolver.test.ts.backup +494 -0
- package/src/utils/debugLogger.ts +26 -5
- package/src/utils/formatDate.test.ts +1 -5
- package/src/utils/organisationContext.test.ts +1 -5
- package/src/utils/performanceBudgets.ts +3 -4
- package/src/utils/secureDataAccess.test.ts +1 -5
- package/src/utils/storage/__tests__/helpers.unit.test.ts +1 -5
- package/src/validation/__tests__/sqlInjectionProtection.unit.test.ts +1 -5
- package/dist/chunk-D7ARGIA3.js.map +0 -1
- package/dist/chunk-IPCH4YPT.js +0 -315
- package/dist/chunk-IPCH4YPT.js.map +0 -1
- package/dist/chunk-KRCRNXPD.js.map +0 -1
- package/dist/chunk-MOJXHWDE.js.map +0 -1
- package/dist/chunk-OPCWH3A4.js.map +0 -1
- package/dist/chunk-ZPG4XPV5.js.map +0 -1
- package/dist/chunk-ZPK5656W.js.map +0 -1
- package/docs/getting-started/installation.md +0 -269
- package/src/__tests__/REBUILD_PLAN.md +0 -223
- /package/dist/{DataTable-4IUY7BXB.js.map → DataTable-MPBSXUC6.js.map} +0 -0
- /package/dist/{chunk-PXWEDX7Y.js.map → chunk-2ARQW6VX.js.map} +0 -0
- /package/dist/{chunk-UYA6U6H7.js.map → chunk-Q2UP3ZWQ.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/hooks/useToast.ts","../src/components/PublicLayout/PublicErrorBoundary.tsx","../src/components/PublicLayout/PublicPageProvider.tsx","../src/hooks/useAppConfig.ts","../src/hooks/public/usePublicEventLogo.ts"],"sourcesContent":["\n/**\n * @file Toast hook for managing toast notifications\n * @package @jmruthers/pace-core\n * @module Hooks\n * @since 0.1.0\n */\n\nimport * as React from \"react\"\n\n/** Maximum number of toasts to show at once */\nconst TOAST_LIMIT = 5\n/** Delay before removing a dismissed toast */\nconst TOAST_REMOVE_DELAY = 1000\n\nexport interface ToastProps {\n title?: React.ReactNode;\n description?: React.ReactNode;\n variant?: 'default' | 'destructive' | 'success';\n duration?: number;\n onClose?: () => void;\n action?: React.ReactElement;\n}\n\n/**\n * Extended toast props with additional properties\n * @interface ToasterToast\n */\ntype ToasterToast = ToastProps & {\n /** Unique identifier for the toast */\n id: string\n /** Optional title content */\n title?: React.ReactNode\n /** Optional description content */\n description?: React.ReactNode\n /** Optional action button */\n action?: React.ReactElement\n /** Open state */\n open?: boolean\n /** Open change handler */\n onOpenChange?: (open: boolean) => void\n /** Dismiss function */\n dismiss?: () => void\n}\n\n/**\n * State interface for toast management\n */\ninterface State {\n /** Array of active toasts */\n toasts: ToasterToast[]\n}\n\n/** Map of toast IDs to their removal timeouts */\nconst toastTimeouts = new Map<string, ReturnType<typeof setTimeout>>()\n\n/** Current toast state */\nlet memoryState: State = {\n toasts: [],\n}\n\n/** List of state change listeners */\nconst listeners: Array<(state: State) => void> = []\n\n/**\n * Reset the toast state and clear all timeouts\n */\nexport function reset() {\n memoryState = { toasts: [] }\n toastTimeouts.forEach((timeout) => clearTimeout(timeout))\n toastTimeouts.clear()\n}\n\n/**\n * Dispatch a state change\n * @param action - Action to dispatch\n */\nfunction dispatch(action: {\n type: \"ADD_TOAST\" | \"UPDATE_TOAST\" | \"DISMISS_TOAST\" | \"REMOVE_TOAST\"\n toast?: ToasterToast\n toastId?: string\n}) {\n memoryState = reducer(memoryState, action)\n listeners.forEach((listener) => {\n listener(memoryState)\n })\n}\n\n/**\n * Generate a unique ID for a toast\n * @returns Unique ID string\n */\nfunction genId() {\n return Math.random().toString(36).substring(2, 9)\n}\n\n/**\n * Add a toast to the removal queue\n * @param toastId - ID of the toast to remove\n */\nconst addToRemoveQueue = (toastId: string) => {\n if (toastTimeouts.has(toastId)) {\n return\n }\n\n const timeout = setTimeout(() => {\n toastTimeouts.delete(toastId)\n dispatch({\n type: \"REMOVE_TOAST\",\n toastId: toastId,\n })\n }, TOAST_REMOVE_DELAY)\n\n toastTimeouts.set(toastId, timeout)\n}\n\n/**\n * State reducer for toast management\n * @param state - Current state\n * @param action - Action to process\n * @returns New state\n */\nfunction reducer(state: State, action: {\n type: \"ADD_TOAST\" | \"UPDATE_TOAST\" | \"DISMISS_TOAST\" | \"REMOVE_TOAST\"\n toast?: ToasterToast\n toastId?: string\n}): State {\n switch (action.type) {\n case \"ADD_TOAST\":\n return {\n ...state,\n toasts: [action.toast!, ...state.toasts].slice(0, TOAST_LIMIT),\n }\n\n case \"UPDATE_TOAST\":\n return {\n ...state,\n toasts: state.toasts.map((t) =>\n t.id === action.toast?.id ? { ...t, ...action.toast } : t\n ),\n }\n\n case \"DISMISS_TOAST\": {\n const { toastId } = action\n\n if (toastId) {\n addToRemoveQueue(toastId)\n }\n\n return {\n ...state,\n toasts: state.toasts.map((t) =>\n t.id === toastId || toastId === undefined\n ? {\n ...t,\n open: false,\n }\n : t\n ),\n }\n }\n\n case \"REMOVE_TOAST\":\n if (action.toastId === undefined) {\n return {\n ...state,\n toasts: [],\n }\n }\n return {\n ...state,\n toasts: state.toasts.filter((t) => t.id !== action.toastId),\n }\n }\n}\n\n/**\n * Toast configuration without ID\n */\ntype Toast = Omit<ToasterToast, \"id\">\n\n/**\n * Creates a new toast notification\n * @param props - Toast configuration\n * @returns Object with toast ID and control methods\n */\nfunction toast({ ...props }: Toast) {\n const id = genId()\n\n const update = (props: Partial<Omit<ToasterToast, \"id\">>) =>\n dispatch({\n type: \"UPDATE_TOAST\",\n toast: { ...props, id },\n })\n const dismiss = () => dispatch({ type: \"DISMISS_TOAST\", toastId: id })\n\n dispatch({\n type: \"ADD_TOAST\",\n toast: {\n ...props,\n id,\n open: true,\n dismiss,\n onOpenChange: (open) => {\n if (!open) dismiss()\n },\n },\n })\n\n return {\n id: id,\n dismiss,\n update,\n }\n}\n\n/**\n * Hook for managing toast notifications\n * @returns Object with toast state and control methods\n */\nfunction useToast() {\n const [state, setState] = React.useState<State>(memoryState)\n\n React.useEffect(() => {\n listeners.push(setState)\n return () => {\n const index = listeners.indexOf(setState)\n if (index > -1) {\n listeners.splice(index, 1)\n }\n }\n }, [state])\n\n return {\n ...state,\n toast,\n dismiss: (toastId?: string) => dispatch({ type: \"DISMISS_TOAST\", toastId }),\n }\n}\n\nexport { useToast, toast }\nexport type { ToasterToast }\n","/**\n * @file Public Error Boundary Component\n * @package @jmruthers/pace-core\n * @module Components/PublicLayout\n * @since 1.0.0\n *\n * An error boundary component specifically designed for public pages.\n * Provides graceful error handling and recovery for public content.\n *\n * Features:\n * - Graceful error handling\n * - User-friendly error messages\n * - Recovery mechanisms\n * - Accessibility compliant\n * - TypeScript support\n *\n * @example\n * ```tsx\n * import { PublicErrorBoundary } from '@jmruthers/pace-core';\n *\n * function PublicEventPage() {\n * return (\n * <PublicErrorBoundary>\n * <PublicPageContent />\n * </PublicErrorBoundary>\n * );\n * }\n * ```\n *\n * @accessibility\n * - WCAG 2.1 AA compliant\n * - Screen reader friendly error messages\n * - Keyboard accessible recovery actions\n * - High contrast support\n *\n * @dependencies\n * - React 18+ - Component framework\n * - Error boundary patterns\n * - Tailwind CSS - Styling\n */\n\nimport React, { Component, ErrorInfo, ReactNode } from 'react';\n\nexport interface PublicErrorBoundaryProps {\n /** Child components to wrap */\n children: ReactNode;\n /** Custom error fallback component */\n fallback?: React.ComponentType<PublicErrorBoundaryState>;\n /** Custom CSS classes for error display */\n className?: string;\n /** Whether to show error details in development */\n showErrorDetails?: boolean;\n /** Custom error message */\n customErrorMessage?: string;\n /** Custom recovery action */\n onRecover?: () => void;\n}\n\nexport interface PublicErrorBoundaryState {\n /** Whether an error has occurred */\n hasError: boolean;\n /** The error that occurred */\n error: Error | null;\n /** Error information */\n errorInfo: ErrorInfo | null;\n /** Function to reset the error state */\n resetError: () => void;\n}\n\n/**\n * Error boundary component for public pages\n * \n * This component catches JavaScript errors anywhere in the child component tree,\n * logs those errors, and displays a fallback UI instead of the component tree that crashed.\n * \n * @param props - Error boundary configuration\n * @returns React element with error boundary wrapper\n */\nexport class PublicErrorBoundary extends Component<PublicErrorBoundaryProps, PublicErrorBoundaryState> {\n constructor(props: PublicErrorBoundaryProps) {\n super(props);\n this.state = {\n hasError: false,\n error: null,\n errorInfo: null,\n resetError: this.resetError.bind(this)\n };\n }\n\n static getDerivedStateFromError(error: Error): Partial<PublicErrorBoundaryState> {\n // Update state so the next render will show the fallback UI\n return {\n hasError: true,\n error\n };\n }\n\n componentDidCatch(error: Error, errorInfo: ErrorInfo) {\n // Log the error to console in development\n if (import.meta.env.MODE === 'development') {\n console.error('PublicErrorBoundary caught an error:', error, errorInfo);\n }\n\n // Update state with error info\n this.setState({\n error,\n errorInfo\n });\n\n // You can also log the error to an error reporting service here\n // Example: logErrorToService(error, errorInfo);\n }\n\n resetError = () => {\n this.setState({\n hasError: false,\n error: null,\n errorInfo: null\n });\n };\n\n render() {\n if (this.state.hasError) {\n // Custom fallback component\n if (this.props.fallback) {\n return <this.props.fallback {...this.state} />;\n }\n\n // Default error UI\n return (\n <div className={`min-h-screen bg-white flex items-center justify-center ${this.props.className || ''}`}>\n <div className=\"max-w-md mx-auto text-center px-4\">\n <div className=\"mb-6\">\n <div className=\"mx-auto flex items-center justify-center h-12 w-12 rounded-full bg-red-100 mb-4\">\n <svg\n className=\"h-6 w-6 text-red-600\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z\"\n />\n </svg>\n </div>\n <h1 className=\"text-2xl font-bold text-gray-900 mb-2\">\n Something went wrong\n </h1>\n <p className=\"text-gray-600 mb-6\">\n {this.props.customErrorMessage || \n 'We encountered an error while loading this page. Please try again.'}\n </p>\n </div>\n\n {/* Error details in development */}\n {this.props.showErrorDetails && this.state.error && (\n <div className=\"mb-6 p-4 bg-red-50 border border-red-200 rounded-md text-left\">\n <h3 className=\"text-sm font-medium text-red-800 mb-2\">\n Error Details (Development Only)\n </h3>\n <pre className=\"text-xs text-red-700 whitespace-pre-wrap\">\n {this.state.error.toString()}\n {this.state.errorInfo?.componentStack}\n </pre>\n </div>\n )}\n\n {/* Recovery actions */}\n <div className=\"space-y-3\">\n <button\n onClick={this.resetError}\n className=\"w-full px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2\"\n >\n Try Again\n </button>\n \n <button\n onClick={() => window.location.reload()}\n className=\"w-full px-4 py-2 bg-gray-600 text-white rounded-md hover:bg-gray-700 transition-colors focus:outline-none focus:ring-2 focus:ring-gray-500 focus:ring-offset-2\"\n >\n Reload Page\n </button>\n\n {this.props.onRecover && (\n <button\n onClick={this.props.onRecover}\n className=\"w-full px-4 py-2 bg-green-600 text-white rounded-md hover:bg-green-700 transition-colors focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-offset-2\"\n >\n Alternative Action\n </button>\n )}\n </div>\n\n {/* Help text */}\n <div className=\"mt-6 text-sm text-gray-500\">\n <p>\n If this problem persists, please contact support or try accessing the page later.\n </p>\n </div>\n </div>\n </div>\n );\n }\n\n return this.props.children;\n }\n}\n\n/**\n * Hook for accessing error boundary state\n * Useful for components that need to know if they're inside an error boundary\n */\nexport function useErrorBoundary() {\n const [error, setError] = React.useState<Error | null>(null);\n\n const resetError = React.useCallback(() => {\n setError(null);\n }, []);\n\n const captureError = React.useCallback((error: Error) => {\n setError(error);\n }, []);\n\n React.useEffect(() => {\n if (error) {\n throw error;\n }\n }, [error]);\n\n return { captureError, resetError };\n}\n\n/**\n * Default error fallback component\n */\nexport function DefaultPublicErrorFallback({ \n error, \n resetError \n}: PublicErrorBoundaryState) {\n return (\n <div className=\"min-h-screen bg-white flex items-center justify-center\">\n <div className=\"max-w-md mx-auto text-center px-4\">\n <div className=\"mb-6\">\n <div className=\"mx-auto flex items-center justify-center h-12 w-12 rounded-full bg-red-100 mb-4\">\n <svg\n className=\"h-6 w-6 text-red-600\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z\"\n />\n </svg>\n </div>\n <h1 className=\"text-2xl font-bold text-gray-900 mb-2\">\n Page Error\n </h1>\n <p className=\"text-gray-600 mb-6\">\n We encountered an error while loading this page.\n </p>\n </div>\n\n <button\n onClick={resetError}\n className=\"w-full px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2\"\n >\n Try Again\n </button>\n </div>\n </div>\n );\n}\n","/**\n * @file Public Page Provider\n * @package @jmruthers/pace-core\n * @module Components/PublicLayout\n * @since 1.0.0\n *\n * A completely isolated provider for public pages that doesn't trigger\n * any authentication context. This ensures public pages work independently\n * of the main application's authentication system.\n *\n * Features:\n * - No authentication required\n * - No organisation context\n * - No event context\n * - Completely isolated from main app context\n * - Environment variable access for public data\n * - Error boundary integration\n *\n * @example\n * ```tsx\n * import { PublicPageProvider } from '@jmruthers/pace-core';\n * \n * function PublicApp() {\n * return (\n * <PublicPageProvider>\n * <Routes>\n * <Route path=\"/events/:eventCode/recipe-grid-report\" element={<PublicRecipePage />} />\n * </Routes>\n * </PublicPageProvider>\n * );\n * }\n * ```\n */\n\nimport React, { createContext, useContext, ReactNode, useMemo } from 'react';\nimport { createClient } from '@supabase/supabase-js';\nimport type { Database } from '../../types/database';\nimport { PublicErrorBoundary } from './PublicErrorBoundary';\n\ninterface PublicPageContextType {\n isPublicPage: true;\n supabase: ReturnType<typeof createClient<Database>> | null;\n environment: {\n supabaseUrl: string | null;\n supabaseKey: string | null;\n };\n}\n\nconst PublicPageContext = createContext<PublicPageContextType | undefined>(undefined);\n\nexport interface PublicPageProviderProps {\n children: ReactNode;\n}\n\n/**\n * Provider for public pages that completely isolates them from authentication context\n * \n * This provider:\n * - Does not initialize any authentication providers\n * - Provides environment variables for public data access\n * - Includes error boundary for graceful error handling\n * - Is completely separate from the main app context\n */\nexport function PublicPageProvider({ children }: PublicPageProviderProps) {\n // Get environment variables for public data access\n // Handle both Vite (import.meta.env) and Node.js (process.env) environments\n const getEnvVar = (key: string): string | undefined => {\n // Check Vite environment first (browser)\n if (typeof import.meta !== 'undefined' && (import.meta as any).env) {\n return (import.meta as any).env[key];\n }\n // Check Node.js environment (server-side)\n if (typeof import.meta !== 'undefined' && import.meta.env) {\n return import.meta.env[key];\n }\n return undefined;\n };\n\n const supabaseUrl = getEnvVar('VITE_SUPABASE_URL') || \n getEnvVar('NEXT_PUBLIC_SUPABASE_URL') || \n null;\n \n const supabaseKey = getEnvVar('VITE_SUPABASE_ANON_KEY') || \n getEnvVar('NEXT_PUBLIC_SUPABASE_ANON_KEY') || \n null;\n\n // Create Supabase client if environment variables are available\n const supabase = useMemo(() => {\n if (!supabaseUrl || !supabaseKey) {\n console.warn('[PublicPageProvider] Missing Supabase environment variables. Please ensure VITE_SUPABASE_URL and VITE_SUPABASE_ANON_KEY are set in your environment.');\n return null;\n }\n return createClient<Database>(supabaseUrl, supabaseKey);\n }, [supabaseUrl, supabaseKey]);\n\n const contextValue: PublicPageContextType = {\n isPublicPage: true,\n supabase,\n environment: {\n supabaseUrl,\n supabaseKey\n }\n };\n\n return (\n <PublicPageContext.Provider value={contextValue}>\n <PublicErrorBoundary>\n {children}\n </PublicErrorBoundary>\n </PublicPageContext.Provider>\n );\n}\n\n/**\n * Hook to access public page context\n * \n * @returns Public page context with environment variables\n */\nexport function usePublicPageContext(): PublicPageContextType {\n const context = useContext(PublicPageContext);\n \n if (!context) {\n throw new Error('usePublicPageContext must be used within a PublicPageProvider');\n }\n \n return context;\n}\n\n/**\n * Hook to check if we're in a public page context\n * \n * @returns True if we're in a public page context\n */\nexport function useIsPublicPage(): boolean {\n const context = useContext(PublicPageContext);\n return context !== undefined;\n}\n","/**\n * @file useAppConfig Hook\n * @package @jmruthers/pace-core\n * @module Hooks/useAppConfig\n * @since 0.4.0\n *\n * Hook for accessing app configuration like direct access support and event requirements.\n * This is a convenience hook that extracts app config from the UnifiedAuthProvider.\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const { supportsDirectAccess, requiresEvent, isLoading } = useAppConfig();\n * \n * if (isLoading) return <div>Loading...</div>;\n * \n * return (\n * <div>\n * {supportsDirectAccess && (\n * <div>This app supports direct access!</div>\n * )}\n * {requiresEvent && (\n * <EventSelector />\n * )}\n * </div>\n * );\n * }\n * ```\n */\n\nimport { useMemo } from 'react';\nimport { useUnifiedAuth } from '../providers/UnifiedAuthProvider';\nimport { useIsPublicPage } from '../components/PublicLayout/PublicPageProvider';\n\nexport interface UseAppConfigReturn {\n supportsDirectAccess: boolean;\n requiresEvent: boolean;\n isLoading: boolean;\n appName: string;\n}\n\n/**\n * Hook to access app configuration\n * Works in both authenticated and public contexts\n * @returns App configuration and loading state\n */\nexport function useAppConfig(): UseAppConfigReturn {\n // Check if we're in a public page context first\n const isPublicPage = useIsPublicPage();\n \n if (isPublicPage) {\n // For public pages, try to get app name from environment variables\n const getAppName = (): string => {\n // Check Vite environment first (browser)\n if (typeof import.meta !== 'undefined' && (import.meta as any).env) {\n return (import.meta as any).env.VITE_APP_NAME || \n (import.meta as any).env.NEXT_PUBLIC_APP_NAME || \n 'PACE';\n }\n // Check Node.js environment (server-side)\n if (typeof import.meta !== 'undefined' && import.meta.env) {\n return import.meta.env.VITE_APP_NAME || \n import.meta.env.NEXT_PUBLIC_APP_NAME || \n 'PACE';\n }\n return 'PACE';\n };\n \n return useMemo(() => ({\n supportsDirectAccess: false, // Public pages don't support direct access\n requiresEvent: true, // Public pages always require an event\n isLoading: false,\n appName: getAppName()\n }), []);\n }\n \n // For authenticated pages, use UnifiedAuthProvider\n try {\n const { appConfig, appName } = useUnifiedAuth();\n return useMemo(() => ({\n supportsDirectAccess: !(appConfig?.requires_event ?? true),\n requiresEvent: appConfig?.requires_event ?? true,\n isLoading: appConfig === null,\n appName\n }), [appConfig?.requires_event, appName]);\n } catch (error) {\n // Fallback if UnifiedAuthProvider is not available\n return useMemo(() => ({\n supportsDirectAccess: false,\n requiresEvent: true,\n isLoading: false,\n appName: 'PACE'\n }), []);\n }\n} ","/**\n * @file Public Event Logo Hook\n * @package @jmruthers/pace-core\n * @module Hooks/Public\n * @since 1.0.0\n *\n * A React hook for accessing public event logo URLs without authentication.\n * Provides logo URLs with fallback handling for public pages.\n *\n * Features:\n * - No authentication required\n * - Automatic fallback to event initials\n * - Caching for performance\n * - Error handling and loading states\n * - TypeScript support\n * - Image validation\n *\n * @example\n * ```tsx\n * import { usePublicEventLogo } from '@jmruthers/pace-core';\n *\n * function EventHeader() {\n * const { logoUrl, fallbackText, isLoading, error } = usePublicEventLogo(\n * eventId, \n * eventName, \n * organisationId\n * );\n *\n * if (isLoading) return <div>Loading logo...</div>;\n * if (error) return <div>Error: {error.message}</div>;\n *\n * return (\n * <div>\n * {logoUrl ? (\n * <img src={logoUrl} alt={`${eventName} logo`} />\n * ) : (\n * <div className=\"logo-fallback\">{fallbackText}</div>\n * )}\n * </div>\n * );\n * }\n * ```\n *\n * @accessibility\n * - No direct accessibility concerns (hook)\n * - Enables accessible logo display with proper alt text\n * - Supports screen reader friendly fallbacks\n *\n * @security\n * - Only returns public-safe logo URLs\n * - Validates image existence before returning URL\n * - No sensitive information exposed\n * - Rate limiting applied at storage level\n *\n * @performance\n * - Built-in caching with TTL\n * - Image validation and optimization\n * - Minimal re-renders with stable references\n * - Lazy loading support\n *\n * @dependencies\n * - React 18+ - Hooks and effects\n * - @supabase/supabase-js - Storage integration\n * - Event types - Type definitions\n */\n\nimport { useState, useEffect, useCallback, useMemo } from 'react';\nimport type { SupabaseClient } from '@supabase/supabase-js';\nimport type { Database } from '../../types/database';\n\n// Simple in-memory cache for public data\nconst publicDataCache = new Map<string, { data: any; timestamp: number; ttl: number }>();\n\nexport interface UsePublicEventLogoReturn {\n /** The logo URL if available, null if not found or error */\n logoUrl: string | null;\n /** Fallback text (event initials) if no logo is available */\n fallbackText: string;\n /** Whether the logo is currently loading */\n isLoading: boolean;\n /** Any error that occurred during loading */\n error: Error | null;\n /** Function to manually refetch the logo */\n refetch: () => Promise<void>;\n}\n\nexport interface UsePublicEventLogoOptions {\n /** Cache TTL in milliseconds (default: 30 minutes) */\n cacheTtl?: number;\n /** Whether to enable caching (default: true) */\n enableCache?: boolean;\n /** Whether to validate image existence (default: true) */\n validateImage?: boolean;\n /** Custom fallback text generator */\n generateFallbackText?: (eventName: string) => string;\n /** Supabase client instance (required) */\n supabase: SupabaseClient<Database>;\n}\n\n/**\n * Generate fallback text from event name (first letter of each word)\n */\nfunction defaultGenerateFallbackText(eventName: string): string {\n if (!eventName) return 'EV';\n \n return eventName\n .split(' ')\n .map(word => word.charAt(0).toUpperCase())\n .join('')\n .substring(0, 3); // Max 3 characters\n}\n\n/**\n * Hook for accessing public event logo URLs\n * \n * This hook provides access to event logo URLs without requiring\n * authentication. It includes fallback handling and image validation.\n * \n * @param eventId - The event ID to fetch logo for\n * @param eventName - The event name for fallback text generation\n * @param organisationId - The organisation ID for storage path\n * @param options - Configuration options for caching and behavior\n * @returns Object containing logo URL, fallback text, loading state, error, and refetch function\n */\nexport function usePublicEventLogo(\n eventId: string | undefined,\n eventName: string | undefined,\n organisationId: string | undefined,\n options: UsePublicEventLogoOptions\n): UsePublicEventLogoReturn {\n const {\n cacheTtl = 30 * 60 * 1000, // 30 minutes\n enableCache = true,\n validateImage = true,\n generateFallbackText = defaultGenerateFallbackText,\n supabase\n } = options;\n\n const [logoUrl, setLogoUrl] = useState<string | null>(null);\n const [isLoading, setIsLoading] = useState<boolean>(false);\n const [error, setError] = useState<Error | null>(null);\n\n // Generate fallback text\n const fallbackText = useMemo(() => {\n return eventName ? generateFallbackText(eventName) : 'EV';\n }, [eventName, generateFallbackText]);\n\n const fetchLogo = useCallback(async (): Promise<void> => {\n if (!eventId || !organisationId || !supabase) {\n setLogoUrl(null);\n setIsLoading(false);\n return;\n }\n\n // Validate UUID format for organisationId to prevent database errors\n const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n if (!uuidRegex.test(organisationId)) {\n console.warn('[usePublicEventLogo] Invalid organisationId format (not a valid UUID):', organisationId);\n // Don't return early - let the database handle the validation\n // This allows for more graceful error handling\n }\n\n // Check cache first\n const cacheKey = `public_logo_${eventId}_${organisationId}`;\n if (enableCache) {\n const cached = publicDataCache.get(cacheKey);\n if (cached && Date.now() - cached.timestamp < cached.ttl) {\n setLogoUrl(cached.data);\n setIsLoading(false);\n setError(null);\n return;\n }\n }\n\n try {\n setIsLoading(true);\n setError(null);\n\n // Call the public logo RPC function\n const { data, error: rpcError } = await (supabase as any).rpc('get_public_event_logo', {\n event_id_param: eventId,\n organisation_id_param: organisationId\n });\n\n if (rpcError) {\n throw new Error(rpcError.message || 'Failed to fetch logo');\n }\n\n if (!data || data.length === 0 || !data[0] || !data[0].logo_url) {\n setLogoUrl(null);\n return;\n }\n\n const logoUrl = data[0].logo_url;\n\n // Validate image existence if requested\n if (validateImage) {\n try {\n const response = await fetch(logoUrl, { method: 'HEAD' });\n if (!response.ok) {\n console.warn('[usePublicEventLogo] Logo URL not accessible:', logoUrl);\n setLogoUrl(null);\n return;\n }\n } catch (fetchError) {\n console.warn('[usePublicEventLogo] Error validating logo URL:', fetchError);\n setLogoUrl(null);\n return;\n }\n }\n\n setLogoUrl(logoUrl);\n\n // Cache the result\n if (enableCache) {\n publicDataCache.set(cacheKey, {\n data: logoUrl,\n timestamp: Date.now(),\n ttl: cacheTtl\n });\n }\n\n } catch (err) {\n console.error('[usePublicEventLogo] Error fetching logo:', err);\n const error = err instanceof Error ? err : new Error('Unknown error occurred');\n setError(error);\n setLogoUrl(null);\n } finally {\n setIsLoading(false);\n }\n }, [eventId, organisationId, supabase, cacheTtl, enableCache, validateImage]);\n\n // Fetch logo when parameters change\n useEffect(() => {\n if (eventId && organisationId) {\n fetchLogo();\n } else {\n setLogoUrl(null);\n setIsLoading(false);\n setError(null);\n }\n }, [fetchLogo, eventId, organisationId]);\n\n const refetch = useCallback(async (): Promise<void> => {\n if (!eventId || !organisationId) return;\n \n // Clear cache for this logo\n if (enableCache) {\n const cacheKey = `public_logo_${eventId}_${organisationId}`;\n publicDataCache.delete(cacheKey);\n }\n await fetchLogo();\n }, [fetchLogo, eventId, organisationId, enableCache]);\n\n return {\n logoUrl,\n fallbackText,\n isLoading,\n error,\n refetch\n };\n}\n\n/**\n * Clear all cached public logo data\n * Useful for testing or when you need to force refresh all data\n */\nexport function clearPublicLogoCache(): void {\n for (const [key] of publicDataCache) {\n if (key.startsWith('public_logo_')) {\n publicDataCache.delete(key);\n }\n }\n}\n\n/**\n * Get cache statistics for debugging\n */\nexport function getPublicLogoCacheStats(): { size: number; keys: string[] } {\n const keys = Array.from(publicDataCache.keys()).filter(key => key.startsWith('public_logo_'));\n return {\n size: keys.length,\n keys\n };\n}\n"],"mappings":"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","names":["props","React","error","jsx","useMemo","useMemo","useState","useEffect","useMemo","logoUrl","error"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/performanceBudgets.ts"],"sourcesContent":["\ninterface PerformanceBudget {\n metric: string;\n budget: number;\n actual: number;\n threshold: 'error' | 'warning' | 'info';\n}\n\ninterface PerformanceMetrics {\n bundleSize: number;\n chunkCount: number;\n treeshakingEffectiveness: number;\n dynamicImportUsage: number;\n}\n\ninterface MeasurementResult {\n passed: boolean;\n value: number;\n threshold: number;\n}\n\n// Performance budget thresholds with index signature\nexport const PERFORMANCE_BUDGETS: { [key: string]: { threshold: number } } = {\n COMPONENT_RENDER: { threshold: 50 },\n BUNDLE_SIZE: { threshold: 150000 },\n CHUNK_COUNT: { threshold: 10 },\n TREESHAKING_SCORE: { threshold: 70 },\n ERROR_BOUNDARY_TRIGGER: { threshold: 5 },\n MEMORY_INCREASE: { threshold: 1000 },\n LARGE_LIST_RENDER: { threshold: 500 },\n} as const;\n\nclass PerformanceBudgetMonitor {\n private metrics: Map<string, number> = new Map();\n private budgets: PerformanceBudget[] = [];\n\n measure(metric: string, value: number, metadata?: Record<string, unknown>): MeasurementResult {\n this.metrics.set(metric, value);\n \n // In production, this would send to a proper logging service\n // For now, we'll log to console for testing purposes\n if (import.meta.env.MODE === 'development' || import.meta.env.MODE === 'test') {\n console.log('📊 Performance Metric: ' + metric + ' = ' + value, metadata);\n }\n\n // Get threshold for this metric\n const budgetConfig = PERFORMANCE_BUDGETS[metric];\n const threshold = budgetConfig?.threshold || 100;\n const passed = value <= threshold;\n\n return {\n passed,\n value,\n threshold\n };\n }\n\n setBudget(metric: string, budget: number, threshold: 'error' | 'warning' | 'info' = 'warning'): void {\n const actual = this.metrics.get(metric) || 0;\n this.budgets.push({ metric, budget, actual, threshold });\n }\n\n checkBudgets(): PerformanceBudget[] {\n const violations: PerformanceBudget[] = [];\n \n for (const budget of this.budgets) {\n const actual = this.metrics.get(budget.metric) || 0;\n budget.actual = actual;\n \n if (actual > budget.budget) {\n violations.push(budget);\n \n // In production, this would send to a proper logging service\n // For now, we'll log to console for testing purposes\n if (import.meta.env.MODE === 'development' || import.meta.env.MODE === 'test') {\n if (budget.threshold === 'error') {\n console.error('❌ Performance budget exceeded: ' + budget.metric + ' (' + actual + ' > ' + budget.budget + ')');\n } else if (budget.threshold === 'warning') {\n console.warn('⚠️ Performance budget exceeded: ' + budget.metric + ' (' + actual + ' > ' + budget.budget + ')');\n } else {\n console.info('ℹ️ Performance budget exceeded: ' + budget.metric + ' (' + actual + ' > ' + budget.budget + ')');\n }\n }\n }\n }\n \n return violations;\n }\n\n getMetrics(): PerformanceMetrics {\n return {\n bundleSize: this.metrics.get('BUNDLE_SIZE') || 0,\n chunkCount: this.metrics.get('CHUNK_COUNT') || 0,\n treeshakingEffectiveness: this.metrics.get('TREESHAKING_SCORE') || 0,\n dynamicImportUsage: this.metrics.get('DYNAMIC_IMPORTS') || 0,\n };\n }\n\n reset(): void {\n this.metrics.clear();\n this.budgets.length = 0;\n }\n}\n\nexport const performanceBudgetMonitor = new PerformanceBudgetMonitor();\n\n// Set default performance budgets\nperformanceBudgetMonitor.setBudget('BUNDLE_SIZE', 150000, 'error'); // 150KB\nperformanceBudgetMonitor.setBudget('CHUNK_COUNT', 10, 'warning');\nperformanceBudgetMonitor.setBudget('TREESHAKING_SCORE', 70, 'warning');\nperformanceBudgetMonitor.setBudget('ERROR_BOUNDARY_TRIGGER', 5, 'error');\n"],"mappings":";AAsBO,IAAM,sBAAgE;AAAA,EAC3E,kBAAkB,EAAE,WAAW,GAAG;AAAA,EAClC,aAAa,EAAE,WAAW,KAAO;AAAA,EACjC,aAAa,EAAE,WAAW,GAAG;AAAA,EAC7B,mBAAmB,EAAE,WAAW,GAAG;AAAA,EACnC,wBAAwB,EAAE,WAAW,EAAE;AAAA,EACvC,iBAAiB,EAAE,WAAW,IAAK;AAAA,EACnC,mBAAmB,EAAE,WAAW,IAAI;AACtC;AAEA,IAAM,2BAAN,MAA+B;AAAA,EAA/B;AACE,SAAQ,UAA+B,oBAAI,IAAI;AAC/C,SAAQ,UAA+B,CAAC;AAAA;AAAA,EAExC,QAAQ,QAAgB,OAAe,UAAuD;AAC5F,SAAK,QAAQ,IAAI,QAAQ,KAAK;AAI9B,QAAI,YAAY,IAAI,SAAS,iBAAiB,YAAY,IAAI,SAAS,QAAQ;AAC7E,cAAQ,IAAI,mCAA4B,SAAS,QAAQ,OAAO,QAAQ;AAAA,IAC1E;AAGA,UAAM,eAAe,oBAAoB,MAAM;AAC/C,UAAM,YAAY,cAAc,aAAa;AAC7C,UAAM,SAAS,SAAS;AAExB,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,UAAU,QAAgB,QAAgB,YAA0C,WAAiB;AACnG,UAAM,SAAS,KAAK,QAAQ,IAAI,MAAM,KAAK;AAC3C,SAAK,QAAQ,KAAK,EAAE,QAAQ,QAAQ,QAAQ,UAAU,CAAC;AAAA,EACzD;AAAA,EAEA,eAAoC;AAClC,UAAM,aAAkC,CAAC;AAEzC,eAAW,UAAU,KAAK,SAAS;AACjC,YAAM,SAAS,KAAK,QAAQ,IAAI,OAAO,MAAM,KAAK;AAClD,aAAO,SAAS;AAEhB,UAAI,SAAS,OAAO,QAAQ;AAC1B,mBAAW,KAAK,MAAM;AAItB,YAAI,YAAY,IAAI,SAAS,iBAAiB,YAAY,IAAI,SAAS,QAAQ;AAC7E,cAAI,OAAO,cAAc,SAAS;AAChC,oBAAQ,MAAM,yCAAoC,OAAO,SAAS,OAAO,SAAS,QAAQ,OAAO,SAAS,GAAG;AAAA,UAC/G,WAAW,OAAO,cAAc,WAAW;AACzC,oBAAQ,KAAK,+CAAqC,OAAO,SAAS,OAAO,SAAS,QAAQ,OAAO,SAAS,GAAG;AAAA,UAC/G,OAAO;AACL,oBAAQ,KAAK,+CAAqC,OAAO,SAAS,OAAO,SAAS,QAAQ,OAAO,SAAS,GAAG;AAAA,UAC/G;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,aAAiC;AAC/B,WAAO;AAAA,MACL,YAAY,KAAK,QAAQ,IAAI,aAAa,KAAK;AAAA,MAC/C,YAAY,KAAK,QAAQ,IAAI,aAAa,KAAK;AAAA,MAC/C,0BAA0B,KAAK,QAAQ,IAAI,mBAAmB,KAAK;AAAA,MACnE,oBAAoB,KAAK,QAAQ,IAAI,iBAAiB,KAAK;AAAA,IAC7D;AAAA,EACF;AAAA,EAEA,QAAc;AACZ,SAAK,QAAQ,MAAM;AACnB,SAAK,QAAQ,SAAS;AAAA,EACxB;AACF;AAEO,IAAM,2BAA2B,IAAI,yBAAyB;AAGrE,yBAAyB,UAAU,eAAe,MAAQ,OAAO;AACjE,yBAAyB,UAAU,eAAe,IAAI,SAAS;AAC/D,yBAAyB,UAAU,qBAAqB,IAAI,SAAS;AACrE,yBAAyB,UAAU,0BAA0B,GAAG,OAAO;","names":[]}
|
|
@@ -1,269 +0,0 @@
|
|
|
1
|
-
# Complete Installation Guide
|
|
2
|
-
|
|
3
|
-
This is the definitive guide for installing and configuring pace-core in your application. Follow these steps exactly to ensure proper styling and functionality.
|
|
4
|
-
|
|
5
|
-
## 🚨 Critical Requirements
|
|
6
|
-
|
|
7
|
-
**IMPORTANT**: Pace-core requires specific configuration to work properly. Without following these steps exactly, components will be unstyled and the UI will be severely compromised.
|
|
8
|
-
|
|
9
|
-
## Step 1: Install Dependencies
|
|
10
|
-
|
|
11
|
-
### Required Packages
|
|
12
|
-
|
|
13
|
-
```bash
|
|
14
|
-
# Install pace-core and all required peer dependencies
|
|
15
|
-
npm install @jmruthers/pace-core @tanstack/react-table @radix-ui/react-checkbox @radix-ui/react-dialog @radix-ui/react-dropdown-menu @radix-ui/react-label @radix-ui/react-slot lucide-react class-variance-authority clsx tailwind-merge
|
|
16
|
-
|
|
17
|
-
# Install Tailwind CSS v4 and Vite plugin (REQUIRED)
|
|
18
|
-
npm install -D @tailwindcss/vite tailwindcss@^4.0.0
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
### Optional Packages (for full functionality)
|
|
22
|
-
|
|
23
|
-
```bash
|
|
24
|
-
# For authentication and database
|
|
25
|
-
npm install @supabase/supabase-js
|
|
26
|
-
|
|
27
|
-
# For routing
|
|
28
|
-
npm install react-router-dom
|
|
29
|
-
|
|
30
|
-
# For TypeScript support
|
|
31
|
-
npm install -D @types/react @types/react-dom
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
## Step 2: Configure Vite with Tailwind v4
|
|
35
|
-
|
|
36
|
-
**⚠️ CRITICAL**: This configuration is essential for pace-core components to be styled correctly.
|
|
37
|
-
|
|
38
|
-
Create or update your `vite.config.ts`:
|
|
39
|
-
|
|
40
|
-
```typescript
|
|
41
|
-
// vite.config.ts
|
|
42
|
-
import { defineConfig } from 'vite'
|
|
43
|
-
import react from '@vitejs/plugin-react'
|
|
44
|
-
import tailwindcss from '@tailwindcss/vite'
|
|
45
|
-
import path from 'path'
|
|
46
|
-
|
|
47
|
-
export default defineConfig({
|
|
48
|
-
plugins: [
|
|
49
|
-
react(),
|
|
50
|
-
tailwindcss({
|
|
51
|
-
// CRITICAL: Include pace-core components for scanning
|
|
52
|
-
content: [
|
|
53
|
-
'./src/**/*.{js,ts,jsx,tsx}',
|
|
54
|
-
'./node_modules/@jmruthers/pace-core/**/*.{js,ts,jsx,tsx}'
|
|
55
|
-
]
|
|
56
|
-
})
|
|
57
|
-
],
|
|
58
|
-
resolve: {
|
|
59
|
-
alias: {
|
|
60
|
-
"@": path.resolve(__dirname, "./src"),
|
|
61
|
-
},
|
|
62
|
-
},
|
|
63
|
-
server: {
|
|
64
|
-
port: 3000,
|
|
65
|
-
open: true,
|
|
66
|
-
},
|
|
67
|
-
build: {
|
|
68
|
-
outDir: 'dist',
|
|
69
|
-
sourcemap: true,
|
|
70
|
-
},
|
|
71
|
-
})
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
### Why This Configuration is Critical
|
|
75
|
-
|
|
76
|
-
Pace-core components contain Tailwind classes that must be scanned during the build process. Without this configuration:
|
|
77
|
-
|
|
78
|
-
- ❌ Component styles will be missing or broken
|
|
79
|
-
- ❌ Colors, spacing, and typography won't work
|
|
80
|
-
- ❌ The UI will be severely compromised
|
|
81
|
-
- ❌ The entire point of using this UI library is undermined
|
|
82
|
-
|
|
83
|
-
### Alternative Configuration (if needed)
|
|
84
|
-
|
|
85
|
-
If you're still having issues with component scanning:
|
|
86
|
-
|
|
87
|
-
```typescript
|
|
88
|
-
// vite.config.ts
|
|
89
|
-
import { defineConfig } from 'vite'
|
|
90
|
-
import react from '@vitejs/plugin-react'
|
|
91
|
-
import tailwindcss from '@tailwindcss/vite'
|
|
92
|
-
|
|
93
|
-
export default defineConfig({
|
|
94
|
-
plugins: [
|
|
95
|
-
react(),
|
|
96
|
-
tailwindcss({
|
|
97
|
-
content: {
|
|
98
|
-
files: [
|
|
99
|
-
'./src/**/*.{js,ts,jsx,tsx}',
|
|
100
|
-
'./node_modules/@jmruthers/pace-core/**/*.{js,ts,jsx,tsx}',
|
|
101
|
-
'./node_modules/@jmruthers/pace-core/dist/**/*.{js,ts,jsx,tsx}'
|
|
102
|
-
]
|
|
103
|
-
}
|
|
104
|
-
})
|
|
105
|
-
],
|
|
106
|
-
})
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
## Step 3: Import Core Styles
|
|
110
|
-
|
|
111
|
-
**CRITICAL**: Import the CSS file in your main entry point:
|
|
112
|
-
|
|
113
|
-
```tsx
|
|
114
|
-
// src/main.tsx (or your app's entry point)
|
|
115
|
-
import '@jmruthers/pace-core/src/styles/core.css';
|
|
116
|
-
import React from 'react';
|
|
117
|
-
import ReactDOM from 'react-dom/client';
|
|
118
|
-
import App from './App';
|
|
119
|
-
|
|
120
|
-
const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
|
|
121
|
-
root.render(
|
|
122
|
-
<React.StrictMode>
|
|
123
|
-
<App />
|
|
124
|
-
</React.StrictMode>
|
|
125
|
-
);
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
### What the CSS File Includes
|
|
129
|
-
|
|
130
|
-
The `core.css` file provides:
|
|
131
|
-
- Complete color palettes (main, secondary, accent)
|
|
132
|
-
- Font definitions with system font fallbacks
|
|
133
|
-
- Base element styles and resets
|
|
134
|
-
- Tailwind v4 utility classes
|
|
135
|
-
- Component styling foundation
|
|
136
|
-
|
|
137
|
-
**Note on Fonts**: The CSS includes font definitions that fall back to system fonts. For custom fonts, you'll need to provide them separately in your consuming app.
|
|
138
|
-
|
|
139
|
-
## Step 4: Verify Installation
|
|
140
|
-
|
|
141
|
-
Create a test component to ensure everything works:
|
|
142
|
-
|
|
143
|
-
```tsx
|
|
144
|
-
// src/App.tsx
|
|
145
|
-
import { Button, Card, Input } from '@jmruthers/pace-core';
|
|
146
|
-
|
|
147
|
-
function App() {
|
|
148
|
-
return (
|
|
149
|
-
<div className="p-8 space-y-4">
|
|
150
|
-
<h1 className="text-2xl font-bold text-main-900">PACE Core Test</h1>
|
|
151
|
-
|
|
152
|
-
<Card className="p-4">
|
|
153
|
-
<h2 className="text-lg font-semibold text-sec-800 mb-2">Components Test</h2>
|
|
154
|
-
<div className="space-y-2">
|
|
155
|
-
<Button variant="primary">Primary Button</Button>
|
|
156
|
-
<Button variant="secondary">Secondary Button</Button>
|
|
157
|
-
<Input placeholder="Test input field" />
|
|
158
|
-
</div>
|
|
159
|
-
</Card>
|
|
160
|
-
</div>
|
|
161
|
-
);
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
export default App;
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
### Expected Result
|
|
168
|
-
|
|
169
|
-
You should see:
|
|
170
|
-
- ✅ Properly styled components with PACE Core's design system
|
|
171
|
-
- ✅ Colors working (text-main-900, bg-sec-500, etc.)
|
|
172
|
-
- ✅ Typography and spacing applied correctly
|
|
173
|
-
- ✅ Hover effects and transitions working
|
|
174
|
-
|
|
175
|
-
## Step 5: Set Up Authentication (Optional)
|
|
176
|
-
|
|
177
|
-
If you're using pace-core's authentication features:
|
|
178
|
-
|
|
179
|
-
### Install Supabase
|
|
180
|
-
|
|
181
|
-
```bash
|
|
182
|
-
npm install @supabase/supabase-js
|
|
183
|
-
```
|
|
184
|
-
|
|
185
|
-
### Create Supabase Client
|
|
186
|
-
|
|
187
|
-
```typescript
|
|
188
|
-
// src/lib/supabase.ts
|
|
189
|
-
import { createClient } from '@supabase/supabase-js'
|
|
190
|
-
|
|
191
|
-
const supabaseUrl = process.env.REACT_APP_SUPABASE_URL!
|
|
192
|
-
const supabaseAnonKey = process.env.REACT_APP_SUPABASE_ANON_KEY!
|
|
193
|
-
|
|
194
|
-
export const supabase = createClient(supabaseUrl, supabaseAnonKey)
|
|
195
|
-
```
|
|
196
|
-
|
|
197
|
-
### Set Up Environment Variables
|
|
198
|
-
|
|
199
|
-
Create `.env.local`:
|
|
200
|
-
|
|
201
|
-
```bash
|
|
202
|
-
REACT_APP_SUPABASE_URL=https://your-project.supabase.co
|
|
203
|
-
REACT_APP_SUPABASE_ANON_KEY=your-anon-key-here
|
|
204
|
-
```
|
|
205
|
-
|
|
206
|
-
### Configure Providers
|
|
207
|
-
|
|
208
|
-
```tsx
|
|
209
|
-
// src/main.tsx
|
|
210
|
-
import { UnifiedAuthProvider, OrganisationProvider, EventProvider } from '@jmruthers/pace-core';
|
|
211
|
-
import { supabase } from './lib/supabase';
|
|
212
|
-
|
|
213
|
-
ReactDOM.createRoot(document.getElementById('root')!).render(
|
|
214
|
-
<React.StrictMode>
|
|
215
|
-
<UnifiedAuthProvider supabaseClient={supabase} appName="your-app">
|
|
216
|
-
<OrganisationProvider>
|
|
217
|
-
<EventProvider>
|
|
218
|
-
<App />
|
|
219
|
-
</EventProvider>
|
|
220
|
-
</OrganisationProvider>
|
|
221
|
-
</UnifiedAuthProvider>
|
|
222
|
-
</React.StrictMode>
|
|
223
|
-
);
|
|
224
|
-
```
|
|
225
|
-
|
|
226
|
-
## Troubleshooting
|
|
227
|
-
|
|
228
|
-
### Common Issues
|
|
229
|
-
|
|
230
|
-
1. **Components appear unstyled**
|
|
231
|
-
- Check that pace-core is included in your Vite content configuration
|
|
232
|
-
- Ensure the CSS file is imported
|
|
233
|
-
- Restart your dev server
|
|
234
|
-
|
|
235
|
-
2. **Colors don't work**
|
|
236
|
-
- Verify the CSS file is imported
|
|
237
|
-
- Check that content scanning includes pace-core
|
|
238
|
-
- Ensure you're using Tailwind v4
|
|
239
|
-
|
|
240
|
-
3. **Build errors about missing classes**
|
|
241
|
-
- Verify your content paths are correct
|
|
242
|
-
- Check that both source files and pace-core are included
|
|
243
|
-
|
|
244
|
-
### Verification Checklist
|
|
245
|
-
|
|
246
|
-
Before asking for help, verify:
|
|
247
|
-
|
|
248
|
-
- [ ] CSS file is imported: `import '@jmruthers/pace-core/src/styles/core.css'`
|
|
249
|
-
- [ ] Vite config includes pace-core in content scanning
|
|
250
|
-
- [ ] Using Tailwind v4 (not v3)
|
|
251
|
-
- [ ] Dev server restarted after config changes
|
|
252
|
-
- [ ] All required peer dependencies installed
|
|
253
|
-
- [ ] Test component renders with proper styling
|
|
254
|
-
|
|
255
|
-
## Next Steps
|
|
256
|
-
|
|
257
|
-
- [Quick Start Guide](./quick-start.md) - Build your first app
|
|
258
|
-
- [Vite Configuration](../consuming-app-vite-config.md) - Detailed Vite setup
|
|
259
|
-
- [Troubleshooting](../troubleshooting/styling-issues.md) - Fix common problems
|
|
260
|
-
- [Component API](../api/README.md) - Explore all components
|
|
261
|
-
|
|
262
|
-
## Need Help?
|
|
263
|
-
|
|
264
|
-
If you're still having issues:
|
|
265
|
-
|
|
266
|
-
1. Check the [Troubleshooting Guide](../troubleshooting/styling-issues.md)
|
|
267
|
-
2. Verify your setup matches this guide exactly
|
|
268
|
-
3. Test with a minimal example to isolate the issue
|
|
269
|
-
4. Check your package versions for compatibility
|
|
@@ -1,223 +0,0 @@
|
|
|
1
|
-
# 🚀 Test Suite Rebuild Plan
|
|
2
|
-
|
|
3
|
-
## 📊 Current Status
|
|
4
|
-
- ✅ **193 broken test files deleted**
|
|
5
|
-
- ✅ **World-class test architecture created**
|
|
6
|
-
- ✅ **Comprehensive utilities and helpers ready**
|
|
7
|
-
- ✅ **Excellent examples and templates provided**
|
|
8
|
-
- ✅ **Testing guidelines and guardrails established**
|
|
9
|
-
|
|
10
|
-
## 🎯 Rebuild Strategy
|
|
11
|
-
|
|
12
|
-
### Phase 1: Foundation (Week 1)
|
|
13
|
-
**Priority: Critical Components**
|
|
14
|
-
|
|
15
|
-
#### 1.1 Core UI Components
|
|
16
|
-
- [ ] **Button** - Already completed ✅
|
|
17
|
-
- [ ] **Input** - Form input component
|
|
18
|
-
- [ ] **Card** - Content container
|
|
19
|
-
- [ ] **Modal** - Overlay component
|
|
20
|
-
- [ ] **LoadingSpinner** - Loading indicator
|
|
21
|
-
|
|
22
|
-
#### 1.2 Essential Hooks
|
|
23
|
-
- [ ] **useDebounce** - Input debouncing
|
|
24
|
-
- [ ] **useLocalStorage** - Local storage management
|
|
25
|
-
- [ ] **useToggle** - Boolean state management
|
|
26
|
-
- [ ] **useAsync** - Async operation handling
|
|
27
|
-
|
|
28
|
-
#### 1.3 Utility Functions
|
|
29
|
-
- [ ] **formatDate** - Date formatting
|
|
30
|
-
- [ ] **validateEmail** - Email validation
|
|
31
|
-
- [ ] **generateId** - ID generation
|
|
32
|
-
- [ ] **deepClone** - Object cloning
|
|
33
|
-
|
|
34
|
-
### Phase 2: Business Logic (Week 2)
|
|
35
|
-
**Priority: High-Value Components**
|
|
36
|
-
|
|
37
|
-
#### 2.1 Authentication Components
|
|
38
|
-
- [ ] **LoginForm** - User authentication
|
|
39
|
-
- [ ] **UserMenu** - User profile menu
|
|
40
|
-
- [ ] **AuthGuard** - Route protection
|
|
41
|
-
- [ ] **PasswordReset** - Password recovery
|
|
42
|
-
|
|
43
|
-
#### 2.2 Data Management
|
|
44
|
-
- [ ] **DataTable** - Data display
|
|
45
|
-
- [ ] **Pagination** - Data pagination
|
|
46
|
-
- [ ] **Search** - Data filtering
|
|
47
|
-
- [ ] **Export** - Data export
|
|
48
|
-
|
|
49
|
-
#### 2.3 Business Hooks
|
|
50
|
-
- [ ] **useAuth** - Authentication state
|
|
51
|
-
- [ ] **useApi** - API calls
|
|
52
|
-
- [ ] **usePermissions** - Access control
|
|
53
|
-
- [ ] **useCache** - Data caching
|
|
54
|
-
|
|
55
|
-
### Phase 3: Advanced Features (Week 3)
|
|
56
|
-
**Priority: Complex Components**
|
|
57
|
-
|
|
58
|
-
#### 3.1 Advanced UI Components
|
|
59
|
-
- [ ] **DataTable** - Complex data display
|
|
60
|
-
- [ ] **FormBuilder** - Dynamic forms
|
|
61
|
-
- [ ] **FileUpload** - File handling
|
|
62
|
-
- [ ] **RichTextEditor** - Text editing
|
|
63
|
-
|
|
64
|
-
#### 3.2 Integration Components
|
|
65
|
-
- [ ] **Dashboard** - Main dashboard
|
|
66
|
-
- [ ] **Settings** - Configuration
|
|
67
|
-
- [ ] **Reports** - Data visualization
|
|
68
|
-
- [ ] **Notifications** - User alerts
|
|
69
|
-
|
|
70
|
-
#### 3.3 Advanced Hooks
|
|
71
|
-
- [ ] **useForm** - Form management
|
|
72
|
-
- [ ] **usePagination** - Pagination logic
|
|
73
|
-
- [ ] **useInfiniteScroll** - Infinite loading
|
|
74
|
-
- [ ] **useWebSocket** - Real-time updates
|
|
75
|
-
|
|
76
|
-
### Phase 4: Integration & E2E (Week 4)
|
|
77
|
-
**Priority: End-to-End Testing**
|
|
78
|
-
|
|
79
|
-
#### 4.1 Integration Tests
|
|
80
|
-
- [ ] **User Authentication Flow**
|
|
81
|
-
- [ ] **Data CRUD Operations**
|
|
82
|
-
- [ ] **File Upload Process**
|
|
83
|
-
- [ ] **Report Generation**
|
|
84
|
-
|
|
85
|
-
#### 4.2 E2E Test Scenarios
|
|
86
|
-
- [ ] **Complete User Journey**
|
|
87
|
-
- [ ] **Admin Workflow**
|
|
88
|
-
- [ ] **Error Handling**
|
|
89
|
-
- [ ] **Performance Testing**
|
|
90
|
-
|
|
91
|
-
## 📋 Implementation Guidelines
|
|
92
|
-
|
|
93
|
-
### Test Creation Process
|
|
94
|
-
1. **Identify Component Priority** - Use the phase-based approach
|
|
95
|
-
2. **Copy Template** - Use provided templates
|
|
96
|
-
3. **Write Tests** - Follow testing guidelines
|
|
97
|
-
4. **Verify Coverage** - Ensure 80%+ coverage
|
|
98
|
-
5. **Review & Refactor** - Code review and optimization
|
|
99
|
-
|
|
100
|
-
### Quality Gates
|
|
101
|
-
- ✅ **All tests pass** - No failing tests
|
|
102
|
-
- ✅ **80%+ coverage** - Meet coverage thresholds
|
|
103
|
-
- ✅ **Fast execution** - Tests run in <5 seconds
|
|
104
|
-
- ✅ **Clear naming** - Descriptive test names
|
|
105
|
-
- ✅ **No flaky tests** - Reliable test results
|
|
106
|
-
|
|
107
|
-
### File Structure
|
|
108
|
-
```
|
|
109
|
-
src/__tests__/
|
|
110
|
-
├── components/
|
|
111
|
-
│ ├── Button.test.tsx ✅
|
|
112
|
-
│ ├── Input.test.tsx
|
|
113
|
-
│ ├── Card.test.tsx
|
|
114
|
-
│ └── ...
|
|
115
|
-
├── hooks/
|
|
116
|
-
│ ├── useDebounce.test.ts
|
|
117
|
-
│ ├── useLocalStorage.test.ts
|
|
118
|
-
│ └── ...
|
|
119
|
-
├── utils/
|
|
120
|
-
│ ├── formatDate.test.ts
|
|
121
|
-
│ ├── validateEmail.test.ts
|
|
122
|
-
│ └── ...
|
|
123
|
-
├── integration/
|
|
124
|
-
│ ├── auth-flow.test.tsx
|
|
125
|
-
│ ├── data-crud.test.tsx
|
|
126
|
-
│ └── ...
|
|
127
|
-
└── templates/
|
|
128
|
-
├── component.test.template.tsx
|
|
129
|
-
├── hook.test.template.ts
|
|
130
|
-
└── ...
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
## 🛠️ Development Workflow
|
|
134
|
-
|
|
135
|
-
### Daily Process
|
|
136
|
-
1. **Start with Template** - Copy appropriate template
|
|
137
|
-
2. **Write Tests First** - TDD approach
|
|
138
|
-
3. **Run Tests Frequently** - `npm test -- --watch`
|
|
139
|
-
4. **Check Coverage** - `npm test -- --coverage`
|
|
140
|
-
5. **Commit Often** - Small, focused commits
|
|
141
|
-
|
|
142
|
-
### Weekly Review
|
|
143
|
-
1. **Coverage Report** - Review coverage metrics
|
|
144
|
-
2. **Test Performance** - Check execution time
|
|
145
|
-
3. **Code Quality** - Review test quality
|
|
146
|
-
4. **Plan Next Week** - Prioritize next components
|
|
147
|
-
|
|
148
|
-
## 📊 Success Metrics
|
|
149
|
-
|
|
150
|
-
### Week 1 Targets
|
|
151
|
-
- [ ] 5 core components tested
|
|
152
|
-
- [ ] 4 essential hooks tested
|
|
153
|
-
- [ ] 4 utility functions tested
|
|
154
|
-
- [ ] 80%+ coverage on tested components
|
|
155
|
-
|
|
156
|
-
### Week 2 Targets
|
|
157
|
-
- [ ] 4 authentication components tested
|
|
158
|
-
- [ ] 4 data management components tested
|
|
159
|
-
- [ ] 4 business hooks tested
|
|
160
|
-
- [ ] 2 integration tests completed
|
|
161
|
-
|
|
162
|
-
### Week 3 Targets
|
|
163
|
-
- [ ] 4 advanced UI components tested
|
|
164
|
-
- [ ] 4 integration components tested
|
|
165
|
-
- [ ] 4 advanced hooks tested
|
|
166
|
-
- [ ] Performance tests added
|
|
167
|
-
|
|
168
|
-
### Week 4 Targets
|
|
169
|
-
- [ ] 4 integration test suites completed
|
|
170
|
-
- [ ] 4 E2E test scenarios completed
|
|
171
|
-
- [ ] 90%+ overall coverage
|
|
172
|
-
- [ ] All tests passing consistently
|
|
173
|
-
|
|
174
|
-
## 🚨 Risk Mitigation
|
|
175
|
-
|
|
176
|
-
### Common Pitfalls
|
|
177
|
-
1. **Over-testing** - Focus on user behavior
|
|
178
|
-
2. **Under-testing** - Ensure critical paths covered
|
|
179
|
-
3. **Flaky tests** - Use proper async handling
|
|
180
|
-
4. **Slow tests** - Optimize test performance
|
|
181
|
-
|
|
182
|
-
### Solutions
|
|
183
|
-
1. **Follow templates** - Use provided patterns
|
|
184
|
-
2. **Review guidelines** - Check testing best practices
|
|
185
|
-
3. **Use utilities** - Leverage test helpers
|
|
186
|
-
4. **Monitor performance** - Track test execution time
|
|
187
|
-
|
|
188
|
-
## 📚 Resources
|
|
189
|
-
|
|
190
|
-
### Quick Reference
|
|
191
|
-
- [Testing Guidelines](./TESTING_GUIDELINES.md)
|
|
192
|
-
- [Component Template](./templates/component.test.template.tsx)
|
|
193
|
-
- [Hook Template](./templates/hook.test.template.ts)
|
|
194
|
-
- [Test Utilities](./helpers/test-utils.tsx)
|
|
195
|
-
|
|
196
|
-
### Commands
|
|
197
|
-
```bash
|
|
198
|
-
# Run all tests
|
|
199
|
-
npm test
|
|
200
|
-
|
|
201
|
-
# Run specific component
|
|
202
|
-
npm test -- Button.test.tsx
|
|
203
|
-
|
|
204
|
-
# Run with coverage
|
|
205
|
-
npm test -- --coverage
|
|
206
|
-
|
|
207
|
-
# Run in watch mode
|
|
208
|
-
npm test -- --watch
|
|
209
|
-
```
|
|
210
|
-
|
|
211
|
-
## 🎉 Expected Outcomes
|
|
212
|
-
|
|
213
|
-
After 4 weeks, you'll have:
|
|
214
|
-
- ✅ **Comprehensive test suite** - 50+ test files
|
|
215
|
-
- ✅ **High code coverage** - 90%+ overall
|
|
216
|
-
- ✅ **Fast test execution** - <10 seconds total
|
|
217
|
-
- ✅ **Reliable tests** - No flaky tests
|
|
218
|
-
- ✅ **Maintainable code** - Clear patterns and guidelines
|
|
219
|
-
- ✅ **Developer confidence** - Safe refactoring and changes
|
|
220
|
-
|
|
221
|
-
---
|
|
222
|
-
|
|
223
|
-
**Ready to start? Begin with Phase 1, Week 1, and work through the components systematically!** 🚀
|
|
File without changes
|
|
File without changes
|
|
File without changes
|