@legendapp/list 3.0.0-beta.30 → 3.0.0-beta.32
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/.DS_Store +0 -0
- package/index.d.mts +10 -3
- package/index.d.ts +10 -3
- package/index.js +335 -239
- package/index.mjs +335 -239
- package/index.native.d.mts +10 -3
- package/index.native.d.ts +10 -3
- package/index.native.js +286 -206
- package/index.native.mjs +288 -208
- package/package.json +1 -1
- package/section-list.d.mts +1 -1
- package/section-list.d.ts +1 -1
- package/section-list.native.d.mts +1 -1
- package/section-list.native.d.ts +1 -1
package/index.js
CHANGED
|
@@ -42,7 +42,7 @@ function getContentInsetEnd(state) {
|
|
|
42
42
|
const baseInset = contentInset != null ? contentInset : state.nativeContentInset;
|
|
43
43
|
const overrideInset = (_a3 = state.contentInsetOverride) != null ? _a3 : void 0;
|
|
44
44
|
if (overrideInset) {
|
|
45
|
-
const mergedInset = { bottom: 0,
|
|
45
|
+
const mergedInset = { bottom: 0, right: 0, ...baseInset, ...overrideInset };
|
|
46
46
|
return (horizontal ? mergedInset.right : mergedInset.bottom) || 0;
|
|
47
47
|
}
|
|
48
48
|
if (baseInset) {
|
|
@@ -193,7 +193,7 @@ function useSelector$(signalName, selector) {
|
|
|
193
193
|
var DebugRow = ({ children }) => {
|
|
194
194
|
return /* @__PURE__ */ React3__namespace.createElement(View, { style: { alignItems: "center", flexDirection: "row", justifyContent: "space-between" } }, children);
|
|
195
195
|
};
|
|
196
|
-
|
|
196
|
+
React3__namespace.memo(function DebugView2({ state }) {
|
|
197
197
|
const ctx = useStateContext();
|
|
198
198
|
const [totalSize = 0, scrollAdjust = 0, rawScroll = 0, scroll = 0, _numContainers = 0, _numContainersPooled = 0] = useArr$([
|
|
199
199
|
"totalSize",
|
|
@@ -358,9 +358,6 @@ var PositionViewSticky = typedMemo(function PositionViewSticky2({
|
|
|
358
358
|
return /* @__PURE__ */ React3__namespace.createElement("div", { ref: refView, style: viewStyle, ...rest }, children);
|
|
359
359
|
});
|
|
360
360
|
var PositionView = PositionViewState;
|
|
361
|
-
|
|
362
|
-
// src/constants-platform.ts
|
|
363
|
-
var IsNewArchitecture = true;
|
|
364
361
|
function useInit(cb) {
|
|
365
362
|
React3.useState(() => cb());
|
|
366
363
|
}
|
|
@@ -571,7 +568,8 @@ function createResizeObserver(element, callback) {
|
|
|
571
568
|
function useOnLayoutSync({
|
|
572
569
|
ref,
|
|
573
570
|
onLayoutProp,
|
|
574
|
-
onLayoutChange
|
|
571
|
+
onLayoutChange,
|
|
572
|
+
webLayoutResync
|
|
575
573
|
}, deps) {
|
|
576
574
|
React3.useLayoutEffect(() => {
|
|
577
575
|
var _a3, _b;
|
|
@@ -595,7 +593,9 @@ function useOnLayoutSync({
|
|
|
595
593
|
var _a4;
|
|
596
594
|
const target = entry.target instanceof HTMLElement ? entry.target : void 0;
|
|
597
595
|
const rectObserved = (_a4 = entry.contentRect) != null ? _a4 : target == null ? void 0 : target.getBoundingClientRect();
|
|
598
|
-
|
|
596
|
+
const didSizeChange = rectObserved.width !== prevRect.width || rectObserved.height !== prevRect.height;
|
|
597
|
+
const shouldResyncLayout = !!(webLayoutResync == null ? void 0 : webLayoutResync());
|
|
598
|
+
if (didSizeChange || shouldResyncLayout) {
|
|
599
599
|
prevRect = rectObserved;
|
|
600
600
|
emit(toLayout(rectObserved), false);
|
|
601
601
|
}
|
|
@@ -621,6 +621,15 @@ var Platform = {
|
|
|
621
621
|
OS: "web"
|
|
622
622
|
};
|
|
623
623
|
|
|
624
|
+
// src/utils/isInMVCPActiveMode.ts
|
|
625
|
+
function isInMVCPActiveMode(state) {
|
|
626
|
+
const lock = state.mvcpAnchorLock;
|
|
627
|
+
if (lock && Date.now() > lock.expiresAt) {
|
|
628
|
+
state.mvcpAnchorLock = void 0;
|
|
629
|
+
}
|
|
630
|
+
return state.dataChangeNeedsScrollUpdate || !!state.mvcpAnchorLock;
|
|
631
|
+
}
|
|
632
|
+
|
|
624
633
|
// src/components/Container.tsx
|
|
625
634
|
var Container = typedMemo(function Container2({
|
|
626
635
|
id,
|
|
@@ -728,7 +737,8 @@ var Container = typedMemo(function Container2({
|
|
|
728
737
|
updateItemSizeFn(currentItemKey, layout);
|
|
729
738
|
itemLayoutRef.current.didLayout = true;
|
|
730
739
|
};
|
|
731
|
-
|
|
740
|
+
const shouldDeferWebShrinkLayoutUpdate = !isInMVCPActiveMode(ctx.state) && prevSize !== void 0 && size + 1 < prevSize;
|
|
741
|
+
if (shouldDeferWebShrinkLayoutUpdate) {
|
|
732
742
|
const token = pendingShrinkToken + 1;
|
|
733
743
|
itemLayoutRef.current.pendingShrinkToken = token;
|
|
734
744
|
requestAnimationFrame(() => {
|
|
@@ -752,7 +762,8 @@ var Container = typedMemo(function Container2({
|
|
|
752
762
|
const { onLayout } = useOnLayoutSync(
|
|
753
763
|
{
|
|
754
764
|
onLayoutChange,
|
|
755
|
-
ref
|
|
765
|
+
ref,
|
|
766
|
+
webLayoutResync: () => isInMVCPActiveMode(ctx.state)
|
|
756
767
|
},
|
|
757
768
|
[itemKey, layoutRenderCount]
|
|
758
769
|
);
|
|
@@ -944,25 +955,6 @@ var Containers = typedMemo(function Containers2({
|
|
|
944
955
|
}
|
|
945
956
|
return /* @__PURE__ */ React3__namespace.createElement(ContainersInner, { horizontal, numColumns, waitForInitialLayout }, containers);
|
|
946
957
|
});
|
|
947
|
-
function DevNumbers() {
|
|
948
|
-
return IS_DEV && // biome-ignore lint/nursery/noShadow: const function name shadowing is intentional
|
|
949
|
-
React3__namespace.memo(function DevNumbers2() {
|
|
950
|
-
return Array.from({ length: 100 }).map((_, index) => /* @__PURE__ */ React3__namespace.createElement(
|
|
951
|
-
"div",
|
|
952
|
-
{
|
|
953
|
-
key: index,
|
|
954
|
-
style: {
|
|
955
|
-
height: 100,
|
|
956
|
-
pointerEvents: "none",
|
|
957
|
-
position: "absolute",
|
|
958
|
-
top: index * 100,
|
|
959
|
-
width: "100%"
|
|
960
|
-
}
|
|
961
|
-
},
|
|
962
|
-
/* @__PURE__ */ React3__namespace.createElement("div", { style: { color: "red" } }, index * 100)
|
|
963
|
-
));
|
|
964
|
-
});
|
|
965
|
-
}
|
|
966
958
|
|
|
967
959
|
// src/platform/StyleSheet.tsx
|
|
968
960
|
function flattenStyles(styles) {
|
|
@@ -1137,6 +1129,7 @@ function useValueListener$(key, callback) {
|
|
|
1137
1129
|
function ScrollAdjust() {
|
|
1138
1130
|
const ctx = useStateContext();
|
|
1139
1131
|
const lastScrollOffsetRef = React3__namespace.useRef(0);
|
|
1132
|
+
const resetPaddingRafRef = React3__namespace.useRef(void 0);
|
|
1140
1133
|
const callback = React3__namespace.useCallback(() => {
|
|
1141
1134
|
var _a3;
|
|
1142
1135
|
const scrollAdjust = peek$(ctx, "scrollAdjust");
|
|
@@ -1151,13 +1144,17 @@ function ScrollAdjust() {
|
|
|
1151
1144
|
const nextScroll = prevScroll + scrollDelta;
|
|
1152
1145
|
const totalSize = el.scrollHeight;
|
|
1153
1146
|
if (scrollDelta > 0 && !ctx.state.adjustingFromInitialMount && totalSize < nextScroll + el.clientHeight) {
|
|
1147
|
+
const paddingBottom = ctx.state.props.stylePaddingBottom || 0;
|
|
1154
1148
|
const child = el.firstElementChild;
|
|
1155
1149
|
const pad = (nextScroll + el.clientHeight - totalSize) * 2;
|
|
1156
1150
|
child.style.paddingBottom = `${pad}px`;
|
|
1157
1151
|
void el.offsetHeight;
|
|
1158
1152
|
scrollView.scrollBy(0, scrollDelta);
|
|
1159
|
-
|
|
1160
|
-
|
|
1153
|
+
if (resetPaddingRafRef.current !== void 0) {
|
|
1154
|
+
cancelAnimationFrame(resetPaddingRafRef.current);
|
|
1155
|
+
}
|
|
1156
|
+
resetPaddingRafRef.current = requestAnimationFrame(() => {
|
|
1157
|
+
resetPaddingRafRef.current = void 0;
|
|
1161
1158
|
child.style.paddingBottom = paddingBottom ? `${paddingBottom}px` : "0";
|
|
1162
1159
|
});
|
|
1163
1160
|
} else {
|
|
@@ -1279,7 +1276,7 @@ var ListComponent = typedMemo(function ListComponent2({
|
|
|
1279
1276
|
},
|
|
1280
1277
|
getComponent(ListFooterComponent)
|
|
1281
1278
|
),
|
|
1282
|
-
IS_DEV && ENABLE_DEVMODE
|
|
1279
|
+
IS_DEV && ENABLE_DEVMODE
|
|
1283
1280
|
);
|
|
1284
1281
|
});
|
|
1285
1282
|
|
|
@@ -1425,151 +1422,11 @@ function clampScrollOffset(ctx, offset) {
|
|
|
1425
1422
|
return clampedOffset;
|
|
1426
1423
|
}
|
|
1427
1424
|
|
|
1428
|
-
// src/utils/setInitialRenderState.ts
|
|
1429
|
-
function setInitialRenderState(ctx, {
|
|
1430
|
-
didLayout,
|
|
1431
|
-
didInitialScroll
|
|
1432
|
-
}) {
|
|
1433
|
-
const { state } = ctx;
|
|
1434
|
-
if (didLayout) {
|
|
1435
|
-
state.didContainersLayout = true;
|
|
1436
|
-
}
|
|
1437
|
-
if (didInitialScroll) {
|
|
1438
|
-
state.didFinishInitialScroll = true;
|
|
1439
|
-
}
|
|
1440
|
-
if (state.didContainersLayout && state.didFinishInitialScroll) {
|
|
1441
|
-
set$(ctx, "readyToRender", true);
|
|
1442
|
-
}
|
|
1443
|
-
}
|
|
1444
|
-
|
|
1445
|
-
// src/core/finishScrollTo.ts
|
|
1446
|
-
function finishScrollTo(ctx) {
|
|
1447
|
-
var _a3, _b;
|
|
1448
|
-
const state = ctx.state;
|
|
1449
|
-
if (state == null ? void 0 : state.scrollingTo) {
|
|
1450
|
-
const scrollingTo = state.scrollingTo;
|
|
1451
|
-
state.scrollHistory.length = 0;
|
|
1452
|
-
state.initialScroll = void 0;
|
|
1453
|
-
state.initialAnchor = void 0;
|
|
1454
|
-
state.scrollingTo = void 0;
|
|
1455
|
-
if (state.pendingTotalSize !== void 0) {
|
|
1456
|
-
addTotalSize(ctx, null, state.pendingTotalSize);
|
|
1457
|
-
}
|
|
1458
|
-
if ((_a3 = state.props) == null ? void 0 : _a3.data) {
|
|
1459
|
-
(_b = state.triggerCalculateItemsInView) == null ? void 0 : _b.call(state, { forceFullItemPositions: true });
|
|
1460
|
-
}
|
|
1461
|
-
{
|
|
1462
|
-
state.scrollAdjustHandler.commitPendingAdjust(scrollingTo);
|
|
1463
|
-
}
|
|
1464
|
-
setInitialRenderState(ctx, { didInitialScroll: true });
|
|
1465
|
-
}
|
|
1466
|
-
}
|
|
1467
|
-
|
|
1468
|
-
// src/core/doScrollTo.ts
|
|
1469
|
-
var SCROLL_END_IDLE_MS = 80;
|
|
1470
|
-
var SCROLL_END_MAX_MS = 1500;
|
|
1471
|
-
var SMOOTH_SCROLL_DURATION_MS = 320;
|
|
1472
|
-
function doScrollTo(ctx, params) {
|
|
1473
|
-
const state = ctx.state;
|
|
1474
|
-
const { animated, horizontal, offset } = params;
|
|
1475
|
-
const scroller = state.refScroller.current;
|
|
1476
|
-
const node = typeof (scroller == null ? void 0 : scroller.getScrollableNode) === "function" ? scroller.getScrollableNode() : scroller;
|
|
1477
|
-
if (node) {
|
|
1478
|
-
const left = horizontal ? offset : 0;
|
|
1479
|
-
const top = horizontal ? 0 : offset;
|
|
1480
|
-
node.scrollTo({ behavior: animated ? "smooth" : "auto", left, top });
|
|
1481
|
-
if (animated) {
|
|
1482
|
-
listenForScrollEnd(ctx, node);
|
|
1483
|
-
} else {
|
|
1484
|
-
state.scroll = offset;
|
|
1485
|
-
setTimeout(() => {
|
|
1486
|
-
finishScrollTo(ctx);
|
|
1487
|
-
}, 100);
|
|
1488
|
-
}
|
|
1489
|
-
}
|
|
1490
|
-
}
|
|
1491
|
-
function listenForScrollEnd(ctx, node) {
|
|
1492
|
-
const supportsScrollEnd = "onscrollend" in node;
|
|
1493
|
-
let idleTimeout;
|
|
1494
|
-
let maxTimeout;
|
|
1495
|
-
let settled = false;
|
|
1496
|
-
const targetToken = ctx.state.scrollingTo;
|
|
1497
|
-
const finish = () => {
|
|
1498
|
-
if (settled) return;
|
|
1499
|
-
settled = true;
|
|
1500
|
-
cleanup();
|
|
1501
|
-
if (targetToken === ctx.state.scrollingTo) {
|
|
1502
|
-
finishScrollTo(ctx);
|
|
1503
|
-
}
|
|
1504
|
-
};
|
|
1505
|
-
const onScroll2 = () => {
|
|
1506
|
-
if (idleTimeout) {
|
|
1507
|
-
clearTimeout(idleTimeout);
|
|
1508
|
-
}
|
|
1509
|
-
idleTimeout = setTimeout(finish, SCROLL_END_IDLE_MS);
|
|
1510
|
-
};
|
|
1511
|
-
const cleanup = () => {
|
|
1512
|
-
if (supportsScrollEnd) {
|
|
1513
|
-
node.removeEventListener("scrollend", finish);
|
|
1514
|
-
} else {
|
|
1515
|
-
node.removeEventListener("scroll", onScroll2);
|
|
1516
|
-
}
|
|
1517
|
-
if (idleTimeout) {
|
|
1518
|
-
clearTimeout(idleTimeout);
|
|
1519
|
-
}
|
|
1520
|
-
if (maxTimeout) {
|
|
1521
|
-
clearTimeout(maxTimeout);
|
|
1522
|
-
}
|
|
1523
|
-
};
|
|
1524
|
-
if (supportsScrollEnd) {
|
|
1525
|
-
node.addEventListener("scrollend", finish, { once: true });
|
|
1526
|
-
} else {
|
|
1527
|
-
node.addEventListener("scroll", onScroll2);
|
|
1528
|
-
idleTimeout = setTimeout(finish, SMOOTH_SCROLL_DURATION_MS);
|
|
1529
|
-
maxTimeout = setTimeout(finish, SCROLL_END_MAX_MS);
|
|
1530
|
-
}
|
|
1531
|
-
return cleanup;
|
|
1532
|
-
}
|
|
1533
|
-
|
|
1534
|
-
// src/core/scrollTo.ts
|
|
1535
|
-
function scrollTo(ctx, params) {
|
|
1536
|
-
const state = ctx.state;
|
|
1537
|
-
const { noScrollingTo, forceScroll, ...scrollTarget } = params;
|
|
1538
|
-
const { animated, isInitialScroll, offset: scrollTargetOffset, precomputedWithViewOffset } = scrollTarget;
|
|
1539
|
-
const {
|
|
1540
|
-
props: { horizontal }
|
|
1541
|
-
} = state;
|
|
1542
|
-
if (state.animFrameCheckFinishedScroll) {
|
|
1543
|
-
cancelAnimationFrame(ctx.state.animFrameCheckFinishedScroll);
|
|
1544
|
-
}
|
|
1545
|
-
if (state.timeoutCheckFinishedScrollFallback) {
|
|
1546
|
-
clearTimeout(ctx.state.timeoutCheckFinishedScrollFallback);
|
|
1547
|
-
}
|
|
1548
|
-
let offset = precomputedWithViewOffset ? scrollTargetOffset : calculateOffsetWithOffsetPosition(ctx, scrollTargetOffset, scrollTarget);
|
|
1549
|
-
offset = clampScrollOffset(ctx, offset);
|
|
1550
|
-
state.scrollHistory.length = 0;
|
|
1551
|
-
if (!noScrollingTo) {
|
|
1552
|
-
state.scrollingTo = scrollTarget;
|
|
1553
|
-
}
|
|
1554
|
-
state.scrollPending = offset;
|
|
1555
|
-
if (forceScroll || !isInitialScroll || Platform.OS === "android") {
|
|
1556
|
-
doScrollTo(ctx, { animated, horizontal, isInitialScroll, offset });
|
|
1557
|
-
} else {
|
|
1558
|
-
state.scroll = offset;
|
|
1559
|
-
}
|
|
1560
|
-
}
|
|
1561
|
-
|
|
1562
1425
|
// src/utils/checkThreshold.ts
|
|
1563
1426
|
var HYSTERESIS_MULTIPLIER = 1.3;
|
|
1564
1427
|
var checkThreshold = (distance, atThreshold, threshold, wasReached, snapshot, context, onReached, setSnapshot, allowReentryOnChange) => {
|
|
1565
1428
|
const absDistance = Math.abs(distance);
|
|
1566
1429
|
const within = atThreshold || threshold > 0 && absDistance <= threshold;
|
|
1567
|
-
if (wasReached === null) {
|
|
1568
|
-
if (!within && distance >= 0) {
|
|
1569
|
-
return false;
|
|
1570
|
-
}
|
|
1571
|
-
return null;
|
|
1572
|
-
}
|
|
1573
1430
|
const updateSnapshot = () => {
|
|
1574
1431
|
setSnapshot({
|
|
1575
1432
|
atThreshold,
|
|
@@ -1607,7 +1464,7 @@ var checkThreshold = (distance, atThreshold, threshold, wasReached, snapshot, co
|
|
|
1607
1464
|
function checkAtBottom(ctx) {
|
|
1608
1465
|
var _a3;
|
|
1609
1466
|
const state = ctx.state;
|
|
1610
|
-
if (!state) {
|
|
1467
|
+
if (!state || state.initialScroll) {
|
|
1611
1468
|
return;
|
|
1612
1469
|
}
|
|
1613
1470
|
const {
|
|
@@ -1617,6 +1474,9 @@ function checkAtBottom(ctx) {
|
|
|
1617
1474
|
maintainingScrollAtEnd,
|
|
1618
1475
|
props: { maintainScrollAtEndThreshold, onEndReachedThreshold }
|
|
1619
1476
|
} = state;
|
|
1477
|
+
if (state.initialScroll) {
|
|
1478
|
+
return;
|
|
1479
|
+
}
|
|
1620
1480
|
const contentSize = getContentSize(ctx);
|
|
1621
1481
|
if (contentSize > 0 && queuedInitialLayout && !maintainingScrollAtEnd) {
|
|
1622
1482
|
const insetEnd = getContentInsetEnd(state);
|
|
@@ -1647,9 +1507,10 @@ function checkAtBottom(ctx) {
|
|
|
1647
1507
|
}
|
|
1648
1508
|
|
|
1649
1509
|
// src/utils/checkAtTop.ts
|
|
1650
|
-
function checkAtTop(
|
|
1510
|
+
function checkAtTop(ctx) {
|
|
1651
1511
|
var _a3;
|
|
1652
|
-
|
|
1512
|
+
const state = ctx == null ? void 0 : ctx.state;
|
|
1513
|
+
if (!state || state.initialScroll) {
|
|
1653
1514
|
return;
|
|
1654
1515
|
}
|
|
1655
1516
|
const {
|
|
@@ -1681,6 +1542,160 @@ function checkAtTop(state) {
|
|
|
1681
1542
|
);
|
|
1682
1543
|
}
|
|
1683
1544
|
|
|
1545
|
+
// src/utils/checkThresholds.ts
|
|
1546
|
+
function checkThresholds(ctx) {
|
|
1547
|
+
checkAtBottom(ctx);
|
|
1548
|
+
checkAtTop(ctx);
|
|
1549
|
+
}
|
|
1550
|
+
|
|
1551
|
+
// src/utils/setInitialRenderState.ts
|
|
1552
|
+
function setInitialRenderState(ctx, {
|
|
1553
|
+
didLayout,
|
|
1554
|
+
didInitialScroll
|
|
1555
|
+
}) {
|
|
1556
|
+
const { state } = ctx;
|
|
1557
|
+
if (didLayout) {
|
|
1558
|
+
state.didContainersLayout = true;
|
|
1559
|
+
}
|
|
1560
|
+
if (didInitialScroll) {
|
|
1561
|
+
state.didFinishInitialScroll = true;
|
|
1562
|
+
}
|
|
1563
|
+
if (state.didContainersLayout && state.didFinishInitialScroll) {
|
|
1564
|
+
set$(ctx, "readyToRender", true);
|
|
1565
|
+
}
|
|
1566
|
+
}
|
|
1567
|
+
|
|
1568
|
+
// src/core/finishScrollTo.ts
|
|
1569
|
+
function finishScrollTo(ctx) {
|
|
1570
|
+
var _a3, _b;
|
|
1571
|
+
const state = ctx.state;
|
|
1572
|
+
if (state == null ? void 0 : state.scrollingTo) {
|
|
1573
|
+
const scrollingTo = state.scrollingTo;
|
|
1574
|
+
state.scrollHistory.length = 0;
|
|
1575
|
+
state.initialScroll = void 0;
|
|
1576
|
+
state.initialAnchor = void 0;
|
|
1577
|
+
state.scrollingTo = void 0;
|
|
1578
|
+
if (state.pendingTotalSize !== void 0) {
|
|
1579
|
+
addTotalSize(ctx, null, state.pendingTotalSize);
|
|
1580
|
+
}
|
|
1581
|
+
if ((_a3 = state.props) == null ? void 0 : _a3.data) {
|
|
1582
|
+
(_b = state.triggerCalculateItemsInView) == null ? void 0 : _b.call(state, { forceFullItemPositions: true });
|
|
1583
|
+
}
|
|
1584
|
+
{
|
|
1585
|
+
state.scrollAdjustHandler.commitPendingAdjust(scrollingTo);
|
|
1586
|
+
}
|
|
1587
|
+
setInitialRenderState(ctx, { didInitialScroll: true });
|
|
1588
|
+
checkThresholds(ctx);
|
|
1589
|
+
}
|
|
1590
|
+
}
|
|
1591
|
+
|
|
1592
|
+
// src/core/doScrollTo.ts
|
|
1593
|
+
var SCROLL_END_IDLE_MS = 80;
|
|
1594
|
+
var SCROLL_END_MAX_MS = 1500;
|
|
1595
|
+
var SMOOTH_SCROLL_DURATION_MS = 320;
|
|
1596
|
+
var SCROLL_END_TARGET_EPSILON = 1;
|
|
1597
|
+
function doScrollTo(ctx, params) {
|
|
1598
|
+
const state = ctx.state;
|
|
1599
|
+
const { animated, horizontal, offset } = params;
|
|
1600
|
+
const scroller = state.refScroller.current;
|
|
1601
|
+
const node = typeof (scroller == null ? void 0 : scroller.getScrollableNode) === "function" ? scroller.getScrollableNode() : scroller;
|
|
1602
|
+
if (node) {
|
|
1603
|
+
const left = horizontal ? offset : 0;
|
|
1604
|
+
const top = horizontal ? 0 : offset;
|
|
1605
|
+
node.scrollTo({ behavior: animated ? "smooth" : "auto", left, top });
|
|
1606
|
+
if (animated) {
|
|
1607
|
+
listenForScrollEnd(ctx, node, {
|
|
1608
|
+
horizontal: !!horizontal,
|
|
1609
|
+
targetOffset: offset
|
|
1610
|
+
});
|
|
1611
|
+
} else {
|
|
1612
|
+
state.scroll = offset;
|
|
1613
|
+
setTimeout(() => {
|
|
1614
|
+
finishScrollTo(ctx);
|
|
1615
|
+
}, 100);
|
|
1616
|
+
}
|
|
1617
|
+
}
|
|
1618
|
+
}
|
|
1619
|
+
function listenForScrollEnd(ctx, node, params) {
|
|
1620
|
+
const { horizontal, targetOffset } = params;
|
|
1621
|
+
const supportsScrollEnd = "onscrollend" in node;
|
|
1622
|
+
let idleTimeout;
|
|
1623
|
+
let maxTimeout;
|
|
1624
|
+
let settled = false;
|
|
1625
|
+
const targetToken = ctx.state.scrollingTo;
|
|
1626
|
+
const cleanup = () => {
|
|
1627
|
+
node.removeEventListener("scroll", onScroll2);
|
|
1628
|
+
if (supportsScrollEnd) {
|
|
1629
|
+
node.removeEventListener("scrollend", onScrollEnd);
|
|
1630
|
+
}
|
|
1631
|
+
if (idleTimeout) {
|
|
1632
|
+
clearTimeout(idleTimeout);
|
|
1633
|
+
}
|
|
1634
|
+
if (maxTimeout) {
|
|
1635
|
+
clearTimeout(maxTimeout);
|
|
1636
|
+
}
|
|
1637
|
+
};
|
|
1638
|
+
const finish = (reason) => {
|
|
1639
|
+
if (settled) return;
|
|
1640
|
+
if (targetToken !== ctx.state.scrollingTo) {
|
|
1641
|
+
settled = true;
|
|
1642
|
+
cleanup();
|
|
1643
|
+
return;
|
|
1644
|
+
}
|
|
1645
|
+
const currentOffset = horizontal ? node.scrollLeft : node.scrollTop;
|
|
1646
|
+
const isNearTarget = Math.abs(currentOffset - targetOffset) <= SCROLL_END_TARGET_EPSILON;
|
|
1647
|
+
if (reason === "scrollend" && !isNearTarget) {
|
|
1648
|
+
return;
|
|
1649
|
+
}
|
|
1650
|
+
settled = true;
|
|
1651
|
+
cleanup();
|
|
1652
|
+
finishScrollTo(ctx);
|
|
1653
|
+
};
|
|
1654
|
+
const onScroll2 = () => {
|
|
1655
|
+
if (idleTimeout) {
|
|
1656
|
+
clearTimeout(idleTimeout);
|
|
1657
|
+
}
|
|
1658
|
+
idleTimeout = setTimeout(() => finish("idle"), SCROLL_END_IDLE_MS);
|
|
1659
|
+
};
|
|
1660
|
+
const onScrollEnd = () => finish("scrollend");
|
|
1661
|
+
node.addEventListener("scroll", onScroll2);
|
|
1662
|
+
if (supportsScrollEnd) {
|
|
1663
|
+
node.addEventListener("scrollend", onScrollEnd);
|
|
1664
|
+
maxTimeout = setTimeout(() => finish("max"), SCROLL_END_MAX_MS);
|
|
1665
|
+
} else {
|
|
1666
|
+
idleTimeout = setTimeout(() => finish("idle"), SMOOTH_SCROLL_DURATION_MS);
|
|
1667
|
+
maxTimeout = setTimeout(() => finish("max"), SCROLL_END_MAX_MS);
|
|
1668
|
+
}
|
|
1669
|
+
}
|
|
1670
|
+
|
|
1671
|
+
// src/core/scrollTo.ts
|
|
1672
|
+
function scrollTo(ctx, params) {
|
|
1673
|
+
const state = ctx.state;
|
|
1674
|
+
const { noScrollingTo, forceScroll, ...scrollTarget } = params;
|
|
1675
|
+
const { animated, isInitialScroll, offset: scrollTargetOffset, precomputedWithViewOffset } = scrollTarget;
|
|
1676
|
+
const {
|
|
1677
|
+
props: { horizontal }
|
|
1678
|
+
} = state;
|
|
1679
|
+
if (state.animFrameCheckFinishedScroll) {
|
|
1680
|
+
cancelAnimationFrame(ctx.state.animFrameCheckFinishedScroll);
|
|
1681
|
+
}
|
|
1682
|
+
if (state.timeoutCheckFinishedScrollFallback) {
|
|
1683
|
+
clearTimeout(ctx.state.timeoutCheckFinishedScrollFallback);
|
|
1684
|
+
}
|
|
1685
|
+
let offset = precomputedWithViewOffset ? scrollTargetOffset : calculateOffsetWithOffsetPosition(ctx, scrollTargetOffset, scrollTarget);
|
|
1686
|
+
offset = clampScrollOffset(ctx, offset);
|
|
1687
|
+
state.scrollHistory.length = 0;
|
|
1688
|
+
if (!noScrollingTo) {
|
|
1689
|
+
state.scrollingTo = scrollTarget;
|
|
1690
|
+
}
|
|
1691
|
+
state.scrollPending = offset;
|
|
1692
|
+
if (forceScroll || !isInitialScroll || Platform.OS === "android") {
|
|
1693
|
+
doScrollTo(ctx, { animated, horizontal, offset });
|
|
1694
|
+
} else {
|
|
1695
|
+
state.scroll = offset;
|
|
1696
|
+
}
|
|
1697
|
+
}
|
|
1698
|
+
|
|
1684
1699
|
// src/core/updateScroll.ts
|
|
1685
1700
|
function updateScroll(ctx, newScroll, forceUpdate) {
|
|
1686
1701
|
const state = ctx.state;
|
|
@@ -1718,7 +1733,8 @@ function updateScroll(ctx, newScroll, forceUpdate) {
|
|
|
1718
1733
|
const scrollDelta = Math.abs(newScroll - prevScroll);
|
|
1719
1734
|
const scrollLength = state.scrollLength;
|
|
1720
1735
|
const lastCalculated = state.scrollLastCalculate;
|
|
1721
|
-
const
|
|
1736
|
+
const useAggressiveItemRecalculation = isInMVCPActiveMode(state);
|
|
1737
|
+
const shouldUpdate = useAggressiveItemRecalculation || forceUpdate || lastCalculated === void 0 || Math.abs(state.scroll - lastCalculated) > 2;
|
|
1722
1738
|
if (shouldUpdate) {
|
|
1723
1739
|
state.scrollLastCalculate = state.scroll;
|
|
1724
1740
|
state.ignoreScrollFromMVCPIgnored = false;
|
|
@@ -1726,8 +1742,7 @@ function updateScroll(ctx, newScroll, forceUpdate) {
|
|
|
1726
1742
|
const runCalculateItems = () => {
|
|
1727
1743
|
var _a3;
|
|
1728
1744
|
(_a3 = state.triggerCalculateItemsInView) == null ? void 0 : _a3.call(state, { doMVCP: scrollingTo !== void 0 });
|
|
1729
|
-
|
|
1730
|
-
checkAtTop(state);
|
|
1745
|
+
checkThresholds(ctx);
|
|
1731
1746
|
};
|
|
1732
1747
|
if (scrollLength > 0 && scrollingTo === void 0 && scrollDelta > scrollLength) {
|
|
1733
1748
|
reactDom.flushSync(runCalculateItems);
|
|
@@ -1764,13 +1779,58 @@ function requestAdjust(ctx, positionDiff, dataChanged) {
|
|
|
1764
1779
|
}
|
|
1765
1780
|
|
|
1766
1781
|
// src/core/mvcp.ts
|
|
1782
|
+
var MVCP_POSITION_EPSILON = 0.1;
|
|
1783
|
+
var MVCP_ANCHOR_LOCK_TTL_MS = 300;
|
|
1784
|
+
var MVCP_ANCHOR_LOCK_QUIET_PASSES_TO_RELEASE = 2;
|
|
1785
|
+
function resolveAnchorLock(state, enableMVCPAnchorLock, mvcpData, now) {
|
|
1786
|
+
if (!enableMVCPAnchorLock) {
|
|
1787
|
+
state.mvcpAnchorLock = void 0;
|
|
1788
|
+
return void 0;
|
|
1789
|
+
}
|
|
1790
|
+
const lock = state.mvcpAnchorLock;
|
|
1791
|
+
if (!lock) {
|
|
1792
|
+
return void 0;
|
|
1793
|
+
}
|
|
1794
|
+
const isExpired = now > lock.expiresAt;
|
|
1795
|
+
const isMissing = state.indexByKey.get(lock.id) === void 0;
|
|
1796
|
+
if (isExpired || isMissing || !mvcpData) {
|
|
1797
|
+
state.mvcpAnchorLock = void 0;
|
|
1798
|
+
return void 0;
|
|
1799
|
+
}
|
|
1800
|
+
return lock;
|
|
1801
|
+
}
|
|
1802
|
+
function updateAnchorLock(state, params) {
|
|
1803
|
+
{
|
|
1804
|
+
const { anchorId, anchorPosition, dataChanged, now, positionDiff } = params;
|
|
1805
|
+
const enableMVCPAnchorLock = !!dataChanged || !!state.mvcpAnchorLock;
|
|
1806
|
+
const mvcpData = state.props.maintainVisibleContentPosition.data;
|
|
1807
|
+
if (!enableMVCPAnchorLock || !mvcpData || state.scrollingTo || !anchorId || anchorPosition === void 0) {
|
|
1808
|
+
return;
|
|
1809
|
+
}
|
|
1810
|
+
const existingLock = state.mvcpAnchorLock;
|
|
1811
|
+
const quietPasses = !dataChanged && Math.abs(positionDiff) <= MVCP_POSITION_EPSILON && (existingLock == null ? void 0 : existingLock.id) === anchorId ? existingLock.quietPasses + 1 : 0;
|
|
1812
|
+
if (!dataChanged && quietPasses >= MVCP_ANCHOR_LOCK_QUIET_PASSES_TO_RELEASE) {
|
|
1813
|
+
state.mvcpAnchorLock = void 0;
|
|
1814
|
+
return;
|
|
1815
|
+
}
|
|
1816
|
+
state.mvcpAnchorLock = {
|
|
1817
|
+
expiresAt: now + MVCP_ANCHOR_LOCK_TTL_MS,
|
|
1818
|
+
id: anchorId,
|
|
1819
|
+
position: anchorPosition,
|
|
1820
|
+
quietPasses
|
|
1821
|
+
};
|
|
1822
|
+
}
|
|
1823
|
+
}
|
|
1767
1824
|
function prepareMVCP(ctx, dataChanged) {
|
|
1768
1825
|
const state = ctx.state;
|
|
1769
1826
|
const { idsInView, positions, props } = state;
|
|
1770
1827
|
const {
|
|
1771
1828
|
maintainVisibleContentPosition: { data: mvcpData, size: mvcpScroll, shouldRestorePosition }
|
|
1772
1829
|
} = props;
|
|
1830
|
+
const now = Date.now();
|
|
1831
|
+
const enableMVCPAnchorLock = (!!dataChanged || !!state.mvcpAnchorLock);
|
|
1773
1832
|
const scrollingTo = state.scrollingTo;
|
|
1833
|
+
const anchorLock = resolveAnchorLock(state, enableMVCPAnchorLock, mvcpData, now) ;
|
|
1774
1834
|
let prevPosition;
|
|
1775
1835
|
let targetId;
|
|
1776
1836
|
const idsInViewWithPositions = [];
|
|
@@ -1779,28 +1839,45 @@ function prepareMVCP(ctx, dataChanged) {
|
|
|
1779
1839
|
const shouldMVCP = dataChanged ? mvcpData : mvcpScroll;
|
|
1780
1840
|
const indexByKey = state.indexByKey;
|
|
1781
1841
|
if (shouldMVCP) {
|
|
1782
|
-
if (scrollTarget
|
|
1842
|
+
if (anchorLock && scrollTarget === void 0) {
|
|
1843
|
+
targetId = anchorLock.id;
|
|
1844
|
+
prevPosition = anchorLock.position;
|
|
1845
|
+
} else if (scrollTarget !== void 0) {
|
|
1783
1846
|
targetId = getId(state, scrollTarget);
|
|
1784
|
-
} else if (idsInView.length > 0 && state.didContainersLayout) {
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1847
|
+
} else if (idsInView.length > 0 && state.didContainersLayout && !dataChanged) {
|
|
1848
|
+
targetId = idsInView.find((id) => indexByKey.get(id) !== void 0);
|
|
1849
|
+
}
|
|
1850
|
+
if (dataChanged && idsInView.length > 0 && state.didContainersLayout) {
|
|
1851
|
+
for (let i = 0; i < idsInView.length; i++) {
|
|
1852
|
+
const id = idsInView[i];
|
|
1853
|
+
const index = indexByKey.get(id);
|
|
1854
|
+
if (index !== void 0) {
|
|
1855
|
+
idsInViewWithPositions.push({ id, position: positions.get(id) });
|
|
1792
1856
|
}
|
|
1793
|
-
} else {
|
|
1794
|
-
targetId = idsInView.find((id) => indexByKey.get(id) !== void 0);
|
|
1795
1857
|
}
|
|
1796
1858
|
}
|
|
1797
|
-
if (targetId !== void 0) {
|
|
1859
|
+
if (targetId !== void 0 && prevPosition === void 0) {
|
|
1798
1860
|
prevPosition = positions.get(targetId);
|
|
1799
1861
|
}
|
|
1800
1862
|
return () => {
|
|
1801
1863
|
let positionDiff = 0;
|
|
1802
|
-
|
|
1803
|
-
|
|
1864
|
+
let anchorIdForLock = anchorLock == null ? void 0 : anchorLock.id;
|
|
1865
|
+
let anchorPositionForLock;
|
|
1866
|
+
let skipTargetAnchor = false;
|
|
1867
|
+
const data = state.props.data;
|
|
1868
|
+
const shouldValidateLockedAnchor = dataChanged && mvcpData && scrollTarget === void 0 && targetId !== void 0 && (anchorLock == null ? void 0 : anchorLock.id) === targetId && shouldRestorePosition !== void 0;
|
|
1869
|
+
if (shouldValidateLockedAnchor && targetId !== void 0) {
|
|
1870
|
+
const index = indexByKey.get(targetId);
|
|
1871
|
+
if (index !== void 0) {
|
|
1872
|
+
const item = data[index];
|
|
1873
|
+
skipTargetAnchor = item === void 0 || !shouldRestorePosition(item, index, data);
|
|
1874
|
+
if (skipTargetAnchor && (anchorLock == null ? void 0 : anchorLock.id) === targetId) {
|
|
1875
|
+
state.mvcpAnchorLock = void 0;
|
|
1876
|
+
}
|
|
1877
|
+
}
|
|
1878
|
+
}
|
|
1879
|
+
const shouldUseFallbackVisibleAnchor = dataChanged && mvcpData && scrollTarget === void 0 && (targetId === void 0 || positions.get(targetId) === void 0 || skipTargetAnchor);
|
|
1880
|
+
if (shouldUseFallbackVisibleAnchor) {
|
|
1804
1881
|
for (let i = 0; i < idsInViewWithPositions.length; i++) {
|
|
1805
1882
|
const { id, position } = idsInViewWithPositions[i];
|
|
1806
1883
|
const index = indexByKey.get(id);
|
|
@@ -1813,11 +1890,13 @@ function prepareMVCP(ctx, dataChanged) {
|
|
|
1813
1890
|
const newPosition = positions.get(id);
|
|
1814
1891
|
if (newPosition !== void 0) {
|
|
1815
1892
|
positionDiff = newPosition - position;
|
|
1893
|
+
anchorIdForLock = id;
|
|
1894
|
+
anchorPositionForLock = newPosition;
|
|
1816
1895
|
break;
|
|
1817
1896
|
}
|
|
1818
1897
|
}
|
|
1819
1898
|
}
|
|
1820
|
-
if (targetId !== void 0 && prevPosition !== void 0) {
|
|
1899
|
+
if (!skipTargetAnchor && targetId !== void 0 && prevPosition !== void 0) {
|
|
1821
1900
|
const newPosition = positions.get(targetId);
|
|
1822
1901
|
if (newPosition !== void 0) {
|
|
1823
1902
|
const totalSize = getContentSize(ctx);
|
|
@@ -1830,20 +1909,29 @@ function prepareMVCP(ctx, dataChanged) {
|
|
|
1830
1909
|
}
|
|
1831
1910
|
}
|
|
1832
1911
|
positionDiff = diff;
|
|
1912
|
+
anchorIdForLock = targetId;
|
|
1913
|
+
anchorPositionForLock = newPosition;
|
|
1833
1914
|
}
|
|
1834
1915
|
}
|
|
1835
1916
|
if (scrollingToViewPosition && scrollingToViewPosition > 0) {
|
|
1836
1917
|
const newSize = getItemSize(ctx, targetId, scrollTarget, state.props.data[scrollTarget]);
|
|
1837
1918
|
const prevSize = scrollingTo == null ? void 0 : scrollingTo.itemSize;
|
|
1838
|
-
if (newSize !== void 0 && prevSize !== void 0 && newSize !==
|
|
1919
|
+
if (newSize !== void 0 && prevSize !== void 0 && newSize !== prevSize) {
|
|
1839
1920
|
const diff = newSize - prevSize;
|
|
1840
1921
|
if (diff !== 0) {
|
|
1841
|
-
positionDiff +=
|
|
1922
|
+
positionDiff += diff * scrollingToViewPosition;
|
|
1842
1923
|
scrollingTo.itemSize = newSize;
|
|
1843
1924
|
}
|
|
1844
1925
|
}
|
|
1845
1926
|
}
|
|
1846
|
-
|
|
1927
|
+
updateAnchorLock(state, {
|
|
1928
|
+
anchorId: anchorIdForLock,
|
|
1929
|
+
anchorPosition: anchorPositionForLock,
|
|
1930
|
+
dataChanged,
|
|
1931
|
+
now,
|
|
1932
|
+
positionDiff
|
|
1933
|
+
});
|
|
1934
|
+
if (Math.abs(positionDiff) > MVCP_POSITION_EPSILON) {
|
|
1847
1935
|
requestAdjust(ctx, positionDiff);
|
|
1848
1936
|
}
|
|
1849
1937
|
};
|
|
@@ -2557,7 +2645,7 @@ function handleStickyActivation(ctx, stickyHeaderIndices, stickyArray, currentSt
|
|
|
2557
2645
|
}
|
|
2558
2646
|
}
|
|
2559
2647
|
}
|
|
2560
|
-
function handleStickyRecycling(ctx, stickyArray, scroll,
|
|
2648
|
+
function handleStickyRecycling(ctx, stickyArray, scroll, drawDistance, currentStickyIdx, pendingRemoval, alwaysRenderIndicesSet) {
|
|
2561
2649
|
var _a3, _b, _c;
|
|
2562
2650
|
const state = ctx.state;
|
|
2563
2651
|
for (const containerIndex of state.stickyContainerPool) {
|
|
@@ -2578,13 +2666,13 @@ function handleStickyRecycling(ctx, stickyArray, scroll, scrollBuffer, currentSt
|
|
|
2578
2666
|
if (nextIndex) {
|
|
2579
2667
|
const nextId = (_a3 = state.idCache[nextIndex]) != null ? _a3 : getId(state, nextIndex);
|
|
2580
2668
|
const nextPos = nextId ? state.positions.get(nextId) : void 0;
|
|
2581
|
-
shouldRecycle = nextPos !== void 0 && scroll > nextPos +
|
|
2669
|
+
shouldRecycle = nextPos !== void 0 && scroll > nextPos + drawDistance * 2;
|
|
2582
2670
|
} else {
|
|
2583
2671
|
const currentId = (_b = state.idCache[itemIndex]) != null ? _b : getId(state, itemIndex);
|
|
2584
2672
|
if (currentId) {
|
|
2585
2673
|
const currentPos = state.positions.get(currentId);
|
|
2586
2674
|
const currentSize = (_c = state.sizes.get(currentId)) != null ? _c : getItemSize(ctx, currentId, itemIndex, state.props.data[itemIndex]);
|
|
2587
|
-
shouldRecycle = currentPos !== void 0 && scroll > currentPos + currentSize +
|
|
2675
|
+
shouldRecycle = currentPos !== void 0 && scroll > currentPos + currentSize + drawDistance * 3;
|
|
2588
2676
|
}
|
|
2589
2677
|
}
|
|
2590
2678
|
if (shouldRecycle) {
|
|
@@ -2609,11 +2697,11 @@ function calculateItemsInView(ctx, params = {}) {
|
|
|
2609
2697
|
props: {
|
|
2610
2698
|
alwaysRenderIndicesArr,
|
|
2611
2699
|
alwaysRenderIndicesSet,
|
|
2700
|
+
drawDistance,
|
|
2612
2701
|
getItemType,
|
|
2613
2702
|
itemsAreEqual,
|
|
2614
2703
|
keyExtractor,
|
|
2615
|
-
onStickyHeaderChange
|
|
2616
|
-
scrollBuffer
|
|
2704
|
+
onStickyHeaderChange
|
|
2617
2705
|
},
|
|
2618
2706
|
scrollForNextCalculateItemsInView,
|
|
2619
2707
|
scrollLength,
|
|
@@ -2626,6 +2714,7 @@ function calculateItemsInView(ctx, params = {}) {
|
|
|
2626
2714
|
const stickyIndicesSet = state.props.stickyIndicesSet || /* @__PURE__ */ new Set();
|
|
2627
2715
|
const alwaysRenderArr = alwaysRenderIndicesArr || [];
|
|
2628
2716
|
const alwaysRenderSet = alwaysRenderIndicesSet || /* @__PURE__ */ new Set();
|
|
2717
|
+
const { dataChanged, doMVCP, forceFullItemPositions } = params;
|
|
2629
2718
|
const prevNumContainers = peek$(ctx, "numContainers");
|
|
2630
2719
|
if (!data || scrollLength === 0 || !prevNumContainers) {
|
|
2631
2720
|
return;
|
|
@@ -2633,7 +2722,6 @@ function calculateItemsInView(ctx, params = {}) {
|
|
|
2633
2722
|
const totalSize = getContentSize(ctx);
|
|
2634
2723
|
const topPad = peek$(ctx, "stylePaddingTop") + peek$(ctx, "headerSize");
|
|
2635
2724
|
const numColumns = peek$(ctx, "numColumns");
|
|
2636
|
-
const { dataChanged, doMVCP, forceFullItemPositions } = params;
|
|
2637
2725
|
const speed = getScrollVelocity(state);
|
|
2638
2726
|
const scrollExtra = 0;
|
|
2639
2727
|
const { queuedInitialLayout } = state;
|
|
@@ -2652,24 +2740,20 @@ function calculateItemsInView(ctx, params = {}) {
|
|
|
2652
2740
|
if (scroll + scrollLength > totalSize) {
|
|
2653
2741
|
scroll = Math.max(0, totalSize - scrollLength);
|
|
2654
2742
|
}
|
|
2655
|
-
if (ENABLE_DEBUG_VIEW) {
|
|
2656
|
-
set$(ctx, "debugRawScroll", scrollState);
|
|
2657
|
-
set$(ctx, "debugComputedScroll", scroll);
|
|
2658
|
-
}
|
|
2659
2743
|
const previousStickyIndex = peek$(ctx, "activeStickyIndex");
|
|
2660
2744
|
const currentStickyIdx = stickyIndicesArr.length > 0 ? findCurrentStickyIndex(stickyIndicesArr, scroll, state) : -1;
|
|
2661
2745
|
const nextActiveStickyIndex = currentStickyIdx >= 0 ? stickyIndicesArr[currentStickyIdx] : -1;
|
|
2662
2746
|
if (currentStickyIdx >= 0 || previousStickyIndex >= 0) {
|
|
2663
2747
|
set$(ctx, "activeStickyIndex", nextActiveStickyIndex);
|
|
2664
2748
|
}
|
|
2665
|
-
let scrollBufferTop =
|
|
2666
|
-
let scrollBufferBottom =
|
|
2667
|
-
if (speed > 0 || speed === 0 && scroll < Math.max(50,
|
|
2668
|
-
scrollBufferTop =
|
|
2669
|
-
scrollBufferBottom =
|
|
2749
|
+
let scrollBufferTop = drawDistance;
|
|
2750
|
+
let scrollBufferBottom = drawDistance;
|
|
2751
|
+
if (speed > 0 || speed === 0 && scroll < Math.max(50, drawDistance)) {
|
|
2752
|
+
scrollBufferTop = drawDistance * 0.5;
|
|
2753
|
+
scrollBufferBottom = drawDistance * 1.5;
|
|
2670
2754
|
} else {
|
|
2671
|
-
scrollBufferTop =
|
|
2672
|
-
scrollBufferBottom =
|
|
2755
|
+
scrollBufferTop = drawDistance * 1.5;
|
|
2756
|
+
scrollBufferBottom = drawDistance * 0.5;
|
|
2673
2757
|
}
|
|
2674
2758
|
const scrollTopBuffered = scroll - scrollBufferTop;
|
|
2675
2759
|
const scrollBottom = scroll + scrollLength + (scroll < 0 ? -scroll : 0);
|
|
@@ -2679,7 +2763,9 @@ function calculateItemsInView(ctx, params = {}) {
|
|
|
2679
2763
|
if (top === null && bottom === null) {
|
|
2680
2764
|
state.scrollForNextCalculateItemsInView = void 0;
|
|
2681
2765
|
} else if ((top === null || scrollTopBuffered > top) && (bottom === null || scrollBottomBuffered < bottom)) {
|
|
2682
|
-
|
|
2766
|
+
if (!isInMVCPActiveMode(state)) {
|
|
2767
|
+
return;
|
|
2768
|
+
}
|
|
2683
2769
|
}
|
|
2684
2770
|
}
|
|
2685
2771
|
const checkMVCP = doMVCP ? prepareMVCP(ctx, dataChanged) : void 0;
|
|
@@ -2911,7 +2997,7 @@ function calculateItemsInView(ctx, params = {}) {
|
|
|
2911
2997
|
ctx,
|
|
2912
2998
|
stickyIndicesArr,
|
|
2913
2999
|
scroll,
|
|
2914
|
-
|
|
3000
|
+
drawDistance,
|
|
2915
3001
|
currentStickyIdx,
|
|
2916
3002
|
pendingRemoval,
|
|
2917
3003
|
alwaysRenderSet
|
|
@@ -3023,7 +3109,8 @@ function checkFinishedScrollFrame(ctx) {
|
|
|
3023
3109
|
const diff1 = Math.abs(scroll - clampedTargetOffset);
|
|
3024
3110
|
const diff2 = Math.abs(diff1 - adjust);
|
|
3025
3111
|
const isNotOverscrolled = Math.abs(scroll - maxOffset) < 1;
|
|
3026
|
-
|
|
3112
|
+
const isAtTarget = diff1 < 1 || !scrollingTo.animated && diff2 < 1;
|
|
3113
|
+
if (isNotOverscrolled && isAtTarget) {
|
|
3027
3114
|
finishScrollTo(ctx);
|
|
3028
3115
|
}
|
|
3029
3116
|
}
|
|
@@ -3154,8 +3241,7 @@ function checkResetContainers(ctx, dataProp) {
|
|
|
3154
3241
|
state.isEndReached = false;
|
|
3155
3242
|
}
|
|
3156
3243
|
if (!didMaintainScrollAtEnd) {
|
|
3157
|
-
|
|
3158
|
-
checkAtBottom(ctx);
|
|
3244
|
+
checkThresholds(ctx);
|
|
3159
3245
|
}
|
|
3160
3246
|
delete state.previousData;
|
|
3161
3247
|
}
|
|
@@ -3168,10 +3254,10 @@ function doInitialAllocateContainers(ctx) {
|
|
|
3168
3254
|
scrollLength,
|
|
3169
3255
|
props: {
|
|
3170
3256
|
data,
|
|
3257
|
+
drawDistance,
|
|
3171
3258
|
getEstimatedItemSize,
|
|
3172
3259
|
getFixedItemSize,
|
|
3173
3260
|
getItemType,
|
|
3174
|
-
scrollBuffer,
|
|
3175
3261
|
numColumns,
|
|
3176
3262
|
estimatedItemSize
|
|
3177
3263
|
}
|
|
@@ -3193,7 +3279,7 @@ function doInitialAllocateContainers(ctx) {
|
|
|
3193
3279
|
} else {
|
|
3194
3280
|
averageItemSize = estimatedItemSize;
|
|
3195
3281
|
}
|
|
3196
|
-
const numContainers = Math.ceil((scrollLength +
|
|
3282
|
+
const numContainers = Math.ceil((scrollLength + drawDistance * 2) / averageItemSize * numColumns);
|
|
3197
3283
|
for (let i = 0; i < numContainers; i++) {
|
|
3198
3284
|
set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
|
|
3199
3285
|
set$(ctx, `containerColumn${i}`, -1);
|
|
@@ -3243,8 +3329,7 @@ function handleLayout(ctx, layout, setCanRender) {
|
|
|
3243
3329
|
if (maintainScrollAtEnd === true || maintainScrollAtEnd.onLayout) {
|
|
3244
3330
|
doMaintainScrollAtEnd(ctx, false);
|
|
3245
3331
|
}
|
|
3246
|
-
|
|
3247
|
-
checkAtTop(state);
|
|
3332
|
+
checkThresholds(ctx);
|
|
3248
3333
|
if (state) {
|
|
3249
3334
|
state.needsOtherAxisSize = otherAxisSize - (state.props.stylePaddingTop || 0) < 10;
|
|
3250
3335
|
}
|
|
@@ -3282,7 +3367,7 @@ function onScroll(ctx, event) {
|
|
|
3282
3367
|
}
|
|
3283
3368
|
}
|
|
3284
3369
|
let newScroll = event.nativeEvent.contentOffset[state.props.horizontal ? "x" : "y"];
|
|
3285
|
-
if (state.scrollingTo) {
|
|
3370
|
+
if (state.scrollingTo && state.scrollingTo.offset >= newScroll) {
|
|
3286
3371
|
const maxOffset = clampScrollOffset(ctx, newScroll);
|
|
3287
3372
|
if (newScroll !== maxOffset && Math.abs(newScroll - maxOffset) > 1) {
|
|
3288
3373
|
newScroll = maxOffset;
|
|
@@ -3355,6 +3440,26 @@ var ScrollAdjustHandler = class {
|
|
|
3355
3440
|
};
|
|
3356
3441
|
|
|
3357
3442
|
// src/core/updateItemSize.ts
|
|
3443
|
+
function runOrScheduleMVCPRecalculate(ctx) {
|
|
3444
|
+
const state = ctx.state;
|
|
3445
|
+
{
|
|
3446
|
+
if (!state.mvcpAnchorLock) {
|
|
3447
|
+
if (state.queuedMVCPRecalculate !== void 0) {
|
|
3448
|
+
cancelAnimationFrame(state.queuedMVCPRecalculate);
|
|
3449
|
+
state.queuedMVCPRecalculate = void 0;
|
|
3450
|
+
}
|
|
3451
|
+
calculateItemsInView(ctx, { doMVCP: true });
|
|
3452
|
+
return;
|
|
3453
|
+
}
|
|
3454
|
+
if (state.queuedMVCPRecalculate !== void 0) {
|
|
3455
|
+
return;
|
|
3456
|
+
}
|
|
3457
|
+
state.queuedMVCPRecalculate = requestAnimationFrame(() => {
|
|
3458
|
+
state.queuedMVCPRecalculate = void 0;
|
|
3459
|
+
calculateItemsInView(ctx, { doMVCP: true });
|
|
3460
|
+
});
|
|
3461
|
+
}
|
|
3462
|
+
}
|
|
3358
3463
|
function updateItemSize(ctx, itemKey, sizeObj) {
|
|
3359
3464
|
var _a3;
|
|
3360
3465
|
const state = ctx.state;
|
|
@@ -3438,7 +3543,7 @@ function updateItemSize(ctx, itemKey, sizeObj) {
|
|
|
3438
3543
|
if (didContainersLayout || checkAllSizesKnown(state)) {
|
|
3439
3544
|
if (needsRecalculate) {
|
|
3440
3545
|
state.scrollForNextCalculateItemsInView = void 0;
|
|
3441
|
-
|
|
3546
|
+
runOrScheduleMVCPRecalculate(ctx);
|
|
3442
3547
|
}
|
|
3443
3548
|
if (shouldMaintainScrollAtEnd) {
|
|
3444
3549
|
if (maintainScrollAtEnd === true || maintainScrollAtEnd.onItemLayout) {
|
|
@@ -3784,8 +3889,6 @@ function useThrottledOnScroll(originalHandler, scrollEventThrottle) {
|
|
|
3784
3889
|
}
|
|
3785
3890
|
|
|
3786
3891
|
// src/components/LegendList.tsx
|
|
3787
|
-
var DEFAULT_DRAW_DISTANCE = 250;
|
|
3788
|
-
var DEFAULT_ITEM_SIZE = 100;
|
|
3789
3892
|
var LegendList = typedMemo(
|
|
3790
3893
|
// biome-ignore lint/nursery/noShadow: const function name shadowing is intentional
|
|
3791
3894
|
typedForwardRef(function LegendList2(props, forwardedRef) {
|
|
@@ -3815,7 +3918,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
3815
3918
|
data: dataProp = [],
|
|
3816
3919
|
dataVersion,
|
|
3817
3920
|
drawDistance = 250,
|
|
3818
|
-
estimatedItemSize
|
|
3921
|
+
estimatedItemSize = 100,
|
|
3819
3922
|
estimatedListSize,
|
|
3820
3923
|
extraData,
|
|
3821
3924
|
getEstimatedItemSize,
|
|
@@ -3894,14 +3997,12 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
3894
3997
|
index: initialScrollIndexProp || 0,
|
|
3895
3998
|
viewOffset: initialScrollOffsetProp || 0
|
|
3896
3999
|
} : void 0;
|
|
3897
|
-
const [canRender, setCanRender] = React3__namespace.useState(
|
|
4000
|
+
const [canRender, setCanRender] = React3__namespace.useState(false);
|
|
3898
4001
|
const ctx = useStateContext();
|
|
3899
4002
|
ctx.columnWrapperStyle = columnWrapperStyle || (contentContainerStyle ? createColumnWrapperStyle(contentContainerStyle) : void 0);
|
|
3900
4003
|
const refScroller = React3.useRef(null);
|
|
3901
4004
|
const combinedRef = useCombinedRef(refScroller, refScrollView);
|
|
3902
|
-
const
|
|
3903
|
-
const scrollBuffer = (drawDistance != null ? drawDistance : DEFAULT_DRAW_DISTANCE) || 1;
|
|
3904
|
-
const keyExtractor = keyExtractorProp != null ? keyExtractorProp : (_item, index) => index.toString();
|
|
4005
|
+
const keyExtractor = keyExtractorProp != null ? keyExtractorProp : ((_item, index) => index.toString());
|
|
3905
4006
|
const stickyHeaderIndices = stickyHeaderIndicesProp != null ? stickyHeaderIndicesProp : stickyIndicesDeprecated;
|
|
3906
4007
|
const alwaysRenderIndices = React3.useMemo(() => {
|
|
3907
4008
|
const indices = getAlwaysRenderIndices(alwaysRender, dataProp, keyExtractor);
|
|
@@ -3930,8 +4031,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
3930
4031
|
ctx.state = {
|
|
3931
4032
|
activeStickyIndex: -1,
|
|
3932
4033
|
averageSizes: {},
|
|
3933
|
-
columns: /* @__PURE__ */ new Map(),
|
|
3934
4034
|
columnSpans: /* @__PURE__ */ new Map(),
|
|
4035
|
+
columns: /* @__PURE__ */ new Map(),
|
|
3935
4036
|
containerItemKeys: /* @__PURE__ */ new Map(),
|
|
3936
4037
|
containerItemTypes: /* @__PURE__ */ new Map(),
|
|
3937
4038
|
contentInsetOverride: void 0,
|
|
@@ -4018,6 +4119,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
4018
4119
|
contentInset,
|
|
4019
4120
|
data: dataProp,
|
|
4020
4121
|
dataVersion,
|
|
4122
|
+
drawDistance,
|
|
4021
4123
|
estimatedItemSize,
|
|
4022
4124
|
getEstimatedItemSize: useWrapIfItem(getEstimatedItemSize),
|
|
4023
4125
|
getFixedItemSize: useWrapIfItem(getFixedItemSize),
|
|
@@ -4041,7 +4143,6 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
4041
4143
|
overrideItemLayout,
|
|
4042
4144
|
recycleItems: !!recycleItems,
|
|
4043
4145
|
renderItem,
|
|
4044
|
-
scrollBuffer,
|
|
4045
4146
|
snapToIndices,
|
|
4046
4147
|
stickyIndicesArr: stickyHeaderIndices != null ? stickyHeaderIndices : [],
|
|
4047
4148
|
stickyIndicesSet: React3.useMemo(() => new Set(stickyHeaderIndices != null ? stickyHeaderIndices : []), [stickyHeaderIndices == null ? void 0 : stickyHeaderIndices.join(",")]),
|
|
@@ -4064,12 +4165,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
4064
4165
|
setPaddingTop(ctx, { stylePaddingTop: stylePaddingTopState });
|
|
4065
4166
|
refState.current.props.stylePaddingBottom = stylePaddingBottomState;
|
|
4066
4167
|
let paddingDiff = stylePaddingTopState - prevPaddingTop;
|
|
4067
|
-
if (shouldAdjustPadding && maintainVisibleContentPositionConfig.size && paddingDiff && prevPaddingTop !== void 0 && Platform.OS === "ios")
|
|
4068
|
-
if (state.scroll < 0) {
|
|
4069
|
-
paddingDiff += state.scroll;
|
|
4070
|
-
}
|
|
4071
|
-
requestAdjust(ctx, paddingDiff);
|
|
4072
|
-
}
|
|
4168
|
+
if (shouldAdjustPadding && maintainVisibleContentPositionConfig.size && paddingDiff && prevPaddingTop !== void 0 && Platform.OS === "ios") ;
|
|
4073
4169
|
};
|
|
4074
4170
|
if (isFirstLocal) {
|
|
4075
4171
|
initializeStateVars(false);
|
|
@@ -4271,7 +4367,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
4271
4367
|
updateItemSize: fns.updateItemSize,
|
|
4272
4368
|
waitForInitialLayout
|
|
4273
4369
|
}
|
|
4274
|
-
), IS_DEV && ENABLE_DEBUG_VIEW
|
|
4370
|
+
), IS_DEV && ENABLE_DEBUG_VIEW);
|
|
4275
4371
|
});
|
|
4276
4372
|
|
|
4277
4373
|
exports.LegendList = LegendList;
|