import { Heart, Sword } from "lucide-react"; import { useCallback, useEffect, useLayoutEffect, useRef, useState, } from "react"; import { Button } from "./ui/button"; import { Input } from "./ui/input"; interface HpAdjustPopoverProps { readonly onAdjust: (delta: number) => void; readonly onClose: () => void; } export function HpAdjustPopover({ onAdjust, onClose }: HpAdjustPopoverProps) { const [inputValue, setInputValue] = useState(""); const [pos, setPos] = useState<{ top: number; left: number } | null>(null); const ref = useRef(null); const inputRef = useRef(null); useLayoutEffect(() => { const el = ref.current; if (!el) return; const parent = el.parentElement; if (!parent) return; const trigger = parent.getBoundingClientRect(); const popover = el.getBoundingClientRect(); const vw = document.documentElement.clientWidth; let left = trigger.left; if (left + popover.width > vw) { left = vw - popover.width - 8; } if (left < 8) { left = 8; } setPos({ top: trigger.bottom + 4, left }); }, []); useEffect(() => { requestAnimationFrame(() => inputRef.current?.focus()); }, []); useEffect(() => { function handleClickOutside(e: MouseEvent) { if (ref.current && !ref.current.contains(e.target as Node)) { onClose(); } } document.addEventListener("mousedown", handleClickOutside); return () => document.removeEventListener("mousedown", handleClickOutside); }, [onClose]); const parsedValue = inputValue === "" ? null : Number.parseInt(inputValue, 10); const isValid = parsedValue !== null && !Number.isNaN(parsedValue) && parsedValue > 0; const applyDelta = useCallback( (sign: -1 | 1) => { if (inputValue === "") return; const n = Number.parseInt(inputValue, 10); if (Number.isNaN(n) || n <= 0) return; onAdjust(sign * n); onClose(); }, [inputValue, onAdjust, onClose], ); const handleKeyDown = useCallback( (e: React.KeyboardEvent) => { if (e.key === "Enter") { if (e.shiftKey) { applyDelta(1); } else { applyDelta(-1); } } else if (e.key === "Escape") { onClose(); } }, [applyDelta, onClose], ); return (
{ const v = e.target.value; if (v === "" || /^\d+$/.test(v)) { setInputValue(v); } }} onKeyDown={handleKeyDown} />
); }