virtua
Version:
A zero-config, fast and small (~3kB) virtual list (and grid) component for React, Vue, Solid and Svelte.
694 lines (683 loc) • 23.3 kB
JavaScript
var e = require("solid-js/web"), t = require("solid-js");
const r = null, {min: n, max: o, abs: s, floor: i} = Math, c = (e, t, r) => n(r, o(t, e)), l = e => [ ...e ].sort((e, t) => e - t), u = "function" == typeof queueMicrotask ? queueMicrotask : e => {
Promise.resolve().then(e);
}, f = () => {
let e;
return [ new Promise(t => {
e = t;
}), e ];
}, a = e => {
let t;
return () => (e && (t = e(), e = void 0), t);
}, d = (e, t, r) => {
const n = r ? "unshift" : "push";
for (let r = 0; r < t; r++) e[n](-1);
return e;
}, g = (e, t) => {
const r = e.o[t];
return -1 === r ? e.i : r;
}, h = (e, t, r) => {
const o = -1 === e.o[t];
return e.o[t] = r, e.l = n(t, e.l), o;
}, p = (e, t) => {
if (!e.u) return 0;
if (e.l >= t) return e.h[t];
e.l < 0 && (e.h[0] = 0, e.l = 0);
let r = e.l, n = e.h[r];
for (;r < t; ) n += g(e, r), e.h[++r] = n;
return e.l = t, n;
}, v = (e, t, r = 0, n = e.u - 1) => {
let o = r;
for (;r <= n; ) {
const s = i((r + n) / 2);
p(e, s) <= t ? (o = s, r = s + 1) : n = s - 1;
}
return c(o, 0, e.u - 1);
}, m = (e, t, r) => {
const o = t - e.u;
return e.l = r ? -1 : n(t - 1, e.l), e.u = t, o > 0 ? (d(e.h, o), d(e.o, o, r),
e.i * o) : (e.h.splice(o), (r ? e.o.splice(0, -o) : e.o.splice(o)).reduce((t, r) => t - (-1 === r ? e.i : r), 0));
}, S = e => e.documentElement, $ = e => e.ownerDocument, b = e => e.defaultView, x = /*#__PURE__*/ a(() => !!/iP(hone|od|ad)/.test(navigator.userAgent) || "MacIntel" === navigator.platform && navigator.maxTouchPoints > 0), z = /*#__PURE__*/ a(() => "scrollBehavior" in S(document).style), w = (e, t = 40, i = 0, c, u = !1) => {
let f = !!i, a = 1, S = 0, $ = 0, b = 0, z = 0, w = 0, y = 0, _ = 0, I = 0, k = r, T = [ 0, f ? o(i - 1, 0) : -1 ], M = 0, O = !1;
const R = ((e, t, r) => ({
i: t,
o: r ? d(r.slice(0, n(e, r.length)), o(0, e - r.length)) : d([], e),
u: e,
l: -1,
h: d([], e + 1)
}))(e, c ? c[1] : t, c && c[0]), q = new Set, J = () => b - $, B = () => J() + w + z, C = (e, t) => ((e, t, r, o) => {
if (o = n(o, e.u - 1), p(e, o) <= t) {
const n = v(e, r, o);
return [ v(e, t, o, n), n ];
}
{
const n = v(e, t, void 0, o);
return [ n, v(e, r, n) ];
}
})(R, e, t, T[0]), E = () => p(R, R.u), H = (e, t) => {
const r = p(R, e) - w;
return t ? E() - r - L(e) : r;
}, L = e => g(R, e), P = (e, t = -1) => R.o[e] === t, W = e => {
e && (x() && 0 !== _ || k && 1 === I ? w += e : z += e);
};
return {
p: () => {
q.clear();
},
v: () => a,
m: () => (e => [ e.o.slice(), e.i ])(R),
S: (e = 200) => {
if (!O || f) return T;
let t, r;
if (y) [t, r] = T; else {
let s = o(0, B()), i = s + S;
u || (e = o(0, e), 1 !== _ && (s -= e), 2 !== _ && (i += e)), [t, r] = T = C(o(0, s), o(0, i)),
k && (t = n(t, k[0]), r = o(r, k[1]));
}
return [ o(t, 0), n(r, R.u - 1) ];
},
$: e => v(R, e - $),
_: P,
I: H,
k: L,
T: () => R.u,
M: () => b,
O: () => 0 !== _,
R: () => S,
q: () => $,
J: E,
B: () => (y = z, z = 0, [ y, 2 === I ]),
C: (e, t) => {
const r = [ e, t ];
return q.add(r), () => {
q.delete(r);
};
},
H: (e, t) => {
let n, i, c = 0;
switch (e) {
case 1:
{
if (t === b && 0 === I) break;
const e = y;
y = 0;
const r = t - b, n = s(r);
e && n < s(e) + 1 || 0 !== I || (_ = r < 0 ? 2 : 1), f && (f = !1), b = t, c = 4;
const o = J();
o >= -S && o <= E() && (c += 1, i = n > S);
break;
}
case 2:
c = 8, 0 !== _ && (n = !0, c += 1), _ = 0, I = 0, k = r;
break;
case 3:
{
const e = t.filter(([e, t]) => !P(e, t));
if (!e.length) break;
W(e.reduce((e, [t, r]) => {
let n;
if (2 === I) n = !0; else if (k && 1 === I) n = t < k[0]; else {
const e = J(), r = H(t), o = L(t);
n = 1 !== _ && 0 === I ? r + o < e : r < e && r + o < e + S;
}
return n && (e += r - L(t)), e;
}, 0));
for (const [t, r] of e) {
const e = L(t), n = h(R, t, r);
u && (M += n ? r : r - e);
}
u && S && M > S && (W(((e, t) => {
let r = 0;
const n = [];
e.o.forEach((e, o) => {
-1 !== e && (n.push(e), o < t && r++);
}), e.l = -1;
const s = l(n), i = s.length, c = i / 2 | 0, u = i % 2 == 0 ? (s[c - 1] + s[c]) / 2 : s[c], f = e.i;
return ((e.i = u) - f) * o(t - r, 0);
})(R, v(R, B()))), u = !1), c = 3, i = !0;
break;
}
case 4:
S !== t && (S || (O = i = !0), S = t, c = 3);
break;
case 5:
t[1] ? (W(m(R, t[0], !0)), I = 2, c = 1) : (m(R, t[0]), c = 1);
break;
case 6:
$ = t;
break;
case 7:
I = 1;
break;
case 8:
k = C(t, t + S), c = 1;
}
c && (a = 1 + (2147483647 & a), n && w && (z += w, w = 0), q.forEach(([e, t]) => {
c & e && t(i);
}));
}
};
}, y = setTimeout, _ = (e, t) => t ? -e : e, I = (e, t, n, o, s, i) => {
const c = Date.now;
let l = 0, u = !1, f = !1, a = !1, d = !1;
const g = (() => {
let t;
const n = () => {
t != r && clearTimeout(t);
}, o = () => {
n(), t = y(() => {
t = r, (() => {
if (u || f) return u = !1, void g();
a = !1, e.H(2);
})();
}, 150);
};
return o.L = n, o;
})(), h = () => {
l = c(), a && (d = !0), i && e.H(6, i()), e.H(1, o()), g();
}, p = t => {
if (u || !e.O() || t.ctrlKey) return;
const r = c() - l;
150 > r && 50 < r && (n ? t.deltaX : t.deltaY) && (u = !0);
}, v = () => {
f = !0, a = d = !1;
}, m = () => {
f = !1, x() && (a = !0);
};
return t.addEventListener("scroll", h), t.addEventListener("wheel", p, {
passive: !0
}), t.addEventListener("touchstart", v, {
passive: !0
}), t.addEventListener("touchend", m, {
passive: !0
}), {
P: () => {
t.removeEventListener("scroll", h), t.removeEventListener("wheel", p), t.removeEventListener("touchstart", v),
t.removeEventListener("touchend", m), g.L();
},
W: () => {
const [t, r] = e.B();
t && (s(t, r, d), d = !1, r && e.R() > e.J() && e.H(1, o()));
}
};
}, k = (e, t, r) => {
let n;
return [ async (o, s) => {
if (!await t()) return;
n && n();
const i = () => {
const [t, r] = f();
return n = () => {
r(!1);
}, e.R() && y(n, 150), [ t, e.C(2, () => {
r(!0);
}) ];
};
if (s && z()) e.H(8, o()), u(async () => {
for (;;) {
let t = !0;
for (let [r, n] = e.S(); r <= n; r++) if (e._(r)) {
t = !1;
break;
}
if (t) break;
const [r, n] = i();
try {
if (!await r) return;
} finally {
n();
}
}
e.H(7), r(o(), s);
}); else for (;;) {
const [t, n] = i();
try {
if (e.H(7), r(o()), !await t) return;
} finally {
n();
}
}
}, () => {
n && n();
} ];
}, T = e => {
let t;
return {
j(r) {
(t || (t = new (b($(r)).ResizeObserver)(e))).observe(r);
},
N(e) {
t.unobserve(e);
},
P() {
t && t.disconnect();
}
};
}, M = r => {
let n;
r = t.mergeProps({
V: "div"
}, r), t.createEffect(() => {
n && t.onCleanup(r.X(n, r.Y));
});
const o = t.createMemo(() => {
const e = r.D, t = {
contain: "layout style",
position: "absolute",
[e ? "height" : "width"]: "100%",
[e ? "top" : "left"]: "0px",
[e ? "left" : "top"]: r.U + "px",
visibility: r.A ? "hidden" : void 0
};
return e && (t.display = "inline-flex"), t;
});
return e.createComponent(e.Dynamic, {
get component() {
return r.V;
},
get index() {
return r.Y;
},
ref(e) {
"function" == typeof n ? n(e) : n = e;
},
get style() {
return o();
},
get children() {
return r.F;
}
});
}, O = (e, t) => e[0] === t[0] && e[1] === t[1], R = n => {
let s;
const {itemSize: i, horizontal: u = !1, cache: a} = n;
n = t.mergeProps({
as: "div"
}, n);
const d = w(n.data.length, i, void 0, a, !i), g = ((e, t) => {
let n;
const o = t ? "width" : "height", s = new WeakMap, i = T(t => {
const i = [];
for (const {target: c, contentRect: l} of t) if (c.offsetParent) if (c === n) e.H(4, l[o]); else {
const e = s.get(c);
e != r && i.push([ e, l[o] ]);
}
i.length && e.H(3, i);
});
return {
G(e) {
i.j(n = e);
},
K: (e, t) => (s.set(e, t), i.j(e), () => {
s.delete(e), i.N(e);
}),
p: i.P
};
})(d, u), h = ((e, t) => {
let r, n, o = f(), s = !1;
const i = t ? "scrollLeft" : "scrollTop", l = t ? "overflowX" : "overflowY", [u, a] = k(e, () => o[0], (e, n) => {
e = _(e, s), n ? r.scrollTo({
[t ? "left" : "top"]: e,
behavior: "smooth"
}) : r[i] = e;
});
return {
Z(c, u) {
r = u, t && (s = "rtl" === getComputedStyle(u).direction), n = I(e, u, t, () => _(u[i], s), (t, r, n) => {
if (n) {
const e = u.style, t = e[l];
e[l] = "hidden", y(() => {
e[l] = t;
});
}
u[i] = _(e.M() + t, s), r && a();
}), o[1](!0);
},
p() {
n && n.P(), o[1](!1), o = f();
},
ee: () => s,
te(e) {
u(() => e);
},
re(t) {
t += e.M(), u(() => t);
},
ne(t, {align: r, smooth: n, offset: o = 0} = {}) {
if (t = c(t, 0, e.T() - 1), "nearest" === r) {
const n = e.I(t), o = e.M();
if (n < o) r = "start"; else {
if (!(n + e.k(t) > o + e.R())) return;
r = "end";
}
}
u(() => o + e.q() + e.I(t) + ("end" === r ? e.k(t) - e.R() : "center" === r ? (e.k(t) - e.R()) / 2 : 0), n);
},
oe: () => {
n && n.W();
}
};
})(d, u), [p, v] = t.createSignal(d.v());
d.C(1, () => {
v(d.v());
}), d.C(4, () => {
n.onScroll?.(d.M());
}), d.C(8, () => {
n.onScrollEnd?.();
});
const m = t.createMemo(e => {
p();
const t = d.S(n.bufferSize);
return e && O(e, t) ? e : t;
}), S = t.createMemo(() => p() && d.O()), $ = t.createMemo(() => p() && d.J()), b = t.createMemo(() => p() && h.ee());
t.onMount(() => {
n.ref && n.ref({
get cache() {
return d.m();
},
get scrollOffset() {
return d.M();
},
get scrollSize() {
return (e => o(e.J(), e.R()))(d);
},
get viewportSize() {
return d.R();
},
findItemIndex: d.$,
getItemOffset: d.I,
getItemSize: d.k,
scrollToIndex: h.ne,
scrollTo: h.te,
scrollBy: h.re
});
const e = s, r = n.scrollRef || e.parentElement;
g.G(r), h.Z(e, r), t.onCleanup(() => {
n.ref && n.ref(), d.p(), g.p(), h.p();
});
}), t.createComputed(t.on(() => n.startMargin || 0, e => {
e !== d.q() && d.H(6, e);
})), t.createEffect(t.on(p, () => {
h.oe();
}));
const x = t.createMemo(() => {
const e = n.data.length;
t.untrack(() => {
e !== d.T() && d.H(5, [ e, n.shift ]);
});
const r = [], o = [];
if (n.keepMounted) {
const e = new Set(n.keepMounted);
for (let [t, r] = m(); t <= r; t++) e.add(t);
l([ ...e ]).forEach(e => {
r.push(n.data[e]), o.push(e);
});
} else for (let [e, t] = m(); e <= t; e++) r.push(n.data[e]), o.push(e);
return {
se: r,
ie: o
};
});
return e.createComponent(e.Dynamic, {
get component() {
return n.as;
},
ref(e) {
"function" == typeof s ? s(e) : s = e;
},
get style() {
return {
contain: "size style",
"overflow-anchor": "none",
flex: "none",
position: "relative",
width: u ? $() + "px" : "100%",
height: u ? "100%" : $() + "px",
"pointer-events": S() ? "none" : void 0
};
},
get children() {
return e.createComponent(t.For, {
get each() {
return x().se;
},
children: (r, o) => ((r, o) => {
const s = t.createMemo(() => (p(), d.I(o(), b()))), i = t.createMemo(() => (p(),
d._(o()))), c = t.createMemo(() => t.untrack(() => n.children(r, o)));
return e.createComponent(M, {
get V() {
return n.item;
},
get Y() {
return o();
},
get X() {
return g.K;
},
get U() {
return s();
},
get A() {
return i();
},
get F() {
return c();
},
D: u
});
})(r, t.createMemo(() => x().ie[o()]))
});
}
});
};
var q = /*#__PURE__*/ e.template("<div>"), J = /*#__PURE__*/ e.template('<div style="contain:size style;overflow-anchor:none;flex:none;position:relative">');
exports.VList = r => {
const [n, o] = t.splitProps(r, [ "ref", "data", "children", "bufferSize", "itemSize", "shift", "horizontal", "keepMounted", "cache", "item", "onScroll", "onScrollEnd", "style" ]);
return s = q(), e.spread(s, e.mergeProps(o, {
get style() {
return {
display: n.horizontal ? "inline-block" : "block",
[n.horizontal ? "overflow-x" : "overflow-y"]: "auto",
contain: "strict",
width: "100%",
height: "100%",
...n.style
};
}
}), !1, !0), e.insert(s, e.createComponent(R, {
ref(e) {
var t = n.ref;
"function" == typeof t ? t(e) : n.ref = e;
},
get data() {
return n.data;
},
get bufferSize() {
return n.bufferSize;
},
get itemSize() {
return n.itemSize;
},
get shift() {
return n.shift;
},
get horizontal() {
return n.horizontal;
},
get keepMounted() {
return n.keepMounted;
},
get cache() {
return n.cache;
},
get item() {
return n.item;
},
get onScroll() {
return n.onScroll;
},
get onScrollEnd() {
return n.onScrollEnd;
},
get children() {
return n.children;
}
})), s;
var s;
}, exports.Virtualizer = R, exports.WindowVirtualizer = n => {
let o;
const {ref: s, data: i, children: l, itemSize: a, shift: d, horizontal: g = !1, cache: h, onScrollEnd: p} = n, v = w(n.data.length, a, void 0, h, !a), m = ((e, t) => {
const n = t ? "width" : "height", o = t ? "innerWidth" : "innerHeight", s = new WeakMap, i = T(t => {
const o = [];
for (const {target: e, contentRect: i} of t) {
if (!e.offsetParent) continue;
const t = s.get(e);
t != r && o.push([ t, i[n] ]);
}
o.length && e.H(3, o);
});
let c;
return {
G(t) {
const r = b($(t)), n = () => {
e.H(4, r[o]);
};
r.addEventListener("resize", n), u(n), c = () => {
r.removeEventListener("resize", n);
};
},
K: (e, t) => (s.set(e, t), i.j(e), () => {
s.delete(e), i.N(e);
}),
p() {
c && c(), i.P();
}
};
})(v, g), x = ((e, t) => {
let r, n, o = f(), s = !1;
const i = t ? "left" : "top", [l] = k(e, () => o[0], (e, t) => {
e = _(e, s);
const n = b($(r));
t ? n.scroll({
[i]: e,
behavior: "smooth"
}) : n.scroll({
[i]: e
});
}), u = (e, t, r, n, o = 0) => {
const i = n ? "offsetLeft" : "offsetTop", c = o + (n && s ? r.innerWidth - e[i] - e.offsetWidth : e[i]), l = e.offsetParent;
return e !== t && l ? u(l, t, r, n, c) : c;
};
return {
Z(c) {
r = c;
const l = t ? "scrollX" : "scrollY", f = $(c), a = b(f);
t && (s = "rtl" === getComputedStyle(S(f)).direction), n = I(e, a, t, () => _(a[l], s), (t, r) => {
r ? a.scroll({
[i]: _(e.M() + t, s)
}) : a.scrollBy({
[i]: _(t, s)
});
}, () => u(c, f.body, a, t)), o[1](!0);
},
p() {
n && n.P(), r = void 0, o[1](!1), o = f();
},
ee: () => s,
oe: () => {
n && n.W();
},
ne(n, {align: o, smooth: s, offset: i = 0} = {}) {
if (!r) return;
if (n = c(n, 0, e.T() - 1), "nearest" === o) {
const t = e.I(n), r = e.M();
if (t < r) o = "start"; else {
if (!(t + e.k(n) > r + e.R())) return;
o = "end";
}
}
const f = $(r), a = b(f), d = S(f), g = () => e.R() - (t ? d.clientWidth : d.clientHeight);
l(() => i + u(r, f.body, a, t) + e.I(n) + ("end" === o ? e.k(n) - (e.R() - g()) : "center" === o ? (e.k(n) - (e.R() - g())) / 2 : 0), s);
}
};
})(v, g), [z, y] = t.createSignal(v.v());
v.C(1, () => {
y(v.v());
}), v.C(4, () => {
n.onScroll?.();
}), v.C(8, () => {
n.onScrollEnd?.();
});
const R = t.createMemo(e => {
z();
const t = v.S(n.bufferSize);
return e && O(e, t) ? e : t;
}), q = t.createMemo(() => z() && v.O()), B = t.createMemo(() => z() && v.J()), C = t.createMemo(() => z() && x.ee());
t.onMount(() => {
n.ref && n.ref({
get cache() {
return v.m();
},
get scrollOffset() {
return v.M();
},
get viewportSize() {
return v.R();
},
findItemIndex: v.$,
getItemOffset: v.I,
getItemSize: v.k,
scrollToIndex: x.ne
}), m.G(o), x.Z(o), t.onCleanup(() => {
n.ref && n.ref(), v.p(), m.p(), x.p();
});
}), t.createEffect(t.on(z, () => {
x.oe();
}));
const E = t.createMemo(() => {
const e = n.data.length;
t.untrack(() => {
e !== v.T() && v.H(5, [ e, n.shift ]);
});
const r = [];
for (let [e, t] = R(); e <= t; e++) r.push(n.data[e]);
return r;
});
return H = J(), "function" == typeof (L = o) ? e.use(L, H) : o = H, e.insert(H, e.createComponent(t.For, {
get each() {
return E();
},
children: (r, o) => {
const s = t.createMemo(() => R()[0] + o()), i = t.createMemo(() => (z(), v.I(s(), C()))), c = t.createMemo(() => (z(),
v._(s()))), l = t.createMemo(() => t.untrack(() => n.children(r, s)));
return e.createComponent(M, {
get Y() {
return s();
},
get X() {
return m.K;
},
get U() {
return i();
},
get A() {
return c();
},
get F() {
return l();
},
D: g
});
}
})), e.effect(t => {
var r = g ? B() + "px" : "100%", n = g ? "100%" : B() + "px", o = q() ? "none" : void 0;
return r !== t.e && e.setStyleProperty(H, "width", t.e = r), n !== t.t && e.setStyleProperty(H, "height", t.t = n),
o !== t.a && e.setStyleProperty(H, "pointer-events", t.a = o), t;
}, {
e: void 0,
t: void 0,
a: void 0
}), H;
var H, L;
};
//# sourceMappingURL=index.cjs.map