import { Check } from "lucide-react"; import { type ReactElement, useCallback, useEffect, useRef, useState, } from "react"; import { cn } from "../../lib/utils"; import { Button } from "./button"; interface ConfirmButtonProps { readonly onConfirm: () => void; readonly icon: ReactElement; readonly label: string; readonly size?: "icon" | "icon-sm"; readonly className?: string; readonly disabled?: boolean; } const REVERT_TIMEOUT_MS = 5_000; export function ConfirmButton({ onConfirm, icon, label, size = "icon", className, disabled, }: ConfirmButtonProps) { const [isConfirming, setIsConfirming] = useState(false); const timerRef = useRef>(undefined); const wrapperRef = useRef(null); const revert = useCallback(() => { setIsConfirming(false); clearTimeout(timerRef.current); }, []); // Cleanup timer on unmount useEffect(() => { return () => clearTimeout(timerRef.current); }, []); // Click-outside listener when confirming useEffect(() => { if (!isConfirming) return; function handleMouseDown(e: MouseEvent) { if ( wrapperRef.current && !wrapperRef.current.contains(e.target as Node) ) { revert(); } } function handleEscapeKey(e: KeyboardEvent) { if (e.key === "Escape") { revert(); } } document.addEventListener("mousedown", handleMouseDown); document.addEventListener("keydown", handleEscapeKey); return () => { document.removeEventListener("mousedown", handleMouseDown); document.removeEventListener("keydown", handleEscapeKey); }; }, [isConfirming, revert]); const handleKeyDown = useCallback((e: React.KeyboardEvent) => { if (e.key === "Enter" || e.key === " ") { e.stopPropagation(); } }, []); const handleClick = useCallback( (e: React.MouseEvent) => { e.stopPropagation(); if (disabled) return; if (isConfirming) { revert(); onConfirm(); } else { setIsConfirming(true); clearTimeout(timerRef.current); timerRef.current = setTimeout(revert, REVERT_TIMEOUT_MS); } }, [isConfirming, disabled, onConfirm, revert], ); return (
); }