UNPKG

react-virtuoso

Version:

A virtual scroll React component for efficiently rendering large scrollable lists, grids, tables, and feeds

1,997 lines 94.5 kB
import { jsx as G, jsxs as Ut, Fragment as ao } from "react/jsx-runtime"; import E, { createElement as $t } from "react"; import fo from "react-dom"; const ve = 0, At = 1, Jt = 2, zn = 4; function un(t) { return () => t; } function mo(t) { t(); } function se(t, e) { return (n) => t(e(n)); } function an(t, e) { return () => t(e); } function po(t, e) { return (n) => t(e, n); } function Ae(t) { return t !== void 0; } function ho(...t) { return () => { t.map(mo); }; } function Qt() { } function ye(t, e) { return e(t), t; } function go(t, e) { return e(t); } function tt(...t) { return t; } function Y(t, e) { return t(At, e); } function D(t, e) { t(ve, e); } function We(t) { t(Jt); } function rt(t) { return t(zn); } function F(t, e) { return Y(t, po(e, ve)); } function Et(t, e) { const n = t(At, (o) => { n(), e(o); }); return n; } function dn(t) { let e, n; return (o) => (r) => { e = r, n && clearTimeout(n), n = setTimeout(() => { o(e); }, t); }; } function On(t, e) { return t === e; } function J(t = On) { let e; return (n) => (o) => { t(e, o) || (e = o, n(o)); }; } function P(t) { return (e) => (n) => { t(n) && e(n); }; } function k(t) { return (e) => se(e, t); } function Ft(t) { return (e) => () => { e(t); }; } function x(t, ...e) { const n = Io(...e); return ((o, r) => { switch (o) { case Jt: We(t); return; case At: return Y(t, n(r)); } }); } function Lt(t, e) { return (n) => (o) => { n(e = t(e, o)); }; } function Kt(t) { return (e) => (n) => { t > 0 ? t-- : e(n); }; } function Gt(t) { let e = null, n; return (o) => (r) => { e = r, !n && (n = setTimeout(() => { n = void 0, o(e); }, t)); }; } function $(...t) { const e = new Array(t.length); let n = 0, o = null; const r = Math.pow(2, t.length) - 1; return t.forEach((s, i) => { const l = Math.pow(2, i); Y(s, (u) => { const d = n; n = n | l, e[i] = u, d !== r && n === r && o && (o(), o = null); }); }), (s) => (i) => { const l = () => { s([i].concat(e)); }; n === r ? l() : o = l; }; } function Io(...t) { return (e) => t.reduceRight(go, e); } function xo(t) { let e, n; const o = () => e == null ? void 0 : e(); return function(r, s) { switch (r) { case At: return s ? n === s ? void 0 : (o(), n = s, e = Y(t, s), e) : (o(), Qt); case Jt: o(), n = null; return; } }; } function C(t) { let e = t; const n = U(); return ((o, r) => { switch (o) { case ve: e = r; break; case At: { r(e); break; } case zn: return e; } return n(o, r); }); } function ht(t, e) { return ye(C(e), (n) => F(t, n)); } function U() { const t = []; return ((e, n) => { switch (e) { case ve: t.slice().forEach((o) => { o(n); }); return; case Jt: t.splice(0, t.length); return; case At: return t.push(n), () => { const o = t.indexOf(n); o > -1 && t.splice(o, 1); }; } }); } function bt(t) { return ye(U(), (e) => F(t, e)); } function K(t, e = [], { singleton: n } = { singleton: !0 }) { return { constructor: t, dependencies: e, id: So(), singleton: n }; } const So = () => Symbol(); function To(t) { const e = /* @__PURE__ */ new Map(), n = ({ constructor: o, dependencies: r, id: s, singleton: i }) => { if (i && e.has(s)) return e.get(s); const l = o(r.map((u) => n(u))); return i && e.set(s, l), l; }; return n(t); } function ut(...t) { const e = U(), n = new Array(t.length); let o = 0; const r = Math.pow(2, t.length) - 1; return t.forEach((s, i) => { const l = Math.pow(2, i); Y(s, (u) => { n[i] = u, o = o | l, o === r && D(e, n); }); }), function(s, i) { switch (s) { case Jt: { We(e); return; } case At: return o === r && i(n), Y(e, i); } }; } function V(t, e = On) { return x(t, J(e)); } function Fe(...t) { return function(e, n) { switch (e) { case Jt: return; case At: return ho(...t.map((o) => Y(o, n))); } }; } var Ct = /* @__PURE__ */ ((t) => (t[t.DEBUG = 0] = "DEBUG", t[t.INFO = 1] = "INFO", t[t.WARN = 2] = "WARN", t[t.ERROR = 3] = "ERROR", t))(Ct || {}); const Co = { 0: "debug", 3: "error", 1: "log", 2: "warn" }, wo = () => typeof globalThis > "u" ? window : globalThis, Wt = K( () => { const t = C( 3 /* ERROR */ ); return { log: C((n, o, r = 1) => { var i; const s = (i = wo().VIRTUOSO_LOG_LEVEL) != null ? i : rt(t); r >= s && console[Co[r]]( "%creact-virtuoso: %c%s %o", "color: #0253b3; font-weight: bold", "color: initial", n, o ); }), logLevel: t }; }, [], { singleton: !0 } ); function Vt(t, e, n) { return _e(t, e, n).callbackRef; } function _e(t, e, n) { const o = E.useRef(null); let r = (i) => { }; const s = E.useMemo(() => typeof ResizeObserver < "u" ? new ResizeObserver((i) => { const l = () => { const u = i[0].target; u.offsetParent !== null && t(u); }; n ? l() : requestAnimationFrame(l); }) : null, [t, n]); return r = (i) => { i && e ? (s == null || s.observe(i), o.current = i) : (o.current && (s == null || s.unobserve(o.current)), o.current = null); }, { callbackRef: r, ref: o }; } function Fn(t, e, n, o, r, s, i, l, u) { const d = E.useCallback( (m) => { const S = vo(m.children, e, l ? "offsetWidth" : "offsetHeight", r); let h = m.parentElement; for (; !h.dataset.virtuosoScroller; ) h = h.parentElement; const T = h.lastElementChild.dataset.viewportType === "window"; let w; T && (w = h.ownerDocument.defaultView); const R = i ? l ? i.scrollLeft : i.scrollTop : T ? l ? w.scrollX || w.document.documentElement.scrollLeft : w.scrollY || w.document.documentElement.scrollTop : l ? h.scrollLeft : h.scrollTop, g = i ? l ? i.scrollWidth : i.scrollHeight : T ? l ? w.document.documentElement.scrollWidth : w.document.documentElement.scrollHeight : l ? h.scrollWidth : h.scrollHeight, f = i ? l ? i.offsetWidth : i.offsetHeight : T ? l ? w.innerWidth : w.innerHeight : l ? h.offsetWidth : h.offsetHeight; o({ scrollHeight: g, scrollTop: Math.max(R, 0), viewportHeight: f }), s == null || s( l ? fn("column-gap", getComputedStyle(m).columnGap, r) : fn("row-gap", getComputedStyle(m).rowGap, r) ), S !== null && t(S); }, [t, e, r, s, i, o, l] ); return _e(d, n, u); } function vo(t, e, n, o) { const r = t.length; if (r === 0) return null; const s = []; for (let i = 0; i < r; i++) { const l = t.item(i); if (l.dataset.index === void 0) continue; const u = parseInt(l.dataset.index), d = parseFloat(l.dataset.knownSize), m = e(l, n); if (m === 0 && o("Zero-sized element, this should not happen", { child: l }, Ct.ERROR), m === d) continue; const S = s[s.length - 1]; s.length === 0 || S.size !== m || S.endIndex !== u - 1 ? s.push({ endIndex: u, size: m, startIndex: u }) : s[s.length - 1].endIndex++; } return s; } function fn(t, e, n) { return e !== "normal" && !(e != null && e.endsWith("px")) && n(`${t} was not resolved to pixel value correctly`, e, Ct.WARN), e === "normal" ? 0 : parseInt(e != null ? e : "0", 10); } function Ne(t, e, n) { const o = E.useRef(null), r = E.useCallback( (u) => { if (!(u != null && u.offsetParent)) return; const d = u.getBoundingClientRect(), m = d.width; let S, h; if (e) { const T = e.getBoundingClientRect(), w = d.top - T.top; h = T.height - Math.max(0, w), S = w + e.scrollTop; } else { const T = i.current.ownerDocument.defaultView; h = T.innerHeight - Math.max(0, d.top), S = d.top + T.scrollY; } o.current = { offsetTop: S, visibleHeight: h, visibleWidth: m }, t(o.current); }, // eslint-disable-next-line react-hooks/exhaustive-deps [t, e] ), { callbackRef: s, ref: i } = _e(r, !0, n), l = E.useCallback(() => { r(i.current); }, [r, i]); return E.useEffect(() => { var u; if (e) { e.addEventListener("scroll", l); const d = new ResizeObserver(() => { requestAnimationFrame(l); }); return d.observe(e), () => { e.removeEventListener("scroll", l), d.unobserve(e); }; } else { const d = (u = i.current) == null ? void 0 : u.ownerDocument.defaultView; return d == null || d.addEventListener("scroll", l), d == null || d.addEventListener("resize", l), () => { d == null || d.removeEventListener("scroll", l), d == null || d.removeEventListener("resize", l); }; } }, [l, e, i]), s; } const It = K( () => { const t = U(), e = U(), n = C(0), o = U(), r = C(0), s = U(), i = U(), l = C(0), u = C(0), d = C(0), m = C(0), S = U(), h = U(), T = C(!1), w = C(!1), R = C(!1); return F( x( t, k(({ scrollTop: g }) => g) ), e ), F( x( t, k(({ scrollHeight: g }) => g) ), i ), F(e, r), { deviation: n, fixedFooterHeight: d, fixedHeaderHeight: u, footerHeight: m, headerHeight: l, horizontalDirection: w, scrollBy: h, // input scrollContainerState: t, scrollHeight: i, scrollingInProgress: T, // signals scrollTo: S, scrollTop: e, skipAnimationFrameInResizeObserver: R, smoothScrollTargetReached: o, // state statefulScrollTop: r, viewportHeight: s }; }, [], { singleton: !0 } ), ie = { lvl: 0 }; function Ln(t, e) { const n = t.length; if (n === 0) return []; let { index: o, value: r } = e(t[0]); const s = []; for (let i = 1; i < n; i++) { const { index: l, value: u } = e(t[i]); s.push({ end: l - 1, start: o, value: r }), o = l, r = u; } return s.push({ end: 1 / 0, start: o, value: r }), s; } function X(t) { return t === ie; } function le(t, e) { if (!X(t)) return e === t.k ? t.v : e < t.k ? le(t.l, e) : le(t.r, e); } function kt(t, e, n = "k") { if (X(t)) return [-1 / 0, void 0]; if (Number(t[n]) === e) return [t.k, t.v]; if (Number(t[n]) < e) { const o = kt(t.r, e, n); return o[0] === -1 / 0 ? [t.k, t.v] : o; } return kt(t.l, e, n); } function yt(t, e, n) { return X(t) ? Gn(e, n, 1) : e === t.k ? dt(t, { k: e, v: n }) : e < t.k ? mn(dt(t, { l: yt(t.l, e, n) })) : mn(dt(t, { r: yt(t.r, e, n) })); } function Zt() { return ie; } function Xt(t, e, n) { if (X(t)) return []; const o = kt(t, e)[0]; return yo(Ve(t, o, n)); } function Le(t, e) { if (X(t)) return ie; const { k: n, l: o, r } = t; if (e === n) { if (X(o)) return r; if (X(r)) return o; { const [s, i] = Pn(o); return Se(dt(t, { k: s, l: Vn(o), v: i })); } } else return e < n ? Se(dt(t, { l: Le(o, e) })) : Se(dt(t, { r: Le(r, e) })); } function Dt(t) { return X(t) ? [] : [...Dt(t.l), { k: t.k, v: t.v }, ...Dt(t.r)]; } function Ve(t, e, n) { if (X(t)) return []; const { k: o, l: r, r: s, v: i } = t; let l = []; return o > e && (l = l.concat(Ve(r, e, n))), o >= e && o <= n && l.push({ k: o, v: i }), o <= n && (l = l.concat(Ve(s, e, n))), l; } function Se(t) { const { l: e, lvl: n, r: o } = t; if (o.lvl >= n - 1 && e.lvl >= n - 1) return t; if (n > o.lvl + 1) { if (Ee(e)) return Mn(dt(t, { lvl: n - 1 })); if (!X(e) && !X(e.r)) return dt(e.r, { l: dt(e, { r: e.r.l }), lvl: n, r: dt(t, { l: e.r.r, lvl: n - 1 }) }); throw new Error("Unexpected empty nodes"); } else { if (Ee(t)) return Pe(dt(t, { lvl: n - 1 })); if (!X(o) && !X(o.l)) { const r = o.l, s = Ee(r) ? o.lvl - 1 : o.lvl; return dt(r, { l: dt(t, { lvl: n - 1, r: r.l }), lvl: r.lvl + 1, r: Pe(dt(o, { l: r.r, lvl: s })) }); } else throw new Error("Unexpected empty nodes"); } } function dt(t, e) { return Gn( e.k !== void 0 ? e.k : t.k, e.v !== void 0 ? e.v : t.v, e.lvl !== void 0 ? e.lvl : t.lvl, e.l !== void 0 ? e.l : t.l, e.r !== void 0 ? e.r : t.r ); } function Vn(t) { return X(t.r) ? t.l : Se(dt(t, { r: Vn(t.r) })); } function Ee(t) { return X(t) || t.lvl > t.r.lvl; } function Pn(t) { return X(t.r) ? [t.k, t.v] : Pn(t.r); } function Gn(t, e, n, o = ie, r = ie) { return { k: t, l: o, lvl: n, r, v: e }; } function mn(t) { return Pe(Mn(t)); } function Mn(t) { const { l: e } = t; return !X(e) && e.lvl === t.lvl ? dt(e, { r: dt(t, { l: e.r }) }) : t; } function Pe(t) { const { lvl: e, r: n } = t; return !X(n) && !X(n.r) && n.lvl === e && n.r.lvl === e ? dt(n, { l: dt(t, { r: n.l }), lvl: e + 1 }) : t; } function yo(t) { return Ln(t, ({ k: e, v: n }) => ({ index: e, value: n })); } function An(t, e) { return !!(t && t.startIndex === e.startIndex && t.endIndex === e.endIndex); } function ce(t, e) { return !!(t && t[0] === e[0] && t[1] === e[1]); } const De = K( () => ({ recalcInProgress: C(!1) }), [], { singleton: !0 } ); function Wn(t, e, n) { return t[Ce(t, e, n)]; } function Ce(t, e, n, o = 0) { let r = t.length - 1; for (; o <= r; ) { const s = Math.floor((o + r) / 2), i = t[s], l = n(i, e); if (l === 0) return s; if (l === -1) { if (r - o < 2) return s - 1; r = s - 1; } else { if (r === o) return s; o = s + 1; } } throw new Error(`Failed binary finding record in array - ${t.join(",")}, searched for ${e}`); } function bo(t, e, n, o) { const r = Ce(t, e, o), s = Ce(t, n, o, r); return t.slice(r, s + 1); } function zt(t, e) { return Math.round(t.getBoundingClientRect()[e]); } function be(t) { return !X(t.groupOffsetTree); } function $e({ index: t }, e) { return e === t ? 0 : e < t ? -1 : 1; } function Ro() { return { groupIndices: [], groupOffsetTree: Zt(), lastIndex: 0, lastOffset: 0, lastSize: 0, offsetTree: [], sizeTree: Zt() }; } function Ho(t, e) { let n = X(t) ? 0 : 1 / 0; for (const o of e) { const { endIndex: r, size: s, startIndex: i } = o; if (n = Math.min(n, i), X(t)) { t = yt(t, 0, s); continue; } const l = Xt(t, i - 1, r + 1); if (l.some(Lo(o))) continue; let u = !1, d = !1; for (const { end: m, start: S, value: h } of l) u ? (r >= S || s === h) && (t = Le(t, S)) : (d = h !== s, u = !0), m > r && r >= S && h !== s && (t = yt(t, r + 1, h)); d && (t = yt(t, i, s)); } return [t, n]; } function Eo(t) { return typeof t.groupIndex < "u"; } function Bo({ offset: t }, e) { return e === t ? 0 : e < t ? -1 : 1; } function ue(t, e, n) { if (e.length === 0) return 0; const { index: o, offset: r, size: s } = Wn(e, t, $e), i = t - o, l = s * i + (i - 1) * n + r; return l > 0 ? l + n : l; } function _n(t, e) { if (!be(e)) return t; let n = 0; for (; e.groupIndices[n] <= t + n; ) n++; return t + n; } function Nn(t, e, n) { if (Eo(t)) return e.groupIndices[t.groupIndex] + 1; { const o = t.index === "LAST" ? n : t.index; let r = _n(o, e); return r = Math.max(0, r, Math.min(n, r)), r; } } function ko(t, e, n, o = 0) { return o > 0 && (e = Math.max(e, Wn(t, o, $e).offset)), Ln(bo(t, e, n, Bo), Fo); } function zo(t, [e, n, o, r]) { e.length > 0 && o("received item sizes", e, Ct.DEBUG); const s = t.sizeTree; let i = s, l = 0; if (n.length > 0 && X(s) && e.length === 2) { const h = e[0].size, T = e[1].size; i = n.reduce((w, R) => yt(yt(w, R, h), R + 1, T), i); } else [i, l] = Ho(i, e); if (i === s) return t; const { lastIndex: u, lastOffset: d, lastSize: m, offsetTree: S } = Ge(t.offsetTree, l, i, r); return { groupIndices: n, groupOffsetTree: n.reduce((h, T) => yt(h, T, ue(T, S, r)), Zt()), lastIndex: u, lastOffset: d, lastSize: m, offsetTree: S, sizeTree: i }; } function Oo(t) { return Dt(t).map(({ k: e, v: n }, o, r) => { const s = r[o + 1]; return { endIndex: s ? s.k - 1 : 1 / 0, size: n, startIndex: e }; }); } function pn(t, e) { let n = 0, o = 0; for (; n < t; ) n += e[o + 1] - e[o] - 1, o++; return o - (n === t ? 0 : 1); } function Ge(t, e, n, o) { let r = t, s = 0, i = 0, l = 0, u = 0; if (e !== 0) { u = Ce(r, e - 1, $e), l = r[u].offset; const m = kt(n, e - 1); s = m[0], i = m[1], r.length && r[u].size === kt(n, e)[1] && (u -= 1), r = r.slice(0, u + 1); } else r = []; for (const { start: d, value: m } of Xt(n, e, 1 / 0)) { const S = d - s, h = S * i + l + S * o; r.push({ index: d, offset: h, size: m }), s = d, l = h, i = m; } return { lastIndex: s, lastOffset: l, lastSize: i, offsetTree: r }; } function Fo(t) { return { index: t.index, value: t }; } function Lo(t) { const { endIndex: e, size: n, startIndex: o } = t; return (r) => r.start === o && (r.end === e || r.end === 1 / 0) && r.value === n; } const Vo = { offsetHeight: "height", offsetWidth: "width" }, Pt = K( ([{ log: t }, { recalcInProgress: e }]) => { const n = U(), o = U(), r = ht(o, 0), s = U(), i = U(), l = C(0), u = C([]), d = C(void 0), m = C(void 0), S = C(void 0), h = C(void 0), T = C((c, p) => zt(c, Vo[p])), w = C(void 0), R = C(0), g = Ro(), f = ht( x(n, $(u, t, R), Lt(zo, g), J()), g ), a = ht( x( u, J(), Lt((c, p) => ({ current: p, prev: c.current }), { current: [], prev: [] }), k(({ prev: c }) => c) ), [] ); F( x( u, P((c) => c.length > 0), $(f, R), k(([c, p, v]) => { const O = c.reduce((B, W, _) => yt(B, W, ue(W, p.offsetTree, v) || _), Zt()); return { ...p, groupIndices: c, groupOffsetTree: O }; }) ), f ), F( x( o, $(f), P(([c, { lastIndex: p }]) => c < p), k(([c, { lastIndex: p, lastSize: v }]) => [ { endIndex: p, size: v, startIndex: c } ]) ), n ), F(d, m); const I = ht( x( d, k((c) => c === void 0) ), !0 ); F( x( m, P((c) => c !== void 0 && X(rt(f).sizeTree)), k((c) => { const p = rt(S), v = rt(u).length > 0; return p ? v ? [ { endIndex: 0, size: p, startIndex: 0 }, { endIndex: 1, size: c, startIndex: 1 } ] : [] : [{ endIndex: 0, size: c, startIndex: 0 }]; }) ), n ), F( x( h, P((c) => c !== void 0 && c.length > 0 && X(rt(f).sizeTree)), k((c) => { const p = []; let v = c[0], O = 0; for (let B = 1; B < c.length; B++) { const W = c[B]; W !== v && (p.push({ endIndex: B - 1, size: v, startIndex: O }), v = W, O = B); } return p.push({ endIndex: c.length - 1, size: v, startIndex: O }), p; }) ), n ), F( x( u, $(S, m), P(([, c, p]) => c !== void 0 && p !== void 0), k(([c, p, v]) => { const O = []; for (let B = 0; B < c.length; B++) { const W = c[B], _ = c[B + 1]; O.push({ startIndex: W, endIndex: W, size: p }), _ !== void 0 && O.push({ startIndex: W + 1, endIndex: _ - 1, size: v }); } return O; }) ), n ); const b = bt( x( n, $(f), Lt( ({ sizes: c }, [p, v]) => ({ changed: v !== c, sizes: v }), { changed: !1, sizes: g } ), k((c) => c.changed) ) ); Y( x( l, Lt( (c, p) => ({ diff: c.prev - p, prev: p }), { diff: 0, prev: 0 } ), k((c) => c.diff) ), (c) => { const { groupIndices: p } = rt(f); if (c > 0) D(e, !0), D(s, c + pn(c, p)); else if (c < 0) { const v = rt(a); v.length > 0 && (c -= pn(-c, v)), D(i, c); } } ), Y(x(l, $(t)), ([c, p]) => { c < 0 && p( "`firstItemIndex` prop should not be set to less than zero. If you don't know the total count, just use a very high value", { firstItemIndex: l }, Ct.ERROR ); }); const y = bt(s); F( x( s, $(f), k(([c, p]) => { const v = p.groupIndices.length > 0, O = [], B = p.lastSize; if (v) { const W = le(p.sizeTree, 0); let _ = 0, j = 0; for (; _ < c; ) { const M = p.groupIndices[j], et = p.groupIndices.length === j + 1 ? 1 / 0 : p.groupIndices[j + 1] - M - 1; O.push({ endIndex: M, size: W, startIndex: M }), O.push({ endIndex: M + 1 + et - 1, size: B, startIndex: M + 1 }), j++, _ += et + 1; } const L = Dt(p.sizeTree); return _ !== c && L.shift(), L.reduce( (M, { k: et, v: wt }) => { let ft = M.ranges; return M.prevSize !== 0 && (ft = [ ...M.ranges, { endIndex: et + c - 1, size: M.prevSize, startIndex: M.prevIndex } ]), { prevIndex: et + c, prevSize: wt, ranges: ft }; }, { prevIndex: c, prevSize: 0, ranges: O } ).ranges; } return Dt(p.sizeTree).reduce( (W, { k: _, v: j }) => ({ prevIndex: _ + c, prevSize: j, ranges: [...W.ranges, { endIndex: _ + c - 1, size: W.prevSize, startIndex: W.prevIndex }] }), { prevIndex: 0, prevSize: B, ranges: [] } ).ranges; }) ), n ); const z = bt( x( i, $(f, R), k(([c, { offsetTree: p }, v]) => { const O = -c; return ue(O, p, v); }) ) ); return F( x( i, $(f, R), k(([c, p, v]) => { if (p.groupIndices.length > 0) { if (X(p.sizeTree)) return p; let B = Zt(); const W = rt(a); let _ = 0, j = 0, L = 0; for (; _ < -c; ) { L = W[j]; const M = W[j + 1] - L - 1; j++, _ += M + 1; } if (B = Dt(p.sizeTree).reduce((M, { k: et, v: wt }) => yt(M, Math.max(0, et + c), wt), B), _ !== -c) { const M = le(p.sizeTree, L); B = yt(B, 0, M); const et = kt(p.sizeTree, -c + 1)[1]; B = yt(B, 1, et); } return { ...p, sizeTree: B, ...Ge(p.offsetTree, 0, B, v) }; } else { const B = Dt(p.sizeTree).reduce((W, { k: _, v: j }) => yt(W, Math.max(0, _ + c), j), Zt()); return { ...p, sizeTree: B, ...Ge(p.offsetTree, 0, B, v) }; } }) ), f ), { beforeUnshiftWith: y, // input data: w, defaultItemSize: m, firstItemIndex: l, fixedItemSize: d, fixedGroupSize: S, gap: R, groupIndices: u, heightEstimates: h, itemSize: T, listRefresh: b, shiftWith: i, shiftWithOffset: z, sizeRanges: n, // output sizes: f, statefulTotalCount: r, totalCount: o, trackItemSizes: I, unshiftWith: s }; }, tt(Wt, De), { singleton: !0 } ); function Po(t) { return t.reduce( (e, n) => (e.groupIndices.push(e.totalCount), e.totalCount += n + 1, e), { groupIndices: [], totalCount: 0 } ); } const Dn = K( ([{ groupIndices: t, sizes: e, totalCount: n }, { headerHeight: o, scrollTop: r }]) => { const s = U(), i = U(), l = bt(x(s, k(Po))); return F( x( l, k((u) => u.totalCount) ), n ), F( x( l, k((u) => u.groupIndices) ), t ), F( x( ut(r, e, o), P(([u, d]) => be(d)), k(([u, d, m]) => kt(d.groupOffsetTree, Math.max(u - m, 0), "v")[0]), J(), k((u) => [u]) ), i ), { groupCounts: s, topItemsIndexes: i }; }, tt(Pt, It) ), _t = K( ([{ log: t }]) => { const e = C(!1), n = bt( x( e, P((o) => o), J() ) ); return Y(e, (o) => { o && rt(t)("props updated", {}, Ct.DEBUG); }), { didMount: n, propsReady: e }; }, tt(Wt), { singleton: !0 } ), Go = typeof document < "u" && "scrollBehavior" in document.documentElement.style; function $n(t) { const e = typeof t == "number" ? { index: t } : t; return e.align || (e.align = "start"), (!e.behavior || !Go) && (e.behavior = "auto"), e.offset || (e.offset = 0), e; } const me = K( ([ { gap: t, listRefresh: e, sizes: n, totalCount: o }, { fixedFooterHeight: r, fixedHeaderHeight: s, footerHeight: i, headerHeight: l, scrollingInProgress: u, scrollTo: d, smoothScrollTargetReached: m, viewportHeight: S }, { log: h } ]) => { const T = U(), w = U(), R = C(0); let g = null, f = null, a = null; function I() { g && (g(), g = null), a && (a(), a = null), f && (clearTimeout(f), f = null), D(u, !1); } return F( x( T, $(n, S, o, R, l, i, h), $(t, s, r), k( ([ [b, y, z, c, p, v, O, B], W, _, j ]) => { const L = $n(b), { align: xt, behavior: M, offset: et } = L, wt = c - 1, ft = Nn(L, y, wt); let St = ue(ft, y.offsetTree, W) + v; xt === "end" ? (St += _ + kt(y.sizeTree, ft)[1] - z + j, ft === wt && (St += O)) : xt === "center" ? St += (_ + kt(y.sizeTree, ft)[1] - z + j) / 2 : St -= p, et && (St += et); const Mt = (pt) => { I(), pt ? (B("retrying to scroll to", { location: b }, Ct.DEBUG), D(T, b)) : (D(w, !0), B("list did not change, scroll successful", {}, Ct.DEBUG)); }; if (I(), M === "smooth") { let pt = !1; a = Y(e, (qt) => { pt = pt || qt; }), g = Et(m, () => { Mt(pt); }); } else g = Et(x(e, Mo(150)), Mt); return f = setTimeout(() => { I(); }, 1200), D(u, !0), B("scrolling from index to", { behavior: M, index: ft, top: St }, Ct.DEBUG), { behavior: M, top: St }; } ) ), d ), { scrollTargetReached: w, scrollToIndex: T, topListHeight: R }; }, tt(Pt, It, Wt), { singleton: !0 } ); function Mo(t) { return (e) => { const n = setTimeout(() => { e(!1); }, t); return (o) => { o && (e(!0), clearTimeout(n)); }; }; } function Ue(t, e) { t == 0 ? e() : requestAnimationFrame(() => { Ue(t - 1, e); }); } function Ke(t, e) { const n = e - 1; return typeof t == "number" ? t : t.index === "LAST" ? n : t.index; } const pe = K( ([{ defaultItemSize: t, listRefresh: e, sizes: n }, { scrollTop: o }, { scrollTargetReached: r, scrollToIndex: s }, { didMount: i }]) => { const l = C(!0), u = C(0), d = C(!0); return F( x( i, $(u), P(([m, S]) => !!S), Ft(!1) ), l ), F( x( i, $(u), P(([m, S]) => !!S), Ft(!1) ), d ), Y( x( ut(e, i), $(l, n, t, d), P(([[, m], S, { sizeTree: h }, T, w]) => m && (!X(h) || Ae(T)) && !S && !w), $(u) ), ([, m]) => { Et(r, () => { D(d, !0); }), Ue(4, () => { Et(o, () => { D(l, !0); }), D(s, m); }); } ), { initialItemFinalLocationReached: d, initialTopMostItemIndex: u, scrolledToInitialItem: l }; }, tt(Pt, It, me, _t), { singleton: !0 } ); function Un(t, e) { return Math.abs(t - e) < 1.01; } const ae = "up", oe = "down", Ao = "none", Wo = { atBottom: !1, notAtBottomBecause: "NOT_SHOWING_LAST_ITEM", state: { offsetBottom: 0, scrollHeight: 0, scrollTop: 0, viewportHeight: 0 } }, _o = 0, he = K(([{ footerHeight: t, headerHeight: e, scrollBy: n, scrollContainerState: o, scrollTop: r, viewportHeight: s }]) => { const i = C(!1), l = C(!0), u = U(), d = U(), m = C(4), S = C(_o), h = ht( x( Fe(x(V(r), Kt(1), Ft(!0)), x(V(r), Kt(1), Ft(!1), dn(100))), J() ), !1 ), T = ht( x(Fe(x(n, Ft(!0)), x(n, Ft(!1), dn(200))), J()), !1 ); F( x( ut(V(r), V(S)), k(([a, I]) => a <= I), J() ), l ), F(x(l, Gt(50)), d); const w = bt( x( ut(o, V(s), V(e), V(t), V(m)), Lt((a, [{ scrollHeight: I, scrollTop: b }, y, z, c, p]) => { const v = b + y - I > -p, O = { scrollHeight: I, scrollTop: b, viewportHeight: y }; if (v) { let W, _; return b > a.state.scrollTop ? (W = "SCROLLED_DOWN", _ = a.state.scrollTop - b) : (W = "SIZE_DECREASED", _ = a.state.scrollTop - b || a.scrollTopDelta), { atBottom: !0, atBottomBecause: W, scrollTopDelta: _, state: O }; } let B; return O.scrollHeight > a.state.scrollHeight ? B = "SIZE_INCREASED" : y < a.state.viewportHeight ? B = "VIEWPORT_HEIGHT_DECREASING" : b < a.state.scrollTop ? B = "SCROLLING_UPWARDS" : B = "NOT_FULLY_SCROLLED_TO_LAST_ITEM_BOTTOM", { atBottom: !1, notAtBottomBecause: B, state: O }; }, Wo), J((a, I) => a && a.atBottom === I.atBottom) ) ), R = ht( x( o, Lt( (a, { scrollHeight: I, scrollTop: b, viewportHeight: y }) => { if (Un(a.scrollHeight, I)) return { changed: !1, jump: 0, scrollHeight: I, scrollTop: b }; { const z = I - (b + y) < 1; return a.scrollTop !== b && z ? { changed: !0, jump: a.scrollTop - b, scrollHeight: I, scrollTop: b } : { changed: !0, jump: 0, scrollHeight: I, scrollTop: b }; } }, { changed: !1, jump: 0, scrollHeight: 0, scrollTop: 0 } ), P((a) => a.changed), k((a) => a.jump) ), 0 ); F( x( w, k((a) => a.atBottom) ), i ), F(x(i, Gt(50)), u); const g = C(oe); F( x( o, k(({ scrollTop: a }) => a), J(), Lt( (a, I) => rt(T) ? { direction: a.direction, prevScrollTop: I } : { direction: I < a.prevScrollTop ? ae : oe, prevScrollTop: I }, { direction: oe, prevScrollTop: 0 } ), k((a) => a.direction) ), g ), F(x(o, Gt(50), Ft(Ao)), g); const f = C(0); return F( x( h, P((a) => !a), Ft(0) ), f ), F( x( r, Gt(100), $(h), P(([a, I]) => I), Lt(([a, I], [b]) => [I, b], [0, 0]), k(([a, I]) => I - a) ), f ), { atBottomState: w, atBottomStateChange: u, atBottomThreshold: m, atTopStateChange: d, atTopThreshold: S, isAtBottom: i, isAtTop: l, isScrolling: h, lastJumpDueToItemResize: R, scrollDirection: g, scrollVelocity: f }; }, tt(It)), de = "top", fe = "bottom", hn = "none"; function gn(t, e, n) { return typeof t == "number" ? n === ae && e === de || n === oe && e === fe ? t : 0 : n === ae ? e === de ? t.main : t.reverse : e === fe ? t.main : t.reverse; } function In(t, e) { var n; return typeof t == "number" ? t : (n = t[e]) != null ? n : 0; } const je = K( ([{ deviation: t, fixedHeaderHeight: e, headerHeight: n, scrollTop: o, viewportHeight: r }]) => { const s = U(), i = C(0), l = C(0), u = C(0), d = ht( x( ut( V(o), V(r), V(n), V(s, ce), V(u), V(i), V(e), V(t), V(l) ), k( ([ m, S, h, [T, w], R, g, f, a, I ]) => { const b = m - a, y = g + f, z = Math.max(h - b, 0); let c = hn; const p = In(I, de), v = In(I, fe); return T -= a, T += h + f, w += h + f, w -= a, T > m + y - p && (c = ae), w < m - z + S + v && (c = oe), c !== hn ? [ Math.max(b - h - gn(R, de, c) - p, 0), b - z - f + S + gn(R, fe, c) + v ] : null; } ), P((m) => m != null), J(ce) ), [0, 0] ); return { increaseViewportBy: l, // input listBoundary: s, overscan: u, topListHeight: i, // output visibleRange: d }; }, tt(It), { singleton: !0 } ); function No(t, e, n) { if (be(e)) { const o = _n(t, e); return [ { index: kt(e.groupOffsetTree, o)[0], offset: 0, size: 0 }, { data: n == null ? void 0 : n[0], index: o, offset: 0, size: 0 } ]; } return [{ data: n == null ? void 0 : n[0], index: t, offset: 0, size: 0 }]; } const Be = { bottom: 0, firstItemIndex: 0, items: [], offsetBottom: 0, offsetTop: 0, top: 0, topItems: [], topListHeight: 0, totalCount: 0 }; function Te(t, e, n, o, r, s) { const { lastIndex: i, lastOffset: l, lastSize: u } = r; let d = 0, m = 0; if (t.length > 0) { d = t[0].offset; const R = t[t.length - 1]; m = R.offset + R.size; } const S = n - i, h = l + S * u + (S - 1) * o, T = d, w = h - m; return { bottom: m, firstItemIndex: s, items: xn(t, r, s), offsetBottom: w, offsetTop: d, top: T, topItems: xn(e, r, s), topListHeight: e.reduce((R, g) => g.size + R, 0), totalCount: n }; } function Kn(t, e, n, o, r, s) { let i = 0; if (n.groupIndices.length > 0) for (const m of n.groupIndices) { if (m - i >= t) break; i++; } const l = t + i, u = Ke(e, l), d = Array.from({ length: l }).map((m, S) => ({ data: s[S + u], index: S + u, offset: 0, size: 0 })); return Te(d, [], l, r, n, o); } function xn(t, e, n) { if (t.length === 0) return []; if (!be(e)) return t.map((d) => ({ ...d, index: d.index + n, originalIndex: d.index })); const o = t[0].index, r = t[t.length - 1].index, s = [], i = Xt(e.groupOffsetTree, o, r); let l, u = 0; for (const d of t) { (!l || l.end < d.index) && (l = i.shift(), u = e.groupIndices.indexOf(l.start)); let m; d.index === l.start ? m = { index: u, type: "group" } : m = { groupIndex: u, index: d.index - (u + 1) + n }, s.push({ ...m, data: d.data, offset: d.offset, originalIndex: d.index, size: d.size }); } return s; } function Sn(t, e) { var n; return t === void 0 ? 0 : typeof t == "number" ? t : (n = t[e]) != null ? n : 0; } const jt = K( ([ { data: t, firstItemIndex: e, gap: n, sizes: o, totalCount: r }, s, { listBoundary: i, topListHeight: l, visibleRange: u }, { initialTopMostItemIndex: d, scrolledToInitialItem: m }, { topListHeight: S }, h, { didMount: T }, { recalcInProgress: w } ]) => { const R = C([]), g = C(0), f = U(), a = C(0); F(s.topItemsIndexes, R); const I = ht( x( ut( T, w, V(u, ce), V(r), V(o), V(d), m, V(R), V(e), V(n), V(a), t ), P(([c, p, , v, , , , , , , , O]) => { const B = O && O.length !== v; return c && !p && !B; }), k( ([ , , [c, p], v, O, B, W, _, j, L, xt, M ]) => { var q, at, gt, Tt; const et = O, { offsetTree: wt, sizeTree: ft } = et, St = rt(g); if (v === 0) return { ...Be, totalCount: v }; if (c === 0 && p === 0) return St === 0 ? { ...Be, totalCount: v } : Kn(St, B, O, j, L, M || []); if (X(ft)) return St > 0 ? null : Te( No(Ke(B, v), et, M), [], v, L, et, j ); const Mt = []; if (_.length > 0) { const st = _[0], it = _[_.length - 1]; let mt = 0; for (const lt of Xt(ft, st, it)) { const Z = lt.value, nt = Math.max(lt.start, st), vt = Math.min(lt.end, it); for (let ct = nt; ct <= vt; ct++) Mt.push({ data: M == null ? void 0 : M[ct], index: ct, offset: mt, size: Z }), mt += Z; } } if (!W) return Te([], Mt, v, L, et, j); const pt = _.length > 0 ? _[_.length - 1] + 1 : 0, qt = ko(wt, c, p, pt); if (qt.length === 0) return null; const ee = v - 1, Ot = ye([], (st) => { for (const it of qt) { const mt = it.value; let lt = mt.offset, Z = it.start; const nt = mt.size; if (mt.offset < c) { Z += Math.floor((c - mt.offset + L) / (nt + L)); const ct = Z - it.start; lt += ct * nt + ct * L; } Z < pt && (lt += (pt - Z) * nt, Z = pt); const vt = Math.min(it.end, ee); for (let ct = Z; ct <= vt && !(lt >= p); ct++) st.push({ data: M == null ? void 0 : M[ct], index: ct, offset: lt, size: nt }), lt += nt + L; } }), ne = Sn(xt, de), H = Sn(xt, fe); if (Ot.length > 0 && (ne > 0 || H > 0)) { const st = Ot[0], it = Ot[Ot.length - 1]; if (ne > 0 && st.index > pt) { const mt = Math.min(ne, st.index - pt), lt = []; let Z = st.offset; for (let nt = st.index - 1; nt >= st.index - mt; nt--) { const ct = (at = (q = Xt(ft, nt, nt)[0]) == null ? void 0 : q.value) != null ? at : st.size; Z -= ct + L, lt.unshift({ data: M == null ? void 0 : M[nt], index: nt, offset: Z, size: ct }); } Ot.unshift(...lt); } if (H > 0 && it.index < ee) { const mt = Math.min(H, ee - it.index); let lt = it.offset + it.size + L; for (let Z = it.index + 1; Z <= it.index + mt; Z++) { const vt = (Tt = (gt = Xt(ft, Z, Z)[0]) == null ? void 0 : gt.value) != null ? Tt : it.size; Ot.push({ data: M == null ? void 0 : M[Z], index: Z, offset: lt, size: vt }), lt += vt + L; } } } return Te(Ot, Mt, v, L, et, j); } ), //@ts-expect-error filter needs to be fixed P((c) => c !== null), J() ), Be ); F( x( t, P(Ae), k((c) => c == null ? void 0 : c.length) ), r ), F( x( I, k((c) => c.topListHeight) ), S ), F(S, l), F( x( I, k((c) => [c.top, c.bottom]) ), i ), F( x( I, k((c) => c.items) ), f ); const b = bt( x( I, P(({ items: c }) => c.length > 0), $(r, t), P(([{ items: c }, p]) => c[c.length - 1].originalIndex === p - 1), k(([, c, p]) => [c - 1, p]), J(ce), k(([c]) => c) ) ), y = bt( x( I, Gt(200), P(({ items: c, topItems: p }) => c.length > 0 && c[0].originalIndex === p.length), k(({ items: c }) => c[0].index), J() ) ), z = bt( x( I, P(({ items: c }) => c.length > 0), k(({ items: c }) => { let p = 0, v = c.length - 1; for (; c[p].type === "group" && p < v; ) p++; for (; c[v].type === "group" && v > p; ) v--; return { endIndex: c[v].index, startIndex: c[p].index }; }), J(An) ) ); return { endReached: b, initialItemCount: g, itemsRendered: f, listState: I, minOverscanItemCount: a, rangeChanged: z, startReached: y, topItemsIndexes: R, ...h }; }, tt( Pt, Dn, je, pe, me, he, _t, De ), { singleton: !0 } ), jn = K( ([{ fixedFooterHeight: t, fixedHeaderHeight: e, footerHeight: n, headerHeight: o }, { listState: r }]) => { const s = U(), i = ht( x( ut(n, t, o, e, r), k(([l, u, d, m, S]) => l + u + d + m + S.offsetBottom + S.bottom) ), 0 ); return F(V(i), s), { totalListHeight: i, totalListHeightChanged: s }; }, tt(It, jt), { singleton: !0 } ), Do = K( ([{ viewportHeight: t }, { totalListHeight: e }]) => { const n = C(!1), o = ht( x( ut(n, t, e), P(([r]) => r), k(([, r, s]) => Math.max(0, r - s)), Gt(0), J() ), 0 ); return { alignToBottom: n, paddingTopAddition: o }; }, tt(It, jn), { singleton: !0 } ), qn = K(() => ({ context: C(null) })), $o = ({ itemBottom: t, itemTop: e, locationParams: { align: n, behavior: o, ...r }, viewportBottom: s, viewportTop: i }) => e < i ? { ...r, align: n != null ? n : "start", behavior: o } : t > s ? { ...r, align: n != null ? n : "end", behavior: o } : null, Yn = K( ([ { gap: t, sizes: e, totalCount: n }, { fixedFooterHeight: o, fixedHeaderHeight: r, headerHeight: s, scrollingInProgress: i, scrollTop: l, viewportHeight: u }, { scrollToIndex: d } ]) => { const m = U(); return F( x( m, $(e, u, n, s, r, o, l), $(t), k(([[S, h, T, w, R, g, f, a], I]) => { const { align: b, behavior: y, calculateViewLocation: z = $o, done: c, ...p } = S, v = Nn(S, h, w - 1), O = ue(v, h.offsetTree, I) + R + g, B = O + kt(h.sizeTree, v)[1], W = a + g, _ = a + T - f, j = z({ itemBottom: B, itemTop: O, locationParams: { align: b, behavior: y, ...p }, viewportBottom: _, viewportTop: W }); return j ? c && Et( x( i, P((L) => !L), // skips the initial publish of false, and the cleanup call. // but if scrollingInProgress is true, we skip the initial publish. Kt(rt(i) ? 1 : 2) ), c ) : c == null || c(), j; }), P((S) => S !== null) ), d ), { scrollIntoView: m }; }, tt(Pt, It, me, jt, Wt), { singleton: !0 } ); function Tn(t) { return t ? t === "smooth" ? "smooth" : "auto" : !1; } const Uo = (t, e) => typeof t == "function" ? Tn(t(e)) : e && Tn(t), Ko = K( ([ { listRefresh: t, totalCount: e, fixedItemSize: n, data: o }, { atBottomState: r, isAtBottom: s }, { scrollToIndex: i }, { scrolledToInitialItem: l }, { didMount: u, propsReady: d }, { log: m }, { scrollingInProgress: S }, { context: h }, { scrollIntoView: T } ]) => { const w = C(!1), R = U(); let g = null; function f(y) { D(i, { align: "end", behavior: y, index: "LAST" }); } Y( x( ut(x(V(e), Kt(1)), u), $(V(w), s, l, S), k(([[y, z], c, p, v, O]) => { let B = z && v, W = "auto"; return B && (W = Uo(c, p || O), B = B && !!W), { followOutputBehavior: W, shouldFollow: B, totalCount: y }; }), P(({ shouldFollow: y }) => y) ), ({ followOutputBehavior: y, totalCount: z }) => { g && (g(), g = null), rt(n) ? requestAnimationFrame(() => { rt(m)("following output to ", { totalCount: z }, Ct.DEBUG), f(y); }) : g = Et(t, () => { rt(m)("following output to ", { totalCount: z }, Ct.DEBUG), f(y), g = null; }); } ); function a(y) { const z = Et(r, (c) => { y && !c.atBottom && c.notAtBottomBecause === "SIZE_INCREASED" && !g && (rt(m)("scrolling to bottom due to increased size", {}, Ct.DEBUG), f("auto")); }); setTimeout(z, 100); } Y( x( ut(V(w), e, d), P(([y, , z]) => y && z), Lt( ({ value: y }, [, z]) => ({ refreshed: y === z, value: z }), { refreshed: !1, value: 0 } ), P(({ refreshed: y }) => y), $(w, e) ), ([, y]) => { rt(l) && a(y !== !1); } ), Y(R, () => { a(rt(w) !== !1); }), Y(ut(V(w), r), ([y, z]) => { y && !z.atBottom && z.notAtBottomBecause === "VIEWPORT_HEIGHT_DECREASING" && f("auto"); }); const I = C(null), b = U(); return F( Fe( x( V(o), k((y) => { var z; return (z = y == null ? void 0 : y.length) != null ? z : 0; }) ), x(V(e)) ), b ), Y( x( ut(x(b, Kt(1)), u), $(V(I), l, S, h), k(([[y, z], c, p, v, O]) => z && p && (c == null ? void 0 : c({ context: O, totalCount: y, scrollingInProgress: v }))), P((y) => !!y), Gt(0) ), (y) => { g && (g(), g = null), rt(n) ? requestAnimationFrame(() => { rt(m)("scrolling into view", {}), D(T, y); }) : g = Et(t, () => { rt(m)("scrolling into view", {}), D(T, y), g = null; }); } ), { autoscrollToBottom: R, followOutput: w, scrollIntoViewOnChange: I }; }, tt( Pt, he, me, pe, _t, Wt, It, qn, Yn ) ), jo = K( ([{ data: t, firstItemIndex: e, gap: n, sizes: o }, { initialTopMostItemIndex: r }, { initialItemCount: s, listState: i }, { didMount: l }]) => (F( x( l, $(s), P(([, u]) => u !== 0), $(r, o, e, n, t), k(([[, u], d, m, S, h, T = []]) => Kn(u, d, m, S, h, T)) ), i ), {}), tt(Pt, pe, jt, _t), { singleton: !0 } ), qo = K( ([{ didMount: t }, { scrollTo: e }, { listState: n }]) => { const o = C(0); return Y( x( t, $(o), P(([, r]) => r !== 0), k(([, r]) => ({ top: r })) ), (r) => { Et( x( n, Kt(1), P((s) => s.items.length > 1) ), () => { requestAnimationFrame(() => { D(e, r); }); } ); } ), { initialScrollTop: o }; }, tt(_t, It, jt), { singleton: !0 } ), Zn = K( ([{ scrollVelocity: t }]) => { const e = C(!1), n = U(), o = C(!1); return F( x( t, $(o, e, n), P(([r, s]) => !!s), k(([r, s, i, l]) => { const { enter: u, exit: d } = s; if (i) { if (d(r, l)) return !1; } else if (u(r, l)) return !0; return i; }), J() ), e ), Y( x(ut(e, t, n), $(o)), ([[r, s, i], l]) => { r && l && l.change && l.change(s, i); } ), { isSeeking: e, scrollSeekConfiguration: o, scrollSeekRangeChanged: n, scrollVelocity: t }; }, tt(he), { singleton: !0 } ), qe = K(([{ scrollContainerState: t, scrollTo: e }]) => { const n = U(), o = U(), r = U(), s = C(!1), i = C(void 0); return F( x( ut(n, o), k(([{ scrollHeight: l, scrollTop: u, viewportHeight: d }, { offsetTop: m }]) => ({ scrollHeight: l, scrollTop: Math.max(0, u - m), viewportHeight: d })) ), t ), F( x( e, $(o), k(([l, { offsetTop: u }]) => ({ ...l, top: l.top + u })) ), r ), { customScrollParent: i, // config useWindowScroll: s, // input windowScrollContainerState: n, // signals windowScrollTo: r, windowViewportRect: o }; }, tt(It)), Yo = K( ([ { sizeRanges: t, sizes: e }, { headerHeight: n, scrollTop