'use client'; import React, { useState, useCallback, useMemo } from 'react'; import { motion, AnimatePresence } from 'framer-motion'; import { cn } from '../utils/cn'; export interface CodeBlockProps { children: React.ReactNode; language?: string; showCopy?: boolean; showHeader?: boolean; className?: string; variant?: 'default' | 'glass'; } // Dedent helper - removes common leading indentation function dedentCode(code: string): string { const normalized = code.replace(/\t/g, ' ').replace(/[ \t]+$/gm, ''); const lines = normalized.split('\n'); if (lines.length <= 1) return normalized.trim(); let start = 0; while (start < lines.length && lines[start].trim() === '') start++; let end = lines.length - 1; while (end >= 0 && lines[end].trim() === '') end--; if (start > end) return ''; const relevantLines = lines.slice(start, end + 1); const nonEmpty = relevantLines.filter((l) => l.trim() !== ''); const minIndent = nonEmpty.reduce((min, line) => { const m = line.match(/^\s*/)?.[0].length ?? 0; return Math.min(min, m); }, Infinity); return minIndent === Infinity || minIndent === 0 ? relevantLines.join('\n') : relevantLines .map((l) => l.startsWith(' '.repeat(minIndent)) ? l.slice(minIndent) : l ) .join('\n'); } function CopyButton({ code }: { code: string }) { const [copied, setCopied] = useState(false); const handleCopy = useCallback(async () => { try { await navigator.clipboard.writeText(code); setCopied(true); setTimeout(() => setCopied(false), 2000); } catch { const textarea = document.createElement('textarea'); textarea.value = code; textarea.style.position = 'fixed'; textarea.style.opacity = '0'; document.body.appendChild(textarea); textarea.select(); document.execCommand('copy'); document.body.removeChild(textarea); setCopied(true); setTimeout(() => setCopied(false), 2000); } }, [code]); return ( ); } export function CodeBlock({ children, language = 'typescript', showCopy = true, showHeader = true, className = '', variant = 'glass', }: CodeBlockProps) { const codeString = useMemo(() => { if (typeof children === 'string') return dedentCode(children); try { const raw = React.Children.toArray(children) .map((c) => typeof c === 'string' ? c : typeof c === 'number' ? String(c) : '' ) .join(''); return dedentCode(raw); } catch { return ''; } }, [children]); return (
{showHeader && (
{language}
{showCopy && }
)}
        
          {codeString}
        
      
); } export function InlineCode({ children, className = '', }: { children: React.ReactNode; className?: string; }) { return ( {children} ); }