stream-chat-react 12.0.0-rc.8 → 12.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. package/dist/components/Avatar/Avatar.js +5 -1
  2. package/dist/components/Channel/Channel.d.ts +3 -4
  3. package/dist/components/Channel/Channel.js +95 -56
  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 +7 -7
  50. package/dist/components/MessageList/VirtualizedMessageList.d.ts +2 -1
  51. package/dist/components/MessageList/VirtualizedMessageList.js +44 -39
  52. package/dist/components/MessageList/VirtualizedMessageListComponents.d.ts +1 -1
  53. package/dist/components/MessageList/VirtualizedMessageListComponents.js +6 -6
  54. package/dist/components/MessageList/renderMessages.d.ts +2 -2
  55. package/dist/components/MessageList/renderMessages.js +4 -1
  56. package/dist/components/MessageList/utils.js +1 -1
  57. package/dist/components/Reactions/ReactionSelector.d.ts +6 -3
  58. package/dist/components/Reactions/ReactionSelector.js +34 -24
  59. package/dist/components/Reactions/ReactionSelectorWithButton.d.ts +13 -0
  60. package/dist/components/Reactions/ReactionSelectorWithButton.js +22 -0
  61. package/dist/components/Reactions/ReactionsList.d.ts +4 -4
  62. package/dist/components/Reactions/hooks/useProcessReactions.js +2 -1
  63. package/dist/components/Thread/Thread.js +38 -10
  64. package/dist/components/Threads/ThreadContext.d.ts +9 -0
  65. package/dist/components/Threads/ThreadContext.js +9 -0
  66. package/dist/components/Threads/ThreadList/ThreadList.d.ts +9 -0
  67. package/dist/components/Threads/ThreadList/ThreadList.js +41 -0
  68. package/dist/components/Threads/ThreadList/ThreadListEmptyPlaceholder.d.ts +2 -0
  69. package/dist/components/Threads/ThreadList/ThreadListEmptyPlaceholder.js +5 -0
  70. package/dist/components/Threads/ThreadList/ThreadListItem.d.ts +9 -0
  71. package/dist/components/Threads/ThreadList/ThreadListItem.js +52 -0
  72. package/dist/components/Threads/ThreadList/ThreadListItemUI.d.ts +15 -0
  73. package/dist/components/Threads/ThreadList/ThreadListItemUI.js +75 -0
  74. package/dist/components/Threads/ThreadList/ThreadListLoadingIndicator.d.ts +2 -0
  75. package/dist/components/Threads/ThreadList/ThreadListLoadingIndicator.js +14 -0
  76. package/dist/components/Threads/ThreadList/ThreadListUnseenThreadsBanner.d.ts +2 -0
  77. package/dist/components/Threads/ThreadList/ThreadListUnseenThreadsBanner.js +16 -0
  78. package/dist/components/Threads/ThreadList/index.d.ts +3 -0
  79. package/dist/components/Threads/ThreadList/index.js +3 -0
  80. package/dist/components/Threads/UnreadCountBadge.d.ts +6 -0
  81. package/dist/components/Threads/UnreadCountBadge.js +5 -0
  82. package/dist/components/Threads/hooks/useThreadManagerState.d.ts +2 -0
  83. package/dist/components/Threads/hooks/useThreadManagerState.js +6 -0
  84. package/dist/components/Threads/hooks/useThreadState.d.ts +5 -0
  85. package/dist/components/Threads/hooks/useThreadState.js +11 -0
  86. package/dist/components/Threads/icons.d.ts +8 -0
  87. package/dist/components/Threads/icons.js +13 -0
  88. package/dist/components/Threads/index.d.ts +2 -0
  89. package/dist/components/Threads/index.js +2 -0
  90. package/dist/components/index.d.ts +3 -0
  91. package/dist/components/index.js +3 -0
  92. package/dist/context/ComponentContext.d.ts +15 -40
  93. package/dist/context/ComponentContext.js +7 -9
  94. package/dist/context/DialogManagerContext.d.ts +10 -0
  95. package/dist/context/DialogManagerContext.js +14 -0
  96. package/dist/context/MessageContext.d.ts +3 -11
  97. package/dist/context/MessageContext.js +3 -2
  98. package/dist/context/TranslationContext.d.ts +1 -11
  99. package/dist/context/TranslationContext.js +1 -9
  100. package/dist/context/WithComponents.d.ts +5 -0
  101. package/dist/context/WithComponents.js +7 -0
  102. package/dist/context/index.d.ts +2 -0
  103. package/dist/context/index.js +2 -0
  104. package/dist/css/v2/index.css +2 -2
  105. package/dist/css/v2/index.layout.css +2 -2
  106. package/dist/i18n/Streami18n.d.ts +1 -3
  107. package/dist/i18n/Streami18n.js +1 -2
  108. package/dist/i18n/index.d.ts +2 -1
  109. package/dist/i18n/index.js +2 -0
  110. package/dist/i18n/types.d.ts +26 -0
  111. package/dist/i18n/types.js +1 -0
  112. package/dist/i18n/utils.d.ts +9 -20
  113. package/dist/i18n/utils.js +10 -1
  114. package/dist/index.browser.cjs +10827 -10601
  115. package/dist/index.browser.cjs.map +4 -4
  116. package/dist/index.d.ts +1 -0
  117. package/dist/index.js +1 -0
  118. package/dist/index.node.cjs +10720 -10510
  119. package/dist/index.node.cjs.map +4 -4
  120. package/dist/plugins/Emojis/index.browser.cjs +7 -169
  121. package/dist/plugins/Emojis/index.browser.cjs.map +4 -4
  122. package/dist/plugins/Emojis/index.node.cjs +7 -169
  123. package/dist/plugins/Emojis/index.node.cjs.map +4 -4
  124. package/dist/plugins/encoders/mp3.browser.cjs +2 -4
  125. package/dist/plugins/encoders/mp3.browser.cjs.map +1 -1
  126. package/dist/plugins/encoders/mp3.node.cjs +2 -4
  127. package/dist/plugins/encoders/mp3.node.cjs.map +1 -1
  128. package/dist/scss/v2/Avatar/Avatar-layout.scss +10 -2
  129. package/dist/scss/v2/Avatar/Avatar-theme.scss +5 -0
  130. package/dist/scss/v2/ChatView/ChatView-layout.scss +43 -0
  131. package/dist/scss/v2/ChatView/ChatView-theme.scss +32 -0
  132. package/dist/scss/v2/Dialog/Dialog-layout.scss +8 -0
  133. package/dist/scss/v2/LoadingIndicator/LoadingIndicator-layout.scss +16 -0
  134. package/dist/scss/v2/Message/Message-layout.scss +8 -0
  135. package/dist/scss/v2/MessageActionsBox/MessageActionsBox-theme.scss +8 -0
  136. package/dist/scss/v2/MessageList/MessageList-layout.scss +0 -6
  137. package/dist/scss/v2/MessageList/VirtualizedMessageList-layout.scss +0 -12
  138. package/dist/scss/v2/MessageReactions/MessageReactionsSelector-layout.scss +16 -0
  139. package/dist/scss/v2/MessageReactions/MessageReactionsSelector-theme.scss +6 -0
  140. package/dist/scss/v2/Thread/Thread-layout.scss +15 -1
  141. package/dist/scss/v2/ThreadList/ThreadList-layout.scss +152 -0
  142. package/dist/scss/v2/ThreadList/ThreadList-theme.scss +75 -0
  143. package/dist/scss/v2/UnreadCountBadge/UnreadCountBadge-layout.scss +49 -0
  144. package/dist/scss/v2/UnreadCountBadge/UnreadCountBadge-theme.scss +11 -0
  145. package/dist/scss/v2/_base.scss +31 -0
  146. package/dist/scss/v2/index.layout.scss +4 -0
  147. package/dist/scss/v2/index.scss +3 -0
  148. package/dist/store/hooks/index.d.ts +1 -0
  149. package/dist/store/hooks/index.js +1 -0
  150. package/dist/store/hooks/useStateStore.d.ts +3 -0
  151. package/dist/store/hooks/useStateStore.js +15 -0
  152. package/dist/store/index.d.ts +1 -0
  153. package/dist/store/index.js +1 -0
  154. package/package.json +7 -6
  155. package/dist/assets/Poweredby_100px-White_VertText.png +0 -0
  156. package/dist/assets/str-chat__reaction-list-sprite@1x.png +0 -0
  157. package/dist/assets/str-chat__reaction-list-sprite@2x.png +0 -0
  158. package/dist/assets/str-chat__reaction-list-sprite@3x.png +0 -0
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { TimestampFormatterOptions } from '../../i18n/utils';
2
+ import type { TimestampFormatterOptions } from '../../i18n/types';
3
3
  export interface TimestampProps extends TimestampFormatterOptions {
4
4
  customClass?: string;
5
5
  timestamp?: Date | string;
@@ -1,7 +1,7 @@
1
1
  import React, { useMemo } from 'react';
2
2
  import { useMessageContext } from '../../context/MessageContext';
3
- import { isDate, useTranslationContext } from '../../context/TranslationContext';
4
- import { getDateString } from '../../i18n/utils';
3
+ import { useTranslationContext } from '../../context/TranslationContext';
4
+ import { getDateString, isDate } from '../../i18n/utils';
5
5
  export function Timestamp(props) {
6
6
  const { calendar, calendarFormats, customClass, format, timestamp } = props;
7
7
  const { formatDate } = useMessageContext('MessageTimestamp');
@@ -1,11 +1,5 @@
1
- import React, { RefObject } from 'react';
1
+ import React from 'react';
2
2
  import { StreamMessage } from '../../../context/ChannelStateContext';
3
- import type { ReactEventHandler } from '../types';
4
3
  import type { DefaultStreamChatGenerics } from '../../../types/types';
5
4
  export declare const reactionHandlerWarning = "Reaction handler was called, but it is missing one of its required arguments.\nMake sure the ChannelAction and ChannelState contexts are properly set and the hook is initialized with a valid message.";
6
5
  export declare const useReactionHandler: <StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics>(message?: StreamMessage<StreamChatGenerics>) => (reactionType: string, event?: React.BaseSyntheticEvent) => Promise<void>;
7
- export declare const useReactionClick: <StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics>(message?: StreamMessage<StreamChatGenerics>, reactionSelectorRef?: RefObject<HTMLDivElement | null>, messageWrapperRef?: RefObject<HTMLDivElement | null>, closeReactionSelectorOnClick?: boolean) => {
8
- isReactionEnabled: boolean;
9
- onReactionListClick: ReactEventHandler;
10
- showDetailedReactions: boolean;
11
- };
@@ -1,11 +1,13 @@
1
- import { useCallback, useEffect, useRef, useState } from 'react';
1
+ import { useCallback } from 'react';
2
2
  import throttle from 'lodash.throttle';
3
3
  import { useChannelActionContext } from '../../../context/ChannelActionContext';
4
4
  import { useChannelStateContext } from '../../../context/ChannelStateContext';
5
5
  import { useChatContext } from '../../../context/ChatContext';
6
+ import { useThreadContext } from '../../Threads';
6
7
  export const reactionHandlerWarning = `Reaction handler was called, but it is missing one of its required arguments.
7
8
  Make sure the ChannelAction and ChannelState contexts are properly set and the hook is initialized with a valid message.`;
8
9
  export const useReactionHandler = (message) => {
10
+ const thread = useThreadContext();
9
11
  const { updateMessage } = useChannelActionContext('useReactionHandler');
10
12
  const { channel, channelCapabilities } = useChannelStateContext('useReactionHandler');
11
13
  const { client } = useChatContext('useReactionHandler');
@@ -64,14 +66,19 @@ export const useReactionHandler = (message) => {
64
66
  const tempMessage = createMessagePreview(add, newReaction, message);
65
67
  try {
66
68
  updateMessage(tempMessage);
69
+ // @ts-expect-error
70
+ thread?.upsertReplyLocally({ message: tempMessage });
67
71
  const messageResponse = add
68
72
  ? await channel.sendReaction(id, { type })
69
73
  : await channel.deleteReaction(id, type);
74
+ // seems useless as we're expecting WS event to come in and replace this anyway
70
75
  updateMessage(messageResponse.message);
71
76
  }
72
77
  catch (error) {
73
78
  // revert to the original message if the API call fails
74
79
  updateMessage(message);
80
+ // @ts-expect-error
81
+ thread?.upsertReplyLocally({ message });
75
82
  }
76
83
  }, 1000);
77
84
  return async (reactionType, event) => {
@@ -107,65 +114,3 @@ export const useReactionHandler = (message) => {
107
114
  }
108
115
  };
109
116
  };
110
- export const useReactionClick = (message, reactionSelectorRef, messageWrapperRef, closeReactionSelectorOnClick) => {
111
- const { channelCapabilities = {} } = useChannelStateContext('useReactionClick');
112
- const [showDetailedReactions, setShowDetailedReactions] = useState(false);
113
- const hasListener = useRef(false);
114
- const isReactionEnabled = channelCapabilities['send-reaction'];
115
- const messageDeleted = !!message?.deleted_at;
116
- const closeDetailedReactions = useCallback((event) => {
117
- if (event.target instanceof HTMLElement &&
118
- reactionSelectorRef?.current?.contains(event.target) &&
119
- !closeReactionSelectorOnClick) {
120
- return;
121
- }
122
- setShowDetailedReactions(false);
123
- },
124
- // eslint-disable-next-line react-hooks/exhaustive-deps
125
- [setShowDetailedReactions, reactionSelectorRef]);
126
- useEffect(() => {
127
- const messageWrapper = messageWrapperRef?.current;
128
- if (showDetailedReactions && !hasListener.current) {
129
- hasListener.current = true;
130
- document.addEventListener('click', closeDetailedReactions);
131
- if (messageWrapper) {
132
- messageWrapper.addEventListener('mouseleave', closeDetailedReactions);
133
- }
134
- }
135
- if (!showDetailedReactions && hasListener.current) {
136
- document.removeEventListener('click', closeDetailedReactions);
137
- if (messageWrapper) {
138
- messageWrapper.removeEventListener('mouseleave', closeDetailedReactions);
139
- }
140
- hasListener.current = false;
141
- }
142
- return () => {
143
- if (hasListener.current) {
144
- document.removeEventListener('click', closeDetailedReactions);
145
- if (messageWrapper) {
146
- messageWrapper.removeEventListener('mouseleave', closeDetailedReactions);
147
- }
148
- hasListener.current = false;
149
- }
150
- };
151
- }, [showDetailedReactions, closeDetailedReactions, messageWrapperRef]);
152
- useEffect(() => {
153
- const messageWrapper = messageWrapperRef?.current;
154
- if (messageDeleted && hasListener.current) {
155
- document.removeEventListener('click', closeDetailedReactions);
156
- if (messageWrapper) {
157
- messageWrapper.removeEventListener('mouseleave', closeDetailedReactions);
158
- }
159
- hasListener.current = false;
160
- }
161
- }, [messageDeleted, closeDetailedReactions, messageWrapperRef]);
162
- const onReactionListClick = (event) => {
163
- event?.stopPropagation?.();
164
- setShowDetailedReactions((prev) => !prev);
165
- };
166
- return {
167
- isReactionEnabled,
168
- onReactionListClick,
169
- showDetailedReactions,
170
- };
171
- };
@@ -2,7 +2,7 @@ import type { TFunction } from 'i18next';
2
2
  import type { MessageResponse, Mute, StreamChat, UserResponse } from 'stream-chat';
3
3
  import type { PinPermissions } from './hooks';
4
4
  import type { MessageProps } from './types';
5
- import type { MessageContextValue, StreamMessage } from '../../context';
5
+ import type { ComponentContextValue, CustomMessageActions, MessageContextValue, StreamMessage } from '../../context';
6
6
  import type { DefaultStreamChatGenerics } from '../../types/types';
7
7
  /**
8
8
  * Following function validates a function which returns notification message.
@@ -39,7 +39,16 @@ export type Capabilities = {
39
39
  };
40
40
  export declare const getMessageActions: (actions: MessageActionsArray | boolean, { canDelete, canEdit, canFlag, canMarkUnread, canMute, canPin, canQuote, canReact, canReply, }: Capabilities) => MessageActionsArray<string>;
41
41
  export declare const ACTIONS_NOT_WORKING_IN_THREAD: string[];
42
+ /**
43
+ * @deprecated use `shouldRenderMessageActions` instead
44
+ */
42
45
  export declare const showMessageActionsBox: (actions: MessageActionsArray<string>, inThread?: boolean | undefined) => boolean;
46
+ export declare const shouldRenderMessageActions: <SCG extends DefaultStreamChatGenerics = DefaultStreamChatGenerics>({ customMessageActions, CustomMessageActionsList, inThread, messageActions, }: {
47
+ messageActions: MessageActionsArray;
48
+ customMessageActions?: CustomMessageActions<SCG>;
49
+ CustomMessageActionsList?: ComponentContextValue<SCG>['CustomMessageActionsList'];
50
+ inThread?: boolean;
51
+ }) => boolean;
43
52
  export declare const areMessagePropsEqual: <StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics>(prevProps: MessageProps<StreamChatGenerics> & {
44
53
  mutes?: Mute<StreamChatGenerics>[];
45
54
  showDetailedReactions?: boolean;
@@ -140,22 +140,31 @@ export const getMessageActions = (actions, { canDelete, canEdit, canFlag, canMar
140
140
  };
141
141
  export const ACTIONS_NOT_WORKING_IN_THREAD = [
142
142
  MESSAGE_ACTIONS.pin,
143
- MESSAGE_ACTIONS.react,
144
143
  MESSAGE_ACTIONS.reply,
145
144
  MESSAGE_ACTIONS.markUnread,
146
145
  ];
147
- export const showMessageActionsBox = (actions, inThread) => {
148
- if (actions.length === 0) {
146
+ /**
147
+ * @deprecated use `shouldRenderMessageActions` instead
148
+ */
149
+ export const showMessageActionsBox = (actions, inThread) => shouldRenderMessageActions({ inThread, messageActions: actions });
150
+ export const shouldRenderMessageActions = ({ customMessageActions, CustomMessageActionsList, inThread, messageActions, }) => {
151
+ if (typeof CustomMessageActionsList !== 'undefined' ||
152
+ typeof customMessageActions !== 'undefined')
153
+ return true;
154
+ if (!messageActions.length)
149
155
  return false;
150
- }
151
156
  if (inThread &&
152
- actions.filter((action) => !ACTIONS_NOT_WORKING_IN_THREAD.includes(action)).length === 0) {
157
+ messageActions.filter((action) => !ACTIONS_NOT_WORKING_IN_THREAD.includes(action)).length === 0) {
153
158
  return false;
154
159
  }
155
- if (actions.length === 1 && (actions.includes('react') || actions.includes('reply'))) {
160
+ if (messageActions.length === 1 &&
161
+ (messageActions.includes(MESSAGE_ACTIONS.react) ||
162
+ messageActions.includes(MESSAGE_ACTIONS.reply))) {
156
163
  return false;
157
164
  }
158
- if (actions.length === 2 && actions.includes('react') && actions.includes('reply')) {
165
+ if (messageActions.length === 2 &&
166
+ messageActions.includes(MESSAGE_ACTIONS.react) &&
167
+ messageActions.includes(MESSAGE_ACTIONS.reply)) {
159
168
  return false;
160
169
  }
161
170
  return true;
@@ -185,6 +194,9 @@ export const areMessagePropsEqual = (prevProps, nextProps) => {
185
194
  if (nextProps.showDetailedReactions !== prevProps.showDetailedReactions) {
186
195
  return false;
187
196
  }
197
+ if (nextProps.closeReactionSelectorOnClick !== prevProps.closeReactionSelectorOnClick) {
198
+ return false;
199
+ }
188
200
  const messagesAreEqual = areMessagesEqual(prevMessage, nextMessage);
189
201
  if (!messagesAreEqual)
190
202
  return false;
@@ -6,13 +6,12 @@ export type MessageActionsProps<StreamChatGenerics extends DefaultStreamChatGene
6
6
  ActionsIcon?: React.ComponentType<IconProps>;
7
7
  customWrapperClass?: string;
8
8
  inline?: boolean;
9
- messageWrapperRef?: React.RefObject<HTMLDivElement>;
10
9
  mine?: () => boolean;
11
10
  };
12
11
  export declare const MessageActions: <StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics>(props: MessageActionsProps<StreamChatGenerics>) => React.JSX.Element | null;
13
12
  export type MessageActionsWrapperProps = {
14
- setActionsBoxOpen: React.Dispatch<React.SetStateAction<boolean>>;
15
13
  customWrapperClass?: string;
16
14
  inline?: boolean;
15
+ toggleOpen?: () => void;
17
16
  };
18
17
  export {};
@@ -1,15 +1,17 @@
1
- import React, { useCallback, useEffect, useRef, useState, } from 'react';
1
+ import clsx from 'clsx';
2
+ import React, { useCallback, useRef } from 'react';
2
3
  import { MessageActionsBox } from './MessageActionsBox';
4
+ import { DialogAnchor, useDialog, useDialogIsOpen } from '../Dialog';
3
5
  import { ActionsIcon as DefaultActionsIcon } from '../Message/icons';
4
- import { isUserMuted } from '../Message/utils';
6
+ import { isUserMuted, shouldRenderMessageActions } from '../Message/utils';
5
7
  import { useChatContext } from '../../context/ChatContext';
6
8
  import { useMessageContext } from '../../context/MessageContext';
7
- import { useMessageActionsBoxPopper } from './hooks';
8
- import { useTranslationContext } from '../../context';
9
+ import { useComponentContext, useTranslationContext } from '../../context';
9
10
  export const MessageActions = (props) => {
10
- const { ActionsIcon = DefaultActionsIcon, customWrapperClass = '', getMessageActions: propGetMessageActions, handleDelete: propHandleDelete, handleFlag: propHandleFlag, handleMarkUnread: propHandleMarkUnread, handleMute: propHandleMute, handlePin: propHandlePin, inline, message: propMessage, messageWrapperRef, mine, } = props;
11
+ const { ActionsIcon = DefaultActionsIcon, customWrapperClass = '', getMessageActions: propGetMessageActions, handleDelete: propHandleDelete, handleFlag: propHandleFlag, handleMarkUnread: propHandleMarkUnread, handleMute: propHandleMute, handlePin: propHandlePin, inline, message: propMessage, mine, } = props;
11
12
  const { mutes } = useChatContext('MessageActions');
12
- const { customMessageActions, getMessageActions: contextGetMessageActions, handleDelete: contextHandleDelete, handleFlag: contextHandleFlag, handleMarkUnread: contextHandleMarkUnread, handleMute: contextHandleMute, handlePin: contextHandlePin, isMyMessage, message: contextMessage, setEditingState, } = useMessageContext('MessageActions');
13
+ const { customMessageActions, getMessageActions: contextGetMessageActions, handleDelete: contextHandleDelete, handleFlag: contextHandleFlag, handleMarkUnread: contextHandleMarkUnread, handleMute: contextHandleMute, handlePin: contextHandlePin, isMyMessage, message: contextMessage, setEditingState, threadList, } = useMessageContext('MessageActions');
14
+ const { CustomMessageActionsList } = useComponentContext('MessageActions');
13
15
  const { t } = useTranslationContext('MessageActions');
14
16
  const getMessageActions = propGetMessageActions || contextGetMessageActions;
15
17
  const handleDelete = propHandleDelete || contextHandleDelete;
@@ -19,64 +21,33 @@ export const MessageActions = (props) => {
19
21
  const handlePin = propHandlePin || contextHandlePin;
20
22
  const message = propMessage || contextMessage;
21
23
  const isMine = mine ? mine() : isMyMessage();
22
- const [actionsBoxOpen, setActionsBoxOpen] = useState(false);
23
24
  const isMuted = useCallback(() => isUserMuted(message, mutes), [message, mutes]);
24
- const hideOptions = useCallback((event) => {
25
- if (event instanceof KeyboardEvent && event.key !== 'Escape') {
26
- return;
27
- }
28
- setActionsBoxOpen(false);
29
- }, []);
25
+ const dialogId = `message-actions--${message.id}`;
26
+ const dialog = useDialog({ id: dialogId });
27
+ const dialogIsOpen = useDialogIsOpen(dialogId);
30
28
  const messageActions = getMessageActions();
31
- const messageDeletedAt = !!message?.deleted_at;
32
- useEffect(() => {
33
- if (messageWrapperRef?.current) {
34
- messageWrapperRef.current.addEventListener('mouseleave', hideOptions);
35
- }
36
- }, [hideOptions, messageWrapperRef]);
37
- useEffect(() => {
38
- if (messageDeletedAt) {
39
- document.removeEventListener('click', hideOptions);
40
- }
41
- }, [hideOptions, messageDeletedAt]);
42
- useEffect(() => {
43
- if (!actionsBoxOpen)
44
- return;
45
- document.addEventListener('click', hideOptions);
46
- document.addEventListener('keyup', hideOptions);
47
- return () => {
48
- document.removeEventListener('click', hideOptions);
49
- document.removeEventListener('keyup', hideOptions);
50
- };
51
- }, [actionsBoxOpen, hideOptions]);
52
- const actionsBoxButtonRef = useRef(null);
53
- const { attributes, popperElementRef, styles } = useMessageActionsBoxPopper({
54
- open: actionsBoxOpen,
55
- placement: isMine ? 'top-end' : 'top-start',
56
- referenceElement: actionsBoxButtonRef.current,
29
+ const renderMessageActions = shouldRenderMessageActions({
30
+ customMessageActions,
31
+ CustomMessageActionsList,
32
+ inThread: threadList,
33
+ messageActions,
57
34
  });
58
- if (!messageActions.length && !customMessageActions)
35
+ const actionsBoxButtonRef = useRef(null);
36
+ if (!renderMessageActions)
59
37
  return null;
60
- return (React.createElement(MessageActionsWrapper, { customWrapperClass: customWrapperClass, inline: inline, setActionsBoxOpen: setActionsBoxOpen },
61
- React.createElement(MessageActionsBox, { ...attributes.popper, getMessageActions: getMessageActions, handleDelete: handleDelete, handleEdit: setEditingState, handleFlag: handleFlag, handleMarkUnread: handleMarkUnread, handleMute: handleMute, handlePin: handlePin, isUserMuted: isMuted, mine: isMine, open: actionsBoxOpen, ref: popperElementRef, style: styles.popper }),
62
- React.createElement("button", { "aria-expanded": actionsBoxOpen, "aria-haspopup": 'true', "aria-label": t('aria/Open Message Actions Menu'), className: 'str-chat__message-actions-box-button', ref: actionsBoxButtonRef },
38
+ return (React.createElement(MessageActionsWrapper, { customWrapperClass: customWrapperClass, inline: inline, toggleOpen: dialog?.toggle },
39
+ React.createElement(DialogAnchor, { id: dialogId, placement: isMine ? 'top-end' : 'top-start', referenceElement: actionsBoxButtonRef.current, trapFocus: true },
40
+ React.createElement(MessageActionsBox, { getMessageActions: getMessageActions, handleDelete: handleDelete, handleEdit: setEditingState, handleFlag: handleFlag, handleMarkUnread: handleMarkUnread, handleMute: handleMute, handlePin: handlePin, isUserMuted: isMuted, mine: isMine, open: dialogIsOpen })),
41
+ React.createElement("button", { "aria-expanded": dialogIsOpen, "aria-haspopup": 'true', "aria-label": t('aria/Open Message Actions Menu'), className: 'str-chat__message-actions-box-button', "data-testid": 'message-actions-toggle-button', ref: actionsBoxButtonRef },
63
42
  React.createElement(ActionsIcon, { className: 'str-chat__message-action-icon' }))));
64
43
  };
65
44
  const MessageActionsWrapper = (props) => {
66
- const { children, customWrapperClass, inline, setActionsBoxOpen } = props;
67
- const defaultWrapperClass = `
68
- str-chat__message-simple__actions__action
69
- str-chat__message-simple__actions__action--options
70
- str-chat__message-actions-container`;
71
- const wrapperClass = customWrapperClass || defaultWrapperClass;
72
- const onClickOptionsAction = (event) => {
73
- event.stopPropagation();
74
- setActionsBoxOpen((prev) => !prev);
75
- };
45
+ const { children, customWrapperClass, inline, toggleOpen } = props;
46
+ const defaultWrapperClass = clsx('str-chat__message-simple__actions__action', 'str-chat__message-simple__actions__action--options', 'str-chat__message-actions-container');
76
47
  const wrapperProps = {
77
- className: wrapperClass,
48
+ className: customWrapperClass || defaultWrapperClass,
78
49
  'data-testid': 'message-actions',
79
- onClick: onClickOptionsAction,
50
+ onClick: toggleOpen,
80
51
  };
81
52
  if (inline)
82
53
  return React.createElement("span", { ...wrapperProps }, children);
@@ -10,5 +10,5 @@ export type MessageActionsBoxProps<StreamChatGenerics extends DefaultStreamChatG
10
10
  /**
11
11
  * A popup box that displays the available actions on a message, such as edit, delete, pin, etc.
12
12
  */
13
- export declare const MessageActionsBox: React.ForwardRefExoticComponent<Omit<MessageActionsBoxProps<DefaultStreamChatGenerics>, "ref"> & React.RefAttributes<HTMLDivElement | null>>;
13
+ export declare const MessageActionsBox: <StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics>(props: MessageActionsBoxProps<StreamChatGenerics>) => React.JSX.Element;
14
14
  export {};
@@ -1,10 +1,10 @@
1
- import React from 'react';
2
1
  import clsx from 'clsx';
2
+ import React from 'react';
3
3
  import { MESSAGE_ACTIONS } from '../Message/utils';
4
4
  import { useChannelActionContext, useComponentContext, useMessageContext, useTranslationContext, } from '../../context';
5
5
  import { CustomMessageActionsList as DefaultCustomMessageActionsList } from './CustomMessageActionsList';
6
- const UnMemoizedMessageActionsBox = React.forwardRef((props, ref) => {
7
- const { getMessageActions, handleDelete, handleEdit, handleFlag, handleMarkUnread, handleMute, handlePin, isUserMuted, mine, open = false, ...restDivProps } = props;
6
+ const UnMemoizedMessageActionsBox = (props) => {
7
+ const { className, getMessageActions, handleDelete, handleEdit, handleFlag, handleMarkUnread, handleMute, handlePin, isUserMuted, mine, open, ...restDivProps } = props;
8
8
  const { CustomMessageActionsList = DefaultCustomMessageActionsList, } = useComponentContext('MessageActionsBox');
9
9
  const { setQuotedMessage } = useChannelActionContext('MessageActionsBox');
10
10
  const { customMessageActions, message, threadList } = useMessageContext('MessageActionsBox');
@@ -20,11 +20,11 @@ const UnMemoizedMessageActionsBox = React.forwardRef((props, ref) => {
20
20
  textarea.focus();
21
21
  }
22
22
  };
23
- const rootClassName = clsx('str-chat__message-actions-box', {
23
+ const rootClassName = clsx('str-chat__message-actions-box', className, {
24
24
  'str-chat__message-actions-box--open': open,
25
25
  });
26
26
  const buttonClassName = 'str-chat__message-actions-list-item str-chat__message-actions-list-item-button';
27
- return (React.createElement("div", { ...restDivProps, className: rootClassName, "data-testid": 'message-actions-box', ref: ref },
27
+ return (React.createElement("div", { ...restDivProps, className: rootClassName, "data-testid": 'message-actions-box' },
28
28
  React.createElement("div", { "aria-label": t('aria/Message Options'), className: 'str-chat__message-actions-list', role: 'listbox' },
29
29
  React.createElement(CustomMessageActionsList, { customMessageActions: customMessageActions, message: message }),
30
30
  messageActions.indexOf(MESSAGE_ACTIONS.quote) > -1 && (React.createElement("button", { "aria-selected": 'false', className: buttonClassName, onClick: handleQuote, role: 'option' }, t('Reply'))),
@@ -34,7 +34,7 @@ const UnMemoizedMessageActionsBox = React.forwardRef((props, ref) => {
34
34
  messageActions.indexOf(MESSAGE_ACTIONS.mute) > -1 && (React.createElement("button", { "aria-selected": 'false', className: buttonClassName, onClick: handleMute, role: 'option' }, isUserMuted() ? t('Unmute') : t('Mute'))),
35
35
  messageActions.indexOf(MESSAGE_ACTIONS.edit) > -1 && (React.createElement("button", { "aria-selected": 'false', className: buttonClassName, onClick: handleEdit, role: 'option' }, t('Edit Message'))),
36
36
  messageActions.indexOf(MESSAGE_ACTIONS.delete) > -1 && (React.createElement("button", { "aria-selected": 'false', className: buttonClassName, onClick: handleDelete, role: 'option' }, t('Delete'))))));
37
- });
37
+ };
38
38
  /**
39
39
  * A popup box that displays the available actions on a message, such as edit, delete, pin, etc.
40
40
  */
@@ -20,7 +20,7 @@ import { useMessageInputContext } from '../../context/MessageInputContext';
20
20
  import { useComponentContext } from '../../context/ComponentContext';
21
21
  export const MessageInputFlat = () => {
22
22
  const { t } = useTranslationContext('MessageInputFlat');
23
- const { asyncMessagesMultiSendEnabled, attachments, cooldownRemaining, findAndEnqueueURLsToEnrich, handleSubmit, hideSendButton, isUploadEnabled, linkPreviews, maxFilesLeft, message, numberOfUploads, recordingController, setCooldownRemaining, text, uploadNewFiles, } = useMessageInputContext('MessageInputFlat');
23
+ const { asyncMessagesMultiSendEnabled, attachments, cooldownRemaining, findAndEnqueueURLsToEnrich, handleSubmit, hideSendButton, isUploadEnabled, linkPreviews, maxFilesLeft, message, numberOfUploads, parent, recordingController, setCooldownRemaining, text, uploadNewFiles, } = useMessageInputContext('MessageInputFlat');
24
24
  const { AudioRecorder = DefaultAudioRecorder, AttachmentPreviewList = DefaultAttachmentPreviewList, CooldownTimer = DefaultCooldownTimer, FileUploadIcon = DefaultUploadIcon, LinkPreviewList = DefaultLinkPreviewList, QuotedMessagePreview = DefaultQuotedMessagePreview, RecordingPermissionDeniedNotification = DefaultRecordingPermissionDeniedNotification, SendButton = DefaultSendButton, StartRecordingAudioButton = DefaultStartRecordingAudioButton, EmojiPicker, } = useComponentContext('MessageInputFlat');
25
25
  const { acceptedFiles = [], multipleUploads, quotedMessage, } = useChannelStateContext('MessageInputFlat');
26
26
  const { setQuotedMessage } = useChannelActionContext('MessageInputFlat');
@@ -64,7 +64,7 @@ export const MessageInputFlat = () => {
64
64
  return React.createElement(AudioRecorder, null);
65
65
  // TODO: "!message" condition is a temporary fix for shared
66
66
  // state when editing a message (fix shared state issue)
67
- const displayQuotedMessage = !message && quotedMessage && !quotedMessage.parent_id;
67
+ const displayQuotedMessage = !message && quotedMessage && quotedMessage.parent_id === parent?.id;
68
68
  const recordingEnabled = !!(recordingController.recorder && navigator.mediaDevices); // account for requirement on iOS as per this bug report: https://bugs.webkit.org/show_bug.cgi?id=252303
69
69
  const isRecording = !!recordingController.recordingState;
70
70
  return (React.createElement(React.Fragment, null,
@@ -1,4 +1,5 @@
1
1
  import React, { useMemo } from 'react';
2
+ import { Attachment as DefaultAttachment } from '../Attachment';
2
3
  import { Avatar as DefaultAvatar } from '../Avatar';
3
4
  import { CloseIcon } from './icons';
4
5
  import { useChannelActionContext } from '../../context/ChannelActionContext';
@@ -13,7 +14,7 @@ export const QuotedMessagePreviewHeader = () => {
13
14
  React.createElement(CloseIcon, null))));
14
15
  };
15
16
  export const QuotedMessagePreview = ({ quotedMessage, }) => {
16
- const { Attachment, Avatar = DefaultAvatar } = useComponentContext('QuotedMessagePreview');
17
+ const { Attachment = DefaultAttachment, Avatar = DefaultAvatar, } = useComponentContext('QuotedMessagePreview');
17
18
  const { userLanguage } = useTranslationContext('QuotedMessagePreview');
18
19
  const quotedMessageText = quotedMessage.i18n?.[`${userLanguage}_text`] ||
19
20
  quotedMessage.text;
@@ -52,7 +52,6 @@ export const useUserTrigger = (params) => {
52
52
  // @ts-expect-error
53
53
  {
54
54
  $or: [{ id: { $autocomplete: query } }, { name: { $autocomplete: query } }],
55
- id: { $ne: client.userID },
56
55
  ...(typeof mentionQueryParams.filters === 'function'
57
56
  ? mentionQueryParams.filters(query)
58
57
  : mentionQueryParams.filters),
@@ -7,6 +7,7 @@ import { MessageListNotifications as DefaultMessageListNotifications } from './M
7
7
  import { UnreadMessagesNotification as DefaultUnreadMessagesNotification } from './UnreadMessagesNotification';
8
8
  import { useChannelActionContext, } from '../../context/ChannelActionContext';
9
9
  import { useChannelStateContext, } from '../../context/ChannelStateContext';
10
+ import { DialogManagerProvider } from '../../context';
10
11
  import { useChatContext } from '../../context/ChatContext';
11
12
  import { useComponentContext } from '../../context/ComponentContext';
12
13
  import { MessageListContextProvider } from '../../context/MessageListContext';
@@ -126,13 +127,12 @@ const MessageListWithContext = (props) => {
126
127
  const showEmptyStateIndicator = elements.length === 0 && !threadList;
127
128
  return (React.createElement(MessageListContextProvider, { value: { listElement, scrollToBottom } },
128
129
  React.createElement(MessageListMainPanel, null,
129
- !threadList && showUnreadMessagesNotification && (React.createElement(UnreadMessagesNotification, { unreadCount: channelUnreadUiState?.unread_messages })),
130
- React.createElement("div", { className: clsx(messageListClass, {
131
- [customClasses?.threadList || 'str-chat__thread-list']: threadList,
132
- }), onScroll: onScroll, ref: setListElement, tabIndex: 0 }, showEmptyStateIndicator ? (React.createElement(EmptyStateIndicator, { key: 'empty-state-indicator', listType: threadList ? 'thread' : 'message' })) : (React.createElement(InfiniteScroll, { className: 'str-chat__message-list-scroll', "data-testid": 'reverse-infinite-scroll', hasNextPage: props.hasMoreNewer, hasPreviousPage: props.hasMore, head: props.head, isLoading: props.loadingMore, loader: React.createElement("div", { className: 'str-chat__list__loading', key: 'loading-indicator' }, props.loadingMore && React.createElement(LoadingIndicator, { size: 20 })), loadNextPage: loadMoreNewer, loadPreviousPage: loadMore, threshold: loadMoreScrollThreshold, ...restInternalInfiniteScrollProps },
133
- React.createElement("ul", { className: 'str-chat__ul', ref: setUlElement }, elements),
134
- React.createElement(TypingIndicator, { threadList: threadList }),
135
- React.createElement("div", { key: 'bottom' }))))),
130
+ React.createElement(DialogManagerProvider, { id: 'message-list-dialog-manager' },
131
+ !threadList && showUnreadMessagesNotification && (React.createElement(UnreadMessagesNotification, { unreadCount: channelUnreadUiState?.unread_messages })),
132
+ React.createElement("div", { className: clsx(messageListClass, customClasses?.threadList), onScroll: onScroll, ref: setListElement, tabIndex: 0 }, showEmptyStateIndicator ? (React.createElement(EmptyStateIndicator, { listType: threadList ? 'thread' : 'message' })) : (React.createElement(InfiniteScroll, { className: 'str-chat__message-list-scroll', "data-testid": 'reverse-infinite-scroll', hasNextPage: props.hasMoreNewer, hasPreviousPage: props.hasMore, head: props.head, isLoading: props.loadingMore, loader: React.createElement("div", { className: 'str-chat__list__loading', key: 'loading-indicator' }, props.loadingMore && React.createElement(LoadingIndicator, { size: 20 })), loadNextPage: loadMoreNewer, loadPreviousPage: loadMore, threshold: loadMoreScrollThreshold, ...restInternalInfiniteScrollProps },
133
+ React.createElement("ul", { className: 'str-chat__ul', ref: setUlElement }, elements),
134
+ React.createElement(TypingIndicator, { threadList: threadList }),
135
+ React.createElement("div", { key: 'bottom' })))))),
136
136
  React.createElement(MessageListNotifications, { hasNewMessages: hasNewMessages, isMessageListScrolledToBottom: isMessageListScrolledToBottom, isNotAtLatestMessageSet: hasMoreNewer, MessageNotification: MessageNotification, notifications: notifications, scrollToBottom: scrollToBottomFromNotification, threadList: threadList, unreadCount: threadList ? undefined : channelUnreadUiState?.unread_messages })));
137
137
  };
138
138
  /**
@@ -3,7 +3,7 @@ import { ScrollSeekConfiguration, ScrollSeekPlaceholderProps, VirtuosoHandle, Vi
3
3
  import { GroupStyle, ProcessMessagesParams } from './utils';
4
4
  import { MessageProps, MessageUIComponentProps } from '../Message';
5
5
  import { ChannelActionContextValue } from '../../context/ChannelActionContext';
6
- import { StreamMessage } from '../../context/ChannelStateContext';
6
+ import { ChannelStateContextValue, StreamMessage } from '../../context/ChannelStateContext';
7
7
  import { ChatContextValue } from '../../context/ChatContext';
8
8
  import { ComponentContextValue } from '../../context/ComponentContext';
9
9
  import type { UserResponse } from 'stream-chat';
@@ -40,6 +40,7 @@ type PropsDrilledToMessage = 'additionalMessageInputProps' | 'customMessageActio
40
40
  export type VirtualizedMessageListProps<StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics> = Partial<Pick<MessageProps<StreamChatGenerics>, PropsDrilledToMessage>> & {
41
41
  /** Additional props to be passed the underlying [`react-virtuoso` virtualized list dependency](https://virtuoso.dev/virtuoso-api-reference/) */
42
42
  additionalVirtuosoProps?: VirtuosoProps<UnknownType, VirtuosoContext<StreamChatGenerics>>;
43
+ channelUnreadUiState?: ChannelStateContextValue['channelUnreadUiState'];
43
44
  /** If true, picking a reaction from the `ReactionSelector` component will close the selector */
44
45
  closeReactionSelectorOnClick?: boolean;
45
46
  /** Custom render function, if passed, certain UI props are ignored */
@@ -11,6 +11,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, 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 {};