"use client"; import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, } from "@/components/ui/input-group"; import { cn } from "@/lib/utils"; import { CheckIcon, CopyIcon } from "lucide-react"; import type { ComponentProps } from "react"; import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, } from "react"; interface SnippetContextType { code: string; } const SnippetContext = createContext({ code: "", }); export type SnippetProps = ComponentProps & { code: string; }; export const Snippet = ({ code, className, children, ...props }: SnippetProps) => { const contextValue = useMemo(() => ({ code }), [code]); return ( {children} ); }; export type SnippetAddonProps = ComponentProps; export const SnippetAddon = (props: SnippetAddonProps) => ( ); export type SnippetTextProps = ComponentProps; export const SnippetText = ({ className, ...props }: SnippetTextProps) => ( ); export type SnippetInputProps = Omit< ComponentProps, "readOnly" | "value" >; export const SnippetInput = ({ className, ...props }: SnippetInputProps) => { const { code } = useContext(SnippetContext); return ( ); }; export type SnippetCopyButtonProps = ComponentProps & { onCopy?: () => void; onError?: (error: Error) => void; timeout?: number; }; export const SnippetCopyButton = ({ onCopy, onError, timeout = 2000, children, className, ...props }: SnippetCopyButtonProps) => { const [isCopied, setIsCopied] = useState(false); const timeoutRef = useRef(0); const { code } = useContext(SnippetContext); const copyToClipboard = useCallback(async () => { if (typeof window === "undefined" || !navigator?.clipboard?.writeText) { onError?.(new Error("Clipboard API not available")); return; } try { if (!isCopied) { await navigator.clipboard.writeText(code); setIsCopied(true); onCopy?.(); timeoutRef.current = window.setTimeout( () => setIsCopied(false), timeout ); } } catch (error) { onError?.(error as Error); } }, [code, onCopy, onError, timeout, isCopied]); useEffect( () => () => { window.clearTimeout(timeoutRef.current); }, [] ); const Icon = isCopied ? CheckIcon : CopyIcon; return ( {children ?? } ); };