fosrl.pangolin/src/components/CopyTextBox.tsx

66 lines
1.8 KiB
TypeScript
Raw Normal View History

2024-11-02 23:46:08 -04:00
"use client";
import { useState, useRef } from "react";
import { Button } from "@/components/ui/button";
import { Copy, Check } from "lucide-react";
2025-04-27 13:03:00 -04:00
type CopyTextBoxProps = {
text?: string;
displayText?: string;
wrapText?: boolean;
outline?: boolean;
};
2025-03-16 15:20:19 -04:00
export default function CopyTextBox({
text = "",
2025-04-27 13:03:00 -04:00
displayText,
2025-03-16 15:20:19 -04:00
wrapText = false,
outline = true
2025-04-27 13:03:00 -04:00
}: CopyTextBoxProps) {
2024-11-02 23:46:08 -04:00
const [isCopied, setIsCopied] = useState(false);
const textRef = useRef<HTMLPreElement>(null);
const copyToClipboard = async () => {
if (textRef.current) {
try {
2025-04-27 13:03:00 -04:00
await navigator.clipboard.writeText(text);
2024-11-02 23:46:08 -04:00
setIsCopied(true);
setTimeout(() => setIsCopied(false), 2000);
} catch (err) {
console.error("Failed to copy text: ", err);
}
}
};
return (
2025-03-16 15:20:19 -04:00
<div
2025-04-12 19:50:30 -04:00
className={`relative w-full border rounded-md ${!outline ? "bg-muted" : "bg-card"}`}
2025-03-16 15:20:19 -04:00
>
2024-11-02 23:46:08 -04:00
<pre
ref={textRef}
2025-04-05 22:28:47 -04:00
className={`p-2 pr-16 text-sm w-full ${
2024-11-02 23:46:08 -04:00
wrapText
? "whitespace-pre-wrap break-words"
: "overflow-x-auto"
}`}
>
2025-04-27 13:03:00 -04:00
<code className="block w-full">{displayText || text}</code>
2024-11-02 23:46:08 -04:00
</pre>
<Button
2025-04-05 22:28:47 -04:00
variant="ghost"
size="sm"
2024-11-10 23:08:06 -05:00
type="button"
2025-04-05 22:28:47 -04:00
className="absolute top-0.5 right-0 z-10 bg-card"
2024-11-02 23:46:08 -04:00
onClick={copyToClipboard}
aria-label="Copy to clipboard"
>
{isCopied ? (
<Check className="h-4 w-4 text-green-500" />
) : (
<Copy className="h-4 w-4" />
)}
</Button>
</div>
);
}