/**
 * `createContextMenu` — headless primitive for the ContextMenu compound.
 *
 * ContextMenu is a thin façade over `<Menu.Root>` that:
 *  - Owns an `anchor` signal (virtual element at the right-click point).
 *  - Owns the open state per Base UI's controlled/uncontrolled contract:
 *    the gesture (right-click / long-press) writes the internal signal,
 *    seeded once from `defaultOpen`; a defined `open` option wins.
 *  - Exposes `setAnchor` + `setOpen` so `<ContextMenu.Trigger>` can update
 *    both atomically on contextmenu / pointerdown events.
 *
 * Gesture capture (contextmenu event, long-press timer, move threshold)
 * and DOM concerns stay in `<ContextMenu.Root>` / `<ContextMenu.Trigger>`.
 *
 * Why a separate primitive instead of reusing `createMenu` directly?
 * ContextMenu needs the `anchor` state and the gesture-driven internal open
 * signal. `createMenu` owns `open` as a pure pass-through, but ContextMenu
 * must manage its own open signal that the trigger writes imperatively —
 * that asymmetry warrants a dedicated primitive rather than composing
 * createMenu with extra options.
 */
import { createContext, createMemo, createSignal, runWithOwner, untrack, useContext } from "solid-js";
import { createControlledState } from "../internals/create-controlled-state.jsx";
import { readOption } from "../internals/maybe-accessor.jsx";
import { SNAPSHOT_KEYS, snapshotKeys } from "../internals/observability/snapshot.jsx";

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

/** Default zero-sized anchor used before the first contextmenu event. */
function createDefaultAnchor() {
  return {
    getBoundingClientRect() {
      return typeof DOMRect !== "undefined" ? DOMRect.fromRect({
        width: 0,
        height: 0,
        x: 0,
        y: 0
      }) : {
        width: 0,
        height: 0,
        x: 0,
        y: 0,
        top: 0,
        right: 0,
        bottom: 0,
        left: 0,
        toJSON: () => ({})
      };
    }
  };
}
// ---------------------------------------------------------------------------
// Context
// ---------------------------------------------------------------------------

const ContextMenuApiContext = createContext(null);

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

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

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

/**
 * Headless primitive for the ContextMenu compound. Owns logical state — open,
 * disabled, anchor. Gesture capture and DOM concerns live in
 * `<ContextMenu.Root>` and `<ContextMenu.Trigger>`.
 */
export function createContextMenu(options = {}) {
  const disabled = createMemo(() => Boolean(readOption(options.disabled)), {
    name: "contextMenu.disabled"
  });

  // Controlled / uncontrolled open state (Base UI `open` / `defaultOpen`
  // contract): the `open` option wins while its resolved value is defined;
  // otherwise the gesture-driven internal signal (seeded once from
  // `defaultOpen`, written by `setOpen`) backs the state.
  const [open, setUncontrolledOpen] = createControlledState({
    controlled: () => {
      const controlled = readOption(options.open);
      return controlled === undefined ? undefined : Boolean(controlled);
    },
    default: () => readOption(options.defaultOpen),
    fallback: false,
    name: "<ContextMenu.Root>",
    state: "open"
  });
  const [anchor, setAnchor] = createSignal(createDefaultAnchor(), {
    ownedWrite: true,
    name: "contextMenu.anchor"
  });

  // Base UI change flow: fire `onOpenChange` (via `runWithOwner(null, ...)`
  // so consumer signal writes don't trip SIGNAL_WRITE_IN_OWNED_SCOPE),
  // honor `details.cancel()`, then write the uncontrolled state (inert
  // while the `open` option is controlled).
  const setOpen = (next, details) => {
    if (untrack(disabled)) return;
    const d = details ?? {
      reason: "none",
      isCanceled: false
    };
    runWithOwner(null, () => options.onOpenChange?.(next, d));
    if (d.isCanceled) return;
    setUncontrolledOpen(next);
  };
  const api = {
    open,
    disabled,
    anchor,
    setAnchor,
    setOpen,
    Provider: props => <ContextMenuApiContext value={api}>
				{props.children}
			</ContextMenuApiContext>
  };
  api[SNAPSHOT_KEYS] = CONTEXT_MENU_SNAPSHOT_KEYS;
  return api;
}
const CONTEXT_MENU_SNAPSHOT_KEYS = snapshotKeys("open", "disabled");
//# sourceMappingURL=create-context-menu.jsx.map
