@legendapp/list 3.0.0-beta.31 → 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 +209 -115
- package/index.mjs +209 -115
- package/index.native.d.mts +10 -3
- package/index.native.d.ts +10 -3
- package/index.native.js +156 -78
- package/index.native.mjs +158 -80
- 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
|
|
|
@@ -1596,6 +1593,7 @@ function finishScrollTo(ctx) {
|
|
|
1596
1593
|
var SCROLL_END_IDLE_MS = 80;
|
|
1597
1594
|
var SCROLL_END_MAX_MS = 1500;
|
|
1598
1595
|
var SMOOTH_SCROLL_DURATION_MS = 320;
|
|
1596
|
+
var SCROLL_END_TARGET_EPSILON = 1;
|
|
1599
1597
|
function doScrollTo(ctx, params) {
|
|
1600
1598
|
const state = ctx.state;
|
|
1601
1599
|
const { animated, horizontal, offset } = params;
|
|
@@ -1606,7 +1604,10 @@ function doScrollTo(ctx, params) {
|
|
|
1606
1604
|
const top = horizontal ? 0 : offset;
|
|
1607
1605
|
node.scrollTo({ behavior: animated ? "smooth" : "auto", left, top });
|
|
1608
1606
|
if (animated) {
|
|
1609
|
-
listenForScrollEnd(ctx, node
|
|
1607
|
+
listenForScrollEnd(ctx, node, {
|
|
1608
|
+
horizontal: !!horizontal,
|
|
1609
|
+
targetOffset: offset
|
|
1610
|
+
});
|
|
1610
1611
|
} else {
|
|
1611
1612
|
state.scroll = offset;
|
|
1612
1613
|
setTimeout(() => {
|
|
@@ -1615,31 +1616,17 @@ function doScrollTo(ctx, params) {
|
|
|
1615
1616
|
}
|
|
1616
1617
|
}
|
|
1617
1618
|
}
|
|
1618
|
-
function listenForScrollEnd(ctx, node) {
|
|
1619
|
+
function listenForScrollEnd(ctx, node, params) {
|
|
1620
|
+
const { horizontal, targetOffset } = params;
|
|
1619
1621
|
const supportsScrollEnd = "onscrollend" in node;
|
|
1620
1622
|
let idleTimeout;
|
|
1621
1623
|
let maxTimeout;
|
|
1622
1624
|
let settled = false;
|
|
1623
1625
|
const targetToken = ctx.state.scrollingTo;
|
|
1624
|
-
const finish = () => {
|
|
1625
|
-
if (settled) return;
|
|
1626
|
-
settled = true;
|
|
1627
|
-
cleanup();
|
|
1628
|
-
if (targetToken === ctx.state.scrollingTo) {
|
|
1629
|
-
finishScrollTo(ctx);
|
|
1630
|
-
}
|
|
1631
|
-
};
|
|
1632
|
-
const onScroll2 = () => {
|
|
1633
|
-
if (idleTimeout) {
|
|
1634
|
-
clearTimeout(idleTimeout);
|
|
1635
|
-
}
|
|
1636
|
-
idleTimeout = setTimeout(finish, SCROLL_END_IDLE_MS);
|
|
1637
|
-
};
|
|
1638
1626
|
const cleanup = () => {
|
|
1627
|
+
node.removeEventListener("scroll", onScroll2);
|
|
1639
1628
|
if (supportsScrollEnd) {
|
|
1640
|
-
node.removeEventListener("scrollend",
|
|
1641
|
-
} else {
|
|
1642
|
-
node.removeEventListener("scroll", onScroll2);
|
|
1629
|
+
node.removeEventListener("scrollend", onScrollEnd);
|
|
1643
1630
|
}
|
|
1644
1631
|
if (idleTimeout) {
|
|
1645
1632
|
clearTimeout(idleTimeout);
|
|
@@ -1648,14 +1635,37 @@ function listenForScrollEnd(ctx, node) {
|
|
|
1648
1635
|
clearTimeout(maxTimeout);
|
|
1649
1636
|
}
|
|
1650
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);
|
|
1651
1662
|
if (supportsScrollEnd) {
|
|
1652
|
-
node.addEventListener("scrollend",
|
|
1663
|
+
node.addEventListener("scrollend", onScrollEnd);
|
|
1664
|
+
maxTimeout = setTimeout(() => finish("max"), SCROLL_END_MAX_MS);
|
|
1653
1665
|
} else {
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
maxTimeout = setTimeout(finish, SCROLL_END_MAX_MS);
|
|
1666
|
+
idleTimeout = setTimeout(() => finish("idle"), SMOOTH_SCROLL_DURATION_MS);
|
|
1667
|
+
maxTimeout = setTimeout(() => finish("max"), SCROLL_END_MAX_MS);
|
|
1657
1668
|
}
|
|
1658
|
-
return cleanup;
|
|
1659
1669
|
}
|
|
1660
1670
|
|
|
1661
1671
|
// src/core/scrollTo.ts
|
|
@@ -1680,7 +1690,7 @@ function scrollTo(ctx, params) {
|
|
|
1680
1690
|
}
|
|
1681
1691
|
state.scrollPending = offset;
|
|
1682
1692
|
if (forceScroll || !isInitialScroll || Platform.OS === "android") {
|
|
1683
|
-
doScrollTo(ctx, { animated, horizontal,
|
|
1693
|
+
doScrollTo(ctx, { animated, horizontal, offset });
|
|
1684
1694
|
} else {
|
|
1685
1695
|
state.scroll = offset;
|
|
1686
1696
|
}
|
|
@@ -1723,7 +1733,8 @@ function updateScroll(ctx, newScroll, forceUpdate) {
|
|
|
1723
1733
|
const scrollDelta = Math.abs(newScroll - prevScroll);
|
|
1724
1734
|
const scrollLength = state.scrollLength;
|
|
1725
1735
|
const lastCalculated = state.scrollLastCalculate;
|
|
1726
|
-
const
|
|
1736
|
+
const useAggressiveItemRecalculation = isInMVCPActiveMode(state);
|
|
1737
|
+
const shouldUpdate = useAggressiveItemRecalculation || forceUpdate || lastCalculated === void 0 || Math.abs(state.scroll - lastCalculated) > 2;
|
|
1727
1738
|
if (shouldUpdate) {
|
|
1728
1739
|
state.scrollLastCalculate = state.scroll;
|
|
1729
1740
|
state.ignoreScrollFromMVCPIgnored = false;
|
|
@@ -1768,13 +1779,58 @@ function requestAdjust(ctx, positionDiff, dataChanged) {
|
|
|
1768
1779
|
}
|
|
1769
1780
|
|
|
1770
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
|
+
}
|
|
1771
1824
|
function prepareMVCP(ctx, dataChanged) {
|
|
1772
1825
|
const state = ctx.state;
|
|
1773
1826
|
const { idsInView, positions, props } = state;
|
|
1774
1827
|
const {
|
|
1775
1828
|
maintainVisibleContentPosition: { data: mvcpData, size: mvcpScroll, shouldRestorePosition }
|
|
1776
1829
|
} = props;
|
|
1830
|
+
const now = Date.now();
|
|
1831
|
+
const enableMVCPAnchorLock = (!!dataChanged || !!state.mvcpAnchorLock);
|
|
1777
1832
|
const scrollingTo = state.scrollingTo;
|
|
1833
|
+
const anchorLock = resolveAnchorLock(state, enableMVCPAnchorLock, mvcpData, now) ;
|
|
1778
1834
|
let prevPosition;
|
|
1779
1835
|
let targetId;
|
|
1780
1836
|
const idsInViewWithPositions = [];
|
|
@@ -1783,28 +1839,45 @@ function prepareMVCP(ctx, dataChanged) {
|
|
|
1783
1839
|
const shouldMVCP = dataChanged ? mvcpData : mvcpScroll;
|
|
1784
1840
|
const indexByKey = state.indexByKey;
|
|
1785
1841
|
if (shouldMVCP) {
|
|
1786
|
-
if (scrollTarget
|
|
1842
|
+
if (anchorLock && scrollTarget === void 0) {
|
|
1843
|
+
targetId = anchorLock.id;
|
|
1844
|
+
prevPosition = anchorLock.position;
|
|
1845
|
+
} else if (scrollTarget !== void 0) {
|
|
1787
1846
|
targetId = getId(state, scrollTarget);
|
|
1788
|
-
} else if (idsInView.length > 0 && state.didContainersLayout) {
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
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) });
|
|
1796
1856
|
}
|
|
1797
|
-
} else {
|
|
1798
|
-
targetId = idsInView.find((id) => indexByKey.get(id) !== void 0);
|
|
1799
1857
|
}
|
|
1800
1858
|
}
|
|
1801
|
-
if (targetId !== void 0) {
|
|
1859
|
+
if (targetId !== void 0 && prevPosition === void 0) {
|
|
1802
1860
|
prevPosition = positions.get(targetId);
|
|
1803
1861
|
}
|
|
1804
1862
|
return () => {
|
|
1805
1863
|
let positionDiff = 0;
|
|
1806
|
-
|
|
1807
|
-
|
|
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) {
|
|
1808
1881
|
for (let i = 0; i < idsInViewWithPositions.length; i++) {
|
|
1809
1882
|
const { id, position } = idsInViewWithPositions[i];
|
|
1810
1883
|
const index = indexByKey.get(id);
|
|
@@ -1817,11 +1890,13 @@ function prepareMVCP(ctx, dataChanged) {
|
|
|
1817
1890
|
const newPosition = positions.get(id);
|
|
1818
1891
|
if (newPosition !== void 0) {
|
|
1819
1892
|
positionDiff = newPosition - position;
|
|
1893
|
+
anchorIdForLock = id;
|
|
1894
|
+
anchorPositionForLock = newPosition;
|
|
1820
1895
|
break;
|
|
1821
1896
|
}
|
|
1822
1897
|
}
|
|
1823
1898
|
}
|
|
1824
|
-
if (targetId !== void 0 && prevPosition !== void 0) {
|
|
1899
|
+
if (!skipTargetAnchor && targetId !== void 0 && prevPosition !== void 0) {
|
|
1825
1900
|
const newPosition = positions.get(targetId);
|
|
1826
1901
|
if (newPosition !== void 0) {
|
|
1827
1902
|
const totalSize = getContentSize(ctx);
|
|
@@ -1834,20 +1909,29 @@ function prepareMVCP(ctx, dataChanged) {
|
|
|
1834
1909
|
}
|
|
1835
1910
|
}
|
|
1836
1911
|
positionDiff = diff;
|
|
1912
|
+
anchorIdForLock = targetId;
|
|
1913
|
+
anchorPositionForLock = newPosition;
|
|
1837
1914
|
}
|
|
1838
1915
|
}
|
|
1839
1916
|
if (scrollingToViewPosition && scrollingToViewPosition > 0) {
|
|
1840
1917
|
const newSize = getItemSize(ctx, targetId, scrollTarget, state.props.data[scrollTarget]);
|
|
1841
1918
|
const prevSize = scrollingTo == null ? void 0 : scrollingTo.itemSize;
|
|
1842
|
-
if (newSize !== void 0 && prevSize !== void 0 && newSize !==
|
|
1919
|
+
if (newSize !== void 0 && prevSize !== void 0 && newSize !== prevSize) {
|
|
1843
1920
|
const diff = newSize - prevSize;
|
|
1844
1921
|
if (diff !== 0) {
|
|
1845
|
-
positionDiff +=
|
|
1922
|
+
positionDiff += diff * scrollingToViewPosition;
|
|
1846
1923
|
scrollingTo.itemSize = newSize;
|
|
1847
1924
|
}
|
|
1848
1925
|
}
|
|
1849
1926
|
}
|
|
1850
|
-
|
|
1927
|
+
updateAnchorLock(state, {
|
|
1928
|
+
anchorId: anchorIdForLock,
|
|
1929
|
+
anchorPosition: anchorPositionForLock,
|
|
1930
|
+
dataChanged,
|
|
1931
|
+
now,
|
|
1932
|
+
positionDiff
|
|
1933
|
+
});
|
|
1934
|
+
if (Math.abs(positionDiff) > MVCP_POSITION_EPSILON) {
|
|
1851
1935
|
requestAdjust(ctx, positionDiff);
|
|
1852
1936
|
}
|
|
1853
1937
|
};
|
|
@@ -2561,7 +2645,7 @@ function handleStickyActivation(ctx, stickyHeaderIndices, stickyArray, currentSt
|
|
|
2561
2645
|
}
|
|
2562
2646
|
}
|
|
2563
2647
|
}
|
|
2564
|
-
function handleStickyRecycling(ctx, stickyArray, scroll,
|
|
2648
|
+
function handleStickyRecycling(ctx, stickyArray, scroll, drawDistance, currentStickyIdx, pendingRemoval, alwaysRenderIndicesSet) {
|
|
2565
2649
|
var _a3, _b, _c;
|
|
2566
2650
|
const state = ctx.state;
|
|
2567
2651
|
for (const containerIndex of state.stickyContainerPool) {
|
|
@@ -2582,13 +2666,13 @@ function handleStickyRecycling(ctx, stickyArray, scroll, scrollBuffer, currentSt
|
|
|
2582
2666
|
if (nextIndex) {
|
|
2583
2667
|
const nextId = (_a3 = state.idCache[nextIndex]) != null ? _a3 : getId(state, nextIndex);
|
|
2584
2668
|
const nextPos = nextId ? state.positions.get(nextId) : void 0;
|
|
2585
|
-
shouldRecycle = nextPos !== void 0 && scroll > nextPos +
|
|
2669
|
+
shouldRecycle = nextPos !== void 0 && scroll > nextPos + drawDistance * 2;
|
|
2586
2670
|
} else {
|
|
2587
2671
|
const currentId = (_b = state.idCache[itemIndex]) != null ? _b : getId(state, itemIndex);
|
|
2588
2672
|
if (currentId) {
|
|
2589
2673
|
const currentPos = state.positions.get(currentId);
|
|
2590
2674
|
const currentSize = (_c = state.sizes.get(currentId)) != null ? _c : getItemSize(ctx, currentId, itemIndex, state.props.data[itemIndex]);
|
|
2591
|
-
shouldRecycle = currentPos !== void 0 && scroll > currentPos + currentSize +
|
|
2675
|
+
shouldRecycle = currentPos !== void 0 && scroll > currentPos + currentSize + drawDistance * 3;
|
|
2592
2676
|
}
|
|
2593
2677
|
}
|
|
2594
2678
|
if (shouldRecycle) {
|
|
@@ -2613,11 +2697,11 @@ function calculateItemsInView(ctx, params = {}) {
|
|
|
2613
2697
|
props: {
|
|
2614
2698
|
alwaysRenderIndicesArr,
|
|
2615
2699
|
alwaysRenderIndicesSet,
|
|
2700
|
+
drawDistance,
|
|
2616
2701
|
getItemType,
|
|
2617
2702
|
itemsAreEqual,
|
|
2618
2703
|
keyExtractor,
|
|
2619
|
-
onStickyHeaderChange
|
|
2620
|
-
scrollBuffer
|
|
2704
|
+
onStickyHeaderChange
|
|
2621
2705
|
},
|
|
2622
2706
|
scrollForNextCalculateItemsInView,
|
|
2623
2707
|
scrollLength,
|
|
@@ -2630,6 +2714,7 @@ function calculateItemsInView(ctx, params = {}) {
|
|
|
2630
2714
|
const stickyIndicesSet = state.props.stickyIndicesSet || /* @__PURE__ */ new Set();
|
|
2631
2715
|
const alwaysRenderArr = alwaysRenderIndicesArr || [];
|
|
2632
2716
|
const alwaysRenderSet = alwaysRenderIndicesSet || /* @__PURE__ */ new Set();
|
|
2717
|
+
const { dataChanged, doMVCP, forceFullItemPositions } = params;
|
|
2633
2718
|
const prevNumContainers = peek$(ctx, "numContainers");
|
|
2634
2719
|
if (!data || scrollLength === 0 || !prevNumContainers) {
|
|
2635
2720
|
return;
|
|
@@ -2637,7 +2722,6 @@ function calculateItemsInView(ctx, params = {}) {
|
|
|
2637
2722
|
const totalSize = getContentSize(ctx);
|
|
2638
2723
|
const topPad = peek$(ctx, "stylePaddingTop") + peek$(ctx, "headerSize");
|
|
2639
2724
|
const numColumns = peek$(ctx, "numColumns");
|
|
2640
|
-
const { dataChanged, doMVCP, forceFullItemPositions } = params;
|
|
2641
2725
|
const speed = getScrollVelocity(state);
|
|
2642
2726
|
const scrollExtra = 0;
|
|
2643
2727
|
const { queuedInitialLayout } = state;
|
|
@@ -2656,24 +2740,20 @@ function calculateItemsInView(ctx, params = {}) {
|
|
|
2656
2740
|
if (scroll + scrollLength > totalSize) {
|
|
2657
2741
|
scroll = Math.max(0, totalSize - scrollLength);
|
|
2658
2742
|
}
|
|
2659
|
-
if (ENABLE_DEBUG_VIEW) {
|
|
2660
|
-
set$(ctx, "debugRawScroll", scrollState);
|
|
2661
|
-
set$(ctx, "debugComputedScroll", scroll);
|
|
2662
|
-
}
|
|
2663
2743
|
const previousStickyIndex = peek$(ctx, "activeStickyIndex");
|
|
2664
2744
|
const currentStickyIdx = stickyIndicesArr.length > 0 ? findCurrentStickyIndex(stickyIndicesArr, scroll, state) : -1;
|
|
2665
2745
|
const nextActiveStickyIndex = currentStickyIdx >= 0 ? stickyIndicesArr[currentStickyIdx] : -1;
|
|
2666
2746
|
if (currentStickyIdx >= 0 || previousStickyIndex >= 0) {
|
|
2667
2747
|
set$(ctx, "activeStickyIndex", nextActiveStickyIndex);
|
|
2668
2748
|
}
|
|
2669
|
-
let scrollBufferTop =
|
|
2670
|
-
let scrollBufferBottom =
|
|
2671
|
-
if (speed > 0 || speed === 0 && scroll < Math.max(50,
|
|
2672
|
-
scrollBufferTop =
|
|
2673
|
-
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;
|
|
2674
2754
|
} else {
|
|
2675
|
-
scrollBufferTop =
|
|
2676
|
-
scrollBufferBottom =
|
|
2755
|
+
scrollBufferTop = drawDistance * 1.5;
|
|
2756
|
+
scrollBufferBottom = drawDistance * 0.5;
|
|
2677
2757
|
}
|
|
2678
2758
|
const scrollTopBuffered = scroll - scrollBufferTop;
|
|
2679
2759
|
const scrollBottom = scroll + scrollLength + (scroll < 0 ? -scroll : 0);
|
|
@@ -2683,7 +2763,9 @@ function calculateItemsInView(ctx, params = {}) {
|
|
|
2683
2763
|
if (top === null && bottom === null) {
|
|
2684
2764
|
state.scrollForNextCalculateItemsInView = void 0;
|
|
2685
2765
|
} else if ((top === null || scrollTopBuffered > top) && (bottom === null || scrollBottomBuffered < bottom)) {
|
|
2686
|
-
|
|
2766
|
+
if (!isInMVCPActiveMode(state)) {
|
|
2767
|
+
return;
|
|
2768
|
+
}
|
|
2687
2769
|
}
|
|
2688
2770
|
}
|
|
2689
2771
|
const checkMVCP = doMVCP ? prepareMVCP(ctx, dataChanged) : void 0;
|
|
@@ -2915,7 +2997,7 @@ function calculateItemsInView(ctx, params = {}) {
|
|
|
2915
2997
|
ctx,
|
|
2916
2998
|
stickyIndicesArr,
|
|
2917
2999
|
scroll,
|
|
2918
|
-
|
|
3000
|
+
drawDistance,
|
|
2919
3001
|
currentStickyIdx,
|
|
2920
3002
|
pendingRemoval,
|
|
2921
3003
|
alwaysRenderSet
|
|
@@ -3027,7 +3109,8 @@ function checkFinishedScrollFrame(ctx) {
|
|
|
3027
3109
|
const diff1 = Math.abs(scroll - clampedTargetOffset);
|
|
3028
3110
|
const diff2 = Math.abs(diff1 - adjust);
|
|
3029
3111
|
const isNotOverscrolled = Math.abs(scroll - maxOffset) < 1;
|
|
3030
|
-
|
|
3112
|
+
const isAtTarget = diff1 < 1 || !scrollingTo.animated && diff2 < 1;
|
|
3113
|
+
if (isNotOverscrolled && isAtTarget) {
|
|
3031
3114
|
finishScrollTo(ctx);
|
|
3032
3115
|
}
|
|
3033
3116
|
}
|
|
@@ -3171,10 +3254,10 @@ function doInitialAllocateContainers(ctx) {
|
|
|
3171
3254
|
scrollLength,
|
|
3172
3255
|
props: {
|
|
3173
3256
|
data,
|
|
3257
|
+
drawDistance,
|
|
3174
3258
|
getEstimatedItemSize,
|
|
3175
3259
|
getFixedItemSize,
|
|
3176
3260
|
getItemType,
|
|
3177
|
-
scrollBuffer,
|
|
3178
3261
|
numColumns,
|
|
3179
3262
|
estimatedItemSize
|
|
3180
3263
|
}
|
|
@@ -3196,7 +3279,7 @@ function doInitialAllocateContainers(ctx) {
|
|
|
3196
3279
|
} else {
|
|
3197
3280
|
averageItemSize = estimatedItemSize;
|
|
3198
3281
|
}
|
|
3199
|
-
const numContainers = Math.ceil((scrollLength +
|
|
3282
|
+
const numContainers = Math.ceil((scrollLength + drawDistance * 2) / averageItemSize * numColumns);
|
|
3200
3283
|
for (let i = 0; i < numContainers; i++) {
|
|
3201
3284
|
set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
|
|
3202
3285
|
set$(ctx, `containerColumn${i}`, -1);
|
|
@@ -3284,7 +3367,7 @@ function onScroll(ctx, event) {
|
|
|
3284
3367
|
}
|
|
3285
3368
|
}
|
|
3286
3369
|
let newScroll = event.nativeEvent.contentOffset[state.props.horizontal ? "x" : "y"];
|
|
3287
|
-
if (state.scrollingTo) {
|
|
3370
|
+
if (state.scrollingTo && state.scrollingTo.offset >= newScroll) {
|
|
3288
3371
|
const maxOffset = clampScrollOffset(ctx, newScroll);
|
|
3289
3372
|
if (newScroll !== maxOffset && Math.abs(newScroll - maxOffset) > 1) {
|
|
3290
3373
|
newScroll = maxOffset;
|
|
@@ -3357,6 +3440,26 @@ var ScrollAdjustHandler = class {
|
|
|
3357
3440
|
};
|
|
3358
3441
|
|
|
3359
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
|
+
}
|
|
3360
3463
|
function updateItemSize(ctx, itemKey, sizeObj) {
|
|
3361
3464
|
var _a3;
|
|
3362
3465
|
const state = ctx.state;
|
|
@@ -3440,7 +3543,7 @@ function updateItemSize(ctx, itemKey, sizeObj) {
|
|
|
3440
3543
|
if (didContainersLayout || checkAllSizesKnown(state)) {
|
|
3441
3544
|
if (needsRecalculate) {
|
|
3442
3545
|
state.scrollForNextCalculateItemsInView = void 0;
|
|
3443
|
-
|
|
3546
|
+
runOrScheduleMVCPRecalculate(ctx);
|
|
3444
3547
|
}
|
|
3445
3548
|
if (shouldMaintainScrollAtEnd) {
|
|
3446
3549
|
if (maintainScrollAtEnd === true || maintainScrollAtEnd.onItemLayout) {
|
|
@@ -3786,8 +3889,6 @@ function useThrottledOnScroll(originalHandler, scrollEventThrottle) {
|
|
|
3786
3889
|
}
|
|
3787
3890
|
|
|
3788
3891
|
// src/components/LegendList.tsx
|
|
3789
|
-
var DEFAULT_DRAW_DISTANCE = 250;
|
|
3790
|
-
var DEFAULT_ITEM_SIZE = 100;
|
|
3791
3892
|
var LegendList = typedMemo(
|
|
3792
3893
|
// biome-ignore lint/nursery/noShadow: const function name shadowing is intentional
|
|
3793
3894
|
typedForwardRef(function LegendList2(props, forwardedRef) {
|
|
@@ -3817,7 +3918,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
3817
3918
|
data: dataProp = [],
|
|
3818
3919
|
dataVersion,
|
|
3819
3920
|
drawDistance = 250,
|
|
3820
|
-
estimatedItemSize
|
|
3921
|
+
estimatedItemSize = 100,
|
|
3821
3922
|
estimatedListSize,
|
|
3822
3923
|
extraData,
|
|
3823
3924
|
getEstimatedItemSize,
|
|
@@ -3896,14 +3997,12 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
3896
3997
|
index: initialScrollIndexProp || 0,
|
|
3897
3998
|
viewOffset: initialScrollOffsetProp || 0
|
|
3898
3999
|
} : void 0;
|
|
3899
|
-
const [canRender, setCanRender] = React3__namespace.useState(
|
|
4000
|
+
const [canRender, setCanRender] = React3__namespace.useState(false);
|
|
3900
4001
|
const ctx = useStateContext();
|
|
3901
4002
|
ctx.columnWrapperStyle = columnWrapperStyle || (contentContainerStyle ? createColumnWrapperStyle(contentContainerStyle) : void 0);
|
|
3902
4003
|
const refScroller = React3.useRef(null);
|
|
3903
4004
|
const combinedRef = useCombinedRef(refScroller, refScrollView);
|
|
3904
|
-
const
|
|
3905
|
-
const scrollBuffer = (drawDistance != null ? drawDistance : DEFAULT_DRAW_DISTANCE) || 1;
|
|
3906
|
-
const keyExtractor = keyExtractorProp != null ? keyExtractorProp : (_item, index) => index.toString();
|
|
4005
|
+
const keyExtractor = keyExtractorProp != null ? keyExtractorProp : ((_item, index) => index.toString());
|
|
3907
4006
|
const stickyHeaderIndices = stickyHeaderIndicesProp != null ? stickyHeaderIndicesProp : stickyIndicesDeprecated;
|
|
3908
4007
|
const alwaysRenderIndices = React3.useMemo(() => {
|
|
3909
4008
|
const indices = getAlwaysRenderIndices(alwaysRender, dataProp, keyExtractor);
|
|
@@ -3932,8 +4031,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
3932
4031
|
ctx.state = {
|
|
3933
4032
|
activeStickyIndex: -1,
|
|
3934
4033
|
averageSizes: {},
|
|
3935
|
-
columns: /* @__PURE__ */ new Map(),
|
|
3936
4034
|
columnSpans: /* @__PURE__ */ new Map(),
|
|
4035
|
+
columns: /* @__PURE__ */ new Map(),
|
|
3937
4036
|
containerItemKeys: /* @__PURE__ */ new Map(),
|
|
3938
4037
|
containerItemTypes: /* @__PURE__ */ new Map(),
|
|
3939
4038
|
contentInsetOverride: void 0,
|
|
@@ -4020,6 +4119,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
4020
4119
|
contentInset,
|
|
4021
4120
|
data: dataProp,
|
|
4022
4121
|
dataVersion,
|
|
4122
|
+
drawDistance,
|
|
4023
4123
|
estimatedItemSize,
|
|
4024
4124
|
getEstimatedItemSize: useWrapIfItem(getEstimatedItemSize),
|
|
4025
4125
|
getFixedItemSize: useWrapIfItem(getFixedItemSize),
|
|
@@ -4043,7 +4143,6 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
4043
4143
|
overrideItemLayout,
|
|
4044
4144
|
recycleItems: !!recycleItems,
|
|
4045
4145
|
renderItem,
|
|
4046
|
-
scrollBuffer,
|
|
4047
4146
|
snapToIndices,
|
|
4048
4147
|
stickyIndicesArr: stickyHeaderIndices != null ? stickyHeaderIndices : [],
|
|
4049
4148
|
stickyIndicesSet: React3.useMemo(() => new Set(stickyHeaderIndices != null ? stickyHeaderIndices : []), [stickyHeaderIndices == null ? void 0 : stickyHeaderIndices.join(",")]),
|
|
@@ -4066,12 +4165,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
4066
4165
|
setPaddingTop(ctx, { stylePaddingTop: stylePaddingTopState });
|
|
4067
4166
|
refState.current.props.stylePaddingBottom = stylePaddingBottomState;
|
|
4068
4167
|
let paddingDiff = stylePaddingTopState - prevPaddingTop;
|
|
4069
|
-
if (shouldAdjustPadding && maintainVisibleContentPositionConfig.size && paddingDiff && prevPaddingTop !== void 0 && Platform.OS === "ios")
|
|
4070
|
-
if (state.scroll < 0) {
|
|
4071
|
-
paddingDiff += state.scroll;
|
|
4072
|
-
}
|
|
4073
|
-
requestAdjust(ctx, paddingDiff);
|
|
4074
|
-
}
|
|
4168
|
+
if (shouldAdjustPadding && maintainVisibleContentPositionConfig.size && paddingDiff && prevPaddingTop !== void 0 && Platform.OS === "ios") ;
|
|
4075
4169
|
};
|
|
4076
4170
|
if (isFirstLocal) {
|
|
4077
4171
|
initializeStateVars(false);
|
|
@@ -4273,7 +4367,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
4273
4367
|
updateItemSize: fns.updateItemSize,
|
|
4274
4368
|
waitForInitialLayout
|
|
4275
4369
|
}
|
|
4276
|
-
), IS_DEV && ENABLE_DEBUG_VIEW
|
|
4370
|
+
), IS_DEV && ENABLE_DEBUG_VIEW);
|
|
4277
4371
|
});
|
|
4278
4372
|
|
|
4279
4373
|
exports.LegendList = LegendList;
|