"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 log = require("../../ui/src/log.js");
const utils = require("../../ui/src/utils.js");
const dom = require("../../ui/src/dom.js");
const index = require("../../button/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 icon = require("../../../../@vxe-ui/core/es/src/icon.js");
function createInternalData() {
  return {
    targetEl: null
  };
}
function createReactData() {
  return {
    showBtn: false,
    backtopZindex: 0
  };
}
const VxeBacktopComponent = comp.defineVxeComponent({
  name: "VxeBacktop",
  props: {
    target: String,
    size: {
      type: String,
      default: () => config.getConfig().backtop.size || config.getConfig().size
    },
    circle: {
      type: Boolean,
      default: () => config.getConfig().backtop.circle
    },
    right: {
      type: [String, Number],
      default: () => config.getConfig().backtop.right
    },
    bottom: {
      type: [String, Number],
      default: () => config.getConfig().backtop.bottom
    },
    status: {
      type: [String, Number],
      default: () => config.getConfig().backtop.status
    },
    icon: {
      type: String,
      default: () => config.getConfig().backtop.icon
    },
    showIcon: {
      type: Boolean,
      default: () => config.getConfig().backtop.showIcon
    },
    content: {
      type: [String, Number],
      default: () => config.getConfig().backtop.content
    },
    showContent: {
      type: Boolean,
      default: () => config.getConfig().backtop.showContent
    },
    showTop: {
      type: Boolean,
      default: () => config.getConfig().backtop.showTop
    },
    showBottom: {
      type: Boolean,
      default: () => config.getConfig().backtop.showBottom
    },
    shadow: {
      type: Boolean,
      default: () => config.getConfig().backtop.shadow
    },
    zIndex: {
      type: [String, Number],
      default: () => config.getConfig().backtop.zIndex
    },
    threshold: {
      type: [String, Number],
      default: () => config.getConfig().backtop.threshold
    },
    position: {
      type: String,
      default: () => config.getConfig().backtop.position
    }
  },
  emits: [
    "click"
  ],
  setup(props, context) {
    const { slots, emit } = context;
    const xID = XEUtils.uniqueId();
    const refElem = vue.ref();
    const { computeSize } = useFns.useSize(props);
    const internalData = createInternalData();
    const reactData = vue.reactive(createReactData());
    const refMaps = {
      refElem
    };
    const computeWrapperStyle = vue.computed(() => {
      const { right, bottom } = props;
      const { backtopZindex } = reactData;
      const stys = {};
      if (right) {
        stys.right = dom.toCssUnit(right);
      }
      if (bottom) {
        stys.bottom = dom.toCssUnit(bottom);
      }
      if (backtopZindex) {
        stys.zIndex = backtopZindex;
      }
      return stys;
    });
    const computeMaps = {};
    const $xeBacktop = {
      xID,
      props,
      context,
      internalData,
      reactData,
      getRefMaps: () => refMaps,
      getComputeMaps: () => computeMaps
    };
    const dispatchEvent = (type, params, evnt) => {
      emit(type, event.createEvent(evnt, { $backtop: $xeBacktop }, params));
    };
    const updateZIndex = () => {
      const { position, zIndex } = props;
      const { backtopZindex } = reactData;
      if (zIndex) {
        reactData.backtopZindex = XEUtils.toNumber(zIndex);
      } else if (position === "fixed") {
        if (backtopZindex < utils.getLastZIndex()) {
          reactData.backtopZindex = utils.nextZIndex();
        }
      }
    };
    const showBacktop = () => {
      updateZIndex();
      reactData.showBtn = true;
    };
    const hideBacktop = () => {
      reactData.showBtn = false;
    };
    const handleScrollEvent = (evnt) => {
      const { threshold } = props;
      const currentEl = evnt.currentTarget;
      const scrollTop = currentEl.scrollTop;
      const showBtn = scrollTop > Math.max(1, XEUtils.toNumber(threshold));
      if (showBtn) {
        showBacktop();
      } else {
        hideBacktop();
      }
    };
    const handleToTop = () => {
      const { targetEl } = internalData;
      if (!targetEl) {
        return;
      }
      const scrollTop = targetEl.scrollTop;
      if (scrollTop > 0) {
        requestAnimationFrame(handleToTop);
        const currScrollTop = scrollTop - Math.max(12, scrollTop / 6);
        targetEl.scrollTop = currScrollTop > 10 ? currScrollTop : 0;
      }
    };
    const removeScrollEvent = () => {
      const { targetEl } = internalData;
      if (targetEl) {
        targetEl.removeEventListener("scroll", handleScrollEvent);
      }
    };
    const addScrollEvent = () => {
      const { targetEl } = internalData;
      if (targetEl) {
        targetEl.addEventListener("scroll", handleScrollEvent, { passive: true });
      }
    };
    const handleTargetElement = () => {
      vue.nextTick(() => {
        const { target } = props;
        if (!target) {
          removeScrollEvent();
          log.errLog("vxe.error.reqProp", ["target"]);
          return;
        }
        if (XEUtils.isString(target)) {
          const tEl = document.querySelector(target);
          if (!tEl) {
            log.errLog("vxe.error.errProp", [`target=${target}`, "body"]);
          }
          const { targetEl } = internalData;
          if (targetEl !== tEl) {
            removeScrollEvent();
            internalData.targetEl = tEl;
            addScrollEvent();
          }
        }
      });
    };
    const clickEvent = (evnt) => {
      handleToTop();
      dispatchEvent("click", {}, evnt);
    };
    const tagMethods = {
      dispatchEvent
    };
    const tagPrivateMethods = {};
    Object.assign($xeBacktop, tagMethods, tagPrivateMethods);
    const renderVN = () => {
      const { circle, position, status, icon: icon$1, showIcon, content, showContent, showTop, showBottom, shadow } = props;
      const { showBtn } = reactData;
      const wrapperStyle = computeWrapperStyle.value;
      const vSize = computeSize.value;
      const defaultSlot = slots.default;
      const topSlot = slots.top;
      const bottomSlot = slots.bottom;
      return vue.h("div", {
        ref: refElem,
        class: ["vxe-backtop", position === "fixed" ? "is--" + position : "is--absolute", {
          [`size--${vSize}`]: vSize,
          "is--visible": showBtn
        }],
        style: wrapperStyle
      }, [
        showTop && topSlot ? vue.h("div", {
          class: "vxe-backtop--top-wrapper"
        }, topSlot({})) : index_esm.renderEmptyElement(),
        vue.h("div", {
          class: "vxe-backtop--content-wrapper",
          onClick: clickEvent
        }, [
          defaultSlot ? defaultSlot({}) : [
            vue.h(index.VxeButton, {
              circle,
              status,
              shadow,
              icon: showIcon ? icon$1 || icon.getIcon().BACKTOP_TOP : "",
              content: showContent ? content : ""
            })
          ]
        ]),
        showBottom && bottomSlot ? vue.h("div", {
          class: "vxe-backtop--bottom-wrapper"
        }, bottomSlot({})) : index_esm.renderEmptyElement()
      ]);
    };
    vue.watch(() => props.position, () => {
      updateZIndex();
    });
    vue.watch(() => props.target, () => {
      handleTargetElement();
    });
    vue.onMounted(() => {
      const { showTop } = props;
      if (showTop) {
        updateZIndex();
      }
      handleTargetElement();
    });
    vue.onBeforeUnmount(() => {
      removeScrollEvent();
      XEUtils.assign(reactData, createReactData());
      XEUtils.assign(internalData, createInternalData());
    });
    $xeBacktop.renderVN = renderVN;
    return $xeBacktop;
  },
  render() {
    return this.renderVN();
  }
});
exports.default = VxeBacktopComponent;
