@jmruthers/pace-core 0.5.88 → 0.5.90

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.
Files changed (159) hide show
  1. package/dist/{AuthService-DcTI5Ov4.d.ts → AuthService-DX15wM6y.d.ts} +8 -0
  2. package/dist/{DataTable-PWBMKMOG.js → DataTable-VIP44OB6.js} +7 -6
  3. package/dist/{UnifiedAuthProvider-5D3HEQND.js → UnifiedAuthProvider-6JRTOFPS.js} +4 -3
  4. package/dist/{chunk-BNXBJOGL.js → chunk-4DYK5KCK.js} +4 -4
  5. package/dist/{chunk-XXVM53P4.js → chunk-7NIERLC6.js} +8 -8
  6. package/dist/{chunk-XXVM53P4.js.map → chunk-7NIERLC6.js.map} +1 -1
  7. package/dist/{chunk-KTPG5VCH.js → chunk-7XBW2P7B.js} +2 -2
  8. package/dist/{chunk-DP5X5ORK.js → chunk-AIV3VYBQ.js} +82 -25
  9. package/dist/chunk-AIV3VYBQ.js.map +1 -0
  10. package/dist/{chunk-CJIZS3UE.js → chunk-EWMXLDIX.js} +19 -15
  11. package/dist/chunk-EWMXLDIX.js.map +1 -0
  12. package/dist/{chunk-YY4YYM3E.js → chunk-G2SCPUKC.js} +2 -2
  13. package/dist/{chunk-CXKMRKRF.js → chunk-G2YT64FA.js} +3 -3
  14. package/dist/{chunk-AQGF5OG7.js → chunk-GD3ENUKD.js} +3 -3
  15. package/dist/{chunk-H3P2RGKZ.js → chunk-JDPFQV3V.js} +55 -6
  16. package/dist/chunk-JDPFQV3V.js.map +1 -0
  17. package/dist/{chunk-3RZBKQ5Y.js → chunk-JQWSAYZC.js} +2 -2
  18. package/dist/{chunk-A6HBIY5P.js → chunk-SMJZMKYN.js} +11 -2
  19. package/dist/{chunk-A6HBIY5P.js.map → chunk-SMJZMKYN.js.map} +1 -1
  20. package/dist/{chunk-L3RV2ALE.js → chunk-VKOCWWVY.js} +6 -1
  21. package/dist/{chunk-L3RV2ALE.js.map → chunk-VKOCWWVY.js.map} +1 -1
  22. package/dist/{chunk-6UHXQH7P.js → chunk-XZHZYSAK.js} +5 -5
  23. package/dist/components.js +9 -8
  24. package/dist/components.js.map +1 -1
  25. package/dist/hooks.js +8 -8
  26. package/dist/index.d.ts +2 -2
  27. package/dist/index.js +13 -13
  28. package/dist/providers.d.ts +2 -2
  29. package/dist/providers.js +3 -2
  30. package/dist/rbac/index.js +8 -7
  31. package/dist/styles/index.js +2 -2
  32. package/dist/theming/runtime.js +3 -1
  33. package/dist/utils.js +1 -1
  34. package/docs/api/classes/ColumnFactory.md +1 -1
  35. package/docs/api/classes/ErrorBoundary.md +1 -1
  36. package/docs/api/classes/InvalidScopeError.md +1 -1
  37. package/docs/api/classes/MissingUserContextError.md +1 -1
  38. package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
  39. package/docs/api/classes/PermissionDeniedError.md +1 -1
  40. package/docs/api/classes/PublicErrorBoundary.md +1 -1
  41. package/docs/api/classes/RBACAuditManager.md +1 -1
  42. package/docs/api/classes/RBACCache.md +1 -1
  43. package/docs/api/classes/RBACEngine.md +1 -1
  44. package/docs/api/classes/RBACError.md +1 -1
  45. package/docs/api/classes/RBACNotInitializedError.md +1 -1
  46. package/docs/api/classes/SecureSupabaseClient.md +1 -1
  47. package/docs/api/classes/StorageUtils.md +1 -1
  48. package/docs/api/enums/FileCategory.md +1 -1
  49. package/docs/api/interfaces/AggregateConfig.md +1 -1
  50. package/docs/api/interfaces/ButtonProps.md +1 -1
  51. package/docs/api/interfaces/CardProps.md +1 -1
  52. package/docs/api/interfaces/ColorPalette.md +1 -1
  53. package/docs/api/interfaces/ColorShade.md +1 -1
  54. package/docs/api/interfaces/DataAccessRecord.md +1 -1
  55. package/docs/api/interfaces/DataRecord.md +1 -1
  56. package/docs/api/interfaces/DataTableAction.md +1 -1
  57. package/docs/api/interfaces/DataTableColumn.md +1 -1
  58. package/docs/api/interfaces/DataTableProps.md +1 -1
  59. package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
  60. package/docs/api/interfaces/EmptyStateConfig.md +1 -1
  61. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  62. package/docs/api/interfaces/EventLogoProps.md +1 -1
  63. package/docs/api/interfaces/FileDisplayProps.md +1 -1
  64. package/docs/api/interfaces/FileMetadata.md +1 -1
  65. package/docs/api/interfaces/FileReference.md +1 -1
  66. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  67. package/docs/api/interfaces/FileUploadOptions.md +1 -1
  68. package/docs/api/interfaces/FileUploadProps.md +1 -1
  69. package/docs/api/interfaces/FooterProps.md +1 -1
  70. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  71. package/docs/api/interfaces/InputProps.md +1 -1
  72. package/docs/api/interfaces/LabelProps.md +1 -1
  73. package/docs/api/interfaces/LoginFormProps.md +1 -1
  74. package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
  75. package/docs/api/interfaces/NavigationContextType.md +1 -1
  76. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  77. package/docs/api/interfaces/NavigationItem.md +1 -1
  78. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  79. package/docs/api/interfaces/NavigationProviderProps.md +1 -1
  80. package/docs/api/interfaces/Organisation.md +1 -1
  81. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  82. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  83. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  84. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  85. package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
  86. package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
  87. package/docs/api/interfaces/PageAccessRecord.md +1 -1
  88. package/docs/api/interfaces/PagePermissionContextType.md +1 -1
  89. package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
  90. package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
  91. package/docs/api/interfaces/PaletteData.md +1 -1
  92. package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
  93. package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
  94. package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
  95. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
  96. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  97. package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
  98. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  99. package/docs/api/interfaces/RBACConfig.md +1 -1
  100. package/docs/api/interfaces/RBACLogger.md +1 -1
  101. package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
  102. package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
  103. package/docs/api/interfaces/RouteAccessRecord.md +1 -1
  104. package/docs/api/interfaces/RouteConfig.md +1 -1
  105. package/docs/api/interfaces/SecureDataContextType.md +1 -1
  106. package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
  107. package/docs/api/interfaces/StorageConfig.md +1 -1
  108. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  109. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  110. package/docs/api/interfaces/StorageListOptions.md +1 -1
  111. package/docs/api/interfaces/StorageListResult.md +1 -1
  112. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  113. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  114. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  115. package/docs/api/interfaces/StyleImport.md +1 -1
  116. package/docs/api/interfaces/SwitchProps.md +1 -1
  117. package/docs/api/interfaces/ToastActionElement.md +1 -1
  118. package/docs/api/interfaces/ToastProps.md +1 -1
  119. package/docs/api/interfaces/UnifiedAuthContextType.md +1 -1
  120. package/docs/api/interfaces/UnifiedAuthProviderProps.md +1 -1
  121. package/docs/api/interfaces/UseEventLogoOptions.md +1 -1
  122. package/docs/api/interfaces/UseEventLogoReturn.md +1 -1
  123. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  124. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  125. package/docs/api/interfaces/UsePublicEventLogoOptions.md +1 -1
  126. package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
  127. package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
  128. package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
  129. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  130. package/docs/api/interfaces/UseResolvedScopeOptions.md +1 -1
  131. package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
  132. package/docs/api/interfaces/UserEventAccess.md +1 -1
  133. package/docs/api/interfaces/UserMenuProps.md +1 -1
  134. package/docs/api/interfaces/UserProfile.md +1 -1
  135. package/docs/api/modules.md +9 -9
  136. package/docs/implementation-guides/public-pages-advanced.md +10 -0
  137. package/package.json +1 -1
  138. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +10 -0
  139. package/src/components/PaceLoginPage/PaceLoginPage.tsx +20 -14
  140. package/src/hooks/public/usePublicEvent.ts +0 -2
  141. package/src/services/AuthService.ts +29 -29
  142. package/src/services/EventService.ts +65 -0
  143. package/src/services/__tests__/AuthService.restoreSession.test.ts +35 -0
  144. package/src/services/__tests__/AuthService.test.ts +6 -7
  145. package/src/services/__tests__/EventService.eventColours.test.ts +72 -0
  146. package/src/utils/storage/helpers.test.ts +107 -3
  147. package/src/utils/storage/helpers.ts +80 -5
  148. package/dist/chunk-CJIZS3UE.js.map +0 -1
  149. package/dist/chunk-DP5X5ORK.js.map +0 -1
  150. package/dist/chunk-H3P2RGKZ.js.map +0 -1
  151. /package/dist/{DataTable-PWBMKMOG.js.map → DataTable-VIP44OB6.js.map} +0 -0
  152. /package/dist/{UnifiedAuthProvider-5D3HEQND.js.map → UnifiedAuthProvider-6JRTOFPS.js.map} +0 -0
  153. /package/dist/{chunk-BNXBJOGL.js.map → chunk-4DYK5KCK.js.map} +0 -0
  154. /package/dist/{chunk-KTPG5VCH.js.map → chunk-7XBW2P7B.js.map} +0 -0
  155. /package/dist/{chunk-YY4YYM3E.js.map → chunk-G2SCPUKC.js.map} +0 -0
  156. /package/dist/{chunk-CXKMRKRF.js.map → chunk-G2YT64FA.js.map} +0 -0
  157. /package/dist/{chunk-AQGF5OG7.js.map → chunk-GD3ENUKD.js.map} +0 -0
  158. /package/dist/{chunk-3RZBKQ5Y.js.map → chunk-JQWSAYZC.js.map} +0 -0
  159. /package/dist/{chunk-6UHXQH7P.js.map → chunk-XZHZYSAK.js.map} +0 -0
@@ -4,7 +4,7 @@ import {
4
4
  init_InactivityServiceProvider,
5
5
  init_OrganisationServiceProvider,
6
6
  init_UnifiedAuthProvider
7
- } from "./chunk-DP5X5ORK.js";
7
+ } from "./chunk-AIV3VYBQ.js";
8
8
 
9
9
  // src/providers/index.ts
10
10
  init_UnifiedAuthProvider();
@@ -12,4 +12,4 @@ init_EventServiceProvider();
12
12
  init_OrganisationServiceProvider();
13
13
  init_InactivityServiceProvider();
14
14
  init_AuthServiceProvider();
15
- //# sourceMappingURL=chunk-YY4YYM3E.js.map
15
+ //# sourceMappingURL=chunk-G2SCPUKC.js.map
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  init_useOrganisations,
3
3
  useOrganisations
4
- } from "./chunk-3RZBKQ5Y.js";
4
+ } from "./chunk-JQWSAYZC.js";
5
5
  import {
6
6
  useUnifiedAuth
7
- } from "./chunk-DP5X5ORK.js";
7
+ } from "./chunk-AIV3VYBQ.js";
8
8
  import {
9
9
  init_organisationContext,
10
10
  setOrganisationContext
@@ -380,4 +380,4 @@ function useSecureDataAccess() {
380
380
  export {
381
381
  useSecureDataAccess
382
382
  };
383
- //# sourceMappingURL=chunk-CXKMRKRF.js.map
383
+ //# sourceMappingURL=chunk-G2YT64FA.js.map
@@ -11,11 +11,11 @@ import {
11
11
  init_useOrganisations,
12
12
  useEvents,
13
13
  useOrganisations
14
- } from "./chunk-3RZBKQ5Y.js";
14
+ } from "./chunk-JQWSAYZC.js";
15
15
  import {
16
16
  init_UnifiedAuthProvider,
17
17
  useUnifiedAuth
18
- } from "./chunk-DP5X5ORK.js";
18
+ } from "./chunk-AIV3VYBQ.js";
19
19
  import {
20
20
  getCurrentAppName
21
21
  } from "./chunk-JCQZ6LA7.js";
@@ -729,4 +729,4 @@ export {
729
729
  useHasAllPermissions,
730
730
  useCachedPermissions
731
731
  };
732
- //# sourceMappingURL=chunk-AQGF5OG7.js.map
732
+ //# sourceMappingURL=chunk-GD3ENUKD.js.map
@@ -1,17 +1,17 @@
1
1
  import {
2
2
  init_useOrganisations,
3
3
  useOrganisations
4
- } from "./chunk-3RZBKQ5Y.js";
4
+ } from "./chunk-JQWSAYZC.js";
5
5
  import {
6
6
  init_UnifiedAuthProvider
7
- } from "./chunk-KTPG5VCH.js";
7
+ } from "./chunk-7XBW2P7B.js";
8
8
  import {
9
9
  OrganisationServiceContext,
10
10
  OrganisationServiceProvider,
11
11
  init_OrganisationServiceProvider,
12
12
  useOrganisationService,
13
13
  useUnifiedAuth
14
- } from "./chunk-DP5X5ORK.js";
14
+ } from "./chunk-AIV3VYBQ.js";
15
15
  import {
16
16
  __esm,
17
17
  __export
@@ -465,10 +465,59 @@ async function uploadFile(supabase, file, options) {
465
465
  }
466
466
  }
467
467
  function getPublicUrl(supabase, path, isPublic = true) {
468
- const bucketName = getBucketName(isPublic);
469
- const { data } = supabase.storage.from(bucketName).getPublicUrl(path);
468
+ if (!supabase) {
469
+ throw new Error("Supabase client is required to generate a public URL");
470
+ }
471
+ if (!path || typeof path !== "string") {
472
+ throw new Error("A valid storage path is required to generate a public URL");
473
+ }
474
+ if (/^https?:\/\//i.test(path)) {
475
+ return path;
476
+ }
477
+ let normalisedPath = path.trim().replace(/^\/+/, "");
478
+ if (!normalisedPath) {
479
+ throw new Error("Storage path cannot be empty after normalisation");
480
+ }
481
+ const { bucketNameFromPath, storagePath } = resolveBucketHint(normalisedPath);
482
+ const bucketName = bucketNameFromPath || getBucketName(isPublic);
483
+ const { data } = supabase.storage.from(bucketName).getPublicUrl(storagePath);
470
484
  return data.publicUrl;
471
485
  }
486
+ function resolveBucketHint(pathWithPotentialBucket) {
487
+ const BUCKET_NAME_PATTERN = /^[a-z0-9][a-z0-9-_\.]{1,62}$/i;
488
+ const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
489
+ const KNOWN_BUCKET_NAMES = /* @__PURE__ */ new Set(["files", "public-files"]);
490
+ const trimmedPath = pathWithPotentialBucket.trim();
491
+ if (!trimmedPath) {
492
+ throw new Error("Storage path cannot be empty after normalisation");
493
+ }
494
+ const doubleColonIndex = trimmedPath.indexOf("::");
495
+ if (doubleColonIndex > 0) {
496
+ const potentialBucket = trimmedPath.slice(0, doubleColonIndex).trim();
497
+ const remainingPath = trimmedPath.slice(doubleColonIndex + 2).replace(/^\/+/, "");
498
+ if (potentialBucket && remainingPath && BUCKET_NAME_PATTERN.test(potentialBucket)) {
499
+ return {
500
+ bucketNameFromPath: potentialBucket,
501
+ storagePath: remainingPath
502
+ };
503
+ }
504
+ }
505
+ const firstSlashIndex = trimmedPath.indexOf("/");
506
+ if (firstSlashIndex > 0) {
507
+ const potentialBucket = trimmedPath.slice(0, firstSlashIndex).trim();
508
+ const remainingPath = trimmedPath.slice(firstSlashIndex + 1).replace(/^\/+/, "");
509
+ if (potentialBucket && remainingPath && BUCKET_NAME_PATTERN.test(potentialBucket) && !UUID_PATTERN.test(potentialBucket) && (KNOWN_BUCKET_NAMES.has(potentialBucket) || !potentialBucket.includes("-")) && !/^\d+$/.test(potentialBucket)) {
510
+ return {
511
+ bucketNameFromPath: potentialBucket,
512
+ storagePath: remainingPath
513
+ };
514
+ }
515
+ }
516
+ return {
517
+ bucketNameFromPath: null,
518
+ storagePath: trimmedPath
519
+ };
520
+ }
472
521
  async function getSignedUrl(supabase, path, options) {
473
522
  try {
474
523
  const bucketName = getBucketName(false);
@@ -761,4 +810,4 @@ export {
761
810
  clearPublicLogoCache,
762
811
  getPublicLogoCacheStats
763
812
  };
764
- //# sourceMappingURL=chunk-H3P2RGKZ.js.map
813
+ //# sourceMappingURL=chunk-JDPFQV3V.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/providers/OrganisationProvider.tsx","../src/components/PublicLayout/PublicErrorBoundary.tsx","../src/components/PublicLayout/PublicPageProvider.tsx","../src/hooks/useAppConfig.ts","../src/utils/storage/config.ts","../src/utils/storage/helpers.ts","../src/hooks/public/usePublicEventLogo.ts"],"sourcesContent":["/**\n * @file Re-export for OrganisationProvider\n * @package @jmruthers/pace-core\n * @module Providers\n * @since 0.1.0\n * \n * Re-exports the service-based OrganisationProvider for backward compatibility.\n */\n\nexport { OrganisationServiceProvider as OrganisationProvider } from './services/OrganisationServiceProvider';\nexport type { OrganisationServiceProviderProps as OrganisationProviderProps } from './services/OrganisationServiceProvider';\n\n// Re-export context and hook\nexport { OrganisationServiceContext, useOrganisationService } from './services/OrganisationServiceProvider';\nexport type { OrganisationServiceContextType } from './services/OrganisationServiceProvider';\n\n// Re-export convenience hook for backward compatibility\nexport { useOrganisations } from '../hooks/useOrganisations';\n\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 // Throw error synchronously during render so error boundary can catch it\n if (error) {\n throw error;\n }\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\nexport const 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 * Storage configuration for pace-core\n */\n\nimport { FileSizeLimits, StorageConfig } from './types';\n\n/**\n * File size limits by MIME type (in bytes)\n */\nexport const FILE_SIZE_LIMITS: FileSizeLimits = {\n // Images\n 'image/jpeg': 5 * 1024 * 1024, // 5MB\n 'image/png': 5 * 1024 * 1024, // 5MB\n 'image/gif': 10 * 1024 * 1024, // 10MB (for animations)\n 'image/webp': 5 * 1024 * 1024, // 5MB\n 'image/svg+xml': 1 * 1024 * 1024, // 1MB (vector graphics)\n \n // Documents\n 'application/pdf': 50 * 1024 * 1024, // 50MB\n 'application/msword': 25 * 1024 * 1024, // 25MB\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': 25 * 1024 * 1024, // 25MB\n 'application/vnd.ms-excel': 25 * 1024 * 1024, // 25MB\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': 25 * 1024 * 1024, // 25MB\n \n // Archives\n 'application/zip': 100 * 1024 * 1024, // 100MB\n 'application/x-rar-compressed': 100 * 1024 * 1024, // 100MB\n \n // Text files\n 'text/plain': 1 * 1024 * 1024, // 1MB\n 'text/csv': 10 * 1024 * 1024, // 10MB\n 'application/json': 10 * 1024 * 1024, // 10MB\n};\n\n/**\n * Default file size limit for unknown MIME types\n */\nexport const DEFAULT_FILE_SIZE_LIMIT = 10 * 1024 * 1024; // 10MB\n\n/**\n * App-specific path mappings for file organization\n * Maps app names to their primary category in the organization-first structure\n */\nexport const APP_PATH_MAPPING: Record<string, string> = {\n 'PACE': 'event_logos',\n 'TRAC': 'trac_accommodation', // Default category for TRAC files\n 'MEDI': 'documents',\n 'CAKE': 'documents'\n};\n\n/**\n * Storage configuration\n */\nexport const STORAGE_CONFIG: StorageConfig = {\n bucketName: 'files',\n fileSizeLimits: FILE_SIZE_LIMITS,\n defaultFileSizeLimit: DEFAULT_FILE_SIZE_LIMIT,\n};\n\n/**\n * Get the file size limit for a given MIME type\n */\nexport function getFileSizeLimit(mimeType: string): number {\n return STORAGE_CONFIG.fileSizeLimits[mimeType] || STORAGE_CONFIG.defaultFileSizeLimit;\n}\n\n/**\n * Get the bucket name based on whether the file is public or private\n * @param isPublic - Whether the file should be publicly accessible\n * @returns The bucket name: 'public-files' for public files, 'files' for private files\n */\nexport function getBucketName(isPublic: boolean): 'files' | 'public-files' {\n return isPublic ? 'public-files' : 'files';\n}\n\n/**\n * Validate file size against limits\n */\nexport function validateFileSize(file: File): { isValid: boolean; error?: string } {\n const limit = getFileSizeLimit(file.type);\n \n if (file.size > limit) {\n const limitMB = Math.round(limit / (1024 * 1024));\n const fileMB = Math.round(file.size / (1024 * 1024));\n return {\n isValid: false,\n error: `File size (${fileMB}MB) exceeds limit (${limitMB}MB) for ${file.type}`\n };\n }\n \n return { isValid: true };\n}\n\n/**\n * Get human-readable file size\n */\nexport function formatFileSize(bytes: number): string {\n if (bytes === 0) return '0 Bytes';\n if (bytes < 0) return `${bytes} Bytes`; // Handle negative numbers\n \n const k = 1024;\n const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n \n // Ensure we don't exceed the available size units\n const sizeIndex = Math.min(Math.max(i, 0), sizes.length - 1);\n \n return parseFloat((bytes / Math.pow(k, sizeIndex)).toFixed(2)) + ' ' + sizes[sizeIndex];\n}\n","/**\n * Storage helper functions for pace-core\n */\n\nimport { SupabaseClient } from '@supabase/supabase-js';\nimport { \n StorageUploadOptions, \n StorageUploadResult, \n StorageFileMetadata,\n StorageUrlOptions,\n StorageListOptions,\n StorageListResult,\n StorageFileInfo\n} from './types';\nimport { validateFileSize, STORAGE_CONFIG, getBucketName } from './config';\n\n/**\n * Generate a file path based on organization-first structure\n */\nexport function generateFilePath(options: StorageUploadOptions, fileName: string): string {\n const { orgId, isPublic = false, customPath } = options;\n \n \n // Validate required orgId\n if (!orgId) {\n throw new Error('orgId is required for file path generation');\n }\n \n if (isPublic) {\n // Public files go to {orgId}/{category}/filename\n if (customPath) {\n return `${orgId}/${customPath}/${fileName}`;\n }\n return `${orgId}/public/${fileName}`;\n }\n \n // Organization-first structure: {orgId}/{category}/filename\n if (customPath) {\n return `${orgId}/${customPath}/${fileName}`;\n }\n \n // Use customPath if available, otherwise default to files\n const pathCategory = customPath || 'files';\n return `${orgId}/${pathCategory}/${fileName}`;\n}\n\n/**\n * Generate a unique filename with timestamp and UUID\n */\nexport function generateUniqueFileName(originalName: string): string {\n const timestamp = Date.now();\n const uuid = crypto.randomUUID();\n const extension = originalName.split('.').pop() || '';\n const baseName = originalName.replace(/\\.[^/.]+$/, '');\n \n // If there's no extension, don't add one\n if (!extension || extension === originalName) {\n return `${timestamp}-${uuid}-${baseName}`;\n }\n \n return `${timestamp}-${uuid}-${baseName}.${extension}`;\n}\n\n/**\n * Extract file metadata from a File object\n */\nexport async function extractFileMetadata(\n file: File, \n options: StorageUploadOptions,\n uploadedBy: string\n): Promise<StorageFileMetadata> {\n const metadata: StorageFileMetadata = {\n mimeType: file.type,\n size: file.size,\n orgId: options.orgId,\n appName: options.appName || 'pace-core',\n uploadedBy,\n uploadedAt: new Date().toISOString(),\n tags: options.tags || [],\n isPublic: options.isPublic || false,\n customMetadata: options.metadata || {}\n };\n\n // Extract image dimensions if it's an image\n if (file.type.startsWith('image/')) {\n try {\n const dimensions = await getImageDimensions(file);\n metadata.width = dimensions.width;\n metadata.height = dimensions.height;\n } catch (error) {\n console.warn('Could not extract image dimensions:', error);\n }\n }\n\n // Generate file hash if possible\n try {\n metadata.hash = await generateFileHash(file);\n } catch (error) {\n console.warn('Could not generate file hash:', error);\n }\n\n return metadata;\n}\n\n/**\n * Get image dimensions from a File object\n */\nasync function getImageDimensions(file: File): Promise<{ width: number; height: number }> {\n return new Promise((resolve, reject) => {\n const img = new Image();\n const url = URL.createObjectURL(file);\n \n img.onload = () => {\n URL.revokeObjectURL(url);\n resolve({ width: img.width, height: img.height });\n };\n \n img.onerror = () => {\n URL.revokeObjectURL(url);\n reject(new Error('Could not load image'));\n };\n \n img.src = url;\n });\n}\n\n/**\n * Generate a hash for a file\n */\nasync function generateFileHash(file: File): Promise<string> {\n const buffer = await file.arrayBuffer();\n const hashBuffer = await crypto.subtle.digest('SHA-256', buffer);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');\n return `sha256:${hashHex}`;\n}\n\n/**\n * Upload a file to Supabase storage with app segregation\n */\nexport async function uploadFile(\n supabase: SupabaseClient,\n file: File,\n options: StorageUploadOptions\n): Promise<StorageUploadResult> {\n try {\n // Validate file size\n const sizeValidation = validateFileSize(file);\n if (!sizeValidation.isValid) {\n return {\n success: false,\n error: sizeValidation.error\n };\n }\n\n // Generate unique filename and path\n const uniqueFileName = generateUniqueFileName(file.name);\n const filePath = generateFilePath(options, uniqueFileName);\n\n // Extract metadata\n const metadata = await extractFileMetadata(file, options, 'current-user'); // TODO: Get actual user ID\n\n // Select bucket based on isPublic flag\n const bucketName = getBucketName(options.isPublic || false);\n\n // Upload file to Supabase\n const { data, error } = await supabase.storage\n .from(bucketName)\n .upload(filePath, file, {\n cacheControl: '3600',\n upsert: false,\n contentType: file.type\n });\n\n if (error) {\n return {\n success: false,\n error: `Upload failed: ${error.message}`\n };\n }\n\n // Generate public URL if file is public\n let publicUrl: string | undefined;\n if (options.isPublic) {\n const { data: urlData } = supabase.storage\n .from(bucketName)\n .getPublicUrl(filePath);\n publicUrl = urlData.publicUrl;\n }\n\n return {\n success: true,\n path: filePath,\n publicUrl,\n metadata\n };\n\n } catch (error) {\n return {\n success: false,\n error: `Upload failed: ${error instanceof Error ? error.message : 'Unknown error'}`\n };\n }\n}\n\n/**\n * Get a public URL for a file\n * @param supabase - Supabase client instance\n * @param path - File path within the bucket\n * @param isPublic - Whether the file is in the public-files bucket (default: true)\n * @returns Public URL for the file\n */\nexport function getPublicUrl(\n supabase: SupabaseClient,\n path: string,\n isPublic: boolean = true\n): string {\n if (!supabase) {\n throw new Error('Supabase client is required to generate a public URL');\n }\n\n if (!path || typeof path !== 'string') {\n throw new Error('A valid storage path is required to generate a public URL');\n }\n\n // If the path is already an absolute URL, return it directly\n if (/^https?:\\/\\//i.test(path)) {\n return path;\n }\n\n // Normalise path by trimming whitespace and leading slashes\n let normalisedPath = path.trim().replace(/^\\/+/, '');\n\n if (!normalisedPath) {\n throw new Error('Storage path cannot be empty after normalisation');\n }\n\n const { bucketNameFromPath, storagePath } = resolveBucketHint(normalisedPath);\n\n const bucketName = bucketNameFromPath || getBucketName(isPublic);\n\n const { data } = supabase.storage\n .from(bucketName)\n .getPublicUrl(storagePath);\n\n return data.publicUrl;\n}\n\nfunction resolveBucketHint(pathWithPotentialBucket: string): { bucketNameFromPath: string | null; storagePath: string } {\n const BUCKET_NAME_PATTERN = /^[a-z0-9][a-z0-9-_\\.]{1,62}$/i;\n const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n const KNOWN_BUCKET_NAMES = new Set(['files', 'public-files']);\n\n const trimmedPath = pathWithPotentialBucket.trim();\n\n if (!trimmedPath) {\n throw new Error('Storage path cannot be empty after normalisation');\n }\n\n // Support \"bucket::path\" notation to remove ambiguity with colon usage in file names.\n const doubleColonIndex = trimmedPath.indexOf('::');\n if (doubleColonIndex > 0) {\n const potentialBucket = trimmedPath.slice(0, doubleColonIndex).trim();\n const remainingPath = trimmedPath.slice(doubleColonIndex + 2).replace(/^\\/+/, '');\n\n if (potentialBucket && remainingPath && BUCKET_NAME_PATTERN.test(potentialBucket)) {\n return {\n bucketNameFromPath: potentialBucket,\n storagePath: remainingPath\n };\n }\n }\n\n // Support \"bucket/path\" hints, provided the first segment looks like a bucket name and not a directory prefix.\n const firstSlashIndex = trimmedPath.indexOf('/');\n if (firstSlashIndex > 0) {\n const potentialBucket = trimmedPath.slice(0, firstSlashIndex).trim();\n const remainingPath = trimmedPath.slice(firstSlashIndex + 1).replace(/^\\/+/, '');\n\n if (\n potentialBucket &&\n remainingPath &&\n BUCKET_NAME_PATTERN.test(potentialBucket) &&\n !UUID_PATTERN.test(potentialBucket) &&\n (KNOWN_BUCKET_NAMES.has(potentialBucket) || !potentialBucket.includes('-')) &&\n !/^\\d+$/.test(potentialBucket)\n ) {\n return {\n bucketNameFromPath: potentialBucket,\n storagePath: remainingPath\n };\n }\n }\n\n return {\n bucketNameFromPath: null,\n storagePath: trimmedPath\n };\n}\n\n/**\n * Get a signed URL for a protected file\n * Private files are always in the 'files' bucket, so this always uses 'files' bucket\n * @param supabase - Supabase client instance\n * @param path - File path within the bucket\n * @param options - URL options including expiry time\n * @returns Signed URL with expiration timestamp, or null if failed\n */\nexport async function getSignedUrl(\n supabase: SupabaseClient,\n path: string,\n options: StorageUrlOptions\n): Promise<{ url: string; expiresAt: string } | null> {\n try {\n // Signed URLs are only for private files, which are always in the 'files' bucket\n const bucketName = getBucketName(false);\n \n const { data, error } = await supabase.storage\n .from(bucketName)\n .createSignedUrl(path, options.expiresIn || 3600);\n\n if (error) {\n console.error('Failed to create signed URL:', error);\n return null;\n }\n\n return {\n url: data.signedUrl,\n expiresAt: new Date(Date.now() + (options.expiresIn || 3600) * 1000).toISOString()\n };\n } catch (error) {\n console.error('Failed to create signed URL:', error);\n return null;\n }\n}\n\n/**\n * Delete a file from storage\n * @param supabase - Supabase client instance\n * @param path - File path within the bucket\n * @param isPublic - Whether the file is in the public-files bucket (default: false)\n * @returns Success status and optional error message\n */\nexport async function deleteFile(\n supabase: SupabaseClient,\n path: string,\n isPublic: boolean = false\n): Promise<{ success: boolean; error?: string }> {\n try {\n const bucketName = getBucketName(isPublic);\n \n const { error } = await supabase.storage\n .from(bucketName)\n .remove([path]);\n\n if (error) {\n return {\n success: false,\n error: `Delete failed: ${error.message}`\n };\n }\n\n return { success: true };\n } catch (error) {\n return {\n success: false,\n error: `Delete failed: ${error instanceof Error ? error.message : 'Unknown error'}`\n };\n }\n}\n\n/**\n * List files in an organization scope\n * @param supabase - Supabase client instance\n * @param options - List options including bucket selection via isPublic\n * @returns List of files with metadata\n */\nexport async function listFiles(\n supabase: SupabaseClient,\n options: StorageListOptions & { isPublic?: boolean }\n): Promise<StorageListResult> {\n try {\n // Select bucket based on isPublic flag (default to private files bucket)\n const bucketName = getBucketName(options.isPublic || false);\n \n // Organization-first structure: {orgId}/{category}/\n const pathPrefix = `${options.orgId}/`;\n const searchPath = options.pathPrefix ? `${pathPrefix}${options.pathPrefix}` : pathPrefix;\n\n const { data, error } = await supabase.storage\n .from(bucketName)\n .list(searchPath, {\n limit: options.limit || 100,\n offset: options.offset || 0,\n sortBy: { column: 'created_at', order: 'desc' }\n });\n\n if (error) {\n console.error('Failed to list files:', error);\n return { files: [], totalCount: 0, hasMore: false };\n }\n\n const files: StorageFileInfo[] = (data || []).map(item => ({\n name: item.name,\n path: `${searchPath}${item.name}`,\n size: item.metadata?.size || 0,\n mimeType: item.metadata?.mimetype || 'application/octet-stream',\n lastModified: item.updated_at || item.created_at || new Date().toISOString(),\n metadata: {\n mimeType: item.metadata?.mimetype || 'application/octet-stream',\n size: item.metadata?.size || 0,\n orgId: options.orgId,\n appName: options.appName,\n uploadedBy: 'unknown',\n uploadedAt: item.created_at || new Date().toISOString(),\n isPublic: options.isPublic || false\n }\n }));\n\n return {\n files,\n totalCount: files.length,\n hasMore: files.length >= (options.limit || 100)\n };\n } catch (error) {\n console.error('Failed to list files:', error);\n return { files: [], totalCount: 0, hasMore: false };\n }\n}\n\n/**\n * Download a file from storage\n * @param supabase - Supabase client instance\n * @param path - File path within the bucket\n * @param isPublic - Whether the file is in the public-files bucket (default: false)\n * @returns File blob with metadata, or null if failed\n */\nexport async function downloadFile(\n supabase: SupabaseClient,\n path: string,\n isPublic: boolean = false\n): Promise<{ blob: Blob; metadata: { name: string; size: number; type: string } } | null> {\n try {\n const bucketName = getBucketName(isPublic);\n \n const { data, error } = await supabase.storage\n .from(bucketName)\n .download(path);\n\n if (error) {\n console.error('Failed to download file:', error);\n return null;\n }\n\n if (!data) {\n return null;\n }\n\n // Extract file name from path\n const fileName = path.split('/').pop() || 'download';\n \n // Get file metadata\n const { data: fileInfo } = await supabase.storage\n .from(bucketName)\n .list(path.split('/').slice(0, -1).join('/'), {\n search: fileName\n });\n\n const metadata = fileInfo?.[0]?.metadata || {};\n \n return {\n blob: data,\n metadata: {\n name: fileName,\n size: metadata.size || data.size,\n type: metadata.mimetype || 'application/octet-stream'\n }\n };\n } catch (error) {\n console.error('Failed to download file:', error);\n return null;\n }\n}\n\n/**\n * Move a file to archived location (soft delete)\n * @param supabase - Supabase client instance\n * @param path - File path within the bucket\n * @param options - Archive options including bucket selection via isPublic\n */\nexport async function archiveFile(\n supabase: SupabaseClient,\n path: string,\n options: { appName: string; orgId: string; isPublic?: boolean }\n): Promise<{ success: boolean; error?: string }> {\n try {\n const bucketName = getBucketName(options.isPublic || false);\n \n // Generate archived path for organization-first structure\n const archivedPath = path.replace(`${options.orgId}/`, `archived/${options.orgId}/`);\n \n // Copy file to archived location\n const { error: copyError } = await supabase.storage\n .from(bucketName)\n .copy(path, archivedPath);\n\n if (copyError) {\n return {\n success: false,\n error: `Archive failed: ${copyError.message}`\n };\n }\n\n // Delete original file\n const deleteResult = await deleteFile(supabase, path, options.isPublic || false);\n if (!deleteResult.success) {\n return deleteResult;\n }\n\n return { success: true };\n } catch (error) {\n return {\n success: false,\n error: `Archive failed: ${error instanceof Error ? error.message : 'Unknown error'}`\n };\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';\nimport { getPublicUrl } from '../../utils/storage/helpers';\nimport { FileCategory } from '../../types/file-reference';\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 // Get event logo from file_references using new RPC function\n const { data, error: rpcError } = await (supabase as any)\n .rpc('data_file_reference_by_category_list', {\n p_table_name: 'event',\n p_record_id: eventId,\n p_category: FileCategory.EVENT_LOGOS,\n p_organisation_id: 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]?.file_path) {\n setLogoUrl(null);\n return;\n }\n\n // Get the file path from the RPC response\n const logoPath = data[0].file_path;\n const isPublic = data[0].is_public ?? true; // Event logos should be public\n\n // Generate public URL using bucket-aware helper (public-files bucket for public files)\n const logoUrl = getPublicUrl(supabase, logoPath, isPublic);\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":["error","jsx","useMemo","useMemo","useMemo","useMemo","logoUrl","error"]}
@@ -3,7 +3,7 @@ import {
3
3
  init_useOrganisationService,
4
4
  useEventService2 as useEventService,
5
5
  useOrganisationService2 as useOrganisationService
6
- } from "./chunk-DP5X5ORK.js";
6
+ } from "./chunk-AIV3VYBQ.js";
7
7
  import {
8
8
  __esm
9
9
  } from "./chunk-PLDDJCW6.js";
@@ -57,4 +57,4 @@ export {
57
57
  init_useOrganisations,
58
58
  useEvents
59
59
  };
60
- //# sourceMappingURL=chunk-3RZBKQ5Y.js.map
60
+ //# sourceMappingURL=chunk-JQWSAYZC.js.map
@@ -1,3 +1,7 @@
1
+ import {
2
+ __esm
3
+ } from "./chunk-PLDDJCW6.js";
4
+
1
5
  // src/theming/runtime.ts
2
6
  function formatOklchCss(color) {
3
7
  return `oklch(${color.L} ${color.C} ${color.H})`;
@@ -121,12 +125,17 @@ function getCurrentThemeData() {
121
125
  const acc = {};
122
126
  return null;
123
127
  }
128
+ var init_runtime = __esm({
129
+ "src/theming/runtime.ts"() {
130
+ }
131
+ });
124
132
 
125
133
  export {
126
134
  applyPalette,
127
135
  clearPalette,
128
136
  generateSSRThemeCSS,
129
137
  isDynamicThemingActive,
130
- getCurrentThemeData
138
+ getCurrentThemeData,
139
+ init_runtime
131
140
  };
132
- //# sourceMappingURL=chunk-A6HBIY5P.js.map
141
+ //# sourceMappingURL=chunk-SMJZMKYN.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/theming/runtime.ts"],"sourcesContent":["/**\n * @file PACE Core Theming Runtime\n * @package @jmruthers/pace-core\n * @module Theming/Runtime\n * @since 2.0.0\n * \n * Runtime helpers for palette replacement from organisation/event payloads.\n * Provides simple applyPalette() and clearPalette() API with SSR support.\n * \n * @example\n * ```ts\n * import { applyPalette, clearPalette } from '@jmruthers/pace-core/theming/runtime';\n * \n * // Apply organisation colors\n * applyPalette({\n * main: { // main palette shades\n * 50: { L: 0.95, C: 0.02, H: 0 },\n * 500: { L: 0.5, C: 0.2, H: 0 }\n * },\n * sec: { // secondary palette shades\n * 50: { L: 0.95, C: 0.02, H: 120 },\n * 500: { L: 0.5, C: 0.2, H: 120 }\n * },\n * acc: { // accent palette shades\n * 50: { L: 0.95, C: 0.02, H: 240 },\n * 500: { L: 0.5, C: 0.2, H: 240 }\n * }\n * });\n * \n * // Clear dynamic theming\n * clearPalette();\n * ```\n */\n\nexport interface ColorShade {\n L: number;\n C: number;\n H: number;\n}\n\nexport interface ColorPalette {\n [shade: string]: ColorShade;\n}\n\nexport interface PaletteData {\n main: ColorPalette;\n sec: ColorPalette;\n acc: ColorPalette;\n}\n\n/**\n * Converts OKLCH color data to CSS string\n */\nfunction formatOklchCss(color: ColorShade): string {\n return `oklch(${color.L} ${color.C} ${color.H})`;\n}\n\n/**\n * Applies a complete palette to the document by setting CSS variables on :root.\n * Uses document.documentElement.style.setProperty() for runtime updates.\n * \n * @param palette - Complete palette data with main, sec, and acc palettes\n */\nexport function applyPalette(palette: PaletteData): void {\n if (typeof document === 'undefined' || document === null) {\n if (typeof console !== 'undefined' && console?.warn) {\n console.warn('applyPalette: Document not available (SSR)');\n }\n return;\n }\n\n const root = document.documentElement;\n const main = palette.main || {};\n const sec = palette.sec || {};\n const acc = palette.acc || {};\n\n // Apply main palette\n if (main.raw) {\n root.style.setProperty('--color-main-raw', formatOklchCss(main.raw));\n }\n for (let i = 50; i <= 950; i += 50) {\n const shade = i.toString();\n if (main[shade]) {\n root.style.setProperty(`--color-main-${shade}`, formatOklchCss(main[shade]));\n }\n }\n\n // Apply sec palette\n if (sec.raw) {\n root.style.setProperty('--color-sec-raw', formatOklchCss(sec.raw));\n }\n for (let i = 50; i <= 950; i += 50) {\n const shade = i.toString();\n if (sec[shade]) {\n root.style.setProperty(`--color-sec-${shade}`, formatOklchCss(sec[shade]));\n }\n }\n\n // Apply acc palette\n if (acc.raw) {\n root.style.setProperty('--color-acc-raw', formatOklchCss(acc.raw));\n }\n for (let i = 50; i <= 950; i += 50) {\n const shade = i.toString();\n if (acc[shade]) {\n root.style.setProperty(`--color-acc-${shade}`, formatOklchCss(acc[shade]));\n }\n }\n\n}\n\n/**\n * Clears dynamic theming by removing CSS variables from :root.\n * This allows the browser to fall back to static CSS values.\n */\nexport function clearPalette(): void {\n if (typeof document === 'undefined' || document === null) {\n return;\n }\n\n const root = document.documentElement;\n const prefixes = ['--color-main-', '--color-sec-', '--color-acc-'];\n \n // Remove all dynamically set color variables\n for (let i = root.style.length - 1; i >= 0; i--) {\n const propertyName = root.style[i];\n if (prefixes.some(prefix => propertyName.startsWith(prefix))) {\n root.style.removeProperty(propertyName);\n }\n }\n}\n\n/**\n * Generates CSS for SSR rendering (for server-side rendering)\n * Creates a :root rule with all color variables\n */\nfunction generateThemeCSS(palette: PaletteData): string {\n // Handle null/undefined palette\n if (!palette) {\n throw new Error('Palette data is required');\n }\n \n const main = palette.main || {};\n const sec = palette.sec || {};\n const acc = palette.acc || {};\n \n let css = ':root {\\n';\n \n // MAIN palette\n css += ' /* MAIN */\\n';\n if (main.raw) {\n css += ` --color-main-raw: ${formatOklchCss(main.raw)};\\n`;\n }\n for (let i = 50; i <= 950; i += 50) {\n const shade = i.toString();\n if (main[shade]) {\n css += ` --color-main-${shade}: ${formatOklchCss(main[shade])};\\n`;\n }\n }\n \n // SEC palette\n css += ' /* SEC */\\n';\n if (sec.raw) {\n css += ` --color-sec-raw: ${formatOklchCss(sec.raw)};\\n`;\n }\n for (let i = 50; i <= 950; i += 50) {\n const shade = i.toString();\n if (sec[shade]) {\n css += ` --color-sec-${shade}: ${formatOklchCss(sec[shade])};\\n`;\n }\n }\n \n // ACC palette\n css += ' /* ACC */\\n';\n if (acc.raw) {\n css += ` --color-acc-raw: ${formatOklchCss(acc.raw)};\\n`;\n }\n for (let i = 50; i <= 950; i += 50) {\n const shade = i.toString();\n if (acc[shade]) {\n css += ` --color-acc-${shade}: ${formatOklchCss(acc[shade])};\\n`;\n }\n }\n \n css += '}\\n';\n \n return css;\n}\n\n/**\n * Generates the same CSS block for SSR rendering\n * Use this in your SSR setup to avoid FOUC\n */\nexport function generateSSRThemeCSS(palette: PaletteData): string {\n return generateThemeCSS(palette);\n}\n\n/**\n * Checks if dynamic theming is currently active\n */\nexport function isDynamicThemingActive(): boolean {\n if (typeof document === 'undefined' || document === null) {\n return false;\n }\n \n const root = document.documentElement;\n // Check if any color variables are set on :root\n return root.style.getPropertyValue('--color-main-500') !== '';\n}\n\n/**\n * Gets the current dynamic theme data (if any)\n * Useful for debugging or persistence\n */\nexport function getCurrentThemeData(): PaletteData | null {\n if (typeof document === 'undefined' || document === null) {\n return null;\n }\n\n const root = document.documentElement;\n const main: ColorPalette = {};\n const sec: ColorPalette = {};\n const acc: ColorPalette = {};\n\n // Extract CSS variables from :root\n // This is a simplified implementation\n // In a real scenario, you might want to parse the actual color values\n // For now, we'll return null as the theme data isn't easily extractable\n return null;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/theming/runtime.ts"],"sourcesContent":["/**\n * @file PACE Core Theming Runtime\n * @package @jmruthers/pace-core\n * @module Theming/Runtime\n * @since 2.0.0\n * \n * Runtime helpers for palette replacement from organisation/event payloads.\n * Provides simple applyPalette() and clearPalette() API with SSR support.\n * \n * @example\n * ```ts\n * import { applyPalette, clearPalette } from '@jmruthers/pace-core/theming/runtime';\n * \n * // Apply organisation colors\n * applyPalette({\n * main: { // main palette shades\n * 50: { L: 0.95, C: 0.02, H: 0 },\n * 500: { L: 0.5, C: 0.2, H: 0 }\n * },\n * sec: { // secondary palette shades\n * 50: { L: 0.95, C: 0.02, H: 120 },\n * 500: { L: 0.5, C: 0.2, H: 120 }\n * },\n * acc: { // accent palette shades\n * 50: { L: 0.95, C: 0.02, H: 240 },\n * 500: { L: 0.5, C: 0.2, H: 240 }\n * }\n * });\n * \n * // Clear dynamic theming\n * clearPalette();\n * ```\n */\n\nexport interface ColorShade {\n L: number;\n C: number;\n H: number;\n}\n\nexport interface ColorPalette {\n [shade: string]: ColorShade;\n}\n\nexport interface PaletteData {\n main: ColorPalette;\n sec: ColorPalette;\n acc: ColorPalette;\n}\n\n/**\n * Converts OKLCH color data to CSS string\n */\nfunction formatOklchCss(color: ColorShade): string {\n return `oklch(${color.L} ${color.C} ${color.H})`;\n}\n\n/**\n * Applies a complete palette to the document by setting CSS variables on :root.\n * Uses document.documentElement.style.setProperty() for runtime updates.\n * \n * @param palette - Complete palette data with main, sec, and acc palettes\n */\nexport function applyPalette(palette: PaletteData): void {\n if (typeof document === 'undefined' || document === null) {\n if (typeof console !== 'undefined' && console?.warn) {\n console.warn('applyPalette: Document not available (SSR)');\n }\n return;\n }\n\n const root = document.documentElement;\n const main = palette.main || {};\n const sec = palette.sec || {};\n const acc = palette.acc || {};\n\n // Apply main palette\n if (main.raw) {\n root.style.setProperty('--color-main-raw', formatOklchCss(main.raw));\n }\n for (let i = 50; i <= 950; i += 50) {\n const shade = i.toString();\n if (main[shade]) {\n root.style.setProperty(`--color-main-${shade}`, formatOklchCss(main[shade]));\n }\n }\n\n // Apply sec palette\n if (sec.raw) {\n root.style.setProperty('--color-sec-raw', formatOklchCss(sec.raw));\n }\n for (let i = 50; i <= 950; i += 50) {\n const shade = i.toString();\n if (sec[shade]) {\n root.style.setProperty(`--color-sec-${shade}`, formatOklchCss(sec[shade]));\n }\n }\n\n // Apply acc palette\n if (acc.raw) {\n root.style.setProperty('--color-acc-raw', formatOklchCss(acc.raw));\n }\n for (let i = 50; i <= 950; i += 50) {\n const shade = i.toString();\n if (acc[shade]) {\n root.style.setProperty(`--color-acc-${shade}`, formatOklchCss(acc[shade]));\n }\n }\n\n}\n\n/**\n * Clears dynamic theming by removing CSS variables from :root.\n * This allows the browser to fall back to static CSS values.\n */\nexport function clearPalette(): void {\n if (typeof document === 'undefined' || document === null) {\n return;\n }\n\n const root = document.documentElement;\n const prefixes = ['--color-main-', '--color-sec-', '--color-acc-'];\n \n // Remove all dynamically set color variables\n for (let i = root.style.length - 1; i >= 0; i--) {\n const propertyName = root.style[i];\n if (prefixes.some(prefix => propertyName.startsWith(prefix))) {\n root.style.removeProperty(propertyName);\n }\n }\n}\n\n/**\n * Generates CSS for SSR rendering (for server-side rendering)\n * Creates a :root rule with all color variables\n */\nfunction generateThemeCSS(palette: PaletteData): string {\n // Handle null/undefined palette\n if (!palette) {\n throw new Error('Palette data is required');\n }\n \n const main = palette.main || {};\n const sec = palette.sec || {};\n const acc = palette.acc || {};\n \n let css = ':root {\\n';\n \n // MAIN palette\n css += ' /* MAIN */\\n';\n if (main.raw) {\n css += ` --color-main-raw: ${formatOklchCss(main.raw)};\\n`;\n }\n for (let i = 50; i <= 950; i += 50) {\n const shade = i.toString();\n if (main[shade]) {\n css += ` --color-main-${shade}: ${formatOklchCss(main[shade])};\\n`;\n }\n }\n \n // SEC palette\n css += ' /* SEC */\\n';\n if (sec.raw) {\n css += ` --color-sec-raw: ${formatOklchCss(sec.raw)};\\n`;\n }\n for (let i = 50; i <= 950; i += 50) {\n const shade = i.toString();\n if (sec[shade]) {\n css += ` --color-sec-${shade}: ${formatOklchCss(sec[shade])};\\n`;\n }\n }\n \n // ACC palette\n css += ' /* ACC */\\n';\n if (acc.raw) {\n css += ` --color-acc-raw: ${formatOklchCss(acc.raw)};\\n`;\n }\n for (let i = 50; i <= 950; i += 50) {\n const shade = i.toString();\n if (acc[shade]) {\n css += ` --color-acc-${shade}: ${formatOklchCss(acc[shade])};\\n`;\n }\n }\n \n css += '}\\n';\n \n return css;\n}\n\n/**\n * Generates the same CSS block for SSR rendering\n * Use this in your SSR setup to avoid FOUC\n */\nexport function generateSSRThemeCSS(palette: PaletteData): string {\n return generateThemeCSS(palette);\n}\n\n/**\n * Checks if dynamic theming is currently active\n */\nexport function isDynamicThemingActive(): boolean {\n if (typeof document === 'undefined' || document === null) {\n return false;\n }\n \n const root = document.documentElement;\n // Check if any color variables are set on :root\n return root.style.getPropertyValue('--color-main-500') !== '';\n}\n\n/**\n * Gets the current dynamic theme data (if any)\n * Useful for debugging or persistence\n */\nexport function getCurrentThemeData(): PaletteData | null {\n if (typeof document === 'undefined' || document === null) {\n return null;\n }\n\n const root = document.documentElement;\n const main: ColorPalette = {};\n const sec: ColorPalette = {};\n const acc: ColorPalette = {};\n\n // Extract CSS variables from :root\n // This is a simplified implementation\n // In a real scenario, you might want to parse the actual color values\n // For now, we'll return null as the theme data isn't easily extractable\n return null;\n}\n"],"mappings":"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","names":[]}
@@ -1,4 +1,9 @@
1
+ import {
2
+ init_runtime
3
+ } from "./chunk-SMJZMKYN.js";
4
+
1
5
  // src/styles/index.ts
6
+ init_runtime();
2
7
  var styleConfig = {
3
8
  core: {
4
9
  path: "./core.css",
@@ -17,4 +22,4 @@ export {
17
22
  getStylePath,
18
23
  getAllStylePaths
19
24
  };
20
- //# sourceMappingURL=chunk-L3RV2ALE.js.map
25
+ //# sourceMappingURL=chunk-VKOCWWVY.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/styles/index.ts"],"sourcesContent":["/**\n * @file Styles Index\n * @package @jmruthers/pace-core\n * @module Styles\n * @since 2.0.0\n * \n * Central export for all pace-core styles.\n * This file provides easy access to all CSS files for consuming applications.\n * \n * @example\n * ```tsx\n * // Import the core CSS file\n * import '@jmruthers/pace-core/src/styles/core.css';\n * ```\n * \n * @example\n * ```tsx\n * // Import theming runtime\n * import { applyPalette, clearPalette } from '@jmruthers/pace-core/theming/runtime';\n * ```\n */\n\n// Note: CSS files are available at runtime via package exports\n// Import them using the individual file paths\n\n// Type definitions for style imports\nexport interface StyleImport {\n default: string;\n}\n\n// Style configuration\nexport const styleConfig = {\n core: {\n path: './core.css',\n description: 'Complete CSS foundation including base styles, theme mappings, fonts, resets, and neutral tokens'\n }\n} as const;\n\n// Helper function to get style paths\nexport function getStylePath(style: keyof typeof styleConfig): string {\n return styleConfig[style].path;\n}\n\n// Helper function to get all style paths\nexport function getAllStylePaths(): string[] {\n return Object.values(styleConfig).map(config => config.path);\n}\n\n// Re-export theming runtime for convenience\nexport { applyPalette, clearPalette, generateSSRThemeCSS, isDynamicThemingActive, getCurrentThemeData } from '../theming/runtime';\nexport type { PaletteData, ColorPalette, ColorShade } from '../theming/runtime';\n"],"mappings":";AA+BO,IAAM,cAAc;AAAA,EACzB,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,EACf;AACF;AAGO,SAAS,aAAa,OAAyC;AACpE,SAAO,YAAY,KAAK,EAAE;AAC5B;AAGO,SAAS,mBAA6B;AAC3C,SAAO,OAAO,OAAO,WAAW,EAAE,IAAI,YAAU,OAAO,IAAI;AAC7D;","names":[]}
1
+ {"version":3,"sources":["../src/styles/index.ts"],"sourcesContent":["/**\n * @file Styles Index\n * @package @jmruthers/pace-core\n * @module Styles\n * @since 2.0.0\n * \n * Central export for all pace-core styles.\n * This file provides easy access to all CSS files for consuming applications.\n * \n * @example\n * ```tsx\n * // Import the core CSS file\n * import '@jmruthers/pace-core/src/styles/core.css';\n * ```\n * \n * @example\n * ```tsx\n * // Import theming runtime\n * import { applyPalette, clearPalette } from '@jmruthers/pace-core/theming/runtime';\n * ```\n */\n\n// Note: CSS files are available at runtime via package exports\n// Import them using the individual file paths\n\n// Type definitions for style imports\nexport interface StyleImport {\n default: string;\n}\n\n// Style configuration\nexport const styleConfig = {\n core: {\n path: './core.css',\n description: 'Complete CSS foundation including base styles, theme mappings, fonts, resets, and neutral tokens'\n }\n} as const;\n\n// Helper function to get style paths\nexport function getStylePath(style: keyof typeof styleConfig): string {\n return styleConfig[style].path;\n}\n\n// Helper function to get all style paths\nexport function getAllStylePaths(): string[] {\n return Object.values(styleConfig).map(config => config.path);\n}\n\n// Re-export theming runtime for convenience\nexport { applyPalette, clearPalette, generateSSRThemeCSS, isDynamicThemingActive, getCurrentThemeData } from '../theming/runtime';\nexport type { PaletteData, ColorPalette, ColorShade } from '../theming/runtime';\n"],"mappings":";;;;;AAiDA;AAlBO,IAAM,cAAc;AAAA,EACzB,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,EACf;AACF;AAGO,SAAS,aAAa,OAAyC;AACpE,SAAO,YAAY,KAAK,EAAE;AAC5B;AAGO,SAAS,mBAA6B;AAC3C,SAAO,OAAO,OAAO,WAAW,EAAE,IAAI,YAAU,OAAO,IAAI;AAC7D;","names":[]}
@@ -2,7 +2,7 @@ import {
2
2
  createScopeFromEvent,
3
3
  useAccessLevel,
4
4
  useCan
5
- } from "./chunk-AQGF5OG7.js";
5
+ } from "./chunk-GD3ENUKD.js";
6
6
  import {
7
7
  OrganisationContextRequiredError,
8
8
  RBACCache,
@@ -11,13 +11,13 @@ import {
11
11
  } from "./chunk-S63MFSY6.js";
12
12
  import {
13
13
  useSecureDataAccess
14
- } from "./chunk-CXKMRKRF.js";
14
+ } from "./chunk-G2YT64FA.js";
15
15
  import {
16
16
  init_UnifiedAuthProvider
17
- } from "./chunk-KTPG5VCH.js";
17
+ } from "./chunk-7XBW2P7B.js";
18
18
  import {
19
19
  useUnifiedAuth
20
- } from "./chunk-DP5X5ORK.js";
20
+ } from "./chunk-AIV3VYBQ.js";
21
21
  import {
22
22
  getCurrentAppName
23
23
  } from "./chunk-JCQZ6LA7.js";
@@ -1860,4 +1860,4 @@ export {
1860
1860
  getPermissionsForRole,
1861
1861
  ALL_PERMISSIONS
1862
1862
  };
1863
- //# sourceMappingURL=chunk-6UHXQH7P.js.map
1863
+ //# sourceMappingURL=chunk-XZHZYSAK.js.map
@@ -56,7 +56,7 @@ import {
56
56
  useFileReferenceForRecord,
57
57
  useFilesByCategory,
58
58
  usePublicPageContext as usePublicPageContext2
59
- } from "./chunk-CJIZS3UE.js";
59
+ } from "./chunk-EWMXLDIX.js";
60
60
  import {
61
61
  Alert,
62
62
  AlertDescription,
@@ -96,8 +96,8 @@ import {
96
96
  TooltipProvider,
97
97
  TooltipRoot,
98
98
  TooltipTrigger
99
- } from "./chunk-BNXBJOGL.js";
100
- import "./chunk-AQGF5OG7.js";
99
+ } from "./chunk-4DYK5KCK.js";
100
+ import "./chunk-GD3ENUKD.js";
101
101
  import "./chunk-S63MFSY6.js";
102
102
  import "./chunk-Q7APDV6H.js";
103
103
  import {
@@ -107,19 +107,19 @@ import {
107
107
  useErrorBoundary,
108
108
  useIsPublicPage,
109
109
  usePublicPageContext
110
- } from "./chunk-H3P2RGKZ.js";
110
+ } from "./chunk-JDPFQV3V.js";
111
111
  import {
112
112
  useToast
113
113
  } from "./chunk-QPCAGLUS.js";
114
- import "./chunk-3RZBKQ5Y.js";
114
+ import "./chunk-JQWSAYZC.js";
115
115
  import {
116
116
  init_UnifiedAuthProvider
117
- } from "./chunk-KTPG5VCH.js";
118
- import "./chunk-YY4YYM3E.js";
117
+ } from "./chunk-7XBW2P7B.js";
118
+ import "./chunk-G2SCPUKC.js";
119
119
  import {
120
120
  UnifiedAuthProvider,
121
121
  useUnifiedAuth
122
- } from "./chunk-DP5X5ORK.js";
122
+ } from "./chunk-AIV3VYBQ.js";
123
123
  import {
124
124
  FileCategory
125
125
  } from "./chunk-XJ2HZOBU.js";
@@ -132,6 +132,7 @@ import {
132
132
  import "./chunk-JCQZ6LA7.js";
133
133
  import "./chunk-O3NWNXDY.js";
134
134
  import "./chunk-BDZUMRBD.js";
135
+ import "./chunk-SMJZMKYN.js";
135
136
  import "./chunk-PLDDJCW6.js";
136
137
 
137
138
  // src/components/index.ts