stream-chat-react 12.0.0-rc.9 → 12.1.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 (161) hide show
  1. package/dist/components/Avatar/Avatar.js +5 -1
  2. package/dist/components/Channel/Channel.d.ts +5 -106
  3. package/dist/components/Channel/Channel.js +76 -24
  4. package/dist/components/Channel/hooks/useCreateChannelStateContext.js +2 -1
  5. package/dist/components/ChannelHeader/ChannelHeader.js +4 -5
  6. package/dist/components/ChannelPreview/hooks/useChannelPreviewInfo.js +14 -16
  7. package/dist/components/ChannelPreview/utils.js +9 -20
  8. package/dist/components/ChannelSearch/hooks/useChannelSearch.js +2 -3
  9. package/dist/components/Chat/Chat.d.ts +1 -1
  10. package/dist/components/Chat/hooks/useChat.d.ts +2 -2
  11. package/dist/components/Chat/hooks/useChat.js +11 -8
  12. package/dist/components/ChatView/ChatView.d.ts +18 -0
  13. package/dist/components/ChatView/ChatView.js +103 -0
  14. package/dist/components/ChatView/index.d.ts +1 -0
  15. package/dist/components/ChatView/index.js +1 -0
  16. package/dist/components/DateSeparator/DateSeparator.d.ts +1 -1
  17. package/dist/components/Dialog/DialogAnchor.d.ts +25 -0
  18. package/dist/components/Dialog/DialogAnchor.js +68 -0
  19. package/dist/components/Dialog/DialogManager.d.ts +43 -0
  20. package/dist/components/Dialog/DialogManager.js +98 -0
  21. package/dist/components/Dialog/DialogPortal.d.ts +7 -0
  22. package/dist/components/Dialog/DialogPortal.js +25 -0
  23. package/dist/components/Dialog/hooks/index.d.ts +1 -0
  24. package/dist/components/Dialog/hooks/index.js +1 -0
  25. package/dist/components/Dialog/hooks/useDialog.d.ts +4 -0
  26. package/dist/components/Dialog/hooks/useDialog.js +26 -0
  27. package/dist/components/Dialog/index.d.ts +4 -0
  28. package/dist/components/Dialog/index.js +4 -0
  29. package/dist/components/EventComponent/EventComponent.d.ts +1 -1
  30. package/dist/components/Message/Message.js +5 -6
  31. package/dist/components/Message/MessageOptions.d.ts +1 -2
  32. package/dist/components/Message/MessageOptions.js +14 -11
  33. package/dist/components/Message/MessageSimple.js +6 -14
  34. package/dist/components/Message/MessageTimestamp.d.ts +1 -1
  35. package/dist/components/Message/QuotedMessage.js +2 -1
  36. package/dist/components/Message/Timestamp.d.ts +1 -1
  37. package/dist/components/Message/Timestamp.js +2 -2
  38. package/dist/components/Message/hooks/useReactionHandler.d.ts +1 -7
  39. package/dist/components/Message/hooks/useReactionHandler.js +8 -63
  40. package/dist/components/Message/utils.d.ts +10 -1
  41. package/dist/components/Message/utils.js +19 -7
  42. package/dist/components/MessageActions/MessageActions.d.ts +1 -2
  43. package/dist/components/MessageActions/MessageActions.js +26 -55
  44. package/dist/components/MessageActions/MessageActionsBox.d.ts +1 -1
  45. package/dist/components/MessageActions/MessageActionsBox.js +6 -6
  46. package/dist/components/MessageInput/MessageInputFlat.js +2 -2
  47. package/dist/components/MessageInput/QuotedMessagePreview.js +2 -1
  48. package/dist/components/MessageInput/hooks/useUserTrigger.js +0 -1
  49. package/dist/components/MessageList/MessageList.js +9 -9
  50. package/dist/components/MessageList/MessageListMainPanel.d.ts +1 -1
  51. package/dist/components/MessageList/MessageListMainPanel.js +1 -1
  52. package/dist/components/MessageList/VirtualizedMessageList.d.ts +2 -1
  53. package/dist/components/MessageList/VirtualizedMessageList.js +45 -40
  54. package/dist/components/MessageList/VirtualizedMessageListComponents.d.ts +1 -1
  55. package/dist/components/MessageList/VirtualizedMessageListComponents.js +6 -6
  56. package/dist/components/MessageList/hooks/MessageList/useUnreadMessagesNotification.js +2 -2
  57. package/dist/components/MessageList/renderMessages.d.ts +2 -2
  58. package/dist/components/MessageList/renderMessages.js +4 -1
  59. package/dist/components/MessageList/utils.js +1 -1
  60. package/dist/components/Reactions/ReactionSelector.d.ts +6 -3
  61. package/dist/components/Reactions/ReactionSelector.js +34 -24
  62. package/dist/components/Reactions/ReactionSelectorWithButton.d.ts +13 -0
  63. package/dist/components/Reactions/ReactionSelectorWithButton.js +22 -0
  64. package/dist/components/Reactions/ReactionsList.d.ts +4 -4
  65. package/dist/components/Reactions/hooks/useProcessReactions.js +2 -1
  66. package/dist/components/Thread/Thread.js +38 -10
  67. package/dist/components/Threads/ThreadContext.d.ts +9 -0
  68. package/dist/components/Threads/ThreadContext.js +9 -0
  69. package/dist/components/Threads/ThreadList/ThreadList.d.ts +9 -0
  70. package/dist/components/Threads/ThreadList/ThreadList.js +41 -0
  71. package/dist/components/Threads/ThreadList/ThreadListEmptyPlaceholder.d.ts +2 -0
  72. package/dist/components/Threads/ThreadList/ThreadListEmptyPlaceholder.js +5 -0
  73. package/dist/components/Threads/ThreadList/ThreadListItem.d.ts +9 -0
  74. package/dist/components/Threads/ThreadList/ThreadListItem.js +52 -0
  75. package/dist/components/Threads/ThreadList/ThreadListItemUI.d.ts +15 -0
  76. package/dist/components/Threads/ThreadList/ThreadListItemUI.js +75 -0
  77. package/dist/components/Threads/ThreadList/ThreadListLoadingIndicator.d.ts +2 -0
  78. package/dist/components/Threads/ThreadList/ThreadListLoadingIndicator.js +14 -0
  79. package/dist/components/Threads/ThreadList/ThreadListUnseenThreadsBanner.d.ts +2 -0
  80. package/dist/components/Threads/ThreadList/ThreadListUnseenThreadsBanner.js +16 -0
  81. package/dist/components/Threads/ThreadList/index.d.ts +3 -0
  82. package/dist/components/Threads/ThreadList/index.js +3 -0
  83. package/dist/components/Threads/UnreadCountBadge.d.ts +6 -0
  84. package/dist/components/Threads/UnreadCountBadge.js +5 -0
  85. package/dist/components/Threads/hooks/useThreadManagerState.d.ts +2 -0
  86. package/dist/components/Threads/hooks/useThreadManagerState.js +6 -0
  87. package/dist/components/Threads/hooks/useThreadState.d.ts +5 -0
  88. package/dist/components/Threads/hooks/useThreadState.js +11 -0
  89. package/dist/components/Threads/icons.d.ts +8 -0
  90. package/dist/components/Threads/icons.js +13 -0
  91. package/dist/components/Threads/index.d.ts +2 -0
  92. package/dist/components/Threads/index.js +2 -0
  93. package/dist/components/index.d.ts +3 -0
  94. package/dist/components/index.js +3 -0
  95. package/dist/context/ComponentContext.d.ts +64 -40
  96. package/dist/context/ComponentContext.js +7 -9
  97. package/dist/context/DialogManagerContext.d.ts +10 -0
  98. package/dist/context/DialogManagerContext.js +14 -0
  99. package/dist/context/MessageContext.d.ts +3 -11
  100. package/dist/context/MessageContext.js +3 -2
  101. package/dist/context/TranslationContext.d.ts +1 -11
  102. package/dist/context/TranslationContext.js +1 -9
  103. package/dist/context/WithComponents.d.ts +5 -0
  104. package/dist/context/WithComponents.js +7 -0
  105. package/dist/context/index.d.ts +2 -0
  106. package/dist/context/index.js +2 -0
  107. package/dist/css/v2/index.css +2 -2
  108. package/dist/css/v2/index.layout.css +2 -2
  109. package/dist/i18n/Streami18n.d.ts +1 -3
  110. package/dist/i18n/Streami18n.js +1 -2
  111. package/dist/i18n/index.d.ts +2 -1
  112. package/dist/i18n/index.js +2 -0
  113. package/dist/i18n/types.d.ts +26 -0
  114. package/dist/i18n/types.js +1 -0
  115. package/dist/i18n/utils.d.ts +9 -20
  116. package/dist/i18n/utils.js +10 -1
  117. package/dist/index.browser.cjs +10823 -10583
  118. package/dist/index.browser.cjs.map +4 -4
  119. package/dist/index.d.ts +1 -0
  120. package/dist/index.js +1 -0
  121. package/dist/index.node.cjs +10765 -10541
  122. package/dist/index.node.cjs.map +4 -4
  123. package/dist/plugins/Emojis/index.browser.cjs +7 -169
  124. package/dist/plugins/Emojis/index.browser.cjs.map +4 -4
  125. package/dist/plugins/Emojis/index.node.cjs +7 -169
  126. package/dist/plugins/Emojis/index.node.cjs.map +4 -4
  127. package/dist/plugins/encoders/mp3.browser.cjs +2 -4
  128. package/dist/plugins/encoders/mp3.browser.cjs.map +1 -1
  129. package/dist/plugins/encoders/mp3.node.cjs +2 -4
  130. package/dist/plugins/encoders/mp3.node.cjs.map +1 -1
  131. package/dist/scss/v2/Avatar/Avatar-layout.scss +10 -2
  132. package/dist/scss/v2/Avatar/Avatar-theme.scss +5 -0
  133. package/dist/scss/v2/ChatView/ChatView-layout.scss +43 -0
  134. package/dist/scss/v2/ChatView/ChatView-theme.scss +32 -0
  135. package/dist/scss/v2/Dialog/Dialog-layout.scss +8 -0
  136. package/dist/scss/v2/LoadingIndicator/LoadingIndicator-layout.scss +16 -0
  137. package/dist/scss/v2/Message/Message-layout.scss +8 -0
  138. package/dist/scss/v2/MessageActionsBox/MessageActionsBox-theme.scss +8 -0
  139. package/dist/scss/v2/MessageList/MessageList-layout.scss +0 -6
  140. package/dist/scss/v2/MessageList/VirtualizedMessageList-layout.scss +0 -12
  141. package/dist/scss/v2/MessageReactions/MessageReactionsSelector-layout.scss +16 -0
  142. package/dist/scss/v2/MessageReactions/MessageReactionsSelector-theme.scss +6 -0
  143. package/dist/scss/v2/Thread/Thread-layout.scss +15 -1
  144. package/dist/scss/v2/ThreadList/ThreadList-layout.scss +152 -0
  145. package/dist/scss/v2/ThreadList/ThreadList-theme.scss +75 -0
  146. package/dist/scss/v2/UnreadCountBadge/UnreadCountBadge-layout.scss +49 -0
  147. package/dist/scss/v2/UnreadCountBadge/UnreadCountBadge-theme.scss +11 -0
  148. package/dist/scss/v2/_base.scss +31 -0
  149. package/dist/scss/v2/index.layout.scss +4 -0
  150. package/dist/scss/v2/index.scss +3 -0
  151. package/dist/store/hooks/index.d.ts +1 -0
  152. package/dist/store/hooks/index.js +1 -0
  153. package/dist/store/hooks/useStateStore.d.ts +3 -0
  154. package/dist/store/hooks/useStateStore.js +15 -0
  155. package/dist/store/index.d.ts +1 -0
  156. package/dist/store/index.js +1 -0
  157. package/package.json +7 -6
  158. package/dist/assets/Poweredby_100px-White_VertText.png +0 -0
  159. package/dist/assets/str-chat__reaction-list-sprite@1x.png +0 -0
  160. package/dist/assets/str-chat__reaction-list-sprite@2x.png +0 -0
  161. package/dist/assets/str-chat__reaction-list-sprite@3x.png +0 -0
@@ -6,11 +6,15 @@ import { useGiphyPreview, useMessageSetKey, useNewMessageNotification, usePrepen
6
6
  import { useMarkRead } from './hooks/useMarkRead';
7
7
  import { MessageNotification as DefaultMessageNotification } from './MessageNotification';
8
8
  import { MessageListNotifications as DefaultMessageListNotifications } from './MessageListNotifications';
9
- import { MessageListMainPanel } from './MessageListMainPanel';
9
+ import { MessageListMainPanel as DefaultMessageListMainPanel } from './MessageListMainPanel';
10
10
  import { getGroupStyles, getLastReceived, processMessages, } from './utils';
11
11
  import { MessageSimple } from '../Message';
12
12
  import { UnreadMessagesNotification as DefaultUnreadMessagesNotification } from './UnreadMessagesNotification';
13
13
  import { calculateFirstItemIndex, calculateItemIndex, EmptyPlaceholder, Header, Item, makeItemsRenderedHandler, messageRenderer, } from './VirtualizedMessageListComponents';
14
+ import { UnreadMessagesSeparator as DefaultUnreadMessagesSeparator } from '../MessageList';
15
+ import { DateSeparator as DefaultDateSeparator } from '../DateSeparator';
16
+ import { EventComponent as DefaultMessageSystem } from '../EventComponent';
17
+ import { DialogManagerProvider } from '../../context';
14
18
  import { useChannelActionContext, } from '../../context/ChannelActionContext';
15
19
  import { useChannelStateContext, } from '../../context/ChannelStateContext';
16
20
  import { useChatContext } from '../../context/ChatContext';
@@ -53,7 +57,7 @@ const VirtualizedMessageListWithContext = (props) => {
53
57
  // Stops errors generated from react-virtuoso to bubble up
54
58
  // to Sentry or other tracking tools.
55
59
  useCaptureResizeObserverExceededError();
56
- const { DateSeparator, GiphyPreviewMessage = DefaultGiphyPreviewMessage, MessageListNotifications = DefaultMessageListNotifications, MessageNotification = DefaultMessageNotification, MessageSystem, UnreadMessagesNotification = DefaultUnreadMessagesNotification, UnreadMessagesSeparator, VirtualMessage: MessageUIComponentFromContext = MessageSimple, TypingIndicator, } = useComponentContext('VirtualizedMessageList');
60
+ const { DateSeparator = DefaultDateSeparator, GiphyPreviewMessage = DefaultGiphyPreviewMessage, MessageListNotifications = DefaultMessageListNotifications, MessageNotification = DefaultMessageNotification, MessageSystem = DefaultMessageSystem, MessageListMainPanel = DefaultMessageListMainPanel, UnreadMessagesNotification = DefaultUnreadMessagesNotification, UnreadMessagesSeparator = DefaultUnreadMessagesSeparator, VirtualMessage: MessageUIComponentFromContext = MessageSimple, TypingIndicator, } = useComponentContext('VirtualizedMessageList');
57
61
  const MessageUIComponent = MessageUIComponentFromProps || MessageUIComponentFromContext;
58
62
  const { client, customClasses } = useChatContext('VirtualizedMessageList');
59
63
  const virtuoso = useRef(null);
@@ -187,43 +191,44 @@ const VirtualizedMessageListWithContext = (props) => {
187
191
  return null;
188
192
  return (React.createElement(React.Fragment, null,
189
193
  React.createElement(MessageListMainPanel, null,
190
- !threadList && showUnreadMessagesNotification && (React.createElement(UnreadMessagesNotification, { unreadCount: channelUnreadUiState?.unread_messages })),
191
- React.createElement("div", { className: customClasses?.virtualizedMessageList || 'str-chat__virtual-list' },
192
- React.createElement(Virtuoso, { atBottomStateChange: atBottomStateChange, atBottomThreshold: 100, atTopStateChange: atTopStateChange, atTopThreshold: 100, className: 'str-chat__message-list-scroll', components: {
193
- EmptyPlaceholder,
194
- Header,
195
- Item,
196
- ...virtuosoComponentsFromProps,
197
- }, computeItemKey: computeItemKey, context: {
198
- additionalMessageInputProps,
199
- closeReactionSelectorOnClick,
200
- customClasses,
201
- customMessageActions,
202
- customMessageRenderer,
203
- DateSeparator,
204
- firstUnreadMessageId: channelUnreadUiState?.first_unread_message_id,
205
- formatDate,
206
- head,
207
- lastReadDate: channelUnreadUiState?.last_read,
208
- lastReadMessageId: channelUnreadUiState?.last_read_message_id,
209
- lastReceivedMessageId,
210
- loadingMore,
211
- Message: MessageUIComponent,
212
- messageActions,
213
- messageGroupStyles,
214
- MessageSystem,
215
- numItemsPrepended,
216
- ownMessagesReadByOthers,
217
- processedMessages,
218
- reactionDetailsSort,
219
- shouldGroupByUser,
220
- sortReactionDetails,
221
- sortReactions,
222
- threadList,
223
- unreadMessageCount: channelUnreadUiState?.unread_messages,
224
- UnreadMessagesSeparator,
225
- virtuosoRef: virtuoso,
226
- }, firstItemIndex: calculateFirstItemIndex(numItemsPrepended), followOutput: followOutput, increaseViewportBy: { bottom: 200, top: 0 }, initialTopMostItemIndex: calculateInitialTopMostItemIndex(processedMessages, highlightedMessageId), itemContent: messageRenderer, itemSize: fractionalItemSize, itemsRendered: handleItemsRendered, key: messageSetKey, overscan: overscan, ref: virtuoso, style: { overflowX: 'hidden' }, totalCount: processedMessages.length, ...overridingVirtuosoProps, ...(scrollSeekPlaceHolder ? { scrollSeek: scrollSeekPlaceHolder } : {}), ...(defaultItemHeight ? { defaultItemHeight } : {}) })),
194
+ React.createElement(DialogManagerProvider, { id: 'virtualized-message-list-dialog-manager' },
195
+ !threadList && showUnreadMessagesNotification && (React.createElement(UnreadMessagesNotification, { unreadCount: channelUnreadUiState?.unread_messages })),
196
+ React.createElement("div", { className: customClasses?.virtualizedMessageList || 'str-chat__virtual-list' },
197
+ React.createElement(Virtuoso, { atBottomStateChange: atBottomStateChange, atBottomThreshold: 100, atTopStateChange: atTopStateChange, atTopThreshold: 100, className: 'str-chat__message-list-scroll', components: {
198
+ EmptyPlaceholder,
199
+ Header,
200
+ Item,
201
+ ...virtuosoComponentsFromProps,
202
+ }, computeItemKey: computeItemKey, context: {
203
+ additionalMessageInputProps,
204
+ closeReactionSelectorOnClick,
205
+ customClasses,
206
+ customMessageActions,
207
+ customMessageRenderer,
208
+ DateSeparator,
209
+ firstUnreadMessageId: channelUnreadUiState?.first_unread_message_id,
210
+ formatDate,
211
+ head,
212
+ lastReadDate: channelUnreadUiState?.last_read,
213
+ lastReadMessageId: channelUnreadUiState?.last_read_message_id,
214
+ lastReceivedMessageId,
215
+ loadingMore,
216
+ Message: MessageUIComponent,
217
+ messageActions,
218
+ messageGroupStyles,
219
+ MessageSystem,
220
+ numItemsPrepended,
221
+ ownMessagesReadByOthers,
222
+ processedMessages,
223
+ reactionDetailsSort,
224
+ shouldGroupByUser,
225
+ sortReactionDetails,
226
+ sortReactions,
227
+ threadList,
228
+ unreadMessageCount: channelUnreadUiState?.unread_messages,
229
+ UnreadMessagesSeparator,
230
+ virtuosoRef: virtuoso,
231
+ }, firstItemIndex: calculateFirstItemIndex(numItemsPrepended), followOutput: followOutput, increaseViewportBy: { bottom: 200, top: 0 }, initialTopMostItemIndex: calculateInitialTopMostItemIndex(processedMessages, highlightedMessageId), itemContent: messageRenderer, itemSize: fractionalItemSize, itemsRendered: handleItemsRendered, key: messageSetKey, overscan: overscan, ref: virtuoso, style: { overflowX: 'hidden' }, totalCount: processedMessages.length, ...overridingVirtuosoProps, ...(scrollSeekPlaceHolder ? { scrollSeek: scrollSeekPlaceHolder } : {}), ...(defaultItemHeight ? { defaultItemHeight } : {}) }))),
227
232
  TypingIndicator && React.createElement(TypingIndicator, null)),
228
233
  React.createElement(MessageListNotifications, { hasNewMessages: newMessagesNotification, isMessageListScrolledToBottom: isMessageListScrolledToBottom, isNotAtLatestMessageSet: hasMoreNewer, MessageNotification: MessageNotification, notifications: notifications, scrollToBottom: scrollToBottom, threadList: threadList, unreadCount: threadList ? undefined : channelUnreadUiState?.unread_messages }),
229
234
  giphyPreviewMessage && React.createElement(GiphyPreviewMessage, { message: giphyPreviewMessage })));
@@ -236,5 +241,5 @@ export function VirtualizedMessageList(props) {
236
241
  const { jumpToLatestMessage, loadMore, loadMoreNewer, } = useChannelActionContext('VirtualizedMessageList');
237
242
  const { channel, channelUnreadUiState, hasMore, hasMoreNewer, highlightedMessageId, loadingMore, loadingMoreNewer, messages: contextMessages, notifications, read, suppressAutoscroll, } = useChannelStateContext('VirtualizedMessageList');
238
243
  const messages = props.messages || contextMessages;
239
- return (React.createElement(VirtualizedMessageListWithContext, { channel: channel, 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 }));
244
+ 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 }));
240
245
  }
@@ -11,7 +11,7 @@ type CommonVirtuosoComponentProps<StreamChatGenerics extends DefaultStreamChatGe
11
11
  context?: VirtuosoContext<StreamChatGenerics>;
12
12
  };
13
13
  export declare const Item: <StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics>({ context, ...props }: ItemProps & CommonVirtuosoComponentProps<StreamChatGenerics>) => React.JSX.Element;
14
- export declare const Header: <StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics>({ context, }: CommonVirtuosoComponentProps<StreamChatGenerics>) => React.JSX.Element | null;
14
+ export declare const Header: <StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics>({ context, }: CommonVirtuosoComponentProps<StreamChatGenerics>) => React.JSX.Element;
15
15
  export declare const EmptyPlaceholder: <StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics>({ context, }: CommonVirtuosoComponentProps<StreamChatGenerics>) => React.JSX.Element;
16
16
  export declare const messageRenderer: <StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics>(virtuosoIndex: number, _data: UnknownType, virtuosoContext: VirtuosoContext<StreamChatGenerics>) => React.JSX.Element | null;
17
17
  export {};
@@ -37,17 +37,17 @@ export const Item = ({ context, ...props }) => {
37
37
  };
38
38
  export const Header = ({ context, }) => {
39
39
  const { LoadingIndicator = DefaultLoadingIndicator } = useComponentContext('VirtualizedMessageListHeader');
40
- if (!context?.loadingMore)
41
- return null;
42
- return LoadingIndicator ? (React.createElement("div", { className: 'str-chat__virtual-list__loading' },
43
- React.createElement(LoadingIndicator, { size: 20 }))) : (context?.head || null);
40
+ return (React.createElement(React.Fragment, null,
41
+ context?.head,
42
+ context?.loadingMore && LoadingIndicator && (React.createElement("div", { className: 'str-chat__virtual-list__loading' },
43
+ React.createElement(LoadingIndicator, { size: 20 })))));
44
44
  };
45
45
  export const EmptyPlaceholder = ({ context, }) => {
46
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) => {
50
- const { additionalMessageInputProps, closeReactionSelectorOnClick, customMessageActions, customMessageRenderer, DateSeparator, firstUnreadMessageId, formatDate, lastReadDate, lastReadMessageId, lastReceivedMessageId, Message: MessageUIComponent, messageActions, messageGroupStyles, MessageSystem, numItemsPrepended, ownMessagesReadByOthers, processedMessages: messageList, reactionDetailsSort, shouldGroupByUser, sortReactionDetails, sortReactions, unreadMessageCount = 0, UnreadMessagesSeparator, virtuosoRef, } = virtuosoContext;
50
+ const { additionalMessageInputProps, closeReactionSelectorOnClick, customMessageActions, customMessageRenderer, DateSeparator, firstUnreadMessageId, formatDate, lastReadDate, lastReadMessageId, lastReceivedMessageId, Message: MessageUIComponent, messageActions, messageGroupStyles, MessageSystem, numItemsPrepended, ownMessagesReadByOthers, processedMessages: messageList, reactionDetailsSort, shouldGroupByUser, sortReactionDetails, sortReactions, threadList, unreadMessageCount = 0, UnreadMessagesSeparator, virtuosoRef, } = virtuosoContext;
51
51
  const streamMessageIndex = calculateItemIndex(virtuosoIndex, numItemsPrepended);
52
52
  if (customMessageRenderer) {
53
53
  return customMessageRenderer(messageList, streamMessageIndex);
@@ -89,7 +89,7 @@ export const messageRenderer = (virtuosoIndex, _data, virtuosoContext) => {
89
89
  return (React.createElement(React.Fragment, null,
90
90
  showUnreadSeparatorAbove && (React.createElement("div", { className: 'str-chat__unread-messages-separator-wrapper' },
91
91
  React.createElement(UnreadMessagesSeparator, { unreadCount: unreadMessageCount }))),
92
- React.createElement(Message, { additionalMessageInputProps: additionalMessageInputProps, autoscrollToBottom: virtuosoRef.current?.autoscrollToBottom, closeReactionSelectorOnClick: closeReactionSelectorOnClick, customMessageActions: customMessageActions, endOfGroup: endOfGroup, firstOfGroup: firstOfGroup, formatDate: formatDate, groupedByUser: groupedByUser, groupStyles: [messageGroupStyles[message.id] ?? ''], lastReceivedId: lastReceivedMessageId, message: message, Message: MessageUIComponent, messageActions: messageActions, reactionDetailsSort: reactionDetailsSort, readBy: ownMessagesReadByOthers[message.id] || [], sortReactionDetails: sortReactionDetails, sortReactions: sortReactions }),
92
+ React.createElement(Message, { additionalMessageInputProps: additionalMessageInputProps, autoscrollToBottom: virtuosoRef.current?.autoscrollToBottom, closeReactionSelectorOnClick: closeReactionSelectorOnClick, customMessageActions: customMessageActions, endOfGroup: endOfGroup, firstOfGroup: firstOfGroup, formatDate: formatDate, groupedByUser: groupedByUser, groupStyles: [messageGroupStyles[message.id] ?? ''], lastReceivedId: lastReceivedMessageId, message: message, Message: MessageUIComponent, messageActions: messageActions, reactionDetailsSort: reactionDetailsSort, readBy: ownMessagesReadByOthers[message.id] || [], sortReactionDetails: sortReactionDetails, sortReactions: sortReactions, threadList: threadList }),
93
93
  showUnreadSeparatorBelow && (React.createElement("div", { className: 'str-chat__unread-messages-separator-wrapper' },
94
94
  React.createElement(UnreadMessagesSeparator, { unreadCount: unreadMessageCount })))));
95
95
  };
@@ -21,10 +21,10 @@ export const useUnreadMessagesNotification = ({ isMessageListScrolledToBottom, s
21
21
  setShow(false);
22
22
  return;
23
23
  }
24
- const msgListPanel = document.querySelector(`.${MESSAGE_LIST_MAIN_PANEL_CLASS}`);
24
+ const [msgListPanel] = document.getElementsByClassName(MESSAGE_LIST_MAIN_PANEL_CLASS);
25
25
  if (!msgListPanel)
26
26
  return;
27
- const observedTarget = document.querySelector(`.${UNREAD_MESSAGE_SEPARATOR_CLASS}`);
27
+ const [observedTarget] = document.getElementsByClassName(UNREAD_MESSAGE_SEPARATOR_CLASS);
28
28
  if (!observedTarget) {
29
29
  setShow(true);
30
30
  return;
@@ -1,10 +1,10 @@
1
1
  import React, { ReactNode } from 'react';
2
+ import type { UserResponse } from 'stream-chat';
2
3
  import { GroupStyle } from './utils';
3
- import { MessageProps } from '../Message';
4
4
  import { ComponentContextValue, CustomClasses } from '../../context';
5
- import type { UserResponse } from 'stream-chat';
6
5
  import type { ChannelUnreadUiState, DefaultStreamChatGenerics } from '../../types';
7
6
  import type { StreamMessage } from '../../context/ChannelStateContext';
7
+ import type { MessageProps } from '../Message';
8
8
  export interface RenderMessagesOptions<StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics> {
9
9
  components: ComponentContextValue<StreamChatGenerics>;
10
10
  lastReceivedMessageId: string | null;
@@ -1,9 +1,12 @@
1
1
  import React, { Fragment } from 'react';
2
2
  import { isDateSeparatorMessage } from './utils';
3
3
  import { Message } from '../Message';
4
+ import { DateSeparator as DefaultDateSeparator } from '../DateSeparator';
5
+ import { EventComponent as DefaultMessageSystem } from '../EventComponent';
6
+ import { UnreadMessagesSeparator as DefaultUnreadMessagesSeparator } from './UnreadMessagesSeparator';
4
7
  import { CUSTOM_MESSAGE_TYPE } from '../../constants/messageTypes';
5
8
  export function defaultRenderMessages({ channelUnreadUiState, components, customClasses, lastReceivedMessageId: lastReceivedId, messageGroupStyles, messages, readData, sharedMessageProps: messageProps, }) {
6
- const { DateSeparator, HeaderComponent, MessageSystem, UnreadMessagesSeparator } = components;
9
+ const { DateSeparator = DefaultDateSeparator, HeaderComponent, MessageSystem = DefaultMessageSystem, UnreadMessagesSeparator = DefaultUnreadMessagesSeparator, } = components;
7
10
  const renderedMessages = [];
8
11
  let firstMessage;
9
12
  for (let index = 0; index < messages.length; index++) {
@@ -1,8 +1,8 @@
1
1
  /* eslint-disable no-continue */
2
2
  import { nanoid } from 'nanoid';
3
3
  import { CUSTOM_MESSAGE_TYPE } from '../../constants/messageTypes';
4
- import { isDate } from '../../context/TranslationContext';
5
4
  import { isMessageEdited } from '../Message/utils';
5
+ import { isDate } from '../../i18n';
6
6
  /**
7
7
  * processMessages - Transform the input message list according to config parameters
8
8
  *
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
- import { AvatarProps } from '../Avatar';
3
2
  import type { ReactionGroupResponse, ReactionResponse } from 'stream-chat';
3
+ import type { AvatarProps } from '../Avatar';
4
4
  import type { DefaultStreamChatGenerics } from '../../types/types';
5
5
  import type { ReactionOptions } from './reactionOptions';
6
6
  export type ReactionSelectorProps<StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics> = {
@@ -21,7 +21,10 @@ export type ReactionSelectorProps<StreamChatGenerics extends DefaultStreamChatGe
21
21
  reaction_counts?: Record<string, number>;
22
22
  /** An object containing summary for each reaction type on a message */
23
23
  reaction_groups?: Record<string, ReactionGroupResponse>;
24
- /** A list of the currently supported reactions on a message */
24
+ /**
25
+ * @deprecated
26
+ * A list of the currently supported reactions on a message
27
+ * */
25
28
  reactionOptions?: ReactionOptions;
26
29
  /** If true, adds a CSS class that reverses the horizontal positioning of the selector */
27
30
  reverse?: boolean;
@@ -29,4 +32,4 @@ export type ReactionSelectorProps<StreamChatGenerics extends DefaultStreamChatGe
29
32
  /**
30
33
  * Component that allows a user to select a reaction.
31
34
  */
32
- export declare const ReactionSelector: React.ForwardRefExoticComponent<ReactionSelectorProps<DefaultStreamChatGenerics> & React.RefAttributes<HTMLDivElement | null>>;
35
+ export declare const ReactionSelector: <StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics>(props: ReactionSelectorProps<StreamChatGenerics>) => React.JSX.Element;
@@ -1,13 +1,17 @@
1
1
  import React, { useCallback, useEffect, useRef, useState } from 'react';
2
2
  import clsx from 'clsx';
3
- import { isMutableRef } from './utils/utils';
4
3
  import { Avatar as DefaultAvatar } from '../Avatar';
4
+ import { useDialog } from '../Dialog';
5
+ import { defaultReactionOptions } from './reactionOptions';
6
+ import { isMutableRef } from './utils/utils';
5
7
  import { useComponentContext } from '../../context/ComponentContext';
6
8
  import { useMessageContext } from '../../context/MessageContext';
7
- const UnMemoizedReactionSelector = React.forwardRef((props, ref) => {
9
+ const UnMemoizedReactionSelector = (props) => {
8
10
  const { Avatar: propAvatar, detailedView = true, handleReaction: propHandleReaction, latest_reactions: propLatestReactions, own_reactions: propOwnReactions, reaction_groups: propReactionGroups, reactionOptions: propReactionOptions, reverse = false, } = props;
9
- const { Avatar: contextAvatar, reactionOptions: contextReactionOptions, } = useComponentContext('ReactionSelector');
10
- const { handleReaction: contextHandleReaction, message, } = useMessageContext('ReactionSelector');
11
+ const { Avatar: contextAvatar, reactionOptions: contextReactionOptions = defaultReactionOptions, } = useComponentContext('ReactionSelector');
12
+ const { closeReactionSelectorOnClick, handleReaction: contextHandleReaction, message, } = useMessageContext('ReactionSelector');
13
+ const dialogId = `reaction-selector--${message.id}`;
14
+ const dialog = useDialog({ id: dialogId });
11
15
  const reactionOptions = propReactionOptions ?? contextReactionOptions;
12
16
  const Avatar = propAvatar || contextAvatar || DefaultAvatar;
13
17
  const handleReaction = propHandleReaction || contextHandleReaction;
@@ -16,6 +20,7 @@ const UnMemoizedReactionSelector = React.forwardRef((props, ref) => {
16
20
  const reactionGroups = propReactionGroups || message?.reaction_groups || {};
17
21
  const [tooltipReactionType, setTooltipReactionType] = useState(null);
18
22
  const [tooltipPositions, setTooltipPositions] = useState(null);
23
+ const rootRef = useRef(null);
19
24
  const targetRef = useRef(null);
20
25
  const tooltipRef = useRef(null);
21
26
  const showTooltip = useCallback((event, reactionType) => {
@@ -27,22 +32,22 @@ const UnMemoizedReactionSelector = React.forwardRef((props, ref) => {
27
32
  setTooltipPositions(null);
28
33
  }, []);
29
34
  useEffect(() => {
30
- if (tooltipReactionType) {
31
- const tooltip = tooltipRef.current?.getBoundingClientRect();
32
- const target = targetRef.current?.getBoundingClientRect();
33
- const container = isMutableRef(ref) ? ref.current?.getBoundingClientRect() : null;
34
- if (!tooltip || !target || !container)
35
- return;
36
- const tooltipPosition = tooltip.width === container.width || tooltip.x < container.x
37
- ? 0
38
- : target.left + target.width / 2 - container.left - tooltip.width / 2;
39
- const arrowPosition = target.x - tooltip.x + target.width / 2 - tooltipPosition;
40
- setTooltipPositions({
41
- arrow: arrowPosition,
42
- tooltip: tooltipPosition,
43
- });
44
- }
45
- }, [tooltipReactionType, ref]);
35
+ if (!tooltipReactionType || !rootRef.current)
36
+ return;
37
+ const tooltip = tooltipRef.current?.getBoundingClientRect();
38
+ const target = targetRef.current?.getBoundingClientRect();
39
+ const container = isMutableRef(rootRef) ? rootRef.current?.getBoundingClientRect() : null;
40
+ if (!tooltip || !target || !container)
41
+ return;
42
+ const tooltipPosition = tooltip.width === container.width || tooltip.x < container.x
43
+ ? 0
44
+ : target.left + target.width / 2 - container.left - tooltip.width / 2;
45
+ const arrowPosition = target.x - tooltip.x + target.width / 2 - tooltipPosition;
46
+ setTooltipPositions({
47
+ arrow: arrowPosition,
48
+ tooltip: tooltipPosition,
49
+ });
50
+ }, [tooltipReactionType, rootRef]);
46
51
  const getUsersPerReactionType = (type) => latestReactions
47
52
  .map((reaction) => {
48
53
  if (reaction.type === type) {
@@ -54,9 +59,9 @@ const UnMemoizedReactionSelector = React.forwardRef((props, ref) => {
54
59
  const iHaveReactedWithReaction = (reactionType) => ownReactions.find((reaction) => reaction.type === reactionType);
55
60
  const getLatestUserForReactionType = (type) => latestReactions.find((reaction) => reaction.type === type && !!reaction.user)?.user ||
56
61
  undefined;
57
- return (React.createElement("div", { className: clsx('str-chat__reaction-selector str-chat__message-reaction-selector', {
62
+ return (React.createElement("div", { className: clsx('str-chat__reaction-selector str-chat__message-reaction-selector str-chat-react__message-reaction-selector', {
58
63
  'str-chat__reaction-selector--reverse': reverse,
59
- }), "data-testid": 'reaction-selector', ref: ref },
64
+ }), "data-testid": 'reaction-selector', ref: rootRef },
60
65
  !!tooltipReactionType && detailedView && (React.createElement("div", { className: 'str-chat__reaction-selector-tooltip', ref: tooltipRef, style: {
61
66
  left: tooltipPositions?.tooltip,
62
67
  visibility: tooltipPositions ? 'visible' : 'hidden',
@@ -69,13 +74,18 @@ const UnMemoizedReactionSelector = React.forwardRef((props, ref) => {
69
74
  return (React.createElement("li", { key: reactionType },
70
75
  React.createElement("button", { "aria-label": `Select Reaction: ${reactionName || reactionType}`, className: clsx('str-chat__message-reactions-list-item str-chat__message-reactions-option', {
71
76
  'str-chat__message-reactions-option-selected': iHaveReactedWithReaction(reactionType),
72
- }), "data-text": reactionType, onClick: (event) => handleReaction(reactionType, event) },
77
+ }), "data-testid": 'select-reaction-button', "data-text": reactionType, onClick: (event) => {
78
+ handleReaction(reactionType, event);
79
+ if (closeReactionSelectorOnClick) {
80
+ dialog.close();
81
+ }
82
+ } },
73
83
  !!count && detailedView && (React.createElement("div", { className: 'latest-user str-chat__message-reactions-last-user', onClick: hideTooltip, onMouseEnter: (e) => showTooltip(e, reactionType), onMouseLeave: hideTooltip }, latestUser ? (React.createElement(Avatar, { image: latestUser.image, name: latestUser.name, size: 20, user: latestUser })) : (React.createElement("div", { className: 'latest-user-not-found' })))),
74
84
  React.createElement("span", { className: 'str-chat__message-reaction-emoji' },
75
85
  React.createElement(Component, null)),
76
86
  Boolean(count) && detailedView && (React.createElement("span", { className: 'str-chat__message-reactions-list-item__count' }, count || '')))));
77
87
  }))));
78
- });
88
+ };
79
89
  /**
80
90
  * Component that allows a user to select a reaction.
81
91
  */
@@ -0,0 +1,13 @@
1
+ import React from 'react';
2
+ import type { DefaultStreamChatGenerics } from '../../types';
3
+ import type { IconProps } from '../../types/types';
4
+ type ReactionSelectorWithButtonProps = {
5
+ ReactionIcon: React.ComponentType<IconProps>;
6
+ theme: string;
7
+ };
8
+ /**
9
+ * Internal convenience component - not to be exported. It just groups the button and the dialog anchor and thus prevents
10
+ * cluttering the parent component.
11
+ */
12
+ export declare const ReactionSelectorWithButton: <StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics>({ ReactionIcon, theme, }: ReactionSelectorWithButtonProps) => React.JSX.Element;
13
+ export {};
@@ -0,0 +1,22 @@
1
+ import React, { useRef } from 'react';
2
+ import { ReactionSelector as DefaultReactionSelector } from './ReactionSelector';
3
+ import { DialogAnchor, useDialog, useDialogIsOpen } from '../Dialog';
4
+ import { useComponentContext, useMessageContext, useTranslationContext } from '../../context';
5
+ /**
6
+ * Internal convenience component - not to be exported. It just groups the button and the dialog anchor and thus prevents
7
+ * cluttering the parent component.
8
+ */
9
+ export const ReactionSelectorWithButton = ({ ReactionIcon, theme, }) => {
10
+ const { t } = useTranslationContext('ReactionSelectorWithButton');
11
+ const { isMyMessage, message } = useMessageContext('MessageOptions');
12
+ const { ReactionSelector = DefaultReactionSelector } = useComponentContext('MessageOptions');
13
+ const buttonRef = useRef(null);
14
+ const dialogId = `reaction-selector--${message.id}`;
15
+ const dialog = useDialog({ id: dialogId });
16
+ const dialogIsOpen = useDialogIsOpen(dialogId);
17
+ return (React.createElement(React.Fragment, null,
18
+ React.createElement(DialogAnchor, { id: dialogId, placement: isMyMessage() ? 'top-end' : 'top-start', referenceElement: buttonRef.current, trapFocus: true },
19
+ React.createElement(ReactionSelector, null)),
20
+ React.createElement("button", { "aria-expanded": dialogIsOpen, "aria-label": t('aria/Open Reaction Selector'), className: `str-chat__message-${theme}__actions__action str-chat__message-${theme}__actions__action--reactions str-chat__message-reactions-button`, "data-testid": 'message-reaction-action', onClick: () => dialog?.toggle(), ref: buttonRef },
21
+ React.createElement(ReactionIcon, { className: 'str-chat__message-action-icon' }))));
22
+ };
@@ -1,13 +1,10 @@
1
1
  import React from 'react';
2
2
  import type { ReactionGroupResponse, ReactionResponse } from 'stream-chat';
3
- import type { ReactEventHandler } from '../Message/types';
4
3
  import type { DefaultStreamChatGenerics } from '../../types/types';
5
4
  import type { ReactionOptions } from './reactionOptions';
6
5
  import type { ReactionDetailsComparator, ReactionsComparator } from './types';
7
6
  import { MessageContextValue } from '../../context';
8
7
  export type ReactionsListProps<StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics> = Partial<Pick<MessageContextValue<StreamChatGenerics>, 'handleFetchReactions' | 'reactionDetailsSort'>> & {
9
- /** Custom on click handler for an individual reaction, defaults to `onReactionListClick` from the `MessageContext` */
10
- onClick?: ReactEventHandler;
11
8
  /** An array of the own reaction objects to distinguish own reactions visually */
12
9
  own_reactions?: ReactionResponse<StreamChatGenerics>[];
13
10
  /**
@@ -17,7 +14,10 @@ export type ReactionsListProps<StreamChatGenerics extends DefaultStreamChatGener
17
14
  reaction_counts?: Record<string, number>;
18
15
  /** An object containing summary for each reaction type on a message */
19
16
  reaction_groups?: Record<string, ReactionGroupResponse>;
20
- /** A list of the currently supported reactions on a message */
17
+ /**
18
+ * @deprecated
19
+ * A list of the currently supported reactions on a message
20
+ * */
21
21
  reactionOptions?: ReactionOptions;
22
22
  /** An array of the reaction objects to display in the list */
23
23
  reactions?: ReactionResponse<StreamChatGenerics>[];
@@ -1,5 +1,6 @@
1
1
  import { useCallback, useMemo } from 'react';
2
2
  import { useComponentContext, useMessageContext } from '../../../context';
3
+ import { defaultReactionOptions } from '../reactionOptions';
3
4
  export const defaultReactionsSort = (a, b) => {
4
5
  if (a.firstReactionAt && b.firstReactionAt) {
5
6
  return +a.firstReactionAt - +b.firstReactionAt;
@@ -9,7 +10,7 @@ export const defaultReactionsSort = (a, b) => {
9
10
  export const useProcessReactions = (params) => {
10
11
  const { own_reactions: propOwnReactions, reaction_groups: propReactionGroups, reactionOptions: propReactionOptions, reactions: propReactions, sortReactions: propSortReactions, } = params;
11
12
  const { message, sortReactions: contextSortReactions } = useMessageContext('useProcessReactions');
12
- const { reactionOptions: contextReactionOptions } = useComponentContext('useProcessReactions');
13
+ const { reactionOptions: contextReactionOptions = defaultReactionOptions, } = useComponentContext('useProcessReactions');
13
14
  const reactionOptions = propReactionOptions ?? contextReactionOptions;
14
15
  const sortReactions = propSortReactions ?? contextSortReactions ?? defaultReactionsSort;
15
16
  const latestReactions = propReactions || message.latest_reactions;
@@ -6,19 +6,32 @@ import { MessageList, VirtualizedMessageList, } from '../MessageList';
6
6
  import { ThreadHeader as DefaultThreadHeader } from './ThreadHeader';
7
7
  import { ThreadHead as DefaultThreadHead } from '../Thread/ThreadHead';
8
8
  import { useChannelActionContext, useChannelStateContext, useChatContext, useComponentContext, } from '../../context';
9
+ import { useThreadContext } from '../Threads';
10
+ import { useStateStore } from '../../store';
9
11
  /**
10
12
  * The Thread component renders a parent Message with a list of replies
11
13
  */
12
14
  export const Thread = (props) => {
13
15
  const { channel, channelConfig, thread } = useChannelStateContext('Thread');
14
- if (!thread || channelConfig?.replies === false)
16
+ const threadInstance = useThreadContext();
17
+ if ((!thread && !threadInstance) || channelConfig?.replies === false)
15
18
  return null;
16
- // The wrapper ensures a key variable is set and the component recreates on thread switch
17
- return React.createElement(ThreadInner, { ...props, key: `thread-${thread.id}-${channel?.cid}` });
19
+ // the wrapper ensures a key variable is set and the component recreates on thread switch
20
+ return (
21
+ // FIXME: TS is having trouble here as at least one of the two would always be defined
22
+ React.createElement(ThreadInner, { ...props, key: `thread-${(thread ?? threadInstance)?.id}-${channel?.cid}` }));
18
23
  };
24
+ const selector = (nextValue) => [
25
+ nextValue.replies,
26
+ nextValue.pagination.isLoadingPrev,
27
+ nextValue.pagination.isLoadingNext,
28
+ nextValue.parentMessage,
29
+ ];
19
30
  const ThreadInner = (props) => {
20
31
  const { additionalMessageInputProps, additionalMessageListProps, additionalParentMessageProps, additionalVirtualizedMessageListProps, autoFocus = true, enableDateSeparator = false, Input: PropInput, Message: PropMessage, messageActions = Object.keys(MESSAGE_ACTIONS), virtualized, } = props;
21
- const { thread, threadHasMore, threadLoadingMore, threadMessages, threadSuppressAutoscroll, } = useChannelStateContext('Thread');
32
+ const threadInstance = useThreadContext();
33
+ const [latestReplies, isLoadingPrev, isLoadingNext, parentMessage] = useStateStore(threadInstance?.state, selector) ?? [];
34
+ const { thread, threadHasMore, threadLoadingMore, threadMessages = [], threadSuppressAutoscroll, } = useChannelStateContext('Thread');
22
35
  const { closeThread, loadMoreThread } = useChannelActionContext('Thread');
23
36
  const { customClasses } = useChatContext('Thread');
24
37
  const { ThreadInput: ContextInput, Message: ContextMessage, ThreadHead = DefaultThreadHead, ThreadHeader = DefaultThreadHeader, VirtualMessage, } = useComponentContext('Thread');
@@ -33,16 +46,31 @@ const ThreadInner = (props) => {
33
46
  loadMoreThread();
34
47
  }
35
48
  // eslint-disable-next-line react-hooks/exhaustive-deps
36
- }, []);
37
- if (!thread)
49
+ }, [thread, loadMoreThread]);
50
+ const threadProps = threadInstance
51
+ ? {
52
+ loadingMore: isLoadingPrev,
53
+ loadingMoreNewer: isLoadingNext,
54
+ loadMore: threadInstance.loadPrevPage,
55
+ loadMoreNewer: threadInstance.loadNextPage,
56
+ messages: latestReplies,
57
+ }
58
+ : {
59
+ hasMore: threadHasMore,
60
+ loadingMore: threadLoadingMore,
61
+ loadMore: loadMoreThread,
62
+ messages: threadMessages,
63
+ };
64
+ const messageAsThread = thread ?? parentMessage;
65
+ if (!messageAsThread)
38
66
  return null;
39
67
  const threadClass = customClasses?.thread ||
40
68
  clsx('str-chat__thread-container str-chat__thread', {
41
69
  'str-chat__thread--virtualized': virtualized,
42
70
  });
43
- const head = (React.createElement(ThreadHead, { key: thread.id, message: thread, Message: MessageUIComponent, ...additionalParentMessageProps }));
71
+ const head = (React.createElement(ThreadHead, { key: messageAsThread.id, message: messageAsThread, Message: MessageUIComponent, ...additionalParentMessageProps }));
44
72
  return (React.createElement("div", { className: threadClass },
45
- React.createElement(ThreadHeader, { closeThread: closeThread, thread: thread }),
46
- React.createElement(ThreadMessageList, { disableDateSeparator: !enableDateSeparator, hasMore: threadHasMore, head: head, loadingMore: threadLoadingMore, loadMore: loadMoreThread, Message: MessageUIComponent, messageActions: messageActions, messages: threadMessages || [], suppressAutoscroll: threadSuppressAutoscroll, threadList: true, ...(virtualized ? additionalVirtualizedMessageListProps : additionalMessageListProps) }),
47
- React.createElement(MessageInput, { focus: autoFocus, Input: ThreadInput, parent: thread, publishTypingEvent: false, ...additionalMessageInputProps })));
73
+ React.createElement(ThreadHeader, { closeThread: closeThread, thread: messageAsThread }),
74
+ React.createElement(ThreadMessageList, { disableDateSeparator: !enableDateSeparator, head: head, Message: MessageUIComponent, messageActions: messageActions, suppressAutoscroll: threadSuppressAutoscroll, threadList: true, ...threadProps, ...(virtualized ? additionalVirtualizedMessageListProps : additionalMessageListProps) }),
75
+ React.createElement(MessageInput, { focus: autoFocus, Input: ThreadInput, parent: thread ?? parentMessage, publishTypingEvent: false, ...additionalMessageInputProps })));
48
76
  };
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import type { PropsWithChildren } from 'react';
3
+ import { Thread } from 'stream-chat';
4
+ export type ThreadContextValue = Thread | undefined;
5
+ export declare const ThreadContext: React.Context<ThreadContextValue>;
6
+ export declare const useThreadContext: () => Thread<import("stream-chat").DefaultGenerics> | undefined;
7
+ export declare const ThreadProvider: ({ children, thread }: PropsWithChildren<{
8
+ thread?: Thread;
9
+ }>) => React.JSX.Element;
@@ -0,0 +1,9 @@
1
+ import React, { createContext, useContext } from 'react';
2
+ import { Channel } from '../../components';
3
+ export const ThreadContext = createContext(undefined);
4
+ export const useThreadContext = () => {
5
+ const thread = useContext(ThreadContext);
6
+ return thread ?? undefined;
7
+ };
8
+ export const ThreadProvider = ({ children, thread }) => (React.createElement(ThreadContext.Provider, { value: thread },
9
+ React.createElement(Channel, { channel: thread?.channel }, children)));
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import { VirtuosoProps } from 'react-virtuoso';
3
+ import type { Thread } from 'stream-chat';
4
+ type ThreadListProps = {
5
+ virtuosoProps?: VirtuosoProps<Thread, unknown>;
6
+ };
7
+ export declare const useThreadList: () => void;
8
+ export declare const ThreadList: ({ virtuosoProps }: ThreadListProps) => React.JSX.Element;
9
+ export {};
@@ -0,0 +1,41 @@
1
+ import React, { useEffect } from 'react';
2
+ import { Virtuoso } from 'react-virtuoso';
3
+ import { ThreadListItem as DefaultThreadListItem } from './ThreadListItem';
4
+ import { ThreadListEmptyPlaceholder as DefaultThreadListEmptyPlaceholder } from './ThreadListEmptyPlaceholder';
5
+ import { ThreadListUnseenThreadsBanner as DefaultThreadListUnseenThreadsBanner } from './ThreadListUnseenThreadsBanner';
6
+ import { ThreadListLoadingIndicator as DefaultThreadListLoadingIndicator } from './ThreadListLoadingIndicator';
7
+ import { useChatContext, useComponentContext } from '../../../context';
8
+ import { useStateStore } from '../../../store';
9
+ const selector = (nextValue) => [nextValue.threads];
10
+ const computeItemKey = (_, item) => item.id;
11
+ export const useThreadList = () => {
12
+ const { client } = useChatContext();
13
+ useEffect(() => {
14
+ const handleVisibilityChange = () => {
15
+ if (document.visibilityState === 'visible') {
16
+ client.threads.activate();
17
+ }
18
+ if (document.visibilityState === 'hidden') {
19
+ client.threads.deactivate();
20
+ }
21
+ };
22
+ handleVisibilityChange();
23
+ document.addEventListener('visibilitychange', handleVisibilityChange);
24
+ return () => {
25
+ client.threads.deactivate();
26
+ document.removeEventListener('visibilitychange', handleVisibilityChange);
27
+ };
28
+ }, [client]);
29
+ };
30
+ export const ThreadList = ({ virtuosoProps }) => {
31
+ const { client } = useChatContext();
32
+ const { ThreadListItem = DefaultThreadListItem, ThreadListEmptyPlaceholder = DefaultThreadListEmptyPlaceholder, ThreadListLoadingIndicator = DefaultThreadListLoadingIndicator, ThreadListUnseenThreadsBanner = DefaultThreadListUnseenThreadsBanner, } = useComponentContext();
33
+ const [threads] = useStateStore(client.threads.state, selector);
34
+ useThreadList();
35
+ return (React.createElement("div", { className: 'str-chat__thread-list-container' },
36
+ React.createElement(ThreadListUnseenThreadsBanner, null),
37
+ React.createElement(Virtuoso, { atBottomStateChange: (atBottom) => atBottom && client.threads.loadNextPage(), className: 'str-chat__thread-list', components: {
38
+ EmptyPlaceholder: ThreadListEmptyPlaceholder,
39
+ Footer: ThreadListLoadingIndicator,
40
+ }, computeItemKey: computeItemKey, data: threads, itemContent: (_, thread) => React.createElement(ThreadListItem, { thread: thread }), ...virtuosoProps })));
41
+ };
@@ -0,0 +1,2 @@
1
+ import React from 'react';
2
+ export declare const ThreadListEmptyPlaceholder: () => React.JSX.Element;
@@ -0,0 +1,5 @@
1
+ import React from 'react';
2
+ import { Icon } from '../icons';
3
+ export const ThreadListEmptyPlaceholder = () => (React.createElement("div", { className: 'str-chat__thread-list-empty-placeholder' },
4
+ React.createElement(Icon.MessageBubble, null),
5
+ "No threads here yet..."));
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import type { Thread } from 'stream-chat';
3
+ import type { ThreadListItemUIProps } from './ThreadListItemUI';
4
+ export type ThreadListItemProps = {
5
+ thread: Thread;
6
+ threadListItemUIProps?: ThreadListItemUIProps;
7
+ };
8
+ export declare const useThreadListItemContext: () => Thread<import("stream-chat").DefaultGenerics> | undefined;
9
+ export declare const ThreadListItem: ({ thread, threadListItemUIProps }: ThreadListItemProps) => React.JSX.Element;