/**
 * ldesign v0.2.14
 * (c) 2022/11/2 16:16 built by swimly
 * @license MIT
 */

import { createPopper } from '@popperjs/core';
import { s as setStyle } from '../../chunks/set-style.js';
import { on, off, once } from '../../utils/dom.js';
import { renderContent, renderLNodeJSX } from '../../utils/render-node.js';
import { getIEVersion } from '../../utils/helper.js';
import { getClassPrefixMixins } from '../config-provider/config-receiver.js';
import mixins from '../../utils/mixins.js';
import popupProps from './props.js';
import Container from './container.js';
import 'vue';
import 'raf';
import 'lodash/isString';
import '../../chunks/index.js';
import '../../chunks/log.js';
import '../../chunks/_commonjsHelpers-2e6815bd.js';
import '../../utils/easing.js';
import 'lodash';
import 'lodash/camelCase';
import 'lodash/mergeWith';
import '../config-provider/context.js';
import '../../chunks/zh_CN.js';
import '../config-provider/type.js';

const classPrefixMixins = getClassPrefixMixins("popup");
const triggers = ["click", "hover", "focus", "context-menu"];
const injectionKey = "__T_POPUP";
function getPopperPlacement(placement) {
  return placement.replace(/-(left|top)$/, "-start").replace(/-(right|bottom)$/, "-end");
}
function attachListeners(elm) {
  const offs = [];
  return {
    add(type, listener) {
      on(elm, type, listener);
      offs.push(() => {
        off(elm, type, listener);
      });
    },
    clean() {
      offs.forEach(handler => handler === null || handler === void 0 ? void 0 : handler());
      offs.length = 0;
    }
  };
}
var LPopup = mixins(classPrefixMixins).extend({
  name: "LPopup",
  provide() {
    return {
      [injectionKey]: this
    };
  },
  inject: {
    popup: {
      from: injectionKey,
      default: void 0
    }
  },
  props: {
    ...popupProps,
    expandAnimation: {
      type: Boolean
    },
    updateScrollTop: {
      type: Function
    }
  },
  data() {
    return {
      popper: null,
      timeout: null,
      hasDocumentEvent: false,
      visibleState: 0,
      mouseInRange: false,
      contentClicked: false
    };
  },
  computed: {
    overlayClasses() {
      return [`${this.componentName}__content`, {
        [`${this.componentName}__content--text`]: this.content === "string",
        [`${this.componentName}__content--arrow`]: this.showArrow,
        [this.commonStatusClassName.disabled]: this.disabled
      }, this.overlayInnerClassName];
    },
    hasTrigger() {
      return triggers.reduce((map, trigger) => ({
        ...map,
        [trigger]: this.trigger.includes(trigger)
      }), {});
    },
    normalizedDelay() {
      const delay = [].concat(this.delay ?? [250, 150]);
      return {
        open: delay[0],
        close: delay[1] ?? delay[0]
      };
    }
  },
  watch: {
    visible(visible) {
      const {
        hasTrigger,
        $el: triggerEl
      } = this;
      if (visible) {
        this.preventClosing(true);
        if (!this.hasDocumentEvent) {
          on(document, "click", this.handleDocumentClick, true);
          this.hasDocumentEvent = true;
        }
        if (triggerEl && hasTrigger.focus) {
          once(triggerEl, "keydown", ev => {
            if (ev.code === "Escape") this.handleClose({
              trigger: "keydown-esc"
            });
          });
        }
        this.$nextTick(() => {
          this.popupMounted();
        });
      } else {
        this.preventClosing(false);
        off(document, "click", this.handleDocumentClick, true);
        this.hasDocumentEvent = false;
        this.mouseInRange = false;
      }
    },
    overlayInnerStyle() {
      this.updateOverlayInnerStyle();
      this.updatePopper();
    },
    placement() {
      var _this$popper;
      (_this$popper = this.popper) === null || _this$popper === void 0 ? void 0 : _this$popper.destroy();
      this.popper = null;
      this.updatePopper();
    },
    contentClicked(clicked) {
      if (this.popup) this.popup.contentClicked = clicked;
    }
  },
  mounted() {
    const trigger = attachListeners(this.$el);
    const updateTrigger = () => {
      trigger.clean();
      const {
        hasTrigger
      } = this;
      if (hasTrigger.hover) {
        trigger.add("mouseenter", () => this.handleOpen({
          trigger: "trigger-element-hover"
        }));
        trigger.add("mouseleave", () => this.handleClose({
          trigger: "trigger-element-hover"
        }));
      } else if (hasTrigger.focus) {
        trigger.add("focusin", () => this.handleOpen({
          trigger: "trigger-element-focus"
        }));
        trigger.add("focusout", () => this.handleClose({
          trigger: "trigger-element-blur"
        }));
      } else if (hasTrigger.click) {
        trigger.add("click", e => {
          this.handleToggle({
            e,
            trigger: "trigger-element-click"
          });
          if (getIEVersion() < 11) this.handleDocumentClick(e);
        });
      } else if (hasTrigger["context-menu"]) {
        trigger.add("contextmenu", e => {
          e.preventDefault();
          e.button === 2 && this.handleToggle({
            trigger: "context-menu"
          });
        });
      }
    };
    updateTrigger();
    this.$watch("trigger", updateTrigger);
  },
  updated() {
    var _this$$refs$container;
    (_this$$refs$container = this.$refs.container) === null || _this$$refs$container === void 0 ? void 0 : _this$$refs$container.updateContent();
  },
  beforeDestroy() {
    var _this$popup;
    if (this.visible) (_this$popup = this.popup) === null || _this$popup === void 0 ? void 0 : _this$popup.preventClosing(false);
    this.destroyPopper();
    off(document, "click", this.handleDocumentClick, true);
    clearTimeout(this.timeout);
  },
  methods: {
    updatePopper() {
      const {
        $el: triggerEl
      } = this;
      const popperEl = this.$refs.popper;
      if (!popperEl || !this.visible) return;
      if (this.popper) {
        this.popper.update();
        return;
      }
      this.popper = createPopper(triggerEl, popperEl, {
        modifiers: getIEVersion() > 9 ? [] : [{
          name: "computeStyles",
          options: {
            gpuAcceleration: false
          }
        }],
        placement: getPopperPlacement(this.placement),
        onFirstUpdate: () => {
          this.$nextTick(this.updatePopper);
        }
      });
    },
    popupMounted() {
      var _this$$refs, _this$updateScrollTop;
      const overlayEl = (_this$$refs = this.$refs) === null || _this$$refs === void 0 ? void 0 : _this$$refs.overlay;
      if (overlayEl) (_this$updateScrollTop = this.updateScrollTop) === null || _this$updateScrollTop === void 0 ? void 0 : _this$updateScrollTop.call(this, overlayEl);
    },
    getOverlayStyle() {
      var _this$$refs2;
      const {
        overlayStyle
      } = this;
      const triggerEl = this.$el;
      const overlayEl = (_this$$refs2 = this.$refs) === null || _this$$refs2 === void 0 ? void 0 : _this$$refs2.overlay;
      if (!triggerEl || !overlayEl) return;
      if (typeof overlayStyle === "function") return overlayStyle(triggerEl, overlayEl);
      if (typeof overlayStyle === "object") return overlayStyle;
    },
    updateOverlayInnerStyle() {
      var _this$$refs3;
      const {
        overlayInnerStyle
      } = this;
      const triggerEl = this.$el;
      const overlayEl = (_this$$refs3 = this.$refs) === null || _this$$refs3 === void 0 ? void 0 : _this$$refs3.overlay;
      if (!triggerEl || !overlayEl) return;
      if (typeof overlayInnerStyle === "function") setStyle(overlayEl, overlayInnerStyle(triggerEl, overlayEl));else if (typeof overlayInnerStyle === "object") setStyle(overlayEl, overlayInnerStyle);
    },
    destroyPopper() {
      var _this$$refs$container2;
      if (this.popper) {
        this.popper.destroy();
        this.popper = null;
      }
      if (this.destroyOnClose) (_this$$refs$container2 = this.$refs.container) === null || _this$$refs$container2 === void 0 ? void 0 : _this$$refs$container2.unmountContent();
    },
    handleToggle(context) {
      this.emitPopVisible(!this.visible, context);
    },
    handleOpen(context) {
      clearTimeout(this.timeout);
      this.timeout = setTimeout(() => {
        this.emitPopVisible(true, context);
      }, this.hasTrigger.click ? 0 : this.normalizedDelay.open);
    },
    handleClose(context) {
      clearTimeout(this.timeout);
      this.timeout = setTimeout(() => {
        this.emitPopVisible(false, context);
      }, this.hasTrigger.click ? 0 : this.normalizedDelay.close);
    },
    handleDocumentClick(ev) {
      if (this.contentClicked) {
        setTimeout(() => {
          this.contentClicked = false;
        });
        return;
      }
      const triggerEl = this.$el;
      if (triggerEl.contains(ev.target)) return;
      this.visibleState = 0;
      this.emitPopVisible(false, {
        trigger: "document"
      });
    },
    emitPopVisible(visible, context) {
      if (this.disabled || visible === this.visible) return;
      if (!visible && this.visibleState > 1) return;
      if (visible && this.mouseInRange) return;
      this.$emit("visible-change", visible, context);
      if (typeof this.onVisibleChange === "function") this.onVisibleChange(visible, context);
    },
    onMouseEnter() {
      this.mouseInRange = true;
      this.handleOpen({});
    },
    onMouseLeave(ev) {
      if (this.visibleState > 1) {
        const rect = this.$refs.popper.getBoundingClientRect();
        if (ev.x > rect.x && ev.x < rect.x + rect.width && ev.y > rect.y && ev.y < rect.y + rect.height) return;
      }
      this.mouseInRange = false;
      this.handleClose({});
      const parent = this.popup;
      if (parent !== null && parent !== void 0 && parent.mouseInRange) parent.onMouseLeave(ev);
    },
    onBeforeEnter() {
      if (this.visible) this.updatePopper();
    },
    onAfterEnter() {
      if (this.visible) this.updatePopper();
    },
    preventClosing(preventing) {
      const parent = this.popup;
      parent === null || parent === void 0 ? void 0 : parent.preventClosing(preventing);
      if (preventing) {
        this.visibleState += 1;
      } else if (this.visibleState) {
        this.visibleState -= 1;
        if (!this.visibleState) {
          this.emitPopVisible(false, {});
          if (parent !== null && parent !== void 0 && parent.hasTrigger.hover && !(parent !== null && parent !== void 0 && parent.mouseInRange)) parent.emitPopVisible(false, {});
        }
      }
    }
  },
  render(h) {
    const {
      visible,
      destroyOnClose,
      hasTrigger,
      onScroll
    } = this;
    const ref = renderContent(this, "default", "triggerElement");
    const content = renderLNodeJSX(this, "content");
    const hidePopup = this.hideEmptyPopup && ["", void 0, null].includes(content);
    const overlay = visible || !destroyOnClose ? h("div", {
      class: [this.componentName, this.overlayClassName],
      ref: "popper",
      style: [hidePopup && {
        visibility: "hidden",
        pointerEvents: "none"
      }, {
        zIndex: this.zIndex
      }, this.getOverlayStyle()],
      directives: destroyOnClose ? void 0 : [{
        name: "show",
        rawName: "v-show",
        value: visible && !hidePopup,
        expression: "visible"
      }],
      on: {
        mousedown: () => {
          this.contentClicked = true;
        },
        ...(hasTrigger.hover && {
          mouseenter: this.onMouseEnter,
          mouseleave: this.onMouseLeave
        })
      }
    }, [h("div", {
      class: this.overlayClasses,
      ref: "overlay",
      on: onScroll ? {
        scroll(e) {
          onScroll({
            e
          });
        }
      } : void 0
    }, [content, this.showArrow && h("div", {
      class: `${this.componentName}__arrow`
    })])]) : null;
    return h(Container, {
      "ref": "container",
      "on": {
        "contentMounted": () => {
          if (visible) {
            this.updatePopper();
            this.updateOverlayInnerStyle();
          }
        },
        "resize": () => {
          if (visible) this.updatePopper();
        }
      },
      "attrs": {
        "parent": this,
        "visible": visible,
        "attach": this.attach
      }
    }, [h("transition", {
      "slot": "content",
      "attrs": {
        "name": this.expandAnimation ? `${this.componentName}--animation-expand` : `${this.componentName}--animation`,
        "appear": true
      },
      "on": {
        "beforeEnter": this.onBeforeEnter,
        "afterEnter": this.onAfterEnter,
        "afterLeave": this.destroyPopper
      }
    }, [overlay]), ref]);
  }
});

export { LPopup as default };
//# sourceMappingURL=popup.js.map
