// Rôle : fournit un dropdown compact réutilisable pour menus d'icônes, couleurs et actions rapides. import { useEffect, useRef, useState } from "react"; export function CompactDropdown({ className = "", menuClassName = "", menuProps = {}, label, openOnHover = false, closeOnMouseLeave = false, preventMouseDown = false, renderTrigger, children }) { const [open, setOpen] = useState(false); const rootRef = useRef(null); const triggerRef = useRef(null); const internalPointerDownRef = useRef(false); useEffect(() => { if (!open) return undefined; function handlePointerDown(event) { if (!rootRef.current?.contains(event.target)) setOpen(false); } function handleKeyDown(event) { if (event.key === "Escape") { setOpen(false); triggerRef.current?.focus(); } } document.addEventListener("pointerdown", handlePointerDown); document.addEventListener("keydown", handleKeyDown); return () => { document.removeEventListener("pointerdown", handlePointerDown); document.removeEventListener("keydown", handleKeyDown); }; }, [open]); function close() { setOpen(false); } function toggle() { setOpen((value) => !value); } return (
setOpen(true) : undefined} onMouseLeave={closeOnMouseLeave ? close : undefined} onFocusCapture={openOnHover ? () => setOpen(true) : undefined} onPointerDownCapture={() => { internalPointerDownRef.current = true; window.setTimeout(() => { internalPointerDownRef.current = false; }, 0); }} onBlurCapture={(event) => { if (internalPointerDownRef.current) return; if (!event.currentTarget.contains(event.relatedTarget)) close(); }} onMouseDown={preventMouseDown ? (event) => event.preventDefault() : undefined} > {renderTrigger({ open, toggle, close, triggerRef })} {open && (
{children({ close })}
)}
); }