@legendapp/list 3.0.0-beta.1 → 3.0.0-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.native.js CHANGED
@@ -28,30 +28,64 @@ var React2__namespace = /*#__PURE__*/_interopNamespace(React2);
28
28
  reactNative.Animated.View;
29
29
  var View = reactNative.View;
30
30
  var Text = reactNative.Text;
31
+
32
+ // src/state/getContentInsetEnd.ts
33
+ function getContentInsetEnd(state) {
34
+ var _a3;
35
+ const { props } = state;
36
+ const horizontal = props.horizontal;
37
+ let contentInset = props.contentInset;
38
+ if (!contentInset) {
39
+ const animatedInset = (_a3 = props.animatedProps) == null ? void 0 : _a3.contentInset;
40
+ if (animatedInset) {
41
+ if ("get" in animatedInset) {
42
+ contentInset = animatedInset.get();
43
+ } else {
44
+ contentInset = animatedInset;
45
+ }
46
+ }
47
+ }
48
+ return (horizontal ? contentInset == null ? void 0 : contentInset.right : contentInset == null ? void 0 : contentInset.bottom) || 0;
49
+ }
50
+
51
+ // src/state/getContentSize.ts
52
+ function getContentSize(ctx) {
53
+ var _a3;
54
+ const { values, state } = ctx;
55
+ const stylePaddingTop = values.get("stylePaddingTop") || 0;
56
+ const stylePaddingBottom = state.props.stylePaddingBottom || 0;
57
+ const headerSize = values.get("headerSize") || 0;
58
+ const footerSize = values.get("footerSize") || 0;
59
+ const contentInsetBottom = getContentInsetEnd(state);
60
+ const totalSize = (_a3 = state.pendingTotalSize) != null ? _a3 : values.get("totalSize");
61
+ return headerSize + footerSize + totalSize + stylePaddingTop + stylePaddingBottom + (contentInsetBottom || 0);
62
+ }
31
63
  var createAnimatedValue = (value) => new reactNative.Animated.Value(value);
32
64
 
33
65
  // src/state/state.tsx
34
66
  var ContextState = React2__namespace.createContext(null);
67
+ var contextNum = 0;
35
68
  function StateProvider({ children }) {
36
69
  const [value] = React2__namespace.useState(() => ({
37
70
  animatedScrollY: createAnimatedValue(0),
38
71
  columnWrapperStyle: void 0,
39
- internalState: void 0,
72
+ contextNum: contextNum++,
40
73
  listeners: /* @__PURE__ */ new Map(),
41
74
  mapViewabilityAmountCallbacks: /* @__PURE__ */ new Map(),
42
75
  mapViewabilityAmountValues: /* @__PURE__ */ new Map(),
43
76
  mapViewabilityCallbacks: /* @__PURE__ */ new Map(),
44
77
  mapViewabilityConfigStates: /* @__PURE__ */ new Map(),
45
78
  mapViewabilityValues: /* @__PURE__ */ new Map(),
79
+ positionListeners: /* @__PURE__ */ new Map(),
80
+ state: void 0,
46
81
  values: /* @__PURE__ */ new Map([
47
82
  ["alignItemsPaddingTop", 0],
48
83
  ["stylePaddingTop", 0],
49
84
  ["headerSize", 0],
50
85
  ["numContainers", 0],
51
- ["activeStickyIndex", void 0],
86
+ ["activeStickyIndex", -1],
52
87
  ["totalSize", 0],
53
- ["scrollAdjustPending", 0],
54
- ["scrollingTo", void 0]
88
+ ["scrollAdjustPending", 0]
55
89
  ]),
56
90
  viewRefs: /* @__PURE__ */ new Map()
57
91
  }));
@@ -119,15 +153,24 @@ function set$(ctx, signalName, value) {
119
153
  }
120
154
  }
121
155
  }
122
- function getContentSize(ctx) {
123
- var _a3, _b;
124
- const { values, internalState } = ctx;
125
- const stylePaddingTop = values.get("stylePaddingTop") || 0;
126
- const stylePaddingBottom = (internalState == null ? void 0 : internalState.props.stylePaddingBottom) || 0;
127
- const headerSize = values.get("headerSize") || 0;
128
- const footerSize = values.get("footerSize") || 0;
129
- const totalSize = (_b = (_a3 = ctx.internalState) == null ? void 0 : _a3.pendingTotalSize) != null ? _b : values.get("totalSize");
130
- return headerSize + footerSize + totalSize + stylePaddingTop + stylePaddingBottom;
156
+ function listenPosition$(ctx, key, cb) {
157
+ const { positionListeners } = ctx;
158
+ let setListeners = positionListeners.get(key);
159
+ if (!setListeners) {
160
+ setListeners = /* @__PURE__ */ new Set();
161
+ positionListeners.set(key, setListeners);
162
+ }
163
+ setListeners.add(cb);
164
+ return () => setListeners.delete(cb);
165
+ }
166
+ function notifyPosition$(ctx, key, value) {
167
+ const { positionListeners } = ctx;
168
+ const setListeners = positionListeners.get(key);
169
+ if (setListeners) {
170
+ for (const listener of setListeners) {
171
+ listener(value);
172
+ }
173
+ }
131
174
  }
132
175
  function useArr$(signalNames) {
133
176
  const ctx = React2__namespace.useContext(ContextState);
@@ -208,7 +251,8 @@ var ENABLE_DEBUG_VIEW = IS_DEV && false;
208
251
  // src/constants-platform.native.ts
209
252
  var IsNewArchitecture = global.nativeFabricUIManager != null;
210
253
  var useAnimatedValue = (initialValue) => {
211
- return React2.useRef(new reactNative.Animated.Value(initialValue)).current;
254
+ const [animAnimatedValue] = React2.useState(() => new reactNative.Animated.Value(initialValue));
255
+ return animAnimatedValue;
212
256
  };
213
257
 
214
258
  // src/utils/helpers.ts
@@ -297,7 +341,7 @@ var typedForwardRef = React2.forwardRef;
297
341
  var typedMemo = React2.memo;
298
342
 
299
343
  // src/components/PositionView.native.tsx
300
- var PositionViewState = typedMemo(function PositionView({
344
+ var PositionViewState = typedMemo(function PositionViewState2({
301
345
  id,
302
346
  horizontal,
303
347
  style,
@@ -317,7 +361,7 @@ var PositionViewState = typedMemo(function PositionView({
317
361
  }
318
362
  );
319
363
  });
320
- var PositionViewAnimated = typedMemo(function PositionView2({
364
+ var PositionViewAnimated = typedMemo(function PositionViewAnimated2({
321
365
  id,
322
366
  horizontal,
323
367
  style,
@@ -360,14 +404,9 @@ var PositionViewSticky = typedMemo(function PositionViewSticky2({
360
404
  const viewStyle = React2__namespace.useMemo(() => [style, { zIndex: index + 1e3 }, { transform }], [style, transform]);
361
405
  return /* @__PURE__ */ React2__namespace.createElement(reactNative.Animated.View, { ref: refView, style: viewStyle, ...rest });
362
406
  });
363
- var PositionView3 = IsNewArchitecture ? PositionViewState : PositionViewAnimated;
364
- var symbolFirst = Symbol();
407
+ var PositionView = IsNewArchitecture ? PositionViewState : PositionViewAnimated;
365
408
  function useInit(cb) {
366
- const refValue = React2.useRef(symbolFirst);
367
- if (refValue.current === symbolFirst) {
368
- refValue.current = cb();
369
- }
370
- return refValue.current;
409
+ React2.useState(() => cb());
371
410
  }
372
411
 
373
412
  // src/state/ContextContainer.ts
@@ -633,6 +672,7 @@ var Container = typedMemo(function Container2({
633
672
  if (!IsNewArchitecture) {
634
673
  React2.useEffect(() => {
635
674
  if (!isNullOrUndefined(itemKey)) {
675
+ didLayoutRef.current = false;
636
676
  const timeout = setTimeout(() => {
637
677
  if (!didLayoutRef.current) {
638
678
  const {
@@ -652,7 +692,7 @@ var Container = typedMemo(function Container2({
652
692
  }
653
693
  }, [itemKey]);
654
694
  }
655
- const PositionComponent = isSticky ? PositionViewSticky : PositionView3;
695
+ const PositionComponent = isSticky ? PositionViewSticky : PositionView;
656
696
  return /* @__PURE__ */ React2__namespace.createElement(
657
697
  PositionComponent,
658
698
  {
@@ -687,10 +727,10 @@ var Containers = typedMemo(function Containers2({
687
727
  // If this is the initial scroll, we don't want to delay because we want to update the size immediately
688
728
  delay: (value, prevValue) => {
689
729
  var _a3;
690
- return !((_a3 = ctx.internalState) == null ? void 0 : _a3.initialScroll) ? !prevValue || value - prevValue > 20 ? 0 : 200 : void 0;
730
+ return !((_a3 = ctx.state) == null ? void 0 : _a3.initialScroll) ? !prevValue || value - prevValue > 20 ? 0 : 200 : void 0;
691
731
  }
692
732
  });
693
- const animOpacity = waitForInitialLayout && !IsNewArchitecture ? useValue$("containersDidLayout", { getValue: (value) => value ? 1 : 0 }) : void 0;
733
+ const animOpacity = waitForInitialLayout && !IsNewArchitecture ? useValue$("readyToRender", { getValue: (value) => value ? 1 : 0 }) : void 0;
694
734
  const otherAxisSize = useValue$("otherAxisSize", { delay: 0 });
695
735
  const containers = [];
696
736
  for (let i = 0; i < numContainers; i++) {
@@ -733,7 +773,8 @@ var Containers = typedMemo(function Containers2({
733
773
  return /* @__PURE__ */ React2__namespace.createElement(reactNative.Animated.View, { style }, containers);
734
774
  });
735
775
  function DevNumbers() {
736
- return IS_DEV && React2__namespace.memo(function DevNumbers2() {
776
+ return IS_DEV && // biome-ignore lint/nursery/noShadow: const function name shadowing is intentional
777
+ React2__namespace.memo(function DevNumbers2() {
737
778
  return Array.from({ length: 100 }).map((_, index) => /* @__PURE__ */ React2__namespace.createElement(
738
779
  reactNative.View,
739
780
  {
@@ -841,13 +882,6 @@ var ListComponent = typedMemo(function ListComponent2({
841
882
  () => React2__namespace.forwardRef((props, ref) => renderScrollComponent({ ...props, ref })),
842
883
  [renderScrollComponent]
843
884
  ) : ListComponentScrollView;
844
- React2__namespace.useEffect(() => {
845
- if (canRender) {
846
- setTimeout(() => {
847
- scrollAdjustHandler.setMounted();
848
- }, 0);
849
- }
850
- }, [canRender]);
851
885
  const SnapOrScroll = snapToIndices ? SnapWrapper : ScrollComponent;
852
886
  return /* @__PURE__ */ React2__namespace.createElement(
853
887
  SnapOrScroll,
@@ -911,10 +945,11 @@ function getId(state, index) {
911
945
  }
912
946
 
913
947
  // src/core/calculateOffsetForIndex.ts
914
- function calculateOffsetForIndex(ctx, state, index) {
948
+ function calculateOffsetForIndex(ctx, index) {
949
+ const state = ctx.state;
915
950
  let position = 0;
916
951
  if (index !== void 0) {
917
- position = (state == null ? void 0 : state.positions.get(getId(state, index))) || 0;
952
+ position = state.positions.get(getId(state, index)) || 0;
918
953
  const paddingTop = peek$(ctx, "stylePaddingTop");
919
954
  if (paddingTop) {
920
955
  position += paddingTop;
@@ -928,7 +963,8 @@ function calculateOffsetForIndex(ctx, state, index) {
928
963
  }
929
964
 
930
965
  // src/utils/setPaddingTop.ts
931
- function setPaddingTop(ctx, state, { stylePaddingTop, alignItemsPaddingTop }) {
966
+ function setPaddingTop(ctx, { stylePaddingTop, alignItemsPaddingTop }) {
967
+ const state = ctx.state;
932
968
  if (stylePaddingTop !== void 0) {
933
969
  const prevStylePaddingTop = peek$(ctx, "stylePaddingTop") || 0;
934
970
  if (stylePaddingTop < prevStylePaddingTop) {
@@ -947,7 +983,8 @@ function setPaddingTop(ctx, state, { stylePaddingTop, alignItemsPaddingTop }) {
947
983
  }
948
984
 
949
985
  // src/utils/updateAlignItemsPaddingTop.ts
950
- function updateAlignItemsPaddingTop(ctx, state) {
986
+ function updateAlignItemsPaddingTop(ctx) {
987
+ const state = ctx.state;
951
988
  const {
952
989
  scrollLength,
953
990
  props: { alignItemsAtEnd, data }
@@ -958,12 +995,13 @@ function updateAlignItemsPaddingTop(ctx, state) {
958
995
  const contentSize = getContentSize(ctx);
959
996
  alignItemsPaddingTop = Math.max(0, Math.floor(scrollLength - contentSize));
960
997
  }
961
- setPaddingTop(ctx, state, { alignItemsPaddingTop });
998
+ setPaddingTop(ctx, { alignItemsPaddingTop });
962
999
  }
963
1000
  }
964
1001
 
965
1002
  // src/core/addTotalSize.ts
966
- function addTotalSize(ctx, state, key, add) {
1003
+ function addTotalSize(ctx, key, add) {
1004
+ const state = ctx.state;
967
1005
  const { alignItemsAtEnd } = state.props;
968
1006
  const prevTotalSize = state.totalSize;
969
1007
  let totalSize = state.totalSize;
@@ -984,31 +1022,34 @@ function addTotalSize(ctx, state, key, add) {
984
1022
  state.totalSize = totalSize;
985
1023
  set$(ctx, "totalSize", totalSize);
986
1024
  if (alignItemsAtEnd) {
987
- updateAlignItemsPaddingTop(ctx, state);
1025
+ updateAlignItemsPaddingTop(ctx);
988
1026
  }
989
1027
  }
990
1028
  }
991
1029
  }
992
1030
 
993
1031
  // src/core/setSize.ts
994
- function setSize(ctx, state, itemKey, size) {
1032
+ function setSize(ctx, itemKey, size) {
1033
+ const state = ctx.state;
995
1034
  const { sizes } = state;
996
1035
  const previousSize = sizes.get(itemKey);
997
1036
  const diff = previousSize !== void 0 ? size - previousSize : size;
998
1037
  if (diff !== 0) {
999
- addTotalSize(ctx, state, itemKey, diff);
1038
+ addTotalSize(ctx, itemKey, diff);
1000
1039
  }
1001
1040
  sizes.set(itemKey, size);
1002
1041
  }
1003
1042
 
1004
1043
  // src/utils/getItemSize.ts
1005
- function getItemSize(ctx, state, key, index, data, useAverageSize, preferCachedSize) {
1044
+ function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize) {
1006
1045
  var _a3, _b;
1046
+ const state = ctx.state;
1007
1047
  const {
1008
1048
  sizesKnown,
1009
1049
  sizes,
1010
1050
  averageSizes,
1011
- props: { estimatedItemSize, getEstimatedItemSize, getFixedItemSize, getItemType }
1051
+ props: { estimatedItemSize, getEstimatedItemSize, getFixedItemSize, getItemType },
1052
+ scrollingTo
1012
1053
  } = state;
1013
1054
  const sizeKnown = sizesKnown.get(key);
1014
1055
  if (sizeKnown !== void 0) {
@@ -1016,7 +1057,6 @@ function getItemSize(ctx, state, key, index, data, useAverageSize, preferCachedS
1016
1057
  }
1017
1058
  let size;
1018
1059
  const itemType = getItemType ? (_a3 = getItemType(data, index)) != null ? _a3 : "" : "";
1019
- const scrollingTo = peek$(ctx, "scrollingTo");
1020
1060
  if (preferCachedSize) {
1021
1061
  const cachedSize = sizes.get(key);
1022
1062
  if (cachedSize !== void 0) {
@@ -1044,84 +1084,167 @@ function getItemSize(ctx, state, key, index, data, useAverageSize, preferCachedS
1044
1084
  if (size === void 0) {
1045
1085
  size = getEstimatedItemSize ? getEstimatedItemSize(index, data, itemType) : estimatedItemSize;
1046
1086
  }
1047
- setSize(ctx, state, key, size);
1087
+ setSize(ctx, key, size);
1048
1088
  return size;
1049
1089
  }
1050
1090
 
1051
1091
  // src/core/calculateOffsetWithOffsetPosition.ts
1052
- function calculateOffsetWithOffsetPosition(ctx, state, offsetParam, params) {
1092
+ function calculateOffsetWithOffsetPosition(ctx, offsetParam, params) {
1093
+ const state = ctx.state;
1053
1094
  const { index, viewOffset, viewPosition } = params;
1054
1095
  let offset = offsetParam;
1055
1096
  if (viewOffset) {
1056
1097
  offset -= viewOffset;
1057
1098
  }
1058
1099
  if (viewPosition !== void 0 && index !== void 0) {
1059
- offset -= viewPosition * (state.scrollLength - getItemSize(ctx, state, getId(state, index), index, state.props.data[index]));
1100
+ const itemSize = getItemSize(ctx, getId(state, index), index, state.props.data[index]);
1101
+ const trailingInset = getContentInsetEnd(state);
1102
+ offset -= viewPosition * (state.scrollLength - trailingInset - itemSize);
1060
1103
  }
1061
1104
  return offset;
1062
1105
  }
1063
1106
 
1107
+ // src/core/clampScrollOffset.ts
1108
+ function clampScrollOffset(ctx, offset) {
1109
+ const state = ctx.state;
1110
+ const contentSize = getContentSize(ctx);
1111
+ let clampedOffset = offset;
1112
+ if (Number.isFinite(contentSize) && Number.isFinite(state.scrollLength)) {
1113
+ const maxOffset = Math.max(0, contentSize - state.scrollLength);
1114
+ clampedOffset = Math.min(offset, maxOffset);
1115
+ }
1116
+ clampedOffset = Math.max(0, clampedOffset);
1117
+ return clampedOffset;
1118
+ }
1119
+ var Platform2 = reactNative.Platform;
1120
+
1121
+ // src/utils/setInitialRenderState.ts
1122
+ function setInitialRenderState(ctx, {
1123
+ didLayout,
1124
+ didInitialScroll
1125
+ }) {
1126
+ const { state } = ctx;
1127
+ if (didLayout) {
1128
+ state.didContainersLayout = true;
1129
+ }
1130
+ if (didInitialScroll) {
1131
+ state.didFinishInitialScroll = true;
1132
+ }
1133
+ if (state.didContainersLayout && state.didFinishInitialScroll) {
1134
+ set$(ctx, "readyToRender", true);
1135
+ }
1136
+ }
1137
+
1064
1138
  // src/core/finishScrollTo.ts
1065
- function finishScrollTo(ctx, state) {
1139
+ function finishScrollTo(ctx) {
1066
1140
  var _a3, _b;
1067
- if (state) {
1141
+ const state = ctx.state;
1142
+ if (state == null ? void 0 : state.scrollingTo) {
1068
1143
  state.scrollHistory.length = 0;
1069
1144
  state.initialScroll = void 0;
1070
1145
  state.initialAnchor = void 0;
1071
- set$(ctx, "scrollingTo", void 0);
1146
+ state.scrollingTo = void 0;
1072
1147
  if (state.pendingTotalSize !== void 0) {
1073
- addTotalSize(ctx, state, null, state.pendingTotalSize);
1148
+ addTotalSize(ctx, null, state.pendingTotalSize);
1074
1149
  }
1075
1150
  if ((_a3 = state.props) == null ? void 0 : _a3.data) {
1076
1151
  (_b = state.triggerCalculateItemsInView) == null ? void 0 : _b.call(state, { forceFullItemPositions: true });
1077
1152
  }
1153
+ if (Platform2.OS === "web") {
1154
+ state.scrollAdjustHandler.commitPendingAdjust();
1155
+ }
1156
+ setInitialRenderState(ctx, { didInitialScroll: true });
1078
1157
  }
1079
1158
  }
1080
- var Platform2 = reactNative.Platform;
1081
1159
 
1082
- // src/core/scrollTo.ts
1083
- function scrollTo(ctx, state, params) {
1160
+ // src/core/checkFinishedScroll.ts
1161
+ function checkFinishedScroll(ctx) {
1162
+ ctx.state.animFrameCheckFinishedScroll = requestAnimationFrame(() => checkFinishedScrollFrame(ctx));
1163
+ }
1164
+ function checkFinishedScrollFrame(ctx) {
1165
+ const scrollingTo = ctx.state.scrollingTo;
1166
+ if (scrollingTo) {
1167
+ const { state } = ctx;
1168
+ state.animFrameCheckFinishedScroll = void 0;
1169
+ const scroll = state.scroll;
1170
+ const adjust = state.scrollAdjustHandler.getAdjust();
1171
+ const clampedTargetOffset = clampScrollOffset(ctx, scrollingTo.offset - (scrollingTo.viewOffset || 0));
1172
+ const maxOffset = clampScrollOffset(ctx, scroll);
1173
+ const diff1 = Math.abs(scroll - clampedTargetOffset);
1174
+ const diff2 = Math.abs(diff1 - adjust);
1175
+ const isNotOverscrolled = Math.abs(scroll - maxOffset) < 1;
1176
+ if (isNotOverscrolled && (diff1 < 1 || diff2 < 1)) {
1177
+ finishScrollTo(ctx);
1178
+ }
1179
+ }
1180
+ }
1181
+ function checkFinishedScrollFallback(ctx) {
1182
+ const state = ctx.state;
1183
+ const scrollingTo = state.scrollingTo;
1184
+ const slowTimeout = (scrollingTo == null ? void 0 : scrollingTo.isInitialScroll) || !state.didContainersLayout;
1185
+ state.timeoutCheckFinishedScrollFallback = setTimeout(
1186
+ () => {
1187
+ let numChecks = 0;
1188
+ const checkHasScrolled = () => {
1189
+ state.timeoutCheckFinishedScrollFallback = void 0;
1190
+ const isStillScrollingTo = state.scrollingTo;
1191
+ if (isStillScrollingTo) {
1192
+ numChecks++;
1193
+ if (state.hasScrolled || numChecks > 5) {
1194
+ finishScrollTo(ctx);
1195
+ } else {
1196
+ state.timeoutCheckFinishedScrollFallback = setTimeout(checkHasScrolled, 100);
1197
+ }
1198
+ }
1199
+ };
1200
+ checkHasScrolled();
1201
+ },
1202
+ slowTimeout ? 500 : 100
1203
+ );
1204
+ }
1205
+
1206
+ // src/core/doScrollTo.native.ts
1207
+ function doScrollTo(ctx, params) {
1084
1208
  var _a3;
1085
- const { noScrollingTo, ...scrollTarget } = params;
1209
+ const state = ctx.state;
1210
+ const { animated, horizontal, offset } = params;
1211
+ const { refScroller } = state;
1212
+ (_a3 = refScroller.current) == null ? void 0 : _a3.scrollTo({
1213
+ animated: !!animated,
1214
+ x: horizontal ? offset : 0,
1215
+ y: horizontal ? 0 : offset
1216
+ });
1217
+ if (!animated) {
1218
+ state.scroll = offset;
1219
+ checkFinishedScrollFallback(ctx);
1220
+ }
1221
+ }
1222
+
1223
+ // src/core/scrollTo.ts
1224
+ function scrollTo(ctx, params) {
1225
+ const state = ctx.state;
1226
+ const { noScrollingTo, forceScroll, ...scrollTarget } = params;
1086
1227
  const { animated, isInitialScroll, offset: scrollTargetOffset, precomputedWithViewOffset } = scrollTarget;
1087
1228
  const {
1088
- refScroller,
1089
1229
  props: { horizontal }
1090
1230
  } = state;
1091
- let offset = precomputedWithViewOffset ? scrollTargetOffset : calculateOffsetWithOffsetPosition(ctx, state, scrollTargetOffset, scrollTarget);
1092
- if (Number.isFinite(state.scrollLength) && Number.isFinite(state.totalSize)) {
1093
- const maxOffset = Math.max(0, getContentSize(ctx) - state.scrollLength);
1094
- offset = Math.min(offset, maxOffset);
1231
+ if (state.animFrameCheckFinishedScroll) {
1232
+ cancelAnimationFrame(ctx.state.animFrameCheckFinishedScroll);
1233
+ }
1234
+ if (state.timeoutCheckFinishedScrollFallback) {
1235
+ clearTimeout(ctx.state.timeoutCheckFinishedScrollFallback);
1095
1236
  }
1237
+ let offset = precomputedWithViewOffset ? scrollTargetOffset : calculateOffsetWithOffsetPosition(ctx, scrollTargetOffset, scrollTarget);
1238
+ offset = clampScrollOffset(ctx, offset);
1096
1239
  state.scrollHistory.length = 0;
1097
1240
  if (!noScrollingTo) {
1098
- set$(ctx, "scrollingTo", scrollTarget);
1241
+ state.scrollingTo = scrollTarget;
1099
1242
  }
1100
1243
  state.scrollPending = offset;
1101
- if (!isInitialScroll || Platform2.OS === "android") {
1102
- (_a3 = refScroller.current) == null ? void 0 : _a3.scrollTo({
1103
- animated: !!animated,
1104
- x: horizontal ? offset : 0,
1105
- y: horizontal ? 0 : offset
1106
- });
1107
- }
1108
- if (!animated) {
1244
+ if (forceScroll || !isInitialScroll || Platform2.OS === "android") {
1245
+ doScrollTo(ctx, { animated, horizontal, isInitialScroll, offset });
1246
+ } else {
1109
1247
  state.scroll = offset;
1110
- if (Platform2.OS === "web") {
1111
- const unlisten = listen$(ctx, "containersDidLayout", (value) => {
1112
- if (value && peek$(ctx, "scrollingTo")) {
1113
- finishScrollTo(ctx, state);
1114
- unlisten();
1115
- }
1116
- });
1117
- } else {
1118
- setTimeout(() => finishScrollTo(ctx, state), 100);
1119
- }
1120
- if (isInitialScroll) {
1121
- setTimeout(() => {
1122
- state.initialScroll = void 0;
1123
- }, 500);
1124
- }
1125
1248
  }
1126
1249
  }
1127
1250
 
@@ -1130,6 +1253,12 @@ var HYSTERESIS_MULTIPLIER = 1.3;
1130
1253
  var checkThreshold = (distance, atThreshold, threshold, wasReached, snapshot, context, onReached, setSnapshot) => {
1131
1254
  const absDistance = Math.abs(distance);
1132
1255
  const within = atThreshold || threshold > 0 && absDistance <= threshold;
1256
+ if (wasReached === null) {
1257
+ if (!within && distance >= 0) {
1258
+ return false;
1259
+ }
1260
+ return null;
1261
+ }
1133
1262
  const updateSnapshot = () => {
1134
1263
  setSnapshot == null ? void 0 : setSnapshot({
1135
1264
  atThreshold,
@@ -1162,8 +1291,9 @@ var checkThreshold = (distance, atThreshold, threshold, wasReached, snapshot, co
1162
1291
  };
1163
1292
 
1164
1293
  // src/utils/checkAtBottom.ts
1165
- function checkAtBottom(ctx, state) {
1294
+ function checkAtBottom(ctx) {
1166
1295
  var _a3;
1296
+ const state = ctx.state;
1167
1297
  if (!state) {
1168
1298
  return;
1169
1299
  }
@@ -1236,15 +1366,15 @@ function checkAtTop(state) {
1236
1366
  }
1237
1367
 
1238
1368
  // src/core/updateScroll.ts
1239
- function updateScroll(ctx, state, newScroll, forceUpdate) {
1369
+ function updateScroll(ctx, newScroll, forceUpdate) {
1240
1370
  var _a3;
1241
- const scrollingTo = peek$(ctx, "scrollingTo");
1371
+ const state = ctx.state;
1372
+ const { scrollingTo, scrollAdjustHandler, lastScrollAdjustForHistory } = state;
1242
1373
  state.hasScrolled = true;
1243
1374
  state.lastBatchingAction = Date.now();
1244
1375
  const currentTime = Date.now();
1245
- const adjust = state.scrollAdjustHandler.getAdjust();
1246
- const lastHistoryAdjust = state.lastScrollAdjustForHistory;
1247
- const adjustChanged = lastHistoryAdjust !== void 0 && Math.abs(adjust - lastHistoryAdjust) > 0.1;
1376
+ const adjust = scrollAdjustHandler.getAdjust();
1377
+ const adjustChanged = lastScrollAdjustForHistory !== void 0 && Math.abs(adjust - lastScrollAdjustForHistory) > 0.1;
1248
1378
  if (adjustChanged) {
1249
1379
  state.scrollHistory.length = 0;
1250
1380
  }
@@ -1269,22 +1399,26 @@ function updateScroll(ctx, state, newScroll, forceUpdate) {
1269
1399
  return;
1270
1400
  }
1271
1401
  }
1272
- if (forceUpdate || state.dataChangeNeedsScrollUpdate || Math.abs(state.scroll - state.scrollPrev) > 2) {
1402
+ const lastCalculated = state.scrollLastCalculate;
1403
+ const shouldUpdate = forceUpdate || state.dataChangeNeedsScrollUpdate || state.scrollLastCalculate === void 0 || lastCalculated === void 0 || Math.abs(state.scroll - lastCalculated) > 2;
1404
+ if (shouldUpdate) {
1405
+ state.scrollLastCalculate = state.scroll;
1273
1406
  state.ignoreScrollFromMVCPIgnored = false;
1274
1407
  (_a3 = state.triggerCalculateItemsInView) == null ? void 0 : _a3.call(state, { doMVCP: scrollingTo !== void 0 });
1275
- checkAtBottom(ctx, state);
1408
+ checkAtBottom(ctx);
1276
1409
  checkAtTop(state);
1277
1410
  state.dataChangeNeedsScrollUpdate = false;
1278
1411
  }
1279
1412
  }
1280
1413
 
1281
1414
  // src/utils/requestAdjust.ts
1282
- function requestAdjust(ctx, state, positionDiff, dataChanged) {
1415
+ function requestAdjust(ctx, positionDiff, dataChanged) {
1416
+ const state = ctx.state;
1283
1417
  if (Math.abs(positionDiff) > 0.1) {
1284
1418
  const needsScrollWorkaround = Platform2.OS === "android" && !IsNewArchitecture && dataChanged && state.scroll <= positionDiff;
1285
1419
  const doit = () => {
1286
1420
  if (needsScrollWorkaround) {
1287
- scrollTo(ctx, state, {
1421
+ scrollTo(ctx, {
1288
1422
  noScrollingTo: true,
1289
1423
  offset: state.scroll
1290
1424
  });
@@ -1297,8 +1431,8 @@ function requestAdjust(ctx, state, positionDiff, dataChanged) {
1297
1431
  };
1298
1432
  state.scroll += positionDiff;
1299
1433
  state.scrollForNextCalculateItemsInView = void 0;
1300
- const didLayout = peek$(ctx, "containersDidLayout");
1301
- if (didLayout) {
1434
+ const readyToRender = peek$(ctx, "readyToRender");
1435
+ if (readyToRender) {
1302
1436
  doit();
1303
1437
  if (Platform2.OS !== "web") {
1304
1438
  const threshold = state.scroll - positionDiff / 2;
@@ -1320,7 +1454,7 @@ function requestAdjust(ctx, state, positionDiff, dataChanged) {
1320
1454
  if (shouldForceUpdate) {
1321
1455
  state.ignoreScrollFromMVCPIgnored = false;
1322
1456
  state.scrollPending = state.scroll;
1323
- updateScroll(ctx, state, state.scroll, true);
1457
+ updateScroll(ctx, state.scroll, true);
1324
1458
  }
1325
1459
  }, delay);
1326
1460
  }
@@ -1335,28 +1469,27 @@ function requestAdjust(ctx, state, positionDiff, dataChanged) {
1335
1469
  var INITIAL_ANCHOR_TOLERANCE = 0.5;
1336
1470
  var INITIAL_ANCHOR_MAX_ATTEMPTS = 4;
1337
1471
  var INITIAL_ANCHOR_SETTLED_TICKS = 2;
1338
- function ensureInitialAnchor(ctx, state) {
1472
+ function ensureInitialAnchor(ctx) {
1339
1473
  var _a3, _b, _c, _d, _e;
1340
- const anchor = state.initialAnchor;
1474
+ const state = ctx.state;
1475
+ const { initialAnchor, didContainersLayout, positions, scroll, scrollLength } = state;
1476
+ const anchor = initialAnchor;
1341
1477
  const item = state.props.data[anchor.index];
1342
- const containersDidLayout = peek$(ctx, "containersDidLayout");
1343
- if (!containersDidLayout) {
1478
+ if (!didContainersLayout) {
1344
1479
  return;
1345
1480
  }
1346
1481
  const id = getId(state, anchor.index);
1347
- if (state.positions.get(id) === void 0) {
1482
+ if (positions.get(id) === void 0) {
1348
1483
  return;
1349
1484
  }
1350
- const size = getItemSize(ctx, state, id, anchor.index, item, true, true);
1485
+ const size = getItemSize(ctx, id, anchor.index, item, true, true);
1351
1486
  if (size === void 0) {
1352
1487
  return;
1353
1488
  }
1354
- const availableSpace = Math.max(0, state.scrollLength - size);
1355
- const desiredOffset = calculateOffsetForIndex(ctx, state, anchor.index) - ((_a3 = anchor.viewOffset) != null ? _a3 : 0) - ((_b = anchor.viewPosition) != null ? _b : 0) * availableSpace;
1356
- const contentSize = getContentSize(ctx);
1357
- const maxOffset = Math.max(0, contentSize - state.scrollLength);
1358
- const clampedDesiredOffset = Math.max(0, Math.min(desiredOffset, maxOffset));
1359
- const delta = clampedDesiredOffset - state.scroll;
1489
+ const availableSpace = Math.max(0, scrollLength - size);
1490
+ const desiredOffset = calculateOffsetForIndex(ctx, anchor.index) - ((_a3 = anchor.viewOffset) != null ? _a3 : 0) - ((_b = anchor.viewPosition) != null ? _b : 0) * availableSpace;
1491
+ const clampedDesiredOffset = clampScrollOffset(ctx, desiredOffset);
1492
+ const delta = clampedDesiredOffset - scroll;
1360
1493
  if (Math.abs(delta) <= INITIAL_ANCHOR_TOLERANCE) {
1361
1494
  const settledTicks = ((_c = anchor.settledTicks) != null ? _c : 0) + 1;
1362
1495
  if (settledTicks >= INITIAL_ANCHOR_SETTLED_TICKS) {
@@ -1380,18 +1513,21 @@ function ensureInitialAnchor(ctx, state) {
1380
1513
  lastDelta: delta,
1381
1514
  settledTicks: 0
1382
1515
  });
1383
- requestAdjust(ctx, state, delta);
1516
+ requestAdjust(ctx, delta);
1517
+ requestAnimationFrame(() => finishScrollTo(ctx));
1384
1518
  }
1385
1519
 
1386
1520
  // src/core/mvcp.ts
1387
- function prepareMVCP(ctx, state, dataChanged) {
1521
+ function prepareMVCP(ctx, dataChanged) {
1522
+ const state = ctx.state;
1388
1523
  const { idsInView, positions, props } = state;
1389
1524
  const { maintainVisibleContentPosition } = props;
1390
- const scrollingTo = peek$(ctx, "scrollingTo");
1525
+ const scrollingTo = state.scrollingTo;
1391
1526
  let prevPosition;
1392
1527
  let targetId;
1393
1528
  const idsInViewWithPositions = [];
1394
1529
  const scrollTarget = scrollingTo == null ? void 0 : scrollingTo.index;
1530
+ const scrollingToViewPosition = scrollingTo == null ? void 0 : scrollingTo.viewPosition;
1395
1531
  const shouldMVCP = !dataChanged || maintainVisibleContentPosition;
1396
1532
  const indexByKey = state.indexByKey;
1397
1533
  if (shouldMVCP) {
@@ -1400,7 +1536,7 @@ function prepareMVCP(ctx, state, dataChanged) {
1400
1536
  return void 0;
1401
1537
  }
1402
1538
  targetId = getId(state, scrollTarget);
1403
- } else if (idsInView.length > 0 && peek$(ctx, "containersDidLayout")) {
1539
+ } else if (idsInView.length > 0 && state.didContainersLayout) {
1404
1540
  if (dataChanged) {
1405
1541
  for (let i = 0; i < idsInView.length; i++) {
1406
1542
  const id = idsInView[i];
@@ -1417,7 +1553,7 @@ function prepareMVCP(ctx, state, dataChanged) {
1417
1553
  prevPosition = positions.get(targetId);
1418
1554
  }
1419
1555
  return () => {
1420
- let positionDiff;
1556
+ let positionDiff = 0;
1421
1557
  if (dataChanged && targetId === void 0 && maintainVisibleContentPosition) {
1422
1558
  for (let i = 0; i < idsInViewWithPositions.length; i++) {
1423
1559
  const { id, position } = idsInViewWithPositions[i];
@@ -1443,16 +1579,28 @@ function prepareMVCP(ctx, state, dataChanged) {
1443
1579
  positionDiff = diff;
1444
1580
  }
1445
1581
  }
1446
- if (positionDiff !== void 0 && Math.abs(positionDiff) > 0.1) {
1447
- requestAdjust(ctx, state, positionDiff, dataChanged && maintainVisibleContentPosition);
1582
+ if (scrollingToViewPosition && scrollingToViewPosition > 0) {
1583
+ const newSize = getItemSize(ctx, targetId, scrollTarget, state.props.data[scrollTarget]);
1584
+ const prevSize = scrollingTo == null ? void 0 : scrollingTo.itemSize;
1585
+ if (newSize !== void 0 && prevSize !== void 0 && newSize !== (scrollingTo == null ? void 0 : scrollingTo.itemSize)) {
1586
+ const diff = newSize - prevSize;
1587
+ if (diff !== 0) {
1588
+ positionDiff += (newSize - prevSize) * scrollingToViewPosition;
1589
+ scrollingTo.itemSize = newSize;
1590
+ }
1591
+ }
1592
+ }
1593
+ if (Math.abs(positionDiff) > 0.1) {
1594
+ requestAdjust(ctx, positionDiff, dataChanged && maintainVisibleContentPosition);
1448
1595
  }
1449
1596
  };
1450
1597
  }
1451
1598
  }
1452
1599
 
1453
1600
  // src/core/prepareColumnStartState.ts
1454
- function prepareColumnStartState(ctx, state, startIndex, useAverageSize) {
1601
+ function prepareColumnStartState(ctx, startIndex, useAverageSize) {
1455
1602
  var _a3;
1603
+ const state = ctx.state;
1456
1604
  const numColumns = peek$(ctx, "numColumns");
1457
1605
  let rowStartIndex = startIndex;
1458
1606
  const columnAtStart = state.columns.get(state.idCache[startIndex]);
@@ -1467,7 +1615,7 @@ function prepareColumnStartState(ctx, state, startIndex, useAverageSize) {
1467
1615
  const prevId = state.idCache[prevIndex];
1468
1616
  const prevPosition = (_a3 = state.positions.get(prevId)) != null ? _a3 : 0;
1469
1617
  const prevRowStart = findRowStartIndex(state, numColumns, prevIndex);
1470
- const prevRowHeight = calculateRowMaxSize(ctx, state, prevRowStart, prevIndex, useAverageSize);
1618
+ const prevRowHeight = calculateRowMaxSize(ctx, prevRowStart, prevIndex, useAverageSize);
1471
1619
  currentRowTop = prevPosition + prevRowHeight;
1472
1620
  }
1473
1621
  return {
@@ -1490,7 +1638,8 @@ function findRowStartIndex(state, numColumns, index) {
1490
1638
  }
1491
1639
  return rowStart;
1492
1640
  }
1493
- function calculateRowMaxSize(ctx, state, startIndex, endIndex, useAverageSize) {
1641
+ function calculateRowMaxSize(ctx, startIndex, endIndex, useAverageSize) {
1642
+ const state = ctx.state;
1494
1643
  if (endIndex < startIndex) {
1495
1644
  return 0;
1496
1645
  }
@@ -1504,7 +1653,7 @@ function calculateRowMaxSize(ctx, state, startIndex, endIndex, useAverageSize) {
1504
1653
  continue;
1505
1654
  }
1506
1655
  const id = state.idCache[i];
1507
- const size = getItemSize(ctx, state, id, i, data[i], useAverageSize);
1656
+ const size = getItemSize(ctx, id, i, data[i], useAverageSize);
1508
1657
  if (size > maxSize) {
1509
1658
  maxSize = size;
1510
1659
  }
@@ -1513,22 +1662,23 @@ function calculateRowMaxSize(ctx, state, startIndex, endIndex, useAverageSize) {
1513
1662
  }
1514
1663
 
1515
1664
  // src/core/updateTotalSize.ts
1516
- function updateTotalSize(ctx, state) {
1665
+ function updateTotalSize(ctx) {
1666
+ const state = ctx.state;
1517
1667
  const {
1518
1668
  positions,
1519
1669
  props: { data }
1520
1670
  } = state;
1521
1671
  if (data.length === 0) {
1522
- addTotalSize(ctx, state, null, 0);
1672
+ addTotalSize(ctx, null, 0);
1523
1673
  } else {
1524
1674
  const lastId = getId(state, data.length - 1);
1525
1675
  if (lastId !== void 0) {
1526
1676
  const lastPosition = positions.get(lastId);
1527
1677
  if (lastPosition !== void 0) {
1528
- const lastSize = getItemSize(ctx, state, lastId, data.length - 1, data[data.length - 1]);
1678
+ const lastSize = getItemSize(ctx, lastId, data.length - 1, data[data.length - 1]);
1529
1679
  if (lastSize !== void 0) {
1530
1680
  const totalSize = lastPosition + lastSize;
1531
- addTotalSize(ctx, state, null, totalSize);
1681
+ addTotalSize(ctx, null, totalSize);
1532
1682
  }
1533
1683
  }
1534
1684
  }
@@ -1574,7 +1724,8 @@ var getScrollVelocity = (state) => {
1574
1724
  };
1575
1725
 
1576
1726
  // src/utils/updateSnapToOffsets.ts
1577
- function updateSnapToOffsets(ctx, state) {
1727
+ function updateSnapToOffsets(ctx) {
1728
+ const state = ctx.state;
1578
1729
  const {
1579
1730
  positions,
1580
1731
  props: { snapToIndices }
@@ -1589,30 +1740,30 @@ function updateSnapToOffsets(ctx, state) {
1589
1740
  }
1590
1741
 
1591
1742
  // src/core/updateItemPositions.ts
1592
- function updateItemPositions(ctx, state, dataChanged, { startIndex, scrollBottomBuffered, forceFullUpdate = false, doMVCP } = {
1743
+ function updateItemPositions(ctx, dataChanged, { startIndex, scrollBottomBuffered, forceFullUpdate = false, doMVCP } = {
1593
1744
  doMVCP: false,
1594
1745
  forceFullUpdate: false,
1595
1746
  scrollBottomBuffered: -1,
1596
1747
  startIndex: 0
1597
1748
  }) {
1598
1749
  var _a3, _b, _c, _d, _e;
1750
+ const state = ctx.state;
1599
1751
  const {
1600
1752
  columns,
1601
1753
  indexByKey,
1602
1754
  positions,
1603
1755
  idCache,
1604
1756
  sizesKnown,
1605
- props: { getEstimatedItemSize, snapToIndices, enableAverages }
1757
+ props: { data, getEstimatedItemSize, snapToIndices },
1758
+ scrollingTo
1606
1759
  } = state;
1607
- const data = state.props.data;
1608
1760
  const dataLength = data.length;
1609
1761
  const numColumns = peek$(ctx, "numColumns");
1610
- const scrollingTo = peek$(ctx, "scrollingTo");
1611
1762
  const hasColumns = numColumns > 1;
1612
1763
  const indexByKeyForChecking = IS_DEV ? /* @__PURE__ */ new Map() : void 0;
1613
1764
  const shouldOptimize = !forceFullUpdate && !dataChanged && Math.abs(getScrollVelocity(state)) > 0;
1614
1765
  const maxVisibleArea = scrollBottomBuffered + 1e3;
1615
- const useAverageSize = enableAverages && !getEstimatedItemSize;
1766
+ const useAverageSize = !getEstimatedItemSize;
1616
1767
  const preferCachedSize = !doMVCP || dataChanged || state.scrollAdjustHandler.getAdjust() !== 0 || ((_a3 = peek$(ctx, "scrollAdjustPending")) != null ? _a3 : 0) !== 0;
1617
1768
  let currentRowTop = 0;
1618
1769
  let column = 1;
@@ -1621,7 +1772,6 @@ function updateItemPositions(ctx, state, dataChanged, { startIndex, scrollBottom
1621
1772
  if (hasColumns) {
1622
1773
  const { startIndex: processedStartIndex, currentRowTop: initialRowTop } = prepareColumnStartState(
1623
1774
  ctx,
1624
- state,
1625
1775
  startIndex,
1626
1776
  useAverageSize
1627
1777
  );
@@ -1631,7 +1781,7 @@ function updateItemPositions(ctx, state, dataChanged, { startIndex, scrollBottom
1631
1781
  const prevIndex = startIndex - 1;
1632
1782
  const prevId = getId(state, prevIndex);
1633
1783
  const prevPosition = (_b = positions.get(prevId)) != null ? _b : 0;
1634
- const prevSize = (_c = sizesKnown.get(prevId)) != null ? _c : getItemSize(ctx, state, prevId, prevIndex, data[prevIndex], useAverageSize, preferCachedSize);
1784
+ const prevSize = (_c = sizesKnown.get(prevId)) != null ? _c : getItemSize(ctx, prevId, prevIndex, data[prevIndex], useAverageSize, preferCachedSize);
1635
1785
  currentRowTop = prevPosition + prevSize;
1636
1786
  }
1637
1787
  }
@@ -1648,7 +1798,7 @@ function updateItemPositions(ctx, state, dataChanged, { startIndex, scrollBottom
1648
1798
  breakAt = i + itemsPerRow + 10;
1649
1799
  }
1650
1800
  const id = (_d = idCache[i]) != null ? _d : getId(state, i);
1651
- const size = (_e = sizesKnown.get(id)) != null ? _e : getItemSize(ctx, state, id, i, data[i], useAverageSize, preferCachedSize);
1801
+ const size = (_e = sizesKnown.get(id)) != null ? _e : getItemSize(ctx, id, i, data[i], useAverageSize, preferCachedSize);
1652
1802
  if (IS_DEV && needsIndexByKey) {
1653
1803
  if (indexByKeyForChecking.has(id)) {
1654
1804
  console.error(
@@ -1657,7 +1807,10 @@ function updateItemPositions(ctx, state, dataChanged, { startIndex, scrollBottom
1657
1807
  }
1658
1808
  indexByKeyForChecking.set(id, i);
1659
1809
  }
1660
- positions.set(id, currentRowTop);
1810
+ if (currentRowTop !== positions.get(id)) {
1811
+ positions.set(id, currentRowTop);
1812
+ notifyPosition$(ctx, id, currentRowTop);
1813
+ }
1661
1814
  if (needsIndexByKey) {
1662
1815
  indexByKey.set(id, i);
1663
1816
  }
@@ -1677,10 +1830,10 @@ function updateItemPositions(ctx, state, dataChanged, { startIndex, scrollBottom
1677
1830
  }
1678
1831
  }
1679
1832
  if (!didBreakEarly) {
1680
- updateTotalSize(ctx, state);
1833
+ updateTotalSize(ctx);
1681
1834
  }
1682
1835
  if (snapToIndices) {
1683
- updateSnapToOffsets(ctx, state);
1836
+ updateSnapToOffsets(ctx);
1684
1837
  }
1685
1838
  }
1686
1839
 
@@ -1758,7 +1911,7 @@ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, stat
1758
1911
  if (previousViewableItems) {
1759
1912
  for (const viewToken of previousViewableItems) {
1760
1913
  const containerId = findContainerId(ctx, viewToken.key);
1761
- if (!isViewable(
1914
+ if (!checkIsViewable(
1762
1915
  state,
1763
1916
  ctx,
1764
1917
  viewabilityConfig,
@@ -1779,7 +1932,7 @@ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, stat
1779
1932
  if (item) {
1780
1933
  const key = getId(state, i);
1781
1934
  const containerId = findContainerId(ctx, key);
1782
- if (isViewable(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, i)) {
1935
+ if (checkIsViewable(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, i)) {
1783
1936
  const viewToken = {
1784
1937
  containerId,
1785
1938
  index: i,
@@ -1839,11 +1992,11 @@ function computeViewability(state, ctx, viewabilityConfig, containerId, key, scr
1839
1992
  const percentVisible = size ? isEntirelyVisible ? 100 : 100 * (sizeVisible / size) : 0;
1840
1993
  const percentOfScroller = size ? 100 * (sizeVisible / scrollSize) : 0;
1841
1994
  const percent = isEntirelyVisible ? 100 : viewAreaMode ? percentOfScroller : percentVisible;
1842
- const isViewable2 = percent >= viewablePercentThreshold;
1995
+ const isViewable = percent >= viewablePercentThreshold;
1843
1996
  const value = {
1844
1997
  containerId,
1845
1998
  index,
1846
- isViewable: isViewable2,
1999
+ isViewable,
1847
2000
  item,
1848
2001
  key,
1849
2002
  percentOfScroller,
@@ -1862,8 +2015,11 @@ function computeViewability(state, ctx, viewabilityConfig, containerId, key, scr
1862
2015
  }
1863
2016
  return value;
1864
2017
  }
1865
- function isViewable(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index) {
1866
- const value = ctx.mapViewabilityAmountValues.get(containerId) || computeViewability(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index);
2018
+ function checkIsViewable(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index) {
2019
+ let value = ctx.mapViewabilityAmountValues.get(containerId);
2020
+ if (!value || value.key !== key) {
2021
+ value = computeViewability(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index);
2022
+ }
1867
2023
  return value.isViewable;
1868
2024
  }
1869
2025
  function maybeUpdateViewabilityCallback(ctx, configId, containerId, viewToken) {
@@ -1891,8 +2047,9 @@ function checkAllSizesKnown(state) {
1891
2047
  }
1892
2048
 
1893
2049
  // src/utils/findAvailableContainers.ts
1894
- function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffered, pendingRemoval, requiredItemTypes, needNewContainers) {
2050
+ function findAvailableContainers(ctx, numNeeded, startBuffered, endBuffered, pendingRemoval, requiredItemTypes, needNewContainers) {
1895
2051
  const numContainers = peek$(ctx, "numContainers");
2052
+ const state = ctx.state;
1896
2053
  const { stickyContainerPool, containerItemTypes } = state;
1897
2054
  const result = [];
1898
2055
  const availableContainers = [];
@@ -1936,14 +2093,14 @@ function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffer
1936
2093
  continue;
1937
2094
  }
1938
2095
  const key = peek$(ctx, `containerItemKey${u}`);
1939
- let isOk = key === void 0;
1940
- if (!isOk && pendingRemovalSet.has(u)) {
1941
- pendingRemovalSet.delete(u);
1942
- pendingRemovalChanged = true;
1943
- const requiredType = neededTypes[typeIndex];
1944
- isOk = canReuseContainer(u, requiredType);
1945
- }
1946
- if (isOk) {
2096
+ const requiredType = neededTypes[typeIndex];
2097
+ const isPending = key !== void 0 && pendingRemovalSet.has(u);
2098
+ const canUse = key === void 0 || isPending && canReuseContainer(u, requiredType);
2099
+ if (canUse) {
2100
+ if (isPending) {
2101
+ pendingRemovalSet.delete(u);
2102
+ pendingRemovalChanged = true;
2103
+ }
1947
2104
  result.push(u);
1948
2105
  if (requiredItemTypes) {
1949
2106
  typeIndex++;
@@ -2012,21 +2169,26 @@ function comparatorByDistance(a, b) {
2012
2169
  }
2013
2170
 
2014
2171
  // src/core/scrollToIndex.ts
2015
- function scrollToIndex(ctx, state, { index, viewOffset = 0, animated = true, viewPosition }) {
2016
- if (index >= state.props.data.length) {
2017
- index = state.props.data.length - 1;
2172
+ function scrollToIndex(ctx, { index, viewOffset = 0, animated = true, viewPosition }) {
2173
+ const state = ctx.state;
2174
+ const { data } = state.props;
2175
+ if (index >= data.length) {
2176
+ index = data.length - 1;
2018
2177
  } else if (index < 0) {
2019
2178
  index = 0;
2020
2179
  }
2021
- const firstIndexOffset = calculateOffsetForIndex(ctx, state, index);
2022
- const isLast = index === state.props.data.length - 1;
2180
+ const firstIndexOffset = calculateOffsetForIndex(ctx, index);
2181
+ const isLast = index === data.length - 1;
2023
2182
  if (isLast && viewPosition === void 0) {
2024
2183
  viewPosition = 1;
2025
2184
  }
2026
2185
  state.scrollForNextCalculateItemsInView = void 0;
2027
- scrollTo(ctx, state, {
2186
+ const targetId = getId(state, index);
2187
+ const itemSize = getItemSize(ctx, targetId, index, state.props.data[index]);
2188
+ scrollTo(ctx, {
2028
2189
  animated,
2029
2190
  index,
2191
+ itemSize,
2030
2192
  offset: firstIndexOffset,
2031
2193
  viewOffset,
2032
2194
  viewPosition: viewPosition != null ? viewPosition : 0
@@ -2034,29 +2196,30 @@ function scrollToIndex(ctx, state, { index, viewOffset = 0, animated = true, vie
2034
2196
  }
2035
2197
 
2036
2198
  // src/utils/setDidLayout.ts
2037
- function setDidLayout(ctx, state) {
2199
+ function setDidLayout(ctx) {
2200
+ const state = ctx.state;
2038
2201
  const {
2039
2202
  loadStartTime,
2040
2203
  initialScroll,
2041
2204
  props: { onLoad }
2042
2205
  } = state;
2043
2206
  state.queuedInitialLayout = true;
2044
- checkAtBottom(ctx, state);
2207
+ checkAtBottom(ctx);
2045
2208
  const setIt = () => {
2046
- set$(ctx, "containersDidLayout", true);
2209
+ setInitialRenderState(ctx, { didLayout: true });
2047
2210
  if (onLoad) {
2048
2211
  onLoad({ elapsedTimeInMs: Date.now() - loadStartTime });
2049
2212
  }
2050
2213
  };
2051
2214
  if (Platform2.OS === "android" && initialScroll) {
2052
2215
  if (IsNewArchitecture) {
2053
- scrollToIndex(ctx, state, { ...initialScroll, animated: false });
2216
+ scrollToIndex(ctx, { ...initialScroll, animated: false });
2054
2217
  requestAnimationFrame(() => {
2055
- scrollToIndex(ctx, state, { ...initialScroll, animated: false });
2218
+ scrollToIndex(ctx, { ...initialScroll, animated: false });
2056
2219
  setIt();
2057
2220
  });
2058
2221
  } else {
2059
- scrollToIndex(ctx, state, { ...initialScroll, animated: false });
2222
+ scrollToIndex(ctx, { ...initialScroll, animated: false });
2060
2223
  setIt();
2061
2224
  }
2062
2225
  } else {
@@ -2079,15 +2242,17 @@ function findCurrentStickyIndex(stickyArray, scroll, state) {
2079
2242
  }
2080
2243
  return -1;
2081
2244
  }
2082
- function getActiveStickyIndices(ctx, state, stickyHeaderIndices) {
2245
+ function getActiveStickyIndices(ctx, stickyHeaderIndices) {
2246
+ const state = ctx.state;
2083
2247
  return new Set(
2084
2248
  Array.from(state.stickyContainerPool).map((i) => peek$(ctx, `containerItemKey${i}`)).map((key) => key ? state.indexByKey.get(key) : void 0).filter((idx) => idx !== void 0 && stickyHeaderIndices.has(idx))
2085
2249
  );
2086
2250
  }
2087
- function handleStickyActivation(ctx, state, stickyHeaderIndices, stickyArray, currentStickyIdx, needNewContainers, startBuffered, endBuffered) {
2251
+ function handleStickyActivation(ctx, stickyHeaderIndices, stickyArray, currentStickyIdx, needNewContainers, startBuffered, endBuffered) {
2088
2252
  var _a3;
2089
- const activeIndices = getActiveStickyIndices(ctx, state, stickyHeaderIndices);
2090
- state.activeStickyIndex = currentStickyIdx >= 0 ? stickyArray[currentStickyIdx] : void 0;
2253
+ const state = ctx.state;
2254
+ const activeIndices = getActiveStickyIndices(ctx, stickyHeaderIndices);
2255
+ set$(ctx, "activeStickyIndex", currentStickyIdx >= 0 ? stickyArray[currentStickyIdx] : -1);
2091
2256
  for (let offset = 0; offset <= 1; offset++) {
2092
2257
  const idx = currentStickyIdx - offset;
2093
2258
  if (idx < 0 || activeIndices.has(stickyArray[idx])) continue;
@@ -2098,8 +2263,9 @@ function handleStickyActivation(ctx, state, stickyHeaderIndices, stickyArray, cu
2098
2263
  }
2099
2264
  }
2100
2265
  }
2101
- function handleStickyRecycling(ctx, state, stickyArray, scroll, scrollBuffer, currentStickyIdx, pendingRemoval) {
2266
+ function handleStickyRecycling(ctx, stickyArray, scroll, scrollBuffer, currentStickyIdx, pendingRemoval) {
2102
2267
  var _a3, _b, _c;
2268
+ const state = ctx.state;
2103
2269
  for (const containerIndex of state.stickyContainerPool) {
2104
2270
  const itemKey = peek$(ctx, `containerItemKey${containerIndex}`);
2105
2271
  const itemIndex = itemKey ? state.indexByKey.get(itemKey) : void 0;
@@ -2123,7 +2289,7 @@ function handleStickyRecycling(ctx, state, stickyArray, scroll, scrollBuffer, cu
2123
2289
  const currentId = (_b = state.idCache[itemIndex]) != null ? _b : getId(state, itemIndex);
2124
2290
  if (currentId) {
2125
2291
  const currentPos = state.positions.get(currentId);
2126
- const currentSize = (_c = state.sizes.get(currentId)) != null ? _c : getItemSize(ctx, state, currentId, itemIndex, state.props.data[itemIndex]);
2292
+ const currentSize = (_c = state.sizes.get(currentId)) != null ? _c : getItemSize(ctx, currentId, itemIndex, state.props.data[itemIndex]);
2127
2293
  shouldRecycle = currentPos !== void 0 && scroll > currentPos + currentSize + scrollBuffer * 3;
2128
2294
  }
2129
2295
  }
@@ -2132,7 +2298,8 @@ function handleStickyRecycling(ctx, state, stickyArray, scroll, scrollBuffer, cu
2132
2298
  }
2133
2299
  }
2134
2300
  }
2135
- function calculateItemsInView(ctx, state, params = {}) {
2301
+ function calculateItemsInView(ctx, params = {}) {
2302
+ const state = ctx.state;
2136
2303
  reactNative.unstable_batchedUpdates(() => {
2137
2304
  var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j;
2138
2305
  const {
@@ -2156,8 +2323,8 @@ function calculateItemsInView(ctx, state, params = {}) {
2156
2323
  const stickyIndicesSet = state.props.stickyIndicesSet || /* @__PURE__ */ new Set();
2157
2324
  const prevNumContainers = peek$(ctx, "numContainers");
2158
2325
  if (!data || scrollLength === 0 || !prevNumContainers) {
2159
- if (state.initialAnchor) {
2160
- ensureInitialAnchor(ctx, state);
2326
+ if (!IsNewArchitecture && state.initialAnchor) {
2327
+ ensureInitialAnchor(ctx);
2161
2328
  }
2162
2329
  return;
2163
2330
  }
@@ -2172,15 +2339,14 @@ function calculateItemsInView(ctx, state, params = {}) {
2172
2339
  if (!queuedInitialLayout && initialScroll) {
2173
2340
  const updatedOffset = calculateOffsetWithOffsetPosition(
2174
2341
  ctx,
2175
- state,
2176
- calculateOffsetForIndex(ctx, state, initialScroll.index),
2342
+ calculateOffsetForIndex(ctx, initialScroll.index),
2177
2343
  initialScroll
2178
2344
  );
2179
2345
  scrollState = updatedOffset;
2180
2346
  }
2181
2347
  const scrollAdjustPending = (_a3 = peek$(ctx, "scrollAdjustPending")) != null ? _a3 : 0;
2182
2348
  const scrollAdjustPad = scrollAdjustPending - topPad;
2183
- let scroll = scrollState + scrollExtra + scrollAdjustPad;
2349
+ let scroll = Math.round(scrollState + scrollExtra + scrollAdjustPad);
2184
2350
  if (scroll + scrollLength > totalSize) {
2185
2351
  scroll = Math.max(0, totalSize - scrollLength);
2186
2352
  }
@@ -2188,11 +2354,12 @@ function calculateItemsInView(ctx, state, params = {}) {
2188
2354
  set$(ctx, "debugRawScroll", scrollState);
2189
2355
  set$(ctx, "debugComputedScroll", scroll);
2190
2356
  }
2191
- const previousStickyIndex = state.activeStickyIndex;
2357
+ const previousStickyIndex = peek$(ctx, "activeStickyIndex");
2192
2358
  const currentStickyIdx = stickyIndicesArr.length > 0 ? findCurrentStickyIndex(stickyIndicesArr, scroll, state) : -1;
2193
- const nextActiveStickyIndex = currentStickyIdx >= 0 ? stickyIndicesArr[currentStickyIdx] : void 0;
2194
- state.activeStickyIndex = nextActiveStickyIndex;
2195
- set$(ctx, "activeStickyIndex", nextActiveStickyIndex);
2359
+ const nextActiveStickyIndex = currentStickyIdx >= 0 ? stickyIndicesArr[currentStickyIdx] : -1;
2360
+ if (currentStickyIdx >= 0 || previousStickyIndex >= 0) {
2361
+ set$(ctx, "activeStickyIndex", nextActiveStickyIndex);
2362
+ }
2196
2363
  let scrollBufferTop = scrollBuffer;
2197
2364
  let scrollBufferBottom = scrollBuffer;
2198
2365
  if (speed > 0 || speed === 0 && scroll < Math.max(50, scrollBuffer)) {
@@ -2205,23 +2372,23 @@ function calculateItemsInView(ctx, state, params = {}) {
2205
2372
  const scrollTopBuffered = scroll - scrollBufferTop;
2206
2373
  const scrollBottom = scroll + scrollLength + (scroll < 0 ? -scroll : 0);
2207
2374
  const scrollBottomBuffered = scrollBottom + scrollBufferBottom;
2208
- if (!dataChanged && scrollForNextCalculateItemsInView) {
2375
+ if (!dataChanged && !forceFullItemPositions && scrollForNextCalculateItemsInView) {
2209
2376
  const { top, bottom } = scrollForNextCalculateItemsInView;
2210
- if (scrollTopBuffered > top && scrollBottomBuffered < bottom) {
2211
- if (state.initialAnchor) {
2212
- ensureInitialAnchor(ctx, state);
2377
+ if ((top === null || scrollTopBuffered > top) && (bottom === null || scrollBottomBuffered < bottom)) {
2378
+ if (!IsNewArchitecture && state.initialAnchor) {
2379
+ ensureInitialAnchor(ctx);
2213
2380
  }
2214
2381
  return;
2215
2382
  }
2216
2383
  }
2217
- const checkMVCP = doMVCP ? prepareMVCP(ctx, state, dataChanged) : void 0;
2384
+ const checkMVCP = doMVCP ? prepareMVCP(ctx, dataChanged) : void 0;
2218
2385
  if (dataChanged) {
2219
2386
  indexByKey.clear();
2220
2387
  idCache.length = 0;
2221
2388
  positions.clear();
2222
2389
  }
2223
- const startIndex = dataChanged ? 0 : (_b = minIndexSizeChanged != null ? minIndexSizeChanged : state.startBuffered) != null ? _b : 0;
2224
- updateItemPositions(ctx, state, dataChanged, {
2390
+ const startIndex = forceFullItemPositions || dataChanged ? 0 : (_b = minIndexSizeChanged != null ? minIndexSizeChanged : state.startBuffered) != null ? _b : 0;
2391
+ updateItemPositions(ctx, dataChanged, {
2225
2392
  doMVCP,
2226
2393
  forceFullUpdate: !!forceFullItemPositions,
2227
2394
  scrollBottomBuffered,
@@ -2240,9 +2407,9 @@ function calculateItemsInView(ctx, state, params = {}) {
2240
2407
  for (let i = loopStart; i >= 0; i--) {
2241
2408
  const id = (_c = idCache[i]) != null ? _c : getId(state, i);
2242
2409
  const top = positions.get(id);
2243
- const size = (_d = sizes.get(id)) != null ? _d : getItemSize(ctx, state, id, i, data[i]);
2410
+ const size = (_d = sizes.get(id)) != null ? _d : getItemSize(ctx, id, i, data[i]);
2244
2411
  const bottom = top + size;
2245
- if (bottom > scroll - scrollBuffer) {
2412
+ if (bottom > scroll - scrollBufferTop) {
2246
2413
  loopStart = i;
2247
2414
  } else {
2248
2415
  break;
@@ -2267,7 +2434,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2267
2434
  const dataLength = data.length;
2268
2435
  for (let i = Math.max(0, loopStart); i < dataLength && (!foundEnd || i <= maxIndexRendered); i++) {
2269
2436
  const id = (_e = idCache[i]) != null ? _e : getId(state, i);
2270
- const size = (_f = sizes.get(id)) != null ? _f : getItemSize(ctx, state, id, i, data[i]);
2437
+ const size = (_f = sizes.get(id)) != null ? _f : getItemSize(ctx, id, i, data[i]);
2271
2438
  const top = positions.get(id);
2272
2439
  if (!foundEnd) {
2273
2440
  if (startNoBuffer === null && top + size > scroll) {
@@ -2279,7 +2446,11 @@ function calculateItemsInView(ctx, state, params = {}) {
2279
2446
  if (startBuffered === null && top + size > scrollTopBuffered) {
2280
2447
  startBuffered = i;
2281
2448
  startBufferedId = id;
2282
- nextTop = top;
2449
+ if (scrollTopBuffered < 0) {
2450
+ nextTop = null;
2451
+ } else {
2452
+ nextTop = top;
2453
+ }
2283
2454
  }
2284
2455
  if (startNoBuffer !== null) {
2285
2456
  if (top <= scrollBottom) {
@@ -2287,7 +2458,11 @@ function calculateItemsInView(ctx, state, params = {}) {
2287
2458
  }
2288
2459
  if (top <= scrollBottomBuffered) {
2289
2460
  endBuffered = i;
2290
- nextBottom = top + size;
2461
+ if (scrollBottomBuffered > totalSize) {
2462
+ nextBottom = null;
2463
+ } else {
2464
+ nextBottom = top + size;
2465
+ }
2291
2466
  } else {
2292
2467
  foundEnd = true;
2293
2468
  }
@@ -2314,7 +2489,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2314
2489
  top: nextTop
2315
2490
  } : void 0;
2316
2491
  }
2317
- const numContainers = peek$(ctx, "numContainers");
2492
+ let numContainers = prevNumContainers;
2318
2493
  const pendingRemoval = [];
2319
2494
  if (dataChanged) {
2320
2495
  for (let i = 0; i < numContainers; i++) {
@@ -2325,7 +2500,6 @@ function calculateItemsInView(ctx, state, params = {}) {
2325
2500
  }
2326
2501
  }
2327
2502
  if (startBuffered !== null && endBuffered !== null) {
2328
- let numContainers2 = prevNumContainers;
2329
2503
  const needNewContainers = [];
2330
2504
  for (let i = startBuffered; i <= endBuffered; i++) {
2331
2505
  const id = (_h = idCache[i]) != null ? _h : getId(state, i);
@@ -2336,7 +2510,6 @@ function calculateItemsInView(ctx, state, params = {}) {
2336
2510
  if (stickyIndicesArr.length > 0) {
2337
2511
  handleStickyActivation(
2338
2512
  ctx,
2339
- state,
2340
2513
  stickyIndicesSet,
2341
2514
  stickyIndicesArr,
2342
2515
  currentStickyIdx,
@@ -2344,9 +2517,8 @@ function calculateItemsInView(ctx, state, params = {}) {
2344
2517
  startBuffered,
2345
2518
  endBuffered
2346
2519
  );
2347
- } else {
2348
- state.activeStickyIndex = void 0;
2349
- set$(ctx, "activeStickyIndex", void 0);
2520
+ } else if (previousStickyIndex !== -1) {
2521
+ set$(ctx, "activeStickyIndex", -1);
2350
2522
  }
2351
2523
  if (needNewContainers.length > 0) {
2352
2524
  const requiredItemTypes = getItemType ? needNewContainers.map((i) => {
@@ -2355,7 +2527,6 @@ function calculateItemsInView(ctx, state, params = {}) {
2355
2527
  }) : void 0;
2356
2528
  const availableContainers = findAvailableContainers(
2357
2529
  ctx,
2358
- state,
2359
2530
  needNewContainers.length,
2360
2531
  startBuffered,
2361
2532
  endBuffered,
@@ -2377,29 +2548,30 @@ function calculateItemsInView(ctx, state, params = {}) {
2377
2548
  state.containerItemTypes.set(containerIndex, requiredItemTypes[idx]);
2378
2549
  }
2379
2550
  containerItemKeys.add(id);
2551
+ const containerSticky = `containerSticky${containerIndex}`;
2380
2552
  if (stickyIndicesSet.has(i)) {
2381
- set$(ctx, `containerSticky${containerIndex}`, true);
2553
+ set$(ctx, containerSticky, true);
2382
2554
  const topPadding = (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "headerSize") || 0);
2383
2555
  set$(ctx, `containerStickyOffset${containerIndex}`, topPadding);
2384
2556
  state.stickyContainerPool.add(containerIndex);
2385
- } else {
2386
- set$(ctx, `containerSticky${containerIndex}`, false);
2557
+ } else if (peek$(ctx, containerSticky)) {
2558
+ set$(ctx, containerSticky, false);
2387
2559
  state.stickyContainerPool.delete(containerIndex);
2388
2560
  }
2389
- if (containerIndex >= numContainers2) {
2390
- numContainers2 = containerIndex + 1;
2561
+ if (containerIndex >= numContainers) {
2562
+ numContainers = containerIndex + 1;
2391
2563
  }
2392
2564
  }
2393
- if (numContainers2 !== prevNumContainers) {
2394
- set$(ctx, "numContainers", numContainers2);
2395
- if (numContainers2 > peek$(ctx, "numContainersPooled")) {
2396
- set$(ctx, "numContainersPooled", Math.ceil(numContainers2 * 1.5));
2565
+ if (numContainers !== prevNumContainers) {
2566
+ set$(ctx, "numContainers", numContainers);
2567
+ if (numContainers > peek$(ctx, "numContainersPooled")) {
2568
+ set$(ctx, "numContainersPooled", Math.ceil(numContainers * 1.5));
2397
2569
  }
2398
2570
  }
2399
2571
  }
2400
2572
  }
2401
2573
  if (stickyIndicesArr.length > 0) {
2402
- handleStickyRecycling(ctx, state, stickyIndicesArr, scroll, scrollBuffer, currentStickyIdx, pendingRemoval);
2574
+ handleStickyRecycling(ctx, stickyIndicesArr, scroll, scrollBuffer, currentStickyIdx, pendingRemoval);
2403
2575
  }
2404
2576
  let didChangePositions = false;
2405
2577
  for (let i = 0; i < numContainers; i++) {
@@ -2451,7 +2623,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2451
2623
  }
2452
2624
  if (!queuedInitialLayout && endBuffered !== null) {
2453
2625
  if (checkAllSizesKnown(state)) {
2454
- setDidLayout(ctx, state);
2626
+ setDidLayout(ctx);
2455
2627
  }
2456
2628
  }
2457
2629
  if (viewabilityConfigCallbackPairs) {
@@ -2464,8 +2636,8 @@ function calculateItemsInView(ctx, state, params = {}) {
2464
2636
  }
2465
2637
  }
2466
2638
  });
2467
- if (state.initialAnchor) {
2468
- ensureInitialAnchor(ctx, state);
2639
+ if (!IsNewArchitecture && state.initialAnchor) {
2640
+ ensureInitialAnchor(ctx);
2469
2641
  }
2470
2642
  }
2471
2643
 
@@ -2490,19 +2662,22 @@ function checkActualChange(state, dataProp, previousData) {
2490
2662
  }
2491
2663
 
2492
2664
  // src/core/doMaintainScrollAtEnd.ts
2493
- function doMaintainScrollAtEnd(ctx, state, animated) {
2665
+ function doMaintainScrollAtEnd(ctx, animated) {
2666
+ const state = ctx.state;
2494
2667
  const {
2668
+ didContainersLayout,
2669
+ isAtEnd,
2495
2670
  refScroller,
2496
2671
  props: { maintainScrollAtEnd }
2497
2672
  } = state;
2498
- if ((state == null ? void 0 : state.isAtEnd) && maintainScrollAtEnd && peek$(ctx, "containersDidLayout")) {
2673
+ if (isAtEnd && maintainScrollAtEnd && didContainersLayout) {
2499
2674
  const paddingTop = peek$(ctx, "alignItemsPaddingTop");
2500
2675
  if (paddingTop > 0) {
2501
2676
  state.scroll = 0;
2502
2677
  }
2503
2678
  requestAnimationFrame(() => {
2504
2679
  var _a3;
2505
- if (state == null ? void 0 : state.isAtEnd) {
2680
+ if (state.isAtEnd) {
2506
2681
  state.maintainingScrollAtEnd = true;
2507
2682
  (_a3 = refScroller.current) == null ? void 0 : _a3.scrollToEnd({
2508
2683
  animated
@@ -2573,28 +2748,30 @@ function updateAveragesOnDataChange(state, oldData, newData) {
2573
2748
  }
2574
2749
 
2575
2750
  // src/core/checkResetContainers.ts
2576
- function checkResetContainers(ctx, state, dataProp) {
2751
+ function checkResetContainers(ctx, dataProp) {
2752
+ const state = ctx.state;
2577
2753
  const { previousData } = state;
2578
2754
  if (previousData) {
2579
2755
  updateAveragesOnDataChange(state, previousData, dataProp);
2580
2756
  }
2581
2757
  const { maintainScrollAtEnd } = state.props;
2582
- calculateItemsInView(ctx, state, { dataChanged: true, doMVCP: true });
2758
+ calculateItemsInView(ctx, { dataChanged: true, doMVCP: true });
2583
2759
  const shouldMaintainScrollAtEnd = maintainScrollAtEnd === true || maintainScrollAtEnd.onDataChange;
2584
- const didMaintainScrollAtEnd = shouldMaintainScrollAtEnd && doMaintainScrollAtEnd(ctx, state, false);
2760
+ const didMaintainScrollAtEnd = shouldMaintainScrollAtEnd && doMaintainScrollAtEnd(ctx, false);
2585
2761
  if (!didMaintainScrollAtEnd && previousData && dataProp.length > previousData.length) {
2586
2762
  state.isEndReached = false;
2587
2763
  }
2588
2764
  if (!didMaintainScrollAtEnd) {
2589
2765
  checkAtTop(state);
2590
- checkAtBottom(ctx, state);
2766
+ checkAtBottom(ctx);
2591
2767
  }
2592
2768
  delete state.previousData;
2593
2769
  }
2594
2770
 
2595
2771
  // src/core/doInitialAllocateContainers.ts
2596
- function doInitialAllocateContainers(ctx, state) {
2772
+ function doInitialAllocateContainers(ctx) {
2597
2773
  var _a3, _b, _c;
2774
+ const state = ctx.state;
2598
2775
  const {
2599
2776
  scrollLength,
2600
2777
  props: {
@@ -2632,10 +2809,10 @@ function doInitialAllocateContainers(ctx, state) {
2632
2809
  if (!IsNewArchitecture || state.lastLayout) {
2633
2810
  if (state.initialScroll) {
2634
2811
  requestAnimationFrame(() => {
2635
- calculateItemsInView(ctx, state, { dataChanged: true, doMVCP: true });
2812
+ calculateItemsInView(ctx, { dataChanged: true, doMVCP: true });
2636
2813
  });
2637
2814
  } else {
2638
- calculateItemsInView(ctx, state, { dataChanged: true, doMVCP: true });
2815
+ calculateItemsInView(ctx, { dataChanged: true, doMVCP: true });
2639
2816
  }
2640
2817
  }
2641
2818
  return true;
@@ -2643,7 +2820,8 @@ function doInitialAllocateContainers(ctx, state) {
2643
2820
  }
2644
2821
 
2645
2822
  // src/core/handleLayout.ts
2646
- function handleLayout(ctx, state, layout, setCanRender) {
2823
+ function handleLayout(ctx, layout, setCanRender) {
2824
+ const state = ctx.state;
2647
2825
  const { maintainScrollAtEnd } = state.props;
2648
2826
  const measuredLength = layout[state.props.horizontal ? "width" : "height"];
2649
2827
  const previousLength = state.scrollLength;
@@ -2659,19 +2837,19 @@ function handleLayout(ctx, state, layout, setCanRender) {
2659
2837
  state.lastBatchingAction = Date.now();
2660
2838
  state.scrollForNextCalculateItemsInView = void 0;
2661
2839
  if (scrollLength > 0) {
2662
- doInitialAllocateContainers(ctx, state);
2840
+ doInitialAllocateContainers(ctx);
2663
2841
  }
2664
2842
  if (needsCalculate) {
2665
- calculateItemsInView(ctx, state, { doMVCP: true });
2843
+ calculateItemsInView(ctx, { doMVCP: true });
2666
2844
  }
2667
2845
  if (didChange || otherAxisSize !== prevOtherAxisSize) {
2668
2846
  set$(ctx, "scrollSize", { height: layout.height, width: layout.width });
2669
2847
  }
2670
2848
  if (maintainScrollAtEnd === true || maintainScrollAtEnd.onLayout) {
2671
- doMaintainScrollAtEnd(ctx, state, false);
2849
+ doMaintainScrollAtEnd(ctx, false);
2672
2850
  }
2673
- updateAlignItemsPaddingTop(ctx, state);
2674
- checkAtBottom(ctx, state);
2851
+ updateAlignItemsPaddingTop(ctx);
2852
+ checkAtBottom(ctx);
2675
2853
  checkAtTop(state);
2676
2854
  if (state) {
2677
2855
  state.needsOtherAxisSize = otherAxisSize - (state.props.stylePaddingTop || 0) < 10;
@@ -2687,8 +2865,9 @@ function handleLayout(ctx, state, layout, setCanRender) {
2687
2865
  }
2688
2866
 
2689
2867
  // src/core/onScroll.ts
2690
- function onScroll(ctx, state, event) {
2868
+ function onScroll(ctx, event) {
2691
2869
  var _a3, _b, _c;
2870
+ const state = ctx.state;
2692
2871
  const {
2693
2872
  scrollProcessingEnabled,
2694
2873
  props: { onScroll: onScrollProp }
@@ -2699,9 +2878,23 @@ function onScroll(ctx, state, event) {
2699
2878
  if (((_b = (_a3 = event.nativeEvent) == null ? void 0 : _a3.contentSize) == null ? void 0 : _b.height) === 0 && ((_c = event.nativeEvent.contentSize) == null ? void 0 : _c.width) === 0) {
2700
2879
  return;
2701
2880
  }
2702
- const newScroll = event.nativeEvent.contentOffset[state.props.horizontal ? "x" : "y"];
2881
+ let newScroll = event.nativeEvent.contentOffset[state.props.horizontal ? "x" : "y"];
2703
2882
  state.scrollPending = newScroll;
2704
- updateScroll(ctx, state, newScroll);
2883
+ if (state.scrollingTo) {
2884
+ const maxOffset = clampScrollOffset(ctx, newScroll);
2885
+ if (newScroll !== maxOffset && Math.abs(newScroll - maxOffset) > 1) {
2886
+ newScroll = maxOffset;
2887
+ scrollTo(ctx, {
2888
+ forceScroll: true,
2889
+ isInitialScroll: true,
2890
+ noScrollingTo: true,
2891
+ offset: newScroll
2892
+ });
2893
+ return;
2894
+ }
2895
+ }
2896
+ updateScroll(ctx, newScroll);
2897
+ checkFinishedScroll(ctx);
2705
2898
  onScrollProp == null ? void 0 : onScrollProp(event);
2706
2899
  }
2707
2900
 
@@ -2710,51 +2903,47 @@ var ScrollAdjustHandler = class {
2710
2903
  constructor(ctx) {
2711
2904
  this.appliedAdjust = 0;
2712
2905
  this.pendingAdjust = 0;
2713
- this.mounted = false;
2714
- this.context = ctx;
2715
- if (Platform2.OS === "web") {
2716
- const commitPendingAdjust = () => {
2717
- const state = this.context.internalState;
2718
- const pending = this.pendingAdjust;
2719
- if (pending !== 0) {
2720
- this.pendingAdjust = 0;
2721
- this.appliedAdjust += pending;
2722
- state.scroll += pending;
2723
- state.scrollForNextCalculateItemsInView = void 0;
2724
- set$(this.context, "scrollAdjustPending", 0);
2725
- set$(this.context, "scrollAdjust", this.appliedAdjust);
2726
- calculateItemsInView(this.context, this.context.internalState);
2727
- }
2728
- };
2729
- listen$(this.context, "scrollingTo", (value) => {
2730
- if (value === void 0) {
2731
- commitPendingAdjust();
2732
- }
2733
- });
2734
- }
2906
+ this.ctx = ctx;
2735
2907
  }
2736
2908
  requestAdjust(add) {
2737
- const scrollingTo = peek$(this.context, "scrollingTo");
2909
+ const scrollingTo = this.ctx.state.scrollingTo;
2738
2910
  if (Platform2.OS === "web" && (scrollingTo == null ? void 0 : scrollingTo.animated) && !scrollingTo.isInitialScroll) {
2739
2911
  this.pendingAdjust += add;
2740
- set$(this.context, "scrollAdjustPending", this.pendingAdjust);
2912
+ set$(this.ctx, "scrollAdjustPending", this.pendingAdjust);
2741
2913
  } else {
2742
2914
  this.appliedAdjust += add;
2743
- set$(this.context, "scrollAdjust", this.appliedAdjust);
2915
+ set$(this.ctx, "scrollAdjust", this.appliedAdjust);
2916
+ }
2917
+ if (this.ctx.state.scrollingTo) {
2918
+ checkFinishedScroll(this.ctx);
2744
2919
  }
2745
- }
2746
- setMounted() {
2747
- this.mounted = true;
2748
2920
  }
2749
2921
  getAdjust() {
2750
2922
  return this.appliedAdjust;
2751
2923
  }
2924
+ commitPendingAdjust() {
2925
+ if (Platform2.OS === "web") {
2926
+ const state = this.ctx.state;
2927
+ const pending = this.pendingAdjust;
2928
+ if (pending !== 0) {
2929
+ this.pendingAdjust = 0;
2930
+ this.appliedAdjust += pending;
2931
+ state.scroll += pending;
2932
+ state.scrollForNextCalculateItemsInView = void 0;
2933
+ set$(this.ctx, "scrollAdjustPending", 0);
2934
+ set$(this.ctx, "scrollAdjust", this.appliedAdjust);
2935
+ calculateItemsInView(this.ctx);
2936
+ }
2937
+ }
2938
+ }
2752
2939
  };
2753
2940
 
2754
2941
  // src/core/updateItemSize.ts
2755
- function updateItemSize(ctx, state, itemKey, sizeObj) {
2942
+ function updateItemSize(ctx, itemKey, sizeObj) {
2756
2943
  var _a3;
2944
+ const state = ctx.state;
2757
2945
  const {
2946
+ didContainersLayout,
2758
2947
  sizesKnown,
2759
2948
  props: {
2760
2949
  getFixedItemSize,
@@ -2782,13 +2971,12 @@ function updateItemSize(ctx, state, itemKey, sizeObj) {
2782
2971
  return;
2783
2972
  }
2784
2973
  }
2785
- const containersDidLayout = peek$(ctx, "containersDidLayout");
2786
- let needsRecalculate = !containersDidLayout;
2974
+ let needsRecalculate = !didContainersLayout;
2787
2975
  let shouldMaintainScrollAtEnd = false;
2788
2976
  let minIndexSizeChanged;
2789
2977
  let maxOtherAxisSize = peek$(ctx, "otherAxisSize") || 0;
2790
2978
  const prevSizeKnown = state.sizesKnown.get(itemKey);
2791
- const diff = updateOneItemSize(ctx, state, itemKey, sizeObj);
2979
+ const diff = updateOneItemSize(ctx, itemKey, sizeObj);
2792
2980
  const size = roundSize(horizontal ? sizeObj.width : sizeObj.height);
2793
2981
  if (diff !== 0) {
2794
2982
  minIndexSizeChanged = minIndexSizeChanged !== void 0 ? Math.min(minIndexSizeChanged, index) : index;
@@ -2837,22 +3025,22 @@ function updateItemSize(ctx, state, itemKey, sizeObj) {
2837
3025
  if (!cur || maxOtherAxisSize > cur) {
2838
3026
  set$(ctx, "otherAxisSize", maxOtherAxisSize);
2839
3027
  }
2840
- if (containersDidLayout || checkAllSizesKnown(state)) {
3028
+ if (didContainersLayout || checkAllSizesKnown(state)) {
2841
3029
  if (needsRecalculate) {
2842
3030
  state.scrollForNextCalculateItemsInView = void 0;
2843
- calculateItemsInView(ctx, state, { doMVCP: true });
3031
+ calculateItemsInView(ctx, { doMVCP: true });
2844
3032
  }
2845
3033
  if (shouldMaintainScrollAtEnd) {
2846
3034
  if (maintainScrollAtEnd === true || maintainScrollAtEnd.onItemLayout) {
2847
- doMaintainScrollAtEnd(ctx, state, false);
3035
+ doMaintainScrollAtEnd(ctx, false);
2848
3036
  }
2849
3037
  }
2850
3038
  }
2851
3039
  }
2852
- function updateOneItemSize(ctx, state, itemKey, sizeObj) {
3040
+ function updateOneItemSize(ctx, itemKey, sizeObj) {
2853
3041
  var _a3;
3042
+ const state = ctx.state;
2854
3043
  const {
2855
- sizes,
2856
3044
  indexByKey,
2857
3045
  sizesKnown,
2858
3046
  averageSizes,
@@ -2860,9 +3048,10 @@ function updateOneItemSize(ctx, state, itemKey, sizeObj) {
2860
3048
  } = state;
2861
3049
  if (!data) return 0;
2862
3050
  const index = indexByKey.get(itemKey);
2863
- const prevSize = getItemSize(ctx, state, itemKey, index, data[index]);
3051
+ const prevSize = getItemSize(ctx, itemKey, index, data[index]);
2864
3052
  const rawSize = horizontal ? sizeObj.width : sizeObj.height;
2865
3053
  const size = Platform2.OS === "web" ? Math.round(rawSize) : roundSize(rawSize);
3054
+ const prevSizeKnown = sizesKnown.get(itemKey);
2866
3055
  sizesKnown.set(itemKey, size);
2867
3056
  if (!getEstimatedItemSize && !getFixedItemSize && size > 0) {
2868
3057
  const itemType = getItemType ? (_a3 = getItemType(data[index], index)) != null ? _a3 : "" : "";
@@ -2870,11 +3059,15 @@ function updateOneItemSize(ctx, state, itemKey, sizeObj) {
2870
3059
  if (!averages) {
2871
3060
  averages = averageSizes[itemType] = { avg: 0, num: 0 };
2872
3061
  }
2873
- averages.avg = (averages.avg * averages.num + size) / (averages.num + 1);
2874
- averages.num++;
3062
+ if (prevSizeKnown !== void 0 && prevSizeKnown > 0) {
3063
+ averages.avg += (size - prevSizeKnown) / averages.num;
3064
+ } else {
3065
+ averages.avg = (averages.avg * averages.num + size) / (averages.num + 1);
3066
+ averages.num++;
3067
+ }
2875
3068
  }
2876
3069
  if (!prevSize || Math.abs(prevSize - size) > 0.1) {
2877
- setSize(ctx, state, itemKey, size);
3070
+ setSize(ctx, itemKey, size);
2878
3071
  return size - prevSize;
2879
3072
  }
2880
3073
  return 0;
@@ -2940,14 +3133,15 @@ function createColumnWrapperStyle(contentContainerStyle) {
2940
3133
  }
2941
3134
 
2942
3135
  // src/utils/createImperativeHandle.ts
2943
- function createImperativeHandle(ctx, state) {
3136
+ function createImperativeHandle(ctx) {
3137
+ const state = ctx.state;
2944
3138
  const scrollIndexIntoView = (options) => {
2945
3139
  if (state) {
2946
3140
  const { index, ...rest } = options;
2947
3141
  const { startNoBuffer, endNoBuffer } = state;
2948
3142
  if (index < startNoBuffer || index > endNoBuffer) {
2949
3143
  const viewPosition = index < startNoBuffer ? 0 : 1;
2950
- scrollToIndex(ctx, state, {
3144
+ scrollToIndex(ctx, {
2951
3145
  ...rest,
2952
3146
  index,
2953
3147
  viewPosition
@@ -2962,7 +3156,7 @@ function createImperativeHandle(ctx, state) {
2962
3156
  getScrollableNode: () => refScroller.current.getScrollableNode(),
2963
3157
  getScrollResponder: () => refScroller.current.getScrollResponder(),
2964
3158
  getState: () => ({
2965
- activeStickyIndex: state.activeStickyIndex,
3159
+ activeStickyIndex: peek$(ctx, "activeStickyIndex"),
2966
3160
  contentLength: state.totalSize,
2967
3161
  data: state.props.data,
2968
3162
  elementAtIndex: (index) => {
@@ -2973,6 +3167,8 @@ function createImperativeHandle(ctx, state) {
2973
3167
  endBuffered: state.endBuffered,
2974
3168
  isAtEnd: state.isAtEnd,
2975
3169
  isAtStart: state.isAtStart,
3170
+ listen: (signalName, cb) => listen$(ctx, signalName, cb),
3171
+ listenToPosition: (key, cb) => listenPosition$(ctx, key, cb),
2976
3172
  positionAtIndex: (index) => state.positions.get(getId(state, index)),
2977
3173
  positions: state.positions,
2978
3174
  scroll: state.scroll,
@@ -2997,23 +3193,23 @@ function createImperativeHandle(ctx, state) {
2997
3193
  if (index !== -1) {
2998
3194
  const paddingBottom = stylePaddingBottom || 0;
2999
3195
  const footerSize = peek$(ctx, "footerSize") || 0;
3000
- scrollToIndex(ctx, state, {
3196
+ scrollToIndex(ctx, {
3197
+ ...options,
3001
3198
  index,
3002
3199
  viewOffset: -paddingBottom - footerSize + ((options == null ? void 0 : options.viewOffset) || 0),
3003
- viewPosition: 1,
3004
- ...options
3200
+ viewPosition: 1
3005
3201
  });
3006
3202
  }
3007
3203
  },
3008
- scrollToIndex: (params) => scrollToIndex(ctx, state, params),
3204
+ scrollToIndex: (params) => scrollToIndex(ctx, params),
3009
3205
  scrollToItem: ({ item, ...props }) => {
3010
3206
  const data = state.props.data;
3011
3207
  const index = data.indexOf(item);
3012
3208
  if (index !== -1) {
3013
- scrollToIndex(ctx, state, { index, ...props });
3209
+ scrollToIndex(ctx, { index, ...props });
3014
3210
  }
3015
3211
  },
3016
- scrollToOffset: (params) => scrollTo(ctx, state, params),
3212
+ scrollToOffset: (params) => scrollTo(ctx, params),
3017
3213
  setScrollProcessingEnabled: (enabled) => {
3018
3214
  state.scrollProcessingEnabled = enabled;
3019
3215
  },
@@ -3023,8 +3219,9 @@ function createImperativeHandle(ctx, state) {
3023
3219
  }
3024
3220
  };
3025
3221
  }
3026
- function getRenderedItem(ctx, state, key) {
3222
+ function getRenderedItem(ctx, key) {
3027
3223
  var _a3;
3224
+ const state = ctx.state;
3028
3225
  if (!state) {
3029
3226
  return null;
3030
3227
  }
@@ -3101,11 +3298,13 @@ function useThrottledOnScroll(originalHandler, scrollEventThrottle) {
3101
3298
  var DEFAULT_DRAW_DISTANCE = 250;
3102
3299
  var DEFAULT_ITEM_SIZE = 100;
3103
3300
  var LegendList = typedMemo(
3301
+ // biome-ignore lint/nursery/noShadow: const function name shadowing is intentional
3104
3302
  typedForwardRef(function LegendList2(props, forwardedRef) {
3105
3303
  const { children, data: dataProp, renderItem: renderItemProp, ...restProps } = props;
3106
3304
  const isChildrenMode = children !== void 0 && dataProp === void 0;
3107
3305
  const processedProps = isChildrenMode ? {
3108
3306
  ...restProps,
3307
+ childrenMode: true,
3109
3308
  data: (isArray(children) ? children : React2__namespace.Children.toArray(children)).flat(1),
3110
3309
  renderItem: ({ item }) => item
3111
3310
  } : {
@@ -3122,10 +3321,10 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3122
3321
  alignItemsAtEnd = false,
3123
3322
  columnWrapperStyle,
3124
3323
  contentContainerStyle: contentContainerStyleProp,
3324
+ contentInset,
3125
3325
  data: dataProp = [],
3126
3326
  dataVersion,
3127
3327
  drawDistance = 250,
3128
- enableAverages = true,
3129
3328
  estimatedItemSize: estimatedItemSizeProp,
3130
3329
  estimatedListSize,
3131
3330
  extraData,
@@ -3167,6 +3366,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3167
3366
  snapToIndices,
3168
3367
  stickyHeaderIndices: stickyHeaderIndicesProp,
3169
3368
  stickyIndices: stickyIndicesDeprecated,
3369
+ // TODOV3: Remove from v3 release
3170
3370
  style: styleProp,
3171
3371
  suggestEstimatedItemSize,
3172
3372
  viewabilityConfig,
@@ -3174,6 +3374,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3174
3374
  waitForInitialLayout = true,
3175
3375
  ...rest
3176
3376
  } = props;
3377
+ const animatedPropsInternal = props.animatedPropsInternal;
3378
+ const { childrenMode } = rest;
3177
3379
  const contentContainerStyle = { ...StyleSheet.flatten(contentContainerStyleProp) };
3178
3380
  const style = { ...StyleSheet.flatten(styleProp) };
3179
3381
  const stylePaddingTopState = extractPadding(style, contentContainerStyle, "Top");
@@ -3197,10 +3399,10 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3197
3399
  }
3198
3400
  const refState = React2.useRef();
3199
3401
  if (!refState.current) {
3200
- if (!ctx.internalState) {
3402
+ if (!ctx.state) {
3201
3403
  const initialScrollLength = (estimatedListSize != null ? estimatedListSize : IsNewArchitecture ? { height: 0, width: 0 } : getWindowSize())[horizontal ? "width" : "height"];
3202
- ctx.internalState = {
3203
- activeStickyIndex: void 0,
3404
+ ctx.state = {
3405
+ activeStickyIndex: -1,
3204
3406
  averageSizes: {},
3205
3407
  columns: /* @__PURE__ */ new Map(),
3206
3408
  containerItemKeys: /* @__PURE__ */ new Set(),
@@ -3226,9 +3428,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3226
3428
  initialScroll: initialScrollProp,
3227
3429
  isAtEnd: false,
3228
3430
  isAtStart: false,
3229
- isEndReached: false,
3431
+ isEndReached: null,
3230
3432
  isFirst: true,
3231
- isStartReached: false,
3433
+ isStartReached: null,
3232
3434
  lastBatchingAction: Date.now(),
3233
3435
  lastLayout: void 0,
3234
3436
  loadStartTime: Date.now(),
@@ -3260,12 +3462,12 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3260
3462
  totalSize: 0,
3261
3463
  viewabilityConfigCallbackPairs: void 0
3262
3464
  };
3263
- const internalState = ctx.internalState;
3264
- internalState.triggerCalculateItemsInView = (params) => calculateItemsInView(ctx, internalState, params);
3465
+ const internalState = ctx.state;
3466
+ internalState.triggerCalculateItemsInView = (params) => calculateItemsInView(ctx, params);
3265
3467
  set$(ctx, "maintainVisibleContentPosition", maintainVisibleContentPosition);
3266
3468
  set$(ctx, "extraData", extraData);
3267
3469
  }
3268
- refState.current = ctx.internalState;
3470
+ refState.current = ctx.state;
3269
3471
  }
3270
3472
  const state = refState.current;
3271
3473
  const isFirstLocal = state.isFirst;
@@ -3279,9 +3481,10 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3279
3481
  const throttleScrollFn = scrollEventThrottle && onScrollProp ? useThrottledOnScroll(onScrollProp, scrollEventThrottle) : onScrollProp;
3280
3482
  state.props = {
3281
3483
  alignItemsAtEnd,
3484
+ animatedProps: animatedPropsInternal,
3485
+ contentInset,
3282
3486
  data: dataProp,
3283
3487
  dataVersion,
3284
- enableAverages,
3285
3488
  estimatedItemSize,
3286
3489
  getEstimatedItemSize,
3287
3490
  getFixedItemSize,
@@ -3324,62 +3527,62 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3324
3527
  set$(ctx, "lastItemKeys", memoizedLastItemKeys);
3325
3528
  set$(ctx, "numColumns", numColumnsProp);
3326
3529
  const prevPaddingTop = peek$(ctx, "stylePaddingTop");
3327
- setPaddingTop(ctx, state, { stylePaddingTop: stylePaddingTopState });
3530
+ setPaddingTop(ctx, { stylePaddingTop: stylePaddingTopState });
3328
3531
  refState.current.props.stylePaddingBottom = stylePaddingBottomState;
3329
3532
  let paddingDiff = stylePaddingTopState - prevPaddingTop;
3330
3533
  if (paddingDiff && prevPaddingTop !== void 0 && Platform2.OS === "ios") {
3331
3534
  if (state.scroll < 0) {
3332
3535
  paddingDiff += state.scroll;
3333
3536
  }
3334
- requestAdjust(ctx, state, paddingDiff);
3537
+ requestAdjust(ctx, paddingDiff);
3335
3538
  }
3336
3539
  };
3337
3540
  if (isFirstLocal) {
3338
3541
  initializeStateVars();
3339
3542
  updateItemPositions(
3340
3543
  ctx,
3341
- state,
3342
3544
  /*dataChanged*/
3343
3545
  true
3344
3546
  );
3345
3547
  }
3346
3548
  const initialContentOffset = React2.useMemo(() => {
3347
- var _a4, _b2;
3348
- const { initialScroll } = refState.current;
3349
- if (!initialScroll) {
3549
+ var _a4;
3550
+ let value;
3551
+ const { initialScroll, initialAnchor } = refState.current;
3552
+ if (initialScroll) {
3553
+ if (!IsNewArchitecture && initialScroll.index !== void 0 && (!initialAnchor || (initialAnchor == null ? void 0 : initialAnchor.index) !== initialScroll.index)) {
3554
+ refState.current.initialAnchor = {
3555
+ attempts: 0,
3556
+ index: initialScroll.index,
3557
+ settledTicks: 0,
3558
+ viewOffset: (_a4 = initialScroll.viewOffset) != null ? _a4 : 0,
3559
+ viewPosition: initialScroll.viewPosition
3560
+ };
3561
+ }
3562
+ if (initialScroll.contentOffset !== void 0) {
3563
+ value = initialScroll.contentOffset;
3564
+ } else {
3565
+ const baseOffset = initialScroll.index !== void 0 ? calculateOffsetForIndex(ctx, initialScroll.index) : 0;
3566
+ const resolvedOffset = calculateOffsetWithOffsetPosition(ctx, baseOffset, initialScroll);
3567
+ const clampedOffset = clampScrollOffset(ctx, resolvedOffset);
3568
+ const updatedInitialScroll = { ...initialScroll, contentOffset: clampedOffset };
3569
+ refState.current.initialScroll = updatedInitialScroll;
3570
+ state.initialScroll = updatedInitialScroll;
3571
+ value = clampedOffset;
3572
+ }
3573
+ } else {
3350
3574
  refState.current.initialAnchor = void 0;
3351
- return 0;
3352
- }
3353
- if (initialScroll.index !== void 0 && (!refState.current.initialAnchor || ((_a4 = refState.current.initialAnchor) == null ? void 0 : _a4.index) !== initialScroll.index)) {
3354
- refState.current.initialAnchor = {
3355
- attempts: 0,
3356
- index: initialScroll.index,
3357
- settledTicks: 0,
3358
- viewOffset: (_b2 = initialScroll.viewOffset) != null ? _b2 : 0,
3359
- viewPosition: initialScroll.viewPosition
3360
- };
3575
+ value = 0;
3361
3576
  }
3362
- if (initialScroll.contentOffset !== void 0) {
3363
- return initialScroll.contentOffset;
3364
- }
3365
- const baseOffset = initialScroll.index !== void 0 ? calculateOffsetForIndex(ctx, state, initialScroll.index) : 0;
3366
- const resolvedOffset = calculateOffsetWithOffsetPosition(ctx, state, baseOffset, initialScroll);
3367
- let clampedOffset = resolvedOffset;
3368
- if (Number.isFinite(state.scrollLength) && Number.isFinite(state.totalSize)) {
3369
- const maxOffset = Math.max(0, state.totalSize - state.scrollLength);
3370
- clampedOffset = Math.min(clampedOffset, maxOffset);
3371
- }
3372
- clampedOffset = Math.max(0, clampedOffset);
3373
- const updatedInitialScroll = { ...initialScroll, contentOffset: clampedOffset };
3374
- refState.current.initialScroll = updatedInitialScroll;
3375
- state.initialScroll = updatedInitialScroll;
3376
- refState.current.isStartReached = clampedOffset < refState.current.scrollLength * onStartReachedThreshold;
3377
- return clampedOffset;
3577
+ if (!value) {
3578
+ state.didFinishInitialScroll = true;
3579
+ }
3580
+ return value;
3378
3581
  }, [renderNum]);
3379
3582
  if (isFirstLocal || didDataChangeLocal || numColumnsProp !== peek$(ctx, "numColumns")) {
3380
3583
  refState.current.lastBatchingAction = Date.now();
3381
3584
  if (!keyExtractorProp && !isFirstLocal && didDataChangeLocal) {
3382
- IS_DEV && warnDevOnce(
3585
+ IS_DEV && !childrenMode && warnDevOnce(
3383
3586
  "keyExtractor",
3384
3587
  "Changing data without a keyExtractor can cause slow performance and resetting scroll. If your list data can change you should use a keyExtractor with a unique id for best performance and behavior."
3385
3588
  );
@@ -3404,12 +3607,11 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3404
3607
  }
3405
3608
  }, []);
3406
3609
  const doInitialScroll = React2.useCallback(() => {
3407
- var _a4;
3408
3610
  const initialScroll = state.initialScroll;
3409
3611
  if (initialScroll) {
3410
- scrollTo(ctx, state, {
3612
+ scrollTo(ctx, {
3411
3613
  animated: false,
3412
- index: (_a4 = state.initialScroll) == null ? void 0 : _a4.index,
3614
+ index: initialScroll == null ? void 0 : initialScroll.index,
3413
3615
  isInitialScroll: true,
3414
3616
  offset: initialContentOffset,
3415
3617
  precomputedWithViewOffset: true
@@ -3418,7 +3620,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3418
3620
  }, [initialContentOffset]);
3419
3621
  const onLayoutChange = React2.useCallback((layout) => {
3420
3622
  doInitialScroll();
3421
- handleLayout(ctx, state, layout, setCanRender);
3623
+ handleLayout(ctx, layout, setCanRender);
3422
3624
  }, []);
3423
3625
  const { onLayout } = useOnLayoutSync({
3424
3626
  onLayoutChange,
@@ -3428,7 +3630,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3428
3630
  });
3429
3631
  React2.useLayoutEffect(() => {
3430
3632
  if (snapToIndices) {
3431
- updateSnapToOffsets(ctx, state);
3633
+ updateSnapToOffsets(ctx);
3432
3634
  }
3433
3635
  }, [snapToIndices]);
3434
3636
  React2.useLayoutEffect(() => {
@@ -3438,9 +3640,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3438
3640
  isFirst,
3439
3641
  props: { data }
3440
3642
  } = state;
3441
- const didAllocateContainers = data.length > 0 && doInitialAllocateContainers(ctx, state);
3643
+ const didAllocateContainers = data.length > 0 && doInitialAllocateContainers(ctx);
3442
3644
  if (!didAllocateContainers && !isFirst && (didDataChange || didColumnsChange)) {
3443
- checkResetContainers(ctx, state, data);
3645
+ checkResetContainers(ctx, data);
3444
3646
  }
3445
3647
  state.didColumnsChange = false;
3446
3648
  state.didDataChange = false;
@@ -3467,18 +3669,24 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3467
3669
  }, [viewabilityConfig, viewabilityConfigCallbackPairs, onViewableItemsChanged]);
3468
3670
  if (!IsNewArchitecture) {
3469
3671
  useInit(() => {
3470
- doInitialAllocateContainers(ctx, state);
3672
+ doInitialAllocateContainers(ctx);
3471
3673
  });
3472
3674
  }
3473
- React2.useImperativeHandle(forwardedRef, () => createImperativeHandle(ctx, state), []);
3675
+ React2.useImperativeHandle(forwardedRef, () => createImperativeHandle(ctx), []);
3474
3676
  if (Platform2.OS === "web") {
3475
3677
  React2.useEffect(doInitialScroll, []);
3476
3678
  }
3477
3679
  const fns = React2.useMemo(
3478
3680
  () => ({
3479
- getRenderedItem: (key) => getRenderedItem(ctx, state, key),
3480
- onScroll: (event) => onScroll(ctx, state, event),
3481
- updateItemSize: (itemKey, sizeObj) => updateItemSize(ctx, state, itemKey, sizeObj)
3681
+ getRenderedItem: (key) => getRenderedItem(ctx, key),
3682
+ onMomentumScrollEnd: (event) => {
3683
+ checkFinishedScrollFallback(ctx);
3684
+ if (onMomentumScrollEnd) {
3685
+ onMomentumScrollEnd(event);
3686
+ }
3687
+ },
3688
+ onScroll: (event) => onScroll(ctx, event),
3689
+ updateItemSize: (itemKey, sizeObj) => updateItemSize(ctx, itemKey, sizeObj)
3482
3690
  }),
3483
3691
  []
3484
3692
  );
@@ -3490,6 +3698,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3490
3698
  alignItemsAtEnd,
3491
3699
  canRender,
3492
3700
  contentContainerStyle,
3701
+ contentInset,
3493
3702
  getRenderedItem: fns.getRenderedItem,
3494
3703
  horizontal,
3495
3704
  initialContentOffset,
@@ -3498,20 +3707,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3498
3707
  maintainVisibleContentPosition,
3499
3708
  onLayout,
3500
3709
  onLayoutHeader,
3501
- onMomentumScrollEnd: (event) => {
3502
- if (IsNewArchitecture) {
3503
- requestAnimationFrame(() => {
3504
- finishScrollTo(ctx, refState.current);
3505
- });
3506
- } else {
3507
- setTimeout(() => {
3508
- finishScrollTo(ctx, refState.current);
3509
- }, 1e3);
3510
- }
3511
- if (onMomentumScrollEnd) {
3512
- onMomentumScrollEnd(event);
3513
- }
3514
- },
3710
+ onMomentumScrollEnd: fns.onMomentumScrollEnd,
3515
3711
  onScroll: onScrollHandler,
3516
3712
  recycleItems,
3517
3713
  refreshControl: refreshControl ? stylePaddingTopState > 0 ? React2__namespace.cloneElement(refreshControl, {
@@ -3526,7 +3722,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3526
3722
  ),
3527
3723
  refScrollView: combinedRef,
3528
3724
  scrollAdjustHandler: (_b = refState.current) == null ? void 0 : _b.scrollAdjustHandler,
3529
- scrollEventThrottle: Platform2.OS === "web" ? 16 : void 0,
3725
+ scrollEventThrottle: 0,
3530
3726
  snapToIndices,
3531
3727
  stickyHeaderIndices,
3532
3728
  style,