import { useEffect, useRef, useState } from "react"; import { PAGE_TYPES } from "../model/book"; import { useEscapeLayer } from "../escape"; import { useFocusTrap } from "../focus"; import { Icon } from "./Icon"; interface AddPageMenuProps { onAdd: (group: "front" | "back", title: string) => void; onAddPart: () => void; } const GROUPS: { key: "front" | "back"; label: string }[] = [ { key: "front", label: "Front matter" }, { key: "back", label: "Back matter" }, ]; export function AddPageMenu({ onAdd, onAddPart }: AddPageMenuProps) { const [open, setOpen] = useState(false); const [coords, setCoords] = useState({ top: 0, left: 0 }); const btnRef = useRef(null); const popRef = useRef(null); const toggle = () => { if (!open && btnRef.current) { const r = btnRef.current.getBoundingClientRect(); setCoords({ top: r.bottom + 4, left: r.left }); } setOpen((v) => !v); }; useEffect(() => { if (!open) return; const close = () => setOpen(false); document.addEventListener("mousedown", close); document.addEventListener("scroll", close, true); window.addEventListener("resize", close); return () => { document.removeEventListener("mousedown", close); document.removeEventListener("scroll", close, true); window.removeEventListener("resize", close); }; }, [open]); useFocusTrap(popRef, open); useEscapeLayer(open, () => { setOpen(false); btnRef.current?.focus(); }); const onMenuKeyDown = (e: React.KeyboardEvent) => { if (e.key === "ArrowDown" || e.key === "ArrowUp") { e.preventDefault(); const items = Array.from(popRef.current?.querySelectorAll(".add-page-item") ?? []); const idx = items.indexOf(document.activeElement as HTMLElement); const nextIdx = e.key === "ArrowDown" ? (idx + 1) % items.length : (idx - 1 + items.length) % items.length; items[nextIdx]?.focus(); } }; const pick = (group: "front" | "back", label: string) => { setOpen(false); onAdd(group, label); }; const pickPart = () => { setOpen(false); onAddPart(); }; return ( <> {open && (
e.stopPropagation()} onKeyDown={onMenuKeyDown} >
Body
{GROUPS.map((g) => (
{g.label}
{PAGE_TYPES.filter((t) => t.group === g.key).map((t) => ( ))}
))}
)} ); }