@tanstack/virtual-core 3.6.0 → 3.7.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.
@@ -177,7 +177,7 @@ class Virtualizer {
177
177
  this.scrollOffset = null;
178
178
  this.scrollDirection = null;
179
179
  this.scrollAdjustments = 0;
180
- this.measureElementCache = /* @__PURE__ */ new Map();
180
+ this.elementsCache = /* @__PURE__ */ new Map();
181
181
  this.observer = /* @__PURE__ */ (() => {
182
182
  let _ro = null;
183
183
  const get = () => {
@@ -256,7 +256,7 @@ class Virtualizer {
256
256
  this.scrollElement = null;
257
257
  this.targetWindow = null;
258
258
  this.observer.disconnect();
259
- this.measureElementCache.clear();
259
+ this.elementsCache.clear();
260
260
  };
261
261
  this._didMount = () => {
262
262
  return () => {
@@ -368,6 +368,7 @@ class Virtualizer {
368
368
  this.getMeasurements = utils.memo(
369
369
  () => [this.getMeasurementOptions(), this.itemSizeCache],
370
370
  ({ count, paddingStart, scrollMargin, getItemKey, enabled }, itemSizeCache) => {
371
+ var _a;
371
372
  if (!enabled) {
372
373
  this.measurementsCache = [];
373
374
  this.itemSizeCache.clear();
@@ -383,6 +384,33 @@ class Virtualizer {
383
384
  this.pendingMeasuredCacheIndexes = [];
384
385
  const measurements = this.measurementsCache.slice(0, min);
385
386
  for (let i = min; i < count; i++) {
387
+ let measureElement2 = (_a = this.measurementsCache[i]) == null ? void 0 : _a.measureElement;
388
+ if (!measureElement2) {
389
+ measureElement2 = (node) => {
390
+ const key2 = getItemKey(i);
391
+ const prevNode = this.elementsCache.get(key2);
392
+ if (!node) {
393
+ if (prevNode) {
394
+ this.observer.unobserve(prevNode);
395
+ this.elementsCache.delete(key2);
396
+ }
397
+ return;
398
+ }
399
+ if (prevNode !== node) {
400
+ if (prevNode) {
401
+ this.observer.unobserve(prevNode);
402
+ }
403
+ this.observer.observe(node);
404
+ this.elementsCache.set(key2, node);
405
+ }
406
+ if (node.isConnected) {
407
+ this.resizeItem(
408
+ i,
409
+ this.options.measureElement(node, void 0, this)
410
+ );
411
+ }
412
+ };
413
+ }
386
414
  const key = getItemKey(i);
387
415
  const furthestMeasurement = this.options.lanes === 1 ? measurements[i - 1] : this.getFurthestMeasurement(measurements, i);
388
416
  const start = furthestMeasurement ? furthestMeasurement.end + this.options.gap : paddingStart + scrollMargin;
@@ -396,7 +424,8 @@ class Virtualizer {
396
424
  size,
397
425
  end,
398
426
  key,
399
- lane
427
+ lane,
428
+ measureElement: measureElement2
400
429
  };
401
430
  }
402
431
  this.measurementsCache = measurements;
@@ -453,28 +482,32 @@ class Virtualizer {
453
482
  return parseInt(indexStr, 10);
454
483
  };
455
484
  this._measureElement = (node, entry) => {
456
- const item = this.getMeasurements()[this.indexFromElement(node)];
485
+ const i = this.indexFromElement(node);
486
+ const item = this.getMeasurements()[i];
457
487
  if (!item || !node.isConnected) {
458
- this.measureElementCache.forEach((cached, key) => {
488
+ this.elementsCache.forEach((cached, key) => {
459
489
  if (cached === node) {
460
490
  this.observer.unobserve(node);
461
- this.measureElementCache.delete(key);
491
+ this.elementsCache.delete(key);
462
492
  }
463
493
  });
464
494
  return;
465
495
  }
466
- const prevNode = this.measureElementCache.get(item.key);
496
+ const prevNode = this.elementsCache.get(item.key);
467
497
  if (prevNode !== node) {
468
498
  if (prevNode) {
469
499
  this.observer.unobserve(prevNode);
470
500
  }
471
501
  this.observer.observe(node);
472
- this.measureElementCache.set(item.key, node);
502
+ this.elementsCache.set(item.key, node);
473
503
  }
474
- const measuredItemSize = this.options.measureElement(node, entry, this);
475
- this.resizeItem(item, measuredItemSize);
504
+ this.resizeItem(i, this.options.measureElement(node, entry, this));
476
505
  };
477
- this.resizeItem = (item, size) => {
506
+ this.resizeItem = (index, size) => {
507
+ const item = this.getMeasurements()[index];
508
+ if (!item) {
509
+ return;
510
+ }
478
511
  const itemSize = this.itemSizeCache.get(item.key) ?? item.size;
479
512
  const delta = size - itemSize;
480
513
  if (delta !== 0) {
@@ -572,7 +605,7 @@ class Virtualizer {
572
605
  const toOffset = align === "end" ? item.end + this.options.scrollPaddingEnd : item.start - this.options.scrollPaddingStart;
573
606
  return [this.getOffsetForAlignment(toOffset, align), align];
574
607
  };
575
- this.isDynamicMode = () => this.measureElementCache.size > 0;
608
+ this.isDynamicMode = () => this.elementsCache.size > 0;
576
609
  this.cancelScrollToIndex = () => {
577
610
  if (this.scrollToIndexTimeoutId !== null && this.targetWindow) {
578
611
  this.targetWindow.clearTimeout(this.scrollToIndexTimeoutId);
@@ -607,7 +640,7 @@ class Virtualizer {
607
640
  if (behavior !== "smooth" && this.isDynamicMode() && this.targetWindow) {
608
641
  this.scrollToIndexTimeoutId = this.targetWindow.setTimeout(() => {
609
642
  this.scrollToIndexTimeoutId = null;
610
- const elementInDOM = this.measureElementCache.has(
643
+ const elementInDOM = this.elementsCache.has(
611
644
  this.options.getItemKey(index)
612
645
  );
613
646
  if (elementInDOM) {
@@ -1 +1 @@
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 const targetWindow = instance.targetWindow\n if (!targetWindow) {\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 (!targetWindow.ResizeObserver) {\n return () => {}\n }\n\n const observer = new targetWindow.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 const targetWindow = instance.targetWindow\n if (!targetWindow) {\n return\n }\n\n let offset = 0\n const fallback = supportsScrollend\n ? () => undefined\n : debounce(\n targetWindow,\n () => {\n cb(offset, false)\n },\n instance.options.isScrollingResetDelay,\n )\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 const targetWindow = instance.targetWindow\n if (!targetWindow) {\n return\n }\n\n let offset = 0\n const fallback = supportsScrollend\n ? () => undefined\n : debounce(\n targetWindow,\n () => {\n cb(offset, false)\n },\n instance.options.isScrollingResetDelay,\n )\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 enabled?: boolean\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 targetWindow: (Window & typeof globalThis) | null = null\n isScrolling: boolean = false\n private scrollToIndexTimeoutId: number | null = null\n measurementsCache: VirtualItem[] = []\n private itemSizeCache = new Map<Key, number>()\n private pendingMeasuredCacheIndexes: number[] = []\n scrollRect: Rect | null = null\n scrollOffset: number | null = null\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 }\n\n if (!this.targetWindow || !this.targetWindow.ResizeObserver) {\n return null\n }\n\n return (_ro = new this.targetWindow.ResizeObserver((entries) => {\n entries.forEach((entry) => {\n this._measureElement(entry.target as TItemElement, entry)\n })\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 }\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 enabled: true,\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 this.targetWindow = null\n this.observer.disconnect()\n this.measureElementCache.clear()\n }\n\n _didMount = () => {\n return () => {\n this.cleanup()\n }\n }\n\n _willUpdate = () => {\n const scrollElement = this.options.enabled\n ? this.options.getScrollElement()\n : null\n\n if (this.scrollElement !== scrollElement) {\n this.cleanup()\n\n if (!scrollElement) {\n this.notify(false, false)\n return\n }\n\n this.scrollElement = scrollElement\n\n if (this.scrollElement && 'ownerDocument' in this.scrollElement) {\n this.targetWindow = this.scrollElement.ownerDocument.defaultView\n } else {\n this.targetWindow = this.scrollElement?.window ?? null\n }\n\n this._scrollToOffset(this.getScrollOffset(), {\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.getScrollOffset() < 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 if (!this.options.enabled) {\n this.scrollRect = null\n return 0\n }\n\n this.scrollRect = this.scrollRect ?? this.options.initialRect\n\n return this.scrollRect[this.options.horizontal ? 'width' : 'height']\n }\n\n private getScrollOffset = () => {\n if (!this.options.enabled) {\n this.scrollOffset = null\n return 0\n }\n\n this.scrollOffset =\n this.scrollOffset ??\n (typeof this.options.initialOffset === 'function'\n ? this.options.initialOffset()\n : this.options.initialOffset)\n\n return this.scrollOffset\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 getMeasurementOptions = memo(\n () => [\n this.options.count,\n this.options.paddingStart,\n this.options.scrollMargin,\n this.options.getItemKey,\n this.options.enabled,\n ],\n (count, paddingStart, scrollMargin, getItemKey, enabled) => {\n this.pendingMeasuredCacheIndexes = []\n return {\n count,\n paddingStart,\n scrollMargin,\n getItemKey,\n enabled,\n }\n },\n {\n key: false,\n },\n )\n\n private getMeasurements = memo(\n () => [this.getMeasurementOptions(), this.itemSizeCache],\n (\n { count, paddingStart, scrollMargin, getItemKey, enabled },\n itemSizeCache,\n ) => {\n if (!enabled) {\n this.measurementsCache = []\n this.itemSizeCache.clear()\n return []\n }\n\n if (this.measurementsCache.length === 0) {\n this.measurementsCache = this.options.initialMeasurementsCache\n this.measurementsCache.forEach((item) => {\n this.itemSizeCache.set(item.key, item.size)\n })\n }\n\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.getScrollOffset()],\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.getMeasurements()[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.getScrollOffset() + this.scrollAdjustments\n ) {\n if (process.env.NODE_ENV !== 'production' && this.options.debug) {\n console.info('correction', delta)\n }\n\n this._scrollToOffset(this.getScrollOffset(), {\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 if (measurements.length === 0) {\n return undefined\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 const scrollOffset = this.getScrollOffset()\n\n if (align === 'auto') {\n if (toOffset <= scrollOffset) {\n align = 'start'\n } else if (toOffset >= 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 - size\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 item = this.getMeasurements()[index]\n if (!item) {\n return undefined\n }\n\n const size = this.getSize()\n const scrollOffset = this.getScrollOffset()\n\n if (align === 'auto') {\n if (item.end >= scrollOffset + size - this.options.scrollPaddingEnd) {\n align = 'end'\n } else if (item.start <= scrollOffset + this.options.scrollPaddingStart) {\n align = 'start'\n } else {\n return [scrollOffset, align] as const\n }\n }\n\n const toOffset =\n align === 'end'\n ? item.end + this.options.scrollPaddingEnd\n : item.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 && this.targetWindow) {\n this.targetWindow.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 offsetAndAlign = this.getOffsetForIndex(index, initialAlign)\n if (!offsetAndAlign) return\n\n const [offset, align] = offsetAndAlign\n\n this._scrollToOffset(offset, { adjustments: undefined, behavior })\n\n if (behavior !== 'smooth' && this.isDynamicMode() && this.targetWindow) {\n this.scrollToIndexTimeoutId = this.targetWindow.setTimeout(() => {\n this.scrollToIndexTimeoutId = null\n\n const elementInDOM = this.measureElementCache.has(\n this.options.getItemKey(index),\n )\n\n if (elementInDOM) {\n const [latestOffset] = notUndefined(\n this.getOffsetForIndex(index, align),\n )\n\n if (!approxEqual(latestOffset, this.getScrollOffset())) {\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.getScrollOffset() + 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","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<TItemElement extends Element> {\n key: Key\n index: number\n start: number\n end: number\n size: number\n lane: number\n measureElement: (node: TItemElement | null | undefined) => void\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 const targetWindow = instance.targetWindow\n if (!targetWindow) {\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 (!targetWindow.ResizeObserver) {\n return () => {}\n }\n\n const observer = new targetWindow.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 const targetWindow = instance.targetWindow\n if (!targetWindow) {\n return\n }\n\n let offset = 0\n const fallback = supportsScrollend\n ? () => undefined\n : debounce(\n targetWindow,\n () => {\n cb(offset, false)\n },\n instance.options.isScrollingResetDelay,\n )\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 const targetWindow = instance.targetWindow\n if (!targetWindow) {\n return\n }\n\n let offset = 0\n const fallback = supportsScrollend\n ? () => undefined\n : debounce(\n targetWindow,\n () => {\n cb(offset, false)\n },\n instance.options.isScrollingResetDelay,\n )\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<TItemElement>[]\n lanes?: number\n isScrollingResetDelay?: number\n enabled?: boolean\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 targetWindow: (Window & typeof globalThis) | null = null\n isScrolling: boolean = false\n private scrollToIndexTimeoutId: number | null = null\n measurementsCache: VirtualItem<TItemElement>[] = []\n private itemSizeCache = new Map<Key, number>()\n private pendingMeasuredCacheIndexes: number[] = []\n scrollRect: Rect | null = null\n scrollOffset: number | null = null\n scrollDirection: ScrollDirection | null = null\n private scrollAdjustments: number = 0\n shouldAdjustScrollPositionOnItemSizeChange:\n | undefined\n | ((\n item: VirtualItem<TItemElement>,\n delta: number,\n instance: Virtualizer<TScrollElement, TItemElement>,\n ) => boolean)\n elementsCache = new Map<Key, TItemElement>()\n private observer = (() => {\n let _ro: ResizeObserver | null = null\n\n const get = () => {\n if (_ro) {\n return _ro\n }\n\n if (!this.targetWindow || !this.targetWindow.ResizeObserver) {\n return null\n }\n\n return (_ro = new this.targetWindow.ResizeObserver((entries) => {\n entries.forEach((entry) => {\n this._measureElement(entry.target as TItemElement, entry)\n })\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 }\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 enabled: true,\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 this.targetWindow = null\n this.observer.disconnect()\n this.elementsCache.clear()\n }\n\n _didMount = () => {\n return () => {\n this.cleanup()\n }\n }\n\n _willUpdate = () => {\n const scrollElement = this.options.enabled\n ? this.options.getScrollElement()\n : null\n\n if (this.scrollElement !== scrollElement) {\n this.cleanup()\n\n if (!scrollElement) {\n this.notify(false, false)\n return\n }\n\n this.scrollElement = scrollElement\n\n if (this.scrollElement && 'ownerDocument' in this.scrollElement) {\n this.targetWindow = this.scrollElement.ownerDocument.defaultView\n } else {\n this.targetWindow = this.scrollElement?.window ?? null\n }\n\n this._scrollToOffset(this.getScrollOffset(), {\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.getScrollOffset() < 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 if (!this.options.enabled) {\n this.scrollRect = null\n return 0\n }\n\n this.scrollRect = this.scrollRect ?? this.options.initialRect\n\n return this.scrollRect[this.options.horizontal ? 'width' : 'height']\n }\n\n private getScrollOffset = () => {\n if (!this.options.enabled) {\n this.scrollOffset = null\n return 0\n }\n\n this.scrollOffset =\n this.scrollOffset ??\n (typeof this.options.initialOffset === 'function'\n ? this.options.initialOffset()\n : this.options.initialOffset)\n\n return this.scrollOffset\n }\n\n private getFurthestMeasurement = (\n measurements: VirtualItem<TItemElement>[],\n index: number,\n ) => {\n const furthestMeasurementsFound = new Map<number, true>()\n const furthestMeasurements = new Map<number, VirtualItem<TItemElement>>()\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 getMeasurementOptions = memo(\n () => [\n this.options.count,\n this.options.paddingStart,\n this.options.scrollMargin,\n this.options.getItemKey,\n this.options.enabled,\n ],\n (count, paddingStart, scrollMargin, getItemKey, enabled) => {\n this.pendingMeasuredCacheIndexes = []\n return {\n count,\n paddingStart,\n scrollMargin,\n getItemKey,\n enabled,\n }\n },\n {\n key: false,\n },\n )\n\n private getMeasurements = memo(\n () => [this.getMeasurementOptions(), this.itemSizeCache],\n (\n { count, paddingStart, scrollMargin, getItemKey, enabled },\n itemSizeCache,\n ) => {\n if (!enabled) {\n this.measurementsCache = []\n this.itemSizeCache.clear()\n return []\n }\n\n if (this.measurementsCache.length === 0) {\n this.measurementsCache = this.options.initialMeasurementsCache\n this.measurementsCache.forEach((item) => {\n this.itemSizeCache.set(item.key, item.size)\n })\n }\n\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 let measureElement = this.measurementsCache[i]?.measureElement\n\n if (!measureElement) {\n measureElement = (node: TItemElement | null | undefined) => {\n const key = getItemKey(i)\n const prevNode = this.elementsCache.get(key)\n\n if (!node) {\n if (prevNode) {\n this.observer.unobserve(prevNode)\n this.elementsCache.delete(key)\n }\n return\n }\n\n if (prevNode !== node) {\n if (prevNode) {\n this.observer.unobserve(prevNode)\n }\n this.observer.observe(node)\n this.elementsCache.set(key, node)\n }\n\n if (node.isConnected) {\n this.resizeItem(\n i,\n this.options.measureElement(node, undefined, this),\n )\n }\n }\n }\n\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 measureElement,\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.getScrollOffset()],\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 i = this.indexFromElement(node)\n const item = this.getMeasurements()[i]\n\n if (!item || !node.isConnected) {\n this.elementsCache.forEach((cached, key) => {\n if (cached === node) {\n this.observer.unobserve(node)\n this.elementsCache.delete(key)\n }\n })\n return\n }\n\n const prevNode = this.elementsCache.get(item.key)\n\n if (prevNode !== node) {\n if (prevNode) {\n this.observer.unobserve(prevNode)\n }\n this.observer.observe(node)\n this.elementsCache.set(item.key, node)\n }\n\n this.resizeItem(i, this.options.measureElement(node, entry, this))\n }\n\n resizeItem = (index: number, size: number) => {\n const item = this.getMeasurements()[index]\n if (!item) {\n return\n }\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.getScrollOffset() + this.scrollAdjustments\n ) {\n if (process.env.NODE_ENV !== 'production' && this.options.debug) {\n console.info('correction', delta)\n }\n\n this._scrollToOffset(this.getScrollOffset(), {\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 | undefined) => {\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<TItemElement>[] = []\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 if (measurements.length === 0) {\n return undefined\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 const scrollOffset = this.getScrollOffset()\n\n if (align === 'auto') {\n if (toOffset <= scrollOffset) {\n align = 'start'\n } else if (toOffset >= 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 - size\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 item = this.getMeasurements()[index]\n if (!item) {\n return undefined\n }\n\n const size = this.getSize()\n const scrollOffset = this.getScrollOffset()\n\n if (align === 'auto') {\n if (item.end >= scrollOffset + size - this.options.scrollPaddingEnd) {\n align = 'end'\n } else if (item.start <= scrollOffset + this.options.scrollPaddingStart) {\n align = 'start'\n } else {\n return [scrollOffset, align] as const\n }\n }\n\n const toOffset =\n align === 'end'\n ? item.end + this.options.scrollPaddingEnd\n : item.start - this.options.scrollPaddingStart\n\n return [this.getOffsetForAlignment(toOffset, align), align] as const\n }\n\n private isDynamicMode = () => this.elementsCache.size > 0\n\n private cancelScrollToIndex = () => {\n if (this.scrollToIndexTimeoutId !== null && this.targetWindow) {\n this.targetWindow.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 offsetAndAlign = this.getOffsetForIndex(index, initialAlign)\n if (!offsetAndAlign) return\n\n const [offset, align] = offsetAndAlign\n\n this._scrollToOffset(offset, { adjustments: undefined, behavior })\n\n if (behavior !== 'smooth' && this.isDynamicMode() && this.targetWindow) {\n this.scrollToIndexTimeoutId = this.targetWindow.setTimeout(() => {\n this.scrollToIndexTimeoutId = null\n\n const elementInDOM = this.elementsCache.has(\n this.options.getItemKey(index),\n )\n\n if (elementInDOM) {\n const [latestOffset] = notUndefined(\n this.getOffsetForIndex(index, align),\n )\n\n if (!approxEqual(latestOffset, this.getScrollOffset())) {\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.getScrollOffset() + 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<TItemElement extends Element>({\n measurements,\n outerSize,\n scrollOffset,\n}: {\n measurements: VirtualItem<TItemElement>[]\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","measureElement","key","notUndefined","approxEqual"],"mappings":"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"}
@@ -15,13 +15,14 @@ export interface Range {
15
15
  count: number;
16
16
  }
17
17
  type Key = number | string;
18
- export interface VirtualItem {
18
+ export interface VirtualItem<TItemElement extends Element> {
19
19
  key: Key;
20
20
  index: number;
21
21
  start: number;
22
22
  end: number;
23
23
  size: number;
24
24
  lane: number;
25
+ measureElement: (node: TItemElement | null | undefined) => void;
25
26
  }
26
27
  export interface Rect {
27
28
  width: number;
@@ -68,7 +69,7 @@ export interface VirtualizerOptions<TScrollElement extends Element | Window, TIt
68
69
  scrollMargin?: number;
69
70
  gap?: number;
70
71
  indexAttribute?: string;
71
- initialMeasurementsCache?: VirtualItem[];
72
+ initialMeasurementsCache?: VirtualItem<TItemElement>[];
72
73
  lanes?: number;
73
74
  isScrollingResetDelay?: number;
74
75
  enabled?: boolean;
@@ -80,15 +81,15 @@ export declare class Virtualizer<TScrollElement extends Element | Window, TItemE
80
81
  targetWindow: (Window & typeof globalThis) | null;
81
82
  isScrolling: boolean;
82
83
  private scrollToIndexTimeoutId;
83
- measurementsCache: VirtualItem[];
84
+ measurementsCache: VirtualItem<TItemElement>[];
84
85
  private itemSizeCache;
85
86
  private pendingMeasuredCacheIndexes;
86
87
  scrollRect: Rect | null;
87
88
  scrollOffset: number | null;
88
89
  scrollDirection: ScrollDirection | null;
89
90
  private scrollAdjustments;
90
- shouldAdjustScrollPositionOnItemSizeChange: undefined | ((item: VirtualItem, delta: number, instance: Virtualizer<TScrollElement, TItemElement>) => boolean);
91
- measureElementCache: Map<Key, TItemElement>;
91
+ shouldAdjustScrollPositionOnItemSizeChange: undefined | ((item: VirtualItem<TItemElement>, delta: number, instance: Virtualizer<TScrollElement, TItemElement>) => boolean);
92
+ elementsCache: Map<Key, TItemElement>;
92
93
  private observer;
93
94
  range: {
94
95
  startIndex: number;
@@ -112,10 +113,10 @@ export declare class Virtualizer<TScrollElement extends Element | Window, TItemE
112
113
  private getIndexes;
113
114
  indexFromElement: (node: TItemElement) => number;
114
115
  private _measureElement;
115
- resizeItem: (item: VirtualItem, size: number) => void;
116
- measureElement: (node: TItemElement | null) => void;
117
- getVirtualItems: () => VirtualItem[];
118
- getVirtualItemForOffset: (offset: number) => VirtualItem | undefined;
116
+ resizeItem: (index: number, size: number) => void;
117
+ measureElement: (node: TItemElement | null | undefined) => void;
118
+ getVirtualItems: () => VirtualItem<TItemElement>[];
119
+ getVirtualItemForOffset: (offset: number) => VirtualItem<TItemElement> | undefined;
119
120
  getOffsetForAlignment: (toOffset: number, align: ScrollAlignment) => number;
120
121
  getOffsetForIndex: (index: number, align?: ScrollAlignment) => readonly [number, "auto"] | readonly [number, "start" | "center" | "end"] | undefined;
121
122
  private isDynamicMode;
@@ -15,13 +15,14 @@ export interface Range {
15
15
  count: number;
16
16
  }
17
17
  type Key = number | string;
18
- export interface VirtualItem {
18
+ export interface VirtualItem<TItemElement extends Element> {
19
19
  key: Key;
20
20
  index: number;
21
21
  start: number;
22
22
  end: number;
23
23
  size: number;
24
24
  lane: number;
25
+ measureElement: (node: TItemElement | null | undefined) => void;
25
26
  }
26
27
  export interface Rect {
27
28
  width: number;
@@ -68,7 +69,7 @@ export interface VirtualizerOptions<TScrollElement extends Element | Window, TIt
68
69
  scrollMargin?: number;
69
70
  gap?: number;
70
71
  indexAttribute?: string;
71
- initialMeasurementsCache?: VirtualItem[];
72
+ initialMeasurementsCache?: VirtualItem<TItemElement>[];
72
73
  lanes?: number;
73
74
  isScrollingResetDelay?: number;
74
75
  enabled?: boolean;
@@ -80,15 +81,15 @@ export declare class Virtualizer<TScrollElement extends Element | Window, TItemE
80
81
  targetWindow: (Window & typeof globalThis) | null;
81
82
  isScrolling: boolean;
82
83
  private scrollToIndexTimeoutId;
83
- measurementsCache: VirtualItem[];
84
+ measurementsCache: VirtualItem<TItemElement>[];
84
85
  private itemSizeCache;
85
86
  private pendingMeasuredCacheIndexes;
86
87
  scrollRect: Rect | null;
87
88
  scrollOffset: number | null;
88
89
  scrollDirection: ScrollDirection | null;
89
90
  private scrollAdjustments;
90
- shouldAdjustScrollPositionOnItemSizeChange: undefined | ((item: VirtualItem, delta: number, instance: Virtualizer<TScrollElement, TItemElement>) => boolean);
91
- measureElementCache: Map<Key, TItemElement>;
91
+ shouldAdjustScrollPositionOnItemSizeChange: undefined | ((item: VirtualItem<TItemElement>, delta: number, instance: Virtualizer<TScrollElement, TItemElement>) => boolean);
92
+ elementsCache: Map<Key, TItemElement>;
92
93
  private observer;
93
94
  range: {
94
95
  startIndex: number;
@@ -112,10 +113,10 @@ export declare class Virtualizer<TScrollElement extends Element | Window, TItemE
112
113
  private getIndexes;
113
114
  indexFromElement: (node: TItemElement) => number;
114
115
  private _measureElement;
115
- resizeItem: (item: VirtualItem, size: number) => void;
116
- measureElement: (node: TItemElement | null) => void;
117
- getVirtualItems: () => VirtualItem[];
118
- getVirtualItemForOffset: (offset: number) => VirtualItem | undefined;
116
+ resizeItem: (index: number, size: number) => void;
117
+ measureElement: (node: TItemElement | null | undefined) => void;
118
+ getVirtualItems: () => VirtualItem<TItemElement>[];
119
+ getVirtualItemForOffset: (offset: number) => VirtualItem<TItemElement> | undefined;
119
120
  getOffsetForAlignment: (toOffset: number, align: ScrollAlignment) => number;
120
121
  getOffsetForIndex: (index: number, align?: ScrollAlignment) => readonly [number, "auto"] | readonly [number, "start" | "center" | "end"] | undefined;
121
122
  private isDynamicMode;
package/dist/esm/index.js CHANGED
@@ -175,7 +175,7 @@ class Virtualizer {
175
175
  this.scrollOffset = null;
176
176
  this.scrollDirection = null;
177
177
  this.scrollAdjustments = 0;
178
- this.measureElementCache = /* @__PURE__ */ new Map();
178
+ this.elementsCache = /* @__PURE__ */ new Map();
179
179
  this.observer = /* @__PURE__ */ (() => {
180
180
  let _ro = null;
181
181
  const get = () => {
@@ -254,7 +254,7 @@ class Virtualizer {
254
254
  this.scrollElement = null;
255
255
  this.targetWindow = null;
256
256
  this.observer.disconnect();
257
- this.measureElementCache.clear();
257
+ this.elementsCache.clear();
258
258
  };
259
259
  this._didMount = () => {
260
260
  return () => {
@@ -366,6 +366,7 @@ class Virtualizer {
366
366
  this.getMeasurements = memo(
367
367
  () => [this.getMeasurementOptions(), this.itemSizeCache],
368
368
  ({ count, paddingStart, scrollMargin, getItemKey, enabled }, itemSizeCache) => {
369
+ var _a;
369
370
  if (!enabled) {
370
371
  this.measurementsCache = [];
371
372
  this.itemSizeCache.clear();
@@ -381,6 +382,33 @@ class Virtualizer {
381
382
  this.pendingMeasuredCacheIndexes = [];
382
383
  const measurements = this.measurementsCache.slice(0, min);
383
384
  for (let i = min; i < count; i++) {
385
+ let measureElement2 = (_a = this.measurementsCache[i]) == null ? void 0 : _a.measureElement;
386
+ if (!measureElement2) {
387
+ measureElement2 = (node) => {
388
+ const key2 = getItemKey(i);
389
+ const prevNode = this.elementsCache.get(key2);
390
+ if (!node) {
391
+ if (prevNode) {
392
+ this.observer.unobserve(prevNode);
393
+ this.elementsCache.delete(key2);
394
+ }
395
+ return;
396
+ }
397
+ if (prevNode !== node) {
398
+ if (prevNode) {
399
+ this.observer.unobserve(prevNode);
400
+ }
401
+ this.observer.observe(node);
402
+ this.elementsCache.set(key2, node);
403
+ }
404
+ if (node.isConnected) {
405
+ this.resizeItem(
406
+ i,
407
+ this.options.measureElement(node, void 0, this)
408
+ );
409
+ }
410
+ };
411
+ }
384
412
  const key = getItemKey(i);
385
413
  const furthestMeasurement = this.options.lanes === 1 ? measurements[i - 1] : this.getFurthestMeasurement(measurements, i);
386
414
  const start = furthestMeasurement ? furthestMeasurement.end + this.options.gap : paddingStart + scrollMargin;
@@ -394,7 +422,8 @@ class Virtualizer {
394
422
  size,
395
423
  end,
396
424
  key,
397
- lane
425
+ lane,
426
+ measureElement: measureElement2
398
427
  };
399
428
  }
400
429
  this.measurementsCache = measurements;
@@ -451,28 +480,32 @@ class Virtualizer {
451
480
  return parseInt(indexStr, 10);
452
481
  };
453
482
  this._measureElement = (node, entry) => {
454
- const item = this.getMeasurements()[this.indexFromElement(node)];
483
+ const i = this.indexFromElement(node);
484
+ const item = this.getMeasurements()[i];
455
485
  if (!item || !node.isConnected) {
456
- this.measureElementCache.forEach((cached, key) => {
486
+ this.elementsCache.forEach((cached, key) => {
457
487
  if (cached === node) {
458
488
  this.observer.unobserve(node);
459
- this.measureElementCache.delete(key);
489
+ this.elementsCache.delete(key);
460
490
  }
461
491
  });
462
492
  return;
463
493
  }
464
- const prevNode = this.measureElementCache.get(item.key);
494
+ const prevNode = this.elementsCache.get(item.key);
465
495
  if (prevNode !== node) {
466
496
  if (prevNode) {
467
497
  this.observer.unobserve(prevNode);
468
498
  }
469
499
  this.observer.observe(node);
470
- this.measureElementCache.set(item.key, node);
500
+ this.elementsCache.set(item.key, node);
471
501
  }
472
- const measuredItemSize = this.options.measureElement(node, entry, this);
473
- this.resizeItem(item, measuredItemSize);
502
+ this.resizeItem(i, this.options.measureElement(node, entry, this));
474
503
  };
475
- this.resizeItem = (item, size) => {
504
+ this.resizeItem = (index, size) => {
505
+ const item = this.getMeasurements()[index];
506
+ if (!item) {
507
+ return;
508
+ }
476
509
  const itemSize = this.itemSizeCache.get(item.key) ?? item.size;
477
510
  const delta = size - itemSize;
478
511
  if (delta !== 0) {
@@ -570,7 +603,7 @@ class Virtualizer {
570
603
  const toOffset = align === "end" ? item.end + this.options.scrollPaddingEnd : item.start - this.options.scrollPaddingStart;
571
604
  return [this.getOffsetForAlignment(toOffset, align), align];
572
605
  };
573
- this.isDynamicMode = () => this.measureElementCache.size > 0;
606
+ this.isDynamicMode = () => this.elementsCache.size > 0;
574
607
  this.cancelScrollToIndex = () => {
575
608
  if (this.scrollToIndexTimeoutId !== null && this.targetWindow) {
576
609
  this.targetWindow.clearTimeout(this.scrollToIndexTimeoutId);
@@ -605,7 +638,7 @@ class Virtualizer {
605
638
  if (behavior !== "smooth" && this.isDynamicMode() && this.targetWindow) {
606
639
  this.scrollToIndexTimeoutId = this.targetWindow.setTimeout(() => {
607
640
  this.scrollToIndexTimeoutId = null;
608
- const elementInDOM = this.measureElementCache.has(
641
+ const elementInDOM = this.elementsCache.has(
609
642
  this.options.getItemKey(index)
610
643
  );
611
644
  if (elementInDOM) {
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","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 const targetWindow = instance.targetWindow\n if (!targetWindow) {\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 (!targetWindow.ResizeObserver) {\n return () => {}\n }\n\n const observer = new targetWindow.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 const targetWindow = instance.targetWindow\n if (!targetWindow) {\n return\n }\n\n let offset = 0\n const fallback = supportsScrollend\n ? () => undefined\n : debounce(\n targetWindow,\n () => {\n cb(offset, false)\n },\n instance.options.isScrollingResetDelay,\n )\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 const targetWindow = instance.targetWindow\n if (!targetWindow) {\n return\n }\n\n let offset = 0\n const fallback = supportsScrollend\n ? () => undefined\n : debounce(\n targetWindow,\n () => {\n cb(offset, false)\n },\n instance.options.isScrollingResetDelay,\n )\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 enabled?: boolean\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 targetWindow: (Window & typeof globalThis) | null = null\n isScrolling: boolean = false\n private scrollToIndexTimeoutId: number | null = null\n measurementsCache: VirtualItem[] = []\n private itemSizeCache = new Map<Key, number>()\n private pendingMeasuredCacheIndexes: number[] = []\n scrollRect: Rect | null = null\n scrollOffset: number | null = null\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 }\n\n if (!this.targetWindow || !this.targetWindow.ResizeObserver) {\n return null\n }\n\n return (_ro = new this.targetWindow.ResizeObserver((entries) => {\n entries.forEach((entry) => {\n this._measureElement(entry.target as TItemElement, entry)\n })\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 }\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 enabled: true,\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 this.targetWindow = null\n this.observer.disconnect()\n this.measureElementCache.clear()\n }\n\n _didMount = () => {\n return () => {\n this.cleanup()\n }\n }\n\n _willUpdate = () => {\n const scrollElement = this.options.enabled\n ? this.options.getScrollElement()\n : null\n\n if (this.scrollElement !== scrollElement) {\n this.cleanup()\n\n if (!scrollElement) {\n this.notify(false, false)\n return\n }\n\n this.scrollElement = scrollElement\n\n if (this.scrollElement && 'ownerDocument' in this.scrollElement) {\n this.targetWindow = this.scrollElement.ownerDocument.defaultView\n } else {\n this.targetWindow = this.scrollElement?.window ?? null\n }\n\n this._scrollToOffset(this.getScrollOffset(), {\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.getScrollOffset() < 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 if (!this.options.enabled) {\n this.scrollRect = null\n return 0\n }\n\n this.scrollRect = this.scrollRect ?? this.options.initialRect\n\n return this.scrollRect[this.options.horizontal ? 'width' : 'height']\n }\n\n private getScrollOffset = () => {\n if (!this.options.enabled) {\n this.scrollOffset = null\n return 0\n }\n\n this.scrollOffset =\n this.scrollOffset ??\n (typeof this.options.initialOffset === 'function'\n ? this.options.initialOffset()\n : this.options.initialOffset)\n\n return this.scrollOffset\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 getMeasurementOptions = memo(\n () => [\n this.options.count,\n this.options.paddingStart,\n this.options.scrollMargin,\n this.options.getItemKey,\n this.options.enabled,\n ],\n (count, paddingStart, scrollMargin, getItemKey, enabled) => {\n this.pendingMeasuredCacheIndexes = []\n return {\n count,\n paddingStart,\n scrollMargin,\n getItemKey,\n enabled,\n }\n },\n {\n key: false,\n },\n )\n\n private getMeasurements = memo(\n () => [this.getMeasurementOptions(), this.itemSizeCache],\n (\n { count, paddingStart, scrollMargin, getItemKey, enabled },\n itemSizeCache,\n ) => {\n if (!enabled) {\n this.measurementsCache = []\n this.itemSizeCache.clear()\n return []\n }\n\n if (this.measurementsCache.length === 0) {\n this.measurementsCache = this.options.initialMeasurementsCache\n this.measurementsCache.forEach((item) => {\n this.itemSizeCache.set(item.key, item.size)\n })\n }\n\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.getScrollOffset()],\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.getMeasurements()[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.getScrollOffset() + this.scrollAdjustments\n ) {\n if (process.env.NODE_ENV !== 'production' && this.options.debug) {\n console.info('correction', delta)\n }\n\n this._scrollToOffset(this.getScrollOffset(), {\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 if (measurements.length === 0) {\n return undefined\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 const scrollOffset = this.getScrollOffset()\n\n if (align === 'auto') {\n if (toOffset <= scrollOffset) {\n align = 'start'\n } else if (toOffset >= 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 - size\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 item = this.getMeasurements()[index]\n if (!item) {\n return undefined\n }\n\n const size = this.getSize()\n const scrollOffset = this.getScrollOffset()\n\n if (align === 'auto') {\n if (item.end >= scrollOffset + size - this.options.scrollPaddingEnd) {\n align = 'end'\n } else if (item.start <= scrollOffset + this.options.scrollPaddingStart) {\n align = 'start'\n } else {\n return [scrollOffset, align] as const\n }\n }\n\n const toOffset =\n align === 'end'\n ? item.end + this.options.scrollPaddingEnd\n : item.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 && this.targetWindow) {\n this.targetWindow.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 offsetAndAlign = this.getOffsetForIndex(index, initialAlign)\n if (!offsetAndAlign) return\n\n const [offset, align] = offsetAndAlign\n\n this._scrollToOffset(offset, { adjustments: undefined, behavior })\n\n if (behavior !== 'smooth' && this.isDynamicMode() && this.targetWindow) {\n this.scrollToIndexTimeoutId = this.targetWindow.setTimeout(() => {\n this.scrollToIndexTimeoutId = null\n\n const elementInDOM = this.measureElementCache.has(\n this.options.getItemKey(index),\n )\n\n if (elementInDOM) {\n const [latestOffset] = notUndefined(\n this.getOffsetForIndex(index, align),\n )\n\n if (!approxEqual(latestOffset, this.getScrollOffset())) {\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.getScrollOffset() + 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":["opts"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","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<TItemElement extends Element> {\n key: Key\n index: number\n start: number\n end: number\n size: number\n lane: number\n measureElement: (node: TItemElement | null | undefined) => void\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 const targetWindow = instance.targetWindow\n if (!targetWindow) {\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 (!targetWindow.ResizeObserver) {\n return () => {}\n }\n\n const observer = new targetWindow.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 const targetWindow = instance.targetWindow\n if (!targetWindow) {\n return\n }\n\n let offset = 0\n const fallback = supportsScrollend\n ? () => undefined\n : debounce(\n targetWindow,\n () => {\n cb(offset, false)\n },\n instance.options.isScrollingResetDelay,\n )\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 const targetWindow = instance.targetWindow\n if (!targetWindow) {\n return\n }\n\n let offset = 0\n const fallback = supportsScrollend\n ? () => undefined\n : debounce(\n targetWindow,\n () => {\n cb(offset, false)\n },\n instance.options.isScrollingResetDelay,\n )\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<TItemElement>[]\n lanes?: number\n isScrollingResetDelay?: number\n enabled?: boolean\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 targetWindow: (Window & typeof globalThis) | null = null\n isScrolling: boolean = false\n private scrollToIndexTimeoutId: number | null = null\n measurementsCache: VirtualItem<TItemElement>[] = []\n private itemSizeCache = new Map<Key, number>()\n private pendingMeasuredCacheIndexes: number[] = []\n scrollRect: Rect | null = null\n scrollOffset: number | null = null\n scrollDirection: ScrollDirection | null = null\n private scrollAdjustments: number = 0\n shouldAdjustScrollPositionOnItemSizeChange:\n | undefined\n | ((\n item: VirtualItem<TItemElement>,\n delta: number,\n instance: Virtualizer<TScrollElement, TItemElement>,\n ) => boolean)\n elementsCache = new Map<Key, TItemElement>()\n private observer = (() => {\n let _ro: ResizeObserver | null = null\n\n const get = () => {\n if (_ro) {\n return _ro\n }\n\n if (!this.targetWindow || !this.targetWindow.ResizeObserver) {\n return null\n }\n\n return (_ro = new this.targetWindow.ResizeObserver((entries) => {\n entries.forEach((entry) => {\n this._measureElement(entry.target as TItemElement, entry)\n })\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 }\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 enabled: true,\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 this.targetWindow = null\n this.observer.disconnect()\n this.elementsCache.clear()\n }\n\n _didMount = () => {\n return () => {\n this.cleanup()\n }\n }\n\n _willUpdate = () => {\n const scrollElement = this.options.enabled\n ? this.options.getScrollElement()\n : null\n\n if (this.scrollElement !== scrollElement) {\n this.cleanup()\n\n if (!scrollElement) {\n this.notify(false, false)\n return\n }\n\n this.scrollElement = scrollElement\n\n if (this.scrollElement && 'ownerDocument' in this.scrollElement) {\n this.targetWindow = this.scrollElement.ownerDocument.defaultView\n } else {\n this.targetWindow = this.scrollElement?.window ?? null\n }\n\n this._scrollToOffset(this.getScrollOffset(), {\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.getScrollOffset() < 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 if (!this.options.enabled) {\n this.scrollRect = null\n return 0\n }\n\n this.scrollRect = this.scrollRect ?? this.options.initialRect\n\n return this.scrollRect[this.options.horizontal ? 'width' : 'height']\n }\n\n private getScrollOffset = () => {\n if (!this.options.enabled) {\n this.scrollOffset = null\n return 0\n }\n\n this.scrollOffset =\n this.scrollOffset ??\n (typeof this.options.initialOffset === 'function'\n ? this.options.initialOffset()\n : this.options.initialOffset)\n\n return this.scrollOffset\n }\n\n private getFurthestMeasurement = (\n measurements: VirtualItem<TItemElement>[],\n index: number,\n ) => {\n const furthestMeasurementsFound = new Map<number, true>()\n const furthestMeasurements = new Map<number, VirtualItem<TItemElement>>()\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 getMeasurementOptions = memo(\n () => [\n this.options.count,\n this.options.paddingStart,\n this.options.scrollMargin,\n this.options.getItemKey,\n this.options.enabled,\n ],\n (count, paddingStart, scrollMargin, getItemKey, enabled) => {\n this.pendingMeasuredCacheIndexes = []\n return {\n count,\n paddingStart,\n scrollMargin,\n getItemKey,\n enabled,\n }\n },\n {\n key: false,\n },\n )\n\n private getMeasurements = memo(\n () => [this.getMeasurementOptions(), this.itemSizeCache],\n (\n { count, paddingStart, scrollMargin, getItemKey, enabled },\n itemSizeCache,\n ) => {\n if (!enabled) {\n this.measurementsCache = []\n this.itemSizeCache.clear()\n return []\n }\n\n if (this.measurementsCache.length === 0) {\n this.measurementsCache = this.options.initialMeasurementsCache\n this.measurementsCache.forEach((item) => {\n this.itemSizeCache.set(item.key, item.size)\n })\n }\n\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 let measureElement = this.measurementsCache[i]?.measureElement\n\n if (!measureElement) {\n measureElement = (node: TItemElement | null | undefined) => {\n const key = getItemKey(i)\n const prevNode = this.elementsCache.get(key)\n\n if (!node) {\n if (prevNode) {\n this.observer.unobserve(prevNode)\n this.elementsCache.delete(key)\n }\n return\n }\n\n if (prevNode !== node) {\n if (prevNode) {\n this.observer.unobserve(prevNode)\n }\n this.observer.observe(node)\n this.elementsCache.set(key, node)\n }\n\n if (node.isConnected) {\n this.resizeItem(\n i,\n this.options.measureElement(node, undefined, this),\n )\n }\n }\n }\n\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 measureElement,\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.getScrollOffset()],\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 i = this.indexFromElement(node)\n const item = this.getMeasurements()[i]\n\n if (!item || !node.isConnected) {\n this.elementsCache.forEach((cached, key) => {\n if (cached === node) {\n this.observer.unobserve(node)\n this.elementsCache.delete(key)\n }\n })\n return\n }\n\n const prevNode = this.elementsCache.get(item.key)\n\n if (prevNode !== node) {\n if (prevNode) {\n this.observer.unobserve(prevNode)\n }\n this.observer.observe(node)\n this.elementsCache.set(item.key, node)\n }\n\n this.resizeItem(i, this.options.measureElement(node, entry, this))\n }\n\n resizeItem = (index: number, size: number) => {\n const item = this.getMeasurements()[index]\n if (!item) {\n return\n }\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.getScrollOffset() + this.scrollAdjustments\n ) {\n if (process.env.NODE_ENV !== 'production' && this.options.debug) {\n console.info('correction', delta)\n }\n\n this._scrollToOffset(this.getScrollOffset(), {\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 | undefined) => {\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<TItemElement>[] = []\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 if (measurements.length === 0) {\n return undefined\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 const scrollOffset = this.getScrollOffset()\n\n if (align === 'auto') {\n if (toOffset <= scrollOffset) {\n align = 'start'\n } else if (toOffset >= 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 - size\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 item = this.getMeasurements()[index]\n if (!item) {\n return undefined\n }\n\n const size = this.getSize()\n const scrollOffset = this.getScrollOffset()\n\n if (align === 'auto') {\n if (item.end >= scrollOffset + size - this.options.scrollPaddingEnd) {\n align = 'end'\n } else if (item.start <= scrollOffset + this.options.scrollPaddingStart) {\n align = 'start'\n } else {\n return [scrollOffset, align] as const\n }\n }\n\n const toOffset =\n align === 'end'\n ? item.end + this.options.scrollPaddingEnd\n : item.start - this.options.scrollPaddingStart\n\n return [this.getOffsetForAlignment(toOffset, align), align] as const\n }\n\n private isDynamicMode = () => this.elementsCache.size > 0\n\n private cancelScrollToIndex = () => {\n if (this.scrollToIndexTimeoutId !== null && this.targetWindow) {\n this.targetWindow.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 offsetAndAlign = this.getOffsetForIndex(index, initialAlign)\n if (!offsetAndAlign) return\n\n const [offset, align] = offsetAndAlign\n\n this._scrollToOffset(offset, { adjustments: undefined, behavior })\n\n if (behavior !== 'smooth' && this.isDynamicMode() && this.targetWindow) {\n this.scrollToIndexTimeoutId = this.targetWindow.setTimeout(() => {\n this.scrollToIndexTimeoutId = null\n\n const elementInDOM = this.elementsCache.has(\n this.options.getItemKey(index),\n )\n\n if (elementInDOM) {\n const [latestOffset] = notUndefined(\n this.getOffsetForIndex(index, align),\n )\n\n if (!approxEqual(latestOffset, this.getScrollOffset())) {\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.getScrollOffset() + 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<TItemElement extends Element>({\n measurements,\n outerSize,\n scrollOffset,\n}: {\n measurements: VirtualItem<TItemElement>[]\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","measureElement","key"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/virtual-core",
3
- "version": "3.6.0",
3
+ "version": "3.7.0",
4
4
  "description": "Headless UI for virtualizing scrollable elements in TS/JS + Frameworks",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
package/src/index.ts CHANGED
@@ -28,13 +28,14 @@ export interface Range {
28
28
 
29
29
  type Key = number | string
30
30
 
31
- export interface VirtualItem {
31
+ export interface VirtualItem<TItemElement extends Element> {
32
32
  key: Key
33
33
  index: number
34
34
  start: number
35
35
  end: number
36
36
  size: number
37
37
  lane: number
38
+ measureElement: (node: TItemElement | null | undefined) => void
38
39
  }
39
40
 
40
41
  export interface Rect {
@@ -315,7 +316,7 @@ export interface VirtualizerOptions<
315
316
  scrollMargin?: number
316
317
  gap?: number
317
318
  indexAttribute?: string
318
- initialMeasurementsCache?: VirtualItem[]
319
+ initialMeasurementsCache?: VirtualItem<TItemElement>[]
319
320
  lanes?: number
320
321
  isScrollingResetDelay?: number
321
322
  enabled?: boolean
@@ -331,7 +332,7 @@ export class Virtualizer<
331
332
  targetWindow: (Window & typeof globalThis) | null = null
332
333
  isScrolling: boolean = false
333
334
  private scrollToIndexTimeoutId: number | null = null
334
- measurementsCache: VirtualItem[] = []
335
+ measurementsCache: VirtualItem<TItemElement>[] = []
335
336
  private itemSizeCache = new Map<Key, number>()
336
337
  private pendingMeasuredCacheIndexes: number[] = []
337
338
  scrollRect: Rect | null = null
@@ -341,11 +342,11 @@ export class Virtualizer<
341
342
  shouldAdjustScrollPositionOnItemSizeChange:
342
343
  | undefined
343
344
  | ((
344
- item: VirtualItem,
345
+ item: VirtualItem<TItemElement>,
345
346
  delta: number,
346
347
  instance: Virtualizer<TScrollElement, TItemElement>,
347
348
  ) => boolean)
348
- measureElementCache = new Map<Key, TItemElement>()
349
+ elementsCache = new Map<Key, TItemElement>()
349
350
  private observer = (() => {
350
351
  let _ro: ResizeObserver | null = null
351
352
 
@@ -430,7 +431,7 @@ export class Virtualizer<
430
431
  this.scrollElement = null
431
432
  this.targetWindow = null
432
433
  this.observer.disconnect()
433
- this.measureElementCache.clear()
434
+ this.elementsCache.clear()
434
435
  }
435
436
 
436
437
  _didMount = () => {
@@ -518,11 +519,11 @@ export class Virtualizer<
518
519
  }
519
520
 
520
521
  private getFurthestMeasurement = (
521
- measurements: VirtualItem[],
522
+ measurements: VirtualItem<TItemElement>[],
522
523
  index: number,
523
524
  ) => {
524
525
  const furthestMeasurementsFound = new Map<number, true>()
525
- const furthestMeasurements = new Map<number, VirtualItem>()
526
+ const furthestMeasurements = new Map<number, VirtualItem<TItemElement>>()
526
527
  for (let m = index - 1; m >= 0; m--) {
527
528
  const measurement = measurements[m]!
528
529
 
@@ -609,6 +610,38 @@ export class Virtualizer<
609
610
  const measurements = this.measurementsCache.slice(0, min)
610
611
 
611
612
  for (let i = min; i < count; i++) {
613
+ let measureElement = this.measurementsCache[i]?.measureElement
614
+
615
+ if (!measureElement) {
616
+ measureElement = (node: TItemElement | null | undefined) => {
617
+ const key = getItemKey(i)
618
+ const prevNode = this.elementsCache.get(key)
619
+
620
+ if (!node) {
621
+ if (prevNode) {
622
+ this.observer.unobserve(prevNode)
623
+ this.elementsCache.delete(key)
624
+ }
625
+ return
626
+ }
627
+
628
+ if (prevNode !== node) {
629
+ if (prevNode) {
630
+ this.observer.unobserve(prevNode)
631
+ }
632
+ this.observer.observe(node)
633
+ this.elementsCache.set(key, node)
634
+ }
635
+
636
+ if (node.isConnected) {
637
+ this.resizeItem(
638
+ i,
639
+ this.options.measureElement(node, undefined, this),
640
+ )
641
+ }
642
+ }
643
+ }
644
+
612
645
  const key = getItemKey(i)
613
646
 
614
647
  const furthestMeasurement =
@@ -639,6 +672,7 @@ export class Virtualizer<
639
672
  end,
640
673
  key,
641
674
  lane,
675
+ measureElement,
642
676
  }
643
677
  }
644
678
 
@@ -711,34 +745,37 @@ export class Virtualizer<
711
745
  node: TItemElement,
712
746
  entry: ResizeObserverEntry | undefined,
713
747
  ) => {
714
- const item = this.getMeasurements()[this.indexFromElement(node)]
748
+ const i = this.indexFromElement(node)
749
+ const item = this.getMeasurements()[i]
715
750
 
716
751
  if (!item || !node.isConnected) {
717
- this.measureElementCache.forEach((cached, key) => {
752
+ this.elementsCache.forEach((cached, key) => {
718
753
  if (cached === node) {
719
754
  this.observer.unobserve(node)
720
- this.measureElementCache.delete(key)
755
+ this.elementsCache.delete(key)
721
756
  }
722
757
  })
723
758
  return
724
759
  }
725
760
 
726
- const prevNode = this.measureElementCache.get(item.key)
761
+ const prevNode = this.elementsCache.get(item.key)
727
762
 
728
763
  if (prevNode !== node) {
729
764
  if (prevNode) {
730
765
  this.observer.unobserve(prevNode)
731
766
  }
732
767
  this.observer.observe(node)
733
- this.measureElementCache.set(item.key, node)
768
+ this.elementsCache.set(item.key, node)
734
769
  }
735
770
 
736
- const measuredItemSize = this.options.measureElement(node, entry, this)
737
-
738
- this.resizeItem(item, measuredItemSize)
771
+ this.resizeItem(i, this.options.measureElement(node, entry, this))
739
772
  }
740
773
 
741
- resizeItem = (item: VirtualItem, size: number) => {
774
+ resizeItem = (index: number, size: number) => {
775
+ const item = this.getMeasurements()[index]
776
+ if (!item) {
777
+ return
778
+ }
742
779
  const itemSize = this.itemSizeCache.get(item.key) ?? item.size
743
780
  const delta = size - itemSize
744
781
 
@@ -765,7 +802,7 @@ export class Virtualizer<
765
802
  }
766
803
  }
767
804
 
768
- measureElement = (node: TItemElement | null) => {
805
+ measureElement = (node: TItemElement | null | undefined) => {
769
806
  if (!node) {
770
807
  return
771
808
  }
@@ -776,7 +813,7 @@ export class Virtualizer<
776
813
  getVirtualItems = memo(
777
814
  () => [this.getIndexes(), this.getMeasurements()],
778
815
  (indexes, measurements) => {
779
- const virtualItems: VirtualItem[] = []
816
+ const virtualItems: VirtualItem<TItemElement>[] = []
780
817
 
781
818
  for (let k = 0, len = indexes.length; k < len; k++) {
782
819
  const i = indexes[k]!
@@ -875,7 +912,7 @@ export class Virtualizer<
875
912
  return [this.getOffsetForAlignment(toOffset, align), align] as const
876
913
  }
877
914
 
878
- private isDynamicMode = () => this.measureElementCache.size > 0
915
+ private isDynamicMode = () => this.elementsCache.size > 0
879
916
 
880
917
  private cancelScrollToIndex = () => {
881
918
  if (this.scrollToIndexTimeoutId !== null && this.targetWindow) {
@@ -927,7 +964,7 @@ export class Virtualizer<
927
964
  this.scrollToIndexTimeoutId = this.targetWindow.setTimeout(() => {
928
965
  this.scrollToIndexTimeoutId = null
929
966
 
930
- const elementInDOM = this.measureElementCache.has(
967
+ const elementInDOM = this.elementsCache.has(
931
968
  this.options.getItemKey(index),
932
969
  )
933
970
 
@@ -1026,12 +1063,12 @@ const findNearestBinarySearch = (
1026
1063
  }
1027
1064
  }
1028
1065
 
1029
- function calculateRange({
1066
+ function calculateRange<TItemElement extends Element>({
1030
1067
  measurements,
1031
1068
  outerSize,
1032
1069
  scrollOffset,
1033
1070
  }: {
1034
- measurements: VirtualItem[]
1071
+ measurements: VirtualItem<TItemElement>[]
1035
1072
  outerSize: number
1036
1073
  scrollOffset: number
1037
1074
  }) {