/**
 * `<Menubar>` — container for top-level menus with arrow-key roving focus
 * between triggers. Solid 2 port of Base UI React's `Menubar`
 * (`packages/react/src/menubar/Menubar.tsx`).
 *
 * Wraps the contained `<Menu.Root>`s in a shared `<FloatingTree>`, provides
 * a `MenubarContext` that each child menu reads, and owns a keyboard
 * handler on the `role="menubar"` element so arrow keys navigate between
 * the contained `<Menu.Trigger>` elements.
 *
 * ### Port deviations from React
 *
 *  - React uses `useListNavigation` inside each menu with `externalTree`
 *    + `parentOrientation` so arrow-keys flow across menus through the
 *    floating tree. The Solid port discovers triggers by querying the
 *    menubar's content element for `button[aria-haspopup="menu"]`.
 *    `useListNavigation` already accepts `parentOrientation` as an
 *    accessor (P3 landed) — now needs structural plumbing
 *    (MenubarContext → child Menu.Root → listnav) and top-level menus
 *    must consume the parent-axis main-key to suppress the menu's own
 *    open-on-arrow path in vertical menubars. Deferred until the
 *    browser harness can verify vertical-menubar key mapping.
 *  - `menuopenchange` events ARE consumed from the shared `FloatingTree`.
 *    The menubar wraps children in
 *    `<FloatingNode id={menubarNodeId}>` so contained `<Menu.Root>`s'
 *    `floatingParentNodeId` equals the menubar's id — that's the key the
 *    event handler filters on. The older direct-through-context path
 *    (`MenubarContext.setHasSubmenuOpen` + `registerOpenMenu`) is
 *    preserved; both paths are idempotent.
 *  - `allowMouseUpTriggerRef` is ported as a shared `MutableRef<boolean>`;
 *    consumers (child menus) can read it when the mouseup-on-item window
 *    lands.
 */

import { dynamic } from "@solidjs/web";
import { createSignal, omit, onCleanup, untrack } from "solid-js";
import { useDirection } from "../direction-provider/direction-provider-context.jsx";
import { useBaseUiId } from "../internals/base-ui-id.jsx";
import { FloatingNode, FloatingTree, useFloatingNodeId } from "../internals/floating-ui/components/floating-tree.jsx";
import { FloatingTreeStore } from "../internals/floating-ui/components/floating-tree-store.jsx";
import { readOption } from "../internals/maybe-accessor.jsx";
import { mergeRootProps } from "../internals/merge-root-props.jsx";
import { resolveClassStyle } from "../internals/resolve-class-style.jsx";
import { createMenubar } from "./create-menubar.jsx";
import { MenubarContext } from "./menubar-context.jsx";
import { MenubarDataAttributes } from "./menubar-data-attributes.jsx";
/** Collect the top-level menu triggers rendered inside the menubar. */
function getTriggers(content) {
  if (!content) return [];
  // Each `<Menu.Trigger>` renders `aria-haspopup="menu"`; a submenu trigger
  // sets the same but lives inside a nested menu popup that is portalled —
  // so it won't match our container-scoped query.
  const nodes = content.querySelectorAll('button[aria-haspopup="menu"]');
  return Array.from(nodes).filter(el => !el.hasAttribute("disabled") && !el.hasAttribute("aria-disabled"));
}

/**
 * Inner body — runs INSIDE the `<FloatingTree>` so `useFloatingNodeId` can
 * allocate a node id bound to the menubar's tree. Child `<Menu.Root>`s
 * mounted under this node read `floatingParentNodeId` as the menubar's id,
 * which is the key the events path filters on.
 */
function MenubarInner(props) {
  // `tree` is a stable store instance passed once from `<Menubar>`; read it
  // under `untrack` so the body-time access doesn't trip STRICT_READ.
  const tree = untrack(() => props.tree);
  // Compose the headless Menubar primitive — owns orientation, modal, disabled,
  // loopFocus, hasSubmenuOpen, and the single-open coordinator. The wrapper
  // layers FloatingTree, FloatingNode, role="menubar", and the keyboard
  // handler on top.
  const menubarPrimitive = createMenubar({
    orientation: () => readOption(props.orientation) ?? "horizontal",
    modal: () => readOption(props.modal) ?? true,
    disabled: () => readOption(props.disabled) ?? false,
    loopFocus: () => readOption(props.loopFocus) ?? true
  });
  const modal = menubarPrimitive.modal;
  const disabled = menubarPrimitive.disabled;
  const orientation = menubarPrimitive.orientation;
  const loopFocus = menubarPrimitive.loopFocus;
  const hasSubmenuOpen = menubarPrimitive.hasSubmenuOpen;
  const setHasSubmenuOpen = menubarPrimitive.setHasSubmenuOpen;
  const registerOpenMenu = menubarPrimitive.registerOpenMenu;
  const fallbackId = useBaseUiId();
  const resolvedId = () => typeof props.id === "string" ? props.id : fallbackId;
  const [contentElement, setContentElement] = createSignal(null, {
    ownedWrite: true
  });
  const allowMouseUpTriggerRef = {
    current: false
  };

  // Allocate a floating-tree node id for the menubar itself. Every child
  // `<Menu.Root>` inside reads this as its `floatingParentNodeId` — that's
  // what distinguishes a top-level menubar child from a submenu when the
  // events path filters `menuopenchange`.
  const menubarNodeId = useFloatingNodeId();

  // Events-path consumption of `menuopenchange`. Child menus
  // emit through `floatingTreeRoot.events`; we filter for ones whose
  // `parentNodeId === menubarNodeId` and track `hasSubmenuOpen` from that
  // stream in parallel with the existing direct-`setHasSubmenuOpen` path.
  // The two are idempotent — a child menu both calls `setHasSubmenuOpen`
  // directly and emits an event; `hasSubmenuOpen` is the disjunction.
  let openFromEvents = 0;
  const handleMenuOpenChange = data => {
    if (data.parentNodeId !== menubarNodeId) return;
    if (data.open) {
      openFromEvents += 1;
      setHasSubmenuOpen(true);
    } else {
      openFromEvents = Math.max(0, openFromEvents - 1);
      if (openFromEvents === 0) {
        setHasSubmenuOpen(false);
      }
    }
  };
  tree.events.on("menuopenchange", handleMenuOpenChange);
  onCleanup(() => {
    tree.events.off("menuopenchange", handleMenuOpenChange);
  });
  const direction = useDirection();

  // Keyboard handler — arrow keys traverse top-level triggers. We discover
  // them by DOM query at event time (the trigger set is stable per render
  // so re-queries are cheap + avoid registration plumbing).
  const handleKeyDown = event => {
    const content = contentElement();
    if (!content) return;
    const triggers = getTriggers(content);
    if (triggers.length === 0) return;
    const target = event.target;
    const active = target instanceof HTMLElement ? triggers.find(t => t === target || t.contains(target)) : undefined;
    if (!active) return;
    const isRtl = direction() === "rtl";
    const forwardKey = orientation() === "horizontal" ? isRtl ? "ArrowLeft" : "ArrowRight" : "ArrowDown";
    const backwardKey = orientation() === "horizontal" ? isRtl ? "ArrowRight" : "ArrowLeft" : "ArrowUp";
    const firstKey = "Home";
    const lastKey = "End";
    const currentIndex = triggers.indexOf(active);
    const max = triggers.length - 1;
    let nextIndex = null;
    if (event.key === forwardKey) {
      if (currentIndex < max) {
        nextIndex = currentIndex + 1;
      } else if (loopFocus()) {
        nextIndex = 0;
      }
    } else if (event.key === backwardKey) {
      if (currentIndex > 0) {
        nextIndex = currentIndex - 1;
      } else if (loopFocus()) {
        nextIndex = max;
      }
    } else if (event.key === firstKey) {
      nextIndex = 0;
    } else if (event.key === lastKey) {
      nextIndex = max;
    }
    if (nextIndex == null || nextIndex === currentIndex) return;
    event.preventDefault();
    event.stopPropagation();
    triggers[nextIndex]?.focus();
  };
  const contextValue = {
    modal,
    disabled,
    contentElement,
    setContentElement,
    hasSubmenuOpen,
    setHasSubmenuOpen: open => {
      setHasSubmenuOpen(open);
    },
    orientation,
    allowMouseUpTriggerRef,
    rootId: resolvedId,
    registerOpenMenu
  };
  const setRef = el => {
    setContentElement(el);
  };
  const userStyling = resolveClassStyle(props, () => ({
    orientation: orientation(),
    modal: modal(),
    hasSubmenuOpen: hasSubmenuOpen()
  }));
  const userHtmlProps = omit(props, "class", "style", "attrs", "as", "children", "modal", "disabled", "orientation", "loopFocus", "id", "tree");
  const internalProps = {
    ref: setRef,
    role: "menubar",
    onKeyDown: handleKeyDown,
    get id() {
      return resolvedId();
    },
    get "aria-orientation"() {
      return orientation();
    },
    get [MenubarDataAttributes.orientation]() {
      return orientation();
    },
    get [MenubarDataAttributes.modal]() {
      return modal() ? "" : undefined;
    },
    get [MenubarDataAttributes.hasSubmenuOpen]() {
      return hasSubmenuOpen() ? "" : undefined;
    }
  };
  const styledUserProps = mergeRootProps(userStyling, userHtmlProps);
  const merged = mergeRootProps(internalProps, styledUserProps);
  const Tag = dynamic(() => props.as ?? "div");
  return <Tag {...merged}>
			<MenubarContext value={contextValue}>
				<FloatingNode id={menubarNodeId}>{props.children}</FloatingNode>
			</MenubarContext>
		</Tag>;
}

/**
 * The container for menus. Renders a `<div role="menubar">` that roving-focuses
 * across contained `<Menu.Trigger>` elements via arrow keys.
 */
export function Menubar(props) {
  const tree = new FloatingTreeStore();
  // Render `MenubarInner` as a component (not a plain call) so its body runs
  // INSIDE the `<FloatingTree>` provider's owner — otherwise `useFloatingNodeId`
  // reads a null tree context and the menubar's own node never registers.
  return <FloatingTree externalTree={tree}>
			<MenubarInner {...props} tree={tree} />
		</FloatingTree>;
}
//# sourceMappingURL=menubar.jsx.map
