virtua 0.40.0 → 0.40.2

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.
@@ -246,6 +246,7 @@ const isSmoothScrollSupported = /*#__PURE__*/ once(() => {
246
246
  return "scrollBehavior" in getDocumentElement().style;
247
247
  });
248
248
 
249
+ const MAX_INT_32 = 0x7fffffff;
249
250
  const SCROLL_IDLE = 0;
250
251
  const SCROLL_DOWN = 1;
251
252
  const SCROLL_UP = 2;
@@ -293,11 +294,10 @@ const isInitialMeasurementDone = (store) => {
293
294
  */
294
295
  const createVirtualStore = (elementsCount, itemSize = 40, overscan = 4, ssrCount = 0, cacheSnapshot, shouldAutoEstimateItemSize = false) => {
295
296
  let isSSR = !!ssrCount;
296
- let stateVersion = [];
297
+ let stateVersion = 1;
297
298
  let viewportSize = 0;
298
299
  let startSpacerSize = 0;
299
300
  let scrollOffset = 0;
300
- let jumpCount = 0;
301
301
  let jump = 0;
302
302
  let pendingJump = 0;
303
303
  let _flushedJump = 0;
@@ -330,7 +330,6 @@ const createVirtualStore = (elementsCount, itemSize = 40, overscan = 4, ssrCount
330
330
  }
331
331
  else {
332
332
  jump += j;
333
- jumpCount++;
334
333
  }
335
334
  }
336
335
  };
@@ -340,14 +339,19 @@ const createVirtualStore = (elementsCount, itemSize = 40, overscan = 4, ssrCount
340
339
  return takeCacheSnapshot(cache);
341
340
  },
342
341
  $getRange: () => {
343
- // Return previous range for consistent render until next scroll event comes in.
342
+ let startIndex;
343
+ let endIndex;
344
344
  if (_flushedJump) {
345
- return _prevRange;
345
+ // Return previous range for consistent render until next scroll event comes in.
346
+ // And it must be clamped. https://github.com/inokawa/virtua/issues/597
347
+ [startIndex, endIndex] = _prevRange;
346
348
  }
347
- let [startIndex, endIndex] = getRange(max(0, getVisibleOffset()));
348
- if (_frozenRange) {
349
- startIndex = min(startIndex, _frozenRange[0]);
350
- endIndex = max(endIndex, _frozenRange[1]);
349
+ else {
350
+ [startIndex, endIndex] = _prevRange = getRange(max(0, getVisibleOffset()));
351
+ if (_frozenRange) {
352
+ startIndex = min(startIndex, _frozenRange[0]);
353
+ endIndex = max(endIndex, _frozenRange[1]);
354
+ }
351
355
  }
352
356
  if (_scrollDirection !== SCROLL_DOWN) {
353
357
  startIndex -= max(0, overscan);
@@ -355,10 +359,7 @@ const createVirtualStore = (elementsCount, itemSize = 40, overscan = 4, ssrCount
355
359
  if (_scrollDirection !== SCROLL_UP) {
356
360
  endIndex += max(0, overscan);
357
361
  }
358
- return (_prevRange = [
359
- max(startIndex, 0),
360
- min(endIndex, cache._length - 1),
361
- ]);
362
+ return [max(startIndex, 0), min(endIndex, cache._length - 1)];
362
363
  },
363
364
  $findStartIndex: () => findIndex(cache, getVisibleOffset()),
364
365
  $findEndIndex: () => findIndex(cache, getVisibleOffset() + viewportSize),
@@ -378,7 +379,6 @@ const createVirtualStore = (elementsCount, itemSize = 40, overscan = 4, ssrCount
378
379
  $getViewportSize: () => viewportSize,
379
380
  $getStartSpacerSize: () => startSpacerSize,
380
381
  $getTotalSize: getTotalSize,
381
- $getJumpCount: () => jumpCount,
382
382
  _flushJump: () => {
383
383
  _flushedJump = jump;
384
384
  jump = 0;
@@ -547,11 +547,10 @@ const createVirtualStore = (elementsCount, itemSize = 40, overscan = 4, ssrCount
547
547
  }
548
548
  }
549
549
  if (mutated) {
550
- stateVersion = [];
550
+ stateVersion = (stateVersion % MAX_INT_32) + 1;
551
551
  if (shouldFlushPendingJump && pendingJump) {
552
552
  jump += pendingJump;
553
553
  pendingJump = 0;
554
- jumpCount++;
555
554
  }
556
555
  subscribers.forEach(([target, cb]) => {
557
556
  // Early return to skip React's computation
@@ -1352,7 +1351,7 @@ const Virtualizer = (props) => {
1352
1351
  const store = createVirtualStore(props.data.length, itemSize, overscan, undefined, undefined, !itemSize);
1353
1352
  const resizer = createResizer(store, horizontal);
1354
1353
  const scroller = createScroller(store, horizontal);
1355
- const [rerender, setRerender] = createSignal(store.$getStateVersion());
1354
+ const [stateVersion, setRerender] = createSignal(store.$getStateVersion());
1356
1355
  const unsubscribeStore = store.$subscribe(UPDATE_VIRTUAL_STATE, () => {
1357
1356
  setRerender(store.$getStateVersion());
1358
1357
  });
@@ -1365,16 +1364,15 @@ const Virtualizer = (props) => {
1365
1364
  (_a = props.onScrollEnd) === null || _a === void 0 ? void 0 : _a.call(props);
1366
1365
  });
1367
1366
  const range = createMemo((prev) => {
1368
- rerender();
1367
+ stateVersion();
1369
1368
  const next = store.$getRange();
1370
1369
  if (prev && isSameRange(prev, next)) {
1371
1370
  return prev;
1372
1371
  }
1373
1372
  return next;
1374
1373
  });
1375
- const isScrolling = createMemo(() => rerender() && store.$isScrolling());
1376
- const totalSize = createMemo(() => rerender() && store.$getTotalSize());
1377
- const jumpCount = createMemo(() => rerender() && store.$getJumpCount());
1374
+ const isScrolling = createMemo(() => stateVersion() && store.$isScrolling());
1375
+ const totalSize = createMemo(() => stateVersion() && store.$getTotalSize());
1378
1376
  onMount(() => {
1379
1377
  if (props.ref) {
1380
1378
  props.ref({
@@ -1420,7 +1418,7 @@ const Virtualizer = (props) => {
1420
1418
  store.$update(ACTION_START_OFFSET_CHANGE, value);
1421
1419
  }
1422
1420
  }));
1423
- createEffect(on(jumpCount, () => {
1421
+ createEffect(on(stateVersion, () => {
1424
1422
  scroller.$fixScrollJump();
1425
1423
  }));
1426
1424
  return (<Dynamic component={props.as} ref={containerRef} style={{
@@ -1435,11 +1433,11 @@ const Virtualizer = (props) => {
1435
1433
  }}>
1436
1434
  <RangedFor _each={props.data} _range={range()} _render={(data, index) => {
1437
1435
  const offset = createMemo(() => {
1438
- rerender();
1436
+ stateVersion();
1439
1437
  return store.$getItemOffset(index);
1440
1438
  });
1441
1439
  const hide = createMemo(() => {
1442
- rerender();
1440
+ stateVersion();
1443
1441
  return store.$isUnmeasuredItem(index);
1444
1442
  });
1445
1443
  return (<ListItem _as={props.item} _index={index} _resizer={resizer.$observeItem} _offset={offset()} _hide={hide()} _children={props.children(data(), index)} _isHorizontal={horizontal}/>);
@@ -1478,7 +1476,7 @@ const WindowVirtualizer = (props) => {
1478
1476
  const store = createVirtualStore(props.data.length, itemSize, overscan, undefined, undefined, !itemSize);
1479
1477
  const resizer = createWindowResizer(store, horizontal);
1480
1478
  const scroller = createWindowScroller(store, horizontal);
1481
- const [rerender, setRerender] = createSignal(store.$getStateVersion());
1479
+ const [stateVersion, setRerender] = createSignal(store.$getStateVersion());
1482
1480
  const unsubscribeStore = store.$subscribe(UPDATE_VIRTUAL_STATE, () => {
1483
1481
  setRerender(store.$getStateVersion());
1484
1482
  });
@@ -1492,16 +1490,15 @@ const WindowVirtualizer = (props) => {
1492
1490
  (_a = props.onScrollEnd) === null || _a === void 0 ? void 0 : _a.call(props);
1493
1491
  });
1494
1492
  const range = createMemo((prev) => {
1495
- rerender();
1493
+ stateVersion();
1496
1494
  const next = store.$getRange();
1497
1495
  if (prev && isSameRange(prev, next)) {
1498
1496
  return prev;
1499
1497
  }
1500
1498
  return next;
1501
1499
  });
1502
- const isScrolling = createMemo(() => rerender() && store.$isScrolling());
1503
- const totalSize = createMemo(() => rerender() && store.$getTotalSize());
1504
- const jumpCount = createMemo(() => rerender() && store.$getJumpCount());
1500
+ const isScrolling = createMemo(() => stateVersion() && store.$isScrolling());
1501
+ const totalSize = createMemo(() => stateVersion() && store.$getTotalSize());
1505
1502
  onMount(() => {
1506
1503
  if (props.ref) {
1507
1504
  props.ref({
@@ -1528,7 +1525,7 @@ const WindowVirtualizer = (props) => {
1528
1525
  store.$update(ACTION_ITEMS_LENGTH_CHANGE, [len, props.shift]);
1529
1526
  }
1530
1527
  }));
1531
- createEffect(on(jumpCount, () => {
1528
+ createEffect(on(stateVersion, () => {
1532
1529
  scroller.$fixScrollJump();
1533
1530
  }));
1534
1531
  return (<div ref={containerRef} style={{
@@ -1543,11 +1540,11 @@ const WindowVirtualizer = (props) => {
1543
1540
  }}>
1544
1541
  <RangedFor _each={props.data} _range={range()} _render={(data, index) => {
1545
1542
  const offset = createMemo(() => {
1546
- rerender();
1543
+ stateVersion();
1547
1544
  return store.$getItemOffset(index);
1548
1545
  });
1549
1546
  const hide = createMemo(() => {
1550
- rerender();
1547
+ stateVersion();
1551
1548
  return store.$isUnmeasuredItem(index);
1552
1549
  });
1553
1550
  return (<ListItem _index={index} _resizer={resizer.$observeItem} _offset={offset()} _hide={hide()} _children={props.children(data(), index)} _isHorizontal={horizontal}/>);