@tanstack/virtual-core 3.0.0-beta.40 → 3.0.0-beta.42

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
@@ -1,4 +1,4 @@
1
- import { memo } from './utils'
1
+ import { approxEqual, memo, notUndefined } from './utils'
2
2
 
3
3
  export * from './utils'
4
4
 
@@ -438,8 +438,6 @@ export class Virtualizer<
438
438
  }, this.options.scrollingDelay)
439
439
  }),
440
440
  )
441
- } else if (!this.isScrolling) {
442
- this.calculateRange()
443
441
  }
444
442
  }
445
443
 
@@ -490,7 +488,7 @@ export class Virtualizer<
490
488
 
491
489
  calculateRange = memo(
492
490
  () => [this.getMeasurements(), this.getSize(), this.scrollOffset],
493
- (measurements, outerSize, scrollOffset) => {
491
+ (measurements, outerSize, scrollOffset, [flush = true]: [boolean?]) => {
494
492
  const range = calculateRange({
495
493
  measurements,
496
494
  outerSize,
@@ -501,7 +499,9 @@ export class Virtualizer<
501
499
  range.endIndex !== this.range.endIndex
502
500
  ) {
503
501
  this.range = range
504
- this.notify()
502
+ if (flush) {
503
+ this.notify()
504
+ }
505
505
  }
506
506
  return this.range
507
507
  },
@@ -514,7 +514,7 @@ export class Virtualizer<
514
514
  private getIndexes = memo(
515
515
  () => [
516
516
  this.options.rangeExtractor,
517
- this.range,
517
+ this.calculateRange(false),
518
518
  this.options.overscan,
519
519
  this.options.count,
520
520
  ],
@@ -693,6 +693,8 @@ export class Virtualizer<
693
693
  index: number,
694
694
  { align = 'auto', behavior }: ScrollToIndexOptions = {},
695
695
  ) => {
696
+ index = Math.max(0, Math.min(index, this.options.count - 1))
697
+
696
698
  if (this.scrollToIndexTimeoutId !== null) {
697
699
  clearTimeout(this.scrollToIndexTimeoutId)
698
700
  this.scrollToIndexTimeoutId = null
@@ -707,19 +709,7 @@ export class Virtualizer<
707
709
  return
708
710
  }
709
711
 
710
- const getMeasurement = () => {
711
- const measurements = this.getMeasurements()
712
- const measurement =
713
- measurements[Math.max(0, Math.min(index, this.options.count - 1))]
714
-
715
- if (!measurement) {
716
- throw new Error(`VirtualItem not found for index = ${index}`)
717
- }
718
-
719
- return measurement
720
- }
721
-
722
- const measurement = getMeasurement()
712
+ const measurement = notUndefined(this.getMeasurements()[index])
723
713
 
724
714
  if (align === 'auto') {
725
715
  if (
@@ -754,8 +744,6 @@ export class Virtualizer<
754
744
  }
755
745
  this._scrollToOffset(toOffset, options)
756
746
 
757
- const approxEqual = (a: number, b: number) => Math.abs(a - b) < 1
758
-
759
747
  if (isDynamic) {
760
748
  this.scrollToIndexTimeoutId = setTimeout(() => {
761
749
  this.scrollToIndexTimeoutId = null
@@ -764,7 +752,9 @@ export class Virtualizer<
764
752
  !!this.measureElementCache[this.options.getItemKey(index)]
765
753
 
766
754
  if (elementInDOM) {
767
- const toOffset = getOffsetForIndexAndAlignment(getMeasurement())
755
+ const toOffset = getOffsetForIndexAndAlignment(
756
+ notUndefined(this.getMeasurements()[index]),
757
+ )
768
758
 
769
759
  if (!approxEqual(toOffset, this.scrollOffset)) {
770
760
  this.scrollToIndex(index, { align, behavior })
package/src/utils.ts CHANGED
@@ -2,19 +2,23 @@ export type NoInfer<A extends any> = [A][A extends any ? 0 : never]
2
2
 
3
3
  export type PartialKeys<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>
4
4
 
5
- export function memo<TDeps extends readonly any[], TResult>(
5
+ export function memo<
6
+ TDeps extends readonly any[],
7
+ TResult,
8
+ FArgs extends readonly any[],
9
+ >(
6
10
  getDeps: () => [...TDeps],
7
- fn: (...args: NoInfer<[...TDeps]>) => TResult,
11
+ fn: (...args: [...TDeps, FArgs]) => TResult,
8
12
  opts: {
9
13
  key: any
10
14
  debug?: () => any
11
15
  onChange?: (result: TResult) => void
12
16
  },
13
- ): () => TResult {
17
+ ) {
14
18
  let deps: any[] = []
15
19
  let result: TResult | undefined
16
20
 
17
- return () => {
21
+ return (...fArgs: FArgs): TResult => {
18
22
  let depTime: number
19
23
  if (opts.key && opts.debug?.()) depTime = Date.now()
20
24
 
@@ -33,7 +37,7 @@ export function memo<TDeps extends readonly any[], TResult>(
33
37
  let resultTime: number
34
38
  if (opts.key && opts.debug?.()) resultTime = Date.now()
35
39
 
36
- result = fn(...newDeps)
40
+ result = fn(...newDeps, fArgs)
37
41
  opts?.onChange?.(result)
38
42
 
39
43
  if (opts.key && opts.debug?.()) {
@@ -65,3 +69,13 @@ export function memo<TDeps extends readonly any[], TResult>(
65
69
  return result!
66
70
  }
67
71
  }
72
+
73
+ export function notUndefined<T>(value: T | undefined, msg?: string): T {
74
+ if (value === undefined) {
75
+ throw new Error(`Unexpected undefined${msg ? `: ${msg}` : ''}`)
76
+ } else {
77
+ return value
78
+ }
79
+ }
80
+
81
+ export const approxEqual = (a: number, b: number) => Math.abs(a - b) < 1