@tanstack/virtual-core 3.0.0-beta.2 → 3.0.0-beta.21
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/cjs/{packages/virtual-core/src/index.js → index.js} +285 -116
- package/build/cjs/index.js.map +1 -0
- package/build/cjs/{packages/virtual-core/src/utils.js → utils.js} +0 -0
- package/build/cjs/utils.js.map +1 -0
- package/build/esm/index.js +285 -185
- package/build/esm/index.js.map +1 -1
- package/build/{stats-html.html → stats.html} +1 -1
- package/build/{stats-react.json → stats.json} +14 -39
- package/build/types/index.d.ts +69 -25
- package/build/umd/index.development.js +283 -183
- 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 +4 -6
- package/src/index.ts +302 -160
- package/build/cjs/packages/virtual-core/src/index.js.map +0 -1
- package/build/cjs/packages/virtual-core/src/utils.js.map +0 -1
- package/build/types/utils.d.ts +0 -7
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sources":["../../src/utils.ts"],"sourcesContent":["export type NoInfer<A extends any> = [A][A extends any ? 0 : never]\n\nexport type PartialKeys<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>\n\nexport function memo<TDeps extends readonly any[], TResult>(\n getDeps: () => [...TDeps],\n fn: (...args: NoInfer<[...TDeps]>) => TResult,\n opts: {\n key: any\n debug?: () => any\n onChange?: (result: TResult) => void\n },\n): () => TResult {\n let deps: any[] = []\n let result: TResult | undefined\n\n return () => {\n let depTime: number\n if (opts.key && opts.debug?.()) depTime = Date.now()\n\n const newDeps = getDeps()\n\n const depsChanged =\n newDeps.length !== deps.length ||\n newDeps.some((dep: any, index: number) => deps[index] !== dep)\n\n if (!depsChanged) {\n return result!\n }\n\n deps = newDeps\n\n let resultTime: number\n if (opts.key && opts.debug?.()) resultTime = Date.now()\n\n result = fn(...newDeps)\n opts?.onChange?.(result)\n\n if (opts.key && opts.debug?.()) {\n const depEndTime = Math.round((Date.now() - depTime!) * 100) / 100\n const resultEndTime = Math.round((Date.now() - resultTime!) * 100) / 100\n const resultFpsPercentage = resultEndTime / 16\n\n const pad = (str: number | string, num: number) => {\n str = String(str)\n while (str.length < num) {\n str = ' ' + str\n }\n return str\n }\n\n console.info(\n `%c⏱ ${pad(resultEndTime, 5)} /${pad(depEndTime, 5)} ms`,\n `\n font-size: .6rem;\n font-weight: bold;\n color: hsl(${Math.max(\n 0,\n Math.min(120 - 120 * resultFpsPercentage, 120),\n )}deg 100% 31%);`,\n opts?.key,\n )\n }\n\n return result!\n }\n}\n"],"names":["memo","getDeps","fn","opts","deps","result","depTime","key","debug","Date","now","newDeps","depsChanged","length","some","dep","index","resultTime","onChange","depEndTime","Math","round","resultEndTime","resultFpsPercentage","pad","str","num","String","console","info","max","min"],"mappings":";;;;;;;;;;;;;;AAIO,SAASA,IAAT,CACLC,OADK,EAELC,EAFK,EAGLC,IAHK,EAQU;EACf,IAAIC,IAAW,GAAG,EAAlB,CAAA;AACA,EAAA,IAAIC,MAAJ,CAAA;AAEA,EAAA,OAAO,MAAM;AACX,IAAA,IAAIC,OAAJ,CAAA;AACA,IAAA,IAAIH,IAAI,CAACI,GAAL,IAAYJ,IAAI,CAACK,KAAjB,IAAYL,IAAAA,IAAAA,IAAI,CAACK,KAAL,EAAhB,EAAgCF,OAAO,GAAGG,IAAI,CAACC,GAAL,EAAV,CAAA;IAEhC,MAAMC,OAAO,GAAGV,OAAO,EAAvB,CAAA;IAEA,MAAMW,WAAW,GACfD,OAAO,CAACE,MAAR,KAAmBT,IAAI,CAACS,MAAxB,IACAF,OAAO,CAACG,IAAR,CAAa,CAACC,GAAD,EAAWC,KAAX,KAA6BZ,IAAI,CAACY,KAAD,CAAJ,KAAgBD,GAA1D,CAFF,CAAA;;IAIA,IAAI,CAACH,WAAL,EAAkB;AAChB,MAAA,OAAOP,MAAP,CAAA;AACD,KAAA;;AAEDD,IAAAA,IAAI,GAAGO,OAAP,CAAA;AAEA,IAAA,IAAIM,UAAJ,CAAA;AACA,IAAA,IAAId,IAAI,CAACI,GAAL,IAAYJ,IAAI,CAACK,KAAjB,IAAYL,IAAAA,IAAAA,IAAI,CAACK,KAAL,EAAhB,EAAgCS,UAAU,GAAGR,IAAI,CAACC,GAAL,EAAb,CAAA;AAEhCL,IAAAA,MAAM,GAAGH,EAAE,CAAC,GAAGS,OAAJ,CAAX,CAAA;IACAR,IAAI,IAAA,IAAJ,GAAAA,KAAAA,CAAAA,GAAAA,IAAI,CAAEe,QAAN,oBAAAf,IAAI,CAAEe,QAAN,CAAiBb,MAAjB,CAAA,CAAA;;AAEA,IAAA,IAAIF,IAAI,CAACI,GAAL,IAAYJ,IAAI,CAACK,KAAjB,IAAA,IAAA,IAAYL,IAAI,CAACK,KAAL,EAAhB,EAAgC;AAC9B,MAAA,MAAMW,UAAU,GAAGC,IAAI,CAACC,KAAL,CAAW,CAACZ,IAAI,CAACC,GAAL,EAAaJ,GAAAA,OAAd,IAA0B,GAArC,IAA4C,GAA/D,CAAA;AACA,MAAA,MAAMgB,aAAa,GAAGF,IAAI,CAACC,KAAL,CAAW,CAACZ,IAAI,CAACC,GAAL,EAAaO,GAAAA,UAAd,IAA6B,GAAxC,IAA+C,GAArE,CAAA;AACA,MAAA,MAAMM,mBAAmB,GAAGD,aAAa,GAAG,EAA5C,CAAA;;AAEA,MAAA,MAAME,GAAG,GAAG,CAACC,GAAD,EAAuBC,GAAvB,KAAuC;AACjDD,QAAAA,GAAG,GAAGE,MAAM,CAACF,GAAD,CAAZ,CAAA;;AACA,QAAA,OAAOA,GAAG,CAACZ,MAAJ,GAAaa,GAApB,EAAyB;UACvBD,GAAG,GAAG,MAAMA,GAAZ,CAAA;AACD,SAAA;;AACD,QAAA,OAAOA,GAAP,CAAA;OALF,CAAA;;AAQAG,MAAAA,OAAO,CAACC,IAAR,CAAA,WAAA,GACSL,GAAG,CAACF,aAAD,EAAgB,CAAhB,CADZ,GAAA,IAAA,GACmCE,GAAG,CAACL,UAAD,EAAa,CAAb,CADtC,uGAKmBC,IAAI,CAACU,GAAL,CACX,CADW,EAEXV,IAAI,CAACW,GAAL,CAAS,MAAM,GAAMR,GAAAA,mBAArB,EAA0C,GAA1C,CAFW,CALnB,GAAA,gBAAA,EASEpB,IATF,IASEA,IAAAA,GAAAA,KAAAA,CAAAA,GAAAA,IAAI,CAAEI,GATR,CAAA,CAAA;AAWD,KAAA;;AAED,IAAA,OAAOF,MAAP,CAAA;GAhDF,CAAA;AAkDD;;;;"}
|
package/build/esm/index.js
CHANGED
|
@@ -8,76 +8,6 @@
|
|
|
8
8
|
*
|
|
9
9
|
* @license MIT
|
|
10
10
|
*/
|
|
11
|
-
var props = ["bottom", "height", "left", "right", "top", "width"];
|
|
12
|
-
|
|
13
|
-
var rectChanged = function rectChanged(a, b) {
|
|
14
|
-
if (a === void 0) {
|
|
15
|
-
a = {};
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
if (b === void 0) {
|
|
19
|
-
b = {};
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
return props.some(function (prop) {
|
|
23
|
-
return a[prop] !== b[prop];
|
|
24
|
-
});
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
var observedNodes = /*#__PURE__*/new Map();
|
|
28
|
-
var rafId;
|
|
29
|
-
|
|
30
|
-
var run = function run() {
|
|
31
|
-
var changedStates = [];
|
|
32
|
-
observedNodes.forEach(function (state, node) {
|
|
33
|
-
var newRect = node.getBoundingClientRect();
|
|
34
|
-
|
|
35
|
-
if (rectChanged(newRect, state.rect)) {
|
|
36
|
-
state.rect = newRect;
|
|
37
|
-
changedStates.push(state);
|
|
38
|
-
}
|
|
39
|
-
});
|
|
40
|
-
changedStates.forEach(function (state) {
|
|
41
|
-
state.callbacks.forEach(function (cb) {
|
|
42
|
-
return cb(state.rect);
|
|
43
|
-
});
|
|
44
|
-
});
|
|
45
|
-
rafId = window.requestAnimationFrame(run);
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
function observeRect(node, cb) {
|
|
49
|
-
return {
|
|
50
|
-
observe: function observe() {
|
|
51
|
-
var wasEmpty = observedNodes.size === 0;
|
|
52
|
-
|
|
53
|
-
if (observedNodes.has(node)) {
|
|
54
|
-
observedNodes.get(node).callbacks.push(cb);
|
|
55
|
-
} else {
|
|
56
|
-
observedNodes.set(node, {
|
|
57
|
-
rect: undefined,
|
|
58
|
-
hasRectChanged: false,
|
|
59
|
-
callbacks: [cb]
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
if (wasEmpty) run();
|
|
64
|
-
},
|
|
65
|
-
unobserve: function unobserve() {
|
|
66
|
-
var state = observedNodes.get(node);
|
|
67
|
-
|
|
68
|
-
if (state) {
|
|
69
|
-
// Remove the callback
|
|
70
|
-
var index = state.callbacks.indexOf(cb);
|
|
71
|
-
if (index >= 0) state.callbacks.splice(index, 1); // Remove the node reference
|
|
72
|
-
|
|
73
|
-
if (!state.callbacks.length) observedNodes["delete"](node); // Stop the loop
|
|
74
|
-
|
|
75
|
-
if (!observedNodes.size) cancelAnimationFrame(rafId);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
|
|
81
11
|
function memo(getDeps, fn, opts) {
|
|
82
12
|
let deps = [];
|
|
83
13
|
let result;
|
|
@@ -132,9 +62,29 @@ const defaultRangeExtractor = range => {
|
|
|
132
62
|
|
|
133
63
|
return arr;
|
|
134
64
|
};
|
|
65
|
+
|
|
66
|
+
const memoRectCallback = (instance, cb) => {
|
|
67
|
+
let prev = {
|
|
68
|
+
height: -1,
|
|
69
|
+
width: -1
|
|
70
|
+
};
|
|
71
|
+
return rect => {
|
|
72
|
+
if (instance.options.horizontal ? rect.width !== prev.width : rect.height !== prev.height) {
|
|
73
|
+
cb(rect);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
prev = rect;
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
|
|
135
80
|
const observeElementRect = (instance, cb) => {
|
|
136
|
-
const observer =
|
|
137
|
-
|
|
81
|
+
const observer = new ResizeObserver(entries => {
|
|
82
|
+
var _entries$, _entries$2;
|
|
83
|
+
|
|
84
|
+
cb({
|
|
85
|
+
width: (_entries$ = entries[0]) == null ? void 0 : _entries$.contentRect.width,
|
|
86
|
+
height: (_entries$2 = entries[0]) == null ? void 0 : _entries$2.contentRect.height
|
|
87
|
+
});
|
|
138
88
|
});
|
|
139
89
|
|
|
140
90
|
if (!instance.scrollElement) {
|
|
@@ -142,18 +92,18 @@ const observeElementRect = (instance, cb) => {
|
|
|
142
92
|
}
|
|
143
93
|
|
|
144
94
|
cb(instance.scrollElement.getBoundingClientRect());
|
|
145
|
-
observer.observe();
|
|
95
|
+
observer.observe(instance.scrollElement);
|
|
146
96
|
return () => {
|
|
147
|
-
observer.unobserve();
|
|
97
|
+
observer.unobserve(instance.scrollElement);
|
|
148
98
|
};
|
|
149
99
|
};
|
|
150
100
|
const observeWindowRect = (instance, cb) => {
|
|
151
|
-
const
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
};
|
|
101
|
+
const memoizedCallback = memoRectCallback(instance, cb);
|
|
102
|
+
|
|
103
|
+
const onResize = () => memoizedCallback({
|
|
104
|
+
width: instance.scrollElement.innerWidth,
|
|
105
|
+
height: instance.scrollElement.innerHeight
|
|
106
|
+
});
|
|
157
107
|
|
|
158
108
|
if (!instance.scrollElement) {
|
|
159
109
|
return;
|
|
@@ -168,52 +118,80 @@ const observeWindowRect = (instance, cb) => {
|
|
|
168
118
|
instance.scrollElement.removeEventListener('resize', onResize);
|
|
169
119
|
};
|
|
170
120
|
};
|
|
171
|
-
const
|
|
172
|
-
|
|
121
|
+
const scrollProps = {
|
|
122
|
+
element: ['scrollLeft', 'scrollTop'],
|
|
123
|
+
window: ['scrollX', 'scrollY']
|
|
124
|
+
};
|
|
173
125
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
126
|
+
const createOffsetObserver = mode => {
|
|
127
|
+
return (instance, cb) => {
|
|
128
|
+
if (!instance.scrollElement) {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
177
131
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
});
|
|
183
|
-
return () => {
|
|
184
|
-
instance.scrollElement.removeEventListener('scroll', onScroll);
|
|
185
|
-
};
|
|
186
|
-
};
|
|
187
|
-
const observeWindowOffset = (instance, cb) => {
|
|
188
|
-
const onScroll = () => cb(instance.scrollElement[instance.options.horizontal ? 'scrollX' : 'scrollY']);
|
|
132
|
+
const propX = scrollProps[mode][0];
|
|
133
|
+
const propY = scrollProps[mode][1];
|
|
134
|
+
let prevX = instance.scrollElement[propX];
|
|
135
|
+
let prevY = instance.scrollElement[propY];
|
|
189
136
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
137
|
+
const scroll = () => {
|
|
138
|
+
const offset = instance.scrollElement[instance.options.horizontal ? propX : propY];
|
|
139
|
+
cb(Math.max(0, offset - instance.options.scrollMargin));
|
|
140
|
+
};
|
|
193
141
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
142
|
+
scroll();
|
|
143
|
+
|
|
144
|
+
const onScroll = e => {
|
|
145
|
+
const target = e.currentTarget;
|
|
146
|
+
const scrollX = target[propX];
|
|
147
|
+
const scrollY = target[propY];
|
|
148
|
+
|
|
149
|
+
if (instance.options.horizontal ? prevX - scrollX : prevY - scrollY) {
|
|
150
|
+
scroll();
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
prevX = scrollX;
|
|
154
|
+
prevY = scrollY;
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
instance.scrollElement.addEventListener('scroll', onScroll, {
|
|
158
|
+
capture: false,
|
|
159
|
+
passive: true
|
|
160
|
+
});
|
|
161
|
+
return () => {
|
|
162
|
+
instance.scrollElement.removeEventListener('scroll', onScroll);
|
|
163
|
+
};
|
|
201
164
|
};
|
|
202
165
|
};
|
|
166
|
+
|
|
167
|
+
const observeElementOffset = createOffsetObserver('element');
|
|
168
|
+
const observeWindowOffset = createOffsetObserver('window');
|
|
203
169
|
const measureElement = (element, instance) => {
|
|
204
|
-
return element.getBoundingClientRect()[instance.options.horizontal ? 'width' : 'height'];
|
|
170
|
+
return Math.round(element.getBoundingClientRect()[instance.options.horizontal ? 'width' : 'height']);
|
|
205
171
|
};
|
|
206
|
-
const windowScroll = (offset,
|
|
172
|
+
const windowScroll = (offset, _ref, instance) => {
|
|
207
173
|
var _instance$scrollEleme;
|
|
208
|
-
|
|
209
|
-
|
|
174
|
+
|
|
175
|
+
let {
|
|
176
|
+
canSmooth,
|
|
177
|
+
sync
|
|
178
|
+
} = _ref;
|
|
179
|
+
const toOffset = sync ? offset : offset + instance.options.scrollMargin;
|
|
180
|
+
(_instance$scrollEleme = instance.scrollElement) == null ? void 0 : _instance$scrollEleme.scrollTo == null ? void 0 : _instance$scrollEleme.scrollTo({
|
|
181
|
+
[instance.options.horizontal ? 'left' : 'top']: toOffset,
|
|
210
182
|
behavior: canSmooth ? 'smooth' : undefined
|
|
211
183
|
});
|
|
212
184
|
};
|
|
213
|
-
const elementScroll = (offset,
|
|
185
|
+
const elementScroll = (offset, _ref2, instance) => {
|
|
214
186
|
var _instance$scrollEleme2;
|
|
215
|
-
|
|
216
|
-
|
|
187
|
+
|
|
188
|
+
let {
|
|
189
|
+
canSmooth,
|
|
190
|
+
sync
|
|
191
|
+
} = _ref2;
|
|
192
|
+
const toOffset = sync ? offset : offset + instance.options.scrollMargin;
|
|
193
|
+
(_instance$scrollEleme2 = instance.scrollElement) == null ? void 0 : _instance$scrollEleme2.scrollTo == null ? void 0 : _instance$scrollEleme2.scrollTo({
|
|
194
|
+
[instance.options.horizontal ? 'left' : 'top']: toOffset,
|
|
217
195
|
behavior: canSmooth ? 'smooth' : undefined
|
|
218
196
|
});
|
|
219
197
|
};
|
|
@@ -223,13 +201,26 @@ class Virtualizer {
|
|
|
223
201
|
|
|
224
202
|
this.unsubs = [];
|
|
225
203
|
this.scrollElement = null;
|
|
204
|
+
this.isScrolling = false;
|
|
205
|
+
this.isScrollingTimeoutId = null;
|
|
226
206
|
this.measurementsCache = [];
|
|
227
207
|
this.itemMeasurementsCache = {};
|
|
228
208
|
this.pendingMeasuredCacheIndexes = [];
|
|
209
|
+
this.scrollDelta = 0;
|
|
210
|
+
this.measureElementCache = {};
|
|
211
|
+
this.ro = new ResizeObserver(entries => {
|
|
212
|
+
entries.forEach(entry => {
|
|
213
|
+
this._measureElement(entry.target, false);
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
this.range = {
|
|
217
|
+
startIndex: 0,
|
|
218
|
+
endIndex: 0
|
|
219
|
+
};
|
|
229
220
|
|
|
230
221
|
this.setOptions = opts => {
|
|
231
|
-
Object.entries(opts).forEach(
|
|
232
|
-
let [key, value] =
|
|
222
|
+
Object.entries(opts).forEach(_ref3 => {
|
|
223
|
+
let [key, value] = _ref3;
|
|
233
224
|
if (typeof value === 'undefined') delete opts[key];
|
|
234
225
|
});
|
|
235
226
|
this.options = {
|
|
@@ -250,6 +241,9 @@ class Virtualizer {
|
|
|
250
241
|
width: 0,
|
|
251
242
|
height: 0
|
|
252
243
|
},
|
|
244
|
+
scrollMargin: 0,
|
|
245
|
+
scrollingDelay: 150,
|
|
246
|
+
indexAttribute: 'data-index',
|
|
253
247
|
...opts
|
|
254
248
|
};
|
|
255
249
|
};
|
|
@@ -263,10 +257,13 @@ class Virtualizer {
|
|
|
263
257
|
this.cleanup = () => {
|
|
264
258
|
this.unsubs.filter(Boolean).forEach(d => d());
|
|
265
259
|
this.unsubs = [];
|
|
260
|
+
this.scrollElement = null;
|
|
266
261
|
};
|
|
267
262
|
|
|
268
263
|
this._didMount = () => {
|
|
269
264
|
return () => {
|
|
265
|
+
this.ro.disconnect();
|
|
266
|
+
this.measureElementCache = {};
|
|
270
267
|
this.cleanup();
|
|
271
268
|
};
|
|
272
269
|
};
|
|
@@ -277,14 +274,41 @@ class Virtualizer {
|
|
|
277
274
|
if (this.scrollElement !== scrollElement) {
|
|
278
275
|
this.cleanup();
|
|
279
276
|
this.scrollElement = scrollElement;
|
|
277
|
+
|
|
278
|
+
this._scrollToOffset(this.scrollOffset, {
|
|
279
|
+
canSmooth: false,
|
|
280
|
+
sync: true,
|
|
281
|
+
requested: false
|
|
282
|
+
});
|
|
283
|
+
|
|
280
284
|
this.unsubs.push(this.options.observeElementRect(this, rect => {
|
|
281
285
|
this.scrollRect = rect;
|
|
282
|
-
this.
|
|
286
|
+
this.calculateRange();
|
|
283
287
|
}));
|
|
284
288
|
this.unsubs.push(this.options.observeElementOffset(this, offset => {
|
|
285
|
-
this.
|
|
286
|
-
|
|
289
|
+
if (this.isScrollingTimeoutId !== null) {
|
|
290
|
+
clearTimeout(this.isScrollingTimeoutId);
|
|
291
|
+
this.isScrollingTimeoutId = null;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
if (this.scrollOffset !== offset) {
|
|
295
|
+
this.scrollOffset = offset;
|
|
296
|
+
this.isScrolling = true;
|
|
297
|
+
this.scrollDelta = 0;
|
|
298
|
+
this.isScrollingTimeoutId = setTimeout(() => {
|
|
299
|
+
this.isScrollingTimeoutId = null;
|
|
300
|
+
this.isScrolling = false;
|
|
301
|
+
this.notify();
|
|
302
|
+
}, this.options.scrollingDelay);
|
|
303
|
+
} else {
|
|
304
|
+
this.isScrolling = false;
|
|
305
|
+
this.scrollDelta = 0;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
this.calculateRange();
|
|
287
309
|
}));
|
|
310
|
+
} else if (!this.isScrolling) {
|
|
311
|
+
this.calculateRange();
|
|
288
312
|
}
|
|
289
313
|
};
|
|
290
314
|
|
|
@@ -315,108 +339,170 @@ class Virtualizer {
|
|
|
315
339
|
this.measurementsCache = measurements;
|
|
316
340
|
return measurements;
|
|
317
341
|
}, {
|
|
318
|
-
key: process.env.NODE_ENV
|
|
342
|
+
key: process.env.NODE_ENV !== 'production' && 'getMeasurements',
|
|
319
343
|
debug: () => this.options.debug
|
|
320
344
|
});
|
|
321
345
|
this.calculateRange = memo(() => [this.getMeasurements(), this.getSize(), this.scrollOffset], (measurements, outerSize, scrollOffset) => {
|
|
322
|
-
|
|
346
|
+
const range = calculateRange({
|
|
323
347
|
measurements,
|
|
324
348
|
outerSize,
|
|
325
349
|
scrollOffset
|
|
326
350
|
});
|
|
351
|
+
|
|
352
|
+
if (range.startIndex !== this.range.startIndex || range.endIndex !== this.range.endIndex) {
|
|
353
|
+
this.range = range;
|
|
354
|
+
this.notify();
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
return this.range;
|
|
327
358
|
}, {
|
|
328
|
-
key: process.env.NODE_ENV
|
|
359
|
+
key: process.env.NODE_ENV !== 'production' && 'calculateRange',
|
|
329
360
|
debug: () => this.options.debug
|
|
330
361
|
});
|
|
331
|
-
this.getIndexes = memo(() => [this.options.rangeExtractor, this.
|
|
362
|
+
this.getIndexes = memo(() => [this.options.rangeExtractor, this.range, this.options.overscan, this.options.count], (rangeExtractor, range, overscan, count) => {
|
|
332
363
|
return rangeExtractor({ ...range,
|
|
333
364
|
overscan,
|
|
334
365
|
count: count
|
|
335
366
|
});
|
|
336
367
|
}, {
|
|
337
|
-
key: process.env.NODE_ENV
|
|
368
|
+
key: process.env.NODE_ENV !== 'production' && 'getIndexes',
|
|
369
|
+
debug: () => this.options.debug
|
|
338
370
|
});
|
|
339
|
-
|
|
371
|
+
|
|
372
|
+
this.indexFromElement = node => {
|
|
373
|
+
const attributeName = this.options.indexAttribute;
|
|
374
|
+
const indexStr = node.getAttribute(attributeName);
|
|
375
|
+
|
|
376
|
+
if (!indexStr) {
|
|
377
|
+
console.warn("Missing attribute name '" + attributeName + "={index}' on measured element.");
|
|
378
|
+
return -1;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
return parseInt(indexStr, 10);
|
|
382
|
+
};
|
|
383
|
+
|
|
384
|
+
this._measureElement = (node, _sync) => {
|
|
385
|
+
var _this$itemMeasurement;
|
|
386
|
+
|
|
387
|
+
const index = this.indexFromElement(node);
|
|
388
|
+
const item = this.measurementsCache[index];
|
|
389
|
+
|
|
390
|
+
if (!item) {
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
const key = String(item.key);
|
|
395
|
+
const prevNode = this.measureElementCache[key];
|
|
396
|
+
|
|
397
|
+
if (!node.isConnected) {
|
|
398
|
+
if (prevNode) {
|
|
399
|
+
this.ro.unobserve(prevNode);
|
|
400
|
+
delete this.measureElementCache[key];
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
if (!prevNode || prevNode !== node) {
|
|
407
|
+
if (prevNode) {
|
|
408
|
+
this.ro.unobserve(prevNode);
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
this.measureElementCache[key] = node;
|
|
412
|
+
this.ro.observe(node);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
const measuredItemSize = this.options.measureElement(node, this);
|
|
416
|
+
const itemSize = (_this$itemMeasurement = this.itemMeasurementsCache[item.key]) != null ? _this$itemMeasurement : item.size;
|
|
417
|
+
|
|
418
|
+
if (measuredItemSize !== itemSize) {
|
|
419
|
+
if (item.start < this.scrollOffset) {
|
|
420
|
+
if (process.env.NODE_ENV !== 'production' && this.options.debug) {
|
|
421
|
+
console.info('correction', measuredItemSize - itemSize);
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
if (this.destinationOffset === undefined) {
|
|
425
|
+
this.scrollDelta += measuredItemSize - itemSize;
|
|
426
|
+
|
|
427
|
+
this._scrollToOffset(this.scrollOffset + this.scrollDelta, {
|
|
428
|
+
canSmooth: false,
|
|
429
|
+
sync: false,
|
|
430
|
+
requested: false
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
this.pendingMeasuredCacheIndexes.push(index);
|
|
436
|
+
this.itemMeasurementsCache = { ...this.itemMeasurementsCache,
|
|
437
|
+
[item.key]: measuredItemSize
|
|
438
|
+
};
|
|
439
|
+
this.notify();
|
|
440
|
+
}
|
|
441
|
+
};
|
|
442
|
+
|
|
443
|
+
this.measureElement = node => {
|
|
444
|
+
if (!node) {
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
this._measureElement(node, true);
|
|
449
|
+
};
|
|
450
|
+
|
|
451
|
+
this.getVirtualItems = memo(() => [this.getIndexes(), this.getMeasurements()], (indexes, measurements) => {
|
|
340
452
|
const virtualItems = [];
|
|
341
453
|
|
|
342
454
|
for (let k = 0, len = indexes.length; k < len; k++) {
|
|
343
455
|
const i = indexes[k];
|
|
344
456
|
const measurement = measurements[i];
|
|
345
|
-
|
|
346
|
-
measureElement: measurableItem => {
|
|
347
|
-
if (measurableItem) {
|
|
348
|
-
const measuredItemSize = measureElement(measurableItem, this);
|
|
349
|
-
|
|
350
|
-
if (measuredItemSize !== item.size) {
|
|
351
|
-
if (item.start < this.scrollOffset) {
|
|
352
|
-
if (process.env.NODE_ENV === 'development' && this.options.debug) console.info('correction', measuredItemSize - item.size);
|
|
353
|
-
|
|
354
|
-
if (!this.destinationOffset) {
|
|
355
|
-
this._scrollToOffset(this.scrollOffset + (measuredItemSize - item.size), false);
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
this.pendingMeasuredCacheIndexes.push(i);
|
|
360
|
-
this.itemMeasurementsCache = { ...this.itemMeasurementsCache,
|
|
361
|
-
[item.key]: measuredItemSize
|
|
362
|
-
};
|
|
363
|
-
this.notify();
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
};
|
|
368
|
-
virtualItems.push(item);
|
|
457
|
+
virtualItems.push(measurement);
|
|
369
458
|
}
|
|
370
459
|
|
|
371
460
|
return virtualItems;
|
|
372
461
|
}, {
|
|
373
|
-
key: process.env.NODE_ENV
|
|
462
|
+
key: process.env.NODE_ENV !== 'production' && 'getIndexes',
|
|
463
|
+
debug: () => this.options.debug
|
|
374
464
|
});
|
|
375
465
|
|
|
376
466
|
this.scrollToOffset = function (toOffset, _temp) {
|
|
377
467
|
let {
|
|
378
|
-
align
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
const attempt = () => {
|
|
384
|
-
const offset = _this.scrollOffset;
|
|
468
|
+
align = 'start',
|
|
469
|
+
smoothScroll = _this.options.enableSmoothScroll
|
|
470
|
+
} = _temp === void 0 ? {} : _temp;
|
|
471
|
+
const offset = _this.scrollOffset;
|
|
385
472
|
|
|
386
|
-
|
|
473
|
+
const size = _this.getSize();
|
|
387
474
|
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
}
|
|
475
|
+
if (align === 'auto') {
|
|
476
|
+
if (toOffset <= offset) {
|
|
477
|
+
align = 'start';
|
|
478
|
+
} else if (toOffset >= offset + size) {
|
|
479
|
+
align = 'end';
|
|
480
|
+
} else {
|
|
481
|
+
align = 'start';
|
|
396
482
|
}
|
|
483
|
+
}
|
|
397
484
|
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
} else if (align === 'center') {
|
|
403
|
-
_this._scrollToOffset(toOffset - size / 2, true);
|
|
404
|
-
}
|
|
485
|
+
const options = {
|
|
486
|
+
canSmooth: smoothScroll,
|
|
487
|
+
sync: false,
|
|
488
|
+
requested: true
|
|
405
489
|
};
|
|
406
490
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
491
|
+
if (align === 'start') {
|
|
492
|
+
_this._scrollToOffset(toOffset, options);
|
|
493
|
+
} else if (align === 'end') {
|
|
494
|
+
_this._scrollToOffset(toOffset - size, options);
|
|
495
|
+
} else if (align === 'center') {
|
|
496
|
+
_this._scrollToOffset(toOffset - size / 2, options);
|
|
497
|
+
}
|
|
411
498
|
};
|
|
412
499
|
|
|
413
500
|
this.scrollToIndex = function (index, _temp2) {
|
|
414
501
|
let {
|
|
415
|
-
align,
|
|
502
|
+
align = 'auto',
|
|
503
|
+
smoothScroll = _this.options.enableSmoothScroll,
|
|
416
504
|
...rest
|
|
417
|
-
} = _temp2 === void 0 ? {
|
|
418
|
-
align: 'auto'
|
|
419
|
-
} : _temp2;
|
|
505
|
+
} = _temp2 === void 0 ? {} : _temp2;
|
|
420
506
|
|
|
421
507
|
const measurements = _this.getMeasurements();
|
|
422
508
|
|
|
@@ -447,6 +533,7 @@ class Virtualizer {
|
|
|
447
533
|
|
|
448
534
|
_this.scrollToOffset(toOffset, {
|
|
449
535
|
align,
|
|
536
|
+
smoothScroll,
|
|
450
537
|
...rest
|
|
451
538
|
});
|
|
452
539
|
};
|
|
@@ -457,10 +544,22 @@ class Virtualizer {
|
|
|
457
544
|
return (((_this$getMeasurements = this.getMeasurements()[this.options.count - 1]) == null ? void 0 : _this$getMeasurements.end) || this.options.paddingStart) + this.options.paddingEnd;
|
|
458
545
|
};
|
|
459
546
|
|
|
460
|
-
this._scrollToOffset = (offset,
|
|
547
|
+
this._scrollToOffset = (offset, _ref4) => {
|
|
548
|
+
let {
|
|
549
|
+
requested,
|
|
550
|
+
canSmooth,
|
|
551
|
+
sync
|
|
552
|
+
} = _ref4;
|
|
461
553
|
clearTimeout(this.scrollCheckFrame);
|
|
462
|
-
|
|
463
|
-
|
|
554
|
+
|
|
555
|
+
if (requested) {
|
|
556
|
+
this.destinationOffset = offset;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
this.options.scrollToFn(offset, {
|
|
560
|
+
canSmooth,
|
|
561
|
+
sync
|
|
562
|
+
}, this);
|
|
464
563
|
let scrollCheckFrame;
|
|
465
564
|
|
|
466
565
|
const check = () => {
|
|
@@ -491,6 +590,7 @@ class Virtualizer {
|
|
|
491
590
|
this.setOptions(_opts);
|
|
492
591
|
this.scrollRect = this.options.initialRect;
|
|
493
592
|
this.scrollOffset = this.options.initialOffset;
|
|
593
|
+
this.calculateRange();
|
|
494
594
|
}
|
|
495
595
|
|
|
496
596
|
}
|
|
@@ -516,12 +616,12 @@ const findNearestBinarySearch = (low, high, getCurrentValue, value) => {
|
|
|
516
616
|
}
|
|
517
617
|
};
|
|
518
618
|
|
|
519
|
-
function calculateRange(
|
|
619
|
+
function calculateRange(_ref5) {
|
|
520
620
|
let {
|
|
521
621
|
measurements,
|
|
522
622
|
outerSize,
|
|
523
623
|
scrollOffset
|
|
524
|
-
} =
|
|
624
|
+
} = _ref5;
|
|
525
625
|
const count = measurements.length - 1;
|
|
526
626
|
|
|
527
627
|
const getOffset = index => measurements[index].start;
|