virtua 0.45.3 → 0.46.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.
- 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 +56 -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 +2 -2
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;
|
|
@@ -517,6 +526,9 @@ const createVirtualStore = (elementsCount, itemSize = 40, overscan = 4, ssrCount
|
|
|
517
526
|
}
|
|
518
527
|
case ACTION_VIEWPORT_RESIZE: {
|
|
519
528
|
if (viewportSize !== payload) {
|
|
529
|
+
if (!viewportSize) {
|
|
530
|
+
shouldSync = true;
|
|
531
|
+
}
|
|
520
532
|
viewportSize = payload;
|
|
521
533
|
mutated = UPDATE_VIRTUAL_STATE + UPDATE_SIZE_EVENT;
|
|
522
534
|
}
|
|
@@ -545,7 +557,7 @@ const createVirtualStore = (elementsCount, itemSize = 40, overscan = 4, ssrCount
|
|
|
545
557
|
break;
|
|
546
558
|
}
|
|
547
559
|
case ACTION_BEFORE_MANUAL_SMOOTH_SCROLL: {
|
|
548
|
-
_frozenRange = getRange(payload);
|
|
560
|
+
_frozenRange = getRange(payload, payload + viewportSize);
|
|
549
561
|
mutated = UPDATE_VIRTUAL_STATE;
|
|
550
562
|
break;
|
|
551
563
|
}
|
|
@@ -914,13 +926,20 @@ const createWindowScroller = (store, isHorizontal) => {
|
|
|
914
926
|
const scrollOffsetKey = isHorizontal ? "scrollX" : "scrollY";
|
|
915
927
|
const document = getCurrentDocument(container);
|
|
916
928
|
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
|
|
929
|
+
scrollObserver = createScrollObserver(store, window, isHorizontal, () => normalizeOffset(window[scrollOffsetKey], isHorizontal), (jump, shift) => {
|
|
920
930
|
// TODO support case two window scrollers exist in the same view
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
931
|
+
if (shift) {
|
|
932
|
+
// Use absolute position not to exceed scrollable bounds
|
|
933
|
+
window.scroll({
|
|
934
|
+
[scrollToKey]: store.$getScrollOffset() + jump,
|
|
935
|
+
});
|
|
936
|
+
}
|
|
937
|
+
else {
|
|
938
|
+
// Use window.scrollBy here, which causes less layout shift for some reason.
|
|
939
|
+
window.scrollBy({
|
|
940
|
+
[scrollToKey]: jump,
|
|
941
|
+
});
|
|
942
|
+
}
|
|
924
943
|
}, () => calcOffsetToViewport(container, document.body, window, isHorizontal));
|
|
925
944
|
initialized[1](true);
|
|
926
945
|
},
|
|
@@ -1287,9 +1306,9 @@ const isSameRange = (prev, next) => {
|
|
|
1287
1306
|
*/
|
|
1288
1307
|
const Virtualizer = (props) => {
|
|
1289
1308
|
let containerRef;
|
|
1290
|
-
const { itemSize, horizontal = false,
|
|
1309
|
+
const { itemSize, horizontal = false, cache } = props;
|
|
1291
1310
|
props = mergeProps({ as: "div" }, props);
|
|
1292
|
-
const store = createVirtualStore(props.data.length, itemSize,
|
|
1311
|
+
const store = createVirtualStore(props.data.length, itemSize, undefined, cache, !itemSize);
|
|
1293
1312
|
const resizer = createResizer(store, horizontal);
|
|
1294
1313
|
const scroller = createScroller(store, horizontal);
|
|
1295
1314
|
const [stateVersion, setRerender] = createSignal(store.$getStateVersion());
|
|
@@ -1306,7 +1325,7 @@ const Virtualizer = (props) => {
|
|
|
1306
1325
|
});
|
|
1307
1326
|
const range = createMemo((prev) => {
|
|
1308
1327
|
stateVersion();
|
|
1309
|
-
const next = store.$getRange();
|
|
1328
|
+
const next = store.$getRange(props.bufferSize);
|
|
1310
1329
|
if (prev && isSameRange(prev, next)) {
|
|
1311
1330
|
return prev;
|
|
1312
1331
|
}
|
|
@@ -1432,7 +1451,7 @@ const VList = (props) => {
|
|
|
1432
1451
|
"ref",
|
|
1433
1452
|
"data",
|
|
1434
1453
|
"children",
|
|
1435
|
-
"
|
|
1454
|
+
"bufferSize",
|
|
1436
1455
|
"itemSize",
|
|
1437
1456
|
"shift",
|
|
1438
1457
|
"horizontal",
|
|
@@ -1451,7 +1470,7 @@ const VList = (props) => {
|
|
|
1451
1470
|
height: "100%",
|
|
1452
1471
|
...local.style,
|
|
1453
1472
|
}}>
|
|
1454
|
-
<Virtualizer ref={local.ref} data={local.data}
|
|
1473
|
+
<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
1474
|
{local.children}
|
|
1456
1475
|
</Virtualizer>
|
|
1457
1476
|
</div>);
|
|
@@ -1465,8 +1484,8 @@ const VList = (props) => {
|
|
|
1465
1484
|
*/
|
|
1466
1485
|
const WindowVirtualizer = (props) => {
|
|
1467
1486
|
let containerRef;
|
|
1468
|
-
const { ref: _ref, data: _data, children: _children,
|
|
1469
|
-
const store = createVirtualStore(props.data.length, itemSize,
|
|
1487
|
+
const { ref: _ref, data: _data, children: _children, itemSize, shift: _shift, horizontal = false, cache, onScrollEnd: _onScrollEnd, } = props;
|
|
1488
|
+
const store = createVirtualStore(props.data.length, itemSize, undefined, cache, !itemSize);
|
|
1470
1489
|
const resizer = createWindowResizer(store, horizontal);
|
|
1471
1490
|
const scroller = createWindowScroller(store, horizontal);
|
|
1472
1491
|
const [stateVersion, setRerender] = createSignal(store.$getStateVersion());
|
|
@@ -1484,7 +1503,7 @@ const WindowVirtualizer = (props) => {
|
|
|
1484
1503
|
});
|
|
1485
1504
|
const range = createMemo((prev) => {
|
|
1486
1505
|
stateVersion();
|
|
1487
|
-
const next = store.$getRange();
|
|
1506
|
+
const next = store.$getRange(props.bufferSize);
|
|
1488
1507
|
if (prev && isSameRange(prev, next)) {
|
|
1489
1508
|
return prev;
|
|
1490
1509
|
}
|