@tanstack/virtual-core 3.0.0-beta.34 → 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 +84 -40
- package/build/lib/index.esm.js.map +1 -1
- package/build/lib/index.js +84 -40
- package/build/lib/index.js.map +1 -1
- package/build/lib/index.mjs +84 -40
- package/build/lib/index.mjs.map +1 -1
- package/build/umd/index.development.js +84 -40
- 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 +89 -35
package/src/index.ts
CHANGED
|
@@ -82,10 +82,16 @@ export const observeElementRect = (
|
|
|
82
82
|
cb: (rect: Rect) => void,
|
|
83
83
|
) => {
|
|
84
84
|
const observer = new ResizeObserver((entries) => {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
85
|
+
const entry = entries[0]
|
|
86
|
+
if (entry) {
|
|
87
|
+
const { width, height } = entry.contentRect
|
|
88
|
+
cb({
|
|
89
|
+
width: Math.round(width),
|
|
90
|
+
height: Math.round(height),
|
|
91
|
+
})
|
|
92
|
+
} else {
|
|
93
|
+
cb({ width: 0, height: 0 })
|
|
94
|
+
}
|
|
89
95
|
})
|
|
90
96
|
|
|
91
97
|
if (!instance.scrollElement) {
|
|
@@ -282,6 +288,7 @@ export class Virtualizer<
|
|
|
282
288
|
scrollElement: TScrollElement | null = null
|
|
283
289
|
isScrolling: boolean = false
|
|
284
290
|
private isScrollingTimeoutId: ReturnType<typeof setTimeout> | null = null
|
|
291
|
+
private scrollToIndexTimeoutId: ReturnType<typeof setTimeout> | null = null
|
|
285
292
|
measurementsCache: VirtualItem[] = []
|
|
286
293
|
private itemSizeCache: Record<Key, number> = {}
|
|
287
294
|
private pendingMeasuredCacheIndexes: number[] = []
|
|
@@ -290,7 +297,6 @@ export class Virtualizer<
|
|
|
290
297
|
scrollDirection: ScrollDirection | null = null
|
|
291
298
|
private scrollAdjustments: number = 0
|
|
292
299
|
private measureElementCache: Record<Key, TItemElement> = {}
|
|
293
|
-
private pendingScrollToIndexCallback: (() => void) | null = null
|
|
294
300
|
private getResizeObserver = (() => {
|
|
295
301
|
let _ro: ResizeObserver | null = null
|
|
296
302
|
|
|
@@ -374,8 +380,6 @@ export class Virtualizer<
|
|
|
374
380
|
}
|
|
375
381
|
|
|
376
382
|
_willUpdate = () => {
|
|
377
|
-
this.pendingScrollToIndexCallback?.()
|
|
378
|
-
|
|
379
383
|
const scrollElement = this.options.getScrollElement()
|
|
380
384
|
|
|
381
385
|
if (this.scrollElement !== scrollElement) {
|
|
@@ -573,11 +577,7 @@ export class Virtualizer<
|
|
|
573
577
|
const delta = measuredItemSize - itemSize
|
|
574
578
|
|
|
575
579
|
if (delta !== 0) {
|
|
576
|
-
if (
|
|
577
|
-
item.start < this.scrollOffset &&
|
|
578
|
-
this.isScrolling &&
|
|
579
|
-
this.scrollDirection === 'backward'
|
|
580
|
-
) {
|
|
580
|
+
if (item.start < this.scrollOffset) {
|
|
581
581
|
if (process.env.NODE_ENV !== 'production' && this.options.debug) {
|
|
582
582
|
console.info('correction', delta)
|
|
583
583
|
}
|
|
@@ -653,6 +653,15 @@ export class Virtualizer<
|
|
|
653
653
|
toOffset: number,
|
|
654
654
|
{ align = 'start', behavior }: ScrollToOffsetOptions = {},
|
|
655
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
|
+
|
|
656
665
|
const options = {
|
|
657
666
|
adjustments: undefined,
|
|
658
667
|
behavior,
|
|
@@ -665,25 +674,43 @@ export class Virtualizer<
|
|
|
665
674
|
index: number,
|
|
666
675
|
{ align = 'auto', behavior }: ScrollToIndexOptions = {},
|
|
667
676
|
) => {
|
|
668
|
-
this.
|
|
677
|
+
if (this.scrollToIndexTimeoutId !== null) {
|
|
678
|
+
clearTimeout(this.scrollToIndexTimeoutId)
|
|
679
|
+
this.scrollToIndexTimeoutId = null
|
|
680
|
+
}
|
|
669
681
|
|
|
670
|
-
const
|
|
671
|
-
const size = this.getSize()
|
|
672
|
-
const { count } = this.options
|
|
682
|
+
const isDynamic = Object.keys(this.measureElementCache).length > 0
|
|
673
683
|
|
|
674
|
-
|
|
675
|
-
|
|
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))]
|
|
676
695
|
|
|
677
|
-
|
|
678
|
-
|
|
696
|
+
if (!measurement) {
|
|
697
|
+
throw new Error(`VirtualItem not found for index = ${index}`)
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
return measurement
|
|
679
701
|
}
|
|
680
702
|
|
|
703
|
+
const measurement = getMeasurement()
|
|
704
|
+
|
|
681
705
|
if (align === 'auto') {
|
|
682
|
-
if (
|
|
706
|
+
if (
|
|
707
|
+
measurement.end >=
|
|
708
|
+
this.scrollOffset + this.getSize() - this.options.scrollPaddingEnd
|
|
709
|
+
) {
|
|
683
710
|
align = 'end'
|
|
684
711
|
} else if (
|
|
685
712
|
measurement.start <=
|
|
686
|
-
|
|
713
|
+
this.scrollOffset + this.options.scrollPaddingStart
|
|
687
714
|
) {
|
|
688
715
|
align = 'start'
|
|
689
716
|
} else {
|
|
@@ -697,34 +724,61 @@ export class Virtualizer<
|
|
|
697
724
|
? measurement.end + this.options.scrollPaddingEnd
|
|
698
725
|
: measurement.start - this.options.scrollPaddingStart
|
|
699
726
|
|
|
700
|
-
|
|
701
|
-
|
|
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
|
|
702
733
|
|
|
703
|
-
|
|
734
|
+
const maxOffset = scrollSize - this.getSize()
|
|
704
735
|
|
|
705
|
-
|
|
706
|
-
return
|
|
736
|
+
return Math.min(maxOffset, this.getOffsetForAlignment(toOffset, align))
|
|
707
737
|
}
|
|
708
738
|
|
|
739
|
+
const toOffset = getOffsetForIndexAndAlignment(measurement)
|
|
740
|
+
|
|
709
741
|
const options = {
|
|
710
742
|
adjustments: undefined,
|
|
711
743
|
behavior,
|
|
712
744
|
}
|
|
713
745
|
this._scrollToOffset(toOffset, options)
|
|
714
746
|
|
|
715
|
-
const
|
|
747
|
+
const approxEqual = (a: number, b: number) => Math.abs(a - b) < 1
|
|
716
748
|
|
|
717
749
|
if (isDynamic) {
|
|
718
|
-
this.
|
|
719
|
-
this.
|
|
720
|
-
|
|
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
|
+
})
|
|
721
766
|
}
|
|
722
767
|
}
|
|
723
768
|
|
|
724
|
-
scrollBy = (
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
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,
|
|
728
782
|
})
|
|
729
783
|
}
|
|
730
784
|
|