import { Check, ChevronDown, Copy } from "lucide-react"; import * as React from "react"; import { Button } from "@/components/ui/button"; import { cn } from "@/lib/utils"; interface StackTraceProps { error?: string; stacktrace?: string[]; className?: string; } export function StackTrace({ error, stacktrace, className }: StackTraceProps) { const [expanded, setExpanded] = React.useState(false); const [copied, setCopied] = React.useState(false); if (!error && (!stacktrace || stacktrace.length === 0)) { return null; } const fullText = [error, ...(stacktrace || [])].filter(Boolean).join("\n"); const handleCopy = () => { navigator.clipboard.writeText(fullText); setCopied(true); setTimeout(() => setCopied(false), 2000); }; return (
{/* Error message header */}

{error || "Unknown error"}

{stacktrace && stacktrace.length > 0 && ( )}
{/* Stack trace */} {expanded && stacktrace && stacktrace.length > 0 && (
            {stacktrace.map((line, i) => (
              
{formatStackLine(line)}
))}
)}
); } function formatStackLine(line: string): React.ReactNode { // Highlight file paths and line numbers const fileMatch = line.match(/at (.+?) \((.+?):(\d+):(\d+)\)/); if (fileMatch) { const [, fnName, filePath, lineNum, colNum] = fileMatch; return ( <> at {fnName} ( {filePath} : {lineNum} : {colNum} ) ); } // Simple file path format const simpleMatch = line.match(/at (.+?):(\d+):(\d+)/); if (simpleMatch) { const [, filePath, lineNum, colNum] = simpleMatch; return ( <> at {filePath} : {lineNum} : {colNum} ); } return line; }