"use client"; import * as React from "react"; import { CheckIcon, CopyIcon } from "lucide-react"; import { useTranslations } from "next-intl"; import { toast } from "sonner"; import { Button } from "@/components/ui/button"; import { cn, copyText } from "@/lib/utils"; type CopyButtonProps = { // 要复制的文本;为空则按钮禁用。 text: string | null | undefined; // 复制成功后的 toast 文案,默认「已复制」。 successMessage?: string; label?: React.ReactNode; size?: React.ComponentProps["size"]; variant?: React.ComponentProps["variant"]; className?: string; }; // CopyButton 统一的「复制到剪贴板」按钮:内置成功/失败反馈,并在 HTTP 非安全上下文 // 下自动降级(见 copyText)。 export function CopyButton({ text, successMessage, label, size = "sm", variant = "outline", className, }: CopyButtonProps) { const t = useTranslations("copyButton"); const [copied, setCopied] = React.useState(false); const timer = React.useRef | null>(null); React.useEffect(() => { return () => { if (timer.current) clearTimeout(timer.current); }; }, []); async function handleCopy() { if (!text) return; const ok = await copyText(text); if (ok) { setCopied(true); toast.success(successMessage ?? t("success")); if (timer.current) clearTimeout(timer.current); timer.current = setTimeout(() => setCopied(false), 1500); } else { toast.error(t("error")); } } return ( ); }