import * as React from "react";
import { getWindow, isElement, isHTMLElement } from "../../../../../@floating-ui/utils/dist/floating-ui.utils.dom.js";
import { isMac, isSafari } from "../../../../utils/esm/detectBrowser.js";
import { useTimeout } from "../../../../utils/esm/useTimeout.js";
import { createChangeEventDetails } from "../../utils/createBaseUIEventDetails.js";
import { createAttribute } from "../utils/createAttribute.js";
import { activeElement, contains, getTarget, isTypeableElement, matchesFocusVisible, getDocument } from "../utils/element.js";
import { triggerFocus, triggerPress, escapeKey } from "../../utils/reason-parts.js";
const isMacSafari = isMac && isSafari;
function useFocus(context, props = {}) {
  const store = "rootStore" in context ? context.rootStore : context;
  const {
    events,
    dataRef
  } = store.context;
  const {
    enabled = true,
    visibleOnly = true
  } = props;
  const blockFocusRef = React.useRef(false);
  const timeout = useTimeout();
  const keyboardModalityRef = React.useRef(true);
  React.useEffect(() => {
    const domReference = store.select("domReferenceElement");
    if (!enabled) {
      return void 0;
    }
    const win = getWindow(domReference);
    function onBlur() {
      if (!store.select("open") && isHTMLElement(domReference) && domReference === activeElement(getDocument(domReference))) {
        blockFocusRef.current = true;
      }
    }
    function onKeyDown() {
      keyboardModalityRef.current = true;
    }
    function onPointerDown() {
      keyboardModalityRef.current = false;
    }
    win.addEventListener("blur", onBlur);
    if (isMacSafari) {
      win.addEventListener("keydown", onKeyDown, true);
      win.addEventListener("pointerdown", onPointerDown, true);
    }
    return () => {
      win.removeEventListener("blur", onBlur);
      if (isMacSafari) {
        win.removeEventListener("keydown", onKeyDown, true);
        win.removeEventListener("pointerdown", onPointerDown, true);
      }
    };
  }, [store, enabled]);
  React.useEffect(() => {
    if (!enabled) {
      return void 0;
    }
    function onOpenChangeLocal(details) {
      if (details.reason === triggerPress || details.reason === escapeKey) {
        blockFocusRef.current = true;
      }
    }
    events.on("openchange", onOpenChangeLocal);
    return () => {
      events.off("openchange", onOpenChangeLocal);
    };
  }, [events, enabled]);
  const reference = React.useMemo(() => ({
    onMouseLeave() {
      blockFocusRef.current = false;
    },
    onFocus(event) {
      if (blockFocusRef.current) {
        return;
      }
      const target = getTarget(event.nativeEvent);
      if (visibleOnly && isElement(target)) {
        if (isMacSafari && !event.relatedTarget) {
          if (!keyboardModalityRef.current && !isTypeableElement(target)) {
            return;
          }
        } else if (!matchesFocusVisible(target)) {
          return;
        }
      }
      store.setOpen(true, createChangeEventDetails(triggerFocus, event.nativeEvent, event.currentTarget));
    },
    onBlur(event) {
      blockFocusRef.current = false;
      const relatedTarget = event.relatedTarget;
      const nativeEvent = event.nativeEvent;
      const movedToFocusGuard = isElement(relatedTarget) && relatedTarget.hasAttribute(createAttribute("focus-guard")) && relatedTarget.getAttribute("data-type") === "outside";
      timeout.start(0, () => {
        const domReference = store.select("domReferenceElement");
        const activeEl = activeElement(domReference ? domReference.ownerDocument : document);
        if (!relatedTarget && activeEl === domReference) {
          return;
        }
        if (contains(dataRef.current.floatingContext?.refs.floating.current, activeEl) || contains(domReference, activeEl) || movedToFocusGuard) {
          return;
        }
        if (store.context.triggerElements.hasElement(event.relatedTarget)) {
          return;
        }
        store.setOpen(false, createChangeEventDetails(triggerFocus, nativeEvent));
      });
    }
  }), [dataRef, store, visibleOnly, timeout]);
  return React.useMemo(() => enabled ? {
    reference,
    trigger: reference
  } : {}, [enabled, reference]);
}
export {
  useFocus
};
//# sourceMappingURL=useFocus.js.map
