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