{"version":3,"file":"index.cjs","sources":["../../src/index.ts"],"sourcesContent":["import { createLazyMeasurementsView } from './lazy-measurements'\nimport { approxEqual, debounce, memo, notUndefined } from './utils'\n\n// Browser-aware iOS detection. Programmatic `scrollTo`/`scrollTop` writes\n// during a momentum-scroll cancel the momentum on iOS WebKit, so we defer\n// scroll-position adjustments triggered by mid-scroll resizes until the\n// scroll settles. SSR-safe (returns false when navigator is unavailable).\nlet _isIOSResult: boolean | undefined\nconst isIOSWebKit = (): boolean => {\n if (_isIOSResult !== undefined) return _isIOSResult\n if (typeof navigator === 'undefined') return (_isIOSResult = false)\n if (/iP(hone|od|ad)/.test(navigator.userAgent)) return (_isIOSResult = true)\n // iPadOS 13+ reports as MacIntel; touch-points distinguishes it from desktop.\n const mtp = (navigator as Navigator & { maxTouchPoints?: number })\n .maxTouchPoints\n return (_isIOSResult =\n navigator.platform === 'MacIntel' && mtp !== undefined && mtp > 0)\n}\n\n// Test hook: reset the iOS detection cache. Not exported.\nexport const _resetIOSDetectionForTests = () => {\n _isIOSResult = undefined\n}\n\nexport { approxEqual, debounce, memo, notUndefined } from './utils'\nexport type { NoInfer, PartialKeys } from './utils'\n\n//\n\ntype ScrollDirection = 'forward' | 'backward'\n\ntype ScrollAlignment = 'start' | 'center' | 'end' | 'auto'\n\ntype ScrollBehavior = 'auto' | 'smooth' | 'instant'\n\ntype ScrollAnchor = 'start' | 'end'\n\ntype FollowOnAppend = boolean | ScrollBehavior\n\nexport interface ScrollToOptions {\n align?: ScrollAlignment\n behavior?: ScrollBehavior\n}\n\ntype ScrollToOffsetOptions = ScrollToOptions\n\ntype ScrollToIndexOptions = ScrollToOptions\n\ntype ScrollToEndOptions = Pick\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 const len = end - start + 1\n\n const arr = new Array(len)\n for (let i = 0; i < len; i++) {\n arr[i] = start + i\n }\n return arr\n}\n\nexport const observeElementRect = (\n instance: Virtualizer,\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,\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\n// Shared core: both element and window variants attach scroll/scrollend\n// listeners with the same lifecycle; they only differ in how to read the\n// current offset from the scroll target.\nconst observeOffset = (\n instance: Virtualizer,\n cb: ObserveOffsetCallBack,\n readOffset: (target: T) => number,\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 registerScrollendEvent =\n instance.options.useScrollendEvent && supportsScrollend\n\n let offset = 0\n const fallback = registerScrollendEvent\n ? null\n : debounce(\n targetWindow,\n () => cb(offset, false),\n instance.options.isScrollingResetDelay,\n )\n\n const createHandler = (isScrolling: boolean) => () => {\n offset = readOffset(element)\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 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 observeElementOffset = (\n instance: Virtualizer,\n cb: ObserveOffsetCallBack,\n) =>\n observeOffset(instance, cb, (el) => {\n const { horizontal, isRtl } = instance.options\n return horizontal ? el.scrollLeft * ((isRtl && -1) || 1) : el.scrollTop\n })\n\nexport const observeWindowOffset = (\n instance: Virtualizer,\n cb: ObserveOffsetCallBack,\n) =>\n observeOffset(instance, cb, (win) =>\n instance.options.horizontal ? win.scrollX : win.scrollY,\n )\n\nexport const measureElement = (\n element: TItemElement,\n entry: ResizeObserverEntry | undefined,\n instance: Virtualizer,\n) => {\n // When useCachedMeasurements is enabled, return the cached size\n // (or estimateSize as fallback) instead of measuring the DOM.\n if (instance.options.useCachedMeasurements) {\n const index = instance.indexFromElement(element)\n const key = instance.options.getItemKey(index)\n return (\n instance.itemSizeCache.get(key) ?? instance.options.estimateSize(index)\n )\n }\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 // When called without a ResizeObserverEntry (sync measurement path),\n // return the previously measured size if available. This avoids a\n // synchronous layout read (offsetWidth/offsetHeight) on re-renders.\n // The ResizeObserver is already observing the element and will deliver\n // the accurate size asynchronously if it changed.\n // Users who need synchronous DOM reads can provide a custom measureElement.\n if (!entry) {\n const index = instance.indexFromElement(element)\n const key = instance.options.getItemKey(index)\n const cachedSize = instance.itemSizeCache.get(key)\n if (cachedSize !== undefined) {\n return cachedSize\n }\n }\n\n return (element as unknown as HTMLElement)[\n instance.options.horizontal ? 'offsetWidth' : 'offsetHeight'\n ]\n}\n\nconst scrollWithAdjustments = (\n offset: number,\n {\n adjustments = 0,\n behavior,\n }: { adjustments?: number; behavior?: ScrollBehavior },\n instance: Virtualizer,\n) => {\n instance.scrollElement?.scrollTo?.({\n [instance.options.horizontal ? 'left' : 'top']: offset + adjustments,\n behavior,\n })\n}\n\nexport const windowScroll: (\n offset: number,\n options: { adjustments?: number; behavior?: ScrollBehavior },\n instance: Virtualizer,\n) => void = scrollWithAdjustments\n\nexport const elementScroll: (\n offset: number,\n options: { adjustments?: number; behavior?: ScrollBehavior },\n instance: Virtualizer,\n) => void = scrollWithAdjustments\n\ntype LaneAssignmentMode = 'estimate' | 'measured'\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,\n ) => void\n observeElementRect: (\n instance: Virtualizer,\n cb: (rect: Rect) => void,\n ) => void | (() => void)\n observeElementOffset: (\n instance: Virtualizer,\n cb: ObserveOffsetCallBack,\n ) => void | (() => void)\n // Optional\n debug?: boolean\n initialRect?: Rect\n onChange?: (\n instance: Virtualizer,\n sync: boolean,\n ) => void\n measureElement?: (\n element: TItemElement,\n entry: ResizeObserverEntry | undefined,\n instance: Virtualizer,\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\n scrollMargin?: number\n gap?: number\n indexAttribute?: string\n initialMeasurementsCache?: Array\n lanes?: number\n anchorTo?: ScrollAnchor\n followOnAppend?: FollowOnAppend\n scrollEndThreshold?: number\n isScrollingResetDelay?: number\n useScrollendEvent?: boolean\n enabled?: boolean\n isRtl?: boolean\n useAnimationFrameWithResizeObserver?: boolean\n laneAssignmentMode?: LaneAssignmentMode\n useCachedMeasurements?: 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\ntype PendingScrollAnchor = [\n key: Key | null,\n offset: number,\n followOnAppend: ScrollBehavior | null,\n anchorDelta: number,\n]\n\nexport class Virtualizer<\n TScrollElement extends Element | Window,\n TItemElement extends Element,\n> {\n private unsubs: Array void)> = []\n options!: Required>\n scrollElement: TScrollElement | null = null\n targetWindow: (Window & typeof globalThis) | null = null\n isScrolling = false\n private scrollState: ScrollState | null = null\n measurementsCache: Array = []\n // Flat backing store for the lanes===1 fast path: [start_0, size_0, start_1, size_1, ...].\n // null until the first single-lane build; reused (and grown) across rebuilds.\n private _flatMeasurements: Float64Array | null = null\n itemSizeCache = new Map()\n private itemSizeCacheVersion = 0\n private laneAssignments = new Map() // index → lane cache\n // Earliest index dirtied since last getMeasurements() rebuild, or null.\n private pendingMin: number | null = null\n private prevLanes: number | undefined = undefined\n private lanesChangedFlag = false\n private lanesSettling = false\n private pendingScrollAnchor: PendingScrollAnchor | null = null\n scrollRect: Rect | null = null\n scrollOffset: number | null = null\n scrollDirection: ScrollDirection | null = null\n private scrollAdjustments = 0\n // Sum of size-change deltas above-viewport that were skipped during\n // iOS momentum scroll (writing scrollTop mid-momentum cancels it).\n // Flushed in a single scrollTo when iOS is fully settled.\n private _iosDeferredAdjustment = 0\n // Touch state. iOS WebKit cancels momentum when scrollTop is written, so\n // we defer adjustments not only during `isScrolling` but also through the\n // touchstart→touchend window (active drag) and a short tail after\n // touchend (early-momentum window — iOS only fires touch events once at\n // the start of momentum, so we use a timer rather than another event).\n private _iosTouching = false\n private _iosJustTouchEnded = false\n private _iosTouchEndTimerId: number | null = null\n // Subpixel reconciliation. Safari (and Chrome/Firefox under certain DPRs)\n // round scrollTop/scrollLeft writes to integer pixels. If we wrote 12345.5\n // but the browser reports back 12346, the next reconcileScroll sees a\n // \"target changed\" and re-fires scrollTo — a feedback loop that the\n // approxEqual(<1.01) tolerance otherwise absorbs as a workaround.\n // By remembering the intended value of our most-recent self-driven\n // scrollTo, we can match the browser's rounded read back to the intended\n // value when the diff is < 1.5 px, distinguishing it from a real user\n // scroll. The +0.5 over Math.abs lets us also absorb the +1 / -1 cases.\n private _intendedScrollOffset: number | null = null\n shouldAdjustScrollPositionOnItemSizeChange:\n | undefined\n | ((\n item: VirtualItem,\n delta: number,\n instance: Virtualizer,\n ) => boolean)\n elementsCache = new Map()\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 // Find the cache entry pointing to this exact node and remove\n // it. We can't call getItemKey(index) here because items may\n // have been removed since this node was rendered — the index\n // could be stale and out-of-bounds in the user's data array\n // (regression test in e2e/.../stale-index.spec.ts, fix #1148).\n // The === comparison naturally handles the React-replaced-\n // a-node-for-the-same-key case: that entry now points to a\n // different node, so this loop won't match.\n for (const [cacheKey, cachedNode] of this.elementsCache) {\n if (cachedNode === node) {\n this.elementsCache.delete(cacheKey)\n break\n }\n }\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) {\n this.setOptions(opts)\n }\n\n setOptions = (opts: VirtualizerOptions) => {\n // Skip `{...defaults, ...opts}` because explicit `undefined` values in\n // opts would override defaults with `undefined`.\n const merged = {\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 anchorTo: 'start',\n followOnAppend: false,\n scrollEndThreshold: 1,\n isScrollingResetDelay: 150,\n enabled: true,\n isRtl: false,\n useScrollendEvent: false,\n useAnimationFrameWithResizeObserver: false,\n laneAssignmentMode: 'estimate',\n useCachedMeasurements: false,\n } as unknown as Required>\n\n for (const key in opts) {\n const v = (opts as any)[key]\n if (v !== undefined) (merged as any)[key] = v\n }\n\n const prevOptions = this.options as\n | Required>\n | undefined\n let anchor: [Key, number] | null = null\n let followOnAppend: ScrollBehavior | null = null\n let edgeKeysChanged = false\n\n if (\n prevOptions !== undefined &&\n prevOptions.enabled &&\n merged.enabled &&\n merged.anchorTo === 'end' &&\n this.scrollElement !== null\n ) {\n const prevCount = prevOptions.count\n const nextCount = merged.count\n const measurements = this.getMeasurements()\n const prevFirstKey =\n prevCount > 0\n ? (measurements[0]?.key ?? prevOptions.getItemKey(0))\n : null\n const prevLastKey =\n prevCount > 0\n ? (measurements[prevCount - 1]?.key ??\n prevOptions.getItemKey(prevCount - 1))\n : null\n const didCountChange = nextCount !== prevCount\n const didEdgeKeysChange =\n didCountChange ||\n (prevCount > 0 &&\n nextCount > 0 &&\n (merged.getItemKey(0) !== prevFirstKey ||\n merged.getItemKey(nextCount - 1) !== prevLastKey))\n\n if (didEdgeKeysChange) {\n edgeKeysChanged = true\n const item =\n prevCount > 0\n ? (this.getVirtualItemForOffset(this.getScrollOffset()) ??\n measurements[0])\n : null\n\n if (item) {\n anchor = [item.key, this.getScrollOffset() - item.start]\n }\n\n const behavior =\n merged.followOnAppend === true\n ? 'auto'\n : merged.followOnAppend || null\n\n if (\n behavior &&\n nextCount > prevCount &&\n this.isAtEnd(prevOptions.scrollEndThreshold) &&\n (prevCount === 0 || merged.getItemKey(nextCount - 1) !== prevLastKey)\n ) {\n followOnAppend = behavior\n }\n }\n }\n\n this.options = merged\n\n // When edge keys changed (prepend, trim, reorder, etc.) the key→index\n // mapping has shifted. Force a full measurement rebuild so the anchor\n // resolution below reads positions from the new layout, not the stale\n // memoised cache. Without this, a stable `getItemKey` reference +\n // unchanged `count` would let getMeasurements() return the old layout.\n if (edgeKeysChanged) {\n this.pendingMin = 0\n this.itemSizeCacheVersion++\n }\n\n // Eagerly adjust scrollOffset so the virtualizer computes the correct\n // visible range during the current render pass — before _willUpdate\n // syncs the DOM scroll position in a layout effect. Without this,\n // the virtualizer would render the wrong items for one frame (the\n // estimate-based positions are stale) and then correct in the next\n // frame, producing a visible \"jump\" on prepend with dynamic sizes.\n let anchorResolved = false\n let anchorDelta = 0\n if (anchor && this.scrollOffset !== null) {\n const [anchorKey, anchorOffset] = anchor\n const newMeasurements = this.getMeasurements()\n const { count, getItemKey } = this.options\n let idx = 0\n while (idx < count && getItemKey(idx) !== anchorKey) {\n idx++\n }\n if (idx < count) {\n const anchorItem = newMeasurements[idx]\n if (anchorItem) {\n const newOffset = anchorItem.start + anchorOffset\n if (newOffset !== this.scrollOffset) {\n anchorDelta = newOffset - this.scrollOffset\n this.scrollOffset = newOffset\n anchorResolved = true\n }\n }\n }\n }\n\n if (anchorResolved || followOnAppend) {\n this.pendingScrollAnchor = [\n anchorResolved ? anchor![0] : null,\n anchorResolved ? anchor![1] : 0,\n followOnAppend,\n anchorDelta,\n ]\n }\n }\n\n private notify = (sync: boolean) => {\n this.options.onChange?.(this, sync)\n }\n\n private applyScrollAdjustment(delta: number, behavior?: ScrollBehavior) {\n if (delta === 0) return\n\n if (process.env.NODE_ENV !== 'production' && this.options.debug) {\n console.info('correction', delta)\n }\n\n if (\n isIOSWebKit() &&\n (this.isScrolling || this._iosTouching || this._iosJustTouchEnded)\n ) {\n this._iosDeferredAdjustment += delta\n } else {\n this._scrollToOffset(this.getScrollOffset(), {\n adjustments: (this.scrollAdjustments += delta),\n behavior,\n })\n // Eagerly carry the intended target in `scrollOffset` so callers that\n // read it before the next scroll event — notably the next `resizeItem`\n // tick's `getVirtualDistanceFromEnd()` / `wasAtEnd` check — see the\n // post-adjustment position even when the DOM `scrollTop` write was\n // clamped because the consumer hasn't grown the sizer yet (`notify()`\n // runs after this in `resizeItem`). Same idea as the eager\n // `scrollOffset` adjustment for prepend in `setOptions` (#1176). The\n // adjustment is now baked into `scrollOffset`, so zero\n // `scrollAdjustments` to keep their sum invariant.\n if (this.scrollOffset !== null) {\n this.scrollOffset += this.scrollAdjustments\n this.scrollAdjustments = 0\n }\n }\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 // A scroll event that reports movement but lands on the offset we\n // already hold — and isn't a self-write read-back — is a spurious\n // no-op re-emit that Safari/Firefox fire after a re-render's layout\n // (Chrome doesn't). Treating it as scrolling re-arms `isScrolling`,\n // which forces a render that triggers another such event: an\n // infinite re-render loop. Ignore it. (Self-writes are handled by\n // the `_intendedScrollOffset` reconciliation just below.)\n if (\n isScrolling &&\n this._intendedScrollOffset === null &&\n offset === this.scrollOffset\n ) {\n return\n }\n\n // If this scroll event looks like the browser's read-back of a\n // value we just wrote, prefer our intended (sub-pixel-accurate)\n // value over the browser's rounded one. The 1.5 px tolerance is\n // tight enough to avoid mistaking a real user scroll for a\n // self-write — by the time the user has moved 1.5 px, the\n // intended value will already have been consumed by a prior\n // scroll event and cleared.\n if (\n this._intendedScrollOffset !== null &&\n Math.abs(offset - this._intendedScrollOffset) < 1.5\n ) {\n offset = this._intendedScrollOffset\n }\n this._intendedScrollOffset = null\n\n this.scrollAdjustments = 0\n // If the offset hasn't moved, this is the echo of our own\n // adjustment write — `applyScrollAdjustment` already folded it\n // into `scrollOffset`. There's no direction to infer, so leave\n // it alone; a real gesture always moves the offset.\n const prevOffset = this.getScrollOffset()\n this.scrollDirection = isScrolling\n ? prevOffset === offset\n ? this.scrollDirection\n : prevOffset < offset\n ? 'forward'\n : 'backward'\n : null\n this.scrollOffset = offset\n this.isScrolling = isScrolling\n\n // Flush deferred iOS adjustments if we're now fully settled.\n // \"Fully settled\" means: not actively scrolling, no finger on\n // screen, and the post-touchend grace window has expired.\n this._flushIosDeferredIfReady()\n\n if (this.scrollState) {\n this.scheduleScrollReconcile()\n }\n this.maybeNotify()\n }),\n )\n\n // Touch event listeners (iOS-aware deferral). We attach unconditionally\n // — the listeners are passive and cheap; on non-touch devices they\n // simply never fire. The gating by isIOSWebKit() lives in resizeItem\n // and _flushIosDeferredIfReady so we only burn the path on iOS.\n if ('addEventListener' in this.scrollElement) {\n const scrollEl = this.scrollElement as unknown as EventTarget\n const onTouchStart = () => {\n this._iosTouching = true\n this._iosJustTouchEnded = false\n if (this._iosTouchEndTimerId !== null && this.targetWindow != null) {\n this.targetWindow.clearTimeout(this._iosTouchEndTimerId)\n this._iosTouchEndTimerId = null\n }\n }\n const onTouchEnd = () => {\n this._iosTouching = false\n if (!isIOSWebKit() || this.targetWindow == null) {\n // Non-iOS: nothing more to track. Just clear the touching flag.\n return\n }\n this._iosJustTouchEnded = true\n // After ~150 ms with no scroll/touch events, momentum is done.\n this._iosTouchEndTimerId = this.targetWindow.setTimeout(() => {\n this._iosJustTouchEnded = false\n this._iosTouchEndTimerId = null\n // After the grace window, attempt to flush. The scroll event\n // for momentum decay may have already fired before our timer.\n this._flushIosDeferredIfReady()\n }, 150)\n }\n scrollEl.addEventListener(\n 'touchstart',\n onTouchStart,\n addEventListenerOptions,\n )\n scrollEl.addEventListener(\n 'touchend',\n onTouchEnd,\n addEventListenerOptions,\n )\n this.unsubs.push(() => {\n scrollEl.removeEventListener('touchstart', onTouchStart)\n scrollEl.removeEventListener('touchend', onTouchEnd)\n if (this._iosTouchEndTimerId !== null && this.targetWindow != null) {\n this.targetWindow.clearTimeout(this._iosTouchEndTimerId)\n this._iosTouchEndTimerId = null\n }\n })\n }\n\n this._scrollToOffset(this.getScrollOffset(), {\n adjustments: undefined,\n behavior: undefined,\n })\n }\n\n const anchor = this.pendingScrollAnchor\n this.pendingScrollAnchor = null\n\n if (anchor && this.scrollElement && this.options.enabled) {\n const [key, _offset, followOnAppend, anchorDelta] = anchor\n\n if (key !== null && !followOnAppend) {\n // scrollOffset was eagerly adjusted in setOptions so the\n // virtualizer already computed the correct range during render.\n // Now sync the browser's actual scroll position to match.\n // Skip when followOnAppend is set — scrollToEnd will handle it.\n //\n // On iOS WebKit, writing scrollTop during touch/momentum cancels\n // the in-flight scroll. Defer the DOM sync the same way\n // applyScrollAdjustment does — accumulate the delta and let\n // _flushIosDeferredIfReady handle it once the scroll settles.\n if (\n isIOSWebKit() &&\n (this.isScrolling || this._iosTouching || this._iosJustTouchEnded)\n ) {\n if (anchorDelta !== 0) {\n this._iosDeferredAdjustment += anchorDelta\n }\n } else {\n this._scrollToOffset(this.getScrollOffset(), {\n adjustments: undefined,\n behavior: undefined,\n })\n }\n }\n\n if (followOnAppend) {\n this.scrollToEnd({ behavior: followOnAppend })\n }\n }\n }\n\n // Apply any accumulated iOS-deferred scroll adjustment, but only when we're\n // truly settled — not actively scrolling, not under an active touch, and\n // past the post-touchend grace window. Called from the scroll callback\n // and the touchend grace-timer.\n private _flushIosDeferredIfReady = () => {\n if (this._iosDeferredAdjustment === 0) return\n if (this.isScrolling) return\n if (this._iosTouching) return\n if (this._iosJustTouchEnded) return\n // Phase 2b: Safari elastic-overscroll (rubber-band) lets scrollTop go\n // negative or beyond scrollHeight - clientHeight. Writing scrollTop\n // while in that zone snaps the page back to the clamped value at the\n // end of the bounce, often discarding the user's intent. Skip the\n // flush; the next in-bounds scroll event will retry.\n const cur = this.getScrollOffset()\n const max = this.getMaxScrollOffset()\n if (cur < 0 || cur > max) return\n const delta = this._iosDeferredAdjustment\n this._iosDeferredAdjustment = 0\n // Roll the deferred delta into the running accumulator so any resize\n // landing between now and the resulting scroll event computes from the\n // post-flush offset rather than the stale one.\n this._scrollToOffset(cur, {\n adjustments: (this.scrollAdjustments += delta),\n behavior: undefined,\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 // Final-pass exact landing. The reconcile-stable check uses a 1.01px\n // tolerance (approxEqual) so we don't fight subpixel browser rounding\n // during the converging phase. Once we're definitively settled,\n // commit the exact target so consumers calling scrollToIndex(N)\n // end up at the EXACT computed position of item N — matching\n // virtuoso's 0px landing accuracy rather than our prior 0.5-1px.\n if (this.getScrollOffset() !== targetOffset) {\n this._scrollToOffset(targetOffset, {\n adjustments: undefined,\n behavior: 'auto',\n })\n }\n this.scrollState = null\n return\n }\n } else {\n this.scrollState.stableFrames = 0\n\n if (targetChanged) {\n // When the target moves during smooth scroll (because items came into\n // view and got measured, shifting positions), the original logic was\n // to immediately snap to 'auto' — visibly jarring on long\n // scroll-to-index calls. Now: keep smooth while we're still far\n // (more than a viewport) from the new target. Only fall back to\n // 'auto' for the final approach, so the user sees one continuous\n // motion that smoothly adjusts its endpoint as measurements arrive.\n const viewport = this.getSize() || 600\n const distance = Math.abs(targetOffset - this.getScrollOffset())\n const keepSmooth =\n this.scrollState.behavior === 'smooth' && distance > viewport\n\n this.scrollState.lastTargetOffset = targetOffset\n if (!keepSmooth) {\n this.scrollState.behavior = 'auto'\n }\n\n this._scrollToOffset(targetOffset, {\n adjustments: undefined,\n behavior: keepSmooth ? 'smooth' : '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,\n index: number,\n ) => {\n const furthestMeasurementsFound = new Map()\n const furthestMeasurements = new Map()\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 this.options.laneAssignmentMode,\n ],\n (\n count,\n paddingStart,\n scrollMargin,\n getItemKey,\n enabled,\n lanes,\n laneAssignmentMode,\n ) => {\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.pendingMin = null\n\n return {\n count,\n paddingStart,\n scrollMargin,\n getItemKey,\n enabled,\n lanes,\n laneAssignmentMode,\n }\n },\n {\n key: false,\n },\n )\n\n private getMeasurements = memo(\n () => [this.getMeasurementOptions(), this.itemSizeCacheVersion],\n (\n {\n count,\n paddingStart,\n scrollMargin,\n getItemKey,\n enabled,\n lanes,\n laneAssignmentMode,\n },\n _itemSizeCacheVersion,\n ) => {\n const itemSizeCache = this.itemSizeCache\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 // Force min = 0 on the rebuild\n this.pendingMin = null\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 pendingMin to prevent repositioning\n const min = this.lanesSettling ? 0 : (this.pendingMin ?? 0)\n this.pendingMin = null\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 // ─── Fast path: single-lane lazy materialization ────────────────────\n // For lanes === 1 (the default and most common case), skip the\n // per-item VirtualItem object allocation. We write start/size pairs\n // into a Float64Array and return a Proxy that builds VirtualItem\n // objects on demand (only the indices a consumer actually reads).\n //\n // At n=100k this drops cold-mount cost from ~2.5ms (eager object\n // allocation) to roughly the cost of a single typed-array fill.\n if (lanes === 1) {\n const gap = this.options.gap\n // Reuse flat backing if large enough; else grow (preserving data\n // before `min` to mirror the slice-and-rebuild contract).\n const need = count * 2\n let flat = this._flatMeasurements\n if (!flat || flat.length < need) {\n const next = new Float64Array(need)\n if (flat && min > 0) next.set(flat.subarray(0, min * 2))\n flat = next\n this._flatMeasurements = flat\n }\n\n let runningStart: number\n if (min === 0) {\n runningStart = paddingStart + scrollMargin\n } else {\n // Continue from where we left off\n const prevIdx = min - 1\n runningStart = flat[prevIdx * 2]! + flat[prevIdx * 2 + 1]! + gap\n }\n\n for (let i = min; i < count; i++) {\n const key = getItemKey(i)\n const measuredSize = itemSizeCache.get(key)\n const size =\n typeof measuredSize === 'number'\n ? measuredSize\n : this.options.estimateSize(i)\n flat[i * 2] = runningStart\n flat[i * 2 + 1] = size\n runningStart += size + gap\n }\n\n const view = createLazyMeasurementsView(count, flat, getItemKey)\n this.measurementsCache = view\n return view\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 = 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 const shouldCacheLane =\n laneAssignmentMode === 'estimate' || itemSizeCache.has(key)\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 if (this.options.lanes > 1 && shouldCacheLane) {\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 if (measurements.length === 0 || outerSize === 0) {\n this.range = null\n return null\n }\n this.range = calculateRangeImpl(\n measurements,\n outerSize,\n scrollOffset,\n lanes,\n // Pass the typed array so binary search + forward-walk can read\n // start/end directly from Float64Array, skipping the Proxy traps.\n lanes === 1 && this._flatMeasurements != null\n ? this._flatMeasurements\n : null,\n )\n return this.range\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 if (index < 0 || index >= this.options.count) return\n\n // Fast field reads. For lanes===1 we read raw start/size from the flat\n // typed array, avoiding a Proxy.get + VirtualItem allocation per call.\n // For lanes>1 we fall back to the cached VirtualItem array.\n let cachedSize: number\n let itemStart: number\n let key: Key\n const flat = this._flatMeasurements\n if (this.options.lanes === 1 && flat !== null) {\n key = this.options.getItemKey(index)\n itemStart = flat[index * 2]!\n cachedSize = flat[index * 2 + 1]!\n } else {\n const item = this.measurementsCache[index]\n if (!item) return\n key = item.key\n itemStart = item.start\n cachedSize = item.size\n }\n\n const itemSize = this.itemSizeCache.get(key) ?? cachedSize\n const delta = size - itemSize\n\n if (delta !== 0) {\n const wasAtEnd =\n this.options.anchorTo === 'end' &&\n this.scrollState?.behavior !== 'smooth' &&\n this.getVirtualDistanceFromEnd() <= this.options.scrollEndThreshold\n const prevTotalSize = wasAtEnd ? this.getTotalSize() : 0\n const shouldAdjustScroll =\n this.scrollState?.behavior !== 'smooth' &&\n (this.shouldAdjustScrollPositionOnItemSizeChange !== undefined\n ? this.shouldAdjustScrollPositionOnItemSizeChange(\n // The callback expects a VirtualItem; build one lazily only\n // when the consumer actually supplied a custom predicate.\n this.measurementsCache[index] ?? {\n index,\n key,\n start: itemStart,\n size: cachedSize,\n end: itemStart + cachedSize,\n lane: 0,\n },\n delta,\n this,\n )\n : // Default: adjust when the resize is an above-viewport item.\n // First measurement (!has(key)): always adjust — the item\n // has never been sized, so the estimate→actual delta must\n // be compensated regardless of scroll direction.\n // Re-measurement (has(key)): skip during backward scroll\n // to avoid the \"items jump while scrolling up\" cascade.\n itemStart < this.getScrollOffset() + this.scrollAdjustments &&\n (!this.itemSizeCache.has(key) ||\n this.scrollDirection !== 'backward'))\n\n if (this.pendingMin === null || index < this.pendingMin) {\n this.pendingMin = index\n }\n this.itemSizeCache.set(key, size)\n this.itemSizeCacheVersion++\n\n if (wasAtEnd) {\n this.applyScrollAdjustment(this.getTotalSize() - prevTotalSize)\n } else if (shouldAdjustScroll) {\n this.applyScrollAdjustment(delta)\n }\n\n this.notify(false)\n }\n }\n\n getVirtualItems = memo(\n () => [this.getVirtualIndexes(), this.getMeasurements()],\n (indexes, measurements) => {\n const virtualItems: Array = []\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 // Same fast-path as calculateRange: read start values directly from the\n // typed array during binary search to skip the Proxy.get materialization\n // per probe.\n const flat = this._flatMeasurements\n const useFlat = this.options.lanes === 1 && flat != null\n const idx = findNearestBinarySearch(\n 0,\n measurements.length - 1,\n useFlat\n ? (i: number) => flat[i * 2]!\n : (i: number) => notUndefined(measurements[i]).start,\n offset,\n )\n return notUndefined(measurements[idx])\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 private getVirtualDistanceFromEnd = () => {\n return Math.max(\n this.getTotalSize() - this.getSize() - this.getScrollOffset(),\n 0,\n )\n }\n\n getDistanceFromEnd = () => {\n return Math.max(this.getMaxScrollOffset() - this.getScrollOffset(), 0)\n }\n\n isAtEnd = (threshold = this.options.scrollEndThreshold) => {\n return this.getDistanceFromEnd() <= threshold\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 scrollToEnd = ({ behavior = 'auto' }: ScrollToEndOptions = {}) => {\n if (this.options.count > 0) {\n this.scrollToIndex(this.options.count - 1, {\n align: 'end',\n behavior,\n })\n return\n }\n\n this.scrollToOffset(Math.max(this.getTotalSize() - this.getSize(), 0), {\n behavior,\n })\n }\n\n getTotalSize = () => {\n const measurements = this.getMeasurements()\n\n let end: number\n // If there are no measurements, set the end to paddingStart\n // If 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 // Fast path: read last item's end directly from the flat typed array\n // when available; avoids a Proxy.get + VirtualItem materialization\n // just to call getTotalSize (which React renders trigger every commit).\n const lastIdx = measurements.length - 1\n const flat = this._flatMeasurements\n if (flat != null) {\n end = flat[lastIdx * 2]! + flat[lastIdx * 2 + 1]!\n } else {\n end = measurements[lastIdx]?.end ?? 0\n }\n } else {\n const endByLane = Array(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 /**\n * Returns a snapshot of currently-measured items suitable for round-\n * tripping through state storage (sessionStorage, history, etc.) and\n * passing back as `initialMeasurementsCache` on remount. Pair with the\n * current `scrollOffset` to restore exact scroll position after navigation.\n *\n * Only items the consumer has actually rendered (and thus measured) appear\n * in the snapshot; unmeasured items will fall back to `estimateSize` on\n * restore. Returns an empty array if no items have been measured.\n */\n takeSnapshot = (): Array => {\n const snapshot: Array = []\n if (this.itemSizeCache.size === 0) return snapshot\n // Iterate measurementsCache only for indices whose key is in itemSizeCache\n // (i.e., have been measured). We build VirtualItem objects with the\n // current start/size/end so they can be persisted as plain data.\n const m = this.getMeasurements()\n for (const item of m) {\n if (item && this.itemSizeCache.has(item.key)) {\n // Force materialization (lazy path) and copy plain fields.\n snapshot.push({\n index: item.index,\n key: item.key,\n start: item.start,\n size: item.size,\n end: item.end,\n lane: item.lane,\n })\n }\n }\n return snapshot\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 // Record the intended logical scroll target so the next scroll event\n // can reconcile against subpixel rounding by the browser.\n this._intendedScrollOffset = offset + (adjustments ?? 0)\n this.options.scrollToFn(offset, { behavior, adjustments }, this)\n }\n\n measure = () => {\n // Reset pendingMin so the next getMeasurements rebuilds from index 0.\n // Without this, a prior resizeItem() that left pendingMin > 0 would\n // cause the rebuild to preserve stale items before that index.\n this.pendingMin = null\n this.itemSizeCache.clear()\n this.laneAssignments.clear() // Clear lane cache for full re-layout\n this.itemSizeCacheVersion++\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\n// Monomorphic Float64Array variant — reads start values directly at stride\n// 2 instead of through a getter closure. JITs the inner load to a typed-\n// array bounds-check + load with no indirect call.\nfunction findNearestBinarySearchFlat(\n flat: Float64Array,\n high: number,\n value: number,\n) {\n let low = 0\n while (low <= high) {\n const middle = ((low + high) / 2) | 0\n const currentValue = flat[middle * 2]!\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 return low > 0 ? low - 1 : 0\n}\n\nfunction calculateRangeImpl(\n measurements: Array,\n outerSize: number,\n scrollOffset: number,\n lanes: number,\n flat: Float64Array | null,\n) {\n const lastIndex = measurements.length - 1\n\n // handle case when item count is less than or equal to lanes\n if (measurements.length <= lanes) {\n return { startIndex: 0, endIndex: lastIndex }\n }\n\n if (lanes === 1 && flat !== null) {\n // Hot single-lane path: typed-array reads, no closures, no Proxy traps.\n const startIndex = findNearestBinarySearchFlat(\n flat,\n lastIndex,\n scrollOffset,\n )\n let endIndex = startIndex\n const limit = scrollOffset + outerSize\n while (\n endIndex < lastIndex &&\n flat[endIndex * 2]! + flat[endIndex * 2 + 1]! < limit\n ) {\n endIndex++\n }\n return { startIndex, endIndex }\n }\n\n // Fallback (lanes > 1 or no flat array): closure-based reads.\n const getStart = (index: number) => measurements[index]!.start\n let startIndex = findNearestBinarySearch(0, lastIndex, getStart, scrollOffset)\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","createLazyMeasurementsView","key","notUndefined","approxEqual","startIndex","endIndex"],"mappings":"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"}