@tanstack/virtual-core 3.0.0-beta.21 → 3.0.0-beta.22
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/cjs/index.js +28 -13
- package/build/cjs/index.js.map +1 -1
- package/build/esm/index.js +28 -13
- package/build/esm/index.js.map +1 -1
- package/build/stats.html +1 -1
- package/build/stats.json +14 -14
- package/build/types/index.d.ts +2 -2
- package/build/umd/index.development.js +28 -13
- 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 +28 -15
|
@@ -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\nexport interface ScrollToOptions {\n align?: ScrollAlignment\n smoothScroll?: boolean\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 = (\n offset: number,\n { canSmooth, sync }: { canSmooth: boolean; sync: boolean },\n instance: Virtualizer<any, any>,\n) => {\n const toOffset = sync ? offset : offset + instance.options.scrollMargin\n\n ;(instance.scrollElement as Window)?.scrollTo?.({\n [instance.options.horizontal ? 'left' : 'top']: toOffset,\n behavior: canSmooth ? 'smooth' : undefined,\n })\n}\n\nexport const elementScroll = (\n offset: number,\n { canSmooth, sync }: { canSmooth: boolean; sync: boolean },\n instance: Virtualizer<any, any>,\n) => {\n const toOffset = sync ? offset : offset + instance.options.scrollMargin\n\n ;(instance.scrollElement as Element)?.scrollTo?.({\n [instance.options.horizontal ? 'left' : 'top']: toOffset,\n behavior: canSmooth ? 'smooth' : undefined,\n })\n}\n\nexport interface VirtualizerOptions<\n TScrollElement extends unknown,\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: { canSmooth: boolean; 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 enableSmoothScroll?: boolean\n scrollMargin?: number\n scrollingDelay?: number\n indexAttribute?: string\n}\n\nexport class Virtualizer<\n TScrollElement extends unknown,\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 scrollDelta: number = 0\n private destinationOffset: undefined | number\n private scrollCheckFrame!: ReturnType<typeof setTimeout>\n private measureElementCache: Record<string, TItemElement> = {}\n private ro = new ResizeObserver((entries) => {\n entries.forEach((entry) => {\n this._measureElement(entry.target as TItemElement, false)\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 enableSmoothScroll: true,\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.ro.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 this._scrollToOffset(this.scrollOffset, {\n canSmooth: false,\n sync: true,\n requested: false,\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.scrollDelta = 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.scrollDelta = 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 _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 const key = String(item.key)\n\n const prevNode = this.measureElementCache[key]\n\n if (!node.isConnected) {\n if (prevNode) {\n this.ro.unobserve(prevNode)\n delete this.measureElementCache[key]\n }\n return\n }\n\n if (!prevNode || prevNode !== node) {\n if (prevNode) {\n this.ro.unobserve(prevNode)\n }\n this.measureElementCache[key] = node\n this.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 if (measuredItemSize !== itemSize) {\n if (item.start < this.scrollOffset) {\n if (process.env.NODE_ENV !== 'production' && this.options.debug) {\n console.info('correction', measuredItemSize - itemSize)\n }\n\n if (this.destinationOffset === undefined) {\n this.scrollDelta += measuredItemSize - itemSize\n\n this._scrollToOffset(this.scrollOffset + this.scrollDelta, {\n canSmooth: false,\n sync: false,\n requested: false,\n })\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 {\n align = 'start',\n smoothScroll = this.options.enableSmoothScroll,\n }: 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 canSmooth: smoothScroll,\n sync: false,\n requested: true,\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 {\n align = 'auto',\n smoothScroll = this.options.enableSmoothScroll,\n ...rest\n }: 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, smoothScroll, ...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 requested,\n canSmooth,\n sync,\n }: { canSmooth: boolean; sync: boolean; requested: boolean },\n ) => {\n clearTimeout(this.scrollCheckFrame)\n\n if (requested) {\n this.destinationOffset = offset\n }\n this.options.scrollToFn(offset, { canSmooth, sync }, this)\n\n let scrollCheckFrame: ReturnType<typeof setTimeout>\n\n const check = () => {\n let lastOffset = this.scrollOffset\n this.scrollCheckFrame = scrollCheckFrame = setTimeout(() => {\n if (this.scrollCheckFrame !== scrollCheckFrame) {\n return\n }\n\n if (this.scrollOffset === lastOffset) {\n this.destinationOffset = undefined\n return\n }\n lastOffset = this.scrollOffset\n check()\n }, 100)\n }\n\n check()\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","scrollDelta","measureElementCache","ro","ResizeObserver","entries","forEach","entry","_measureElement","setOptions","Object","_ref3","value","initialOffset","paddingStart","paddingEnd","scrollPaddingStart","scrollPaddingEnd","getItemKey","rangeExtractor","enableSmoothScroll","initialRect","width","height","scrollingDelay","indexAttribute","notify","_this$options$onChang","_this$options","call","cleanup","filter","Boolean","d","_didMount","disconnect","_willUpdate","getScrollElement","_scrollToOffset","scrollOffset","canSmooth","sync","requested","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","_this$itemMeasurement","item","prevNode","isConnected","unobserve","observe","measuredItemSize","itemSize","undefined","destinationOffset","getVirtualItems","indexes","virtualItems","k","len","measurement","scrollToOffset","toOffset","_temp","align","smoothScroll","scrollToIndex","_temp2","rest","getTotalSize","_this$getMeasurements","_ref4","scrollCheckFrame","scrollToFn","check","lastOffset","measure","_ref2","_instance$scrollEleme2","scrollTo","behavior","observer","_entries$","_entries$2","contentRect","memoizedCallback","prev","memoRectCallback","onResize","innerWidth","innerHeight","_ref","_instance$scrollEleme"],"mappings":";;;;;;;;;;mPAIO,SAASA,EACdC,EACAC,EACAC,GAMA,IACIC,EADAC,EAAc,GAGlB,MAAO,KACL,IAAIC,EACAH,EAAKI,KAAOJ,MAAAA,EAAKK,OAALL,EAAKK,UAAWF,EAAUG,KAAKC,OAE/C,MAAMC,EAAUV,IAMhB,KAHEU,EAAQC,SAAWP,EAAKO,QACxBD,EAAQE,MAAK,CAACC,EAAUC,IAAkBV,EAAKU,KAAWD,KAG1D,OAAOV,EAKT,IAAIY,EAMJ,GARAX,EAAOM,EAGHR,EAAKI,KAAOJ,MAAAA,EAAKK,OAALL,EAAKK,UAAWQ,EAAaP,KAAKC,OAElDN,EAASF,KAAMS,GACX,MAAJR,SAAAA,EAAMc,UAANd,EAAMc,SAAWb,GAEbD,EAAKI,KAAL,MAAYJ,EAAKK,OAALL,EAAKK,QAAW,CAC9B,MAAMU,EAAaC,KAAKC,MAAgC,KAAzBX,KAAKC,MAAQJ,IAAmB,IACzDe,EAAgBF,KAAKC,MAAmC,KAA5BX,KAAKC,MAAQM,IAAsB,IAC/DM,EAAsBD,EAAgB,GAEtCE,EAAM,CAACC,EAAsBC,KAEjC,IADAD,EAAME,OAAOF,GACNA,EAAIZ,OAASa,GAClBD,EAAM,IAAMA,EAEd,OAAOA,CAAP,EAGFG,QAAQC,KAAR,OACSL,EAAIF,EAAe,GAD5B,KACmCE,EAAIL,EAAY,oGAIhCC,KAAKU,IAChB,EACAV,KAAKW,IAAI,IAAM,IAAMR,EAAqB,MAPlD,iBASEnB,MAAAA,OAAAA,EAAAA,EAAMI,IAET,CAED,OAAOH,CAAP,CAEH,CCzBY2B,MAAAA,EAAuBhB,GAAkBA,EAEzCiB,EAAyBC,IACpC,MAAMC,EAAQf,KAAKU,IAAII,EAAME,WAAaF,EAAMG,SAAU,GACpDC,EAAMlB,KAAKW,IAAIG,EAAMK,SAAWL,EAAMG,SAAUH,EAAMM,MAAQ,GAE9DC,EAAM,GAEZ,IAAK,IAAIC,EAAIP,EAAOO,GAAKJ,EAAKI,IAC5BD,EAAIE,KAAKD,GAGX,OAAOD,CAAP,EA2EIG,EAAc,CAClBC,QAAS,CAAC,aAAc,aACxBC,OAAQ,CAAC,UAAW,YAGhBC,EAAwBC,GACrB,CAACC,EAAiCC,KACvC,IAAKD,EAASE,cACZ,OAGF,MAAMC,EAAQR,EAAYI,GAAM,GAC1BK,EAAQT,EAAYI,GAAM,GAEhC,IAAIM,EAAgBL,EAASE,cAAcC,GACvCG,EAAgBN,EAASE,cAAcE,GAE3C,MAAMG,EAAS,KACb,MAAMC,EACJR,EAASE,cAAcF,EAASS,QAAQC,WAAaP,EAAQC,GAE/DH,EAAG9B,KAAKU,IAAI,EAAG2B,EAASR,EAASS,QAAQE,cAAzC,EAGFJ,IAEA,MAAMK,EAAYC,IAChB,MAAMC,EAASD,EAAEE,cACXC,EAAUF,EAAOX,GACjBc,EAAUH,EAAOV,IAEnBJ,EAASS,QAAQC,WAAaL,EAAQW,EAAUV,EAAQW,IAC1DV,IAGFF,EAAQW,EACRV,EAAQW,CAAR,EAQF,OALAjB,EAASE,cAAcgB,iBAAiB,SAAUN,EAAU,CAC1DO,SAAS,EACTC,SAAS,IAGJ,KACLpB,EAASE,cAAcmB,oBAAoB,SAAUT,EAArD,CADF,EAMSU,EAAuBxB,EAAqB,WAC5CyB,EAAsBzB,EAAqB,UAE3C0B,EAAiB,CAC5B5B,EACAI,IAEO7B,KAAKC,MACVwB,EAAQ6B,wBACNzB,EAASS,QAAQC,WAAa,QAAU,yBA8EvC,MA4BLgB,YAAYvE,GAAwD,IAAAwE,EAAAC,KAAAA,KAxB5DC,OAAkC,GAwB0BD,KAtBpE1B,cAAuC,KAsB6B0B,KArBpEE,aAAuB,EAqB6CF,KApB5DG,qBAA6D,KAoBDH,KAnBpEI,kBAAmC,GAmBiCJ,KAlB5DK,sBAA6C,GAkBeL,KAjB5DM,4BAAwC,GAiBoBN,KAd5DO,YAAsB,EAcsCP,KAX5DQ,oBAAoD,GAWQR,KAV5DS,GAAK,IAAIC,gBAAgBC,IAC/BA,EAAQC,SAASC,IACfb,KAAKc,gBAAgBD,EAAM3B,QAAwB,EAAnD,GADF,IASkEc,KALpE3C,MAAkD,CAChDE,WAAY,EACZG,SAAU,GAGwDsC,KAQpEe,WAAcxF,IACZyF,OAAOL,QAAQpF,GAAMqF,SAAQK,IAAkB,IAAhBtF,EAAKuF,GAAWD,OACxB,IAAVC,UAA+B3F,EAAaI,EAArB,IAGpCqE,KAAKnB,QAAU,CACbjD,OAAO,EACPuF,cAAe,EACf3D,SAAU,EACV4D,aAAc,EACdC,WAAY,EACZC,mBAAoB,EACpBC,iBAAkB,EAClBzC,YAAY,EACZ0C,WAAYrE,EACZsE,eAAgBrE,EAChBsE,oBAAoB,EACpBrF,SAAU,OACVuD,iBACA+B,YAAa,CAAEC,MAAO,EAAGC,OAAQ,GACjC9C,aAAc,EACd+C,eAAgB,IAChBC,eAAgB,gBACbxG,EAlBL,EAbkEyE,KAmC5DgC,OAAS,KAAM,IAAAC,EAAAC,EACrB,OAAAD,GAAAC,EAAAlC,KAAKnB,SAAQxC,WAAb4F,EAAAE,KAAAD,EAAwBlC,KAAxB,EApCkEA,KAuC5DoC,QAAU,KAChBpC,KAAKC,OAAOoC,OAAOC,SAAS1B,SAAS2B,GAAMA,MAC3CvC,KAAKC,OAAS,GACdD,KAAK1B,cAAgB,IAArB,EA1CkE0B,KA6CpEwC,UAAY,IACH,KACLxC,KAAKS,GAAGgC,aACRzC,KAAKQ,oBAAsB,GAE3BR,KAAKoC,SAAL,EAlDgEpC,KAsDpE0C,YAAc,KACZ,MAAMpE,EAAgB0B,KAAKnB,QAAQ8D,mBAE/B3C,KAAK1B,gBAAkBA,GACzB0B,KAAKoC,UAELpC,KAAK1B,cAAgBA,EACrB0B,KAAK4C,gBAAgB5C,KAAK6C,aAAc,CACtCC,WAAW,EACXC,MAAM,EACNC,WAAW,IAGbhD,KAAKC,OAAOnC,KACVkC,KAAKnB,QAAQoE,mBAAmBjD,MAAOkD,IACrClD,KAAKmD,WAAaD,EAClBlD,KAAKoD,gBAAL,KAIJpD,KAAKC,OAAOnC,KACVkC,KAAKnB,QAAQa,qBAAqBM,MAAOpB,IACL,OAA9BoB,KAAKG,uBACPkD,aAAarD,KAAKG,sBAClBH,KAAKG,qBAAuB,MAG1BH,KAAK6C,eAAiBjE,GACxBoB,KAAK6C,aAAejE,EACpBoB,KAAKE,aAAc,EACnBF,KAAKO,YAAc,EAEnBP,KAAKG,qBAAuBmD,YAAW,KACrCtD,KAAKG,qBAAuB,KAC5BH,KAAKE,aAAc,EAEnBF,KAAKgC,QAAL,GACChC,KAAKnB,QAAQiD,kBAEhB9B,KAAKE,aAAc,EACnBF,KAAKO,YAAc,GAGrBP,KAAKoD,gBAAL,MAGMpD,KAAKE,aACfF,KAAKoD,gBACN,EAtGiEpD,KAyG5DuD,QAAU,IACTvD,KAAKmD,WAAWnD,KAAKnB,QAAQC,WAAa,QAAU,UA1GOkB,KA6G5DwD,gBAAkBpI,GACxB,IAAM,CACJ4E,KAAKnB,QAAQlB,MACbqC,KAAKnB,QAAQuC,aACbpB,KAAKnB,QAAQ2C,WACbxB,KAAKK,yBAEP,CAAC1C,EAAOyD,EAAcI,EAAYpB,KAChC,MAAMlD,EACJ8C,KAAKM,4BAA4BtE,OAAS,EACtCO,KAAKW,OAAO8C,KAAKM,6BACjB,EACNN,KAAKM,4BAA8B,GAEnC,MAAMmD,EAAezD,KAAKI,kBAAkBsD,MAAM,EAAGxG,GAErD,IAAK,IAAIW,EAAIX,EAAKW,EAAIF,EAAOE,IAAK,CAChC,MAAMlC,EAAM6F,EAAW3D,GACjB8F,EAAevD,EAAkBzE,GACjC2B,EAAQmG,EAAa5F,EAAI,GAC3B4F,EAAa5F,EAAI,GAAIJ,IACrB2D,EACEwC,EACoB,iBAAjBD,EACHA,EACA3D,KAAKnB,QAAQgF,aAAahG,GAC1BJ,EAAMH,EAAQsG,EACpBH,EAAa5F,GAAK,CAAE1B,MAAO0B,EAAGP,QAAOsG,OAAMnG,MAAK9B,MACjD,CAGD,OADAqE,KAAKI,kBAAoBqD,EAClBA,CAAP,GAEF,CACE9H,KAAKmI,EACLlI,MAAO,IAAMoE,KAAKnB,QAAQjD,QAhJsCoE,KAoJpEoD,eAAiBhI,GACf,IAAM,CAAC4E,KAAKwD,kBAAmBxD,KAAKuD,UAAWvD,KAAK6C,gBACpD,CAACY,EAAcM,EAAWlB,KACxB,MAAMxF,EA6RZ,SAQG2G,GAAA,IARqBP,aACtBA,EADsBM,UAEtBA,EAFsBlB,aAGtBA,GAKCmB,EACD,MAAMrG,EAAQ8F,EAAazH,OAAS,EAG9BuB,EAtCwB,EAC9B0G,EACAC,EACAC,EACAjD,KAEA,KAAO+C,GAAOC,GAAM,CAClB,MAAME,GAAWH,EAAMC,GAAQ,EAAK,EAC9BG,EAAeF,EAAgBC,GAErC,GAAIC,EAAenD,EACjB+C,EAAMG,EAAS,MACV,MAAIC,EAAenD,GAGxB,OAAOkD,EAFPF,EAAOE,EAAS,CAGjB,CACF,CAED,OAAIH,EAAM,EACDA,EAAM,EAEN,CACR,EAekBK,CAAwB,EAAG3G,GAF3BxB,GAAkBsH,EAAatH,GAAQmB,OAEMuF,GAChE,IAAInF,EAAWH,EAEf,KACEG,EAAWC,GACX8F,EAAa/F,GAAWD,IAAMoF,EAAekB,GAE7CrG,IAGF,MAAO,CAAEH,aAAYG,WACtB,CApTmB0F,CAAe,CAC3BK,eACAM,YACAlB,iBASF,OANExF,EAAME,aAAeyC,KAAK3C,MAAME,YAChCF,EAAMK,WAAasC,KAAK3C,MAAMK,WAE9BsC,KAAK3C,MAAQA,EACb2C,KAAKgC,UAEAhC,KAAK3C,KAAZ,GAEF,CACE1B,KAAKmI,EACLlI,MAAO,IAAMoE,KAAKnB,QAAQjD,QAvKsCoE,KA2K5DuE,WAAanJ,GACnB,IAAM,CACJ4E,KAAKnB,QAAQ4C,eACbzB,KAAK3C,MACL2C,KAAKnB,QAAQrB,SACbwC,KAAKnB,QAAQlB,SAEf,CAAC8D,EAAgBpE,EAAOG,EAAUG,IACzB8D,EAAe,IACjBpE,EACHG,WACAG,MAAOA,KAGX,CACEhC,KAAKmI,EACLlI,MAAO,IAAMoE,KAAKnB,QAAQjD,QA3LsCoE,KA+LpEwE,iBAAoBC,IAClB,MAAMC,EAAgB1E,KAAKnB,QAAQkD,eAC7B4C,EAAWF,EAAKG,aAAaF,GAEnC,OAAKC,EAOEE,SAASF,EAAU,KANxB5H,QAAQ+H,KAAR,2BAC6BJ,EAD7B,mCAGQ,EAGV,EA1MkE1E,KA6MpEc,gBAAkB,CAAC2D,EAAoBM,KAAmB,IAAAC,EACxD,MAAM7I,EAAQ6D,KAAKwE,iBAAiBC,GAE9BQ,EAAOjF,KAAKI,kBAAkBjE,GACpC,IAAK8I,EACH,OAEF,MAAMtJ,EAAMmB,OAAOmI,EAAKtJ,KAElBuJ,EAAWlF,KAAKQ,oBAAoB7E,GAE1C,IAAK8I,EAAKU,YAKR,YAJID,IACFlF,KAAKS,GAAG2E,UAAUF,UACXlF,KAAKQ,oBAAoB7E,KAK/BuJ,GAAYA,IAAaT,IACxBS,GACFlF,KAAKS,GAAG2E,UAAUF,GAEpBlF,KAAKQ,oBAAoB7E,GAAO8I,EAChCzE,KAAKS,GAAG4E,QAAQZ,IAGlB,MAAMa,EAAmBtF,KAAKnB,QAAQe,eAAe6E,EAAMzE,MAErDuF,EAAQ,OAAAP,EAAGhF,KAAKK,sBAAsB4E,EAAKtJ,MAAnCqJ,EAA2CC,EAAKrB,KAE1D0B,IAAqBC,IACnBN,EAAK3H,MAAQ0C,KAAK6C,mBAKW2C,IAA3BxF,KAAKyF,oBACPzF,KAAKO,aAAe+E,EAAmBC,EAEvCvF,KAAK4C,gBAAgB5C,KAAK6C,aAAe7C,KAAKO,YAAa,CACzDuC,WAAW,EACXC,MAAM,EACNC,WAAW,KAKjBhD,KAAKM,4BAA4BxC,KAAK3B,GACtC6D,KAAKK,sBAAwB,IACxBL,KAAKK,sBACR,CAAC4E,EAAKtJ,KAAM2J,GAEdtF,KAAKgC,SACN,EAnQiEhC,KAsQpEJ,eAAkB6E,IACXA,GAILzE,KAAKc,gBAAgB2D,GAAM,EAA3B,EA3QkEzE,KA8QpE0F,gBAAkBtK,GAChB,IAAM,CAAC4E,KAAKuE,aAAcvE,KAAKwD,qBAC/B,CAACmC,EAASlC,KACR,MAAMmC,EAA8B,GAEpC,IAAK,IAAIC,EAAI,EAAGC,EAAMH,EAAQ3J,OAAQ6J,EAAIC,EAAKD,IAAK,CAClD,MACME,EAActC,EADVkC,EAAQE,IAGlBD,EAAa9H,KAAKiI,EACnB,CAED,OAAOH,CAAP,GAEF,CACEjK,KAAKmI,EACLlI,MAAO,IAAMoE,KAAKnB,QAAQjD,QA9RsCoE,KAkSpEgG,eAAiB,SACfC,EAKGC,GAAA,IAJHC,MACEA,EAAQ,QADVC,aAEEA,EAAerG,EAAKlB,QAAQ6C,+BACH,CAAA,EACxBwE,EACH,MAAMtH,EAASmB,EAAK8C,aACde,EAAO7D,EAAKwD,UAEJ,SAAV4C,IAEAA,EADEF,GAAYrH,EACN,QACCqH,GAAYrH,EAASgF,EACtB,MAEA,SAIZ,MAAM/E,EAAU,CACdiE,UAAWsD,EACXrD,MAAM,EACNC,WAAW,GAEC,UAAVmD,EACFpG,EAAK6C,gBAAgBqD,EAAUpH,GACZ,QAAVsH,EACTpG,EAAK6C,gBAAgBqD,EAAWrC,EAAM/E,GACnB,WAAVsH,GACTpG,EAAK6C,gBAAgBqD,EAAWrC,EAAO,EAAG/E,IAhUsBmB,KAoUpEqG,cAAgB,SACdlK,EAMGmK,GAAA,IALHH,MACEA,EAAQ,OADVC,aAEEA,EAAerG,EAAKlB,QAAQ6C,sBACzB6E,cACqB,CAAA,EACvBD,EACH,MAAM7C,EAAe1D,EAAKyD,kBACpB5E,EAASmB,EAAK8C,aACde,EAAO7D,EAAKwD,WACZ5F,MAAEA,GAAUoC,EAAKlB,QAEjBkH,EAActC,EAAalH,KAAKU,IAAI,EAAGV,KAAKW,IAAIf,EAAOwB,EAAQ,KAErE,IAAKoI,EACH,OAGF,GAAc,SAAVI,EACF,GAAIJ,EAAYtI,KAAOmB,EAASgF,EAAO7D,EAAKlB,QAAQ0C,iBAClD4E,EAAQ,UACH,MACLJ,EAAYzI,OACZsB,EAASmB,EAAKlB,QAAQyC,oBAItB,OAFA6E,EAAQ,OAGT,CAGH,MAAMF,EACM,QAAVE,EACIJ,EAAYtI,IAAMsC,EAAKlB,QAAQ0C,iBAC/BwE,EAAYzI,MAAQyC,EAAKlB,QAAQyC,mBAEvCvB,EAAKiG,eAAeC,EAAU,CAAEE,QAAOC,kBAAiBG,KAzWUvG,KA4WpEwG,aAAe,KAAA,IAAAC,EAAA,sBACPjD,kBAAkBxD,KAAKnB,QAAQlB,MAAQ,aAAIF,MAC/CuC,KAAKnB,QAAQuC,cAAgBpB,KAAKnB,QAAQwC,UAF/B,EA5WqDrB,KAgX5D4C,gBAAkB,CACxBhE,EAMG8H,KAAA,IAQCC,GAbJ3D,UACEA,EADFF,UAEEA,EAFFC,KAGEA,GAEC2D,EACHrD,aAAarD,KAAK2G,kBAEd3D,IACFhD,KAAKyF,kBAAoB7G,GAE3BoB,KAAKnB,QAAQ+H,WAAWhI,EAAQ,CAAEkE,YAAWC,QAAQ/C,MAIrD,MAAM6G,EAAQ,KACZ,IAAIC,EAAa9G,KAAK6C,aACtB7C,KAAK2G,iBAAmBA,EAAmBrD,YAAW,KAChDtD,KAAK2G,mBAAqBA,IAI1B3G,KAAK6C,eAAiBiE,GAI1BA,EAAa9G,KAAK6C,aAClBgE,KAJE7G,KAAKyF,uBAAoBD,EAItB,GACJ,IAXH,EAcFqB,GAAK,EAjZ6D7G,KAoZpE+G,QAAU,KACR/G,KAAKK,sBAAwB,GAC7BL,KAAKgC,QAAL,EArZAhC,KAAKe,WAAWxF,GAChByE,KAAKmD,WAAanD,KAAKnB,QAAQ8C,YAC/B3B,KAAK6C,aAAe7C,KAAKnB,QAAQsC,cAEjCnB,KAAKoD,gBACN,qEA9F0B,CAC3BxE,EAD2BoI,EAG3B5I,KACG,IAAA6I,EAAA,IAFHnE,UAAEA,EAAFC,KAAaA,GAEViE,EACH,MAAMf,EAAWlD,EAAOnE,EAASA,EAASR,EAASS,QAAQE,oBAE1DkI,EAAC7I,EAASE,gBAAV,QAAqC4I,UAArCD,EAAqCC,SAAW,CAC/C,CAAC9I,EAASS,QAAQC,WAAa,OAAS,OAAQmH,EAChDkB,SAAUrE,EAAY,cAAW0C,GAFlC,4EAzI+B,CAChCpH,EACAC,KAEA,MAAM+I,EAAW,IAAI1G,gBAAgBC,IAAY,IAAA0G,EAAAC,EAC/CjJ,EAAG,CACDuD,MAAO,OAAFyF,EAAE1G,EAAQ,SAAR,EAAA0G,EAAYE,YAAY3F,MAC/BC,OAAQ,OAAFyF,EAAE3G,EAAQ,SAAR,EAAA2G,EAAYC,YAAY1F,QAFlC,IAMF,GAAKzD,EAASE,cAQd,OAJAD,EAAGD,EAASE,cAAcuB,yBAE1BuH,EAAS/B,QAAQjH,EAASE,eAEnB,KACL8I,EAAShC,UAAUhH,EAASE,cAA5B,CADF,8CAK+B,CAC/BF,EACAC,KAEA,MAAMmJ,EA/CiB,EACvBpJ,EACAC,KAEA,IAAIoJ,EAAa,CAAE5F,QAAS,EAAGD,OAAQ,GAEvC,OAAQsB,KAEJ9E,EAASS,QAAQC,WACboE,EAAKtB,QAAU6F,EAAK7F,MACpBsB,EAAKrB,SAAW4F,EAAK5F,SAEzBxD,EAAG6E,GAGLuE,EAAOvE,CAAP,CATF,EAyCyBwE,CAAiBtJ,EAAUC,GAC9CsJ,EAAW,IACfH,EAAiB,CACf5F,MAAOxD,EAASE,cAAcsJ,WAC9B/F,OAAQzD,EAASE,cAAcuJ,cAGnC,GAAKzJ,EAASE,cAWd,OAPAqJ,IAEAvJ,EAASE,cAAcgB,iBAAiB,SAAUqI,EAAU,CAC1DpI,SAAS,EACTC,SAAS,IAGJ,KACLpB,EAASE,cAAcmB,oBAAoB,SAAUkI,EAArD,CADF,iBAuE0B,CAC1B/I,EAD0BkJ,EAG1B1J,KACG,IAAA2J,EAAA,IAFHjF,UAAEA,EAAFC,KAAaA,GAEV+E,EACH,MAAM7B,EAAWlD,EAAOnE,EAASA,EAASR,EAASS,QAAQE,oBAE1DgJ,EAAC3J,EAASE,gBAAV,QAAoC4I,UAApCa,EAAoCb,SAAW,CAC9C,CAAC9I,EAASS,QAAQC,WAAa,OAAS,OAAQmH,EAChDkB,SAAUrE,EAAY,cAAW0C,GAFlC"}
|
|
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\nexport interface ScrollToOptions {\n align?: ScrollAlignment\n smoothScroll?: boolean\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 = (\n offset: number,\n { canSmooth, sync }: { canSmooth: boolean; sync: boolean },\n instance: Virtualizer<any, any>,\n) => {\n const toOffset = sync ? offset : offset + instance.options.scrollMargin\n\n ;(instance.scrollElement as Window)?.scrollTo?.({\n [instance.options.horizontal ? 'left' : 'top']: toOffset,\n behavior: canSmooth ? 'smooth' : undefined,\n })\n}\n\nexport const elementScroll = (\n offset: number,\n { canSmooth, sync }: { canSmooth: boolean; sync: boolean },\n instance: Virtualizer<any, any>,\n) => {\n const toOffset = sync ? offset : offset + instance.options.scrollMargin\n\n ;(instance.scrollElement as Element)?.scrollTo?.({\n [instance.options.horizontal ? 'left' : 'top']: toOffset,\n behavior: canSmooth ? 'smooth' : undefined,\n })\n}\n\nexport interface VirtualizerOptions<\n TScrollElement extends unknown,\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: { canSmooth: boolean; 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 enableSmoothScroll?: boolean\n scrollMargin?: number\n scrollingDelay?: number\n indexAttribute?: string\n}\n\nexport class Virtualizer<\n TScrollElement extends unknown,\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 scrollDelta: number = 0\n private destinationOffset: undefined | number\n private scrollCheckFrame!: ReturnType<typeof setTimeout>\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 enableSmoothScroll: true,\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 this._scrollToOffset(this.scrollOffset, {\n canSmooth: false,\n sync: true,\n requested: false,\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.scrollDelta = 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.scrollDelta = 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 if (measuredItemSize !== itemSize) {\n if (item.start < this.scrollOffset) {\n if (process.env.NODE_ENV !== 'production' && this.options.debug) {\n console.info('correction', measuredItemSize - itemSize)\n }\n\n if (this.destinationOffset === undefined) {\n this.scrollDelta += measuredItemSize - itemSize\n\n this._scrollToOffset(this.scrollOffset + this.scrollDelta, {\n canSmooth: false,\n sync: false,\n requested: false,\n })\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 {\n align = 'start',\n smoothScroll = this.options.enableSmoothScroll,\n }: 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 canSmooth: smoothScroll,\n sync: false,\n requested: true,\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 {\n align = 'auto',\n smoothScroll = this.options.enableSmoothScroll,\n ...rest\n }: 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, smoothScroll, ...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 requested,\n canSmooth,\n sync,\n }: { canSmooth: boolean; sync: boolean; requested: boolean },\n ) => {\n clearTimeout(this.scrollCheckFrame)\n\n if (requested) {\n this.destinationOffset = offset\n }\n this.options.scrollToFn(offset, { canSmooth, sync }, this)\n\n let scrollCheckFrame: ReturnType<typeof setTimeout>\n\n const check = () => {\n let lastOffset = this.scrollOffset\n this.scrollCheckFrame = scrollCheckFrame = setTimeout(() => {\n if (this.scrollCheckFrame !== scrollCheckFrame) {\n return\n }\n\n if (this.scrollOffset === lastOffset) {\n this.destinationOffset = undefined\n return\n }\n lastOffset = this.scrollOffset\n check()\n }, 100)\n }\n\n check()\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","scrollDelta","measureElementCache","getResizeObserver","_ro","ResizeObserver","entries","forEach","entry","_measureElement","setOptions","Object","_ref3","value","initialOffset","paddingStart","paddingEnd","scrollPaddingStart","scrollPaddingEnd","getItemKey","rangeExtractor","enableSmoothScroll","initialRect","width","height","scrollingDelay","indexAttribute","notify","_this$options$onChang","_this$options","call","cleanup","filter","Boolean","d","_didMount","_this$getResizeObserv","disconnect","_willUpdate","getScrollElement","_scrollToOffset","scrollOffset","canSmooth","sync","requested","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","_this$itemMeasurement","item","prevNode","ro","isConnected","unobserve","observe","measuredItemSize","itemSize","undefined","destinationOffset","getVirtualItems","indexes","virtualItems","k","len","measurement","scrollToOffset","toOffset","_temp","align","smoothScroll","scrollToIndex","_temp2","rest","getTotalSize","_this$getMeasurements","_ref4","scrollCheckFrame","scrollToFn","check","lastOffset","measure","_ref2","_instance$scrollEleme2","scrollTo","behavior","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.22",
|
|
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
|
@@ -280,12 +280,24 @@ export class Virtualizer<
|
|
|
280
280
|
private scrollDelta: number = 0
|
|
281
281
|
private destinationOffset: undefined | number
|
|
282
282
|
private scrollCheckFrame!: ReturnType<typeof setTimeout>
|
|
283
|
-
private measureElementCache: Record<
|
|
284
|
-
private
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
283
|
+
private measureElementCache: Record<Key, TItemElement> = {}
|
|
284
|
+
private getResizeObserver = (() => {
|
|
285
|
+
let _ro: ResizeObserver | null = null
|
|
286
|
+
|
|
287
|
+
return () => {
|
|
288
|
+
if (_ro) {
|
|
289
|
+
return _ro
|
|
290
|
+
} else if (typeof ResizeObserver !== 'undefined') {
|
|
291
|
+
return (_ro = new ResizeObserver((entries) => {
|
|
292
|
+
entries.forEach((entry) => {
|
|
293
|
+
this._measureElement(entry.target as TItemElement, false)
|
|
294
|
+
})
|
|
295
|
+
}))
|
|
296
|
+
} else {
|
|
297
|
+
return null
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
})()
|
|
289
301
|
range: { startIndex: number; endIndex: number } = {
|
|
290
302
|
startIndex: 0,
|
|
291
303
|
endIndex: 0,
|
|
@@ -338,7 +350,7 @@ export class Virtualizer<
|
|
|
338
350
|
|
|
339
351
|
_didMount = () => {
|
|
340
352
|
return () => {
|
|
341
|
-
this.
|
|
353
|
+
this.getResizeObserver()?.disconnect()
|
|
342
354
|
this.measureElementCache = {}
|
|
343
355
|
|
|
344
356
|
this.cleanup()
|
|
@@ -496,31 +508,32 @@ export class Virtualizer<
|
|
|
496
508
|
return parseInt(indexStr, 10)
|
|
497
509
|
}
|
|
498
510
|
|
|
499
|
-
_measureElement = (node: TItemElement, _sync: boolean) => {
|
|
511
|
+
private _measureElement = (node: TItemElement, _sync: boolean) => {
|
|
500
512
|
const index = this.indexFromElement(node)
|
|
501
513
|
|
|
502
514
|
const item = this.measurementsCache[index]
|
|
503
515
|
if (!item) {
|
|
504
516
|
return
|
|
505
517
|
}
|
|
506
|
-
const key = String(item.key)
|
|
507
518
|
|
|
508
|
-
const prevNode = this.measureElementCache[key]
|
|
519
|
+
const prevNode = this.measureElementCache[item.key]
|
|
520
|
+
|
|
521
|
+
const ro = this.getResizeObserver()
|
|
509
522
|
|
|
510
523
|
if (!node.isConnected) {
|
|
511
524
|
if (prevNode) {
|
|
512
|
-
|
|
513
|
-
delete this.measureElementCache[key]
|
|
525
|
+
ro?.unobserve(prevNode)
|
|
526
|
+
delete this.measureElementCache[item.key]
|
|
514
527
|
}
|
|
515
528
|
return
|
|
516
529
|
}
|
|
517
530
|
|
|
518
531
|
if (!prevNode || prevNode !== node) {
|
|
519
532
|
if (prevNode) {
|
|
520
|
-
|
|
533
|
+
ro?.unobserve(prevNode)
|
|
521
534
|
}
|
|
522
|
-
this.measureElementCache[key] = node
|
|
523
|
-
|
|
535
|
+
this.measureElementCache[item.key] = node
|
|
536
|
+
ro?.observe(node)
|
|
524
537
|
}
|
|
525
538
|
|
|
526
539
|
const measuredItemSize = this.options.measureElement(node, this)
|