@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,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;