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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (260) hide show
  1. package/{dist/animated.d.mts → animated.d.mts} +1 -0
  2. package/{dist/animated.d.ts → animated.d.ts} +1 -0
  3. package/{dist/index.d.mts → index.d.mts} +8 -1
  4. package/{dist/index.d.ts → index.d.ts} +8 -1
  5. package/{dist/index.js → index.js} +50 -4
  6. package/{dist/index.mjs → index.mjs} +50 -4
  7. package/{dist/keyboard-controller.d.mts → keyboard-controller.d.mts} +4 -0
  8. package/{dist/keyboard-controller.d.ts → keyboard-controller.d.ts} +4 -0
  9. package/package.json +34 -88
  10. package/.claude/settings.local.json +0 -8
  11. package/.cursor/rules/changelog.mdc +0 -60
  12. package/.github/FUNDING.yml +0 -15
  13. package/.gitignore +0 -5
  14. package/.prettierrc.json +0 -5
  15. package/.vscode/settings.json +0 -14
  16. package/CLAUDE.md +0 -126
  17. package/biome.json +0 -46
  18. package/bun.lock +0 -1289
  19. package/bunfig.toml +0 -2
  20. package/dist/CHANGELOG.md +0 -119
  21. package/dist/LICENSE +0 -21
  22. package/dist/README.md +0 -139
  23. package/dist/package.json +0 -35
  24. package/example/README.md +0 -40
  25. package/example/api/data/genres.json +0 -23
  26. package/example/api/data/playlist/10402-10749.json +0 -1
  27. package/example/api/data/playlist/10402-10770.json +0 -1
  28. package/example/api/data/playlist/10402-37.json +0 -1
  29. package/example/api/data/playlist/10749-10752.json +0 -1
  30. package/example/api/data/playlist/10749-10770.json +0 -1
  31. package/example/api/data/playlist/10749-37.json +0 -1
  32. package/example/api/data/playlist/10749-878.json +0 -1
  33. package/example/api/data/playlist/10751-10402.json +0 -1
  34. package/example/api/data/playlist/10751-10752.json +0 -1
  35. package/example/api/data/playlist/10751-37.json +0 -1
  36. package/example/api/data/playlist/10751-53.json +0 -1
  37. package/example/api/data/playlist/10751-878.json +0 -1
  38. package/example/api/data/playlist/10751-9648.json +0 -1
  39. package/example/api/data/playlist/10752-37.json +0 -1
  40. package/example/api/data/playlist/12-10402.json +0 -1
  41. package/example/api/data/playlist/12-10749.json +0 -1
  42. package/example/api/data/playlist/12-18.json +0 -1
  43. package/example/api/data/playlist/12-27.json +0 -1
  44. package/example/api/data/playlist/12-35.json +0 -1
  45. package/example/api/data/playlist/14-36.json +0 -1
  46. package/example/api/data/playlist/14-878.json +0 -1
  47. package/example/api/data/playlist/16-10751.json +0 -1
  48. package/example/api/data/playlist/16-10770.json +0 -1
  49. package/example/api/data/playlist/16-35.json +0 -1
  50. package/example/api/data/playlist/16-36.json +0 -1
  51. package/example/api/data/playlist/16-53.json +0 -1
  52. package/example/api/data/playlist/18-10751.json +0 -1
  53. package/example/api/data/playlist/18-10752.json +0 -1
  54. package/example/api/data/playlist/18-37.json +0 -1
  55. package/example/api/data/playlist/18-53.json +0 -1
  56. package/example/api/data/playlist/18-878.json +0 -1
  57. package/example/api/data/playlist/27-10749.json +0 -1
  58. package/example/api/data/playlist/27-10770.json +0 -1
  59. package/example/api/data/playlist/28-10749.json +0 -1
  60. package/example/api/data/playlist/28-10751.json +0 -1
  61. package/example/api/data/playlist/28-10770.json +0 -1
  62. package/example/api/data/playlist/28-16.json +0 -1
  63. package/example/api/data/playlist/28-18.json +0 -1
  64. package/example/api/data/playlist/28-36.json +0 -1
  65. package/example/api/data/playlist/28-37.json +0 -1
  66. package/example/api/data/playlist/28-53.json +0 -1
  67. package/example/api/data/playlist/28-80.json +0 -1
  68. package/example/api/data/playlist/28-99.json +0 -1
  69. package/example/api/data/playlist/35-10749.json +0 -1
  70. package/example/api/data/playlist/35-10751.json +0 -1
  71. package/example/api/data/playlist/35-10752.json +0 -1
  72. package/example/api/data/playlist/35-27.json +0 -1
  73. package/example/api/data/playlist/35-36.json +0 -1
  74. package/example/api/data/playlist/35-53.json +0 -1
  75. package/example/api/data/playlist/35-80.json +0 -1
  76. package/example/api/data/playlist/36-37.json +0 -1
  77. package/example/api/data/playlist/36-878.json +0 -1
  78. package/example/api/data/playlist/36-9648.json +0 -1
  79. package/example/api/data/playlist/53-10752.json +0 -1
  80. package/example/api/data/playlist/80-10770.json +0 -1
  81. package/example/api/data/playlist/80-14.json +0 -1
  82. package/example/api/data/playlist/80-18.json +0 -1
  83. package/example/api/data/playlist/80-37.json +0 -1
  84. package/example/api/data/playlist/878-37.json +0 -1
  85. package/example/api/data/playlist/9648-10770.json +0 -1
  86. package/example/api/data/playlist/9648-37.json +0 -1
  87. package/example/api/data/playlist/9648-53.json +0 -1
  88. package/example/api/data/playlist/9648-878.json +0 -1
  89. package/example/api/data/playlist/99-10749.json +0 -1
  90. package/example/api/data/playlist/99-14.json +0 -1
  91. package/example/api/data/playlist/99-18.json +0 -1
  92. package/example/api/data/playlist/99-27.json +0 -1
  93. package/example/api/data/playlist/99-53.json +0 -1
  94. package/example/api/data/playlist/99-9648.json +0 -1
  95. package/example/api/data/playlist/index.ts +0 -73
  96. package/example/api/data/rows.json +0 -1
  97. package/example/api/index.ts +0 -36
  98. package/example/app/(tabs)/_layout.tsx +0 -60
  99. package/example/app/(tabs)/cards.tsx +0 -81
  100. package/example/app/(tabs)/index.tsx +0 -205
  101. package/example/app/(tabs)/moviesL.tsx +0 -7
  102. package/example/app/(tabs)/moviesLR.tsx +0 -7
  103. package/example/app/+not-found.tsx +0 -32
  104. package/example/app/_layout.tsx +0 -34
  105. package/example/app/accurate-scrollto/index.tsx +0 -125
  106. package/example/app/accurate-scrollto-2/index.tsx +0 -52
  107. package/example/app/accurate-scrollto-huge/index.tsx +0 -128
  108. package/example/app/add-to-end/index.tsx +0 -82
  109. package/example/app/ai-chat/index.tsx +0 -236
  110. package/example/app/bidirectional-infinite-list/index.tsx +0 -133
  111. package/example/app/cards-columns/index.tsx +0 -37
  112. package/example/app/cards-flashlist/index.tsx +0 -122
  113. package/example/app/cards-flatlist/index.tsx +0 -94
  114. package/example/app/cards-no-recycle/index.tsx +0 -110
  115. package/example/app/cards-renderItem.tsx +0 -354
  116. package/example/app/chat-example/index.tsx +0 -167
  117. package/example/app/chat-infinite/index.tsx +0 -239
  118. package/example/app/chat-keyboard/index.tsx +0 -248
  119. package/example/app/chat-resize-outer/index.tsx +0 -247
  120. package/example/app/columns/index.tsx +0 -78
  121. package/example/app/countries/index.tsx +0 -182
  122. package/example/app/countries-flashlist/index.tsx +0 -163
  123. package/example/app/countries-reorder/index.tsx +0 -187
  124. package/example/app/extra-data/index.tsx +0 -86
  125. package/example/app/filter-elements/filter-data-provider.tsx +0 -55
  126. package/example/app/filter-elements/index.tsx +0 -118
  127. package/example/app/initial-scroll-index/index.tsx +0 -106
  128. package/example/app/initial-scroll-index/renderFixedItem.tsx +0 -215
  129. package/example/app/initial-scroll-index-free-height/index.tsx +0 -70
  130. package/example/app/initial-scroll-index-keyed/index.tsx +0 -62
  131. package/example/app/lazy-list/index.tsx +0 -123
  132. package/example/app/movies-flashlist/index.tsx +0 -7
  133. package/example/app/mutable-cells/index.tsx +0 -104
  134. package/example/app/video-feed/index.tsx +0 -119
  135. package/example/app.config.js +0 -22
  136. package/example/app.json +0 -45
  137. package/example/assets/fonts/SpaceMono-Regular.ttf +0 -0
  138. package/example/assets/images/adaptive-icon.png +0 -0
  139. package/example/assets/images/favicon.png +0 -0
  140. package/example/assets/images/icon.png +0 -0
  141. package/example/assets/images/partial-react-logo.png +0 -0
  142. package/example/assets/images/react-logo.png +0 -0
  143. package/example/assets/images/react-logo@2x.png +0 -0
  144. package/example/assets/images/react-logo@3x.png +0 -0
  145. package/example/assets/images/splash-icon.png +0 -0
  146. package/example/autoscroll.sh +0 -101
  147. package/example/bun.lock +0 -2266
  148. package/example/bunfig.toml +0 -2
  149. package/example/components/Breathe.tsx +0 -54
  150. package/example/components/Circle.tsx +0 -69
  151. package/example/components/Collapsible.tsx +0 -44
  152. package/example/components/ExternalLink.tsx +0 -24
  153. package/example/components/HapticTab.tsx +0 -18
  154. package/example/components/HelloWave.tsx +0 -37
  155. package/example/components/Movies.tsx +0 -179
  156. package/example/components/ParallaxScrollView.tsx +0 -81
  157. package/example/components/ThemedText.tsx +0 -60
  158. package/example/components/ThemedView.tsx +0 -14
  159. package/example/components/__tests__/ThemedText-test.tsx +0 -10
  160. package/example/components/__tests__/__snapshots__/ThemedText-test.tsx.snap +0 -24
  161. package/example/components/ui/IconSymbol.ios.tsx +0 -32
  162. package/example/components/ui/IconSymbol.tsx +0 -43
  163. package/example/components/ui/TabBarBackground.ios.tsx +0 -22
  164. package/example/components/ui/TabBarBackground.tsx +0 -6
  165. package/example/constants/Colors.ts +0 -26
  166. package/example/constants/constants.ts +0 -5
  167. package/example/constants/useScrollTest.ts +0 -19
  168. package/example/hooks/useColorScheme.ts +0 -1
  169. package/example/hooks/useColorScheme.web.ts +0 -8
  170. package/example/hooks/useThemeColor.ts +0 -22
  171. package/example/ios/.xcode.env +0 -11
  172. package/example/ios/Podfile +0 -64
  173. package/example/ios/Podfile.lock +0 -2767
  174. package/example/ios/Podfile.properties.json +0 -5
  175. package/example/ios/listtest/AppDelegate.swift +0 -70
  176. package/example/ios/listtest/Images.xcassets/AppIcon.appiconset/App-Icon-1024x1024@1x.png +0 -0
  177. package/example/ios/listtest/Images.xcassets/AppIcon.appiconset/Contents.json +0 -14
  178. package/example/ios/listtest/Images.xcassets/Contents.json +0 -6
  179. package/example/ios/listtest/Images.xcassets/SplashScreenBackground.colorset/Contents.json +0 -20
  180. package/example/ios/listtest/Images.xcassets/SplashScreenLogo.imageset/Contents.json +0 -23
  181. package/example/ios/listtest/Images.xcassets/SplashScreenLogo.imageset/image.png +0 -0
  182. package/example/ios/listtest/Images.xcassets/SplashScreenLogo.imageset/image@2x.png +0 -0
  183. package/example/ios/listtest/Images.xcassets/SplashScreenLogo.imageset/image@3x.png +0 -0
  184. package/example/ios/listtest/Info.plist +0 -85
  185. package/example/ios/listtest/PrivacyInfo.xcprivacy +0 -48
  186. package/example/ios/listtest/SplashScreen.storyboard +0 -42
  187. package/example/ios/listtest/Supporting/Expo.plist +0 -12
  188. package/example/ios/listtest/listtest-Bridging-Header.h +0 -3
  189. package/example/ios/listtest/listtest.entitlements +0 -5
  190. package/example/ios/listtest.xcodeproj/project.pbxproj +0 -547
  191. package/example/ios/listtest.xcodeproj/xcshareddata/xcschemes/listtest.xcscheme +0 -88
  192. package/example/ios/listtest.xcworkspace/contents.xcworkspacedata +0 -10
  193. package/example/metro.config.js +0 -16
  194. package/example/package.json +0 -73
  195. package/example/scripts/reset-project.js +0 -84
  196. package/example/tsconfig.json +0 -26
  197. package/posttsup.ts +0 -24
  198. package/src/Container.tsx +0 -176
  199. package/src/Containers.tsx +0 -85
  200. package/src/ContextContainer.ts +0 -145
  201. package/src/DebugView.tsx +0 -83
  202. package/src/LazyLegendList.tsx +0 -41
  203. package/src/LeanView.tsx +0 -18
  204. package/src/LegendList.tsx +0 -558
  205. package/src/ListComponent.tsx +0 -191
  206. package/src/ScrollAdjust.tsx +0 -24
  207. package/src/ScrollAdjustHandler.ts +0 -26
  208. package/src/Separator.tsx +0 -14
  209. package/src/animated.tsx +0 -6
  210. package/src/calculateItemsInView.ts +0 -363
  211. package/src/calculateOffsetForIndex.ts +0 -23
  212. package/src/calculateOffsetWithOffsetPosition.ts +0 -26
  213. package/src/checkAllSizesKnown.ts +0 -17
  214. package/src/checkAtBottom.ts +0 -36
  215. package/src/checkAtTop.ts +0 -27
  216. package/src/checkThreshold.ts +0 -30
  217. package/src/constants.ts +0 -11
  218. package/src/createColumnWrapperStyle.ts +0 -16
  219. package/src/doInitialAllocateContainers.ts +0 -40
  220. package/src/doMaintainScrollAtEnd.ts +0 -34
  221. package/src/findAvailableContainers.ts +0 -98
  222. package/src/finishScrollTo.ts +0 -8
  223. package/src/getId.ts +0 -21
  224. package/src/getItemSize.ts +0 -52
  225. package/src/getRenderedItem.ts +0 -34
  226. package/src/getScrollVelocity.ts +0 -47
  227. package/src/handleLayout.ts +0 -70
  228. package/src/helpers.ts +0 -39
  229. package/src/index.ts +0 -11
  230. package/src/keyboard-controller.tsx +0 -63
  231. package/src/onScroll.ts +0 -66
  232. package/src/prepareMVCP.ts +0 -50
  233. package/src/reanimated.tsx +0 -63
  234. package/src/requestAdjust.ts +0 -41
  235. package/src/scrollTo.ts +0 -40
  236. package/src/scrollToIndex.ts +0 -34
  237. package/src/setDidLayout.ts +0 -25
  238. package/src/setPaddingTop.ts +0 -28
  239. package/src/state.tsx +0 -304
  240. package/src/types.ts +0 -610
  241. package/src/updateAlignItemsPaddingTop.ts +0 -18
  242. package/src/updateAllPositions.ts +0 -130
  243. package/src/updateItemSize.ts +0 -203
  244. package/src/updateTotalSize.ts +0 -44
  245. package/src/useAnimatedValue.ts +0 -6
  246. package/src/useCombinedRef.ts +0 -22
  247. package/src/useInit.ts +0 -17
  248. package/src/useSyncLayout.tsx +0 -68
  249. package/src/useValue$.ts +0 -53
  250. package/src/viewability.ts +0 -279
  251. package/tsconfig.json +0 -59
  252. package/tsup.config.ts +0 -21
  253. /package/{dist/animated.js → animated.js} +0 -0
  254. /package/{dist/animated.mjs → animated.mjs} +0 -0
  255. /package/{dist/keyboard-controller.js → keyboard-controller.js} +0 -0
  256. /package/{dist/keyboard-controller.mjs → keyboard-controller.mjs} +0 -0
  257. /package/{dist/reanimated.d.mts → reanimated.d.mts} +0 -0
  258. /package/{dist/reanimated.d.ts → reanimated.d.ts} +0 -0
  259. /package/{dist/reanimated.js → reanimated.js} +0 -0
  260. /package/{dist/reanimated.mjs → reanimated.mjs} +0 -0
@@ -1,187 +0,0 @@
1
- import { LegendList } from "@legendapp/list";
2
- import { type TCountryCode, countries, getEmojiFlag } from "countries-list";
3
- import { useMemo, useState } from "react";
4
- import { Pressable, StatusBar, StyleSheet, Text, View } from "react-native";
5
- import { SafeAreaProvider, SafeAreaView } from "react-native-safe-area-context";
6
-
7
- export const unstable_settings = {
8
- initialRouteName: "index",
9
- };
10
-
11
- export const createTitle = () => "Countries";
12
-
13
- type Country = {
14
- id: string;
15
- name: string;
16
- flag: string;
17
- };
18
-
19
- // Convert countries object to array and add an id
20
- const DATA: Country[] = Object.entries(countries)
21
- // .slice(0, 5)
22
- .map(([code, country]) => ({
23
- id: code,
24
- name: country.name,
25
- flag: getEmojiFlag(code as TCountryCode),
26
- }))
27
- .sort((a, b) => a.name.localeCompare(b.name));
28
-
29
- type ItemProps = {
30
- item: Country;
31
- onPress: () => void;
32
- isSelected: boolean;
33
- };
34
-
35
- const Item = ({ item, onPress, isSelected }: ItemProps) => (
36
- <Pressable
37
- onPress={onPress}
38
- style={({ pressed }) => [styles.item, isSelected && styles.selectedItem, pressed && styles.pressedItem]}
39
- >
40
- <View style={styles.flagContainer}>
41
- <Text style={styles.flag}>{item.flag}</Text>
42
- </View>
43
- <View style={styles.contentContainer}>
44
- <Text style={[styles.title, isSelected && styles.selectedText]}>
45
- {item.name}
46
- <Text style={styles.countryCode}> ({item.id})</Text>
47
- </Text>
48
- </View>
49
- </Pressable>
50
- );
51
-
52
- const App = () => {
53
- const [selectedId, setSelectedId] = useState<string>();
54
- const [randomSeed, setRandomSeed] = useState(0);
55
-
56
- // Display either ordered or randomized data based on state
57
- const displayData = useMemo(() => {
58
- if (randomSeed) {
59
- // Randomize the order
60
- return [...DATA].sort(() => Math.random() - 0.5);
61
- }
62
- // Return alphabetically sorted data
63
- return [...DATA].sort((a, b) => a.name.localeCompare(b.name));
64
- }, [randomSeed]);
65
-
66
- const renderItem = ({ item }: { item: Country }) => {
67
- const isSelected = item.id === selectedId;
68
- return <Item item={item} onPress={() => setSelectedId(item.id)} isSelected={isSelected} />;
69
- };
70
-
71
- return (
72
- <SafeAreaProvider>
73
- <SafeAreaView style={styles.container}>
74
- <View style={styles.headerContainer}>
75
- <Pressable style={styles.reorderButton} onPress={() => setRandomSeed(randomSeed + 1)}>
76
- <Text style={styles.buttonText}>Randomize Order</Text>
77
- </Pressable>
78
- </View>
79
- <LegendList
80
- data={displayData}
81
- renderItem={renderItem}
82
- keyExtractor={(item) => item.id}
83
- extraData={selectedId}
84
- estimatedItemSize={70}
85
- recycleItems
86
- onStartReachedThreshold={0.1}
87
- onStartReached={({ distanceFromStart }) => {
88
- console.log("onStartReached", distanceFromStart);
89
- }}
90
- onEndReachedThreshold={0.1}
91
- onEndReached={({ distanceFromEnd }) => {
92
- console.log("onEndReached", distanceFromEnd);
93
- }}
94
- // ListHeaderComponent={<View style={{ height: 200, backgroundColor: "red" }} />}
95
- // ListFooterComponent={<View style={{ height: 200, backgroundColor: "blue" }} />}
96
- ItemSeparatorComponent={Separator}
97
- />
98
- </SafeAreaView>
99
- </SafeAreaProvider>
100
- );
101
- };
102
-
103
- const Separator = () => <View style={{ height: 5, backgroundColor: "green" }} />;
104
-
105
- export default App;
106
-
107
- const styles = StyleSheet.create({
108
- container: {
109
- flex: 1,
110
- marginTop: StatusBar.currentHeight || 0,
111
- backgroundColor: "#f5f5f5",
112
- },
113
- headerContainer: {
114
- padding: 8,
115
- backgroundColor: "#fff",
116
- borderBottomWidth: 1,
117
- borderBottomColor: "#e0e0e0",
118
- alignItems: "center",
119
- },
120
- reorderButton: {
121
- backgroundColor: "#4a86e8",
122
- paddingVertical: 10,
123
- paddingHorizontal: 20,
124
- borderRadius: 8,
125
- width: "80%",
126
- alignItems: "center",
127
- },
128
- buttonText: {
129
- color: "#fff",
130
- fontSize: 16,
131
- fontWeight: "500",
132
- },
133
- item: {
134
- paddingHorizontal: 16,
135
- paddingVertical: 6,
136
- flexDirection: "row",
137
- alignItems: "center",
138
- backgroundColor: "#fff",
139
- borderRadius: 12,
140
- // shadowColor: "#000",
141
- // shadowOffset: {
142
- // width: 0,
143
- // height: 2,
144
- // },
145
- // shadowOpacity: 0.1,
146
- // shadowRadius: 3,
147
- // elevation: 3,
148
- },
149
- selectedItem: {
150
- // backgroundColor: "#e3f2fd",
151
- // borderColor: "#1976d2",
152
- // borderWidth: 1,
153
- },
154
- pressedItem: {
155
- // backgroundColor: "#f0f0f0",
156
- },
157
- flagContainer: {
158
- marginRight: 16,
159
- width: 40,
160
- height: 40,
161
- borderRadius: 20,
162
- backgroundColor: "#f8f9fa",
163
- alignItems: "center",
164
- justifyContent: "center",
165
- },
166
- flag: {
167
- fontSize: 28,
168
- },
169
- contentContainer: {
170
- flex: 1,
171
- justifyContent: "center",
172
- },
173
- title: {
174
- fontSize: 16,
175
- color: "#333",
176
- fontWeight: "500",
177
- },
178
- selectedText: {
179
- color: "#1976d2",
180
- fontWeight: "600",
181
- },
182
- countryCode: {
183
- fontSize: 14,
184
- color: "#666",
185
- fontWeight: "400",
186
- },
187
- });
@@ -1,86 +0,0 @@
1
- import { LegendList } from "@legendapp/list";
2
- import { useState } from "react";
3
- import { StatusBar, StyleSheet, Text, TouchableOpacity } from "react-native";
4
- import { SafeAreaProvider, SafeAreaView } from "react-native-safe-area-context";
5
-
6
- type ItemData = {
7
- id: string;
8
- title: string;
9
- };
10
-
11
- const DATA: ItemData[] = [
12
- {
13
- id: "bd7acbea-c1b1-46c2-aed5-3ad53abb28ba",
14
- title: "First Item",
15
- },
16
- {
17
- id: "3ac68afc-c605-48d3-a4f8-fbd91aa97f63",
18
- title: "Second Item",
19
- },
20
- {
21
- id: "58694a0f-3da1-471f-bd96-145571e29d72",
22
- title: "Third Item",
23
- },
24
- ];
25
-
26
- type ItemProps = {
27
- item: ItemData;
28
- onPress: () => void;
29
- backgroundColor: string;
30
- textColor: string;
31
- };
32
-
33
- const Item = ({ item, onPress, backgroundColor, textColor }: ItemProps) => (
34
- <TouchableOpacity onPress={onPress} style={[styles.item, { backgroundColor }]}>
35
- <Text style={[styles.title, { color: textColor }]}>{item.title}</Text>
36
- </TouchableOpacity>
37
- );
38
-
39
- const App = () => {
40
- const [selectedId, setSelectedId] = useState<string>();
41
-
42
- const renderItem = ({ item }: { item: ItemData }) => {
43
- const backgroundColor = item.id === selectedId ? "#6e3b6e" : "#f9c2ff";
44
- const color = item.id === selectedId ? "white" : "black";
45
-
46
- return (
47
- <Item
48
- item={item}
49
- onPress={() => setSelectedId(item.id)}
50
- backgroundColor={backgroundColor}
51
- textColor={color}
52
- />
53
- );
54
- };
55
-
56
- return (
57
- <SafeAreaProvider>
58
- <SafeAreaView style={styles.container}>
59
- <LegendList
60
- data={DATA}
61
- renderItem={renderItem}
62
- keyExtractor={(item) => item.id}
63
- extraData={selectedId}
64
- estimatedItemSize={100}
65
- />
66
- </SafeAreaView>
67
- </SafeAreaProvider>
68
- );
69
- };
70
-
71
- export default App;
72
-
73
- const styles = StyleSheet.create({
74
- container: {
75
- flex: 1,
76
- marginTop: StatusBar.currentHeight || 0,
77
- },
78
- item: {
79
- padding: 20,
80
- marginVertical: 8,
81
- marginHorizontal: 16,
82
- },
83
- title: {
84
- fontSize: 32,
85
- },
86
- });
@@ -1,55 +0,0 @@
1
- import type React from "react";
2
- import { createContext, useCallback, useContext, useMemo, useState } from "react";
3
-
4
- export interface CardItem {
5
- id: string;
6
- isExpanded: boolean;
7
- }
8
-
9
- const DataContext = createContext({
10
- data: [] as CardItem[],
11
- setExpanded: (id: string, expanded: boolean) => {},
12
- filter: "",
13
- setFilter: null as unknown as React.Dispatch<React.SetStateAction<string>>,
14
- });
15
-
16
- export const CardsDataProvider = ({
17
- initialData,
18
- children,
19
- }: { initialData: CardItem[]; children: React.ReactNode }) => {
20
- const [data, setData] = useState(initialData);
21
- const [filter, setFilter] = useState("");
22
-
23
- const setExpanded = useCallback((id: string, expanded: boolean) => {
24
- setData((prevData) => {
25
- return prevData.map((item) => {
26
- if (item.id === id) {
27
- return { ...item, isExpanded: expanded };
28
- }
29
- return item;
30
- });
31
- });
32
- }, []);
33
-
34
- const filteredData = useMemo(() => {
35
- if (filter !== "") {
36
- const filterLower = filter.toLowerCase();
37
- return data.filter((item) => item.id.includes(filterLower));
38
- }
39
- return data;
40
- }, [filter, data]);
41
-
42
- return (
43
- <DataContext.Provider value={{ data: filteredData, setExpanded, filter, setFilter }}>
44
- {children}
45
- </DataContext.Provider>
46
- );
47
- };
48
-
49
- export const useCardData = () => {
50
- const contextValue = useContext(DataContext);
51
- if (!contextValue) {
52
- throw new Error("useData must be used within a CardDataProvider");
53
- }
54
- return contextValue;
55
- };
@@ -1,118 +0,0 @@
1
- import { renderItem } from "@/app/cards-renderItem";
2
- import { DRAW_DISTANCE, ESTIMATED_ITEM_LENGTH } from "@/constants/constants";
3
- import { LegendList, type LegendListRef } from "@legendapp/list";
4
- import { useNavigation } from "expo-router";
5
- import { useEffect, useRef, useState } from "react";
6
- import { Button, StyleSheet, Text, TextInput, View } from "react-native";
7
- import { CardsDataProvider, useCardData } from "./filter-data-provider";
8
-
9
- interface CardsProps {
10
- numColumns?: number;
11
- }
12
-
13
- function FilteredCards({ numColumns = 1 }: CardsProps) {
14
- const listRef = useRef<LegendListRef>(null);
15
- const { data } = useCardData();
16
- const navigation = useNavigation();
17
- const [mvcp, setMvcp] = useState(false);
18
- const [key, setKey] = useState(0);
19
-
20
- useEffect(() => {
21
- navigation.setOptions({
22
- title: "Filter",
23
- headerRight: () => (
24
- <Button
25
- title={`${mvcp ? "✓" : ""}MVCP`}
26
- onPress={() => {
27
- setMvcp((prev) => !prev);
28
- setKey((prev) => prev + 1);
29
- }}
30
- color={mvcp ? "#00e" : "black"}
31
- />
32
- ),
33
- });
34
- }, [mvcp]);
35
-
36
- return (
37
- <View style={[StyleSheet.absoluteFill, styles.outerContainer]} key="legendlist">
38
- <FilterInput />
39
- <View style={{ flexGrow: 1 }}>
40
- <LegendList
41
- key={key} // LegendList react weird on the changing of maintainVisibleContentPosition on the fly, make sure to remount the list
42
- ref={listRef}
43
- style={[StyleSheet.absoluteFill, styles.scrollContainer]}
44
- contentContainerStyle={styles.listContainer}
45
- data={data}
46
- renderItem={renderItem}
47
- keyExtractor={(item) => `id${item.id}`}
48
- estimatedItemSize={ESTIMATED_ITEM_LENGTH}
49
- drawDistance={DRAW_DISTANCE}
50
- maintainVisibleContentPosition={mvcp}
51
- recycleItems={true}
52
- numColumns={numColumns}
53
- ListFooterComponent={<View />}
54
- ListFooterComponentStyle={styles.listHeader}
55
- ListEmptyComponent={
56
- <View style={styles.listEmpty}>
57
- <Text style={{ color: "white" }}>Empty</Text>
58
- </View>
59
- }
60
- />
61
- </View>
62
- </View>
63
- );
64
- }
65
-
66
- export default function CardsWrapper({ numColumns = 1 }: CardsProps) {
67
- return (
68
- <CardsDataProvider
69
- initialData={
70
- Array.from({ length: 1000 }, (_, i) => ({
71
- id: i.toString(),
72
- })) as any[]
73
- }
74
- >
75
- <FilteredCards numColumns={numColumns} />
76
- </CardsDataProvider>
77
- );
78
- }
79
-
80
- const FilterInput = () => {
81
- const { filter, setFilter } = useCardData();
82
- return (
83
- <TextInput
84
- placeholder="Filter"
85
- style={{ backgroundColor: "white", padding: 8, margin: 8, height: 40 }}
86
- value={filter}
87
- onChangeText={setFilter}
88
- keyboardType="numeric"
89
- />
90
- );
91
- };
92
-
93
- const styles = StyleSheet.create({
94
- listHeader: {
95
- alignSelf: "center",
96
- width: "100%",
97
- backgroundColor: "#456AAA",
98
- borderRadius: 12,
99
- marginHorizontal: 8,
100
- marginVertical: 8,
101
- },
102
- listEmpty: {
103
- flex: 1,
104
- justifyContent: "center",
105
- alignItems: "center",
106
- backgroundColor: "#6789AB",
107
- paddingVertical: 16,
108
- },
109
- outerContainer: {
110
- backgroundColor: "#456",
111
- },
112
- scrollContainer: {},
113
- listContainer: {
114
- width: 400,
115
- maxWidth: "100%",
116
- marginHorizontal: "auto",
117
- },
118
- });
@@ -1,106 +0,0 @@
1
- import { LegendList, type LegendListRef } from "@legendapp/list";
2
- import { useNavigation } from "expo-router";
3
- import { useLayoutEffect, useRef, useState } from "react";
4
- import { StyleSheet, Text, View } from "react-native";
5
- import { type Item, renderItem } from "./renderFixedItem";
6
-
7
- const ITEM_HEIGHT = 400;
8
- const SEPARATOR_HEIGHT = 52;
9
- const ESTIMATED_ITEM_LENGTH = 200;
10
-
11
- type RenderItem = Item & { type: "separator" | "item" };
12
-
13
- const RenderMultiItem = ({
14
- item,
15
- index,
16
- }: {
17
- item: RenderItem;
18
- index: number;
19
- }) => {
20
- if (item.type === "separator") {
21
- return (
22
- <View
23
- style={{
24
- height: SEPARATOR_HEIGHT,
25
- backgroundColor: "red",
26
- justifyContent: "center",
27
- alignItems: "center",
28
- }}
29
- >
30
- <Text style={{ color: "white" }}>Separator {item.id}</Text>
31
- </View>
32
- );
33
- }
34
- return renderItem({ item, index, height: ITEM_HEIGHT });
35
- };
36
-
37
- export default function ScrollIndexDemo() {
38
- const scrollViewRef = useRef<LegendListRef>(null);
39
-
40
- const [data, setData] = useState<RenderItem[]>(
41
- () =>
42
- Array.from({ length: 500 }, (_, i) => ({
43
- id: i.toString(),
44
- type: i % 3 === 0 ? "separator" : "item",
45
- })) as any[],
46
- );
47
-
48
- const navigation = useNavigation();
49
- useLayoutEffect(() => {
50
- navigation.setOptions({
51
- title: "Initial scroll index",
52
- });
53
- }, []);
54
-
55
- return (
56
- <View style={[StyleSheet.absoluteFill, styles.outerContainer]}>
57
- <LegendList
58
- ref={scrollViewRef}
59
- style={[StyleSheet.absoluteFill, styles.scrollContainer]}
60
- contentContainerStyle={styles.listContainer}
61
- data={data}
62
- renderItem={RenderMultiItem}
63
- keyExtractor={(item) => item.id}
64
- getEstimatedItemSize={(i, item) => (data[i].type === "separator" ? 52 : 400)}
65
- estimatedItemSize={ESTIMATED_ITEM_LENGTH}
66
- drawDistance={1000}
67
- recycleItems={true}
68
- // alignItemsAtEnd
69
- // maintainScrollAtEnd
70
- onEndReached={({ distanceFromEnd }) => {
71
- console.log("onEndReached", distanceFromEnd);
72
- }}
73
- ListHeaderComponent={<View />}
74
- ListHeaderComponentStyle={styles.listHeader}
75
- // initialScrollOffset={20000}
76
- initialScrollIndex={50}
77
- // inverted
78
- // horizontal
79
- />
80
- </View>
81
- );
82
- }
83
-
84
- const styles = StyleSheet.create({
85
- listHeader: {
86
- alignSelf: "center",
87
- height: 100,
88
- width: 100,
89
- backgroundColor: "#456AAA",
90
- borderRadius: 12,
91
- marginHorizontal: 8,
92
- marginTop: 8,
93
- },
94
- outerContainer: {
95
- backgroundColor: "#456",
96
- },
97
- scrollContainer: {
98
- paddingHorizontal: 16,
99
- // paddingrVertical: 48,
100
- },
101
-
102
- listContainer: {
103
- // paddingHorizontal: 16,
104
- paddingTop: 48,
105
- },
106
- });