@legendapp/list 1.0.6 → 1.0.8
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/index.js +200 -103
- package/index.mjs +200 -103
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -46,15 +46,42 @@ function StateProvider({ children }) {
|
|
|
46
46
|
function useStateContext() {
|
|
47
47
|
return React2__namespace.useContext(ContextState);
|
|
48
48
|
}
|
|
49
|
-
function
|
|
49
|
+
function createSelectorFunctionsArr(ctx, signalNames) {
|
|
50
|
+
let lastValues = [];
|
|
51
|
+
let lastSignalValues = [];
|
|
50
52
|
return {
|
|
51
|
-
subscribe: (cb) =>
|
|
52
|
-
|
|
53
|
+
subscribe: (cb) => {
|
|
54
|
+
const listeners = [];
|
|
55
|
+
for (const signalName of signalNames) {
|
|
56
|
+
listeners.push(listen$(ctx, signalName, cb));
|
|
57
|
+
}
|
|
58
|
+
return () => {
|
|
59
|
+
for (const listener of listeners) {
|
|
60
|
+
listener();
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
},
|
|
64
|
+
get: () => {
|
|
65
|
+
const currentValues = [];
|
|
66
|
+
let hasChanged = false;
|
|
67
|
+
for (let i = 0; i < signalNames.length; i++) {
|
|
68
|
+
const value = peek$(ctx, signalNames[i]);
|
|
69
|
+
currentValues.push(value);
|
|
70
|
+
if (value !== lastSignalValues[i]) {
|
|
71
|
+
hasChanged = true;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
lastSignalValues = currentValues;
|
|
75
|
+
if (hasChanged) {
|
|
76
|
+
lastValues = currentValues;
|
|
77
|
+
}
|
|
78
|
+
return lastValues;
|
|
79
|
+
}
|
|
53
80
|
};
|
|
54
81
|
}
|
|
55
|
-
function
|
|
82
|
+
function useArr$(signalNames) {
|
|
56
83
|
const ctx = React2__namespace.useContext(ContextState);
|
|
57
|
-
const { subscribe, get } = React2__namespace.useMemo(() =>
|
|
84
|
+
const { subscribe, get } = React2__namespace.useMemo(() => createSelectorFunctionsArr(ctx, signalNames), [ctx, signalNames]);
|
|
58
85
|
const value = React2.useSyncExternalStore(subscribe, get);
|
|
59
86
|
return value;
|
|
60
87
|
}
|
|
@@ -99,15 +126,25 @@ var DebugRow = ({ children }) => {
|
|
|
99
126
|
};
|
|
100
127
|
var DebugView = React2__namespace.memo(function DebugView2({ state }) {
|
|
101
128
|
const ctx = useStateContext();
|
|
102
|
-
const
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
129
|
+
const [
|
|
130
|
+
totalSize = 0,
|
|
131
|
+
totalSizeWithScrollAdjust = 0,
|
|
132
|
+
scrollAdjust = 0,
|
|
133
|
+
rawScroll = 0,
|
|
134
|
+
scroll = 0,
|
|
135
|
+
numContainers = 0,
|
|
136
|
+
numContainersPooled = 0
|
|
137
|
+
] = useArr$([
|
|
138
|
+
"totalSize",
|
|
139
|
+
"totalSizeWithScrollAdjust",
|
|
140
|
+
"scrollAdjust",
|
|
141
|
+
"debugRawScroll",
|
|
142
|
+
"debugComputedScroll",
|
|
143
|
+
"numContainers",
|
|
144
|
+
"numContainersPooled"
|
|
145
|
+
]);
|
|
107
146
|
const contentSize = getContentSize(ctx);
|
|
108
147
|
const [, forceUpdate] = React2.useReducer((x) => x + 1, 0);
|
|
109
|
-
use$("numContainers");
|
|
110
|
-
use$("numContainersPooled");
|
|
111
148
|
useInterval(() => {
|
|
112
149
|
forceUpdate();
|
|
113
150
|
}, 100);
|
|
@@ -162,6 +199,12 @@ function roundSize(size) {
|
|
|
162
199
|
function isNullOrUndefined(value) {
|
|
163
200
|
return value === null || value === void 0;
|
|
164
201
|
}
|
|
202
|
+
function comparatorByDistance(a, b) {
|
|
203
|
+
return b.distance - a.distance;
|
|
204
|
+
}
|
|
205
|
+
function comparatorDefault(a, b) {
|
|
206
|
+
return a - b;
|
|
207
|
+
}
|
|
165
208
|
var symbolFirst = Symbol();
|
|
166
209
|
function useInit(cb) {
|
|
167
210
|
const refValue = React2.useRef(symbolFirst);
|
|
@@ -285,14 +328,25 @@ var Container = ({
|
|
|
285
328
|
}) => {
|
|
286
329
|
const ctx = useStateContext();
|
|
287
330
|
const columnWrapperStyle = ctx.columnWrapperStyle;
|
|
288
|
-
const
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
331
|
+
const [
|
|
332
|
+
maintainVisibleContentPosition,
|
|
333
|
+
position = ANCHORED_POSITION_OUT_OF_VIEW,
|
|
334
|
+
column = 0,
|
|
335
|
+
numColumns,
|
|
336
|
+
lastItemKeys,
|
|
337
|
+
itemKey,
|
|
338
|
+
data,
|
|
339
|
+
extraData
|
|
340
|
+
] = useArr$([
|
|
341
|
+
"maintainVisibleContentPosition",
|
|
342
|
+
`containerPosition${id}`,
|
|
343
|
+
`containerColumn${id}`,
|
|
344
|
+
"numColumns",
|
|
345
|
+
"lastItemKeys",
|
|
346
|
+
`containerItemKey${id}`,
|
|
347
|
+
`containerItemData${id}`,
|
|
348
|
+
"extraData"
|
|
349
|
+
]);
|
|
296
350
|
const refLastSize = React2.useRef();
|
|
297
351
|
const ref = React2.useRef(null);
|
|
298
352
|
const [layoutRenderCount, forceLayoutRender] = React2.useState(0);
|
|
@@ -390,11 +444,11 @@ var Container = ({
|
|
|
390
444
|
const contentFragment = /* @__PURE__ */ React2__namespace.default.createElement(React2__namespace.default.Fragment, { key: recycleItems ? void 0 : itemKey }, /* @__PURE__ */ React2__namespace.default.createElement(ContextContainer.Provider, { value: contextValue }, renderedItem, renderedItemInfo && ItemSeparatorComponent && !lastItemKeys.includes(itemKey) && /* @__PURE__ */ React2__namespace.default.createElement(ItemSeparatorComponent, { leadingItem: renderedItemInfo.item })));
|
|
391
445
|
if (maintainVisibleContentPosition) {
|
|
392
446
|
const anchorStyle = position.type === "top" ? { position: "absolute", top: 0, left: 0, right: 0 } : { position: "absolute", bottom: 0, left: 0, right: 0 };
|
|
393
|
-
if (ENABLE_DEVMODE) {
|
|
447
|
+
if (__DEV__ && ENABLE_DEVMODE) {
|
|
394
448
|
anchorStyle.borderColor = position.type === "top" ? "red" : "blue";
|
|
395
449
|
anchorStyle.borderWidth = 1;
|
|
396
450
|
}
|
|
397
|
-
return /* @__PURE__ */ React2__namespace.default.createElement(LeanView, { style }, /* @__PURE__ */ React2__namespace.default.createElement(LeanView, { style: anchorStyle, onLayout, ref }, contentFragment, ENABLE_DEVMODE && /* @__PURE__ */ React2__namespace.default.createElement(reactNative.Text, { style: { position: "absolute", top: 0, left: 0, zIndex: 1e3 } }, position.top)));
|
|
451
|
+
return /* @__PURE__ */ React2__namespace.default.createElement(LeanView, { style }, /* @__PURE__ */ React2__namespace.default.createElement(LeanView, { style: anchorStyle, onLayout, ref }, contentFragment, __DEV__ && ENABLE_DEVMODE && /* @__PURE__ */ React2__namespace.default.createElement(reactNative.Text, { style: { position: "absolute", top: 0, left: 0, zIndex: 1e3 } }, position.top)));
|
|
398
452
|
}
|
|
399
453
|
return /* @__PURE__ */ React2__namespace.default.createElement(LeanView, { style, onLayout, ref }, contentFragment);
|
|
400
454
|
};
|
|
@@ -438,7 +492,7 @@ var Containers = typedMemo(function Containers2({
|
|
|
438
492
|
}) {
|
|
439
493
|
const ctx = useStateContext();
|
|
440
494
|
const columnWrapperStyle = ctx.columnWrapperStyle;
|
|
441
|
-
const numContainers =
|
|
495
|
+
const [numContainers] = useArr$(["numContainersPooled"]);
|
|
442
496
|
const animSize = useValue$(
|
|
443
497
|
"totalSizeWithScrollAdjust",
|
|
444
498
|
void 0,
|
|
@@ -1035,10 +1089,10 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
1035
1089
|
isAtTop: false,
|
|
1036
1090
|
data: dataProp,
|
|
1037
1091
|
scrollLength: initialScrollLength,
|
|
1038
|
-
startBuffered:
|
|
1039
|
-
startNoBuffer:
|
|
1040
|
-
endBuffered:
|
|
1041
|
-
endNoBuffer:
|
|
1092
|
+
startBuffered: -1,
|
|
1093
|
+
startNoBuffer: -1,
|
|
1094
|
+
endBuffered: -1,
|
|
1095
|
+
endNoBuffer: -1,
|
|
1042
1096
|
scroll: initialContentOffset || 0,
|
|
1043
1097
|
totalSize: 0,
|
|
1044
1098
|
totalSizeBelowAnchor: 0,
|
|
@@ -1353,14 +1407,14 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
1353
1407
|
const topPad = peek$(ctx, "stylePaddingTop") + peek$(ctx, "headerSize");
|
|
1354
1408
|
const numColumns = peek$(ctx, "numColumns");
|
|
1355
1409
|
const previousScrollAdjust = scrollAdjustHandler.getAppliedAdjust();
|
|
1356
|
-
const scrollExtra = Math.max(-16, Math.min(16, speed)) * 16;
|
|
1357
1410
|
let scrollState = state.scroll;
|
|
1411
|
+
const scrollExtra = Math.max(-16, Math.min(16, speed)) * 24;
|
|
1358
1412
|
const useAverageSize = !state.disableScrollJumpsFrom && speed >= 0 && peek$(ctx, "containersDidLayout");
|
|
1359
1413
|
if (!state.queuedInitialLayout && initialScrollIndex) {
|
|
1360
1414
|
const updatedOffset = calculateOffsetForIndex(initialScrollIndex);
|
|
1361
1415
|
scrollState = updatedOffset;
|
|
1362
1416
|
}
|
|
1363
|
-
let scroll = scrollState - previousScrollAdjust - topPad;
|
|
1417
|
+
let scroll = scrollState + scrollExtra - previousScrollAdjust - topPad;
|
|
1364
1418
|
if (scroll + scrollLength > totalSize) {
|
|
1365
1419
|
scroll = totalSize - scrollLength;
|
|
1366
1420
|
}
|
|
@@ -1370,13 +1424,13 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
1370
1424
|
}
|
|
1371
1425
|
let scrollBufferTop = scrollBuffer;
|
|
1372
1426
|
let scrollBufferBottom = scrollBuffer;
|
|
1373
|
-
if (
|
|
1374
|
-
scrollBufferTop = 0;
|
|
1375
|
-
scrollBufferBottom = scrollBuffer
|
|
1427
|
+
if (speed > 0) {
|
|
1428
|
+
scrollBufferTop = scrollBuffer * 0.1;
|
|
1429
|
+
scrollBufferBottom = scrollBuffer * 1.9;
|
|
1376
1430
|
}
|
|
1377
|
-
if (
|
|
1378
|
-
scrollBufferTop = scrollBuffer
|
|
1379
|
-
scrollBufferBottom = 0;
|
|
1431
|
+
if (speed < 0) {
|
|
1432
|
+
scrollBufferTop = scrollBuffer * 1.9;
|
|
1433
|
+
scrollBufferBottom = scrollBuffer * 0.1;
|
|
1380
1434
|
}
|
|
1381
1435
|
if (state.scrollForNextCalculateItemsInView) {
|
|
1382
1436
|
const { top: top2, bottom } = state.scrollForNextCalculateItemsInView;
|
|
@@ -1385,7 +1439,6 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
1385
1439
|
}
|
|
1386
1440
|
}
|
|
1387
1441
|
const scrollBottom = scroll + scrollLength;
|
|
1388
|
-
const prevEndBuffered = state.endBuffered;
|
|
1389
1442
|
let startNoBuffer = null;
|
|
1390
1443
|
let startBuffered = null;
|
|
1391
1444
|
let startBufferedId = null;
|
|
@@ -1437,7 +1490,17 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
1437
1490
|
return topOffset;
|
|
1438
1491
|
};
|
|
1439
1492
|
let foundEnd = false;
|
|
1440
|
-
|
|
1493
|
+
let lastSize;
|
|
1494
|
+
const prevNumContainers = ctx.values.get("numContainers");
|
|
1495
|
+
let maxIndexRendered = 0;
|
|
1496
|
+
for (let i = 0; i < prevNumContainers; i++) {
|
|
1497
|
+
const key = peek$(ctx, `containerItemKey${i}`);
|
|
1498
|
+
if (key !== void 0) {
|
|
1499
|
+
const index = state.indexByKey.get(key);
|
|
1500
|
+
maxIndexRendered = Math.max(maxIndexRendered, index);
|
|
1501
|
+
}
|
|
1502
|
+
}
|
|
1503
|
+
for (let i = Math.max(0, loopStart); i < data.length && (!foundEnd || i <= maxIndexRendered); i++) {
|
|
1441
1504
|
const id = getId(i);
|
|
1442
1505
|
const size = getItemSize(id, i, data[i], useAverageSize);
|
|
1443
1506
|
maxSizeInRow = Math.max(maxSizeInRow, size);
|
|
@@ -1464,6 +1527,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
1464
1527
|
}
|
|
1465
1528
|
if (top <= scrollBottom + scrollBufferBottom) {
|
|
1466
1529
|
endBuffered = i;
|
|
1530
|
+
lastSize = maxSizeInRow;
|
|
1467
1531
|
} else {
|
|
1468
1532
|
foundEnd = true;
|
|
1469
1533
|
}
|
|
@@ -1476,6 +1540,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
1476
1540
|
maxSizeInRow = 0;
|
|
1477
1541
|
}
|
|
1478
1542
|
}
|
|
1543
|
+
const prevStartBuffered = state.startBuffered;
|
|
1544
|
+
const prevEndBuffered = state.endBuffered;
|
|
1479
1545
|
Object.assign(state, {
|
|
1480
1546
|
startBuffered,
|
|
1481
1547
|
startBufferedId,
|
|
@@ -1483,83 +1549,64 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
1483
1549
|
endBuffered,
|
|
1484
1550
|
endNoBuffer
|
|
1485
1551
|
});
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1552
|
+
if (state.enableScrollForNextCalculateItemsInView && lastSize) {
|
|
1553
|
+
const aboveFirst = startBuffered - 1;
|
|
1554
|
+
let nextTop = 0;
|
|
1555
|
+
if (aboveFirst >= 0) {
|
|
1556
|
+
const aboveFirstSize = getItemSize(getId(aboveFirst), aboveFirst, data[aboveFirst], useAverageSize);
|
|
1557
|
+
nextTop = scroll - aboveFirstSize;
|
|
1558
|
+
}
|
|
1559
|
+
const nextBottom = scroll + lastSize;
|
|
1491
1560
|
state.scrollForNextCalculateItemsInView = nextTop >= 0 && nextBottom >= 0 ? {
|
|
1492
1561
|
top: nextTop,
|
|
1493
1562
|
bottom: nextBottom
|
|
1494
1563
|
} : void 0;
|
|
1495
1564
|
}
|
|
1496
1565
|
if (startBuffered !== null && endBuffered !== null) {
|
|
1497
|
-
const prevNumContainers = ctx.values.get("numContainers");
|
|
1498
1566
|
let numContainers = prevNumContainers;
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
isContained = true;
|
|
1508
|
-
break;
|
|
1509
|
-
}
|
|
1510
|
-
}
|
|
1511
|
-
if (!isContained) {
|
|
1512
|
-
const top2 = positions.get(id) || 0;
|
|
1513
|
-
let furthestIndex = -1;
|
|
1514
|
-
let furthestDistance = 0;
|
|
1515
|
-
for (let u = 0; u < numContainers; u++) {
|
|
1516
|
-
if (allocatedContainers.has(u)) {
|
|
1517
|
-
continue;
|
|
1518
|
-
}
|
|
1519
|
-
const key = peek$(ctx, `containerItemKey${u}`);
|
|
1520
|
-
if (key === void 0) {
|
|
1521
|
-
furthestIndex = u;
|
|
1522
|
-
break;
|
|
1523
|
-
}
|
|
1524
|
-
const index2 = state.indexByKey.get(key);
|
|
1525
|
-
const pos = peek$(ctx, `containerPosition${u}`).top;
|
|
1526
|
-
if (isNullOrUndefined(index2) || pos === POSITION_OUT_OF_VIEW) {
|
|
1527
|
-
furthestIndex = u;
|
|
1528
|
-
break;
|
|
1529
|
-
}
|
|
1530
|
-
if (index2 < startBuffered || index2 > endBuffered) {
|
|
1531
|
-
const distance = Math.abs(pos - top2);
|
|
1532
|
-
if (index2 < 0 || pos === POSITION_OUT_OF_VIEW || distance > furthestDistance) {
|
|
1533
|
-
furthestDistance = distance;
|
|
1534
|
-
furthestIndex = u;
|
|
1535
|
-
}
|
|
1567
|
+
const needNewContainers = [];
|
|
1568
|
+
if (startBuffered < prevStartBuffered || endBuffered > prevEndBuffered) {
|
|
1569
|
+
const isContained = (i) => {
|
|
1570
|
+
const id = getId(i);
|
|
1571
|
+
for (let j = 0; j < numContainers; j++) {
|
|
1572
|
+
const key = peek$(ctx, `containerItemKey${j}`);
|
|
1573
|
+
if (key === id) {
|
|
1574
|
+
return true;
|
|
1536
1575
|
}
|
|
1537
1576
|
}
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
set$(ctx, `containerItemData${containerId}`, data[index2]);
|
|
1548
|
-
set$(ctx, `containerPosition${containerId}`, ANCHORED_POSITION_OUT_OF_VIEW);
|
|
1549
|
-
set$(ctx, `containerColumn${containerId}`, -1);
|
|
1550
|
-
if (__DEV__ && !didWarnMoreContainers && numContainers > peek$(ctx, "numContainersPooled")) {
|
|
1551
|
-
didWarnMoreContainers = true;
|
|
1552
|
-
console.warn(
|
|
1553
|
-
"[legend-list] No container to recycle, so creating one on demand. This can be a minor performance issue and is likely caused by the estimatedItemSize being too large. Consider decreasing estimatedItemSize or increasing initialContainerPoolRatio."
|
|
1554
|
-
);
|
|
1555
|
-
}
|
|
1577
|
+
};
|
|
1578
|
+
for (let i = startBuffered; i < prevStartBuffered; i++) {
|
|
1579
|
+
if (!isContained(i)) {
|
|
1580
|
+
needNewContainers.push(i);
|
|
1581
|
+
}
|
|
1582
|
+
}
|
|
1583
|
+
for (let i = Math.max(prevEndBuffered + 1, startBuffered); i <= endBuffered; i++) {
|
|
1584
|
+
if (!isContained(i)) {
|
|
1585
|
+
needNewContainers.push(i);
|
|
1556
1586
|
}
|
|
1557
1587
|
}
|
|
1558
1588
|
}
|
|
1559
|
-
if (
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1589
|
+
if (needNewContainers.length > 0) {
|
|
1590
|
+
const availableContainers = findAvailableContainers(
|
|
1591
|
+
needNewContainers.length,
|
|
1592
|
+
startBuffered,
|
|
1593
|
+
endBuffered
|
|
1594
|
+
);
|
|
1595
|
+
for (let idx = 0; idx < needNewContainers.length; idx++) {
|
|
1596
|
+
const i = needNewContainers[idx];
|
|
1597
|
+
const containerIndex = availableContainers[idx];
|
|
1598
|
+
const id = getId(i);
|
|
1599
|
+
set$(ctx, `containerItemKey${containerIndex}`, id);
|
|
1600
|
+
set$(ctx, `containerItemData${containerIndex}`, data[i]);
|
|
1601
|
+
if (containerIndex >= numContainers) {
|
|
1602
|
+
numContainers = containerIndex + 1;
|
|
1603
|
+
}
|
|
1604
|
+
}
|
|
1605
|
+
if (numContainers !== prevNumContainers) {
|
|
1606
|
+
set$(ctx, "numContainers", numContainers);
|
|
1607
|
+
if (numContainers > peek$(ctx, "numContainersPooled")) {
|
|
1608
|
+
set$(ctx, "numContainersPooled", Math.ceil(numContainers * 1.5));
|
|
1609
|
+
}
|
|
1563
1610
|
}
|
|
1564
1611
|
}
|
|
1565
1612
|
for (let i = 0; i < numContainers; i++) {
|
|
@@ -1589,7 +1636,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
1589
1636
|
const prevPos = peek$(ctx, `containerPosition${i}`);
|
|
1590
1637
|
const prevColumn = peek$(ctx, `containerColumn${i}`);
|
|
1591
1638
|
const prevData = peek$(ctx, `containerItemData${i}`);
|
|
1592
|
-
if (pos.relativeCoordinate > POSITION_OUT_OF_VIEW && pos.top !== prevPos.top) {
|
|
1639
|
+
if (!prevPos || pos.relativeCoordinate > POSITION_OUT_OF_VIEW && pos.top !== prevPos.top) {
|
|
1593
1640
|
set$(ctx, `containerPosition${i}`, pos);
|
|
1594
1641
|
}
|
|
1595
1642
|
if (column2 >= 0 && column2 !== prevColumn) {
|
|
@@ -1881,6 +1928,56 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
1881
1928
|
});
|
|
1882
1929
|
addTotalSize(null, totalSize, totalSizeBelowIndex);
|
|
1883
1930
|
};
|
|
1931
|
+
const findAvailableContainers = (numNeeded, startBuffered, endBuffered) => {
|
|
1932
|
+
const state = refState.current;
|
|
1933
|
+
const numContainers = peek$(ctx, "numContainers");
|
|
1934
|
+
if (numNeeded === 0) return [];
|
|
1935
|
+
const result = [];
|
|
1936
|
+
const availableContainers = [];
|
|
1937
|
+
for (let u = 0; u < numContainers; u++) {
|
|
1938
|
+
const key = peek$(ctx, `containerItemKey${u}`);
|
|
1939
|
+
if (key === void 0) {
|
|
1940
|
+
result.push(u);
|
|
1941
|
+
if (result.length >= numNeeded) {
|
|
1942
|
+
return result;
|
|
1943
|
+
}
|
|
1944
|
+
}
|
|
1945
|
+
}
|
|
1946
|
+
for (let u = 0; u < numContainers; u++) {
|
|
1947
|
+
const key = peek$(ctx, `containerItemKey${u}`);
|
|
1948
|
+
if (key === void 0) continue;
|
|
1949
|
+
const index = state.indexByKey.get(key);
|
|
1950
|
+
if (index < startBuffered) {
|
|
1951
|
+
availableContainers.push({ index: u, distance: startBuffered - index });
|
|
1952
|
+
} else if (index > endBuffered) {
|
|
1953
|
+
availableContainers.push({ index: u, distance: index - endBuffered });
|
|
1954
|
+
}
|
|
1955
|
+
}
|
|
1956
|
+
const remaining = numNeeded - result.length;
|
|
1957
|
+
if (remaining > 0) {
|
|
1958
|
+
if (availableContainers.length > 0) {
|
|
1959
|
+
if (availableContainers.length > remaining) {
|
|
1960
|
+
availableContainers.sort(comparatorByDistance);
|
|
1961
|
+
availableContainers.length = remaining;
|
|
1962
|
+
}
|
|
1963
|
+
for (const container of availableContainers) {
|
|
1964
|
+
result.push(container.index);
|
|
1965
|
+
}
|
|
1966
|
+
}
|
|
1967
|
+
const stillNeeded = numNeeded - result.length;
|
|
1968
|
+
if (stillNeeded > 0) {
|
|
1969
|
+
for (let i = 0; i < stillNeeded; i++) {
|
|
1970
|
+
result.push(numContainers + i);
|
|
1971
|
+
}
|
|
1972
|
+
if (__DEV__ && numContainers + stillNeeded > peek$(ctx, "numContainersPooled")) {
|
|
1973
|
+
console.warn(
|
|
1974
|
+
"[legend-list] No container to recycle, so creating one on demand. This can be a minor performance issue and is likely caused by the estimatedItemSize being too large. Consider decreasing estimatedItemSize or increasing initialContainerPoolRatio."
|
|
1975
|
+
);
|
|
1976
|
+
}
|
|
1977
|
+
}
|
|
1978
|
+
}
|
|
1979
|
+
return result.sort(comparatorDefault);
|
|
1980
|
+
};
|
|
1884
1981
|
const isFirst = !refState.current.renderItem;
|
|
1885
1982
|
const memoizedLastItemKeys = React2.useMemo(() => {
|
|
1886
1983
|
if (!dataProp.length) return [];
|
package/index.mjs
CHANGED
|
@@ -25,15 +25,42 @@ function StateProvider({ children }) {
|
|
|
25
25
|
function useStateContext() {
|
|
26
26
|
return React2.useContext(ContextState);
|
|
27
27
|
}
|
|
28
|
-
function
|
|
28
|
+
function createSelectorFunctionsArr(ctx, signalNames) {
|
|
29
|
+
let lastValues = [];
|
|
30
|
+
let lastSignalValues = [];
|
|
29
31
|
return {
|
|
30
|
-
subscribe: (cb) =>
|
|
31
|
-
|
|
32
|
+
subscribe: (cb) => {
|
|
33
|
+
const listeners = [];
|
|
34
|
+
for (const signalName of signalNames) {
|
|
35
|
+
listeners.push(listen$(ctx, signalName, cb));
|
|
36
|
+
}
|
|
37
|
+
return () => {
|
|
38
|
+
for (const listener of listeners) {
|
|
39
|
+
listener();
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
},
|
|
43
|
+
get: () => {
|
|
44
|
+
const currentValues = [];
|
|
45
|
+
let hasChanged = false;
|
|
46
|
+
for (let i = 0; i < signalNames.length; i++) {
|
|
47
|
+
const value = peek$(ctx, signalNames[i]);
|
|
48
|
+
currentValues.push(value);
|
|
49
|
+
if (value !== lastSignalValues[i]) {
|
|
50
|
+
hasChanged = true;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
lastSignalValues = currentValues;
|
|
54
|
+
if (hasChanged) {
|
|
55
|
+
lastValues = currentValues;
|
|
56
|
+
}
|
|
57
|
+
return lastValues;
|
|
58
|
+
}
|
|
32
59
|
};
|
|
33
60
|
}
|
|
34
|
-
function
|
|
61
|
+
function useArr$(signalNames) {
|
|
35
62
|
const ctx = React2.useContext(ContextState);
|
|
36
|
-
const { subscribe, get } = React2.useMemo(() =>
|
|
63
|
+
const { subscribe, get } = React2.useMemo(() => createSelectorFunctionsArr(ctx, signalNames), [ctx, signalNames]);
|
|
37
64
|
const value = useSyncExternalStore(subscribe, get);
|
|
38
65
|
return value;
|
|
39
66
|
}
|
|
@@ -78,15 +105,25 @@ var DebugRow = ({ children }) => {
|
|
|
78
105
|
};
|
|
79
106
|
var DebugView = React2.memo(function DebugView2({ state }) {
|
|
80
107
|
const ctx = useStateContext();
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
108
|
+
const [
|
|
109
|
+
totalSize = 0,
|
|
110
|
+
totalSizeWithScrollAdjust = 0,
|
|
111
|
+
scrollAdjust = 0,
|
|
112
|
+
rawScroll = 0,
|
|
113
|
+
scroll = 0,
|
|
114
|
+
numContainers = 0,
|
|
115
|
+
numContainersPooled = 0
|
|
116
|
+
] = useArr$([
|
|
117
|
+
"totalSize",
|
|
118
|
+
"totalSizeWithScrollAdjust",
|
|
119
|
+
"scrollAdjust",
|
|
120
|
+
"debugRawScroll",
|
|
121
|
+
"debugComputedScroll",
|
|
122
|
+
"numContainers",
|
|
123
|
+
"numContainersPooled"
|
|
124
|
+
]);
|
|
86
125
|
const contentSize = getContentSize(ctx);
|
|
87
126
|
const [, forceUpdate] = useReducer((x) => x + 1, 0);
|
|
88
|
-
use$("numContainers");
|
|
89
|
-
use$("numContainersPooled");
|
|
90
127
|
useInterval(() => {
|
|
91
128
|
forceUpdate();
|
|
92
129
|
}, 100);
|
|
@@ -141,6 +178,12 @@ function roundSize(size) {
|
|
|
141
178
|
function isNullOrUndefined(value) {
|
|
142
179
|
return value === null || value === void 0;
|
|
143
180
|
}
|
|
181
|
+
function comparatorByDistance(a, b) {
|
|
182
|
+
return b.distance - a.distance;
|
|
183
|
+
}
|
|
184
|
+
function comparatorDefault(a, b) {
|
|
185
|
+
return a - b;
|
|
186
|
+
}
|
|
144
187
|
var symbolFirst = Symbol();
|
|
145
188
|
function useInit(cb) {
|
|
146
189
|
const refValue = useRef(symbolFirst);
|
|
@@ -264,14 +307,25 @@ var Container = ({
|
|
|
264
307
|
}) => {
|
|
265
308
|
const ctx = useStateContext();
|
|
266
309
|
const columnWrapperStyle = ctx.columnWrapperStyle;
|
|
267
|
-
const
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
310
|
+
const [
|
|
311
|
+
maintainVisibleContentPosition,
|
|
312
|
+
position = ANCHORED_POSITION_OUT_OF_VIEW,
|
|
313
|
+
column = 0,
|
|
314
|
+
numColumns,
|
|
315
|
+
lastItemKeys,
|
|
316
|
+
itemKey,
|
|
317
|
+
data,
|
|
318
|
+
extraData
|
|
319
|
+
] = useArr$([
|
|
320
|
+
"maintainVisibleContentPosition",
|
|
321
|
+
`containerPosition${id}`,
|
|
322
|
+
`containerColumn${id}`,
|
|
323
|
+
"numColumns",
|
|
324
|
+
"lastItemKeys",
|
|
325
|
+
`containerItemKey${id}`,
|
|
326
|
+
`containerItemData${id}`,
|
|
327
|
+
"extraData"
|
|
328
|
+
]);
|
|
275
329
|
const refLastSize = useRef();
|
|
276
330
|
const ref = useRef(null);
|
|
277
331
|
const [layoutRenderCount, forceLayoutRender] = useState(0);
|
|
@@ -369,11 +423,11 @@ var Container = ({
|
|
|
369
423
|
const contentFragment = /* @__PURE__ */ React2__default.createElement(React2__default.Fragment, { key: recycleItems ? void 0 : itemKey }, /* @__PURE__ */ React2__default.createElement(ContextContainer.Provider, { value: contextValue }, renderedItem, renderedItemInfo && ItemSeparatorComponent && !lastItemKeys.includes(itemKey) && /* @__PURE__ */ React2__default.createElement(ItemSeparatorComponent, { leadingItem: renderedItemInfo.item })));
|
|
370
424
|
if (maintainVisibleContentPosition) {
|
|
371
425
|
const anchorStyle = position.type === "top" ? { position: "absolute", top: 0, left: 0, right: 0 } : { position: "absolute", bottom: 0, left: 0, right: 0 };
|
|
372
|
-
if (ENABLE_DEVMODE) {
|
|
426
|
+
if (__DEV__ && ENABLE_DEVMODE) {
|
|
373
427
|
anchorStyle.borderColor = position.type === "top" ? "red" : "blue";
|
|
374
428
|
anchorStyle.borderWidth = 1;
|
|
375
429
|
}
|
|
376
|
-
return /* @__PURE__ */ React2__default.createElement(LeanView, { style }, /* @__PURE__ */ React2__default.createElement(LeanView, { style: anchorStyle, onLayout, ref }, contentFragment, ENABLE_DEVMODE && /* @__PURE__ */ React2__default.createElement(Text, { style: { position: "absolute", top: 0, left: 0, zIndex: 1e3 } }, position.top)));
|
|
430
|
+
return /* @__PURE__ */ React2__default.createElement(LeanView, { style }, /* @__PURE__ */ React2__default.createElement(LeanView, { style: anchorStyle, onLayout, ref }, contentFragment, __DEV__ && ENABLE_DEVMODE && /* @__PURE__ */ React2__default.createElement(Text, { style: { position: "absolute", top: 0, left: 0, zIndex: 1e3 } }, position.top)));
|
|
377
431
|
}
|
|
378
432
|
return /* @__PURE__ */ React2__default.createElement(LeanView, { style, onLayout, ref }, contentFragment);
|
|
379
433
|
};
|
|
@@ -417,7 +471,7 @@ var Containers = typedMemo(function Containers2({
|
|
|
417
471
|
}) {
|
|
418
472
|
const ctx = useStateContext();
|
|
419
473
|
const columnWrapperStyle = ctx.columnWrapperStyle;
|
|
420
|
-
const numContainers =
|
|
474
|
+
const [numContainers] = useArr$(["numContainersPooled"]);
|
|
421
475
|
const animSize = useValue$(
|
|
422
476
|
"totalSizeWithScrollAdjust",
|
|
423
477
|
void 0,
|
|
@@ -1014,10 +1068,10 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
1014
1068
|
isAtTop: false,
|
|
1015
1069
|
data: dataProp,
|
|
1016
1070
|
scrollLength: initialScrollLength,
|
|
1017
|
-
startBuffered:
|
|
1018
|
-
startNoBuffer:
|
|
1019
|
-
endBuffered:
|
|
1020
|
-
endNoBuffer:
|
|
1071
|
+
startBuffered: -1,
|
|
1072
|
+
startNoBuffer: -1,
|
|
1073
|
+
endBuffered: -1,
|
|
1074
|
+
endNoBuffer: -1,
|
|
1021
1075
|
scroll: initialContentOffset || 0,
|
|
1022
1076
|
totalSize: 0,
|
|
1023
1077
|
totalSizeBelowAnchor: 0,
|
|
@@ -1332,14 +1386,14 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
1332
1386
|
const topPad = peek$(ctx, "stylePaddingTop") + peek$(ctx, "headerSize");
|
|
1333
1387
|
const numColumns = peek$(ctx, "numColumns");
|
|
1334
1388
|
const previousScrollAdjust = scrollAdjustHandler.getAppliedAdjust();
|
|
1335
|
-
const scrollExtra = Math.max(-16, Math.min(16, speed)) * 16;
|
|
1336
1389
|
let scrollState = state.scroll;
|
|
1390
|
+
const scrollExtra = Math.max(-16, Math.min(16, speed)) * 24;
|
|
1337
1391
|
const useAverageSize = !state.disableScrollJumpsFrom && speed >= 0 && peek$(ctx, "containersDidLayout");
|
|
1338
1392
|
if (!state.queuedInitialLayout && initialScrollIndex) {
|
|
1339
1393
|
const updatedOffset = calculateOffsetForIndex(initialScrollIndex);
|
|
1340
1394
|
scrollState = updatedOffset;
|
|
1341
1395
|
}
|
|
1342
|
-
let scroll = scrollState - previousScrollAdjust - topPad;
|
|
1396
|
+
let scroll = scrollState + scrollExtra - previousScrollAdjust - topPad;
|
|
1343
1397
|
if (scroll + scrollLength > totalSize) {
|
|
1344
1398
|
scroll = totalSize - scrollLength;
|
|
1345
1399
|
}
|
|
@@ -1349,13 +1403,13 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
1349
1403
|
}
|
|
1350
1404
|
let scrollBufferTop = scrollBuffer;
|
|
1351
1405
|
let scrollBufferBottom = scrollBuffer;
|
|
1352
|
-
if (
|
|
1353
|
-
scrollBufferTop = 0;
|
|
1354
|
-
scrollBufferBottom = scrollBuffer
|
|
1406
|
+
if (speed > 0) {
|
|
1407
|
+
scrollBufferTop = scrollBuffer * 0.1;
|
|
1408
|
+
scrollBufferBottom = scrollBuffer * 1.9;
|
|
1355
1409
|
}
|
|
1356
|
-
if (
|
|
1357
|
-
scrollBufferTop = scrollBuffer
|
|
1358
|
-
scrollBufferBottom = 0;
|
|
1410
|
+
if (speed < 0) {
|
|
1411
|
+
scrollBufferTop = scrollBuffer * 1.9;
|
|
1412
|
+
scrollBufferBottom = scrollBuffer * 0.1;
|
|
1359
1413
|
}
|
|
1360
1414
|
if (state.scrollForNextCalculateItemsInView) {
|
|
1361
1415
|
const { top: top2, bottom } = state.scrollForNextCalculateItemsInView;
|
|
@@ -1364,7 +1418,6 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
1364
1418
|
}
|
|
1365
1419
|
}
|
|
1366
1420
|
const scrollBottom = scroll + scrollLength;
|
|
1367
|
-
const prevEndBuffered = state.endBuffered;
|
|
1368
1421
|
let startNoBuffer = null;
|
|
1369
1422
|
let startBuffered = null;
|
|
1370
1423
|
let startBufferedId = null;
|
|
@@ -1416,7 +1469,17 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
1416
1469
|
return topOffset;
|
|
1417
1470
|
};
|
|
1418
1471
|
let foundEnd = false;
|
|
1419
|
-
|
|
1472
|
+
let lastSize;
|
|
1473
|
+
const prevNumContainers = ctx.values.get("numContainers");
|
|
1474
|
+
let maxIndexRendered = 0;
|
|
1475
|
+
for (let i = 0; i < prevNumContainers; i++) {
|
|
1476
|
+
const key = peek$(ctx, `containerItemKey${i}`);
|
|
1477
|
+
if (key !== void 0) {
|
|
1478
|
+
const index = state.indexByKey.get(key);
|
|
1479
|
+
maxIndexRendered = Math.max(maxIndexRendered, index);
|
|
1480
|
+
}
|
|
1481
|
+
}
|
|
1482
|
+
for (let i = Math.max(0, loopStart); i < data.length && (!foundEnd || i <= maxIndexRendered); i++) {
|
|
1420
1483
|
const id = getId(i);
|
|
1421
1484
|
const size = getItemSize(id, i, data[i], useAverageSize);
|
|
1422
1485
|
maxSizeInRow = Math.max(maxSizeInRow, size);
|
|
@@ -1443,6 +1506,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
1443
1506
|
}
|
|
1444
1507
|
if (top <= scrollBottom + scrollBufferBottom) {
|
|
1445
1508
|
endBuffered = i;
|
|
1509
|
+
lastSize = maxSizeInRow;
|
|
1446
1510
|
} else {
|
|
1447
1511
|
foundEnd = true;
|
|
1448
1512
|
}
|
|
@@ -1455,6 +1519,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
1455
1519
|
maxSizeInRow = 0;
|
|
1456
1520
|
}
|
|
1457
1521
|
}
|
|
1522
|
+
const prevStartBuffered = state.startBuffered;
|
|
1523
|
+
const prevEndBuffered = state.endBuffered;
|
|
1458
1524
|
Object.assign(state, {
|
|
1459
1525
|
startBuffered,
|
|
1460
1526
|
startBufferedId,
|
|
@@ -1462,83 +1528,64 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
1462
1528
|
endBuffered,
|
|
1463
1529
|
endNoBuffer
|
|
1464
1530
|
});
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1531
|
+
if (state.enableScrollForNextCalculateItemsInView && lastSize) {
|
|
1532
|
+
const aboveFirst = startBuffered - 1;
|
|
1533
|
+
let nextTop = 0;
|
|
1534
|
+
if (aboveFirst >= 0) {
|
|
1535
|
+
const aboveFirstSize = getItemSize(getId(aboveFirst), aboveFirst, data[aboveFirst], useAverageSize);
|
|
1536
|
+
nextTop = scroll - aboveFirstSize;
|
|
1537
|
+
}
|
|
1538
|
+
const nextBottom = scroll + lastSize;
|
|
1470
1539
|
state.scrollForNextCalculateItemsInView = nextTop >= 0 && nextBottom >= 0 ? {
|
|
1471
1540
|
top: nextTop,
|
|
1472
1541
|
bottom: nextBottom
|
|
1473
1542
|
} : void 0;
|
|
1474
1543
|
}
|
|
1475
1544
|
if (startBuffered !== null && endBuffered !== null) {
|
|
1476
|
-
const prevNumContainers = ctx.values.get("numContainers");
|
|
1477
1545
|
let numContainers = prevNumContainers;
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
isContained = true;
|
|
1487
|
-
break;
|
|
1488
|
-
}
|
|
1489
|
-
}
|
|
1490
|
-
if (!isContained) {
|
|
1491
|
-
const top2 = positions.get(id) || 0;
|
|
1492
|
-
let furthestIndex = -1;
|
|
1493
|
-
let furthestDistance = 0;
|
|
1494
|
-
for (let u = 0; u < numContainers; u++) {
|
|
1495
|
-
if (allocatedContainers.has(u)) {
|
|
1496
|
-
continue;
|
|
1497
|
-
}
|
|
1498
|
-
const key = peek$(ctx, `containerItemKey${u}`);
|
|
1499
|
-
if (key === void 0) {
|
|
1500
|
-
furthestIndex = u;
|
|
1501
|
-
break;
|
|
1502
|
-
}
|
|
1503
|
-
const index2 = state.indexByKey.get(key);
|
|
1504
|
-
const pos = peek$(ctx, `containerPosition${u}`).top;
|
|
1505
|
-
if (isNullOrUndefined(index2) || pos === POSITION_OUT_OF_VIEW) {
|
|
1506
|
-
furthestIndex = u;
|
|
1507
|
-
break;
|
|
1508
|
-
}
|
|
1509
|
-
if (index2 < startBuffered || index2 > endBuffered) {
|
|
1510
|
-
const distance = Math.abs(pos - top2);
|
|
1511
|
-
if (index2 < 0 || pos === POSITION_OUT_OF_VIEW || distance > furthestDistance) {
|
|
1512
|
-
furthestDistance = distance;
|
|
1513
|
-
furthestIndex = u;
|
|
1514
|
-
}
|
|
1546
|
+
const needNewContainers = [];
|
|
1547
|
+
if (startBuffered < prevStartBuffered || endBuffered > prevEndBuffered) {
|
|
1548
|
+
const isContained = (i) => {
|
|
1549
|
+
const id = getId(i);
|
|
1550
|
+
for (let j = 0; j < numContainers; j++) {
|
|
1551
|
+
const key = peek$(ctx, `containerItemKey${j}`);
|
|
1552
|
+
if (key === id) {
|
|
1553
|
+
return true;
|
|
1515
1554
|
}
|
|
1516
1555
|
}
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
set$(ctx, `containerItemData${containerId}`, data[index2]);
|
|
1527
|
-
set$(ctx, `containerPosition${containerId}`, ANCHORED_POSITION_OUT_OF_VIEW);
|
|
1528
|
-
set$(ctx, `containerColumn${containerId}`, -1);
|
|
1529
|
-
if (__DEV__ && !didWarnMoreContainers && numContainers > peek$(ctx, "numContainersPooled")) {
|
|
1530
|
-
didWarnMoreContainers = true;
|
|
1531
|
-
console.warn(
|
|
1532
|
-
"[legend-list] No container to recycle, so creating one on demand. This can be a minor performance issue and is likely caused by the estimatedItemSize being too large. Consider decreasing estimatedItemSize or increasing initialContainerPoolRatio."
|
|
1533
|
-
);
|
|
1534
|
-
}
|
|
1556
|
+
};
|
|
1557
|
+
for (let i = startBuffered; i < prevStartBuffered; i++) {
|
|
1558
|
+
if (!isContained(i)) {
|
|
1559
|
+
needNewContainers.push(i);
|
|
1560
|
+
}
|
|
1561
|
+
}
|
|
1562
|
+
for (let i = Math.max(prevEndBuffered + 1, startBuffered); i <= endBuffered; i++) {
|
|
1563
|
+
if (!isContained(i)) {
|
|
1564
|
+
needNewContainers.push(i);
|
|
1535
1565
|
}
|
|
1536
1566
|
}
|
|
1537
1567
|
}
|
|
1538
|
-
if (
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1568
|
+
if (needNewContainers.length > 0) {
|
|
1569
|
+
const availableContainers = findAvailableContainers(
|
|
1570
|
+
needNewContainers.length,
|
|
1571
|
+
startBuffered,
|
|
1572
|
+
endBuffered
|
|
1573
|
+
);
|
|
1574
|
+
for (let idx = 0; idx < needNewContainers.length; idx++) {
|
|
1575
|
+
const i = needNewContainers[idx];
|
|
1576
|
+
const containerIndex = availableContainers[idx];
|
|
1577
|
+
const id = getId(i);
|
|
1578
|
+
set$(ctx, `containerItemKey${containerIndex}`, id);
|
|
1579
|
+
set$(ctx, `containerItemData${containerIndex}`, data[i]);
|
|
1580
|
+
if (containerIndex >= numContainers) {
|
|
1581
|
+
numContainers = containerIndex + 1;
|
|
1582
|
+
}
|
|
1583
|
+
}
|
|
1584
|
+
if (numContainers !== prevNumContainers) {
|
|
1585
|
+
set$(ctx, "numContainers", numContainers);
|
|
1586
|
+
if (numContainers > peek$(ctx, "numContainersPooled")) {
|
|
1587
|
+
set$(ctx, "numContainersPooled", Math.ceil(numContainers * 1.5));
|
|
1588
|
+
}
|
|
1542
1589
|
}
|
|
1543
1590
|
}
|
|
1544
1591
|
for (let i = 0; i < numContainers; i++) {
|
|
@@ -1568,7 +1615,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
1568
1615
|
const prevPos = peek$(ctx, `containerPosition${i}`);
|
|
1569
1616
|
const prevColumn = peek$(ctx, `containerColumn${i}`);
|
|
1570
1617
|
const prevData = peek$(ctx, `containerItemData${i}`);
|
|
1571
|
-
if (pos.relativeCoordinate > POSITION_OUT_OF_VIEW && pos.top !== prevPos.top) {
|
|
1618
|
+
if (!prevPos || pos.relativeCoordinate > POSITION_OUT_OF_VIEW && pos.top !== prevPos.top) {
|
|
1572
1619
|
set$(ctx, `containerPosition${i}`, pos);
|
|
1573
1620
|
}
|
|
1574
1621
|
if (column2 >= 0 && column2 !== prevColumn) {
|
|
@@ -1860,6 +1907,56 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
1860
1907
|
});
|
|
1861
1908
|
addTotalSize(null, totalSize, totalSizeBelowIndex);
|
|
1862
1909
|
};
|
|
1910
|
+
const findAvailableContainers = (numNeeded, startBuffered, endBuffered) => {
|
|
1911
|
+
const state = refState.current;
|
|
1912
|
+
const numContainers = peek$(ctx, "numContainers");
|
|
1913
|
+
if (numNeeded === 0) return [];
|
|
1914
|
+
const result = [];
|
|
1915
|
+
const availableContainers = [];
|
|
1916
|
+
for (let u = 0; u < numContainers; u++) {
|
|
1917
|
+
const key = peek$(ctx, `containerItemKey${u}`);
|
|
1918
|
+
if (key === void 0) {
|
|
1919
|
+
result.push(u);
|
|
1920
|
+
if (result.length >= numNeeded) {
|
|
1921
|
+
return result;
|
|
1922
|
+
}
|
|
1923
|
+
}
|
|
1924
|
+
}
|
|
1925
|
+
for (let u = 0; u < numContainers; u++) {
|
|
1926
|
+
const key = peek$(ctx, `containerItemKey${u}`);
|
|
1927
|
+
if (key === void 0) continue;
|
|
1928
|
+
const index = state.indexByKey.get(key);
|
|
1929
|
+
if (index < startBuffered) {
|
|
1930
|
+
availableContainers.push({ index: u, distance: startBuffered - index });
|
|
1931
|
+
} else if (index > endBuffered) {
|
|
1932
|
+
availableContainers.push({ index: u, distance: index - endBuffered });
|
|
1933
|
+
}
|
|
1934
|
+
}
|
|
1935
|
+
const remaining = numNeeded - result.length;
|
|
1936
|
+
if (remaining > 0) {
|
|
1937
|
+
if (availableContainers.length > 0) {
|
|
1938
|
+
if (availableContainers.length > remaining) {
|
|
1939
|
+
availableContainers.sort(comparatorByDistance);
|
|
1940
|
+
availableContainers.length = remaining;
|
|
1941
|
+
}
|
|
1942
|
+
for (const container of availableContainers) {
|
|
1943
|
+
result.push(container.index);
|
|
1944
|
+
}
|
|
1945
|
+
}
|
|
1946
|
+
const stillNeeded = numNeeded - result.length;
|
|
1947
|
+
if (stillNeeded > 0) {
|
|
1948
|
+
for (let i = 0; i < stillNeeded; i++) {
|
|
1949
|
+
result.push(numContainers + i);
|
|
1950
|
+
}
|
|
1951
|
+
if (__DEV__ && numContainers + stillNeeded > peek$(ctx, "numContainersPooled")) {
|
|
1952
|
+
console.warn(
|
|
1953
|
+
"[legend-list] No container to recycle, so creating one on demand. This can be a minor performance issue and is likely caused by the estimatedItemSize being too large. Consider decreasing estimatedItemSize or increasing initialContainerPoolRatio."
|
|
1954
|
+
);
|
|
1955
|
+
}
|
|
1956
|
+
}
|
|
1957
|
+
}
|
|
1958
|
+
return result.sort(comparatorDefault);
|
|
1959
|
+
};
|
|
1863
1960
|
const isFirst = !refState.current.renderItem;
|
|
1864
1961
|
const memoizedLastItemKeys = useMemo(() => {
|
|
1865
1962
|
if (!dataProp.length) return [];
|
package/package.json
CHANGED