@tanstack/virtual-core 3.0.0-beta.44 → 3.0.0-beta.45

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
@@ -58,137 +58,101 @@ export const defaultRangeExtractor = (range: Range) => {
58
58
  return arr
59
59
  }
60
60
 
61
- const memoRectCallback = (
62
- instance: Virtualizer<any, any>,
61
+ export const observeElementRect = <T extends Element>(
62
+ instance: Virtualizer<T, any>,
63
63
  cb: (rect: Rect) => void,
64
64
  ) => {
65
- let prev: Rect = { height: -1, width: -1 }
66
-
67
- return (rect: Rect) => {
68
- if (
69
- instance.options.horizontal
70
- ? rect.width !== prev.width
71
- : rect.height !== prev.height
72
- ) {
73
- cb(rect)
74
- }
75
-
76
- prev = rect
65
+ const element = instance.scrollElement
66
+ if (!element) {
67
+ return
77
68
  }
78
- }
79
69
 
80
- export const observeElementRect = (
81
- instance: Virtualizer<any, any>,
82
- cb: (rect: Rect) => void,
83
- ) => {
84
- const observer = new ResizeObserver((entries) => {
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
- }
95
- })
96
-
97
- if (!instance.scrollElement) {
98
- return
70
+ const handler = () => {
71
+ const { width, height } = element.getBoundingClientRect()
72
+ cb({ width: Math.round(width), height: Math.round(height) })
99
73
  }
74
+ handler()
100
75
 
101
- cb(instance.scrollElement.getBoundingClientRect())
76
+ const observer = new ResizeObserver(() => {
77
+ handler()
78
+ })
102
79
 
103
- observer.observe(instance.scrollElement)
80
+ observer.observe(element)
104
81
 
105
82
  return () => {
106
- observer.unobserve(instance.scrollElement)
83
+ observer.unobserve(element)
107
84
  }
108
85
  }
109
86
 
110
87
  export const observeWindowRect = (
111
- instance: Virtualizer<any, any>,
88
+ instance: Virtualizer<Window, any>,
112
89
  cb: (rect: Rect) => void,
113
90
  ) => {
114
- const memoizedCallback = memoRectCallback(instance, cb)
115
- const onResize = () =>
116
- memoizedCallback({
117
- width: instance.scrollElement.innerWidth,
118
- height: instance.scrollElement.innerHeight,
119
- })
120
-
121
- if (!instance.scrollElement) {
91
+ const element = instance.scrollElement
92
+ if (!element) {
122
93
  return
123
94
  }
124
95
 
125
- onResize()
96
+ const handler = () => {
97
+ cb({ width: element.innerWidth, height: element.innerHeight })
98
+ }
99
+ handler()
126
100
 
127
- instance.scrollElement.addEventListener('resize', onResize, {
128
- capture: false,
101
+ element.addEventListener('resize', handler, {
129
102
  passive: true,
130
103
  })
131
104
 
132
105
  return () => {
133
- instance.scrollElement.removeEventListener('resize', onResize)
106
+ element.removeEventListener('resize', handler)
134
107
  }
135
108
  }
136
109
 
137
- type ObserverMode = 'element' | 'window'
138
-
139
- const scrollProps = {
140
- element: ['scrollLeft', 'scrollTop'],
141
- window: ['scrollX', 'scrollY'],
142
- } as const
143
-
144
- const createOffsetObserver = (mode: ObserverMode) => {
145
- return (instance: Virtualizer<any, any>, cb: (offset: number) => void) => {
146
- if (!instance.scrollElement) {
147
- return
148
- }
149
-
150
- const propX = scrollProps[mode][0]
151
- const propY = scrollProps[mode][1]
152
-
153
- let prevX: number = instance.scrollElement[propX]
154
- let prevY: number = instance.scrollElement[propY]
155
-
156
- const scroll = () => {
157
- const offset =
158
- instance.scrollElement[instance.options.horizontal ? propX : propY]
110
+ export const observeElementOffset = <T extends Element>(
111
+ instance: Virtualizer<T, any>,
112
+ cb: (offset: number) => void,
113
+ ) => {
114
+ const element = instance.scrollElement
115
+ if (!element) {
116
+ return
117
+ }
159
118
 
160
- cb(offset)
161
- }
119
+ const handler = () => {
120
+ cb(element[instance.options.horizontal ? 'scrollLeft' : 'scrollTop'])
121
+ }
122
+ handler()
162
123
 
163
- scroll()
124
+ element.addEventListener('scroll', handler, {
125
+ passive: true,
126
+ })
164
127
 
165
- const onScroll = (e: Event) => {
166
- const target = e.currentTarget as HTMLElement & Window
167
- const scrollX = target[propX]
168
- const scrollY = target[propY]
128
+ return () => {
129
+ element.removeEventListener('scroll', handler)
130
+ }
131
+ }
169
132
 
170
- if (instance.options.horizontal ? prevX - scrollX : prevY - scrollY) {
171
- scroll()
172
- }
133
+ export const observeWindowOffset = (
134
+ instance: Virtualizer<Window, any>,
135
+ cb: (offset: number) => void,
136
+ ) => {
137
+ const element = instance.scrollElement
138
+ if (!element) {
139
+ return
140
+ }
173
141
 
174
- prevX = scrollX
175
- prevY = scrollY
176
- }
142
+ const handler = () => {
143
+ cb(element[instance.options.horizontal ? 'scrollX' : 'scrollY'])
144
+ }
145
+ handler()
177
146
 
178
- instance.scrollElement.addEventListener('scroll', onScroll, {
179
- capture: false,
180
- passive: true,
181
- })
147
+ element.addEventListener('scroll', handler, {
148
+ passive: true,
149
+ })
182
150
 
183
- return () => {
184
- instance.scrollElement.removeEventListener('scroll', onScroll)
185
- }
151
+ return () => {
152
+ element.removeEventListener('scroll', handler)
186
153
  }
187
154
  }
188
155
 
189
- export const observeElementOffset = createOffsetObserver('element')
190
- export const observeWindowOffset = createOffsetObserver('window')
191
-
192
156
  export const measureElement = <TItemElement extends Element>(
193
157
  element: TItemElement,
194
158
  instance: Virtualizer<any, TItemElement>,
@@ -397,8 +361,15 @@ export class Virtualizer<
397
361
 
398
362
  this.unsubs.push(
399
363
  this.options.observeElementRect(this, (rect) => {
364
+ const prev = this.scrollRect
400
365
  this.scrollRect = rect
401
- this.maybeNotify()
366
+ if (
367
+ this.options.horizontal
368
+ ? rect.width !== prev.width
369
+ : rect.height !== prev.height
370
+ ) {
371
+ this.maybeNotify()
372
+ }
402
373
  }),
403
374
  )
404
375