stream-chat-react 12.9.0 → 12.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (207) hide show
  1. package/dist/components/Attachment/Attachment.js +2 -1
  2. package/dist/components/Attachment/AttachmentContainer.d.ts +1 -1
  3. package/dist/components/Attachment/AttachmentContainer.js +2 -2
  4. package/dist/components/Attachment/Card.js +3 -3
  5. package/dist/components/Attachment/VoiceRecording.d.ts +1 -1
  6. package/dist/components/Attachment/VoiceRecording.js +2 -2
  7. package/dist/components/Attachment/attachment-sizing.js +2 -1
  8. package/dist/components/Attachment/components/FileSizeIndicator.d.ts +1 -1
  9. package/dist/components/Attachment/components/FileSizeIndicator.js +1 -1
  10. package/dist/components/Attachment/components/WaveProgressBar.js +1 -1
  11. package/dist/components/Attachment/hooks/useAudioController.d.ts +1 -1
  12. package/dist/components/Attachment/hooks/useAudioController.js +4 -2
  13. package/dist/components/Attachment/utils.d.ts +1 -1
  14. package/dist/components/Attachment/utils.js +12 -3
  15. package/dist/components/AutoCompleteTextarea/List.js +3 -2
  16. package/dist/components/AutoCompleteTextarea/Textarea.js +3 -7
  17. package/dist/components/AutoCompleteTextarea/utils.js +3 -7
  18. package/dist/components/Avatar/ChannelAvatar.js +1 -1
  19. package/dist/components/Channel/Channel.d.ts +1 -1
  20. package/dist/components/Channel/Channel.js +30 -14
  21. package/dist/components/Channel/channelState.d.ts +1 -3
  22. package/dist/components/Channel/channelState.js +10 -4
  23. package/dist/components/Channel/hooks/useCreateChannelStateContext.js +5 -3
  24. package/dist/components/Channel/hooks/useIsMounted.d.ts +1 -1
  25. package/dist/components/Channel/hooks/useMentionsHandlers.js +5 -2
  26. package/dist/components/Channel/utils.js +2 -1
  27. package/dist/components/ChannelHeader/ChannelHeader.js +1 -1
  28. package/dist/components/ChannelList/ChannelList.js +13 -8
  29. package/dist/components/ChannelList/hooks/useChannelListShape.d.ts +2 -2
  30. package/dist/components/ChannelList/hooks/useChannelListShape.js +46 -19
  31. package/dist/components/ChannelList/hooks/useChannelUpdatedListener.js +2 -1
  32. package/dist/components/ChannelList/hooks/useMessageNewListener.js +3 -1
  33. package/dist/components/ChannelList/hooks/useMobileNavigation.d.ts +1 -1
  34. package/dist/components/ChannelList/hooks/usePaginatedChannels.js +5 -3
  35. package/dist/components/ChannelList/hooks/useSelectedChannelState.js +1 -1
  36. package/dist/components/ChannelPreview/ChannelPreview.js +2 -2
  37. package/dist/components/ChannelPreview/ChannelPreviewMessenger.js +1 -1
  38. package/dist/components/ChannelPreview/icons.js +0 -1
  39. package/dist/components/ChannelPreview/utils.js +3 -3
  40. package/dist/components/ChannelSearch/ChannelSearch.js +5 -3
  41. package/dist/components/ChannelSearch/SearchBar.d.ts +1 -1
  42. package/dist/components/ChannelSearch/SearchInput.d.ts +1 -1
  43. package/dist/components/ChannelSearch/SearchResults.js +1 -1
  44. package/dist/components/ChannelSearch/hooks/useChannelSearch.d.ts +4 -2
  45. package/dist/components/ChannelSearch/hooks/useChannelSearch.js +61 -36
  46. package/dist/components/ChannelSearch/index.d.ts +1 -1
  47. package/dist/components/Chat/hooks/useChat.js +4 -2
  48. package/dist/components/Chat/hooks/useCreateChatClient.js +3 -1
  49. package/dist/components/ChatAutoComplete/ChatAutoComplete.js +1 -1
  50. package/dist/components/ChatView/ChatView.js +0 -1
  51. package/dist/components/Dialog/PromptDialog.d.ts +1 -1
  52. package/dist/components/Dialog/PromptDialog.js +1 -1
  53. package/dist/components/EventComponent/EventComponent.js +1 -1
  54. package/dist/components/Gallery/BaseImage.d.ts +1 -3
  55. package/dist/components/Gallery/Gallery.js +10 -2
  56. package/dist/components/Gallery/Image.js +1 -1
  57. package/dist/components/Gallery/ModalGallery.js +4 -4
  58. package/dist/components/InfiniteScrollPaginator/InfiniteScroll.js +9 -6
  59. package/dist/components/InfiniteScrollPaginator/InfiniteScrollPaginator.js +1 -1
  60. package/dist/components/LoadMore/LoadMorePaginator.js +1 -1
  61. package/dist/components/MML/MML.js +1 -0
  62. package/dist/components/MediaRecorder/transcode/wav.js +6 -3
  63. package/dist/components/Message/FixedHeightMessage.js +6 -8
  64. package/dist/components/Message/Message.js +2 -1
  65. package/dist/components/Message/MessageEditedTimestamp.js +1 -1
  66. package/dist/components/Message/MessageSimple.js +2 -5
  67. package/dist/components/Message/MessageStatus.js +1 -1
  68. package/dist/components/Message/MessageText.js +7 -7
  69. package/dist/components/Message/QuotedMessage.js +2 -2
  70. package/dist/components/Message/Timestamp.js +9 -1
  71. package/dist/components/Message/hooks/useActionHandler.js +1 -1
  72. package/dist/components/Message/hooks/useFlagHandler.js +2 -1
  73. package/dist/components/Message/hooks/useMarkUnreadHandler.js +2 -1
  74. package/dist/components/Message/hooks/useMessageTextStreaming.d.ts +1 -1
  75. package/dist/components/Message/hooks/useMessageTextStreaming.js +1 -1
  76. package/dist/components/Message/hooks/useMuteHandler.js +7 -4
  77. package/dist/components/Message/hooks/usePinHandler.js +1 -1
  78. package/dist/components/Message/hooks/useReactionHandler.js +10 -5
  79. package/dist/components/Message/hooks/useRetryHandler.js +1 -1
  80. package/dist/components/Message/hooks/useUserRole.js +1 -1
  81. package/dist/components/Message/renderText/renderText.js +2 -2
  82. package/dist/components/Message/utils.js +3 -3
  83. package/dist/components/MessageActions/MessageActionsBox.js +7 -3
  84. package/dist/components/MessageActions/hooks/useMessageActionsBoxPopper.d.ts +1 -1
  85. package/dist/components/MessageInput/AttachmentPreviewList/AttachmentPreviewList.js +1 -1
  86. package/dist/components/MessageInput/AttachmentPreviewList/FileAttachmentPreview.js +4 -2
  87. package/dist/components/MessageInput/AttachmentPreviewList/UnsupportedAttachmentPreview.js +4 -2
  88. package/dist/components/MessageInput/AttachmentSelector.js +1 -1
  89. package/dist/components/MessageInput/DefaultTriggerProvider.js +1 -1
  90. package/dist/components/MessageInput/DropzoneProvider.js +1 -1
  91. package/dist/components/MessageInput/MessageInput.js +1 -1
  92. package/dist/components/MessageInput/MessageInputFlat.js +4 -3
  93. package/dist/components/MessageInput/QuotedMessagePreview.js +1 -1
  94. package/dist/components/MessageInput/hooks/useAttachments.js +12 -4
  95. package/dist/components/MessageInput/hooks/useLinkPreviews.js +3 -1
  96. package/dist/components/MessageInput/hooks/useMessageInputState.js +4 -3
  97. package/dist/components/MessageInput/hooks/useMessageInputText.d.ts +1 -1
  98. package/dist/components/MessageInput/hooks/useMessageInputText.js +5 -3
  99. package/dist/components/MessageInput/hooks/useSubmitHandler.js +5 -3
  100. package/dist/components/MessageInput/hooks/useTimeElapsed.js +1 -1
  101. package/dist/components/MessageInput/hooks/useUserTrigger.js +2 -2
  102. package/dist/components/MessageInput/hooks/utils.js +6 -2
  103. package/dist/components/MessageList/ConnectionStatus.js +1 -1
  104. package/dist/components/MessageList/MessageList.js +5 -6
  105. package/dist/components/MessageList/MessageListNotifications.js +3 -1
  106. package/dist/components/MessageList/VirtualizedMessageList.d.ts +1 -1
  107. package/dist/components/MessageList/VirtualizedMessageList.js +19 -12
  108. package/dist/components/MessageList/VirtualizedMessageListComponents.js +2 -2
  109. package/dist/components/MessageList/hooks/MessageList/useMessageListElements.js +1 -3
  110. package/dist/components/MessageList/hooks/MessageList/useMessageListScrollManager.js +3 -2
  111. package/dist/components/MessageList/hooks/MessageList/useScrollLocationLogic.js +3 -2
  112. package/dist/components/MessageList/hooks/MessageList/useUnreadMessagesNotification.js +6 -2
  113. package/dist/components/MessageList/hooks/VirtualizedMessageList/useMessageSetKey.js +1 -1
  114. package/dist/components/MessageList/hooks/VirtualizedMessageList/useNewMessageNotification.d.ts +1 -1
  115. package/dist/components/MessageList/hooks/VirtualizedMessageList/usePrependMessagesCount.js +4 -3
  116. package/dist/components/MessageList/hooks/VirtualizedMessageList/useScrollToBottomOnNewMessage.js +1 -1
  117. package/dist/components/MessageList/hooks/VirtualizedMessageList/useUnreadMessagesNotificationVirtualized.js +7 -3
  118. package/dist/components/MessageList/hooks/useMarkRead.d.ts +2 -4
  119. package/dist/components/MessageList/hooks/useMarkRead.js +14 -16
  120. package/dist/components/MessageList/utils.js +28 -11
  121. package/dist/components/Modal/Modal.d.ts +1 -1
  122. package/dist/components/Modal/Modal.js +1 -1
  123. package/dist/components/Modal/ModalHeader.js +1 -1
  124. package/dist/components/Poll/Poll.js +1 -1
  125. package/dist/components/Poll/PollActions/PollActions.js +6 -4
  126. package/dist/components/Poll/PollActions/PollAnswerList.js +1 -1
  127. package/dist/components/Poll/PollActions/PollResults/PollOptionVotesList.js +1 -1
  128. package/dist/components/Poll/PollActions/PollResults/PollOptionWithLatestVotes.js +4 -2
  129. package/dist/components/Poll/PollActions/PollResults/PollResults.js +2 -1
  130. package/dist/components/Poll/PollContent.js +1 -1
  131. package/dist/components/Poll/PollCreationDialog/OptionFieldSet.d.ts +1 -1
  132. package/dist/components/Poll/PollCreationDialog/OptionFieldSet.js +11 -4
  133. package/dist/components/Poll/PollCreationDialog/PollCreationDialog.js +13 -4
  134. package/dist/components/Poll/PollCreationDialog/PollCreationDialogControls.js +6 -3
  135. package/dist/components/Poll/PollOptionList.js +1 -1
  136. package/dist/components/Poll/PollOptionSelector.js +12 -5
  137. package/dist/components/Poll/hooks/useManagePollVotesRealtime.js +9 -4
  138. package/dist/components/Poll/hooks/usePollAnswerPagination.js +8 -2
  139. package/dist/components/Poll/hooks/usePollOptionVotesPagination.js +8 -2
  140. package/dist/components/ReactFileUtilities/FileIcon/mimeTypes.d.ts +1 -1
  141. package/dist/components/ReactFileUtilities/ImageDropzone.js +3 -1
  142. package/dist/components/ReactFileUtilities/UploadButton.js +1 -1
  143. package/dist/components/ReactFileUtilities/utils.js +3 -1
  144. package/dist/components/Reactions/ReactionSelector.js +3 -1
  145. package/dist/components/Reactions/ReactionSelectorWithButton.js +1 -1
  146. package/dist/components/Reactions/ReactionsList.d.ts +2 -2
  147. package/dist/components/Reactions/ReactionsList.js +7 -4
  148. package/dist/components/Reactions/ReactionsListModal.d.ts +1 -2
  149. package/dist/components/Reactions/ReactionsListModal.js +1 -1
  150. package/dist/components/Reactions/SpriteImage.js +6 -2
  151. package/dist/components/Reactions/hooks/useFetchReactions.js +1 -1
  152. package/dist/components/Reactions/hooks/useProcessReactions.js +1 -1
  153. package/dist/components/Reactions/index.d.ts +1 -0
  154. package/dist/components/Reactions/index.js +1 -0
  155. package/dist/components/Reactions/reactionOptions.js +20 -5
  156. package/dist/components/Thread/Thread.js +4 -3
  157. package/dist/components/Threads/ThreadContext.d.ts +1 -1
  158. package/dist/components/Threads/ThreadContext.js +1 -1
  159. package/dist/components/Threads/ThreadList/ThreadList.js +1 -1
  160. package/dist/components/Threads/ThreadList/ThreadListItem.d.ts +1 -1
  161. package/dist/components/Threads/ThreadList/ThreadListItem.js +1 -1
  162. package/dist/components/Threads/ThreadList/ThreadListItemUI.js +5 -3
  163. package/dist/components/Threads/icons.js +0 -1
  164. package/dist/components/Tooltip/Tooltip.d.ts +1 -1
  165. package/dist/components/Tooltip/Tooltip.js +1 -1
  166. package/dist/context/ComponentContext.d.ts +3 -1
  167. package/dist/context/ComponentContext.js +1 -1
  168. package/dist/context/DialogManagerContext.d.ts +1 -1
  169. package/dist/context/DialogManagerContext.js +1 -1
  170. package/dist/context/MessageBounceContext.js +2 -2
  171. package/dist/context/MessageContext.js +1 -1
  172. package/dist/context/VirtualizedMessageListContext.d.ts +13 -0
  173. package/dist/context/VirtualizedMessageListContext.js +7 -0
  174. package/dist/context/WithComponents.js +1 -1
  175. package/dist/css/v2/index.css +2 -2
  176. package/dist/css/v2/index.layout.css +2 -2
  177. package/dist/experimental/MessageActions/MessageActions.js +0 -1
  178. package/dist/experimental/MessageActions/defaults.js +31 -7
  179. package/dist/experimental/index.browser.cjs +103 -37
  180. package/dist/experimental/index.browser.cjs.map +2 -2
  181. package/dist/experimental/index.node.cjs +103 -37
  182. package/dist/experimental/index.node.cjs.map +2 -2
  183. package/dist/i18n/Streami18n.js +11 -2
  184. package/dist/i18n/utils.js +14 -1
  185. package/dist/index.browser.cjs +2329 -1145
  186. package/dist/index.browser.cjs.map +4 -4
  187. package/dist/index.node.cjs +2594 -1164
  188. package/dist/index.node.cjs.map +4 -4
  189. package/dist/plugins/Emojis/EmojiPicker.js +0 -1
  190. package/dist/plugins/Emojis/index.browser.cjs +3 -1
  191. package/dist/plugins/Emojis/index.browser.cjs.map +2 -2
  192. package/dist/plugins/Emojis/index.node.cjs +3 -1
  193. package/dist/plugins/Emojis/index.node.cjs.map +2 -2
  194. package/dist/plugins/encoders/mp3.browser.cjs +7 -4
  195. package/dist/plugins/encoders/mp3.browser.cjs.map +2 -2
  196. package/dist/plugins/encoders/mp3.node.cjs +7 -4
  197. package/dist/plugins/encoders/mp3.node.cjs.map +2 -2
  198. package/dist/scss/v2/ChannelSearch/ChannelSearch-layout.scss +1 -0
  199. package/dist/scss/v2/Message/Message-layout.scss +12 -5
  200. package/dist/scss/v2/Poll/Poll-layout.scss +1 -1
  201. package/dist/scss/v2/Search/Search-layout.scss +148 -0
  202. package/dist/scss/v2/Search/Search-theme.scss +222 -0
  203. package/dist/scss/v2/_icons.scss +2 -0
  204. package/dist/scss/v2/index.layout.scss +1 -0
  205. package/dist/scss/v2/index.scss +1 -0
  206. package/dist/store/hooks/useStateStore.js +35 -11
  207. package/package.json +32 -47
@@ -8,13 +8,15 @@ export const UnsupportedAttachmentPreview = ({ attachment, handleRetry, removeAt
8
8
  return (React.createElement("div", { className: 'str-chat__attachment-preview-unsupported', "data-testid": 'attachment-preview-unknown' },
9
9
  React.createElement("div", { className: 'str-chat__attachment-preview-file-icon' },
10
10
  React.createElement(FileIcon, { filename: title, mimeType: attachment.mime_type })),
11
- React.createElement("button", { className: 'str-chat__attachment-preview-delete', "data-testid": 'file-preview-item-delete-button', disabled: attachment.localMetadata?.uploadState === 'uploading', onClick: () => attachment.localMetadata?.id && removeAttachments([attachment.localMetadata?.id]) },
11
+ React.createElement("button", { className: 'str-chat__attachment-preview-delete', "data-testid": 'file-preview-item-delete-button', disabled: attachment.localMetadata?.uploadState === 'uploading', onClick: () => attachment.localMetadata?.id &&
12
+ removeAttachments([attachment.localMetadata?.id]) },
12
13
  React.createElement(CloseIcon, null)),
13
14
  attachment.localMetadata?.uploadState === 'failed' && !!handleRetry && (React.createElement("button", { className: 'str-chat__attachment-preview-error str-chat__attachment-preview-error-file', "data-testid": 'file-preview-item-retry-button', onClick: () => handleRetry(attachment) },
14
15
  React.createElement(RetryIcon, null))),
15
16
  React.createElement("div", { className: 'str-chat__attachment-preview-metadata' },
16
17
  React.createElement("div", { className: 'str-chat__attachment-preview-title', title: title }, title),
17
- attachment.localMetadata?.uploadState === 'finished' && !!attachment.asset_url && (React.createElement("a", { className: 'str-chat__attachment-preview-file-download', download: true, href: attachment.asset_url, rel: 'noreferrer', target: '_blank' },
18
+ attachment.localMetadata?.uploadState === 'finished' &&
19
+ !!attachment.asset_url && (React.createElement("a", { className: 'str-chat__attachment-preview-file-download', download: true, href: attachment.asset_url, rel: 'noreferrer', target: '_blank' },
18
20
  React.createElement(DownloadIcon, null))),
19
21
  attachment.localMetadata?.uploadState === 'uploading' && (React.createElement(LoadingIndicatorIcon, { size: 17 })))));
20
22
  };
@@ -1,5 +1,5 @@
1
1
  import { nanoid } from 'nanoid';
2
- import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
2
+ import React, { useCallback, useEffect, useMemo, useRef, useState, } from 'react';
3
3
  import { UploadIcon as DefaultUploadIcon } from './icons';
4
4
  import { CHANNEL_CONTAINER_ID } from '../Channel/constants';
5
5
  import { DialogAnchor, useDialog, useDialogIsOpen } from '../Dialog';
@@ -20,5 +20,5 @@ export const DefaultTriggerProvider = ({ children, }) => {
20
20
  ...currentValue,
21
21
  autocompleteTriggers: defaultAutocompleteTriggers,
22
22
  };
23
- return React.createElement(MessageInputContextProvider, { value: newValue }, children);
23
+ return (React.createElement(MessageInputContextProvider, { value: newValue }, children));
24
24
  };
@@ -7,7 +7,7 @@ import { useChannelStateContext } from '../../context/ChannelStateContext';
7
7
  import { MessageInputContextProvider, useMessageInputContext, } from '../../context/MessageInputContext';
8
8
  const DropzoneInner = ({ children, }) => {
9
9
  const { acceptedFiles, multipleUploads } = useChannelStateContext('DropzoneProvider');
10
- const { cooldownRemaining, isUploadEnabled, maxFilesLeft, uploadNewFiles, } = useMessageInputContext('DropzoneProvider');
10
+ const { cooldownRemaining, isUploadEnabled, maxFilesLeft, uploadNewFiles } = useMessageInputContext('DropzoneProvider');
11
11
  return (React.createElement(ImageDropzone, { accept: acceptedFiles, disabled: !isUploadEnabled || maxFilesLeft === 0 || !!cooldownRemaining, handleFiles: uploadNewFiles, maxNumberOfFiles: maxFilesLeft, multiple: multipleUploads }, children));
12
12
  };
13
13
  export const DropzoneProvider = (props) => {
@@ -5,7 +5,7 @@ import { useCooldownTimer } from './hooks/useCooldownTimer';
5
5
  import { useCreateMessageInputContext } from './hooks/useCreateMessageInputContext';
6
6
  import { useMessageInputState } from './hooks/useMessageInputState';
7
7
  import { useChannelStateContext } from '../../context/ChannelStateContext';
8
- import { useComponentContext } from '../../context/ComponentContext';
8
+ import { useComponentContext, } from '../../context/ComponentContext';
9
9
  import { MessageInputContextProvider } from '../../context/MessageInputContext';
10
10
  import { DialogManagerProvider } from '../../context';
11
11
  const MessageInputProvider = (props) => {
@@ -21,7 +21,7 @@ import { AIStates, useAIState } from '../AIStateIndicator';
21
21
  export const MessageInputFlat = () => {
22
22
  const { t } = useTranslationContext('MessageInputFlat');
23
23
  const { asyncMessagesMultiSendEnabled, attachments, cooldownRemaining, findAndEnqueueURLsToEnrich, handleSubmit, hideSendButton, isUploadEnabled, linkPreviews, maxFilesLeft, message, numberOfUploads, parent, recordingController, setCooldownRemaining, text, uploadNewFiles, } = useMessageInputContext('MessageInputFlat');
24
- const { AudioRecorder = DefaultAudioRecorder, AttachmentPreviewList = DefaultAttachmentPreviewList, AttachmentSelector = message ? SimpleAttachmentSelector : DefaultAttachmentSelector, CooldownTimer = DefaultCooldownTimer, LinkPreviewList = DefaultLinkPreviewList, QuotedMessagePreview = DefaultQuotedMessagePreview, RecordingPermissionDeniedNotification = DefaultRecordingPermissionDeniedNotification, SendButton = DefaultSendButton, StartRecordingAudioButton = DefaultStartRecordingAudioButton, StopAIGenerationButton: StopAIGenerationButtonOverride, EmojiPicker, } = useComponentContext('MessageInputFlat');
24
+ const { AttachmentPreviewList = DefaultAttachmentPreviewList, AttachmentSelector = message ? SimpleAttachmentSelector : DefaultAttachmentSelector, AudioRecorder = DefaultAudioRecorder, CooldownTimer = DefaultCooldownTimer, EmojiPicker, LinkPreviewList = DefaultLinkPreviewList, QuotedMessagePreview = DefaultQuotedMessagePreview, RecordingPermissionDeniedNotification = DefaultRecordingPermissionDeniedNotification, SendButton = DefaultSendButton, StartRecordingAudioButton = DefaultStartRecordingAudioButton, StopAIGenerationButton: StopAIGenerationButtonOverride, } = useComponentContext('MessageInputFlat');
25
25
  const { acceptedFiles = [], multipleUploads, quotedMessage, } = useChannelStateContext('MessageInputFlat');
26
26
  const { setQuotedMessage } = useChannelActionContext('MessageInputFlat');
27
27
  const { channel } = useChatContext('MessageInputFlat');
@@ -76,7 +76,8 @@ export const MessageInputFlat = () => {
76
76
  const StopAIGenerationButton = StopAIGenerationButtonOverride === undefined
77
77
  ? DefaultStopAIGenerationButton
78
78
  : StopAIGenerationButtonOverride;
79
- const shouldDisplayStopAIGeneration = [AIStates.Thinking, AIStates.Generating].includes(aiState) && !!StopAIGenerationButton;
79
+ const shouldDisplayStopAIGeneration = [AIStates.Thinking, AIStates.Generating].includes(aiState) &&
80
+ !!StopAIGenerationButton;
80
81
  return (React.createElement(React.Fragment, null,
81
82
  React.createElement("div", { ...getRootProps({ className: 'str-chat__message-input' }) },
82
83
  recordingEnabled &&
@@ -92,7 +93,7 @@ export const MessageInputFlat = () => {
92
93
  React.createElement("div", { className: 'str-chat__message-input-inner' },
93
94
  React.createElement(AttachmentSelector, null),
94
95
  React.createElement("div", { className: 'str-chat__message-textarea-container' },
95
- displayQuotedMessage && React.createElement(QuotedMessagePreview, { quotedMessage: quotedMessage }),
96
+ displayQuotedMessage && (React.createElement(QuotedMessagePreview, { quotedMessage: quotedMessage })),
96
97
  isUploadEnabled &&
97
98
  !!(numberOfUploads + failedUploadsCount || attachments.length > 0) && (React.createElement(AttachmentPreviewList, null)),
98
99
  React.createElement("div", { className: 'str-chat__message-textarea-with-emoji-picker' },
@@ -17,7 +17,7 @@ export const QuotedMessagePreviewHeader = () => {
17
17
  };
18
18
  export const QuotedMessagePreview = ({ quotedMessage, }) => {
19
19
  const { client } = useChatContext();
20
- const { Attachment = DefaultAttachment, Avatar = DefaultAvatar, } = useComponentContext('QuotedMessagePreview');
20
+ const { Attachment = DefaultAttachment, Avatar = DefaultAvatar } = useComponentContext('QuotedMessagePreview');
21
21
  const { userLanguage } = useTranslationContext('QuotedMessagePreview');
22
22
  const quotedMessageText = quotedMessage.i18n?.[`${userLanguage}_text`] ||
23
23
  quotedMessage.text;
@@ -2,7 +2,7 @@ import { useCallback } from 'react';
2
2
  import { nanoid } from 'nanoid';
3
3
  import { checkUploadPermissions } from './utils';
4
4
  import { isLocalAttachment, isLocalImageAttachment } from '../../Attachment';
5
- import { createFileFromBlobs, generateFileName, isBlobButNotFile } from '../../ReactFileUtilities';
5
+ import { createFileFromBlobs, generateFileName, isBlobButNotFile, } from '../../ReactFileUtilities';
6
6
  import { useChannelActionContext, useChannelStateContext, useChatContext, useTranslationContext, } from '../../../context';
7
7
  const apiMaxNumberOfFiles = 10;
8
8
  // const isAudioFile = (file: FileLike) => file.type.includes('audio/');
@@ -109,7 +109,10 @@ export const useAttachments = (props, state, dispatch, textareaRef) => {
109
109
  }
110
110
  }
111
111
  catch (error) {
112
- let finalError = { message: t('Error uploading attachment'), name: 'Error' };
112
+ let finalError = {
113
+ message: t('Error uploading attachment'),
114
+ name: 'Error',
115
+ };
113
116
  if (typeof error.message === 'string') {
114
117
  finalError = error;
115
118
  }
@@ -127,7 +130,10 @@ export const useAttachments = (props, state, dispatch, textareaRef) => {
127
130
  };
128
131
  upsertAttachments([failedAttachment]);
129
132
  if (errorHandler) {
130
- errorHandler(finalError, 'upload-attachment', { ...file, id: localMetadata.id });
133
+ errorHandler(finalError, 'upload-attachment', {
134
+ ...file,
135
+ id: localMetadata.id,
136
+ });
131
137
  }
132
138
  return failedAttachment;
133
139
  }
@@ -173,7 +179,9 @@ export const useAttachments = (props, state, dispatch, textareaRef) => {
173
179
  upsertAttachments,
174
180
  ]);
175
181
  const uploadNewFiles = useCallback((files) => {
176
- const filesToBeUploaded = noFiles ? Array.from(files).filter(isImageFile) : Array.from(files);
182
+ const filesToBeUploaded = noFiles
183
+ ? Array.from(files).filter(isImageFile)
184
+ : Array.from(files);
177
185
  filesToBeUploaded.slice(0, maxFilesLeft).forEach((fileLike) => {
178
186
  uploadAttachment({
179
187
  localMetadata: {
@@ -102,6 +102,8 @@ export const useLinkPreviews = ({ debounceURLEnrichmentMs: debounceURLEnrichment
102
102
  return {
103
103
  cancelURLEnrichment,
104
104
  dismissLinkPreview,
105
- findAndEnqueueURLsToEnrich: channelConfig?.url_enrichment && enrichURLForPreview ? findAndEnqueueURLsToEnrich : undefined,
105
+ findAndEnqueueURLsToEnrich: channelConfig?.url_enrichment && enrichURLForPreview
106
+ ? findAndEnqueueURLsToEnrich
107
+ : undefined,
106
108
  };
107
109
  };
@@ -1,12 +1,12 @@
1
1
  import { useCallback, useReducer, useState } from 'react';
2
2
  import { nanoid } from 'nanoid';
3
- import { useChannelStateContext } from '../../../context/ChannelStateContext';
3
+ import { useChannelStateContext, } from '../../../context/ChannelStateContext';
4
4
  import { useAttachments } from './useAttachments';
5
5
  import { useLinkPreviews } from './useLinkPreviews';
6
6
  import { useMessageInputText } from './useMessageInputText';
7
7
  import { useSubmitHandler } from './useSubmitHandler';
8
8
  import { usePasteHandler } from './usePasteHandler';
9
- import { useMediaRecorder } from '../../MediaRecorder/hooks/useMediaRecorder';
9
+ import { useMediaRecorder, } from '../../MediaRecorder/hooks/useMediaRecorder';
10
10
  import { LinkPreviewState, SetLinkPreviewMode } from '../types';
11
11
  import { mergeDeep } from '../../../utils/mergeDeep';
12
12
  const makeEmptyMessageInputState = () => ({
@@ -59,7 +59,8 @@ const messageInputReducer = (state, action) => {
59
59
  case 'upsertAttachments': {
60
60
  const attachments = [...state.attachments];
61
61
  action.attachments.forEach((actionAttachment) => {
62
- const attachmentIndex = state.attachments.findIndex((att) => att.localMetadata?.id && att.localMetadata?.id === actionAttachment.localMetadata?.id);
62
+ const attachmentIndex = state.attachments.findIndex((att) => att.localMetadata?.id &&
63
+ att.localMetadata?.id === actionAttachment.localMetadata?.id);
63
64
  if (attachmentIndex === -1) {
64
65
  attachments.push(actionAttachment);
65
66
  }
@@ -6,5 +6,5 @@ import type { EnrichURLsController } from './useLinkPreviews';
6
6
  export declare const useMessageInputText: <StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics, V extends CustomTrigger = CustomTrigger>(props: MessageInputProps<StreamChatGenerics, V>, state: MessageInputState<StreamChatGenerics>, dispatch: React.Dispatch<MessageInputReducerAction<StreamChatGenerics>>, findAndEnqueueURLsToEnrich?: EnrichURLsController['findAndEnqueueURLsToEnrich']) => {
7
7
  handleChange: import("react").ChangeEventHandler<HTMLTextAreaElement>;
8
8
  insertText: (textToInsert: string) => void;
9
- textareaRef: import("react").MutableRefObject<HTMLTextAreaElement | undefined>;
9
+ textareaRef: import("react").RefObject<HTMLTextAreaElement | undefined>;
10
10
  };
@@ -5,7 +5,7 @@ export const useMessageInputText = (props, state, dispatch, findAndEnqueueURLsTo
5
5
  const { channel } = useChannelStateContext('useMessageInputText');
6
6
  const { additionalTextareaProps, focus, parent, publishTypingEvent = true } = props;
7
7
  const { text } = state;
8
- const textareaRef = useRef();
8
+ const textareaRef = useRef(undefined);
9
9
  // Focus
10
10
  useEffect(() => {
11
11
  if (focus && textareaRef.current) {
@@ -13,7 +13,7 @@ export const useMessageInputText = (props, state, dispatch, findAndEnqueueURLsTo
13
13
  }
14
14
  }, [focus]);
15
15
  // Text + cursor position
16
- const newCursorPosition = useRef();
16
+ const newCursorPosition = useRef(undefined);
17
17
  const insertText = useCallback((textToInsert) => {
18
18
  const { maxLength } = additionalTextareaProps || {};
19
19
  if (!textareaRef.current) {
@@ -32,7 +32,9 @@ export const useMessageInputText = (props, state, dispatch, findAndEnqueueURLsTo
32
32
  newCursorPosition.current = selectionStart + textToInsert.length;
33
33
  dispatch({
34
34
  getNewText: (prevText) => {
35
- const updatedText = prevText.slice(0, selectionStart) + textToInsert + prevText.slice(selectionEnd);
35
+ const updatedText = prevText.slice(0, selectionStart) +
36
+ textToInsert +
37
+ prevText.slice(selectionEnd);
36
38
  if (maxLength && updatedText.length > maxLength) {
37
39
  return updatedText.slice(0, maxLength);
38
40
  }
@@ -4,7 +4,7 @@ import { useChannelStateContext } from '../../../context/ChannelStateContext';
4
4
  import { useTranslationContext } from '../../../context/TranslationContext';
5
5
  import { LinkPreviewState } from '../types';
6
6
  export const useSubmitHandler = (props, state, dispatch, numberOfUploads, enrichURLsController) => {
7
- const { clearEditingState, message, overrideSubmitHandler, parent, publishTypingEvent } = props;
7
+ const { clearEditingState, message, overrideSubmitHandler, parent, publishTypingEvent, } = props;
8
8
  const { attachments, linkPreviews, mentioned_users, text } = state;
9
9
  const { cancelURLEnrichment, findAndEnqueueURLsToEnrich } = enrichURLsController;
10
10
  const { channel } = useChannelStateContext('useSubmitHandler');
@@ -42,6 +42,7 @@ export const useSubmitHandler = (props, state, dispatch, numberOfUploads, enrich
42
42
  .filter((att) => att.localMetadata?.uploadState !== 'failed' ||
43
43
  (findAndEnqueueURLsToEnrich && !att.og_scrape_url))
44
44
  .map((localAttachment) => {
45
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
45
46
  const { localMetadata: _, ...attachment } = localAttachment;
46
47
  return attachment;
47
48
  });
@@ -57,8 +58,9 @@ export const useSubmitHandler = (props, state, dispatch, numberOfUploads, enrich
57
58
  : Array.from(linkPreviews.values())
58
59
  .filter((linkPreview) => linkPreview.state === LinkPreviewState.LOADED &&
59
60
  !attachmentsFromUploads.find((attFromUpload) => attFromUpload.og_scrape_url === linkPreview.og_scrape_url))
60
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
61
- .map(({ state: linkPreviewState, ...ogAttachment }) => ogAttachment);
61
+ .map(
62
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
63
+ ({ state: linkPreviewState, ...ogAttachment }) => ogAttachment);
62
64
  // scraped attachments are added only if all enrich queries has completed. Otherwise, the scraping has to be done server-side.
63
65
  sendOptions.skip_enrich_url =
64
66
  (!someLinkPreviewsLoading && attachmentsFromLinkPreviews.length > 0) ||
@@ -2,7 +2,7 @@ import { useCallback, useEffect, useRef, useState } from 'react';
2
2
  // todo: provide start timestamp
3
3
  export const useTimeElapsed = ({ startOnMount } = {}) => {
4
4
  const [secondsElapsed, setSecondsElapsed] = useState(0);
5
- const updateInterval = useRef();
5
+ const updateInterval = useRef(undefined);
6
6
  const startCounter = useCallback(() => {
7
7
  if (updateInterval.current)
8
8
  return;
@@ -27,7 +27,7 @@ export const useUserTrigger = (params) => {
27
27
  // eslint-disable-next-line react-hooks/exhaustive-deps
28
28
  const queryMembersThrottled = useCallback(throttle(async (query, onReady) => {
29
29
  try {
30
- // @ts-expect-error
30
+ // @ts-expect-error valid query
31
31
  const response = await channel.queryMembers({
32
32
  name: { $autocomplete: query },
33
33
  });
@@ -49,7 +49,7 @@ export const useUserTrigger = (params) => {
49
49
  setSearching(true);
50
50
  try {
51
51
  const { users } = await client.queryUsers(
52
- // @ts-expect-error
52
+ // @ts-expect-error valid query
53
53
  {
54
54
  $or: [{ id: { $autocomplete: query } }, { name: { $autocomplete: query } }],
55
55
  ...(typeof mentionQueryParams.filters === 'function'
@@ -53,6 +53,7 @@ export const searchLocalUsers = (params) => {
53
53
  let updatedQuery = removeDiacritics(query).toLowerCase();
54
54
  if (useMentionsTransliteration) {
55
55
  (async () => {
56
+ // eslint-disable-next-line import/no-extraneous-dependencies
56
57
  const { default: transliterate } = await import('@stream-io/transliterate');
57
58
  updatedName = transliterate(user.name || '').toLowerCase();
58
59
  updatedQuery = transliterate(query).toLowerCase();
@@ -63,7 +64,8 @@ export const searchLocalUsers = (params) => {
63
64
  const lastDigits = text.slice(-(maxDistance + 1)).includes('@');
64
65
  if (updatedName) {
65
66
  const levenshtein = calculateLevenshtein(updatedQuery, updatedName);
66
- if (updatedName.includes(updatedQuery) || (levenshtein <= maxDistance && lastDigits)) {
67
+ if (updatedName.includes(updatedQuery) ||
68
+ (levenshtein <= maxDistance && lastDigits)) {
67
69
  return true;
68
70
  }
69
71
  }
@@ -79,7 +81,9 @@ export const checkUploadPermissions = async (params) => {
79
81
  const { allowed_file_extensions, allowed_mime_types, blocked_file_extensions, blocked_mime_types, size_limit, } = (uploadType === 'image'
80
82
  ? appSettings?.app?.image_upload_config
81
83
  : appSettings?.app?.file_upload_config) || {};
82
- const sendNotAllowedErrorNotification = () => addNotification(t(`Upload type: "{{ type }}" is not allowed`, { type: file.type || 'unknown type' }), 'error');
84
+ const sendNotAllowedErrorNotification = () => addNotification(t(`Upload type: "{{ type }}" is not allowed`, {
85
+ type: file.type || 'unknown type',
86
+ }), 'error');
83
87
  if (allowed_file_extensions?.length) {
84
88
  const allowed = allowed_file_extensions.some((ext) => file.name.toLowerCase().endsWith(ext.toLowerCase()));
85
89
  if (!allowed) {
@@ -6,7 +6,7 @@ const UnMemoizedConnectionStatus = () => {
6
6
  const { t } = useTranslationContext('ConnectionStatus');
7
7
  const [online, setOnline] = useState(true);
8
8
  useEffect(() => {
9
- const connectionChanged = ({ online: onlineStatus = false }) => {
9
+ const connectionChanged = ({ online: onlineStatus = false, }) => {
10
10
  if (online !== onlineStatus) {
11
11
  setOnline(onlineStatus);
12
12
  }
@@ -12,7 +12,7 @@ import { useChatContext } from '../../context/ChatContext';
12
12
  import { useComponentContext } from '../../context/ComponentContext';
13
13
  import { MessageListContextProvider } from '../../context/MessageListContext';
14
14
  import { EmptyStateIndicator as DefaultEmptyStateIndicator } from '../EmptyStateIndicator';
15
- import { InfiniteScroll } from '../InfiniteScrollPaginator/InfiniteScroll';
15
+ import { InfiniteScroll, } from '../InfiniteScrollPaginator/InfiniteScroll';
16
16
  import { LoadingIndicator as DefaultLoadingIndicator } from '../Loading';
17
17
  import { defaultPinPermissions, MESSAGE_ACTIONS } from '../Message/utils';
18
18
  import { TypingIndicator as DefaultTypingIndicator } from '../TypingIndicator';
@@ -20,12 +20,12 @@ import { MessageListMainPanel as DefaultMessageListMainPanel } from './MessageLi
20
20
  import { defaultRenderMessages } from './renderMessages';
21
21
  import { DEFAULT_LOAD_PAGE_SCROLL_THRESHOLD, DEFAULT_NEXT_CHANNEL_PAGE_SIZE, } from '../../constants/limits';
22
22
  const MessageListWithContext = (props) => {
23
- const { channel, channelUnreadUiState, disableDateSeparator = false, groupStyles, hideDeletedMessages = false, hideNewMessageSeparator = false, internalInfiniteScrollProps: { threshold: loadMoreScrollThreshold = DEFAULT_LOAD_PAGE_SCROLL_THRESHOLD, ...restInternalInfiniteScrollProps } = {}, maxTimeBetweenGroupedMessages, messageActions = Object.keys(MESSAGE_ACTIONS), messages = [], notifications, noGroupByUser = false, pinPermissions = defaultPinPermissions, // @deprecated in favor of `channelCapabilities` - TODO: remove in next major release
24
- returnAllReadData = false, threadList = false, unsafeHTML = false, headerPosition, read, renderMessages = defaultRenderMessages, reviewProcessedMessage, messageLimit = DEFAULT_NEXT_CHANNEL_PAGE_SIZE, loadMore: loadMoreCallback, loadMoreNewer: loadMoreNewerCallback, hasMoreNewer = false, reactionDetailsSort, showUnreadNotificationAlways, sortReactionDetails, sortReactions, suppressAutoscroll, highlightedMessageId, jumpToLatestMessage = () => Promise.resolve(), } = props;
23
+ const { channel, channelUnreadUiState, disableDateSeparator = false, groupStyles, hasMoreNewer = false, headerPosition, hideDeletedMessages = false, hideNewMessageSeparator = false, highlightedMessageId, internalInfiniteScrollProps: { threshold: loadMoreScrollThreshold = DEFAULT_LOAD_PAGE_SCROLL_THRESHOLD, ...restInternalInfiniteScrollProps } = {}, jumpToLatestMessage = () => Promise.resolve(), loadMore: loadMoreCallback, loadMoreNewer: loadMoreNewerCallback, // @deprecated in favor of `channelCapabilities` - TODO: remove in next major release
24
+ maxTimeBetweenGroupedMessages, messageActions = Object.keys(MESSAGE_ACTIONS), messageLimit = DEFAULT_NEXT_CHANNEL_PAGE_SIZE, messages = [], noGroupByUser = false, notifications, pinPermissions = defaultPinPermissions, reactionDetailsSort, read, renderMessages = defaultRenderMessages, returnAllReadData = false, reviewProcessedMessage, showUnreadNotificationAlways, sortReactionDetails, sortReactions, suppressAutoscroll, threadList = false, unsafeHTML = false, } = props;
25
25
  const [listElement, setListElement] = React.useState(null);
26
26
  const [ulElement, setUlElement] = React.useState(null);
27
27
  const { customClasses } = useChatContext('MessageList');
28
- const { EmptyStateIndicator = DefaultEmptyStateIndicator, LoadingIndicator = DefaultLoadingIndicator, MessageListNotifications = DefaultMessageListNotifications, MessageNotification = DefaultMessageNotification, TypingIndicator = DefaultTypingIndicator, UnreadMessagesNotification = DefaultUnreadMessagesNotification, MessageListMainPanel = DefaultMessageListMainPanel, } = useComponentContext('MessageList');
28
+ const { EmptyStateIndicator = DefaultEmptyStateIndicator, LoadingIndicator = DefaultLoadingIndicator, MessageListMainPanel = DefaultMessageListMainPanel, MessageListNotifications = DefaultMessageListNotifications, MessageNotification = DefaultMessageNotification, TypingIndicator = DefaultTypingIndicator, UnreadMessagesNotification = DefaultUnreadMessagesNotification, } = useComponentContext('MessageList');
29
29
  const { hasNewMessages, isMessageListScrolledToBottom, onScroll, scrollToBottom, wrapperRect, } = useScrollLocationLogic({
30
30
  hasMoreNewer,
31
31
  listElement,
@@ -42,7 +42,6 @@ const MessageListWithContext = (props) => {
42
42
  useMarkRead({
43
43
  isMessageListScrolledToBottom,
44
44
  messageListIsThread: threadList,
45
- unreadCount: channelUnreadUiState?.unread_messages ?? 0,
46
45
  wasMarkedUnread: !!channelUnreadUiState?.first_unread_message_id,
47
46
  });
48
47
  const { messageGroupStyles, messages: enrichedMessages } = useEnrichedMessages({
@@ -147,7 +146,7 @@ const MessageListWithContext = (props) => {
147
146
  * - [TypingContext](https://getstream.io/chat/docs/sdk/react/contexts/typing_context/)
148
147
  */
149
148
  export const MessageList = (props) => {
150
- const { jumpToLatestMessage, loadMore, loadMoreNewer, } = useChannelActionContext('MessageList');
149
+ const { jumpToLatestMessage, loadMore, loadMoreNewer } = useChannelActionContext('MessageList');
151
150
  const { members: membersPropToNotPass, // eslint-disable-line @typescript-eslint/no-unused-vars
152
151
  mutes: mutesPropToNotPass, // eslint-disable-line @typescript-eslint/no-unused-vars
153
152
  watchers: watchersPropToNotPass, // eslint-disable-line @typescript-eslint/no-unused-vars
@@ -8,5 +8,7 @@ export const MessageListNotifications = (props) => {
8
8
  return (React.createElement("div", { className: 'str-chat__list-notifications' },
9
9
  notifications.map((notification) => (React.createElement(CustomNotification, { active: true, key: notification.id, type: notification.type }, notification.text))),
10
10
  React.createElement(ConnectionStatus, null),
11
- React.createElement(MessageNotification, { isMessageListScrolledToBottom: isMessageListScrolledToBottom, onClick: scrollToBottom, showNotification: hasNewMessages || isNotAtLatestMessageSet, threadList: threadList, unreadCount: unreadCount }, isNotAtLatestMessageSet ? t('Latest Messages') : t('New Messages!'))));
11
+ React.createElement(MessageNotification, { isMessageListScrolledToBottom: isMessageListScrolledToBottom, onClick: scrollToBottom, showNotification: hasNewMessages || isNotAtLatestMessageSet, threadList: threadList, unreadCount: unreadCount }, isNotAtLatestMessageSet
12
+ ? t('Latest Messages')
13
+ : t('New Messages!'))));
12
14
  };
@@ -25,7 +25,7 @@ export type VirtuosoContext<StreamChatGenerics extends DefaultStreamChatGenerics
25
25
  /** The original message list enriched with date separators, omitted deleted messages or giphy previews. */
26
26
  processedMessages: StreamMessage<StreamChatGenerics>[];
27
27
  /** Instance of VirtuosoHandle object providing the API to navigate in the virtualized list by various scroll actions. */
28
- virtuosoRef: RefObject<VirtuosoHandle>;
28
+ virtuosoRef: RefObject<VirtuosoHandle | null>;
29
29
  /** Message id which was marked as unread. ALl the messages following this message are considered unrea. */
30
30
  firstUnreadMessageId?: string;
31
31
  lastReadDate?: Date;
@@ -18,7 +18,8 @@ import { DialogManagerProvider } from '../../context';
18
18
  import { useChannelActionContext, } from '../../context/ChannelActionContext';
19
19
  import { useChannelStateContext, } from '../../context/ChannelStateContext';
20
20
  import { useChatContext } from '../../context/ChatContext';
21
- import { useComponentContext } from '../../context/ComponentContext';
21
+ import { useComponentContext, } from '../../context/ComponentContext';
22
+ import { VirtualizedMessageListContextProvider } from '../../context/VirtualizedMessageListContext';
22
23
  import { DEFAULT_NEXT_CHANNEL_PAGE_SIZE } from '../../constants/limits';
23
24
  function captureResizeObserverExceededError(e) {
24
25
  if (e.message === 'ResizeObserver loop completed with undelivered notifications.' ||
@@ -52,17 +53,17 @@ function calculateInitialTopMostItemIndex(messages, highlightedMessageId) {
52
53
  const VirtualizedMessageListWithContext = (props) => {
53
54
  const { additionalMessageInputProps, additionalVirtuosoProps = {}, channel, channelUnreadUiState, closeReactionSelectorOnClick, customMessageActions, customMessageRenderer, defaultItemHeight, disableDateSeparator = true, formatDate, groupStyles, hasMoreNewer, head, hideDeletedMessages = false, hideNewMessageSeparator = false, highlightedMessageId, jumpToLatestMessage, loadingMore, loadMore, loadMoreNewer, maxTimeBetweenGroupedMessages, Message: MessageUIComponentFromProps, messageActions, messageLimit = DEFAULT_NEXT_CHANNEL_PAGE_SIZE, messages, notifications, openThread,
54
55
  // TODO: refactor to scrollSeekPlaceHolderConfiguration and components.ScrollSeekPlaceholder, like the Virtuoso Component
55
- overscan = 0, read, returnAllReadData = false, reviewProcessedMessage, scrollSeekPlaceHolder, scrollToLatestMessageOnFocus = false, separateGiphyPreview = false, shouldGroupByUser = false, showUnreadNotificationAlways, reactionDetailsSort, sortReactionDetails, sortReactions, stickToBottomScrollBehavior = 'smooth', suppressAutoscroll, threadList, } = props;
56
+ overscan = 0, reactionDetailsSort, read, returnAllReadData = false, reviewProcessedMessage, scrollSeekPlaceHolder, scrollToLatestMessageOnFocus = false, separateGiphyPreview = false, shouldGroupByUser = false, showUnreadNotificationAlways, sortReactionDetails, sortReactions, stickToBottomScrollBehavior = 'smooth', suppressAutoscroll, threadList, } = props;
56
57
  const { components: virtuosoComponentsFromProps, ...overridingVirtuosoProps } = additionalVirtuosoProps;
57
58
  // Stops errors generated from react-virtuoso to bubble up
58
59
  // to Sentry or other tracking tools.
59
60
  useCaptureResizeObserverExceededError();
60
- const { DateSeparator = DefaultDateSeparator, GiphyPreviewMessage = DefaultGiphyPreviewMessage, MessageListNotifications = DefaultMessageListNotifications, MessageNotification = DefaultMessageNotification, MessageSystem = DefaultMessageSystem, MessageListMainPanel = DefaultMessageListMainPanel, UnreadMessagesNotification = DefaultUnreadMessagesNotification, UnreadMessagesSeparator = DefaultUnreadMessagesSeparator, VirtualMessage: MessageUIComponentFromContext = MessageSimple, TypingIndicator, } = useComponentContext('VirtualizedMessageList');
61
+ const { DateSeparator = DefaultDateSeparator, GiphyPreviewMessage = DefaultGiphyPreviewMessage, MessageListMainPanel = DefaultMessageListMainPanel, MessageListNotifications = DefaultMessageListNotifications, MessageNotification = DefaultMessageNotification, MessageSystem = DefaultMessageSystem, TypingIndicator, UnreadMessagesNotification = DefaultUnreadMessagesNotification, UnreadMessagesSeparator = DefaultUnreadMessagesSeparator, VirtualMessage: MessageUIComponentFromContext = MessageSimple, } = useComponentContext('VirtualizedMessageList');
61
62
  const MessageUIComponent = MessageUIComponentFromProps || MessageUIComponentFromContext;
62
63
  const { client, customClasses } = useChatContext('VirtualizedMessageList');
63
64
  const virtuoso = useRef(null);
64
65
  const lastRead = useMemo(() => channel.lastRead?.(), [channel]);
65
- const { show: showUnreadMessagesNotification, toggleShowUnreadMessagesNotification, } = useUnreadMessagesNotificationVirtualized({
66
+ const { show: showUnreadMessagesNotification, toggleShowUnreadMessagesNotification } = useUnreadMessagesNotificationVirtualized({
66
67
  lastRead: channelUnreadUiState?.last_read,
67
68
  showAlways: !!showUnreadNotificationAlways,
68
69
  unreadCount: channelUnreadUiState?.unread_messages ?? 0,
@@ -105,9 +106,7 @@ const VirtualizedMessageListWithContext = (props) => {
105
106
  returnAllReadData,
106
107
  userID: client.userID,
107
108
  });
108
- const lastReceivedMessageId = useMemo(() => getLastReceived(processedMessages), [
109
- processedMessages,
110
- ]);
109
+ const lastReceivedMessageId = useMemo(() => getLastReceived(processedMessages), [processedMessages]);
111
110
  const groupStylesFn = groupStyles || getGroupStyles;
112
111
  const messageGroupStyles = useMemo(() => processedMessages.reduce((acc, message, i) => {
113
112
  const style = groupStylesFn(message, processedMessages[i - 1], processedMessages[i + 1], !shouldGroupByUser, maxTimeBetweenGroupedMessages);
@@ -117,12 +116,16 @@ const VirtualizedMessageListWithContext = (props) => {
117
116
  }, {}),
118
117
  // processedMessages were incorrectly rebuilt with a new object identity at some point, hence the .length usage
119
118
  // eslint-disable-next-line react-hooks/exhaustive-deps
120
- [maxTimeBetweenGroupedMessages, processedMessages.length, shouldGroupByUser, groupStylesFn]);
119
+ [
120
+ maxTimeBetweenGroupedMessages,
121
+ processedMessages.length,
122
+ shouldGroupByUser,
123
+ groupStylesFn,
124
+ ]);
121
125
  const { atBottom, isMessageListScrolledToBottom, newMessagesNotification, setIsMessageListScrolledToBottom, setNewMessagesNotification, } = useNewMessageNotification(processedMessages, client.userID, hasMoreNewer);
122
126
  useMarkRead({
123
127
  isMessageListScrolledToBottom,
124
128
  messageListIsThread: !!threadList,
125
- unreadCount: channelUnreadUiState?.unread_messages ?? 0,
126
129
  wasMarkedUnread: !!channelUnreadUiState?.first_unread_message_id,
127
130
  });
128
131
  const scrollToBottom = useCallback(async () => {
@@ -144,7 +147,11 @@ const VirtualizedMessageListWithContext = (props) => {
144
147
  hasMoreNewer,
145
148
  jumpToLatestMessage,
146
149
  ]);
147
- useScrollToBottomOnNewMessage({ messages, scrollToBottom, scrollToLatestMessageOnFocus });
150
+ useScrollToBottomOnNewMessage({
151
+ messages,
152
+ scrollToBottom,
153
+ scrollToLatestMessageOnFocus,
154
+ });
148
155
  const numItemsPrepended = usePrependedMessagesCount(processedMessages, !disableDateSeparator);
149
156
  const { messageSetKey } = useMessageSetKey({ messages });
150
157
  const shouldForceScrollToBottom = useShouldForceScrollToBottom(processedMessages, client.userID);
@@ -192,7 +199,7 @@ const VirtualizedMessageListWithContext = (props) => {
192
199
  const dialogManagerId = threadList
193
200
  ? 'virtualized-message-list-dialog-manager-thread'
194
201
  : 'virtualized-message-list-dialog-manager';
195
- return (React.createElement(React.Fragment, null,
202
+ return (React.createElement(VirtualizedMessageListContextProvider, { value: { scrollToBottom } },
196
203
  React.createElement(MessageListMainPanel, null,
197
204
  React.createElement(DialogManagerProvider, { id: dialogManagerId },
198
205
  !threadList && showUnreadMessagesNotification && (React.createElement(UnreadMessagesNotification, { unreadCount: channelUnreadUiState?.unread_messages })),
@@ -242,7 +249,7 @@ const VirtualizedMessageListWithContext = (props) => {
242
249
  * It is a consumer of the React contexts set in [Channel](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Channel/Channel.tsx).
243
250
  */
244
251
  export function VirtualizedMessageList(props) {
245
- const { jumpToLatestMessage, loadMore, loadMoreNewer, } = useChannelActionContext('VirtualizedMessageList');
252
+ const { jumpToLatestMessage, loadMore, loadMoreNewer } = useChannelActionContext('VirtualizedMessageList');
246
253
  const { channel, channelUnreadUiState, hasMore, hasMoreNewer, highlightedMessageId, loadingMore, loadingMoreNewer, messages: contextMessages, notifications, read, suppressAutoscroll, } = useChannelStateContext('VirtualizedMessageList');
247
254
  const messages = props.messages || contextMessages;
248
255
  return (React.createElement(VirtualizedMessageListWithContext, { channel: channel, channelUnreadUiState: props.channelUnreadUiState ?? channelUnreadUiState, hasMore: !!hasMore, hasMoreNewer: !!hasMoreNewer, highlightedMessageId: highlightedMessageId, jumpToLatestMessage: jumpToLatestMessage, loadingMore: !!loadingMore, loadingMoreNewer: !!loadingMoreNewer, loadMore: loadMore, loadMoreNewer: loadMoreNewer, messages: messages, notifications: notifications, read: read, suppressAutoscroll: suppressAutoscroll, ...props }));
@@ -43,7 +43,7 @@ export const Header = ({ context, }) => {
43
43
  React.createElement(LoadingIndicator, { size: 20 })))));
44
44
  };
45
45
  export const EmptyPlaceholder = ({ context, }) => {
46
- const { EmptyStateIndicator = DefaultEmptyStateIndicator, } = useComponentContext('VirtualizedMessageList');
46
+ const { EmptyStateIndicator = DefaultEmptyStateIndicator } = useComponentContext('VirtualizedMessageList');
47
47
  return (React.createElement(React.Fragment, null, EmptyStateIndicator && (React.createElement(EmptyStateIndicator, { listType: context?.threadList ? 'thread' : 'message' }))));
48
48
  };
49
49
  export const messageRenderer = (virtuosoIndex, _data, virtuosoContext) => {
@@ -56,7 +56,7 @@ export const messageRenderer = (virtuosoIndex, _data, virtuosoContext) => {
56
56
  if (!message)
57
57
  return React.createElement("div", { style: { height: '1px' } }); // returning null or zero height breaks the virtuoso
58
58
  if (isDateSeparatorMessage(message)) {
59
- return DateSeparator ? React.createElement(DateSeparator, { date: message.date, unread: message.unread }) : null;
59
+ return DateSeparator ? (React.createElement(DateSeparator, { date: message.date, unread: message.unread })) : null;
60
60
  }
61
61
  if (message.type === 'system') {
62
62
  return MessageSystem ? React.createElement(MessageSystem, { message: message }) : null;
@@ -14,9 +14,7 @@ export const useMessageListElements = (props) => {
14
14
  returnAllReadData,
15
15
  userID: client.userID,
16
16
  });
17
- const lastReceivedMessageId = useMemo(() => getLastReceived(enrichedMessages), [
18
- enrichedMessages,
19
- ]);
17
+ const lastReceivedMessageId = useMemo(() => getLastReceived(enrichedMessages), [enrichedMessages]);
20
18
  const elements = useMemo(() => renderMessages({
21
19
  channelUnreadUiState,
22
20
  components,
@@ -8,7 +8,7 @@ export function useMessageListScrollManager(params) {
8
8
  offsetHeight: 0,
9
9
  scrollHeight: 0,
10
10
  });
11
- const messages = useRef();
11
+ const messages = useRef(undefined);
12
12
  const scrollTop = useRef(0);
13
13
  useLayoutEffect(() => {
14
14
  const prevMeasures = measures.current;
@@ -41,7 +41,8 @@ export function useMessageListScrollManager(params) {
41
41
  }
42
42
  // message list length didn't change, but check if last message had reaction/reply update
43
43
  else {
44
- const hasNewReactions = lastPrevMessage?.latest_reactions?.length !== lastNewMessage.latest_reactions?.length;
44
+ const hasNewReactions = lastPrevMessage?.latest_reactions?.length !==
45
+ lastNewMessage.latest_reactions?.length;
45
46
  const hasNewReplies = lastPrevMessage?.reply_count !== lastNewMessage.reply_count;
46
47
  if ((hasNewReactions || hasNewReplies) && wasAtBottom) {
47
48
  scrollToBottom();
@@ -1,7 +1,7 @@
1
1
  import { useCallback, useLayoutEffect, useRef, useState } from 'react';
2
2
  import { useMessageListScrollManager } from './useMessageListScrollManager';
3
3
  export const useScrollLocationLogic = (params) => {
4
- const { loadMoreScrollThreshold, messages = [], scrolledUpThreshold = 200, hasMoreNewer, suppressAutoscroll, listElement, } = params;
4
+ const { hasMoreNewer, listElement, loadMoreScrollThreshold, messages = [], scrolledUpThreshold = 200, suppressAutoscroll, } = params;
5
5
  const [hasNewMessages, setHasNewMessages] = useState(false);
6
6
  const [wrapperRect, setWrapperRect] = useState();
7
7
  const [isMessageListScrolledToBottom, setIsMessageListScrolledToBottom] = useState(true);
@@ -44,7 +44,8 @@ export const useScrollLocationLogic = (params) => {
44
44
  const offsetHeight = element.offsetHeight;
45
45
  const scrollHeight = element.scrollHeight;
46
46
  const prevCloseToBottom = closeToBottom.current;
47
- closeToBottom.current = scrollHeight - (scrollTop + offsetHeight) < scrolledUpThreshold;
47
+ closeToBottom.current =
48
+ scrollHeight - (scrollTop + offsetHeight) < scrolledUpThreshold;
48
49
  closeToTop.current = scrollTop < scrolledUpThreshold;
49
50
  if (closeToBottom.current) {
50
51
  setHasNewMessages(false);
@@ -31,7 +31,9 @@ export const useUnreadMessagesNotification = ({ isMessageListScrolledToBottom, s
31
31
  }
32
32
  const scrolledBelowSeparator = targetScrolledAboveVisibleContainerArea(observedTarget);
33
33
  const scrolledAboveSeparator = targetScrolledBelowVisibleContainerArea(observedTarget, msgListPanel);
34
- setShow(showAlways ? scrolledBelowSeparator || scrolledAboveSeparator : scrolledBelowSeparator);
34
+ setShow(showAlways
35
+ ? scrolledBelowSeparator || scrolledAboveSeparator
36
+ : scrolledBelowSeparator);
35
37
  const observer = new IntersectionObserver((elements) => {
36
38
  if (!elements.length)
37
39
  return;
@@ -61,7 +63,9 @@ export const useUnreadMessagesNotification = ({ isMessageListScrolledToBottom, s
61
63
  * The intersection observer is not triggered when Element.scrollTo() is called. So we end up in a situation when we are scrolled to the bottom
62
64
  * and at the same time scrolled above the observed target.
63
65
  */
64
- if (unreadCount && isMessageListScrolledToBottom && isScrolledAboveTargetTop.current) {
66
+ if (unreadCount &&
67
+ isMessageListScrolledToBottom &&
68
+ isScrolledAboveTargetTop.current) {
65
69
  setShow(true);
66
70
  isScrolledAboveTargetTop.current = false;
67
71
  }
@@ -4,7 +4,7 @@ export const useMessageSetKey = ({ messages, }) => {
4
4
  * Logic to update the key of the virtuoso component when the list jumps to a new location.
5
5
  */
6
6
  const [messageSetKey, setMessageSetKey] = useState(+new Date());
7
- const firstMessageId = useRef();
7
+ const firstMessageId = useRef(undefined);
8
8
  useEffect(() => {
9
9
  const continuousSet = messages?.find((message) => message.id === firstMessageId.current);
10
10
  if (!continuousSet) {
@@ -2,7 +2,7 @@
2
2
  import type { StreamMessage } from '../../../../context/ChannelStateContext';
3
3
  import type { DefaultStreamChatGenerics } from '../../../../types/types';
4
4
  export declare function useNewMessageNotification<StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics>(messages: StreamMessage<StreamChatGenerics>[], currentUserId: string | undefined, hasMoreNewer?: boolean): {
5
- atBottom: import("react").MutableRefObject<boolean>;
5
+ atBottom: import("react").RefObject<boolean>;
6
6
  isMessageListScrolledToBottom: boolean;
7
7
  newMessagesNotification: boolean;
8
8
  setIsMessageListScrolledToBottom: import("react").Dispatch<import("react").SetStateAction<boolean>>;