@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
@@ -1,558 +0,0 @@
1
- import * as React from "react";
2
- import {
3
- type ForwardedRef,
4
- useCallback,
5
- useEffect,
6
- useImperativeHandle,
7
- useLayoutEffect,
8
- useMemo,
9
- useRef,
10
- useState,
11
- } from "react";
12
- import {
13
- Dimensions,
14
- type LayoutChangeEvent,
15
- type LayoutRectangle,
16
- type NativeScrollEvent,
17
- Platform,
18
- RefreshControl,
19
- type ScrollView,
20
- StyleSheet,
21
- type View,
22
- } from "react-native";
23
- import { DebugView } from "./DebugView";
24
- import { ListComponent } from "./ListComponent";
25
- import { ScrollAdjustHandler } from "./ScrollAdjustHandler";
26
- import { calculateItemsInView } from "./calculateItemsInView";
27
- import { calculateOffsetForIndex } from "./calculateOffsetForIndex";
28
- import { checkAtBottom } from "./checkAtBottom";
29
- import { checkAtTop } from "./checkAtTop";
30
- import { ENABLE_DEBUG_VIEW, IsNewArchitecture } from "./constants";
31
- import { createColumnWrapperStyle } from "./createColumnWrapperStyle";
32
- import { doInitialAllocateContainers } from "./doInitialAllocateContainers";
33
- import { doMaintainScrollAtEnd } from "./doMaintainScrollAtEnd";
34
- import { finishScrollTo } from "./finishScrollTo";
35
- import { getId } from "./getId";
36
- import { getRenderedItem } from "./getRenderedItem";
37
- import { handleLayout } from "./handleLayout";
38
- import { extractPadding, warnDevOnce } from "./helpers";
39
- import { onScroll } from "./onScroll";
40
- import { requestAdjust } from "./requestAdjust";
41
- import { scrollTo } from "./scrollTo";
42
- import { scrollToIndex } from "./scrollToIndex";
43
- import { setPaddingTop } from "./setPaddingTop";
44
- import { StateProvider, peek$, set$, useStateContext } from "./state";
45
- import type {
46
- InternalState,
47
- LegendListProps,
48
- LegendListRef,
49
- MaintainScrollAtEndOptions,
50
- ScrollIndexWithOffsetPosition,
51
- ScrollState,
52
- } from "./types";
53
- import { typedForwardRef } from "./types";
54
- import { updateAllPositions } from "./updateAllPositions";
55
- import { updateItemSize } from "./updateItemSize";
56
- import { useCombinedRef } from "./useCombinedRef";
57
- import { useInit } from "./useInit";
58
- import { setupViewability } from "./viewability";
59
-
60
- const DEFAULT_DRAW_DISTANCE = 250;
61
- const DEFAULT_ITEM_SIZE = 100;
62
-
63
- export const LegendList = typedForwardRef(function LegendList<T>(
64
- props: LegendListProps<T>,
65
- forwardedRef: ForwardedRef<LegendListRef>,
66
- ) {
67
- return (
68
- <StateProvider>
69
- <LegendListInner {...props} ref={forwardedRef} />
70
- </StateProvider>
71
- );
72
- });
73
-
74
- const LegendListInner = typedForwardRef(function LegendListInner<T>(
75
- props: LegendListProps<T>,
76
- forwardedRef: ForwardedRef<LegendListRef>,
77
- ) {
78
- const {
79
- data: dataProp = [],
80
- initialScrollIndex: initialScrollIndexProp,
81
- initialScrollOffset,
82
- horizontal,
83
- drawDistance = 250,
84
- recycleItems = false,
85
- onEndReachedThreshold = 0.5,
86
- onStartReachedThreshold = 0.5,
87
- maintainScrollAtEnd = false,
88
- maintainScrollAtEndThreshold = 0.1,
89
- alignItemsAtEnd = false,
90
- maintainVisibleContentPosition = false,
91
- onScroll: onScrollProp,
92
- onMomentumScrollEnd,
93
- numColumns: numColumnsProp = 1,
94
- columnWrapperStyle,
95
- keyExtractor: keyExtractorProp,
96
- renderItem,
97
- estimatedListSize,
98
- estimatedItemSize: estimatedItemSizeProp,
99
- getEstimatedItemSize,
100
- suggestEstimatedItemSize,
101
- ListHeaderComponent,
102
- ListEmptyComponent,
103
- onItemSizeChanged,
104
- refScrollView,
105
- waitForInitialLayout = true,
106
- extraData,
107
- contentContainerStyle: contentContainerStyleProp,
108
- style: styleProp,
109
- onLayout: onLayoutProp,
110
- onRefresh,
111
- refreshing,
112
- progressViewOffset,
113
- refreshControl,
114
- initialContainerPoolRatio = 2,
115
- viewabilityConfig,
116
- viewabilityConfigCallbackPairs,
117
- onViewableItemsChanged,
118
- onStartReached,
119
- onEndReached,
120
- onLoad,
121
- ...rest
122
- } = props;
123
-
124
- const [renderNum, setRenderNum] = useState(0);
125
- const initialScroll: ScrollIndexWithOffsetPosition | undefined =
126
- typeof initialScrollIndexProp === "number" ? { index: initialScrollIndexProp } : initialScrollIndexProp;
127
- const initialScrollIndex = initialScroll?.index;
128
-
129
- const [canRender, setCanRender] = React.useState(!IsNewArchitecture);
130
-
131
- const contentContainerStyle = { ...StyleSheet.flatten(contentContainerStyleProp) };
132
- const style = { ...StyleSheet.flatten(styleProp) };
133
- const stylePaddingTopState = extractPadding(style, contentContainerStyle, "Top");
134
- const stylePaddingBottomState = extractPadding(style, contentContainerStyle, "Bottom");
135
-
136
- const ctx = useStateContext();
137
- ctx.columnWrapperStyle =
138
- columnWrapperStyle || (contentContainerStyle ? createColumnWrapperStyle(contentContainerStyle) : undefined);
139
-
140
- const refScroller = useRef<ScrollView>(null) as React.MutableRefObject<ScrollView>;
141
- const combinedRef = useCombinedRef(refScroller, refScrollView);
142
- const estimatedItemSize = estimatedItemSizeProp ?? DEFAULT_ITEM_SIZE;
143
- const scrollBuffer = (drawDistance ?? DEFAULT_DRAW_DISTANCE) || 1;
144
- const keyExtractor = keyExtractorProp ?? ((item, index) => index.toString());
145
-
146
- const refState = useRef<InternalState>();
147
-
148
- if (!refState.current) {
149
- const initialScrollLength = (estimatedListSize ??
150
- (IsNewArchitecture ? { width: 0, height: 0 } : Dimensions.get("window")))[horizontal ? "width" : "height"];
151
-
152
- refState.current = {
153
- sizes: new Map(),
154
- positions: new Map(),
155
- columns: new Map(),
156
- pendingAdjust: 0,
157
- isStartReached: false,
158
- isEndReached: false,
159
- isAtEnd: false,
160
- isAtStart: false,
161
- scrollLength: initialScrollLength,
162
- startBuffered: -1,
163
- startNoBuffer: -1,
164
- endBuffered: -1,
165
- endNoBuffer: -1,
166
- firstFullyOnScreenIndex: -1,
167
- scroll: 0,
168
- totalSize: 0,
169
- timeouts: new Set(),
170
- viewabilityConfigCallbackPairs: undefined as never,
171
- scrollAdjustHandler: new ScrollAdjustHandler(ctx),
172
- nativeMarginTop: 0,
173
- scrollPrev: 0,
174
- scrollPrevTime: 0,
175
- scrollTime: 0,
176
- scrollPending: 0,
177
- indexByKey: new Map(),
178
- scrollHistory: [],
179
- sizesKnown: new Map(),
180
- timeoutSizeMessage: 0,
181
- startReachedBlockedByTimer: false,
182
- endReachedBlockedByTimer: false,
183
- scrollForNextCalculateItemsInView: undefined,
184
- enableScrollForNextCalculateItemsInView: true,
185
- minIndexSizeChanged: 0,
186
- queuedCalculateItemsInView: 0,
187
- lastBatchingAction: Date.now(),
188
- averageSizes: {},
189
- idsInView: [],
190
- containerItemKeys: new Set(),
191
- idCache: new Map(),
192
- props: {} as any,
193
- refScroller: undefined as any,
194
- loadStartTime: Date.now(),
195
- initialScroll,
196
- lastLayout: undefined,
197
- };
198
-
199
- set$(ctx, "maintainVisibleContentPosition", maintainVisibleContentPosition);
200
- set$(ctx, "extraData", extraData);
201
- }
202
-
203
- const state = refState.current!;
204
-
205
- const isFirst = !state.props.renderItem;
206
-
207
- const didDataChange = state.props.data !== dataProp;
208
- state.props = {
209
- alignItemsAtEnd,
210
- data: dataProp,
211
- estimatedItemSize,
212
- maintainScrollAtEnd,
213
- maintainScrollAtEndThreshold,
214
- onEndReachedThreshold,
215
- onStartReachedThreshold,
216
- stylePaddingBottom: stylePaddingBottomState,
217
- horizontal: !!horizontal,
218
- maintainVisibleContentPosition,
219
- onItemSizeChanged,
220
- suggestEstimatedItemSize: !!suggestEstimatedItemSize,
221
- keyExtractor,
222
- onScroll: onScrollProp,
223
- getEstimatedItemSize,
224
- onStartReached,
225
- onEndReached,
226
- onLoad,
227
- renderItem: renderItem!,
228
- initialScroll,
229
- scrollBuffer,
230
- viewabilityConfigCallbackPairs: undefined,
231
- numColumns: numColumnsProp,
232
- initialContainerPoolRatio,
233
- stylePaddingTop: stylePaddingTopState,
234
- };
235
-
236
- state.refScroller = refScroller;
237
-
238
- const checkResetContainers = (isFirst: boolean) => {
239
- const state = refState.current;
240
- if (state) {
241
- state.props.data = dataProp;
242
-
243
- if (!isFirst) {
244
- calculateItemsInView(ctx, state, { dataChanged: true, doMVCP: true });
245
-
246
- const shouldMaintainScrollAtEnd =
247
- maintainScrollAtEnd === true || (maintainScrollAtEnd as MaintainScrollAtEndOptions).onDataChange;
248
-
249
- const didMaintainScrollAtEnd = shouldMaintainScrollAtEnd && doMaintainScrollAtEnd(ctx, state, false);
250
-
251
- // Reset the endReached flag if new data has been added and we didn't
252
- // just maintain the scroll at end
253
- if (!didMaintainScrollAtEnd && dataProp.length > state.props.data.length) {
254
- state.isEndReached = false;
255
- }
256
-
257
- if (!didMaintainScrollAtEnd) {
258
- checkAtTop(state);
259
- checkAtBottom(ctx, state);
260
- }
261
- }
262
- }
263
- };
264
-
265
- const memoizedLastItemKeys = useMemo(() => {
266
- if (!dataProp.length) return [];
267
- return Array.from({ length: Math.min(numColumnsProp, dataProp.length) }, (_, i) =>
268
- getId(state, dataProp.length - 1 - i),
269
- );
270
- }, [dataProp, numColumnsProp]);
271
-
272
- // Run first time and whenever data changes
273
- const initalizeStateVars = () => {
274
- set$(ctx, "lastItemKeys", memoizedLastItemKeys);
275
- set$(ctx, "numColumns", numColumnsProp);
276
-
277
- // If the stylePaddingTop has changed, scroll to an adjusted offset to
278
- // keep the same content in view
279
- const prevPaddingTop = peek$(ctx, "stylePaddingTop");
280
- setPaddingTop(ctx, { stylePaddingTop: stylePaddingTopState });
281
- refState.current!.props.stylePaddingBottom = stylePaddingBottomState;
282
-
283
- const paddingDiff = stylePaddingTopState - prevPaddingTop;
284
- // If the style padding has changed then adjust the paddingTop and update scroll to compensate
285
- // Only iOS seems to need the scroll compensation
286
- if (paddingDiff && prevPaddingTop !== undefined && Platform.OS === "ios") {
287
- calculateItemsInView(ctx, state, { doMVCP: true });
288
- requestAdjust(ctx, state, paddingDiff);
289
- }
290
- };
291
- if (isFirst) {
292
- initalizeStateVars();
293
- updateAllPositions(ctx, state);
294
- }
295
- const initialContentOffset = useMemo(() => {
296
- const initialContentOffset = initialScrollOffset || calculateOffsetForIndex(ctx, state, initialScrollIndex);
297
- refState.current!.isStartReached =
298
- initialContentOffset < refState.current!.scrollLength * onStartReachedThreshold!;
299
-
300
- if (initialContentOffset > 0) {
301
- scrollTo(state, { offset: initialContentOffset, animated: false, index: initialScrollIndex });
302
- }
303
-
304
- return initialContentOffset;
305
- }, [renderNum]);
306
-
307
- if (isFirst || didDataChange || numColumnsProp !== peek$(ctx, "numColumns")) {
308
- refState.current.lastBatchingAction = Date.now();
309
- if (!keyExtractorProp && !isFirst && didDataChange) {
310
- __DEV__ &&
311
- warnDevOnce(
312
- "keyExtractor",
313
- "Changing data without a keyExtractor can cause slow performance and resetting scroll. If your list data can change you should use a keyExtractor with a unique id for best performance and behavior.",
314
- );
315
- // If we have no keyExtractor then we have no guarantees about previous item sizes so we have to reset
316
- refState.current.sizes.clear();
317
- refState.current.positions.clear();
318
- }
319
- }
320
-
321
- useLayoutEffect(() => {
322
- if (IsNewArchitecture) {
323
- let measured: LayoutRectangle;
324
- (refScroller.current as unknown as View).measure((x, y, width, height) => {
325
- measured = { x, y, width, height };
326
- });
327
- if (measured!) {
328
- const size = Math.floor(measured[horizontal ? "width" : "height"] * 8) / 8;
329
-
330
- if (size) {
331
- handleLayout(ctx, state, measured, setCanRender);
332
- }
333
- }
334
- }
335
- if (!isFirst) {
336
- calculateItemsInView(ctx, state, { doMVCP: true });
337
- }
338
- }, [dataProp]);
339
-
340
- const onLayoutHeader = useCallback((rect: LayoutRectangle, fromLayoutEffect: boolean) => {
341
- const size = rect[horizontal ? "width" : "height"];
342
- set$(ctx, "headerSize", size);
343
-
344
- if (initialScroll) {
345
- if (IsNewArchitecture && Platform.OS !== "android") {
346
- if (fromLayoutEffect) {
347
- setRenderNum((v) => v + 1);
348
- }
349
- } else {
350
- setTimeout(() => {
351
- scrollToIndex(ctx, state, { ...initialScroll, animated: false });
352
- }, 17);
353
- }
354
- }
355
- }, []);
356
-
357
- useLayoutEffect(() => {
358
- const didAllocateContainers = doInitialAllocateContainersCallback();
359
- if (!didAllocateContainers) {
360
- checkResetContainers(/*isFirst*/ isFirst);
361
- }
362
- }, [dataProp, numColumnsProp]);
363
-
364
- useLayoutEffect(() => {
365
- set$(ctx, "extraData", extraData);
366
- }, [extraData]);
367
-
368
- useLayoutEffect(initalizeStateVars, [
369
- memoizedLastItemKeys.join(","),
370
- numColumnsProp,
371
- stylePaddingTopState,
372
- stylePaddingBottomState,
373
- ]);
374
-
375
- const doInitialAllocateContainersCallback = () => {
376
- return doInitialAllocateContainers(ctx, state);
377
- };
378
-
379
- useEffect(() => {
380
- const viewability = setupViewability({
381
- viewabilityConfig,
382
- viewabilityConfigCallbackPairs,
383
- onViewableItemsChanged,
384
- });
385
- state.viewabilityConfigCallbackPairs = viewability;
386
- state.props.viewabilityConfigCallbackPairs = viewability;
387
- state.enableScrollForNextCalculateItemsInView = !viewability;
388
- }, [viewabilityConfig, viewabilityConfigCallbackPairs, onViewableItemsChanged]);
389
-
390
- if (!IsNewArchitecture) {
391
- // Needs to use the initial estimated size on old arch, new arch will come within the useLayoutEffect
392
- useInit(() => {
393
- doInitialAllocateContainersCallback();
394
- });
395
- }
396
-
397
- const onLayout = useCallback((event: LayoutChangeEvent) => {
398
- const layout = event.nativeEvent.layout;
399
- handleLayout(ctx, state, layout, setCanRender);
400
-
401
- if (onLayoutProp) {
402
- onLayoutProp(event);
403
- }
404
- }, []);
405
-
406
- useImperativeHandle(
407
- forwardedRef,
408
- () => {
409
- const scrollIndexIntoView = (options: Parameters<LegendListRef["scrollIndexIntoView"]>[0]) => {
410
- const state = refState.current;
411
- if (state) {
412
- const { index, ...rest } = options;
413
- const { startNoBuffer, endNoBuffer } = state;
414
- if (index < startNoBuffer || index > endNoBuffer) {
415
- const viewPosition = index < startNoBuffer ? 0 : 1;
416
- scrollToIndex(ctx, state, {
417
- ...rest,
418
- viewPosition,
419
- index,
420
- });
421
- }
422
- }
423
- };
424
- return {
425
- flashScrollIndicators: () => refScroller.current!.flashScrollIndicators(),
426
- getNativeScrollRef: () => refScroller.current!,
427
- getScrollableNode: () => refScroller.current!.getScrollableNode(),
428
- getScrollResponder: () => refScroller.current!.getScrollResponder(),
429
- getState: () => {
430
- const state = refState.current;
431
- return state
432
- ? {
433
- contentLength: state.totalSize,
434
- end: state.endNoBuffer,
435
- endBuffered: state.endBuffered,
436
- isAtEnd: state.isAtEnd,
437
- isAtStart: state.isAtStart,
438
- scroll: state.scroll,
439
- scrollLength: state.scrollLength,
440
- start: state.startNoBuffer,
441
- startBuffered: state.startBuffered,
442
- sizes: state.sizesKnown,
443
- sizeAtIndex: (index: number) => state.sizesKnown.get(getId(state, index))!,
444
- }
445
- : ({} as ScrollState);
446
- },
447
- scrollIndexIntoView,
448
- scrollItemIntoView: ({ item, ...props }) => {
449
- const data = refState.current!.props.data;
450
- const index = data.indexOf(item);
451
- if (index !== -1) {
452
- scrollIndexIntoView({ index, ...props });
453
- }
454
- },
455
- scrollToIndex: (params) => scrollToIndex(ctx, state, params),
456
- scrollToItem: ({ item, ...props }) => {
457
- const data = refState.current!.props.data;
458
- const index = data.indexOf(item);
459
- if (index !== -1) {
460
- scrollToIndex(ctx, state, { index, ...props });
461
- }
462
- },
463
- scrollToOffset: (params) => scrollTo(state, params),
464
- scrollToEnd: (options) => {
465
- const data = refState.current!.props.data;
466
- const stylePaddingBottom = refState.current!.props.stylePaddingBottom;
467
- const index = data.length - 1;
468
- if (index !== -1) {
469
- const paddingBottom = stylePaddingBottom || 0;
470
- const footerSize = peek$(ctx, "footerSize") || 0;
471
- scrollToIndex(ctx, state, {
472
- index,
473
- viewPosition: 1,
474
- viewOffset: -paddingBottom - footerSize,
475
- ...options,
476
- });
477
- }
478
- },
479
- setVisibleContentAnchorOffset: (value: number | ((value: number) => number)) => {
480
- const val = typeof value === "function" ? value(peek$(ctx, "scrollAdjustUserOffset") || 0) : value;
481
- set$(ctx, "scrollAdjustUserOffset", val);
482
- },
483
- };
484
- },
485
- [],
486
- );
487
-
488
- if (Platform.OS === "web") {
489
- useEffect(() => {
490
- if (initialContentOffset) {
491
- scrollTo(state, { offset: initialContentOffset, animated: false });
492
- }
493
- }, []);
494
- }
495
-
496
- const fns = useMemo(
497
- () => ({
498
- updateItemSize: (itemKey: string, sizeObj: { width: number; height: number }) =>
499
- updateItemSize(ctx, state, itemKey, sizeObj),
500
- getRenderedItem: (key: string) => getRenderedItem(ctx, state, key),
501
- onScroll: (event: { nativeEvent: NativeScrollEvent }) => onScroll(ctx, state, event),
502
- }),
503
- [],
504
- );
505
-
506
- return (
507
- <>
508
- <ListComponent
509
- {...rest}
510
- canRender={canRender}
511
- horizontal={horizontal!}
512
- refScrollView={combinedRef}
513
- initialContentOffset={initialContentOffset}
514
- getRenderedItem={fns.getRenderedItem}
515
- updateItemSize={fns.updateItemSize}
516
- onScroll={fns.onScroll}
517
- onMomentumScrollEnd={(event) => {
518
- requestAnimationFrame(() => {
519
- finishScrollTo(refState.current);
520
- });
521
-
522
- if (onMomentumScrollEnd) {
523
- onMomentumScrollEnd(event);
524
- }
525
- }}
526
- onLayout={onLayout}
527
- recycleItems={recycleItems}
528
- alignItemsAtEnd={alignItemsAtEnd}
529
- ListEmptyComponent={dataProp.length === 0 ? ListEmptyComponent : undefined}
530
- ListHeaderComponent={ListHeaderComponent}
531
- maintainVisibleContentPosition={maintainVisibleContentPosition}
532
- scrollEventThrottle={Platform.OS === "web" ? 16 : undefined}
533
- waitForInitialLayout={waitForInitialLayout}
534
- refreshControl={
535
- refreshControl
536
- ? stylePaddingTopState > 0
537
- ? React.cloneElement(refreshControl, {
538
- progressViewOffset:
539
- (refreshControl.props.progressViewOffset || 0) + stylePaddingTopState,
540
- })
541
- : refreshControl
542
- : onRefresh && (
543
- <RefreshControl
544
- refreshing={!!refreshing}
545
- onRefresh={onRefresh}
546
- progressViewOffset={(progressViewOffset || 0) + stylePaddingTopState}
547
- />
548
- )
549
- }
550
- style={style}
551
- contentContainerStyle={contentContainerStyle}
552
- scrollAdjustHandler={refState.current?.scrollAdjustHandler}
553
- onLayoutHeader={onLayoutHeader}
554
- />
555
- {__DEV__ && ENABLE_DEBUG_VIEW && <DebugView state={refState.current!} />}
556
- </>
557
- );
558
- });