{"version":3,"file":"index.cjs","sources":["../../src/src/core/utils.ts","../../src/src/core/cache.ts","../../src/src/core/environment.ts","../../src/src/core/scroller.ts","../../src/src/core/store.ts","../../src/src/core/resizer.ts"],"sourcesContent":["/** @internal */\nexport const NULL = null;\n\n/** @internal */\nexport const { min, max, abs, floor } = Math;\n\n/**\n * @internal\n */\nexport const clamp = (\n  value: number,\n  minValue: number,\n  maxValue: number,\n): number => min(maxValue, max(minValue, value));\n\n/**\n * @internal\n */\nexport const sort = <T extends number>(arr: readonly T[]): T[] => {\n  return [...arr].sort((a, b) => a - b);\n};\n\n/**\n * @internal\n */\nexport const microtask: (fn: () => void) => void =\n  typeof queueMicrotask === \"function\"\n    ? queueMicrotask\n    : (fn) => {\n        Promise.resolve().then(fn);\n      };\n\n/**\n * @internal\n */\nexport const createPromise = <T = void>(): [Promise<T>, (arg: T) => void] => {\n  let resolve: ((arg: T) => void) | undefined;\n  const promise = new Promise<T>((res) => {\n    resolve = res;\n  });\n  return [promise, resolve!];\n};\n\n/**\n * @internal\n */\nexport const once = <T>(fn: () => T): (() => T) => {\n  let cache: T;\n\n  return () => {\n    if (fn) {\n      cache = fn();\n      fn = undefined!;\n    }\n    return cache;\n  };\n};\n","import { type InternalCacheSnapshot, type ItemsRange } from \"./types.js\";\nimport { clamp, floor, max, min, sort } from \"./utils.js\";\n\ntype Writeable<T> = {\n  -readonly [key in keyof T]: Writeable<T[key]>;\n};\n\n/** @internal */\nexport const UNCACHED = -1;\n\n/**\n * @internal\n */\nexport type Cache = {\n  readonly _length: number;\n  // sizes\n  readonly _sizes: number[];\n  readonly _defaultItemSize: number;\n  // offsets\n  readonly _computedOffsetIndex: number;\n  readonly _offsets: number[];\n};\n\nconst fill = (array: number[], length: number, prepend?: boolean): number[] => {\n  const key = prepend ? \"unshift\" : \"push\";\n  for (let i = 0; i < length; i++) {\n    array[key](UNCACHED);\n  }\n  return array;\n};\n\n/**\n * @internal\n */\nexport const getItemSize = (cache: Cache, index: number): number => {\n  const size = cache._sizes[index]!;\n  return size === UNCACHED ? cache._defaultItemSize : size;\n};\n\n/**\n * @internal\n */\nexport const setItemSize = (\n  cache: Writeable<Cache>,\n  index: number,\n  size: number,\n): boolean => {\n  const isInitialMeasurement = cache._sizes[index] === UNCACHED;\n  cache._sizes[index] = size;\n  // mark as dirty\n  cache._computedOffsetIndex = min(index, cache._computedOffsetIndex);\n  return isInitialMeasurement;\n};\n\n/**\n * @internal\n */\nexport const getItemOffset = (\n  cache: Writeable<Cache>,\n  index: number,\n): number => {\n  if (!cache._length) return 0;\n  if (cache._computedOffsetIndex >= index) {\n    return cache._offsets[index]!;\n  }\n\n  if (cache._computedOffsetIndex < 0) {\n    // first offset must be 0 to avoid returning NaN, which can cause infinite rerender.\n    // https://github.com/inokawa/virtua/pull/160\n    cache._offsets[0] = 0;\n    cache._computedOffsetIndex = 0;\n  }\n  let i = cache._computedOffsetIndex;\n  let top = cache._offsets[i]!;\n  while (i < index) {\n    top += getItemSize(cache, i);\n    cache._offsets[++i] = top;\n  }\n  // mark as measured\n  cache._computedOffsetIndex = index;\n  return top;\n};\n\n/**\n * Finds the index of an item in the cache whose computed offset is closest to the specified offset.\n *\n * @internal\n */\nexport const findIndex = (\n  cache: Cache,\n  offset: number,\n  low: number = 0,\n  high: number = cache._length - 1,\n): number => {\n  // Find with binary search\n  let found: number = low;\n  while (low <= high) {\n    const mid = floor((low + high) / 2);\n    if (getItemOffset(cache, mid) <= offset) {\n      found = mid;\n      low = mid + 1;\n    } else {\n      high = mid - 1;\n    }\n  }\n  return clamp(found, 0, cache._length - 1);\n};\n\n/**\n * @internal\n */\nexport const computeRange = (\n  cache: Cache,\n  startOffset: number,\n  endOffset: number,\n  prevStartIndex: number,\n): ItemsRange => {\n  // Clamp because prevStartIndex may exceed the limit when children decreased a lot after scrolling\n  prevStartIndex = min(prevStartIndex, cache._length - 1);\n\n  if (getItemOffset(cache, prevStartIndex) <= startOffset) {\n    // search forward\n    // start <= end, prevStartIndex <= start\n    const end = findIndex(cache, endOffset, prevStartIndex);\n    return [findIndex(cache, startOffset, prevStartIndex, end), end];\n  } else {\n    // search backward\n    // start <= end, start <= prevStartIndex\n    const start = findIndex(cache, startOffset, undefined, prevStartIndex);\n    return [start, findIndex(cache, endOffset, start)];\n  }\n};\n\n/**\n * @internal\n */\nexport const estimateDefaultItemSize = (\n  cache: Writeable<Cache>,\n  startIndex: number,\n): number => {\n  let measuredCountBeforeStart = 0;\n  // This function will be called after measurement so measured size array must be longer than 0\n  const measuredSizes: number[] = [];\n  cache._sizes.forEach((s, i) => {\n    if (s !== UNCACHED) {\n      measuredSizes.push(s);\n      if (i < startIndex) {\n        measuredCountBeforeStart++;\n      }\n    }\n  });\n\n  // Discard cache for now\n  cache._computedOffsetIndex = -1;\n\n  // Calculate median\n  const sorted = sort(measuredSizes);\n  const len = sorted.length;\n  const mid = (len / 2) | 0;\n  const median =\n    len % 2 === 0 ? (sorted[mid - 1]! + sorted[mid]!) / 2 : sorted[mid]!;\n\n  const prevDefaultItemSize = cache._defaultItemSize;\n\n  // Calculate diff of unmeasured items before start\n  return (\n    ((cache._defaultItemSize = median) - prevDefaultItemSize) *\n    max(startIndex - measuredCountBeforeStart, 0)\n  );\n};\n\n/**\n * @internal\n */\nexport const initCache = (\n  length: number,\n  itemSize: number,\n  sizes?: readonly number[],\n): Cache => {\n  return {\n    _defaultItemSize: itemSize,\n    _sizes: sizes\n      ? // https://github.com/inokawa/virtua/issues/441\n        fill(\n          sizes.slice(0, min(length, sizes.length)),\n          max(0, length - sizes.length),\n        )\n      : fill([], length),\n    _length: length,\n    _computedOffsetIndex: -1,\n    _offsets: fill([], length + 1),\n  };\n};\n\n/**\n * @internal\n */\nexport const takeCacheSnapshot = (cache: Cache): InternalCacheSnapshot => {\n  return [cache._sizes.slice(), cache._defaultItemSize];\n};\n\n/**\n * @internal\n */\nexport const updateCacheLength = (\n  cache: Writeable<Cache>,\n  length: number,\n  isShift?: boolean,\n): number => {\n  const diff = length - cache._length;\n\n  cache._computedOffsetIndex = isShift\n    ? // Discard cache for now\n      -1\n    : min(length - 1, cache._computedOffsetIndex);\n  cache._length = length;\n\n  if (diff > 0) {\n    // Added\n    fill(cache._offsets, diff);\n    fill(cache._sizes, diff, isShift);\n    return cache._defaultItemSize * diff;\n  } else {\n    // Removed\n    cache._offsets.splice(diff);\n    return (\n      isShift ? cache._sizes.splice(0, -diff) : cache._sizes.splice(diff)\n    ).reduce(\n      (acc, removed) =>\n        acc - (removed === UNCACHED ? cache._defaultItemSize : removed),\n      0,\n    );\n  }\n};\n","import { once } from \"./utils.js\";\n\n/**\n * @internal\n */\nexport const isBrowser = typeof window !== \"undefined\";\n\n/**\n * @internal\n */\nexport const getDocumentElement = (doc: Document): HTMLElement =>\n  doc.documentElement;\n\n/**\n * @internal\n */\nexport const getCurrentDocument = (node: HTMLElement): Document =>\n  node.ownerDocument;\n\n/**\n * @internal\n */\nexport const getCurrentWindow = (doc: Document) => doc.defaultView!;\n\n/**\n * Currently, all browsers on iOS/iPadOS are WebKit, including WebView.\n * @internal\n */\nexport const isIOSWebKit = /*#__PURE__*/ once((): boolean => {\n  if (/iP(hone|od|ad)/.test(navigator.userAgent)) {\n    return true;\n  }\n  // Modern iPad detection (iPadOS 13+)\n  // iPadOS 13+ reports the same userAgent/platform information as macOS, to enable desktop sites.\n  // So we treat devices that have macOS like information but with touch support as iPadOS.\n  // https://stackoverflow.com/questions/57776001/how-to-detect-ipad-pro-as-ipad-using-javascript\n  return navigator.platform === \"MacIntel\" && navigator.maxTouchPoints > 0;\n});\n\n/**\n * @internal\n */\nexport const isSmoothScrollSupported = /*#__PURE__*/ once((): boolean => {\n  return \"scrollBehavior\" in getDocumentElement(document).style;\n});\n","import {\n  getCurrentDocument,\n  getCurrentWindow,\n  getDocumentElement,\n  isIOSWebKit,\n  isSmoothScrollSupported,\n} from \"./environment.js\";\nimport {\n  ACTION_SCROLL,\n  type VirtualStore,\n  ACTION_SCROLL_END,\n  UPDATE_SIZE_EVENT,\n  ACTION_MANUAL_SCROLL,\n  ACTION_BEFORE_MANUAL_SMOOTH_SCROLL,\n  ACTION_START_OFFSET_CHANGE,\n} from \"./store.js\";\nimport { type ScrollToIndexOpts } from \"./types.js\";\nimport { clamp, createPromise, microtask, NULL } from \"./utils.js\";\n\nconst timeout = setTimeout;\n\nconst debounce = <T extends () => void>(fn: T, ms: number) => {\n  let id: ReturnType<typeof setTimeout> | undefined | null;\n\n  const cancel = () => {\n    if (id != NULL) {\n      clearTimeout(id);\n    }\n  };\n  const debouncedFn = () => {\n    cancel();\n    id = timeout(() => {\n      id = NULL;\n      fn();\n    }, ms);\n  };\n  debouncedFn._cancel = cancel;\n  return debouncedFn;\n};\n\n/**\n * scrollTop/scrollLeft can be negative value under certain styles.\n * - direction: rtl https://github.com/othree/jquery.rtl-scroll-type\n * - writing-mode   https://people.igalia.com/fwang/scrollable-elements-in-non-default-writing-modes/\n * - flex-direction: column-reverse/row-reverse\n *\n * top/left bottom/right\n * 0        100          spec compliant bottom/right overflow, or possibly top/left overflow in Chrome earlier than v85\n * -100     0            spec compliant top/left overflow\n * https://drafts.csswg.org/cssom-view/#scroll-an-element\n */\nconst normalizeScrollOffset = (offset: number, isNegative: boolean): number => {\n  return isNegative ? -offset : offset;\n};\n\nconst createScrollObserver = (\n  store: VirtualStore,\n  viewport: HTMLElement | Window,\n  isHorizontal: boolean,\n  getScrollOffset: () => number,\n  updateScrollOffset: (\n    value: number,\n    shift: boolean,\n    isMomentumScrolling: boolean,\n  ) => void,\n  getStartOffset?: () => number,\n) => {\n  const now = Date.now;\n\n  let lastScrollTime = 0;\n  let wheeling = false;\n  let touching = false;\n  let justTouchEnded = false;\n  let stillMomentumScrolling = false;\n\n  const onScrollEnd = debounce(() => {\n    if (wheeling || touching) {\n      wheeling = false;\n\n      // Wait while wheeling or touching\n      onScrollEnd();\n      return;\n    }\n\n    justTouchEnded = false;\n\n    store.$update(ACTION_SCROLL_END);\n  }, 150);\n\n  const onScroll = () => {\n    lastScrollTime = now();\n\n    if (justTouchEnded) {\n      stillMomentumScrolling = true;\n    }\n\n    if (getStartOffset) {\n      store.$update(ACTION_START_OFFSET_CHANGE, getStartOffset());\n    }\n    store.$update(ACTION_SCROLL, getScrollOffset());\n\n    onScrollEnd();\n  };\n\n  // Infer scroll state also from wheel events\n  // Sometimes scroll events do not fire when frame dropped even if the visual have been already scrolled\n  const onWheel = ((e: WheelEvent) => {\n    if (\n      wheeling ||\n      // Scroll start should be detected with scroll event\n      !store.$isScrolling() ||\n      // Probably a pinch-to-zoom gesture\n      e.ctrlKey\n    ) {\n      return;\n    }\n\n    const timeDelta = now() - lastScrollTime;\n    if (\n      // Check if wheel event occurs some time after scrolling\n      150 > timeDelta &&\n      50 < timeDelta &&\n      // Get delta before checking deltaMode for firefox behavior\n      // https://github.com/w3c/uievents/issues/181#issuecomment-392648065\n      // https://bugzilla.mozilla.org/show_bug.cgi?id=1392460#c34\n      (isHorizontal ? e.deltaX : e.deltaY)\n    ) {\n      wheeling = true;\n    }\n  }) as (e: Event) => void; // FIXME type error. why only here?\n\n  const onTouchStart = () => {\n    touching = true;\n    justTouchEnded = stillMomentumScrolling = false;\n  };\n  const onTouchEnd = () => {\n    touching = false;\n    if (isIOSWebKit()) {\n      justTouchEnded = true;\n    }\n  };\n\n  viewport.addEventListener(\"scroll\", onScroll);\n  viewport.addEventListener(\"wheel\", onWheel, { passive: true });\n  viewport.addEventListener(\"touchstart\", onTouchStart, { passive: true });\n  viewport.addEventListener(\"touchend\", onTouchEnd, { passive: true });\n\n  return {\n    _dispose: () => {\n      viewport.removeEventListener(\"scroll\", onScroll);\n      viewport.removeEventListener(\"wheel\", onWheel);\n      viewport.removeEventListener(\"touchstart\", onTouchStart);\n      viewport.removeEventListener(\"touchend\", onTouchEnd);\n      onScrollEnd._cancel();\n    },\n    _fixScrollJump: () => {\n      const [jump, shift] = store._flushJump();\n      if (!jump) return;\n      updateScrollOffset(jump, shift, stillMomentumScrolling);\n      stillMomentumScrolling = false;\n\n      if (shift && store.$getViewportSize() > store.$getTotalSize()) {\n        // In this case applying jump may not cause scroll.\n        // Current logic expects scroll event occurs after applying jump so we dispatch it manually.\n        store.$update(ACTION_SCROLL, getScrollOffset());\n      }\n    },\n  };\n};\n\ntype ScrollObserver = ReturnType<typeof createScrollObserver>;\n\ntype ScheduleScrollFunction = (\n  getTargetOffset: () => number,\n  smooth?: boolean,\n) => Promise<void>;\n\nconst createScrollScheduler = (\n  store: VirtualStore,\n  initialized: () => Promise<boolean>,\n  scroll: (offset: number, smooth?: boolean) => void,\n): [scroll: ScheduleScrollFunction, cancel: () => void] => {\n  let cancelScroll: (() => void) | undefined;\n\n  // The given offset will be clamped by browser\n  // https://drafts.csswg.org/cssom-view/#dom-element-scrolltop\n  return [\n    async (getTargetOffset, smooth) => {\n      // Wait for element assign. The element may be undefined if scrollRef prop is used and scroll is scheduled on mount.\n      // https://github.com/inokawa/virtua/pull/733\n      // https://github.com/inokawa/virtua/pull/750\n      if (!(await initialized())) {\n        return;\n      }\n\n      if (cancelScroll) {\n        // Cancel waiting scrollTo\n        cancelScroll();\n      }\n\n      const waitForMeasurement = (): [Promise<boolean>, () => void] => {\n        // Wait for the scroll destination items to be measured.\n        // The measurement will be done asynchronously and the timing is not predictable so we use promise.\n        const [promise, resolve] = createPromise<boolean>();\n        cancelScroll = () => {\n          resolve(false);\n        };\n\n        // Resize event may not happen when the window/tab is not visible, or during browser back in Safari.\n        // We have to wait for the initial measurement to avoid failing imperative scroll on mount.\n        // https://github.com/inokawa/virtua/issues/450\n        if (store.$getViewportSize()) {\n          // Cancel when items around scroll destination completely measured\n          timeout(cancelScroll, 150);\n        }\n        return [\n          promise,\n          store.$subscribe(UPDATE_SIZE_EVENT, () => {\n            resolve(true);\n          }),\n        ];\n      };\n\n      if (smooth && isSmoothScrollSupported()) {\n        store.$update(ACTION_BEFORE_MANUAL_SMOOTH_SCROLL, getTargetOffset());\n\n        // https://github.com/inokawa/virtua/issues/590\n        microtask(async () => {\n          while (true) {\n            let done = true;\n            for (let [i, end] = store.$getRange(); i <= end; i++) {\n              if (store.$isUnmeasuredItem(i)) {\n                done = false;\n                break;\n              }\n            }\n            if (done) {\n              break;\n            }\n            const [promise, unsubscribe] = waitForMeasurement();\n\n            try {\n              if (!(await promise)) {\n                // canceled\n                return;\n              }\n            } finally {\n              unsubscribe();\n            }\n          }\n\n          store.$update(ACTION_MANUAL_SCROLL);\n          scroll(getTargetOffset(), smooth);\n        });\n      } else {\n        while (true) {\n          const [promise, unsubscribe] = waitForMeasurement();\n\n          try {\n            store.$update(ACTION_MANUAL_SCROLL);\n            scroll(getTargetOffset());\n\n            if (!(await promise)) {\n              // canceled or finished\n              return;\n            }\n          } finally {\n            unsubscribe();\n          }\n        }\n      }\n    },\n    () => {\n      cancelScroll && cancelScroll();\n    },\n  ];\n};\n\ninterface Scroller<T extends HTMLElement | void> {\n  $observe: (containerElement: HTMLElement, viewport: T) => void;\n  $dispose(): void;\n  $fixScrollJump: () => void;\n  $isNegative(): boolean;\n}\n\n/**\n * @internal\n */\nexport const createScroller = (\n  store: VirtualStore,\n  isHorizontal: boolean,\n): Scroller<HTMLElement> & {\n  $scrollTo: (offset: number) => void;\n  $scrollBy: (offset: number) => void;\n  $scrollToIndex: (index: number, opts?: ScrollToIndexOpts) => void;\n} => {\n  let viewportElement: HTMLElement | undefined;\n  let scrollObserver: ScrollObserver | undefined;\n  let initialized = createPromise<boolean>();\n  let isNegative = false;\n  const scrollOffsetKey = isHorizontal ? \"scrollLeft\" : \"scrollTop\";\n  const overflowKey = isHorizontal ? \"overflowX\" : \"overflowY\";\n\n  const [scheduleScroll, cancelScroll] = createScrollScheduler(\n    store,\n    () => initialized[0],\n    (offset, smooth) => {\n      offset = normalizeScrollOffset(offset, isNegative);\n\n      if (smooth) {\n        viewportElement!.scrollTo({\n          [isHorizontal ? \"left\" : \"top\"]: offset,\n          behavior: \"smooth\",\n        });\n      } else {\n        viewportElement![scrollOffsetKey] = offset;\n      }\n    },\n  );\n\n  return {\n    $observe(_, viewport) {\n      viewportElement = viewport;\n\n      if (isHorizontal) {\n        isNegative = getComputedStyle(viewport).direction === \"rtl\";\n      }\n\n      scrollObserver = createScrollObserver(\n        store,\n        viewport,\n        isHorizontal,\n        () => normalizeScrollOffset(viewport[scrollOffsetKey], isNegative),\n        (jump, shift, isMomentumScrolling) => {\n          // If we update scroll position while touching on iOS, the position will be reverted.\n          // However iOS WebKit fires touch events only once at the beginning of momentum scrolling.\n          // That means we have no reliable way to confirm still touched or not if user touches more than once during momentum scrolling...\n          // This is a hack for the suspectable situations, inspired by https://github.com/prud/ios-overflow-scroll-to-top\n          if (isMomentumScrolling) {\n            const style = viewport.style;\n            const prev = style[overflowKey];\n            style[overflowKey] = \"hidden\";\n            timeout(() => {\n              style[overflowKey] = prev;\n            });\n          }\n\n          // Use absolute position not to exceed scrollable bounds\n          // https://github.com/inokawa/virtua/discussions/475\n          viewport[scrollOffsetKey] = normalizeScrollOffset(\n            store.$getScrollOffset() + jump,\n            isNegative,\n          );\n          if (shift) {\n            // https://github.com/inokawa/virtua/issues/357\n            cancelScroll();\n          }\n        },\n      );\n\n      initialized[1](true);\n    },\n    $dispose() {\n      scrollObserver && scrollObserver._dispose();\n      initialized[1](false);\n      // https://github.com/inokawa/virtua/pull/765\n      initialized = createPromise();\n    },\n    $isNegative: () => isNegative,\n    $scrollTo(offset) {\n      scheduleScroll(() => offset);\n    },\n    $scrollBy(offset) {\n      offset += store.$getScrollOffset();\n      scheduleScroll(() => offset);\n    },\n    $scrollToIndex(index, { align, smooth, offset = 0 } = {}) {\n      index = clamp(index, 0, store.$getItemsLength() - 1);\n\n      if (align === \"nearest\") {\n        const itemOffset = store.$getItemOffset(index);\n        const scrollOffset = store.$getScrollOffset();\n\n        if (itemOffset < scrollOffset) {\n          align = \"start\";\n        } else if (\n          itemOffset + store.$getItemSize(index) >\n          scrollOffset + store.$getViewportSize()\n        ) {\n          align = \"end\";\n        } else {\n          // already completely visible\n          return;\n        }\n      }\n\n      scheduleScroll(() => {\n        return (\n          offset +\n          store.$getStartSpacerSize() +\n          store.$getItemOffset(index) +\n          (align === \"end\"\n            ? store.$getItemSize(index) - store.$getViewportSize()\n            : align === \"center\"\n              ? (store.$getItemSize(index) - store.$getViewportSize()) / 2\n              : 0)\n        );\n      }, smooth);\n    },\n    $fixScrollJump: () => {\n      scrollObserver && scrollObserver._fixScrollJump();\n    },\n  };\n};\n\n/**\n * @internal\n */\nexport const createWindowScroller = (\n  store: VirtualStore,\n  isHorizontal: boolean,\n): Scroller<void> & {\n  $scrollToIndex: (index: number, opts?: ScrollToIndexOpts) => void;\n} => {\n  let containerElement: HTMLElement | undefined;\n  let scrollObserver: ScrollObserver | undefined;\n  let initialized = createPromise<boolean>();\n  let isNegative = false;\n  const scrollToKey = isHorizontal ? \"left\" : \"top\";\n\n  const [scheduleScroll] = createScrollScheduler(\n    store,\n    () => initialized[0],\n    (offset, smooth) => {\n      offset = normalizeScrollOffset(offset, isNegative);\n\n      const window = getCurrentWindow(getCurrentDocument(containerElement!));\n\n      if (smooth) {\n        window.scroll({\n          [scrollToKey]: offset,\n          behavior: \"smooth\",\n        });\n      } else {\n        window.scroll({\n          [scrollToKey]: offset,\n        });\n      }\n    },\n  );\n\n  const calcOffsetToViewport = (\n    node: HTMLElement,\n    viewport: HTMLElement,\n    window: Window,\n    isHorizontal: boolean,\n    offset: number = 0,\n  ): number => {\n    // TODO calc offset only when it changes (maybe impossible)\n    const offsetKey = isHorizontal ? \"offsetLeft\" : \"offsetTop\";\n    const offsetSum =\n      offset +\n      (isHorizontal && isNegative\n        ? window.innerWidth - node[offsetKey] - node.offsetWidth\n        : node[offsetKey]);\n\n    const parent = node.offsetParent;\n    if (node === viewport || !parent) {\n      return offsetSum;\n    }\n\n    return calcOffsetToViewport(\n      parent as HTMLElement,\n      viewport,\n      window,\n      isHorizontal,\n      offsetSum,\n    );\n  };\n\n  return {\n    $observe(container) {\n      containerElement = container;\n      const scrollOffsetKey = isHorizontal ? \"scrollX\" : \"scrollY\";\n\n      const document = getCurrentDocument(container);\n      const window = getCurrentWindow(document);\n\n      if (isHorizontal) {\n        // Detect RTL document\n        isNegative =\n          getComputedStyle(getDocumentElement(document)).direction === \"rtl\";\n      }\n\n      scrollObserver = createScrollObserver(\n        store,\n        window,\n        isHorizontal,\n        () => normalizeScrollOffset(window[scrollOffsetKey], isNegative),\n        (jump, shift) => {\n          // TODO support case two window scrollers exist in the same view\n          if (shift) {\n            // Use absolute position not to exceed scrollable bounds\n            window.scroll({\n              [scrollToKey]: normalizeScrollOffset(\n                store.$getScrollOffset() + jump,\n                isNegative,\n              ),\n            });\n          } else {\n            // Use window.scrollBy here, which causes less layout shift for some reason.\n            window.scrollBy({\n              [scrollToKey]: normalizeScrollOffset(jump, isNegative),\n            });\n          }\n        },\n        () =>\n          calcOffsetToViewport(container, document.body, window, isHorizontal),\n      );\n\n      initialized[1](true);\n    },\n    $dispose() {\n      scrollObserver && scrollObserver._dispose();\n      containerElement = undefined;\n      initialized[1](false);\n      // https://github.com/inokawa/virtua/pull/765\n      initialized = createPromise();\n    },\n    $isNegative: () => isNegative,\n    $fixScrollJump: () => {\n      scrollObserver && scrollObserver._fixScrollJump();\n    },\n    $scrollToIndex(index, { align, smooth, offset = 0 } = {}) {\n      if (!containerElement) return;\n\n      index = clamp(index, 0, store.$getItemsLength() - 1);\n\n      if (align === \"nearest\") {\n        const itemOffset = store.$getItemOffset(index);\n        const scrollOffset = store.$getScrollOffset();\n\n        if (itemOffset < scrollOffset) {\n          align = \"start\";\n        } else if (\n          itemOffset + store.$getItemSize(index) >\n          scrollOffset + store.$getViewportSize()\n        ) {\n          align = \"end\";\n        } else {\n          return;\n        }\n      }\n\n      const document = getCurrentDocument(containerElement);\n      const window = getCurrentWindow(document);\n      const html = getDocumentElement(document);\n      const getScrollbarSize = () =>\n        store.$getViewportSize() -\n        (isHorizontal ? html.clientWidth : html.clientHeight);\n\n      scheduleScroll(() => {\n        return (\n          offset +\n          // Calculate target scroll position including container's offset from document\n          calcOffsetToViewport(\n            containerElement!,\n            document.body,\n            window,\n            isHorizontal,\n          ) +\n          // store._getStartSpacerSize() +\n          store.$getItemOffset(index) +\n          (align === \"end\"\n            ? store.$getItemSize(index) -\n              (store.$getViewportSize() - getScrollbarSize())\n            : align === \"center\"\n              ? (store.$getItemSize(index) -\n                  (store.$getViewportSize() - getScrollbarSize())) /\n                2\n              : 0)\n        );\n      }, smooth);\n    },\n  };\n};\n\n/**\n * @internal\n */\nexport interface GridScroller extends Scroller<HTMLElement> {\n  $scrollTo: (offsetX?: number, offsetY?: number) => void;\n  $scrollBy: (offsetX?: number, offsetY?: number) => void;\n  $scrollToIndex: (indexX?: number, indexY?: number) => void;\n}\n\n/**\n * @internal\n */\nexport const createGridScroller = (\n  rowStore: VirtualStore,\n  colStore: VirtualStore,\n): GridScroller => {\n  const rowScroller = createScroller(rowStore, false);\n  const colScroller = createScroller(colStore, true);\n  return {\n    $observe(container, viewport) {\n      rowScroller.$observe(container, viewport);\n      colScroller.$observe(container, viewport);\n    },\n    $dispose() {\n      rowScroller.$dispose();\n      colScroller.$dispose();\n    },\n    $isNegative: colScroller.$isNegative,\n    $scrollTo(row, col) {\n      if (row != null) {\n        rowScroller.$scrollTo(row);\n      }\n      if (col != null) {\n        colScroller.$scrollTo(col);\n      }\n    },\n    $scrollBy(row, col) {\n      if (row != null) {\n        rowScroller.$scrollBy(row);\n      }\n      if (col != null) {\n        colScroller.$scrollBy(col);\n      }\n    },\n    $scrollToIndex(row, col) {\n      if (row != null) {\n        rowScroller.$scrollToIndex(row);\n      }\n      if (col != null) {\n        colScroller.$scrollToIndex(col);\n      }\n    },\n    $fixScrollJump() {\n      rowScroller.$fixScrollJump();\n      colScroller.$fixScrollJump();\n    },\n  };\n};\n","import {\n  initCache,\n  getItemSize as _getItemSize,\n  getItemOffset as _getItemOffset,\n  UNCACHED,\n  setItemSize,\n  estimateDefaultItemSize,\n  updateCacheLength,\n  computeRange,\n  takeCacheSnapshot,\n  findIndex,\n} from \"./cache.js\";\nimport { isIOSWebKit } from \"./environment.js\";\nimport type {\n  CacheSnapshot,\n  InternalCacheSnapshot,\n  ItemResize,\n  ItemsRange,\n} from \"./types.js\";\nimport { abs, max, min, NULL } from \"./utils.js\";\n\nconst MAX_INT_32 = 0x7fffffff;\n\nconst SCROLL_IDLE = 0;\nconst SCROLL_DOWN = 1;\nconst SCROLL_UP = 2;\ntype ScrollDirection =\n  | typeof SCROLL_IDLE\n  | typeof SCROLL_DOWN\n  | typeof SCROLL_UP;\n\nconst SCROLL_BY_NATIVE = 0;\nconst SCROLL_BY_MANUAL_SCROLL = 1;\nconst SCROLL_BY_SHIFT = 2;\ntype ScrollMode =\n  | typeof SCROLL_BY_NATIVE\n  | typeof SCROLL_BY_MANUAL_SCROLL\n  | typeof SCROLL_BY_SHIFT;\n\n/** @internal */\nexport const ACTION_SCROLL = 1;\n/** @internal */\nexport const ACTION_SCROLL_END = 2;\n/** @internal */\nexport const ACTION_ITEM_RESIZE = 3;\n/** @internal */\nexport const ACTION_VIEWPORT_RESIZE = 4;\n/** @internal */\nexport const ACTION_ITEMS_LENGTH_CHANGE = 5;\n/** @internal */\nexport const ACTION_START_OFFSET_CHANGE = 6;\n/** @internal */\nexport const ACTION_MANUAL_SCROLL = 7;\n/** @internal */\nexport const ACTION_BEFORE_MANUAL_SMOOTH_SCROLL = 8;\n\ntype Actions =\n  | [type: typeof ACTION_SCROLL, offset: number]\n  | [type: typeof ACTION_SCROLL_END, dummy?: void]\n  | [type: typeof ACTION_ITEM_RESIZE, entries: ItemResize[]]\n  | [type: typeof ACTION_VIEWPORT_RESIZE, size: number]\n  | [\n      type: typeof ACTION_ITEMS_LENGTH_CHANGE,\n      arg: [length: number, isShift?: boolean | undefined],\n    ]\n  | [type: typeof ACTION_START_OFFSET_CHANGE, offset: number]\n  | [type: typeof ACTION_MANUAL_SCROLL, dummy?: void]\n  | [type: typeof ACTION_BEFORE_MANUAL_SMOOTH_SCROLL, offset: number];\n\n/** @internal */\nexport const UPDATE_VIRTUAL_STATE = 0b0001;\n/** @internal */\nexport const UPDATE_SIZE_EVENT = 0b0010;\n/** @internal */\nexport const UPDATE_SCROLL_EVENT = 0b0100;\n/** @internal */\nexport const UPDATE_SCROLL_END_EVENT = 0b1000;\n\n/**\n * @internal\n */\nexport const getScrollSize = (store: VirtualStore): number => {\n  return max(store.$getTotalSize(), store.$getViewportSize());\n};\n\ntype Subscriber = (sync?: boolean) => void;\n\n/** @internal */\nexport type StateVersion =\n  number & {} /* hack for typescript to pretend as not falsy */;\n\n/**\n * @internal\n */\nexport type VirtualStore = {\n  $dispose(): void;\n  $getStateVersion(): StateVersion;\n  $getCacheSnapshot(): CacheSnapshot;\n  $getRange(bufferSize?: number): ItemsRange;\n  $findItemIndex(offset: number): number;\n  $isUnmeasuredItem(index: number): boolean;\n  $getItemOffset(index: number, fromEnd?: boolean): number;\n  $getItemSize(index: number): number;\n  $getItemsLength(): number;\n  $getScrollOffset(): number;\n  $isScrolling(): boolean;\n  $getViewportSize(): number;\n  $getStartSpacerSize(): number;\n  $getTotalSize(): number;\n  _flushJump(): [number, boolean];\n  $subscribe(target: number, cb: Subscriber): () => void;\n  $update(...action: Actions): void;\n};\n\n/**\n * @internal\n */\nexport const createVirtualStore = (\n  elementsCount: number,\n  itemSize: number = 40,\n  ssrCount: number = 0,\n  cacheSnapshot?: CacheSnapshot | undefined,\n  shouldAutoEstimateItemSize: boolean = false,\n): VirtualStore => {\n  let isSSR = !!ssrCount;\n  let stateVersion: StateVersion = 1;\n  let viewportSize = 0;\n  let startSpacerSize = 0;\n  let scrollOffset = 0;\n  let jump = 0;\n  let pendingJump = 0;\n  let _flushedJump = 0;\n  let _scrollDirection: ScrollDirection = SCROLL_IDLE;\n  let _scrollMode: ScrollMode = SCROLL_BY_NATIVE;\n  let _frozenRange: ItemsRange | null = NULL;\n  let _prevRange: ItemsRange = [0, isSSR ? max(ssrCount - 1, 0) : -1];\n  let _totalMeasuredSize = 0;\n  let _isViewportMeasured = false;\n\n  const cache = initCache(\n    elementsCount,\n    cacheSnapshot\n      ? (cacheSnapshot as unknown as InternalCacheSnapshot)[1]\n      : itemSize,\n    cacheSnapshot && (cacheSnapshot as unknown as InternalCacheSnapshot)[0],\n  );\n  const subscribers = new Set<[number, Subscriber]>();\n  const getRelativeScrollOffset = () => scrollOffset - startSpacerSize;\n  const getVisibleOffset = () => getRelativeScrollOffset() + pendingJump + jump;\n  const getRange = (startOffset: number, endOffset: number) => {\n    return computeRange(cache, startOffset, endOffset, _prevRange[0]);\n  };\n  const getTotalSize = (): number => _getItemOffset(cache, cache._length);\n  const getItemOffset = (index: number, fromEnd?: boolean): number => {\n    const offset = _getItemOffset(cache, index) - pendingJump;\n    if (fromEnd) {\n      return getTotalSize() - offset - getItemSize(index);\n    }\n    return offset;\n  };\n  const getItemSize = (index: number): number => {\n    return _getItemSize(cache, index);\n  };\n  const isSizeEqual = (index: number, value: number = UNCACHED): boolean => {\n    return cache._sizes[index] === value;\n  };\n\n  const applyJump = (j: number) => {\n    if (j) {\n      if (\n        // In iOS WebKit browsers, updating scroll position will stop scrolling so it have to be deferred during scrolling.\n        (isIOSWebKit() && _scrollDirection !== SCROLL_IDLE) ||\n        // Before imperative smooth scrolling, we measure all items which may be visible during scrolling.\n        // However, especially in Firefox, there are rare cases where items resize while scrolling, which can stop smooth scrolling.\n        (_frozenRange && _scrollMode === SCROLL_BY_MANUAL_SCROLL)\n      ) {\n        pendingJump += j;\n      } else {\n        jump += j;\n      }\n    }\n  };\n\n  return {\n    $dispose: () => {\n      subscribers.clear();\n    },\n    $getStateVersion: () => stateVersion,\n    $getCacheSnapshot: () => {\n      return takeCacheSnapshot(cache) as unknown as CacheSnapshot;\n    },\n    $getRange: (bufferSize = 200) => {\n      if (!_isViewportMeasured || isSSR) {\n        // Return range for SSR, or return [0, -1] to render nothing, until the scroll offset and viewport size are determined.\n        // https://github.com/inokawa/virtua/issues/415\n        // https://github.com/inokawa/virtua/pull/818\n        return _prevRange;\n      }\n      let startIndex: number;\n      let endIndex: number;\n      if (_flushedJump) {\n        // Return previous range for consistent render until next scroll event comes in.\n        // And it must be clamped. https://github.com/inokawa/virtua/issues/597\n        [startIndex, endIndex] = _prevRange;\n      } else {\n        let startOffset = max(0, getVisibleOffset());\n        let endOffset = startOffset + viewportSize;\n\n        // For faster initial render pass, returns without buffer if measurement seems to be in progress.\n        if (!shouldAutoEstimateItemSize) {\n          bufferSize = max(0, bufferSize);\n\n          if (_scrollDirection !== SCROLL_DOWN) {\n            startOffset -= bufferSize;\n          }\n          if (_scrollDirection !== SCROLL_UP) {\n            endOffset += bufferSize;\n          }\n        }\n\n        [startIndex, endIndex] = _prevRange = getRange(\n          max(0, startOffset),\n          max(0, endOffset),\n        );\n        if (_frozenRange) {\n          startIndex = min(startIndex, _frozenRange[0]);\n          endIndex = max(endIndex, _frozenRange[1]);\n        }\n      }\n\n      return [max(startIndex, 0), min(endIndex, cache._length - 1)];\n    },\n    $findItemIndex: (offset) => findIndex(cache, offset - startSpacerSize),\n    $isUnmeasuredItem: isSizeEqual,\n    $getItemOffset: getItemOffset,\n    $getItemSize: getItemSize,\n    $getItemsLength: () => cache._length,\n    $getScrollOffset: () => scrollOffset,\n    $isScrolling: () => _scrollDirection !== SCROLL_IDLE,\n    $getViewportSize: () => viewportSize,\n    $getStartSpacerSize: () => startSpacerSize,\n    $getTotalSize: getTotalSize,\n    _flushJump: () => {\n      _flushedJump = jump;\n      jump = 0;\n      return [_flushedJump, _scrollMode === SCROLL_BY_SHIFT];\n    },\n    $subscribe: (target, cb) => {\n      const sub: [number, Subscriber] = [target, cb];\n      subscribers.add(sub);\n      return () => {\n        subscribers.delete(sub);\n      };\n    },\n    $update: (type, payload): void => {\n      let shouldFlushPendingJump: boolean | undefined;\n      let shouldSync: boolean | undefined;\n      let mutated = 0;\n\n      switch (type) {\n        case ACTION_SCROLL: {\n          if (payload === scrollOffset && _scrollMode === SCROLL_BY_NATIVE) {\n            // Ignore scroll events from different direction\n            break;\n          }\n\n          const flushedJump = _flushedJump;\n          _flushedJump = 0;\n\n          const delta = payload - scrollOffset;\n          const distance = abs(delta);\n\n          // Scroll event after jump compensation is not reliable because it may result in the opposite direction.\n          // The delta of artificial scroll may not be equal with the jump because it may be batched with other scrolls.\n          // And at least in latest Chrome/Firefox/Safari in 2023, setting value to scrollTop/scrollLeft can lose subpixel because its integer (sometimes float probably depending on dpr).\n          const isJustJumped = flushedJump && distance < abs(flushedJump) + 1;\n\n          // Scroll events are dispatched enough so it's ok to skip some of them.\n          if (\n            !isJustJumped &&\n            // Ignore until manual scrolling\n            _scrollMode === SCROLL_BY_NATIVE\n          ) {\n            _scrollDirection = delta < 0 ? SCROLL_UP : SCROLL_DOWN;\n          }\n\n          // TODO This will cause glitch in reverse infinite scrolling. Disable this until better solution is found.\n          // if (\n          //   pendingJump &&\n          //   ((_scrollDirection === SCROLL_UP &&\n          //     payload - max(pendingJump, 0) <= 0) ||\n          //     (_scrollDirection === SCROLL_DOWN &&\n          //       payload - min(pendingJump, 0) >= getScrollOffsetMax()))\n          // ) {\n          //   // Flush if almost reached to start or end\n          //   shouldFlushPendingJump = true;\n          // }\n\n          if (isSSR) {\n            isSSR = false;\n          }\n\n          scrollOffset = payload;\n          mutated = UPDATE_SCROLL_EVENT;\n\n          // Skip if offset is not changed\n          // Scroll offset may exceed min or max especially in Safari's elastic scrolling.\n          const relativeOffset = getRelativeScrollOffset();\n          if (\n            relativeOffset >= -viewportSize &&\n            relativeOffset <= getTotalSize()\n          ) {\n            mutated += UPDATE_VIRTUAL_STATE;\n\n            // Update synchronously if scrolled a lot\n            shouldSync = distance > viewportSize;\n          }\n          break;\n        }\n        case ACTION_SCROLL_END: {\n          mutated = UPDATE_SCROLL_END_EVENT;\n          if (_scrollDirection !== SCROLL_IDLE) {\n            shouldFlushPendingJump = true;\n            mutated += UPDATE_VIRTUAL_STATE;\n          }\n          _scrollDirection = SCROLL_IDLE;\n          _scrollMode = SCROLL_BY_NATIVE;\n          _frozenRange = NULL;\n          break;\n        }\n        case ACTION_ITEM_RESIZE: {\n          const updated = payload.filter(\n            ([index, size]) => !isSizeEqual(index, size),\n          );\n\n          // Skip if all items are cached and not updated\n          if (!updated.length) {\n            break;\n          }\n\n          // Calculate jump by resize to minimize junks in appearance\n          applyJump(\n            updated.reduce((acc, [index, size]) => {\n              let shouldKeep: boolean;\n              if (\n                // Keep distance from end during shifting\n                _scrollMode === SCROLL_BY_SHIFT\n              ) {\n                shouldKeep = true;\n              } else if (\n                _frozenRange &&\n                _scrollMode === SCROLL_BY_MANUAL_SCROLL\n              ) {\n                // https://github.com/inokawa/virtua/issues/380\n                // https://github.com/inokawa/virtua/issues/758\n                shouldKeep = index < _frozenRange[0];\n              } else {\n                // Otherwise we should maintain visible position\n                const start = getRelativeScrollOffset();\n                const itemOffset = getItemOffset(index);\n                const itemSize = getItemSize(index);\n                shouldKeep =\n                  _scrollDirection !== SCROLL_DOWN &&\n                  _scrollMode === SCROLL_BY_NATIVE\n                    ? // https://github.com/inokawa/virtua/issues/385\n                      // https://github.com/inokawa/virtua/discussions/865\n                      itemOffset + itemSize < start\n                    : // https://github.com/inokawa/virtua/pull/868\n                      itemOffset < start &&\n                      itemOffset + itemSize < start + viewportSize;\n              }\n\n              if (shouldKeep) {\n                acc += size - getItemSize(index);\n              }\n              return acc;\n            }, 0),\n          );\n\n          // Update item sizes\n          for (const [index, size] of updated) {\n            const prevSize = getItemSize(index);\n            const isInitialMeasurement = setItemSize(cache, index, size);\n\n            if (shouldAutoEstimateItemSize) {\n              _totalMeasuredSize += isInitialMeasurement\n                ? size\n                : size - prevSize;\n            }\n          }\n\n          // Estimate initial item size from measured sizes\n          if (\n            shouldAutoEstimateItemSize &&\n            viewportSize &&\n            // If the total size is lower than the viewport, the item may be a empty state\n            _totalMeasuredSize > viewportSize\n          ) {\n            applyJump(\n              estimateDefaultItemSize(\n                cache,\n                findIndex(cache, getVisibleOffset()),\n              ),\n            );\n            shouldAutoEstimateItemSize = false;\n          }\n\n          mutated = UPDATE_VIRTUAL_STATE + UPDATE_SIZE_EVENT;\n\n          // Synchronous update is necessary in current design to minimize visible glitch in concurrent rendering.\n          // However this seems to be the main cause of the errors from ResizeObserver.\n          // https://github.com/inokawa/virtua/issues/470\n          //\n          // And in React, synchronous update with flushSync after asynchronous update will overtake the asynchronous one.\n          // If items resize happens just after scroll, race condition can occur depending on implementation.\n          shouldSync = true;\n          break;\n        }\n        case ACTION_VIEWPORT_RESIZE: {\n          if (viewportSize !== payload) {\n            if (!viewportSize) {\n              _isViewportMeasured = shouldSync = true;\n            }\n            viewportSize = payload;\n            mutated = UPDATE_VIRTUAL_STATE + UPDATE_SIZE_EVENT;\n          }\n          break;\n        }\n        case ACTION_ITEMS_LENGTH_CHANGE: {\n          if (payload[1]) {\n            applyJump(updateCacheLength(cache, payload[0], true));\n            _scrollMode = SCROLL_BY_SHIFT;\n            mutated = UPDATE_VIRTUAL_STATE;\n          } else {\n            updateCacheLength(cache, payload[0]);\n            // https://github.com/inokawa/virtua/issues/552\n            // https://github.com/inokawa/virtua/issues/557\n            mutated = UPDATE_VIRTUAL_STATE;\n          }\n          break;\n        }\n        case ACTION_START_OFFSET_CHANGE: {\n          startSpacerSize = payload;\n          break;\n        }\n        case ACTION_MANUAL_SCROLL: {\n          _scrollMode = SCROLL_BY_MANUAL_SCROLL;\n          break;\n        }\n        case ACTION_BEFORE_MANUAL_SMOOTH_SCROLL: {\n          _frozenRange = getRange(payload, payload + viewportSize);\n          mutated = UPDATE_VIRTUAL_STATE;\n          break;\n        }\n      }\n\n      if (mutated) {\n        stateVersion = (stateVersion & MAX_INT_32) + 1;\n\n        if (shouldFlushPendingJump && pendingJump) {\n          jump += pendingJump;\n          pendingJump = 0;\n        }\n\n        subscribers.forEach(([target, cb]) => {\n          // Early return to skip React's computation\n          if (!(mutated & target)) {\n            return;\n          }\n          // https://github.com/facebook/react/issues/25191\n          // https://github.com/facebook/react/blob/a5fc797db14c6e05d4d5c4dbb22a0dd70d41f5d5/packages/react-reconciler/src/ReactFiberWorkLoop.js#L1443-L1447\n          cb(shouldSync);\n        });\n      }\n    },\n  };\n};\n","import { getCurrentDocument, getCurrentWindow } from \"./environment.js\";\nimport {\n  ACTION_ITEM_RESIZE,\n  ACTION_VIEWPORT_RESIZE,\n  type VirtualStore,\n} from \"./store.js\";\nimport { type ItemResize } from \"./types.js\";\nimport { max, microtask, NULL } from \"./utils.js\";\n\nconst createResizeObserver = (cb: ResizeObserverCallback) => {\n  let ro: ResizeObserver | undefined;\n\n  return {\n    _observe(e: HTMLElement) {\n      // Initialize ResizeObserver lazily for SSR\n      // https://www.w3.org/TR/resize-observer/#intro\n      (\n        ro ||\n        // https://bugs.chromium.org/p/chromium/issues/detail?id=1491739\n        (ro = new (getCurrentWindow(getCurrentDocument(e)).ResizeObserver)(cb))\n      ).observe(e);\n    },\n    _unobserve(e: HTMLElement) {\n      ro!.unobserve(e);\n    },\n    _dispose() {\n      ro && ro.disconnect();\n    },\n  };\n};\n\n/**\n * @internal\n */\nexport type ItemResizeObserver = (el: HTMLElement, i: number) => () => void;\n\ninterface ListResizer {\n  $observeRoot(viewportElement: HTMLElement): void;\n  $observeItem: ItemResizeObserver;\n  $dispose(): void;\n}\n\n/**\n * @internal\n */\nexport const createResizer = (\n  store: VirtualStore,\n  isHorizontal: boolean,\n): ListResizer => {\n  let viewportElement: HTMLElement | undefined;\n  const sizeKey = isHorizontal ? \"width\" : \"height\";\n  const mountedIndexes = new WeakMap<Element, number>();\n\n  const resizeObserver = createResizeObserver((entries) => {\n    const resizes: ItemResize[] = [];\n    for (const { target, contentRect } of entries) {\n      // Skip zero-sized rects that may be observed under `display: none` style\n      if (!(target as HTMLElement).offsetParent) continue;\n\n      if (target === viewportElement) {\n        store.$update(ACTION_VIEWPORT_RESIZE, contentRect[sizeKey]);\n      } else {\n        const index = mountedIndexes.get(target);\n        if (index != NULL) {\n          resizes.push([index, contentRect[sizeKey]]);\n        }\n      }\n    }\n\n    if (resizes.length) {\n      store.$update(ACTION_ITEM_RESIZE, resizes);\n    }\n  });\n\n  return {\n    $observeRoot(viewport: HTMLElement) {\n      resizeObserver._observe((viewportElement = viewport));\n    },\n    $observeItem: (el: HTMLElement, i: number) => {\n      mountedIndexes.set(el, i);\n      resizeObserver._observe(el);\n      return () => {\n        mountedIndexes.delete(el);\n        resizeObserver._unobserve(el);\n      };\n    },\n    $dispose: resizeObserver._dispose,\n  };\n};\n\ninterface WindowListResizer {\n  $observeRoot(container: HTMLElement): void;\n  $observeItem: ItemResizeObserver;\n  $dispose(): void;\n}\n\n/**\n * @internal\n */\nexport const createWindowResizer = (\n  store: VirtualStore,\n  isHorizontal: boolean,\n): WindowListResizer => {\n  const sizeKey = isHorizontal ? \"width\" : \"height\";\n  const windowSizeKey = isHorizontal ? \"innerWidth\" : \"innerHeight\";\n  const mountedIndexes = new WeakMap<Element, number>();\n\n  const resizeObserver = createResizeObserver((entries) => {\n    const resizes: ItemResize[] = [];\n    for (const { target, contentRect } of entries) {\n      // Skip zero-sized rects that may be observed under `display: none` style\n      if (!(target as HTMLElement).offsetParent) continue;\n\n      const index = mountedIndexes.get(target);\n      if (index != NULL) {\n        resizes.push([index, contentRect[sizeKey]]);\n      }\n    }\n\n    if (resizes.length) {\n      store.$update(ACTION_ITEM_RESIZE, resizes);\n    }\n  });\n\n  let cleanupOnWindowResize: (() => void) | undefined;\n\n  return {\n    $observeRoot(container) {\n      const window = getCurrentWindow(getCurrentDocument(container));\n      const onWindowResize = () => {\n        store.$update(ACTION_VIEWPORT_RESIZE, window[windowSizeKey]);\n      };\n      window.addEventListener(\"resize\", onWindowResize);\n\n      // https://github.com/inokawa/virtua/issues/792\n      microtask(onWindowResize);\n\n      cleanupOnWindowResize = () => {\n        window.removeEventListener(\"resize\", onWindowResize);\n      };\n    },\n    $observeItem: (el: HTMLElement, i: number) => {\n      mountedIndexes.set(el, i);\n      resizeObserver._observe(el);\n      return () => {\n        mountedIndexes.delete(el);\n        resizeObserver._unobserve(el);\n      };\n    },\n    $dispose() {\n      cleanupOnWindowResize && cleanupOnWindowResize();\n      resizeObserver._dispose();\n    },\n  };\n};\n\n/**\n * @internal\n */\nexport const createGridResizer = (\n  rowStore: VirtualStore,\n  colStore: VirtualStore,\n) => {\n  let viewportElement: HTMLElement | undefined;\n\n  const mountedIndexes = new WeakMap<\n    Element,\n    [rowIndex: number, colIndex: number]\n  >();\n\n  type CellSize = [height: number, width: number];\n  const maybeCachedRowIndexes = new Set<number>();\n  const maybeCachedColIndexes = new Set<number>();\n  const sizeCache = new Map<string, CellSize>();\n  const getKey = (rowIndex: number, colIndex: number): string =>\n    `${rowIndex}-${colIndex}`;\n\n  const resizeObserver = createResizeObserver((entries) => {\n    const resizedRows = new Set<number>();\n    const resizedCols = new Set<number>();\n    for (const {\n      target,\n      contentRect: { width, height },\n    } of entries) {\n      // Skip zero-sized rects that may be observed under `display: none` style\n      if (!(target as HTMLElement).offsetParent) continue;\n\n      if (target === viewportElement) {\n        rowStore.$update(ACTION_VIEWPORT_RESIZE, height);\n        colStore.$update(ACTION_VIEWPORT_RESIZE, width);\n      } else {\n        const cell = mountedIndexes.get(target);\n        if (cell) {\n          const [rowIndex, colIndex] = cell;\n          const key = getKey(rowIndex, colIndex);\n          const prevSize = sizeCache.get(key);\n          let rowResized: boolean | undefined;\n          let colResized: boolean | undefined;\n          if (!prevSize) {\n            rowResized = colResized = true;\n          } else {\n            if (prevSize[0] !== height) {\n              rowResized = true;\n            }\n            if (prevSize[1] !== width) {\n              colResized = true;\n            }\n          }\n          if (rowResized) {\n            resizedRows.add(rowIndex);\n          }\n          if (colResized) {\n            resizedCols.add(colIndex);\n          }\n          if (rowResized || colResized) {\n            sizeCache.set(key, [height, width]);\n          }\n        }\n      }\n    }\n\n    if (resizedRows.size) {\n      const heightResizes: ItemResize[] = [];\n      resizedRows.forEach((rowIndex) => {\n        let maxHeight = 0;\n        maybeCachedColIndexes.forEach((colIndex) => {\n          const size = sizeCache.get(getKey(rowIndex, colIndex));\n          if (size) {\n            maxHeight = max(maxHeight, size[0]);\n          }\n        });\n        if (maxHeight) {\n          heightResizes.push([rowIndex, maxHeight]);\n        }\n      });\n      rowStore.$update(ACTION_ITEM_RESIZE, heightResizes);\n    }\n    if (resizedCols.size) {\n      const widthResizes: ItemResize[] = [];\n      resizedCols.forEach((colIndex) => {\n        let maxWidth = 0;\n        maybeCachedRowIndexes.forEach((rowIndex) => {\n          const size = sizeCache.get(getKey(rowIndex, colIndex));\n          if (size) {\n            maxWidth = max(maxWidth, size[1]);\n          }\n        });\n        if (maxWidth) {\n          widthResizes.push([colIndex, maxWidth]);\n        }\n      });\n      colStore.$update(ACTION_ITEM_RESIZE, widthResizes);\n    }\n  });\n\n  return {\n    $observeRoot(viewport: HTMLElement) {\n      resizeObserver._observe((viewportElement = viewport));\n    },\n    $observeItem(el: HTMLElement, rowIndex: number, colIndex: number) {\n      mountedIndexes.set(el, [rowIndex, colIndex]);\n      maybeCachedRowIndexes.add(rowIndex);\n      maybeCachedColIndexes.add(colIndex);\n      resizeObserver._observe(el);\n      return () => {\n        mountedIndexes.delete(el);\n        resizeObserver._unobserve(el);\n      };\n    },\n    $resizeCols(cols: ItemResize[]) {\n      for (const [c] of cols) {\n        for (let r = 0; r < rowStore.$getItemsLength(); r++) {\n          sizeCache.delete(getKey(r, c));\n        }\n      }\n      colStore.$update(ACTION_ITEM_RESIZE, cols);\n    },\n    $resizeRows(rows: ItemResize[]) {\n      for (const [r] of rows) {\n        for (let c = 0; c < colStore.$getItemsLength(); c++) {\n          sizeCache.delete(getKey(r, c));\n        }\n      }\n      rowStore.$update(ACTION_ITEM_RESIZE, rows);\n    },\n    $dispose: resizeObserver._dispose,\n  };\n};\n\n/**\n * @internal\n */\nexport type GridResizer = ReturnType<typeof createGridResizer>;\n"],"names":["NULL","min","max","abs","floor","Math","clamp","value","minValue","maxValue","sort","arr","a","b","microtask","queueMicrotask","fn","Promise","resolve","then","createPromise","res","once","cache","undefined","fill","array","length","prepend","key","i","getItemSize","index","size","_sizes","_defaultItemSize","setItemSize","isInitialMeasurement","_computedOffsetIndex","getItemOffset","_length","_offsets","top","findIndex","offset","low","high","found","mid","updateCacheLength","isShift","diff","splice","reduce","acc","removed","isBrowser","window","getDocumentElement","doc","documentElement","getCurrentDocument","node","ownerDocument","getCurrentWindow","defaultView","isIOSWebKit","test","navigator","userAgent","platform","maxTouchPoints","isSmoothScrollSupported","document","style","timeout","setTimeout","normalizeScrollOffset","isNegative","createScrollObserver","store","viewport","isHorizontal","getScrollOffset","updateScrollOffset","getStartOffset","now","Date","lastScrollTime","wheeling","touching","justTouchEnded","stillMomentumScrolling","onScrollEnd","id","cancel","clearTimeout","debouncedFn","$update","_cancel","debounce","onScroll","onWheel","e","$isScrolling","ctrlKey","timeDelta","deltaX","deltaY","onTouchStart","onTouchEnd","addEventListener","passive","_dispose","removeEventListener","_fixScrollJump","jump","shift","_flushJump","$getViewportSize","$getTotalSize","createScrollScheduler","initialized","scroll","cancelScroll","async","getTargetOffset","smooth","waitForMeasurement","promise","$subscribe","done","end","$getRange","$isUnmeasuredItem","unsubscribe","createScroller","viewportElement","scrollObserver","scrollOffsetKey","overflowKey","scheduleScroll","scrollTo","behavior","$observe","_","getComputedStyle","direction","isMomentumScrolling","prev","$getScrollOffset","$dispose","$isNegative","$scrollTo","$scrollBy","$scrollToIndex","align","$getItemsLength","itemOffset","$getItemOffset","scrollOffset","$getItemSize","$getStartSpacerSize","$fixScrollJump","createResizeObserver","cb","ro","_observe","observe","_unobserve","unobserve","disconnect","rowStore","colStore","mountedIndexes","WeakMap","maybeCachedRowIndexes","Set","maybeCachedColIndexes","sizeCache","Map","getKey","rowIndex","colIndex","resizeObserver","entries","resizedRows","resizedCols","target","contentRect","width","height","offsetParent","cell","get","prevSize","rowResized","colResized","add","set","heightResizes","forEach","maxHeight","push","widthResizes","maxWidth","$observeRoot","$observeItem","el","delete","$resizeCols","cols","c","r","$resizeRows","rows","rowScroller","colScroller","container","row","col","sizeKey","resizes","elementsCount","itemSize","ssrCount","cacheSnapshot","shouldAutoEstimateItemSize","isSSR","stateVersion","viewportSize","startSpacerSize","pendingJump","_flushedJump","_scrollDirection","_scrollMode","_frozenRange","_prevRange","_totalMeasuredSize","_isViewportMeasured","sizes","slice","initCache","subscribers","getRelativeScrollOffset","getVisibleOffset","getRange","startOffset","endOffset","prevStartIndex","start","computeRange","getTotalSize","_getItemOffset","fromEnd","_getItemSize","isSizeEqual","UNCACHED","applyJump","j","clear","$getStateVersion","$getCacheSnapshot","takeCacheSnapshot","bufferSize","startIndex","endIndex","$findItemIndex","sub","type","payload","shouldFlushPendingJump","shouldSync","mutated","flushedJump","delta","distance","relativeOffset","updated","filter","shouldKeep","measuredCountBeforeStart","measuredSizes","s","sorted","len","median","prevDefaultItemSize","estimateDefaultItemSize","UPDATE_VIRTUAL_STATE","windowSizeKey","cleanupOnWindowResize","onWindowResize","containerElement","scrollToKey","calcOffsetToViewport","offsetKey","offsetSum","innerWidth","offsetWidth","parent","scrollBy","body","html","getScrollbarSize","clientWidth","clientHeight"],"mappings":"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"}