/**
 * `createMenu` — headless primitive for the Menu compound.
 *
 * Owns the logical state surface only:
 *  - `open` — consumer-owned signal, read through the option accessor.
 *  - `activeIndex` — keyboard-highlighted item index.
 *  - `payload` — active trigger payload (for handle-driven workflows).
 *  - `setOpen` — pure event-emitter via `runWithOwner(null, ...)`.
 *
 * All DOM concerns (FloatingTree, floating-ui interaction hooks, focus trap,
 * portal, transition) stay in `<Menu.Root>`.
 */
import { createContext, createMemo, createSignal, runWithOwner, untrack, useContext } from "solid-js";
import { readOption } from "../internals/maybe-accessor.jsx";
import { SNAPSHOT_KEYS, snapshotKeys } from "../internals/observability/snapshot.jsx";

// ---------------------------------------------------------------------------
// Public types
// ---------------------------------------------------------------------------

// ---------------------------------------------------------------------------
// Context
// ---------------------------------------------------------------------------

const MenuApiContext = createContext(null);

/**
 * Read the nearest {@link MenuApi}. Throws unless `optional` is true.
 */

export function useMenu(optional) {
  const ctx = useContext(MenuApiContext);
  if (ctx == null && !optional) {
    throw new Error("Base UI: useMenu() must be called inside a <m.Provider>.");
  }
  return ctx;
}

// ---------------------------------------------------------------------------
// Primitive
// ---------------------------------------------------------------------------

/**
 * Headless primitive for the Menu compound. Owns logical state — open,
 * disabled, modal, active item index, and payload. DOM concerns (floating-ui,
 * focus trap, portal, animation) live in `<Menu.Root>`.
 */
export function createMenu(options) {
  const open = createMemo(() => Boolean(readOption(options.open)), {
    name: "menu.open"
  });
  const disabled = createMemo(() => Boolean(readOption(options.disabled)), {
    name: "menu.disabled"
  });
  const modal = createMemo(() => readOption(options.modal) ?? true, {
    name: "menu.modal"
  });

  // Internal state — not consumer-owned but privately mutable.
  const [activeIndex, setActiveIndex] = createSignal(null, {
    ownedWrite: true,
    name: "menu.activeIndex"
  });
  const [payload, setPayload] = createSignal(undefined, {
    ownedWrite: true,
    name: "menu.payload"
  });

  // Pure event-emitter — escapes the reactive owner so consumer signal
  // writes inside onOpenChange don't trip SIGNAL_WRITE_IN_OWNED_SCOPE.
  const setOpen = (next, details) => {
    if (untrack(disabled)) return;
    const d = details ?? {
      reason: "none",
      isCanceled: false
    };
    runWithOwner(null, () => options.onOpenChange?.(next, d));
  };
  const api = {
    open,
    disabled,
    modal,
    activeIndex,
    payload: payload,
    setOpen,
    setActiveIndex,
    setPayload: setPayload,
    Provider: props => <MenuApiContext value={api}>
				{props.children}
			</MenuApiContext>
  };
  api[SNAPSHOT_KEYS] = MENU_SNAPSHOT_KEYS;
  return api;
}
const MENU_SNAPSHOT_KEYS = snapshotKeys("open", "disabled", "modal", "activeIndex");
//# sourceMappingURL=create-menu.jsx.map
