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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (260) hide show
  1. package/{dist/animated.d.mts → animated.d.mts} +7 -2
  2. package/{dist/animated.d.ts → animated.d.ts} +7 -2
  3. package/{dist/animated.js → animated.js} +2 -2
  4. package/{dist/animated.mjs → animated.mjs} +2 -2
  5. package/{dist/index.d.mts → index.d.mts} +106 -56
  6. package/{dist/index.d.ts → index.d.ts} +106 -56
  7. package/{dist/index.js → index.js} +1589 -1095
  8. package/{dist/index.mjs → index.mjs} +1591 -1097
  9. package/{dist/keyboard-controller.d.mts → keyboard-controller.d.mts} +28 -8
  10. package/{dist/keyboard-controller.d.ts → keyboard-controller.d.ts} +28 -8
  11. package/{dist/keyboard-controller.js → keyboard-controller.js} +4 -4
  12. package/{dist/keyboard-controller.mjs → keyboard-controller.mjs} +4 -4
  13. package/package.json +34 -88
  14. package/{dist/reanimated.d.mts → reanimated.d.mts} +2 -2
  15. package/{dist/reanimated.d.ts → reanimated.d.ts} +2 -2
  16. package/{dist/reanimated.js → reanimated.js} +7 -7
  17. package/{dist/reanimated.mjs → reanimated.mjs} +7 -7
  18. package/.claude/settings.local.json +0 -8
  19. package/.cursor/rules/changelog.mdc +0 -60
  20. package/.github/FUNDING.yml +0 -15
  21. package/.gitignore +0 -5
  22. package/.prettierrc.json +0 -5
  23. package/.vscode/settings.json +0 -14
  24. package/CLAUDE.md +0 -126
  25. package/biome.json +0 -46
  26. package/bun.lock +0 -1289
  27. package/bunfig.toml +0 -2
  28. package/dist/CHANGELOG.md +0 -119
  29. package/dist/LICENSE +0 -21
  30. package/dist/README.md +0 -139
  31. package/dist/package.json +0 -35
  32. package/example/README.md +0 -40
  33. package/example/api/data/genres.json +0 -23
  34. package/example/api/data/playlist/10402-10749.json +0 -1
  35. package/example/api/data/playlist/10402-10770.json +0 -1
  36. package/example/api/data/playlist/10402-37.json +0 -1
  37. package/example/api/data/playlist/10749-10752.json +0 -1
  38. package/example/api/data/playlist/10749-10770.json +0 -1
  39. package/example/api/data/playlist/10749-37.json +0 -1
  40. package/example/api/data/playlist/10749-878.json +0 -1
  41. package/example/api/data/playlist/10751-10402.json +0 -1
  42. package/example/api/data/playlist/10751-10752.json +0 -1
  43. package/example/api/data/playlist/10751-37.json +0 -1
  44. package/example/api/data/playlist/10751-53.json +0 -1
  45. package/example/api/data/playlist/10751-878.json +0 -1
  46. package/example/api/data/playlist/10751-9648.json +0 -1
  47. package/example/api/data/playlist/10752-37.json +0 -1
  48. package/example/api/data/playlist/12-10402.json +0 -1
  49. package/example/api/data/playlist/12-10749.json +0 -1
  50. package/example/api/data/playlist/12-18.json +0 -1
  51. package/example/api/data/playlist/12-27.json +0 -1
  52. package/example/api/data/playlist/12-35.json +0 -1
  53. package/example/api/data/playlist/14-36.json +0 -1
  54. package/example/api/data/playlist/14-878.json +0 -1
  55. package/example/api/data/playlist/16-10751.json +0 -1
  56. package/example/api/data/playlist/16-10770.json +0 -1
  57. package/example/api/data/playlist/16-35.json +0 -1
  58. package/example/api/data/playlist/16-36.json +0 -1
  59. package/example/api/data/playlist/16-53.json +0 -1
  60. package/example/api/data/playlist/18-10751.json +0 -1
  61. package/example/api/data/playlist/18-10752.json +0 -1
  62. package/example/api/data/playlist/18-37.json +0 -1
  63. package/example/api/data/playlist/18-53.json +0 -1
  64. package/example/api/data/playlist/18-878.json +0 -1
  65. package/example/api/data/playlist/27-10749.json +0 -1
  66. package/example/api/data/playlist/27-10770.json +0 -1
  67. package/example/api/data/playlist/28-10749.json +0 -1
  68. package/example/api/data/playlist/28-10751.json +0 -1
  69. package/example/api/data/playlist/28-10770.json +0 -1
  70. package/example/api/data/playlist/28-16.json +0 -1
  71. package/example/api/data/playlist/28-18.json +0 -1
  72. package/example/api/data/playlist/28-36.json +0 -1
  73. package/example/api/data/playlist/28-37.json +0 -1
  74. package/example/api/data/playlist/28-53.json +0 -1
  75. package/example/api/data/playlist/28-80.json +0 -1
  76. package/example/api/data/playlist/28-99.json +0 -1
  77. package/example/api/data/playlist/35-10749.json +0 -1
  78. package/example/api/data/playlist/35-10751.json +0 -1
  79. package/example/api/data/playlist/35-10752.json +0 -1
  80. package/example/api/data/playlist/35-27.json +0 -1
  81. package/example/api/data/playlist/35-36.json +0 -1
  82. package/example/api/data/playlist/35-53.json +0 -1
  83. package/example/api/data/playlist/35-80.json +0 -1
  84. package/example/api/data/playlist/36-37.json +0 -1
  85. package/example/api/data/playlist/36-878.json +0 -1
  86. package/example/api/data/playlist/36-9648.json +0 -1
  87. package/example/api/data/playlist/53-10752.json +0 -1
  88. package/example/api/data/playlist/80-10770.json +0 -1
  89. package/example/api/data/playlist/80-14.json +0 -1
  90. package/example/api/data/playlist/80-18.json +0 -1
  91. package/example/api/data/playlist/80-37.json +0 -1
  92. package/example/api/data/playlist/878-37.json +0 -1
  93. package/example/api/data/playlist/9648-10770.json +0 -1
  94. package/example/api/data/playlist/9648-37.json +0 -1
  95. package/example/api/data/playlist/9648-53.json +0 -1
  96. package/example/api/data/playlist/9648-878.json +0 -1
  97. package/example/api/data/playlist/99-10749.json +0 -1
  98. package/example/api/data/playlist/99-14.json +0 -1
  99. package/example/api/data/playlist/99-18.json +0 -1
  100. package/example/api/data/playlist/99-27.json +0 -1
  101. package/example/api/data/playlist/99-53.json +0 -1
  102. package/example/api/data/playlist/99-9648.json +0 -1
  103. package/example/api/data/playlist/index.ts +0 -73
  104. package/example/api/data/rows.json +0 -1
  105. package/example/api/index.ts +0 -36
  106. package/example/app/(tabs)/_layout.tsx +0 -60
  107. package/example/app/(tabs)/cards.tsx +0 -81
  108. package/example/app/(tabs)/index.tsx +0 -205
  109. package/example/app/(tabs)/moviesL.tsx +0 -7
  110. package/example/app/(tabs)/moviesLR.tsx +0 -7
  111. package/example/app/+not-found.tsx +0 -32
  112. package/example/app/_layout.tsx +0 -34
  113. package/example/app/accurate-scrollto/index.tsx +0 -125
  114. package/example/app/accurate-scrollto-2/index.tsx +0 -52
  115. package/example/app/accurate-scrollto-huge/index.tsx +0 -128
  116. package/example/app/add-to-end/index.tsx +0 -82
  117. package/example/app/ai-chat/index.tsx +0 -236
  118. package/example/app/bidirectional-infinite-list/index.tsx +0 -133
  119. package/example/app/cards-columns/index.tsx +0 -37
  120. package/example/app/cards-flashlist/index.tsx +0 -122
  121. package/example/app/cards-flatlist/index.tsx +0 -94
  122. package/example/app/cards-no-recycle/index.tsx +0 -110
  123. package/example/app/cards-renderItem.tsx +0 -354
  124. package/example/app/chat-example/index.tsx +0 -167
  125. package/example/app/chat-infinite/index.tsx +0 -239
  126. package/example/app/chat-keyboard/index.tsx +0 -248
  127. package/example/app/chat-resize-outer/index.tsx +0 -247
  128. package/example/app/columns/index.tsx +0 -78
  129. package/example/app/countries/index.tsx +0 -182
  130. package/example/app/countries-flashlist/index.tsx +0 -163
  131. package/example/app/countries-reorder/index.tsx +0 -187
  132. package/example/app/extra-data/index.tsx +0 -86
  133. package/example/app/filter-elements/filter-data-provider.tsx +0 -55
  134. package/example/app/filter-elements/index.tsx +0 -118
  135. package/example/app/initial-scroll-index/index.tsx +0 -106
  136. package/example/app/initial-scroll-index/renderFixedItem.tsx +0 -215
  137. package/example/app/initial-scroll-index-free-height/index.tsx +0 -70
  138. package/example/app/initial-scroll-index-keyed/index.tsx +0 -62
  139. package/example/app/lazy-list/index.tsx +0 -123
  140. package/example/app/movies-flashlist/index.tsx +0 -7
  141. package/example/app/mutable-cells/index.tsx +0 -104
  142. package/example/app/video-feed/index.tsx +0 -119
  143. package/example/app.config.js +0 -22
  144. package/example/app.json +0 -45
  145. package/example/assets/fonts/SpaceMono-Regular.ttf +0 -0
  146. package/example/assets/images/adaptive-icon.png +0 -0
  147. package/example/assets/images/favicon.png +0 -0
  148. package/example/assets/images/icon.png +0 -0
  149. package/example/assets/images/partial-react-logo.png +0 -0
  150. package/example/assets/images/react-logo.png +0 -0
  151. package/example/assets/images/react-logo@2x.png +0 -0
  152. package/example/assets/images/react-logo@3x.png +0 -0
  153. package/example/assets/images/splash-icon.png +0 -0
  154. package/example/autoscroll.sh +0 -101
  155. package/example/bun.lock +0 -2266
  156. package/example/bunfig.toml +0 -2
  157. package/example/components/Breathe.tsx +0 -54
  158. package/example/components/Circle.tsx +0 -69
  159. package/example/components/Collapsible.tsx +0 -44
  160. package/example/components/ExternalLink.tsx +0 -24
  161. package/example/components/HapticTab.tsx +0 -18
  162. package/example/components/HelloWave.tsx +0 -37
  163. package/example/components/Movies.tsx +0 -179
  164. package/example/components/ParallaxScrollView.tsx +0 -81
  165. package/example/components/ThemedText.tsx +0 -60
  166. package/example/components/ThemedView.tsx +0 -14
  167. package/example/components/__tests__/ThemedText-test.tsx +0 -10
  168. package/example/components/__tests__/__snapshots__/ThemedText-test.tsx.snap +0 -24
  169. package/example/components/ui/IconSymbol.ios.tsx +0 -32
  170. package/example/components/ui/IconSymbol.tsx +0 -43
  171. package/example/components/ui/TabBarBackground.ios.tsx +0 -22
  172. package/example/components/ui/TabBarBackground.tsx +0 -6
  173. package/example/constants/Colors.ts +0 -26
  174. package/example/constants/constants.ts +0 -5
  175. package/example/constants/useScrollTest.ts +0 -19
  176. package/example/hooks/useColorScheme.ts +0 -1
  177. package/example/hooks/useColorScheme.web.ts +0 -8
  178. package/example/hooks/useThemeColor.ts +0 -22
  179. package/example/ios/.xcode.env +0 -11
  180. package/example/ios/Podfile +0 -64
  181. package/example/ios/Podfile.lock +0 -2767
  182. package/example/ios/Podfile.properties.json +0 -5
  183. package/example/ios/listtest/AppDelegate.swift +0 -70
  184. package/example/ios/listtest/Images.xcassets/AppIcon.appiconset/App-Icon-1024x1024@1x.png +0 -0
  185. package/example/ios/listtest/Images.xcassets/AppIcon.appiconset/Contents.json +0 -14
  186. package/example/ios/listtest/Images.xcassets/Contents.json +0 -6
  187. package/example/ios/listtest/Images.xcassets/SplashScreenBackground.colorset/Contents.json +0 -20
  188. package/example/ios/listtest/Images.xcassets/SplashScreenLogo.imageset/Contents.json +0 -23
  189. package/example/ios/listtest/Images.xcassets/SplashScreenLogo.imageset/image.png +0 -0
  190. package/example/ios/listtest/Images.xcassets/SplashScreenLogo.imageset/image@2x.png +0 -0
  191. package/example/ios/listtest/Images.xcassets/SplashScreenLogo.imageset/image@3x.png +0 -0
  192. package/example/ios/listtest/Info.plist +0 -85
  193. package/example/ios/listtest/PrivacyInfo.xcprivacy +0 -48
  194. package/example/ios/listtest/SplashScreen.storyboard +0 -42
  195. package/example/ios/listtest/Supporting/Expo.plist +0 -12
  196. package/example/ios/listtest/listtest-Bridging-Header.h +0 -3
  197. package/example/ios/listtest/listtest.entitlements +0 -5
  198. package/example/ios/listtest.xcodeproj/project.pbxproj +0 -547
  199. package/example/ios/listtest.xcodeproj/xcshareddata/xcschemes/listtest.xcscheme +0 -88
  200. package/example/ios/listtest.xcworkspace/contents.xcworkspacedata +0 -10
  201. package/example/metro.config.js +0 -16
  202. package/example/package.json +0 -73
  203. package/example/scripts/reset-project.js +0 -84
  204. package/example/tsconfig.json +0 -26
  205. package/posttsup.ts +0 -24
  206. package/src/Container.tsx +0 -176
  207. package/src/Containers.tsx +0 -85
  208. package/src/ContextContainer.ts +0 -145
  209. package/src/DebugView.tsx +0 -83
  210. package/src/LazyLegendList.tsx +0 -41
  211. package/src/LeanView.tsx +0 -18
  212. package/src/LegendList.tsx +0 -558
  213. package/src/ListComponent.tsx +0 -191
  214. package/src/ScrollAdjust.tsx +0 -24
  215. package/src/ScrollAdjustHandler.ts +0 -26
  216. package/src/Separator.tsx +0 -14
  217. package/src/animated.tsx +0 -6
  218. package/src/calculateItemsInView.ts +0 -363
  219. package/src/calculateOffsetForIndex.ts +0 -23
  220. package/src/calculateOffsetWithOffsetPosition.ts +0 -26
  221. package/src/checkAllSizesKnown.ts +0 -17
  222. package/src/checkAtBottom.ts +0 -36
  223. package/src/checkAtTop.ts +0 -27
  224. package/src/checkThreshold.ts +0 -30
  225. package/src/constants.ts +0 -11
  226. package/src/createColumnWrapperStyle.ts +0 -16
  227. package/src/doInitialAllocateContainers.ts +0 -40
  228. package/src/doMaintainScrollAtEnd.ts +0 -34
  229. package/src/findAvailableContainers.ts +0 -98
  230. package/src/finishScrollTo.ts +0 -8
  231. package/src/getId.ts +0 -21
  232. package/src/getItemSize.ts +0 -52
  233. package/src/getRenderedItem.ts +0 -34
  234. package/src/getScrollVelocity.ts +0 -47
  235. package/src/handleLayout.ts +0 -70
  236. package/src/helpers.ts +0 -39
  237. package/src/index.ts +0 -11
  238. package/src/keyboard-controller.tsx +0 -63
  239. package/src/onScroll.ts +0 -66
  240. package/src/prepareMVCP.ts +0 -50
  241. package/src/reanimated.tsx +0 -63
  242. package/src/requestAdjust.ts +0 -41
  243. package/src/scrollTo.ts +0 -40
  244. package/src/scrollToIndex.ts +0 -34
  245. package/src/setDidLayout.ts +0 -25
  246. package/src/setPaddingTop.ts +0 -28
  247. package/src/state.tsx +0 -304
  248. package/src/types.ts +0 -610
  249. package/src/updateAlignItemsPaddingTop.ts +0 -18
  250. package/src/updateAllPositions.ts +0 -130
  251. package/src/updateItemSize.ts +0 -203
  252. package/src/updateTotalSize.ts +0 -44
  253. package/src/useAnimatedValue.ts +0 -6
  254. package/src/useCombinedRef.ts +0 -22
  255. package/src/useInit.ts +0 -17
  256. package/src/useSyncLayout.tsx +0 -68
  257. package/src/useValue$.ts +0 -53
  258. package/src/viewability.ts +0 -279
  259. package/tsconfig.json +0 -59
  260. package/tsup.config.ts +0 -21
@@ -1,110 +0,0 @@
1
- import { type Item, renderItem } from "@/app/cards-renderItem";
2
- import { DO_SCROLL_TEST, DRAW_DISTANCE, ESTIMATED_ITEM_LENGTH } from "@/constants/constants";
3
- import { useScrollTest } from "@/constants/useScrollTest";
4
- import { LegendList, type LegendListRef } from "@legendapp/list";
5
- import { useRef, useState } from "react";
6
- import { LogBox, Platform, StyleSheet, Text, View } from "react-native";
7
-
8
- LogBox.ignoreLogs(["Open debugger"]);
9
-
10
- interface CardsProps {
11
- numColumns?: number;
12
- }
13
-
14
- export default function Cards({ numColumns = 1 }: CardsProps) {
15
- const listRef = useRef<LegendListRef>(null);
16
-
17
- const [data, setData] = useState<Item[]>(
18
- () =>
19
- Array.from({ length: 1000 }, (_, i) => ({
20
- id: i.toString(),
21
- })) as any[],
22
- );
23
-
24
- if (DO_SCROLL_TEST) {
25
- useScrollTest((offset) => {
26
- listRef.current?.scrollToOffset({
27
- offset: offset,
28
- animated: true,
29
- });
30
- });
31
- }
32
-
33
- return (
34
- <View style={[StyleSheet.absoluteFill, styles.outerContainer]} key="legendlist">
35
- <LegendList
36
- ref={listRef}
37
- style={[StyleSheet.absoluteFill, styles.scrollContainer]}
38
- contentContainerStyle={styles.listContainer}
39
- data={data}
40
- renderItem={renderItem}
41
- keyExtractor={(item) => `id${item.id}`}
42
- estimatedItemSize={ESTIMATED_ITEM_LENGTH}
43
- drawDistance={DRAW_DISTANCE}
44
- recycleItems={false}
45
- numColumns={numColumns}
46
- // initialScrollIndex={50}
47
- // alignItemsAtEnd
48
- // maintainScrollAtEnd
49
- // onEndReached={({ distanceFromEnd }) => {
50
- // console.log("onEndReached", distanceFromEnd);
51
- // }}
52
- ListHeaderComponent={<View />}
53
- ListHeaderComponentStyle={styles.listHeader}
54
- ListFooterComponent={<View />}
55
- ListFooterComponentStyle={styles.listHeader}
56
- ListEmptyComponent={
57
- <View style={styles.listEmpty}>
58
- <Text style={{ color: "white" }}>Empty</Text>
59
- </View>
60
- }
61
- // viewabilityConfigCallbackPairs={[
62
- // {
63
- // viewabilityConfig: { id: "viewability", viewAreaCoveragePercentThreshold: 50 },
64
- // // onViewableItemsChanged: ({ viewableItems, changed }) => {
65
- // // console.log(
66
- // // 'onViewableItems',
67
- // // viewableItems.map((v) => v.key),
68
- // // );
69
- // // // console.log('onViewableChanged', changed);
70
- // // },
71
- // },
72
- // ]}
73
-
74
- // initialScrollOffset={20000}
75
- // initialScrollIndex={500}
76
- // inverted
77
- // horizontal
78
- />
79
- </View>
80
- );
81
- }
82
-
83
- const styles = StyleSheet.create({
84
- listHeader: {
85
- alignSelf: "center",
86
- height: 100,
87
- width: 100,
88
- backgroundColor: "#456AAA",
89
- borderRadius: 12,
90
- marginHorizontal: 8,
91
- marginVertical: 8,
92
- },
93
- listEmpty: {
94
- flex: 1,
95
- justifyContent: "center",
96
- alignItems: "center",
97
- backgroundColor: "#6789AB",
98
- paddingVertical: 16,
99
- },
100
- outerContainer: {
101
- backgroundColor: "#456",
102
- bottom: Platform.OS === "ios" ? 82 : 0,
103
- },
104
- scrollContainer: {},
105
- listContainer: {
106
- width: 400,
107
- maxWidth: "100%",
108
- marginHorizontal: "auto",
109
- },
110
- });
@@ -1,354 +0,0 @@
1
- import { MaterialIcons } from "@expo/vector-icons";
2
- import { LegendList, type LegendListRenderItemProps, useRecyclingState } from "@legendapp/list";
3
- import { memo, useRef, useState } from "react";
4
- import { Animated, Image, Platform, Pressable, StyleSheet, Text, UIManager, View } from "react-native";
5
- import { RectButton } from "react-native-gesture-handler";
6
- import Swipeable, { type SwipeableMethods } from "react-native-gesture-handler/ReanimatedSwipeable";
7
-
8
- export interface Item {
9
- id: string;
10
- }
11
- const demoNestedList = false;
12
-
13
- // Generate random metadata
14
- const randomAvatars = Array.from({ length: 20 }, (_, i) => `https://i.pravatar.cc/150?img=${i + 1}`);
15
-
16
- export const randomNames = [
17
- "Alex Thompson",
18
- "Jordan Lee",
19
- "Sam Parker",
20
- "Taylor Kim",
21
- "Morgan Chen",
22
- "Riley Zhang",
23
- "Casey Williams",
24
- "Quinn Anderson",
25
- "Blake Martinez",
26
- "Avery Rodriguez",
27
- "Drew Campbell",
28
- "Jamie Foster",
29
- "Skylar Patel",
30
- "Charlie Wright",
31
- "Sage Mitchell",
32
- "River Johnson",
33
- "Phoenix Garcia",
34
- "Jordan Taylor",
35
- "Reese Cooper",
36
- "Morgan Bailey",
37
- ];
38
-
39
- // Array of lorem ipsum sentences to randomly choose from
40
- export const loremSentences = [
41
- "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
42
- "Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
43
- "Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris.",
44
- "Duis aute irure dolor in reprehenderit in voluptate velit esse.",
45
- "Excepteur sint occaecat cupidatat non proident, sunt in culpa.",
46
- "Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit.",
47
- "Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet.",
48
- "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
49
- "Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
50
- "Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris.",
51
- "Duis aute irure dolor in reprehenderit in voluptate velit esse.",
52
- "Excepteur sint occaecat cupidatat non proident, sunt in culpa.",
53
- "Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit.",
54
- "Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet.",
55
- ];
56
-
57
- if (Platform.OS === "android") {
58
- if (UIManager.setLayoutAnimationEnabledExperimental) {
59
- UIManager.setLayoutAnimationEnabledExperimental(true);
60
- }
61
- }
62
-
63
- const renderRightActions = () => {
64
- return (
65
- <RectButton
66
- style={{
67
- width: 80,
68
- height: "100%",
69
- backgroundColor: "#4CAF50",
70
- justifyContent: "center",
71
- alignItems: "center",
72
- borderTopRightRadius: 12,
73
- borderBottomRightRadius: 12,
74
- shadowColor: "#000",
75
- shadowOffset: { width: 2, height: 0 },
76
- shadowOpacity: 0.1,
77
- shadowRadius: 4,
78
- }}
79
- onPress={() => {
80
- console.log("Marked as complete");
81
- }}
82
- >
83
- <MaterialIcons name="check-circle" size={24} color="white" />
84
- <Text
85
- style={{
86
- color: "white",
87
- fontSize: 12,
88
- marginTop: 4,
89
- fontWeight: "600",
90
- }}
91
- >
92
- Complete
93
- </Text>
94
- </RectButton>
95
- );
96
- };
97
-
98
- // Inline Separator makes containers rerender each data change
99
- const Separator = () => <View style={{ height: 10 }} />;
100
-
101
- export const ItemCard = memo(
102
- ({
103
- item,
104
- index,
105
- extraData,
106
- numSentences: numSentencesProp,
107
- }: LegendListRenderItemProps<Item> & { numSentences: number | ((index: number) => number) }) => {
108
- const refSwipeable = useRef<SwipeableMethods>();
109
-
110
- // A useState that resets when the item is recycled
111
- const [isExpanded, setIsExpanded] = extraData?.recycleState ? useRecyclingState(() => false) : useState(false);
112
-
113
- const swipeableState = useRef(false);
114
-
115
- // console.log(Math.round(performance.now()), "renderItem", index);
116
-
117
- // A callback when the item is recycled
118
- // useRecyclingEffect?.(({ item, prevItem, index, prevIndex }) => {
119
- // if (swipeableState.current) {
120
- // // this is expensive operation, run .close() only if the swipeable is open
121
- // refSwipeable?.current?.close();
122
- // }
123
- // });
124
-
125
- // A callback when the item viewability (from viewabilityConfig) changes
126
- // useViewability?.("viewability", ({ item, isViewable, index }) => {
127
- // // console.log('viewable', viewToken.index, viewToken.isViewable);
128
- // });
129
-
130
- // @ts-ignore
131
- // const opacity = useViewabilityAmount ? useAnimatedValue(1) : 1;
132
- // useViewabilityAmount?.(({ sizeVisible, size, percentOfScroller }) => {
133
- // // @ts-ignore
134
- // // opacity.setValue(Math.max(0, Math.min(1, sizeVisible / Math.min(400, size || 400)) ** 1.5));
135
- // // console.log('viewable', sizeVisible, size, percentOfScroller);
136
- // });
137
-
138
- // Math.abs needed for negative indices
139
- const indexForData = Math.abs(item.id.includes("new") ? 100 + +item.id.replace("new", "") : +item.id);
140
-
141
- // Generate 1-5 random sentences
142
- const numSentences = numSentencesProp
143
- ? typeof numSentencesProp === "function"
144
- ? numSentencesProp(indexForData)
145
- : numSentencesProp
146
- : ((indexForData * 7919) % 4) + 1; // Using prime number 7919 for better distribution
147
- // const indexForData =
148
- // item.id === "0" ? 0 : item.id === "1" ? 1 : item.id === "new0" ? 2 : 3;
149
- // const numSentences =
150
- // item.id === "0" ? 1 : item.id === "1" ? 2 : item.id === "new0" ? 4 : 8;
151
- const randomText = Array.from(
152
- { length: numSentences },
153
- (_, i) => loremSentences[i % loremSentences.length],
154
- ).join(" ");
155
-
156
- // Use randomIndex to deterministically select random data
157
- const avatarUrl = randomAvatars[indexForData % randomAvatars.length];
158
- const authorName = randomNames[indexForData % randomNames.length];
159
- const timestamp = `${Math.max(1, indexForData % 24)}h ago`;
160
-
161
- if (index === 1 && demoNestedList) {
162
- return (
163
- <Animated.View style={[styles.nestedListContainer]}>
164
- <LegendList
165
- showsHorizontalScrollIndicator={false}
166
- horizontal
167
- estimatedItemSize={400}
168
- keyExtractor={(item) => item.text}
169
- data={[
170
- {
171
- id: "1",
172
- text: "List Item 1",
173
- },
174
- {
175
- id: "2",
176
- text: "List Item 2",
177
- },
178
- {
179
- id: "3",
180
- text: "List Item 3",
181
- },
182
- ]}
183
- ItemSeparatorComponent={Separator}
184
- renderItem={({ item }) => (
185
- <View style={styles.nestedListItem}>
186
- <Text>{item.text}</Text>
187
- </View>
188
- )}
189
- />
190
- </Animated.View>
191
- );
192
- }
193
-
194
- return (
195
- <View style={{ ...styles.itemOuterContainer }}>
196
- <Swipeable
197
- renderRightActions={renderRightActions}
198
- overshootRight={true}
199
- containerStyle={styles.swipeableContainer}
200
- ref={refSwipeable as any}
201
- onSwipeableWillOpen={() => {
202
- swipeableState.current = true;
203
- }}
204
- onSwipeableWillClose={() => {
205
- swipeableState.current = false;
206
- }}
207
- >
208
- <Pressable
209
- onPress={(e) => {
210
- // LinearTransition.easing(Easing.ease);
211
-
212
- e.stopPropagation();
213
- setIsExpanded(!isExpanded);
214
- }}
215
- >
216
- <View
217
- style={[
218
- styles.itemContainer,
219
- {
220
- // padding: 16,
221
- backgroundColor: "#ffffff",
222
- borderRadius: 12,
223
- shadowColor: "#000",
224
- shadowOffset: { width: 0, height: 2 },
225
- shadowOpacity: 0.1,
226
- shadowRadius: 4,
227
- // marginVertical: 8,
228
- overflow: "hidden",
229
- },
230
- ]}
231
- >
232
- <View style={styles.headerContainer}>
233
- <Image source={{ uri: avatarUrl }} style={styles.avatar} />
234
- <View style={styles.headerText}>
235
- <Text style={styles.authorName}>
236
- {authorName} {item.id}
237
- </Text>
238
- <Text style={styles.timestamp}>{timestamp}</Text>
239
- </View>
240
- </View>
241
-
242
- <Text style={styles.itemTitle}>Item #{item.id}</Text>
243
- <Text
244
- style={styles.itemBody}
245
- // numberOfLines={isExpanded ? undefined : 10}
246
- >
247
- {randomText}
248
- {isExpanded ? randomText : null}
249
- </Text>
250
- <View style={styles.itemFooter}>
251
- <Text style={styles.footerText}>❤️ 42</Text>
252
- <Text style={styles.footerText}>💬 12</Text>
253
- <Text style={styles.footerText}>🔄 8</Text>
254
- </View>
255
- </View>
256
- {/* <Breathe /> */}
257
- </Pressable>
258
- </Swipeable>
259
- </View>
260
- );
261
- },
262
- );
263
-
264
- export const renderItem = (props: LegendListRenderItemProps<Item>) => <ItemCard {...props} />;
265
-
266
- const styles = StyleSheet.create({
267
- nestedListContainer: {
268
- paddingVertical: 8,
269
- paddingHorizontal: 8,
270
- height: 200,
271
- },
272
- nestedListItem: {
273
- backgroundColor: "white",
274
- height: 200,
275
- width: 200,
276
- justifyContent: "center",
277
- alignItems: "center",
278
- },
279
- itemOuterContainer: {
280
- paddingVertical: 8,
281
- paddingHorizontal: 8,
282
- //width: 380,
283
- //marginLeft: 6,
284
- },
285
- itemContainer: {
286
- padding: 16,
287
- // borderBottomWidth: 1,
288
- // borderBottomColor: "#ccc",
289
- },
290
- titleContainer: {
291
- flexDirection: "row",
292
- alignItems: "center",
293
- gap: 8,
294
- },
295
- stepContainer: {
296
- gap: 8,
297
- marginBottom: 8,
298
- },
299
- listContainer: {
300
- paddingHorizontal: 16,
301
- },
302
- itemTitle: {
303
- fontSize: 18,
304
- fontWeight: "bold",
305
- marginBottom: 8,
306
- color: "#1a1a1a",
307
- },
308
- itemBody: {
309
- fontSize: 14,
310
- color: "#666666",
311
- lineHeight: 20,
312
- // flex: 1,
313
- },
314
- itemFooter: {
315
- flexDirection: "row",
316
- justifyContent: "flex-start",
317
- gap: 16,
318
- marginTop: 12,
319
- paddingTop: 12,
320
- borderTopWidth: 1,
321
- borderTopColor: "#f0f0f0",
322
- },
323
- footerText: {
324
- fontSize: 14,
325
- color: "#888888",
326
- },
327
- headerContainer: {
328
- flexDirection: "row",
329
- alignItems: "center",
330
- marginBottom: 12,
331
- },
332
- avatar: {
333
- width: 40,
334
- height: 40,
335
- borderRadius: 20,
336
- marginRight: 12,
337
- },
338
- headerText: {
339
- flex: 1,
340
- },
341
- authorName: {
342
- fontSize: 16,
343
- fontWeight: "600",
344
- color: "#1a1a1a",
345
- },
346
- timestamp: {
347
- fontSize: 12,
348
- color: "#888888",
349
- marginTop: 2,
350
- },
351
- swipeableContainer: { backgroundColor: "#4CAF50", borderRadius: 12 },
352
- });
353
-
354
- export default renderItem;
@@ -1,167 +0,0 @@
1
- import { LegendList } from "@legendapp/list";
2
- import { useHeaderHeight } from "@react-navigation/elements";
3
- import { useState } from "react";
4
- import { Button, KeyboardAvoidingView, Platform, StyleSheet, Text, TextInput, View } from "react-native";
5
- import { SafeAreaView } from "react-native-safe-area-context";
6
-
7
- type Message = {
8
- id: string;
9
- text: string;
10
- sender: "user" | "bot";
11
- timeStamp: number;
12
- };
13
-
14
- let idCounter = 0;
15
- const MS_PER_SECOND = 1000;
16
-
17
- const defaultChatMessages: Message[] = [
18
- {
19
- id: String(idCounter++),
20
- text: "Hi, I have a question",
21
- sender: "user",
22
- timeStamp: Date.now() - MS_PER_SECOND * 5,
23
- },
24
- { id: String(idCounter++), text: "Hello", sender: "bot", timeStamp: Date.now() - MS_PER_SECOND * 4 },
25
- { id: String(idCounter++), text: "How can I help you?", sender: "bot", timeStamp: Date.now() - MS_PER_SECOND * 3 },
26
- ];
27
-
28
- const ChatExample = () => {
29
- const [messages, setMessages] = useState<Message[]>(defaultChatMessages);
30
- const [inputText, setInputText] = useState("");
31
- const headerHeight = Platform.OS === "ios" ? useHeaderHeight() : 80;
32
-
33
- const sendMessage = () => {
34
- const text = inputText || "Empty message";
35
- if (text.trim()) {
36
- setMessages((messages) => [
37
- ...messages,
38
- { id: String(idCounter++), text: text, sender: "user", timeStamp: Date.now() },
39
- ]);
40
- setInputText("");
41
- setTimeout(() => {
42
- setMessages((messages) => [
43
- ...messages,
44
- {
45
- id: String(idCounter++),
46
- text: `Answer: ${text.toUpperCase()}`,
47
- sender: "bot",
48
- timeStamp: Date.now(),
49
- },
50
- ]);
51
- }, 300);
52
- }
53
- };
54
-
55
- return (
56
- <SafeAreaView style={styles.container} edges={["bottom"]}>
57
- <KeyboardAvoidingView
58
- style={styles.container}
59
- behavior="padding"
60
- keyboardVerticalOffset={headerHeight}
61
- contentContainerStyle={{ flex: 1 }}
62
- >
63
- <LegendList
64
- data={messages}
65
- contentContainerStyle={styles.contentContainer}
66
- keyExtractor={(item) => item.id}
67
- estimatedItemSize={10} // A size that's way too small to check the behavior is correct
68
- initialScrollIndex={messages.length - 1}
69
- maintainVisibleContentPosition
70
- maintainScrollAtEnd
71
- alignItemsAtEnd
72
- renderItem={({ item }) => (
73
- <>
74
- <View
75
- style={[
76
- styles.messageContainer,
77
- item.sender === "bot" ? styles.botMessageContainer : styles.userMessageContainer,
78
- item.sender === "bot" ? styles.botStyle : styles.userStyle,
79
- ]}
80
- >
81
- <Text style={[styles.messageText, item.sender === "user" && styles.userMessageText]}>
82
- {item.text}
83
- </Text>
84
- </View>
85
- <View
86
- style={[styles.timeStamp, item.sender === "bot" ? styles.botStyle : styles.userStyle]}
87
- >
88
- <Text style={styles.timeStampText}>
89
- {new Date(item.timeStamp).toLocaleTimeString()}
90
- </Text>
91
- </View>
92
- </>
93
- )}
94
- />
95
- <View style={styles.inputContainer}>
96
- <TextInput
97
- style={styles.input}
98
- value={inputText}
99
- onChangeText={setInputText}
100
- placeholder="Type a message"
101
- />
102
- <Button title="Send" onPress={sendMessage} />
103
- </View>
104
- </KeyboardAvoidingView>
105
- </SafeAreaView>
106
- );
107
- };
108
-
109
- const styles = StyleSheet.create({
110
- container: {
111
- flex: 1,
112
- backgroundColor: "#fff",
113
- },
114
- contentContainer: {
115
- paddingHorizontal: 16,
116
- },
117
- messageContainer: {
118
- padding: 16,
119
- borderRadius: 16,
120
- marginVertical: 4,
121
- },
122
- messageText: {
123
- fontSize: 16,
124
- },
125
- userMessageText: {
126
- color: "white",
127
- },
128
- inputContainer: {
129
- flexDirection: "row",
130
- alignItems: "center",
131
- padding: 10,
132
- borderTopWidth: 1,
133
- borderColor: "#ccc",
134
- },
135
- botMessageContainer: {
136
- backgroundColor: "#f1f1f1",
137
- },
138
- userMessageContainer: {
139
- backgroundColor: "#007AFF",
140
- },
141
- botStyle: {
142
- maxWidth: "75%",
143
- alignSelf: "flex-start",
144
- },
145
- userStyle: {
146
- maxWidth: "75%",
147
- alignSelf: "flex-end",
148
- alignItems: "flex-end",
149
- },
150
- input: {
151
- flex: 1,
152
- borderWidth: 1,
153
- borderColor: "#ccc",
154
- borderRadius: 5,
155
- padding: 10,
156
- marginRight: 10,
157
- },
158
- timeStamp: {
159
- marginVertical: 5,
160
- },
161
- timeStampText: {
162
- fontSize: 12,
163
- color: "#888",
164
- },
165
- });
166
-
167
- export default ChatExample;