{"version":3,"file":"ReactEnvironmentProvider.mjs","sources":["../../../../src/lib/core/react-env/ReactEnvironmentProvider.tsx"],"sourcesContent":["/**\n * @fileoverview React Environment Provider Component\n *\n * A provider component that validates the React environment and provides\n * context about environment health to child components. This helps prevent\n * blank pages caused by React version conflicts or multiple React instances.\n *\n * @module core/react-env/ReactEnvironmentProvider\n * @version 1.0.0\n */\n\nimport React, {\n  createContext,\n  useContext,\n  useEffect,\n  useState,\n  useMemo,\n  type ReactNode,\n} from 'react';\nimport {\n  checkReactEnvironment,\n  type ReactEnvironmentStatus,\n  type ReactEnvironmentConfig,\n} from './index';\n\n// ============================================================================\n// Context\n// ============================================================================\n\n/**\n * Context value for React environment status.\n */\nexport interface ReactEnvironmentContextValue {\n  /** Current environment status */\n  status: ReactEnvironmentStatus | null;\n  /** Whether the environment is healthy */\n  isHealthy: boolean;\n  /** Whether the check is still pending */\n  isPending: boolean;\n  /** Force a re-check of the environment */\n  recheck: () => void;\n}\n\nconst defaultContextValue: ReactEnvironmentContextValue = {\n  status: null,\n  isHealthy: true,\n  isPending: true,\n  recheck: () => {},\n};\n\nconst ReactEnvironmentContext = createContext<ReactEnvironmentContextValue>(defaultContextValue);\n\n// ============================================================================\n// Hook\n// ============================================================================\n\n/**\n * Hook to access React environment status.\n *\n * @returns React environment context value\n *\n * @example\n * ```tsx\n * function MyComponent() {\n *   const { isHealthy, status } = useReactEnvironment();\n *\n *   if (!isHealthy) {\n *     return <div>React environment issues detected</div>;\n *   }\n *\n *   return <div>App is running</div>;\n * }\n * ```\n */\nexport function useReactEnvironment(): ReactEnvironmentContextValue {\n  return useContext(ReactEnvironmentContext);\n}\n\n// ============================================================================\n// Provider Props\n// ============================================================================\n\n/**\n * Props for ReactEnvironmentProvider.\n */\nexport interface ReactEnvironmentProviderProps {\n  /** Child components */\n  children: ReactNode;\n  /**\n   * Configuration for environment checks.\n   */\n  config?: ReactEnvironmentConfig;\n  /**\n   * Content to render when environment is unhealthy.\n   * If not provided, children will still render with a console warning.\n   */\n  fallback?: ReactNode;\n  /**\n   * Whether to block rendering of children when environment is unhealthy.\n   * @default false\n   */\n  blockOnUnhealthy?: boolean;\n  /**\n   * Callback when environment issues are detected.\n   */\n  onEnvironmentError?: (status: ReactEnvironmentStatus) => void;\n}\n\n// ============================================================================\n// Provider Component\n// ============================================================================\n\n/**\n * Provider component that validates the React environment.\n *\n * Wraps your application to detect React version conflicts and provide\n * environment health information to child components.\n *\n * @example\n * ```tsx\n * // Basic usage\n * <ReactEnvironmentProvider>\n *   <App />\n * </ReactEnvironmentProvider>\n *\n * // With fallback and blocking\n * <ReactEnvironmentProvider\n *   blockOnUnhealthy\n *   fallback={<ErrorPage message=\"React configuration error\" />}\n *   onEnvironmentError={(status) => console.error('React issues:', status)}\n * >\n *   <App />\n * </ReactEnvironmentProvider>\n * ```\n */\nexport function ReactEnvironmentProvider({\n  children,\n  config,\n  fallback,\n  blockOnUnhealthy = false,\n  onEnvironmentError,\n}: ReactEnvironmentProviderProps): React.JSX.Element {\n  const [status, setStatus] = useState<ReactEnvironmentStatus | null>(null);\n  const [isPending, setIsPending] = useState(true);\n\n  const checkEnvironment = React.useCallback(() => {\n    try {\n      const envStatus = checkReactEnvironment({\n        ...config,\n        logWarnings: config?.logWarnings ?? true,\n      });\n      setStatus(envStatus);\n\n      // Call error callback if there are issues\n      if (envStatus.issues.length > 0 && onEnvironmentError) {\n        onEnvironmentError(envStatus);\n      }\n    } catch (err) {\n      // Create an error status if the check itself fails\n      const errorStatus: ReactEnvironmentStatus = {\n        isReactAvailable: false,\n        isReactDOMAvailable: false,\n        reactVersion: null,\n        hasMultipleInstances: false,\n        isVersionCompatible: false,\n        issues: [\n          {\n            type: 'hooks_error',\n            severity: 'error',\n            message: `Environment check failed: ${err instanceof Error ? err.message : 'Unknown error'}`,\n            resolution: 'Check that React is properly installed and configured.',\n          },\n        ],\n        checkedAt: Date.now(),\n      };\n      setStatus(errorStatus);\n      onEnvironmentError?.(errorStatus);\n    } finally {\n      setIsPending(false);\n    }\n  }, [config, onEnvironmentError]);\n\n  useEffect(() => {\n    // Run check on mount (client-side only)\n    if (typeof window !== 'undefined') {\n      // Small delay to ensure React is fully loaded\n      const timeoutId = setTimeout(() => {\n        checkEnvironment();\n      }, 0);\n\n      return () => clearTimeout(timeoutId);\n    }\n\n    // SSR - assume healthy\n    setStatus({\n      isReactAvailable: true,\n      isReactDOMAvailable: true,\n      reactVersion: null,\n      hasMultipleInstances: false,\n      isVersionCompatible: true,\n      issues: [],\n      checkedAt: Date.now(),\n    });\n    setIsPending(false);\n    return undefined;\n  }, [checkEnvironment]);\n\n  const isHealthy = useMemo(() => {\n    if (status === null) return true; // Assume healthy while pending\n    return status.issues.filter((i) => i.severity === 'error').length === 0;\n  }, [status]);\n\n  const contextValue = useMemo<ReactEnvironmentContextValue>(\n    () => ({\n      status,\n      isHealthy,\n      isPending,\n      recheck: checkEnvironment,\n    }),\n    [status, isHealthy, isPending, checkEnvironment]\n  );\n\n  // Render fallback if unhealthy and blocking is enabled\n  if (!isHealthy && blockOnUnhealthy) {\n    if (fallback !== undefined) {\n      return (\n        <ReactEnvironmentContext.Provider value={contextValue}>\n          {fallback}\n        </ReactEnvironmentContext.Provider>\n      );\n    }\n\n    // Default error display\n    return (\n      <ReactEnvironmentContext.Provider value={contextValue}>\n        <div\n          style={{\n            padding: '20px',\n            margin: '20px',\n            backgroundColor: '#fff3cd',\n            border: '1px solid #ffc107',\n            borderRadius: '8px',\n            color: '#856404',\n            fontFamily: 'system-ui, -apple-system, sans-serif',\n          }}\n        >\n          <h2 style={{ margin: '0 0 10px 0', fontSize: '18px' }}>React Environment Error</h2>\n          <p style={{ margin: '0 0 10px 0' }}>\n            Issues were detected with your React configuration that may cause blank pages or\n            unexpected behavior.\n          </p>\n          {status?.issues.map((issue, index) => (\n            <div\n              key={index}\n              style={{\n                padding: '10px',\n                marginBottom: '10px',\n                backgroundColor: issue.severity === 'error' ? '#f8d7da' : '#fff3cd',\n                borderRadius: '4px',\n              }}\n            >\n              <strong>{issue.type}:</strong> {issue.message}\n              {issue.resolution !== undefined && issue.resolution !== '' && (\n                <div style={{ marginTop: '5px', fontSize: '14px' }}>\n                  <em>Resolution: {issue.resolution}</em>\n                </div>\n              )}\n            </div>\n          ))}\n          <p style={{ margin: '10px 0 0 0', fontSize: '14px' }}>\n            <strong>Common fix:</strong> Run{' '}\n            <code style={{ backgroundColor: '#f4f4f4', padding: '2px 4px' }}>npm ls react</code> to\n            check for duplicate React installations.\n          </p>\n        </div>\n      </ReactEnvironmentContext.Provider>\n    );\n  }\n\n  return (\n    <ReactEnvironmentContext.Provider value={contextValue}>\n      {children}\n    </ReactEnvironmentContext.Provider>\n  );\n}\n\nReactEnvironmentProvider.displayName = 'ReactEnvironmentProvider';\n\n// ============================================================================\n// HOC for environment checking\n// ============================================================================\n\n/**\n * Higher-order component that checks React environment before rendering.\n *\n * @param Component - Component to wrap\n * @param fallback - Optional fallback to render on environment error\n * @returns Wrapped component\n *\n * @example\n * ```tsx\n * const SafeApp = withReactEnvironmentCheck(App);\n * // or\n * const SafeApp = withReactEnvironmentCheck(App, <LoadingSpinner />);\n * ```\n */\nexport function withReactEnvironmentCheck<P extends object>(\n  Component: React.ComponentType<P>,\n  fallback?: ReactNode\n): React.FC<P> {\n  const WrappedComponent: React.FC<P> = (props) => {\n    const { isHealthy, isPending } = useReactEnvironment();\n\n    if (isPending) {\n      return fallback !== undefined ? <>{fallback}</> : null;\n    }\n\n    if (!isHealthy && fallback !== undefined) {\n      return <>{fallback}</>;\n    }\n\n    return <Component {...props} />;\n  };\n\n  WrappedComponent.displayName = `withReactEnvironmentCheck(${Component.displayName ?? Component.name ?? 'Component'})`;\n\n  return WrappedComponent;\n}\n"],"names":["defaultContextValue","ReactEnvironmentContext","createContext","useReactEnvironment","useContext","ReactEnvironmentProvider","children","config","fallback","blockOnUnhealthy","onEnvironmentError","status","setStatus","useState","isPending","setIsPending","checkEnvironment","React","envStatus","checkReactEnvironment","err","errorStatus","useEffect","timeoutId","isHealthy","useMemo","i","contextValue","jsx","jsxs","issue","index","withReactEnvironmentCheck","Component","WrappedComponent","props","Fragment"],"mappings":"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"}