Spaces:
Running
Running
Rename client/src/components/examples/CodePanel.tsx to client/src/components/CodePanel.tsx
88d2e45 verified | import { useState } from "react"; | |
| import { Button } from "@/components/ui/button"; | |
| import { Badge } from "@/components/ui/badge"; | |
| import { Download, Copy, Play, X } from "lucide-react"; | |
| import { useToast } from "@/hooks/use-toast"; | |
| type CodePanelProps = { | |
| fileName: string; | |
| language: string; | |
| code: string; | |
| onClose?: () => void; | |
| onRun?: () => void; | |
| }; | |
| export function CodePanel({ fileName, language, code, onClose, onRun }: CodePanelProps) { | |
| const { toast } = useToast(); | |
| const [copied, setCopied] = useState(false); | |
| const handleCopy = async () => { | |
| await navigator.clipboard.writeText(code); | |
| setCopied(true); | |
| toast({ | |
| title: "Copied!", | |
| description: "Code copied to clipboard", | |
| }); | |
| setTimeout(() => setCopied(false), 2000); | |
| }; | |
| const handleDownload = () => { | |
| const blob = new Blob([code], { type: "text/plain" }); | |
| const url = URL.createObjectURL(blob); | |
| const a = document.createElement("a"); | |
| a.href = url; | |
| a.download = fileName; | |
| a.click(); | |
| URL.revokeObjectURL(url); | |
| toast({ | |
| title: "Downloaded!", | |
| description: `${fileName} has been downloaded`, | |
| }); | |
| }; | |
| return ( | |
| <div className="flex flex-col h-full border-l border-border bg-card"> | |
| <div className="flex items-center justify-between p-4 border-b border-card-border"> | |
| <div className="flex items-center gap-3"> | |
| <h3 className="font-semibold text-sm" data-testid="text-filename">{fileName}</h3> | |
| <Badge variant="secondary" className="text-xs">{language}</Badge> | |
| </div> | |
| <div className="flex items-center gap-2"> | |
| {onRun && ( | |
| <Button variant="outline" size="sm" onClick={onRun} data-testid="button-run-code"> | |
| <Play className="h-4 w-4 mr-2" /> | |
| Run | |
| </Button> | |
| )} | |
| <Button variant="outline" size="sm" onClick={handleCopy} data-testid="button-copy-code"> | |
| <Copy className="h-4 w-4 mr-2" /> | |
| {copied ? "Copied!" : "Copy"} | |
| </Button> | |
| <Button variant="outline" size="sm" onClick={handleDownload} data-testid="button-download-code"> | |
| <Download className="h-4 w-4 mr-2" /> | |
| Download | |
| </Button> | |
| {onClose && ( | |
| <Button variant="ghost" size="icon" onClick={onClose} data-testid="button-close-panel"> | |
| <X className="h-5 w-5" /> | |
| </Button> | |
| )} | |
| </div> | |
| </div> | |
| <div className="flex-1 overflow-auto p-4 bg-muted/30"> | |
| <pre className="font-mono text-sm"> | |
| <code>{code}</code> | |
| </pre> | |
| </div> | |
| </div> | |
| ); | |
| } | |