@jmruthers/pace-core 0.5.105 → 0.5.107

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/{DataTable-BE0OXZKQ.d.ts → DataTable-D5cBRca8.d.ts} +1 -1
  2. package/dist/{DataTable-LWHFLTEW.js → DataTable-H2WIR2DN.js} +3 -3
  3. package/dist/{chunk-QPCAGLUS.js → chunk-4OX5PXHX.js} +5 -2
  4. package/dist/chunk-4OX5PXHX.js.map +1 -0
  5. package/dist/{chunk-75G3NZWN.js → chunk-5JJCXTVE.js} +293 -37
  6. package/dist/chunk-5JJCXTVE.js.map +1 -0
  7. package/dist/{chunk-HBGPLSA5.js → chunk-DMNMZKWS.js} +70 -24
  8. package/dist/chunk-DMNMZKWS.js.map +1 -0
  9. package/dist/{chunk-AZFPGDCJ.js → chunk-EWKCROSF.js} +133 -49
  10. package/dist/chunk-EWKCROSF.js.map +1 -0
  11. package/dist/{chunk-4BWGRQBG.js → chunk-NFPV7MRN.js} +22 -2
  12. package/dist/chunk-NFPV7MRN.js.map +1 -0
  13. package/dist/{chunk-DWYMGSGU.js → chunk-VJ7MPS2K.js} +2 -2
  14. package/dist/components.d.ts +3 -3
  15. package/dist/components.js +4 -4
  16. package/dist/{formatting-BfDeV-ja.d.ts → formatting-BiEv5oEk.d.ts} +32 -2
  17. package/dist/hooks.d.ts +2 -2
  18. package/dist/hooks.js +3 -3
  19. package/dist/index.d.ts +5 -5
  20. package/dist/index.js +6 -6
  21. package/dist/{types-BDg1mAGG.d.ts → types-D4TVpDa1.d.ts} +24 -1
  22. package/dist/{useToast-Bm6TnSK-.d.ts → useToast-DRah6K-g.d.ts} +5 -2
  23. package/dist/utils.d.ts +3 -3
  24. package/dist/utils.js +2 -2
  25. package/docs/api/classes/ColumnFactory.md +1 -1
  26. package/docs/api/classes/ErrorBoundary.md +1 -1
  27. package/docs/api/classes/InvalidScopeError.md +1 -1
  28. package/docs/api/classes/MissingUserContextError.md +1 -1
  29. package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
  30. package/docs/api/classes/PermissionDeniedError.md +1 -1
  31. package/docs/api/classes/PublicErrorBoundary.md +1 -1
  32. package/docs/api/classes/RBACAuditManager.md +1 -1
  33. package/docs/api/classes/RBACCache.md +1 -1
  34. package/docs/api/classes/RBACEngine.md +1 -1
  35. package/docs/api/classes/RBACError.md +1 -1
  36. package/docs/api/classes/RBACNotInitializedError.md +1 -1
  37. package/docs/api/classes/SecureSupabaseClient.md +1 -1
  38. package/docs/api/classes/StorageUtils.md +1 -1
  39. package/docs/api/enums/FileCategory.md +1 -1
  40. package/docs/api/interfaces/AggregateConfig.md +4 -4
  41. package/docs/api/interfaces/ButtonProps.md +1 -1
  42. package/docs/api/interfaces/CardProps.md +1 -1
  43. package/docs/api/interfaces/ColorPalette.md +1 -1
  44. package/docs/api/interfaces/ColorShade.md +1 -1
  45. package/docs/api/interfaces/DataAccessRecord.md +1 -1
  46. package/docs/api/interfaces/DataRecord.md +1 -1
  47. package/docs/api/interfaces/DataTableAction.md +18 -18
  48. package/docs/api/interfaces/DataTableColumn.md +115 -10
  49. package/docs/api/interfaces/DataTableProps.md +38 -38
  50. package/docs/api/interfaces/DataTableToolbarButton.md +7 -7
  51. package/docs/api/interfaces/EmptyStateConfig.md +5 -5
  52. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  53. package/docs/api/interfaces/FileDisplayProps.md +1 -1
  54. package/docs/api/interfaces/FileMetadata.md +1 -1
  55. package/docs/api/interfaces/FileReference.md +1 -1
  56. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  57. package/docs/api/interfaces/FileUploadOptions.md +1 -1
  58. package/docs/api/interfaces/FileUploadProps.md +1 -1
  59. package/docs/api/interfaces/FooterProps.md +1 -1
  60. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  61. package/docs/api/interfaces/InputProps.md +1 -1
  62. package/docs/api/interfaces/LabelProps.md +1 -1
  63. package/docs/api/interfaces/LoginFormProps.md +1 -1
  64. package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
  65. package/docs/api/interfaces/NavigationContextType.md +1 -1
  66. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  67. package/docs/api/interfaces/NavigationItem.md +1 -1
  68. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  69. package/docs/api/interfaces/NavigationProviderProps.md +1 -1
  70. package/docs/api/interfaces/Organisation.md +1 -1
  71. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  72. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  73. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  74. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  75. package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
  76. package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
  77. package/docs/api/interfaces/PageAccessRecord.md +1 -1
  78. package/docs/api/interfaces/PagePermissionContextType.md +1 -1
  79. package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
  80. package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
  81. package/docs/api/interfaces/PaletteData.md +1 -1
  82. package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
  83. package/docs/api/interfaces/ProtectedRouteProps.md +1 -1
  84. package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
  85. package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
  86. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
  87. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  88. package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
  89. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  90. package/docs/api/interfaces/RBACConfig.md +1 -1
  91. package/docs/api/interfaces/RBACLogger.md +1 -1
  92. package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
  93. package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
  94. package/docs/api/interfaces/RouteAccessRecord.md +1 -1
  95. package/docs/api/interfaces/RouteConfig.md +1 -1
  96. package/docs/api/interfaces/SecureDataContextType.md +1 -1
  97. package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
  98. package/docs/api/interfaces/StorageConfig.md +1 -1
  99. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  100. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  101. package/docs/api/interfaces/StorageListOptions.md +1 -1
  102. package/docs/api/interfaces/StorageListResult.md +1 -1
  103. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  104. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  105. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  106. package/docs/api/interfaces/StyleImport.md +1 -1
  107. package/docs/api/interfaces/SwitchProps.md +1 -1
  108. package/docs/api/interfaces/ToastActionElement.md +1 -1
  109. package/docs/api/interfaces/ToastProps.md +1 -1
  110. package/docs/api/interfaces/UnifiedAuthContextType.md +1 -1
  111. package/docs/api/interfaces/UnifiedAuthProviderProps.md +1 -1
  112. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  113. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  114. package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
  115. package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
  116. package/docs/api/interfaces/UsePublicFileDisplayOptions.md +1 -1
  117. package/docs/api/interfaces/UsePublicFileDisplayReturn.md +1 -1
  118. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  119. package/docs/api/interfaces/UseResolvedScopeOptions.md +1 -1
  120. package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
  121. package/docs/api/interfaces/UserEventAccess.md +1 -1
  122. package/docs/api/interfaces/UserMenuProps.md +1 -1
  123. package/docs/api/interfaces/UserProfile.md +1 -1
  124. package/docs/api/modules.md +39 -18
  125. package/docs/api-reference/utilities.md +26 -3
  126. package/docs/implementation-guides/data-tables.md +390 -0
  127. package/package.json +1 -1
  128. package/src/components/DataTable/DataTable.tsx +4 -0
  129. package/src/components/DataTable/__tests__/DataTableCore.test.tsx +25 -10
  130. package/src/components/DataTable/components/EditableRow.tsx +174 -16
  131. package/src/components/DataTable/components/UnifiedTableBody.tsx +205 -35
  132. package/src/components/DataTable/types.ts +34 -4
  133. package/src/components/FileDisplay/FileDisplay.test.tsx +184 -201
  134. package/src/components/FileDisplay/FileDisplay.tsx +40 -39
  135. package/src/components/NavigationMenu/NavigationMenu.test.tsx +189 -13
  136. package/src/components/NavigationMenu/NavigationMenu.tsx +142 -35
  137. package/src/components/PublicLayout/__tests__/PublicPageHeader.test.tsx +4 -4
  138. package/src/components/Toast/Toast.tsx +1 -1
  139. package/src/hooks/public/usePublicFileDisplay.ts +25 -15
  140. package/src/hooks/useEventTheme.test.ts +11 -0
  141. package/src/hooks/useFileDisplay.ts +11 -0
  142. package/src/hooks/useSecureDataAccess.test.ts +22 -5
  143. package/src/hooks/useToast.ts +11 -2
  144. package/src/providers/UnifiedAuthProvider.smoke.test.tsx +67 -3
  145. package/src/providers/__tests__/ProviderLifecycle.test.tsx +72 -4
  146. package/src/services/__tests__/OrganisationService.pagination.test.ts +10 -2
  147. package/src/styles/core.css +11 -0
  148. package/src/utils/__tests__/formatting.unit.test.ts +33 -0
  149. package/src/utils/file-reference.test.ts +44 -5
  150. package/src/utils/file-reference.ts +49 -26
  151. package/src/utils/formatting.ts +57 -2
  152. package/src/validation/__tests__/passwordSchema.unit.test.ts +3 -3
  153. package/dist/chunk-4BWGRQBG.js.map +0 -1
  154. package/dist/chunk-75G3NZWN.js.map +0 -1
  155. package/dist/chunk-AZFPGDCJ.js.map +0 -1
  156. package/dist/chunk-HBGPLSA5.js.map +0 -1
  157. package/dist/chunk-QPCAGLUS.js.map +0 -1
  158. /package/dist/{DataTable-LWHFLTEW.js.map → DataTable-H2WIR2DN.js.map} +0 -0
  159. /package/dist/{chunk-DWYMGSGU.js.map → chunk-VJ7MPS2K.js.map} +0 -0
@@ -1 +0,0 @@
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/usePublicFileDisplay.ts","../src/hooks/useFileDisplay.ts","../src/utils/file-reference.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 * Sanitizes the original filename to remove spaces and invalid characters for storage compatibility\n */\nexport function generateUniqueFileName(originalName: string): string {\n const timestamp = Date.now();\n const uuid = crypto.randomUUID();\n const extension = originalName.split('.').pop() || '';\n let baseName = originalName.replace(/\\.[^/.]+$/, '');\n \n // Sanitize the base name for storage compatibility\n // Replace spaces with underscores and remove invalid characters\n baseName = baseName\n .trim()\n .replace(/\\s+/g, '_') // Replace spaces with underscores\n .replace(/[<>:\"/\\\\|?*]/g, '') // Remove invalid file name characters\n .replace(/\\.\\./g, '') // Remove directory traversal attempts\n .replace(/^\\.+|\\.+$/g, '') // Remove leading/trailing dots\n .substring(0, 200); // Limit length to leave room for timestamp and UUID\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 File Display Hook\n * @package @jmruthers/pace-core\n * @module Hooks/Public\n * @since 1.0.0\n *\n * A React hook for accessing file references in public contexts without authentication.\n * Provides file URLs and metadata for public pages.\n *\n * Features:\n * - No authentication required\n * - Only returns public files (is_public = true)\n * - Caching for performance\n * - Error handling and loading states\n * - TypeScript support\n * - Supports both single file (category) and multiple files\n *\n * @example\n * ```tsx\n * import { usePublicFileDisplay } from '@jmruthers/pace-core';\n *\n * function PublicFileView() {\n * const { fileUrl, fileReference, isLoading, error } = usePublicFileDisplay(\n * 'event',\n * eventId,\n * organisationId,\n * FileCategory.EVENT_LOGOS,\n * { supabase }\n * );\n *\n * if (isLoading) return <div>Loading...</div>;\n * if (error) return <div>Error: {error.message}</div>;\n *\n * return fileUrl ? <img src={fileUrl} alt=\"File\" /> : null;\n * }\n * ```\n */\n\nimport { useState, useEffect, useCallback, useMemo } from 'react';\nimport type { SupabaseClient } from '@supabase/supabase-js';\nimport type { Database } from '../../types/database';\nimport { FileReference, FileCategory } from '../../types/file-reference';\nimport { getPublicUrl } from '../../utils/storage/helpers';\n\n// Simple in-memory cache for public file data\nconst publicFileCache = new Map<string, { data: any; timestamp: number; ttl: number }>();\n\nexport interface UsePublicFileDisplayReturn {\n /** Single file URL if category is provided and file found, null otherwise */\n fileUrl: string | null;\n /** Single file reference if category is provided and file found, null otherwise */\n fileReference: FileReference | null;\n /** Array of all file references for the record (when category not provided or for multiple files) */\n fileReferences: FileReference[];\n /** Map of file IDs to URLs for multiple files */\n fileUrls: Map<string, string>;\n /** Total count of files for the record */\n fileCount: number;\n /** Whether the data is currently loading */\n isLoading: boolean;\n /** Any error that occurred during loading */\n error: Error | null;\n /** Function to manually refetch the data */\n refetch: () => Promise<void>;\n}\n\nexport interface UsePublicFileDisplayOptions {\n /** Cache TTL in milliseconds (default: 30 minutes) */\n cacheTtl?: number;\n /** Whether to enable caching (default: true) */\n enableCache?: boolean;\n /** Supabase client instance (required) */\n supabase: SupabaseClient<Database>;\n}\n\n/**\n * Hook for accessing public file references\n * \n * This hook provides access to file references without requiring\n * authentication. It only returns public files and generates public URLs.\n * \n * @param table_name - The table name containing the file reference\n * @param record_id - The record ID that owns the file(s)\n * @param organisation_id - The organisation ID for storage path\n * @param category - Optional file category to filter by (for single file mode)\n * @param options - Configuration options for caching and behavior\n * @returns Object containing file data, loading state, error, and refetch function\n */\nexport function usePublicFileDisplay(\n table_name: string | undefined,\n record_id: string | undefined,\n organisation_id: string | undefined,\n category: FileCategory | undefined,\n options: UsePublicFileDisplayOptions\n): UsePublicFileDisplayReturn {\n const {\n cacheTtl = 30 * 60 * 1000, // 30 minutes\n enableCache = true,\n supabase\n } = options;\n\n const [fileUrl, setFileUrl] = useState<string | null>(null);\n const [fileReference, setFileReference] = useState<FileReference | null>(null);\n const [fileReferences, setFileReferences] = useState<FileReference[]>([]);\n const [fileUrls, setFileUrls] = useState<Map<string, string>>(new Map());\n const [fileCount, setFileCount] = useState<number>(0);\n const [isLoading, setIsLoading] = useState<boolean>(false);\n const [error, setError] = useState<Error | null>(null);\n\n const fetchFiles = useCallback(async (): Promise<void> => {\n if (!table_name || !record_id || !organisation_id || !supabase) {\n setFileUrl(null);\n setFileReference(null);\n setFileReferences([]);\n setFileUrls(new Map());\n setFileCount(0);\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(organisation_id)) {\n console.warn('[usePublicFileDisplay] Invalid organisationId format (not a valid UUID):', organisation_id);\n }\n\n // Check cache first\n const cacheKey = `public_file_${table_name}_${record_id}_${organisation_id}_${category || 'all'}`;\n if (enableCache) {\n const cached = publicFileCache.get(cacheKey);\n if (cached && Date.now() - cached.timestamp < cached.ttl) {\n const cachedData = cached.data;\n setFileUrl(cachedData.fileUrl || null);\n setFileReference(cachedData.fileReference || null);\n setFileReferences(cachedData.fileReferences || []);\n setFileUrls(cachedData.fileUrls || new Map());\n setFileCount(cachedData.fileCount || 0);\n setIsLoading(false);\n setError(null);\n return;\n }\n }\n\n try {\n setIsLoading(true);\n setError(null);\n\n let files: any[] = [];\n\n // CRITICAL: When category is provided, MUST use RPC function, not direct queries\n // Category is stored in file_metadata JSONB field, not a direct column\n if (category) {\n // Single file mode - use RPC to get files by category\n console.log('[usePublicFileDisplay] Using RPC function for category filtering:', {\n table_name,\n record_id,\n category,\n organisation_id\n });\n const { data, error: rpcError } = await (supabase as any)\n .rpc('data_file_reference_by_category_list', {\n p_table_name: table_name,\n p_record_id: record_id,\n p_category: category,\n p_organisation_id: organisation_id\n });\n\n if (rpcError) {\n throw new Error(rpcError.message || 'Failed to fetch file reference');\n }\n\n // RPC returns partial data, need to fetch full file references\n if (!data || data.length === 0) {\n files = [];\n } else {\n // Extract IDs from RPC response and fetch full file reference data\n // Note: This query does NOT filter by category - the RPC already did that filtering\n const ids = data.map((item: any) => item.id);\n const { data: fullData, error: fetchError } = await supabase\n .from('file_references')\n .select('*')\n .in('id', ids)\n .eq('is_public', true); // Only public files in public context\n\n if (fetchError) {\n throw new Error(fetchError.message || 'Failed to fetch file references');\n }\n\n files = fullData || [];\n }\n } else {\n // Multiple files mode - use RPC to get all files\n const { data: fileIds, error: rpcError } = await (supabase as any)\n .rpc('data_file_reference_list', {\n p_table_name: table_name,\n p_record_id: record_id,\n p_organisation_id: organisation_id\n });\n\n if (rpcError) {\n throw new Error(rpcError.message || 'Failed to fetch file references');\n }\n\n if (!fileIds || fileIds.length === 0) {\n files = [];\n } else {\n // Fetch full file reference data for each ID, but only public files\n const ids = fileIds.map((item: any) => item.id);\n const { data: fullData, error: fetchError } = await supabase\n .from('file_references')\n .select('*')\n .in('id', ids)\n .eq('is_public', true); // Only public files in public context\n\n if (fetchError) {\n throw new Error(fetchError.message || 'Failed to fetch file references');\n }\n\n files = fullData || [];\n }\n }\n\n // Ensure all files are public (category RPC might return both)\n const publicFiles = files.filter((f: any) => f.is_public === true);\n\n if (publicFiles.length === 0) {\n setFileUrl(null);\n setFileReference(null);\n setFileReferences([]);\n setFileUrls(new Map());\n setFileCount(0);\n \n // Cache empty result\n if (enableCache) {\n publicFileCache.set(cacheKey, {\n data: { fileUrl: null, fileReference: null, fileReferences: [], fileUrls: new Map(), fileCount: 0 },\n timestamp: Date.now(),\n ttl: cacheTtl\n });\n }\n return;\n }\n\n // Convert to FileReference format\n const fileRefs: FileReference[] = publicFiles.map((f: any) => ({\n id: f.id,\n table_name: f.table_name,\n record_id: f.record_id,\n file_path: f.file_path,\n file_metadata: f.file_metadata || {},\n organisation_id: f.organisation_id,\n app_id: f.app_id,\n is_public: f.is_public ?? true,\n created_at: f.created_at,\n updated_at: f.updated_at\n }));\n\n setFileReferences(fileRefs);\n setFileCount(fileRefs.length);\n\n if (category && fileRefs.length > 0) {\n // Single file mode - get first file\n const firstFile = fileRefs[0];\n setFileReference(firstFile);\n \n // Generate public URL\n const url = getPublicUrl(supabase, firstFile.file_path, true);\n setFileUrl(url);\n } else {\n // Multiple files mode - generate URLs for all files\n const urlMap = new Map<string, string>();\n for (const fileRef of fileRefs) {\n const url = getPublicUrl(supabase, fileRef.file_path, true);\n if (url) {\n urlMap.set(fileRef.id, url);\n }\n }\n setFileUrls(urlMap);\n setFileReference(null);\n setFileUrl(null);\n }\n\n // Cache the result\n if (enableCache) {\n publicFileCache.set(cacheKey, {\n data: {\n fileUrl: category ? (fileRefs.length > 0 ? getPublicUrl(supabase, fileRefs[0].file_path, true) : null) : null,\n fileReference: category && fileRefs.length > 0 ? fileRefs[0] : null,\n fileReferences: fileRefs,\n fileUrls: category ? new Map() : (() => {\n const urlMap = new Map<string, string>();\n for (const fileRef of fileRefs) {\n const url = getPublicUrl(supabase, fileRef.file_path, true);\n if (url) {\n urlMap.set(fileRef.id, url);\n }\n }\n return urlMap;\n })(),\n fileCount: fileRefs.length\n },\n timestamp: Date.now(),\n ttl: cacheTtl\n });\n }\n\n } catch (err) {\n console.error('[usePublicFileDisplay] Error fetching files:', err);\n const error = err instanceof Error ? err : new Error('Unknown error occurred');\n setError(error);\n setFileUrl(null);\n setFileReference(null);\n setFileReferences([]);\n setFileUrls(new Map());\n setFileCount(0);\n } finally {\n setIsLoading(false);\n }\n }, [table_name, record_id, organisation_id, category, supabase, cacheTtl, enableCache]);\n\n // Fetch files when parameters change\n useEffect(() => {\n if (table_name && record_id && organisation_id) {\n fetchFiles();\n } else {\n setFileUrl(null);\n setFileReference(null);\n setFileReferences([]);\n setFileUrls(new Map());\n setFileCount(0);\n setIsLoading(false);\n setError(null);\n }\n }, [fetchFiles, table_name, record_id, organisation_id]);\n\n const refetch = useCallback(async (): Promise<void> => {\n if (!table_name || !record_id || !organisation_id) return;\n \n // Clear cache for this file\n if (enableCache) {\n const cacheKey = `public_file_${table_name}_${record_id}_${organisation_id}_${category || 'all'}`;\n publicFileCache.delete(cacheKey);\n }\n await fetchFiles();\n }, [fetchFiles, table_name, record_id, organisation_id, category, enableCache]);\n\n return {\n fileUrl,\n fileReference,\n fileReferences,\n fileUrls,\n fileCount,\n isLoading,\n error,\n refetch\n };\n}\n\n/**\n * Clear all cached public file data\n * Useful for testing or when you need to force refresh all data\n */\nexport function clearPublicFileDisplayCache(): void {\n for (const [key] of publicFileCache) {\n if (key.startsWith('public_file_')) {\n publicFileCache.delete(key);\n }\n }\n}\n\n/**\n * Get cache statistics for debugging\n */\nexport function getPublicFileDisplayCacheStats(): { size: number; keys: string[] } {\n const keys = Array.from(publicFileCache.keys()).filter(key => key.startsWith('public_file_'));\n return {\n size: keys.length,\n keys\n };\n}\n\n","/**\n * @file File Display Hook (Authenticated)\n * @package @jmruthers/pace-core\n * @module Hooks\n *\n * A React hook for accessing file references in authenticated contexts.\n * Can handle both public and private files using the file_references system.\n *\n * Features:\n * - Works in authenticated contexts\n * - Supports both public and private files\n * - Automatic signed URL generation for private files\n * - Caching for performance\n * - Error handling and loading states\n * - Supports both single file (category) and multiple files\n *\n * @example\n * ```tsx\n * import { useFileDisplay } from '@jmruthers/pace-core';\n *\n * function FileView() {\n * const { fileUrl, fileReference, isLoading, error } = useFileDisplay(\n * 'event',\n * eventId,\n * organisationId,\n * FileCategory.EVENT_LOGOS\n * );\n *\n * if (isLoading) return <div>Loading...</div>;\n * if (error) return <div>Error: {error.message}</div>;\n *\n * return fileUrl ? <img src={fileUrl} alt=\"File\" /> : null;\n * }\n * ```\n */\n\nimport { useState, useEffect, useCallback } from 'react';\nimport type { SupabaseClient } from '@supabase/supabase-js';\nimport { FileReference, FileCategory } from '../types/file-reference';\nimport { getPublicUrl, getSignedUrl } from '../utils/storage/helpers';\nimport { createFileReferenceService } from '../utils/file-reference';\n\n// Simple in-memory cache for authenticated file data\nconst authenticatedFileCache = new Map<string, { data: any; timestamp: number; ttl: number }>();\n\n// Cache size limit to prevent memory leaks\nconst MAX_CACHE_SIZE = 100;\n\n// Helper function to clean up expired entries and enforce size limit\nfunction cleanupCache() {\n const now = Date.now();\n const entries = Array.from(authenticatedFileCache.entries());\n \n // Remove expired entries\n const expiredKeys: string[] = [];\n entries.forEach(([key, value]) => {\n if (now - value.timestamp >= value.ttl) {\n expiredKeys.push(key);\n }\n });\n expiredKeys.forEach(key => authenticatedFileCache.delete(key));\n \n // If still over limit, remove oldest entries\n if (authenticatedFileCache.size > MAX_CACHE_SIZE) {\n const sorted = entries\n .filter(([key]) => !expiredKeys.includes(key))\n .sort((a, b) => a[1].timestamp - b[1].timestamp);\n const toRemove = sorted.slice(0, authenticatedFileCache.size - MAX_CACHE_SIZE);\n toRemove.forEach(([key]) => authenticatedFileCache.delete(key));\n }\n}\n\nexport interface UseFileDisplayReturn {\n /** Single file URL if category is provided and file found, null otherwise */\n fileUrl: string | null;\n /** Single file reference if category is provided and file found, null otherwise */\n fileReference: FileReference | null;\n /** Array of all file references for the record (when category not provided or for multiple files) */\n fileReferences: FileReference[];\n /** Map of file IDs to URLs for multiple files */\n fileUrls: Map<string, string>;\n /** Total count of files for the record */\n fileCount: number;\n /** Whether the data is currently loading */\n isLoading: boolean;\n /** Any error that occurred during loading */\n error: Error | null;\n /** Function to manually refetch the data */\n refetch: () => Promise<void>;\n}\n\nexport interface UseFileDisplayOptions {\n /** Cache TTL in milliseconds (default: 30 minutes) */\n cacheTtl?: number;\n /** Whether to enable caching (default: true) */\n enableCache?: boolean;\n /** Supabase client instance (required) */\n supabase: SupabaseClient | null;\n}\n\n/**\n * Hook for accessing file references in authenticated contexts\n * \n * This hook provides access to file references for authenticated users.\n * It supports both public and private files, generating appropriate URLs\n * (public URLs for public files, signed URLs for private files).\n * \n * @param table_name - The table name containing the file reference\n * @param record_id - The record ID that owns the file(s)\n * @param organisation_id - The organisation ID for storage path\n * @param category - Optional file category to filter by (for single file mode)\n * @param options - Configuration options for caching and behavior\n * @returns Object containing file data, loading state, error, and refetch function\n */\nexport function useFileDisplay(\n table_name: string | undefined,\n record_id: string | undefined,\n organisation_id: string | undefined,\n category: FileCategory | undefined,\n options: UseFileDisplayOptions\n): UseFileDisplayReturn {\n const {\n cacheTtl = 30 * 60 * 1000, // 30 minutes\n enableCache = true,\n supabase\n } = options;\n\n const [fileUrl, setFileUrl] = useState<string | null>(null);\n const [fileReference, setFileReference] = useState<FileReference | null>(null);\n const [fileReferences, setFileReferences] = useState<FileReference[]>([]);\n const [fileUrls, setFileUrls] = useState<Map<string, string>>(new Map());\n const [fileCount, setFileCount] = useState<number>(0);\n const [isLoading, setIsLoading] = useState<boolean>(false);\n const [error, setError] = useState<Error | null>(null);\n\n const fetchFiles = useCallback(async (): Promise<void> => {\n if (!table_name || !record_id || !organisation_id || !supabase) {\n setFileUrl(null);\n setFileReference(null);\n setFileReferences([]);\n setFileUrls(new Map());\n setFileCount(0);\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(organisation_id)) {\n console.warn('[useFileDisplay] Invalid organisationId format (not a valid UUID):', organisation_id);\n }\n\n // Check cache first\n const cacheKey = `file_${table_name}_${record_id}_${organisation_id}_${category || 'all'}`;\n if (enableCache) {\n const cached = authenticatedFileCache.get(cacheKey);\n if (cached && Date.now() - cached.timestamp < cached.ttl) {\n const cachedData = cached.data;\n setFileUrl(cachedData.fileUrl || null);\n setFileReference(cachedData.fileReference || null);\n setFileReferences(cachedData.fileReferences || []);\n setFileUrls(cachedData.fileUrls || new Map());\n setFileCount(cachedData.fileCount || 0);\n setIsLoading(false);\n setError(null);\n return;\n }\n }\n\n try {\n setIsLoading(true);\n setError(null);\n\n const service = createFileReferenceService(supabase);\n let files: FileReference[] = [];\n\n // CRITICAL: When category is provided, MUST use RPC function, not direct queries\n // Category is stored in file_metadata JSONB field, not a direct column\n if (category) {\n // Single file mode - get files by category using RPC\n console.log('[useFileDisplay] Using RPC function for category filtering:', {\n table_name,\n record_id,\n category,\n organisation_id\n });\n files = await service.getFilesByCategory(\n table_name,\n record_id,\n category,\n organisation_id\n );\n } else {\n // Multiple files mode - get all files using RPC\n files = await service.listFileReferences(\n table_name,\n record_id,\n organisation_id\n );\n }\n\n if (files.length === 0) {\n setFileUrl(null);\n setFileReference(null);\n setFileReferences([]);\n setFileUrls(new Map());\n setFileCount(0);\n \n // Cache empty result\n if (enableCache) {\n authenticatedFileCache.set(cacheKey, {\n data: { fileUrl: null, fileReference: null, fileReferences: [], fileUrls: new Map(), fileCount: 0 },\n timestamp: Date.now(),\n ttl: cacheTtl\n });\n cleanupCache();\n }\n return;\n }\n\n setFileReferences(files);\n setFileCount(files.length);\n\n if (category && files.length > 0) {\n // Single file mode - get first file\n const firstFile = files[0];\n setFileReference(firstFile);\n \n // Generate URL based on file visibility\n let url: string | null = null;\n if (firstFile.is_public) {\n url = getPublicUrl(supabase, firstFile.file_path, true);\n } else {\n const signedUrlResult = await getSignedUrl(supabase, firstFile.file_path, {\n appName: 'pace-core',\n orgId: organisation_id,\n expiresIn: 3600\n });\n url = signedUrlResult?.url || null;\n }\n setFileUrl(url);\n } else {\n // Multiple files mode - generate URLs for all files\n const urlMap = new Map<string, string>();\n for (const fileRef of files) {\n let url: string | null = null;\n if (fileRef.is_public) {\n url = getPublicUrl(supabase, fileRef.file_path, true);\n } else {\n const signedUrlResult = await getSignedUrl(supabase, fileRef.file_path, {\n appName: 'pace-core',\n orgId: organisation_id,\n expiresIn: 3600\n });\n url = signedUrlResult?.url || null;\n }\n if (url) {\n urlMap.set(fileRef.id, url);\n }\n }\n setFileUrls(urlMap);\n setFileReference(null);\n setFileUrl(null);\n }\n\n // Cache the result\n if (enableCache) {\n // Prepare cache data\n let cacheData: any = {\n fileReference: category && files.length > 0 ? files[0] : null,\n fileReferences: files,\n fileUrls: new Map(),\n fileCount: files.length\n };\n\n if (category && files.length > 0) {\n const firstFile = files[0];\n let url: string | null = null;\n if (firstFile.is_public) {\n url = getPublicUrl(supabase, firstFile.file_path, true);\n }\n cacheData.fileUrl = url;\n } else {\n const urlMap = new Map<string, string>();\n for (const fileRef of files) {\n if (fileRef.is_public) {\n const url = getPublicUrl(supabase, fileRef.file_path, true);\n if (url) {\n urlMap.set(fileRef.id, url);\n }\n }\n }\n cacheData.fileUrls = urlMap;\n }\n\n authenticatedFileCache.set(cacheKey, {\n data: cacheData,\n timestamp: Date.now(),\n ttl: cacheTtl\n });\n cleanupCache();\n }\n\n } catch (err) {\n console.error('[useFileDisplay] Error fetching files:', err);\n const error = err instanceof Error ? err : new Error('Unknown error occurred');\n setError(error);\n setFileUrl(null);\n setFileReference(null);\n setFileReferences([]);\n setFileUrls(new Map());\n setFileCount(0);\n } finally {\n setIsLoading(false);\n }\n }, [table_name, record_id, organisation_id, category, supabase, cacheTtl, enableCache]);\n\n // Fetch files when parameters change\n useEffect(() => {\n if (table_name && record_id && organisation_id && supabase) {\n fetchFiles();\n } else {\n setFileUrl(null);\n setFileReference(null);\n setFileReferences([]);\n setFileUrls(new Map());\n setFileCount(0);\n setIsLoading(false);\n setError(null);\n }\n }, [fetchFiles, table_name, record_id, organisation_id, supabase]);\n\n const refetch = useCallback(async (): Promise<void> => {\n if (!table_name || !record_id || !organisation_id || !supabase) return;\n \n // Clear cache for this file\n if (enableCache) {\n const cacheKey = `file_${table_name}_${record_id}_${organisation_id}_${category || 'all'}`;\n authenticatedFileCache.delete(cacheKey);\n }\n await fetchFiles();\n }, [fetchFiles, table_name, record_id, organisation_id, category, supabase, enableCache]);\n\n return {\n fileUrl,\n fileReference,\n fileReferences,\n fileUrls,\n fileCount,\n isLoading,\n error,\n refetch\n };\n}\n\n/**\n * Clear all cached authenticated file data\n * Useful for testing or when you need to force refresh all data\n */\nexport function clearFileDisplayCache(): void {\n for (const [key] of authenticatedFileCache) {\n if (key.startsWith('file_')) {\n authenticatedFileCache.delete(key);\n }\n }\n}\n\n/**\n * Get cache statistics for debugging\n */\nexport function getFileDisplayCacheStats(): { size: number; keys: string[] } {\n const keys = Array.from(authenticatedFileCache.keys()).filter(key => key.startsWith('file_'));\n return {\n size: keys.length,\n keys\n };\n}\n\n","// File Reference Service\n// Provides CRUD operations for the centralized file reference system\n\nimport { SupabaseClient } from '@supabase/supabase-js';\nimport { \n FileReference, \n FileUploadOptions, \n FileReferenceService, \n FileUploadResult,\n FileCategory \n} from '../types/file-reference';\nimport { uploadFile, getPublicUrl, getSignedUrl, deleteFile, extractFileMetadata } from './storage/helpers';\nimport { setOrganisationContext } from './organisationContext';\n\nexport class FileReferenceServiceImpl implements FileReferenceService {\n constructor(private supabase: SupabaseClient) {}\n\n /**\n * Creates a file reference by uploading a file to storage and linking it in the database.\n * \n * Storage Flow:\n * 1. Upload file to storage bucket first (files or public-files based on is_public flag)\n * - Path format: {orgId}/{category}/{timestamp-uuid-filename}\n * - Bucket selection: 'files' (private) or 'public-files' (public)\n * 2. Extract file metadata (dimensions, hash, etc.)\n * 3. Set organisation context for RLS policies\n * 4. Create database reference via RPC function\n * 5. If DB insert fails, rollback by deleting uploaded file\n * \n * This ensures atomicity: either both storage and DB succeed, or both are cleaned up.\n */\n async createFileReference(options: FileUploadOptions, file: File): Promise<FileReference> {\n try {\n\n // Validate required options\n if (!options.organisation_id) {\n throw new Error('organisation_id is required for file upload');\n }\n if (!options.table_name) {\n throw new Error('table_name is required for file upload');\n }\n if (!options.record_id) {\n throw new Error('record_id is required for file upload');\n }\n\n // Step 1: Upload file to storage bucket first\n // This generates a unique path: {orgId}/{category}/{timestamp-uuid-filename}\n // Bucket is automatically selected based on is_public flag\n const uploadResult = await uploadFile(this.supabase, file, {\n appName: 'file-reference',\n orgId: options.organisation_id,\n isPublic: options.is_public || false,\n customPath: options.category // Use category as the custom path segment\n });\n if (!uploadResult.success) {\n throw new Error(`Failed to upload file: ${uploadResult.error}`);\n }\n\n if (!uploadResult.path) {\n throw new Error('File upload did not return a path');\n }\n\n const filePath = uploadResult.path;\n\n // Step 2: Extract file metadata (dimensions, hash, etc.)\n const metadata = await extractFileMetadata(file, {\n appName: 'file-reference',\n orgId: options.organisation_id,\n isPublic: options.is_public || false\n }, 'system');\n\n // Step 3: Set organisation context in database session before creating file reference\n // This ensures RLS policies can check the organisation context\n await setOrganisationContext(this.supabase, options.organisation_id);\n\n // Step 4: Create file reference in database using RPC function\n // This links the storage path to the record in file_references table\n const { data, error } = await this.supabase\n .rpc('data_file_reference_create', {\n p_table_name: options.table_name,\n p_record_id: options.record_id,\n p_file_path: filePath, // Storage path from step 1\n p_organisation_id: options.organisation_id,\n p_app_id: options.app_id,\n p_file_metadata: {\n fileName: file.name,\n fileType: file.type,\n fileSize: file.size,\n category: options.category,\n ...metadata,\n ...options.custom_metadata\n },\n p_is_public: options.is_public || false\n });\n\n // Step 5: Rollback - if database insert fails, clean up uploaded file\n if (error) {\n await deleteFile(this.supabase, filePath, options.is_public || false);\n throw new Error(`Failed to create file reference: ${error.message}`);\n }\n\n // Get the created file reference\n const { data: fileRef, error: fetchError } = await this.supabase\n .from('file_references')\n .select('*')\n .eq('id', data)\n .single();\n\n if (fetchError || !fileRef) {\n throw new Error(`Failed to fetch created file reference: ${fetchError?.message}`);\n }\n\n return fileRef as FileReference;\n } catch (error) {\n console.error('Error creating file reference:', error);\n throw error;\n }\n }\n\n async getFileReference(table_name: string, record_id: string, organisation_id: string): Promise<FileReference | null> {\n try {\n const { data, error } = await this.supabase\n .from('file_references')\n .select('*')\n .eq('table_name', table_name)\n .eq('record_id', record_id)\n .eq('organisation_id', organisation_id)\n .single();\n\n if (error) {\n if (error.code === 'PGRST116') {\n return null; // No rows found\n }\n throw new Error(`Failed to get file reference: ${error.message}`);\n }\n\n return data as FileReference;\n } catch (error) {\n console.error('Error getting file reference:', error);\n throw error;\n }\n }\n\n async getFileUrl(table_name: string, record_id: string, organisation_id: string): Promise<string | null> {\n try {\n // Get file reference to check if it's public\n const fileRef = await this.getFileReference(table_name, record_id, organisation_id);\n if (!fileRef) {\n return null;\n }\n\n // For public files, RPC returns file path - generate public URL client-side\n if (fileRef.is_public) {\n const { data: pathData } = await this.supabase\n .rpc('data_file_reference_url_get', {\n p_table_name: table_name,\n p_record_id: record_id,\n p_organisation_id: organisation_id\n });\n\n if (!pathData) {\n return null;\n }\n\n // Generate public URL using bucket-aware helper\n return getPublicUrl(this.supabase, pathData, true);\n } else {\n // For private files, use signed URL\n return await this.getSignedUrl(table_name, record_id, organisation_id);\n }\n } catch (error) {\n console.error('Error getting file URL:', error);\n throw error;\n }\n }\n\n async getSignedUrl(table_name: string, record_id: string, organisation_id: string, expires_in: number = 3600): Promise<string | null> {\n try {\n // Get file path from RPC function\n const { data: filePath, error } = await this.supabase\n .rpc('data_file_reference_signed_url_get', {\n p_table_name: table_name,\n p_record_id: record_id,\n p_organisation_id: organisation_id,\n p_expires_in: expires_in\n });\n\n if (error) {\n throw new Error(`Failed to get signed URL: ${error.message}`);\n }\n\n if (!filePath) {\n return null;\n }\n\n // Generate signed URL client-side using bucket-aware helper (files bucket for private files)\n const signedUrlResult = await getSignedUrl(this.supabase, filePath, {\n appName: 'file-reference',\n orgId: organisation_id,\n expiresIn: expires_in\n });\n\n return signedUrlResult?.url || null;\n } catch (error) {\n console.error('Error getting signed URL:', error);\n throw error;\n }\n }\n\n async updateFileReference(id: string, updates: Partial<FileReference>): Promise<FileReference> {\n try {\n const { data, error } = await this.supabase\n .from('file_references')\n .update(updates)\n .eq('id', id)\n .select()\n .single();\n\n if (error) {\n throw new Error(`Failed to update file reference: ${error.message}`);\n }\n\n return data as FileReference;\n } catch (error) {\n console.error('Error updating file reference:', error);\n throw error;\n }\n }\n\n async deleteFileReference(table_name: string, record_id: string, organisation_id: string, delete_file: boolean = false): Promise<boolean> {\n try {\n // Get file reference first to determine bucket\n const fileRef = await this.getFileReference(table_name, record_id, organisation_id);\n \n const { error } = await this.supabase\n .rpc('data_file_reference_delete', {\n p_table_name: table_name,\n p_record_id: record_id,\n p_organisation_id: organisation_id,\n p_delete_file: delete_file\n });\n\n if (error) {\n throw new Error(`Failed to delete file reference: ${error.message}`);\n }\n\n // If delete_file is true and we have the file reference, delete from storage\n if (delete_file && fileRef) {\n await deleteFile(this.supabase, fileRef.file_path, fileRef.is_public || false);\n }\n\n return true;\n } catch (error) {\n console.error('Error deleting file reference:', error);\n throw error;\n }\n }\n\n async listFileReferences(table_name: string, record_id: string, organisation_id: string): Promise<FileReference[]> {\n try {\n const { data, error } = await this.supabase\n .rpc('data_file_reference_list', {\n p_table_name: table_name,\n p_record_id: record_id,\n p_organisation_id: organisation_id\n });\n\n if (error) {\n throw new Error(`Failed to list file references: ${error.message}`);\n }\n\n // RPC returns partial data, need to fetch full file references\n if (!data || data.length === 0) {\n return [];\n }\n\n // Fetch full file reference data for each ID\n const ids = data.map((item: any) => item.id);\n const { data: fullData, error: fetchError } = await this.supabase\n .from('file_references')\n .select('*')\n .in('id', ids);\n\n if (fetchError) {\n throw new Error(`Failed to fetch file references: ${fetchError.message}`);\n }\n\n return (fullData || []) as FileReference[];\n } catch (error) {\n console.error('Error listing file references:', error);\n throw error;\n }\n }\n\n async getFileCount(table_name: string, record_id: string, organisation_id: string): Promise<number> {\n try {\n const { data, error } = await this.supabase\n .rpc('data_file_reference_count_get', {\n p_table_name: table_name,\n p_record_id: record_id,\n p_organisation_id: organisation_id\n });\n\n if (error) {\n throw new Error(`Failed to get file count: ${error.message}`);\n }\n\n return data || 0;\n } catch (error) {\n console.error('Error getting file count:', error);\n throw error;\n }\n }\n\n async getFileReferenceById(id: string, organisation_id: string): Promise<FileReference | null> {\n try {\n const { data, error } = await this.supabase\n .rpc('data_file_reference_get', {\n p_file_reference_id: id,\n p_organisation_id: organisation_id\n });\n\n if (error) {\n throw new Error(`Failed to get file reference by ID: ${error.message}`);\n }\n\n if (!data || data.length === 0) {\n return null;\n }\n\n return data[0] as FileReference;\n } catch (error) {\n console.error('Error getting file reference by ID:', error);\n throw error;\n }\n }\n\n async getFilesByCategory(\n table_name: string, \n record_id: string, \n category: FileCategory, \n organisation_id: string\n ): Promise<FileReference[]> {\n try {\n // CRITICAL: Use RPC function to get files by category - this correctly filters on file_metadata->>'category'\n // NOTE: We MUST use RPC function. Direct queries with .eq('category', ...) will FAIL with HTTP 406\n // because there is NO 'category' column. The category is stored in the JSONB file_metadata field.\n console.log('[FileReferenceService.getFilesByCategory] Calling RPC function:', {\n table_name,\n record_id,\n category,\n organisation_id\n });\n const { data, error } = await this.supabase\n .rpc('data_file_reference_by_category_list', {\n p_table_name: table_name,\n p_record_id: record_id,\n p_category: category,\n p_organisation_id: organisation_id\n });\n\n if (error) {\n // Provide clear error message about category filtering\n console.error('[FileReferenceService.getFilesByCategory] RPC ERROR:', {\n error,\n errorCode: error.code,\n errorMessage: error.message,\n errorDetails: error.details,\n table_name,\n record_id,\n category,\n organisation_id,\n message: 'CRITICAL: Category filtering MUST use RPC function data_file_reference_by_category_list. Direct queries with .eq(\\'category\\', ...) will FAIL with HTTP 406 because category is stored in file_metadata JSONB field, not a direct column.'\n });\n throw new Error(`Failed to get files by category: ${error.message}. Category filtering uses file_metadata JSONB field, not a direct column. RPC function required.`);\n }\n\n // RPC returns partial data, need to fetch full file references\n if (!data || data.length === 0) {\n return [];\n }\n\n // Fetch full file reference data for each ID\n // Note: This query does NOT filter by category - the RPC already did that filtering\n const ids = data.map((item: any) => item.id);\n const { data: fullData, error: fetchError } = await this.supabase\n .from('file_references')\n .select('*')\n .in('id', ids);\n\n if (fetchError) {\n throw new Error(`Failed to fetch file references: ${fetchError.message}`);\n }\n\n // Verify that all returned files match the category (defensive check)\n const filteredFiles = (fullData || []).filter((file: any) => {\n const fileCategory = file.file_metadata?.category;\n return fileCategory === category;\n });\n\n if (filteredFiles.length !== fullData.length) {\n console.warn('[FileReferenceService] RPC returned files with mismatched categories. Filtering client-side.', {\n expected: category,\n returned: fullData.map((f: any) => f.file_metadata?.category),\n filtered: filteredFiles.length,\n total: fullData.length\n });\n }\n\n return filteredFiles as FileReference[];\n } catch (error) {\n console.error('Error getting files by category:', error);\n throw error;\n }\n }\n\n async uploadMultipleFiles(\n options: FileUploadOptions,\n files: File[]\n ): Promise<import('../types/file-reference').BulkUploadResult> {\n const success: FileReference[] = [];\n const failed: { file: File; error: string }[] = [];\n const results: Array<{ file: File; result: FileUploadResult | null; error?: string }> = [];\n\n // Upload files sequentially to avoid overwhelming the server\n for (const file of files) {\n try {\n const fileReference = await this.createFileReference(options, file);\n\n success.push(fileReference);\n results.push({\n file,\n result: {\n file_reference: fileReference,\n file_url: fileReference.is_public\n ? getPublicUrl(this.supabase, fileReference.file_path, true)\n : '',\n },\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n failed.push({ file, error: message });\n results.push({ file, result: null, error: message });\n }\n }\n\n return {\n success,\n failed,\n total: results.length,\n successful: success.length,\n results,\n };\n }\n}\n\n// Factory function to create file reference service\nexport function createFileReferenceService(supabase: SupabaseClient): FileReferenceService {\n return new FileReferenceServiceImpl(supabase);\n}\n\n// Helper function to upload file and create reference in one operation\nexport async function uploadFileWithReference(\n supabase: SupabaseClient,\n options: FileUploadOptions,\n file: File\n): Promise<FileUploadResult> {\n \n const service = createFileReferenceService(supabase);\n const fileReference = await service.createFileReference(options, file);\n \n const fileUrl = options.is_public \n ? getPublicUrl(supabase, fileReference.file_path, true)\n : await getSignedUrl(supabase, fileReference.file_path, { \n appName: 'file-reference',\n orgId: options.organisation_id,\n expiresIn: 3600 \n });\n\n const urlString = typeof fileUrl === 'string' ? fileUrl : fileUrl?.url || '';\n\n return {\n file_reference: fileReference,\n file_url: urlString,\n signed_url: options.is_public ? undefined : urlString || undefined\n };\n}\n"],"mappings":"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","names":["error","jsx","useMemo","useMemo","error","useState","useEffect","useCallback","useState","useCallback","error","useEffect"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/hooks/useToast.ts","../src/components/DataTable/utils/performanceUtils.ts","../src/components/DataTable/utils/errorHandling.ts","../src/hooks/useDataTablePerformance.ts"],"sourcesContent":["\n/**\n * @file Toast hook for managing toast notifications\n * @package @jmruthers/pace-core\n * @module Hooks\n * @since 0.1.0\n */\n\nimport * as React from \"react\"\n\n/** Maximum number of toasts to show at once */\nconst TOAST_LIMIT = 5\n/** Delay before removing a dismissed toast */\nconst TOAST_REMOVE_DELAY = 1000\n\nexport interface ToastProps {\n title?: React.ReactNode;\n description?: React.ReactNode;\n variant?: 'default' | 'destructive' | 'success';\n duration?: number;\n onClose?: () => void;\n action?: React.ReactElement;\n}\n\n/**\n * Extended toast props with additional properties\n * @interface ToasterToast\n */\ntype ToasterToast = ToastProps & {\n /** Unique identifier for the toast */\n id: string\n /** Optional title content */\n title?: React.ReactNode\n /** Optional description content */\n description?: React.ReactNode\n /** Optional action button */\n action?: React.ReactElement\n /** Open state */\n open?: boolean\n /** Open change handler */\n onOpenChange?: (open: boolean) => void\n /** Dismiss function */\n dismiss?: () => void\n}\n\n/**\n * State interface for toast management\n */\ninterface State {\n /** Array of active toasts */\n toasts: ToasterToast[]\n}\n\n/** Map of toast IDs to their removal timeouts */\nconst toastTimeouts = new Map<string, ReturnType<typeof setTimeout>>()\n\n/** Current toast state */\nlet memoryState: State = {\n toasts: [],\n}\n\n/** List of state change listeners */\nconst listeners: Array<(state: State) => void> = []\n\n/**\n * Reset the toast state and clear all timeouts\n */\nexport function reset() {\n memoryState = { toasts: [] }\n toastTimeouts.forEach((timeout) => clearTimeout(timeout))\n toastTimeouts.clear()\n}\n\n/**\n * Dispatch a state change\n * @param action - Action to dispatch\n */\nfunction dispatch(action: {\n type: \"ADD_TOAST\" | \"UPDATE_TOAST\" | \"DISMISS_TOAST\" | \"REMOVE_TOAST\"\n toast?: ToasterToast\n toastId?: string\n}) {\n memoryState = reducer(memoryState, action)\n listeners.forEach((listener) => {\n listener(memoryState)\n })\n}\n\n/**\n * Generate a unique ID for a toast\n * @returns Unique ID string\n */\nfunction genId() {\n return Math.random().toString(36).substring(2, 9)\n}\n\n/**\n * Add a toast to the removal queue\n * @param toastId - ID of the toast to remove\n */\nconst addToRemoveQueue = (toastId: string) => {\n if (toastTimeouts.has(toastId)) {\n return\n }\n\n const timeout = setTimeout(() => {\n toastTimeouts.delete(toastId)\n dispatch({\n type: \"REMOVE_TOAST\",\n toastId: toastId,\n })\n }, TOAST_REMOVE_DELAY)\n\n toastTimeouts.set(toastId, timeout)\n}\n\n/**\n * State reducer for toast management\n * @param state - Current state\n * @param action - Action to process\n * @returns New state\n */\nfunction reducer(state: State, action: {\n type: \"ADD_TOAST\" | \"UPDATE_TOAST\" | \"DISMISS_TOAST\" | \"REMOVE_TOAST\"\n toast?: ToasterToast\n toastId?: string\n}): State {\n switch (action.type) {\n case \"ADD_TOAST\":\n return {\n ...state,\n toasts: [action.toast!, ...state.toasts].slice(0, TOAST_LIMIT),\n }\n\n case \"UPDATE_TOAST\":\n return {\n ...state,\n toasts: state.toasts.map((t) =>\n t.id === action.toast?.id ? { ...t, ...action.toast } : t\n ),\n }\n\n case \"DISMISS_TOAST\": {\n const { toastId } = action\n\n if (toastId) {\n addToRemoveQueue(toastId)\n }\n\n return {\n ...state,\n toasts: state.toasts.map((t) =>\n t.id === toastId || toastId === undefined\n ? {\n ...t,\n open: false,\n }\n : t\n ),\n }\n }\n\n case \"REMOVE_TOAST\":\n if (action.toastId === undefined) {\n return {\n ...state,\n toasts: [],\n }\n }\n return {\n ...state,\n toasts: state.toasts.filter((t) => t.id !== action.toastId),\n }\n }\n}\n\n/**\n * Toast configuration without ID\n */\ntype Toast = Omit<ToasterToast, \"id\">\n\n/**\n * Creates a new toast notification\n * @param props - Toast configuration\n * @returns Object with toast ID and control methods\n */\nfunction toast({ ...props }: Toast) {\n const id = genId()\n\n const update = (props: Partial<Omit<ToasterToast, \"id\">>) =>\n dispatch({\n type: \"UPDATE_TOAST\",\n toast: { ...props, id },\n })\n const dismiss = () => dispatch({ type: \"DISMISS_TOAST\", toastId: id })\n\n dispatch({\n type: \"ADD_TOAST\",\n toast: {\n ...props,\n id,\n open: true,\n dismiss,\n onOpenChange: (open) => {\n if (!open) dismiss()\n },\n },\n })\n\n return {\n id: id,\n dismiss,\n update,\n }\n}\n\n/**\n * Hook for managing toast notifications\n * @returns Object with toast state and control methods\n */\nfunction useToast() {\n const [state, setState] = React.useState<State>(memoryState)\n\n React.useEffect(() => {\n listeners.push(setState)\n return () => {\n const index = listeners.indexOf(setState)\n if (index > -1) {\n listeners.splice(index, 1)\n }\n }\n }, [state])\n\n return {\n ...state,\n toast,\n dismiss: (toastId?: string) => dispatch({ type: \"DISMISS_TOAST\", toastId }),\n }\n}\n\nexport { useToast, toast }\nexport type { ToasterToast }\n","/**\n * @file Performance Utilities for DataTable\n * @package @jmruthers/pace-core\n * @module Components/DataTable/Utils/Performance\n * @since 0.3.0\n */\n\nimport type { \n DataRecord, \n PaginationMode, \n ChunkingConfig, \n SearchIndexConfig\n} from '../types';\n\n// ============================================================================\n// PAGINATION MODE DETECTION\n// ============================================================================\n\n/**\n * Determines the optimal pagination mode based on dataset size\n * \n * IMPORTANT: This function NEVER returns 'server' mode - it only returns 'client' or 'hybrid'.\n * Server mode should ONLY be used when serverSide config is explicitly provided.\n * Returning 'server' without serverSide config breaks pagination because TanStack Table\n * expects pre-paginated data but receives all client-side data.\n * \n * For large datasets (>10k rows), returns 'hybrid' which still uses client-side pagination\n * but with optimizations. If true server-side pagination is needed, serverSide config must be provided.\n */\nexport function determinePaginationMode(\n dataLength: number,\n serverSideThreshold: number = 10000\n): 'client' | 'hybrid' {\n if (dataLength <= 1000) return 'client';\n // Even for very large datasets, use 'hybrid' mode (client-side pagination with optimizations)\n // unless serverSide config is explicitly provided (handled in useDataTablePerformance)\n return 'hybrid';\n}\n\n/**\n * Gets optimal page size options based on pagination mode and dataset size\n */\nexport function getOptimalPageSizeOptions(\n mode: PaginationMode,\n dataLength: number\n): number[] {\n switch (mode) {\n case 'client':\n return dataLength <= 100 ? [10, 25, 50] : [10, 25, 50, 100];\n case 'hybrid':\n return [50, 100, 250, 500];\n case 'server':\n return [25, 50, 100, 250];\n default:\n return [10, 25, 50, 100];\n }\n}\n\n// ============================================================================\n// DATA CHUNKING\n// ============================================================================\n\n/**\n * Splits data into chunks for memory management\n */\nexport function chunkData<TData extends DataRecord>(\n data: TData[],\n chunkSize: number\n): TData[][] {\n const chunks: TData[][] = [];\n for (let i = 0; i < data.length; i += chunkSize) {\n chunks.push(data.slice(i, i + chunkSize));\n }\n return chunks;\n}\n\n/**\n * Manages data chunks with LRU cache\n */\nexport class DataChunkManager<TData extends DataRecord> {\n private chunks: Map<number, TData[]> = new Map();\n private accessOrder: number[] = [];\n private maxChunks: number;\n private chunkSize: number;\n\n constructor(config: ChunkingConfig) {\n this.maxChunks = config.maxChunksInMemory;\n this.chunkSize = config.chunkSize;\n }\n\n getChunk(chunkIndex: number, allData: TData[]): TData[] {\n // Check if chunk is already in memory\n if (this.chunks.has(chunkIndex)) {\n this.updateAccessOrder(chunkIndex);\n return this.chunks.get(chunkIndex)!;\n }\n\n // Calculate chunk bounds\n const startIndex = chunkIndex * this.chunkSize;\n const endIndex = Math.min(startIndex + this.chunkSize, allData.length);\n const chunk = allData.slice(startIndex, endIndex);\n\n // Add chunk to memory\n this.addChunk(chunkIndex, chunk);\n return chunk;\n }\n\n private addChunk(chunkIndex: number, chunk: TData[]): void {\n // Remove oldest chunk if at capacity\n if (this.chunks.size >= this.maxChunks && !this.chunks.has(chunkIndex)) {\n const oldestChunk = this.accessOrder.shift();\n if (oldestChunk !== undefined) {\n this.chunks.delete(oldestChunk);\n }\n }\n\n this.chunks.set(chunkIndex, chunk);\n this.updateAccessOrder(chunkIndex);\n }\n\n private updateAccessOrder(chunkIndex: number): void {\n const existingIndex = this.accessOrder.indexOf(chunkIndex);\n if (existingIndex > -1) {\n this.accessOrder.splice(existingIndex, 1);\n }\n this.accessOrder.push(chunkIndex);\n }\n\n clear(): void {\n this.chunks.clear();\n this.accessOrder = [];\n }\n\n getMemoryUsage(): number {\n let totalSize = 0;\n for (const chunk of this.chunks.values()) {\n totalSize += JSON.stringify(chunk).length;\n }\n return totalSize / (1024 * 1024); // Convert to MB\n }\n}\n\n// ============================================================================\n// SEARCH INDEXING\n// ============================================================================\n\n/**\n * Creates a search index for fast text searching\n */\nexport class SearchIndex<TData extends DataRecord> {\n private index: Map<string, Set<number>> = new Map();\n private data: TData[] = [];\n private indexedFields: string[];\n private fuzzySearch: boolean;\n private fuzzyThreshold: number;\n\n constructor(config: SearchIndexConfig) {\n this.indexedFields = config.indexedFields;\n this.fuzzySearch = config.fuzzySearch ?? false;\n this.fuzzyThreshold = config.fuzzyThreshold ?? 0.6;\n }\n\n buildIndex(data: TData[]): void {\n this.data = data;\n this.index.clear();\n\n data.forEach((row, rowIndex) => {\n this.indexedFields.forEach(field => {\n const value = this.getNestedValue(row, field);\n if (value != null) {\n const searchableText = String(value).toLowerCase();\n const words = this.tokenize(searchableText);\n \n words.forEach(word => {\n if (!this.index.has(word)) {\n this.index.set(word, new Set());\n }\n this.index.get(word)!.add(rowIndex);\n });\n }\n });\n });\n }\n\n search(query: string): number[] {\n if (!query.trim()) return [];\n\n const searchTerms = this.tokenize(query.toLowerCase());\n const matchingSets: Set<number>[] = [];\n\n searchTerms.forEach(term => {\n const matches = new Set<number>();\n \n // Exact matches\n if (this.index.has(term)) {\n this.index.get(term)!.forEach(index => matches.add(index));\n }\n\n // Fuzzy matches\n if (this.fuzzySearch) {\n for (const [indexedTerm, indices] of this.index.entries()) {\n if (this.calculateSimilarity(term, indexedTerm) >= this.fuzzyThreshold) {\n indices.forEach(index => matches.add(index));\n }\n }\n }\n\n matchingSets.push(matches);\n });\n\n // Find intersection of all matching sets\n if (matchingSets.length === 0) return [];\n \n let result = matchingSets[0];\n for (let i = 1; i < matchingSets.length; i++) {\n result = new Set([...result].filter(x => matchingSets[i].has(x)));\n }\n\n return Array.from(result);\n }\n\n private getNestedValue(obj: any, path: string): any {\n return path.split('.').reduce((current, key) => current?.[key], obj);\n }\n\n private tokenize(text: string): string[] {\n return text\n .replace(/[^\\w\\s]/g, ' ')\n .split(/\\s+/)\n .filter(word => word.length > 0);\n }\n\n private calculateSimilarity(str1: string, str2: string): number {\n const longer = str1.length > str2.length ? str1 : str2;\n const shorter = str1.length > str2.length ? str2 : str1;\n \n if (longer.length === 0) return 1.0;\n \n const editDistance = this.levenshteinDistance(longer, shorter);\n return (longer.length - editDistance) / longer.length;\n }\n\n private levenshteinDistance(str1: string, str2: string): number {\n const matrix = Array(str2.length + 1).fill(null).map(() => \n Array(str1.length + 1).fill(null)\n );\n\n for (let i = 0; i <= str1.length; i++) matrix[0][i] = i;\n for (let j = 0; j <= str2.length; j++) matrix[j][0] = j;\n\n for (let j = 1; j <= str2.length; j++) {\n for (let i = 1; i <= str1.length; i++) {\n const substitutionCost = str1[i - 1] === str2[j - 1] ? 0 : 1;\n matrix[j][i] = Math.min(\n matrix[j][i - 1] + 1, // insertion\n matrix[j - 1][i] + 1, // deletion\n matrix[j - 1][i - 1] + substitutionCost // substitution\n );\n }\n }\n\n return matrix[str2.length][str1.length];\n }\n}\n\n\n// ============================================================================\n// DEBOUNCE UTILITIES\n// ============================================================================\n\n/**\n * Creates a debounced function\n */\nexport function debounce<T extends (...args: any[]) => any>(\n func: T,\n delay: number\n): (...args: Parameters<T>) => void {\n let timeoutId: NodeJS.Timeout;\n \n return (...args: Parameters<T>) => {\n clearTimeout(timeoutId);\n timeoutId = setTimeout(() => func(...args), delay);\n };\n}\n\n/**\n * Creates a throttled function\n */\nexport function throttle<T extends (...args: any[]) => any>(\n func: T,\n delay: number\n): (...args: Parameters<T>) => void {\n let lastCall = 0;\n \n return (...args: Parameters<T>) => {\n const now = Date.now();\n if (now - lastCall >= delay) {\n lastCall = now;\n func(...args);\n }\n };\n}\n\n// ============================================================================\n// MEMORY MANAGEMENT\n// ============================================================================\n\n/**\n * Intersection Observer for tracking visible rows\n */\nexport class VisibilityTracker {\n private observer: IntersectionObserver | null = null;\n private visibleElements = new Set<Element>();\n private callbacks = new Set<(visibleCount: number) => void>();\n\n constructor() {\n if (typeof IntersectionObserver !== 'undefined') {\n this.observer = new IntersectionObserver(\n (entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n this.visibleElements.add(entry.target);\n } else {\n this.visibleElements.delete(entry.target);\n }\n });\n \n this.callbacks.forEach(callback => {\n callback(this.visibleElements.size);\n });\n },\n { threshold: 0.1 }\n );\n }\n }\n\n observe(element: Element): void {\n this.observer?.observe(element);\n }\n\n unobserve(element: Element): void {\n this.observer?.unobserve(element);\n this.visibleElements.delete(element);\n }\n\n onVisibilityChange(callback: (visibleCount: number) => void): () => void {\n this.callbacks.add(callback);\n return () => this.callbacks.delete(callback);\n }\n\n getVisibleCount(): number {\n return this.visibleElements.size;\n }\n\n destroy(): void {\n this.observer?.disconnect();\n this.visibleElements.clear();\n this.callbacks.clear();\n }\n} ","/**\n * @file Error Handling Stubs\n * @package @jmruthers/pace-core\n * @module Components/DataTable/Utils/Stubs\n * \n * Minimal stubs for removed error handling utilities.\n * This file exists only to prevent import errors in useDataTablePerformance.\n */\n\nexport interface FallbackConfig {\n enabled: boolean;\n}\n\nexport const DEFAULT_FALLBACK_CONFIG: FallbackConfig = {\n enabled: false\n};\n\nexport enum DataTableErrorType {\n VIRTUALIZATION = 'virtualization',\n SEARCH_INDEX = 'search_index',\n DATA_CHUNK = 'data_chunk',\n SERVER_FETCH = 'server_fetch',\n MEMORY = 'memory'\n}\n\nexport class DataTableError extends Error {\n constructor(\n message: string,\n public type: DataTableErrorType,\n public recoverable: boolean = true\n ) {\n super(message);\n this.name = 'DataTableError';\n }\n}\n\nexport class ErrorRecoveryManager {\n constructor(private config: FallbackConfig) {}\n \n async handleError(error: DataTableError) {\n return { recovered: false, strategy: null };\n }\n \n clearErrorLog(): void {\n // Stub method\n }\n}\n\nexport class MemoryMonitor {\n constructor(private threshold: number = 100) {}\n \n getCurrentUsage(): number {\n return 0;\n }\n \n checkThreshold(): boolean {\n return true;\n }\n \n stopMonitoring(): void {\n // Stub method\n }\n}\n\nexport class CircuitBreaker {\n constructor() {}\n \n isOpen(): boolean {\n return false;\n }\n \n recordSuccess(): void {}\n \n recordFailure(): void {}\n \n reset(): void {}\n}\n\nexport function safeExecute<T>(fn: () => T, fallback: T): T {\n try {\n return fn();\n } catch {\n return fallback;\n }\n}\n\n","/**\n * @file DataTable Performance Hook\n * @package @jmruthers/pace-core\n * @module Hooks/DataTablePerformance\n * @since 0.3.0\n */\n\nimport { useState, useEffect, useCallback, useMemo, useRef } from 'react';\nimport type { \n DataRecord,\n PaginationMode,\n PerformanceConfig,\n ServerSideConfig,\n ServerSideParams,\n ServerSideResponse,\n ChunkingConfig,\n SearchIndexConfig,\n} from '../components/DataTable/types';\nimport {\n determinePaginationMode,\n getOptimalPageSizeOptions,\n DataChunkManager,\n SearchIndex,\n debounce,\n VisibilityTracker\n} from '../components/DataTable/utils/performanceUtils';\nimport {\n ErrorRecoveryManager,\n DataTableError,\n DataTableErrorType,\n safeExecute,\n MemoryMonitor,\n CircuitBreaker,\n DEFAULT_FALLBACK_CONFIG,\n type FallbackConfig\n} from '../components/DataTable/utils/errorHandling';\n\nexport interface UseDataTablePerformanceOptions<TData extends DataRecord> {\n data: TData[];\n performance?: PerformanceConfig;\n serverSide?: ServerSideConfig<TData>;\n chunking?: ChunkingConfig;\n searchIndex?: SearchIndexConfig;\n // Enhanced error handling options\n fallbackConfig?: FallbackConfig;\n onError?: (error: DataTableError) => void;\n enableErrorRecovery?: boolean;\n}\n\nexport interface UseDataTablePerformanceReturn<TData extends DataRecord> {\n // Performance state\n paginationMode: PaginationMode;\n isVirtualized: boolean;\n pageSizeOptions: number[];\n \n // Data management\n processedData: TData[];\n totalCount: number;\n isLoading: boolean;\n \n // Search functionality\n searchQuery: string;\n setSearchQuery: (query: string) => void;\n searchResults: number[];\n \n // Server-side functionality\n fetchServerData: (params: ServerSideParams) => Promise<void>;\n serverData: ServerSideResponse<TData> | null;\n \n // Performance monitoring\n memoryUsage: number;\n \n // Error handling and recovery\n errorState: {\n hasErrors: boolean;\n errorCount: number;\n lastError: DataTableError | null;\n fallbacksActive: string[];\n };\n retryLastOperation: () => Promise<void>;\n clearErrors: () => void;\n \n // Cleanup\n cleanup: () => void;\n}\n\n/**\n * Hook for managing DataTable performance optimizations\n */\nexport function useDataTablePerformance<TData extends DataRecord>({\n data,\n performance = {},\n serverSide,\n chunking,\n searchIndex,\n fallbackConfig = DEFAULT_FALLBACK_CONFIG,\n onError,\n enableErrorRecovery = true\n}: UseDataTablePerformanceOptions<TData>): UseDataTablePerformanceReturn<TData> {\n // ============================================================================\n // STATE MANAGEMENT\n // ============================================================================\n \n const [isLoading, setIsLoading] = useState(false);\n const [searchQuery, setSearchQuery] = useState('');\n const [searchResults, setSearchResults] = useState<number[]>([]);\n const [serverData, setServerData] = useState<ServerSideResponse<TData> | null>(null);\n const [memoryUsage, setMemoryUsage] = useState(0);\n \n // Error handling state\n const [errorState, setErrorState] = useState({\n hasErrors: false,\n errorCount: 0,\n lastError: null as DataTableError | null,\n fallbacksActive: [] as string[],\n });\n const [lastFailedOperation, setLastFailedOperation] = useState<(() => Promise<any>) | null>(null);\n\n // ============================================================================\n // REFS AND MANAGERS\n // ============================================================================\n \n const chunkManagerRef = useRef<DataChunkManager<TData> | null>(null);\n const searchIndexRef = useRef<SearchIndex<TData> | null>(null);\n const visibilityTrackerRef = useRef<VisibilityTracker | null>(null);\n \n // Error handling managers\n const errorRecoveryManagerRef = useRef<ErrorRecoveryManager>(new ErrorRecoveryManager(fallbackConfig));\n const memoryMonitorRef = useRef<MemoryMonitor | null>(null);\n const circuitBreakerRef = useRef<CircuitBreaker>(new CircuitBreaker());\n\n // ============================================================================\n // COMPUTED VALUES\n // ============================================================================\n \n const paginationMode = useMemo(() => {\n // CRITICAL FIX: Only use 'server' mode if serverSide config is explicitly provided.\n // determinePaginationMode now never returns 'server' - it only returns 'client' or 'hybrid'.\n // This fixes pagination issues where large datasets would auto-detect 'server' mode\n // but have no serverSide config, causing pagination controls to break.\n if (serverSide) return 'server';\n return determinePaginationMode(data?.length || 0, performance.serverSideThreshold);\n }, [data?.length, performance.serverSideThreshold, serverSide]);\n\n // Virtualization is now handled internally by UnifiedTableBody\n const isVirtualized = false;\n\n const pageSizeOptions = useMemo(() => {\n return getOptimalPageSizeOptions(paginationMode, data?.length || 0);\n }, [paginationMode, data?.length]);\n\n // ============================================================================\n // DATA PROCESSING\n // ============================================================================\n \n const processedData = useMemo(() => {\n if (serverSide && serverData) {\n return serverData.data;\n }\n\n let filteredData = data;\n \n // Apply search filtering - ensure we don't exclude zero values\n if (searchQuery && searchResults.length > 0) {\n filteredData = searchResults.map(index => data[index]);\n }\n\n // Important: Ensure we don't accidentally filter out rows with zero values\n // This was causing \"no data\" issues when rows contained zero values in numeric columns\n // The filtering should be explicit, not implicit based on falsy values\n\n return filteredData;\n }, [data, serverData, searchQuery, searchResults, serverSide]);\n\n const totalCount = useMemo(() => {\n if (serverSide && serverData) {\n return serverData.totalCount;\n }\n return processedData?.length || 0;\n }, [serverData, processedData?.length, serverSide]);\n\n // ============================================================================\n // CHUNK MANAGEMENT\n // ============================================================================\n \n useEffect(() => {\n if (chunking && !chunkManagerRef.current) {\n chunkManagerRef.current = new DataChunkManager<TData>(chunking);\n }\n }, [chunking]);\n\n // ============================================================================\n // SEARCH INDEX MANAGEMENT\n // ============================================================================\n \n useEffect(() => {\n if (searchIndex && !searchIndexRef.current) {\n searchIndexRef.current = new SearchIndex<TData>(searchIndex);\n }\n\n if (searchIndexRef.current && data.length > 0) {\n searchIndexRef.current.buildIndex(data);\n }\n }, [searchIndex, data]);\n\n // Debounced search function\n const debouncedSearch = useCallback(\n debounce((query: string) => {\n if (!searchIndexRef.current) return;\n \n if (!query.trim()) {\n setSearchResults([]);\n return;\n }\n\n const results = searchIndexRef.current.search(query);\n setSearchResults(results);\n }, performance.debounceSearch ?? 300),\n [performance.debounceSearch]\n );\n\n // Handle search query changes\n useEffect(() => {\n debouncedSearch(searchQuery);\n }, [searchQuery, debouncedSearch]);\n\n // ============================================================================\n // SERVER-SIDE DATA FETCHING\n // ============================================================================\n \n const fetchServerData = useCallback(async (params: ServerSideParams) => {\n if (!serverSide) return;\n\n setIsLoading(true);\n try {\n const response = await serverSide.fetchData(params);\n setServerData(response);\n } catch (error) {\n console.error('Failed to fetch server data:', error);\n } finally {\n setIsLoading(false);\n }\n }, [serverSide]);\n\n // ============================================================================\n // PERFORMANCE MONITORING\n // ============================================================================\n \n useEffect(() => {\n if (!visibilityTrackerRef.current) {\n visibilityTrackerRef.current = new VisibilityTracker();\n }\n\n const tracker = visibilityTrackerRef.current;\n const unsubscribe = tracker.onVisibilityChange((visibleCount) => {\n // Performance monitoring removed\n });\n\n return unsubscribe;\n }, [totalCount, isVirtualized, paginationMode]);\n\n // Update memory usage\n useEffect(() => {\n const updateMemoryUsage = () => {\n let usage = 0;\n \n if (chunkManagerRef.current) {\n usage += chunkManagerRef.current.getMemoryUsage();\n }\n \n // Add general memory estimation\n usage += (JSON.stringify(processedData || []).length) / (1024 * 1024);\n \n setMemoryUsage(usage);\n };\n\n updateMemoryUsage();\n \n // Only set up interval in non-test environments to prevent memory leaks during testing\n const interval = import.meta.env.MODE !== 'test' \n ? setInterval(updateMemoryUsage, 5000) \n : null;\n \n return () => {\n if (interval) {\n clearInterval(interval);\n }\n };\n }, [processedData]);\n\n // ============================================================================\n // ERROR HANDLING FUNCTIONS\n // ============================================================================\n \n const handleError = useCallback(async (error: DataTableError, operation?: () => Promise<any>) => {\n if (enableErrorRecovery) {\n try {\n const recovery = await errorRecoveryManagerRef.current.handleError(error);\n setErrorState(prev => ({\n hasErrors: true,\n errorCount: prev.errorCount + 1,\n lastError: error,\n fallbacksActive: [...prev.fallbacksActive, error.type],\n }));\n \n if (operation) {\n setLastFailedOperation(() => operation);\n }\n \n onError?.(error);\n return recovery;\n } catch (recoveryError) {\n console.error('Error recovery failed:', recoveryError);\n }\n }\n throw error;\n }, [enableErrorRecovery, onError]);\n\n const retryLastOperation = useCallback(async () => {\n if (lastFailedOperation) {\n try {\n await lastFailedOperation();\n setLastFailedOperation(null);\n setErrorState(prev => ({ ...prev, hasErrors: false }));\n } catch (error) {\n console.error('Retry failed:', error);\n }\n }\n }, [lastFailedOperation]);\n\n const clearErrors = useCallback(() => {\n setErrorState({\n hasErrors: false,\n errorCount: 0,\n lastError: null,\n fallbacksActive: [],\n });\n setLastFailedOperation(null);\n errorRecoveryManagerRef.current.clearErrorLog();\n }, []);\n\n // ============================================================================\n // CLEANUP\n // ============================================================================\n \n const cleanup = useCallback(() => {\n chunkManagerRef.current?.clear();\n visibilityTrackerRef.current?.destroy();\n memoryMonitorRef.current?.stopMonitoring();\n }, []);\n\n useEffect(() => {\n return cleanup;\n }, [cleanup]);\n\n // ============================================================================\n // RETURN VALUES\n // ============================================================================\n \n return {\n // Performance state\n paginationMode,\n isVirtualized,\n pageSizeOptions,\n \n // Data management\n processedData,\n totalCount,\n isLoading,\n \n // Search functionality\n searchQuery,\n setSearchQuery,\n searchResults,\n \n // Server-side functionality\n fetchServerData,\n serverData,\n \n // Performance monitoring\n memoryUsage,\n \n // Error handling and recovery\n errorState,\n retryLastOperation,\n clearErrors,\n \n // Cleanup\n cleanup\n };\n} "],"mappings":"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","names":["props","DataTableErrorType","useState","useEffect","useState","useEffect"]}