58c4cb12a8
- ship libvips with the runtime image so POST /api/v1/media stops failing - admin downloads openapi.json and the style guide via session, no token - copy rows for both API addresses - anchor mark in the wordmark and a favicon
47 lines
1009 B
TypeScript
47 lines
1009 B
TypeScript
'use client'
|
|
|
|
import { useEffect, useState } from 'react'
|
|
import { TbCheck, TbCopy } from 'react-icons/tb'
|
|
import { ghostButtonClass } from '~/components/admin/styles'
|
|
|
|
export type CopyButtonProps = {
|
|
value: string
|
|
label: string
|
|
doneLabel: string
|
|
className?: string
|
|
}
|
|
|
|
export function CopyButton({ value, label, doneLabel, className }: CopyButtonProps) {
|
|
const [copied, setCopied] = useState(false)
|
|
|
|
useEffect(() => {
|
|
if (!copied) {
|
|
return
|
|
}
|
|
|
|
const timer = setTimeout(() => setCopied(false), 2000)
|
|
|
|
return () => clearTimeout(timer)
|
|
}, [copied])
|
|
|
|
async function copy() {
|
|
try {
|
|
await navigator.clipboard.writeText(value)
|
|
setCopied(true)
|
|
} catch {
|
|
setCopied(false)
|
|
}
|
|
}
|
|
|
|
return (
|
|
<button type="button" onClick={copy} className={`${ghostButtonClass} ${className ?? ''}`}>
|
|
{copied ? (
|
|
<TbCheck aria-hidden="true" className="size-4 shrink-0" />
|
|
) : (
|
|
<TbCopy aria-hidden="true" className="size-4 shrink-0" />
|
|
)}
|
|
{copied ? doneLabel : label}
|
|
</button>
|
|
)
|
|
}
|