Files
kilo-maintainer[bot] 74b3afaacb chore: generate
2026-02-19 12:51:37 +00:00

107 lines
2.8 KiB
TypeScript

import Prism from "prismjs"
import * as React from "react"
import { Codicon } from "./Codicon"
export function CodeBlock({ children, "data-language": language }) {
const ref = React.useRef(null)
const timeoutRef = React.useRef(null)
const [copied, setCopied] = React.useState(false)
React.useEffect(() => {
if (ref.current) Prism.highlightElement(ref.current, false)
}, [children])
React.useEffect(() => {
return () => {
if (timeoutRef.current) {
clearTimeout(timeoutRef.current)
}
}
}, [])
const handleCopy = async () => {
const code = ref.current?.textContent || ""
try {
await navigator.clipboard.writeText(code)
setCopied(true)
if (timeoutRef.current) {
clearTimeout(timeoutRef.current)
}
timeoutRef.current = setTimeout(() => setCopied(false), 2000)
} catch (err) {
console.error("Failed to copy code:", err)
}
}
return (
<div className="code" aria-live="polite">
<button
type="button"
className="copy-button"
onClick={handleCopy}
aria-label="Copy code to clipboard"
title={copied ? "Copied!" : "Copy code"}
>
{copied ? <Codicon name="check" /> : <Codicon name="copy" />}
</button>
<pre ref={ref} className={`language-${language}`}>
{children}
</pre>
<style jsx>
{`
.code {
position: relative;
}
.copy-button {
position: absolute;
top: 8px;
right: 8px;
padding: 6px 8px;
background: rgba(0, 0, 0, 0.05);
border: 1px solid rgba(0, 0, 0, 0.1);
border-radius: 4px;
color: rgba(0, 0, 0, 0.4);
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s ease;
z-index: 10;
}
.copy-button:hover {
background: rgba(0, 0, 0, 0.1);
color: rgba(0, 0, 0, 0.6);
border-color: rgba(0, 0, 0, 0.2);
}
:global(.dark) .copy-button {
background: rgba(255, 255, 255, 0.05);
border-color: rgba(255, 255, 255, 0.1);
color: rgba(255, 255, 255, 0.4);
}
:global(.dark) .copy-button:hover {
background: rgba(255, 255, 255, 0.1);
color: rgba(255, 255, 255, 0.7);
border-color: rgba(255, 255, 255, 0.2);
}
.copy-button:active {
transform: scale(0.95);
}
/* Override Prism styles */
.code :global(pre[class*="language-"]) {
text-shadow: none;
border-radius: 4px;
padding-right: 3.5rem;
}
`}
</style>
</div>
)
}