Spaces:
Sleeping
Sleeping
File size: 4,216 Bytes
7e92e00 | 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 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | "use client";
import React, { useState } from "react";
import { Check, Copy, Terminal, Play } from "lucide-react";
interface CodeBlockProps {
language: string;
code: string;
}
export const CodeBlock: React.FC<CodeBlockProps> = ({ language, code }) => {
const [copied, setCopied] = useState(false);
const [output, setOutput] = useState<string | null>(null);
const [isRunning, setIsRunning] = useState(false);
const handleCopy = async () => {
try {
await navigator.clipboard.writeText(code);
setCopied(true);
setTimeout(() => setCopied(false), 2000);
} catch {
// ignore
}
};
const handleSimulateRun = () => {
setIsRunning(true);
setOutput(null);
setTimeout(() => {
setIsRunning(false);
if (language === "python" || language === "py") {
setOutput(">>> Process finished with exit code 0\n[Tensor shape: torch.Size([2, 64, 896]) | Latency: 4.2ms | Device: CUDA]");
} else {
setOutput("✓ Compiled successfully in 12ms. Zero runtime warnings.");
}
}, 600);
};
const lines = code.trim().split("\n");
return (
<div className="my-4 rounded-xl border border-white/[0.08] bg-[#070709] overflow-hidden shadow-2xl">
{/* Code Header Bar */}
<div className="flex items-center justify-between px-3.5 py-2 bg-white/[0.03] border-b border-white/[0.06] text-xs font-mono">
<div className="flex items-center gap-2">
<div className="flex gap-1.5">
<div className="w-2.5 h-2.5 rounded-full bg-white/10" />
<div className="w-2.5 h-2.5 rounded-full bg-white/10" />
<div className="w-2.5 h-2.5 rounded-full bg-white/10" />
</div>
<span className="text-zinc-400 uppercase text-[11px] font-semibold tracking-wider ml-1">
{language || "code"}
</span>
</div>
<div className="flex items-center gap-2">
<button
onClick={handleSimulateRun}
disabled={isRunning}
className="flex items-center gap-1.5 px-2.5 py-1 rounded-md bg-white/[0.05] hover:bg-white/[0.1] text-zinc-300 hover:text-white transition-all text-[11px]"
title="Simulate Code Execution"
>
<Play className={`w-3 h-3 text-emerald-400 ${isRunning ? "animate-spin" : ""}`} />
<span>{isRunning ? "Running..." : "Run"}</span>
</button>
<button
onClick={handleCopy}
className="flex items-center gap-1.5 px-2.5 py-1 rounded-md bg-white/[0.05] hover:bg-white/[0.1] text-zinc-300 hover:text-white transition-all text-[11px]"
title="Copy to clipboard"
>
{copied ? (
<>
<Check className="w-3 h-3 text-emerald-400" />
<span className="text-emerald-400 font-medium">Copied</span>
</>
) : (
<>
<Copy className="w-3 h-3 text-zinc-400" />
<span>Copy</span>
</>
)}
</button>
</div>
</div>
{/* Code Content */}
<div className="p-4 overflow-x-auto text-xs font-mono leading-relaxed bg-black/70">
<table className="w-full border-collapse">
<tbody>
{lines.map((line, idx) => (
<tr key={idx} className="hover:bg-white/[0.02]">
<td className="w-8 select-none text-right pr-4 text-zinc-600 font-mono text-[11px]">
{idx + 1}
</td>
<td className="text-zinc-200 whitespace-pre">{line}</td>
</tr>
))}
</tbody>
</table>
</div>
{/* Simulated Execution Output Drawer */}
{output && (
<div className="border-t border-white/[0.08] bg-black/90 p-3 text-xs font-mono">
<div className="flex items-center gap-1.5 text-zinc-500 text-[10px] uppercase tracking-wider mb-1">
<Terminal className="w-3 h-3 text-emerald-400" />
<span>Output Console</span>
</div>
<pre className="text-emerald-400/90 whitespace-pre-wrap leading-tight">{output}</pre>
</div>
)}
</div>
);
};
|