@tanstack/virtual-core 3.10.8 → 3.11.2

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.
@@ -73,7 +73,7 @@ const observeElementOffset = (instance, cb) => {
73
73
  return;
74
74
  }
75
75
  let offset = 0;
76
- const fallback = supportsScrollend ? () => void 0 : utils.debounce(
76
+ const fallback = instance.options.useScrollendEvent && supportsScrollend ? () => void 0 : utils.debounce(
77
77
  targetWindow,
78
78
  () => {
79
79
  cb(offset, false);
@@ -106,7 +106,7 @@ const observeWindowOffset = (instance, cb) => {
106
106
  return;
107
107
  }
108
108
  let offset = 0;
109
- const fallback = supportsScrollend ? () => void 0 : utils.debounce(
109
+ const fallback = instance.options.useScrollendEvent && supportsScrollend ? () => void 0 : utils.debounce(
110
110
  targetWindow,
111
111
  () => {
112
112
  cb(offset, false);
@@ -238,6 +238,7 @@ class Virtualizer {
238
238
  isScrollingResetDelay: 150,
239
239
  enabled: true,
240
240
  isRtl: false,
241
+ useScrollendEvent: true,
241
242
  ...opts2
242
243
  };
243
244
  };
@@ -557,20 +558,12 @@ class Virtualizer {
557
558
  const size = this.getSize();
558
559
  const scrollOffset = this.getScrollOffset();
559
560
  if (align === "auto") {
560
- if (toOffset <= scrollOffset) {
561
- align = "start";
562
- } else if (toOffset >= scrollOffset + size) {
561
+ if (toOffset >= scrollOffset + size) {
563
562
  align = "end";
564
- } else {
565
- align = "start";
566
563
  }
567
564
  }
568
- if (align === "start") {
569
- toOffset = toOffset;
570
- } else if (align === "end") {
571
- toOffset = toOffset - size;
572
- } else if (align === "center") {
573
- toOffset = toOffset - size / 2;
565
+ if (align === "end") {
566
+ toOffset -= size;
574
567
  }
575
568
  const scrollSizeProp = this.options.horizontal ? "scrollWidth" : "scrollHeight";
576
569
  const scrollSize = this.scrollElement ? "document" in this.scrollElement ? this.scrollElement.document.documentElement[scrollSizeProp] : this.scrollElement[scrollSizeProp] : 0;
@@ -594,8 +587,27 @@ class Virtualizer {
594
587
  return [scrollOffset, align];
595
588
  }
596
589
  }
597
- const toOffset = align === "end" ? item.end + this.options.scrollPaddingEnd : item.start - this.options.scrollPaddingStart;
598
- return [this.getOffsetForAlignment(toOffset, align), align];
590
+ const centerOffset = item.start - this.options.scrollPaddingStart + (item.size - size) / 2;
591
+ switch (align) {
592
+ case "center":
593
+ return [this.getOffsetForAlignment(centerOffset, align), align];
594
+ case "end":
595
+ return [
596
+ this.getOffsetForAlignment(
597
+ item.end + this.options.scrollPaddingEnd,
598
+ align
599
+ ),
600
+ align
601
+ ];
602
+ default:
603
+ return [
604
+ this.getOffsetForAlignment(
605
+ item.start - this.options.scrollPaddingStart,
606
+ align
607
+ ),
608
+ align
609
+ ];
610
+ }
599
611
  };
600
612
  this.isDynamicMode = () => this.elementsCache.size > 0;
601
613
  this.cancelScrollToIndex = () => {
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../../src/index.ts"],"sourcesContent":["import { approxEqual, debounce, memo, notUndefined } from './utils'\n\nexport * from './utils'\n\n//\n\ntype ScrollDirection = 'forward' | 'backward'\n\ntype ScrollAlignment = 'start' | 'center' | 'end' | 'auto'\n\ntype ScrollBehavior = 'auto' | 'smooth'\n\nexport interface ScrollToOptions {\n align?: ScrollAlignment\n behavior?: ScrollBehavior\n}\n\ntype ScrollToOffsetOptions = ScrollToOptions\n\ntype ScrollToIndexOptions = ScrollToOptions\n\nexport interface Range {\n startIndex: number\n endIndex: number\n overscan: number\n count: number\n}\n\ntype Key = number | string | bigint\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 const { horizontal, isRtl } = instance.options\n offset = horizontal\n ? element['scrollLeft'] * ((isRtl && -1) || 1)\n : element['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?: boolean\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) => Array<number>\n scrollMargin?: number\n gap?: number\n indexAttribute?: string\n initialMeasurementsCache?: Array<VirtualItem>\n lanes?: number\n isScrollingResetDelay?: number\n enabled?: boolean\n isRtl?: boolean\n}\n\nexport class Virtualizer<\n TScrollElement extends Element | Window,\n TItemElement extends Element,\n> {\n private unsubs: Array<void | (() => void)> = []\n options!: Required<VirtualizerOptions<TScrollElement, TItemElement>>\n scrollElement: TScrollElement | null = null\n targetWindow: (Window & typeof globalThis) | null = null\n isScrolling = false\n private scrollToIndexTimeoutId: number | null = null\n measurementsCache: Array<VirtualItem> = []\n private itemSizeCache = new Map<Key, number>()\n private pendingMeasuredCacheIndexes: Array<number> = []\n scrollRect: Rect | null = null\n scrollOffset: number | null = null\n scrollDirection: ScrollDirection | null = null\n private scrollAdjustments = 0\n shouldAdjustScrollPositionOnItemSizeChange:\n | undefined\n | ((\n item: VirtualItem,\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: () => {\n get()?.disconnect()\n _ro = null\n },\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 isRtl: false,\n ...opts,\n }\n }\n\n private notify = (sync: boolean) => {\n this.options.onChange?.(this, sync)\n }\n\n private maybeNotify = memo(\n () => {\n this.calculateRange()\n\n return [\n this.isScrolling,\n this.range ? this.range.startIndex : null,\n this.range ? this.range.endIndex : null,\n ]\n },\n (isScrolling) => {\n this.notify(isScrolling)\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'maybeNotify',\n debug: () => this.options.debug,\n initialDeps: [\n this.isScrolling,\n this.range ? this.range.startIndex : null,\n this.range ? this.range.endIndex : null,\n ] as [boolean, number | null, number | null],\n },\n )\n\n private cleanup = () => {\n this.unsubs.filter(Boolean).forEach((d) => d!())\n this.unsubs = []\n this.observer.disconnect()\n this.scrollElement = null\n this.targetWindow = null\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.maybeNotify()\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.elementsCache.forEach((cached) => {\n this.observer.observe(cached)\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.maybeNotify()\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 this.isScrolling = isScrolling\n\n this.maybeNotify()\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: Array<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 index = this.indexFromElement(node)\n const item = this.measurementsCache[index]\n if (!item) {\n return\n }\n const key = item.key\n const prevNode = this.elementsCache.get(key)\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(index, this.options.measureElement(node, entry, this))\n }\n }\n\n resizeItem = (index: number, size: number) => {\n const item = this.measurementsCache[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(false)\n }\n }\n\n measureElement = (node: TItemElement | null | undefined) => {\n if (!node) {\n this.elementsCache.forEach((cached, key) => {\n if (!cached.isConnected) {\n this.observer.unobserve(cached)\n this.elementsCache.delete(key)\n }\n })\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: Array<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' && 'getVirtualItems',\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.measurementsCache[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 Math.max(\n end - this.options.scrollMargin + this.options.paddingEnd,\n 0,\n )\n }\n\n private _scrollToOffset = (\n offset: number,\n {\n adjustments,\n behavior,\n }: {\n adjustments: number | undefined\n behavior: ScrollBehavior | undefined\n },\n ) => {\n this.options.scrollToFn(offset, { behavior, adjustments }, this)\n }\n\n measure = () => {\n this.itemSizeCache = new Map()\n this.notify(false)\n }\n}\n\nconst findNearestBinarySearch = (\n low: number,\n high: number,\n getCurrentValue: (i: number) => number,\n value: number,\n) => {\n while (low <= high) {\n const middle = ((low + high) / 2) | 0\n const currentValue = getCurrentValue(middle)\n\n if (currentValue < value) {\n low = middle + 1\n } else if (currentValue > value) {\n high = middle - 1\n } else {\n return middle\n }\n }\n\n if (low > 0) {\n return low - 1\n } else {\n return 0\n }\n}\n\nfunction calculateRange({\n measurements,\n outerSize,\n scrollOffset,\n}: {\n measurements: Array<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, debounce, memo, notUndefined } from './utils'\n\nexport * from './utils'\n\n//\n\ntype ScrollDirection = 'forward' | 'backward'\n\ntype ScrollAlignment = 'start' | 'center' | 'end' | 'auto'\n\ntype ScrollBehavior = 'auto' | 'smooth'\n\nexport interface ScrollToOptions {\n align?: ScrollAlignment\n behavior?: ScrollBehavior\n}\n\ntype ScrollToOffsetOptions = ScrollToOptions\n\ntype ScrollToIndexOptions = ScrollToOptions\n\nexport interface Range {\n startIndex: number\n endIndex: number\n overscan: number\n count: number\n}\n\ntype Key = number | string | bigint\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\ntype ObserveOffsetCallBack = (offset: number, isScrolling: boolean) => void\n\nexport const observeElementOffset = <T extends Element>(\n instance: Virtualizer<T, any>,\n cb: ObserveOffsetCallBack,\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 =\n instance.options.useScrollendEvent && 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 const { horizontal, isRtl } = instance.options\n offset = horizontal\n ? element['scrollLeft'] * ((isRtl && -1) || 1)\n : element['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: ObserveOffsetCallBack,\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 =\n instance.options.useScrollendEvent && 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: ObserveOffsetCallBack,\n ) => void | (() => void)\n // Optional\n debug?: boolean\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) => Array<number>\n scrollMargin?: number\n gap?: number\n indexAttribute?: string\n initialMeasurementsCache?: Array<VirtualItem>\n lanes?: number\n isScrollingResetDelay?: number\n useScrollendEvent?: boolean\n enabled?: boolean\n isRtl?: boolean\n}\n\nexport class Virtualizer<\n TScrollElement extends Element | Window,\n TItemElement extends Element,\n> {\n private unsubs: Array<void | (() => void)> = []\n options!: Required<VirtualizerOptions<TScrollElement, TItemElement>>\n scrollElement: TScrollElement | null = null\n targetWindow: (Window & typeof globalThis) | null = null\n isScrolling = false\n private scrollToIndexTimeoutId: number | null = null\n measurementsCache: Array<VirtualItem> = []\n private itemSizeCache = new Map<Key, number>()\n private pendingMeasuredCacheIndexes: Array<number> = []\n scrollRect: Rect | null = null\n scrollOffset: number | null = null\n scrollDirection: ScrollDirection | null = null\n private scrollAdjustments = 0\n shouldAdjustScrollPositionOnItemSizeChange:\n | undefined\n | ((\n item: VirtualItem,\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: () => {\n get()?.disconnect()\n _ro = null\n },\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 isRtl: false,\n useScrollendEvent: true,\n ...opts,\n }\n }\n\n private notify = (sync: boolean) => {\n this.options.onChange?.(this, sync)\n }\n\n private maybeNotify = memo(\n () => {\n this.calculateRange()\n\n return [\n this.isScrolling,\n this.range ? this.range.startIndex : null,\n this.range ? this.range.endIndex : null,\n ]\n },\n (isScrolling) => {\n this.notify(isScrolling)\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'maybeNotify',\n debug: () => this.options.debug,\n initialDeps: [\n this.isScrolling,\n this.range ? this.range.startIndex : null,\n this.range ? this.range.endIndex : null,\n ] as [boolean, number | null, number | null],\n },\n )\n\n private cleanup = () => {\n this.unsubs.filter(Boolean).forEach((d) => d!())\n this.unsubs = []\n this.observer.disconnect()\n this.scrollElement = null\n this.targetWindow = null\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.maybeNotify()\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.elementsCache.forEach((cached) => {\n this.observer.observe(cached)\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.maybeNotify()\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 this.isScrolling = isScrolling\n\n this.maybeNotify()\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: Array<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 index = this.indexFromElement(node)\n const item = this.measurementsCache[index]\n if (!item) {\n return\n }\n const key = item.key\n const prevNode = this.elementsCache.get(key)\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(index, this.options.measureElement(node, entry, this))\n }\n }\n\n resizeItem = (index: number, size: number) => {\n const item = this.measurementsCache[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(false)\n }\n }\n\n measureElement = (node: TItemElement | null | undefined) => {\n if (!node) {\n this.elementsCache.forEach((cached, key) => {\n if (!cached.isConnected) {\n this.observer.unobserve(cached)\n this.elementsCache.delete(key)\n }\n })\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: Array<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' && 'getVirtualItems',\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 + size) {\n align = 'end'\n }\n }\n\n if (align === 'end') {\n toOffset -= size\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.measurementsCache[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 centerOffset =\n item.start - this.options.scrollPaddingStart + (item.size - size) / 2\n\n switch (align) {\n case 'center':\n return [this.getOffsetForAlignment(centerOffset, align), align] as const\n case 'end':\n return [\n this.getOffsetForAlignment(\n item.end + this.options.scrollPaddingEnd,\n align,\n ),\n align,\n ] as const\n default:\n return [\n this.getOffsetForAlignment(\n item.start - this.options.scrollPaddingStart,\n align,\n ),\n align,\n ] as const\n }\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 Math.max(\n end - this.options.scrollMargin + this.options.paddingEnd,\n 0,\n )\n }\n\n private _scrollToOffset = (\n offset: number,\n {\n adjustments,\n behavior,\n }: {\n adjustments: number | undefined\n behavior: ScrollBehavior | undefined\n },\n ) => {\n this.options.scrollToFn(offset, { behavior, adjustments }, this)\n }\n\n measure = () => {\n this.itemSizeCache = new Map()\n this.notify(false)\n }\n}\n\nconst findNearestBinarySearch = (\n low: number,\n high: number,\n getCurrentValue: (i: number) => number,\n value: number,\n) => {\n while (low <= high) {\n const middle = ((low + high) / 2) | 0\n const currentValue = getCurrentValue(middle)\n\n if (currentValue < value) {\n low = middle + 1\n } else if (currentValue > value) {\n high = middle - 1\n } else {\n return middle\n }\n }\n\n if (low > 0) {\n return low - 1\n } else {\n return 0\n }\n}\n\nfunction calculateRange({\n measurements,\n outerSize,\n scrollOffset,\n}: {\n measurements: Array<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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"}
@@ -31,8 +31,9 @@ export declare const defaultKeyExtractor: (index: number) => number;
31
31
  export declare const defaultRangeExtractor: (range: Range) => number[];
32
32
  export declare const observeElementRect: <T extends Element>(instance: Virtualizer<T, any>, cb: (rect: Rect) => void) => (() => void) | undefined;
33
33
  export declare const observeWindowRect: (instance: Virtualizer<Window, any>, cb: (rect: Rect) => void) => (() => void) | undefined;
34
- export declare const observeElementOffset: <T extends Element>(instance: Virtualizer<T, any>, cb: (offset: number, isScrolling: boolean) => void) => (() => void) | undefined;
35
- export declare const observeWindowOffset: (instance: Virtualizer<Window, any>, cb: (offset: number, isScrolling: boolean) => void) => (() => void) | undefined;
34
+ type ObserveOffsetCallBack = (offset: number, isScrolling: boolean) => void;
35
+ export declare const observeElementOffset: <T extends Element>(instance: Virtualizer<T, any>, cb: ObserveOffsetCallBack) => (() => void) | undefined;
36
+ export declare const observeWindowOffset: (instance: Virtualizer<Window, any>, cb: ObserveOffsetCallBack) => (() => void) | undefined;
36
37
  export declare const measureElement: <TItemElement extends Element>(element: TItemElement, entry: ResizeObserverEntry | undefined, instance: Virtualizer<any, TItemElement>) => number;
37
38
  export declare const windowScroll: <T extends Window>(offset: number, { adjustments, behavior, }: {
38
39
  adjustments?: number | undefined;
@@ -51,7 +52,7 @@ export interface VirtualizerOptions<TScrollElement extends Element | Window, TIt
51
52
  behavior?: ScrollBehavior;
52
53
  }, instance: Virtualizer<TScrollElement, TItemElement>) => void;
53
54
  observeElementRect: (instance: Virtualizer<TScrollElement, TItemElement>, cb: (rect: Rect) => void) => void | (() => void);
54
- observeElementOffset: (instance: Virtualizer<TScrollElement, TItemElement>, cb: (offset: number, isScrolling: boolean) => void) => void | (() => void);
55
+ observeElementOffset: (instance: Virtualizer<TScrollElement, TItemElement>, cb: ObserveOffsetCallBack) => void | (() => void);
55
56
  debug?: boolean;
56
57
  initialRect?: Rect;
57
58
  onChange?: (instance: Virtualizer<TScrollElement, TItemElement>, sync: boolean) => void;
@@ -71,6 +72,7 @@ export interface VirtualizerOptions<TScrollElement extends Element | Window, TIt
71
72
  initialMeasurementsCache?: Array<VirtualItem>;
72
73
  lanes?: number;
73
74
  isScrollingResetDelay?: number;
75
+ useScrollendEvent?: boolean;
74
76
  enabled?: boolean;
75
77
  isRtl?: boolean;
76
78
  }
@@ -119,7 +121,7 @@ export declare class Virtualizer<TScrollElement extends Element | Window, TItemE
119
121
  getVirtualItems: () => VirtualItem[];
120
122
  getVirtualItemForOffset: (offset: number) => VirtualItem | undefined;
121
123
  getOffsetForAlignment: (toOffset: number, align: ScrollAlignment) => number;
122
- getOffsetForIndex: (index: number, align?: ScrollAlignment) => readonly [number, "auto"] | readonly [number, "start" | "center" | "end"] | undefined;
124
+ getOffsetForIndex: (index: number, align?: ScrollAlignment) => readonly [number, "auto"] | readonly [number, "center"] | readonly [number, "end"] | readonly [number, "start"] | undefined;
123
125
  private isDynamicMode;
124
126
  private cancelScrollToIndex;
125
127
  scrollToOffset: (toOffset: number, { align, behavior }?: ScrollToOffsetOptions) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"utils.cjs","sources":["../../src/utils.ts"],"sourcesContent":["export type NoInfer<A extends any> = [A][A extends any ? 0 : never]\n\nexport type PartialKeys<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>\n\nexport function memo<TDeps extends ReadonlyArray<any>, TResult>(\n getDeps: () => [...TDeps],\n fn: (...args: NoInfer<[...TDeps]>) => TResult,\n opts: {\n key: false | string\n debug?: () => boolean\n onChange?: (result: TResult) => void\n initialDeps?: TDeps\n },\n) {\n let deps = opts.initialDeps ?? []\n let result: TResult | undefined\n\n return (): TResult => {\n let depTime: number\n if (opts.key && opts.debug?.()) depTime = Date.now()\n\n const newDeps = getDeps()\n\n const depsChanged =\n newDeps.length !== deps.length ||\n newDeps.some((dep: any, index: number) => deps[index] !== dep)\n\n if (!depsChanged) {\n return result!\n }\n\n deps = newDeps\n\n let resultTime: number\n if (opts.key && opts.debug?.()) resultTime = Date.now()\n\n result = fn(...newDeps)\n\n if (opts.key && opts.debug?.()) {\n const depEndTime = Math.round((Date.now() - depTime!) * 100) / 100\n const resultEndTime = Math.round((Date.now() - resultTime!) * 100) / 100\n const resultFpsPercentage = resultEndTime / 16\n\n const pad = (str: number | string, num: number) => {\n str = String(str)\n while (str.length < num) {\n str = ' ' + str\n }\n return str\n }\n\n console.info(\n `%c⏱ ${pad(resultEndTime, 5)} /${pad(depEndTime, 5)} ms`,\n `\n font-size: .6rem;\n font-weight: bold;\n color: hsl(${Math.max(\n 0,\n Math.min(120 - 120 * resultFpsPercentage, 120),\n )}deg 100% 31%);`,\n opts?.key,\n )\n }\n\n opts?.onChange?.(result)\n\n return result\n }\n}\n\nexport function notUndefined<T>(value: T | undefined, msg?: string): T {\n if (value === undefined) {\n throw new Error(`Unexpected undefined${msg ? `: ${msg}` : ''}`)\n } else {\n return value\n }\n}\n\nexport const approxEqual = (a: number, b: number) => Math.abs(a - b) < 1\n\nexport const debounce = (\n targetWindow: Window & typeof globalThis,\n fn: Function,\n ms: number,\n) => {\n let timeoutId: number\n return function (this: any, ...args: Array<any>) {\n targetWindow.clearTimeout(timeoutId)\n timeoutId = targetWindow.setTimeout(() => fn.apply(this, args), ms)\n }\n}\n"],"names":[],"mappings":";;AAIgB,SAAA,KACd,SACA,IACA,MAMA;AACI,MAAA,OAAO,KAAK,eAAe;AAC3B,MAAA;AAEJ,SAAO,MAAe;;AAChB,QAAA;AACJ,QAAI,KAAK,SAAO,UAAK,UAAL,+BAAgB,WAAU,KAAK;AAE/C,UAAM,UAAU;AAEhB,UAAM,cACJ,QAAQ,WAAW,KAAK,UACxB,QAAQ,KAAK,CAAC,KAAU,UAAkB,KAAK,KAAK,MAAM,GAAG;AAE/D,QAAI,CAAC,aAAa;AACT,aAAA;AAAA,IACT;AAEO,WAAA;AAEH,QAAA;AACJ,QAAI,KAAK,SAAO,UAAK,UAAL,+BAAgB,cAAa,KAAK;AAEzC,aAAA,GAAG,GAAG,OAAO;AAEtB,QAAI,KAAK,SAAO,UAAK,UAAL,gCAAgB;AACxB,YAAA,aAAa,KAAK,OAAO,KAAK,QAAQ,WAAY,GAAG,IAAI;AACzD,YAAA,gBAAgB,KAAK,OAAO,KAAK,QAAQ,cAAe,GAAG,IAAI;AACrE,YAAM,sBAAsB,gBAAgB;AAEtC,YAAA,MAAM,CAAC,KAAsB,QAAgB;AACjD,cAAM,OAAO,GAAG;AACT,eAAA,IAAI,SAAS,KAAK;AACvB,gBAAM,MAAM;AAAA,QACd;AACO,eAAA;AAAA,MAAA;AAGD,cAAA;AAAA,QACN,OAAO,IAAI,eAAe,CAAC,CAAC,KAAK,IAAI,YAAY,CAAC,CAAC;AAAA,QACnD;AAAA;AAAA;AAAA,yBAGiB,KAAK;AAAA,UAChB;AAAA,UACA,KAAK,IAAI,MAAM,MAAM,qBAAqB,GAAG;AAAA,QAC9C,CAAA;AAAA,QACL,6BAAM;AAAA,MAAA;AAAA,IAEV;AAEA,uCAAM,aAAN,8BAAiB;AAEV,WAAA;AAAA,EAAA;AAEX;AAEgB,SAAA,aAAgB,OAAsB,KAAiB;AACrE,MAAI,UAAU,QAAW;AACjB,UAAA,IAAI,MAAM,uBAAuB,MAAM,KAAK,GAAG,KAAK,EAAE,EAAE;AAAA,EAAA,OACzD;AACE,WAAA;AAAA,EACT;AACF;AAEa,MAAA,cAAc,CAAC,GAAW,MAAc,KAAK,IAAI,IAAI,CAAC,IAAI;AAEhE,MAAM,WAAW,CACtB,cACA,IACA,OACG;AACC,MAAA;AACJ,SAAO,YAAwB,MAAkB;AAC/C,iBAAa,aAAa,SAAS;AACvB,gBAAA,aAAa,WAAW,MAAM,GAAG,MAAM,MAAM,IAAI,GAAG,EAAE;AAAA,EAAA;AAEtE;;;;;"}
1
+ {"version":3,"file":"utils.cjs","sources":["../../src/utils.ts"],"sourcesContent":["export type NoInfer<A extends any> = [A][A extends any ? 0 : never]\n\nexport type PartialKeys<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>\n\nexport function memo<TDeps extends ReadonlyArray<any>, TResult>(\n getDeps: () => [...TDeps],\n fn: (...args: NoInfer<[...TDeps]>) => TResult,\n opts: {\n key: false | string\n debug?: () => boolean\n onChange?: (result: TResult) => void\n initialDeps?: TDeps\n },\n) {\n let deps = opts.initialDeps ?? []\n let result: TResult | undefined\n\n return (): TResult => {\n let depTime: number\n if (opts.key && opts.debug?.()) depTime = Date.now()\n\n const newDeps = getDeps()\n\n const depsChanged =\n newDeps.length !== deps.length ||\n newDeps.some((dep: any, index: number) => deps[index] !== dep)\n\n if (!depsChanged) {\n return result!\n }\n\n deps = newDeps\n\n let resultTime: number\n if (opts.key && opts.debug?.()) resultTime = Date.now()\n\n result = fn(...newDeps)\n\n if (opts.key && opts.debug?.()) {\n const depEndTime = Math.round((Date.now() - depTime!) * 100) / 100\n const resultEndTime = Math.round((Date.now() - resultTime!) * 100) / 100\n const resultFpsPercentage = resultEndTime / 16\n\n const pad = (str: number | string, num: number) => {\n str = String(str)\n while (str.length < num) {\n str = ' ' + str\n }\n return str\n }\n\n console.info(\n `%c⏱ ${pad(resultEndTime, 5)} /${pad(depEndTime, 5)} ms`,\n `\n font-size: .6rem;\n font-weight: bold;\n color: hsl(${Math.max(\n 0,\n Math.min(120 - 120 * resultFpsPercentage, 120),\n )}deg 100% 31%);`,\n opts?.key,\n )\n }\n\n opts?.onChange?.(result)\n\n return result\n }\n}\n\nexport function notUndefined<T>(value: T | undefined, msg?: string): T {\n if (value === undefined) {\n throw new Error(`Unexpected undefined${msg ? `: ${msg}` : ''}`)\n } else {\n return value\n }\n}\n\nexport const approxEqual = (a: number, b: number) => Math.abs(a - b) < 1\n\nexport const debounce = (\n targetWindow: Window & typeof globalThis,\n fn: Function,\n ms: number,\n) => {\n let timeoutId: number\n return function (this: any, ...args: Array<any>) {\n targetWindow.clearTimeout(timeoutId)\n timeoutId = targetWindow.setTimeout(() => fn.apply(this, args), ms)\n }\n}\n"],"names":[],"mappings":";;AAIgB,SAAA,KACd,SACA,IACA,MAMA;AACI,MAAA,OAAO,KAAK,eAAe,CAAC;AAC5B,MAAA;AAEJ,SAAO,MAAe;;AAChB,QAAA;AACJ,QAAI,KAAK,SAAO,UAAK,UAAL,+BAAgB,WAAU,KAAK,IAAI;AAEnD,UAAM,UAAU,QAAQ;AAExB,UAAM,cACJ,QAAQ,WAAW,KAAK,UACxB,QAAQ,KAAK,CAAC,KAAU,UAAkB,KAAK,KAAK,MAAM,GAAG;AAE/D,QAAI,CAAC,aAAa;AACT,aAAA;AAAA,IAAA;AAGF,WAAA;AAEH,QAAA;AACJ,QAAI,KAAK,SAAO,UAAK,UAAL,+BAAgB,cAAa,KAAK,IAAI;AAE7C,aAAA,GAAG,GAAG,OAAO;AAEtB,QAAI,KAAK,SAAO,UAAK,UAAL,gCAAgB;AACxB,YAAA,aAAa,KAAK,OAAO,KAAK,QAAQ,WAAY,GAAG,IAAI;AACzD,YAAA,gBAAgB,KAAK,OAAO,KAAK,QAAQ,cAAe,GAAG,IAAI;AACrE,YAAM,sBAAsB,gBAAgB;AAEtC,YAAA,MAAM,CAAC,KAAsB,QAAgB;AACjD,cAAM,OAAO,GAAG;AACT,eAAA,IAAI,SAAS,KAAK;AACvB,gBAAM,MAAM;AAAA,QAAA;AAEP,eAAA;AAAA,MACT;AAEQ,cAAA;AAAA,QACN,OAAO,IAAI,eAAe,CAAC,CAAC,KAAK,IAAI,YAAY,CAAC,CAAC;AAAA,QACnD;AAAA;AAAA;AAAA,yBAGiB,KAAK;AAAA,UAChB;AAAA,UACA,KAAK,IAAI,MAAM,MAAM,qBAAqB,GAAG;AAAA,QAC9C,CAAA;AAAA,QACL,6BAAM;AAAA,MACR;AAAA,IAAA;AAGF,uCAAM,aAAN,8BAAiB;AAEV,WAAA;AAAA,EACT;AACF;AAEgB,SAAA,aAAgB,OAAsB,KAAiB;AACrE,MAAI,UAAU,QAAW;AACjB,UAAA,IAAI,MAAM,uBAAuB,MAAM,KAAK,GAAG,KAAK,EAAE,EAAE;AAAA,EAAA,OACzD;AACE,WAAA;AAAA,EAAA;AAEX;AAEa,MAAA,cAAc,CAAC,GAAW,MAAc,KAAK,IAAI,IAAI,CAAC,IAAI;AAEhE,MAAM,WAAW,CACtB,cACA,IACA,OACG;AACC,MAAA;AACJ,SAAO,YAAwB,MAAkB;AAC/C,iBAAa,aAAa,SAAS;AACvB,gBAAA,aAAa,WAAW,MAAM,GAAG,MAAM,MAAM,IAAI,GAAG,EAAE;AAAA,EACpE;AACF;;;;;"}
@@ -31,8 +31,9 @@ export declare const defaultKeyExtractor: (index: number) => number;
31
31
  export declare const defaultRangeExtractor: (range: Range) => number[];
32
32
  export declare const observeElementRect: <T extends Element>(instance: Virtualizer<T, any>, cb: (rect: Rect) => void) => (() => void) | undefined;
33
33
  export declare const observeWindowRect: (instance: Virtualizer<Window, any>, cb: (rect: Rect) => void) => (() => void) | undefined;
34
- export declare const observeElementOffset: <T extends Element>(instance: Virtualizer<T, any>, cb: (offset: number, isScrolling: boolean) => void) => (() => void) | undefined;
35
- export declare const observeWindowOffset: (instance: Virtualizer<Window, any>, cb: (offset: number, isScrolling: boolean) => void) => (() => void) | undefined;
34
+ type ObserveOffsetCallBack = (offset: number, isScrolling: boolean) => void;
35
+ export declare const observeElementOffset: <T extends Element>(instance: Virtualizer<T, any>, cb: ObserveOffsetCallBack) => (() => void) | undefined;
36
+ export declare const observeWindowOffset: (instance: Virtualizer<Window, any>, cb: ObserveOffsetCallBack) => (() => void) | undefined;
36
37
  export declare const measureElement: <TItemElement extends Element>(element: TItemElement, entry: ResizeObserverEntry | undefined, instance: Virtualizer<any, TItemElement>) => number;
37
38
  export declare const windowScroll: <T extends Window>(offset: number, { adjustments, behavior, }: {
38
39
  adjustments?: number | undefined;
@@ -51,7 +52,7 @@ export interface VirtualizerOptions<TScrollElement extends Element | Window, TIt
51
52
  behavior?: ScrollBehavior;
52
53
  }, instance: Virtualizer<TScrollElement, TItemElement>) => void;
53
54
  observeElementRect: (instance: Virtualizer<TScrollElement, TItemElement>, cb: (rect: Rect) => void) => void | (() => void);
54
- observeElementOffset: (instance: Virtualizer<TScrollElement, TItemElement>, cb: (offset: number, isScrolling: boolean) => void) => void | (() => void);
55
+ observeElementOffset: (instance: Virtualizer<TScrollElement, TItemElement>, cb: ObserveOffsetCallBack) => void | (() => void);
55
56
  debug?: boolean;
56
57
  initialRect?: Rect;
57
58
  onChange?: (instance: Virtualizer<TScrollElement, TItemElement>, sync: boolean) => void;
@@ -71,6 +72,7 @@ export interface VirtualizerOptions<TScrollElement extends Element | Window, TIt
71
72
  initialMeasurementsCache?: Array<VirtualItem>;
72
73
  lanes?: number;
73
74
  isScrollingResetDelay?: number;
75
+ useScrollendEvent?: boolean;
74
76
  enabled?: boolean;
75
77
  isRtl?: boolean;
76
78
  }
@@ -119,7 +121,7 @@ export declare class Virtualizer<TScrollElement extends Element | Window, TItemE
119
121
  getVirtualItems: () => VirtualItem[];
120
122
  getVirtualItemForOffset: (offset: number) => VirtualItem | undefined;
121
123
  getOffsetForAlignment: (toOffset: number, align: ScrollAlignment) => number;
122
- getOffsetForIndex: (index: number, align?: ScrollAlignment) => readonly [number, "auto"] | readonly [number, "start" | "center" | "end"] | undefined;
124
+ getOffsetForIndex: (index: number, align?: ScrollAlignment) => readonly [number, "auto"] | readonly [number, "center"] | readonly [number, "end"] | readonly [number, "start"] | undefined;
123
125
  private isDynamicMode;
124
126
  private cancelScrollToIndex;
125
127
  scrollToOffset: (toOffset: number, { align, behavior }?: ScrollToOffsetOptions) => void;
package/dist/esm/index.js CHANGED
@@ -71,7 +71,7 @@ const observeElementOffset = (instance, cb) => {
71
71
  return;
72
72
  }
73
73
  let offset = 0;
74
- const fallback = supportsScrollend ? () => void 0 : debounce(
74
+ const fallback = instance.options.useScrollendEvent && supportsScrollend ? () => void 0 : debounce(
75
75
  targetWindow,
76
76
  () => {
77
77
  cb(offset, false);
@@ -104,7 +104,7 @@ const observeWindowOffset = (instance, cb) => {
104
104
  return;
105
105
  }
106
106
  let offset = 0;
107
- const fallback = supportsScrollend ? () => void 0 : debounce(
107
+ const fallback = instance.options.useScrollendEvent && supportsScrollend ? () => void 0 : debounce(
108
108
  targetWindow,
109
109
  () => {
110
110
  cb(offset, false);
@@ -236,6 +236,7 @@ class Virtualizer {
236
236
  isScrollingResetDelay: 150,
237
237
  enabled: true,
238
238
  isRtl: false,
239
+ useScrollendEvent: true,
239
240
  ...opts2
240
241
  };
241
242
  };
@@ -555,20 +556,12 @@ class Virtualizer {
555
556
  const size = this.getSize();
556
557
  const scrollOffset = this.getScrollOffset();
557
558
  if (align === "auto") {
558
- if (toOffset <= scrollOffset) {
559
- align = "start";
560
- } else if (toOffset >= scrollOffset + size) {
559
+ if (toOffset >= scrollOffset + size) {
561
560
  align = "end";
562
- } else {
563
- align = "start";
564
561
  }
565
562
  }
566
- if (align === "start") {
567
- toOffset = toOffset;
568
- } else if (align === "end") {
569
- toOffset = toOffset - size;
570
- } else if (align === "center") {
571
- toOffset = toOffset - size / 2;
563
+ if (align === "end") {
564
+ toOffset -= size;
572
565
  }
573
566
  const scrollSizeProp = this.options.horizontal ? "scrollWidth" : "scrollHeight";
574
567
  const scrollSize = this.scrollElement ? "document" in this.scrollElement ? this.scrollElement.document.documentElement[scrollSizeProp] : this.scrollElement[scrollSizeProp] : 0;
@@ -592,8 +585,27 @@ class Virtualizer {
592
585
  return [scrollOffset, align];
593
586
  }
594
587
  }
595
- const toOffset = align === "end" ? item.end + this.options.scrollPaddingEnd : item.start - this.options.scrollPaddingStart;
596
- return [this.getOffsetForAlignment(toOffset, align), align];
588
+ const centerOffset = item.start - this.options.scrollPaddingStart + (item.size - size) / 2;
589
+ switch (align) {
590
+ case "center":
591
+ return [this.getOffsetForAlignment(centerOffset, align), align];
592
+ case "end":
593
+ return [
594
+ this.getOffsetForAlignment(
595
+ item.end + this.options.scrollPaddingEnd,
596
+ align
597
+ ),
598
+ align
599
+ ];
600
+ default:
601
+ return [
602
+ this.getOffsetForAlignment(
603
+ item.start - this.options.scrollPaddingStart,
604
+ align
605
+ ),
606
+ align
607
+ ];
608
+ }
597
609
  };
598
610
  this.isDynamicMode = () => this.elementsCache.size > 0;
599
611
  this.cancelScrollToIndex = () => {
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../src/index.ts"],"sourcesContent":["import { approxEqual, debounce, memo, notUndefined } from './utils'\n\nexport * from './utils'\n\n//\n\ntype ScrollDirection = 'forward' | 'backward'\n\ntype ScrollAlignment = 'start' | 'center' | 'end' | 'auto'\n\ntype ScrollBehavior = 'auto' | 'smooth'\n\nexport interface ScrollToOptions {\n align?: ScrollAlignment\n behavior?: ScrollBehavior\n}\n\ntype ScrollToOffsetOptions = ScrollToOptions\n\ntype ScrollToIndexOptions = ScrollToOptions\n\nexport interface Range {\n startIndex: number\n endIndex: number\n overscan: number\n count: number\n}\n\ntype Key = number | string | bigint\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 const { horizontal, isRtl } = instance.options\n offset = horizontal\n ? element['scrollLeft'] * ((isRtl && -1) || 1)\n : element['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?: boolean\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) => Array<number>\n scrollMargin?: number\n gap?: number\n indexAttribute?: string\n initialMeasurementsCache?: Array<VirtualItem>\n lanes?: number\n isScrollingResetDelay?: number\n enabled?: boolean\n isRtl?: boolean\n}\n\nexport class Virtualizer<\n TScrollElement extends Element | Window,\n TItemElement extends Element,\n> {\n private unsubs: Array<void | (() => void)> = []\n options!: Required<VirtualizerOptions<TScrollElement, TItemElement>>\n scrollElement: TScrollElement | null = null\n targetWindow: (Window & typeof globalThis) | null = null\n isScrolling = false\n private scrollToIndexTimeoutId: number | null = null\n measurementsCache: Array<VirtualItem> = []\n private itemSizeCache = new Map<Key, number>()\n private pendingMeasuredCacheIndexes: Array<number> = []\n scrollRect: Rect | null = null\n scrollOffset: number | null = null\n scrollDirection: ScrollDirection | null = null\n private scrollAdjustments = 0\n shouldAdjustScrollPositionOnItemSizeChange:\n | undefined\n | ((\n item: VirtualItem,\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: () => {\n get()?.disconnect()\n _ro = null\n },\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 isRtl: false,\n ...opts,\n }\n }\n\n private notify = (sync: boolean) => {\n this.options.onChange?.(this, sync)\n }\n\n private maybeNotify = memo(\n () => {\n this.calculateRange()\n\n return [\n this.isScrolling,\n this.range ? this.range.startIndex : null,\n this.range ? this.range.endIndex : null,\n ]\n },\n (isScrolling) => {\n this.notify(isScrolling)\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'maybeNotify',\n debug: () => this.options.debug,\n initialDeps: [\n this.isScrolling,\n this.range ? this.range.startIndex : null,\n this.range ? this.range.endIndex : null,\n ] as [boolean, number | null, number | null],\n },\n )\n\n private cleanup = () => {\n this.unsubs.filter(Boolean).forEach((d) => d!())\n this.unsubs = []\n this.observer.disconnect()\n this.scrollElement = null\n this.targetWindow = null\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.maybeNotify()\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.elementsCache.forEach((cached) => {\n this.observer.observe(cached)\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.maybeNotify()\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 this.isScrolling = isScrolling\n\n this.maybeNotify()\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: Array<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 index = this.indexFromElement(node)\n const item = this.measurementsCache[index]\n if (!item) {\n return\n }\n const key = item.key\n const prevNode = this.elementsCache.get(key)\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(index, this.options.measureElement(node, entry, this))\n }\n }\n\n resizeItem = (index: number, size: number) => {\n const item = this.measurementsCache[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(false)\n }\n }\n\n measureElement = (node: TItemElement | null | undefined) => {\n if (!node) {\n this.elementsCache.forEach((cached, key) => {\n if (!cached.isConnected) {\n this.observer.unobserve(cached)\n this.elementsCache.delete(key)\n }\n })\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: Array<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' && 'getVirtualItems',\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.measurementsCache[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 Math.max(\n end - this.options.scrollMargin + this.options.paddingEnd,\n 0,\n )\n }\n\n private _scrollToOffset = (\n offset: number,\n {\n adjustments,\n behavior,\n }: {\n adjustments: number | undefined\n behavior: ScrollBehavior | undefined\n },\n ) => {\n this.options.scrollToFn(offset, { behavior, adjustments }, this)\n }\n\n measure = () => {\n this.itemSizeCache = new Map()\n this.notify(false)\n }\n}\n\nconst findNearestBinarySearch = (\n low: number,\n high: number,\n getCurrentValue: (i: number) => number,\n value: number,\n) => {\n while (low <= high) {\n const middle = ((low + high) / 2) | 0\n const currentValue = getCurrentValue(middle)\n\n if (currentValue < value) {\n low = middle + 1\n } else if (currentValue > value) {\n high = middle - 1\n } else {\n return middle\n }\n }\n\n if (low > 0) {\n return low - 1\n } else {\n return 0\n }\n}\n\nfunction calculateRange({\n measurements,\n outerSize,\n scrollOffset,\n}: {\n measurements: Array<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, debounce, memo, notUndefined } from './utils'\n\nexport * from './utils'\n\n//\n\ntype ScrollDirection = 'forward' | 'backward'\n\ntype ScrollAlignment = 'start' | 'center' | 'end' | 'auto'\n\ntype ScrollBehavior = 'auto' | 'smooth'\n\nexport interface ScrollToOptions {\n align?: ScrollAlignment\n behavior?: ScrollBehavior\n}\n\ntype ScrollToOffsetOptions = ScrollToOptions\n\ntype ScrollToIndexOptions = ScrollToOptions\n\nexport interface Range {\n startIndex: number\n endIndex: number\n overscan: number\n count: number\n}\n\ntype Key = number | string | bigint\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\ntype ObserveOffsetCallBack = (offset: number, isScrolling: boolean) => void\n\nexport const observeElementOffset = <T extends Element>(\n instance: Virtualizer<T, any>,\n cb: ObserveOffsetCallBack,\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 =\n instance.options.useScrollendEvent && 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 const { horizontal, isRtl } = instance.options\n offset = horizontal\n ? element['scrollLeft'] * ((isRtl && -1) || 1)\n : element['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: ObserveOffsetCallBack,\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 =\n instance.options.useScrollendEvent && 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: ObserveOffsetCallBack,\n ) => void | (() => void)\n // Optional\n debug?: boolean\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) => Array<number>\n scrollMargin?: number\n gap?: number\n indexAttribute?: string\n initialMeasurementsCache?: Array<VirtualItem>\n lanes?: number\n isScrollingResetDelay?: number\n useScrollendEvent?: boolean\n enabled?: boolean\n isRtl?: boolean\n}\n\nexport class Virtualizer<\n TScrollElement extends Element | Window,\n TItemElement extends Element,\n> {\n private unsubs: Array<void | (() => void)> = []\n options!: Required<VirtualizerOptions<TScrollElement, TItemElement>>\n scrollElement: TScrollElement | null = null\n targetWindow: (Window & typeof globalThis) | null = null\n isScrolling = false\n private scrollToIndexTimeoutId: number | null = null\n measurementsCache: Array<VirtualItem> = []\n private itemSizeCache = new Map<Key, number>()\n private pendingMeasuredCacheIndexes: Array<number> = []\n scrollRect: Rect | null = null\n scrollOffset: number | null = null\n scrollDirection: ScrollDirection | null = null\n private scrollAdjustments = 0\n shouldAdjustScrollPositionOnItemSizeChange:\n | undefined\n | ((\n item: VirtualItem,\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: () => {\n get()?.disconnect()\n _ro = null\n },\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 isRtl: false,\n useScrollendEvent: true,\n ...opts,\n }\n }\n\n private notify = (sync: boolean) => {\n this.options.onChange?.(this, sync)\n }\n\n private maybeNotify = memo(\n () => {\n this.calculateRange()\n\n return [\n this.isScrolling,\n this.range ? this.range.startIndex : null,\n this.range ? this.range.endIndex : null,\n ]\n },\n (isScrolling) => {\n this.notify(isScrolling)\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'maybeNotify',\n debug: () => this.options.debug,\n initialDeps: [\n this.isScrolling,\n this.range ? this.range.startIndex : null,\n this.range ? this.range.endIndex : null,\n ] as [boolean, number | null, number | null],\n },\n )\n\n private cleanup = () => {\n this.unsubs.filter(Boolean).forEach((d) => d!())\n this.unsubs = []\n this.observer.disconnect()\n this.scrollElement = null\n this.targetWindow = null\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.maybeNotify()\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.elementsCache.forEach((cached) => {\n this.observer.observe(cached)\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.maybeNotify()\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 this.isScrolling = isScrolling\n\n this.maybeNotify()\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: Array<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 index = this.indexFromElement(node)\n const item = this.measurementsCache[index]\n if (!item) {\n return\n }\n const key = item.key\n const prevNode = this.elementsCache.get(key)\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(index, this.options.measureElement(node, entry, this))\n }\n }\n\n resizeItem = (index: number, size: number) => {\n const item = this.measurementsCache[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(false)\n }\n }\n\n measureElement = (node: TItemElement | null | undefined) => {\n if (!node) {\n this.elementsCache.forEach((cached, key) => {\n if (!cached.isConnected) {\n this.observer.unobserve(cached)\n this.elementsCache.delete(key)\n }\n })\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: Array<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' && 'getVirtualItems',\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 + size) {\n align = 'end'\n }\n }\n\n if (align === 'end') {\n toOffset -= size\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.measurementsCache[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 centerOffset =\n item.start - this.options.scrollPaddingStart + (item.size - size) / 2\n\n switch (align) {\n case 'center':\n return [this.getOffsetForAlignment(centerOffset, align), align] as const\n case 'end':\n return [\n this.getOffsetForAlignment(\n item.end + this.options.scrollPaddingEnd,\n align,\n ),\n align,\n ] as const\n default:\n return [\n this.getOffsetForAlignment(\n item.start - this.options.scrollPaddingStart,\n align,\n ),\n align,\n ] as const\n }\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 Math.max(\n end - this.options.scrollMargin + this.options.paddingEnd,\n 0,\n )\n }\n\n private _scrollToOffset = (\n offset: number,\n {\n adjustments,\n behavior,\n }: {\n adjustments: number | undefined\n behavior: ScrollBehavior | undefined\n },\n ) => {\n this.options.scrollToFn(offset, { behavior, adjustments }, this)\n }\n\n measure = () => {\n this.itemSizeCache = new Map()\n this.notify(false)\n }\n}\n\nconst findNearestBinarySearch = (\n low: number,\n high: number,\n getCurrentValue: (i: number) => number,\n value: number,\n) => {\n while (low <= high) {\n const middle = ((low + high) / 2) | 0\n const currentValue = getCurrentValue(middle)\n\n if (currentValue < value) {\n low = middle + 1\n } else if (currentValue > value) {\n high = middle - 1\n } else {\n return middle\n }\n }\n\n if (low > 0) {\n return low - 1\n } else {\n return 0\n }\n}\n\nfunction calculateRange({\n measurements,\n outerSize,\n scrollOffset,\n}: {\n measurements: Array<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 +1 @@
1
- {"version":3,"file":"utils.js","sources":["../../src/utils.ts"],"sourcesContent":["export type NoInfer<A extends any> = [A][A extends any ? 0 : never]\n\nexport type PartialKeys<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>\n\nexport function memo<TDeps extends ReadonlyArray<any>, TResult>(\n getDeps: () => [...TDeps],\n fn: (...args: NoInfer<[...TDeps]>) => TResult,\n opts: {\n key: false | string\n debug?: () => boolean\n onChange?: (result: TResult) => void\n initialDeps?: TDeps\n },\n) {\n let deps = opts.initialDeps ?? []\n let result: TResult | undefined\n\n return (): TResult => {\n let depTime: number\n if (opts.key && opts.debug?.()) depTime = Date.now()\n\n const newDeps = getDeps()\n\n const depsChanged =\n newDeps.length !== deps.length ||\n newDeps.some((dep: any, index: number) => deps[index] !== dep)\n\n if (!depsChanged) {\n return result!\n }\n\n deps = newDeps\n\n let resultTime: number\n if (opts.key && opts.debug?.()) resultTime = Date.now()\n\n result = fn(...newDeps)\n\n if (opts.key && opts.debug?.()) {\n const depEndTime = Math.round((Date.now() - depTime!) * 100) / 100\n const resultEndTime = Math.round((Date.now() - resultTime!) * 100) / 100\n const resultFpsPercentage = resultEndTime / 16\n\n const pad = (str: number | string, num: number) => {\n str = String(str)\n while (str.length < num) {\n str = ' ' + str\n }\n return str\n }\n\n console.info(\n `%c⏱ ${pad(resultEndTime, 5)} /${pad(depEndTime, 5)} ms`,\n `\n font-size: .6rem;\n font-weight: bold;\n color: hsl(${Math.max(\n 0,\n Math.min(120 - 120 * resultFpsPercentage, 120),\n )}deg 100% 31%);`,\n opts?.key,\n )\n }\n\n opts?.onChange?.(result)\n\n return result\n }\n}\n\nexport function notUndefined<T>(value: T | undefined, msg?: string): T {\n if (value === undefined) {\n throw new Error(`Unexpected undefined${msg ? `: ${msg}` : ''}`)\n } else {\n return value\n }\n}\n\nexport const approxEqual = (a: number, b: number) => Math.abs(a - b) < 1\n\nexport const debounce = (\n targetWindow: Window & typeof globalThis,\n fn: Function,\n ms: number,\n) => {\n let timeoutId: number\n return function (this: any, ...args: Array<any>) {\n targetWindow.clearTimeout(timeoutId)\n timeoutId = targetWindow.setTimeout(() => fn.apply(this, args), ms)\n }\n}\n"],"names":[],"mappings":"AAIgB,SAAA,KACd,SACA,IACA,MAMA;AACI,MAAA,OAAO,KAAK,eAAe;AAC3B,MAAA;AAEJ,SAAO,MAAe;AAbR;AAcR,QAAA;AACJ,QAAI,KAAK,SAAO,UAAK,UAAL,+BAAgB,WAAU,KAAK;AAE/C,UAAM,UAAU;AAEhB,UAAM,cACJ,QAAQ,WAAW,KAAK,UACxB,QAAQ,KAAK,CAAC,KAAU,UAAkB,KAAK,KAAK,MAAM,GAAG;AAE/D,QAAI,CAAC,aAAa;AACT,aAAA;AAAA,IACT;AAEO,WAAA;AAEH,QAAA;AACJ,QAAI,KAAK,SAAO,UAAK,UAAL,+BAAgB,cAAa,KAAK;AAEzC,aAAA,GAAG,GAAG,OAAO;AAEtB,QAAI,KAAK,SAAO,UAAK,UAAL,gCAAgB;AACxB,YAAA,aAAa,KAAK,OAAO,KAAK,QAAQ,WAAY,GAAG,IAAI;AACzD,YAAA,gBAAgB,KAAK,OAAO,KAAK,QAAQ,cAAe,GAAG,IAAI;AACrE,YAAM,sBAAsB,gBAAgB;AAEtC,YAAA,MAAM,CAAC,KAAsB,QAAgB;AACjD,cAAM,OAAO,GAAG;AACT,eAAA,IAAI,SAAS,KAAK;AACvB,gBAAM,MAAM;AAAA,QACd;AACO,eAAA;AAAA,MAAA;AAGD,cAAA;AAAA,QACN,OAAO,IAAI,eAAe,CAAC,CAAC,KAAK,IAAI,YAAY,CAAC,CAAC;AAAA,QACnD;AAAA;AAAA;AAAA,yBAGiB,KAAK;AAAA,UAChB;AAAA,UACA,KAAK,IAAI,MAAM,MAAM,qBAAqB,GAAG;AAAA,QAC9C,CAAA;AAAA,QACL,6BAAM;AAAA,MAAA;AAAA,IAEV;AAEA,uCAAM,aAAN,8BAAiB;AAEV,WAAA;AAAA,EAAA;AAEX;AAEgB,SAAA,aAAgB,OAAsB,KAAiB;AACrE,MAAI,UAAU,QAAW;AACjB,UAAA,IAAI,MAAM,uBAAuB,MAAM,KAAK,GAAG,KAAK,EAAE,EAAE;AAAA,EAAA,OACzD;AACE,WAAA;AAAA,EACT;AACF;AAEa,MAAA,cAAc,CAAC,GAAW,MAAc,KAAK,IAAI,IAAI,CAAC,IAAI;AAEhE,MAAM,WAAW,CACtB,cACA,IACA,OACG;AACC,MAAA;AACJ,SAAO,YAAwB,MAAkB;AAC/C,iBAAa,aAAa,SAAS;AACvB,gBAAA,aAAa,WAAW,MAAM,GAAG,MAAM,MAAM,IAAI,GAAG,EAAE;AAAA,EAAA;AAEtE;"}
1
+ {"version":3,"file":"utils.js","sources":["../../src/utils.ts"],"sourcesContent":["export type NoInfer<A extends any> = [A][A extends any ? 0 : never]\n\nexport type PartialKeys<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>\n\nexport function memo<TDeps extends ReadonlyArray<any>, TResult>(\n getDeps: () => [...TDeps],\n fn: (...args: NoInfer<[...TDeps]>) => TResult,\n opts: {\n key: false | string\n debug?: () => boolean\n onChange?: (result: TResult) => void\n initialDeps?: TDeps\n },\n) {\n let deps = opts.initialDeps ?? []\n let result: TResult | undefined\n\n return (): TResult => {\n let depTime: number\n if (opts.key && opts.debug?.()) depTime = Date.now()\n\n const newDeps = getDeps()\n\n const depsChanged =\n newDeps.length !== deps.length ||\n newDeps.some((dep: any, index: number) => deps[index] !== dep)\n\n if (!depsChanged) {\n return result!\n }\n\n deps = newDeps\n\n let resultTime: number\n if (opts.key && opts.debug?.()) resultTime = Date.now()\n\n result = fn(...newDeps)\n\n if (opts.key && opts.debug?.()) {\n const depEndTime = Math.round((Date.now() - depTime!) * 100) / 100\n const resultEndTime = Math.round((Date.now() - resultTime!) * 100) / 100\n const resultFpsPercentage = resultEndTime / 16\n\n const pad = (str: number | string, num: number) => {\n str = String(str)\n while (str.length < num) {\n str = ' ' + str\n }\n return str\n }\n\n console.info(\n `%c⏱ ${pad(resultEndTime, 5)} /${pad(depEndTime, 5)} ms`,\n `\n font-size: .6rem;\n font-weight: bold;\n color: hsl(${Math.max(\n 0,\n Math.min(120 - 120 * resultFpsPercentage, 120),\n )}deg 100% 31%);`,\n opts?.key,\n )\n }\n\n opts?.onChange?.(result)\n\n return result\n }\n}\n\nexport function notUndefined<T>(value: T | undefined, msg?: string): T {\n if (value === undefined) {\n throw new Error(`Unexpected undefined${msg ? `: ${msg}` : ''}`)\n } else {\n return value\n }\n}\n\nexport const approxEqual = (a: number, b: number) => Math.abs(a - b) < 1\n\nexport const debounce = (\n targetWindow: Window & typeof globalThis,\n fn: Function,\n ms: number,\n) => {\n let timeoutId: number\n return function (this: any, ...args: Array<any>) {\n targetWindow.clearTimeout(timeoutId)\n timeoutId = targetWindow.setTimeout(() => fn.apply(this, args), ms)\n }\n}\n"],"names":[],"mappings":"AAIgB,SAAA,KACd,SACA,IACA,MAMA;AACI,MAAA,OAAO,KAAK,eAAe,CAAC;AAC5B,MAAA;AAEJ,SAAO,MAAe;AAbR;AAcR,QAAA;AACJ,QAAI,KAAK,SAAO,UAAK,UAAL,+BAAgB,WAAU,KAAK,IAAI;AAEnD,UAAM,UAAU,QAAQ;AAExB,UAAM,cACJ,QAAQ,WAAW,KAAK,UACxB,QAAQ,KAAK,CAAC,KAAU,UAAkB,KAAK,KAAK,MAAM,GAAG;AAE/D,QAAI,CAAC,aAAa;AACT,aAAA;AAAA,IAAA;AAGF,WAAA;AAEH,QAAA;AACJ,QAAI,KAAK,SAAO,UAAK,UAAL,+BAAgB,cAAa,KAAK,IAAI;AAE7C,aAAA,GAAG,GAAG,OAAO;AAEtB,QAAI,KAAK,SAAO,UAAK,UAAL,gCAAgB;AACxB,YAAA,aAAa,KAAK,OAAO,KAAK,QAAQ,WAAY,GAAG,IAAI;AACzD,YAAA,gBAAgB,KAAK,OAAO,KAAK,QAAQ,cAAe,GAAG,IAAI;AACrE,YAAM,sBAAsB,gBAAgB;AAEtC,YAAA,MAAM,CAAC,KAAsB,QAAgB;AACjD,cAAM,OAAO,GAAG;AACT,eAAA,IAAI,SAAS,KAAK;AACvB,gBAAM,MAAM;AAAA,QAAA;AAEP,eAAA;AAAA,MACT;AAEQ,cAAA;AAAA,QACN,OAAO,IAAI,eAAe,CAAC,CAAC,KAAK,IAAI,YAAY,CAAC,CAAC;AAAA,QACnD;AAAA;AAAA;AAAA,yBAGiB,KAAK;AAAA,UAChB;AAAA,UACA,KAAK,IAAI,MAAM,MAAM,qBAAqB,GAAG;AAAA,QAC9C,CAAA;AAAA,QACL,6BAAM;AAAA,MACR;AAAA,IAAA;AAGF,uCAAM,aAAN,8BAAiB;AAEV,WAAA;AAAA,EACT;AACF;AAEgB,SAAA,aAAgB,OAAsB,KAAiB;AACrE,MAAI,UAAU,QAAW;AACjB,UAAA,IAAI,MAAM,uBAAuB,MAAM,KAAK,GAAG,KAAK,EAAE,EAAE;AAAA,EAAA,OACzD;AACE,WAAA;AAAA,EAAA;AAEX;AAEa,MAAA,cAAc,CAAC,GAAW,MAAc,KAAK,IAAI,IAAI,CAAC,IAAI;AAEhE,MAAM,WAAW,CACtB,cACA,IACA,OACG;AACC,MAAA;AACJ,SAAO,YAAwB,MAAkB;AAC/C,iBAAa,aAAa,SAAS;AACvB,gBAAA,aAAa,WAAW,MAAM,GAAG,MAAM,MAAM,IAAI,GAAG,EAAE;AAAA,EACpE;AACF;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/virtual-core",
3
- "version": "3.10.8",
3
+ "version": "3.11.2",
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
@@ -130,9 +130,11 @@ export const observeWindowRect = (
130
130
  const supportsScrollend =
131
131
  typeof window == 'undefined' ? true : 'onscrollend' in window
132
132
 
133
+ type ObserveOffsetCallBack = (offset: number, isScrolling: boolean) => void
134
+
133
135
  export const observeElementOffset = <T extends Element>(
134
136
  instance: Virtualizer<T, any>,
135
- cb: (offset: number, isScrolling: boolean) => void,
137
+ cb: ObserveOffsetCallBack,
136
138
  ) => {
137
139
  const element = instance.scrollElement
138
140
  if (!element) {
@@ -144,15 +146,16 @@ export const observeElementOffset = <T extends Element>(
144
146
  }
145
147
 
146
148
  let offset = 0
147
- const fallback = supportsScrollend
148
- ? () => undefined
149
- : debounce(
150
- targetWindow,
151
- () => {
152
- cb(offset, false)
153
- },
154
- instance.options.isScrollingResetDelay,
155
- )
149
+ const fallback =
150
+ instance.options.useScrollendEvent && supportsScrollend
151
+ ? () => undefined
152
+ : debounce(
153
+ targetWindow,
154
+ () => {
155
+ cb(offset, false)
156
+ },
157
+ instance.options.isScrollingResetDelay,
158
+ )
156
159
 
157
160
  const createHandler = (isScrolling: boolean) => () => {
158
161
  const { horizontal, isRtl } = instance.options
@@ -177,7 +180,7 @@ export const observeElementOffset = <T extends Element>(
177
180
 
178
181
  export const observeWindowOffset = (
179
182
  instance: Virtualizer<Window, any>,
180
- cb: (offset: number, isScrolling: boolean) => void,
183
+ cb: ObserveOffsetCallBack,
181
184
  ) => {
182
185
  const element = instance.scrollElement
183
186
  if (!element) {
@@ -189,15 +192,16 @@ export const observeWindowOffset = (
189
192
  }
190
193
 
191
194
  let offset = 0
192
- const fallback = supportsScrollend
193
- ? () => undefined
194
- : debounce(
195
- targetWindow,
196
- () => {
197
- cb(offset, false)
198
- },
199
- instance.options.isScrollingResetDelay,
200
- )
195
+ const fallback =
196
+ instance.options.useScrollendEvent && supportsScrollend
197
+ ? () => undefined
198
+ : debounce(
199
+ targetWindow,
200
+ () => {
201
+ cb(offset, false)
202
+ },
203
+ instance.options.isScrollingResetDelay,
204
+ )
201
205
 
202
206
  const createHandler = (isScrolling: boolean) => () => {
203
207
  offset = element[instance.options.horizontal ? 'scrollX' : 'scrollY']
@@ -291,9 +295,8 @@ export interface VirtualizerOptions<
291
295
  ) => void | (() => void)
292
296
  observeElementOffset: (
293
297
  instance: Virtualizer<TScrollElement, TItemElement>,
294
- cb: (offset: number, isScrolling: boolean) => void,
298
+ cb: ObserveOffsetCallBack,
295
299
  ) => void | (() => void)
296
-
297
300
  // Optional
298
301
  debug?: boolean
299
302
  initialRect?: Rect
@@ -321,6 +324,7 @@ export interface VirtualizerOptions<
321
324
  initialMeasurementsCache?: Array<VirtualItem>
322
325
  lanes?: number
323
326
  isScrollingResetDelay?: number
327
+ useScrollendEvent?: boolean
324
328
  enabled?: boolean
325
329
  isRtl?: boolean
326
330
  }
@@ -412,6 +416,7 @@ export class Virtualizer<
412
416
  isScrollingResetDelay: 150,
413
417
  enabled: true,
414
418
  isRtl: false,
419
+ useScrollendEvent: true,
415
420
  ...opts,
416
421
  }
417
422
  }
@@ -840,21 +845,13 @@ export class Virtualizer<
840
845
  const scrollOffset = this.getScrollOffset()
841
846
 
842
847
  if (align === 'auto') {
843
- if (toOffset <= scrollOffset) {
844
- align = 'start'
845
- } else if (toOffset >= scrollOffset + size) {
848
+ if (toOffset >= scrollOffset + size) {
846
849
  align = 'end'
847
- } else {
848
- align = 'start'
849
850
  }
850
851
  }
851
852
 
852
- if (align === 'start') {
853
- toOffset = toOffset
854
- } else if (align === 'end') {
855
- toOffset = toOffset - size
856
- } else if (align === 'center') {
857
- toOffset = toOffset - size / 2
853
+ if (align === 'end') {
854
+ toOffset -= size
858
855
  }
859
856
 
860
857
  const scrollSizeProp = this.options.horizontal
@@ -892,12 +889,29 @@ export class Virtualizer<
892
889
  }
893
890
  }
894
891
 
895
- const toOffset =
896
- align === 'end'
897
- ? item.end + this.options.scrollPaddingEnd
898
- : item.start - this.options.scrollPaddingStart
899
-
900
- return [this.getOffsetForAlignment(toOffset, align), align] as const
892
+ const centerOffset =
893
+ item.start - this.options.scrollPaddingStart + (item.size - size) / 2
894
+
895
+ switch (align) {
896
+ case 'center':
897
+ return [this.getOffsetForAlignment(centerOffset, align), align] as const
898
+ case 'end':
899
+ return [
900
+ this.getOffsetForAlignment(
901
+ item.end + this.options.scrollPaddingEnd,
902
+ align,
903
+ ),
904
+ align,
905
+ ] as const
906
+ default:
907
+ return [
908
+ this.getOffsetForAlignment(
909
+ item.start - this.options.scrollPaddingStart,
910
+ align,
911
+ ),
912
+ align,
913
+ ] as const
914
+ }
901
915
  }
902
916
 
903
917
  private isDynamicMode = () => this.elementsCache.size > 0