"use client";
import { usePortal } from './WAGAC6PJ.js';
import { HeadingLevel } from './5M6RIVE2.js';
import { useFocusableContainer } from './ZWYATQFU.js';
import { prependHiddenDismiss } from './6GXEOXGT.js';
import { useHideOnInteractOutside } from './HP6HHD56.js';
import { useNestedDialogs } from './TOU75OXH.js';
import { usePreventBodyScroll } from './BGQ3KQ5M.js';
import { disableTree, disableTreeOutside } from './Z5GCVBAY.js';
import { supportsInert } from './677M2CI3.js';
import { DialogBackdrop } from './JEWPFJH2.js';
import { markTreeOutside, isElementMarked } from './3NDVDEB4.js';
import { createWalkTreeSnapshot } from './AOUGVQZ3.js';
import { useDisclosureContent, isHidden } from './KFH4SEIX.js';
import { useDialogStore } from './BM6PGYQY.js';
import { useDialogProviderContext, DialogScopedContextProvider, DialogHeadingContext, DialogDescriptionContext } from './RS7LB2H4.js';
import { useFocusable } from './PFRGBC2K.js';
import { useStoreState } from './YV4JVR4I.js';
import { createHook, forwardRef as forwardRef2, createElement } from './LMDWO4NN.js';
import { usePortalRef, useId, useWrapElement, useSafeLayoutEffect, useEvent, useBooleanEvent, useMergeRefs } from './ABQUS43J.js';
import { __objRest, __spreadProps, __spreadValues } from './3YLGPPWQ.js';
import { getActiveElement, contains, isButton, getWindow, getDocument } from '../../../../../../@ariakit_core@0.4.15/node_modules/@ariakit/core/esm/__chunks/DTR5TSDJ.js';
import { addGlobalEventListener, queueBeforeEvent } from '../../../../../../@ariakit_core@0.4.15/node_modules/@ariakit/core/esm/utils/events.js';
import { getFirstTabbableIn, isFocusable, focusIfNeeded } from '../../../../../../@ariakit_core@0.4.15/node_modules/@ariakit/core/esm/utils/focus.js';
import { chain } from '../../../../../../@ariakit_core@0.4.15/node_modules/@ariakit/core/esm/__chunks/PBFD2E7P.js';
import { isSafari } from '../../../../../../@ariakit_core@0.4.15/node_modules/@ariakit/core/esm/__chunks/QAGXQEUG.js';
import { useRef, useEffect, useState, useCallback } from 'react';
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';

var TagName = "div";
var isSafariBrowser = isSafari();
function isAlreadyFocusingAnotherElement(dialog) {
  const activeElement = getActiveElement();
  if (!activeElement) return false;
  if (dialog && contains(dialog, activeElement)) return false;
  if (isFocusable(activeElement)) return true;
  return false;
}
function getElementFromProp(prop, focusable = false) {
  if (!prop) return null;
  const element = "current" in prop ? prop.current : prop;
  if (!element) return null;
  if (focusable) return isFocusable(element) ? element : null;
  return element;
}
var useDialog = createHook(function useDialog2(_a) {
  var _b = _a, {
    store: storeProp,
    open: openProp,
    onClose,
    focusable = true,
    modal = true,
    portal = !!modal,
    backdrop = !!modal,
    hideOnEscape = true,
    hideOnInteractOutside = true,
    getPersistentElements,
    preventBodyScroll = !!modal,
    autoFocusOnShow = true,
    autoFocusOnHide = true,
    initialFocus,
    finalFocus,
    unmountOnHide,
    unstable_treeSnapshotKey
  } = _b, props = __objRest(_b, [
    "store",
    "open",
    "onClose",
    "focusable",
    "modal",
    "portal",
    "backdrop",
    "hideOnEscape",
    "hideOnInteractOutside",
    "getPersistentElements",
    "preventBodyScroll",
    "autoFocusOnShow",
    "autoFocusOnHide",
    "initialFocus",
    "finalFocus",
    "unmountOnHide",
    "unstable_treeSnapshotKey"
  ]);
  const context = useDialogProviderContext();
  const ref = useRef(null);
  const store = useDialogStore({
    store: storeProp || context,
    open: openProp,
    setOpen(open2) {
      if (open2) return;
      const dialog = ref.current;
      if (!dialog) return;
      const event = new Event("close", { bubbles: false, cancelable: true });
      if (onClose) {
        dialog.addEventListener("close", onClose, { once: true });
      }
      dialog.dispatchEvent(event);
      if (!event.defaultPrevented) return;
      store.setOpen(true);
    }
  });
  const { portalRef, domReady } = usePortalRef(portal, props.portalRef);
  const preserveTabOrderProp = props.preserveTabOrder;
  const preserveTabOrder = useStoreState(
    store,
    (state) => preserveTabOrderProp && !modal && state.mounted
  );
  const id = useId(props.id);
  const open = useStoreState(store, "open");
  const mounted = useStoreState(store, "mounted");
  const contentElement = useStoreState(store, "contentElement");
  const hidden = isHidden(mounted, props.hidden, props.alwaysVisible);
  usePreventBodyScroll(contentElement, id, preventBodyScroll && !hidden);
  useHideOnInteractOutside(store, hideOnInteractOutside, domReady);
  const { wrapElement, nestedDialogs } = useNestedDialogs(store);
  props = useWrapElement(props, wrapElement, [wrapElement]);
  useSafeLayoutEffect(() => {
    if (!open) return;
    const dialog = ref.current;
    const activeElement = getActiveElement(dialog, true);
    if (!activeElement) return;
    if (activeElement.tagName === "BODY") return;
    if (dialog && contains(dialog, activeElement)) return;
    store.setDisclosureElement(activeElement);
  }, [store, open]);
  if (isSafariBrowser) {
    useEffect(() => {
      if (!mounted) return;
      const { disclosureElement } = store.getState();
      if (!disclosureElement) return;
      if (!isButton(disclosureElement)) return;
      const onMouseDown = () => {
        let receivedFocus = false;
        const onFocus = () => {
          receivedFocus = true;
        };
        const options = { capture: true, once: true };
        disclosureElement.addEventListener("focusin", onFocus, options);
        queueBeforeEvent(disclosureElement, "mouseup", () => {
          disclosureElement.removeEventListener("focusin", onFocus, true);
          if (receivedFocus) return;
          focusIfNeeded(disclosureElement);
        });
      };
      disclosureElement.addEventListener("mousedown", onMouseDown);
      return () => {
        disclosureElement.removeEventListener("mousedown", onMouseDown);
      };
    }, [store, mounted]);
  }
  useEffect(() => {
    if (!mounted) return;
    if (!domReady) return;
    const dialog = ref.current;
    if (!dialog) return;
    const win = getWindow(dialog);
    const viewport = win.visualViewport || win;
    const setViewportHeight = () => {
      var _a2, _b2;
      const height = (_b2 = (_a2 = win.visualViewport) == null ? void 0 : _a2.height) != null ? _b2 : win.innerHeight;
      dialog.style.setProperty("--dialog-viewport-height", `${height}px`);
    };
    setViewportHeight();
    viewport.addEventListener("resize", setViewportHeight);
    return () => {
      viewport.removeEventListener("resize", setViewportHeight);
    };
  }, [mounted, domReady]);
  useEffect(() => {
    if (!modal) return;
    if (!mounted) return;
    if (!domReady) return;
    const dialog = ref.current;
    if (!dialog) return;
    const existingDismiss = dialog.querySelector("[data-dialog-dismiss]");
    if (existingDismiss) return;
    return prependHiddenDismiss(dialog, store.hide);
  }, [store, modal, mounted, domReady]);
  useSafeLayoutEffect(() => {
    if (!supportsInert()) return;
    if (open) return;
    if (!mounted) return;
    if (!domReady) return;
    const dialog = ref.current;
    if (!dialog) return;
    return disableTree(dialog);
  }, [open, mounted, domReady]);
  const canTakeTreeSnapshot = open && domReady;
  useSafeLayoutEffect(() => {
    if (!id) return;
    if (!canTakeTreeSnapshot) return;
    const dialog = ref.current;
    return createWalkTreeSnapshot(id, [dialog]);
  }, [id, canTakeTreeSnapshot, unstable_treeSnapshotKey]);
  const getPersistentElementsProp = useEvent(getPersistentElements);
  useSafeLayoutEffect(() => {
    if (!id) return;
    if (!canTakeTreeSnapshot) return;
    const { disclosureElement } = store.getState();
    const dialog = ref.current;
    const persistentElements = getPersistentElementsProp() || [];
    const allElements = [
      dialog,
      ...persistentElements,
      ...nestedDialogs.map((dialog2) => dialog2.getState().contentElement)
    ];
    if (modal) {
      return chain(
        markTreeOutside(id, allElements),
        disableTreeOutside(id, allElements)
      );
    }
    return markTreeOutside(id, [disclosureElement, ...allElements]);
  }, [
    id,
    store,
    canTakeTreeSnapshot,
    getPersistentElementsProp,
    nestedDialogs,
    modal,
    unstable_treeSnapshotKey
  ]);
  const mayAutoFocusOnShow = !!autoFocusOnShow;
  const autoFocusOnShowProp = useBooleanEvent(autoFocusOnShow);
  const [autoFocusEnabled, setAutoFocusEnabled] = useState(false);
  useEffect(() => {
    if (!open) return;
    if (!mayAutoFocusOnShow) return;
    if (!domReady) return;
    if (!(contentElement == null ? void 0 : contentElement.isConnected)) return;
    const element = getElementFromProp(initialFocus, true) || // If no initial focus is specified, we try to focus the first element
    // with the autofocus attribute. If it's an Ariakit component, the
    // Focusable component will consume the autoFocus prop and add the
    // data-autofocus attribute to the element instead.
    contentElement.querySelector(
      "[data-autofocus=true],[autofocus]"
    ) || // We have to fallback to the first focusable element otherwise portaled
    // dialogs with preserveTabOrder set to true will not receive focus
    // properly because the elements aren't tabbable until the dialog receives
    // focus.
    getFirstTabbableIn(contentElement, true, portal && preserveTabOrder) || // Finally, we fallback to the dialog element itself.
    contentElement;
    const isElementFocusable = isFocusable(element);
    if (!autoFocusOnShowProp(isElementFocusable ? element : null)) return;
    setAutoFocusEnabled(true);
    queueMicrotask(() => {
      element.focus();
      if (!isSafariBrowser) return;
      if (!isElementFocusable) return;
      element.scrollIntoView({ block: "nearest", inline: "nearest" });
    });
  }, [
    open,
    mayAutoFocusOnShow,
    domReady,
    contentElement,
    initialFocus,
    portal,
    preserveTabOrder,
    autoFocusOnShowProp
  ]);
  const mayAutoFocusOnHide = !!autoFocusOnHide;
  const autoFocusOnHideProp = useBooleanEvent(autoFocusOnHide);
  const [hasOpened, setHasOpened] = useState(false);
  useEffect(() => {
    if (!open) return;
    setHasOpened(true);
    return () => setHasOpened(false);
  }, [open]);
  const focusOnHide = useCallback(
    (dialog, retry = true) => {
      const { disclosureElement } = store.getState();
      if (isAlreadyFocusingAnotherElement(dialog)) return;
      let element = getElementFromProp(finalFocus) || disclosureElement;
      if (element == null ? void 0 : element.id) {
        const doc = getDocument(element);
        const selector = `[aria-activedescendant="${element.id}"]`;
        const composite = doc.querySelector(selector);
        if (composite) {
          element = composite;
        }
      }
      if (element && !isFocusable(element)) {
        const maybeParentDialog = element.closest("[data-dialog]");
        if (maybeParentDialog == null ? void 0 : maybeParentDialog.id) {
          const doc = getDocument(maybeParentDialog);
          const selector = `[aria-controls~="${maybeParentDialog.id}"]`;
          const control = doc.querySelector(selector);
          if (control) {
            element = control;
          }
        }
      }
      const isElementFocusable = element && isFocusable(element);
      if (!isElementFocusable && retry) {
        requestAnimationFrame(() => focusOnHide(dialog, false));
        return;
      }
      if (!autoFocusOnHideProp(isElementFocusable ? element : null)) return;
      if (!isElementFocusable) return;
      element == null ? void 0 : element.focus({ preventScroll: true });
    },
    [store, finalFocus, autoFocusOnHideProp]
  );
  const focusedOnHideRef = useRef(false);
  useSafeLayoutEffect(() => {
    if (open) return;
    if (!hasOpened) return;
    if (!mayAutoFocusOnHide) return;
    const dialog = ref.current;
    focusedOnHideRef.current = true;
    focusOnHide(dialog);
  }, [open, hasOpened, domReady, mayAutoFocusOnHide, focusOnHide]);
  useEffect(() => {
    if (!hasOpened) return;
    if (!mayAutoFocusOnHide) return;
    const dialog = ref.current;
    return () => {
      if (focusedOnHideRef.current) {
        focusedOnHideRef.current = false;
        return;
      }
      focusOnHide(dialog);
    };
  }, [hasOpened, mayAutoFocusOnHide, focusOnHide]);
  const hideOnEscapeProp = useBooleanEvent(hideOnEscape);
  useEffect(() => {
    if (!domReady) return;
    if (!mounted) return;
    const onKeyDown = (event) => {
      if (event.key !== "Escape") return;
      if (event.defaultPrevented) return;
      const dialog = ref.current;
      if (!dialog) return;
      if (isElementMarked(dialog)) return;
      const target = event.target;
      if (!target) return;
      const { disclosureElement } = store.getState();
      const isValidTarget = () => {
        if (target.tagName === "BODY") return true;
        if (contains(dialog, target)) return true;
        if (!disclosureElement) return true;
        if (contains(disclosureElement, target)) return true;
        return false;
      };
      if (!isValidTarget()) return;
      if (!hideOnEscapeProp(event)) return;
      store.hide();
    };
    return addGlobalEventListener("keydown", onKeyDown, true);
  }, [store, domReady, mounted, hideOnEscapeProp]);
  props = useWrapElement(
    props,
    (element) => /* @__PURE__ */ jsx(HeadingLevel, { level: modal ? 1 : void 0, children: element }),
    [modal]
  );
  const hiddenProp = props.hidden;
  const alwaysVisible = props.alwaysVisible;
  props = useWrapElement(
    props,
    (element) => {
      if (!backdrop) return element;
      return /* @__PURE__ */ jsxs(Fragment, { children: [
        /* @__PURE__ */ jsx(
          DialogBackdrop,
          {
            store,
            backdrop,
            hidden: hiddenProp,
            alwaysVisible
          }
        ),
        element
      ] });
    },
    [store, backdrop, hiddenProp, alwaysVisible]
  );
  const [headingId, setHeadingId] = useState();
  const [descriptionId, setDescriptionId] = useState();
  props = useWrapElement(
    props,
    (element) => /* @__PURE__ */ jsx(DialogScopedContextProvider, { value: store, children: /* @__PURE__ */ jsx(DialogHeadingContext.Provider, { value: setHeadingId, children: /* @__PURE__ */ jsx(DialogDescriptionContext.Provider, { value: setDescriptionId, children: element }) }) }),
    [store]
  );
  props = __spreadProps(__spreadValues({
    id,
    "data-dialog": "",
    role: "dialog",
    tabIndex: focusable ? -1 : void 0,
    "aria-labelledby": headingId,
    "aria-describedby": descriptionId
  }, props), {
    ref: useMergeRefs(ref, props.ref)
  });
  props = useFocusableContainer(__spreadProps(__spreadValues({}, props), {
    autoFocusOnShow: autoFocusEnabled
  }));
  props = useDisclosureContent(__spreadValues({ store }, props));
  props = useFocusable(__spreadProps(__spreadValues({}, props), { focusable }));
  props = usePortal(__spreadProps(__spreadValues({ portal }, props), { portalRef, preserveTabOrder }));
  return props;
});
function createDialogComponent(Component, useProviderContext = useDialogProviderContext) {
  return forwardRef2(function DialogComponent(props) {
    const context = useProviderContext();
    const store = props.store || context;
    const mounted = useStoreState(
      store,
      (state) => !props.unmountOnHide || (state == null ? void 0 : state.mounted) || !!props.open
    );
    if (!mounted) return null;
    return /* @__PURE__ */ jsx(Component, __spreadValues({}, props));
  });
}
createDialogComponent(
  forwardRef2(function Dialog2(props) {
    const htmlProps = useDialog(props);
    return createElement(TagName, htmlProps);
  }),
  useDialogProviderContext
);

export { createDialogComponent, useDialog };
//# sourceMappingURL=DVTPF4J4.js.map
