@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.
@@ -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,388 +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
- if (this.scrollOffset !== offset) {
282
- this.scrollOffset = offset;
283
- this.isScrolling = true;
284
- this.scrollAdjustments = 0;
285
- this.isScrollingTimeoutId = setTimeout(() => {
286
- this.isScrollingTimeoutId = null;
287
- this.isScrolling = false;
288
- this.notify();
289
- }, this.options.scrollingDelay);
290
- } else {
291
- this.isScrolling = false;
292
- this.scrollAdjustments = 0;
293
- }
294
- this.calculateRange();
295
- }));
296
- } else if (!this.isScrolling) {
297
- this.calculateRange();
213
+ } else {
214
+ return null;
298
215
  }
299
216
  };
300
- this.getSize = () => {
301
- return this.scrollRect[this.options.horizontal ? 'width' : 'height'];
302
- };
303
- this.getMeasurements = memo(() => [this.options.count, this.options.paddingStart, this.options.getItemKey, this.itemMeasurementsCache], (count, paddingStart, getItemKey, measurementsCache) => {
304
- const min = this.pendingMeasuredCacheIndexes.length > 0 ? Math.min(...this.pendingMeasuredCacheIndexes) : 0;
305
- this.pendingMeasuredCacheIndexes = [];
306
- const measurements = this.measurementsCache.slice(0, min);
307
- for (let i = min; i < count; i++) {
308
- const key = getItemKey(i);
309
- const measuredSize = measurementsCache[key];
310
- const start = measurements[i - 1] ? measurements[i - 1].end : paddingStart;
311
- const size = typeof measuredSize === 'number' ? measuredSize : this.options.estimateSize(i);
312
- const end = start + size;
313
- measurements[i] = {
314
- index: i,
315
- start,
316
- size,
317
- end,
318
- key
319
- };
320
- }
321
- this.measurementsCache = measurements;
322
- return measurements;
323
- }, {
324
- key: 'getMeasurements',
325
- 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];
326
227
  });
327
- this.calculateRange = memo(() => [this.getMeasurements(), this.getSize(), this.scrollOffset], (measurements, outerSize, scrollOffset) => {
328
- const range = calculateRange({
329
- measurements,
330
- outerSize,
331
- scrollOffset
332
- });
333
- if (range.startIndex !== this.range.startIndex || range.endIndex !== this.range.endIndex) {
334
- this.range = range;
335
- this.notify();
336
- }
337
- return this.range;
338
- }, {
339
- key: 'calculateRange',
340
- 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();
341
256
  });
342
- this.getIndexes = memo(() => [this.options.rangeExtractor, this.range, this.options.overscan, this.options.count], (rangeExtractor, range, overscan, count) => {
343
- return rangeExtractor({
344
- ...range,
345
- overscan,
346
- count: count
347
- });
348
- }, {
349
- key: 'getIndexes',
350
- 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);
351
264
  });
352
- this.indexFromElement = node => {
353
- const attributeName = this.options.indexAttribute;
354
- const indexStr = node.getAttribute(attributeName);
355
- if (!indexStr) {
356
- console.warn(`Missing attribute name '${attributeName}={index}' on measured element.`);
357
- return -1;
358
- }
359
- return parseInt(indexStr, 10);
265
+ return function () {
266
+ ro == null ? void 0 : ro.disconnect();
267
+ _this.cleanup();
360
268
  };
361
- this._measureElement = (node, _sync) => {
362
- const index = this.indexFromElement(node);
363
- const item = this.measurementsCache[index];
364
- if (!item) {
365
- return;
366
- }
367
- const prevNode = this.measureElementCache[item.key];
368
- const ro = this.getResizeObserver();
369
- if (!node.isConnected) {
370
- if (prevNode) {
371
- ro == null ? void 0 : ro.unobserve(prevNode);
372
- delete this.measureElementCache[item.key];
373
- }
374
- return;
375
- }
376
- if (!prevNode || prevNode !== node) {
377
- if (prevNode) {
378
- 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;
379
289
  }
380
- this.measureElementCache[item.key] = node;
381
- ro == null ? void 0 : ro.observe(node);
382
- }
383
- const measuredItemSize = this.options.measureElement(node, this);
384
- const itemSize = this.itemMeasurementsCache[item.key] ?? item.size;
385
- const delta = measuredItemSize - itemSize;
386
- if (delta !== 0) {
387
- if (item.start < this.scrollOffset && this.isScrolling) {
388
- if (this.options.debug) {
389
- console.info('correction', delta);
290
+ var onIsScrollingChange = function onIsScrollingChange(isScrolling) {
291
+ if (_this.isScrolling !== isScrolling) {
292
+ _this.isScrolling = isScrolling;
293
+ _this.notify();
390
294
  }
391
- this._scrollToOffset(this.scrollOffset, {
392
- adjustments: this.scrollAdjustments += delta,
393
- behavior: undefined,
394
- sync: false
395
- });
396
- }
397
- this.pendingMeasuredCacheIndexes.push(index);
398
- this.itemMeasurementsCache = {
399
- ...this.itemMeasurementsCache,
400
- [item.key]: measuredItemSize
401
295
  };
402
- this.notify();
403
- }
404
- };
405
- this.measureElement = node => {
406
- if (!node) {
407
- return;
408
- }
409
- this._measureElement(node, true);
410
- };
411
- this.getVirtualItems = memo(() => [this.getIndexes(), this.getMeasurements()], (indexes, measurements) => {
412
- const virtualItems = [];
413
- for (let k = 0, len = indexes.length; k < len; k++) {
414
- const i = indexes[k];
415
- const measurement = measurements[i];
416
- virtualItems.push(measurement);
417
- }
418
- return virtualItems;
419
- }, {
420
- key: 'getIndexes',
421
- debug: () => this.options.debug
422
- });
423
- this.scrollToOffset = function (toOffset, _temp) {
424
- let {
425
- align = 'start',
426
- behavior
427
- } = _temp === void 0 ? {} : _temp;
428
- const offset = _this.scrollOffset;
429
- const size = _this.getSize();
430
- if (align === 'auto') {
431
- if (toOffset <= offset) {
432
- align = 'start';
433
- } else if (toOffset >= offset + size) {
434
- align = 'end';
435
- } else {
436
- align = 'start';
296
+ _this.scrollAdjustments = 0;
297
+ if (_this.scrollOffset !== offset) {
298
+ _this.scrollOffset = offset;
299
+ onIsScrollingChange(true);
437
300
  }
438
- }
439
- const options = {
440
- adjustments: undefined,
441
- behavior,
442
- 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
443
332
  };
444
- if (align === 'start') {
445
- _this._scrollToOffset(toOffset, options);
446
- } else if (align === 'end') {
447
- _this._scrollToOffset(toOffset - size, options);
448
- } else if (align === 'center') {
449
- _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];
450
396
  }
451
- };
452
- this.scrollToIndex = function (index, _temp2) {
453
- let {
454
- align = 'auto',
455
- ...rest
456
- } = _temp2 === void 0 ? {} : _temp2;
457
- _this.pendingScrollToIndexCallback = null;
458
- const measurements = _this.getMeasurements();
459
- const offset = _this.scrollOffset;
460
- const size = _this.getSize();
461
- const {
462
- count
463
- } = _this.options;
464
- const measurement = measurements[Math.max(0, Math.min(index, count - 1))];
465
- if (!measurement) {
466
- return;
397
+ return;
398
+ }
399
+ if (!prevNode || prevNode !== node) {
400
+ if (prevNode) {
401
+ ro == null ? void 0 : ro.unobserve(prevNode);
467
402
  }
468
- if (align === 'auto') {
469
- if (measurement.end >= offset + size - _this.options.scrollPaddingEnd) {
470
- align = 'end';
471
- } else if (measurement.start <= offset + _this.options.scrollPaddingStart) {
472
- align = 'start';
473
- } else {
474
- 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);
475
414
  }
415
+ _this._scrollToOffset(_this.scrollOffset, {
416
+ adjustments: _this.scrollAdjustments += delta,
417
+ behavior: undefined,
418
+ sync: false
419
+ });
476
420
  }
477
- const toOffset = align === 'end' ? measurement.end + _this.options.scrollPaddingEnd : measurement.start - _this.options.scrollPaddingStart;
478
- _this.scrollToOffset(toOffset, {
479
- align,
480
- ...rest
481
- });
482
- const isDynamic = Object.keys(_this.measureElementCache).length > 0;
483
- if (isDynamic) {
484
- const didSeen = () => typeof _this.itemMeasurementsCache[_this.options.getItemKey(index)] === 'number';
485
- if (!didSeen()) {
486
- _this.pendingScrollToIndexCallback = () => {
487
- if (didSeen()) {
488
- _this.pendingScrollToIndexCallback = null;
489
- _this.scrollToIndex(index, {
490
- align,
491
- ...rest
492
- });
493
- }
494
- };
495
- }
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';
496
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
497
478
  };
498
- this.getTotalSize = () => {
499
- var _this$getMeasurements;
500
- return (((_this$getMeasurements = this.getMeasurements()[this.options.count - 1]) == null ? void 0 : _this$getMeasurements.end) || this.options.paddingStart) + this.options.paddingEnd;
501
- };
502
- this._scrollToOffset = (offset, _ref4) => {
503
- let {
504
- adjustments,
505
- behavior,
506
- sync
507
- } = _ref4;
508
- this.options.scrollToFn(offset, {
509
- behavior,
510
- sync,
511
- adjustments
512
- }, 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);
513
507
  };
514
- this.measure = () => {
515
- this.itemMeasurementsCache = {};
516
- 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
517
516
  };
518
- this.setOptions(_opts);
519
- this.scrollRect = this.options.initialRect;
520
- this.scrollOffset = this.options.initialOffset;
521
- this.calculateRange();
522
- }
523
- }
524
- 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) {
525
559
  while (low <= high) {
526
- const middle = (low + high) / 2 | 0;
527
- const currentValue = getCurrentValue(middle);
560
+ var middle = (low + high) / 2 | 0;
561
+ var currentValue = getCurrentValue(middle);
528
562
  if (currentValue < value) {
529
563
  low = middle + 1;
530
564
  } else if (currentValue > value) {
@@ -539,22 +573,22 @@
539
573
  return 0;
540
574
  }
541
575
  };
542
- function calculateRange(_ref5) {
543
- let {
544
- measurements,
545
- outerSize,
546
- scrollOffset
547
- } = _ref5;
548
- const count = measurements.length - 1;
549
- const getOffset = index => measurements[index].start;
550
- const startIndex = findNearestBinarySearch(0, count, getOffset, scrollOffset);
551
- 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;
552
586
  while (endIndex < count && measurements[endIndex].end < scrollOffset + outerSize) {
553
587
  endIndex++;
554
588
  }
555
589
  return {
556
- startIndex,
557
- endIndex
590
+ startIndex: startIndex,
591
+ endIndex: endIndex
558
592
  };
559
593
  }
560
594