@legendapp/list 2.0.0-next.2 → 2.0.0-next.20

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.
Files changed (260) hide show
  1. package/{dist/animated.d.mts → animated.d.mts} +7 -2
  2. package/{dist/animated.d.ts → animated.d.ts} +7 -2
  3. package/{dist/animated.js → animated.js} +2 -2
  4. package/{dist/animated.mjs → animated.mjs} +2 -2
  5. package/{dist/index.d.mts → index.d.mts} +106 -56
  6. package/{dist/index.d.ts → index.d.ts} +106 -56
  7. package/{dist/index.js → index.js} +1589 -1095
  8. package/{dist/index.mjs → index.mjs} +1591 -1097
  9. package/{dist/keyboard-controller.d.mts → keyboard-controller.d.mts} +28 -8
  10. package/{dist/keyboard-controller.d.ts → keyboard-controller.d.ts} +28 -8
  11. package/{dist/keyboard-controller.js → keyboard-controller.js} +4 -4
  12. package/{dist/keyboard-controller.mjs → keyboard-controller.mjs} +4 -4
  13. package/package.json +34 -88
  14. package/{dist/reanimated.d.mts → reanimated.d.mts} +2 -2
  15. package/{dist/reanimated.d.ts → reanimated.d.ts} +2 -2
  16. package/{dist/reanimated.js → reanimated.js} +7 -7
  17. package/{dist/reanimated.mjs → reanimated.mjs} +7 -7
  18. package/.claude/settings.local.json +0 -8
  19. package/.cursor/rules/changelog.mdc +0 -60
  20. package/.github/FUNDING.yml +0 -15
  21. package/.gitignore +0 -5
  22. package/.prettierrc.json +0 -5
  23. package/.vscode/settings.json +0 -14
  24. package/CLAUDE.md +0 -126
  25. package/biome.json +0 -46
  26. package/bun.lock +0 -1289
  27. package/bunfig.toml +0 -2
  28. package/dist/CHANGELOG.md +0 -119
  29. package/dist/LICENSE +0 -21
  30. package/dist/README.md +0 -139
  31. package/dist/package.json +0 -35
  32. package/example/README.md +0 -40
  33. package/example/api/data/genres.json +0 -23
  34. package/example/api/data/playlist/10402-10749.json +0 -1
  35. package/example/api/data/playlist/10402-10770.json +0 -1
  36. package/example/api/data/playlist/10402-37.json +0 -1
  37. package/example/api/data/playlist/10749-10752.json +0 -1
  38. package/example/api/data/playlist/10749-10770.json +0 -1
  39. package/example/api/data/playlist/10749-37.json +0 -1
  40. package/example/api/data/playlist/10749-878.json +0 -1
  41. package/example/api/data/playlist/10751-10402.json +0 -1
  42. package/example/api/data/playlist/10751-10752.json +0 -1
  43. package/example/api/data/playlist/10751-37.json +0 -1
  44. package/example/api/data/playlist/10751-53.json +0 -1
  45. package/example/api/data/playlist/10751-878.json +0 -1
  46. package/example/api/data/playlist/10751-9648.json +0 -1
  47. package/example/api/data/playlist/10752-37.json +0 -1
  48. package/example/api/data/playlist/12-10402.json +0 -1
  49. package/example/api/data/playlist/12-10749.json +0 -1
  50. package/example/api/data/playlist/12-18.json +0 -1
  51. package/example/api/data/playlist/12-27.json +0 -1
  52. package/example/api/data/playlist/12-35.json +0 -1
  53. package/example/api/data/playlist/14-36.json +0 -1
  54. package/example/api/data/playlist/14-878.json +0 -1
  55. package/example/api/data/playlist/16-10751.json +0 -1
  56. package/example/api/data/playlist/16-10770.json +0 -1
  57. package/example/api/data/playlist/16-35.json +0 -1
  58. package/example/api/data/playlist/16-36.json +0 -1
  59. package/example/api/data/playlist/16-53.json +0 -1
  60. package/example/api/data/playlist/18-10751.json +0 -1
  61. package/example/api/data/playlist/18-10752.json +0 -1
  62. package/example/api/data/playlist/18-37.json +0 -1
  63. package/example/api/data/playlist/18-53.json +0 -1
  64. package/example/api/data/playlist/18-878.json +0 -1
  65. package/example/api/data/playlist/27-10749.json +0 -1
  66. package/example/api/data/playlist/27-10770.json +0 -1
  67. package/example/api/data/playlist/28-10749.json +0 -1
  68. package/example/api/data/playlist/28-10751.json +0 -1
  69. package/example/api/data/playlist/28-10770.json +0 -1
  70. package/example/api/data/playlist/28-16.json +0 -1
  71. package/example/api/data/playlist/28-18.json +0 -1
  72. package/example/api/data/playlist/28-36.json +0 -1
  73. package/example/api/data/playlist/28-37.json +0 -1
  74. package/example/api/data/playlist/28-53.json +0 -1
  75. package/example/api/data/playlist/28-80.json +0 -1
  76. package/example/api/data/playlist/28-99.json +0 -1
  77. package/example/api/data/playlist/35-10749.json +0 -1
  78. package/example/api/data/playlist/35-10751.json +0 -1
  79. package/example/api/data/playlist/35-10752.json +0 -1
  80. package/example/api/data/playlist/35-27.json +0 -1
  81. package/example/api/data/playlist/35-36.json +0 -1
  82. package/example/api/data/playlist/35-53.json +0 -1
  83. package/example/api/data/playlist/35-80.json +0 -1
  84. package/example/api/data/playlist/36-37.json +0 -1
  85. package/example/api/data/playlist/36-878.json +0 -1
  86. package/example/api/data/playlist/36-9648.json +0 -1
  87. package/example/api/data/playlist/53-10752.json +0 -1
  88. package/example/api/data/playlist/80-10770.json +0 -1
  89. package/example/api/data/playlist/80-14.json +0 -1
  90. package/example/api/data/playlist/80-18.json +0 -1
  91. package/example/api/data/playlist/80-37.json +0 -1
  92. package/example/api/data/playlist/878-37.json +0 -1
  93. package/example/api/data/playlist/9648-10770.json +0 -1
  94. package/example/api/data/playlist/9648-37.json +0 -1
  95. package/example/api/data/playlist/9648-53.json +0 -1
  96. package/example/api/data/playlist/9648-878.json +0 -1
  97. package/example/api/data/playlist/99-10749.json +0 -1
  98. package/example/api/data/playlist/99-14.json +0 -1
  99. package/example/api/data/playlist/99-18.json +0 -1
  100. package/example/api/data/playlist/99-27.json +0 -1
  101. package/example/api/data/playlist/99-53.json +0 -1
  102. package/example/api/data/playlist/99-9648.json +0 -1
  103. package/example/api/data/playlist/index.ts +0 -73
  104. package/example/api/data/rows.json +0 -1
  105. package/example/api/index.ts +0 -36
  106. package/example/app/(tabs)/_layout.tsx +0 -60
  107. package/example/app/(tabs)/cards.tsx +0 -81
  108. package/example/app/(tabs)/index.tsx +0 -205
  109. package/example/app/(tabs)/moviesL.tsx +0 -7
  110. package/example/app/(tabs)/moviesLR.tsx +0 -7
  111. package/example/app/+not-found.tsx +0 -32
  112. package/example/app/_layout.tsx +0 -34
  113. package/example/app/accurate-scrollto/index.tsx +0 -125
  114. package/example/app/accurate-scrollto-2/index.tsx +0 -52
  115. package/example/app/accurate-scrollto-huge/index.tsx +0 -128
  116. package/example/app/add-to-end/index.tsx +0 -82
  117. package/example/app/ai-chat/index.tsx +0 -236
  118. package/example/app/bidirectional-infinite-list/index.tsx +0 -133
  119. package/example/app/cards-columns/index.tsx +0 -37
  120. package/example/app/cards-flashlist/index.tsx +0 -122
  121. package/example/app/cards-flatlist/index.tsx +0 -94
  122. package/example/app/cards-no-recycle/index.tsx +0 -110
  123. package/example/app/cards-renderItem.tsx +0 -354
  124. package/example/app/chat-example/index.tsx +0 -167
  125. package/example/app/chat-infinite/index.tsx +0 -239
  126. package/example/app/chat-keyboard/index.tsx +0 -248
  127. package/example/app/chat-resize-outer/index.tsx +0 -247
  128. package/example/app/columns/index.tsx +0 -78
  129. package/example/app/countries/index.tsx +0 -182
  130. package/example/app/countries-flashlist/index.tsx +0 -163
  131. package/example/app/countries-reorder/index.tsx +0 -187
  132. package/example/app/extra-data/index.tsx +0 -86
  133. package/example/app/filter-elements/filter-data-provider.tsx +0 -55
  134. package/example/app/filter-elements/index.tsx +0 -118
  135. package/example/app/initial-scroll-index/index.tsx +0 -106
  136. package/example/app/initial-scroll-index/renderFixedItem.tsx +0 -215
  137. package/example/app/initial-scroll-index-free-height/index.tsx +0 -70
  138. package/example/app/initial-scroll-index-keyed/index.tsx +0 -62
  139. package/example/app/lazy-list/index.tsx +0 -123
  140. package/example/app/movies-flashlist/index.tsx +0 -7
  141. package/example/app/mutable-cells/index.tsx +0 -104
  142. package/example/app/video-feed/index.tsx +0 -119
  143. package/example/app.config.js +0 -22
  144. package/example/app.json +0 -45
  145. package/example/assets/fonts/SpaceMono-Regular.ttf +0 -0
  146. package/example/assets/images/adaptive-icon.png +0 -0
  147. package/example/assets/images/favicon.png +0 -0
  148. package/example/assets/images/icon.png +0 -0
  149. package/example/assets/images/partial-react-logo.png +0 -0
  150. package/example/assets/images/react-logo.png +0 -0
  151. package/example/assets/images/react-logo@2x.png +0 -0
  152. package/example/assets/images/react-logo@3x.png +0 -0
  153. package/example/assets/images/splash-icon.png +0 -0
  154. package/example/autoscroll.sh +0 -101
  155. package/example/bun.lock +0 -2266
  156. package/example/bunfig.toml +0 -2
  157. package/example/components/Breathe.tsx +0 -54
  158. package/example/components/Circle.tsx +0 -69
  159. package/example/components/Collapsible.tsx +0 -44
  160. package/example/components/ExternalLink.tsx +0 -24
  161. package/example/components/HapticTab.tsx +0 -18
  162. package/example/components/HelloWave.tsx +0 -37
  163. package/example/components/Movies.tsx +0 -179
  164. package/example/components/ParallaxScrollView.tsx +0 -81
  165. package/example/components/ThemedText.tsx +0 -60
  166. package/example/components/ThemedView.tsx +0 -14
  167. package/example/components/__tests__/ThemedText-test.tsx +0 -10
  168. package/example/components/__tests__/__snapshots__/ThemedText-test.tsx.snap +0 -24
  169. package/example/components/ui/IconSymbol.ios.tsx +0 -32
  170. package/example/components/ui/IconSymbol.tsx +0 -43
  171. package/example/components/ui/TabBarBackground.ios.tsx +0 -22
  172. package/example/components/ui/TabBarBackground.tsx +0 -6
  173. package/example/constants/Colors.ts +0 -26
  174. package/example/constants/constants.ts +0 -5
  175. package/example/constants/useScrollTest.ts +0 -19
  176. package/example/hooks/useColorScheme.ts +0 -1
  177. package/example/hooks/useColorScheme.web.ts +0 -8
  178. package/example/hooks/useThemeColor.ts +0 -22
  179. package/example/ios/.xcode.env +0 -11
  180. package/example/ios/Podfile +0 -64
  181. package/example/ios/Podfile.lock +0 -2767
  182. package/example/ios/Podfile.properties.json +0 -5
  183. package/example/ios/listtest/AppDelegate.swift +0 -70
  184. package/example/ios/listtest/Images.xcassets/AppIcon.appiconset/App-Icon-1024x1024@1x.png +0 -0
  185. package/example/ios/listtest/Images.xcassets/AppIcon.appiconset/Contents.json +0 -14
  186. package/example/ios/listtest/Images.xcassets/Contents.json +0 -6
  187. package/example/ios/listtest/Images.xcassets/SplashScreenBackground.colorset/Contents.json +0 -20
  188. package/example/ios/listtest/Images.xcassets/SplashScreenLogo.imageset/Contents.json +0 -23
  189. package/example/ios/listtest/Images.xcassets/SplashScreenLogo.imageset/image.png +0 -0
  190. package/example/ios/listtest/Images.xcassets/SplashScreenLogo.imageset/image@2x.png +0 -0
  191. package/example/ios/listtest/Images.xcassets/SplashScreenLogo.imageset/image@3x.png +0 -0
  192. package/example/ios/listtest/Info.plist +0 -85
  193. package/example/ios/listtest/PrivacyInfo.xcprivacy +0 -48
  194. package/example/ios/listtest/SplashScreen.storyboard +0 -42
  195. package/example/ios/listtest/Supporting/Expo.plist +0 -12
  196. package/example/ios/listtest/listtest-Bridging-Header.h +0 -3
  197. package/example/ios/listtest/listtest.entitlements +0 -5
  198. package/example/ios/listtest.xcodeproj/project.pbxproj +0 -547
  199. package/example/ios/listtest.xcodeproj/xcshareddata/xcschemes/listtest.xcscheme +0 -88
  200. package/example/ios/listtest.xcworkspace/contents.xcworkspacedata +0 -10
  201. package/example/metro.config.js +0 -16
  202. package/example/package.json +0 -73
  203. package/example/scripts/reset-project.js +0 -84
  204. package/example/tsconfig.json +0 -26
  205. package/posttsup.ts +0 -24
  206. package/src/Container.tsx +0 -176
  207. package/src/Containers.tsx +0 -85
  208. package/src/ContextContainer.ts +0 -145
  209. package/src/DebugView.tsx +0 -83
  210. package/src/LazyLegendList.tsx +0 -41
  211. package/src/LeanView.tsx +0 -18
  212. package/src/LegendList.tsx +0 -558
  213. package/src/ListComponent.tsx +0 -191
  214. package/src/ScrollAdjust.tsx +0 -24
  215. package/src/ScrollAdjustHandler.ts +0 -26
  216. package/src/Separator.tsx +0 -14
  217. package/src/animated.tsx +0 -6
  218. package/src/calculateItemsInView.ts +0 -363
  219. package/src/calculateOffsetForIndex.ts +0 -23
  220. package/src/calculateOffsetWithOffsetPosition.ts +0 -26
  221. package/src/checkAllSizesKnown.ts +0 -17
  222. package/src/checkAtBottom.ts +0 -36
  223. package/src/checkAtTop.ts +0 -27
  224. package/src/checkThreshold.ts +0 -30
  225. package/src/constants.ts +0 -11
  226. package/src/createColumnWrapperStyle.ts +0 -16
  227. package/src/doInitialAllocateContainers.ts +0 -40
  228. package/src/doMaintainScrollAtEnd.ts +0 -34
  229. package/src/findAvailableContainers.ts +0 -98
  230. package/src/finishScrollTo.ts +0 -8
  231. package/src/getId.ts +0 -21
  232. package/src/getItemSize.ts +0 -52
  233. package/src/getRenderedItem.ts +0 -34
  234. package/src/getScrollVelocity.ts +0 -47
  235. package/src/handleLayout.ts +0 -70
  236. package/src/helpers.ts +0 -39
  237. package/src/index.ts +0 -11
  238. package/src/keyboard-controller.tsx +0 -63
  239. package/src/onScroll.ts +0 -66
  240. package/src/prepareMVCP.ts +0 -50
  241. package/src/reanimated.tsx +0 -63
  242. package/src/requestAdjust.ts +0 -41
  243. package/src/scrollTo.ts +0 -40
  244. package/src/scrollToIndex.ts +0 -34
  245. package/src/setDidLayout.ts +0 -25
  246. package/src/setPaddingTop.ts +0 -28
  247. package/src/state.tsx +0 -304
  248. package/src/types.ts +0 -610
  249. package/src/updateAlignItemsPaddingTop.ts +0 -18
  250. package/src/updateAllPositions.ts +0 -130
  251. package/src/updateItemSize.ts +0 -203
  252. package/src/updateTotalSize.ts +0 -44
  253. package/src/useAnimatedValue.ts +0 -6
  254. package/src/useCombinedRef.ts +0 -22
  255. package/src/useInit.ts +0 -17
  256. package/src/useSyncLayout.tsx +0 -68
  257. package/src/useValue$.ts +0 -53
  258. package/src/viewability.ts +0 -279
  259. package/tsconfig.json +0 -59
  260. package/tsup.config.ts +0 -21
@@ -24,21 +24,24 @@ function _interopNamespace(e) {
24
24
 
25
25
  var React3__namespace = /*#__PURE__*/_interopNamespace(React3);
26
26
 
27
- // src/LegendList.tsx
27
+ // src/components/LazyLegendList.tsx
28
28
  var ContextState = React3__namespace.createContext(null);
29
29
  function StateProvider({ children }) {
30
30
  const [value] = React3__namespace.useState(() => ({
31
+ animatedScrollY: new reactNative.Animated.Value(0),
32
+ columnWrapperStyle: void 0,
31
33
  listeners: /* @__PURE__ */ new Map(),
34
+ mapViewabilityAmountCallbacks: /* @__PURE__ */ new Map(),
35
+ mapViewabilityAmountValues: /* @__PURE__ */ new Map(),
36
+ mapViewabilityCallbacks: /* @__PURE__ */ new Map(),
37
+ mapViewabilityValues: /* @__PURE__ */ new Map(),
32
38
  values: /* @__PURE__ */ new Map([
33
39
  ["alignItemsPaddingTop", 0],
34
40
  ["stylePaddingTop", 0],
35
- ["headerSize", 0]
41
+ ["headerSize", 0],
42
+ ["numContainers", 0],
43
+ ["totalSize", 0]
36
44
  ]),
37
- mapViewabilityCallbacks: /* @__PURE__ */ new Map(),
38
- mapViewabilityValues: /* @__PURE__ */ new Map(),
39
- mapViewabilityAmountCallbacks: /* @__PURE__ */ new Map(),
40
- mapViewabilityAmountValues: /* @__PURE__ */ new Map(),
41
- columnWrapperStyle: void 0,
42
45
  viewRefs: /* @__PURE__ */ new Map()
43
46
  }));
44
47
  return /* @__PURE__ */ React3__namespace.createElement(ContextState.Provider, { value }, children);
@@ -50,17 +53,6 @@ function createSelectorFunctionsArr(ctx, signalNames) {
50
53
  let lastValues = [];
51
54
  let lastSignalValues = [];
52
55
  return {
53
- subscribe: (cb) => {
54
- const listeners = [];
55
- for (const signalName of signalNames) {
56
- listeners.push(listen$(ctx, signalName, cb));
57
- }
58
- return () => {
59
- for (const listener of listeners) {
60
- listener();
61
- }
62
- };
63
- },
64
56
  get: () => {
65
57
  const currentValues = [];
66
58
  let hasChanged = false;
@@ -76,6 +68,17 @@ function createSelectorFunctionsArr(ctx, signalNames) {
76
68
  lastValues = currentValues;
77
69
  }
78
70
  return lastValues;
71
+ },
72
+ subscribe: (cb) => {
73
+ const listeners = [];
74
+ for (const signalName of signalNames) {
75
+ listeners.push(listen$(ctx, signalName, cb));
76
+ }
77
+ return () => {
78
+ for (const listener of listeners) {
79
+ listener();
80
+ }
81
+ };
79
82
  }
80
83
  };
81
84
  }
@@ -110,7 +113,7 @@ function getContentSize(ctx) {
110
113
  const stylePaddingTop = values.get("stylePaddingTop") || 0;
111
114
  const headerSize = values.get("headerSize") || 0;
112
115
  const footerSize = values.get("footerSize") || 0;
113
- const totalSize = values.get("totalSize") || 0;
116
+ const totalSize = values.get("totalSize");
114
117
  return headerSize + footerSize + totalSize + stylePaddingTop;
115
118
  }
116
119
  function useArr$(signalNames) {
@@ -126,13 +129,13 @@ function useSelector$(signalName, selector) {
126
129
  return value;
127
130
  }
128
131
 
129
- // src/DebugView.tsx
132
+ // src/components/DebugView.tsx
130
133
  var DebugRow = ({ children }) => {
131
- return /* @__PURE__ */ React3__namespace.createElement(reactNative.View, { style: { flexDirection: "row", alignItems: "center", justifyContent: "space-between" } }, children);
134
+ return /* @__PURE__ */ React3__namespace.createElement(reactNative.View, { style: { alignItems: "center", flexDirection: "row", justifyContent: "space-between" } }, children);
132
135
  };
133
136
  var DebugView = React3__namespace.memo(function DebugView2({ state }) {
134
137
  const ctx = useStateContext();
135
- const [totalSize = 0, scrollAdjust = 0, rawScroll = 0, scroll = 0, numContainers = 0, numContainersPooled = 0] = useArr$([
138
+ const [totalSize = 0, scrollAdjust = 0, rawScroll = 0, scroll = 0, _numContainers = 0, _numContainersPooled = 0] = useArr$([
136
139
  "totalSize",
137
140
  "scrollAdjust",
138
141
  "debugRawScroll",
@@ -148,18 +151,18 @@ var DebugView = React3__namespace.memo(function DebugView2({ state }) {
148
151
  return /* @__PURE__ */ React3__namespace.createElement(
149
152
  reactNative.View,
150
153
  {
154
+ pointerEvents: "none",
151
155
  style: {
152
- position: "absolute",
153
- top: 0,
154
- right: 0,
155
- paddingLeft: 4,
156
- paddingBottom: 4,
157
156
  // height: 100,
158
157
  backgroundColor: "#FFFFFFCC",
158
+ borderRadius: 4,
159
159
  padding: 4,
160
- borderRadius: 4
161
- },
162
- pointerEvents: "none"
160
+ paddingBottom: 4,
161
+ paddingLeft: 4,
162
+ position: "absolute",
163
+ right: 0,
164
+ top: 0
165
+ }
163
166
  },
164
167
  /* @__PURE__ */ React3__namespace.createElement(DebugRow, null, /* @__PURE__ */ React3__namespace.createElement(reactNative.Text, null, "TotalSize:"), /* @__PURE__ */ React3__namespace.createElement(reactNative.Text, null, totalSize.toFixed(2))),
165
168
  /* @__PURE__ */ React3__namespace.createElement(DebugRow, null, /* @__PURE__ */ React3__namespace.createElement(reactNative.Text, null, "ContentSize:"), /* @__PURE__ */ React3__namespace.createElement(reactNative.Text, null, contentSize.toFixed(2))),
@@ -177,8 +180,143 @@ function useInterval(callback, delay) {
177
180
  return () => clearInterval(interval);
178
181
  }, [delay]);
179
182
  }
183
+ var LeanViewComponent = React3__namespace.forwardRef((props, ref) => {
184
+ return React3__namespace.createElement("RCTView", { ...props, ref });
185
+ });
186
+ LeanViewComponent.displayName = "RCTView";
187
+ var LeanView = reactNative.Platform.OS === "android" || reactNative.Platform.OS === "ios" ? LeanViewComponent : reactNative.View;
188
+
189
+ // src/constants.ts
190
+ var POSITION_OUT_OF_VIEW = -1e7;
191
+ var ENABLE_DEVMODE = __DEV__ && false;
192
+ var ENABLE_DEBUG_VIEW = __DEV__ && false;
193
+ var IsNewArchitecture = global.nativeFabricUIManager != null;
194
+ var useAnimatedValue = (initialValue) => {
195
+ return React3.useRef(new reactNative.Animated.Value(initialValue)).current;
196
+ };
197
+
198
+ // src/hooks/useValue$.ts
199
+ function useValue$(key, params) {
200
+ var _a;
201
+ const { getValue, delay } = params || {};
202
+ const ctx = useStateContext();
203
+ const animValue = useAnimatedValue((_a = getValue ? getValue(peek$(ctx, key)) : peek$(ctx, key)) != null ? _a : 0);
204
+ React3.useMemo(() => {
205
+ let newValue;
206
+ let prevValue;
207
+ let didQueueTask = false;
208
+ listen$(ctx, key, (v) => {
209
+ newValue = getValue ? getValue(v) : v;
210
+ if (delay !== void 0) {
211
+ const fn = () => {
212
+ didQueueTask = false;
213
+ if (newValue !== void 0) {
214
+ animValue.setValue(newValue);
215
+ }
216
+ };
217
+ const delayValue = typeof delay === "function" ? delay(newValue, prevValue) : delay;
218
+ prevValue = newValue;
219
+ if (!didQueueTask) {
220
+ didQueueTask = true;
221
+ if (delayValue === 0) {
222
+ queueMicrotask(fn);
223
+ } else {
224
+ setTimeout(fn, delayValue);
225
+ }
226
+ }
227
+ } else {
228
+ animValue.setValue(newValue);
229
+ }
230
+ });
231
+ }, []);
232
+ return animValue;
233
+ }
234
+ var typedForwardRef = React3.forwardRef;
235
+ var typedMemo = React3.memo;
236
+
237
+ // src/components/PositionView.tsx
238
+ var PositionViewState = typedMemo(function PositionView({
239
+ id,
240
+ horizontal,
241
+ style,
242
+ refView,
243
+ ...rest
244
+ }) {
245
+ const [position = POSITION_OUT_OF_VIEW] = useArr$([`containerPosition${id}`]);
246
+ return /* @__PURE__ */ React3__namespace.createElement(
247
+ LeanView,
248
+ {
249
+ ref: refView,
250
+ style: [
251
+ style,
252
+ horizontal ? { transform: [{ translateX: position }] } : { transform: [{ translateY: position }] }
253
+ ],
254
+ ...rest
255
+ }
256
+ );
257
+ });
258
+ var PositionViewAnimated = typedMemo(function PositionView2({
259
+ id,
260
+ horizontal,
261
+ style,
262
+ refView,
263
+ ...rest
264
+ }) {
265
+ const position$ = useValue$(`containerPosition${id}`, {
266
+ getValue: (v) => v != null ? v : POSITION_OUT_OF_VIEW
267
+ });
268
+ return /* @__PURE__ */ React3__namespace.createElement(
269
+ reactNative.Animated.View,
270
+ {
271
+ ref: refView,
272
+ style: [
273
+ style,
274
+ horizontal ? { transform: [{ translateX: position$ }] } : { transform: [{ translateY: position$ }] }
275
+ ],
276
+ ...rest
277
+ }
278
+ );
279
+ });
280
+ var PositionViewSticky = typedMemo(function PositionViewSticky2({
281
+ id,
282
+ horizontal,
283
+ style,
284
+ refView,
285
+ animatedScrollY,
286
+ stickyOffset,
287
+ index,
288
+ ...rest
289
+ }) {
290
+ const [position = POSITION_OUT_OF_VIEW] = useArr$([`containerPosition${id}`]);
291
+ const transform = React3__namespace.useMemo(() => {
292
+ if (animatedScrollY && stickyOffset) {
293
+ const stickyPosition = animatedScrollY.interpolate({
294
+ extrapolate: "clamp",
295
+ inputRange: [position, position + 5e3],
296
+ outputRange: [position, position + 5e3]
297
+ });
298
+ return horizontal ? [{ translateX: stickyPosition }] : [{ translateY: stickyPosition }];
299
+ }
300
+ }, [position, horizontal, animatedScrollY, stickyOffset]);
301
+ const viewStyle = React3__namespace.useMemo(() => [style, { zIndex: index + 1e3 }, { transform }], [style, transform]);
302
+ return /* @__PURE__ */ React3__namespace.createElement(reactNative.Animated.View, { ref: refView, style: viewStyle, ...rest });
303
+ });
304
+ var PositionView3 = IsNewArchitecture ? PositionViewState : PositionViewAnimated;
305
+ function Separator({ ItemSeparatorComponent, itemKey, leadingItem }) {
306
+ const [lastItemKeys] = useArr$(["lastItemKeys"]);
307
+ const isALastItem = lastItemKeys.includes(itemKey);
308
+ return isALastItem ? null : /* @__PURE__ */ React3__namespace.createElement(ItemSeparatorComponent, { leadingItem });
309
+ }
310
+ var symbolFirst = Symbol();
311
+ function useInit(cb) {
312
+ const refValue = React3.useRef(symbolFirst);
313
+ if (refValue.current === symbolFirst) {
314
+ refValue.current = cb();
315
+ }
316
+ return refValue.current;
317
+ }
180
318
 
181
- // src/helpers.ts
319
+ // src/utils/helpers.ts
182
320
  function isFunction(obj) {
183
321
  return typeof obj === "function";
184
322
  }
@@ -208,16 +346,8 @@ function getPadding(s, type) {
208
346
  function extractPadding(style, contentContainerStyle, type) {
209
347
  return getPadding(style, type) + getPadding(contentContainerStyle, type);
210
348
  }
211
- var symbolFirst = Symbol();
212
- function useInit(cb) {
213
- const refValue = React3.useRef(symbolFirst);
214
- if (refValue.current === symbolFirst) {
215
- refValue.current = cb();
216
- }
217
- return refValue.current;
218
- }
219
349
 
220
- // src/ContextContainer.ts
350
+ // src/state/ContextContainer.ts
221
351
  var ContextContainer = React3.createContext(null);
222
352
  function useViewability(callback, configId) {
223
353
  const ctx = useStateContext();
@@ -261,7 +391,7 @@ function useRecyclingEffect(effect) {
261
391
  prevItem: void 0
262
392
  });
263
393
  React3.useEffect(() => {
264
- let ret = void 0;
394
+ let ret;
265
395
  if (prevValues.current.prevIndex !== void 0 && prevValues.current.prevItem !== void 0) {
266
396
  ret = effect({
267
397
  index,
@@ -275,7 +405,7 @@ function useRecyclingEffect(effect) {
275
405
  prevItem: value
276
406
  };
277
407
  return ret;
278
- }, [index, value]);
408
+ }, [index, value, effect]);
279
409
  }
280
410
  function useRecyclingState(valueOrFun) {
281
411
  const { index, value, itemKey, triggerLayout } = React3.useContext(ContextContainer);
@@ -313,43 +443,26 @@ function useListScrollSize() {
313
443
  const [scrollSize] = useArr$(["scrollSize"]);
314
444
  return scrollSize;
315
445
  }
316
- var LeanViewComponent = React3__namespace.forwardRef((props, ref) => {
317
- return React3__namespace.createElement("RCTView", { ...props, ref });
318
- });
319
- LeanViewComponent.displayName = "RCTView";
320
- var LeanView = reactNative.Platform.OS === "android" || reactNative.Platform.OS === "ios" ? LeanViewComponent : reactNative.View;
321
-
322
- // src/Separator.tsx
323
- function Separator({ ItemSeparatorComponent, itemKey, leadingItem }) {
324
- const [lastItemKeys] = useArr$(["lastItemKeys"]);
325
- const isALastItem = lastItemKeys.includes(itemKey);
326
- return isALastItem ? null : /* @__PURE__ */ React.createElement(ItemSeparatorComponent, { leadingItem });
327
- }
328
-
329
- // src/constants.ts
330
- var POSITION_OUT_OF_VIEW = -1e7;
331
- var ENABLE_DEVMODE = __DEV__ && false;
332
- var ENABLE_DEBUG_VIEW = __DEV__ && false;
333
- var IsNewArchitecture = global.nativeFabricUIManager != null;
334
446
 
335
- // src/Container.tsx
336
- var Container = ({
447
+ // src/components/Container.tsx
448
+ var Container = typedMemo(function Container2({
337
449
  id,
338
450
  recycleItems,
339
451
  horizontal,
340
452
  getRenderedItem: getRenderedItem2,
341
453
  updateItemSize: updateItemSize2,
342
454
  ItemSeparatorComponent
343
- }) => {
455
+ }) {
344
456
  const ctx = useStateContext();
345
- const columnWrapperStyle = ctx.columnWrapperStyle;
346
- const [column = 0, data, itemKey, position = POSITION_OUT_OF_VIEW, numColumns, extraData] = useArr$([
457
+ const { columnWrapperStyle, animatedScrollY } = ctx;
458
+ const [column = 0, data, itemKey, numColumns, extraData, isSticky, stickyOffset] = useArr$([
347
459
  `containerColumn${id}`,
348
460
  `containerItemData${id}`,
349
461
  `containerItemKey${id}`,
350
- `containerPosition${id}`,
351
462
  "numColumns",
352
- "extraData"
463
+ "extraData",
464
+ `containerSticky${id}`,
465
+ `containerStickyOffset${id}`
353
466
  ]);
354
467
  const refLastSize = React3.useRef();
355
468
  const ref = React3.useRef(null);
@@ -357,47 +470,54 @@ var Container = ({
357
470
  const otherAxisPos = numColumns > 1 ? `${(column - 1) / numColumns * 100}%` : 0;
358
471
  const otherAxisSize = numColumns > 1 ? `${1 / numColumns * 100}%` : void 0;
359
472
  let didLayout = false;
360
- let paddingStyles;
361
- if (columnWrapperStyle) {
362
- const { columnGap, rowGap, gap } = columnWrapperStyle;
363
- if (horizontal) {
364
- paddingStyles = {
365
- paddingRight: columnGap || gap || void 0,
366
- paddingVertical: numColumns > 1 ? (rowGap || gap || 0) / 2 : void 0
367
- };
368
- } else {
369
- paddingStyles = {
370
- paddingBottom: rowGap || gap || void 0,
371
- paddingHorizontal: numColumns > 1 ? (columnGap || gap || 0) / 2 : void 0
372
- };
473
+ const style = React3.useMemo(() => {
474
+ let paddingStyles;
475
+ if (columnWrapperStyle) {
476
+ const { columnGap, rowGap, gap } = columnWrapperStyle;
477
+ if (horizontal) {
478
+ paddingStyles = {
479
+ paddingRight: columnGap || gap || void 0,
480
+ paddingVertical: numColumns > 1 ? (rowGap || gap || 0) / 2 : void 0
481
+ };
482
+ } else {
483
+ paddingStyles = {
484
+ paddingBottom: rowGap || gap || void 0,
485
+ paddingHorizontal: numColumns > 1 ? (columnGap || gap || 0) / 2 : void 0
486
+ };
487
+ }
373
488
  }
374
- }
375
- const style = horizontal ? {
376
- flexDirection: ItemSeparatorComponent ? "row" : void 0,
377
- position: "absolute",
378
- top: otherAxisPos,
379
- height: otherAxisSize,
380
- left: position,
381
- ...paddingStyles || {}
382
- } : {
383
- position: "absolute",
384
- left: otherAxisPos,
385
- right: numColumns > 1 ? null : 0,
386
- width: otherAxisSize,
387
- top: position,
388
- ...paddingStyles || {}
389
- };
489
+ return horizontal ? {
490
+ flexDirection: ItemSeparatorComponent ? "row" : void 0,
491
+ height: otherAxisSize,
492
+ left: 0,
493
+ position: "absolute",
494
+ top: otherAxisPos,
495
+ ...paddingStyles || {}
496
+ } : {
497
+ left: otherAxisPos,
498
+ position: "absolute",
499
+ right: numColumns > 1 ? null : 0,
500
+ top: 0,
501
+ width: otherAxisSize,
502
+ ...paddingStyles || {}
503
+ };
504
+ }, [horizontal, otherAxisPos, otherAxisSize, columnWrapperStyle, numColumns]);
390
505
  const renderedItemInfo = React3.useMemo(
391
506
  () => itemKey !== void 0 ? getRenderedItem2(itemKey) : null,
392
507
  [itemKey, data, extraData]
393
508
  );
394
509
  const { index, renderedItem } = renderedItemInfo || {};
395
- const triggerLayout = React3.useCallback(() => {
396
- forceLayoutRender((v) => v + 1);
397
- }, []);
398
510
  const contextValue = React3.useMemo(() => {
399
511
  ctx.viewRefs.set(id, ref);
400
- return { containerId: id, itemKey, index, value: data, triggerLayout };
512
+ return {
513
+ containerId: id,
514
+ index,
515
+ itemKey,
516
+ triggerLayout: () => {
517
+ forceLayoutRender((v) => v + 1);
518
+ },
519
+ value: data
520
+ };
401
521
  }, [id, itemKey, index, data]);
402
522
  const onLayout = (event) => {
403
523
  var _a, _b;
@@ -406,14 +526,14 @@ var Container = ({
406
526
  let layout = event.nativeEvent.layout;
407
527
  const size = layout[horizontal ? "width" : "height"];
408
528
  const doUpdate = () => {
409
- refLastSize.current = { width: layout.width, height: layout.height };
529
+ refLastSize.current = { height: layout.height, width: layout.width };
410
530
  updateItemSize2(itemKey, layout);
411
531
  };
412
532
  if (IsNewArchitecture || size > 0) {
413
533
  doUpdate();
414
534
  } else {
415
- (_b = (_a = ref.current) == null ? void 0 : _a.measure) == null ? void 0 : _b.call(_a, (x, y, width, height) => {
416
- layout = { width, height };
535
+ (_b = (_a = ref.current) == null ? void 0 : _a.measure) == null ? void 0 : _b.call(_a, (_x, _y, width, height) => {
536
+ layout = { height, width };
417
537
  doUpdate();
418
538
  });
419
539
  }
@@ -446,59 +566,32 @@ var Container = ({
446
566
  }
447
567
  }, [itemKey]);
448
568
  }
449
- return /* @__PURE__ */ React3__namespace.createElement(LeanView, { style, onLayout, ref, key: recycleItems ? void 0 : itemKey }, /* @__PURE__ */ React3__namespace.createElement(ContextContainer.Provider, { value: contextValue }, renderedItem, renderedItemInfo && ItemSeparatorComponent && /* @__PURE__ */ React3__namespace.createElement(
450
- Separator,
569
+ const PositionComponent = isSticky ? PositionViewSticky : PositionView3;
570
+ return /* @__PURE__ */ React3__namespace.createElement(
571
+ PositionComponent,
451
572
  {
452
- itemKey,
453
- ItemSeparatorComponent,
454
- leadingItem: renderedItemInfo.item
455
- }
456
- )));
457
- };
458
- var typedForwardRef = React3.forwardRef;
459
- var typedMemo = React3.memo;
460
- var useAnimatedValue = (initialValue) => {
461
- return React3.useRef(new reactNative.Animated.Value(initialValue)).current;
462
- };
463
-
464
- // src/useValue$.ts
465
- function useValue$(key, params) {
466
- var _a;
467
- const { getValue, delay } = params || {};
468
- const ctx = useStateContext();
469
- const animValue = useAnimatedValue((_a = getValue ? getValue(peek$(ctx, key)) : peek$(ctx, key)) != null ? _a : 0);
470
- React3.useMemo(() => {
471
- let newValue = void 0;
472
- let prevValue = void 0;
473
- let didQueueTask = false;
474
- listen$(ctx, key, (v) => {
475
- newValue = getValue ? getValue(v) : v;
476
- if (delay !== void 0) {
477
- const fn = () => {
478
- didQueueTask = false;
479
- if (newValue !== void 0) {
480
- animValue.setValue(newValue);
481
- }
482
- };
483
- const delayValue = typeof delay === "function" ? delay(newValue, prevValue) : delay;
484
- prevValue = newValue;
485
- if (!didQueueTask) {
486
- didQueueTask = true;
487
- if (delayValue === 0) {
488
- queueMicrotask(fn);
489
- } else {
490
- setTimeout(fn, delayValue);
491
- }
492
- }
493
- } else {
494
- animValue.setValue(newValue);
573
+ animatedScrollY: isSticky ? animatedScrollY : void 0,
574
+ horizontal,
575
+ id,
576
+ index,
577
+ key: recycleItems ? void 0 : itemKey,
578
+ onLayout,
579
+ refView: ref,
580
+ stickyOffset: isSticky ? stickyOffset : void 0,
581
+ style
582
+ },
583
+ /* @__PURE__ */ React3__namespace.createElement(ContextContainer.Provider, { value: contextValue }, renderedItem, renderedItemInfo && ItemSeparatorComponent && /* @__PURE__ */ React3__namespace.createElement(
584
+ Separator,
585
+ {
586
+ ItemSeparatorComponent,
587
+ itemKey,
588
+ leadingItem: renderedItemInfo.item
495
589
  }
496
- });
497
- }, []);
498
- return animValue;
499
- }
590
+ ))
591
+ );
592
+ });
500
593
 
501
- // src/Containers.tsx
594
+ // src/components/Containers.tsx
502
595
  var Containers = typedMemo(function Containers2({
503
596
  horizontal,
504
597
  recycleItems,
@@ -522,18 +615,18 @@ var Containers = typedMemo(function Containers2({
522
615
  /* @__PURE__ */ React3__namespace.createElement(
523
616
  Container,
524
617
  {
618
+ getRenderedItem: getRenderedItem2,
619
+ horizontal,
620
+ ItemSeparatorComponent,
525
621
  id: i,
526
622
  key: i,
527
623
  recycleItems,
528
- horizontal,
529
- getRenderedItem: getRenderedItem2,
530
- updateItemSize: updateItemSize2,
531
- ItemSeparatorComponent
624
+ updateItemSize: updateItemSize2
532
625
  }
533
626
  )
534
627
  );
535
628
  }
536
- const style = horizontal ? { width: animSize, opacity: animOpacity, minHeight: otherAxisSize } : { height: animSize, opacity: animOpacity, minWidth: otherAxisSize };
629
+ const style = horizontal ? { minHeight: otherAxisSize, opacity: animOpacity, width: animSize } : { height: animSize, minWidth: otherAxisSize, opacity: animOpacity };
537
630
  if (columnWrapperStyle && numColumns > 1) {
538
631
  const { columnGap, rowGap, gap } = columnWrapperStyle;
539
632
  const gapX = columnGap || gap || 0;
@@ -564,15 +657,21 @@ function ScrollAdjust() {
564
657
  reactNative.View,
565
658
  {
566
659
  style: {
567
- position: "absolute",
568
660
  height: 0,
569
- width: 0,
661
+ left: 0,
662
+ position: "absolute",
570
663
  top: scrollOffset,
571
- left: 0
664
+ width: 0
572
665
  }
573
666
  }
574
667
  );
575
668
  }
669
+
670
+ // src/components/SnapWrapper.tsx
671
+ function SnapWrapper({ ScrollComponent, ...props }) {
672
+ const [snapToOffsets] = useArr$(["snapToOffsets"]);
673
+ return /* @__PURE__ */ React.createElement(ScrollComponent, { ...props, snapToOffsets });
674
+ }
576
675
  function useSyncLayout({
577
676
  onChange
578
677
  }) {
@@ -583,17 +682,19 @@ function useSyncLayout({
583
682
  },
584
683
  [onChange]
585
684
  );
586
- React3.useLayoutEffect(() => {
587
- if (ref.current) {
588
- ref.current.measure((x, y, width, height) => {
589
- onChange({ x, y, width, height }, true);
590
- });
591
- }
592
- }, []);
685
+ if (IsNewArchitecture) {
686
+ React3.useLayoutEffect(() => {
687
+ if (ref.current) {
688
+ ref.current.measure((x, y, width, height) => {
689
+ onChange({ height, width, x, y }, true);
690
+ });
691
+ }
692
+ }, []);
693
+ }
593
694
  return { onLayout, ref };
594
695
  }
595
696
 
596
- // src/ListComponent.tsx
697
+ // src/components/ListComponent.tsx
597
698
  var getComponent = (Component) => {
598
699
  if (React3__namespace.isValidElement(Component)) {
599
700
  return Component;
@@ -613,12 +714,12 @@ var PaddingDevMode = () => {
613
714
  reactNative.Animated.View,
614
715
  {
615
716
  style: {
616
- position: "absolute",
617
- top: 0,
717
+ backgroundColor: "green",
618
718
  height: animPaddingTop,
619
719
  left: 0,
720
+ position: "absolute",
620
721
  right: 0,
621
- backgroundColor: "green"
722
+ top: 0
622
723
  }
623
724
  }
624
725
  ));
@@ -647,6 +748,8 @@ var ListComponent = typedMemo(function ListComponent2({
647
748
  renderScrollComponent,
648
749
  scrollAdjustHandler,
649
750
  onLayoutHeader,
751
+ snapToIndices,
752
+ stickyIndices,
650
753
  ...rest
651
754
  }) {
652
755
  const ctx = useStateContext();
@@ -656,7 +759,7 @@ var ListComponent = typedMemo(function ListComponent2({
656
759
  const ScrollComponent = renderScrollComponent ? React3.useMemo(
657
760
  () => React3__namespace.forwardRef((props, ref) => renderScrollComponent({ ...props, ref })),
658
761
  [renderScrollComponent]
659
- ) : reactNative.ScrollView;
762
+ ) : reactNative.Animated.ScrollView;
660
763
  React3__namespace.useEffect(() => {
661
764
  if (canRender) {
662
765
  setTimeout(() => {
@@ -664,76 +767,73 @@ var ListComponent = typedMemo(function ListComponent2({
664
767
  }, 0);
665
768
  }
666
769
  }, [canRender]);
770
+ const SnapOrScroll = snapToIndices ? SnapWrapper : ScrollComponent;
667
771
  return /* @__PURE__ */ React3__namespace.createElement(
668
- ScrollComponent,
772
+ SnapOrScroll,
669
773
  {
670
774
  ...rest,
671
- style,
672
- maintainVisibleContentPosition: maintainVisibleContentPosition && !ListEmptyComponent ? { minIndexForVisible: 0 } : void 0,
673
775
  contentContainerStyle: [
674
776
  contentContainerStyle,
675
777
  horizontal ? {
676
778
  height: "100%"
677
779
  } : {}
678
780
  ],
679
- onScroll: onScroll2,
680
- onLayout,
681
- horizontal,
682
781
  contentOffset: initialContentOffset ? horizontal ? { x: initialContentOffset, y: 0 } : { x: 0, y: initialContentOffset } : void 0,
683
- ref: refScrollView
782
+ horizontal,
783
+ maintainVisibleContentPosition: maintainVisibleContentPosition && !ListEmptyComponent ? { minIndexForVisible: 0 } : void 0,
784
+ onLayout,
785
+ onScroll: onScroll2,
786
+ ref: refScrollView,
787
+ ScrollComponent: snapToIndices ? ScrollComponent : void 0,
788
+ style
684
789
  },
685
790
  maintainVisibleContentPosition && /* @__PURE__ */ React3__namespace.createElement(ScrollAdjust, null),
686
791
  ENABLE_DEVMODE ? /* @__PURE__ */ React3__namespace.createElement(PaddingDevMode, null) : /* @__PURE__ */ React3__namespace.createElement(Padding, null),
687
- ListHeaderComponent && /* @__PURE__ */ React3__namespace.createElement(reactNative.View, { style: ListHeaderComponentStyle, onLayout: onLayoutHeaderSync, ref: refHeader }, getComponent(ListHeaderComponent)),
792
+ ListHeaderComponent && /* @__PURE__ */ React3__namespace.createElement(reactNative.View, { onLayout: onLayoutHeaderSync, ref: refHeader, style: ListHeaderComponentStyle }, getComponent(ListHeaderComponent)),
688
793
  ListEmptyComponent && getComponent(ListEmptyComponent),
689
794
  canRender && /* @__PURE__ */ React3__namespace.createElement(
690
795
  Containers,
691
796
  {
692
- horizontal,
693
- recycleItems,
694
- waitForInitialLayout,
695
797
  getRenderedItem: getRenderedItem2,
798
+ horizontal,
696
799
  ItemSeparatorComponent,
697
- updateItemSize: updateItemSize2
800
+ recycleItems,
801
+ updateItemSize: updateItemSize2,
802
+ waitForInitialLayout
698
803
  }
699
804
  ),
700
805
  ListFooterComponent && /* @__PURE__ */ React3__namespace.createElement(
701
806
  reactNative.View,
702
807
  {
703
- style: ListFooterComponentStyle,
704
808
  onLayout: (event) => {
705
809
  const size = event.nativeEvent.layout[horizontal ? "width" : "height"];
706
810
  set$(ctx, "footerSize", size);
707
- }
811
+ },
812
+ style: ListFooterComponentStyle
708
813
  },
709
814
  getComponent(ListFooterComponent)
710
- )
815
+ ),
816
+ __DEV__ && ENABLE_DEVMODE && /* @__PURE__ */ React3__namespace.createElement(DevNumbers, null)
711
817
  );
712
818
  });
819
+ var DevNumbers = __DEV__ && React3__namespace.memo(function DevNumbers2() {
820
+ return Array.from({ length: 100 }).map((_, index) => /* @__PURE__ */ React3__namespace.createElement(
821
+ reactNative.View,
822
+ {
823
+ key: index,
824
+ style: {
825
+ height: 100,
826
+ pointerEvents: "none",
827
+ position: "absolute",
828
+ top: index * 100,
829
+ width: "100%"
830
+ }
831
+ },
832
+ /* @__PURE__ */ React3__namespace.createElement(reactNative.Text, { style: { color: "red" } }, index * 100)
833
+ ));
834
+ });
713
835
 
714
- // src/ScrollAdjustHandler.ts
715
- var ScrollAdjustHandler = class {
716
- constructor(ctx) {
717
- this.appliedAdjust = 0;
718
- this.mounted = false;
719
- this.context = ctx;
720
- }
721
- requestAdjust(add) {
722
- const oldAdjustTop = peek$(this.context, "scrollAdjust") || 0;
723
- this.appliedAdjust = add + oldAdjustTop;
724
- const set = () => set$(this.context, "scrollAdjust", this.appliedAdjust);
725
- if (this.mounted) {
726
- set();
727
- } else {
728
- requestAnimationFrame(set);
729
- }
730
- }
731
- setMounted() {
732
- this.mounted = true;
733
- }
734
- };
735
-
736
- // src/getId.ts
836
+ // src/utils/getId.ts
737
837
  function getId(state, index) {
738
838
  const { data, keyExtractor } = state.props;
739
839
  if (!data) {
@@ -745,7 +845,7 @@ function getId(state, index) {
745
845
  return id;
746
846
  }
747
847
 
748
- // src/calculateOffsetForIndex.ts
848
+ // src/core/calculateOffsetForIndex.ts
749
849
  function calculateOffsetForIndex(ctx, state, index) {
750
850
  let position = 0;
751
851
  if (index !== void 0) {
@@ -762,21 +862,37 @@ function calculateOffsetForIndex(ctx, state, index) {
762
862
  return position;
763
863
  }
764
864
 
765
- // src/getItemSize.ts
766
- function getItemSize(state, key, index, data, useAverageSize) {
865
+ // src/utils/getItemSize.ts
866
+ function getItemSize(state, key, index, data, useAverageSize, defaultAverageSize) {
867
+ var _a, _b;
767
868
  const {
768
869
  sizesKnown,
769
870
  sizes,
770
871
  scrollingTo,
771
- props: { estimatedItemSize, getEstimatedItemSize }
872
+ averageSizes,
873
+ props: { estimatedItemSize, getEstimatedItemSize, getFixedItemSize, getItemType }
772
874
  } = state;
773
875
  const sizeKnown = sizesKnown.get(key);
774
876
  if (sizeKnown !== void 0) {
775
877
  return sizeKnown;
776
878
  }
777
879
  let size;
778
- if (IsNewArchitecture && useAverageSize !== void 0 && sizeKnown === void 0 && !getEstimatedItemSize && !scrollingTo) {
779
- size = useAverageSize;
880
+ const itemType = getItemType ? (_a = getItemType(data, index)) != null ? _a : "" : "";
881
+ if (getFixedItemSize) {
882
+ size = getFixedItemSize(index, data, itemType);
883
+ if (size !== void 0) {
884
+ sizesKnown.set(key, size);
885
+ }
886
+ }
887
+ if (size === void 0 && useAverageSize && sizeKnown === void 0 && !scrollingTo) {
888
+ if (itemType === "") {
889
+ size = defaultAverageSize;
890
+ } else {
891
+ const averageSizeForType = (_b = averageSizes[itemType]) == null ? void 0 : _b.avg;
892
+ if (averageSizeForType !== void 0) {
893
+ size = roundSize(averageSizeForType);
894
+ }
895
+ }
780
896
  }
781
897
  if (size === void 0) {
782
898
  size = sizes.get(key);
@@ -785,13 +901,13 @@ function getItemSize(state, key, index, data, useAverageSize) {
785
901
  }
786
902
  }
787
903
  if (size === void 0) {
788
- size = getEstimatedItemSize ? getEstimatedItemSize(index, data) : estimatedItemSize;
904
+ size = getEstimatedItemSize ? getEstimatedItemSize(index, data, itemType) : estimatedItemSize;
789
905
  }
790
906
  sizes.set(key, size);
791
907
  return size;
792
908
  }
793
909
 
794
- // src/calculateOffsetWithOffsetPosition.ts
910
+ // src/core/calculateOffsetWithOffsetPosition.ts
795
911
  function calculateOffsetWithOffsetPosition(state, offsetParam, params) {
796
912
  const { index, viewOffset, viewPosition } = params;
797
913
  let offset = offsetParam;
@@ -804,127 +920,50 @@ function calculateOffsetWithOffsetPosition(state, offsetParam, params) {
804
920
  return offset;
805
921
  }
806
922
 
807
- // src/checkAllSizesKnown.ts
808
- function checkAllSizesKnown(state) {
809
- const { startBuffered, endBuffered, sizesKnown } = state;
810
- if (endBuffered !== null) {
811
- let areAllKnown = true;
812
- for (let i = startBuffered; areAllKnown && i <= endBuffered; i++) {
813
- const key = getId(state, i);
814
- areAllKnown && (areAllKnown = sizesKnown.has(key));
815
- }
816
- return areAllKnown;
923
+ // src/core/getEffectiveScroll.ts
924
+ function getEffectiveScroll(ctx, state) {
925
+ const { scroll: scrollState, scrollLength } = state;
926
+ const topPad = peek$(ctx, "stylePaddingTop") + peek$(ctx, "headerSize");
927
+ const totalSize = peek$(ctx, "totalSize");
928
+ let scroll = scrollState - topPad;
929
+ if (scroll + scrollLength > totalSize) {
930
+ scroll = Math.max(0, totalSize - scrollLength);
817
931
  }
818
- return false;
932
+ return scroll;
819
933
  }
820
934
 
821
- // src/findAvailableContainers.ts
822
- function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffered, pendingRemoval) {
823
- const numContainers = peek$(ctx, "numContainers");
824
- const result = [];
825
- const availableContainers = [];
826
- for (let u = 0; u < numContainers; u++) {
827
- const key = peek$(ctx, `containerItemKey${u}`);
828
- let isOk = key === void 0;
829
- if (!isOk) {
830
- const index = pendingRemoval.indexOf(u);
831
- if (index !== -1) {
832
- pendingRemoval.splice(index, 1);
833
- isOk = true;
834
- }
835
- }
836
- if (isOk) {
837
- result.push(u);
838
- if (result.length >= numNeeded) {
839
- return result;
840
- }
841
- }
842
- }
843
- for (let u = 0; u < numContainers; u++) {
844
- const key = peek$(ctx, `containerItemKey${u}`);
845
- if (key === void 0) continue;
846
- const index = state.indexByKey.get(key);
847
- if (index < startBuffered) {
848
- availableContainers.push({ index: u, distance: startBuffered - index });
849
- } else if (index > endBuffered) {
850
- availableContainers.push({ index: u, distance: index - endBuffered });
851
- }
852
- }
853
- const remaining = numNeeded - result.length;
854
- if (remaining > 0) {
855
- if (availableContainers.length > 0) {
856
- if (availableContainers.length > remaining) {
857
- availableContainers.sort(comparatorByDistance);
858
- availableContainers.length = remaining;
859
- }
860
- for (const container of availableContainers) {
861
- result.push(container.index);
862
- }
863
- }
864
- const stillNeeded = numNeeded - result.length;
865
- if (stillNeeded > 0) {
866
- for (let i = 0; i < stillNeeded; i++) {
867
- result.push(numContainers + i);
868
- }
869
- if (__DEV__ && numContainers + stillNeeded > peek$(ctx, "numContainersPooled")) {
870
- console.warn(
871
- "[legend-list] No unused container available, so creating one on demand. This can be a minor performance issue and is likely caused by the estimatedItemSize being too large. Consider decreasing estimatedItemSize or increasing initialContainerPoolRatio.",
872
- {
873
- debugInfo: {
874
- numContainers,
875
- numNeeded,
876
- stillNeeded,
877
- numContainersPooled: peek$(ctx, "numContainersPooled")
878
- }
879
- }
880
- );
881
- }
882
- }
935
+ // src/core/finishScrollTo.ts
936
+ var finishScrollTo = (state) => {
937
+ if (state) {
938
+ state.scrollingTo = void 0;
939
+ state.scrollHistory.length = 0;
883
940
  }
884
- return result.sort(comparatorDefault);
885
- }
886
- function comparatorByDistance(a, b) {
887
- return b.distance - a.distance;
888
- }
941
+ };
889
942
 
890
- // src/getScrollVelocity.ts
891
- var getScrollVelocity = (state) => {
892
- const { scrollHistory } = state;
893
- let velocity = 0;
894
- if (scrollHistory.length >= 1) {
895
- const newest = scrollHistory[scrollHistory.length - 1];
896
- let oldest;
897
- let start = 0;
898
- for (let i = 0; i < scrollHistory.length - 1; i++) {
899
- const entry = scrollHistory[i];
900
- const nextEntry = scrollHistory[i + 1];
901
- if (i > 0) {
902
- const prevEntry = scrollHistory[i - 1];
903
- const prevDirection = entry.scroll - prevEntry.scroll;
904
- const currentDirection = nextEntry.scroll - entry.scroll;
905
- if (prevDirection > 0 && currentDirection < 0 || prevDirection < 0 && currentDirection > 0) {
906
- start = i;
907
- break;
908
- }
909
- }
910
- }
911
- for (let i = start; i < scrollHistory.length - 1; i++) {
912
- const entry = scrollHistory[i];
913
- if (newest.time - entry.time <= 1e3) {
914
- oldest = entry;
915
- break;
916
- }
917
- }
918
- if (oldest) {
919
- const scrollDiff = newest.scroll - oldest.scroll;
920
- const timeDiff = newest.time - oldest.time;
921
- velocity = timeDiff > 0 ? scrollDiff / timeDiff : 0;
922
- }
943
+ // src/core/scrollTo.ts
944
+ function scrollTo(state, params = {}) {
945
+ var _a;
946
+ const { animated } = params;
947
+ const {
948
+ refScroller,
949
+ props: { horizontal }
950
+ } = state;
951
+ const offset = calculateOffsetWithOffsetPosition(state, params.offset, params);
952
+ state.scrollHistory.length = 0;
953
+ state.scrollingTo = params;
954
+ state.scrollPending = offset;
955
+ (_a = refScroller.current) == null ? void 0 : _a.scrollTo({
956
+ animated: !!animated,
957
+ x: horizontal ? offset : 0,
958
+ y: horizontal ? 0 : offset
959
+ });
960
+ if (!animated) {
961
+ state.scroll = offset;
962
+ setTimeout(() => finishScrollTo(state), 100);
923
963
  }
924
- return velocity;
925
- };
964
+ }
926
965
 
927
- // src/requestAdjust.ts
966
+ // src/utils/requestAdjust.ts
928
967
  function requestAdjust(ctx, state, positionDiff) {
929
968
  if (Math.abs(positionDiff) > 0.1) {
930
969
  const doit = () => {
@@ -956,8 +995,28 @@ function requestAdjust(ctx, state, positionDiff) {
956
995
  }
957
996
  }
958
997
 
959
- // src/prepareMVCP.ts
960
- function prepareMVCP(ctx, state) {
998
+ // src/core/mvcp.ts
999
+ function getItemsInView(ctx, state) {
1000
+ const { startNoBuffer, endNoBuffer, positions, scrollLength } = state;
1001
+ const idsInViewWithPositions = [];
1002
+ const scroll = getEffectiveScroll(ctx, state);
1003
+ if (startNoBuffer !== null && endNoBuffer !== null) {
1004
+ for (let i = startNoBuffer; i <= endNoBuffer; i++) {
1005
+ const id = getId(state, i);
1006
+ if (id) {
1007
+ const position = positions.get(id);
1008
+ if (position === void 0 || position > scroll + scrollLength) {
1009
+ break;
1010
+ } else if (position >= scroll) {
1011
+ idsInViewWithPositions.push({ id, position });
1012
+ }
1013
+ }
1014
+ }
1015
+ }
1016
+ return idsInViewWithPositions;
1017
+ }
1018
+ function prepareMVCP(ctx, state, dataChanged) {
1019
+ var _a;
961
1020
  const {
962
1021
  positions,
963
1022
  scrollingTo,
@@ -965,170 +1024,62 @@ function prepareMVCP(ctx, state) {
965
1024
  } = state;
966
1025
  let prevPosition;
967
1026
  let targetId;
968
- let targetIndex;
1027
+ let idsInViewWithPositions;
969
1028
  const scrollTarget = scrollingTo == null ? void 0 : scrollingTo.index;
970
1029
  if (maintainVisibleContentPosition) {
971
1030
  const indexByKey = state.indexByKey;
972
1031
  if (scrollTarget !== void 0) {
973
1032
  targetId = getId(state, scrollTarget);
974
- targetIndex = scrollTarget;
975
- } else if (state.idsInView.length > 0 && peek$(ctx, "containersDidLayout")) {
976
- targetId = state.idsInView.find((id) => indexByKey.get(id) !== void 0);
977
- targetIndex = indexByKey.get(targetId);
1033
+ } else if (peek$(ctx, "containersDidLayout")) {
1034
+ idsInViewWithPositions = getItemsInView(ctx, state);
1035
+ if (!dataChanged) {
1036
+ targetId = (_a = idsInViewWithPositions.find(({ id }) => indexByKey.get(id) !== void 0)) == null ? void 0 : _a.id;
1037
+ }
978
1038
  }
979
- if (targetId !== void 0 && targetIndex !== void 0) {
1039
+ if (targetId !== void 0) {
980
1040
  prevPosition = positions.get(targetId);
981
1041
  }
982
1042
  }
983
1043
  return () => {
1044
+ let positionDiff;
1045
+ if (dataChanged && idsInViewWithPositions && targetId === void 0) {
1046
+ for (let i = 0; i < idsInViewWithPositions.length; i++) {
1047
+ const { id, position } = idsInViewWithPositions[i];
1048
+ const newPosition = positions.get(id);
1049
+ if (newPosition !== void 0) {
1050
+ positionDiff = newPosition - position;
1051
+ break;
1052
+ }
1053
+ }
1054
+ }
984
1055
  if (targetId !== void 0 && prevPosition !== void 0) {
985
1056
  const newPosition = positions.get(targetId);
986
1057
  if (newPosition !== void 0) {
987
- const positionDiff = newPosition - prevPosition;
988
- if (Math.abs(positionDiff) > 0.1) {
989
- requestAdjust(ctx, state, positionDiff);
990
- }
1058
+ positionDiff = newPosition - prevPosition;
991
1059
  }
992
1060
  }
993
- };
994
- }
995
-
996
- // src/checkThreshold.ts
997
- var checkThreshold = (distance, atThreshold, threshold, isReached, isBlockedByTimer, onReached, blockTimer) => {
998
- const distanceAbs = Math.abs(distance);
999
- const isAtThreshold = atThreshold || distanceAbs < threshold;
1000
- if (!isReached && !isBlockedByTimer) {
1001
- if (isAtThreshold) {
1002
- onReached == null ? void 0 : onReached(distance);
1003
- blockTimer == null ? void 0 : blockTimer(true);
1004
- setTimeout(() => {
1005
- blockTimer == null ? void 0 : blockTimer(false);
1006
- }, 700);
1007
- return true;
1008
- }
1009
- } else {
1010
- if (distance >= 1.3 * threshold) {
1011
- return false;
1012
- }
1013
- }
1014
- return isReached;
1015
- };
1016
-
1017
- // src/checkAtBottom.ts
1018
- function checkAtBottom(ctx, state) {
1019
- if (!state) {
1020
- return;
1021
- }
1022
- const {
1023
- queuedInitialLayout,
1024
- scrollLength,
1025
- scroll,
1026
- maintainingScrollAtEnd,
1027
- props: { maintainScrollAtEndThreshold, onEndReachedThreshold }
1028
- } = state;
1029
- const contentSize = getContentSize(ctx);
1030
- if (contentSize > 0 && queuedInitialLayout && !maintainingScrollAtEnd) {
1031
- const distanceFromEnd = contentSize - scroll - scrollLength;
1032
- const isContentLess = contentSize < scrollLength;
1033
- state.isAtEnd = isContentLess || distanceFromEnd < scrollLength * maintainScrollAtEndThreshold;
1034
- state.isEndReached = checkThreshold(
1035
- distanceFromEnd,
1036
- isContentLess,
1037
- onEndReachedThreshold * scrollLength,
1038
- state.isEndReached,
1039
- state.endReachedBlockedByTimer,
1040
- (distance) => {
1041
- var _a, _b;
1042
- return (_b = (_a = state.props).onEndReached) == null ? void 0 : _b.call(_a, { distanceFromEnd: distance });
1043
- },
1044
- (block) => {
1045
- state.endReachedBlockedByTimer = block;
1061
+ if (positionDiff !== void 0 && Math.abs(positionDiff) > 0.1) {
1062
+ if (reactNative.Platform.OS === "android" && !IsNewArchitecture && dataChanged && state.scroll <= positionDiff) {
1063
+ scrollTo(state, {
1064
+ offset: state.scroll + positionDiff
1065
+ });
1066
+ } else {
1067
+ requestAdjust(ctx, state, positionDiff);
1046
1068
  }
1047
- );
1048
- }
1049
- }
1050
-
1051
- // src/finishScrollTo.ts
1052
- var finishScrollTo = (state) => {
1053
- if (state) {
1054
- state.scrollingTo = void 0;
1055
- state.scrollHistory.length = 0;
1056
- }
1057
- };
1058
-
1059
- // src/scrollTo.ts
1060
- function scrollTo(state, params = {}) {
1061
- var _a;
1062
- const { animated } = params;
1063
- const {
1064
- refScroller,
1065
- props: { horizontal }
1066
- } = state;
1067
- const offset = calculateOffsetWithOffsetPosition(state, params.offset, params);
1068
- state.scrollHistory.length = 0;
1069
- state.scrollingTo = params;
1070
- state.scrollPending = offset;
1071
- (_a = refScroller.current) == null ? void 0 : _a.scrollTo({
1072
- x: horizontal ? offset : 0,
1073
- y: horizontal ? 0 : offset,
1074
- animated: !!animated
1075
- });
1076
- if (!animated) {
1077
- state.scroll = offset;
1078
- setTimeout(() => finishScrollTo(state), 100);
1079
- }
1080
- }
1081
-
1082
- // src/scrollToIndex.ts
1083
- function scrollToIndex(ctx, state, { index, viewOffset = 0, animated = true, viewPosition }) {
1084
- if (index >= state.props.data.length) {
1085
- index = state.props.data.length - 1;
1086
- } else if (index < 0) {
1087
- index = 0;
1088
- }
1089
- const firstIndexOffset = calculateOffsetForIndex(ctx, state, index);
1090
- const isLast = index === state.props.data.length - 1;
1091
- if (isLast && viewPosition === void 0) {
1092
- viewPosition = 1;
1093
- }
1094
- const firstIndexScrollPostion = firstIndexOffset - viewOffset;
1095
- state.scrollForNextCalculateItemsInView = void 0;
1096
- scrollTo(state, {
1097
- offset: firstIndexScrollPostion,
1098
- animated,
1099
- index,
1100
- viewPosition: viewPosition != null ? viewPosition : 0,
1101
- viewOffset
1102
- });
1103
- }
1104
-
1105
- // src/setDidLayout.ts
1106
- function setDidLayout(ctx, state) {
1107
- const {
1108
- loadStartTime,
1109
- initialScroll,
1110
- props: { onLoad }
1111
- } = state;
1112
- state.queuedInitialLayout = true;
1113
- checkAtBottom(ctx, state);
1114
- if (!IsNewArchitecture && initialScroll) {
1115
- scrollToIndex(ctx, state, { ...initialScroll, animated: false });
1116
- }
1117
- set$(ctx, "containersDidLayout", true);
1118
- if (onLoad) {
1119
- onLoad({ elapsedTimeInMs: Date.now() - loadStartTime });
1120
- }
1069
+ }
1070
+ };
1121
1071
  }
1122
1072
 
1123
- // src/setPaddingTop.ts
1124
- function setPaddingTop(ctx, { stylePaddingTop, alignItemsPaddingTop }) {
1073
+ // src/utils/setPaddingTop.ts
1074
+ function setPaddingTop(ctx, state, { stylePaddingTop, alignItemsPaddingTop }) {
1125
1075
  if (stylePaddingTop !== void 0) {
1126
1076
  const prevStylePaddingTop = peek$(ctx, "stylePaddingTop") || 0;
1127
1077
  if (stylePaddingTop < prevStylePaddingTop) {
1128
- const prevTotalSize = peek$(ctx, "totalSize") || 0;
1078
+ let prevTotalSize = peek$(ctx, "totalSize");
1129
1079
  set$(ctx, "totalSize", prevTotalSize + prevStylePaddingTop);
1130
- setTimeout(() => {
1131
- set$(ctx, "totalSize", prevTotalSize);
1080
+ state.timeoutSetPaddingTop = setTimeout(() => {
1081
+ prevTotalSize = peek$(ctx, "totalSize");
1082
+ set$(ctx, "totalSize", prevTotalSize - prevStylePaddingTop);
1132
1083
  }, 16);
1133
1084
  }
1134
1085
  set$(ctx, "stylePaddingTop", stylePaddingTop);
@@ -1138,7 +1089,7 @@ function setPaddingTop(ctx, { stylePaddingTop, alignItemsPaddingTop }) {
1138
1089
  }
1139
1090
  }
1140
1091
 
1141
- // src/updateAlignItemsPaddingTop.ts
1092
+ // src/utils/updateAlignItemsPaddingTop.ts
1142
1093
  function updateAlignItemsPaddingTop(ctx, state) {
1143
1094
  const {
1144
1095
  scrollLength,
@@ -1150,55 +1101,118 @@ function updateAlignItemsPaddingTop(ctx, state) {
1150
1101
  const contentSize = getContentSize(ctx);
1151
1102
  alignItemsPaddingTop = Math.max(0, Math.floor(scrollLength - contentSize));
1152
1103
  }
1153
- setPaddingTop(ctx, { alignItemsPaddingTop });
1104
+ setPaddingTop(ctx, state, { alignItemsPaddingTop });
1105
+ }
1106
+ }
1107
+
1108
+ // src/core/updateTotalSize.ts
1109
+ function updateTotalSize(ctx, state) {
1110
+ const {
1111
+ positions,
1112
+ props: { data }
1113
+ } = state;
1114
+ if (data.length === 0) {
1115
+ addTotalSize(ctx, state, null, 0);
1116
+ } else {
1117
+ const lastId = getId(state, data.length - 1);
1118
+ if (lastId !== void 0) {
1119
+ const lastPosition = positions.get(lastId);
1120
+ if (lastPosition !== void 0) {
1121
+ const lastSize = getItemSize(state, lastId, data.length - 1, data[data.length - 1]);
1122
+ if (lastSize !== void 0) {
1123
+ const totalSize = lastPosition + lastSize;
1124
+ addTotalSize(ctx, state, null, totalSize);
1125
+ }
1126
+ }
1127
+ }
1128
+ }
1129
+ }
1130
+ function addTotalSize(ctx, state, key, add) {
1131
+ const { alignItemsAtEnd } = state.props;
1132
+ {
1133
+ state.totalSize = add;
1134
+ if (state.timeoutSetPaddingTop) {
1135
+ clearTimeout(state.timeoutSetPaddingTop);
1136
+ state.timeoutSetPaddingTop = void 0;
1137
+ }
1138
+ }
1139
+ set$(ctx, "totalSize", state.totalSize);
1140
+ if (alignItemsAtEnd) {
1141
+ updateAlignItemsPaddingTop(ctx, state);
1142
+ }
1143
+ }
1144
+
1145
+ // src/utils/getScrollVelocity.ts
1146
+ var getScrollVelocity = (state) => {
1147
+ const { scrollHistory } = state;
1148
+ let velocity = 0;
1149
+ if (scrollHistory.length >= 1) {
1150
+ const newest = scrollHistory[scrollHistory.length - 1];
1151
+ let oldest;
1152
+ let start = 0;
1153
+ const now = Date.now();
1154
+ for (let i = 0; i < scrollHistory.length - 1; i++) {
1155
+ const entry = scrollHistory[i];
1156
+ const nextEntry = scrollHistory[i + 1];
1157
+ if (i > 0) {
1158
+ const prevEntry = scrollHistory[i - 1];
1159
+ const prevDirection = entry.scroll - prevEntry.scroll;
1160
+ const currentDirection = nextEntry.scroll - entry.scroll;
1161
+ if (prevDirection > 0 && currentDirection < 0 || prevDirection < 0 && currentDirection > 0) {
1162
+ start = i;
1163
+ break;
1164
+ }
1165
+ }
1166
+ }
1167
+ for (let i = start; i < scrollHistory.length - 1; i++) {
1168
+ const entry = scrollHistory[i];
1169
+ if (now - entry.time <= 1e3) {
1170
+ oldest = entry;
1171
+ break;
1172
+ }
1173
+ }
1174
+ if (oldest && oldest !== newest) {
1175
+ const scrollDiff = newest.scroll - oldest.scroll;
1176
+ const timeDiff = newest.time - oldest.time;
1177
+ velocity = timeDiff > 0 ? scrollDiff / timeDiff : 0;
1178
+ }
1154
1179
  }
1155
- }
1180
+ return velocity;
1181
+ };
1156
1182
 
1157
- // src/updateTotalSize.ts
1158
- function updateTotalSize(ctx, state) {
1183
+ // src/utils/updateSnapToOffsets.ts
1184
+ function updateSnapToOffsets(ctx, state) {
1159
1185
  const {
1160
1186
  positions,
1161
- props: { data }
1187
+ props: { snapToIndices }
1162
1188
  } = state;
1163
- if (data.length === 0) {
1164
- addTotalSize(ctx, state, null, 0);
1165
- } else {
1166
- const lastId = getId(state, data.length - 1);
1167
- if (lastId !== void 0) {
1168
- const lastPosition = positions.get(lastId);
1169
- if (lastPosition !== void 0) {
1170
- const lastSize = getItemSize(state, lastId, data.length - 1, data[data.length - 1]);
1171
- if (lastSize !== void 0) {
1172
- const totalSize = lastPosition + lastSize;
1173
- addTotalSize(ctx, state, null, totalSize);
1174
- }
1175
- }
1176
- }
1177
- }
1178
- }
1179
- function addTotalSize(ctx, state, key, add) {
1180
- const { alignItemsAtEnd } = state.props;
1181
- {
1182
- state.totalSize = add;
1183
- }
1184
- set$(ctx, "totalSize", state.totalSize);
1185
- if (alignItemsAtEnd) {
1186
- updateAlignItemsPaddingTop(ctx, state);
1189
+ const snapToOffsets = Array(snapToIndices.length);
1190
+ for (let i = 0; i < snapToIndices.length; i++) {
1191
+ const idx = snapToIndices[i];
1192
+ const key = getId(state, idx);
1193
+ snapToOffsets[i] = positions.get(key);
1187
1194
  }
1195
+ set$(ctx, "snapToOffsets", snapToOffsets);
1188
1196
  }
1189
1197
 
1190
- // src/updateAllPositions.ts
1198
+ // src/core/updateAllPositions.ts
1191
1199
  function updateAllPositions(ctx, state, dataChanged) {
1192
1200
  var _a, _b, _c, _d, _e;
1193
- const { averageSizes, columns, indexByKey, positions, firstFullyOnScreenIndex, idCache, sizesKnown } = state;
1201
+ const {
1202
+ averageSizes,
1203
+ columns,
1204
+ indexByKey,
1205
+ positions,
1206
+ firstFullyOnScreenIndex,
1207
+ idCache,
1208
+ sizesKnown,
1209
+ props: { getEstimatedItemSize, snapToIndices }
1210
+ } = state;
1194
1211
  const data = state.props.data;
1195
1212
  const numColumns = peek$(ctx, "numColumns");
1196
1213
  const indexByKeyForChecking = __DEV__ ? /* @__PURE__ */ new Map() : void 0;
1197
1214
  const scrollVelocity = getScrollVelocity(state);
1198
- if (dataChanged) {
1199
- indexByKey.clear();
1200
- idCache.clear();
1201
- }
1215
+ const useAverageSize = false;
1202
1216
  const itemType = "";
1203
1217
  let averageSize = (_a = averageSizes[itemType]) == null ? void 0 : _a.avg;
1204
1218
  if (averageSize !== void 0) {
@@ -1214,7 +1228,7 @@ function updateAllPositions(ctx, state, dataChanged) {
1214
1228
  let bailout = false;
1215
1229
  for (let i = firstFullyOnScreenIndex - 1; i >= 0; i--) {
1216
1230
  const id = (_b = idCache.get(i)) != null ? _b : getId(state, i);
1217
- const size = (_c = sizesKnown.get(id)) != null ? _c : getItemSize(state, id, i, data[i], averageSize);
1231
+ const size = (_c = sizesKnown.get(id)) != null ? _c : getItemSize(state, id, i, data[i], useAverageSize, averageSize);
1218
1232
  const itemColumn = columns.get(id);
1219
1233
  maxSizeInRow2 = Math.max(maxSizeInRow2, size);
1220
1234
  if (itemColumn === 1) {
@@ -1241,7 +1255,7 @@ function updateAllPositions(ctx, state, dataChanged) {
1241
1255
  const dataLength = data.length;
1242
1256
  for (let i = 0; i < dataLength; i++) {
1243
1257
  const id = (_d = idCache.get(i)) != null ? _d : getId(state, i);
1244
- const size = (_e = sizesKnown.get(id)) != null ? _e : getItemSize(state, id, i, data[i], averageSize);
1258
+ const size = (_e = sizesKnown.get(id)) != null ? _e : getItemSize(state, id, i, data[i], useAverageSize, averageSize);
1245
1259
  if (__DEV__ && needsIndexByKey) {
1246
1260
  if (indexByKeyForChecking.has(id)) {
1247
1261
  console.error(
@@ -1270,9 +1284,12 @@ function updateAllPositions(ctx, state, dataChanged) {
1270
1284
  }
1271
1285
  }
1272
1286
  updateTotalSize(ctx, state);
1287
+ if (snapToIndices) {
1288
+ updateSnapToOffsets(ctx, state);
1289
+ }
1273
1290
  }
1274
1291
 
1275
- // src/viewability.ts
1292
+ // src/core/viewability.ts
1276
1293
  var mapViewabilityConfigCallbackPairs = /* @__PURE__ */ new Map();
1277
1294
  function setupViewability(props) {
1278
1295
  let { viewabilityConfig, viewabilityConfigCallbackPairs, onViewableItemsChanged } = props;
@@ -1280,27 +1297,31 @@ function setupViewability(props) {
1280
1297
  viewabilityConfigCallbackPairs = [
1281
1298
  ...viewabilityConfigCallbackPairs || [],
1282
1299
  {
1300
+ onViewableItemsChanged,
1283
1301
  viewabilityConfig: viewabilityConfig || {
1284
1302
  viewAreaCoveragePercentThreshold: 0
1285
- },
1286
- onViewableItemsChanged
1303
+ }
1287
1304
  }
1288
1305
  ];
1289
1306
  }
1290
1307
  if (viewabilityConfigCallbackPairs) {
1291
1308
  for (const pair of viewabilityConfigCallbackPairs) {
1292
1309
  mapViewabilityConfigCallbackPairs.set(pair.viewabilityConfig.id, {
1293
- viewableItems: [],
1294
- start: -1,
1295
1310
  end: -1,
1311
+ previousEnd: -1,
1296
1312
  previousStart: -1,
1297
- previousEnd: -1
1313
+ start: -1,
1314
+ viewableItems: []
1298
1315
  });
1299
1316
  }
1300
1317
  }
1301
1318
  return viewabilityConfigCallbackPairs;
1302
1319
  }
1303
1320
  function updateViewableItems(state, ctx, viewabilityConfigCallbackPairs, scrollSize, start, end) {
1321
+ const {
1322
+ timeouts,
1323
+ props: { data }
1324
+ } = state;
1304
1325
  for (const viewabilityConfigCallbackPair of viewabilityConfigCallbackPairs) {
1305
1326
  const viewabilityState = mapViewabilityConfigCallbackPairs.get(
1306
1327
  viewabilityConfigCallbackPair.viewabilityConfig.id
@@ -1309,12 +1330,12 @@ function updateViewableItems(state, ctx, viewabilityConfigCallbackPairs, scrollS
1309
1330
  viewabilityState.end = end;
1310
1331
  if (viewabilityConfigCallbackPair.viewabilityConfig.minimumViewTime) {
1311
1332
  const timer = setTimeout(() => {
1312
- state.timeouts.delete(timer);
1313
- updateViewableItemsWithConfig(state.data, viewabilityConfigCallbackPair, state, ctx, scrollSize);
1333
+ timeouts.delete(timer);
1334
+ updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, state, ctx, scrollSize);
1314
1335
  }, viewabilityConfigCallbackPair.viewabilityConfig.minimumViewTime);
1315
- state.timeouts.add(timer);
1336
+ timeouts.add(timer);
1316
1337
  } else {
1317
- updateViewableItemsWithConfig(state.data, viewabilityConfigCallbackPair, state, ctx, scrollSize);
1338
+ updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, state, ctx, scrollSize);
1318
1339
  }
1319
1340
  }
1320
1341
  }
@@ -1366,11 +1387,11 @@ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, stat
1366
1387
  const containerId = findContainerId(ctx, key);
1367
1388
  if (isViewable(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, i)) {
1368
1389
  const viewToken = {
1369
- item,
1370
- key,
1390
+ containerId,
1371
1391
  index: i,
1372
1392
  isViewable: true,
1373
- containerId
1393
+ item,
1394
+ key
1374
1395
  };
1375
1396
  viewableItems.push(viewToken);
1376
1397
  if (!(previousViewableItems == null ? void 0 : previousViewableItems.find((v) => v.key === viewToken.key))) {
@@ -1380,9 +1401,9 @@ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, stat
1380
1401
  }
1381
1402
  }
1382
1403
  Object.assign(viewabilityState, {
1383
- viewableItems,
1404
+ previousEnd: end,
1384
1405
  previousStart: start,
1385
- previousEnd: end
1406
+ viewableItems
1386
1407
  });
1387
1408
  if (changed.length > 0) {
1388
1409
  viewabilityState.viewableItems = viewableItems;
@@ -1391,7 +1412,7 @@ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, stat
1391
1412
  maybeUpdateViewabilityCallback(ctx, configId, change.containerId, change);
1392
1413
  }
1393
1414
  if (onViewableItemsChanged) {
1394
- onViewableItemsChanged({ viewableItems, changed });
1415
+ onViewableItemsChanged({ changed, viewableItems });
1395
1416
  }
1396
1417
  }
1397
1418
  for (const [containerId, value] of ctx.mapViewabilityAmountValues) {
@@ -1417,16 +1438,16 @@ function computeViewability(state, ctx, viewabilityConfig, containerId, key, scr
1417
1438
  const percent = isEntirelyVisible ? 100 : viewAreaMode ? percentOfScroller : percentVisible;
1418
1439
  const isViewable2 = percent >= viewablePercentThreshold;
1419
1440
  const value = {
1441
+ containerId,
1420
1442
  index,
1421
1443
  isViewable: isViewable2,
1422
1444
  item,
1423
1445
  key,
1424
- percentVisible,
1425
1446
  percentOfScroller,
1426
- sizeVisible,
1427
- size,
1447
+ percentVisible,
1428
1448
  scrollSize,
1429
- containerId
1449
+ size,
1450
+ sizeVisible
1430
1451
  };
1431
1452
  if (JSON.stringify(value) !== JSON.stringify(ctx.mapViewabilityAmountValues.get(containerId))) {
1432
1453
  ctx.mapViewabilityAmountValues.set(containerId, value);
@@ -1458,319 +1479,611 @@ function maybeUpdateViewabilityCallback(ctx, configId, containerId, viewToken) {
1458
1479
  cb == null ? void 0 : cb(viewToken);
1459
1480
  }
1460
1481
 
1461
- // src/calculateItemsInView.ts
1462
- function calculateItemsInView(ctx, state, params = {}) {
1463
- var _a, _b, _c, _d, _e, _f, _g, _h;
1464
- const {
1465
- scrollLength,
1466
- startBufferedId: startBufferedIdOrig,
1467
- positions,
1468
- columns,
1469
- containerItemKeys,
1470
- idCache,
1471
- sizes,
1472
- indexByKey,
1473
- scrollForNextCalculateItemsInView,
1474
- enableScrollForNextCalculateItemsInView,
1475
- minIndexSizeChanged
1476
- } = state;
1477
- const data = state.props.data;
1478
- if (!data || scrollLength === 0) {
1479
- return;
1480
- }
1481
- const totalSize = peek$(ctx, "totalSize");
1482
- const topPad = peek$(ctx, "stylePaddingTop") + peek$(ctx, "headerSize");
1483
- const numColumns = peek$(ctx, "numColumns");
1484
- const previousScrollAdjust = 0;
1485
- const { dataChanged, doMVCP } = params;
1486
- const speed = getScrollVelocity(state);
1487
- if (doMVCP || dataChanged) {
1488
- const checkMVCP = doMVCP ? prepareMVCP(ctx, state) : void 0;
1489
- updateAllPositions(ctx, state, dataChanged);
1490
- checkMVCP == null ? void 0 : checkMVCP();
1491
- }
1492
- const scrollExtra = 0;
1493
- const { queuedInitialLayout } = state;
1494
- let { scroll: scrollState } = state;
1495
- const initialScroll = state.props.initialScroll;
1496
- if (!queuedInitialLayout && initialScroll) {
1497
- const updatedOffset = calculateOffsetWithOffsetPosition(
1498
- state,
1499
- calculateOffsetForIndex(ctx, state, initialScroll.index),
1500
- initialScroll
1501
- );
1502
- scrollState = updatedOffset;
1503
- }
1504
- const scrollAdjustPad = -previousScrollAdjust - topPad;
1505
- let scroll = scrollState + scrollExtra + scrollAdjustPad;
1506
- if (scroll + scrollLength > totalSize) {
1507
- scroll = totalSize - scrollLength;
1508
- }
1509
- if (ENABLE_DEBUG_VIEW) {
1510
- set$(ctx, "debugRawScroll", scrollState);
1511
- set$(ctx, "debugComputedScroll", scroll);
1512
- }
1513
- const scrollBuffer = state.props.scrollBuffer;
1514
- let scrollBufferTop = scrollBuffer;
1515
- let scrollBufferBottom = scrollBuffer;
1516
- if (speed > 0) {
1517
- scrollBufferTop = scrollBuffer * 0.5;
1518
- scrollBufferBottom = scrollBuffer * 1.5;
1519
- } else {
1520
- scrollBufferTop = scrollBuffer * 1.5;
1521
- scrollBufferBottom = scrollBuffer * 0.5;
1522
- }
1523
- const scrollTopBuffered = scroll - scrollBufferTop;
1524
- const scrollBottom = scroll + scrollLength;
1525
- const scrollBottomBuffered = scrollBottom + scrollBufferBottom;
1526
- if (scrollForNextCalculateItemsInView) {
1527
- const { top, bottom } = scrollForNextCalculateItemsInView;
1528
- if (scrollTopBuffered > top && scrollBottomBuffered < bottom) {
1529
- return;
1482
+ // src/utils/checkAllSizesKnown.ts
1483
+ function checkAllSizesKnown(state) {
1484
+ const { startBuffered, endBuffered, sizesKnown } = state;
1485
+ if (endBuffered !== null) {
1486
+ let areAllKnown = true;
1487
+ for (let i = startBuffered; areAllKnown && i <= endBuffered; i++) {
1488
+ const key = getId(state, i);
1489
+ areAllKnown && (areAllKnown = sizesKnown.has(key));
1530
1490
  }
1491
+ return areAllKnown;
1531
1492
  }
1532
- let startNoBuffer = null;
1533
- let startBuffered = null;
1534
- let startBufferedId = null;
1535
- let endNoBuffer = null;
1536
- let endBuffered = null;
1537
- let loopStart = startBufferedIdOrig ? indexByKey.get(startBufferedIdOrig) || 0 : 0;
1538
- if (minIndexSizeChanged !== void 0) {
1539
- loopStart = Math.min(minIndexSizeChanged, loopStart);
1540
- state.minIndexSizeChanged = void 0;
1541
- }
1542
- for (let i = loopStart; i >= 0; i--) {
1543
- const id = (_a = idCache.get(i)) != null ? _a : getId(state, i);
1544
- const top = positions.get(id);
1545
- const size = (_b = sizes.get(id)) != null ? _b : getItemSize(state, id, i, data[i]);
1546
- const bottom = top + size;
1547
- if (bottom > scroll - scrollBuffer) {
1548
- loopStart = i;
1549
- } else {
1550
- break;
1493
+ return false;
1494
+ }
1495
+
1496
+ // src/utils/findAvailableContainers.ts
1497
+ function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffered, pendingRemoval, requiredItemTypes, needNewContainers) {
1498
+ const numContainers = peek$(ctx, "numContainers");
1499
+ const { stickyIndicesSet } = state.props;
1500
+ const result = [];
1501
+ const availableContainers = [];
1502
+ const stickyItemIndices = (needNewContainers == null ? void 0 : needNewContainers.filter((index) => stickyIndicesSet.has(index))) || [];
1503
+ const nonStickyItemIndices = (needNewContainers == null ? void 0 : needNewContainers.filter((index) => !stickyIndicesSet.has(index))) || [];
1504
+ const canReuseContainer = (containerIndex, requiredType) => {
1505
+ if (!requiredType) return true;
1506
+ const existingType = state.containerItemTypes.get(containerIndex);
1507
+ if (!existingType) return true;
1508
+ return existingType === requiredType;
1509
+ };
1510
+ const neededTypes = requiredItemTypes ? [...requiredItemTypes] : [];
1511
+ let typeIndex = 0;
1512
+ for (let i = 0; i < stickyItemIndices.length; i++) {
1513
+ const requiredType = neededTypes[typeIndex];
1514
+ let foundContainer = false;
1515
+ for (const containerIndex of state.stickyContainerPool) {
1516
+ const key = peek$(ctx, `containerItemKey${containerIndex}`);
1517
+ const isPendingRemoval = pendingRemoval.includes(containerIndex);
1518
+ if ((key === void 0 || isPendingRemoval) && canReuseContainer(containerIndex, requiredType)) {
1519
+ result.push(containerIndex);
1520
+ if (isPendingRemoval) {
1521
+ const index = pendingRemoval.indexOf(containerIndex);
1522
+ pendingRemoval.splice(index, 1);
1523
+ }
1524
+ foundContainer = true;
1525
+ if (requiredItemTypes) typeIndex++;
1526
+ break;
1527
+ }
1528
+ }
1529
+ if (!foundContainer) {
1530
+ const newContainerIndex = numContainers + result.filter((index) => index >= numContainers).length;
1531
+ result.push(newContainerIndex);
1532
+ state.stickyContainerPool.add(newContainerIndex);
1533
+ if (requiredItemTypes) typeIndex++;
1551
1534
  }
1552
1535
  }
1553
- const loopStartMod = loopStart % numColumns;
1554
- if (loopStartMod > 0) {
1555
- loopStart -= loopStartMod;
1536
+ if (nonStickyItemIndices.length > 0) {
1537
+ for (let u = 0; u < numContainers; u++) {
1538
+ if (state.stickyContainerPool.has(u)) {
1539
+ continue;
1540
+ }
1541
+ const key = peek$(ctx, `containerItemKey${u}`);
1542
+ let isOk = key === void 0;
1543
+ if (!isOk) {
1544
+ const index = pendingRemoval.indexOf(u);
1545
+ if (index !== -1) {
1546
+ pendingRemoval.splice(index, 1);
1547
+ const requiredType = neededTypes[typeIndex];
1548
+ isOk = canReuseContainer(u, requiredType);
1549
+ }
1550
+ }
1551
+ if (isOk) {
1552
+ result.push(u);
1553
+ if (requiredItemTypes) {
1554
+ typeIndex++;
1555
+ }
1556
+ if (result.length >= numNeeded) {
1557
+ return result;
1558
+ }
1559
+ }
1560
+ }
1556
1561
  }
1557
- let foundEnd = false;
1558
- let nextTop;
1559
- let nextBottom;
1560
- const prevNumContainers = ctx.values.get("numContainers");
1561
- let maxIndexRendered = 0;
1562
- for (let i = 0; i < prevNumContainers; i++) {
1563
- const key = peek$(ctx, `containerItemKey${i}`);
1564
- if (key !== void 0) {
1565
- const index = indexByKey.get(key);
1566
- maxIndexRendered = Math.max(maxIndexRendered, index);
1562
+ for (let u = 0; u < numContainers; u++) {
1563
+ if (state.stickyContainerPool.has(u)) {
1564
+ continue;
1565
+ }
1566
+ const key = peek$(ctx, `containerItemKey${u}`);
1567
+ if (key === void 0) continue;
1568
+ const index = state.indexByKey.get(key);
1569
+ const isOutOfView = index < startBuffered || index > endBuffered;
1570
+ if (isOutOfView) {
1571
+ const distance = index < startBuffered ? startBuffered - index : index - endBuffered;
1572
+ if (!requiredItemTypes || typeIndex < neededTypes.length && canReuseContainer(u, neededTypes[typeIndex])) {
1573
+ availableContainers.push({ distance, index: u });
1574
+ }
1567
1575
  }
1568
1576
  }
1569
- let firstFullyOnScreenIndex;
1570
- const dataLength = data.length;
1571
- for (let i = Math.max(0, loopStart); i < dataLength && (!foundEnd || i <= maxIndexRendered); i++) {
1572
- const id = (_c = idCache.get(i)) != null ? _c : getId(state, i);
1573
- const size = (_d = sizes.get(id)) != null ? _d : getItemSize(state, id, i, data[i]);
1574
- const top = positions.get(id);
1575
- if (!foundEnd) {
1576
- if (startNoBuffer === null && top + size > scroll) {
1577
- startNoBuffer = i;
1578
- }
1579
- if (firstFullyOnScreenIndex === void 0 && top >= scroll - 10) {
1580
- firstFullyOnScreenIndex = i;
1581
- }
1582
- if (startBuffered === null && top + size > scrollTopBuffered) {
1583
- startBuffered = i;
1584
- startBufferedId = id;
1585
- nextTop = top;
1586
- }
1587
- if (startNoBuffer !== null) {
1588
- if (top <= scrollBottom) {
1589
- endNoBuffer = i;
1590
- }
1591
- if (top <= scrollBottomBuffered) {
1592
- endBuffered = i;
1593
- nextBottom = top + size;
1594
- } else {
1595
- foundEnd = true;
1577
+ const remaining = numNeeded - result.length;
1578
+ if (remaining > 0) {
1579
+ if (availableContainers.length > 0) {
1580
+ if (availableContainers.length > remaining) {
1581
+ availableContainers.sort(comparatorByDistance);
1582
+ availableContainers.length = remaining;
1583
+ }
1584
+ for (const container of availableContainers) {
1585
+ result.push(container.index);
1586
+ if (requiredItemTypes) {
1587
+ typeIndex++;
1596
1588
  }
1597
1589
  }
1598
1590
  }
1591
+ const stillNeeded = numNeeded - result.length;
1592
+ if (stillNeeded > 0) {
1593
+ for (let i = 0; i < stillNeeded; i++) {
1594
+ result.push(numContainers + i);
1595
+ }
1596
+ if (__DEV__ && numContainers + stillNeeded > peek$(ctx, "numContainersPooled")) {
1597
+ console.warn(
1598
+ "[legend-list] No unused container available, so creating one on demand. This can be a minor performance issue and is likely caused by the estimatedItemSize being too large. Consider decreasing estimatedItemSize or increasing initialContainerPoolRatio.",
1599
+ {
1600
+ debugInfo: {
1601
+ numContainers,
1602
+ numContainersPooled: peek$(ctx, "numContainersPooled"),
1603
+ numNeeded,
1604
+ stillNeeded
1605
+ }
1606
+ }
1607
+ );
1608
+ }
1609
+ }
1599
1610
  }
1600
- const idsInView = [];
1601
- for (let i = firstFullyOnScreenIndex; i <= endNoBuffer; i++) {
1602
- const id = (_e = idCache.get(i)) != null ? _e : getId(state, i);
1603
- idsInView.push(id);
1611
+ return result.sort(comparatorDefault);
1612
+ }
1613
+ function comparatorByDistance(a, b) {
1614
+ return b.distance - a.distance;
1615
+ }
1616
+
1617
+ // src/core/scrollToIndex.ts
1618
+ function scrollToIndex(ctx, state, { index, viewOffset = 0, animated = true, viewPosition }) {
1619
+ if (index >= state.props.data.length) {
1620
+ index = state.props.data.length - 1;
1621
+ } else if (index < 0) {
1622
+ index = 0;
1623
+ }
1624
+ const firstIndexOffset = calculateOffsetForIndex(ctx, state, index);
1625
+ const isLast = index === state.props.data.length - 1;
1626
+ if (isLast && viewPosition === void 0) {
1627
+ viewPosition = 1;
1604
1628
  }
1605
- Object.assign(state, {
1606
- startBuffered,
1607
- startBufferedId,
1608
- startNoBuffer,
1609
- endBuffered,
1610
- endNoBuffer,
1611
- idsInView,
1612
- firstFullyOnScreenIndex
1629
+ const firstIndexScrollPostion = firstIndexOffset - viewOffset;
1630
+ state.scrollForNextCalculateItemsInView = void 0;
1631
+ scrollTo(state, {
1632
+ animated,
1633
+ index,
1634
+ offset: firstIndexScrollPostion,
1635
+ viewOffset,
1636
+ viewPosition: viewPosition != null ? viewPosition : 0
1613
1637
  });
1614
- if (enableScrollForNextCalculateItemsInView && nextTop !== void 0 && nextBottom !== void 0) {
1615
- state.scrollForNextCalculateItemsInView = nextTop !== void 0 && nextBottom !== void 0 ? {
1616
- top: nextTop,
1617
- bottom: nextBottom
1618
- } : void 0;
1638
+ }
1639
+
1640
+ // src/utils/checkThreshold.ts
1641
+ var checkThreshold = (distance, atThreshold, threshold, isReached, isBlockedByTimer, onReached, blockTimer) => {
1642
+ const distanceAbs = Math.abs(distance);
1643
+ const isAtThreshold = atThreshold || distanceAbs < threshold;
1644
+ if (!isReached && !isBlockedByTimer) {
1645
+ if (isAtThreshold) {
1646
+ onReached == null ? void 0 : onReached(distance);
1647
+ blockTimer == null ? void 0 : blockTimer(true);
1648
+ setTimeout(() => {
1649
+ blockTimer == null ? void 0 : blockTimer(false);
1650
+ }, 700);
1651
+ return true;
1652
+ }
1653
+ } else {
1654
+ if (distance >= 1.3 * threshold) {
1655
+ return false;
1656
+ }
1619
1657
  }
1620
- const numContainers = peek$(ctx, "numContainers");
1621
- const pendingRemoval = [];
1622
- if (dataChanged) {
1623
- for (let i = 0; i < numContainers; i++) {
1624
- const itemKey = peek$(ctx, `containerItemKey${i}`);
1625
- if (!state.props.keyExtractor || itemKey && indexByKey.get(itemKey) === void 0) {
1626
- pendingRemoval.push(i);
1658
+ return isReached;
1659
+ };
1660
+
1661
+ // src/utils/checkAtBottom.ts
1662
+ function checkAtBottom(ctx, state) {
1663
+ if (!state) {
1664
+ return;
1665
+ }
1666
+ const {
1667
+ queuedInitialLayout,
1668
+ scrollLength,
1669
+ scroll,
1670
+ maintainingScrollAtEnd,
1671
+ props: { maintainScrollAtEndThreshold, onEndReachedThreshold }
1672
+ } = state;
1673
+ const contentSize = getContentSize(ctx);
1674
+ if (contentSize > 0 && queuedInitialLayout && !maintainingScrollAtEnd) {
1675
+ const distanceFromEnd = contentSize - scroll - scrollLength;
1676
+ const isContentLess = contentSize < scrollLength;
1677
+ state.isAtEnd = isContentLess || distanceFromEnd < scrollLength * maintainScrollAtEndThreshold;
1678
+ state.isEndReached = checkThreshold(
1679
+ distanceFromEnd,
1680
+ isContentLess,
1681
+ onEndReachedThreshold * scrollLength,
1682
+ state.isEndReached,
1683
+ state.endReachedBlockedByTimer,
1684
+ (distance) => {
1685
+ var _a, _b;
1686
+ return (_b = (_a = state.props).onEndReached) == null ? void 0 : _b.call(_a, { distanceFromEnd: distance });
1687
+ },
1688
+ (block) => {
1689
+ state.endReachedBlockedByTimer = block;
1690
+ }
1691
+ );
1692
+ }
1693
+ }
1694
+
1695
+ // src/utils/setDidLayout.ts
1696
+ function setDidLayout(ctx, state) {
1697
+ const {
1698
+ loadStartTime,
1699
+ initialScroll,
1700
+ props: { onLoad }
1701
+ } = state;
1702
+ state.queuedInitialLayout = true;
1703
+ checkAtBottom(ctx, state);
1704
+ const setIt = () => {
1705
+ set$(ctx, "containersDidLayout", true);
1706
+ if (onLoad) {
1707
+ onLoad({ elapsedTimeInMs: Date.now() - loadStartTime });
1708
+ }
1709
+ };
1710
+ if (reactNative.Platform.OS === "android" || !IsNewArchitecture) {
1711
+ if (initialScroll) {
1712
+ queueMicrotask(() => {
1713
+ scrollToIndex(ctx, state, { ...initialScroll, animated: false });
1714
+ requestAnimationFrame(() => {
1715
+ scrollToIndex(ctx, state, { ...initialScroll, animated: false });
1716
+ setIt();
1717
+ });
1718
+ });
1719
+ } else {
1720
+ queueMicrotask(setIt);
1721
+ }
1722
+ } else {
1723
+ setIt();
1724
+ }
1725
+ }
1726
+
1727
+ // src/core/calculateItemsInView.ts
1728
+ function findCurrentStickyIndex(stickyArray, scroll, state) {
1729
+ var _a;
1730
+ const idCache = state.idCache;
1731
+ const positions = state.positions;
1732
+ for (let i = stickyArray.length - 1; i >= 0; i--) {
1733
+ const stickyId = (_a = idCache.get(stickyArray[i])) != null ? _a : getId(state, stickyArray[i]);
1734
+ const stickyPos = stickyId ? positions.get(stickyId) : void 0;
1735
+ if (stickyPos !== void 0 && scroll >= stickyPos) {
1736
+ return i;
1737
+ }
1738
+ }
1739
+ return -1;
1740
+ }
1741
+ function getActiveStickyIndices(ctx, state, stickyIndices) {
1742
+ return new Set(
1743
+ Array.from(state.stickyContainerPool).map((i) => peek$(ctx, `containerItemKey${i}`)).map((key) => key ? state.indexByKey.get(key) : void 0).filter((idx) => idx !== void 0 && stickyIndices.has(idx))
1744
+ );
1745
+ }
1746
+ function handleStickyActivation(ctx, state, stickyIndices, stickyArray, scroll, needNewContainers, startBuffered, endBuffered) {
1747
+ var _a;
1748
+ const activeIndices = getActiveStickyIndices(ctx, state, stickyIndices);
1749
+ const currentStickyIdx = findCurrentStickyIndex(stickyArray, scroll, state);
1750
+ for (let offset = 0; offset <= 1; offset++) {
1751
+ const idx = currentStickyIdx - offset;
1752
+ if (idx < 0 || activeIndices.has(stickyArray[idx])) continue;
1753
+ const stickyIndex = stickyArray[idx];
1754
+ const stickyId = (_a = state.idCache.get(stickyIndex)) != null ? _a : getId(state, stickyIndex);
1755
+ if (stickyId && !state.containerItemKeys.has(stickyId) && (stickyIndex < startBuffered || stickyIndex > endBuffered)) {
1756
+ needNewContainers.push(stickyIndex);
1757
+ }
1758
+ }
1759
+ }
1760
+ function handleStickyRecycling(ctx, state, stickyArray, scroll, scrollBuffer, pendingRemoval) {
1761
+ var _a, _b, _c;
1762
+ const currentStickyIdx = findCurrentStickyIndex(stickyArray, scroll, state);
1763
+ for (const containerIndex of state.stickyContainerPool) {
1764
+ const itemKey = peek$(ctx, `containerItemKey${containerIndex}`);
1765
+ const itemIndex = itemKey ? state.indexByKey.get(itemKey) : void 0;
1766
+ if (itemIndex === void 0) continue;
1767
+ const arrayIdx = stickyArray.indexOf(itemIndex);
1768
+ if (arrayIdx === -1) continue;
1769
+ const isRecentSticky = arrayIdx >= currentStickyIdx - 1 && arrayIdx <= currentStickyIdx + 1;
1770
+ if (isRecentSticky) continue;
1771
+ const nextIndex = stickyArray[arrayIdx + 1];
1772
+ let shouldRecycle = false;
1773
+ if (nextIndex) {
1774
+ const nextId = (_a = state.idCache.get(nextIndex)) != null ? _a : getId(state, nextIndex);
1775
+ const nextPos = nextId ? state.positions.get(nextId) : void 0;
1776
+ shouldRecycle = nextPos !== void 0 && scroll > nextPos + scrollBuffer * 2;
1777
+ } else {
1778
+ const currentId = (_b = state.idCache.get(itemIndex)) != null ? _b : getId(state, itemIndex);
1779
+ if (currentId) {
1780
+ const currentPos = state.positions.get(currentId);
1781
+ const currentSize = (_c = state.sizes.get(currentId)) != null ? _c : getItemSize(state, currentId, itemIndex, state.props.data[itemIndex]);
1782
+ shouldRecycle = currentPos !== void 0 && scroll > currentPos + currentSize + scrollBuffer * 3;
1627
1783
  }
1628
1784
  }
1785
+ if (shouldRecycle) {
1786
+ pendingRemoval.push(containerIndex);
1787
+ }
1629
1788
  }
1630
- if (startBuffered !== null && endBuffered !== null) {
1631
- let numContainers2 = prevNumContainers;
1632
- const needNewContainers = [];
1633
- for (let i = startBuffered; i <= endBuffered; i++) {
1634
- const id = (_f = idCache.get(i)) != null ? _f : getId(state, i);
1635
- if (!containerItemKeys.has(id)) {
1636
- needNewContainers.push(i);
1789
+ }
1790
+ function calculateItemsInView(ctx, state, params = {}) {
1791
+ reactNative.unstable_batchedUpdates(() => {
1792
+ var _a, _b, _c, _d, _e, _f, _g;
1793
+ const {
1794
+ columns,
1795
+ containerItemKeys,
1796
+ enableScrollForNextCalculateItemsInView,
1797
+ idCache,
1798
+ indexByKey,
1799
+ minIndexSizeChanged,
1800
+ positions,
1801
+ scrollForNextCalculateItemsInView,
1802
+ scrollLength,
1803
+ sizes,
1804
+ startBufferedId: startBufferedIdOrig,
1805
+ viewabilityConfigCallbackPairs,
1806
+ props: { getItemType, initialScroll, itemsAreEqual, keyExtractor, scrollBuffer }
1807
+ } = state;
1808
+ const { data, stickyIndicesArr, stickyIndicesSet } = state.props;
1809
+ const prevNumContainers = peek$(ctx, "numContainers");
1810
+ if (!data || scrollLength === 0 || !prevNumContainers) {
1811
+ return;
1812
+ }
1813
+ const numColumns = peek$(ctx, "numColumns");
1814
+ const { dataChanged, doMVCP } = params;
1815
+ const speed = getScrollVelocity(state);
1816
+ if (doMVCP || dataChanged) {
1817
+ const checkMVCP = doMVCP ? prepareMVCP(ctx, state, dataChanged) : void 0;
1818
+ if (dataChanged) {
1819
+ indexByKey.clear();
1820
+ idCache.clear();
1821
+ positions.clear();
1637
1822
  }
1823
+ updateAllPositions(ctx, state, dataChanged);
1824
+ checkMVCP == null ? void 0 : checkMVCP();
1638
1825
  }
1639
- if (needNewContainers.length > 0) {
1640
- const availableContainers = findAvailableContainers(
1641
- ctx,
1826
+ const { queuedInitialLayout } = state;
1827
+ let { scroll: scrollState } = state;
1828
+ if (!queuedInitialLayout && initialScroll) {
1829
+ const updatedOffset = calculateOffsetWithOffsetPosition(
1642
1830
  state,
1643
- needNewContainers.length,
1644
- startBuffered,
1645
- endBuffered,
1646
- pendingRemoval
1831
+ calculateOffsetForIndex(ctx, state, initialScroll.index),
1832
+ initialScroll
1647
1833
  );
1648
- for (let idx = 0; idx < needNewContainers.length; idx++) {
1649
- const i = needNewContainers[idx];
1650
- const containerIndex = availableContainers[idx];
1651
- const id = (_g = idCache.get(i)) != null ? _g : getId(state, i);
1652
- const oldKey = peek$(ctx, `containerItemKey${containerIndex}`);
1653
- if (oldKey && oldKey !== id) {
1654
- containerItemKeys.delete(oldKey);
1834
+ scrollState = updatedOffset;
1835
+ state.scroll = scrollState;
1836
+ }
1837
+ const scroll = getEffectiveScroll(ctx, state);
1838
+ if (ENABLE_DEBUG_VIEW) {
1839
+ set$(ctx, "debugRawScroll", scrollState);
1840
+ set$(ctx, "debugComputedScroll", scroll);
1841
+ }
1842
+ let scrollBufferTop = scrollBuffer;
1843
+ let scrollBufferBottom = scrollBuffer;
1844
+ if (speed > 0) {
1845
+ scrollBufferTop = scrollBuffer * 0.5;
1846
+ scrollBufferBottom = scrollBuffer * 1.5;
1847
+ } else {
1848
+ scrollBufferTop = scrollBuffer * 1.5;
1849
+ scrollBufferBottom = scrollBuffer * 0.5;
1850
+ }
1851
+ const scrollTopBuffered = scroll - scrollBufferTop;
1852
+ const scrollBottom = scroll + scrollLength + (scroll < 0 ? -scroll : 0);
1853
+ const scrollBottomBuffered = scrollBottom + scrollBufferBottom;
1854
+ if (scrollForNextCalculateItemsInView) {
1855
+ const { top, bottom } = scrollForNextCalculateItemsInView;
1856
+ if (scrollTopBuffered > top && scrollBottomBuffered < bottom) {
1857
+ return;
1858
+ }
1859
+ }
1860
+ let startNoBuffer = null;
1861
+ let startBuffered = null;
1862
+ let startBufferedId = null;
1863
+ let endNoBuffer = null;
1864
+ let endBuffered = null;
1865
+ let loopStart = startBufferedIdOrig ? indexByKey.get(startBufferedIdOrig) || 0 : 0;
1866
+ if (minIndexSizeChanged !== void 0) {
1867
+ loopStart = Math.min(minIndexSizeChanged, loopStart);
1868
+ state.minIndexSizeChanged = void 0;
1869
+ }
1870
+ for (let i = loopStart; i >= 0; i--) {
1871
+ const id = (_a = idCache.get(i)) != null ? _a : getId(state, i);
1872
+ const top = positions.get(id);
1873
+ const size = (_b = sizes.get(id)) != null ? _b : getItemSize(state, id, i, data[i]);
1874
+ const bottom = top + size;
1875
+ if (bottom > scroll - scrollBuffer) {
1876
+ loopStart = i;
1877
+ } else {
1878
+ break;
1879
+ }
1880
+ }
1881
+ const loopStartMod = loopStart % numColumns;
1882
+ if (loopStartMod > 0) {
1883
+ loopStart -= loopStartMod;
1884
+ }
1885
+ let foundEnd = false;
1886
+ let nextTop;
1887
+ let nextBottom;
1888
+ let maxIndexRendered = 0;
1889
+ for (let i = 0; i < prevNumContainers; i++) {
1890
+ const key = peek$(ctx, `containerItemKey${i}`);
1891
+ if (key !== void 0) {
1892
+ const index = indexByKey.get(key);
1893
+ maxIndexRendered = Math.max(maxIndexRendered, index);
1894
+ }
1895
+ }
1896
+ let firstFullyOnScreenIndex;
1897
+ const dataLength = data.length;
1898
+ for (let i = Math.max(0, loopStart); i < dataLength && (!foundEnd || i <= maxIndexRendered); i++) {
1899
+ const id = (_c = idCache.get(i)) != null ? _c : getId(state, i);
1900
+ const size = (_d = sizes.get(id)) != null ? _d : getItemSize(state, id, i, data[i]);
1901
+ const top = positions.get(id);
1902
+ if (!foundEnd) {
1903
+ if (startNoBuffer === null && top + size > scroll) {
1904
+ startNoBuffer = i;
1655
1905
  }
1656
- set$(ctx, `containerItemKey${containerIndex}`, id);
1657
- set$(ctx, `containerItemData${containerIndex}`, data[i]);
1658
- containerItemKeys.add(id);
1659
- if (containerIndex >= numContainers2) {
1660
- numContainers2 = containerIndex + 1;
1906
+ if (firstFullyOnScreenIndex === void 0 && top >= scroll - 10) {
1907
+ firstFullyOnScreenIndex = i;
1908
+ }
1909
+ if (startBuffered === null && top + size > scrollTopBuffered) {
1910
+ startBuffered = i;
1911
+ startBufferedId = id;
1912
+ nextTop = top;
1913
+ }
1914
+ if (startNoBuffer !== null) {
1915
+ if (top <= scrollBottom) {
1916
+ endNoBuffer = i;
1917
+ }
1918
+ if (top <= scrollBottomBuffered) {
1919
+ endBuffered = i;
1920
+ nextBottom = top + size;
1921
+ } else {
1922
+ foundEnd = true;
1923
+ }
1661
1924
  }
1662
1925
  }
1663
- if (numContainers2 !== prevNumContainers) {
1664
- set$(ctx, "numContainers", numContainers2);
1665
- if (numContainers2 > peek$(ctx, "numContainersPooled")) {
1666
- set$(ctx, "numContainersPooled", Math.ceil(numContainers2 * 1.5));
1926
+ }
1927
+ Object.assign(state, {
1928
+ endBuffered,
1929
+ endNoBuffer,
1930
+ firstFullyOnScreenIndex,
1931
+ startBuffered,
1932
+ startBufferedId,
1933
+ startNoBuffer
1934
+ });
1935
+ if (enableScrollForNextCalculateItemsInView && nextTop !== void 0 && nextBottom !== void 0) {
1936
+ state.scrollForNextCalculateItemsInView = nextTop !== void 0 && nextBottom !== void 0 ? {
1937
+ bottom: nextBottom,
1938
+ top: nextTop
1939
+ } : void 0;
1940
+ }
1941
+ const numContainers = peek$(ctx, "numContainers");
1942
+ const pendingRemoval = [];
1943
+ if (dataChanged) {
1944
+ for (let i = 0; i < numContainers; i++) {
1945
+ const itemKey = peek$(ctx, `containerItemKey${i}`);
1946
+ if (!keyExtractor || itemKey && indexByKey.get(itemKey) === void 0) {
1947
+ pendingRemoval.push(i);
1667
1948
  }
1668
1949
  }
1669
1950
  }
1670
- }
1671
- for (let i = 0; i < numContainers; i++) {
1672
- const itemKey = peek$(ctx, `containerItemKey${i}`);
1673
- if (pendingRemoval.includes(i)) {
1674
- if (itemKey) {
1675
- containerItemKeys.delete(itemKey);
1951
+ if (startBuffered !== null && endBuffered !== null) {
1952
+ let numContainers2 = prevNumContainers;
1953
+ const needNewContainers = [];
1954
+ for (let i = startBuffered; i <= endBuffered; i++) {
1955
+ const id = (_e = idCache.get(i)) != null ? _e : getId(state, i);
1956
+ if (!containerItemKeys.has(id)) {
1957
+ needNewContainers.push(i);
1958
+ }
1676
1959
  }
1677
- set$(ctx, `containerItemKey${i}`, void 0);
1678
- set$(ctx, `containerItemData${i}`, void 0);
1679
- set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
1680
- set$(ctx, `containerColumn${i}`, -1);
1681
- } else {
1682
- const itemIndex = indexByKey.get(itemKey);
1683
- const item = data[itemIndex];
1684
- if (item !== void 0) {
1685
- const id = (_h = idCache.get(itemIndex)) != null ? _h : getId(state, itemIndex);
1686
- const position = positions.get(id);
1687
- if (position === void 0) {
1688
- set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
1689
- } else {
1690
- const pos = positions.get(id);
1691
- const column = columns.get(id) || 1;
1692
- const prevPos = peek$(ctx, `containerPosition${i}`);
1693
- const prevColumn = peek$(ctx, `containerColumn${i}`);
1694
- const prevData = peek$(ctx, `containerItemData${i}`);
1695
- if (!prevPos || pos > POSITION_OUT_OF_VIEW && pos !== prevPos) {
1696
- set$(ctx, `containerPosition${i}`, pos);
1960
+ if (stickyIndicesArr.length > 0) {
1961
+ handleStickyActivation(
1962
+ ctx,
1963
+ state,
1964
+ stickyIndicesSet,
1965
+ stickyIndicesArr,
1966
+ scroll,
1967
+ needNewContainers,
1968
+ startBuffered,
1969
+ endBuffered
1970
+ );
1971
+ }
1972
+ if (needNewContainers.length > 0) {
1973
+ const requiredItemTypes = getItemType ? needNewContainers.map((i) => {
1974
+ const itemType = getItemType(data[i], i);
1975
+ return itemType ? String(itemType) : "";
1976
+ }) : void 0;
1977
+ const availableContainers = findAvailableContainers(
1978
+ ctx,
1979
+ state,
1980
+ needNewContainers.length,
1981
+ startBuffered,
1982
+ endBuffered,
1983
+ pendingRemoval,
1984
+ requiredItemTypes,
1985
+ needNewContainers
1986
+ );
1987
+ for (let idx = 0; idx < needNewContainers.length; idx++) {
1988
+ const i = needNewContainers[idx];
1989
+ const containerIndex = availableContainers[idx];
1990
+ const id = (_f = idCache.get(i)) != null ? _f : getId(state, i);
1991
+ const oldKey = peek$(ctx, `containerItemKey${containerIndex}`);
1992
+ if (oldKey && oldKey !== id) {
1993
+ containerItemKeys.delete(oldKey);
1994
+ }
1995
+ set$(ctx, `containerItemKey${containerIndex}`, id);
1996
+ set$(ctx, `containerItemData${containerIndex}`, data[i]);
1997
+ if (requiredItemTypes) {
1998
+ state.containerItemTypes.set(containerIndex, requiredItemTypes[idx]);
1697
1999
  }
1698
- if (column >= 0 && column !== prevColumn) {
1699
- set$(ctx, `containerColumn${i}`, column);
2000
+ containerItemKeys.add(id);
2001
+ if (stickyIndicesSet.has(i)) {
2002
+ set$(ctx, `containerSticky${containerIndex}`, true);
2003
+ const topPadding = (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "headerSize") || 0);
2004
+ set$(ctx, `containerStickyOffset${containerIndex}`, new reactNative.Animated.Value(topPadding));
2005
+ state.stickyContainerPool.add(containerIndex);
2006
+ } else {
2007
+ state.stickyContainerPool.delete(containerIndex);
2008
+ }
2009
+ if (containerIndex >= numContainers2) {
2010
+ numContainers2 = containerIndex + 1;
1700
2011
  }
1701
- if (prevData !== item) {
1702
- set$(ctx, `containerItemData${i}`, data[itemIndex]);
2012
+ }
2013
+ if (numContainers2 !== prevNumContainers) {
2014
+ set$(ctx, "numContainers", numContainers2);
2015
+ if (numContainers2 > peek$(ctx, "numContainersPooled")) {
2016
+ set$(ctx, "numContainersPooled", Math.ceil(numContainers2 * 1.5));
1703
2017
  }
1704
2018
  }
1705
2019
  }
1706
2020
  }
1707
- }
1708
- if (!queuedInitialLayout && endBuffered !== null) {
1709
- if (checkAllSizesKnown(state)) {
1710
- setDidLayout(ctx, state);
2021
+ if (stickyIndicesArr.length > 0) {
2022
+ handleStickyRecycling(ctx, state, stickyIndicesArr, scroll, scrollBuffer, pendingRemoval);
1711
2023
  }
1712
- }
1713
- if (state.props.viewabilityConfigCallbackPairs) {
1714
- updateViewableItems(
1715
- state,
1716
- ctx,
1717
- state.props.viewabilityConfigCallbackPairs,
1718
- scrollLength,
1719
- startNoBuffer,
1720
- endNoBuffer
1721
- );
1722
- }
2024
+ for (let i = 0; i < numContainers; i++) {
2025
+ const itemKey = peek$(ctx, `containerItemKey${i}`);
2026
+ if (pendingRemoval.includes(i)) {
2027
+ if (itemKey) {
2028
+ containerItemKeys.delete(itemKey);
2029
+ }
2030
+ state.containerItemTypes.delete(i);
2031
+ if (state.stickyContainerPool.has(i)) {
2032
+ set$(ctx, `containerSticky${i}`, false);
2033
+ set$(ctx, `containerStickyOffset${i}`, void 0);
2034
+ state.stickyContainerPool.delete(i);
2035
+ }
2036
+ set$(ctx, `containerItemKey${i}`, void 0);
2037
+ set$(ctx, `containerItemData${i}`, void 0);
2038
+ set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
2039
+ set$(ctx, `containerColumn${i}`, -1);
2040
+ } else {
2041
+ const itemIndex = indexByKey.get(itemKey);
2042
+ const item = data[itemIndex];
2043
+ if (item !== void 0) {
2044
+ const id = (_g = idCache.get(itemIndex)) != null ? _g : getId(state, itemIndex);
2045
+ const position = positions.get(id);
2046
+ if (position === void 0) {
2047
+ set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
2048
+ } else {
2049
+ const column = columns.get(id) || 1;
2050
+ const prevPos = peek$(ctx, `containerPosition${i}`);
2051
+ const prevColumn = peek$(ctx, `containerColumn${i}`);
2052
+ const prevData = peek$(ctx, `containerItemData${i}`);
2053
+ if (position > POSITION_OUT_OF_VIEW && position !== prevPos) {
2054
+ set$(ctx, `containerPosition${i}`, position);
2055
+ }
2056
+ if (column >= 0 && column !== prevColumn) {
2057
+ set$(ctx, `containerColumn${i}`, column);
2058
+ }
2059
+ if (prevData !== item && (itemsAreEqual ? !itemsAreEqual(prevData, item, itemIndex, data) : true)) {
2060
+ set$(ctx, `containerItemData${i}`, data[itemIndex]);
2061
+ }
2062
+ }
2063
+ }
2064
+ }
2065
+ }
2066
+ if (!queuedInitialLayout && endBuffered !== null) {
2067
+ if (checkAllSizesKnown(state)) {
2068
+ setDidLayout(ctx, state);
2069
+ }
2070
+ }
2071
+ if (viewabilityConfigCallbackPairs) {
2072
+ updateViewableItems(state, ctx, viewabilityConfigCallbackPairs, scrollLength, startNoBuffer, endNoBuffer);
2073
+ }
2074
+ });
1723
2075
  }
1724
2076
 
1725
- // src/checkAtTop.ts
1726
- function checkAtTop(state) {
1727
- if (!state) {
1728
- return;
1729
- }
2077
+ // src/core/doInitialAllocateContainers.ts
2078
+ function doInitialAllocateContainers(ctx, state) {
2079
+ var _a;
1730
2080
  const {
1731
2081
  scrollLength,
1732
- scroll,
1733
- props: { onStartReachedThreshold }
2082
+ props: { getItemType }
1734
2083
  } = state;
1735
- const distanceFromTop = scroll;
1736
- state.isAtStart = distanceFromTop <= 0;
1737
- state.isStartReached = checkThreshold(
1738
- distanceFromTop,
1739
- false,
1740
- onStartReachedThreshold * scrollLength,
1741
- state.isStartReached,
1742
- state.startReachedBlockedByTimer,
1743
- (distance) => {
1744
- var _a, _b;
1745
- return (_b = (_a = state.props).onStartReached) == null ? void 0 : _b.call(_a, { distanceFromStart: distance });
1746
- },
1747
- (block) => {
1748
- state.startReachedBlockedByTimer = block;
1749
- }
1750
- );
1751
- }
1752
-
1753
- // src/createColumnWrapperStyle.ts
1754
- function createColumnWrapperStyle(contentContainerStyle) {
1755
- const { gap, columnGap, rowGap } = contentContainerStyle;
1756
- if (gap || columnGap || rowGap) {
1757
- contentContainerStyle.gap = void 0;
1758
- contentContainerStyle.columnGap = void 0;
1759
- contentContainerStyle.rowGap = void 0;
1760
- return {
1761
- gap,
1762
- columnGap,
1763
- rowGap
1764
- };
1765
- }
1766
- }
1767
-
1768
- // src/doInitialAllocateContainers.ts
1769
- function doInitialAllocateContainers(ctx, state) {
1770
- const { scrollLength } = state;
1771
2084
  const data = state.props.data;
1772
2085
  if (scrollLength > 0 && data.length > 0 && !peek$(ctx, "numContainers")) {
1773
- const averageItemSize = state.props.getEstimatedItemSize ? state.props.getEstimatedItemSize(0, data[0]) : state.props.estimatedItemSize;
2086
+ const averageItemSize = state.props.getEstimatedItemSize ? state.props.getEstimatedItemSize(0, data[0], getItemType ? (_a = getItemType(data[0], 0)) != null ? _a : "" : "") : state.props.estimatedItemSize;
1774
2087
  const Extra = 1.5;
1775
2088
  const numContainers = Math.ceil(
1776
2089
  (scrollLength + state.props.scrollBuffer * 2) / averageItemSize * state.props.numColumns * Extra
@@ -1794,7 +2107,7 @@ function doInitialAllocateContainers(ctx, state) {
1794
2107
  }
1795
2108
  }
1796
2109
 
1797
- // src/doMaintainScrollAtEnd.ts
2110
+ // src/core/doMaintainScrollAtEnd.ts
1798
2111
  function doMaintainScrollAtEnd(ctx, state, animated) {
1799
2112
  const {
1800
2113
  refScroller,
@@ -1807,45 +2120,52 @@ function doMaintainScrollAtEnd(ctx, state, animated) {
1807
2120
  }
1808
2121
  requestAnimationFrame(() => {
1809
2122
  var _a;
1810
- state.maintainingScrollAtEnd = true;
1811
- (_a = refScroller.current) == null ? void 0 : _a.scrollToEnd({
1812
- animated
1813
- });
1814
- setTimeout(
1815
- () => {
1816
- state.maintainingScrollAtEnd = false;
1817
- },
1818
- 0
1819
- );
2123
+ if (state == null ? void 0 : state.isAtEnd) {
2124
+ state.maintainingScrollAtEnd = true;
2125
+ (_a = refScroller.current) == null ? void 0 : _a.scrollToEnd({
2126
+ animated
2127
+ });
2128
+ setTimeout(
2129
+ () => {
2130
+ state.maintainingScrollAtEnd = false;
2131
+ },
2132
+ 0
2133
+ );
2134
+ }
1820
2135
  });
1821
2136
  return true;
1822
2137
  }
1823
2138
  }
1824
- function getRenderedItem(ctx, state, key) {
2139
+
2140
+ // src/utils/checkAtTop.ts
2141
+ function checkAtTop(state) {
1825
2142
  if (!state) {
1826
- return null;
2143
+ return;
1827
2144
  }
1828
2145
  const {
1829
- indexByKey,
1830
- props: { data, renderItem: renderItem2 }
2146
+ scrollLength,
2147
+ scroll,
2148
+ props: { onStartReachedThreshold }
1831
2149
  } = state;
1832
- const index = indexByKey.get(key);
1833
- if (index === void 0) {
1834
- return null;
1835
- }
1836
- let renderedItem = null;
1837
- if (renderItem2) {
1838
- const itemProps = {
1839
- item: data[index],
1840
- index,
1841
- extraData: peek$(ctx, "extraData")
1842
- };
1843
- renderedItem = React3__namespace.default.createElement(renderItem2, itemProps);
1844
- }
1845
- return { index, item: data[index], renderedItem };
2150
+ const distanceFromTop = scroll;
2151
+ state.isAtStart = distanceFromTop <= 0;
2152
+ state.isStartReached = checkThreshold(
2153
+ distanceFromTop,
2154
+ false,
2155
+ onStartReachedThreshold * scrollLength,
2156
+ state.isStartReached,
2157
+ state.startReachedBlockedByTimer,
2158
+ (distance) => {
2159
+ var _a, _b;
2160
+ return (_b = (_a = state.props).onStartReached) == null ? void 0 : _b.call(_a, { distanceFromStart: distance });
2161
+ },
2162
+ (block) => {
2163
+ state.startReachedBlockedByTimer = block;
2164
+ }
2165
+ );
1846
2166
  }
1847
2167
 
1848
- // src/handleLayout.ts
2168
+ // src/core/handleLayout.ts
1849
2169
  function handleLayout(ctx, state, layout, setCanRender) {
1850
2170
  const { maintainScrollAtEnd } = state.props;
1851
2171
  const scrollLength = layout[state.props.horizontal ? "width" : "height"];
@@ -1863,7 +2183,7 @@ function handleLayout(ctx, state, layout, setCanRender) {
1863
2183
  calculateItemsInView(ctx, state, { doMVCP: true });
1864
2184
  }
1865
2185
  if (didChange || otherAxisSize !== prevOtherAxisSize) {
1866
- set$(ctx, "scrollSize", { width: layout.width, height: layout.height });
2186
+ set$(ctx, "scrollSize", { height: layout.height, width: layout.width });
1867
2187
  }
1868
2188
  if (maintainScrollAtEnd === true || maintainScrollAtEnd.onLayout) {
1869
2189
  doMaintainScrollAtEnd(ctx, state, false);
@@ -1883,9 +2203,12 @@ function handleLayout(ctx, state, layout, setCanRender) {
1883
2203
  setCanRender(true);
1884
2204
  }
1885
2205
 
1886
- // src/onScroll.ts
2206
+ // src/core/onScroll.ts
1887
2207
  function onScroll(ctx, state, event) {
1888
2208
  var _a, _b, _c, _d, _e;
2209
+ if (!state.scrollProcessingEnabled) {
2210
+ return;
2211
+ }
1889
2212
  if (((_b = (_a = event.nativeEvent) == null ? void 0 : _a.contentSize) == null ? void 0 : _b.height) === 0 && ((_c = event.nativeEvent.contentSize) == null ? void 0 : _c.width) === 0) {
1890
2213
  return;
1891
2214
  }
@@ -1921,7 +2244,29 @@ function updateScroll(ctx, state, newScroll) {
1921
2244
  checkAtTop(state);
1922
2245
  }
1923
2246
 
1924
- // src/updateItemSize.ts
2247
+ // src/core/ScrollAdjustHandler.ts
2248
+ var ScrollAdjustHandler = class {
2249
+ constructor(ctx) {
2250
+ this.appliedAdjust = 0;
2251
+ this.mounted = false;
2252
+ this.context = ctx;
2253
+ }
2254
+ requestAdjust(add) {
2255
+ const oldAdjustTop = peek$(this.context, "scrollAdjust") || 0;
2256
+ this.appliedAdjust = add + oldAdjustTop;
2257
+ const set = () => set$(this.context, "scrollAdjust", this.appliedAdjust);
2258
+ if (this.mounted) {
2259
+ set();
2260
+ } else {
2261
+ requestAnimationFrame(set);
2262
+ }
2263
+ }
2264
+ setMounted() {
2265
+ this.mounted = true;
2266
+ }
2267
+ };
2268
+
2269
+ // src/core/updateItemSize.ts
1925
2270
  function updateItemSizes(ctx, state, itemUpdates) {
1926
2271
  var _a;
1927
2272
  const {
@@ -1935,7 +2280,8 @@ function updateItemSizes(ctx, state, itemUpdates) {
1935
2280
  }
1936
2281
  } = state;
1937
2282
  if (!data) return;
1938
- let needsRecalculate = false;
2283
+ const containersDidLayout = peek$(ctx, "containersDidLayout");
2284
+ let needsRecalculate = !containersDidLayout;
1939
2285
  let shouldMaintainScrollAtEnd = false;
1940
2286
  let minIndexSizeChanged;
1941
2287
  let maxOtherAxisSize = peek$(ctx, "otherAxisSize") || 0;
@@ -1946,7 +2292,7 @@ function updateItemSizes(ctx, state, itemUpdates) {
1946
2292
  const size = Math.floor((horizontal ? sizeObj.width : sizeObj.height) * 8) / 8;
1947
2293
  if (diff !== 0) {
1948
2294
  minIndexSizeChanged = minIndexSizeChanged !== void 0 ? Math.min(minIndexSizeChanged, index) : index;
1949
- if (((_a = state.scrollingTo) == null ? void 0 : _a.viewPosition) && maintainVisibleContentPosition && index === state.scrollingTo.index) {
2295
+ if (((_a = state.scrollingTo) == null ? void 0 : _a.viewPosition) && maintainVisibleContentPosition && index === state.scrollingTo.index && diff > 0) {
1950
2296
  requestAdjust(ctx, state, diff * state.scrollingTo.viewPosition);
1951
2297
  }
1952
2298
  const { startBuffered, endBuffered } = state;
@@ -1968,11 +2314,11 @@ function updateItemSizes(ctx, state, itemUpdates) {
1968
2314
  shouldMaintainScrollAtEnd = true;
1969
2315
  }
1970
2316
  onItemSizeChanged == null ? void 0 : onItemSizeChanged({
1971
- size,
1972
- previous: size - diff,
1973
2317
  index,
2318
+ itemData: state.props.data[index],
1974
2319
  itemKey,
1975
- itemData: state.props.data[index]
2320
+ previous: size - diff,
2321
+ size
1976
2322
  });
1977
2323
  }
1978
2324
  }
@@ -1995,7 +2341,6 @@ function updateItemSizes(ctx, state, itemUpdates) {
1995
2341
  if (!cur || maxOtherAxisSize > cur) {
1996
2342
  set$(ctx, "otherAxisSize", maxOtherAxisSize);
1997
2343
  }
1998
- const containersDidLayout = peek$(ctx, "containersDidLayout");
1999
2344
  if (containersDidLayout || checkAllSizesKnown(state)) {
2000
2345
  if (needsRecalculate) {
2001
2346
  state.scrollForNextCalculateItemsInView = void 0;
@@ -2009,77 +2354,182 @@ function updateItemSizes(ctx, state, itemUpdates) {
2009
2354
  }
2010
2355
  }
2011
2356
  function updateItemSize(ctx, state, itemKey, sizeObj) {
2012
- if (IsNewArchitecture) {
2013
- const { sizesKnown } = state;
2014
- const numContainers = ctx.values.get("numContainers");
2015
- const changes = [];
2016
- for (let i = 0; i < numContainers; i++) {
2017
- const containerItemKey = peek$(ctx, `containerItemKey${i}`);
2018
- if (itemKey === containerItemKey) {
2019
- changes.push({ itemKey, sizeObj });
2020
- } else if (!sizesKnown.has(containerItemKey) && containerItemKey !== void 0) {
2021
- const containerRef = ctx.viewRefs.get(i);
2022
- if (containerRef == null ? void 0 : containerRef.current) {
2023
- let measured;
2024
- containerRef.current.measure((x, y, width, height) => {
2025
- measured = { x, y, width, height };
2026
- });
2027
- if (measured) {
2028
- changes.push({ itemKey: containerItemKey, sizeObj: measured });
2029
- }
2030
- }
2031
- }
2357
+ var _a;
2358
+ const {
2359
+ queuedItemSizeUpdates,
2360
+ queuedItemSizeUpdatesWaiting,
2361
+ sizesKnown,
2362
+ props: { getFixedItemSize, getItemType }
2363
+ } = state;
2364
+ if (getFixedItemSize) {
2365
+ const index = state.indexByKey.get(itemKey);
2366
+ if (index === void 0) {
2367
+ return;
2368
+ }
2369
+ const itemData = state.props.data[index];
2370
+ if (itemData === void 0) {
2371
+ return;
2032
2372
  }
2033
- if (changes.length > 0) {
2034
- updateItemSizes(ctx, state, changes);
2373
+ const type = getItemType ? (_a = getItemType(itemData, index)) != null ? _a : "" : "";
2374
+ const size = getFixedItemSize(index, itemData, type);
2375
+ if (size !== void 0 && size === sizesKnown.get(itemKey)) {
2376
+ return;
2035
2377
  }
2036
- } else {
2378
+ }
2379
+ const containersDidLayout = peek$(ctx, "containersDidLayout");
2380
+ const speed = getScrollVelocity(state);
2381
+ if (!containersDidLayout || !queuedItemSizeUpdatesWaiting || Math.abs(speed) < 1) {
2037
2382
  updateItemSizes(ctx, state, [{ itemKey, sizeObj }]);
2383
+ if (containersDidLayout) {
2384
+ state.queuedItemSizeUpdatesWaiting = true;
2385
+ requestAnimationFrame(() => {
2386
+ state.queuedItemSizeUpdatesWaiting = false;
2387
+ updateItemSizes(ctx, state, queuedItemSizeUpdates);
2388
+ queuedItemSizeUpdates.length = 0;
2389
+ });
2390
+ }
2391
+ } else {
2392
+ queuedItemSizeUpdates.push({ itemKey, sizeObj });
2038
2393
  }
2039
2394
  }
2040
2395
  function updateOneItemSize(state, itemKey, sizeObj) {
2396
+ var _a;
2041
2397
  const {
2042
2398
  sizes,
2043
2399
  indexByKey,
2044
2400
  sizesKnown,
2045
2401
  averageSizes,
2046
- props: { data, horizontal }
2402
+ props: { data, horizontal, getEstimatedItemSize, getItemType, getFixedItemSize }
2047
2403
  } = state;
2048
2404
  if (!data) return 0;
2049
2405
  const index = indexByKey.get(itemKey);
2050
2406
  const prevSize = getItemSize(state, itemKey, index, data);
2051
2407
  const size = Math.floor((horizontal ? sizeObj.width : sizeObj.height) * 8) / 8;
2052
2408
  sizesKnown.set(itemKey, size);
2053
- const itemType = "";
2054
- let averages = averageSizes[itemType];
2055
- if (!averages) {
2056
- averages = averageSizes[itemType] = { num: 0, avg: 0 };
2409
+ if (!getEstimatedItemSize && !getFixedItemSize) {
2410
+ const itemType = getItemType ? (_a = getItemType(data[index], index)) != null ? _a : "" : "";
2411
+ let averages = averageSizes[itemType];
2412
+ if (!averages) {
2413
+ averages = averageSizes[itemType] = { avg: 0, num: 0 };
2414
+ }
2415
+ averages.avg = (averages.avg * averages.num + size) / (averages.num + 1);
2416
+ averages.num++;
2057
2417
  }
2058
- averages.avg = (averages.avg * averages.num + size) / (averages.num + 1);
2059
- averages.num++;
2060
2418
  if (!prevSize || Math.abs(prevSize - size) > 0.1) {
2061
2419
  sizes.set(itemKey, size);
2062
2420
  return size - prevSize;
2063
2421
  }
2064
- return 0;
2065
- }
2066
- var useCombinedRef = (...refs) => {
2067
- const callback = React3.useCallback((element) => {
2068
- for (const ref of refs) {
2069
- if (!ref) {
2070
- continue;
2071
- }
2072
- if (isFunction(ref)) {
2073
- ref(element);
2074
- } else {
2075
- ref.current = element;
2422
+ return 0;
2423
+ }
2424
+ var useCombinedRef = (...refs) => {
2425
+ const callback = React3.useCallback((element) => {
2426
+ for (const ref of refs) {
2427
+ if (!ref) {
2428
+ continue;
2429
+ }
2430
+ if (isFunction(ref)) {
2431
+ ref(element);
2432
+ } else {
2433
+ ref.current = element;
2434
+ }
2435
+ }
2436
+ }, refs);
2437
+ return callback;
2438
+ };
2439
+
2440
+ // src/utils/createColumnWrapperStyle.ts
2441
+ function createColumnWrapperStyle(contentContainerStyle) {
2442
+ const { gap, columnGap, rowGap } = contentContainerStyle;
2443
+ if (gap || columnGap || rowGap) {
2444
+ contentContainerStyle.gap = void 0;
2445
+ contentContainerStyle.columnGap = void 0;
2446
+ contentContainerStyle.rowGap = void 0;
2447
+ return {
2448
+ columnGap,
2449
+ gap,
2450
+ rowGap
2451
+ };
2452
+ }
2453
+ }
2454
+ function getRenderedItem(ctx, state, key) {
2455
+ var _a;
2456
+ if (!state) {
2457
+ return null;
2458
+ }
2459
+ const {
2460
+ indexByKey,
2461
+ props: { data, getItemType, renderItem: renderItem2 }
2462
+ } = state;
2463
+ const index = indexByKey.get(key);
2464
+ if (index === void 0) {
2465
+ return null;
2466
+ }
2467
+ let renderedItem = null;
2468
+ if (renderItem2 && data[index]) {
2469
+ const itemProps = {
2470
+ extraData: peek$(ctx, "extraData"),
2471
+ index,
2472
+ item: data[index],
2473
+ type: getItemType ? (_a = getItemType(data[index], index)) != null ? _a : "" : ""
2474
+ };
2475
+ renderedItem = isFunction(renderItem2) ? renderItem2(itemProps) : React3__namespace.default.createElement(renderItem2, itemProps);
2476
+ }
2477
+ return { index, item: data[index], renderedItem };
2478
+ }
2479
+
2480
+ // src/utils/updateAveragesOnDataChange.ts
2481
+ function updateAveragesOnDataChange(state, oldData, newData) {
2482
+ var _a;
2483
+ const {
2484
+ averageSizes,
2485
+ sizesKnown,
2486
+ indexByKey,
2487
+ props: { itemsAreEqual, getItemType, keyExtractor }
2488
+ } = state;
2489
+ if (!itemsAreEqual || !oldData.length || !newData.length) {
2490
+ for (const key in averageSizes) {
2491
+ delete averageSizes[key];
2492
+ }
2493
+ return;
2494
+ }
2495
+ const itemTypesToPreserve = {};
2496
+ const newDataLength = newData.length;
2497
+ const oldDataLength = oldData.length;
2498
+ for (let newIndex = 0; newIndex < newDataLength; newIndex++) {
2499
+ const newItem = newData[newIndex];
2500
+ const id = keyExtractor ? keyExtractor(newItem, newIndex) : String(newIndex);
2501
+ const oldIndex = indexByKey.get(id);
2502
+ if (oldIndex !== void 0 && oldIndex < oldDataLength) {
2503
+ const knownSize = sizesKnown.get(id);
2504
+ if (knownSize === void 0) continue;
2505
+ const oldItem = oldData[oldIndex];
2506
+ const areEqual = itemsAreEqual(oldItem, newItem, newIndex, newData);
2507
+ if (areEqual) {
2508
+ const itemType = getItemType ? (_a = getItemType(newItem, newIndex)) != null ? _a : "" : "";
2509
+ let typeData = itemTypesToPreserve[itemType];
2510
+ if (!typeData) {
2511
+ typeData = itemTypesToPreserve[itemType] = { count: 0, totalSize: 0 };
2512
+ }
2513
+ typeData.totalSize += knownSize;
2514
+ typeData.count++;
2076
2515
  }
2077
2516
  }
2078
- }, refs);
2079
- return callback;
2080
- };
2517
+ }
2518
+ for (const key in averageSizes) {
2519
+ delete averageSizes[key];
2520
+ }
2521
+ for (const itemType in itemTypesToPreserve) {
2522
+ const { totalSize, count } = itemTypesToPreserve[itemType];
2523
+ if (count > 0) {
2524
+ averageSizes[itemType] = {
2525
+ avg: totalSize / count,
2526
+ num: count
2527
+ };
2528
+ }
2529
+ }
2530
+ }
2081
2531
 
2082
- // src/LegendList.tsx
2532
+ // src/components/LegendList.tsx
2083
2533
  var DEFAULT_DRAW_DISTANCE = 250;
2084
2534
  var DEFAULT_ITEM_SIZE = 100;
2085
2535
  var LegendList = typedForwardRef(function LegendList2(props, forwardedRef) {
@@ -2088,48 +2538,53 @@ var LegendList = typedForwardRef(function LegendList2(props, forwardedRef) {
2088
2538
  var LegendListInner = typedForwardRef(function LegendListInner2(props, forwardedRef) {
2089
2539
  var _a;
2090
2540
  const {
2541
+ alignItemsAtEnd = false,
2542
+ columnWrapperStyle,
2543
+ contentContainerStyle: contentContainerStyleProp,
2091
2544
  data: dataProp = [],
2545
+ drawDistance = 250,
2546
+ estimatedItemSize: estimatedItemSizeProp,
2547
+ estimatedListSize,
2548
+ extraData,
2549
+ getEstimatedItemSize,
2550
+ getFixedItemSize,
2551
+ getItemType,
2552
+ horizontal,
2553
+ initialContainerPoolRatio = 2,
2092
2554
  initialScrollIndex: initialScrollIndexProp,
2093
2555
  initialScrollOffset,
2094
- horizontal,
2095
- drawDistance = 250,
2096
- recycleItems = false,
2097
- onEndReachedThreshold = 0.5,
2098
- onStartReachedThreshold = 0.5,
2556
+ itemsAreEqual,
2557
+ keyExtractor: keyExtractorProp,
2558
+ ListEmptyComponent,
2559
+ ListHeaderComponent,
2099
2560
  maintainScrollAtEnd = false,
2100
2561
  maintainScrollAtEndThreshold = 0.1,
2101
- alignItemsAtEnd = false,
2102
2562
  maintainVisibleContentPosition = false,
2103
- onScroll: onScrollProp,
2104
- onMomentumScrollEnd,
2105
2563
  numColumns: numColumnsProp = 1,
2106
- columnWrapperStyle,
2107
- keyExtractor: keyExtractorProp,
2108
- renderItem: renderItem2,
2109
- estimatedListSize,
2110
- estimatedItemSize: estimatedItemSizeProp,
2111
- getEstimatedItemSize,
2112
- suggestEstimatedItemSize,
2113
- ListHeaderComponent,
2114
- ListEmptyComponent,
2564
+ onEndReached,
2565
+ onEndReachedThreshold = 0.5,
2115
2566
  onItemSizeChanged,
2116
- refScrollView,
2117
- waitForInitialLayout = true,
2118
- extraData,
2119
- contentContainerStyle: contentContainerStyleProp,
2120
- style: styleProp,
2121
2567
  onLayout: onLayoutProp,
2568
+ onLoad,
2569
+ onMomentumScrollEnd,
2122
2570
  onRefresh,
2123
- refreshing,
2571
+ onScroll: onScrollProp,
2572
+ onStartReached,
2573
+ onStartReachedThreshold = 0.5,
2574
+ onViewableItemsChanged,
2124
2575
  progressViewOffset,
2576
+ recycleItems = false,
2125
2577
  refreshControl,
2126
- initialContainerPoolRatio = 2,
2578
+ refreshing,
2579
+ refScrollView,
2580
+ renderItem: renderItem2,
2581
+ snapToIndices,
2582
+ stickyIndices,
2583
+ style: styleProp,
2584
+ suggestEstimatedItemSize,
2127
2585
  viewabilityConfig,
2128
2586
  viewabilityConfigCallbackPairs,
2129
- onViewableItemsChanged,
2130
- onStartReached,
2131
- onEndReached,
2132
- onLoad,
2587
+ waitForInitialLayout = true,
2133
2588
  ...rest
2134
2589
  } = props;
2135
2590
  const [renderNum, setRenderNum] = React3.useState(0);
@@ -2146,55 +2601,60 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2146
2601
  const combinedRef = useCombinedRef(refScroller, refScrollView);
2147
2602
  const estimatedItemSize = estimatedItemSizeProp != null ? estimatedItemSizeProp : DEFAULT_ITEM_SIZE;
2148
2603
  const scrollBuffer = (drawDistance != null ? drawDistance : DEFAULT_DRAW_DISTANCE) || 1;
2149
- const keyExtractor = keyExtractorProp != null ? keyExtractorProp : (item, index) => index.toString();
2604
+ const keyExtractor = keyExtractorProp != null ? keyExtractorProp : (_item, index) => index.toString();
2150
2605
  const refState = React3.useRef();
2151
2606
  if (!refState.current) {
2152
- const initialScrollLength = (estimatedListSize != null ? estimatedListSize : IsNewArchitecture ? { width: 0, height: 0 } : reactNative.Dimensions.get("window"))[horizontal ? "width" : "height"];
2607
+ const initialScrollLength = (estimatedListSize != null ? estimatedListSize : IsNewArchitecture ? { height: 0, width: 0 } : reactNative.Dimensions.get("window"))[horizontal ? "width" : "height"];
2153
2608
  refState.current = {
2154
- sizes: /* @__PURE__ */ new Map(),
2155
- positions: /* @__PURE__ */ new Map(),
2609
+ activeStickyIndex: void 0,
2610
+ averageSizes: {},
2156
2611
  columns: /* @__PURE__ */ new Map(),
2157
- pendingAdjust: 0,
2158
- isStartReached: false,
2159
- isEndReached: false,
2160
- isAtEnd: false,
2161
- isAtStart: false,
2162
- scrollLength: initialScrollLength,
2163
- startBuffered: -1,
2164
- startNoBuffer: -1,
2612
+ containerItemKeys: /* @__PURE__ */ new Set(),
2613
+ containerItemTypes: /* @__PURE__ */ new Map(),
2614
+ enableScrollForNextCalculateItemsInView: true,
2165
2615
  endBuffered: -1,
2166
2616
  endNoBuffer: -1,
2617
+ endReachedBlockedByTimer: false,
2167
2618
  firstFullyOnScreenIndex: -1,
2619
+ idCache: /* @__PURE__ */ new Map(),
2620
+ indexByKey: /* @__PURE__ */ new Map(),
2621
+ initialScroll,
2622
+ isAtEnd: false,
2623
+ isAtStart: false,
2624
+ isEndReached: false,
2625
+ isStartReached: false,
2626
+ lastBatchingAction: Date.now(),
2627
+ lastLayout: void 0,
2628
+ loadStartTime: Date.now(),
2629
+ minIndexSizeChanged: 0,
2630
+ nativeMarginTop: 0,
2631
+ pendingAdjust: 0,
2632
+ positions: /* @__PURE__ */ new Map(),
2633
+ props: {},
2634
+ queuedCalculateItemsInView: 0,
2635
+ queuedItemSizeUpdates: [],
2636
+ refScroller: void 0,
2168
2637
  scroll: 0,
2169
- totalSize: 0,
2170
- timeouts: /* @__PURE__ */ new Set(),
2171
- viewabilityConfigCallbackPairs: void 0,
2172
2638
  scrollAdjustHandler: new ScrollAdjustHandler(ctx),
2173
- nativeMarginTop: 0,
2639
+ scrollForNextCalculateItemsInView: void 0,
2640
+ scrollHistory: [],
2641
+ scrollLength: initialScrollLength,
2642
+ scrollPending: 0,
2174
2643
  scrollPrev: 0,
2175
2644
  scrollPrevTime: 0,
2645
+ scrollProcessingEnabled: true,
2176
2646
  scrollTime: 0,
2177
- scrollPending: 0,
2178
- indexByKey: /* @__PURE__ */ new Map(),
2179
- scrollHistory: [],
2647
+ sizes: /* @__PURE__ */ new Map(),
2180
2648
  sizesKnown: /* @__PURE__ */ new Map(),
2181
- timeoutSizeMessage: 0,
2649
+ startBuffered: -1,
2650
+ startNoBuffer: -1,
2182
2651
  startReachedBlockedByTimer: false,
2183
- endReachedBlockedByTimer: false,
2184
- scrollForNextCalculateItemsInView: void 0,
2185
- enableScrollForNextCalculateItemsInView: true,
2186
- minIndexSizeChanged: 0,
2187
- queuedCalculateItemsInView: 0,
2188
- lastBatchingAction: Date.now(),
2189
- averageSizes: {},
2190
- idsInView: [],
2191
- containerItemKeys: /* @__PURE__ */ new Set(),
2192
- idCache: /* @__PURE__ */ new Map(),
2193
- props: {},
2194
- refScroller: void 0,
2195
- loadStartTime: Date.now(),
2196
- initialScroll,
2197
- lastLayout: void 0
2652
+ stickyContainerPool: /* @__PURE__ */ new Set(),
2653
+ stickyContainers: /* @__PURE__ */ new Map(),
2654
+ timeoutSizeMessage: 0,
2655
+ timeouts: /* @__PURE__ */ new Set(),
2656
+ totalSize: 0,
2657
+ viewabilityConfigCallbackPairs: void 0
2198
2658
  };
2199
2659
  set$(ctx, "maintainVisibleContentPosition", maintainVisibleContentPosition);
2200
2660
  set$(ctx, "extraData", extraData);
@@ -2206,33 +2666,42 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2206
2666
  alignItemsAtEnd,
2207
2667
  data: dataProp,
2208
2668
  estimatedItemSize,
2669
+ getEstimatedItemSize,
2670
+ getFixedItemSize,
2671
+ getItemType,
2672
+ horizontal: !!horizontal,
2673
+ initialContainerPoolRatio,
2674
+ initialScroll,
2675
+ itemsAreEqual,
2676
+ keyExtractor,
2209
2677
  maintainScrollAtEnd,
2210
2678
  maintainScrollAtEndThreshold,
2211
- onEndReachedThreshold,
2212
- onStartReachedThreshold,
2213
- stylePaddingBottom: stylePaddingBottomState,
2214
- horizontal: !!horizontal,
2215
2679
  maintainVisibleContentPosition,
2680
+ numColumns: numColumnsProp,
2681
+ onEndReached,
2682
+ onEndReachedThreshold,
2216
2683
  onItemSizeChanged,
2217
- suggestEstimatedItemSize: !!suggestEstimatedItemSize,
2218
- keyExtractor,
2684
+ onLoad,
2219
2685
  onScroll: onScrollProp,
2220
- getEstimatedItemSize,
2221
2686
  onStartReached,
2222
- onEndReached,
2223
- onLoad,
2687
+ onStartReachedThreshold,
2688
+ recycleItems: !!recycleItems,
2224
2689
  renderItem: renderItem2,
2225
- initialScroll,
2226
2690
  scrollBuffer,
2227
- viewabilityConfigCallbackPairs: void 0,
2228
- numColumns: numColumnsProp,
2229
- initialContainerPoolRatio,
2230
- stylePaddingTop: stylePaddingTopState
2691
+ snapToIndices,
2692
+ stickyIndicesArr: stickyIndices != null ? stickyIndices : [],
2693
+ stickyIndicesSet: React3.useMemo(() => new Set(stickyIndices), [stickyIndices]),
2694
+ stylePaddingBottom: stylePaddingBottomState,
2695
+ stylePaddingTop: stylePaddingTopState,
2696
+ suggestEstimatedItemSize: !!suggestEstimatedItemSize
2231
2697
  };
2232
2698
  state.refScroller = refScroller;
2233
2699
  const checkResetContainers = (isFirst2) => {
2234
2700
  const state2 = refState.current;
2235
2701
  if (state2) {
2702
+ if (!isFirst2 && state2.props.data !== dataProp) {
2703
+ updateAveragesOnDataChange(state2, state2.props.data, dataProp);
2704
+ }
2236
2705
  state2.props.data = dataProp;
2237
2706
  if (!isFirst2) {
2238
2707
  calculateItemsInView(ctx, state2, { dataChanged: true, doMVCP: true });
@@ -2255,27 +2724,29 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2255
2724
  (_, i) => getId(state, dataProp.length - 1 - i)
2256
2725
  );
2257
2726
  }, [dataProp, numColumnsProp]);
2258
- const initalizeStateVars = () => {
2727
+ const initializeStateVars = () => {
2259
2728
  set$(ctx, "lastItemKeys", memoizedLastItemKeys);
2260
2729
  set$(ctx, "numColumns", numColumnsProp);
2261
2730
  const prevPaddingTop = peek$(ctx, "stylePaddingTop");
2262
- setPaddingTop(ctx, { stylePaddingTop: stylePaddingTopState });
2731
+ setPaddingTop(ctx, state, { stylePaddingTop: stylePaddingTopState });
2263
2732
  refState.current.props.stylePaddingBottom = stylePaddingBottomState;
2264
- const paddingDiff = stylePaddingTopState - prevPaddingTop;
2265
- if (paddingDiff && prevPaddingTop !== void 0 && reactNative.Platform.OS === "ios") {
2266
- calculateItemsInView(ctx, state, { doMVCP: true });
2733
+ let paddingDiff = stylePaddingTopState - prevPaddingTop;
2734
+ if (maintainVisibleContentPosition && paddingDiff && prevPaddingTop !== void 0 && reactNative.Platform.OS === "ios") {
2735
+ if (state.scroll < 0) {
2736
+ paddingDiff += state.scroll;
2737
+ }
2267
2738
  requestAdjust(ctx, state, paddingDiff);
2268
2739
  }
2269
2740
  };
2270
2741
  if (isFirst) {
2271
- initalizeStateVars();
2742
+ initializeStateVars();
2272
2743
  updateAllPositions(ctx, state);
2273
2744
  }
2274
2745
  const initialContentOffset = React3.useMemo(() => {
2275
2746
  const initialContentOffset2 = initialScrollOffset || calculateOffsetForIndex(ctx, state, initialScrollIndex);
2276
2747
  refState.current.isStartReached = initialContentOffset2 < refState.current.scrollLength * onStartReachedThreshold;
2277
2748
  if (initialContentOffset2 > 0) {
2278
- scrollTo(state, { offset: initialContentOffset2, animated: false, index: initialScrollIndex });
2749
+ scrollTo(state, { animated: false, index: initialScrollIndex, offset: initialContentOffset2 });
2279
2750
  }
2280
2751
  return initialContentOffset2;
2281
2752
  }, [renderNum]);
@@ -2290,23 +2761,6 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2290
2761
  refState.current.positions.clear();
2291
2762
  }
2292
2763
  }
2293
- React3.useLayoutEffect(() => {
2294
- if (IsNewArchitecture) {
2295
- let measured;
2296
- refScroller.current.measure((x, y, width, height) => {
2297
- measured = { x, y, width, height };
2298
- });
2299
- if (measured) {
2300
- const size = Math.floor(measured[horizontal ? "width" : "height"] * 8) / 8;
2301
- if (size) {
2302
- handleLayout(ctx, state, measured, setCanRender);
2303
- }
2304
- }
2305
- }
2306
- if (!isFirst) {
2307
- calculateItemsInView(ctx, state, { doMVCP: true });
2308
- }
2309
- }, [dataProp]);
2310
2764
  const onLayoutHeader = React3.useCallback((rect, fromLayoutEffect) => {
2311
2765
  const size = rect[horizontal ? "width" : "height"];
2312
2766
  set$(ctx, "headerSize", size);
@@ -2322,6 +2776,11 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2322
2776
  }
2323
2777
  }
2324
2778
  }, []);
2779
+ React3.useLayoutEffect(() => {
2780
+ if (snapToIndices) {
2781
+ updateSnapToOffsets(ctx, state);
2782
+ }
2783
+ }, [snapToIndices]);
2325
2784
  React3.useLayoutEffect(() => {
2326
2785
  const didAllocateContainers = doInitialAllocateContainersCallback();
2327
2786
  if (!didAllocateContainers) {
@@ -2334,7 +2793,21 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2334
2793
  React3.useLayoutEffect(() => {
2335
2794
  set$(ctx, "extraData", extraData);
2336
2795
  }, [extraData]);
2337
- React3.useLayoutEffect(initalizeStateVars, [
2796
+ React3.useLayoutEffect(() => {
2797
+ if (IsNewArchitecture) {
2798
+ let measured;
2799
+ refScroller.current.measure((x, y, width, height) => {
2800
+ measured = { height, width, x, y };
2801
+ });
2802
+ if (measured) {
2803
+ const size = Math.floor(measured[horizontal ? "width" : "height"] * 8) / 8;
2804
+ if (size) {
2805
+ handleLayout(ctx, state, measured, setCanRender);
2806
+ }
2807
+ }
2808
+ }
2809
+ }, []);
2810
+ React3.useLayoutEffect(initializeStateVars, [
2338
2811
  memoizedLastItemKeys.join(","),
2339
2812
  numColumnsProp,
2340
2813
  stylePaddingTopState,
@@ -2345,12 +2818,11 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2345
2818
  };
2346
2819
  React3.useEffect(() => {
2347
2820
  const viewability = setupViewability({
2821
+ onViewableItemsChanged,
2348
2822
  viewabilityConfig,
2349
- viewabilityConfigCallbackPairs,
2350
- onViewableItemsChanged
2823
+ viewabilityConfigCallbackPairs
2351
2824
  });
2352
2825
  state.viewabilityConfigCallbackPairs = viewability;
2353
- state.props.viewabilityConfigCallbackPairs = viewability;
2354
2826
  state.enableScrollForNextCalculateItemsInView = !viewability;
2355
2827
  }, [viewabilityConfig, viewabilityConfigCallbackPairs, onViewableItemsChanged]);
2356
2828
  if (!IsNewArchitecture) {
@@ -2365,144 +2837,166 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2365
2837
  onLayoutProp(event);
2366
2838
  }
2367
2839
  }, []);
2368
- React3.useImperativeHandle(
2369
- forwardedRef,
2370
- () => {
2371
- const scrollIndexIntoView = (options) => {
2840
+ React3.useImperativeHandle(forwardedRef, () => {
2841
+ const scrollIndexIntoView = (options) => {
2842
+ const state2 = refState.current;
2843
+ if (state2) {
2844
+ const { index, ...rest2 } = options;
2845
+ const { startNoBuffer, endNoBuffer } = state2;
2846
+ if (index < startNoBuffer || index > endNoBuffer) {
2847
+ const viewPosition = index < startNoBuffer ? 0 : 1;
2848
+ scrollToIndex(ctx, state2, {
2849
+ ...rest2,
2850
+ index,
2851
+ viewPosition
2852
+ });
2853
+ }
2854
+ }
2855
+ };
2856
+ return {
2857
+ flashScrollIndicators: () => refScroller.current.flashScrollIndicators(),
2858
+ getNativeScrollRef: () => refScroller.current,
2859
+ getScrollableNode: () => refScroller.current.getScrollableNode(),
2860
+ getScrollResponder: () => refScroller.current.getScrollResponder(),
2861
+ getState: () => {
2372
2862
  const state2 = refState.current;
2373
- if (state2) {
2374
- const { index, ...rest2 } = options;
2375
- const { startNoBuffer, endNoBuffer } = state2;
2376
- if (index < startNoBuffer || index > endNoBuffer) {
2377
- const viewPosition = index < startNoBuffer ? 0 : 1;
2378
- scrollToIndex(ctx, state2, {
2379
- ...rest2,
2380
- viewPosition,
2381
- index
2382
- });
2383
- }
2863
+ return state2 ? {
2864
+ contentLength: state2.totalSize,
2865
+ data: state2.props.data,
2866
+ end: state2.endNoBuffer,
2867
+ endBuffered: state2.endBuffered,
2868
+ isAtEnd: state2.isAtEnd,
2869
+ isAtStart: state2.isAtStart,
2870
+ positionAtIndex: (index) => state2.positions.get(getId(state2, index)),
2871
+ positions: state2.positions,
2872
+ scroll: state2.scroll,
2873
+ scrollLength: state2.scrollLength,
2874
+ sizeAtIndex: (index) => state2.sizesKnown.get(getId(state2, index)),
2875
+ sizes: state2.sizesKnown,
2876
+ start: state2.startNoBuffer,
2877
+ startBuffered: state2.startBuffered
2878
+ } : {};
2879
+ },
2880
+ scrollIndexIntoView,
2881
+ scrollItemIntoView: ({ item, ...props2 }) => {
2882
+ const data = refState.current.props.data;
2883
+ const index = data.indexOf(item);
2884
+ if (index !== -1) {
2885
+ scrollIndexIntoView({ index, ...props2 });
2384
2886
  }
2385
- };
2386
- return {
2387
- flashScrollIndicators: () => refScroller.current.flashScrollIndicators(),
2388
- getNativeScrollRef: () => refScroller.current,
2389
- getScrollableNode: () => refScroller.current.getScrollableNode(),
2390
- getScrollResponder: () => refScroller.current.getScrollResponder(),
2391
- getState: () => {
2392
- const state2 = refState.current;
2393
- return state2 ? {
2394
- contentLength: state2.totalSize,
2395
- end: state2.endNoBuffer,
2396
- endBuffered: state2.endBuffered,
2397
- isAtEnd: state2.isAtEnd,
2398
- isAtStart: state2.isAtStart,
2399
- scroll: state2.scroll,
2400
- scrollLength: state2.scrollLength,
2401
- start: state2.startNoBuffer,
2402
- startBuffered: state2.startBuffered,
2403
- sizes: state2.sizesKnown,
2404
- sizeAtIndex: (index) => state2.sizesKnown.get(getId(state2, index))
2405
- } : {};
2406
- },
2407
- scrollIndexIntoView,
2408
- scrollItemIntoView: ({ item, ...props2 }) => {
2409
- const data = refState.current.props.data;
2410
- const index = data.indexOf(item);
2411
- if (index !== -1) {
2412
- scrollIndexIntoView({ index, ...props2 });
2413
- }
2414
- },
2415
- scrollToIndex: (params) => scrollToIndex(ctx, state, params),
2416
- scrollToItem: ({ item, ...props2 }) => {
2417
- const data = refState.current.props.data;
2418
- const index = data.indexOf(item);
2419
- if (index !== -1) {
2420
- scrollToIndex(ctx, state, { index, ...props2 });
2421
- }
2422
- },
2423
- scrollToOffset: (params) => scrollTo(state, params),
2424
- scrollToEnd: (options) => {
2425
- const data = refState.current.props.data;
2426
- const stylePaddingBottom = refState.current.props.stylePaddingBottom;
2427
- const index = data.length - 1;
2428
- if (index !== -1) {
2429
- const paddingBottom = stylePaddingBottom || 0;
2430
- const footerSize = peek$(ctx, "footerSize") || 0;
2431
- scrollToIndex(ctx, state, {
2432
- index,
2433
- viewPosition: 1,
2434
- viewOffset: -paddingBottom - footerSize,
2435
- ...options
2436
- });
2437
- }
2438
- },
2439
- setVisibleContentAnchorOffset: (value) => {
2440
- const val = typeof value === "function" ? value(peek$(ctx, "scrollAdjustUserOffset") || 0) : value;
2441
- set$(ctx, "scrollAdjustUserOffset", val);
2887
+ },
2888
+ scrollToEnd: (options) => {
2889
+ const data = refState.current.props.data;
2890
+ const stylePaddingBottom = refState.current.props.stylePaddingBottom;
2891
+ const index = data.length - 1;
2892
+ if (index !== -1) {
2893
+ const paddingBottom = stylePaddingBottom || 0;
2894
+ const footerSize = peek$(ctx, "footerSize") || 0;
2895
+ scrollToIndex(ctx, state, {
2896
+ index,
2897
+ viewOffset: -paddingBottom - footerSize + ((options == null ? void 0 : options.viewOffset) || 0),
2898
+ viewPosition: 1,
2899
+ ...options
2900
+ });
2442
2901
  }
2443
- };
2444
- },
2445
- []
2446
- );
2902
+ },
2903
+ scrollToIndex: (params) => scrollToIndex(ctx, state, params),
2904
+ scrollToItem: ({ item, ...props2 }) => {
2905
+ const data = refState.current.props.data;
2906
+ const index = data.indexOf(item);
2907
+ if (index !== -1) {
2908
+ scrollToIndex(ctx, state, { index, ...props2 });
2909
+ }
2910
+ },
2911
+ scrollToOffset: (params) => scrollTo(state, params),
2912
+ setScrollProcessingEnabled: (enabled) => {
2913
+ refState.current.scrollProcessingEnabled = enabled;
2914
+ },
2915
+ setVisibleContentAnchorOffset: (value) => {
2916
+ const val = typeof value === "function" ? value(peek$(ctx, "scrollAdjustUserOffset") || 0) : value;
2917
+ set$(ctx, "scrollAdjustUserOffset", val);
2918
+ }
2919
+ };
2920
+ }, []);
2447
2921
  if (reactNative.Platform.OS === "web") {
2448
2922
  React3.useEffect(() => {
2449
2923
  if (initialContentOffset) {
2450
- scrollTo(state, { offset: initialContentOffset, animated: false });
2924
+ scrollTo(state, { animated: false, offset: initialContentOffset });
2451
2925
  }
2452
2926
  }, []);
2453
2927
  }
2454
2928
  const fns = React3.useMemo(
2455
2929
  () => ({
2456
- updateItemSize: (itemKey, sizeObj) => updateItemSize(ctx, state, itemKey, sizeObj),
2457
2930
  getRenderedItem: (key) => getRenderedItem(ctx, state, key),
2458
- onScroll: (event) => onScroll(ctx, state, event)
2931
+ onScroll: (event) => onScroll(ctx, state, event),
2932
+ updateItemSize: (itemKey, sizeObj) => updateItemSize(ctx, state, itemKey, sizeObj)
2459
2933
  }),
2460
2934
  []
2461
2935
  );
2936
+ const animatedScrollHandler = React3.useMemo(() => {
2937
+ if (stickyIndices == null ? void 0 : stickyIndices.length) {
2938
+ const { animatedScrollY } = ctx;
2939
+ return reactNative.Animated.event([{ nativeEvent: { contentOffset: { [horizontal ? "x" : "y"]: animatedScrollY } } }], {
2940
+ listener: fns.onScroll,
2941
+ useNativeDriver: true
2942
+ });
2943
+ }
2944
+ return fns.onScroll;
2945
+ }, [stickyIndices, horizontal, onScroll]);
2462
2946
  return /* @__PURE__ */ React3__namespace.createElement(React3__namespace.Fragment, null, /* @__PURE__ */ React3__namespace.createElement(
2463
2947
  ListComponent,
2464
2948
  {
2465
2949
  ...rest,
2950
+ alignItemsAtEnd,
2466
2951
  canRender,
2952
+ contentContainerStyle,
2953
+ getRenderedItem: fns.getRenderedItem,
2467
2954
  horizontal,
2468
- refScrollView: combinedRef,
2469
2955
  initialContentOffset,
2470
- getRenderedItem: fns.getRenderedItem,
2471
- updateItemSize: fns.updateItemSize,
2472
- onScroll: fns.onScroll,
2956
+ ListEmptyComponent: dataProp.length === 0 ? ListEmptyComponent : void 0,
2957
+ ListHeaderComponent,
2958
+ maintainVisibleContentPosition,
2959
+ onLayout,
2960
+ onLayoutHeader,
2473
2961
  onMomentumScrollEnd: (event) => {
2474
- requestAnimationFrame(() => {
2475
- finishScrollTo(refState.current);
2476
- });
2962
+ if (IsNewArchitecture) {
2963
+ requestAnimationFrame(() => {
2964
+ finishScrollTo(refState.current);
2965
+ });
2966
+ } else {
2967
+ setTimeout(() => {
2968
+ finishScrollTo(refState.current);
2969
+ }, 1e3);
2970
+ }
2477
2971
  if (onMomentumScrollEnd) {
2478
2972
  onMomentumScrollEnd(event);
2479
2973
  }
2480
2974
  },
2481
- onLayout,
2975
+ onScroll: animatedScrollHandler,
2482
2976
  recycleItems,
2483
- alignItemsAtEnd,
2484
- ListEmptyComponent: dataProp.length === 0 ? ListEmptyComponent : void 0,
2485
- ListHeaderComponent,
2486
- maintainVisibleContentPosition,
2487
- scrollEventThrottle: reactNative.Platform.OS === "web" ? 16 : void 0,
2488
- waitForInitialLayout,
2489
2977
  refreshControl: refreshControl ? stylePaddingTopState > 0 ? React3__namespace.cloneElement(refreshControl, {
2490
2978
  progressViewOffset: (refreshControl.props.progressViewOffset || 0) + stylePaddingTopState
2491
2979
  }) : refreshControl : onRefresh && /* @__PURE__ */ React3__namespace.createElement(
2492
2980
  reactNative.RefreshControl,
2493
2981
  {
2494
- refreshing: !!refreshing,
2495
2982
  onRefresh,
2496
- progressViewOffset: (progressViewOffset || 0) + stylePaddingTopState
2983
+ progressViewOffset: (progressViewOffset || 0) + stylePaddingTopState,
2984
+ refreshing: !!refreshing
2497
2985
  }
2498
2986
  ),
2499
- style,
2500
- contentContainerStyle,
2987
+ refScrollView: combinedRef,
2501
2988
  scrollAdjustHandler: (_a = refState.current) == null ? void 0 : _a.scrollAdjustHandler,
2502
- onLayoutHeader
2989
+ scrollEventThrottle: reactNative.Platform.OS === "web" ? 16 : void 0,
2990
+ snapToIndices,
2991
+ stickyIndices,
2992
+ style,
2993
+ updateItemSize: fns.updateItemSize,
2994
+ waitForInitialLayout
2503
2995
  }
2504
2996
  ), __DEV__ && ENABLE_DEBUG_VIEW && /* @__PURE__ */ React3__namespace.createElement(DebugView, { state: refState.current }));
2505
2997
  });
2998
+
2999
+ // src/components/LazyLegendList.tsx
2506
3000
  var typedForwardRef2 = React3.forwardRef;
2507
3001
  var renderItem = ({ item }) => item;
2508
3002
  var LazyLegendList = typedForwardRef2(function LazyLegendList2(props, forwardedRef) {
@@ -2511,7 +3005,7 @@ var LazyLegendList = typedForwardRef2(function LazyLegendList2(props, forwardedR
2511
3005
  const data = (isArray(children) ? children : React3__namespace.Children.toArray(children)).flat(1);
2512
3006
  return (
2513
3007
  // @ts-expect-error TODO: Fix this type
2514
- /* @__PURE__ */ React3__namespace.createElement(LegendListComponent, { ...rest, data, renderItem, ref: forwardedRef })
3008
+ /* @__PURE__ */ React3__namespace.createElement(LegendListComponent, { ...rest, data, ref: forwardedRef, renderItem })
2515
3009
  );
2516
3010
  });
2517
3011