import { Button, type ButtonProps } from "@/components/ui/button"; import { Check, Copy } from "lucide-react"; import { type HTMLProps, type ReactNode, useCallback, useEffect, useState } from "react"; import { CopyToClipboard } from "react-copy-to-clipboard"; import { useTranslation } from "react-i18next"; import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"; import { materialDark } from "react-syntax-highlighter/dist/esm/styles/prism"; import { toast } from "sonner"; interface CopyButtonProps extends ButtonProps { value: string; src?: string; } export function CopyButton({ value }: Readonly) { const [hasCopied, setHasCopied] = useState(false); const { t } = useTranslation(); useEffect(() => { if (hasCopied) { const timer = setTimeout(() => { setHasCopied(false); }, 1000); return () => clearTimeout(timer); } }, [hasCopied]); const handleCopy = useCallback(() => { if (!hasCopied) { setHasCopied(true); toast.success(t("copySuccess"), { duration: 1000 }); } }, [hasCopied, t]); return ( ); } export function CodeViewer({ code, header, language, height, showLineNumbers = true, wrapLongLines = true, }: CodeViewerProps) { const lineProps: lineTagPropsFunction | HTMLProps | undefined = wrapLongLines ? { style: { overflowWrap: "break-word", whiteSpace: "pre-wrap" } } : undefined; return (
{header && (
{header}
)} {!header && (
)}
{code}
); } interface CodeViewerProps { code: string; language: string; header?: ReactNode; height?: string | number; showLineNumbers?: boolean; wrapLongLines?: boolean; lineProps?: (lineNumber: number) => React.HTMLProps; }