@tanstack/virtual-core 3.0.0-beta.29 → 3.0.0-beta.32

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/src/index.ts CHANGED
@@ -289,7 +289,7 @@ export class Virtualizer<
289
289
  private itemMeasurementsCache: Record<Key, number> = {}
290
290
  private pendingMeasuredCacheIndexes: number[] = []
291
291
  private scrollRect: Rect
292
- private scrollOffset: number
292
+ scrollOffset: number
293
293
  private scrollAdjustments: number = 0
294
294
  private measureElementCache: Record<Key, TItemElement> = {}
295
295
  private pendingScrollToIndexCallback: (() => void) | null = null
@@ -400,23 +400,26 @@ export class Virtualizer<
400
400
  this.isScrollingTimeoutId = null
401
401
  }
402
402
 
403
- if (this.scrollOffset !== offset) {
404
- this.scrollOffset = offset
405
- this.isScrolling = true
406
- this.scrollAdjustments = 0
403
+ const onIsScrollingChange = (isScrolling: boolean) => {
404
+ if (this.isScrolling !== isScrolling) {
405
+ this.isScrolling = isScrolling
406
+ this.notify()
407
+ }
408
+ }
407
409
 
408
- this.isScrollingTimeoutId = setTimeout(() => {
409
- this.isScrollingTimeoutId = null
410
- this.isScrolling = false
410
+ this.scrollAdjustments = 0
411
411
 
412
- this.notify()
413
- }, this.options.scrollingDelay)
414
- } else {
415
- this.isScrolling = false
416
- this.scrollAdjustments = 0
412
+ if (this.scrollOffset !== offset) {
413
+ this.scrollOffset = offset
414
+ onIsScrollingChange(true)
417
415
  }
418
416
 
419
417
  this.calculateRange()
418
+
419
+ this.isScrollingTimeoutId = setTimeout(() => {
420
+ this.isScrollingTimeoutId = null
421
+ onIsScrollingChange(false)
422
+ }, this.options.scrollingDelay)
420
423
  }),
421
424
  )
422
425
  } else if (!this.isScrolling) {
@@ -608,10 +611,7 @@ export class Virtualizer<
608
611
  },
609
612
  )
610
613
 
611
- scrollToOffset = (
612
- toOffset: number,
613
- { align = 'start', behavior }: ScrollToOffsetOptions = {},
614
- ) => {
614
+ getOffsetForAlignment = (toOffset: number, align: ScrollAlignment) => {
615
615
  const offset = this.scrollOffset
616
616
  const size = this.getSize()
617
617
 
@@ -625,35 +625,43 @@ export class Virtualizer<
625
625
  }
626
626
  }
627
627
 
628
+ if (align === 'start') {
629
+ return toOffset
630
+ } else if (align === 'end') {
631
+ return toOffset - size
632
+ } else if (align === 'center') {
633
+ return toOffset - size / 2
634
+ }
635
+ return toOffset
636
+ }
637
+
638
+ scrollToOffset = (
639
+ toOffset: number,
640
+ { align = 'start', behavior }: ScrollToOffsetOptions = {},
641
+ ) => {
628
642
  const options = {
629
643
  adjustments: undefined,
630
644
  behavior,
631
645
  sync: false,
632
646
  }
633
- if (align === 'start') {
634
- this._scrollToOffset(toOffset, options)
635
- } else if (align === 'end') {
636
- this._scrollToOffset(toOffset - size, options)
637
- } else if (align === 'center') {
638
- this._scrollToOffset(toOffset - size / 2, options)
639
- }
647
+ this._scrollToOffset(this.getOffsetForAlignment(toOffset, align), options)
640
648
  }
641
649
 
642
650
  scrollToIndex = (
643
651
  index: number,
644
- { align = 'auto', ...rest }: ScrollToIndexOptions = {},
652
+ { align = 'auto', behavior }: ScrollToIndexOptions = {},
645
653
  ) => {
646
654
  this.pendingScrollToIndexCallback = null
647
655
 
648
- const measurements = this.getMeasurements()
649
656
  const offset = this.scrollOffset
650
657
  const size = this.getSize()
651
658
  const { count } = this.options
652
659
 
660
+ const measurements = this.getMeasurements()
653
661
  const measurement = measurements[Math.max(0, Math.min(index, count - 1))]
654
662
 
655
663
  if (!measurement) {
656
- return
664
+ throw new Error(`VirtualItem not found for index = ${index}`)
657
665
  }
658
666
 
659
667
  if (align === 'auto') {
@@ -669,31 +677,45 @@ export class Virtualizer<
669
677
  }
670
678
  }
671
679
 
672
- const toOffset =
673
- align === 'end'
674
- ? measurement.end + this.options.scrollPaddingEnd
675
- : measurement.start - this.options.scrollPaddingStart
680
+ const getOffsetForIndexAndAlignment = (measurement: VirtualItem) => {
681
+ const toOffset =
682
+ align === 'end'
683
+ ? measurement.end + this.options.scrollPaddingEnd
684
+ : measurement.start - this.options.scrollPaddingStart
685
+
686
+ return this.getOffsetForAlignment(toOffset, align)
687
+ }
688
+
689
+ const toOffset = getOffsetForIndexAndAlignment(measurement)
690
+
691
+ if (toOffset === offset) {
692
+ return
693
+ }
676
694
 
677
- this.scrollToOffset(toOffset, { align, ...rest })
695
+ const options = {
696
+ adjustments: undefined,
697
+ behavior,
698
+ sync: false,
699
+ }
700
+ this._scrollToOffset(toOffset, options)
678
701
 
679
702
  const isDynamic = Object.keys(this.measureElementCache).length > 0
680
703
 
681
704
  if (isDynamic) {
682
- const didSeen = () =>
683
- typeof this.itemMeasurementsCache[this.options.getItemKey(index)] ===
684
- 'number'
685
-
686
- if (!didSeen()) {
687
- this.pendingScrollToIndexCallback = () => {
688
- if (didSeen()) {
689
- this.pendingScrollToIndexCallback = null
690
- this.scrollToIndex(index, { align, ...rest })
691
- }
692
- }
705
+ this.pendingScrollToIndexCallback = () => {
706
+ this.scrollToIndex(index, { align, behavior })
693
707
  }
694
708
  }
695
709
  }
696
710
 
711
+ scrollBy = (adjustments: number, options?: { behavior: ScrollBehavior }) => {
712
+ this._scrollToOffset(this.scrollOffset, {
713
+ adjustments,
714
+ behavior: options?.behavior,
715
+ sync: false,
716
+ })
717
+ }
718
+
697
719
  getTotalSize = () =>
698
720
  (this.getMeasurements()[this.options.count - 1]?.end ||
699
721
  this.options.paddingStart) + this.options.paddingEnd