@floor/vlist 0.5.1

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.
Files changed (120) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +839 -0
  3. package/dist/adapters/index.d.ts +20 -0
  4. package/dist/adapters/index.d.ts.map +1 -0
  5. package/dist/adapters/react.d.ts +119 -0
  6. package/dist/adapters/react.d.ts.map +1 -0
  7. package/dist/adapters/svelte.d.ts +198 -0
  8. package/dist/adapters/svelte.d.ts.map +1 -0
  9. package/dist/adapters/vue.d.ts +151 -0
  10. package/dist/adapters/vue.d.ts.map +1 -0
  11. package/dist/builder/context.d.ts +36 -0
  12. package/dist/builder/context.d.ts.map +1 -0
  13. package/dist/builder/core.d.ts +16 -0
  14. package/dist/builder/core.d.ts.map +1 -0
  15. package/dist/builder/data.d.ts +71 -0
  16. package/dist/builder/data.d.ts.map +1 -0
  17. package/dist/builder/index.d.ts +25 -0
  18. package/dist/builder/index.d.ts.map +1 -0
  19. package/dist/builder/index.js +1 -0
  20. package/dist/builder/types.d.ts +269 -0
  21. package/dist/builder/types.d.ts.map +1 -0
  22. package/dist/compression/index.js +1 -0
  23. package/dist/constants.d.ts +65 -0
  24. package/dist/constants.d.ts.map +1 -0
  25. package/dist/core/index.js +1 -0
  26. package/dist/core-light.d.ts +104 -0
  27. package/dist/core-light.d.ts.map +1 -0
  28. package/dist/core-light.js +1 -0
  29. package/dist/core.d.ts +129 -0
  30. package/dist/core.d.ts.map +1 -0
  31. package/dist/data/index.js +1 -0
  32. package/dist/events/emitter.d.ts +20 -0
  33. package/dist/events/emitter.d.ts.map +1 -0
  34. package/dist/events/index.d.ts +6 -0
  35. package/dist/events/index.d.ts.map +1 -0
  36. package/dist/grid/index.js +1 -0
  37. package/dist/groups/index.js +1 -0
  38. package/dist/index.d.ts +17 -0
  39. package/dist/index.d.ts.map +1 -0
  40. package/dist/index.js +1 -0
  41. package/dist/plugins/compression/index.d.ts +10 -0
  42. package/dist/plugins/compression/index.d.ts.map +1 -0
  43. package/dist/plugins/compression/plugin.d.ts +42 -0
  44. package/dist/plugins/compression/plugin.d.ts.map +1 -0
  45. package/dist/plugins/data/index.d.ts +9 -0
  46. package/dist/plugins/data/index.d.ts.map +1 -0
  47. package/dist/plugins/data/manager.d.ts +103 -0
  48. package/dist/plugins/data/manager.d.ts.map +1 -0
  49. package/dist/plugins/data/placeholder.d.ts +62 -0
  50. package/dist/plugins/data/placeholder.d.ts.map +1 -0
  51. package/dist/plugins/data/plugin.d.ts +60 -0
  52. package/dist/plugins/data/plugin.d.ts.map +1 -0
  53. package/dist/plugins/data/sparse.d.ts +91 -0
  54. package/dist/plugins/data/sparse.d.ts.map +1 -0
  55. package/dist/plugins/grid/index.d.ts +9 -0
  56. package/dist/plugins/grid/index.d.ts.map +1 -0
  57. package/dist/plugins/grid/layout.d.ts +29 -0
  58. package/dist/plugins/grid/layout.d.ts.map +1 -0
  59. package/dist/plugins/grid/plugin.d.ts +48 -0
  60. package/dist/plugins/grid/plugin.d.ts.map +1 -0
  61. package/dist/plugins/grid/renderer.d.ts +55 -0
  62. package/dist/plugins/grid/renderer.d.ts.map +1 -0
  63. package/dist/plugins/grid/types.d.ts +71 -0
  64. package/dist/plugins/grid/types.d.ts.map +1 -0
  65. package/dist/plugins/groups/index.d.ts +10 -0
  66. package/dist/plugins/groups/index.d.ts.map +1 -0
  67. package/dist/plugins/groups/layout.d.ts +46 -0
  68. package/dist/plugins/groups/layout.d.ts.map +1 -0
  69. package/dist/plugins/groups/plugin.d.ts +63 -0
  70. package/dist/plugins/groups/plugin.d.ts.map +1 -0
  71. package/dist/plugins/groups/sticky.d.ts +33 -0
  72. package/dist/plugins/groups/sticky.d.ts.map +1 -0
  73. package/dist/plugins/groups/types.d.ts +86 -0
  74. package/dist/plugins/groups/types.d.ts.map +1 -0
  75. package/dist/plugins/scroll/controller.d.ts +121 -0
  76. package/dist/plugins/scroll/controller.d.ts.map +1 -0
  77. package/dist/plugins/scroll/index.d.ts +8 -0
  78. package/dist/plugins/scroll/index.d.ts.map +1 -0
  79. package/dist/plugins/scroll/plugin.d.ts +60 -0
  80. package/dist/plugins/scroll/plugin.d.ts.map +1 -0
  81. package/dist/plugins/scroll/scrollbar.d.ts +73 -0
  82. package/dist/plugins/scroll/scrollbar.d.ts.map +1 -0
  83. package/dist/plugins/selection/index.d.ts +7 -0
  84. package/dist/plugins/selection/index.d.ts.map +1 -0
  85. package/dist/plugins/selection/plugin.d.ts +44 -0
  86. package/dist/plugins/selection/plugin.d.ts.map +1 -0
  87. package/dist/plugins/selection/state.d.ts +102 -0
  88. package/dist/plugins/selection/state.d.ts.map +1 -0
  89. package/dist/plugins/snapshots/index.d.ts +8 -0
  90. package/dist/plugins/snapshots/index.d.ts.map +1 -0
  91. package/dist/plugins/snapshots/plugin.d.ts +44 -0
  92. package/dist/plugins/snapshots/plugin.d.ts.map +1 -0
  93. package/dist/plugins/window/index.d.ts +8 -0
  94. package/dist/plugins/window/index.d.ts.map +1 -0
  95. package/dist/plugins/window/plugin.d.ts +53 -0
  96. package/dist/plugins/window/plugin.d.ts.map +1 -0
  97. package/dist/react/index.js +1 -0
  98. package/dist/render/compression.d.ts +116 -0
  99. package/dist/render/compression.d.ts.map +1 -0
  100. package/dist/render/heights.d.ts +63 -0
  101. package/dist/render/heights.d.ts.map +1 -0
  102. package/dist/render/index.d.ts +9 -0
  103. package/dist/render/index.d.ts.map +1 -0
  104. package/dist/render/renderer.d.ts +103 -0
  105. package/dist/render/renderer.d.ts.map +1 -0
  106. package/dist/render/virtual.d.ts +139 -0
  107. package/dist/render/virtual.d.ts.map +1 -0
  108. package/dist/scroll/index.js +1 -0
  109. package/dist/selection/index.js +1 -0
  110. package/dist/snapshots/index.js +1 -0
  111. package/dist/svelte/index.js +1 -0
  112. package/dist/types.d.ts +559 -0
  113. package/dist/types.d.ts.map +1 -0
  114. package/dist/vlist-extras.css +1 -0
  115. package/dist/vlist.css +1 -0
  116. package/dist/vlist.d.ts +22 -0
  117. package/dist/vlist.d.ts.map +1 -0
  118. package/dist/vue/index.js +1 -0
  119. package/dist/window/index.js +1 -0
  120. package/package.json +137 -0
@@ -0,0 +1 @@
1
+ var QJ=0,m=5,qJ=100,Oj=2,KJ=(X=0)=>{let U=Array(m);for(let $=0;$<m;$++)U[$]={position:0,time:0};return{velocity:0,lastPosition:X,lastTime:performance.now(),samples:U,sampleIndex:0,sampleCount:0}},UJ=(X,U)=>{let $=performance.now(),Y=$-X.lastTime;if(Y===0)return X;if(Y>qJ){X.sampleCount=0,X.sampleIndex=0,X.velocity=0;let Q=X.samples[0];return Q.position=U,Q.time=$,X.sampleIndex=1,X.sampleCount=1,X.lastPosition=U,X.lastTime=$,X}let V=X.samples[X.sampleIndex];if(V.position=U,V.time=$,X.sampleIndex=(X.sampleIndex+1)%m,X.sampleCount=Math.min(X.sampleCount+1,m),X.sampleCount>=Oj){let Q=(X.sampleIndex-X.sampleCount+m)%m,K=X.samples[Q],W=U-K.position,C=$-K.time;X.velocity=C>0?Math.abs(W)/C:0}return X.lastPosition=U,X.lastTime=$,X},Ij=(X,U)=>{if(typeof X==="number"){let Q=U;return{getOffset:(K)=>K*X,getHeight:()=>X,indexAtOffset:(K)=>{if(Q===0||X===0)return 0;return Math.max(0,Math.min(Math.floor(K/X),Q-1))},getTotalHeight:()=>Q*X,getTotal:()=>Q,rebuild:(K)=>{Q=K},isVariable:()=>!1}}let $=U,Y=new Float64Array(0),V=(Q)=>{$=Q,Y=new Float64Array(Q+1),Y[0]=0;for(let K=0;K<Q;K++)Y[K+1]=Y[K]+X(K)};return V(U),{getOffset:(Q)=>{if(Q<=0)return 0;if(Q>=$)return Y[$];return Y[Q]},getHeight:(Q)=>X(Q),indexAtOffset:(Q)=>{if($===0)return 0;if(Q<=0)return 0;if(Q>=Y[$])return $-1;let K=0,W=$-1;while(K<W){let C=K+W+1>>>1;if(Y[C]<=Q)K=C;else W=C-1}return K},getTotalHeight:()=>Y[$]??0,getTotal:()=>$,rebuild:(Q)=>V(Q),isVariable:()=>!0}},YJ=()=>{let X={},U=(Q,K)=>{if(!X[Q])X[Q]=new Set;return X[Q].add(K),()=>$(Q,K)},$=(Q,K)=>{X[Q]?.delete(K)};return{on:U,off:$,emit:(Q,K)=>{X[Q]?.forEach((W)=>{try{W(K)}catch(C){console.error(`[vlist] Error in "${Q}" handler:`,C)}})},clear:()=>{for(let Q in X)delete X[Q]}}},BJ=(X)=>{if(typeof X==="string"){let U=document.querySelector(X);if(!U)throw Error(`[vlist/builder] Container not found: ${X}`);return U}return X},GJ=(X,U,$,Y)=>{let V=document.createElement("div");if(V.className=U,Y)V.classList.add(`${U}--horizontal`);if(V.setAttribute("role","listbox"),V.setAttribute("tabindex","0"),$)V.setAttribute("aria-label",$);if(Y)V.setAttribute("aria-orientation","horizontal");let Q=document.createElement("div");if(Q.className=`${U}-viewport`,Y)Q.style.overflowX="auto",Q.style.overflowY="hidden";else Q.style.overflow="auto";Q.style.height="100%",Q.style.width="100%";let K=document.createElement("div");if(K.className=`${U}-content`,K.style.position="relative",Y)K.style.height="100%";else K.style.width="100%";let W=document.createElement("div");if(W.className=`${U}-items`,W.style.position="relative",Y)W.style.height="100%";else W.style.width="100%";return K.appendChild(W),Q.appendChild(K),V.appendChild(Q),X.appendChild(V),{root:V,viewport:Q,content:K,items:W}},DJ=(X=100)=>{let U=[];return{acquire:()=>{let $=U.pop();if($)return $;let Y=document.createElement("div");return Y.setAttribute("role","option"),Y},release:($)=>{if(U.length<X)$.className="",$.textContent="",$.removeAttribute("style"),$.removeAttribute("data-index"),$.removeAttribute("data-id"),U.push($)},clear:()=>{U.length=0}}},WJ=(X,U,$,Y,V)=>{if(Y===0||U===0){V.start=0,V.end=0;return}let Q=$.indexAtOffset(X),K=$.indexAtOffset(X+U);if(K<Y-1)K++;V.start=Math.max(0,Q),V.end=Math.min(Y-1,Math.max(0,K))},VJ=(X,U,$,Y)=>{if($===0){Y.start=0,Y.end=0;return}Y.start=Math.max(0,X.start-U),Y.end=Math.min($-1,X.end+U)},_J=(X,U,$,Y,V)=>{if(Y===0)return 0;let Q=Math.max(0,Math.min(X,Y-1)),K=U.getOffset(Q),W=U.getHeight(Q),C=Math.max(0,U.getTotalHeight()-$),f;switch(V){case"center":f=K-($-W)/2;break;case"end":f=K-$+W;break;default:f=K}return Math.max(0,Math.min(f,C))},LJ=(X)=>X<0.5?2*X*X:-1+(4-2*X)*X,NJ=(X)=>{if(typeof X==="string")return{align:X,behavior:"auto",duration:300};if(X&&typeof X==="object")return{align:X.align??"start",behavior:X.behavior??"auto",duration:X.duration??300};return{align:"start",behavior:"auto",duration:300}},MJ=(X)=>{if(!X.container)throw Error("[vlist/builder] Container is required");if(!X.item)throw Error("[vlist/builder] item configuration is required");let U=X.direction==="horizontal",$=U?"width":"height",Y=U?X.item.width:X.item.height;if(Y==null)throw Error(`[vlist/builder] item.${$} is required${U?" when direction is 'horizontal'":""}`);if(typeof Y==="number"&&Y<=0)throw Error(`[vlist/builder] item.${$} must be a positive number`);if(typeof Y!=="number"&&typeof Y!=="function")throw Error(`[vlist/builder] item.${$} must be a number or a function (index) => number`);if(!X.item.template)throw Error("[vlist/builder] item.template is required");if(U&&X.reverse)throw Error("[vlist/builder] horizontal direction cannot be combined with reverse mode");let V=new Map,Q=!1,K={use(W){if(Q)throw Error("[vlist/builder] Cannot call .use() after .build()");return V.set(W.name,W),K},build(){if(Q)throw Error("[vlist/builder] .build() can only be called once");return Q=!0,AJ(X,V,U,Y)}};return K};function AJ(X,U,$,Y){let{item:V,items:Q,overscan:K=3,classPrefix:W="vlist",ariaLabel:C,reverse:f=!1,scroll:Kj}=X,Sj=Kj?.wheel??!0,Fj=Kj?.wrap??!1,c=f,Rj=`${W}-${QJ++}`,Tj=Y,yj=$?typeof V.height==="number"?V.height:void 0:typeof V.width==="number"?V.width:void 0,e=V.template,uj={overscan:K,classPrefix:W,reverse:c,wrap:Fj,horizontal:$,ariaIdPrefix:Rj},d=Array.from(U.values()).sort((j,J)=>(j.priority??50)-(J.priority??50)),s=new Set(d.map((j)=>j.name));for(let j of d)if(j.conflicts){for(let J of j.conflicts)if(s.has(J))throw Error(`[vlist/builder] ${j.name} and ${J} cannot be combined`)}if($){if(s.has("withGrid"))throw Error("[vlist/builder] withGrid cannot be used with direction: 'horizontal'");if(s.has("withGroups"))throw Error("[vlist/builder] withGroups cannot be used with direction: 'horizontal'")}if(c){if(s.has("withGrid"))throw Error("[vlist/builder] withGrid cannot be used with reverse: true");if(s.has("withGroups"))throw Error("[vlist/builder] withGroups cannot be used with reverse: true")}let fj=BJ(X.container),_=GJ(fj,W,C,$),k=YJ(),B=Q?[...Q]:[],N=Ij(Tj,B.length),jj=DJ(),R=_.viewport.clientHeight,l=_.viewport.clientWidth,a=!1,x=!1,O=0,p=null,r=null,S=KJ(0),Jj={start:0,end:0},E={start:0,end:0},h={start:-1,end:-1},z={viewportState:{scrollTop:0,containerHeight:R,totalHeight:N.getTotalHeight(),actualHeight:N.getTotalHeight(),isCompressed:!1,compressionRatio:1,visibleRange:{start:0,end:0},renderRange:{start:0,end:0}},lastRenderRange:{start:-1,end:-1},isInitialized:!1,isDestroyed:!1,cachedCompression:null},v=new Map,Uj={selected:!1,focused:!1},xj=`${W}-item`,o="",P=new Map,Yj=()=>{P.clear();for(let j=0;j<B.length;j++){let J=B[j];if(J)P.set(J.id,j)}};Yj();let F=null,H=()=>F?F.getTotal():B.length,Bj=[],Gj=[],Dj=[],Wj=[],n=[],Vj=[],L=new Map,u=()=>{return $?_.viewport.scrollLeft:_.viewport.scrollTop},I=(j)=>{if($)_.viewport.scrollLeft=j;else _.viewport.scrollTop=j},Cj=(j=2)=>{let J=N.getTotalHeight();return O+R>=J-j},pj=!1,y,T,kj=(j,J,Z,q,D)=>{WJ(j,J,Z,q,D)},Xj=(j,J,Z,q,D)=>{return _J(j,J,Z,q,D)},_j=(j,J)=>{if(typeof J==="string")j.innerHTML=J;else j.replaceChildren(J)},Lj=(j,J)=>{let Z=Math.round(N.getOffset(J));if($)j.style.transform=`translateX(${Z}px)`;else j.style.transform=`translateY(${Z}px)`},hj=(j,J)=>{let Z=jj.acquire();if(Z.className=xj,$){if(Z.style.width=`${N.getHeight(j)}px`,yj!=null)Z.style.height=`${yj}px`}else Z.style.height=`${N.getHeight(j)}px`;return Z.dataset.index=String(j),Z.dataset.id=String(J.id),Z.ariaSelected="false",Z.id=`${Rj}-item-${j}`,o=String(H()),Z.setAttribute("aria-setsize",o),Z.setAttribute("aria-posinset",String(j+1)),_j(Z,e(J,j,Uj)),Lj(Z,j),Z},i=()=>{let j=`${N.getTotalHeight()}px`;if($)_.content.style.width=j;else _.content.style.height=j},Nj=new Set,Mj=-1,gj=()=>{if(a)return;let j=H();if(kj(O,R,N,j,Jj),VJ(Jj,K,j,E),E.start===h.start&&E.end===h.end)return;let J=String(j),Z=J!==o;o=J;for(let[G,A]of v)if(G<E.start||G>E.end)A.remove(),jj.release(A),v.delete(G);let q=document.createDocumentFragment(),D=[];for(let G=E.start;G<=E.end;G++){let A=F?F.getItem(G):B[G];if(!A)continue;let b=v.get(G);if(b){let w=b.dataset.id,Qj=String(A.id);if(w!==Qj)if(_j(b,e(A,G,Uj)),b.dataset.id=Qj,$)b.style.width=`${N.getHeight(G)}px`;else b.style.height=`${N.getHeight(G)}px`;Lj(b,G);let qj=Nj.has(A.id),$J=G===Mj;if(b.classList.toggle(`${W}-item--selected`,qj),b.classList.toggle(`${W}-item--focused`,$J),b.ariaSelected=qj?"true":"false",Z)b.setAttribute("aria-setsize",o)}else{let w=hj(G,A),Qj=Nj.has(A.id),qj=G===Mj;if(Qj)w.classList.add(`${W}-item--selected`),w.ariaSelected="true";if(qj)w.classList.add(`${W}-item--focused`);q.appendChild(w),D.push({index:G,element:w})}}if(D.length>0){_.items.appendChild(q);for(let{index:G,element:A}of D)v.set(G,A)}h.start=E.start,h.end=E.end,z.lastRenderRange.start=E.start,z.lastRenderRange.end=E.end,z.viewportState.scrollTop=O,z.viewportState.visibleRange.start=Jj.start,z.viewportState.visibleRange.end=Jj.end,z.viewportState.renderRange.start=E.start,z.viewportState.renderRange.end=E.end,k.emit("range:change",{range:{start:E.start,end:E.end}})},mj=()=>{h.start=-1,h.end=-1,y()};y=gj,T=mj;let t=()=>{if(a)return;let j=u(),J=j>=O?"down":"up";if(S=UJ(S,j),!_.root.classList.contains(`${W}--scrolling`))_.root.classList.add(`${W}--scrolling`);O=j,y(),k.emit("scroll",{scrollTop:j,direction:J}),k.emit("velocity:change",{velocity:S.velocity,reliable:S.sampleCount>=Oj});for(let Z=0;Z<Bj.length;Z++)Bj[Z](j,J);if(r)clearTimeout(r);r=setTimeout(()=>{_.root.classList.remove(`${W}--scrolling`),S.velocity=0,S.sampleCount=0,k.emit("velocity:change",{velocity:0,reliable:!1})},Kj?.idleTimeout??150)},Zj=null,g=_.viewport;if(g.addEventListener("scroll",t,{passive:!0}),$&&Sj)Zj=(j)=>{if(j.deltaX)return;j.preventDefault(),_.viewport.scrollLeft+=j.deltaY},_.viewport.addEventListener("wheel",Zj);_.viewport.classList.add(`${W}-viewport--custom-scrollbar`);let zj=(j)=>{let Z=j.target.closest("[data-index]");if(Z){let q=parseInt(Z.dataset.index??"-1",10);if(q>=0){let D=F?.getItem(q)??B[q];if(D){if(D.__groupHeader)return;k.emit("item:click",{item:D,index:q,event:j})}}}for(let q=0;q<Gj.length;q++)Gj[q](j)},cj=(j)=>{let Z=j.target.closest("[data-index]");if(Z){let q=parseInt(Z.dataset.index??"-1",10);if(q>=0){let D=F?.getItem(q)??B[q];if(D){if(D.__groupHeader)return;k.emit("item:dblclick",{item:D,index:q,event:j})}}}},Pj=(j)=>{for(let J=0;J<Dj.length;J++)Dj[J](j)};_.items.addEventListener("click",zj),_.items.addEventListener("dblclick",cj),_.root.addEventListener("keydown",Pj);let Aj=!0,dj=()=>l,sj=()=>R,bj=new ResizeObserver((j)=>{if(a)return;for(let J of j){let Z=J.contentRect.height,q=J.contentRect.width,D=$?q:Z;if(l=q,Math.abs(D-R)>1){if(R=D,z.viewportState.containerHeight=D,x)i(),y(),k.emit("resize",{height:Z,width:q})}if(x)for(let G=0;G<Wj.length;G++)Wj[G](q,Z)}});if(Aj)bj.observe(_.viewport);let M={get dom(){return _},get heightCache(){return N},get emitter(){return k},get config(){return uj},get rawConfig(){return X},get renderer(){return{render:(j,J,Z,q,D)=>{Nj=Z,Mj=q,T()},updateItemClasses:(j,J,Z)=>{let q=v.get(j);if(!q)return;q.classList.toggle(`${W}-item--selected`,J),q.classList.toggle(`${W}-item--focused`,Z),q.ariaSelected=J?"true":"false"},updatePositions:()=>{},updateItem:()=>{},getElement:(j)=>v.get(j)??null,clear:()=>{},destroy:()=>{}}},set renderer(j){},get dataManager(){return F},set dataManager(j){F=j},get scrollController(){return Ej},set scrollController(j){Ej=j},state:z,getContainerWidth(){return l},afterScroll:Bj,clickHandlers:Gj,keydownHandlers:Dj,resizeHandlers:Wj,contentSizeHandlers:n,destroyHandlers:Vj,methods:L,replaceTemplate(j){e=j},replaceRenderer(j){},replaceDataManager(j){F=j},replaceScrollController(j){Ej=j},getItemsForRange(j){let J=[];for(let Z=j.start;Z<=j.end;Z++){let q=F?F.getItem(Z):B[Z];if(q)J.push(q)}return J},getAllLoadedItems(){if(F){let j=F.getTotal(),J=[];for(let Z=0;Z<j;Z++){let q=F.getItem(Z);if(q)J.push(q)}return J}return[...B]},getVirtualTotal(){return H()},getCachedCompression(){return{isCompressed:!1,actualHeight:N.getTotalHeight(),virtualHeight:N.getTotalHeight(),ratio:1}},getCompressionContext(){return{scrollTop:O,totalItems:H(),containerHeight:R,rangeStart:E.start}},renderIfNeeded(){y()},forceRender(){T()},getRenderFns(){return{renderIfNeeded:y,forceRender:T}},setRenderFns(j,J){y=j,T=J},setVirtualTotalFn(j){H=j},rebuildHeightCache(j){N.rebuild(j??H())},setHeightConfig(j){N=Ij(j,H())},updateContentSize(j){let J=`${j}px`;if($)_.content.style.width=J;else _.content.style.height=J},updateCompressionMode(){},setVisibleRangeFn(j){kj=j},setScrollToPosFn(j){Xj=j},setPositionElementFn(j){Lj=j},setScrollFns(j,J){u=j,I=(Z)=>{J(Z),t()}},setScrollTarget(j){g.removeEventListener("scroll",t),g=j,g.addEventListener("scroll",t,{passive:!0})},getScrollTarget(){return g},setContainerDimensions(j){dj=j.width,sj=j.height,l=j.width(),R=j.height(),z.viewportState.containerWidth=l,z.viewportState.containerHeight=R},disableViewportResize(){if(Aj)Aj=!1,bj.unobserve(_.viewport)}};F={getState:()=>({total:B.length,cached:B.length,isLoading:!1,pendingRanges:[],error:void 0,hasMore:!1,cursor:void 0}),getTotal:()=>B.length,getCached:()=>B.length,getIsLoading:()=>!1,getHasMore:()=>!1,getStorage:()=>null,getPlaceholders:()=>null,getItem:(j)=>B[j],getItemById:(j)=>{let J=P.get(j);return J!==void 0?B[J]:void 0},getIndexById:(j)=>P.get(j)??-1,isItemLoaded:(j)=>j>=0&&j<B.length&&B[j]!==void 0,getItemsInRange:(j,J)=>{let Z=[],q=Math.max(0,j),D=Math.min(J,B.length-1);for(let G=q;G<=D;G++)Z.push(B[G]);return Z},setTotal:(j)=>{},setItems:(j,J=0,Z)=>{if(J===0&&(Z!==void 0||B.length===0))B=[...j];else{let q=J+j.length;if(B.length<q)B.length=q;for(let D=0;D<j.length;D++)B[J+D]=j[D]}if(Yj(),x){N.rebuild(H()),i(),M.updateCompressionMode();for(let q=0;q<n.length;q++)n[q]();T()}},updateItem:(j,J)=>{let Z=P.get(j);if(Z===void 0)return!1;let q=B[Z];if(!q)return!1;if(B[Z]={...q,...J},J.id!==void 0&&J.id!==j)P.delete(j),P.set(J.id,Z);let D=v.get(Z);if(D)_j(D,e(B[Z],Z,Uj)),D.dataset.id=String(B[Z].id);return!0},removeItem:(j)=>{let J=P.get(j);if(J===void 0)return!1;if(B.splice(J,1),Yj(),x){N.rebuild(H()),i(),M.updateCompressionMode();for(let Z=0;Z<n.length;Z++)n[Z]();T()}return!0},loadRange:async()=>{},ensureRange:async()=>{},loadInitial:async()=>{},loadMore:async()=>!1,reload:async()=>{},evictDistant:()=>{},clear:()=>{B=[],P.clear()},reset:()=>{if(B=[],P.clear(),x)N.rebuild(0),i(),T()}};let Ej={getScrollTop:()=>u(),scrollTo:(j)=>{I(j),O=j,y()},scrollBy:(j)=>{let J=u()+j;I(J),O=J,y()},isAtTop:()=>O<=2,isAtBottom:(j=2)=>Cj(j),getScrollPercentage:()=>{let j=N.getTotalHeight(),J=Math.max(0,j-R);return J>0?O/J:0},getVelocity:()=>S.velocity,isTracking:()=>S.sampleCount>=Oj,isScrolling:()=>_.root.classList.contains(`${W}--scrolling`),updateConfig:()=>{},enableCompression:()=>{},disableCompression:()=>{},isCompressed:()=>pj,isWindowMode:()=>!1,updateContainerHeight:(j)=>{R=j},destroy:()=>{}},Hj=new Map;for(let j of d)if(j.methods)for(let J of j.methods){let Z=Hj.get(J);if(Z)throw Error(`[vlist/builder] Method "${J}" is registered by both "${Z}" and "${j.name}"`);Hj.set(J,j.name)}for(let j of d)j.setup(M);if(x=!0,M.state.isInitialized=!0,i(),y(),c&&B.length>0){let j=Xj(B.length-1,N,R,B.length,"end");I(j),O=j,y()}let lj=(j)=>{M.dataManager.setItems(j,0,j.length)},aj=c?(j)=>{let J=Cj(2),Z=B.length;if(M.dataManager.setItems(j,Z),J&&B.length>0){let q=Xj(B.length-1,N,R,B.length,"end");I(q),O=q,y()}}:(j)=>{let J=B.length;M.dataManager.setItems(j,J)},rj=c?(j)=>{let J=u(),Z=N.getTotalHeight(),q=[...B];M.dataManager.clear(),M.dataManager.setItems([...j,...q],0);let G=N.getTotalHeight()-Z;if(G>0)I(J+G),O=J+G}:(j)=>{let J=[...B];M.dataManager.clear(),M.dataManager.setItems([...j,...J],0)},oj=(j,J)=>{M.dataManager.updateItem(j,J)},nj=(j)=>{M.dataManager.removeItem(j)},ij=async()=>{if(M.dataManager.reload)await M.dataManager.reload()},$j=()=>{if(p!==null)cancelAnimationFrame(p),p=null},tj=(j,J,Z)=>{if($j(),Math.abs(J-j)<1){I(J),O=J,y();return}let q=performance.now(),D=(G)=>{let A=G-q,b=Math.min(A/Z,1),w=j+(J-j)*LJ(b);if(I(w),O=w,y(),b<1)p=requestAnimationFrame(D);else p=null};p=requestAnimationFrame(D)},wj=(j,J)=>{let{align:Z,behavior:q,duration:D}=NJ(J),G=H(),A=j;if(Fj&&G>0)A=(A%G+G)%G;let b=Xj(A,N,R,G,Z);if(q==="smooth")tj(u(),b,D);else $j(),I(b)},ej=(j,J)=>{let Z=P.get(j)??M.dataManager.getIndexById(j);if(Z>=0)wj(Z,J)},jJ=()=>u(),JJ=(j,J)=>{return k.on(j,J)},XJ=(j,J)=>{k.off(j,J)},ZJ=()=>{if(a)return;if(a=!0,M.state.isDestroyed=!0,_.items.removeEventListener("click",zj),_.root.removeEventListener("keydown",Pj),g.removeEventListener("scroll",t),bj.disconnect(),Zj)_.viewport.removeEventListener("wheel",Zj);if(r)clearTimeout(r);for(let j=0;j<Vj.length;j++)Vj[j]();for(let j of d)if(j.destroy)j.destroy();$j();for(let[,j]of v)j.remove(),jj.release(j);v.clear(),jj.clear(),k.clear(),_.root.remove()},vj={get element(){return _.root},get items(){if(L.has("_getItems"))return L.get("_getItems")();return B},get total(){if(L.has("_getTotal"))return L.get("_getTotal")();return H()},setItems:L.has("setItems")?L.get("setItems"):lj,appendItems:L.has("appendItems")?L.get("appendItems"):aj,prependItems:L.has("prependItems")?L.get("prependItems"):rj,updateItem:L.has("updateItem")?L.get("updateItem"):oj,removeItem:L.has("removeItem")?L.get("removeItem"):nj,reload:L.has("reload")?L.get("reload"):ij,scrollToIndex:L.has("scrollToIndex")?L.get("scrollToIndex"):wj,scrollToItem:L.has("scrollToItem")?L.get("scrollToItem"):ej,cancelScroll:L.has("cancelScroll")?L.get("cancelScroll"):$j,getScrollPosition:L.has("getScrollPosition")?L.get("getScrollPosition"):jJ,on:JJ,off:XJ,destroy:ZJ};for(let[j,J]of L){if(j==="setItems"||j==="appendItems"||j==="prependItems"||j==="updateItem"||j==="removeItem"||j==="reload"||j==="scrollToIndex"||j==="scrollToItem"||j==="cancelScroll"||j==="getScrollPosition")continue;vj[j]=J}return vj}export{MJ as vlist};
@@ -0,0 +1,269 @@
1
+ /**
2
+ * vlist/builder - Types
3
+ * Plugin interface, builder config, builder context, and return types
4
+ */
5
+ import type { VListItem, VListEvents, ItemConfig, Range, ViewportState, EventHandler, Unsubscribe, ScrollToOptions, ScrollSnapshot } from "../types";
6
+ import type { DOMStructure, Renderer, HeightCache, CompressionContext } from "../render";
7
+ import type { CompressionState } from "../render/virtual";
8
+ import type { SimpleDataManager } from "./data";
9
+ import type { ScrollController } from "../scroll/controller";
10
+ import type { Emitter } from "../events";
11
+ /** Configuration accepted by the builder's vlist() factory */
12
+ export interface BuilderConfig<T extends VListItem = VListItem> {
13
+ /** Container element or selector */
14
+ container: HTMLElement | string;
15
+ /** Item configuration (height/width and template) */
16
+ item: ItemConfig<T>;
17
+ /** Static items array (optional if using adapter via plugin) */
18
+ items?: T[];
19
+ /** Number of extra items to render outside viewport (default: 3) */
20
+ overscan?: number;
21
+ /** Custom CSS class prefix (default: 'vlist') */
22
+ classPrefix?: string;
23
+ /** Accessible label for the listbox */
24
+ ariaLabel?: string;
25
+ /**
26
+ * Scroll direction (default: 'vertical')
27
+ * - 'vertical' — Standard top-to-bottom scrolling
28
+ * - 'horizontal' — Left-to-right scrolling
29
+ */
30
+ direction?: "vertical" | "horizontal";
31
+ /** Reverse mode for chat UIs */
32
+ reverse?: boolean;
33
+ /** Scroll behavior configuration (non-scrollbar options) */
34
+ scroll?: {
35
+ /** Enable mouse wheel scrolling (default: true) */
36
+ wheel?: boolean;
37
+ /** Wrap around when scrolling past boundaries (default: false) */
38
+ wrap?: boolean;
39
+ /** Scroll idle detection timeout in ms (default: 150) */
40
+ idleTimeout?: number;
41
+ /** External scroll element for window scrolling */
42
+ element?: Window;
43
+ };
44
+ }
45
+ /** Resolved configuration stored inside BuilderContext */
46
+ export interface ResolvedBuilderConfig {
47
+ readonly overscan: number;
48
+ readonly classPrefix: string;
49
+ readonly reverse: boolean;
50
+ readonly wrap: boolean;
51
+ readonly horizontal: boolean;
52
+ readonly ariaIdPrefix: string;
53
+ }
54
+ /** Cached compression state */
55
+ export interface CachedCompression {
56
+ state: CompressionState;
57
+ totalItems: number;
58
+ }
59
+ /** Builder state */
60
+ export interface BuilderState {
61
+ viewportState: ViewportState;
62
+ lastRenderRange: Range;
63
+ isInitialized: boolean;
64
+ isDestroyed: boolean;
65
+ cachedCompression: CachedCompression | null;
66
+ }
67
+ /**
68
+ * BuilderContext — the internal interface that plugins receive during setup.
69
+ *
70
+ * Provides access to all core components plus registration points for
71
+ * handlers, methods, and cleanup callbacks.
72
+ */
73
+ export interface BuilderContext<T extends VListItem = VListItem> {
74
+ readonly dom: DOMStructure;
75
+ readonly heightCache: HeightCache;
76
+ readonly emitter: Emitter<VListEvents<T>>;
77
+ readonly config: ResolvedBuilderConfig;
78
+ /** The raw user-provided builder config (for plugins that need original values) */
79
+ readonly rawConfig: BuilderConfig<T>;
80
+ renderer: Renderer<T>;
81
+ dataManager: SimpleDataManager<T>;
82
+ scrollController: ScrollController;
83
+ state: BuilderState;
84
+ /**
85
+ * Plugins register lightweight callbacks that run after each
86
+ * scroll-triggered render. These are NOT on the hot path —
87
+ * they run after DOM updates are complete.
88
+ */
89
+ afterScroll: Array<(scrollTop: number, direction: string) => void>;
90
+ /**
91
+ * Plugins register handlers for user interaction events.
92
+ * These are attached as DOM event listeners during .build().
93
+ */
94
+ clickHandlers: Array<(event: MouseEvent) => void>;
95
+ keydownHandlers: Array<(event: KeyboardEvent) => void>;
96
+ resizeHandlers: Array<(width: number, height: number) => void>;
97
+ contentSizeHandlers: Array<() => void>;
98
+ destroyHandlers: Array<() => void>;
99
+ /** Plugins register public methods by name. Exposed on the returned API. */
100
+ methods: Map<string, Function>;
101
+ replaceTemplate(template: ItemTemplate<T>): void;
102
+ replaceRenderer(renderer: Renderer<T>): void;
103
+ replaceDataManager(dataManager: SimpleDataManager<T>): void;
104
+ replaceScrollController(scrollController: ScrollController): void;
105
+ getItemsForRange(range: Range): T[];
106
+ getAllLoadedItems(): T[];
107
+ getVirtualTotal(): number;
108
+ getCachedCompression(): CompressionState;
109
+ getCompressionContext(): CompressionContext;
110
+ renderIfNeeded(): void;
111
+ forceRender(): void;
112
+ /**
113
+ * Get current render functions (for wrapping by selection/other plugins).
114
+ * Call this BEFORE setRenderFns to capture the current functions.
115
+ */
116
+ getRenderFns(): {
117
+ renderIfNeeded: () => void;
118
+ forceRender: () => void;
119
+ };
120
+ /**
121
+ * Get current container width (for grid plugin).
122
+ * This returns the width detected by ResizeObserver, which is more reliable
123
+ * than viewport.clientWidth in test environments.
124
+ */
125
+ getContainerWidth(): number;
126
+ /**
127
+ * Replace the virtual-total function.
128
+ * Used by grid/groups plugins that change what "total" means
129
+ * (e.g. row count instead of item count).
130
+ */
131
+ setVirtualTotalFn(fn: () => number): void;
132
+ /**
133
+ * Replace the effective height config.
134
+ * Used by groups plugin to inject grouped height function and by grid to add gap.
135
+ */
136
+ rebuildHeightCache(total?: number): void;
137
+ /**
138
+ * Set a new effective height config function/value.
139
+ * Plugins that change heights (groups, grid) call this before rebuildHeightCache.
140
+ */
141
+ setHeightConfig(config: number | ((index: number) => number)): void;
142
+ /**
143
+ * Update content size on the main axis (height for vertical, width for horizontal).
144
+ */
145
+ updateContentSize(totalSize: number): void;
146
+ /**
147
+ * Update compression mode when total items changes.
148
+ * Called by the core after data changes and by plugins that alter totals.
149
+ */
150
+ updateCompressionMode(): void;
151
+ /**
152
+ * Replace the visible-range calculation function.
153
+ * Used by withCompression to inject compressed range calculation.
154
+ */
155
+ setVisibleRangeFn(fn: (scrollTop: number, containerHeight: number, hc: HeightCache, totalItems: number, out: Range) => void): void;
156
+ /**
157
+ * Replace the scroll-to-index position calculator.
158
+ * Used by withCompression to inject compressed position calculation.
159
+ */
160
+ setScrollToPosFn(fn: (index: number, hc: HeightCache, containerHeight: number, totalItems: number, align: "start" | "center" | "end") => number): void;
161
+ /**
162
+ * Replace the item positioning function.
163
+ * Used by withCompression to inject compressed item positioning.
164
+ */
165
+ setPositionElementFn(fn: (element: HTMLElement, index: number) => void): void;
166
+ /**
167
+ * Replace the render functions.
168
+ * Used by grid/groups plugins that need to completely replace the render logic
169
+ * (e.g., to convert row ranges to item ranges for grid rendering).
170
+ */
171
+ setRenderFns(renderIfNeeded: () => void, forceRender: () => void): void;
172
+ /**
173
+ * Replace the scroll get/set functions.
174
+ * Used by withCompression to manage a virtual scroll position that bypasses
175
+ * native DOM scrollTop (which can't represent compressed scroll space).
176
+ */
177
+ setScrollFns(getTop: () => number, setTop: (pos: number) => void): void;
178
+ /**
179
+ * Set the scroll target element (default: viewport).
180
+ * Used by window mode plugin to use window instead of viewport for scroll events.
181
+ */
182
+ setScrollTarget(target: HTMLElement | Window): void;
183
+ /**
184
+ * Get the current scroll target element.
185
+ * Returns the element/window that scroll events are bound to.
186
+ */
187
+ getScrollTarget(): HTMLElement | Window;
188
+ /**
189
+ * Override container dimension getters.
190
+ * Used by window mode plugin to use window.innerWidth/innerHeight instead
191
+ * of viewport.clientWidth/clientHeight.
192
+ */
193
+ setContainerDimensions(getter: {
194
+ width: () => number;
195
+ height: () => number;
196
+ }): void;
197
+ /**
198
+ * Disable the ResizeObserver on the viewport element.
199
+ * Used by window mode plugin where the viewport doesn't need observation
200
+ * (window resize is used instead).
201
+ */
202
+ disableViewportResize(): void;
203
+ }
204
+ /**
205
+ * VListPlugin — the interface for builder plugins.
206
+ *
207
+ * Each plugin:
208
+ * - Has a unique name (used for deduplication and error messages)
209
+ * - Optionally declares a priority (lower runs first, default: 50)
210
+ * - Implements setup() which receives BuilderContext and wires in handlers/methods
211
+ * - Optionally implements destroy() for cleanup
212
+ * - Optionally declares methods it adds and plugins it conflicts with
213
+ */
214
+ export interface VListPlugin<T extends VListItem = VListItem> {
215
+ /** Unique plugin name (used for deduplication and error messages) */
216
+ readonly name: string;
217
+ /** Execution priority — lower runs first (default: 50) */
218
+ readonly priority?: number;
219
+ /** Setup function — receives BuilderContext, wires handlers and methods */
220
+ setup(ctx: BuilderContext<T>): void;
221
+ /** Cleanup function — called on destroy */
222
+ destroy?(): void;
223
+ /** Methods this plugin adds to the public API */
224
+ readonly methods?: readonly string[];
225
+ /** Plugins this plugin conflicts with (cannot be combined) */
226
+ readonly conflicts?: readonly string[];
227
+ }
228
+ /** Factory function that returns a plugin */
229
+ export type PluginFactory<T extends VListItem = VListItem> = VListPlugin<T>;
230
+ /** Chainable builder interface */
231
+ export interface VListBuilder<T extends VListItem = VListItem> {
232
+ /** Register a feature plugin. Chainable. */
233
+ use(plugin: VListPlugin<T>): VListBuilder<T>;
234
+ /** Materialize the virtual list. Creates DOM, initializes plugins, returns API. */
235
+ build(): BuiltVList<T>;
236
+ }
237
+ /** Base API always available from builder (data methods, scroll methods, events, lifecycle) */
238
+ export interface BuiltVList<T extends VListItem = VListItem> {
239
+ /** The root DOM element */
240
+ readonly element: HTMLElement;
241
+ /** Current items */
242
+ readonly items: readonly T[];
243
+ /** Total item count */
244
+ readonly total: number;
245
+ setItems: (items: T[]) => void;
246
+ appendItems: (items: T[]) => void;
247
+ prependItems: (items: T[]) => void;
248
+ updateItem: (id: string | number, updates: Partial<T>) => void;
249
+ removeItem: (id: string | number) => void;
250
+ reload: () => Promise<void>;
251
+ scrollToIndex: (index: number, alignOrOptions?: "start" | "center" | "end" | ScrollToOptions) => void;
252
+ scrollToItem: (id: string | number, alignOrOptions?: "start" | "center" | "end" | ScrollToOptions) => void;
253
+ cancelScroll: () => void;
254
+ getScrollPosition: () => number;
255
+ on: <K extends keyof VListEvents<T>>(event: K, handler: EventHandler<VListEvents<T>[K]>) => Unsubscribe;
256
+ off: <K extends keyof VListEvents<T>>(event: K, handler: EventHandler<VListEvents<T>[K]>) => void;
257
+ destroy: () => void;
258
+ select?: (...ids: Array<string | number>) => void;
259
+ deselect?: (...ids: Array<string | number>) => void;
260
+ toggleSelect?: (id: string | number) => void;
261
+ selectAll?: () => void;
262
+ clearSelection?: () => void;
263
+ getSelected?: () => Array<string | number>;
264
+ getSelectedItems?: () => T[];
265
+ getScrollSnapshot?: () => ScrollSnapshot;
266
+ restoreScroll?: (snapshot: ScrollSnapshot) => void;
267
+ [key: string]: unknown;
268
+ }
269
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/builder/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ var z=16000000;var Ny=(j,K,J,y)=>{if(y===0)return 0;if(!j.isVariable())return Math.ceil(J/j.getHeight(0));let N=0,Q=0,q=K;while(q<y&&Q<J)Q+=j.getHeight(q),N++,q++;return Math.max(1,N)},n=(j,K,J)=>{if(J===0)return 0;if(!j.isVariable())return Math.floor(K/j.getHeight(0));let y=0,N=0;for(let Q=J-1;Q>=0;Q--){let q=j.getHeight(Q);if(N+q>K)break;N+=q,y++}return Math.max(y,1)},l=(j,K,J)=>{if(J===0)return 0;let y=Math.floor(K),N=K-y,Q=Math.max(0,Math.min(y,J-1));return j.getOffset(Q)+N*j.getHeight(Q)};var P=(j,K)=>{let J=K.getTotalHeight(),y=J>z,N=y?z:J,Q=J>0?N/J:1;return{isCompressed:y,actualHeight:J,virtualHeight:N,ratio:Q}},r=(j,K,J,y,N,Q)=>{if(y===0||K===0)return Q.start=0,Q.end=-1,Q;if(!N.isCompressed){let X=J.indexAtOffset(j),W=J.indexAtOffset(j+K);if(W<y-1)W++;return Q.start=Math.max(0,X),Q.end=Math.min(y-1,Math.max(0,W)),Q}let{virtualHeight:q}=N,V=j/q*y,_=Math.floor(V),M=Ny(J,Math.max(0,_),K,y),G=Math.ceil(V)+M,U=q-K-j;if(U<=K&&U>=-1){let X=n(J,K,y),W=Math.max(0,y-X),$=Math.max(0,Math.min(1,1-U/K));_=Math.floor(_+(W-_)*$),G=U<=1?y-1:Math.min(y-1,_+M)}return Q.start=Math.max(0,_),Q.end=Math.min(y-1,Math.max(0,G)),Q},Gy=(j,K,J,y)=>{if(J===0)return y.start=0,y.end=-1,y;return y.start=Math.max(0,j.start-K),y.end=Math.min(J-1,j.end+K),y},c=(j,K,J,y,N,Q,q)=>{if(!Q.isCompressed||y===0)return J.getOffset(j);let{virtualHeight:O}=Q,V=O-N,_=V-K;if(_<=N&&_>=-1){if(K>=V-1){let F=J.getTotalHeight()-J.getOffset(j);return N-F}let Y=n(J,N,y),U=Math.max(0,y-Y),W=K/O*y,$=Math.max(0,Math.min(1,1-_/N)),B=J.getOffset(j)-J.getOffset(U),A=J.getOffset(j)-l(J,W,y);return A+(B-A)*$}let G=K/O*y;return J.getOffset(j)-l(J,G,y)},a=(j,K,J,y,N,Q="start")=>{if(y===0)return 0;let q;if(N.isCompressed){if(Q==="end"&&j===y-1)return Math.max(0,N.virtualHeight-J);q=j/y*N.virtualHeight}else q=K.getOffset(j);let O=K.getHeight(j);switch(Q){case"center":q-=(J-O)/2;break;case"end":q-=J-O;break}let V=N.virtualHeight-J;return Math.max(0,Math.min(q,V))},Uy=(j,K,J,y)=>{if(J===0)return 0;if(y.isCompressed){let N=j/y.virtualHeight;return Math.floor(N*J)}return K.indexAtOffset(j)},Dy=(j,K)=>{if(typeof K==="number")return j*K>z;return K.getTotalHeight()>z},_y=(j)=>{if(j<=0)return 0;return Math.floor(z/j)},Ey=(j,K)=>{let J=P(j,K);if(!J.isCompressed)return`No compression needed (${j} items, ${(J.actualHeight/1e6).toFixed(2)}M px)`;return`Compressed to ${(J.ratio*100).toFixed(1)}% (${j} items, ${(J.actualHeight/1e6).toFixed(1)}M px → ${(J.virtualHeight/1e6).toFixed(1)}M px virtual)`};var i=(j,K,J={},y="vlist",N=!1)=>{let{autoHide:Q=!0,autoHideDelay:q=1000,minThumbSize:O=30,showOnHover:V=!0,hoverZoneWidth:_=16,showOnViewportEnter:M=!0}=J,G=0,Y=0,U=0,X=0,W=!1,$=!1,B=0,A=0,F=0,f=null,T=!1,Z=null,C=null,Qy=N?"width":"height",o=N?"translateX":"translateY",u=N?(E)=>E.clientX:(E)=>E.clientY,Yy=N?"left":"top",D=document.createElement("div"),R=document.createElement("div"),L=V?document.createElement("div"):null,$y=()=>{if(D.className=`${y}-scrollbar`,R.className=`${y}-scrollbar-thumb`,N)D.classList.add(`${y}-scrollbar--horizontal`);if(D.appendChild(R),j.appendChild(D),L){if(L.className=`${y}-scrollbar-hover`,N)L.classList.add(`${y}-scrollbar-hover--horizontal`),L.style.height=`${_}px`;else L.style.width=`${_}px`;j.appendChild(L)}},S=()=>{if(f)clearTimeout(f),f=null},v=()=>{if(!Q)return;S(),f=setTimeout(d,q)},H=()=>{if(G<=Y)return;if(S(),!T)D.classList.add(`${y}-scrollbar--visible`),T=!0;if(Q&&!W&&!$)v()},d=()=>{if(W||$)return;D.classList.remove(`${y}-scrollbar--visible`),T=!1},Wy=(E,w)=>{G=E,Y=w;let b=G>Y;if(D.style.display=b?"":"none",!b){d();return}let k=Y/G;U=Math.max(O,k*Y),R.style[Qy]=`${U}px`,X=Y-U,e(F)},e=(E)=>{if(F=E,G<=Y||X<=0)return;let w=G-Y,k=Math.min(1,Math.max(0,E/w))*X;R.style.transform=`${o}(${k}px)`},t=(E)=>{if(E.target===R)return;let w=D.getBoundingClientRect(),m=u(E)-w[Yy]-U/2,Ky=Math.max(0,Math.min(m,X))/X,h=G-Y,qy=Ky*h;K(qy),H()},yy=(E)=>{E.preventDefault(),E.stopPropagation(),W=!0,B=u(E),A=F,S(),D.classList.add(`${y}-scrollbar--dragging`),document.addEventListener("mousemove",x),document.addEventListener("mouseup",g)},x=(E)=>{if(!W)return;let w=u(E)-B,b=X>0?w/X:0,k=G-Y,m=b*k,s=Math.max(0,Math.min(A+m,k)),h=s/k*X;if(R.style.transform=`${o}(${h}px)`,C=s,Z===null)Z=requestAnimationFrame(()=>{if(C!==null)K(C);Z=null})},g=()=>{if(W=!1,Z!==null)cancelAnimationFrame(Z),Z=null;if(C!==null)K(C),C=null;if(D.classList.remove(`${y}-scrollbar--dragging`),Q&&!$)v();document.removeEventListener("mousemove",x),document.removeEventListener("mouseup",g)},jy=()=>{if(M)H()},Jy=()=>{if(!W){if($=!1,Q)v()}},p=()=>{$=!0,S(),H()},I=()=>{if($=!1,!W&&Q)v()},Xy=()=>{if(S(),Z!==null)cancelAnimationFrame(Z),Z=null;if(D.removeEventListener("click",t),D.removeEventListener("mouseenter",p),D.removeEventListener("mouseleave",I),R.removeEventListener("mousedown",yy),j.removeEventListener("mouseenter",jy),j.removeEventListener("mouseleave",Jy),document.removeEventListener("mousemove",x),document.removeEventListener("mouseup",g),L){if(L.removeEventListener("mouseenter",p),L.removeEventListener("mouseleave",I),L.parentNode)L.parentNode.removeChild(L)}if(D.parentNode)D.parentNode.removeChild(D)};if($y(),D.addEventListener("click",t),D.addEventListener("mouseenter",p),D.addEventListener("mouseleave",I),R.addEventListener("mousedown",yy),j.addEventListener("mouseenter",jy),j.addEventListener("mouseleave",Jy),L)L.addEventListener("mouseenter",p),L.addEventListener("mouseleave",I);return{show:H,hide:d,updateBounds:Wy,updatePosition:e,isVisible:()=>T,destroy:Xy}};var Ly=()=>{let j=null,K=0,J=!1;return{name:"withCompression",priority:20,setup(y){let{dom:N,config:Q}=y,{classPrefix:q,horizontal:O}=Q,V=y.updateCompressionMode.bind(y),_=()=>{let G=y.getVirtualTotal(),Y=P(G,y.heightCache);if(Y.isCompressed&&!J){J=!0,y.scrollController.enableCompression(Y),y.updateContentSize(Y.virtualHeight),y.setScrollFns(()=>K,($)=>{K=$});let U=N.viewport,X=($)=>{$.preventDefault();let B=Y.virtualHeight-y.state.viewportState.containerHeight;K=Math.max(0,Math.min(K+$.deltaY,B)),y.scrollController.scrollTo(K)};if(U.addEventListener("wheel",X,{passive:!1}),y.destroyHandlers.push(()=>{U.removeEventListener("wheel",X)}),!N.viewport.querySelector(`.${q}-scrollbar-track`)){if(j=i(N.viewport,(B)=>y.scrollController.scrollTo(B),{},q,O),!N.viewport.classList.contains(`${q}-viewport--custom-scrollbar`))N.viewport.classList.add(`${q}-viewport--custom-scrollbar`);j.updateBounds(Y.virtualHeight,y.state.viewportState.containerHeight);let $=j;y.afterScroll.push((B,A)=>{if($)$.updatePosition(B),$.show()}),y.resizeHandlers.push((B,A)=>{if($){let F=y.getCachedCompression();$.updateBounds(F.virtualHeight,y.state.viewportState.containerHeight)}})}}else if(!Y.isCompressed&&J)J=!1,y.scrollController.disableCompression(),y.updateContentSize(Y.actualHeight);else if(Y.isCompressed)y.scrollController.updateConfig({compression:Y}),y.updateContentSize(Y.virtualHeight);if(j)j.updateBounds(Y.virtualHeight,y.state.viewportState.containerHeight);y.state.cachedCompression={state:Y,totalItems:G}};y.updateCompressionMode=_;let M=y.getCachedCompression.bind(y);y.getCachedCompression=()=>{if(y.state.cachedCompression)return y.state.cachedCompression.state;return M()},y.setVisibleRangeFn((G,Y,U,X,W)=>{let $=P(X,U);r(G,Y,U,X,$,W)}),y.setScrollToPosFn((G,Y,U,X,W)=>{let $=P(X,Y);return a(G,Y,U,X,$,W)}),y.setPositionElementFn((G,Y)=>{let U=y.getVirtualTotal(),X=P(U,y.heightCache);if(X.isCompressed){let W=Math.round(c(Y,y.scrollController.getScrollTop(),y.heightCache,U,y.state.viewportState.containerHeight,X)),$=y.config.horizontal;G.style.transform=$?`translateX(${W}px)`:`translateY(${W}px)`}else{let W=Math.round(y.heightCache.getOffset(Y)),$=y.config.horizontal;G.style.transform=$?`translateX(${W}px)`:`translateY(${W}px)`}}),_(),y.destroyHandlers.push(()=>{if(j)j.destroy(),j=null})},destroy(){if(j)j.destroy(),j=null}}};export{Ly as withCompression,Dy as needsCompression,_y as getMaxItemsWithoutCompression,P as getCompressionState,Ey as getCompressionInfo,Uy as calculateIndexFromScrollPosition,r as calculateCompressedVisibleRange,a as calculateCompressedScrollToIndex,Gy as calculateCompressedRenderRange,c as calculateCompressedItemPosition,z as MAX_VIRTUAL_HEIGHT};
@@ -0,0 +1,65 @@
1
+ /**
2
+ * vlist - Constants
3
+ * All default values and magic numbers in one place
4
+ */
5
+ /** Default number of extra items to render outside viewport */
6
+ export declare const DEFAULT_OVERSCAN = 3;
7
+ /** Default CSS class prefix */
8
+ export declare const DEFAULT_CLASS_PREFIX = "vlist";
9
+ /** Distance from bottom (in pixels) to trigger infinite scroll */
10
+ export declare const LOAD_MORE_THRESHOLD = 200;
11
+ /** Default number of items to load per request */
12
+ export declare const INITIAL_LOAD_SIZE = 50;
13
+ /** Default page size for data manager */
14
+ export declare const DEFAULT_PAGE_SIZE = 50;
15
+ /**
16
+ * Velocity threshold above which data loading is cancelled (px/ms)
17
+ * When scrolling faster than this, we skip loading data since the user
18
+ * is likely scrolling quickly past content they don't want to see.
19
+ * Default: 25 px/ms (same as mtrl-addons viewport)
20
+ */
21
+ export declare const CANCEL_LOAD_VELOCITY_THRESHOLD = 15;
22
+ /**
23
+ * Velocity threshold for preloading (px/ms)
24
+ * When scrolling faster than this but slower than CANCEL_LOAD_VELOCITY_THRESHOLD,
25
+ * we preload extra items in the scroll direction to reduce placeholder flashing.
26
+ * Default: 2 px/ms (medium scroll speed)
27
+ */
28
+ export declare const PRELOAD_VELOCITY_THRESHOLD = 2;
29
+ /**
30
+ * Number of extra items to preload ahead of scroll direction
31
+ * Only applies when velocity is between PRELOAD_VELOCITY_THRESHOLD and
32
+ * CANCEL_LOAD_VELOCITY_THRESHOLD.
33
+ * Default: 50 items
34
+ */
35
+ export declare const PRELOAD_ITEMS_AHEAD = 50;
36
+ /**
37
+ * Maximum virtual height in pixels
38
+ * Most browsers support ~16.7M pixels, we use 16M for safety margin
39
+ */
40
+ export declare const MAX_VIRTUAL_HEIGHT = 16000000;
41
+ /** Default auto-hide behavior */
42
+ export declare const DEFAULT_SCROLLBAR_AUTO_HIDE = true;
43
+ /** Default auto-hide delay in milliseconds */
44
+ export declare const DEFAULT_SCROLLBAR_AUTO_HIDE_DELAY = 1000;
45
+ /** Default minimum thumb size in pixels */
46
+ export declare const DEFAULT_SCROLLBAR_MIN_THUMB_SIZE = 30;
47
+ /** Default character used for masking text in placeholders */
48
+ export declare const DEFAULT_MASK_CHARACTER = "\u2588";
49
+ /** Maximum items to sample for placeholder structure analysis */
50
+ export declare const DEFAULT_MAX_SAMPLE_SIZE = 20;
51
+ /** Internal flag to identify placeholder items */
52
+ export declare const PLACEHOLDER_FLAG = "_isPlaceholder";
53
+ /** Prefix for placeholder item IDs */
54
+ export declare const PLACEHOLDER_ID_PREFIX = "__placeholder_";
55
+ /** Default chunk size for sparse storage */
56
+ export declare const DEFAULT_CHUNK_SIZE = 100;
57
+ /** Default maximum cached items before eviction */
58
+ export declare const DEFAULT_MAX_CACHED_ITEMS = 10000;
59
+ /** Buffer for eviction (keep extra items around visible range) */
60
+ export declare const DEFAULT_EVICTION_BUFFER = 500;
61
+ /** Idle timeout for scroll detection (ms) */
62
+ export declare const SCROLL_IDLE_TIMEOUT = 150;
63
+ /** Default wheel sensitivity multiplier */
64
+ export declare const DEFAULT_WHEEL_SENSITIVITY = 1;
65
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,+DAA+D;AAC/D,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAElC,+BAA+B;AAC/B,eAAO,MAAM,oBAAoB,UAAU,CAAC;AAM5C,kEAAkE;AAClE,eAAO,MAAM,mBAAmB,MAAM,CAAC;AAEvC,kDAAkD;AAClD,eAAO,MAAM,iBAAiB,KAAK,CAAC;AAEpC,yCAAyC;AACzC,eAAO,MAAM,iBAAiB,KAAK,CAAC;AAMpC;;;;;GAKG;AACH,eAAO,MAAM,8BAA8B,KAAK,CAAC;AAEjD;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,IAAI,CAAC;AAE5C;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,KAAK,CAAC;AAMtC;;;GAGG;AACH,eAAO,MAAM,kBAAkB,WAAa,CAAC;AAM7C,iCAAiC;AACjC,eAAO,MAAM,2BAA2B,OAAO,CAAC;AAEhD,8CAA8C;AAC9C,eAAO,MAAM,iCAAiC,OAAO,CAAC;AAEtD,2CAA2C;AAC3C,eAAO,MAAM,gCAAgC,KAAK,CAAC;AAMnD,8DAA8D;AAC9D,eAAO,MAAM,sBAAsB,WAAM,CAAC;AAE1C,iEAAiE;AACjE,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAE1C,kDAAkD;AAClD,eAAO,MAAM,gBAAgB,mBAAmB,CAAC;AAEjD,sCAAsC;AACtC,eAAO,MAAM,qBAAqB,mBAAmB,CAAC;AAMtD,4CAA4C;AAC5C,eAAO,MAAM,kBAAkB,MAAM,CAAC;AAEtC,mDAAmD;AACnD,eAAO,MAAM,wBAAwB,QAAS,CAAC;AAE/C,kEAAkE;AAClE,eAAO,MAAM,uBAAuB,MAAM,CAAC;AAM3C,6CAA6C;AAC7C,eAAO,MAAM,mBAAmB,MAAM,CAAC;AAEvC,2CAA2C;AAC3C,eAAO,MAAM,yBAAyB,IAAI,CAAC"}
@@ -0,0 +1 @@
1
+ var Yj=(B,X)=>{if(typeof B==="number"){let q=X;return{getOffset:(J)=>J*B,getHeight:()=>B,indexAtOffset:(J)=>{if(q===0||B===0)return 0;return Math.max(0,Math.min(Math.floor(J/B),q-1))},getTotalHeight:()=>q*B,getTotal:()=>q,rebuild:(J)=>{q=J}}}let Y=X,U=new Float64Array(0),$=(q)=>{Y=q,U=new Float64Array(q+1),U[0]=0;for(let J=0;J<q;J++)U[J+1]=U[J]+B(J)};return $(X),{getOffset:(q)=>{if(q<=0)return 0;if(q>=Y)return U[Y];return U[q]},getHeight:(q)=>B(q),indexAtOffset:(q)=>{if(Y===0)return 0;if(q<=0)return 0;if(q>=U[Y])return Y-1;let J=0,F=Y-1;while(J<F){let N=J+F+1>>>1;if(U[N]<=q)J=N;else F=N-1}return J},getTotalHeight:()=>U[Y]??0,getTotal:()=>Y,rebuild:(q)=>$(q)}},Zj=()=>{let B={},X=(q,J)=>{if(!B[q])B[q]=new Set;return B[q].add(J),()=>Y(q,J)},Y=(q,J)=>{B[q]?.delete(J)};return{on:X,off:Y,emit:(q,J)=>{B[q]?.forEach((F)=>{try{F(J)}catch(N){console.error(`[vlist] Error in "${q}" handler:`,N)}})},clear:()=>{for(let q in B)delete B[q]}}},_j=(B)=>{if(typeof B==="string"){let X=document.querySelector(B);if(!X)throw Error(`[vlist] Container not found: ${B}`);return X}return B},$j=(B,X,Y)=>{let U=document.createElement("div");if(U.className=X,U.setAttribute("role","listbox"),U.setAttribute("tabindex","0"),Y)U.setAttribute("aria-label",Y);let $=document.createElement("div");$.className=`${X}-viewport`,$.style.overflow="auto",$.style.height="100%",$.style.width="100%";let q=document.createElement("div");q.className=`${X}-content`,q.style.position="relative",q.style.width="100%";let J=document.createElement("div");return J.className=`${X}-items`,J.style.position="relative",J.style.width="100%",q.appendChild(J),$.appendChild(q),U.appendChild($),B.appendChild(U),{root:U,viewport:$,content:q,items:J}},Qj=(B=100)=>{let X=[];return{acquire:()=>{let q=X.pop();if(q)return q;let J=document.createElement("div");return J.setAttribute("role","option"),J},release:(q)=>{if(X.length<B)q.className="",q.textContent="",q.removeAttribute("style"),q.removeAttribute("data-index"),q.removeAttribute("data-id"),X.push(q)},clear:()=>{X.length=0}}},Vj=(B,X,Y,U,$)=>{if(U===0){$.start=0,$.end=0;return}let q=Y.indexAtOffset(B),J=q,F=Y.getOffset(q)-B;while(J<U-1&&F<X)F+=Y.getHeight(J),J++;$.start=q,$.end=Math.min(J,U-1)},Lj=(B,X,Y,U)=>{U.start=Math.max(0,B.start-X),U.end=Math.min(Y-1,B.end+X)},kj=(B,X,Y,U,$)=>{if(U===0)return 0;let q=Math.max(0,Math.min(B,U-1)),J=X.getOffset(q),F=X.getHeight(q),N=Math.max(0,X.getTotalHeight()-Y),k;switch($){case"center":k=J-(Y-F)/2;break;case"end":k=J-Y+F;break;default:k=J}return Math.max(0,Math.min(k,N))},Fj=(B)=>B<0.5?2*B*B:-1+(4-2*B)*B,Nj=0,Aj=(B)=>{if(!B.container)throw Error("[vlist] container is required");if(!B.item)throw Error("[vlist] item configuration is required");if(B.item.height==null)throw Error("[vlist] item.height is required");if(typeof B.item.height==="number"&&B.item.height<=0)throw Error("[vlist] item.height must be positive");if(typeof B.item.height!=="number"&&typeof B.item.height!=="function")throw Error("[vlist] item.height must be a number or (index) => number");if(!B.item.template)throw Error("[vlist] item.template is required");let{item:X,items:Y,overscan:U=3,classPrefix:$="vlist",scrollElement:q,ariaLabel:J}=B,{height:F,template:N}=X,k=!!q,_=Y?[...Y]:[],y=!1,R=null,D=0,l=`${$}-${Nj++}`,o=_j(B.container),V=$j(o,$,J),W=Zj(),A=Yj(F,_.length),I=Qj();if(k)V.root.style.overflow="visible",V.root.style.height="auto",V.viewport.style.overflow="visible",V.viewport.style.height="auto";let E=k?window.innerHeight:V.viewport.clientHeight,h={start:0,end:0},M={start:0,end:0},C={start:-1,end:-1},b=new Map,f={selected:!1,focused:!1},n=`${$}-item`,T="",p=(j,K)=>{if(typeof K==="string")j.innerHTML=K;else j.replaceChildren(K)},c=(j,K)=>{j.style.transform=`translateY(${Math.round(A.getOffset(K))}px)`},i=(j,K)=>{let G=I.acquire();return G.className=n,G.style.height=`${A.getHeight(j)}px`,G.dataset.index=String(j),G.dataset.id=String(K.id),G.ariaSelected="false",G.id=`${l}-item-${j}`,T=String(_.length),G.setAttribute("aria-setsize",T),G.setAttribute("aria-posinset",String(j+1)),p(G,N(K,j,f)),c(G,j),G},v=()=>{V.content.style.height=`${A.getTotalHeight()}px`},P=()=>{if(y)return;if(Vj(D,E,A,_.length,h),Lj(h,U,_.length,M),M.start===C.start&&M.end===C.end)return;let j=String(_.length),K=j!==T;T=j;for(let[Z,L]of b)if(Z<M.start||Z>M.end)L.remove(),I.release(L),b.delete(Z);let G=document.createDocumentFragment(),Q=[];for(let Z=M.start;Z<=M.end;Z++){let L=_[Z];if(!L)continue;let z=b.get(Z);if(z){let H=z.dataset.id,w=String(L.id);if(H!==w)p(z,N(L,Z,f)),z.dataset.id=w,z.style.height=`${A.getHeight(Z)}px`;if(c(z,Z),K)z.setAttribute("aria-setsize",T)}else{let H=i(Z,L);G.appendChild(H),Q.push({index:Z,element:H})}}if(Q.length>0){V.items.appendChild(G);for(let{index:Z,element:L}of Q)b.set(Z,L)}C.start=M.start,C.end=M.end,W.emit("range:change",{range:{start:M.start,end:M.end}})},t=()=>{C.start=-1,C.end=-1,P()},O=null,m=()=>{if(y)return;let j=k?Math.max(0,q.scrollY-V.viewport.getBoundingClientRect().top-q.scrollY+window.scrollY):V.viewport.scrollTop,K=k?Math.max(0,q.scrollY+V.viewport.getBoundingClientRect().top*-1):j,G=K>=D?"down":"up";if(!V.root.classList.contains(`${$}--scrolling`))V.root.classList.add(`${$}--scrolling`);if(D=K,P(),W.emit("scroll",{scrollTop:K,direction:G}),O)clearTimeout(O);O=setTimeout(()=>{V.root.classList.remove(`${$}--scrolling`)},150)},d=k?q:V.viewport;d.addEventListener("scroll",m,{passive:!0});let s=(j)=>{if(y)return;let G=j.target.closest("[data-index]");if(!G)return;let Q=parseInt(G.dataset.index??"-1",10);if(Q<0)return;let Z=_[Q];if(!Z)return;W.emit("item:click",{item:Z,index:Q,event:j})},e=(j)=>{if(y)return;let G=j.target.closest("[data-index]");if(!G)return;let Q=parseInt(G.dataset.index??"-1",10);if(Q<0)return;let Z=_[Q];if(!Z)return;W.emit("item:dblclick",{item:Z,index:Q,event:j})};V.items.addEventListener("click",s),V.items.addEventListener("dblclick",e);let a=new ResizeObserver((j)=>{if(y||k)return;for(let K of j){let G=K.contentRect.height;if(Math.abs(G-E)>1)E=G,v(),P(),W.emit("resize",{height:G,width:K.contentRect.width})}});a.observe(V.viewport);let u=null;if(k)u=()=>{if(y)return;let j=window.innerHeight;if(Math.abs(j-E)>1)E=j,v(),P(),W.emit("resize",{height:j,width:window.innerWidth})},window.addEventListener("resize",u);let S=()=>{if(R!==null)cancelAnimationFrame(R),R=null},jj=(j)=>{if(typeof j==="string")return{align:j,behavior:"auto",duration:300};if(j&&typeof j==="object")return{align:j.align??"start",behavior:j.behavior??"auto",duration:j.duration??300};return{align:"start",behavior:"auto",duration:300}},g=(j)=>{if(k){let G=V.viewport.getBoundingClientRect().top+window.scrollY;q.scrollTo(0,G+j)}else V.viewport.scrollTop=j},qj=(j,K,G)=>{if(S(),Math.abs(K-j)<1){g(K),D=K,P();return}let Q=performance.now(),Z=(L)=>{let z=L-Q,H=Math.min(z/G,1),w=j+(K-j)*Fj(H);if(g(w),D=w,P(),H<1)R=requestAnimationFrame(Z);else R=null};R=requestAnimationFrame(Z)},r=(j,K)=>{let{align:G,behavior:Q,duration:Z}=jj(K),L=kj(j,A,E,_.length,G);if(Q==="smooth")qj(D,L,Z);else S(),g(L)},x=()=>{A.rebuild(_.length),v(),t()},Bj=(j)=>{_=[...j],x()},Gj=(j)=>{_=[..._,...j],x()},Jj=(j)=>{_=[...j,..._],x()},Kj=(j,K)=>{let G=_.findIndex((Z)=>Z.id===j);if(G<0)return;_[G]={..._[G],...K};let Q=b.get(G);if(Q)p(Q,N(_[G],G,f)),Q.dataset.id=String(_[G].id)},Uj=(j)=>{_=_.filter((K)=>K.id!==j),x()},Xj=()=>{if(y)return;if(y=!0,S(),d.removeEventListener("scroll",m),V.items.removeEventListener("click",s),a.disconnect(),u)window.removeEventListener("resize",u);if(O)clearTimeout(O);for(let[,j]of b)j.remove(),I.release(j);b.clear(),I.clear(),W.clear(),V.root.remove()};return v(),P(),{get element(){return V.root},get items(){return _},get total(){return _.length},setItems:Bj,appendItems:Gj,prependItems:Jj,updateItem:Kj,removeItem:Uj,scrollToIndex:r,scrollToItem:(j,K)=>{let G=_.findIndex((Q)=>Q.id===j);if(G>=0)r(G,K)},cancelScroll:S,getScrollPosition:()=>D,getScrollSnapshot:()=>{if(_.length===0)return{index:0,offsetInItem:0};let j=A.indexAtOffset(D),K=Math.max(0,D-A.getOffset(j));return{index:j,offsetInItem:K}},restoreScroll:(j)=>{if(_.length===0)return;let K=Math.max(0,Math.min(j.index,_.length-1)),G=Math.max(0,A.getTotalHeight()-E),Q=Math.max(0,Math.min(A.getOffset(K)+j.offsetInItem,G));if(k){let L=V.viewport.getBoundingClientRect().top+window.scrollY;window.scrollTo({top:L+Q,behavior:"auto"})}else V.viewport.scrollTo({top:Q,behavior:"auto"});D=Q,P()},on:(j,K)=>W.on(j,K),off:(j,K)=>W.off(j,K),destroy:Xj}};export{Aj as createVList};
@@ -0,0 +1,104 @@
1
+ /**
2
+ * vlist/core-light - Ultra-Lightweight Virtual List (Fixed Heights Only)
3
+ *
4
+ * An even lighter variant of vlist/core that only supports fixed-height items.
5
+ * Use this when all items have the same height and you need the absolute smallest bundle.
6
+ *
7
+ * ~3-4 KB minified vs ~10 KB for vlist/core vs ~42 KB for the full bundle.
8
+ *
9
+ * Supports:
10
+ * - Fixed item heights only
11
+ * - Container scrolling only
12
+ * - Single item selection
13
+ * - Instant scrollToIndex (no animation)
14
+ * - setItems / appendItems / prependItems
15
+ * - Events (scroll, range:change, selection:change)
16
+ * - DOM element pooling & DocumentFragment batching
17
+ *
18
+ * Does NOT include (use vlist/core or full `vlist` if needed):
19
+ * - Variable item heights
20
+ * - Window scrolling
21
+ * - Smooth scroll animation
22
+ * - Single item mutations (updateItem/removeItem)
23
+ * - Click event handling
24
+ * - ResizeObserver / auto-resize
25
+ * - Validation
26
+ * - Selection / keyboard navigation
27
+ * - Groups / sticky headers
28
+ * - Compression (lists > ~100K items)
29
+ * - Custom scrollbar
30
+ * - Async data adapter / placeholders
31
+ */
32
+ /** Base item interface — must have an id */
33
+ export interface VListItem {
34
+ id: string | number;
35
+ [key: string]: unknown;
36
+ }
37
+ /** State passed to template */
38
+ export interface ItemState {
39
+ selected: boolean;
40
+ focused: boolean;
41
+ }
42
+ /** Item template function */
43
+ export type ItemTemplate<T extends VListItem = VListItem> = (item: T, index: number, state: ItemState) => string | HTMLElement;
44
+ /** Visible range */
45
+ export interface Range {
46
+ start: number;
47
+ end: number;
48
+ }
49
+ /** Event handler / unsubscribe */
50
+ export type EventHandler<T> = (payload: T) => void;
51
+ export type Unsubscribe = () => void;
52
+ /** Core event map */
53
+ export interface CoreEvents<T extends VListItem = VListItem> {
54
+ scroll: {
55
+ scrollTop: number;
56
+ direction: "up" | "down";
57
+ };
58
+ "range:change": {
59
+ range: Range;
60
+ };
61
+ "selection:change": {
62
+ selectedId: string | number | null;
63
+ };
64
+ }
65
+ /** Item configuration */
66
+ export interface CoreItemConfig<T extends VListItem = VListItem> {
67
+ height: number;
68
+ template: ItemTemplate<T>;
69
+ }
70
+ /** Core configuration */
71
+ export interface CoreConfig<T extends VListItem = VListItem> {
72
+ container: HTMLElement | string;
73
+ item: CoreItemConfig<T>;
74
+ items?: T[];
75
+ overscan?: number;
76
+ classPrefix?: string;
77
+ ariaLabel?: string;
78
+ }
79
+ /** Core VList instance */
80
+ export interface VListCore<T extends VListItem = VListItem> {
81
+ readonly element: HTMLElement;
82
+ readonly items: readonly T[];
83
+ readonly total: number;
84
+ setItems(items: T[]): void;
85
+ appendItems(items: T[]): void;
86
+ prependItems(items: T[]): void;
87
+ scrollToIndex(index: number, align?: "start" | "center" | "end"): void;
88
+ getScrollPosition(): number;
89
+ selectItem(id: string | number): void;
90
+ deselectItem(): void;
91
+ getSelectedId(): string | number | null;
92
+ on<K extends keyof CoreEvents<T>>(event: K, handler: EventHandler<CoreEvents<T>[K]>): Unsubscribe;
93
+ off<K extends keyof CoreEvents<T>>(event: K, handler: EventHandler<CoreEvents<T>[K]>): void;
94
+ destroy(): void;
95
+ }
96
+ /**
97
+ * Create a lightweight virtual list (core).
98
+ *
99
+ * This is the minimal-footprint alternative to `createVList` from `vlist`.
100
+ * Same essential behaviour, but without selection, groups, compression,
101
+ * custom scrollbar, or async data adapter support.
102
+ */
103
+ export declare const createVList: <T extends VListItem = VListItem>(config: CoreConfig<T>) => VListCore<T>;
104
+ //# sourceMappingURL=core-light.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"core-light.d.ts","sourceRoot":"","sources":["../src/core-light.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ var e=(B,K)=>{let W=K;return{getOffset:(J)=>J*B,getHeight:()=>B,indexAtOffset:(J)=>{if(W===0||B===0)return 0;return Math.max(0,Math.min(Math.floor(J/B),W-1))},getTotalHeight:()=>W*B,getTotal:()=>W,rebuild:(J)=>{W=J}}},jj=()=>{let B={},K=(j,Q)=>{if(!B[j])B[j]=new Set;return B[j].add(Q),()=>W(j,Q)},W=(j,Q)=>{B[j]?.delete(Q)};return{on:K,off:W,emit:(j,Q)=>{B[j]?.forEach((N)=>{try{N(Q)}catch(Z){console.error(`[vlist] Error in "${j}" handler:`,Z)}})},clear:()=>{for(let j in B)delete B[j]}}},qj=(B)=>{if(typeof B==="string"){let K=document.querySelector(B);if(!K)throw Error(`[vlist] Container not found: ${B}`);return K}return B},Bj=(B,K,W)=>{let J=document.createElement("div");if(J.className=K,J.setAttribute("role","listbox"),J.setAttribute("tabindex","0"),W)J.setAttribute("aria-label",W);let G=document.createElement("div");G.className=`${K}-viewport`,G.style.overflow="auto",G.style.height="100%",G.style.width="100%";let j=document.createElement("div");j.className=`${K}-content`,j.style.position="relative",j.style.width="100%";let Q=document.createElement("div");return Q.className=`${K}-items`,Q.style.position="relative",Q.style.width="100%",j.appendChild(Q),G.appendChild(j),J.appendChild(G),B.appendChild(J),{root:J,viewport:G,content:j,items:Q}},Gj=(B=100)=>{let K=[];return{acquire:()=>{let j=K.pop();if(j)return j;let Q=document.createElement("div");return Q.setAttribute("role","option"),Q},release:(j)=>{if(K.length<B)j.className="",j.textContent="",j.removeAttribute("style"),j.removeAttribute("data-index"),j.removeAttribute("data-id"),K.push(j)},clear:()=>{K.length=0}}},Jj=(B,K,W,J,G)=>{if(J===0){G.start=0,G.end=0;return}let j=W.indexAtOffset(B),Q=j,N=W.getOffset(j)-B;while(Q<J-1&&N<K)N+=W.getHeight(Q),Q++;G.start=j,G.end=Math.min(Q,J-1)},Kj=(B,K,W,J)=>{J.start=Math.max(0,B.start-K),J.end=Math.min(W-1,B.end+K)},Qj=0,Uj=(B)=>{let{item:K,items:W,overscan:J=3,classPrefix:G="vlist",ariaLabel:j}=B,{height:Q,template:N}=K,Z=W?[...W]:[],y=!1,H=0,O=null,h=`${G}-${Qj++}`,c=qj(B.container),$=Bj(c,G,j),D=jj(),F=e(Q,Z.length),b=Gj(),w=$.viewport.clientHeight,S={start:0,end:0},M={start:0,end:0},L={start:-1,end:-1},A=new Map,P={selected:!1,focused:!1},m=`${G}-item`,z="",v=(q,U)=>{if(typeof U==="string")q.innerHTML=U;else q.replaceChildren(U)},I=(q,U)=>{q.style.transform=`translateY(${Math.round(F.getOffset(U))}px)`},d=(q,U)=>{let X=b.acquire();X.className=m,X.style.height=`${F.getHeight(q)}px`,X.dataset.index=String(q),X.dataset.id=String(U.id),X.ariaSelected="false",X.id=`${h}-item-${q}`,z=String(Z.length),X.setAttribute("aria-setsize",z),X.setAttribute("aria-posinset",String(q+1));let V=U.id===O;if(P.selected=V,V)X.classList.add(`${G}-item--selected`);else X.classList.remove(`${G}-item--selected`);return v(X,N(U,q,P)),I(X,q),X},f=()=>{$.content.style.height=`${F.getTotalHeight()}px`},C=()=>{if(y)return;if(Jj(H,w,F,Z.length,S),Kj(S,J,Z.length,M),M.start===L.start&&M.end===L.end)return;let q=String(Z.length),U=q!==z;z=q;for(let[Y,k]of A)if(Y<M.start||Y>M.end)k.remove(),b.release(k),A.delete(Y);let X=document.createDocumentFragment(),V=[];for(let Y=M.start;Y<=M.end;Y++){let k=Z[Y];if(!k)continue;let _=A.get(Y);if(_){let T=_.dataset.id,p=String(k.id);if(T!==p)v(_,N(k,Y,P)),_.dataset.id=p,_.style.height=`${F.getHeight(Y)}px`;let g=k.id===O;if(P.selected=g,g)_.classList.add(`${G}-item--selected`);else _.classList.remove(`${G}-item--selected`);if(I(_,Y),U)_.setAttribute("aria-setsize",z)}else{let T=d(Y,k);X.appendChild(T),V.push({index:Y,element:T})}}if(V.length>0){$.items.appendChild(X);for(let{index:Y,element:k}of V)A.set(Y,k)}L.start=M.start,L.end=M.end,D.emit("range:change",{range:{start:M.start,end:M.end}})},u=()=>{L.start=-1,L.end=-1,C()},E=null,x=()=>{if(y)return;let q=$.viewport.scrollTop,U=Math.max(0,q),X=U>=H?"down":"up";if(!$.root.classList.contains(`${G}--scrolling`))$.root.classList.add(`${G}--scrolling`);if(H=U,C(),D.emit("scroll",{scrollTop:U,direction:X}),E)clearTimeout(E);E=setTimeout(()=>{$.root.classList.remove(`${G}--scrolling`)},150)};$.viewport.addEventListener("scroll",x,{passive:!0});let o=(q)=>{if(O===q)return;O=q,u(),D.emit("selection:change",{selectedId:O})},s=()=>{if(O===null)return;O=null,u(),D.emit("selection:change",{selectedId:null})},a=()=>O,r=(q,U="start")=>{let X=Math.max(0,Math.min(q,Z.length-1)),V=F.getOffset(X),Y=F.getHeight(X),k=Math.max(0,F.getTotalHeight()-w),_=V;if(U==="center")_=V-w/2+Y/2;else if(U==="end")_=V-w+Y;_=Math.max(0,Math.min(_,k)),$.viewport.scrollTop=_},R=()=>{F.rebuild(Z.length),f(),u()},l=(q)=>{Z=[...q],R()},n=(q)=>{Z=[...Z,...q],R()},i=(q)=>{Z=[...q,...Z],R()},t=()=>{if(y)return;if(y=!0,$.viewport.removeEventListener("scroll",x),E)clearTimeout(E);for(let[,q]of A)q.remove(),b.release(q);A.clear(),b.clear(),D.clear(),$.root.remove()};return f(),C(),{get element(){return $.root},get items(){return Z},get total(){return Z.length},setItems:l,appendItems:n,prependItems:i,scrollToIndex:r,getScrollPosition:()=>H,selectItem:o,deselectItem:s,getSelectedId:a,on:(q,U)=>D.on(q,U),off:(q,U)=>D.off(q,U),destroy:t}};export{Uj as createVList};