virtua 0.50.3 → 0.50.4

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.
@@ -30,112 +30,6 @@ var once = (fn) => {
30
30
  };
31
31
  };
32
32
 
33
- //#endregion
34
- //#region src/core/cache.ts
35
- var UNCACHED = -1;
36
- var fill = (array, length, prepend) => {
37
- const key = prepend ? "unshift" : "push";
38
- for (let i = 0; i < length; i++) {
39
- array[key](-1);
40
- }
41
- return array;
42
- };
43
- var getItemSize = (cache, index) => {
44
- const size = cache._sizes[index];
45
- return size === -1 ? cache._defaultItemSize : size;
46
- };
47
- var setItemSize = (cache, index, size) => {
48
- const isInitialMeasurement = cache._sizes[index] === -1;
49
- cache._sizes[index] = size;
50
- cache._computedOffsetIndex = min(index, cache._computedOffsetIndex);
51
- return isInitialMeasurement;
52
- };
53
- var getItemOffset = (cache, index) => {
54
- if (!cache._length) return 0;
55
- if (cache._computedOffsetIndex >= index) {
56
- return cache._offsets[index];
57
- }
58
- if (cache._computedOffsetIndex < 0) {
59
- cache._offsets[0] = 0;
60
- cache._computedOffsetIndex = 0;
61
- }
62
- let i = cache._computedOffsetIndex;
63
- let top = cache._offsets[i];
64
- while (i < index) {
65
- top += getItemSize(cache, i);
66
- cache._offsets[++i] = top;
67
- }
68
- cache._computedOffsetIndex = index;
69
- return top;
70
- };
71
- var findIndex = (cache, offset, low = 0, high = cache._length - 1) => {
72
- let found = low;
73
- while (low <= high) {
74
- const mid = floor((low + high) / 2);
75
- if (getItemOffset(cache, mid) <= offset) {
76
- found = mid;
77
- low = mid + 1;
78
- } else {
79
- high = mid - 1;
80
- }
81
- }
82
- return clamp(found, 0, cache._length - 1);
83
- };
84
- var computeRange = (cache, startOffset, endOffset, prevStartIndex) => {
85
- prevStartIndex = min(prevStartIndex, cache._length - 1);
86
- if (getItemOffset(cache, prevStartIndex) <= startOffset) {
87
- const end = findIndex(cache, endOffset, prevStartIndex);
88
- return [findIndex(cache, startOffset, prevStartIndex, end), end];
89
- } else {
90
- const start = findIndex(cache, startOffset, undefined, prevStartIndex);
91
- return [start, findIndex(cache, endOffset, start)];
92
- }
93
- };
94
- var estimateDefaultItemSize = (cache, startIndex) => {
95
- let measuredCountBeforeStart = 0;
96
- const measuredSizes = [];
97
- cache._sizes.forEach((s, i) => {
98
- if (s !== -1) {
99
- measuredSizes.push(s);
100
- if (i < startIndex) {
101
- measuredCountBeforeStart++;
102
- }
103
- }
104
- });
105
- cache._computedOffsetIndex = -1;
106
- const sorted = sort(measuredSizes);
107
- const len = sorted.length;
108
- const mid = len / 2 | 0;
109
- const median = len % 2 === 0 ? (sorted[mid - 1] + sorted[mid]) / 2 : sorted[mid];
110
- const prevDefaultItemSize = cache._defaultItemSize;
111
- return ((cache._defaultItemSize = median) - prevDefaultItemSize) * max(startIndex - measuredCountBeforeStart, 0);
112
- };
113
- var initCache = (length, itemSize, sizes) => {
114
- return {
115
- _defaultItemSize: itemSize,
116
- _sizes: sizes ? fill(sizes.slice(0, min(length, sizes.length)), max(0, length - sizes.length)) : fill([], length),
117
- _length: length,
118
- _computedOffsetIndex: -1,
119
- _offsets: fill([], length + 1)
120
- };
121
- };
122
- var takeCacheSnapshot = (cache) => {
123
- return [cache._sizes.slice(), cache._defaultItemSize];
124
- };
125
- var updateCacheLength = (cache, length, isShift) => {
126
- const diff = length - cache._length;
127
- cache._computedOffsetIndex = isShift ? -1 : min(length - 1, cache._computedOffsetIndex);
128
- cache._length = length;
129
- if (diff > 0) {
130
- fill(cache._offsets, diff);
131
- fill(cache._sizes, diff, isShift);
132
- return cache._defaultItemSize * diff;
133
- } else {
134
- cache._offsets.splice(diff);
135
- return (isShift ? cache._sizes.splice(0, -diff) : cache._sizes.splice(diff)).reduce((acc, removed) => acc - (removed === -1 ? cache._defaultItemSize : removed), 0);
136
- }
137
- };
138
-
139
33
  //#endregion
140
34
  //#region src/core/environment.ts
141
35
  var isBrowser = typeof window !== "undefined";
@@ -176,7 +70,8 @@ var UPDATE_SCROLL_END_EVENT = 8;
176
70
  var getScrollSize = (store) => {
177
71
  return max(store.$getTotalSize(), store.$getViewportSize());
178
72
  };
179
- var createVirtualStore = (elementsCount, itemSize = 40, ssrCount = 0, cacheSnapshot, shouldAutoEstimateItemSize = false) => {
73
+ var createVirtualStore = ({ $getRange: getRange, $findIndex: findIndex, $getItemOffset: getOffset, $getItemSize: getItemSize, $setItemSize: setItemSize, $isSizeEqual: isSizeEqual, $getTotalSize: getTotalSize, $getLength: getLength, $setLength: setLength, $estimateDefaultSize: estimateDefaultSize }, ssrCount = 0) => {
74
+ let shouldAutoEstimateItemSize = !!estimateDefaultSize;
180
75
  let isSSR = !!ssrCount;
181
76
  let stateVersion = 1;
182
77
  let viewportSize = 0;
@@ -191,27 +86,16 @@ var createVirtualStore = (elementsCount, itemSize = 40, ssrCount = 0, cacheSnaps
191
86
  let _prevRange = [0, isSSR ? max(ssrCount - 1, 0) : -1];
192
87
  let _totalMeasuredSize = 0;
193
88
  let _isViewportMeasured = false;
194
- const cache = initCache(elementsCount, cacheSnapshot && cacheSnapshot[1] || itemSize, cacheSnapshot && cacheSnapshot[0]);
195
89
  const subscribers = new Set();
196
90
  const getRelativeScrollOffset = () => scrollOffset - startSpacerSize;
197
91
  const getVisibleOffset = () => getRelativeScrollOffset() + pendingJump + jump;
198
- const getRange = (startOffset, endOffset) => {
199
- return computeRange(cache, startOffset, endOffset, _prevRange[0]);
200
- };
201
- const getTotalSize = () => getItemOffset(cache, cache._length);
202
- const getItemOffset$1 = (index, fromEnd) => {
203
- const offset = getItemOffset(cache, index) - pendingJump;
92
+ const getItemOffset = (index, fromEnd) => {
93
+ const offset = getOffset(index) - pendingJump;
204
94
  if (fromEnd) {
205
- return getTotalSize() - offset - getItemSize$1(index);
95
+ return getTotalSize() - offset - getItemSize(index);
206
96
  }
207
97
  return offset;
208
98
  };
209
- const getItemSize$1 = (index) => {
210
- return getItemSize(cache, index);
211
- };
212
- const isSizeEqual = (index, value = -1) => {
213
- return cache._sizes[index] === value;
214
- };
215
99
  const applyJump = (j) => {
216
100
  if (j) {
217
101
  if (isIOSWebKit() && _scrollDirection !== SCROLL_IDLE || _frozenRange && _scrollMode === SCROLL_BY_MANUAL_SCROLL) {
@@ -226,9 +110,6 @@ var createVirtualStore = (elementsCount, itemSize = 40, ssrCount = 0, cacheSnaps
226
110
  subscribers.clear();
227
111
  },
228
112
  $getStateVersion: () => stateVersion,
229
- $getCacheSnapshot: () => {
230
- return takeCacheSnapshot(cache);
231
- },
232
113
  $getRange: (bufferSize = 200) => {
233
114
  if (!_isViewportMeasured || isSSR) {
234
115
  return _prevRange;
@@ -255,13 +136,13 @@ var createVirtualStore = (elementsCount, itemSize = 40, ssrCount = 0, cacheSnaps
255
136
  endIndex = max(endIndex, _frozenRange[1]);
256
137
  }
257
138
  }
258
- return [max(startIndex, 0), min(endIndex, cache._length - 1)];
139
+ return [max(startIndex, 0), min(endIndex, getLength() - 1)];
259
140
  },
260
- $findItemIndex: (offset) => findIndex(cache, offset - startSpacerSize),
141
+ $findItemIndex: (offset) => findIndex(offset - startSpacerSize),
261
142
  $isUnmeasuredItem: isSizeEqual,
262
- $getItemOffset: getItemOffset$1,
263
- $getItemSize: getItemSize$1,
264
- $getItemsLength: () => cache._length,
143
+ $getItemOffset: getItemOffset,
144
+ $getItemSize: getItemSize,
145
+ $getItemsLength: getLength,
265
146
  $getScrollOffset: () => scrollOffset,
266
147
  $isScrolling: () => _scrollDirection !== SCROLL_IDLE,
267
148
  $getViewportSize: () => viewportSize,
@@ -332,24 +213,24 @@ var createVirtualStore = (elementsCount, itemSize = 40, ssrCount = 0, cacheSnaps
332
213
  shouldKeep = index < _frozenRange[0];
333
214
  } else {
334
215
  const start = getRelativeScrollOffset();
335
- const itemOffset = getItemOffset$1(index);
336
- const itemSize = getItemSize$1(index);
216
+ const itemOffset = getItemOffset(index);
217
+ const itemSize = getItemSize(index);
337
218
  shouldKeep = _scrollDirection !== SCROLL_DOWN && _scrollMode === SCROLL_BY_NATIVE ? itemOffset + itemSize <= start : itemOffset < start && itemOffset + itemSize < start + viewportSize;
338
219
  }
339
220
  if (shouldKeep) {
340
- acc += size - getItemSize$1(index);
221
+ acc += size - getItemSize(index);
341
222
  }
342
223
  return acc;
343
224
  }, 0));
344
225
  for (const [index, size] of updated) {
345
- const prevSize = getItemSize$1(index);
346
- const isInitialMeasurement = setItemSize(cache, index, size);
226
+ const prevSize = getItemSize(index);
227
+ const isInitialMeasurement = setItemSize(index, size);
347
228
  if (shouldAutoEstimateItemSize) {
348
229
  _totalMeasuredSize += isInitialMeasurement ? size : size - prevSize;
349
230
  }
350
231
  }
351
232
  if (shouldAutoEstimateItemSize && viewportSize && _totalMeasuredSize > viewportSize) {
352
- applyJump(estimateDefaultItemSize(cache, findIndex(cache, getVisibleOffset())));
233
+ applyJump(estimateDefaultSize(findIndex(getVisibleOffset())));
353
234
  shouldAutoEstimateItemSize = false;
354
235
  }
355
236
  mutated = 1 + 2;
@@ -368,11 +249,11 @@ var createVirtualStore = (elementsCount, itemSize = 40, ssrCount = 0, cacheSnaps
368
249
  }
369
250
  case 5: {
370
251
  if (payload[1]) {
371
- applyJump(updateCacheLength(cache, payload[0], true));
252
+ applyJump(setLength(payload[0], true));
372
253
  _scrollMode = SCROLL_BY_SHIFT;
373
254
  mutated = 1;
374
255
  } else {
375
- updateCacheLength(cache, payload[0]);
256
+ setLength(payload[0]);
376
257
  mutated = 1;
377
258
  }
378
259
  break;
@@ -408,6 +289,124 @@ var createVirtualStore = (elementsCount, itemSize = 40, ssrCount = 0, cacheSnaps
408
289
  };
409
290
  };
410
291
 
292
+ //#endregion
293
+ //#region src/core/cache.ts
294
+ var UNCACHED = -1;
295
+ var findIndex = (getOffset, length, offset, low = 0, high = length - 1) => {
296
+ let found = low;
297
+ while (low <= high) {
298
+ const mid = floor((low + high) / 2);
299
+ if (getOffset(mid) <= offset) {
300
+ found = mid;
301
+ low = mid + 1;
302
+ } else {
303
+ high = mid - 1;
304
+ }
305
+ }
306
+ return clamp(found, 0, length - 1);
307
+ };
308
+
309
+ //#endregion
310
+ //#region src/core/layouts/list.ts
311
+ var fill = (array, length, prepend) => {
312
+ const key = prepend ? "unshift" : "push";
313
+ for (let i = 0; i < length; i++) {
314
+ array[key](-1);
315
+ }
316
+ return array;
317
+ };
318
+ var createListLayout = (length, itemSize, snapshot) => {
319
+ let defaultItemSize = snapshot && snapshot[1] || itemSize || 40;
320
+ let computedOffsetIndex = -1;
321
+ let prevStartIndex = 0;
322
+ const restoredSizes = snapshot && snapshot[0];
323
+ const sizes = restoredSizes ? fill(restoredSizes.slice(0, min(length, restoredSizes.length)), max(0, length - restoredSizes.length)) : fill([], length);
324
+ const offsets = fill([], length + 1);
325
+ const getSize = (index) => {
326
+ const size = sizes[index];
327
+ return size === -1 ? defaultItemSize : size;
328
+ };
329
+ const getOffset = (index) => {
330
+ if (!length) return 0;
331
+ if (computedOffsetIndex >= index) {
332
+ return offsets[index];
333
+ }
334
+ if (computedOffsetIndex < 0) {
335
+ offsets[0] = 0;
336
+ computedOffsetIndex = 0;
337
+ }
338
+ let i = computedOffsetIndex;
339
+ let top = offsets[i];
340
+ while (i < index) {
341
+ top += getSize(i);
342
+ offsets[++i] = top;
343
+ }
344
+ computedOffsetIndex = index;
345
+ return top;
346
+ };
347
+ return {
348
+ $getRange: (startOffset, endOffset) => {
349
+ prevStartIndex = min(prevStartIndex, length - 1);
350
+ let start;
351
+ let end;
352
+ if (getOffset(prevStartIndex) <= startOffset) {
353
+ end = findIndex(getOffset, length, endOffset, prevStartIndex);
354
+ start = findIndex(getOffset, length, startOffset, prevStartIndex, end);
355
+ } else {
356
+ start = findIndex(getOffset, length, startOffset, undefined, prevStartIndex);
357
+ end = findIndex(getOffset, length, endOffset, start);
358
+ }
359
+ prevStartIndex = start;
360
+ return [start, end];
361
+ },
362
+ $findIndex: (offset) => findIndex(getOffset, length, offset),
363
+ $getItemOffset: getOffset,
364
+ $getItemSize: getSize,
365
+ $setItemSize: (index, size) => {
366
+ const isInitialMeasurement = sizes[index] === -1;
367
+ sizes[index] = size;
368
+ computedOffsetIndex = min(index, computedOffsetIndex);
369
+ return isInitialMeasurement;
370
+ },
371
+ $isSizeEqual: (index, size = -1) => sizes[index] === size,
372
+ $getTotalSize: () => getOffset(length),
373
+ $getLength: () => length,
374
+ $setLength: (nextLength, isShift) => {
375
+ const diff = nextLength - length;
376
+ computedOffsetIndex = isShift ? -1 : min(nextLength - 1, computedOffsetIndex);
377
+ length = nextLength;
378
+ if (diff > 0) {
379
+ fill(offsets, diff);
380
+ fill(sizes, diff, isShift);
381
+ return defaultItemSize * diff;
382
+ } else {
383
+ offsets.splice(diff);
384
+ return (isShift ? sizes.splice(0, -diff) : sizes.splice(diff)).reduce((acc, removed) => acc - (removed === -1 ? defaultItemSize : removed), 0);
385
+ }
386
+ },
387
+ $estimateDefaultSize: itemSize ? undefined : (startIndex) => {
388
+ let measuredCountBeforeStart = 0;
389
+ const measuredSizes = [];
390
+ sizes.forEach((s, i) => {
391
+ if (s !== -1) {
392
+ measuredSizes.push(s);
393
+ if (i < startIndex) {
394
+ measuredCountBeforeStart++;
395
+ }
396
+ }
397
+ });
398
+ computedOffsetIndex = -1;
399
+ const sorted = sort(measuredSizes);
400
+ const len = sorted.length;
401
+ const mid = len / 2 | 0;
402
+ const median = len % 2 === 0 ? (sorted[mid - 1] + sorted[mid]) / 2 : sorted[mid];
403
+ const prevDefaultItemSize = defaultItemSize;
404
+ return ((defaultItemSize = median) - prevDefaultItemSize) * max(startIndex - measuredCountBeforeStart, 0);
405
+ },
406
+ $snapshot: () => [sizes.slice(), defaultItemSize]
407
+ };
408
+ };
409
+
411
410
  //#endregion
412
411
  //#region src/core/observer.ts
413
412
  var createResizeObserver = (cb) => {
@@ -996,13 +995,15 @@ var ListItem = (props) => {
996
995
  });
997
996
  const style = createMemo(() => {
998
997
  const isHorizontal = props._isHorizontal;
998
+ const hide = props._hide;
999
+ const isSSR = props._isSSR;
999
1000
  const style = {
1000
1001
  contain: "layout style",
1001
- position: "absolute",
1002
+ position: hide && isSSR ? undefined : "absolute",
1002
1003
  [isHorizontal ? "height" : "width"]: "100%",
1003
1004
  [isHorizontal ? "top" : "left"]: "0px",
1004
1005
  [isHorizontal ? "left" : "top"]: props._offset + "px",
1005
- visibility: props._hide ? "hidden" : undefined
1006
+ visibility: !hide || isSSR ? undefined : "hidden"
1006
1007
  };
1007
1008
  if (isHorizontal) {
1008
1009
  style.display = "inline-flex";
@@ -1024,9 +1025,11 @@ var isSameRange = (prev, next) => {
1024
1025
  //#region src/solid/Virtualizer.tsx
1025
1026
  var Virtualizer = (props) => {
1026
1027
  let containerRef;
1027
- const { itemSize, horizontal = false, cache } = props;
1028
+ const { itemSize, horizontal = false, cache, ssrCount } = props;
1028
1029
  props = mergeProps({ as: "div" }, props);
1029
- const store = createVirtualStore(props.data.length, itemSize, undefined, cache, !itemSize);
1030
+ const [isSSR, setIsSSR] = createSignal(!!ssrCount);
1031
+ const layout = createListLayout(props.data.length, itemSize, cache);
1032
+ const store = createVirtualStore(layout, ssrCount);
1030
1033
  const driver = createContainerDriver(store, horizontal);
1031
1034
  const [stateVersion, setRerender] = createSignal(store.$getStateVersion());
1032
1035
  store.$subscribe(1, () => {
@@ -1050,10 +1053,11 @@ var Virtualizer = (props) => {
1050
1053
  const totalSize = createMemo(() => stateVersion() && store.$getTotalSize());
1051
1054
  const isNegative = createMemo(() => stateVersion() && driver.$isNegative());
1052
1055
  onMount(() => {
1056
+ setIsSSR(false);
1053
1057
  if (props.ref) {
1054
1058
  props.ref({
1055
1059
  get cache() {
1056
- return store.$getCacheSnapshot();
1060
+ return layout.$snapshot();
1057
1061
  },
1058
1062
  get scrollOffset() {
1059
1063
  return store.$getScrollOffset();
@@ -1130,7 +1134,7 @@ var Virtualizer = (props) => {
1130
1134
  const children = createMemo(() => {
1131
1135
  return untrack(() => props.children(data, index));
1132
1136
  });
1133
- return <ListItem _as={props.item} _index={index()} _resizer={driver.$observeItem} _offset={offset()} _hide={hide()} _children={children()} _isHorizontal={horizontal} />;
1137
+ return <ListItem _as={props.item} _index={index()} _resizer={driver.$observeItem} _offset={offset()} _hide={hide()} _children={children()} _isHorizontal={horizontal} _isSSR={isSSR()} />;
1134
1138
  };
1135
1139
  return <Dynamic component={props.as} ref={containerRef} style={{
1136
1140
  contain: "size style",
@@ -1159,6 +1163,7 @@ var VList = (props) => {
1159
1163
  "children",
1160
1164
  "bufferSize",
1161
1165
  "itemSize",
1166
+ "ssrCount",
1162
1167
  "shift",
1163
1168
  "horizontal",
1164
1169
  "keepMounted",
@@ -1176,7 +1181,7 @@ var VList = (props) => {
1176
1181
  height: "100%",
1177
1182
  ...local.style
1178
1183
  }}>
1179
- <Virtualizer ref={local.ref} data={local.data} bufferSize={local.bufferSize} itemSize={local.itemSize} shift={local.shift} horizontal={local.horizontal} keepMounted={local.keepMounted} cache={local.cache} item={local.item} onScroll={local.onScroll} onScrollEnd={local.onScrollEnd}>
1184
+ <Virtualizer ref={local.ref} data={local.data} bufferSize={local.bufferSize} itemSize={local.itemSize} ssrCount={local.ssrCount} shift={local.shift} horizontal={local.horizontal} keepMounted={local.keepMounted} cache={local.cache} item={local.item} onScroll={local.onScroll} onScrollEnd={local.onScrollEnd}>
1180
1185
  {local.children}
1181
1186
  </Virtualizer>
1182
1187
  </div>;
@@ -1186,8 +1191,10 @@ var VList = (props) => {
1186
1191
  //#region src/solid/WindowVirtualizer.tsx
1187
1192
  var WindowVirtualizer = (props) => {
1188
1193
  let containerRef;
1189
- const { ref: _ref, data: _data, children: _children, itemSize, shift: _shift, horizontal = false, cache, onScrollEnd: _onScrollEnd } = props;
1190
- const store = createVirtualStore(props.data.length, itemSize, undefined, cache, !itemSize);
1194
+ const { ref: _ref, data: _data, children: _children, itemSize, ssrCount, shift: _shift, horizontal = false, cache, onScrollEnd: _onScrollEnd } = props;
1195
+ const [isSSR, setIsSSR] = createSignal(!!ssrCount);
1196
+ const layout = createListLayout(props.data.length, itemSize, cache);
1197
+ const store = createVirtualStore(layout, ssrCount);
1191
1198
  const driver = createWindowDriver(store, horizontal);
1192
1199
  const [stateVersion, setRerender] = createSignal(store.$getStateVersion());
1193
1200
  store.$subscribe(1, () => {
@@ -1211,10 +1218,11 @@ var WindowVirtualizer = (props) => {
1211
1218
  const totalSize = createMemo(() => stateVersion() && store.$getTotalSize());
1212
1219
  const isNegative = createMemo(() => stateVersion() && driver.$isNegative());
1213
1220
  onMount(() => {
1221
+ setIsSSR(false);
1214
1222
  if (props.ref) {
1215
1223
  props.ref({
1216
1224
  get cache() {
1217
- return store.$getCacheSnapshot();
1225
+ return layout.$snapshot();
1218
1226
  },
1219
1227
  get scrollOffset() {
1220
1228
  return store.$getScrollOffset();
@@ -1276,7 +1284,7 @@ var WindowVirtualizer = (props) => {
1276
1284
  const children = createMemo(() => {
1277
1285
  return untrack(() => props.children(data, itemIndex));
1278
1286
  });
1279
- return <ListItem _index={itemIndex()} _resizer={driver.$observeItem} _offset={offset()} _hide={hide()} _children={children()} _isHorizontal={horizontal} />;
1287
+ return <ListItem _index={itemIndex()} _resizer={driver.$observeItem} _offset={offset()} _hide={hide()} _children={children()} _isHorizontal={horizontal} _isSSR={isSSR()} />;
1280
1288
  }}
1281
1289
  </For>
1282
1290
  </div>;