({
value,
className,
variant = "ghost",
event,
...props
}: React.ComponentProps<typeof Button> & {
value: string
src?: string
event?: Event["name"]
tooltip?: string
})
| 65 | } |
| 66 | |
| 67 | export function CopyButton({ |
| 68 | value, |
| 69 | className, |
| 70 | variant = "ghost", |
| 71 | event, |
| 72 | ...props |
| 73 | }: React.ComponentProps<typeof Button> & { |
| 74 | value: string |
| 75 | src?: string |
| 76 | event?: Event["name"] |
| 77 | tooltip?: string |
| 78 | }) { |
| 79 | const [hasCopied, setHasCopied] = React.useState(false) |
| 80 | |
| 81 | React.useEffect(() => { |
| 82 | if (hasCopied) { |
| 83 | const timer = setTimeout(() => setHasCopied(false), 2000) |
| 84 | return () => clearTimeout(timer) |
| 85 | } |
| 86 | }, [hasCopied]) |
| 87 | |
| 88 | return ( |
| 89 | <Button |
| 90 | data-slot="copy-button" |
| 91 | data-copied={hasCopied} |
| 92 | size="icon" |
| 93 | variant={variant} |
| 94 | className={cn( |
| 95 | "absolute top-3 right-2 z-10 size-7 bg-code hover:opacity-100 focus-visible:opacity-100", |
| 96 | className |
| 97 | )} |
| 98 | onClick={async () => { |
| 99 | const hasCopied = await copyToClipboardWithMeta( |
| 100 | value, |
| 101 | event |
| 102 | ? { |
| 103 | name: event, |
| 104 | properties: { |
| 105 | code: value, |
| 106 | }, |
| 107 | } |
| 108 | : undefined |
| 109 | ) |
| 110 | |
| 111 | if (hasCopied) { |
| 112 | setHasCopied(true) |
| 113 | } |
| 114 | }} |
| 115 | {...props} |
| 116 | > |
| 117 | <span className="sr-only">Copy</span> |
| 118 | {hasCopied ? <IconCheck /> : <IconCopy />} |
| 119 | </Button> |
| 120 | ) |
| 121 | } |
nothing calls this directly
no test coverage detected