-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathCodeDisplay.tsx
80 lines (70 loc) · 2.35 KB
/
CodeDisplay.tsx
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
import { useState, useEffect } from 'react';
import { Button } from '@/components/ui/button';
import { Clipboard, Check } from 'lucide-react';
import { highlightCode } from '@/utils/highlightUtils';
// We still need the CSS though
import 'highlight.js/styles/github-dark.css';
interface CodeDisplayProps {
code: string;
maxHeight?: string;
showLineNumbers?: boolean;
language?: string;
}
export function CodeDisplay({
code,
maxHeight = '300px',
showLineNumbers = true,
language,
}: CodeDisplayProps) {
const [copied, setCopied] = useState(false);
const [highlightedCode, setHighlightedCode] = useState('');
useEffect(() => {
if (!code) return;
// Use our shared utility
setHighlightedCode(highlightCode(code, language, true, 1000));
}, [code, language]);
if (!code) return null;
const handleCopy = () => {
navigator.clipboard.writeText(code);
setCopied(true);
setTimeout(() => setCopied(false), 2000);
};
const lines = code.split('\n');
return (
<div className="relative overflow-hidden rounded bg-muted">
<div className="absolute right-1 z-10">
<Button
variant="ghost"
size="sm"
onClick={handleCopy}
className="h-10 w-10 p-1 opacity-50 hover:opacity-100"
>
{copied ? <Check size={16} /> : <Clipboard className="drop-shadow-md" size={16} />}
</Button>
</div>
{/* Single scrollable container for both line numbers and code */}
<div className="overflow-auto" style={{ maxHeight }}>
<div className="flex">
{showLineNumbers && lines.length > 1 && (
<div className="min-w-12 flex-none select-none border-r border-muted-foreground/20 bg-muted/50 py-1 pr-1 text-right font-mono text-muted-foreground">
{lines.map((_, i) => (
<div key={i} className="px-2 text-xs leading-6">
{i + 1}
</div>
))}
</div>
)}
<div className="flex-1">
{highlightedCode ? (
<pre className="whitespace-pre px-4 py-1 leading-6">
<code dangerouslySetInnerHTML={{ __html: highlightedCode }} />
</pre>
) : (
<pre className="whitespace-pre px-4 py-1 leading-6">{code}</pre>
)}
</div>
</div>
</div>
</div>
);
}