import { defineComponent, ref, watch, computed, onMounted, onUnmounted, createBlock, openBlock, Teleport, withDirectives, createCommentVNode, createElementBlock, mergeProps, createVNode, Transition, withCtx, createElementVNode, vShow, normalizeStyle, normalizeClass, renderSlot, unref, nextTick } from "vue";
import { layerProps } from "./types.mjs";
import { useMouse } from "../hooks/use-mouse.mjs";
import { isFunction } from "../_utils/is.mjs";
import { createTopZIndex, removeZIndex } from "../_utils/z-index.mjs";
import { IconClose } from "../_utils/icons.mjs";
import { OIcon } from "../icon/index.mjs";
const __default__ = {
  inheritAttrs: false
};
const _sfc_main = /* @__PURE__ */ defineComponent({
  ...__default__,
  __name: "OLayer",
  props: layerProps,
  emits: ["change", "update:visible", "click:mask", "click:button"],
  setup(__props, { expose: __expose, emit: __emit }) {
    const props = __props;
    const emits = __emit;
    const visible = ref(props.visible);
    const toMount = ref(props.visible);
    const zIndex = ref(visible.value ? createTopZIndex() : 0);
    const isToBody = ref(false);
    const LayerClass = {
      OPEN: "o-layer-open"
    };
    const mainRef = ref(null);
    let mouse = useMouse({
      type: "client"
    });
    const layerRef = ref(null);
    let wrapperEl = null;
    const initWrapperEl = () => {
      if (!wrapperEl && layerRef.value) {
        wrapperEl = layerRef.value.offsetParent;
        if (!wrapperEl) {
          wrapperEl = document.body;
          isToBody.value = true;
        } else {
          isToBody.value = wrapperEl === document.body;
        }
      }
      return wrapperEl;
    };
    const handleWrapperScroll = () => {
      nextTick(() => {
        initWrapperEl();
        if (wrapperEl) {
          if (visible.value) {
            wrapperEl.classList.add(LayerClass.OPEN);
          } else {
            wrapperEl.classList.remove(LayerClass.OPEN);
          }
        }
      });
    };
    const mainStyle = ref({});
    const getOriginStyle = () => {
      let ox = "center";
      let oy = "center";
      if (mainRef.value && mouse) {
        const { offsetLeft, offsetTop } = mainRef.value;
        if (isToBody.value) {
          ox = `${mouse.x.value - offsetLeft}px`;
          oy = `${mouse.y.value - offsetTop}px`;
        } else if (wrapperEl) {
          const size = wrapperEl.getBoundingClientRect();
          ox = `${mouse.x.value - offsetLeft - size.x}px`;
          oy = `${mouse.y.value - offsetTop - size.y}px`;
        }
      }
      return `${ox} ${oy}`;
    };
    const updateOrigin = (_el) => {
      if (props.transitionOrign === "mouse") {
        initWrapperEl();
        mainStyle.value.transformOrigin = getOriginStyle();
      }
    };
    const beforeToggle = async (show) => {
      let goon = true;
      if (show) {
        if (isFunction(props.beforeShow)) {
          goon = await props.beforeShow();
        }
      } else {
        if (isFunction(props.beforeHide)) {
          goon = await props.beforeHide();
        }
      }
      return goon !== false;
    };
    const updateZIndex = (show) => {
      if (show) {
        zIndex.value = createTopZIndex();
      } else {
        removeZIndex(zIndex.value);
      }
    };
    watch(
      () => props.visible,
      async (v) => {
        if (visible.value !== v) {
          const goon = await beforeToggle(v);
          if (!goon) {
            emits("update:visible", visible.value);
            return;
          }
          updateZIndex(v);
          visible.value = v;
          emits("change", v);
          handleWrapperScroll();
        }
      }
    );
    const toggle = async (show) => {
      if (visible.value === show) {
        return;
      }
      let toShow = show === void 0 ? !visible.value : show;
      const goon = await beforeToggle(toShow);
      if (!goon) {
        return;
      }
      updateZIndex(toShow);
      visible.value = toShow;
      emits("update:visible", visible.value);
      emits("change", visible.value);
      handleWrapperScroll();
    };
    const isMounted = computed(() => {
      return !props.unmountOnHide || visible.value || toMount.value;
    });
    const handleTransitionStart = () => {
      toMount.value = true;
    };
    const handleTransitionEnter = () => {
      if (visible.value) {
        updateOrigin(mainRef.value);
      }
    };
    const handleTransitionEnd = () => {
      if (!props.unmountOnHide) {
        toMount.value = false;
      } else if (!visible.value) {
        toMount.value = false;
      }
    };
    const onMaskClick = (e) => {
      if (props.maskClose) {
        toggle(false);
      }
      emits("click:mask", e);
    };
    const onCloseButtonClick = (e) => {
      toggle(false);
      emits("click:button", e);
    };
    onMounted(() => {
      if (visible.value) {
        handleWrapperScroll();
      }
    });
    onUnmounted(() => {
      mouse == null ? void 0 : mouse.destroy();
      wrapperEl == null ? void 0 : wrapperEl.classList.remove(LayerClass.OPEN);
    });
    __expose({
      /** Toggle the OLayer */
      toggle
    });
    return (_ctx, _cache) => {
      return openBlock(), createBlock(Teleport, {
        to: props.wrapper,
        disabled: !props.wrapper
      }, [
        isMounted.value ? withDirectives((openBlock(), createElementBlock(
          "div",
          mergeProps({
            key: 0,
            ref_key: "layerRef",
            ref: layerRef,
            class: ["o-layer", { "o-layer-to-body": isToBody.value }]
          }, _ctx.$attrs, {
            style: {
              "--layer-z-index": zIndex.value
            }
          }),
          [
            props.mask ? (openBlock(), createBlock(Transition, {
              key: 0,
              name: props.maskTransition,
              appear: true,
              persisted: ""
            }, {
              default: withCtx(() => [
                withDirectives(createElementVNode(
                  "div",
                  {
                    class: "o-layer-mask",
                    onClick: onMaskClick
                  },
                  null,
                  512
                  /* NEED_PATCH */
                ), [
                  [vShow, visible.value]
                ])
              ]),
              _: 1
              /* STABLE */
            }, 8, ["name"])) : createCommentVNode("v-if", true),
            createVNode(Transition, {
              appear: true,
              name: props.mainTransition,
              onBeforeEnter: handleTransitionStart,
              onEnter: handleTransitionEnter,
              onAfterEnter: handleTransitionEnd,
              onBeforeLeave: handleTransitionStart,
              onAfterLeave: handleTransitionEnd,
              persisted: ""
            }, {
              default: withCtx(() => [
                withDirectives(createElementVNode(
                  "div",
                  {
                    ref_key: "mainRef",
                    ref: mainRef,
                    class: normalizeClass([props.mainClass, "o-layer-main"]),
                    style: normalizeStyle(mainStyle.value)
                  },
                  [
                    renderSlot(_ctx.$slots, "default")
                  ],
                  6
                  /* CLASS, STYLE */
                ), [
                  [vShow, visible.value]
                ])
              ]),
              _: 3
              /* FORWARDED */
            }, 8, ["name"]),
            props.buttonClose ? (openBlock(), createElementBlock("div", {
              key: 1,
              class: "o-layer-close",
              onClick: onCloseButtonClick
            }, [
              renderSlot(_ctx.$slots, "close", {}, () => [
                createVNode(unref(OIcon), {
                  button: "",
                  icon: unref(IconClose),
                  class: "o-layer-close-icon"
                }, null, 8, ["icon"])
              ])
            ])) : createCommentVNode("v-if", true)
          ],
          16
          /* FULL_PROPS */
        )), [
          [vShow, visible.value || toMount.value]
        ]) : createCommentVNode("v-if", true)
      ], 8, ["to", "disabled"]);
    };
  }
});
export {
  _sfc_main as default
};
