{"version":3,"file":"index.cjs","sources":["../../src/index.ts"],"sourcesContent":["import {\n  createLazyMeasurementsView,\n  getMeasurementKey,\n} from './lazy-measurements'\nimport { approxEqual, debounce, memo, notUndefined } from './utils'\nimport {\n  classifyScrollEvent,\n  externalRetiresCommand,\n  flingCaught,\n  flingSpedUp,\n} from './scroll-classifier'\nimport { IosGesture, isIOSWebKit, momentumOverridesWrites } from './ios-gesture'\nimport type { ScrollPhase, ScrollSample } from './scroll-classifier'\n\nexport { _resetIOSDetectionForTests } from './ios-gesture'\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<ScrollToOptions, 'behavior'>\n\nexport interface Range {\n  startIndex: number\n  endIndex: number\n  overscan: number\n  count: number\n  /**\n   * Lane count of the virtualizer. When greater than 1, `overscan` counts\n   * rows of `lanes` items rather than single items.\n   */\n  lanes?: 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 { clientWidth, clientHeight } = element\n  return { width: clientWidth, height: clientHeight }\n}\n\n// Animation frames for `useAnimationFrameWithResizeObserver`, requested from\n// the scroll element's own window rather than the global one.\nconst createFrameQueue = (targetWindow: Window) => {\n  const ids = new Set<number>()\n  return {\n    schedule: (fn: () => void) => {\n      const id = targetWindow.requestAnimationFrame(() => {\n        ids.delete(id)\n        fn()\n      })\n      ids.add(id)\n    },\n    cancel: () => {\n      ids.forEach((id) => targetWindow.cancelAnimationFrame(id))\n      ids.clear()\n    },\n  }\n}\n\nexport const defaultKeyExtractor = (index: number) => index\n\nexport const defaultRangeExtractor = (range: Range) => {\n  // With lanes, the visible range is already aligned to whole rows; overscan\n  // by whole rows too, so every lane gets the same number of items rendered\n  // (and measured). Overscanning single items leaves partial rows, letting one\n  // lane collect more measured sizes than the others and drift (#1036).\n  const overscan = range.overscan * Math.max(range.lanes ?? 1, 1)\n  const start = Math.max(range.startIndex - overscan, 0)\n  const end = Math.min(range.endIndex + overscan, range.count - 1)\n  const len = end - start + 1\n\n  const arr = new Array<number>(len)\n  for (let i = 0; i < len; i++) {\n    arr[i] = start + i\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 frames = createFrameQueue(targetWindow)\n  const observer = new targetWindow.ResizeObserver(() => {\n    const run = () => {\n      handler(getRect(element as unknown as HTMLElement))\n    }\n\n    instance.options.useAnimationFrameWithResizeObserver\n      ? frames.schedule(run)\n      : run()\n  })\n\n  observer.observe(element, { box: 'content-box' })\n\n  return () => {\n    observer.unobserve(element)\n    frames.cancel()\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\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 = <T extends Element | Window>(\n  instance: Virtualizer<T, any>,\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(readOffset(element), 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    // Removing the listener doesn't retract a reset already queued by the\n    // last scroll, and that call would land on a virtualizer that has been\n    // torn down — in React, a dispatch into an unmounted tree.\n    fallback?.cancel()\n  }\n}\n\nexport const observeElementOffset = <T extends Element>(\n  instance: Virtualizer<T, any>,\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<Window, any>,\n  cb: ObserveOffsetCallBack,\n) =>\n  observeOffset(instance, cb, (win) =>\n    instance.options.horizontal ? win.scrollX : win.scrollY,\n  )\n\nexport const measureElement = <TItemElement extends Element>(\n  element: TItemElement,\n  entry: ResizeObserverEntry | undefined,\n  instance: Virtualizer<any, TItemElement>,\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  TScrollElement extends Element | Window,\n  TItemElement extends Element,\n>(\n  offset: number,\n  {\n    adjustments = 0,\n    behavior,\n  }: { adjustments?: number; behavior?: ScrollBehavior },\n  instance: Virtualizer<TScrollElement, TItemElement>,\n) => {\n  const { scrollElement, options } = instance\n  const adjustedOffset = offset + adjustments\n  const isRtlElement =\n    options.horizontal &&\n    options.isRtl &&\n    scrollElement !== null &&\n    'ownerDocument' in scrollElement\n\n  scrollElement?.scrollTo?.({\n    [options.horizontal ? 'left' : 'top']: isRtlElement\n      ? -adjustedOffset\n      : adjustedOffset,\n    behavior,\n  })\n}\n\nexport const windowScroll: <T extends Window>(\n  offset: number,\n  options: { adjustments?: number; behavior?: ScrollBehavior },\n  instance: Virtualizer<T, any>,\n) => void = scrollWithAdjustments\n\nexport const elementScroll: <T extends Element>(\n  offset: number,\n  options: { adjustments?: number; behavior?: ScrollBehavior },\n  instance: Virtualizer<T, any>,\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<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  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  // scrollToEnd: track the DOM max scroll offset instead of the item's offset\n  toEnd?: boolean\n\n  // lifecycle\n  startedAt: number\n  // how the command was asked to scroll; a queued command writes with it\n  behavior: ScrollBehavior\n\n  // target tracking\n  lastTargetOffset: number\n\n  // settling\n  stableFrames: number\n  phase: ScrollPhase\n\n  // A `queued` command's view of the fling it waits for: the scroll events\n  // since it was queued, at most the last 200ms (`flingSpedUp`,\n  // `flingCaught`). Read only while `queued`.\n  samples?: Array<ScrollSample>\n}\n\nconst initialScrollPhase = (\n  behavior: ScrollBehavior,\n  atTarget: boolean,\n): ScrollPhase =>\n  behavior === 'smooth' ? (atTarget ? 'smoothLanded' : 'smooth') : 'instant'\n\n// A smooth scroll owns the position: size compensation, the prepend anchor\n// sync and far measurements hold off until it switches to instant writes.\nconst isSmoothScroll = (state: ScrollState | null): state is ScrollState =>\n  state?.phase === 'smooth' || state?.phase === 'smoothLanded'\n\n// What `setOptions` decided about the scroll position for `_willUpdate` to\n// carry out once the consumer has rendered: keep the reading anchor in place\n// after a prepend (`scrollOffset` already moved by `delta`, the element has\n// not), or follow an append to the end. A prepend that qualifies for both\n// only follows.\ntype PendingScrollAnchor =\n  | { kind: 'anchor'; delta: number }\n  | { kind: 'follow'; behavior: ScrollBehavior }\n\nfunction isAppendWithTrim(\n  prevCount: number,\n  nextCount: number,\n  getPreviousKey: (index: number) => Key,\n  getNextKey: (index: number) => Key,\n): boolean {\n  if (nextCount === 0) return false\n\n  const firstKey = getNextKey(0)\n  const removedKeys = new Set<Key>()\n  let removedCount = 0\n  while (removedCount < prevCount) {\n    const key = getPreviousKey(removedCount)\n    if (key === firstKey) break\n    removedKeys.add(key)\n    removedCount++\n  }\n\n  const retainedCount = prevCount - removedCount\n  if (retainedCount === 0 || retainedCount >= nextCount) return false\n\n  for (let i = 0; i < retainedCount; i++) {\n    if (getNextKey(i) !== getPreviousKey(removedCount + i)) return false\n  }\n  for (let i = retainedCount; i < nextCount; i++) {\n    if (removedKeys.has(getNextKey(i))) return false\n  }\n  return true\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  // Keys belong to the layout build, even when VirtualItems are read later.\n  // The flat [start, size, ...] buffer is reused across builds.\n  private _singleLaneMeasurements: {\n    flat: Float64Array\n    items: Array<Key | VirtualItem>\n  } | null = null\n  itemSizeCache = new Map<Key, number>()\n  private itemSizeCacheVersion = 0\n  private laneAssignments = new Map<number, number>() // 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  /**\n   * The scroll position in the list's layout, consistent with\n   * `getOffsetForIndex`, `scrollToOffset` and `initialOffset`. While a\n   * correction is held (`_holdOffset`), `getVirtualItems()` and\n   * `getTotalSize()` describe what is rendered, shifted by the held amount;\n   * this stays the layout position.\n   */\n  scrollOffset: number | null = null\n  scrollDirection: ScrollDirection | null = null\n  /**\n   * @deprecated Always 0: a scroll correction is folded into `scrollOffset`\n   * at once, so there is never an outstanding adjustment to add to it. Read\n   * `scrollOffset` alone.\n   */\n  get scrollAdjustments() {\n    return 0\n  }\n  // Scroll corrections (a prepend's anchor delta, size changes above the\n  // viewport) that could not be written to the element because a write was\n  // impossible at the time (see `_canWriteScroll`): the difference between\n  // `scrollOffset`, which always carries the corrected layout position, and\n  // where the element is. While it is non-zero the rows and the total size\n  // are exposed shifted by `-_holdOffset`, so every adapter renders the\n  // reader's row where it was, writes subtract it (`_scrollToOffset`) and\n  // scroll events add it back (the handler in `_willUpdate`). Released by\n  // `_flushHoldIfReady`: the rows re-render in layout coordinates and the\n  // element moves by the same amount in one paint.\n  private _holdOffset = 0\n  // Whether the element's last scroll event reported a position past either\n  // edge (the rubber-band bounce). Judged at report time against the\n  // element's own max, with a 1px tolerance for a fractional scrollTop: a\n  // sizer that shrinks after the report (a trim) is not a bounce, and\n  // `scrollOffset` is no judge either, since an eager bump past the max while\n  // the sizer has not grown yet (#1258) is not one.\n  //\n  // Stored rather than read from the element when a write is decided. The\n  // two differ once a write has landed but not been reported back, and in\n  // that window the element reads in bounds while `scrollOffset` is still\n  // the pre-write value. With the anchor sync now skipped in that window\n  // (`_awaitingCommandReadBack`), the remaining difference is the trim: a\n  // list that shrank under the position reads past the element's max until\n  // the browser clamps it, which is where the anchor's write has to go\n  // (`followOnAppend does not follow 'trim only'`; reading the element at\n  // write time still moves 49 of 1080 snapshot seeds).\n  private _reportedOverscroll = false\n  // The touch gesture in progress (see `IosGesture`). Its tail closing on\n  // its own makes a write possible again: the last momentum frame may have\n  // come before the timer. The hold is released first, so a command that\n  // waited for the tail is written over rows already back in layout\n  // coordinates.\n  private _iosGesture = new IosGesture({\n    getWindow: () => this.targetWindow,\n    now: () => this.now(),\n    // The end of a fling can move less than a pixel per scroll event, so\n    // events can stop for 150ms while the fling is still running (seen on\n    // an iPhone, 27.0.1). A command waiting for it would then be written\n    // into the fling and overridden. The element having moved since the\n    // last event means it has not ended: wait again. Not while our own\n    // write has yet to report: that moved it.\n    tailStillMoving: () => {\n      const state = this.scrollState\n      if (state?.phase !== 'queued' || this.pendingWrite !== null) {\n        return false\n      }\n      const now = this._readElementOffset()\n      if (\n        now === null ||\n        this._lastElementOffset === null ||\n        Math.abs(now - this._lastElementOffset) < 1\n      ) {\n        return false\n      }\n      this._lastElementOffset = now\n      // It moved with no event: a sample, so the speed `flingCaught` reads\n      // when it stops is not the one from before the silence.\n      state.samples = [...(state.samples ?? []), { t: this.now(), offset: now }]\n      return true\n    },\n    onTailClosed: () => {\n      // A fling that stopped at speed was caught by a finger that is still\n      // down, with no touch events: the user has taken over, as with a\n      // drag, and iOS would undo the write anyway.\n      const state = this.scrollState\n      if (state?.phase === 'queued' && flingCaught(state.samples ?? [])) {\n        this.scrollState = null\n      }\n      this._flushHoldIfReady(true)\n      this._writeAwaitingCommand()\n      // A clamped write the touch held back; a command written above has\n      // cleared it.\n      this._retryClampedAdjustment()\n    },\n  })\n  // The last position the scroll handler was given, in the element's own\n  // coordinates. The tail compares it with the element (`tailStillMoving`\n  // above).\n  private _lastElementOffset: number | null = null\n  // Our last write to the element, from `_scrollToOffset` until the next\n  // scroll event reports it (the only place it is cleared). Until then\n  // `scrollOffset` may still hold the old position.\n  //\n  // - `target`: where the write puts the element (offset + the adjustment\n  //   passed to `scrollToFn`).\n  //   Safari (and Chrome/Firefox under certain DPRs) round writes to whole\n  //   pixels: wrote 12345.5, read back 12346. A read-back within 1.5px of\n  //   `target` is taken as our own and adopts the exact value, so reconcile\n  //   does not see a moved target and write again; a user scroll has moved\n  //   further by the time it reports.\n  // - `smooth`: the write animates, so until it lands the element is\n  //   somewhere between the old offset and `target`.\n  // - `lowMaxes`: for a command's instant write, each scroll max below\n  //   `target` the element had since the write. A command's target is\n  //   clamped to the max at the write, but the sizer can shrink under it\n  //   before the report (rows measured smaller, a count change) and grow\n  //   back, so the read-back is the max the browser clamped to then rather\n  //   than the element's current one. Read wherever the sizer can have\n  //   been committed (`_noteClampMax`).\n  private pendingWrite: {\n    target: number\n    smooth: boolean\n    lowMaxes?: Array<number>\n  } | null = null\n  // A compensation write from `applyScrollAdjustment` whose target exceeded\n  // the element's scroll max at the moment of the write. The browser clamps\n  // such a write because the consumer's sizer has not grown yet: an\n  // end-anchored item growing at the bottom only extends `scrollHeight` to\n  // its own end, so with `paddingEnd > 0` the clamp lands exactly\n  // `paddingEnd` short of the target (#1258). `_willUpdate` re-issues the\n  // write once the sizer has caught up; the clamped read-back keeps it\n  // pending, any other scroll event (a real gesture) cancels it.\n  private _clampedAdjustment: { target: number; maxAtWrite: number } | null =\n    null\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  // Set while a ResizeObserver callback measures its entries; `resizeItem`\n  // records the pending notify here instead of firing it per entry.\n  private _resizeBatch: { sync: boolean; notify?: boolean } | null = null\n  private now = () => this.targetWindow?.performance?.now?.() ?? Date.now()\n  private observer = (() => {\n    let _ro: ResizeObserver | null = null\n    let _frames: ReturnType<typeof createFrameQueue> | null = null\n    let delivering = false\n    let observeQueued = false\n    const pendingObservations = new Set<Element>()\n\n    const get = () => {\n      if (_ro) {\n        return _ro\n      }\n\n      const targetWindow = this.targetWindow\n      if (!targetWindow || !targetWindow.ResizeObserver) {\n        return null\n      }\n\n      const frames = (_frames = createFrameQueue(targetWindow))\n      return (_ro = new targetWindow.ResizeObserver((entries) => {\n        const run = () => {\n          // Measure every entry before notifying. A notify that adjusted\n          // scroll re-renders synchronously, and that render can unmount\n          // nodes whose entries are still queued here, leaving them\n          // unmeasured. With lanes, a half-measured row lets one lane drift\n          // away from the others (#1036).\n          const batch: { sync: boolean; notify?: boolean } = { sync: false }\n          this._resizeBatch = batch\n          try {\n            entries.forEach(measureEntry)\n          } finally {\n            this._resizeBatch = null\n            if (batch.notify) {\n              this.notify(batch.sync)\n              this._noteClampMax()\n              this._flushHoldIfReady(true)\n              this._retryClampedAdjustment()\n              // Ref-null callbacks run before the host nodes are detached.\n              // Drop them after the sync renders, before the browser gathers\n              // another round of ResizeObserver entries at their new depth.\n              this.measureElement(null)\n            }\n          }\n        }\n        if (this.options.useAnimationFrameWithResizeObserver) {\n          frames.schedule(run)\n        } else {\n          delivering = true\n          try {\n            run()\n          } finally {\n            delivering = false\n          }\n        }\n      }))\n    }\n\n    const measureEntry = (entry: ResizeObserverEntry) => {\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.isIndexInRange(index)) return\n\n      if (this.shouldMeasureDuringScroll(index)) {\n        this.resizeItem(index, this.options.measureElement(node, entry, this))\n      }\n    }\n\n    return {\n      disconnect: () => {\n        get()?.disconnect()\n        _frames?.cancel()\n        pendingObservations.clear()\n        observeQueued = false\n        _ro = null\n        _frames = null\n      },\n      observe: (target: Element) => {\n        const observer = get()\n        if (!observer) return\n        if (!delivering) {\n          observer.observe(target, { box: 'border-box' })\n          return\n        }\n        // A sync render can also mount rows at the depth being delivered.\n        // A microtask is still inside that delivery: register next frame,\n        // while measureElement continues to measure the new row immediately.\n        pendingObservations.add(target)\n        if (!observeQueued) {\n          observeQueued = true\n          _frames?.schedule(() => {\n            observeQueued = false\n            pendingObservations.forEach((node) => {\n              if (node.isConnected) _ro?.observe(node, { box: 'border-box' })\n            })\n            pendingObservations.clear()\n          })\n        }\n      },\n      unobserve: (target: Element) => {\n        pendingObservations.delete(target)\n        get()?.unobserve(target)\n      },\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    // 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<VirtualizerOptions<TScrollElement, TItemElement>>\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<VirtualizerOptions<TScrollElement, TItemElement>>\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 previousItems = this._singleLaneMeasurements?.items ?? measurements\n      const getPreviousKey = (index: number) =>\n        getMeasurementKey(previousItems[index]!)\n      const prevFirstKey = prevCount > 0 ? getPreviousKey(0) : null\n      const prevLastKey = prevCount > 0 ? getPreviousKey(prevCount - 1) : 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 > 0 &&\n          this.isAtEnd(prevOptions.scrollEndThreshold) &&\n          (prevCount === 0 || merged.getItemKey(nextCount - 1) !== prevLastKey)\n        ) {\n          if (\n            nextCount > prevCount ||\n            isAppendWithTrim(\n              prevCount,\n              nextCount,\n              getPreviousKey,\n              merged.getItemKey,\n            )\n          ) {\n            followOnAppend = behavior\n          }\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    // Not before a scroll command's write has been read back: `scrollOffset`\n    // is still the pre-command position, so the anchor would be resolved\n    // against rows that are no longer where the command put the element, and\n    // the sync would write that stale offset over the command. Reconcile\n    // retargets an index or end command from the new layout; an offset\n    // command lands where it was written (#1307, step 5).\n    let anchorDelta: number | null = null\n    if (\n      anchor &&\n      this.scrollOffset !== null &&\n      !this._awaitingCommandReadBack()\n    ) {\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          // Clamp to the reachable range's lower bound — anchorOffset may\n          // have been derived from a transiently negative scrollOffset\n          // (rubber-band), and a negative tracked offset never self-heals\n          // when the element cannot scroll (#1229).\n          const newOffset = Math.max(0, anchorItem.start + anchorOffset)\n          // A no-op end scroll emits no event to correct a reading-anchor offset.\n          if (!followOnAppend && newOffset !== this.scrollOffset) {\n            anchorDelta = newOffset - this.scrollOffset\n            this.scrollOffset = newOffset\n          }\n        }\n      }\n    }\n\n    if (followOnAppend) {\n      this.pendingScrollAnchor = { kind: 'follow', behavior: followOnAppend }\n    } else if (anchorDelta !== null) {\n      if (this._canWriteScroll()) {\n        this.pendingScrollAnchor = { kind: 'anchor', delta: anchorDelta }\n      } else {\n        // The element cannot take the write (a touch owns it on iOS, or it is\n        // overscrolled). Hold the delta instead: this render already exposes\n        // the rows and the total shifted back by it, so the reader's row\n        // stays put, and the flush writes it once a write is possible.\n        this._holdOffset += anchorDelta\n        this._followOffsetTarget(anchorDelta)\n      }\n    }\n  }\n\n  private notify = (sync: boolean) => {\n    this.options.onChange?.(this, sync)\n  }\n\n  // Returns `true` when it performed a synchronous `scrollTop` write this\n  // tick, `false` when the delta was zero or the write was deferred (iOS).\n  // `resizeItem` uses that to decide whether the follow-up `notify` must be\n  // synchronous so the grown transforms commit in the same paint (#1227).\n  private applyScrollAdjustment(\n    delta: number,\n    behavior?: ScrollBehavior,\n  ): boolean {\n    if (delta === 0) return false\n\n    if (process.env.NODE_ENV !== 'production' && this.options.debug) {\n      console.info('correction', delta)\n    }\n\n    // The correction moves the content the viewport is on; an offset target\n    // moves with it, or reconcile would wait for a position it can never see.\n    this._followOffsetTarget(delta)\n\n    if (!this._canWriteScroll()) {\n      // Hold the correction: `scrollOffset` takes it as if written, the rows\n      // are exposed shifted back by it. The notify must be synchronous like\n      // a write's, so the shifted rows commit in the same paint as the\n      // content change that caused the correction.\n      this._holdOffset += delta\n      if (this.scrollOffset !== null) this.scrollOffset += delta\n      return true\n    } else {\n      const offset = this.getScrollOffset()\n      this._clampedAdjustment = this._clampedBy(offset + delta)\n      const write = this._scrollToOffset(offset, {\n        adjustments: 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). A\n      // `scrollToFn` that reports the write synchronously has already set\n      // `scrollOffset` to the read-back (and cleared `pendingWrite`).\n      if (this.scrollOffset !== null) {\n        if (this.pendingWrite === write) this.scrollOffset += delta\n        // Clamp only the lower bound: a negative offset is unreachable, and\n        // on an unscrollable element (content fits the viewport) no scroll\n        // event ever fires to correct it, permanently skewing\n        // getDistanceFromEnd() and wedging the hold flush (#1229).\n        // Upper-bound overflow stays untouched — it is transiently\n        // legitimate mid-prepend while the consumer's sizer catches up.\n        if (this.scrollOffset < 0) this.scrollOffset = 0\n      }\n      return true\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    // The element is let go of: give it back its overflow now. A stop the\n    // next element needs starts afresh.\n    this._momentumStop?.restore()\n    this._momentumStop = null\n    // The debounce cancelled above is the only thing that writes `isScrolling`\n    // back to false, so a cleanup inside the reset window would strand it, and\n    // the direction derived from it, as true. That matters because `cleanup`\n    // also runs when the scroll element changes or `enabled` goes false, where\n    // the instance lives on.\n    this.isScrolling = false\n    this.scrollDirection = null\n    // The iOS gesture/deferral state is scoped to the current scroll\n    // element: the touch listeners that maintain it were just removed, and\n    // an in-flight touch keeps targeting the old element (implicit touch\n    // capture), so the new element never reports it. Carrying the state\n    // over would replay a stale deferred delta on the new element's first\n    // flush, and a cleanup that lands mid-touch or inside the post-touchend\n    // grace window would strand the gesture (the listeners that end it were\n    // just removed), deferring every adjustment on the new element until\n    // its next touch cycle.\n    this._holdOffset = 0\n    this._reportedOverscroll = false\n    // (The gesture was ended with its listeners, in the unsubs above.)\n    this._clampedAdjustment = null\n    // A write to the old element will never be read back.\n    this.pendingWrite = 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          // Past the top is never a resting position. Past the bottom is\n          // judged only while scrolling: at rest the element has clamped,\n          // and a stale sizer makes no bounce.\n          const elementMax = isScrolling ? this._elementMaxScrollOffset() : null\n          const wasOverscrolled = this._reportedOverscroll\n          this._reportedOverscroll =\n            offset < 0 || (elementMax !== null && offset > elementMax + 1)\n          const elementOffset = offset\n          this._lastElementOffset = elementOffset\n          // Everything below works in layout coordinates.\n          offset = this._toLayoutOffset(offset)\n\n          const kind = this._classifyScrollEvent(\n            offset,\n            isScrolling,\n            elementMax,\n          )\n          if (kind === 'spurious') return\n\n          if (kind === 'readBack') {\n            // Adopt the exact target over the browser's rounded value (see\n            // `pendingWrite`).\n            offset = this.pendingWrite!.target\n          } else if (\n            kind === 'clampedReadBack' &&\n            this.scrollState?.index != null &&\n            // Not `elementMax`: an adapter can report the read-back at rest.\n            offset < this.getMaxScrollOffset() - 1.5\n          ) {\n            // Our write, clamped at a max the sizer has since grown back\n            // from: reconcile writes the target again, even when the layout\n            // came back to the same end.\n            this.scrollState.lastTargetOffset = offset\n          } else if (\n            externalRetiresCommand({\n              kind,\n              offset,\n              command: this.scrollState,\n              target: () => this.getScrollStateTarget(this.scrollState!),\n            })\n          ) {\n            this.scrollState = null\n          }\n          this.pendingWrite = null\n\n          // A pending clamped compensation write (#1258) survives only its\n          // own read-back, which the browser reports at the scroll max we\n          // saw at write time. Anything else is a real gesture (or the write\n          // landing after all), so drop it rather than yank the user later.\n          // Not `kind !== 'clampedEcho'`: the classifier ranks `readBack` and\n          // `clampedReadBack` first, and either can also sit at that max, so\n          // the record must survive them too.\n          if (\n            this._clampedAdjustment !== null &&\n            Math.abs(offset - this._clampedAdjustment.maxAtWrite) >= 1.5\n          ) {\n            this._clampedAdjustment = null\n          }\n\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          const prevDirection = this.scrollDirection\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          // A finger that lands on a fling fires no touch events (#1307), so\n          // while a command waits for the fling, the scroll events are all\n          // that show the user taking over: the scroll turns back, or speeds\n          // up (`flingSpedUp`). Momentum does neither inside the scroll\n          // range; a bounce does both, so no part of one counts.\n          const queued = this.scrollState\n          if (\n            queued?.phase === 'queued' &&\n            kind === 'external' &&\n            isScrolling\n          ) {\n            if (wasOverscrolled || this._reportedOverscroll) {\n              queued.samples = []\n            } else {\n              const t = this.now()\n              queued.samples = [\n                ...(queued.samples ?? []).filter(\n                  (sample) => t - sample.t <= 200,\n                ),\n                { t, offset: elementOffset },\n              ]\n              if (\n                (prevDirection !== null &&\n                  this.scrollDirection !== prevDirection) ||\n                flingSpedUp(queued.samples)\n              ) {\n                this.scrollState = null\n              }\n            }\n          }\n          if (\n            this._iosGesture.onScroll({\n              isScrolling,\n              ownReadBack: kind === 'readBack',\n              moved: offset !== prevOffset,\n              // Neither our write's read-back nor a frame of our smooth\n              // animation: the user or a fling moved it.\n              external:\n                kind === 'external' &&\n                this.scrollState?.phase !== 'smooth' &&\n                this.scrollState?.phase !== 'smoothFinishing',\n            }) &&\n            // The user scrolls: a command still waiting for the tail is\n            // theirs to override, like a written one would be.\n            this.scrollState?.phase === 'queued'\n          ) {\n            this.scrollState = null\n          }\n\n          // A held correction is written once a write is possible.\n          this._flushHoldIfReady(true)\n\n          if (this.scrollState) {\n            this.scheduleScrollReconcile()\n          }\n          this.maybeNotify()\n        }),\n      )\n\n      // Touch event listeners (iOS-aware deferral).\n      if ('addEventListener' in this.scrollElement) {\n        this.unsubs.push(\n          this._iosGesture.listen(this.scrollElement as unknown as EventTarget),\n        )\n      }\n\n      this._scrollToOffset(this.getScrollOffset())\n    }\n\n    // The consumer has committed the sizer.\n    this._noteClampMax()\n\n    const anchor = this.pendingScrollAnchor\n    this.pendingScrollAnchor = null\n\n    if (anchor && this.scrollElement && this.options.enabled) {\n      if (anchor.kind === 'anchor') {\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        //\n        // `setOptions` found the element writable; a scroll event between\n        // it and this commit (a concurrent render) can have changed that.\n        // Hold the delta after all and have the rows re-rendered shifted;\n        // an update scheduled from a layout effect commits before paint.\n        if (!this._canWriteScroll()) {\n          this._holdOffset += anchor.delta\n          this._followOffsetTarget(anchor.delta)\n          this.notify(false)\n        } else if (\n          isSmoothScroll(this.scrollState) &&\n          !approxEqual(\n            this.getScrollOffset() - anchor.delta,\n            this.scrollState.lastTargetOffset,\n          )\n        ) {\n          // A smooth programmatic scroll is still travelling. Writing scrollTop\n          // here would cancel the browser's animation, and Chromium drops a\n          // smooth request re-issued in the frame right after that cancel, so\n          // the journey would be stranded. The target is index-based and\n          // recomputes against the new layout in reconcileScroll, so let the\n          // animation run; the next scroll event re-syncs the tracked offset.\n          // A smooth scroll that has already landed (offset at its target,\n          // reconcile not yet retired it) still gets the anchor sync.\n        } else {\n          this._followOffsetTarget(anchor.delta)\n          this._scrollToOffset(this.getScrollOffset())\n        }\n      } else {\n        this.scrollToEnd({ behavior: anchor.behavior })\n      }\n    }\n\n    // A hold whose cause has passed without a scroll event (the sizer caught\n    // up with a position that read as overscrolled) is written here. An\n    // update scheduled from a layout effect commits before paint, so the\n    // notify need not be synchronous.\n    this._flushHoldIfReady(false)\n    // The consumer has committed the new total size by now, so a clamped\n    // compensation write may have room (#1258).\n    this._retryClampedAdjustment()\n  }\n\n  // Classify a scroll event (see `ScrollEventKind`) from the state as it was\n  // before the event. `offset` is the reported position in layout\n  // coordinates; `elementMax` is the element's own max, read only while\n  // scrolling (null otherwise).\n  private _classifyScrollEvent = (\n    offset: number,\n    isScrolling: boolean,\n    elementMax: number | null,\n  ) =>\n    classifyScrollEvent({\n      offset,\n      isScrolling,\n      elementMax,\n      holdOffset: this._holdOffset,\n      scrollOffset: this.scrollOffset,\n      pendingWrite: this.pendingWrite,\n      clampedMaxAtWrite: this._clampedAdjustment?.maxAtWrite ?? null,\n    })\n\n  // Re-issue a compensation write the browser clamped because the sizer had\n  // not grown yet (#1258, #1266). Called after `notify` in `resizeItem`,\n  // which covers consumers that size the container synchronously inside\n  // `onChange` (direct DOM updates, flushSync renders — where no re-render\n  // may follow at all), and from `_willUpdate` for consumers that size it\n  // during an asynchronous render. Both the clamped read-back and the\n  // absence of one leave `_clampedAdjustment` set, so timing does not matter.\n  // While the element cannot take a write (`_canWriteScroll`) the record is\n  // kept for the next opportunity, the latest being the tail closing.\n  private _retryClampedAdjustment = () => {\n    if (\n      this._clampedAdjustment === null ||\n      !this.scrollElement ||\n      !this.options.enabled ||\n      !this._canWriteScroll()\n    ) {\n      return\n    }\n    const { target, maxAtWrite } = this._clampedAdjustment\n    const max = this.getMaxScrollOffset()\n    if (max > maxAtWrite + 0.5) {\n      // Still short (the sizer grew only partially): stay pending against\n      // the new max so the next opportunity retries.\n      this._clampedAdjustment =\n        target > max + 0.5 ? { target, maxAtWrite: max } : null\n      this._scrollToOffset(target)\n    }\n  }\n\n  // Write the command that `_startScroll` left waiting for the momentum\n  // tail, against the layout as it is now (rows measured during the fling\n  // have moved an index target).\n  private _writeAwaitingCommand = () => {\n    const state = this.scrollState\n    if (state === null || state.phase !== 'queued') return\n    const { behavior } = state\n    this.getMeasurements()\n    const offset = this.getScrollStateTarget(state)\n    state.lastTargetOffset = offset\n    // The hold flushed just before can leave a clamp retry (#1258); it\n    // would write its old target over this command.\n    this._clampedAdjustment = null\n    state.phase = initialScrollPhase(\n      behavior,\n      state.index != null && approxEqual(offset, this.getScrollOffset()),\n    )\n    this._scrollToOffset(offset, { behavior })\n    this.scheduleScrollReconcile()\n  }\n\n  // The element's position as the offset observers report it, or null for a\n  // scroll element that is neither an element nor a window.\n  private _readElementOffset = (): number | null => {\n    const el = this.scrollElement as unknown as Partial<\n      Element & Pick<Window, 'scrollX' | 'scrollY'>\n    > | null\n    if (el == null) return null\n    const { horizontal, isRtl } = this.options\n    if (typeof el.scrollTop === 'number') {\n      return horizontal ? el.scrollLeft! * ((isRtl && -1) || 1) : el.scrollTop\n    }\n    if (typeof el.scrollY === 'number') {\n      return horizontal ? el.scrollX! : el.scrollY\n    }\n    return null\n  }\n\n  // Whether a scrollTop write made now would reach the element and stay:\n  // - not on iOS while a touch gesture owns the scroll (`IosGesture`): a\n  //   dragging finger ignores the write, momentum is cancelled by it on\n  //   iOS 26 and earlier and overrides it within a frame on 27 (#884,\n  //   #1307), so a correction is held through the tail on every version;\n  // - not while the element is overscrolled past either edge (the\n  //   rubber-band bounce): WebKit discards the write and the bounce can\n  //   stall where it was (#1287).\n  // A write that is unwanted for another reason (a travelling smooth scroll\n  // owns the position) is a separate check at the call sites.\n  private _canWriteScroll = () =>\n    !(isIOSWebKit() && this._iosGesture.inMotion()) && !this._reportedOverscroll\n\n  // Write a held correction once a write is possible, from the scroll\n  // handler, the touch tail timer, `_willUpdate` and a resize notify. The\n  // rows go back to layout coordinates and the total grows by the hold in a\n  // notify issued before the write, so the sizer can take the position and\n  // both commit in the paint the write lands in. `sync` is false only where\n  // the caller already runs inside the consumer's commit (`_willUpdate`),\n  // where an update it schedules commits before paint anyway.\n  private _flushHoldIfReady = (sync: boolean) => {\n    if (this._holdOffset === 0) return\n    if (!this.scrollElement || !this.options.enabled) return\n    if (!this._canWriteScroll()) return\n    // Let a travelling smooth scroll land first (see `_willUpdate`).\n    if (this.scrollState?.phase === 'smooth') return\n    this._holdOffset = 0\n    // A held shrink can leave the layout position above the top; the\n    // element clamps that to 0 without an event to say so (#1229).\n    if (this.scrollOffset !== null && this.scrollOffset < 0) {\n      this.scrollOffset = 0\n    }\n    this.notify(sync)\n    // A command whose write has not been reported back yet owns the target:\n    // `scrollOffset` is still the pre-command position until its read-back,\n    // and a command that closes the touch tail makes a write possible with\n    // no scroll event in between, so this flush can run first.\n    const target = this.getCommandWrittenOffset() ?? this.getScrollOffset()\n    // A consumer that sizes the container after this write gets the retry\n    // (#1258).\n    this._clampedAdjustment = this._clampedBy(target)\n    this._scrollToOffset(target)\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 getScrollStateTarget(state: ScrollState) {\n    const offsetInfo = state.toEnd\n      ? ([Math.max(this.getMaxScrollOffset(), 0)] as const)\n      : state.index != null\n        ? this.getOffsetForIndex(state.index, state.align)\n        : undefined\n    return offsetInfo ? offsetInfo[0] : state.lastTargetOffset\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    // Nothing to reconcile until the tail closes and the command is written;\n    // only the safety valve above applies.\n    if (this.scrollState.phase === 'queued') {\n      this.scheduleScrollReconcile()\n      return\n    }\n\n    // A resize since the last render leaves measurementsCache stale until\n    // something reads getMeasurements(); rebuild it (memoized) so an index\n    // target reflects it even when no render ran in between.\n    this.getMeasurements()\n    const targetOffset = this.getScrollStateTarget(this.scrollState)\n\n    // Index targets can still depend on cached sizes during the first rAF,\n    // which runs before ResizeObserver delivers pending measurements. Wait\n    // another frame (two when measurements are themselves deferred to rAF)\n    // before retiring an index scroll. Absolute offsets don't need this wait.\n    const STABLE_FRAMES =\n      this.scrollState.index == null\n        ? 1\n        : this.options.useAnimationFrameWithResizeObserver\n          ? 3\n          : 2\n\n    const targetChanged = targetOffset !== this.scrollState.lastTargetOffset\n\n    if (!targetChanged && approxEqual(targetOffset, this.getScrollOffset())) {\n      // At the target: a travelling smooth scroll has landed, and a\n      // finishing one is now an instant scroll.\n      if (this.scrollState.phase === 'smooth') {\n        this.scrollState.phase = 'smoothLanded'\n      } else if (this.scrollState.phase === 'smoothFinishing') {\n        this.scrollState.phase = 'instant'\n      }\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, { behavior: 'auto' })\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          isSmoothScroll(this.scrollState) && distance > viewport\n\n        this.scrollState.lastTargetOffset = targetOffset\n        if (keepSmooth) {\n          // A smooth retarget travels again, so its intermediate scroll\n          // events must not read as an external scroll away from the target.\n          this.scrollState.phase = 'smooth'\n        } else if (this.scrollState.phase === 'smooth') {\n          // The final approach is instant, but the animation can still report.\n          this.scrollState.phase = 'smoothFinishing'\n        } else if (this.scrollState.phase === 'smoothLanded') {\n          this.scrollState.phase = 'instant'\n        }\n        // 'smoothFinishing' stays as it is (its animation may still report)\n        // until reconcile sees it at the target; 'instant' stays instant.\n\n        this._scrollToOffset(targetOffset, {\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 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      this.options.gap,\n    ],\n    (\n      count,\n      paddingStart,\n      scrollMargin,\n      getItemKey,\n      enabled,\n      lanes,\n      laneAssignmentMode,\n      gap,\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        gap,\n      }\n    },\n    {\n      key: false,\n    },\n  )\n\n  private isIndexInRange = (index: number): boolean =>\n    index >= 0 && index < this.options.count\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        gap,\n      },\n      _itemSizeCacheVersion,\n    ) => {\n      const itemSizeCache = this.itemSizeCache\n      if (!enabled) {\n        this.measurementsCache = []\n        this._singleLaneMeasurements = null\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._singleLaneMeasurements = null\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      if (lanes === 1) {\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._singleLaneMeasurements?.flat\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        }\n\n        const items: Array<Key | VirtualItem> =\n          min === 0\n            ? new Array(count)\n            : this._singleLaneMeasurements!.items.slice()\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          items[i] = key\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        this._singleLaneMeasurements = { flat, items }\n        const view = createLazyMeasurementsView(items, flat)\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<number | undefined> = new Array(lanes).fill(\n        undefined,\n      )\n      // Running end position of each lane's last item, so the shortest lane\n      // can be found with an O(lanes) argmin instead of the old backward walk\n      // through `measurements` (getFurthestMeasurement). `filledLanes` tracks\n      // how many lanes have at least one item, mirroring the previous\n      // \"all lanes seen → shortest lane, else i % lanes\" branch.\n      const laneEnds = new Float64Array(lanes)\n      let filledLanes = 0\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          if (laneLastIndex[item.lane] === undefined) filledLanes++\n          laneLastIndex[item.lane] = m\n          laneEnds[item.lane] = item.end\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 + gap\n            : paddingStart + scrollMargin\n        } else if (filledLanes === lanes) {\n          // No cache, every lane seeded: place in the shortest lane.\n          // Read the running per-lane ends (O(lanes) argmin) instead of the\n          // old backward scan. Tie-break on the lane's last-item index to\n          // preserve the previous sort-by-(end, index) placement exactly.\n          let bestLane = 0\n          let bestEnd = laneEnds[0]!\n          let bestIdx = laneLastIndex[0]!\n          for (let l = 1; l < lanes; l++) {\n            const e = laneEnds[l]!\n            if (e < bestEnd || (e === bestEnd && laneLastIndex[l]! < bestIdx)) {\n              bestLane = l\n              bestEnd = e\n              bestIdx = laneLastIndex[l]!\n            }\n          }\n          lane = bestLane\n          start = bestEnd + gap\n\n          if (shouldCacheLane) {\n            this.laneAssignments.set(i, lane)\n          }\n        } else {\n          // No cache and not every lane seeded yet — seed lanes in order,\n          // matching the previous `i % lanes` fallback for the first row.\n          lane = i % this.options.lanes\n          start = paddingStart + scrollMargin\n\n          if (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 + running end\n        if (laneLastIndex[lane] === undefined) filledLanes++\n        laneLastIndex[lane] = i\n        laneEnds[lane] = end\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      // scrollOffset is measured in the scroll element and the layout total\n      // from the list start, so the list ends scrollMargin further down.\n      this._getLayoutTotalSize() + this.options.scrollMargin,\n    ],\n    (measurements, outerSize, scrollOffset, lanes, listEnd) => {\n      if (measurements.length === 0 || outerSize === 0) {\n        this.range = null\n        return null\n      }\n      // Until the element reports a clamped position (the list shrank, a\n      // rubber-band bounce), the offset can sit past the last row, which\n      // would leave only that row in the range.\n      const maxScrollOffset = Math.max(listEnd - outerSize, 0)\n      this.range = calculateRangeImpl(\n        measurements,\n        outerSize,\n        Math.min(scrollOffset, maxScrollOffset),\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._singleLaneMeasurements !== null\n          ? this._singleLaneMeasurements.flat\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        this.options.lanes,\n      ]\n    },\n    (rangeExtractor, overscan, count, startIndex, endIndex, lanes) => {\n      return startIndex === null || endIndex === null\n        ? []\n        : rangeExtractor({\n            startIndex,\n            endIndex,\n            overscan,\n            count,\n            lanes,\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 (!isSmoothScroll(this.scrollState)) {\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    if (!this.isIndexInRange(index)) return\n\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    // Skip nodes that aren't attached yet: they have no layout and would be\n    // cached as 0. Vue calls function refs during patch, before the parent is\n    // inserted. The node is observed above, so the RO reports its size once\n    // it's connected.\n    if (\n      node.isConnected &&\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 (!this.isIndexInRange(index)) return\n\n    // An earlier entry in this ResizeObserver batch moved `scrollOffset`.\n    // Outside a batch its sync notify would have re-rendered and rebuilt the\n    // caches read below; rebuild them here so the anchoring check compares\n    // this item's current start, not a stale one, against the adjusted\n    // offset (#1218). Without a scroll move, the caches are exactly as stale\n    // as they were before batching, so skip the rebuild.\n    if (this._resizeBatch?.sync) this.getMeasurements()\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._singleLaneMeasurements?.flat\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        !isSmoothScroll(this.scrollState) &&\n        this.getVirtualDistanceFromEnd() <= this.options.scrollEndThreshold\n      const prevTotalSize = wasAtEnd ? this._getLayoutTotalSize() : 0\n      // Default anchoring predicate (used unless the consumer supplies a\n      // custom shouldAdjustScrollPositionOnItemSizeChange).\n      const scrollOffset = this.getScrollOffset()\n      const isFirstMeasure = !this.itemSizeCache.has(key)\n      const defaultShouldAdjust = isFirstMeasure\n        ? // First measurement: compensate any item whose top sits above the\n          // fold — the estimate→actual delta must be corrected regardless of\n          // scroll direction, since the whole estimated block was above it.\n          itemStart < scrollOffset\n        : // Re-measurement: only compensate an item that is ENTIRELY above the\n          // fold. An item that merely *spans* the fold (top above, bottom\n          // below — e.g. a streaming chat message growing at its bottom)\n          // changes size *below* the anchor point, so shifting scrollTop by the\n          // delta would drag the viewport downward on every growth (#1218).\n          // Also skip during backward scroll to avoid the \"items jump while\n          // scrolling up\" cascade.\n          itemStart + itemSize <= scrollOffset &&\n          this.scrollDirection !== 'backward'\n      const shouldAdjustScroll =\n        !isSmoothScroll(this.scrollState) &&\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          : defaultShouldAdjust)\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      // Before a command's read-back, an index or end target is retargeted\n      // from fresh measurements by reconcileScroll next frame; an offset\n      // target lands where it was written and the delta is not applied.\n      let adjustedSync = false\n      if (!this._awaitingCommandReadBack()) {\n        if (wasAtEnd) {\n          adjustedSync = this.applyScrollAdjustment(\n            this._getLayoutTotalSize() - prevTotalSize,\n          )\n        } else if (shouldAdjustScroll) {\n          adjustedSync = this.applyScrollAdjustment(delta)\n        }\n      }\n\n      // When we just moved `scrollTop` to compensate for an above-viewport\n      // resize, the grown item transforms must commit in the SAME frame as\n      // that write. `applyScrollAdjustment` writes `scrollTop` synchronously\n      // inside this ResizeObserver callback, but an async `notify` schedules\n      // the transform render for a later commit — so the browser can paint\n      // one frame with the new `scrollTop` and the old positions, and the\n      // viewport visibly jumps by `delta` before snapping back (#1227). A\n      // synchronous notify flushes the render in this same callback, so both\n      // land in one paint. When nothing moved (or the write was deferred on\n      // iOS), keep the cheaper async notify.\n      if (this._resizeBatch) {\n        // Inside a ResizeObserver callback: notify once after every entry\n        // is measured, synchronously if any of them moved `scrollTop`.\n        this._resizeBatch.notify = true\n        this._resizeBatch.sync ||= adjustedSync\n        return\n      }\n      this.notify(adjustedSync)\n      this._noteClampMax()\n      // A consumer that grows the sizer synchronously inside `onChange`\n      // (direct DOM updates) may never re-render when the range is\n      // unchanged, so retry a clamped write here rather than only in\n      // `_willUpdate` (#1266).\n      this._flushHoldIfReady(true)\n      this._retryClampedAdjustment()\n    }\n  }\n\n  getVirtualItems = memo(\n    () => [this.getVirtualIndexes(), this.getMeasurements(), this._holdOffset],\n    (indexes, measurements, hold) => {\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        // A held correction is exposed as a shift of every row (see\n        // `_holdOffset`); the layout itself is untouched.\n        virtualItems.push(\n          hold === 0\n            ? measurement\n            : {\n                ...measurement,\n                start: measurement.start - hold,\n                end: measurement.end - hold,\n              },\n        )\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._singleLaneMeasurements?.flat\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  // Record the element's max, in layout coordinates, as one a command's\n  // pending instant write may be clamped to (see `lowMaxes` on\n  // `pendingWrite`). Called where the sizer can have been committed: after\n  // a notify, for a consumer that sizes it in `onChange`, and in\n  // `_willUpdate`. The element cannot clamp below its own 0, which is the\n  // hold in layout coordinates.\n  private _noteClampMax = () => {\n    if (!this._awaitingCommandReadBack()) return\n    const elementMax = this._elementMaxScrollOffset()\n    if (elementMax === null) return\n    const write = this.pendingWrite!\n    const max = Math.max(elementMax, 0) + this._holdOffset\n    if (max >= write.target) return\n    const lowMaxes = (write.lowMaxes ??= [])\n    if (lowMaxes[lowMaxes.length - 1] !== max) lowMaxes.push(max)\n  }\n\n  // The element's scroll range in layout coordinates: while a correction is\n  // held the sizer is short by the hold, so the element's own max is too.\n  private getMaxScrollOffset = () =>\n    (this._elementMaxScrollOffset() ?? 0) + this._holdOffset\n\n  // An element position in layout coordinates: how far the layout position\n  // is ahead of the element. The element is `_holdOffset` behind while a\n  // correction is held, and a prepend's anchor delta behind from\n  // `setOptions` (which moved `scrollOffset` by it) until `_willUpdate`\n  // writes or holds it. Writes (`_scrollToOffset`) and the clamp record\n  // (`_clampedBy`) deliberately subtract the hold alone, not this whole\n  // lead: by the time they run, the anchor delta is already in\n  // `scrollOffset`, and writing that layout position is what closes it.\n  private _toLayoutOffset = (elementOffset: number) => {\n    let offset = elementOffset + this._holdOffset\n    if (this.pendingScrollAnchor?.kind === 'anchor') {\n      offset += this.pendingScrollAnchor.delta\n    }\n    return offset\n  }\n\n  // The element's own scroll range, or null where it cannot be read (no\n  // element, or a bare test double without `scrollHeight` / `document`).\n  private _elementMaxScrollOffset = (): number | null => {\n    const el = this.scrollElement\n    if (el === null) return null\n    if ('scrollHeight' in el) {\n      return this.options.horizontal\n        ? el.scrollWidth - el.clientWidth\n        : el.scrollHeight - el.clientHeight\n    }\n    if ('document' in el) {\n      const doc = el.document.documentElement\n      return this.options.horizontal\n        ? doc.scrollWidth - el.innerWidth\n        : doc.scrollHeight - el.innerHeight\n    }\n    return null\n  }\n\n  // Stop a running fling, then call `done`: the momentum does not survive\n  // the element losing its overflow for a frame. Hidden and restored within\n  // one task, iOS never sees the change and the fling carries on (27.0.1\n  // iPhone); hidden for two frames, it stops at once, there and in Chrome on\n  // Android. Nothing moves on screen. A second call while one is in progress\n  // waits for the same frames. The app's inline value comes back, unless the\n  // app set a new one meanwhile; `done` is then not called.\n  private _momentumStop: { restore: () => boolean; done: () => void } | null =\n    null\n  private _stopMomentum = (done: () => void) => {\n    const el = this.scrollElement\n    const win = this.targetWindow\n    if (el === null || win === null) return\n    const scroller = (\n      'document' in el ? el.document.scrollingElement : el\n    ) as HTMLElement | null\n    // A test double may have no style to change.\n    if (!scroller?.style) return\n    if (this._momentumStop) {\n      this._momentumStop.done = done\n      return\n    }\n    const { style } = scroller\n    const property = this.options.horizontal ? 'overflow-x' : 'overflow-y'\n    const value = style.getPropertyValue(property)\n    const priority = style.getPropertyPriority(property)\n    const crossSize = () =>\n      this.options.horizontal ? scroller.clientHeight : scroller.clientWidth\n    const crossSizeBefore = crossSize()\n    style.setProperty(property, 'hidden', 'important')\n    // A classic scrollbar takes layout space, so hiding it would reflow the\n    // content for two frames (a touchscreen laptop). Put it back before\n    // anything paints and leave the command to the tail, as without a style.\n    if (crossSize() !== crossSizeBefore) {\n      style.setProperty(property, value, priority)\n      return\n    }\n    const stop = {\n      // False when the app replaced the hidden value: the fling may not\n      // have stopped.\n      restore: () => {\n        if (\n          style.getPropertyValue(property) !== 'hidden' ||\n          style.getPropertyPriority(property) !== 'important'\n        ) {\n          return false\n        }\n        style.setProperty(property, value, priority)\n        return true\n      },\n      done,\n    }\n    this._momentumStop = stop\n    win.requestAnimationFrame(() =>\n      win.requestAnimationFrame(() => {\n        // Already restored by `cleanup`, which also drops its command.\n        if (this._momentumStop !== stop) return\n        this._momentumStop = null\n        // The command waits for the tail, as without the stop.\n        if (stop.restore()) stop.done()\n      }),\n    )\n  }\n\n  // A compensation write past the element's current max (the sizer has not\n  // grown yet) is clamped by the browser; record it for the retry (#1258).\n  private _clampedBy = (target: number) => {\n    const elementMax = this._elementMaxScrollOffset()\n    if (elementMax === null) return null\n    const maxAtWrite = elementMax + this._holdOffset\n    return target > maxAtWrite + 0.5 ? { target, maxAtWrite } : null\n  }\n\n  private getVirtualDistanceFromEnd = () => {\n    // `_getLayoutTotalSize()` measures the sizer, which starts `scrollMargin`\n    // into the scroll content, while `getScrollOffset()` is measured from the\n    // top of that content. Lift the total into the element's space before\n    // subtracting, or the viewport reads `scrollMargin` px closer to the end\n    // than it is and `getDistanceFromEnd()` disagrees by that much.\n    return Math.max(\n      this._getLayoutTotalSize() +\n        this.options.scrollMargin -\n        this.getSize() -\n        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    // Not `measurementsCache`: that field is only rebuilt by getMeasurements,\n    // so it lags a size change until the next render reads the items.\n    const item = this.getMeasurements()[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 (#1001),\n    // but swap paddingEnd for scrollPaddingEnd so the last item lands where\n    // any other end-aligned item would instead of overshooting past it (#1257).\n    if (align === 'end' && index === this.options.count - 1) {\n      const maxOffset = this.getMaxScrollOffset()\n      const toOffset =\n        maxOffset - this.options.paddingEnd + this.options.scrollPaddingEnd\n      return [Math.max(Math.min(toOffset, maxOffset), 0), 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    this._startScroll(\n      { index: null, align },\n      this.getOffsetForAlignment(toOffset, align),\n      behavior,\n      'absolute',\n    )\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    // No target (an empty list), so nothing is written.\n    if (!offsetInfo) return\n    const [offset, align] = offsetInfo\n\n    this._startScroll({ index, align }, offset, behavior, 'absolute')\n  }\n\n  scrollBy = (\n    delta: number,\n    { behavior = 'auto' }: ScrollToOffsetOptions = {},\n  ) => {\n    // Build on a position we just wrote even before its scroll event arrives.\n    // Clamp: a write past either edge that leaves the element where it was\n    // fires no scroll event, so nothing would clear an unreachable offset.\n    const offset = this.getOffsetForAlignment(\n      (this.getCommandWrittenOffset() ?? this.getScrollOffset()) + delta,\n      'start',\n    )\n\n    this._startScroll(\n      { index: null, align: 'start' },\n      offset,\n      behavior,\n      'relative',\n    )\n  }\n\n  scrollToEnd = ({ behavior = 'auto' }: ScrollToEndOptions = {}) => {\n    if (this.options.count > 0) {\n      // Target the browser's max scroll rather than the last item's end-align\n      // offset, so paddingEnd is included and isAtEnd() holds afterwards.\n      this._startScroll(\n        { index: this.options.count - 1, align: 'end', toEnd: true },\n        Math.max(this.getMaxScrollOffset(), 0),\n        behavior,\n        'absolute',\n      )\n      return\n    }\n\n    this.scrollToOffset(Math.max(this.getTotalSize() - this.getSize(), 0), {\n      behavior,\n    })\n  }\n\n  // Every scroll command starts here: it becomes the in-flight command,\n  // writes its first target and leaves reconcile to retarget and retire it.\n  //\n  // Targets are layout offsets. A held correction is not dropped by a\n  // command: the write lands the element `_holdOffset` short of the target,\n  // under the rows exposed shifted by the same amount, and the flush moves\n  // both together once a write is possible.\n  //\n  // An index or end target that is already at its offset starts a smooth\n  // scroll as landed; an offset target never does, so its first scroll\n  // event is read as the user's (see the scroll handler in `_willUpdate`).\n  private _startScroll(\n    target: Pick<ScrollState, 'index' | 'align' | 'toEnd'>,\n    offset: number,\n    behavior: ScrollBehavior,\n    kind: 'absolute' | 'relative',\n  ) {\n    // A new explicit command supersedes layout-driven work queued before it.\n    // Clear both before any iOS deferral so a later commit/retry cannot\n    // overwrite the user's newer scroll intent.\n    this.pendingScrollAnchor = null\n    this._clampedAdjustment = null\n\n    const tail = this._iosGesture.tail()\n    if (kind === 'absolute' && tail !== null) {\n      if (tail === 'fling' && momentumOverridesWrites()) {\n        // A write now would not end the fling: on iOS 27 it shows for one\n        // frame and the fling carries on along its own path (#1307, step 3);\n        // in Chrome on Android the fling carries on from the written\n        // position. The command would be lost or overshot. Stop the fling\n        // and write two frames later. Otherwise (no style to change, a\n        // classic scrollbar, a finger down, a bounce) the tail stays open and\n        // the command is written when it closes, ~150ms after the last\n        // fling frame. The user taking over before the write (a drag, a\n        // second flick, a finger stopping the fling) cancels the command\n        // (see the scroll handler and `onTailClosed`). A relative command\n        // (`scrollBy`) is not postponed: its target is taken from the\n        // position at the call, which the fling leaves behind either way.\n        this._stopMomentum(() => {\n          const state = this.scrollState\n          if (\n            state?.phase !== 'queued' ||\n            // A finger came down: it owns the scroll until it lifts.\n            this._iosGesture.tail() !== 'fling' ||\n            // In a bounce WebKit can drop the write (#1287): the tail\n            // decides, as without the stop. (Not `flingCaught`: our stop\n            // also ends the fling at speed, so a slow frame would read as\n            // a catch and the tail would drop the command.)\n            this._reportedOverscroll\n          ) {\n            return\n          }\n          this._iosGesture.end()\n          this._flushHoldIfReady(true)\n          this._writeAwaitingCommand()\n        })\n        this.scrollState = {\n          ...target,\n          startedAt: this.now(),\n          lastTargetOffset: offset,\n          stableFrames: 0,\n          phase: 'queued',\n          behavior,\n          samples: [],\n        }\n        this.scheduleScrollReconcile()\n        return\n      }\n      // The command takes over the scroll, so close the tail: the landing's\n      // corrections then apply before paint, even for a command issued from\n      // a tap handler inside the tail (#1250). On iOS 26 and earlier the\n      // write stops the momentum. With a finger down the user owns the\n      // scroll: leave it.\n      this._iosGesture.end()\n    }\n    this.scrollState = {\n      ...target,\n      startedAt: this.now(),\n      lastTargetOffset: offset,\n      stableFrames: 0,\n      behavior,\n      phase: initialScrollPhase(\n        behavior,\n        target.index != null && approxEqual(offset, this.getScrollOffset()),\n      ),\n    }\n    this._scrollToOffset(offset, { behavior })\n    this.scheduleScrollReconcile()\n  }\n\n  // Drops the target of an in-flight scrollToIndex / scrollToOffset /\n  // scrollBy / scrollToEnd so a user gesture can take over the viewport.\n  // The scroll position is left untouched: writing it would stop iOS\n  // momentum, and a real gesture already interrupts a native smooth scroll.\n  cancelScroll = () => {\n    if (this.rafId != null && this.targetWindow) {\n      this.targetWindow.cancelAnimationFrame(this.rafId)\n      this.rafId = null\n    }\n    this.scrollState = null\n  }\n\n  // The size the consumer gives the container: the layout's total, short by\n  // a held correction so the rows exposed shifted by it still fill it (see\n  // `_holdOffset`).\n  getTotalSize = () =>\n    Math.max(this._getLayoutTotalSize() - this._holdOffset, 0)\n\n  private _getLayoutTotalSize = () => {\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._singleLaneMeasurements?.flat\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<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  /**\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<VirtualItem> => {\n    const snapshot: Array<VirtualItem> = []\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    }: { adjustments?: number; behavior?: ScrollBehavior } = {},\n  ) => {\n    const write = {\n      target: offset + (adjustments ?? 0),\n      smooth: behavior === 'smooth',\n    }\n    this.pendingWrite = write\n    // The element sits `_holdOffset` behind the layout while a correction\n    // is held; `target` and the read-back stay in layout coordinates.\n    this.options.scrollToFn(\n      offset - this._holdOffset,\n      { behavior, adjustments },\n      this,\n    )\n    return write\n  }\n\n  // Where the in-flight command's last instant write put the element, until\n  // its scroll event arrives; the rows on screen are still the ones rendered\n  // for the old `scrollOffset`. Null after a smooth write (the element is\n  // somewhere on the way) and without a command, so a write the browser\n  // ignored (no read-back) does not outlive its command.\n  private getCommandWrittenOffset = () =>\n    this.scrollState !== null &&\n    this.pendingWrite !== null &&\n    !this.pendingWrite.smooth\n      ? this.pendingWrite.target\n      : null\n\n  // A scroll command (or reconcile) wrote a new position that neither a\n  // scroll event nor an eager update has reflected in `scrollOffset` yet.\n  // The rows on screen were rendered for the old position, so \"above the\n  // viewport\" means nothing against either offset: a correction decided now\n  // would be written over the command. Compensation writes and the prepend\n  // anchor sync update `scrollOffset` eagerly, and the hold's flush writes\n  // exactly `scrollOffset`, so none of them count. Under a dragging finger\n  // iOS ignores the write, so no read-back will come and the hold takes the\n  // correction instead.\n  private _awaitingCommandReadBack = () => {\n    const writtenOffset = this.getCommandWrittenOffset()\n    return (\n      !(isIOSWebKit() && this._iosGesture.dragging()) &&\n      writtenOffset !== null &&\n      !approxEqual(writtenOffset, this.getScrollOffset())\n    )\n  }\n\n  // An offset target (scrollToOffset, scrollBy) is a layout position. A\n  // correction for content above the viewport moves the viewport's layout\n  // position by `delta`, and the target moves with it, so reconcile sees the\n  // command reached rather than waiting for a position it can never see\n  // (#1307, step 5). Index and end targets are recomputed from the layout.\n  private _followOffsetTarget = (delta: number) => {\n    if (this.scrollState !== null && this.scrollState.index == null) {\n      this.scrollState.lastTargetOffset += delta\n    }\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<VirtualItem>,\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","IosGesture","flingCaught","opts","getMeasurementKey","memo","_a","externalRetiresCommand","flingSpedUp","approxEqual","classifyScrollEvent","isIOSWebKit","createLazyMeasurementsView","key","notUndefined","toOffset","momentumOverridesWrites","startIndex","endIndex"],"mappings":"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"}