/**
 * Simple context menu component.
 * Shows a menu at a given position with clickable items.
 */
let activeMenu = null;
let dismissListener = null;
let escapeListener = null;
/** Close any open context menu and remove dismiss listeners */
export function closeContextMenu() {
    if (activeMenu) {
        activeMenu.remove();
        activeMenu = null;
    }
    if (dismissListener) {
        document.removeEventListener("pointerdown", dismissListener, true);
        dismissListener = null;
    }
    if (escapeListener) {
        document.removeEventListener("keydown", escapeListener, true);
        escapeListener = null;
    }
}
/** Show a context menu at the given position */
export function showContextMenu(x, y, items) {
    closeContextMenu();
    const menu = document.createElement("div");
    menu.className = "ctx-menu";
    for (const item of items) {
        if (item.separator) {
            const sep = document.createElement("div");
            sep.className = "ctx-sep";
            menu.appendChild(sep);
            continue;
        }
        const el = document.createElement("div");
        el.className = "ctx-item" + (item.disabled ? " ctx-disabled" : "") + (item.emphasized ? " ctx-emphasized" : "");
        if (item.emphasized)
            el.style.fontWeight = "600";
        el.textContent = item.label;
        if (item.tooltip)
            el.title = item.tooltip;
        if (!item.disabled) {
            el.addEventListener("click", () => {
                closeContextMenu();
                item.action();
            });
        }
        menu.appendChild(el);
    }
    menu.style.left = `${x}px`;
    menu.style.top = `${y}px`;
    document.body.appendChild(menu);
    // Keep the menu fully on-screen — clamp to ALL FOUR edges. The old
    // flip-only logic (x − width) went NEGATIVE when the press was near an
    // edge on a narrow screen, so Android long-press menus rendered clipped
    // mid-word off the left side (Bob 2026-07-13). visualViewport tracks
    // the on-screen keyboard; taller-than-screen menus scroll internally.
    const vw = window.visualViewport?.width ?? window.innerWidth;
    const vh = window.visualViewport?.height ?? window.innerHeight;
    let rect = menu.getBoundingClientRect();
    if (rect.height > vh - 8) {
        menu.style.maxHeight = `${vh - 8}px`;
        menu.style.overflowY = "auto";
        rect = menu.getBoundingClientRect();
    }
    let left = x, top = y;
    if (left + rect.width > vw)
        left = x - rect.width; // prefer flipping…
    if (top + rect.height > vh)
        top = y - rect.height;
    left = Math.max(4, Math.min(left, vw - rect.width - 4)); // …then clamp
    top = Math.max(4, Math.min(top, vh - rect.height - 4));
    menu.style.left = `${left}px`;
    menu.style.top = `${top}px`;
    activeMenu = menu;
    // Dismiss on click/tap outside the menu. Uses pointerdown in capture phase
    // so it fires before any child handler and catches both left- and right-clicks.
    // Deferred by one frame so the opening pointerdown doesn't immediately close it.
    requestAnimationFrame(() => {
        dismissListener = (e) => {
            if (activeMenu && !activeMenu.contains(e.target)) {
                closeContextMenu();
            }
        };
        document.addEventListener("pointerdown", dismissListener, true);
        escapeListener = (e) => {
            if (e.key === "Escape") {
                e.preventDefault();
                e.stopPropagation();
                closeContextMenu();
            }
        };
        document.addEventListener("keydown", escapeListener, true);
    });
}
// Scroll anywhere closes the menu (capture phase so nested scrollers trigger it)
document.addEventListener("scroll", closeContextMenu, true);
// A new right-click that opens a different menu goes through showContextMenu→closeContextMenu
document.addEventListener("contextmenu", () => { });
// Iframe pointerdown forwarded from preview/compose iframes — needed because
// iframe events don't bubble to the parent document, so the dismissListener
// (which hooks document.pointerdown) doesn't see clicks INSIDE iframes. The
// message-viewer's inline iframe script posts {type:"iframePointerDown"} on
// every non-right-click pointerdown.
window.addEventListener("message", (e) => {
    if (e.data && e.data.type === "iframePointerDown")
        closeContextMenu();
});
//# sourceMappingURL=context-menu.js.map