@tanstack/virtual-core 3.0.0-beta.32 → 3.0.0-beta.33
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 +6 -6
- package/build/lib/index.esm.js +40 -37
- package/build/lib/index.esm.js.map +1 -1
- package/build/lib/index.js +40 -37
- package/build/lib/index.js.map +1 -1
- package/build/lib/index.mjs +40 -37
- package/build/lib/index.mjs.map +1 -1
- package/build/umd/index.development.js +40 -37
- 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 +49 -37
package/src/index.ts
CHANGED
|
@@ -4,6 +4,8 @@ export * from './utils'
|
|
|
4
4
|
|
|
5
5
|
//
|
|
6
6
|
|
|
7
|
+
type ScrollDirection = 'forward' | 'backward'
|
|
8
|
+
|
|
7
9
|
type ScrollAlignment = 'start' | 'center' | 'end' | 'auto'
|
|
8
10
|
|
|
9
11
|
type ScrollBehavior = 'auto' | 'smooth'
|
|
@@ -149,7 +151,7 @@ const createOffsetObserver = (mode: ObserverMode) => {
|
|
|
149
151
|
const offset =
|
|
150
152
|
instance.scrollElement[instance.options.horizontal ? propX : propY]
|
|
151
153
|
|
|
152
|
-
cb(
|
|
154
|
+
cb(offset)
|
|
153
155
|
}
|
|
154
156
|
|
|
155
157
|
scroll()
|
|
@@ -195,15 +197,12 @@ export const measureElement = <TItemElement extends Element>(
|
|
|
195
197
|
export const windowScroll = <T extends Window>(
|
|
196
198
|
offset: number,
|
|
197
199
|
{
|
|
198
|
-
adjustments,
|
|
200
|
+
adjustments = 0,
|
|
199
201
|
behavior,
|
|
200
|
-
|
|
201
|
-
}: { adjustments?: number; behavior?: ScrollBehavior; sync: boolean },
|
|
202
|
+
}: { adjustments?: number; behavior?: ScrollBehavior },
|
|
202
203
|
instance: Virtualizer<T, any>,
|
|
203
204
|
) => {
|
|
204
|
-
const toOffset =
|
|
205
|
-
(sync ? offset : offset + instance.options.scrollMargin) +
|
|
206
|
-
(adjustments ?? 0)
|
|
205
|
+
const toOffset = offset + adjustments
|
|
207
206
|
|
|
208
207
|
instance.scrollElement?.scrollTo?.({
|
|
209
208
|
[instance.options.horizontal ? 'left' : 'top']: toOffset,
|
|
@@ -214,15 +213,12 @@ export const windowScroll = <T extends Window>(
|
|
|
214
213
|
export const elementScroll = <T extends Element>(
|
|
215
214
|
offset: number,
|
|
216
215
|
{
|
|
217
|
-
adjustments,
|
|
216
|
+
adjustments = 0,
|
|
218
217
|
behavior,
|
|
219
|
-
|
|
220
|
-
}: { adjustments?: number; behavior?: ScrollBehavior; sync: boolean },
|
|
218
|
+
}: { adjustments?: number; behavior?: ScrollBehavior },
|
|
221
219
|
instance: Virtualizer<T, any>,
|
|
222
220
|
) => {
|
|
223
|
-
const toOffset =
|
|
224
|
-
(sync ? offset : offset + instance.options.scrollMargin) +
|
|
225
|
-
(adjustments ?? 0)
|
|
221
|
+
const toOffset = offset + adjustments
|
|
226
222
|
|
|
227
223
|
instance.scrollElement?.scrollTo?.({
|
|
228
224
|
[instance.options.horizontal ? 'left' : 'top']: toOffset,
|
|
@@ -242,7 +238,7 @@ export interface VirtualizerOptions<
|
|
|
242
238
|
// Required from the framework adapter (but can be overridden)
|
|
243
239
|
scrollToFn: (
|
|
244
240
|
offset: number,
|
|
245
|
-
options: { adjustments?: number; behavior?: ScrollBehavior
|
|
241
|
+
options: { adjustments?: number; behavior?: ScrollBehavior },
|
|
246
242
|
instance: Virtualizer<TScrollElement, TItemElement>,
|
|
247
243
|
) => void
|
|
248
244
|
observeElementRect: (
|
|
@@ -274,6 +270,7 @@ export interface VirtualizerOptions<
|
|
|
274
270
|
scrollMargin?: number
|
|
275
271
|
scrollingDelay?: number
|
|
276
272
|
indexAttribute?: string
|
|
273
|
+
initialMeasurementsCache?: VirtualItem[]
|
|
277
274
|
}
|
|
278
275
|
|
|
279
276
|
export class Virtualizer<
|
|
@@ -286,10 +283,11 @@ export class Virtualizer<
|
|
|
286
283
|
isScrolling: boolean = false
|
|
287
284
|
private isScrollingTimeoutId: ReturnType<typeof setTimeout> | null = null
|
|
288
285
|
measurementsCache: VirtualItem[] = []
|
|
289
|
-
private
|
|
286
|
+
private itemSizeCache: Record<Key, number> = {}
|
|
290
287
|
private pendingMeasuredCacheIndexes: number[] = []
|
|
291
288
|
private scrollRect: Rect
|
|
292
289
|
scrollOffset: number
|
|
290
|
+
scrollDirection: ScrollDirection | null = null
|
|
293
291
|
private scrollAdjustments: number = 0
|
|
294
292
|
private measureElementCache: Record<Key, TItemElement> = {}
|
|
295
293
|
private pendingScrollToIndexCallback: (() => void) | null = null
|
|
@@ -319,6 +317,10 @@ export class Virtualizer<
|
|
|
319
317
|
this.setOptions(opts)
|
|
320
318
|
this.scrollRect = this.options.initialRect
|
|
321
319
|
this.scrollOffset = this.options.initialOffset
|
|
320
|
+
this.measurementsCache = this.options.initialMeasurementsCache
|
|
321
|
+
this.measurementsCache.forEach((item) => {
|
|
322
|
+
this.itemSizeCache[item.key] = item.size
|
|
323
|
+
})
|
|
322
324
|
|
|
323
325
|
this.calculateRange()
|
|
324
326
|
}
|
|
@@ -345,6 +347,7 @@ export class Virtualizer<
|
|
|
345
347
|
scrollMargin: 0,
|
|
346
348
|
scrollingDelay: 150,
|
|
347
349
|
indexAttribute: 'data-index',
|
|
350
|
+
initialMeasurementsCache: [],
|
|
348
351
|
...opts,
|
|
349
352
|
}
|
|
350
353
|
}
|
|
@@ -383,7 +386,6 @@ export class Virtualizer<
|
|
|
383
386
|
this._scrollToOffset(this.scrollOffset, {
|
|
384
387
|
adjustments: undefined,
|
|
385
388
|
behavior: undefined,
|
|
386
|
-
sync: true,
|
|
387
389
|
})
|
|
388
390
|
|
|
389
391
|
this.unsubs.push(
|
|
@@ -395,6 +397,12 @@ export class Virtualizer<
|
|
|
395
397
|
|
|
396
398
|
this.unsubs.push(
|
|
397
399
|
this.options.observeElementOffset(this, (offset) => {
|
|
400
|
+
this.scrollAdjustments = 0
|
|
401
|
+
|
|
402
|
+
if (this.scrollOffset === offset) {
|
|
403
|
+
return
|
|
404
|
+
}
|
|
405
|
+
|
|
398
406
|
if (this.isScrollingTimeoutId !== null) {
|
|
399
407
|
clearTimeout(this.isScrollingTimeoutId)
|
|
400
408
|
this.isScrollingTimeoutId = null
|
|
@@ -407,17 +415,18 @@ export class Virtualizer<
|
|
|
407
415
|
}
|
|
408
416
|
}
|
|
409
417
|
|
|
410
|
-
this.
|
|
418
|
+
this.scrollDirection =
|
|
419
|
+
this.scrollOffset < offset ? 'forward' : 'backward'
|
|
411
420
|
|
|
412
|
-
|
|
413
|
-
this.scrollOffset = offset
|
|
414
|
-
onIsScrollingChange(true)
|
|
415
|
-
}
|
|
421
|
+
this.scrollOffset = offset
|
|
416
422
|
|
|
417
423
|
this.calculateRange()
|
|
418
424
|
|
|
425
|
+
onIsScrollingChange(true)
|
|
426
|
+
|
|
419
427
|
this.isScrollingTimeoutId = setTimeout(() => {
|
|
420
428
|
this.isScrollingTimeoutId = null
|
|
429
|
+
this.scrollDirection = null
|
|
421
430
|
onIsScrollingChange(false)
|
|
422
431
|
}, this.options.scrollingDelay)
|
|
423
432
|
}),
|
|
@@ -435,10 +444,11 @@ export class Virtualizer<
|
|
|
435
444
|
() => [
|
|
436
445
|
this.options.count,
|
|
437
446
|
this.options.paddingStart,
|
|
447
|
+
this.options.scrollMargin,
|
|
438
448
|
this.options.getItemKey,
|
|
439
|
-
this.
|
|
449
|
+
this.itemSizeCache,
|
|
440
450
|
],
|
|
441
|
-
(count, paddingStart, getItemKey,
|
|
451
|
+
(count, paddingStart, scrollMargin, getItemKey, itemSizeCache) => {
|
|
442
452
|
const min =
|
|
443
453
|
this.pendingMeasuredCacheIndexes.length > 0
|
|
444
454
|
? Math.min(...this.pendingMeasuredCacheIndexes)
|
|
@@ -449,10 +459,10 @@ export class Virtualizer<
|
|
|
449
459
|
|
|
450
460
|
for (let i = min; i < count; i++) {
|
|
451
461
|
const key = getItemKey(i)
|
|
452
|
-
const measuredSize =
|
|
462
|
+
const measuredSize = itemSizeCache[key]
|
|
453
463
|
const start = measurements[i - 1]
|
|
454
464
|
? measurements[i - 1]!.end
|
|
455
|
-
: paddingStart
|
|
465
|
+
: paddingStart + scrollMargin
|
|
456
466
|
const size =
|
|
457
467
|
typeof measuredSize === 'number'
|
|
458
468
|
? measuredSize
|
|
@@ -462,6 +472,7 @@ export class Virtualizer<
|
|
|
462
472
|
}
|
|
463
473
|
|
|
464
474
|
this.measurementsCache = measurements
|
|
475
|
+
|
|
465
476
|
return measurements
|
|
466
477
|
},
|
|
467
478
|
{
|
|
@@ -557,12 +568,16 @@ export class Virtualizer<
|
|
|
557
568
|
|
|
558
569
|
const measuredItemSize = this.options.measureElement(node, this)
|
|
559
570
|
|
|
560
|
-
const itemSize = this.
|
|
571
|
+
const itemSize = this.itemSizeCache[item.key] ?? item.size
|
|
561
572
|
|
|
562
573
|
const delta = measuredItemSize - itemSize
|
|
563
574
|
|
|
564
575
|
if (delta !== 0) {
|
|
565
|
-
if (
|
|
576
|
+
if (
|
|
577
|
+
item.start < this.scrollOffset &&
|
|
578
|
+
this.isScrolling &&
|
|
579
|
+
this.scrollDirection === 'backward'
|
|
580
|
+
) {
|
|
566
581
|
if (process.env.NODE_ENV !== 'production' && this.options.debug) {
|
|
567
582
|
console.info('correction', delta)
|
|
568
583
|
}
|
|
@@ -570,13 +585,12 @@ export class Virtualizer<
|
|
|
570
585
|
this._scrollToOffset(this.scrollOffset, {
|
|
571
586
|
adjustments: (this.scrollAdjustments += delta),
|
|
572
587
|
behavior: undefined,
|
|
573
|
-
sync: false,
|
|
574
588
|
})
|
|
575
589
|
}
|
|
576
590
|
|
|
577
591
|
this.pendingMeasuredCacheIndexes.push(index)
|
|
578
|
-
this.
|
|
579
|
-
...this.
|
|
592
|
+
this.itemSizeCache = {
|
|
593
|
+
...this.itemSizeCache,
|
|
580
594
|
[item.key]: measuredItemSize,
|
|
581
595
|
}
|
|
582
596
|
this.notify()
|
|
@@ -695,7 +709,6 @@ export class Virtualizer<
|
|
|
695
709
|
const options = {
|
|
696
710
|
adjustments: undefined,
|
|
697
711
|
behavior,
|
|
698
|
-
sync: false,
|
|
699
712
|
}
|
|
700
713
|
this._scrollToOffset(toOffset, options)
|
|
701
714
|
|
|
@@ -712,31 +725,30 @@ export class Virtualizer<
|
|
|
712
725
|
this._scrollToOffset(this.scrollOffset, {
|
|
713
726
|
adjustments,
|
|
714
727
|
behavior: options?.behavior,
|
|
715
|
-
sync: false,
|
|
716
728
|
})
|
|
717
729
|
}
|
|
718
730
|
|
|
719
731
|
getTotalSize = () =>
|
|
720
732
|
(this.getMeasurements()[this.options.count - 1]?.end ||
|
|
721
|
-
this.options.paddingStart)
|
|
733
|
+
this.options.paddingStart) -
|
|
734
|
+
this.options.scrollMargin +
|
|
735
|
+
this.options.paddingEnd
|
|
722
736
|
|
|
723
737
|
private _scrollToOffset = (
|
|
724
738
|
offset: number,
|
|
725
739
|
{
|
|
726
740
|
adjustments,
|
|
727
741
|
behavior,
|
|
728
|
-
sync,
|
|
729
742
|
}: {
|
|
730
743
|
adjustments: number | undefined
|
|
731
744
|
behavior: ScrollBehavior | undefined
|
|
732
|
-
sync: boolean
|
|
733
745
|
},
|
|
734
746
|
) => {
|
|
735
|
-
this.options.scrollToFn(offset, { behavior,
|
|
747
|
+
this.options.scrollToFn(offset, { behavior, adjustments }, this)
|
|
736
748
|
}
|
|
737
749
|
|
|
738
750
|
measure = () => {
|
|
739
|
-
this.
|
|
751
|
+
this.itemSizeCache = {}
|
|
740
752
|
this.notify()
|
|
741
753
|
}
|
|
742
754
|
}
|