@tanstack/virtual-core 3.0.0-beta.43 → 3.0.0-beta.44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/lib/index.d.ts +4 -1
- package/build/lib/index.esm.js +48 -42
- package/build/lib/index.esm.js.map +1 -1
- package/build/lib/index.js +48 -42
- package/build/lib/index.js.map +1 -1
- package/build/lib/index.mjs +48 -42
- package/build/lib/index.mjs.map +1 -1
- package/build/umd/index.development.js +48 -42
- package/build/umd/index.development.js.map +1 -1
- package/build/umd/index.production.js +1 -1
- package/build/umd/index.production.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +52 -57
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.production.js","sources":["../../src/utils.ts","../../src/index.ts"],"sourcesContent":["export type NoInfer<A extends any> = [A][A extends any ? 0 : never]\n\nexport type PartialKeys<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>\n\nexport function memo<TDeps extends readonly any[], TResult>(\n getDeps: () => [...TDeps],\n fn: (...args: NoInfer<[...TDeps]>) => TResult,\n opts: {\n key: any\n debug?: () => any\n onChange?: (result: TResult) => void\n initialDeps?: TDeps\n },\n) {\n let deps = opts.initialDeps ?? []\n let result: TResult | undefined\n\n return (): TResult => {\n let depTime: number\n if (opts.key && opts.debug?.()) depTime = Date.now()\n\n const newDeps = getDeps()\n\n const depsChanged =\n newDeps.length !== deps.length ||\n newDeps.some((dep: any, index: number) => deps[index] !== dep)\n\n if (!depsChanged) {\n return result!\n }\n\n deps = newDeps\n\n let resultTime: number\n if (opts.key && opts.debug?.()) resultTime = Date.now()\n\n result = fn(...newDeps)\n\n if (opts.key && opts.debug?.()) {\n const depEndTime = Math.round((Date.now() - depTime!) * 100) / 100\n const resultEndTime = Math.round((Date.now() - resultTime!) * 100) / 100\n const resultFpsPercentage = resultEndTime / 16\n\n const pad = (str: number | string, num: number) => {\n str = String(str)\n while (str.length < num) {\n str = ' ' + str\n }\n return str\n }\n\n console.info(\n `%c⏱ ${pad(resultEndTime, 5)} /${pad(depEndTime, 5)} ms`,\n `\n font-size: .6rem;\n font-weight: bold;\n color: hsl(${Math.max(\n 0,\n Math.min(120 - 120 * resultFpsPercentage, 120),\n )}deg 100% 31%);`,\n opts?.key,\n )\n }\n\n opts?.onChange?.(result)\n\n return result!\n }\n}\n\nexport function notUndefined<T>(value: T | undefined, msg?: string): T {\n if (value === undefined) {\n throw new Error(`Unexpected undefined${msg ? `: ${msg}` : ''}`)\n } else {\n return value\n }\n}\n\nexport const approxEqual = (a: number, b: number) => Math.abs(a - b) < 1\n","import { approxEqual, memo, notUndefined } from './utils'\n\nexport * from './utils'\n\n//\n\ntype ScrollDirection = 'forward' | 'backward'\n\ntype ScrollAlignment = 'start' | 'center' | 'end' | 'auto'\n\ntype ScrollBehavior = 'auto' | 'smooth'\n\nexport interface ScrollToOptions {\n align?: ScrollAlignment\n behavior?: ScrollBehavior\n}\n\ntype ScrollToOffsetOptions = ScrollToOptions\n\ntype ScrollToIndexOptions = ScrollToOptions\n\nexport interface Range {\n startIndex: number\n endIndex: number\n overscan: number\n count: number\n}\n\ntype Key = number | string\n\nexport interface VirtualItem {\n key: Key\n index: number\n start: number\n end: number\n size: number\n}\n\ninterface Rect {\n width: number\n height: number\n}\n\n//\n\nexport const defaultKeyExtractor = (index: number) => index\n\nexport const defaultRangeExtractor = (range: Range) => {\n const start = Math.max(range.startIndex - range.overscan, 0)\n const end = Math.min(range.endIndex + range.overscan, range.count - 1)\n\n const arr = []\n\n for (let i = start; i <= end; i++) {\n arr.push(i)\n }\n\n return arr\n}\n\nconst memoRectCallback = (\n instance: Virtualizer<any, any>,\n cb: (rect: Rect) => void,\n) => {\n let prev: Rect = { height: -1, width: -1 }\n\n return (rect: Rect) => {\n if (\n instance.options.horizontal\n ? rect.width !== prev.width\n : rect.height !== prev.height\n ) {\n cb(rect)\n }\n\n prev = rect\n }\n}\n\nexport const observeElementRect = (\n instance: Virtualizer<any, any>,\n cb: (rect: Rect) => void,\n) => {\n const observer = new ResizeObserver((entries) => {\n const entry = entries[0]\n if (entry) {\n const { width, height } = entry.contentRect\n cb({\n width: Math.round(width),\n height: Math.round(height),\n })\n } else {\n cb({ width: 0, height: 0 })\n }\n })\n\n if (!instance.scrollElement) {\n return\n }\n\n cb(instance.scrollElement.getBoundingClientRect())\n\n observer.observe(instance.scrollElement)\n\n return () => {\n observer.unobserve(instance.scrollElement)\n }\n}\n\nexport const observeWindowRect = (\n instance: Virtualizer<any, any>,\n cb: (rect: Rect) => void,\n) => {\n const memoizedCallback = memoRectCallback(instance, cb)\n const onResize = () =>\n memoizedCallback({\n width: instance.scrollElement.innerWidth,\n height: instance.scrollElement.innerHeight,\n })\n\n if (!instance.scrollElement) {\n return\n }\n\n onResize()\n\n instance.scrollElement.addEventListener('resize', onResize, {\n capture: false,\n passive: true,\n })\n\n return () => {\n instance.scrollElement.removeEventListener('resize', onResize)\n }\n}\n\ntype ObserverMode = 'element' | 'window'\n\nconst scrollProps = {\n element: ['scrollLeft', 'scrollTop'],\n window: ['scrollX', 'scrollY'],\n} as const\n\nconst createOffsetObserver = (mode: ObserverMode) => {\n return (instance: Virtualizer<any, any>, cb: (offset: number) => void) => {\n if (!instance.scrollElement) {\n return\n }\n\n const propX = scrollProps[mode][0]\n const propY = scrollProps[mode][1]\n\n let prevX: number = instance.scrollElement[propX]\n let prevY: number = instance.scrollElement[propY]\n\n const scroll = () => {\n const offset =\n instance.scrollElement[instance.options.horizontal ? propX : propY]\n\n cb(offset)\n }\n\n scroll()\n\n const onScroll = (e: Event) => {\n const target = e.currentTarget as HTMLElement & Window\n const scrollX = target[propX]\n const scrollY = target[propY]\n\n if (instance.options.horizontal ? prevX - scrollX : prevY - scrollY) {\n scroll()\n }\n\n prevX = scrollX\n prevY = scrollY\n }\n\n instance.scrollElement.addEventListener('scroll', onScroll, {\n capture: false,\n passive: true,\n })\n\n return () => {\n instance.scrollElement.removeEventListener('scroll', onScroll)\n }\n }\n}\n\nexport const observeElementOffset = createOffsetObserver('element')\nexport const observeWindowOffset = createOffsetObserver('window')\n\nexport const measureElement = <TItemElement extends Element>(\n element: TItemElement,\n instance: Virtualizer<any, TItemElement>,\n) => {\n return Math.round(\n element.getBoundingClientRect()[\n instance.options.horizontal ? 'width' : 'height'\n ],\n )\n}\n\nexport const windowScroll = <T extends Window>(\n offset: number,\n {\n adjustments = 0,\n behavior,\n }: { adjustments?: number; behavior?: ScrollBehavior },\n instance: Virtualizer<T, any>,\n) => {\n const toOffset = offset + adjustments\n\n instance.scrollElement?.scrollTo?.({\n [instance.options.horizontal ? 'left' : 'top']: toOffset,\n behavior,\n })\n}\n\nexport const elementScroll = <T extends Element>(\n offset: number,\n {\n adjustments = 0,\n behavior,\n }: { adjustments?: number; behavior?: ScrollBehavior },\n instance: Virtualizer<T, any>,\n) => {\n const toOffset = offset + adjustments\n\n instance.scrollElement?.scrollTo?.({\n [instance.options.horizontal ? 'left' : 'top']: toOffset,\n behavior,\n })\n}\n\nexport interface VirtualizerOptions<\n TScrollElement extends Element | Window,\n TItemElement extends Element,\n> {\n // Required from the user\n count: number\n getScrollElement: () => TScrollElement | null\n estimateSize: (index: number) => number\n\n // Required from the framework adapter (but can be overridden)\n scrollToFn: (\n offset: number,\n options: { adjustments?: number; behavior?: ScrollBehavior },\n instance: Virtualizer<TScrollElement, TItemElement>,\n ) => void\n observeElementRect: (\n instance: Virtualizer<TScrollElement, TItemElement>,\n cb: (rect: Rect) => void,\n ) => void | (() => void)\n observeElementOffset: (\n instance: Virtualizer<TScrollElement, TItemElement>,\n cb: (offset: number) => void,\n ) => void | (() => void)\n\n // Optional\n debug?: any\n initialRect?: Rect\n onChange?: (instance: Virtualizer<TScrollElement, TItemElement>) => void\n measureElement?: (\n el: TItemElement,\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\n getItemKey?: (index: number) => Key\n rangeExtractor?: (range: Range) => number[]\n scrollMargin?: number\n scrollingDelay?: number\n indexAttribute?: string\n initialMeasurementsCache?: VirtualItem[]\n}\n\nexport class Virtualizer<\n TScrollElement extends Element | Window,\n TItemElement extends Element,\n> {\n private unsubs: (void | (() => void))[] = []\n options!: Required<VirtualizerOptions<TScrollElement, TItemElement>>\n scrollElement: TScrollElement | null = null\n isScrolling: boolean = false\n private isScrollingTimeoutId: ReturnType<typeof setTimeout> | null = null\n private scrollToIndexTimeoutId: ReturnType<typeof setTimeout> | null = null\n measurementsCache: VirtualItem[] = []\n private itemSizeCache: Record<Key, number> = {}\n private pendingMeasuredCacheIndexes: number[] = []\n private scrollRect: Rect\n scrollOffset: number\n scrollDirection: ScrollDirection | null = null\n private scrollAdjustments: number = 0\n private measureElementCache: Record<\n Key,\n TItemElement & { __virtualizerSkipFirstNotSync?: boolean }\n > = {}\n private getResizeObserver = (() => {\n let _ro: ResizeObserver | null = null\n\n return () => {\n if (_ro) {\n return _ro\n } else if (typeof ResizeObserver !== 'undefined') {\n return (_ro = new ResizeObserver((entries) => {\n entries.forEach((entry) => {\n this._measureElement(entry.target as TItemElement, false)\n })\n }))\n } else {\n return null\n }\n }\n })()\n range: { startIndex: number; endIndex: number } = {\n startIndex: 0,\n endIndex: 0,\n }\n\n constructor(opts: VirtualizerOptions<TScrollElement, TItemElement>) {\n this.setOptions(opts)\n this.scrollRect = this.options.initialRect\n this.scrollOffset = this.options.initialOffset\n this.measurementsCache = this.options.initialMeasurementsCache\n this.measurementsCache.forEach((item) => {\n this.itemSizeCache[item.key] = item.size\n })\n\n this.maybeNotify()\n }\n\n setOptions = (opts: VirtualizerOptions<TScrollElement, TItemElement>) => {\n Object.entries(opts).forEach(([key, value]) => {\n if (typeof value === 'undefined') delete (opts as any)[key]\n })\n\n this.options = {\n debug: false,\n initialOffset: 0,\n overscan: 1,\n paddingStart: 0,\n paddingEnd: 0,\n scrollPaddingStart: 0,\n scrollPaddingEnd: 0,\n horizontal: false,\n getItemKey: defaultKeyExtractor,\n rangeExtractor: defaultRangeExtractor,\n onChange: () => {},\n measureElement,\n initialRect: { width: 0, height: 0 },\n scrollMargin: 0,\n scrollingDelay: 150,\n indexAttribute: 'data-index',\n initialMeasurementsCache: [],\n ...opts,\n }\n }\n\n private notify = () => {\n this.options.onChange?.(this)\n }\n\n private cleanup = () => {\n this.unsubs.filter(Boolean).forEach((d) => d!())\n this.unsubs = []\n this.scrollElement = null\n }\n\n _didMount = () => {\n const ro = this.getResizeObserver()\n Object.values(this.measureElementCache).forEach((node) => ro?.observe(node))\n\n return () => {\n ro?.disconnect()\n\n this.cleanup()\n }\n }\n\n _willUpdate = () => {\n const scrollElement = this.options.getScrollElement()\n\n if (this.scrollElement !== scrollElement) {\n this.cleanup()\n\n this.scrollElement = scrollElement\n\n this._scrollToOffset(this.scrollOffset, {\n adjustments: undefined,\n behavior: undefined,\n })\n\n this.unsubs.push(\n this.options.observeElementRect(this, (rect) => {\n this.scrollRect = rect\n this.maybeNotify()\n }),\n )\n\n this.unsubs.push(\n this.options.observeElementOffset(this, (offset) => {\n this.scrollAdjustments = 0\n\n if (this.scrollOffset === offset) {\n return\n }\n\n if (this.isScrollingTimeoutId !== null) {\n clearTimeout(this.isScrollingTimeoutId)\n this.isScrollingTimeoutId = null\n }\n\n this.isScrolling = true\n this.scrollDirection =\n this.scrollOffset < offset ? 'forward' : 'backward'\n this.scrollOffset = offset\n\n this.maybeNotify()\n\n this.isScrollingTimeoutId = setTimeout(() => {\n this.isScrollingTimeoutId = null\n this.isScrolling = false\n this.scrollDirection = null\n\n this.maybeNotify()\n }, this.options.scrollingDelay)\n }),\n )\n }\n }\n\n private getSize = () => {\n return this.scrollRect[this.options.horizontal ? 'width' : 'height']\n }\n\n private getMeasurements = memo(\n () => [\n this.options.count,\n this.options.paddingStart,\n this.options.scrollMargin,\n this.options.getItemKey,\n this.itemSizeCache,\n ],\n (count, paddingStart, scrollMargin, getItemKey, itemSizeCache) => {\n const min =\n this.pendingMeasuredCacheIndexes.length > 0\n ? Math.min(...this.pendingMeasuredCacheIndexes)\n : 0\n this.pendingMeasuredCacheIndexes = []\n\n const measurements = this.measurementsCache.slice(0, min)\n\n for (let i = min; i < count; i++) {\n const key = getItemKey(i)\n const measuredSize = itemSizeCache[key]\n const start = measurements[i - 1]\n ? measurements[i - 1]!.end\n : paddingStart + scrollMargin\n const size =\n typeof measuredSize === 'number'\n ? measuredSize\n : this.options.estimateSize(i)\n const end = start + size\n measurements[i] = { index: i, start, size, end, key }\n }\n\n this.measurementsCache = measurements\n\n return measurements\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'getMeasurements',\n debug: () => this.options.debug,\n },\n )\n\n calculateRange = memo(\n () => [this.getMeasurements(), this.getSize(), this.scrollOffset],\n (measurements, outerSize, scrollOffset) => {\n return (this.range = calculateRange({\n measurements,\n outerSize,\n scrollOffset,\n }))\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'calculateRange',\n debug: () => this.options.debug,\n },\n )\n\n private maybeNotify = memo(\n () => [...Object.values(this.calculateRange()), this.isScrolling],\n () => {\n this.notify()\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'maybeNotify',\n debug: () => this.options.debug,\n initialDeps: [...Object.values(this.range), this.isScrolling],\n },\n )\n\n private getIndexes = memo(\n () => [\n this.options.rangeExtractor,\n this.calculateRange(),\n this.options.overscan,\n this.options.count,\n ],\n (rangeExtractor, range, overscan, count) => {\n return rangeExtractor({\n ...range,\n overscan,\n count,\n })\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'getIndexes',\n debug: () => this.options.debug,\n },\n )\n\n indexFromElement = (node: TItemElement) => {\n const attributeName = this.options.indexAttribute\n const indexStr = node.getAttribute(attributeName)\n\n if (!indexStr) {\n console.warn(\n `Missing attribute name '${attributeName}={index}' on measured element.`,\n )\n return -1\n }\n\n return parseInt(indexStr, 10)\n }\n\n private _measureElement = (node: TItemElement, sync: boolean) => {\n const index = this.indexFromElement(node)\n\n const item = this.measurementsCache[index]\n if (!item) {\n return\n }\n\n const prevNode = this.measureElementCache[item.key]\n\n const ro = this.getResizeObserver()\n\n if (!node.isConnected) {\n ro?.unobserve(node)\n if (node === prevNode) {\n delete this.measureElementCache[item.key]\n }\n return\n }\n\n if (prevNode !== node) {\n if (prevNode) {\n ro?.unobserve(prevNode)\n }\n ro?.observe(node)\n this.measureElementCache[item.key] = node\n } else {\n if (!sync && !prevNode.__virtualizerSkipFirstNotSync) {\n prevNode.__virtualizerSkipFirstNotSync = true\n return\n }\n }\n\n const measuredItemSize = this.options.measureElement(node, this)\n\n const itemSize = this.itemSizeCache[item.key] ?? item.size\n\n const delta = measuredItemSize - itemSize\n\n if (delta !== 0) {\n if (item.start < this.scrollOffset) {\n if (process.env.NODE_ENV !== 'production' && this.options.debug) {\n console.info('correction', delta)\n }\n\n this._scrollToOffset(this.scrollOffset, {\n adjustments: (this.scrollAdjustments += delta),\n behavior: undefined,\n })\n }\n\n this.pendingMeasuredCacheIndexes.push(index)\n this.itemSizeCache = {\n ...this.itemSizeCache,\n [item.key]: measuredItemSize,\n }\n this.notify()\n }\n }\n\n measureElement = (node: TItemElement | null) => {\n if (!node) {\n return\n }\n\n this._measureElement(node, true)\n }\n\n getVirtualItems = memo(\n () => [this.getIndexes(), this.getMeasurements()],\n (indexes, measurements) => {\n const virtualItems: VirtualItem[] = []\n\n for (let k = 0, len = indexes.length; k < len; k++) {\n const i = indexes[k]!\n const measurement = measurements[i]!\n\n virtualItems.push(measurement)\n }\n\n return virtualItems\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'getIndexes',\n debug: () => this.options.debug,\n },\n )\n\n getOffsetForAlignment = (toOffset: number, align: ScrollAlignment) => {\n const size = this.getSize()\n\n if (align === 'auto') {\n if (toOffset <= this.scrollOffset) {\n align = 'start'\n } else if (toOffset >= this.scrollOffset + size) {\n align = 'end'\n } else {\n align = 'start'\n }\n }\n\n if (align === 'start') {\n toOffset = toOffset\n } else if (align === 'end') {\n toOffset = toOffset - size\n } else if (align === 'center') {\n toOffset = toOffset - size / 2\n }\n\n const scrollSizeProp = this.options.horizontal\n ? 'scrollWidth'\n : 'scrollHeight'\n const scrollSize = this.scrollElement\n ? 'document' in this.scrollElement\n ? this.scrollElement.document.documentElement[scrollSizeProp]\n : this.scrollElement[scrollSizeProp]\n : 0\n\n const maxOffset = scrollSize - this.getSize()\n\n return Math.max(Math.min(maxOffset, toOffset), 0)\n }\n\n scrollToOffset = (\n toOffset: number,\n { align = 'start', behavior }: ScrollToOffsetOptions = {},\n ) => {\n const isDynamic = Object.keys(this.measureElementCache).length > 0\n\n if (isDynamic && behavior === 'smooth') {\n console.warn(\n 'The `smooth` scroll behavior is not supported with dynamic size.',\n )\n return\n }\n\n const options = {\n adjustments: undefined,\n behavior,\n sync: false,\n }\n this._scrollToOffset(this.getOffsetForAlignment(toOffset, align), options)\n }\n\n scrollToIndex = (\n index: number,\n { align = 'auto', behavior }: ScrollToIndexOptions = {},\n ) => {\n index = Math.max(0, Math.min(index, this.options.count - 1))\n\n if (this.scrollToIndexTimeoutId !== null) {\n clearTimeout(this.scrollToIndexTimeoutId)\n this.scrollToIndexTimeoutId = null\n }\n\n const isDynamic = Object.keys(this.measureElementCache).length > 0\n\n if (isDynamic && behavior === 'smooth') {\n console.warn(\n 'The `smooth` scroll behavior is not supported with dynamic size.',\n )\n return\n }\n\n const measurement = notUndefined(this.getMeasurements()[index])\n\n if (align === 'auto') {\n if (\n measurement.end >=\n this.scrollOffset + this.getSize() - this.options.scrollPaddingEnd\n ) {\n align = 'end'\n } else if (\n measurement.start <=\n this.scrollOffset + this.options.scrollPaddingStart\n ) {\n align = 'start'\n } else {\n return\n }\n }\n\n const getOffsetForIndexAndAlignment = (measurement: VirtualItem) => {\n const toOffset =\n align === 'end'\n ? measurement.end + this.options.scrollPaddingEnd\n : measurement.start - this.options.scrollPaddingStart\n\n return this.getOffsetForAlignment(toOffset, align)\n }\n\n const toOffset = getOffsetForIndexAndAlignment(measurement)\n\n const options = {\n adjustments: undefined,\n behavior,\n }\n this._scrollToOffset(toOffset, options)\n\n if (isDynamic) {\n this.scrollToIndexTimeoutId = setTimeout(() => {\n this.scrollToIndexTimeoutId = null\n\n const elementInDOM =\n !!this.measureElementCache[this.options.getItemKey(index)]\n\n if (elementInDOM) {\n const toOffset = getOffsetForIndexAndAlignment(\n notUndefined(this.getMeasurements()[index]),\n )\n\n if (!approxEqual(toOffset, this.scrollOffset)) {\n this.scrollToIndex(index, { align, behavior })\n }\n } else {\n this.scrollToIndex(index, { align, behavior })\n }\n })\n }\n }\n\n scrollBy = (delta: number, { behavior }: ScrollToOffsetOptions = {}) => {\n const isDynamic = Object.keys(this.measureElementCache).length > 0\n\n if (isDynamic && behavior === 'smooth') {\n console.warn(\n 'The `smooth` scroll behavior is not supported with dynamic size.',\n )\n return\n }\n\n this._scrollToOffset(this.scrollOffset + delta, {\n adjustments: undefined,\n behavior,\n })\n }\n\n getTotalSize = () =>\n (this.getMeasurements()[this.options.count - 1]?.end ||\n this.options.paddingStart) -\n this.options.scrollMargin +\n this.options.paddingEnd\n\n private _scrollToOffset = (\n offset: number,\n {\n adjustments,\n behavior,\n }: {\n adjustments: number | undefined\n behavior: ScrollBehavior | undefined\n },\n ) => {\n this.options.scrollToFn(offset, { behavior, adjustments }, this)\n }\n\n measure = () => {\n this.itemSizeCache = {}\n this.notify()\n }\n}\n\nconst findNearestBinarySearch = (\n low: number,\n high: number,\n getCurrentValue: (i: number) => number,\n value: number,\n) => {\n while (low <= high) {\n const middle = ((low + high) / 2) | 0\n const currentValue = getCurrentValue(middle)\n\n if (currentValue < value) {\n low = middle + 1\n } else if (currentValue > value) {\n high = middle - 1\n } else {\n return middle\n }\n }\n\n if (low > 0) {\n return low - 1\n } else {\n return 0\n }\n}\n\nfunction calculateRange({\n measurements,\n outerSize,\n scrollOffset,\n}: {\n measurements: VirtualItem[]\n outerSize: number\n scrollOffset: number\n}) {\n const count = measurements.length - 1\n const getOffset = (index: number) => measurements[index]!.start\n\n const startIndex = findNearestBinarySearch(0, count, getOffset, scrollOffset)\n let endIndex = startIndex\n\n while (\n endIndex < count &&\n measurements[endIndex]!.end < scrollOffset + outerSize\n ) {\n endIndex++\n }\n\n return { startIndex, endIndex }\n}\n"],"names":["memo","getDeps","fn","opts","_opts$initialDeps","result","deps","initialDeps","depTime","key","debug","Date","now","resultTime","newDeps","length","some","dep","index","depEndTime","Math","round","resultEndTime","resultFpsPercentage","pad","str","num","String","console","info","max","min","onChange","notUndefined","value","msg","undefined","Error","approxEqual","a","b","abs","defaultKeyExtractor","defaultRangeExtractor","range","start","startIndex","overscan","end","endIndex","count","arr","i","push","scrollProps","element","window","createOffsetObserver","mode","instance","cb","scrollElement","propX","propY","prevX","prevY","scroll","offset","options","horizontal","onScroll","e","target","currentTarget","scrollX","scrollY","addEventListener","capture","passive","removeEventListener","observeElementOffset","observeWindowOffset","measureElement","getBoundingClientRect","_ro","_this","this","unsubs","isScrolling","isScrollingTimeoutId","scrollToIndexTimeoutId","measurementsCache","itemSizeCache","pendingMeasuredCacheIndexes","scrollDirection","scrollAdjustments","measureElementCache","getResizeObserver","ResizeObserver","entries","forEach","entry","_measureElement","setOptions","Object","_ref3","_extends","initialOffset","paddingStart","paddingEnd","scrollPaddingStart","scrollPaddingEnd","getItemKey","rangeExtractor","initialRect","width","height","scrollMargin","scrollingDelay","indexAttribute","initialMeasurementsCache","notify","cleanup","filter","Boolean","d","_didMount","ro","values","node","observe","disconnect","_willUpdate","getScrollElement","_scrollToOffset","scrollOffset","adjustments","behavior","observeElementRect","rect","scrollRect","maybeNotify","clearTimeout","setTimeout","getSize","getMeasurements","measurements","slice","measuredSize","size","estimateSize","process","calculateRange","outerSize","_ref8","low","high","getCurrentValue","middle","currentValue","findNearestBinarySearch","concat","getIndexes","indexFromElement","attributeName","indexStr","getAttribute","parseInt","warn","sync","_this$itemSizeCache$i","item","prevNode","isConnected","unobserve","__virtualizerSkipFirstNotSync","_extends2","measuredItemSize","delta","getVirtualItems","indexes","virtualItems","k","len","measurement","getOffsetForAlignment","toOffset","align","scrollSizeProp","maxOffset","document","documentElement","scrollToOffset","_temp","_ref4","_ref4$align","keys","scrollToIndex","_temp2","_ref5","_ref5$align","isDynamic","getOffsetForIndexAndAlignment","scrollBy","_temp3","getTotalSize","_this$getMeasurements","_ref7","scrollToFn","measure","_instance$scrollEleme3","_instance$scrollEleme4","_ref2$adjustments","_ref2","scrollTo","observer","contentRect","memoizedCallback","prev","memoRectCallback","onResize","innerWidth","innerHeight","_instance$scrollEleme","_instance$scrollEleme2","_ref$adjustments","_ref"],"mappings":";;;;;;;;;;udAIO,SAASA,EACdC,EACAC,EACAC,GAMA,IAAAC,EAEIC,EADAC,SAAOH,EAAAA,EAAKI,eAAe,GAG/B,OAAO,WACL,IAAIC,EACAL,EAAKM,KAAON,MAAAA,EAAKO,OAALP,EAAKO,UAAWF,EAAUG,KAAKC,OAE/C,IAYIC,EAZEC,EAAUb,IAMhB,KAHEa,EAAQC,SAAWT,EAAKS,QACxBD,EAAQE,MAAK,SAACC,EAAUC,GAAa,OAAKZ,EAAKY,KAAWD,MAG1D,OAAOZ,EAUT,GAPAC,EAAOQ,EAGHX,EAAKM,KAAON,MAAAA,EAAKO,OAALP,EAAKO,UAAWG,EAAaF,KAAKC,OAElDP,EAASH,EAAMY,WAAAA,EAAAA,GAEXX,EAAKM,KAAiB,MAAVN,EAAKO,OAALP,EAAKO,QAAW,CAC9B,IAAMS,EAAaC,KAAKC,MAAgC,KAAzBV,KAAKC,MAAQJ,IAAmB,IACzDc,EAAgBF,KAAKC,MAAmC,KAA5BV,KAAKC,MAAQC,IAAsB,IAC/DU,EAAsBD,EAAgB,GAEtCE,EAAM,SAACC,EAAsBC,GAEjC,IADAD,EAAME,OAAOF,GACNA,EAAIV,OAASW,GAClBD,EAAM,IAAMA,EAEd,OAAOA,GAGTG,QAAQC,KAAI,OACHL,EAAIF,EAAe,QAAOE,EAAIL,EAAY,GAIhCC,MAAAA,2FAAAA,KAAKU,IAChB,EACAV,KAAKW,IAAI,IAAM,IAAMR,EAAqB,MAEhDpB,uBAAAA,SAAAA,EAAMM,IAEV,CAIA,OAFI,MAAJN,GAAc,MAAdA,EAAM6B,UAAN7B,EAAM6B,SAAW3B,GAEVA,EAEX,CAEO,SAAS4B,EAAgBC,EAAsBC,GACpD,QAAcC,IAAVF,EACF,MAAM,IAAIG,MAA6BF,wBAAAA,OAAWA,EAAQ,KAE1D,OAAOD,CAEX,CAEaI,IAAAA,EAAc,SAACC,EAAWC,GAAS,OAAKpB,KAAKqB,IAAIF,EAAIC,GAAK,CAAC,ECjC3DE,EAAsB,SAACxB,GAAa,OAAKA,CAAK,EAE9CyB,EAAwB,SAACC,GAMpC,IALA,IAAMC,EAAQzB,KAAKU,IAAIc,EAAME,WAAaF,EAAMG,SAAU,GACpDC,EAAM5B,KAAKW,IAAIa,EAAMK,SAAWL,EAAMG,SAAUH,EAAMM,MAAQ,GAE9DC,EAAM,GAEHC,EAAIP,EAAOO,GAAKJ,EAAKI,IAC5BD,EAAIE,KAAKD,GAGX,OAAOD,CACT,EAgFMG,EAAc,CAClBC,QAAS,CAAC,aAAc,aACxBC,OAAQ,CAAC,UAAW,YAGhBC,EAAuB,SAACC,GAC5B,OAAO,SAACC,EAAiCC,GACvC,GAAKD,EAASE,cAAd,CAIA,IAAMC,EAAQR,EAAYI,GAAM,GAC1BK,EAAQT,EAAYI,GAAM,GAE5BM,EAAgBL,EAASE,cAAcC,GACvCG,EAAgBN,EAASE,cAAcE,GAErCG,EAAS,WACb,IAAMC,EACJR,EAASE,cAAcF,EAASS,QAAQC,WAAaP,EAAQC,GAE/DH,EAAGO,IAGLD,IAEA,IAAMI,EAAW,SAACC,GAChB,IAAMC,EAASD,EAAEE,cACXC,EAAUF,EAAOV,GACjBa,EAAUH,EAAOT,IAEnBJ,EAASS,QAAQC,WAAaL,EAAQU,EAAUT,EAAQU,IAC1DT,IAGFF,EAAQU,EACRT,EAAQU,GAQV,OALAhB,EAASE,cAAce,iBAAiB,SAAUN,EAAU,CAC1DO,SAAS,EACTC,SAAS,IAGJ,WACLnB,EAASE,cAAckB,oBAAoB,SAAUT,GApCvD,EAuCJ,EAEaU,EAAuBvB,EAAqB,WAC5CwB,EAAsBxB,EAAqB,UAE3CyB,EAAiB,SAC5B3B,EACAI,GAEA,OAAOvC,KAAKC,MACVkC,EAAQ4B,wBACNxB,EAASS,QAAQC,WAAa,QAAU,UAG9C,gBA4HE,SAAYlE,GAAwD,IArB9DiF,EAqB8DC,EAAAC,KAAAA,KAvC5DC,OAAkC,GAAED,KAE5CzB,cAAuC,KAAIyB,KAC3CE,aAAuB,EAAKF,KACpBG,qBAA6D,KAAIH,KACjEI,uBAA+D,KAAIJ,KAC3EK,kBAAmC,GAAEL,KAC7BM,cAAqC,GAAEN,KACvCO,4BAAwC,GAAEP,KAGlDQ,gBAA0C,KAAIR,KACtCS,kBAA4B,EAACT,KAC7BU,oBAGJ,GAAEV,KACEW,mBACFb,EAA6B,KAE1B,WACL,OAAIA,IAEiC,oBAAnBc,eACRd,EAAM,IAAIc,gBAAe,SAACC,GAChCA,EAAQC,SAAQ,SAACC,GACfhB,EAAKiB,gBAAgBD,EAAM7B,QAAwB,EACrD,GACF,IAEO,QAGTc,KACJ1C,MAAkD,CAChDE,WAAY,EACZG,SAAU,GACXqC,KAcDiB,WAAa,SAACpG,GACZqG,OAAOL,QAAQhG,GAAMiG,SAAQ,SAAkBK,GAAA,IAAhBhG,EAAGgG,EAAA,QACX,IADkBA,EAAA,WACGtG,EAAaM,EACzD,IAEA4E,EAAKjB,QAAOsC,EAAA,CACVhG,OAAO,EACPiG,cAAe,EACf5D,SAAU,EACV6D,aAAc,EACdC,WAAY,EACZC,mBAAoB,EACpBC,iBAAkB,EAClB1C,YAAY,EACZ2C,WAAYtE,EACZuE,eAAgBtE,EAChBX,SAAU,WAAQ,EAClBkD,eAAAA,EACAgC,YAAa,CAAEC,MAAO,EAAGC,OAAQ,GACjCC,aAAc,EACdC,eAAgB,IAChBC,eAAgB,aAChBC,yBAA0B,IACvBrH,IAENmF,KAEOmC,OAAS,WACf,MAAApC,EAAKjB,QAAQpC,UAAbqD,EAAKjB,QAAQpC,SAAWqD,IACzBC,KAEOoC,QAAU,WAChBrC,EAAKE,OAAOoC,OAAOC,SAASxB,SAAQ,SAACyB,GAAC,OAAKA,OAC3CxC,EAAKE,OAAS,GACdF,EAAKxB,cAAgB,MACtByB,KAEDwC,UAAY,WACV,IAAMC,EAAK1C,EAAKY,oBAGhB,OAFAO,OAAOwB,OAAO3C,EAAKW,qBAAqBI,SAAQ,SAAC6B,GAAI,OAAKF,MAAAA,OAAAA,EAAAA,EAAIG,QAAQD,MAE/D,WACLF,MAAAA,GAAAA,EAAII,aAEJ9C,EAAKqC,YAERpC,KAED8C,YAAc,WACZ,IAAMvE,EAAgBwB,EAAKjB,QAAQiE,mBAE/BhD,EAAKxB,gBAAkBA,IACzBwB,EAAKqC,UAELrC,EAAKxB,cAAgBA,EAErBwB,EAAKiD,gBAAgBjD,EAAKkD,aAAc,CACtCC,iBAAapG,EACbqG,cAAUrG,IAGZiD,EAAKE,OAAOlC,KACVgC,EAAKjB,QAAQsE,mBAAmBrD,GAAM,SAACsD,GACrCtD,EAAKuD,WAAaD,EAClBtD,EAAKwD,aACN,KAGHxD,EAAKE,OAAOlC,KACVgC,EAAKjB,QAAQY,qBAAqBK,GAAM,SAAClB,GACvCkB,EAAKU,kBAAoB,EAErBV,EAAKkD,eAAiBpE,IAIQ,OAA9BkB,EAAKI,uBACPqD,aAAazD,EAAKI,sBAClBJ,EAAKI,qBAAuB,MAG9BJ,EAAKG,aAAc,EACnBH,EAAKS,gBACHT,EAAKkD,aAAepE,EAAS,UAAY,WAC3CkB,EAAKkD,aAAepE,EAEpBkB,EAAKwD,cAELxD,EAAKI,qBAAuBsD,YAAW,WACrC1D,EAAKI,qBAAuB,KAC5BJ,EAAKG,aAAc,EACnBH,EAAKS,gBAAkB,KAEvBT,EAAKwD,aACP,GAAGxD,EAAKjB,QAAQkD,gBACjB,OAGNhC,KAEO0D,QAAU,WAChB,OAAO3D,EAAKuD,WAAWvD,EAAKjB,QAAQC,WAAa,QAAU,WAC5DiB,KAEO2D,gBAAkBjJ,GACxB,WAAA,MAAM,CACJqF,EAAKjB,QAAQlB,MACbmC,EAAKjB,QAAQwC,aACbvB,EAAKjB,QAAQiD,aACbhC,EAAKjB,QAAQ4C,WACb3B,EAAKO,cAEP,IAAA,SAAC1C,EAAO0D,EAAcS,EAAcL,EAAYpB,GAC9C,IAAM7D,EACJsD,EAAKQ,4BAA4B9E,OAAS,EACtCK,KAAKW,UAALX,KAAYiE,EAAKQ,6BACjB,EACNR,EAAKQ,4BAA8B,GAInC,IAFA,IAAMqD,EAAe7D,EAAKM,kBAAkBwD,MAAM,EAAGpH,GAE5CqB,EAAIrB,EAAKqB,EAAIF,EAAOE,IAAK,CAChC,IAAM3C,EAAMuG,EAAW5D,GACjBgG,EAAexD,EAAcnF,GAC7BoC,EAAQqG,EAAa9F,EAAI,GAC3B8F,EAAa9F,EAAI,GAAIJ,IACrB4D,EAAeS,EACbgC,EACoB,iBAAjBD,EACHA,EACA/D,EAAKjB,QAAQkF,aAAalG,GAC1BJ,EAAMH,EAAQwG,EACpBH,EAAa9F,GAAK,CAAElC,MAAOkC,EAAGP,MAAAA,EAAOwG,KAAAA,EAAMrG,IAAAA,EAAKvC,IAAAA,EAClD,CAIA,OAFA4E,EAAKM,kBAAoBuD,EAElBA,CACT,GACA,CACEzI,KAAK8I,EACL7I,MAAO,WAAA,OAAM2E,EAAKjB,QAAQ1D,KAAK,IAElC4E,KAEDkE,eAAiBxJ,GACf,WAAA,MAAM,CAACqF,EAAK4D,kBAAmB5D,EAAK2D,UAAW3D,EAAKkD,aAAa,IACjE,SAACW,EAAcO,EAAWlB,GACxB,OAAQlD,EAAKzC,MA0VnB,SAQG8G,GAAA,IAPDR,IAAAA,aACAO,IAAAA,UACAlB,IAAAA,aAMMrF,EAAQgG,EAAanI,OAAS,EAG9B+B,EAtCwB,SAC9B6G,EACAC,EACAC,EACA3H,GAEA,KAAOyH,GAAOC,GAAM,CAClB,IAAME,GAAWH,EAAMC,GAAQ,EAAK,EAC9BG,EAAeF,EAAgBC,GAErC,GAAIC,EAAe7H,EACjByH,EAAMG,EAAS,MACV,MAAIC,EAAe7H,GAGxB,OAAO4H,EAFPF,EAAOE,EAAS,CAGlB,CACF,CAEA,OAAIH,EAAM,EACDA,EAAM,EAEN,CAEX,CAcqBK,CAAwB,EAAG9G,GAF5B,SAAChC,GAAa,OAAKgI,EAAahI,GAAQ2B,KAAK,GAEC0F,GAC5DtF,EAAWH,EAEf,KACEG,EAAWC,GACXgG,EAAajG,GAAWD,IAAMuF,EAAekB,GAE7CxG,IAGF,MAAO,CAAEH,WAAAA,EAAYG,SAAAA,EACvB,CAjX2BuG,CAAe,CAClCN,aAAAA,EACAO,UAAAA,EACAlB,aAAAA,GAEJ,GACA,CACE9H,KAAK8I,EACL7I,MAAO,WAAA,OAAM2E,EAAKjB,QAAQ1D,KAAK,IAElC4E,KAEOuD,YAAc7I,GACpB,WAAA,MAAA,GAAAiK,OAAUzD,OAAOwB,OAAO3C,EAAKmE,kBAAiB,CAAEnE,EAAKG,aAAW,IAChE,WACEH,EAAKoC,QACP,GACA,CACEhH,KAAK8I,EACL7I,MAAO,WAAA,OAAM2E,EAAKjB,QAAQ1D,KAAK,EAC/BH,YAAiBiG,GAAAA,OAAAA,OAAOwB,OAAO1C,KAAK1C,OAAM,CAAE0C,KAAKE,gBAEpDF,KAEO4E,WAAalK,GACnB,WAAA,MAAM,CACJqF,EAAKjB,QAAQ6C,eACb5B,EAAKmE,iBACLnE,EAAKjB,QAAQrB,SACbsC,EAAKjB,QAAQlB,MAEf,IAAA,SAAC+D,EAAgBrE,EAAOG,EAAUG,GAChC,OAAO+D,OACFrE,EAAK,CACRG,SAAAA,EACAG,MAAAA,IAEJ,GACA,CACEzC,KAAK8I,EACL7I,MAAO,WAAA,OAAM2E,EAAKjB,QAAQ1D,KAAK,IAElC4E,KAED6E,iBAAmB,SAAClC,GAClB,IAAMmC,EAAgB/E,EAAKjB,QAAQmD,eAC7B8C,EAAWpC,EAAKqC,aAAaF,GAEnC,OAAKC,EAOEE,SAASF,EAAU,KANxBzI,QAAQ4I,KACqBJ,2BAAAA,EAC5B,mCACO,IAIX9E,KAEOgB,gBAAkB,SAAC2B,EAAoBwC,GAAkB,IAAAC,EACzDxJ,EAAQmE,EAAK8E,iBAAiBlC,GAE9B0C,EAAOtF,EAAKM,kBAAkBzE,GACpC,GAAKyJ,EAAL,CAIA,IAAMC,EAAWvF,EAAKW,oBAAoB2E,EAAKlK,KAEzCsH,EAAK1C,EAAKY,oBAEhB,IAAKgC,EAAK4C,YAKR,aAJA9C,GAAAA,EAAI+C,UAAU7C,QACVA,IAAS2C,UACJvF,EAAKW,oBAAoB2E,EAAKlK,MAKzC,GAAImK,IAAa3C,EACX2C,UACF7C,GAAAA,EAAI+C,UAAUF,UAEhB7C,GAAAA,EAAIG,QAAQD,GACZ5C,EAAKW,oBAAoB2E,EAAKlK,KAAOwH,OAErC,IAAKwC,IAASG,EAASG,8BAErB,YADAH,EAASG,+BAAgC,GAK7C,IAMiBC,EANXC,EAAmB5F,EAAKjB,QAAQc,eAAe+C,EAAM5C,GAIrD6F,EAAQD,GAFmCN,OAAnCD,EAAGrF,EAAKO,cAAc+E,EAAKlK,MAAQkK,EAAAA,EAAKtB,MAItD,GAAc,IAAV6B,EACEP,EAAK9H,MAAQwC,EAAKkD,cAKpBlD,EAAKiD,gBAAgBjD,EAAKkD,aAAc,CACtCC,YAAcnD,EAAKU,mBAAqBmF,EACxCzC,cAAUrG,IAIdiD,EAAKQ,4BAA4BxC,KAAKnC,GACtCmE,EAAKO,cACAc,EAAA,CAAA,EAAArB,EAAKO,gBACP+E,EAAAA,CAAAA,GAAAA,EAAKlK,KAAMwK,EACbD,IACD3F,EAAKoC,QAlDP,GAoDDnC,KAEDJ,eAAiB,SAAC+C,GACXA,GAIL5C,EAAKiB,gBAAgB2B,GAAM,IAC5B3C,KAED6F,gBAAkBnL,GAChB,WAAA,MAAM,CAACqF,EAAK6E,aAAc7E,EAAK4D,kBAAkB,IACjD,SAACmC,EAASlC,GAGR,IAFA,IAAMmC,EAA8B,GAE3BC,EAAI,EAAGC,EAAMH,EAAQrK,OAAQuK,EAAIC,EAAKD,IAAK,CAClD,IACME,EAActC,EADVkC,EAAQE,IAGlBD,EAAahI,KAAKmI,EACpB,CAEA,OAAOH,CACT,GACA,CACE5K,KAAK8I,EACL7I,MAAO,WAAA,OAAM2E,EAAKjB,QAAQ1D,KAAK,IAElC4E,KAEDmG,sBAAwB,SAACC,EAAkBC,GACzC,IAAMtC,EAAOhE,EAAK2D,UAEJ,SAAV2C,IAEAA,EADED,GAAYrG,EAAKkD,aACX,QACCmD,GAAYrG,EAAKkD,aAAec,EACjC,MAEA,SAIE,UAAVsC,IAEiB,QAAVA,EACTD,GAAsBrC,EACH,WAAVsC,IACTD,GAAsBrC,EAAO,IAG/B,IAAMuC,EAAiBvG,EAAKjB,QAAQC,WAChC,cACA,eAOEwH,GANaxG,EAAKxB,cACpB,aAAcwB,EAAKxB,cACjBwB,EAAKxB,cAAciI,SAASC,gBAAgBH,GAC5CvG,EAAKxB,cAAc+H,GACrB,GAE2BvG,EAAK2D,UAEpC,OAAO5H,KAAKU,IAAIV,KAAKW,IAAI8J,EAAWH,GAAW,IAChDpG,KAED0G,eAAiB,SACfN,EAEGO,GAAA,IAAAC,OAAA,IAAAD,EADoD,CAAE,EAAAA,EAAAE,EAAAD,EAAvDP,MAAAA,aAAQ,QAAOQ,EAAE1D,IAAAA,SAInB,GAFkBjC,OAAO4F,KAAK/G,EAAKW,qBAAqBjF,OAAS,GAEnC,WAAb0H,EACf7G,QAAQ4I,KACN,wEAFJ,CAOA,IAAMpG,EAAU,CACdoE,iBAAapG,EACbqG,SAAAA,EACAgC,MAAM,GAERpF,EAAKiD,gBAAgBjD,EAAKoG,sBAAsBC,EAAUC,GAAQvH,EAPlE,GAQDkB,KAED+G,cAAgB,SACdnL,EAEGoL,GAAA,IAAAC,OAAA,IAAAD,EADkD,CAAE,EAAAA,EAAAE,EAAAD,EAArDZ,MAAAA,aAAQ,OAAMa,EAAE/D,IAAAA,SAElBvH,EAAQE,KAAKU,IAAI,EAAGV,KAAKW,IAAIb,EAAOmE,EAAKjB,QAAQlB,MAAQ,IAErB,OAAhCmC,EAAKK,yBACPoD,aAAazD,EAAKK,wBAClBL,EAAKK,uBAAyB,MAGhC,IAAM+G,EAAYjG,OAAO4F,KAAK/G,EAAKW,qBAAqBjF,OAAS,EAEjE,GAAI0L,GAA0B,WAAbhE,EACf7G,QAAQ4I,KACN,wEAFJ,CAOA,IAAMgB,EAAcvJ,EAAaoD,EAAK4D,kBAAkB/H,IAExD,GAAc,SAAVyK,EACF,GACEH,EAAYxI,KACZqC,EAAKkD,aAAelD,EAAK2D,UAAY3D,EAAKjB,QAAQ2C,iBAElD4E,EAAQ,UACH,MACLH,EAAY3I,OACZwC,EAAKkD,aAAelD,EAAKjB,QAAQ0C,oBAIjC,OAFA6E,EAAQ,OAGV,CAGF,IAAMe,EAAgC,SAAClB,GACrC,IAAME,EACM,QAAVC,EACIH,EAAYxI,IAAMqC,EAAKjB,QAAQ2C,iBAC/ByE,EAAY3I,MAAQwC,EAAKjB,QAAQ0C,mBAEvC,OAAOzB,EAAKoG,sBAAsBC,EAAUC,IAGxCD,EAAWgB,EAA8BlB,GAEzCpH,EAAU,CACdoE,iBAAapG,EACbqG,SAAAA,GAEFpD,EAAKiD,gBAAgBoD,EAAUtH,GAE3BqI,IACFpH,EAAKK,uBAAyBqD,YAAW,WAMvC,GALA1D,EAAKK,uBAAyB,OAG1BL,EAAKW,oBAAoBX,EAAKjB,QAAQ4C,WAAW9F,IAEnC,CAChB,IAAMwK,EAAWgB,EACfzK,EAAaoD,EAAK4D,kBAAkB/H,KAGjCoB,EAAYoJ,EAAUrG,EAAKkD,eAC9BlD,EAAKgH,cAAcnL,EAAO,CAAEyK,MAAAA,EAAOlD,SAAAA,GAEvC,MACEpD,EAAKgH,cAAcnL,EAAO,CAAEyK,MAAAA,EAAOlD,SAAAA,GAEvC,IAvDF,GAyDDnD,KAEDqH,SAAW,SAACzB,EAA4D0B,GAAA,IAA3CnE,QAA2C,IAAAmE,EAAP,CAAE,EAAAA,GAAtCnE,SACTjC,OAAO4F,KAAK/G,EAAKW,qBAAqBjF,OAAS,GAEnC,WAAb0H,EACf7G,QAAQ4I,KACN,oEAKJnF,EAAKiD,gBAAgBjD,EAAKkD,aAAe2C,EAAO,CAC9C1C,iBAAapG,EACbqG,SAAAA,KAEHnD,KAEDuH,aAAe,WAAA,IAAAC,EAAA,eACZA,EAAAzH,EAAK4D,kBAAkB5D,EAAKjB,QAAQlB,MAAQ,WAA5C4J,EAAgD9J,MAC/CqC,EAAKjB,QAAQwC,cACfvB,EAAKjB,QAAQiD,aACbhC,EAAKjB,QAAQyC,UAAU,EAAAvB,KAEjBgD,gBAAkB,SACxBnE,EAQG4I,GAAA,IANDvE,IAAAA,YACAC,IAAAA,SAMFpD,EAAKjB,QAAQ4I,WAAW7I,EAAQ,CAAEsE,SAAAA,EAAUD,YAAAA,GAAenD,IAC5DC,KAED2H,QAAU,WACR5H,EAAKO,cAAgB,GACrBP,EAAKoC,UA3dLnC,KAAKiB,WAAWpG,GAChBmF,KAAKsD,WAAatD,KAAKlB,QAAQ8C,YAC/B5B,KAAKiD,aAAejD,KAAKlB,QAAQuC,cACjCrB,KAAKK,kBAAoBL,KAAKlB,QAAQoD,yBACtClC,KAAKK,kBAAkBS,SAAQ,SAACuE,GAC9BtF,EAAKO,cAAc+E,EAAKlK,KAAOkK,EAAKtB,IACtC,IAEA/D,KAAKuD,aACP,oFApH2B,SAC3B1E,EAKAR,EAAAA,GACG,IAAAuJ,EAAAC,EAAAC,EAAAC,EAJD7E,YAAAA,aAAc,EAAC4E,EACf3E,IAAAA,SAIIiD,EAAWvH,EAASqE,EAE1B,OAAA7E,EAAAA,EAASE,gBAAT,MAAAqJ,EAAwBI,UAAxBJ,EAAwBI,WAAQH,EAAA,CAAA,GAC7BxJ,EAASS,QAAQC,WAAa,OAAS,OAAQqH,EAChDjD,EAAAA,SAAAA,EACA0E,GACJ,6FAzJkC,SAChCxJ,EACAC,GAEA,IAAM2J,EAAW,IAAIrH,gBAAe,SAACC,GACnC,IAAME,EAAQF,EAAQ,GACtB,GAAIE,EAAO,CACT,IAA0BA,EAAAA,EAAMmH,YAAxBrG,IAAAA,MAAOC,IAAAA,OACfxD,EAAG,CACDuD,MAAO/F,KAAKC,MAAM8F,GAClBC,OAAQhG,KAAKC,MAAM+F,IAEvB,MACExD,EAAG,CAAEuD,MAAO,EAAGC,OAAQ,GAE3B,IAEA,GAAKzD,EAASE,cAQd,OAJAD,EAAGD,EAASE,cAAcsB,yBAE1BoI,EAASrF,QAAQvE,EAASE,eAEnB,WACL0J,EAASzC,UAAUnH,EAASE,eAEhC,8CAEiC,SAC/BF,EACAC,GAEA,IAAM6J,EArDiB,SACvB9J,EACAC,GAEA,IAAI8J,EAAa,CAAEtG,QAAS,EAAGD,OAAQ,GAEvC,OAAO,SAACwB,IAEJhF,EAASS,QAAQC,WACbsE,EAAKxB,QAAUuG,EAAKvG,MACpBwB,EAAKvB,SAAWsG,EAAKtG,SAEzBxD,EAAG+E,GAGL+E,EAAO/E,EAEX,CAoC2BgF,CAAiBhK,EAAUC,GAC9CgK,EAAW,WAAH,OACZH,EAAiB,CACftG,MAAOxD,EAASE,cAAcgK,WAC9BzG,OAAQzD,EAASE,cAAciK,aAC/B,EAEJ,GAAKnK,EAASE,cAWd,OAPA+J,IAEAjK,EAASE,cAAce,iBAAiB,SAAUgJ,EAAU,CAC1D/I,SAAS,EACTC,SAAS,IAGJ,WACLnB,EAASE,cAAckB,oBAAoB,SAAU6I,GAEzD,iBAoE4B,SAC1BzJ,EAKAR,EAAAA,GACG,IAAAoK,EAAAC,EAAAC,EAAAC,EAJD1F,YAAAA,aAAc,EAACyF,EACfxF,IAAAA,SAIIiD,EAAWvH,EAASqE,EAE1B,OAAA7E,EAAAA,EAASE,gBAAT,MAAAkK,EAAwBT,UAAxBS,EAAwBT,WAAQU,EAAA,CAAA,GAC7BrK,EAASS,QAAQC,WAAa,OAAS,OAAQqH,EAChDjD,EAAAA,SAAAA,EACAuF,GACJ"}
|
|
1
|
+
{"version":3,"file":"index.production.js","sources":["../../src/utils.ts","../../src/index.ts"],"sourcesContent":["export type NoInfer<A extends any> = [A][A extends any ? 0 : never]\n\nexport type PartialKeys<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>\n\nexport function memo<TDeps extends readonly any[], TResult>(\n getDeps: () => [...TDeps],\n fn: (...args: NoInfer<[...TDeps]>) => TResult,\n opts: {\n key: any\n debug?: () => any\n onChange?: (result: TResult) => void\n initialDeps?: TDeps\n },\n) {\n let deps = opts.initialDeps ?? []\n let result: TResult | undefined\n\n return (): TResult => {\n let depTime: number\n if (opts.key && opts.debug?.()) depTime = Date.now()\n\n const newDeps = getDeps()\n\n const depsChanged =\n newDeps.length !== deps.length ||\n newDeps.some((dep: any, index: number) => deps[index] !== dep)\n\n if (!depsChanged) {\n return result!\n }\n\n deps = newDeps\n\n let resultTime: number\n if (opts.key && opts.debug?.()) resultTime = Date.now()\n\n result = fn(...newDeps)\n\n if (opts.key && opts.debug?.()) {\n const depEndTime = Math.round((Date.now() - depTime!) * 100) / 100\n const resultEndTime = Math.round((Date.now() - resultTime!) * 100) / 100\n const resultFpsPercentage = resultEndTime / 16\n\n const pad = (str: number | string, num: number) => {\n str = String(str)\n while (str.length < num) {\n str = ' ' + str\n }\n return str\n }\n\n console.info(\n `%c⏱ ${pad(resultEndTime, 5)} /${pad(depEndTime, 5)} ms`,\n `\n font-size: .6rem;\n font-weight: bold;\n color: hsl(${Math.max(\n 0,\n Math.min(120 - 120 * resultFpsPercentage, 120),\n )}deg 100% 31%);`,\n opts?.key,\n )\n }\n\n opts?.onChange?.(result)\n\n return result!\n }\n}\n\nexport function notUndefined<T>(value: T | undefined, msg?: string): T {\n if (value === undefined) {\n throw new Error(`Unexpected undefined${msg ? `: ${msg}` : ''}`)\n } else {\n return value\n }\n}\n\nexport const approxEqual = (a: number, b: number) => Math.abs(a - b) < 1\n","import { approxEqual, memo, notUndefined } from './utils'\n\nexport * from './utils'\n\n//\n\ntype ScrollDirection = 'forward' | 'backward'\n\ntype ScrollAlignment = 'start' | 'center' | 'end' | 'auto'\n\ntype ScrollBehavior = 'auto' | 'smooth'\n\nexport interface ScrollToOptions {\n align?: ScrollAlignment\n behavior?: ScrollBehavior\n}\n\ntype ScrollToOffsetOptions = ScrollToOptions\n\ntype ScrollToIndexOptions = ScrollToOptions\n\nexport interface Range {\n startIndex: number\n endIndex: number\n overscan: number\n count: number\n}\n\ntype Key = number | string\n\nexport interface VirtualItem {\n key: Key\n index: number\n start: number\n end: number\n size: number\n}\n\ninterface Rect {\n width: number\n height: number\n}\n\n//\n\nexport const defaultKeyExtractor = (index: number) => index\n\nexport const defaultRangeExtractor = (range: Range) => {\n const start = Math.max(range.startIndex - range.overscan, 0)\n const end = Math.min(range.endIndex + range.overscan, range.count - 1)\n\n const arr = []\n\n for (let i = start; i <= end; i++) {\n arr.push(i)\n }\n\n return arr\n}\n\nconst memoRectCallback = (\n instance: Virtualizer<any, any>,\n cb: (rect: Rect) => void,\n) => {\n let prev: Rect = { height: -1, width: -1 }\n\n return (rect: Rect) => {\n if (\n instance.options.horizontal\n ? rect.width !== prev.width\n : rect.height !== prev.height\n ) {\n cb(rect)\n }\n\n prev = rect\n }\n}\n\nexport const observeElementRect = (\n instance: Virtualizer<any, any>,\n cb: (rect: Rect) => void,\n) => {\n const observer = new ResizeObserver((entries) => {\n const entry = entries[0]\n if (entry) {\n const { width, height } = entry.contentRect\n cb({\n width: Math.round(width),\n height: Math.round(height),\n })\n } else {\n cb({ width: 0, height: 0 })\n }\n })\n\n if (!instance.scrollElement) {\n return\n }\n\n cb(instance.scrollElement.getBoundingClientRect())\n\n observer.observe(instance.scrollElement)\n\n return () => {\n observer.unobserve(instance.scrollElement)\n }\n}\n\nexport const observeWindowRect = (\n instance: Virtualizer<any, any>,\n cb: (rect: Rect) => void,\n) => {\n const memoizedCallback = memoRectCallback(instance, cb)\n const onResize = () =>\n memoizedCallback({\n width: instance.scrollElement.innerWidth,\n height: instance.scrollElement.innerHeight,\n })\n\n if (!instance.scrollElement) {\n return\n }\n\n onResize()\n\n instance.scrollElement.addEventListener('resize', onResize, {\n capture: false,\n passive: true,\n })\n\n return () => {\n instance.scrollElement.removeEventListener('resize', onResize)\n }\n}\n\ntype ObserverMode = 'element' | 'window'\n\nconst scrollProps = {\n element: ['scrollLeft', 'scrollTop'],\n window: ['scrollX', 'scrollY'],\n} as const\n\nconst createOffsetObserver = (mode: ObserverMode) => {\n return (instance: Virtualizer<any, any>, cb: (offset: number) => void) => {\n if (!instance.scrollElement) {\n return\n }\n\n const propX = scrollProps[mode][0]\n const propY = scrollProps[mode][1]\n\n let prevX: number = instance.scrollElement[propX]\n let prevY: number = instance.scrollElement[propY]\n\n const scroll = () => {\n const offset =\n instance.scrollElement[instance.options.horizontal ? propX : propY]\n\n cb(offset)\n }\n\n scroll()\n\n const onScroll = (e: Event) => {\n const target = e.currentTarget as HTMLElement & Window\n const scrollX = target[propX]\n const scrollY = target[propY]\n\n if (instance.options.horizontal ? prevX - scrollX : prevY - scrollY) {\n scroll()\n }\n\n prevX = scrollX\n prevY = scrollY\n }\n\n instance.scrollElement.addEventListener('scroll', onScroll, {\n capture: false,\n passive: true,\n })\n\n return () => {\n instance.scrollElement.removeEventListener('scroll', onScroll)\n }\n }\n}\n\nexport const observeElementOffset = createOffsetObserver('element')\nexport const observeWindowOffset = createOffsetObserver('window')\n\nexport const measureElement = <TItemElement extends Element>(\n element: TItemElement,\n instance: Virtualizer<any, TItemElement>,\n) => {\n return Math.round(\n element.getBoundingClientRect()[\n instance.options.horizontal ? 'width' : 'height'\n ],\n )\n}\n\nexport const windowScroll = <T extends Window>(\n offset: number,\n {\n adjustments = 0,\n behavior,\n }: { adjustments?: number; behavior?: ScrollBehavior },\n instance: Virtualizer<T, any>,\n) => {\n const toOffset = offset + adjustments\n\n instance.scrollElement?.scrollTo?.({\n [instance.options.horizontal ? 'left' : 'top']: toOffset,\n behavior,\n })\n}\n\nexport const elementScroll = <T extends Element>(\n offset: number,\n {\n adjustments = 0,\n behavior,\n }: { adjustments?: number; behavior?: ScrollBehavior },\n instance: Virtualizer<T, any>,\n) => {\n const toOffset = offset + adjustments\n\n instance.scrollElement?.scrollTo?.({\n [instance.options.horizontal ? 'left' : 'top']: toOffset,\n behavior,\n })\n}\n\nexport interface VirtualizerOptions<\n TScrollElement extends Element | Window,\n TItemElement extends Element,\n> {\n // Required from the user\n count: number\n getScrollElement: () => TScrollElement | null\n estimateSize: (index: number) => number\n\n // Required from the framework adapter (but can be overridden)\n scrollToFn: (\n offset: number,\n options: { adjustments?: number; behavior?: ScrollBehavior },\n instance: Virtualizer<TScrollElement, TItemElement>,\n ) => void\n observeElementRect: (\n instance: Virtualizer<TScrollElement, TItemElement>,\n cb: (rect: Rect) => void,\n ) => void | (() => void)\n observeElementOffset: (\n instance: Virtualizer<TScrollElement, TItemElement>,\n cb: (offset: number) => void,\n ) => void | (() => void)\n\n // Optional\n debug?: any\n initialRect?: Rect\n onChange?: (instance: Virtualizer<TScrollElement, TItemElement>) => void\n measureElement?: (\n el: TItemElement,\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\n getItemKey?: (index: number) => Key\n rangeExtractor?: (range: Range) => number[]\n scrollMargin?: number\n scrollingDelay?: number\n indexAttribute?: string\n initialMeasurementsCache?: VirtualItem[]\n}\n\nexport class Virtualizer<\n TScrollElement extends Element | Window,\n TItemElement extends Element,\n> {\n private unsubs: (void | (() => void))[] = []\n options!: Required<VirtualizerOptions<TScrollElement, TItemElement>>\n scrollElement: TScrollElement | null = null\n isScrolling: boolean = false\n private isScrollingTimeoutId: ReturnType<typeof setTimeout> | null = null\n private scrollToIndexTimeoutId: ReturnType<typeof setTimeout> | null = null\n measurementsCache: VirtualItem[] = []\n private itemSizeCache: Record<Key, number> = {}\n private pendingMeasuredCacheIndexes: number[] = []\n private scrollRect: Rect\n scrollOffset: number\n scrollDirection: ScrollDirection | null = null\n private scrollAdjustments: number = 0\n private measureElementCache: Record<\n Key,\n TItemElement & { __virtualizerSkipFirstNotSync?: boolean }\n > = {}\n private getResizeObserver = (() => {\n let _ro: ResizeObserver | null = null\n\n return () => {\n if (_ro) {\n return _ro\n } else if (typeof ResizeObserver !== 'undefined') {\n return (_ro = new ResizeObserver((entries) => {\n entries.forEach((entry) => {\n this._measureElement(entry.target as TItemElement, false)\n })\n }))\n } else {\n return null\n }\n }\n })()\n range: { startIndex: number; endIndex: number } = {\n startIndex: 0,\n endIndex: 0,\n }\n\n constructor(opts: VirtualizerOptions<TScrollElement, TItemElement>) {\n this.setOptions(opts)\n this.scrollRect = this.options.initialRect\n this.scrollOffset = this.options.initialOffset\n this.measurementsCache = this.options.initialMeasurementsCache\n this.measurementsCache.forEach((item) => {\n this.itemSizeCache[item.key] = item.size\n })\n\n this.maybeNotify()\n }\n\n setOptions = (opts: VirtualizerOptions<TScrollElement, TItemElement>) => {\n Object.entries(opts).forEach(([key, value]) => {\n if (typeof value === 'undefined') delete (opts as any)[key]\n })\n\n this.options = {\n debug: false,\n initialOffset: 0,\n overscan: 1,\n paddingStart: 0,\n paddingEnd: 0,\n scrollPaddingStart: 0,\n scrollPaddingEnd: 0,\n horizontal: false,\n getItemKey: defaultKeyExtractor,\n rangeExtractor: defaultRangeExtractor,\n onChange: () => {},\n measureElement,\n initialRect: { width: 0, height: 0 },\n scrollMargin: 0,\n scrollingDelay: 150,\n indexAttribute: 'data-index',\n initialMeasurementsCache: [],\n ...opts,\n }\n }\n\n private notify = () => {\n this.options.onChange?.(this)\n }\n\n private cleanup = () => {\n this.unsubs.filter(Boolean).forEach((d) => d!())\n this.unsubs = []\n this.scrollElement = null\n }\n\n _didMount = () => {\n const ro = this.getResizeObserver()\n Object.values(this.measureElementCache).forEach((node) => ro?.observe(node))\n\n return () => {\n ro?.disconnect()\n\n this.cleanup()\n }\n }\n\n _willUpdate = () => {\n const scrollElement = this.options.getScrollElement()\n\n if (this.scrollElement !== scrollElement) {\n this.cleanup()\n\n this.scrollElement = scrollElement\n\n this._scrollToOffset(this.scrollOffset, {\n adjustments: undefined,\n behavior: undefined,\n })\n\n this.unsubs.push(\n this.options.observeElementRect(this, (rect) => {\n this.scrollRect = rect\n this.maybeNotify()\n }),\n )\n\n this.unsubs.push(\n this.options.observeElementOffset(this, (offset) => {\n this.scrollAdjustments = 0\n\n if (this.scrollOffset === offset) {\n return\n }\n\n if (this.isScrollingTimeoutId !== null) {\n clearTimeout(this.isScrollingTimeoutId)\n this.isScrollingTimeoutId = null\n }\n\n this.isScrolling = true\n this.scrollDirection =\n this.scrollOffset < offset ? 'forward' : 'backward'\n this.scrollOffset = offset\n\n this.maybeNotify()\n\n this.isScrollingTimeoutId = setTimeout(() => {\n this.isScrollingTimeoutId = null\n this.isScrolling = false\n this.scrollDirection = null\n\n this.maybeNotify()\n }, this.options.scrollingDelay)\n }),\n )\n }\n }\n\n private getSize = () => {\n return this.scrollRect[this.options.horizontal ? 'width' : 'height']\n }\n\n private getMeasurements = memo(\n () => [\n this.options.count,\n this.options.paddingStart,\n this.options.scrollMargin,\n this.options.getItemKey,\n this.itemSizeCache,\n ],\n (count, paddingStart, scrollMargin, getItemKey, itemSizeCache) => {\n const min =\n this.pendingMeasuredCacheIndexes.length > 0\n ? Math.min(...this.pendingMeasuredCacheIndexes)\n : 0\n this.pendingMeasuredCacheIndexes = []\n\n const measurements = this.measurementsCache.slice(0, min)\n\n for (let i = min; i < count; i++) {\n const key = getItemKey(i)\n const measuredSize = itemSizeCache[key]\n const start = measurements[i - 1]\n ? measurements[i - 1]!.end\n : paddingStart + scrollMargin\n const size =\n typeof measuredSize === 'number'\n ? measuredSize\n : this.options.estimateSize(i)\n const end = start + size\n measurements[i] = { index: i, start, size, end, key }\n }\n\n this.measurementsCache = measurements\n\n return measurements\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'getMeasurements',\n debug: () => this.options.debug,\n },\n )\n\n calculateRange = memo(\n () => [this.getMeasurements(), this.getSize(), this.scrollOffset],\n (measurements, outerSize, scrollOffset) => {\n return (this.range = calculateRange({\n measurements,\n outerSize,\n scrollOffset,\n }))\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'calculateRange',\n debug: () => this.options.debug,\n },\n )\n\n private maybeNotify = memo(\n () => [...Object.values(this.calculateRange()), this.isScrolling],\n () => {\n this.notify()\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'maybeNotify',\n debug: () => this.options.debug,\n initialDeps: [...Object.values(this.range), this.isScrolling],\n },\n )\n\n private getIndexes = memo(\n () => [\n this.options.rangeExtractor,\n this.calculateRange(),\n this.options.overscan,\n this.options.count,\n ],\n (rangeExtractor, range, overscan, count) => {\n return rangeExtractor({\n ...range,\n overscan,\n count,\n })\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'getIndexes',\n debug: () => this.options.debug,\n },\n )\n\n indexFromElement = (node: TItemElement) => {\n const attributeName = this.options.indexAttribute\n const indexStr = node.getAttribute(attributeName)\n\n if (!indexStr) {\n console.warn(\n `Missing attribute name '${attributeName}={index}' on measured element.`,\n )\n return -1\n }\n\n return parseInt(indexStr, 10)\n }\n\n private _measureElement = (node: TItemElement, sync: boolean) => {\n const index = this.indexFromElement(node)\n\n const item = this.measurementsCache[index]\n if (!item) {\n return\n }\n\n const prevNode = this.measureElementCache[item.key]\n\n const ro = this.getResizeObserver()\n\n if (!node.isConnected) {\n ro?.unobserve(node)\n if (node === prevNode) {\n delete this.measureElementCache[item.key]\n }\n return\n }\n\n if (prevNode !== node) {\n if (prevNode) {\n ro?.unobserve(prevNode)\n }\n ro?.observe(node)\n this.measureElementCache[item.key] = node\n } else {\n if (!sync && !prevNode.__virtualizerSkipFirstNotSync) {\n prevNode.__virtualizerSkipFirstNotSync = true\n return\n }\n }\n\n const measuredItemSize = this.options.measureElement(node, this)\n\n const itemSize = this.itemSizeCache[item.key] ?? item.size\n\n const delta = measuredItemSize - itemSize\n\n if (delta !== 0) {\n if (item.start < this.scrollOffset) {\n if (process.env.NODE_ENV !== 'production' && this.options.debug) {\n console.info('correction', delta)\n }\n\n this._scrollToOffset(this.scrollOffset, {\n adjustments: (this.scrollAdjustments += delta),\n behavior: undefined,\n })\n }\n\n this.pendingMeasuredCacheIndexes.push(index)\n this.itemSizeCache = {\n ...this.itemSizeCache,\n [item.key]: measuredItemSize,\n }\n this.notify()\n }\n }\n\n measureElement = (node: TItemElement | null) => {\n if (!node) {\n return\n }\n\n this._measureElement(node, true)\n }\n\n getVirtualItems = memo(\n () => [this.getIndexes(), this.getMeasurements()],\n (indexes, measurements) => {\n const virtualItems: VirtualItem[] = []\n\n for (let k = 0, len = indexes.length; k < len; k++) {\n const i = indexes[k]!\n const measurement = measurements[i]!\n\n virtualItems.push(measurement)\n }\n\n return virtualItems\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'getIndexes',\n debug: () => this.options.debug,\n },\n )\n\n getOffsetForAlignment = (toOffset: number, align: ScrollAlignment) => {\n const size = this.getSize()\n\n if (align === 'auto') {\n if (toOffset <= this.scrollOffset) {\n align = 'start'\n } else if (toOffset >= this.scrollOffset + size) {\n align = 'end'\n } else {\n align = 'start'\n }\n }\n\n if (align === 'start') {\n toOffset = toOffset\n } else if (align === 'end') {\n toOffset = toOffset - size\n } else if (align === 'center') {\n toOffset = toOffset - size / 2\n }\n\n const scrollSizeProp = this.options.horizontal\n ? 'scrollWidth'\n : 'scrollHeight'\n const scrollSize = this.scrollElement\n ? 'document' in this.scrollElement\n ? this.scrollElement.document.documentElement[scrollSizeProp]\n : this.scrollElement[scrollSizeProp]\n : 0\n\n const maxOffset = scrollSize - this.getSize()\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 measurement = notUndefined(this.getMeasurements()[index])\n\n if (align === 'auto') {\n if (\n measurement.end >=\n this.scrollOffset + this.getSize() - this.options.scrollPaddingEnd\n ) {\n align = 'end'\n } else if (\n measurement.start <=\n this.scrollOffset + this.options.scrollPaddingStart\n ) {\n align = 'start'\n } else {\n return [this.scrollOffset, align] as const\n }\n }\n\n const toOffset =\n align === 'end'\n ? measurement.end + this.options.scrollPaddingEnd\n : measurement.start - this.options.scrollPaddingStart\n\n return [this.getOffsetForAlignment(toOffset, align), align] as const\n }\n\n private isDynamicMode = () => Object.keys(this.measureElementCache).length > 0\n\n private cancelScrollToIndex = () => {\n if (this.scrollToIndexTimeoutId !== null) {\n clearTimeout(this.scrollToIndexTimeoutId)\n this.scrollToIndexTimeoutId = null\n }\n }\n\n scrollToOffset = (\n toOffset: number,\n { align = 'start', behavior }: ScrollToOffsetOptions = {},\n ) => {\n this.cancelScrollToIndex()\n\n if (behavior === 'smooth' && this.isDynamicMode()) {\n console.warn(\n 'The `smooth` scroll behavior is not fully supported with dynamic size.',\n )\n }\n\n this._scrollToOffset(this.getOffsetForAlignment(toOffset, align), {\n adjustments: undefined,\n behavior,\n })\n }\n\n scrollToIndex = (\n index: number,\n { align: initialAlign = 'auto', behavior }: ScrollToIndexOptions = {},\n ) => {\n index = Math.max(0, Math.min(index, this.options.count - 1))\n\n this.cancelScrollToIndex()\n\n if (behavior === 'smooth' && this.isDynamicMode()) {\n console.warn(\n 'The `smooth` scroll behavior is not fully supported with dynamic size.',\n )\n }\n\n const [toOffset, align] = this.getOffsetForIndex(index, initialAlign)\n\n this._scrollToOffset(toOffset, { adjustments: undefined, behavior })\n\n if (behavior !== 'smooth' && this.isDynamicMode()) {\n this.scrollToIndexTimeoutId = setTimeout(() => {\n this.scrollToIndexTimeoutId = null\n\n const elementInDOM =\n !!this.measureElementCache[this.options.getItemKey(index)]\n\n if (elementInDOM) {\n const [toOffset] = this.getOffsetForIndex(index, align)\n\n if (!approxEqual(toOffset, this.scrollOffset)) {\n this.scrollToIndex(index, { align, behavior })\n }\n } else {\n this.scrollToIndex(index, { align, behavior })\n }\n })\n }\n }\n\n scrollBy = (delta: number, { behavior }: ScrollToOffsetOptions = {}) => {\n this.cancelScrollToIndex()\n\n if (behavior === 'smooth' && this.isDynamicMode()) {\n console.warn(\n 'The `smooth` scroll behavior is not fully supported with dynamic size.',\n )\n }\n\n this._scrollToOffset(this.scrollOffset + delta, {\n adjustments: undefined,\n behavior,\n })\n }\n\n getTotalSize = () =>\n (this.getMeasurements()[this.options.count - 1]?.end ||\n this.options.paddingStart) -\n this.options.scrollMargin +\n this.options.paddingEnd\n\n private _scrollToOffset = (\n offset: number,\n {\n adjustments,\n behavior,\n }: {\n adjustments: number | undefined\n behavior: ScrollBehavior | undefined\n },\n ) => {\n this.options.scrollToFn(offset, { behavior, adjustments }, this)\n }\n\n measure = () => {\n this.itemSizeCache = {}\n this.notify()\n }\n}\n\nconst findNearestBinarySearch = (\n low: number,\n high: number,\n getCurrentValue: (i: number) => number,\n value: number,\n) => {\n while (low <= high) {\n const middle = ((low + high) / 2) | 0\n const currentValue = getCurrentValue(middle)\n\n if (currentValue < value) {\n low = middle + 1\n } else if (currentValue > value) {\n high = middle - 1\n } else {\n return middle\n }\n }\n\n if (low > 0) {\n return low - 1\n } else {\n return 0\n }\n}\n\nfunction calculateRange({\n measurements,\n outerSize,\n scrollOffset,\n}: {\n measurements: VirtualItem[]\n outerSize: number\n scrollOffset: number\n}) {\n const count = measurements.length - 1\n const getOffset = (index: number) => measurements[index]!.start\n\n const startIndex = findNearestBinarySearch(0, count, getOffset, scrollOffset)\n let endIndex = startIndex\n\n while (\n endIndex < count &&\n measurements[endIndex]!.end < scrollOffset + outerSize\n ) {\n endIndex++\n }\n\n return { startIndex, endIndex }\n}\n"],"names":["memo","getDeps","fn","opts","_opts$initialDeps","result","deps","initialDeps","depTime","key","debug","Date","now","resultTime","newDeps","length","some","dep","index","depEndTime","Math","round","resultEndTime","resultFpsPercentage","pad","str","num","String","console","info","max","min","onChange","notUndefined","value","msg","undefined","Error","approxEqual","a","b","abs","defaultKeyExtractor","defaultRangeExtractor","range","start","startIndex","overscan","end","endIndex","count","arr","i","push","scrollProps","element","window","createOffsetObserver","mode","instance","cb","scrollElement","propX","propY","prevX","prevY","scroll","offset","options","horizontal","onScroll","e","target","currentTarget","scrollX","scrollY","addEventListener","capture","passive","removeEventListener","observeElementOffset","observeWindowOffset","measureElement","getBoundingClientRect","_ro","_this","this","unsubs","isScrolling","isScrollingTimeoutId","scrollToIndexTimeoutId","measurementsCache","itemSizeCache","pendingMeasuredCacheIndexes","scrollDirection","scrollAdjustments","measureElementCache","getResizeObserver","ResizeObserver","entries","forEach","entry","_measureElement","setOptions","Object","_ref3","_extends","initialOffset","paddingStart","paddingEnd","scrollPaddingStart","scrollPaddingEnd","getItemKey","rangeExtractor","initialRect","width","height","scrollMargin","scrollingDelay","indexAttribute","initialMeasurementsCache","notify","cleanup","filter","Boolean","d","_didMount","ro","values","node","observe","disconnect","_willUpdate","getScrollElement","_scrollToOffset","scrollOffset","adjustments","behavior","observeElementRect","rect","scrollRect","maybeNotify","clearTimeout","setTimeout","getSize","getMeasurements","measurements","slice","measuredSize","size","estimateSize","process","calculateRange","outerSize","_ref8","low","high","getCurrentValue","middle","currentValue","findNearestBinarySearch","concat","getIndexes","indexFromElement","attributeName","indexStr","getAttribute","parseInt","warn","sync","_this$itemSizeCache$i","item","prevNode","isConnected","unobserve","__virtualizerSkipFirstNotSync","_extends2","measuredItemSize","delta","getVirtualItems","indexes","virtualItems","k","len","measurement","getOffsetForAlignment","toOffset","align","scrollSizeProp","maxOffset","document","documentElement","getOffsetForIndex","isDynamicMode","keys","cancelScrollToIndex","scrollToOffset","_temp","_ref4","_ref4$align","scrollToIndex","_temp2","_ref5","_ref5$align","initialAlign","_this$getOffsetForInd","scrollBy","_temp3","getTotalSize","_this$getMeasurements","_ref7","scrollToFn","measure","_instance$scrollEleme3","_instance$scrollEleme4","_ref2$adjustments","_ref2","scrollTo","observer","contentRect","memoizedCallback","prev","memoRectCallback","onResize","innerWidth","innerHeight","_instance$scrollEleme","_instance$scrollEleme2","_ref$adjustments","_ref"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/virtual-core",
|
|
3
3
|
"author": "Tanner Linsley",
|
|
4
|
-
"version": "3.0.0-beta.
|
|
4
|
+
"version": "3.0.0-beta.44",
|
|
5
5
|
"description": "Headless UI for virtualizing scrollable elements in TS/JS + Frameworks",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"homepage": "https://github.com/tanstack/virtual#readme",
|
package/src/index.ts
CHANGED
|
@@ -663,47 +663,9 @@ export class Virtualizer<
|
|
|
663
663
|
return Math.max(Math.min(maxOffset, toOffset), 0)
|
|
664
664
|
}
|
|
665
665
|
|
|
666
|
-
|
|
667
|
-
toOffset: number,
|
|
668
|
-
{ align = 'start', behavior }: ScrollToOffsetOptions = {},
|
|
669
|
-
) => {
|
|
670
|
-
const isDynamic = Object.keys(this.measureElementCache).length > 0
|
|
671
|
-
|
|
672
|
-
if (isDynamic && behavior === 'smooth') {
|
|
673
|
-
console.warn(
|
|
674
|
-
'The `smooth` scroll behavior is not supported with dynamic size.',
|
|
675
|
-
)
|
|
676
|
-
return
|
|
677
|
-
}
|
|
678
|
-
|
|
679
|
-
const options = {
|
|
680
|
-
adjustments: undefined,
|
|
681
|
-
behavior,
|
|
682
|
-
sync: false,
|
|
683
|
-
}
|
|
684
|
-
this._scrollToOffset(this.getOffsetForAlignment(toOffset, align), options)
|
|
685
|
-
}
|
|
686
|
-
|
|
687
|
-
scrollToIndex = (
|
|
688
|
-
index: number,
|
|
689
|
-
{ align = 'auto', behavior }: ScrollToIndexOptions = {},
|
|
690
|
-
) => {
|
|
666
|
+
getOffsetForIndex = (index: number, align: ScrollAlignment = 'auto') => {
|
|
691
667
|
index = Math.max(0, Math.min(index, this.options.count - 1))
|
|
692
668
|
|
|
693
|
-
if (this.scrollToIndexTimeoutId !== null) {
|
|
694
|
-
clearTimeout(this.scrollToIndexTimeoutId)
|
|
695
|
-
this.scrollToIndexTimeoutId = null
|
|
696
|
-
}
|
|
697
|
-
|
|
698
|
-
const isDynamic = Object.keys(this.measureElementCache).length > 0
|
|
699
|
-
|
|
700
|
-
if (isDynamic && behavior === 'smooth') {
|
|
701
|
-
console.warn(
|
|
702
|
-
'The `smooth` scroll behavior is not supported with dynamic size.',
|
|
703
|
-
)
|
|
704
|
-
return
|
|
705
|
-
}
|
|
706
|
-
|
|
707
669
|
const measurement = notUndefined(this.getMeasurements()[index])
|
|
708
670
|
|
|
709
671
|
if (align === 'auto') {
|
|
@@ -718,28 +680,64 @@ export class Virtualizer<
|
|
|
718
680
|
) {
|
|
719
681
|
align = 'start'
|
|
720
682
|
} else {
|
|
721
|
-
return
|
|
683
|
+
return [this.scrollOffset, align] as const
|
|
722
684
|
}
|
|
723
685
|
}
|
|
724
686
|
|
|
725
|
-
const
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
: measurement.start - this.options.scrollPaddingStart
|
|
687
|
+
const toOffset =
|
|
688
|
+
align === 'end'
|
|
689
|
+
? measurement.end + this.options.scrollPaddingEnd
|
|
690
|
+
: measurement.start - this.options.scrollPaddingStart
|
|
730
691
|
|
|
731
|
-
|
|
692
|
+
return [this.getOffsetForAlignment(toOffset, align), align] as const
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
private isDynamicMode = () => Object.keys(this.measureElementCache).length > 0
|
|
696
|
+
|
|
697
|
+
private cancelScrollToIndex = () => {
|
|
698
|
+
if (this.scrollToIndexTimeoutId !== null) {
|
|
699
|
+
clearTimeout(this.scrollToIndexTimeoutId)
|
|
700
|
+
this.scrollToIndexTimeoutId = null
|
|
732
701
|
}
|
|
702
|
+
}
|
|
733
703
|
|
|
734
|
-
|
|
704
|
+
scrollToOffset = (
|
|
705
|
+
toOffset: number,
|
|
706
|
+
{ align = 'start', behavior }: ScrollToOffsetOptions = {},
|
|
707
|
+
) => {
|
|
708
|
+
this.cancelScrollToIndex()
|
|
709
|
+
|
|
710
|
+
if (behavior === 'smooth' && this.isDynamicMode()) {
|
|
711
|
+
console.warn(
|
|
712
|
+
'The `smooth` scroll behavior is not fully supported with dynamic size.',
|
|
713
|
+
)
|
|
714
|
+
}
|
|
735
715
|
|
|
736
|
-
|
|
716
|
+
this._scrollToOffset(this.getOffsetForAlignment(toOffset, align), {
|
|
737
717
|
adjustments: undefined,
|
|
738
718
|
behavior,
|
|
719
|
+
})
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
scrollToIndex = (
|
|
723
|
+
index: number,
|
|
724
|
+
{ align: initialAlign = 'auto', behavior }: ScrollToIndexOptions = {},
|
|
725
|
+
) => {
|
|
726
|
+
index = Math.max(0, Math.min(index, this.options.count - 1))
|
|
727
|
+
|
|
728
|
+
this.cancelScrollToIndex()
|
|
729
|
+
|
|
730
|
+
if (behavior === 'smooth' && this.isDynamicMode()) {
|
|
731
|
+
console.warn(
|
|
732
|
+
'The `smooth` scroll behavior is not fully supported with dynamic size.',
|
|
733
|
+
)
|
|
739
734
|
}
|
|
740
|
-
this._scrollToOffset(toOffset, options)
|
|
741
735
|
|
|
742
|
-
|
|
736
|
+
const [toOffset, align] = this.getOffsetForIndex(index, initialAlign)
|
|
737
|
+
|
|
738
|
+
this._scrollToOffset(toOffset, { adjustments: undefined, behavior })
|
|
739
|
+
|
|
740
|
+
if (behavior !== 'smooth' && this.isDynamicMode()) {
|
|
743
741
|
this.scrollToIndexTimeoutId = setTimeout(() => {
|
|
744
742
|
this.scrollToIndexTimeoutId = null
|
|
745
743
|
|
|
@@ -747,9 +745,7 @@ export class Virtualizer<
|
|
|
747
745
|
!!this.measureElementCache[this.options.getItemKey(index)]
|
|
748
746
|
|
|
749
747
|
if (elementInDOM) {
|
|
750
|
-
const toOffset =
|
|
751
|
-
notUndefined(this.getMeasurements()[index]),
|
|
752
|
-
)
|
|
748
|
+
const [toOffset] = this.getOffsetForIndex(index, align)
|
|
753
749
|
|
|
754
750
|
if (!approxEqual(toOffset, this.scrollOffset)) {
|
|
755
751
|
this.scrollToIndex(index, { align, behavior })
|
|
@@ -762,13 +758,12 @@ export class Virtualizer<
|
|
|
762
758
|
}
|
|
763
759
|
|
|
764
760
|
scrollBy = (delta: number, { behavior }: ScrollToOffsetOptions = {}) => {
|
|
765
|
-
|
|
761
|
+
this.cancelScrollToIndex()
|
|
766
762
|
|
|
767
|
-
if (
|
|
763
|
+
if (behavior === 'smooth' && this.isDynamicMode()) {
|
|
768
764
|
console.warn(
|
|
769
|
-
'The `smooth` scroll behavior is not supported with dynamic size.',
|
|
765
|
+
'The `smooth` scroll behavior is not fully supported with dynamic size.',
|
|
770
766
|
)
|
|
771
|
-
return
|
|
772
767
|
}
|
|
773
768
|
|
|
774
769
|
this._scrollToOffset(this.scrollOffset + delta, {
|