stream-chat-react-native-core 9.1.3 → 9.2.0-beta.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 (466) hide show
  1. package/lib/commonjs/a11y/a11yUtils.js +40 -0
  2. package/lib/commonjs/a11y/a11yUtils.js.map +1 -0
  3. package/lib/commonjs/a11y/hooks/useA11yLabel.js +16 -0
  4. package/lib/commonjs/a11y/hooks/useA11yLabel.js.map +1 -0
  5. package/lib/commonjs/a11y/hooks/useAccessibilityActivateAction.js +25 -0
  6. package/lib/commonjs/a11y/hooks/useAccessibilityActivateAction.js.map +1 -0
  7. package/lib/commonjs/a11y/hooks/useAnnounceOnStateChange.js +36 -0
  8. package/lib/commonjs/a11y/hooks/useAnnounceOnStateChange.js.map +1 -0
  9. package/lib/commonjs/a11y/hooks/useReducedMotionPreference.js +34 -0
  10. package/lib/commonjs/a11y/hooks/useReducedMotionPreference.js.map +1 -0
  11. package/lib/commonjs/a11y/hooks/useResolvedModalAccessibilityProps.js +20 -0
  12. package/lib/commonjs/a11y/hooks/useResolvedModalAccessibilityProps.js.map +1 -0
  13. package/lib/commonjs/a11y/hooks/useScreenReaderEnabled.js +37 -0
  14. package/lib/commonjs/a11y/hooks/useScreenReaderEnabled.js.map +1 -0
  15. package/lib/commonjs/a11y/index.js +81 -0
  16. package/lib/commonjs/a11y/index.js.map +1 -0
  17. package/lib/commonjs/components/AITypingIndicatorView/AITypingIndicatorView.js +10 -0
  18. package/lib/commonjs/components/AITypingIndicatorView/AITypingIndicatorView.js.map +1 -1
  19. package/lib/commonjs/components/Accessibility/NotificationAnnouncer.js +37 -0
  20. package/lib/commonjs/components/Accessibility/NotificationAnnouncer.js.map +1 -0
  21. package/lib/commonjs/components/Accessibility/hooks/useIncomingMessageAnnouncements.js +109 -0
  22. package/lib/commonjs/components/Accessibility/hooks/useIncomingMessageAnnouncements.js.map +1 -0
  23. package/lib/commonjs/components/Accessibility/index.js +37 -0
  24. package/lib/commonjs/components/Accessibility/index.js.map +1 -0
  25. package/lib/commonjs/components/Accessibility/useAccessibilityAnnouncer.js +15 -0
  26. package/lib/commonjs/components/Accessibility/useAccessibilityAnnouncer.js.map +1 -0
  27. package/lib/commonjs/components/AttachmentPicker/AttachmentPicker.js +20 -0
  28. package/lib/commonjs/components/AttachmentPicker/AttachmentPicker.js.map +1 -1
  29. package/lib/commonjs/components/AttachmentPicker/components/AttachmentMediaPicker/AttachmentMediaPicker.js +1 -0
  30. package/lib/commonjs/components/AttachmentPicker/components/AttachmentMediaPicker/AttachmentMediaPicker.js.map +1 -1
  31. package/lib/commonjs/components/AttachmentPicker/components/AttachmentMediaPicker/AttachmentPickerItem.js +19 -2
  32. package/lib/commonjs/components/AttachmentPicker/components/AttachmentMediaPicker/AttachmentPickerItem.js.map +1 -1
  33. package/lib/commonjs/components/AttachmentPicker/components/AttachmentPickerContent.js +2 -1
  34. package/lib/commonjs/components/AttachmentPicker/components/AttachmentPickerContent.js.map +1 -1
  35. package/lib/commonjs/components/AttachmentPicker/components/AttachmentTypePickerButton.js +9 -1
  36. package/lib/commonjs/components/AttachmentPicker/components/AttachmentTypePickerButton.js.map +1 -1
  37. package/lib/commonjs/components/Channel/Channel.js +2 -1
  38. package/lib/commonjs/components/Channel/Channel.js.map +1 -1
  39. package/lib/commonjs/components/ChannelPreview/ChannelMessagePreviewDeliveryStatus.js +4 -0
  40. package/lib/commonjs/components/ChannelPreview/ChannelMessagePreviewDeliveryStatus.js.map +1 -1
  41. package/lib/commonjs/components/ImageGallery/components/ImageGalleryFooter.js +2 -2
  42. package/lib/commonjs/components/ImageGallery/components/ImageGalleryFooter.js.map +1 -1
  43. package/lib/commonjs/components/ImageGallery/components/ImageGalleryHeader.js +1 -1
  44. package/lib/commonjs/components/ImageGallery/components/ImageGalleryHeader.js.map +1 -1
  45. package/lib/commonjs/components/ImageGallery/components/ImageGalleryVideoControl.js +1 -1
  46. package/lib/commonjs/components/ImageGallery/components/ImageGalleryVideoControl.js.map +1 -1
  47. package/lib/commonjs/components/Indicators/LoadingDots.js +2 -0
  48. package/lib/commonjs/components/Indicators/LoadingDots.js.map +1 -1
  49. package/lib/commonjs/components/Indicators/LoadingErrorIndicator.js +3 -0
  50. package/lib/commonjs/components/Indicators/LoadingErrorIndicator.js.map +1 -1
  51. package/lib/commonjs/components/Indicators/LoadingIndicator.js +2 -0
  52. package/lib/commonjs/components/Indicators/LoadingIndicator.js.map +1 -1
  53. package/lib/commonjs/components/MessageInput/components/AttachmentPreview/AttachmentRemoveControl.js +16 -4
  54. package/lib/commonjs/components/MessageInput/components/AttachmentPreview/AttachmentRemoveControl.js.map +1 -1
  55. package/lib/commonjs/components/MessageInput/components/AudioRecorder/AudioRecorder.js +3 -0
  56. package/lib/commonjs/components/MessageInput/components/AudioRecorder/AudioRecorder.js.map +1 -1
  57. package/lib/commonjs/components/MessageInput/components/AudioRecorder/AudioRecordingButton.js +5 -0
  58. package/lib/commonjs/components/MessageInput/components/AudioRecorder/AudioRecordingButton.js.map +1 -1
  59. package/lib/commonjs/components/MessageInput/components/InputButtons/AttachButton.js +12 -3
  60. package/lib/commonjs/components/MessageInput/components/InputButtons/AttachButton.js.map +1 -1
  61. package/lib/commonjs/components/MessageInput/components/OutputButtons/EditButton.js +1 -0
  62. package/lib/commonjs/components/MessageInput/components/OutputButtons/EditButton.js.map +1 -1
  63. package/lib/commonjs/components/MessageInput/components/OutputButtons/SendButton.js +1 -0
  64. package/lib/commonjs/components/MessageInput/components/OutputButtons/SendButton.js.map +1 -1
  65. package/lib/commonjs/components/MessageList/MessageFlashList.js +19 -2
  66. package/lib/commonjs/components/MessageList/MessageFlashList.js.map +1 -1
  67. package/lib/commonjs/components/MessageList/MessageList.js +32 -8
  68. package/lib/commonjs/components/MessageList/MessageList.js.map +1 -1
  69. package/lib/commonjs/components/MessageList/ScrollToBottomButton.js +12 -1
  70. package/lib/commonjs/components/MessageList/ScrollToBottomButton.js.map +1 -1
  71. package/lib/commonjs/components/MessageList/UnreadMessagesNotification.js +1 -0
  72. package/lib/commonjs/components/MessageList/UnreadMessagesNotification.js.map +1 -1
  73. package/lib/commonjs/components/MessageList/hooks/useScrollToBottomAccessibilityAction.js +47 -0
  74. package/lib/commonjs/components/MessageList/hooks/useScrollToBottomAccessibilityAction.js.map +1 -0
  75. package/lib/commonjs/components/MessageMenu/MessageActionList.js +4 -1
  76. package/lib/commonjs/components/MessageMenu/MessageActionList.js.map +1 -1
  77. package/lib/commonjs/components/MessageMenu/MessageActionListItem.js +12 -3
  78. package/lib/commonjs/components/MessageMenu/MessageActionListItem.js.map +1 -1
  79. package/lib/commonjs/components/MessageMenu/MessageReactionPicker.js +2 -0
  80. package/lib/commonjs/components/MessageMenu/MessageReactionPicker.js.map +1 -1
  81. package/lib/commonjs/components/MessageMenu/ReactionButton.js +9 -1
  82. package/lib/commonjs/components/MessageMenu/ReactionButton.js.map +1 -1
  83. package/lib/commonjs/components/Poll/components/CreatePollHeader.js +2 -0
  84. package/lib/commonjs/components/Poll/components/CreatePollHeader.js.map +1 -1
  85. package/lib/commonjs/components/Poll/components/MultipleVotesSettings.js +2 -0
  86. package/lib/commonjs/components/Poll/components/MultipleVotesSettings.js.map +1 -1
  87. package/lib/commonjs/components/Poll/components/PollModalHeader.js +1 -0
  88. package/lib/commonjs/components/Poll/components/PollModalHeader.js.map +1 -1
  89. package/lib/commonjs/components/Poll/components/PollOption.js +15 -0
  90. package/lib/commonjs/components/Poll/components/PollOption.js.map +1 -1
  91. package/lib/commonjs/components/ProgressControl/ProgressControl.js +10 -0
  92. package/lib/commonjs/components/ProgressControl/ProgressControl.js.map +1 -1
  93. package/lib/commonjs/components/Reply/Reply.js +3 -0
  94. package/lib/commonjs/components/Reply/Reply.js.map +1 -1
  95. package/lib/commonjs/components/UIComponents/BottomSheetModal.js +6 -3
  96. package/lib/commonjs/components/UIComponents/BottomSheetModal.js.map +1 -1
  97. package/lib/commonjs/components/index.js +11 -0
  98. package/lib/commonjs/components/index.js.map +1 -1
  99. package/lib/commonjs/components/ui/Avatar/Avatar.js +17 -2
  100. package/lib/commonjs/components/ui/Avatar/Avatar.js.map +1 -1
  101. package/lib/commonjs/components/ui/Avatar/ChannelAvatar.js +3 -1
  102. package/lib/commonjs/components/ui/Avatar/ChannelAvatar.js.map +1 -1
  103. package/lib/commonjs/components/ui/Avatar/UserAvatar.js +1 -0
  104. package/lib/commonjs/components/ui/Avatar/UserAvatar.js.map +1 -1
  105. package/lib/commonjs/components/ui/Button/Button.js +64 -21
  106. package/lib/commonjs/components/ui/Button/Button.js.map +1 -1
  107. package/lib/commonjs/components/ui/Input/Input.js +63 -21
  108. package/lib/commonjs/components/ui/Input/Input.js.map +1 -1
  109. package/lib/commonjs/contexts/accessibilityContext/AccessibilityContext.js +134 -0
  110. package/lib/commonjs/contexts/accessibilityContext/AccessibilityContext.js.map +1 -0
  111. package/lib/commonjs/contexts/accessibilityContext/index.js +15 -0
  112. package/lib/commonjs/contexts/accessibilityContext/index.js.map +1 -0
  113. package/lib/commonjs/contexts/index.js +11 -0
  114. package/lib/commonjs/contexts/index.js.map +1 -1
  115. package/lib/commonjs/contexts/overlayContext/OverlayContext.js.map +1 -1
  116. package/lib/commonjs/contexts/overlayContext/OverlayProvider.js +19 -14
  117. package/lib/commonjs/contexts/overlayContext/OverlayProvider.js.map +1 -1
  118. package/lib/commonjs/hooks/index.js +11 -0
  119. package/lib/commonjs/hooks/index.js.map +1 -1
  120. package/lib/commonjs/i18n/en.json +57 -1
  121. package/lib/commonjs/i18n/es.json +57 -1
  122. package/lib/commonjs/i18n/fr.json +57 -1
  123. package/lib/commonjs/i18n/he.json +57 -1
  124. package/lib/commonjs/i18n/hi.json +57 -1
  125. package/lib/commonjs/i18n/it.json +57 -1
  126. package/lib/commonjs/i18n/ja.json +57 -1
  127. package/lib/commonjs/i18n/ko.json +57 -1
  128. package/lib/commonjs/i18n/nl.json +57 -1
  129. package/lib/commonjs/i18n/pt-br.json +57 -1
  130. package/lib/commonjs/i18n/ru.json +57 -1
  131. package/lib/commonjs/i18n/tr.json +57 -1
  132. package/lib/commonjs/mock-builders/DB/mock.js +3 -1
  133. package/lib/commonjs/mock-builders/DB/mock.js.map +1 -1
  134. package/lib/commonjs/test-utils/BetterSqlite.js +3 -2
  135. package/lib/commonjs/test-utils/BetterSqlite.js.map +1 -1
  136. package/lib/commonjs/version.json +1 -1
  137. package/lib/module/a11y/a11yUtils.js +40 -0
  138. package/lib/module/a11y/a11yUtils.js.map +1 -0
  139. package/lib/module/a11y/hooks/useA11yLabel.js +16 -0
  140. package/lib/module/a11y/hooks/useA11yLabel.js.map +1 -0
  141. package/lib/module/a11y/hooks/useAccessibilityActivateAction.js +25 -0
  142. package/lib/module/a11y/hooks/useAccessibilityActivateAction.js.map +1 -0
  143. package/lib/module/a11y/hooks/useAnnounceOnStateChange.js +36 -0
  144. package/lib/module/a11y/hooks/useAnnounceOnStateChange.js.map +1 -0
  145. package/lib/module/a11y/hooks/useReducedMotionPreference.js +34 -0
  146. package/lib/module/a11y/hooks/useReducedMotionPreference.js.map +1 -0
  147. package/lib/module/a11y/hooks/useResolvedModalAccessibilityProps.js +20 -0
  148. package/lib/module/a11y/hooks/useResolvedModalAccessibilityProps.js.map +1 -0
  149. package/lib/module/a11y/hooks/useScreenReaderEnabled.js +37 -0
  150. package/lib/module/a11y/hooks/useScreenReaderEnabled.js.map +1 -0
  151. package/lib/module/a11y/index.js +81 -0
  152. package/lib/module/a11y/index.js.map +1 -0
  153. package/lib/module/components/AITypingIndicatorView/AITypingIndicatorView.js +10 -0
  154. package/lib/module/components/AITypingIndicatorView/AITypingIndicatorView.js.map +1 -1
  155. package/lib/module/components/Accessibility/NotificationAnnouncer.js +37 -0
  156. package/lib/module/components/Accessibility/NotificationAnnouncer.js.map +1 -0
  157. package/lib/module/components/Accessibility/hooks/useIncomingMessageAnnouncements.js +109 -0
  158. package/lib/module/components/Accessibility/hooks/useIncomingMessageAnnouncements.js.map +1 -0
  159. package/lib/module/components/Accessibility/index.js +37 -0
  160. package/lib/module/components/Accessibility/index.js.map +1 -0
  161. package/lib/module/components/Accessibility/useAccessibilityAnnouncer.js +15 -0
  162. package/lib/module/components/Accessibility/useAccessibilityAnnouncer.js.map +1 -0
  163. package/lib/module/components/AttachmentPicker/AttachmentPicker.js +20 -0
  164. package/lib/module/components/AttachmentPicker/AttachmentPicker.js.map +1 -1
  165. package/lib/module/components/AttachmentPicker/components/AttachmentMediaPicker/AttachmentMediaPicker.js +1 -0
  166. package/lib/module/components/AttachmentPicker/components/AttachmentMediaPicker/AttachmentMediaPicker.js.map +1 -1
  167. package/lib/module/components/AttachmentPicker/components/AttachmentMediaPicker/AttachmentPickerItem.js +19 -2
  168. package/lib/module/components/AttachmentPicker/components/AttachmentMediaPicker/AttachmentPickerItem.js.map +1 -1
  169. package/lib/module/components/AttachmentPicker/components/AttachmentPickerContent.js +2 -1
  170. package/lib/module/components/AttachmentPicker/components/AttachmentPickerContent.js.map +1 -1
  171. package/lib/module/components/AttachmentPicker/components/AttachmentTypePickerButton.js +9 -1
  172. package/lib/module/components/AttachmentPicker/components/AttachmentTypePickerButton.js.map +1 -1
  173. package/lib/module/components/Channel/Channel.js +2 -1
  174. package/lib/module/components/Channel/Channel.js.map +1 -1
  175. package/lib/module/components/ChannelPreview/ChannelMessagePreviewDeliveryStatus.js +4 -0
  176. package/lib/module/components/ChannelPreview/ChannelMessagePreviewDeliveryStatus.js.map +1 -1
  177. package/lib/module/components/ImageGallery/components/ImageGalleryFooter.js +2 -2
  178. package/lib/module/components/ImageGallery/components/ImageGalleryFooter.js.map +1 -1
  179. package/lib/module/components/ImageGallery/components/ImageGalleryHeader.js +1 -1
  180. package/lib/module/components/ImageGallery/components/ImageGalleryHeader.js.map +1 -1
  181. package/lib/module/components/ImageGallery/components/ImageGalleryVideoControl.js +1 -1
  182. package/lib/module/components/ImageGallery/components/ImageGalleryVideoControl.js.map +1 -1
  183. package/lib/module/components/Indicators/LoadingDots.js +2 -0
  184. package/lib/module/components/Indicators/LoadingDots.js.map +1 -1
  185. package/lib/module/components/Indicators/LoadingErrorIndicator.js +3 -0
  186. package/lib/module/components/Indicators/LoadingErrorIndicator.js.map +1 -1
  187. package/lib/module/components/Indicators/LoadingIndicator.js +2 -0
  188. package/lib/module/components/Indicators/LoadingIndicator.js.map +1 -1
  189. package/lib/module/components/MessageInput/components/AttachmentPreview/AttachmentRemoveControl.js +16 -4
  190. package/lib/module/components/MessageInput/components/AttachmentPreview/AttachmentRemoveControl.js.map +1 -1
  191. package/lib/module/components/MessageInput/components/AudioRecorder/AudioRecorder.js +3 -0
  192. package/lib/module/components/MessageInput/components/AudioRecorder/AudioRecorder.js.map +1 -1
  193. package/lib/module/components/MessageInput/components/AudioRecorder/AudioRecordingButton.js +5 -0
  194. package/lib/module/components/MessageInput/components/AudioRecorder/AudioRecordingButton.js.map +1 -1
  195. package/lib/module/components/MessageInput/components/InputButtons/AttachButton.js +12 -3
  196. package/lib/module/components/MessageInput/components/InputButtons/AttachButton.js.map +1 -1
  197. package/lib/module/components/MessageInput/components/OutputButtons/EditButton.js +1 -0
  198. package/lib/module/components/MessageInput/components/OutputButtons/EditButton.js.map +1 -1
  199. package/lib/module/components/MessageInput/components/OutputButtons/SendButton.js +1 -0
  200. package/lib/module/components/MessageInput/components/OutputButtons/SendButton.js.map +1 -1
  201. package/lib/module/components/MessageList/MessageFlashList.js +19 -2
  202. package/lib/module/components/MessageList/MessageFlashList.js.map +1 -1
  203. package/lib/module/components/MessageList/MessageList.js +32 -8
  204. package/lib/module/components/MessageList/MessageList.js.map +1 -1
  205. package/lib/module/components/MessageList/ScrollToBottomButton.js +12 -1
  206. package/lib/module/components/MessageList/ScrollToBottomButton.js.map +1 -1
  207. package/lib/module/components/MessageList/UnreadMessagesNotification.js +1 -0
  208. package/lib/module/components/MessageList/UnreadMessagesNotification.js.map +1 -1
  209. package/lib/module/components/MessageList/hooks/useScrollToBottomAccessibilityAction.js +47 -0
  210. package/lib/module/components/MessageList/hooks/useScrollToBottomAccessibilityAction.js.map +1 -0
  211. package/lib/module/components/MessageMenu/MessageActionList.js +4 -1
  212. package/lib/module/components/MessageMenu/MessageActionList.js.map +1 -1
  213. package/lib/module/components/MessageMenu/MessageActionListItem.js +12 -3
  214. package/lib/module/components/MessageMenu/MessageActionListItem.js.map +1 -1
  215. package/lib/module/components/MessageMenu/MessageReactionPicker.js +2 -0
  216. package/lib/module/components/MessageMenu/MessageReactionPicker.js.map +1 -1
  217. package/lib/module/components/MessageMenu/ReactionButton.js +9 -1
  218. package/lib/module/components/MessageMenu/ReactionButton.js.map +1 -1
  219. package/lib/module/components/Poll/components/CreatePollHeader.js +2 -0
  220. package/lib/module/components/Poll/components/CreatePollHeader.js.map +1 -1
  221. package/lib/module/components/Poll/components/MultipleVotesSettings.js +2 -0
  222. package/lib/module/components/Poll/components/MultipleVotesSettings.js.map +1 -1
  223. package/lib/module/components/Poll/components/PollModalHeader.js +1 -0
  224. package/lib/module/components/Poll/components/PollModalHeader.js.map +1 -1
  225. package/lib/module/components/Poll/components/PollOption.js +15 -0
  226. package/lib/module/components/Poll/components/PollOption.js.map +1 -1
  227. package/lib/module/components/ProgressControl/ProgressControl.js +10 -0
  228. package/lib/module/components/ProgressControl/ProgressControl.js.map +1 -1
  229. package/lib/module/components/Reply/Reply.js +3 -0
  230. package/lib/module/components/Reply/Reply.js.map +1 -1
  231. package/lib/module/components/UIComponents/BottomSheetModal.js +6 -3
  232. package/lib/module/components/UIComponents/BottomSheetModal.js.map +1 -1
  233. package/lib/module/components/index.js +11 -0
  234. package/lib/module/components/index.js.map +1 -1
  235. package/lib/module/components/ui/Avatar/Avatar.js +17 -2
  236. package/lib/module/components/ui/Avatar/Avatar.js.map +1 -1
  237. package/lib/module/components/ui/Avatar/ChannelAvatar.js +3 -1
  238. package/lib/module/components/ui/Avatar/ChannelAvatar.js.map +1 -1
  239. package/lib/module/components/ui/Avatar/UserAvatar.js +1 -0
  240. package/lib/module/components/ui/Avatar/UserAvatar.js.map +1 -1
  241. package/lib/module/components/ui/Button/Button.js +64 -21
  242. package/lib/module/components/ui/Button/Button.js.map +1 -1
  243. package/lib/module/components/ui/Input/Input.js +63 -21
  244. package/lib/module/components/ui/Input/Input.js.map +1 -1
  245. package/lib/module/contexts/accessibilityContext/AccessibilityContext.js +134 -0
  246. package/lib/module/contexts/accessibilityContext/AccessibilityContext.js.map +1 -0
  247. package/lib/module/contexts/accessibilityContext/index.js +15 -0
  248. package/lib/module/contexts/accessibilityContext/index.js.map +1 -0
  249. package/lib/module/contexts/index.js +11 -0
  250. package/lib/module/contexts/index.js.map +1 -1
  251. package/lib/module/contexts/overlayContext/OverlayContext.js.map +1 -1
  252. package/lib/module/contexts/overlayContext/OverlayProvider.js +19 -14
  253. package/lib/module/contexts/overlayContext/OverlayProvider.js.map +1 -1
  254. package/lib/module/hooks/index.js +11 -0
  255. package/lib/module/hooks/index.js.map +1 -1
  256. package/lib/module/i18n/en.json +57 -1
  257. package/lib/module/i18n/es.json +57 -1
  258. package/lib/module/i18n/fr.json +57 -1
  259. package/lib/module/i18n/he.json +57 -1
  260. package/lib/module/i18n/hi.json +57 -1
  261. package/lib/module/i18n/it.json +57 -1
  262. package/lib/module/i18n/ja.json +57 -1
  263. package/lib/module/i18n/ko.json +57 -1
  264. package/lib/module/i18n/nl.json +57 -1
  265. package/lib/module/i18n/pt-br.json +57 -1
  266. package/lib/module/i18n/ru.json +57 -1
  267. package/lib/module/i18n/tr.json +57 -1
  268. package/lib/module/mock-builders/DB/mock.js +3 -1
  269. package/lib/module/mock-builders/DB/mock.js.map +1 -1
  270. package/lib/module/test-utils/BetterSqlite.js +3 -2
  271. package/lib/module/test-utils/BetterSqlite.js.map +1 -1
  272. package/lib/module/version.json +1 -1
  273. package/lib/typescript/a11y/a11yUtils.d.ts +31 -0
  274. package/lib/typescript/a11y/a11yUtils.d.ts.map +1 -0
  275. package/lib/typescript/a11y/hooks/useA11yLabel.d.ts +13 -0
  276. package/lib/typescript/a11y/hooks/useA11yLabel.d.ts.map +1 -0
  277. package/lib/typescript/a11y/hooks/useAccessibilityActivateAction.d.ts +17 -0
  278. package/lib/typescript/a11y/hooks/useAccessibilityActivateAction.d.ts.map +1 -0
  279. package/lib/typescript/a11y/hooks/useAnnounceOnStateChange.d.ts +14 -0
  280. package/lib/typescript/a11y/hooks/useAnnounceOnStateChange.d.ts.map +1 -0
  281. package/lib/typescript/a11y/hooks/useReducedMotionPreference.d.ts +6 -0
  282. package/lib/typescript/a11y/hooks/useReducedMotionPreference.d.ts.map +1 -0
  283. package/lib/typescript/a11y/hooks/useResolvedModalAccessibilityProps.d.ts +18 -0
  284. package/lib/typescript/a11y/hooks/useResolvedModalAccessibilityProps.d.ts.map +1 -0
  285. package/lib/typescript/a11y/hooks/useScreenReaderEnabled.d.ts +10 -0
  286. package/lib/typescript/a11y/hooks/useScreenReaderEnabled.d.ts.map +1 -0
  287. package/lib/typescript/a11y/index.d.ts +8 -0
  288. package/lib/typescript/a11y/index.d.ts.map +1 -0
  289. package/lib/typescript/components/AITypingIndicatorView/AITypingIndicatorView.d.ts.map +1 -1
  290. package/lib/typescript/components/Accessibility/NotificationAnnouncer.d.ts +12 -0
  291. package/lib/typescript/components/Accessibility/NotificationAnnouncer.d.ts.map +1 -0
  292. package/lib/typescript/components/Accessibility/hooks/useIncomingMessageAnnouncements.d.ts +20 -0
  293. package/lib/typescript/components/Accessibility/hooks/useIncomingMessageAnnouncements.d.ts.map +1 -0
  294. package/lib/typescript/components/Accessibility/index.d.ts +4 -0
  295. package/lib/typescript/components/Accessibility/index.d.ts.map +1 -0
  296. package/lib/typescript/components/Accessibility/useAccessibilityAnnouncer.d.ts +15 -0
  297. package/lib/typescript/components/Accessibility/useAccessibilityAnnouncer.d.ts.map +1 -0
  298. package/lib/typescript/components/AttachmentPicker/AttachmentPicker.d.ts.map +1 -1
  299. package/lib/typescript/components/AttachmentPicker/components/AttachmentMediaPicker/AttachmentMediaPicker.d.ts.map +1 -1
  300. package/lib/typescript/components/AttachmentPicker/components/AttachmentMediaPicker/AttachmentPickerItem.d.ts.map +1 -1
  301. package/lib/typescript/components/AttachmentPicker/components/AttachmentPickerContent.d.ts.map +1 -1
  302. package/lib/typescript/components/AttachmentPicker/components/AttachmentTypePickerButton.d.ts +2 -1
  303. package/lib/typescript/components/AttachmentPicker/components/AttachmentTypePickerButton.d.ts.map +1 -1
  304. package/lib/typescript/components/Channel/Channel.d.ts.map +1 -1
  305. package/lib/typescript/components/ChannelPreview/ChannelMessagePreviewDeliveryStatus.d.ts.map +1 -1
  306. package/lib/typescript/components/Indicators/LoadingDots.d.ts.map +1 -1
  307. package/lib/typescript/components/Indicators/LoadingErrorIndicator.d.ts.map +1 -1
  308. package/lib/typescript/components/MessageInput/components/AttachmentPreview/AttachmentRemoveControl.d.ts +5 -2
  309. package/lib/typescript/components/MessageInput/components/AttachmentPreview/AttachmentRemoveControl.d.ts.map +1 -1
  310. package/lib/typescript/components/MessageInput/components/AudioRecorder/AudioRecorder.d.ts.map +1 -1
  311. package/lib/typescript/components/MessageInput/components/AudioRecorder/AudioRecordingButton.d.ts.map +1 -1
  312. package/lib/typescript/components/MessageInput/components/InputButtons/AttachButton.d.ts +1 -0
  313. package/lib/typescript/components/MessageInput/components/InputButtons/AttachButton.d.ts.map +1 -1
  314. package/lib/typescript/components/MessageInput/components/OutputButtons/EditButton.d.ts.map +1 -1
  315. package/lib/typescript/components/MessageInput/components/OutputButtons/SendButton.d.ts.map +1 -1
  316. package/lib/typescript/components/MessageList/MessageFlashList.d.ts.map +1 -1
  317. package/lib/typescript/components/MessageList/MessageList.d.ts.map +1 -1
  318. package/lib/typescript/components/MessageList/ScrollToBottomButton.d.ts +2 -0
  319. package/lib/typescript/components/MessageList/ScrollToBottomButton.d.ts.map +1 -1
  320. package/lib/typescript/components/MessageList/UnreadMessagesNotification.d.ts.map +1 -1
  321. package/lib/typescript/components/MessageList/hooks/useScrollToBottomAccessibilityAction.d.ts +20 -0
  322. package/lib/typescript/components/MessageList/hooks/useScrollToBottomAccessibilityAction.d.ts.map +1 -0
  323. package/lib/typescript/components/MessageMenu/MessageActionList.d.ts.map +1 -1
  324. package/lib/typescript/components/MessageMenu/MessageActionListItem.d.ts.map +1 -1
  325. package/lib/typescript/components/MessageMenu/MessageReactionPicker.d.ts.map +1 -1
  326. package/lib/typescript/components/MessageMenu/ReactionButton.d.ts.map +1 -1
  327. package/lib/typescript/components/Poll/components/CreatePollHeader.d.ts.map +1 -1
  328. package/lib/typescript/components/Poll/components/MultipleVotesSettings.d.ts.map +1 -1
  329. package/lib/typescript/components/Poll/components/PollModalHeader.d.ts.map +1 -1
  330. package/lib/typescript/components/Poll/components/PollOption.d.ts.map +1 -1
  331. package/lib/typescript/components/ProgressControl/ProgressControl.d.ts.map +1 -1
  332. package/lib/typescript/components/Reply/Reply.d.ts.map +1 -1
  333. package/lib/typescript/components/UIComponents/BottomSheetModal.d.ts.map +1 -1
  334. package/lib/typescript/components/index.d.ts +1 -0
  335. package/lib/typescript/components/index.d.ts.map +1 -1
  336. package/lib/typescript/components/ui/Avatar/Avatar.d.ts +12 -1
  337. package/lib/typescript/components/ui/Avatar/Avatar.d.ts.map +1 -1
  338. package/lib/typescript/components/ui/Avatar/ChannelAvatar.d.ts.map +1 -1
  339. package/lib/typescript/components/ui/Avatar/UserAvatar.d.ts.map +1 -1
  340. package/lib/typescript/components/ui/Button/Button.d.ts +10 -1
  341. package/lib/typescript/components/ui/Button/Button.d.ts.map +1 -1
  342. package/lib/typescript/components/ui/Input/Input.d.ts.map +1 -1
  343. package/lib/typescript/contexts/accessibilityContext/AccessibilityContext.d.ts +34 -0
  344. package/lib/typescript/contexts/accessibilityContext/AccessibilityContext.d.ts.map +1 -0
  345. package/lib/typescript/contexts/accessibilityContext/index.d.ts +2 -0
  346. package/lib/typescript/contexts/accessibilityContext/index.d.ts.map +1 -0
  347. package/lib/typescript/contexts/index.d.ts +1 -0
  348. package/lib/typescript/contexts/index.d.ts.map +1 -1
  349. package/lib/typescript/contexts/overlayContext/OverlayContext.d.ts +7 -0
  350. package/lib/typescript/contexts/overlayContext/OverlayContext.d.ts.map +1 -1
  351. package/lib/typescript/contexts/overlayContext/OverlayProvider.d.ts.map +1 -1
  352. package/lib/typescript/hooks/index.d.ts +1 -0
  353. package/lib/typescript/hooks/index.d.ts.map +1 -1
  354. package/lib/typescript/hooks/useTranslatedMessage.d.ts +2 -2
  355. package/lib/typescript/i18n/en.json +57 -1
  356. package/lib/typescript/i18n/es.json +57 -1
  357. package/lib/typescript/i18n/fr.json +57 -1
  358. package/lib/typescript/i18n/he.json +57 -1
  359. package/lib/typescript/i18n/hi.json +57 -1
  360. package/lib/typescript/i18n/it.json +57 -1
  361. package/lib/typescript/i18n/ja.json +57 -1
  362. package/lib/typescript/i18n/ko.json +57 -1
  363. package/lib/typescript/i18n/nl.json +57 -1
  364. package/lib/typescript/i18n/pt-br.json +57 -1
  365. package/lib/typescript/i18n/ru.json +57 -1
  366. package/lib/typescript/i18n/tr.json +57 -1
  367. package/lib/typescript/test-utils/BetterSqlite.d.ts.map +1 -1
  368. package/lib/typescript/utils/i18n/Streami18n.d.ts +56 -0
  369. package/lib/typescript/utils/i18n/Streami18n.d.ts.map +1 -1
  370. package/package.json +1 -1
  371. package/src/__tests__/offline-support/offline-feature.tsx +40 -34
  372. package/src/a11y/__tests__/a11yUtils.test.ts +70 -0
  373. package/src/a11y/a11yUtils.ts +50 -0
  374. package/src/a11y/hooks/useA11yLabel.ts +22 -0
  375. package/src/a11y/hooks/useAccessibilityActivateAction.ts +44 -0
  376. package/src/a11y/hooks/useAnnounceOnStateChange.ts +47 -0
  377. package/src/a11y/hooks/useReducedMotionPreference.ts +38 -0
  378. package/src/a11y/hooks/useResolvedModalAccessibilityProps.ts +30 -0
  379. package/src/a11y/hooks/useScreenReaderEnabled.ts +44 -0
  380. package/src/a11y/index.ts +7 -0
  381. package/src/components/AITypingIndicatorView/AITypingIndicatorView.tsx +17 -2
  382. package/src/components/AITypingIndicatorView/__tests__/AITypingIndicatorView.test.tsx +73 -0
  383. package/src/components/Accessibility/NotificationAnnouncer.tsx +43 -0
  384. package/src/components/Accessibility/__tests__/AccessibilityAnnouncer.test.tsx +75 -0
  385. package/src/components/Accessibility/hooks/useIncomingMessageAnnouncements.ts +157 -0
  386. package/src/components/Accessibility/index.ts +3 -0
  387. package/src/components/Accessibility/useAccessibilityAnnouncer.ts +30 -0
  388. package/src/components/AttachmentPicker/AttachmentPicker.tsx +23 -1
  389. package/src/components/AttachmentPicker/components/AttachmentMediaPicker/AttachmentMediaPicker.tsx +1 -0
  390. package/src/components/AttachmentPicker/components/AttachmentMediaPicker/AttachmentPickerItem.tsx +15 -2
  391. package/src/components/AttachmentPicker/components/AttachmentPickerContent.tsx +1 -0
  392. package/src/components/AttachmentPicker/components/AttachmentTypePickerButton.tsx +9 -0
  393. package/src/components/Channel/Channel.tsx +3 -0
  394. package/src/components/ChannelList/__tests__/ChannelListView.test.tsx +16 -5
  395. package/src/components/ChannelPreview/ChannelMessagePreviewDeliveryStatus.tsx +14 -1
  396. package/src/components/ImageGallery/__tests__/ImageGalleryFooter.test.tsx +9 -3
  397. package/src/components/ImageGallery/__tests__/ImageGalleryHeader.test.tsx +4 -1
  398. package/src/components/ImageGallery/components/ImageGalleryFooter.tsx +2 -2
  399. package/src/components/ImageGallery/components/ImageGalleryHeader.tsx +1 -1
  400. package/src/components/ImageGallery/components/ImageGalleryVideoControl.tsx +1 -1
  401. package/src/components/Indicators/LoadingDots.tsx +5 -1
  402. package/src/components/Indicators/LoadingErrorIndicator.tsx +7 -1
  403. package/src/components/Indicators/LoadingIndicator.tsx +1 -1
  404. package/src/components/Message/MessageItemView/__tests__/__snapshots__/MessageAuthor.test.tsx.snap +2 -0
  405. package/src/components/MessageInput/__tests__/__snapshots__/AttachButton.test.tsx.snap +30 -15
  406. package/src/components/MessageInput/__tests__/__snapshots__/SendButton.test.tsx.snap +20 -10
  407. package/src/components/MessageInput/components/AttachmentPreview/AttachmentRemoveControl.tsx +18 -2
  408. package/src/components/MessageInput/components/AudioRecorder/AudioRecorder.tsx +3 -0
  409. package/src/components/MessageInput/components/AudioRecorder/AudioRecordingButton.tsx +8 -1
  410. package/src/components/MessageInput/components/InputButtons/AttachButton.tsx +13 -3
  411. package/src/components/MessageInput/components/OutputButtons/EditButton.tsx +1 -0
  412. package/src/components/MessageInput/components/OutputButtons/SendButton.tsx +1 -0
  413. package/src/components/MessageList/MessageFlashList.tsx +23 -2
  414. package/src/components/MessageList/MessageList.tsx +32 -2
  415. package/src/components/MessageList/ScrollToBottomButton.tsx +19 -1
  416. package/src/components/MessageList/UnreadMessagesNotification.tsx +1 -0
  417. package/src/components/MessageList/__tests__/MessageList.test.tsx +186 -0
  418. package/src/components/MessageList/__tests__/ScrollToBottomButton.test.tsx +2 -2
  419. package/src/components/MessageList/__tests__/__snapshots__/ScrollToBottomButton.test.tsx.snap +4 -1
  420. package/src/components/MessageList/__tests__/__snapshots__/TypingIndicator.test.tsx.snap +6 -0
  421. package/src/components/MessageList/hooks/useScrollToBottomAccessibilityAction.ts +74 -0
  422. package/src/components/MessageMenu/MessageActionList.tsx +4 -1
  423. package/src/components/MessageMenu/MessageActionListItem.tsx +11 -4
  424. package/src/components/MessageMenu/MessageReactionPicker.tsx +2 -0
  425. package/src/components/MessageMenu/ReactionButton.tsx +7 -1
  426. package/src/components/MessageMenu/__tests__/MessageReactionPicker.test.tsx +13 -15
  427. package/src/components/MessageMenu/__tests__/MessageUserReactions.test.tsx +20 -18
  428. package/src/components/MessageMenu/__tests__/ReactionButton.test.tsx +18 -5
  429. package/src/components/Poll/components/CreatePollHeader.tsx +2 -0
  430. package/src/components/Poll/components/MultipleVotesSettings.tsx +2 -0
  431. package/src/components/Poll/components/PollModalHeader.tsx +1 -0
  432. package/src/components/Poll/components/PollOption.tsx +11 -0
  433. package/src/components/ProgressControl/ProgressControl.tsx +8 -0
  434. package/src/components/Reply/Reply.tsx +9 -2
  435. package/src/components/Thread/__tests__/__snapshots__/Thread.test.tsx.snap +23 -6
  436. package/src/components/UIComponents/BottomSheetModal.tsx +4 -0
  437. package/src/components/index.ts +2 -0
  438. package/src/components/ui/Avatar/Avatar.tsx +24 -2
  439. package/src/components/ui/Avatar/ChannelAvatar.tsx +3 -0
  440. package/src/components/ui/Avatar/UserAvatar.tsx +1 -0
  441. package/src/components/ui/Button/Button.tsx +50 -0
  442. package/src/components/ui/Button/__tests__/Button.test.tsx +44 -0
  443. package/src/components/ui/Input/Input.tsx +35 -0
  444. package/src/contexts/accessibilityContext/AccessibilityContext.tsx +199 -0
  445. package/src/contexts/accessibilityContext/__tests__/AccessibilityContext.test.tsx +65 -0
  446. package/src/contexts/accessibilityContext/index.ts +1 -0
  447. package/src/contexts/index.ts +1 -0
  448. package/src/contexts/overlayContext/OverlayContext.tsx +7 -0
  449. package/src/contexts/overlayContext/OverlayProvider.tsx +18 -14
  450. package/src/contexts/overlayContext/__tests__/OverlayProvider.test.tsx +51 -0
  451. package/src/hooks/index.ts +1 -0
  452. package/src/i18n/en.json +57 -1
  453. package/src/i18n/es.json +57 -1
  454. package/src/i18n/fr.json +57 -1
  455. package/src/i18n/he.json +57 -1
  456. package/src/i18n/hi.json +57 -1
  457. package/src/i18n/it.json +57 -1
  458. package/src/i18n/ja.json +57 -1
  459. package/src/i18n/ko.json +57 -1
  460. package/src/i18n/nl.json +57 -1
  461. package/src/i18n/pt-br.json +57 -1
  462. package/src/i18n/ru.json +57 -1
  463. package/src/i18n/tr.json +57 -1
  464. package/src/mock-builders/DB/mock.ts +2 -1
  465. package/src/test-utils/BetterSqlite.ts +3 -1
  466. package/src/version.json +1 -1
@@ -20,6 +20,7 @@ import { channelInitialState } from '../../Channel/hooks/useChannelDataState';
20
20
  import * as MessageListPaginationHook from '../../Channel/hooks/useMessageListPagination';
21
21
  import { Chat } from '../../Chat/Chat';
22
22
 
23
+ import { SCROLL_TO_BOTTOM_ACCESSIBILITY_ACTION_NAME } from '../hooks/useScrollToBottomAccessibilityAction';
23
24
  import { MessageList } from '../MessageList';
24
25
 
25
26
  describe('MessageList', () => {
@@ -487,6 +488,49 @@ describe('MessageList pagination', () => {
487
488
  }));
488
489
  };
489
490
 
491
+ const renderMessageListForScrollToBottom = async ({
492
+ additionalFlatListProps,
493
+ accessibility = { enabled: true },
494
+ staleChannelState = false,
495
+ }: {
496
+ additionalFlatListProps?: React.ComponentProps<typeof MessageList>['additionalFlatListProps'];
497
+ accessibility?: React.ComponentProps<typeof OverlayProvider>['accessibility'];
498
+ staleChannelState?: boolean;
499
+ } = {}) => {
500
+ const user1 = generateUser();
501
+ const mockedChannel = generateChannelResponse({
502
+ members: [generateMember({ user: user1 })],
503
+ messages: Array.from({ length: 10 }, (_, i) => generateMessage({ text: `message-${i}` })),
504
+ });
505
+
506
+ const chatClient = await getTestClientWithUser({ id: 'testID' });
507
+ useMockedApis(chatClient, [getOrCreateChannelApi(mockedChannel)]);
508
+ const channel = chatClient.channel('messaging', mockedChannel.channel.id);
509
+ await channel.watch();
510
+
511
+ if (staleChannelState) {
512
+ channel.state = {
513
+ ...channelInitialState,
514
+ latestMessages: [],
515
+ members: Object.fromEntries(
516
+ Array.from({ length: 10 }, (_, i) => [i, generateMember({ user_id: String(i) })]),
517
+ ),
518
+ messages: Array.from({ length: 10 }, (_, i) => generateMessage({ id: String(i) })),
519
+ messageSets: [{ isCurrent: true, isLatest: true }],
520
+ } as unknown as typeof channel.state;
521
+ }
522
+
523
+ return render(
524
+ <OverlayProvider accessibility={accessibility}>
525
+ <Chat client={chatClient}>
526
+ <Channel channel={channel}>
527
+ <MessageList additionalFlatListProps={additionalFlatListProps} />
528
+ </Channel>
529
+ </Chat>
530
+ </OverlayProvider>,
531
+ );
532
+ };
533
+
490
534
  it('should load more recent messages when the user scrolls to the start of the list', async () => {
491
535
  const user1 = generateUser();
492
536
  const mockedChannel = generateChannelResponse({
@@ -630,4 +674,146 @@ describe('MessageList pagination', () => {
630
674
  expect(loadLatestMessages).toHaveBeenCalledTimes(1);
631
675
  });
632
676
  });
677
+
678
+ it('should not expose the scroll to bottom accessibility action when hidden', async () => {
679
+ const { getByTestId, queryByTestId } = await renderMessageListForScrollToBottom();
680
+
681
+ await waitFor(() => {
682
+ expect(queryByTestId('scroll-to-bottom-button')).toBeFalsy();
683
+ expect(getByTestId('message-flat-list').props.accessibilityActions).toBeUndefined();
684
+ });
685
+ });
686
+
687
+ it('should not expose the SDK scroll to bottom action when SDK accessibility is disabled', async () => {
688
+ const { getByTestId, queryByTestId } = await renderMessageListForScrollToBottom({
689
+ accessibility: { enabled: false },
690
+ staleChannelState: true,
691
+ });
692
+
693
+ act(() => {
694
+ fireEvent(getByTestId('message-flat-list'), 'scroll', {
695
+ nativeEvent: {
696
+ contentOffset: { y: 1900 },
697
+ contentSize: { height: 2000, width: 200 },
698
+ layoutMeasurement: { height: 400, width: 200 },
699
+ },
700
+ });
701
+ });
702
+
703
+ await waitFor(() => {
704
+ expect(queryByTestId('scroll-to-bottom-button')).toBeTruthy();
705
+ expect(getByTestId('message-flat-list').props.accessibilityActions ?? []).not.toEqual(
706
+ expect.arrayContaining([
707
+ expect.objectContaining({
708
+ name: SCROLL_TO_BOTTOM_ACCESSIBILITY_ACTION_NAME,
709
+ }),
710
+ ]),
711
+ );
712
+ });
713
+ });
714
+
715
+ it('should preserve additional message list accessibility actions when scroll to bottom is hidden', async () => {
716
+ const { getByTestId, queryByTestId } = await renderMessageListForScrollToBottom({
717
+ additionalFlatListProps: {
718
+ accessibilityActions: [{ label: 'Custom action', name: 'customAction' }],
719
+ },
720
+ });
721
+
722
+ await waitFor(() => {
723
+ expect(queryByTestId('scroll-to-bottom-button')).toBeFalsy();
724
+ expect(getByTestId('message-flat-list').props.accessibilityActions).toEqual([
725
+ { label: 'Custom action', name: 'customAction' },
726
+ ]);
727
+ });
728
+ });
729
+
730
+ it('should expose scroll to bottom as a message list accessibility action when visible', async () => {
731
+ const loadLatestMessages = jest.fn(() => Promise.resolve());
732
+ mockedHook({ loadLatestMessages });
733
+
734
+ const { getByTestId } = await renderMessageListForScrollToBottom({
735
+ staleChannelState: true,
736
+ });
737
+
738
+ act(() => {
739
+ fireEvent(getByTestId('message-flat-list'), 'scroll', {
740
+ nativeEvent: {
741
+ contentOffset: { y: 1900 },
742
+ contentSize: { height: 2000, width: 200 },
743
+ layoutMeasurement: { height: 400, width: 200 },
744
+ },
745
+ });
746
+ });
747
+
748
+ await waitFor(() => {
749
+ expect(getByTestId('message-flat-list').props.accessibilityActions).toEqual(
750
+ expect.arrayContaining([
751
+ expect.objectContaining({
752
+ label: expect.stringContaining('Scroll to bottom'),
753
+ name: SCROLL_TO_BOTTOM_ACCESSIBILITY_ACTION_NAME,
754
+ }),
755
+ ]),
756
+ );
757
+ });
758
+
759
+ await act(async () => {
760
+ await getByTestId('message-flat-list').props.onAccessibilityAction({
761
+ nativeEvent: { actionName: SCROLL_TO_BOTTOM_ACCESSIBILITY_ACTION_NAME },
762
+ });
763
+ });
764
+
765
+ expect(loadLatestMessages).toHaveBeenCalledTimes(1);
766
+ });
767
+
768
+ it('should preserve additional message list accessibility actions', async () => {
769
+ const loadLatestMessages = jest.fn(() => Promise.resolve());
770
+ const onAccessibilityAction = jest.fn();
771
+ mockedHook({ loadLatestMessages });
772
+
773
+ const { getByTestId } = await renderMessageListForScrollToBottom({
774
+ additionalFlatListProps: {
775
+ accessibilityActions: [{ label: 'Custom action', name: 'customAction' }],
776
+ onAccessibilityAction,
777
+ },
778
+ staleChannelState: true,
779
+ });
780
+
781
+ act(() => {
782
+ fireEvent(getByTestId('message-flat-list'), 'scroll', {
783
+ nativeEvent: {
784
+ contentOffset: { y: 1900 },
785
+ contentSize: { height: 2000, width: 200 },
786
+ layoutMeasurement: { height: 400, width: 200 },
787
+ },
788
+ });
789
+ });
790
+
791
+ await waitFor(() => {
792
+ expect(getByTestId('message-flat-list').props.accessibilityActions).toEqual(
793
+ expect.arrayContaining([
794
+ { label: 'Custom action', name: 'customAction' },
795
+ expect.objectContaining({
796
+ label: expect.stringContaining('Scroll to bottom'),
797
+ name: SCROLL_TO_BOTTOM_ACCESSIBILITY_ACTION_NAME,
798
+ }),
799
+ ]),
800
+ );
801
+ });
802
+
803
+ act(() => {
804
+ getByTestId('message-flat-list').props.onAccessibilityAction({
805
+ nativeEvent: { actionName: 'customAction' },
806
+ });
807
+ });
808
+ expect(onAccessibilityAction).toHaveBeenCalledTimes(1);
809
+
810
+ await act(async () => {
811
+ await getByTestId('message-flat-list').props.onAccessibilityAction({
812
+ nativeEvent: { actionName: SCROLL_TO_BOTTOM_ACCESSIBILITY_ACTION_NAME },
813
+ });
814
+ });
815
+
816
+ expect(loadLatestMessages).toHaveBeenCalledTimes(1);
817
+ expect(onAccessibilityAction).toHaveBeenCalledTimes(1);
818
+ });
633
819
  });
@@ -75,8 +75,8 @@ describe('ScrollToBottomButton', () => {
75
75
  </ThemeProvider>,
76
76
  );
77
77
  await waitFor(() => {
78
- expect(getByTestId('unread-count')).toBeTruthy();
79
- expect(getByText('3')).toBeTruthy();
78
+ expect(getByTestId('unread-count', { includeHiddenElements: true })).toBeTruthy();
79
+ expect(getByText('3', { includeHiddenElements: true })).toBeTruthy();
80
80
  });
81
81
  });
82
82
 
@@ -50,13 +50,14 @@ exports[`ScrollToBottomButton should render the message notification and match s
50
50
  }
51
51
  >
52
52
  <View
53
+ accessibilityRole="button"
53
54
  accessibilityState={
54
55
  {
55
56
  "busy": undefined,
56
57
  "checked": undefined,
57
58
  "disabled": false,
58
59
  "expanded": undefined,
59
- "selected": undefined,
60
+ "selected": false,
60
61
  }
61
62
  }
62
63
  accessibilityValue={
@@ -185,6 +186,8 @@ exports[`ScrollToBottomButton should render the message notification and match s
185
186
  </View>
186
187
  </View>
187
188
  <View
189
+ accessibilityElementsHidden={true}
190
+ importantForAccessibility="no-hide-descendants"
188
191
  style={
189
192
  {
190
193
  "position": "absolute",
@@ -87,6 +87,8 @@ exports[`TypingIndicator should match typing indicator snapshot 1`] = `
87
87
  testID="avatar-image"
88
88
  >
89
89
  <Image
90
+ accessibilityElementsHidden={true}
91
+ importantForAccessibility="no"
90
92
  onError={[Function]}
91
93
  source={
92
94
  {
@@ -147,6 +149,8 @@ exports[`TypingIndicator should match typing indicator snapshot 1`] = `
147
149
  testID="avatar-image"
148
150
  >
149
151
  <Image
152
+ accessibilityElementsHidden={true}
153
+ importantForAccessibility="no"
150
154
  onError={[Function]}
151
155
  source={
152
156
  {
@@ -186,6 +190,8 @@ exports[`TypingIndicator should match typing indicator snapshot 1`] = `
186
190
  }
187
191
  >
188
192
  <View
193
+ accessibilityElementsHidden={true}
194
+ importantForAccessibility="no-hide-descendants"
189
195
  style={
190
196
  [
191
197
  {
@@ -0,0 +1,74 @@
1
+ import { useContext, useMemo } from 'react';
2
+
3
+ import type { AccessibilityActionEvent, AccessibilityProps } from 'react-native';
4
+
5
+ import { mergeAccessibilityActions } from '../../../a11y/a11yUtils';
6
+ import { useAccessibilityContext } from '../../../contexts/accessibilityContext/AccessibilityContext';
7
+ import { TranslationContext } from '../../../contexts/translationContext/TranslationContext';
8
+ import { useStableCallback } from '../../../hooks';
9
+ import {
10
+ SCROLL_TO_BOTTOM_ACCESSIBILITY_LABEL_KEY,
11
+ SCROLL_TO_BOTTOM_WITH_COUNT_ACCESSIBILITY_LABEL_KEY,
12
+ } from '../ScrollToBottomButton';
13
+
14
+ export const SCROLL_TO_BOTTOM_ACCESSIBILITY_ACTION_NAME = 'streamScrollToBottom';
15
+
16
+ type AccessibilityActions = AccessibilityProps['accessibilityActions'];
17
+ type OnAccessibilityAction = AccessibilityProps['onAccessibilityAction'];
18
+
19
+ type UseScrollToBottomAccessibilityActionParams = {
20
+ accessibilityActions?: AccessibilityActions;
21
+ onAccessibilityAction?: OnAccessibilityAction;
22
+ onScrollToBottom: () => Promise<void> | void;
23
+ unreadCount?: number;
24
+ visible: boolean;
25
+ };
26
+
27
+ export const useScrollToBottomAccessibilityAction = ({
28
+ accessibilityActions,
29
+ onAccessibilityAction,
30
+ onScrollToBottom,
31
+ unreadCount,
32
+ visible,
33
+ }: UseScrollToBottomAccessibilityActionParams) => {
34
+ const { enabled } = useAccessibilityContext();
35
+ const { t } = useContext(TranslationContext);
36
+
37
+ const scrollToBottomAccessibilityAction = useMemo(() => {
38
+ if (!enabled || !visible) {
39
+ return undefined;
40
+ }
41
+
42
+ return [
43
+ {
44
+ name: SCROLL_TO_BOTTOM_ACCESSIBILITY_ACTION_NAME,
45
+ label: unreadCount
46
+ ? t(SCROLL_TO_BOTTOM_WITH_COUNT_ACCESSIBILITY_LABEL_KEY, { count: unreadCount })
47
+ : t(SCROLL_TO_BOTTOM_ACCESSIBILITY_LABEL_KEY),
48
+ },
49
+ ];
50
+ }, [enabled, t, unreadCount, visible]);
51
+
52
+ const mergedAccessibilityActions = useMemo(
53
+ () => mergeAccessibilityActions(accessibilityActions, scrollToBottomAccessibilityAction),
54
+ [accessibilityActions, scrollToBottomAccessibilityAction],
55
+ );
56
+
57
+ const handleAccessibilityAction = useStableCallback((event: AccessibilityActionEvent) => {
58
+ if (event.nativeEvent.actionName === SCROLL_TO_BOTTOM_ACCESSIBILITY_ACTION_NAME) {
59
+ return onScrollToBottom();
60
+ }
61
+
62
+ return onAccessibilityAction?.(event);
63
+ });
64
+
65
+ return {
66
+ accessibilityActions: mergedAccessibilityActions.length
67
+ ? mergedAccessibilityActions
68
+ : undefined,
69
+ onAccessibilityAction:
70
+ (enabled && visible) || onAccessibilityAction
71
+ ? handleAccessibilityAction
72
+ : onAccessibilityAction,
73
+ };
74
+ };
@@ -5,6 +5,7 @@ import { ScrollView } from 'react-native-gesture-handler';
5
5
 
6
6
  import { MessageActionType } from './MessageActionListItem';
7
7
 
8
+ import { useA11yLabel } from '../../a11y/hooks/useA11yLabel';
8
9
  import { useComponentsContext } from '../../contexts/componentsContext/ComponentsContext';
9
10
  import { useTheme } from '../../contexts/themeContext/ThemeContext';
10
11
  import { primitives } from '../../theme';
@@ -24,6 +25,7 @@ export type MessageActionListProps = {
24
25
  export const MessageActionList = (props: MessageActionListProps) => {
25
26
  const { messageActions } = props;
26
27
  const { MessageActionListItem } = useComponentsContext();
28
+ const a11yLabel = useA11yLabel('a11y/Message actions');
27
29
  const {
28
30
  theme: {
29
31
  messageMenu: {
@@ -43,7 +45,8 @@ export const MessageActionList = (props: MessageActionListProps) => {
43
45
 
44
46
  return (
45
47
  <ScrollView
46
- accessibilityLabel='Message action list'
48
+ accessibilityLabel={a11yLabel ?? 'Message action list'}
49
+ accessibilityRole='menu'
47
50
  contentContainerStyle={[styles.contentContainer, contentContainer]}
48
51
  style={[styles.container, container]}
49
52
  >
@@ -3,6 +3,7 @@ import { StyleProp, StyleSheet, Text, TextStyle, View } from 'react-native';
3
3
 
4
4
  import { Pressable } from 'react-native-gesture-handler';
5
5
 
6
+ import { useAccessibilityActivateAction } from '../../a11y/hooks/useAccessibilityActivateAction';
6
7
  import { useTheme } from '../../contexts/themeContext/ThemeContext';
7
8
  import { useStableCallback } from '../../hooks';
8
9
  import { closeOverlay, scheduleActionOnClose } from '../../state-store';
@@ -74,19 +75,25 @@ export const MessageActionListItem = (props: MessageActionListItemProps) => {
74
75
  closeOverlay();
75
76
  scheduleActionOnClose(() => action());
76
77
  });
78
+ const accessibilityLabel = `${actionType} action list item`;
79
+ const accessibilityActivateActionProps = useAccessibilityActivateAction({
80
+ onPress: onActionPress,
81
+ shouldHandleActivate: true,
82
+ });
77
83
 
78
84
  return (
79
85
  <Pressable
86
+ accessible
87
+ accessibilityLabel={accessibilityLabel}
88
+ accessibilityRole='menuitem'
89
+ {...accessibilityActivateActionProps}
80
90
  onPress={onActionPress}
81
91
  style={({ pressed }) => [
82
92
  styles.buttonContainer,
83
93
  { backgroundColor: pressed ? semantics.backgroundUtilityPressed : 'transparent' },
84
94
  ]}
85
95
  >
86
- <View
87
- accessibilityLabel={`${actionType} action list item`}
88
- style={[styles.container, container]}
89
- >
96
+ <View style={[styles.container, container]}>
90
97
  <View style={iconTheme}>{icon}</View>
91
98
  <Text style={[styles.titleStyle, titleStyle, titleTheme]}>{title}</Text>
92
99
  </View>
@@ -115,6 +115,7 @@ export const EmojiViewerButton = ({
115
115
  <>
116
116
  <View style={[styles.emojiViewerButton, emojiViewerButton]}>
117
117
  <Button
118
+ accessibilityLabelKey='a11y/Open more reactions'
118
119
  variant='secondary'
119
120
  type='outline'
120
121
  size='sm'
@@ -163,6 +164,7 @@ export const MessageReactionPicker = (props: MessageReactionPickerProps) => {
163
164
  return (
164
165
  <View
165
166
  accessibilityLabel='Reaction Selector on long pressing message'
167
+ accessibilityRole='menu'
166
168
  style={[styles.container, container]}
167
169
  >
168
170
  <MessageReactionPickerList onSelectReaction={onSelectReaction} />
@@ -49,11 +49,17 @@ export const ReactionButton = (props: ReactionButtonProps) => {
49
49
  () => <Icon size={reactionIconSize ?? 24} />,
50
50
  [Icon, reactionIconSize],
51
51
  );
52
+ const selectedLabelState = selected ? 'selected' : 'unselected';
53
+ const accessibilityLabelParams = useMemo(
54
+ () => ({ selected: selectedLabelState, type }),
55
+ [selectedLabelState, type],
56
+ );
52
57
 
53
58
  return (
54
59
  <View style={styles.reactionButton}>
55
60
  <Button
56
- accessibilityLabel={`reaction-button-${type}-${selected ? 'selected' : 'unselected'}`}
61
+ accessibilityLabelKey='a11y/reaction-button-{{type}}-{{selected}}'
62
+ accessibilityLabelParams={accessibilityLabelParams}
57
63
  variant={'secondary'}
58
64
  type={'outline'}
59
65
  iconOnly={!count}
@@ -80,12 +80,10 @@ describe('MessageReactionPicker', () => {
80
80
  });
81
81
 
82
82
  it('renders correctly with supported reactions', async () => {
83
- const { getAllByLabelText, getByLabelText } = renderComponent();
83
+ const { getAllByRole, getByLabelText } = renderComponent();
84
84
  await waitFor(() => {
85
85
  expect(getByLabelText('Reaction Selector on long pressing message')).toBeTruthy();
86
- expect(getAllByLabelText(/\breaction-button[^\s]+/)).toHaveLength(
87
- mockSupportedReactions.length,
88
- );
86
+ expect(getAllByRole('button')).toHaveLength(mockSupportedReactions.length + 1);
89
87
  });
90
88
  });
91
89
 
@@ -95,20 +93,20 @@ describe('MessageReactionPicker', () => {
95
93
  });
96
94
 
97
95
  it('marks own reactions as selected', async () => {
98
- const { getAllByLabelText } = renderComponent();
96
+ const { getAllByRole } = renderComponent();
99
97
 
100
98
  await waitFor(() => {
101
- const reactionButtons = getAllByLabelText(/\breaction-button[^\s]+/);
102
- expect(reactionButtons[0].props.accessibilityLabel).toBe('reaction-button-like-selected');
103
- expect(reactionButtons[1].props.accessibilityLabel).toBe('reaction-button-love-unselected');
99
+ const reactionButtons = getAllByRole('button');
100
+ expect(reactionButtons[0].props.accessibilityState.selected).toBe(true);
101
+ expect(reactionButtons[1].props.accessibilityState.selected).toBe(false);
104
102
  });
105
103
  });
106
104
 
107
105
  it('calls handleReaction and dismissOverlay when a reaction is pressed', async () => {
108
- const { getAllByLabelText } = renderComponent();
106
+ const { getAllByRole } = renderComponent();
109
107
 
110
108
  await waitFor(() => {
111
- const reactionButtons = getAllByLabelText(/\breaction-button[^\s]+/);
109
+ const reactionButtons = getAllByRole('button');
112
110
  fireEvent.press(reactionButtons[1]);
113
111
  expect(defaultProps.handleReaction).toHaveBeenCalledWith('love');
114
112
  expect(defaultProps.dismissOverlay).toHaveBeenCalled();
@@ -117,9 +115,9 @@ describe('MessageReactionPicker', () => {
117
115
  });
118
116
 
119
117
  it("doesn't call handleReaction when it's not provided", async () => {
120
- const { getAllByLabelText } = renderComponent({ handleReaction: undefined });
118
+ const { getAllByRole } = renderComponent({ handleReaction: undefined });
121
119
  await waitFor(() => {
122
- const reactionButtons = getAllByLabelText(/\breaction-button[^\s]+/);
120
+ const reactionButtons = getAllByRole('button');
123
121
 
124
122
  fireEvent.press(reactionButtons[1]);
125
123
 
@@ -132,11 +130,11 @@ describe('MessageReactionPicker', () => {
132
130
  { Icon: () => null, isMain: true, type: 'wow' },
133
131
  { Icon: () => null, isMain: true, type: 'haha' },
134
132
  ];
135
- const { getAllByLabelText } = renderComponent({ supportedReactions: customSupportedReactions });
133
+ const { getAllByRole } = renderComponent({ supportedReactions: customSupportedReactions });
136
134
 
137
135
  await waitFor(() => {
138
- const reactionButtons = getAllByLabelText(/\breaction-button[^\s]+/);
139
- expect(reactionButtons).toHaveLength(customSupportedReactions.length);
136
+ const reactionButtons = getAllByRole('button');
137
+ expect(reactionButtons).toHaveLength(customSupportedReactions.length + 1);
140
138
  });
141
139
  });
142
140
  });
@@ -2,6 +2,8 @@ import React from 'react';
2
2
 
3
3
  import { Text } from 'react-native';
4
4
 
5
+ import type { ReactTestInstance } from 'react-test-renderer';
6
+
5
7
  import { fireEvent, render } from '@testing-library/react-native';
6
8
 
7
9
  import { ReactionResponse } from 'stream-chat';
@@ -39,6 +41,9 @@ const defaultProps = {
39
41
  supportedReactions: mockSupportedReactions,
40
42
  };
41
43
 
44
+ const filterReactionButtons = (buttons: ReactTestInstance[]) =>
45
+ buttons.filter((button) => button.props.accessibilityLabel !== 'more-reactions-button');
46
+
42
47
  const renderComponent = (props = {}) =>
43
48
  render(
44
49
  <ThemeProvider theme={defaultTheme}>
@@ -87,35 +92,32 @@ describe('MessageUserReactions when the supportedReactions are defined', () => {
87
92
  });
88
93
 
89
94
  it('renders reaction buttons', () => {
90
- const { getByLabelText } = renderComponent();
91
- const likeReactionButton = getByLabelText('reaction-button-like-unselected');
92
- expect(likeReactionButton).toBeDefined();
93
- const loveReactionButton = getByLabelText('reaction-button-love-unselected');
94
- expect(loveReactionButton).toBeDefined();
95
+ const { getAllByRole } = renderComponent();
96
+ expect(filterReactionButtons(getAllByRole('button'))).toHaveLength(2);
95
97
  });
96
98
 
97
99
  it('starts with no reaction filter selected by default', () => {
98
- const { getAllByLabelText } = renderComponent();
99
- const reactionButtons = getAllByLabelText(/\breaction-button[^\s]+/);
100
- expect(reactionButtons[0].props.accessibilityLabel).toBe('reaction-button-like-unselected');
101
- expect(reactionButtons[1].props.accessibilityLabel).toBe('reaction-button-love-unselected');
100
+ const { getAllByRole } = renderComponent();
101
+ const reactionButtons = filterReactionButtons(getAllByRole('button'));
102
+ expect(reactionButtons[0].props.accessibilityState.selected).toBe(false);
103
+ expect(reactionButtons[1].props.accessibilityState.selected).toBe(false);
102
104
  });
103
105
 
104
106
  it('toggles the selected reaction when a reaction button is pressed twice', () => {
105
- const { getAllByLabelText } = renderComponent();
106
- let reactionButtons = getAllByLabelText(/\breaction-button[^\s]+/);
107
+ const { getAllByRole } = renderComponent();
108
+ let reactionButtons = filterReactionButtons(getAllByRole('button'));
107
109
 
108
110
  fireEvent.press(reactionButtons[1]);
109
111
 
110
- expect(reactionButtons[0].props.accessibilityLabel).toBe('reaction-button-like-unselected');
111
- expect(reactionButtons[1].props.accessibilityLabel).toBe('reaction-button-love-selected');
112
+ expect(reactionButtons[0].props.accessibilityState.selected).toBe(false);
113
+ expect(reactionButtons[1].props.accessibilityState.selected).toBe(true);
112
114
 
113
115
  fireEvent.press(reactionButtons[1]);
114
116
 
115
- reactionButtons = getAllByLabelText(/\breaction-button[^\s]+/);
117
+ reactionButtons = filterReactionButtons(getAllByRole('button'));
116
118
 
117
- expect(reactionButtons[0].props.accessibilityLabel).toBe('reaction-button-like-unselected');
118
- expect(reactionButtons[1].props.accessibilityLabel).toBe('reaction-button-love-unselected');
119
+ expect(reactionButtons[0].props.accessibilityState.selected).toBe(false);
120
+ expect(reactionButtons[1].props.accessibilityState.selected).toBe(false);
119
121
  });
120
122
 
121
123
  it('renders reactions list', () => {
@@ -133,10 +135,10 @@ describe('MessageUserReactions when the supportedReactions are defined', () => {
133
135
  });
134
136
 
135
137
  it("don't render reaction buttons that is of unsupported type", () => {
136
- const { queryAllByLabelText } = renderComponent({
138
+ const { queryAllByRole } = renderComponent({
137
139
  message: { ...generateMessage(), reaction_groups: { money: 1 } },
138
140
  });
139
- const reactionButtons = queryAllByLabelText(/\breaction-button[^\s]+/);
141
+ const reactionButtons = filterReactionButtons(queryAllByRole('button'));
140
142
 
141
143
  expect(reactionButtons.length).toBe(0);
142
144
  });
@@ -2,8 +2,9 @@ import React from 'react';
2
2
 
3
3
  import { Text } from 'react-native';
4
4
 
5
- import { cleanup, fireEvent, render } from '@testing-library/react-native';
5
+ import { cleanup, fireEvent, render, screen, waitFor } from '@testing-library/react-native';
6
6
 
7
+ import { OverlayProvider } from '../../../contexts/overlayContext/OverlayProvider';
7
8
  import { ThemeProvider } from '../../../contexts/themeContext/ThemeContext';
8
9
  import { defaultTheme } from '../../../contexts/themeContext/utils/theme';
9
10
  import { IconProps } from '../../../icons';
@@ -37,28 +38,40 @@ describe('ReactionButton', () => {
37
38
  expect(getByText('24')).toBeTruthy();
38
39
  });
39
40
 
41
+ it('uses the released reaction button label when accessibility labels are translated', async () => {
42
+ render(
43
+ <OverlayProvider accessibility={{ enabled: true }}>
44
+ <ReactionButton {...defaultProps} />
45
+ </OverlayProvider>,
46
+ );
47
+
48
+ await waitFor(() => {
49
+ expect(screen.getByLabelText('reaction-button-like-unselected')).toBeTruthy();
50
+ });
51
+ });
52
+
40
53
  it('should call onPress function with the correct reaction type when pressed', () => {
41
- const { getByLabelText } = render(
54
+ const { getByRole } = render(
42
55
  <ThemeProvider theme={defaultTheme}>
43
56
  <ReactionButton {...defaultProps} />
44
57
  </ThemeProvider>,
45
58
  );
46
59
 
47
60
  // Simulate a press event
48
- fireEvent.press(getByLabelText('reaction-button-like-unselected'));
61
+ fireEvent.press(getByRole('button'));
49
62
 
50
63
  // Verify if the mock function has been called with the correct reaction type
51
64
  expect(mockOnPress).toHaveBeenCalledWith('like');
52
65
  });
53
66
 
54
67
  it('should not call onPress when the onPress prop is not provided', () => {
55
- const { getByLabelText } = render(
68
+ const { getByRole } = render(
56
69
  <ThemeProvider theme={defaultTheme}>
57
70
  <ReactionButton {...defaultProps} onPress={undefined} />
58
71
  </ThemeProvider>,
59
72
  );
60
73
 
61
- fireEvent.press(getByLabelText('reaction-button-like-unselected'));
74
+ fireEvent.press(getByRole('button'));
62
75
 
63
76
  expect(mockOnPress).not.toHaveBeenCalled();
64
77
  });
@@ -51,6 +51,7 @@ export const CreatePollHeader = ({
51
51
  return (
52
52
  <View style={[styles.headerContainer, headerContainer]}>
53
53
  <Button
54
+ accessibilityLabelKey='a11y/Close poll creation'
54
55
  variant='secondary'
55
56
  onPress={onBackPressHandler}
56
57
  type='solid'
@@ -63,6 +64,7 @@ export const CreatePollHeader = ({
63
64
  </Text>
64
65
 
65
66
  <Button
67
+ accessibilityLabelKey='a11y/Create poll'
66
68
  variant='primary'
67
69
  onPress={onCreatePollPressHandler}
68
70
  type='solid'