import { useEffect, useState, type ReactElement, type ReactNode } from 'react' // The view's small buttons, icons named for screen readers and on hover. A delete takes a second // press, since a view's frame shows no dialog to confirm with. const CONFIRM_MS = 3000 export function IconButton({ label, onClick, className, children, }: { label: string onClick: () => void className?: string children: ReactNode }): ReactElement { return ( ) } /** The + that starts a new one of what its list holds, at the end of its bar. */ export function AddButton({ label, onClick }: { label: string; onClick: () => void }): ReactElement { return ( ) } /** A trash can that turns red on a press: a second press within a few seconds deletes. */ export function DeleteButton({ label, onDelete }: { label: string; onDelete: () => void }): ReactElement { const [armed, setArmed] = useState(false) useEffect(() => { if (!armed) return const timer = setTimeout(() => setArmed(false), CONFIRM_MS) return () => clearTimeout(timer) }, [armed]) return ( { if (armed) { setArmed(false) onDelete() } else { setArmed(true) } }} > ) } export function EditButton({ label, onClick }: { label: string; onClick: () => void }): ReactElement { return ( ) } export function RefreshButton({ label, onClick }: { label: string; onClick: () => void }): ReactElement { return ( ) } export function StopButton({ label, onClick }: { label: string; onClick: () => void }): ReactElement { return ( ) } /** Copies on a press, and shows a check for a moment once it has. */ export function CopyButton({ label, onCopy }: { label: string; onCopy: () => Promise }): ReactElement { const [copied, setCopied] = useState(false) useEffect(() => { if (!copied) return const timer = setTimeout(() => setCopied(false), CONFIRM_MS / 2) return () => clearTimeout(timer) }, [copied]) return ( void onCopy().then( () => setCopied(true), () => {}, ) } > {copied ? ( ) : ( )} ) }