Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

react-virtuoso

Package Overview
Dependencies
Maintainers
1
Versions
288
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-virtuoso - npm Package Compare versions

Comparing version 0.4.5 to 0.5.0

dist/ItemHeightPublisher.d.ts

3

dist/GroupedVirtuoso.d.ts
import { VirtuosoProps, VirtuosoState } from './Virtuoso';
import React, { ReactElement, PureComponent } from 'react';
import { TScrollLocation } from './VirtuosoStore';
import { ListItem } from 'GroupIndexTransposer';

@@ -8,2 +9,3 @@ declare type GroupedVirtuosoProps = Pick<VirtuosoProps, Exclude<keyof VirtuosoProps, 'totalCount' | 'topItems' | 'item'>> & {

item: (index: number, groupIndex: number) => ReactElement;
groupIndices?: (indices: number[]) => void;
};

@@ -14,4 +16,5 @@ export declare class GroupedVirtuoso extends PureComponent<GroupedVirtuosoProps, VirtuosoState> {

protected itemRender: (item: ListItem) => React.ReactElement<any, string | ((props: any) => React.ReactElement<any, string | any | (new (props: any) => React.Component<any, any, any>)> | null) | (new (props: any) => React.Component<any, any, any>)>;
scrollToIndex(location: TScrollLocation): void;
render(): JSX.Element;
}
export {};

3

dist/OffsetList.d.ts

@@ -15,2 +15,3 @@ import { AATree } from './AATree';

offsetTree: AATree<OffsetValue>;
private nanIndices;
static create(): OffsetList;

@@ -20,3 +21,3 @@ private constructor();

insert(start: number, end: number, size: number): OffsetList;
insertException(index: number, value: number): OffsetList;
insertSpots(spotIndexes: number[], value: number): OffsetList;
offsetOf(index: number): number;

@@ -23,0 +24,0 @@ itemAt(index: number): Item;

@@ -53,3 +53,3 @@ 'use strict';

}
function subject(initial) {
function subject(initial, distinct = true) {
let subscribers = [];

@@ -59,3 +59,3 @@ let val = initial;

const next = newVal => {
if (newVal !== val) {
if (!distinct || newVal !== val) {
val = newVal;

@@ -681,23 +681,33 @@ subscribers.forEach(subscriber => subscriber(newVal));

class OffsetList {
static create() {
return new OffsetList(AATree.empty());
}
constructor(rangeTree) {
this.nanIndices = [];
this.rangeTree = rangeTree;
let offsetTree = AATree.empty();
let offset = 0;
const ranges = rangeTree.ranges();
let nanFound = false;
for (const {
for (let {
start: startIndex,
end: endIndex,
value: size
} of rangeTree.ranges()) {
offsetTree = offsetTree.insert(offset, {
startIndex,
endIndex: endIndex,
size
});
} of ranges) {
if (isNaN(size)) {
this.nanIndices.push(startIndex);
if (endIndex !== Infinity) {
if (!nanFound) {
offsetTree = offsetTree.insert(offset, {
startIndex,
endIndex: Infinity,
size
});
}
nanFound = true;
} else if (!nanFound) {
offsetTree = offsetTree.insert(offset, {
startIndex,
endIndex: endIndex,
size
});
offset += (endIndex - startIndex + 1) * size;

@@ -710,2 +720,6 @@ }

static create() {
return new OffsetList(AATree.empty());
}
empty() {

@@ -720,2 +734,11 @@ return this.rangeTree.empty();

return new OffsetList(tree.insert(0, size));
} // tree is in non-complete state - we know the group sizes, but not the item sizes
if (this.nanIndices.length && this.nanIndices.indexOf(start) > -1) {
for (const nanIndex of this.nanIndices) {
tree = tree.insert(nanIndex, size);
}
return new OffsetList(tree);
} // extend the range in both directions, so that we can get adjacent neighbours.

@@ -769,7 +792,13 @@ // if the previous / next ones have the same value as the one we are about to insert,

insertException(index, value) {
insertSpots(spotIndexes, value) {
if (this.empty()) {
return new OffsetList(this.rangeTree.insert(1, NaN).insert(index, value));
let tree = this.rangeTree;
for (const spot of spotIndexes) {
tree = tree.insert(spot, value).insert(spot + 1, NaN);
}
return new OffsetList(tree);
} else {
return this.insert(index, index, value);
throw new Error('attempting to overwrite non-empty tree');
}

@@ -916,3 +945,3 @@ }

end = Math.min(end, endIndex);
total += (end - start + 1) * size;
total += (end - start + 1) * (isNaN(size) ? 0 : size);
}

@@ -1056,2 +1085,3 @@

const stickyItems$ = subject([]);
const scrollToIndex$ = subject(undefined, false);

@@ -1065,3 +1095,3 @@ if (itemHeight) {

if (!itemHeight) {
itemHeights$.pipe(withLatestFrom(offsetList$.subscribe, stickyItems$.subscribe)).subscribe(([heights, offsetList, _]) => {
itemHeights$.pipe(withLatestFrom(offsetList$.subscribe, stickyItems$.subscribe)).subscribe(([heights, offsetList, stickyItems]) => {
let newList = offsetList;

@@ -1074,3 +1104,7 @@

} of heights) {
newList = newList.insert(start, end, size);
if (newList.empty() && start == end && stickyItems.indexOf(start) > -1) {
newList = newList.insertSpots(stickyItems, size);
} else {
newList = newList.insert(start, end, size);
}
}

@@ -1144,2 +1178,8 @@

const list$ = combineLatest(viewportHeight$.subscribe, scrollTop$.subscribe, topListHeight$.subscribe, listHeight$.subscribe, footerHeight$.subscribe, minListIndex$.subscribe, totalCount$.subscribe, offsetList$.subscribe).pipe(scan(listScanner(overscan), []));
/*
list$.subscribe(list => {
console.log(list)
})
*/
const endReached$ = subject(0);

@@ -1158,2 +1198,30 @@ let currentEndIndex = 0;

scrollTop$.pipe(skip(1), mapTo(false), debounceTime(200)).subscribe(isScrolling$.next);
const scrollTo$ = scrollToIndex$.pipe(withLatestFrom(offsetList$.subscribe, topListHeight$.subscribe, stickyItems$.subscribe, viewportHeight$.subscribe, totalCount$.subscribe), map(([location, offsetList, topListHeight, stickyItems, viewportHeight, totalCount]) => {
if (typeof location === 'number') {
location = {
index: location,
align: 'start'
};
}
let {
index,
align = 'start'
} = location;
index = Math.max(0, index, Math.min(totalCount - 1, index));
let offset = offsetList.offsetOf(index);
if (align == 'end') {
offset = offset - viewportHeight + offsetList.itemAt(index).size;
} else if (align === 'center') {
offset = Math.round(offset - viewportHeight / 2 + offsetList.itemAt(index).size / 2);
} else {
if (stickyItems.indexOf(index) === -1) {
offset -= topListHeight;
}
}
return offset;
}));
const groupIndices$ = stickyItems$.pipe();
return {

@@ -1168,2 +1236,3 @@ groupCounts: makeInput(groupCounts$),

totalCount: makeInput(totalCount$),
scrollToIndex: makeInput(scrollToIndex$),
list: makeOutput(list$),

@@ -1175,3 +1244,5 @@ topList: makeOutput(topList$),

isScrolling: makeOutput(isScrolling$),
stickyItems: makeOutput(stickyItems$)
stickyItems: makeOutput(stickyItems$),
groupIndices: makeOutput(groupIndices$),
scrollTo: makeOutput(scrollTo$)
};

@@ -1229,12 +1300,13 @@ };

};
const VirtuosoScroller = ({
children,
style
const DefaultScrollContainer = ({
className,
style,
reportScrollTop,
scrollTo,
children
}) => {
const {
scrollTop
} = React.useContext(VirtuosoContext);
const elRef = React.useRef(null);
const onScroll = React.useCallback(e => {
scrollTop(e.target.scrollTop);
reportScrollTop(e.target.scrollTop);
}, []);

@@ -1251,8 +1323,33 @@ const ref = React.useCallback(theRef => {

}, []);
scrollTo(scrollTop => {
const goTo = {
top: scrollTop
};
elRef.current.scrollTo(goTo);
});
return React__default.createElement("div", {
ref: ref,
style: style,
tabIndex: 0,
className: className
}, children);
};
const VirtuosoScroller = ({
children,
style,
className,
ScrollContainer = DefaultScrollContainer
}) => {
const {
scrollTop,
scrollTo
} = React.useContext(VirtuosoContext);
return React__default.createElement(ScrollContainer, {
style: { ...scrollerStyle,
...style
},
tabIndex: 0
reportScrollTop: scrollTop,
scrollTo: scrollTo,
className: className
}, children);

@@ -1326,3 +1423,5 @@ };

item,
fixedItemHeight
fixedItemHeight,
ScrollContainer,
className
}) => {

@@ -1379,3 +1478,5 @@ const {

return React__default.createElement(VirtuosoScroller, {
style: style
style: style,
ScrollContainer: ScrollContainer,
className: className
}, React__default.createElement("div", {

@@ -1405,5 +1506,7 @@ style: viewportStyle,

style,
className,
item,
footer,
itemHeight
itemHeight,
ScrollContainer
}) => {

@@ -1414,5 +1517,7 @@ return React__default.createElement(VirtuosoContext.Provider, {

style: style || {},
className: className,
item: item,
footer: footer,
fixedItemHeight: itemHeight !== undefined
fixedItemHeight: itemHeight !== undefined,
ScrollContainer: ScrollContainer
}));

@@ -1424,3 +1529,3 @@ };

this.itemRenderer = item => {
this.itemRender = item => {
return this.props.item(item.index);

@@ -1440,2 +1545,6 @@ };

scrollToIndex(location) {
this.state.scrollToIndex(location);
}
render() {

@@ -1445,5 +1554,7 @@ return React__default.createElement(VirtuosoPresentation, {

style: this.props.style,
item: this.itemRenderer,
className: this.props.className,
item: this.itemRender,
footer: this.props.footer,
itemHeight: this.props.itemHeight
itemHeight: this.props.itemHeight,
ScrollContainer: this.props.ScrollContainer
});

@@ -1473,5 +1584,10 @@ }

state.groupCounts(props.groupCounts);
state.groupIndices(props.groupIndices);
return null;
}
scrollToIndex(location) {
this.state.scrollToIndex(location);
}
render() {

@@ -1481,5 +1597,7 @@ return React__default.createElement(VirtuosoPresentation, {

style: this.props.style,
className: this.props.className,
item: this.itemRender,
footer: this.props.footer,
itemHeight: this.props.itemHeight
itemHeight: this.props.itemHeight,
ScrollContainer: this.props.ScrollContainer
});

@@ -1486,0 +1604,0 @@ }

@@ -1,2 +0,2 @@

"use strict";function e(e){return e&&"object"==typeof e&&"default"in e?e.default:e}var t=require("react"),r=e(t),n=e(require("resize-observer-polyfill"));const i=t.createContext(void 0);function s(e){return function(...t){const r=function(...e){return 0===e.length?(e,t)=>t(e):1===e.length?e[0]:(t,r)=>{let n=e=>r(e);e.slice().reverse().forEach(e=>{const t=n;n=(r=>e(r,t))}),n(t)}}(...t);return function(e,t){const r=r=>e(e=>t(e,r));return{subscribe:r,pipe:s(r)}}(e,r)}}function o(e){let t=[],r=e;const n=e=>(t.push(e),void 0!==r&&e(r),()=>{t=t.filter(t=>t!==e)});return{next:e=>{e!==r&&(r=e,t.forEach(t=>t(e)))},subscribe:n,pipe:s(n),subscribers:t}}function l(...e){const t=Array(e.length).fill(!1),r=Array(e.length);let n=[];const i=e=>{t.every(e=>e)&&e.forEach(e=>e(r))};e.forEach((e,s)=>{e(e=>{t[s]=!0,r[s]=e,i(n)})});const o=e=>(n.push(e),i([e]),()=>{n=n.filter(t=>t!==e)});return{subscribe:o,pipe:s(o)}}function u(e){return(t,r)=>{r(e(t))}}function a(e){return(t,r)=>r(e)}function h(e){return(t,r)=>{e>0?e--:r(t)}}function c(e){return(t,r)=>{e(t)&&r(t)}}function f(...e){const t=Array(e.length).fill(!1),r=Array(e.length);return e.forEach((e,n)=>{e(e=>{r[n]=e,t[n]=!0})}),(e,n)=>{t.every(e=>e)&&n([e,...r])}}class d{constructor(){this.level=0}rebalance(){return this}adjust(){return this}remove(){return this}find(){}findWith(){}findMax(){return-Infinity}findMaxValue(){}insert(e,t){return new m({key:e,value:t,level:1})}walkWithin(){return[]}walk(){return[]}ranges(){return[]}rangesWithin(){return[]}empty(){return!0}isSingle(){return!0}isInvariant(){return!0}keys(){return[]}}const p=new d;Object.freeze(p);class g extends Error{constructor(e){super(`Unreachable case: ${e}`)}}class m{constructor({key:e,value:t,level:r,left:n=p,right:i=p}){this.key=e,this.value=t,this.level=r,this.left=n,this.right=i}remove(e){const{left:t,right:r}=this;if(e===this.key){if(t.empty())return r;if(r.empty())return t;{const[e,r]=t.last();return this.clone({key:e,value:r,left:t.deleteLast()}).adjust()}}return e<this.key?this.clone({left:t.remove(e)}).adjust():this.clone({right:r.remove(e)}).adjust()}empty(){return!1}find(e){return e===this.key?this.value:e<this.key?this.left.find(e):this.right.find(e)}findWith(e){const t=e(this.value);switch(t){case-1:return this.left.findWith(e);case 0:return[this.key,this.value];case 1:return this.right.findWith(e);default:throw new g(t)}}findMax(e){if(this.key===e)return e;if(this.key<e){const t=this.right.findMax(e);return-Infinity===t?this.key:t}return this.left.findMax(e)}findMaxValue(e){if(this.key===e)return this.value;if(this.key<e){const t=this.right.findMaxValue(e);return void 0===t?this.value:t}return this.left.findMaxValue(e)}insert(e,t){return e===this.key?this.clone({key:e,value:t}):e<this.key?this.clone({left:this.left.insert(e,t)}).rebalance():this.clone({right:this.right.insert(e,t)}).rebalance()}walkWithin(e,t){const{key:r,value:n}=this;let i=[];return r>e&&(i=i.concat(this.left.walkWithin(e,t))),r>=e&&r<=t&&i.push({key:r,value:n}),r<=t&&(i=i.concat(this.right.walkWithin(e,t))),i}walk(){return[...this.left.walk(),{key:this.key,value:this.value},...this.right.walk()]}last(){return this.right.empty()?[this.key,this.value]:this.right.last()}deleteLast(){return this.right.empty()?this.left:this.clone({right:this.right.deleteLast()}).adjust()}clone(e){return new m({key:void 0!==e.key?e.key:this.key,value:void 0!==e.value?e.value:this.value,level:void 0!==e.level?e.level:this.level,left:void 0!==e.left?e.left:this.left,right:void 0!==e.right?e.right:this.right})}isSingle(){return this.level>this.right.level}rebalance(){return this.skew().split()}adjust(){const{left:e,right:t,level:r}=this;if(t.level>=r-1&&e.level>=r-1)return this;if(r>t.level+1){if(e.isSingle())return this.clone({level:r-1}).skew();if(e.empty()||e.right.empty())throw new Error("Unexpected empty nodes");return e.right.clone({left:e.clone({right:e.right.left}),right:this.clone({left:e.right.right,level:r-1}),level:r})}if(this.isSingle())return this.clone({level:r-1}).split();if(t.empty()||t.left.empty())throw new Error("Unexpected empty nodes");{const e=t.left,n=e.isSingle()?t.level-1:t.level;return e.clone({left:this.clone({right:e.left,level:r-1}),right:t.clone({left:e.right,level:n}).split(),level:e.level+1})}}isInvariant(){const{left:e,right:t,level:r}=this;return r===e.level+1&&((r===t.level||r===t.level+1)&&(!(!t.empty()&&r<=t.right.level)&&(e.isInvariant()&&t.isInvariant())))}keys(){return[...this.left.keys(),this.key,...this.right.keys()]}ranges(){return this.toRanges(this.walk())}rangesWithin(e,t){return this.toRanges(this.walkWithin(e,t))}toRanges(e){if(0===e.length)return[];const t=e[0];let{key:r,value:n}=t;const i=[];for(let t=1;t<=e.length;t++){let s=e[t],o=s?s.key-1:Infinity;i.push({start:r,end:o,value:n}),s&&(r=s.key,n=s.value)}return i}split(){const{right:e,level:t}=this;return e.empty()||e.right.empty()||e.level!=t||e.right.level!=t?this:e.clone({left:this.clone({right:e.left}),level:t+1})}skew(){const{left:e}=this;return e.empty()||e.level!==this.level?this:e.clone({right:this.clone({left:e.right})})}}class v{constructor(e){this.root=e}static empty(){return new v(p)}find(e){return this.root.find(e)}findMax(e){return this.root.findMax(e)}findMaxValue(e){if(this.empty())throw new Error("Searching for max value in an empty tree");return this.root.findMaxValue(e)}findWith(e){return this.root.findWith(e)}insert(e,t){return new v(this.root.insert(e,t))}remove(e){return new v(this.root.remove(e))}empty(){return this.root.empty()}keys(){return this.root.keys()}walk(){return this.root.walk()}walkWithin(e,t){let r=this.root.findMax(e);return this.root.walkWithin(r,t)}ranges(){return this.root.ranges()}rangesWithin(e,t){let r=this.root.findMax(e);return this.root.rangesWithin(r,t)}isInvariant(){return this.root.isInvariant()}}class y{static create(){return new y(v.empty())}constructor(e){this.rangeTree=e;let t=v.empty(),r=0;for(const{start:n,end:i,value:s}of e.ranges())t=t.insert(r,{startIndex:n,endIndex:i,size:s}),Infinity!==i&&(r+=(i-n+1)*s);this.offsetTree=t}empty(){return this.rangeTree.empty()}insert(e,t,r){let n=this.rangeTree;if(n.empty())return new y(n.insert(0,r));const i=n.rangesWithin(e-1,t+1);if(i.some(n=>n.start===e&&(n.end===t||Infinity===n.end)&&n.value===r))return this;let s=!1,o=!1;for(const{start:e,end:l,value:u}of i)s?(t>=e||r===u)&&(n=n.remove(e)):(o=u!==r,s=!0),l>t&&t>=e&&(u===r||isNaN(u)||(n=n.insert(t+1,u)));return o&&(n=n.insert(e,r)),n===this.rangeTree?this:new y(n)}insertException(e,t){return this.empty()?new y(this.rangeTree.insert(1,NaN).insert(e,t)):this.insert(e,e,t)}offsetOf(e){if(this.offsetTree.empty())return 0;const t=this.offsetTree.findWith(t=>t.startIndex>e?-1:t.endIndex<e?1:0);if(t){const[r,{startIndex:n,size:i}]=t;return r+(e-n)*i}throw new Error(`Requested offset outside of the known ones, index: ${e}`)}itemAt(e){const t=this.rangeTree.findMaxValue(e);return{index:e,size:t,offset:NaN}}indexRange(e,t){if(0===t)return[];if(this.rangeTree.empty())return[{index:0,size:0,offset:NaN}];const r=this.rangeTree.rangesWithin(e,t),n=[];for(const i of r){const r=Math.max(e,i.start),s=void 0===i.end?Infinity:i.end,o=Math.min(t,s);for(let e=r;e<=o;e++)n.push({index:e,size:i.value,offset:NaN})}return n}range(e,t,r=0,n=Infinity){if(this.offsetTree.empty())return[{index:0,size:0,offset:0}];const i=this.offsetTree.rangesWithin(e,t),s=[];for(let{start:o,value:{startIndex:l,endIndex:u,size:a}}of i){let i=o,h=l;if(o<e&&(h+=Math.floor((e-o)/a),i+=(h-l)*a),h<r&&(i+=(r-h)*a,h=r),isNaN(a))return s.push({index:h,size:0,offset:i}),s;u=Math.min(u,n);for(let e=h;e<=u&&!(i>t);e++)s.push({index:e,size:a,offset:i}),i+=a}return s}total(e){const t=this.rangeTree.rangesWithin(0,e);let r=0;for(let{start:n,end:i,value:s}of t)i=Math.min(i,e),r+=(i-n+1)*s;return r}getOffsets(e){let t=v.empty();return e.forEach(e=>{const r=this.offsetOf(e);t=t.insert(r,e)}),new x(t)}}class x{constructor(e){this.tree=e}findMaxValue(e){return this.tree.findMaxValue(e)}empty(){return this.tree.empty()}}class b{transpose(e){return e.map(e=>({groupIndex:0,index:e.index,offset:e.offset,size:e.size,transposedIndex:e.index,type:"item"}))}}class k{constructor(e){this.count=e.reduce((e,t)=>e+t+1,0);let t=v.empty(),r=0,n=0;for(let i of e)t=t.insert(n,[r,n]),r++,n+=i+1;this.tree=t}totalCount(){return this.count}transpose(e){return e.map(e=>{const t=this.tree.find(e.index);if(t)return{groupIndex:t[0],index:e.index,offset:e.offset,size:e.size,type:"group"};const[r]=this.tree.findMaxValue(e.index);return{groupIndex:r,index:e.index,offset:e.offset,size:e.size,transposedIndex:e.index-r-1,type:"item"}})}groupIndices(){return this.tree.keys()}}function w(e){let t,r=e=>{t&&t(e)},n=!1;return i=>{t=i,n||(e.subscribe(r),n=!0)}}function I(e){return e.next}const E=e=>e.length>0?e[0].offset:0,M=([e,t])=>e.total(t-1),C=({overscan:e=0,totalCount:t=0,itemHeight:r})=>{const n=o(0),i=o(0),s=o(0),d=o(0),p=o(),g=o(t),m=o(),v=o(),x=o(!1);let C=y.create();const z=o([]);r&&(C=C.insert(0,0,r));const W=o(C);r||p.pipe(f(W.subscribe,z.subscribe)).subscribe(([e,t,r])=>{let n=t;for(let{start:t,end:r,size:i}of e)n=n.insert(t,r,i);n!==t&&W.next(n)});let H=new b;m.subscribe(e=>{H=new k(e),g.next(H.totalCount()),z.next(H.groupIndices())});const R=l(W.subscribe,g.subscribe).pipe(u(M)),T=l(R.subscribe,d.subscribe).pipe(u(([e,t])=>e+t)),V=l(W.subscribe,z.subscribe).pipe(u(([e,t])=>e.getOffsets(t))),S=o([]);l(W.subscribe,v.subscribe,g.subscribe).pipe(c(e=>e[1]>0),u(([e,t,r])=>{const n=Math.max(0,Math.min(t-1,r));return H.transpose(e.indexRange(0,n))})).subscribe(S.next),l(W.subscribe,V.subscribe,s.subscribe).pipe(c(e=>!e[1].empty()&&!e[0].empty()),f(S.subscribe),u(([[e,t,r],n])=>{const i=t.findMaxValue(r);if(1===n.length&&n[0].index===i)return n;const s=e.itemAt(i);return H.transpose([s])})).subscribe(S.next);const N=S.pipe(u(e=>e.reduce((e,t)=>e+t.size,0))),j=S.pipe(u(e=>e.length&&e[e.length-1].index+1)),L=l(n.subscribe,s.subscribe,N.subscribe,i.subscribe,d.subscribe,j.subscribe,g.subscribe,W.subscribe).pipe(function(e,t){let r=t;return(t,n)=>{n(r=e(r,t))}}((e=>(t,[r,n,i,s,o,l,u,a])=>{const h=t.length;if(0===u)return 0===h?t:[];const c=E(t),f=c-n+s-o-i,d=Math.max(u-1,0),p=h>0&&(t[0].index<l||t[h-1].index>d);if(f<r||p){const t=Math.max(n+i,i),s=n+r+2*e-1,o=H.transpose(a.range(t,s,l,d));return o}if(c>n+i){const t=Math.max(n+i-2*e,i),s=n+r-1;return H.transpose(a.range(t,s,l,d))}return t})(e),[])),O=o(0);let A=0;L.pipe(u(e=>e.length?e[e.length-1].index:0)).pipe(f(g.subscribe)).subscribe(([e,t])=>{e==t-1&&A!==e&&(A=e,O.next(e))});const P=l(L.subscribe,s.subscribe,N.subscribe).pipe(u(([e,t,r])=>E(e)-t-r));return s.pipe(h(1),a(!0)).subscribe(x.next),s.pipe(h(1),a(!1),function(e){let t,r;return(n,i)=>{t=n,r&&clearTimeout(r),r=setTimeout(()=>{i(t)},e)}}(200)).subscribe(x.next),{groupCounts:I(m),itemHeights:I(p),footerHeight:I(d),listHeight:I(i),viewportHeight:I(n),scrollTop:I(s),topItemCount:I(v),totalCount:I(g),list:w(L),topList:w(S),listOffset:w(P),totalHeight:w(T),endReached:w(O),isScrolling:w(x),stickyItems:w(z)}},z=(e,r,i)=>{const s=t.useRef(null),o=t.useRef(0),l=new n(t=>{const r=t[0].contentRect.height;o.current!==r&&(o.current=r,i&&i(t[0].target),e(r))});return e=>{e?(l.observe(e),r&&r(e),s.current=e):(l.unobserve(s.current),s.current=null)}};function W(e,r){const[n,i]=t.useState(r);return t.useLayoutEffect(()=>{e(i)},[]),n}const H={height:"40rem",overflowY:"auto",WebkitOverflowScrolling:"touch",position:"relative",outline:"none"},R=({children:e,style:n})=>{const{scrollTop:s}=t.useContext(i),o=t.useRef(null),l=t.useCallback(e=>{s(e.target.scrollTop)},[]),u=t.useCallback(e=>{e?(e.addEventListener("scroll",l,{passive:!0}),o.current=e):o.current.removeEventListener("scroll",l)},[]);return r.createElement("div",{ref:u,style:{...H,...n},tabIndex:0},e)},T=({list:e,transform:n="",render:s})=>{const{stickyItems:o}=t.useContext(i),l=W(e,[]),u=W(o,[]),a=t.useCallback(e=>{const t=u.some(t=>t===e),r={transform:n,zIndex:t?2:void 0,position:t?"relative":void 0};return r},[u,n]);return 0===l.length?null:r.createElement(r.Fragment,null,l.map(e=>r.createElement("div",{key:e.index,"data-index":e.index,"data-known-size":e.size,style:a(e.index)},s(e))))},V=()=>{const e=W(t.useContext(i).totalHeight,0);return r.createElement("div",{style:{height:`${e}px`,position:"absolute",top:0}}," ")},S=({footer:e})=>{const n=z(t.useContext(i).footerHeight);return r.createElement("footer",{ref:n},e())},N={top:0,position:"sticky",height:"100%",overflow:"hidden",WebkitBackfaceVisibility:"hidden"},j=({style:e,footer:n,item:s,fixedItemHeight:o})=>{const{itemHeights:l,listHeight:u,viewportHeight:a,listOffset:h,list:c,topList:f}=t.useContext(i),d=W(h,0),p=t.useCallback(e=>{const t=[];for(var r=0,n=e.length;r<n;r++){let n=e.item(r);if(!n||"DIV"!==n.tagName)continue;const i=parseInt(n.dataset.index),s=n.offsetHeight;0===t.length||t[t.length-1].size!==s?t.push({start:i,end:i,size:s}):t[t.length-1].end++}t.length>0&&l(t)},[]),g=z(u,()=>{},e=>{o||p(e.children)}),m=z(a,e=>{""===e.style.position&&(e.style.position="-webkit-sticky")}),v=`translateY(${d}px)`,y=`translateY(${-d}px)`;return r.createElement(R,{style:e},r.createElement("div",{style:N,ref:m},r.createElement("div",{style:{transform:v}},r.createElement("div",{ref:g},r.createElement(T,{list:f,transform:y,render:s}),r.createElement(T,{list:c,render:s}),n&&r.createElement(S,{footer:n})))),r.createElement(V,null))},L=({contextValue:e,style:t,item:n,footer:s,itemHeight:o})=>r.createElement(i.Provider,{value:e},r.createElement(j,{style:t||{},item:n,footer:s,fixedItemHeight:void 0!==o}));exports.GroupedVirtuoso=class extends t.PureComponent{constructor(e){super(e),this.itemRender=(e=>"group"==e.type?this.props.group(e.groupIndex):this.props.item(e.transposedIndex,e.groupIndex)),this.state=C(e)}static getDerivedStateFromProps(e,t){return t.endReached(e.endReached),t.isScrolling(e.scrollingStateChange),t.groupCounts(e.groupCounts),null}render(){return r.createElement(L,{contextValue:this.state,style:this.props.style,item:this.itemRender,footer:this.props.footer,itemHeight:this.props.itemHeight})}},exports.Virtuoso=class extends t.PureComponent{constructor(e){super(e),this.itemRenderer=(e=>this.props.item(e.index)),this.state=C(e)}static getDerivedStateFromProps(e,t){return t.isScrolling(e.scrollingStateChange),t.endReached(e.endReached),t.topItemCount(e.topItems||0),t.totalCount(e.totalCount),null}render(){return r.createElement(L,{contextValue:this.state,style:this.props.style,item:this.itemRenderer,footer:this.props.footer,itemHeight:this.props.itemHeight})}},exports.VirtuosoPresentation=L;
"use strict";function e(e){return e&&"object"==typeof e&&"default"in e?e.default:e}var t=require("react"),r=e(t),n=e(require("resize-observer-polyfill"));const s=t.createContext(void 0);function i(e){return function(...t){const r=function(...e){return 0===e.length?(e,t)=>t(e):1===e.length?e[0]:(t,r)=>{let n=e=>r(e);e.slice().reverse().forEach(e=>{const t=n;n=(r=>e(r,t))}),n(t)}}(...t);return function(e,t){const r=r=>e(e=>t(e,r));return{subscribe:r,pipe:i(r)}}(e,r)}}function o(e,t=!0){let r=[],n=e;const s=e=>(r.push(e),void 0!==n&&e(n),()=>{r=r.filter(t=>t!==e)});return{next:e=>{t&&e===n||(n=e,r.forEach(t=>t(e)))},subscribe:s,pipe:i(s),subscribers:r}}function l(...e){const t=Array(e.length).fill(!1),r=Array(e.length);let n=[];const s=e=>{t.every(e=>e)&&e.forEach(e=>e(r))};e.forEach((e,i)=>{e(e=>{t[i]=!0,r[i]=e,s(n)})});const o=e=>(n.push(e),s([e]),()=>{n=n.filter(t=>t!==e)});return{subscribe:o,pipe:i(o)}}function a(e){return(t,r)=>{r(e(t))}}function u(e){return(t,r)=>r(e)}function c(e){return(t,r)=>{e>0?e--:r(t)}}function h(e){return(t,r)=>{e(t)&&r(t)}}function f(...e){const t=Array(e.length).fill(!1),r=Array(e.length);return e.forEach((e,n)=>{e(e=>{r[n]=e,t[n]=!0})}),(e,n)=>{t.every(e=>e)&&n([e,...r])}}class d{constructor(){this.level=0}rebalance(){return this}adjust(){return this}remove(){return this}find(){}findWith(){}findMax(){return-Infinity}findMaxValue(){}insert(e,t){return new m({key:e,value:t,level:1})}walkWithin(){return[]}walk(){return[]}ranges(){return[]}rangesWithin(){return[]}empty(){return!0}isSingle(){return!0}isInvariant(){return!0}keys(){return[]}}const p=new d;Object.freeze(p);class g extends Error{constructor(e){super(`Unreachable case: ${e}`)}}class m{constructor({key:e,value:t,level:r,left:n=p,right:s=p}){this.key=e,this.value=t,this.level=r,this.left=n,this.right=s}remove(e){const{left:t,right:r}=this;if(e===this.key){if(t.empty())return r;if(r.empty())return t;{const[e,r]=t.last();return this.clone({key:e,value:r,left:t.deleteLast()}).adjust()}}return e<this.key?this.clone({left:t.remove(e)}).adjust():this.clone({right:r.remove(e)}).adjust()}empty(){return!1}find(e){return e===this.key?this.value:e<this.key?this.left.find(e):this.right.find(e)}findWith(e){const t=e(this.value);switch(t){case-1:return this.left.findWith(e);case 0:return[this.key,this.value];case 1:return this.right.findWith(e);default:throw new g(t)}}findMax(e){if(this.key===e)return e;if(this.key<e){const t=this.right.findMax(e);return-Infinity===t?this.key:t}return this.left.findMax(e)}findMaxValue(e){if(this.key===e)return this.value;if(this.key<e){const t=this.right.findMaxValue(e);return void 0===t?this.value:t}return this.left.findMaxValue(e)}insert(e,t){return e===this.key?this.clone({key:e,value:t}):e<this.key?this.clone({left:this.left.insert(e,t)}).rebalance():this.clone({right:this.right.insert(e,t)}).rebalance()}walkWithin(e,t){const{key:r,value:n}=this;let s=[];return r>e&&(s=s.concat(this.left.walkWithin(e,t))),r>=e&&r<=t&&s.push({key:r,value:n}),r<=t&&(s=s.concat(this.right.walkWithin(e,t))),s}walk(){return[...this.left.walk(),{key:this.key,value:this.value},...this.right.walk()]}last(){return this.right.empty()?[this.key,this.value]:this.right.last()}deleteLast(){return this.right.empty()?this.left:this.clone({right:this.right.deleteLast()}).adjust()}clone(e){return new m({key:void 0!==e.key?e.key:this.key,value:void 0!==e.value?e.value:this.value,level:void 0!==e.level?e.level:this.level,left:void 0!==e.left?e.left:this.left,right:void 0!==e.right?e.right:this.right})}isSingle(){return this.level>this.right.level}rebalance(){return this.skew().split()}adjust(){const{left:e,right:t,level:r}=this;if(t.level>=r-1&&e.level>=r-1)return this;if(r>t.level+1){if(e.isSingle())return this.clone({level:r-1}).skew();if(e.empty()||e.right.empty())throw new Error("Unexpected empty nodes");return e.right.clone({left:e.clone({right:e.right.left}),right:this.clone({left:e.right.right,level:r-1}),level:r})}if(this.isSingle())return this.clone({level:r-1}).split();if(t.empty()||t.left.empty())throw new Error("Unexpected empty nodes");{const e=t.left,n=e.isSingle()?t.level-1:t.level;return e.clone({left:this.clone({right:e.left,level:r-1}),right:t.clone({left:e.right,level:n}).split(),level:e.level+1})}}isInvariant(){const{left:e,right:t,level:r}=this;return r===e.level+1&&((r===t.level||r===t.level+1)&&(!(!t.empty()&&r<=t.right.level)&&(e.isInvariant()&&t.isInvariant())))}keys(){return[...this.left.keys(),this.key,...this.right.keys()]}ranges(){return this.toRanges(this.walk())}rangesWithin(e,t){return this.toRanges(this.walkWithin(e,t))}toRanges(e){if(0===e.length)return[];const t=e[0];let{key:r,value:n}=t;const s=[];for(let t=1;t<=e.length;t++){let i=e[t],o=i?i.key-1:Infinity;s.push({start:r,end:o,value:n}),i&&(r=i.key,n=i.value)}return s}split(){const{right:e,level:t}=this;return e.empty()||e.right.empty()||e.level!=t||e.right.level!=t?this:e.clone({left:this.clone({right:e.left}),level:t+1})}skew(){const{left:e}=this;return e.empty()||e.level!==this.level?this:e.clone({right:this.clone({left:e.right})})}}class v{constructor(e){this.root=e}static empty(){return new v(p)}find(e){return this.root.find(e)}findMax(e){return this.root.findMax(e)}findMaxValue(e){if(this.empty())throw new Error("Searching for max value in an empty tree");return this.root.findMaxValue(e)}findWith(e){return this.root.findWith(e)}insert(e,t){return new v(this.root.insert(e,t))}remove(e){return new v(this.root.remove(e))}empty(){return this.root.empty()}keys(){return this.root.keys()}walk(){return this.root.walk()}walkWithin(e,t){let r=this.root.findMax(e);return this.root.walkWithin(r,t)}ranges(){return this.root.ranges()}rangesWithin(e,t){let r=this.root.findMax(e);return this.root.rangesWithin(r,t)}isInvariant(){return this.root.isInvariant()}}class y{constructor(e){this.nanIndices=[],this.rangeTree=e;let t=v.empty(),r=0;const n=e.ranges();let s=!1;for(let{start:e,end:i,value:o}of n)isNaN(o)?(this.nanIndices.push(e),s||(t=t.insert(r,{startIndex:e,endIndex:Infinity,size:o})),s=!0):s||(t=t.insert(r,{startIndex:e,endIndex:i,size:o}),r+=(i-e+1)*o);this.offsetTree=t}static create(){return new y(v.empty())}empty(){return this.rangeTree.empty()}insert(e,t,r){let n=this.rangeTree;if(n.empty())return new y(n.insert(0,r));if(this.nanIndices.length&&this.nanIndices.indexOf(e)>-1){for(const e of this.nanIndices)n=n.insert(e,r);return new y(n)}const s=n.rangesWithin(e-1,t+1);if(s.some(n=>n.start===e&&(n.end===t||Infinity===n.end)&&n.value===r))return this;let i=!1,o=!1;for(const{start:e,end:l,value:a}of s)i?(t>=e||r===a)&&(n=n.remove(e)):(o=a!==r,i=!0),l>t&&t>=e&&(a===r||isNaN(a)||(n=n.insert(t+1,a)));return o&&(n=n.insert(e,r)),n===this.rangeTree?this:new y(n)}insertSpots(e,t){if(this.empty()){let r=this.rangeTree;for(const n of e)r=r.insert(n,t).insert(n+1,NaN);return new y(r)}throw new Error("attempting to overwrite non-empty tree")}offsetOf(e){if(this.offsetTree.empty())return 0;const t=this.offsetTree.findWith(t=>t.startIndex>e?-1:t.endIndex<e?1:0);if(t){const[r,{startIndex:n,size:s}]=t;return r+(e-n)*s}throw new Error(`Requested offset outside of the known ones, index: ${e}`)}itemAt(e){const t=this.rangeTree.findMaxValue(e);return{index:e,size:t,offset:NaN}}indexRange(e,t){if(0===t)return[];if(this.rangeTree.empty())return[{index:0,size:0,offset:NaN}];const r=this.rangeTree.rangesWithin(e,t),n=[];for(const s of r){const r=Math.max(e,s.start),i=void 0===s.end?Infinity:s.end,o=Math.min(t,i);for(let e=r;e<=o;e++)n.push({index:e,size:s.value,offset:NaN})}return n}range(e,t,r=0,n=Infinity){if(this.offsetTree.empty())return[{index:0,size:0,offset:0}];const s=this.offsetTree.rangesWithin(e,t),i=[];for(let{start:o,value:{startIndex:l,endIndex:a,size:u}}of s){let s=o,c=l;if(o<e&&(c+=Math.floor((e-o)/u),s+=(c-l)*u),c<r&&(s+=(r-c)*u,c=r),isNaN(u))return i.push({index:c,size:0,offset:s}),i;a=Math.min(a,n);for(let e=c;e<=a&&!(s>t);e++)i.push({index:e,size:u,offset:s}),s+=u}return i}total(e){const t=this.rangeTree.rangesWithin(0,e);let r=0;for(let{start:n,end:s,value:i}of t)s=Math.min(s,e),r+=(s-n+1)*(isNaN(i)?0:i);return r}getOffsets(e){let t=v.empty();return e.forEach(e=>{const r=this.offsetOf(e);t=t.insert(r,e)}),new x(t)}}class x{constructor(e){this.tree=e}findMaxValue(e){return this.tree.findMaxValue(e)}empty(){return this.tree.empty()}}class b{transpose(e){return e.map(e=>({groupIndex:0,index:e.index,offset:e.offset,size:e.size,transposedIndex:e.index,type:"item"}))}}class k{constructor(e){this.count=e.reduce((e,t)=>e+t+1,0);let t=v.empty(),r=0,n=0;for(let s of e)t=t.insert(n,[r,n]),r++,n+=s+1;this.tree=t}totalCount(){return this.count}transpose(e){return e.map(e=>{const t=this.tree.find(e.index);if(t)return{groupIndex:t[0],index:e.index,offset:e.offset,size:e.size,type:"group"};const[r]=this.tree.findMaxValue(e.index);return{groupIndex:r,index:e.index,offset:e.offset,size:e.size,transposedIndex:e.index-r-1,type:"item"}})}groupIndices(){return this.tree.keys()}}function I(e){let t,r=e=>{t&&t(e)},n=!1;return s=>{t=s,n||(e.subscribe(r),n=!0)}}function w(e){return e.next}const C=e=>e.length>0?e[0].offset:0,E=([e,t])=>e.total(t-1),M=({overscan:e=0,totalCount:t=0,itemHeight:r})=>{const n=o(0),s=o(0),i=o(0),d=o(0),p=o(),g=o(t),m=o(),v=o(),x=o(!1);let M=y.create();const T=o([]),N=o(void 0,!1);r&&(M=M.insert(0,0,r));const S=o(M);r||p.pipe(f(S.subscribe,T.subscribe)).subscribe(([e,t,r])=>{let n=t;for(let{start:t,end:s,size:i}of e)n=n.empty()&&t==s&&r.indexOf(t)>-1?n.insertSpots(r,i):n.insert(t,s,i);n!==t&&S.next(n)});let z=new b;m.subscribe(e=>{z=new k(e),g.next(z.totalCount()),T.next(z.groupIndices())});const W=l(S.subscribe,g.subscribe).pipe(a(E)),H=l(W.subscribe,d.subscribe).pipe(a(([e,t])=>e+t)),R=l(S.subscribe,T.subscribe).pipe(a(([e,t])=>e.getOffsets(t))),V=o([]);l(S.subscribe,v.subscribe,g.subscribe).pipe(h(e=>e[1]>0),a(([e,t,r])=>{const n=Math.max(0,Math.min(t-1,r));return z.transpose(e.indexRange(0,n))})).subscribe(V.next),l(S.subscribe,R.subscribe,i.subscribe).pipe(h(e=>!e[1].empty()&&!e[0].empty()),f(V.subscribe),a(([[e,t,r],n])=>{const s=t.findMaxValue(r);if(1===n.length&&n[0].index===s)return n;const i=e.itemAt(s);return z.transpose([i])})).subscribe(V.next);const O=V.pipe(a(e=>e.reduce((e,t)=>e+t.size,0))),j=V.pipe(a(e=>e.length&&e[e.length-1].index+1)),A=l(n.subscribe,i.subscribe,O.subscribe,s.subscribe,d.subscribe,j.subscribe,g.subscribe,S.subscribe).pipe(function(e,t){let r=t;return(t,n)=>{n(r=e(r,t))}}((e=>(t,[r,n,s,i,o,l,a,u])=>{const c=t.length;if(0===a)return 0===c?t:[];const h=C(t),f=h-n+i-o-s,d=Math.max(a-1,0),p=c>0&&(t[0].index<l||t[c-1].index>d);if(f<r||p){const t=Math.max(n+s,s),i=n+r+2*e-1,o=z.transpose(u.range(t,i,l,d));return o}if(h>n+s){const t=Math.max(n+s-2*e,s),i=n+r-1;return z.transpose(u.range(t,i,l,d))}return t})(e),[])),L=o(0);let P=0;A.pipe(a(e=>e.length?e[e.length-1].index:0)).pipe(f(g.subscribe)).subscribe(([e,t])=>{e==t-1&&P!==e&&(P=e,L.next(e))});const $=l(A.subscribe,i.subscribe,O.subscribe).pipe(a(([e,t,r])=>C(e)-t-r));i.pipe(c(1),u(!0)).subscribe(x.next),i.pipe(c(1),u(!1),function(e){let t,r;return(n,s)=>{t=n,r&&clearTimeout(r),r=setTimeout(()=>{s(t)},e)}}(200)).subscribe(x.next);const q=N.pipe(f(S.subscribe,O.subscribe,T.subscribe,n.subscribe,g.subscribe),a(([e,t,r,n,s,i])=>{"number"==typeof e&&(e={index:e,align:"start"});let{index:o,align:l="start"}=e;o=Math.max(0,o,Math.min(i-1,o));let a=t.offsetOf(o);return"end"==l?a=a-s+t.itemAt(o).size:"center"===l?a=Math.round(a-s/2+t.itemAt(o).size/2):-1===n.indexOf(o)&&(a-=r),a})),D=T.pipe();return{groupCounts:w(m),itemHeights:w(p),footerHeight:w(d),listHeight:w(s),viewportHeight:w(n),scrollTop:w(i),topItemCount:w(v),totalCount:w(g),scrollToIndex:w(N),list:I(A),topList:I(V),listOffset:I($),totalHeight:I(H),endReached:I(L),isScrolling:I(x),stickyItems:I(T),groupIndices:I(D),scrollTo:I(q)}},T=(e,r,s)=>{const i=t.useRef(null),o=t.useRef(0),l=new n(t=>{const r=t[0].contentRect.height;o.current!==r&&(o.current=r,s&&s(t[0].target),e(r))});return e=>{e?(l.observe(e),r&&r(e),i.current=e):(l.unobserve(i.current),i.current=null)}};function N(e,r){const[n,s]=t.useState(r);return t.useLayoutEffect(()=>{e(s)},[]),n}const S={height:"40rem",overflowY:"auto",WebkitOverflowScrolling:"touch",position:"relative",outline:"none"},z=({className:e,style:n,reportScrollTop:s,scrollTo:i,children:o})=>{const l=t.useRef(null),a=t.useCallback(e=>{s(e.target.scrollTop)},[]),u=t.useCallback(e=>{e?(e.addEventListener("scroll",a,{passive:!0}),l.current=e):l.current.removeEventListener("scroll",a)},[]);return i(e=>{const t={top:e};l.current.scrollTo(t)}),r.createElement("div",{ref:u,style:n,tabIndex:0,className:e},o)},W=({children:e,style:n,className:i,ScrollContainer:o=z})=>{const{scrollTop:l,scrollTo:a}=t.useContext(s);return r.createElement(o,{style:{...S,...n},reportScrollTop:l,scrollTo:a,className:i},e)},H=({list:e,transform:n="",render:i})=>{const{stickyItems:o}=t.useContext(s),l=N(e,[]),a=N(o,[]),u=t.useCallback(e=>{const t=a.some(t=>t===e),r={transform:n,zIndex:t?2:void 0,position:t?"relative":void 0};return r},[a,n]);return 0===l.length?null:r.createElement(r.Fragment,null,l.map(e=>r.createElement("div",{key:e.index,"data-index":e.index,"data-known-size":e.size,style:u(e.index)},i(e))))},R=()=>{const e=N(t.useContext(s).totalHeight,0);return r.createElement("div",{style:{height:`${e}px`,position:"absolute",top:0}}," ")},V=({footer:e})=>{const n=T(t.useContext(s).footerHeight);return r.createElement("footer",{ref:n},e())},O={top:0,position:"sticky",height:"100%",overflow:"hidden",WebkitBackfaceVisibility:"hidden"},j=({style:e,footer:n,item:i,fixedItemHeight:o,ScrollContainer:l,className:a})=>{const{itemHeights:u,listHeight:c,viewportHeight:h,listOffset:f,list:d,topList:p}=t.useContext(s),g=N(f,0),m=t.useCallback(e=>{const t=[];for(var r=0,n=e.length;r<n;r++){let n=e.item(r);if(!n||"DIV"!==n.tagName)continue;const s=parseInt(n.dataset.index),i=n.offsetHeight;0===t.length||t[t.length-1].size!==i?t.push({start:s,end:s,size:i}):t[t.length-1].end++}t.length>0&&u(t)},[]),v=T(c,()=>{},e=>{o||m(e.children)}),y=T(h,e=>{""===e.style.position&&(e.style.position="-webkit-sticky")}),x=`translateY(${g}px)`,b=`translateY(${-g}px)`;return r.createElement(W,{style:e,ScrollContainer:l,className:a},r.createElement("div",{style:O,ref:y},r.createElement("div",{style:{transform:x}},r.createElement("div",{ref:v},r.createElement(H,{list:p,transform:b,render:i}),r.createElement(H,{list:d,render:i}),n&&r.createElement(V,{footer:n})))),r.createElement(R,null))},A=({contextValue:e,style:t,className:n,item:i,footer:o,itemHeight:l,ScrollContainer:a})=>r.createElement(s.Provider,{value:e},r.createElement(j,{style:t||{},className:n,item:i,footer:o,fixedItemHeight:void 0!==l,ScrollContainer:a}));exports.GroupedVirtuoso=class extends t.PureComponent{constructor(e){super(e),this.itemRender=(e=>"group"==e.type?this.props.group(e.groupIndex):this.props.item(e.transposedIndex,e.groupIndex)),this.state=M(e)}static getDerivedStateFromProps(e,t){return t.endReached(e.endReached),t.isScrolling(e.scrollingStateChange),t.groupCounts(e.groupCounts),t.groupIndices(e.groupIndices),null}scrollToIndex(e){this.state.scrollToIndex(e)}render(){return r.createElement(A,{contextValue:this.state,style:this.props.style,className:this.props.className,item:this.itemRender,footer:this.props.footer,itemHeight:this.props.itemHeight,ScrollContainer:this.props.ScrollContainer})}},exports.Virtuoso=class extends t.PureComponent{constructor(e){super(e),this.itemRender=(e=>this.props.item(e.index)),this.state=M(e)}static getDerivedStateFromProps(e,t){return t.isScrolling(e.scrollingStateChange),t.endReached(e.endReached),t.topItemCount(e.topItems||0),t.totalCount(e.totalCount),null}scrollToIndex(e){this.state.scrollToIndex(e)}render(){return r.createElement(A,{contextValue:this.state,style:this.props.style,className:this.props.className,item:this.itemRender,footer:this.props.footer,itemHeight:this.props.itemHeight,ScrollContainer:this.props.ScrollContainer})}},exports.VirtuosoPresentation=A;
//# sourceMappingURL=react-virtuoso.cjs.production.js.map

@@ -1,2 +0,2 @@

import e,{createContext as t,useRef as r,useState as i,useLayoutEffect as n,useContext as s,useCallback as o,PureComponent as l}from"react";import h from"resize-observer-polyfill";const u=t(void 0);function a(e){return function(...t){const r=function(...e){return 0===e.length?(e,t)=>t(e):1===e.length?e[0]:(t,r)=>{let i=e=>r(e);e.slice().reverse().forEach(e=>{const t=i;i=(r=>e(r,t))}),i(t)}}(...t);return function(e,t){const r=r=>e(e=>t(e,r));return{subscribe:r,pipe:a(r)}}(e,r)}}function c(e){let t=[],r=e;const i=e=>(t.push(e),void 0!==r&&e(r),()=>{t=t.filter(t=>t!==e)});return{next:e=>{e!==r&&(r=e,t.forEach(t=>t(e)))},subscribe:i,pipe:a(i),subscribers:t}}function f(...e){const t=Array(e.length).fill(!1),r=Array(e.length);let i=[];const n=e=>{t.every(e=>e)&&e.forEach(e=>e(r))};e.forEach((e,s)=>{e(e=>{t[s]=!0,r[s]=e,n(i)})});const s=e=>(i.push(e),n([e]),()=>{i=i.filter(t=>t!==e)});return{subscribe:s,pipe:a(s)}}function d(e){return(t,r)=>{r(e(t))}}function p(e){return(t,r)=>r(e)}function g(e){return(t,r)=>{e>0?e--:r(t)}}function m(e){return(t,r)=>{e(t)&&r(t)}}function v(...e){const t=Array(e.length).fill(!1),r=Array(e.length);return e.forEach((e,i)=>{e(e=>{r[i]=e,t[i]=!0})}),(e,i)=>{t.every(e=>e)&&i([e,...r])}}class y{constructor(){this.level=0}rebalance(){return this}adjust(){return this}remove(){return this}find(){}findWith(){}findMax(){return-Infinity}findMaxValue(){}insert(e,t){return new k({key:e,value:t,level:1})}walkWithin(){return[]}walk(){return[]}ranges(){return[]}rangesWithin(){return[]}empty(){return!0}isSingle(){return!0}isInvariant(){return!0}keys(){return[]}}const x=new y;Object.freeze(x);class b extends Error{constructor(e){super(`Unreachable case: ${e}`)}}class k{constructor({key:e,value:t,level:r,left:i=x,right:n=x}){this.key=e,this.value=t,this.level=r,this.left=i,this.right=n}remove(e){const{left:t,right:r}=this;if(e===this.key){if(t.empty())return r;if(r.empty())return t;{const[e,r]=t.last();return this.clone({key:e,value:r,left:t.deleteLast()}).adjust()}}return e<this.key?this.clone({left:t.remove(e)}).adjust():this.clone({right:r.remove(e)}).adjust()}empty(){return!1}find(e){return e===this.key?this.value:e<this.key?this.left.find(e):this.right.find(e)}findWith(e){const t=e(this.value);switch(t){case-1:return this.left.findWith(e);case 0:return[this.key,this.value];case 1:return this.right.findWith(e);default:throw new b(t)}}findMax(e){if(this.key===e)return e;if(this.key<e){const t=this.right.findMax(e);return-Infinity===t?this.key:t}return this.left.findMax(e)}findMaxValue(e){if(this.key===e)return this.value;if(this.key<e){const t=this.right.findMaxValue(e);return void 0===t?this.value:t}return this.left.findMaxValue(e)}insert(e,t){return e===this.key?this.clone({key:e,value:t}):e<this.key?this.clone({left:this.left.insert(e,t)}).rebalance():this.clone({right:this.right.insert(e,t)}).rebalance()}walkWithin(e,t){const{key:r,value:i}=this;let n=[];return r>e&&(n=n.concat(this.left.walkWithin(e,t))),r>=e&&r<=t&&n.push({key:r,value:i}),r<=t&&(n=n.concat(this.right.walkWithin(e,t))),n}walk(){return[...this.left.walk(),{key:this.key,value:this.value},...this.right.walk()]}last(){return this.right.empty()?[this.key,this.value]:this.right.last()}deleteLast(){return this.right.empty()?this.left:this.clone({right:this.right.deleteLast()}).adjust()}clone(e){return new k({key:void 0!==e.key?e.key:this.key,value:void 0!==e.value?e.value:this.value,level:void 0!==e.level?e.level:this.level,left:void 0!==e.left?e.left:this.left,right:void 0!==e.right?e.right:this.right})}isSingle(){return this.level>this.right.level}rebalance(){return this.skew().split()}adjust(){const{left:e,right:t,level:r}=this;if(t.level>=r-1&&e.level>=r-1)return this;if(r>t.level+1){if(e.isSingle())return this.clone({level:r-1}).skew();if(e.empty()||e.right.empty())throw new Error("Unexpected empty nodes");return e.right.clone({left:e.clone({right:e.right.left}),right:this.clone({left:e.right.right,level:r-1}),level:r})}if(this.isSingle())return this.clone({level:r-1}).split();if(t.empty()||t.left.empty())throw new Error("Unexpected empty nodes");{const e=t.left,i=e.isSingle()?t.level-1:t.level;return e.clone({left:this.clone({right:e.left,level:r-1}),right:t.clone({left:e.right,level:i}).split(),level:e.level+1})}}isInvariant(){const{left:e,right:t,level:r}=this;return r===e.level+1&&((r===t.level||r===t.level+1)&&(!(!t.empty()&&r<=t.right.level)&&(e.isInvariant()&&t.isInvariant())))}keys(){return[...this.left.keys(),this.key,...this.right.keys()]}ranges(){return this.toRanges(this.walk())}rangesWithin(e,t){return this.toRanges(this.walkWithin(e,t))}toRanges(e){if(0===e.length)return[];const t=e[0];let{key:r,value:i}=t;const n=[];for(let t=1;t<=e.length;t++){let s=e[t],o=s?s.key-1:Infinity;n.push({start:r,end:o,value:i}),s&&(r=s.key,i=s.value)}return n}split(){const{right:e,level:t}=this;return e.empty()||e.right.empty()||e.level!=t||e.right.level!=t?this:e.clone({left:this.clone({right:e.left}),level:t+1})}skew(){const{left:e}=this;return e.empty()||e.level!==this.level?this:e.clone({right:this.clone({left:e.right})})}}class w{constructor(e){this.root=e}static empty(){return new w(x)}find(e){return this.root.find(e)}findMax(e){return this.root.findMax(e)}findMaxValue(e){if(this.empty())throw new Error("Searching for max value in an empty tree");return this.root.findMaxValue(e)}findWith(e){return this.root.findWith(e)}insert(e,t){return new w(this.root.insert(e,t))}remove(e){return new w(this.root.remove(e))}empty(){return this.root.empty()}keys(){return this.root.keys()}walk(){return this.root.walk()}walkWithin(e,t){let r=this.root.findMax(e);return this.root.walkWithin(r,t)}ranges(){return this.root.ranges()}rangesWithin(e,t){let r=this.root.findMax(e);return this.root.rangesWithin(r,t)}isInvariant(){return this.root.isInvariant()}}class I{static create(){return new I(w.empty())}constructor(e){this.rangeTree=e;let t=w.empty(),r=0;for(const{start:i,end:n,value:s}of e.ranges())t=t.insert(r,{startIndex:i,endIndex:n,size:s}),Infinity!==n&&(r+=(n-i+1)*s);this.offsetTree=t}empty(){return this.rangeTree.empty()}insert(e,t,r){let i=this.rangeTree;if(i.empty())return new I(i.insert(0,r));const n=i.rangesWithin(e-1,t+1);if(n.some(i=>i.start===e&&(i.end===t||Infinity===i.end)&&i.value===r))return this;let s=!1,o=!1;for(const{start:e,end:l,value:h}of n)s?(t>=e||r===h)&&(i=i.remove(e)):(o=h!==r,s=!0),l>t&&t>=e&&(h===r||isNaN(h)||(i=i.insert(t+1,h)));return o&&(i=i.insert(e,r)),i===this.rangeTree?this:new I(i)}insertException(e,t){return this.empty()?new I(this.rangeTree.insert(1,NaN).insert(e,t)):this.insert(e,e,t)}offsetOf(e){if(this.offsetTree.empty())return 0;const t=this.offsetTree.findWith(t=>t.startIndex>e?-1:t.endIndex<e?1:0);if(t){const[r,{startIndex:i,size:n}]=t;return r+(e-i)*n}throw new Error(`Requested offset outside of the known ones, index: ${e}`)}itemAt(e){const t=this.rangeTree.findMaxValue(e);return{index:e,size:t,offset:NaN}}indexRange(e,t){if(0===t)return[];if(this.rangeTree.empty())return[{index:0,size:0,offset:NaN}];const r=this.rangeTree.rangesWithin(e,t),i=[];for(const n of r){const r=Math.max(e,n.start),s=void 0===n.end?Infinity:n.end,o=Math.min(t,s);for(let e=r;e<=o;e++)i.push({index:e,size:n.value,offset:NaN})}return i}range(e,t,r=0,i=Infinity){if(this.offsetTree.empty())return[{index:0,size:0,offset:0}];const n=this.offsetTree.rangesWithin(e,t),s=[];for(let{start:o,value:{startIndex:l,endIndex:h,size:u}}of n){let n=o,a=l;if(o<e&&(a+=Math.floor((e-o)/u),n+=(a-l)*u),a<r&&(n+=(r-a)*u,a=r),isNaN(u))return s.push({index:a,size:0,offset:n}),s;h=Math.min(h,i);for(let e=a;e<=h&&!(n>t);e++)s.push({index:e,size:u,offset:n}),n+=u}return s}total(e){const t=this.rangeTree.rangesWithin(0,e);let r=0;for(let{start:i,end:n,value:s}of t)n=Math.min(n,e),r+=(n-i+1)*s;return r}getOffsets(e){let t=w.empty();return e.forEach(e=>{const r=this.offsetOf(e);t=t.insert(r,e)}),new E(t)}}class E{constructor(e){this.tree=e}findMaxValue(e){return this.tree.findMaxValue(e)}empty(){return this.tree.empty()}}class M{transpose(e){return e.map(e=>({groupIndex:0,index:e.index,offset:e.offset,size:e.size,transposedIndex:e.index,type:"item"}))}}class z{constructor(e){this.count=e.reduce((e,t)=>e+t+1,0);let t=w.empty(),r=0,i=0;for(let n of e)t=t.insert(i,[r,i]),r++,i+=n+1;this.tree=t}totalCount(){return this.count}transpose(e){return e.map(e=>{const t=this.tree.find(e.index);if(t)return{groupIndex:t[0],index:e.index,offset:e.offset,size:e.size,type:"group"};const[r]=this.tree.findMaxValue(e.index);return{groupIndex:r,index:e.index,offset:e.offset,size:e.size,transposedIndex:e.index-r-1,type:"item"}})}groupIndices(){return this.tree.keys()}}function W(e){let t,r=e=>{t&&t(e)},i=!1;return n=>{t=n,i||(e.subscribe(r),i=!0)}}function H(e){return e.next}const T=e=>e.length>0?e[0].offset:0,R=([e,t])=>e.total(t-1),V=({overscan:e=0,totalCount:t=0,itemHeight:r})=>{const i=c(0),n=c(0),s=c(0),o=c(0),l=c(),h=c(t),u=c(),a=c(),y=c(!1);let x=I.create();const b=c([]);r&&(x=x.insert(0,0,r));const k=c(x);r||l.pipe(v(k.subscribe,b.subscribe)).subscribe(([e,t,r])=>{let i=t;for(let{start:t,end:r,size:n}of e)i=i.insert(t,r,n);i!==t&&k.next(i)});let w=new M;u.subscribe(e=>{w=new z(e),h.next(w.totalCount()),b.next(w.groupIndices())});const E=f(k.subscribe,h.subscribe).pipe(d(R)),V=f(E.subscribe,o.subscribe).pipe(d(([e,t])=>e+t)),S=f(k.subscribe,b.subscribe).pipe(d(([e,t])=>e.getOffsets(t))),C=c([]);f(k.subscribe,a.subscribe,h.subscribe).pipe(m(e=>e[1]>0),d(([e,t,r])=>{const i=Math.max(0,Math.min(t-1,r));return w.transpose(e.indexRange(0,i))})).subscribe(C.next),f(k.subscribe,S.subscribe,s.subscribe).pipe(m(e=>!e[1].empty()&&!e[0].empty()),v(C.subscribe),d(([[e,t,r],i])=>{const n=t.findMaxValue(r);if(1===i.length&&i[0].index===n)return i;const s=e.itemAt(n);return w.transpose([s])})).subscribe(C.next);const N=C.pipe(d(e=>e.reduce((e,t)=>e+t.size,0))),O=C.pipe(d(e=>e.length&&e[e.length-1].index+1)),j=f(i.subscribe,s.subscribe,N.subscribe,n.subscribe,o.subscribe,O.subscribe,h.subscribe,k.subscribe).pipe(function(e,t){let r=t;return(t,i)=>{i(r=e(r,t))}}((e=>(t,[r,i,n,s,o,l,h,u])=>{const a=t.length;if(0===h)return 0===a?t:[];const c=T(t),f=c-i+s-o-n,d=Math.max(h-1,0),p=a>0&&(t[0].index<l||t[a-1].index>d);if(f<r||p){const t=Math.max(i+n,n),s=i+r+2*e-1,o=w.transpose(u.range(t,s,l,d));return o}if(c>i+n){const t=Math.max(i+n-2*e,n),s=i+r-1;return w.transpose(u.range(t,s,l,d))}return t})(e),[])),L=c(0);let A=0;j.pipe(d(e=>e.length?e[e.length-1].index:0)).pipe(v(h.subscribe)).subscribe(([e,t])=>{e==t-1&&A!==e&&(A=e,L.next(e))});const $=f(j.subscribe,s.subscribe,N.subscribe).pipe(d(([e,t,r])=>T(e)-t-r));return s.pipe(g(1),p(!0)).subscribe(y.next),s.pipe(g(1),p(!1),function(e){let t,r;return(i,n)=>{t=i,r&&clearTimeout(r),r=setTimeout(()=>{n(t)},e)}}(200)).subscribe(y.next),{groupCounts:H(u),itemHeights:H(l),footerHeight:H(o),listHeight:H(n),viewportHeight:H(i),scrollTop:H(s),topItemCount:H(a),totalCount:H(h),list:W(j),topList:W(C),listOffset:W($),totalHeight:W(V),endReached:W(L),isScrolling:W(y),stickyItems:W(b)}},S=(e,t,i)=>{const n=r(null),s=r(0),o=new h(t=>{const r=t[0].contentRect.height;s.current!==r&&(s.current=r,i&&i(t[0].target),e(r))});return e=>{e?(o.observe(e),t&&t(e),n.current=e):(o.unobserve(n.current),n.current=null)}};function C(e,t){const[r,s]=i(t);return n(()=>{e(s)},[]),r}const N={height:"40rem",overflowY:"auto",WebkitOverflowScrolling:"touch",position:"relative",outline:"none"},O=({children:t,style:i})=>{const{scrollTop:n}=s(u),l=r(null),h=o(e=>{n(e.target.scrollTop)},[]),a=o(e=>{e?(e.addEventListener("scroll",h,{passive:!0}),l.current=e):l.current.removeEventListener("scroll",h)},[]);return e.createElement("div",{ref:a,style:{...N,...i},tabIndex:0},t)},j=({list:t,transform:r="",render:i})=>{const{stickyItems:n}=s(u),l=C(t,[]),h=C(n,[]),a=o(e=>{const t=h.some(t=>t===e),i={transform:r,zIndex:t?2:void 0,position:t?"relative":void 0};return i},[h,r]);return 0===l.length?null:e.createElement(e.Fragment,null,l.map(t=>e.createElement("div",{key:t.index,"data-index":t.index,"data-known-size":t.size,style:a(t.index)},i(t))))},L=()=>{const t=C(s(u).totalHeight,0);return e.createElement("div",{style:{height:`${t}px`,position:"absolute",top:0}}," ")},A=({footer:t})=>{const r=S(s(u).footerHeight);return e.createElement("footer",{ref:r},t())},$={top:0,position:"sticky",height:"100%",overflow:"hidden",WebkitBackfaceVisibility:"hidden"},D=({style:t,footer:r,item:i,fixedItemHeight:n})=>{const{itemHeights:l,listHeight:h,viewportHeight:a,listOffset:c,list:f,topList:d}=s(u),p=C(c,0),g=o(e=>{const t=[];for(var r=0,i=e.length;r<i;r++){let i=e.item(r);if(!i||"DIV"!==i.tagName)continue;const n=parseInt(i.dataset.index),s=i.offsetHeight;0===t.length||t[t.length-1].size!==s?t.push({start:n,end:n,size:s}):t[t.length-1].end++}t.length>0&&l(t)},[]),m=S(h,()=>{},e=>{n||g(e.children)}),v=S(a,e=>{""===e.style.position&&(e.style.position="-webkit-sticky")}),y=`translateY(${p}px)`,x=`translateY(${-p}px)`;return e.createElement(O,{style:t},e.createElement("div",{style:$,ref:v},e.createElement("div",{style:{transform:y}},e.createElement("div",{ref:m},e.createElement(j,{list:d,transform:x,render:i}),e.createElement(j,{list:f,render:i}),r&&e.createElement(A,{footer:r})))),e.createElement(L,null))},F=({contextValue:t,style:r,item:i,footer:n,itemHeight:s})=>e.createElement(u.Provider,{value:t},e.createElement(D,{style:r||{},item:i,footer:n,fixedItemHeight:void 0!==s}));class P extends l{constructor(e){super(e),this.itemRenderer=(e=>this.props.item(e.index)),this.state=V(e)}static getDerivedStateFromProps(e,t){return t.isScrolling(e.scrollingStateChange),t.endReached(e.endReached),t.topItemCount(e.topItems||0),t.totalCount(e.totalCount),null}render(){return e.createElement(F,{contextValue:this.state,style:this.props.style,item:this.itemRenderer,footer:this.props.footer,itemHeight:this.props.itemHeight})}}class U extends l{constructor(e){super(e),this.itemRender=(e=>"group"==e.type?this.props.group(e.groupIndex):this.props.item(e.transposedIndex,e.groupIndex)),this.state=V(e)}static getDerivedStateFromProps(e,t){return t.endReached(e.endReached),t.isScrolling(e.scrollingStateChange),t.groupCounts(e.groupCounts),null}render(){return e.createElement(F,{contextValue:this.state,style:this.props.style,item:this.itemRender,footer:this.props.footer,itemHeight:this.props.itemHeight})}}export{U as GroupedVirtuoso,P as Virtuoso,F as VirtuosoPresentation};
import e,{createContext as t,useRef as r,useState as n,useLayoutEffect as s,useContext as i,useCallback as o,PureComponent as l}from"react";import a from"resize-observer-polyfill";const h=t(void 0);function u(e){return function(...t){const r=function(...e){return 0===e.length?(e,t)=>t(e):1===e.length?e[0]:(t,r)=>{let n=e=>r(e);e.slice().reverse().forEach(e=>{const t=n;n=(r=>e(r,t))}),n(t)}}(...t);return function(e,t){const r=r=>e(e=>t(e,r));return{subscribe:r,pipe:u(r)}}(e,r)}}function c(e,t=!0){let r=[],n=e;const s=e=>(r.push(e),void 0!==n&&e(n),()=>{r=r.filter(t=>t!==e)});return{next:e=>{t&&e===n||(n=e,r.forEach(t=>t(e)))},subscribe:s,pipe:u(s),subscribers:r}}function f(...e){const t=Array(e.length).fill(!1),r=Array(e.length);let n=[];const s=e=>{t.every(e=>e)&&e.forEach(e=>e(r))};e.forEach((e,i)=>{e(e=>{t[i]=!0,r[i]=e,s(n)})});const i=e=>(n.push(e),s([e]),()=>{n=n.filter(t=>t!==e)});return{subscribe:i,pipe:u(i)}}function d(e){return(t,r)=>{r(e(t))}}function p(e){return(t,r)=>r(e)}function g(e){return(t,r)=>{e>0?e--:r(t)}}function m(e){return(t,r)=>{e(t)&&r(t)}}function v(...e){const t=Array(e.length).fill(!1),r=Array(e.length);return e.forEach((e,n)=>{e(e=>{r[n]=e,t[n]=!0})}),(e,n)=>{t.every(e=>e)&&n([e,...r])}}class y{constructor(){this.level=0}rebalance(){return this}adjust(){return this}remove(){return this}find(){}findWith(){}findMax(){return-Infinity}findMaxValue(){}insert(e,t){return new k({key:e,value:t,level:1})}walkWithin(){return[]}walk(){return[]}ranges(){return[]}rangesWithin(){return[]}empty(){return!0}isSingle(){return!0}isInvariant(){return!0}keys(){return[]}}const x=new y;Object.freeze(x);class b extends Error{constructor(e){super(`Unreachable case: ${e}`)}}class k{constructor({key:e,value:t,level:r,left:n=x,right:s=x}){this.key=e,this.value=t,this.level=r,this.left=n,this.right=s}remove(e){const{left:t,right:r}=this;if(e===this.key){if(t.empty())return r;if(r.empty())return t;{const[e,r]=t.last();return this.clone({key:e,value:r,left:t.deleteLast()}).adjust()}}return e<this.key?this.clone({left:t.remove(e)}).adjust():this.clone({right:r.remove(e)}).adjust()}empty(){return!1}find(e){return e===this.key?this.value:e<this.key?this.left.find(e):this.right.find(e)}findWith(e){const t=e(this.value);switch(t){case-1:return this.left.findWith(e);case 0:return[this.key,this.value];case 1:return this.right.findWith(e);default:throw new b(t)}}findMax(e){if(this.key===e)return e;if(this.key<e){const t=this.right.findMax(e);return-Infinity===t?this.key:t}return this.left.findMax(e)}findMaxValue(e){if(this.key===e)return this.value;if(this.key<e){const t=this.right.findMaxValue(e);return void 0===t?this.value:t}return this.left.findMaxValue(e)}insert(e,t){return e===this.key?this.clone({key:e,value:t}):e<this.key?this.clone({left:this.left.insert(e,t)}).rebalance():this.clone({right:this.right.insert(e,t)}).rebalance()}walkWithin(e,t){const{key:r,value:n}=this;let s=[];return r>e&&(s=s.concat(this.left.walkWithin(e,t))),r>=e&&r<=t&&s.push({key:r,value:n}),r<=t&&(s=s.concat(this.right.walkWithin(e,t))),s}walk(){return[...this.left.walk(),{key:this.key,value:this.value},...this.right.walk()]}last(){return this.right.empty()?[this.key,this.value]:this.right.last()}deleteLast(){return this.right.empty()?this.left:this.clone({right:this.right.deleteLast()}).adjust()}clone(e){return new k({key:void 0!==e.key?e.key:this.key,value:void 0!==e.value?e.value:this.value,level:void 0!==e.level?e.level:this.level,left:void 0!==e.left?e.left:this.left,right:void 0!==e.right?e.right:this.right})}isSingle(){return this.level>this.right.level}rebalance(){return this.skew().split()}adjust(){const{left:e,right:t,level:r}=this;if(t.level>=r-1&&e.level>=r-1)return this;if(r>t.level+1){if(e.isSingle())return this.clone({level:r-1}).skew();if(e.empty()||e.right.empty())throw new Error("Unexpected empty nodes");return e.right.clone({left:e.clone({right:e.right.left}),right:this.clone({left:e.right.right,level:r-1}),level:r})}if(this.isSingle())return this.clone({level:r-1}).split();if(t.empty()||t.left.empty())throw new Error("Unexpected empty nodes");{const e=t.left,n=e.isSingle()?t.level-1:t.level;return e.clone({left:this.clone({right:e.left,level:r-1}),right:t.clone({left:e.right,level:n}).split(),level:e.level+1})}}isInvariant(){const{left:e,right:t,level:r}=this;return r===e.level+1&&((r===t.level||r===t.level+1)&&(!(!t.empty()&&r<=t.right.level)&&(e.isInvariant()&&t.isInvariant())))}keys(){return[...this.left.keys(),this.key,...this.right.keys()]}ranges(){return this.toRanges(this.walk())}rangesWithin(e,t){return this.toRanges(this.walkWithin(e,t))}toRanges(e){if(0===e.length)return[];const t=e[0];let{key:r,value:n}=t;const s=[];for(let t=1;t<=e.length;t++){let i=e[t],o=i?i.key-1:Infinity;s.push({start:r,end:o,value:n}),i&&(r=i.key,n=i.value)}return s}split(){const{right:e,level:t}=this;return e.empty()||e.right.empty()||e.level!=t||e.right.level!=t?this:e.clone({left:this.clone({right:e.left}),level:t+1})}skew(){const{left:e}=this;return e.empty()||e.level!==this.level?this:e.clone({right:this.clone({left:e.right})})}}class I{constructor(e){this.root=e}static empty(){return new I(x)}find(e){return this.root.find(e)}findMax(e){return this.root.findMax(e)}findMaxValue(e){if(this.empty())throw new Error("Searching for max value in an empty tree");return this.root.findMaxValue(e)}findWith(e){return this.root.findWith(e)}insert(e,t){return new I(this.root.insert(e,t))}remove(e){return new I(this.root.remove(e))}empty(){return this.root.empty()}keys(){return this.root.keys()}walk(){return this.root.walk()}walkWithin(e,t){let r=this.root.findMax(e);return this.root.walkWithin(r,t)}ranges(){return this.root.ranges()}rangesWithin(e,t){let r=this.root.findMax(e);return this.root.rangesWithin(r,t)}isInvariant(){return this.root.isInvariant()}}class w{constructor(e){this.nanIndices=[],this.rangeTree=e;let t=I.empty(),r=0;const n=e.ranges();let s=!1;for(let{start:e,end:i,value:o}of n)isNaN(o)?(this.nanIndices.push(e),s||(t=t.insert(r,{startIndex:e,endIndex:Infinity,size:o})),s=!0):s||(t=t.insert(r,{startIndex:e,endIndex:i,size:o}),r+=(i-e+1)*o);this.offsetTree=t}static create(){return new w(I.empty())}empty(){return this.rangeTree.empty()}insert(e,t,r){let n=this.rangeTree;if(n.empty())return new w(n.insert(0,r));if(this.nanIndices.length&&this.nanIndices.indexOf(e)>-1){for(const e of this.nanIndices)n=n.insert(e,r);return new w(n)}const s=n.rangesWithin(e-1,t+1);if(s.some(n=>n.start===e&&(n.end===t||Infinity===n.end)&&n.value===r))return this;let i=!1,o=!1;for(const{start:e,end:l,value:a}of s)i?(t>=e||r===a)&&(n=n.remove(e)):(o=a!==r,i=!0),l>t&&t>=e&&(a===r||isNaN(a)||(n=n.insert(t+1,a)));return o&&(n=n.insert(e,r)),n===this.rangeTree?this:new w(n)}insertSpots(e,t){if(this.empty()){let r=this.rangeTree;for(const n of e)r=r.insert(n,t).insert(n+1,NaN);return new w(r)}throw new Error("attempting to overwrite non-empty tree")}offsetOf(e){if(this.offsetTree.empty())return 0;const t=this.offsetTree.findWith(t=>t.startIndex>e?-1:t.endIndex<e?1:0);if(t){const[r,{startIndex:n,size:s}]=t;return r+(e-n)*s}throw new Error(`Requested offset outside of the known ones, index: ${e}`)}itemAt(e){const t=this.rangeTree.findMaxValue(e);return{index:e,size:t,offset:NaN}}indexRange(e,t){if(0===t)return[];if(this.rangeTree.empty())return[{index:0,size:0,offset:NaN}];const r=this.rangeTree.rangesWithin(e,t),n=[];for(const s of r){const r=Math.max(e,s.start),i=void 0===s.end?Infinity:s.end,o=Math.min(t,i);for(let e=r;e<=o;e++)n.push({index:e,size:s.value,offset:NaN})}return n}range(e,t,r=0,n=Infinity){if(this.offsetTree.empty())return[{index:0,size:0,offset:0}];const s=this.offsetTree.rangesWithin(e,t),i=[];for(let{start:o,value:{startIndex:l,endIndex:a,size:h}}of s){let s=o,u=l;if(o<e&&(u+=Math.floor((e-o)/h),s+=(u-l)*h),u<r&&(s+=(r-u)*h,u=r),isNaN(h))return i.push({index:u,size:0,offset:s}),i;a=Math.min(a,n);for(let e=u;e<=a&&!(s>t);e++)i.push({index:e,size:h,offset:s}),s+=h}return i}total(e){const t=this.rangeTree.rangesWithin(0,e);let r=0;for(let{start:n,end:s,value:i}of t)s=Math.min(s,e),r+=(s-n+1)*(isNaN(i)?0:i);return r}getOffsets(e){let t=I.empty();return e.forEach(e=>{const r=this.offsetOf(e);t=t.insert(r,e)}),new E(t)}}class E{constructor(e){this.tree=e}findMaxValue(e){return this.tree.findMaxValue(e)}empty(){return this.tree.empty()}}class M{transpose(e){return e.map(e=>({groupIndex:0,index:e.index,offset:e.offset,size:e.size,transposedIndex:e.index,type:"item"}))}}class T{constructor(e){this.count=e.reduce((e,t)=>e+t+1,0);let t=I.empty(),r=0,n=0;for(let s of e)t=t.insert(n,[r,n]),r++,n+=s+1;this.tree=t}totalCount(){return this.count}transpose(e){return e.map(e=>{const t=this.tree.find(e.index);if(t)return{groupIndex:t[0],index:e.index,offset:e.offset,size:e.size,type:"group"};const[r]=this.tree.findMaxValue(e.index);return{groupIndex:r,index:e.index,offset:e.offset,size:e.size,transposedIndex:e.index-r-1,type:"item"}})}groupIndices(){return this.tree.keys()}}function N(e){let t,r=e=>{t&&t(e)},n=!1;return s=>{t=s,n||(e.subscribe(r),n=!0)}}function z(e){return e.next}const S=e=>e.length>0?e[0].offset:0,W=([e,t])=>e.total(t-1),C=({overscan:e=0,totalCount:t=0,itemHeight:r})=>{const n=c(0),s=c(0),i=c(0),o=c(0),l=c(),a=c(t),h=c(),u=c(),y=c(!1);let x=w.create();const b=c([]),k=c(void 0,!1);r&&(x=x.insert(0,0,r));const I=c(x);r||l.pipe(v(I.subscribe,b.subscribe)).subscribe(([e,t,r])=>{let n=t;for(let{start:t,end:s,size:i}of e)n=n.empty()&&t==s&&r.indexOf(t)>-1?n.insertSpots(r,i):n.insert(t,s,i);n!==t&&I.next(n)});let E=new M;h.subscribe(e=>{E=new T(e),a.next(E.totalCount()),b.next(E.groupIndices())});const C=f(I.subscribe,a.subscribe).pipe(d(W)),H=f(C.subscribe,o.subscribe).pipe(d(([e,t])=>e+t)),R=f(I.subscribe,b.subscribe).pipe(d(([e,t])=>e.getOffsets(t))),V=c([]);f(I.subscribe,u.subscribe,a.subscribe).pipe(m(e=>e[1]>0),d(([e,t,r])=>{const n=Math.max(0,Math.min(t-1,r));return E.transpose(e.indexRange(0,n))})).subscribe(V.next),f(I.subscribe,R.subscribe,i.subscribe).pipe(m(e=>!e[1].empty()&&!e[0].empty()),v(V.subscribe),d(([[e,t,r],n])=>{const s=t.findMaxValue(r);if(1===n.length&&n[0].index===s)return n;const i=e.itemAt(s);return E.transpose([i])})).subscribe(V.next);const O=V.pipe(d(e=>e.reduce((e,t)=>e+t.size,0))),A=V.pipe(d(e=>e.length&&e[e.length-1].index+1)),j=f(n.subscribe,i.subscribe,O.subscribe,s.subscribe,o.subscribe,A.subscribe,a.subscribe,I.subscribe).pipe(function(e,t){let r=t;return(t,n)=>{n(r=e(r,t))}}((e=>(t,[r,n,s,i,o,l,a,h])=>{const u=t.length;if(0===a)return 0===u?t:[];const c=S(t),f=c-n+i-o-s,d=Math.max(a-1,0),p=u>0&&(t[0].index<l||t[u-1].index>d);if(f<r||p){const t=Math.max(n+s,s),i=n+r+2*e-1,o=E.transpose(h.range(t,i,l,d));return o}if(c>n+s){const t=Math.max(n+s-2*e,s),i=n+r-1;return E.transpose(h.range(t,i,l,d))}return t})(e),[])),L=c(0);let $=0;j.pipe(d(e=>e.length?e[e.length-1].index:0)).pipe(v(a.subscribe)).subscribe(([e,t])=>{e==t-1&&$!==e&&($=e,L.next(e))});const D=f(j.subscribe,i.subscribe,O.subscribe).pipe(d(([e,t,r])=>S(e)-t-r));i.pipe(g(1),p(!0)).subscribe(y.next),i.pipe(g(1),p(!1),function(e){let t,r;return(n,s)=>{t=n,r&&clearTimeout(r),r=setTimeout(()=>{s(t)},e)}}(200)).subscribe(y.next);const F=k.pipe(v(I.subscribe,O.subscribe,b.subscribe,n.subscribe,a.subscribe),d(([e,t,r,n,s,i])=>{"number"==typeof e&&(e={index:e,align:"start"});let{index:o,align:l="start"}=e;o=Math.max(0,o,Math.min(i-1,o));let a=t.offsetOf(o);return"end"==l?a=a-s+t.itemAt(o).size:"center"===l?a=Math.round(a-s/2+t.itemAt(o).size/2):-1===n.indexOf(o)&&(a-=r),a})),P=b.pipe();return{groupCounts:z(h),itemHeights:z(l),footerHeight:z(o),listHeight:z(s),viewportHeight:z(n),scrollTop:z(i),topItemCount:z(u),totalCount:z(a),scrollToIndex:z(k),list:N(j),topList:N(V),listOffset:N(D),totalHeight:N(H),endReached:N(L),isScrolling:N(y),stickyItems:N(b),groupIndices:N(P),scrollTo:N(F)}},H=(e,t,n)=>{const s=r(null),i=r(0),o=new a(t=>{const r=t[0].contentRect.height;i.current!==r&&(i.current=r,n&&n(t[0].target),e(r))});return e=>{e?(o.observe(e),t&&t(e),s.current=e):(o.unobserve(s.current),s.current=null)}};function R(e,t){const[r,i]=n(t);return s(()=>{e(i)},[]),r}const V={height:"40rem",overflowY:"auto",WebkitOverflowScrolling:"touch",position:"relative",outline:"none"},O=({className:t,style:n,reportScrollTop:s,scrollTo:i,children:l})=>{const a=r(null),h=o(e=>{s(e.target.scrollTop)},[]),u=o(e=>{e?(e.addEventListener("scroll",h,{passive:!0}),a.current=e):a.current.removeEventListener("scroll",h)},[]);return i(e=>{const t={top:e};a.current.scrollTo(t)}),e.createElement("div",{ref:u,style:n,tabIndex:0,className:t},l)},A=({children:t,style:r,className:n,ScrollContainer:s=O})=>{const{scrollTop:o,scrollTo:l}=i(h);return e.createElement(s,{style:{...V,...r},reportScrollTop:o,scrollTo:l,className:n},t)},j=({list:t,transform:r="",render:n})=>{const{stickyItems:s}=i(h),l=R(t,[]),a=R(s,[]),u=o(e=>{const t=a.some(t=>t===e),n={transform:r,zIndex:t?2:void 0,position:t?"relative":void 0};return n},[a,r]);return 0===l.length?null:e.createElement(e.Fragment,null,l.map(t=>e.createElement("div",{key:t.index,"data-index":t.index,"data-known-size":t.size,style:u(t.index)},n(t))))},L=()=>{const t=R(i(h).totalHeight,0);return e.createElement("div",{style:{height:`${t}px`,position:"absolute",top:0}}," ")},$=({footer:t})=>{const r=H(i(h).footerHeight);return e.createElement("footer",{ref:r},t())},D={top:0,position:"sticky",height:"100%",overflow:"hidden",WebkitBackfaceVisibility:"hidden"},F=({style:t,footer:r,item:n,fixedItemHeight:s,ScrollContainer:l,className:a})=>{const{itemHeights:u,listHeight:c,viewportHeight:f,listOffset:d,list:p,topList:g}=i(h),m=R(d,0),v=o(e=>{const t=[];for(var r=0,n=e.length;r<n;r++){let n=e.item(r);if(!n||"DIV"!==n.tagName)continue;const s=parseInt(n.dataset.index),i=n.offsetHeight;0===t.length||t[t.length-1].size!==i?t.push({start:s,end:s,size:i}):t[t.length-1].end++}t.length>0&&u(t)},[]),y=H(c,()=>{},e=>{s||v(e.children)}),x=H(f,e=>{""===e.style.position&&(e.style.position="-webkit-sticky")}),b=`translateY(${m}px)`,k=`translateY(${-m}px)`;return e.createElement(A,{style:t,ScrollContainer:l,className:a},e.createElement("div",{style:D,ref:x},e.createElement("div",{style:{transform:b}},e.createElement("div",{ref:y},e.createElement(j,{list:g,transform:k,render:n}),e.createElement(j,{list:p,render:n}),r&&e.createElement($,{footer:r})))),e.createElement(L,null))},P=({contextValue:t,style:r,className:n,item:s,footer:i,itemHeight:o,ScrollContainer:l})=>e.createElement(h.Provider,{value:t},e.createElement(F,{style:r||{},className:n,item:s,footer:i,fixedItemHeight:void 0!==o,ScrollContainer:l}));class U extends l{constructor(e){super(e),this.itemRender=(e=>this.props.item(e.index)),this.state=C(e)}static getDerivedStateFromProps(e,t){return t.isScrolling(e.scrollingStateChange),t.endReached(e.endReached),t.topItemCount(e.topItems||0),t.totalCount(e.totalCount),null}scrollToIndex(e){this.state.scrollToIndex(e)}render(){return e.createElement(P,{contextValue:this.state,style:this.props.style,className:this.props.className,item:this.itemRender,footer:this.props.footer,itemHeight:this.props.itemHeight,ScrollContainer:this.props.ScrollContainer})}}class Y extends l{constructor(e){super(e),this.itemRender=(e=>"group"==e.type?this.props.group(e.groupIndex):this.props.item(e.transposedIndex,e.groupIndex)),this.state=C(e)}static getDerivedStateFromProps(e,t){return t.endReached(e.endReached),t.isScrolling(e.scrollingStateChange),t.groupCounts(e.groupCounts),t.groupIndices(e.groupIndices),null}scrollToIndex(e){this.state.scrollToIndex(e)}render(){return e.createElement(P,{contextValue:this.state,style:this.props.style,className:this.props.className,item:this.itemRender,footer:this.props.footer,itemHeight:this.props.itemHeight,ScrollContainer:this.props.ScrollContainer})}}export{Y as GroupedVirtuoso,U as Virtuoso,P as VirtuosoPresentation};
//# sourceMappingURL=react-virtuoso.es.production.js.map

@@ -54,3 +54,3 @@ (function (global, factory) {

}
function subject(initial) {
function subject(initial, distinct = true) {
let subscribers = [];

@@ -60,3 +60,3 @@ let val = initial;

const next = newVal => {
if (newVal !== val) {
if (!distinct || newVal !== val) {
val = newVal;

@@ -682,23 +682,33 @@ subscribers.forEach(subscriber => subscriber(newVal));

class OffsetList {
static create() {
return new OffsetList(AATree.empty());
}
constructor(rangeTree) {
this.nanIndices = [];
this.rangeTree = rangeTree;
let offsetTree = AATree.empty();
let offset = 0;
const ranges = rangeTree.ranges();
let nanFound = false;
for (const {
for (let {
start: startIndex,
end: endIndex,
value: size
} of rangeTree.ranges()) {
offsetTree = offsetTree.insert(offset, {
startIndex,
endIndex: endIndex,
size
});
} of ranges) {
if (isNaN(size)) {
this.nanIndices.push(startIndex);
if (endIndex !== Infinity) {
if (!nanFound) {
offsetTree = offsetTree.insert(offset, {
startIndex,
endIndex: Infinity,
size
});
}
nanFound = true;
} else if (!nanFound) {
offsetTree = offsetTree.insert(offset, {
startIndex,
endIndex: endIndex,
size
});
offset += (endIndex - startIndex + 1) * size;

@@ -711,2 +721,6 @@ }

static create() {
return new OffsetList(AATree.empty());
}
empty() {

@@ -721,2 +735,11 @@ return this.rangeTree.empty();

return new OffsetList(tree.insert(0, size));
} // tree is in non-complete state - we know the group sizes, but not the item sizes
if (this.nanIndices.length && this.nanIndices.indexOf(start) > -1) {
for (const nanIndex of this.nanIndices) {
tree = tree.insert(nanIndex, size);
}
return new OffsetList(tree);
} // extend the range in both directions, so that we can get adjacent neighbours.

@@ -770,7 +793,13 @@ // if the previous / next ones have the same value as the one we are about to insert,

insertException(index, value) {
insertSpots(spotIndexes, value) {
if (this.empty()) {
return new OffsetList(this.rangeTree.insert(1, NaN).insert(index, value));
let tree = this.rangeTree;
for (const spot of spotIndexes) {
tree = tree.insert(spot, value).insert(spot + 1, NaN);
}
return new OffsetList(tree);
} else {
return this.insert(index, index, value);
throw new Error('attempting to overwrite non-empty tree');
}

@@ -917,3 +946,3 @@ }

end = Math.min(end, endIndex);
total += (end - start + 1) * size;
total += (end - start + 1) * (isNaN(size) ? 0 : size);
}

@@ -1057,2 +1086,3 @@

const stickyItems$ = subject([]);
const scrollToIndex$ = subject(undefined, false);

@@ -1066,3 +1096,3 @@ if (itemHeight) {

if (!itemHeight) {
itemHeights$.pipe(withLatestFrom(offsetList$.subscribe, stickyItems$.subscribe)).subscribe(([heights, offsetList, _]) => {
itemHeights$.pipe(withLatestFrom(offsetList$.subscribe, stickyItems$.subscribe)).subscribe(([heights, offsetList, stickyItems]) => {
let newList = offsetList;

@@ -1075,3 +1105,7 @@

} of heights) {
newList = newList.insert(start, end, size);
if (newList.empty() && start == end && stickyItems.indexOf(start) > -1) {
newList = newList.insertSpots(stickyItems, size);
} else {
newList = newList.insert(start, end, size);
}
}

@@ -1145,2 +1179,8 @@

const list$ = combineLatest(viewportHeight$.subscribe, scrollTop$.subscribe, topListHeight$.subscribe, listHeight$.subscribe, footerHeight$.subscribe, minListIndex$.subscribe, totalCount$.subscribe, offsetList$.subscribe).pipe(scan(listScanner(overscan), []));
/*
list$.subscribe(list => {
console.log(list)
})
*/
const endReached$ = subject(0);

@@ -1159,2 +1199,30 @@ let currentEndIndex = 0;

scrollTop$.pipe(skip(1), mapTo(false), debounceTime(200)).subscribe(isScrolling$.next);
const scrollTo$ = scrollToIndex$.pipe(withLatestFrom(offsetList$.subscribe, topListHeight$.subscribe, stickyItems$.subscribe, viewportHeight$.subscribe, totalCount$.subscribe), map(([location, offsetList, topListHeight, stickyItems, viewportHeight, totalCount]) => {
if (typeof location === 'number') {
location = {
index: location,
align: 'start'
};
}
let {
index,
align = 'start'
} = location;
index = Math.max(0, index, Math.min(totalCount - 1, index));
let offset = offsetList.offsetOf(index);
if (align == 'end') {
offset = offset - viewportHeight + offsetList.itemAt(index).size;
} else if (align === 'center') {
offset = Math.round(offset - viewportHeight / 2 + offsetList.itemAt(index).size / 2);
} else {
if (stickyItems.indexOf(index) === -1) {
offset -= topListHeight;
}
}
return offset;
}));
const groupIndices$ = stickyItems$.pipe();
return {

@@ -1169,2 +1237,3 @@ groupCounts: makeInput(groupCounts$),

totalCount: makeInput(totalCount$),
scrollToIndex: makeInput(scrollToIndex$),
list: makeOutput(list$),

@@ -1176,3 +1245,5 @@ topList: makeOutput(topList$),

isScrolling: makeOutput(isScrolling$),
stickyItems: makeOutput(stickyItems$)
stickyItems: makeOutput(stickyItems$),
groupIndices: makeOutput(groupIndices$),
scrollTo: makeOutput(scrollTo$)
};

@@ -1230,12 +1301,13 @@ };

};
const VirtuosoScroller = ({
children,
style
const DefaultScrollContainer = ({
className,
style,
reportScrollTop,
scrollTo,
children
}) => {
const {
scrollTop
} = React.useContext(VirtuosoContext);
const elRef = React.useRef(null);
const onScroll = React.useCallback(e => {
scrollTop(e.target.scrollTop);
reportScrollTop(e.target.scrollTop);
}, []);

@@ -1252,8 +1324,33 @@ const ref = React.useCallback(theRef => {

}, []);
scrollTo(scrollTop => {
const goTo = {
top: scrollTop
};
elRef.current.scrollTo(goTo);
});
return React__default.createElement("div", {
ref: ref,
style: style,
tabIndex: 0,
className: className
}, children);
};
const VirtuosoScroller = ({
children,
style,
className,
ScrollContainer = DefaultScrollContainer
}) => {
const {
scrollTop,
scrollTo
} = React.useContext(VirtuosoContext);
return React__default.createElement(ScrollContainer, {
style: { ...scrollerStyle,
...style
},
tabIndex: 0
reportScrollTop: scrollTop,
scrollTo: scrollTo,
className: className
}, children);

@@ -1327,3 +1424,5 @@ };

item,
fixedItemHeight
fixedItemHeight,
ScrollContainer,
className
}) => {

@@ -1380,3 +1479,5 @@ const {

return React__default.createElement(VirtuosoScroller, {
style: style
style: style,
ScrollContainer: ScrollContainer,
className: className
}, React__default.createElement("div", {

@@ -1406,5 +1507,7 @@ style: viewportStyle,

style,
className,
item,
footer,
itemHeight
itemHeight,
ScrollContainer
}) => {

@@ -1415,5 +1518,7 @@ return React__default.createElement(VirtuosoContext.Provider, {

style: style || {},
className: className,
item: item,
footer: footer,
fixedItemHeight: itemHeight !== undefined
fixedItemHeight: itemHeight !== undefined,
ScrollContainer: ScrollContainer
}));

@@ -1425,3 +1530,3 @@ };

this.itemRenderer = item => {
this.itemRender = item => {
return this.props.item(item.index);

@@ -1441,2 +1546,6 @@ };

scrollToIndex(location) {
this.state.scrollToIndex(location);
}
render() {

@@ -1446,5 +1555,7 @@ return React__default.createElement(VirtuosoPresentation, {

style: this.props.style,
item: this.itemRenderer,
className: this.props.className,
item: this.itemRender,
footer: this.props.footer,
itemHeight: this.props.itemHeight
itemHeight: this.props.itemHeight,
ScrollContainer: this.props.ScrollContainer
});

@@ -1474,5 +1585,10 @@ }

state.groupCounts(props.groupCounts);
state.groupIndices(props.groupIndices);
return null;
}
scrollToIndex(location) {
this.state.scrollToIndex(location);
}
render() {

@@ -1482,5 +1598,7 @@ return React__default.createElement(VirtuosoPresentation, {

style: this.props.style,
className: this.props.className,
item: this.itemRender,
footer: this.props.footer,
itemHeight: this.props.itemHeight
itemHeight: this.props.itemHeight,
ScrollContainer: this.props.ScrollContainer
});

@@ -1487,0 +1605,0 @@ }

@@ -1,2 +0,2 @@

!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("react"),require("resize-observer-polyfill")):"function"==typeof define&&define.amd?define(["exports","react","resize-observer-polyfill"],t):(e=e||self,t(e["react-virtuoso"]={},e.React,e.ResizeObserver))}(this,function(e,t,r){"use strict";var n="default"in t?t.default:t;r=r&&r.hasOwnProperty("default")?r.default:r;const i=t.createContext(void 0);function s(e){return function(...t){const r=function(...e){return 0===e.length?(e,t)=>t(e):1===e.length?e[0]:(t,r)=>{let n=e=>r(e);e.slice().reverse().forEach(e=>{const t=n;n=(r=>e(r,t))}),n(t)}}(...t);return function(e,t){const r=r=>e(e=>t(e,r));return{subscribe:r,pipe:s(r)}}(e,r)}}function o(e){let t=[],r=e;const n=e=>(t.push(e),void 0!==r&&e(r),()=>{t=t.filter(t=>t!==e)});return{next:e=>{e!==r&&(r=e,t.forEach(t=>t(e)))},subscribe:n,pipe:s(n),subscribers:t}}function l(...e){const t=Array(e.length).fill(!1),r=Array(e.length);let n=[];const i=e=>{t.every(e=>e)&&e.forEach(e=>e(r))};e.forEach((e,s)=>{e(e=>{t[s]=!0,r[s]=e,i(n)})});const o=e=>(n.push(e),i([e]),()=>{n=n.filter(t=>t!==e)});return{subscribe:o,pipe:s(o)}}function u(e){return(t,r)=>{r(e(t))}}function a(e){return(t,r)=>r(e)}function h(e){return(t,r)=>{e>0?e--:r(t)}}function c(e){return(t,r)=>{e(t)&&r(t)}}function f(...e){const t=Array(e.length).fill(!1),r=Array(e.length);return e.forEach((e,n)=>{e(e=>{r[n]=e,t[n]=!0})}),(e,n)=>{t.every(e=>e)&&n([e,...r])}}class d{constructor(){this.level=0}rebalance(){return this}adjust(){return this}remove(){return this}find(){}findWith(){}findMax(){return-Infinity}findMaxValue(){}insert(e,t){return new m({key:e,value:t,level:1})}walkWithin(){return[]}walk(){return[]}ranges(){return[]}rangesWithin(){return[]}empty(){return!0}isSingle(){return!0}isInvariant(){return!0}keys(){return[]}}const p=new d;Object.freeze(p);class g extends Error{constructor(e){super(`Unreachable case: ${e}`)}}class m{constructor({key:e,value:t,level:r,left:n=p,right:i=p}){this.key=e,this.value=t,this.level=r,this.left=n,this.right=i}remove(e){const{left:t,right:r}=this;if(e===this.key){if(t.empty())return r;if(r.empty())return t;{const[e,r]=t.last();return this.clone({key:e,value:r,left:t.deleteLast()}).adjust()}}return e<this.key?this.clone({left:t.remove(e)}).adjust():this.clone({right:r.remove(e)}).adjust()}empty(){return!1}find(e){return e===this.key?this.value:e<this.key?this.left.find(e):this.right.find(e)}findWith(e){const t=e(this.value);switch(t){case-1:return this.left.findWith(e);case 0:return[this.key,this.value];case 1:return this.right.findWith(e);default:throw new g(t)}}findMax(e){if(this.key===e)return e;if(this.key<e){const t=this.right.findMax(e);return-Infinity===t?this.key:t}return this.left.findMax(e)}findMaxValue(e){if(this.key===e)return this.value;if(this.key<e){const t=this.right.findMaxValue(e);return void 0===t?this.value:t}return this.left.findMaxValue(e)}insert(e,t){return e===this.key?this.clone({key:e,value:t}):e<this.key?this.clone({left:this.left.insert(e,t)}).rebalance():this.clone({right:this.right.insert(e,t)}).rebalance()}walkWithin(e,t){const{key:r,value:n}=this;let i=[];return r>e&&(i=i.concat(this.left.walkWithin(e,t))),r>=e&&r<=t&&i.push({key:r,value:n}),r<=t&&(i=i.concat(this.right.walkWithin(e,t))),i}walk(){return[...this.left.walk(),{key:this.key,value:this.value},...this.right.walk()]}last(){return this.right.empty()?[this.key,this.value]:this.right.last()}deleteLast(){return this.right.empty()?this.left:this.clone({right:this.right.deleteLast()}).adjust()}clone(e){return new m({key:void 0!==e.key?e.key:this.key,value:void 0!==e.value?e.value:this.value,level:void 0!==e.level?e.level:this.level,left:void 0!==e.left?e.left:this.left,right:void 0!==e.right?e.right:this.right})}isSingle(){return this.level>this.right.level}rebalance(){return this.skew().split()}adjust(){const{left:e,right:t,level:r}=this;if(t.level>=r-1&&e.level>=r-1)return this;if(r>t.level+1){if(e.isSingle())return this.clone({level:r-1}).skew();if(e.empty()||e.right.empty())throw new Error("Unexpected empty nodes");return e.right.clone({left:e.clone({right:e.right.left}),right:this.clone({left:e.right.right,level:r-1}),level:r})}if(this.isSingle())return this.clone({level:r-1}).split();if(t.empty()||t.left.empty())throw new Error("Unexpected empty nodes");{const e=t.left,n=e.isSingle()?t.level-1:t.level;return e.clone({left:this.clone({right:e.left,level:r-1}),right:t.clone({left:e.right,level:n}).split(),level:e.level+1})}}isInvariant(){const{left:e,right:t,level:r}=this;return r===e.level+1&&((r===t.level||r===t.level+1)&&(!(!t.empty()&&r<=t.right.level)&&(e.isInvariant()&&t.isInvariant())))}keys(){return[...this.left.keys(),this.key,...this.right.keys()]}ranges(){return this.toRanges(this.walk())}rangesWithin(e,t){return this.toRanges(this.walkWithin(e,t))}toRanges(e){if(0===e.length)return[];const t=e[0];let{key:r,value:n}=t;const i=[];for(let t=1;t<=e.length;t++){let s=e[t],o=s?s.key-1:Infinity;i.push({start:r,end:o,value:n}),s&&(r=s.key,n=s.value)}return i}split(){const{right:e,level:t}=this;return e.empty()||e.right.empty()||e.level!=t||e.right.level!=t?this:e.clone({left:this.clone({right:e.left}),level:t+1})}skew(){const{left:e}=this;return e.empty()||e.level!==this.level?this:e.clone({right:this.clone({left:e.right})})}}class v{constructor(e){this.root=e}static empty(){return new v(p)}find(e){return this.root.find(e)}findMax(e){return this.root.findMax(e)}findMaxValue(e){if(this.empty())throw new Error("Searching for max value in an empty tree");return this.root.findMaxValue(e)}findWith(e){return this.root.findWith(e)}insert(e,t){return new v(this.root.insert(e,t))}remove(e){return new v(this.root.remove(e))}empty(){return this.root.empty()}keys(){return this.root.keys()}walk(){return this.root.walk()}walkWithin(e,t){let r=this.root.findMax(e);return this.root.walkWithin(r,t)}ranges(){return this.root.ranges()}rangesWithin(e,t){let r=this.root.findMax(e);return this.root.rangesWithin(r,t)}isInvariant(){return this.root.isInvariant()}}class y{static create(){return new y(v.empty())}constructor(e){this.rangeTree=e;let t=v.empty(),r=0;for(const{start:n,end:i,value:s}of e.ranges())t=t.insert(r,{startIndex:n,endIndex:i,size:s}),Infinity!==i&&(r+=(i-n+1)*s);this.offsetTree=t}empty(){return this.rangeTree.empty()}insert(e,t,r){let n=this.rangeTree;if(n.empty())return new y(n.insert(0,r));const i=n.rangesWithin(e-1,t+1);if(i.some(n=>n.start===e&&(n.end===t||Infinity===n.end)&&n.value===r))return this;let s=!1,o=!1;for(const{start:e,end:l,value:u}of i)s?(t>=e||r===u)&&(n=n.remove(e)):(o=u!==r,s=!0),l>t&&t>=e&&(u===r||isNaN(u)||(n=n.insert(t+1,u)));return o&&(n=n.insert(e,r)),n===this.rangeTree?this:new y(n)}insertException(e,t){return this.empty()?new y(this.rangeTree.insert(1,NaN).insert(e,t)):this.insert(e,e,t)}offsetOf(e){if(this.offsetTree.empty())return 0;const t=this.offsetTree.findWith(t=>t.startIndex>e?-1:t.endIndex<e?1:0);if(t){const[r,{startIndex:n,size:i}]=t;return r+(e-n)*i}throw new Error(`Requested offset outside of the known ones, index: ${e}`)}itemAt(e){const t=this.rangeTree.findMaxValue(e);return{index:e,size:t,offset:NaN}}indexRange(e,t){if(0===t)return[];if(this.rangeTree.empty())return[{index:0,size:0,offset:NaN}];const r=this.rangeTree.rangesWithin(e,t),n=[];for(const i of r){const r=Math.max(e,i.start),s=void 0===i.end?Infinity:i.end,o=Math.min(t,s);for(let e=r;e<=o;e++)n.push({index:e,size:i.value,offset:NaN})}return n}range(e,t,r=0,n=Infinity){if(this.offsetTree.empty())return[{index:0,size:0,offset:0}];const i=this.offsetTree.rangesWithin(e,t),s=[];for(let{start:o,value:{startIndex:l,endIndex:u,size:a}}of i){let i=o,h=l;if(o<e&&(h+=Math.floor((e-o)/a),i+=(h-l)*a),h<r&&(i+=(r-h)*a,h=r),isNaN(a))return s.push({index:h,size:0,offset:i}),s;u=Math.min(u,n);for(let e=h;e<=u&&!(i>t);e++)s.push({index:e,size:a,offset:i}),i+=a}return s}total(e){const t=this.rangeTree.rangesWithin(0,e);let r=0;for(let{start:n,end:i,value:s}of t)i=Math.min(i,e),r+=(i-n+1)*s;return r}getOffsets(e){let t=v.empty();return e.forEach(e=>{const r=this.offsetOf(e);t=t.insert(r,e)}),new x(t)}}class x{constructor(e){this.tree=e}findMaxValue(e){return this.tree.findMaxValue(e)}empty(){return this.tree.empty()}}class b{transpose(e){return e.map(e=>({groupIndex:0,index:e.index,offset:e.offset,size:e.size,transposedIndex:e.index,type:"item"}))}}class k{constructor(e){this.count=e.reduce((e,t)=>e+t+1,0);let t=v.empty(),r=0,n=0;for(let i of e)t=t.insert(n,[r,n]),r++,n+=i+1;this.tree=t}totalCount(){return this.count}transpose(e){return e.map(e=>{const t=this.tree.find(e.index);if(t)return{groupIndex:t[0],index:e.index,offset:e.offset,size:e.size,type:"group"};const[r]=this.tree.findMaxValue(e.index);return{groupIndex:r,index:e.index,offset:e.offset,size:e.size,transposedIndex:e.index-r-1,type:"item"}})}groupIndices(){return this.tree.keys()}}function w(e){let t,r=e=>{t&&t(e)},n=!1;return i=>{t=i,n||(e.subscribe(r),n=!0)}}function I(e){return e.next}const E=e=>e.length>0?e[0].offset:0,M=([e,t])=>e.total(t-1),z=({overscan:e=0,totalCount:t=0,itemHeight:r})=>{const n=o(0),i=o(0),s=o(0),d=o(0),p=o(),g=o(t),m=o(),v=o(),x=o(!1);let z=y.create();const C=o([]);r&&(z=z.insert(0,0,r));const W=o(z);r||p.pipe(f(W.subscribe,C.subscribe)).subscribe(([e,t,r])=>{let n=t;for(let{start:t,end:r,size:i}of e)n=n.insert(t,r,i);n!==t&&W.next(n)});let R=new b;m.subscribe(e=>{R=new k(e),g.next(R.totalCount()),C.next(R.groupIndices())});const H=l(W.subscribe,g.subscribe).pipe(u(M)),T=l(H.subscribe,d.subscribe).pipe(u(([e,t])=>e+t)),V=l(W.subscribe,C.subscribe).pipe(u(([e,t])=>e.getOffsets(t))),S=o([]);l(W.subscribe,v.subscribe,g.subscribe).pipe(c(e=>e[1]>0),u(([e,t,r])=>{const n=Math.max(0,Math.min(t-1,r));return R.transpose(e.indexRange(0,n))})).subscribe(S.next),l(W.subscribe,V.subscribe,s.subscribe).pipe(c(e=>!e[1].empty()&&!e[0].empty()),f(S.subscribe),u(([[e,t,r],n])=>{const i=t.findMaxValue(r);if(1===n.length&&n[0].index===i)return n;const s=e.itemAt(i);return R.transpose([s])})).subscribe(S.next);const N=S.pipe(u(e=>e.reduce((e,t)=>e+t.size,0))),O=S.pipe(u(e=>e.length&&e[e.length-1].index+1)),j=l(n.subscribe,s.subscribe,N.subscribe,i.subscribe,d.subscribe,O.subscribe,g.subscribe,W.subscribe).pipe(function(e,t){let r=t;return(t,n)=>{n(r=e(r,t))}}((e=>(t,[r,n,i,s,o,l,u,a])=>{const h=t.length;if(0===u)return 0===h?t:[];const c=E(t),f=c-n+s-o-i,d=Math.max(u-1,0),p=h>0&&(t[0].index<l||t[h-1].index>d);if(f<r||p){const t=Math.max(n+i,i),s=n+r+2*e-1,o=R.transpose(a.range(t,s,l,d));return o}if(c>n+i){const t=Math.max(n+i-2*e,i),s=n+r-1;return R.transpose(a.range(t,s,l,d))}return t})(e),[])),L=o(0);let P=0;j.pipe(u(e=>e.length?e[e.length-1].index:0)).pipe(f(g.subscribe)).subscribe(([e,t])=>{e==t-1&&P!==e&&(P=e,L.next(e))});const A=l(j.subscribe,s.subscribe,N.subscribe).pipe(u(([e,t,r])=>E(e)-t-r));return s.pipe(h(1),a(!0)).subscribe(x.next),s.pipe(h(1),a(!1),function(e){let t,r;return(n,i)=>{t=n,r&&clearTimeout(r),r=setTimeout(()=>{i(t)},e)}}(200)).subscribe(x.next),{groupCounts:I(m),itemHeights:I(p),footerHeight:I(d),listHeight:I(i),viewportHeight:I(n),scrollTop:I(s),topItemCount:I(v),totalCount:I(g),list:w(j),topList:w(S),listOffset:w(A),totalHeight:w(T),endReached:w(L),isScrolling:w(x),stickyItems:w(C)}},C=(e,n,i)=>{const s=t.useRef(null),o=t.useRef(0),l=new r(t=>{const r=t[0].contentRect.height;o.current!==r&&(o.current=r,i&&i(t[0].target),e(r))});return e=>{e?(l.observe(e),n&&n(e),s.current=e):(l.unobserve(s.current),s.current=null)}};function W(e,r){const[n,i]=t.useState(r);return t.useLayoutEffect(()=>{e(i)},[]),n}const R={height:"40rem",overflowY:"auto",WebkitOverflowScrolling:"touch",position:"relative",outline:"none"},H=({children:e,style:r})=>{const{scrollTop:s}=t.useContext(i),o=t.useRef(null),l=t.useCallback(e=>{s(e.target.scrollTop)},[]),u=t.useCallback(e=>{e?(e.addEventListener("scroll",l,{passive:!0}),o.current=e):o.current.removeEventListener("scroll",l)},[]);return n.createElement("div",{ref:u,style:{...R,...r},tabIndex:0},e)},T=({list:e,transform:r="",render:s})=>{const{stickyItems:o}=t.useContext(i),l=W(e,[]),u=W(o,[]),a=t.useCallback(e=>{const t=u.some(t=>t===e),n={transform:r,zIndex:t?2:void 0,position:t?"relative":void 0};return n},[u,r]);return 0===l.length?null:n.createElement(n.Fragment,null,l.map(e=>n.createElement("div",{key:e.index,"data-index":e.index,"data-known-size":e.size,style:a(e.index)},s(e))))},V=()=>{const e=W(t.useContext(i).totalHeight,0);return n.createElement("div",{style:{height:`${e}px`,position:"absolute",top:0}}," ")},S=({footer:e})=>{const r=C(t.useContext(i).footerHeight);return n.createElement("footer",{ref:r},e())},N={top:0,position:"sticky",height:"100%",overflow:"hidden",WebkitBackfaceVisibility:"hidden"},O=({style:e,footer:r,item:s,fixedItemHeight:o})=>{const{itemHeights:l,listHeight:u,viewportHeight:a,listOffset:h,list:c,topList:f}=t.useContext(i),d=W(h,0),p=t.useCallback(e=>{const t=[];for(var r=0,n=e.length;r<n;r++){let n=e.item(r);if(!n||"DIV"!==n.tagName)continue;const i=parseInt(n.dataset.index),s=n.offsetHeight;0===t.length||t[t.length-1].size!==s?t.push({start:i,end:i,size:s}):t[t.length-1].end++}t.length>0&&l(t)},[]),g=C(u,()=>{},e=>{o||p(e.children)}),m=C(a,e=>{""===e.style.position&&(e.style.position="-webkit-sticky")}),v=`translateY(${d}px)`,y=`translateY(${-d}px)`;return n.createElement(H,{style:e},n.createElement("div",{style:N,ref:m},n.createElement("div",{style:{transform:v}},n.createElement("div",{ref:g},n.createElement(T,{list:f,transform:y,render:s}),n.createElement(T,{list:c,render:s}),r&&n.createElement(S,{footer:r})))),n.createElement(V,null))},j=({contextValue:e,style:t,item:r,footer:s,itemHeight:o})=>n.createElement(i.Provider,{value:e},n.createElement(O,{style:t||{},item:r,footer:s,fixedItemHeight:void 0!==o}));e.GroupedVirtuoso=class extends t.PureComponent{constructor(e){super(e),this.itemRender=(e=>"group"==e.type?this.props.group(e.groupIndex):this.props.item(e.transposedIndex,e.groupIndex)),this.state=z(e)}static getDerivedStateFromProps(e,t){return t.endReached(e.endReached),t.isScrolling(e.scrollingStateChange),t.groupCounts(e.groupCounts),null}render(){return n.createElement(j,{contextValue:this.state,style:this.props.style,item:this.itemRender,footer:this.props.footer,itemHeight:this.props.itemHeight})}},e.Virtuoso=class extends t.PureComponent{constructor(e){super(e),this.itemRenderer=(e=>this.props.item(e.index)),this.state=z(e)}static getDerivedStateFromProps(e,t){return t.isScrolling(e.scrollingStateChange),t.endReached(e.endReached),t.topItemCount(e.topItems||0),t.totalCount(e.totalCount),null}render(){return n.createElement(j,{contextValue:this.state,style:this.props.style,item:this.itemRenderer,footer:this.props.footer,itemHeight:this.props.itemHeight})}},e.VirtuosoPresentation=j});
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("react"),require("resize-observer-polyfill")):"function"==typeof define&&define.amd?define(["exports","react","resize-observer-polyfill"],t):(e=e||self,t(e["react-virtuoso"]={},e.React,e.ResizeObserver))}(this,function(e,t,r){"use strict";var n="default"in t?t.default:t;r=r&&r.hasOwnProperty("default")?r.default:r;const s=t.createContext(void 0);function i(e){return function(...t){const r=function(...e){return 0===e.length?(e,t)=>t(e):1===e.length?e[0]:(t,r)=>{let n=e=>r(e);e.slice().reverse().forEach(e=>{const t=n;n=(r=>e(r,t))}),n(t)}}(...t);return function(e,t){const r=r=>e(e=>t(e,r));return{subscribe:r,pipe:i(r)}}(e,r)}}function o(e,t=!0){let r=[],n=e;const s=e=>(r.push(e),void 0!==n&&e(n),()=>{r=r.filter(t=>t!==e)});return{next:e=>{t&&e===n||(n=e,r.forEach(t=>t(e)))},subscribe:s,pipe:i(s),subscribers:r}}function l(...e){const t=Array(e.length).fill(!1),r=Array(e.length);let n=[];const s=e=>{t.every(e=>e)&&e.forEach(e=>e(r))};e.forEach((e,i)=>{e(e=>{t[i]=!0,r[i]=e,s(n)})});const o=e=>(n.push(e),s([e]),()=>{n=n.filter(t=>t!==e)});return{subscribe:o,pipe:i(o)}}function a(e){return(t,r)=>{r(e(t))}}function u(e){return(t,r)=>r(e)}function c(e){return(t,r)=>{e>0?e--:r(t)}}function h(e){return(t,r)=>{e(t)&&r(t)}}function f(...e){const t=Array(e.length).fill(!1),r=Array(e.length);return e.forEach((e,n)=>{e(e=>{r[n]=e,t[n]=!0})}),(e,n)=>{t.every(e=>e)&&n([e,...r])}}class d{constructor(){this.level=0}rebalance(){return this}adjust(){return this}remove(){return this}find(){}findWith(){}findMax(){return-Infinity}findMaxValue(){}insert(e,t){return new m({key:e,value:t,level:1})}walkWithin(){return[]}walk(){return[]}ranges(){return[]}rangesWithin(){return[]}empty(){return!0}isSingle(){return!0}isInvariant(){return!0}keys(){return[]}}const p=new d;Object.freeze(p);class g extends Error{constructor(e){super(`Unreachable case: ${e}`)}}class m{constructor({key:e,value:t,level:r,left:n=p,right:s=p}){this.key=e,this.value=t,this.level=r,this.left=n,this.right=s}remove(e){const{left:t,right:r}=this;if(e===this.key){if(t.empty())return r;if(r.empty())return t;{const[e,r]=t.last();return this.clone({key:e,value:r,left:t.deleteLast()}).adjust()}}return e<this.key?this.clone({left:t.remove(e)}).adjust():this.clone({right:r.remove(e)}).adjust()}empty(){return!1}find(e){return e===this.key?this.value:e<this.key?this.left.find(e):this.right.find(e)}findWith(e){const t=e(this.value);switch(t){case-1:return this.left.findWith(e);case 0:return[this.key,this.value];case 1:return this.right.findWith(e);default:throw new g(t)}}findMax(e){if(this.key===e)return e;if(this.key<e){const t=this.right.findMax(e);return-Infinity===t?this.key:t}return this.left.findMax(e)}findMaxValue(e){if(this.key===e)return this.value;if(this.key<e){const t=this.right.findMaxValue(e);return void 0===t?this.value:t}return this.left.findMaxValue(e)}insert(e,t){return e===this.key?this.clone({key:e,value:t}):e<this.key?this.clone({left:this.left.insert(e,t)}).rebalance():this.clone({right:this.right.insert(e,t)}).rebalance()}walkWithin(e,t){const{key:r,value:n}=this;let s=[];return r>e&&(s=s.concat(this.left.walkWithin(e,t))),r>=e&&r<=t&&s.push({key:r,value:n}),r<=t&&(s=s.concat(this.right.walkWithin(e,t))),s}walk(){return[...this.left.walk(),{key:this.key,value:this.value},...this.right.walk()]}last(){return this.right.empty()?[this.key,this.value]:this.right.last()}deleteLast(){return this.right.empty()?this.left:this.clone({right:this.right.deleteLast()}).adjust()}clone(e){return new m({key:void 0!==e.key?e.key:this.key,value:void 0!==e.value?e.value:this.value,level:void 0!==e.level?e.level:this.level,left:void 0!==e.left?e.left:this.left,right:void 0!==e.right?e.right:this.right})}isSingle(){return this.level>this.right.level}rebalance(){return this.skew().split()}adjust(){const{left:e,right:t,level:r}=this;if(t.level>=r-1&&e.level>=r-1)return this;if(r>t.level+1){if(e.isSingle())return this.clone({level:r-1}).skew();if(e.empty()||e.right.empty())throw new Error("Unexpected empty nodes");return e.right.clone({left:e.clone({right:e.right.left}),right:this.clone({left:e.right.right,level:r-1}),level:r})}if(this.isSingle())return this.clone({level:r-1}).split();if(t.empty()||t.left.empty())throw new Error("Unexpected empty nodes");{const e=t.left,n=e.isSingle()?t.level-1:t.level;return e.clone({left:this.clone({right:e.left,level:r-1}),right:t.clone({left:e.right,level:n}).split(),level:e.level+1})}}isInvariant(){const{left:e,right:t,level:r}=this;return r===e.level+1&&((r===t.level||r===t.level+1)&&(!(!t.empty()&&r<=t.right.level)&&(e.isInvariant()&&t.isInvariant())))}keys(){return[...this.left.keys(),this.key,...this.right.keys()]}ranges(){return this.toRanges(this.walk())}rangesWithin(e,t){return this.toRanges(this.walkWithin(e,t))}toRanges(e){if(0===e.length)return[];const t=e[0];let{key:r,value:n}=t;const s=[];for(let t=1;t<=e.length;t++){let i=e[t],o=i?i.key-1:Infinity;s.push({start:r,end:o,value:n}),i&&(r=i.key,n=i.value)}return s}split(){const{right:e,level:t}=this;return e.empty()||e.right.empty()||e.level!=t||e.right.level!=t?this:e.clone({left:this.clone({right:e.left}),level:t+1})}skew(){const{left:e}=this;return e.empty()||e.level!==this.level?this:e.clone({right:this.clone({left:e.right})})}}class v{constructor(e){this.root=e}static empty(){return new v(p)}find(e){return this.root.find(e)}findMax(e){return this.root.findMax(e)}findMaxValue(e){if(this.empty())throw new Error("Searching for max value in an empty tree");return this.root.findMaxValue(e)}findWith(e){return this.root.findWith(e)}insert(e,t){return new v(this.root.insert(e,t))}remove(e){return new v(this.root.remove(e))}empty(){return this.root.empty()}keys(){return this.root.keys()}walk(){return this.root.walk()}walkWithin(e,t){let r=this.root.findMax(e);return this.root.walkWithin(r,t)}ranges(){return this.root.ranges()}rangesWithin(e,t){let r=this.root.findMax(e);return this.root.rangesWithin(r,t)}isInvariant(){return this.root.isInvariant()}}class y{constructor(e){this.nanIndices=[],this.rangeTree=e;let t=v.empty(),r=0;const n=e.ranges();let s=!1;for(let{start:e,end:i,value:o}of n)isNaN(o)?(this.nanIndices.push(e),s||(t=t.insert(r,{startIndex:e,endIndex:Infinity,size:o})),s=!0):s||(t=t.insert(r,{startIndex:e,endIndex:i,size:o}),r+=(i-e+1)*o);this.offsetTree=t}static create(){return new y(v.empty())}empty(){return this.rangeTree.empty()}insert(e,t,r){let n=this.rangeTree;if(n.empty())return new y(n.insert(0,r));if(this.nanIndices.length&&this.nanIndices.indexOf(e)>-1){for(const e of this.nanIndices)n=n.insert(e,r);return new y(n)}const s=n.rangesWithin(e-1,t+1);if(s.some(n=>n.start===e&&(n.end===t||Infinity===n.end)&&n.value===r))return this;let i=!1,o=!1;for(const{start:e,end:l,value:a}of s)i?(t>=e||r===a)&&(n=n.remove(e)):(o=a!==r,i=!0),l>t&&t>=e&&(a===r||isNaN(a)||(n=n.insert(t+1,a)));return o&&(n=n.insert(e,r)),n===this.rangeTree?this:new y(n)}insertSpots(e,t){if(this.empty()){let r=this.rangeTree;for(const n of e)r=r.insert(n,t).insert(n+1,NaN);return new y(r)}throw new Error("attempting to overwrite non-empty tree")}offsetOf(e){if(this.offsetTree.empty())return 0;const t=this.offsetTree.findWith(t=>t.startIndex>e?-1:t.endIndex<e?1:0);if(t){const[r,{startIndex:n,size:s}]=t;return r+(e-n)*s}throw new Error(`Requested offset outside of the known ones, index: ${e}`)}itemAt(e){const t=this.rangeTree.findMaxValue(e);return{index:e,size:t,offset:NaN}}indexRange(e,t){if(0===t)return[];if(this.rangeTree.empty())return[{index:0,size:0,offset:NaN}];const r=this.rangeTree.rangesWithin(e,t),n=[];for(const s of r){const r=Math.max(e,s.start),i=void 0===s.end?Infinity:s.end,o=Math.min(t,i);for(let e=r;e<=o;e++)n.push({index:e,size:s.value,offset:NaN})}return n}range(e,t,r=0,n=Infinity){if(this.offsetTree.empty())return[{index:0,size:0,offset:0}];const s=this.offsetTree.rangesWithin(e,t),i=[];for(let{start:o,value:{startIndex:l,endIndex:a,size:u}}of s){let s=o,c=l;if(o<e&&(c+=Math.floor((e-o)/u),s+=(c-l)*u),c<r&&(s+=(r-c)*u,c=r),isNaN(u))return i.push({index:c,size:0,offset:s}),i;a=Math.min(a,n);for(let e=c;e<=a&&!(s>t);e++)i.push({index:e,size:u,offset:s}),s+=u}return i}total(e){const t=this.rangeTree.rangesWithin(0,e);let r=0;for(let{start:n,end:s,value:i}of t)s=Math.min(s,e),r+=(s-n+1)*(isNaN(i)?0:i);return r}getOffsets(e){let t=v.empty();return e.forEach(e=>{const r=this.offsetOf(e);t=t.insert(r,e)}),new x(t)}}class x{constructor(e){this.tree=e}findMaxValue(e){return this.tree.findMaxValue(e)}empty(){return this.tree.empty()}}class b{transpose(e){return e.map(e=>({groupIndex:0,index:e.index,offset:e.offset,size:e.size,transposedIndex:e.index,type:"item"}))}}class k{constructor(e){this.count=e.reduce((e,t)=>e+t+1,0);let t=v.empty(),r=0,n=0;for(let s of e)t=t.insert(n,[r,n]),r++,n+=s+1;this.tree=t}totalCount(){return this.count}transpose(e){return e.map(e=>{const t=this.tree.find(e.index);if(t)return{groupIndex:t[0],index:e.index,offset:e.offset,size:e.size,type:"group"};const[r]=this.tree.findMaxValue(e.index);return{groupIndex:r,index:e.index,offset:e.offset,size:e.size,transposedIndex:e.index-r-1,type:"item"}})}groupIndices(){return this.tree.keys()}}function I(e){let t,r=e=>{t&&t(e)},n=!1;return s=>{t=s,n||(e.subscribe(r),n=!0)}}function w(e){return e.next}const C=e=>e.length>0?e[0].offset:0,E=([e,t])=>e.total(t-1),M=({overscan:e=0,totalCount:t=0,itemHeight:r})=>{const n=o(0),s=o(0),i=o(0),d=o(0),p=o(),g=o(t),m=o(),v=o(),x=o(!1);let M=y.create();const T=o([]),z=o(void 0,!1);r&&(M=M.insert(0,0,r));const N=o(M);r||p.pipe(f(N.subscribe,T.subscribe)).subscribe(([e,t,r])=>{let n=t;for(let{start:t,end:s,size:i}of e)n=n.empty()&&t==s&&r.indexOf(t)>-1?n.insertSpots(r,i):n.insert(t,s,i);n!==t&&N.next(n)});let S=new b;m.subscribe(e=>{S=new k(e),g.next(S.totalCount()),T.next(S.groupIndices())});const W=l(N.subscribe,g.subscribe).pipe(a(E)),R=l(W.subscribe,d.subscribe).pipe(a(([e,t])=>e+t)),H=l(N.subscribe,T.subscribe).pipe(a(([e,t])=>e.getOffsets(t))),V=o([]);l(N.subscribe,v.subscribe,g.subscribe).pipe(h(e=>e[1]>0),a(([e,t,r])=>{const n=Math.max(0,Math.min(t-1,r));return S.transpose(e.indexRange(0,n))})).subscribe(V.next),l(N.subscribe,H.subscribe,i.subscribe).pipe(h(e=>!e[1].empty()&&!e[0].empty()),f(V.subscribe),a(([[e,t,r],n])=>{const s=t.findMaxValue(r);if(1===n.length&&n[0].index===s)return n;const i=e.itemAt(s);return S.transpose([i])})).subscribe(V.next);const O=V.pipe(a(e=>e.reduce((e,t)=>e+t.size,0))),j=V.pipe(a(e=>e.length&&e[e.length-1].index+1)),A=l(n.subscribe,i.subscribe,O.subscribe,s.subscribe,d.subscribe,j.subscribe,g.subscribe,N.subscribe).pipe(function(e,t){let r=t;return(t,n)=>{n(r=e(r,t))}}((e=>(t,[r,n,s,i,o,l,a,u])=>{const c=t.length;if(0===a)return 0===c?t:[];const h=C(t),f=h-n+i-o-s,d=Math.max(a-1,0),p=c>0&&(t[0].index<l||t[c-1].index>d);if(f<r||p){const t=Math.max(n+s,s),i=n+r+2*e-1,o=S.transpose(u.range(t,i,l,d));return o}if(h>n+s){const t=Math.max(n+s-2*e,s),i=n+r-1;return S.transpose(u.range(t,i,l,d))}return t})(e),[])),L=o(0);let P=0;A.pipe(a(e=>e.length?e[e.length-1].index:0)).pipe(f(g.subscribe)).subscribe(([e,t])=>{e==t-1&&P!==e&&(P=e,L.next(e))});const $=l(A.subscribe,i.subscribe,O.subscribe).pipe(a(([e,t,r])=>C(e)-t-r));i.pipe(c(1),u(!0)).subscribe(x.next),i.pipe(c(1),u(!1),function(e){let t,r;return(n,s)=>{t=n,r&&clearTimeout(r),r=setTimeout(()=>{s(t)},e)}}(200)).subscribe(x.next);const q=z.pipe(f(N.subscribe,O.subscribe,T.subscribe,n.subscribe,g.subscribe),a(([e,t,r,n,s,i])=>{"number"==typeof e&&(e={index:e,align:"start"});let{index:o,align:l="start"}=e;o=Math.max(0,o,Math.min(i-1,o));let a=t.offsetOf(o);return"end"==l?a=a-s+t.itemAt(o).size:"center"===l?a=Math.round(a-s/2+t.itemAt(o).size/2):-1===n.indexOf(o)&&(a-=r),a})),D=T.pipe();return{groupCounts:w(m),itemHeights:w(p),footerHeight:w(d),listHeight:w(s),viewportHeight:w(n),scrollTop:w(i),topItemCount:w(v),totalCount:w(g),scrollToIndex:w(z),list:I(A),topList:I(V),listOffset:I($),totalHeight:I(R),endReached:I(L),isScrolling:I(x),stickyItems:I(T),groupIndices:I(D),scrollTo:I(q)}},T=(e,n,s)=>{const i=t.useRef(null),o=t.useRef(0),l=new r(t=>{const r=t[0].contentRect.height;o.current!==r&&(o.current=r,s&&s(t[0].target),e(r))});return e=>{e?(l.observe(e),n&&n(e),i.current=e):(l.unobserve(i.current),i.current=null)}};function z(e,r){const[n,s]=t.useState(r);return t.useLayoutEffect(()=>{e(s)},[]),n}const N={height:"40rem",overflowY:"auto",WebkitOverflowScrolling:"touch",position:"relative",outline:"none"},S=({className:e,style:r,reportScrollTop:s,scrollTo:i,children:o})=>{const l=t.useRef(null),a=t.useCallback(e=>{s(e.target.scrollTop)},[]),u=t.useCallback(e=>{e?(e.addEventListener("scroll",a,{passive:!0}),l.current=e):l.current.removeEventListener("scroll",a)},[]);return i(e=>{const t={top:e};l.current.scrollTo(t)}),n.createElement("div",{ref:u,style:r,tabIndex:0,className:e},o)},W=({children:e,style:r,className:i,ScrollContainer:o=S})=>{const{scrollTop:l,scrollTo:a}=t.useContext(s);return n.createElement(o,{style:{...N,...r},reportScrollTop:l,scrollTo:a,className:i},e)},R=({list:e,transform:r="",render:i})=>{const{stickyItems:o}=t.useContext(s),l=z(e,[]),a=z(o,[]),u=t.useCallback(e=>{const t=a.some(t=>t===e),n={transform:r,zIndex:t?2:void 0,position:t?"relative":void 0};return n},[a,r]);return 0===l.length?null:n.createElement(n.Fragment,null,l.map(e=>n.createElement("div",{key:e.index,"data-index":e.index,"data-known-size":e.size,style:u(e.index)},i(e))))},H=()=>{const e=z(t.useContext(s).totalHeight,0);return n.createElement("div",{style:{height:`${e}px`,position:"absolute",top:0}}," ")},V=({footer:e})=>{const r=T(t.useContext(s).footerHeight);return n.createElement("footer",{ref:r},e())},O={top:0,position:"sticky",height:"100%",overflow:"hidden",WebkitBackfaceVisibility:"hidden"},j=({style:e,footer:r,item:i,fixedItemHeight:o,ScrollContainer:l,className:a})=>{const{itemHeights:u,listHeight:c,viewportHeight:h,listOffset:f,list:d,topList:p}=t.useContext(s),g=z(f,0),m=t.useCallback(e=>{const t=[];for(var r=0,n=e.length;r<n;r++){let n=e.item(r);if(!n||"DIV"!==n.tagName)continue;const s=parseInt(n.dataset.index),i=n.offsetHeight;0===t.length||t[t.length-1].size!==i?t.push({start:s,end:s,size:i}):t[t.length-1].end++}t.length>0&&u(t)},[]),v=T(c,()=>{},e=>{o||m(e.children)}),y=T(h,e=>{""===e.style.position&&(e.style.position="-webkit-sticky")}),x=`translateY(${g}px)`,b=`translateY(${-g}px)`;return n.createElement(W,{style:e,ScrollContainer:l,className:a},n.createElement("div",{style:O,ref:y},n.createElement("div",{style:{transform:x}},n.createElement("div",{ref:v},n.createElement(R,{list:p,transform:b,render:i}),n.createElement(R,{list:d,render:i}),r&&n.createElement(V,{footer:r})))),n.createElement(H,null))},A=({contextValue:e,style:t,className:r,item:i,footer:o,itemHeight:l,ScrollContainer:a})=>n.createElement(s.Provider,{value:e},n.createElement(j,{style:t||{},className:r,item:i,footer:o,fixedItemHeight:void 0!==l,ScrollContainer:a}));e.GroupedVirtuoso=class extends t.PureComponent{constructor(e){super(e),this.itemRender=(e=>"group"==e.type?this.props.group(e.groupIndex):this.props.item(e.transposedIndex,e.groupIndex)),this.state=M(e)}static getDerivedStateFromProps(e,t){return t.endReached(e.endReached),t.isScrolling(e.scrollingStateChange),t.groupCounts(e.groupCounts),t.groupIndices(e.groupIndices),null}scrollToIndex(e){this.state.scrollToIndex(e)}render(){return n.createElement(A,{contextValue:this.state,style:this.props.style,className:this.props.className,item:this.itemRender,footer:this.props.footer,itemHeight:this.props.itemHeight,ScrollContainer:this.props.ScrollContainer})}},e.Virtuoso=class extends t.PureComponent{constructor(e){super(e),this.itemRender=(e=>this.props.item(e.index)),this.state=M(e)}static getDerivedStateFromProps(e,t){return t.isScrolling(e.scrollingStateChange),t.endReached(e.endReached),t.topItemCount(e.topItems||0),t.totalCount(e.totalCount),null}scrollToIndex(e){this.state.scrollToIndex(e)}render(){return n.createElement(A,{contextValue:this.state,style:this.props.style,className:this.props.className,item:this.itemRender,footer:this.props.footer,itemHeight:this.props.itemHeight,ScrollContainer:this.props.ScrollContainer})}},e.VirtuosoPresentation=A});
//# sourceMappingURL=react-virtuoso.umd.production.js.map

@@ -5,6 +5,6 @@ import { TObservable } from './tinyrx';

export declare function makeInput<T>(subject: {
next: (val: T) => void;
}): (val: T) => void;
next: (value: T) => void;
}): (value: T) => void;
export declare type TOutput<T> = (callback: TCallback<T>) => void;
export declare type TInput<T> = TCallback<T>;
export {};

@@ -21,3 +21,3 @@ export declare type TSubscriber<T> = (val: T) => void;

};
export declare function subject<T>(initial?: T): {
export declare function subject<T>(initial?: T, distinct?: boolean): {
next: (newVal: T) => void;

@@ -46,1 +46,4 @@ subscribe: (subscriber: TSubscriber<T>) => () => void;

export declare function withLatestFrom<T, R1, R2>(s1: TSubscribe<R1>, s2: TSubscribe<R2>): (val: T, done: TSubscriber<[T, R1, R2]>) => void;
export declare function withLatestFrom<T, R1, R2, R3>(s1: TSubscribe<R1>, s2: TSubscribe<R2>, s3: TSubscribe<R3>): (val: T, done: TSubscriber<[T, R1, R2, R3]>) => void;
export declare function withLatestFrom<T, R1, R2, R3, R4>(s1: TSubscribe<R1>, s2: TSubscribe<R2>, s3: TSubscribe<R3>, s4: TSubscribe<R4>): (val: T, done: TSubscriber<[T, R1, R2, R3, R4]>) => void;
export declare function withLatestFrom<T, R1, R2, R3, R4, R5>(s1: TSubscribe<R1>, s2: TSubscribe<R2>, s3: TSubscribe<R3>, s4: TSubscribe<R4>, s5: TSubscribe<R5>): (val: T, done: TSubscriber<[T, R1, R2, R3, R4, R5]>) => void;
import { CSSProperties, PureComponent, ReactElement, FC } from 'react';
import { VirtuosoStore } from './VirtuosoStore';
import { VirtuosoStore, TScrollLocation } from './VirtuosoStore';
import { TScrollContainer } from './VirtuosoView';
import { TRender } from './VirtuosoList';

@@ -15,2 +16,4 @@ export declare type VirtuosoState = ReturnType<typeof VirtuosoStore>;

style?: CSSProperties;
className?: string;
ScrollContainer?: TScrollContainer;
}

@@ -22,4 +25,7 @@ interface TVirtuosoPresentationProps {

style?: CSSProperties;
className?: string;
itemHeight?: number;
ScrollContainer?: TScrollContainer;
}
export { TScrollContainer };
export declare const VirtuosoPresentation: FC<TVirtuosoPresentationProps>;

@@ -29,5 +35,5 @@ export declare class Virtuoso extends PureComponent<VirtuosoProps, VirtuosoState> {

static getDerivedStateFromProps(props: VirtuosoProps, state: VirtuosoState): null;
private itemRenderer;
private itemRender;
scrollToIndex(location: TScrollLocation): void;
render(): JSX.Element;
}
export {};
import { FC, CSSProperties } from 'react';
export declare type TScrollContainer = FC<{
style: CSSProperties;
className?: string;
reportScrollTop: (scrollTop: number) => void;
scrollTo: (callback: (scrollTop: number) => void) => void;
}>;
export declare const VirtuosoScroller: FC<{
className?: string;
style: CSSProperties;
ScrollContainer?: TScrollContainer;
}>;

@@ -13,11 +13,17 @@ import { ListItem } from './GroupIndexTransposer';

}
interface TScrollLocationWithAlign {
index: number;
align: 'start' | 'center' | 'end';
}
export declare type TScrollLocation = number | TScrollLocationWithAlign;
declare const VirtuosoStore: ({ overscan, totalCount, itemHeight }: TVirtuosoConstructorParams) => {
groupCounts: (val: number[]) => void;
itemHeights: (val: ItemHeight[]) => void;
footerHeight: (val: number) => void;
listHeight: (val: number) => void;
viewportHeight: (val: number) => void;
scrollTop: (val: number) => void;
topItemCount: (val: number) => void;
totalCount: (val: number) => void;
groupCounts: (value: number[]) => void;
itemHeights: (value: ItemHeight[]) => void;
footerHeight: (value: number) => void;
listHeight: (value: number) => void;
viewportHeight: (value: number) => void;
scrollTop: (value: number) => void;
topItemCount: (value: number) => void;
totalCount: (value: number) => void;
scrollToIndex: (value: TScrollLocation) => void;
list: (callback: ((val: ListItem[]) => void) | undefined) => void;

@@ -30,3 +36,5 @@ topList: (callback: ((val: ListItem[]) => void) | undefined) => void;

stickyItems: (callback: ((val: number[]) => void) | undefined) => void;
groupIndices: (callback: ((val: number[]) => void) | undefined) => void;
scrollTo: (callback: ((val: number) => void) | undefined) => void;
};
export { VirtuosoStore };
import React, { ReactElement, CSSProperties } from 'react';
import { TScrollContainer } from './VirtuosoScroller';
import { TRender } from './VirtuosoList';
export declare const VirtuosoView: React.FC<{
style: CSSProperties;
footer: (() => ReactElement) | undefined;
className?: string;
footer?: () => ReactElement;
ScrollContainer?: TScrollContainer;
item: TRender;
fixedItemHeight: boolean;
}>;
export { TScrollContainer };
{
"name": "react-virtuoso",
"version": "0.4.5",
"version": "0.5.0",
"homepage": "https://virtuoso.dev",

@@ -14,8 +14,5 @@ "license": "MIT",

"scripts": {
"buildstorybook": "build-storybook -o .out -s ./.storybook/static",
"deploy-storybook": "rm -fr .out && npm run buildstorybook && echo 'virtuoso.dev' > '.out/CNAME' && storybook-to-ghpages --existing-output-dir=.out",
"start": "tsdx watch",
"build": "tsdx build",
"test": "tsdx test --env=jsdom",
"storybook": "start-storybook -p 6006 -s ./.storybook/static"
"test": "tsdx test --env=jsdom"
},

@@ -32,7 +29,2 @@ "peerDependencies": {

"@babel/core": "^7.4.4",
"@storybook/addon-google-analytics": "^5.0.11",
"@storybook/addon-storysource": "^5.0.11",
"@storybook/addons": "^5.0.11",
"@storybook/react": "^5.0.11",
"@storybook/storybook-deployer": "^2.8.1",
"@types/babel__core": "^7.1.1",

@@ -42,3 +34,2 @@ "@types/bootstrap": "^4.3.0",

"@types/eslint-plugin-prettier": "^2.2.0",
"@types/faker": "^4.1.5",
"@types/jest": "^24.0.12",

@@ -49,5 +40,2 @@ "@types/lodash": "^4.14.123",

"@types/react-dom": "^16.8.4",
"@types/storybook-readme": "^5.0.2",
"@types/storybook__react": "^4.0.1",
"@types/styled-components": "^4.1.14",
"@typescript-eslint/eslint-plugin": "^1.7.0",

@@ -68,6 +56,3 @@ "awesome-typescript-loader": "^5.2.1",

"react": "^16.8.6",
"react-docgen-typescript-loader": "^3.1.0",
"react-dom": "^16.8.6",
"storybook-readme": "^5.0.3",
"styled-components": "^4.2.0",
"tsdx": "^0.5.6",

@@ -74,0 +59,0 @@ "typescript": "^3.4.5"

@@ -7,3 +7,3 @@ <img src="https://user-images.githubusercontent.com/13347/57673110-85aab180-7623-11e9-97b4-27bbdcf8cf40.png" width="292">

- Handles gracefully variable sized items; no manual measurements or hard-coding of item heights;
- Handles variable sized items; no manual measurements or hard-coding of item heights;
- Supports grouping with sticky group headers;

@@ -46,17 +46,7 @@ - Automatically handles content resizing;

### Add a Footer
### Footer
The component accepts an optional `footer` [render property](https://reactjs.org/docs/render-props.html), the contents of which are rendered at the bottom of the list. The footer can be used to host a "load more" button or an indicator that the user has reached the end of the list.
The component accepts an optional `footer` [render property](https://reactjs.org/docs/render-props.html), rendered at the bottom of the list.
The footer can be used to host a "load more" button or an indicator that the user has reached the end of the list.
```jsx
return (
<Virtuoso
style={{ height: '300px', width: '500px' }}
totalCount={100}
item={index => <div>Item {index}</div>}
footer={() => <div>-- end reached --</div>}
/>
)
```
Check the [footer](//virtuoso.dev/footer), [load more](//virtuoso.dev/press-to-load-more) and [endless scrolling](//virtuoso.dev/endless-scrolling) examples for practical applications of the footer.

@@ -68,13 +58,2 @@

```jsx
return (
<Virtuoso
style={{ height: '500px', width: '500px' }}
topItems={2}
totalCount={100000}
item={index => <div>Item {index}</div>}
/>
)
```
Check the [fixed top items](//virtuoso.dev/top-items) example for a live version of the above.

@@ -85,36 +64,4 @@

The package exports two components - `Virtuoso` and `GroupedVirtuoso`.
The Grouped component supports rendering sticky group headers at the beginning of each group.
The grouped component is similar to the flat one, with the following differences:
- Instead of `totalCount`, the component accepts `groupedCounts: number[]`, which specifies the amount of items in each group.
For example, passing `[20, 30]` will cause the component to render two groups with 20 and 30 items respectively;
- In addition the `item` render prop, the component requires an additional `group` render prop,
which renders the group header. The property receives the zero-based group index as a parameter;
- The `item` render prop gets called with an additional second parameter, `groupIndex: number`.
```jsx
// generate 100 groups with 10 items each
const groupCounts = []
for (let index = 0; index < 100; index++) {
groupCounts.push(10)
}
return (
<GroupedVirtuoso
style={{ height: '500px', width: '500px' }}
groupCounts={groupCounts}
group={index => (
<div>
Group {index * 10} - {index * 10 + 10}
</div>
)}
item={(index, groupIndex) => (
<div>
Item {index} from group {groupIndex}
</div>
)}
/>
)
```
Check the

@@ -126,110 +73,6 @@ [grouped numbers](//virtuoso.dev/grouped-numbers),

## Tweaking Performance
## Documentation and Demos
Several factors affect the component performance, the most important being the _size of the visible area_. Redrawing large items takes more time and reduces the frame rate. To see if this affects your case, change the component `style` property to something like `{{width: '200px'}}` and see if the frame rate gets better.
For in-depth documentation and live examples of the supported features and live demos, check the [website](https://virtuoso.dev).
Next, if the content in the item prop is complex / large, use [React.memo](https://reactjs.org/docs/react-api.html#reactmemo).
You can experiment with the `overscan` property which specifies how much more to render in addition to the viewport visible height. For example, if the component is `100px` tall, setting the `overscan` to `150` will cause the list to render **at least** `250px` tall content. In a nutshell, increasing the `overscan` causes less frequent re-renders, but makes each re-render more expensive (because more items will get replaced).
Loading images and displaying complex components while scrolling can cause hiccups and frame skips. To fix that, you can hook to the `scrollingStateChange` callback and replace the complex content in the item render prop with a simplified one. Check the [scroll handling example](//virtuoso.dev/?path=/story/features-overview--scroll-handling) for a possible implementation.
Finally, as a last resort, you can speed up things by hard-coding the size of the items using the `itemHeight` property. This will cause the component to stop measuring and observing the item sizes. Be careful with that option; ensure that the items won't change size on different resolutions.
## Properties of the `Virtuoso` Component
### `total: number`
Mandatory. Specifies the total amount of items to be displayed by the list.
### `item: (index: number) => ReactElement`
Mandatory. Specifies how each item gets rendered. The callback receives the zero-based index of the item.
### `style?: CSSProperties`
Optional; most often, you will need to tweak the size of the component by setting `width` and `height`.
The style is passed to the outermost `div` element of the component.
### `footer?: () => ReactElement`
Optional. Defines content to be rendered at the bottom of the list.
### `overscan?: number`
Optional. Causes the component to render extra content in addition to the necessary one to fill in the visible viewport.
Check the Tweaking Performance section.
### `endReached?: (index: number) => void`
Gets called when the user scrolls to the end of the list.
Receives the last item index as an argument. Can be used to implement [endless scrolling](//virtuoso.dev/endless-scrolling).
### `scrollingStateChange?: (isScrolling: boolean) => void`
Gets called when the user starts / stops scrolling. Can be used to hide complex item contents during scrolling.
### `itemHeight?: number`
Can be used to improve performance if the rendered items are of known size. Setting it causes the component to skip item measurements. See the Tweaking Performance section for more details.
## Properties of the `GroupedVirtuoso` Component
### `groupCounts: number[]`
Mandatory. Specifies the amount of items in each group (and, actually, how many groups are there). For example, passing `[20, 30]` will display 2 groups with 20 and 30 items each.
### `item: (index: number, groupIndex: number) => ReactElement`
Mandatory. Specifies how each item gets rendered. The callback receives the zero-based index of the item and the index of the group of the item.
### `group: (groupIndex: number) => ReactElement`
Mandatory. Specifies how each each group header gets rendered. The callback receives the zero-based index of the group.
### `style?: CSSProperties`
Works just like the `style` property of the flat component.
### `footer?: () => ReactElement`
Works just like the `footer` property of the flat component.
### `overscan?: number`
Works just like the `overscan` property of the flat component.
### `endReached?: (index: number) => void`
Works just like the `endReached` callback of the flat component.
### `scrollingStateChange?: (isScrolling: boolean) => void`
Works just like the `scrollingStateChange` callback of the flat component.
## Gotchas
CSS margins in the content are the Kryptonite of Virtuoso's content measuring mechanism - the [`contentRect` measurement](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver) does not include them.
If this affects you, the total scroll height will be miscalculated, and the user won't be able to scroll all the way down to the list.
To avoid that, if you are putting paragraphs and headings inside the `item`, make sure that the top / bottom elements' margins do not protrude outside of the item container.
```jsx
<Virtuoso
totalCount={100}
item={index => (
<div>
<p style={{ margin: 0 }}>Item {index}</p>
</div>
)}
/>
```
## Browser Support
Virtuoso uses `position: sticky` to keep the virtual viewport at top of the scroller.
[This does not work in IE 11](https://caniuse.com/#feat=css-sticky).
Please open an issue (or even, PR) if you need this - it should be possible to implement a fallback mechanism using `position: absolute`.
## Author

@@ -236,0 +79,0 @@

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc