UNPKG

@opensig/opendesign

Version:

<p align="center"><img src="../docs/public/opendesign-logo-light.png"/></p> <h1 align="center">opendesign</h1> <p align="center">一个 Vue 3 组件库</p> <p align="center"><b>皮肤可定制,使用 TypeScript</b></p>

328 lines (327 loc) 11.2 kB
"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;