virtua 0.45.3 → 0.46.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/lib/core/index.cjs +1 -1
- package/lib/core/index.cjs.map +1 -1
- package/lib/core/index.js +1 -1
- package/lib/core/index.js.map +1 -1
- package/lib/index.cjs +1 -1
- package/lib/index.cjs.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/react/VGrid.d.ts +3 -3
- package/lib/react/VList.d.ts +1 -1
- package/lib/react/Virtualizer.d.ts +4 -4
- package/lib/react/WindowVirtualizer.d.ts +4 -4
- package/lib/solid/VList.d.ts +1 -1
- package/lib/solid/Virtualizer.d.ts +3 -3
- package/lib/solid/WindowVirtualizer.d.ts +3 -3
- package/lib/solid/index.cjs +1 -1
- package/lib/solid/index.cjs.map +1 -1
- package/lib/solid/index.js +1 -1
- package/lib/solid/index.js.map +1 -1
- package/lib/solid/index.jsx +53 -37
- package/lib/solid/index.jsx.map +1 -1
- package/lib/svelte/VList.svelte +2 -2
- package/lib/svelte/VList.type.d.ts +1 -1
- package/lib/svelte/Virtualizer.svelte +2 -3
- package/lib/svelte/Virtualizer.type.d.ts +3 -3
- package/lib/svelte/WindowVirtualizer.svelte +2 -3
- package/lib/svelte/WindowVirtualizer.type.d.ts +3 -3
- package/lib/vue/VList.d.ts +8 -8
- package/lib/vue/Virtualizer.d.ts +8 -8
- package/lib/vue/WindowVirtualizer.d.ts +6 -6
- package/lib/vue/index.cjs +1 -1
- package/lib/vue/index.cjs.map +1 -1
- package/lib/vue/index.js +1 -1
- package/lib/vue/index.js.map +1 -1
- package/package.json +1 -1
package/lib/solid/index.jsx
CHANGED
|
@@ -132,20 +132,20 @@ const findIndex = (cache, offset, low = 0, high = cache._length - 1) => {
|
|
|
132
132
|
/**
|
|
133
133
|
* @internal
|
|
134
134
|
*/
|
|
135
|
-
const computeRange = (cache,
|
|
135
|
+
const computeRange = (cache, startOffset, endOffset, prevStartIndex) => {
|
|
136
136
|
// Clamp because prevStartIndex may exceed the limit when children decreased a lot after scrolling
|
|
137
137
|
prevStartIndex = min(prevStartIndex, cache._length - 1);
|
|
138
|
-
if (computeOffset(cache, prevStartIndex) <=
|
|
138
|
+
if (computeOffset(cache, prevStartIndex) <= startOffset) {
|
|
139
139
|
// search forward
|
|
140
140
|
// start <= end, prevStartIndex <= start
|
|
141
|
-
const end = findIndex(cache,
|
|
142
|
-
return [findIndex(cache,
|
|
141
|
+
const end = findIndex(cache, endOffset, prevStartIndex);
|
|
142
|
+
return [findIndex(cache, startOffset, prevStartIndex, end), end];
|
|
143
143
|
}
|
|
144
144
|
else {
|
|
145
145
|
// search backward
|
|
146
146
|
// start <= end, start <= prevStartIndex
|
|
147
|
-
const start = findIndex(cache,
|
|
148
|
-
return [start, findIndex(cache,
|
|
147
|
+
const start = findIndex(cache, startOffset, undefined, prevStartIndex);
|
|
148
|
+
return [start, findIndex(cache, endOffset, start)];
|
|
149
149
|
}
|
|
150
150
|
};
|
|
151
151
|
/**
|
|
@@ -302,7 +302,7 @@ const getScrollSize = (store) => {
|
|
|
302
302
|
/**
|
|
303
303
|
* @internal
|
|
304
304
|
*/
|
|
305
|
-
const createVirtualStore = (elementsCount, itemSize = 40,
|
|
305
|
+
const createVirtualStore = (elementsCount, itemSize = 40, ssrCount = 0, cacheSnapshot, shouldAutoEstimateItemSize = false) => {
|
|
306
306
|
let isSSR = !!ssrCount;
|
|
307
307
|
let stateVersion = 1;
|
|
308
308
|
let viewportSize = 0;
|
|
@@ -313,17 +313,15 @@ const createVirtualStore = (elementsCount, itemSize = 40, overscan = 4, ssrCount
|
|
|
313
313
|
let _flushedJump = 0;
|
|
314
314
|
let _scrollDirection = SCROLL_IDLE;
|
|
315
315
|
let _scrollMode = SCROLL_BY_NATIVE;
|
|
316
|
-
let _frozenRange =
|
|
317
|
-
|
|
318
|
-
: NULL;
|
|
319
|
-
let _prevRange = [0, 0];
|
|
316
|
+
let _frozenRange = NULL;
|
|
317
|
+
let _prevRange = [0, isSSR ? max(ssrCount - 1, 0) : -1];
|
|
320
318
|
let _totalMeasuredSize = 0;
|
|
321
319
|
const cache = initCache(elementsCount, itemSize, cacheSnapshot);
|
|
322
320
|
const subscribers = new Set();
|
|
323
321
|
const getRelativeScrollOffset = () => scrollOffset - startSpacerSize;
|
|
324
322
|
const getVisibleOffset = () => getRelativeScrollOffset() + pendingJump + jump;
|
|
325
|
-
const getRange = (
|
|
326
|
-
return computeRange(cache,
|
|
323
|
+
const getRange = (startOffset, endOffset) => {
|
|
324
|
+
return computeRange(cache, startOffset, endOffset, _prevRange[0]);
|
|
327
325
|
};
|
|
328
326
|
const getTotalSize = () => computeTotalSize(cache);
|
|
329
327
|
const getItemOffset = (index) => {
|
|
@@ -355,7 +353,13 @@ const createVirtualStore = (elementsCount, itemSize = 40, overscan = 4, ssrCount
|
|
|
355
353
|
$getCacheSnapshot: () => {
|
|
356
354
|
return takeCacheSnapshot(cache);
|
|
357
355
|
},
|
|
358
|
-
$getRange: () => {
|
|
356
|
+
$getRange: (bufferSize = 200) => {
|
|
357
|
+
if (!viewportSize || isSSR) {
|
|
358
|
+
// Empty viewportSize means the first render.
|
|
359
|
+
// We return range for SSR here, or return [0, -1] to render nothing, until the scroll offset and viewport size are determined.
|
|
360
|
+
// https://github.com/inokawa/virtua/issues/415
|
|
361
|
+
return _prevRange;
|
|
362
|
+
}
|
|
359
363
|
let startIndex;
|
|
360
364
|
let endIndex;
|
|
361
365
|
if (_flushedJump) {
|
|
@@ -364,18 +368,24 @@ const createVirtualStore = (elementsCount, itemSize = 40, overscan = 4, ssrCount
|
|
|
364
368
|
[startIndex, endIndex] = _prevRange;
|
|
365
369
|
}
|
|
366
370
|
else {
|
|
367
|
-
|
|
371
|
+
bufferSize = max(0, bufferSize);
|
|
372
|
+
let startOffset = max(0, getVisibleOffset());
|
|
373
|
+
let endOffset = startOffset + viewportSize;
|
|
374
|
+
// For faster initial render pass, returns without buffer if measurement seems to be in progress.
|
|
375
|
+
if (!shouldAutoEstimateItemSize) {
|
|
376
|
+
if (_scrollDirection !== SCROLL_DOWN) {
|
|
377
|
+
startOffset -= bufferSize;
|
|
378
|
+
}
|
|
379
|
+
if (_scrollDirection !== SCROLL_UP) {
|
|
380
|
+
endOffset += bufferSize;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
[startIndex, endIndex] = _prevRange = getRange(max(0, startOffset), max(0, endOffset));
|
|
368
384
|
if (_frozenRange) {
|
|
369
385
|
startIndex = min(startIndex, _frozenRange[0]);
|
|
370
386
|
endIndex = max(endIndex, _frozenRange[1]);
|
|
371
387
|
}
|
|
372
388
|
}
|
|
373
|
-
if (_scrollDirection !== SCROLL_DOWN) {
|
|
374
|
-
startIndex -= max(0, overscan);
|
|
375
|
-
}
|
|
376
|
-
if (_scrollDirection !== SCROLL_UP) {
|
|
377
|
-
endIndex += max(0, overscan);
|
|
378
|
-
}
|
|
379
389
|
return [max(startIndex, 0), min(endIndex, cache._length - 1)];
|
|
380
390
|
},
|
|
381
391
|
$findStartIndex: () => findIndex(cache, getVisibleOffset()),
|
|
@@ -433,7 +443,6 @@ const createVirtualStore = (elementsCount, itemSize = 40, overscan = 4, ssrCount
|
|
|
433
443
|
// shouldFlushPendingJump = true;
|
|
434
444
|
// }
|
|
435
445
|
if (isSSR) {
|
|
436
|
-
_frozenRange = NULL;
|
|
437
446
|
isSSR = false;
|
|
438
447
|
}
|
|
439
448
|
scrollOffset = payload;
|
|
@@ -545,7 +554,7 @@ const createVirtualStore = (elementsCount, itemSize = 40, overscan = 4, ssrCount
|
|
|
545
554
|
break;
|
|
546
555
|
}
|
|
547
556
|
case ACTION_BEFORE_MANUAL_SMOOTH_SCROLL: {
|
|
548
|
-
_frozenRange = getRange(payload);
|
|
557
|
+
_frozenRange = getRange(payload, payload + viewportSize);
|
|
549
558
|
mutated = UPDATE_VIRTUAL_STATE;
|
|
550
559
|
break;
|
|
551
560
|
}
|
|
@@ -914,13 +923,20 @@ const createWindowScroller = (store, isHorizontal) => {
|
|
|
914
923
|
const scrollOffsetKey = isHorizontal ? "scrollX" : "scrollY";
|
|
915
924
|
const document = getCurrentDocument(container);
|
|
916
925
|
const window = getCurrentWindow(document);
|
|
917
|
-
scrollObserver = createScrollObserver(store, window, isHorizontal, () => normalizeOffset(window[scrollOffsetKey], isHorizontal), (jump) => {
|
|
918
|
-
// Use absolute position not to exceed scrollable bounds
|
|
919
|
-
// https://github.com/inokawa/virtua/discussions/475
|
|
926
|
+
scrollObserver = createScrollObserver(store, window, isHorizontal, () => normalizeOffset(window[scrollOffsetKey], isHorizontal), (jump, shift) => {
|
|
920
927
|
// TODO support case two window scrollers exist in the same view
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
928
|
+
if (shift) {
|
|
929
|
+
// Use absolute position not to exceed scrollable bounds
|
|
930
|
+
window.scroll({
|
|
931
|
+
[scrollToKey]: store.$getScrollOffset() + jump,
|
|
932
|
+
});
|
|
933
|
+
}
|
|
934
|
+
else {
|
|
935
|
+
// Use window.scrollBy here, which causes less layout shift for some reason.
|
|
936
|
+
window.scrollBy({
|
|
937
|
+
[scrollToKey]: jump,
|
|
938
|
+
});
|
|
939
|
+
}
|
|
924
940
|
}, () => calcOffsetToViewport(container, document.body, window, isHorizontal));
|
|
925
941
|
initialized[1](true);
|
|
926
942
|
},
|
|
@@ -1287,9 +1303,9 @@ const isSameRange = (prev, next) => {
|
|
|
1287
1303
|
*/
|
|
1288
1304
|
const Virtualizer = (props) => {
|
|
1289
1305
|
let containerRef;
|
|
1290
|
-
const { itemSize, horizontal = false,
|
|
1306
|
+
const { itemSize, horizontal = false, cache } = props;
|
|
1291
1307
|
props = mergeProps({ as: "div" }, props);
|
|
1292
|
-
const store = createVirtualStore(props.data.length, itemSize,
|
|
1308
|
+
const store = createVirtualStore(props.data.length, itemSize, undefined, cache, !itemSize);
|
|
1293
1309
|
const resizer = createResizer(store, horizontal);
|
|
1294
1310
|
const scroller = createScroller(store, horizontal);
|
|
1295
1311
|
const [stateVersion, setRerender] = createSignal(store.$getStateVersion());
|
|
@@ -1306,7 +1322,7 @@ const Virtualizer = (props) => {
|
|
|
1306
1322
|
});
|
|
1307
1323
|
const range = createMemo((prev) => {
|
|
1308
1324
|
stateVersion();
|
|
1309
|
-
const next = store.$getRange();
|
|
1325
|
+
const next = store.$getRange(props.bufferSize);
|
|
1310
1326
|
if (prev && isSameRange(prev, next)) {
|
|
1311
1327
|
return prev;
|
|
1312
1328
|
}
|
|
@@ -1432,7 +1448,7 @@ const VList = (props) => {
|
|
|
1432
1448
|
"ref",
|
|
1433
1449
|
"data",
|
|
1434
1450
|
"children",
|
|
1435
|
-
"
|
|
1451
|
+
"bufferSize",
|
|
1436
1452
|
"itemSize",
|
|
1437
1453
|
"shift",
|
|
1438
1454
|
"horizontal",
|
|
@@ -1451,7 +1467,7 @@ const VList = (props) => {
|
|
|
1451
1467
|
height: "100%",
|
|
1452
1468
|
...local.style,
|
|
1453
1469
|
}}>
|
|
1454
|
-
<Virtualizer ref={local.ref} data={local.data}
|
|
1470
|
+
<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}>
|
|
1455
1471
|
{local.children}
|
|
1456
1472
|
</Virtualizer>
|
|
1457
1473
|
</div>);
|
|
@@ -1465,8 +1481,8 @@ const VList = (props) => {
|
|
|
1465
1481
|
*/
|
|
1466
1482
|
const WindowVirtualizer = (props) => {
|
|
1467
1483
|
let containerRef;
|
|
1468
|
-
const { ref: _ref, data: _data, children: _children,
|
|
1469
|
-
const store = createVirtualStore(props.data.length, itemSize,
|
|
1484
|
+
const { ref: _ref, data: _data, children: _children, itemSize, shift: _shift, horizontal = false, cache, onScrollEnd: _onScrollEnd, } = props;
|
|
1485
|
+
const store = createVirtualStore(props.data.length, itemSize, undefined, cache, !itemSize);
|
|
1470
1486
|
const resizer = createWindowResizer(store, horizontal);
|
|
1471
1487
|
const scroller = createWindowScroller(store, horizontal);
|
|
1472
1488
|
const [stateVersion, setRerender] = createSignal(store.$getStateVersion());
|
|
@@ -1484,7 +1500,7 @@ const WindowVirtualizer = (props) => {
|
|
|
1484
1500
|
});
|
|
1485
1501
|
const range = createMemo((prev) => {
|
|
1486
1502
|
stateVersion();
|
|
1487
|
-
const next = store.$getRange();
|
|
1503
|
+
const next = store.$getRange(props.bufferSize);
|
|
1488
1504
|
if (prev && isSameRange(prev, next)) {
|
|
1489
1505
|
return prev;
|
|
1490
1506
|
}
|