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

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/index.d.mts → index.d.mts} +28 -21
  2. package/{dist/index.d.ts → index.d.ts} +28 -21
  3. package/{dist/index.js → index.js} +808 -760
  4. package/{dist/index.mjs → index.mjs} +808 -760
  5. package/{dist → integrations}/animated.d.mts +2 -1
  6. package/{dist → integrations}/animated.d.ts +2 -1
  7. package/{dist → integrations}/animated.js +2 -2
  8. package/{dist → integrations}/animated.mjs +2 -2
  9. package/{dist → integrations}/keyboard-controller.d.mts +4 -0
  10. package/{dist → integrations}/keyboard-controller.d.ts +4 -0
  11. package/{dist → integrations}/keyboard-controller.js +4 -4
  12. package/{dist → integrations}/keyboard-controller.mjs +4 -4
  13. package/{dist → integrations}/reanimated.js +7 -7
  14. package/{dist → integrations}/reanimated.mjs +7 -7
  15. package/package.json +34 -88
  16. package/.claude/settings.local.json +0 -8
  17. package/.cursor/rules/changelog.mdc +0 -60
  18. package/.github/FUNDING.yml +0 -15
  19. package/.gitignore +0 -5
  20. package/.prettierrc.json +0 -5
  21. package/.vscode/settings.json +0 -14
  22. package/CLAUDE.md +0 -126
  23. package/biome.json +0 -46
  24. package/bun.lock +0 -1289
  25. package/bunfig.toml +0 -2
  26. package/dist/CHANGELOG.md +0 -119
  27. package/dist/LICENSE +0 -21
  28. package/dist/README.md +0 -139
  29. package/dist/package.json +0 -35
  30. package/example/README.md +0 -40
  31. package/example/api/data/genres.json +0 -23
  32. package/example/api/data/playlist/10402-10749.json +0 -1
  33. package/example/api/data/playlist/10402-10770.json +0 -1
  34. package/example/api/data/playlist/10402-37.json +0 -1
  35. package/example/api/data/playlist/10749-10752.json +0 -1
  36. package/example/api/data/playlist/10749-10770.json +0 -1
  37. package/example/api/data/playlist/10749-37.json +0 -1
  38. package/example/api/data/playlist/10749-878.json +0 -1
  39. package/example/api/data/playlist/10751-10402.json +0 -1
  40. package/example/api/data/playlist/10751-10752.json +0 -1
  41. package/example/api/data/playlist/10751-37.json +0 -1
  42. package/example/api/data/playlist/10751-53.json +0 -1
  43. package/example/api/data/playlist/10751-878.json +0 -1
  44. package/example/api/data/playlist/10751-9648.json +0 -1
  45. package/example/api/data/playlist/10752-37.json +0 -1
  46. package/example/api/data/playlist/12-10402.json +0 -1
  47. package/example/api/data/playlist/12-10749.json +0 -1
  48. package/example/api/data/playlist/12-18.json +0 -1
  49. package/example/api/data/playlist/12-27.json +0 -1
  50. package/example/api/data/playlist/12-35.json +0 -1
  51. package/example/api/data/playlist/14-36.json +0 -1
  52. package/example/api/data/playlist/14-878.json +0 -1
  53. package/example/api/data/playlist/16-10751.json +0 -1
  54. package/example/api/data/playlist/16-10770.json +0 -1
  55. package/example/api/data/playlist/16-35.json +0 -1
  56. package/example/api/data/playlist/16-36.json +0 -1
  57. package/example/api/data/playlist/16-53.json +0 -1
  58. package/example/api/data/playlist/18-10751.json +0 -1
  59. package/example/api/data/playlist/18-10752.json +0 -1
  60. package/example/api/data/playlist/18-37.json +0 -1
  61. package/example/api/data/playlist/18-53.json +0 -1
  62. package/example/api/data/playlist/18-878.json +0 -1
  63. package/example/api/data/playlist/27-10749.json +0 -1
  64. package/example/api/data/playlist/27-10770.json +0 -1
  65. package/example/api/data/playlist/28-10749.json +0 -1
  66. package/example/api/data/playlist/28-10751.json +0 -1
  67. package/example/api/data/playlist/28-10770.json +0 -1
  68. package/example/api/data/playlist/28-16.json +0 -1
  69. package/example/api/data/playlist/28-18.json +0 -1
  70. package/example/api/data/playlist/28-36.json +0 -1
  71. package/example/api/data/playlist/28-37.json +0 -1
  72. package/example/api/data/playlist/28-53.json +0 -1
  73. package/example/api/data/playlist/28-80.json +0 -1
  74. package/example/api/data/playlist/28-99.json +0 -1
  75. package/example/api/data/playlist/35-10749.json +0 -1
  76. package/example/api/data/playlist/35-10751.json +0 -1
  77. package/example/api/data/playlist/35-10752.json +0 -1
  78. package/example/api/data/playlist/35-27.json +0 -1
  79. package/example/api/data/playlist/35-36.json +0 -1
  80. package/example/api/data/playlist/35-53.json +0 -1
  81. package/example/api/data/playlist/35-80.json +0 -1
  82. package/example/api/data/playlist/36-37.json +0 -1
  83. package/example/api/data/playlist/36-878.json +0 -1
  84. package/example/api/data/playlist/36-9648.json +0 -1
  85. package/example/api/data/playlist/53-10752.json +0 -1
  86. package/example/api/data/playlist/80-10770.json +0 -1
  87. package/example/api/data/playlist/80-14.json +0 -1
  88. package/example/api/data/playlist/80-18.json +0 -1
  89. package/example/api/data/playlist/80-37.json +0 -1
  90. package/example/api/data/playlist/878-37.json +0 -1
  91. package/example/api/data/playlist/9648-10770.json +0 -1
  92. package/example/api/data/playlist/9648-37.json +0 -1
  93. package/example/api/data/playlist/9648-53.json +0 -1
  94. package/example/api/data/playlist/9648-878.json +0 -1
  95. package/example/api/data/playlist/99-10749.json +0 -1
  96. package/example/api/data/playlist/99-14.json +0 -1
  97. package/example/api/data/playlist/99-18.json +0 -1
  98. package/example/api/data/playlist/99-27.json +0 -1
  99. package/example/api/data/playlist/99-53.json +0 -1
  100. package/example/api/data/playlist/99-9648.json +0 -1
  101. package/example/api/data/playlist/index.ts +0 -73
  102. package/example/api/data/rows.json +0 -1
  103. package/example/api/index.ts +0 -36
  104. package/example/app/(tabs)/_layout.tsx +0 -60
  105. package/example/app/(tabs)/cards.tsx +0 -81
  106. package/example/app/(tabs)/index.tsx +0 -205
  107. package/example/app/(tabs)/moviesL.tsx +0 -7
  108. package/example/app/(tabs)/moviesLR.tsx +0 -7
  109. package/example/app/+not-found.tsx +0 -32
  110. package/example/app/_layout.tsx +0 -34
  111. package/example/app/accurate-scrollto/index.tsx +0 -125
  112. package/example/app/accurate-scrollto-2/index.tsx +0 -52
  113. package/example/app/accurate-scrollto-huge/index.tsx +0 -128
  114. package/example/app/add-to-end/index.tsx +0 -82
  115. package/example/app/ai-chat/index.tsx +0 -236
  116. package/example/app/bidirectional-infinite-list/index.tsx +0 -133
  117. package/example/app/cards-columns/index.tsx +0 -37
  118. package/example/app/cards-flashlist/index.tsx +0 -122
  119. package/example/app/cards-flatlist/index.tsx +0 -94
  120. package/example/app/cards-no-recycle/index.tsx +0 -110
  121. package/example/app/cards-renderItem.tsx +0 -354
  122. package/example/app/chat-example/index.tsx +0 -167
  123. package/example/app/chat-infinite/index.tsx +0 -239
  124. package/example/app/chat-keyboard/index.tsx +0 -248
  125. package/example/app/chat-resize-outer/index.tsx +0 -247
  126. package/example/app/columns/index.tsx +0 -78
  127. package/example/app/countries/index.tsx +0 -182
  128. package/example/app/countries-flashlist/index.tsx +0 -163
  129. package/example/app/countries-reorder/index.tsx +0 -187
  130. package/example/app/extra-data/index.tsx +0 -86
  131. package/example/app/filter-elements/filter-data-provider.tsx +0 -55
  132. package/example/app/filter-elements/index.tsx +0 -118
  133. package/example/app/initial-scroll-index/index.tsx +0 -106
  134. package/example/app/initial-scroll-index/renderFixedItem.tsx +0 -215
  135. package/example/app/initial-scroll-index-free-height/index.tsx +0 -70
  136. package/example/app/initial-scroll-index-keyed/index.tsx +0 -62
  137. package/example/app/lazy-list/index.tsx +0 -123
  138. package/example/app/movies-flashlist/index.tsx +0 -7
  139. package/example/app/mutable-cells/index.tsx +0 -104
  140. package/example/app/video-feed/index.tsx +0 -119
  141. package/example/app.config.js +0 -22
  142. package/example/app.json +0 -45
  143. package/example/assets/fonts/SpaceMono-Regular.ttf +0 -0
  144. package/example/assets/images/adaptive-icon.png +0 -0
  145. package/example/assets/images/favicon.png +0 -0
  146. package/example/assets/images/icon.png +0 -0
  147. package/example/assets/images/partial-react-logo.png +0 -0
  148. package/example/assets/images/react-logo.png +0 -0
  149. package/example/assets/images/react-logo@2x.png +0 -0
  150. package/example/assets/images/react-logo@3x.png +0 -0
  151. package/example/assets/images/splash-icon.png +0 -0
  152. package/example/autoscroll.sh +0 -101
  153. package/example/bun.lock +0 -2266
  154. package/example/bunfig.toml +0 -2
  155. package/example/components/Breathe.tsx +0 -54
  156. package/example/components/Circle.tsx +0 -69
  157. package/example/components/Collapsible.tsx +0 -44
  158. package/example/components/ExternalLink.tsx +0 -24
  159. package/example/components/HapticTab.tsx +0 -18
  160. package/example/components/HelloWave.tsx +0 -37
  161. package/example/components/Movies.tsx +0 -179
  162. package/example/components/ParallaxScrollView.tsx +0 -81
  163. package/example/components/ThemedText.tsx +0 -60
  164. package/example/components/ThemedView.tsx +0 -14
  165. package/example/components/__tests__/ThemedText-test.tsx +0 -10
  166. package/example/components/__tests__/__snapshots__/ThemedText-test.tsx.snap +0 -24
  167. package/example/components/ui/IconSymbol.ios.tsx +0 -32
  168. package/example/components/ui/IconSymbol.tsx +0 -43
  169. package/example/components/ui/TabBarBackground.ios.tsx +0 -22
  170. package/example/components/ui/TabBarBackground.tsx +0 -6
  171. package/example/constants/Colors.ts +0 -26
  172. package/example/constants/constants.ts +0 -5
  173. package/example/constants/useScrollTest.ts +0 -19
  174. package/example/hooks/useColorScheme.ts +0 -1
  175. package/example/hooks/useColorScheme.web.ts +0 -8
  176. package/example/hooks/useThemeColor.ts +0 -22
  177. package/example/ios/.xcode.env +0 -11
  178. package/example/ios/Podfile +0 -64
  179. package/example/ios/Podfile.lock +0 -2767
  180. package/example/ios/Podfile.properties.json +0 -5
  181. package/example/ios/listtest/AppDelegate.swift +0 -70
  182. package/example/ios/listtest/Images.xcassets/AppIcon.appiconset/App-Icon-1024x1024@1x.png +0 -0
  183. package/example/ios/listtest/Images.xcassets/AppIcon.appiconset/Contents.json +0 -14
  184. package/example/ios/listtest/Images.xcassets/Contents.json +0 -6
  185. package/example/ios/listtest/Images.xcassets/SplashScreenBackground.colorset/Contents.json +0 -20
  186. package/example/ios/listtest/Images.xcassets/SplashScreenLogo.imageset/Contents.json +0 -23
  187. package/example/ios/listtest/Images.xcassets/SplashScreenLogo.imageset/image.png +0 -0
  188. package/example/ios/listtest/Images.xcassets/SplashScreenLogo.imageset/image@2x.png +0 -0
  189. package/example/ios/listtest/Images.xcassets/SplashScreenLogo.imageset/image@3x.png +0 -0
  190. package/example/ios/listtest/Info.plist +0 -85
  191. package/example/ios/listtest/PrivacyInfo.xcprivacy +0 -48
  192. package/example/ios/listtest/SplashScreen.storyboard +0 -42
  193. package/example/ios/listtest/Supporting/Expo.plist +0 -12
  194. package/example/ios/listtest/listtest-Bridging-Header.h +0 -3
  195. package/example/ios/listtest/listtest.entitlements +0 -5
  196. package/example/ios/listtest.xcodeproj/project.pbxproj +0 -547
  197. package/example/ios/listtest.xcodeproj/xcshareddata/xcschemes/listtest.xcscheme +0 -88
  198. package/example/ios/listtest.xcworkspace/contents.xcworkspacedata +0 -10
  199. package/example/metro.config.js +0 -16
  200. package/example/package.json +0 -73
  201. package/example/scripts/reset-project.js +0 -84
  202. package/example/tsconfig.json +0 -26
  203. package/posttsup.ts +0 -24
  204. package/src/Container.tsx +0 -176
  205. package/src/Containers.tsx +0 -85
  206. package/src/ContextContainer.ts +0 -145
  207. package/src/DebugView.tsx +0 -83
  208. package/src/LazyLegendList.tsx +0 -41
  209. package/src/LeanView.tsx +0 -18
  210. package/src/LegendList.tsx +0 -558
  211. package/src/ListComponent.tsx +0 -191
  212. package/src/ScrollAdjust.tsx +0 -24
  213. package/src/ScrollAdjustHandler.ts +0 -26
  214. package/src/Separator.tsx +0 -14
  215. package/src/animated.tsx +0 -6
  216. package/src/calculateItemsInView.ts +0 -363
  217. package/src/calculateOffsetForIndex.ts +0 -23
  218. package/src/calculateOffsetWithOffsetPosition.ts +0 -26
  219. package/src/checkAllSizesKnown.ts +0 -17
  220. package/src/checkAtBottom.ts +0 -36
  221. package/src/checkAtTop.ts +0 -27
  222. package/src/checkThreshold.ts +0 -30
  223. package/src/constants.ts +0 -11
  224. package/src/createColumnWrapperStyle.ts +0 -16
  225. package/src/doInitialAllocateContainers.ts +0 -40
  226. package/src/doMaintainScrollAtEnd.ts +0 -34
  227. package/src/findAvailableContainers.ts +0 -98
  228. package/src/finishScrollTo.ts +0 -8
  229. package/src/getId.ts +0 -21
  230. package/src/getItemSize.ts +0 -52
  231. package/src/getRenderedItem.ts +0 -34
  232. package/src/getScrollVelocity.ts +0 -47
  233. package/src/handleLayout.ts +0 -70
  234. package/src/helpers.ts +0 -39
  235. package/src/index.ts +0 -11
  236. package/src/keyboard-controller.tsx +0 -63
  237. package/src/onScroll.ts +0 -66
  238. package/src/prepareMVCP.ts +0 -50
  239. package/src/reanimated.tsx +0 -63
  240. package/src/requestAdjust.ts +0 -41
  241. package/src/scrollTo.ts +0 -40
  242. package/src/scrollToIndex.ts +0 -34
  243. package/src/setDidLayout.ts +0 -25
  244. package/src/setPaddingTop.ts +0 -28
  245. package/src/state.tsx +0 -304
  246. package/src/types.ts +0 -610
  247. package/src/updateAlignItemsPaddingTop.ts +0 -18
  248. package/src/updateAllPositions.ts +0 -130
  249. package/src/updateItemSize.ts +0 -203
  250. package/src/updateTotalSize.ts +0 -44
  251. package/src/useAnimatedValue.ts +0 -6
  252. package/src/useCombinedRef.ts +0 -22
  253. package/src/useInit.ts +0 -17
  254. package/src/useSyncLayout.tsx +0 -68
  255. package/src/useValue$.ts +0 -53
  256. package/src/viewability.ts +0 -279
  257. package/tsconfig.json +0 -59
  258. package/tsup.config.ts +0 -21
  259. package/{dist → integrations}/reanimated.d.mts +1 -1
  260. package/{dist → integrations}/reanimated.d.ts +1 -1
@@ -3,21 +3,22 @@ import React3__default, { useReducer, useEffect, createContext, useMemo, useStat
3
3
  import { View, Text, Platform, Animated, ScrollView, StyleSheet, Dimensions, RefreshControl } 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
+ columnWrapperStyle: void 0,
10
11
  listeners: /* @__PURE__ */ new Map(),
12
+ mapViewabilityAmountCallbacks: /* @__PURE__ */ new Map(),
13
+ mapViewabilityAmountValues: /* @__PURE__ */ new Map(),
14
+ mapViewabilityCallbacks: /* @__PURE__ */ new Map(),
15
+ mapViewabilityValues: /* @__PURE__ */ new Map(),
11
16
  values: /* @__PURE__ */ new Map([
12
17
  ["alignItemsPaddingTop", 0],
13
18
  ["stylePaddingTop", 0],
14
- ["headerSize", 0]
19
+ ["headerSize", 0],
20
+ ["numContainers", 0]
15
21
  ]),
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
22
  viewRefs: /* @__PURE__ */ new Map()
22
23
  }));
23
24
  return /* @__PURE__ */ React3.createElement(ContextState.Provider, { value }, children);
@@ -29,17 +30,6 @@ function createSelectorFunctionsArr(ctx, signalNames) {
29
30
  let lastValues = [];
30
31
  let lastSignalValues = [];
31
32
  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
33
  get: () => {
44
34
  const currentValues = [];
45
35
  let hasChanged = false;
@@ -55,6 +45,17 @@ function createSelectorFunctionsArr(ctx, signalNames) {
55
45
  lastValues = currentValues;
56
46
  }
57
47
  return lastValues;
48
+ },
49
+ subscribe: (cb) => {
50
+ const listeners = [];
51
+ for (const signalName of signalNames) {
52
+ listeners.push(listen$(ctx, signalName, cb));
53
+ }
54
+ return () => {
55
+ for (const listener of listeners) {
56
+ listener();
57
+ }
58
+ };
58
59
  }
59
60
  };
60
61
  }
@@ -105,13 +106,13 @@ function useSelector$(signalName, selector) {
105
106
  return value;
106
107
  }
107
108
 
108
- // src/DebugView.tsx
109
+ // src/components/DebugView.tsx
109
110
  var DebugRow = ({ children }) => {
110
- return /* @__PURE__ */ React3.createElement(View, { style: { flexDirection: "row", alignItems: "center", justifyContent: "space-between" } }, children);
111
+ return /* @__PURE__ */ React3.createElement(View, { style: { alignItems: "center", flexDirection: "row", justifyContent: "space-between" } }, children);
111
112
  };
112
113
  var DebugView = React3.memo(function DebugView2({ state }) {
113
114
  const ctx = useStateContext();
114
- const [totalSize = 0, scrollAdjust = 0, rawScroll = 0, scroll = 0, numContainers = 0, numContainersPooled = 0] = useArr$([
115
+ const [totalSize = 0, scrollAdjust = 0, rawScroll = 0, scroll = 0, _numContainers = 0, _numContainersPooled = 0] = useArr$([
115
116
  "totalSize",
116
117
  "scrollAdjust",
117
118
  "debugRawScroll",
@@ -127,18 +128,18 @@ var DebugView = React3.memo(function DebugView2({ state }) {
127
128
  return /* @__PURE__ */ React3.createElement(
128
129
  View,
129
130
  {
131
+ pointerEvents: "none",
130
132
  style: {
131
- position: "absolute",
132
- top: 0,
133
- right: 0,
134
- paddingLeft: 4,
135
- paddingBottom: 4,
136
133
  // height: 100,
137
134
  backgroundColor: "#FFFFFFCC",
135
+ borderRadius: 4,
138
136
  padding: 4,
139
- borderRadius: 4
140
- },
141
- pointerEvents: "none"
137
+ paddingBottom: 4,
138
+ paddingLeft: 4,
139
+ position: "absolute",
140
+ right: 0,
141
+ top: 0
142
+ }
142
143
  },
143
144
  /* @__PURE__ */ React3.createElement(DebugRow, null, /* @__PURE__ */ React3.createElement(Text, null, "TotalSize:"), /* @__PURE__ */ React3.createElement(Text, null, totalSize.toFixed(2))),
144
145
  /* @__PURE__ */ React3.createElement(DebugRow, null, /* @__PURE__ */ React3.createElement(Text, null, "ContentSize:"), /* @__PURE__ */ React3.createElement(Text, null, contentSize.toFixed(2))),
@@ -156,8 +157,34 @@ function useInterval(callback, delay) {
156
157
  return () => clearInterval(interval);
157
158
  }, [delay]);
158
159
  }
160
+ var LeanViewComponent = React3.forwardRef((props, ref) => {
161
+ return React3.createElement("RCTView", { ...props, ref });
162
+ });
163
+ LeanViewComponent.displayName = "RCTView";
164
+ var LeanView = Platform.OS === "android" || Platform.OS === "ios" ? LeanViewComponent : View;
165
+
166
+ // src/components/Separator.tsx
167
+ function Separator({ ItemSeparatorComponent, itemKey, leadingItem }) {
168
+ const [lastItemKeys] = useArr$(["lastItemKeys"]);
169
+ const isALastItem = lastItemKeys.includes(itemKey);
170
+ return isALastItem ? null : /* @__PURE__ */ React.createElement(ItemSeparatorComponent, { leadingItem });
171
+ }
172
+
173
+ // src/constants.ts
174
+ var POSITION_OUT_OF_VIEW = -1e7;
175
+ var ENABLE_DEVMODE = __DEV__ && false;
176
+ var ENABLE_DEBUG_VIEW = __DEV__ && false;
177
+ var IsNewArchitecture = global.nativeFabricUIManager != null;
178
+ var symbolFirst = Symbol();
179
+ function useInit(cb) {
180
+ const refValue = useRef(symbolFirst);
181
+ if (refValue.current === symbolFirst) {
182
+ refValue.current = cb();
183
+ }
184
+ return refValue.current;
185
+ }
159
186
 
160
- // src/helpers.ts
187
+ // src/utils/helpers.ts
161
188
  function isFunction(obj) {
162
189
  return typeof obj === "function";
163
190
  }
@@ -187,16 +214,8 @@ function getPadding(s, type) {
187
214
  function extractPadding(style, contentContainerStyle, type) {
188
215
  return getPadding(style, type) + getPadding(contentContainerStyle, type);
189
216
  }
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
217
 
199
- // src/ContextContainer.ts
218
+ // src/state/ContextContainer.ts
200
219
  var ContextContainer = createContext(null);
201
220
  function useViewability(callback, configId) {
202
221
  const ctx = useStateContext();
@@ -240,7 +259,7 @@ function useRecyclingEffect(effect) {
240
259
  prevItem: void 0
241
260
  });
242
261
  useEffect(() => {
243
- let ret = void 0;
262
+ let ret;
244
263
  if (prevValues.current.prevIndex !== void 0 && prevValues.current.prevItem !== void 0) {
245
264
  ret = effect({
246
265
  index,
@@ -254,7 +273,7 @@ function useRecyclingEffect(effect) {
254
273
  prevItem: value
255
274
  };
256
275
  return ret;
257
- }, [index, value]);
276
+ }, [index, value, effect]);
258
277
  }
259
278
  function useRecyclingState(valueOrFun) {
260
279
  const { index, value, itemKey, triggerLayout } = useContext(ContextContainer);
@@ -292,26 +311,8 @@ function useListScrollSize() {
292
311
  const [scrollSize] = useArr$(["scrollSize"]);
293
312
  return scrollSize;
294
313
  }
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
314
 
314
- // src/Container.tsx
315
+ // src/components/Container.tsx
315
316
  var Container = ({
316
317
  id,
317
318
  recycleItems,
@@ -353,17 +354,17 @@ var Container = ({
353
354
  }
354
355
  const style = horizontal ? {
355
356
  flexDirection: ItemSeparatorComponent ? "row" : void 0,
356
- position: "absolute",
357
- top: otherAxisPos,
358
357
  height: otherAxisSize,
359
358
  left: position,
359
+ position: "absolute",
360
+ top: otherAxisPos,
360
361
  ...paddingStyles || {}
361
362
  } : {
362
- position: "absolute",
363
363
  left: otherAxisPos,
364
+ position: "absolute",
364
365
  right: numColumns > 1 ? null : 0,
365
- width: otherAxisSize,
366
366
  top: position,
367
+ width: otherAxisSize,
367
368
  ...paddingStyles || {}
368
369
  };
369
370
  const renderedItemInfo = useMemo(
@@ -376,7 +377,7 @@ var Container = ({
376
377
  }, []);
377
378
  const contextValue = useMemo(() => {
378
379
  ctx.viewRefs.set(id, ref);
379
- return { containerId: id, itemKey, index, value: data, triggerLayout };
380
+ return { containerId: id, index, itemKey, triggerLayout, value: data };
380
381
  }, [id, itemKey, index, data]);
381
382
  const onLayout = (event) => {
382
383
  var _a, _b;
@@ -385,14 +386,14 @@ var Container = ({
385
386
  let layout = event.nativeEvent.layout;
386
387
  const size = layout[horizontal ? "width" : "height"];
387
388
  const doUpdate = () => {
388
- refLastSize.current = { width: layout.width, height: layout.height };
389
+ refLastSize.current = { height: layout.height, width: layout.width };
389
390
  updateItemSize2(itemKey, layout);
390
391
  };
391
392
  if (IsNewArchitecture || size > 0) {
392
393
  doUpdate();
393
394
  } 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 };
395
+ (_b = (_a = ref.current) == null ? void 0 : _a.measure) == null ? void 0 : _b.call(_a, (_x, _y, width, height) => {
396
+ layout = { height, width };
396
397
  doUpdate();
397
398
  });
398
399
  }
@@ -425,30 +426,28 @@ var Container = ({
425
426
  }
426
427
  }, [itemKey]);
427
428
  }
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
+ return /* @__PURE__ */ React3.createElement(LeanView, { key: recycleItems ? void 0 : itemKey, onLayout, ref, style }, /* @__PURE__ */ React3.createElement(ContextContainer.Provider, { value: contextValue }, renderedItem, renderedItemInfo && ItemSeparatorComponent && /* @__PURE__ */ React3.createElement(
429
430
  Separator,
430
431
  {
431
- itemKey,
432
432
  ItemSeparatorComponent,
433
+ itemKey,
433
434
  leadingItem: renderedItemInfo.item
434
435
  }
435
436
  )));
436
437
  };
437
- var typedForwardRef = forwardRef;
438
- var typedMemo = memo;
439
438
  var useAnimatedValue = (initialValue) => {
440
439
  return useRef(new Animated.Value(initialValue)).current;
441
440
  };
442
441
 
443
- // src/useValue$.ts
442
+ // src/hooks/useValue$.ts
444
443
  function useValue$(key, params) {
445
444
  var _a;
446
445
  const { getValue, delay } = params || {};
447
446
  const ctx = useStateContext();
448
447
  const animValue = useAnimatedValue((_a = getValue ? getValue(peek$(ctx, key)) : peek$(ctx, key)) != null ? _a : 0);
449
448
  useMemo(() => {
450
- let newValue = void 0;
451
- let prevValue = void 0;
449
+ let newValue;
450
+ let prevValue;
452
451
  let didQueueTask = false;
453
452
  listen$(ctx, key, (v) => {
454
453
  newValue = getValue ? getValue(v) : v;
@@ -476,8 +475,10 @@ function useValue$(key, params) {
476
475
  }, []);
477
476
  return animValue;
478
477
  }
478
+ var typedForwardRef = forwardRef;
479
+ var typedMemo = memo;
479
480
 
480
- // src/Containers.tsx
481
+ // src/components/Containers.tsx
481
482
  var Containers = typedMemo(function Containers2({
482
483
  horizontal,
483
484
  recycleItems,
@@ -501,18 +502,18 @@ var Containers = typedMemo(function Containers2({
501
502
  /* @__PURE__ */ React3.createElement(
502
503
  Container,
503
504
  {
505
+ getRenderedItem: getRenderedItem2,
506
+ horizontal,
507
+ ItemSeparatorComponent,
504
508
  id: i,
505
509
  key: i,
506
510
  recycleItems,
507
- horizontal,
508
- getRenderedItem: getRenderedItem2,
509
- updateItemSize: updateItemSize2,
510
- ItemSeparatorComponent
511
+ updateItemSize: updateItemSize2
511
512
  }
512
513
  )
513
514
  );
514
515
  }
515
- const style = horizontal ? { width: animSize, opacity: animOpacity, minHeight: otherAxisSize } : { height: animSize, opacity: animOpacity, minWidth: otherAxisSize };
516
+ const style = horizontal ? { minHeight: otherAxisSize, opacity: animOpacity, width: animSize } : { height: animSize, minWidth: otherAxisSize, opacity: animOpacity };
516
517
  if (columnWrapperStyle && numColumns > 1) {
517
518
  const { columnGap, rowGap, gap } = columnWrapperStyle;
518
519
  const gapX = columnGap || gap || 0;
@@ -543,15 +544,21 @@ function ScrollAdjust() {
543
544
  View,
544
545
  {
545
546
  style: {
546
- position: "absolute",
547
547
  height: 0,
548
- width: 0,
548
+ left: 0,
549
+ position: "absolute",
549
550
  top: scrollOffset,
550
- left: 0
551
+ width: 0
551
552
  }
552
553
  }
553
554
  );
554
555
  }
556
+
557
+ // src/components/SnapWrapper.tsx
558
+ function SnapWrapper({ ScrollComponent, ...props }) {
559
+ const [snapToOffsets] = useArr$(["snapToOffsets"]);
560
+ return /* @__PURE__ */ React.createElement(ScrollComponent, { ...props, snapToOffsets });
561
+ }
555
562
  function useSyncLayout({
556
563
  onChange
557
564
  }) {
@@ -565,14 +572,14 @@ function useSyncLayout({
565
572
  useLayoutEffect(() => {
566
573
  if (ref.current) {
567
574
  ref.current.measure((x, y, width, height) => {
568
- onChange({ x, y, width, height }, true);
575
+ onChange({ height, width, x, y }, true);
569
576
  });
570
577
  }
571
578
  }, []);
572
579
  return { onLayout, ref };
573
580
  }
574
581
 
575
- // src/ListComponent.tsx
582
+ // src/components/ListComponent.tsx
576
583
  var getComponent = (Component) => {
577
584
  if (React3.isValidElement(Component)) {
578
585
  return Component;
@@ -592,12 +599,12 @@ var PaddingDevMode = () => {
592
599
  Animated.View,
593
600
  {
594
601
  style: {
595
- position: "absolute",
596
- top: 0,
602
+ backgroundColor: "green",
597
603
  height: animPaddingTop,
598
604
  left: 0,
605
+ position: "absolute",
599
606
  right: 0,
600
- backgroundColor: "green"
607
+ top: 0
601
608
  }
602
609
  }
603
610
  ));
@@ -626,6 +633,7 @@ var ListComponent = typedMemo(function ListComponent2({
626
633
  renderScrollComponent,
627
634
  scrollAdjustHandler,
628
635
  onLayoutHeader,
636
+ snapToIndices,
629
637
  ...rest
630
638
  }) {
631
639
  const ctx = useStateContext();
@@ -643,76 +651,56 @@ var ListComponent = typedMemo(function ListComponent2({
643
651
  }, 0);
644
652
  }
645
653
  }, [canRender]);
654
+ const SnapOrScroll = snapToIndices ? SnapWrapper : ScrollComponent;
646
655
  return /* @__PURE__ */ React3.createElement(
647
- ScrollComponent,
656
+ SnapOrScroll,
648
657
  {
649
658
  ...rest,
650
- style,
651
- maintainVisibleContentPosition: maintainVisibleContentPosition && !ListEmptyComponent ? { minIndexForVisible: 0 } : void 0,
652
659
  contentContainerStyle: [
653
660
  contentContainerStyle,
654
661
  horizontal ? {
655
662
  height: "100%"
656
663
  } : {}
657
664
  ],
658
- onScroll: onScroll2,
659
- onLayout,
660
- horizontal,
661
665
  contentOffset: initialContentOffset ? horizontal ? { x: initialContentOffset, y: 0 } : { x: 0, y: initialContentOffset } : void 0,
662
- ref: refScrollView
666
+ horizontal,
667
+ maintainVisibleContentPosition: maintainVisibleContentPosition && !ListEmptyComponent ? { minIndexForVisible: 0 } : void 0,
668
+ onLayout,
669
+ onScroll: onScroll2,
670
+ ref: refScrollView,
671
+ ScrollComponent: snapToIndices ? ScrollComponent : void 0,
672
+ style
663
673
  },
664
674
  maintainVisibleContentPosition && /* @__PURE__ */ React3.createElement(ScrollAdjust, null),
665
675
  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)),
676
+ ListHeaderComponent && /* @__PURE__ */ React3.createElement(View, { onLayout: onLayoutHeaderSync, ref: refHeader, style: ListHeaderComponentStyle }, getComponent(ListHeaderComponent)),
667
677
  ListEmptyComponent && getComponent(ListEmptyComponent),
668
678
  canRender && /* @__PURE__ */ React3.createElement(
669
679
  Containers,
670
680
  {
671
- horizontal,
672
- recycleItems,
673
- waitForInitialLayout,
674
681
  getRenderedItem: getRenderedItem2,
682
+ horizontal,
675
683
  ItemSeparatorComponent,
676
- updateItemSize: updateItemSize2
684
+ recycleItems,
685
+ updateItemSize: updateItemSize2,
686
+ waitForInitialLayout
677
687
  }
678
688
  ),
679
689
  ListFooterComponent && /* @__PURE__ */ React3.createElement(
680
690
  View,
681
691
  {
682
- style: ListFooterComponentStyle,
683
692
  onLayout: (event) => {
684
693
  const size = event.nativeEvent.layout[horizontal ? "width" : "height"];
685
694
  set$(ctx, "footerSize", size);
686
- }
695
+ },
696
+ style: ListFooterComponentStyle
687
697
  },
688
698
  getComponent(ListFooterComponent)
689
699
  )
690
700
  );
691
701
  });
692
702
 
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
703
+ // src/utils/getId.ts
716
704
  function getId(state, index) {
717
705
  const { data, keyExtractor } = state.props;
718
706
  if (!data) {
@@ -724,7 +712,7 @@ function getId(state, index) {
724
712
  return id;
725
713
  }
726
714
 
727
- // src/calculateOffsetForIndex.ts
715
+ // src/core/calculateOffsetForIndex.ts
728
716
  function calculateOffsetForIndex(ctx, state, index) {
729
717
  let position = 0;
730
718
  if (index !== void 0) {
@@ -741,7 +729,7 @@ function calculateOffsetForIndex(ctx, state, index) {
741
729
  return position;
742
730
  }
743
731
 
744
- // src/getItemSize.ts
732
+ // src/utils/getItemSize.ts
745
733
  function getItemSize(state, key, index, data, useAverageSize) {
746
734
  const {
747
735
  sizesKnown,
@@ -770,7 +758,7 @@ function getItemSize(state, key, index, data, useAverageSize) {
770
758
  return size;
771
759
  }
772
760
 
773
- // src/calculateOffsetWithOffsetPosition.ts
761
+ // src/core/calculateOffsetWithOffsetPosition.ts
774
762
  function calculateOffsetWithOffsetPosition(state, offsetParam, params) {
775
763
  const { index, viewOffset, viewPosition } = params;
776
764
  let offset = offsetParam;
@@ -783,323 +771,76 @@ function calculateOffsetWithOffsetPosition(state, offsetParam, params) {
783
771
  return offset;
784
772
  }
785
773
 
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));
774
+ // src/utils/requestAdjust.ts
775
+ function requestAdjust(ctx, state, positionDiff) {
776
+ if (Math.abs(positionDiff) > 0.1) {
777
+ const doit = () => {
778
+ state.scrollAdjustHandler.requestAdjust(positionDiff);
779
+ };
780
+ state.scroll += positionDiff;
781
+ state.scrollForNextCalculateItemsInView = void 0;
782
+ const didLayout = peek$(ctx, "containersDidLayout");
783
+ if (didLayout) {
784
+ doit();
785
+ const threshold = state.scroll - positionDiff / 2;
786
+ if (!state.ignoreScrollFromMVCP) {
787
+ state.ignoreScrollFromMVCP = {};
788
+ }
789
+ if (positionDiff > 0) {
790
+ state.ignoreScrollFromMVCP.lt = threshold;
791
+ } else {
792
+ state.ignoreScrollFromMVCP.gt = threshold;
793
+ }
794
+ if (state.ignoreScrollFromMVCPTimeout) {
795
+ clearTimeout(state.ignoreScrollFromMVCPTimeout);
796
+ }
797
+ state.ignoreScrollFromMVCPTimeout = setTimeout(() => {
798
+ state.ignoreScrollFromMVCP = void 0;
799
+ }, 100);
800
+ } else {
801
+ requestAnimationFrame(doit);
794
802
  }
795
- return areAllKnown;
796
803
  }
797
- return false;
798
804
  }
799
805
 
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
- }
806
+ // src/core/prepareMVCP.ts
807
+ function prepareMVCP(ctx, state) {
808
+ const {
809
+ positions,
810
+ scrollingTo,
811
+ props: { maintainVisibleContentPosition }
812
+ } = state;
813
+ let prevPosition;
814
+ let targetId;
815
+ let targetIndex;
816
+ const scrollTarget = scrollingTo == null ? void 0 : scrollingTo.index;
817
+ if (maintainVisibleContentPosition) {
818
+ const indexByKey = state.indexByKey;
819
+ if (scrollTarget !== void 0) {
820
+ targetId = getId(state, scrollTarget);
821
+ targetIndex = scrollTarget;
822
+ } else if (state.idsInView.length > 0 && peek$(ctx, "containersDidLayout")) {
823
+ targetId = state.idsInView.find((id) => indexByKey.get(id) !== void 0);
824
+ targetIndex = indexByKey.get(targetId);
820
825
  }
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 });
826
+ if (targetId !== void 0 && targetIndex !== void 0) {
827
+ prevPosition = positions.get(targetId);
830
828
  }
831
829
  }
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
- }
862
- }
863
- return result.sort(comparatorDefault);
864
- }
865
- function comparatorByDistance(a, b) {
866
- return b.distance - a.distance;
867
- }
868
-
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
- }
902
- }
903
- return velocity;
904
- };
905
-
906
- // src/requestAdjust.ts
907
- function requestAdjust(ctx, state, positionDiff) {
908
- if (Math.abs(positionDiff) > 0.1) {
909
- const doit = () => {
910
- state.scrollAdjustHandler.requestAdjust(positionDiff);
911
- };
912
- state.scroll += positionDiff;
913
- state.scrollForNextCalculateItemsInView = void 0;
914
- const didLayout = peek$(ctx, "containersDidLayout");
915
- if (didLayout) {
916
- doit();
917
- const threshold = state.scroll - positionDiff / 2;
918
- if (!state.ignoreScrollFromMVCP) {
919
- state.ignoreScrollFromMVCP = {};
920
- }
921
- if (positionDiff > 0) {
922
- state.ignoreScrollFromMVCP.lt = threshold;
923
- } else {
924
- state.ignoreScrollFromMVCP.gt = threshold;
925
- }
926
- if (state.ignoreScrollFromMVCPTimeout) {
927
- clearTimeout(state.ignoreScrollFromMVCPTimeout);
928
- }
929
- state.ignoreScrollFromMVCPTimeout = setTimeout(() => {
930
- state.ignoreScrollFromMVCP = void 0;
931
- }, 100);
932
- } else {
933
- requestAnimationFrame(doit);
934
- }
935
- }
936
- }
937
-
938
- // src/prepareMVCP.ts
939
- function prepareMVCP(ctx, state) {
940
- const {
941
- positions,
942
- scrollingTo,
943
- props: { maintainVisibleContentPosition }
944
- } = state;
945
- let prevPosition;
946
- let targetId;
947
- let targetIndex;
948
- const scrollTarget = scrollingTo == null ? void 0 : scrollingTo.index;
949
- if (maintainVisibleContentPosition) {
950
- const indexByKey = state.indexByKey;
951
- if (scrollTarget !== void 0) {
952
- 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);
957
- }
958
- if (targetId !== void 0 && targetIndex !== void 0) {
959
- prevPosition = positions.get(targetId);
960
- }
961
- }
962
- return () => {
963
- if (targetId !== void 0 && prevPosition !== void 0) {
964
- const newPosition = positions.get(targetId);
965
- if (newPosition !== void 0) {
966
- const positionDiff = newPosition - prevPosition;
967
- if (Math.abs(positionDiff) > 0.1) {
968
- requestAdjust(ctx, state, positionDiff);
969
- }
830
+ return () => {
831
+ if (targetId !== void 0 && prevPosition !== void 0) {
832
+ const newPosition = positions.get(targetId);
833
+ if (newPosition !== void 0) {
834
+ const positionDiff = newPosition - prevPosition;
835
+ if (Math.abs(positionDiff) > 0.1) {
836
+ requestAdjust(ctx, state, positionDiff);
837
+ }
970
838
  }
971
839
  }
972
840
  };
973
841
  }
974
842
 
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;
1025
- }
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
- }
1100
- }
1101
-
1102
- // src/setPaddingTop.ts
843
+ // src/utils/setPaddingTop.ts
1103
844
  function setPaddingTop(ctx, { stylePaddingTop, alignItemsPaddingTop }) {
1104
845
  if (stylePaddingTop !== void 0) {
1105
846
  const prevStylePaddingTop = peek$(ctx, "stylePaddingTop") || 0;
@@ -1117,7 +858,7 @@ function setPaddingTop(ctx, { stylePaddingTop, alignItemsPaddingTop }) {
1117
858
  }
1118
859
  }
1119
860
 
1120
- // src/updateAlignItemsPaddingTop.ts
861
+ // src/utils/updateAlignItemsPaddingTop.ts
1121
862
  function updateAlignItemsPaddingTop(ctx, state) {
1122
863
  const {
1123
864
  scrollLength,
@@ -1133,7 +874,7 @@ function updateAlignItemsPaddingTop(ctx, state) {
1133
874
  }
1134
875
  }
1135
876
 
1136
- // src/updateTotalSize.ts
877
+ // src/core/updateTotalSize.ts
1137
878
  function updateTotalSize(ctx, state) {
1138
879
  const {
1139
880
  positions,
@@ -1166,10 +907,71 @@ function addTotalSize(ctx, state, key, add) {
1166
907
  }
1167
908
  }
1168
909
 
1169
- // src/updateAllPositions.ts
910
+ // src/utils/getScrollVelocity.ts
911
+ var getScrollVelocity = (state) => {
912
+ const { scrollHistory } = state;
913
+ let velocity = 0;
914
+ if (scrollHistory.length >= 1) {
915
+ const newest = scrollHistory[scrollHistory.length - 1];
916
+ let oldest;
917
+ let start = 0;
918
+ for (let i = 0; i < scrollHistory.length - 1; i++) {
919
+ const entry = scrollHistory[i];
920
+ const nextEntry = scrollHistory[i + 1];
921
+ if (i > 0) {
922
+ const prevEntry = scrollHistory[i - 1];
923
+ const prevDirection = entry.scroll - prevEntry.scroll;
924
+ const currentDirection = nextEntry.scroll - entry.scroll;
925
+ if (prevDirection > 0 && currentDirection < 0 || prevDirection < 0 && currentDirection > 0) {
926
+ start = i;
927
+ break;
928
+ }
929
+ }
930
+ }
931
+ for (let i = start; i < scrollHistory.length - 1; i++) {
932
+ const entry = scrollHistory[i];
933
+ if (newest.time - entry.time <= 1e3) {
934
+ oldest = entry;
935
+ break;
936
+ }
937
+ }
938
+ if (oldest) {
939
+ const scrollDiff = newest.scroll - oldest.scroll;
940
+ const timeDiff = newest.time - oldest.time;
941
+ velocity = timeDiff > 0 ? scrollDiff / timeDiff : 0;
942
+ }
943
+ }
944
+ return velocity;
945
+ };
946
+
947
+ // src/utils/updateSnapToOffsets.ts
948
+ function updateSnapToOffsets(ctx, state) {
949
+ const {
950
+ positions,
951
+ props: { snapToIndices }
952
+ } = state;
953
+ const snapToOffsets = Array(snapToIndices.length);
954
+ for (let i = 0; i < snapToIndices.length; i++) {
955
+ const idx = snapToIndices[i];
956
+ const key = getId(state, idx);
957
+ snapToOffsets[i] = positions.get(key);
958
+ }
959
+ set$(ctx, "snapToOffsets", snapToOffsets);
960
+ }
961
+
962
+ // src/core/updateAllPositions.ts
1170
963
  function updateAllPositions(ctx, state, dataChanged) {
1171
964
  var _a, _b, _c, _d, _e;
1172
- const { averageSizes, columns, indexByKey, positions, firstFullyOnScreenIndex, idCache, sizesKnown } = state;
965
+ const {
966
+ averageSizes,
967
+ columns,
968
+ indexByKey,
969
+ positions,
970
+ firstFullyOnScreenIndex,
971
+ idCache,
972
+ sizesKnown,
973
+ props: { snapToIndices }
974
+ } = state;
1173
975
  const data = state.props.data;
1174
976
  const numColumns = peek$(ctx, "numColumns");
1175
977
  const indexByKeyForChecking = __DEV__ ? /* @__PURE__ */ new Map() : void 0;
@@ -1249,9 +1051,12 @@ function updateAllPositions(ctx, state, dataChanged) {
1249
1051
  }
1250
1052
  }
1251
1053
  updateTotalSize(ctx, state);
1054
+ if (snapToIndices) {
1055
+ updateSnapToOffsets(ctx, state);
1056
+ }
1252
1057
  }
1253
1058
 
1254
- // src/viewability.ts
1059
+ // src/core/viewability.ts
1255
1060
  var mapViewabilityConfigCallbackPairs = /* @__PURE__ */ new Map();
1256
1061
  function setupViewability(props) {
1257
1062
  let { viewabilityConfig, viewabilityConfigCallbackPairs, onViewableItemsChanged } = props;
@@ -1259,27 +1064,31 @@ function setupViewability(props) {
1259
1064
  viewabilityConfigCallbackPairs = [
1260
1065
  ...viewabilityConfigCallbackPairs || [],
1261
1066
  {
1067
+ onViewableItemsChanged,
1262
1068
  viewabilityConfig: viewabilityConfig || {
1263
1069
  viewAreaCoveragePercentThreshold: 0
1264
- },
1265
- onViewableItemsChanged
1070
+ }
1266
1071
  }
1267
1072
  ];
1268
1073
  }
1269
1074
  if (viewabilityConfigCallbackPairs) {
1270
1075
  for (const pair of viewabilityConfigCallbackPairs) {
1271
1076
  mapViewabilityConfigCallbackPairs.set(pair.viewabilityConfig.id, {
1272
- viewableItems: [],
1273
- start: -1,
1274
1077
  end: -1,
1078
+ previousEnd: -1,
1275
1079
  previousStart: -1,
1276
- previousEnd: -1
1080
+ start: -1,
1081
+ viewableItems: []
1277
1082
  });
1278
1083
  }
1279
1084
  }
1280
1085
  return viewabilityConfigCallbackPairs;
1281
1086
  }
1282
1087
  function updateViewableItems(state, ctx, viewabilityConfigCallbackPairs, scrollSize, start, end) {
1088
+ const {
1089
+ timeouts,
1090
+ props: { data }
1091
+ } = state;
1283
1092
  for (const viewabilityConfigCallbackPair of viewabilityConfigCallbackPairs) {
1284
1093
  const viewabilityState = mapViewabilityConfigCallbackPairs.get(
1285
1094
  viewabilityConfigCallbackPair.viewabilityConfig.id
@@ -1288,12 +1097,12 @@ function updateViewableItems(state, ctx, viewabilityConfigCallbackPairs, scrollS
1288
1097
  viewabilityState.end = end;
1289
1098
  if (viewabilityConfigCallbackPair.viewabilityConfig.minimumViewTime) {
1290
1099
  const timer = setTimeout(() => {
1291
- state.timeouts.delete(timer);
1292
- updateViewableItemsWithConfig(state.data, viewabilityConfigCallbackPair, state, ctx, scrollSize);
1100
+ timeouts.delete(timer);
1101
+ updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, state, ctx, scrollSize);
1293
1102
  }, viewabilityConfigCallbackPair.viewabilityConfig.minimumViewTime);
1294
- state.timeouts.add(timer);
1103
+ timeouts.add(timer);
1295
1104
  } else {
1296
- updateViewableItemsWithConfig(state.data, viewabilityConfigCallbackPair, state, ctx, scrollSize);
1105
+ updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, state, ctx, scrollSize);
1297
1106
  }
1298
1107
  }
1299
1108
  }
@@ -1345,11 +1154,11 @@ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, stat
1345
1154
  const containerId = findContainerId(ctx, key);
1346
1155
  if (isViewable(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, i)) {
1347
1156
  const viewToken = {
1348
- item,
1349
- key,
1157
+ containerId,
1350
1158
  index: i,
1351
1159
  isViewable: true,
1352
- containerId
1160
+ item,
1161
+ key
1353
1162
  };
1354
1163
  viewableItems.push(viewToken);
1355
1164
  if (!(previousViewableItems == null ? void 0 : previousViewableItems.find((v) => v.key === viewToken.key))) {
@@ -1359,9 +1168,9 @@ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, stat
1359
1168
  }
1360
1169
  }
1361
1170
  Object.assign(viewabilityState, {
1362
- viewableItems,
1171
+ previousEnd: end,
1363
1172
  previousStart: start,
1364
- previousEnd: end
1173
+ viewableItems
1365
1174
  });
1366
1175
  if (changed.length > 0) {
1367
1176
  viewabilityState.viewableItems = viewableItems;
@@ -1370,74 +1179,284 @@ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, stat
1370
1179
  maybeUpdateViewabilityCallback(ctx, configId, change.containerId, change);
1371
1180
  }
1372
1181
  if (onViewableItemsChanged) {
1373
- onViewableItemsChanged({ viewableItems, changed });
1182
+ onViewableItemsChanged({ changed, viewableItems });
1183
+ }
1184
+ }
1185
+ for (const [containerId, value] of ctx.mapViewabilityAmountValues) {
1186
+ if (value.sizeVisible < 0) {
1187
+ ctx.mapViewabilityAmountValues.delete(containerId);
1188
+ }
1189
+ }
1190
+ }
1191
+ function computeViewability(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index) {
1192
+ const { sizes, positions, scroll: scrollState } = state;
1193
+ const topPad = (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "headerSize") || 0);
1194
+ const { itemVisiblePercentThreshold, viewAreaCoveragePercentThreshold } = viewabilityConfig;
1195
+ const viewAreaMode = viewAreaCoveragePercentThreshold != null;
1196
+ const viewablePercentThreshold = viewAreaMode ? viewAreaCoveragePercentThreshold : itemVisiblePercentThreshold;
1197
+ const scroll = scrollState - topPad;
1198
+ const top = positions.get(key) - scroll;
1199
+ const size = sizes.get(key) || 0;
1200
+ const bottom = top + size;
1201
+ const isEntirelyVisible = top >= 0 && bottom <= scrollSize && bottom > top;
1202
+ const sizeVisible = isEntirelyVisible ? size : Math.min(bottom, scrollSize) - Math.max(top, 0);
1203
+ const percentVisible = size ? isEntirelyVisible ? 100 : 100 * (sizeVisible / size) : 0;
1204
+ const percentOfScroller = size ? 100 * (sizeVisible / scrollSize) : 0;
1205
+ const percent = isEntirelyVisible ? 100 : viewAreaMode ? percentOfScroller : percentVisible;
1206
+ const isViewable2 = percent >= viewablePercentThreshold;
1207
+ const value = {
1208
+ containerId,
1209
+ index,
1210
+ isViewable: isViewable2,
1211
+ item,
1212
+ key,
1213
+ percentOfScroller,
1214
+ percentVisible,
1215
+ scrollSize,
1216
+ size,
1217
+ sizeVisible
1218
+ };
1219
+ if (JSON.stringify(value) !== JSON.stringify(ctx.mapViewabilityAmountValues.get(containerId))) {
1220
+ ctx.mapViewabilityAmountValues.set(containerId, value);
1221
+ const cb = ctx.mapViewabilityAmountCallbacks.get(containerId);
1222
+ if (cb) {
1223
+ cb(value);
1224
+ }
1225
+ }
1226
+ return value;
1227
+ }
1228
+ function isViewable(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index) {
1229
+ const value = ctx.mapViewabilityAmountValues.get(containerId) || computeViewability(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index);
1230
+ return value.isViewable;
1231
+ }
1232
+ function findContainerId(ctx, key) {
1233
+ const numContainers = peek$(ctx, "numContainers");
1234
+ for (let i = 0; i < numContainers; i++) {
1235
+ const itemKey = peek$(ctx, `containerItemKey${i}`);
1236
+ if (itemKey === key) {
1237
+ return i;
1238
+ }
1239
+ }
1240
+ return -1;
1241
+ }
1242
+ function maybeUpdateViewabilityCallback(ctx, configId, containerId, viewToken) {
1243
+ const key = containerId + configId;
1244
+ ctx.mapViewabilityValues.set(key, viewToken);
1245
+ const cb = ctx.mapViewabilityCallbacks.get(key);
1246
+ cb == null ? void 0 : cb(viewToken);
1247
+ }
1248
+
1249
+ // src/utils/checkAllSizesKnown.ts
1250
+ function checkAllSizesKnown(state) {
1251
+ const { startBuffered, endBuffered, sizesKnown } = state;
1252
+ if (endBuffered !== null) {
1253
+ let areAllKnown = true;
1254
+ for (let i = startBuffered; areAllKnown && i <= endBuffered; i++) {
1255
+ const key = getId(state, i);
1256
+ areAllKnown && (areAllKnown = sizesKnown.has(key));
1257
+ }
1258
+ return areAllKnown;
1259
+ }
1260
+ return false;
1261
+ }
1262
+
1263
+ // src/utils/findAvailableContainers.ts
1264
+ function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffered, pendingRemoval) {
1265
+ const numContainers = peek$(ctx, "numContainers");
1266
+ const result = [];
1267
+ const availableContainers = [];
1268
+ for (let u = 0; u < numContainers; u++) {
1269
+ const key = peek$(ctx, `containerItemKey${u}`);
1270
+ let isOk = key === void 0;
1271
+ if (!isOk) {
1272
+ const index = pendingRemoval.indexOf(u);
1273
+ if (index !== -1) {
1274
+ pendingRemoval.splice(index, 1);
1275
+ isOk = true;
1276
+ }
1277
+ }
1278
+ if (isOk) {
1279
+ result.push(u);
1280
+ if (result.length >= numNeeded) {
1281
+ return result;
1282
+ }
1283
+ }
1284
+ }
1285
+ for (let u = 0; u < numContainers; u++) {
1286
+ const key = peek$(ctx, `containerItemKey${u}`);
1287
+ if (key === void 0) continue;
1288
+ const index = state.indexByKey.get(key);
1289
+ if (index < startBuffered) {
1290
+ availableContainers.push({ distance: startBuffered - index, index: u });
1291
+ } else if (index > endBuffered) {
1292
+ availableContainers.push({ distance: index - endBuffered, index: u });
1374
1293
  }
1375
1294
  }
1376
- for (const [containerId, value] of ctx.mapViewabilityAmountValues) {
1377
- if (value.sizeVisible < 0) {
1378
- ctx.mapViewabilityAmountValues.delete(containerId);
1295
+ const remaining = numNeeded - result.length;
1296
+ if (remaining > 0) {
1297
+ if (availableContainers.length > 0) {
1298
+ if (availableContainers.length > remaining) {
1299
+ availableContainers.sort(comparatorByDistance);
1300
+ availableContainers.length = remaining;
1301
+ }
1302
+ for (const container of availableContainers) {
1303
+ result.push(container.index);
1304
+ }
1305
+ }
1306
+ const stillNeeded = numNeeded - result.length;
1307
+ if (stillNeeded > 0) {
1308
+ for (let i = 0; i < stillNeeded; i++) {
1309
+ result.push(numContainers + i);
1310
+ }
1311
+ if (__DEV__ && numContainers + stillNeeded > peek$(ctx, "numContainersPooled")) {
1312
+ console.warn(
1313
+ "[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.",
1314
+ {
1315
+ debugInfo: {
1316
+ numContainers,
1317
+ numContainersPooled: peek$(ctx, "numContainersPooled"),
1318
+ numNeeded,
1319
+ stillNeeded
1320
+ }
1321
+ }
1322
+ );
1323
+ }
1379
1324
  }
1380
1325
  }
1326
+ return result.sort(comparatorDefault);
1381
1327
  }
1382
- function computeViewability(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index) {
1383
- const { sizes, positions, scroll: scrollState } = state;
1384
- const topPad = (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "headerSize") || 0);
1385
- const { itemVisiblePercentThreshold, viewAreaCoveragePercentThreshold } = viewabilityConfig;
1386
- const viewAreaMode = viewAreaCoveragePercentThreshold != null;
1387
- const viewablePercentThreshold = viewAreaMode ? viewAreaCoveragePercentThreshold : itemVisiblePercentThreshold;
1388
- const scroll = scrollState - topPad;
1389
- const top = positions.get(key) - scroll;
1390
- const size = sizes.get(key) || 0;
1391
- const bottom = top + size;
1392
- const isEntirelyVisible = top >= 0 && bottom <= scrollSize && bottom > top;
1393
- const sizeVisible = isEntirelyVisible ? size : Math.min(bottom, scrollSize) - Math.max(top, 0);
1394
- const percentVisible = size ? isEntirelyVisible ? 100 : 100 * (sizeVisible / size) : 0;
1395
- const percentOfScroller = size ? 100 * (sizeVisible / scrollSize) : 0;
1396
- const percent = isEntirelyVisible ? 100 : viewAreaMode ? percentOfScroller : percentVisible;
1397
- const isViewable2 = percent >= viewablePercentThreshold;
1398
- const value = {
1399
- index,
1400
- isViewable: isViewable2,
1401
- item,
1402
- key,
1403
- percentVisible,
1404
- percentOfScroller,
1405
- sizeVisible,
1406
- size,
1407
- scrollSize,
1408
- containerId
1409
- };
1410
- if (JSON.stringify(value) !== JSON.stringify(ctx.mapViewabilityAmountValues.get(containerId))) {
1411
- ctx.mapViewabilityAmountValues.set(containerId, value);
1412
- const cb = ctx.mapViewabilityAmountCallbacks.get(containerId);
1413
- if (cb) {
1414
- cb(value);
1415
- }
1328
+ function comparatorByDistance(a, b) {
1329
+ return b.distance - a.distance;
1330
+ }
1331
+
1332
+ // src/core/finishScrollTo.ts
1333
+ var finishScrollTo = (state) => {
1334
+ if (state) {
1335
+ state.scrollingTo = void 0;
1336
+ state.scrollHistory.length = 0;
1337
+ }
1338
+ };
1339
+
1340
+ // src/core/scrollTo.ts
1341
+ function scrollTo(state, params = {}) {
1342
+ var _a;
1343
+ const { animated } = params;
1344
+ const {
1345
+ refScroller,
1346
+ props: { horizontal }
1347
+ } = state;
1348
+ const offset = calculateOffsetWithOffsetPosition(state, params.offset, params);
1349
+ state.scrollHistory.length = 0;
1350
+ state.scrollingTo = params;
1351
+ state.scrollPending = offset;
1352
+ (_a = refScroller.current) == null ? void 0 : _a.scrollTo({
1353
+ animated: !!animated,
1354
+ x: horizontal ? offset : 0,
1355
+ y: horizontal ? 0 : offset
1356
+ });
1357
+ if (!animated) {
1358
+ state.scroll = offset;
1359
+ setTimeout(() => finishScrollTo(state), 100);
1416
1360
  }
1417
- return value;
1418
1361
  }
1419
- function isViewable(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index) {
1420
- const value = ctx.mapViewabilityAmountValues.get(containerId) || computeViewability(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index);
1421
- return value.isViewable;
1362
+
1363
+ // src/core/scrollToIndex.ts
1364
+ function scrollToIndex(ctx, state, { index, viewOffset = 0, animated = true, viewPosition }) {
1365
+ if (index >= state.props.data.length) {
1366
+ index = state.props.data.length - 1;
1367
+ } else if (index < 0) {
1368
+ index = 0;
1369
+ }
1370
+ const firstIndexOffset = calculateOffsetForIndex(ctx, state, index);
1371
+ const isLast = index === state.props.data.length - 1;
1372
+ if (isLast && viewPosition === void 0) {
1373
+ viewPosition = 1;
1374
+ }
1375
+ const firstIndexScrollPostion = firstIndexOffset - viewOffset;
1376
+ state.scrollForNextCalculateItemsInView = void 0;
1377
+ scrollTo(state, {
1378
+ animated,
1379
+ index,
1380
+ offset: firstIndexScrollPostion,
1381
+ viewOffset,
1382
+ viewPosition: viewPosition != null ? viewPosition : 0
1383
+ });
1422
1384
  }
1423
- function findContainerId(ctx, key) {
1424
- const numContainers = peek$(ctx, "numContainers");
1425
- for (let i = 0; i < numContainers; i++) {
1426
- const itemKey = peek$(ctx, `containerItemKey${i}`);
1427
- if (itemKey === key) {
1428
- return i;
1385
+
1386
+ // src/utils/checkThreshold.ts
1387
+ var checkThreshold = (distance, atThreshold, threshold, isReached, isBlockedByTimer, onReached, blockTimer) => {
1388
+ const distanceAbs = Math.abs(distance);
1389
+ const isAtThreshold = atThreshold || distanceAbs < threshold;
1390
+ if (!isReached && !isBlockedByTimer) {
1391
+ if (isAtThreshold) {
1392
+ onReached == null ? void 0 : onReached(distance);
1393
+ blockTimer == null ? void 0 : blockTimer(true);
1394
+ setTimeout(() => {
1395
+ blockTimer == null ? void 0 : blockTimer(false);
1396
+ }, 700);
1397
+ return true;
1398
+ }
1399
+ } else {
1400
+ if (distance >= 1.3 * threshold) {
1401
+ return false;
1429
1402
  }
1430
1403
  }
1431
- return -1;
1404
+ return isReached;
1405
+ };
1406
+
1407
+ // src/utils/checkAtBottom.ts
1408
+ function checkAtBottom(ctx, state) {
1409
+ if (!state) {
1410
+ return;
1411
+ }
1412
+ const {
1413
+ queuedInitialLayout,
1414
+ scrollLength,
1415
+ scroll,
1416
+ maintainingScrollAtEnd,
1417
+ props: { maintainScrollAtEndThreshold, onEndReachedThreshold }
1418
+ } = state;
1419
+ const contentSize = getContentSize(ctx);
1420
+ if (contentSize > 0 && queuedInitialLayout && !maintainingScrollAtEnd) {
1421
+ const distanceFromEnd = contentSize - scroll - scrollLength;
1422
+ const isContentLess = contentSize < scrollLength;
1423
+ state.isAtEnd = isContentLess || distanceFromEnd < scrollLength * maintainScrollAtEndThreshold;
1424
+ state.isEndReached = checkThreshold(
1425
+ distanceFromEnd,
1426
+ isContentLess,
1427
+ onEndReachedThreshold * scrollLength,
1428
+ state.isEndReached,
1429
+ state.endReachedBlockedByTimer,
1430
+ (distance) => {
1431
+ var _a, _b;
1432
+ return (_b = (_a = state.props).onEndReached) == null ? void 0 : _b.call(_a, { distanceFromEnd: distance });
1433
+ },
1434
+ (block) => {
1435
+ state.endReachedBlockedByTimer = block;
1436
+ }
1437
+ );
1438
+ }
1432
1439
  }
1433
- function maybeUpdateViewabilityCallback(ctx, configId, containerId, viewToken) {
1434
- const key = containerId + configId;
1435
- ctx.mapViewabilityValues.set(key, viewToken);
1436
- const cb = ctx.mapViewabilityCallbacks.get(key);
1437
- cb == null ? void 0 : cb(viewToken);
1440
+
1441
+ // src/utils/setDidLayout.ts
1442
+ function setDidLayout(ctx, state) {
1443
+ const {
1444
+ loadStartTime,
1445
+ initialScroll,
1446
+ props: { onLoad }
1447
+ } = state;
1448
+ state.queuedInitialLayout = true;
1449
+ checkAtBottom(ctx, state);
1450
+ if (!IsNewArchitecture && initialScroll) {
1451
+ scrollToIndex(ctx, state, { ...initialScroll, animated: false });
1452
+ }
1453
+ set$(ctx, "containersDidLayout", true);
1454
+ if (onLoad) {
1455
+ onLoad({ elapsedTimeInMs: Date.now() - loadStartTime });
1456
+ }
1438
1457
  }
1439
1458
 
1440
- // src/calculateItemsInView.ts
1459
+ // src/core/calculateItemsInView.ts
1441
1460
  function calculateItemsInView(ctx, state, params = {}) {
1442
1461
  var _a, _b, _c, _d, _e, _f, _g, _h;
1443
1462
  const {
@@ -1454,7 +1473,8 @@ function calculateItemsInView(ctx, state, params = {}) {
1454
1473
  minIndexSizeChanged
1455
1474
  } = state;
1456
1475
  const data = state.props.data;
1457
- if (!data || scrollLength === 0) {
1476
+ const prevNumContainers = peek$(ctx, "numContainers");
1477
+ if (!data || scrollLength === 0 || !prevNumContainers) {
1458
1478
  return;
1459
1479
  }
1460
1480
  const totalSize = peek$(ctx, "totalSize");
@@ -1536,7 +1556,6 @@ function calculateItemsInView(ctx, state, params = {}) {
1536
1556
  let foundEnd = false;
1537
1557
  let nextTop;
1538
1558
  let nextBottom;
1539
- const prevNumContainers = ctx.values.get("numContainers");
1540
1559
  let maxIndexRendered = 0;
1541
1560
  for (let i = 0; i < prevNumContainers; i++) {
1542
1561
  const key = peek$(ctx, `containerItemKey${i}`);
@@ -1582,18 +1601,18 @@ function calculateItemsInView(ctx, state, params = {}) {
1582
1601
  idsInView.push(id);
1583
1602
  }
1584
1603
  Object.assign(state, {
1585
- startBuffered,
1586
- startBufferedId,
1587
- startNoBuffer,
1588
1604
  endBuffered,
1589
1605
  endNoBuffer,
1606
+ firstFullyOnScreenIndex,
1590
1607
  idsInView,
1591
- firstFullyOnScreenIndex
1608
+ startBuffered,
1609
+ startBufferedId,
1610
+ startNoBuffer
1592
1611
  });
1593
1612
  if (enableScrollForNextCalculateItemsInView && nextTop !== void 0 && nextBottom !== void 0) {
1594
1613
  state.scrollForNextCalculateItemsInView = nextTop !== void 0 && nextBottom !== void 0 ? {
1595
- top: nextTop,
1596
- bottom: nextBottom
1614
+ bottom: nextBottom,
1615
+ top: nextTop
1597
1616
  } : void 0;
1598
1617
  }
1599
1618
  const numContainers = peek$(ctx, "numContainers");
@@ -1680,71 +1699,28 @@ function calculateItemsInView(ctx, state, params = {}) {
1680
1699
  if (prevData !== item) {
1681
1700
  set$(ctx, `containerItemData${i}`, data[itemIndex]);
1682
1701
  }
1683
- }
1684
- }
1685
- }
1686
- }
1687
- if (!queuedInitialLayout && endBuffered !== null) {
1688
- if (checkAllSizesKnown(state)) {
1689
- setDidLayout(ctx, state);
1690
- }
1691
- }
1692
- if (state.props.viewabilityConfigCallbackPairs) {
1693
- updateViewableItems(
1694
- state,
1695
- ctx,
1696
- state.props.viewabilityConfigCallbackPairs,
1697
- scrollLength,
1698
- startNoBuffer,
1699
- endNoBuffer
1700
- );
1701
- }
1702
- }
1703
-
1704
- // src/checkAtTop.ts
1705
- function checkAtTop(state) {
1706
- if (!state) {
1707
- return;
1708
- }
1709
- const {
1710
- scrollLength,
1711
- scroll,
1712
- props: { onStartReachedThreshold }
1713
- } = 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
- };
1702
+ }
1703
+ }
1704
+ }
1705
+ }
1706
+ if (!queuedInitialLayout && endBuffered !== null) {
1707
+ if (checkAllSizesKnown(state)) {
1708
+ setDidLayout(ctx, state);
1709
+ }
1710
+ }
1711
+ if (state.props.viewabilityConfigCallbackPairs) {
1712
+ updateViewableItems(
1713
+ state,
1714
+ ctx,
1715
+ state.props.viewabilityConfigCallbackPairs,
1716
+ scrollLength,
1717
+ startNoBuffer,
1718
+ endNoBuffer
1719
+ );
1744
1720
  }
1745
1721
  }
1746
1722
 
1747
- // src/doInitialAllocateContainers.ts
1723
+ // src/core/doInitialAllocateContainers.ts
1748
1724
  function doInitialAllocateContainers(ctx, state) {
1749
1725
  const { scrollLength } = state;
1750
1726
  const data = state.props.data;
@@ -1773,7 +1749,7 @@ function doInitialAllocateContainers(ctx, state) {
1773
1749
  }
1774
1750
  }
1775
1751
 
1776
- // src/doMaintainScrollAtEnd.ts
1752
+ // src/core/doMaintainScrollAtEnd.ts
1777
1753
  function doMaintainScrollAtEnd(ctx, state, animated) {
1778
1754
  const {
1779
1755
  refScroller,
@@ -1800,31 +1776,36 @@ function doMaintainScrollAtEnd(ctx, state, animated) {
1800
1776
  return true;
1801
1777
  }
1802
1778
  }
1803
- function getRenderedItem(ctx, state, key) {
1779
+
1780
+ // src/utils/checkAtTop.ts
1781
+ function checkAtTop(state) {
1804
1782
  if (!state) {
1805
- return null;
1783
+ return;
1806
1784
  }
1807
1785
  const {
1808
- indexByKey,
1809
- props: { data, renderItem: renderItem2 }
1786
+ scrollLength,
1787
+ scroll,
1788
+ props: { onStartReachedThreshold }
1810
1789
  } = 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 };
1790
+ const distanceFromTop = scroll;
1791
+ state.isAtStart = distanceFromTop <= 0;
1792
+ state.isStartReached = checkThreshold(
1793
+ distanceFromTop,
1794
+ false,
1795
+ onStartReachedThreshold * scrollLength,
1796
+ state.isStartReached,
1797
+ state.startReachedBlockedByTimer,
1798
+ (distance) => {
1799
+ var _a, _b;
1800
+ return (_b = (_a = state.props).onStartReached) == null ? void 0 : _b.call(_a, { distanceFromStart: distance });
1801
+ },
1802
+ (block) => {
1803
+ state.startReachedBlockedByTimer = block;
1804
+ }
1805
+ );
1825
1806
  }
1826
1807
 
1827
- // src/handleLayout.ts
1808
+ // src/core/handleLayout.ts
1828
1809
  function handleLayout(ctx, state, layout, setCanRender) {
1829
1810
  const { maintainScrollAtEnd } = state.props;
1830
1811
  const scrollLength = layout[state.props.horizontal ? "width" : "height"];
@@ -1842,7 +1823,7 @@ function handleLayout(ctx, state, layout, setCanRender) {
1842
1823
  calculateItemsInView(ctx, state, { doMVCP: true });
1843
1824
  }
1844
1825
  if (didChange || otherAxisSize !== prevOtherAxisSize) {
1845
- set$(ctx, "scrollSize", { width: layout.width, height: layout.height });
1826
+ set$(ctx, "scrollSize", { height: layout.height, width: layout.width });
1846
1827
  }
1847
1828
  if (maintainScrollAtEnd === true || maintainScrollAtEnd.onLayout) {
1848
1829
  doMaintainScrollAtEnd(ctx, state, false);
@@ -1862,7 +1843,7 @@ function handleLayout(ctx, state, layout, setCanRender) {
1862
1843
  setCanRender(true);
1863
1844
  }
1864
1845
 
1865
- // src/onScroll.ts
1846
+ // src/core/onScroll.ts
1866
1847
  function onScroll(ctx, state, event) {
1867
1848
  var _a, _b, _c, _d, _e;
1868
1849
  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) {
@@ -1900,7 +1881,29 @@ function updateScroll(ctx, state, newScroll) {
1900
1881
  checkAtTop(state);
1901
1882
  }
1902
1883
 
1903
- // src/updateItemSize.ts
1884
+ // src/core/ScrollAdjustHandler.ts
1885
+ var ScrollAdjustHandler = class {
1886
+ constructor(ctx) {
1887
+ this.appliedAdjust = 0;
1888
+ this.mounted = false;
1889
+ this.context = ctx;
1890
+ }
1891
+ requestAdjust(add) {
1892
+ const oldAdjustTop = peek$(this.context, "scrollAdjust") || 0;
1893
+ this.appliedAdjust = add + oldAdjustTop;
1894
+ const set = () => set$(this.context, "scrollAdjust", this.appliedAdjust);
1895
+ if (this.mounted) {
1896
+ set();
1897
+ } else {
1898
+ requestAnimationFrame(set);
1899
+ }
1900
+ }
1901
+ setMounted() {
1902
+ this.mounted = true;
1903
+ }
1904
+ };
1905
+
1906
+ // src/core/updateItemSize.ts
1904
1907
  function updateItemSizes(ctx, state, itemUpdates) {
1905
1908
  var _a;
1906
1909
  const {
@@ -1914,7 +1917,8 @@ function updateItemSizes(ctx, state, itemUpdates) {
1914
1917
  }
1915
1918
  } = state;
1916
1919
  if (!data) return;
1917
- let needsRecalculate = false;
1920
+ const containersDidLayout = peek$(ctx, "containersDidLayout");
1921
+ let needsRecalculate = !containersDidLayout;
1918
1922
  let shouldMaintainScrollAtEnd = false;
1919
1923
  let minIndexSizeChanged;
1920
1924
  let maxOtherAxisSize = peek$(ctx, "otherAxisSize") || 0;
@@ -1925,7 +1929,7 @@ function updateItemSizes(ctx, state, itemUpdates) {
1925
1929
  const size = Math.floor((horizontal ? sizeObj.width : sizeObj.height) * 8) / 8;
1926
1930
  if (diff !== 0) {
1927
1931
  minIndexSizeChanged = minIndexSizeChanged !== void 0 ? Math.min(minIndexSizeChanged, index) : index;
1928
- if (((_a = state.scrollingTo) == null ? void 0 : _a.viewPosition) && maintainVisibleContentPosition && index === state.scrollingTo.index) {
1932
+ if (((_a = state.scrollingTo) == null ? void 0 : _a.viewPosition) && maintainVisibleContentPosition && index === state.scrollingTo.index && diff > 0) {
1929
1933
  requestAdjust(ctx, state, diff * state.scrollingTo.viewPosition);
1930
1934
  }
1931
1935
  const { startBuffered, endBuffered } = state;
@@ -1947,11 +1951,11 @@ function updateItemSizes(ctx, state, itemUpdates) {
1947
1951
  shouldMaintainScrollAtEnd = true;
1948
1952
  }
1949
1953
  onItemSizeChanged == null ? void 0 : onItemSizeChanged({
1950
- size,
1951
- previous: size - diff,
1952
1954
  index,
1955
+ itemData: state.props.data[index],
1953
1956
  itemKey,
1954
- itemData: state.props.data[index]
1957
+ previous: size - diff,
1958
+ size
1955
1959
  });
1956
1960
  }
1957
1961
  }
@@ -1974,7 +1978,6 @@ function updateItemSizes(ctx, state, itemUpdates) {
1974
1978
  if (!cur || maxOtherAxisSize > cur) {
1975
1979
  set$(ctx, "otherAxisSize", maxOtherAxisSize);
1976
1980
  }
1977
- const containersDidLayout = peek$(ctx, "containersDidLayout");
1978
1981
  if (containersDidLayout || checkAllSizesKnown(state)) {
1979
1982
  if (needsRecalculate) {
1980
1983
  state.scrollForNextCalculateItemsInView = void 0;
@@ -1990,7 +1993,7 @@ function updateItemSizes(ctx, state, itemUpdates) {
1990
1993
  function updateItemSize(ctx, state, itemKey, sizeObj) {
1991
1994
  if (IsNewArchitecture) {
1992
1995
  const { sizesKnown } = state;
1993
- const numContainers = ctx.values.get("numContainers");
1996
+ const numContainers = peek$(ctx, "numContainers");
1994
1997
  const changes = [];
1995
1998
  for (let i = 0; i < numContainers; i++) {
1996
1999
  const containerItemKey = peek$(ctx, `containerItemKey${i}`);
@@ -2001,7 +2004,7 @@ function updateItemSize(ctx, state, itemKey, sizeObj) {
2001
2004
  if (containerRef == null ? void 0 : containerRef.current) {
2002
2005
  let measured;
2003
2006
  containerRef.current.measure((x, y, width, height) => {
2004
- measured = { x, y, width, height };
2007
+ measured = { height, width, x, y };
2005
2008
  });
2006
2009
  if (measured) {
2007
2010
  changes.push({ itemKey: containerItemKey, sizeObj: measured });
@@ -2032,7 +2035,7 @@ function updateOneItemSize(state, itemKey, sizeObj) {
2032
2035
  const itemType = "";
2033
2036
  let averages = averageSizes[itemType];
2034
2037
  if (!averages) {
2035
- averages = averageSizes[itemType] = { num: 0, avg: 0 };
2038
+ averages = averageSizes[itemType] = { avg: 0, num: 0 };
2036
2039
  }
2037
2040
  averages.avg = (averages.avg * averages.num + size) / (averages.num + 1);
2038
2041
  averages.num++;
@@ -2058,7 +2061,45 @@ var useCombinedRef = (...refs) => {
2058
2061
  return callback;
2059
2062
  };
2060
2063
 
2061
- // src/LegendList.tsx
2064
+ // src/utils/createColumnWrapperStyle.ts
2065
+ function createColumnWrapperStyle(contentContainerStyle) {
2066
+ const { gap, columnGap, rowGap } = contentContainerStyle;
2067
+ if (gap || columnGap || rowGap) {
2068
+ contentContainerStyle.gap = void 0;
2069
+ contentContainerStyle.columnGap = void 0;
2070
+ contentContainerStyle.rowGap = void 0;
2071
+ return {
2072
+ columnGap,
2073
+ gap,
2074
+ rowGap
2075
+ };
2076
+ }
2077
+ }
2078
+ function getRenderedItem(ctx, state, key) {
2079
+ if (!state) {
2080
+ return null;
2081
+ }
2082
+ const {
2083
+ indexByKey,
2084
+ props: { data, renderItem: renderItem2 }
2085
+ } = state;
2086
+ const index = indexByKey.get(key);
2087
+ if (index === void 0) {
2088
+ return null;
2089
+ }
2090
+ let renderedItem = null;
2091
+ if (renderItem2) {
2092
+ const itemProps = {
2093
+ extraData: peek$(ctx, "extraData"),
2094
+ index,
2095
+ item: data[index]
2096
+ };
2097
+ renderedItem = React3__default.createElement(renderItem2, itemProps);
2098
+ }
2099
+ return { index, item: data[index], renderedItem };
2100
+ }
2101
+
2102
+ // src/components/LegendList.tsx
2062
2103
  var DEFAULT_DRAW_DISTANCE = 250;
2063
2104
  var DEFAULT_ITEM_SIZE = 100;
2064
2105
  var LegendList = typedForwardRef(function LegendList2(props, forwardedRef) {
@@ -2105,6 +2146,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2105
2146
  initialContainerPoolRatio = 2,
2106
2147
  viewabilityConfig,
2107
2148
  viewabilityConfigCallbackPairs,
2149
+ snapToIndices,
2108
2150
  onViewableItemsChanged,
2109
2151
  onStartReached,
2110
2152
  onEndReached,
@@ -2125,55 +2167,55 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2125
2167
  const combinedRef = useCombinedRef(refScroller, refScrollView);
2126
2168
  const estimatedItemSize = estimatedItemSizeProp != null ? estimatedItemSizeProp : DEFAULT_ITEM_SIZE;
2127
2169
  const scrollBuffer = (drawDistance != null ? drawDistance : DEFAULT_DRAW_DISTANCE) || 1;
2128
- const keyExtractor = keyExtractorProp != null ? keyExtractorProp : (item, index) => index.toString();
2170
+ const keyExtractor = keyExtractorProp != null ? keyExtractorProp : (_item, index) => index.toString();
2129
2171
  const refState = useRef();
2130
2172
  if (!refState.current) {
2131
- const initialScrollLength = (estimatedListSize != null ? estimatedListSize : IsNewArchitecture ? { width: 0, height: 0 } : Dimensions.get("window"))[horizontal ? "width" : "height"];
2173
+ const initialScrollLength = (estimatedListSize != null ? estimatedListSize : IsNewArchitecture ? { height: 0, width: 0 } : Dimensions.get("window"))[horizontal ? "width" : "height"];
2132
2174
  refState.current = {
2133
- sizes: /* @__PURE__ */ new Map(),
2134
- positions: /* @__PURE__ */ new Map(),
2175
+ averageSizes: {},
2135
2176
  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,
2177
+ containerItemKeys: /* @__PURE__ */ new Set(),
2178
+ enableScrollForNextCalculateItemsInView: true,
2144
2179
  endBuffered: -1,
2145
2180
  endNoBuffer: -1,
2181
+ endReachedBlockedByTimer: false,
2146
2182
  firstFullyOnScreenIndex: -1,
2183
+ idCache: /* @__PURE__ */ new Map(),
2184
+ idsInView: [],
2185
+ indexByKey: /* @__PURE__ */ new Map(),
2186
+ initialScroll,
2187
+ isAtEnd: false,
2188
+ isAtStart: false,
2189
+ isEndReached: false,
2190
+ isStartReached: false,
2191
+ lastBatchingAction: Date.now(),
2192
+ lastLayout: void 0,
2193
+ loadStartTime: Date.now(),
2194
+ minIndexSizeChanged: 0,
2195
+ nativeMarginTop: 0,
2196
+ pendingAdjust: 0,
2197
+ positions: /* @__PURE__ */ new Map(),
2198
+ props: {},
2199
+ queuedCalculateItemsInView: 0,
2200
+ refScroller: void 0,
2147
2201
  scroll: 0,
2148
- totalSize: 0,
2149
- timeouts: /* @__PURE__ */ new Set(),
2150
- viewabilityConfigCallbackPairs: void 0,
2151
2202
  scrollAdjustHandler: new ScrollAdjustHandler(ctx),
2152
- nativeMarginTop: 0,
2203
+ scrollForNextCalculateItemsInView: void 0,
2204
+ scrollHistory: [],
2205
+ scrollLength: initialScrollLength,
2206
+ scrollPending: 0,
2153
2207
  scrollPrev: 0,
2154
2208
  scrollPrevTime: 0,
2155
2209
  scrollTime: 0,
2156
- scrollPending: 0,
2157
- indexByKey: /* @__PURE__ */ new Map(),
2158
- scrollHistory: [],
2210
+ sizes: /* @__PURE__ */ new Map(),
2159
2211
  sizesKnown: /* @__PURE__ */ new Map(),
2160
- timeoutSizeMessage: 0,
2212
+ startBuffered: -1,
2213
+ startNoBuffer: -1,
2161
2214
  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
2215
+ timeoutSizeMessage: 0,
2216
+ timeouts: /* @__PURE__ */ new Set(),
2217
+ totalSize: 0,
2218
+ viewabilityConfigCallbackPairs: void 0
2177
2219
  };
2178
2220
  set$(ctx, "maintainVisibleContentPosition", maintainVisibleContentPosition);
2179
2221
  set$(ctx, "extraData", extraData);
@@ -2185,28 +2227,29 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2185
2227
  alignItemsAtEnd,
2186
2228
  data: dataProp,
2187
2229
  estimatedItemSize,
2230
+ getEstimatedItemSize,
2231
+ horizontal: !!horizontal,
2232
+ initialContainerPoolRatio,
2233
+ initialScroll,
2234
+ keyExtractor,
2188
2235
  maintainScrollAtEnd,
2189
2236
  maintainScrollAtEndThreshold,
2190
- onEndReachedThreshold,
2191
- onStartReachedThreshold,
2192
- stylePaddingBottom: stylePaddingBottomState,
2193
- horizontal: !!horizontal,
2194
2237
  maintainVisibleContentPosition,
2238
+ numColumns: numColumnsProp,
2239
+ onEndReached,
2240
+ onEndReachedThreshold,
2195
2241
  onItemSizeChanged,
2196
- suggestEstimatedItemSize: !!suggestEstimatedItemSize,
2197
- keyExtractor,
2242
+ onLoad,
2198
2243
  onScroll: onScrollProp,
2199
- getEstimatedItemSize,
2200
2244
  onStartReached,
2201
- onEndReached,
2202
- onLoad,
2245
+ onStartReachedThreshold,
2203
2246
  renderItem: renderItem2,
2204
- initialScroll,
2205
2247
  scrollBuffer,
2206
- viewabilityConfigCallbackPairs: void 0,
2207
- numColumns: numColumnsProp,
2208
- initialContainerPoolRatio,
2209
- stylePaddingTop: stylePaddingTopState
2248
+ snapToIndices,
2249
+ stylePaddingBottom: stylePaddingBottomState,
2250
+ stylePaddingTop: stylePaddingTopState,
2251
+ suggestEstimatedItemSize: !!suggestEstimatedItemSize,
2252
+ viewabilityConfigCallbackPairs: void 0
2210
2253
  };
2211
2254
  state.refScroller = refScroller;
2212
2255
  const checkResetContainers = (isFirst2) => {
@@ -2254,7 +2297,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2254
2297
  const initialContentOffset2 = initialScrollOffset || calculateOffsetForIndex(ctx, state, initialScrollIndex);
2255
2298
  refState.current.isStartReached = initialContentOffset2 < refState.current.scrollLength * onStartReachedThreshold;
2256
2299
  if (initialContentOffset2 > 0) {
2257
- scrollTo(state, { offset: initialContentOffset2, animated: false, index: initialScrollIndex });
2300
+ scrollTo(state, { animated: false, index: initialScrollIndex, offset: initialContentOffset2 });
2258
2301
  }
2259
2302
  return initialContentOffset2;
2260
2303
  }, [renderNum]);
@@ -2273,7 +2316,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2273
2316
  if (IsNewArchitecture) {
2274
2317
  let measured;
2275
2318
  refScroller.current.measure((x, y, width, height) => {
2276
- measured = { x, y, width, height };
2319
+ measured = { height, width, x, y };
2277
2320
  });
2278
2321
  if (measured) {
2279
2322
  const size = Math.floor(measured[horizontal ? "width" : "height"] * 8) / 8;
@@ -2301,6 +2344,11 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2301
2344
  }
2302
2345
  }
2303
2346
  }, []);
2347
+ useLayoutEffect(() => {
2348
+ if (snapToIndices) {
2349
+ updateSnapToOffsets(ctx, state);
2350
+ }
2351
+ }, [snapToIndices]);
2304
2352
  useLayoutEffect(() => {
2305
2353
  const didAllocateContainers = doInitialAllocateContainersCallback();
2306
2354
  if (!didAllocateContainers) {
@@ -2324,9 +2372,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2324
2372
  };
2325
2373
  useEffect(() => {
2326
2374
  const viewability = setupViewability({
2375
+ onViewableItemsChanged,
2327
2376
  viewabilityConfig,
2328
- viewabilityConfigCallbackPairs,
2329
- onViewableItemsChanged
2377
+ viewabilityConfigCallbackPairs
2330
2378
  });
2331
2379
  state.viewabilityConfigCallbackPairs = viewability;
2332
2380
  state.props.viewabilityConfigCallbackPairs = viewability;
@@ -2344,97 +2392,94 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2344
2392
  onLayoutProp(event);
2345
2393
  }
2346
2394
  }, []);
2347
- useImperativeHandle(
2348
- forwardedRef,
2349
- () => {
2350
- const scrollIndexIntoView = (options) => {
2395
+ useImperativeHandle(forwardedRef, () => {
2396
+ const scrollIndexIntoView = (options) => {
2397
+ const state2 = refState.current;
2398
+ if (state2) {
2399
+ const { index, ...rest2 } = options;
2400
+ const { startNoBuffer, endNoBuffer } = state2;
2401
+ if (index < startNoBuffer || index > endNoBuffer) {
2402
+ const viewPosition = index < startNoBuffer ? 0 : 1;
2403
+ scrollToIndex(ctx, state2, {
2404
+ ...rest2,
2405
+ index,
2406
+ viewPosition
2407
+ });
2408
+ }
2409
+ }
2410
+ };
2411
+ return {
2412
+ flashScrollIndicators: () => refScroller.current.flashScrollIndicators(),
2413
+ getNativeScrollRef: () => refScroller.current,
2414
+ getScrollableNode: () => refScroller.current.getScrollableNode(),
2415
+ getScrollResponder: () => refScroller.current.getScrollResponder(),
2416
+ getState: () => {
2351
2417
  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
- }
2418
+ return state2 ? {
2419
+ contentLength: state2.totalSize,
2420
+ end: state2.endNoBuffer,
2421
+ endBuffered: state2.endBuffered,
2422
+ isAtEnd: state2.isAtEnd,
2423
+ isAtStart: state2.isAtStart,
2424
+ positions: state2.positions,
2425
+ scroll: state2.scroll,
2426
+ scrollLength: state2.scrollLength,
2427
+ sizeAtIndex: (index) => state2.sizesKnown.get(getId(state2, index)),
2428
+ sizes: state2.sizesKnown,
2429
+ start: state2.startNoBuffer,
2430
+ startBuffered: state2.startBuffered
2431
+ } : {};
2432
+ },
2433
+ scrollIndexIntoView,
2434
+ scrollItemIntoView: ({ item, ...props2 }) => {
2435
+ const data = refState.current.props.data;
2436
+ const index = data.indexOf(item);
2437
+ if (index !== -1) {
2438
+ scrollIndexIntoView({ index, ...props2 });
2363
2439
  }
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);
2440
+ },
2441
+ scrollToEnd: (options) => {
2442
+ const data = refState.current.props.data;
2443
+ const stylePaddingBottom = refState.current.props.stylePaddingBottom;
2444
+ const index = data.length - 1;
2445
+ if (index !== -1) {
2446
+ const paddingBottom = stylePaddingBottom || 0;
2447
+ const footerSize = peek$(ctx, "footerSize") || 0;
2448
+ scrollToIndex(ctx, state, {
2449
+ index,
2450
+ viewOffset: -paddingBottom - footerSize,
2451
+ viewPosition: 1,
2452
+ ...options
2453
+ });
2421
2454
  }
2422
- };
2423
- },
2424
- []
2425
- );
2455
+ },
2456
+ scrollToIndex: (params) => scrollToIndex(ctx, state, params),
2457
+ scrollToItem: ({ item, ...props2 }) => {
2458
+ const data = refState.current.props.data;
2459
+ const index = data.indexOf(item);
2460
+ if (index !== -1) {
2461
+ scrollToIndex(ctx, state, { index, ...props2 });
2462
+ }
2463
+ },
2464
+ scrollToOffset: (params) => scrollTo(state, params),
2465
+ setVisibleContentAnchorOffset: (value) => {
2466
+ const val = typeof value === "function" ? value(peek$(ctx, "scrollAdjustUserOffset") || 0) : value;
2467
+ set$(ctx, "scrollAdjustUserOffset", val);
2468
+ }
2469
+ };
2470
+ }, []);
2426
2471
  if (Platform.OS === "web") {
2427
2472
  useEffect(() => {
2428
2473
  if (initialContentOffset) {
2429
- scrollTo(state, { offset: initialContentOffset, animated: false });
2474
+ scrollTo(state, { animated: false, offset: initialContentOffset });
2430
2475
  }
2431
2476
  }, []);
2432
2477
  }
2433
2478
  const fns = useMemo(
2434
2479
  () => ({
2435
- updateItemSize: (itemKey, sizeObj) => updateItemSize(ctx, state, itemKey, sizeObj),
2436
2480
  getRenderedItem: (key) => getRenderedItem(ctx, state, key),
2437
- onScroll: (event) => onScroll(ctx, state, event)
2481
+ onScroll: (event) => onScroll(ctx, state, event),
2482
+ updateItemSize: (itemKey, sizeObj) => updateItemSize(ctx, state, itemKey, sizeObj)
2438
2483
  }),
2439
2484
  []
2440
2485
  );
@@ -2442,13 +2487,17 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2442
2487
  ListComponent,
2443
2488
  {
2444
2489
  ...rest,
2490
+ alignItemsAtEnd,
2445
2491
  canRender,
2492
+ contentContainerStyle,
2493
+ getRenderedItem: fns.getRenderedItem,
2446
2494
  horizontal,
2447
- refScrollView: combinedRef,
2448
2495
  initialContentOffset,
2449
- getRenderedItem: fns.getRenderedItem,
2450
- updateItemSize: fns.updateItemSize,
2451
- onScroll: fns.onScroll,
2496
+ ListEmptyComponent: dataProp.length === 0 ? ListEmptyComponent : void 0,
2497
+ ListHeaderComponent,
2498
+ maintainVisibleContentPosition,
2499
+ onLayout,
2500
+ onLayoutHeader,
2452
2501
  onMomentumScrollEnd: (event) => {
2453
2502
  requestAnimationFrame(() => {
2454
2503
  finishScrollTo(refState.current);
@@ -2457,31 +2506,30 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2457
2506
  onMomentumScrollEnd(event);
2458
2507
  }
2459
2508
  },
2460
- onLayout,
2509
+ onScroll: fns.onScroll,
2461
2510
  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
2511
  refreshControl: refreshControl ? stylePaddingTopState > 0 ? React3.cloneElement(refreshControl, {
2469
2512
  progressViewOffset: (refreshControl.props.progressViewOffset || 0) + stylePaddingTopState
2470
2513
  }) : refreshControl : onRefresh && /* @__PURE__ */ React3.createElement(
2471
2514
  RefreshControl,
2472
2515
  {
2473
- refreshing: !!refreshing,
2474
2516
  onRefresh,
2475
- progressViewOffset: (progressViewOffset || 0) + stylePaddingTopState
2517
+ progressViewOffset: (progressViewOffset || 0) + stylePaddingTopState,
2518
+ refreshing: !!refreshing
2476
2519
  }
2477
2520
  ),
2478
- style,
2479
- contentContainerStyle,
2521
+ refScrollView: combinedRef,
2480
2522
  scrollAdjustHandler: (_a = refState.current) == null ? void 0 : _a.scrollAdjustHandler,
2481
- onLayoutHeader
2523
+ scrollEventThrottle: Platform.OS === "web" ? 16 : void 0,
2524
+ snapToIndices,
2525
+ style,
2526
+ updateItemSize: fns.updateItemSize,
2527
+ waitForInitialLayout
2482
2528
  }
2483
2529
  ), __DEV__ && ENABLE_DEBUG_VIEW && /* @__PURE__ */ React3.createElement(DebugView, { state: refState.current }));
2484
2530
  });
2531
+
2532
+ // src/components/LazyLegendList.tsx
2485
2533
  var typedForwardRef2 = forwardRef;
2486
2534
  var renderItem = ({ item }) => item;
2487
2535
  var LazyLegendList = typedForwardRef2(function LazyLegendList2(props, forwardedRef) {
@@ -2490,7 +2538,7 @@ var LazyLegendList = typedForwardRef2(function LazyLegendList2(props, forwardedR
2490
2538
  const data = (isArray(children) ? children : React3.Children.toArray(children)).flat(1);
2491
2539
  return (
2492
2540
  // @ts-expect-error TODO: Fix this type
2493
- /* @__PURE__ */ React3.createElement(LegendListComponent, { ...rest, data, renderItem, ref: forwardedRef })
2541
+ /* @__PURE__ */ React3.createElement(LegendListComponent, { ...rest, data, ref: forwardedRef, renderItem })
2494
2542
  );
2495
2543
  });
2496
2544