@tanstack/virtual-core 3.0.0-beta.42 → 3.0.0-beta.44

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.
@@ -8,5 +8,5 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
- !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).VirtualCore={})}(this,(function(e){"use strict";function t(){return t=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var o in n)Object.prototype.hasOwnProperty.call(n,o)&&(e[o]=n[o])}return e},t.apply(this,arguments)}function n(e,t,n){var o,r=[];return function(){var i;n.key&&null!=n.debug&&n.debug()&&(i=Date.now());var s,l=e(),a=l.length!==r.length||l.some((function(e,t){return r[t]!==e}));if(!a)return o;r=l,n.key&&null!=n.debug&&n.debug()&&(s=Date.now());for(var u=arguments.length,c=new Array(u),d=0;d<u;d++)c[d]=arguments[d];if(o=t.apply(void 0,l.concat([c])),null==n||null==n.onChange||n.onChange(o),n.key&&null!=n.debug&&n.debug()){var f=Math.round(100*(Date.now()-i))/100,h=Math.round(100*(Date.now()-s))/100,m=h/16,g=function(e,t){for(e=String(e);e.length<t;)e=" "+e;return e};console.info("%c⏱ "+g(h,5)+" /"+g(f,5)+" ms","\n font-size: .6rem;\n font-weight: bold;\n color: hsl("+Math.max(0,Math.min(120-120*m,120))+"deg 100% 31%);",null==n?void 0:n.key)}return o}}function o(e,t){if(void 0===e)throw new Error("Unexpected undefined"+(t?": "+t:""));return e}var r=function(e,t){return Math.abs(e-t)<1},i=function(e){return e},s=function(e){for(var t=Math.max(e.startIndex-e.overscan,0),n=Math.min(e.endIndex+e.overscan,e.count-1),o=[],r=t;r<=n;r++)o.push(r);return o},l={element:["scrollLeft","scrollTop"],window:["scrollX","scrollY"]},a=function(e){return function(t,n){if(t.scrollElement){var o=l[e][0],r=l[e][1],i=t.scrollElement[o],s=t.scrollElement[r],a=function(){var e=t.scrollElement[t.options.horizontal?o:r];n(e)};a();var u=function(e){var n=e.currentTarget,l=n[o],u=n[r];(t.options.horizontal?i-l:s-u)&&a(),i=l,s=u};return t.scrollElement.addEventListener("scroll",u,{capture:!1,passive:!0}),function(){t.scrollElement.removeEventListener("scroll",u)}}}},u=a("element"),c=a("window"),d=function(e,t){return Math.round(e.getBoundingClientRect()[t.options.horizontal?"width":"height"])};e.Virtualizer=function(e){var l,a=this;this.unsubs=[],this.scrollElement=null,this.isScrolling=!1,this.isScrollingTimeoutId=null,this.scrollToIndexTimeoutId=null,this.measurementsCache=[],this.itemSizeCache={},this.pendingMeasuredCacheIndexes=[],this.scrollDirection=null,this.scrollAdjustments=0,this.measureElementCache={},this.getResizeObserver=(l=null,function(){return l||("undefined"!=typeof ResizeObserver?l=new ResizeObserver((function(e){e.forEach((function(e){a._measureElement(e.target,!1)}))})):null)}),this.range={startIndex:0,endIndex:0},this.setOptions=function(e){Object.entries(e).forEach((function(t){var n=t[0];void 0===t[1]&&delete e[n]})),a.options=t({debug:!1,initialOffset:0,overscan:1,paddingStart:0,paddingEnd:0,scrollPaddingStart:0,scrollPaddingEnd:0,horizontal:!1,getItemKey:i,rangeExtractor:s,onChange:function(){},measureElement:d,initialRect:{width:0,height:0},scrollMargin:0,scrollingDelay:150,indexAttribute:"data-index",initialMeasurementsCache:[]},e)},this.notify=function(){null==a.options.onChange||a.options.onChange(a)},this.cleanup=function(){a.unsubs.filter(Boolean).forEach((function(e){return e()})),a.unsubs=[],a.scrollElement=null},this._didMount=function(){var e=a.getResizeObserver();return Object.values(a.measureElementCache).forEach((function(t){return null==e?void 0:e.observe(t)})),function(){null==e||e.disconnect(),a.cleanup()}},this._willUpdate=function(){var e=a.options.getScrollElement();a.scrollElement!==e&&(a.cleanup(),a.scrollElement=e,a._scrollToOffset(a.scrollOffset,{adjustments:void 0,behavior:void 0}),a.unsubs.push(a.options.observeElementRect(a,(function(e){a.scrollRect=e,a.calculateRange()}))),a.unsubs.push(a.options.observeElementOffset(a,(function(e){if(a.scrollAdjustments=0,a.scrollOffset!==e){null!==a.isScrollingTimeoutId&&(clearTimeout(a.isScrollingTimeoutId),a.isScrollingTimeoutId=null);var t=function(e){a.isScrolling!==e&&(a.isScrolling=e,a.notify())};a.scrollDirection=a.scrollOffset<e?"forward":"backward",a.scrollOffset=e,a.calculateRange(),t(!0),a.isScrollingTimeoutId=setTimeout((function(){a.isScrollingTimeoutId=null,a.scrollDirection=null,t(!1)}),a.options.scrollingDelay)}}))))},this.getSize=function(){return a.scrollRect[a.options.horizontal?"width":"height"]},this.getMeasurements=n((function(){return[a.options.count,a.options.paddingStart,a.options.scrollMargin,a.options.getItemKey,a.itemSizeCache]}),(function(e,t,n,o,r){var i=a.pendingMeasuredCacheIndexes.length>0?Math.min.apply(Math,a.pendingMeasuredCacheIndexes):0;a.pendingMeasuredCacheIndexes=[];for(var s=a.measurementsCache.slice(0,i),l=i;l<e;l++){var u=o(l),c=r[u],d=s[l-1]?s[l-1].end:t+n,f="number"==typeof c?c:a.options.estimateSize(l),h=d+f;s[l]={index:l,start:d,size:f,end:h,key:u}}return a.measurementsCache=s,s}),{key:!1,debug:function(){return a.options.debug}}),this.calculateRange=n((function(){return[a.getMeasurements(),a.getSize(),a.scrollOffset]}),(function(e,t,n,o){var r=o[0],i=void 0===r||r,s=function(e){var t=e.measurements,n=e.outerSize,o=e.scrollOffset,r=t.length-1,i=function(e,t,n,o){for(;e<=t;){var r=(e+t)/2|0,i=n(r);if(i<o)e=r+1;else{if(!(i>o))return r;t=r-1}}return e>0?e-1:0}(0,r,(function(e){return t[e].start}),o),s=i;for(;s<r&&t[s].end<o+n;)s++;return{startIndex:i,endIndex:s}}({measurements:e,outerSize:t,scrollOffset:n});return s.startIndex===a.range.startIndex&&s.endIndex===a.range.endIndex||(a.range=s,i&&a.notify()),a.range}),{key:!1,debug:function(){return a.options.debug}}),this.getIndexes=n((function(){return[a.options.rangeExtractor,a.calculateRange(!1),a.options.overscan,a.options.count]}),(function(e,n,o,r){return e(t({},n,{overscan:o,count:r}))}),{key:!1,debug:function(){return a.options.debug}}),this.indexFromElement=function(e){var t=a.options.indexAttribute,n=e.getAttribute(t);return n?parseInt(n,10):(console.warn("Missing attribute name '"+t+"={index}' on measured element."),-1)},this._measureElement=function(e,n){var o,r=a.indexFromElement(e),i=a.measurementsCache[r];if(i){var s=a.measureElementCache[i.key],l=a.getResizeObserver();if(!e.isConnected)return null==l||l.unobserve(e),void(e===s&&delete a.measureElementCache[i.key]);if(s!==e)s&&(null==l||l.unobserve(s)),null==l||l.observe(e),a.measureElementCache[i.key]=e;else if(!n&&!s.__virtualizerSkipFirstNotSync)return void(s.__virtualizerSkipFirstNotSync=!0);var u,c=a.options.measureElement(e,a),d=c-(null!=(o=a.itemSizeCache[i.key])?o:i.size);if(0!==d)i.start<a.scrollOffset&&a._scrollToOffset(a.scrollOffset,{adjustments:a.scrollAdjustments+=d,behavior:void 0}),a.pendingMeasuredCacheIndexes.push(r),a.itemSizeCache=t({},a.itemSizeCache,((u={})[i.key]=c,u)),a.notify()}},this.measureElement=function(e){e&&a._measureElement(e,!0)},this.getVirtualItems=n((function(){return[a.getIndexes(),a.getMeasurements()]}),(function(e,t){for(var n=[],o=0,r=e.length;o<r;o++){var i=t[e[o]];n.push(i)}return n}),{key:!1,debug:function(){return a.options.debug}}),this.getOffsetForAlignment=function(e,t){var n=a.getSize();"auto"===t&&(t=e<=a.scrollOffset?"start":e>=a.scrollOffset+n?"end":"start"),"start"===t||("end"===t?e-=n:"center"===t&&(e-=n/2));var o=a.options.horizontal?"scrollWidth":"scrollHeight",r=(a.scrollElement?"document"in a.scrollElement?a.scrollElement.document.documentElement[o]:a.scrollElement[o]:0)-a.getSize();return Math.max(Math.min(r,e),0)},this.scrollToOffset=function(e,t){var n=void 0===t?{}:t,o=n.align,r=void 0===o?"start":o,i=n.behavior;if(Object.keys(a.measureElementCache).length>0&&"smooth"===i)console.warn("The `smooth` scroll behavior is not supported with dynamic size.");else{var s={adjustments:void 0,behavior:i,sync:!1};a._scrollToOffset(a.getOffsetForAlignment(e,r),s)}},this.scrollToIndex=function(e,t){var n=void 0===t?{}:t,i=n.align,s=void 0===i?"auto":i,l=n.behavior;e=Math.max(0,Math.min(e,a.options.count-1)),null!==a.scrollToIndexTimeoutId&&(clearTimeout(a.scrollToIndexTimeoutId),a.scrollToIndexTimeoutId=null);var u=Object.keys(a.measureElementCache).length>0;if(u&&"smooth"===l)console.warn("The `smooth` scroll behavior is not supported with dynamic size.");else{var c=o(a.getMeasurements()[e]);if("auto"===s)if(c.end>=a.scrollOffset+a.getSize()-a.options.scrollPaddingEnd)s="end";else{if(!(c.start<=a.scrollOffset+a.options.scrollPaddingStart))return;s="start"}var d=function(e){var t="end"===s?e.end+a.options.scrollPaddingEnd:e.start-a.options.scrollPaddingStart;return a.getOffsetForAlignment(t,s)},f=d(c),h={adjustments:void 0,behavior:l};a._scrollToOffset(f,h),u&&(a.scrollToIndexTimeoutId=setTimeout((function(){if(a.scrollToIndexTimeoutId=null,!!a.measureElementCache[a.options.getItemKey(e)]){var t=d(o(a.getMeasurements()[e]));r(t,a.scrollOffset)||a.scrollToIndex(e,{align:s,behavior:l})}else a.scrollToIndex(e,{align:s,behavior:l})})))}},this.scrollBy=function(e,t){var n=(void 0===t?{}:t).behavior;Object.keys(a.measureElementCache).length>0&&"smooth"===n?console.warn("The `smooth` scroll behavior is not supported with dynamic size."):a._scrollToOffset(a.scrollOffset+e,{adjustments:void 0,behavior:n})},this.getTotalSize=function(){var e;return((null==(e=a.getMeasurements()[a.options.count-1])?void 0:e.end)||a.options.paddingStart)-a.options.scrollMargin+a.options.paddingEnd},this._scrollToOffset=function(e,t){var n=t.adjustments,o=t.behavior;a.options.scrollToFn(e,{behavior:o,adjustments:n},a)},this.measure=function(){a.itemSizeCache={},a.notify()},this.setOptions(e),this.scrollRect=this.options.initialRect,this.scrollOffset=this.options.initialOffset,this.measurementsCache=this.options.initialMeasurementsCache,this.measurementsCache.forEach((function(e){a.itemSizeCache[e.key]=e.size})),this.calculateRange()},e.approxEqual=r,e.defaultKeyExtractor=i,e.defaultRangeExtractor=s,e.elementScroll=function(e,t,n){var o,r,i=t.adjustments,s=void 0===i?0:i,l=t.behavior,a=e+s;null==(o=n.scrollElement)||null==o.scrollTo||o.scrollTo(((r={})[n.options.horizontal?"left":"top"]=a,r.behavior=l,r))},e.measureElement=d,e.memo=n,e.notUndefined=o,e.observeElementOffset=u,e.observeElementRect=function(e,t){var n=new ResizeObserver((function(e){var n=e[0];if(n){var o=n.contentRect,r=o.width,i=o.height;t({width:Math.round(r),height:Math.round(i)})}else t({width:0,height:0})}));if(e.scrollElement)return t(e.scrollElement.getBoundingClientRect()),n.observe(e.scrollElement),function(){n.unobserve(e.scrollElement)}},e.observeWindowOffset=c,e.observeWindowRect=function(e,t){var n=function(e,t){var n={height:-1,width:-1};return function(o){(e.options.horizontal?o.width!==n.width:o.height!==n.height)&&t(o),n=o}}(e,t),o=function(){return n({width:e.scrollElement.innerWidth,height:e.scrollElement.innerHeight})};if(e.scrollElement)return o(),e.scrollElement.addEventListener("resize",o,{capture:!1,passive:!0}),function(){e.scrollElement.removeEventListener("resize",o)}},e.windowScroll=function(e,t,n){var o,r,i=t.adjustments,s=void 0===i?0:i,l=t.behavior,a=e+s;null==(o=n.scrollElement)||null==o.scrollTo||o.scrollTo(((r={})[n.options.horizontal?"left":"top"]=a,r.behavior=l,r))},Object.defineProperty(e,"__esModule",{value:!0})}));
11
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).VirtualCore={})}(this,(function(e){"use strict";function t(){return t=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var o in n)Object.prototype.hasOwnProperty.call(n,o)&&(e[o]=n[o])}return e},t.apply(this,arguments)}function n(e,t,n){var o,i,r=null!=(o=n.initialDeps)?o:[];return function(){var o;n.key&&null!=n.debug&&n.debug()&&(o=Date.now());var s,l=e();if(!(l.length!==r.length||l.some((function(e,t){return r[t]!==e}))))return i;if(r=l,n.key&&null!=n.debug&&n.debug()&&(s=Date.now()),i=t.apply(void 0,l),n.key&&null!=n.debug&&n.debug()){var a=Math.round(100*(Date.now()-o))/100,u=Math.round(100*(Date.now()-s))/100,c=u/16,d=function(e,t){for(e=String(e);e.length<t;)e=" "+e;return e};console.info("%c⏱ "+d(u,5)+" /"+d(a,5)+" ms","\n font-size: .6rem;\n font-weight: bold;\n color: hsl("+Math.max(0,Math.min(120-120*c,120))+"deg 100% 31%);",null==n?void 0:n.key)}return null==n||null==n.onChange||n.onChange(i),i}}function o(e,t){if(void 0===e)throw new Error("Unexpected undefined"+(t?": "+t:""));return e}var i=function(e,t){return Math.abs(e-t)<1},r=function(e){return e},s=function(e){for(var t=Math.max(e.startIndex-e.overscan,0),n=Math.min(e.endIndex+e.overscan,e.count-1),o=[],i=t;i<=n;i++)o.push(i);return o},l={element:["scrollLeft","scrollTop"],window:["scrollX","scrollY"]},a=function(e){return function(t,n){if(t.scrollElement){var o=l[e][0],i=l[e][1],r=t.scrollElement[o],s=t.scrollElement[i],a=function(){var e=t.scrollElement[t.options.horizontal?o:i];n(e)};a();var u=function(e){var n=e.currentTarget,l=n[o],u=n[i];(t.options.horizontal?r-l:s-u)&&a(),r=l,s=u};return t.scrollElement.addEventListener("scroll",u,{capture:!1,passive:!0}),function(){t.scrollElement.removeEventListener("scroll",u)}}}},u=a("element"),c=a("window"),d=function(e,t){return Math.round(e.getBoundingClientRect()[t.options.horizontal?"width":"height"])};e.Virtualizer=function(e){var l,a=this;this.unsubs=[],this.scrollElement=null,this.isScrolling=!1,this.isScrollingTimeoutId=null,this.scrollToIndexTimeoutId=null,this.measurementsCache=[],this.itemSizeCache={},this.pendingMeasuredCacheIndexes=[],this.scrollDirection=null,this.scrollAdjustments=0,this.measureElementCache={},this.getResizeObserver=(l=null,function(){return l||("undefined"!=typeof ResizeObserver?l=new ResizeObserver((function(e){e.forEach((function(e){a._measureElement(e.target,!1)}))})):null)}),this.range={startIndex:0,endIndex:0},this.setOptions=function(e){Object.entries(e).forEach((function(t){var n=t[0];void 0===t[1]&&delete e[n]})),a.options=t({debug:!1,initialOffset:0,overscan:1,paddingStart:0,paddingEnd:0,scrollPaddingStart:0,scrollPaddingEnd:0,horizontal:!1,getItemKey:r,rangeExtractor:s,onChange:function(){},measureElement:d,initialRect:{width:0,height:0},scrollMargin:0,scrollingDelay:150,indexAttribute:"data-index",initialMeasurementsCache:[]},e)},this.notify=function(){null==a.options.onChange||a.options.onChange(a)},this.cleanup=function(){a.unsubs.filter(Boolean).forEach((function(e){return e()})),a.unsubs=[],a.scrollElement=null},this._didMount=function(){var e=a.getResizeObserver();return Object.values(a.measureElementCache).forEach((function(t){return null==e?void 0:e.observe(t)})),function(){null==e||e.disconnect(),a.cleanup()}},this._willUpdate=function(){var e=a.options.getScrollElement();a.scrollElement!==e&&(a.cleanup(),a.scrollElement=e,a._scrollToOffset(a.scrollOffset,{adjustments:void 0,behavior:void 0}),a.unsubs.push(a.options.observeElementRect(a,(function(e){a.scrollRect=e,a.maybeNotify()}))),a.unsubs.push(a.options.observeElementOffset(a,(function(e){a.scrollAdjustments=0,a.scrollOffset!==e&&(null!==a.isScrollingTimeoutId&&(clearTimeout(a.isScrollingTimeoutId),a.isScrollingTimeoutId=null),a.isScrolling=!0,a.scrollDirection=a.scrollOffset<e?"forward":"backward",a.scrollOffset=e,a.maybeNotify(),a.isScrollingTimeoutId=setTimeout((function(){a.isScrollingTimeoutId=null,a.isScrolling=!1,a.scrollDirection=null,a.maybeNotify()}),a.options.scrollingDelay))}))))},this.getSize=function(){return a.scrollRect[a.options.horizontal?"width":"height"]},this.getMeasurements=n((function(){return[a.options.count,a.options.paddingStart,a.options.scrollMargin,a.options.getItemKey,a.itemSizeCache]}),(function(e,t,n,o,i){var r=a.pendingMeasuredCacheIndexes.length>0?Math.min.apply(Math,a.pendingMeasuredCacheIndexes):0;a.pendingMeasuredCacheIndexes=[];for(var s=a.measurementsCache.slice(0,r),l=r;l<e;l++){var u=o(l),c=i[u],d=s[l-1]?s[l-1].end:t+n,f="number"==typeof c?c:a.options.estimateSize(l),h=d+f;s[l]={index:l,start:d,size:f,end:h,key:u}}return a.measurementsCache=s,s}),{key:!1,debug:function(){return a.options.debug}}),this.calculateRange=n((function(){return[a.getMeasurements(),a.getSize(),a.scrollOffset]}),(function(e,t,n){return a.range=function(e){var t=e.measurements,n=e.outerSize,o=e.scrollOffset,i=t.length-1,r=function(e,t,n,o){for(;e<=t;){var i=(e+t)/2|0,r=n(i);if(r<o)e=i+1;else{if(!(r>o))return i;t=i-1}}return e>0?e-1:0}(0,i,(function(e){return t[e].start}),o),s=r;for(;s<i&&t[s].end<o+n;)s++;return{startIndex:r,endIndex:s}}({measurements:e,outerSize:t,scrollOffset:n})}),{key:!1,debug:function(){return a.options.debug}}),this.maybeNotify=n((function(){return[].concat(Object.values(a.calculateRange()),[a.isScrolling])}),(function(){a.notify()}),{key:!1,debug:function(){return a.options.debug},initialDeps:[].concat(Object.values(this.range),[this.isScrolling])}),this.getIndexes=n((function(){return[a.options.rangeExtractor,a.calculateRange(),a.options.overscan,a.options.count]}),(function(e,n,o,i){return e(t({},n,{overscan:o,count:i}))}),{key:!1,debug:function(){return a.options.debug}}),this.indexFromElement=function(e){var t=a.options.indexAttribute,n=e.getAttribute(t);return n?parseInt(n,10):(console.warn("Missing attribute name '"+t+"={index}' on measured element."),-1)},this._measureElement=function(e,n){var o,i=a.indexFromElement(e),r=a.measurementsCache[i];if(r){var s=a.measureElementCache[r.key],l=a.getResizeObserver();if(!e.isConnected)return null==l||l.unobserve(e),void(e===s&&delete a.measureElementCache[r.key]);if(s!==e)s&&(null==l||l.unobserve(s)),null==l||l.observe(e),a.measureElementCache[r.key]=e;else if(!n&&!s.__virtualizerSkipFirstNotSync)return void(s.__virtualizerSkipFirstNotSync=!0);var u,c=a.options.measureElement(e,a),d=c-(null!=(o=a.itemSizeCache[r.key])?o:r.size);if(0!==d)r.start<a.scrollOffset&&a._scrollToOffset(a.scrollOffset,{adjustments:a.scrollAdjustments+=d,behavior:void 0}),a.pendingMeasuredCacheIndexes.push(i),a.itemSizeCache=t({},a.itemSizeCache,((u={})[r.key]=c,u)),a.notify()}},this.measureElement=function(e){e&&a._measureElement(e,!0)},this.getVirtualItems=n((function(){return[a.getIndexes(),a.getMeasurements()]}),(function(e,t){for(var n=[],o=0,i=e.length;o<i;o++){var r=t[e[o]];n.push(r)}return n}),{key:!1,debug:function(){return a.options.debug}}),this.getOffsetForAlignment=function(e,t){var n=a.getSize();"auto"===t&&(t=e<=a.scrollOffset?"start":e>=a.scrollOffset+n?"end":"start"),"start"===t||("end"===t?e-=n:"center"===t&&(e-=n/2));var o=a.options.horizontal?"scrollWidth":"scrollHeight",i=(a.scrollElement?"document"in a.scrollElement?a.scrollElement.document.documentElement[o]:a.scrollElement[o]:0)-a.getSize();return Math.max(Math.min(i,e),0)},this.getOffsetForIndex=function(e,t){void 0===t&&(t="auto"),e=Math.max(0,Math.min(e,a.options.count-1));var n=o(a.getMeasurements()[e]);if("auto"===t)if(n.end>=a.scrollOffset+a.getSize()-a.options.scrollPaddingEnd)t="end";else{if(!(n.start<=a.scrollOffset+a.options.scrollPaddingStart))return[a.scrollOffset,t];t="start"}var i="end"===t?n.end+a.options.scrollPaddingEnd:n.start-a.options.scrollPaddingStart;return[a.getOffsetForAlignment(i,t),t]},this.isDynamicMode=function(){return Object.keys(a.measureElementCache).length>0},this.cancelScrollToIndex=function(){null!==a.scrollToIndexTimeoutId&&(clearTimeout(a.scrollToIndexTimeoutId),a.scrollToIndexTimeoutId=null)},this.scrollToOffset=function(e,t){var n=void 0===t?{}:t,o=n.align,i=void 0===o?"start":o,r=n.behavior;a.cancelScrollToIndex(),"smooth"===r&&a.isDynamicMode()&&console.warn("The `smooth` scroll behavior is not fully supported with dynamic size."),a._scrollToOffset(a.getOffsetForAlignment(e,i),{adjustments:void 0,behavior:r})},this.scrollToIndex=function(e,t){var n=void 0===t?{}:t,o=n.align,r=void 0===o?"auto":o,s=n.behavior;e=Math.max(0,Math.min(e,a.options.count-1)),a.cancelScrollToIndex(),"smooth"===s&&a.isDynamicMode()&&console.warn("The `smooth` scroll behavior is not fully supported with dynamic size.");var l=a.getOffsetForIndex(e,r),u=l[0],c=l[1];a._scrollToOffset(u,{adjustments:void 0,behavior:s}),"smooth"!==s&&a.isDynamicMode()&&(a.scrollToIndexTimeoutId=setTimeout((function(){if(a.scrollToIndexTimeoutId=null,!!a.measureElementCache[a.options.getItemKey(e)]){var t=a.getOffsetForIndex(e,c)[0];i(t,a.scrollOffset)||a.scrollToIndex(e,{align:c,behavior:s})}else a.scrollToIndex(e,{align:c,behavior:s})})))},this.scrollBy=function(e,t){var n=(void 0===t?{}:t).behavior;a.cancelScrollToIndex(),"smooth"===n&&a.isDynamicMode()&&console.warn("The `smooth` scroll behavior is not fully supported with dynamic size."),a._scrollToOffset(a.scrollOffset+e,{adjustments:void 0,behavior:n})},this.getTotalSize=function(){var e;return((null==(e=a.getMeasurements()[a.options.count-1])?void 0:e.end)||a.options.paddingStart)-a.options.scrollMargin+a.options.paddingEnd},this._scrollToOffset=function(e,t){var n=t.adjustments,o=t.behavior;a.options.scrollToFn(e,{behavior:o,adjustments:n},a)},this.measure=function(){a.itemSizeCache={},a.notify()},this.setOptions(e),this.scrollRect=this.options.initialRect,this.scrollOffset=this.options.initialOffset,this.measurementsCache=this.options.initialMeasurementsCache,this.measurementsCache.forEach((function(e){a.itemSizeCache[e.key]=e.size})),this.maybeNotify()},e.approxEqual=i,e.defaultKeyExtractor=r,e.defaultRangeExtractor=s,e.elementScroll=function(e,t,n){var o,i,r=t.adjustments,s=void 0===r?0:r,l=t.behavior,a=e+s;null==(o=n.scrollElement)||null==o.scrollTo||o.scrollTo(((i={})[n.options.horizontal?"left":"top"]=a,i.behavior=l,i))},e.measureElement=d,e.memo=n,e.notUndefined=o,e.observeElementOffset=u,e.observeElementRect=function(e,t){var n=new ResizeObserver((function(e){var n=e[0];if(n){var o=n.contentRect,i=o.width,r=o.height;t({width:Math.round(i),height:Math.round(r)})}else t({width:0,height:0})}));if(e.scrollElement)return t(e.scrollElement.getBoundingClientRect()),n.observe(e.scrollElement),function(){n.unobserve(e.scrollElement)}},e.observeWindowOffset=c,e.observeWindowRect=function(e,t){var n=function(e,t){var n={height:-1,width:-1};return function(o){(e.options.horizontal?o.width!==n.width:o.height!==n.height)&&t(o),n=o}}(e,t),o=function(){return n({width:e.scrollElement.innerWidth,height:e.scrollElement.innerHeight})};if(e.scrollElement)return o(),e.scrollElement.addEventListener("resize",o,{capture:!1,passive:!0}),function(){e.scrollElement.removeEventListener("resize",o)}},e.windowScroll=function(e,t,n){var o,i,r=t.adjustments,s=void 0===r?0:r,l=t.behavior,a=e+s;null==(o=n.scrollElement)||null==o.scrollTo||o.scrollTo(((i={})[n.options.horizontal?"left":"top"]=a,i.behavior=l,i))},Object.defineProperty(e,"__esModule",{value:!0})}));
12
12
  //# sourceMappingURL=index.production.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.production.js","sources":["../../src/utils.ts","../../src/index.ts"],"sourcesContent":["export type NoInfer<A extends any> = [A][A extends any ? 0 : never]\n\nexport type PartialKeys<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>\n\nexport function memo<\n TDeps extends readonly any[],\n TResult,\n FArgs extends readonly any[],\n>(\n getDeps: () => [...TDeps],\n fn: (...args: [...TDeps, FArgs]) => TResult,\n opts: {\n key: any\n debug?: () => any\n onChange?: (result: TResult) => void\n },\n) {\n let deps: any[] = []\n let result: TResult | undefined\n\n return (...fArgs: FArgs): TResult => {\n let depTime: number\n if (opts.key && opts.debug?.()) depTime = Date.now()\n\n const newDeps = getDeps()\n\n const depsChanged =\n newDeps.length !== deps.length ||\n newDeps.some((dep: any, index: number) => deps[index] !== dep)\n\n if (!depsChanged) {\n return result!\n }\n\n deps = newDeps\n\n let resultTime: number\n if (opts.key && opts.debug?.()) resultTime = Date.now()\n\n result = fn(...newDeps, fArgs)\n opts?.onChange?.(result)\n\n if (opts.key && opts.debug?.()) {\n const depEndTime = Math.round((Date.now() - depTime!) * 100) / 100\n const resultEndTime = Math.round((Date.now() - resultTime!) * 100) / 100\n const resultFpsPercentage = resultEndTime / 16\n\n const pad = (str: number | string, num: number) => {\n str = String(str)\n while (str.length < num) {\n str = ' ' + str\n }\n return str\n }\n\n console.info(\n `%c⏱ ${pad(resultEndTime, 5)} /${pad(depEndTime, 5)} ms`,\n `\n font-size: .6rem;\n font-weight: bold;\n color: hsl(${Math.max(\n 0,\n Math.min(120 - 120 * resultFpsPercentage, 120),\n )}deg 100% 31%);`,\n opts?.key,\n )\n }\n\n return result!\n }\n}\n\nexport function notUndefined<T>(value: T | undefined, msg?: string): T {\n if (value === undefined) {\n throw new Error(`Unexpected undefined${msg ? `: ${msg}` : ''}`)\n } else {\n return value\n }\n}\n\nexport const approxEqual = (a: number, b: number) => Math.abs(a - b) < 1\n","import { approxEqual, memo, notUndefined } from './utils'\n\nexport * from './utils'\n\n//\n\ntype ScrollDirection = 'forward' | 'backward'\n\ntype ScrollAlignment = 'start' | 'center' | 'end' | 'auto'\n\ntype ScrollBehavior = 'auto' | 'smooth'\n\nexport interface ScrollToOptions {\n align?: ScrollAlignment\n behavior?: ScrollBehavior\n}\n\ntype ScrollToOffsetOptions = ScrollToOptions\n\ntype ScrollToIndexOptions = ScrollToOptions\n\nexport interface Range {\n startIndex: number\n endIndex: number\n overscan: number\n count: number\n}\n\ntype Key = number | string\n\nexport interface VirtualItem {\n key: Key\n index: number\n start: number\n end: number\n size: number\n}\n\ninterface Rect {\n width: number\n height: number\n}\n\n//\n\nexport const defaultKeyExtractor = (index: number) => index\n\nexport const defaultRangeExtractor = (range: Range) => {\n const start = Math.max(range.startIndex - range.overscan, 0)\n const end = Math.min(range.endIndex + range.overscan, range.count - 1)\n\n const arr = []\n\n for (let i = start; i <= end; i++) {\n arr.push(i)\n }\n\n return arr\n}\n\nconst memoRectCallback = (\n instance: Virtualizer<any, any>,\n cb: (rect: Rect) => void,\n) => {\n let prev: Rect = { height: -1, width: -1 }\n\n return (rect: Rect) => {\n if (\n instance.options.horizontal\n ? rect.width !== prev.width\n : rect.height !== prev.height\n ) {\n cb(rect)\n }\n\n prev = rect\n }\n}\n\nexport const observeElementRect = (\n instance: Virtualizer<any, any>,\n cb: (rect: Rect) => void,\n) => {\n const observer = new ResizeObserver((entries) => {\n const entry = entries[0]\n if (entry) {\n const { width, height } = entry.contentRect\n cb({\n width: Math.round(width),\n height: Math.round(height),\n })\n } else {\n cb({ width: 0, height: 0 })\n }\n })\n\n if (!instance.scrollElement) {\n return\n }\n\n cb(instance.scrollElement.getBoundingClientRect())\n\n observer.observe(instance.scrollElement)\n\n return () => {\n observer.unobserve(instance.scrollElement)\n }\n}\n\nexport const observeWindowRect = (\n instance: Virtualizer<any, any>,\n cb: (rect: Rect) => void,\n) => {\n const memoizedCallback = memoRectCallback(instance, cb)\n const onResize = () =>\n memoizedCallback({\n width: instance.scrollElement.innerWidth,\n height: instance.scrollElement.innerHeight,\n })\n\n if (!instance.scrollElement) {\n return\n }\n\n onResize()\n\n instance.scrollElement.addEventListener('resize', onResize, {\n capture: false,\n passive: true,\n })\n\n return () => {\n instance.scrollElement.removeEventListener('resize', onResize)\n }\n}\n\ntype ObserverMode = 'element' | 'window'\n\nconst scrollProps = {\n element: ['scrollLeft', 'scrollTop'],\n window: ['scrollX', 'scrollY'],\n} as const\n\nconst createOffsetObserver = (mode: ObserverMode) => {\n return (instance: Virtualizer<any, any>, cb: (offset: number) => void) => {\n if (!instance.scrollElement) {\n return\n }\n\n const propX = scrollProps[mode][0]\n const propY = scrollProps[mode][1]\n\n let prevX: number = instance.scrollElement[propX]\n let prevY: number = instance.scrollElement[propY]\n\n const scroll = () => {\n const offset =\n instance.scrollElement[instance.options.horizontal ? propX : propY]\n\n cb(offset)\n }\n\n scroll()\n\n const onScroll = (e: Event) => {\n const target = e.currentTarget as HTMLElement & Window\n const scrollX = target[propX]\n const scrollY = target[propY]\n\n if (instance.options.horizontal ? prevX - scrollX : prevY - scrollY) {\n scroll()\n }\n\n prevX = scrollX\n prevY = scrollY\n }\n\n instance.scrollElement.addEventListener('scroll', onScroll, {\n capture: false,\n passive: true,\n })\n\n return () => {\n instance.scrollElement.removeEventListener('scroll', onScroll)\n }\n }\n}\n\nexport const observeElementOffset = createOffsetObserver('element')\nexport const observeWindowOffset = createOffsetObserver('window')\n\nexport const measureElement = <TItemElement extends Element>(\n element: TItemElement,\n instance: Virtualizer<any, TItemElement>,\n) => {\n return Math.round(\n element.getBoundingClientRect()[\n instance.options.horizontal ? 'width' : 'height'\n ],\n )\n}\n\nexport const windowScroll = <T extends Window>(\n offset: number,\n {\n adjustments = 0,\n behavior,\n }: { adjustments?: number; behavior?: ScrollBehavior },\n instance: Virtualizer<T, any>,\n) => {\n const toOffset = offset + adjustments\n\n instance.scrollElement?.scrollTo?.({\n [instance.options.horizontal ? 'left' : 'top']: toOffset,\n behavior,\n })\n}\n\nexport const elementScroll = <T extends Element>(\n offset: number,\n {\n adjustments = 0,\n behavior,\n }: { adjustments?: number; behavior?: ScrollBehavior },\n instance: Virtualizer<T, any>,\n) => {\n const toOffset = offset + adjustments\n\n instance.scrollElement?.scrollTo?.({\n [instance.options.horizontal ? 'left' : 'top']: toOffset,\n behavior,\n })\n}\n\nexport interface VirtualizerOptions<\n TScrollElement extends Element | Window,\n TItemElement extends Element,\n> {\n // Required from the user\n count: number\n getScrollElement: () => TScrollElement | null\n estimateSize: (index: number) => number\n\n // Required from the framework adapter (but can be overridden)\n scrollToFn: (\n offset: number,\n options: { adjustments?: number; behavior?: ScrollBehavior },\n instance: Virtualizer<TScrollElement, TItemElement>,\n ) => void\n observeElementRect: (\n instance: Virtualizer<TScrollElement, TItemElement>,\n cb: (rect: Rect) => void,\n ) => void | (() => void)\n observeElementOffset: (\n instance: Virtualizer<TScrollElement, TItemElement>,\n cb: (offset: number) => void,\n ) => void | (() => void)\n\n // Optional\n debug?: any\n initialRect?: Rect\n onChange?: (instance: Virtualizer<TScrollElement, TItemElement>) => void\n measureElement?: (\n el: TItemElement,\n instance: Virtualizer<TScrollElement, TItemElement>,\n ) => number\n overscan?: number\n horizontal?: boolean\n paddingStart?: number\n paddingEnd?: number\n scrollPaddingStart?: number\n scrollPaddingEnd?: number\n initialOffset?: number\n getItemKey?: (index: number) => Key\n rangeExtractor?: (range: Range) => number[]\n scrollMargin?: number\n scrollingDelay?: number\n indexAttribute?: string\n initialMeasurementsCache?: VirtualItem[]\n}\n\nexport class Virtualizer<\n TScrollElement extends Element | Window,\n TItemElement extends Element,\n> {\n private unsubs: (void | (() => void))[] = []\n options!: Required<VirtualizerOptions<TScrollElement, TItemElement>>\n scrollElement: TScrollElement | null = null\n isScrolling: boolean = false\n private isScrollingTimeoutId: ReturnType<typeof setTimeout> | null = null\n private scrollToIndexTimeoutId: ReturnType<typeof setTimeout> | null = null\n measurementsCache: VirtualItem[] = []\n private itemSizeCache: Record<Key, number> = {}\n private pendingMeasuredCacheIndexes: number[] = []\n private scrollRect: Rect\n scrollOffset: number\n scrollDirection: ScrollDirection | null = null\n private scrollAdjustments: number = 0\n private measureElementCache: Record<\n Key,\n TItemElement & { __virtualizerSkipFirstNotSync?: boolean }\n > = {}\n private getResizeObserver = (() => {\n let _ro: ResizeObserver | null = null\n\n return () => {\n if (_ro) {\n return _ro\n } else if (typeof ResizeObserver !== 'undefined') {\n return (_ro = new ResizeObserver((entries) => {\n entries.forEach((entry) => {\n this._measureElement(entry.target as TItemElement, false)\n })\n }))\n } else {\n return null\n }\n }\n })()\n range: { startIndex: number; endIndex: number } = {\n startIndex: 0,\n endIndex: 0,\n }\n\n constructor(opts: VirtualizerOptions<TScrollElement, TItemElement>) {\n this.setOptions(opts)\n this.scrollRect = this.options.initialRect\n this.scrollOffset = this.options.initialOffset\n this.measurementsCache = this.options.initialMeasurementsCache\n this.measurementsCache.forEach((item) => {\n this.itemSizeCache[item.key] = item.size\n })\n\n this.calculateRange()\n }\n\n setOptions = (opts: VirtualizerOptions<TScrollElement, TItemElement>) => {\n Object.entries(opts).forEach(([key, value]) => {\n if (typeof value === 'undefined') delete (opts as any)[key]\n })\n\n this.options = {\n debug: false,\n initialOffset: 0,\n overscan: 1,\n paddingStart: 0,\n paddingEnd: 0,\n scrollPaddingStart: 0,\n scrollPaddingEnd: 0,\n horizontal: false,\n getItemKey: defaultKeyExtractor,\n rangeExtractor: defaultRangeExtractor,\n onChange: () => {},\n measureElement,\n initialRect: { width: 0, height: 0 },\n scrollMargin: 0,\n scrollingDelay: 150,\n indexAttribute: 'data-index',\n initialMeasurementsCache: [],\n ...opts,\n }\n }\n\n private notify = () => {\n this.options.onChange?.(this)\n }\n\n private cleanup = () => {\n this.unsubs.filter(Boolean).forEach((d) => d!())\n this.unsubs = []\n this.scrollElement = null\n }\n\n _didMount = () => {\n const ro = this.getResizeObserver()\n Object.values(this.measureElementCache).forEach((node) => ro?.observe(node))\n\n return () => {\n ro?.disconnect()\n\n this.cleanup()\n }\n }\n\n _willUpdate = () => {\n const scrollElement = this.options.getScrollElement()\n\n if (this.scrollElement !== scrollElement) {\n this.cleanup()\n\n this.scrollElement = scrollElement\n\n this._scrollToOffset(this.scrollOffset, {\n adjustments: undefined,\n behavior: undefined,\n })\n\n this.unsubs.push(\n this.options.observeElementRect(this, (rect) => {\n this.scrollRect = rect\n this.calculateRange()\n }),\n )\n\n this.unsubs.push(\n this.options.observeElementOffset(this, (offset) => {\n this.scrollAdjustments = 0\n\n if (this.scrollOffset === offset) {\n return\n }\n\n if (this.isScrollingTimeoutId !== null) {\n clearTimeout(this.isScrollingTimeoutId)\n this.isScrollingTimeoutId = null\n }\n\n const onIsScrollingChange = (isScrolling: boolean) => {\n if (this.isScrolling !== isScrolling) {\n this.isScrolling = isScrolling\n this.notify()\n }\n }\n\n this.scrollDirection =\n this.scrollOffset < offset ? 'forward' : 'backward'\n\n this.scrollOffset = offset\n\n this.calculateRange()\n\n onIsScrollingChange(true)\n\n this.isScrollingTimeoutId = setTimeout(() => {\n this.isScrollingTimeoutId = null\n this.scrollDirection = null\n onIsScrollingChange(false)\n }, this.options.scrollingDelay)\n }),\n )\n }\n }\n\n private getSize = () => {\n return this.scrollRect[this.options.horizontal ? 'width' : 'height']\n }\n\n private getMeasurements = memo(\n () => [\n this.options.count,\n this.options.paddingStart,\n this.options.scrollMargin,\n this.options.getItemKey,\n this.itemSizeCache,\n ],\n (count, paddingStart, scrollMargin, getItemKey, itemSizeCache) => {\n const min =\n this.pendingMeasuredCacheIndexes.length > 0\n ? Math.min(...this.pendingMeasuredCacheIndexes)\n : 0\n this.pendingMeasuredCacheIndexes = []\n\n const measurements = this.measurementsCache.slice(0, min)\n\n for (let i = min; i < count; i++) {\n const key = getItemKey(i)\n const measuredSize = itemSizeCache[key]\n const start = measurements[i - 1]\n ? measurements[i - 1]!.end\n : paddingStart + scrollMargin\n const size =\n typeof measuredSize === 'number'\n ? measuredSize\n : this.options.estimateSize(i)\n const end = start + size\n measurements[i] = { index: i, start, size, end, key }\n }\n\n this.measurementsCache = measurements\n\n return measurements\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'getMeasurements',\n debug: () => this.options.debug,\n },\n )\n\n calculateRange = memo(\n () => [this.getMeasurements(), this.getSize(), this.scrollOffset],\n (measurements, outerSize, scrollOffset, [flush = true]: [boolean?]) => {\n const range = calculateRange({\n measurements,\n outerSize,\n scrollOffset,\n })\n if (\n range.startIndex !== this.range.startIndex ||\n range.endIndex !== this.range.endIndex\n ) {\n this.range = range\n if (flush) {\n this.notify()\n }\n }\n return this.range\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'calculateRange',\n debug: () => this.options.debug,\n },\n )\n\n private getIndexes = memo(\n () => [\n this.options.rangeExtractor,\n this.calculateRange(false),\n this.options.overscan,\n this.options.count,\n ],\n (rangeExtractor, range, overscan, count) => {\n return rangeExtractor({\n ...range,\n overscan,\n count,\n })\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'getIndexes',\n debug: () => this.options.debug,\n },\n )\n\n indexFromElement = (node: TItemElement) => {\n const attributeName = this.options.indexAttribute\n const indexStr = node.getAttribute(attributeName)\n\n if (!indexStr) {\n console.warn(\n `Missing attribute name '${attributeName}={index}' on measured element.`,\n )\n return -1\n }\n\n return parseInt(indexStr, 10)\n }\n\n private _measureElement = (node: TItemElement, sync: boolean) => {\n const index = this.indexFromElement(node)\n\n const item = this.measurementsCache[index]\n if (!item) {\n return\n }\n\n const prevNode = this.measureElementCache[item.key]\n\n const ro = this.getResizeObserver()\n\n if (!node.isConnected) {\n ro?.unobserve(node)\n if (node === prevNode) {\n delete this.measureElementCache[item.key]\n }\n return\n }\n\n if (prevNode !== node) {\n if (prevNode) {\n ro?.unobserve(prevNode)\n }\n ro?.observe(node)\n this.measureElementCache[item.key] = node\n } else {\n if (!sync && !prevNode.__virtualizerSkipFirstNotSync) {\n prevNode.__virtualizerSkipFirstNotSync = true\n return\n }\n }\n\n const measuredItemSize = this.options.measureElement(node, this)\n\n const itemSize = this.itemSizeCache[item.key] ?? item.size\n\n const delta = measuredItemSize - itemSize\n\n if (delta !== 0) {\n if (item.start < this.scrollOffset) {\n if (process.env.NODE_ENV !== 'production' && this.options.debug) {\n console.info('correction', delta)\n }\n\n this._scrollToOffset(this.scrollOffset, {\n adjustments: (this.scrollAdjustments += delta),\n behavior: undefined,\n })\n }\n\n this.pendingMeasuredCacheIndexes.push(index)\n this.itemSizeCache = {\n ...this.itemSizeCache,\n [item.key]: measuredItemSize,\n }\n this.notify()\n }\n }\n\n measureElement = (node: TItemElement | null) => {\n if (!node) {\n return\n }\n\n this._measureElement(node, true)\n }\n\n getVirtualItems = memo(\n () => [this.getIndexes(), this.getMeasurements()],\n (indexes, measurements) => {\n const virtualItems: VirtualItem[] = []\n\n for (let k = 0, len = indexes.length; k < len; k++) {\n const i = indexes[k]!\n const measurement = measurements[i]!\n\n virtualItems.push(measurement)\n }\n\n return virtualItems\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'getIndexes',\n debug: () => this.options.debug,\n },\n )\n\n getOffsetForAlignment = (toOffset: number, align: ScrollAlignment) => {\n const size = this.getSize()\n\n if (align === 'auto') {\n if (toOffset <= this.scrollOffset) {\n align = 'start'\n } else if (toOffset >= this.scrollOffset + size) {\n align = 'end'\n } else {\n align = 'start'\n }\n }\n\n if (align === 'start') {\n toOffset = toOffset\n } else if (align === 'end') {\n toOffset = toOffset - size\n } else if (align === 'center') {\n toOffset = toOffset - size / 2\n }\n\n const scrollSizeProp = this.options.horizontal\n ? 'scrollWidth'\n : 'scrollHeight'\n const scrollSize = this.scrollElement\n ? 'document' in this.scrollElement\n ? this.scrollElement.document.documentElement[scrollSizeProp]\n : this.scrollElement[scrollSizeProp]\n : 0\n\n const maxOffset = scrollSize - this.getSize()\n\n return Math.max(Math.min(maxOffset, toOffset), 0)\n }\n\n scrollToOffset = (\n toOffset: number,\n { align = 'start', behavior }: ScrollToOffsetOptions = {},\n ) => {\n const isDynamic = Object.keys(this.measureElementCache).length > 0\n\n if (isDynamic && behavior === 'smooth') {\n console.warn(\n 'The `smooth` scroll behavior is not supported with dynamic size.',\n )\n return\n }\n\n const options = {\n adjustments: undefined,\n behavior,\n sync: false,\n }\n this._scrollToOffset(this.getOffsetForAlignment(toOffset, align), options)\n }\n\n scrollToIndex = (\n index: number,\n { align = 'auto', behavior }: ScrollToIndexOptions = {},\n ) => {\n index = Math.max(0, Math.min(index, this.options.count - 1))\n\n if (this.scrollToIndexTimeoutId !== null) {\n clearTimeout(this.scrollToIndexTimeoutId)\n this.scrollToIndexTimeoutId = null\n }\n\n const isDynamic = Object.keys(this.measureElementCache).length > 0\n\n if (isDynamic && behavior === 'smooth') {\n console.warn(\n 'The `smooth` scroll behavior is not supported with dynamic size.',\n )\n return\n }\n\n const measurement = notUndefined(this.getMeasurements()[index])\n\n if (align === 'auto') {\n if (\n measurement.end >=\n this.scrollOffset + this.getSize() - this.options.scrollPaddingEnd\n ) {\n align = 'end'\n } else if (\n measurement.start <=\n this.scrollOffset + this.options.scrollPaddingStart\n ) {\n align = 'start'\n } else {\n return\n }\n }\n\n const getOffsetForIndexAndAlignment = (measurement: VirtualItem) => {\n const toOffset =\n align === 'end'\n ? measurement.end + this.options.scrollPaddingEnd\n : measurement.start - this.options.scrollPaddingStart\n\n return this.getOffsetForAlignment(toOffset, align)\n }\n\n const toOffset = getOffsetForIndexAndAlignment(measurement)\n\n const options = {\n adjustments: undefined,\n behavior,\n }\n this._scrollToOffset(toOffset, options)\n\n if (isDynamic) {\n this.scrollToIndexTimeoutId = setTimeout(() => {\n this.scrollToIndexTimeoutId = null\n\n const elementInDOM =\n !!this.measureElementCache[this.options.getItemKey(index)]\n\n if (elementInDOM) {\n const toOffset = getOffsetForIndexAndAlignment(\n notUndefined(this.getMeasurements()[index]),\n )\n\n if (!approxEqual(toOffset, this.scrollOffset)) {\n this.scrollToIndex(index, { align, behavior })\n }\n } else {\n this.scrollToIndex(index, { align, behavior })\n }\n })\n }\n }\n\n scrollBy = (delta: number, { behavior }: ScrollToOffsetOptions = {}) => {\n const isDynamic = Object.keys(this.measureElementCache).length > 0\n\n if (isDynamic && behavior === 'smooth') {\n console.warn(\n 'The `smooth` scroll behavior is not supported with dynamic size.',\n )\n return\n }\n\n this._scrollToOffset(this.scrollOffset + delta, {\n adjustments: undefined,\n behavior,\n })\n }\n\n getTotalSize = () =>\n (this.getMeasurements()[this.options.count - 1]?.end ||\n this.options.paddingStart) -\n this.options.scrollMargin +\n this.options.paddingEnd\n\n private _scrollToOffset = (\n offset: number,\n {\n adjustments,\n behavior,\n }: {\n adjustments: number | undefined\n behavior: ScrollBehavior | undefined\n },\n ) => {\n this.options.scrollToFn(offset, { behavior, adjustments }, this)\n }\n\n measure = () => {\n this.itemSizeCache = {}\n this.notify()\n }\n}\n\nconst findNearestBinarySearch = (\n low: number,\n high: number,\n getCurrentValue: (i: number) => number,\n value: number,\n) => {\n while (low <= high) {\n const middle = ((low + high) / 2) | 0\n const currentValue = getCurrentValue(middle)\n\n if (currentValue < value) {\n low = middle + 1\n } else if (currentValue > value) {\n high = middle - 1\n } else {\n return middle\n }\n }\n\n if (low > 0) {\n return low - 1\n } else {\n return 0\n }\n}\n\nfunction calculateRange({\n measurements,\n outerSize,\n scrollOffset,\n}: {\n measurements: VirtualItem[]\n outerSize: number\n scrollOffset: number\n}) {\n const count = measurements.length - 1\n const getOffset = (index: number) => measurements[index]!.start\n\n const startIndex = findNearestBinarySearch(0, count, getOffset, scrollOffset)\n let endIndex = startIndex\n\n while (\n endIndex < count &&\n measurements[endIndex]!.end < scrollOffset + outerSize\n ) {\n endIndex++\n }\n\n return { startIndex, endIndex }\n}\n"],"names":["memo","getDeps","fn","opts","result","deps","depTime","key","debug","Date","now","resultTime","newDeps","depsChanged","length","some","dep","index","_len","arguments","fArgs","Array","_key","apply","concat","onChange","depEndTime","Math","round","resultEndTime","resultFpsPercentage","pad","str","num","String","console","info","max","min","notUndefined","value","msg","undefined","Error","approxEqual","a","b","abs","defaultKeyExtractor","defaultRangeExtractor","range","start","startIndex","overscan","end","endIndex","count","arr","i","push","scrollProps","element","window","createOffsetObserver","mode","instance","cb","scrollElement","propX","propY","prevX","prevY","scroll","offset","options","horizontal","onScroll","e","target","currentTarget","scrollX","scrollY","addEventListener","capture","passive","removeEventListener","observeElementOffset","observeWindowOffset","measureElement","getBoundingClientRect","_ro","_this","this","unsubs","isScrolling","isScrollingTimeoutId","scrollToIndexTimeoutId","measurementsCache","itemSizeCache","pendingMeasuredCacheIndexes","scrollDirection","scrollAdjustments","measureElementCache","getResizeObserver","ResizeObserver","entries","forEach","entry","_measureElement","setOptions","Object","_ref3","_extends","initialOffset","paddingStart","paddingEnd","scrollPaddingStart","scrollPaddingEnd","getItemKey","rangeExtractor","initialRect","width","height","scrollMargin","scrollingDelay","indexAttribute","initialMeasurementsCache","notify","cleanup","filter","Boolean","d","_didMount","ro","values","node","observe","disconnect","_willUpdate","getScrollElement","_scrollToOffset","scrollOffset","adjustments","behavior","observeElementRect","rect","scrollRect","calculateRange","clearTimeout","onIsScrollingChange","setTimeout","getSize","getMeasurements","measurements","slice","measuredSize","size","estimateSize","process","outerSize","_ref4","_ref4$","flush","_ref9","low","high","getCurrentValue","middle","currentValue","findNearestBinarySearch","getIndexes","indexFromElement","attributeName","indexStr","getAttribute","parseInt","warn","sync","_this$itemSizeCache$i","item","prevNode","isConnected","unobserve","__virtualizerSkipFirstNotSync","_extends2","measuredItemSize","delta","getVirtualItems","indexes","virtualItems","k","len","measurement","getOffsetForAlignment","toOffset","align","scrollSizeProp","maxOffset","document","documentElement","scrollToOffset","_temp","_ref5","_ref5$align","keys","scrollToIndex","_temp2","_ref6","_ref6$align","isDynamic","getOffsetForIndexAndAlignment","scrollBy","_temp3","getTotalSize","_this$getMeasurements","_ref8","scrollToFn","measure","_instance$scrollEleme3","_instance$scrollEleme4","_ref2$adjustments","_ref2","scrollTo","observer","contentRect","memoizedCallback","prev","memoRectCallback","onResize","innerWidth","innerHeight","_instance$scrollEleme","_instance$scrollEleme2","_ref$adjustments","_ref"],"mappings":"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"}
1
+ {"version":3,"file":"index.production.js","sources":["../../src/utils.ts","../../src/index.ts"],"sourcesContent":["export type NoInfer<A extends any> = [A][A extends any ? 0 : never]\n\nexport type PartialKeys<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>\n\nexport function memo<TDeps extends readonly any[], TResult>(\n getDeps: () => [...TDeps],\n fn: (...args: NoInfer<[...TDeps]>) => TResult,\n opts: {\n key: any\n debug?: () => any\n onChange?: (result: TResult) => void\n initialDeps?: TDeps\n },\n) {\n let deps = opts.initialDeps ?? []\n let result: TResult | undefined\n\n return (): TResult => {\n let depTime: number\n if (opts.key && opts.debug?.()) depTime = Date.now()\n\n const newDeps = getDeps()\n\n const depsChanged =\n newDeps.length !== deps.length ||\n newDeps.some((dep: any, index: number) => deps[index] !== dep)\n\n if (!depsChanged) {\n return result!\n }\n\n deps = newDeps\n\n let resultTime: number\n if (opts.key && opts.debug?.()) resultTime = Date.now()\n\n result = fn(...newDeps)\n\n if (opts.key && opts.debug?.()) {\n const depEndTime = Math.round((Date.now() - depTime!) * 100) / 100\n const resultEndTime = Math.round((Date.now() - resultTime!) * 100) / 100\n const resultFpsPercentage = resultEndTime / 16\n\n const pad = (str: number | string, num: number) => {\n str = String(str)\n while (str.length < num) {\n str = ' ' + str\n }\n return str\n }\n\n console.info(\n `%c⏱ ${pad(resultEndTime, 5)} /${pad(depEndTime, 5)} ms`,\n `\n font-size: .6rem;\n font-weight: bold;\n color: hsl(${Math.max(\n 0,\n Math.min(120 - 120 * resultFpsPercentage, 120),\n )}deg 100% 31%);`,\n opts?.key,\n )\n }\n\n opts?.onChange?.(result)\n\n return result!\n }\n}\n\nexport function notUndefined<T>(value: T | undefined, msg?: string): T {\n if (value === undefined) {\n throw new Error(`Unexpected undefined${msg ? `: ${msg}` : ''}`)\n } else {\n return value\n }\n}\n\nexport const approxEqual = (a: number, b: number) => Math.abs(a - b) < 1\n","import { approxEqual, memo, notUndefined } from './utils'\n\nexport * from './utils'\n\n//\n\ntype ScrollDirection = 'forward' | 'backward'\n\ntype ScrollAlignment = 'start' | 'center' | 'end' | 'auto'\n\ntype ScrollBehavior = 'auto' | 'smooth'\n\nexport interface ScrollToOptions {\n align?: ScrollAlignment\n behavior?: ScrollBehavior\n}\n\ntype ScrollToOffsetOptions = ScrollToOptions\n\ntype ScrollToIndexOptions = ScrollToOptions\n\nexport interface Range {\n startIndex: number\n endIndex: number\n overscan: number\n count: number\n}\n\ntype Key = number | string\n\nexport interface VirtualItem {\n key: Key\n index: number\n start: number\n end: number\n size: number\n}\n\ninterface Rect {\n width: number\n height: number\n}\n\n//\n\nexport const defaultKeyExtractor = (index: number) => index\n\nexport const defaultRangeExtractor = (range: Range) => {\n const start = Math.max(range.startIndex - range.overscan, 0)\n const end = Math.min(range.endIndex + range.overscan, range.count - 1)\n\n const arr = []\n\n for (let i = start; i <= end; i++) {\n arr.push(i)\n }\n\n return arr\n}\n\nconst memoRectCallback = (\n instance: Virtualizer<any, any>,\n cb: (rect: Rect) => void,\n) => {\n let prev: Rect = { height: -1, width: -1 }\n\n return (rect: Rect) => {\n if (\n instance.options.horizontal\n ? rect.width !== prev.width\n : rect.height !== prev.height\n ) {\n cb(rect)\n }\n\n prev = rect\n }\n}\n\nexport const observeElementRect = (\n instance: Virtualizer<any, any>,\n cb: (rect: Rect) => void,\n) => {\n const observer = new ResizeObserver((entries) => {\n const entry = entries[0]\n if (entry) {\n const { width, height } = entry.contentRect\n cb({\n width: Math.round(width),\n height: Math.round(height),\n })\n } else {\n cb({ width: 0, height: 0 })\n }\n })\n\n if (!instance.scrollElement) {\n return\n }\n\n cb(instance.scrollElement.getBoundingClientRect())\n\n observer.observe(instance.scrollElement)\n\n return () => {\n observer.unobserve(instance.scrollElement)\n }\n}\n\nexport const observeWindowRect = (\n instance: Virtualizer<any, any>,\n cb: (rect: Rect) => void,\n) => {\n const memoizedCallback = memoRectCallback(instance, cb)\n const onResize = () =>\n memoizedCallback({\n width: instance.scrollElement.innerWidth,\n height: instance.scrollElement.innerHeight,\n })\n\n if (!instance.scrollElement) {\n return\n }\n\n onResize()\n\n instance.scrollElement.addEventListener('resize', onResize, {\n capture: false,\n passive: true,\n })\n\n return () => {\n instance.scrollElement.removeEventListener('resize', onResize)\n }\n}\n\ntype ObserverMode = 'element' | 'window'\n\nconst scrollProps = {\n element: ['scrollLeft', 'scrollTop'],\n window: ['scrollX', 'scrollY'],\n} as const\n\nconst createOffsetObserver = (mode: ObserverMode) => {\n return (instance: Virtualizer<any, any>, cb: (offset: number) => void) => {\n if (!instance.scrollElement) {\n return\n }\n\n const propX = scrollProps[mode][0]\n const propY = scrollProps[mode][1]\n\n let prevX: number = instance.scrollElement[propX]\n let prevY: number = instance.scrollElement[propY]\n\n const scroll = () => {\n const offset =\n instance.scrollElement[instance.options.horizontal ? propX : propY]\n\n cb(offset)\n }\n\n scroll()\n\n const onScroll = (e: Event) => {\n const target = e.currentTarget as HTMLElement & Window\n const scrollX = target[propX]\n const scrollY = target[propY]\n\n if (instance.options.horizontal ? prevX - scrollX : prevY - scrollY) {\n scroll()\n }\n\n prevX = scrollX\n prevY = scrollY\n }\n\n instance.scrollElement.addEventListener('scroll', onScroll, {\n capture: false,\n passive: true,\n })\n\n return () => {\n instance.scrollElement.removeEventListener('scroll', onScroll)\n }\n }\n}\n\nexport const observeElementOffset = createOffsetObserver('element')\nexport const observeWindowOffset = createOffsetObserver('window')\n\nexport const measureElement = <TItemElement extends Element>(\n element: TItemElement,\n instance: Virtualizer<any, TItemElement>,\n) => {\n return Math.round(\n element.getBoundingClientRect()[\n instance.options.horizontal ? 'width' : 'height'\n ],\n )\n}\n\nexport const windowScroll = <T extends Window>(\n offset: number,\n {\n adjustments = 0,\n behavior,\n }: { adjustments?: number; behavior?: ScrollBehavior },\n instance: Virtualizer<T, any>,\n) => {\n const toOffset = offset + adjustments\n\n instance.scrollElement?.scrollTo?.({\n [instance.options.horizontal ? 'left' : 'top']: toOffset,\n behavior,\n })\n}\n\nexport const elementScroll = <T extends Element>(\n offset: number,\n {\n adjustments = 0,\n behavior,\n }: { adjustments?: number; behavior?: ScrollBehavior },\n instance: Virtualizer<T, any>,\n) => {\n const toOffset = offset + adjustments\n\n instance.scrollElement?.scrollTo?.({\n [instance.options.horizontal ? 'left' : 'top']: toOffset,\n behavior,\n })\n}\n\nexport interface VirtualizerOptions<\n TScrollElement extends Element | Window,\n TItemElement extends Element,\n> {\n // Required from the user\n count: number\n getScrollElement: () => TScrollElement | null\n estimateSize: (index: number) => number\n\n // Required from the framework adapter (but can be overridden)\n scrollToFn: (\n offset: number,\n options: { adjustments?: number; behavior?: ScrollBehavior },\n instance: Virtualizer<TScrollElement, TItemElement>,\n ) => void\n observeElementRect: (\n instance: Virtualizer<TScrollElement, TItemElement>,\n cb: (rect: Rect) => void,\n ) => void | (() => void)\n observeElementOffset: (\n instance: Virtualizer<TScrollElement, TItemElement>,\n cb: (offset: number) => void,\n ) => void | (() => void)\n\n // Optional\n debug?: any\n initialRect?: Rect\n onChange?: (instance: Virtualizer<TScrollElement, TItemElement>) => void\n measureElement?: (\n el: TItemElement,\n instance: Virtualizer<TScrollElement, TItemElement>,\n ) => number\n overscan?: number\n horizontal?: boolean\n paddingStart?: number\n paddingEnd?: number\n scrollPaddingStart?: number\n scrollPaddingEnd?: number\n initialOffset?: number\n getItemKey?: (index: number) => Key\n rangeExtractor?: (range: Range) => number[]\n scrollMargin?: number\n scrollingDelay?: number\n indexAttribute?: string\n initialMeasurementsCache?: VirtualItem[]\n}\n\nexport class Virtualizer<\n TScrollElement extends Element | Window,\n TItemElement extends Element,\n> {\n private unsubs: (void | (() => void))[] = []\n options!: Required<VirtualizerOptions<TScrollElement, TItemElement>>\n scrollElement: TScrollElement | null = null\n isScrolling: boolean = false\n private isScrollingTimeoutId: ReturnType<typeof setTimeout> | null = null\n private scrollToIndexTimeoutId: ReturnType<typeof setTimeout> | null = null\n measurementsCache: VirtualItem[] = []\n private itemSizeCache: Record<Key, number> = {}\n private pendingMeasuredCacheIndexes: number[] = []\n private scrollRect: Rect\n scrollOffset: number\n scrollDirection: ScrollDirection | null = null\n private scrollAdjustments: number = 0\n private measureElementCache: Record<\n Key,\n TItemElement & { __virtualizerSkipFirstNotSync?: boolean }\n > = {}\n private getResizeObserver = (() => {\n let _ro: ResizeObserver | null = null\n\n return () => {\n if (_ro) {\n return _ro\n } else if (typeof ResizeObserver !== 'undefined') {\n return (_ro = new ResizeObserver((entries) => {\n entries.forEach((entry) => {\n this._measureElement(entry.target as TItemElement, false)\n })\n }))\n } else {\n return null\n }\n }\n })()\n range: { startIndex: number; endIndex: number } = {\n startIndex: 0,\n endIndex: 0,\n }\n\n constructor(opts: VirtualizerOptions<TScrollElement, TItemElement>) {\n this.setOptions(opts)\n this.scrollRect = this.options.initialRect\n this.scrollOffset = this.options.initialOffset\n this.measurementsCache = this.options.initialMeasurementsCache\n this.measurementsCache.forEach((item) => {\n this.itemSizeCache[item.key] = item.size\n })\n\n this.maybeNotify()\n }\n\n setOptions = (opts: VirtualizerOptions<TScrollElement, TItemElement>) => {\n Object.entries(opts).forEach(([key, value]) => {\n if (typeof value === 'undefined') delete (opts as any)[key]\n })\n\n this.options = {\n debug: false,\n initialOffset: 0,\n overscan: 1,\n paddingStart: 0,\n paddingEnd: 0,\n scrollPaddingStart: 0,\n scrollPaddingEnd: 0,\n horizontal: false,\n getItemKey: defaultKeyExtractor,\n rangeExtractor: defaultRangeExtractor,\n onChange: () => {},\n measureElement,\n initialRect: { width: 0, height: 0 },\n scrollMargin: 0,\n scrollingDelay: 150,\n indexAttribute: 'data-index',\n initialMeasurementsCache: [],\n ...opts,\n }\n }\n\n private notify = () => {\n this.options.onChange?.(this)\n }\n\n private cleanup = () => {\n this.unsubs.filter(Boolean).forEach((d) => d!())\n this.unsubs = []\n this.scrollElement = null\n }\n\n _didMount = () => {\n const ro = this.getResizeObserver()\n Object.values(this.measureElementCache).forEach((node) => ro?.observe(node))\n\n return () => {\n ro?.disconnect()\n\n this.cleanup()\n }\n }\n\n _willUpdate = () => {\n const scrollElement = this.options.getScrollElement()\n\n if (this.scrollElement !== scrollElement) {\n this.cleanup()\n\n this.scrollElement = scrollElement\n\n this._scrollToOffset(this.scrollOffset, {\n adjustments: undefined,\n behavior: undefined,\n })\n\n this.unsubs.push(\n this.options.observeElementRect(this, (rect) => {\n this.scrollRect = rect\n this.maybeNotify()\n }),\n )\n\n this.unsubs.push(\n this.options.observeElementOffset(this, (offset) => {\n this.scrollAdjustments = 0\n\n if (this.scrollOffset === offset) {\n return\n }\n\n if (this.isScrollingTimeoutId !== null) {\n clearTimeout(this.isScrollingTimeoutId)\n this.isScrollingTimeoutId = null\n }\n\n this.isScrolling = true\n this.scrollDirection =\n this.scrollOffset < offset ? 'forward' : 'backward'\n this.scrollOffset = offset\n\n this.maybeNotify()\n\n this.isScrollingTimeoutId = setTimeout(() => {\n this.isScrollingTimeoutId = null\n this.isScrolling = false\n this.scrollDirection = null\n\n this.maybeNotify()\n }, this.options.scrollingDelay)\n }),\n )\n }\n }\n\n private getSize = () => {\n return this.scrollRect[this.options.horizontal ? 'width' : 'height']\n }\n\n private getMeasurements = memo(\n () => [\n this.options.count,\n this.options.paddingStart,\n this.options.scrollMargin,\n this.options.getItemKey,\n this.itemSizeCache,\n ],\n (count, paddingStart, scrollMargin, getItemKey, itemSizeCache) => {\n const min =\n this.pendingMeasuredCacheIndexes.length > 0\n ? Math.min(...this.pendingMeasuredCacheIndexes)\n : 0\n this.pendingMeasuredCacheIndexes = []\n\n const measurements = this.measurementsCache.slice(0, min)\n\n for (let i = min; i < count; i++) {\n const key = getItemKey(i)\n const measuredSize = itemSizeCache[key]\n const start = measurements[i - 1]\n ? measurements[i - 1]!.end\n : paddingStart + scrollMargin\n const size =\n typeof measuredSize === 'number'\n ? measuredSize\n : this.options.estimateSize(i)\n const end = start + size\n measurements[i] = { index: i, start, size, end, key }\n }\n\n this.measurementsCache = measurements\n\n return measurements\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'getMeasurements',\n debug: () => this.options.debug,\n },\n )\n\n calculateRange = memo(\n () => [this.getMeasurements(), this.getSize(), this.scrollOffset],\n (measurements, outerSize, scrollOffset) => {\n return (this.range = calculateRange({\n measurements,\n outerSize,\n scrollOffset,\n }))\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'calculateRange',\n debug: () => this.options.debug,\n },\n )\n\n private maybeNotify = memo(\n () => [...Object.values(this.calculateRange()), this.isScrolling],\n () => {\n this.notify()\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'maybeNotify',\n debug: () => this.options.debug,\n initialDeps: [...Object.values(this.range), this.isScrolling],\n },\n )\n\n private getIndexes = memo(\n () => [\n this.options.rangeExtractor,\n this.calculateRange(),\n this.options.overscan,\n this.options.count,\n ],\n (rangeExtractor, range, overscan, count) => {\n return rangeExtractor({\n ...range,\n overscan,\n count,\n })\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'getIndexes',\n debug: () => this.options.debug,\n },\n )\n\n indexFromElement = (node: TItemElement) => {\n const attributeName = this.options.indexAttribute\n const indexStr = node.getAttribute(attributeName)\n\n if (!indexStr) {\n console.warn(\n `Missing attribute name '${attributeName}={index}' on measured element.`,\n )\n return -1\n }\n\n return parseInt(indexStr, 10)\n }\n\n private _measureElement = (node: TItemElement, sync: boolean) => {\n const index = this.indexFromElement(node)\n\n const item = this.measurementsCache[index]\n if (!item) {\n return\n }\n\n const prevNode = this.measureElementCache[item.key]\n\n const ro = this.getResizeObserver()\n\n if (!node.isConnected) {\n ro?.unobserve(node)\n if (node === prevNode) {\n delete this.measureElementCache[item.key]\n }\n return\n }\n\n if (prevNode !== node) {\n if (prevNode) {\n ro?.unobserve(prevNode)\n }\n ro?.observe(node)\n this.measureElementCache[item.key] = node\n } else {\n if (!sync && !prevNode.__virtualizerSkipFirstNotSync) {\n prevNode.__virtualizerSkipFirstNotSync = true\n return\n }\n }\n\n const measuredItemSize = this.options.measureElement(node, this)\n\n const itemSize = this.itemSizeCache[item.key] ?? item.size\n\n const delta = measuredItemSize - itemSize\n\n if (delta !== 0) {\n if (item.start < this.scrollOffset) {\n if (process.env.NODE_ENV !== 'production' && this.options.debug) {\n console.info('correction', delta)\n }\n\n this._scrollToOffset(this.scrollOffset, {\n adjustments: (this.scrollAdjustments += delta),\n behavior: undefined,\n })\n }\n\n this.pendingMeasuredCacheIndexes.push(index)\n this.itemSizeCache = {\n ...this.itemSizeCache,\n [item.key]: measuredItemSize,\n }\n this.notify()\n }\n }\n\n measureElement = (node: TItemElement | null) => {\n if (!node) {\n return\n }\n\n this._measureElement(node, true)\n }\n\n getVirtualItems = memo(\n () => [this.getIndexes(), this.getMeasurements()],\n (indexes, measurements) => {\n const virtualItems: VirtualItem[] = []\n\n for (let k = 0, len = indexes.length; k < len; k++) {\n const i = indexes[k]!\n const measurement = measurements[i]!\n\n virtualItems.push(measurement)\n }\n\n return virtualItems\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'getIndexes',\n debug: () => this.options.debug,\n },\n )\n\n getOffsetForAlignment = (toOffset: number, align: ScrollAlignment) => {\n const size = this.getSize()\n\n if (align === 'auto') {\n if (toOffset <= this.scrollOffset) {\n align = 'start'\n } else if (toOffset >= this.scrollOffset + size) {\n align = 'end'\n } else {\n align = 'start'\n }\n }\n\n if (align === 'start') {\n toOffset = toOffset\n } else if (align === 'end') {\n toOffset = toOffset - size\n } else if (align === 'center') {\n toOffset = toOffset - size / 2\n }\n\n const scrollSizeProp = this.options.horizontal\n ? 'scrollWidth'\n : 'scrollHeight'\n const scrollSize = this.scrollElement\n ? 'document' in this.scrollElement\n ? this.scrollElement.document.documentElement[scrollSizeProp]\n : this.scrollElement[scrollSizeProp]\n : 0\n\n const maxOffset = scrollSize - this.getSize()\n\n return Math.max(Math.min(maxOffset, toOffset), 0)\n }\n\n getOffsetForIndex = (index: number, align: ScrollAlignment = 'auto') => {\n index = Math.max(0, Math.min(index, this.options.count - 1))\n\n const measurement = notUndefined(this.getMeasurements()[index])\n\n if (align === 'auto') {\n if (\n measurement.end >=\n this.scrollOffset + this.getSize() - this.options.scrollPaddingEnd\n ) {\n align = 'end'\n } else if (\n measurement.start <=\n this.scrollOffset + this.options.scrollPaddingStart\n ) {\n align = 'start'\n } else {\n return [this.scrollOffset, align] as const\n }\n }\n\n const toOffset =\n align === 'end'\n ? measurement.end + this.options.scrollPaddingEnd\n : measurement.start - this.options.scrollPaddingStart\n\n return [this.getOffsetForAlignment(toOffset, align), align] as const\n }\n\n private isDynamicMode = () => Object.keys(this.measureElementCache).length > 0\n\n private cancelScrollToIndex = () => {\n if (this.scrollToIndexTimeoutId !== null) {\n clearTimeout(this.scrollToIndexTimeoutId)\n this.scrollToIndexTimeoutId = null\n }\n }\n\n scrollToOffset = (\n toOffset: number,\n { align = 'start', behavior }: ScrollToOffsetOptions = {},\n ) => {\n this.cancelScrollToIndex()\n\n if (behavior === 'smooth' && this.isDynamicMode()) {\n console.warn(\n 'The `smooth` scroll behavior is not fully supported with dynamic size.',\n )\n }\n\n this._scrollToOffset(this.getOffsetForAlignment(toOffset, align), {\n adjustments: undefined,\n behavior,\n })\n }\n\n scrollToIndex = (\n index: number,\n { align: initialAlign = 'auto', behavior }: ScrollToIndexOptions = {},\n ) => {\n index = Math.max(0, Math.min(index, this.options.count - 1))\n\n this.cancelScrollToIndex()\n\n if (behavior === 'smooth' && this.isDynamicMode()) {\n console.warn(\n 'The `smooth` scroll behavior is not fully supported with dynamic size.',\n )\n }\n\n const [toOffset, align] = this.getOffsetForIndex(index, initialAlign)\n\n this._scrollToOffset(toOffset, { adjustments: undefined, behavior })\n\n if (behavior !== 'smooth' && this.isDynamicMode()) {\n this.scrollToIndexTimeoutId = setTimeout(() => {\n this.scrollToIndexTimeoutId = null\n\n const elementInDOM =\n !!this.measureElementCache[this.options.getItemKey(index)]\n\n if (elementInDOM) {\n const [toOffset] = this.getOffsetForIndex(index, align)\n\n if (!approxEqual(toOffset, this.scrollOffset)) {\n this.scrollToIndex(index, { align, behavior })\n }\n } else {\n this.scrollToIndex(index, { align, behavior })\n }\n })\n }\n }\n\n scrollBy = (delta: number, { behavior }: ScrollToOffsetOptions = {}) => {\n this.cancelScrollToIndex()\n\n if (behavior === 'smooth' && this.isDynamicMode()) {\n console.warn(\n 'The `smooth` scroll behavior is not fully supported with dynamic size.',\n )\n }\n\n this._scrollToOffset(this.scrollOffset + delta, {\n adjustments: undefined,\n behavior,\n })\n }\n\n getTotalSize = () =>\n (this.getMeasurements()[this.options.count - 1]?.end ||\n this.options.paddingStart) -\n this.options.scrollMargin +\n this.options.paddingEnd\n\n private _scrollToOffset = (\n offset: number,\n {\n adjustments,\n behavior,\n }: {\n adjustments: number | undefined\n behavior: ScrollBehavior | undefined\n },\n ) => {\n this.options.scrollToFn(offset, { behavior, adjustments }, this)\n }\n\n measure = () => {\n this.itemSizeCache = {}\n this.notify()\n }\n}\n\nconst findNearestBinarySearch = (\n low: number,\n high: number,\n getCurrentValue: (i: number) => number,\n value: number,\n) => {\n while (low <= high) {\n const middle = ((low + high) / 2) | 0\n const currentValue = getCurrentValue(middle)\n\n if (currentValue < value) {\n low = middle + 1\n } else if (currentValue > value) {\n high = middle - 1\n } else {\n return middle\n }\n }\n\n if (low > 0) {\n return low - 1\n } else {\n return 0\n }\n}\n\nfunction calculateRange({\n measurements,\n outerSize,\n scrollOffset,\n}: {\n measurements: VirtualItem[]\n outerSize: number\n scrollOffset: number\n}) {\n const count = measurements.length - 1\n const getOffset = (index: number) => measurements[index]!.start\n\n const startIndex = findNearestBinarySearch(0, count, getOffset, scrollOffset)\n let endIndex = startIndex\n\n while (\n endIndex < count &&\n measurements[endIndex]!.end < scrollOffset + outerSize\n ) {\n endIndex++\n }\n\n return { startIndex, endIndex }\n}\n"],"names":["memo","getDeps","fn","opts","_opts$initialDeps","result","deps","initialDeps","depTime","key","debug","Date","now","resultTime","newDeps","length","some","dep","index","depEndTime","Math","round","resultEndTime","resultFpsPercentage","pad","str","num","String","console","info","max","min","onChange","notUndefined","value","msg","undefined","Error","approxEqual","a","b","abs","defaultKeyExtractor","defaultRangeExtractor","range","start","startIndex","overscan","end","endIndex","count","arr","i","push","scrollProps","element","window","createOffsetObserver","mode","instance","cb","scrollElement","propX","propY","prevX","prevY","scroll","offset","options","horizontal","onScroll","e","target","currentTarget","scrollX","scrollY","addEventListener","capture","passive","removeEventListener","observeElementOffset","observeWindowOffset","measureElement","getBoundingClientRect","_ro","_this","this","unsubs","isScrolling","isScrollingTimeoutId","scrollToIndexTimeoutId","measurementsCache","itemSizeCache","pendingMeasuredCacheIndexes","scrollDirection","scrollAdjustments","measureElementCache","getResizeObserver","ResizeObserver","entries","forEach","entry","_measureElement","setOptions","Object","_ref3","_extends","initialOffset","paddingStart","paddingEnd","scrollPaddingStart","scrollPaddingEnd","getItemKey","rangeExtractor","initialRect","width","height","scrollMargin","scrollingDelay","indexAttribute","initialMeasurementsCache","notify","cleanup","filter","Boolean","d","_didMount","ro","values","node","observe","disconnect","_willUpdate","getScrollElement","_scrollToOffset","scrollOffset","adjustments","behavior","observeElementRect","rect","scrollRect","maybeNotify","clearTimeout","setTimeout","getSize","getMeasurements","measurements","slice","measuredSize","size","estimateSize","process","calculateRange","outerSize","_ref8","low","high","getCurrentValue","middle","currentValue","findNearestBinarySearch","concat","getIndexes","indexFromElement","attributeName","indexStr","getAttribute","parseInt","warn","sync","_this$itemSizeCache$i","item","prevNode","isConnected","unobserve","__virtualizerSkipFirstNotSync","_extends2","measuredItemSize","delta","getVirtualItems","indexes","virtualItems","k","len","measurement","getOffsetForAlignment","toOffset","align","scrollSizeProp","maxOffset","document","documentElement","getOffsetForIndex","isDynamicMode","keys","cancelScrollToIndex","scrollToOffset","_temp","_ref4","_ref4$align","scrollToIndex","_temp2","_ref5","_ref5$align","initialAlign","_this$getOffsetForInd","scrollBy","_temp3","getTotalSize","_this$getMeasurements","_ref7","scrollToFn","measure","_instance$scrollEleme3","_instance$scrollEleme4","_ref2$adjustments","_ref2","scrollTo","observer","contentRect","memoizedCallback","prev","memoRectCallback","onResize","innerWidth","innerHeight","_instance$scrollEleme","_instance$scrollEleme2","_ref$adjustments","_ref"],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tanstack/virtual-core",
3
3
  "author": "Tanner Linsley",
4
- "version": "3.0.0-beta.42",
4
+ "version": "3.0.0-beta.44",
5
5
  "description": "Headless UI for virtualizing scrollable elements in TS/JS + Frameworks",
6
6
  "license": "MIT",
7
7
  "homepage": "https://github.com/tanstack/virtual#readme",
package/src/index.ts CHANGED
@@ -331,7 +331,7 @@ export class Virtualizer<
331
331
  this.itemSizeCache[item.key] = item.size
332
332
  })
333
333
 
334
- this.calculateRange()
334
+ this.maybeNotify()
335
335
  }
336
336
 
337
337
  setOptions = (opts: VirtualizerOptions<TScrollElement, TItemElement>) => {
@@ -398,7 +398,7 @@ export class Virtualizer<
398
398
  this.unsubs.push(
399
399
  this.options.observeElementRect(this, (rect) => {
400
400
  this.scrollRect = rect
401
- this.calculateRange()
401
+ this.maybeNotify()
402
402
  }),
403
403
  )
404
404
 
@@ -415,26 +415,19 @@ export class Virtualizer<
415
415
  this.isScrollingTimeoutId = null
416
416
  }
417
417
 
418
- const onIsScrollingChange = (isScrolling: boolean) => {
419
- if (this.isScrolling !== isScrolling) {
420
- this.isScrolling = isScrolling
421
- this.notify()
422
- }
423
- }
424
-
418
+ this.isScrolling = true
425
419
  this.scrollDirection =
426
420
  this.scrollOffset < offset ? 'forward' : 'backward'
427
-
428
421
  this.scrollOffset = offset
429
422
 
430
- this.calculateRange()
431
-
432
- onIsScrollingChange(true)
423
+ this.maybeNotify()
433
424
 
434
425
  this.isScrollingTimeoutId = setTimeout(() => {
435
426
  this.isScrollingTimeoutId = null
427
+ this.isScrolling = false
436
428
  this.scrollDirection = null
437
- onIsScrollingChange(false)
429
+
430
+ this.maybeNotify()
438
431
  }, this.options.scrollingDelay)
439
432
  }),
440
433
  )
@@ -488,22 +481,12 @@ export class Virtualizer<
488
481
 
489
482
  calculateRange = memo(
490
483
  () => [this.getMeasurements(), this.getSize(), this.scrollOffset],
491
- (measurements, outerSize, scrollOffset, [flush = true]: [boolean?]) => {
492
- const range = calculateRange({
484
+ (measurements, outerSize, scrollOffset) => {
485
+ return (this.range = calculateRange({
493
486
  measurements,
494
487
  outerSize,
495
488
  scrollOffset,
496
- })
497
- if (
498
- range.startIndex !== this.range.startIndex ||
499
- range.endIndex !== this.range.endIndex
500
- ) {
501
- this.range = range
502
- if (flush) {
503
- this.notify()
504
- }
505
- }
506
- return this.range
489
+ }))
507
490
  },
508
491
  {
509
492
  key: process.env.NODE_ENV !== 'production' && 'calculateRange',
@@ -511,10 +494,22 @@ export class Virtualizer<
511
494
  },
512
495
  )
513
496
 
497
+ private maybeNotify = memo(
498
+ () => [...Object.values(this.calculateRange()), this.isScrolling],
499
+ () => {
500
+ this.notify()
501
+ },
502
+ {
503
+ key: process.env.NODE_ENV !== 'production' && 'maybeNotify',
504
+ debug: () => this.options.debug,
505
+ initialDeps: [...Object.values(this.range), this.isScrolling],
506
+ },
507
+ )
508
+
514
509
  private getIndexes = memo(
515
510
  () => [
516
511
  this.options.rangeExtractor,
517
- this.calculateRange(false),
512
+ this.calculateRange(),
518
513
  this.options.overscan,
519
514
  this.options.count,
520
515
  ],
@@ -668,47 +663,9 @@ export class Virtualizer<
668
663
  return Math.max(Math.min(maxOffset, toOffset), 0)
669
664
  }
670
665
 
671
- scrollToOffset = (
672
- toOffset: number,
673
- { align = 'start', behavior }: ScrollToOffsetOptions = {},
674
- ) => {
675
- const isDynamic = Object.keys(this.measureElementCache).length > 0
676
-
677
- if (isDynamic && behavior === 'smooth') {
678
- console.warn(
679
- 'The `smooth` scroll behavior is not supported with dynamic size.',
680
- )
681
- return
682
- }
683
-
684
- const options = {
685
- adjustments: undefined,
686
- behavior,
687
- sync: false,
688
- }
689
- this._scrollToOffset(this.getOffsetForAlignment(toOffset, align), options)
690
- }
691
-
692
- scrollToIndex = (
693
- index: number,
694
- { align = 'auto', behavior }: ScrollToIndexOptions = {},
695
- ) => {
666
+ getOffsetForIndex = (index: number, align: ScrollAlignment = 'auto') => {
696
667
  index = Math.max(0, Math.min(index, this.options.count - 1))
697
668
 
698
- if (this.scrollToIndexTimeoutId !== null) {
699
- clearTimeout(this.scrollToIndexTimeoutId)
700
- this.scrollToIndexTimeoutId = null
701
- }
702
-
703
- const isDynamic = Object.keys(this.measureElementCache).length > 0
704
-
705
- if (isDynamic && behavior === 'smooth') {
706
- console.warn(
707
- 'The `smooth` scroll behavior is not supported with dynamic size.',
708
- )
709
- return
710
- }
711
-
712
669
  const measurement = notUndefined(this.getMeasurements()[index])
713
670
 
714
671
  if (align === 'auto') {
@@ -723,28 +680,64 @@ export class Virtualizer<
723
680
  ) {
724
681
  align = 'start'
725
682
  } else {
726
- return
683
+ return [this.scrollOffset, align] as const
727
684
  }
728
685
  }
729
686
 
730
- const getOffsetForIndexAndAlignment = (measurement: VirtualItem) => {
731
- const toOffset =
732
- align === 'end'
733
- ? measurement.end + this.options.scrollPaddingEnd
734
- : measurement.start - this.options.scrollPaddingStart
687
+ const toOffset =
688
+ align === 'end'
689
+ ? measurement.end + this.options.scrollPaddingEnd
690
+ : measurement.start - this.options.scrollPaddingStart
735
691
 
736
- return this.getOffsetForAlignment(toOffset, align)
692
+ return [this.getOffsetForAlignment(toOffset, align), align] as const
693
+ }
694
+
695
+ private isDynamicMode = () => Object.keys(this.measureElementCache).length > 0
696
+
697
+ private cancelScrollToIndex = () => {
698
+ if (this.scrollToIndexTimeoutId !== null) {
699
+ clearTimeout(this.scrollToIndexTimeoutId)
700
+ this.scrollToIndexTimeoutId = null
737
701
  }
702
+ }
703
+
704
+ scrollToOffset = (
705
+ toOffset: number,
706
+ { align = 'start', behavior }: ScrollToOffsetOptions = {},
707
+ ) => {
708
+ this.cancelScrollToIndex()
738
709
 
739
- const toOffset = getOffsetForIndexAndAlignment(measurement)
710
+ if (behavior === 'smooth' && this.isDynamicMode()) {
711
+ console.warn(
712
+ 'The `smooth` scroll behavior is not fully supported with dynamic size.',
713
+ )
714
+ }
740
715
 
741
- const options = {
716
+ this._scrollToOffset(this.getOffsetForAlignment(toOffset, align), {
742
717
  adjustments: undefined,
743
718
  behavior,
719
+ })
720
+ }
721
+
722
+ scrollToIndex = (
723
+ index: number,
724
+ { align: initialAlign = 'auto', behavior }: ScrollToIndexOptions = {},
725
+ ) => {
726
+ index = Math.max(0, Math.min(index, this.options.count - 1))
727
+
728
+ this.cancelScrollToIndex()
729
+
730
+ if (behavior === 'smooth' && this.isDynamicMode()) {
731
+ console.warn(
732
+ 'The `smooth` scroll behavior is not fully supported with dynamic size.',
733
+ )
744
734
  }
745
- this._scrollToOffset(toOffset, options)
746
735
 
747
- if (isDynamic) {
736
+ const [toOffset, align] = this.getOffsetForIndex(index, initialAlign)
737
+
738
+ this._scrollToOffset(toOffset, { adjustments: undefined, behavior })
739
+
740
+ if (behavior !== 'smooth' && this.isDynamicMode()) {
748
741
  this.scrollToIndexTimeoutId = setTimeout(() => {
749
742
  this.scrollToIndexTimeoutId = null
750
743
 
@@ -752,9 +745,7 @@ export class Virtualizer<
752
745
  !!this.measureElementCache[this.options.getItemKey(index)]
753
746
 
754
747
  if (elementInDOM) {
755
- const toOffset = getOffsetForIndexAndAlignment(
756
- notUndefined(this.getMeasurements()[index]),
757
- )
748
+ const [toOffset] = this.getOffsetForIndex(index, align)
758
749
 
759
750
  if (!approxEqual(toOffset, this.scrollOffset)) {
760
751
  this.scrollToIndex(index, { align, behavior })
@@ -767,13 +758,12 @@ export class Virtualizer<
767
758
  }
768
759
 
769
760
  scrollBy = (delta: number, { behavior }: ScrollToOffsetOptions = {}) => {
770
- const isDynamic = Object.keys(this.measureElementCache).length > 0
761
+ this.cancelScrollToIndex()
771
762
 
772
- if (isDynamic && behavior === 'smooth') {
763
+ if (behavior === 'smooth' && this.isDynamicMode()) {
773
764
  console.warn(
774
- 'The `smooth` scroll behavior is not supported with dynamic size.',
765
+ 'The `smooth` scroll behavior is not fully supported with dynamic size.',
775
766
  )
776
- return
777
767
  }
778
768
 
779
769
  this._scrollToOffset(this.scrollOffset + delta, {
package/src/utils.ts CHANGED
@@ -2,23 +2,20 @@ export type NoInfer<A extends any> = [A][A extends any ? 0 : never]
2
2
 
3
3
  export type PartialKeys<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>
4
4
 
5
- export function memo<
6
- TDeps extends readonly any[],
7
- TResult,
8
- FArgs extends readonly any[],
9
- >(
5
+ export function memo<TDeps extends readonly any[], TResult>(
10
6
  getDeps: () => [...TDeps],
11
- fn: (...args: [...TDeps, FArgs]) => TResult,
7
+ fn: (...args: NoInfer<[...TDeps]>) => TResult,
12
8
  opts: {
13
9
  key: any
14
10
  debug?: () => any
15
11
  onChange?: (result: TResult) => void
12
+ initialDeps?: TDeps
16
13
  },
17
14
  ) {
18
- let deps: any[] = []
15
+ let deps = opts.initialDeps ?? []
19
16
  let result: TResult | undefined
20
17
 
21
- return (...fArgs: FArgs): TResult => {
18
+ return (): TResult => {
22
19
  let depTime: number
23
20
  if (opts.key && opts.debug?.()) depTime = Date.now()
24
21
 
@@ -37,8 +34,7 @@ export function memo<
37
34
  let resultTime: number
38
35
  if (opts.key && opts.debug?.()) resultTime = Date.now()
39
36
 
40
- result = fn(...newDeps, fArgs)
41
- opts?.onChange?.(result)
37
+ result = fn(...newDeps)
42
38
 
43
39
  if (opts.key && opts.debug?.()) {
44
40
  const depEndTime = Math.round((Date.now() - depTime!) * 100) / 100
@@ -66,6 +62,8 @@ export function memo<
66
62
  )
67
63
  }
68
64
 
65
+ opts?.onChange?.(result)
66
+
69
67
  return result!
70
68
  }
71
69
  }