"use strict";
const vue = require("vue");
const ScrollbarRail_vue_vue_type_script_setup_true_lang = require("./ScrollbarRail.vue.js");
const types = require("./types.js");
const vueUtils = require("../_utils/vue-utils.js");
const useResizeObserver = require("../hooks/use-resize-observer.js");
const useScreen = require("../hooks/use-screen.js");
const _sfc_main = /* @__PURE__ */ vue.defineComponent({
  __name: "OScrollbar",
  props: types.scrollbarProps,
  setup(__props, { expose: __expose }) {
    const ScrollbarClass = {
      container: "o-scrollbar-container"
    };
    const props = __props;
    const { isPhonePad } = useScreen.useScreen();
    let scrollTargetEl = null;
    let scrollListenEl = null;
    const rootRef = vue.ref(null);
    const hasY = vue.ref(false);
    const hasX = vue.ref(false);
    const hThumbRate = vue.ref(0);
    const vThumbRate = vue.ref(0);
    const hOffsetRate = vue.ref(0);
    const vOffsetRate = vue.ref(0);
    const isBody = vue.ref(false);
    const showXBar = vue.ref(false);
    const showYBar = vue.ref(false);
    let lastTop = -1;
    let lastLeft = -1;
    let xTimer = null;
    let yTimer = null;
    let ro = null;
    let lastScrollWidth = -1;
    let lastScrollHeight = -1;
    const updateScrollbar = () => {
      if (!scrollTargetEl) {
        return;
      }
      const { clientWidth, clientHeight, scrollWidth, scrollHeight, scrollTop, scrollLeft } = scrollTargetEl;
      lastScrollWidth = scrollWidth;
      lastScrollHeight = scrollHeight;
      hThumbRate.value = clientWidth / scrollWidth;
      vThumbRate.value = clientHeight / scrollHeight;
      hOffsetRate.value = scrollLeft / scrollWidth;
      vOffsetRate.value = scrollTop / scrollHeight;
      if (!props.disabledX) {
        hasX.value = clientWidth < scrollWidth;
      }
      if (!props.disabledY) {
        hasY.value = clientHeight < scrollHeight;
      }
    };
    const updateScrollbarByScollSize = () => {
      if (!scrollTargetEl) {
        return;
      }
      const { scrollWidth, scrollHeight } = scrollTargetEl;
      if (lastScrollWidth !== scrollWidth || lastScrollHeight !== scrollHeight) {
        updateScrollbar();
      }
    };
    const onScroll = () => {
      if (!scrollTargetEl) {
        return;
      }
      const { scrollLeft, scrollWidth, scrollTop, scrollHeight } = scrollTargetEl;
      if (lastScrollWidth !== scrollWidth || lastScrollHeight !== scrollHeight) {
        updateScrollbar();
      }
      hOffsetRate.value = scrollLeft / scrollWidth;
      vOffsetRate.value = scrollTop / scrollHeight;
      if (lastLeft >= 0) {
        showXBar.value = scrollLeft !== lastLeft;
        if (xTimer) {
          clearTimeout(xTimer);
        }
        xTimer = window.setTimeout(() => {
          showXBar.value = false;
          xTimer = null;
        }, props.duration);
      }
      lastLeft = scrollLeft;
      if (lastTop >= 0) {
        showYBar.value = scrollTop !== lastTop;
        if (yTimer) {
          clearTimeout(yTimer);
          yTimer = null;
        }
        yTimer = window.setTimeout(() => {
          showYBar.value = false;
        }, props.duration);
      }
      lastTop = scrollTop;
    };
    let childToObserve = null;
    const init = () => {
      if (!scrollTargetEl) {
        return;
      }
      scrollTargetEl.classList.add(ScrollbarClass.container);
      ro = useResizeObserver.useResizeObserver();
      ro.observe(scrollTargetEl, updateScrollbar);
      if (scrollTargetEl.children.length === 1 && scrollTargetEl.children[0] instanceof HTMLElement) {
        childToObserve = scrollTargetEl.children[0];
        ro.observe(childToObserve, updateScrollbar);
      }
      updateScrollbar();
      scrollListenEl = isBody.value ? window : scrollTargetEl;
      scrollListenEl.addEventListener("scroll", onScroll, { passive: true });
      handleWrapperHoverEvent();
    };
    let updateTimer;
    let updateIdleTimer;
    const updateScrollbarOnIdle = () => {
      if (window.requestIdleCallback) {
        updateTimer = window.setInterval(() => {
          updateIdleTimer = window.requestIdleCallback(updateScrollbarByScollSize);
        }, 1e3);
      }
    };
    const cancelUpdateScrollbarOnIdle = () => {
      if (updateTimer) {
        clearInterval(updateTimer);
        cancelIdleCallback && cancelIdleCallback(updateIdleTimer);
        updateTimer = 0;
        updateIdleTimer = 0;
      }
    };
    const { target } = vue.toRefs(props);
    vueUtils.resolveHtmlElement(target).then((el) => {
      if (el === document.body) {
        isBody.value = true;
        scrollTargetEl = document.documentElement;
      } else if (el) {
        scrollTargetEl = el;
      }
      if (!scrollTargetEl) {
        return;
      }
      init();
    });
    const isShowScrollbar = vue.ref(props.showType === "always");
    vue.watchEffect(() => {
      isShowScrollbar.value = props.showType === "always";
      if (props.showType === "always") {
        if (props.autoUpdateOnScrollSize) {
          updateScrollbarOnIdle();
        }
      } else {
        cancelUpdateScrollbarOnIdle();
      }
    });
    let wrapperEl = null;
    const onWrapperHoverIn = () => {
      isShowScrollbar.value = true;
    };
    const onWrapperHoverOut = () => {
      isShowScrollbar.value = false;
      if (scrollTargetEl) {
        const { scrollWidth, scrollHeight } = scrollTargetEl;
        if (lastScrollWidth !== scrollWidth || lastScrollHeight !== scrollHeight) {
          updateScrollbar();
        }
      }
    };
    const removeWrapperHoverEvent = () => {
      if (wrapperEl) {
        wrapperEl.removeEventListener("mouseenter", onWrapperHoverIn);
        wrapperEl.removeEventListener("mouseleave", onWrapperHoverOut);
      }
    };
    const handleWrapperHoverEvent = () => {
      vue.watchEffect(() => {
        var _a;
        const isHoverShow = props.showType === "hover" && !isPhonePad.value;
        wrapperEl = (_a = rootRef.value) == null ? void 0 : _a.offsetParent;
        if (!wrapperEl) {
          return;
        }
        if (isHoverShow) {
          wrapperEl == null ? void 0 : wrapperEl.addEventListener("mouseenter", onWrapperHoverIn);
          wrapperEl == null ? void 0 : wrapperEl.addEventListener("mouseleave", onWrapperHoverOut);
        } else {
          removeWrapperHoverEvent();
        }
      });
    };
    vue.onUnmounted(() => {
      if (scrollTargetEl) {
        ro == null ? void 0 : ro.unobserve(scrollTargetEl, updateScrollbar);
        scrollListenEl == null ? void 0 : scrollListenEl.removeEventListener("scroll", onScroll);
      }
      if (childToObserve) {
        ro == null ? void 0 : ro.unobserve(childToObserve, updateScrollbar);
      }
      removeWrapperHoverEvent();
      cancelUpdateScrollbarOnIdle();
      scrollTargetEl == null ? void 0 : scrollTargetEl.classList.remove(ScrollbarClass.container);
    });
    const onHBarScroll = (ratio) => {
      if (scrollTargetEl) {
        const d = ratio * scrollTargetEl.scrollWidth;
        scrollTargetEl.scrollTo({
          left: d
        });
      }
    };
    const onVBarScroll = (ratio) => {
      if (scrollTargetEl) {
        const d = ratio * scrollTargetEl.scrollHeight;
        scrollTargetEl.scrollTo({
          top: d
        });
      }
    };
    const onBarHoverIn = (d) => {
      if (isPhonePad.value) {
        return;
      }
      if (d === "x") {
        showXBar.value = true;
        if (xTimer) {
          clearTimeout(xTimer);
          yTimer = null;
        }
      } else if (d === "y") {
        showYBar.value = true;
        if (yTimer) {
          clearTimeout(yTimer);
          yTimer = null;
        }
      }
    };
    const onBarHoverOut = (d) => {
      if (isPhonePad.value) {
        return;
      }
      if (d === "x") {
        xTimer = window.setTimeout(() => {
          showXBar.value = false;
        }, props.duration);
      } else if (d === "y") {
        yTimer = window.setTimeout(() => {
          showYBar.value = false;
        }, props.duration);
      }
    };
    __expose({
      update: updateScrollbar
    });
    return (_ctx, _cache) => {
      return vue.openBlock(), vue.createElementBlock(
        "div",
        {
          class: vue.normalizeClass(["o-scrollbar", [
            props.barClass,
            `o-scrollbar-${props.size}`,
            {
              "o-scrollbar-auto-show": props.showType === "auto",
              "o-scrollbar-always-show": props.showType === "always",
              "o-scrollbar-hover-show": props.showType === "hover" && !vue.unref(isPhonePad),
              "o-scrollbar-visible": isShowScrollbar.value,
              "o-scrollbar-both": hasX.value && hasY.value,
              "o-scrollbar-visible-x": showXBar.value,
              "o-scrollbar-visible-y": showYBar.value,
              "o-scrollbar-to-body": isBody.value
            }
          ]]),
          ref_key: "rootRef",
          ref: rootRef
        },
        [
          props.showType !== "never" ? (vue.openBlock(), vue.createElementBlock(
            vue.Fragment,
            { key: 0 },
            [
              hasX.value && !props.disabledX ? (vue.openBlock(), vue.createBlock(ScrollbarRail_vue_vue_type_script_setup_true_lang, {
                key: 0,
                size: props.size,
                direction: "x",
                "thumb-rate": hThumbRate.value,
                "offset-rate": hOffsetRate.value,
                onScroll: onHBarScroll,
                onMouseenter: _cache[0] || (_cache[0] = ($event) => onBarHoverIn("x")),
                onMouseleave: _cache[1] || (_cache[1] = ($event) => onBarHoverOut("x"))
              }, {
                thumb: vue.withCtx(() => [
                  vue.renderSlot(_ctx.$slots, "thumb")
                ]),
                track: vue.withCtx(() => [
                  vue.renderSlot(_ctx.$slots, "track")
                ]),
                _: 3
                /* FORWARDED */
              }, 8, ["size", "thumb-rate", "offset-rate"])) : vue.createCommentVNode("v-if", true),
              hasY.value && !props.disabledY ? (vue.openBlock(), vue.createBlock(ScrollbarRail_vue_vue_type_script_setup_true_lang, {
                key: 1,
                direction: "y",
                size: props.size,
                "thumb-rate": vThumbRate.value,
                "offset-rate": vOffsetRate.value,
                onScroll: onVBarScroll,
                onMouseenter: _cache[2] || (_cache[2] = ($event) => onBarHoverIn("y")),
                onMouseleave: _cache[3] || (_cache[3] = ($event) => onBarHoverOut("y"))
              }, {
                thumb: vue.withCtx(() => [
                  vue.renderSlot(_ctx.$slots, "thumb")
                ]),
                track: vue.withCtx(() => [
                  vue.renderSlot(_ctx.$slots, "track")
                ]),
                _: 3
                /* FORWARDED */
              }, 8, ["size", "thumb-rate", "offset-rate"])) : vue.createCommentVNode("v-if", true)
            ],
            64
            /* STABLE_FRAGMENT */
          )) : vue.createCommentVNode("v-if", true)
        ],
        2
        /* CLASS */
      );
    };
  }
});
module.exports = _sfc_main;
