virtua 0.40.4 → 0.41.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.
@@ -1,4 +1,4 @@
1
- import { mergeProps, createEffect, onCleanup, createMemo, createRoot, createSignal, onMount, createComputed, on } from 'solid-js';
1
+ import { mergeProps, createEffect, onCleanup, createMemo, createSignal, onMount, createComputed, on, For, untrack } from 'solid-js';
2
2
  import { Dynamic } from 'solid-js/web';
3
3
 
4
4
  /** @internal */
@@ -1277,60 +1277,6 @@ const ListItem = (props) => {
1277
1277
  </Dynamic>);
1278
1278
  };
1279
1279
 
1280
- /**
1281
- * @jsxImportSource solid-js
1282
- */
1283
- /**
1284
- * https://github.com/solidjs/solid/blob/main/packages/solid/src/reactive/array.ts
1285
- * https://github.com/solidjs/solid/blob/main/packages/solid/src/render/flow.ts
1286
- * https://github.com/solidjs/solid/discussions/366
1287
- * @internal
1288
- */
1289
- const RangedFor = (props) => {
1290
- let prev = new Map();
1291
- onCleanup(() => {
1292
- for (const node of prev.values()) {
1293
- node._dispose();
1294
- }
1295
- });
1296
- return createMemo(() => {
1297
- const list = props._each;
1298
- const [start, end] = props._range;
1299
- const current = new Map();
1300
- const items = [];
1301
- for (let i = start; i <= end; i++) {
1302
- const newData = list[i];
1303
- const lookup = prev.get(i);
1304
- items.push(lookup
1305
- ? lookup._element
1306
- : createRoot((dispose) => {
1307
- const data = createSignal(newData);
1308
- const result = props._render(data[0], i);
1309
- current.set(i, {
1310
- _data: data,
1311
- _element: result,
1312
- _dispose: dispose,
1313
- });
1314
- return result;
1315
- }));
1316
- if (lookup) {
1317
- if (newData !== lookup._data) {
1318
- lookup._data[1](newData // TODO improve type
1319
- );
1320
- }
1321
- current.set(i, lookup);
1322
- }
1323
- }
1324
- for (const [key, node] of prev.entries()) {
1325
- if (!current.has(key)) {
1326
- node._dispose();
1327
- }
1328
- }
1329
- prev = current;
1330
- return items;
1331
- }); // TODO improve type
1332
- };
1333
-
1334
1280
  /**
1335
1281
  * @internal
1336
1282
  */
@@ -1346,9 +1292,9 @@ const isSameRange = (prev, next) => {
1346
1292
  */
1347
1293
  const Virtualizer = (props) => {
1348
1294
  let containerRef;
1349
- const { itemSize, horizontal = false, overscan } = props;
1295
+ const { itemSize, horizontal = false, overscan, cache } = props;
1350
1296
  props = mergeProps({ as: "div" }, props);
1351
- const store = createVirtualStore(props.data.length, itemSize, overscan, undefined, undefined, !itemSize);
1297
+ const store = createVirtualStore(props.data.length, itemSize, overscan, undefined, cache, !itemSize);
1352
1298
  const resizer = createResizer(store, horizontal);
1353
1299
  const scroller = createScroller(store, horizontal);
1354
1300
  const [stateVersion, setRerender] = createSignal(store.$getStateVersion());
@@ -1376,6 +1322,9 @@ const Virtualizer = (props) => {
1376
1322
  onMount(() => {
1377
1323
  if (props.ref) {
1378
1324
  props.ref({
1325
+ get cache() {
1326
+ return store.$getCacheSnapshot();
1327
+ },
1379
1328
  get scrollOffset() {
1380
1329
  return store.$getScrollOffset();
1381
1330
  },
@@ -1421,6 +1370,10 @@ const Virtualizer = (props) => {
1421
1370
  createEffect(on(stateVersion, () => {
1422
1371
  scroller.$fixScrollJump();
1423
1372
  }));
1373
+ const dataSlice = createMemo(() => {
1374
+ const [start, end] = range();
1375
+ return end >= 0 ? props.data.slice(start, end + 1) : [];
1376
+ });
1424
1377
  return (<Dynamic component={props.as} ref={containerRef} style={{
1425
1378
  // contain: "content",
1426
1379
  "overflow-anchor": "none", // opt out browser's scroll anchoring because it will conflict to scroll anchoring of virtualizer
@@ -1431,17 +1384,23 @@ const Virtualizer = (props) => {
1431
1384
  height: horizontal ? "100%" : totalSize() + "px",
1432
1385
  "pointer-events": isScrolling() ? "none" : undefined,
1433
1386
  }}>
1434
- <RangedFor _each={props.data} _range={range()} _render={(data, index) => {
1387
+ <For each={dataSlice()}>
1388
+ {(data, index) => {
1389
+ const itemIndex = createMemo(() => range()[0] + index());
1435
1390
  const offset = createMemo(() => {
1436
1391
  stateVersion();
1437
- return store.$getItemOffset(index);
1392
+ return store.$getItemOffset(itemIndex());
1438
1393
  });
1439
1394
  const hide = createMemo(() => {
1440
1395
  stateVersion();
1441
- return store.$isUnmeasuredItem(index);
1396
+ return store.$isUnmeasuredItem(itemIndex());
1397
+ });
1398
+ const children = createMemo(() => {
1399
+ return untrack(() => props.children(data, itemIndex));
1442
1400
  });
1443
- return (<ListItem _as={props.item} _index={index} _resizer={resizer.$observeItem} _offset={offset()} _hide={hide()} _children={props.children(data(), index)} _isHorizontal={horizontal}/>);
1444
- }}/>
1401
+ return (<ListItem _as={props.item} _index={itemIndex()} _resizer={resizer.$observeItem} _offset={offset()} _hide={hide()} _children={children()} _isHorizontal={horizontal}/>);
1402
+ }}
1403
+ </For>
1445
1404
  </Dynamic>);
1446
1405
  };
1447
1406
 
@@ -1449,7 +1408,7 @@ const Virtualizer = (props) => {
1449
1408
  * Virtualized list component. See {@link VListProps} and {@link VListHandle}.
1450
1409
  */
1451
1410
  const VList = (props) => {
1452
- const { ref, data, children, overscan, itemSize, shift, horizontal, onScroll, onScrollEnd, style, ...attrs } = props;
1411
+ const { ref, data, children, overscan, itemSize, shift, horizontal, cache, onScroll, onScrollEnd, style, ...attrs } = props;
1453
1412
  return (<div {...attrs} style={{
1454
1413
  display: horizontal ? "inline-block" : "block",
1455
1414
  [horizontal ? "overflow-x" : "overflow-y"]: "auto",
@@ -1458,7 +1417,7 @@ const VList = (props) => {
1458
1417
  height: "100%",
1459
1418
  ...props.style,
1460
1419
  }}>
1461
- <Virtualizer ref={props.ref} data={props.data} overscan={props.overscan} itemSize={props.itemSize} shift={props.shift} horizontal={horizontal} onScroll={props.onScroll} onScrollEnd={props.onScrollEnd}>
1420
+ <Virtualizer ref={props.ref} data={props.data} overscan={props.overscan} itemSize={props.itemSize} shift={props.shift} horizontal={horizontal} cache={cache} onScroll={props.onScroll} onScrollEnd={props.onScrollEnd}>
1462
1421
  {props.children}
1463
1422
  </Virtualizer>
1464
1423
  </div>);
@@ -1472,8 +1431,8 @@ const VList = (props) => {
1472
1431
  */
1473
1432
  const WindowVirtualizer = (props) => {
1474
1433
  let containerRef;
1475
- const { ref: _ref, data: _data, children: _children, overscan, itemSize, shift: _shift, horizontal = false, onScrollEnd: _onScrollEnd, } = props;
1476
- const store = createVirtualStore(props.data.length, itemSize, overscan, undefined, undefined, !itemSize);
1434
+ const { ref: _ref, data: _data, children: _children, overscan, itemSize, shift: _shift, horizontal = false, cache, onScrollEnd: _onScrollEnd, } = props;
1435
+ const store = createVirtualStore(props.data.length, itemSize, overscan, undefined, cache, !itemSize);
1477
1436
  const resizer = createWindowResizer(store, horizontal);
1478
1437
  const scroller = createWindowScroller(store, horizontal);
1479
1438
  const [stateVersion, setRerender] = createSignal(store.$getStateVersion());
@@ -1502,6 +1461,9 @@ const WindowVirtualizer = (props) => {
1502
1461
  onMount(() => {
1503
1462
  if (props.ref) {
1504
1463
  props.ref({
1464
+ get cache() {
1465
+ return store.$getCacheSnapshot();
1466
+ },
1505
1467
  findStartIndex: store.$findStartIndex,
1506
1468
  findEndIndex: store.$findEndIndex,
1507
1469
  scrollToIndex: scroller.$scrollToIndex,
@@ -1528,6 +1490,10 @@ const WindowVirtualizer = (props) => {
1528
1490
  createEffect(on(stateVersion, () => {
1529
1491
  scroller.$fixScrollJump();
1530
1492
  }));
1493
+ const dataSlice = createMemo(() => {
1494
+ const [start, end] = range();
1495
+ return end >= 0 ? props.data.slice(start, end + 1) : [];
1496
+ });
1531
1497
  return (<div ref={containerRef} style={{
1532
1498
  // contain: "content",
1533
1499
  "overflow-anchor": "none", // opt out browser's scroll anchoring because it will conflict to scroll anchoring of virtualizer
@@ -1538,17 +1504,23 @@ const WindowVirtualizer = (props) => {
1538
1504
  height: horizontal ? "100%" : totalSize() + "px",
1539
1505
  "pointer-events": isScrolling() ? "none" : undefined,
1540
1506
  }}>
1541
- <RangedFor _each={props.data} _range={range()} _render={(data, index) => {
1507
+ <For each={dataSlice()}>
1508
+ {(data, index) => {
1509
+ const itemIndex = createMemo(() => range()[0] + index());
1542
1510
  const offset = createMemo(() => {
1543
1511
  stateVersion();
1544
- return store.$getItemOffset(index);
1512
+ return store.$getItemOffset(itemIndex());
1545
1513
  });
1546
1514
  const hide = createMemo(() => {
1547
1515
  stateVersion();
1548
- return store.$isUnmeasuredItem(index);
1516
+ return store.$isUnmeasuredItem(itemIndex());
1517
+ });
1518
+ const children = createMemo(() => {
1519
+ return untrack(() => props.children(data, itemIndex));
1549
1520
  });
1550
- return (<ListItem _index={index} _resizer={resizer.$observeItem} _offset={offset()} _hide={hide()} _children={props.children(data(), index)} _isHorizontal={horizontal}/>);
1551
- }}/>
1521
+ return (<ListItem _index={itemIndex()} _resizer={resizer.$observeItem} _offset={offset()} _hide={hide()} _children={children()} _isHorizontal={horizontal}/>);
1522
+ }}
1523
+ </For>
1552
1524
  </div>);
1553
1525
  };
1554
1526