@tanstack/solid-virtual 3.0.0-beta.9 → 3.0.1

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.
@@ -11,7 +11,7 @@
11
11
  (function (global, factory) {
12
12
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('solid-js'), require('solid-js/store')) :
13
13
  typeof define === 'function' && define.amd ? define(['exports', 'solid-js', 'solid-js/store'], factory) :
14
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.SolidVirtual = {}, global.Solid, global["Solid/Store"]));
14
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.SolidVirtual = {}, global.Solid, global.SolidStore));
15
15
  })(this, (function (exports, solidJs, store) { 'use strict';
16
16
 
17
17
  /**
@@ -24,546 +24,678 @@
24
24
  *
25
25
  * @license MIT
26
26
  */
27
- var props = ["bottom", "height", "left", "right", "top", "width"];
28
-
29
- var rectChanged = function rectChanged(a, b) {
30
- if (a === void 0) {
31
- a = {};
32
- }
33
-
34
- if (b === void 0) {
35
- b = {};
36
- }
37
-
38
- return props.some(function (prop) {
39
- return a[prop] !== b[prop];
40
- });
41
- };
42
-
43
- var observedNodes = /*#__PURE__*/new Map();
44
- var rafId;
45
-
46
- var run = function run() {
47
- var changedStates = [];
48
- observedNodes.forEach(function (state, node) {
49
- var newRect = node.getBoundingClientRect();
50
-
51
- if (rectChanged(newRect, state.rect)) {
52
- state.rect = newRect;
53
- changedStates.push(state);
54
- }
55
- });
56
- changedStates.forEach(function (state) {
57
- state.callbacks.forEach(function (cb) {
58
- return cb(state.rect);
59
- });
60
- });
61
- rafId = window.requestAnimationFrame(run);
62
- };
63
-
64
- function observeRect(node, cb) {
65
- return {
66
- observe: function observe() {
67
- var wasEmpty = observedNodes.size === 0;
68
-
69
- if (observedNodes.has(node)) {
70
- observedNodes.get(node).callbacks.push(cb);
71
- } else {
72
- observedNodes.set(node, {
73
- rect: undefined,
74
- hasRectChanged: false,
75
- callbacks: [cb]
76
- });
77
- }
78
-
79
- if (wasEmpty) run();
80
- },
81
- unobserve: function unobserve() {
82
- var state = observedNodes.get(node);
83
-
84
- if (state) {
85
- // Remove the callback
86
- var index = state.callbacks.indexOf(cb);
87
- if (index >= 0) state.callbacks.splice(index, 1); // Remove the node reference
88
-
89
- if (!state.callbacks.length) observedNodes["delete"](node); // Stop the loop
90
-
91
- if (!observedNodes.size) cancelAnimationFrame(rafId);
27
+ function _extends() {
28
+ _extends = Object.assign ? Object.assign.bind() : function (target) {
29
+ for (var i = 1; i < arguments.length; i++) {
30
+ var source = arguments[i];
31
+ for (var key in source) {
32
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
33
+ target[key] = source[key];
34
+ }
92
35
  }
93
36
  }
37
+ return target;
94
38
  };
39
+ return _extends.apply(this, arguments);
95
40
  }
96
41
 
42
+ /**
43
+ * virtual-core
44
+ *
45
+ * Copyright (c) TanStack
46
+ *
47
+ * This source code is licensed under the MIT license found in the
48
+ * LICENSE.md file in the root directory of this source tree.
49
+ *
50
+ * @license MIT
51
+ */
97
52
  function memo(getDeps, fn, opts) {
98
- let deps = [];
99
- let result;
100
- return () => {
101
- let depTime;
53
+ var _opts$initialDeps;
54
+ var deps = (_opts$initialDeps = opts.initialDeps) != null ? _opts$initialDeps : [];
55
+ var result;
56
+ return function () {
57
+ var depTime;
102
58
  if (opts.key && opts.debug != null && opts.debug()) depTime = Date.now();
103
- const newDeps = getDeps();
104
- const depsChanged = newDeps.length !== deps.length || newDeps.some((dep, index) => deps[index] !== dep);
105
-
59
+ var newDeps = getDeps();
60
+ var depsChanged = newDeps.length !== deps.length || newDeps.some(function (dep, index) {
61
+ return deps[index] !== dep;
62
+ });
106
63
  if (!depsChanged) {
107
64
  return result;
108
65
  }
109
-
110
66
  deps = newDeps;
111
- let resultTime;
67
+ var resultTime;
112
68
  if (opts.key && opts.debug != null && opts.debug()) resultTime = Date.now();
113
- result = fn(...newDeps);
114
- opts == null ? void 0 : opts.onChange == null ? void 0 : opts.onChange(result);
115
-
69
+ result = fn.apply(void 0, newDeps);
116
70
  if (opts.key && opts.debug != null && opts.debug()) {
117
- const depEndTime = Math.round((Date.now() - depTime) * 100) / 100;
118
- const resultEndTime = Math.round((Date.now() - resultTime) * 100) / 100;
119
- const resultFpsPercentage = resultEndTime / 16;
120
-
121
- const pad = (str, num) => {
71
+ var depEndTime = Math.round((Date.now() - depTime) * 100) / 100;
72
+ var resultEndTime = Math.round((Date.now() - resultTime) * 100) / 100;
73
+ var resultFpsPercentage = resultEndTime / 16;
74
+ var pad = function pad(str, num) {
122
75
  str = String(str);
123
-
124
76
  while (str.length < num) {
125
77
  str = ' ' + str;
126
78
  }
127
-
128
79
  return str;
129
80
  };
130
-
131
81
  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);
132
82
  }
133
-
83
+ opts == null || opts.onChange == null || opts.onChange(result);
134
84
  return result;
135
85
  };
136
86
  }
87
+ function notUndefined(value, msg) {
88
+ if (value === undefined) {
89
+ throw new Error("Unexpected undefined" + (msg ? ": " + msg : ''));
90
+ } else {
91
+ return value;
92
+ }
93
+ }
94
+ var approxEqual = function approxEqual(a, b) {
95
+ return Math.abs(a - b) < 1;
96
+ };
97
+
98
+ /**
99
+ * virtual-core
100
+ *
101
+ * Copyright (c) TanStack
102
+ *
103
+ * This source code is licensed under the MIT license found in the
104
+ * LICENSE.md file in the root directory of this source tree.
105
+ *
106
+ * @license MIT
107
+ */
137
108
 
138
109
  //
139
- const defaultKeyExtractor = index => index;
140
- const defaultRangeExtractor = range => {
141
- const start = Math.max(range.startIndex - range.overscan, 0);
142
- const end = Math.min(range.endIndex + range.overscan, range.count - 1);
143
- const arr = [];
144
110
 
145
- for (let i = start; i <= end; i++) {
146
- arr.push(i);
147
- }
111
+ //
148
112
 
113
+ var defaultKeyExtractor = function defaultKeyExtractor(index) {
114
+ return index;
115
+ };
116
+ var defaultRangeExtractor = function defaultRangeExtractor(range) {
117
+ var start = Math.max(range.startIndex - range.overscan, 0);
118
+ var end = Math.min(range.endIndex + range.overscan, range.count - 1);
119
+ var arr = [];
120
+ for (var _i = start; _i <= end; _i++) {
121
+ arr.push(_i);
122
+ }
149
123
  return arr;
150
124
  };
151
-
152
- const memoRectCallback = (instance, cb) => {
153
- let prev = {
154
- height: -1,
155
- width: -1
156
- };
157
- return rect => {
158
- if (instance.options.horizontal ? rect.width !== prev.width : rect.height !== prev.height) {
159
- cb(rect);
125
+ var observeElementRect = function observeElementRect(instance, cb) {
126
+ var element = instance.scrollElement;
127
+ if (!element) {
128
+ return;
129
+ }
130
+ var handler = function handler(rect) {
131
+ var width = rect.width,
132
+ height = rect.height;
133
+ cb({
134
+ width: Math.round(width),
135
+ height: Math.round(height)
136
+ });
137
+ };
138
+ handler(element.getBoundingClientRect());
139
+ var observer = new ResizeObserver(function (entries) {
140
+ var entry = entries[0];
141
+ if (entry != null && entry.borderBoxSize) {
142
+ var box = entry.borderBoxSize[0];
143
+ if (box) {
144
+ handler({
145
+ width: box.inlineSize,
146
+ height: box.blockSize
147
+ });
148
+ return;
149
+ }
160
150
  }
161
-
162
- prev = rect;
151
+ handler(element.getBoundingClientRect());
152
+ });
153
+ observer.observe(element, {
154
+ box: 'border-box'
155
+ });
156
+ return function () {
157
+ observer.unobserve(element);
163
158
  };
164
159
  };
165
-
166
- const observeElementRect = (instance, cb) => {
167
- const onResize = memoRectCallback(instance, cb);
168
- const observer = observeRect(instance.scrollElement, rect => {
169
- onResize(rect);
170
- });
171
-
172
- if (!instance.scrollElement) {
160
+ var observeWindowRect = function observeWindowRect(instance, cb) {
161
+ var element = instance.scrollElement;
162
+ if (!element) {
173
163
  return;
174
164
  }
175
-
176
- onResize(instance.scrollElement.getBoundingClientRect());
177
- observer.observe();
178
- return () => {
179
- observer.unobserve();
165
+ var handler = function handler() {
166
+ cb({
167
+ width: element.innerWidth,
168
+ height: element.innerHeight
169
+ });
180
170
  };
181
- };
182
- const observeWindowRect = (instance, cb) => {
183
- const memoizedCallback = memoRectCallback(instance, cb);
184
-
185
- const onResize = () => memoizedCallback({
186
- width: instance.scrollElement.innerWidth,
187
- height: instance.scrollElement.innerHeight
171
+ handler();
172
+ element.addEventListener('resize', handler, {
173
+ passive: true
188
174
  });
189
-
190
- if (!instance.scrollElement) {
175
+ return function () {
176
+ element.removeEventListener('resize', handler);
177
+ };
178
+ };
179
+ var observeElementOffset = function observeElementOffset(instance, cb) {
180
+ var element = instance.scrollElement;
181
+ if (!element) {
191
182
  return;
192
183
  }
193
-
194
- onResize();
195
- instance.scrollElement.addEventListener('resize', onResize, {
196
- capture: false,
184
+ var handler = function handler() {
185
+ cb(element[instance.options.horizontal ? 'scrollLeft' : 'scrollTop']);
186
+ };
187
+ handler();
188
+ element.addEventListener('scroll', handler, {
197
189
  passive: true
198
190
  });
199
- return () => {
200
- instance.scrollElement.removeEventListener('resize', onResize);
191
+ return function () {
192
+ element.removeEventListener('scroll', handler);
201
193
  };
202
194
  };
203
- const scrollProps = {
204
- element: ['scrollLeft', 'scrollTop'],
205
- window: ['scrollX', 'scrollY']
206
- };
207
-
208
- const createOffsetObserver = mode => {
209
- return (instance, cb) => {
210
- if (!instance.scrollElement) {
211
- return;
212
- }
213
-
214
- const propX = scrollProps[mode][0];
215
- const propY = scrollProps[mode][1];
216
- let prevX = instance.scrollElement[propX];
217
- let prevY = instance.scrollElement[propY];
218
-
219
- const scroll = () => {
220
- cb(instance.scrollElement[instance.options.horizontal ? propX : propY]);
221
- };
222
-
223
- scroll();
224
-
225
- const onScroll = e => {
226
- const target = e.currentTarget;
227
- const scrollX = target[propX];
228
- const scrollY = target[propY];
229
-
230
- if (instance.options.horizontal ? prevX - scrollX : prevY - scrollY) {
231
- scroll();
232
- }
233
-
234
- prevX = scrollX;
235
- prevY = scrollY;
236
- };
237
-
238
- instance.scrollElement.addEventListener('scroll', onScroll, {
239
- capture: false,
240
- passive: true
241
- });
242
- return () => {
243
- instance.scrollElement.removeEventListener('scroll', onScroll);
244
- };
195
+ var observeWindowOffset = function observeWindowOffset(instance, cb) {
196
+ var element = instance.scrollElement;
197
+ if (!element) {
198
+ return;
199
+ }
200
+ var handler = function handler() {
201
+ cb(element[instance.options.horizontal ? 'scrollX' : 'scrollY']);
202
+ };
203
+ handler();
204
+ element.addEventListener('scroll', handler, {
205
+ passive: true
206
+ });
207
+ return function () {
208
+ element.removeEventListener('scroll', handler);
245
209
  };
246
210
  };
247
-
248
- const observeElementOffset = createOffsetObserver('element');
249
- const observeWindowOffset = createOffsetObserver('window');
250
- const measureElement = (element, instance) => {
251
- return element.getBoundingClientRect()[instance.options.horizontal ? 'width' : 'height'];
211
+ var measureElement = function measureElement(element, entry, instance) {
212
+ if (entry != null && entry.borderBoxSize) {
213
+ var box = entry.borderBoxSize[0];
214
+ if (box) {
215
+ var size = Math.round(box[instance.options.horizontal ? 'inlineSize' : 'blockSize']);
216
+ return size;
217
+ }
218
+ }
219
+ return Math.round(element.getBoundingClientRect()[instance.options.horizontal ? 'width' : 'height']);
252
220
  };
253
- const windowScroll = (offset, canSmooth, instance) => {
254
- var _instance$scrollEleme;
255
- (_instance$scrollEleme = instance.scrollElement) == null ? void 0 : _instance$scrollEleme.scrollTo({
256
- [instance.options.horizontal ? 'left' : 'top']: offset,
257
- behavior: canSmooth ? 'smooth' : undefined
258
- });
221
+ var windowScroll = function windowScroll(offset, _ref, instance) {
222
+ var _instance$scrollEleme, _instance$scrollEleme2;
223
+ var _ref$adjustments = _ref.adjustments,
224
+ adjustments = _ref$adjustments === void 0 ? 0 : _ref$adjustments,
225
+ behavior = _ref.behavior;
226
+ var toOffset = offset + adjustments;
227
+ (_instance$scrollEleme = instance.scrollElement) == null || _instance$scrollEleme.scrollTo == null || _instance$scrollEleme.scrollTo((_instance$scrollEleme2 = {}, _instance$scrollEleme2[instance.options.horizontal ? 'left' : 'top'] = toOffset, _instance$scrollEleme2.behavior = behavior, _instance$scrollEleme2));
259
228
  };
260
- const elementScroll = (offset, canSmooth, instance) => {
261
- var _instance$scrollEleme2;
262
- (_instance$scrollEleme2 = instance.scrollElement) == null ? void 0 : _instance$scrollEleme2.scrollTo({
263
- [instance.options.horizontal ? 'left' : 'top']: offset,
264
- behavior: canSmooth ? 'smooth' : undefined
265
- });
229
+ var elementScroll = function elementScroll(offset, _ref2, instance) {
230
+ var _instance$scrollEleme3, _instance$scrollEleme4;
231
+ var _ref2$adjustments = _ref2.adjustments,
232
+ adjustments = _ref2$adjustments === void 0 ? 0 : _ref2$adjustments,
233
+ behavior = _ref2.behavior;
234
+ var toOffset = offset + adjustments;
235
+ (_instance$scrollEleme3 = instance.scrollElement) == null || _instance$scrollEleme3.scrollTo == null || _instance$scrollEleme3.scrollTo((_instance$scrollEleme4 = {}, _instance$scrollEleme4[instance.options.horizontal ? 'left' : 'top'] = toOffset, _instance$scrollEleme4.behavior = behavior, _instance$scrollEleme4));
266
236
  };
267
- class Virtualizer {
268
- constructor(_opts) {
269
- var _this = this;
270
-
271
- this.unsubs = [];
272
- this.scrollElement = null;
273
- this.measurementsCache = [];
274
- this.itemMeasurementsCache = {};
275
- this.pendingMeasuredCacheIndexes = [];
276
- this.measureElementCache = {};
277
-
278
- this.setOptions = opts => {
279
- Object.entries(opts).forEach(_ref => {
280
- let [key, value] = _ref;
281
- if (typeof value === 'undefined') delete opts[key];
282
- });
283
- this.options = {
284
- debug: false,
285
- initialOffset: 0,
286
- overscan: 1,
287
- paddingStart: 0,
288
- paddingEnd: 0,
289
- scrollPaddingStart: 0,
290
- scrollPaddingEnd: 0,
291
- horizontal: false,
292
- getItemKey: defaultKeyExtractor,
293
- rangeExtractor: defaultRangeExtractor,
294
- enableSmoothScroll: true,
295
- onChange: () => {},
296
- measureElement,
297
- initialRect: {
298
- width: 0,
299
- height: 0
300
- },
301
- ...opts
302
- };
303
- };
304
-
305
- this.notify = () => {
306
- var _this$options$onChang, _this$options;
307
-
308
- (_this$options$onChang = (_this$options = this.options).onChange) == null ? void 0 : _this$options$onChang.call(_this$options, this);
309
- };
310
-
311
- this.cleanup = () => {
312
- this.unsubs.filter(Boolean).forEach(d => d());
313
- this.unsubs = [];
314
- this.scrollElement = null;
315
- };
316
-
317
- this._didMount = () => {
318
- return () => {
319
- this.cleanup();
320
- };
321
- };
322
-
323
- this._willUpdate = () => {
324
- const scrollElement = this.options.getScrollElement();
325
-
326
- if (this.scrollElement !== scrollElement) {
327
- this.cleanup();
328
- this.scrollElement = scrollElement;
329
- this.unsubs.push(this.options.observeElementRect(this, rect => {
330
- this.scrollRect = rect;
331
- this.notify();
332
- }));
333
- this.unsubs.push(this.options.observeElementOffset(this, offset => {
334
- this.scrollOffset = offset;
335
- this.notify();
336
- }));
237
+ var Virtualizer = function Virtualizer(_opts) {
238
+ var _this = this;
239
+ this.unsubs = [];
240
+ this.scrollElement = null;
241
+ this.isScrolling = false;
242
+ this.isScrollingTimeoutId = null;
243
+ this.scrollToIndexTimeoutId = null;
244
+ this.measurementsCache = [];
245
+ this.itemSizeCache = new Map();
246
+ this.pendingMeasuredCacheIndexes = [];
247
+ this.scrollDirection = null;
248
+ this.scrollAdjustments = 0;
249
+ this.measureElementCache = new Map();
250
+ this.observer = function () {
251
+ var _ro = null;
252
+ var get = function get() {
253
+ if (_ro) {
254
+ return _ro;
255
+ } else if (typeof ResizeObserver !== 'undefined') {
256
+ return _ro = new ResizeObserver(function (entries) {
257
+ entries.forEach(function (entry) {
258
+ _this._measureElement(entry.target, entry);
259
+ });
260
+ });
261
+ } else {
262
+ return null;
337
263
  }
338
264
  };
339
-
340
- this.getSize = () => {
341
- return this.scrollRect[this.options.horizontal ? 'width' : 'height'];
342
- };
343
-
344
- this.getMeasurements = memo(() => [this.options.count, this.options.paddingStart, this.options.getItemKey, this.itemMeasurementsCache], (count, paddingStart, getItemKey, measurementsCache) => {
345
- const min = this.pendingMeasuredCacheIndexes.length > 0 ? Math.min(...this.pendingMeasuredCacheIndexes) : 0;
346
- this.pendingMeasuredCacheIndexes = [];
347
- const measurements = this.measurementsCache.slice(0, min);
348
-
349
- for (let i = min; i < count; i++) {
350
- const key = getItemKey(i);
351
- const measuredSize = measurementsCache[key];
352
- const start = measurements[i - 1] ? measurements[i - 1].end : paddingStart;
353
- const size = typeof measuredSize === 'number' ? measuredSize : this.options.estimateSize(i);
354
- const end = start + size;
355
- measurements[i] = {
356
- index: i,
357
- start,
358
- size,
359
- end,
360
- key
361
- };
265
+ return {
266
+ disconnect: function disconnect() {
267
+ var _get;
268
+ return (_get = get()) == null ? void 0 : _get.disconnect();
269
+ },
270
+ observe: function observe(target) {
271
+ var _get2;
272
+ return (_get2 = get()) == null ? void 0 : _get2.observe(target, {
273
+ box: 'border-box'
274
+ });
275
+ },
276
+ unobserve: function unobserve(target) {
277
+ var _get3;
278
+ return (_get3 = get()) == null ? void 0 : _get3.unobserve(target);
362
279
  }
363
-
364
- this.measurementsCache = measurements;
365
- return measurements;
366
- }, {
367
- key: 'getMeasurements',
368
- debug: () => this.options.debug
280
+ };
281
+ }();
282
+ this.range = null;
283
+ this.setOptions = function (opts) {
284
+ Object.entries(opts).forEach(function (_ref3) {
285
+ var key = _ref3[0],
286
+ value = _ref3[1];
287
+ if (typeof value === 'undefined') delete opts[key];
369
288
  });
370
- this.calculateRange = memo(() => [this.getMeasurements(), this.getSize(), this.scrollOffset], (measurements, outerSize, scrollOffset) => {
371
- return calculateRange({
372
- measurements,
373
- outerSize,
374
- scrollOffset
375
- });
376
- }, {
377
- key: 'calculateRange',
378
- debug: () => this.options.debug
289
+ _this.options = _extends({
290
+ debug: false,
291
+ initialOffset: 0,
292
+ overscan: 1,
293
+ paddingStart: 0,
294
+ paddingEnd: 0,
295
+ scrollPaddingStart: 0,
296
+ scrollPaddingEnd: 0,
297
+ horizontal: false,
298
+ getItemKey: defaultKeyExtractor,
299
+ rangeExtractor: defaultRangeExtractor,
300
+ onChange: function onChange() {},
301
+ measureElement: measureElement,
302
+ initialRect: {
303
+ width: 0,
304
+ height: 0
305
+ },
306
+ scrollMargin: 0,
307
+ scrollingDelay: 150,
308
+ indexAttribute: 'data-index',
309
+ initialMeasurementsCache: [],
310
+ lanes: 1
311
+ }, opts);
312
+ };
313
+ this.notify = function (sync) {
314
+ _this.options.onChange == null || _this.options.onChange(_this, sync);
315
+ };
316
+ this.maybeNotify = memo(function () {
317
+ _this.calculateRange();
318
+ return [_this.isScrolling, _this.range ? _this.range.startIndex : null, _this.range ? _this.range.endIndex : null];
319
+ }, function (isScrolling) {
320
+ _this.notify(isScrolling);
321
+ }, {
322
+ key: 'maybeNotify',
323
+ debug: function debug() {
324
+ return _this.options.debug;
325
+ },
326
+ initialDeps: [this.isScrolling, this.range ? this.range.startIndex : null, this.range ? this.range.endIndex : null]
327
+ });
328
+ this.cleanup = function () {
329
+ _this.unsubs.filter(Boolean).forEach(function (d) {
330
+ return d();
379
331
  });
380
- this.getIndexes = memo(() => [this.options.rangeExtractor, this.calculateRange(), this.options.overscan, this.options.count], (rangeExtractor, range, overscan, count) => {
381
- return rangeExtractor({ ...range,
382
- overscan,
383
- count: count
332
+ _this.unsubs = [];
333
+ _this.scrollElement = null;
334
+ };
335
+ this._didMount = function () {
336
+ _this.measureElementCache.forEach(_this.observer.observe);
337
+ return function () {
338
+ _this.observer.disconnect();
339
+ _this.cleanup();
340
+ };
341
+ };
342
+ this._willUpdate = function () {
343
+ var scrollElement = _this.options.getScrollElement();
344
+ if (_this.scrollElement !== scrollElement) {
345
+ _this.cleanup();
346
+ _this.scrollElement = scrollElement;
347
+ _this._scrollToOffset(_this.scrollOffset, {
348
+ adjustments: undefined,
349
+ behavior: undefined
384
350
  });
385
- }, {
386
- key: 'getIndexes'
387
- });
388
- this.getVirtualItems = memo(() => [this.getIndexes(), this.getMeasurements(), this.options.measureElement], (indexes, measurements, measureElement) => {
389
- const makeMeasureElement = index => measurableItem => {
390
- var _this$itemMeasurement;
391
-
392
- const item = this.measurementsCache[index];
393
-
394
- if (!measurableItem) {
351
+ _this.unsubs.push(_this.options.observeElementRect(_this, function (rect) {
352
+ _this.scrollRect = rect;
353
+ _this.maybeNotify();
354
+ }));
355
+ _this.unsubs.push(_this.options.observeElementOffset(_this, function (offset) {
356
+ _this.scrollAdjustments = 0;
357
+ if (_this.scrollOffset === offset) {
395
358
  return;
396
359
  }
397
-
398
- const measuredItemSize = measureElement(measurableItem, this);
399
- const itemSize = (_this$itemMeasurement = this.itemMeasurementsCache[item.key]) != null ? _this$itemMeasurement : item.size;
400
-
401
- if (measuredItemSize !== itemSize) {
402
- if (item.start < this.scrollOffset) {
403
- if (this.options.debug) {
404
- console.info('correction', measuredItemSize - itemSize);
405
- }
406
-
407
- if (!this.destinationOffset) {
408
- this._scrollToOffset(this.scrollOffset + (measuredItemSize - itemSize), false);
409
- }
410
- }
411
-
412
- this.pendingMeasuredCacheIndexes.push(index);
413
- this.itemMeasurementsCache = { ...this.itemMeasurementsCache,
414
- [item.key]: measuredItemSize
415
- };
416
- this.notify();
360
+ if (_this.isScrollingTimeoutId !== null) {
361
+ clearTimeout(_this.isScrollingTimeoutId);
362
+ _this.isScrollingTimeoutId = null;
417
363
  }
418
- };
419
-
420
- const virtualItems = [];
421
- const currentMeasureElements = {};
422
-
423
- for (let k = 0, len = indexes.length; k < len; k++) {
424
- var _this$measureElementC;
425
-
426
- const i = indexes[k];
427
- const measurement = measurements[i];
428
- const item = { ...measurement,
429
- measureElement: currentMeasureElements[i] = (_this$measureElementC = this.measureElementCache[i]) != null ? _this$measureElementC : makeMeasureElement(i)
430
- };
431
- virtualItems.push(item);
364
+ _this.isScrolling = true;
365
+ _this.scrollDirection = _this.scrollOffset < offset ? 'forward' : 'backward';
366
+ _this.scrollOffset = offset;
367
+ _this.maybeNotify();
368
+ _this.isScrollingTimeoutId = setTimeout(function () {
369
+ _this.isScrollingTimeoutId = null;
370
+ _this.isScrolling = false;
371
+ _this.scrollDirection = null;
372
+ _this.maybeNotify();
373
+ }, _this.options.scrollingDelay);
374
+ }));
375
+ }
376
+ };
377
+ this.getSize = function () {
378
+ return _this.scrollRect[_this.options.horizontal ? 'width' : 'height'];
379
+ };
380
+ this.memoOptions = memo(function () {
381
+ return [_this.options.count, _this.options.paddingStart, _this.options.scrollMargin, _this.options.getItemKey];
382
+ }, function (count, paddingStart, scrollMargin, getItemKey) {
383
+ _this.pendingMeasuredCacheIndexes = [];
384
+ return {
385
+ count: count,
386
+ paddingStart: paddingStart,
387
+ scrollMargin: scrollMargin,
388
+ getItemKey: getItemKey
389
+ };
390
+ }, {
391
+ key: false
392
+ });
393
+ this.getFurthestMeasurement = function (measurements, index) {
394
+ var furthestMeasurementsFound = new Map();
395
+ var furthestMeasurements = new Map();
396
+ for (var m = index - 1; m >= 0; m--) {
397
+ var measurement = measurements[m];
398
+ if (furthestMeasurementsFound.has(measurement.lane)) {
399
+ continue;
432
400
  }
433
-
434
- this.measureElementCache = currentMeasureElements;
435
- return virtualItems;
436
- }, {
437
- key: 'getIndexes'
438
- });
439
-
440
- this.scrollToOffset = function (toOffset, _temp) {
441
- let {
442
- align
443
- } = _temp === void 0 ? {
444
- align: 'start'
445
- } : _temp;
446
-
447
- const attempt = () => {
448
- const offset = _this.scrollOffset;
449
-
450
- const size = _this.getSize();
451
-
452
- if (align === 'auto') {
453
- if (toOffset <= offset) {
454
- align = 'start';
455
- } else if (toOffset >= offset + size) {
456
- align = 'end';
457
- } else {
458
- align = 'start';
459
- }
460
- }
461
-
462
- if (align === 'start') {
463
- _this._scrollToOffset(toOffset, true);
464
- } else if (align === 'end') {
465
- _this._scrollToOffset(toOffset - size, true);
466
- } else if (align === 'center') {
467
- _this._scrollToOffset(toOffset - size / 2, true);
468
- }
401
+ var previousFurthestMeasurement = furthestMeasurements.get(measurement.lane);
402
+ if (previousFurthestMeasurement == null || measurement.end > previousFurthestMeasurement.end) {
403
+ furthestMeasurements.set(measurement.lane, measurement);
404
+ } else if (measurement.end < previousFurthestMeasurement.end) {
405
+ furthestMeasurementsFound.set(measurement.lane, true);
406
+ }
407
+ if (furthestMeasurementsFound.size === _this.options.lanes) {
408
+ break;
409
+ }
410
+ }
411
+ return furthestMeasurements.size === _this.options.lanes ? Array.from(furthestMeasurements.values()).sort(function (a, b) {
412
+ return a.end - b.end;
413
+ })[0] : undefined;
414
+ };
415
+ this.getMeasurements = memo(function () {
416
+ return [_this.memoOptions(), _this.itemSizeCache];
417
+ }, function (_ref4, itemSizeCache) {
418
+ var count = _ref4.count,
419
+ paddingStart = _ref4.paddingStart,
420
+ scrollMargin = _ref4.scrollMargin,
421
+ getItemKey = _ref4.getItemKey;
422
+ var min = _this.pendingMeasuredCacheIndexes.length > 0 ? Math.min.apply(Math, _this.pendingMeasuredCacheIndexes) : 0;
423
+ _this.pendingMeasuredCacheIndexes = [];
424
+ var measurements = _this.measurementsCache.slice(0, min);
425
+ for (var _i2 = min; _i2 < count; _i2++) {
426
+ var key = getItemKey(_i2);
427
+ var furthestMeasurement = _this.options.lanes === 1 ? measurements[_i2 - 1] : _this.getFurthestMeasurement(measurements, _i2);
428
+ var start = furthestMeasurement ? furthestMeasurement.end : paddingStart + scrollMargin;
429
+ var measuredSize = itemSizeCache.get(key);
430
+ var size = typeof measuredSize === 'number' ? measuredSize : _this.options.estimateSize(_i2);
431
+ var end = start + size;
432
+ var lane = furthestMeasurement ? furthestMeasurement.lane : _i2 % _this.options.lanes;
433
+ measurements[_i2] = {
434
+ index: _i2,
435
+ start: start,
436
+ size: size,
437
+ end: end,
438
+ key: key,
439
+ lane: lane
469
440
  };
470
-
471
- attempt();
472
- requestAnimationFrame(() => {
473
- attempt();
441
+ }
442
+ _this.measurementsCache = measurements;
443
+ return measurements;
444
+ }, {
445
+ key: 'getMeasurements',
446
+ debug: function debug() {
447
+ return _this.options.debug;
448
+ }
449
+ });
450
+ this.calculateRange = memo(function () {
451
+ return [_this.getMeasurements(), _this.getSize(), _this.scrollOffset];
452
+ }, function (measurements, outerSize, scrollOffset) {
453
+ return _this.range = measurements.length > 0 && outerSize > 0 ? calculateRange({
454
+ measurements: measurements,
455
+ outerSize: outerSize,
456
+ scrollOffset: scrollOffset
457
+ }) : null;
458
+ }, {
459
+ key: 'calculateRange',
460
+ debug: function debug() {
461
+ return _this.options.debug;
462
+ }
463
+ });
464
+ this.getIndexes = memo(function () {
465
+ return [_this.options.rangeExtractor, _this.calculateRange(), _this.options.overscan, _this.options.count];
466
+ }, function (rangeExtractor, range, overscan, count) {
467
+ return range === null ? [] : rangeExtractor(_extends({}, range, {
468
+ overscan: overscan,
469
+ count: count
470
+ }));
471
+ }, {
472
+ key: 'getIndexes',
473
+ debug: function debug() {
474
+ return _this.options.debug;
475
+ }
476
+ });
477
+ this.indexFromElement = function (node) {
478
+ var attributeName = _this.options.indexAttribute;
479
+ var indexStr = node.getAttribute(attributeName);
480
+ if (!indexStr) {
481
+ console.warn("Missing attribute name '" + attributeName + "={index}' on measured element.");
482
+ return -1;
483
+ }
484
+ return parseInt(indexStr, 10);
485
+ };
486
+ this._measureElement = function (node, entry) {
487
+ var item = _this.measurementsCache[_this.indexFromElement(node)];
488
+ if (!item || !node.isConnected) {
489
+ _this.measureElementCache.forEach(function (cached, key) {
490
+ if (cached === node) {
491
+ _this.observer.unobserve(node);
492
+ _this.measureElementCache["delete"](key);
493
+ }
474
494
  });
475
- };
476
-
477
- this.scrollToIndex = function (index, _temp2) {
478
- let {
479
- align,
480
- ...rest
481
- } = _temp2 === void 0 ? {
482
- align: 'auto'
483
- } : _temp2;
484
-
485
- const measurements = _this.getMeasurements();
486
-
487
- const offset = _this.scrollOffset;
488
-
489
- const size = _this.getSize();
490
-
491
- const {
492
- count
493
- } = _this.options;
494
- const measurement = measurements[Math.max(0, Math.min(index, count - 1))];
495
-
496
- if (!measurement) {
497
- return;
495
+ return;
496
+ }
497
+ var prevNode = _this.measureElementCache.get(item.key);
498
+ if (prevNode !== node) {
499
+ if (prevNode) {
500
+ _this.observer.unobserve(prevNode);
498
501
  }
499
-
500
- if (align === 'auto') {
501
- if (measurement.end >= offset + size - _this.options.scrollPaddingEnd) {
502
- align = 'end';
503
- } else if (measurement.start <= offset + _this.options.scrollPaddingStart) {
504
- align = 'start';
505
- } else {
506
- return;
502
+ _this.observer.observe(node);
503
+ _this.measureElementCache.set(item.key, node);
504
+ }
505
+ var measuredItemSize = _this.options.measureElement(node, entry, _this);
506
+ _this.resizeItem(item, measuredItemSize);
507
+ };
508
+ this.resizeItem = function (item, size) {
509
+ var _this$itemSizeCache$g;
510
+ var itemSize = (_this$itemSizeCache$g = _this.itemSizeCache.get(item.key)) != null ? _this$itemSizeCache$g : item.size;
511
+ var delta = size - itemSize;
512
+ if (delta !== 0) {
513
+ if (item.start < _this.scrollOffset) {
514
+ if (_this.options.debug) {
515
+ console.info('correction', delta);
507
516
  }
517
+ _this._scrollToOffset(_this.scrollOffset, {
518
+ adjustments: _this.scrollAdjustments += delta,
519
+ behavior: undefined
520
+ });
508
521
  }
509
-
510
- const toOffset = align === 'end' ? measurement.end + _this.options.scrollPaddingEnd : measurement.start - _this.options.scrollPaddingStart;
511
-
512
- _this.scrollToOffset(toOffset, {
513
- align,
514
- ...rest
515
- });
516
- };
517
-
518
- this.getTotalSize = () => {
519
- var _this$getMeasurements;
520
-
521
- return (((_this$getMeasurements = this.getMeasurements()[this.options.count - 1]) == null ? void 0 : _this$getMeasurements.end) || this.options.paddingStart) + this.options.paddingEnd;
522
- };
523
-
524
- this._scrollToOffset = (offset, canSmooth) => {
525
- clearTimeout(this.scrollCheckFrame);
526
- this.destinationOffset = offset;
527
- this.options.scrollToFn(offset, this.options.enableSmoothScroll && canSmooth, this);
528
- let scrollCheckFrame;
529
-
530
- const check = () => {
531
- let lastOffset = this.scrollOffset;
532
- this.scrollCheckFrame = scrollCheckFrame = setTimeout(() => {
533
- if (this.scrollCheckFrame !== scrollCheckFrame) {
534
- return;
535
- }
536
-
537
- if (this.scrollOffset === lastOffset) {
538
- this.destinationOffset = undefined;
539
- return;
522
+ _this.pendingMeasuredCacheIndexes.push(item.index);
523
+ _this.itemSizeCache = new Map(_this.itemSizeCache.set(item.key, size));
524
+ _this.notify(false);
525
+ }
526
+ };
527
+ this.measureElement = function (node) {
528
+ if (!node) {
529
+ return;
530
+ }
531
+ _this._measureElement(node, undefined);
532
+ };
533
+ this.getVirtualItems = memo(function () {
534
+ return [_this.getIndexes(), _this.getMeasurements()];
535
+ }, function (indexes, measurements) {
536
+ var virtualItems = [];
537
+ for (var k = 0, len = indexes.length; k < len; k++) {
538
+ var _i3 = indexes[k];
539
+ var measurement = measurements[_i3];
540
+ virtualItems.push(measurement);
541
+ }
542
+ return virtualItems;
543
+ }, {
544
+ key: 'getIndexes',
545
+ debug: function debug() {
546
+ return _this.options.debug;
547
+ }
548
+ });
549
+ this.getVirtualItemForOffset = function (offset) {
550
+ var measurements = _this.getMeasurements();
551
+ return notUndefined(measurements[findNearestBinarySearch(0, measurements.length - 1, function (index) {
552
+ return notUndefined(measurements[index]).start;
553
+ }, offset)]);
554
+ };
555
+ this.getOffsetForAlignment = function (toOffset, align) {
556
+ var size = _this.getSize();
557
+ if (align === 'auto') {
558
+ if (toOffset <= _this.scrollOffset) {
559
+ align = 'start';
560
+ } else if (toOffset >= _this.scrollOffset + size) {
561
+ align = 'end';
562
+ } else {
563
+ align = 'start';
564
+ }
565
+ }
566
+ if (align === 'start') {
567
+ toOffset = toOffset;
568
+ } else if (align === 'end') {
569
+ toOffset = toOffset - size;
570
+ } else if (align === 'center') {
571
+ toOffset = toOffset - size / 2;
572
+ }
573
+ var scrollSizeProp = _this.options.horizontal ? 'scrollWidth' : 'scrollHeight';
574
+ var scrollSize = _this.scrollElement ? 'document' in _this.scrollElement ? _this.scrollElement.document.documentElement[scrollSizeProp] : _this.scrollElement[scrollSizeProp] : 0;
575
+ var maxOffset = scrollSize - _this.getSize();
576
+ return Math.max(Math.min(maxOffset, toOffset), 0);
577
+ };
578
+ this.getOffsetForIndex = function (index, align) {
579
+ if (align === void 0) {
580
+ align = 'auto';
581
+ }
582
+ index = Math.max(0, Math.min(index, _this.options.count - 1));
583
+ var measurement = notUndefined(_this.getMeasurements()[index]);
584
+ if (align === 'auto') {
585
+ if (measurement.end >= _this.scrollOffset + _this.getSize() - _this.options.scrollPaddingEnd) {
586
+ align = 'end';
587
+ } else if (measurement.start <= _this.scrollOffset + _this.options.scrollPaddingStart) {
588
+ align = 'start';
589
+ } else {
590
+ return [_this.scrollOffset, align];
591
+ }
592
+ }
593
+ var toOffset = align === 'end' ? measurement.end + _this.options.scrollPaddingEnd : measurement.start - _this.options.scrollPaddingStart;
594
+ return [_this.getOffsetForAlignment(toOffset, align), align];
595
+ };
596
+ this.isDynamicMode = function () {
597
+ return _this.measureElementCache.size > 0;
598
+ };
599
+ this.cancelScrollToIndex = function () {
600
+ if (_this.scrollToIndexTimeoutId !== null) {
601
+ clearTimeout(_this.scrollToIndexTimeoutId);
602
+ _this.scrollToIndexTimeoutId = null;
603
+ }
604
+ };
605
+ this.scrollToOffset = function (toOffset, _temp) {
606
+ var _ref5 = _temp === void 0 ? {} : _temp,
607
+ _ref5$align = _ref5.align,
608
+ align = _ref5$align === void 0 ? 'start' : _ref5$align,
609
+ behavior = _ref5.behavior;
610
+ _this.cancelScrollToIndex();
611
+ if (behavior === 'smooth' && _this.isDynamicMode()) {
612
+ console.warn('The `smooth` scroll behavior is not fully supported with dynamic size.');
613
+ }
614
+ _this._scrollToOffset(_this.getOffsetForAlignment(toOffset, align), {
615
+ adjustments: undefined,
616
+ behavior: behavior
617
+ });
618
+ };
619
+ this.scrollToIndex = function (index, _temp2) {
620
+ var _ref6 = _temp2 === void 0 ? {} : _temp2,
621
+ _ref6$align = _ref6.align,
622
+ initialAlign = _ref6$align === void 0 ? 'auto' : _ref6$align,
623
+ behavior = _ref6.behavior;
624
+ index = Math.max(0, Math.min(index, _this.options.count - 1));
625
+ _this.cancelScrollToIndex();
626
+ if (behavior === 'smooth' && _this.isDynamicMode()) {
627
+ console.warn('The `smooth` scroll behavior is not fully supported with dynamic size.');
628
+ }
629
+ var _this$getOffsetForInd = _this.getOffsetForIndex(index, initialAlign),
630
+ toOffset = _this$getOffsetForInd[0],
631
+ align = _this$getOffsetForInd[1];
632
+ _this._scrollToOffset(toOffset, {
633
+ adjustments: undefined,
634
+ behavior: behavior
635
+ });
636
+ if (behavior !== 'smooth' && _this.isDynamicMode()) {
637
+ _this.scrollToIndexTimeoutId = setTimeout(function () {
638
+ _this.scrollToIndexTimeoutId = null;
639
+ var elementInDOM = _this.measureElementCache.has(_this.options.getItemKey(index));
640
+ if (elementInDOM) {
641
+ var _this$getOffsetForInd2 = _this.getOffsetForIndex(index, align),
642
+ _toOffset = _this$getOffsetForInd2[0];
643
+ if (!approxEqual(_toOffset, _this.scrollOffset)) {
644
+ _this.scrollToIndex(index, {
645
+ align: align,
646
+ behavior: behavior
647
+ });
540
648
  }
541
-
542
- lastOffset = this.scrollOffset;
543
- check();
544
- }, 100);
545
- };
546
-
547
- check();
548
- };
549
-
550
- this.measure = () => {
551
- this.itemMeasurementsCache = {};
552
- this.notify();
553
- };
554
-
555
- this.setOptions(_opts);
556
- this.scrollRect = this.options.initialRect;
557
- this.scrollOffset = this.options.initialOffset;
558
- }
559
-
560
- }
561
-
562
- const findNearestBinarySearch = (low, high, getCurrentValue, value) => {
649
+ } else {
650
+ _this.scrollToIndex(index, {
651
+ align: align,
652
+ behavior: behavior
653
+ });
654
+ }
655
+ });
656
+ }
657
+ };
658
+ this.scrollBy = function (delta, _temp3) {
659
+ var _ref7 = _temp3 === void 0 ? {} : _temp3,
660
+ behavior = _ref7.behavior;
661
+ _this.cancelScrollToIndex();
662
+ if (behavior === 'smooth' && _this.isDynamicMode()) {
663
+ console.warn('The `smooth` scroll behavior is not fully supported with dynamic size.');
664
+ }
665
+ _this._scrollToOffset(_this.scrollOffset + delta, {
666
+ adjustments: undefined,
667
+ behavior: behavior
668
+ });
669
+ };
670
+ this.getTotalSize = function () {
671
+ var _this$getMeasurements;
672
+ return (((_this$getMeasurements = _this.getMeasurements()[_this.options.count - 1]) == null ? void 0 : _this$getMeasurements.end) || _this.options.paddingStart) - _this.options.scrollMargin + _this.options.paddingEnd;
673
+ };
674
+ this._scrollToOffset = function (offset, _ref8) {
675
+ var adjustments = _ref8.adjustments,
676
+ behavior = _ref8.behavior;
677
+ _this.options.scrollToFn(offset, {
678
+ behavior: behavior,
679
+ adjustments: adjustments
680
+ }, _this);
681
+ };
682
+ this.measure = function () {
683
+ _this.itemSizeCache = new Map();
684
+ _this.notify(false);
685
+ };
686
+ this.setOptions(_opts);
687
+ this.scrollRect = this.options.initialRect;
688
+ this.scrollOffset = this.options.initialOffset;
689
+ this.measurementsCache = this.options.initialMeasurementsCache;
690
+ this.measurementsCache.forEach(function (item) {
691
+ _this.itemSizeCache.set(item.key, item.size);
692
+ });
693
+ this.maybeNotify();
694
+ };
695
+ var findNearestBinarySearch = function findNearestBinarySearch(low, high, getCurrentValue, value) {
563
696
  while (low <= high) {
564
- const middle = (low + high) / 2 | 0;
565
- const currentValue = getCurrentValue(middle);
566
-
697
+ var middle = (low + high) / 2 | 0;
698
+ var currentValue = getCurrentValue(middle);
567
699
  if (currentValue < value) {
568
700
  low = middle + 1;
569
701
  } else if (currentValue > value) {
@@ -572,83 +704,78 @@
572
704
  return middle;
573
705
  }
574
706
  }
575
-
576
707
  if (low > 0) {
577
708
  return low - 1;
578
709
  } else {
579
710
  return 0;
580
711
  }
581
712
  };
582
-
583
- function calculateRange(_ref2) {
584
- let {
585
- measurements,
586
- outerSize,
587
- scrollOffset
588
- } = _ref2;
589
- const count = measurements.length - 1;
590
-
591
- const getOffset = index => measurements[index].start;
592
-
593
- const startIndex = findNearestBinarySearch(0, count, getOffset, scrollOffset);
594
- let endIndex = startIndex;
595
-
713
+ function calculateRange(_ref9) {
714
+ var measurements = _ref9.measurements,
715
+ outerSize = _ref9.outerSize,
716
+ scrollOffset = _ref9.scrollOffset;
717
+ var count = measurements.length - 1;
718
+ var getOffset = function getOffset(index) {
719
+ return measurements[index].start;
720
+ };
721
+ var startIndex = findNearestBinarySearch(0, count, getOffset, scrollOffset);
722
+ var endIndex = startIndex;
596
723
  while (endIndex < count && measurements[endIndex].end < scrollOffset + outerSize) {
597
724
  endIndex++;
598
725
  }
599
-
600
726
  return {
601
- startIndex,
602
- endIndex
727
+ startIndex: startIndex,
728
+ endIndex: endIndex
603
729
  };
604
730
  }
605
731
 
606
732
  function createVirtualizerBase(options) {
607
- const resolvedOptions = solidJs.mergeProps(options);
608
- const instance = new Virtualizer(resolvedOptions);
609
- const [virtualItems, setVirtualItems] = store.createStore(instance.getVirtualItems());
610
- const [totalSize, setTotalSize] = solidJs.createSignal(instance.getTotalSize());
611
- const handler = {
612
- get(target, prop) {
733
+ var resolvedOptions = solidJs.mergeProps(options);
734
+ var instance = new Virtualizer(resolvedOptions);
735
+ var _createStore = store.createStore(instance.getVirtualItems()),
736
+ virtualItems = _createStore[0],
737
+ setVirtualItems = _createStore[1];
738
+ var _createSignal = solidJs.createSignal(instance.getTotalSize()),
739
+ totalSize = _createSignal[0],
740
+ setTotalSize = _createSignal[1];
741
+ var handler = {
742
+ get: function get(target, prop) {
613
743
  switch (prop) {
614
744
  case 'getVirtualItems':
615
- return () => virtualItems;
616
-
745
+ return function () {
746
+ return virtualItems;
747
+ };
617
748
  case 'getTotalSize':
618
- return () => totalSize();
619
-
749
+ return function () {
750
+ return totalSize();
751
+ };
620
752
  default:
621
753
  return Reflect.get(target, prop);
622
754
  }
623
755
  }
624
-
625
756
  };
626
- const virtualizer = new Proxy(instance, handler);
757
+ var virtualizer = new Proxy(instance, handler);
627
758
  virtualizer.setOptions(resolvedOptions);
628
- solidJs.onMount(() => {
629
- const cleanup = virtualizer._didMount();
630
-
759
+ solidJs.onMount(function () {
760
+ var cleanup = virtualizer._didMount();
631
761
  virtualizer._willUpdate();
632
-
633
762
  solidJs.onCleanup(cleanup);
634
763
  });
635
- solidJs.createComputed(() => {
764
+ solidJs.createComputed(function () {
636
765
  virtualizer.setOptions(solidJs.mergeProps(resolvedOptions, options, {
637
- onChange: instance => {
766
+ onChange: function onChange(instance, sync) {
638
767
  instance._willUpdate();
639
-
640
768
  setVirtualItems(store.reconcile(instance.getVirtualItems(), {
641
769
  key: 'index'
642
770
  }));
643
771
  setTotalSize(instance.getTotalSize());
644
- options.onChange == null ? void 0 : options.onChange(instance);
772
+ options.onChange == null || options.onChange(instance, sync);
645
773
  }
646
774
  }));
647
775
  virtualizer.measure();
648
776
  });
649
777
  return virtualizer;
650
778
  }
651
-
652
779
  function createVirtualizer(options) {
653
780
  return createVirtualizerBase(solidJs.mergeProps({
654
781
  observeElementRect: observeElementRect,
@@ -658,14 +785,18 @@
658
785
  }
659
786
  function createWindowVirtualizer(options) {
660
787
  return createVirtualizerBase(solidJs.mergeProps({
661
- getScrollElement: () => typeof window !== 'undefined' ? window : null,
788
+ getScrollElement: function getScrollElement() {
789
+ return typeof document !== 'undefined' ? window : null;
790
+ },
662
791
  observeElementRect: observeWindowRect,
663
792
  observeElementOffset: observeWindowOffset,
664
- scrollToFn: windowScroll
793
+ scrollToFn: windowScroll,
794
+ initialOffset: typeof document !== 'undefined' ? window.scrollY : undefined
665
795
  }, options));
666
796
  }
667
797
 
668
798
  exports.Virtualizer = Virtualizer;
799
+ exports.approxEqual = approxEqual;
669
800
  exports.createVirtualizer = createVirtualizer;
670
801
  exports.createWindowVirtualizer = createWindowVirtualizer;
671
802
  exports.defaultKeyExtractor = defaultKeyExtractor;
@@ -673,6 +804,7 @@
673
804
  exports.elementScroll = elementScroll;
674
805
  exports.measureElement = measureElement;
675
806
  exports.memo = memo;
807
+ exports.notUndefined = notUndefined;
676
808
  exports.observeElementOffset = observeElementOffset;
677
809
  exports.observeElementRect = observeElementRect;
678
810
  exports.observeWindowOffset = observeWindowOffset;