'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

var vue = require('vue');
var domAlign = require('dom-align');
require('../../../utils/index.cjs');
var lodashEs = require('lodash-es');
var util = require('./util.cjs');
var useBuffer = require('./hooks/useBuffer.cjs');
var is = require('../../../utils/is.cjs');
var addEventListener = require('../../../utils/event/addEventListener.cjs');
var vnode = require('../../../utils/vue/vnode.cjs');

const alignProps = {
  align: Object,
  target: [Object, Function],
  onAlign: Function,
  monitorBufferTime: Number,
  monitorWindowResize: Boolean,
  disabled: Boolean
};
function getElement(func) {
  if (typeof func !== "function")
    return null;
  return func();
}
function getPoint(point) {
  if (typeof point !== "object" || !point)
    return null;
  return point;
}
var Align = /* @__PURE__ */ vue.defineComponent({
  compatConfig: {
    MODE: 3
  },
  name: "Align",
  props: alignProps,
  emits: ["align"],
  setup(props, {
    expose,
    slots
  }) {
    const cacheRef = vue.ref({});
    const nodeRef = vue.ref();
    const [forceAlign, cancelForceAlign] = useBuffer.default(() => {
      const {
        disabled: latestDisabled,
        target: latestTarget,
        align: latestAlign,
        onAlign: latestOnAlign
      } = props;
      if (!latestDisabled && latestTarget && nodeRef.value) {
        const source = nodeRef.value;
        let result;
        const element = getElement(latestTarget);
        const point = getPoint(latestTarget);
        cacheRef.value.element = element;
        cacheRef.value.point = point;
        cacheRef.value.align = latestAlign;
        const {
          activeElement
        } = document;
        if (element && is.isVisible(element))
          result = domAlign.alignElement(source, element, latestAlign);
        else if (point)
          result = domAlign.alignPoint(source, point, latestAlign);
        util.restoreFocus(activeElement, source);
        if (latestOnAlign && result)
          latestOnAlign(source, result);
        return true;
      }
      return false;
    }, vue.computed(() => props.monitorBufferTime));
    const resizeMonitor = vue.ref({
      cancel: () => {
      }
    });
    const sourceResizeMonitor = vue.ref({
      cancel: () => {
      }
    });
    const goAlign = () => {
      const target = props.target;
      const element = getElement(target);
      const point = getPoint(target);
      if (nodeRef.value !== sourceResizeMonitor.value.element) {
        sourceResizeMonitor.value.cancel();
        sourceResizeMonitor.value.element = nodeRef.value;
        sourceResizeMonitor.value.cancel = util.monitorResize(nodeRef.value, forceAlign);
      }
      if (cacheRef.value.element !== element || !util.isSamePoint(cacheRef.value.point, point) || !lodashEs.isEqual(cacheRef.value.align, props.align)) {
        forceAlign();
        if (resizeMonitor.value.element !== element) {
          resizeMonitor.value.cancel();
          resizeMonitor.value.element = element;
          resizeMonitor.value.cancel = util.monitorResize(element, forceAlign);
        }
      }
    };
    vue.onMounted(() => {
      vue.nextTick(() => {
        goAlign();
      });
    });
    vue.onUpdated(() => {
      vue.nextTick(() => {
        goAlign();
      });
    });
    vue.watch(() => props.disabled, (disabled) => {
      if (!disabled)
        forceAlign();
      else
        cancelForceAlign();
    }, {
      immediate: true,
      flush: "post"
    });
    const winResizeRef = vue.ref(null);
    vue.watch(() => props.monitorWindowResize, (monitorWindowResize) => {
      if (monitorWindowResize) {
        if (!winResizeRef.value)
          winResizeRef.value = addEventListener.addEventListenerWrap(window, "resize", forceAlign);
      } else if (winResizeRef.value) {
        winResizeRef.value.remove();
        winResizeRef.value = null;
      }
    }, {
      flush: "post"
    });
    vue.onUnmounted(() => {
      resizeMonitor.value.cancel();
      sourceResizeMonitor.value.cancel();
      if (winResizeRef.value)
        winResizeRef.value.remove();
      cancelForceAlign();
    });
    expose({
      forceAlign: () => forceAlign(true)
    });
    return () => {
      const child = slots == null ? void 0 : slots.default();
      if (child)
        return vnode.cloneElement(child[0], {
          ref: nodeRef
        }, true, true);
      return null;
    };
  }
});

exports.alignProps = alignProps;
exports.default = Align;
//# sourceMappingURL=Align.cjs.map
