UNPKG

virtua

Version:

A zero-config, fast and small (~3kB) virtual list (and grid) component for React, Vue, Solid and Svelte.

3 lines (2 loc) 9.41 kB
const e=null,{min:t,max:o,abs:n,floor:r}=Math,s=(e,n,r)=>t(r,o(n,e)),c=e=>[...e].sort(((e,t)=>e-t)),i="function"==typeof queueMicrotask?queueMicrotask:e=>{Promise.resolve().then(e)},l=e=>{let t,o;return()=>(t||(t=!0,o=e()),o)},f=-1,a=(e,t,o)=>{const n=o?"unshift":"push";for(let o=0;o<t;o++)e[n](f);return e},u=(e,t)=>{const o=e.t[t];return o===f?e.o:o},d=(e,o,n)=>{const r=e.t[o]===f;return e.t[o]=n,e.i=t(o,e.i),r},$=(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,n=e.u[o];for(;o<t;)n+=u(e,o),e.u[++o]=n;return e.i=t,n},h=(e,t,o=0,n=e.l-1)=>{for(;o<=n;){const s=r((o+n)/2),c=$(e,s);if(c<=t){if(c+u(e,s)>t)return s;o=s+1}else n=s-1}return s(o,0,e.l-1)},p=(e,o,n)=>{const r=o-e.l;return e.i=n?-1:t(o-1,e.i),e.l=o,r>0?(a(e.u,r),a(e.t,r,n),e.o*r):(e.u.splice(r),(n?e.t.splice(0,-r):e.t.splice(r)).reduce(((t,o)=>t-(o===f?e.o:o)),0))},m="undefined"!=typeof window,w=()=>document.documentElement,g=e=>e.ownerDocument,v=e=>e.defaultView,b=/*#__PURE__*/l((()=>!!m&&"rtl"===getComputedStyle(w()).direction)),S=/*#__PURE__*/l((()=>/iP(hone|od|ad)/.test(navigator.userAgent))),I=/*#__PURE__*/l((()=>"scrollBehavior"in w().style)),y=5,k=6,x=1,_=4,T=8,z=e=>o(e.$getTotalSize(),e.$getViewportSize()),R=e=>!!e.$getViewportSize(),M=(r,s=40,i=4,l=0,m,w=!1)=>{let g=!!l,v=1,b=0,I=0,y=0,k=0,x=0,_=0,T=0,z=0,R=g?[0,o(l-1,0)]:e,M=[0,0],J=0;const P=((e,n,r)=>({o:r?r[1]:n,t:r&&r[0]?a(r[0].slice(0,t(e,r[0].length)),o(0,e-r[0].length)):a([],e),l:e,i:-1,u:a([],e)}))(r,s,m),W=new Set,B=()=>y-I,L=()=>B()+x+k,O=e=>((e,o,n,r)=>{if(r=t(r,e.l-1),$(e,r)<=o){const t=h(e,o+n,r);return[h(e,o,r,t),t]}{const t=h(e,o,void 0,r);return[t,h(e,o+n,t)]}})(P,e,b,M[0]),q=()=>(e=>e.l?$(e,e.l-1)+u(e,e.l-1):0)(P),C=e=>$(P,e)-x,U=e=>u(P,e),V=e=>{e&&(S()&&0!==T?x+=e:k+=e)};return{$getStateVersion:()=>v,$getCacheSnapshot:()=>(e=>[e.t.slice(),e.o])(P),$getRange:()=>{let e,n;return _?[e,n]=M:([e,n]=M=O(o(0,L())),R&&(e=t(e,R[0]),n=o(n,R[1]))),1!==T&&(e-=o(0,i)),2!==T&&(n+=o(0,i)),[o(e,0),t(n,P.l-1)]},$findStartIndex:()=>h(P,L()),$findEndIndex:()=>h(P,L()+b),$isUnmeasuredItem:e=>P.t[e]===f,$:()=>!!R&&P.t.slice(o(0,R[0]-1),t(P.l-1,R[1]+1)+1).includes(f),$getItemOffset:C,$getItemSize:U,$getItemsLength:()=>P.l,$getScrollOffset:()=>y,$isScrolling:()=>0!==T,$getViewportSize:()=>b,$getStartSpacerSize:()=>I,$getTotalSize:q,h:()=>(_=k,k=0,[_,2===z||B()+b>=q()]),$subscribe:(e,t)=>{const o=[e,t];return W.add(o),()=>{W.delete(o)}},$update:(t,r)=>{let s,i,l=0;switch(t){case 1:{const t=_;_=0;const o=r-y,s=n(o);t&&s<n(t)+1||0!==z||(T=o<0?2:1),g&&(R=e,g=!1),y=r,l=4;const c=B();c>=-b&&c<=q()&&(l+=1,i=s>b);break}case 2:l=8,0!==T&&(s=!0,l+=1),T=0,z=0,R=e;break;case 3:{const e=r.filter((([e,t])=>P.t[e]!==t));if(!e.length)break;V(e.reduce(((e,[t,o])=>((2===z||(R?!g&&t<R[0]:C(t)+(0===T&&0===z?U(t):0)<B()))&&(e+=o-U(t)),e)),0));for(const[t,o]of e){const e=U(t),n=d(P,t,o);w&&(J+=n?o:o-e)}w&&b&&J>b&&(V(((e,t)=>{let n=0;const r=[];e.t.forEach(((e,o)=>{e!==f&&(r.push(e),o<t&&n++)})),e.i=-1;const s=c(r),i=s.length,l=i/2|0,a=i%2==0?(s[l-1]+s[l])/2:s[l],u=e.o;return((e.o=a)-u)*o(t-n,0)})(P,h(P,L()))),w=!1),l=3,i=!0;break}case 4:b!==r&&(b=r,l=3);break;case 5:r[1]?(V(p(P,r[0],!0)),z=2,l=1):(p(P,r[0]),l=1);break;case 6:I=r;break;case 7:z=1;break;case 8:R=O(r),l=1}l&&(v=1+(2147483647&v),s&&x&&(k+=x,x=0),W.forEach((([e,t])=>{l&e&&t(i)})))}}},J=setTimeout,P=(e,t)=>t&&b()?-e:e,W=(t,o,n,r,s,c)=>{const i=Date.now;let l=0,f=!1,a=!1,u=!1,d=!1;const $=(()=>{let o;const n=()=>{o!=e&&clearTimeout(o)},r=()=>{n(),o=J((()=>{o=e,(()=>{if(f||a)return f=!1,void $();u=!1,t.$update(2)})()}),150)};return r.p=n,r})(),h=()=>{l=i(),u&&(d=!0),c&&t.$update(6,c()),t.$update(1,r()),$()},p=e=>{if(f||!t.$isScrolling()||e.ctrlKey)return;const o=i()-l;150>o&&50<o&&(n?e.deltaX:e.deltaY)&&(f=!0)},m=()=>{a=!0,u=d=!1},w=()=>{a=!1,S()&&(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(P(e,n),o,d),d=!1,o&&t.$getViewportSize()>t.$getTotalSize()&&t.$update(1,r()))}}},B=(e,t)=>{let o,n,r;const c=t?"scrollLeft":"scrollTop",l=t?"overflowX":"overflowY",f=async(n,s)=>{if(!o)return void i((()=>f(n,s)));r&&r();const l=()=>{let t;return[new Promise(((o,n)=>{t=o,r=n,R(e)&&J(n,150)})),e.$subscribe(2,(()=>{t&&t()}))]};if(s&&I()){for(;e.$update(8,n()),e.$();){const[e,t]=l();try{await e}catch(e){return}finally{t()}}o.scrollTo({[t?"left":"top"]:P(n(),t),behavior:"smooth"})}else for(;;){const[r,s]=l();try{o[c]=P(n(),t),e.$update(7),await r}catch(e){return}finally{s()}}};return{$observe(s){o=s,n=W(e,s,t,(()=>P(s[c],t)),((t,o,n)=>{if(n){const e=s.style,t=e[l];e[l]="hidden",J((()=>{e[l]=t}))}o?(s[c]=e.$getScrollOffset()+t,r&&r()):s[c]+=t}))},$dispose(){n&&n.m()},$scrollTo(e){f((()=>e))},$scrollBy(t){t+=e.$getScrollOffset(),f((()=>t))},$scrollToIndex(t,{align:o,smooth:n,offset:r=0}={}){if(t=s(t,0,e.$getItemsLength()-1),"nearest"===o){const n=e.$getItemOffset(t),r=e.$getScrollOffset();if(n<r)o="start";else{if(!(n+e.$getItemSize(t)>r+e.$getViewportSize()))return;o="end"}}f((()=>r+e.$getStartSpacerSize()+e.$getItemOffset(t)+("end"===o?e.$getItemSize(t)-e.$getViewportSize():"center"===o?(e.$getItemSize(t)-e.$getViewportSize())/2:0)),n)},$fixScrollJump:()=>{n&&n.v()}}},L=(e,t)=>{let o,n,r;const c=(e,t,o,n,r=0)=>{const s=n?"offsetLeft":"offsetTop",i=r+(n&&b()?o.innerWidth-e[s]-e.offsetWidth:e[s]),l=e.offsetParent;return e!==t&&l?c(l,t,o,n,i):i},l=async(n,s)=>{if(!o)return void i((()=>l(n,s)));r&&r();const c=()=>{let t;return[new Promise(((o,n)=>{t=o,r=n,R(e)&&J(n,150)})),e.$subscribe(2,(()=>{t&&t()}))]},f=v(g(o));if(s&&I()){for(;e.$update(8,n()),e.$();){const[e,t]=c();try{await e}catch(e){return}finally{t()}}f.scroll({[t?"left":"top"]:P(n(),t),behavior:"smooth"})}else for(;;){const[o,r]=c();try{f.scroll({[t?"left":"top"]:P(n(),t)}),e.$update(7),await o}catch(e){return}finally{r()}}};return{$observe(r){o=r;const s=t?"scrollX":"scrollY",i=g(r),l=v(i),f=i.body;n=W(e,l,t,(()=>P(l[s],t)),((o,n)=>{n?l.scroll({[t?"left":"top"]:e.$getScrollOffset()+o}):l.scrollBy(t?o:0,t?0:o)}),(()=>c(r,f,l,t)))},$dispose(){n&&n.m(),o=void 0},$fixScrollJump:()=>{n&&n.v()},$scrollToIndex(n,{align:r,smooth:i,offset:f=0}={}){if(!o)return;if(n=s(n,0,e.$getItemsLength()-1),"nearest"===r){const t=e.$getItemOffset(n),o=e.$getScrollOffset();if(t<o)r="start";else{if(!(t+e.$getItemSize(n)>o+e.$getViewportSize()))return;r="end"}}const a=g(o),u=v(a),d=a.documentElement,$=()=>e.$getViewportSize()-(t?d.clientWidth:d.clientHeight);l((()=>f+c(o,a.body,u,t)+e.$getItemOffset(n)+("end"===r?e.$getItemSize(n)-(e.$getViewportSize()-$()):"center"===r?(e.$getItemSize(n)-(e.$getViewportSize()-$()))/2:0)),i)}}},O=(e,t)=>{const o=B(e,!1),n=B(t,!0);return{$observe(e){o.$observe(e),n.$observe(e)},$dispose(){o.$dispose(),n.$dispose()},$scrollTo(e,t){o.$scrollTo(t),n.$scrollTo(e)},$scrollBy(e,t){o.$scrollBy(t),n.$scrollBy(e)},$scrollToIndex(e,t){o.$scrollToIndex(t),n.$scrollToIndex(e)},$fixScrollJump(){o.$fixScrollJump(),n.$fixScrollJump()}}},q=e=>{let t;return{S(o){(t||(t=new(v(g(o)).ResizeObserver)(e))).observe(o)},I(e){t.unobserve(e)},m(){t&&t.disconnect()}}},C=(t,o)=>{let n;const r=o?"width":"height",s=new WeakMap,c=q((o=>{const c=[];for(const{target:i,contentRect:l}of o)if(i.offsetParent)if(i===n)t.$update(4,l[r]);else{const t=s.get(i);t!=e&&c.push([t,l[r]])}c.length&&t.$update(3,c)}));return{$observeRoot(e){c.S(n=e)},$observeItem:(e,t)=>(s.set(e,t),c.S(e),()=>{s.delete(e),c.I(e)}),$dispose:c.m}},U=(t,o)=>{const n=o?"width":"height",r=o?"innerWidth":"innerHeight",s=new WeakMap,c=q((o=>{const r=[];for(const{target:t,contentRect:c}of o){if(!t.offsetParent)continue;const o=s.get(t);o!=e&&r.push([o,c[n]])}r.length&&t.$update(3,r)}));let i;return{$observeRoot(e){const o=v(g(e)),n=()=>{t.$update(4,o[r])};o.addEventListener("resize",n),n(),i=()=>{o.removeEventListener("resize",n)}},$observeItem:(e,t)=>(s.set(e,t),c.S(e),()=>{s.delete(e),c.I(e)}),$dispose(){i&&i(),c.m()}}},V=(e,t)=>{let n;const r="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===n)e.$update(4,i[r]),t.$update(4,i[s]);else{const e=c.get(o);if(e){const[t,o]=e,n=a(t,o),c=f.get(n),l=[i[r],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(n,l)}}if(d.size){const t=[];d.forEach((e=>{let n=0;l.forEach((t=>{const r=f.get(a(e,t));r&&(n=o(n,r[0]))})),n&&t.push([e,n])})),e.$update(3,t)}if($.size){const e=[];$.forEach((t=>{let n=0;i.forEach((e=>{const r=f.get(a(e,t));r&&(n=o(n,r[1]))})),n&&e.push([t,n])})),t.$update(3,e)}}));return{$observeRoot(e){u.S(n=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)}),$dispose:u.m}};export{y as ACTION_ITEMS_LENGTH_CHANGE,k as ACTION_START_OFFSET_CHANGE,T as UPDATE_SCROLL_END_EVENT,_ as UPDATE_SCROLL_EVENT,x as UPDATE_VIRTUAL_STATE,V as createGridResizer,O as createGridScroller,C as createResizer,B as createScroller,M as createVirtualStore,U as createWindowResizer,L as createWindowScroller,z as getScrollSize,m as isBrowser,b as isRTLDocument,i as microtask,c as sort}; //# sourceMappingURL=index.mjs.map