@imengyu/vue-scroll-rect
Version:
A scroll rect component for Vue3
531 lines (530 loc) • 18.5 kB
JavaScript
var Ge = Object.defineProperty;
var Ne = (a, s, r) => s in a ? Ge(a, s, { enumerable: !0, configurable: !0, writable: !0, value: r }) : a[s] = r;
var Q = (a, s, r) => Ne(a, typeof s != "symbol" ? s + "" : s, r);
import { createElementBlock as D, openBlock as H, createElementVNode as b, defineComponent as je, ref as h, computed as g, reactive as Se, watch as Pe, nextTick as Z, onMounted as qe, onBeforeUnmount as Fe, normalizeStyle as C, normalizeClass as A, renderSlot as W, createCommentVNode as y, toDisplayString as Je, createVNode as Ke, unref as _ } from "vue";
class ye {
constructor(s, r) {
Q(this, "x", 0);
Q(this, "y", 0);
this.x = s || 0, this.y = r || 0;
}
set(s, r) {
this.x = s, this.y = r;
}
substract(s) {
this.x -= s.x, this.y -= s.y;
}
}
function ke(a) {
const { onDown: s, onMove: r, onUp: t } = a, u = new ye(), l = new ye();
let m;
function p(i) {
i.stopPropagation(), l.set(i.x, i.y), l.substract(u), r(u, l, i, m);
}
function S(i) {
t(i, m), u.set(0, 0), document.removeEventListener("mousemove", p), document.removeEventListener("mouseup", S);
}
return (i, P) => s(i, P) ? (m = P, u.set(i.x, i.y), document.addEventListener("mousemove", p), document.addEventListener("mouseup", S), i.stopPropagation(), !0) : !1;
}
function Tl(a) {
const { onDown: s, onUp: r } = a;
function t(u) {
r(u), document.removeEventListener("mouseup", t);
}
return (u) => s(u) ? (document.addEventListener("mouseup", t), u.preventDefault(), u.stopPropagation(), !0) : !1;
}
function ml(a, s) {
let r = 0;
return {
start() {
r > 0 && clearTimeout(r), r = setTimeout(() => {
r = 0, s();
}, a);
},
stop() {
r > 0 && (clearTimeout(r), r = 0);
}
};
}
function Qe(a, s) {
let r = 0;
return {
start() {
r > 0 && clearInterval(r), r = setInterval(() => {
r = 0, s();
}, a);
},
stop() {
r > 0 && (clearInterval(r), r = 0);
}
};
}
function Re(a, s) {
let r = null, t = 0;
return function(...u) {
const l = Date.now(), m = l - t, p = s - m;
p <= 0 ? (t = l, a.apply(this, u)) : (r !== null && window.clearTimeout(r), r = window.setTimeout(() => {
t = Date.now(), r = null, a.apply(this, u);
}, p));
};
}
const z = [], Be = Qe(100, () => {
for (const a of z)
a();
});
function Ze(a, s, r, t) {
let u = 0, l = 0;
function m() {
a.value && (s && u !== a.value.offsetWidth && s(a.value.offsetWidth), r && l !== a.value.offsetHeight && r(a.value.offsetHeight), t && (u !== a.value.offsetWidth || l !== a.value.offsetHeight) && t(a.value.offsetWidth, a.value.offsetHeight), u = a.value.offsetWidth, l = a.value.offsetHeight);
}
return {
startResizeChecker() {
Be.start(), z.push(m);
},
stopResizeChecker() {
const p = z.indexOf(m);
p >= 0 && z.splice(p, 1), z.length === 0 && Be.stop();
}
};
}
const el = (a, s) => {
const r = a.__vccOpts || a;
for (const [t, u] of s)
r[t] = u;
return r;
}, ll = {}, tl = { viewBox: "0 0 1024 1024" };
function ol(a, s) {
return H(), D("svg", tl, s[0] || (s[0] = [
b("path", {
d: "M188.274526 257.534448l0-97.428983 645.061528 0 0 97.428983L188.274526 257.534448zM252.732583 515.366677l255.82655-226.355331 260.329097 226.355331-192.371332 0 0 192.362122 0 161.89625-130.911562 0 0-354.258373L252.732583 515.366677z",
fill: "currentColor"
}, null, -1)
]));
}
const rl = /* @__PURE__ */ el(ll, [["render", ol]]), al = { class: "pull-refresh-track-inner" }, sl = { class: "pull-refresh-default" }, nl = {
key: 0,
class: "pull-refresh-default-spinner",
"aria-hidden": "true"
}, ul = { class: "pull-refresh-default-text" }, il = ["aria-hidden", "tabindex"], cl = 8, fl = 140, vl = 120, hl = /* @__PURE__ */ je({
__name: "ScrollRect",
props: {
scroll: { default: "both" },
scrollBarAlwaysShow: { type: Boolean, default: !1 },
scrollBarBackgroundClickable: { type: Boolean, default: !0 },
containerClass: { default: "" },
containerStyle: {},
width: {},
height: {},
maxWidth: {},
maxHeight: {},
scrollToStartThreshold: { default: 50 },
scrollToEndThreshold: { default: 50 },
enablePullToRefresh: { type: Boolean, default: !1 },
pullToRefreshThreshold: { default: 50 },
pullToRefreshLoading: { type: Boolean, default: !1 },
pullRefreshLoadingHeight: { default: 48 },
pullRefreshMaxDistance: { default: 120 },
enableBackToTop: { type: Boolean, default: !1 },
backToTopThreshold: { default: 120 }
},
emits: ["scroll", "resized", "scrollToStart", "scrollToEnd", "pullToRefreshStart", "pullToRefreshEnd", "update:pullToRefreshLoading"],
setup(a, { expose: s, emit: r }) {
const t = a, u = r, l = h(), m = h(), p = h(), S = h(), i = h(), P = h(), k = h(!1), Le = g(() => t.scroll === "horizontal" || t.scroll === "both"), w = g(() => t.scroll === "vertical" || t.scroll === "both"), d = Se({
show: !1,
size: 0,
sizeRaw: 0,
pos: 0
}), f = Se({
show: !1,
size: 0,
sizeRaw: 0,
pos: 0
});
function M(e) {
return typeof e == "number" ? `${e}px` : /^\d+$/.test(e) ? `${e}px` : e;
}
const O = h(0), U = h(0), Y = g(() => {
if (!t.enableBackToTop)
return !1;
const e = t.backToTopThreshold, o = t.scroll;
return o === "vertical" ? O.value > e : o === "horizontal" ? U.value > e : o === "both" ? O.value > e || U.value > e : !1;
}), c = h(0), E = h(!0), v = h(null), T = h(!1), G = h(0), N = g(() => t.pullToRefreshThreshold), ee = g(() => t.pullRefreshLoadingHeight), j = g(() => t.pullToRefreshLoading ? "loading" : c.value <= 0.5 ? "idle" : c.value >= N.value ? "release" : "pulling"), Ce = g(() => t.pullToRefreshLoading ? ee.value : c.value), We = g(() => {
switch (j.value) {
case "loading":
return "加载中…";
case "release":
return "释放加载";
case "pulling":
return "下拉加载";
default:
return "下拉加载";
}
}), De = g(() => c.value > 0);
function le(e) {
const o = t.pullRefreshMaxDistance, n = Math.min(Math.max(e, 0), o * 2);
return o * (1 - Math.exp(-n / (o * 0.9)));
}
function He(e) {
!t.enablePullToRefresh || !w.value || t.pullToRefreshLoading || !l.value || l.value.scrollTop > 1 || e.pointerType === "mouse" && e.button !== 0 || (v.value = e.pointerId, T.value = !1, G.value = e.clientY, E.value = !1);
}
function R() {
if (v.value === null)
return;
const e = v.value, o = T.value;
if (v.value = null, T.value = !1, c.value = 0, E.value = !0, o && l.value)
try {
l.value.releasePointerCapture(e);
} catch {
}
}
function te(e) {
if (v.value === null || e.pointerId !== v.value || !t.enablePullToRefresh || !w.value || t.pullToRefreshLoading || !l.value)
return;
if (!T.value) {
if (l.value.scrollTop > 0.1) {
R();
return;
}
const n = e.clientY - G.value;
if (n < -8) {
R();
return;
}
if (n < cl)
return;
T.value = !0;
try {
e.currentTarget.setPointerCapture(e.pointerId);
} catch {
T.value = !1, R();
return;
}
c.value = le(n * 0.55), e.preventDefault();
return;
}
if (l.value.scrollTop > 0.1) {
c.value = 0, q();
return;
}
const o = e.clientY - G.value;
if (o <= 0) {
c.value = 0, q();
return;
}
e.preventDefault(), c.value = le(o * 0.55);
}
function oe(e) {
if (!(v.value === null || e.pointerId !== v.value)) {
if (!T.value) {
R();
return;
}
re();
}
}
function q(e, o) {
if (v.value === null)
return;
const n = v.value, $ = T.value;
if (v.value = null, T.value = !1, E.value = !0, c.value = 0, $ && l.value)
try {
l.value.releasePointerCapture(n);
} catch {
}
}
function ze(e) {
v.value === null || e.pointerId !== v.value || (T.value ? re() : R());
}
function re(e) {
const o = T.value, n = c.value;
q(), o && !t.pullToRefreshLoading && n >= N.value && u("pullToRefreshStart"), c.value = 0;
}
let X = !1;
function ae() {
X || !l.value || !t.enablePullToRefresh || !w.value || (l.value.addEventListener("pointermove", te, { passive: !1 }), X = !0);
}
function se() {
!X || !l.value || (l.value.removeEventListener("pointermove", te), X = !1);
}
Pe(
() => t.pullToRefreshLoading,
(e, o) => {
o === !0 && e === !1 && (u("pullToRefreshEnd"), c.value = 0);
}
), Pe(
() => t.enablePullToRefresh && w.value,
(e) => {
e ? Z(() => ae()) : (c.value = 0, v.value = null, T.value = !1, Z(() => se()));
}
);
let F = 0, J = 0, ne = 0, ue = 0, B = null;
const Me = { attributes: !0, childList: !0 };
function ie(e) {
if (l.value) {
if (O.value = l.value.scrollTop, U.value = l.value.scrollLeft, d.show) {
const o = l.value.offsetWidth / l.value.scrollWidth;
d.sizeRaw = o * l.value.offsetWidth, d.size = o * 100, d.pos = l.value.scrollLeft / (l.value.scrollWidth - l.value.offsetWidth) * (100 - d.size), o >= 1 && (d.show = !1);
}
if (f.show) {
const o = l.value.offsetHeight / l.value.scrollHeight;
f.sizeRaw = o * l.value.offsetHeight, f.size = o * 100, f.pos = l.value.scrollTop / (l.value.scrollHeight - l.value.offsetHeight) * (100 - f.size), o >= 1 && (f.show = !1);
}
e === "scroll" && (t.scroll === "vertical" ? (t.scrollToStartThreshold && l.value.scrollTop <= t.scrollToStartThreshold && u("scrollToStart"), t.scrollToEndThreshold && l.value.scrollTop >= l.value.scrollHeight - t.scrollToEndThreshold - l.value.offsetHeight && u("scrollToEnd")) : t.scroll === "horizontal" && (t.scrollToStartThreshold && l.value.scrollLeft <= t.scrollToStartThreshold && u("scrollToStart"), t.scrollToEndThreshold && l.value.scrollLeft >= l.value.scrollWidth - t.scrollToEndThreshold - l.value.offsetWidth && u("scrollToEnd")), u("scroll", l.value.scrollLeft, l.value.scrollTop));
}
}
function L(e, o = !1) {
if (!l.value)
return;
let n = Le.value, $ = w.value;
const Oe = n && (F !== l.value.scrollWidth || ne !== l.value.offsetWidth), Ue = w && (J !== l.value.scrollHeight || ue !== l.value.offsetHeight);
if (!o && !Oe && !Ue)
return;
const V = window.getComputedStyle(l.value);
(V.overflow === "hidden" || V.overflowX === "hidden") && (n = !1), (V.overflow === "hidden" || V.overflowY === "hidden") && ($ = !1), d.show = n, f.show = $, ie(e), ne = l.value.offsetWidth, ue = l.value.offsetHeight, F = l.value.scrollWidth, J = l.value.scrollHeight, u("resized", F, J);
}
function Ye(e) {
ie("scroll");
}
const ce = Re((e) => {
var o;
(o = l.value) == null || o.scrollTo({
left: l.value.scrollLeft + (e ? fl : -140),
behavior: "smooth"
});
}, 120), Ee = Re((e) => {
var o;
(o = l.value) == null || o.scrollTo({
top: l.value.scrollTop + (e ? vl : -120),
behavior: "smooth"
});
}, 20);
function Xe(e) {
t.scroll == "horizontal" && (e.deltaMode == 0 && ce(e.deltaY > 0), e.preventDefault(), e.stopPropagation());
}
function fe(e) {
e.deltaMode == 0 && (ce(e.deltaY > 0), e.preventDefault(), e.stopPropagation());
}
function ve(e) {
e.deltaMode == 0 && (Ee(e.deltaY > 0), e.preventDefault(), e.stopPropagation());
}
let he = 0, de = 0, pe = 0, Te = 0, x = !1, I = !1;
const me = ke({
onDown(e) {
return !p.value || !i.value ? !1 : (he = e.offsetX, de = e.x - e.offsetX - i.value.offsetLeft, e.preventDefault(), e.stopPropagation(), k.value = !0, x = !1, !0);
},
onMove(e, o, n) {
l.value && p.value && (be(n.x - he - de), n.preventDefault(), n.stopPropagation(), x = !0);
},
onUp() {
k.value = !1;
}
}), ge = ke({
onDown(e) {
return !S.value || !P.value ? !1 : (pe = e.offsetY, Te = e.y - e.offsetY - P.value.offsetTop, e.preventDefault(), e.stopPropagation(), k.value = !0, I = !1, !0);
},
onMove(e, o, n) {
l.value && S.value && (we(n.y - pe - Te), n.preventDefault(), n.stopPropagation(), I = !0);
},
onUp() {
k.value = !1;
}
});
function xe(e) {
l.value && (l.value.scrollLeft = e / 100 * (l.value.scrollWidth - l.value.offsetWidth));
}
function Ie(e) {
l.value && (l.value.scrollLeft = e / 100 * (l.value.scrollHeight - l.value.offsetHeight));
}
function be(e) {
l.value && (e = Math.max(0, e), l.value.scrollLeft = e / (l.value.offsetWidth - d.sizeRaw) * (l.value.scrollWidth - l.value.offsetWidth));
}
function we(e) {
l.value && (e = Math.max(0, e), l.value.scrollTop = e / (l.value.offsetHeight - f.sizeRaw) * (l.value.scrollHeight - l.value.offsetHeight));
}
function $e(e) {
if (t.scrollBarBackgroundClickable) {
if (x) {
x = !1;
return;
}
be(e.offsetX - d.sizeRaw / 2);
}
}
function Ve(e) {
if (t.scrollBarBackgroundClickable) {
if (I) {
I = !1;
return;
}
we(e.offsetY - f.sizeRaw / 2);
}
}
const {
startResizeChecker: Ae,
stopResizeChecker: _e
} = Ze(
l,
() => L("layout"),
() => L("layout")
);
qe(() => {
Z(() => {
setTimeout(() => L("layout", !0), 200), Ae(), B = new MutationObserver(() => L("layout")), B.observe(l.value, Me), ae();
});
}), Fe(() => {
se(), _e(), B && (B.disconnect(), B = null);
});
const K = {
refreshScrollState() {
L("layout", !0);
},
getScrollContainer() {
return l.value;
},
scrollTo(e, o) {
var n;
(n = l.value) == null || n.scrollTo(e, o);
},
scrollToStart() {
var e;
(e = l.value) == null || e.scrollTo(0, 0);
},
scrollToEnd() {
var e;
(e = l.value) == null || e.scrollTo(l.value.scrollWidth, l.value.scrollHeight);
}
};
return s(K), (e, o) => (H(), D("div", {
ref_key: "scrollrect",
ref: m,
class: A([
"vue-scroll-rect",
e.scrollBarAlwaysShow ? "always-show-scrollbar" : "",
e.scrollBarBackgroundClickable ? "background-clickable" : "",
k.value ? "dragging" : "",
De.value ? "pulling" : ""
]),
style: C({
width: e.width ? M(e.width) : void 0,
height: e.height ? M(e.height) : void 0
}),
onWheel: Xe
}, [
b("div", {
ref_key: "container",
ref: l,
class: A(["scroll-content", e.scroll, e.containerClass, { "pull-refresh-enabled": e.enablePullToRefresh && w.value }]),
style: C({
maxWidth: e.maxWidth ? M(e.maxWidth) : void 0,
maxHeight: e.maxHeight ? M(e.maxHeight) : void 0,
...e.containerStyle
}),
onScroll: Ye,
onPointerdown: He,
onPointerup: oe,
onPointercancel: oe,
onLostpointercapture: ze
}, [
e.enablePullToRefresh && w.value ? (H(), D("div", {
key: 0,
class: A(["pull-refresh-track", { "is-transition": E.value }]),
style: C({ height: `${Ce.value}px` }),
"aria-hidden": "true"
}, [
b("div", al, [
W(e.$slots, "pullRefresh", {
state: j.value,
distance: c.value,
threshold: N.value,
loading: e.pullToRefreshLoading,
loadingHeight: ee.value
}, () => [
b("div", sl, [
j.value === "loading" ? (H(), D("span", nl)) : y("", !0),
b("span", ul, Je(We.value), 1)
])
])
])
], 6)) : y("", !0),
W(e.$slots, "default")
], 38),
e.enableBackToTop ? W(e.$slots, "backToTop", {
key: 0,
onBackToTop: K.scrollToStart,
visible: Y.value
}, () => [
b("button", {
type: "button",
class: A(["back-to-top-button", { "is-visible": Y.value }]),
"aria-hidden": !Y.value,
tabindex: Y.value ? 0 : -1,
onClick: o[0] || (o[0] = (n) => K.scrollToStart())
}, [
Ke(rl)
], 10, il)
]) : y("", !0),
d.show ? W(e.$slots, "scrollBarX", {
key: 1,
scrollBarValue: d,
onScroll: xe
}, () => [
b("div", {
ref_key: "scrollBarRefX",
ref: p,
class: "scrollbar horizontal",
onClick: $e,
onWheel: fe
}, [
b("div", {
class: "thumb",
ref_key: "scrollBarThumbRefX",
ref: i,
style: C({ left: `${d.pos}%`, width: `${d.size}%` }),
onMousedown: o[1] || (o[1] = //@ts-ignore
(...n) => _(me) && _(me)(...n)),
onWheel: fe
}, null, 36)
], 544)
]) : y("", !0),
f.show ? W(e.$slots, "scrollBarY", {
key: 2,
scrollBarValue: f,
onScroll: Ie
}, () => [
f.show ? (H(), D("div", {
key: 0,
ref_key: "scrollBarRefY",
ref: S,
class: "scrollbar vertical",
onClick: Ve,
onWheel: ve
}, [
b("div", {
class: "thumb",
ref_key: "scrollBarThumbRefY",
ref: P,
style: C({ top: `${f.pos}%`, height: `${f.size}%` }),
onMousedown: o[2] || (o[2] = //@ts-ignore
(...n) => _(ge) && _(ge)(...n)),
onWheel: ve
}, null, 36)
], 544)) : y("", !0)
]) : y("", !0)
], 38));
}
}), gl = {
install(a) {
a.component("scroll-rect", hl);
}
};
export {
hl as ScrollRect,
ml as createMiniTimeOut,
Qe as createMiniTimer,
Tl as createMouseDownAndUpHandler,
ke as createMouseDragHandler,
gl as default,
Re as throttle,
Ze as useResizeChecker
};
//# sourceMappingURL=vue-scroll-rect.es.js.map