/**
 * `<Menu.Trigger>` — the button that opens the menu. Solid 2 port of Base
 * UI React's `MenuTrigger` (`packages/react/src/menu/trigger/MenuTrigger.tsx`).
 *
 * Renders a `<button>` with `aria-haspopup="menu"`, `aria-expanded`, and
 * `aria-controls` pointing at the popup.
 *
 * ### Wiring
 *
 *  - Self-registers in the `MenuStore`'s `PopupTriggerMap` so
 *    `MenuHandle.open(id)` can look the trigger up.
 *  - Spreads `openInteractionTypeProps` from the root so
 *    `useOpenInteractionType` captures `openMethod` at click/pointerdown
 *    time.
 *  - When `isOpenedByThisTrigger`, wraps its element in two `FocusGuard`
 *    sentinels that catch Tab / Shift+Tab out of the trigger
 *    while the menu is open and redirect through `useTriggerFocusGuards`.
 *
 * ### Port deviations
 *
 *  - Hover-to-open is wired via `useHoverReferenceInteraction` when
 *    `openOnHover` is set.
 *  - The 200ms mouseup-on-item window (which lets users drag from the
 *    trigger to an item and release to commit) is not ported — not
 *    testable in happy-dom.
 */

import { dynamic } from "@solidjs/web";
import { createMemo, createSignal, omit, onCleanup, untrack } from "solid-js";
import { useBaseUiId } from "../../internals/base-ui-id.jsx";
import { composeRefs, userRef } from "../../internals/compose-refs.jsx";
import { useClick } from "../../internals/floating-ui/hooks/use-click.jsx";
import { useHoverReferenceInteraction } from "../../internals/floating-ui/hooks/use-hover-reference-interaction.jsx";
import { useInteractions } from "../../internals/floating-ui/hooks/use-interactions.jsx";
import { safePolygon } from "../../internals/floating-ui/safe-polygon.jsx";
import { mergeRootProps } from "../../internals/merge-root-props.jsx";
import { FocusGuard } from "../../internals/popups/focus-guard.jsx";
import { useTriggerFocusGuards } from "../../internals/popups/use-trigger-focus-guards.jsx";
import { resolveClassStyle } from "../../internals/resolve-class-style.jsx";
import { useButton } from "../../internals/use-button/use-button.jsx";
import { useMenubarContext } from "../../menubar/menubar-context.jsx";
import { useMenuRootContext } from "../root/menu-root-context.jsx";
export function MenuTrigger(props) {
  const root = useMenuRootContext();
  const fallbackId = useBaseUiId();
  const resolvedId = () => typeof props.id === "string" ? props.id : fallbackId;
  const disabled = () => Boolean(props.disabled) || root.disabled();
  const nativeButton = () => props.nativeButton ?? true;
  const {
    props: buttonProps,
    ref: buttonRef
  } = useButton({
    disabled,
    focusableWhenDisabled: () => false,
    native: nativeButton
  });

  // Determine which store to register into — handle's if supplied, else
  // the root's. Handle takes precedence so consumers opt into a shared
  // registry by passing the same handle on trigger + root.
  const store = () => props.handle?.store ?? root.store;

  // Trigger DOM element ref — used by hover + focus-guard hooks.
  const triggerElementRef = {
    current: null
  };
  const [triggerElement, setTriggerElement] = createSignal(null, {
    ownedWrite: true
  });

  // Active-trigger flag — `true` when this trigger is the one that opened
  // the menu. Drives `data-open` + focus-guard render.
  const isActive = createMemo(() => {
    const id = resolvedId();
    if (id === undefined) return true;
    return root.activeTriggerId() === id;
  });
  const isOpenedByThisTrigger = createMemo(() => root.open() && isActive());

  // Register in the trigger map on mount; unregister on cleanup.
  let registeredId = null;
  let registeredElement = null;
  const setTriggerRef = el => untrack(() => {
    const id = resolvedId();
    const s = store();
    triggerElementRef.current = el;
    setTriggerElement(el);
    if (registeredId !== null && registeredElement !== null) {
      const current = s.context.triggerElements.getById(registeredId);
      if (current === registeredElement) {
        s.context.triggerElements.delete(registeredId);
      }
      registeredId = null;
      registeredElement = null;
    }
    if (el && id !== undefined) {
      s.context.triggerElements.add(id, el);
      registeredId = id;
      registeredElement = el;
    }
    if (el) {
      // Keep the root's active-trigger slot in sync for single-trigger
      // setups and for positioner anchoring.
      if (id === undefined || isActive()) {
        root.setActiveTriggerElement(el);
      }
      if (id !== undefined && root.activeTriggerId() == null) {
        root.setActiveTriggerId(id);
      }
    }

    // Forward the payload when this trigger is (or becomes) the active one.
    if ("payload" in props && (id === undefined || isActive())) {
      root.setPayload(props.payload);
    }
  });
  onCleanup(() => {
    if (registeredId !== null && registeredElement !== null) {
      const s = store();
      const current = s.context.triggerElements.getById(registeredId);
      if (current === registeredElement) {
        s.context.triggerElements.delete(registeredId);
      }
    }
  });

  // Inside a menubar, once any of its menus is open, hovering another
  // trigger hands off to that trigger's menu (Base UI parity).
  const menubar = useMenubarContext(true);
  const inMenubar = () => menubar != null && root.parentType() === "menubar";
  const menubarHasMenuOpen = () => inMenubar() && (menubar?.hasSubmenuOpen() ?? false);
  const hoverProps = useHoverReferenceInteraction(root.floatingRootContext, {
    enabled: () => (props.openOnHover ?? menubarHasMenuOpen()) && !disabled() && root.parentType() !== "context-menu" && (!inMenubar() || menubarHasMenuOpen() && !isOpenedByThisTrigger()),
    mouseOnly: true,
    move: false,
    handleClose: safePolygon(),
    delay: () => ({
      open: props.delay ?? (inMenubar() ? 0 : 100),
      close: props.closeDelay ?? 0
    }),
    triggerElementRef,
    triggerElement
  });

  // Click hook — latched enabled (papercut #2). Disable-reactivity is
  // covered by the fact that the button itself refuses clicks when
  // `disabled()` returns true via `useButton`.
  const click = useClick(root.floatingRootContext, {
    enabled: true,
    event: "mousedown",
    toggle: true,
    // In a menubar, a click on a trigger whose menu opened on hover closes
    // it (Base UI parity); elsewhere a hover-opened menu sticks.
    stickIfOpen: !untrack(inMenubar)
  });
  const localInteractions = useInteractions([hoverProps ? {
    reference: hoverProps
  } : undefined, click]);
  const state = createMemo(() => ({
    open: isOpenedByThisTrigger(),
    disabled: disabled()
  }));

  // onClick capture — write the active-trigger id + payload when this
  // trigger originates the open. `useClick` toggles open via its own
  // merged handler; we run alongside to capture the identity.
  const markActive = () => {
    const id = resolvedId();
    if (id !== undefined) {
      root.setActiveTriggerId(id);
    }
    if ("payload" in props) {
      root.setPayload(props.payload);
    }
    if (triggerElementRef.current) {
      root.setActiveTriggerElement(triggerElementRef.current);
    }
  };
  const handleTriggerClick = event => {
    markActive();
    void event;
  };

  // Focus-guard integration. We build a `TriggerFocusGuardStore`
  // on the fly that satisfies the structural shape the hook expects —
  // the real `MenuStore` in this port doesn't yet carry state selectors,
  // so we project through the root context instead.
  const focusGuardStore = {
    setOpen: (openNext, details) => {
      root.setOpen(openNext, details);
    },
    select: key => {
      if (key === "positionerElement") return root.positionerRef.current;
      return null;
    },
    context: {
      beforeContentFocusGuardRef: root.beforeContentFocusGuardRef,
      triggerFocusTargetRef: root.triggerFocusTargetRef
    }
  };
  const {
    preFocusGuardRef,
    handlePreFocusGuardFocus,
    handleFocusTargetFocus
  } = useTriggerFocusGuards(focusGuardStore, triggerElementRef);
  const setPreFocusGuardRef = el => {
    preFocusGuardRef.current = el;
  };
  const setPostFocusGuardRef = el => {
    root.triggerFocusTargetRef.current = el;
  };
  const internal = {
    onClick: handleTriggerClick,
    onPointerEnter: markActive,
    onFocus: markActive,
    get id() {
      return resolvedId();
    },
    "aria-haspopup": "menu",
    get role() {
      // Menubar-nested triggers announce as `menuitem`; top-level
      // triggers stay on the native `button` role.
      return root.parentType() === "menubar" ? "menuitem" : undefined;
    },
    get "aria-expanded"() {
      return root.open() ? "true" : "false";
    },
    get "aria-controls"() {
      // Seed "" so Solid's spread subscribes. Returns
      // the popup id once the popup mounts.
      if (!root.open()) return "";
      return root.popupRef.current?.id ?? "";
    },
    get "data-popup-open"() {
      return state().open ? "" : undefined;
    },
    get "data-pressed"() {
      return state().open ? "" : undefined;
    },
    get "data-disabled"() {
      return state().disabled ? "" : undefined;
    }
  };
  const userClassStyle = resolveClassStyle(props, () => state());
  const userProps = omit(props, "as", "class", "style", "attrs", "disabled", "nativeButton", "openOnHover", "delay", "closeDelay", "handle", "payload");
  let merged = mergeRootProps(root.interactions.getReferenceProps(), localInteractions.getReferenceProps());
  merged = mergeRootProps(merged, root.openInteractionTypeProps);
  merged = mergeRootProps(merged, buttonProps);
  merged = mergeRootProps(merged, internal);
  merged = mergeRootProps(merged, userClassStyle);
  merged = mergeRootProps(merged, userProps);
  const Tag = dynamic(() => props.as ?? "button");
  const element = <Tag {...merged} ref={composeRefs(buttonRef, setTriggerRef, userRef(props))} />;
  return <>
			{isOpenedByThisTrigger() ? <FocusGuard ref={setPreFocusGuardRef} onFocus={handlePreFocusGuardFocus} /> : null}
			{element}
			{isOpenedByThisTrigger() ? <FocusGuard ref={setPostFocusGuardRef} onFocus={handleFocusTargetFocus} /> : null}
		</>;
}
//# sourceMappingURL=menu-trigger.jsx.map
