| 347 | } |
| 348 | |
| 349 | export class Virtualizer< |
| 350 | TScrollElement extends Element | Window, |
| 351 | TItemElement extends Element, |
| 352 | > { |
| 353 | private unsubs: Array<void | (() => void)> = [] |
| 354 | options!: Required<VirtualizerOptions<TScrollElement, TItemElement>> |
| 355 | scrollElement: TScrollElement | null = null |
| 356 | targetWindow: (Window & typeof globalThis) | null = null |
| 357 | isScrolling = false |
| 358 | private scrollToIndexTimeoutId: number | null = null |
| 359 | measurementsCache: Array<VirtualItem> = [] |
| 360 | private itemSizeCache = new Map<Key, number>() |
| 361 | private pendingMeasuredCacheIndexes: Array<number> = [] |
| 362 | scrollRect: Rect | null = null |
| 363 | scrollOffset: number | null = null |
| 364 | scrollDirection: ScrollDirection | null = null |
| 365 | private scrollAdjustments = 0 |
| 366 | shouldAdjustScrollPositionOnItemSizeChange: |
| 367 | | undefined |
| 368 | | (( |
| 369 | item: VirtualItem, |
| 370 | delta: number, |
| 371 | instance: Virtualizer<TScrollElement, TItemElement>, |
| 372 | ) => boolean) |
| 373 | elementsCache = new Map<Key, TItemElement>() |
| 374 | private observer = (() => { |
| 375 | let _ro: ResizeObserver | null = null |
| 376 | |
| 377 | const get = () => { |
| 378 | if (_ro) { |
| 379 | return _ro |
| 380 | } |
| 381 | |
| 382 | if (!this.targetWindow || !this.targetWindow.ResizeObserver) { |
| 383 | return null |
| 384 | } |
| 385 | |
| 386 | return (_ro = new this.targetWindow.ResizeObserver((entries) => { |
| 387 | entries.forEach((entry) => { |
| 388 | const run = () => { |
| 389 | this._measureElement(entry.target as TItemElement, entry) |
| 390 | } |
| 391 | this.options.useAnimationFrameWithResizeObserver |
| 392 | ? requestAnimationFrame(run) |
| 393 | : run() |
| 394 | }) |
| 395 | })) |
| 396 | } |
| 397 | |
| 398 | return { |
| 399 | disconnect: () => { |
| 400 | get()?.disconnect() |
| 401 | _ro = null |
| 402 | }, |
| 403 | observe: (target: Element) => |
| 404 | get()?.observe(target, { box: 'border-box' }), |
| 405 | unobserve: (target: Element) => get()?.unobserve(target), |
| 406 | } |
nothing calls this directly
no test coverage detected