import { ownerDocument } from "./dom/owner-document.jsx";

/**
 * Accessor-or-value. Consumers may pass plain values or Solid accessors for
 * any reactive gate; readers resolve at call time so the returned handlers
 * see the latest state without recreating the primitive.
 */

function read(value) {
  return typeof value === "function" ? value() : value;
}

/**
 * Minimal event shape — both Solid JSX events and raw DOM events satisfy it.
 * `baseUIHandlerPrevented` / `preventBaseUIHandler` are layered on by
 * `mergePropsN` during the event chain (see `merge-props-n.ts`).
 */

/**
 * Port of Base UI React's `useMixedToggleClickHandler`
 * (`packages/react/src/utils/useMixedToggleClickHandler.ts`).
 *
 * Produces a pair of `onMouseDown` / `onClick` handlers that fix the
 * "mousedown opens, click closes" (or "mousedown closes, click opens")
 * race that occurs when a popup trigger is toggled by different events:
 * the mousedown flips the popup state, and the ensuing click — fired by
 * the same user gesture — would otherwise immediately flip it back.
 *
 * The fix is to record, on mousedown, that a subsequent click should be
 * ignored; the one-shot `click` listener installed on the owner document
 * clears the latch at the end of the event loop so unrelated future
 * clicks still work.
 *
 * Solid 2 notes:
 *
 * - Unlike React's `useMemo` gate on `enabled`, the Solid port reads
 *   `enabled` at event time. That keeps the primitive's return value
 *   identity stable (`mergePropsN` doesn't care about identity, but
 *   callers that capture the handlers once don't need to rewire on
 *   toggle) and avoids a stale-closure hazard during a transition.
 * - `mouseDownAction` and `open` are likewise read at event time so the
 *   primitive can be called once during setup rather than inside an
 *   effect.
 * - The returned shape is `PropsLike` so consumers feed it directly into
 *   `mergePropsN`. The right-most handler can call `preventBaseUIHandler()`
 *   to short-circuit chained consumer handlers — matching the React
 *   source, which uses `event.preventBaseUIHandler()` for the same
 *   purpose.
 */
export function useMixedToggleClickHandler(params) {
  // Closure-captured latch. Set on mousedown when the follow-up click would
  // unwind the popup toggle; cleared either by the one-shot document listener
  // (end-of-event-loop cleanup) or by the `onClick` handler itself (so a
  // direct same-gesture click path still preventBaseUIHandler's).
  let ignoreClick = false;
  function onMouseDown(event) {
    if (read(params.enabled) === false) return;
    const action = read(params.mouseDownAction);
    const open = read(params.open);
    // Only engage when the mousedown is actually going to flip the popup.
    // If `mouseDownAction === "open"` and the popup is already open,
    // mousedown is a no-op and the follow-up click is fine; same for the
    // `close` side.
    if (action === "open" && !open || action === "close" && open) {
      ignoreClick = true;
      const target = event.currentTarget;
      // Install a one-shot `click` listener on the owner document so the
      // latch is cleared even if the click bubbles out of our element
      // (e.g. consumer stopPropagation elsewhere in the tree). `once:
      // true` means we don't need to manage removal.
      ownerDocument(target).addEventListener("click", () => {
        ignoreClick = false;
      }, {
        once: true
      });
    }
  }
  function onClick(event) {
    if (read(params.enabled) === false) return;
    if (ignoreClick) {
      ignoreClick = false;
      // Tell downstream merged handlers not to act on this click — the
      // mousedown already toggled the popup, so the click would undo it.
      event.preventBaseUIHandler?.();
    }
  }
  return {
    onClick,
    onMouseDown
  };
}
//# sourceMappingURL=use-mixed-toggle-click-handler.jsx.map
