@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
@@ -24,21 +24,22 @@ function _interopNamespace(e) {
24
24
 
25
25
  var React3__namespace = /*#__PURE__*/_interopNamespace(React3);
26
26
 
27
- // src/LegendList.tsx
27
+ // src/components/LazyLegendList.tsx
28
28
  var ContextState = React3__namespace.createContext(null);
29
29
  function StateProvider({ children }) {
30
30
  const [value] = React3__namespace.useState(() => ({
31
+ columnWrapperStyle: void 0,
31
32
  listeners: /* @__PURE__ */ new Map(),
33
+ mapViewabilityAmountCallbacks: /* @__PURE__ */ new Map(),
34
+ mapViewabilityAmountValues: /* @__PURE__ */ new Map(),
35
+ mapViewabilityCallbacks: /* @__PURE__ */ new Map(),
36
+ mapViewabilityValues: /* @__PURE__ */ new Map(),
32
37
  values: /* @__PURE__ */ new Map([
33
38
  ["alignItemsPaddingTop", 0],
34
39
  ["stylePaddingTop", 0],
35
- ["headerSize", 0]
40
+ ["headerSize", 0],
41
+ ["numContainers", 0]
36
42
  ]),
37
- mapViewabilityCallbacks: /* @__PURE__ */ new Map(),
38
- mapViewabilityValues: /* @__PURE__ */ new Map(),
39
- mapViewabilityAmountCallbacks: /* @__PURE__ */ new Map(),
40
- mapViewabilityAmountValues: /* @__PURE__ */ new Map(),
41
- columnWrapperStyle: void 0,
42
43
  viewRefs: /* @__PURE__ */ new Map()
43
44
  }));
44
45
  return /* @__PURE__ */ React3__namespace.createElement(ContextState.Provider, { value }, children);
@@ -50,17 +51,6 @@ function createSelectorFunctionsArr(ctx, signalNames) {
50
51
  let lastValues = [];
51
52
  let lastSignalValues = [];
52
53
  return {
53
- subscribe: (cb) => {
54
- const listeners = [];
55
- for (const signalName of signalNames) {
56
- listeners.push(listen$(ctx, signalName, cb));
57
- }
58
- return () => {
59
- for (const listener of listeners) {
60
- listener();
61
- }
62
- };
63
- },
64
54
  get: () => {
65
55
  const currentValues = [];
66
56
  let hasChanged = false;
@@ -76,6 +66,17 @@ function createSelectorFunctionsArr(ctx, signalNames) {
76
66
  lastValues = currentValues;
77
67
  }
78
68
  return lastValues;
69
+ },
70
+ subscribe: (cb) => {
71
+ const listeners = [];
72
+ for (const signalName of signalNames) {
73
+ listeners.push(listen$(ctx, signalName, cb));
74
+ }
75
+ return () => {
76
+ for (const listener of listeners) {
77
+ listener();
78
+ }
79
+ };
79
80
  }
80
81
  };
81
82
  }
@@ -126,13 +127,13 @@ function useSelector$(signalName, selector) {
126
127
  return value;
127
128
  }
128
129
 
129
- // src/DebugView.tsx
130
+ // src/components/DebugView.tsx
130
131
  var DebugRow = ({ children }) => {
131
- return /* @__PURE__ */ React3__namespace.createElement(reactNative.View, { style: { flexDirection: "row", alignItems: "center", justifyContent: "space-between" } }, children);
132
+ return /* @__PURE__ */ React3__namespace.createElement(reactNative.View, { style: { alignItems: "center", flexDirection: "row", justifyContent: "space-between" } }, children);
132
133
  };
133
134
  var DebugView = React3__namespace.memo(function DebugView2({ state }) {
134
135
  const ctx = useStateContext();
135
- const [totalSize = 0, scrollAdjust = 0, rawScroll = 0, scroll = 0, numContainers = 0, numContainersPooled = 0] = useArr$([
136
+ const [totalSize = 0, scrollAdjust = 0, rawScroll = 0, scroll = 0, _numContainers = 0, _numContainersPooled = 0] = useArr$([
136
137
  "totalSize",
137
138
  "scrollAdjust",
138
139
  "debugRawScroll",
@@ -148,18 +149,18 @@ var DebugView = React3__namespace.memo(function DebugView2({ state }) {
148
149
  return /* @__PURE__ */ React3__namespace.createElement(
149
150
  reactNative.View,
150
151
  {
152
+ pointerEvents: "none",
151
153
  style: {
152
- position: "absolute",
153
- top: 0,
154
- right: 0,
155
- paddingLeft: 4,
156
- paddingBottom: 4,
157
154
  // height: 100,
158
155
  backgroundColor: "#FFFFFFCC",
156
+ borderRadius: 4,
159
157
  padding: 4,
160
- borderRadius: 4
161
- },
162
- pointerEvents: "none"
158
+ paddingBottom: 4,
159
+ paddingLeft: 4,
160
+ position: "absolute",
161
+ right: 0,
162
+ top: 0
163
+ }
163
164
  },
164
165
  /* @__PURE__ */ React3__namespace.createElement(DebugRow, null, /* @__PURE__ */ React3__namespace.createElement(reactNative.Text, null, "TotalSize:"), /* @__PURE__ */ React3__namespace.createElement(reactNative.Text, null, totalSize.toFixed(2))),
165
166
  /* @__PURE__ */ React3__namespace.createElement(DebugRow, null, /* @__PURE__ */ React3__namespace.createElement(reactNative.Text, null, "ContentSize:"), /* @__PURE__ */ React3__namespace.createElement(reactNative.Text, null, contentSize.toFixed(2))),
@@ -177,8 +178,34 @@ function useInterval(callback, delay) {
177
178
  return () => clearInterval(interval);
178
179
  }, [delay]);
179
180
  }
181
+ var LeanViewComponent = React3__namespace.forwardRef((props, ref) => {
182
+ return React3__namespace.createElement("RCTView", { ...props, ref });
183
+ });
184
+ LeanViewComponent.displayName = "RCTView";
185
+ var LeanView = reactNative.Platform.OS === "android" || reactNative.Platform.OS === "ios" ? LeanViewComponent : reactNative.View;
186
+
187
+ // src/components/Separator.tsx
188
+ function Separator({ ItemSeparatorComponent, itemKey, leadingItem }) {
189
+ const [lastItemKeys] = useArr$(["lastItemKeys"]);
190
+ const isALastItem = lastItemKeys.includes(itemKey);
191
+ return isALastItem ? null : /* @__PURE__ */ React.createElement(ItemSeparatorComponent, { leadingItem });
192
+ }
193
+
194
+ // src/constants.ts
195
+ var POSITION_OUT_OF_VIEW = -1e7;
196
+ var ENABLE_DEVMODE = __DEV__ && false;
197
+ var ENABLE_DEBUG_VIEW = __DEV__ && false;
198
+ var IsNewArchitecture = global.nativeFabricUIManager != null;
199
+ var symbolFirst = Symbol();
200
+ function useInit(cb) {
201
+ const refValue = React3.useRef(symbolFirst);
202
+ if (refValue.current === symbolFirst) {
203
+ refValue.current = cb();
204
+ }
205
+ return refValue.current;
206
+ }
180
207
 
181
- // src/helpers.ts
208
+ // src/utils/helpers.ts
182
209
  function isFunction(obj) {
183
210
  return typeof obj === "function";
184
211
  }
@@ -208,16 +235,8 @@ function getPadding(s, type) {
208
235
  function extractPadding(style, contentContainerStyle, type) {
209
236
  return getPadding(style, type) + getPadding(contentContainerStyle, type);
210
237
  }
211
- var symbolFirst = Symbol();
212
- function useInit(cb) {
213
- const refValue = React3.useRef(symbolFirst);
214
- if (refValue.current === symbolFirst) {
215
- refValue.current = cb();
216
- }
217
- return refValue.current;
218
- }
219
238
 
220
- // src/ContextContainer.ts
239
+ // src/state/ContextContainer.ts
221
240
  var ContextContainer = React3.createContext(null);
222
241
  function useViewability(callback, configId) {
223
242
  const ctx = useStateContext();
@@ -261,7 +280,7 @@ function useRecyclingEffect(effect) {
261
280
  prevItem: void 0
262
281
  });
263
282
  React3.useEffect(() => {
264
- let ret = void 0;
283
+ let ret;
265
284
  if (prevValues.current.prevIndex !== void 0 && prevValues.current.prevItem !== void 0) {
266
285
  ret = effect({
267
286
  index,
@@ -275,7 +294,7 @@ function useRecyclingEffect(effect) {
275
294
  prevItem: value
276
295
  };
277
296
  return ret;
278
- }, [index, value]);
297
+ }, [index, value, effect]);
279
298
  }
280
299
  function useRecyclingState(valueOrFun) {
281
300
  const { index, value, itemKey, triggerLayout } = React3.useContext(ContextContainer);
@@ -313,26 +332,8 @@ function useListScrollSize() {
313
332
  const [scrollSize] = useArr$(["scrollSize"]);
314
333
  return scrollSize;
315
334
  }
316
- var LeanViewComponent = React3__namespace.forwardRef((props, ref) => {
317
- return React3__namespace.createElement("RCTView", { ...props, ref });
318
- });
319
- LeanViewComponent.displayName = "RCTView";
320
- var LeanView = reactNative.Platform.OS === "android" || reactNative.Platform.OS === "ios" ? LeanViewComponent : reactNative.View;
321
-
322
- // src/Separator.tsx
323
- function Separator({ ItemSeparatorComponent, itemKey, leadingItem }) {
324
- const [lastItemKeys] = useArr$(["lastItemKeys"]);
325
- const isALastItem = lastItemKeys.includes(itemKey);
326
- return isALastItem ? null : /* @__PURE__ */ React.createElement(ItemSeparatorComponent, { leadingItem });
327
- }
328
-
329
- // src/constants.ts
330
- var POSITION_OUT_OF_VIEW = -1e7;
331
- var ENABLE_DEVMODE = __DEV__ && false;
332
- var ENABLE_DEBUG_VIEW = __DEV__ && false;
333
- var IsNewArchitecture = global.nativeFabricUIManager != null;
334
335
 
335
- // src/Container.tsx
336
+ // src/components/Container.tsx
336
337
  var Container = ({
337
338
  id,
338
339
  recycleItems,
@@ -374,17 +375,17 @@ var Container = ({
374
375
  }
375
376
  const style = horizontal ? {
376
377
  flexDirection: ItemSeparatorComponent ? "row" : void 0,
377
- position: "absolute",
378
- top: otherAxisPos,
379
378
  height: otherAxisSize,
380
379
  left: position,
380
+ position: "absolute",
381
+ top: otherAxisPos,
381
382
  ...paddingStyles || {}
382
383
  } : {
383
- position: "absolute",
384
384
  left: otherAxisPos,
385
+ position: "absolute",
385
386
  right: numColumns > 1 ? null : 0,
386
- width: otherAxisSize,
387
387
  top: position,
388
+ width: otherAxisSize,
388
389
  ...paddingStyles || {}
389
390
  };
390
391
  const renderedItemInfo = React3.useMemo(
@@ -397,7 +398,7 @@ var Container = ({
397
398
  }, []);
398
399
  const contextValue = React3.useMemo(() => {
399
400
  ctx.viewRefs.set(id, ref);
400
- return { containerId: id, itemKey, index, value: data, triggerLayout };
401
+ return { containerId: id, index, itemKey, triggerLayout, value: data };
401
402
  }, [id, itemKey, index, data]);
402
403
  const onLayout = (event) => {
403
404
  var _a, _b;
@@ -406,14 +407,14 @@ var Container = ({
406
407
  let layout = event.nativeEvent.layout;
407
408
  const size = layout[horizontal ? "width" : "height"];
408
409
  const doUpdate = () => {
409
- refLastSize.current = { width: layout.width, height: layout.height };
410
+ refLastSize.current = { height: layout.height, width: layout.width };
410
411
  updateItemSize2(itemKey, layout);
411
412
  };
412
413
  if (IsNewArchitecture || size > 0) {
413
414
  doUpdate();
414
415
  } else {
415
- (_b = (_a = ref.current) == null ? void 0 : _a.measure) == null ? void 0 : _b.call(_a, (x, y, width, height) => {
416
- layout = { width, height };
416
+ (_b = (_a = ref.current) == null ? void 0 : _a.measure) == null ? void 0 : _b.call(_a, (_x, _y, width, height) => {
417
+ layout = { height, width };
417
418
  doUpdate();
418
419
  });
419
420
  }
@@ -446,30 +447,28 @@ var Container = ({
446
447
  }
447
448
  }, [itemKey]);
448
449
  }
449
- return /* @__PURE__ */ React3__namespace.createElement(LeanView, { style, onLayout, ref, key: recycleItems ? void 0 : itemKey }, /* @__PURE__ */ React3__namespace.createElement(ContextContainer.Provider, { value: contextValue }, renderedItem, renderedItemInfo && ItemSeparatorComponent && /* @__PURE__ */ React3__namespace.createElement(
450
+ return /* @__PURE__ */ React3__namespace.createElement(LeanView, { key: recycleItems ? void 0 : itemKey, onLayout, ref, style }, /* @__PURE__ */ React3__namespace.createElement(ContextContainer.Provider, { value: contextValue }, renderedItem, renderedItemInfo && ItemSeparatorComponent && /* @__PURE__ */ React3__namespace.createElement(
450
451
  Separator,
451
452
  {
452
- itemKey,
453
453
  ItemSeparatorComponent,
454
+ itemKey,
454
455
  leadingItem: renderedItemInfo.item
455
456
  }
456
457
  )));
457
458
  };
458
- var typedForwardRef = React3.forwardRef;
459
- var typedMemo = React3.memo;
460
459
  var useAnimatedValue = (initialValue) => {
461
460
  return React3.useRef(new reactNative.Animated.Value(initialValue)).current;
462
461
  };
463
462
 
464
- // src/useValue$.ts
463
+ // src/hooks/useValue$.ts
465
464
  function useValue$(key, params) {
466
465
  var _a;
467
466
  const { getValue, delay } = params || {};
468
467
  const ctx = useStateContext();
469
468
  const animValue = useAnimatedValue((_a = getValue ? getValue(peek$(ctx, key)) : peek$(ctx, key)) != null ? _a : 0);
470
469
  React3.useMemo(() => {
471
- let newValue = void 0;
472
- let prevValue = void 0;
470
+ let newValue;
471
+ let prevValue;
473
472
  let didQueueTask = false;
474
473
  listen$(ctx, key, (v) => {
475
474
  newValue = getValue ? getValue(v) : v;
@@ -497,8 +496,10 @@ function useValue$(key, params) {
497
496
  }, []);
498
497
  return animValue;
499
498
  }
499
+ var typedForwardRef = React3.forwardRef;
500
+ var typedMemo = React3.memo;
500
501
 
501
- // src/Containers.tsx
502
+ // src/components/Containers.tsx
502
503
  var Containers = typedMemo(function Containers2({
503
504
  horizontal,
504
505
  recycleItems,
@@ -522,18 +523,18 @@ var Containers = typedMemo(function Containers2({
522
523
  /* @__PURE__ */ React3__namespace.createElement(
523
524
  Container,
524
525
  {
526
+ getRenderedItem: getRenderedItem2,
527
+ horizontal,
528
+ ItemSeparatorComponent,
525
529
  id: i,
526
530
  key: i,
527
531
  recycleItems,
528
- horizontal,
529
- getRenderedItem: getRenderedItem2,
530
- updateItemSize: updateItemSize2,
531
- ItemSeparatorComponent
532
+ updateItemSize: updateItemSize2
532
533
  }
533
534
  )
534
535
  );
535
536
  }
536
- const style = horizontal ? { width: animSize, opacity: animOpacity, minHeight: otherAxisSize } : { height: animSize, opacity: animOpacity, minWidth: otherAxisSize };
537
+ const style = horizontal ? { minHeight: otherAxisSize, opacity: animOpacity, width: animSize } : { height: animSize, minWidth: otherAxisSize, opacity: animOpacity };
537
538
  if (columnWrapperStyle && numColumns > 1) {
538
539
  const { columnGap, rowGap, gap } = columnWrapperStyle;
539
540
  const gapX = columnGap || gap || 0;
@@ -564,15 +565,21 @@ function ScrollAdjust() {
564
565
  reactNative.View,
565
566
  {
566
567
  style: {
567
- position: "absolute",
568
568
  height: 0,
569
- width: 0,
569
+ left: 0,
570
+ position: "absolute",
570
571
  top: scrollOffset,
571
- left: 0
572
+ width: 0
572
573
  }
573
574
  }
574
575
  );
575
576
  }
577
+
578
+ // src/components/SnapWrapper.tsx
579
+ function SnapWrapper({ ScrollComponent, ...props }) {
580
+ const [snapToOffsets] = useArr$(["snapToOffsets"]);
581
+ return /* @__PURE__ */ React.createElement(ScrollComponent, { ...props, snapToOffsets });
582
+ }
576
583
  function useSyncLayout({
577
584
  onChange
578
585
  }) {
@@ -586,14 +593,14 @@ function useSyncLayout({
586
593
  React3.useLayoutEffect(() => {
587
594
  if (ref.current) {
588
595
  ref.current.measure((x, y, width, height) => {
589
- onChange({ x, y, width, height }, true);
596
+ onChange({ height, width, x, y }, true);
590
597
  });
591
598
  }
592
599
  }, []);
593
600
  return { onLayout, ref };
594
601
  }
595
602
 
596
- // src/ListComponent.tsx
603
+ // src/components/ListComponent.tsx
597
604
  var getComponent = (Component) => {
598
605
  if (React3__namespace.isValidElement(Component)) {
599
606
  return Component;
@@ -613,12 +620,12 @@ var PaddingDevMode = () => {
613
620
  reactNative.Animated.View,
614
621
  {
615
622
  style: {
616
- position: "absolute",
617
- top: 0,
623
+ backgroundColor: "green",
618
624
  height: animPaddingTop,
619
625
  left: 0,
626
+ position: "absolute",
620
627
  right: 0,
621
- backgroundColor: "green"
628
+ top: 0
622
629
  }
623
630
  }
624
631
  ));
@@ -647,6 +654,7 @@ var ListComponent = typedMemo(function ListComponent2({
647
654
  renderScrollComponent,
648
655
  scrollAdjustHandler,
649
656
  onLayoutHeader,
657
+ snapToIndices,
650
658
  ...rest
651
659
  }) {
652
660
  const ctx = useStateContext();
@@ -664,76 +672,56 @@ var ListComponent = typedMemo(function ListComponent2({
664
672
  }, 0);
665
673
  }
666
674
  }, [canRender]);
675
+ const SnapOrScroll = snapToIndices ? SnapWrapper : ScrollComponent;
667
676
  return /* @__PURE__ */ React3__namespace.createElement(
668
- ScrollComponent,
677
+ SnapOrScroll,
669
678
  {
670
679
  ...rest,
671
- style,
672
- maintainVisibleContentPosition: maintainVisibleContentPosition && !ListEmptyComponent ? { minIndexForVisible: 0 } : void 0,
673
680
  contentContainerStyle: [
674
681
  contentContainerStyle,
675
682
  horizontal ? {
676
683
  height: "100%"
677
684
  } : {}
678
685
  ],
679
- onScroll: onScroll2,
680
- onLayout,
681
- horizontal,
682
686
  contentOffset: initialContentOffset ? horizontal ? { x: initialContentOffset, y: 0 } : { x: 0, y: initialContentOffset } : void 0,
683
- ref: refScrollView
687
+ horizontal,
688
+ maintainVisibleContentPosition: maintainVisibleContentPosition && !ListEmptyComponent ? { minIndexForVisible: 0 } : void 0,
689
+ onLayout,
690
+ onScroll: onScroll2,
691
+ ref: refScrollView,
692
+ ScrollComponent: snapToIndices ? ScrollComponent : void 0,
693
+ style
684
694
  },
685
695
  maintainVisibleContentPosition && /* @__PURE__ */ React3__namespace.createElement(ScrollAdjust, null),
686
696
  ENABLE_DEVMODE ? /* @__PURE__ */ React3__namespace.createElement(PaddingDevMode, null) : /* @__PURE__ */ React3__namespace.createElement(Padding, null),
687
- ListHeaderComponent && /* @__PURE__ */ React3__namespace.createElement(reactNative.View, { style: ListHeaderComponentStyle, onLayout: onLayoutHeaderSync, ref: refHeader }, getComponent(ListHeaderComponent)),
697
+ ListHeaderComponent && /* @__PURE__ */ React3__namespace.createElement(reactNative.View, { onLayout: onLayoutHeaderSync, ref: refHeader, style: ListHeaderComponentStyle }, getComponent(ListHeaderComponent)),
688
698
  ListEmptyComponent && getComponent(ListEmptyComponent),
689
699
  canRender && /* @__PURE__ */ React3__namespace.createElement(
690
700
  Containers,
691
701
  {
692
- horizontal,
693
- recycleItems,
694
- waitForInitialLayout,
695
702
  getRenderedItem: getRenderedItem2,
703
+ horizontal,
696
704
  ItemSeparatorComponent,
697
- updateItemSize: updateItemSize2
705
+ recycleItems,
706
+ updateItemSize: updateItemSize2,
707
+ waitForInitialLayout
698
708
  }
699
709
  ),
700
710
  ListFooterComponent && /* @__PURE__ */ React3__namespace.createElement(
701
711
  reactNative.View,
702
712
  {
703
- style: ListFooterComponentStyle,
704
713
  onLayout: (event) => {
705
714
  const size = event.nativeEvent.layout[horizontal ? "width" : "height"];
706
715
  set$(ctx, "footerSize", size);
707
- }
716
+ },
717
+ style: ListFooterComponentStyle
708
718
  },
709
719
  getComponent(ListFooterComponent)
710
720
  )
711
721
  );
712
722
  });
713
723
 
714
- // src/ScrollAdjustHandler.ts
715
- var ScrollAdjustHandler = class {
716
- constructor(ctx) {
717
- this.appliedAdjust = 0;
718
- this.mounted = false;
719
- this.context = ctx;
720
- }
721
- requestAdjust(add) {
722
- const oldAdjustTop = peek$(this.context, "scrollAdjust") || 0;
723
- this.appliedAdjust = add + oldAdjustTop;
724
- const set = () => set$(this.context, "scrollAdjust", this.appliedAdjust);
725
- if (this.mounted) {
726
- set();
727
- } else {
728
- requestAnimationFrame(set);
729
- }
730
- }
731
- setMounted() {
732
- this.mounted = true;
733
- }
734
- };
735
-
736
- // src/getId.ts
724
+ // src/utils/getId.ts
737
725
  function getId(state, index) {
738
726
  const { data, keyExtractor } = state.props;
739
727
  if (!data) {
@@ -745,7 +733,7 @@ function getId(state, index) {
745
733
  return id;
746
734
  }
747
735
 
748
- // src/calculateOffsetForIndex.ts
736
+ // src/core/calculateOffsetForIndex.ts
749
737
  function calculateOffsetForIndex(ctx, state, index) {
750
738
  let position = 0;
751
739
  if (index !== void 0) {
@@ -762,7 +750,7 @@ function calculateOffsetForIndex(ctx, state, index) {
762
750
  return position;
763
751
  }
764
752
 
765
- // src/getItemSize.ts
753
+ // src/utils/getItemSize.ts
766
754
  function getItemSize(state, key, index, data, useAverageSize) {
767
755
  const {
768
756
  sizesKnown,
@@ -791,7 +779,7 @@ function getItemSize(state, key, index, data, useAverageSize) {
791
779
  return size;
792
780
  }
793
781
 
794
- // src/calculateOffsetWithOffsetPosition.ts
782
+ // src/core/calculateOffsetWithOffsetPosition.ts
795
783
  function calculateOffsetWithOffsetPosition(state, offsetParam, params) {
796
784
  const { index, viewOffset, viewPosition } = params;
797
785
  let offset = offsetParam;
@@ -804,323 +792,76 @@ function calculateOffsetWithOffsetPosition(state, offsetParam, params) {
804
792
  return offset;
805
793
  }
806
794
 
807
- // src/checkAllSizesKnown.ts
808
- function checkAllSizesKnown(state) {
809
- const { startBuffered, endBuffered, sizesKnown } = state;
810
- if (endBuffered !== null) {
811
- let areAllKnown = true;
812
- for (let i = startBuffered; areAllKnown && i <= endBuffered; i++) {
813
- const key = getId(state, i);
814
- areAllKnown && (areAllKnown = sizesKnown.has(key));
795
+ // src/utils/requestAdjust.ts
796
+ function requestAdjust(ctx, state, positionDiff) {
797
+ if (Math.abs(positionDiff) > 0.1) {
798
+ const doit = () => {
799
+ state.scrollAdjustHandler.requestAdjust(positionDiff);
800
+ };
801
+ state.scroll += positionDiff;
802
+ state.scrollForNextCalculateItemsInView = void 0;
803
+ const didLayout = peek$(ctx, "containersDidLayout");
804
+ if (didLayout) {
805
+ doit();
806
+ const threshold = state.scroll - positionDiff / 2;
807
+ if (!state.ignoreScrollFromMVCP) {
808
+ state.ignoreScrollFromMVCP = {};
809
+ }
810
+ if (positionDiff > 0) {
811
+ state.ignoreScrollFromMVCP.lt = threshold;
812
+ } else {
813
+ state.ignoreScrollFromMVCP.gt = threshold;
814
+ }
815
+ if (state.ignoreScrollFromMVCPTimeout) {
816
+ clearTimeout(state.ignoreScrollFromMVCPTimeout);
817
+ }
818
+ state.ignoreScrollFromMVCPTimeout = setTimeout(() => {
819
+ state.ignoreScrollFromMVCP = void 0;
820
+ }, 100);
821
+ } else {
822
+ requestAnimationFrame(doit);
815
823
  }
816
- return areAllKnown;
817
824
  }
818
- return false;
819
825
  }
820
826
 
821
- // src/findAvailableContainers.ts
822
- function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffered, pendingRemoval) {
823
- const numContainers = peek$(ctx, "numContainers");
824
- const result = [];
825
- const availableContainers = [];
826
- for (let u = 0; u < numContainers; u++) {
827
- const key = peek$(ctx, `containerItemKey${u}`);
828
- let isOk = key === void 0;
829
- if (!isOk) {
830
- const index = pendingRemoval.indexOf(u);
831
- if (index !== -1) {
832
- pendingRemoval.splice(index, 1);
833
- isOk = true;
834
- }
835
- }
836
- if (isOk) {
837
- result.push(u);
838
- if (result.length >= numNeeded) {
839
- return result;
840
- }
827
+ // src/core/prepareMVCP.ts
828
+ function prepareMVCP(ctx, state) {
829
+ const {
830
+ positions,
831
+ scrollingTo,
832
+ props: { maintainVisibleContentPosition }
833
+ } = state;
834
+ let prevPosition;
835
+ let targetId;
836
+ let targetIndex;
837
+ const scrollTarget = scrollingTo == null ? void 0 : scrollingTo.index;
838
+ if (maintainVisibleContentPosition) {
839
+ const indexByKey = state.indexByKey;
840
+ if (scrollTarget !== void 0) {
841
+ targetId = getId(state, scrollTarget);
842
+ targetIndex = scrollTarget;
843
+ } else if (state.idsInView.length > 0 && peek$(ctx, "containersDidLayout")) {
844
+ targetId = state.idsInView.find((id) => indexByKey.get(id) !== void 0);
845
+ targetIndex = indexByKey.get(targetId);
841
846
  }
842
- }
843
- for (let u = 0; u < numContainers; u++) {
844
- const key = peek$(ctx, `containerItemKey${u}`);
845
- if (key === void 0) continue;
846
- const index = state.indexByKey.get(key);
847
- if (index < startBuffered) {
848
- availableContainers.push({ index: u, distance: startBuffered - index });
849
- } else if (index > endBuffered) {
850
- availableContainers.push({ index: u, distance: index - endBuffered });
847
+ if (targetId !== void 0 && targetIndex !== void 0) {
848
+ prevPosition = positions.get(targetId);
851
849
  }
852
850
  }
853
- const remaining = numNeeded - result.length;
854
- if (remaining > 0) {
855
- if (availableContainers.length > 0) {
856
- if (availableContainers.length > remaining) {
857
- availableContainers.sort(comparatorByDistance);
858
- availableContainers.length = remaining;
859
- }
860
- for (const container of availableContainers) {
861
- result.push(container.index);
862
- }
863
- }
864
- const stillNeeded = numNeeded - result.length;
865
- if (stillNeeded > 0) {
866
- for (let i = 0; i < stillNeeded; i++) {
867
- result.push(numContainers + i);
868
- }
869
- if (__DEV__ && numContainers + stillNeeded > peek$(ctx, "numContainersPooled")) {
870
- console.warn(
871
- "[legend-list] No unused container available, so creating one on demand. This can be a minor performance issue and is likely caused by the estimatedItemSize being too large. Consider decreasing estimatedItemSize or increasing initialContainerPoolRatio.",
872
- {
873
- debugInfo: {
874
- numContainers,
875
- numNeeded,
876
- stillNeeded,
877
- numContainersPooled: peek$(ctx, "numContainersPooled")
878
- }
879
- }
880
- );
881
- }
882
- }
883
- }
884
- return result.sort(comparatorDefault);
885
- }
886
- function comparatorByDistance(a, b) {
887
- return b.distance - a.distance;
888
- }
889
-
890
- // src/getScrollVelocity.ts
891
- var getScrollVelocity = (state) => {
892
- const { scrollHistory } = state;
893
- let velocity = 0;
894
- if (scrollHistory.length >= 1) {
895
- const newest = scrollHistory[scrollHistory.length - 1];
896
- let oldest;
897
- let start = 0;
898
- for (let i = 0; i < scrollHistory.length - 1; i++) {
899
- const entry = scrollHistory[i];
900
- const nextEntry = scrollHistory[i + 1];
901
- if (i > 0) {
902
- const prevEntry = scrollHistory[i - 1];
903
- const prevDirection = entry.scroll - prevEntry.scroll;
904
- const currentDirection = nextEntry.scroll - entry.scroll;
905
- if (prevDirection > 0 && currentDirection < 0 || prevDirection < 0 && currentDirection > 0) {
906
- start = i;
907
- break;
908
- }
909
- }
910
- }
911
- for (let i = start; i < scrollHistory.length - 1; i++) {
912
- const entry = scrollHistory[i];
913
- if (newest.time - entry.time <= 1e3) {
914
- oldest = entry;
915
- break;
916
- }
917
- }
918
- if (oldest) {
919
- const scrollDiff = newest.scroll - oldest.scroll;
920
- const timeDiff = newest.time - oldest.time;
921
- velocity = timeDiff > 0 ? scrollDiff / timeDiff : 0;
922
- }
923
- }
924
- return velocity;
925
- };
926
-
927
- // src/requestAdjust.ts
928
- function requestAdjust(ctx, state, positionDiff) {
929
- if (Math.abs(positionDiff) > 0.1) {
930
- const doit = () => {
931
- state.scrollAdjustHandler.requestAdjust(positionDiff);
932
- };
933
- state.scroll += positionDiff;
934
- state.scrollForNextCalculateItemsInView = void 0;
935
- const didLayout = peek$(ctx, "containersDidLayout");
936
- if (didLayout) {
937
- doit();
938
- const threshold = state.scroll - positionDiff / 2;
939
- if (!state.ignoreScrollFromMVCP) {
940
- state.ignoreScrollFromMVCP = {};
941
- }
942
- if (positionDiff > 0) {
943
- state.ignoreScrollFromMVCP.lt = threshold;
944
- } else {
945
- state.ignoreScrollFromMVCP.gt = threshold;
946
- }
947
- if (state.ignoreScrollFromMVCPTimeout) {
948
- clearTimeout(state.ignoreScrollFromMVCPTimeout);
949
- }
950
- state.ignoreScrollFromMVCPTimeout = setTimeout(() => {
951
- state.ignoreScrollFromMVCP = void 0;
952
- }, 100);
953
- } else {
954
- requestAnimationFrame(doit);
955
- }
956
- }
957
- }
958
-
959
- // src/prepareMVCP.ts
960
- function prepareMVCP(ctx, state) {
961
- const {
962
- positions,
963
- scrollingTo,
964
- props: { maintainVisibleContentPosition }
965
- } = state;
966
- let prevPosition;
967
- let targetId;
968
- let targetIndex;
969
- const scrollTarget = scrollingTo == null ? void 0 : scrollingTo.index;
970
- if (maintainVisibleContentPosition) {
971
- const indexByKey = state.indexByKey;
972
- if (scrollTarget !== void 0) {
973
- targetId = getId(state, scrollTarget);
974
- targetIndex = scrollTarget;
975
- } else if (state.idsInView.length > 0 && peek$(ctx, "containersDidLayout")) {
976
- targetId = state.idsInView.find((id) => indexByKey.get(id) !== void 0);
977
- targetIndex = indexByKey.get(targetId);
978
- }
979
- if (targetId !== void 0 && targetIndex !== void 0) {
980
- prevPosition = positions.get(targetId);
981
- }
982
- }
983
- return () => {
984
- if (targetId !== void 0 && prevPosition !== void 0) {
985
- const newPosition = positions.get(targetId);
986
- if (newPosition !== void 0) {
987
- const positionDiff = newPosition - prevPosition;
988
- if (Math.abs(positionDiff) > 0.1) {
989
- requestAdjust(ctx, state, positionDiff);
990
- }
851
+ return () => {
852
+ if (targetId !== void 0 && prevPosition !== void 0) {
853
+ const newPosition = positions.get(targetId);
854
+ if (newPosition !== void 0) {
855
+ const positionDiff = newPosition - prevPosition;
856
+ if (Math.abs(positionDiff) > 0.1) {
857
+ requestAdjust(ctx, state, positionDiff);
858
+ }
991
859
  }
992
860
  }
993
861
  };
994
862
  }
995
863
 
996
- // src/checkThreshold.ts
997
- var checkThreshold = (distance, atThreshold, threshold, isReached, isBlockedByTimer, onReached, blockTimer) => {
998
- const distanceAbs = Math.abs(distance);
999
- const isAtThreshold = atThreshold || distanceAbs < threshold;
1000
- if (!isReached && !isBlockedByTimer) {
1001
- if (isAtThreshold) {
1002
- onReached == null ? void 0 : onReached(distance);
1003
- blockTimer == null ? void 0 : blockTimer(true);
1004
- setTimeout(() => {
1005
- blockTimer == null ? void 0 : blockTimer(false);
1006
- }, 700);
1007
- return true;
1008
- }
1009
- } else {
1010
- if (distance >= 1.3 * threshold) {
1011
- return false;
1012
- }
1013
- }
1014
- return isReached;
1015
- };
1016
-
1017
- // src/checkAtBottom.ts
1018
- function checkAtBottom(ctx, state) {
1019
- if (!state) {
1020
- return;
1021
- }
1022
- const {
1023
- queuedInitialLayout,
1024
- scrollLength,
1025
- scroll,
1026
- maintainingScrollAtEnd,
1027
- props: { maintainScrollAtEndThreshold, onEndReachedThreshold }
1028
- } = state;
1029
- const contentSize = getContentSize(ctx);
1030
- if (contentSize > 0 && queuedInitialLayout && !maintainingScrollAtEnd) {
1031
- const distanceFromEnd = contentSize - scroll - scrollLength;
1032
- const isContentLess = contentSize < scrollLength;
1033
- state.isAtEnd = isContentLess || distanceFromEnd < scrollLength * maintainScrollAtEndThreshold;
1034
- state.isEndReached = checkThreshold(
1035
- distanceFromEnd,
1036
- isContentLess,
1037
- onEndReachedThreshold * scrollLength,
1038
- state.isEndReached,
1039
- state.endReachedBlockedByTimer,
1040
- (distance) => {
1041
- var _a, _b;
1042
- return (_b = (_a = state.props).onEndReached) == null ? void 0 : _b.call(_a, { distanceFromEnd: distance });
1043
- },
1044
- (block) => {
1045
- state.endReachedBlockedByTimer = block;
1046
- }
1047
- );
1048
- }
1049
- }
1050
-
1051
- // src/finishScrollTo.ts
1052
- var finishScrollTo = (state) => {
1053
- if (state) {
1054
- state.scrollingTo = void 0;
1055
- state.scrollHistory.length = 0;
1056
- }
1057
- };
1058
-
1059
- // src/scrollTo.ts
1060
- function scrollTo(state, params = {}) {
1061
- var _a;
1062
- const { animated } = params;
1063
- const {
1064
- refScroller,
1065
- props: { horizontal }
1066
- } = state;
1067
- const offset = calculateOffsetWithOffsetPosition(state, params.offset, params);
1068
- state.scrollHistory.length = 0;
1069
- state.scrollingTo = params;
1070
- state.scrollPending = offset;
1071
- (_a = refScroller.current) == null ? void 0 : _a.scrollTo({
1072
- x: horizontal ? offset : 0,
1073
- y: horizontal ? 0 : offset,
1074
- animated: !!animated
1075
- });
1076
- if (!animated) {
1077
- state.scroll = offset;
1078
- setTimeout(() => finishScrollTo(state), 100);
1079
- }
1080
- }
1081
-
1082
- // src/scrollToIndex.ts
1083
- function scrollToIndex(ctx, state, { index, viewOffset = 0, animated = true, viewPosition }) {
1084
- if (index >= state.props.data.length) {
1085
- index = state.props.data.length - 1;
1086
- } else if (index < 0) {
1087
- index = 0;
1088
- }
1089
- const firstIndexOffset = calculateOffsetForIndex(ctx, state, index);
1090
- const isLast = index === state.props.data.length - 1;
1091
- if (isLast && viewPosition === void 0) {
1092
- viewPosition = 1;
1093
- }
1094
- const firstIndexScrollPostion = firstIndexOffset - viewOffset;
1095
- state.scrollForNextCalculateItemsInView = void 0;
1096
- scrollTo(state, {
1097
- offset: firstIndexScrollPostion,
1098
- animated,
1099
- index,
1100
- viewPosition: viewPosition != null ? viewPosition : 0,
1101
- viewOffset
1102
- });
1103
- }
1104
-
1105
- // src/setDidLayout.ts
1106
- function setDidLayout(ctx, state) {
1107
- const {
1108
- loadStartTime,
1109
- initialScroll,
1110
- props: { onLoad }
1111
- } = state;
1112
- state.queuedInitialLayout = true;
1113
- checkAtBottom(ctx, state);
1114
- if (!IsNewArchitecture && initialScroll) {
1115
- scrollToIndex(ctx, state, { ...initialScroll, animated: false });
1116
- }
1117
- set$(ctx, "containersDidLayout", true);
1118
- if (onLoad) {
1119
- onLoad({ elapsedTimeInMs: Date.now() - loadStartTime });
1120
- }
1121
- }
1122
-
1123
- // src/setPaddingTop.ts
864
+ // src/utils/setPaddingTop.ts
1124
865
  function setPaddingTop(ctx, { stylePaddingTop, alignItemsPaddingTop }) {
1125
866
  if (stylePaddingTop !== void 0) {
1126
867
  const prevStylePaddingTop = peek$(ctx, "stylePaddingTop") || 0;
@@ -1138,7 +879,7 @@ function setPaddingTop(ctx, { stylePaddingTop, alignItemsPaddingTop }) {
1138
879
  }
1139
880
  }
1140
881
 
1141
- // src/updateAlignItemsPaddingTop.ts
882
+ // src/utils/updateAlignItemsPaddingTop.ts
1142
883
  function updateAlignItemsPaddingTop(ctx, state) {
1143
884
  const {
1144
885
  scrollLength,
@@ -1154,7 +895,7 @@ function updateAlignItemsPaddingTop(ctx, state) {
1154
895
  }
1155
896
  }
1156
897
 
1157
- // src/updateTotalSize.ts
898
+ // src/core/updateTotalSize.ts
1158
899
  function updateTotalSize(ctx, state) {
1159
900
  const {
1160
901
  positions,
@@ -1187,10 +928,71 @@ function addTotalSize(ctx, state, key, add) {
1187
928
  }
1188
929
  }
1189
930
 
1190
- // src/updateAllPositions.ts
931
+ // src/utils/getScrollVelocity.ts
932
+ var getScrollVelocity = (state) => {
933
+ const { scrollHistory } = state;
934
+ let velocity = 0;
935
+ if (scrollHistory.length >= 1) {
936
+ const newest = scrollHistory[scrollHistory.length - 1];
937
+ let oldest;
938
+ let start = 0;
939
+ for (let i = 0; i < scrollHistory.length - 1; i++) {
940
+ const entry = scrollHistory[i];
941
+ const nextEntry = scrollHistory[i + 1];
942
+ if (i > 0) {
943
+ const prevEntry = scrollHistory[i - 1];
944
+ const prevDirection = entry.scroll - prevEntry.scroll;
945
+ const currentDirection = nextEntry.scroll - entry.scroll;
946
+ if (prevDirection > 0 && currentDirection < 0 || prevDirection < 0 && currentDirection > 0) {
947
+ start = i;
948
+ break;
949
+ }
950
+ }
951
+ }
952
+ for (let i = start; i < scrollHistory.length - 1; i++) {
953
+ const entry = scrollHistory[i];
954
+ if (newest.time - entry.time <= 1e3) {
955
+ oldest = entry;
956
+ break;
957
+ }
958
+ }
959
+ if (oldest) {
960
+ const scrollDiff = newest.scroll - oldest.scroll;
961
+ const timeDiff = newest.time - oldest.time;
962
+ velocity = timeDiff > 0 ? scrollDiff / timeDiff : 0;
963
+ }
964
+ }
965
+ return velocity;
966
+ };
967
+
968
+ // src/utils/updateSnapToOffsets.ts
969
+ function updateSnapToOffsets(ctx, state) {
970
+ const {
971
+ positions,
972
+ props: { snapToIndices }
973
+ } = state;
974
+ const snapToOffsets = Array(snapToIndices.length);
975
+ for (let i = 0; i < snapToIndices.length; i++) {
976
+ const idx = snapToIndices[i];
977
+ const key = getId(state, idx);
978
+ snapToOffsets[i] = positions.get(key);
979
+ }
980
+ set$(ctx, "snapToOffsets", snapToOffsets);
981
+ }
982
+
983
+ // src/core/updateAllPositions.ts
1191
984
  function updateAllPositions(ctx, state, dataChanged) {
1192
985
  var _a, _b, _c, _d, _e;
1193
- const { averageSizes, columns, indexByKey, positions, firstFullyOnScreenIndex, idCache, sizesKnown } = state;
986
+ const {
987
+ averageSizes,
988
+ columns,
989
+ indexByKey,
990
+ positions,
991
+ firstFullyOnScreenIndex,
992
+ idCache,
993
+ sizesKnown,
994
+ props: { snapToIndices }
995
+ } = state;
1194
996
  const data = state.props.data;
1195
997
  const numColumns = peek$(ctx, "numColumns");
1196
998
  const indexByKeyForChecking = __DEV__ ? /* @__PURE__ */ new Map() : void 0;
@@ -1270,9 +1072,12 @@ function updateAllPositions(ctx, state, dataChanged) {
1270
1072
  }
1271
1073
  }
1272
1074
  updateTotalSize(ctx, state);
1075
+ if (snapToIndices) {
1076
+ updateSnapToOffsets(ctx, state);
1077
+ }
1273
1078
  }
1274
1079
 
1275
- // src/viewability.ts
1080
+ // src/core/viewability.ts
1276
1081
  var mapViewabilityConfigCallbackPairs = /* @__PURE__ */ new Map();
1277
1082
  function setupViewability(props) {
1278
1083
  let { viewabilityConfig, viewabilityConfigCallbackPairs, onViewableItemsChanged } = props;
@@ -1280,27 +1085,31 @@ function setupViewability(props) {
1280
1085
  viewabilityConfigCallbackPairs = [
1281
1086
  ...viewabilityConfigCallbackPairs || [],
1282
1087
  {
1088
+ onViewableItemsChanged,
1283
1089
  viewabilityConfig: viewabilityConfig || {
1284
1090
  viewAreaCoveragePercentThreshold: 0
1285
- },
1286
- onViewableItemsChanged
1091
+ }
1287
1092
  }
1288
1093
  ];
1289
1094
  }
1290
1095
  if (viewabilityConfigCallbackPairs) {
1291
1096
  for (const pair of viewabilityConfigCallbackPairs) {
1292
1097
  mapViewabilityConfigCallbackPairs.set(pair.viewabilityConfig.id, {
1293
- viewableItems: [],
1294
- start: -1,
1295
1098
  end: -1,
1099
+ previousEnd: -1,
1296
1100
  previousStart: -1,
1297
- previousEnd: -1
1101
+ start: -1,
1102
+ viewableItems: []
1298
1103
  });
1299
1104
  }
1300
1105
  }
1301
1106
  return viewabilityConfigCallbackPairs;
1302
1107
  }
1303
1108
  function updateViewableItems(state, ctx, viewabilityConfigCallbackPairs, scrollSize, start, end) {
1109
+ const {
1110
+ timeouts,
1111
+ props: { data }
1112
+ } = state;
1304
1113
  for (const viewabilityConfigCallbackPair of viewabilityConfigCallbackPairs) {
1305
1114
  const viewabilityState = mapViewabilityConfigCallbackPairs.get(
1306
1115
  viewabilityConfigCallbackPair.viewabilityConfig.id
@@ -1309,12 +1118,12 @@ function updateViewableItems(state, ctx, viewabilityConfigCallbackPairs, scrollS
1309
1118
  viewabilityState.end = end;
1310
1119
  if (viewabilityConfigCallbackPair.viewabilityConfig.minimumViewTime) {
1311
1120
  const timer = setTimeout(() => {
1312
- state.timeouts.delete(timer);
1313
- updateViewableItemsWithConfig(state.data, viewabilityConfigCallbackPair, state, ctx, scrollSize);
1121
+ timeouts.delete(timer);
1122
+ updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, state, ctx, scrollSize);
1314
1123
  }, viewabilityConfigCallbackPair.viewabilityConfig.minimumViewTime);
1315
- state.timeouts.add(timer);
1124
+ timeouts.add(timer);
1316
1125
  } else {
1317
- updateViewableItemsWithConfig(state.data, viewabilityConfigCallbackPair, state, ctx, scrollSize);
1126
+ updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, state, ctx, scrollSize);
1318
1127
  }
1319
1128
  }
1320
1129
  }
@@ -1366,11 +1175,11 @@ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, stat
1366
1175
  const containerId = findContainerId(ctx, key);
1367
1176
  if (isViewable(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, i)) {
1368
1177
  const viewToken = {
1369
- item,
1370
- key,
1178
+ containerId,
1371
1179
  index: i,
1372
1180
  isViewable: true,
1373
- containerId
1181
+ item,
1182
+ key
1374
1183
  };
1375
1184
  viewableItems.push(viewToken);
1376
1185
  if (!(previousViewableItems == null ? void 0 : previousViewableItems.find((v) => v.key === viewToken.key))) {
@@ -1380,9 +1189,9 @@ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, stat
1380
1189
  }
1381
1190
  }
1382
1191
  Object.assign(viewabilityState, {
1383
- viewableItems,
1192
+ previousEnd: end,
1384
1193
  previousStart: start,
1385
- previousEnd: end
1194
+ viewableItems
1386
1195
  });
1387
1196
  if (changed.length > 0) {
1388
1197
  viewabilityState.viewableItems = viewableItems;
@@ -1391,74 +1200,284 @@ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, stat
1391
1200
  maybeUpdateViewabilityCallback(ctx, configId, change.containerId, change);
1392
1201
  }
1393
1202
  if (onViewableItemsChanged) {
1394
- onViewableItemsChanged({ viewableItems, changed });
1203
+ onViewableItemsChanged({ changed, viewableItems });
1204
+ }
1205
+ }
1206
+ for (const [containerId, value] of ctx.mapViewabilityAmountValues) {
1207
+ if (value.sizeVisible < 0) {
1208
+ ctx.mapViewabilityAmountValues.delete(containerId);
1209
+ }
1210
+ }
1211
+ }
1212
+ function computeViewability(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index) {
1213
+ const { sizes, positions, scroll: scrollState } = state;
1214
+ const topPad = (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "headerSize") || 0);
1215
+ const { itemVisiblePercentThreshold, viewAreaCoveragePercentThreshold } = viewabilityConfig;
1216
+ const viewAreaMode = viewAreaCoveragePercentThreshold != null;
1217
+ const viewablePercentThreshold = viewAreaMode ? viewAreaCoveragePercentThreshold : itemVisiblePercentThreshold;
1218
+ const scroll = scrollState - topPad;
1219
+ const top = positions.get(key) - scroll;
1220
+ const size = sizes.get(key) || 0;
1221
+ const bottom = top + size;
1222
+ const isEntirelyVisible = top >= 0 && bottom <= scrollSize && bottom > top;
1223
+ const sizeVisible = isEntirelyVisible ? size : Math.min(bottom, scrollSize) - Math.max(top, 0);
1224
+ const percentVisible = size ? isEntirelyVisible ? 100 : 100 * (sizeVisible / size) : 0;
1225
+ const percentOfScroller = size ? 100 * (sizeVisible / scrollSize) : 0;
1226
+ const percent = isEntirelyVisible ? 100 : viewAreaMode ? percentOfScroller : percentVisible;
1227
+ const isViewable2 = percent >= viewablePercentThreshold;
1228
+ const value = {
1229
+ containerId,
1230
+ index,
1231
+ isViewable: isViewable2,
1232
+ item,
1233
+ key,
1234
+ percentOfScroller,
1235
+ percentVisible,
1236
+ scrollSize,
1237
+ size,
1238
+ sizeVisible
1239
+ };
1240
+ if (JSON.stringify(value) !== JSON.stringify(ctx.mapViewabilityAmountValues.get(containerId))) {
1241
+ ctx.mapViewabilityAmountValues.set(containerId, value);
1242
+ const cb = ctx.mapViewabilityAmountCallbacks.get(containerId);
1243
+ if (cb) {
1244
+ cb(value);
1245
+ }
1246
+ }
1247
+ return value;
1248
+ }
1249
+ function isViewable(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index) {
1250
+ const value = ctx.mapViewabilityAmountValues.get(containerId) || computeViewability(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index);
1251
+ return value.isViewable;
1252
+ }
1253
+ function findContainerId(ctx, key) {
1254
+ const numContainers = peek$(ctx, "numContainers");
1255
+ for (let i = 0; i < numContainers; i++) {
1256
+ const itemKey = peek$(ctx, `containerItemKey${i}`);
1257
+ if (itemKey === key) {
1258
+ return i;
1259
+ }
1260
+ }
1261
+ return -1;
1262
+ }
1263
+ function maybeUpdateViewabilityCallback(ctx, configId, containerId, viewToken) {
1264
+ const key = containerId + configId;
1265
+ ctx.mapViewabilityValues.set(key, viewToken);
1266
+ const cb = ctx.mapViewabilityCallbacks.get(key);
1267
+ cb == null ? void 0 : cb(viewToken);
1268
+ }
1269
+
1270
+ // src/utils/checkAllSizesKnown.ts
1271
+ function checkAllSizesKnown(state) {
1272
+ const { startBuffered, endBuffered, sizesKnown } = state;
1273
+ if (endBuffered !== null) {
1274
+ let areAllKnown = true;
1275
+ for (let i = startBuffered; areAllKnown && i <= endBuffered; i++) {
1276
+ const key = getId(state, i);
1277
+ areAllKnown && (areAllKnown = sizesKnown.has(key));
1278
+ }
1279
+ return areAllKnown;
1280
+ }
1281
+ return false;
1282
+ }
1283
+
1284
+ // src/utils/findAvailableContainers.ts
1285
+ function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffered, pendingRemoval) {
1286
+ const numContainers = peek$(ctx, "numContainers");
1287
+ const result = [];
1288
+ const availableContainers = [];
1289
+ for (let u = 0; u < numContainers; u++) {
1290
+ const key = peek$(ctx, `containerItemKey${u}`);
1291
+ let isOk = key === void 0;
1292
+ if (!isOk) {
1293
+ const index = pendingRemoval.indexOf(u);
1294
+ if (index !== -1) {
1295
+ pendingRemoval.splice(index, 1);
1296
+ isOk = true;
1297
+ }
1298
+ }
1299
+ if (isOk) {
1300
+ result.push(u);
1301
+ if (result.length >= numNeeded) {
1302
+ return result;
1303
+ }
1304
+ }
1305
+ }
1306
+ for (let u = 0; u < numContainers; u++) {
1307
+ const key = peek$(ctx, `containerItemKey${u}`);
1308
+ if (key === void 0) continue;
1309
+ const index = state.indexByKey.get(key);
1310
+ if (index < startBuffered) {
1311
+ availableContainers.push({ distance: startBuffered - index, index: u });
1312
+ } else if (index > endBuffered) {
1313
+ availableContainers.push({ distance: index - endBuffered, index: u });
1395
1314
  }
1396
1315
  }
1397
- for (const [containerId, value] of ctx.mapViewabilityAmountValues) {
1398
- if (value.sizeVisible < 0) {
1399
- ctx.mapViewabilityAmountValues.delete(containerId);
1316
+ const remaining = numNeeded - result.length;
1317
+ if (remaining > 0) {
1318
+ if (availableContainers.length > 0) {
1319
+ if (availableContainers.length > remaining) {
1320
+ availableContainers.sort(comparatorByDistance);
1321
+ availableContainers.length = remaining;
1322
+ }
1323
+ for (const container of availableContainers) {
1324
+ result.push(container.index);
1325
+ }
1326
+ }
1327
+ const stillNeeded = numNeeded - result.length;
1328
+ if (stillNeeded > 0) {
1329
+ for (let i = 0; i < stillNeeded; i++) {
1330
+ result.push(numContainers + i);
1331
+ }
1332
+ if (__DEV__ && numContainers + stillNeeded > peek$(ctx, "numContainersPooled")) {
1333
+ console.warn(
1334
+ "[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.",
1335
+ {
1336
+ debugInfo: {
1337
+ numContainers,
1338
+ numContainersPooled: peek$(ctx, "numContainersPooled"),
1339
+ numNeeded,
1340
+ stillNeeded
1341
+ }
1342
+ }
1343
+ );
1344
+ }
1400
1345
  }
1401
1346
  }
1347
+ return result.sort(comparatorDefault);
1402
1348
  }
1403
- function computeViewability(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index) {
1404
- const { sizes, positions, scroll: scrollState } = state;
1405
- const topPad = (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "headerSize") || 0);
1406
- const { itemVisiblePercentThreshold, viewAreaCoveragePercentThreshold } = viewabilityConfig;
1407
- const viewAreaMode = viewAreaCoveragePercentThreshold != null;
1408
- const viewablePercentThreshold = viewAreaMode ? viewAreaCoveragePercentThreshold : itemVisiblePercentThreshold;
1409
- const scroll = scrollState - topPad;
1410
- const top = positions.get(key) - scroll;
1411
- const size = sizes.get(key) || 0;
1412
- const bottom = top + size;
1413
- const isEntirelyVisible = top >= 0 && bottom <= scrollSize && bottom > top;
1414
- const sizeVisible = isEntirelyVisible ? size : Math.min(bottom, scrollSize) - Math.max(top, 0);
1415
- const percentVisible = size ? isEntirelyVisible ? 100 : 100 * (sizeVisible / size) : 0;
1416
- const percentOfScroller = size ? 100 * (sizeVisible / scrollSize) : 0;
1417
- const percent = isEntirelyVisible ? 100 : viewAreaMode ? percentOfScroller : percentVisible;
1418
- const isViewable2 = percent >= viewablePercentThreshold;
1419
- const value = {
1420
- index,
1421
- isViewable: isViewable2,
1422
- item,
1423
- key,
1424
- percentVisible,
1425
- percentOfScroller,
1426
- sizeVisible,
1427
- size,
1428
- scrollSize,
1429
- containerId
1430
- };
1431
- if (JSON.stringify(value) !== JSON.stringify(ctx.mapViewabilityAmountValues.get(containerId))) {
1432
- ctx.mapViewabilityAmountValues.set(containerId, value);
1433
- const cb = ctx.mapViewabilityAmountCallbacks.get(containerId);
1434
- if (cb) {
1435
- cb(value);
1436
- }
1349
+ function comparatorByDistance(a, b) {
1350
+ return b.distance - a.distance;
1351
+ }
1352
+
1353
+ // src/core/finishScrollTo.ts
1354
+ var finishScrollTo = (state) => {
1355
+ if (state) {
1356
+ state.scrollingTo = void 0;
1357
+ state.scrollHistory.length = 0;
1358
+ }
1359
+ };
1360
+
1361
+ // src/core/scrollTo.ts
1362
+ function scrollTo(state, params = {}) {
1363
+ var _a;
1364
+ const { animated } = params;
1365
+ const {
1366
+ refScroller,
1367
+ props: { horizontal }
1368
+ } = state;
1369
+ const offset = calculateOffsetWithOffsetPosition(state, params.offset, params);
1370
+ state.scrollHistory.length = 0;
1371
+ state.scrollingTo = params;
1372
+ state.scrollPending = offset;
1373
+ (_a = refScroller.current) == null ? void 0 : _a.scrollTo({
1374
+ animated: !!animated,
1375
+ x: horizontal ? offset : 0,
1376
+ y: horizontal ? 0 : offset
1377
+ });
1378
+ if (!animated) {
1379
+ state.scroll = offset;
1380
+ setTimeout(() => finishScrollTo(state), 100);
1437
1381
  }
1438
- return value;
1439
1382
  }
1440
- function isViewable(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index) {
1441
- const value = ctx.mapViewabilityAmountValues.get(containerId) || computeViewability(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index);
1442
- return value.isViewable;
1383
+
1384
+ // src/core/scrollToIndex.ts
1385
+ function scrollToIndex(ctx, state, { index, viewOffset = 0, animated = true, viewPosition }) {
1386
+ if (index >= state.props.data.length) {
1387
+ index = state.props.data.length - 1;
1388
+ } else if (index < 0) {
1389
+ index = 0;
1390
+ }
1391
+ const firstIndexOffset = calculateOffsetForIndex(ctx, state, index);
1392
+ const isLast = index === state.props.data.length - 1;
1393
+ if (isLast && viewPosition === void 0) {
1394
+ viewPosition = 1;
1395
+ }
1396
+ const firstIndexScrollPostion = firstIndexOffset - viewOffset;
1397
+ state.scrollForNextCalculateItemsInView = void 0;
1398
+ scrollTo(state, {
1399
+ animated,
1400
+ index,
1401
+ offset: firstIndexScrollPostion,
1402
+ viewOffset,
1403
+ viewPosition: viewPosition != null ? viewPosition : 0
1404
+ });
1443
1405
  }
1444
- function findContainerId(ctx, key) {
1445
- const numContainers = peek$(ctx, "numContainers");
1446
- for (let i = 0; i < numContainers; i++) {
1447
- const itemKey = peek$(ctx, `containerItemKey${i}`);
1448
- if (itemKey === key) {
1449
- return i;
1406
+
1407
+ // src/utils/checkThreshold.ts
1408
+ var checkThreshold = (distance, atThreshold, threshold, isReached, isBlockedByTimer, onReached, blockTimer) => {
1409
+ const distanceAbs = Math.abs(distance);
1410
+ const isAtThreshold = atThreshold || distanceAbs < threshold;
1411
+ if (!isReached && !isBlockedByTimer) {
1412
+ if (isAtThreshold) {
1413
+ onReached == null ? void 0 : onReached(distance);
1414
+ blockTimer == null ? void 0 : blockTimer(true);
1415
+ setTimeout(() => {
1416
+ blockTimer == null ? void 0 : blockTimer(false);
1417
+ }, 700);
1418
+ return true;
1419
+ }
1420
+ } else {
1421
+ if (distance >= 1.3 * threshold) {
1422
+ return false;
1450
1423
  }
1451
1424
  }
1452
- return -1;
1425
+ return isReached;
1426
+ };
1427
+
1428
+ // src/utils/checkAtBottom.ts
1429
+ function checkAtBottom(ctx, state) {
1430
+ if (!state) {
1431
+ return;
1432
+ }
1433
+ const {
1434
+ queuedInitialLayout,
1435
+ scrollLength,
1436
+ scroll,
1437
+ maintainingScrollAtEnd,
1438
+ props: { maintainScrollAtEndThreshold, onEndReachedThreshold }
1439
+ } = state;
1440
+ const contentSize = getContentSize(ctx);
1441
+ if (contentSize > 0 && queuedInitialLayout && !maintainingScrollAtEnd) {
1442
+ const distanceFromEnd = contentSize - scroll - scrollLength;
1443
+ const isContentLess = contentSize < scrollLength;
1444
+ state.isAtEnd = isContentLess || distanceFromEnd < scrollLength * maintainScrollAtEndThreshold;
1445
+ state.isEndReached = checkThreshold(
1446
+ distanceFromEnd,
1447
+ isContentLess,
1448
+ onEndReachedThreshold * scrollLength,
1449
+ state.isEndReached,
1450
+ state.endReachedBlockedByTimer,
1451
+ (distance) => {
1452
+ var _a, _b;
1453
+ return (_b = (_a = state.props).onEndReached) == null ? void 0 : _b.call(_a, { distanceFromEnd: distance });
1454
+ },
1455
+ (block) => {
1456
+ state.endReachedBlockedByTimer = block;
1457
+ }
1458
+ );
1459
+ }
1453
1460
  }
1454
- function maybeUpdateViewabilityCallback(ctx, configId, containerId, viewToken) {
1455
- const key = containerId + configId;
1456
- ctx.mapViewabilityValues.set(key, viewToken);
1457
- const cb = ctx.mapViewabilityCallbacks.get(key);
1458
- cb == null ? void 0 : cb(viewToken);
1461
+
1462
+ // src/utils/setDidLayout.ts
1463
+ function setDidLayout(ctx, state) {
1464
+ const {
1465
+ loadStartTime,
1466
+ initialScroll,
1467
+ props: { onLoad }
1468
+ } = state;
1469
+ state.queuedInitialLayout = true;
1470
+ checkAtBottom(ctx, state);
1471
+ if (!IsNewArchitecture && initialScroll) {
1472
+ scrollToIndex(ctx, state, { ...initialScroll, animated: false });
1473
+ }
1474
+ set$(ctx, "containersDidLayout", true);
1475
+ if (onLoad) {
1476
+ onLoad({ elapsedTimeInMs: Date.now() - loadStartTime });
1477
+ }
1459
1478
  }
1460
1479
 
1461
- // src/calculateItemsInView.ts
1480
+ // src/core/calculateItemsInView.ts
1462
1481
  function calculateItemsInView(ctx, state, params = {}) {
1463
1482
  var _a, _b, _c, _d, _e, _f, _g, _h;
1464
1483
  const {
@@ -1475,7 +1494,8 @@ function calculateItemsInView(ctx, state, params = {}) {
1475
1494
  minIndexSizeChanged
1476
1495
  } = state;
1477
1496
  const data = state.props.data;
1478
- if (!data || scrollLength === 0) {
1497
+ const prevNumContainers = peek$(ctx, "numContainers");
1498
+ if (!data || scrollLength === 0 || !prevNumContainers) {
1479
1499
  return;
1480
1500
  }
1481
1501
  const totalSize = peek$(ctx, "totalSize");
@@ -1557,7 +1577,6 @@ function calculateItemsInView(ctx, state, params = {}) {
1557
1577
  let foundEnd = false;
1558
1578
  let nextTop;
1559
1579
  let nextBottom;
1560
- const prevNumContainers = ctx.values.get("numContainers");
1561
1580
  let maxIndexRendered = 0;
1562
1581
  for (let i = 0; i < prevNumContainers; i++) {
1563
1582
  const key = peek$(ctx, `containerItemKey${i}`);
@@ -1603,18 +1622,18 @@ function calculateItemsInView(ctx, state, params = {}) {
1603
1622
  idsInView.push(id);
1604
1623
  }
1605
1624
  Object.assign(state, {
1606
- startBuffered,
1607
- startBufferedId,
1608
- startNoBuffer,
1609
1625
  endBuffered,
1610
1626
  endNoBuffer,
1627
+ firstFullyOnScreenIndex,
1611
1628
  idsInView,
1612
- firstFullyOnScreenIndex
1629
+ startBuffered,
1630
+ startBufferedId,
1631
+ startNoBuffer
1613
1632
  });
1614
1633
  if (enableScrollForNextCalculateItemsInView && nextTop !== void 0 && nextBottom !== void 0) {
1615
1634
  state.scrollForNextCalculateItemsInView = nextTop !== void 0 && nextBottom !== void 0 ? {
1616
- top: nextTop,
1617
- bottom: nextBottom
1635
+ bottom: nextBottom,
1636
+ top: nextTop
1618
1637
  } : void 0;
1619
1638
  }
1620
1639
  const numContainers = peek$(ctx, "numContainers");
@@ -1701,71 +1720,28 @@ function calculateItemsInView(ctx, state, params = {}) {
1701
1720
  if (prevData !== item) {
1702
1721
  set$(ctx, `containerItemData${i}`, data[itemIndex]);
1703
1722
  }
1704
- }
1705
- }
1706
- }
1707
- }
1708
- if (!queuedInitialLayout && endBuffered !== null) {
1709
- if (checkAllSizesKnown(state)) {
1710
- setDidLayout(ctx, state);
1711
- }
1712
- }
1713
- if (state.props.viewabilityConfigCallbackPairs) {
1714
- updateViewableItems(
1715
- state,
1716
- ctx,
1717
- state.props.viewabilityConfigCallbackPairs,
1718
- scrollLength,
1719
- startNoBuffer,
1720
- endNoBuffer
1721
- );
1722
- }
1723
- }
1724
-
1725
- // src/checkAtTop.ts
1726
- function checkAtTop(state) {
1727
- if (!state) {
1728
- return;
1729
- }
1730
- const {
1731
- scrollLength,
1732
- scroll,
1733
- props: { onStartReachedThreshold }
1734
- } = state;
1735
- const distanceFromTop = scroll;
1736
- state.isAtStart = distanceFromTop <= 0;
1737
- state.isStartReached = checkThreshold(
1738
- distanceFromTop,
1739
- false,
1740
- onStartReachedThreshold * scrollLength,
1741
- state.isStartReached,
1742
- state.startReachedBlockedByTimer,
1743
- (distance) => {
1744
- var _a, _b;
1745
- return (_b = (_a = state.props).onStartReached) == null ? void 0 : _b.call(_a, { distanceFromStart: distance });
1746
- },
1747
- (block) => {
1748
- state.startReachedBlockedByTimer = block;
1749
- }
1750
- );
1751
- }
1752
-
1753
- // src/createColumnWrapperStyle.ts
1754
- function createColumnWrapperStyle(contentContainerStyle) {
1755
- const { gap, columnGap, rowGap } = contentContainerStyle;
1756
- if (gap || columnGap || rowGap) {
1757
- contentContainerStyle.gap = void 0;
1758
- contentContainerStyle.columnGap = void 0;
1759
- contentContainerStyle.rowGap = void 0;
1760
- return {
1761
- gap,
1762
- columnGap,
1763
- rowGap
1764
- };
1723
+ }
1724
+ }
1725
+ }
1726
+ }
1727
+ if (!queuedInitialLayout && endBuffered !== null) {
1728
+ if (checkAllSizesKnown(state)) {
1729
+ setDidLayout(ctx, state);
1730
+ }
1731
+ }
1732
+ if (state.props.viewabilityConfigCallbackPairs) {
1733
+ updateViewableItems(
1734
+ state,
1735
+ ctx,
1736
+ state.props.viewabilityConfigCallbackPairs,
1737
+ scrollLength,
1738
+ startNoBuffer,
1739
+ endNoBuffer
1740
+ );
1765
1741
  }
1766
1742
  }
1767
1743
 
1768
- // src/doInitialAllocateContainers.ts
1744
+ // src/core/doInitialAllocateContainers.ts
1769
1745
  function doInitialAllocateContainers(ctx, state) {
1770
1746
  const { scrollLength } = state;
1771
1747
  const data = state.props.data;
@@ -1794,7 +1770,7 @@ function doInitialAllocateContainers(ctx, state) {
1794
1770
  }
1795
1771
  }
1796
1772
 
1797
- // src/doMaintainScrollAtEnd.ts
1773
+ // src/core/doMaintainScrollAtEnd.ts
1798
1774
  function doMaintainScrollAtEnd(ctx, state, animated) {
1799
1775
  const {
1800
1776
  refScroller,
@@ -1821,31 +1797,36 @@ function doMaintainScrollAtEnd(ctx, state, animated) {
1821
1797
  return true;
1822
1798
  }
1823
1799
  }
1824
- function getRenderedItem(ctx, state, key) {
1800
+
1801
+ // src/utils/checkAtTop.ts
1802
+ function checkAtTop(state) {
1825
1803
  if (!state) {
1826
- return null;
1804
+ return;
1827
1805
  }
1828
1806
  const {
1829
- indexByKey,
1830
- props: { data, renderItem: renderItem2 }
1807
+ scrollLength,
1808
+ scroll,
1809
+ props: { onStartReachedThreshold }
1831
1810
  } = state;
1832
- const index = indexByKey.get(key);
1833
- if (index === void 0) {
1834
- return null;
1835
- }
1836
- let renderedItem = null;
1837
- if (renderItem2) {
1838
- const itemProps = {
1839
- item: data[index],
1840
- index,
1841
- extraData: peek$(ctx, "extraData")
1842
- };
1843
- renderedItem = React3__namespace.default.createElement(renderItem2, itemProps);
1844
- }
1845
- return { index, item: data[index], renderedItem };
1811
+ const distanceFromTop = scroll;
1812
+ state.isAtStart = distanceFromTop <= 0;
1813
+ state.isStartReached = checkThreshold(
1814
+ distanceFromTop,
1815
+ false,
1816
+ onStartReachedThreshold * scrollLength,
1817
+ state.isStartReached,
1818
+ state.startReachedBlockedByTimer,
1819
+ (distance) => {
1820
+ var _a, _b;
1821
+ return (_b = (_a = state.props).onStartReached) == null ? void 0 : _b.call(_a, { distanceFromStart: distance });
1822
+ },
1823
+ (block) => {
1824
+ state.startReachedBlockedByTimer = block;
1825
+ }
1826
+ );
1846
1827
  }
1847
1828
 
1848
- // src/handleLayout.ts
1829
+ // src/core/handleLayout.ts
1849
1830
  function handleLayout(ctx, state, layout, setCanRender) {
1850
1831
  const { maintainScrollAtEnd } = state.props;
1851
1832
  const scrollLength = layout[state.props.horizontal ? "width" : "height"];
@@ -1863,7 +1844,7 @@ function handleLayout(ctx, state, layout, setCanRender) {
1863
1844
  calculateItemsInView(ctx, state, { doMVCP: true });
1864
1845
  }
1865
1846
  if (didChange || otherAxisSize !== prevOtherAxisSize) {
1866
- set$(ctx, "scrollSize", { width: layout.width, height: layout.height });
1847
+ set$(ctx, "scrollSize", { height: layout.height, width: layout.width });
1867
1848
  }
1868
1849
  if (maintainScrollAtEnd === true || maintainScrollAtEnd.onLayout) {
1869
1850
  doMaintainScrollAtEnd(ctx, state, false);
@@ -1883,7 +1864,7 @@ function handleLayout(ctx, state, layout, setCanRender) {
1883
1864
  setCanRender(true);
1884
1865
  }
1885
1866
 
1886
- // src/onScroll.ts
1867
+ // src/core/onScroll.ts
1887
1868
  function onScroll(ctx, state, event) {
1888
1869
  var _a, _b, _c, _d, _e;
1889
1870
  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) {
@@ -1921,7 +1902,29 @@ function updateScroll(ctx, state, newScroll) {
1921
1902
  checkAtTop(state);
1922
1903
  }
1923
1904
 
1924
- // src/updateItemSize.ts
1905
+ // src/core/ScrollAdjustHandler.ts
1906
+ var ScrollAdjustHandler = class {
1907
+ constructor(ctx) {
1908
+ this.appliedAdjust = 0;
1909
+ this.mounted = false;
1910
+ this.context = ctx;
1911
+ }
1912
+ requestAdjust(add) {
1913
+ const oldAdjustTop = peek$(this.context, "scrollAdjust") || 0;
1914
+ this.appliedAdjust = add + oldAdjustTop;
1915
+ const set = () => set$(this.context, "scrollAdjust", this.appliedAdjust);
1916
+ if (this.mounted) {
1917
+ set();
1918
+ } else {
1919
+ requestAnimationFrame(set);
1920
+ }
1921
+ }
1922
+ setMounted() {
1923
+ this.mounted = true;
1924
+ }
1925
+ };
1926
+
1927
+ // src/core/updateItemSize.ts
1925
1928
  function updateItemSizes(ctx, state, itemUpdates) {
1926
1929
  var _a;
1927
1930
  const {
@@ -1935,7 +1938,8 @@ function updateItemSizes(ctx, state, itemUpdates) {
1935
1938
  }
1936
1939
  } = state;
1937
1940
  if (!data) return;
1938
- let needsRecalculate = false;
1941
+ const containersDidLayout = peek$(ctx, "containersDidLayout");
1942
+ let needsRecalculate = !containersDidLayout;
1939
1943
  let shouldMaintainScrollAtEnd = false;
1940
1944
  let minIndexSizeChanged;
1941
1945
  let maxOtherAxisSize = peek$(ctx, "otherAxisSize") || 0;
@@ -1946,7 +1950,7 @@ function updateItemSizes(ctx, state, itemUpdates) {
1946
1950
  const size = Math.floor((horizontal ? sizeObj.width : sizeObj.height) * 8) / 8;
1947
1951
  if (diff !== 0) {
1948
1952
  minIndexSizeChanged = minIndexSizeChanged !== void 0 ? Math.min(minIndexSizeChanged, index) : index;
1949
- if (((_a = state.scrollingTo) == null ? void 0 : _a.viewPosition) && maintainVisibleContentPosition && index === state.scrollingTo.index) {
1953
+ if (((_a = state.scrollingTo) == null ? void 0 : _a.viewPosition) && maintainVisibleContentPosition && index === state.scrollingTo.index && diff > 0) {
1950
1954
  requestAdjust(ctx, state, diff * state.scrollingTo.viewPosition);
1951
1955
  }
1952
1956
  const { startBuffered, endBuffered } = state;
@@ -1968,11 +1972,11 @@ function updateItemSizes(ctx, state, itemUpdates) {
1968
1972
  shouldMaintainScrollAtEnd = true;
1969
1973
  }
1970
1974
  onItemSizeChanged == null ? void 0 : onItemSizeChanged({
1971
- size,
1972
- previous: size - diff,
1973
1975
  index,
1976
+ itemData: state.props.data[index],
1974
1977
  itemKey,
1975
- itemData: state.props.data[index]
1978
+ previous: size - diff,
1979
+ size
1976
1980
  });
1977
1981
  }
1978
1982
  }
@@ -1995,7 +1999,6 @@ function updateItemSizes(ctx, state, itemUpdates) {
1995
1999
  if (!cur || maxOtherAxisSize > cur) {
1996
2000
  set$(ctx, "otherAxisSize", maxOtherAxisSize);
1997
2001
  }
1998
- const containersDidLayout = peek$(ctx, "containersDidLayout");
1999
2002
  if (containersDidLayout || checkAllSizesKnown(state)) {
2000
2003
  if (needsRecalculate) {
2001
2004
  state.scrollForNextCalculateItemsInView = void 0;
@@ -2011,7 +2014,7 @@ function updateItemSizes(ctx, state, itemUpdates) {
2011
2014
  function updateItemSize(ctx, state, itemKey, sizeObj) {
2012
2015
  if (IsNewArchitecture) {
2013
2016
  const { sizesKnown } = state;
2014
- const numContainers = ctx.values.get("numContainers");
2017
+ const numContainers = peek$(ctx, "numContainers");
2015
2018
  const changes = [];
2016
2019
  for (let i = 0; i < numContainers; i++) {
2017
2020
  const containerItemKey = peek$(ctx, `containerItemKey${i}`);
@@ -2022,7 +2025,7 @@ function updateItemSize(ctx, state, itemKey, sizeObj) {
2022
2025
  if (containerRef == null ? void 0 : containerRef.current) {
2023
2026
  let measured;
2024
2027
  containerRef.current.measure((x, y, width, height) => {
2025
- measured = { x, y, width, height };
2028
+ measured = { height, width, x, y };
2026
2029
  });
2027
2030
  if (measured) {
2028
2031
  changes.push({ itemKey: containerItemKey, sizeObj: measured });
@@ -2053,7 +2056,7 @@ function updateOneItemSize(state, itemKey, sizeObj) {
2053
2056
  const itemType = "";
2054
2057
  let averages = averageSizes[itemType];
2055
2058
  if (!averages) {
2056
- averages = averageSizes[itemType] = { num: 0, avg: 0 };
2059
+ averages = averageSizes[itemType] = { avg: 0, num: 0 };
2057
2060
  }
2058
2061
  averages.avg = (averages.avg * averages.num + size) / (averages.num + 1);
2059
2062
  averages.num++;
@@ -2079,7 +2082,45 @@ var useCombinedRef = (...refs) => {
2079
2082
  return callback;
2080
2083
  };
2081
2084
 
2082
- // src/LegendList.tsx
2085
+ // src/utils/createColumnWrapperStyle.ts
2086
+ function createColumnWrapperStyle(contentContainerStyle) {
2087
+ const { gap, columnGap, rowGap } = contentContainerStyle;
2088
+ if (gap || columnGap || rowGap) {
2089
+ contentContainerStyle.gap = void 0;
2090
+ contentContainerStyle.columnGap = void 0;
2091
+ contentContainerStyle.rowGap = void 0;
2092
+ return {
2093
+ columnGap,
2094
+ gap,
2095
+ rowGap
2096
+ };
2097
+ }
2098
+ }
2099
+ function getRenderedItem(ctx, state, key) {
2100
+ if (!state) {
2101
+ return null;
2102
+ }
2103
+ const {
2104
+ indexByKey,
2105
+ props: { data, renderItem: renderItem2 }
2106
+ } = state;
2107
+ const index = indexByKey.get(key);
2108
+ if (index === void 0) {
2109
+ return null;
2110
+ }
2111
+ let renderedItem = null;
2112
+ if (renderItem2) {
2113
+ const itemProps = {
2114
+ extraData: peek$(ctx, "extraData"),
2115
+ index,
2116
+ item: data[index]
2117
+ };
2118
+ renderedItem = React3__namespace.default.createElement(renderItem2, itemProps);
2119
+ }
2120
+ return { index, item: data[index], renderedItem };
2121
+ }
2122
+
2123
+ // src/components/LegendList.tsx
2083
2124
  var DEFAULT_DRAW_DISTANCE = 250;
2084
2125
  var DEFAULT_ITEM_SIZE = 100;
2085
2126
  var LegendList = typedForwardRef(function LegendList2(props, forwardedRef) {
@@ -2126,6 +2167,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2126
2167
  initialContainerPoolRatio = 2,
2127
2168
  viewabilityConfig,
2128
2169
  viewabilityConfigCallbackPairs,
2170
+ snapToIndices,
2129
2171
  onViewableItemsChanged,
2130
2172
  onStartReached,
2131
2173
  onEndReached,
@@ -2146,55 +2188,55 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2146
2188
  const combinedRef = useCombinedRef(refScroller, refScrollView);
2147
2189
  const estimatedItemSize = estimatedItemSizeProp != null ? estimatedItemSizeProp : DEFAULT_ITEM_SIZE;
2148
2190
  const scrollBuffer = (drawDistance != null ? drawDistance : DEFAULT_DRAW_DISTANCE) || 1;
2149
- const keyExtractor = keyExtractorProp != null ? keyExtractorProp : (item, index) => index.toString();
2191
+ const keyExtractor = keyExtractorProp != null ? keyExtractorProp : (_item, index) => index.toString();
2150
2192
  const refState = React3.useRef();
2151
2193
  if (!refState.current) {
2152
- const initialScrollLength = (estimatedListSize != null ? estimatedListSize : IsNewArchitecture ? { width: 0, height: 0 } : reactNative.Dimensions.get("window"))[horizontal ? "width" : "height"];
2194
+ const initialScrollLength = (estimatedListSize != null ? estimatedListSize : IsNewArchitecture ? { height: 0, width: 0 } : reactNative.Dimensions.get("window"))[horizontal ? "width" : "height"];
2153
2195
  refState.current = {
2154
- sizes: /* @__PURE__ */ new Map(),
2155
- positions: /* @__PURE__ */ new Map(),
2196
+ averageSizes: {},
2156
2197
  columns: /* @__PURE__ */ new Map(),
2157
- pendingAdjust: 0,
2158
- isStartReached: false,
2159
- isEndReached: false,
2160
- isAtEnd: false,
2161
- isAtStart: false,
2162
- scrollLength: initialScrollLength,
2163
- startBuffered: -1,
2164
- startNoBuffer: -1,
2198
+ containerItemKeys: /* @__PURE__ */ new Set(),
2199
+ enableScrollForNextCalculateItemsInView: true,
2165
2200
  endBuffered: -1,
2166
2201
  endNoBuffer: -1,
2202
+ endReachedBlockedByTimer: false,
2167
2203
  firstFullyOnScreenIndex: -1,
2204
+ idCache: /* @__PURE__ */ new Map(),
2205
+ idsInView: [],
2206
+ indexByKey: /* @__PURE__ */ new Map(),
2207
+ initialScroll,
2208
+ isAtEnd: false,
2209
+ isAtStart: false,
2210
+ isEndReached: false,
2211
+ isStartReached: false,
2212
+ lastBatchingAction: Date.now(),
2213
+ lastLayout: void 0,
2214
+ loadStartTime: Date.now(),
2215
+ minIndexSizeChanged: 0,
2216
+ nativeMarginTop: 0,
2217
+ pendingAdjust: 0,
2218
+ positions: /* @__PURE__ */ new Map(),
2219
+ props: {},
2220
+ queuedCalculateItemsInView: 0,
2221
+ refScroller: void 0,
2168
2222
  scroll: 0,
2169
- totalSize: 0,
2170
- timeouts: /* @__PURE__ */ new Set(),
2171
- viewabilityConfigCallbackPairs: void 0,
2172
2223
  scrollAdjustHandler: new ScrollAdjustHandler(ctx),
2173
- nativeMarginTop: 0,
2224
+ scrollForNextCalculateItemsInView: void 0,
2225
+ scrollHistory: [],
2226
+ scrollLength: initialScrollLength,
2227
+ scrollPending: 0,
2174
2228
  scrollPrev: 0,
2175
2229
  scrollPrevTime: 0,
2176
2230
  scrollTime: 0,
2177
- scrollPending: 0,
2178
- indexByKey: /* @__PURE__ */ new Map(),
2179
- scrollHistory: [],
2231
+ sizes: /* @__PURE__ */ new Map(),
2180
2232
  sizesKnown: /* @__PURE__ */ new Map(),
2181
- timeoutSizeMessage: 0,
2233
+ startBuffered: -1,
2234
+ startNoBuffer: -1,
2182
2235
  startReachedBlockedByTimer: false,
2183
- endReachedBlockedByTimer: false,
2184
- scrollForNextCalculateItemsInView: void 0,
2185
- enableScrollForNextCalculateItemsInView: true,
2186
- minIndexSizeChanged: 0,
2187
- queuedCalculateItemsInView: 0,
2188
- lastBatchingAction: Date.now(),
2189
- averageSizes: {},
2190
- idsInView: [],
2191
- containerItemKeys: /* @__PURE__ */ new Set(),
2192
- idCache: /* @__PURE__ */ new Map(),
2193
- props: {},
2194
- refScroller: void 0,
2195
- loadStartTime: Date.now(),
2196
- initialScroll,
2197
- lastLayout: void 0
2236
+ timeoutSizeMessage: 0,
2237
+ timeouts: /* @__PURE__ */ new Set(),
2238
+ totalSize: 0,
2239
+ viewabilityConfigCallbackPairs: void 0
2198
2240
  };
2199
2241
  set$(ctx, "maintainVisibleContentPosition", maintainVisibleContentPosition);
2200
2242
  set$(ctx, "extraData", extraData);
@@ -2206,28 +2248,29 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2206
2248
  alignItemsAtEnd,
2207
2249
  data: dataProp,
2208
2250
  estimatedItemSize,
2251
+ getEstimatedItemSize,
2252
+ horizontal: !!horizontal,
2253
+ initialContainerPoolRatio,
2254
+ initialScroll,
2255
+ keyExtractor,
2209
2256
  maintainScrollAtEnd,
2210
2257
  maintainScrollAtEndThreshold,
2211
- onEndReachedThreshold,
2212
- onStartReachedThreshold,
2213
- stylePaddingBottom: stylePaddingBottomState,
2214
- horizontal: !!horizontal,
2215
2258
  maintainVisibleContentPosition,
2259
+ numColumns: numColumnsProp,
2260
+ onEndReached,
2261
+ onEndReachedThreshold,
2216
2262
  onItemSizeChanged,
2217
- suggestEstimatedItemSize: !!suggestEstimatedItemSize,
2218
- keyExtractor,
2263
+ onLoad,
2219
2264
  onScroll: onScrollProp,
2220
- getEstimatedItemSize,
2221
2265
  onStartReached,
2222
- onEndReached,
2223
- onLoad,
2266
+ onStartReachedThreshold,
2224
2267
  renderItem: renderItem2,
2225
- initialScroll,
2226
2268
  scrollBuffer,
2227
- viewabilityConfigCallbackPairs: void 0,
2228
- numColumns: numColumnsProp,
2229
- initialContainerPoolRatio,
2230
- stylePaddingTop: stylePaddingTopState
2269
+ snapToIndices,
2270
+ stylePaddingBottom: stylePaddingBottomState,
2271
+ stylePaddingTop: stylePaddingTopState,
2272
+ suggestEstimatedItemSize: !!suggestEstimatedItemSize,
2273
+ viewabilityConfigCallbackPairs: void 0
2231
2274
  };
2232
2275
  state.refScroller = refScroller;
2233
2276
  const checkResetContainers = (isFirst2) => {
@@ -2275,7 +2318,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2275
2318
  const initialContentOffset2 = initialScrollOffset || calculateOffsetForIndex(ctx, state, initialScrollIndex);
2276
2319
  refState.current.isStartReached = initialContentOffset2 < refState.current.scrollLength * onStartReachedThreshold;
2277
2320
  if (initialContentOffset2 > 0) {
2278
- scrollTo(state, { offset: initialContentOffset2, animated: false, index: initialScrollIndex });
2321
+ scrollTo(state, { animated: false, index: initialScrollIndex, offset: initialContentOffset2 });
2279
2322
  }
2280
2323
  return initialContentOffset2;
2281
2324
  }, [renderNum]);
@@ -2294,7 +2337,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2294
2337
  if (IsNewArchitecture) {
2295
2338
  let measured;
2296
2339
  refScroller.current.measure((x, y, width, height) => {
2297
- measured = { x, y, width, height };
2340
+ measured = { height, width, x, y };
2298
2341
  });
2299
2342
  if (measured) {
2300
2343
  const size = Math.floor(measured[horizontal ? "width" : "height"] * 8) / 8;
@@ -2322,6 +2365,11 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2322
2365
  }
2323
2366
  }
2324
2367
  }, []);
2368
+ React3.useLayoutEffect(() => {
2369
+ if (snapToIndices) {
2370
+ updateSnapToOffsets(ctx, state);
2371
+ }
2372
+ }, [snapToIndices]);
2325
2373
  React3.useLayoutEffect(() => {
2326
2374
  const didAllocateContainers = doInitialAllocateContainersCallback();
2327
2375
  if (!didAllocateContainers) {
@@ -2345,9 +2393,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2345
2393
  };
2346
2394
  React3.useEffect(() => {
2347
2395
  const viewability = setupViewability({
2396
+ onViewableItemsChanged,
2348
2397
  viewabilityConfig,
2349
- viewabilityConfigCallbackPairs,
2350
- onViewableItemsChanged
2398
+ viewabilityConfigCallbackPairs
2351
2399
  });
2352
2400
  state.viewabilityConfigCallbackPairs = viewability;
2353
2401
  state.props.viewabilityConfigCallbackPairs = viewability;
@@ -2365,97 +2413,94 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2365
2413
  onLayoutProp(event);
2366
2414
  }
2367
2415
  }, []);
2368
- React3.useImperativeHandle(
2369
- forwardedRef,
2370
- () => {
2371
- const scrollIndexIntoView = (options) => {
2416
+ React3.useImperativeHandle(forwardedRef, () => {
2417
+ const scrollIndexIntoView = (options) => {
2418
+ const state2 = refState.current;
2419
+ if (state2) {
2420
+ const { index, ...rest2 } = options;
2421
+ const { startNoBuffer, endNoBuffer } = state2;
2422
+ if (index < startNoBuffer || index > endNoBuffer) {
2423
+ const viewPosition = index < startNoBuffer ? 0 : 1;
2424
+ scrollToIndex(ctx, state2, {
2425
+ ...rest2,
2426
+ index,
2427
+ viewPosition
2428
+ });
2429
+ }
2430
+ }
2431
+ };
2432
+ return {
2433
+ flashScrollIndicators: () => refScroller.current.flashScrollIndicators(),
2434
+ getNativeScrollRef: () => refScroller.current,
2435
+ getScrollableNode: () => refScroller.current.getScrollableNode(),
2436
+ getScrollResponder: () => refScroller.current.getScrollResponder(),
2437
+ getState: () => {
2372
2438
  const state2 = refState.current;
2373
- if (state2) {
2374
- const { index, ...rest2 } = options;
2375
- const { startNoBuffer, endNoBuffer } = state2;
2376
- if (index < startNoBuffer || index > endNoBuffer) {
2377
- const viewPosition = index < startNoBuffer ? 0 : 1;
2378
- scrollToIndex(ctx, state2, {
2379
- ...rest2,
2380
- viewPosition,
2381
- index
2382
- });
2383
- }
2439
+ return state2 ? {
2440
+ contentLength: state2.totalSize,
2441
+ end: state2.endNoBuffer,
2442
+ endBuffered: state2.endBuffered,
2443
+ isAtEnd: state2.isAtEnd,
2444
+ isAtStart: state2.isAtStart,
2445
+ positions: state2.positions,
2446
+ scroll: state2.scroll,
2447
+ scrollLength: state2.scrollLength,
2448
+ sizeAtIndex: (index) => state2.sizesKnown.get(getId(state2, index)),
2449
+ sizes: state2.sizesKnown,
2450
+ start: state2.startNoBuffer,
2451
+ startBuffered: state2.startBuffered
2452
+ } : {};
2453
+ },
2454
+ scrollIndexIntoView,
2455
+ scrollItemIntoView: ({ item, ...props2 }) => {
2456
+ const data = refState.current.props.data;
2457
+ const index = data.indexOf(item);
2458
+ if (index !== -1) {
2459
+ scrollIndexIntoView({ index, ...props2 });
2384
2460
  }
2385
- };
2386
- return {
2387
- flashScrollIndicators: () => refScroller.current.flashScrollIndicators(),
2388
- getNativeScrollRef: () => refScroller.current,
2389
- getScrollableNode: () => refScroller.current.getScrollableNode(),
2390
- getScrollResponder: () => refScroller.current.getScrollResponder(),
2391
- getState: () => {
2392
- const state2 = refState.current;
2393
- return state2 ? {
2394
- contentLength: state2.totalSize,
2395
- end: state2.endNoBuffer,
2396
- endBuffered: state2.endBuffered,
2397
- isAtEnd: state2.isAtEnd,
2398
- isAtStart: state2.isAtStart,
2399
- scroll: state2.scroll,
2400
- scrollLength: state2.scrollLength,
2401
- start: state2.startNoBuffer,
2402
- startBuffered: state2.startBuffered,
2403
- sizes: state2.sizesKnown,
2404
- sizeAtIndex: (index) => state2.sizesKnown.get(getId(state2, index))
2405
- } : {};
2406
- },
2407
- scrollIndexIntoView,
2408
- scrollItemIntoView: ({ item, ...props2 }) => {
2409
- const data = refState.current.props.data;
2410
- const index = data.indexOf(item);
2411
- if (index !== -1) {
2412
- scrollIndexIntoView({ index, ...props2 });
2413
- }
2414
- },
2415
- scrollToIndex: (params) => scrollToIndex(ctx, state, params),
2416
- scrollToItem: ({ item, ...props2 }) => {
2417
- const data = refState.current.props.data;
2418
- const index = data.indexOf(item);
2419
- if (index !== -1) {
2420
- scrollToIndex(ctx, state, { index, ...props2 });
2421
- }
2422
- },
2423
- scrollToOffset: (params) => scrollTo(state, params),
2424
- scrollToEnd: (options) => {
2425
- const data = refState.current.props.data;
2426
- const stylePaddingBottom = refState.current.props.stylePaddingBottom;
2427
- const index = data.length - 1;
2428
- if (index !== -1) {
2429
- const paddingBottom = stylePaddingBottom || 0;
2430
- const footerSize = peek$(ctx, "footerSize") || 0;
2431
- scrollToIndex(ctx, state, {
2432
- index,
2433
- viewPosition: 1,
2434
- viewOffset: -paddingBottom - footerSize,
2435
- ...options
2436
- });
2437
- }
2438
- },
2439
- setVisibleContentAnchorOffset: (value) => {
2440
- const val = typeof value === "function" ? value(peek$(ctx, "scrollAdjustUserOffset") || 0) : value;
2441
- set$(ctx, "scrollAdjustUserOffset", val);
2461
+ },
2462
+ scrollToEnd: (options) => {
2463
+ const data = refState.current.props.data;
2464
+ const stylePaddingBottom = refState.current.props.stylePaddingBottom;
2465
+ const index = data.length - 1;
2466
+ if (index !== -1) {
2467
+ const paddingBottom = stylePaddingBottom || 0;
2468
+ const footerSize = peek$(ctx, "footerSize") || 0;
2469
+ scrollToIndex(ctx, state, {
2470
+ index,
2471
+ viewOffset: -paddingBottom - footerSize,
2472
+ viewPosition: 1,
2473
+ ...options
2474
+ });
2442
2475
  }
2443
- };
2444
- },
2445
- []
2446
- );
2476
+ },
2477
+ scrollToIndex: (params) => scrollToIndex(ctx, state, params),
2478
+ scrollToItem: ({ item, ...props2 }) => {
2479
+ const data = refState.current.props.data;
2480
+ const index = data.indexOf(item);
2481
+ if (index !== -1) {
2482
+ scrollToIndex(ctx, state, { index, ...props2 });
2483
+ }
2484
+ },
2485
+ scrollToOffset: (params) => scrollTo(state, params),
2486
+ setVisibleContentAnchorOffset: (value) => {
2487
+ const val = typeof value === "function" ? value(peek$(ctx, "scrollAdjustUserOffset") || 0) : value;
2488
+ set$(ctx, "scrollAdjustUserOffset", val);
2489
+ }
2490
+ };
2491
+ }, []);
2447
2492
  if (reactNative.Platform.OS === "web") {
2448
2493
  React3.useEffect(() => {
2449
2494
  if (initialContentOffset) {
2450
- scrollTo(state, { offset: initialContentOffset, animated: false });
2495
+ scrollTo(state, { animated: false, offset: initialContentOffset });
2451
2496
  }
2452
2497
  }, []);
2453
2498
  }
2454
2499
  const fns = React3.useMemo(
2455
2500
  () => ({
2456
- updateItemSize: (itemKey, sizeObj) => updateItemSize(ctx, state, itemKey, sizeObj),
2457
2501
  getRenderedItem: (key) => getRenderedItem(ctx, state, key),
2458
- onScroll: (event) => onScroll(ctx, state, event)
2502
+ onScroll: (event) => onScroll(ctx, state, event),
2503
+ updateItemSize: (itemKey, sizeObj) => updateItemSize(ctx, state, itemKey, sizeObj)
2459
2504
  }),
2460
2505
  []
2461
2506
  );
@@ -2463,13 +2508,17 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2463
2508
  ListComponent,
2464
2509
  {
2465
2510
  ...rest,
2511
+ alignItemsAtEnd,
2466
2512
  canRender,
2513
+ contentContainerStyle,
2514
+ getRenderedItem: fns.getRenderedItem,
2467
2515
  horizontal,
2468
- refScrollView: combinedRef,
2469
2516
  initialContentOffset,
2470
- getRenderedItem: fns.getRenderedItem,
2471
- updateItemSize: fns.updateItemSize,
2472
- onScroll: fns.onScroll,
2517
+ ListEmptyComponent: dataProp.length === 0 ? ListEmptyComponent : void 0,
2518
+ ListHeaderComponent,
2519
+ maintainVisibleContentPosition,
2520
+ onLayout,
2521
+ onLayoutHeader,
2473
2522
  onMomentumScrollEnd: (event) => {
2474
2523
  requestAnimationFrame(() => {
2475
2524
  finishScrollTo(refState.current);
@@ -2478,31 +2527,30 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2478
2527
  onMomentumScrollEnd(event);
2479
2528
  }
2480
2529
  },
2481
- onLayout,
2530
+ onScroll: fns.onScroll,
2482
2531
  recycleItems,
2483
- alignItemsAtEnd,
2484
- ListEmptyComponent: dataProp.length === 0 ? ListEmptyComponent : void 0,
2485
- ListHeaderComponent,
2486
- maintainVisibleContentPosition,
2487
- scrollEventThrottle: reactNative.Platform.OS === "web" ? 16 : void 0,
2488
- waitForInitialLayout,
2489
2532
  refreshControl: refreshControl ? stylePaddingTopState > 0 ? React3__namespace.cloneElement(refreshControl, {
2490
2533
  progressViewOffset: (refreshControl.props.progressViewOffset || 0) + stylePaddingTopState
2491
2534
  }) : refreshControl : onRefresh && /* @__PURE__ */ React3__namespace.createElement(
2492
2535
  reactNative.RefreshControl,
2493
2536
  {
2494
- refreshing: !!refreshing,
2495
2537
  onRefresh,
2496
- progressViewOffset: (progressViewOffset || 0) + stylePaddingTopState
2538
+ progressViewOffset: (progressViewOffset || 0) + stylePaddingTopState,
2539
+ refreshing: !!refreshing
2497
2540
  }
2498
2541
  ),
2499
- style,
2500
- contentContainerStyle,
2542
+ refScrollView: combinedRef,
2501
2543
  scrollAdjustHandler: (_a = refState.current) == null ? void 0 : _a.scrollAdjustHandler,
2502
- onLayoutHeader
2544
+ scrollEventThrottle: reactNative.Platform.OS === "web" ? 16 : void 0,
2545
+ snapToIndices,
2546
+ style,
2547
+ updateItemSize: fns.updateItemSize,
2548
+ waitForInitialLayout
2503
2549
  }
2504
2550
  ), __DEV__ && ENABLE_DEBUG_VIEW && /* @__PURE__ */ React3__namespace.createElement(DebugView, { state: refState.current }));
2505
2551
  });
2552
+
2553
+ // src/components/LazyLegendList.tsx
2506
2554
  var typedForwardRef2 = React3.forwardRef;
2507
2555
  var renderItem = ({ item }) => item;
2508
2556
  var LazyLegendList = typedForwardRef2(function LazyLegendList2(props, forwardedRef) {
@@ -2511,7 +2559,7 @@ var LazyLegendList = typedForwardRef2(function LazyLegendList2(props, forwardedR
2511
2559
  const data = (isArray(children) ? children : React3__namespace.Children.toArray(children)).flat(1);
2512
2560
  return (
2513
2561
  // @ts-expect-error TODO: Fix this type
2514
- /* @__PURE__ */ React3__namespace.createElement(LegendListComponent, { ...rest, data, renderItem, ref: forwardedRef })
2562
+ /* @__PURE__ */ React3__namespace.createElement(LegendListComponent, { ...rest, data, ref: forwardedRef, renderItem })
2515
2563
  );
2516
2564
  });
2517
2565