@tanstack/virtual-core 3.0.0-beta.26 → 3.0.0-beta.28
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 +1 -0
- package/build/lib/index.esm.js +19 -0
- package/build/lib/index.esm.js.map +1 -1
- package/build/lib/index.js +19 -0
- package/build/lib/index.js.map +1 -1
- package/build/lib/index.mjs +19 -0
- package/build/lib/index.mjs.map +1 -1
- package/build/umd/index.development.js +19 -0
- 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 +22 -0
|
@@ -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 },\n): () => TResult {\n let deps: any[] = []\n let result: TResult | undefined\n\n return () => {\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 opts?.onChange?.(result)\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 return result!\n }\n}\n","import { memo } from './utils'\n\nexport * from './utils'\n\n//\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 cb({\n width: entries[0]?.contentRect.width as number,\n height: entries[0]?.contentRect.height as number,\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(Math.max(0, offset - instance.options.scrollMargin))\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,\n behavior,\n sync,\n }: { adjustments?: number; behavior?: ScrollBehavior; sync: boolean },\n instance: Virtualizer<T, any>,\n) => {\n const toOffset =\n (sync ? offset : offset + instance.options.scrollMargin) +\n (adjustments ?? 0)\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,\n behavior,\n sync,\n }: { adjustments?: number; behavior?: ScrollBehavior; sync: boolean },\n instance: Virtualizer<T, any>,\n) => {\n const toOffset =\n (sync ? offset : offset + instance.options.scrollMargin) +\n (adjustments ?? 0)\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; sync: boolean },\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}\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 measurementsCache: VirtualItem[] = []\n private itemMeasurementsCache: Record<Key, number> = {}\n private pendingMeasuredCacheIndexes: number[] = []\n private scrollRect: Rect\n private scrollOffset: number\n private scrollAdjustments: number = 0\n private measureElementCache: Record<Key, TItemElement> = {}\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\n this.calculateRange()\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 ...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 return () => {\n this.getResizeObserver()?.disconnect()\n this.measureElementCache = {}\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 sync: true,\n })\n\n this.unsubs.push(\n this.options.observeElementRect(this, (rect) => {\n this.scrollRect = rect\n this.calculateRange()\n }),\n )\n\n this.unsubs.push(\n this.options.observeElementOffset(this, (offset) => {\n if (this.isScrollingTimeoutId !== null) {\n clearTimeout(this.isScrollingTimeoutId)\n this.isScrollingTimeoutId = null\n }\n\n if (this.scrollOffset !== offset) {\n this.scrollOffset = offset\n this.isScrolling = true\n this.scrollAdjustments = 0\n\n this.isScrollingTimeoutId = setTimeout(() => {\n this.isScrollingTimeoutId = null\n this.isScrolling = false\n\n this.notify()\n }, this.options.scrollingDelay)\n } else {\n this.isScrolling = false\n this.scrollAdjustments = 0\n }\n\n this.calculateRange()\n }),\n )\n } else if (!this.isScrolling) {\n this.calculateRange()\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.getItemKey,\n this.itemMeasurementsCache,\n ],\n (count, paddingStart, getItemKey, measurementsCache) => {\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 = measurementsCache[key]\n const start = measurements[i - 1]\n ? measurements[i - 1]!.end\n : paddingStart\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 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 const range = calculateRange({\n measurements,\n outerSize,\n scrollOffset,\n })\n if (\n range.startIndex !== this.range.startIndex ||\n range.endIndex !== this.range.endIndex\n ) {\n this.range = range\n this.notify()\n }\n return this.range\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'calculateRange',\n debug: () => this.options.debug,\n },\n )\n\n private getIndexes = memo(\n () => [\n this.options.rangeExtractor,\n this.range,\n this.options.overscan,\n this.options.count,\n ],\n (rangeExtractor, range, overscan, count) => {\n return rangeExtractor({\n ...range,\n overscan,\n count: 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 if (prevNode) {\n ro?.unobserve(prevNode)\n delete this.measureElementCache[item.key]\n }\n return\n }\n\n if (!prevNode || prevNode !== node) {\n if (prevNode) {\n ro?.unobserve(prevNode)\n }\n this.measureElementCache[item.key] = node\n ro?.observe(node)\n }\n\n const measuredItemSize = this.options.measureElement(node, this)\n\n const itemSize = this.itemMeasurementsCache[item.key] ?? item.size\n\n const delta = measuredItemSize - itemSize\n\n if (delta !== 0) {\n if (item.start < this.scrollOffset && this.isScrolling) {\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 sync: false,\n })\n }\n\n this.pendingMeasuredCacheIndexes.push(index)\n this.itemMeasurementsCache = {\n ...this.itemMeasurementsCache,\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 scrollToOffset = (\n toOffset: number,\n { align = 'start', behavior }: ScrollToOffsetOptions = {},\n ) => {\n const offset = this.scrollOffset\n const size = this.getSize()\n\n if (align === 'auto') {\n if (toOffset <= offset) {\n align = 'start'\n } else if (toOffset >= offset + size) {\n align = 'end'\n } else {\n align = 'start'\n }\n }\n\n const options = {\n adjustments: undefined,\n behavior,\n sync: false,\n }\n if (align === 'start') {\n this._scrollToOffset(toOffset, options)\n } else if (align === 'end') {\n this._scrollToOffset(toOffset - size, options)\n } else if (align === 'center') {\n this._scrollToOffset(toOffset - size / 2, options)\n }\n }\n\n scrollToIndex = (\n index: number,\n { align = 'auto', ...rest }: ScrollToIndexOptions = {},\n ) => {\n const measurements = this.getMeasurements()\n const offset = this.scrollOffset\n const size = this.getSize()\n const { count } = this.options\n\n const measurement = measurements[Math.max(0, Math.min(index, count - 1))]\n\n if (!measurement) {\n return\n }\n\n if (align === 'auto') {\n if (measurement.end >= offset + size - this.options.scrollPaddingEnd) {\n align = 'end'\n } else if (\n measurement.start <=\n offset + this.options.scrollPaddingStart\n ) {\n align = 'start'\n } else {\n return\n }\n }\n\n const toOffset =\n align === 'end'\n ? measurement.end + this.options.scrollPaddingEnd\n : measurement.start - this.options.scrollPaddingStart\n\n this.scrollToOffset(toOffset, { align, ...rest })\n }\n\n getTotalSize = () =>\n (this.getMeasurements()[this.options.count - 1]?.end ||\n this.options.paddingStart) + this.options.paddingEnd\n\n private _scrollToOffset = (\n offset: number,\n {\n adjustments,\n behavior,\n sync,\n }: {\n adjustments: number | undefined\n behavior: ScrollBehavior | undefined\n sync: boolean\n },\n ) => {\n this.options.scrollToFn(offset, { behavior, sync, adjustments }, this)\n }\n\n measure = () => {\n this.itemMeasurementsCache = {}\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","result","deps","depTime","key","debug","Date","now","newDeps","length","some","dep","index","resultTime","onChange","depEndTime","Math","round","resultEndTime","resultFpsPercentage","pad","str","num","String","console","info","max","min","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","scrollMargin","onScroll","e","target","currentTarget","scrollX","scrollY","addEventListener","capture","passive","removeEventListener","observeElementOffset","observeWindowOffset","measureElement","getBoundingClientRect","constructor","_this","this","unsubs","isScrolling","isScrollingTimeoutId","measurementsCache","itemMeasurementsCache","pendingMeasuredCacheIndexes","scrollAdjustments","measureElementCache","getResizeObserver","_ro","ResizeObserver","entries","forEach","entry","_measureElement","setOptions","Object","_ref3","value","initialOffset","paddingStart","paddingEnd","scrollPaddingStart","scrollPaddingEnd","getItemKey","rangeExtractor","initialRect","width","height","scrollingDelay","indexAttribute","notify","_this$options$onChang","_this$options","call","cleanup","filter","Boolean","d","_didMount","_this$getResizeObserv","disconnect","_willUpdate","getScrollElement","_scrollToOffset","scrollOffset","adjustments","undefined","behavior","sync","observeElementRect","rect","scrollRect","calculateRange","clearTimeout","setTimeout","getSize","getMeasurements","measurements","slice","measuredSize","size","estimateSize","process","outerSize","_ref5","low","high","getCurrentValue","middle","currentValue","findNearestBinarySearch","getIndexes","indexFromElement","node","attributeName","indexStr","getAttribute","parseInt","warn","_sync","item","prevNode","ro","isConnected","unobserve","observe","measuredItemSize","delta","getVirtualItems","indexes","virtualItems","k","len","measurement","scrollToOffset","toOffset","_temp","align","scrollToIndex","_temp2","rest","getTotalSize","_this$getMeasurements","_ref4","scrollToFn","measure","_ref2","_instance$scrollEleme2","scrollTo","observer","_entries$","_entries$2","contentRect","memoizedCallback","prev","memoRectCallback","onResize","innerWidth","innerHeight","_ref","_instance$scrollEleme"],"mappings":"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"}
|
|
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 },\n): () => TResult {\n let deps: any[] = []\n let result: TResult | undefined\n\n return () => {\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 opts?.onChange?.(result)\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 return result!\n }\n}\n","import { memo } from './utils'\n\nexport * from './utils'\n\n//\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 cb({\n width: entries[0]?.contentRect.width as number,\n height: entries[0]?.contentRect.height as number,\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(Math.max(0, offset - instance.options.scrollMargin))\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,\n behavior,\n sync,\n }: { adjustments?: number; behavior?: ScrollBehavior; sync: boolean },\n instance: Virtualizer<T, any>,\n) => {\n const toOffset =\n (sync ? offset : offset + instance.options.scrollMargin) +\n (adjustments ?? 0)\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,\n behavior,\n sync,\n }: { adjustments?: number; behavior?: ScrollBehavior; sync: boolean },\n instance: Virtualizer<T, any>,\n) => {\n const toOffset =\n (sync ? offset : offset + instance.options.scrollMargin) +\n (adjustments ?? 0)\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; sync: boolean },\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}\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 measurementsCache: VirtualItem[] = []\n private itemMeasurementsCache: Record<Key, number> = {}\n private pendingMeasuredCacheIndexes: number[] = []\n private scrollRect: Rect\n private scrollOffset: number\n private scrollAdjustments: number = 0\n private measureElementCache: Record<Key, TItemElement> = {}\n private pendingScrollToIndexCallback: (() => void) | null = null\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\n this.calculateRange()\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 ...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 return () => {\n this.getResizeObserver()?.disconnect()\n this.measureElementCache = {}\n\n this.cleanup()\n }\n }\n\n _willUpdate = () => {\n this.pendingScrollToIndexCallback?.()\n\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 sync: true,\n })\n\n this.unsubs.push(\n this.options.observeElementRect(this, (rect) => {\n this.scrollRect = rect\n this.calculateRange()\n }),\n )\n\n this.unsubs.push(\n this.options.observeElementOffset(this, (offset) => {\n if (this.isScrollingTimeoutId !== null) {\n clearTimeout(this.isScrollingTimeoutId)\n this.isScrollingTimeoutId = null\n }\n\n if (this.scrollOffset !== offset) {\n this.scrollOffset = offset\n this.isScrolling = true\n this.scrollAdjustments = 0\n\n this.isScrollingTimeoutId = setTimeout(() => {\n this.isScrollingTimeoutId = null\n this.isScrolling = false\n\n this.notify()\n }, this.options.scrollingDelay)\n } else {\n this.isScrolling = false\n this.scrollAdjustments = 0\n }\n\n this.calculateRange()\n }),\n )\n } else if (!this.isScrolling) {\n this.calculateRange()\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.getItemKey,\n this.itemMeasurementsCache,\n ],\n (count, paddingStart, getItemKey, measurementsCache) => {\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 = measurementsCache[key]\n const start = measurements[i - 1]\n ? measurements[i - 1]!.end\n : paddingStart\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 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 const range = calculateRange({\n measurements,\n outerSize,\n scrollOffset,\n })\n if (\n range.startIndex !== this.range.startIndex ||\n range.endIndex !== this.range.endIndex\n ) {\n this.range = range\n this.notify()\n }\n return this.range\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'calculateRange',\n debug: () => this.options.debug,\n },\n )\n\n private getIndexes = memo(\n () => [\n this.options.rangeExtractor,\n this.range,\n this.options.overscan,\n this.options.count,\n ],\n (rangeExtractor, range, overscan, count) => {\n return rangeExtractor({\n ...range,\n overscan,\n count: 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 if (prevNode) {\n ro?.unobserve(prevNode)\n delete this.measureElementCache[item.key]\n }\n return\n }\n\n if (!prevNode || prevNode !== node) {\n if (prevNode) {\n ro?.unobserve(prevNode)\n }\n this.measureElementCache[item.key] = node\n ro?.observe(node)\n }\n\n const measuredItemSize = this.options.measureElement(node, this)\n\n const itemSize = this.itemMeasurementsCache[item.key] ?? item.size\n\n const delta = measuredItemSize - itemSize\n\n if (delta !== 0) {\n if (item.start < this.scrollOffset && this.isScrolling) {\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 sync: false,\n })\n }\n\n this.pendingMeasuredCacheIndexes.push(index)\n this.itemMeasurementsCache = {\n ...this.itemMeasurementsCache,\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 scrollToOffset = (\n toOffset: number,\n { align = 'start', behavior }: ScrollToOffsetOptions = {},\n ) => {\n const offset = this.scrollOffset\n const size = this.getSize()\n\n if (align === 'auto') {\n if (toOffset <= offset) {\n align = 'start'\n } else if (toOffset >= offset + size) {\n align = 'end'\n } else {\n align = 'start'\n }\n }\n\n const options = {\n adjustments: undefined,\n behavior,\n sync: false,\n }\n if (align === 'start') {\n this._scrollToOffset(toOffset, options)\n } else if (align === 'end') {\n this._scrollToOffset(toOffset - size, options)\n } else if (align === 'center') {\n this._scrollToOffset(toOffset - size / 2, options)\n }\n }\n\n scrollToIndex = (\n index: number,\n { align = 'auto', ...rest }: ScrollToIndexOptions = {},\n ) => {\n this.pendingScrollToIndexCallback = null\n\n const measurements = this.getMeasurements()\n const offset = this.scrollOffset\n const size = this.getSize()\n const { count } = this.options\n\n const measurement = measurements[Math.max(0, Math.min(index, count - 1))]\n\n if (!measurement) {\n return\n }\n\n if (align === 'auto') {\n if (measurement.end >= offset + size - this.options.scrollPaddingEnd) {\n align = 'end'\n } else if (\n measurement.start <=\n offset + this.options.scrollPaddingStart\n ) {\n align = 'start'\n } else {\n return\n }\n }\n\n const toOffset =\n align === 'end'\n ? measurement.end + this.options.scrollPaddingEnd\n : measurement.start - this.options.scrollPaddingStart\n\n this.scrollToOffset(toOffset, { align, ...rest })\n\n const isDynamic = Object.keys(this.measureElementCache).length > 0\n\n if (isDynamic) {\n const didSeen = () =>\n typeof this.itemMeasurementsCache[this.options.getItemKey(index)] ===\n 'number'\n\n if (!didSeen()) {\n this.pendingScrollToIndexCallback = () => {\n if (didSeen()) {\n this.pendingScrollToIndexCallback = null\n this.scrollToIndex(index, { align, ...rest })\n }\n }\n }\n }\n }\n\n getTotalSize = () =>\n (this.getMeasurements()[this.options.count - 1]?.end ||\n this.options.paddingStart) + this.options.paddingEnd\n\n private _scrollToOffset = (\n offset: number,\n {\n adjustments,\n behavior,\n sync,\n }: {\n adjustments: number | undefined\n behavior: ScrollBehavior | undefined\n sync: boolean\n },\n ) => {\n this.options.scrollToFn(offset, { behavior, sync, adjustments }, this)\n }\n\n measure = () => {\n this.itemMeasurementsCache = {}\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","result","deps","depTime","key","debug","Date","now","newDeps","length","some","dep","index","resultTime","onChange","depEndTime","Math","round","resultEndTime","resultFpsPercentage","pad","str","num","String","console","info","max","min","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","scrollMargin","onScroll","e","target","currentTarget","scrollX","scrollY","addEventListener","capture","passive","removeEventListener","observeElementOffset","observeWindowOffset","measureElement","getBoundingClientRect","constructor","_this","this","unsubs","isScrolling","isScrollingTimeoutId","measurementsCache","itemMeasurementsCache","pendingMeasuredCacheIndexes","scrollAdjustments","measureElementCache","pendingScrollToIndexCallback","getResizeObserver","_ro","ResizeObserver","entries","forEach","entry","_measureElement","setOptions","Object","_ref3","value","initialOffset","paddingStart","paddingEnd","scrollPaddingStart","scrollPaddingEnd","getItemKey","rangeExtractor","initialRect","width","height","scrollingDelay","indexAttribute","notify","_this$options$onChang","_this$options","call","cleanup","filter","Boolean","d","_didMount","_this$getResizeObserv","disconnect","_willUpdate","_this$pendingScrollTo","getScrollElement","_scrollToOffset","scrollOffset","adjustments","undefined","behavior","sync","observeElementRect","rect","scrollRect","calculateRange","clearTimeout","setTimeout","getSize","getMeasurements","measurements","slice","measuredSize","size","estimateSize","process","outerSize","_ref5","low","high","getCurrentValue","middle","currentValue","findNearestBinarySearch","getIndexes","indexFromElement","node","attributeName","indexStr","getAttribute","parseInt","warn","_sync","item","prevNode","ro","isConnected","unobserve","observe","measuredItemSize","delta","getVirtualItems","indexes","virtualItems","k","len","measurement","scrollToOffset","toOffset","_temp","align","scrollToIndex","_temp2","rest","keys","didSeen","getTotalSize","_this$getMeasurements","_ref4","scrollToFn","measure","_ref2","_instance$scrollEleme2","scrollTo","observer","_entries$","_entries$2","contentRect","memoizedCallback","prev","memoRectCallback","onResize","innerWidth","innerHeight","_ref","_instance$scrollEleme"],"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.28",
|
|
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
|
@@ -292,6 +292,7 @@ export class Virtualizer<
|
|
|
292
292
|
private scrollOffset: number
|
|
293
293
|
private scrollAdjustments: number = 0
|
|
294
294
|
private measureElementCache: Record<Key, TItemElement> = {}
|
|
295
|
+
private pendingScrollToIndexCallback: (() => void) | null = null
|
|
295
296
|
private getResizeObserver = (() => {
|
|
296
297
|
let _ro: ResizeObserver | null = null
|
|
297
298
|
|
|
@@ -368,6 +369,8 @@ export class Virtualizer<
|
|
|
368
369
|
}
|
|
369
370
|
|
|
370
371
|
_willUpdate = () => {
|
|
372
|
+
this.pendingScrollToIndexCallback?.()
|
|
373
|
+
|
|
371
374
|
const scrollElement = this.options.getScrollElement()
|
|
372
375
|
|
|
373
376
|
if (this.scrollElement !== scrollElement) {
|
|
@@ -638,6 +641,8 @@ export class Virtualizer<
|
|
|
638
641
|
index: number,
|
|
639
642
|
{ align = 'auto', ...rest }: ScrollToIndexOptions = {},
|
|
640
643
|
) => {
|
|
644
|
+
this.pendingScrollToIndexCallback = null
|
|
645
|
+
|
|
641
646
|
const measurements = this.getMeasurements()
|
|
642
647
|
const offset = this.scrollOffset
|
|
643
648
|
const size = this.getSize()
|
|
@@ -668,6 +673,23 @@ export class Virtualizer<
|
|
|
668
673
|
: measurement.start - this.options.scrollPaddingStart
|
|
669
674
|
|
|
670
675
|
this.scrollToOffset(toOffset, { align, ...rest })
|
|
676
|
+
|
|
677
|
+
const isDynamic = Object.keys(this.measureElementCache).length > 0
|
|
678
|
+
|
|
679
|
+
if (isDynamic) {
|
|
680
|
+
const didSeen = () =>
|
|
681
|
+
typeof this.itemMeasurementsCache[this.options.getItemKey(index)] ===
|
|
682
|
+
'number'
|
|
683
|
+
|
|
684
|
+
if (!didSeen()) {
|
|
685
|
+
this.pendingScrollToIndexCallback = () => {
|
|
686
|
+
if (didSeen()) {
|
|
687
|
+
this.pendingScrollToIndexCallback = null
|
|
688
|
+
this.scrollToIndex(index, { align, ...rest })
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
}
|
|
671
693
|
}
|
|
672
694
|
|
|
673
695
|
getTotalSize = () =>
|