"use client";

// src/hooks/focus/useFocusTrap.ts
import { useCallback, useEffect as useEffect2, useId, useRef, useState as useState2 } from "react";

// src/hooks/focus/useIsMounted.ts
import { useEffect, useLayoutEffect, useState } from "react";
var isClient = typeof window !== "undefined" && typeof document !== "undefined";
var useIsomorphicEffect = isClient ? useLayoutEffect : useEffect;
var useIsMounted = () => {
  const [isMounted, setIsMounted] = useState(false);
  useIsomorphicEffect(() => {
    setIsMounted(true);
    return () => {
      setIsMounted(false);
    };
  }, []);
  return isMounted;
};

// src/hooks/focus/useFocusTrap.ts
var createFocusGuard = () => {
  const div = document.createElement("div");
  Object.assign(div.style, {
    opacity: "0",
    outline: "none",
    boxShadow: "none",
    position: "fixed",
    pointerEvents: "none",
    touchAction: "none"
  });
  div.tabIndex = 0;
  div.setAttribute("data-hw-focus-guard", "");
  document.body.appendChild(div);
  return div;
};
function getContainedFocusableElements(element) {
  return element?.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');
}
var FocusTrapService = class {
  constructor() {
    // The last entry is always the active one
    this.listeners = [];
    this.onFocusIn = (event) => {
      const active = this.getActive();
      if (!active || !active.container.current) return;
      const { container } = active;
      if (!container.current.contains(event.target)) {
        this.focusElement();
      }
    };
  }
  getActive() {
    if (this.listeners.length === 0) return void 0;
    return this.listeners[this.listeners.length - 1];
  }
  focusElement() {
    const active = this.getActive();
    if (!active) return;
    const { container, initialFocusElement } = active;
    const containerElement = container.current;
    if (initialFocusElement?.current) {
      initialFocusElement.current.focus();
    } else {
      const elements = getContainedFocusableElements(containerElement);
      if (elements && elements.length > 0) {
        const first = elements.item(0);
        first.focus();
      } else {
        containerElement.focus();
      }
    }
  }
  removeGuards() {
    document.querySelectorAll("[data-hw-focus-guard]").forEach((node) => node.remove());
  }
  addGuards() {
    document.body.insertAdjacentElement("afterbegin", createFocusGuard());
    document.body.insertAdjacentElement("beforeend", createFocusGuard());
  }
  activate() {
    document.addEventListener("focusin", this.onFocusIn);
    this.addGuards();
  }
  deactivate() {
    document.removeEventListener("focusin", this.onFocusIn);
    this.removeGuards();
  }
  register(listener) {
    this.listeners.push(listener);
    if (this.listeners.length === 1) {
      this.activate();
    }
    const active = listener;
    this.listeners.forEach((listener2) => {
      const { focus, pause } = listener2;
      if (listener2 === active) {
        focus();
      } else {
        pause();
      }
    });
  }
  unregister(id) {
    const index = this.listeners.findIndex((trap) => trap.id === id);
    if (index !== -1) {
      const isActive = index === this.listeners.length - 1;
      const listener = this.listeners[index];
      this.listeners = this.listeners.filter((listener2) => listener2.id !== id);
      if (isActive) {
        this.deactivate();
        listener.focusLast();
        const active = this.getActive();
        this.listeners.forEach((listener2) => {
          const { pause, unpause } = listener2;
          if (listener2 === active) {
            unpause();
          } else {
            pause();
          }
        });
        if (this.listeners.length > 0) {
          this.activate();
        }
      }
    } else {
      console.warn(`Unable to unregister id ${id}: not found`);
    }
  }
};
var service = new FocusTrapService();
var useFocusTrap = ({
  container,
  active = true,
  initialFocus,
  focusFirst = true
}) => {
  const lastFocusRef = useRef(null);
  const [paused, setPaused] = useState2(false);
  const isMounted = useIsMounted();
  const id = useId();
  const focusElement = useCallback(() => {
    const containerElement = container.current;
    if (initialFocus?.current) {
      initialFocus.current.focus();
    } else {
      const elements = getContainedFocusableElements(containerElement);
      if (elements && elements.length > 0) {
        const first = elements.item(0);
        first.focus();
      } else {
        containerElement.focus();
      }
    }
  }, [container, initialFocus]);
  useEffect2(() => {
    if (active && isMounted) {
      let pause = function() {
        setPaused(true);
      }, unpause = function() {
        setPaused(false);
        if (!container.current.contains(document.activeElement)) {
          focusElement();
        }
      }, focus = function() {
        focusElement();
        setPaused(false);
      }, focusLast = function() {
        lastFocusRef.current?.focus();
      };
      if (!lastFocusRef.current) {
        lastFocusRef.current = document.activeElement;
      }
      service.register({ id, pause, focus, focusLast, unpause, container, initialFocusElement: initialFocus });
      return () => {
        service.unregister(id);
        lastFocusRef.current = void 0;
      };
    }
  }, [active, container, focusElement, id, initialFocus, isMounted]);
  useEffect2(() => {
    if (active && !paused && isMounted) {
      let onKeyDown = function(event) {
        const key = event.key;
        const elements = getContainedFocusableElements(containerElement);
        const active2 = document.activeElement;
        const index = [...elements].findIndex((value) => value === active2);
        if (index === -1 || event.altKey || event.ctrlKey || event.metaKey) {
          return;
        }
        if (key === "Tab") {
          const next = event.shiftKey ? -1 : 1;
          const nextIndex = (index + next + elements.length) % elements.length;
          const nextElement = elements[nextIndex];
          nextElement.focus();
          event.preventDefault();
        }
      };
      const containerElement = container.current;
      containerElement.addEventListener("keydown", onKeyDown);
      return () => {
        containerElement.removeEventListener("keydown", onKeyDown);
      };
    }
  }, [active, paused, isMounted, container, initialFocus, focusFirst, focusElement]);
};
export {
  useFocusTrap
};
//# sourceMappingURL=useFocusTrap.mjs.map