@sujeetdotkumar/react-native-gifted-chat-performant 1.0.0

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 (231) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +868 -0
  3. package/lib/Actions.d.ts +16 -0
  4. package/lib/Actions.d.ts.map +1 -0
  5. package/lib/Actions.js +65 -0
  6. package/lib/Actions.js.map +1 -0
  7. package/lib/Avatar.d.ts +19 -0
  8. package/lib/Avatar.d.ts.map +1 -0
  9. package/lib/Avatar.js +93 -0
  10. package/lib/Avatar.js.map +1 -0
  11. package/lib/Bubble/index.d.ts +6 -0
  12. package/lib/Bubble/index.d.ts.map +1 -0
  13. package/lib/Bubble/index.js +269 -0
  14. package/lib/Bubble/index.js.map +1 -0
  15. package/lib/Bubble/styles.d.ts +57 -0
  16. package/lib/Bubble/styles.d.ts.map +1 -0
  17. package/lib/Bubble/styles.js +59 -0
  18. package/lib/Bubble/styles.js.map +1 -0
  19. package/lib/Bubble/types.d.ts +59 -0
  20. package/lib/Bubble/types.d.ts.map +1 -0
  21. package/lib/Bubble/types.js +2 -0
  22. package/lib/Bubble/types.js.map +1 -0
  23. package/lib/Color.d.ts +18 -0
  24. package/lib/Color.d.ts.map +1 -0
  25. package/lib/Color.js +18 -0
  26. package/lib/Color.js.map +1 -0
  27. package/lib/Composer.d.ts +9 -0
  28. package/lib/Composer.d.ts.map +1 -0
  29. package/lib/Composer.js +56 -0
  30. package/lib/Composer.js.map +1 -0
  31. package/lib/Constant.d.ts +6 -0
  32. package/lib/Constant.d.ts.map +1 -0
  33. package/lib/Constant.js +6 -0
  34. package/lib/Constant.js.map +1 -0
  35. package/lib/Day/index.d.ts +5 -0
  36. package/lib/Day/index.d.ts.map +1 -0
  37. package/lib/Day/index.js +37 -0
  38. package/lib/Day/index.js.map +1 -0
  39. package/lib/Day/styles.d.ts +21 -0
  40. package/lib/Day/styles.d.ts.map +1 -0
  41. package/lib/Day/styles.js +22 -0
  42. package/lib/Day/styles.js.map +1 -0
  43. package/lib/Day/types.d.ts +11 -0
  44. package/lib/Day/types.d.ts.map +1 -0
  45. package/lib/Day/types.js +2 -0
  46. package/lib/Day/types.js.map +1 -0
  47. package/lib/GiftedAvatar.d.ts +12 -0
  48. package/lib/GiftedAvatar.d.ts.map +1 -0
  49. package/lib/GiftedAvatar.js +101 -0
  50. package/lib/GiftedAvatar.js.map +1 -0
  51. package/lib/GiftedChat/index.d.ts +10 -0
  52. package/lib/GiftedChat/index.d.ts.map +1 -0
  53. package/lib/GiftedChat/index.js +215 -0
  54. package/lib/GiftedChat/index.js.map +1 -0
  55. package/lib/GiftedChat/styles.d.ts +13 -0
  56. package/lib/GiftedChat/styles.d.ts.map +1 -0
  57. package/lib/GiftedChat/styles.js +13 -0
  58. package/lib/GiftedChat/styles.js.map +1 -0
  59. package/lib/GiftedChat/types.d.ts +89 -0
  60. package/lib/GiftedChat/types.d.ts.map +1 -0
  61. package/lib/GiftedChat/types.js +2 -0
  62. package/lib/GiftedChat/types.js.map +1 -0
  63. package/lib/GiftedChatContext.d.ts +11 -0
  64. package/lib/GiftedChatContext.d.ts.map +1 -0
  65. package/lib/GiftedChatContext.js +10 -0
  66. package/lib/GiftedChatContext.js.map +1 -0
  67. package/lib/InputToolbar.d.ts +36 -0
  68. package/lib/InputToolbar.d.ts.map +1 -0
  69. package/lib/InputToolbar.js +108 -0
  70. package/lib/InputToolbar.js.map +1 -0
  71. package/lib/LoadEarlierMessages.d.ts +17 -0
  72. package/lib/LoadEarlierMessages.d.ts.map +1 -0
  73. package/lib/LoadEarlierMessages.js +45 -0
  74. package/lib/LoadEarlierMessages.js.map +1 -0
  75. package/lib/Message/index.d.ts +6 -0
  76. package/lib/Message/index.d.ts.map +1 -0
  77. package/lib/Message/index.js +180 -0
  78. package/lib/Message/index.js.map +1 -0
  79. package/lib/Message/styles.d.ts +18 -0
  80. package/lib/Message/styles.d.ts.map +1 -0
  81. package/lib/Message/styles.js +18 -0
  82. package/lib/Message/styles.js.map +1 -0
  83. package/lib/Message/types.d.ts +25 -0
  84. package/lib/Message/types.d.ts.map +1 -0
  85. package/lib/Message/types.js +2 -0
  86. package/lib/Message/types.js.map +1 -0
  87. package/lib/MessageAudio.d.ts +3 -0
  88. package/lib/MessageAudio.d.ts.map +1 -0
  89. package/lib/MessageAudio.js +25 -0
  90. package/lib/MessageAudio.js.map +1 -0
  91. package/lib/MessageImage.d.ts +12 -0
  92. package/lib/MessageImage.d.ts.map +1 -0
  93. package/lib/MessageImage.js +164 -0
  94. package/lib/MessageImage.js.map +1 -0
  95. package/lib/MessageReply.d.ts +15 -0
  96. package/lib/MessageReply.d.ts.map +1 -0
  97. package/lib/MessageReply.js +103 -0
  98. package/lib/MessageReply.js.map +1 -0
  99. package/lib/MessageText.d.ts +24 -0
  100. package/lib/MessageText.d.ts.map +1 -0
  101. package/lib/MessageText.js +41 -0
  102. package/lib/MessageText.js.map +1 -0
  103. package/lib/MessageVideo.d.ts +3 -0
  104. package/lib/MessageVideo.d.ts.map +1 -0
  105. package/lib/MessageVideo.js +25 -0
  106. package/lib/MessageVideo.js.map +1 -0
  107. package/lib/MessagesContainer/components/DayAnimated/index.d.ts +5 -0
  108. package/lib/MessagesContainer/components/DayAnimated/index.d.ts.map +1 -0
  109. package/lib/MessagesContainer/components/DayAnimated/index.js +44 -0
  110. package/lib/MessagesContainer/components/DayAnimated/index.js.map +1 -0
  111. package/lib/MessagesContainer/components/DayAnimated/styles.d.ts +12 -0
  112. package/lib/MessagesContainer/components/DayAnimated/styles.d.ts.map +1 -0
  113. package/lib/MessagesContainer/components/DayAnimated/styles.js +12 -0
  114. package/lib/MessagesContainer/components/DayAnimated/styles.js.map +1 -0
  115. package/lib/MessagesContainer/components/DayAnimated/types.d.ts +9 -0
  116. package/lib/MessagesContainer/components/DayAnimated/types.d.ts.map +1 -0
  117. package/lib/MessagesContainer/components/DayAnimated/types.js +2 -0
  118. package/lib/MessagesContainer/components/DayAnimated/types.js.map +1 -0
  119. package/lib/MessagesContainer/components/Item/index.d.ts +6 -0
  120. package/lib/MessagesContainer/components/Item/index.d.ts.map +1 -0
  121. package/lib/MessagesContainer/components/Item/index.js +25 -0
  122. package/lib/MessagesContainer/components/Item/index.js.map +1 -0
  123. package/lib/MessagesContainer/components/Item/types.d.ts +10 -0
  124. package/lib/MessagesContainer/components/Item/types.d.ts.map +1 -0
  125. package/lib/MessagesContainer/components/Item/types.js +2 -0
  126. package/lib/MessagesContainer/components/Item/types.js.map +1 -0
  127. package/lib/MessagesContainer/index.d.ts +7 -0
  128. package/lib/MessagesContainer/index.d.ts.map +1 -0
  129. package/lib/MessagesContainer/index.js +168 -0
  130. package/lib/MessagesContainer/index.js.map +1 -0
  131. package/lib/MessagesContainer/styles.d.ts +55 -0
  132. package/lib/MessagesContainer/styles.d.ts.map +1 -0
  133. package/lib/MessagesContainer/styles.js +42 -0
  134. package/lib/MessagesContainer/styles.js.map +1 -0
  135. package/lib/MessagesContainer/types.d.ts +72 -0
  136. package/lib/MessagesContainer/types.d.ts.map +1 -0
  137. package/lib/MessagesContainer/types.js +2 -0
  138. package/lib/MessagesContainer/types.js.map +1 -0
  139. package/lib/MessagesContainer/utils.d.ts +20 -0
  140. package/lib/MessagesContainer/utils.d.ts.map +1 -0
  141. package/lib/MessagesContainer/utils.js +28 -0
  142. package/lib/MessagesContainer/utils.js.map +1 -0
  143. package/lib/Models.d.ts +58 -0
  144. package/lib/Models.d.ts.map +1 -0
  145. package/lib/Models.js +2 -0
  146. package/lib/Models.js.map +1 -0
  147. package/lib/QuickReplies.d.ts +16 -0
  148. package/lib/QuickReplies.d.ts.map +1 -0
  149. package/lib/QuickReplies.js +108 -0
  150. package/lib/QuickReplies.js.map +1 -0
  151. package/lib/Reply/index.d.ts +2 -0
  152. package/lib/Reply/index.d.ts.map +1 -0
  153. package/lib/Reply/index.js +2 -0
  154. package/lib/Reply/index.js.map +1 -0
  155. package/lib/Reply/types.d.ts +72 -0
  156. package/lib/Reply/types.d.ts.map +1 -0
  157. package/lib/Reply/types.js +2 -0
  158. package/lib/Reply/types.js.map +1 -0
  159. package/lib/ReplyPreview.d.ts +14 -0
  160. package/lib/ReplyPreview.d.ts.map +1 -0
  161. package/lib/ReplyPreview.js +95 -0
  162. package/lib/ReplyPreview.js.map +1 -0
  163. package/lib/Send.d.ts +19 -0
  164. package/lib/Send.d.ts.map +1 -0
  165. package/lib/Send.js +57 -0
  166. package/lib/Send.js.map +1 -0
  167. package/lib/SystemMessage.d.ts +14 -0
  168. package/lib/SystemMessage.d.ts.map +1 -0
  169. package/lib/SystemMessage.js +42 -0
  170. package/lib/SystemMessage.js.map +1 -0
  171. package/lib/Time.d.ts +13 -0
  172. package/lib/Time.d.ts.map +1 -0
  173. package/lib/Time.js +42 -0
  174. package/lib/Time.js.map +1 -0
  175. package/lib/TypingIndicator/index.d.ts +5 -0
  176. package/lib/TypingIndicator/index.d.ts.map +1 -0
  177. package/lib/TypingIndicator/index.js +94 -0
  178. package/lib/TypingIndicator/index.js.map +1 -0
  179. package/lib/TypingIndicator/styles.d.ts +21 -0
  180. package/lib/TypingIndicator/styles.d.ts.map +1 -0
  181. package/lib/TypingIndicator/styles.js +22 -0
  182. package/lib/TypingIndicator/styles.js.map +1 -0
  183. package/lib/TypingIndicator/types.d.ts +6 -0
  184. package/lib/TypingIndicator/types.d.ts.map +1 -0
  185. package/lib/TypingIndicator/types.js +2 -0
  186. package/lib/TypingIndicator/types.js.map +1 -0
  187. package/lib/components/MessageReply.d.ts +29 -0
  188. package/lib/components/MessageReply.d.ts.map +1 -0
  189. package/lib/components/MessageReply.js +87 -0
  190. package/lib/components/MessageReply.js.map +1 -0
  191. package/lib/components/ReplyPreview.d.ts +17 -0
  192. package/lib/components/ReplyPreview.d.ts.map +1 -0
  193. package/lib/components/ReplyPreview.js +148 -0
  194. package/lib/components/ReplyPreview.js.map +1 -0
  195. package/lib/components/TouchableOpacity.d.ts +9 -0
  196. package/lib/components/TouchableOpacity.d.ts.map +1 -0
  197. package/lib/components/TouchableOpacity.js +37 -0
  198. package/lib/components/TouchableOpacity.js.map +1 -0
  199. package/lib/hooks/useColorScheme.d.ts +8 -0
  200. package/lib/hooks/useColorScheme.d.ts.map +1 -0
  201. package/lib/hooks/useColorScheme.js +17 -0
  202. package/lib/hooks/useColorScheme.js.map +1 -0
  203. package/lib/hooks/useUpdateLayoutEffect.d.ts +9 -0
  204. package/lib/hooks/useUpdateLayoutEffect.d.ts.map +1 -0
  205. package/lib/hooks/useUpdateLayoutEffect.js +17 -0
  206. package/lib/hooks/useUpdateLayoutEffect.js.map +1 -0
  207. package/lib/index.d.ts +31 -0
  208. package/lib/index.d.ts.map +1 -0
  209. package/lib/index.js +31 -0
  210. package/lib/index.js.map +1 -0
  211. package/lib/linkParser.d.ts +39 -0
  212. package/lib/linkParser.d.ts.map +1 -0
  213. package/lib/linkParser.js +154 -0
  214. package/lib/linkParser.js.map +1 -0
  215. package/lib/logging.d.ts +3 -0
  216. package/lib/logging.d.ts.map +1 -0
  217. package/lib/logging.js +5 -0
  218. package/lib/logging.js.map +1 -0
  219. package/lib/styles.d.ts +14 -0
  220. package/lib/styles.d.ts.map +1 -0
  221. package/lib/styles.js +23 -0
  222. package/lib/styles.js.map +1 -0
  223. package/lib/types.d.ts +19 -0
  224. package/lib/types.d.ts.map +1 -0
  225. package/lib/types.js +2 -0
  226. package/lib/types.js.map +1 -0
  227. package/lib/utils.d.ts +8 -0
  228. package/lib/utils.d.ts.map +1 -0
  229. package/lib/utils.js +104 -0
  230. package/lib/utils.js.map +1 -0
  231. package/package.json +114 -0
package/README.md ADDED
@@ -0,0 +1,868 @@
1
+ <p align="center">
2
+ <a href="https://www.npmjs.com/package/react-native-gifted-chat"><img alt="npm version" src="https://badge.fury.io/js/react-native-gifted-chat.svg"/></a>
3
+ <a href="https://www.npmjs.com/package/react-native-gifted-chat"><img alt="npm downloads" src="https://img.shields.io/npm/dm/react-native-gifted-chat.svg"/></a>
4
+ <a href="https://circleci.com/gh/FaridSafi/react-native-gifted-chat"><img src="https://circleci.com/gh/FaridSafi/react-native-gifted-chat.svg?style=shield" alt="build"></a>
5
+ <img src="https://img.shields.io/badge/platforms-iOS%20%7C%20Android%20%7C%20Web-lightgrey.svg" alt="platforms">
6
+ <img src="https://img.shields.io/badge/TypeScript-supported-blue.svg" alt="TypeScript">
7
+ <img src="https://img.shields.io/badge/Expo-compatible-000020.svg" alt="Expo compatible">
8
+ </p>
9
+
10
+ <h1 align="center">React Native Gifted Chat</h1>
11
+
12
+ <p align="center">
13
+ The most complete chat UI for React Native & Web
14
+ </p>
15
+
16
+ <p align="center">
17
+ <a href="https://snack.expo.dev/@kesha-antonov/gifted-chat-playground" target="_blank">
18
+ <img src="https://img.shields.io/badge/â–ļī¸_Try_in_Browser-4630EB?style=for-the-badge&logo=expo&logoColor=white" alt="Try GiftedChat on Expo Snack"/>
19
+ </a>
20
+ </p>
21
+
22
+ ---
23
+
24
+ ## ✨ Features
25
+
26
+ - 🎨 **Fully Customizable** - Override any component with your own implementation
27
+ - 📎 **Composer Actions** - Attach photos, files, or trigger custom actions
28
+ - â†Šī¸ **Reply to Messages** - Swipe-to-reply with reply preview and message threading
29
+ - âŽī¸ **Load Earlier Messages** - Infinite scroll with pagination support
30
+ - 📋 **Copy to Clipboard** - Long-press messages to copy text
31
+ - 🔗 **Smart Link Parsing** - Auto-detect URLs, emails, phone numbers, hashtags, mentions
32
+ - 👤 **Avatars** - User initials or custom avatar images
33
+ - 🌍 **Localized Dates** - Full i18n support via Day.js
34
+ - âŒ¨ī¸ **Keyboard Handling** - Smart keyboard avoidance for all platforms
35
+ - đŸ’Ŧ **System Messages** - Display system notifications in chat
36
+ - ⚡ **Quick Replies** - Bot-style quick reply buttons
37
+ - âœī¸ **Typing Indicator** - Show when users are typing
38
+ - ✅ **Message Status** - Tick indicators for sent/delivered/read states
39
+ - âŦ‡ī¸ **Scroll to Bottom** - Quick navigation button
40
+ - 🌐 **Web Support** - Works with react-native-web
41
+ - 📱 **Expo Support** - Easy integration with Expo projects
42
+ - 📝 **TypeScript** - Complete TypeScript definitions included
43
+
44
+ <p align="center">
45
+ <img width="200" src="https://github.com/user-attachments/assets/c9da88f5-0b20-471c-8cd7-373bdb767517" />
46
+ &nbsp;&nbsp;&nbsp;&nbsp;
47
+ <img width="200" src="https://github.com/user-attachments/assets/f72b17f1-6c2e-43b5-87e7-477011aa3b07" />
48
+ &nbsp;&nbsp;&nbsp;&nbsp;
49
+ <img width="200" src="https://github.com/user-attachments/assets/86711e73-ee3c-4527-b38d-e4dab47a44fe" />
50
+ </p>
51
+
52
+ ---
53
+
54
+ <h3 align="center">Sponsors</h3>
55
+
56
+ <table align="center" border="0" cellspacing="20">
57
+ <tr>
58
+ <td align="center" valign="middle">
59
+ <a href="https://www.lereacteur.io" target="_blank"><img src="https://raw.githubusercontent.com/FaridSafi/react-native-gifted-chat/master/media/logo_sponsor.png" height="50"></a>
60
+ </td>
61
+ <td align="center" valign="middle">
62
+ <a href="https://getstream.io/chat/?utm_source=Github&utm_medium=Github_Repo_Content_Ad&utm_content=Developer&utm_campaign=Github_Jan2022_Chat&utm_term=react-native-gifted-chat" target="_blank"><img src="https://raw.githubusercontent.com/FaridSafi/react-native-gifted-chat/master/media/stream-logo.png" height="35"></a>
63
+ </td>
64
+ <td align="center" valign="middle">
65
+ <a href="https://www.ethora.com" target="_blank"><img src="https://www.dappros.com/wp-content/uploads/2023/12/Ethora-Logo.png" height="50"></a>
66
+ </td>
67
+ </tr>
68
+ </table>
69
+
70
+ <p align="center">
71
+ <a href="https://www.lereacteur.io" target="_blank"><strong>Le Reacteur</strong></a> - Coding Bootcamp in Paris co-founded by Farid Safi
72
+ <br>
73
+ <a href="https://getstream.io/chat/?utm_source=Github&utm_medium=Github_Repo_Content_Ad&utm_content=Developer&utm_campaign=Github_Jan2022_Chat&utm_term=react-native-gifted-chat" target="_blank"><strong>Stream</strong></a> - Scalable chat API/Server written in Go (<a href="https://getstream.io/chat/get_started/?utm_source=Github&utm_medium=Github_Repo_Content_Ad&utm_content=Developer&utm_campaign=Github_Jan2022_Chat&utm_term=react-native-gifted-chat" target="_blank">API Tour</a> | <a href="https://dev.to/nickparsons/react-native-chat-with-chuck-norris-3h7m?utm_source=Github&utm_medium=Github_Repo_Content_Ad&utm_content=Developer&utm_campaign=Github_Jan2022_Chat&utm_term=react-native-gifted-chat" target="_blank">Tutorial</a>)
74
+ <br>
75
+ <a href="https://www.ethora.com" target="_blank"><strong>Ethora</strong></a> - A complete app engine featuring GiftedChat (<a href="https://bit.ly/ethorachat" target="_blank">GitHub</a>)
76
+ <br><br>
77
+ 📚 <a href="https://amzn.to/3ZmTyb2" target="_blank">React Key Concepts (2nd ed.)</a>
78
+ </p>
79
+
80
+ ---
81
+
82
+ ## 📖 Table of Contents
83
+
84
+ - [Features](#-features)
85
+ - [Requirements](#-requirements)
86
+ - [Installation](#-installation)
87
+ - [Usage](#-usage)
88
+ - [Props Reference](#-props-reference)
89
+ - [Data Structure](#-data-structure)
90
+ - [Platform Notes](#-platform-notes)
91
+ - [Example App](#-example-app)
92
+ - [Troubleshooting](#-troubleshooting)
93
+ - [Contributing](#-contributing)
94
+ - [Authors](#-authors)
95
+ - [License](#-license)
96
+
97
+ ---
98
+
99
+ ## 📋 Requirements
100
+
101
+ | Requirement | Version |
102
+ |-------------|---------|
103
+ | React Native | >= 0.70.0 |
104
+ | iOS | >= 13.4 |
105
+ | Android | API 21+ (Android 5.0) |
106
+ | Expo | SDK 50+ |
107
+ | TypeScript | >= 5.0 (optional) |
108
+
109
+ ---
110
+
111
+ ## đŸ“Ļ Installation
112
+
113
+ ### Expo Projects
114
+
115
+ ```bash
116
+ npx expo install react-native-gifted-chat react-native-reanimated react-native-gesture-handler react-native-safe-area-context react-native-keyboard-controller
117
+ ```
118
+
119
+ ### Bare React Native Projects
120
+
121
+ **Step 1:** Install the packages
122
+
123
+ Using yarn:
124
+ ```bash
125
+ yarn add react-native-gifted-chat react-native-reanimated react-native-gesture-handler react-native-safe-area-context react-native-keyboard-controller
126
+ ```
127
+
128
+ Using npm:
129
+ ```bash
130
+ npm install --save react-native-gifted-chat react-native-reanimated react-native-gesture-handler react-native-safe-area-context react-native-keyboard-controller
131
+ ```
132
+
133
+ **Step 2:** Install iOS pods
134
+
135
+ ```bash
136
+ npx pod-install
137
+ ```
138
+
139
+ **Step 3:** Configure react-native-reanimated
140
+
141
+ Follow the [react-native-reanimated installation guide](https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/getting-started/#step-2-add-reanimateds-babel-plugin) to add the Babel plugin.
142
+
143
+ ---
144
+
145
+ ## 🚀 Usage
146
+
147
+ ### Basic Example
148
+
149
+ ```jsx
150
+ import React, { useState, useCallback, useEffect } from 'react'
151
+ import { GiftedChat } from 'react-native-gifted-chat'
152
+ import { useHeaderHeight } from '@react-navigation/elements'
153
+
154
+ export function Example() {
155
+ const [messages, setMessages] = useState([])
156
+
157
+ // keyboardVerticalOffset = distance from screen top to GiftedChat container
158
+ // useHeaderHeight() returns status bar + navigation header height
159
+ const headerHeight = useHeaderHeight()
160
+
161
+ useEffect(() => {
162
+ setMessages([
163
+ {
164
+ _id: 1,
165
+ text: 'Hello developer',
166
+ createdAt: new Date(),
167
+ user: {
168
+ _id: 2,
169
+ name: 'John Doe',
170
+ avatar: 'https://placeimg.com/140/140/any',
171
+ },
172
+ },
173
+ ])
174
+ }, [])
175
+
176
+ const onSend = useCallback((messages = []) => {
177
+ setMessages(previousMessages =>
178
+ GiftedChat.append(previousMessages, messages),
179
+ )
180
+ }, [])
181
+
182
+ return (
183
+ <GiftedChat
184
+ messages={messages}
185
+ onSend={messages => onSend(messages)}
186
+ user={{
187
+ _id: 1,
188
+ }}
189
+ keyboardAvoidingViewProps={{ keyboardVerticalOffset: headerHeight }}
190
+ />
191
+ )
192
+ }
193
+ ```
194
+
195
+ > **💡 Tip:** Check out more examples in the [`example`](example) directory including Slack-style messages, quick replies, and custom components.
196
+
197
+ ---
198
+
199
+ ## 📊 Data Structure
200
+
201
+ Messages, system messages, and quick replies follow the structure defined in [Models.ts](src/Models.ts).
202
+
203
+ <details>
204
+ <summary><strong>Message Object Structure</strong></summary>
205
+
206
+ ```typescript
207
+ interface IMessage {
208
+ _id: string | number
209
+ text: string
210
+ createdAt: Date | number
211
+ user: User
212
+ image?: string
213
+ video?: string
214
+ audio?: string
215
+ system?: boolean
216
+ sent?: boolean
217
+ received?: boolean
218
+ pending?: boolean
219
+ quickReplies?: QuickReplies
220
+ }
221
+
222
+ interface User {
223
+ _id: string | number
224
+ name?: string
225
+ avatar?: string | number | (() => React.ReactNode)
226
+ }
227
+ ```
228
+
229
+ </details>
230
+
231
+ ---
232
+
233
+ ## 📖 Props Reference
234
+
235
+ ### Core Configuration
236
+
237
+ - **`messages`** _(Array)_ - Messages to display
238
+ - **`user`** _(Object)_ - User sending the messages: `{ _id, name, avatar }`
239
+ - **`onSend`** _(Function)_ - Callback when sending a message
240
+ - **`messageIdGenerator`** _(Function)_ - Generate an id for new messages. Defaults to a simple random string generator.
241
+ - **`locale`** _(String)_ - Locale to localize the dates. You need first to import the locale you need (ie. `require('dayjs/locale/de')` or `import 'dayjs/locale/fr'`)
242
+ - **`colorScheme`** _('light' | 'dark')_ - Force color scheme (light/dark mode). When set to `'light'` or `'dark'`, it overrides the system color scheme. When `undefined`, it uses the system color scheme. Default is `undefined`.
243
+
244
+ ### Refs
245
+
246
+ - **`messagesContainerRef`** _(FlatList ref)_ - Ref to the flatlist
247
+ - **`textInputRef`** _(TextInput ref)_ - Ref to the text input
248
+
249
+ ### Keyboard & Layout
250
+
251
+ - **`keyboardProviderProps`** _(Object)_ - Props to be passed to the [`KeyboardProvider`](https://kirillzyusko.github.io/react-native-keyboard-controller/docs/api/keyboard-provider) for keyboard handling. Default values:
252
+ - `statusBarTranslucent: true` - Required on Android for correct keyboard height calculation when status bar is translucent (edge-to-edge mode)
253
+ - `navigationBarTranslucent: true` - Required on Android for correct keyboard height calculation when navigation bar is translucent (edge-to-edge mode)
254
+ - **`keyboardAvoidingViewProps`** _(Object)_ - Props to be passed to the [`KeyboardAvoidingView`](https://kirillzyusko.github.io/react-native-keyboard-controller/docs/api/components/keyboard-avoiding-view). See **keyboardVerticalOffset** below for proper keyboard handling.
255
+ - **`isAlignedTop`** _(Boolean)_ Controls whether or not the message bubbles appear at the top of the chat (Default is false - bubbles align to bottom)
256
+ - **`isInverted`** _(Bool)_ - Reverses display order of `messages`; default is `true`
257
+
258
+ #### Understanding `keyboardVerticalOffset`
259
+
260
+ The [`keyboardVerticalOffset`](https://kirillzyusko.github.io/react-native-keyboard-controller/docs/api/components/keyboard-avoiding-view#keyboardverticaloffset) tells the KeyboardAvoidingView where its container starts relative to the top of the screen. This is essential when GiftedChat is not positioned at the very top of the screen (e.g., when you have a navigation header).
261
+
262
+ **Default value:** `insets.top` (status bar height from `useSafeAreaInsets()`). This works correctly only when GiftedChat fills the entire screen without a navigation header. If you have a navigation header, you need to pass the correct offset via `keyboardAvoidingViewProps`.
263
+
264
+ **What the value means:** The offset equals the distance (in points) from the top of the screen to the top of your GiftedChat container. This typically includes:
265
+ - Status bar height
266
+ - Navigation header height (on iOS, `useHeaderHeight()` already includes status bar)
267
+
268
+ **How to use:**
269
+
270
+ ```jsx
271
+ import { useHeaderHeight } from '@react-navigation/elements'
272
+
273
+ function ChatScreen() {
274
+ // useHeaderHeight() returns status bar + navigation header height on iOS
275
+ const headerHeight = useHeaderHeight()
276
+
277
+ return (
278
+ <GiftedChat
279
+ keyboardAvoidingViewProps={{ keyboardVerticalOffset: headerHeight }}
280
+ // ... other props
281
+ />
282
+ )
283
+ }
284
+ ```
285
+
286
+ > **Note:** `useHeaderHeight()` requires your chat component to be rendered inside a proper navigation screen (not conditional rendering). If it returns `0`, ensure your chat screen is a real navigation screen with a visible header.
287
+
288
+ **Why this matters:** Without the correct offset, the keyboard may overlap the input field or leave extra space. The KeyboardAvoidingView uses this value to calculate how much to shift the content when the keyboard appears.
289
+
290
+ ### Text Input & Composer
291
+
292
+ - **`text`** _(String)_ - Input text; default is `undefined`, but if specified, it will override GiftedChat's internal state. Useful for managing text state outside of GiftedChat (e.g. with Redux). Don't forget to implement `textInputProps.onChangeText` to update the text state.
293
+ - **`initialText`** _(String)_ - Initial text to display in the input field
294
+ - **`isSendButtonAlwaysVisible`** _(Bool)_ - Always show send button in input text composer; default `false`, show only when text input is not empty
295
+ - **`isTextOptional`** _(Bool)_ - Allow sending messages without text (useful for media-only messages); default `false`. Use with `isSendButtonAlwaysVisible` for media attachments.
296
+ - **`minComposerHeight`** _(Object)_ - Custom min-height of the composer.
297
+ - **`maxComposerHeight`** _(Object)_ - Custom max height of the composer.
298
+ - **`minInputToolbarHeight`** _(Integer)_ - Minimum height of the input toolbar; default is `44`
299
+ - **`renderInputToolbar`** _(Component | Function)_ - Custom message composer container
300
+ - **`renderComposer`** _(Component | Function)_ - Custom text input message composer
301
+ - **`renderSend`** _(Component | Function)_ - Custom send button; you can pass children to the original `Send` component quite easily, for example, to use a custom icon ([example](https://github.com/FaridSafi/react-native-gifted-chat/pull/487))
302
+ - **`renderActions`** _(Component | Function)_ - Custom action button on the left of the message composer
303
+ - **`renderAccessory`** _(Component | Function)_ - Custom second line of actions below the message composer
304
+ - **`textInputProps`** _(Object)_ - props to be passed to the [`<TextInput>`](https://reactnative.dev/docs/textinput).
305
+
306
+ ### Actions & Action Sheet
307
+
308
+ - **`onPressActionButton`** _(Function)_ - Callback when the Action button is pressed (if set, the default `actionSheet` will not be used)
309
+ - **`actionSheet`** _(Function)_ - Custom action sheet interface for showing action options
310
+ - **`actions`** _(Array)_ - Custom action options for the input toolbar action button; array of objects with `title` (string) and `action` (function) properties
311
+ - **`actionSheetOptionTintColor`** _(String)_ - Tint color for action sheet options
312
+
313
+ ### Messages & Message Container
314
+
315
+ - **`messagesContainerStyle`** _(Object)_ - Custom style for the messages container
316
+ - **`renderMessage`** _(Component | Function)_ - Custom message container
317
+ - **`renderLoading`** _(Component | Function)_ - Render a loading view when initializing
318
+ - **`renderChatEmpty`** _(Component | Function)_ - Custom component to render in the ListView when messages are empty
319
+ - **`renderChatFooter`** _(Component | Function)_ - Custom component to render below the MessagesContainer (separate from the ListView)
320
+ - **`listProps`** _(Object)_ - Extra props to be passed to the messages [`<FlatList>`](https://reactnative.dev/docs/flatlist). Supports all FlatList props including `maintainVisibleContentPosition` for keeping scroll position when new messages arrive (useful for AI chatbots).
321
+
322
+ ### Message Bubbles & Content
323
+
324
+ - **`renderBubble`** _(Component | Function(`props: BubbleProps`))_ - Custom message bubble. Receives [BubbleProps](src/Bubble/types.ts) as parameter.
325
+ - **`renderMessageText`** _(Component | Function)_ - Custom message text
326
+ - **`renderMessageImage`** _(Component | Function)_ - Custom message image
327
+ - **`renderMessageVideo`** _(Component | Function)_ - Custom message video
328
+ - **`renderMessageAudio`** _(Component | Function)_ - Custom message audio
329
+ - **`renderCustomView`** _(Component | Function)_ - Custom view inside the bubble
330
+ - **`isCustomViewBottom`** _(Bool)_ - Determine whether renderCustomView is displayed before or after the text, image and video views; default is `false`
331
+ - **`onPressMessage`** _(Function(`context`, `message`))_ - Callback when a message bubble is pressed
332
+ - **`onLongPressMessage`** _(Function(`context`, `message`))_ - Callback when a message bubble is long-pressed; you can use this to show action sheets (e.g., copy, delete, reply)
333
+ - **`imageProps`** _(Object)_ - Extra props to be passed to the [`<Image>`](https://reactnative.dev/docs/image) component created by the default `renderMessageImage`
334
+ - **`imageStyle`** _(Object)_ - Custom style for message images
335
+ - **`videoProps`** _(Object)_ - Extra props to be passed to the video component created by the required `renderMessageVideo`
336
+ - **`messageTextProps`** _(Object)_ - Extra props to be passed to the MessageText component. Useful for customizing link parsing behavior, text styles, and matchers. Supports the following props:
337
+ - `matchers` - Custom matchers for linking message content (like URLs, phone numbers, hashtags, mentions)
338
+ - `linkStyle` - Custom style for links
339
+ - `email` - Enable/disable email parsing (default: true)
340
+ - `phone` - Enable/disable phone number parsing (default: true)
341
+ - `url` - Enable/disable URL parsing (default: true)
342
+ - `hashtag` - Enable/disable hashtag parsing (default: false)
343
+ - `mention` - Enable/disable mention parsing (default: false)
344
+ - `hashtagUrl` - Base URL for hashtags (e.g., 'https://x.com/hashtag')
345
+ - `mentionUrl` - Base URL for mentions (e.g., 'https://x.com')
346
+ - `stripPrefix` - Strip 'http://' or 'https://' from URL display (default: false)
347
+ - `TextComponent` - Custom Text component to use (e.g., from react-native-gesture-handler)
348
+
349
+ Example:
350
+
351
+ ```tsx
352
+ <GiftedChat
353
+ messageTextProps={{
354
+ phone: false, // Disable default phone number linking
355
+ matchers: [
356
+ {
357
+ type: 'phone',
358
+ pattern: /\+?[1-9][0-9\-\(\) ]{7,}[0-9]/g,
359
+ getLinkUrl: (replacerArgs: ReplacerArgs): string => {
360
+ return replacerArgs[0].replace(/[\-\(\) ]/g, '')
361
+ },
362
+ getLinkText: (replacerArgs: ReplacerArgs): string => {
363
+ return replacerArgs[0]
364
+ },
365
+ style: styles.linkStyle,
366
+ onPress: (match: CustomMatch) => {
367
+ const url = match.getAnchorHref()
368
+
369
+ const options: {
370
+ title: string
371
+ action?: () => void
372
+ }[] = [
373
+ { title: 'Copy', action: () => setStringAsync(url) },
374
+ { title: 'Call', action: () => Linking.openURL(`tel:${url}`) },
375
+ { title: 'Send SMS', action: () => Linking.openURL(`sms:${url}`) },
376
+ { title: 'Cancel' },
377
+ ]
378
+
379
+ showActionSheetWithOptions({
380
+ options: options.map(o => o.title),
381
+ cancelButtonIndex: options.length - 1,
382
+ }, (buttonIndex?: number) => {
383
+ if (buttonIndex === undefined)
384
+ return
385
+
386
+ const option = options[buttonIndex]
387
+ option.action?.()
388
+ })
389
+ },
390
+ },
391
+ ],
392
+ linkStyle: { left: { color: 'blue' }, right: { color: 'lightblue' } },
393
+ }}
394
+ />
395
+ ```
396
+
397
+ See full example in [LinksExample](example/components/chat-examples/LinksExample.tsx)
398
+
399
+ ### Avatars
400
+
401
+ - **`renderAvatar`** _(Component | Function)_ - Custom message avatar; set to `null` to not render any avatar for the message
402
+ - **`isUserAvatarVisible`** _(Bool)_ - Whether to render an avatar for the current user; default is `false`, only show avatars for other users
403
+ - **`isAvatarVisibleForEveryMessage`** _(Bool)_ - When false, avatars will only be displayed when a consecutive message is from the same user on the same day; default is `false`
404
+ - **`onPressAvatar`** _(Function(`user`))_ - Callback when a message avatar is tapped
405
+ - **`onLongPressAvatar`** _(Function(`user`))_ - Callback when a message avatar is long-pressed
406
+ - **`isAvatarOnTop`** _(Bool)_ - Render the message avatar at the top of consecutive messages, rather than the bottom; default is `false`
407
+
408
+ ### Username
409
+
410
+ - **`isUsernameVisible`** _(Bool)_ - Indicate whether to show the user's username inside the message bubble; default is `false`
411
+ - **`renderUsername`** _(Component | Function)_ - Custom Username container
412
+
413
+ ### Date & Time
414
+
415
+ - **`timeFormat`** _(String)_ - Format to use for rendering times; default is `'LT'` (see [Day.js Format](https://day.js.org/docs/en/display/format))
416
+ - **`dateFormat`** _(String)_ - Format to use for rendering dates; default is `'D MMMM'` (see [Day.js Format](https://day.js.org/docs/en/display/format))
417
+ - **`dateFormatCalendar`** _(Object)_ - Format to use for rendering relative times; default is `{ sameDay: '[Today]' }` (see [Day.js Calendar](https://day.js.org/docs/en/plugin/calendar))
418
+ - **`renderDay`** _(Component | Function)_ - Custom day above a message
419
+ - **`dayProps`** _(Object)_ - Props to pass to the Day component:
420
+ - `containerStyle` - Custom style for the day container
421
+ - `wrapperStyle` - Custom style for the day wrapper
422
+ - `textProps` - Props to pass to the Text component (e.g., `style`, `allowFontScaling`, `numberOfLines`)
423
+ - **`renderTime`** _(Component | Function)_ - Custom time inside a message
424
+ - **`timeTextStyle`** _(Object)_ - Custom text style for time inside messages (supports left/right styles)
425
+ - **`isDayAnimationEnabled`** _(Bool)_ - Enable animated day label that appears on scroll; default is `true`
426
+
427
+ ### System Messages
428
+
429
+ - **`renderSystemMessage`** _(Component | Function)_ - Custom system message
430
+
431
+ ### Load Earlier Messages
432
+
433
+ - **`loadEarlierMessagesProps`** _(Object)_ - Props to pass to the LoadEarlierMessages component. The button is only visible when `isAvailable` is `true`. Supports the following props:
434
+ - `isAvailable` - Controls button visibility (default: false)
435
+ - `onPress` - Callback when button is pressed
436
+ - `isLoading` - Display loading indicator (default: false)
437
+ - `isInfiniteScrollEnabled` - Enable infinite scroll up when reaching the top of messages container, automatically calls `onPress` (not yet supported for web)
438
+ - `label` - Override the default "Load earlier messages" text
439
+ - `containerStyle` - Custom style for the button container
440
+ - `wrapperStyle` - Custom style for the button wrapper
441
+ - `textStyle` - Custom style for the button text
442
+ - `activityIndicatorStyle` - Custom style for the loading indicator
443
+ - `activityIndicatorColor` - Color of the loading indicator (default: 'white')
444
+ - `activityIndicatorSize` - Size of the loading indicator (default: 'small')
445
+ - **`renderLoadEarlier`** _(Component | Function)_ - Custom "Load earlier messages" button
446
+
447
+ ### Typing Indicator
448
+
449
+ - **`isTyping`** _(Bool)_ - Typing Indicator state; default `false`. If you use`renderFooter` it will override this.
450
+ - **`renderTypingIndicator`** _(Component | Function)_ - Custom typing indicator component
451
+ - **`typingIndicatorStyle`** _(StyleProp<ViewStyle>)_ - Custom style for the TypingIndicator component.
452
+ - **`renderFooter`** _(Component | Function)_ - Custom footer component on the ListView, e.g. `'User is typing...'`; see [CustomizedFeaturesExample.tsx](example/components/chat-examples/CustomizedFeaturesExample.tsx) for an example. Overrides default typing indicator that triggers when `isTyping` is true.
453
+
454
+ ### Quick Replies
455
+
456
+ See [Quick Replies example in messages.ts](example/example-expo/data/messages.ts)
457
+
458
+ - **`onQuickReply`** _(Function)_ - Callback when sending a quick reply (to backend server)
459
+ - **`renderQuickReplies`** _(Function)_ - Custom all quick reply view
460
+ - **`quickReplyStyle`** _(StyleProp<ViewStyle>)_ - Custom quick reply view style
461
+ - **`quickReplyTextStyle`** _(StyleProp<TextStyle>)_ - Custom text style for quick reply buttons
462
+ - **`quickReplyContainerStyle`** _(StyleProp<ViewStyle>)_ - Custom container style for quick replies
463
+ - **`renderQuickReplySend`** _(Function)_ - Custom quick reply **send** view
464
+
465
+ ### Reply to Messages
466
+
467
+ Gifted Chat supports swipe-to-reply functionality out of the box. When enabled, users can swipe on a message to reply to it, displaying a reply preview in the input toolbar and the replied message above the new message bubble.
468
+
469
+ > **Note:** This feature uses `ReanimatedSwipeable` from `react-native-gesture-handler` and `react-native-reanimated` for smooth, performant animations.
470
+
471
+ #### Basic Usage
472
+
473
+ ```tsx
474
+ <GiftedChat
475
+ messages={messages}
476
+ onSend={onSend}
477
+ user={{ _id: 1 }}
478
+ reply={{
479
+ swipe: {
480
+ isEnabled: true,
481
+ direction: 'left', // swipe left to reply
482
+ },
483
+ }}
484
+ />
485
+ ```
486
+
487
+ #### Reply Props (Grouped)
488
+
489
+ The `reply` prop accepts an object with the following structure:
490
+
491
+ ```typescript
492
+ interface ReplyProps<TMessage> {
493
+ // Swipe gesture configuration
494
+ swipe?: {
495
+ isEnabled?: boolean // Enable swipe-to-reply; default false
496
+ direction?: 'left' | 'right' // Swipe direction; default 'left'
497
+ onSwipe?: (message: TMessage) => void // Callback when swiped
498
+ renderAction?: ( // Custom swipe action component
499
+ progress: SharedValue<number>,
500
+ translation: SharedValue<number>,
501
+ position: 'left' | 'right'
502
+ ) => React.ReactNode
503
+ actionContainerStyle?: StyleProp<ViewStyle>
504
+ }
505
+
506
+ // Reply preview styling (above input toolbar)
507
+ previewStyle?: {
508
+ containerStyle?: StyleProp<ViewStyle>
509
+ textStyle?: StyleProp<TextStyle>
510
+ imageStyle?: StyleProp<ImageStyle>
511
+ }
512
+
513
+ // In-bubble reply styling
514
+ messageStyle?: {
515
+ containerStyle?: StyleProp<ViewStyle>
516
+ containerStyleLeft?: StyleProp<ViewStyle>
517
+ containerStyleRight?: StyleProp<ViewStyle>
518
+ textStyle?: StyleProp<TextStyle>
519
+ textStyleLeft?: StyleProp<TextStyle>
520
+ textStyleRight?: StyleProp<TextStyle>
521
+ imageStyle?: StyleProp<ImageStyle>
522
+ }
523
+
524
+ // Callbacks and state
525
+ message?: ReplyMessage // Controlled reply state
526
+ onClear?: () => void // Called when reply cleared
527
+ onPress?: (message: TMessage) => void // Called when reply preview tapped
528
+
529
+ // Custom renderers
530
+ renderPreview?: (props: ReplyPreviewProps) => React.ReactNode
531
+ renderMessageReply?: (props: MessageReplyProps) => React.ReactNode
532
+ }
533
+ ```
534
+
535
+ #### ReplyMessage Structure
536
+
537
+ When a message has a reply, it includes a `replyMessage` property:
538
+
539
+ ```typescript
540
+ interface ReplyMessage {
541
+ _id: string | number
542
+ text: string
543
+ user: User
544
+ image?: string
545
+ audio?: string
546
+ }
547
+ ```
548
+
549
+ #### Advanced Example with External State
550
+
551
+ ```tsx
552
+ const [replyMessage, setReplyMessage] = useState<ReplyMessage | null>(null)
553
+
554
+ <GiftedChat
555
+ messages={messages}
556
+ onSend={messages => {
557
+ const newMessages = messages.map(msg => ({
558
+ ...msg,
559
+ replyMessage: replyMessage || undefined,
560
+ }))
561
+ setMessages(prev => GiftedChat.append(prev, newMessages))
562
+ setReplyMessage(null)
563
+ }}
564
+ user={{ _id: 1 }}
565
+ reply={{
566
+ swipe: {
567
+ isEnabled: true,
568
+ direction: 'right',
569
+ onSwipe: setReplyMessage,
570
+ },
571
+ message: replyMessage,
572
+ onClear: () => setReplyMessage(null),
573
+ onPress: (msg) => scrollToMessage(msg._id),
574
+ }}
575
+ />
576
+ ```
577
+
578
+ #### Smooth Animations
579
+
580
+ The reply preview automatically animates when:
581
+ - **Appearing**: Smoothly expands from zero height with fade-in effect
582
+ - **Disappearing**: Smoothly collapses with fade-out effect
583
+ - **Content changes**: Smoothly transitions when replying to a different message
584
+
585
+ These animations use `react-native-reanimated` for 60fps performance.
586
+
587
+ ### Scroll to Bottom
588
+
589
+ - **`isScrollToBottomEnabled`** _(Bool)_ - Enables the scroll to bottom Component (Default is false)
590
+ - **`scrollToBottomComponent`** _(Function)_ - Custom Scroll To Bottom Component container
591
+ - **`scrollToBottomOffset`** _(Integer)_ - Custom Height Offset upon which to begin showing Scroll To Bottom Component (Default is 200)
592
+ - **`scrollToBottomStyle`** _(Object)_ - Custom style for Scroll To Bottom wrapper (position, bottom, right, etc.)
593
+ - **`scrollToBottomContentStyle`** _(Object)_ - Custom style for Scroll To Bottom content (size, background, shadow, etc.)
594
+
595
+ ### Maintaining Scroll Position (AI Chatbots)
596
+
597
+ For AI chat interfaces where long responses arrive and you don't want to disrupt the user's reading position, use [`maintainVisibleContentPosition`](https://reactnative.dev/docs/scrollview#maintainvisiblecontentposition) via `listProps`:
598
+
599
+ ```tsx
600
+ // Basic usage - always maintain scroll position
601
+ <GiftedChat
602
+ listProps={{
603
+ maintainVisibleContentPosition: {
604
+ minIndexForVisible: 0,
605
+ },
606
+ }}
607
+ />
608
+
609
+ // With auto-scroll threshold - auto-scroll if within 10 pixels of newest content
610
+ <GiftedChat
611
+ listProps={{
612
+ maintainVisibleContentPosition: {
613
+ minIndexForVisible: 0,
614
+ autoscrollToTopThreshold: 10,
615
+ },
616
+ }}
617
+ />
618
+
619
+ // Conditionally enable based on scroll state (recommended for chatbots)
620
+ const [isScrolledUp, setIsScrolledUp] = useState(false)
621
+
622
+ <GiftedChat
623
+ listProps={{
624
+ onScroll: (event) => {
625
+ setIsScrolledUp(event.contentOffset.y > 50)
626
+ },
627
+ maintainVisibleContentPosition: isScrolledUp
628
+ ? { minIndexForVisible: 0, autoscrollToTopThreshold: 10 }
629
+ : undefined,
630
+ }}
631
+ />
632
+ ```
633
+
634
+ ---
635
+
636
+ ## 📱 Platform Notes
637
+
638
+ ### Android
639
+
640
+ <details>
641
+ <summary><strong>Keyboard configuration</strong></summary>
642
+
643
+ If you are using Create React Native App / Expo, no Android specific installation steps are required. Otherwise, we recommend modifying your project configuration:
644
+
645
+ Make sure you have `android:windowSoftInputMode="adjustResize"` in your `AndroidManifest.xml`:
646
+
647
+ ```xml
648
+ <activity
649
+ android:name=".MainActivity"
650
+ android:label="@string/app_name"
651
+ android:windowSoftInputMode="adjustResize"
652
+ android:configChanges="keyboard|keyboardHidden|orientation|screenSize">
653
+ ```
654
+
655
+ For **Expo**, you can append `KeyboardAvoidingView` after GiftedChat (Android only):
656
+
657
+ ```jsx
658
+ <View style={{ flex: 1 }}>
659
+ <GiftedChat />
660
+ {Platform.OS === 'android' && <KeyboardAvoidingView behavior="padding" />}
661
+ </View>
662
+ ```
663
+
664
+ </details>
665
+
666
+ ### Web (react-native-web)
667
+
668
+ <details>
669
+ <summary><strong>With create-react-app</strong></summary>
670
+
671
+ 1. Install react-app-rewired: `yarn add -D react-app-rewired`
672
+ 2. Create `config-overrides.js`:
673
+
674
+ ```js
675
+ module.exports = function override(config, env) {
676
+ config.module.rules.push({
677
+ test: /\.js$/,
678
+ exclude: /node_modules[/\\](?!react-native-gifted-chat)/,
679
+ use: {
680
+ loader: 'babel-loader',
681
+ options: {
682
+ babelrc: false,
683
+ configFile: false,
684
+ presets: [
685
+ ['@babel/preset-env', { useBuiltIns: 'usage' }],
686
+ '@babel/preset-react',
687
+ ],
688
+ plugins: ['@babel/plugin-proposal-class-properties'],
689
+ },
690
+ },
691
+ })
692
+ return config
693
+ }
694
+ ```
695
+
696
+ > **Examples:**
697
+ > - [xcarpentier/gifted-chat-web-demo](https://github.com/xcarpentier/gifted-chat-web-demo)
698
+ > - [Gatsby example](https://github.com/xcarpentier/clean-archi-boilerplate/tree/develop/apps/web)
699
+
700
+ </details>
701
+
702
+ ---
703
+
704
+ ## đŸ§Ē Testing
705
+
706
+ <details>
707
+ <summary><strong>Triggering layout events in tests</strong></summary>
708
+
709
+ `TEST_ID` is exported as constants that can be used in your testing library of choice.
710
+
711
+ Gifted Chat uses `onLayout` to determine the height of the chat container. To trigger `onLayout` during your tests:
712
+
713
+ ```typescript
714
+ const WIDTH = 200
715
+ const HEIGHT = 2000
716
+
717
+ const loadingWrapper = getByTestId(TEST_ID.LOADING_WRAPPER)
718
+ fireEvent(loadingWrapper, 'layout', {
719
+ nativeEvent: {
720
+ layout: {
721
+ width: WIDTH,
722
+ height: HEIGHT,
723
+ },
724
+ },
725
+ })
726
+ ```
727
+
728
+ </details>
729
+
730
+ ---
731
+
732
+ ## đŸ“Ļ Example App
733
+
734
+ The repository includes a comprehensive example app demonstrating all features:
735
+
736
+ ```bash
737
+ # Clone and install
738
+ git clone https://github.com/FaridSafi/react-native-gifted-chat.git
739
+ cd react-native-gifted-chat/example
740
+ yarn install
741
+
742
+ # Run on iOS
743
+ npx expo run:ios
744
+
745
+ # Run on Android
746
+ npx expo run:android
747
+
748
+ # Run on Web
749
+ npx expo start --web
750
+ ```
751
+
752
+ The example app showcases:
753
+ - đŸ’Ŧ Basic chat functionality
754
+ - 🎨 Custom message bubbles and avatars
755
+ - â†Šī¸ Reply to messages with swipe gesture
756
+ - ⚡ Quick replies (bot-style)
757
+ - âœī¸ Typing indicators
758
+ - 📎 Attachment actions
759
+ - 🔗 Link parsing and custom matchers
760
+ - 🌐 Web compatibility
761
+
762
+ ---
763
+
764
+ ## ❓ Troubleshooting
765
+
766
+ <details>
767
+ <summary><strong>TextInput is hidden on Android</strong></summary>
768
+
769
+ Make sure you have `android:windowSoftInputMode="adjustResize"` in your `AndroidManifest.xml`. See [Android configuration](#android) above.
770
+
771
+ </details>
772
+
773
+ <details>
774
+ <summary><strong>How to set Bubble color for each user?</strong></summary>
775
+
776
+ See [this issue](https://github.com/FaridSafi/react-native-gifted-chat/issues/672) for examples.
777
+
778
+ </details>
779
+
780
+ <details>
781
+ <summary><strong>How to customize InputToolbar styles?</strong></summary>
782
+
783
+ See [this issue](https://github.com/FaridSafi/react-native-gifted-chat/issues/662) for examples.
784
+
785
+ </details>
786
+
787
+ <details>
788
+ <summary><strong>How to manually dismiss the keyboard?</strong></summary>
789
+
790
+ See [this issue](https://github.com/FaridSafi/react-native-gifted-chat/issues/647) for examples.
791
+
792
+ </details>
793
+
794
+ <details>
795
+ <summary><strong>How to use renderLoading?</strong></summary>
796
+
797
+ See [this issue](https://github.com/FaridSafi/react-native-gifted-chat/issues/298) for examples.
798
+
799
+ </details>
800
+
801
+ ---
802
+
803
+ ## 🤔 Have a Question?
804
+
805
+ 1. Check this README first
806
+ 2. Search [existing issues](https://github.com/FaridSafi/react-native-gifted-chat/issues)
807
+ 3. Ask on [StackOverflow](https://stackoverflow.com/questions/tagged/react-native-gifted-chat)
808
+ 4. Open a new issue if needed
809
+
810
+ ---
811
+
812
+ ## 🤝 Contributing
813
+
814
+ Contributions are welcome! Please feel free to submit a Pull Request.
815
+
816
+ 1. Fork the repository
817
+ 2. Create your feature branch (`git checkout -b feature/amazing-feature`)
818
+ 3. Install dependencies (`yarn install`)
819
+ 4. Make your changes
820
+ 5. Run tests (`yarn test`)
821
+ 6. Run linting (`yarn lint`)
822
+ 7. Build the library (`yarn build`)
823
+ 8. Commit your changes (`git commit -m 'Add amazing feature'`)
824
+ 9. Push to the branch (`git push origin feature/amazing-feature`)
825
+ 10. Open a Pull Request
826
+
827
+ ### Development Setup
828
+
829
+ ```bash
830
+ # Install dependencies
831
+ yarn install
832
+
833
+ # Build the library
834
+ yarn build
835
+
836
+ # Run tests
837
+ yarn test
838
+
839
+ # Run linting
840
+ yarn lint
841
+
842
+ # Full validation
843
+ yarn prepublishOnly
844
+ ```
845
+
846
+ ---
847
+
848
+ ## đŸ‘Ĩ Authors
849
+
850
+ **Original Author:** [Farid Safi](https://www.x.com/FaridSafi)
851
+
852
+ **Co-author:** [Xavier Carpentier](https://www.x.com/xcapetir) - [Hire Xavier](https://xaviercarpentier.com)
853
+
854
+ **Maintainer:** [Kesha Antonov](https://github.com/kesha-antonov)
855
+
856
+ > I've been maintaining this project for 2 years, completely in my free time and without any compensation. If you find it helpful, please consider [becoming a sponsor](https://github.com/sponsors/kesha-antonov) to support continued development. 💖
857
+
858
+ ---
859
+
860
+ ## 📄 License
861
+
862
+ [MIT](LICENSE)
863
+
864
+ ---
865
+
866
+ <p align="center">
867
+ <sub>Built with â¤ī¸ by the React Native community</sub>
868
+ </p>