"use strict";
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
const vue = require("vue");
const comp = require("../../ui/src/comp.js");
const XEUtils = require("xe-utils");
require("../../ui/index.js");
const utils = require("../../ui/src/utils.js");
const dom = require("../../ui/src/dom.js");
const vn = require("../../ui/src/vn.js");
const button = require("../../button/src/button.js");
const index = require("../../loading/index.js");
const config = require("../../../../@vxe-ui/core/es/src/config.js");
const useFns = require("../../../../@vxe-ui/core/es/src/useFns.js");
const event = require("../../../../@vxe-ui/core/es/src/event.js");
const index_esm = require("../../../../@vxe-ui/core/es/index.esm.js");
const i18n = require("../../../../@vxe-ui/core/es/src/i18n.js");
const icon = require("../../../../@vxe-ui/core/es/src/icon.js");
const allActiveDrawers = [];
const VxeDrawerComponent = comp.defineVxeComponent({
  name: "VxeDrawer",
  props: {
    modelValue: Boolean,
    id: String,
    title: String,
    loading: {
      type: Boolean,
      default: null
    },
    className: String,
    position: {
      type: [String, Object],
      default: () => config.getConfig().drawer.position
    },
    lockView: {
      type: Boolean,
      default: () => config.getConfig().drawer.lockView
    },
    lockScroll: Boolean,
    mask: {
      type: Boolean,
      default: () => config.getConfig().drawer.mask
    },
    maskClosable: {
      type: Boolean,
      default: () => config.getConfig().drawer.maskClosable
    },
    escClosable: {
      type: Boolean,
      default: () => config.getConfig().drawer.escClosable
    },
    cancelClosable: {
      type: Boolean,
      default: () => config.getConfig().drawer.cancelClosable
    },
    confirmClosable: {
      type: Boolean,
      default: () => config.getConfig().drawer.confirmClosable
    },
    showHeader: {
      type: Boolean,
      default: () => config.getConfig().drawer.showHeader
    },
    showFooter: {
      type: Boolean,
      default: () => config.getConfig().drawer.showFooter
    },
    showClose: {
      type: Boolean,
      default: () => config.getConfig().drawer.showClose
    },
    content: [Number, String],
    showCancelButton: {
      type: Boolean,
      default: null
    },
    cancelButtonText: {
      type: String,
      default: () => config.getConfig().drawer.cancelButtonText
    },
    showConfirmButton: {
      type: Boolean,
      default: () => config.getConfig().drawer.showConfirmButton
    },
    confirmButtonText: {
      type: String,
      default: () => config.getConfig().drawer.confirmButtonText
    },
    destroyOnClose: {
      type: Boolean,
      default: () => config.getConfig().drawer.destroyOnClose
    },
    showTitleOverflow: {
      type: Boolean,
      default: () => config.getConfig().drawer.showTitleOverflow
    },
    width: [Number, String],
    height: [Number, String],
    resize: {
      type: Boolean,
      default: () => config.getConfig().drawer.resize
    },
    zIndex: Number,
    transfer: {
      type: Boolean,
      default: () => config.getConfig().drawer.transfer
    },
    padding: {
      type: Boolean,
      default: () => config.getConfig().drawer.padding
    },
    size: {
      type: String,
      default: () => config.getConfig().drawer.size || config.getConfig().size
    },
    beforeHideMethod: {
      type: Function,
      default: () => config.getConfig().drawer.beforeHideMethod
    },
    slots: Object
  },
  emits: [
    "update:modelValue",
    "show",
    "hide",
    "before-hide",
    "close",
    "confirm",
    "cancel",
    "resize"
  ],
  setup(props, context) {
    const { slots, emit } = context;
    const xID = XEUtils.uniqueId();
    const $xeModal = vue.inject("$xeModal", null);
    const $xeParentDrawer = vue.inject("$xeDrawer", null);
    const $xeTable = vue.inject("$xeTable", null);
    const $xeForm = vue.inject("$xeForm", null);
    const { computeSize } = useFns.useSize(props);
    const refElem = vue.ref();
    const refDrawerBox = vue.ref();
    const refConfirmBtn = vue.ref();
    const refCancelBtn = vue.ref();
    const reactData = vue.reactive({
      initialized: false,
      visible: false,
      contentVisible: false,
      drawerZIndex: 0,
      resizeFlag: 1
    });
    const refMaps = {
      refElem
    };
    const computeBtnTransfer = vue.computed(() => {
      const { transfer } = props;
      if (transfer === null) {
        const globalTransfer = config.getConfig().modal.transfer;
        if (XEUtils.isBoolean(globalTransfer)) {
          return globalTransfer;
        }
        if ($xeTable || $xeModal || $xeParentDrawer || $xeForm) {
          return true;
        }
      }
      return transfer;
    });
    const computeDragType = vue.computed(() => {
      switch (props.position) {
        case "top":
          return "sb";
        case "bottom":
          return "st";
        case "left":
          return "wr";
      }
      return "wl";
    });
    const computeMaps = {};
    const $xeDrawer = {
      xID,
      props,
      context,
      reactData,
      getRefMaps: () => refMaps,
      getComputeMaps: () => computeMaps
    };
    const getBox = () => {
      const boxElem = refDrawerBox.value;
      return boxElem;
    };
    const recalculate = () => {
      const { width, height } = props;
      const boxElem = getBox();
      if (boxElem) {
        boxElem.style.width = dom.toCssUnit(width);
        boxElem.style.height = dom.toCssUnit(height);
      }
      return vue.nextTick();
    };
    const updateZindex = () => {
      const { zIndex } = props;
      const { drawerZIndex } = reactData;
      if (zIndex) {
        reactData.drawerZIndex = zIndex;
      } else if (drawerZIndex < utils.getLastZIndex()) {
        reactData.drawerZIndex = utils.nextZIndex();
      }
    };
    const removeActiveQueue = () => {
      if (allActiveDrawers.indexOf($xeDrawer) > -1) {
        XEUtils.remove(allActiveDrawers, (item) => item === $xeDrawer);
      }
    };
    const closeDrawer = (type) => {
      const { beforeHideMethod } = props;
      const { visible } = reactData;
      const params = { type };
      if (visible) {
        Promise.resolve(beforeHideMethod ? beforeHideMethod(params) : null).then((rest) => {
          if (!XEUtils.isError(rest)) {
            reactData.contentVisible = false;
            removeActiveQueue();
            dispatchEvent("before-hide", params, null);
            setTimeout(() => {
              reactData.visible = false;
              emit("update:modelValue", false);
              dispatchEvent("hide", params, null);
            }, 200);
          }
        }).catch((e) => e);
      }
      return vue.nextTick();
    };
    const closeEvent = (evnt) => {
      const type = "close";
      dispatchEvent(type, { type }, evnt);
      closeDrawer(type);
    };
    const confirmEvent = (evnt) => {
      const { confirmClosable } = props;
      const type = "confirm";
      dispatchEvent(type, { type }, evnt);
      if (confirmClosable) {
        closeDrawer(type);
      }
    };
    const cancelEvent = (evnt) => {
      const { cancelClosable } = props;
      const type = "cancel";
      dispatchEvent(type, { type }, evnt);
      if (cancelClosable) {
        closeDrawer(type);
      }
    };
    const openDrawer = () => {
      const { showFooter } = props;
      const { initialized, visible } = reactData;
      if (!initialized) {
        reactData.initialized = true;
      }
      if (!visible) {
        reactData.visible = true;
        reactData.contentVisible = false;
        updateZindex();
        allActiveDrawers.push($xeDrawer);
        setTimeout(() => {
          recalculate();
          reactData.contentVisible = true;
          vue.nextTick(() => {
            if (showFooter) {
              const confirmBtn = refConfirmBtn.value;
              const cancelBtn = refCancelBtn.value;
              const operBtn = confirmBtn || cancelBtn;
              if (operBtn) {
                operBtn.focus();
              }
            }
            const type = "";
            const params = { type };
            emit("update:modelValue", true);
            dispatchEvent("show", params, null);
          });
        }, 10);
      }
      return vue.nextTick();
    };
    const dispatchEvent = (type, params, evnt) => {
      emit(type, event.createEvent(evnt, { $drawer: $xeDrawer }, params));
    };
    const drawerMethods = {
      dispatchEvent,
      open: openDrawer,
      close() {
        return closeDrawer("close");
      },
      getBox
    };
    const selfClickEvent = (evnt) => {
      const el = refElem.value;
      if (props.maskClosable && evnt.target === el) {
        const type = "mask";
        closeDrawer(type);
      }
    };
    const handleGlobalKeydownEvent = (evnt) => {
      const isEsc = event.globalEvents.hasKey(evnt, event.GLOBAL_EVENT_KEYS.ESCAPE);
      if (isEsc) {
        const lastDrawer = XEUtils.max(allActiveDrawers, (item) => item.reactData.drawerZIndex);
        if (lastDrawer) {
          setTimeout(() => {
            if (lastDrawer === $xeDrawer && lastDrawer.props.escClosable) {
              const type = "exit";
              dispatchEvent("close", { type }, evnt);
              closeDrawer(type);
            }
          }, 10);
        }
      }
    };
    const boxMousedownEvent = () => {
      const { drawerZIndex } = reactData;
      if (allActiveDrawers.some((comp2) => comp2.reactData.visible && comp2.reactData.drawerZIndex > drawerZIndex)) {
        updateZindex();
      }
    };
    const dragEvent = (evnt) => {
      evnt.preventDefault();
      const { visibleHeight, visibleWidth } = dom.getDomNode();
      const marginSize = 0;
      const targetElem = evnt.target;
      const type = targetElem.getAttribute("type");
      const minWidth = 0;
      const minHeight = 0;
      const maxWidth = visibleWidth;
      const maxHeight = visibleHeight;
      const boxElem = getBox();
      const clientWidth = boxElem.clientWidth;
      const clientHeight = boxElem.clientHeight;
      const disX = evnt.clientX;
      const disY = evnt.clientY;
      const offsetTop = boxElem.offsetTop;
      const offsetLeft = boxElem.offsetLeft;
      const params = { type: "resize" };
      document.onmousemove = (evnt2) => {
        evnt2.preventDefault();
        let dragLeft;
        let dragTop;
        let width;
        let height;
        switch (type) {
          case "wl":
            dragLeft = disX - evnt2.clientX;
            width = dragLeft + clientWidth;
            if (offsetLeft - dragLeft > marginSize) {
              if (width > minWidth) {
                boxElem.style.width = `${width < maxWidth ? width : maxWidth}px`;
              }
            }
            break;
          case "st":
            dragTop = disY - evnt2.clientY;
            height = clientHeight + dragTop;
            if (offsetTop - dragTop > marginSize) {
              if (height > minHeight) {
                boxElem.style.height = `${height < maxHeight ? height : maxHeight}px`;
              }
            }
            break;
          case "wr":
            dragLeft = evnt2.clientX - disX;
            width = dragLeft + clientWidth;
            if (offsetLeft + width + marginSize < visibleWidth) {
              if (width > minWidth) {
                boxElem.style.width = `${width < maxWidth ? width : maxWidth}px`;
              }
            }
            break;
          case "sb":
            dragTop = evnt2.clientY - disY;
            height = dragTop + clientHeight;
            if (offsetTop + height + marginSize < visibleHeight) {
              if (height > minHeight) {
                boxElem.style.height = `${height < maxHeight ? height : maxHeight}px`;
              }
            }
            break;
        }
        boxElem.className = boxElem.className.replace(/\s?is--drag/, "") + " is--drag";
        dispatchEvent("resize", params, evnt2);
        reactData.resizeFlag++;
      };
      document.onmouseup = () => {
        document.onmousemove = null;
        document.onmouseup = null;
        reactData.resizeFlag++;
        setTimeout(() => {
          boxElem.className = boxElem.className.replace(/\s?is--drag/, "");
        }, 50);
      };
    };
    const formDesignPrivateMethods = {};
    Object.assign($xeDrawer, drawerMethods, formDesignPrivateMethods);
    const renderTitles = () => {
      const { slots: propSlots = {}, showClose, title } = props;
      const titleSlot = slots.title || propSlots.title;
      const cornerSlot = slots.corner || propSlots.corner;
      return [
        vue.h("div", {
          class: "vxe-drawer--header-title"
        }, titleSlot ? vn.getSlotVNs(titleSlot({ $drawer: $xeDrawer })) : title ? utils.getFuncText(title) : i18n.getI18n("vxe.alert.title")),
        vue.h("div", {
          class: "vxe-drawer--header-right"
        }, [
          cornerSlot ? vue.h("div", {
            class: "vxe-drawer--corner-wrapper"
          }, vn.getSlotVNs(cornerSlot({ $drawer: $xeDrawer }))) : index_esm.renderEmptyElement(),
          showClose ? vue.h("div", {
            class: ["vxe-drawer--close-btn", "trigger--btn"],
            title: i18n.getI18n("vxe.drawer.close"),
            onClick: closeEvent
          }, [
            vue.h("i", {
              class: icon.getIcon().DRAWER_CLOSE
            })
          ]) : index_esm.renderEmptyElement()
        ])
      ];
    };
    const renderHeader = () => {
      const { slots: propSlots = {}, showTitleOverflow } = props;
      const headerSlot = slots.header || propSlots.header;
      if (props.showHeader) {
        return vue.h("div", {
          class: ["vxe-drawer--header", {
            "is--ellipsis": showTitleOverflow
          }]
        }, headerSlot ? vn.getSlotVNs(headerSlot({ $drawer: $xeDrawer })) : renderTitles());
      }
      return index_esm.renderEmptyElement();
    };
    const renderBody = () => {
      const { slots: propSlots = {}, content } = props;
      const defaultSlot = slots.default || propSlots.default;
      const leftSlot = slots.left || propSlots.left;
      const rightSlot = slots.right || propSlots.right;
      return vue.h("div", {
        class: "vxe-drawer--body"
      }, [
        leftSlot ? vue.h("div", {
          class: "vxe-drawer--body-left"
        }, vn.getSlotVNs(leftSlot({ $drawer: $xeDrawer }))) : index_esm.renderEmptyElement(),
        vue.h("div", {
          class: "vxe-drawer--body-default"
        }, [
          vue.h("div", {
            class: "vxe-drawer--content"
          }, defaultSlot ? vn.getSlotVNs(defaultSlot({ $drawer: $xeDrawer })) : utils.getFuncText(content))
        ]),
        rightSlot ? vue.h("div", {
          class: "vxe-drawer--body-right"
        }, vn.getSlotVNs(rightSlot({ $drawer: $xeDrawer }))) : index_esm.renderEmptyElement(),
        vue.h(index.VxeLoading, {
          class: "vxe-drawer--loading",
          modelValue: props.loading
        })
      ]);
    };
    const renderDefaultFooter = () => {
      const { slots: propSlots = {}, showCancelButton, showConfirmButton, loading } = props;
      const lfSlot = slots.leftfoot || propSlots.leftfoot;
      const rfSlot = slots.rightfoot || propSlots.rightfoot;
      const btnVNs = [];
      if (showCancelButton) {
        btnVNs.push(vue.h(button.default, {
          key: 1,
          ref: refCancelBtn,
          content: props.cancelButtonText || i18n.getI18n("vxe.button.cancel"),
          onClick: cancelEvent
        }));
      }
      if (showConfirmButton) {
        btnVNs.push(vue.h(button.default, {
          key: 2,
          ref: refConfirmBtn,
          loading,
          status: "primary",
          content: props.confirmButtonText || i18n.getI18n("vxe.button.confirm"),
          onClick: confirmEvent
        }));
      }
      return vue.h("div", {
        class: "vxe-drawer--footer-wrapper"
      }, [
        vue.h("div", {
          class: "vxe-drawer--footer-left"
        }, lfSlot ? vn.getSlotVNs(lfSlot({ $drawer: $xeDrawer })) : []),
        vue.h("div", {
          class: "vxe-drawer--footer-right"
        }, rfSlot ? vn.getSlotVNs(rfSlot({ $drawer: $xeDrawer })) : btnVNs)
      ]);
    };
    const renderFooter = () => {
      const { slots: propSlots = {} } = props;
      const footerSlot = slots.footer || propSlots.footer;
      if (props.showFooter) {
        return vue.h("div", {
          class: "vxe-drawer--footer"
        }, footerSlot ? vn.getSlotVNs(footerSlot({ $drawer: $xeDrawer })) : [renderDefaultFooter()]);
      }
      return index_esm.renderEmptyElement();
    };
    const renderVN = () => {
      const { slots: propSlots = {}, className, position, loading, lockScroll, padding, lockView, mask, resize, destroyOnClose } = props;
      const { initialized, contentVisible, visible } = reactData;
      const asideSlot = slots.aside || propSlots.aside;
      const vSize = computeSize.value;
      const dragType = computeDragType.value;
      const btnTransfer = computeBtnTransfer.value;
      return vue.h(vue.Teleport, {
        to: "body",
        disabled: btnTransfer ? !initialized : true
      }, [
        vue.h("div", {
          ref: refElem,
          class: ["vxe-drawer--wrapper", `pos--${position}`, className || "", {
            [`size--${vSize}`]: vSize,
            "is--padding": padding,
            "lock--scroll": lockScroll,
            "lock--view": lockView,
            "is--resize": resize,
            "is--mask": mask,
            "is--visible": contentVisible,
            "is--active": visible,
            "is--loading": loading
          }],
          style: {
            zIndex: reactData.drawerZIndex
          },
          onClick: selfClickEvent
        }, [
          vue.h("div", {
            ref: refDrawerBox,
            class: "vxe-drawer--box",
            onMousedown: boxMousedownEvent
          }, [
            asideSlot ? vue.h("div", {
              class: "vxe-drawer--aside"
            }, vn.getSlotVNs(asideSlot({ $drawer: $xeDrawer }))) : index_esm.renderEmptyElement(),
            vue.h("div", {
              class: "vxe-drawer--container"
            }, !reactData.initialized || destroyOnClose && !reactData.visible ? [] : [
              renderHeader(),
              renderBody(),
              renderFooter(),
              resize ? vue.h("span", {
                class: "vxe-drawer--resize"
              }, [
                vue.h("span", {
                  class: `${dragType}-resize`,
                  type: dragType,
                  onMousedown: dragEvent
                })
              ]) : index_esm.renderEmptyElement()
            ])
          ])
        ])
      ]);
    };
    vue.watch(() => props.width, recalculate);
    vue.watch(() => props.height, recalculate);
    vue.watch(() => props.modelValue, (value) => {
      if (value) {
        openDrawer();
      } else {
        closeDrawer("model");
      }
    });
    vue.onMounted(() => {
      vue.nextTick(() => {
        if (props.modelValue) {
          openDrawer();
        }
        recalculate();
      });
      if (props.escClosable) {
        event.globalEvents.on($xeDrawer, "keydown", handleGlobalKeydownEvent);
      }
    });
    vue.onUnmounted(() => {
      event.globalEvents.off($xeDrawer, "keydown");
      removeActiveQueue();
    });
    vue.provide("$xeDrawer", $xeDrawer);
    $xeDrawer.renderVN = renderVN;
    return $xeDrawer;
  },
  render() {
    return this.renderVN();
  }
});
exports.allActiveDrawers = allActiveDrawers;
exports.default = VxeDrawerComponent;
