# All files / src/components/features/snippet-editor ReactPreview.tsx

0% Statements 0/94
0% Branches 0/1
0% Functions 0/1
0% Lines 0/94

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95

     import { useMemo } from 'react'
    import * as React from 'react'
    import { Alert, AlertDescription } from '@/components/ui/alert'
    import { AIErrorHelper } from '@/components/error/AIErrorHelper'
    import { WarningCircle } from '@phosphor-icons/react'
    import { InputParameter } from '@/lib/types'
    import { transformReactCode } from '@/lib/react-transform'
    import { parseInputParameters } from '@/lib/parse-parameters'

    interface ReactPreviewProps {
      code: string
      language: string
      functionName?: string
      inputParameters?: InputParameter[]
    }

    export function ReactPreview({ code, language, functionName, inputParameters }: ReactPreviewProps) {
      const { Component, error } = useMemo(() => {
        const isReactCode = ['JSX', 'TSX', 'JavaScript', 'TypeScript'].includes(language)
        if (!isReactCode) {
          return { Component: null, error: null }
        }

        try {
          const transformedComponent = transformReactCode(code, functionName)
          return { Component: transformedComponent, error: null }
        } catch (err) {
          return { Component: null, error: err instanceof Error ? err.message : 'Failed to render preview' }
        }
      }, [code, language, functionName])

      const props = useMemo(() => parseInputParameters(inputParameters), [inputParameters])

      if (!['JSX', 'TSX', 'JavaScript', 'TypeScript'].includes(language)) {
        return (
          <div
            className="h-full flex items-center justify-center p-6 bg-muted/30"
            data-testid="preview-unsupported"
            role="status"
            aria-label="Preview not available"
          >
            <div className="text-center text-muted-foreground">
              <WarningCircle className="h-12 w-12 mx-auto mb-3 opacity-50" aria-hidden="true" />
              <p className="text-sm">Preview not available for {language}</p>
              <p className="text-xs mt-1">Use JSX, TSX, JavaScript, or TypeScript</p>
            </div>
          </div>
        )
      }

      if (error) {
        return (
          <div
            className="h-full overflow-auto p-6 bg-destructive/5"
            data-testid="preview-error"
            role="alert"
          >
            <Alert variant="destructive" className="mb-4" data-testid="preview-error-alert">
              <WarningCircle className="h-4 w-4" aria-hidden="true" />
              <AlertDescription className="font-mono text-xs whitespace-pre-wrap" data-testid="preview-error-message">
                {error}
              </AlertDescription>
            </Alert>
            <AIErrorHelper
              error={error}
              context={`React component preview rendering (Language: ${language})`}
            />
          </div>
        )
      }

      if (!Component) {
        return (
          <div
            className="h-full flex items-center justify-center p-6 bg-muted/30"
            data-testid="preview-loading"
            role="status"
            aria-label="Loading preview"
          >
            <div className="text-center text-muted-foreground">
              <p className="text-sm">Loading preview...</p>
            </div>
          </div>
        )
      }

      return (
        <div className="h-full overflow-auto bg-background">
          <div className="p-6">
            <Component {...props} />
          </div>
        </div>
      )
    }