react-native-gifted-chat 2.8.2-alpha.0 → 2.8.2-alpha.2

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 (203) hide show
  1. package/README.md +51 -31
  2. package/package.json +28 -30
  3. package/src/Actions.tsx +1 -1
  4. package/src/Avatar.tsx +1 -1
  5. package/src/Bubble/index.tsx +24 -20
  6. package/src/Bubble/types.ts +7 -6
  7. package/src/Composer.tsx +19 -26
  8. package/src/Constant.ts +0 -1
  9. package/src/Day/index.tsx +3 -3
  10. package/src/GiftedAvatar.tsx +31 -38
  11. package/src/GiftedChat/index.tsx +59 -106
  12. package/src/GiftedChat/styles.ts +3 -0
  13. package/src/GiftedChat/types.ts +17 -67
  14. package/src/InputToolbar.tsx +27 -10
  15. package/src/LoadEarlier.tsx +22 -20
  16. package/src/Message/index.tsx +4 -18
  17. package/src/Message/types.ts +2 -2
  18. package/src/MessageAudio.tsx +19 -7
  19. package/src/MessageContainer/components/DayAnimated/index.tsx +16 -11
  20. package/src/MessageContainer/components/Item/index.tsx +10 -4
  21. package/src/MessageContainer/components/Item/types.ts +1 -1
  22. package/src/MessageContainer/index.tsx +57 -38
  23. package/src/MessageContainer/types.ts +32 -7
  24. package/src/MessageImage.tsx +132 -18
  25. package/src/MessageText.tsx +24 -64
  26. package/src/MessageVideo.tsx +19 -7
  27. package/src/QuickReplies.tsx +19 -12
  28. package/src/Send.tsx +10 -5
  29. package/src/SystemMessage.tsx +10 -3
  30. package/src/Time.tsx +10 -3
  31. package/src/TypingIndicator/index.tsx +4 -3
  32. package/src/TypingIndicator/types.ts +3 -0
  33. package/src/__tests__/Actions.test.tsx +3 -4
  34. package/src/__tests__/Avatar.test.tsx +5 -6
  35. package/src/__tests__/Bubble.test.tsx +14 -19
  36. package/src/__tests__/Composer.test.tsx +3 -4
  37. package/src/__tests__/Day.test.tsx +5 -8
  38. package/src/__tests__/DayAnimated.test.tsx +12 -14
  39. package/src/__tests__/GiftedAvatar.test.tsx +3 -8
  40. package/src/__tests__/GiftedChat.test.tsx +34 -43
  41. package/src/__tests__/InputToolbar.test.tsx +3 -4
  42. package/src/__tests__/LoadEarlier.test.tsx +3 -4
  43. package/src/__tests__/Message.test.tsx +51 -58
  44. package/src/__tests__/MessageContainer.test.tsx +39 -5
  45. package/src/__tests__/MessageImage.test.tsx +12 -15
  46. package/src/__tests__/MessageText.test.tsx +7 -4
  47. package/src/__tests__/Send.test.tsx +7 -8
  48. package/src/__tests__/SystemMessage.test.tsx +12 -15
  49. package/src/__tests__/Time.test.tsx +5 -8
  50. package/src/__tests__/__snapshots__/Actions.test.tsx.snap +39 -7
  51. package/src/__tests__/__snapshots__/Bubble.test.tsx.snap +48 -50
  52. package/src/__tests__/__snapshots__/Composer.test.tsx.snap +1 -2
  53. package/src/__tests__/__snapshots__/Constant.test.tsx.snap +0 -1
  54. package/src/__tests__/__snapshots__/GiftedChat.test.tsx.snap +20 -22
  55. package/src/__tests__/__snapshots__/InputToolbar.test.tsx.snap +2 -2
  56. package/src/__tests__/__snapshots__/LoadEarlier.test.tsx.snap +37 -6
  57. package/src/__tests__/__snapshots__/Message.test.tsx.snap +146 -150
  58. package/src/__tests__/__snapshots__/MessageImage.test.tsx.snap +32 -11
  59. package/src/__tests__/__snapshots__/MessageText.test.tsx.snap +12 -8
  60. package/src/__tests__/__snapshots__/Send.test.tsx.snap +72 -10
  61. package/src/components/TouchableOpacity.tsx +45 -0
  62. package/src/reanimatedCompat.ts +27 -0
  63. package/src/types.ts +4 -2
  64. package/src/utils.ts +2 -2
  65. package/lib/Actions.d.ts +0 -14
  66. package/lib/Actions.js +0 -57
  67. package/lib/Actions.js.map +0 -1
  68. package/lib/Avatar.d.ts +0 -18
  69. package/lib/Avatar.js +0 -93
  70. package/lib/Avatar.js.map +0 -1
  71. package/lib/Bubble/index.d.ts +0 -6
  72. package/lib/Bubble/index.js +0 -242
  73. package/lib/Bubble/index.js.map +0 -1
  74. package/lib/Bubble/styles.d.ts +0 -69
  75. package/lib/Bubble/styles.js +0 -72
  76. package/lib/Bubble/styles.js.map +0 -1
  77. package/lib/Bubble/types.d.ts +0 -47
  78. package/lib/Bubble/types.js +0 -2
  79. package/lib/Bubble/types.js.map +0 -1
  80. package/lib/Color.d.ts +0 -18
  81. package/lib/Color.js +0 -18
  82. package/lib/Color.js.map +0 -1
  83. package/lib/Composer.d.ts +0 -20
  84. package/lib/Composer.js +0 -60
  85. package/lib/Composer.js.map +0 -1
  86. package/lib/Constant.d.ts +0 -10
  87. package/lib/Constant.js +0 -17
  88. package/lib/Constant.js.map +0 -1
  89. package/lib/Day/index.d.ts +0 -4
  90. package/lib/Day/index.js +0 -39
  91. package/lib/Day/index.js.map +0 -1
  92. package/lib/Day/styles.d.ts +0 -20
  93. package/lib/Day/styles.js +0 -22
  94. package/lib/Day/styles.js.map +0 -1
  95. package/lib/Day/types.d.ts +0 -9
  96. package/lib/Day/types.js +0 -2
  97. package/lib/Day/types.js.map +0 -1
  98. package/lib/GiftedAvatar.d.ts +0 -11
  99. package/lib/GiftedAvatar.js +0 -104
  100. package/lib/GiftedAvatar.js.map +0 -1
  101. package/lib/GiftedChat/index.d.ts +0 -26
  102. package/lib/GiftedChat/index.js +0 -317
  103. package/lib/GiftedChat/index.js.map +0 -1
  104. package/lib/GiftedChat/styles.d.ts +0 -6
  105. package/lib/GiftedChat/styles.js +0 -7
  106. package/lib/GiftedChat/styles.js.map +0 -1
  107. package/lib/GiftedChat/types.d.ts +0 -112
  108. package/lib/GiftedChat/types.js +0 -2
  109. package/lib/GiftedChat/types.js.map +0 -1
  110. package/lib/GiftedChatContext.d.ts +0 -9
  111. package/lib/GiftedChatContext.js +0 -9
  112. package/lib/GiftedChatContext.js.map +0 -1
  113. package/lib/InputToolbar.d.ts +0 -23
  114. package/lib/InputToolbar.js +0 -56
  115. package/lib/InputToolbar.js.map +0 -1
  116. package/lib/LoadEarlier.d.ts +0 -14
  117. package/lib/LoadEarlier.js +0 -45
  118. package/lib/LoadEarlier.js.map +0 -1
  119. package/lib/Message/index.d.ts +0 -6
  120. package/lib/Message/index.js +0 -80
  121. package/lib/Message/index.js.map +0 -1
  122. package/lib/Message/styles.d.ts +0 -21
  123. package/lib/Message/styles.js +0 -22
  124. package/lib/Message/styles.js.map +0 -1
  125. package/lib/Message/types.d.ts +0 -22
  126. package/lib/Message/types.js +0 -2
  127. package/lib/Message/types.js.map +0 -1
  128. package/lib/MessageAudio.d.ts +0 -2
  129. package/lib/MessageAudio.js +0 -14
  130. package/lib/MessageAudio.js.map +0 -1
  131. package/lib/MessageContainer/components/DayAnimated/index.d.ts +0 -5
  132. package/lib/MessageContainer/components/DayAnimated/index.js +0 -85
  133. package/lib/MessageContainer/components/DayAnimated/index.js.map +0 -1
  134. package/lib/MessageContainer/components/DayAnimated/styles.d.ts +0 -11
  135. package/lib/MessageContainer/components/DayAnimated/styles.js +0 -12
  136. package/lib/MessageContainer/components/DayAnimated/styles.js.map +0 -1
  137. package/lib/MessageContainer/components/DayAnimated/types.d.ts +0 -17
  138. package/lib/MessageContainer/components/DayAnimated/types.js +0 -2
  139. package/lib/MessageContainer/components/DayAnimated/types.js.map +0 -1
  140. package/lib/MessageContainer/components/Item/index.d.ts +0 -23
  141. package/lib/MessageContainer/components/Item/index.js +0 -88
  142. package/lib/MessageContainer/components/Item/index.js.map +0 -1
  143. package/lib/MessageContainer/components/Item/types.d.ts +0 -17
  144. package/lib/MessageContainer/components/Item/types.js +0 -2
  145. package/lib/MessageContainer/components/Item/types.js.map +0 -1
  146. package/lib/MessageContainer/index.d.ts +0 -6
  147. package/lib/MessageContainer/index.js +0 -235
  148. package/lib/MessageContainer/index.js.map +0 -1
  149. package/lib/MessageContainer/styles.d.ts +0 -35
  150. package/lib/MessageContainer/styles.js +0 -32
  151. package/lib/MessageContainer/styles.js.map +0 -1
  152. package/lib/MessageContainer/types.d.ts +0 -51
  153. package/lib/MessageContainer/types.js +0 -2
  154. package/lib/MessageContainer/types.js.map +0 -1
  155. package/lib/MessageImage.d.ts +0 -13
  156. package/lib/MessageImage.js +0 -30
  157. package/lib/MessageImage.js.map +0 -1
  158. package/lib/MessageText.d.ts +0 -19
  159. package/lib/MessageText.js +0 -69
  160. package/lib/MessageText.js.map +0 -1
  161. package/lib/MessageVideo.d.ts +0 -2
  162. package/lib/MessageVideo.js +0 -14
  163. package/lib/MessageVideo.js.map +0 -1
  164. package/lib/QuickReplies.d.ts +0 -15
  165. package/lib/QuickReplies.js +0 -101
  166. package/lib/QuickReplies.js.map +0 -1
  167. package/lib/Send.d.ts +0 -15
  168. package/lib/Send.js +0 -34
  169. package/lib/Send.js.map +0 -1
  170. package/lib/SystemMessage.d.ts +0 -11
  171. package/lib/SystemMessage.js +0 -27
  172. package/lib/SystemMessage.js.map +0 -1
  173. package/lib/Time.d.ts +0 -11
  174. package/lib/Time.js +0 -56
  175. package/lib/Time.js.map +0 -1
  176. package/lib/TypingIndicator/index.d.ts +0 -5
  177. package/lib/TypingIndicator/index.js +0 -94
  178. package/lib/TypingIndicator/index.js.map +0 -1
  179. package/lib/TypingIndicator/styles.d.ts +0 -20
  180. package/lib/TypingIndicator/styles.js +0 -22
  181. package/lib/TypingIndicator/styles.js.map +0 -1
  182. package/lib/TypingIndicator/types.d.ts +0 -3
  183. package/lib/TypingIndicator/types.js +0 -2
  184. package/lib/TypingIndicator/types.js.map +0 -1
  185. package/lib/hooks/useUpdateLayoutEffect.d.ts +0 -8
  186. package/lib/hooks/useUpdateLayoutEffect.js +0 -17
  187. package/lib/hooks/useUpdateLayoutEffect.js.map +0 -1
  188. package/lib/index.d.ts +0 -4
  189. package/lib/index.js +0 -5
  190. package/lib/index.js.map +0 -1
  191. package/lib/logging.d.ts +0 -2
  192. package/lib/logging.js +0 -5
  193. package/lib/logging.js.map +0 -1
  194. package/lib/styles.d.ts +0 -10
  195. package/lib/styles.js +0 -11
  196. package/lib/styles.js.map +0 -1
  197. package/lib/types.d.ts +0 -67
  198. package/lib/types.js +0 -2
  199. package/lib/types.js.map +0 -1
  200. package/lib/utils.d.ts +0 -5
  201. package/lib/utils.js +0 -83
  202. package/lib/utils.js.map +0 -1
  203. package/src/__tests__/__snapshots__/MessageContainer.test.tsx.snap +0 -108
package/README.md CHANGED
@@ -85,21 +85,19 @@
85
85
 
86
86
  ## Features
87
87
 
88
- - 🎉 **_`react-native-web`able_ (since 0.10.0)** [web configuration](#react-native-web)
89
- - Write with **TypeScript** (since 0.8.0)
90
88
  - Fully customizable components
91
89
  - Composer actions (to attach photos, etc.)
92
90
  - Load earlier messages
93
91
  - Copy messages to clipboard
94
- - Touchable links using [react-native-parsed-text](https://github.com/taskrabbit/react-native-parsed-text)
92
+ - Touchable links using [react-native-autolink](https://github.com/joshswan/react-native-autolink)
95
93
  - Avatar as user's initials
96
94
  - Localized dates
97
95
  - Multi-line TextInput
98
96
  - InputToolbar avoiding keyboard
99
- - Redux support
100
97
  - System message
101
98
  - Quick Reply messages (bot)
102
99
  - Typing indicator
100
+ - react-native-web [web configuration](#react-native-web)
103
101
 
104
102
  # Getting started
105
103
 
@@ -117,18 +115,18 @@ Readme for this version: [2.6.5 readme](https://github.com/FaridSafi/react-nativ
117
115
 
118
116
  Yarn:
119
117
  ```bash
120
- yarn add react-native-gifted-chat react-native-reanimated react-native-keyboard-controller
118
+ yarn add react-native-gifted-chat react-native-reanimated react-native-keyboard-controller react-native-gesture-handler react-native-safe-area-context
121
119
  ```
122
120
 
123
121
  Npm:
124
122
 
125
123
  ```bash
126
- npm install --save react-native-gifted-chat react-native-reanimated react-native-keyboard-controller
124
+ npm install --save react-native-gifted-chat react-native-reanimated react-native-keyboard-controller react-native-gesture-handler react-native-safe-area-context
127
125
  ```
128
126
 
129
127
  Expo
130
128
  ```bash
131
- npx expo install react-native-gifted-chat react-native-reanimated react-native-keyboard-controller
129
+ npx expo install react-native-gifted-chat react-native-reanimated react-native-keyboard-controller react-native-gesture-handler react-native-safe-area-context
132
130
  ```
133
131
 
134
132
  ### Non-expo users
@@ -173,9 +171,15 @@ fireEvent(loadingWrapper, 'layout', {
173
171
  ```jsx
174
172
  import React, { useState, useCallback, useEffect } from 'react'
175
173
  import { GiftedChat } from 'react-native-gifted-chat'
174
+ import { useSafeAreaInsets } from 'react-native-safe-area-context'
176
175
 
177
176
  export function Example() {
178
177
  const [messages, setMessages] = useState([])
178
+ const insets = useSafeAreaInsets()
179
+
180
+ // If you have a tab bar, include its height
181
+ const tabbarHeight = 50
182
+ const keyboardBottomOffset = insets.bottom + tabbarHeight
179
183
 
180
184
  useEffect(() => {
181
185
  setMessages([
@@ -205,6 +209,7 @@ export function Example() {
205
209
  user={{
206
210
  _id: 1,
207
211
  }}
212
+ keyboardBottomOffset={keyboardBottomOffset}
208
213
  />
209
214
  )
210
215
  }
@@ -212,7 +217,7 @@ export function Example() {
212
217
 
213
218
  ## Advanced example
214
219
 
215
- See [`App.tsx`](https://github.com/FaridSafi/react-native-gifted-chat/blob/master/example/App.tsx) for a working demo!
220
+ See [`examples`](example) for a working demo!
216
221
 
217
222
  ## "Slack" example
218
223
 
@@ -354,10 +359,10 @@ interface QuickReplies {
354
359
  - **`textInputRef`** _(TextInput ref)_ - Ref to the text input
355
360
  - **`messages`** _(Array)_ - Messages to display
356
361
  - **`isTyping`** _(Bool)_ - Typing Indicator state; default `false`. If you use`renderFooter` it will override this.
362
+ - **`keyboardBottomOffset`** _(Integer)_ - Distance between the bottom of the screen and bottom of the `GiftedChat` component. Useful when you have a tab bar or navigation bar; default is `0`. Needed for correct keyboard avoiding behavior. Without it you might see gap between the keyboard and the input toolbar if you have a tab bar, navigation bar, or safe area.
357
363
  - **`isKeyboardInternallyHandled`** _(Bool)_ - Determine whether to handle keyboard awareness inside the plugin. If you have your own keyboard handling outside the plugin set this to false; default is `true`
358
- - **`disableKeyboardController`** _(Bool)_ - Completely disable react-native-keyboard-controller. Useful when using react-native-navigation or other conflicting keyboard libraries; default is `false`
359
364
  - **`text`** _(String)_ - Input text; default is `undefined`, but if specified, it will override GiftedChat's internal state (e.g. for redux; [see notes below](#notes-for-redux))
360
- - **`placeholder`** _(String)_ - Placeholder when `text` is empty; default is `'Type a message...'`
365
+ - **`onInputTextChanged`** _(Function)_ - Callback when the input text changes
361
366
  - **`messageIdGenerator`** _(Function)_ - Generate an id for new messages. Defaults to UUID v4, generated by [uuid](https://github.com/kelektiv/node-uuid)
362
367
  - **`user`** _(Object)_ - User sending the messages: `{ _id, name, avatar }`
363
368
  - **`onSend`** _(Function)_ - Callback when sending a message
@@ -380,8 +385,8 @@ interface QuickReplies {
380
385
  - **`renderBubble`** _(Function)_ - Custom message bubble
381
386
  - **`renderTicks`** _(Function(`message`))_ - Custom ticks indicator to display message status
382
387
  - **`renderSystemMessage`** _(Function)_ - Custom system message
383
- - **`onPress`** _(Function(`context`, `message`))_ - Callback when a message bubble is pressed
384
- - **`onLongPress`** _(Function(`context`, `message`))_ - Callback when a message bubble is long-pressed (see [example using `showActionSheetWithOptions()`](https://github.com/FaridSafi/react-native-gifted-chat/blob/master@%7B2017-09-25%7D/src/Bubble.js#L96-L119))
388
+ - **`onPressMessage`** _(Function(`context`, `message`))_ - Callback when a message bubble is pressed
389
+ - **`onLongPressMessage`** _(Function(`context`, `message`))_ - Callback when a message bubble is long-pressed (see [example using `showActionSheetWithOptions()`](https://github.com/FaridSafi/react-native-gifted-chat/blob/master@%7B2017-09-25%7D/src/Bubble.js#L96-L119))
385
390
  - **`inverted`** _(Bool)_ - Reverses display order of `messages`; default is `true`
386
391
  - **`renderUsernameOnMessage`** _(Bool)_ - Indicate whether to show the user's username inside the message bubble; default is `false`
387
392
  - **`renderUsername`** _(Function)_ - Custom Username container
@@ -389,9 +394,8 @@ interface QuickReplies {
389
394
  - **`renderMessageText`** _(Function)_ - Custom message text
390
395
  - **`renderMessageImage`** _(Function)_ - Custom message image
391
396
  - **`renderMessageVideo`** _(Function)_ - Custom message video
392
- - **`imageProps`** _(Object)_ - Extra props to be passed to the [`<Image>`](https://facebook.github.io/react-native/docs/image.html) component created by the default `renderMessageImage`
397
+ - **`imageProps`** _(Object)_ - Extra props to be passed to the [`<Image>`](https://reactnative.dev/docs/image.html) component created by the default `renderMessageImage`
393
398
  - **`videoProps`** _(Object)_ - Extra props to be passed to the video component created by the required `renderMessageVideo`
394
- - **`lightboxProps`** _(Object)_ - Extra props to be passed to the `MessageImage`'s [Lightbox](https://github.com/oblador/react-native-lightbox)
395
399
  - **`isCustomViewBottom`** _(Bool)_ - Determine whether renderCustomView is displayed before or after the text, image and video views; default is `false`
396
400
  - **`renderCustomView`** _(Function)_ - Custom view inside the bubble
397
401
  - **`renderDay`** _(Function)_ - Custom day above a message
@@ -405,27 +409,42 @@ interface QuickReplies {
405
409
  - **`renderSend`** _(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))
406
410
  - **`renderAccessory`** _(Function)_ - Custom second line of actions below the message composer
407
411
  - **`onPressActionButton`** _(Function)_ - Callback when the Action button is pressed (if set, the default `actionSheet` will not be used)
408
- - **`bottomOffset`** _(Integer)_ - Distance of the chat from the bottom of the screen (e.g. useful if you display a tab bar)
409
412
  - **`focusOnInputWhenOpeningKeyboard`** _(Bool)_ - Focus on <TextInput> automatically when opening the keyboard; default `true`
410
413
  - **`minInputToolbarHeight`** _(Integer)_ - Minimum height of the input toolbar; default is `44`
411
- - **`listViewProps`** _(Object)_ - Extra props to be passed to the messages [`<ListView>`](https://facebook.github.io/react-native/docs/listview.html); some props can't be overridden, see the code in `MessageContainer.render()` for details
412
- - **`textInputProps`** _(Object)_ - Extra props to be passed to the [`<TextInput>`](https://facebook.github.io/react-native/docs/textinput.html)
413
- - **`textInputStyle`** _(Object)_ - Custom style to be passed to the [`<TextInput>`](https://facebook.github.io/react-native/docs/textinput.html)
414
- - **`multiline`** _(Bool)_ - Indicates whether to allow the [`<TextInput>`](https://facebook.github.io/react-native/docs/textinput.html) to be multiple lines or not; default `true`.
415
- - **`keyboardShouldPersistTaps`** _(Enum)_ - Determines whether the keyboard should stay visible after a tap; see [`<ScrollView>`](https://facebook.github.io/react-native/docs/scrollview.html) docs
416
- - **`onInputTextChanged`** _(Function)_ - Callback when the input text changes
417
- - **`maxInputLength`** _(Integer)_ - Max message composer TextInput length
418
- - **`matchers`** _(Array)_ - Custom matchers for [react-native-autolink](https://github.com/joshswan/react-native-autolink) used to linking message content (like URLs and phone numbers), e.g.:
414
+ - **`listProps`** _(Object)_ - Extra props to be passed to the messages [`<FlatList>`](https://reactnative.dev/docs/flatlist.html); some props can't be overridden, see the code in `MessageContainer.render()` for details
415
+ - **`textInputProps`** _(Object)_ - props to be passed to the [`<TextInput>`](https://reactnative.dev/docs/textinput.html).
416
+ - **`messageTextProps`** _(Object)_ - Extra props to be passed to the MessageText component. Useful for customizing link parsing behavior, text styles, and matchers. Supports all [react-native-autolink](https://github.com/joshswan/react-native-autolink) props including:
417
+ - `matchers` - Custom matchers for linking message content (like URLs, phone numbers, hashtags, mentions)
418
+ - `linkStyle` - Custom style for links
419
+ - `email` - Enable/disable email parsing (default: true)
420
+ - `phone` - Enable/disable phone number parsing (default: true)
421
+ - `url` - Enable/disable URL parsing (default: true)
422
+
423
+ Example:
419
424
 
420
425
  ```js
421
- <GiftedChat
422
- matchers={[
423
- { type: 'phone', style: linkStyle, onPress: onPressPhoneNumber },
424
- { pattern: /#(\w+)/, style: [linkStyle, styles.hashtag], onPress: onPressHashtag },
425
- ]}
426
- />
426
+ <GiftedChat
427
+ messageTextProps={{
428
+ matchers: [
429
+ {
430
+ pattern: /#(\w+)/g,
431
+ style: { color: '#0084ff', fontWeight: 'bold' },
432
+ onPress: (match) => console.log('Hashtag:', match.getAnchorText()),
433
+ },
434
+ {
435
+ pattern: /(?<![\.\w])@(?!__ELEMENT-)([\w-]+)/g,
436
+ style: { color: '#0084ff', fontWeight: 'bold' },
437
+ onPress: (match) => console.log('Mention:', match.getAnchorText()),
438
+ },
439
+ ],
440
+ linkStyle: { left: { color: 'blue' }, right: { color: 'lightblue' } },
441
+ phone: false,
442
+ }}
443
+ />
427
444
  ```
428
445
 
446
+ - **`matchers`** _(Array)_ - **Deprecated:** Use `messageTextProps.matchers` instead. Custom matchers for [react-native-autolink](https://github.com/joshswan/react-native-autolink) used to linking message content (like URLs and phone numbers).
447
+
429
448
  - **`extraData`** _(Object)_ - Extra props for re-rendering FlatList on demand. This will be useful for rendering footer etc.
430
449
  - **`minComposerHeight`** _(Object)_ - Custom min-height of the composer.
431
450
  - **`maxComposerHeight`** _(Object)_ - Custom max height of the composer.
@@ -441,6 +460,7 @@ interface QuickReplies {
441
460
  * **`renderQuickReplySend`** _(Function)_ - Custom quick reply **send** view
442
461
  * **`shouldUpdateMessage`** _(Function)_ - Lets the message component know when to update outside of normal cases.
443
462
  * **`infiniteScroll`** _(Bool)_ - infinite scroll up when reach the top of messages container, automatically call onLoadEarlier function if exist (not yet supported for the web). You need to add `loadEarlier` prop too.
463
+ * **`typingIndicatorStyle`** _(StyleProp<ViewStyle>)_ - Custom style for the TypingIndicator component.
444
464
 
445
465
  ## Notes for [Redux](https://github.com/reactjs/redux)
446
466
 
@@ -474,7 +494,7 @@ If you are using Create React Native App / Expo, no Android specific installatio
474
494
 
475
495
  - For **Expo**, there are at least 2 solutions to fix it:
476
496
 
477
- - Append [`KeyboardAvoidingView`](https://facebook.github.io/react-native/docs/keyboardavoidingview) after GiftedChat. This should only be done for Android, as `KeyboardAvoidingView` may conflict with the iOS keyboard avoidance already built into GiftedChat, e.g.:
497
+ - Append [`KeyboardAvoidingView`](https://reactnative.dev/docs/keyboardavoidingview) after GiftedChat. This should only be done for Android, as `KeyboardAvoidingView` may conflict with the iOS keyboard avoidance already built into GiftedChat, e.g.:
478
498
 
479
499
  ```
480
500
  <View style={{ flex: 1 }}>
@@ -518,7 +538,7 @@ If you use React Navigation, additional handling may be required to account for
518
538
  module.exports = function override(config, env) {
519
539
  config.module.rules.push({
520
540
  test: /\.js$/,
521
- exclude: /node_modules[/\\](?!react-native-gifted-chat|react-native-lightbox|react-native-parsed-text)/,
541
+ exclude: /node_modules[/\\](?!react-native-gifted-chat)/,
522
542
  use: {
523
543
  loader: 'babel-loader',
524
544
  options: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-gifted-chat",
3
- "version": "2.8.2-alpha.0",
3
+ "version": "2.8.2-alpha.2",
4
4
  "description": "The most complete chat UI for React Native",
5
5
  "keywords": [
6
6
  "android",
@@ -23,17 +23,15 @@
23
23
  "license": "MIT",
24
24
  "author": "Farid Safi",
25
25
  "type": "module",
26
- "main": "lib/index.js",
27
- "types": "lib/index.d.ts",
26
+ "main": "src/index.ts",
27
+ "types": "src/index.ts",
28
28
  "files": [
29
- "src",
30
- "lib"
29
+ "src"
31
30
  ],
32
31
  "scripts": {
33
- "build": "rm -rf lib/ && yarn tsc",
34
32
  "lint": "yarn eslint src",
35
33
  "lint:fix": "yarn eslint --cache --fix",
36
- "prepublishOnly": "yarn lint && yarn build",
34
+ "prepublishOnly": "yarn lint && yarn test",
37
35
  "start": "cd example && expo start",
38
36
  "start:web": "cd example && expo start -w --dev",
39
37
  "test": "TZ=Europe/Paris jest --no-watchman",
@@ -46,26 +44,22 @@
46
44
  },
47
45
  "lint-staged": {
48
46
  "src/*.{json,js,jsx,ts,tsx}": [
49
- "yarn lint:fix",
50
- "bash -c 'yarn tsc:write'"
47
+ "yarn lint:fix"
51
48
  ]
52
49
  },
53
50
  "dependencies": {
54
51
  "@expo/react-native-action-sheet": "^4.1.1",
55
52
  "@types/lodash.isequal": "^4.5.8",
56
- "dayjs": "^1.11.18",
53
+ "dayjs": "^1.11.19",
57
54
  "lodash.isequal": "^4.5.0",
58
55
  "react-native-autolink": "^4.2.0",
59
- "react-native-communications": "^2.2.1",
60
- "react-native-iphone-x-helper": "^1.3.1",
61
- "react-native-lightbox-v2": "^0.9.2"
56
+ "react-native-zoom-reanimated": "^1.4.10"
62
57
  },
63
58
  "devDependencies": {
64
- "@babel/core": "^7.28.4",
59
+ "@babel/core": "^7.28.5",
65
60
  "@babel/plugin-transform-react-jsx": "^7.27.1",
66
61
  "@babel/plugin-transform-unicode-property-regex": "^7.27.1",
67
- "@babel/preset-env": "^7.28.3",
68
- "@stylistic/eslint-plugin": "^3.1.0",
62
+ "@babel/preset-env": "^7.28.5",
69
63
  "@react-native-community/cli": "20.0.0",
70
64
  "@react-native-community/cli-platform-android": "20.0.0",
71
65
  "@react-native-community/cli-platform-ios": "20.0.0",
@@ -73,24 +67,24 @@
73
67
  "@react-native/eslint-config": "0.81.5",
74
68
  "@react-native/metro-config": "0.81.5",
75
69
  "@react-native/typescript-config": "0.81.5",
70
+ "@stylistic/eslint-plugin": "^3.1.0",
71
+ "@testing-library/dom": "^10.4.1",
72
+ "@testing-library/react": "^16.3.0",
73
+ "@testing-library/react-native": "^13.3.3",
76
74
  "@types/jest": "^29.5.13",
77
- "@types/react": "^19.1.0",
78
- "@types/react-test-renderer": "^19.1.0",
79
- "@types/react-dom": "^19.1.9",
75
+ "@types/react": "^19.2.5",
76
+ "@types/react-dom": "^19.2.3",
80
77
  "@types/react-native": "^0.72.8",
81
- "@typescript-eslint/eslint-plugin": "^8.44.1",
82
- "@typescript-eslint/parser": "^8.44.1",
78
+ "@types/react-test-renderer": "^19.1.0",
79
+ "@typescript-eslint/eslint-plugin": "^8.46.4",
80
+ "@typescript-eslint/parser": "^8.46.4",
83
81
  "babel-jest": "^29.7.0",
84
- "eslint": "^8.57.0",
85
- "eslint-config-standard": "^17.1.0",
86
- "eslint-config-standard-jsx": "^11.0.0",
82
+ "eslint": "^9.18.0",
87
83
  "eslint-plugin-import": "^2.32.0",
88
84
  "eslint-plugin-jest": "^28.11.0",
89
- "eslint-plugin-json": "^4.0.1",
90
- "eslint-plugin-n": "^17.23.1",
91
- "eslint-plugin-node": "^11.1.0",
92
- "eslint-plugin-promise": "^7.2.1",
85
+ "eslint-plugin-perfectionist": "^4.15.1",
93
86
  "eslint-plugin-react": "^7.37.5",
87
+ "eslint-plugin-react-hooks": "^5.1.0",
94
88
  "husky": "^9.1.7",
95
89
  "jest": "^29.7.0",
96
90
  "json": "^11.0.0",
@@ -98,16 +92,20 @@
98
92
  "react": "19.1.0",
99
93
  "react-dom": "19.1.0",
100
94
  "react-native": "0.81.5",
95
+ "react-native-gesture-handler": "^2.29.1",
101
96
  "react-native-keyboard-controller": "^1.19.5",
102
97
  "react-native-reanimated": "^3.19.4",
98
+ "react-native-safe-area-context": "^5.6.2",
103
99
  "react-test-renderer": "19.1.0",
104
- "typescript": "^5.9.2"
100
+ "typescript": "^5.9.3"
105
101
  },
106
102
  "peerDependencies": {
107
103
  "react": ">=18.0.0",
108
104
  "react-native": "*",
105
+ "react-native-gesture-handler": ">=2.0.0",
109
106
  "react-native-keyboard-controller": ">=1.0.0",
110
- "react-native-reanimated": ">=3.0.0"
107
+ "react-native-reanimated": ">=3.0.0 || ^4.0.0",
108
+ "react-native-safe-area-context": ">=5.0.0"
111
109
  },
112
110
  "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e",
113
111
  "engines": {
package/src/Actions.tsx CHANGED
@@ -2,13 +2,13 @@ import React, { ReactNode, useCallback } from 'react'
2
2
  import {
3
3
  StyleSheet,
4
4
  Text,
5
- TouchableOpacity,
6
5
  View,
7
6
  StyleProp,
8
7
  ViewStyle,
9
8
  TextStyle,
10
9
  } from 'react-native'
11
10
  import Color from './Color'
11
+ import { TouchableOpacity } from './components/TouchableOpacity'
12
12
  import { useChatContext } from './GiftedChatContext'
13
13
 
14
14
  import stylesCommon from './styles'
package/src/Avatar.tsx CHANGED
@@ -7,8 +7,8 @@ import {
7
7
  ViewStyle,
8
8
  } from 'react-native'
9
9
  import { GiftedAvatar } from './GiftedAvatar'
10
- import { isSameUser, isSameDay } from './utils'
11
10
  import { IMessage, LeftRightStyle, User } from './types'
11
+ import { isSameUser, isSameDay } from './utils'
12
12
 
13
13
  interface Styles {
14
14
  left: {
@@ -1,24 +1,24 @@
1
1
  import React, { JSX, useCallback } from 'react'
2
2
  import {
3
3
  Text,
4
- TouchableWithoutFeedback,
4
+ Pressable,
5
5
  View,
6
6
  } from 'react-native'
7
7
 
8
8
  import { useChatContext } from '../GiftedChatContext'
9
- import { QuickReplies } from '../QuickReplies'
10
- import { MessageText } from '../MessageText'
9
+ import { MessageAudio } from '../MessageAudio'
11
10
  import { MessageImage } from '../MessageImage'
11
+ import { MessageText } from '../MessageText'
12
12
  import { MessageVideo } from '../MessageVideo'
13
- import { MessageAudio } from '../MessageAudio'
14
- import { Time } from '../Time'
13
+ import { QuickReplies } from '../QuickReplies'
14
+ import stylesCommon from '../styles'
15
15
 
16
- import { isSameUser, isSameDay } from '../utils'
16
+ import { Time } from '../Time'
17
17
  import { IMessage } from '../types'
18
- import { BubbleProps } from './types'
18
+ import { isSameUser, isSameDay } from '../utils'
19
19
 
20
- import stylesCommon from '../styles'
21
20
  import styles from './styles'
21
+ import { BubbleProps, RenderMessageTextProps } from './types'
22
22
 
23
23
  export * from './types'
24
24
 
@@ -38,22 +38,22 @@ const Bubble = <TMessage extends IMessage = IMessage>(props: BubbleProps<TMessag
38
38
  containerStyle,
39
39
  wrapperStyle,
40
40
  bottomContainerStyle,
41
- onPress: onPressProp,
42
- onLongPress: onLongPressProp,
41
+ onPressMessage: onPressMessageProp,
42
+ onLongPressMessage: onLongPressMessageProp,
43
43
  } = props
44
44
 
45
45
  const context = useChatContext()
46
46
 
47
47
  const onPress = useCallback(() => {
48
- onPressProp?.(context, currentMessage)
49
- }, [onPressProp, context, currentMessage])
48
+ onPressMessageProp?.(context, currentMessage)
49
+ }, [onPressMessageProp, context, currentMessage])
50
50
 
51
51
  const onLongPress = useCallback(() => {
52
- onLongPressProp?.(context, currentMessage)
52
+ onLongPressMessageProp?.(context, currentMessage)
53
53
  }, [
54
54
  currentMessage,
55
55
  context,
56
- onLongPressProp,
56
+ onLongPressMessageProp,
57
57
  ])
58
58
 
59
59
  const styledBubbleToNext = useCallback(() => {
@@ -142,15 +142,19 @@ const Bubble = <TMessage extends IMessage = IMessage>(props: BubbleProps<TMessag
142
142
  /* eslint-disable @typescript-eslint/no-unused-vars */
143
143
  containerStyle,
144
144
  wrapperStyle,
145
+ messageTextProps,
145
146
  /* eslint-enable @typescript-eslint/no-unused-vars */
146
- ...messageTextProps
147
+ ...messageTextPropsRest
147
148
  } = props
148
149
 
150
+ const combinedProps = { ...messageTextPropsRest, ...messageTextProps } as RenderMessageTextProps<TMessage>
151
+
149
152
  if (props.renderMessageText)
150
- return props.renderMessageText(messageTextProps)
153
+ return props.renderMessageText(combinedProps)
151
154
 
152
- return <MessageText {...messageTextProps} />
155
+ return <MessageText {...combinedProps} />
153
156
  }
157
+
154
158
  return null
155
159
  }, [props, currentMessage])
156
160
 
@@ -169,6 +173,7 @@ const Bubble = <TMessage extends IMessage = IMessage>(props: BubbleProps<TMessag
169
173
 
170
174
  return <MessageImage {...messageImageProps} />
171
175
  }
176
+
172
177
  return null
173
178
  }, [props, currentMessage])
174
179
 
@@ -349,10 +354,9 @@ const Bubble = <TMessage extends IMessage = IMessage>(props: BubbleProps<TMessag
349
354
  wrapperStyle && wrapperStyle[position],
350
355
  ]}
351
356
  >
352
- <TouchableWithoutFeedback
357
+ <Pressable
353
358
  onPress={onPress}
354
359
  onLongPress={onLongPress}
355
- accessibilityRole='text'
356
360
  {...props.touchableProps}
357
361
  >
358
362
  <View>
@@ -368,7 +372,7 @@ const Bubble = <TMessage extends IMessage = IMessage>(props: BubbleProps<TMessag
368
372
  {renderTicks()}
369
373
  </View>
370
374
  </View>
371
- </TouchableWithoutFeedback>
375
+ </Pressable>
372
376
  </View>
373
377
  {renderQuickReplies()}
374
378
  </View>
@@ -4,9 +4,9 @@ import {
4
4
  ViewStyle,
5
5
  TextStyle,
6
6
  } from 'react-native'
7
- import { QuickRepliesProps } from '../QuickReplies'
8
- import { MessageTextProps, MessageOption } from '../MessageText'
9
7
  import { MessageImageProps } from '../MessageImage'
8
+ import { MessageTextProps, MessageOption } from '../MessageText'
9
+ import { QuickRepliesProps } from '../QuickReplies'
10
10
  import { TimeProps } from '../Time'
11
11
  import {
12
12
  User,
@@ -18,7 +18,7 @@ import {
18
18
  MessageAudioProps,
19
19
  } from '../types'
20
20
 
21
- /* eslint-disable no-use-before-define */
21
+
22
22
  export type RenderMessageImageProps<TMessage extends IMessage> = Omit<
23
23
  BubbleProps<TMessage>,
24
24
  'containerStyle' | 'wrapperStyle'
@@ -42,7 +42,7 @@ export type RenderMessageTextProps<TMessage extends IMessage> = Omit<
42
42
  'containerStyle' | 'wrapperStyle' | 'options'
43
43
  > &
44
44
  MessageTextProps<TMessage>
45
- /* eslint-enable no-use-before-define */
45
+
46
46
 
47
47
  export interface BubbleProps<TMessage extends IMessage> {
48
48
  user?: User
@@ -66,8 +66,9 @@ export interface BubbleProps<TMessage extends IMessage> {
66
66
  quickReplyStyle?: StyleProp<ViewStyle>
67
67
  quickReplyTextStyle?: StyleProp<TextStyle>
68
68
  quickReplyContainerStyle?: StyleProp<ViewStyle>
69
- onPress?(context?: unknown, message?: unknown): void
70
- onLongPress?(context?: unknown, message?: unknown): void
69
+ messageTextProps?: Partial<MessageTextProps<TMessage>>
70
+ onPressMessage?(context?: unknown, message?: unknown): void
71
+ onLongPressMessage?(context?: unknown, message?: unknown): void
71
72
  onQuickReply?(replies: Reply[]): void
72
73
  renderMessageImage?(
73
74
  props: RenderMessageImageProps<TMessage>,
package/src/Composer.tsx CHANGED
@@ -6,41 +6,30 @@ import {
6
6
  TextInputProps,
7
7
  NativeSyntheticEvent,
8
8
  TextInputContentSizeChangeEventData,
9
+ useColorScheme,
9
10
  } from 'react-native'
10
- import { MIN_COMPOSER_HEIGHT, DEFAULT_PLACEHOLDER } from './Constant'
11
11
  import Color from './Color'
12
+ import { MIN_COMPOSER_HEIGHT } from './Constant'
12
13
  import stylesCommon from './styles'
13
14
 
14
15
  export interface ComposerProps {
15
16
  composerHeight?: number
16
17
  text?: string
17
- placeholder?: string
18
- placeholderTextColor?: string
19
18
  textInputProps?: Partial<TextInputProps>
20
- textInputStyle?: TextInputProps['style']
21
- textInputAutoFocus?: boolean
22
- keyboardAppearance?: TextInputProps['keyboardAppearance']
23
- multiline?: boolean
24
- disableComposer?: boolean
25
19
  onTextChanged?(text: string): void
26
20
  onInputSizeChanged?(layout: { width: number, height: number }): void
27
21
  }
28
22
 
29
23
  export function Composer ({
30
24
  composerHeight = MIN_COMPOSER_HEIGHT,
31
- disableComposer = false,
32
- keyboardAppearance = 'default',
33
- multiline = true,
34
25
  onInputSizeChanged,
35
26
  onTextChanged,
36
- placeholder = DEFAULT_PLACEHOLDER,
37
- placeholderTextColor = Color.defaultColor,
38
27
  text = '',
39
- textInputAutoFocus = false,
40
28
  textInputProps,
41
- textInputStyle,
42
29
  }: ComposerProps): React.ReactElement {
43
30
  const dimensionsRef = useRef<{ width: number, height: number }>(null)
31
+ const colorScheme = useColorScheme()
32
+ const isDark = colorScheme === 'dark'
44
33
 
45
34
  const determineInputSizeChange = useCallback(
46
35
  (dimensions: { width: number, height: number }) => {
@@ -69,21 +58,28 @@ export function Composer ({
69
58
  [determineInputSizeChange]
70
59
  )
71
60
 
61
+ const placeholder = textInputProps?.placeholder ?? 'Type a message...'
62
+
72
63
  return (
73
64
  <TextInput
74
65
  testID={placeholder}
75
66
  accessible
76
67
  accessibilityLabel={placeholder}
77
- placeholder={placeholder}
78
- placeholderTextColor={placeholderTextColor}
79
- multiline={multiline}
80
- editable={!disableComposer}
68
+ placeholderTextColor={textInputProps?.placeholderTextColor ?? (isDark ? '#888' : Color.defaultColor)}
81
69
  onContentSizeChange={handleContentSizeChange}
82
70
  onChangeText={onTextChanged}
71
+ value={text}
72
+ enablesReturnKeyAutomatically
73
+ underlineColorAndroid='transparent'
74
+ keyboardAppearance={isDark ? 'dark' : 'default'}
75
+ multiline
76
+ placeholder={placeholder}
77
+ {...textInputProps}
83
78
  style={[
84
79
  stylesCommon.fill,
85
80
  styles.textInput,
86
- textInputStyle,
81
+ styles[`textInput_${colorScheme}`],
82
+ textInputProps?.style,
87
83
  {
88
84
  height: composerHeight,
89
85
  ...Platform.select({
@@ -95,12 +91,6 @@ export function Composer ({
95
91
  }),
96
92
  },
97
93
  ]}
98
- autoFocus={textInputAutoFocus}
99
- value={text}
100
- enablesReturnKeyAutomatically
101
- underlineColorAndroid='transparent'
102
- keyboardAppearance={keyboardAppearance}
103
- {...textInputProps}
104
94
  />
105
95
  )
106
96
  }
@@ -127,4 +117,7 @@ const styles = StyleSheet.create({
127
117
  web: 4,
128
118
  }),
129
119
  },
120
+ textInput_dark: {
121
+ color: '#fff',
122
+ },
130
123
  })
package/src/Constant.ts CHANGED
@@ -7,7 +7,6 @@ export const MIN_COMPOSER_HEIGHT = Platform.select({
7
7
  windows: 34,
8
8
  })
9
9
  export const MAX_COMPOSER_HEIGHT = 200
10
- export const DEFAULT_PLACEHOLDER = 'Type a message...'
11
10
  export const DATE_FORMAT = 'D MMMM'
12
11
  export const TIME_FORMAT = 'LT'
13
12
 
package/src/Day/index.tsx CHANGED
@@ -4,15 +4,15 @@ import {
4
4
  View,
5
5
  } from 'react-native'
6
6
  import dayjs from 'dayjs'
7
- import relativeTime from 'dayjs/plugin/relativeTime'
8
7
  import calendar from 'dayjs/plugin/calendar'
8
+ import relativeTime from 'dayjs/plugin/relativeTime'
9
9
 
10
10
  import { DATE_FORMAT } from '../Constant'
11
- import { DayProps } from './types'
12
-
13
11
  import { useChatContext } from '../GiftedChatContext'
12
+
14
13
  import stylesCommon from '../styles'
15
14
  import styles from './styles'
15
+ import { DayProps } from './types'
16
16
 
17
17
  export * from './types'
18
18