@tanstack/virtual-core 3.0.0-beta.35 → 3.0.0-beta.36
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 +2 -4
- package/build/lib/index.esm.js +69 -35
- package/build/lib/index.esm.js.map +1 -1
- package/build/lib/index.js +69 -35
- package/build/lib/index.js.map +1 -1
- package/build/lib/index.mjs +69 -35
- package/build/lib/index.mjs.map +1 -1
- package/build/umd/index.development.js +69 -35
- 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 +79 -31
package/src/index.ts
CHANGED
|
@@ -288,6 +288,7 @@ export class Virtualizer<
|
|
|
288
288
|
scrollElement: TScrollElement | null = null
|
|
289
289
|
isScrolling: boolean = false
|
|
290
290
|
private isScrollingTimeoutId: ReturnType<typeof setTimeout> | null = null
|
|
291
|
+
private scrollToIndexTimeoutId: ReturnType<typeof setTimeout> | null = null
|
|
291
292
|
measurementsCache: VirtualItem[] = []
|
|
292
293
|
private itemSizeCache: Record<Key, number> = {}
|
|
293
294
|
private pendingMeasuredCacheIndexes: number[] = []
|
|
@@ -296,7 +297,6 @@ export class Virtualizer<
|
|
|
296
297
|
scrollDirection: ScrollDirection | null = null
|
|
297
298
|
private scrollAdjustments: number = 0
|
|
298
299
|
private measureElementCache: Record<Key, TItemElement> = {}
|
|
299
|
-
private pendingScrollToIndexCallback: (() => void) | null = null
|
|
300
300
|
private getResizeObserver = (() => {
|
|
301
301
|
let _ro: ResizeObserver | null = null
|
|
302
302
|
|
|
@@ -380,8 +380,6 @@ export class Virtualizer<
|
|
|
380
380
|
}
|
|
381
381
|
|
|
382
382
|
_willUpdate = () => {
|
|
383
|
-
this.pendingScrollToIndexCallback?.()
|
|
384
|
-
|
|
385
383
|
const scrollElement = this.options.getScrollElement()
|
|
386
384
|
|
|
387
385
|
if (this.scrollElement !== scrollElement) {
|
|
@@ -579,11 +577,7 @@ export class Virtualizer<
|
|
|
579
577
|
const delta = measuredItemSize - itemSize
|
|
580
578
|
|
|
581
579
|
if (delta !== 0) {
|
|
582
|
-
if (
|
|
583
|
-
item.start < this.scrollOffset &&
|
|
584
|
-
this.isScrolling &&
|
|
585
|
-
this.scrollDirection === 'backward'
|
|
586
|
-
) {
|
|
580
|
+
if (item.start < this.scrollOffset) {
|
|
587
581
|
if (process.env.NODE_ENV !== 'production' && this.options.debug) {
|
|
588
582
|
console.info('correction', delta)
|
|
589
583
|
}
|
|
@@ -659,6 +653,15 @@ export class Virtualizer<
|
|
|
659
653
|
toOffset: number,
|
|
660
654
|
{ align = 'start', behavior }: ScrollToOffsetOptions = {},
|
|
661
655
|
) => {
|
|
656
|
+
const isDynamic = Object.keys(this.measureElementCache).length > 0
|
|
657
|
+
|
|
658
|
+
if (isDynamic && behavior === 'smooth') {
|
|
659
|
+
console.warn(
|
|
660
|
+
'The `smooth` scroll behavior is not supported with dynamic size.',
|
|
661
|
+
)
|
|
662
|
+
return
|
|
663
|
+
}
|
|
664
|
+
|
|
662
665
|
const options = {
|
|
663
666
|
adjustments: undefined,
|
|
664
667
|
behavior,
|
|
@@ -671,25 +674,43 @@ export class Virtualizer<
|
|
|
671
674
|
index: number,
|
|
672
675
|
{ align = 'auto', behavior }: ScrollToIndexOptions = {},
|
|
673
676
|
) => {
|
|
674
|
-
this.
|
|
677
|
+
if (this.scrollToIndexTimeoutId !== null) {
|
|
678
|
+
clearTimeout(this.scrollToIndexTimeoutId)
|
|
679
|
+
this.scrollToIndexTimeoutId = null
|
|
680
|
+
}
|
|
675
681
|
|
|
676
|
-
const
|
|
677
|
-
|
|
678
|
-
|
|
682
|
+
const isDynamic = Object.keys(this.measureElementCache).length > 0
|
|
683
|
+
|
|
684
|
+
if (isDynamic && behavior === 'smooth') {
|
|
685
|
+
console.warn(
|
|
686
|
+
'The `smooth` scroll behavior is not supported with dynamic size.',
|
|
687
|
+
)
|
|
688
|
+
return
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
const getMeasurement = () => {
|
|
692
|
+
const measurements = this.getMeasurements()
|
|
693
|
+
const measurement =
|
|
694
|
+
measurements[Math.max(0, Math.min(index, this.options.count - 1))]
|
|
679
695
|
|
|
680
|
-
|
|
681
|
-
|
|
696
|
+
if (!measurement) {
|
|
697
|
+
throw new Error(`VirtualItem not found for index = ${index}`)
|
|
698
|
+
}
|
|
682
699
|
|
|
683
|
-
|
|
684
|
-
throw new Error(`VirtualItem not found for index = ${index}`)
|
|
700
|
+
return measurement
|
|
685
701
|
}
|
|
686
702
|
|
|
703
|
+
const measurement = getMeasurement()
|
|
704
|
+
|
|
687
705
|
if (align === 'auto') {
|
|
688
|
-
if (
|
|
706
|
+
if (
|
|
707
|
+
measurement.end >=
|
|
708
|
+
this.scrollOffset + this.getSize() - this.options.scrollPaddingEnd
|
|
709
|
+
) {
|
|
689
710
|
align = 'end'
|
|
690
711
|
} else if (
|
|
691
712
|
measurement.start <=
|
|
692
|
-
|
|
713
|
+
this.scrollOffset + this.options.scrollPaddingStart
|
|
693
714
|
) {
|
|
694
715
|
align = 'start'
|
|
695
716
|
} else {
|
|
@@ -703,34 +724,61 @@ export class Virtualizer<
|
|
|
703
724
|
? measurement.end + this.options.scrollPaddingEnd
|
|
704
725
|
: measurement.start - this.options.scrollPaddingStart
|
|
705
726
|
|
|
706
|
-
|
|
707
|
-
|
|
727
|
+
const sizeProp = this.options.horizontal ? 'scrollWidth' : 'scrollHeight'
|
|
728
|
+
const scrollSize = this.scrollElement
|
|
729
|
+
? 'document' in this.scrollElement
|
|
730
|
+
? this.scrollElement.document.documentElement[sizeProp]
|
|
731
|
+
: this.scrollElement[sizeProp]
|
|
732
|
+
: 0
|
|
708
733
|
|
|
709
|
-
|
|
734
|
+
const maxOffset = scrollSize - this.getSize()
|
|
710
735
|
|
|
711
|
-
|
|
712
|
-
return
|
|
736
|
+
return Math.min(maxOffset, this.getOffsetForAlignment(toOffset, align))
|
|
713
737
|
}
|
|
714
738
|
|
|
739
|
+
const toOffset = getOffsetForIndexAndAlignment(measurement)
|
|
740
|
+
|
|
715
741
|
const options = {
|
|
716
742
|
adjustments: undefined,
|
|
717
743
|
behavior,
|
|
718
744
|
}
|
|
719
745
|
this._scrollToOffset(toOffset, options)
|
|
720
746
|
|
|
721
|
-
const
|
|
747
|
+
const approxEqual = (a: number, b: number) => Math.abs(a - b) < 1
|
|
722
748
|
|
|
723
749
|
if (isDynamic) {
|
|
724
|
-
this.
|
|
725
|
-
this.
|
|
726
|
-
|
|
750
|
+
this.scrollToIndexTimeoutId = setTimeout(() => {
|
|
751
|
+
this.scrollToIndexTimeoutId = null
|
|
752
|
+
|
|
753
|
+
const elementInDOM =
|
|
754
|
+
!!this.measureElementCache[this.options.getItemKey(index)]
|
|
755
|
+
|
|
756
|
+
if (elementInDOM) {
|
|
757
|
+
const toOffset = getOffsetForIndexAndAlignment(getMeasurement())
|
|
758
|
+
|
|
759
|
+
if (!approxEqual(toOffset, this.scrollOffset)) {
|
|
760
|
+
this.scrollToIndex(index, { align, behavior })
|
|
761
|
+
}
|
|
762
|
+
} else {
|
|
763
|
+
this.scrollToIndex(index, { align, behavior })
|
|
764
|
+
}
|
|
765
|
+
})
|
|
727
766
|
}
|
|
728
767
|
}
|
|
729
768
|
|
|
730
|
-
scrollBy = (
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
769
|
+
scrollBy = (delta: number, { behavior }: ScrollToOffsetOptions = {}) => {
|
|
770
|
+
const isDynamic = Object.keys(this.measureElementCache).length > 0
|
|
771
|
+
|
|
772
|
+
if (isDynamic && behavior === 'smooth') {
|
|
773
|
+
console.warn(
|
|
774
|
+
'The `smooth` scroll behavior is not supported with dynamic size.',
|
|
775
|
+
)
|
|
776
|
+
return
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
this._scrollToOffset(this.scrollOffset + delta, {
|
|
780
|
+
adjustments: undefined,
|
|
781
|
+
behavior,
|
|
734
782
|
})
|
|
735
783
|
}
|
|
736
784
|
|