@legendapp/list 3.0.0-beta.31 → 3.0.0-beta.33
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/README.md +7 -1
- package/animated.d.ts +600 -6
- package/animated.js +2 -2
- package/animated.mjs +1 -1
- package/index.d.ts +462 -109
- package/index.js +290 -147
- package/index.mjs +290 -147
- package/index.native.js +245 -122
- package/index.native.mjs +246 -123
- package/keyboard-controller.d.ts +611 -6
- package/keyboard-controller.js +2 -2
- package/keyboard-controller.mjs +1 -1
- package/keyboard.d.ts +204 -8
- package/keyboard.js +66 -52
- package/keyboard.mjs +69 -54
- package/{index.d.mts → list-react-native.d.ts} +103 -33
- package/list-react-native.js +4234 -0
- package/list-react-native.mjs +4204 -0
- package/{index.native.d.mts → list-react.d.ts} +363 -41
- package/list-react.js +4426 -0
- package/list-react.mjs +4396 -0
- package/package.json +52 -1
- package/reanimated.d.ts +595 -7
- package/reanimated.js +156 -11
- package/reanimated.mjs +153 -8
- package/section-list.d.ts +610 -14
- package/section-list.js +6 -6
- package/section-list.mjs +1 -1
- package/animated.d.mts +0 -9
- package/animated.native.d.mts +0 -9
- package/animated.native.d.ts +0 -9
- package/animated.native.js +0 -9
- package/animated.native.mjs +0 -7
- package/index.native.d.ts +0 -810
- package/keyboard-controller.d.mts +0 -12
- package/keyboard-controller.native.d.mts +0 -12
- package/keyboard-controller.native.d.ts +0 -12
- package/keyboard-controller.native.js +0 -69
- package/keyboard-controller.native.mjs +0 -48
- package/keyboard.d.mts +0 -13
- package/keyboard.native.d.mts +0 -13
- package/keyboard.native.d.ts +0 -13
- package/keyboard.native.js +0 -399
- package/keyboard.native.mjs +0 -377
- package/reanimated.d.mts +0 -18
- package/reanimated.native.d.mts +0 -18
- package/reanimated.native.d.ts +0 -18
- package/reanimated.native.js +0 -89
- package/reanimated.native.mjs +0 -65
- package/section-list.d.mts +0 -112
- package/section-list.native.d.mts +0 -112
- package/section-list.native.d.ts +0 -112
- package/section-list.native.js +0 -293
- package/section-list.native.mjs +0 -271
package/index.mjs
CHANGED
|
@@ -21,7 +21,7 @@ function getContentInsetEnd(state) {
|
|
|
21
21
|
const baseInset = contentInset != null ? contentInset : state.nativeContentInset;
|
|
22
22
|
const overrideInset = (_a3 = state.contentInsetOverride) != null ? _a3 : void 0;
|
|
23
23
|
if (overrideInset) {
|
|
24
|
-
const mergedInset = { bottom: 0,
|
|
24
|
+
const mergedInset = { bottom: 0, right: 0, ...baseInset, ...overrideInset };
|
|
25
25
|
return (horizontal ? mergedInset.right : mergedInset.bottom) || 0;
|
|
26
26
|
}
|
|
27
27
|
if (baseInset) {
|
|
@@ -172,7 +172,7 @@ function useSelector$(signalName, selector) {
|
|
|
172
172
|
var DebugRow = ({ children }) => {
|
|
173
173
|
return /* @__PURE__ */ React3.createElement(View, { style: { alignItems: "center", flexDirection: "row", justifyContent: "space-between" } }, children);
|
|
174
174
|
};
|
|
175
|
-
|
|
175
|
+
React3.memo(function DebugView2({ state }) {
|
|
176
176
|
const ctx = useStateContext();
|
|
177
177
|
const [totalSize = 0, scrollAdjust = 0, rawScroll = 0, scroll = 0, _numContainers = 0, _numContainersPooled = 0] = useArr$([
|
|
178
178
|
"totalSize",
|
|
@@ -224,7 +224,7 @@ var _a;
|
|
|
224
224
|
var envMode = typeof process !== "undefined" && typeof process.env === "object" && process.env ? (_a = process.env.NODE_ENV) != null ? _a : process.env.MODE : void 0;
|
|
225
225
|
var processDev = typeof envMode === "string" ? envMode.toLowerCase() !== "production" : void 0;
|
|
226
226
|
var _a2;
|
|
227
|
-
var IS_DEV = (_a2 =
|
|
227
|
+
var IS_DEV = (_a2 = processDev != null ? processDev : metroDev) != null ? _a2 : false;
|
|
228
228
|
|
|
229
229
|
// src/constants.ts
|
|
230
230
|
var POSITION_OUT_OF_VIEW = -1e7;
|
|
@@ -307,7 +307,10 @@ var PositionViewSticky = typedMemo(function PositionViewSticky2({
|
|
|
307
307
|
children,
|
|
308
308
|
...rest
|
|
309
309
|
}) {
|
|
310
|
-
const [position = POSITION_OUT_OF_VIEW, activeStickyIndex] = useArr$([
|
|
310
|
+
const [position = POSITION_OUT_OF_VIEW, activeStickyIndex] = useArr$([
|
|
311
|
+
`containerPosition${id}`,
|
|
312
|
+
"activeStickyIndex"
|
|
313
|
+
]);
|
|
311
314
|
const base = {
|
|
312
315
|
contain: "paint layout style"
|
|
313
316
|
};
|
|
@@ -337,9 +340,6 @@ var PositionViewSticky = typedMemo(function PositionViewSticky2({
|
|
|
337
340
|
return /* @__PURE__ */ React3.createElement("div", { ref: refView, style: viewStyle, ...rest }, children);
|
|
338
341
|
});
|
|
339
342
|
var PositionView = PositionViewState;
|
|
340
|
-
|
|
341
|
-
// src/constants-platform.ts
|
|
342
|
-
var IsNewArchitecture = true;
|
|
343
343
|
function useInit(cb) {
|
|
344
344
|
useState(() => cb());
|
|
345
345
|
}
|
|
@@ -550,7 +550,8 @@ function createResizeObserver(element, callback) {
|
|
|
550
550
|
function useOnLayoutSync({
|
|
551
551
|
ref,
|
|
552
552
|
onLayoutProp,
|
|
553
|
-
onLayoutChange
|
|
553
|
+
onLayoutChange,
|
|
554
|
+
webLayoutResync
|
|
554
555
|
}, deps) {
|
|
555
556
|
useLayoutEffect(() => {
|
|
556
557
|
var _a3, _b;
|
|
@@ -574,7 +575,9 @@ function useOnLayoutSync({
|
|
|
574
575
|
var _a4;
|
|
575
576
|
const target = entry.target instanceof HTMLElement ? entry.target : void 0;
|
|
576
577
|
const rectObserved = (_a4 = entry.contentRect) != null ? _a4 : target == null ? void 0 : target.getBoundingClientRect();
|
|
577
|
-
|
|
578
|
+
const didSizeChange = rectObserved.width !== prevRect.width || rectObserved.height !== prevRect.height;
|
|
579
|
+
const shouldResyncLayout = !!(webLayoutResync == null ? void 0 : webLayoutResync());
|
|
580
|
+
if (didSizeChange || shouldResyncLayout) {
|
|
578
581
|
prevRect = rectObserved;
|
|
579
582
|
emit(toLayout(rectObserved), false);
|
|
580
583
|
}
|
|
@@ -600,6 +603,15 @@ var Platform = {
|
|
|
600
603
|
OS: "web"
|
|
601
604
|
};
|
|
602
605
|
|
|
606
|
+
// src/utils/isInMVCPActiveMode.ts
|
|
607
|
+
function isInMVCPActiveMode(state) {
|
|
608
|
+
const lock = state.mvcpAnchorLock;
|
|
609
|
+
if (lock && Date.now() > lock.expiresAt) {
|
|
610
|
+
state.mvcpAnchorLock = void 0;
|
|
611
|
+
}
|
|
612
|
+
return state.dataChangeNeedsScrollUpdate || !!state.mvcpAnchorLock;
|
|
613
|
+
}
|
|
614
|
+
|
|
603
615
|
// src/components/Container.tsx
|
|
604
616
|
var Container = typedMemo(function Container2({
|
|
605
617
|
id,
|
|
@@ -612,6 +624,7 @@ var Container = typedMemo(function Container2({
|
|
|
612
624
|
}) {
|
|
613
625
|
const ctx = useStateContext();
|
|
614
626
|
const { columnWrapperStyle, animatedScrollY } = ctx;
|
|
627
|
+
const stickyPositionComponentInternal = ctx.state.props.stickyPositionComponentInternal;
|
|
615
628
|
const [column = 0, span = 1, data, itemKey, numColumns = 1, extraData, isSticky] = useArr$([
|
|
616
629
|
`containerColumn${id}`,
|
|
617
630
|
`containerSpan${id}`,
|
|
@@ -707,7 +720,8 @@ var Container = typedMemo(function Container2({
|
|
|
707
720
|
updateItemSizeFn(currentItemKey, layout);
|
|
708
721
|
itemLayoutRef.current.didLayout = true;
|
|
709
722
|
};
|
|
710
|
-
|
|
723
|
+
const shouldDeferWebShrinkLayoutUpdate = !isInMVCPActiveMode(ctx.state) && prevSize !== void 0 && size + 1 < prevSize;
|
|
724
|
+
if (shouldDeferWebShrinkLayoutUpdate) {
|
|
711
725
|
const token = pendingShrinkToken + 1;
|
|
712
726
|
itemLayoutRef.current.pendingShrinkToken = token;
|
|
713
727
|
requestAnimationFrame(() => {
|
|
@@ -731,11 +745,12 @@ var Container = typedMemo(function Container2({
|
|
|
731
745
|
const { onLayout } = useOnLayoutSync(
|
|
732
746
|
{
|
|
733
747
|
onLayoutChange,
|
|
734
|
-
ref
|
|
748
|
+
ref,
|
|
749
|
+
webLayoutResync: () => isInMVCPActiveMode(ctx.state)
|
|
735
750
|
},
|
|
736
751
|
[itemKey, layoutRenderCount]
|
|
737
752
|
);
|
|
738
|
-
const PositionComponent = isSticky ? PositionViewSticky : PositionView;
|
|
753
|
+
const PositionComponent = isSticky ? stickyPositionComponentInternal ? stickyPositionComponentInternal : PositionViewSticky : PositionView;
|
|
739
754
|
return /* @__PURE__ */ React3.createElement(
|
|
740
755
|
PositionComponent,
|
|
741
756
|
{
|
|
@@ -923,25 +938,6 @@ var Containers = typedMemo(function Containers2({
|
|
|
923
938
|
}
|
|
924
939
|
return /* @__PURE__ */ React3.createElement(ContainersInner, { horizontal, numColumns, waitForInitialLayout }, containers);
|
|
925
940
|
});
|
|
926
|
-
function DevNumbers() {
|
|
927
|
-
return IS_DEV && // biome-ignore lint/nursery/noShadow: const function name shadowing is intentional
|
|
928
|
-
React3.memo(function DevNumbers2() {
|
|
929
|
-
return Array.from({ length: 100 }).map((_, index) => /* @__PURE__ */ React3.createElement(
|
|
930
|
-
"div",
|
|
931
|
-
{
|
|
932
|
-
key: index,
|
|
933
|
-
style: {
|
|
934
|
-
height: 100,
|
|
935
|
-
pointerEvents: "none",
|
|
936
|
-
position: "absolute",
|
|
937
|
-
top: index * 100,
|
|
938
|
-
width: "100%"
|
|
939
|
-
}
|
|
940
|
-
},
|
|
941
|
-
/* @__PURE__ */ React3.createElement("div", { style: { color: "red" } }, index * 100)
|
|
942
|
-
));
|
|
943
|
-
});
|
|
944
|
-
}
|
|
945
941
|
|
|
946
942
|
// src/platform/StyleSheet.tsx
|
|
947
943
|
function flattenStyles(styles) {
|
|
@@ -1116,6 +1112,7 @@ function useValueListener$(key, callback) {
|
|
|
1116
1112
|
function ScrollAdjust() {
|
|
1117
1113
|
const ctx = useStateContext();
|
|
1118
1114
|
const lastScrollOffsetRef = React3.useRef(0);
|
|
1115
|
+
const resetPaddingRafRef = React3.useRef(void 0);
|
|
1119
1116
|
const callback = React3.useCallback(() => {
|
|
1120
1117
|
var _a3;
|
|
1121
1118
|
const scrollAdjust = peek$(ctx, "scrollAdjust");
|
|
@@ -1130,13 +1127,17 @@ function ScrollAdjust() {
|
|
|
1130
1127
|
const nextScroll = prevScroll + scrollDelta;
|
|
1131
1128
|
const totalSize = el.scrollHeight;
|
|
1132
1129
|
if (scrollDelta > 0 && !ctx.state.adjustingFromInitialMount && totalSize < nextScroll + el.clientHeight) {
|
|
1130
|
+
const paddingBottom = ctx.state.props.stylePaddingBottom || 0;
|
|
1133
1131
|
const child = el.firstElementChild;
|
|
1134
1132
|
const pad = (nextScroll + el.clientHeight - totalSize) * 2;
|
|
1135
1133
|
child.style.paddingBottom = `${pad}px`;
|
|
1136
1134
|
void el.offsetHeight;
|
|
1137
1135
|
scrollView.scrollBy(0, scrollDelta);
|
|
1138
|
-
|
|
1139
|
-
|
|
1136
|
+
if (resetPaddingRafRef.current !== void 0) {
|
|
1137
|
+
cancelAnimationFrame(resetPaddingRafRef.current);
|
|
1138
|
+
}
|
|
1139
|
+
resetPaddingRafRef.current = requestAnimationFrame(() => {
|
|
1140
|
+
resetPaddingRafRef.current = void 0;
|
|
1140
1141
|
child.style.paddingBottom = paddingBottom ? `${paddingBottom}px` : "0";
|
|
1141
1142
|
});
|
|
1142
1143
|
} else {
|
|
@@ -1201,7 +1202,9 @@ var ListComponent = typedMemo(function ListComponent2({
|
|
|
1201
1202
|
const ctx = useStateContext();
|
|
1202
1203
|
const maintainVisibleContentPosition = ctx.state.props.maintainVisibleContentPosition;
|
|
1203
1204
|
const ScrollComponent = renderScrollComponent ? useMemo(
|
|
1204
|
-
() => React3.forwardRef(
|
|
1205
|
+
() => React3.forwardRef(
|
|
1206
|
+
(props, ref) => renderScrollComponent({ ...props, ref })
|
|
1207
|
+
),
|
|
1205
1208
|
[renderScrollComponent]
|
|
1206
1209
|
) : ListComponentScrollView;
|
|
1207
1210
|
const SnapOrScroll = snapToIndices ? SnapWrapper : ScrollComponent;
|
|
@@ -1258,7 +1261,7 @@ var ListComponent = typedMemo(function ListComponent2({
|
|
|
1258
1261
|
},
|
|
1259
1262
|
getComponent(ListFooterComponent)
|
|
1260
1263
|
),
|
|
1261
|
-
IS_DEV && ENABLE_DEVMODE
|
|
1264
|
+
IS_DEV && ENABLE_DEVMODE
|
|
1262
1265
|
);
|
|
1263
1266
|
});
|
|
1264
1267
|
|
|
@@ -1392,12 +1395,15 @@ function calculateOffsetWithOffsetPosition(ctx, offsetParam, params) {
|
|
|
1392
1395
|
}
|
|
1393
1396
|
|
|
1394
1397
|
// src/core/clampScrollOffset.ts
|
|
1395
|
-
function clampScrollOffset(ctx, offset) {
|
|
1398
|
+
function clampScrollOffset(ctx, offset, scrollTarget) {
|
|
1396
1399
|
const state = ctx.state;
|
|
1397
1400
|
const contentSize = getContentSize(ctx);
|
|
1398
1401
|
let clampedOffset = offset;
|
|
1399
1402
|
if (Number.isFinite(contentSize) && Number.isFinite(state.scrollLength) && (Platform.OS !== "android")) {
|
|
1400
|
-
const
|
|
1403
|
+
const baseMaxOffset = Math.max(0, contentSize - state.scrollLength);
|
|
1404
|
+
const viewOffset = scrollTarget == null ? void 0 : scrollTarget.viewOffset;
|
|
1405
|
+
const extraEndOffset = typeof viewOffset === "number" && viewOffset < 0 ? -viewOffset : 0;
|
|
1406
|
+
const maxOffset = baseMaxOffset + extraEndOffset;
|
|
1401
1407
|
clampedOffset = Math.min(offset, maxOffset);
|
|
1402
1408
|
}
|
|
1403
1409
|
clampedOffset = Math.max(0, clampedOffset);
|
|
@@ -1492,7 +1498,7 @@ function checkAtBottom(ctx) {
|
|
|
1492
1498
|
function checkAtTop(ctx) {
|
|
1493
1499
|
var _a3;
|
|
1494
1500
|
const state = ctx == null ? void 0 : ctx.state;
|
|
1495
|
-
if (!state || state.initialScroll) {
|
|
1501
|
+
if (!state || state.initialScroll || state.scrollingTo) {
|
|
1496
1502
|
return;
|
|
1497
1503
|
}
|
|
1498
1504
|
const {
|
|
@@ -1536,14 +1542,22 @@ function setInitialRenderState(ctx, {
|
|
|
1536
1542
|
didInitialScroll
|
|
1537
1543
|
}) {
|
|
1538
1544
|
const { state } = ctx;
|
|
1545
|
+
const {
|
|
1546
|
+
loadStartTime,
|
|
1547
|
+
props: { onLoad }
|
|
1548
|
+
} = state;
|
|
1539
1549
|
if (didLayout) {
|
|
1540
1550
|
state.didContainersLayout = true;
|
|
1541
1551
|
}
|
|
1542
1552
|
if (didInitialScroll) {
|
|
1543
1553
|
state.didFinishInitialScroll = true;
|
|
1544
1554
|
}
|
|
1545
|
-
|
|
1555
|
+
const isReadyToRender = Boolean(state.didContainersLayout && state.didFinishInitialScroll);
|
|
1556
|
+
if (isReadyToRender && !peek$(ctx, "readyToRender")) {
|
|
1546
1557
|
set$(ctx, "readyToRender", true);
|
|
1558
|
+
if (onLoad) {
|
|
1559
|
+
onLoad({ elapsedTimeInMs: Date.now() - loadStartTime });
|
|
1560
|
+
}
|
|
1547
1561
|
}
|
|
1548
1562
|
}
|
|
1549
1563
|
|
|
@@ -1575,6 +1589,7 @@ function finishScrollTo(ctx) {
|
|
|
1575
1589
|
var SCROLL_END_IDLE_MS = 80;
|
|
1576
1590
|
var SCROLL_END_MAX_MS = 1500;
|
|
1577
1591
|
var SMOOTH_SCROLL_DURATION_MS = 320;
|
|
1592
|
+
var SCROLL_END_TARGET_EPSILON = 1;
|
|
1578
1593
|
function doScrollTo(ctx, params) {
|
|
1579
1594
|
const state = ctx.state;
|
|
1580
1595
|
const { animated, horizontal, offset } = params;
|
|
@@ -1585,7 +1600,10 @@ function doScrollTo(ctx, params) {
|
|
|
1585
1600
|
const top = horizontal ? 0 : offset;
|
|
1586
1601
|
node.scrollTo({ behavior: animated ? "smooth" : "auto", left, top });
|
|
1587
1602
|
if (animated) {
|
|
1588
|
-
listenForScrollEnd(ctx, node
|
|
1603
|
+
listenForScrollEnd(ctx, node, {
|
|
1604
|
+
horizontal: !!horizontal,
|
|
1605
|
+
targetOffset: offset
|
|
1606
|
+
});
|
|
1589
1607
|
} else {
|
|
1590
1608
|
state.scroll = offset;
|
|
1591
1609
|
setTimeout(() => {
|
|
@@ -1594,31 +1612,17 @@ function doScrollTo(ctx, params) {
|
|
|
1594
1612
|
}
|
|
1595
1613
|
}
|
|
1596
1614
|
}
|
|
1597
|
-
function listenForScrollEnd(ctx, node) {
|
|
1615
|
+
function listenForScrollEnd(ctx, node, params) {
|
|
1616
|
+
const { horizontal, targetOffset } = params;
|
|
1598
1617
|
const supportsScrollEnd = "onscrollend" in node;
|
|
1599
1618
|
let idleTimeout;
|
|
1600
1619
|
let maxTimeout;
|
|
1601
1620
|
let settled = false;
|
|
1602
1621
|
const targetToken = ctx.state.scrollingTo;
|
|
1603
|
-
const finish = () => {
|
|
1604
|
-
if (settled) return;
|
|
1605
|
-
settled = true;
|
|
1606
|
-
cleanup();
|
|
1607
|
-
if (targetToken === ctx.state.scrollingTo) {
|
|
1608
|
-
finishScrollTo(ctx);
|
|
1609
|
-
}
|
|
1610
|
-
};
|
|
1611
|
-
const onScroll2 = () => {
|
|
1612
|
-
if (idleTimeout) {
|
|
1613
|
-
clearTimeout(idleTimeout);
|
|
1614
|
-
}
|
|
1615
|
-
idleTimeout = setTimeout(finish, SCROLL_END_IDLE_MS);
|
|
1616
|
-
};
|
|
1617
1622
|
const cleanup = () => {
|
|
1623
|
+
node.removeEventListener("scroll", onScroll2);
|
|
1618
1624
|
if (supportsScrollEnd) {
|
|
1619
|
-
node.removeEventListener("scrollend",
|
|
1620
|
-
} else {
|
|
1621
|
-
node.removeEventListener("scroll", onScroll2);
|
|
1625
|
+
node.removeEventListener("scrollend", onScrollEnd);
|
|
1622
1626
|
}
|
|
1623
1627
|
if (idleTimeout) {
|
|
1624
1628
|
clearTimeout(idleTimeout);
|
|
@@ -1627,14 +1631,37 @@ function listenForScrollEnd(ctx, node) {
|
|
|
1627
1631
|
clearTimeout(maxTimeout);
|
|
1628
1632
|
}
|
|
1629
1633
|
};
|
|
1634
|
+
const finish = (reason) => {
|
|
1635
|
+
if (settled) return;
|
|
1636
|
+
if (targetToken !== ctx.state.scrollingTo) {
|
|
1637
|
+
settled = true;
|
|
1638
|
+
cleanup();
|
|
1639
|
+
return;
|
|
1640
|
+
}
|
|
1641
|
+
const currentOffset = horizontal ? node.scrollLeft : node.scrollTop;
|
|
1642
|
+
const isNearTarget = Math.abs(currentOffset - targetOffset) <= SCROLL_END_TARGET_EPSILON;
|
|
1643
|
+
if (reason === "scrollend" && !isNearTarget) {
|
|
1644
|
+
return;
|
|
1645
|
+
}
|
|
1646
|
+
settled = true;
|
|
1647
|
+
cleanup();
|
|
1648
|
+
finishScrollTo(ctx);
|
|
1649
|
+
};
|
|
1650
|
+
const onScroll2 = () => {
|
|
1651
|
+
if (idleTimeout) {
|
|
1652
|
+
clearTimeout(idleTimeout);
|
|
1653
|
+
}
|
|
1654
|
+
idleTimeout = setTimeout(() => finish("idle"), SCROLL_END_IDLE_MS);
|
|
1655
|
+
};
|
|
1656
|
+
const onScrollEnd = () => finish("scrollend");
|
|
1657
|
+
node.addEventListener("scroll", onScroll2);
|
|
1630
1658
|
if (supportsScrollEnd) {
|
|
1631
|
-
node.addEventListener("scrollend",
|
|
1659
|
+
node.addEventListener("scrollend", onScrollEnd);
|
|
1660
|
+
maxTimeout = setTimeout(() => finish("max"), SCROLL_END_MAX_MS);
|
|
1632
1661
|
} else {
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
maxTimeout = setTimeout(finish, SCROLL_END_MAX_MS);
|
|
1662
|
+
idleTimeout = setTimeout(() => finish("idle"), SMOOTH_SCROLL_DURATION_MS);
|
|
1663
|
+
maxTimeout = setTimeout(() => finish("max"), SCROLL_END_MAX_MS);
|
|
1636
1664
|
}
|
|
1637
|
-
return cleanup;
|
|
1638
1665
|
}
|
|
1639
1666
|
|
|
1640
1667
|
// src/core/scrollTo.ts
|
|
@@ -1652,14 +1679,14 @@ function scrollTo(ctx, params) {
|
|
|
1652
1679
|
clearTimeout(ctx.state.timeoutCheckFinishedScrollFallback);
|
|
1653
1680
|
}
|
|
1654
1681
|
let offset = precomputedWithViewOffset ? scrollTargetOffset : calculateOffsetWithOffsetPosition(ctx, scrollTargetOffset, scrollTarget);
|
|
1655
|
-
offset = clampScrollOffset(ctx, offset);
|
|
1682
|
+
offset = clampScrollOffset(ctx, offset, scrollTarget);
|
|
1656
1683
|
state.scrollHistory.length = 0;
|
|
1657
1684
|
if (!noScrollingTo) {
|
|
1658
1685
|
state.scrollingTo = scrollTarget;
|
|
1659
1686
|
}
|
|
1660
1687
|
state.scrollPending = offset;
|
|
1661
1688
|
if (forceScroll || !isInitialScroll || Platform.OS === "android") {
|
|
1662
|
-
doScrollTo(ctx, { animated, horizontal,
|
|
1689
|
+
doScrollTo(ctx, { animated, horizontal, offset });
|
|
1663
1690
|
} else {
|
|
1664
1691
|
state.scroll = offset;
|
|
1665
1692
|
}
|
|
@@ -1702,7 +1729,8 @@ function updateScroll(ctx, newScroll, forceUpdate) {
|
|
|
1702
1729
|
const scrollDelta = Math.abs(newScroll - prevScroll);
|
|
1703
1730
|
const scrollLength = state.scrollLength;
|
|
1704
1731
|
const lastCalculated = state.scrollLastCalculate;
|
|
1705
|
-
const
|
|
1732
|
+
const useAggressiveItemRecalculation = isInMVCPActiveMode(state);
|
|
1733
|
+
const shouldUpdate = useAggressiveItemRecalculation || forceUpdate || lastCalculated === void 0 || Math.abs(state.scroll - lastCalculated) > 2;
|
|
1706
1734
|
if (shouldUpdate) {
|
|
1707
1735
|
state.scrollLastCalculate = state.scroll;
|
|
1708
1736
|
state.ignoreScrollFromMVCPIgnored = false;
|
|
@@ -1747,43 +1775,106 @@ function requestAdjust(ctx, positionDiff, dataChanged) {
|
|
|
1747
1775
|
}
|
|
1748
1776
|
|
|
1749
1777
|
// src/core/mvcp.ts
|
|
1778
|
+
var MVCP_POSITION_EPSILON = 0.1;
|
|
1779
|
+
var MVCP_ANCHOR_LOCK_TTL_MS = 300;
|
|
1780
|
+
var MVCP_ANCHOR_LOCK_QUIET_PASSES_TO_RELEASE = 2;
|
|
1781
|
+
function resolveAnchorLock(state, enableMVCPAnchorLock, mvcpData, now) {
|
|
1782
|
+
if (!enableMVCPAnchorLock) {
|
|
1783
|
+
state.mvcpAnchorLock = void 0;
|
|
1784
|
+
return void 0;
|
|
1785
|
+
}
|
|
1786
|
+
const lock = state.mvcpAnchorLock;
|
|
1787
|
+
if (!lock) {
|
|
1788
|
+
return void 0;
|
|
1789
|
+
}
|
|
1790
|
+
const isExpired = now > lock.expiresAt;
|
|
1791
|
+
const isMissing = state.indexByKey.get(lock.id) === void 0;
|
|
1792
|
+
if (isExpired || isMissing || !mvcpData) {
|
|
1793
|
+
state.mvcpAnchorLock = void 0;
|
|
1794
|
+
return void 0;
|
|
1795
|
+
}
|
|
1796
|
+
return lock;
|
|
1797
|
+
}
|
|
1798
|
+
function updateAnchorLock(state, params) {
|
|
1799
|
+
{
|
|
1800
|
+
const { anchorId, anchorPosition, dataChanged, now, positionDiff } = params;
|
|
1801
|
+
const enableMVCPAnchorLock = !!dataChanged || !!state.mvcpAnchorLock;
|
|
1802
|
+
const mvcpData = state.props.maintainVisibleContentPosition.data;
|
|
1803
|
+
if (!enableMVCPAnchorLock || !mvcpData || state.scrollingTo || !anchorId || anchorPosition === void 0) {
|
|
1804
|
+
return;
|
|
1805
|
+
}
|
|
1806
|
+
const existingLock = state.mvcpAnchorLock;
|
|
1807
|
+
const quietPasses = !dataChanged && Math.abs(positionDiff) <= MVCP_POSITION_EPSILON && (existingLock == null ? void 0 : existingLock.id) === anchorId ? existingLock.quietPasses + 1 : 0;
|
|
1808
|
+
if (!dataChanged && quietPasses >= MVCP_ANCHOR_LOCK_QUIET_PASSES_TO_RELEASE) {
|
|
1809
|
+
state.mvcpAnchorLock = void 0;
|
|
1810
|
+
return;
|
|
1811
|
+
}
|
|
1812
|
+
state.mvcpAnchorLock = {
|
|
1813
|
+
expiresAt: now + MVCP_ANCHOR_LOCK_TTL_MS,
|
|
1814
|
+
id: anchorId,
|
|
1815
|
+
position: anchorPosition,
|
|
1816
|
+
quietPasses
|
|
1817
|
+
};
|
|
1818
|
+
}
|
|
1819
|
+
}
|
|
1750
1820
|
function prepareMVCP(ctx, dataChanged) {
|
|
1751
1821
|
const state = ctx.state;
|
|
1752
1822
|
const { idsInView, positions, props } = state;
|
|
1753
1823
|
const {
|
|
1754
1824
|
maintainVisibleContentPosition: { data: mvcpData, size: mvcpScroll, shouldRestorePosition }
|
|
1755
1825
|
} = props;
|
|
1826
|
+
const now = Date.now();
|
|
1827
|
+
const enableMVCPAnchorLock = (!!dataChanged || !!state.mvcpAnchorLock);
|
|
1756
1828
|
const scrollingTo = state.scrollingTo;
|
|
1829
|
+
const anchorLock = resolveAnchorLock(state, enableMVCPAnchorLock, mvcpData, now) ;
|
|
1757
1830
|
let prevPosition;
|
|
1758
1831
|
let targetId;
|
|
1759
1832
|
const idsInViewWithPositions = [];
|
|
1760
1833
|
const scrollTarget = scrollingTo == null ? void 0 : scrollingTo.index;
|
|
1761
1834
|
const scrollingToViewPosition = scrollingTo == null ? void 0 : scrollingTo.viewPosition;
|
|
1835
|
+
const isEndAnchoredScrollTarget = scrollTarget !== void 0 && state.props.data.length > 0 && scrollTarget >= state.props.data.length - 1 && (scrollingToViewPosition != null ? scrollingToViewPosition : 0) > 0;
|
|
1762
1836
|
const shouldMVCP = dataChanged ? mvcpData : mvcpScroll;
|
|
1763
1837
|
const indexByKey = state.indexByKey;
|
|
1764
1838
|
if (shouldMVCP) {
|
|
1765
|
-
if (scrollTarget
|
|
1839
|
+
if (anchorLock && scrollTarget === void 0) {
|
|
1840
|
+
targetId = anchorLock.id;
|
|
1841
|
+
prevPosition = anchorLock.position;
|
|
1842
|
+
} else if (scrollTarget !== void 0) {
|
|
1766
1843
|
targetId = getId(state, scrollTarget);
|
|
1767
|
-
} else if (idsInView.length > 0 && state.didContainersLayout) {
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1844
|
+
} else if (idsInView.length > 0 && state.didContainersLayout && !dataChanged) {
|
|
1845
|
+
targetId = idsInView.find((id) => indexByKey.get(id) !== void 0);
|
|
1846
|
+
}
|
|
1847
|
+
if (dataChanged && idsInView.length > 0 && state.didContainersLayout) {
|
|
1848
|
+
for (let i = 0; i < idsInView.length; i++) {
|
|
1849
|
+
const id = idsInView[i];
|
|
1850
|
+
const index = indexByKey.get(id);
|
|
1851
|
+
if (index !== void 0) {
|
|
1852
|
+
idsInViewWithPositions.push({ id, position: positions.get(id) });
|
|
1775
1853
|
}
|
|
1776
|
-
} else {
|
|
1777
|
-
targetId = idsInView.find((id) => indexByKey.get(id) !== void 0);
|
|
1778
1854
|
}
|
|
1779
1855
|
}
|
|
1780
|
-
if (targetId !== void 0) {
|
|
1856
|
+
if (targetId !== void 0 && prevPosition === void 0) {
|
|
1781
1857
|
prevPosition = positions.get(targetId);
|
|
1782
1858
|
}
|
|
1783
1859
|
return () => {
|
|
1784
1860
|
let positionDiff = 0;
|
|
1785
|
-
|
|
1786
|
-
|
|
1861
|
+
let anchorIdForLock = anchorLock == null ? void 0 : anchorLock.id;
|
|
1862
|
+
let anchorPositionForLock;
|
|
1863
|
+
let skipTargetAnchor = false;
|
|
1864
|
+
const data = state.props.data;
|
|
1865
|
+
const shouldValidateLockedAnchor = dataChanged && mvcpData && scrollTarget === void 0 && targetId !== void 0 && (anchorLock == null ? void 0 : anchorLock.id) === targetId && shouldRestorePosition !== void 0;
|
|
1866
|
+
if (shouldValidateLockedAnchor && targetId !== void 0) {
|
|
1867
|
+
const index = indexByKey.get(targetId);
|
|
1868
|
+
if (index !== void 0) {
|
|
1869
|
+
const item = data[index];
|
|
1870
|
+
skipTargetAnchor = item === void 0 || !shouldRestorePosition(item, index, data);
|
|
1871
|
+
if (skipTargetAnchor && (anchorLock == null ? void 0 : anchorLock.id) === targetId) {
|
|
1872
|
+
state.mvcpAnchorLock = void 0;
|
|
1873
|
+
}
|
|
1874
|
+
}
|
|
1875
|
+
}
|
|
1876
|
+
const shouldUseFallbackVisibleAnchor = dataChanged && mvcpData && scrollTarget === void 0 && (targetId === void 0 || positions.get(targetId) === void 0 || skipTargetAnchor);
|
|
1877
|
+
if (shouldUseFallbackVisibleAnchor) {
|
|
1787
1878
|
for (let i = 0; i < idsInViewWithPositions.length; i++) {
|
|
1788
1879
|
const { id, position } = idsInViewWithPositions[i];
|
|
1789
1880
|
const index = indexByKey.get(id);
|
|
@@ -1796,16 +1887,18 @@ function prepareMVCP(ctx, dataChanged) {
|
|
|
1796
1887
|
const newPosition = positions.get(id);
|
|
1797
1888
|
if (newPosition !== void 0) {
|
|
1798
1889
|
positionDiff = newPosition - position;
|
|
1890
|
+
anchorIdForLock = id;
|
|
1891
|
+
anchorPositionForLock = newPosition;
|
|
1799
1892
|
break;
|
|
1800
1893
|
}
|
|
1801
1894
|
}
|
|
1802
1895
|
}
|
|
1803
|
-
if (targetId !== void 0 && prevPosition !== void 0) {
|
|
1896
|
+
if (!skipTargetAnchor && targetId !== void 0 && prevPosition !== void 0) {
|
|
1804
1897
|
const newPosition = positions.get(targetId);
|
|
1805
1898
|
if (newPosition !== void 0) {
|
|
1806
1899
|
const totalSize = getContentSize(ctx);
|
|
1807
1900
|
let diff = newPosition - prevPosition;
|
|
1808
|
-
if (diff !== 0 && state.scroll + state.scrollLength > totalSize) {
|
|
1901
|
+
if (diff !== 0 && isEndAnchoredScrollTarget && state.scroll + state.scrollLength > totalSize) {
|
|
1809
1902
|
if (diff > 0) {
|
|
1810
1903
|
diff = Math.max(0, totalSize - state.scroll - state.scrollLength);
|
|
1811
1904
|
} else {
|
|
@@ -1813,20 +1906,29 @@ function prepareMVCP(ctx, dataChanged) {
|
|
|
1813
1906
|
}
|
|
1814
1907
|
}
|
|
1815
1908
|
positionDiff = diff;
|
|
1909
|
+
anchorIdForLock = targetId;
|
|
1910
|
+
anchorPositionForLock = newPosition;
|
|
1816
1911
|
}
|
|
1817
1912
|
}
|
|
1818
1913
|
if (scrollingToViewPosition && scrollingToViewPosition > 0) {
|
|
1819
1914
|
const newSize = getItemSize(ctx, targetId, scrollTarget, state.props.data[scrollTarget]);
|
|
1820
1915
|
const prevSize = scrollingTo == null ? void 0 : scrollingTo.itemSize;
|
|
1821
|
-
if (newSize !== void 0 && prevSize !== void 0 && newSize !==
|
|
1916
|
+
if (newSize !== void 0 && prevSize !== void 0 && newSize !== prevSize) {
|
|
1822
1917
|
const diff = newSize - prevSize;
|
|
1823
1918
|
if (diff !== 0) {
|
|
1824
|
-
positionDiff +=
|
|
1919
|
+
positionDiff += diff * scrollingToViewPosition;
|
|
1825
1920
|
scrollingTo.itemSize = newSize;
|
|
1826
1921
|
}
|
|
1827
1922
|
}
|
|
1828
1923
|
}
|
|
1829
|
-
|
|
1924
|
+
updateAnchorLock(state, {
|
|
1925
|
+
anchorId: anchorIdForLock,
|
|
1926
|
+
anchorPosition: anchorPositionForLock,
|
|
1927
|
+
dataChanged,
|
|
1928
|
+
now,
|
|
1929
|
+
positionDiff
|
|
1930
|
+
});
|
|
1931
|
+
if (Math.abs(positionDiff) > MVCP_POSITION_EPSILON) {
|
|
1830
1932
|
requestAdjust(ctx, positionDiff);
|
|
1831
1933
|
}
|
|
1832
1934
|
};
|
|
@@ -2481,26 +2583,16 @@ function scrollToIndex(ctx, { index, viewOffset = 0, animated = true, viewPositi
|
|
|
2481
2583
|
// src/utils/setDidLayout.ts
|
|
2482
2584
|
function setDidLayout(ctx) {
|
|
2483
2585
|
const state = ctx.state;
|
|
2484
|
-
const {
|
|
2485
|
-
loadStartTime,
|
|
2486
|
-
initialScroll,
|
|
2487
|
-
props: { onLoad }
|
|
2488
|
-
} = state;
|
|
2586
|
+
const { initialScroll } = state;
|
|
2489
2587
|
state.queuedInitialLayout = true;
|
|
2490
2588
|
checkAtBottom(ctx);
|
|
2491
|
-
const setIt = () => {
|
|
2492
|
-
setInitialRenderState(ctx, { didLayout: true });
|
|
2493
|
-
if (onLoad) {
|
|
2494
|
-
onLoad({ elapsedTimeInMs: Date.now() - loadStartTime });
|
|
2495
|
-
}
|
|
2496
|
-
};
|
|
2497
2589
|
if ((initialScroll == null ? void 0 : initialScroll.index) !== void 0) {
|
|
2498
2590
|
const target = initialScroll;
|
|
2499
2591
|
const runScroll = () => scrollToIndex(ctx, { ...target, animated: false });
|
|
2500
2592
|
runScroll();
|
|
2501
2593
|
requestAnimationFrame(runScroll);
|
|
2502
2594
|
}
|
|
2503
|
-
|
|
2595
|
+
setInitialRenderState(ctx, { didLayout: true });
|
|
2504
2596
|
}
|
|
2505
2597
|
|
|
2506
2598
|
// src/core/calculateItemsInView.ts
|
|
@@ -2540,7 +2632,7 @@ function handleStickyActivation(ctx, stickyHeaderIndices, stickyArray, currentSt
|
|
|
2540
2632
|
}
|
|
2541
2633
|
}
|
|
2542
2634
|
}
|
|
2543
|
-
function handleStickyRecycling(ctx, stickyArray, scroll,
|
|
2635
|
+
function handleStickyRecycling(ctx, stickyArray, scroll, drawDistance, currentStickyIdx, pendingRemoval, alwaysRenderIndicesSet) {
|
|
2544
2636
|
var _a3, _b, _c;
|
|
2545
2637
|
const state = ctx.state;
|
|
2546
2638
|
for (const containerIndex of state.stickyContainerPool) {
|
|
@@ -2561,13 +2653,13 @@ function handleStickyRecycling(ctx, stickyArray, scroll, scrollBuffer, currentSt
|
|
|
2561
2653
|
if (nextIndex) {
|
|
2562
2654
|
const nextId = (_a3 = state.idCache[nextIndex]) != null ? _a3 : getId(state, nextIndex);
|
|
2563
2655
|
const nextPos = nextId ? state.positions.get(nextId) : void 0;
|
|
2564
|
-
shouldRecycle = nextPos !== void 0 && scroll > nextPos +
|
|
2656
|
+
shouldRecycle = nextPos !== void 0 && scroll > nextPos + drawDistance * 2;
|
|
2565
2657
|
} else {
|
|
2566
2658
|
const currentId = (_b = state.idCache[itemIndex]) != null ? _b : getId(state, itemIndex);
|
|
2567
2659
|
if (currentId) {
|
|
2568
2660
|
const currentPos = state.positions.get(currentId);
|
|
2569
2661
|
const currentSize = (_c = state.sizes.get(currentId)) != null ? _c : getItemSize(ctx, currentId, itemIndex, state.props.data[itemIndex]);
|
|
2570
|
-
shouldRecycle = currentPos !== void 0 && scroll > currentPos + currentSize +
|
|
2662
|
+
shouldRecycle = currentPos !== void 0 && scroll > currentPos + currentSize + drawDistance * 3;
|
|
2571
2663
|
}
|
|
2572
2664
|
}
|
|
2573
2665
|
if (shouldRecycle) {
|
|
@@ -2592,11 +2684,11 @@ function calculateItemsInView(ctx, params = {}) {
|
|
|
2592
2684
|
props: {
|
|
2593
2685
|
alwaysRenderIndicesArr,
|
|
2594
2686
|
alwaysRenderIndicesSet,
|
|
2687
|
+
drawDistance,
|
|
2595
2688
|
getItemType,
|
|
2596
2689
|
itemsAreEqual,
|
|
2597
2690
|
keyExtractor,
|
|
2598
|
-
onStickyHeaderChange
|
|
2599
|
-
scrollBuffer
|
|
2691
|
+
onStickyHeaderChange
|
|
2600
2692
|
},
|
|
2601
2693
|
scrollForNextCalculateItemsInView,
|
|
2602
2694
|
scrollLength,
|
|
@@ -2609,6 +2701,7 @@ function calculateItemsInView(ctx, params = {}) {
|
|
|
2609
2701
|
const stickyIndicesSet = state.props.stickyIndicesSet || /* @__PURE__ */ new Set();
|
|
2610
2702
|
const alwaysRenderArr = alwaysRenderIndicesArr || [];
|
|
2611
2703
|
const alwaysRenderSet = alwaysRenderIndicesSet || /* @__PURE__ */ new Set();
|
|
2704
|
+
const { dataChanged, doMVCP, forceFullItemPositions } = params;
|
|
2612
2705
|
const prevNumContainers = peek$(ctx, "numContainers");
|
|
2613
2706
|
if (!data || scrollLength === 0 || !prevNumContainers) {
|
|
2614
2707
|
return;
|
|
@@ -2616,7 +2709,6 @@ function calculateItemsInView(ctx, params = {}) {
|
|
|
2616
2709
|
const totalSize = getContentSize(ctx);
|
|
2617
2710
|
const topPad = peek$(ctx, "stylePaddingTop") + peek$(ctx, "headerSize");
|
|
2618
2711
|
const numColumns = peek$(ctx, "numColumns");
|
|
2619
|
-
const { dataChanged, doMVCP, forceFullItemPositions } = params;
|
|
2620
2712
|
const speed = getScrollVelocity(state);
|
|
2621
2713
|
const scrollExtra = 0;
|
|
2622
2714
|
const { queuedInitialLayout } = state;
|
|
@@ -2635,24 +2727,20 @@ function calculateItemsInView(ctx, params = {}) {
|
|
|
2635
2727
|
if (scroll + scrollLength > totalSize) {
|
|
2636
2728
|
scroll = Math.max(0, totalSize - scrollLength);
|
|
2637
2729
|
}
|
|
2638
|
-
if (ENABLE_DEBUG_VIEW) {
|
|
2639
|
-
set$(ctx, "debugRawScroll", scrollState);
|
|
2640
|
-
set$(ctx, "debugComputedScroll", scroll);
|
|
2641
|
-
}
|
|
2642
2730
|
const previousStickyIndex = peek$(ctx, "activeStickyIndex");
|
|
2643
2731
|
const currentStickyIdx = stickyIndicesArr.length > 0 ? findCurrentStickyIndex(stickyIndicesArr, scroll, state) : -1;
|
|
2644
2732
|
const nextActiveStickyIndex = currentStickyIdx >= 0 ? stickyIndicesArr[currentStickyIdx] : -1;
|
|
2645
2733
|
if (currentStickyIdx >= 0 || previousStickyIndex >= 0) {
|
|
2646
2734
|
set$(ctx, "activeStickyIndex", nextActiveStickyIndex);
|
|
2647
2735
|
}
|
|
2648
|
-
let scrollBufferTop =
|
|
2649
|
-
let scrollBufferBottom =
|
|
2650
|
-
if (speed > 0 || speed === 0 && scroll < Math.max(50,
|
|
2651
|
-
scrollBufferTop =
|
|
2652
|
-
scrollBufferBottom =
|
|
2736
|
+
let scrollBufferTop = drawDistance;
|
|
2737
|
+
let scrollBufferBottom = drawDistance;
|
|
2738
|
+
if (speed > 0 || speed === 0 && scroll < Math.max(50, drawDistance)) {
|
|
2739
|
+
scrollBufferTop = drawDistance * 0.5;
|
|
2740
|
+
scrollBufferBottom = drawDistance * 1.5;
|
|
2653
2741
|
} else {
|
|
2654
|
-
scrollBufferTop =
|
|
2655
|
-
scrollBufferBottom =
|
|
2742
|
+
scrollBufferTop = drawDistance * 1.5;
|
|
2743
|
+
scrollBufferBottom = drawDistance * 0.5;
|
|
2656
2744
|
}
|
|
2657
2745
|
const scrollTopBuffered = scroll - scrollBufferTop;
|
|
2658
2746
|
const scrollBottom = scroll + scrollLength + (scroll < 0 ? -scroll : 0);
|
|
@@ -2662,7 +2750,9 @@ function calculateItemsInView(ctx, params = {}) {
|
|
|
2662
2750
|
if (top === null && bottom === null) {
|
|
2663
2751
|
state.scrollForNextCalculateItemsInView = void 0;
|
|
2664
2752
|
} else if ((top === null || scrollTopBuffered > top) && (bottom === null || scrollBottomBuffered < bottom)) {
|
|
2665
|
-
|
|
2753
|
+
if (!isInMVCPActiveMode(state)) {
|
|
2754
|
+
return;
|
|
2755
|
+
}
|
|
2666
2756
|
}
|
|
2667
2757
|
}
|
|
2668
2758
|
const checkMVCP = doMVCP ? prepareMVCP(ctx, dataChanged) : void 0;
|
|
@@ -2894,7 +2984,7 @@ function calculateItemsInView(ctx, params = {}) {
|
|
|
2894
2984
|
ctx,
|
|
2895
2985
|
stickyIndicesArr,
|
|
2896
2986
|
scroll,
|
|
2897
|
-
|
|
2987
|
+
drawDistance,
|
|
2898
2988
|
currentStickyIdx,
|
|
2899
2989
|
pendingRemoval,
|
|
2900
2990
|
alwaysRenderSet
|
|
@@ -3001,12 +3091,17 @@ function checkFinishedScrollFrame(ctx) {
|
|
|
3001
3091
|
state.animFrameCheckFinishedScroll = void 0;
|
|
3002
3092
|
const scroll = state.scrollPending;
|
|
3003
3093
|
const adjust = state.scrollAdjustHandler.getAdjust();
|
|
3004
|
-
const clampedTargetOffset = clampScrollOffset(
|
|
3005
|
-
|
|
3094
|
+
const clampedTargetOffset = clampScrollOffset(
|
|
3095
|
+
ctx,
|
|
3096
|
+
scrollingTo.offset - (scrollingTo.viewOffset || 0),
|
|
3097
|
+
scrollingTo
|
|
3098
|
+
);
|
|
3099
|
+
const maxOffset = clampScrollOffset(ctx, scroll, scrollingTo);
|
|
3006
3100
|
const diff1 = Math.abs(scroll - clampedTargetOffset);
|
|
3007
3101
|
const diff2 = Math.abs(diff1 - adjust);
|
|
3008
3102
|
const isNotOverscrolled = Math.abs(scroll - maxOffset) < 1;
|
|
3009
|
-
|
|
3103
|
+
const isAtTarget = diff1 < 1 || !scrollingTo.animated && diff2 < 1;
|
|
3104
|
+
if (isNotOverscrolled && isAtTarget) {
|
|
3010
3105
|
finishScrollTo(ctx);
|
|
3011
3106
|
}
|
|
3012
3107
|
}
|
|
@@ -3150,10 +3245,10 @@ function doInitialAllocateContainers(ctx) {
|
|
|
3150
3245
|
scrollLength,
|
|
3151
3246
|
props: {
|
|
3152
3247
|
data,
|
|
3248
|
+
drawDistance,
|
|
3153
3249
|
getEstimatedItemSize,
|
|
3154
3250
|
getFixedItemSize,
|
|
3155
3251
|
getItemType,
|
|
3156
|
-
scrollBuffer,
|
|
3157
3252
|
numColumns,
|
|
3158
3253
|
estimatedItemSize
|
|
3159
3254
|
}
|
|
@@ -3175,7 +3270,7 @@ function doInitialAllocateContainers(ctx) {
|
|
|
3175
3270
|
} else {
|
|
3176
3271
|
averageItemSize = estimatedItemSize;
|
|
3177
3272
|
}
|
|
3178
|
-
const numContainers = Math.ceil((scrollLength +
|
|
3273
|
+
const numContainers = Math.ceil((scrollLength + drawDistance * 2) / averageItemSize * numColumns);
|
|
3179
3274
|
for (let i = 0; i < numContainers; i++) {
|
|
3180
3275
|
set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
|
|
3181
3276
|
set$(ctx, `containerColumn${i}`, -1);
|
|
@@ -3263,8 +3358,8 @@ function onScroll(ctx, event) {
|
|
|
3263
3358
|
}
|
|
3264
3359
|
}
|
|
3265
3360
|
let newScroll = event.nativeEvent.contentOffset[state.props.horizontal ? "x" : "y"];
|
|
3266
|
-
if (state.scrollingTo) {
|
|
3267
|
-
const maxOffset = clampScrollOffset(ctx, newScroll);
|
|
3361
|
+
if (state.scrollingTo && state.scrollingTo.offset >= newScroll) {
|
|
3362
|
+
const maxOffset = clampScrollOffset(ctx, newScroll, state.scrollingTo);
|
|
3268
3363
|
if (newScroll !== maxOffset && Math.abs(newScroll - maxOffset) > 1) {
|
|
3269
3364
|
newScroll = maxOffset;
|
|
3270
3365
|
scrollTo(ctx, {
|
|
@@ -3317,7 +3412,7 @@ var ScrollAdjustHandler = class {
|
|
|
3317
3412
|
if ((scrollTarget == null ? void 0 : scrollTarget.index) !== void 0) {
|
|
3318
3413
|
const currentOffset = calculateOffsetForIndex(this.ctx, scrollTarget.index);
|
|
3319
3414
|
targetScroll = calculateOffsetWithOffsetPosition(this.ctx, currentOffset, scrollTarget);
|
|
3320
|
-
targetScroll = clampScrollOffset(this.ctx, targetScroll);
|
|
3415
|
+
targetScroll = clampScrollOffset(this.ctx, targetScroll, scrollTarget);
|
|
3321
3416
|
} else {
|
|
3322
3417
|
targetScroll = clampScrollOffset(this.ctx, state.scroll + pending);
|
|
3323
3418
|
}
|
|
@@ -3336,6 +3431,26 @@ var ScrollAdjustHandler = class {
|
|
|
3336
3431
|
};
|
|
3337
3432
|
|
|
3338
3433
|
// src/core/updateItemSize.ts
|
|
3434
|
+
function runOrScheduleMVCPRecalculate(ctx) {
|
|
3435
|
+
const state = ctx.state;
|
|
3436
|
+
{
|
|
3437
|
+
if (!state.mvcpAnchorLock) {
|
|
3438
|
+
if (state.queuedMVCPRecalculate !== void 0) {
|
|
3439
|
+
cancelAnimationFrame(state.queuedMVCPRecalculate);
|
|
3440
|
+
state.queuedMVCPRecalculate = void 0;
|
|
3441
|
+
}
|
|
3442
|
+
calculateItemsInView(ctx, { doMVCP: true });
|
|
3443
|
+
return;
|
|
3444
|
+
}
|
|
3445
|
+
if (state.queuedMVCPRecalculate !== void 0) {
|
|
3446
|
+
return;
|
|
3447
|
+
}
|
|
3448
|
+
state.queuedMVCPRecalculate = requestAnimationFrame(() => {
|
|
3449
|
+
state.queuedMVCPRecalculate = void 0;
|
|
3450
|
+
calculateItemsInView(ctx, { doMVCP: true });
|
|
3451
|
+
});
|
|
3452
|
+
}
|
|
3453
|
+
}
|
|
3339
3454
|
function updateItemSize(ctx, itemKey, sizeObj) {
|
|
3340
3455
|
var _a3;
|
|
3341
3456
|
const state = ctx.state;
|
|
@@ -3419,7 +3534,7 @@ function updateItemSize(ctx, itemKey, sizeObj) {
|
|
|
3419
3534
|
if (didContainersLayout || checkAllSizesKnown(state)) {
|
|
3420
3535
|
if (needsRecalculate) {
|
|
3421
3536
|
state.scrollForNextCalculateItemsInView = void 0;
|
|
3422
|
-
|
|
3537
|
+
runOrScheduleMVCPRecalculate(ctx);
|
|
3423
3538
|
}
|
|
3424
3539
|
if (shouldMaintainScrollAtEnd) {
|
|
3425
3540
|
if (maintainScrollAtEnd === true || maintainScrollAtEnd.onItemLayout) {
|
|
@@ -3531,7 +3646,30 @@ function createImperativeHandle(ctx) {
|
|
|
3531
3646
|
}
|
|
3532
3647
|
};
|
|
3533
3648
|
const refScroller = state.refScroller;
|
|
3649
|
+
const clearCaches = (options) => {
|
|
3650
|
+
var _a3, _b;
|
|
3651
|
+
const mode = (_a3 = options == null ? void 0 : options.mode) != null ? _a3 : "sizes";
|
|
3652
|
+
state.sizes.clear();
|
|
3653
|
+
state.sizesKnown.clear();
|
|
3654
|
+
for (const key in state.averageSizes) {
|
|
3655
|
+
delete state.averageSizes[key];
|
|
3656
|
+
}
|
|
3657
|
+
state.minIndexSizeChanged = 0;
|
|
3658
|
+
state.scrollForNextCalculateItemsInView = void 0;
|
|
3659
|
+
state.pendingTotalSize = void 0;
|
|
3660
|
+
state.totalSize = 0;
|
|
3661
|
+
set$(ctx, "totalSize", 0);
|
|
3662
|
+
if (mode === "full") {
|
|
3663
|
+
state.indexByKey.clear();
|
|
3664
|
+
state.idCache.length = 0;
|
|
3665
|
+
state.positions.clear();
|
|
3666
|
+
state.columns.clear();
|
|
3667
|
+
state.columnSpans.clear();
|
|
3668
|
+
}
|
|
3669
|
+
(_b = state.triggerCalculateItemsInView) == null ? void 0 : _b.call(state, { forceFullItemPositions: true });
|
|
3670
|
+
};
|
|
3534
3671
|
return {
|
|
3672
|
+
clearCaches,
|
|
3535
3673
|
flashScrollIndicators: () => refScroller.current.flashScrollIndicators(),
|
|
3536
3674
|
getNativeScrollRef: () => refScroller.current,
|
|
3537
3675
|
getScrollableNode: () => refScroller.current.getScrollableNode(),
|
|
@@ -3692,8 +3830,8 @@ function normalizeMaintainVisibleContentPosition(value) {
|
|
|
3692
3830
|
if (value && typeof value === "object") {
|
|
3693
3831
|
return {
|
|
3694
3832
|
data: (_a3 = value.data) != null ? _a3 : false,
|
|
3695
|
-
|
|
3696
|
-
|
|
3833
|
+
shouldRestorePosition: value.shouldRestorePosition,
|
|
3834
|
+
size: (_b = value.size) != null ? _b : true
|
|
3697
3835
|
};
|
|
3698
3836
|
}
|
|
3699
3837
|
if (value === false) {
|
|
@@ -3765,8 +3903,6 @@ function useThrottledOnScroll(originalHandler, scrollEventThrottle) {
|
|
|
3765
3903
|
}
|
|
3766
3904
|
|
|
3767
3905
|
// src/components/LegendList.tsx
|
|
3768
|
-
var DEFAULT_DRAW_DISTANCE = 250;
|
|
3769
|
-
var DEFAULT_ITEM_SIZE = 100;
|
|
3770
3906
|
var LegendList = typedMemo(
|
|
3771
3907
|
// biome-ignore lint/nursery/noShadow: const function name shadowing is intentional
|
|
3772
3908
|
typedForwardRef(function LegendList2(props, forwardedRef) {
|
|
@@ -3796,7 +3932,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
3796
3932
|
data: dataProp = [],
|
|
3797
3933
|
dataVersion,
|
|
3798
3934
|
drawDistance = 250,
|
|
3799
|
-
estimatedItemSize
|
|
3935
|
+
estimatedItemSize = 100,
|
|
3800
3936
|
estimatedListSize,
|
|
3801
3937
|
extraData,
|
|
3802
3938
|
getEstimatedItemSize,
|
|
@@ -3848,7 +3984,12 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
3848
3984
|
...rest
|
|
3849
3985
|
} = props;
|
|
3850
3986
|
const animatedPropsInternal = props.animatedPropsInternal;
|
|
3851
|
-
const
|
|
3987
|
+
const stickyPositionComponentInternal = props.stickyPositionComponentInternal;
|
|
3988
|
+
const {
|
|
3989
|
+
childrenMode,
|
|
3990
|
+
stickyPositionComponentInternal: _stickyPositionComponentInternal,
|
|
3991
|
+
...restProps
|
|
3992
|
+
} = rest;
|
|
3852
3993
|
const contentContainerStyleBase = StyleSheet.flatten(contentContainerStyleProp);
|
|
3853
3994
|
const shouldFlexGrow = alignItemsAtEnd && (horizontal ? (contentContainerStyleBase == null ? void 0 : contentContainerStyleBase.minWidth) == null : (contentContainerStyleBase == null ? void 0 : contentContainerStyleBase.minHeight) == null);
|
|
3854
3995
|
const contentContainerStyle = {
|
|
@@ -3875,14 +4016,12 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
3875
4016
|
index: initialScrollIndexProp || 0,
|
|
3876
4017
|
viewOffset: initialScrollOffsetProp || 0
|
|
3877
4018
|
} : void 0;
|
|
3878
|
-
const [canRender, setCanRender] = React3.useState(
|
|
4019
|
+
const [canRender, setCanRender] = React3.useState(false);
|
|
3879
4020
|
const ctx = useStateContext();
|
|
3880
4021
|
ctx.columnWrapperStyle = columnWrapperStyle || (contentContainerStyle ? createColumnWrapperStyle(contentContainerStyle) : void 0);
|
|
3881
4022
|
const refScroller = useRef(null);
|
|
3882
4023
|
const combinedRef = useCombinedRef(refScroller, refScrollView);
|
|
3883
|
-
const
|
|
3884
|
-
const scrollBuffer = (drawDistance != null ? drawDistance : DEFAULT_DRAW_DISTANCE) || 1;
|
|
3885
|
-
const keyExtractor = keyExtractorProp != null ? keyExtractorProp : (_item, index) => index.toString();
|
|
4024
|
+
const keyExtractor = keyExtractorProp != null ? keyExtractorProp : ((_item, index) => index.toString());
|
|
3886
4025
|
const stickyHeaderIndices = stickyHeaderIndicesProp != null ? stickyHeaderIndicesProp : stickyIndicesDeprecated;
|
|
3887
4026
|
const alwaysRenderIndices = useMemo(() => {
|
|
3888
4027
|
const indices = getAlwaysRenderIndices(alwaysRender, dataProp, keyExtractor);
|
|
@@ -3911,8 +4050,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
3911
4050
|
ctx.state = {
|
|
3912
4051
|
activeStickyIndex: -1,
|
|
3913
4052
|
averageSizes: {},
|
|
3914
|
-
columns: /* @__PURE__ */ new Map(),
|
|
3915
4053
|
columnSpans: /* @__PURE__ */ new Map(),
|
|
4054
|
+
columns: /* @__PURE__ */ new Map(),
|
|
3916
4055
|
containerItemKeys: /* @__PURE__ */ new Map(),
|
|
3917
4056
|
containerItemTypes: /* @__PURE__ */ new Map(),
|
|
3918
4057
|
contentInsetOverride: void 0,
|
|
@@ -3999,6 +4138,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
3999
4138
|
contentInset,
|
|
4000
4139
|
data: dataProp,
|
|
4001
4140
|
dataVersion,
|
|
4141
|
+
drawDistance,
|
|
4002
4142
|
estimatedItemSize,
|
|
4003
4143
|
getEstimatedItemSize: useWrapIfItem(getEstimatedItemSize),
|
|
4004
4144
|
getFixedItemSize: useWrapIfItem(getFixedItemSize),
|
|
@@ -4022,10 +4162,10 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
4022
4162
|
overrideItemLayout,
|
|
4023
4163
|
recycleItems: !!recycleItems,
|
|
4024
4164
|
renderItem,
|
|
4025
|
-
scrollBuffer,
|
|
4026
4165
|
snapToIndices,
|
|
4027
4166
|
stickyIndicesArr: stickyHeaderIndices != null ? stickyHeaderIndices : [],
|
|
4028
4167
|
stickyIndicesSet: useMemo(() => new Set(stickyHeaderIndices != null ? stickyHeaderIndices : []), [stickyHeaderIndices == null ? void 0 : stickyHeaderIndices.join(",")]),
|
|
4168
|
+
stickyPositionComponentInternal,
|
|
4029
4169
|
stylePaddingBottom: stylePaddingBottomState,
|
|
4030
4170
|
stylePaddingTop: stylePaddingTopState,
|
|
4031
4171
|
suggestEstimatedItemSize: !!suggestEstimatedItemSize
|
|
@@ -4045,12 +4185,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
4045
4185
|
setPaddingTop(ctx, { stylePaddingTop: stylePaddingTopState });
|
|
4046
4186
|
refState.current.props.stylePaddingBottom = stylePaddingBottomState;
|
|
4047
4187
|
let paddingDiff = stylePaddingTopState - prevPaddingTop;
|
|
4048
|
-
if (shouldAdjustPadding && maintainVisibleContentPositionConfig.size && paddingDiff && prevPaddingTop !== void 0 && Platform.OS === "ios")
|
|
4049
|
-
if (state.scroll < 0) {
|
|
4050
|
-
paddingDiff += state.scroll;
|
|
4051
|
-
}
|
|
4052
|
-
requestAdjust(ctx, paddingDiff);
|
|
4053
|
-
}
|
|
4188
|
+
if (shouldAdjustPadding && maintainVisibleContentPositionConfig.size && paddingDiff && prevPaddingTop !== void 0 && Platform.OS === "ios") ;
|
|
4054
4189
|
};
|
|
4055
4190
|
if (isFirstLocal) {
|
|
4056
4191
|
initializeStateVars(false);
|
|
@@ -4069,7 +4204,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
4069
4204
|
} else {
|
|
4070
4205
|
const baseOffset = initialScroll.index !== void 0 ? calculateOffsetForIndex(ctx, initialScroll.index) : 0;
|
|
4071
4206
|
const resolvedOffset = calculateOffsetWithOffsetPosition(ctx, baseOffset, initialScroll);
|
|
4072
|
-
const clampedOffset = clampScrollOffset(ctx, resolvedOffset);
|
|
4207
|
+
const clampedOffset = clampScrollOffset(ctx, resolvedOffset, initialScroll);
|
|
4073
4208
|
const updatedInitialScroll = { ...initialScroll, contentOffset: clampedOffset };
|
|
4074
4209
|
refState.current.initialScroll = updatedInitialScroll;
|
|
4075
4210
|
state.initialScroll = updatedInitialScroll;
|
|
@@ -4218,7 +4353,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
4218
4353
|
return /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(
|
|
4219
4354
|
ListComponent,
|
|
4220
4355
|
{
|
|
4221
|
-
...
|
|
4356
|
+
...restProps,
|
|
4222
4357
|
alignItemsAtEnd,
|
|
4223
4358
|
canRender,
|
|
4224
4359
|
contentContainerStyle,
|
|
@@ -4252,7 +4387,15 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
4252
4387
|
updateItemSize: fns.updateItemSize,
|
|
4253
4388
|
waitForInitialLayout
|
|
4254
4389
|
}
|
|
4255
|
-
), IS_DEV && ENABLE_DEBUG_VIEW
|
|
4390
|
+
), IS_DEV && ENABLE_DEBUG_VIEW);
|
|
4256
4391
|
});
|
|
4257
4392
|
|
|
4258
|
-
|
|
4393
|
+
// src/index.ts
|
|
4394
|
+
var LegendList3 = LegendList;
|
|
4395
|
+
if (IS_DEV) {
|
|
4396
|
+
console.warn(
|
|
4397
|
+
"[legend-list] Legend List 3.0 deprecates the root import (@legendapp/list) because it now supports both react and react-native. The root import is fully functional, but please switch to platform-specific imports for strict platform types:\n - React Native: @legendapp/list/react-native\n - React: @legendapp/list/react\nSee README for details."
|
|
4398
|
+
);
|
|
4399
|
+
}
|
|
4400
|
+
|
|
4401
|
+
export { LegendList3 as LegendList, typedForwardRef, typedMemo, useIsLastItem, useListScrollSize, useRecyclingEffect, useRecyclingState, useSyncLayout, useViewability, useViewabilityAmount };
|