UNPKG

virtua

Version:

A zero-config, fast and small (~3kB) virtual list (and grid) component for React, Vue, Solid and Svelte.

775 lines (765 loc) 26.3 kB
import { defineComponent as e, ref as t, computed as r, watch as o, createVNode as n, mergeProps as s, isVNode as i, onMounted as l, onUnmounted as c } from "vue"; const a = null, {min: u, max: f, abs: d, floor: p} = Math, m = (e, t, r) => u(r, f(t, e)), h = e => [ ...e ].sort((e, t) => e - t), _ = "function" == typeof queueMicrotask ? queueMicrotask : e => { Promise.resolve().then(e); }, b = () => { let e; return [ new Promise(t => { e = t; }), e ]; }, g = e => { let t; return () => (e && (t = e(), e = void 0), t); }, v = (e, t, r) => { const o = r ? "unshift" : "push"; for (let r = 0; r < t; r++) e[o](-1); return e; }, y = (e, t) => { const r = e.t[t]; return -1 === r ? e.o : r; }, S = (e, t, r) => { const o = -1 === e.t[t]; return e.t[t] = r, e.i = u(t, e.i), o; }, z = (e, t) => { if (!e.l) return 0; if (e.i >= t) return e.u[t]; e.i < 0 && (e.u[0] = 0, e.i = 0); let r = e.i, o = e.u[r]; for (;r < t; ) o += y(e, r), e.u[++r] = o; return e.i = t, o; }, x = (e, t, r = 0, o = e.l - 1) => { let n = r; for (;r <= o; ) { const s = p((r + o) / 2); z(e, s) <= t ? (n = s, r = s + 1) : o = s - 1; } return m(n, 0, e.l - 1); }, $ = (e, t, r) => { const o = t - e.l; return e.i = r ? -1 : u(t - 1, e.i), e.l = t, o > 0 ? (v(e.u, o), v(e.t, o, r), e.o * o) : (e.u.splice(o), (r ? e.t.splice(0, -o) : e.t.splice(o)).reduce((t, r) => t - (-1 === r ? e.o : r), 0)); }, w = e => e.documentElement, I = e => e.ownerDocument, O = e => e.defaultView, k = /*#__PURE__*/ g(() => !!/iP(hone|od|ad)/.test(navigator.userAgent) || "MacIntel" === navigator.platform && navigator.maxTouchPoints > 0), j = /*#__PURE__*/ g(() => "scrollBehavior" in w(document).style), N = (e, t = 40, r = 0, o, n = !1) => { let s = !!r, i = 1, l = 0, c = 0, p = 0, m = 0, _ = 0, b = 0, g = 0, w = 0, I = a, O = [ 0, s ? f(r - 1, 0) : -1 ], j = 0, N = !1; const B = ((e, t, r) => ({ o: t, t: r ? v(r.slice(0, u(e, r.length)), f(0, e - r.length)) : v([], e), l: e, i: -1, u: v([], e + 1) }))(e, o ? o[1] : t, o && o[0]), T = new Set, q = () => p - c, M = () => q() + _ + m, E = (e, t) => ((e, t, r, o) => { if (o = u(o, e.l - 1), z(e, o) <= t) { const n = x(e, r, o); return [ x(e, t, o, n), n ]; } { const n = x(e, t, void 0, o); return [ n, x(e, r, n) ]; } })(B, e, t, O[0]), P = () => z(B, B.l), R = (e, t) => { const r = z(B, e) - _; return t ? P() - r - A(e) : r; }, A = e => y(B, e), C = (e, t = -1) => B.t[e] === t, H = e => { e && (k() && 0 !== g || I && 1 === w ? _ += e : m += e); }; return { p: () => { T.clear(); }, m: () => i, h: () => (e => [ e.t.slice(), e.o ])(B), v: (e = 200) => { if (!N || s) return O; let t, r; if (b) [t, r] = O; else { let o = f(0, M()), s = o + l; n || (e = f(0, e), 1 !== g && (o -= e), 2 !== g && (s += e)), [t, r] = O = E(f(0, o), f(0, s)), I && (t = u(t, I[0]), r = f(r, I[1])); } return [ f(t, 0), u(r, B.l - 1) ]; }, S: e => x(B, e - c), I: C, O: R, k: A, j: () => B.l, N: () => p, B: () => 0 !== g, T: () => l, q: () => c, M: P, P: () => (b = m, m = 0, [ b, 2 === w ]), R: (e, t) => { const r = [ e, t ]; return T.add(r), () => { T.delete(r); }; }, A: (e, t) => { let r, o, u = 0; switch (e) { case 1: { if (t === p && 0 === w) break; const e = b; b = 0; const r = t - p, n = d(r); e && n < d(e) + 1 || 0 !== w || (g = r < 0 ? 2 : 1), s && (s = !1), p = t, u = 4; const i = q(); i >= -l && i <= P() && (u += 1, o = n > l); break; } case 2: u = 8, 0 !== g && (r = !0, u += 1), g = 0, w = 0, I = a; break; case 3: { const e = t.filter(([e, t]) => !C(e, t)); if (!e.length) break; H(e.reduce((e, [t, r]) => { let o; if (2 === w) o = !0; else if (I && 1 === w) o = t < I[0]; else { const e = q(), r = R(t), n = A(t); o = 1 !== g && 0 === w ? r + n < e : r < e && r + n < e + l; } return o && (e += r - A(t)), e; }, 0)); for (const [t, r] of e) { const e = A(t), o = S(B, t, r); n && (j += o ? r : r - e); } n && l && j > l && (H(((e, t) => { let r = 0; const o = []; e.t.forEach((e, n) => { -1 !== e && (o.push(e), n < t && r++); }), e.i = -1; const n = h(o), s = n.length, i = s / 2 | 0, l = s % 2 == 0 ? (n[i - 1] + n[i]) / 2 : n[i], c = e.o; return ((e.o = l) - c) * f(t - r, 0); })(B, x(B, M()))), n = !1), u = 3, o = !0; break; } case 4: l !== t && (l || (N = o = !0), l = t, u = 3); break; case 5: t[1] ? (H($(B, t[0], !0)), w = 2, u = 1) : ($(B, t[0]), u = 1); break; case 6: c = t; break; case 7: w = 1; break; case 8: I = E(t, t + l), u = 1; } u && (i = 1 + (2147483647 & i), r && _ && (m += _, _ = 0), T.forEach(([e, t]) => { u & e && t(o); })); } }; }, B = setTimeout, T = (e, t) => t ? -e : e, q = (e, t, r, o, n, s) => { const i = Date.now; let l = 0, c = !1, u = !1, f = !1, d = !1; const p = (() => { let t; const r = () => { t != a && clearTimeout(t); }, o = () => { r(), t = B(() => { t = a, (() => { if (c || u) return c = !1, void p(); f = !1, e.A(2); })(); }, 150); }; return o.C = r, o; })(), m = () => { l = i(), f && (d = !0), s && e.A(6, s()), e.A(1, o()), p(); }, h = t => { if (c || !e.B() || t.ctrlKey) return; const o = i() - l; 150 > o && 50 < o && (r ? t.deltaX : t.deltaY) && (c = !0); }, _ = () => { u = !0, f = d = !1; }, b = () => { u = !1, k() && (f = !0); }; return t.addEventListener("scroll", m), t.addEventListener("wheel", h, { passive: !0 }), t.addEventListener("touchstart", _, { passive: !0 }), t.addEventListener("touchend", b, { passive: !0 }), { H: () => { t.removeEventListener("scroll", m), t.removeEventListener("wheel", h), t.removeEventListener("touchstart", _), t.removeEventListener("touchend", b), p.C(); }, V: () => { const [t, r] = e.P(); t && (n(t, r, d), d = !1, r && e.T() > e.M() && e.A(1, o())); } }; }, M = (e, t, r) => { let o; return [ async (n, s) => { if (!await t()) return; o && o(); const i = () => { const [t, r] = b(); return o = () => { r(!1); }, e.T() && B(o, 150), [ t, e.R(2, () => { r(!0); }) ]; }; if (s && j()) e.A(8, n()), _(async () => { for (;;) { let t = !0; for (let [r, o] = e.v(); r <= o; r++) if (e.I(r)) { t = !1; break; } if (t) break; const [r, o] = i(); try { if (!await r) return; } finally { o(); } } e.A(7), r(n(), s); }); else for (;;) { const [t, o] = i(); try { if (e.A(7), r(n()), !await t) return; } finally { o(); } } }, () => { o && o(); } ]; }, E = e => { let t; return { F(r) { (t || (t = new (O(I(r)).ResizeObserver)(e))).observe(r); }, J(e) { t.unobserve(e); }, H() { t && t.disconnect(); } }; }, P = /*#__PURE__*/ e({ props: { L: { type: Object, required: !0 }, W: { type: Object, required: !0 }, X: { type: Object, required: !0 }, Y: { type: Function, required: !0 }, D: { type: Number, required: !0 }, U: { type: Boolean }, G: { type: Boolean }, K: { type: Boolean }, Z: { type: String, required: !0 }, ee: Object }, setup(e) { const l = t(), c = r(() => e.L.value && e.W.O(e.D, e.K)), a = r(() => e.L.value && e.W.I(e.D)); return o(() => l.value && e.D, (t, r, o) => { o(e.Y(l.value, e.D)); }, { flush: "post" }), () => { const {X: t, U: r, G: o, Z: u} = e, f = a.value, {style: d, ...p} = e.ee ?? {}, m = { contain: "layout style", position: f && o ? void 0 : "absolute", [r ? "height" : "width"]: "100%", [r ? "top" : "left"]: "0px", [r ? "left" : "top"]: c.value + "px", visibility: !f || o ? void 0 : "hidden", ...d }; return r && (m.display = "inline-flex"), n(u, s({ ref: l, style: m }, p), "function" == typeof (h = t) || "[object Object]" === Object.prototype.toString.call(h) && !i(h) ? t : { default: () => [ t ], _: 2 }, 16, [ "style" ]); var h; }; } }), R = (e, t) => { if (1 === e.length) { const t = e[0].key; if (null != t) return t; } return "_" + t; }, A = (e, t) => e[0] === t[0] && e[1] === t[1], C = /*#__PURE__*/ e({ props: { data: { type: Array, required: !0 }, bufferSize: Number, itemSize: Number, shift: Boolean, horizontal: Boolean, startMargin: { type: Number, default: 0 }, ssrCount: Number, scrollRef: Object, as: { type: String, default: "div" }, item: { type: String, default: "div" }, itemProps: Function, keepMounted: Array, cache: Object }, emits: [ "scroll", "scrollEnd" ], setup(e, {emit: s, expose: u, slots: d}) { let p = !!e.ssrCount; const _ = e.horizontal, g = t(), v = N(e.data.length, e.itemSize, e.ssrCount, e.cache, !e.itemSize), y = ((e, t) => { let r; const o = t ? "width" : "height", n = new WeakMap, s = E(t => { const s = []; for (const {target: i, contentRect: l} of t) if (i.offsetParent) if (i === r) e.A(4, l[o]); else { const e = n.get(i); e != a && s.push([ e, l[o] ]); } s.length && e.A(3, s); }); return { te(e) { s.F(r = e); }, re: (e, t) => (n.set(e, t), s.F(e), () => { n.delete(e), s.J(e); }), p: s.H }; })(v, _), S = ((e, t) => { let r, o, n = b(), s = !1; const i = t ? "scrollLeft" : "scrollTop", l = t ? "overflowX" : "overflowY", [c, a] = M(e, () => n[0], (e, o) => { e = T(e, s), o ? r.scrollTo({ [t ? "left" : "top"]: e, behavior: "smooth" }) : r[i] = e; }); return { oe(c, u) { r = u, t && (s = "rtl" === getComputedStyle(u).direction), o = q(e, u, t, () => T(u[i], s), (t, r, o) => { if (o) { const e = u.style, t = e[l]; e[l] = "hidden", B(() => { e[l] = t; }); } u[i] = T(e.N() + t, s), r && a(); }), n[1](!0); }, p() { o && o.H(), n[1](!1), n = b(); }, ne: () => s, se(e) { c(() => e); }, ie(t) { t += e.N(), c(() => t); }, le(t, {align: r, smooth: o, offset: n = 0} = {}) { if (t = m(t, 0, e.j() - 1), "nearest" === r) { const o = e.O(t), n = e.N(); if (o < n) r = "start"; else { if (!(o + e.k(t) > n + e.T())) return; r = "end"; } } c(() => n + e.q() + e.O(t) + ("end" === r ? e.k(t) - e.T() : "center" === r ? (e.k(t) - e.T()) / 2 : 0), o); }, ce: () => { o && o.V(); } }; })(v, _), z = t(v.m()); v.R(1, () => { z.value = v.m(); }), v.R(4, () => { s("scroll", v.N()); }), v.R(8, () => { s("scrollEnd"); }); const x = r(t => { z.value; const r = v.v(e.bufferSize); return t && A(t, r) ? t : r; }), $ = r(() => z.value && v.B()), w = r(() => z.value && v.M()); return l(() => { p = !1; const t = g.value, r = requestAnimationFrame(() => { const r = e => { y.te(e), S.oe(t, e); }; e.scrollRef ? r(e.scrollRef) : r(t.parentElement); }); c(() => { cancelAnimationFrame(r); }); }), c(() => { v.p(), y.p(), S.p(); }), o(() => e.data.length, t => { v.A(5, [ t, e.shift ]); }), o(() => e.startMargin, e => { v.A(6, e); }, { immediate: !0 }), o([ z ], () => { S.ce(); }, { flush: "post" }), u({ get cache() { return v.h(); }, get scrollOffset() { return v.N(); }, get scrollSize() { return (e => f(e.M(), e.T()))(v); }, get viewportSize() { return v.T(); }, findItemIndex: v.S, getItemOffset: v.O, getItemSize: v.k, scrollToIndex: S.le, scrollTo: S.se, scrollBy: S.ie }), () => { const t = e.as, r = e.item, o = w.value, s = S.ne(), l = [], c = t => { const o = d.default({ item: e.data[t], index: t }); return n(P, { key: R(o, t), L: z, W: v, Y: y.re, D: t, X: o, U: _, K: s, G: p, Z: r, ee: e.itemProps?.({ item: e.data[t], index: t }) }, null, 8, [ "L", "W", "Y", "D", "X", "U", "K", "G", "Z", "ee" ]); }; if (e.keepMounted) { const t = new Set(e.keepMounted); for (let [e, r] = x.value; e <= r; e++) t.add(e); h([ ...t ]).forEach(e => { l.push(c(e)); }); } else for (let [e, t] = x.value; e <= t; e++) l.push(c(e)); return n(t, { ref: g, style: { contain: "size style", overflowAnchor: "none", flex: "none", position: "relative", width: _ ? o + "px" : "100%", height: _ ? "100%" : o + "px", pointerEvents: $.value ? "none" : void 0 } }, "function" == typeof (a = l) || "[object Object]" === Object.prototype.toString.call(a) && !i(a) ? l : { default: () => [ l ], _: 2 }, 8, [ "style" ]); var a; }; } }), H = /*#__PURE__*/ e({ props: { data: { type: Array, required: !0 }, bufferSize: Number, itemSize: Number, shift: Boolean, horizontal: Boolean, ssrCount: Number, itemProps: Function, keepMounted: Array, cache: Object }, emits: [ "scroll", "scrollEnd" ], setup(e, {emit: r, expose: o, slots: s}) { const l = e.horizontal, c = e => { r("scroll", e); }, a = () => { r("scrollEnd"); }, u = t(); return o({ get cache() { return u.value.cache; }, get scrollOffset() { return u.value.scrollOffset; }, get scrollSize() { return u.value.scrollSize; }, get viewportSize() { return u.value.viewportSize; }, findItemIndex: (...e) => u.value.findItemIndex(...e), getItemOffset: (...e) => u.value.getItemOffset(...e), getItemSize: (...e) => u.value.getItemSize(...e), scrollToIndex: (...e) => u.value.scrollToIndex(...e), scrollTo: (...e) => u.value.scrollTo(...e), scrollBy: (...e) => u.value.scrollBy(...e) }), () => { return n("div", { style: { display: l ? "inline-block" : "block", [l ? "overflowX" : "overflowY"]: "auto", contain: "strict", width: "100%", height: "100%" } }, [ n(C, { ref: u, data: e.data, bufferSize: e.bufferSize, itemSize: e.itemSize, itemProps: e.itemProps, shift: e.shift, ssrCount: e.ssrCount, horizontal: l, keepMounted: e.keepMounted, cache: e.cache, onScroll: c, onScrollEnd: a }, (t = s, "function" == typeof t || "[object Object]" === Object.prototype.toString.call(t) && !i(t) ? s : { default: () => [ s ], _: 2 }), 8, [ "data", "bufferSize", "itemSize", "itemProps", "shift", "ssrCount", "horizontal", "keepMounted", "cache", "onScroll", "onScrollEnd" ]) ], 4); var t; }; } }), V = /*#__PURE__*/ e({ props: { data: { type: Array, required: !0 }, bufferSize: Number, itemSize: Number, shift: Boolean, horizontal: Boolean, as: { type: String, default: "div" }, item: { type: String, default: "div" }, cache: Object }, emits: [ "scroll", "scrollEnd" ], setup(e, {emit: s, slots: u, expose: f}) { const d = e.horizontal, p = t(), h = N(e.data.length, e.itemSize, void 0, e.cache, !e.itemSize), g = ((e, t) => { const r = t ? "width" : "height", o = t ? "innerWidth" : "innerHeight", n = new WeakMap, s = E(t => { const o = []; for (const {target: e, contentRect: s} of t) { if (!e.offsetParent) continue; const t = n.get(e); t != a && o.push([ t, s[r] ]); } o.length && e.A(3, o); }); let i; return { te(t) { const r = O(I(t)), n = () => { e.A(4, r[o]); }; r.addEventListener("resize", n), _(n), i = () => { r.removeEventListener("resize", n); }; }, re: (e, t) => (n.set(e, t), s.F(e), () => { n.delete(e), s.J(e); }), p() { i && i(), s.H(); } }; })(h, d), v = ((e, t) => { let r, o, n = b(), s = !1; const i = t ? "left" : "top", [l] = M(e, () => n[0], (e, t) => { e = T(e, s); const o = O(I(r)); t ? o.scroll({ [i]: e, behavior: "smooth" }) : o.scroll({ [i]: e }); }), c = (e, t, r, o, n = 0) => { const i = o ? "offsetLeft" : "offsetTop", l = n + (o && s ? r.innerWidth - e[i] - e.offsetWidth : e[i]), a = e.offsetParent; return e !== t && a ? c(a, t, r, o, l) : l; }; return { oe(l) { r = l; const a = t ? "scrollX" : "scrollY", u = I(l), f = O(u); t && (s = "rtl" === getComputedStyle(w(u)).direction), o = q(e, f, t, () => T(f[a], s), (t, r) => { r ? f.scroll({ [i]: T(e.N() + t, s) }) : f.scrollBy({ [i]: T(t, s) }); }, () => c(l, u.body, f, t)), n[1](!0); }, p() { o && o.H(), r = void 0, n[1](!1), n = b(); }, ne: () => s, ce: () => { o && o.V(); }, le(o, {align: n, smooth: s, offset: i = 0} = {}) { if (!r) return; if (o = m(o, 0, e.j() - 1), "nearest" === n) { const t = e.O(o), r = e.N(); if (t < r) n = "start"; else { if (!(t + e.k(o) > r + e.T())) return; n = "end"; } } const a = I(r), u = O(a), f = w(a), d = () => e.T() - (t ? f.clientWidth : f.clientHeight); l(() => i + c(r, a.body, u, t) + e.O(o) + ("end" === n ? e.k(o) - (e.T() - d()) : "center" === n ? (e.k(o) - (e.T() - d())) / 2 : 0), s); } }; })(h, d), y = t(h.m()); h.R(1, () => { y.value = h.m(); }), h.R(4, () => { s("scroll"); }), h.R(8, () => { s("scrollEnd"); }); const S = r(t => { y.value; const r = h.v(e.bufferSize); return t && A(t, r) ? t : r; }), z = r(() => y.value && h.B()), x = r(() => y.value && h.M()); return l(() => { const e = p.value; e && (g.te(e), v.oe(e)); }), c(() => { h.p(), g.p(), v.p(); }), o(() => e.data.length, t => { h.A(5, [ t, e.shift ]); }), o([ y ], () => { v.ce(); }, { flush: "post" }), f({ get cache() { return h.h(); }, get scrollOffset() { return h.N(); }, get viewportSize() { return h.T(); }, findItemIndex: h.S, getItemOffset: h.O, getItemSize: h.k, scrollToIndex: v.le }), () => { const t = e.as, r = e.item, o = x.value, s = v.ne(), l = []; for (let [t, o] = S.value; t <= o; t++) { const o = u.default({ item: e.data[t], index: t }); l.push(n(P, { key: R(o, t), L: y, W: h, Y: g.re, D: t, X: o, U: d, K: s, Z: r }, null, 8, [ "L", "W", "Y", "D", "X", "U", "K", "Z" ])); } return n(t, { ref: p, style: { contain: "size style", overflowAnchor: "none", flex: "none", position: "relative", width: d ? o + "px" : "100%", height: d ? "100%" : o + "px", pointerEvents: z.value ? "none" : void 0 } }, "function" == typeof (c = l) || "[object Object]" === Object.prototype.toString.call(c) && !i(c) ? l : { default: () => [ l ], _: 2 }, 8, [ "style" ]); var c; }; } }); export { H as VList, C as Virtualizer, V as WindowVirtualizer }; //# sourceMappingURL=index.js.map