import { defineComponent, shallowRef, onUpdated, getCurrentInstance, computed, onMounted, watch, nextTick, onBeforeUnmount, createVNode } from 'vue';
import '../../hooks/index.mjs';
import PropTypes from '../vue-types/index.mjs';
import wrapperRaf from '../raf.mjs';
import canUseDom from '../canUseDom.mjs';
import Portal$1 from './Portal.mjs';
import { useScrollLocker } from '../../hooks/useScrollLocker.mjs';

let openCount = 0;
const supportDom = canUseDom();
function getOpenCount() {
  return process.env.NODE_ENV === "test" ? openCount : 0;
}
const getParent = (getContainer) => {
  if (!supportDom)
    return null;
  if (getContainer) {
    if (typeof getContainer === "string")
      return document.querySelectorAll(getContainer)[0];
    if (typeof getContainer === "function")
      return getContainer();
    if (typeof getContainer === "object" && getContainer instanceof window.HTMLElement)
      return getContainer;
  }
  return document.body;
};
var Portal = /* @__PURE__ */ defineComponent({
  compatConfig: {
    MODE: 3
  },
  name: "PortalWrapper",
  inheritAttrs: false,
  props: {
    wrapperClassName: String,
    forceRender: {
      type: Boolean,
      default: void 0
    },
    getContainer: PropTypes.any,
    visible: {
      type: Boolean,
      default: void 0
    },
    autoLock: {
      type: Boolean,
      default: void 0
    },
    didUpdate: Function
  },
  setup(props, {
    slots
  }) {
    const container = shallowRef();
    const componentRef = shallowRef();
    const rafId = shallowRef();
    const removeCurrentContainer = () => {
      var _a, _b;
      (_b = (_a = container.value) == null ? void 0 : _a.parentNode) == null ? void 0 : _b.removeChild(container.value);
      container.value = null;
    };
    let parent = null;
    const attachToParent = (force = false) => {
      if (force || container.value && !container.value.parentNode) {
        parent = getParent(props.getContainer);
        if (parent) {
          parent.appendChild(container.value);
          return true;
        }
        return false;
      }
      return true;
    };
    const defaultContainer = document.createElement("div");
    const setWrapperClassName = () => {
      const {
        wrapperClassName
      } = props;
      if (container.value && wrapperClassName && wrapperClassName !== container.value.className)
        container.value.className = wrapperClassName;
    };
    const getContainer = () => {
      if (!supportDom)
        return null;
      if (!container.value) {
        container.value = defaultContainer;
        attachToParent(true);
      }
      setWrapperClassName();
      return container.value;
    };
    onUpdated(() => {
      setWrapperClassName();
      attachToParent();
    });
    const instance = getCurrentInstance();
    useScrollLocker(computed(() => {
      return props.autoLock && props.visible && canUseDom() && (container.value === document.body || container.value === defaultContainer);
    }));
    onMounted(() => {
      let init = false;
      watch([() => props.visible, () => props.getContainer], ([visible, getContainer2], [prevVisible, prevGetContainer]) => {
        if (supportDom) {
          parent = getParent(props.getContainer);
          if (parent === document.body) {
            if (visible && !prevVisible)
              openCount += 1;
            else if (init)
              openCount -= 1;
          }
        }
        if (init) {
          const getContainerIsFunc = typeof getContainer2 === "function" && typeof prevGetContainer === "function";
          if (getContainerIsFunc ? getContainer2.toString() !== prevGetContainer.toString() : getContainer2 !== prevGetContainer)
            removeCurrentContainer();
        }
        init = true;
      }, {
        immediate: true,
        flush: "post"
      });
      nextTick(() => {
        if (!attachToParent()) {
          rafId.value = wrapperRaf(() => {
            instance.update();
          });
        }
      });
    });
    onBeforeUnmount(() => {
      const {
        visible
      } = props;
      if (supportDom && parent === document.body) {
        openCount = visible && openCount ? openCount - 1 : openCount;
      }
      removeCurrentContainer();
      wrapperRaf.cancel(rafId.value);
    });
    return () => {
      const {
        forceRender,
        visible
      } = props;
      let portal = null;
      const childProps = {
        getOpenCount: () => openCount,
        getContainer
      };
      if (forceRender || visible || componentRef.value) {
        portal = createVNode(Portal$1, {
          "getContainer": getContainer,
          "ref": componentRef,
          "didUpdate": props.didUpdate
        }, {
          default: () => {
            var _a;
            return (_a = slots.default) == null ? void 0 : _a.call(slots, childProps);
          }
        });
      }
      return portal;
    };
  }
});

export { Portal as default, getOpenCount };
//# sourceMappingURL=PortalWrapper.mjs.map
