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
JavaScript
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