@imengyu/vue-scroll-rect
Version:
A scroll rect component for Vue3
371 lines (370 loc) • 11.3 kB
JavaScript
var ue = Object.defineProperty;
var fe = (t, s, o) => s in t ? ue(t, s, { enumerable: !0, configurable: !0, writable: !0, value: o }) : t[s] = o;
var C = (t, s, o) => fe(t, typeof s != "symbol" ? s + "" : s, o);
import { defineComponent as ve, ref as d, computed as A, reactive as j, onMounted as he, nextTick as de, onBeforeUnmount as me, createElementBlock as q, openBlock as F, normalizeStyle as B, normalizeClass as G, createElementVNode as W, renderSlot as T, createCommentVNode as D, unref as k } from "vue";
class J {
constructor(s, o) {
C(this, "x", 0);
C(this, "y", 0);
this.x = s || 0, this.y = o || 0;
}
set(s, o) {
this.x = s, this.y = o;
}
substract(s) {
this.x -= s.x, this.y -= s.y;
}
}
function K(t) {
const { onDown: s, onMove: o, onUp: i } = t, a = new J(), e = new J();
let h;
function v(c) {
c.stopPropagation(), e.set(c.x, c.y), e.substract(a), o(a, e, c, h);
}
function m(c) {
i(c, h), a.set(0, 0), document.removeEventListener("mousemove", v), document.removeEventListener("mouseup", m);
}
return (c, g) => s(c, g) ? (h = g, a.set(c.x, c.y), document.addEventListener("mousemove", v), document.addEventListener("mouseup", m), c.stopPropagation(), !0) : !1;
}
function Be(t) {
const { onDown: s, onUp: o } = t;
function i(a) {
o(a), document.removeEventListener("mouseup", i);
}
return (a) => s(a) ? (document.addEventListener("mouseup", i), a.preventDefault(), a.stopPropagation(), !0) : !1;
}
function We(t, s) {
let o = 0;
return {
start() {
o > 0 && clearTimeout(o), o = setTimeout(() => {
o = 0, s();
}, t);
},
stop() {
o > 0 && (clearTimeout(o), o = 0);
}
};
}
function ge(t, s) {
let o = 0;
return {
start() {
o > 0 && clearInterval(o), o = setInterval(() => {
o = 0, s();
}, t);
},
stop() {
o > 0 && (clearInterval(o), o = 0);
}
};
}
const y = [], Q = ge(100, () => {
for (const t of y)
t();
});
function pe(t, s, o, i) {
let a = 0, e = 0;
function h() {
t.value && (s && a !== t.value.offsetWidth && s(t.value.offsetWidth), o && e !== t.value.offsetHeight && o(t.value.offsetHeight), i && (a !== t.value.offsetWidth || e !== t.value.offsetHeight) && i(t.value.offsetWidth, t.value.offsetHeight), a = t.value.offsetWidth, e = t.value.offsetHeight);
}
return {
startResizeChecker() {
Q.start(), y.push(h);
},
stopResizeChecker() {
const v = y.indexOf(h);
v >= 0 && y.splice(v, 1), y.length === 0 && Q.stop();
}
};
}
const Z = 140, we = 70, be = /* @__PURE__ */ ve({
__name: "ScrollRect",
props: {
/**
* Scroll direction
*
* * both : Scroll in both directions
* * vertical : Scroll only in vertical direction
* * horizontal : Scroll only in horizontal direction
* * none : Disable scroll
*
* @default both
*/
scroll: {
type: String,
default: "both"
},
/**
* Show scroll bar always, otherwise show scroll bar when mouse over
* @default false
*/
scrollBarAlwaysShow: {
type: Boolean,
default: !1
},
/**
* Is able to click scroll bar background to set scroll position? (When `scrollBarAlwaysShow` is true)
* @default true
*/
scrollBarBackgroundClickable: {
type: Boolean,
default: !1
},
height: {
type: Number,
default: void 0
},
width: {
type: Number,
default: void 0
},
/**
*
*/
maxHeight: {
type: Number,
default: void 0
},
maxWidth: {
type: Number,
default: void 0
},
/**
* CSS class of inner container
*/
containerClass: {
type: String,
default: ""
},
/**
* Container style
*/
containerStyle: {
type: null
}
},
emits: ["scroll", "resized"],
setup(t, { expose: s, emit: o }) {
const i = t, a = o, e = d(), h = d(), v = d(), m = d(), c = d(), g = d(), w = d(!1), _ = A(() => i.scroll === "horizontal" || i.scroll === "both"), x = A(() => i.scroll === "vertical" || i.scroll === "both"), f = j({
show: !1,
size: 0,
sizeRaw: 0,
pos: 0
}), u = j({
show: !1,
size: 0,
sizeRaw: 0,
pos: 0
});
let z = 0, H = 0, R = 0, Y = 0, b = null;
const ee = { attributes: !0, childList: !0 };
function L() {
if (e.value) {
if (f.show) {
const l = e.value.offsetWidth / e.value.scrollWidth;
f.sizeRaw = l * e.value.offsetWidth, f.size = l * 100, f.pos = e.value.scrollLeft / (e.value.scrollWidth - e.value.offsetWidth) * (100 - f.size), l >= 1 && (f.show = !1);
}
if (u.show) {
const l = e.value.offsetHeight / e.value.scrollHeight;
u.sizeRaw = l * e.value.offsetHeight, u.size = l * 100, u.pos = e.value.scrollTop / (e.value.scrollHeight - e.value.offsetHeight) * (100 - u.size), l >= 1 && (u.show = !1);
}
a("scroll", e.value.scrollLeft, e.value.scrollTop);
}
}
function p(l = !1) {
if (!e.value)
return;
let r = _.value, n = x.value;
const ie = r && (z !== e.value.scrollWidth || R !== e.value.offsetWidth), ce = x && (H !== e.value.scrollHeight || Y !== e.value.offsetHeight);
if (!l && !ie && !ce)
return;
const S = window.getComputedStyle(e.value);
(S.overflow === "hidden" || S.overflowX === "hidden") && (r = !1), (S.overflow === "hidden" || S.overflowY === "hidden") && (n = !1), f.show = r, u.show = n, L(), R = e.value.offsetWidth, Y = e.value.offsetHeight, z = e.value.scrollWidth, H = e.value.scrollHeight, a("resized", z, H);
}
function le(l) {
var r;
i.scroll == "horizontal" && (l.deltaMode == 0 && ((r = e.value) == null || r.scrollTo({
left: e.value.scrollLeft + (l.deltaY > 0 ? Z : -140),
behavior: "smooth"
})), l.preventDefault(), l.stopPropagation());
}
function X(l) {
var r;
l.deltaMode == 0 && ((r = e.value) == null || r.scrollTo({
left: e.value.scrollLeft + (l.deltaY > 0 ? Z : -140),
behavior: "smooth"
}), l.preventDefault(), l.stopPropagation());
}
function P(l) {
var r;
l.deltaMode == 0 && ((r = e.value) == null || r.scrollTo({
top: e.value.scrollTop + (l.deltaY > 0 ? we : -70),
behavior: "smooth"
}), l.preventDefault(), l.stopPropagation());
}
let M = 0, $ = 0, E = 0, V = 0;
const I = K({
onDown(l) {
return !v.value || !c.value ? !1 : (M = l.offsetX, $ = l.x - l.offsetX - c.value.offsetLeft, l.preventDefault(), w.value = !0, !0);
},
onMove(l, r, n) {
e.value && v.value && (O(n.x - M - $), n.preventDefault(), n.stopPropagation());
},
onUp() {
w.value = !1;
}
}), N = K({
onDown(l) {
return !m.value || !g.value ? !1 : (E = l.offsetY, V = l.y - l.offsetY - g.value.offsetTop, l.preventDefault(), w.value = !0, !0);
},
onMove(l, r, n) {
e.value && m.value && (U(n.y - E - V), n.preventDefault(), n.stopPropagation());
},
onUp() {
w.value = !1;
}
});
function te(l) {
e.value && (e.value.scrollLeft = l / 100 * (e.value.scrollWidth - e.value.offsetWidth));
}
function oe(l) {
e.value && (e.value.scrollLeft = l / 100 * (e.value.scrollHeight - e.value.offsetHeight));
}
function O(l) {
e.value && (e.value.scrollLeft = l / (e.value.offsetWidth - f.sizeRaw) * (e.value.scrollWidth - e.value.offsetWidth));
}
function U(l) {
e.value && (e.value.scrollTop = l / (e.value.offsetHeight - u.sizeRaw) * (e.value.scrollHeight - e.value.offsetHeight));
}
function se(l) {
i.scrollBarBackgroundClickable && O(l.offsetX - f.sizeRaw / 2);
}
function re(l) {
i.scrollBarBackgroundClickable && U(l.offsetY - u.sizeRaw / 2);
}
const {
startResizeChecker: ae,
stopResizeChecker: ne
} = pe(
e,
() => p(),
() => p()
);
return he(() => {
de(() => {
setTimeout(() => p(!0), 200), p(!0), ae(), b = new MutationObserver(() => p()), b.observe(e.value, ee);
});
}), me(() => {
ne(), b && (b.disconnect(), b = null);
}), s({
refreshScrollState() {
p(!0);
},
getScrollContainer() {
return e.value;
},
scrollTo(l, r) {
var n;
(n = e.value) == null || n.scrollTo(l, r);
},
scrollToTop() {
var l;
(l = e.value) == null || l.scrollTo(0, 0);
},
scrollToBottom() {
var l;
(l = e.value) == null || l.scrollTo(e.value.scrollWidth, e.value.scrollHeight);
}
}), (l, r) => (F(), q("div", {
ref_key: "scrollrect",
ref: h,
class: G([
"vue-scroll-rect",
t.scrollBarAlwaysShow ? "always-show-scrollbar" : "",
t.scrollBarBackgroundClickable ? "background-clickable" : "",
w.value ? "dragging" : ""
]),
style: B({
width: t.width ? `${t.width}px` : void 0,
height: t.height ? `${t.height}px` : void 0
}),
onWheel: le
}, [
W("div", {
ref_key: "container",
ref: e,
class: G(["scroll-content", t.scroll, t.containerClass]),
style: B({
maxWidth: t.maxWidth ? `${t.maxWidth}px` : void 0,
maxHeight: t.maxHeight ? `${t.maxHeight}px` : void 0,
...t.containerStyle
}),
onScroll: L
}, [
T(l.$slots, "default")
], 38),
f.show ? T(l.$slots, "scrollBarX", {
key: 0,
scrollBarValue: f,
onScroll: te
}, () => [
W("div", {
ref_key: "scrollBarRefX",
ref: v,
class: "scrollbar horizontal",
onClick: se,
onWheel: X
}, [
W("div", {
class: "thumb",
ref_key: "scrollBarThumbRefX",
ref: c,
style: B({ left: `${f.pos}%`, width: `${f.size}%` }),
onMousedown: r[0] || (r[0] = //@ts-ignore
(...n) => k(I) && k(I)(...n)),
onWheel: X
}, null, 36)
], 544)
]) : D("", !0),
u.show ? T(l.$slots, "scrollBarY", {
key: 1,
scrollBarValue: u,
onScroll: oe
}, () => [
u.show ? (F(), q("div", {
key: 0,
ref_key: "scrollBarRefY",
ref: m,
class: "scrollbar vertical",
onClick: re,
onWheel: P
}, [
W("div", {
class: "thumb",
ref_key: "scrollBarThumbRefY",
ref: g,
style: B({ top: `${u.pos}%`, height: `${u.size}%` }),
onMousedown: r[1] || (r[1] = //@ts-ignore
(...n) => k(N) && k(N)(...n)),
onWheel: P
}, null, 36)
], 544)) : D("", !0)
]) : D("", !0)
], 38));
}
}), ke = {
install(t) {
t.component("scroll-rect", be);
}
};
export {
be as ScrollRect,
We as createMiniTimeOut,
ge as createMiniTimer,
Be as createMouseDownAndUpHandler,
K as createMouseDragHandler,
ke as default,
pe as useResizeChecker
};
//# sourceMappingURL=vue-scroll-rect.es.js.map