virtua 0.43.1 → 0.43.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/lib/core/index.js +1 -1
- package/lib/core/index.js.map +1 -1
- package/lib/core/index.mjs +1 -1
- package/lib/core/index.mjs.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +1 -1
- package/lib/index.mjs.map +1 -1
- package/lib/solid/index.js +1 -1
- package/lib/solid/index.js.map +1 -1
- package/lib/solid/index.jsx +48 -32
- package/lib/solid/index.jsx.map +1 -1
- package/lib/solid/index.mjs +1 -1
- package/lib/solid/index.mjs.map +1 -1
- package/lib/vue/index.js +1 -1
- package/lib/vue/index.js.map +1 -1
- package/lib/vue/index.mjs +1 -1
- package/lib/vue/index.mjs.map +1 -1
- package/package.json +15 -14
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@ If you want to check the difference with the alternatives right away, [see compa
|
|
|
13
13
|
This project is a challenge to rethink virtualization. The goals are...
|
|
14
14
|
|
|
15
15
|
- **Zero-config virtualization:** This library is designed to give the best performance without configuration. It also handles common hard things in the real world (dynamic size measurement, scroll position adjustment while reverse scrolling and imperative scrolling, iOS support, etc).
|
|
16
|
-
- **Fast:** Natural virtual scrolling needs optimization in many aspects (eliminate frame drops by reducing CPU usage and GC, reduce [synchronous layout recalculation](https://gist.github.com/paulirish/5d52fb081b3570c81e3a), reduce visual jumps on repaint, optimize with CSS, optimize for frameworks, etc). We are trying to combine the best of them.
|
|
16
|
+
- **Fast:** Natural virtual scrolling needs optimization in many aspects (eliminate frame drops by reducing CPU usage and GC, reduce [synchronous layout recalculation](https://gist.github.com/paulirish/5d52fb081b3570c81e3a), reduce visual jumps on repaint, optimize with CSS, optimize for JIT, optimize for frameworks, etc). We are trying to combine the best of them.
|
|
17
17
|
- **Small:** Its bundle size should be small as much as possible to be friendly with modern web development. Currently each components are ~3kB gzipped and tree-shakeable. The total size for React is [~5kB gzipped](https://bundlephobia.com/package/virtua).
|
|
18
18
|
- **Flexible:** Aiming to support many usecases - fixed size, dynamic size, horizontal scrolling, reverse scrolling, RTL, mobile, infinite scrolling, scroll restoration, DnD, keyboard navigation, sticky, placeholder and more. See [live demo](#demo).
|
|
19
19
|
- **Framework agnostic:** [React](https://react.dev/), [Vue](https://vuejs.org/), [Solid](https://www.solidjs.com/) and [Svelte](https://svelte.dev/) are supported. We could support other frameworks in the future.
|
package/lib/core/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=null,{min:t,max:o,abs:r,floor:s}=Math,n=(e,r,s)=>t(s,o(r,e)),c=e=>[...e].sort(((e,t)=>e-t)),i="function"==typeof queueMicrotask?queueMicrotask:e=>{Promise.resolve().then(e)},l=e=>{let t;return()=>(e&&(t=e(),e=void 0),t)},
|
|
1
|
+
const e=null,{min:t,max:o,abs:r,floor:s}=Math,n=(e,r,s)=>t(s,o(r,e)),c=e=>[...e].sort(((e,t)=>e-t)),i="function"==typeof queueMicrotask?queueMicrotask:e=>{Promise.resolve().then(e)},l=()=>{let e,t;return[new Promise(((o,r)=>{e=o,t=r})),e,t]},f=e=>{let t;return()=>(e&&(t=e(),e=void 0),t)},a=-1,u=(e,t,o)=>{const r=o?"unshift":"push";for(let o=0;o<t;o++)e[r](a);return e},p=(e,t)=>{const o=e.t[t];return o===a?e.o:o},d=(e,o,r)=>{const s=e.t[o]===a;return e.t[o]=r,e.i=t(o,e.i),s},$=(e,t)=>{if(!e.l)return 0;if(e.i>=t)return e.u[t];e.i<0&&(e.u[0]=0,e.i=0);let o=e.i,r=e.u[o];for(;o<t;)r+=p(e,o),e.u[++o]=r;return e.i=t,r},h=(e,t,o=0,r=e.l-1)=>{for(;o<=r;){const n=s((o+r)/2),c=$(e,n);if(c<=t){if(c+p(e,n)>t)return n;o=n+1}else r=n-1}return n(o,0,e.l-1)},m=(e,o,r)=>{const s=o-e.l;return e.i=r?-1:t(o-1,e.i),e.l=o,s>0?(u(e.u,s),u(e.t,s,r),e.o*s):(e.u.splice(s),(r?e.t.splice(0,-s):e.t.splice(s)).reduce(((t,o)=>t-(o===a?e.o:o)),0))},w="undefined"!=typeof window,x=()=>document.documentElement,g=e=>e.ownerDocument,b=e=>e.defaultView,v=/*#__PURE__*/f((()=>!!w&&"rtl"===getComputedStyle(x()).direction)),S=/*#__PURE__*/f((()=>/iP(hone|od|ad)/.test(navigator.userAgent))),I=/*#__PURE__*/f((()=>"scrollBehavior"in x().style)),y=e=>!!e.$getViewportSize(),k=setTimeout,_=(e,t)=>t&&v()?-e:e,z=(t,o,r,s,n,c)=>{const i=Date.now;let l=0,f=!1,a=!1,u=!1,p=!1;const d=(()=>{let o;const r=()=>{o!=e&&clearTimeout(o)},s=()=>{r(),o=k((()=>{o=e,(()=>{if(f||a)return f=!1,void d();u=!1,t.$update(2)})()}),150)};return s.p=r,s})(),$=()=>{l=i(),u&&(p=!0),c&&t.$update(6,c()),t.$update(1,s()),d()},h=e=>{if(f||!t.$isScrolling()||e.ctrlKey)return;const o=i()-l;150>o&&50<o&&(r?e.deltaX:e.deltaY)&&(f=!0)},m=()=>{a=!0,u=p=!1},w=()=>{a=!1,S()&&(u=!0)};return o.addEventListener("scroll",$),o.addEventListener("wheel",h,{passive:!0}),o.addEventListener("touchstart",m,{passive:!0}),o.addEventListener("touchend",w,{passive:!0}),{$:()=>{o.removeEventListener("scroll",$),o.removeEventListener("wheel",h),o.removeEventListener("touchstart",m),o.removeEventListener("touchend",w),d.p()},h:()=>{const[e,o]=t.m();e&&(n(_(e,r),o,p),p=!1,o&&t.$getViewportSize()>t.$getTotalSize()&&t.$update(1,s()))}}},T=(e,t)=>{let o,r,s;const[c,i,f]=l(),a=t?"scrollLeft":"scrollTop",u=t?"overflowX":"overflowY",p=async(r,n)=>{await c,s&&s();const i=()=>{const[t,o,r]=l();return s=r,y(e)&&k(r,150),[t,e.$subscribe(2,(()=>{o()}))]};if(n&&I()){for(;e.$update(8,r()),e.v();){const[e,t]=i();try{await e}catch(e){return}finally{t()}}o.scrollTo({[t?"left":"top"]:_(r(),t),behavior:"smooth"})}else for(;;){const[s,n]=i();try{o[a]=_(r(),t),e.$update(7),await s}catch(e){return}finally{n()}}};return{$observe(n){o=n,r=z(e,n,t,(()=>_(n[a],t)),((t,o,r)=>{if(r){const e=n.style,t=e[u];e[u]="hidden",k((()=>{e[u]=t}))}o?(n[a]=e.$getScrollOffset()+t,s&&s()):n[a]+=t})),i()},$dispose(){r&&r.$(),f()},$scrollTo(e){p((()=>e))},$scrollBy(t){t+=e.$getScrollOffset(),p((()=>t))},$scrollToIndex(t,{align:o,smooth:r,offset:s=0}={}){if(t=n(t,0,e.$getItemsLength()-1),"nearest"===o){const r=e.$getItemOffset(t),s=e.$getScrollOffset();if(r<s)o="start";else{if(!(r+e.$getItemSize(t)>s+e.$getViewportSize()))return;o="end"}}p((()=>s+e.$getStartSpacerSize()+e.$getItemOffset(t)+("end"===o?e.$getItemSize(t)-e.$getViewportSize():"center"===o?(e.$getItemSize(t)-e.$getViewportSize())/2:0)),r)},$fixScrollJump:()=>{r&&r.h()}}},R=e=>{let t;return{S(o){(t||(t=new(b(g(o)).ResizeObserver)(e))).observe(o)},I(e){t.unobserve(e)},$(){t&&t.disconnect()}}};exports.ACTION_ITEMS_LENGTH_CHANGE=5,exports.ACTION_START_OFFSET_CHANGE=6,exports.UPDATE_SCROLL_END_EVENT=8,exports.UPDATE_SCROLL_EVENT=4,exports.UPDATE_VIRTUAL_STATE=1,exports.createGridResizer=(e,t)=>{let r;const s="height",n="width",c=new WeakMap,i=new Set,l=new Set,f=new Map,a=(e,t)=>`${e}-${t}`,u=R((u=>{const p=new Set,d=new Set;for(const{target:o,contentRect:i}of u)if(o.offsetParent)if(o===r)e.$update(4,i[s]),t.$update(4,i[n]);else{const e=c.get(o);if(e){const[t,o]=e,r=a(t,o),c=f.get(r),l=[i[s],i[n]];let u,$;c?(c[0]!==l[0]&&(u=!0),c[1]!==l[1]&&($=!0)):u=$=!0,u&&p.add(t),$&&d.add(o),(u||$)&&f.set(r,l)}}if(p.size){const t=[];p.forEach((e=>{let r=0;l.forEach((t=>{const s=f.get(a(e,t));s&&(r=o(r,s[0]))})),r&&t.push([e,r])})),e.$update(3,t)}if(d.size){const e=[];d.forEach((t=>{let r=0;i.forEach((e=>{const s=f.get(a(e,t));s&&(r=o(r,s[1]))})),r&&e.push([t,r])})),t.$update(3,e)}}));return{$observeRoot(e){u.S(r=e)},$observeItem:(e,t,o)=>(c.set(e,[t,o]),i.add(t),l.add(o),u.S(e),()=>{c.delete(e),u.I(e)}),$resizeCols(o){for(const[t]of o)for(let o=0;o<e.$getItemsLength();o++)f.delete(a(o,t));t.$update(3,o)},$resizeRows(o){for(const[e]of o)for(let o=0;o<t.$getItemsLength();o++)f.delete(a(e,o));e.$update(3,o)},$dispose:u.$}},exports.createGridScroller=(e,t)=>{const o=T(e,!1),r=T(t,!0);return{$observe(e){o.$observe(e),r.$observe(e)},$dispose(){o.$dispose(),r.$dispose()},$scrollTo(e,t){o.$scrollTo(t),r.$scrollTo(e)},$scrollBy(e,t){o.$scrollBy(t),r.$scrollBy(e)},$scrollToIndex(e,t){o.$scrollToIndex(t),r.$scrollToIndex(e)},$fixScrollJump(){o.$fixScrollJump(),r.$fixScrollJump()}}},exports.createResizer=(t,o)=>{let r;const s=o?"width":"height",n=new WeakMap,c=R((o=>{const c=[];for(const{target:i,contentRect:l}of o)if(i.offsetParent)if(i===r)t.$update(4,l[s]);else{const t=n.get(i);t!=e&&c.push([t,l[s]])}c.length&&t.$update(3,c)}));return{$observeRoot(e){c.S(r=e)},$observeItem:(e,t)=>(n.set(e,t),c.S(e),()=>{n.delete(e),c.I(e)}),$dispose:c.$}},exports.createScroller=T,exports.createVirtualStore=(s,n=40,i=4,l=0,f,w=!1)=>{let x=!!l,g=1,b=0,v=0,I=0,y=0,k=0,_=0,z=0,T=0,R=x?[0,o(l-1,0)]:e,M=[0,0],J=0;const W=((e,r,s)=>({o:s?s[1]:r,t:s&&s[0]?u(s[0].slice(0,t(e,s[0].length)),o(0,e-s[0].length)):u([],e),l:e,i:-1,u:u([],e)}))(s,n,f),B=new Set,C=()=>I-v,L=()=>C()+k+y,O=e=>((e,o,r,s)=>{if(s=t(s,e.l-1),$(e,s)<=o){const t=h(e,o+r,s);return[h(e,o,s,t),t]}{const t=h(e,o,void 0,s);return[t,h(e,o+r,t)]}})(W,e,b,M[0]),P=()=>(e=>e.l?$(e,e.l-1)+p(e,e.l-1):0)(W),q=e=>$(W,e)-k,U=e=>p(W,e),V=e=>{e&&(S()&&0!==z?k+=e:y+=e)};return{$getStateVersion:()=>g,$getCacheSnapshot:()=>(e=>[e.t.slice(),e.o])(W),$getRange:()=>{let e,r;return _?[e,r]=M:([e,r]=M=O(o(0,L())),R&&(e=t(e,R[0]),r=o(r,R[1]))),1!==z&&(e-=o(0,i)),2!==z&&(r+=o(0,i)),[o(e,0),t(r,W.l-1)]},$findStartIndex:()=>h(W,L()),$findEndIndex:()=>h(W,L()+b),$isUnmeasuredItem:e=>W.t[e]===a,v:()=>!!R&&W.t.slice(o(0,R[0]-1),t(W.l-1,R[1]+1)+1).includes(a),$getItemOffset:q,$getItemSize:U,$getItemsLength:()=>W.l,$getScrollOffset:()=>I,$isScrolling:()=>0!==z,$getViewportSize:()=>b,$getStartSpacerSize:()=>v,$getTotalSize:P,m:()=>(_=y,y=0,[_,2===T||C()+b>=P()]),$subscribe:(e,t)=>{const o=[e,t];return B.add(o),()=>{B.delete(o)}},$update:(t,s)=>{let n,i,l=0;switch(t){case 1:{const t=_;_=0;const o=s-I,n=r(o);t&&n<r(t)+1||0!==T||(z=o<0?2:1),x&&(R=e,x=!1),I=s,l=4;const c=C();c>=-b&&c<=P()&&(l+=1,i=n>b);break}case 2:l=8,0!==z&&(n=!0,l+=1),z=0,T=0,R=e;break;case 3:{const e=s.filter((([e,t])=>W.t[e]!==t));if(!e.length)break;V(e.reduce(((e,[t,o])=>((2===T||(R?!x&&t<R[0]:q(t)+(0===z&&0===T?U(t):0)<C()))&&(e+=o-U(t)),e)),0));for(const[t,o]of e){const e=U(t),r=d(W,t,o);w&&(J+=r?o:o-e)}w&&b&&J>b&&(V(((e,t)=>{let r=0;const s=[];e.t.forEach(((e,o)=>{e!==a&&(s.push(e),o<t&&r++)})),e.i=-1;const n=c(s),i=n.length,l=i/2|0,f=i%2==0?(n[l-1]+n[l])/2:n[l],u=e.o;return((e.o=f)-u)*o(t-r,0)})(W,h(W,L()))),w=!1),l=3,i=!0;break}case 4:b!==s&&(b=s,l=3);break;case 5:s[1]?(V(m(W,s[0],!0)),T=2,l=1):(m(W,s[0]),l=1);break;case 6:v=s;break;case 7:T=1;break;case 8:R=O(s),l=1}l&&(g=1+(2147483647&g),n&&k&&(y+=k,k=0),B.forEach((([e,t])=>{l&e&&t(i)})))}}},exports.createWindowResizer=(t,o)=>{const r=o?"width":"height",s=o?"innerWidth":"innerHeight",n=new WeakMap,c=R((o=>{const s=[];for(const{target:t,contentRect:c}of o){if(!t.offsetParent)continue;const o=n.get(t);o!=e&&s.push([o,c[r]])}s.length&&t.$update(3,s)}));let i;return{$observeRoot(e){const o=b(g(e)),r=()=>{t.$update(4,o[s])};o.addEventListener("resize",r),r(),i=()=>{o.removeEventListener("resize",r)}},$observeItem:(e,t)=>(n.set(e,t),c.S(e),()=>{n.delete(e),c.I(e)}),$dispose(){i&&i(),c.$()}}},exports.createWindowScroller=(e,t)=>{let o,r,s;const[c,i,f]=l(),a=(e,t,o,r,s=0)=>{const n=r?"offsetLeft":"offsetTop",c=s+(r&&v()?o.innerWidth-e[n]-e.offsetWidth:e[n]),i=e.offsetParent;return e!==t&&i?a(i,t,o,r,c):c};return{$observe(s){o=s;const n=t?"scrollX":"scrollY",c=g(s),l=b(c),f=c.body;r=z(e,l,t,(()=>_(l[n],t)),((o,r)=>{r?l.scroll({[t?"left":"top"]:e.$getScrollOffset()+o}):l.scrollBy(t?o:0,t?0:o)}),(()=>a(s,f,l,t))),i()},$dispose(){r&&r.$(),o=void 0,f()},$fixScrollJump:()=>{r&&r.h()},$scrollToIndex(r,{align:i,smooth:f,offset:u=0}={}){if(!o)return;if(r=n(r,0,e.$getItemsLength()-1),"nearest"===i){const t=e.$getItemOffset(r),o=e.$getScrollOffset();if(t<o)i="start";else{if(!(t+e.$getItemSize(r)>o+e.$getViewportSize()))return;i="end"}}const p=g(o),d=b(p),$=p.documentElement,h=()=>e.$getViewportSize()-(t?$.clientWidth:$.clientHeight);(async(r,n)=>{await c,s&&s();const i=()=>{const[t,o,r]=l();return s=r,y(e)&&k(r,150),[t,e.$subscribe(2,(()=>{o()}))]},f=b(g(o));if(n&&I()){for(;e.$update(8,r()),e.v();){const[e,t]=i();try{await e}catch(e){return}finally{t()}}f.scroll({[t?"left":"top"]:_(r(),t),behavior:"smooth"})}else for(;;){const[o,s]=i();try{f.scroll({[t?"left":"top"]:_(r(),t)}),e.$update(7),await o}catch(e){return}finally{s()}}})((()=>u+a(o,p.body,d,t)+e.$getItemOffset(r)+("end"===i?e.$getItemSize(r)-(e.$getViewportSize()-h()):"center"===i?(e.$getItemSize(r)-(e.$getViewportSize()-h()))/2:0)),f)}}},exports.getScrollSize=e=>o(e.$getTotalSize(),e.$getViewportSize()),exports.isBrowser=w,exports.isRTLDocument=v,exports.microtask=i,exports.sort=c;
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/lib/core/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../src/src/core/utils.ts","../../src/src/core/cache.ts","../../src/src/core/environment.ts","../../src/src/core/store.ts","../../src/src/core/scroller.ts","../../src/src/core/resizer.ts"],"sourcesContent":["/** @internal */\nexport const NULL = null;\n\n/** @internal */\nexport const { min, max, abs, floor } = Math;\n\n/**\n * @internal\n */\nexport const clamp = (\n value: number,\n minValue: number,\n maxValue: number\n): number => min(maxValue, max(minValue, value));\n\n/**\n * @internal\n */\nexport const sort = <T extends number>(arr: readonly T[]): T[] => {\n return [...arr].sort((a, b) => a - b);\n};\n\n/**\n * @internal\n */\nexport const microtask: (fn: () => void) => void =\n typeof queueMicrotask === \"function\"\n ? queueMicrotask\n : (fn) => {\n Promise.resolve().then(fn);\n };\n\n/**\n * @internal\n */\nexport const once = <T>(fn: () => T): (() => T) => {\n let cache: T;\n\n return () => {\n if (fn) {\n cache = fn();\n fn = undefined!;\n }\n return cache;\n };\n};\n","import { type InternalCacheSnapshot, type ItemsRange } from \"./types\";\nimport { clamp, floor, max, min, sort } from \"./utils\";\n\ntype Writeable<T> = {\n -readonly [key in keyof T]: Writeable<T[key]>;\n};\n\n/** @internal */\nexport const UNCACHED = -1;\n\n/**\n * @internal\n */\nexport type Cache = {\n readonly _length: number;\n // sizes\n readonly _sizes: number[];\n readonly _defaultItemSize: number;\n // offsets\n readonly _computedOffsetIndex: number;\n readonly _offsets: number[];\n};\n\nconst fill = (array: number[], length: number, prepend?: boolean): number[] => {\n const key = prepend ? \"unshift\" : \"push\";\n for (let i = 0; i < length; i++) {\n array[key](UNCACHED);\n }\n return array;\n};\n\n/**\n * @internal\n */\nexport const getItemSize = (cache: Cache, index: number): number => {\n const size = cache._sizes[index]!;\n return size === UNCACHED ? cache._defaultItemSize : size;\n};\n\n/**\n * @internal\n */\nexport const setItemSize = (\n cache: Writeable<Cache>,\n index: number,\n size: number\n): boolean => {\n const isInitialMeasurement = cache._sizes[index] === UNCACHED;\n cache._sizes[index] = size;\n // mark as dirty\n cache._computedOffsetIndex = min(index, cache._computedOffsetIndex);\n return isInitialMeasurement;\n};\n\n/**\n * @internal\n */\nexport const computeOffset = (\n cache: Writeable<Cache>,\n index: number\n): number => {\n if (!cache._length) return 0;\n if (cache._computedOffsetIndex >= index) {\n return cache._offsets[index]!;\n }\n\n if (cache._computedOffsetIndex < 0) {\n // first offset must be 0 to avoid returning NaN, which can cause infinite rerender.\n // https://github.com/inokawa/virtua/pull/160\n cache._offsets[0] = 0;\n cache._computedOffsetIndex = 0;\n }\n let i = cache._computedOffsetIndex;\n let top = cache._offsets[i]!;\n while (i < index) {\n top += getItemSize(cache, i);\n cache._offsets[++i] = top;\n }\n // mark as measured\n cache._computedOffsetIndex = index;\n return top;\n};\n\n/**\n * @internal\n */\nexport const computeTotalSize = (cache: Cache): number => {\n if (!cache._length) return 0;\n return (\n computeOffset(cache, cache._length - 1) +\n getItemSize(cache, cache._length - 1)\n );\n};\n\n/**\n * Finds the index of an item in the cache whose computed offset is closest to the specified offset.\n *\n * @internal\n */\nexport const findIndex = (\n cache: Cache,\n offset: number,\n low: number = 0,\n high: number = cache._length - 1\n): number => {\n // Find with binary search\n while (low <= high) {\n const mid = floor((low + high) / 2);\n const itemOffset = computeOffset(cache, mid);\n if (itemOffset <= offset) {\n if (itemOffset + getItemSize(cache, mid) > offset) {\n return mid;\n }\n low = mid + 1;\n } else {\n high = mid - 1;\n }\n }\n return clamp(low, 0, cache._length - 1);\n};\n\n/**\n * @internal\n */\nexport const computeRange = (\n cache: Cache,\n scrollOffset: number,\n viewportSize: number,\n prevStartIndex: number\n): ItemsRange => {\n // Clamp because prevStartIndex may exceed the limit when children decreased a lot after scrolling\n prevStartIndex = min(prevStartIndex, cache._length - 1);\n\n if (computeOffset(cache, prevStartIndex) <= scrollOffset) {\n // search forward\n // start <= end, prevStartIndex <= start\n const end = findIndex(cache, scrollOffset + viewportSize, prevStartIndex);\n return [findIndex(cache, scrollOffset, prevStartIndex, end), end];\n } else {\n // search backward\n // start <= end, start <= prevStartIndex\n const start = findIndex(cache, scrollOffset, undefined, prevStartIndex);\n return [start, findIndex(cache, scrollOffset + viewportSize, start)];\n }\n};\n\n/**\n * @internal\n */\nexport const estimateDefaultItemSize = (\n cache: Writeable<Cache>,\n startIndex: number\n): number => {\n let measuredCountBeforeStart = 0;\n // This function will be called after measurement so measured size array must be longer than 0\n const measuredSizes: number[] = [];\n cache._sizes.forEach((s, i) => {\n if (s !== UNCACHED) {\n measuredSizes.push(s);\n if (i < startIndex) {\n measuredCountBeforeStart++;\n }\n }\n });\n\n // Discard cache for now\n cache._computedOffsetIndex = -1;\n\n // Calculate median\n const sorted = sort(measuredSizes);\n const len = sorted.length;\n const mid = (len / 2) | 0;\n const median =\n len % 2 === 0 ? (sorted[mid - 1]! + sorted[mid]!) / 2 : sorted[mid]!;\n\n const prevDefaultItemSize = cache._defaultItemSize;\n\n // Calculate diff of unmeasured items before start\n return (\n ((cache._defaultItemSize = median) - prevDefaultItemSize) *\n max(startIndex - measuredCountBeforeStart, 0)\n );\n};\n\n/**\n * @internal\n */\nexport const initCache = (\n length: number,\n itemSize: number,\n snapshot?: InternalCacheSnapshot\n): Cache => {\n return {\n _defaultItemSize: snapshot ? snapshot[1] : itemSize,\n _sizes:\n snapshot && snapshot[0]\n ? // https://github.com/inokawa/virtua/issues/441\n fill(\n snapshot[0].slice(0, min(length, snapshot[0].length)),\n max(0, length - snapshot[0].length)\n )\n : fill([], length),\n _length: length,\n _computedOffsetIndex: -1,\n _offsets: fill([], length),\n };\n};\n\n/**\n * @internal\n */\nexport const takeCacheSnapshot = (cache: Cache): InternalCacheSnapshot => {\n return [cache._sizes.slice(), cache._defaultItemSize];\n};\n\n/**\n * @internal\n */\nexport const updateCacheLength = (\n cache: Writeable<Cache>,\n length: number,\n isShift?: boolean\n): number => {\n const diff = length - cache._length;\n\n cache._computedOffsetIndex = isShift\n ? // Discard cache for now\n -1\n : min(length - 1, cache._computedOffsetIndex);\n cache._length = length;\n\n if (diff > 0) {\n // Added\n fill(cache._offsets, diff);\n fill(cache._sizes, diff, isShift);\n return cache._defaultItemSize * diff;\n } else {\n // Removed\n cache._offsets.splice(diff);\n return (\n isShift ? cache._sizes.splice(0, -diff) : cache._sizes.splice(diff)\n ).reduce(\n (acc, removed) =>\n acc - (removed === UNCACHED ? cache._defaultItemSize : removed),\n 0\n );\n }\n};\n","import { once } from \"./utils\";\n\n/**\n * @internal\n */\nexport const isBrowser = typeof window !== \"undefined\";\n\nconst getDocumentElement = () => document.documentElement;\n\n/**\n * @internal\n */\nexport const getCurrentDocument = (node: HTMLElement): Document =>\n node.ownerDocument;\n\n/**\n * @internal\n */\nexport const getCurrentWindow = (doc: Document) => doc.defaultView!;\n\n/**\n * @internal\n */\nexport const isRTLDocument = /*#__PURE__*/ once((): boolean => {\n // TODO support SSR in rtl\n return isBrowser\n ? getComputedStyle(getDocumentElement()).direction === \"rtl\"\n : false;\n});\n\n/**\n * Currently, all browsers on iOS/iPadOS are WebKit, including WebView.\n * @internal\n */\nexport const isIOSWebKit = /*#__PURE__*/ once((): boolean => {\n return /iP(hone|od|ad)/.test(navigator.userAgent);\n});\n\n/**\n * @internal\n */\nexport const isSmoothScrollSupported = /*#__PURE__*/ once((): boolean => {\n return \"scrollBehavior\" in getDocumentElement().style;\n});\n","import {\n initCache,\n getItemSize as _getItemSize,\n computeTotalSize,\n computeOffset as computeStartOffset,\n UNCACHED,\n setItemSize,\n estimateDefaultItemSize,\n updateCacheLength,\n computeRange,\n takeCacheSnapshot,\n findIndex,\n} from \"./cache\";\nimport { isIOSWebKit } from \"./environment\";\nimport type {\n CacheSnapshot,\n InternalCacheSnapshot,\n ItemResize,\n ItemsRange,\n} from \"./types\";\nimport { abs, max, min, NULL } from \"./utils\";\n\nconst MAX_INT_32 = 0x7fffffff;\n\nconst SCROLL_IDLE = 0;\nconst SCROLL_DOWN = 1;\nconst SCROLL_UP = 2;\ntype ScrollDirection =\n | typeof SCROLL_IDLE\n | typeof SCROLL_DOWN\n | typeof SCROLL_UP;\n\nconst SCROLL_BY_NATIVE = 0;\nconst SCROLL_BY_MANUAL_SCROLL = 1;\nconst SCROLL_BY_SHIFT = 2;\ntype ScrollMode =\n | typeof SCROLL_BY_NATIVE\n | typeof SCROLL_BY_MANUAL_SCROLL\n | typeof SCROLL_BY_SHIFT;\n\n/** @internal */\nexport const ACTION_SCROLL = 1;\n/** @internal */\nexport const ACTION_SCROLL_END = 2;\n/** @internal */\nexport const ACTION_ITEM_RESIZE = 3;\n/** @internal */\nexport const ACTION_VIEWPORT_RESIZE = 4;\n/** @internal */\nexport const ACTION_ITEMS_LENGTH_CHANGE = 5;\n/** @internal */\nexport const ACTION_START_OFFSET_CHANGE = 6;\n/** @internal */\nexport const ACTION_MANUAL_SCROLL = 7;\n/** @internal */\nexport const ACTION_BEFORE_MANUAL_SMOOTH_SCROLL = 8;\n\ntype Actions =\n | [type: typeof ACTION_SCROLL, offset: number]\n | [type: typeof ACTION_SCROLL_END, dummy?: void]\n | [type: typeof ACTION_ITEM_RESIZE, entries: ItemResize[]]\n | [type: typeof ACTION_VIEWPORT_RESIZE, size: number]\n | [\n type: typeof ACTION_ITEMS_LENGTH_CHANGE,\n arg: [length: number, isShift?: boolean | undefined],\n ]\n | [type: typeof ACTION_START_OFFSET_CHANGE, offset: number]\n | [type: typeof ACTION_MANUAL_SCROLL, dummy?: void]\n | [type: typeof ACTION_BEFORE_MANUAL_SMOOTH_SCROLL, offset: number];\n\n/** @internal */\nexport const UPDATE_VIRTUAL_STATE = 0b0001;\n/** @internal */\nexport const UPDATE_SIZE_EVENT = 0b0010;\n/** @internal */\nexport const UPDATE_SCROLL_EVENT = 0b0100;\n/** @internal */\nexport const UPDATE_SCROLL_END_EVENT = 0b1000;\n\n/**\n * @internal\n */\nexport const getScrollSize = (store: VirtualStore): number => {\n return max(store.$getTotalSize(), store.$getViewportSize());\n};\n\n/**\n * @internal\n */\nexport const isInitialMeasurementDone = (store: VirtualStore): boolean => {\n return !!store.$getViewportSize();\n};\n\ntype Subscriber = (sync?: boolean) => void;\n\n/** @internal */\nexport type StateVersion =\n number & {} /* hack for typescript to pretend as not falsy */;\n\n/**\n * @internal\n */\nexport type VirtualStore = {\n $getStateVersion(): StateVersion;\n $getCacheSnapshot(): CacheSnapshot;\n $getRange(): ItemsRange;\n $findStartIndex(): number;\n $findEndIndex(): number;\n $isUnmeasuredItem(index: number): boolean;\n $getItemOffset(index: number): number;\n $getItemSize(index: number): number;\n $getItemsLength(): number;\n $getScrollOffset(): number;\n $isScrolling(): boolean;\n $getViewportSize(): number;\n $getStartSpacerSize(): number;\n $getTotalSize(): number;\n _flushJump(): [number, boolean];\n $subscribe(target: number, cb: Subscriber): () => void;\n $update(...action: Actions): void;\n _hasUnmeasuredItemsInFrozenRange(): boolean;\n};\n\n/**\n * @internal\n */\nexport const createVirtualStore = (\n elementsCount: number,\n itemSize: number = 40,\n overscan: number = 4,\n ssrCount: number = 0,\n cacheSnapshot?: CacheSnapshot | undefined,\n shouldAutoEstimateItemSize: boolean = false\n): VirtualStore => {\n let isSSR = !!ssrCount;\n let stateVersion: StateVersion = 1;\n let viewportSize = 0;\n let startSpacerSize = 0;\n let scrollOffset = 0;\n let jump = 0;\n let pendingJump = 0;\n let _flushedJump = 0;\n let _scrollDirection: ScrollDirection = SCROLL_IDLE;\n let _scrollMode: ScrollMode = SCROLL_BY_NATIVE;\n let _frozenRange: ItemsRange | null = isSSR\n ? [0, max(ssrCount - 1, 0)]\n : NULL;\n let _prevRange: ItemsRange = [0, 0];\n let _totalMeasuredSize = 0;\n\n const cache = initCache(\n elementsCount,\n itemSize,\n cacheSnapshot as unknown as InternalCacheSnapshot | undefined\n );\n const subscribers = new Set<[number, Subscriber]>();\n const getRelativeScrollOffset = () => scrollOffset - startSpacerSize;\n const getVisibleOffset = () => getRelativeScrollOffset() + pendingJump + jump;\n const getRange = (offset: number) => {\n return computeRange(cache, offset, viewportSize, _prevRange[0]);\n };\n const getTotalSize = (): number => computeTotalSize(cache);\n const getItemOffset = (index: number): number => {\n return computeStartOffset(cache, index) - pendingJump;\n };\n const getItemSize = (index: number): number => {\n return _getItemSize(cache, index);\n };\n\n const applyJump = (j: number) => {\n if (j) {\n // In iOS WebKit browsers, updating scroll position will stop scrolling so it have to be deferred during scrolling.\n if (isIOSWebKit() && _scrollDirection !== SCROLL_IDLE) {\n pendingJump += j;\n } else {\n jump += j;\n }\n }\n };\n\n return {\n $getStateVersion: () => stateVersion,\n $getCacheSnapshot: () => {\n return takeCacheSnapshot(cache) as unknown as CacheSnapshot;\n },\n $getRange: () => {\n let startIndex: number;\n let endIndex: number;\n if (_flushedJump) {\n // Return previous range for consistent render until next scroll event comes in.\n // And it must be clamped. https://github.com/inokawa/virtua/issues/597\n [startIndex, endIndex] = _prevRange;\n } else {\n [startIndex, endIndex] = _prevRange = getRange(\n max(0, getVisibleOffset())\n );\n if (_frozenRange) {\n startIndex = min(startIndex, _frozenRange[0]);\n endIndex = max(endIndex, _frozenRange[1]);\n }\n }\n\n if (_scrollDirection !== SCROLL_DOWN) {\n startIndex -= max(0, overscan);\n }\n if (_scrollDirection !== SCROLL_UP) {\n endIndex += max(0, overscan);\n }\n return [max(startIndex, 0), min(endIndex, cache._length - 1)];\n },\n $findStartIndex: () => findIndex(cache, getVisibleOffset()),\n $findEndIndex: () => findIndex(cache, getVisibleOffset() + viewportSize),\n $isUnmeasuredItem: (index) => cache._sizes[index] === UNCACHED,\n _hasUnmeasuredItemsInFrozenRange: () => {\n if (!_frozenRange) return false;\n return cache._sizes\n .slice(\n max(0, _frozenRange[0] - 1),\n min(cache._length - 1, _frozenRange[1] + 1) + 1\n )\n .includes(UNCACHED);\n },\n $getItemOffset: getItemOffset,\n $getItemSize: getItemSize,\n $getItemsLength: () => cache._length,\n $getScrollOffset: () => scrollOffset,\n $isScrolling: () => _scrollDirection !== SCROLL_IDLE,\n $getViewportSize: () => viewportSize,\n $getStartSpacerSize: () => startSpacerSize,\n $getTotalSize: getTotalSize,\n _flushJump: () => {\n _flushedJump = jump;\n jump = 0;\n return [\n _flushedJump,\n // Use absolute position not to exceed scrollable bounds\n _scrollMode === SCROLL_BY_SHIFT ||\n // https://github.com/inokawa/virtua/discussions/475\n getRelativeScrollOffset() + viewportSize >= getTotalSize(),\n ];\n },\n $subscribe: (target, cb) => {\n const sub: [number, Subscriber] = [target, cb];\n subscribers.add(sub);\n return () => {\n subscribers.delete(sub);\n };\n },\n $update: (type, payload): void => {\n let shouldFlushPendingJump: boolean | undefined;\n let shouldSync: boolean | undefined;\n let mutated = 0;\n\n switch (type) {\n case ACTION_SCROLL: {\n const flushedJump = _flushedJump;\n _flushedJump = 0;\n\n const delta = payload - scrollOffset;\n const distance = abs(delta);\n\n // Scroll event after jump compensation is not reliable because it may result in the opposite direction.\n // The delta of artificial scroll may not be equal with the jump because it may be batched with other scrolls.\n // And at least in latest Chrome/Firefox/Safari in 2023, setting value to scrollTop/scrollLeft can lose subpixel because its integer (sometimes float probably depending on dpr).\n const isJustJumped = flushedJump && distance < abs(flushedJump) + 1;\n\n // Scroll events are dispatched enough so it's ok to skip some of them.\n if (\n !isJustJumped &&\n // Ignore until manual scrolling\n _scrollMode === SCROLL_BY_NATIVE\n ) {\n _scrollDirection = delta < 0 ? SCROLL_UP : SCROLL_DOWN;\n }\n\n // TODO This will cause glitch in reverse infinite scrolling. Disable this until better solution is found.\n // if (\n // pendingJump &&\n // ((_scrollDirection === SCROLL_UP &&\n // payload - max(pendingJump, 0) <= 0) ||\n // (_scrollDirection === SCROLL_DOWN &&\n // payload - min(pendingJump, 0) >= getScrollOffsetMax()))\n // ) {\n // // Flush if almost reached to start or end\n // shouldFlushPendingJump = true;\n // }\n\n if (isSSR) {\n _frozenRange = NULL;\n isSSR = false;\n }\n\n scrollOffset = payload;\n mutated = UPDATE_SCROLL_EVENT;\n\n // Skip if offset is not changed\n // Scroll offset may exceed min or max especially in Safari's elastic scrolling.\n const relativeOffset = getRelativeScrollOffset();\n if (\n relativeOffset >= -viewportSize &&\n relativeOffset <= getTotalSize()\n ) {\n mutated += UPDATE_VIRTUAL_STATE;\n\n // Update synchronously if scrolled a lot\n shouldSync = distance > viewportSize;\n }\n break;\n }\n case ACTION_SCROLL_END: {\n mutated = UPDATE_SCROLL_END_EVENT;\n if (_scrollDirection !== SCROLL_IDLE) {\n shouldFlushPendingJump = true;\n mutated += UPDATE_VIRTUAL_STATE;\n }\n _scrollDirection = SCROLL_IDLE;\n _scrollMode = SCROLL_BY_NATIVE;\n _frozenRange = NULL;\n break;\n }\n case ACTION_ITEM_RESIZE: {\n const updated = payload.filter(\n ([index, size]) => cache._sizes[index] !== size\n );\n\n // Skip if all items are cached and not updated\n if (!updated.length) {\n break;\n }\n\n // Calculate jump by resize to minimize junks in appearance\n applyJump(\n updated.reduce((acc, [index, size]) => {\n if (\n // Keep distance from end during shifting\n _scrollMode === SCROLL_BY_SHIFT ||\n (_frozenRange\n ? // https://github.com/inokawa/virtua/issues/380\n // https://github.com/inokawa/virtua/issues/590\n !isSSR && index < _frozenRange[0]\n : // Otherwise we should maintain visible position\n getItemOffset(index) +\n // https://github.com/inokawa/virtua/issues/385\n (_scrollDirection === SCROLL_IDLE &&\n _scrollMode === SCROLL_BY_NATIVE\n ? getItemSize(index)\n : 0) <\n getRelativeScrollOffset())\n ) {\n acc += size - getItemSize(index);\n }\n return acc;\n }, 0)\n );\n\n // Update item sizes\n for (const [index, size] of updated) {\n const prevSize = getItemSize(index);\n const isInitialMeasurement = setItemSize(cache, index, size);\n\n if (shouldAutoEstimateItemSize) {\n _totalMeasuredSize += isInitialMeasurement\n ? size\n : size - prevSize;\n }\n }\n\n // Estimate initial item size from measured sizes\n if (\n shouldAutoEstimateItemSize &&\n viewportSize &&\n // If the total size is lower than the viewport, the item may be a empty state\n _totalMeasuredSize > viewportSize\n ) {\n applyJump(\n estimateDefaultItemSize(\n cache,\n findIndex(cache, getVisibleOffset())\n )\n );\n shouldAutoEstimateItemSize = false;\n }\n\n mutated = UPDATE_VIRTUAL_STATE + UPDATE_SIZE_EVENT;\n\n // Synchronous update is necessary in current design to minimize visible glitch in concurrent rendering.\n // However this seems to be the main cause of the errors from ResizeObserver.\n // https://github.com/inokawa/virtua/issues/470\n //\n // And in React, synchronous update with flushSync after asynchronous update will overtake the asynchronous one.\n // If items resize happens just after scroll, race condition can occur depending on implementation.\n shouldSync = true;\n break;\n }\n case ACTION_VIEWPORT_RESIZE: {\n if (viewportSize !== payload) {\n viewportSize = payload;\n mutated = UPDATE_VIRTUAL_STATE + UPDATE_SIZE_EVENT;\n }\n break;\n }\n case ACTION_ITEMS_LENGTH_CHANGE: {\n if (payload[1]) {\n applyJump(updateCacheLength(cache, payload[0], true));\n _scrollMode = SCROLL_BY_SHIFT;\n mutated = UPDATE_VIRTUAL_STATE;\n } else {\n updateCacheLength(cache, payload[0]);\n // https://github.com/inokawa/virtua/issues/552\n // https://github.com/inokawa/virtua/issues/557\n mutated = UPDATE_VIRTUAL_STATE;\n }\n break;\n }\n case ACTION_START_OFFSET_CHANGE: {\n startSpacerSize = payload;\n break;\n }\n case ACTION_MANUAL_SCROLL: {\n _scrollMode = SCROLL_BY_MANUAL_SCROLL;\n break;\n }\n case ACTION_BEFORE_MANUAL_SMOOTH_SCROLL: {\n _frozenRange = getRange(payload);\n mutated = UPDATE_VIRTUAL_STATE;\n break;\n }\n }\n\n if (mutated) {\n stateVersion = (stateVersion & MAX_INT_32) + 1;\n\n if (shouldFlushPendingJump && pendingJump) {\n jump += pendingJump;\n pendingJump = 0;\n }\n\n subscribers.forEach(([target, cb]) => {\n // Early return to skip React's computation\n if (!(mutated & target)) {\n return;\n }\n // https://github.com/facebook/react/issues/25191\n // https://github.com/facebook/react/blob/a5fc797db14c6e05d4d5c4dbb22a0dd70d41f5d5/packages/react-reconciler/src/ReactFiberWorkLoop.js#L1443-L1447\n cb(shouldSync);\n });\n }\n },\n };\n};\n","import {\n getCurrentDocument,\n getCurrentWindow,\n isIOSWebKit,\n isRTLDocument,\n isSmoothScrollSupported,\n} from \"./environment\";\nimport {\n ACTION_SCROLL,\n type VirtualStore,\n ACTION_SCROLL_END,\n UPDATE_SIZE_EVENT,\n ACTION_MANUAL_SCROLL,\n ACTION_BEFORE_MANUAL_SMOOTH_SCROLL,\n ACTION_START_OFFSET_CHANGE,\n isInitialMeasurementDone,\n} from \"./store\";\nimport { type ScrollToIndexOpts } from \"./types\";\nimport { clamp, microtask, NULL } from \"./utils\";\n\nconst timeout = setTimeout;\n\nconst debounce = <T extends () => void>(fn: T, ms: number) => {\n let id: ReturnType<typeof setTimeout> | undefined | null;\n\n const cancel = () => {\n if (id != NULL) {\n clearTimeout(id);\n }\n };\n const debouncedFn = () => {\n cancel();\n id = timeout(() => {\n id = NULL;\n fn();\n }, ms);\n };\n debouncedFn._cancel = cancel;\n return debouncedFn;\n};\n\n/**\n * scrollLeft is negative value in rtl direction.\n *\n * left right\n * 0 100 spec compliant (ltr)\n * -100 0 spec compliant (rtl)\n * https://github.com/othree/jquery.rtl-scroll-type\n */\nconst normalizeOffset = (offset: number, isHorizontal: boolean): number => {\n if (isHorizontal && isRTLDocument()) {\n return -offset;\n } else {\n return offset;\n }\n};\n\nconst createScrollObserver = (\n store: VirtualStore,\n viewport: HTMLElement | Window,\n isHorizontal: boolean,\n getScrollOffset: () => number,\n updateScrollOffset: (\n value: number,\n shift: boolean,\n isMomentumScrolling: boolean\n ) => void,\n getStartOffset?: () => number\n) => {\n const now = Date.now;\n\n let lastScrollTime = 0;\n let wheeling = false;\n let touching = false;\n let justTouchEnded = false;\n let stillMomentumScrolling = false;\n\n const onScrollEnd = debounce(() => {\n if (wheeling || touching) {\n wheeling = false;\n\n // Wait while wheeling or touching\n onScrollEnd();\n return;\n }\n\n justTouchEnded = false;\n\n store.$update(ACTION_SCROLL_END);\n }, 150);\n\n const onScroll = () => {\n lastScrollTime = now();\n\n if (justTouchEnded) {\n stillMomentumScrolling = true;\n }\n\n if (getStartOffset) {\n store.$update(ACTION_START_OFFSET_CHANGE, getStartOffset());\n }\n store.$update(ACTION_SCROLL, getScrollOffset());\n\n onScrollEnd();\n };\n\n // Infer scroll state also from wheel events\n // Sometimes scroll events do not fire when frame dropped even if the visual have been already scrolled\n const onWheel = ((e: WheelEvent) => {\n if (\n wheeling ||\n // Scroll start should be detected with scroll event\n !store.$isScrolling() ||\n // Probably a pinch-to-zoom gesture\n e.ctrlKey\n ) {\n return;\n }\n\n const timeDelta = now() - lastScrollTime;\n if (\n // Check if wheel event occurs some time after scrolling\n 150 > timeDelta &&\n 50 < timeDelta &&\n // Get delta before checking deltaMode for firefox behavior\n // https://github.com/w3c/uievents/issues/181#issuecomment-392648065\n // https://bugzilla.mozilla.org/show_bug.cgi?id=1392460#c34\n (isHorizontal ? e.deltaX : e.deltaY)\n ) {\n wheeling = true;\n }\n }) as (e: Event) => void; // FIXME type error. why only here?\n\n const onTouchStart = () => {\n touching = true;\n justTouchEnded = stillMomentumScrolling = false;\n };\n const onTouchEnd = () => {\n touching = false;\n if (isIOSWebKit()) {\n justTouchEnded = true;\n }\n };\n\n viewport.addEventListener(\"scroll\", onScroll);\n viewport.addEventListener(\"wheel\", onWheel, { passive: true });\n viewport.addEventListener(\"touchstart\", onTouchStart, { passive: true });\n viewport.addEventListener(\"touchend\", onTouchEnd, { passive: true });\n\n return {\n _dispose: () => {\n viewport.removeEventListener(\"scroll\", onScroll);\n viewport.removeEventListener(\"wheel\", onWheel);\n viewport.removeEventListener(\"touchstart\", onTouchStart);\n viewport.removeEventListener(\"touchend\", onTouchEnd);\n onScrollEnd._cancel();\n },\n _fixScrollJump: () => {\n const [jump, shift] = store._flushJump();\n if (!jump) return;\n updateScrollOffset(\n normalizeOffset(jump, isHorizontal),\n shift,\n stillMomentumScrolling\n );\n stillMomentumScrolling = false;\n\n if (shift && store.$getViewportSize() > store.$getTotalSize()) {\n // In this case applying jump may not cause scroll.\n // Current logic expects scroll event occurs after applying jump so we dispatch it manually.\n store.$update(ACTION_SCROLL, getScrollOffset());\n }\n },\n };\n};\n\ntype ScrollObserver = ReturnType<typeof createScrollObserver>;\n\n/**\n * @internal\n */\nexport type Scroller = {\n $observe: (viewportElement: HTMLElement) => void;\n $dispose(): void;\n $scrollTo: (offset: number) => void;\n $scrollBy: (offset: number) => void;\n $scrollToIndex: (index: number, opts?: ScrollToIndexOpts) => void;\n $fixScrollJump: () => void;\n};\n\n/**\n * @internal\n */\nexport const createScroller = (\n store: VirtualStore,\n isHorizontal: boolean\n): Scroller => {\n let viewportElement: HTMLElement | undefined;\n let scrollObserver: ScrollObserver | undefined;\n let cancelScroll: (() => void) | undefined;\n const scrollOffsetKey = isHorizontal ? \"scrollLeft\" : \"scrollTop\";\n const overflowKey = isHorizontal ? \"overflowX\" : \"overflowY\";\n\n // The given offset will be clamped by browser\n // https://drafts.csswg.org/cssom-view/#dom-element-scrolltop\n const scheduleImperativeScroll = async (\n getTargetOffset: () => number,\n smooth?: boolean\n ) => {\n if (!viewportElement) {\n // Wait for element assign. The element may be undefined if scrollRef prop is used and scroll is scheduled on mount.\n microtask(() => scheduleImperativeScroll(getTargetOffset, smooth));\n return;\n }\n\n if (cancelScroll) {\n // Cancel waiting scrollTo\n cancelScroll();\n }\n\n const waitForMeasurement = (): [Promise<void>, () => void] => {\n // Wait for the scroll destination items to be measured.\n // The measurement will be done asynchronously and the timing is not predictable so we use promise.\n let queue: (() => void) | undefined;\n return [\n new Promise<void>((resolve, reject) => {\n queue = resolve;\n cancelScroll = reject;\n\n // Resize event may not happen when the window/tab is not visible, or during browser back in Safari.\n // We have to wait for the initial measurement to avoid failing imperative scroll on mount.\n // https://github.com/inokawa/virtua/issues/450\n if (isInitialMeasurementDone(store)) {\n // Reject when items around scroll destination completely measured\n timeout(reject, 150);\n }\n }),\n store.$subscribe(UPDATE_SIZE_EVENT, () => {\n queue && queue();\n }),\n ];\n };\n\n if (smooth && isSmoothScrollSupported()) {\n while (true) {\n store.$update(ACTION_BEFORE_MANUAL_SMOOTH_SCROLL, getTargetOffset());\n\n if (!store._hasUnmeasuredItemsInFrozenRange()) {\n break;\n }\n\n const [promise, unsubscribe] = waitForMeasurement();\n\n try {\n await promise;\n } catch (e) {\n // canceled\n return;\n } finally {\n unsubscribe();\n }\n }\n\n viewportElement.scrollTo({\n [isHorizontal ? \"left\" : \"top\"]: normalizeOffset(\n getTargetOffset(),\n isHorizontal\n ),\n behavior: \"smooth\",\n });\n } else {\n while (true) {\n const [promise, unsubscribe] = waitForMeasurement();\n\n try {\n viewportElement[scrollOffsetKey] = normalizeOffset(\n getTargetOffset(),\n isHorizontal\n );\n store.$update(ACTION_MANUAL_SCROLL);\n\n await promise;\n } catch (e) {\n // canceled or finished\n return;\n } finally {\n unsubscribe();\n }\n }\n }\n };\n\n return {\n $observe(viewport) {\n viewportElement = viewport;\n\n scrollObserver = createScrollObserver(\n store,\n viewport,\n isHorizontal,\n () => normalizeOffset(viewport[scrollOffsetKey], isHorizontal),\n (jump, shift, isMomentumScrolling) => {\n // If we update scroll position while touching on iOS, the position will be reverted.\n // However iOS WebKit fires touch events only once at the beginning of momentum scrolling.\n // That means we have no reliable way to confirm still touched or not if user touches more than once during momentum scrolling...\n // This is a hack for the suspectable situations, inspired by https://github.com/prud/ios-overflow-scroll-to-top\n if (isMomentumScrolling) {\n const style = viewport.style;\n const prev = style[overflowKey];\n style[overflowKey] = \"hidden\";\n timeout(() => {\n style[overflowKey] = prev;\n });\n }\n\n if (shift) {\n viewport[scrollOffsetKey] = store.$getScrollOffset() + jump;\n // https://github.com/inokawa/virtua/issues/357\n cancelScroll && cancelScroll();\n } else {\n viewport[scrollOffsetKey] += jump;\n }\n }\n );\n },\n $dispose() {\n scrollObserver && scrollObserver._dispose();\n },\n $scrollTo(offset) {\n scheduleImperativeScroll(() => offset);\n },\n $scrollBy(offset) {\n offset += store.$getScrollOffset();\n scheduleImperativeScroll(() => offset);\n },\n $scrollToIndex(index, { align, smooth, offset = 0 } = {}) {\n index = clamp(index, 0, store.$getItemsLength() - 1);\n\n if (align === \"nearest\") {\n const itemOffset = store.$getItemOffset(index);\n const scrollOffset = store.$getScrollOffset();\n\n if (itemOffset < scrollOffset) {\n align = \"start\";\n } else if (\n itemOffset + store.$getItemSize(index) >\n scrollOffset + store.$getViewportSize()\n ) {\n align = \"end\";\n } else {\n // already completely visible\n return;\n }\n }\n\n scheduleImperativeScroll(() => {\n return (\n offset +\n store.$getStartSpacerSize() +\n store.$getItemOffset(index) +\n (align === \"end\"\n ? store.$getItemSize(index) - store.$getViewportSize()\n : align === \"center\"\n ? (store.$getItemSize(index) - store.$getViewportSize()) / 2\n : 0)\n );\n }, smooth);\n },\n $fixScrollJump: () => {\n scrollObserver && scrollObserver._fixScrollJump();\n },\n };\n};\n\n/**\n * @internal\n */\nexport type WindowScroller = {\n $observe(containerElement: HTMLElement): void;\n $dispose(): void;\n $scrollToIndex: (index: number, opts?: ScrollToIndexOpts) => void;\n $fixScrollJump: () => void;\n};\n\n/**\n * @internal\n */\nexport const createWindowScroller = (\n store: VirtualStore,\n isHorizontal: boolean\n): WindowScroller => {\n let containerElement: HTMLElement | undefined;\n let scrollObserver: ScrollObserver | undefined;\n let cancelScroll: (() => void) | undefined;\n\n const calcOffsetToViewport = (\n node: HTMLElement,\n viewport: HTMLElement,\n window: Window,\n isHorizontal: boolean,\n offset: number = 0\n ): number => {\n // TODO calc offset only when it changes (maybe impossible)\n const offsetKey = isHorizontal ? \"offsetLeft\" : \"offsetTop\";\n const offsetSum =\n offset +\n (isHorizontal && isRTLDocument()\n ? window.innerWidth - node[offsetKey] - node.offsetWidth\n : node[offsetKey]);\n\n const parent = node.offsetParent;\n if (node === viewport || !parent) {\n return offsetSum;\n }\n\n return calcOffsetToViewport(\n parent as HTMLElement,\n viewport,\n window,\n isHorizontal,\n offsetSum\n );\n };\n\n const scheduleImperativeScroll = async (\n getTargetOffset: () => number,\n smooth?: boolean\n ) => {\n if (!containerElement) {\n // Wait for element assign\n microtask(() => scheduleImperativeScroll(getTargetOffset, smooth));\n return;\n }\n\n if (cancelScroll) {\n cancelScroll();\n }\n\n const waitForMeasurement = (): [Promise<void>, () => void] => {\n let queue: (() => void) | undefined;\n return [\n new Promise<void>((resolve, reject) => {\n queue = resolve;\n cancelScroll = reject;\n\n if (isInitialMeasurementDone(store)) {\n timeout(reject, 150);\n }\n }),\n store.$subscribe(UPDATE_SIZE_EVENT, () => {\n queue && queue();\n }),\n ];\n };\n\n const window = getCurrentWindow(getCurrentDocument(containerElement));\n\n if (smooth && isSmoothScrollSupported()) {\n while (true) {\n store.$update(ACTION_BEFORE_MANUAL_SMOOTH_SCROLL, getTargetOffset());\n\n if (!store._hasUnmeasuredItemsInFrozenRange()) {\n break;\n }\n\n const [promise, unsubscribe] = waitForMeasurement();\n\n try {\n await promise;\n } catch (e) {\n return;\n } finally {\n unsubscribe();\n }\n }\n\n window.scroll({\n [isHorizontal ? \"left\" : \"top\"]: normalizeOffset(\n getTargetOffset(),\n isHorizontal\n ),\n behavior: \"smooth\",\n });\n } else {\n while (true) {\n const [promise, unsubscribe] = waitForMeasurement();\n\n try {\n window.scroll({\n [isHorizontal ? \"left\" : \"top\"]: normalizeOffset(\n getTargetOffset(),\n isHorizontal\n ),\n });\n store.$update(ACTION_MANUAL_SCROLL);\n\n await promise;\n } catch (e) {\n return;\n } finally {\n unsubscribe();\n }\n }\n }\n };\n\n return {\n $observe(container) {\n containerElement = container;\n const scrollOffsetKey = isHorizontal ? \"scrollX\" : \"scrollY\";\n\n const document = getCurrentDocument(container);\n const window = getCurrentWindow(document);\n const documentBody = document.body;\n\n scrollObserver = createScrollObserver(\n store,\n window,\n isHorizontal,\n () => normalizeOffset(window[scrollOffsetKey], isHorizontal),\n (jump, shift) => {\n // TODO support case two window scrollers exist in the same view\n if (shift) {\n window.scroll({\n [isHorizontal ? \"left\" : \"top\"]: store.$getScrollOffset() + jump,\n });\n } else {\n window.scrollBy(isHorizontal ? jump : 0, isHorizontal ? 0 : jump);\n }\n },\n () =>\n calcOffsetToViewport(container, documentBody, window, isHorizontal)\n );\n },\n $dispose() {\n scrollObserver && scrollObserver._dispose();\n containerElement = undefined;\n },\n $fixScrollJump: () => {\n scrollObserver && scrollObserver._fixScrollJump();\n },\n $scrollToIndex(index, { align, smooth, offset = 0 } = {}) {\n if (!containerElement) return;\n\n index = clamp(index, 0, store.$getItemsLength() - 1);\n\n if (align === \"nearest\") {\n const itemOffset = store.$getItemOffset(index);\n const scrollOffset = store.$getScrollOffset();\n\n if (itemOffset < scrollOffset) {\n align = \"start\";\n } else if (\n itemOffset + store.$getItemSize(index) >\n scrollOffset + store.$getViewportSize()\n ) {\n align = \"end\";\n } else {\n return;\n }\n }\n\n const document = getCurrentDocument(containerElement);\n const window = getCurrentWindow(document);\n const html = document.documentElement;\n const getScrollbarSize = () =>\n store.$getViewportSize() -\n (isHorizontal ? html.clientWidth : html.clientHeight);\n\n scheduleImperativeScroll(() => {\n return (\n offset +\n // Calculate target scroll position including container's offset from document\n calcOffsetToViewport(\n containerElement!,\n document.body,\n window,\n isHorizontal\n ) +\n // store._getStartSpacerSize() +\n store.$getItemOffset(index) +\n (align === \"end\"\n ? store.$getItemSize(index) -\n (store.$getViewportSize() - getScrollbarSize())\n : align === \"center\"\n ? (store.$getItemSize(index) -\n (store.$getViewportSize() - getScrollbarSize())) /\n 2\n : 0)\n );\n }, smooth);\n },\n };\n};\n\n/**\n * @internal\n */\nexport type GridScroller = {\n $observe: (viewportElement: HTMLElement) => void;\n $dispose(): void;\n $scrollTo: (offsetX: number, offsetY: number) => void;\n $scrollBy: (offsetX: number, offsetY: number) => void;\n $scrollToIndex: (indexX: number, indexY: number) => void;\n $fixScrollJump: () => void;\n};\n\n/**\n * @internal\n */\nexport const createGridScroller = (\n vStore: VirtualStore,\n hStore: VirtualStore\n): GridScroller => {\n const vScroller = createScroller(vStore, false);\n const hScroller = createScroller(hStore, true);\n return {\n $observe(viewportElement) {\n vScroller.$observe(viewportElement);\n hScroller.$observe(viewportElement);\n },\n $dispose() {\n vScroller.$dispose();\n hScroller.$dispose();\n },\n $scrollTo(offsetX, offsetY) {\n vScroller.$scrollTo(offsetY);\n hScroller.$scrollTo(offsetX);\n },\n $scrollBy(offsetX, offsetY) {\n vScroller.$scrollBy(offsetY);\n hScroller.$scrollBy(offsetX);\n },\n $scrollToIndex(indexX, indexY) {\n vScroller.$scrollToIndex(indexY);\n hScroller.$scrollToIndex(indexX);\n },\n $fixScrollJump() {\n vScroller.$fixScrollJump();\n hScroller.$fixScrollJump();\n },\n };\n};\n","import { getCurrentDocument, getCurrentWindow } from \"./environment\";\nimport {\n ACTION_ITEM_RESIZE,\n ACTION_VIEWPORT_RESIZE,\n type VirtualStore,\n} from \"./store\";\nimport { type ItemResize } from \"./types\";\nimport { max, NULL } from \"./utils\";\n\nconst createResizeObserver = (cb: ResizeObserverCallback) => {\n let ro: ResizeObserver | undefined;\n\n return {\n _observe(e: HTMLElement) {\n // Initialize ResizeObserver lazily for SSR\n // https://www.w3.org/TR/resize-observer/#intro\n (\n ro ||\n // https://bugs.chromium.org/p/chromium/issues/detail?id=1491739\n (ro = new (getCurrentWindow(getCurrentDocument(e)).ResizeObserver)(cb))\n ).observe(e);\n },\n _unobserve(e: HTMLElement) {\n ro!.unobserve(e);\n },\n _dispose() {\n ro && ro.disconnect();\n },\n };\n};\n\n/**\n * @internal\n */\nexport type ItemResizeObserver = (el: HTMLElement, i: number) => () => void;\n\ninterface ListResizer {\n $observeRoot(viewportElement: HTMLElement): void;\n $observeItem: ItemResizeObserver;\n $dispose(): void;\n}\n\n/**\n * @internal\n */\nexport const createResizer = (\n store: VirtualStore,\n isHorizontal: boolean\n): ListResizer => {\n let viewportElement: HTMLElement | undefined;\n const sizeKey = isHorizontal ? \"width\" : \"height\";\n const mountedIndexes = new WeakMap<Element, number>();\n\n const resizeObserver = createResizeObserver((entries) => {\n const resizes: ItemResize[] = [];\n for (const { target, contentRect } of entries) {\n // Skip zero-sized rects that may be observed under `display: none` style\n if (!(target as HTMLElement).offsetParent) continue;\n\n if (target === viewportElement) {\n store.$update(ACTION_VIEWPORT_RESIZE, contentRect[sizeKey]);\n } else {\n const index = mountedIndexes.get(target);\n if (index != NULL) {\n resizes.push([index, contentRect[sizeKey]]);\n }\n }\n }\n\n if (resizes.length) {\n store.$update(ACTION_ITEM_RESIZE, resizes);\n }\n });\n\n return {\n $observeRoot(viewport: HTMLElement) {\n resizeObserver._observe((viewportElement = viewport));\n },\n $observeItem: (el: HTMLElement, i: number) => {\n mountedIndexes.set(el, i);\n resizeObserver._observe(el);\n return () => {\n mountedIndexes.delete(el);\n resizeObserver._unobserve(el);\n };\n },\n $dispose: resizeObserver._dispose,\n };\n};\n\ninterface WindowListResizer {\n $observeRoot(container: HTMLElement): void;\n $observeItem: ItemResizeObserver;\n $dispose(): void;\n}\n\n/**\n * @internal\n */\nexport const createWindowResizer = (\n store: VirtualStore,\n isHorizontal: boolean\n): WindowListResizer => {\n const sizeKey = isHorizontal ? \"width\" : \"height\";\n const windowSizeKey = isHorizontal ? \"innerWidth\" : \"innerHeight\";\n const mountedIndexes = new WeakMap<Element, number>();\n\n const resizeObserver = createResizeObserver((entries) => {\n const resizes: ItemResize[] = [];\n for (const { target, contentRect } of entries) {\n // Skip zero-sized rects that may be observed under `display: none` style\n if (!(target as HTMLElement).offsetParent) continue;\n\n const index = mountedIndexes.get(target);\n if (index != NULL) {\n resizes.push([index, contentRect[sizeKey]]);\n }\n }\n\n if (resizes.length) {\n store.$update(ACTION_ITEM_RESIZE, resizes);\n }\n });\n\n let cleanupOnWindowResize: (() => void) | undefined;\n\n return {\n $observeRoot(container) {\n const window = getCurrentWindow(getCurrentDocument(container));\n const onWindowResize = () => {\n store.$update(ACTION_VIEWPORT_RESIZE, window[windowSizeKey]);\n };\n window.addEventListener(\"resize\", onWindowResize);\n onWindowResize();\n\n cleanupOnWindowResize = () => {\n window.removeEventListener(\"resize\", onWindowResize);\n };\n },\n $observeItem: (el: HTMLElement, i: number) => {\n mountedIndexes.set(el, i);\n resizeObserver._observe(el);\n return () => {\n mountedIndexes.delete(el);\n resizeObserver._unobserve(el);\n };\n },\n $dispose() {\n cleanupOnWindowResize && cleanupOnWindowResize();\n resizeObserver._dispose();\n },\n };\n};\n\n/**\n * @internal\n */\nexport const createGridResizer = (\n vStore: VirtualStore,\n hStore: VirtualStore\n) => {\n let viewportElement: HTMLElement | undefined;\n\n const heightKey = \"height\";\n const widthKey = \"width\";\n const mountedIndexes = new WeakMap<\n Element,\n [rowIndex: number, colIndex: number]\n >();\n\n type CellSize = [height: number, width: number];\n const maybeCachedRowIndexes = new Set<number>();\n const maybeCachedColIndexes = new Set<number>();\n const sizeCache = new Map<string, CellSize>();\n const getKey = (rowIndex: number, colIndex: number): string =>\n `${rowIndex}-${colIndex}`;\n\n const resizeObserver = createResizeObserver((entries) => {\n const resizedRows = new Set<number>();\n const resizedCols = new Set<number>();\n for (const { target, contentRect } of entries) {\n // Skip zero-sized rects that may be observed under `display: none` style\n if (!(target as HTMLElement).offsetParent) continue;\n\n if (target === viewportElement) {\n vStore.$update(ACTION_VIEWPORT_RESIZE, contentRect[heightKey]);\n hStore.$update(ACTION_VIEWPORT_RESIZE, contentRect[widthKey]);\n } else {\n const cell = mountedIndexes.get(target);\n if (cell) {\n const [rowIndex, colIndex] = cell;\n const key = getKey(rowIndex, colIndex);\n const prevSize = sizeCache.get(key);\n const size: CellSize = [\n contentRect[heightKey],\n contentRect[widthKey],\n ];\n let rowResized: boolean | undefined;\n let colResized: boolean | undefined;\n if (!prevSize) {\n rowResized = colResized = true;\n } else {\n if (prevSize[0] !== size[0]) {\n rowResized = true;\n }\n if (prevSize[1] !== size[1]) {\n colResized = true;\n }\n }\n if (rowResized) {\n resizedRows.add(rowIndex);\n }\n if (colResized) {\n resizedCols.add(colIndex);\n }\n if (rowResized || colResized) {\n sizeCache.set(key, size);\n }\n }\n }\n }\n\n if (resizedRows.size) {\n const heightResizes: ItemResize[] = [];\n resizedRows.forEach((rowIndex) => {\n let maxHeight = 0;\n maybeCachedColIndexes.forEach((colIndex) => {\n const size = sizeCache.get(getKey(rowIndex, colIndex));\n if (size) {\n maxHeight = max(maxHeight, size[0]);\n }\n });\n if (maxHeight) {\n heightResizes.push([rowIndex, maxHeight]);\n }\n });\n vStore.$update(ACTION_ITEM_RESIZE, heightResizes);\n }\n if (resizedCols.size) {\n const widthResizes: ItemResize[] = [];\n resizedCols.forEach((colIndex) => {\n let maxWidth = 0;\n maybeCachedRowIndexes.forEach((rowIndex) => {\n const size = sizeCache.get(getKey(rowIndex, colIndex));\n if (size) {\n maxWidth = max(maxWidth, size[1]);\n }\n });\n if (maxWidth) {\n widthResizes.push([colIndex, maxWidth]);\n }\n });\n hStore.$update(ACTION_ITEM_RESIZE, widthResizes);\n }\n });\n\n return {\n $observeRoot(viewport: HTMLElement) {\n resizeObserver._observe((viewportElement = viewport));\n },\n $observeItem(el: HTMLElement, rowIndex: number, colIndex: number) {\n mountedIndexes.set(el, [rowIndex, colIndex]);\n maybeCachedRowIndexes.add(rowIndex);\n maybeCachedColIndexes.add(colIndex);\n resizeObserver._observe(el);\n return () => {\n mountedIndexes.delete(el);\n resizeObserver._unobserve(el);\n };\n },\n $resizeCols(cols: ItemResize[]) {\n for (const [c] of cols) {\n for (let r = 0; r < vStore.$getItemsLength(); r++) {\n sizeCache.delete(getKey(r, c));\n }\n }\n hStore.$update(ACTION_ITEM_RESIZE, cols);\n },\n $resizeRows(rows: ItemResize[]) {\n for (const [r] of rows) {\n for (let c = 0; c < hStore.$getItemsLength(); c++) {\n sizeCache.delete(getKey(r, c));\n }\n }\n vStore.$update(ACTION_ITEM_RESIZE, rows);\n },\n $dispose: resizeObserver._dispose,\n };\n};\n\n/**\n * @internal\n */\nexport type GridResizer = ReturnType<typeof createGridResizer>;\n"],"names":["NULL","min","max","abs","floor","Math","clamp","value","minValue","maxValue","sort","arr","a","b","microtask","queueMicrotask","fn","Promise","resolve","then","once","cache","undefined","UNCACHED","fill","array","length","prepend","key","i","getItemSize","index","size","_sizes","_defaultItemSize","setItemSize","isInitialMeasurement","_computedOffsetIndex","computeOffset","_length","_offsets","top","findIndex","offset","low","high","mid","itemOffset","updateCacheLength","isShift","diff","splice","reduce","acc","removed","isBrowser","window","getDocumentElement","document","documentElement","getCurrentDocument","node","ownerDocument","getCurrentWindow","doc","defaultView","isRTLDocument","getComputedStyle","direction","isIOSWebKit","test","navigator","userAgent","isSmoothScrollSupported","style","isInitialMeasurementDone","store","$getViewportSize","timeout","setTimeout","normalizeOffset","isHorizontal","createScrollObserver","viewport","getScrollOffset","updateScrollOffset","getStartOffset","now","Date","lastScrollTime","wheeling","touching","justTouchEnded","stillMomentumScrolling","onScrollEnd","id","cancel","clearTimeout","debouncedFn","$update","_cancel","debounce","onScroll","onWheel","e","$isScrolling","ctrlKey","timeDelta","deltaX","deltaY","onTouchStart","onTouchEnd","addEventListener","passive","_dispose","removeEventListener","_fixScrollJump","jump","shift","_flushJump","$getTotalSize","createScroller","viewportElement","scrollObserver","cancelScroll","scrollOffsetKey","overflowKey","scheduleImperativeScroll","async","getTargetOffset","smooth","waitForMeasurement","queue","reject","$subscribe","_hasUnmeasuredItemsInFrozenRange","promise","unsubscribe","scrollTo","behavior","$observe","isMomentumScrolling","prev","$getScrollOffset","$dispose","$scrollTo","$scrollBy","$scrollToIndex","align","$getItemsLength","$getItemOffset","scrollOffset","$getItemSize","$getStartSpacerSize","$fixScrollJump","createResizeObserver","cb","ro","_observe","observe","_unobserve","unobserve","disconnect","vStore","hStore","heightKey","widthKey","mountedIndexes","WeakMap","maybeCachedRowIndexes","Set","maybeCachedColIndexes","sizeCache","Map","getKey","rowIndex","colIndex","resizeObserver","entries","resizedRows","resizedCols","target","contentRect","offsetParent","cell","get","prevSize","rowResized","colResized","add","set","heightResizes","forEach","maxHeight","push","widthResizes","maxWidth","$observeRoot","$observeItem","el","delete","$resizeCols","cols","c","r","$resizeRows","rows","vScroller","hScroller","offsetX","offsetY","indexX","indexY","sizeKey","resizes","elementsCount","itemSize","overscan","ssrCount","cacheSnapshot","shouldAutoEstimateItemSize","isSSR","stateVersion","viewportSize","startSpacerSize","pendingJump","_flushedJump","_scrollDirection","_scrollMode","_frozenRange","_prevRange","_totalMeasuredSize","snapshot","slice","initCache","subscribers","getRelativeScrollOffset","getVisibleOffset","getRange","prevStartIndex","end","start","computeRange","getTotalSize","computeTotalSize","getItemOffset","computeStartOffset","_getItemSize","applyJump","j","$getStateVersion","$getCacheSnapshot","takeCacheSnapshot","$getRange","startIndex","endIndex","$findStartIndex","$findEndIndex","$isUnmeasuredItem","includes","sub","type","payload","shouldFlushPendingJump","shouldSync","mutated","flushedJump","delta","distance","relativeOffset","updated","filter","measuredCountBeforeStart","measuredSizes","s","sorted","len","median","prevDefaultItemSize","estimateDefaultItemSize","UPDATE_VIRTUAL_STATE","windowSizeKey","cleanupOnWindowResize","container","onWindowResize","containerElement","calcOffsetToViewport","offsetKey","offsetSum","innerWidth","offsetWidth","parent","scroll","documentBody","body","scrollBy","html","getScrollbarSize","clientWidth","clientHeight"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/src/core/utils.ts","../../src/src/core/cache.ts","../../src/src/core/environment.ts","../../src/src/core/store.ts","../../src/src/core/scroller.ts","../../src/src/core/resizer.ts"],"sourcesContent":["/** @internal */\nexport const NULL = null;\n\n/** @internal */\nexport const { min, max, abs, floor } = Math;\n\n/**\n * @internal\n */\nexport const clamp = (\n value: number,\n minValue: number,\n maxValue: number\n): number => min(maxValue, max(minValue, value));\n\n/**\n * @internal\n */\nexport const sort = <T extends number>(arr: readonly T[]): T[] => {\n return [...arr].sort((a, b) => a - b);\n};\n\n/**\n * @internal\n */\nexport const microtask: (fn: () => void) => void =\n typeof queueMicrotask === \"function\"\n ? queueMicrotask\n : (fn) => {\n Promise.resolve().then(fn);\n };\n\n/**\n * @internal\n */\nexport const createPromise = (): [Promise<void>, () => void, () => void] => {\n let resolve: (() => void) | undefined;\n let reject: (() => void) | undefined;\n const promise = new Promise<void>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n return [promise, resolve!, reject!];\n};\n\n/**\n * @internal\n */\nexport const once = <T>(fn: () => T): (() => T) => {\n let cache: T;\n\n return () => {\n if (fn) {\n cache = fn();\n fn = undefined!;\n }\n return cache;\n };\n};\n","import { type InternalCacheSnapshot, type ItemsRange } from \"./types\";\nimport { clamp, floor, max, min, sort } from \"./utils\";\n\ntype Writeable<T> = {\n -readonly [key in keyof T]: Writeable<T[key]>;\n};\n\n/** @internal */\nexport const UNCACHED = -1;\n\n/**\n * @internal\n */\nexport type Cache = {\n readonly _length: number;\n // sizes\n readonly _sizes: number[];\n readonly _defaultItemSize: number;\n // offsets\n readonly _computedOffsetIndex: number;\n readonly _offsets: number[];\n};\n\nconst fill = (array: number[], length: number, prepend?: boolean): number[] => {\n const key = prepend ? \"unshift\" : \"push\";\n for (let i = 0; i < length; i++) {\n array[key](UNCACHED);\n }\n return array;\n};\n\n/**\n * @internal\n */\nexport const getItemSize = (cache: Cache, index: number): number => {\n const size = cache._sizes[index]!;\n return size === UNCACHED ? cache._defaultItemSize : size;\n};\n\n/**\n * @internal\n */\nexport const setItemSize = (\n cache: Writeable<Cache>,\n index: number,\n size: number\n): boolean => {\n const isInitialMeasurement = cache._sizes[index] === UNCACHED;\n cache._sizes[index] = size;\n // mark as dirty\n cache._computedOffsetIndex = min(index, cache._computedOffsetIndex);\n return isInitialMeasurement;\n};\n\n/**\n * @internal\n */\nexport const computeOffset = (\n cache: Writeable<Cache>,\n index: number\n): number => {\n if (!cache._length) return 0;\n if (cache._computedOffsetIndex >= index) {\n return cache._offsets[index]!;\n }\n\n if (cache._computedOffsetIndex < 0) {\n // first offset must be 0 to avoid returning NaN, which can cause infinite rerender.\n // https://github.com/inokawa/virtua/pull/160\n cache._offsets[0] = 0;\n cache._computedOffsetIndex = 0;\n }\n let i = cache._computedOffsetIndex;\n let top = cache._offsets[i]!;\n while (i < index) {\n top += getItemSize(cache, i);\n cache._offsets[++i] = top;\n }\n // mark as measured\n cache._computedOffsetIndex = index;\n return top;\n};\n\n/**\n * @internal\n */\nexport const computeTotalSize = (cache: Cache): number => {\n if (!cache._length) return 0;\n return (\n computeOffset(cache, cache._length - 1) +\n getItemSize(cache, cache._length - 1)\n );\n};\n\n/**\n * Finds the index of an item in the cache whose computed offset is closest to the specified offset.\n *\n * @internal\n */\nexport const findIndex = (\n cache: Cache,\n offset: number,\n low: number = 0,\n high: number = cache._length - 1\n): number => {\n // Find with binary search\n while (low <= high) {\n const mid = floor((low + high) / 2);\n const itemOffset = computeOffset(cache, mid);\n if (itemOffset <= offset) {\n if (itemOffset + getItemSize(cache, mid) > offset) {\n return mid;\n }\n low = mid + 1;\n } else {\n high = mid - 1;\n }\n }\n return clamp(low, 0, cache._length - 1);\n};\n\n/**\n * @internal\n */\nexport const computeRange = (\n cache: Cache,\n scrollOffset: number,\n viewportSize: number,\n prevStartIndex: number\n): ItemsRange => {\n // Clamp because prevStartIndex may exceed the limit when children decreased a lot after scrolling\n prevStartIndex = min(prevStartIndex, cache._length - 1);\n\n if (computeOffset(cache, prevStartIndex) <= scrollOffset) {\n // search forward\n // start <= end, prevStartIndex <= start\n const end = findIndex(cache, scrollOffset + viewportSize, prevStartIndex);\n return [findIndex(cache, scrollOffset, prevStartIndex, end), end];\n } else {\n // search backward\n // start <= end, start <= prevStartIndex\n const start = findIndex(cache, scrollOffset, undefined, prevStartIndex);\n return [start, findIndex(cache, scrollOffset + viewportSize, start)];\n }\n};\n\n/**\n * @internal\n */\nexport const estimateDefaultItemSize = (\n cache: Writeable<Cache>,\n startIndex: number\n): number => {\n let measuredCountBeforeStart = 0;\n // This function will be called after measurement so measured size array must be longer than 0\n const measuredSizes: number[] = [];\n cache._sizes.forEach((s, i) => {\n if (s !== UNCACHED) {\n measuredSizes.push(s);\n if (i < startIndex) {\n measuredCountBeforeStart++;\n }\n }\n });\n\n // Discard cache for now\n cache._computedOffsetIndex = -1;\n\n // Calculate median\n const sorted = sort(measuredSizes);\n const len = sorted.length;\n const mid = (len / 2) | 0;\n const median =\n len % 2 === 0 ? (sorted[mid - 1]! + sorted[mid]!) / 2 : sorted[mid]!;\n\n const prevDefaultItemSize = cache._defaultItemSize;\n\n // Calculate diff of unmeasured items before start\n return (\n ((cache._defaultItemSize = median) - prevDefaultItemSize) *\n max(startIndex - measuredCountBeforeStart, 0)\n );\n};\n\n/**\n * @internal\n */\nexport const initCache = (\n length: number,\n itemSize: number,\n snapshot?: InternalCacheSnapshot\n): Cache => {\n return {\n _defaultItemSize: snapshot ? snapshot[1] : itemSize,\n _sizes:\n snapshot && snapshot[0]\n ? // https://github.com/inokawa/virtua/issues/441\n fill(\n snapshot[0].slice(0, min(length, snapshot[0].length)),\n max(0, length - snapshot[0].length)\n )\n : fill([], length),\n _length: length,\n _computedOffsetIndex: -1,\n _offsets: fill([], length),\n };\n};\n\n/**\n * @internal\n */\nexport const takeCacheSnapshot = (cache: Cache): InternalCacheSnapshot => {\n return [cache._sizes.slice(), cache._defaultItemSize];\n};\n\n/**\n * @internal\n */\nexport const updateCacheLength = (\n cache: Writeable<Cache>,\n length: number,\n isShift?: boolean\n): number => {\n const diff = length - cache._length;\n\n cache._computedOffsetIndex = isShift\n ? // Discard cache for now\n -1\n : min(length - 1, cache._computedOffsetIndex);\n cache._length = length;\n\n if (diff > 0) {\n // Added\n fill(cache._offsets, diff);\n fill(cache._sizes, diff, isShift);\n return cache._defaultItemSize * diff;\n } else {\n // Removed\n cache._offsets.splice(diff);\n return (\n isShift ? cache._sizes.splice(0, -diff) : cache._sizes.splice(diff)\n ).reduce(\n (acc, removed) =>\n acc - (removed === UNCACHED ? cache._defaultItemSize : removed),\n 0\n );\n }\n};\n","import { once } from \"./utils\";\n\n/**\n * @internal\n */\nexport const isBrowser = typeof window !== \"undefined\";\n\nconst getDocumentElement = () => document.documentElement;\n\n/**\n * @internal\n */\nexport const getCurrentDocument = (node: HTMLElement): Document =>\n node.ownerDocument;\n\n/**\n * @internal\n */\nexport const getCurrentWindow = (doc: Document) => doc.defaultView!;\n\n/**\n * @internal\n */\nexport const isRTLDocument = /*#__PURE__*/ once((): boolean => {\n // TODO support SSR in rtl\n return isBrowser\n ? getComputedStyle(getDocumentElement()).direction === \"rtl\"\n : false;\n});\n\n/**\n * Currently, all browsers on iOS/iPadOS are WebKit, including WebView.\n * @internal\n */\nexport const isIOSWebKit = /*#__PURE__*/ once((): boolean => {\n return /iP(hone|od|ad)/.test(navigator.userAgent);\n});\n\n/**\n * @internal\n */\nexport const isSmoothScrollSupported = /*#__PURE__*/ once((): boolean => {\n return \"scrollBehavior\" in getDocumentElement().style;\n});\n","import {\n initCache,\n getItemSize as _getItemSize,\n computeTotalSize,\n computeOffset as computeStartOffset,\n UNCACHED,\n setItemSize,\n estimateDefaultItemSize,\n updateCacheLength,\n computeRange,\n takeCacheSnapshot,\n findIndex,\n} from \"./cache\";\nimport { isIOSWebKit } from \"./environment\";\nimport type {\n CacheSnapshot,\n InternalCacheSnapshot,\n ItemResize,\n ItemsRange,\n} from \"./types\";\nimport { abs, max, min, NULL } from \"./utils\";\n\nconst MAX_INT_32 = 0x7fffffff;\n\nconst SCROLL_IDLE = 0;\nconst SCROLL_DOWN = 1;\nconst SCROLL_UP = 2;\ntype ScrollDirection =\n | typeof SCROLL_IDLE\n | typeof SCROLL_DOWN\n | typeof SCROLL_UP;\n\nconst SCROLL_BY_NATIVE = 0;\nconst SCROLL_BY_MANUAL_SCROLL = 1;\nconst SCROLL_BY_SHIFT = 2;\ntype ScrollMode =\n | typeof SCROLL_BY_NATIVE\n | typeof SCROLL_BY_MANUAL_SCROLL\n | typeof SCROLL_BY_SHIFT;\n\n/** @internal */\nexport const ACTION_SCROLL = 1;\n/** @internal */\nexport const ACTION_SCROLL_END = 2;\n/** @internal */\nexport const ACTION_ITEM_RESIZE = 3;\n/** @internal */\nexport const ACTION_VIEWPORT_RESIZE = 4;\n/** @internal */\nexport const ACTION_ITEMS_LENGTH_CHANGE = 5;\n/** @internal */\nexport const ACTION_START_OFFSET_CHANGE = 6;\n/** @internal */\nexport const ACTION_MANUAL_SCROLL = 7;\n/** @internal */\nexport const ACTION_BEFORE_MANUAL_SMOOTH_SCROLL = 8;\n\ntype Actions =\n | [type: typeof ACTION_SCROLL, offset: number]\n | [type: typeof ACTION_SCROLL_END, dummy?: void]\n | [type: typeof ACTION_ITEM_RESIZE, entries: ItemResize[]]\n | [type: typeof ACTION_VIEWPORT_RESIZE, size: number]\n | [\n type: typeof ACTION_ITEMS_LENGTH_CHANGE,\n arg: [length: number, isShift?: boolean | undefined],\n ]\n | [type: typeof ACTION_START_OFFSET_CHANGE, offset: number]\n | [type: typeof ACTION_MANUAL_SCROLL, dummy?: void]\n | [type: typeof ACTION_BEFORE_MANUAL_SMOOTH_SCROLL, offset: number];\n\n/** @internal */\nexport const UPDATE_VIRTUAL_STATE = 0b0001;\n/** @internal */\nexport const UPDATE_SIZE_EVENT = 0b0010;\n/** @internal */\nexport const UPDATE_SCROLL_EVENT = 0b0100;\n/** @internal */\nexport const UPDATE_SCROLL_END_EVENT = 0b1000;\n\n/**\n * @internal\n */\nexport const getScrollSize = (store: VirtualStore): number => {\n return max(store.$getTotalSize(), store.$getViewportSize());\n};\n\n/**\n * @internal\n */\nexport const isInitialMeasurementDone = (store: VirtualStore): boolean => {\n return !!store.$getViewportSize();\n};\n\ntype Subscriber = (sync?: boolean) => void;\n\n/** @internal */\nexport type StateVersion =\n number & {} /* hack for typescript to pretend as not falsy */;\n\n/**\n * @internal\n */\nexport type VirtualStore = {\n $getStateVersion(): StateVersion;\n $getCacheSnapshot(): CacheSnapshot;\n $getRange(): ItemsRange;\n $findStartIndex(): number;\n $findEndIndex(): number;\n $isUnmeasuredItem(index: number): boolean;\n $getItemOffset(index: number): number;\n $getItemSize(index: number): number;\n $getItemsLength(): number;\n $getScrollOffset(): number;\n $isScrolling(): boolean;\n $getViewportSize(): number;\n $getStartSpacerSize(): number;\n $getTotalSize(): number;\n _flushJump(): [number, boolean];\n $subscribe(target: number, cb: Subscriber): () => void;\n $update(...action: Actions): void;\n _hasUnmeasuredItemsInFrozenRange(): boolean;\n};\n\n/**\n * @internal\n */\nexport const createVirtualStore = (\n elementsCount: number,\n itemSize: number = 40,\n overscan: number = 4,\n ssrCount: number = 0,\n cacheSnapshot?: CacheSnapshot | undefined,\n shouldAutoEstimateItemSize: boolean = false\n): VirtualStore => {\n let isSSR = !!ssrCount;\n let stateVersion: StateVersion = 1;\n let viewportSize = 0;\n let startSpacerSize = 0;\n let scrollOffset = 0;\n let jump = 0;\n let pendingJump = 0;\n let _flushedJump = 0;\n let _scrollDirection: ScrollDirection = SCROLL_IDLE;\n let _scrollMode: ScrollMode = SCROLL_BY_NATIVE;\n let _frozenRange: ItemsRange | null = isSSR\n ? [0, max(ssrCount - 1, 0)]\n : NULL;\n let _prevRange: ItemsRange = [0, 0];\n let _totalMeasuredSize = 0;\n\n const cache = initCache(\n elementsCount,\n itemSize,\n cacheSnapshot as unknown as InternalCacheSnapshot | undefined\n );\n const subscribers = new Set<[number, Subscriber]>();\n const getRelativeScrollOffset = () => scrollOffset - startSpacerSize;\n const getVisibleOffset = () => getRelativeScrollOffset() + pendingJump + jump;\n const getRange = (offset: number) => {\n return computeRange(cache, offset, viewportSize, _prevRange[0]);\n };\n const getTotalSize = (): number => computeTotalSize(cache);\n const getItemOffset = (index: number): number => {\n return computeStartOffset(cache, index) - pendingJump;\n };\n const getItemSize = (index: number): number => {\n return _getItemSize(cache, index);\n };\n\n const applyJump = (j: number) => {\n if (j) {\n // In iOS WebKit browsers, updating scroll position will stop scrolling so it have to be deferred during scrolling.\n if (isIOSWebKit() && _scrollDirection !== SCROLL_IDLE) {\n pendingJump += j;\n } else {\n jump += j;\n }\n }\n };\n\n return {\n $getStateVersion: () => stateVersion,\n $getCacheSnapshot: () => {\n return takeCacheSnapshot(cache) as unknown as CacheSnapshot;\n },\n $getRange: () => {\n let startIndex: number;\n let endIndex: number;\n if (_flushedJump) {\n // Return previous range for consistent render until next scroll event comes in.\n // And it must be clamped. https://github.com/inokawa/virtua/issues/597\n [startIndex, endIndex] = _prevRange;\n } else {\n [startIndex, endIndex] = _prevRange = getRange(\n max(0, getVisibleOffset())\n );\n if (_frozenRange) {\n startIndex = min(startIndex, _frozenRange[0]);\n endIndex = max(endIndex, _frozenRange[1]);\n }\n }\n\n if (_scrollDirection !== SCROLL_DOWN) {\n startIndex -= max(0, overscan);\n }\n if (_scrollDirection !== SCROLL_UP) {\n endIndex += max(0, overscan);\n }\n return [max(startIndex, 0), min(endIndex, cache._length - 1)];\n },\n $findStartIndex: () => findIndex(cache, getVisibleOffset()),\n $findEndIndex: () => findIndex(cache, getVisibleOffset() + viewportSize),\n $isUnmeasuredItem: (index) => cache._sizes[index] === UNCACHED,\n _hasUnmeasuredItemsInFrozenRange: () => {\n if (!_frozenRange) return false;\n return cache._sizes\n .slice(\n max(0, _frozenRange[0] - 1),\n min(cache._length - 1, _frozenRange[1] + 1) + 1\n )\n .includes(UNCACHED);\n },\n $getItemOffset: getItemOffset,\n $getItemSize: getItemSize,\n $getItemsLength: () => cache._length,\n $getScrollOffset: () => scrollOffset,\n $isScrolling: () => _scrollDirection !== SCROLL_IDLE,\n $getViewportSize: () => viewportSize,\n $getStartSpacerSize: () => startSpacerSize,\n $getTotalSize: getTotalSize,\n _flushJump: () => {\n _flushedJump = jump;\n jump = 0;\n return [\n _flushedJump,\n // Use absolute position not to exceed scrollable bounds\n _scrollMode === SCROLL_BY_SHIFT ||\n // https://github.com/inokawa/virtua/discussions/475\n getRelativeScrollOffset() + viewportSize >= getTotalSize(),\n ];\n },\n $subscribe: (target, cb) => {\n const sub: [number, Subscriber] = [target, cb];\n subscribers.add(sub);\n return () => {\n subscribers.delete(sub);\n };\n },\n $update: (type, payload): void => {\n let shouldFlushPendingJump: boolean | undefined;\n let shouldSync: boolean | undefined;\n let mutated = 0;\n\n switch (type) {\n case ACTION_SCROLL: {\n const flushedJump = _flushedJump;\n _flushedJump = 0;\n\n const delta = payload - scrollOffset;\n const distance = abs(delta);\n\n // Scroll event after jump compensation is not reliable because it may result in the opposite direction.\n // The delta of artificial scroll may not be equal with the jump because it may be batched with other scrolls.\n // And at least in latest Chrome/Firefox/Safari in 2023, setting value to scrollTop/scrollLeft can lose subpixel because its integer (sometimes float probably depending on dpr).\n const isJustJumped = flushedJump && distance < abs(flushedJump) + 1;\n\n // Scroll events are dispatched enough so it's ok to skip some of them.\n if (\n !isJustJumped &&\n // Ignore until manual scrolling\n _scrollMode === SCROLL_BY_NATIVE\n ) {\n _scrollDirection = delta < 0 ? SCROLL_UP : SCROLL_DOWN;\n }\n\n // TODO This will cause glitch in reverse infinite scrolling. Disable this until better solution is found.\n // if (\n // pendingJump &&\n // ((_scrollDirection === SCROLL_UP &&\n // payload - max(pendingJump, 0) <= 0) ||\n // (_scrollDirection === SCROLL_DOWN &&\n // payload - min(pendingJump, 0) >= getScrollOffsetMax()))\n // ) {\n // // Flush if almost reached to start or end\n // shouldFlushPendingJump = true;\n // }\n\n if (isSSR) {\n _frozenRange = NULL;\n isSSR = false;\n }\n\n scrollOffset = payload;\n mutated = UPDATE_SCROLL_EVENT;\n\n // Skip if offset is not changed\n // Scroll offset may exceed min or max especially in Safari's elastic scrolling.\n const relativeOffset = getRelativeScrollOffset();\n if (\n relativeOffset >= -viewportSize &&\n relativeOffset <= getTotalSize()\n ) {\n mutated += UPDATE_VIRTUAL_STATE;\n\n // Update synchronously if scrolled a lot\n shouldSync = distance > viewportSize;\n }\n break;\n }\n case ACTION_SCROLL_END: {\n mutated = UPDATE_SCROLL_END_EVENT;\n if (_scrollDirection !== SCROLL_IDLE) {\n shouldFlushPendingJump = true;\n mutated += UPDATE_VIRTUAL_STATE;\n }\n _scrollDirection = SCROLL_IDLE;\n _scrollMode = SCROLL_BY_NATIVE;\n _frozenRange = NULL;\n break;\n }\n case ACTION_ITEM_RESIZE: {\n const updated = payload.filter(\n ([index, size]) => cache._sizes[index] !== size\n );\n\n // Skip if all items are cached and not updated\n if (!updated.length) {\n break;\n }\n\n // Calculate jump by resize to minimize junks in appearance\n applyJump(\n updated.reduce((acc, [index, size]) => {\n if (\n // Keep distance from end during shifting\n _scrollMode === SCROLL_BY_SHIFT ||\n (_frozenRange\n ? // https://github.com/inokawa/virtua/issues/380\n // https://github.com/inokawa/virtua/issues/590\n !isSSR && index < _frozenRange[0]\n : // Otherwise we should maintain visible position\n getItemOffset(index) +\n // https://github.com/inokawa/virtua/issues/385\n (_scrollDirection === SCROLL_IDLE &&\n _scrollMode === SCROLL_BY_NATIVE\n ? getItemSize(index)\n : 0) <\n getRelativeScrollOffset())\n ) {\n acc += size - getItemSize(index);\n }\n return acc;\n }, 0)\n );\n\n // Update item sizes\n for (const [index, size] of updated) {\n const prevSize = getItemSize(index);\n const isInitialMeasurement = setItemSize(cache, index, size);\n\n if (shouldAutoEstimateItemSize) {\n _totalMeasuredSize += isInitialMeasurement\n ? size\n : size - prevSize;\n }\n }\n\n // Estimate initial item size from measured sizes\n if (\n shouldAutoEstimateItemSize &&\n viewportSize &&\n // If the total size is lower than the viewport, the item may be a empty state\n _totalMeasuredSize > viewportSize\n ) {\n applyJump(\n estimateDefaultItemSize(\n cache,\n findIndex(cache, getVisibleOffset())\n )\n );\n shouldAutoEstimateItemSize = false;\n }\n\n mutated = UPDATE_VIRTUAL_STATE + UPDATE_SIZE_EVENT;\n\n // Synchronous update is necessary in current design to minimize visible glitch in concurrent rendering.\n // However this seems to be the main cause of the errors from ResizeObserver.\n // https://github.com/inokawa/virtua/issues/470\n //\n // And in React, synchronous update with flushSync after asynchronous update will overtake the asynchronous one.\n // If items resize happens just after scroll, race condition can occur depending on implementation.\n shouldSync = true;\n break;\n }\n case ACTION_VIEWPORT_RESIZE: {\n if (viewportSize !== payload) {\n viewportSize = payload;\n mutated = UPDATE_VIRTUAL_STATE + UPDATE_SIZE_EVENT;\n }\n break;\n }\n case ACTION_ITEMS_LENGTH_CHANGE: {\n if (payload[1]) {\n applyJump(updateCacheLength(cache, payload[0], true));\n _scrollMode = SCROLL_BY_SHIFT;\n mutated = UPDATE_VIRTUAL_STATE;\n } else {\n updateCacheLength(cache, payload[0]);\n // https://github.com/inokawa/virtua/issues/552\n // https://github.com/inokawa/virtua/issues/557\n mutated = UPDATE_VIRTUAL_STATE;\n }\n break;\n }\n case ACTION_START_OFFSET_CHANGE: {\n startSpacerSize = payload;\n break;\n }\n case ACTION_MANUAL_SCROLL: {\n _scrollMode = SCROLL_BY_MANUAL_SCROLL;\n break;\n }\n case ACTION_BEFORE_MANUAL_SMOOTH_SCROLL: {\n _frozenRange = getRange(payload);\n mutated = UPDATE_VIRTUAL_STATE;\n break;\n }\n }\n\n if (mutated) {\n stateVersion = (stateVersion & MAX_INT_32) + 1;\n\n if (shouldFlushPendingJump && pendingJump) {\n jump += pendingJump;\n pendingJump = 0;\n }\n\n subscribers.forEach(([target, cb]) => {\n // Early return to skip React's computation\n if (!(mutated & target)) {\n return;\n }\n // https://github.com/facebook/react/issues/25191\n // https://github.com/facebook/react/blob/a5fc797db14c6e05d4d5c4dbb22a0dd70d41f5d5/packages/react-reconciler/src/ReactFiberWorkLoop.js#L1443-L1447\n cb(shouldSync);\n });\n }\n },\n };\n};\n","import {\n getCurrentDocument,\n getCurrentWindow,\n isIOSWebKit,\n isRTLDocument,\n isSmoothScrollSupported,\n} from \"./environment\";\nimport {\n ACTION_SCROLL,\n type VirtualStore,\n ACTION_SCROLL_END,\n UPDATE_SIZE_EVENT,\n ACTION_MANUAL_SCROLL,\n ACTION_BEFORE_MANUAL_SMOOTH_SCROLL,\n ACTION_START_OFFSET_CHANGE,\n isInitialMeasurementDone,\n} from \"./store\";\nimport { type ScrollToIndexOpts } from \"./types\";\nimport { clamp, createPromise, NULL } from \"./utils\";\n\nconst timeout = setTimeout;\n\nconst debounce = <T extends () => void>(fn: T, ms: number) => {\n let id: ReturnType<typeof setTimeout> | undefined | null;\n\n const cancel = () => {\n if (id != NULL) {\n clearTimeout(id);\n }\n };\n const debouncedFn = () => {\n cancel();\n id = timeout(() => {\n id = NULL;\n fn();\n }, ms);\n };\n debouncedFn._cancel = cancel;\n return debouncedFn;\n};\n\n/**\n * scrollLeft is negative value in rtl direction.\n *\n * left right\n * 0 100 spec compliant (ltr)\n * -100 0 spec compliant (rtl)\n * https://github.com/othree/jquery.rtl-scroll-type\n */\nconst normalizeOffset = (offset: number, isHorizontal: boolean): number => {\n if (isHorizontal && isRTLDocument()) {\n return -offset;\n } else {\n return offset;\n }\n};\n\nconst createScrollObserver = (\n store: VirtualStore,\n viewport: HTMLElement | Window,\n isHorizontal: boolean,\n getScrollOffset: () => number,\n updateScrollOffset: (\n value: number,\n shift: boolean,\n isMomentumScrolling: boolean\n ) => void,\n getStartOffset?: () => number\n) => {\n const now = Date.now;\n\n let lastScrollTime = 0;\n let wheeling = false;\n let touching = false;\n let justTouchEnded = false;\n let stillMomentumScrolling = false;\n\n const onScrollEnd = debounce(() => {\n if (wheeling || touching) {\n wheeling = false;\n\n // Wait while wheeling or touching\n onScrollEnd();\n return;\n }\n\n justTouchEnded = false;\n\n store.$update(ACTION_SCROLL_END);\n }, 150);\n\n const onScroll = () => {\n lastScrollTime = now();\n\n if (justTouchEnded) {\n stillMomentumScrolling = true;\n }\n\n if (getStartOffset) {\n store.$update(ACTION_START_OFFSET_CHANGE, getStartOffset());\n }\n store.$update(ACTION_SCROLL, getScrollOffset());\n\n onScrollEnd();\n };\n\n // Infer scroll state also from wheel events\n // Sometimes scroll events do not fire when frame dropped even if the visual have been already scrolled\n const onWheel = ((e: WheelEvent) => {\n if (\n wheeling ||\n // Scroll start should be detected with scroll event\n !store.$isScrolling() ||\n // Probably a pinch-to-zoom gesture\n e.ctrlKey\n ) {\n return;\n }\n\n const timeDelta = now() - lastScrollTime;\n if (\n // Check if wheel event occurs some time after scrolling\n 150 > timeDelta &&\n 50 < timeDelta &&\n // Get delta before checking deltaMode for firefox behavior\n // https://github.com/w3c/uievents/issues/181#issuecomment-392648065\n // https://bugzilla.mozilla.org/show_bug.cgi?id=1392460#c34\n (isHorizontal ? e.deltaX : e.deltaY)\n ) {\n wheeling = true;\n }\n }) as (e: Event) => void; // FIXME type error. why only here?\n\n const onTouchStart = () => {\n touching = true;\n justTouchEnded = stillMomentumScrolling = false;\n };\n const onTouchEnd = () => {\n touching = false;\n if (isIOSWebKit()) {\n justTouchEnded = true;\n }\n };\n\n viewport.addEventListener(\"scroll\", onScroll);\n viewport.addEventListener(\"wheel\", onWheel, { passive: true });\n viewport.addEventListener(\"touchstart\", onTouchStart, { passive: true });\n viewport.addEventListener(\"touchend\", onTouchEnd, { passive: true });\n\n return {\n _dispose: () => {\n viewport.removeEventListener(\"scroll\", onScroll);\n viewport.removeEventListener(\"wheel\", onWheel);\n viewport.removeEventListener(\"touchstart\", onTouchStart);\n viewport.removeEventListener(\"touchend\", onTouchEnd);\n onScrollEnd._cancel();\n },\n _fixScrollJump: () => {\n const [jump, shift] = store._flushJump();\n if (!jump) return;\n updateScrollOffset(\n normalizeOffset(jump, isHorizontal),\n shift,\n stillMomentumScrolling\n );\n stillMomentumScrolling = false;\n\n if (shift && store.$getViewportSize() > store.$getTotalSize()) {\n // In this case applying jump may not cause scroll.\n // Current logic expects scroll event occurs after applying jump so we dispatch it manually.\n store.$update(ACTION_SCROLL, getScrollOffset());\n }\n },\n };\n};\n\ntype ScrollObserver = ReturnType<typeof createScrollObserver>;\n\n/**\n * @internal\n */\nexport type Scroller = {\n $observe: (viewportElement: HTMLElement) => void;\n $dispose(): void;\n $scrollTo: (offset: number) => void;\n $scrollBy: (offset: number) => void;\n $scrollToIndex: (index: number, opts?: ScrollToIndexOpts) => void;\n $fixScrollJump: () => void;\n};\n\n/**\n * @internal\n */\nexport const createScroller = (\n store: VirtualStore,\n isHorizontal: boolean\n): Scroller => {\n let viewportElement: HTMLElement | undefined;\n let scrollObserver: ScrollObserver | undefined;\n let cancelScroll: (() => void) | undefined;\n const [initialized, resolveInitialized, rejectInitialized] = createPromise();\n const scrollOffsetKey = isHorizontal ? \"scrollLeft\" : \"scrollTop\";\n const overflowKey = isHorizontal ? \"overflowX\" : \"overflowY\";\n\n // The given offset will be clamped by browser\n // https://drafts.csswg.org/cssom-view/#dom-element-scrolltop\n const scheduleImperativeScroll = async (\n getTargetOffset: () => number,\n smooth?: boolean\n ) => {\n // Wait for element assign. The element may be undefined if scrollRef prop is used and scroll is scheduled on mount.\n // https://github.com/inokawa/virtua/pull/733\n await initialized;\n\n if (cancelScroll) {\n // Cancel waiting scrollTo\n cancelScroll();\n }\n\n const waitForMeasurement = (): [Promise<void>, () => void] => {\n // Wait for the scroll destination items to be measured.\n // The measurement will be done asynchronously and the timing is not predictable so we use promise.\n const [promise, resolve, reject] = createPromise();\n cancelScroll = reject;\n\n // Resize event may not happen when the window/tab is not visible, or during browser back in Safari.\n // We have to wait for the initial measurement to avoid failing imperative scroll on mount.\n // https://github.com/inokawa/virtua/issues/450\n if (isInitialMeasurementDone(store)) {\n // Reject when items around scroll destination completely measured\n timeout(reject, 150);\n }\n return [\n promise,\n store.$subscribe(UPDATE_SIZE_EVENT, () => {\n resolve();\n }),\n ];\n };\n\n if (smooth && isSmoothScrollSupported()) {\n while (true) {\n store.$update(ACTION_BEFORE_MANUAL_SMOOTH_SCROLL, getTargetOffset());\n\n if (!store._hasUnmeasuredItemsInFrozenRange()) {\n break;\n }\n\n const [promise, unsubscribe] = waitForMeasurement();\n\n try {\n await promise;\n } catch (e) {\n // canceled\n return;\n } finally {\n unsubscribe();\n }\n }\n\n viewportElement!.scrollTo({\n [isHorizontal ? \"left\" : \"top\"]: normalizeOffset(\n getTargetOffset(),\n isHorizontal\n ),\n behavior: \"smooth\",\n });\n } else {\n while (true) {\n const [promise, unsubscribe] = waitForMeasurement();\n\n try {\n viewportElement![scrollOffsetKey] = normalizeOffset(\n getTargetOffset(),\n isHorizontal\n );\n store.$update(ACTION_MANUAL_SCROLL);\n\n await promise;\n } catch (e) {\n // canceled or finished\n return;\n } finally {\n unsubscribe();\n }\n }\n }\n };\n\n return {\n $observe(viewport) {\n viewportElement = viewport;\n\n scrollObserver = createScrollObserver(\n store,\n viewport,\n isHorizontal,\n () => normalizeOffset(viewport[scrollOffsetKey], isHorizontal),\n (jump, shift, isMomentumScrolling) => {\n // If we update scroll position while touching on iOS, the position will be reverted.\n // However iOS WebKit fires touch events only once at the beginning of momentum scrolling.\n // That means we have no reliable way to confirm still touched or not if user touches more than once during momentum scrolling...\n // This is a hack for the suspectable situations, inspired by https://github.com/prud/ios-overflow-scroll-to-top\n if (isMomentumScrolling) {\n const style = viewport.style;\n const prev = style[overflowKey];\n style[overflowKey] = \"hidden\";\n timeout(() => {\n style[overflowKey] = prev;\n });\n }\n\n if (shift) {\n viewport[scrollOffsetKey] = store.$getScrollOffset() + jump;\n // https://github.com/inokawa/virtua/issues/357\n cancelScroll && cancelScroll();\n } else {\n viewport[scrollOffsetKey] += jump;\n }\n }\n );\n\n resolveInitialized();\n },\n $dispose() {\n scrollObserver && scrollObserver._dispose();\n rejectInitialized();\n },\n $scrollTo(offset) {\n scheduleImperativeScroll(() => offset);\n },\n $scrollBy(offset) {\n offset += store.$getScrollOffset();\n scheduleImperativeScroll(() => offset);\n },\n $scrollToIndex(index, { align, smooth, offset = 0 } = {}) {\n index = clamp(index, 0, store.$getItemsLength() - 1);\n\n if (align === \"nearest\") {\n const itemOffset = store.$getItemOffset(index);\n const scrollOffset = store.$getScrollOffset();\n\n if (itemOffset < scrollOffset) {\n align = \"start\";\n } else if (\n itemOffset + store.$getItemSize(index) >\n scrollOffset + store.$getViewportSize()\n ) {\n align = \"end\";\n } else {\n // already completely visible\n return;\n }\n }\n\n scheduleImperativeScroll(() => {\n return (\n offset +\n store.$getStartSpacerSize() +\n store.$getItemOffset(index) +\n (align === \"end\"\n ? store.$getItemSize(index) - store.$getViewportSize()\n : align === \"center\"\n ? (store.$getItemSize(index) - store.$getViewportSize()) / 2\n : 0)\n );\n }, smooth);\n },\n $fixScrollJump: () => {\n scrollObserver && scrollObserver._fixScrollJump();\n },\n };\n};\n\n/**\n * @internal\n */\nexport type WindowScroller = {\n $observe(containerElement: HTMLElement): void;\n $dispose(): void;\n $scrollToIndex: (index: number, opts?: ScrollToIndexOpts) => void;\n $fixScrollJump: () => void;\n};\n\n/**\n * @internal\n */\nexport const createWindowScroller = (\n store: VirtualStore,\n isHorizontal: boolean\n): WindowScroller => {\n let containerElement: HTMLElement | undefined;\n let scrollObserver: ScrollObserver | undefined;\n let cancelScroll: (() => void) | undefined;\n const [initialized, resolveInitialized, rejectInitialized] = createPromise();\n\n const calcOffsetToViewport = (\n node: HTMLElement,\n viewport: HTMLElement,\n window: Window,\n isHorizontal: boolean,\n offset: number = 0\n ): number => {\n // TODO calc offset only when it changes (maybe impossible)\n const offsetKey = isHorizontal ? \"offsetLeft\" : \"offsetTop\";\n const offsetSum =\n offset +\n (isHorizontal && isRTLDocument()\n ? window.innerWidth - node[offsetKey] - node.offsetWidth\n : node[offsetKey]);\n\n const parent = node.offsetParent;\n if (node === viewport || !parent) {\n return offsetSum;\n }\n\n return calcOffsetToViewport(\n parent as HTMLElement,\n viewport,\n window,\n isHorizontal,\n offsetSum\n );\n };\n\n const scheduleImperativeScroll = async (\n getTargetOffset: () => number,\n smooth?: boolean\n ) => {\n // Wait for element assign. The element may be undefined if scrollRef prop is used and scroll is scheduled on mount.\n // https://github.com/inokawa/virtua/pull/733\n await initialized;\n\n if (cancelScroll) {\n cancelScroll();\n }\n\n const waitForMeasurement = (): [Promise<void>, () => void] => {\n // Wait for the scroll destination items to be measured.\n // The measurement will be done asynchronously and the timing is not predictable so we use promise.\n const [promise, resolve, reject] = createPromise();\n cancelScroll = reject;\n\n // Resize event may not happen when the window/tab is not visible, or during browser back in Safari.\n // We have to wait for the initial measurement to avoid failing imperative scroll on mount.\n // https://github.com/inokawa/virtua/issues/450\n if (isInitialMeasurementDone(store)) {\n // Reject when items around scroll destination completely measured\n timeout(reject, 150);\n }\n return [\n promise,\n store.$subscribe(UPDATE_SIZE_EVENT, () => {\n resolve();\n }),\n ];\n };\n\n const window = getCurrentWindow(getCurrentDocument(containerElement!));\n\n if (smooth && isSmoothScrollSupported()) {\n while (true) {\n store.$update(ACTION_BEFORE_MANUAL_SMOOTH_SCROLL, getTargetOffset());\n\n if (!store._hasUnmeasuredItemsInFrozenRange()) {\n break;\n }\n\n const [promise, unsubscribe] = waitForMeasurement();\n\n try {\n await promise;\n } catch (e) {\n return;\n } finally {\n unsubscribe();\n }\n }\n\n window.scroll({\n [isHorizontal ? \"left\" : \"top\"]: normalizeOffset(\n getTargetOffset(),\n isHorizontal\n ),\n behavior: \"smooth\",\n });\n } else {\n while (true) {\n const [promise, unsubscribe] = waitForMeasurement();\n\n try {\n window.scroll({\n [isHorizontal ? \"left\" : \"top\"]: normalizeOffset(\n getTargetOffset(),\n isHorizontal\n ),\n });\n store.$update(ACTION_MANUAL_SCROLL);\n\n await promise;\n } catch (e) {\n return;\n } finally {\n unsubscribe();\n }\n }\n }\n };\n\n return {\n $observe(container) {\n containerElement = container;\n const scrollOffsetKey = isHorizontal ? \"scrollX\" : \"scrollY\";\n\n const document = getCurrentDocument(container);\n const window = getCurrentWindow(document);\n const documentBody = document.body;\n\n scrollObserver = createScrollObserver(\n store,\n window,\n isHorizontal,\n () => normalizeOffset(window[scrollOffsetKey], isHorizontal),\n (jump, shift) => {\n // TODO support case two window scrollers exist in the same view\n if (shift) {\n window.scroll({\n [isHorizontal ? \"left\" : \"top\"]: store.$getScrollOffset() + jump,\n });\n } else {\n window.scrollBy(isHorizontal ? jump : 0, isHorizontal ? 0 : jump);\n }\n },\n () =>\n calcOffsetToViewport(container, documentBody, window, isHorizontal)\n );\n\n resolveInitialized();\n },\n $dispose() {\n scrollObserver && scrollObserver._dispose();\n containerElement = undefined;\n rejectInitialized();\n },\n $fixScrollJump: () => {\n scrollObserver && scrollObserver._fixScrollJump();\n },\n $scrollToIndex(index, { align, smooth, offset = 0 } = {}) {\n if (!containerElement) return;\n\n index = clamp(index, 0, store.$getItemsLength() - 1);\n\n if (align === \"nearest\") {\n const itemOffset = store.$getItemOffset(index);\n const scrollOffset = store.$getScrollOffset();\n\n if (itemOffset < scrollOffset) {\n align = \"start\";\n } else if (\n itemOffset + store.$getItemSize(index) >\n scrollOffset + store.$getViewportSize()\n ) {\n align = \"end\";\n } else {\n return;\n }\n }\n\n const document = getCurrentDocument(containerElement);\n const window = getCurrentWindow(document);\n const html = document.documentElement;\n const getScrollbarSize = () =>\n store.$getViewportSize() -\n (isHorizontal ? html.clientWidth : html.clientHeight);\n\n scheduleImperativeScroll(() => {\n return (\n offset +\n // Calculate target scroll position including container's offset from document\n calcOffsetToViewport(\n containerElement!,\n document.body,\n window,\n isHorizontal\n ) +\n // store._getStartSpacerSize() +\n store.$getItemOffset(index) +\n (align === \"end\"\n ? store.$getItemSize(index) -\n (store.$getViewportSize() - getScrollbarSize())\n : align === \"center\"\n ? (store.$getItemSize(index) -\n (store.$getViewportSize() - getScrollbarSize())) /\n 2\n : 0)\n );\n }, smooth);\n },\n };\n};\n\n/**\n * @internal\n */\nexport type GridScroller = {\n $observe: (viewportElement: HTMLElement) => void;\n $dispose(): void;\n $scrollTo: (offsetX: number, offsetY: number) => void;\n $scrollBy: (offsetX: number, offsetY: number) => void;\n $scrollToIndex: (indexX: number, indexY: number) => void;\n $fixScrollJump: () => void;\n};\n\n/**\n * @internal\n */\nexport const createGridScroller = (\n vStore: VirtualStore,\n hStore: VirtualStore\n): GridScroller => {\n const vScroller = createScroller(vStore, false);\n const hScroller = createScroller(hStore, true);\n return {\n $observe(viewportElement) {\n vScroller.$observe(viewportElement);\n hScroller.$observe(viewportElement);\n },\n $dispose() {\n vScroller.$dispose();\n hScroller.$dispose();\n },\n $scrollTo(offsetX, offsetY) {\n vScroller.$scrollTo(offsetY);\n hScroller.$scrollTo(offsetX);\n },\n $scrollBy(offsetX, offsetY) {\n vScroller.$scrollBy(offsetY);\n hScroller.$scrollBy(offsetX);\n },\n $scrollToIndex(indexX, indexY) {\n vScroller.$scrollToIndex(indexY);\n hScroller.$scrollToIndex(indexX);\n },\n $fixScrollJump() {\n vScroller.$fixScrollJump();\n hScroller.$fixScrollJump();\n },\n };\n};\n","import { getCurrentDocument, getCurrentWindow } from \"./environment\";\nimport {\n ACTION_ITEM_RESIZE,\n ACTION_VIEWPORT_RESIZE,\n type VirtualStore,\n} from \"./store\";\nimport { type ItemResize } from \"./types\";\nimport { max, NULL } from \"./utils\";\n\nconst createResizeObserver = (cb: ResizeObserverCallback) => {\n let ro: ResizeObserver | undefined;\n\n return {\n _observe(e: HTMLElement) {\n // Initialize ResizeObserver lazily for SSR\n // https://www.w3.org/TR/resize-observer/#intro\n (\n ro ||\n // https://bugs.chromium.org/p/chromium/issues/detail?id=1491739\n (ro = new (getCurrentWindow(getCurrentDocument(e)).ResizeObserver)(cb))\n ).observe(e);\n },\n _unobserve(e: HTMLElement) {\n ro!.unobserve(e);\n },\n _dispose() {\n ro && ro.disconnect();\n },\n };\n};\n\n/**\n * @internal\n */\nexport type ItemResizeObserver = (el: HTMLElement, i: number) => () => void;\n\ninterface ListResizer {\n $observeRoot(viewportElement: HTMLElement): void;\n $observeItem: ItemResizeObserver;\n $dispose(): void;\n}\n\n/**\n * @internal\n */\nexport const createResizer = (\n store: VirtualStore,\n isHorizontal: boolean\n): ListResizer => {\n let viewportElement: HTMLElement | undefined;\n const sizeKey = isHorizontal ? \"width\" : \"height\";\n const mountedIndexes = new WeakMap<Element, number>();\n\n const resizeObserver = createResizeObserver((entries) => {\n const resizes: ItemResize[] = [];\n for (const { target, contentRect } of entries) {\n // Skip zero-sized rects that may be observed under `display: none` style\n if (!(target as HTMLElement).offsetParent) continue;\n\n if (target === viewportElement) {\n store.$update(ACTION_VIEWPORT_RESIZE, contentRect[sizeKey]);\n } else {\n const index = mountedIndexes.get(target);\n if (index != NULL) {\n resizes.push([index, contentRect[sizeKey]]);\n }\n }\n }\n\n if (resizes.length) {\n store.$update(ACTION_ITEM_RESIZE, resizes);\n }\n });\n\n return {\n $observeRoot(viewport: HTMLElement) {\n resizeObserver._observe((viewportElement = viewport));\n },\n $observeItem: (el: HTMLElement, i: number) => {\n mountedIndexes.set(el, i);\n resizeObserver._observe(el);\n return () => {\n mountedIndexes.delete(el);\n resizeObserver._unobserve(el);\n };\n },\n $dispose: resizeObserver._dispose,\n };\n};\n\ninterface WindowListResizer {\n $observeRoot(container: HTMLElement): void;\n $observeItem: ItemResizeObserver;\n $dispose(): void;\n}\n\n/**\n * @internal\n */\nexport const createWindowResizer = (\n store: VirtualStore,\n isHorizontal: boolean\n): WindowListResizer => {\n const sizeKey = isHorizontal ? \"width\" : \"height\";\n const windowSizeKey = isHorizontal ? \"innerWidth\" : \"innerHeight\";\n const mountedIndexes = new WeakMap<Element, number>();\n\n const resizeObserver = createResizeObserver((entries) => {\n const resizes: ItemResize[] = [];\n for (const { target, contentRect } of entries) {\n // Skip zero-sized rects that may be observed under `display: none` style\n if (!(target as HTMLElement).offsetParent) continue;\n\n const index = mountedIndexes.get(target);\n if (index != NULL) {\n resizes.push([index, contentRect[sizeKey]]);\n }\n }\n\n if (resizes.length) {\n store.$update(ACTION_ITEM_RESIZE, resizes);\n }\n });\n\n let cleanupOnWindowResize: (() => void) | undefined;\n\n return {\n $observeRoot(container) {\n const window = getCurrentWindow(getCurrentDocument(container));\n const onWindowResize = () => {\n store.$update(ACTION_VIEWPORT_RESIZE, window[windowSizeKey]);\n };\n window.addEventListener(\"resize\", onWindowResize);\n onWindowResize();\n\n cleanupOnWindowResize = () => {\n window.removeEventListener(\"resize\", onWindowResize);\n };\n },\n $observeItem: (el: HTMLElement, i: number) => {\n mountedIndexes.set(el, i);\n resizeObserver._observe(el);\n return () => {\n mountedIndexes.delete(el);\n resizeObserver._unobserve(el);\n };\n },\n $dispose() {\n cleanupOnWindowResize && cleanupOnWindowResize();\n resizeObserver._dispose();\n },\n };\n};\n\n/**\n * @internal\n */\nexport const createGridResizer = (\n vStore: VirtualStore,\n hStore: VirtualStore\n) => {\n let viewportElement: HTMLElement | undefined;\n\n const heightKey = \"height\";\n const widthKey = \"width\";\n const mountedIndexes = new WeakMap<\n Element,\n [rowIndex: number, colIndex: number]\n >();\n\n type CellSize = [height: number, width: number];\n const maybeCachedRowIndexes = new Set<number>();\n const maybeCachedColIndexes = new Set<number>();\n const sizeCache = new Map<string, CellSize>();\n const getKey = (rowIndex: number, colIndex: number): string =>\n `${rowIndex}-${colIndex}`;\n\n const resizeObserver = createResizeObserver((entries) => {\n const resizedRows = new Set<number>();\n const resizedCols = new Set<number>();\n for (const { target, contentRect } of entries) {\n // Skip zero-sized rects that may be observed under `display: none` style\n if (!(target as HTMLElement).offsetParent) continue;\n\n if (target === viewportElement) {\n vStore.$update(ACTION_VIEWPORT_RESIZE, contentRect[heightKey]);\n hStore.$update(ACTION_VIEWPORT_RESIZE, contentRect[widthKey]);\n } else {\n const cell = mountedIndexes.get(target);\n if (cell) {\n const [rowIndex, colIndex] = cell;\n const key = getKey(rowIndex, colIndex);\n const prevSize = sizeCache.get(key);\n const size: CellSize = [\n contentRect[heightKey],\n contentRect[widthKey],\n ];\n let rowResized: boolean | undefined;\n let colResized: boolean | undefined;\n if (!prevSize) {\n rowResized = colResized = true;\n } else {\n if (prevSize[0] !== size[0]) {\n rowResized = true;\n }\n if (prevSize[1] !== size[1]) {\n colResized = true;\n }\n }\n if (rowResized) {\n resizedRows.add(rowIndex);\n }\n if (colResized) {\n resizedCols.add(colIndex);\n }\n if (rowResized || colResized) {\n sizeCache.set(key, size);\n }\n }\n }\n }\n\n if (resizedRows.size) {\n const heightResizes: ItemResize[] = [];\n resizedRows.forEach((rowIndex) => {\n let maxHeight = 0;\n maybeCachedColIndexes.forEach((colIndex) => {\n const size = sizeCache.get(getKey(rowIndex, colIndex));\n if (size) {\n maxHeight = max(maxHeight, size[0]);\n }\n });\n if (maxHeight) {\n heightResizes.push([rowIndex, maxHeight]);\n }\n });\n vStore.$update(ACTION_ITEM_RESIZE, heightResizes);\n }\n if (resizedCols.size) {\n const widthResizes: ItemResize[] = [];\n resizedCols.forEach((colIndex) => {\n let maxWidth = 0;\n maybeCachedRowIndexes.forEach((rowIndex) => {\n const size = sizeCache.get(getKey(rowIndex, colIndex));\n if (size) {\n maxWidth = max(maxWidth, size[1]);\n }\n });\n if (maxWidth) {\n widthResizes.push([colIndex, maxWidth]);\n }\n });\n hStore.$update(ACTION_ITEM_RESIZE, widthResizes);\n }\n });\n\n return {\n $observeRoot(viewport: HTMLElement) {\n resizeObserver._observe((viewportElement = viewport));\n },\n $observeItem(el: HTMLElement, rowIndex: number, colIndex: number) {\n mountedIndexes.set(el, [rowIndex, colIndex]);\n maybeCachedRowIndexes.add(rowIndex);\n maybeCachedColIndexes.add(colIndex);\n resizeObserver._observe(el);\n return () => {\n mountedIndexes.delete(el);\n resizeObserver._unobserve(el);\n };\n },\n $resizeCols(cols: ItemResize[]) {\n for (const [c] of cols) {\n for (let r = 0; r < vStore.$getItemsLength(); r++) {\n sizeCache.delete(getKey(r, c));\n }\n }\n hStore.$update(ACTION_ITEM_RESIZE, cols);\n },\n $resizeRows(rows: ItemResize[]) {\n for (const [r] of rows) {\n for (let c = 0; c < hStore.$getItemsLength(); c++) {\n sizeCache.delete(getKey(r, c));\n }\n }\n vStore.$update(ACTION_ITEM_RESIZE, rows);\n },\n $dispose: resizeObserver._dispose,\n };\n};\n\n/**\n * @internal\n */\nexport type GridResizer = ReturnType<typeof createGridResizer>;\n"],"names":["NULL","min","max","abs","floor","Math","clamp","value","minValue","maxValue","sort","arr","a","b","microtask","queueMicrotask","fn","Promise","resolve","then","createPromise","reject","res","rej","once","cache","undefined","UNCACHED","fill","array","length","prepend","key","i","getItemSize","index","size","_sizes","_defaultItemSize","setItemSize","isInitialMeasurement","_computedOffsetIndex","computeOffset","_length","_offsets","top","findIndex","offset","low","high","mid","itemOffset","updateCacheLength","isShift","diff","splice","reduce","acc","removed","isBrowser","window","getDocumentElement","document","documentElement","getCurrentDocument","node","ownerDocument","getCurrentWindow","doc","defaultView","isRTLDocument","getComputedStyle","direction","isIOSWebKit","test","navigator","userAgent","isSmoothScrollSupported","style","isInitialMeasurementDone","store","$getViewportSize","timeout","setTimeout","normalizeOffset","isHorizontal","createScrollObserver","viewport","getScrollOffset","updateScrollOffset","getStartOffset","now","Date","lastScrollTime","wheeling","touching","justTouchEnded","stillMomentumScrolling","onScrollEnd","id","cancel","clearTimeout","debouncedFn","$update","_cancel","debounce","onScroll","onWheel","e","$isScrolling","ctrlKey","timeDelta","deltaX","deltaY","onTouchStart","onTouchEnd","addEventListener","passive","_dispose","removeEventListener","_fixScrollJump","jump","shift","_flushJump","$getTotalSize","createScroller","viewportElement","scrollObserver","cancelScroll","initialized","resolveInitialized","rejectInitialized","scrollOffsetKey","overflowKey","scheduleImperativeScroll","async","getTargetOffset","smooth","waitForMeasurement","promise","$subscribe","_hasUnmeasuredItemsInFrozenRange","unsubscribe","scrollTo","behavior","$observe","isMomentumScrolling","prev","$getScrollOffset","$dispose","$scrollTo","$scrollBy","$scrollToIndex","align","$getItemsLength","$getItemOffset","scrollOffset","$getItemSize","$getStartSpacerSize","$fixScrollJump","createResizeObserver","cb","ro","_observe","observe","_unobserve","unobserve","disconnect","vStore","hStore","heightKey","widthKey","mountedIndexes","WeakMap","maybeCachedRowIndexes","Set","maybeCachedColIndexes","sizeCache","Map","getKey","rowIndex","colIndex","resizeObserver","entries","resizedRows","resizedCols","target","contentRect","offsetParent","cell","get","prevSize","rowResized","colResized","add","set","heightResizes","forEach","maxHeight","push","widthResizes","maxWidth","$observeRoot","$observeItem","el","delete","$resizeCols","cols","c","r","$resizeRows","rows","vScroller","hScroller","offsetX","offsetY","indexX","indexY","sizeKey","resizes","elementsCount","itemSize","overscan","ssrCount","cacheSnapshot","shouldAutoEstimateItemSize","isSSR","stateVersion","viewportSize","startSpacerSize","pendingJump","_flushedJump","_scrollDirection","_scrollMode","_frozenRange","_prevRange","_totalMeasuredSize","snapshot","slice","initCache","subscribers","getRelativeScrollOffset","getVisibleOffset","getRange","prevStartIndex","end","start","computeRange","getTotalSize","computeTotalSize","getItemOffset","computeStartOffset","_getItemSize","applyJump","j","$getStateVersion","$getCacheSnapshot","takeCacheSnapshot","$getRange","startIndex","endIndex","$findStartIndex","$findEndIndex","$isUnmeasuredItem","includes","sub","type","payload","shouldFlushPendingJump","shouldSync","mutated","flushedJump","delta","distance","relativeOffset","updated","filter","measuredCountBeforeStart","measuredSizes","s","sorted","len","median","prevDefaultItemSize","estimateDefaultItemSize","UPDATE_VIRTUAL_STATE","windowSizeKey","cleanupOnWindowResize","container","onWindowResize","containerElement","calcOffsetToViewport","offsetKey","offsetSum","innerWidth","offsetWidth","parent","documentBody","body","scroll","scrollBy","html","getScrollbarSize","clientWidth","clientHeight"],"mappings":"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"}
|
package/lib/core/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=null,{min:t,max:o,abs:r,floor:n}=Math,s=(e,r,n)=>t(n,o(r,e)),c=e=>[...e].sort(((e,t)=>e-t)),i="function"==typeof queueMicrotask?queueMicrotask:e=>{Promise.resolve().then(e)},l=e=>{let t;return()=>(e&&(t=e(),e=void 0),t)},
|
|
1
|
+
const e=null,{min:t,max:o,abs:r,floor:n}=Math,s=(e,r,n)=>t(n,o(r,e)),c=e=>[...e].sort(((e,t)=>e-t)),i="function"==typeof queueMicrotask?queueMicrotask:e=>{Promise.resolve().then(e)},l=()=>{let e,t;return[new Promise(((o,r)=>{e=o,t=r})),e,t]},f=e=>{let t;return()=>(e&&(t=e(),e=void 0),t)},a=-1,u=(e,t,o)=>{const r=o?"unshift":"push";for(let o=0;o<t;o++)e[r](a);return e},d=(e,t)=>{const o=e.t[t];return o===a?e.o:o},$=(e,o,r)=>{const n=e.t[o]===a;return e.t[o]=r,e.i=t(o,e.i),n},h=(e,t)=>{if(!e.l)return 0;if(e.i>=t)return e.u[t];e.i<0&&(e.u[0]=0,e.i=0);let o=e.i,r=e.u[o];for(;o<t;)r+=d(e,o),e.u[++o]=r;return e.i=t,r},p=(e,t,o=0,r=e.l-1)=>{for(;o<=r;){const s=n((o+r)/2),c=h(e,s);if(c<=t){if(c+d(e,s)>t)return s;o=s+1}else r=s-1}return s(o,0,e.l-1)},m=(e,o,r)=>{const n=o-e.l;return e.i=r?-1:t(o-1,e.i),e.l=o,n>0?(u(e.u,n),u(e.t,n,r),e.o*n):(e.u.splice(n),(r?e.t.splice(0,-n):e.t.splice(n)).reduce(((t,o)=>t-(o===a?e.o:o)),0))},w="undefined"!=typeof window,g=()=>document.documentElement,b=e=>e.ownerDocument,v=e=>e.defaultView,S=/*#__PURE__*/f((()=>!!w&&"rtl"===getComputedStyle(g()).direction)),I=/*#__PURE__*/f((()=>/iP(hone|od|ad)/.test(navigator.userAgent))),y=/*#__PURE__*/f((()=>"scrollBehavior"in g().style)),k=5,x=6,_=1,z=4,T=8,R=e=>o(e.$getTotalSize(),e.$getViewportSize()),M=e=>!!e.$getViewportSize(),J=(n,s=40,i=4,l=0,f,w=!1)=>{let g=!!l,b=1,v=0,S=0,y=0,k=0,x=0,_=0,z=0,T=0,R=g?[0,o(l-1,0)]:e,M=[0,0],J=0;const W=((e,r,n)=>({o:n?n[1]:r,t:n&&n[0]?u(n[0].slice(0,t(e,n[0].length)),o(0,e-n[0].length)):u([],e),l:e,i:-1,u:u([],e)}))(n,s,f),B=new Set,C=()=>y-S,L=()=>C()+x+k,O=e=>((e,o,r,n)=>{if(n=t(n,e.l-1),h(e,n)<=o){const t=p(e,o+r,n);return[p(e,o,n,t),t]}{const t=p(e,o,void 0,n);return[t,p(e,o+r,t)]}})(W,e,v,M[0]),P=()=>(e=>e.l?h(e,e.l-1)+d(e,e.l-1):0)(W),q=e=>h(W,e)-x,U=e=>d(W,e),V=e=>{e&&(I()&&0!==z?x+=e:k+=e)};return{$getStateVersion:()=>b,$getCacheSnapshot:()=>(e=>[e.t.slice(),e.o])(W),$getRange:()=>{let e,r;return _?[e,r]=M:([e,r]=M=O(o(0,L())),R&&(e=t(e,R[0]),r=o(r,R[1]))),1!==z&&(e-=o(0,i)),2!==z&&(r+=o(0,i)),[o(e,0),t(r,W.l-1)]},$findStartIndex:()=>p(W,L()),$findEndIndex:()=>p(W,L()+v),$isUnmeasuredItem:e=>W.t[e]===a,$:()=>!!R&&W.t.slice(o(0,R[0]-1),t(W.l-1,R[1]+1)+1).includes(a),$getItemOffset:q,$getItemSize:U,$getItemsLength:()=>W.l,$getScrollOffset:()=>y,$isScrolling:()=>0!==z,$getViewportSize:()=>v,$getStartSpacerSize:()=>S,$getTotalSize:P,h:()=>(_=k,k=0,[_,2===T||C()+v>=P()]),$subscribe:(e,t)=>{const o=[e,t];return B.add(o),()=>{B.delete(o)}},$update:(t,n)=>{let s,i,l=0;switch(t){case 1:{const t=_;_=0;const o=n-y,s=r(o);t&&s<r(t)+1||0!==T||(z=o<0?2:1),g&&(R=e,g=!1),y=n,l=4;const c=C();c>=-v&&c<=P()&&(l+=1,i=s>v);break}case 2:l=8,0!==z&&(s=!0,l+=1),z=0,T=0,R=e;break;case 3:{const e=n.filter((([e,t])=>W.t[e]!==t));if(!e.length)break;V(e.reduce(((e,[t,o])=>((2===T||(R?!g&&t<R[0]:q(t)+(0===z&&0===T?U(t):0)<C()))&&(e+=o-U(t)),e)),0));for(const[t,o]of e){const e=U(t),r=$(W,t,o);w&&(J+=r?o:o-e)}w&&v&&J>v&&(V(((e,t)=>{let r=0;const n=[];e.t.forEach(((e,o)=>{e!==a&&(n.push(e),o<t&&r++)})),e.i=-1;const s=c(n),i=s.length,l=i/2|0,f=i%2==0?(s[l-1]+s[l])/2:s[l],u=e.o;return((e.o=f)-u)*o(t-r,0)})(W,p(W,L()))),w=!1),l=3,i=!0;break}case 4:v!==n&&(v=n,l=3);break;case 5:n[1]?(V(m(W,n[0],!0)),T=2,l=1):(m(W,n[0]),l=1);break;case 6:S=n;break;case 7:T=1;break;case 8:R=O(n),l=1}l&&(b=1+(2147483647&b),s&&x&&(k+=x,x=0),B.forEach((([e,t])=>{l&e&&t(i)})))}}},W=setTimeout,B=(e,t)=>t&&S()?-e:e,C=(t,o,r,n,s,c)=>{const i=Date.now;let l=0,f=!1,a=!1,u=!1,d=!1;const $=(()=>{let o;const r=()=>{o!=e&&clearTimeout(o)},n=()=>{r(),o=W((()=>{o=e,(()=>{if(f||a)return f=!1,void $();u=!1,t.$update(2)})()}),150)};return n.p=r,n})(),h=()=>{l=i(),u&&(d=!0),c&&t.$update(6,c()),t.$update(1,n()),$()},p=e=>{if(f||!t.$isScrolling()||e.ctrlKey)return;const o=i()-l;150>o&&50<o&&(r?e.deltaX:e.deltaY)&&(f=!0)},m=()=>{a=!0,u=d=!1},w=()=>{a=!1,I()&&(u=!0)};return o.addEventListener("scroll",h),o.addEventListener("wheel",p,{passive:!0}),o.addEventListener("touchstart",m,{passive:!0}),o.addEventListener("touchend",w,{passive:!0}),{m:()=>{o.removeEventListener("scroll",h),o.removeEventListener("wheel",p),o.removeEventListener("touchstart",m),o.removeEventListener("touchend",w),$.p()},v:()=>{const[e,o]=t.h();e&&(s(B(e,r),o,d),d=!1,o&&t.$getViewportSize()>t.$getTotalSize()&&t.$update(1,n()))}}},L=(e,t)=>{let o,r,n;const[c,i,f]=l(),a=t?"scrollLeft":"scrollTop",u=t?"overflowX":"overflowY",d=async(r,s)=>{await c,n&&n();const i=()=>{const[t,o,r]=l();return n=r,M(e)&&W(r,150),[t,e.$subscribe(2,(()=>{o()}))]};if(s&&y()){for(;e.$update(8,r()),e.$();){const[e,t]=i();try{await e}catch(e){return}finally{t()}}o.scrollTo({[t?"left":"top"]:B(r(),t),behavior:"smooth"})}else for(;;){const[n,s]=i();try{o[a]=B(r(),t),e.$update(7),await n}catch(e){return}finally{s()}}};return{$observe(s){o=s,r=C(e,s,t,(()=>B(s[a],t)),((t,o,r)=>{if(r){const e=s.style,t=e[u];e[u]="hidden",W((()=>{e[u]=t}))}o?(s[a]=e.$getScrollOffset()+t,n&&n()):s[a]+=t})),i()},$dispose(){r&&r.m(),f()},$scrollTo(e){d((()=>e))},$scrollBy(t){t+=e.$getScrollOffset(),d((()=>t))},$scrollToIndex(t,{align:o,smooth:r,offset:n=0}={}){if(t=s(t,0,e.$getItemsLength()-1),"nearest"===o){const r=e.$getItemOffset(t),n=e.$getScrollOffset();if(r<n)o="start";else{if(!(r+e.$getItemSize(t)>n+e.$getViewportSize()))return;o="end"}}d((()=>n+e.$getStartSpacerSize()+e.$getItemOffset(t)+("end"===o?e.$getItemSize(t)-e.$getViewportSize():"center"===o?(e.$getItemSize(t)-e.$getViewportSize())/2:0)),r)},$fixScrollJump:()=>{r&&r.v()}}},O=(e,t)=>{let o,r,n;const[c,i,f]=l(),a=(e,t,o,r,n=0)=>{const s=r?"offsetLeft":"offsetTop",c=n+(r&&S()?o.innerWidth-e[s]-e.offsetWidth:e[s]),i=e.offsetParent;return e!==t&&i?a(i,t,o,r,c):c};return{$observe(n){o=n;const s=t?"scrollX":"scrollY",c=b(n),l=v(c),f=c.body;r=C(e,l,t,(()=>B(l[s],t)),((o,r)=>{r?l.scroll({[t?"left":"top"]:e.$getScrollOffset()+o}):l.scrollBy(t?o:0,t?0:o)}),(()=>a(n,f,l,t))),i()},$dispose(){r&&r.m(),o=void 0,f()},$fixScrollJump:()=>{r&&r.v()},$scrollToIndex(r,{align:i,smooth:f,offset:u=0}={}){if(!o)return;if(r=s(r,0,e.$getItemsLength()-1),"nearest"===i){const t=e.$getItemOffset(r),o=e.$getScrollOffset();if(t<o)i="start";else{if(!(t+e.$getItemSize(r)>o+e.$getViewportSize()))return;i="end"}}const d=b(o),$=v(d),h=d.documentElement,p=()=>e.$getViewportSize()-(t?h.clientWidth:h.clientHeight);(async(r,s)=>{await c,n&&n();const i=()=>{const[t,o,r]=l();return n=r,M(e)&&W(r,150),[t,e.$subscribe(2,(()=>{o()}))]},f=v(b(o));if(s&&y()){for(;e.$update(8,r()),e.$();){const[e,t]=i();try{await e}catch(e){return}finally{t()}}f.scroll({[t?"left":"top"]:B(r(),t),behavior:"smooth"})}else for(;;){const[o,n]=i();try{f.scroll({[t?"left":"top"]:B(r(),t)}),e.$update(7),await o}catch(e){return}finally{n()}}})((()=>u+a(o,d.body,$,t)+e.$getItemOffset(r)+("end"===i?e.$getItemSize(r)-(e.$getViewportSize()-p()):"center"===i?(e.$getItemSize(r)-(e.$getViewportSize()-p()))/2:0)),f)}}},P=(e,t)=>{const o=L(e,!1),r=L(t,!0);return{$observe(e){o.$observe(e),r.$observe(e)},$dispose(){o.$dispose(),r.$dispose()},$scrollTo(e,t){o.$scrollTo(t),r.$scrollTo(e)},$scrollBy(e,t){o.$scrollBy(t),r.$scrollBy(e)},$scrollToIndex(e,t){o.$scrollToIndex(t),r.$scrollToIndex(e)},$fixScrollJump(){o.$fixScrollJump(),r.$fixScrollJump()}}},q=e=>{let t;return{S(o){(t||(t=new(v(b(o)).ResizeObserver)(e))).observe(o)},I(e){t.unobserve(e)},m(){t&&t.disconnect()}}},U=(t,o)=>{let r;const n=o?"width":"height",s=new WeakMap,c=q((o=>{const c=[];for(const{target:i,contentRect:l}of o)if(i.offsetParent)if(i===r)t.$update(4,l[n]);else{const t=s.get(i);t!=e&&c.push([t,l[n]])}c.length&&t.$update(3,c)}));return{$observeRoot(e){c.S(r=e)},$observeItem:(e,t)=>(s.set(e,t),c.S(e),()=>{s.delete(e),c.I(e)}),$dispose:c.m}},V=(t,o)=>{const r=o?"width":"height",n=o?"innerWidth":"innerHeight",s=new WeakMap,c=q((o=>{const n=[];for(const{target:t,contentRect:c}of o){if(!t.offsetParent)continue;const o=s.get(t);o!=e&&n.push([o,c[r]])}n.length&&t.$update(3,n)}));let i;return{$observeRoot(e){const o=v(b(e)),r=()=>{t.$update(4,o[n])};o.addEventListener("resize",r),r(),i=()=>{o.removeEventListener("resize",r)}},$observeItem:(e,t)=>(s.set(e,t),c.S(e),()=>{s.delete(e),c.I(e)}),$dispose(){i&&i(),c.m()}}},X=(e,t)=>{let r;const n="height",s="width",c=new WeakMap,i=new Set,l=new Set,f=new Map,a=(e,t)=>`${e}-${t}`,u=q((u=>{const d=new Set,$=new Set;for(const{target:o,contentRect:i}of u)if(o.offsetParent)if(o===r)e.$update(4,i[n]),t.$update(4,i[s]);else{const e=c.get(o);if(e){const[t,o]=e,r=a(t,o),c=f.get(r),l=[i[n],i[s]];let u,h;c?(c[0]!==l[0]&&(u=!0),c[1]!==l[1]&&(h=!0)):u=h=!0,u&&d.add(t),h&&$.add(o),(u||h)&&f.set(r,l)}}if(d.size){const t=[];d.forEach((e=>{let r=0;l.forEach((t=>{const n=f.get(a(e,t));n&&(r=o(r,n[0]))})),r&&t.push([e,r])})),e.$update(3,t)}if($.size){const e=[];$.forEach((t=>{let r=0;i.forEach((e=>{const n=f.get(a(e,t));n&&(r=o(r,n[1]))})),r&&e.push([t,r])})),t.$update(3,e)}}));return{$observeRoot(e){u.S(r=e)},$observeItem:(e,t,o)=>(c.set(e,[t,o]),i.add(t),l.add(o),u.S(e),()=>{c.delete(e),u.I(e)}),$resizeCols(o){for(const[t]of o)for(let o=0;o<e.$getItemsLength();o++)f.delete(a(o,t));t.$update(3,o)},$resizeRows(o){for(const[e]of o)for(let o=0;o<t.$getItemsLength();o++)f.delete(a(e,o));e.$update(3,o)},$dispose:u.m}};export{k as ACTION_ITEMS_LENGTH_CHANGE,x as ACTION_START_OFFSET_CHANGE,T as UPDATE_SCROLL_END_EVENT,z as UPDATE_SCROLL_EVENT,_ as UPDATE_VIRTUAL_STATE,X as createGridResizer,P as createGridScroller,U as createResizer,L as createScroller,J as createVirtualStore,V as createWindowResizer,O as createWindowScroller,R as getScrollSize,w as isBrowser,S as isRTLDocument,i as microtask,c as sort};
|
|
2
2
|
//# sourceMappingURL=index.mjs.map
|