forked from baron/baron-sso
55 lines
1.2 KiB
TypeScript
55 lines
1.2 KiB
TypeScript
import * as React from "react";
|
|
import { Check, Copy } from "lucide-react";
|
|
import { Button, type ButtonProps } from "./button";
|
|
import { cn } from "../../lib/utils";
|
|
|
|
interface CopyButtonProps extends ButtonProps {
|
|
value: string;
|
|
onCopy?: () => void;
|
|
}
|
|
|
|
export function CopyButton({
|
|
value,
|
|
onCopy,
|
|
className,
|
|
variant = "secondary",
|
|
size = "icon",
|
|
...props
|
|
}: CopyButtonProps) {
|
|
const [hasCopied, setHasCopied] = React.useState(false);
|
|
|
|
React.useEffect(() => {
|
|
if (hasCopied) {
|
|
const timer = setTimeout(() => setHasCopied(false), 1500);
|
|
return () => clearTimeout(timer);
|
|
}
|
|
}, [hasCopied]);
|
|
|
|
const copyToClipboard = async () => {
|
|
try {
|
|
await navigator.clipboard.writeText(value);
|
|
setHasCopied(true);
|
|
if (onCopy) onCopy();
|
|
} catch (err) {
|
|
console.error("Failed to copy text: ", err);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<Button
|
|
size={size}
|
|
variant={variant}
|
|
className={cn("relative z-10", className)}
|
|
onClick={copyToClipboard}
|
|
{...props}
|
|
>
|
|
<span className="sr-only">Copy</span>
|
|
{hasCopied ? (
|
|
<Check className="h-4 w-4 text-emerald-500 transition-all scale-110" />
|
|
) : (
|
|
<Copy className="h-4 w-4 transition-all" />
|
|
)}
|
|
</Button>
|
|
);
|
|
}
|