@jmruthers/pace-core 0.5.101 → 0.5.103
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-DXELRJIX.js → DataTable-EEDFYMJP.js} +2 -2
- package/dist/{PublicLoadingSpinner-C2h8zg67.d.ts → PublicLoadingSpinner-48ewSMKK.d.ts} +22 -150
- package/dist/{chunk-2ZYHCFUO.js → chunk-5SGBVBRU.js} +2 -2
- package/dist/{chunk-EVVRUGQ2.js → chunk-62AVH7CM.js} +78 -55
- package/dist/{chunk-EVVRUGQ2.js.map → chunk-62AVH7CM.js.map} +1 -1
- package/dist/{chunk-A5DFMP3O.js → chunk-SZWCMVTQ.js} +135 -669
- package/dist/chunk-SZWCMVTQ.js.map +1 -0
- package/dist/{chunk-MKMKUCPF.js → chunk-X33A4WWI.js} +42 -141
- package/dist/chunk-X33A4WWI.js.map +1 -0
- package/dist/components.d.ts +1 -1
- package/dist/components.js +3 -15
- package/dist/components.js.map +1 -1
- package/dist/hooks.d.ts +1 -1
- package/dist/hooks.js +2 -9
- package/dist/hooks.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +4 -22
- package/dist/index.js.map +1 -1
- package/dist/types.js +3 -3
- package/dist/{usePublicRouteParams-BwMR2uub.d.ts → usePublicRouteParams-BiXgKiYa.d.ts} +1 -117
- package/dist/utils.js +1 -1
- 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 +2 -1
- package/docs/api/enums/FileCategory.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/DataRecord.md +1 -1
- package/docs/api/interfaces/DataTableAction.md +1 -1
- package/docs/api/interfaces/DataTableColumn.md +1 -1
- package/docs/api/interfaces/DataTableProps.md +1 -1
- package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
- package/docs/api/interfaces/EmptyStateConfig.md +1 -1
- package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
- package/docs/api/interfaces/FileDisplayProps.md +77 -35
- package/docs/api/interfaces/FileMetadata.md +1 -1
- package/docs/api/interfaces/FileReference.md +1 -1
- package/docs/api/interfaces/FileSizeLimits.md +1 -1
- package/docs/api/interfaces/FileUploadOptions.md +1 -1
- package/docs/api/interfaces/FileUploadProps.md +1 -1
- package/docs/api/interfaces/FooterProps.md +1 -1
- package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
- package/docs/api/interfaces/InputProps.md +1 -1
- package/docs/api/interfaces/LabelProps.md +1 -1
- package/docs/api/interfaces/LoginFormProps.md +1 -1
- package/docs/api/interfaces/NavigationAccessRecord.md +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/ProtectedRouteProps.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 +11 -24
- package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
- package/docs/api/interfaces/RBACConfig.md +1 -1
- package/docs/api/interfaces/RBACLogger.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
- package/docs/api/interfaces/RouteAccessRecord.md +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/UsePublicEventOptions.md +1 -1
- package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
- package/docs/api/interfaces/UsePublicFileDisplayOptions.md +1 -1
- package/docs/api/interfaces/UsePublicFileDisplayReturn.md +1 -1
- package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
- package/docs/api/interfaces/UseResolvedScopeOptions.md +1 -1
- package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
- package/docs/api/interfaces/UserEventAccess.md +1 -1
- package/docs/api/interfaces/UserMenuProps.md +1 -1
- package/docs/api/interfaces/UserProfile.md +1 -1
- package/docs/api/modules.md +29 -244
- package/docs/implementation-guides/file-reference-system.md +84 -21
- package/package.json +1 -1
- package/src/components/DataTable/components/DataTableCore.tsx +23 -13
- package/src/components/DataTable/hooks/useTableColumns.ts +36 -6
- package/src/components/FileDisplay/FileDisplay.test.tsx +1 -1
- package/src/components/FileDisplay/FileDisplay.tsx +189 -300
- package/src/components/PublicLayout/PublicPageHeader.tsx +15 -10
- package/src/components/PublicLayout/__tests__/PublicPageHeader.test.tsx +25 -35
- package/src/components/PublicLayout/index.ts +2 -5
- package/src/components/Toast/Toast.tsx +1 -1
- package/src/components/index.ts +0 -2
- package/src/examples/PublicEventPage.tsx +17 -7
- package/src/examples/PublicPageApp.tsx +18 -8
- package/src/hooks/public/index.ts +2 -4
- package/src/hooks/useFileReference.ts +10 -1
- package/src/index.ts +0 -2
- package/src/utils/file-reference.ts +54 -9
- package/src/utils/storage/README.md +22 -20
- package/src/utils/storage/helpers.ts +12 -1
- package/dist/chunk-A5DFMP3O.js.map +0 -1
- package/dist/chunk-MKMKUCPF.js.map +0 -1
- package/docs/api/interfaces/EventLogoProps.md +0 -152
- package/docs/api/interfaces/UseEventLogoOptions.md +0 -74
- package/docs/api/interfaces/UseEventLogoReturn.md +0 -81
- package/docs/api/interfaces/UsePublicEventLogoOptions.md +0 -87
- package/docs/api/interfaces/UsePublicEventLogoReturn.md +0 -81
- package/src/components/PublicLayout/EventLogo.tsx +0 -474
- package/src/hooks/public/usePublicEventLogo.ts +0 -295
- package/src/hooks/useEventLogo.ts +0 -316
- /package/dist/{DataTable-DXELRJIX.js.map → DataTable-EEDFYMJP.js.map} +0 -0
- /package/dist/{chunk-2ZYHCFUO.js.map → chunk-5SGBVBRU.js.map} +0 -0
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
[@jmruthers/pace-core - v0.5.101](../README.md) / [Exports](../modules.md) / UsePublicEventLogoOptions
|
|
2
|
-
|
|
3
|
-
# Interface: UsePublicEventLogoOptions
|
|
4
|
-
|
|
5
|
-
## Table of contents
|
|
6
|
-
|
|
7
|
-
### Properties
|
|
8
|
-
|
|
9
|
-
- [cacheTtl](UsePublicEventLogoOptions.md#cachettl)
|
|
10
|
-
- [enableCache](UsePublicEventLogoOptions.md#enablecache)
|
|
11
|
-
- [validateImage](UsePublicEventLogoOptions.md#validateimage)
|
|
12
|
-
- [generateFallbackText](UsePublicEventLogoOptions.md#generatefallbacktext)
|
|
13
|
-
- [supabase](UsePublicEventLogoOptions.md#supabase)
|
|
14
|
-
|
|
15
|
-
## Properties
|
|
16
|
-
|
|
17
|
-
### cacheTtl
|
|
18
|
-
|
|
19
|
-
• `Optional` **cacheTtl**: `number`
|
|
20
|
-
|
|
21
|
-
Cache TTL in milliseconds (default: 30 minutes)
|
|
22
|
-
|
|
23
|
-
#### Defined in
|
|
24
|
-
|
|
25
|
-
[packages/core/src/hooks/public/usePublicEventLogo.ts:91](https://github.com/jmruthers/pace-core/blob/main/packages/core/src/hooks/public/usePublicEventLogo.ts#L91)
|
|
26
|
-
|
|
27
|
-
___
|
|
28
|
-
|
|
29
|
-
### enableCache
|
|
30
|
-
|
|
31
|
-
• `Optional` **enableCache**: `boolean`
|
|
32
|
-
|
|
33
|
-
Whether to enable caching (default: true)
|
|
34
|
-
|
|
35
|
-
#### Defined in
|
|
36
|
-
|
|
37
|
-
[packages/core/src/hooks/public/usePublicEventLogo.ts:93](https://github.com/jmruthers/pace-core/blob/main/packages/core/src/hooks/public/usePublicEventLogo.ts#L93)
|
|
38
|
-
|
|
39
|
-
___
|
|
40
|
-
|
|
41
|
-
### validateImage
|
|
42
|
-
|
|
43
|
-
• `Optional` **validateImage**: `boolean`
|
|
44
|
-
|
|
45
|
-
Whether to validate image existence (default: true)
|
|
46
|
-
|
|
47
|
-
#### Defined in
|
|
48
|
-
|
|
49
|
-
[packages/core/src/hooks/public/usePublicEventLogo.ts:95](https://github.com/jmruthers/pace-core/blob/main/packages/core/src/hooks/public/usePublicEventLogo.ts#L95)
|
|
50
|
-
|
|
51
|
-
___
|
|
52
|
-
|
|
53
|
-
### generateFallbackText
|
|
54
|
-
|
|
55
|
-
• `Optional` **generateFallbackText**: (`eventName`: `string`) => `string`
|
|
56
|
-
|
|
57
|
-
Custom fallback text generator
|
|
58
|
-
|
|
59
|
-
#### Type declaration
|
|
60
|
-
|
|
61
|
-
▸ (`eventName`): `string`
|
|
62
|
-
|
|
63
|
-
##### Parameters
|
|
64
|
-
|
|
65
|
-
| Name | Type |
|
|
66
|
-
| :------ | :------ |
|
|
67
|
-
| `eventName` | `string` |
|
|
68
|
-
|
|
69
|
-
##### Returns
|
|
70
|
-
|
|
71
|
-
`string`
|
|
72
|
-
|
|
73
|
-
#### Defined in
|
|
74
|
-
|
|
75
|
-
[packages/core/src/hooks/public/usePublicEventLogo.ts:97](https://github.com/jmruthers/pace-core/blob/main/packages/core/src/hooks/public/usePublicEventLogo.ts#L97)
|
|
76
|
-
|
|
77
|
-
___
|
|
78
|
-
|
|
79
|
-
### supabase
|
|
80
|
-
|
|
81
|
-
• **supabase**: `default`\<`Database`, ``"public"``, ``"public"``, `never`, {}\>
|
|
82
|
-
|
|
83
|
-
Supabase client instance (required)
|
|
84
|
-
|
|
85
|
-
#### Defined in
|
|
86
|
-
|
|
87
|
-
[packages/core/src/hooks/public/usePublicEventLogo.ts:99](https://github.com/jmruthers/pace-core/blob/main/packages/core/src/hooks/public/usePublicEventLogo.ts#L99)
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
[@jmruthers/pace-core - v0.5.101](../README.md) / [Exports](../modules.md) / UsePublicEventLogoReturn
|
|
2
|
-
|
|
3
|
-
# Interface: UsePublicEventLogoReturn
|
|
4
|
-
|
|
5
|
-
## Table of contents
|
|
6
|
-
|
|
7
|
-
### Properties
|
|
8
|
-
|
|
9
|
-
- [logoUrl](UsePublicEventLogoReturn.md#logourl)
|
|
10
|
-
- [fallbackText](UsePublicEventLogoReturn.md#fallbacktext)
|
|
11
|
-
- [isLoading](UsePublicEventLogoReturn.md#isloading)
|
|
12
|
-
- [error](UsePublicEventLogoReturn.md#error)
|
|
13
|
-
- [refetch](UsePublicEventLogoReturn.md#refetch)
|
|
14
|
-
|
|
15
|
-
## Properties
|
|
16
|
-
|
|
17
|
-
### logoUrl
|
|
18
|
-
|
|
19
|
-
• **logoUrl**: ``null`` \| `string`
|
|
20
|
-
|
|
21
|
-
The logo URL if available, null if not found or error
|
|
22
|
-
|
|
23
|
-
#### Defined in
|
|
24
|
-
|
|
25
|
-
[packages/core/src/hooks/public/usePublicEventLogo.ts:78](https://github.com/jmruthers/pace-core/blob/main/packages/core/src/hooks/public/usePublicEventLogo.ts#L78)
|
|
26
|
-
|
|
27
|
-
___
|
|
28
|
-
|
|
29
|
-
### fallbackText
|
|
30
|
-
|
|
31
|
-
• **fallbackText**: `string`
|
|
32
|
-
|
|
33
|
-
Fallback text (event initials) if no logo is available
|
|
34
|
-
|
|
35
|
-
#### Defined in
|
|
36
|
-
|
|
37
|
-
[packages/core/src/hooks/public/usePublicEventLogo.ts:80](https://github.com/jmruthers/pace-core/blob/main/packages/core/src/hooks/public/usePublicEventLogo.ts#L80)
|
|
38
|
-
|
|
39
|
-
___
|
|
40
|
-
|
|
41
|
-
### isLoading
|
|
42
|
-
|
|
43
|
-
• **isLoading**: `boolean`
|
|
44
|
-
|
|
45
|
-
Whether the logo is currently loading
|
|
46
|
-
|
|
47
|
-
#### Defined in
|
|
48
|
-
|
|
49
|
-
[packages/core/src/hooks/public/usePublicEventLogo.ts:82](https://github.com/jmruthers/pace-core/blob/main/packages/core/src/hooks/public/usePublicEventLogo.ts#L82)
|
|
50
|
-
|
|
51
|
-
___
|
|
52
|
-
|
|
53
|
-
### error
|
|
54
|
-
|
|
55
|
-
• **error**: ``null`` \| `Error`
|
|
56
|
-
|
|
57
|
-
Any error that occurred during loading
|
|
58
|
-
|
|
59
|
-
#### Defined in
|
|
60
|
-
|
|
61
|
-
[packages/core/src/hooks/public/usePublicEventLogo.ts:84](https://github.com/jmruthers/pace-core/blob/main/packages/core/src/hooks/public/usePublicEventLogo.ts#L84)
|
|
62
|
-
|
|
63
|
-
___
|
|
64
|
-
|
|
65
|
-
### refetch
|
|
66
|
-
|
|
67
|
-
• **refetch**: () => `Promise`\<`void`\>
|
|
68
|
-
|
|
69
|
-
Function to manually refetch the logo
|
|
70
|
-
|
|
71
|
-
#### Type declaration
|
|
72
|
-
|
|
73
|
-
▸ (): `Promise`\<`void`\>
|
|
74
|
-
|
|
75
|
-
##### Returns
|
|
76
|
-
|
|
77
|
-
`Promise`\<`void`\>
|
|
78
|
-
|
|
79
|
-
#### Defined in
|
|
80
|
-
|
|
81
|
-
[packages/core/src/hooks/public/usePublicEventLogo.ts:86](https://github.com/jmruthers/pace-core/blob/main/packages/core/src/hooks/public/usePublicEventLogo.ts#L86)
|
|
@@ -1,474 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file Event Logo Component
|
|
3
|
-
* @package @jmruthers/pace-core
|
|
4
|
-
* @module Components/PublicLayout
|
|
5
|
-
* @since 1.0.0
|
|
6
|
-
*
|
|
7
|
-
* A context-aware component for displaying event logos with automatic fallback to event initials.
|
|
8
|
-
* Automatically detects whether it's being used in a public or authenticated context and behaves
|
|
9
|
-
* appropriately without triggering authentication context leakage.
|
|
10
|
-
*
|
|
11
|
-
* Features:
|
|
12
|
-
* - Context-aware (works in both public and authenticated contexts)
|
|
13
|
-
* - Automatic fallback to event initials
|
|
14
|
-
* - Logo validation and error handling
|
|
15
|
-
* - Multiple size options
|
|
16
|
-
* - Responsive design
|
|
17
|
-
* - Accessibility compliant
|
|
18
|
-
* - TypeScript support
|
|
19
|
-
*
|
|
20
|
-
* @example
|
|
21
|
-
* ```tsx
|
|
22
|
-
* import { EventLogo } from '@jmruthers/pace-core';
|
|
23
|
-
*
|
|
24
|
-
* function EventHeader() {
|
|
25
|
-
* return (
|
|
26
|
-
* <EventLogo
|
|
27
|
-
* eventId={event.id}
|
|
28
|
-
* eventName={event.event_name}
|
|
29
|
-
* organisationId={event.organisation_id}
|
|
30
|
-
* size="lg"
|
|
31
|
-
* className="rounded-full"
|
|
32
|
-
* />
|
|
33
|
-
* );
|
|
34
|
-
* }
|
|
35
|
-
* ```
|
|
36
|
-
*
|
|
37
|
-
* @accessibility
|
|
38
|
-
* - WCAG 2.1 AA compliant
|
|
39
|
-
* - Proper alt text for images
|
|
40
|
-
* - Screen reader friendly fallbacks
|
|
41
|
-
* - High contrast support
|
|
42
|
-
*
|
|
43
|
-
* @dependencies
|
|
44
|
-
* - React 18+ - Component framework
|
|
45
|
-
* - usePublicEventLogo hook - Logo data access
|
|
46
|
-
* - Tailwind CSS - Styling
|
|
47
|
-
*/
|
|
48
|
-
|
|
49
|
-
import React, { useMemo, useContext } from 'react';
|
|
50
|
-
import { usePublicEventLogo } from '../../hooks/public/usePublicEventLogo';
|
|
51
|
-
import { useEventLogo } from '../../hooks/useEventLogo';
|
|
52
|
-
import { PublicPageContext, useIsPublicPage } from './PublicPageProvider';
|
|
53
|
-
import { useUnifiedAuth } from '../../providers/services/UnifiedAuthProvider';
|
|
54
|
-
import type { SupabaseClient } from '@supabase/supabase-js';
|
|
55
|
-
import type { Database } from '../../types/database';
|
|
56
|
-
|
|
57
|
-
export interface EventLogoProps {
|
|
58
|
-
/** The event ID to fetch logo for */
|
|
59
|
-
eventId: string;
|
|
60
|
-
/** The event name for fallback text generation */
|
|
61
|
-
eventName: string;
|
|
62
|
-
/** The organisation ID for storage path */
|
|
63
|
-
organisationId: string;
|
|
64
|
-
/** Logo size variant */
|
|
65
|
-
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl';
|
|
66
|
-
/** Custom CSS classes */
|
|
67
|
-
className?: string;
|
|
68
|
-
/** Whether to show fallback text when no logo is available */
|
|
69
|
-
showFallback?: boolean;
|
|
70
|
-
/** Custom fallback text generator */
|
|
71
|
-
generateFallbackText?: (eventName: string) => string;
|
|
72
|
-
/** Whether to validate image existence */
|
|
73
|
-
validateImage?: boolean;
|
|
74
|
-
/** Custom loading component */
|
|
75
|
-
loadingComponent?: React.ComponentType;
|
|
76
|
-
/** Custom error component */
|
|
77
|
-
errorComponent?: React.ComponentType<{ error: Error }>;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Size classes for different logo sizes
|
|
82
|
-
*/
|
|
83
|
-
const sizeClasses = {
|
|
84
|
-
xs: 'h-4 w-4 text-xs',
|
|
85
|
-
sm: 'h-6 w-6 text-sm',
|
|
86
|
-
md: 'h-8 w-8 text-base',
|
|
87
|
-
lg: 'h-12 w-12 text-lg',
|
|
88
|
-
xl: 'h-16 w-16 text-xl',
|
|
89
|
-
'2xl': 'h-20 w-20 text-2xl'
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Default fallback text generator
|
|
94
|
-
*/
|
|
95
|
-
function defaultGenerateFallbackText(eventName: string): string {
|
|
96
|
-
if (!eventName) return 'EV';
|
|
97
|
-
|
|
98
|
-
return eventName
|
|
99
|
-
.split(' ')
|
|
100
|
-
.map(word => word.charAt(0).toUpperCase())
|
|
101
|
-
.join('')
|
|
102
|
-
.substring(0, 3); // Max 3 characters
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Component for displaying event logos with fallback to initials
|
|
107
|
-
*
|
|
108
|
-
* This component is context-aware and automatically detects whether it's being used
|
|
109
|
-
* in a public or authenticated context. It fetches and displays event logos from storage,
|
|
110
|
-
* with automatic fallback to event initials if no logo is available.
|
|
111
|
-
*
|
|
112
|
-
* @param props - Logo configuration and styling
|
|
113
|
-
* @returns React element with event logo or fallback
|
|
114
|
-
*/
|
|
115
|
-
/**
|
|
116
|
-
* Internal component for public page context
|
|
117
|
-
* Uses PublicPageContext to get Supabase client
|
|
118
|
-
*/
|
|
119
|
-
function EventLogoPublic({
|
|
120
|
-
eventId,
|
|
121
|
-
eventName,
|
|
122
|
-
organisationId,
|
|
123
|
-
size,
|
|
124
|
-
className,
|
|
125
|
-
showFallback,
|
|
126
|
-
generateFallbackText,
|
|
127
|
-
validateImage,
|
|
128
|
-
LoadingComponent,
|
|
129
|
-
ErrorComponent
|
|
130
|
-
}: EventLogoProps & { LoadingComponent?: React.ComponentType; ErrorComponent?: React.ComponentType<{ error: Error }> }) {
|
|
131
|
-
const publicPageContext = useContext(PublicPageContext);
|
|
132
|
-
const supabase = publicPageContext?.supabase ?? null;
|
|
133
|
-
|
|
134
|
-
// Validate UUID format for organisationId to prevent database errors
|
|
135
|
-
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
136
|
-
const hasValidOrganisationId = organisationId && uuidRegex.test(organisationId);
|
|
137
|
-
|
|
138
|
-
// If no Supabase client is available, show fallback immediately
|
|
139
|
-
if (!supabase) {
|
|
140
|
-
const effectiveSize = size || 'md';
|
|
141
|
-
return (
|
|
142
|
-
<div className={`${sizeClasses[effectiveSize]} ${className}`.trim()} title={`${eventName} logo (Supabase not configured)`}>
|
|
143
|
-
{eventName ? defaultGenerateFallbackText(eventName) : 'EV'}
|
|
144
|
-
</div>
|
|
145
|
-
);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
const {
|
|
149
|
-
logoUrl,
|
|
150
|
-
fallbackText,
|
|
151
|
-
isLoading,
|
|
152
|
-
error
|
|
153
|
-
} = usePublicEventLogo(
|
|
154
|
-
eventId,
|
|
155
|
-
eventName,
|
|
156
|
-
organisationId, // Always pass organisationId, let the hook handle validation
|
|
157
|
-
{
|
|
158
|
-
validateImage,
|
|
159
|
-
generateFallbackText,
|
|
160
|
-
supabase
|
|
161
|
-
}
|
|
162
|
-
);
|
|
163
|
-
|
|
164
|
-
// Memoize the size classes - provide default 'md' if size is undefined
|
|
165
|
-
const sizeClass = useMemo(() => sizeClasses[size || 'md'], [size]);
|
|
166
|
-
|
|
167
|
-
// Memoize the combined classes
|
|
168
|
-
const combinedClasses = useMemo(() => {
|
|
169
|
-
const baseClasses = 'flex items-center justify-center bg-gray-100 text-gray-600 font-semibold rounded';
|
|
170
|
-
return `${baseClasses} ${sizeClass} ${className}`.trim();
|
|
171
|
-
}, [sizeClass, className]);
|
|
172
|
-
|
|
173
|
-
// Handle invalid organisation ID - show fallback immediately only if we have no data
|
|
174
|
-
if (!hasValidOrganisationId && !isLoading && !logoUrl && showFallback) {
|
|
175
|
-
return (
|
|
176
|
-
<div className={combinedClasses} title={`${eventName} logo (invalid organisation ID)`}>
|
|
177
|
-
{fallbackText}
|
|
178
|
-
</div>
|
|
179
|
-
);
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
// Handle loading state
|
|
183
|
-
if (isLoading) {
|
|
184
|
-
if (LoadingComponent) {
|
|
185
|
-
return <LoadingComponent />;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
return (
|
|
189
|
-
<div className={`${combinedClasses} animate-pulse`}>
|
|
190
|
-
<div className="w-3/4 h-3/4 bg-gray-300 rounded"></div>
|
|
191
|
-
</div>
|
|
192
|
-
);
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
// Handle error state
|
|
196
|
-
if (error) {
|
|
197
|
-
if (ErrorComponent) {
|
|
198
|
-
return <ErrorComponent error={error} />;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
if (showFallback) {
|
|
202
|
-
return (
|
|
203
|
-
<div className={combinedClasses} title={`${eventName} (logo unavailable)`}>
|
|
204
|
-
{fallbackText}
|
|
205
|
-
</div>
|
|
206
|
-
);
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
return null;
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
// Handle no logo available
|
|
213
|
-
if (!logoUrl) {
|
|
214
|
-
if (showFallback) {
|
|
215
|
-
return (
|
|
216
|
-
<div className={combinedClasses} title={`${eventName} logo`}>
|
|
217
|
-
{fallbackText}
|
|
218
|
-
</div>
|
|
219
|
-
);
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
return null;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
// Render the actual logo
|
|
226
|
-
// Apply object-contain to maintain aspect ratio and rounded to match fallback styling
|
|
227
|
-
const imageClasses = `${sizeClass} object-contain rounded ${className}`.trim();
|
|
228
|
-
|
|
229
|
-
return (
|
|
230
|
-
<img
|
|
231
|
-
src={logoUrl}
|
|
232
|
-
alt={`${eventName} logo`}
|
|
233
|
-
className={imageClasses}
|
|
234
|
-
onError={(e) => {
|
|
235
|
-
// If image fails to load, hide it and show fallback
|
|
236
|
-
const target = e.target as HTMLImageElement;
|
|
237
|
-
target.style.display = 'none';
|
|
238
|
-
|
|
239
|
-
// Create fallback element
|
|
240
|
-
const fallback = document.createElement('div');
|
|
241
|
-
fallback.className = combinedClasses;
|
|
242
|
-
fallback.textContent = fallbackText;
|
|
243
|
-
fallback.title = `${eventName} logo`;
|
|
244
|
-
|
|
245
|
-
// Insert fallback after the image
|
|
246
|
-
target.parentNode?.insertBefore(fallback, target.nextSibling);
|
|
247
|
-
}}
|
|
248
|
-
/>
|
|
249
|
-
);
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
/**
|
|
253
|
-
* Internal component for authenticated page context
|
|
254
|
-
* Uses UnifiedAuthProvider to get Supabase client
|
|
255
|
-
*/
|
|
256
|
-
function EventLogoAuthenticated({
|
|
257
|
-
eventId,
|
|
258
|
-
eventName,
|
|
259
|
-
organisationId,
|
|
260
|
-
size,
|
|
261
|
-
className,
|
|
262
|
-
showFallback,
|
|
263
|
-
generateFallbackText,
|
|
264
|
-
validateImage,
|
|
265
|
-
LoadingComponent,
|
|
266
|
-
ErrorComponent
|
|
267
|
-
}: EventLogoProps & { LoadingComponent?: React.ComponentType; ErrorComponent?: React.ComponentType<{ error: Error }> }) {
|
|
268
|
-
const { supabase } = useUnifiedAuth();
|
|
269
|
-
|
|
270
|
-
// Validate UUID format for organisationId to prevent database errors
|
|
271
|
-
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
272
|
-
const hasValidOrganisationId = organisationId && uuidRegex.test(organisationId);
|
|
273
|
-
|
|
274
|
-
// If no Supabase client is available, show fallback immediately
|
|
275
|
-
if (!supabase) {
|
|
276
|
-
const effectiveSize = size || 'md';
|
|
277
|
-
return (
|
|
278
|
-
<div className={`${sizeClasses[effectiveSize]} ${className}`.trim()} title={`${eventName} logo (Supabase not configured)`}>
|
|
279
|
-
{eventName ? defaultGenerateFallbackText(eventName) : 'EV'}
|
|
280
|
-
</div>
|
|
281
|
-
);
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
// Use the authenticated event logo hook (supports both public and private logos)
|
|
285
|
-
const {
|
|
286
|
-
logoUrl,
|
|
287
|
-
fallbackText,
|
|
288
|
-
isLoading,
|
|
289
|
-
error
|
|
290
|
-
} = useEventLogo(
|
|
291
|
-
supabase,
|
|
292
|
-
eventId,
|
|
293
|
-
eventName,
|
|
294
|
-
organisationId,
|
|
295
|
-
{
|
|
296
|
-
validateImage,
|
|
297
|
-
generateFallbackText
|
|
298
|
-
}
|
|
299
|
-
);
|
|
300
|
-
|
|
301
|
-
// Memoize the size classes - provide default 'md' if size is undefined
|
|
302
|
-
const sizeClass = useMemo(() => sizeClasses[size || 'md'], [size]);
|
|
303
|
-
|
|
304
|
-
// Memoize the combined classes
|
|
305
|
-
const combinedClasses = useMemo(() => {
|
|
306
|
-
const baseClasses = 'flex items-center justify-center bg-gray-100 text-gray-600 font-semibold rounded';
|
|
307
|
-
return `${baseClasses} ${sizeClass} ${className}`.trim();
|
|
308
|
-
}, [sizeClass, className]);
|
|
309
|
-
|
|
310
|
-
// Handle invalid organisation ID - show fallback immediately only if we have no data
|
|
311
|
-
if (!hasValidOrganisationId && !isLoading && !logoUrl && showFallback) {
|
|
312
|
-
return (
|
|
313
|
-
<div className={combinedClasses} title={`${eventName} logo (invalid organisation ID)`}>
|
|
314
|
-
{fallbackText}
|
|
315
|
-
</div>
|
|
316
|
-
);
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
// Handle loading state
|
|
320
|
-
if (isLoading) {
|
|
321
|
-
if (LoadingComponent) {
|
|
322
|
-
return <LoadingComponent />;
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
return (
|
|
326
|
-
<div className={`${combinedClasses} animate-pulse`}>
|
|
327
|
-
<div className="w-3/4 h-3/4 bg-gray-300 rounded"></div>
|
|
328
|
-
</div>
|
|
329
|
-
);
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
// Handle error state
|
|
333
|
-
if (error) {
|
|
334
|
-
if (ErrorComponent) {
|
|
335
|
-
return <ErrorComponent error={error} />;
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
if (showFallback) {
|
|
339
|
-
return (
|
|
340
|
-
<div className={combinedClasses} title={`${eventName} (logo unavailable)`}>
|
|
341
|
-
{fallbackText}
|
|
342
|
-
</div>
|
|
343
|
-
);
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
return null;
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
// Handle no logo available
|
|
350
|
-
if (!logoUrl) {
|
|
351
|
-
if (showFallback) {
|
|
352
|
-
return (
|
|
353
|
-
<div className={combinedClasses} title={`${eventName} logo`}>
|
|
354
|
-
{fallbackText}
|
|
355
|
-
</div>
|
|
356
|
-
);
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
return null;
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
// Render the actual logo
|
|
363
|
-
// Apply object-contain to maintain aspect ratio and rounded to match fallback styling
|
|
364
|
-
const imageClasses = `${sizeClass} object-contain rounded ${className}`.trim();
|
|
365
|
-
|
|
366
|
-
return (
|
|
367
|
-
<img
|
|
368
|
-
src={logoUrl}
|
|
369
|
-
alt={`${eventName} logo`}
|
|
370
|
-
className={imageClasses}
|
|
371
|
-
onError={(e) => {
|
|
372
|
-
// If image fails to load, hide it and show fallback
|
|
373
|
-
const target = e.target as HTMLImageElement;
|
|
374
|
-
target.style.display = 'none';
|
|
375
|
-
|
|
376
|
-
// Create fallback element
|
|
377
|
-
const fallback = document.createElement('div');
|
|
378
|
-
fallback.className = combinedClasses;
|
|
379
|
-
fallback.textContent = fallbackText;
|
|
380
|
-
fallback.title = `${eventName} logo`;
|
|
381
|
-
|
|
382
|
-
// Insert fallback after the image
|
|
383
|
-
target.parentNode?.insertBefore(fallback, target.nextSibling);
|
|
384
|
-
}}
|
|
385
|
-
/>
|
|
386
|
-
);
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
/**
|
|
390
|
-
* Component for displaying event logos with fallback to initials
|
|
391
|
-
*
|
|
392
|
-
* This component is context-aware and automatically detects whether it's being used
|
|
393
|
-
* in a public or authenticated context. It fetches and displays event logos from storage,
|
|
394
|
-
* with automatic fallback to event initials if no logo is available.
|
|
395
|
-
*
|
|
396
|
-
* @param props - Logo configuration and styling
|
|
397
|
-
* @returns React element with event logo or fallback
|
|
398
|
-
*/
|
|
399
|
-
export function EventLogo({
|
|
400
|
-
eventId,
|
|
401
|
-
eventName,
|
|
402
|
-
organisationId,
|
|
403
|
-
size = 'md',
|
|
404
|
-
className = '',
|
|
405
|
-
showFallback = true,
|
|
406
|
-
generateFallbackText = defaultGenerateFallbackText,
|
|
407
|
-
validateImage = true,
|
|
408
|
-
loadingComponent: LoadingComponent,
|
|
409
|
-
errorComponent: ErrorComponent
|
|
410
|
-
}: EventLogoProps) {
|
|
411
|
-
// Check which context we're in and route to the appropriate component
|
|
412
|
-
const isPublicPage = useIsPublicPage();
|
|
413
|
-
|
|
414
|
-
// If we're in a public page context, use the public component
|
|
415
|
-
if (isPublicPage) {
|
|
416
|
-
return (
|
|
417
|
-
<EventLogoPublic
|
|
418
|
-
eventId={eventId}
|
|
419
|
-
eventName={eventName}
|
|
420
|
-
organisationId={organisationId}
|
|
421
|
-
size={size}
|
|
422
|
-
className={className}
|
|
423
|
-
showFallback={showFallback}
|
|
424
|
-
generateFallbackText={generateFallbackText}
|
|
425
|
-
validateImage={validateImage}
|
|
426
|
-
LoadingComponent={LoadingComponent}
|
|
427
|
-
ErrorComponent={ErrorComponent}
|
|
428
|
-
/>
|
|
429
|
-
);
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
// Otherwise, try to use the authenticated component
|
|
433
|
-
// It will throw if not in UnifiedAuthProvider, which will be caught by error boundary
|
|
434
|
-
return (
|
|
435
|
-
<EventLogoAuthenticated
|
|
436
|
-
eventId={eventId}
|
|
437
|
-
eventName={eventName}
|
|
438
|
-
organisationId={organisationId}
|
|
439
|
-
size={size}
|
|
440
|
-
className={className}
|
|
441
|
-
showFallback={showFallback}
|
|
442
|
-
generateFallbackText={generateFallbackText}
|
|
443
|
-
validateImage={validateImage}
|
|
444
|
-
LoadingComponent={LoadingComponent}
|
|
445
|
-
ErrorComponent={ErrorComponent}
|
|
446
|
-
/>
|
|
447
|
-
);
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
/**
|
|
451
|
-
* Compact event logo for small spaces
|
|
452
|
-
*/
|
|
453
|
-
export function EventLogoCompact(props: EventLogoProps) {
|
|
454
|
-
return (
|
|
455
|
-
<EventLogo
|
|
456
|
-
{...props}
|
|
457
|
-
size="sm"
|
|
458
|
-
className={`${props.className || ''} rounded-sm`}
|
|
459
|
-
/>
|
|
460
|
-
);
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
/**
|
|
464
|
-
* Large event logo for prominent display
|
|
465
|
-
*/
|
|
466
|
-
export function EventLogoLarge(props: EventLogoProps) {
|
|
467
|
-
return (
|
|
468
|
-
<EventLogo
|
|
469
|
-
{...props}
|
|
470
|
-
size="xl"
|
|
471
|
-
className={`${props.className || ''} rounded-lg`}
|
|
472
|
-
/>
|
|
473
|
-
);
|
|
474
|
-
}
|