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