@tanstack/virtual-core 3.0.0-beta.30 → 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.
@@ -14,37 +14,51 @@
14
14
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.VirtualCore = {}));
15
15
  })(this, (function (exports) { 'use strict';
16
16
 
17
+ function _extends() {
18
+ _extends = Object.assign ? Object.assign.bind() : function (target) {
19
+ for (var i = 1; i < arguments.length; i++) {
20
+ var source = arguments[i];
21
+ for (var key in source) {
22
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
23
+ target[key] = source[key];
24
+ }
25
+ }
26
+ }
27
+ return target;
28
+ };
29
+ return _extends.apply(this, arguments);
30
+ }
31
+
17
32
  function memo(getDeps, fn, opts) {
18
- let deps = [];
19
- let result;
20
- return () => {
21
- let depTime;
33
+ var deps = [];
34
+ var result;
35
+ return function () {
36
+ var depTime;
22
37
  if (opts.key && opts.debug != null && opts.debug()) depTime = Date.now();
23
- const newDeps = getDeps();
24
- const depsChanged = newDeps.length !== deps.length || newDeps.some((dep, index) => deps[index] !== dep);
38
+ var newDeps = getDeps();
39
+ var depsChanged = newDeps.length !== deps.length || newDeps.some(function (dep, index) {
40
+ return deps[index] !== dep;
41
+ });
25
42
  if (!depsChanged) {
26
43
  return result;
27
44
  }
28
45
  deps = newDeps;
29
- let resultTime;
46
+ var resultTime;
30
47
  if (opts.key && opts.debug != null && opts.debug()) resultTime = Date.now();
31
- result = fn(...newDeps);
48
+ result = fn.apply(void 0, newDeps);
32
49
  opts == null ? void 0 : opts.onChange == null ? void 0 : opts.onChange(result);
33
50
  if (opts.key && opts.debug != null && opts.debug()) {
34
- const depEndTime = Math.round((Date.now() - depTime) * 100) / 100;
35
- const resultEndTime = Math.round((Date.now() - resultTime) * 100) / 100;
36
- const resultFpsPercentage = resultEndTime / 16;
37
- const pad = (str, num) => {
51
+ var depEndTime = Math.round((Date.now() - depTime) * 100) / 100;
52
+ var resultEndTime = Math.round((Date.now() - resultTime) * 100) / 100;
53
+ var resultFpsPercentage = resultEndTime / 16;
54
+ var pad = function pad(str, num) {
38
55
  str = String(str);
39
56
  while (str.length < num) {
40
57
  str = ' ' + str;
41
58
  }
42
59
  return str;
43
60
  };
44
- console.info(`%c ${pad(resultEndTime, 5)} /${pad(depEndTime, 5)} ms`, `
45
- font-size: .6rem;
46
- font-weight: bold;
47
- color: hsl(${Math.max(0, Math.min(120 - 120 * resultFpsPercentage, 120))}deg 100% 31%);`, opts == null ? void 0 : opts.key);
61
+ console.info("%c\u23F1 " + pad(resultEndTime, 5) + " /" + pad(depEndTime, 5) + " ms", "\n font-size: .6rem;\n font-weight: bold;\n color: hsl(" + Math.max(0, Math.min(120 - 120 * resultFpsPercentage, 120)) + "deg 100% 31%);", opts == null ? void 0 : opts.key);
48
62
  }
49
63
  return result;
50
64
  };
@@ -54,30 +68,32 @@
54
68
 
55
69
  //
56
70
 
57
- const defaultKeyExtractor = index => index;
58
- const defaultRangeExtractor = range => {
59
- const start = Math.max(range.startIndex - range.overscan, 0);
60
- const end = Math.min(range.endIndex + range.overscan, range.count - 1);
61
- const arr = [];
62
- for (let i = start; i <= end; i++) {
63
- arr.push(i);
71
+ var defaultKeyExtractor = function defaultKeyExtractor(index) {
72
+ return index;
73
+ };
74
+ var defaultRangeExtractor = function defaultRangeExtractor(range) {
75
+ var start = Math.max(range.startIndex - range.overscan, 0);
76
+ var end = Math.min(range.endIndex + range.overscan, range.count - 1);
77
+ var arr = [];
78
+ for (var _i = start; _i <= end; _i++) {
79
+ arr.push(_i);
64
80
  }
65
81
  return arr;
66
82
  };
67
- const memoRectCallback = (instance, cb) => {
68
- let prev = {
83
+ var memoRectCallback = function memoRectCallback(instance, cb) {
84
+ var prev = {
69
85
  height: -1,
70
86
  width: -1
71
87
  };
72
- return rect => {
88
+ return function (rect) {
73
89
  if (instance.options.horizontal ? rect.width !== prev.width : rect.height !== prev.height) {
74
90
  cb(rect);
75
91
  }
76
92
  prev = rect;
77
93
  };
78
94
  };
79
- const observeElementRect = (instance, cb) => {
80
- const observer = new ResizeObserver(entries => {
95
+ var observeElementRect = function observeElementRect(instance, cb) {
96
+ var observer = new ResizeObserver(function (entries) {
81
97
  var _entries$, _entries$2;
82
98
  cb({
83
99
  width: (_entries$ = entries[0]) == null ? void 0 : _entries$.contentRect.width,
@@ -89,16 +105,18 @@
89
105
  }
90
106
  cb(instance.scrollElement.getBoundingClientRect());
91
107
  observer.observe(instance.scrollElement);
92
- return () => {
108
+ return function () {
93
109
  observer.unobserve(instance.scrollElement);
94
110
  };
95
111
  };
96
- const observeWindowRect = (instance, cb) => {
97
- const memoizedCallback = memoRectCallback(instance, cb);
98
- const onResize = () => memoizedCallback({
99
- width: instance.scrollElement.innerWidth,
100
- height: instance.scrollElement.innerHeight
101
- });
112
+ var observeWindowRect = function observeWindowRect(instance, cb) {
113
+ var memoizedCallback = memoRectCallback(instance, cb);
114
+ var onResize = function onResize() {
115
+ return memoizedCallback({
116
+ width: instance.scrollElement.innerWidth,
117
+ height: instance.scrollElement.innerHeight
118
+ });
119
+ };
102
120
  if (!instance.scrollElement) {
103
121
  return;
104
122
  }
@@ -107,32 +125,32 @@
107
125
  capture: false,
108
126
  passive: true
109
127
  });
110
- return () => {
128
+ return function () {
111
129
  instance.scrollElement.removeEventListener('resize', onResize);
112
130
  };
113
131
  };
114
- const scrollProps = {
132
+ var scrollProps = {
115
133
  element: ['scrollLeft', 'scrollTop'],
116
134
  window: ['scrollX', 'scrollY']
117
135
  };
118
- const createOffsetObserver = mode => {
119
- return (instance, cb) => {
136
+ var createOffsetObserver = function createOffsetObserver(mode) {
137
+ return function (instance, cb) {
120
138
  if (!instance.scrollElement) {
121
139
  return;
122
140
  }
123
- const propX = scrollProps[mode][0];
124
- const propY = scrollProps[mode][1];
125
- let prevX = instance.scrollElement[propX];
126
- let prevY = instance.scrollElement[propY];
127
- const scroll = () => {
128
- const offset = instance.scrollElement[instance.options.horizontal ? propX : propY];
141
+ var propX = scrollProps[mode][0];
142
+ var propY = scrollProps[mode][1];
143
+ var prevX = instance.scrollElement[propX];
144
+ var prevY = instance.scrollElement[propY];
145
+ var scroll = function scroll() {
146
+ var offset = instance.scrollElement[instance.options.horizontal ? propX : propY];
129
147
  cb(Math.max(0, offset - instance.options.scrollMargin));
130
148
  };
131
149
  scroll();
132
- const onScroll = e => {
133
- const target = e.currentTarget;
134
- const scrollX = target[propX];
135
- const scrollY = target[propY];
150
+ var onScroll = function onScroll(e) {
151
+ var target = e.currentTarget;
152
+ var scrollX = target[propX];
153
+ var scrollY = target[propY];
136
154
  if (instance.options.horizontal ? prevX - scrollX : prevY - scrollY) {
137
155
  scroll();
138
156
  }
@@ -143,390 +161,404 @@
143
161
  capture: false,
144
162
  passive: true
145
163
  });
146
- return () => {
164
+ return function () {
147
165
  instance.scrollElement.removeEventListener('scroll', onScroll);
148
166
  };
149
167
  };
150
168
  };
151
- const observeElementOffset = createOffsetObserver('element');
152
- const observeWindowOffset = createOffsetObserver('window');
153
- const measureElement = (element, instance) => {
169
+ var observeElementOffset = createOffsetObserver('element');
170
+ var observeWindowOffset = createOffsetObserver('window');
171
+ var measureElement = function measureElement(element, instance) {
154
172
  return Math.round(element.getBoundingClientRect()[instance.options.horizontal ? 'width' : 'height']);
155
173
  };
156
- const windowScroll = (offset, _ref, instance) => {
157
- var _instance$scrollEleme;
158
- let {
159
- adjustments,
160
- behavior,
161
- sync
162
- } = _ref;
163
- const toOffset = (sync ? offset : offset + instance.options.scrollMargin) + (adjustments ?? 0);
164
- (_instance$scrollEleme = instance.scrollElement) == null ? void 0 : _instance$scrollEleme.scrollTo == null ? void 0 : _instance$scrollEleme.scrollTo({
165
- [instance.options.horizontal ? 'left' : 'top']: toOffset,
166
- behavior
167
- });
174
+ var windowScroll = function windowScroll(offset, _ref, instance) {
175
+ var _instance$scrollEleme, _instance$scrollEleme2;
176
+ var adjustments = _ref.adjustments,
177
+ behavior = _ref.behavior,
178
+ sync = _ref.sync;
179
+ var toOffset = (sync ? offset : offset + instance.options.scrollMargin) + (adjustments != null ? adjustments : 0);
180
+ (_instance$scrollEleme = instance.scrollElement) == null ? void 0 : _instance$scrollEleme.scrollTo == null ? void 0 : _instance$scrollEleme.scrollTo((_instance$scrollEleme2 = {}, _instance$scrollEleme2[instance.options.horizontal ? 'left' : 'top'] = toOffset, _instance$scrollEleme2.behavior = behavior, _instance$scrollEleme2));
168
181
  };
169
- const elementScroll = (offset, _ref2, instance) => {
170
- var _instance$scrollEleme2;
171
- let {
172
- adjustments,
173
- behavior,
174
- sync
175
- } = _ref2;
176
- const toOffset = (sync ? offset : offset + instance.options.scrollMargin) + (adjustments ?? 0);
177
- (_instance$scrollEleme2 = instance.scrollElement) == null ? void 0 : _instance$scrollEleme2.scrollTo == null ? void 0 : _instance$scrollEleme2.scrollTo({
178
- [instance.options.horizontal ? 'left' : 'top']: toOffset,
179
- behavior
180
- });
182
+ var elementScroll = function elementScroll(offset, _ref2, instance) {
183
+ var _instance$scrollEleme3, _instance$scrollEleme4;
184
+ var adjustments = _ref2.adjustments,
185
+ behavior = _ref2.behavior,
186
+ sync = _ref2.sync;
187
+ var toOffset = (sync ? offset : offset + instance.options.scrollMargin) + (adjustments != null ? adjustments : 0);
188
+ (_instance$scrollEleme3 = instance.scrollElement) == null ? void 0 : _instance$scrollEleme3.scrollTo == null ? void 0 : _instance$scrollEleme3.scrollTo((_instance$scrollEleme4 = {}, _instance$scrollEleme4[instance.options.horizontal ? 'left' : 'top'] = toOffset, _instance$scrollEleme4.behavior = behavior, _instance$scrollEleme4));
181
189
  };
182
- class Virtualizer {
183
- constructor(_opts) {
184
- var _this = this;
185
- this.unsubs = [];
186
- this.scrollElement = null;
187
- this.isScrolling = false;
188
- this.isScrollingTimeoutId = null;
189
- this.measurementsCache = [];
190
- this.itemMeasurementsCache = {};
191
- this.pendingMeasuredCacheIndexes = [];
192
- this.scrollAdjustments = 0;
193
- this.measureElementCache = {};
194
- this.pendingScrollToIndexCallback = null;
195
- this.getResizeObserver = (() => {
196
- let _ro = null;
197
- return () => {
198
- if (_ro) {
199
- return _ro;
200
- } else if (typeof ResizeObserver !== 'undefined') {
201
- return _ro = new ResizeObserver(entries => {
202
- entries.forEach(entry => {
203
- this._measureElement(entry.target, false);
204
- });
190
+ var Virtualizer = function Virtualizer(_opts) {
191
+ var _this = this;
192
+ this.unsubs = [];
193
+ this.scrollElement = null;
194
+ this.isScrolling = false;
195
+ this.isScrollingTimeoutId = null;
196
+ this.measurementsCache = [];
197
+ this.itemMeasurementsCache = {};
198
+ this.pendingMeasuredCacheIndexes = [];
199
+ this.scrollAdjustments = 0;
200
+ this.measureElementCache = {};
201
+ this.pendingScrollToIndexCallback = null;
202
+ this.getResizeObserver = function () {
203
+ var _ro = null;
204
+ return function () {
205
+ if (_ro) {
206
+ return _ro;
207
+ } else if (typeof ResizeObserver !== 'undefined') {
208
+ return _ro = new ResizeObserver(function (entries) {
209
+ entries.forEach(function (entry) {
210
+ _this._measureElement(entry.target, false);
205
211
  });
206
- } else {
207
- return null;
208
- }
209
- };
210
- })();
211
- this.range = {
212
- startIndex: 0,
213
- endIndex: 0
214
- };
215
- this.setOptions = opts => {
216
- Object.entries(opts).forEach(_ref3 => {
217
- let [key, value] = _ref3;
218
- if (typeof value === 'undefined') delete opts[key];
219
- });
220
- this.options = {
221
- debug: false,
222
- initialOffset: 0,
223
- overscan: 1,
224
- paddingStart: 0,
225
- paddingEnd: 0,
226
- scrollPaddingStart: 0,
227
- scrollPaddingEnd: 0,
228
- horizontal: false,
229
- getItemKey: defaultKeyExtractor,
230
- rangeExtractor: defaultRangeExtractor,
231
- onChange: () => {},
232
- measureElement,
233
- initialRect: {
234
- width: 0,
235
- height: 0
236
- },
237
- scrollMargin: 0,
238
- scrollingDelay: 150,
239
- indexAttribute: 'data-index',
240
- ...opts
241
- };
242
- };
243
- this.notify = () => {
244
- var _this$options$onChang, _this$options;
245
- (_this$options$onChang = (_this$options = this.options).onChange) == null ? void 0 : _this$options$onChang.call(_this$options, this);
246
- };
247
- this.cleanup = () => {
248
- this.unsubs.filter(Boolean).forEach(d => d());
249
- this.unsubs = [];
250
- this.scrollElement = null;
251
- };
252
- this._didMount = () => {
253
- const ro = this.getResizeObserver();
254
- Object.values(this.measureElementCache).forEach(node => ro == null ? void 0 : ro.observe(node));
255
- return () => {
256
- ro == null ? void 0 : ro.disconnect();
257
- this.cleanup();
258
- };
259
- };
260
- this._willUpdate = () => {
261
- var _this$pendingScrollTo;
262
- (_this$pendingScrollTo = this.pendingScrollToIndexCallback) == null ? void 0 : _this$pendingScrollTo.call(this);
263
- const scrollElement = this.options.getScrollElement();
264
- if (this.scrollElement !== scrollElement) {
265
- this.cleanup();
266
- this.scrollElement = scrollElement;
267
- this._scrollToOffset(this.scrollOffset, {
268
- adjustments: undefined,
269
- behavior: undefined,
270
- sync: true
271
212
  });
272
- this.unsubs.push(this.options.observeElementRect(this, rect => {
273
- this.scrollRect = rect;
274
- this.calculateRange();
275
- }));
276
- this.unsubs.push(this.options.observeElementOffset(this, offset => {
277
- if (this.isScrollingTimeoutId !== null) {
278
- clearTimeout(this.isScrollingTimeoutId);
279
- this.isScrollingTimeoutId = null;
280
- }
281
- const onIsScrollingChange = isScrolling => {
282
- if (this.isScrolling !== isScrolling) {
283
- this.isScrolling = isScrolling;
284
- this.notify();
285
- }
286
- };
287
- this.scrollAdjustments = 0;
288
- if (this.scrollOffset !== offset) {
289
- this.scrollOffset = offset;
290
- onIsScrollingChange(true);
291
- }
292
- this.calculateRange();
293
- this.isScrollingTimeoutId = setTimeout(() => {
294
- this.isScrollingTimeoutId = null;
295
- onIsScrollingChange(false);
296
- }, this.options.scrollingDelay);
297
- }));
298
- } else if (!this.isScrolling) {
299
- this.calculateRange();
213
+ } else {
214
+ return null;
300
215
  }
301
216
  };
302
- this.getSize = () => {
303
- return this.scrollRect[this.options.horizontal ? 'width' : 'height'];
304
- };
305
- this.getMeasurements = memo(() => [this.options.count, this.options.paddingStart, this.options.getItemKey, this.itemMeasurementsCache], (count, paddingStart, getItemKey, measurementsCache) => {
306
- const min = this.pendingMeasuredCacheIndexes.length > 0 ? Math.min(...this.pendingMeasuredCacheIndexes) : 0;
307
- this.pendingMeasuredCacheIndexes = [];
308
- const measurements = this.measurementsCache.slice(0, min);
309
- for (let i = min; i < count; i++) {
310
- const key = getItemKey(i);
311
- const measuredSize = measurementsCache[key];
312
- const start = measurements[i - 1] ? measurements[i - 1].end : paddingStart;
313
- const size = typeof measuredSize === 'number' ? measuredSize : this.options.estimateSize(i);
314
- const end = start + size;
315
- measurements[i] = {
316
- index: i,
317
- start,
318
- size,
319
- end,
320
- key
321
- };
322
- }
323
- this.measurementsCache = measurements;
324
- return measurements;
325
- }, {
326
- key: 'getMeasurements',
327
- debug: () => this.options.debug
217
+ }();
218
+ this.range = {
219
+ startIndex: 0,
220
+ endIndex: 0
221
+ };
222
+ this.setOptions = function (opts) {
223
+ Object.entries(opts).forEach(function (_ref3) {
224
+ var key = _ref3[0],
225
+ value = _ref3[1];
226
+ if (typeof value === 'undefined') delete opts[key];
328
227
  });
329
- this.calculateRange = memo(() => [this.getMeasurements(), this.getSize(), this.scrollOffset], (measurements, outerSize, scrollOffset) => {
330
- const range = calculateRange({
331
- measurements,
332
- outerSize,
333
- scrollOffset
334
- });
335
- if (range.startIndex !== this.range.startIndex || range.endIndex !== this.range.endIndex) {
336
- this.range = range;
337
- this.notify();
338
- }
339
- return this.range;
340
- }, {
341
- key: 'calculateRange',
342
- debug: () => this.options.debug
228
+ _this.options = _extends({
229
+ debug: false,
230
+ initialOffset: 0,
231
+ overscan: 1,
232
+ paddingStart: 0,
233
+ paddingEnd: 0,
234
+ scrollPaddingStart: 0,
235
+ scrollPaddingEnd: 0,
236
+ horizontal: false,
237
+ getItemKey: defaultKeyExtractor,
238
+ rangeExtractor: defaultRangeExtractor,
239
+ onChange: function onChange() {},
240
+ measureElement: measureElement,
241
+ initialRect: {
242
+ width: 0,
243
+ height: 0
244
+ },
245
+ scrollMargin: 0,
246
+ scrollingDelay: 150,
247
+ indexAttribute: 'data-index'
248
+ }, opts);
249
+ };
250
+ this.notify = function () {
251
+ _this.options.onChange == null ? void 0 : _this.options.onChange(_this);
252
+ };
253
+ this.cleanup = function () {
254
+ _this.unsubs.filter(Boolean).forEach(function (d) {
255
+ return d();
343
256
  });
344
- this.getIndexes = memo(() => [this.options.rangeExtractor, this.range, this.options.overscan, this.options.count], (rangeExtractor, range, overscan, count) => {
345
- return rangeExtractor({
346
- ...range,
347
- overscan,
348
- count: count
349
- });
350
- }, {
351
- key: 'getIndexes',
352
- debug: () => this.options.debug
257
+ _this.unsubs = [];
258
+ _this.scrollElement = null;
259
+ };
260
+ this._didMount = function () {
261
+ var ro = _this.getResizeObserver();
262
+ Object.values(_this.measureElementCache).forEach(function (node) {
263
+ return ro == null ? void 0 : ro.observe(node);
353
264
  });
354
- this.indexFromElement = node => {
355
- const attributeName = this.options.indexAttribute;
356
- const indexStr = node.getAttribute(attributeName);
357
- if (!indexStr) {
358
- console.warn(`Missing attribute name '${attributeName}={index}' on measured element.`);
359
- return -1;
360
- }
361
- return parseInt(indexStr, 10);
265
+ return function () {
266
+ ro == null ? void 0 : ro.disconnect();
267
+ _this.cleanup();
362
268
  };
363
- this._measureElement = (node, _sync) => {
364
- const index = this.indexFromElement(node);
365
- const item = this.measurementsCache[index];
366
- if (!item) {
367
- return;
368
- }
369
- const prevNode = this.measureElementCache[item.key];
370
- const ro = this.getResizeObserver();
371
- if (!node.isConnected) {
372
- if (prevNode) {
373
- ro == null ? void 0 : ro.unobserve(prevNode);
374
- delete this.measureElementCache[item.key];
375
- }
376
- return;
377
- }
378
- if (!prevNode || prevNode !== node) {
379
- if (prevNode) {
380
- ro == null ? void 0 : ro.unobserve(prevNode);
269
+ };
270
+ this._willUpdate = function () {
271
+ _this.pendingScrollToIndexCallback == null ? void 0 : _this.pendingScrollToIndexCallback();
272
+ var scrollElement = _this.options.getScrollElement();
273
+ if (_this.scrollElement !== scrollElement) {
274
+ _this.cleanup();
275
+ _this.scrollElement = scrollElement;
276
+ _this._scrollToOffset(_this.scrollOffset, {
277
+ adjustments: undefined,
278
+ behavior: undefined,
279
+ sync: true
280
+ });
281
+ _this.unsubs.push(_this.options.observeElementRect(_this, function (rect) {
282
+ _this.scrollRect = rect;
283
+ _this.calculateRange();
284
+ }));
285
+ _this.unsubs.push(_this.options.observeElementOffset(_this, function (offset) {
286
+ if (_this.isScrollingTimeoutId !== null) {
287
+ clearTimeout(_this.isScrollingTimeoutId);
288
+ _this.isScrollingTimeoutId = null;
381
289
  }
382
- this.measureElementCache[item.key] = node;
383
- ro == null ? void 0 : ro.observe(node);
384
- }
385
- const measuredItemSize = this.options.measureElement(node, this);
386
- const itemSize = this.itemMeasurementsCache[item.key] ?? item.size;
387
- const delta = measuredItemSize - itemSize;
388
- if (delta !== 0) {
389
- if (item.start < this.scrollOffset && this.isScrolling) {
390
- if (this.options.debug) {
391
- console.info('correction', delta);
290
+ var onIsScrollingChange = function onIsScrollingChange(isScrolling) {
291
+ if (_this.isScrolling !== isScrolling) {
292
+ _this.isScrolling = isScrolling;
293
+ _this.notify();
392
294
  }
393
- this._scrollToOffset(this.scrollOffset, {
394
- adjustments: this.scrollAdjustments += delta,
395
- behavior: undefined,
396
- sync: false
397
- });
398
- }
399
- this.pendingMeasuredCacheIndexes.push(index);
400
- this.itemMeasurementsCache = {
401
- ...this.itemMeasurementsCache,
402
- [item.key]: measuredItemSize
403
295
  };
404
- this.notify();
405
- }
406
- };
407
- this.measureElement = node => {
408
- if (!node) {
409
- return;
410
- }
411
- this._measureElement(node, true);
412
- };
413
- this.getVirtualItems = memo(() => [this.getIndexes(), this.getMeasurements()], (indexes, measurements) => {
414
- const virtualItems = [];
415
- for (let k = 0, len = indexes.length; k < len; k++) {
416
- const i = indexes[k];
417
- const measurement = measurements[i];
418
- virtualItems.push(measurement);
419
- }
420
- return virtualItems;
421
- }, {
422
- key: 'getIndexes',
423
- debug: () => this.options.debug
424
- });
425
- this.scrollToOffset = function (toOffset, _temp) {
426
- let {
427
- align = 'start',
428
- behavior
429
- } = _temp === void 0 ? {} : _temp;
430
- const offset = _this.scrollOffset;
431
- const size = _this.getSize();
432
- if (align === 'auto') {
433
- if (toOffset <= offset) {
434
- align = 'start';
435
- } else if (toOffset >= offset + size) {
436
- align = 'end';
437
- } else {
438
- align = 'start';
296
+ _this.scrollAdjustments = 0;
297
+ if (_this.scrollOffset !== offset) {
298
+ _this.scrollOffset = offset;
299
+ onIsScrollingChange(true);
439
300
  }
440
- }
441
- const options = {
442
- adjustments: undefined,
443
- behavior,
444
- sync: false
301
+ _this.calculateRange();
302
+ _this.isScrollingTimeoutId = setTimeout(function () {
303
+ _this.isScrollingTimeoutId = null;
304
+ onIsScrollingChange(false);
305
+ }, _this.options.scrollingDelay);
306
+ }));
307
+ } else if (!_this.isScrolling) {
308
+ _this.calculateRange();
309
+ }
310
+ };
311
+ this.getSize = function () {
312
+ return _this.scrollRect[_this.options.horizontal ? 'width' : 'height'];
313
+ };
314
+ this.getMeasurements = memo(function () {
315
+ return [_this.options.count, _this.options.paddingStart, _this.options.getItemKey, _this.itemMeasurementsCache];
316
+ }, function (count, paddingStart, getItemKey, measurementsCache) {
317
+ var min = _this.pendingMeasuredCacheIndexes.length > 0 ? Math.min.apply(Math, _this.pendingMeasuredCacheIndexes) : 0;
318
+ _this.pendingMeasuredCacheIndexes = [];
319
+ var measurements = _this.measurementsCache.slice(0, min);
320
+ for (var _i2 = min; _i2 < count; _i2++) {
321
+ var key = getItemKey(_i2);
322
+ var measuredSize = measurementsCache[key];
323
+ var start = measurements[_i2 - 1] ? measurements[_i2 - 1].end : paddingStart;
324
+ var size = typeof measuredSize === 'number' ? measuredSize : _this.options.estimateSize(_i2);
325
+ var end = start + size;
326
+ measurements[_i2] = {
327
+ index: _i2,
328
+ start: start,
329
+ size: size,
330
+ end: end,
331
+ key: key
445
332
  };
446
- if (align === 'start') {
447
- _this._scrollToOffset(toOffset, options);
448
- } else if (align === 'end') {
449
- _this._scrollToOffset(toOffset - size, options);
450
- } else if (align === 'center') {
451
- _this._scrollToOffset(toOffset - size / 2, options);
333
+ }
334
+ _this.measurementsCache = measurements;
335
+ return measurements;
336
+ }, {
337
+ key: 'getMeasurements',
338
+ debug: function debug() {
339
+ return _this.options.debug;
340
+ }
341
+ });
342
+ this.calculateRange = memo(function () {
343
+ return [_this.getMeasurements(), _this.getSize(), _this.scrollOffset];
344
+ }, function (measurements, outerSize, scrollOffset) {
345
+ var range = calculateRange({
346
+ measurements: measurements,
347
+ outerSize: outerSize,
348
+ scrollOffset: scrollOffset
349
+ });
350
+ if (range.startIndex !== _this.range.startIndex || range.endIndex !== _this.range.endIndex) {
351
+ _this.range = range;
352
+ _this.notify();
353
+ }
354
+ return _this.range;
355
+ }, {
356
+ key: 'calculateRange',
357
+ debug: function debug() {
358
+ return _this.options.debug;
359
+ }
360
+ });
361
+ this.getIndexes = memo(function () {
362
+ return [_this.options.rangeExtractor, _this.range, _this.options.overscan, _this.options.count];
363
+ }, function (rangeExtractor, range, overscan, count) {
364
+ return rangeExtractor(_extends({}, range, {
365
+ overscan: overscan,
366
+ count: count
367
+ }));
368
+ }, {
369
+ key: 'getIndexes',
370
+ debug: function debug() {
371
+ return _this.options.debug;
372
+ }
373
+ });
374
+ this.indexFromElement = function (node) {
375
+ var attributeName = _this.options.indexAttribute;
376
+ var indexStr = node.getAttribute(attributeName);
377
+ if (!indexStr) {
378
+ console.warn("Missing attribute name '" + attributeName + "={index}' on measured element.");
379
+ return -1;
380
+ }
381
+ return parseInt(indexStr, 10);
382
+ };
383
+ this._measureElement = function (node, _sync) {
384
+ var _this$itemMeasurement;
385
+ var index = _this.indexFromElement(node);
386
+ var item = _this.measurementsCache[index];
387
+ if (!item) {
388
+ return;
389
+ }
390
+ var prevNode = _this.measureElementCache[item.key];
391
+ var ro = _this.getResizeObserver();
392
+ if (!node.isConnected) {
393
+ if (prevNode) {
394
+ ro == null ? void 0 : ro.unobserve(prevNode);
395
+ delete _this.measureElementCache[item.key];
452
396
  }
453
- };
454
- this.scrollToIndex = function (index, _temp2) {
455
- let {
456
- align = 'auto',
457
- ...rest
458
- } = _temp2 === void 0 ? {} : _temp2;
459
- _this.pendingScrollToIndexCallback = null;
460
- const measurements = _this.getMeasurements();
461
- const offset = _this.scrollOffset;
462
- const size = _this.getSize();
463
- const {
464
- count
465
- } = _this.options;
466
- const measurement = measurements[Math.max(0, Math.min(index, count - 1))];
467
- if (!measurement) {
468
- return;
397
+ return;
398
+ }
399
+ if (!prevNode || prevNode !== node) {
400
+ if (prevNode) {
401
+ ro == null ? void 0 : ro.unobserve(prevNode);
469
402
  }
470
- if (align === 'auto') {
471
- if (measurement.end >= offset + size - _this.options.scrollPaddingEnd) {
472
- align = 'end';
473
- } else if (measurement.start <= offset + _this.options.scrollPaddingStart) {
474
- align = 'start';
475
- } else {
476
- return;
403
+ _this.measureElementCache[item.key] = node;
404
+ ro == null ? void 0 : ro.observe(node);
405
+ }
406
+ var measuredItemSize = _this.options.measureElement(node, _this);
407
+ var itemSize = (_this$itemMeasurement = _this.itemMeasurementsCache[item.key]) != null ? _this$itemMeasurement : item.size;
408
+ var delta = measuredItemSize - itemSize;
409
+ if (delta !== 0) {
410
+ var _extends2;
411
+ if (item.start < _this.scrollOffset && _this.isScrolling) {
412
+ if (_this.options.debug) {
413
+ console.info('correction', delta);
477
414
  }
415
+ _this._scrollToOffset(_this.scrollOffset, {
416
+ adjustments: _this.scrollAdjustments += delta,
417
+ behavior: undefined,
418
+ sync: false
419
+ });
478
420
  }
479
- const toOffset = align === 'end' ? measurement.end + _this.options.scrollPaddingEnd : measurement.start - _this.options.scrollPaddingStart;
480
- _this.scrollToOffset(toOffset, {
481
- align,
482
- ...rest
483
- });
484
- const isDynamic = Object.keys(_this.measureElementCache).length > 0;
485
- if (isDynamic) {
486
- const didSeen = () => typeof _this.itemMeasurementsCache[_this.options.getItemKey(index)] === 'number';
487
- if (!didSeen()) {
488
- _this.pendingScrollToIndexCallback = () => {
489
- if (didSeen()) {
490
- _this.pendingScrollToIndexCallback = null;
491
- _this.scrollToIndex(index, {
492
- align,
493
- ...rest
494
- });
495
- }
496
- };
497
- }
421
+ _this.pendingMeasuredCacheIndexes.push(index);
422
+ _this.itemMeasurementsCache = _extends({}, _this.itemMeasurementsCache, (_extends2 = {}, _extends2[item.key] = measuredItemSize, _extends2));
423
+ _this.notify();
424
+ }
425
+ };
426
+ this.measureElement = function (node) {
427
+ if (!node) {
428
+ return;
429
+ }
430
+ _this._measureElement(node, true);
431
+ };
432
+ this.getVirtualItems = memo(function () {
433
+ return [_this.getIndexes(), _this.getMeasurements()];
434
+ }, function (indexes, measurements) {
435
+ var virtualItems = [];
436
+ for (var k = 0, len = indexes.length; k < len; k++) {
437
+ var _i3 = indexes[k];
438
+ var measurement = measurements[_i3];
439
+ virtualItems.push(measurement);
440
+ }
441
+ return virtualItems;
442
+ }, {
443
+ key: 'getIndexes',
444
+ debug: function debug() {
445
+ return _this.options.debug;
446
+ }
447
+ });
448
+ this.getOffsetForAlignment = function (toOffset, align) {
449
+ var offset = _this.scrollOffset;
450
+ var size = _this.getSize();
451
+ if (align === 'auto') {
452
+ if (toOffset <= offset) {
453
+ align = 'start';
454
+ } else if (toOffset >= offset + size) {
455
+ align = 'end';
456
+ } else {
457
+ align = 'start';
498
458
  }
459
+ }
460
+ if (align === 'start') {
461
+ return toOffset;
462
+ } else if (align === 'end') {
463
+ return toOffset - size;
464
+ } else if (align === 'center') {
465
+ return toOffset - size / 2;
466
+ }
467
+ return toOffset;
468
+ };
469
+ this.scrollToOffset = function (toOffset, _temp) {
470
+ var _ref4 = _temp === void 0 ? {} : _temp,
471
+ _ref4$align = _ref4.align,
472
+ align = _ref4$align === void 0 ? 'start' : _ref4$align,
473
+ behavior = _ref4.behavior;
474
+ var options = {
475
+ adjustments: undefined,
476
+ behavior: behavior,
477
+ sync: false
499
478
  };
500
- this.getTotalSize = () => {
501
- var _this$getMeasurements;
502
- return (((_this$getMeasurements = this.getMeasurements()[this.options.count - 1]) == null ? void 0 : _this$getMeasurements.end) || this.options.paddingStart) + this.options.paddingEnd;
503
- };
504
- this._scrollToOffset = (offset, _ref4) => {
505
- let {
506
- adjustments,
507
- behavior,
508
- sync
509
- } = _ref4;
510
- this.options.scrollToFn(offset, {
511
- behavior,
512
- sync,
513
- adjustments
514
- }, this);
479
+ _this._scrollToOffset(_this.getOffsetForAlignment(toOffset, align), options);
480
+ };
481
+ this.scrollToIndex = function (index, _temp2) {
482
+ var _ref5 = _temp2 === void 0 ? {} : _temp2,
483
+ _ref5$align = _ref5.align,
484
+ align = _ref5$align === void 0 ? 'auto' : _ref5$align,
485
+ behavior = _ref5.behavior;
486
+ _this.pendingScrollToIndexCallback = null;
487
+ var offset = _this.scrollOffset;
488
+ var size = _this.getSize();
489
+ var count = _this.options.count;
490
+ var measurements = _this.getMeasurements();
491
+ var measurement = measurements[Math.max(0, Math.min(index, count - 1))];
492
+ if (!measurement) {
493
+ throw new Error("VirtualItem not found for index = " + index);
494
+ }
495
+ if (align === 'auto') {
496
+ if (measurement.end >= offset + size - _this.options.scrollPaddingEnd) {
497
+ align = 'end';
498
+ } else if (measurement.start <= offset + _this.options.scrollPaddingStart) {
499
+ align = 'start';
500
+ } else {
501
+ return;
502
+ }
503
+ }
504
+ var getOffsetForIndexAndAlignment = function getOffsetForIndexAndAlignment(measurement) {
505
+ var toOffset = align === 'end' ? measurement.end + _this.options.scrollPaddingEnd : measurement.start - _this.options.scrollPaddingStart;
506
+ return _this.getOffsetForAlignment(toOffset, align);
515
507
  };
516
- this.measure = () => {
517
- this.itemMeasurementsCache = {};
518
- this.notify();
508
+ var toOffset = getOffsetForIndexAndAlignment(measurement);
509
+ if (toOffset === offset) {
510
+ return;
511
+ }
512
+ var options = {
513
+ adjustments: undefined,
514
+ behavior: behavior,
515
+ sync: false
519
516
  };
520
- this.setOptions(_opts);
521
- this.scrollRect = this.options.initialRect;
522
- this.scrollOffset = this.options.initialOffset;
523
- this.calculateRange();
524
- }
525
- }
526
- const findNearestBinarySearch = (low, high, getCurrentValue, value) => {
517
+ _this._scrollToOffset(toOffset, options);
518
+ var isDynamic = Object.keys(_this.measureElementCache).length > 0;
519
+ if (isDynamic) {
520
+ _this.pendingScrollToIndexCallback = function () {
521
+ _this.scrollToIndex(index, {
522
+ align: align,
523
+ behavior: behavior
524
+ });
525
+ };
526
+ }
527
+ };
528
+ this.scrollBy = function (adjustments, options) {
529
+ _this._scrollToOffset(_this.scrollOffset, {
530
+ adjustments: adjustments,
531
+ behavior: options == null ? void 0 : options.behavior,
532
+ sync: false
533
+ });
534
+ };
535
+ this.getTotalSize = function () {
536
+ var _this$getMeasurements;
537
+ return (((_this$getMeasurements = _this.getMeasurements()[_this.options.count - 1]) == null ? void 0 : _this$getMeasurements.end) || _this.options.paddingStart) + _this.options.paddingEnd;
538
+ };
539
+ this._scrollToOffset = function (offset, _ref6) {
540
+ var adjustments = _ref6.adjustments,
541
+ behavior = _ref6.behavior,
542
+ sync = _ref6.sync;
543
+ _this.options.scrollToFn(offset, {
544
+ behavior: behavior,
545
+ sync: sync,
546
+ adjustments: adjustments
547
+ }, _this);
548
+ };
549
+ this.measure = function () {
550
+ _this.itemMeasurementsCache = {};
551
+ _this.notify();
552
+ };
553
+ this.setOptions(_opts);
554
+ this.scrollRect = this.options.initialRect;
555
+ this.scrollOffset = this.options.initialOffset;
556
+ this.calculateRange();
557
+ };
558
+ var findNearestBinarySearch = function findNearestBinarySearch(low, high, getCurrentValue, value) {
527
559
  while (low <= high) {
528
- const middle = (low + high) / 2 | 0;
529
- const currentValue = getCurrentValue(middle);
560
+ var middle = (low + high) / 2 | 0;
561
+ var currentValue = getCurrentValue(middle);
530
562
  if (currentValue < value) {
531
563
  low = middle + 1;
532
564
  } else if (currentValue > value) {
@@ -541,22 +573,22 @@
541
573
  return 0;
542
574
  }
543
575
  };
544
- function calculateRange(_ref5) {
545
- let {
546
- measurements,
547
- outerSize,
548
- scrollOffset
549
- } = _ref5;
550
- const count = measurements.length - 1;
551
- const getOffset = index => measurements[index].start;
552
- const startIndex = findNearestBinarySearch(0, count, getOffset, scrollOffset);
553
- let endIndex = startIndex;
576
+ function calculateRange(_ref7) {
577
+ var measurements = _ref7.measurements,
578
+ outerSize = _ref7.outerSize,
579
+ scrollOffset = _ref7.scrollOffset;
580
+ var count = measurements.length - 1;
581
+ var getOffset = function getOffset(index) {
582
+ return measurements[index].start;
583
+ };
584
+ var startIndex = findNearestBinarySearch(0, count, getOffset, scrollOffset);
585
+ var endIndex = startIndex;
554
586
  while (endIndex < count && measurements[endIndex].end < scrollOffset + outerSize) {
555
587
  endIndex++;
556
588
  }
557
589
  return {
558
- startIndex,
559
- endIndex
590
+ startIndex: startIndex,
591
+ endIndex: endIndex
560
592
  };
561
593
  }
562
594