@tanstack/virtual-core 3.13.22 → 3.13.23

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.
@@ -216,7 +216,6 @@ class Virtualizer {
216
216
  const index = this.indexFromElement(node);
217
217
  if (!node.isConnected) {
218
218
  this.observer.unobserve(node);
219
- this.elementsCache.delete(this.options.getItemKey(index));
220
219
  return;
221
220
  }
222
221
  if (this.shouldMeasureDuringScroll(index)) {
@@ -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' | 'instant'\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\nconst getRect = (element: HTMLElement): Rect => {\n const { offsetWidth, offsetHeight } = element\n return { width: offsetWidth, height: offsetHeight }\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(getRect(element as unknown as HTMLElement))\n\n if (!targetWindow.ResizeObserver) {\n return () => {}\n }\n\n const observer = new targetWindow.ResizeObserver((entries) => {\n const run = () => {\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(getRect(element as unknown as HTMLElement))\n }\n\n instance.options.useAnimationFrameWithResizeObserver\n ? requestAnimationFrame(run)\n : run()\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\n element.addEventListener('scroll', handler, addEventListenerOptions)\n const registerScrollendEvent =\n instance.options.useScrollendEvent && supportsScrollend\n if (registerScrollendEvent) {\n element.addEventListener('scrollend', endHandler, addEventListenerOptions)\n }\n return () => {\n element.removeEventListener('scroll', handler)\n if (registerScrollendEvent) {\n element.removeEventListener('scrollend', endHandler)\n }\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\n element.addEventListener('scroll', handler, addEventListenerOptions)\n const registerScrollendEvent =\n instance.options.useScrollendEvent && supportsScrollend\n if (registerScrollendEvent) {\n element.addEventListener('scrollend', endHandler, addEventListenerOptions)\n }\n return () => {\n element.removeEventListener('scroll', handler)\n if (registerScrollendEvent) {\n element.removeEventListener('scrollend', endHandler)\n }\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\n return (element as unknown as HTMLElement)[\n instance.options.horizontal ? 'offsetWidth' : 'offsetHeight'\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 useAnimationFrameWithResizeObserver?: boolean\n}\n\ntype ScrollState = {\n // what we want\n index: number | null\n align: ScrollAlignment\n behavior: ScrollBehavior\n\n // lifecycle\n startedAt: number\n\n // target tracking\n lastTargetOffset: number\n\n // settling\n stableFrames: number\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 scrollState: ScrollState | null = null\n measurementsCache: Array<VirtualItem> = []\n private itemSizeCache = new Map<Key, number>()\n private laneAssignments = new Map<number, number>() // index → lane cache\n private pendingMeasuredCacheIndexes: Array<number> = []\n private prevLanes: number | undefined = undefined\n private lanesChangedFlag = false\n private lanesSettling = false\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 now = () => this.targetWindow?.performance?.now?.() ?? Date.now()\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 const run = () => {\n const node = entry.target as TItemElement\n const index = this.indexFromElement(node)\n\n if (!node.isConnected) {\n this.observer.unobserve(node)\n this.elementsCache.delete(this.options.getItemKey(index))\n return\n }\n\n if (this.shouldMeasureDuringScroll(index)) {\n this.resizeItem(\n index,\n this.options.measureElement(node, entry, this),\n )\n }\n }\n this.options.useAnimationFrameWithResizeObserver\n ? requestAnimationFrame(run)\n : run()\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: false,\n useAnimationFrameWithResizeObserver: 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 if (this.rafId != null && this.targetWindow) {\n this.targetWindow.cancelAnimationFrame(this.rafId)\n this.rafId = null\n }\n this.scrollState = null\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.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 if (this.scrollState) {\n this.scheduleScrollReconcile()\n }\n this.maybeNotify()\n }),\n )\n\n this._scrollToOffset(this.getScrollOffset(), {\n adjustments: undefined,\n behavior: undefined,\n })\n }\n }\n\n private rafId: number | null = null\n private scheduleScrollReconcile() {\n if (!this.targetWindow) {\n this.scrollState = null\n return\n }\n if (this.rafId != null) return\n this.rafId = this.targetWindow.requestAnimationFrame(() => {\n this.rafId = null\n this.reconcileScroll()\n })\n }\n private reconcileScroll() {\n if (!this.scrollState) return\n\n const el = this.scrollElement\n if (!el) return\n\n // Safety valve: bail out if reconciliation has been running too long\n const MAX_RECONCILE_MS = 5000\n if (this.now() - this.scrollState.startedAt > MAX_RECONCILE_MS) {\n this.scrollState = null\n return\n }\n\n const offsetInfo =\n this.scrollState.index != null\n ? this.getOffsetForIndex(this.scrollState.index, this.scrollState.align)\n : undefined\n const targetOffset = offsetInfo\n ? offsetInfo[0]\n : this.scrollState.lastTargetOffset\n\n // Require one stable frame where target matches scroll offset.\n // approxEqual() already tolerates minor fluctuations, so one frame is sufficient\n // to confirm scroll has reached its target without premature cleanup.\n const STABLE_FRAMES = 1\n\n const targetChanged = targetOffset !== this.scrollState.lastTargetOffset\n\n if (!targetChanged && approxEqual(targetOffset, this.getScrollOffset())) {\n this.scrollState.stableFrames++\n if (this.scrollState.stableFrames >= STABLE_FRAMES) {\n this.scrollState = null\n return\n }\n } else {\n this.scrollState.stableFrames = 0\n\n if (targetChanged) {\n this.scrollState.lastTargetOffset = targetOffset\n // Switch to 'auto' behavior once measurements cause target to change\n // We want to jump directly to the correct position, not smoothly animate to it\n this.scrollState.behavior = 'auto'\n\n this._scrollToOffset(targetOffset, {\n adjustments: undefined,\n behavior: 'auto',\n })\n }\n }\n\n // Always reschedule while scrollState is active to guarantee\n // the safety valve timeout runs even if no scroll events fire\n // (e.g. no-op scrollToFn, detached element)\n this.scheduleScrollReconcile()\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 this.options.lanes,\n ],\n (count, paddingStart, scrollMargin, getItemKey, enabled, lanes) => {\n const lanesChanged =\n this.prevLanes !== undefined && this.prevLanes !== lanes\n\n if (lanesChanged) {\n // Set flag for getMeasurements to handle\n this.lanesChangedFlag = true\n }\n\n this.prevLanes = lanes\n this.pendingMeasuredCacheIndexes = []\n\n return {\n count,\n paddingStart,\n scrollMargin,\n getItemKey,\n enabled,\n lanes,\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, lanes },\n itemSizeCache,\n ) => {\n if (!enabled) {\n this.measurementsCache = []\n this.itemSizeCache.clear()\n this.laneAssignments.clear()\n return []\n }\n\n // Clean up stale lane cache entries when count decreases\n if (this.laneAssignments.size > count) {\n for (const index of this.laneAssignments.keys()) {\n if (index >= count) {\n this.laneAssignments.delete(index)\n }\n }\n }\n\n // ✅ Force complete recalculation when lanes change\n if (this.lanesChangedFlag) {\n this.lanesChangedFlag = false // Reset immediately\n this.lanesSettling = true // Start settling period\n this.measurementsCache = []\n this.itemSizeCache.clear()\n this.laneAssignments.clear() // Clear lane cache for new lane count\n // Clear pending indexes to force min = 0\n this.pendingMeasuredCacheIndexes = []\n }\n\n // Don't restore from initialMeasurementsCache during lane changes\n // as it contains stale lane assignments from the previous lane count\n if (this.measurementsCache.length === 0 && !this.lanesSettling) {\n this.measurementsCache = this.options.initialMeasurementsCache\n this.measurementsCache.forEach((item) => {\n this.itemSizeCache.set(item.key, item.size)\n })\n }\n\n // ✅ During lanes settling, ignore pendingMeasuredCacheIndexes to prevent repositioning\n const min = this.lanesSettling\n ? 0\n : this.pendingMeasuredCacheIndexes.length > 0\n ? Math.min(...this.pendingMeasuredCacheIndexes)\n : 0\n this.pendingMeasuredCacheIndexes = []\n\n // ✅ End settling period when cache is fully built\n if (this.lanesSettling && this.measurementsCache.length === count) {\n this.lanesSettling = false\n }\n\n const measurements = this.measurementsCache.slice(0, min)\n\n // ✅ Performance: Track last item index per lane for O(1) lookup\n const laneLastIndex: Array<number | undefined> = new Array(lanes).fill(\n undefined,\n )\n\n // Initialize from existing measurements (before min)\n for (let m = 0; m < min; m++) {\n const item = measurements[m]\n if (item) {\n laneLastIndex[item.lane] = m\n }\n }\n\n for (let i = min; i < count; i++) {\n const key = getItemKey(i)\n\n // Check for cached lane assignment\n const cachedLane = this.laneAssignments.get(i)\n let lane: number\n let start: number\n\n if (cachedLane !== undefined && this.options.lanes > 1) {\n // Use cached lane - O(1) lookup for previous item in same lane\n lane = cachedLane\n const prevIndex = laneLastIndex[lane]\n const prevInLane =\n prevIndex !== undefined ? measurements[prevIndex] : undefined\n start = prevInLane\n ? prevInLane.end + this.options.gap\n : paddingStart + scrollMargin\n } else {\n // No cache - use original logic (find shortest lane)\n const furthestMeasurement =\n this.options.lanes === 1\n ? measurements[i - 1]\n : this.getFurthestMeasurement(measurements, i)\n\n start = furthestMeasurement\n ? furthestMeasurement.end + this.options.gap\n : paddingStart + scrollMargin\n\n lane = furthestMeasurement\n ? furthestMeasurement.lane\n : i % this.options.lanes\n\n // Cache the lane assignment\n if (this.options.lanes > 1) {\n this.laneAssignments.set(i, lane)\n }\n }\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 measurements[i] = {\n index: i,\n start,\n size,\n end,\n key,\n lane,\n }\n\n // ✅ Performance: Update lane's last item index\n laneLastIndex[lane] = i\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 () => [\n this.getMeasurements(),\n this.getSize(),\n this.getScrollOffset(),\n this.options.lanes,\n ],\n (measurements, outerSize, scrollOffset, lanes) => {\n return (this.range =\n measurements.length > 0 && outerSize > 0\n ? calculateRange({\n measurements,\n outerSize,\n scrollOffset,\n lanes,\n })\n : null)\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'calculateRange',\n debug: () => this.options.debug,\n },\n )\n\n getVirtualIndexes = memo(\n () => {\n let startIndex: number | null = null\n let endIndex: number | null = null\n const range = this.calculateRange()\n if (range) {\n startIndex = range.startIndex\n endIndex = range.endIndex\n }\n this.maybeNotify.updateDeps([this.isScrolling, startIndex, endIndex])\n return [\n this.options.rangeExtractor,\n this.options.overscan,\n this.options.count,\n startIndex,\n endIndex,\n ]\n },\n (rangeExtractor, overscan, count, startIndex, endIndex) => {\n return startIndex === null || endIndex === null\n ? []\n : rangeExtractor({\n startIndex,\n endIndex,\n overscan,\n count,\n })\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'getVirtualIndexes',\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 /**\n * Determines if an item at the given index should be measured during smooth scroll.\n * During smooth scroll, only items within a buffer range around the target are measured\n * to prevent items far from the target from pushing it away.\n */\n private shouldMeasureDuringScroll = (index: number): boolean => {\n // No scroll state or not smooth scroll - always allow measurements\n if (!this.scrollState || this.scrollState.behavior !== 'smooth') {\n return true\n }\n\n const scrollIndex =\n this.scrollState.index ??\n this.getVirtualItemForOffset(this.scrollState.lastTargetOffset)?.index\n\n if (scrollIndex !== undefined && this.range) {\n // Allow measurements within a buffer range around the scroll target\n const bufferSize = Math.max(\n this.options.overscan,\n Math.ceil((this.range.endIndex - this.range.startIndex) / 2),\n )\n const minIndex = Math.max(0, scrollIndex - bufferSize)\n const maxIndex = Math.min(\n this.options.count - 1,\n scrollIndex + bufferSize,\n )\n return index >= minIndex && index <= maxIndex\n }\n\n return true\n }\n\n measureElement = (node: TItemElement | null) => {\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 const index = this.indexFromElement(node)\n const key = this.options.getItemKey(index)\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 // Sync-measure when idle (initial render) or during programmatic scrolling\n // (scrollToIndex/scrollToOffset) where reconcileScroll needs sizes in the same frame.\n // During normal user scrolling, skip sync measurement — the RO callback handles it async.\n if (\n (!this.isScrolling || this.scrollState) &&\n this.shouldMeasureDuringScroll(index)\n ) {\n this.resizeItem(index, this.options.measureElement(node, undefined, this))\n }\n }\n\n resizeItem = (index: number, size: number) => {\n const item = this.measurementsCache[index]\n if (!item) 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.scrollState?.behavior !== 'smooth' &&\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 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 getVirtualItems = memo(\n () => [this.getVirtualIndexes(), 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 private getMaxScrollOffset = () => {\n if (!this.scrollElement) return 0\n\n if ('scrollHeight' in this.scrollElement) {\n // Element\n return this.options.horizontal\n ? this.scrollElement.scrollWidth - this.scrollElement.clientWidth\n : this.scrollElement.scrollHeight - this.scrollElement.clientHeight\n } else {\n // Window\n const doc = this.scrollElement.document.documentElement\n return this.options.horizontal\n ? doc.scrollWidth - this.scrollElement.innerWidth\n : doc.scrollHeight - this.scrollElement.innerHeight\n }\n }\n\n getOffsetForAlignment = (\n toOffset: number,\n align: ScrollAlignment,\n itemSize = 0,\n ) => {\n if (!this.scrollElement) return 0\n\n const size = this.getSize()\n const scrollOffset = this.getScrollOffset()\n\n if (align === 'auto') {\n align = toOffset >= scrollOffset + size ? 'end' : 'start'\n }\n\n if (align === 'center') {\n // When aligning to a particular item (e.g. with scrollToIndex),\n // adjust offset by the size of the item to center on the item\n toOffset += (itemSize - size) / 2\n } else if (align === 'end') {\n toOffset -= size\n }\n\n const maxOffset = this.getMaxScrollOffset()\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 size = this.getSize()\n const scrollOffset = this.getScrollOffset()\n\n const item = this.measurementsCache[index]\n if (!item) return\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 // For the last item with 'end' alignment, use browser's actual max scroll\n // to account for borders/padding that aren't in our measurements\n if (align === 'end' && index === this.options.count - 1) {\n return [this.getMaxScrollOffset(), align] as const\n }\n\n const toOffset =\n align === 'end'\n ? item.end + this.options.scrollPaddingEnd\n : item.start - this.options.scrollPaddingStart\n\n return [\n this.getOffsetForAlignment(toOffset, align, item.size),\n align,\n ] as const\n }\n\n scrollToOffset = (\n toOffset: number,\n { align = 'start', behavior = 'auto' }: ScrollToOffsetOptions = {},\n ) => {\n const offset = this.getOffsetForAlignment(toOffset, align)\n\n const now = this.now()\n this.scrollState = {\n index: null,\n align,\n behavior,\n startedAt: now,\n lastTargetOffset: offset,\n stableFrames: 0,\n }\n\n this._scrollToOffset(offset, { adjustments: undefined, behavior })\n\n this.scheduleScrollReconcile()\n }\n\n scrollToIndex = (\n index: number,\n {\n align: initialAlign = 'auto',\n behavior = 'auto',\n }: ScrollToIndexOptions = {},\n ) => {\n index = Math.max(0, Math.min(index, this.options.count - 1))\n\n const offsetInfo = this.getOffsetForIndex(index, initialAlign)\n if (!offsetInfo) {\n return\n }\n const [offset, align] = offsetInfo\n\n const now = this.now()\n this.scrollState = {\n index,\n align,\n behavior,\n startedAt: now,\n lastTargetOffset: offset,\n stableFrames: 0,\n }\n\n this._scrollToOffset(offset, { adjustments: undefined, behavior })\n\n this.scheduleScrollReconcile()\n }\n\n scrollBy = (\n delta: number,\n { behavior = 'auto' }: ScrollToOffsetOptions = {},\n ) => {\n const offset = this.getScrollOffset() + delta\n const now = this.now()\n\n this.scrollState = {\n index: null,\n align: 'start',\n behavior,\n startedAt: now,\n lastTargetOffset: offset,\n stableFrames: 0,\n }\n\n this._scrollToOffset(offset, { adjustments: undefined, behavior })\n\n this.scheduleScrollReconcile()\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 there is only one lane, use the last measurement's end\n // Otherwise find the maximum end value among all measurements\n if (measurements.length === 0) {\n end = this.options.paddingStart\n } else if (this.options.lanes === 1) {\n end = measurements[measurements.length - 1]?.end ?? 0\n } else {\n const endByLane = Array<number | null>(this.options.lanes).fill(null)\n let endIndex = measurements.length - 1\n while (endIndex >= 0 && endByLane.some((val) => val === null)) {\n const item = measurements[endIndex]!\n if (endByLane[item.lane] === null) {\n endByLane[item.lane] = item.end\n }\n\n endIndex--\n }\n\n end = Math.max(...endByLane.filter((val): val is number => val !== null))\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.laneAssignments = new Map() // Clear lane cache for full re-layout\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 lanes,\n}: {\n measurements: Array<VirtualItem>\n outerSize: number\n scrollOffset: number\n lanes: number\n}) {\n const lastIndex = measurements.length - 1\n const getOffset = (index: number) => measurements[index]!.start\n\n // handle case when item count is less than or equal to lanes\n if (measurements.length <= lanes) {\n return {\n startIndex: 0,\n endIndex: lastIndex,\n }\n }\n\n let startIndex = findNearestBinarySearch(\n 0,\n lastIndex,\n getOffset,\n scrollOffset,\n )\n let endIndex = startIndex\n\n if (lanes === 1) {\n while (\n endIndex < lastIndex &&\n measurements[endIndex]!.end < scrollOffset + outerSize\n ) {\n endIndex++\n }\n } else if (lanes > 1) {\n // Expand forward until we include the visible items from all lanes\n // which are closer to the end of the virtualizer window\n const endPerLane = Array(lanes).fill(0)\n while (\n endIndex < lastIndex &&\n endPerLane.some((pos) => pos < scrollOffset + outerSize)\n ) {\n const item = measurements[endIndex]!\n endPerLane[item.lane] = item.end\n endIndex++\n }\n\n // Expand backward until we include all lanes' visible items\n // closer to the top\n const startPerLane = Array(lanes).fill(scrollOffset + outerSize)\n while (startIndex >= 0 && startPerLane.some((pos) => pos >= scrollOffset)) {\n const item = measurements[startIndex]!\n startPerLane[item.lane] = item.start\n startIndex--\n }\n\n // Align startIndex to the beginning of its lane\n startIndex = Math.max(0, startIndex - (startIndex % lanes))\n // Align endIndex to the end of its lane\n endIndex = Math.min(lastIndex, endIndex + (lanes - 1 - (endIndex % lanes)))\n }\n\n return { startIndex, endIndex }\n}\n"],"names":["debounce","opts","memo","key","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' | 'instant'\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\nconst getRect = (element: HTMLElement): Rect => {\n const { offsetWidth, offsetHeight } = element\n return { width: offsetWidth, height: offsetHeight }\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(getRect(element as unknown as HTMLElement))\n\n if (!targetWindow.ResizeObserver) {\n return () => {}\n }\n\n const observer = new targetWindow.ResizeObserver((entries) => {\n const run = () => {\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(getRect(element as unknown as HTMLElement))\n }\n\n instance.options.useAnimationFrameWithResizeObserver\n ? requestAnimationFrame(run)\n : run()\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\n element.addEventListener('scroll', handler, addEventListenerOptions)\n const registerScrollendEvent =\n instance.options.useScrollendEvent && supportsScrollend\n if (registerScrollendEvent) {\n element.addEventListener('scrollend', endHandler, addEventListenerOptions)\n }\n return () => {\n element.removeEventListener('scroll', handler)\n if (registerScrollendEvent) {\n element.removeEventListener('scrollend', endHandler)\n }\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\n element.addEventListener('scroll', handler, addEventListenerOptions)\n const registerScrollendEvent =\n instance.options.useScrollendEvent && supportsScrollend\n if (registerScrollendEvent) {\n element.addEventListener('scrollend', endHandler, addEventListenerOptions)\n }\n return () => {\n element.removeEventListener('scroll', handler)\n if (registerScrollendEvent) {\n element.removeEventListener('scrollend', endHandler)\n }\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\n return (element as unknown as HTMLElement)[\n instance.options.horizontal ? 'offsetWidth' : 'offsetHeight'\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 useAnimationFrameWithResizeObserver?: boolean\n}\n\ntype ScrollState = {\n // what we want\n index: number | null\n align: ScrollAlignment\n behavior: ScrollBehavior\n\n // lifecycle\n startedAt: number\n\n // target tracking\n lastTargetOffset: number\n\n // settling\n stableFrames: number\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 scrollState: ScrollState | null = null\n measurementsCache: Array<VirtualItem> = []\n private itemSizeCache = new Map<Key, number>()\n private laneAssignments = new Map<number, number>() // index → lane cache\n private pendingMeasuredCacheIndexes: Array<number> = []\n private prevLanes: number | undefined = undefined\n private lanesChangedFlag = false\n private lanesSettling = false\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 now = () => this.targetWindow?.performance?.now?.() ?? Date.now()\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 const run = () => {\n const node = entry.target as TItemElement\n const index = this.indexFromElement(node)\n\n if (!node.isConnected) {\n this.observer.unobserve(node)\n return\n }\n\n if (this.shouldMeasureDuringScroll(index)) {\n this.resizeItem(\n index,\n this.options.measureElement(node, entry, this),\n )\n }\n }\n this.options.useAnimationFrameWithResizeObserver\n ? requestAnimationFrame(run)\n : run()\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: false,\n useAnimationFrameWithResizeObserver: 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 if (this.rafId != null && this.targetWindow) {\n this.targetWindow.cancelAnimationFrame(this.rafId)\n this.rafId = null\n }\n this.scrollState = null\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.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 if (this.scrollState) {\n this.scheduleScrollReconcile()\n }\n this.maybeNotify()\n }),\n )\n\n this._scrollToOffset(this.getScrollOffset(), {\n adjustments: undefined,\n behavior: undefined,\n })\n }\n }\n\n private rafId: number | null = null\n private scheduleScrollReconcile() {\n if (!this.targetWindow) {\n this.scrollState = null\n return\n }\n if (this.rafId != null) return\n this.rafId = this.targetWindow.requestAnimationFrame(() => {\n this.rafId = null\n this.reconcileScroll()\n })\n }\n private reconcileScroll() {\n if (!this.scrollState) return\n\n const el = this.scrollElement\n if (!el) return\n\n // Safety valve: bail out if reconciliation has been running too long\n const MAX_RECONCILE_MS = 5000\n if (this.now() - this.scrollState.startedAt > MAX_RECONCILE_MS) {\n this.scrollState = null\n return\n }\n\n const offsetInfo =\n this.scrollState.index != null\n ? this.getOffsetForIndex(this.scrollState.index, this.scrollState.align)\n : undefined\n const targetOffset = offsetInfo\n ? offsetInfo[0]\n : this.scrollState.lastTargetOffset\n\n // Require one stable frame where target matches scroll offset.\n // approxEqual() already tolerates minor fluctuations, so one frame is sufficient\n // to confirm scroll has reached its target without premature cleanup.\n const STABLE_FRAMES = 1\n\n const targetChanged = targetOffset !== this.scrollState.lastTargetOffset\n\n if (!targetChanged && approxEqual(targetOffset, this.getScrollOffset())) {\n this.scrollState.stableFrames++\n if (this.scrollState.stableFrames >= STABLE_FRAMES) {\n this.scrollState = null\n return\n }\n } else {\n this.scrollState.stableFrames = 0\n\n if (targetChanged) {\n this.scrollState.lastTargetOffset = targetOffset\n // Switch to 'auto' behavior once measurements cause target to change\n // We want to jump directly to the correct position, not smoothly animate to it\n this.scrollState.behavior = 'auto'\n\n this._scrollToOffset(targetOffset, {\n adjustments: undefined,\n behavior: 'auto',\n })\n }\n }\n\n // Always reschedule while scrollState is active to guarantee\n // the safety valve timeout runs even if no scroll events fire\n // (e.g. no-op scrollToFn, detached element)\n this.scheduleScrollReconcile()\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 this.options.lanes,\n ],\n (count, paddingStart, scrollMargin, getItemKey, enabled, lanes) => {\n const lanesChanged =\n this.prevLanes !== undefined && this.prevLanes !== lanes\n\n if (lanesChanged) {\n // Set flag for getMeasurements to handle\n this.lanesChangedFlag = true\n }\n\n this.prevLanes = lanes\n this.pendingMeasuredCacheIndexes = []\n\n return {\n count,\n paddingStart,\n scrollMargin,\n getItemKey,\n enabled,\n lanes,\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, lanes },\n itemSizeCache,\n ) => {\n if (!enabled) {\n this.measurementsCache = []\n this.itemSizeCache.clear()\n this.laneAssignments.clear()\n return []\n }\n\n // Clean up stale lane cache entries when count decreases\n if (this.laneAssignments.size > count) {\n for (const index of this.laneAssignments.keys()) {\n if (index >= count) {\n this.laneAssignments.delete(index)\n }\n }\n }\n\n // ✅ Force complete recalculation when lanes change\n if (this.lanesChangedFlag) {\n this.lanesChangedFlag = false // Reset immediately\n this.lanesSettling = true // Start settling period\n this.measurementsCache = []\n this.itemSizeCache.clear()\n this.laneAssignments.clear() // Clear lane cache for new lane count\n // Clear pending indexes to force min = 0\n this.pendingMeasuredCacheIndexes = []\n }\n\n // Don't restore from initialMeasurementsCache during lane changes\n // as it contains stale lane assignments from the previous lane count\n if (this.measurementsCache.length === 0 && !this.lanesSettling) {\n this.measurementsCache = this.options.initialMeasurementsCache\n this.measurementsCache.forEach((item) => {\n this.itemSizeCache.set(item.key, item.size)\n })\n }\n\n // ✅ During lanes settling, ignore pendingMeasuredCacheIndexes to prevent repositioning\n const min = this.lanesSettling\n ? 0\n : this.pendingMeasuredCacheIndexes.length > 0\n ? Math.min(...this.pendingMeasuredCacheIndexes)\n : 0\n this.pendingMeasuredCacheIndexes = []\n\n // ✅ End settling period when cache is fully built\n if (this.lanesSettling && this.measurementsCache.length === count) {\n this.lanesSettling = false\n }\n\n const measurements = this.measurementsCache.slice(0, min)\n\n // ✅ Performance: Track last item index per lane for O(1) lookup\n const laneLastIndex: Array<number | undefined> = new Array(lanes).fill(\n undefined,\n )\n\n // Initialize from existing measurements (before min)\n for (let m = 0; m < min; m++) {\n const item = measurements[m]\n if (item) {\n laneLastIndex[item.lane] = m\n }\n }\n\n for (let i = min; i < count; i++) {\n const key = getItemKey(i)\n\n // Check for cached lane assignment\n const cachedLane = this.laneAssignments.get(i)\n let lane: number\n let start: number\n\n if (cachedLane !== undefined && this.options.lanes > 1) {\n // Use cached lane - O(1) lookup for previous item in same lane\n lane = cachedLane\n const prevIndex = laneLastIndex[lane]\n const prevInLane =\n prevIndex !== undefined ? measurements[prevIndex] : undefined\n start = prevInLane\n ? prevInLane.end + this.options.gap\n : paddingStart + scrollMargin\n } else {\n // No cache - use original logic (find shortest lane)\n const furthestMeasurement =\n this.options.lanes === 1\n ? measurements[i - 1]\n : this.getFurthestMeasurement(measurements, i)\n\n start = furthestMeasurement\n ? furthestMeasurement.end + this.options.gap\n : paddingStart + scrollMargin\n\n lane = furthestMeasurement\n ? furthestMeasurement.lane\n : i % this.options.lanes\n\n // Cache the lane assignment\n if (this.options.lanes > 1) {\n this.laneAssignments.set(i, lane)\n }\n }\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 measurements[i] = {\n index: i,\n start,\n size,\n end,\n key,\n lane,\n }\n\n // ✅ Performance: Update lane's last item index\n laneLastIndex[lane] = i\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 () => [\n this.getMeasurements(),\n this.getSize(),\n this.getScrollOffset(),\n this.options.lanes,\n ],\n (measurements, outerSize, scrollOffset, lanes) => {\n return (this.range =\n measurements.length > 0 && outerSize > 0\n ? calculateRange({\n measurements,\n outerSize,\n scrollOffset,\n lanes,\n })\n : null)\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'calculateRange',\n debug: () => this.options.debug,\n },\n )\n\n getVirtualIndexes = memo(\n () => {\n let startIndex: number | null = null\n let endIndex: number | null = null\n const range = this.calculateRange()\n if (range) {\n startIndex = range.startIndex\n endIndex = range.endIndex\n }\n this.maybeNotify.updateDeps([this.isScrolling, startIndex, endIndex])\n return [\n this.options.rangeExtractor,\n this.options.overscan,\n this.options.count,\n startIndex,\n endIndex,\n ]\n },\n (rangeExtractor, overscan, count, startIndex, endIndex) => {\n return startIndex === null || endIndex === null\n ? []\n : rangeExtractor({\n startIndex,\n endIndex,\n overscan,\n count,\n })\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'getVirtualIndexes',\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 /**\n * Determines if an item at the given index should be measured during smooth scroll.\n * During smooth scroll, only items within a buffer range around the target are measured\n * to prevent items far from the target from pushing it away.\n */\n private shouldMeasureDuringScroll = (index: number): boolean => {\n // No scroll state or not smooth scroll - always allow measurements\n if (!this.scrollState || this.scrollState.behavior !== 'smooth') {\n return true\n }\n\n const scrollIndex =\n this.scrollState.index ??\n this.getVirtualItemForOffset(this.scrollState.lastTargetOffset)?.index\n\n if (scrollIndex !== undefined && this.range) {\n // Allow measurements within a buffer range around the scroll target\n const bufferSize = Math.max(\n this.options.overscan,\n Math.ceil((this.range.endIndex - this.range.startIndex) / 2),\n )\n const minIndex = Math.max(0, scrollIndex - bufferSize)\n const maxIndex = Math.min(\n this.options.count - 1,\n scrollIndex + bufferSize,\n )\n return index >= minIndex && index <= maxIndex\n }\n\n return true\n }\n\n measureElement = (node: TItemElement | null) => {\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 const index = this.indexFromElement(node)\n const key = this.options.getItemKey(index)\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 // Sync-measure when idle (initial render) or during programmatic scrolling\n // (scrollToIndex/scrollToOffset) where reconcileScroll needs sizes in the same frame.\n // During normal user scrolling, skip sync measurement — the RO callback handles it async.\n if (\n (!this.isScrolling || this.scrollState) &&\n this.shouldMeasureDuringScroll(index)\n ) {\n this.resizeItem(index, this.options.measureElement(node, undefined, this))\n }\n }\n\n resizeItem = (index: number, size: number) => {\n const item = this.measurementsCache[index]\n if (!item) 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.scrollState?.behavior !== 'smooth' &&\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 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 getVirtualItems = memo(\n () => [this.getVirtualIndexes(), 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 private getMaxScrollOffset = () => {\n if (!this.scrollElement) return 0\n\n if ('scrollHeight' in this.scrollElement) {\n // Element\n return this.options.horizontal\n ? this.scrollElement.scrollWidth - this.scrollElement.clientWidth\n : this.scrollElement.scrollHeight - this.scrollElement.clientHeight\n } else {\n // Window\n const doc = this.scrollElement.document.documentElement\n return this.options.horizontal\n ? doc.scrollWidth - this.scrollElement.innerWidth\n : doc.scrollHeight - this.scrollElement.innerHeight\n }\n }\n\n getOffsetForAlignment = (\n toOffset: number,\n align: ScrollAlignment,\n itemSize = 0,\n ) => {\n if (!this.scrollElement) return 0\n\n const size = this.getSize()\n const scrollOffset = this.getScrollOffset()\n\n if (align === 'auto') {\n align = toOffset >= scrollOffset + size ? 'end' : 'start'\n }\n\n if (align === 'center') {\n // When aligning to a particular item (e.g. with scrollToIndex),\n // adjust offset by the size of the item to center on the item\n toOffset += (itemSize - size) / 2\n } else if (align === 'end') {\n toOffset -= size\n }\n\n const maxOffset = this.getMaxScrollOffset()\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 size = this.getSize()\n const scrollOffset = this.getScrollOffset()\n\n const item = this.measurementsCache[index]\n if (!item) return\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 // For the last item with 'end' alignment, use browser's actual max scroll\n // to account for borders/padding that aren't in our measurements\n if (align === 'end' && index === this.options.count - 1) {\n return [this.getMaxScrollOffset(), align] as const\n }\n\n const toOffset =\n align === 'end'\n ? item.end + this.options.scrollPaddingEnd\n : item.start - this.options.scrollPaddingStart\n\n return [\n this.getOffsetForAlignment(toOffset, align, item.size),\n align,\n ] as const\n }\n\n scrollToOffset = (\n toOffset: number,\n { align = 'start', behavior = 'auto' }: ScrollToOffsetOptions = {},\n ) => {\n const offset = this.getOffsetForAlignment(toOffset, align)\n\n const now = this.now()\n this.scrollState = {\n index: null,\n align,\n behavior,\n startedAt: now,\n lastTargetOffset: offset,\n stableFrames: 0,\n }\n\n this._scrollToOffset(offset, { adjustments: undefined, behavior })\n\n this.scheduleScrollReconcile()\n }\n\n scrollToIndex = (\n index: number,\n {\n align: initialAlign = 'auto',\n behavior = 'auto',\n }: ScrollToIndexOptions = {},\n ) => {\n index = Math.max(0, Math.min(index, this.options.count - 1))\n\n const offsetInfo = this.getOffsetForIndex(index, initialAlign)\n if (!offsetInfo) {\n return\n }\n const [offset, align] = offsetInfo\n\n const now = this.now()\n this.scrollState = {\n index,\n align,\n behavior,\n startedAt: now,\n lastTargetOffset: offset,\n stableFrames: 0,\n }\n\n this._scrollToOffset(offset, { adjustments: undefined, behavior })\n\n this.scheduleScrollReconcile()\n }\n\n scrollBy = (\n delta: number,\n { behavior = 'auto' }: ScrollToOffsetOptions = {},\n ) => {\n const offset = this.getScrollOffset() + delta\n const now = this.now()\n\n this.scrollState = {\n index: null,\n align: 'start',\n behavior,\n startedAt: now,\n lastTargetOffset: offset,\n stableFrames: 0,\n }\n\n this._scrollToOffset(offset, { adjustments: undefined, behavior })\n\n this.scheduleScrollReconcile()\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 there is only one lane, use the last measurement's end\n // Otherwise find the maximum end value among all measurements\n if (measurements.length === 0) {\n end = this.options.paddingStart\n } else if (this.options.lanes === 1) {\n end = measurements[measurements.length - 1]?.end ?? 0\n } else {\n const endByLane = Array<number | null>(this.options.lanes).fill(null)\n let endIndex = measurements.length - 1\n while (endIndex >= 0 && endByLane.some((val) => val === null)) {\n const item = measurements[endIndex]!\n if (endByLane[item.lane] === null) {\n endByLane[item.lane] = item.end\n }\n\n endIndex--\n }\n\n end = Math.max(...endByLane.filter((val): val is number => val !== null))\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.laneAssignments = new Map() // Clear lane cache for full re-layout\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 lanes,\n}: {\n measurements: Array<VirtualItem>\n outerSize: number\n scrollOffset: number\n lanes: number\n}) {\n const lastIndex = measurements.length - 1\n const getOffset = (index: number) => measurements[index]!.start\n\n // handle case when item count is less than or equal to lanes\n if (measurements.length <= lanes) {\n return {\n startIndex: 0,\n endIndex: lastIndex,\n }\n }\n\n let startIndex = findNearestBinarySearch(\n 0,\n lastIndex,\n getOffset,\n scrollOffset,\n )\n let endIndex = startIndex\n\n if (lanes === 1) {\n while (\n endIndex < lastIndex &&\n measurements[endIndex]!.end < scrollOffset + outerSize\n ) {\n endIndex++\n }\n } else if (lanes > 1) {\n // Expand forward until we include the visible items from all lanes\n // which are closer to the end of the virtualizer window\n const endPerLane = Array(lanes).fill(0)\n while (\n endIndex < lastIndex &&\n endPerLane.some((pos) => pos < scrollOffset + outerSize)\n ) {\n const item = measurements[endIndex]!\n endPerLane[item.lane] = item.end\n endIndex++\n }\n\n // Expand backward until we include all lanes' visible items\n // closer to the top\n const startPerLane = Array(lanes).fill(scrollOffset + outerSize)\n while (startIndex >= 0 && startPerLane.some((pos) => pos >= scrollOffset)) {\n const item = measurements[startIndex]!\n startPerLane[item.lane] = item.start\n startIndex--\n }\n\n // Align startIndex to the beginning of its lane\n startIndex = Math.max(0, startIndex - (startIndex % lanes))\n // Align endIndex to the end of its lane\n endIndex = Math.min(lastIndex, endIndex + (lanes - 1 - (endIndex % lanes)))\n }\n\n return { startIndex, endIndex }\n}\n"],"names":["debounce","opts","memo","key","notUndefined","approxEqual"],"mappings":"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"}
package/dist/esm/index.js CHANGED
@@ -214,7 +214,6 @@ class Virtualizer {
214
214
  const index = this.indexFromElement(node);
215
215
  if (!node.isConnected) {
216
216
  this.observer.unobserve(node);
217
- this.elementsCache.delete(this.options.getItemKey(index));
218
217
  return;
219
218
  }
220
219
  if (this.shouldMeasureDuringScroll(index)) {
@@ -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' | 'instant'\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\nconst getRect = (element: HTMLElement): Rect => {\n const { offsetWidth, offsetHeight } = element\n return { width: offsetWidth, height: offsetHeight }\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(getRect(element as unknown as HTMLElement))\n\n if (!targetWindow.ResizeObserver) {\n return () => {}\n }\n\n const observer = new targetWindow.ResizeObserver((entries) => {\n const run = () => {\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(getRect(element as unknown as HTMLElement))\n }\n\n instance.options.useAnimationFrameWithResizeObserver\n ? requestAnimationFrame(run)\n : run()\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\n element.addEventListener('scroll', handler, addEventListenerOptions)\n const registerScrollendEvent =\n instance.options.useScrollendEvent && supportsScrollend\n if (registerScrollendEvent) {\n element.addEventListener('scrollend', endHandler, addEventListenerOptions)\n }\n return () => {\n element.removeEventListener('scroll', handler)\n if (registerScrollendEvent) {\n element.removeEventListener('scrollend', endHandler)\n }\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\n element.addEventListener('scroll', handler, addEventListenerOptions)\n const registerScrollendEvent =\n instance.options.useScrollendEvent && supportsScrollend\n if (registerScrollendEvent) {\n element.addEventListener('scrollend', endHandler, addEventListenerOptions)\n }\n return () => {\n element.removeEventListener('scroll', handler)\n if (registerScrollendEvent) {\n element.removeEventListener('scrollend', endHandler)\n }\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\n return (element as unknown as HTMLElement)[\n instance.options.horizontal ? 'offsetWidth' : 'offsetHeight'\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 useAnimationFrameWithResizeObserver?: boolean\n}\n\ntype ScrollState = {\n // what we want\n index: number | null\n align: ScrollAlignment\n behavior: ScrollBehavior\n\n // lifecycle\n startedAt: number\n\n // target tracking\n lastTargetOffset: number\n\n // settling\n stableFrames: number\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 scrollState: ScrollState | null = null\n measurementsCache: Array<VirtualItem> = []\n private itemSizeCache = new Map<Key, number>()\n private laneAssignments = new Map<number, number>() // index → lane cache\n private pendingMeasuredCacheIndexes: Array<number> = []\n private prevLanes: number | undefined = undefined\n private lanesChangedFlag = false\n private lanesSettling = false\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 now = () => this.targetWindow?.performance?.now?.() ?? Date.now()\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 const run = () => {\n const node = entry.target as TItemElement\n const index = this.indexFromElement(node)\n\n if (!node.isConnected) {\n this.observer.unobserve(node)\n this.elementsCache.delete(this.options.getItemKey(index))\n return\n }\n\n if (this.shouldMeasureDuringScroll(index)) {\n this.resizeItem(\n index,\n this.options.measureElement(node, entry, this),\n )\n }\n }\n this.options.useAnimationFrameWithResizeObserver\n ? requestAnimationFrame(run)\n : run()\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: false,\n useAnimationFrameWithResizeObserver: 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 if (this.rafId != null && this.targetWindow) {\n this.targetWindow.cancelAnimationFrame(this.rafId)\n this.rafId = null\n }\n this.scrollState = null\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.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 if (this.scrollState) {\n this.scheduleScrollReconcile()\n }\n this.maybeNotify()\n }),\n )\n\n this._scrollToOffset(this.getScrollOffset(), {\n adjustments: undefined,\n behavior: undefined,\n })\n }\n }\n\n private rafId: number | null = null\n private scheduleScrollReconcile() {\n if (!this.targetWindow) {\n this.scrollState = null\n return\n }\n if (this.rafId != null) return\n this.rafId = this.targetWindow.requestAnimationFrame(() => {\n this.rafId = null\n this.reconcileScroll()\n })\n }\n private reconcileScroll() {\n if (!this.scrollState) return\n\n const el = this.scrollElement\n if (!el) return\n\n // Safety valve: bail out if reconciliation has been running too long\n const MAX_RECONCILE_MS = 5000\n if (this.now() - this.scrollState.startedAt > MAX_RECONCILE_MS) {\n this.scrollState = null\n return\n }\n\n const offsetInfo =\n this.scrollState.index != null\n ? this.getOffsetForIndex(this.scrollState.index, this.scrollState.align)\n : undefined\n const targetOffset = offsetInfo\n ? offsetInfo[0]\n : this.scrollState.lastTargetOffset\n\n // Require one stable frame where target matches scroll offset.\n // approxEqual() already tolerates minor fluctuations, so one frame is sufficient\n // to confirm scroll has reached its target without premature cleanup.\n const STABLE_FRAMES = 1\n\n const targetChanged = targetOffset !== this.scrollState.lastTargetOffset\n\n if (!targetChanged && approxEqual(targetOffset, this.getScrollOffset())) {\n this.scrollState.stableFrames++\n if (this.scrollState.stableFrames >= STABLE_FRAMES) {\n this.scrollState = null\n return\n }\n } else {\n this.scrollState.stableFrames = 0\n\n if (targetChanged) {\n this.scrollState.lastTargetOffset = targetOffset\n // Switch to 'auto' behavior once measurements cause target to change\n // We want to jump directly to the correct position, not smoothly animate to it\n this.scrollState.behavior = 'auto'\n\n this._scrollToOffset(targetOffset, {\n adjustments: undefined,\n behavior: 'auto',\n })\n }\n }\n\n // Always reschedule while scrollState is active to guarantee\n // the safety valve timeout runs even if no scroll events fire\n // (e.g. no-op scrollToFn, detached element)\n this.scheduleScrollReconcile()\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 this.options.lanes,\n ],\n (count, paddingStart, scrollMargin, getItemKey, enabled, lanes) => {\n const lanesChanged =\n this.prevLanes !== undefined && this.prevLanes !== lanes\n\n if (lanesChanged) {\n // Set flag for getMeasurements to handle\n this.lanesChangedFlag = true\n }\n\n this.prevLanes = lanes\n this.pendingMeasuredCacheIndexes = []\n\n return {\n count,\n paddingStart,\n scrollMargin,\n getItemKey,\n enabled,\n lanes,\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, lanes },\n itemSizeCache,\n ) => {\n if (!enabled) {\n this.measurementsCache = []\n this.itemSizeCache.clear()\n this.laneAssignments.clear()\n return []\n }\n\n // Clean up stale lane cache entries when count decreases\n if (this.laneAssignments.size > count) {\n for (const index of this.laneAssignments.keys()) {\n if (index >= count) {\n this.laneAssignments.delete(index)\n }\n }\n }\n\n // ✅ Force complete recalculation when lanes change\n if (this.lanesChangedFlag) {\n this.lanesChangedFlag = false // Reset immediately\n this.lanesSettling = true // Start settling period\n this.measurementsCache = []\n this.itemSizeCache.clear()\n this.laneAssignments.clear() // Clear lane cache for new lane count\n // Clear pending indexes to force min = 0\n this.pendingMeasuredCacheIndexes = []\n }\n\n // Don't restore from initialMeasurementsCache during lane changes\n // as it contains stale lane assignments from the previous lane count\n if (this.measurementsCache.length === 0 && !this.lanesSettling) {\n this.measurementsCache = this.options.initialMeasurementsCache\n this.measurementsCache.forEach((item) => {\n this.itemSizeCache.set(item.key, item.size)\n })\n }\n\n // ✅ During lanes settling, ignore pendingMeasuredCacheIndexes to prevent repositioning\n const min = this.lanesSettling\n ? 0\n : this.pendingMeasuredCacheIndexes.length > 0\n ? Math.min(...this.pendingMeasuredCacheIndexes)\n : 0\n this.pendingMeasuredCacheIndexes = []\n\n // ✅ End settling period when cache is fully built\n if (this.lanesSettling && this.measurementsCache.length === count) {\n this.lanesSettling = false\n }\n\n const measurements = this.measurementsCache.slice(0, min)\n\n // ✅ Performance: Track last item index per lane for O(1) lookup\n const laneLastIndex: Array<number | undefined> = new Array(lanes).fill(\n undefined,\n )\n\n // Initialize from existing measurements (before min)\n for (let m = 0; m < min; m++) {\n const item = measurements[m]\n if (item) {\n laneLastIndex[item.lane] = m\n }\n }\n\n for (let i = min; i < count; i++) {\n const key = getItemKey(i)\n\n // Check for cached lane assignment\n const cachedLane = this.laneAssignments.get(i)\n let lane: number\n let start: number\n\n if (cachedLane !== undefined && this.options.lanes > 1) {\n // Use cached lane - O(1) lookup for previous item in same lane\n lane = cachedLane\n const prevIndex = laneLastIndex[lane]\n const prevInLane =\n prevIndex !== undefined ? measurements[prevIndex] : undefined\n start = prevInLane\n ? prevInLane.end + this.options.gap\n : paddingStart + scrollMargin\n } else {\n // No cache - use original logic (find shortest lane)\n const furthestMeasurement =\n this.options.lanes === 1\n ? measurements[i - 1]\n : this.getFurthestMeasurement(measurements, i)\n\n start = furthestMeasurement\n ? furthestMeasurement.end + this.options.gap\n : paddingStart + scrollMargin\n\n lane = furthestMeasurement\n ? furthestMeasurement.lane\n : i % this.options.lanes\n\n // Cache the lane assignment\n if (this.options.lanes > 1) {\n this.laneAssignments.set(i, lane)\n }\n }\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 measurements[i] = {\n index: i,\n start,\n size,\n end,\n key,\n lane,\n }\n\n // ✅ Performance: Update lane's last item index\n laneLastIndex[lane] = i\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 () => [\n this.getMeasurements(),\n this.getSize(),\n this.getScrollOffset(),\n this.options.lanes,\n ],\n (measurements, outerSize, scrollOffset, lanes) => {\n return (this.range =\n measurements.length > 0 && outerSize > 0\n ? calculateRange({\n measurements,\n outerSize,\n scrollOffset,\n lanes,\n })\n : null)\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'calculateRange',\n debug: () => this.options.debug,\n },\n )\n\n getVirtualIndexes = memo(\n () => {\n let startIndex: number | null = null\n let endIndex: number | null = null\n const range = this.calculateRange()\n if (range) {\n startIndex = range.startIndex\n endIndex = range.endIndex\n }\n this.maybeNotify.updateDeps([this.isScrolling, startIndex, endIndex])\n return [\n this.options.rangeExtractor,\n this.options.overscan,\n this.options.count,\n startIndex,\n endIndex,\n ]\n },\n (rangeExtractor, overscan, count, startIndex, endIndex) => {\n return startIndex === null || endIndex === null\n ? []\n : rangeExtractor({\n startIndex,\n endIndex,\n overscan,\n count,\n })\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'getVirtualIndexes',\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 /**\n * Determines if an item at the given index should be measured during smooth scroll.\n * During smooth scroll, only items within a buffer range around the target are measured\n * to prevent items far from the target from pushing it away.\n */\n private shouldMeasureDuringScroll = (index: number): boolean => {\n // No scroll state or not smooth scroll - always allow measurements\n if (!this.scrollState || this.scrollState.behavior !== 'smooth') {\n return true\n }\n\n const scrollIndex =\n this.scrollState.index ??\n this.getVirtualItemForOffset(this.scrollState.lastTargetOffset)?.index\n\n if (scrollIndex !== undefined && this.range) {\n // Allow measurements within a buffer range around the scroll target\n const bufferSize = Math.max(\n this.options.overscan,\n Math.ceil((this.range.endIndex - this.range.startIndex) / 2),\n )\n const minIndex = Math.max(0, scrollIndex - bufferSize)\n const maxIndex = Math.min(\n this.options.count - 1,\n scrollIndex + bufferSize,\n )\n return index >= minIndex && index <= maxIndex\n }\n\n return true\n }\n\n measureElement = (node: TItemElement | null) => {\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 const index = this.indexFromElement(node)\n const key = this.options.getItemKey(index)\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 // Sync-measure when idle (initial render) or during programmatic scrolling\n // (scrollToIndex/scrollToOffset) where reconcileScroll needs sizes in the same frame.\n // During normal user scrolling, skip sync measurement — the RO callback handles it async.\n if (\n (!this.isScrolling || this.scrollState) &&\n this.shouldMeasureDuringScroll(index)\n ) {\n this.resizeItem(index, this.options.measureElement(node, undefined, this))\n }\n }\n\n resizeItem = (index: number, size: number) => {\n const item = this.measurementsCache[index]\n if (!item) 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.scrollState?.behavior !== 'smooth' &&\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 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 getVirtualItems = memo(\n () => [this.getVirtualIndexes(), 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 private getMaxScrollOffset = () => {\n if (!this.scrollElement) return 0\n\n if ('scrollHeight' in this.scrollElement) {\n // Element\n return this.options.horizontal\n ? this.scrollElement.scrollWidth - this.scrollElement.clientWidth\n : this.scrollElement.scrollHeight - this.scrollElement.clientHeight\n } else {\n // Window\n const doc = this.scrollElement.document.documentElement\n return this.options.horizontal\n ? doc.scrollWidth - this.scrollElement.innerWidth\n : doc.scrollHeight - this.scrollElement.innerHeight\n }\n }\n\n getOffsetForAlignment = (\n toOffset: number,\n align: ScrollAlignment,\n itemSize = 0,\n ) => {\n if (!this.scrollElement) return 0\n\n const size = this.getSize()\n const scrollOffset = this.getScrollOffset()\n\n if (align === 'auto') {\n align = toOffset >= scrollOffset + size ? 'end' : 'start'\n }\n\n if (align === 'center') {\n // When aligning to a particular item (e.g. with scrollToIndex),\n // adjust offset by the size of the item to center on the item\n toOffset += (itemSize - size) / 2\n } else if (align === 'end') {\n toOffset -= size\n }\n\n const maxOffset = this.getMaxScrollOffset()\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 size = this.getSize()\n const scrollOffset = this.getScrollOffset()\n\n const item = this.measurementsCache[index]\n if (!item) return\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 // For the last item with 'end' alignment, use browser's actual max scroll\n // to account for borders/padding that aren't in our measurements\n if (align === 'end' && index === this.options.count - 1) {\n return [this.getMaxScrollOffset(), align] as const\n }\n\n const toOffset =\n align === 'end'\n ? item.end + this.options.scrollPaddingEnd\n : item.start - this.options.scrollPaddingStart\n\n return [\n this.getOffsetForAlignment(toOffset, align, item.size),\n align,\n ] as const\n }\n\n scrollToOffset = (\n toOffset: number,\n { align = 'start', behavior = 'auto' }: ScrollToOffsetOptions = {},\n ) => {\n const offset = this.getOffsetForAlignment(toOffset, align)\n\n const now = this.now()\n this.scrollState = {\n index: null,\n align,\n behavior,\n startedAt: now,\n lastTargetOffset: offset,\n stableFrames: 0,\n }\n\n this._scrollToOffset(offset, { adjustments: undefined, behavior })\n\n this.scheduleScrollReconcile()\n }\n\n scrollToIndex = (\n index: number,\n {\n align: initialAlign = 'auto',\n behavior = 'auto',\n }: ScrollToIndexOptions = {},\n ) => {\n index = Math.max(0, Math.min(index, this.options.count - 1))\n\n const offsetInfo = this.getOffsetForIndex(index, initialAlign)\n if (!offsetInfo) {\n return\n }\n const [offset, align] = offsetInfo\n\n const now = this.now()\n this.scrollState = {\n index,\n align,\n behavior,\n startedAt: now,\n lastTargetOffset: offset,\n stableFrames: 0,\n }\n\n this._scrollToOffset(offset, { adjustments: undefined, behavior })\n\n this.scheduleScrollReconcile()\n }\n\n scrollBy = (\n delta: number,\n { behavior = 'auto' }: ScrollToOffsetOptions = {},\n ) => {\n const offset = this.getScrollOffset() + delta\n const now = this.now()\n\n this.scrollState = {\n index: null,\n align: 'start',\n behavior,\n startedAt: now,\n lastTargetOffset: offset,\n stableFrames: 0,\n }\n\n this._scrollToOffset(offset, { adjustments: undefined, behavior })\n\n this.scheduleScrollReconcile()\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 there is only one lane, use the last measurement's end\n // Otherwise find the maximum end value among all measurements\n if (measurements.length === 0) {\n end = this.options.paddingStart\n } else if (this.options.lanes === 1) {\n end = measurements[measurements.length - 1]?.end ?? 0\n } else {\n const endByLane = Array<number | null>(this.options.lanes).fill(null)\n let endIndex = measurements.length - 1\n while (endIndex >= 0 && endByLane.some((val) => val === null)) {\n const item = measurements[endIndex]!\n if (endByLane[item.lane] === null) {\n endByLane[item.lane] = item.end\n }\n\n endIndex--\n }\n\n end = Math.max(...endByLane.filter((val): val is number => val !== null))\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.laneAssignments = new Map() // Clear lane cache for full re-layout\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 lanes,\n}: {\n measurements: Array<VirtualItem>\n outerSize: number\n scrollOffset: number\n lanes: number\n}) {\n const lastIndex = measurements.length - 1\n const getOffset = (index: number) => measurements[index]!.start\n\n // handle case when item count is less than or equal to lanes\n if (measurements.length <= lanes) {\n return {\n startIndex: 0,\n endIndex: lastIndex,\n }\n }\n\n let startIndex = findNearestBinarySearch(\n 0,\n lastIndex,\n getOffset,\n scrollOffset,\n )\n let endIndex = startIndex\n\n if (lanes === 1) {\n while (\n endIndex < lastIndex &&\n measurements[endIndex]!.end < scrollOffset + outerSize\n ) {\n endIndex++\n }\n } else if (lanes > 1) {\n // Expand forward until we include the visible items from all lanes\n // which are closer to the end of the virtualizer window\n const endPerLane = Array(lanes).fill(0)\n while (\n endIndex < lastIndex &&\n endPerLane.some((pos) => pos < scrollOffset + outerSize)\n ) {\n const item = measurements[endIndex]!\n endPerLane[item.lane] = item.end\n endIndex++\n }\n\n // Expand backward until we include all lanes' visible items\n // closer to the top\n const startPerLane = Array(lanes).fill(scrollOffset + outerSize)\n while (startIndex >= 0 && startPerLane.some((pos) => pos >= scrollOffset)) {\n const item = measurements[startIndex]!\n startPerLane[item.lane] = item.start\n startIndex--\n }\n\n // Align startIndex to the beginning of its lane\n startIndex = Math.max(0, startIndex - (startIndex % lanes))\n // Align endIndex to the end of its lane\n endIndex = Math.min(lastIndex, endIndex + (lanes - 1 - (endIndex % lanes)))\n }\n\n return { startIndex, endIndex }\n}\n"],"names":["opts","key"],"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' | 'instant'\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\nconst getRect = (element: HTMLElement): Rect => {\n const { offsetWidth, offsetHeight } = element\n return { width: offsetWidth, height: offsetHeight }\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(getRect(element as unknown as HTMLElement))\n\n if (!targetWindow.ResizeObserver) {\n return () => {}\n }\n\n const observer = new targetWindow.ResizeObserver((entries) => {\n const run = () => {\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(getRect(element as unknown as HTMLElement))\n }\n\n instance.options.useAnimationFrameWithResizeObserver\n ? requestAnimationFrame(run)\n : run()\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\n element.addEventListener('scroll', handler, addEventListenerOptions)\n const registerScrollendEvent =\n instance.options.useScrollendEvent && supportsScrollend\n if (registerScrollendEvent) {\n element.addEventListener('scrollend', endHandler, addEventListenerOptions)\n }\n return () => {\n element.removeEventListener('scroll', handler)\n if (registerScrollendEvent) {\n element.removeEventListener('scrollend', endHandler)\n }\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\n element.addEventListener('scroll', handler, addEventListenerOptions)\n const registerScrollendEvent =\n instance.options.useScrollendEvent && supportsScrollend\n if (registerScrollendEvent) {\n element.addEventListener('scrollend', endHandler, addEventListenerOptions)\n }\n return () => {\n element.removeEventListener('scroll', handler)\n if (registerScrollendEvent) {\n element.removeEventListener('scrollend', endHandler)\n }\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\n return (element as unknown as HTMLElement)[\n instance.options.horizontal ? 'offsetWidth' : 'offsetHeight'\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 useAnimationFrameWithResizeObserver?: boolean\n}\n\ntype ScrollState = {\n // what we want\n index: number | null\n align: ScrollAlignment\n behavior: ScrollBehavior\n\n // lifecycle\n startedAt: number\n\n // target tracking\n lastTargetOffset: number\n\n // settling\n stableFrames: number\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 scrollState: ScrollState | null = null\n measurementsCache: Array<VirtualItem> = []\n private itemSizeCache = new Map<Key, number>()\n private laneAssignments = new Map<number, number>() // index → lane cache\n private pendingMeasuredCacheIndexes: Array<number> = []\n private prevLanes: number | undefined = undefined\n private lanesChangedFlag = false\n private lanesSettling = false\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 now = () => this.targetWindow?.performance?.now?.() ?? Date.now()\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 const run = () => {\n const node = entry.target as TItemElement\n const index = this.indexFromElement(node)\n\n if (!node.isConnected) {\n this.observer.unobserve(node)\n return\n }\n\n if (this.shouldMeasureDuringScroll(index)) {\n this.resizeItem(\n index,\n this.options.measureElement(node, entry, this),\n )\n }\n }\n this.options.useAnimationFrameWithResizeObserver\n ? requestAnimationFrame(run)\n : run()\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: false,\n useAnimationFrameWithResizeObserver: 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 if (this.rafId != null && this.targetWindow) {\n this.targetWindow.cancelAnimationFrame(this.rafId)\n this.rafId = null\n }\n this.scrollState = null\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.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 if (this.scrollState) {\n this.scheduleScrollReconcile()\n }\n this.maybeNotify()\n }),\n )\n\n this._scrollToOffset(this.getScrollOffset(), {\n adjustments: undefined,\n behavior: undefined,\n })\n }\n }\n\n private rafId: number | null = null\n private scheduleScrollReconcile() {\n if (!this.targetWindow) {\n this.scrollState = null\n return\n }\n if (this.rafId != null) return\n this.rafId = this.targetWindow.requestAnimationFrame(() => {\n this.rafId = null\n this.reconcileScroll()\n })\n }\n private reconcileScroll() {\n if (!this.scrollState) return\n\n const el = this.scrollElement\n if (!el) return\n\n // Safety valve: bail out if reconciliation has been running too long\n const MAX_RECONCILE_MS = 5000\n if (this.now() - this.scrollState.startedAt > MAX_RECONCILE_MS) {\n this.scrollState = null\n return\n }\n\n const offsetInfo =\n this.scrollState.index != null\n ? this.getOffsetForIndex(this.scrollState.index, this.scrollState.align)\n : undefined\n const targetOffset = offsetInfo\n ? offsetInfo[0]\n : this.scrollState.lastTargetOffset\n\n // Require one stable frame where target matches scroll offset.\n // approxEqual() already tolerates minor fluctuations, so one frame is sufficient\n // to confirm scroll has reached its target without premature cleanup.\n const STABLE_FRAMES = 1\n\n const targetChanged = targetOffset !== this.scrollState.lastTargetOffset\n\n if (!targetChanged && approxEqual(targetOffset, this.getScrollOffset())) {\n this.scrollState.stableFrames++\n if (this.scrollState.stableFrames >= STABLE_FRAMES) {\n this.scrollState = null\n return\n }\n } else {\n this.scrollState.stableFrames = 0\n\n if (targetChanged) {\n this.scrollState.lastTargetOffset = targetOffset\n // Switch to 'auto' behavior once measurements cause target to change\n // We want to jump directly to the correct position, not smoothly animate to it\n this.scrollState.behavior = 'auto'\n\n this._scrollToOffset(targetOffset, {\n adjustments: undefined,\n behavior: 'auto',\n })\n }\n }\n\n // Always reschedule while scrollState is active to guarantee\n // the safety valve timeout runs even if no scroll events fire\n // (e.g. no-op scrollToFn, detached element)\n this.scheduleScrollReconcile()\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 this.options.lanes,\n ],\n (count, paddingStart, scrollMargin, getItemKey, enabled, lanes) => {\n const lanesChanged =\n this.prevLanes !== undefined && this.prevLanes !== lanes\n\n if (lanesChanged) {\n // Set flag for getMeasurements to handle\n this.lanesChangedFlag = true\n }\n\n this.prevLanes = lanes\n this.pendingMeasuredCacheIndexes = []\n\n return {\n count,\n paddingStart,\n scrollMargin,\n getItemKey,\n enabled,\n lanes,\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, lanes },\n itemSizeCache,\n ) => {\n if (!enabled) {\n this.measurementsCache = []\n this.itemSizeCache.clear()\n this.laneAssignments.clear()\n return []\n }\n\n // Clean up stale lane cache entries when count decreases\n if (this.laneAssignments.size > count) {\n for (const index of this.laneAssignments.keys()) {\n if (index >= count) {\n this.laneAssignments.delete(index)\n }\n }\n }\n\n // ✅ Force complete recalculation when lanes change\n if (this.lanesChangedFlag) {\n this.lanesChangedFlag = false // Reset immediately\n this.lanesSettling = true // Start settling period\n this.measurementsCache = []\n this.itemSizeCache.clear()\n this.laneAssignments.clear() // Clear lane cache for new lane count\n // Clear pending indexes to force min = 0\n this.pendingMeasuredCacheIndexes = []\n }\n\n // Don't restore from initialMeasurementsCache during lane changes\n // as it contains stale lane assignments from the previous lane count\n if (this.measurementsCache.length === 0 && !this.lanesSettling) {\n this.measurementsCache = this.options.initialMeasurementsCache\n this.measurementsCache.forEach((item) => {\n this.itemSizeCache.set(item.key, item.size)\n })\n }\n\n // ✅ During lanes settling, ignore pendingMeasuredCacheIndexes to prevent repositioning\n const min = this.lanesSettling\n ? 0\n : this.pendingMeasuredCacheIndexes.length > 0\n ? Math.min(...this.pendingMeasuredCacheIndexes)\n : 0\n this.pendingMeasuredCacheIndexes = []\n\n // ✅ End settling period when cache is fully built\n if (this.lanesSettling && this.measurementsCache.length === count) {\n this.lanesSettling = false\n }\n\n const measurements = this.measurementsCache.slice(0, min)\n\n // ✅ Performance: Track last item index per lane for O(1) lookup\n const laneLastIndex: Array<number | undefined> = new Array(lanes).fill(\n undefined,\n )\n\n // Initialize from existing measurements (before min)\n for (let m = 0; m < min; m++) {\n const item = measurements[m]\n if (item) {\n laneLastIndex[item.lane] = m\n }\n }\n\n for (let i = min; i < count; i++) {\n const key = getItemKey(i)\n\n // Check for cached lane assignment\n const cachedLane = this.laneAssignments.get(i)\n let lane: number\n let start: number\n\n if (cachedLane !== undefined && this.options.lanes > 1) {\n // Use cached lane - O(1) lookup for previous item in same lane\n lane = cachedLane\n const prevIndex = laneLastIndex[lane]\n const prevInLane =\n prevIndex !== undefined ? measurements[prevIndex] : undefined\n start = prevInLane\n ? prevInLane.end + this.options.gap\n : paddingStart + scrollMargin\n } else {\n // No cache - use original logic (find shortest lane)\n const furthestMeasurement =\n this.options.lanes === 1\n ? measurements[i - 1]\n : this.getFurthestMeasurement(measurements, i)\n\n start = furthestMeasurement\n ? furthestMeasurement.end + this.options.gap\n : paddingStart + scrollMargin\n\n lane = furthestMeasurement\n ? furthestMeasurement.lane\n : i % this.options.lanes\n\n // Cache the lane assignment\n if (this.options.lanes > 1) {\n this.laneAssignments.set(i, lane)\n }\n }\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 measurements[i] = {\n index: i,\n start,\n size,\n end,\n key,\n lane,\n }\n\n // ✅ Performance: Update lane's last item index\n laneLastIndex[lane] = i\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 () => [\n this.getMeasurements(),\n this.getSize(),\n this.getScrollOffset(),\n this.options.lanes,\n ],\n (measurements, outerSize, scrollOffset, lanes) => {\n return (this.range =\n measurements.length > 0 && outerSize > 0\n ? calculateRange({\n measurements,\n outerSize,\n scrollOffset,\n lanes,\n })\n : null)\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'calculateRange',\n debug: () => this.options.debug,\n },\n )\n\n getVirtualIndexes = memo(\n () => {\n let startIndex: number | null = null\n let endIndex: number | null = null\n const range = this.calculateRange()\n if (range) {\n startIndex = range.startIndex\n endIndex = range.endIndex\n }\n this.maybeNotify.updateDeps([this.isScrolling, startIndex, endIndex])\n return [\n this.options.rangeExtractor,\n this.options.overscan,\n this.options.count,\n startIndex,\n endIndex,\n ]\n },\n (rangeExtractor, overscan, count, startIndex, endIndex) => {\n return startIndex === null || endIndex === null\n ? []\n : rangeExtractor({\n startIndex,\n endIndex,\n overscan,\n count,\n })\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'getVirtualIndexes',\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 /**\n * Determines if an item at the given index should be measured during smooth scroll.\n * During smooth scroll, only items within a buffer range around the target are measured\n * to prevent items far from the target from pushing it away.\n */\n private shouldMeasureDuringScroll = (index: number): boolean => {\n // No scroll state or not smooth scroll - always allow measurements\n if (!this.scrollState || this.scrollState.behavior !== 'smooth') {\n return true\n }\n\n const scrollIndex =\n this.scrollState.index ??\n this.getVirtualItemForOffset(this.scrollState.lastTargetOffset)?.index\n\n if (scrollIndex !== undefined && this.range) {\n // Allow measurements within a buffer range around the scroll target\n const bufferSize = Math.max(\n this.options.overscan,\n Math.ceil((this.range.endIndex - this.range.startIndex) / 2),\n )\n const minIndex = Math.max(0, scrollIndex - bufferSize)\n const maxIndex = Math.min(\n this.options.count - 1,\n scrollIndex + bufferSize,\n )\n return index >= minIndex && index <= maxIndex\n }\n\n return true\n }\n\n measureElement = (node: TItemElement | null) => {\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 const index = this.indexFromElement(node)\n const key = this.options.getItemKey(index)\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 // Sync-measure when idle (initial render) or during programmatic scrolling\n // (scrollToIndex/scrollToOffset) where reconcileScroll needs sizes in the same frame.\n // During normal user scrolling, skip sync measurement — the RO callback handles it async.\n if (\n (!this.isScrolling || this.scrollState) &&\n this.shouldMeasureDuringScroll(index)\n ) {\n this.resizeItem(index, this.options.measureElement(node, undefined, this))\n }\n }\n\n resizeItem = (index: number, size: number) => {\n const item = this.measurementsCache[index]\n if (!item) 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.scrollState?.behavior !== 'smooth' &&\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 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 getVirtualItems = memo(\n () => [this.getVirtualIndexes(), 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 private getMaxScrollOffset = () => {\n if (!this.scrollElement) return 0\n\n if ('scrollHeight' in this.scrollElement) {\n // Element\n return this.options.horizontal\n ? this.scrollElement.scrollWidth - this.scrollElement.clientWidth\n : this.scrollElement.scrollHeight - this.scrollElement.clientHeight\n } else {\n // Window\n const doc = this.scrollElement.document.documentElement\n return this.options.horizontal\n ? doc.scrollWidth - this.scrollElement.innerWidth\n : doc.scrollHeight - this.scrollElement.innerHeight\n }\n }\n\n getOffsetForAlignment = (\n toOffset: number,\n align: ScrollAlignment,\n itemSize = 0,\n ) => {\n if (!this.scrollElement) return 0\n\n const size = this.getSize()\n const scrollOffset = this.getScrollOffset()\n\n if (align === 'auto') {\n align = toOffset >= scrollOffset + size ? 'end' : 'start'\n }\n\n if (align === 'center') {\n // When aligning to a particular item (e.g. with scrollToIndex),\n // adjust offset by the size of the item to center on the item\n toOffset += (itemSize - size) / 2\n } else if (align === 'end') {\n toOffset -= size\n }\n\n const maxOffset = this.getMaxScrollOffset()\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 size = this.getSize()\n const scrollOffset = this.getScrollOffset()\n\n const item = this.measurementsCache[index]\n if (!item) return\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 // For the last item with 'end' alignment, use browser's actual max scroll\n // to account for borders/padding that aren't in our measurements\n if (align === 'end' && index === this.options.count - 1) {\n return [this.getMaxScrollOffset(), align] as const\n }\n\n const toOffset =\n align === 'end'\n ? item.end + this.options.scrollPaddingEnd\n : item.start - this.options.scrollPaddingStart\n\n return [\n this.getOffsetForAlignment(toOffset, align, item.size),\n align,\n ] as const\n }\n\n scrollToOffset = (\n toOffset: number,\n { align = 'start', behavior = 'auto' }: ScrollToOffsetOptions = {},\n ) => {\n const offset = this.getOffsetForAlignment(toOffset, align)\n\n const now = this.now()\n this.scrollState = {\n index: null,\n align,\n behavior,\n startedAt: now,\n lastTargetOffset: offset,\n stableFrames: 0,\n }\n\n this._scrollToOffset(offset, { adjustments: undefined, behavior })\n\n this.scheduleScrollReconcile()\n }\n\n scrollToIndex = (\n index: number,\n {\n align: initialAlign = 'auto',\n behavior = 'auto',\n }: ScrollToIndexOptions = {},\n ) => {\n index = Math.max(0, Math.min(index, this.options.count - 1))\n\n const offsetInfo = this.getOffsetForIndex(index, initialAlign)\n if (!offsetInfo) {\n return\n }\n const [offset, align] = offsetInfo\n\n const now = this.now()\n this.scrollState = {\n index,\n align,\n behavior,\n startedAt: now,\n lastTargetOffset: offset,\n stableFrames: 0,\n }\n\n this._scrollToOffset(offset, { adjustments: undefined, behavior })\n\n this.scheduleScrollReconcile()\n }\n\n scrollBy = (\n delta: number,\n { behavior = 'auto' }: ScrollToOffsetOptions = {},\n ) => {\n const offset = this.getScrollOffset() + delta\n const now = this.now()\n\n this.scrollState = {\n index: null,\n align: 'start',\n behavior,\n startedAt: now,\n lastTargetOffset: offset,\n stableFrames: 0,\n }\n\n this._scrollToOffset(offset, { adjustments: undefined, behavior })\n\n this.scheduleScrollReconcile()\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 there is only one lane, use the last measurement's end\n // Otherwise find the maximum end value among all measurements\n if (measurements.length === 0) {\n end = this.options.paddingStart\n } else if (this.options.lanes === 1) {\n end = measurements[measurements.length - 1]?.end ?? 0\n } else {\n const endByLane = Array<number | null>(this.options.lanes).fill(null)\n let endIndex = measurements.length - 1\n while (endIndex >= 0 && endByLane.some((val) => val === null)) {\n const item = measurements[endIndex]!\n if (endByLane[item.lane] === null) {\n endByLane[item.lane] = item.end\n }\n\n endIndex--\n }\n\n end = Math.max(...endByLane.filter((val): val is number => val !== null))\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.laneAssignments = new Map() // Clear lane cache for full re-layout\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 lanes,\n}: {\n measurements: Array<VirtualItem>\n outerSize: number\n scrollOffset: number\n lanes: number\n}) {\n const lastIndex = measurements.length - 1\n const getOffset = (index: number) => measurements[index]!.start\n\n // handle case when item count is less than or equal to lanes\n if (measurements.length <= lanes) {\n return {\n startIndex: 0,\n endIndex: lastIndex,\n }\n }\n\n let startIndex = findNearestBinarySearch(\n 0,\n lastIndex,\n getOffset,\n scrollOffset,\n )\n let endIndex = startIndex\n\n if (lanes === 1) {\n while (\n endIndex < lastIndex &&\n measurements[endIndex]!.end < scrollOffset + outerSize\n ) {\n endIndex++\n }\n } else if (lanes > 1) {\n // Expand forward until we include the visible items from all lanes\n // which are closer to the end of the virtualizer window\n const endPerLane = Array(lanes).fill(0)\n while (\n endIndex < lastIndex &&\n endPerLane.some((pos) => pos < scrollOffset + outerSize)\n ) {\n const item = measurements[endIndex]!\n endPerLane[item.lane] = item.end\n endIndex++\n }\n\n // Expand backward until we include all lanes' visible items\n // closer to the top\n const startPerLane = Array(lanes).fill(scrollOffset + outerSize)\n while (startIndex >= 0 && startPerLane.some((pos) => pos >= scrollOffset)) {\n const item = measurements[startIndex]!\n startPerLane[item.lane] = item.start\n startIndex--\n }\n\n // Align startIndex to the beginning of its lane\n startIndex = Math.max(0, startIndex - (startIndex % lanes))\n // Align endIndex to the end of its lane\n endIndex = Math.min(lastIndex, endIndex + (lanes - 1 - (endIndex % lanes)))\n }\n\n return { startIndex, endIndex }\n}\n"],"names":["opts","key"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/virtual-core",
3
- "version": "3.13.22",
3
+ "version": "3.13.23",
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
@@ -414,7 +414,6 @@ export class Virtualizer<
414
414
 
415
415
  if (!node.isConnected) {
416
416
  this.observer.unobserve(node)
417
- this.elementsCache.delete(this.options.getItemKey(index))
418
417
  return
419
418
  }
420
419