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

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 (264) hide show
  1. package/{dist/animated.d.mts → animated.d.mts} +10 -3
  2. package/{dist/animated.d.ts → animated.d.ts} +10 -3
  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} +86 -167
  6. package/{dist/index.d.ts → index.d.ts} +86 -167
  7. package/{dist/index.js → index.js} +1594 -1098
  8. package/{dist/index.mjs → index.mjs} +1596 -1100
  9. package/keyboard-controller.d.mts +148 -0
  10. package/keyboard-controller.d.ts +148 -0
  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/reanimated.js +60 -0
  17. package/reanimated.mjs +53 -0
  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/keyboard-controller.d.mts +0 -261
  32. package/dist/keyboard-controller.d.ts +0 -261
  33. package/dist/package.json +0 -35
  34. package/dist/reanimated.js +0 -58
  35. package/dist/reanimated.mjs +0 -51
  36. package/example/README.md +0 -40
  37. package/example/api/data/genres.json +0 -23
  38. package/example/api/data/playlist/10402-10749.json +0 -1
  39. package/example/api/data/playlist/10402-10770.json +0 -1
  40. package/example/api/data/playlist/10402-37.json +0 -1
  41. package/example/api/data/playlist/10749-10752.json +0 -1
  42. package/example/api/data/playlist/10749-10770.json +0 -1
  43. package/example/api/data/playlist/10749-37.json +0 -1
  44. package/example/api/data/playlist/10749-878.json +0 -1
  45. package/example/api/data/playlist/10751-10402.json +0 -1
  46. package/example/api/data/playlist/10751-10752.json +0 -1
  47. package/example/api/data/playlist/10751-37.json +0 -1
  48. package/example/api/data/playlist/10751-53.json +0 -1
  49. package/example/api/data/playlist/10751-878.json +0 -1
  50. package/example/api/data/playlist/10751-9648.json +0 -1
  51. package/example/api/data/playlist/10752-37.json +0 -1
  52. package/example/api/data/playlist/12-10402.json +0 -1
  53. package/example/api/data/playlist/12-10749.json +0 -1
  54. package/example/api/data/playlist/12-18.json +0 -1
  55. package/example/api/data/playlist/12-27.json +0 -1
  56. package/example/api/data/playlist/12-35.json +0 -1
  57. package/example/api/data/playlist/14-36.json +0 -1
  58. package/example/api/data/playlist/14-878.json +0 -1
  59. package/example/api/data/playlist/16-10751.json +0 -1
  60. package/example/api/data/playlist/16-10770.json +0 -1
  61. package/example/api/data/playlist/16-35.json +0 -1
  62. package/example/api/data/playlist/16-36.json +0 -1
  63. package/example/api/data/playlist/16-53.json +0 -1
  64. package/example/api/data/playlist/18-10751.json +0 -1
  65. package/example/api/data/playlist/18-10752.json +0 -1
  66. package/example/api/data/playlist/18-37.json +0 -1
  67. package/example/api/data/playlist/18-53.json +0 -1
  68. package/example/api/data/playlist/18-878.json +0 -1
  69. package/example/api/data/playlist/27-10749.json +0 -1
  70. package/example/api/data/playlist/27-10770.json +0 -1
  71. package/example/api/data/playlist/28-10749.json +0 -1
  72. package/example/api/data/playlist/28-10751.json +0 -1
  73. package/example/api/data/playlist/28-10770.json +0 -1
  74. package/example/api/data/playlist/28-16.json +0 -1
  75. package/example/api/data/playlist/28-18.json +0 -1
  76. package/example/api/data/playlist/28-36.json +0 -1
  77. package/example/api/data/playlist/28-37.json +0 -1
  78. package/example/api/data/playlist/28-53.json +0 -1
  79. package/example/api/data/playlist/28-80.json +0 -1
  80. package/example/api/data/playlist/28-99.json +0 -1
  81. package/example/api/data/playlist/35-10749.json +0 -1
  82. package/example/api/data/playlist/35-10751.json +0 -1
  83. package/example/api/data/playlist/35-10752.json +0 -1
  84. package/example/api/data/playlist/35-27.json +0 -1
  85. package/example/api/data/playlist/35-36.json +0 -1
  86. package/example/api/data/playlist/35-53.json +0 -1
  87. package/example/api/data/playlist/35-80.json +0 -1
  88. package/example/api/data/playlist/36-37.json +0 -1
  89. package/example/api/data/playlist/36-878.json +0 -1
  90. package/example/api/data/playlist/36-9648.json +0 -1
  91. package/example/api/data/playlist/53-10752.json +0 -1
  92. package/example/api/data/playlist/80-10770.json +0 -1
  93. package/example/api/data/playlist/80-14.json +0 -1
  94. package/example/api/data/playlist/80-18.json +0 -1
  95. package/example/api/data/playlist/80-37.json +0 -1
  96. package/example/api/data/playlist/878-37.json +0 -1
  97. package/example/api/data/playlist/9648-10770.json +0 -1
  98. package/example/api/data/playlist/9648-37.json +0 -1
  99. package/example/api/data/playlist/9648-53.json +0 -1
  100. package/example/api/data/playlist/9648-878.json +0 -1
  101. package/example/api/data/playlist/99-10749.json +0 -1
  102. package/example/api/data/playlist/99-14.json +0 -1
  103. package/example/api/data/playlist/99-18.json +0 -1
  104. package/example/api/data/playlist/99-27.json +0 -1
  105. package/example/api/data/playlist/99-53.json +0 -1
  106. package/example/api/data/playlist/99-9648.json +0 -1
  107. package/example/api/data/playlist/index.ts +0 -73
  108. package/example/api/data/rows.json +0 -1
  109. package/example/api/index.ts +0 -36
  110. package/example/app/(tabs)/_layout.tsx +0 -60
  111. package/example/app/(tabs)/cards.tsx +0 -81
  112. package/example/app/(tabs)/index.tsx +0 -205
  113. package/example/app/(tabs)/moviesL.tsx +0 -7
  114. package/example/app/(tabs)/moviesLR.tsx +0 -7
  115. package/example/app/+not-found.tsx +0 -32
  116. package/example/app/_layout.tsx +0 -34
  117. package/example/app/accurate-scrollto/index.tsx +0 -125
  118. package/example/app/accurate-scrollto-2/index.tsx +0 -52
  119. package/example/app/accurate-scrollto-huge/index.tsx +0 -128
  120. package/example/app/add-to-end/index.tsx +0 -82
  121. package/example/app/ai-chat/index.tsx +0 -236
  122. package/example/app/bidirectional-infinite-list/index.tsx +0 -133
  123. package/example/app/cards-columns/index.tsx +0 -37
  124. package/example/app/cards-flashlist/index.tsx +0 -122
  125. package/example/app/cards-flatlist/index.tsx +0 -94
  126. package/example/app/cards-no-recycle/index.tsx +0 -110
  127. package/example/app/cards-renderItem.tsx +0 -354
  128. package/example/app/chat-example/index.tsx +0 -167
  129. package/example/app/chat-infinite/index.tsx +0 -239
  130. package/example/app/chat-keyboard/index.tsx +0 -248
  131. package/example/app/chat-resize-outer/index.tsx +0 -247
  132. package/example/app/columns/index.tsx +0 -78
  133. package/example/app/countries/index.tsx +0 -182
  134. package/example/app/countries-flashlist/index.tsx +0 -163
  135. package/example/app/countries-reorder/index.tsx +0 -187
  136. package/example/app/extra-data/index.tsx +0 -86
  137. package/example/app/filter-elements/filter-data-provider.tsx +0 -55
  138. package/example/app/filter-elements/index.tsx +0 -118
  139. package/example/app/initial-scroll-index/index.tsx +0 -106
  140. package/example/app/initial-scroll-index/renderFixedItem.tsx +0 -215
  141. package/example/app/initial-scroll-index-free-height/index.tsx +0 -70
  142. package/example/app/initial-scroll-index-keyed/index.tsx +0 -62
  143. package/example/app/lazy-list/index.tsx +0 -123
  144. package/example/app/movies-flashlist/index.tsx +0 -7
  145. package/example/app/mutable-cells/index.tsx +0 -104
  146. package/example/app/video-feed/index.tsx +0 -119
  147. package/example/app.config.js +0 -22
  148. package/example/app.json +0 -45
  149. package/example/assets/fonts/SpaceMono-Regular.ttf +0 -0
  150. package/example/assets/images/adaptive-icon.png +0 -0
  151. package/example/assets/images/favicon.png +0 -0
  152. package/example/assets/images/icon.png +0 -0
  153. package/example/assets/images/partial-react-logo.png +0 -0
  154. package/example/assets/images/react-logo.png +0 -0
  155. package/example/assets/images/react-logo@2x.png +0 -0
  156. package/example/assets/images/react-logo@3x.png +0 -0
  157. package/example/assets/images/splash-icon.png +0 -0
  158. package/example/autoscroll.sh +0 -101
  159. package/example/bun.lock +0 -2266
  160. package/example/bunfig.toml +0 -2
  161. package/example/components/Breathe.tsx +0 -54
  162. package/example/components/Circle.tsx +0 -69
  163. package/example/components/Collapsible.tsx +0 -44
  164. package/example/components/ExternalLink.tsx +0 -24
  165. package/example/components/HapticTab.tsx +0 -18
  166. package/example/components/HelloWave.tsx +0 -37
  167. package/example/components/Movies.tsx +0 -179
  168. package/example/components/ParallaxScrollView.tsx +0 -81
  169. package/example/components/ThemedText.tsx +0 -60
  170. package/example/components/ThemedView.tsx +0 -14
  171. package/example/components/__tests__/ThemedText-test.tsx +0 -10
  172. package/example/components/__tests__/__snapshots__/ThemedText-test.tsx.snap +0 -24
  173. package/example/components/ui/IconSymbol.ios.tsx +0 -32
  174. package/example/components/ui/IconSymbol.tsx +0 -43
  175. package/example/components/ui/TabBarBackground.ios.tsx +0 -22
  176. package/example/components/ui/TabBarBackground.tsx +0 -6
  177. package/example/constants/Colors.ts +0 -26
  178. package/example/constants/constants.ts +0 -5
  179. package/example/constants/useScrollTest.ts +0 -19
  180. package/example/hooks/useColorScheme.ts +0 -1
  181. package/example/hooks/useColorScheme.web.ts +0 -8
  182. package/example/hooks/useThemeColor.ts +0 -22
  183. package/example/ios/.xcode.env +0 -11
  184. package/example/ios/Podfile +0 -64
  185. package/example/ios/Podfile.lock +0 -2767
  186. package/example/ios/Podfile.properties.json +0 -5
  187. package/example/ios/listtest/AppDelegate.swift +0 -70
  188. package/example/ios/listtest/Images.xcassets/AppIcon.appiconset/App-Icon-1024x1024@1x.png +0 -0
  189. package/example/ios/listtest/Images.xcassets/AppIcon.appiconset/Contents.json +0 -14
  190. package/example/ios/listtest/Images.xcassets/Contents.json +0 -6
  191. package/example/ios/listtest/Images.xcassets/SplashScreenBackground.colorset/Contents.json +0 -20
  192. package/example/ios/listtest/Images.xcassets/SplashScreenLogo.imageset/Contents.json +0 -23
  193. package/example/ios/listtest/Images.xcassets/SplashScreenLogo.imageset/image.png +0 -0
  194. package/example/ios/listtest/Images.xcassets/SplashScreenLogo.imageset/image@2x.png +0 -0
  195. package/example/ios/listtest/Images.xcassets/SplashScreenLogo.imageset/image@3x.png +0 -0
  196. package/example/ios/listtest/Info.plist +0 -85
  197. package/example/ios/listtest/PrivacyInfo.xcprivacy +0 -48
  198. package/example/ios/listtest/SplashScreen.storyboard +0 -42
  199. package/example/ios/listtest/Supporting/Expo.plist +0 -12
  200. package/example/ios/listtest/listtest-Bridging-Header.h +0 -3
  201. package/example/ios/listtest/listtest.entitlements +0 -5
  202. package/example/ios/listtest.xcodeproj/project.pbxproj +0 -547
  203. package/example/ios/listtest.xcodeproj/xcshareddata/xcschemes/listtest.xcscheme +0 -88
  204. package/example/ios/listtest.xcworkspace/contents.xcworkspacedata +0 -10
  205. package/example/metro.config.js +0 -16
  206. package/example/package.json +0 -73
  207. package/example/scripts/reset-project.js +0 -84
  208. package/example/tsconfig.json +0 -26
  209. package/posttsup.ts +0 -24
  210. package/src/Container.tsx +0 -176
  211. package/src/Containers.tsx +0 -85
  212. package/src/ContextContainer.ts +0 -145
  213. package/src/DebugView.tsx +0 -83
  214. package/src/LazyLegendList.tsx +0 -41
  215. package/src/LeanView.tsx +0 -18
  216. package/src/LegendList.tsx +0 -558
  217. package/src/ListComponent.tsx +0 -191
  218. package/src/ScrollAdjust.tsx +0 -24
  219. package/src/ScrollAdjustHandler.ts +0 -26
  220. package/src/Separator.tsx +0 -14
  221. package/src/animated.tsx +0 -6
  222. package/src/calculateItemsInView.ts +0 -363
  223. package/src/calculateOffsetForIndex.ts +0 -23
  224. package/src/calculateOffsetWithOffsetPosition.ts +0 -26
  225. package/src/checkAllSizesKnown.ts +0 -17
  226. package/src/checkAtBottom.ts +0 -36
  227. package/src/checkAtTop.ts +0 -27
  228. package/src/checkThreshold.ts +0 -30
  229. package/src/constants.ts +0 -11
  230. package/src/createColumnWrapperStyle.ts +0 -16
  231. package/src/doInitialAllocateContainers.ts +0 -40
  232. package/src/doMaintainScrollAtEnd.ts +0 -34
  233. package/src/findAvailableContainers.ts +0 -98
  234. package/src/finishScrollTo.ts +0 -8
  235. package/src/getId.ts +0 -21
  236. package/src/getItemSize.ts +0 -52
  237. package/src/getRenderedItem.ts +0 -34
  238. package/src/getScrollVelocity.ts +0 -47
  239. package/src/handleLayout.ts +0 -70
  240. package/src/helpers.ts +0 -39
  241. package/src/index.ts +0 -11
  242. package/src/keyboard-controller.tsx +0 -63
  243. package/src/onScroll.ts +0 -66
  244. package/src/prepareMVCP.ts +0 -50
  245. package/src/reanimated.tsx +0 -63
  246. package/src/requestAdjust.ts +0 -41
  247. package/src/scrollTo.ts +0 -40
  248. package/src/scrollToIndex.ts +0 -34
  249. package/src/setDidLayout.ts +0 -25
  250. package/src/setPaddingTop.ts +0 -28
  251. package/src/state.tsx +0 -304
  252. package/src/types.ts +0 -610
  253. package/src/updateAlignItemsPaddingTop.ts +0 -18
  254. package/src/updateAllPositions.ts +0 -130
  255. package/src/updateItemSize.ts +0 -203
  256. package/src/updateTotalSize.ts +0 -44
  257. package/src/useAnimatedValue.ts +0 -6
  258. package/src/useCombinedRef.ts +0 -22
  259. package/src/useInit.ts +0 -17
  260. package/src/useSyncLayout.tsx +0 -68
  261. package/src/useValue$.ts +0 -53
  262. package/src/viewability.ts +0 -279
  263. package/tsconfig.json +0 -59
  264. package/tsup.config.ts +0 -21
@@ -1,239 +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 { RefreshControl } from "react-native-gesture-handler";
6
- import { SafeAreaView, useSafeAreaInsets } from "react-native-safe-area-context";
7
-
8
- type MessageSide = "user" | "bot";
9
- type Message = {
10
- id: string;
11
- text: string;
12
- sender: MessageSide;
13
- timeStamp: number;
14
- };
15
-
16
- let idCounter = 0;
17
- const MS_PER_SECOND = 1000;
18
-
19
- const defaultChatMessages: Message[] = [
20
- {
21
- id: String(idCounter++),
22
- text: "Hi, I have a question",
23
- sender: "user",
24
- timeStamp: Date.now() - MS_PER_SECOND * 5,
25
- },
26
- { id: String(idCounter++), text: "Are we there yet1?", sender: "bot", timeStamp: Date.now() - MS_PER_SECOND * 4 },
27
- { id: String(idCounter++), text: "Are we there yet2?", sender: "bot", timeStamp: Date.now() - MS_PER_SECOND * 4 },
28
- { id: String(idCounter++), text: "Are we there yet3?", sender: "bot", timeStamp: Date.now() - MS_PER_SECOND * 4 },
29
- { id: String(idCounter++), text: "Are we there yet4?", sender: "bot", timeStamp: Date.now() - MS_PER_SECOND * 4 },
30
- { id: String(idCounter++), text: "Are we there yet5?", sender: "bot", timeStamp: Date.now() - MS_PER_SECOND * 4 },
31
- { id: String(idCounter++), text: "Are we there yet6?", sender: "bot", timeStamp: Date.now() - MS_PER_SECOND * 4 },
32
- { id: String(idCounter++), text: "Are we there yet7?", sender: "bot", timeStamp: Date.now() - MS_PER_SECOND * 4 },
33
- { id: String(idCounter++), text: "Are we there yet8?", sender: "bot", timeStamp: Date.now() - MS_PER_SECOND * 4 },
34
- { id: String(idCounter++), text: "Are we there yet9?", sender: "bot", timeStamp: Date.now() - MS_PER_SECOND * 4 },
35
- { id: String(idCounter++), text: "Are we there yet10?", sender: "bot", timeStamp: Date.now() - MS_PER_SECOND * 4 },
36
- { id: String(idCounter++), text: "Are we there yet11?", sender: "bot", timeStamp: Date.now() - MS_PER_SECOND * 4 },
37
- { id: String(idCounter++), text: "Are we there yet12?", sender: "bot", timeStamp: Date.now() - MS_PER_SECOND * 4 },
38
- { id: String(idCounter++), text: "Are we there yet13?", sender: "bot", timeStamp: Date.now() - MS_PER_SECOND * 4 },
39
- { id: String(idCounter++), text: "Are we there yet14?", sender: "bot", timeStamp: Date.now() - MS_PER_SECOND * 4 },
40
- { id: String(idCounter++), text: "Are we there yet15?", sender: "bot", timeStamp: Date.now() - MS_PER_SECOND * 4 },
41
- { id: String(idCounter++), text: "Are we there yet16?", sender: "bot", timeStamp: Date.now() - MS_PER_SECOND * 4 },
42
- { id: String(idCounter++), text: "Are we there yet17?", sender: "bot", timeStamp: Date.now() - MS_PER_SECOND * 4 },
43
- { id: String(idCounter++), text: "Are we there yet18?", sender: "bot", timeStamp: Date.now() - MS_PER_SECOND * 4 },
44
- {
45
- id: String(idCounter++),
46
- text: "LAST MESSAGE: How can I help you?",
47
- sender: "bot",
48
- timeStamp: Date.now() - MS_PER_SECOND * 3,
49
- },
50
- ];
51
-
52
- const ChatExample = () => {
53
- const [messages, setMessages] = useState<Message[]>(defaultChatMessages);
54
- const [inputText, setInputText] = useState("");
55
- const headerHeight = Platform.OS === "ios" ? useHeaderHeight() : 0;
56
-
57
- const sendMessage = () => {
58
- const text = inputText || "Empty message";
59
- if (text.trim()) {
60
- setMessages((messages) => [
61
- ...messages,
62
- { id: String(idCounter++), text: text, sender: "user", timeStamp: Date.now() },
63
- ]);
64
- setInputText("");
65
- setTimeout(() => {
66
- setMessages((messages) => [
67
- ...messages,
68
- {
69
- id: String(idCounter++),
70
- text: `Answer: ${text.toUpperCase()}`,
71
- sender: "bot",
72
- timeStamp: Date.now(),
73
- },
74
- ]);
75
- }, 300);
76
- }
77
- };
78
-
79
- const [refreshing, setRefreshing] = useState(false);
80
- const onRefresh = () => {
81
- console.log("onRefresh");
82
- setRefreshing(true);
83
- setTimeout(() => {
84
- setMessages((prevData) => {
85
- const initialIndex = Number.parseInt(prevData[0].id);
86
- const newData = [
87
- ...Array.from({ length: 5 }, (_, i) => ({
88
- id: (initialIndex - i - 1).toString(),
89
- text: `Previous message${(initialIndex - i - 1).toString()}`,
90
- sender: "user" as MessageSide,
91
- timeStamp: Date.now() - MS_PER_SECOND * 5,
92
- })).reverse(),
93
- ...prevData,
94
- ];
95
- return newData;
96
- });
97
- setRefreshing(false);
98
- }, 500);
99
- };
100
-
101
- // useEffect(() => {
102
- // setInterval(() => {
103
- // setMessages((prevData) => {
104
- // const initialIndex = Number.parseInt(prevData[0].id);
105
- // const newData = [
106
- // ...Array.from({ length: 1 }, (_, i) => ({
107
- // id: (initialIndex - i - 1).toString(),
108
- // text: `Previous message${(initialIndex - i - 1).toString()}`,
109
- // sender: "user" as MessageSide,
110
- // timeStamp: Date.now() - MS_PER_SECOND * 5,
111
- // })).reverse(),
112
- // ...prevData,
113
- // ];
114
- // return newData;
115
- // });
116
- // setRefreshing(false);
117
- // }, 500);
118
- // }, []);
119
-
120
- const { top } = useSafeAreaInsets();
121
-
122
- return (
123
- <SafeAreaView style={styles.container} edges={["bottom"]}>
124
- <KeyboardAvoidingView style={styles.container} behavior="padding" keyboardVerticalOffset={headerHeight}>
125
- <LegendList
126
- data={messages}
127
- contentContainerStyle={styles.contentContainer}
128
- keyExtractor={(item) => item.id}
129
- estimatedItemSize={80}
130
- maintainScrollAtEnd
131
- maintainVisibleContentPosition
132
- initialScrollIndex={messages.length - 1}
133
- alignItemsAtEnd
134
- recycleItems={true}
135
- ListHeaderComponent={<View style={{ height: top }} />}
136
- refreshControl={
137
- <RefreshControl
138
- refreshing={refreshing}
139
- onRefresh={onRefresh}
140
- tintColor={"#000000"}
141
- progressViewOffset={40}
142
- />
143
- }
144
- renderItem={({ item }) => (
145
- <View>
146
- <View
147
- style={[
148
- styles.messageContainer,
149
- item.sender === "bot" ? styles.botMessageContainer : styles.userMessageContainer,
150
- item.sender === "bot" ? styles.botStyle : styles.userStyle,
151
- ]}
152
- >
153
- <Text style={[styles.messageText, item.sender === "user" && styles.userMessageText]}>
154
- {item.text}
155
- </Text>
156
- </View>
157
- <View
158
- style={[styles.timeStamp, item.sender === "bot" ? styles.botStyle : styles.userStyle]}
159
- >
160
- <Text style={styles.timeStampText}>
161
- {new Date(item.timeStamp).toLocaleTimeString()}
162
- </Text>
163
- </View>
164
- </View>
165
- )}
166
- />
167
- <View style={styles.inputContainer}>
168
- <TextInput
169
- style={styles.input}
170
- value={inputText}
171
- onChangeText={setInputText}
172
- placeholder="Type a message"
173
- />
174
- <Button title="Send" onPress={sendMessage} />
175
- </View>
176
- </KeyboardAvoidingView>
177
- </SafeAreaView>
178
- );
179
- };
180
-
181
- const styles = StyleSheet.create({
182
- container: {
183
- flex: 1,
184
- backgroundColor: "#fff",
185
- },
186
- contentContainer: {
187
- paddingHorizontal: 16,
188
- },
189
- messageContainer: {
190
- padding: 16,
191
- borderRadius: 16,
192
- marginVertical: 4,
193
- },
194
- messageText: {
195
- fontSize: 16,
196
- },
197
- userMessageText: {
198
- color: "white",
199
- },
200
- inputContainer: {
201
- flexDirection: "row",
202
- alignItems: "center",
203
- padding: 10,
204
- borderTopWidth: 1,
205
- borderColor: "#ccc",
206
- },
207
- botMessageContainer: {
208
- backgroundColor: "#f1f1f1",
209
- },
210
- userMessageContainer: {
211
- backgroundColor: "#007AFF",
212
- },
213
- botStyle: {
214
- maxWidth: "75%",
215
- alignSelf: "flex-start",
216
- },
217
- userStyle: {
218
- maxWidth: "75%",
219
- alignSelf: "flex-end",
220
- alignItems: "flex-end",
221
- },
222
- input: {
223
- flex: 1,
224
- borderWidth: 1,
225
- borderColor: "#ccc",
226
- borderRadius: 5,
227
- padding: 10,
228
- marginRight: 10,
229
- },
230
- timeStamp: {
231
- marginVertical: 5,
232
- },
233
- timeStampText: {
234
- fontSize: 12,
235
- color: "#888",
236
- },
237
- });
238
-
239
- export default ChatExample;
@@ -1,248 +0,0 @@
1
- import { LegendList } from "@legendapp/list/keyboard-controller";
2
- import { AnimatedLegendList } from "@legendapp/list/reanimated";
3
- import { useHeaderHeight } from "@react-navigation/elements";
4
- import { useState } from "react";
5
- import { Button, Platform, StyleSheet, Text, TextInput, View } from "react-native";
6
- import { KeyboardAvoidingView, KeyboardProvider } from "react-native-keyboard-controller";
7
-
8
- type Message = {
9
- id: string;
10
- text: string;
11
- sender: "user" | "bot";
12
- timeStamp: number;
13
- };
14
-
15
- let idCounter = 0;
16
- const MS_PER_SECOND = 1000;
17
-
18
- const defaultChatMessages: Message[] = [
19
- {
20
- id: String(idCounter++),
21
- text: "Hi, I have a question about your product",
22
- sender: "user",
23
- timeStamp: Date.now() - MS_PER_SECOND * 5,
24
- },
25
- {
26
- id: String(idCounter++),
27
- text: "Hello there! How can I assist you today?",
28
- sender: "bot",
29
- timeStamp: Date.now() - MS_PER_SECOND * 4,
30
- },
31
- {
32
- id: String(idCounter++),
33
- text: "I'm looking for information about pricing plans",
34
- sender: "user",
35
- timeStamp: Date.now() - MS_PER_SECOND * 4,
36
- },
37
- {
38
- id: String(idCounter++),
39
- text: "We offer several pricing tiers based on your needs",
40
- sender: "bot",
41
- timeStamp: Date.now() - MS_PER_SECOND * 4,
42
- },
43
- {
44
- id: String(idCounter++),
45
- text: "Our basic plan starts at $9.99 per month",
46
- sender: "bot",
47
- timeStamp: Date.now() - MS_PER_SECOND * 4,
48
- },
49
- {
50
- id: String(idCounter++),
51
- text: "Do you offer any discounts for annual billing?",
52
- sender: "user",
53
- timeStamp: Date.now() - MS_PER_SECOND * 4,
54
- },
55
- {
56
- id: String(idCounter++),
57
- text: "Yes! You can save 20% with our annual billing option",
58
- sender: "bot",
59
- timeStamp: Date.now() - MS_PER_SECOND * 4,
60
- },
61
- {
62
- id: String(idCounter++),
63
- text: "That sounds great. What features are included?",
64
- sender: "user",
65
- timeStamp: Date.now() - MS_PER_SECOND * 4,
66
- },
67
- {
68
- id: String(idCounter++),
69
- text: "The basic plan includes all core features plus 10GB storage",
70
- sender: "bot",
71
- timeStamp: Date.now() - MS_PER_SECOND * 4,
72
- },
73
- {
74
- id: String(idCounter++),
75
- text: "Premium plans include priority support and additional tools",
76
- sender: "bot",
77
- timeStamp: Date.now() - MS_PER_SECOND * 4,
78
- },
79
- {
80
- id: String(idCounter++),
81
- text: "I think the basic plan would work for my needs",
82
- sender: "user",
83
- timeStamp: Date.now() - MS_PER_SECOND * 4,
84
- },
85
- {
86
- id: String(idCounter++),
87
- text: "Perfect! I can help you get set up with that",
88
- sender: "bot",
89
- timeStamp: Date.now() - MS_PER_SECOND * 4,
90
- },
91
- {
92
- id: String(idCounter++),
93
- text: "Thanks for your help so far",
94
- sender: "user",
95
- timeStamp: Date.now() - MS_PER_SECOND * 4,
96
- },
97
- {
98
- id: String(idCounter++),
99
- text: "You're welcome! Is there anything else I can assist with today?",
100
- sender: "bot",
101
- timeStamp: Date.now() - MS_PER_SECOND * 3,
102
- },
103
- ];
104
-
105
- const ChatExample = () => {
106
- const [messages, setMessages] = useState<Message[]>(defaultChatMessages);
107
- const [inputText, setInputText] = useState("");
108
- const headerHeight = Platform.OS === "ios" ? useHeaderHeight() : 56;
109
-
110
- const sendMessage = () => {
111
- const text = inputText || "Empty message";
112
- if (text.trim()) {
113
- setMessages((messages) => [
114
- ...messages,
115
- { id: String(idCounter++), text: text, sender: "user", timeStamp: Date.now() },
116
- ]);
117
- setInputText("");
118
- setTimeout(() => {
119
- setMessages((messages) => [
120
- ...messages,
121
- {
122
- id: String(idCounter++),
123
- text: `Answer: ${text.toUpperCase()}`,
124
- sender: "bot",
125
- timeStamp: Date.now(),
126
- },
127
- ]);
128
- }, 300);
129
- }
130
- };
131
-
132
- // Note: There's something weird with the SafeAreaView interacting with the KeyboardAvoidingView here I think,
133
- // so there's some weird margins going on...
134
-
135
- return (
136
- <KeyboardProvider>
137
- <KeyboardAvoidingView
138
- style={styles.container}
139
- behavior="position"
140
- contentContainerStyle={{ flex: 1 }}
141
- keyboardVerticalOffset={headerHeight}
142
- >
143
- <LegendList
144
- data={messages}
145
- contentContainerStyle={styles.contentContainer}
146
- keyExtractor={(item) => item.id}
147
- estimatedItemSize={80}
148
- LegendList={AnimatedLegendList}
149
- maintainScrollAtEnd
150
- alignItemsAtEnd
151
- initialScrollIndex={messages.length - 1}
152
- maintainVisibleContentPosition
153
- renderItem={({ item }) => (
154
- <>
155
- <View
156
- style={[
157
- styles.messageContainer,
158
- item.sender === "bot" ? styles.botMessageContainer : styles.userMessageContainer,
159
- item.sender === "bot" ? styles.botStyle : styles.userStyle,
160
- ]}
161
- >
162
- <Text style={[styles.messageText, item.sender === "user" && styles.userMessageText]}>
163
- {item.text}
164
- </Text>
165
- </View>
166
- <View
167
- style={[styles.timeStamp, item.sender === "bot" ? styles.botStyle : styles.userStyle]}
168
- >
169
- <Text style={styles.timeStampText}>
170
- {new Date(item.timeStamp).toLocaleTimeString()}
171
- </Text>
172
- </View>
173
- </>
174
- )}
175
- />
176
- <View style={styles.inputContainer}>
177
- <TextInput
178
- style={styles.input}
179
- value={inputText}
180
- onChangeText={setInputText}
181
- placeholder="Type a message"
182
- />
183
- <Button title="Send" onPress={sendMessage} />
184
- </View>
185
- </KeyboardAvoidingView>
186
- </KeyboardProvider>
187
- );
188
- };
189
-
190
- const styles = StyleSheet.create({
191
- container: {
192
- flex: 1,
193
- backgroundColor: "#fff",
194
- },
195
- contentContainer: {
196
- paddingHorizontal: 16,
197
- },
198
- messageContainer: {
199
- padding: 16,
200
- borderRadius: 16,
201
- marginVertical: 4,
202
- },
203
- messageText: {
204
- fontSize: 16,
205
- },
206
- userMessageText: {
207
- color: "white",
208
- },
209
- inputContainer: {
210
- flexDirection: "row",
211
- alignItems: "center",
212
- padding: 10,
213
- borderTopWidth: 1,
214
- borderColor: "#ccc",
215
- },
216
- botMessageContainer: {
217
- backgroundColor: "#f1f1f1",
218
- },
219
- userMessageContainer: {
220
- backgroundColor: "#007AFF",
221
- },
222
- botStyle: {
223
- maxWidth: "75%",
224
- alignSelf: "flex-start",
225
- },
226
- userStyle: {
227
- maxWidth: "75%",
228
- alignSelf: "flex-end",
229
- alignItems: "flex-end",
230
- },
231
- input: {
232
- flex: 1,
233
- borderWidth: 1,
234
- borderColor: "#ccc",
235
- borderRadius: 5,
236
- padding: 10,
237
- marginRight: 10,
238
- },
239
- timeStamp: {
240
- marginVertical: 5,
241
- },
242
- timeStampText: {
243
- fontSize: 12,
244
- color: "#888",
245
- },
246
- });
247
-
248
- export default ChatExample;