@tanstack/virtual-core 3.3.0 → 3.5.0

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.
@@ -41,6 +41,9 @@ const observeElementRect = (instance, cb) => {
41
41
  observer.unobserve(element);
42
42
  };
43
43
  };
44
+ const addEventListenerOptions = {
45
+ passive: true
46
+ };
44
47
  const observeWindowRect = (instance, cb) => {
45
48
  const element = instance.scrollElement;
46
49
  if (!element) {
@@ -50,27 +53,34 @@ const observeWindowRect = (instance, cb) => {
50
53
  cb({ width: element.innerWidth, height: element.innerHeight });
51
54
  };
52
55
  handler();
53
- element.addEventListener("resize", handler, {
54
- passive: true
55
- });
56
+ element.addEventListener("resize", handler, addEventListenerOptions);
56
57
  return () => {
57
58
  element.removeEventListener("resize", handler);
58
59
  };
59
60
  };
61
+ const supportsScrollend = typeof window == "undefined" ? true : "onscrollend" in window;
60
62
  const observeElementOffset = (instance, cb) => {
61
63
  const element = instance.scrollElement;
62
64
  if (!element) {
63
65
  return;
64
66
  }
65
- const handler = () => {
66
- cb(element[instance.options.horizontal ? "scrollLeft" : "scrollTop"]);
67
+ let offset = 0;
68
+ const fallback = supportsScrollend ? () => void 0 : utils.debounce(() => {
69
+ cb(offset, false);
70
+ }, instance.options.isScrollingResetDelay);
71
+ const createHandler = (isScrolling) => () => {
72
+ offset = element[instance.options.horizontal ? "scrollLeft" : "scrollTop"];
73
+ fallback();
74
+ cb(offset, isScrolling);
67
75
  };
68
- handler();
69
- element.addEventListener("scroll", handler, {
70
- passive: true
71
- });
76
+ const handler = createHandler(true);
77
+ const endHandler = createHandler(false);
78
+ endHandler();
79
+ element.addEventListener("scroll", handler, addEventListenerOptions);
80
+ element.addEventListener("scrollend", endHandler, addEventListenerOptions);
72
81
  return () => {
73
82
  element.removeEventListener("scroll", handler);
83
+ element.removeEventListener("scrollend", endHandler);
74
84
  };
75
85
  };
76
86
  const observeWindowOffset = (instance, cb) => {
@@ -78,15 +88,23 @@ const observeWindowOffset = (instance, cb) => {
78
88
  if (!element) {
79
89
  return;
80
90
  }
81
- const handler = () => {
82
- cb(element[instance.options.horizontal ? "scrollX" : "scrollY"]);
91
+ let offset = 0;
92
+ const fallback = supportsScrollend ? () => void 0 : utils.debounce(() => {
93
+ cb(offset, false);
94
+ }, instance.options.isScrollingResetDelay);
95
+ const createHandler = (isScrolling) => () => {
96
+ offset = element[instance.options.horizontal ? "scrollX" : "scrollY"];
97
+ fallback();
98
+ cb(offset, isScrolling);
83
99
  };
84
- handler();
85
- element.addEventListener("scroll", handler, {
86
- passive: true
87
- });
100
+ const handler = createHandler(true);
101
+ const endHandler = createHandler(false);
102
+ endHandler();
103
+ element.addEventListener("scroll", handler, addEventListenerOptions);
104
+ element.addEventListener("scrollend", endHandler, addEventListenerOptions);
88
105
  return () => {
89
106
  element.removeEventListener("scroll", handler);
107
+ element.removeEventListener("scrollend", endHandler);
90
108
  };
91
109
  };
92
110
  const measureElement = (element, entry, instance) => {
@@ -130,7 +148,6 @@ class Virtualizer {
130
148
  this.unsubs = [];
131
149
  this.scrollElement = null;
132
150
  this.isScrolling = false;
133
- this.isScrollingTimeoutId = null;
134
151
  this.scrollToIndexTimeoutId = null;
135
152
  this.measurementsCache = [];
136
153
  this.itemSizeCache = /* @__PURE__ */ new Map();
@@ -191,39 +208,24 @@ class Virtualizer {
191
208
  initialRect: { width: 0, height: 0 },
192
209
  scrollMargin: 0,
193
210
  gap: 0,
194
- scrollingDelay: 150,
195
211
  indexAttribute: "data-index",
196
212
  initialMeasurementsCache: [],
197
213
  lanes: 1,
214
+ isScrollingResetDelay: 150,
198
215
  ...opts2
199
216
  };
200
217
  };
201
- this.notify = (sync) => {
218
+ this.notify = (force, sync) => {
202
219
  var _a, _b;
203
- (_b = (_a = this.options).onChange) == null ? void 0 : _b.call(_a, this, sync);
204
- };
205
- this.maybeNotify = utils.memo(
206
- () => {
207
- this.calculateRange();
208
- return [
209
- this.isScrolling,
210
- this.range ? this.range.startIndex : null,
211
- this.range ? this.range.endIndex : null
212
- ];
213
- },
214
- (isScrolling) => {
215
- this.notify(isScrolling);
216
- },
217
- {
218
- key: process.env.NODE_ENV !== "production" && "maybeNotify",
219
- debug: () => this.options.debug,
220
- initialDeps: [
221
- this.isScrolling,
222
- this.range ? this.range.startIndex : null,
223
- this.range ? this.range.endIndex : null
224
- ]
220
+ const { startIndex, endIndex } = this.range ?? {
221
+ startIndex: void 0,
222
+ endIndex: void 0
223
+ };
224
+ const range = this.calculateRange();
225
+ if (force || startIndex !== (range == null ? void 0 : range.startIndex) || endIndex !== (range == null ? void 0 : range.endIndex)) {
226
+ (_b = (_a = this.options).onChange) == null ? void 0 : _b.call(_a, this, sync);
225
227
  }
226
- );
228
+ };
227
229
  this.cleanup = () => {
228
230
  this.unsubs.filter(Boolean).forEach((d) => d());
229
231
  this.unsubs = [];
@@ -248,29 +250,17 @@ class Virtualizer {
248
250
  this.unsubs.push(
249
251
  this.options.observeElementRect(this, (rect) => {
250
252
  this.scrollRect = rect;
251
- this.maybeNotify();
253
+ this.notify(false, false);
252
254
  })
253
255
  );
254
256
  this.unsubs.push(
255
- this.options.observeElementOffset(this, (offset) => {
257
+ this.options.observeElementOffset(this, (offset, isScrolling) => {
256
258
  this.scrollAdjustments = 0;
257
- if (this.scrollOffset === offset) {
258
- return;
259
- }
260
- if (this.isScrollingTimeoutId !== null) {
261
- clearTimeout(this.isScrollingTimeoutId);
262
- this.isScrollingTimeoutId = null;
263
- }
264
- this.isScrolling = true;
265
- this.scrollDirection = this.scrollOffset < offset ? "forward" : "backward";
259
+ this.scrollDirection = isScrolling ? this.scrollOffset < offset ? "forward" : "backward" : null;
266
260
  this.scrollOffset = offset;
267
- this.maybeNotify();
268
- this.isScrollingTimeoutId = setTimeout(() => {
269
- this.isScrollingTimeoutId = null;
270
- this.isScrolling = false;
271
- this.scrollDirection = null;
272
- this.maybeNotify();
273
- }, this.options.scrollingDelay);
261
+ const prevIsScrolling = this.isScrolling;
262
+ this.isScrolling = isScrolling;
263
+ this.notify(prevIsScrolling !== isScrolling, isScrolling);
274
264
  })
275
265
  );
276
266
  }
@@ -278,7 +268,7 @@ class Virtualizer {
278
268
  this.getSize = () => {
279
269
  return this.scrollRect[this.options.horizontal ? "width" : "height"];
280
270
  };
281
- this.memoOptions = utils.memo(
271
+ this.getMeasurementOptions = utils.memo(
282
272
  () => [
283
273
  this.options.count,
284
274
  this.options.paddingStart,
@@ -326,7 +316,7 @@ class Virtualizer {
326
316
  })[0] : void 0;
327
317
  };
328
318
  this.getMeasurements = utils.memo(
329
- () => [this.memoOptions(), this.itemSizeCache],
319
+ () => [this.getMeasurementOptions(), this.itemSizeCache],
330
320
  ({ count, paddingStart, scrollMargin, getItemKey }, itemSizeCache) => {
331
321
  const min = this.pendingMeasuredCacheIndexes.length > 0 ? Math.min(...this.pendingMeasuredCacheIndexes) : 0;
332
322
  this.pendingMeasuredCacheIndexes = [];
@@ -379,7 +369,8 @@ class Virtualizer {
379
369
  ],
380
370
  (rangeExtractor, range, overscan, count) => {
381
371
  return range === null ? [] : rangeExtractor({
382
- ...range,
372
+ startIndex: range.startIndex,
373
+ endIndex: range.endIndex,
383
374
  overscan,
384
375
  count
385
376
  });
@@ -437,7 +428,7 @@ class Virtualizer {
437
428
  }
438
429
  this.pendingMeasuredCacheIndexes.push(item.index);
439
430
  this.itemSizeCache = new Map(this.itemSizeCache.set(item.key, size));
440
- this.notify(false);
431
+ this.notify(true, false);
441
432
  }
442
433
  };
443
434
  this.measureElement = (node) => {
@@ -589,8 +580,9 @@ class Virtualizer {
589
580
  this.options.scrollToFn(offset, { behavior, adjustments }, this);
590
581
  };
591
582
  this.measure = () => {
583
+ var _a, _b;
592
584
  this.itemSizeCache = /* @__PURE__ */ new Map();
593
- this.notify(false);
585
+ (_b = (_a = this.options).onChange) == null ? void 0 : _b.call(_a, this, false);
594
586
  };
595
587
  this.setOptions(opts);
596
588
  this.scrollRect = this.options.initialRect;
@@ -599,7 +591,7 @@ class Virtualizer {
599
591
  this.measurementsCache.forEach((item) => {
600
592
  this.itemSizeCache.set(item.key, item.size);
601
593
  });
602
- this.maybeNotify();
594
+ this.notify(false, false);
603
595
  }
604
596
  }
605
597
  const findNearestBinarySearch = (low, high, getCurrentValue, value) => {
@@ -635,6 +627,7 @@ function calculateRange({
635
627
  return { startIndex, endIndex };
636
628
  }
637
629
  exports.approxEqual = utils.approxEqual;
630
+ exports.debounce = utils.debounce;
638
631
  exports.memo = utils.memo;
639
632
  exports.notUndefined = utils.notUndefined;
640
633
  exports.Virtualizer = Virtualizer;
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../../src/index.ts"],"sourcesContent":["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 lane: number\n}\n\nexport interface 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\nexport const observeElementRect = <T extends Element>(\n instance: Virtualizer<T, any>,\n cb: (rect: Rect) => void,\n) => {\n const element = instance.scrollElement\n if (!element) {\n return\n }\n\n const handler = (rect: Rect) => {\n const { width, height } = rect\n cb({ width: Math.round(width), height: Math.round(height) })\n }\n\n handler(element.getBoundingClientRect())\n\n if (typeof ResizeObserver === 'undefined') {\n return () => {}\n }\n\n const observer = new ResizeObserver((entries) => {\n const entry = entries[0]\n if (entry?.borderBoxSize) {\n const box = entry.borderBoxSize[0]\n if (box) {\n handler({ width: box.inlineSize, height: box.blockSize })\n return\n }\n }\n handler(element.getBoundingClientRect())\n })\n\n observer.observe(element, { box: 'border-box' })\n\n return () => {\n observer.unobserve(element)\n }\n}\n\nexport const observeWindowRect = (\n instance: Virtualizer<Window, any>,\n cb: (rect: Rect) => void,\n) => {\n const element = instance.scrollElement\n if (!element) {\n return\n }\n\n const handler = () => {\n cb({ width: element.innerWidth, height: element.innerHeight })\n }\n handler()\n\n element.addEventListener('resize', handler, {\n passive: true,\n })\n\n return () => {\n element.removeEventListener('resize', handler)\n }\n}\n\nexport const observeElementOffset = <T extends Element>(\n instance: Virtualizer<T, any>,\n cb: (offset: number) => void,\n) => {\n const element = instance.scrollElement\n if (!element) {\n return\n }\n\n const handler = () => {\n cb(element[instance.options.horizontal ? 'scrollLeft' : 'scrollTop'])\n }\n handler()\n\n element.addEventListener('scroll', handler, {\n passive: true,\n })\n\n return () => {\n element.removeEventListener('scroll', handler)\n }\n}\n\nexport const observeWindowOffset = (\n instance: Virtualizer<Window, any>,\n cb: (offset: number) => void,\n) => {\n const element = instance.scrollElement\n if (!element) {\n return\n }\n\n const handler = () => {\n cb(element[instance.options.horizontal ? 'scrollX' : 'scrollY'])\n }\n handler()\n\n element.addEventListener('scroll', handler, {\n passive: true,\n })\n\n return () => {\n element.removeEventListener('scroll', handler)\n }\n}\n\nexport const measureElement = <TItemElement extends Element>(\n element: TItemElement,\n entry: ResizeObserverEntry | undefined,\n instance: Virtualizer<any, TItemElement>,\n) => {\n if (entry?.borderBoxSize) {\n const box = entry.borderBoxSize[0]\n if (box) {\n const size = Math.round(\n box[instance.options.horizontal ? 'inlineSize' : 'blockSize'],\n )\n return size\n }\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?: (\n instance: Virtualizer<TScrollElement, TItemElement>,\n sync: boolean,\n ) => void\n measureElement?: (\n element: TItemElement,\n entry: ResizeObserverEntry | undefined,\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 | (() => number)\n getItemKey?: (index: number) => Key\n rangeExtractor?: (range: Range) => number[]\n scrollMargin?: number\n gap?: number\n scrollingDelay?: number\n indexAttribute?: string\n initialMeasurementsCache?: VirtualItem[]\n lanes?: number\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 = new Map<Key, number>()\n private pendingMeasuredCacheIndexes: number[] = []\n scrollRect: Rect\n scrollOffset: number\n scrollDirection: ScrollDirection | null = null\n private scrollAdjustments: number = 0\n shouldAdjustScrollPositionOnItemSizeChange:\n | undefined\n | ((\n item: VirtualItem,\n delta: number,\n instance: Virtualizer<TScrollElement, TItemElement>,\n ) => boolean)\n measureElementCache = new Map<Key, TItemElement>()\n private observer = (() => {\n let _ro: ResizeObserver | null = null\n\n const get = () => {\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, entry)\n })\n }))\n } else {\n return null\n }\n }\n\n return {\n disconnect: () => get()?.disconnect(),\n observe: (target: Element) =>\n get()?.observe(target, { box: 'border-box' }),\n unobserve: (target: Element) => get()?.unobserve(target),\n }\n })()\n range: { startIndex: number; endIndex: number } | null = null\n\n constructor(opts: VirtualizerOptions<TScrollElement, TItemElement>) {\n this.setOptions(opts)\n this.scrollRect = this.options.initialRect\n this.scrollOffset =\n typeof this.options.initialOffset === 'function'\n ? this.options.initialOffset()\n : this.options.initialOffset\n this.measurementsCache = this.options.initialMeasurementsCache\n this.measurementsCache.forEach((item) => {\n this.itemSizeCache.set(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 gap: 0,\n scrollingDelay: 150,\n indexAttribute: 'data-index',\n initialMeasurementsCache: [],\n lanes: 1,\n ...opts,\n }\n }\n\n private notify = (sync: boolean) => {\n this.options.onChange?.(this, sync)\n }\n\n private maybeNotify = memo(\n () => {\n this.calculateRange()\n\n return [\n this.isScrolling,\n this.range ? this.range.startIndex : null,\n this.range ? this.range.endIndex : null,\n ]\n },\n (isScrolling) => {\n this.notify(isScrolling)\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'maybeNotify',\n debug: () => this.options.debug,\n initialDeps: [\n this.isScrolling,\n this.range ? this.range.startIndex : null,\n this.range ? this.range.endIndex : null,\n ] as [boolean, number | null, number | null],\n },\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 this.measureElementCache.forEach(this.observer.observe)\n return () => {\n this.observer.disconnect()\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 memoOptions = memo(\n () => [\n this.options.count,\n this.options.paddingStart,\n this.options.scrollMargin,\n this.options.getItemKey,\n ],\n (count, paddingStart, scrollMargin, getItemKey) => {\n this.pendingMeasuredCacheIndexes = []\n return {\n count,\n paddingStart,\n scrollMargin,\n getItemKey,\n }\n },\n {\n key: false,\n },\n )\n\n private getFurthestMeasurement = (\n measurements: VirtualItem[],\n index: number,\n ) => {\n const furthestMeasurementsFound = new Map<number, true>()\n const furthestMeasurements = new Map<number, VirtualItem>()\n for (let m = index - 1; m >= 0; m--) {\n const measurement = measurements[m]!\n\n if (furthestMeasurementsFound.has(measurement.lane)) {\n continue\n }\n\n const previousFurthestMeasurement = furthestMeasurements.get(\n measurement.lane,\n )\n if (\n previousFurthestMeasurement == null ||\n measurement.end > previousFurthestMeasurement.end\n ) {\n furthestMeasurements.set(measurement.lane, measurement)\n } else if (measurement.end < previousFurthestMeasurement.end) {\n furthestMeasurementsFound.set(measurement.lane, true)\n }\n\n if (furthestMeasurementsFound.size === this.options.lanes) {\n break\n }\n }\n\n return furthestMeasurements.size === this.options.lanes\n ? Array.from(furthestMeasurements.values()).sort((a, b) => {\n if (a.end === b.end) {\n return a.index - b.index\n }\n\n return a.end - b.end\n })[0]\n : undefined\n }\n\n private getMeasurements = memo(\n () => [this.memoOptions(), this.itemSizeCache],\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\n const furthestMeasurement =\n this.options.lanes === 1\n ? measurements[i - 1]\n : this.getFurthestMeasurement(measurements, i)\n\n const start = furthestMeasurement\n ? furthestMeasurement.end + this.options.gap\n : paddingStart + scrollMargin\n\n const measuredSize = itemSizeCache.get(key)\n const size =\n typeof measuredSize === 'number'\n ? measuredSize\n : this.options.estimateSize(i)\n\n const end = start + size\n\n const lane = furthestMeasurement\n ? furthestMeasurement.lane\n : i % this.options.lanes\n\n measurements[i] = {\n index: i,\n start,\n size,\n end,\n key,\n lane,\n }\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 =\n measurements.length > 0 && outerSize > 0\n ? calculateRange({\n measurements,\n outerSize,\n scrollOffset,\n })\n : null)\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(),\n this.options.overscan,\n this.options.count,\n ],\n (rangeExtractor, range, overscan, count) => {\n return range === null\n ? []\n : 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 = (\n node: TItemElement,\n entry: ResizeObserverEntry | undefined,\n ) => {\n const item = this.measurementsCache[this.indexFromElement(node)]\n\n if (!item || !node.isConnected) {\n this.measureElementCache.forEach((cached, key) => {\n if (cached === node) {\n this.observer.unobserve(node)\n this.measureElementCache.delete(key)\n }\n })\n return\n }\n\n const prevNode = this.measureElementCache.get(item.key)\n\n if (prevNode !== node) {\n if (prevNode) {\n this.observer.unobserve(prevNode)\n }\n this.observer.observe(node)\n this.measureElementCache.set(item.key, node)\n }\n\n const measuredItemSize = this.options.measureElement(node, entry, this)\n\n this.resizeItem(item, measuredItemSize)\n }\n\n resizeItem = (item: VirtualItem, size: number) => {\n const itemSize = this.itemSizeCache.get(item.key) ?? item.size\n const delta = size - itemSize\n\n if (delta !== 0) {\n if (\n this.shouldAdjustScrollPositionOnItemSizeChange !== undefined\n ? this.shouldAdjustScrollPositionOnItemSizeChange(item, delta, this)\n : item.start < this.scrollOffset + this.scrollAdjustments\n ) {\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(item.index)\n this.itemSizeCache = new Map(this.itemSizeCache.set(item.key, size))\n\n this.notify(false)\n }\n }\n\n measureElement = (node: TItemElement | null) => {\n if (!node) {\n return\n }\n\n this._measureElement(node, undefined)\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 getVirtualItemForOffset = (offset: number) => {\n const measurements = this.getMeasurements()\n\n return notUndefined(\n measurements[\n findNearestBinarySearch(\n 0,\n measurements.length - 1,\n (index: number) => notUndefined(measurements[index]).start,\n offset,\n )\n ],\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 = () => this.measureElementCache.size > 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 = this.measureElementCache.has(\n this.options.getItemKey(index),\n )\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 const measurements = this.getMeasurements()\n\n let end: number\n // If there are no measurements, set the end to paddingStart\n if (measurements.length === 0) {\n end = this.options.paddingStart\n } else {\n // If lanes is 1, use the last measurement's end, otherwise find the maximum end value among all measurements\n end =\n this.options.lanes === 1\n ? measurements[measurements.length - 1]?.end ?? 0\n : Math.max(\n ...measurements.slice(-this.options.lanes).map((m) => m.end),\n )\n }\n\n return end - this.options.scrollMargin + this.options.paddingEnd\n }\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 = new Map()\n this.notify(false)\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":["opts","memo","notUndefined","toOffset","approxEqual"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":["../../src/index.ts"],"sourcesContent":["import { approxEqual, memo, notUndefined, debounce } 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 lane: number\n}\n\nexport interface 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\nexport const observeElementRect = <T extends Element>(\n instance: Virtualizer<T, any>,\n cb: (rect: Rect) => void,\n) => {\n const element = instance.scrollElement\n if (!element) {\n return\n }\n\n const handler = (rect: Rect) => {\n const { width, height } = rect\n cb({ width: Math.round(width), height: Math.round(height) })\n }\n\n handler(element.getBoundingClientRect())\n\n if (typeof ResizeObserver === 'undefined') {\n return () => {}\n }\n\n const observer = new ResizeObserver((entries) => {\n const entry = entries[0]\n if (entry?.borderBoxSize) {\n const box = entry.borderBoxSize[0]\n if (box) {\n handler({ width: box.inlineSize, height: box.blockSize })\n return\n }\n }\n handler(element.getBoundingClientRect())\n })\n\n observer.observe(element, { box: 'border-box' })\n\n return () => {\n observer.unobserve(element)\n }\n}\n\nconst addEventListenerOptions = {\n passive: true,\n}\n\nexport const observeWindowRect = (\n instance: Virtualizer<Window, any>,\n cb: (rect: Rect) => void,\n) => {\n const element = instance.scrollElement\n if (!element) {\n return\n }\n\n const handler = () => {\n cb({ width: element.innerWidth, height: element.innerHeight })\n }\n handler()\n\n element.addEventListener('resize', handler, addEventListenerOptions)\n\n return () => {\n element.removeEventListener('resize', handler)\n }\n}\n\nconst supportsScrollend =\n typeof window == 'undefined' ? true : 'onscrollend' in window\n\nexport const observeElementOffset = <T extends Element>(\n instance: Virtualizer<T, any>,\n cb: (offset: number, isScrolling: boolean) => void,\n) => {\n const element = instance.scrollElement\n if (!element) {\n return\n }\n\n let offset = 0\n const fallback = supportsScrollend\n ? () => undefined\n : debounce(() => {\n cb(offset, false)\n }, instance.options.isScrollingResetDelay)\n\n const createHandler = (isScrolling: boolean) => () => {\n offset = element[instance.options.horizontal ? 'scrollLeft' : 'scrollTop']\n fallback()\n cb(offset, isScrolling)\n }\n const handler = createHandler(true)\n const endHandler = createHandler(false)\n endHandler()\n\n element.addEventListener('scroll', handler, addEventListenerOptions)\n element.addEventListener('scrollend', endHandler, addEventListenerOptions)\n\n return () => {\n element.removeEventListener('scroll', handler)\n element.removeEventListener('scrollend', endHandler)\n }\n}\n\nexport const observeWindowOffset = (\n instance: Virtualizer<Window, any>,\n cb: (offset: number, isScrolling: boolean) => void,\n) => {\n const element = instance.scrollElement\n if (!element) {\n return\n }\n\n let offset = 0\n const fallback = supportsScrollend\n ? () => undefined\n : debounce(() => {\n cb(offset, false)\n }, instance.options.isScrollingResetDelay)\n\n const createHandler = (isScrolling: boolean) => () => {\n offset = element[instance.options.horizontal ? 'scrollX' : 'scrollY']\n fallback()\n cb(offset, isScrolling)\n }\n const handler = createHandler(true)\n const endHandler = createHandler(false)\n endHandler()\n\n element.addEventListener('scroll', handler, addEventListenerOptions)\n element.addEventListener('scrollend', endHandler, addEventListenerOptions)\n\n return () => {\n element.removeEventListener('scroll', handler)\n element.removeEventListener('scrollend', endHandler)\n }\n}\n\nexport const measureElement = <TItemElement extends Element>(\n element: TItemElement,\n entry: ResizeObserverEntry | undefined,\n instance: Virtualizer<any, TItemElement>,\n) => {\n if (entry?.borderBoxSize) {\n const box = entry.borderBoxSize[0]\n if (box) {\n const size = Math.round(\n box[instance.options.horizontal ? 'inlineSize' : 'blockSize'],\n )\n return size\n }\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, isScrolling: boolean) => void,\n ) => void | (() => void)\n\n // Optional\n debug?: any\n initialRect?: Rect\n onChange?: (\n instance: Virtualizer<TScrollElement, TItemElement>,\n sync: boolean,\n ) => void\n measureElement?: (\n element: TItemElement,\n entry: ResizeObserverEntry | undefined,\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 | (() => number)\n getItemKey?: (index: number) => Key\n rangeExtractor?: (range: Range) => number[]\n scrollMargin?: number\n gap?: number\n indexAttribute?: string\n initialMeasurementsCache?: VirtualItem[]\n lanes?: number\n isScrollingResetDelay?: number\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 scrollToIndexTimeoutId: ReturnType<typeof setTimeout> | null = null\n measurementsCache: VirtualItem[] = []\n private itemSizeCache = new Map<Key, number>()\n private pendingMeasuredCacheIndexes: number[] = []\n scrollRect: Rect\n scrollOffset: number\n scrollDirection: ScrollDirection | null = null\n private scrollAdjustments: number = 0\n shouldAdjustScrollPositionOnItemSizeChange:\n | undefined\n | ((\n item: VirtualItem,\n delta: number,\n instance: Virtualizer<TScrollElement, TItemElement>,\n ) => boolean)\n measureElementCache = new Map<Key, TItemElement>()\n private observer = (() => {\n let _ro: ResizeObserver | null = null\n\n const get = () => {\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, entry)\n })\n }))\n } else {\n return null\n }\n }\n\n return {\n disconnect: () => get()?.disconnect(),\n observe: (target: Element) =>\n get()?.observe(target, { box: 'border-box' }),\n unobserve: (target: Element) => get()?.unobserve(target),\n }\n })()\n range: { startIndex: number; endIndex: number } | null = null\n\n constructor(opts: VirtualizerOptions<TScrollElement, TItemElement>) {\n this.setOptions(opts)\n this.scrollRect = this.options.initialRect\n this.scrollOffset =\n typeof this.options.initialOffset === 'function'\n ? this.options.initialOffset()\n : this.options.initialOffset\n this.measurementsCache = this.options.initialMeasurementsCache\n this.measurementsCache.forEach((item) => {\n this.itemSizeCache.set(item.key, item.size)\n })\n\n this.notify(false, false)\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 gap: 0,\n indexAttribute: 'data-index',\n initialMeasurementsCache: [],\n lanes: 1,\n isScrollingResetDelay: 150,\n ...opts,\n }\n }\n\n private notify = (force: boolean, sync: boolean) => {\n const { startIndex, endIndex } = this.range ?? {\n startIndex: undefined,\n endIndex: undefined,\n }\n const range = this.calculateRange()\n\n if (\n force ||\n startIndex !== range?.startIndex ||\n endIndex !== range?.endIndex\n ) {\n this.options.onChange?.(this, sync)\n }\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 this.measureElementCache.forEach(this.observer.observe)\n return () => {\n this.observer.disconnect()\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.notify(false, false)\n }),\n )\n\n this.unsubs.push(\n this.options.observeElementOffset(this, (offset, isScrolling) => {\n this.scrollAdjustments = 0\n this.scrollDirection = isScrolling\n ? this.scrollOffset < offset\n ? 'forward'\n : 'backward'\n : null\n this.scrollOffset = offset\n\n const prevIsScrolling = this.isScrolling\n this.isScrolling = isScrolling\n\n this.notify(prevIsScrolling !== isScrolling, isScrolling)\n }),\n )\n }\n }\n\n private getSize = () => {\n return this.scrollRect[this.options.horizontal ? 'width' : 'height']\n }\n\n private getMeasurementOptions = memo(\n () => [\n this.options.count,\n this.options.paddingStart,\n this.options.scrollMargin,\n this.options.getItemKey,\n ],\n (count, paddingStart, scrollMargin, getItemKey) => {\n this.pendingMeasuredCacheIndexes = []\n return {\n count,\n paddingStart,\n scrollMargin,\n getItemKey,\n }\n },\n {\n key: false,\n },\n )\n\n private getFurthestMeasurement = (\n measurements: VirtualItem[],\n index: number,\n ) => {\n const furthestMeasurementsFound = new Map<number, true>()\n const furthestMeasurements = new Map<number, VirtualItem>()\n for (let m = index - 1; m >= 0; m--) {\n const measurement = measurements[m]!\n\n if (furthestMeasurementsFound.has(measurement.lane)) {\n continue\n }\n\n const previousFurthestMeasurement = furthestMeasurements.get(\n measurement.lane,\n )\n if (\n previousFurthestMeasurement == null ||\n measurement.end > previousFurthestMeasurement.end\n ) {\n furthestMeasurements.set(measurement.lane, measurement)\n } else if (measurement.end < previousFurthestMeasurement.end) {\n furthestMeasurementsFound.set(measurement.lane, true)\n }\n\n if (furthestMeasurementsFound.size === this.options.lanes) {\n break\n }\n }\n\n return furthestMeasurements.size === this.options.lanes\n ? Array.from(furthestMeasurements.values()).sort((a, b) => {\n if (a.end === b.end) {\n return a.index - b.index\n }\n\n return a.end - b.end\n })[0]\n : undefined\n }\n\n private getMeasurements = memo(\n () => [this.getMeasurementOptions(), this.itemSizeCache],\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\n const furthestMeasurement =\n this.options.lanes === 1\n ? measurements[i - 1]\n : this.getFurthestMeasurement(measurements, i)\n\n const start = furthestMeasurement\n ? furthestMeasurement.end + this.options.gap\n : paddingStart + scrollMargin\n\n const measuredSize = itemSizeCache.get(key)\n const size =\n typeof measuredSize === 'number'\n ? measuredSize\n : this.options.estimateSize(i)\n\n const end = start + size\n\n const lane = furthestMeasurement\n ? furthestMeasurement.lane\n : i % this.options.lanes\n\n measurements[i] = {\n index: i,\n start,\n size,\n end,\n key,\n lane,\n }\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 =\n measurements.length > 0 && outerSize > 0\n ? calculateRange({\n measurements,\n outerSize,\n scrollOffset,\n })\n : null)\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(),\n this.options.overscan,\n this.options.count,\n ],\n (rangeExtractor, range, overscan, count) => {\n return range === null\n ? []\n : rangeExtractor({\n startIndex: range.startIndex,\n endIndex: range.endIndex,\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 = (\n node: TItemElement,\n entry: ResizeObserverEntry | undefined,\n ) => {\n const item = this.measurementsCache[this.indexFromElement(node)]\n\n if (!item || !node.isConnected) {\n this.measureElementCache.forEach((cached, key) => {\n if (cached === node) {\n this.observer.unobserve(node)\n this.measureElementCache.delete(key)\n }\n })\n return\n }\n\n const prevNode = this.measureElementCache.get(item.key)\n\n if (prevNode !== node) {\n if (prevNode) {\n this.observer.unobserve(prevNode)\n }\n this.observer.observe(node)\n this.measureElementCache.set(item.key, node)\n }\n\n const measuredItemSize = this.options.measureElement(node, entry, this)\n\n this.resizeItem(item, measuredItemSize)\n }\n\n resizeItem = (item: VirtualItem, size: number) => {\n const itemSize = this.itemSizeCache.get(item.key) ?? item.size\n const delta = size - itemSize\n\n if (delta !== 0) {\n if (\n this.shouldAdjustScrollPositionOnItemSizeChange !== undefined\n ? this.shouldAdjustScrollPositionOnItemSizeChange(item, delta, this)\n : item.start < this.scrollOffset + this.scrollAdjustments\n ) {\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(item.index)\n this.itemSizeCache = new Map(this.itemSizeCache.set(item.key, size))\n\n this.notify(true, false)\n }\n }\n\n measureElement = (node: TItemElement | null) => {\n if (!node) {\n return\n }\n\n this._measureElement(node, undefined)\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 getVirtualItemForOffset = (offset: number) => {\n const measurements = this.getMeasurements()\n\n return notUndefined(\n measurements[\n findNearestBinarySearch(\n 0,\n measurements.length - 1,\n (index: number) => notUndefined(measurements[index]).start,\n offset,\n )\n ],\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 = () => this.measureElementCache.size > 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 = this.measureElementCache.has(\n this.options.getItemKey(index),\n )\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 const measurements = this.getMeasurements()\n\n let end: number\n // If there are no measurements, set the end to paddingStart\n if (measurements.length === 0) {\n end = this.options.paddingStart\n } else {\n // If lanes is 1, use the last measurement's end, otherwise find the maximum end value among all measurements\n end =\n this.options.lanes === 1\n ? measurements[measurements.length - 1]?.end ?? 0\n : Math.max(\n ...measurements.slice(-this.options.lanes).map((m) => m.end),\n )\n }\n\n return end - this.options.scrollMargin + this.options.paddingEnd\n }\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 = new Map()\n this.options.onChange?.(this, false)\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":["debounce","opts","memo","notUndefined","toOffset","approxEqual"],"mappings":"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"}
@@ -31,8 +31,8 @@ export declare const defaultKeyExtractor: (index: number) => number;
31
31
  export declare const defaultRangeExtractor: (range: Range) => number[];
32
32
  export declare const observeElementRect: <T extends Element>(instance: Virtualizer<T, any>, cb: (rect: Rect) => void) => (() => void) | undefined;
33
33
  export declare const observeWindowRect: (instance: Virtualizer<Window, any>, cb: (rect: Rect) => void) => (() => void) | undefined;
34
- export declare const observeElementOffset: <T extends Element>(instance: Virtualizer<T, any>, cb: (offset: number) => void) => (() => void) | undefined;
35
- export declare const observeWindowOffset: (instance: Virtualizer<Window, any>, cb: (offset: number) => void) => (() => void) | undefined;
34
+ export declare const observeElementOffset: <T extends Element>(instance: Virtualizer<T, any>, cb: (offset: number, isScrolling: boolean) => void) => (() => void) | undefined;
35
+ export declare const observeWindowOffset: (instance: Virtualizer<Window, any>, cb: (offset: number, isScrolling: boolean) => void) => (() => void) | undefined;
36
36
  export declare const measureElement: <TItemElement extends Element>(element: TItemElement, entry: ResizeObserverEntry | undefined, instance: Virtualizer<any, TItemElement>) => number;
37
37
  export declare const windowScroll: <T extends Window>(offset: number, { adjustments, behavior, }: {
38
38
  adjustments?: number | undefined;
@@ -51,7 +51,7 @@ export interface VirtualizerOptions<TScrollElement extends Element | Window, TIt
51
51
  behavior?: ScrollBehavior;
52
52
  }, instance: Virtualizer<TScrollElement, TItemElement>) => void;
53
53
  observeElementRect: (instance: Virtualizer<TScrollElement, TItemElement>, cb: (rect: Rect) => void) => void | (() => void);
54
- observeElementOffset: (instance: Virtualizer<TScrollElement, TItemElement>, cb: (offset: number) => void) => void | (() => void);
54
+ observeElementOffset: (instance: Virtualizer<TScrollElement, TItemElement>, cb: (offset: number, isScrolling: boolean) => void) => void | (() => void);
55
55
  debug?: any;
56
56
  initialRect?: Rect;
57
57
  onChange?: (instance: Virtualizer<TScrollElement, TItemElement>, sync: boolean) => void;
@@ -67,17 +67,16 @@ export interface VirtualizerOptions<TScrollElement extends Element | Window, TIt
67
67
  rangeExtractor?: (range: Range) => number[];
68
68
  scrollMargin?: number;
69
69
  gap?: number;
70
- scrollingDelay?: number;
71
70
  indexAttribute?: string;
72
71
  initialMeasurementsCache?: VirtualItem[];
73
72
  lanes?: number;
73
+ isScrollingResetDelay?: number;
74
74
  }
75
75
  export declare class Virtualizer<TScrollElement extends Element | Window, TItemElement extends Element> {
76
76
  private unsubs;
77
77
  options: Required<VirtualizerOptions<TScrollElement, TItemElement>>;
78
78
  scrollElement: TScrollElement | null;
79
79
  isScrolling: boolean;
80
- private isScrollingTimeoutId;
81
80
  private scrollToIndexTimeoutId;
82
81
  measurementsCache: VirtualItem[];
83
82
  private itemSizeCache;
@@ -96,12 +95,11 @@ export declare class Virtualizer<TScrollElement extends Element | Window, TItemE
96
95
  constructor(opts: VirtualizerOptions<TScrollElement, TItemElement>);
97
96
  setOptions: (opts: VirtualizerOptions<TScrollElement, TItemElement>) => void;
98
97
  private notify;
99
- private maybeNotify;
100
98
  private cleanup;
101
99
  _didMount: () => () => void;
102
100
  _willUpdate: () => void;
103
101
  private getSize;
104
- private memoOptions;
102
+ private getMeasurementOptions;
105
103
  private getFurthestMeasurement;
106
104
  private getMeasurements;
107
105
  calculateRange: () => {
@@ -53,7 +53,15 @@ function notUndefined(value, msg) {
53
53
  }
54
54
  }
55
55
  const approxEqual = (a, b) => Math.abs(a - b) < 1;
56
+ const debounce = (fn, ms) => {
57
+ let timeoutId;
58
+ return function(...args) {
59
+ clearTimeout(timeoutId);
60
+ timeoutId = setTimeout(() => fn.apply(this, args), ms);
61
+ };
62
+ };
56
63
  exports.approxEqual = approxEqual;
64
+ exports.debounce = debounce;
57
65
  exports.memo = memo;
58
66
  exports.notUndefined = notUndefined;
59
67
  //# sourceMappingURL=utils.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.cjs","sources":["../../src/utils.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: false | string\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"],"names":[],"mappings":";;AAIgB,SAAA,KACd,SACA,IACA,MAMA;AACI,MAAA,OAAO,KAAK,eAAe;AAC3B,MAAA;AAEJ,SAAO,MAAe;;AAChB,QAAA;AACA,QAAA,KAAK,SAAO,UAAK,UAAL;AAAgB,gBAAU,KAAK;AAE/C,UAAM,UAAU;AAEhB,UAAM,cACJ,QAAQ,WAAW,KAAK,UACxB,QAAQ,KAAK,CAAC,KAAU,UAAkB,KAAK,KAAK,MAAM,GAAG;AAE/D,QAAI,CAAC,aAAa;AACT,aAAA;AAAA,IACT;AAEO,WAAA;AAEH,QAAA;AACA,QAAA,KAAK,SAAO,UAAK,UAAL;AAAgB,mBAAa,KAAK;AAEzC,aAAA,GAAG,GAAG,OAAO;AAEtB,QAAI,KAAK,SAAO,UAAK,UAAL,gCAAgB;AACxB,YAAA,aAAa,KAAK,OAAO,KAAK,QAAQ,WAAY,GAAG,IAAI;AACzD,YAAA,gBAAgB,KAAK,OAAO,KAAK,QAAQ,cAAe,GAAG,IAAI;AACrE,YAAM,sBAAsB,gBAAgB;AAEtC,YAAA,MAAM,CAAC,KAAsB,QAAgB;AACjD,cAAM,OAAO,GAAG;AACT,eAAA,IAAI,SAAS,KAAK;AACvB,gBAAM,MAAM;AAAA,QACd;AACO,eAAA;AAAA,MAAA;AAGD,cAAA;AAAA,QACN,OAAO,IAAI,eAAe,CAAC,CAAC,KAAK,IAAI,YAAY,CAAC,CAAC;AAAA,QACnD;AAAA;AAAA;AAAA,yBAGiB,KAAK;AAAA,UAChB;AAAA,UACA,KAAK,IAAI,MAAM,MAAM,qBAAqB,GAAG;AAAA,QAC9C,CAAA;AAAA,QACL,6BAAM;AAAA,MAAA;AAAA,IAEV;AAEA,uCAAM,aAAN,8BAAiB;AAEV,WAAA;AAAA,EAAA;AAEX;AAEgB,SAAA,aAAgB,OAAsB,KAAiB;AACrE,MAAI,UAAU,QAAW;AACjB,UAAA,IAAI,MAAM,uBAAuB,MAAM,KAAK,GAAG,KAAK,EAAE,EAAE;AAAA,EAAA,OACzD;AACE,WAAA;AAAA,EACT;AACF;AAEa,MAAA,cAAc,CAAC,GAAW,MAAc,KAAK,IAAI,IAAI,CAAC,IAAI;;;;"}
1
+ {"version":3,"file":"utils.cjs","sources":["../../src/utils.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: false | string\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\nexport const debounce = (fn: Function, ms: number) => {\n let timeoutId: ReturnType<typeof setTimeout>\n return function (this: any, ...args: any[]) {\n clearTimeout(timeoutId)\n timeoutId = setTimeout(() => fn.apply(this, args), ms)\n }\n}\n"],"names":[],"mappings":";;AAIgB,SAAA,KACd,SACA,IACA,MAMA;AACI,MAAA,OAAO,KAAK,eAAe;AAC3B,MAAA;AAEJ,SAAO,MAAe;;AAChB,QAAA;AACA,QAAA,KAAK,SAAO,UAAK,UAAL;AAAgB,gBAAU,KAAK;AAE/C,UAAM,UAAU;AAEhB,UAAM,cACJ,QAAQ,WAAW,KAAK,UACxB,QAAQ,KAAK,CAAC,KAAU,UAAkB,KAAK,KAAK,MAAM,GAAG;AAE/D,QAAI,CAAC,aAAa;AACT,aAAA;AAAA,IACT;AAEO,WAAA;AAEH,QAAA;AACA,QAAA,KAAK,SAAO,UAAK,UAAL;AAAgB,mBAAa,KAAK;AAEzC,aAAA,GAAG,GAAG,OAAO;AAEtB,QAAI,KAAK,SAAO,UAAK,UAAL,gCAAgB;AACxB,YAAA,aAAa,KAAK,OAAO,KAAK,QAAQ,WAAY,GAAG,IAAI;AACzD,YAAA,gBAAgB,KAAK,OAAO,KAAK,QAAQ,cAAe,GAAG,IAAI;AACrE,YAAM,sBAAsB,gBAAgB;AAEtC,YAAA,MAAM,CAAC,KAAsB,QAAgB;AACjD,cAAM,OAAO,GAAG;AACT,eAAA,IAAI,SAAS,KAAK;AACvB,gBAAM,MAAM;AAAA,QACd;AACO,eAAA;AAAA,MAAA;AAGD,cAAA;AAAA,QACN,OAAO,IAAI,eAAe,CAAC,CAAC,KAAK,IAAI,YAAY,CAAC,CAAC;AAAA,QACnD;AAAA;AAAA;AAAA,yBAGiB,KAAK;AAAA,UAChB;AAAA,UACA,KAAK,IAAI,MAAM,MAAM,qBAAqB,GAAG;AAAA,QAC9C,CAAA;AAAA,QACL,6BAAM;AAAA,MAAA;AAAA,IAEV;AAEA,uCAAM,aAAN,8BAAiB;AAEV,WAAA;AAAA,EAAA;AAEX;AAEgB,SAAA,aAAgB,OAAsB,KAAiB;AACrE,MAAI,UAAU,QAAW;AACjB,UAAA,IAAI,MAAM,uBAAuB,MAAM,KAAK,GAAG,KAAK,EAAE,EAAE;AAAA,EAAA,OACzD;AACE,WAAA;AAAA,EACT;AACF;AAEa,MAAA,cAAc,CAAC,GAAW,MAAc,KAAK,IAAI,IAAI,CAAC,IAAI;AAE1D,MAAA,WAAW,CAAC,IAAc,OAAe;AAChD,MAAA;AACJ,SAAO,YAAwB,MAAa;AAC1C,iBAAa,SAAS;AACtB,gBAAY,WAAW,MAAM,GAAG,MAAM,MAAM,IAAI,GAAG,EAAE;AAAA,EAAA;AAEzD;;;;;"}
@@ -8,3 +8,4 @@ export declare function memo<TDeps extends readonly any[], TResult>(getDeps: ()
8
8
  }): () => TResult;
9
9
  export declare function notUndefined<T>(value: T | undefined, msg?: string): T;
10
10
  export declare const approxEqual: (a: number, b: number) => boolean;
11
+ export declare const debounce: (fn: Function, ms: number) => (this: any, ...args: any[]) => void;
@@ -31,8 +31,8 @@ export declare const defaultKeyExtractor: (index: number) => number;
31
31
  export declare const defaultRangeExtractor: (range: Range) => number[];
32
32
  export declare const observeElementRect: <T extends Element>(instance: Virtualizer<T, any>, cb: (rect: Rect) => void) => (() => void) | undefined;
33
33
  export declare const observeWindowRect: (instance: Virtualizer<Window, any>, cb: (rect: Rect) => void) => (() => void) | undefined;
34
- export declare const observeElementOffset: <T extends Element>(instance: Virtualizer<T, any>, cb: (offset: number) => void) => (() => void) | undefined;
35
- export declare const observeWindowOffset: (instance: Virtualizer<Window, any>, cb: (offset: number) => void) => (() => void) | undefined;
34
+ export declare const observeElementOffset: <T extends Element>(instance: Virtualizer<T, any>, cb: (offset: number, isScrolling: boolean) => void) => (() => void) | undefined;
35
+ export declare const observeWindowOffset: (instance: Virtualizer<Window, any>, cb: (offset: number, isScrolling: boolean) => void) => (() => void) | undefined;
36
36
  export declare const measureElement: <TItemElement extends Element>(element: TItemElement, entry: ResizeObserverEntry | undefined, instance: Virtualizer<any, TItemElement>) => number;
37
37
  export declare const windowScroll: <T extends Window>(offset: number, { adjustments, behavior, }: {
38
38
  adjustments?: number | undefined;
@@ -51,7 +51,7 @@ export interface VirtualizerOptions<TScrollElement extends Element | Window, TIt
51
51
  behavior?: ScrollBehavior;
52
52
  }, instance: Virtualizer<TScrollElement, TItemElement>) => void;
53
53
  observeElementRect: (instance: Virtualizer<TScrollElement, TItemElement>, cb: (rect: Rect) => void) => void | (() => void);
54
- observeElementOffset: (instance: Virtualizer<TScrollElement, TItemElement>, cb: (offset: number) => void) => void | (() => void);
54
+ observeElementOffset: (instance: Virtualizer<TScrollElement, TItemElement>, cb: (offset: number, isScrolling: boolean) => void) => void | (() => void);
55
55
  debug?: any;
56
56
  initialRect?: Rect;
57
57
  onChange?: (instance: Virtualizer<TScrollElement, TItemElement>, sync: boolean) => void;
@@ -67,17 +67,16 @@ export interface VirtualizerOptions<TScrollElement extends Element | Window, TIt
67
67
  rangeExtractor?: (range: Range) => number[];
68
68
  scrollMargin?: number;
69
69
  gap?: number;
70
- scrollingDelay?: number;
71
70
  indexAttribute?: string;
72
71
  initialMeasurementsCache?: VirtualItem[];
73
72
  lanes?: number;
73
+ isScrollingResetDelay?: number;
74
74
  }
75
75
  export declare class Virtualizer<TScrollElement extends Element | Window, TItemElement extends Element> {
76
76
  private unsubs;
77
77
  options: Required<VirtualizerOptions<TScrollElement, TItemElement>>;
78
78
  scrollElement: TScrollElement | null;
79
79
  isScrolling: boolean;
80
- private isScrollingTimeoutId;
81
80
  private scrollToIndexTimeoutId;
82
81
  measurementsCache: VirtualItem[];
83
82
  private itemSizeCache;
@@ -96,12 +95,11 @@ export declare class Virtualizer<TScrollElement extends Element | Window, TItemE
96
95
  constructor(opts: VirtualizerOptions<TScrollElement, TItemElement>);
97
96
  setOptions: (opts: VirtualizerOptions<TScrollElement, TItemElement>) => void;
98
97
  private notify;
99
- private maybeNotify;
100
98
  private cleanup;
101
99
  _didMount: () => () => void;
102
100
  _willUpdate: () => void;
103
101
  private getSize;
104
- private memoOptions;
102
+ private getMeasurementOptions;
105
103
  private getFurthestMeasurement;
106
104
  private getMeasurements;
107
105
  calculateRange: () => {