virtua 0.40.4 → 0.41.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 +4 -2
- package/lib/solid/VList.d.ts +1 -1
- package/lib/solid/Virtualizer.d.ts +17 -3
- package/lib/solid/WindowVirtualizer.d.ts +13 -3
- package/lib/solid/index.d.ts +1 -0
- package/lib/solid/index.js +1 -1
- package/lib/solid/index.js.map +1 -1
- package/lib/solid/index.jsx +100 -83
- package/lib/solid/index.jsx.map +1 -1
- package/lib/solid/index.mjs +1 -1
- package/lib/solid/index.mjs.map +1 -1
- package/lib/solid/types.d.ts +17 -1
- package/package.json +2 -2
- package/lib/solid/RangedFor.d.ts +0 -1
package/lib/solid/index.jsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { mergeProps, createEffect, onCleanup, createMemo,
|
|
1
|
+
import { mergeProps, createEffect, onCleanup, createMemo, createSignal, onMount, createComputed, on, untrack, For, splitProps } from 'solid-js';
|
|
2
2
|
import { Dynamic } from 'solid-js/web';
|
|
3
3
|
|
|
4
4
|
/** @internal */
|
|
@@ -1272,65 +1272,11 @@ const ListItem = (props) => {
|
|
|
1272
1272
|
}
|
|
1273
1273
|
return style;
|
|
1274
1274
|
});
|
|
1275
|
-
return (<Dynamic component={props._as} ref={elementRef} style={style()}>
|
|
1275
|
+
return (<Dynamic component={props._as} index={props._index} ref={elementRef} style={style()}>
|
|
1276
1276
|
{props._children}
|
|
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,
|
|
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,48 @@ const Virtualizer = (props) => {
|
|
|
1421
1370
|
createEffect(on(stateVersion, () => {
|
|
1422
1371
|
scroller.$fixScrollJump();
|
|
1423
1372
|
}));
|
|
1373
|
+
const dataSlice = createMemo(() => {
|
|
1374
|
+
const [start, end] = range();
|
|
1375
|
+
const items = end >= 0 ? props.data.slice(start, end + 1) : [];
|
|
1376
|
+
const indexes = items.map((_, index) => start + index);
|
|
1377
|
+
if (props.keepMounted) {
|
|
1378
|
+
const startItems = [];
|
|
1379
|
+
const startIndexes = [];
|
|
1380
|
+
const endItems = [];
|
|
1381
|
+
const endIndexes = [];
|
|
1382
|
+
sort(props.keepMounted).forEach((index) => {
|
|
1383
|
+
if (index < 0 || index >= props.data.length)
|
|
1384
|
+
return;
|
|
1385
|
+
if (index < start) {
|
|
1386
|
+
startItems.push(props.data[index]);
|
|
1387
|
+
startIndexes.push(index);
|
|
1388
|
+
}
|
|
1389
|
+
if (index > end) {
|
|
1390
|
+
endItems.push(props.data[index]);
|
|
1391
|
+
endIndexes.push(index);
|
|
1392
|
+
}
|
|
1393
|
+
});
|
|
1394
|
+
items.unshift(...startItems);
|
|
1395
|
+
indexes.unshift(...startIndexes);
|
|
1396
|
+
items.push(...endItems);
|
|
1397
|
+
indexes.push(...endIndexes);
|
|
1398
|
+
}
|
|
1399
|
+
return { _items: items, _indexes: indexes };
|
|
1400
|
+
});
|
|
1401
|
+
const renderItem = (data, index) => {
|
|
1402
|
+
const offset = createMemo(() => {
|
|
1403
|
+
stateVersion();
|
|
1404
|
+
return store.$getItemOffset(index());
|
|
1405
|
+
});
|
|
1406
|
+
const hide = createMemo(() => {
|
|
1407
|
+
stateVersion();
|
|
1408
|
+
return store.$isUnmeasuredItem(index());
|
|
1409
|
+
});
|
|
1410
|
+
const children = createMemo(() => {
|
|
1411
|
+
return untrack(() => props.children(data, index));
|
|
1412
|
+
});
|
|
1413
|
+
return (<ListItem _as={props.item} _index={index()} _resizer={resizer.$observeItem} _offset={offset()} _hide={hide()} _children={children()} _isHorizontal={horizontal}/>);
|
|
1414
|
+
};
|
|
1424
1415
|
return (<Dynamic component={props.as} ref={containerRef} style={{
|
|
1425
1416
|
// contain: "content",
|
|
1426
1417
|
"overflow-anchor": "none", // opt out browser's scroll anchoring because it will conflict to scroll anchoring of virtualizer
|
|
@@ -1431,35 +1422,48 @@ const Virtualizer = (props) => {
|
|
|
1431
1422
|
height: horizontal ? "100%" : totalSize() + "px",
|
|
1432
1423
|
"pointer-events": isScrolling() ? "none" : undefined,
|
|
1433
1424
|
}}>
|
|
1434
|
-
<
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
return store.$isUnmeasuredItem(index);
|
|
1442
|
-
});
|
|
1443
|
-
return (<ListItem _as={props.item} _index={index} _resizer={resizer.$observeItem} _offset={offset()} _hide={hide()} _children={props.children(data(), index)} _isHorizontal={horizontal}/>);
|
|
1444
|
-
}}/>
|
|
1425
|
+
<For each={dataSlice()._items}>
|
|
1426
|
+
{(data, index) => {
|
|
1427
|
+
const itemIndex = createMemo(() => dataSlice()._indexes[index()]);
|
|
1428
|
+
// eslint-disable-next-line solid/reactivity
|
|
1429
|
+
return renderItem(data, itemIndex);
|
|
1430
|
+
}}
|
|
1431
|
+
</For>
|
|
1445
1432
|
</Dynamic>);
|
|
1446
1433
|
};
|
|
1447
1434
|
|
|
1435
|
+
/**
|
|
1436
|
+
* @jsxImportSource solid-js
|
|
1437
|
+
*/
|
|
1448
1438
|
/**
|
|
1449
1439
|
* Virtualized list component. See {@link VListProps} and {@link VListHandle}.
|
|
1450
1440
|
*/
|
|
1451
1441
|
const VList = (props) => {
|
|
1452
|
-
const
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1442
|
+
const [local, others] = splitProps(props, [
|
|
1443
|
+
"ref",
|
|
1444
|
+
"data",
|
|
1445
|
+
"children",
|
|
1446
|
+
"overscan",
|
|
1447
|
+
"itemSize",
|
|
1448
|
+
"shift",
|
|
1449
|
+
"horizontal",
|
|
1450
|
+
"keepMounted",
|
|
1451
|
+
"cache",
|
|
1452
|
+
"item",
|
|
1453
|
+
"onScroll",
|
|
1454
|
+
"onScrollEnd",
|
|
1455
|
+
"style",
|
|
1456
|
+
]);
|
|
1457
|
+
return (<div {...others} style={{
|
|
1458
|
+
display: local.horizontal ? "inline-block" : "block",
|
|
1459
|
+
[local.horizontal ? "overflow-x" : "overflow-y"]: "auto",
|
|
1456
1460
|
contain: "strict",
|
|
1457
1461
|
width: "100%",
|
|
1458
1462
|
height: "100%",
|
|
1459
|
-
...
|
|
1463
|
+
...local.style,
|
|
1460
1464
|
}}>
|
|
1461
|
-
<Virtualizer ref={
|
|
1462
|
-
{
|
|
1465
|
+
<Virtualizer ref={local.ref} data={local.data} overscan={local.overscan} itemSize={local.itemSize} shift={local.shift} horizontal={local.horizontal} keepMounted={local.keepMounted} cache={local.cache} item={local.item} onScroll={local.onScroll} onScrollEnd={local.onScrollEnd}>
|
|
1466
|
+
{local.children}
|
|
1463
1467
|
</Virtualizer>
|
|
1464
1468
|
</div>);
|
|
1465
1469
|
};
|
|
@@ -1472,8 +1476,8 @@ const VList = (props) => {
|
|
|
1472
1476
|
*/
|
|
1473
1477
|
const WindowVirtualizer = (props) => {
|
|
1474
1478
|
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,
|
|
1479
|
+
const { ref: _ref, data: _data, children: _children, overscan, itemSize, shift: _shift, horizontal = false, cache, onScrollEnd: _onScrollEnd, } = props;
|
|
1480
|
+
const store = createVirtualStore(props.data.length, itemSize, overscan, undefined, cache, !itemSize);
|
|
1477
1481
|
const resizer = createWindowResizer(store, horizontal);
|
|
1478
1482
|
const scroller = createWindowScroller(store, horizontal);
|
|
1479
1483
|
const [stateVersion, setRerender] = createSignal(store.$getStateVersion());
|
|
@@ -1502,6 +1506,9 @@ const WindowVirtualizer = (props) => {
|
|
|
1502
1506
|
onMount(() => {
|
|
1503
1507
|
if (props.ref) {
|
|
1504
1508
|
props.ref({
|
|
1509
|
+
get cache() {
|
|
1510
|
+
return store.$getCacheSnapshot();
|
|
1511
|
+
},
|
|
1505
1512
|
findStartIndex: store.$findStartIndex,
|
|
1506
1513
|
findEndIndex: store.$findEndIndex,
|
|
1507
1514
|
scrollToIndex: scroller.$scrollToIndex,
|
|
@@ -1528,6 +1535,10 @@ const WindowVirtualizer = (props) => {
|
|
|
1528
1535
|
createEffect(on(stateVersion, () => {
|
|
1529
1536
|
scroller.$fixScrollJump();
|
|
1530
1537
|
}));
|
|
1538
|
+
const dataSlice = createMemo(() => {
|
|
1539
|
+
const [start, end] = range();
|
|
1540
|
+
return end >= 0 ? props.data.slice(start, end + 1) : [];
|
|
1541
|
+
});
|
|
1531
1542
|
return (<div ref={containerRef} style={{
|
|
1532
1543
|
// contain: "content",
|
|
1533
1544
|
"overflow-anchor": "none", // opt out browser's scroll anchoring because it will conflict to scroll anchoring of virtualizer
|
|
@@ -1538,17 +1549,23 @@ const WindowVirtualizer = (props) => {
|
|
|
1538
1549
|
height: horizontal ? "100%" : totalSize() + "px",
|
|
1539
1550
|
"pointer-events": isScrolling() ? "none" : undefined,
|
|
1540
1551
|
}}>
|
|
1541
|
-
<
|
|
1552
|
+
<For each={dataSlice()}>
|
|
1553
|
+
{(data, index) => {
|
|
1554
|
+
const itemIndex = createMemo(() => range()[0] + index());
|
|
1542
1555
|
const offset = createMemo(() => {
|
|
1543
1556
|
stateVersion();
|
|
1544
|
-
return store.$getItemOffset(
|
|
1557
|
+
return store.$getItemOffset(itemIndex());
|
|
1545
1558
|
});
|
|
1546
1559
|
const hide = createMemo(() => {
|
|
1547
1560
|
stateVersion();
|
|
1548
|
-
return store.$isUnmeasuredItem(
|
|
1561
|
+
return store.$isUnmeasuredItem(itemIndex());
|
|
1562
|
+
});
|
|
1563
|
+
const children = createMemo(() => {
|
|
1564
|
+
return untrack(() => props.children(data, itemIndex));
|
|
1549
1565
|
});
|
|
1550
|
-
return (<ListItem _index={
|
|
1551
|
-
}}
|
|
1566
|
+
return (<ListItem _index={itemIndex()} _resizer={resizer.$observeItem} _offset={offset()} _hide={hide()} _children={children()} _isHorizontal={horizontal}/>);
|
|
1567
|
+
}}
|
|
1568
|
+
</For>
|
|
1552
1569
|
</div>);
|
|
1553
1570
|
};
|
|
1554
1571
|
|