stream-chat-react 12.8.2 → 12.10.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.
- package/dist/components/Attachment/components/WaveProgressBar.js +1 -1
- package/dist/components/Attachment/hooks/useAudioController.d.ts +1 -1
- package/dist/components/Attachment/hooks/useAudioController.js +1 -1
- package/dist/components/AutoCompleteTextarea/Textarea.js +0 -4
- package/dist/components/AutoCompleteTextarea/utils.js +1 -5
- package/dist/components/Channel/Channel.js +3 -2
- package/dist/components/Channel/channelState.d.ts +1 -3
- package/dist/components/Channel/channelState.js +1 -1
- package/dist/components/Channel/hooks/useIsMounted.d.ts +1 -1
- package/dist/components/ChannelList/hooks/useChannelListShape.d.ts +3 -3
- package/dist/components/ChannelList/hooks/useChannelListShape.js +54 -47
- package/dist/components/ChannelList/hooks/useChannelMembershipState.d.ts +3 -2
- package/dist/components/ChannelList/hooks/useChannelMembershipState.js +6 -15
- package/dist/components/ChannelList/hooks/useMobileNavigation.d.ts +1 -1
- package/dist/components/ChannelList/hooks/usePaginatedChannels.js +1 -1
- package/dist/components/ChannelList/hooks/useSelectedChannelState.d.ts +11 -0
- package/dist/components/ChannelList/hooks/useSelectedChannelState.js +20 -0
- package/dist/components/ChannelList/utils.d.ts +16 -6
- package/dist/components/ChannelList/utils.js +44 -18
- package/dist/components/ChannelSearch/SearchBar.d.ts +1 -1
- package/dist/components/ChannelSearch/SearchInput.d.ts +1 -1
- package/dist/components/ChannelSearch/hooks/useChannelSearch.js +1 -1
- package/dist/components/Chat/hooks/useChat.js +1 -1
- package/dist/components/ChatAutoComplete/ChatAutoComplete.d.ts +2 -0
- package/dist/components/ChatAutoComplete/ChatAutoComplete.js +1 -1
- package/dist/components/Gallery/BaseImage.d.ts +1 -3
- package/dist/components/Gallery/Gallery.js +10 -2
- package/dist/components/Gallery/ModalGallery.js +5 -4
- package/dist/components/InfiniteScrollPaginator/InfiniteScroll.js +4 -4
- package/dist/components/MessageActions/hooks/useMessageActionsBoxPopper.d.ts +1 -1
- package/dist/components/MessageInput/hooks/useMessageInputText.d.ts +1 -1
- package/dist/components/MessageInput/hooks/useMessageInputText.js +2 -2
- package/dist/components/MessageInput/hooks/useTimeElapsed.js +1 -1
- package/dist/components/MessageList/MessageList.js +0 -1
- package/dist/components/MessageList/VirtualizedMessageList.d.ts +1 -1
- package/dist/components/MessageList/VirtualizedMessageList.js +2 -2
- package/dist/components/MessageList/hooks/MessageList/useMessageListScrollManager.js +1 -1
- package/dist/components/MessageList/hooks/VirtualizedMessageList/useMessageSetKey.js +1 -1
- package/dist/components/MessageList/hooks/VirtualizedMessageList/useNewMessageNotification.d.ts +1 -1
- package/dist/components/MessageList/hooks/VirtualizedMessageList/usePrependMessagesCount.js +2 -2
- package/dist/components/MessageList/hooks/VirtualizedMessageList/useScrollToBottomOnNewMessage.js +1 -1
- package/dist/components/MessageList/hooks/useMarkRead.d.ts +2 -4
- package/dist/components/MessageList/hooks/useMarkRead.js +14 -16
- package/dist/context/VirtualizedMessageListContext.d.ts +13 -0
- package/dist/context/VirtualizedMessageListContext.js +7 -0
- package/dist/experimental/index.browser.cjs.map +2 -2
- package/dist/experimental/index.node.cjs.map +2 -2
- package/dist/index.browser.cjs +721 -267
- package/dist/index.browser.cjs.map +4 -4
- package/dist/index.node.cjs +986 -286
- package/dist/index.node.cjs.map +4 -4
- package/package.json +17 -18
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/experimental/index.ts", "../../src/experimental/MessageActions/MessageActions.tsx", "../../src/context/ChannelActionContext.tsx", "../../src/context/ChannelStateContext.tsx", "../../src/context/ChatContext.tsx", "../../src/context/ComponentContext.tsx", "../../src/context/DialogManagerContext.tsx", "../../src/components/Dialog/DialogPortal.tsx", "../../src/components/Dialog/hooks/useDialog.ts", "../../src/store/hooks/useStateStore.ts", "../../src/components/Portal/Portal.ts", "../../src/context/MessageContext.tsx", "../../src/context/TranslationContext.tsx", "../../src/i18n/utils.ts", "../../src/components/Avatar/Avatar.tsx", "../../src/components/Threads/icons.tsx", "../../src/utils/getWholeChar.ts", "../../src/components/Message/utils.tsx", "../../src/components/Message/hooks/useUserRole.ts", "../../src/components/Message/icons.tsx", "../../src/components/MessageActions/MessageActions.tsx", "../../src/components/Dialog/DialogAnchor.tsx", "../../src/components/Reactions/ReactionSelectorWithButton.tsx", "../../src/components/Reactions/ReactionSelector.tsx", "../../src/components/Reactions/reactionOptions.tsx", "../../src/components/Reactions/StreamEmoji.tsx", "../../src/components/Reactions/SpriteImage.tsx", "../../src/components/Reactions/utils/utils.ts", "../../src/experimental/MessageActions/hooks/useBaseMessageActionSetFilter.ts", "../../src/experimental/MessageActions/hooks/useSplitMessageActionSet.ts", "../../src/experimental/MessageActions/defaults.tsx"],
|
|
4
|
-
"sourcesContent": ["export * from './MessageActions';\n", "/* eslint-disable sort-keys */\nimport clsx from 'clsx';\nimport React, { PropsWithChildren, useState } from 'react';\n\nimport { useChatContext, useMessageContext, useTranslationContext } from '../../context';\nimport { ActionsIcon } from '../../components/Message/icons';\nimport { DialogAnchor, useDialog, useDialogIsOpen } from '../../components/Dialog';\nimport { MessageActionsWrapper } from '../../components/MessageActions/MessageActions';\nimport { MESSAGE_ACTIONS } from '../../components';\n\nimport { useBaseMessageActionSetFilter, useSplitMessageActionSet } from './hooks';\nimport { defaultMessageActionSet } from './defaults';\n\nexport type MessageActionSetItem = {\n Component: React.ComponentType;\n placement: 'quick' | 'dropdown';\n type:\n | keyof typeof MESSAGE_ACTIONS\n // eslint-disable-next-line @typescript-eslint/ban-types\n | (string & {});\n};\n\nexport type MessageActionsProps = {\n disableBaseMessageActionSetFilter?: boolean;\n messageActionSet?: MessageActionSetItem[];\n};\n\n// TODO: allow passing down customWrapperClass\n/**\n * A new actions component to replace current `MessageOptions` component.\n * Exports from `stream-chat-react/experimental` __MIGHT__ change - use with caution\n * and follow release notes in case you notice unexpected behavior.\n */\nexport const MessageActions = ({\n disableBaseMessageActionSetFilter = false,\n messageActionSet = defaultMessageActionSet,\n}: MessageActionsProps) => {\n const { theme } = useChatContext();\n const { isMyMessage, message } = useMessageContext();\n const { t } = useTranslationContext();\n const [actionsBoxButtonElement, setActionsBoxButtonElement] = useState<HTMLButtonElement | null>(\n null,\n );\n\n const filteredMessageActionSet = useBaseMessageActionSetFilter(\n messageActionSet,\n disableBaseMessageActionSetFilter,\n );\n\n const { dropdownActionSet, quickActionSet } = useSplitMessageActionSet(filteredMessageActionSet);\n\n const dropdownDialogId = `message-actions--${message.id}`;\n const reactionSelectorDialogId = `reaction-selector--${message.id}`;\n const dialog = useDialog({ id: dropdownDialogId });\n const dropdownDialogIsOpen = useDialogIsOpen(dropdownDialogId);\n const reactionSelectorDialogIsOpen = useDialogIsOpen(reactionSelectorDialogId);\n\n // do not render anything if total action count is zero\n if (dropdownActionSet.length + quickActionSet.length === 0) {\n return null;\n }\n\n return (\n <div\n className={clsx(`str-chat__message-${theme}__actions str-chat__message-options`, {\n 'str-chat__message-options--active': dropdownDialogIsOpen || reactionSelectorDialogIsOpen,\n })}\n >\n {dropdownActionSet.length > 0 && (\n <MessageActionsWrapper inline={false} toggleOpen={dialog?.toggle}>\n <button\n aria-expanded={dropdownDialogIsOpen}\n aria-haspopup='true'\n aria-label={t('aria/Open Message Actions Menu')}\n className='str-chat__message-actions-box-button'\n data-testid='message-actions-toggle-button'\n ref={setActionsBoxButtonElement}\n >\n <ActionsIcon className='str-chat__message-action-icon' />\n </button>\n\n <DialogAnchor\n id={dropdownDialogId}\n placement={isMyMessage() ? 'top-end' : 'top-start'}\n referenceElement={actionsBoxButtonElement}\n trapFocus\n >\n <DropdownBox open={dropdownDialogIsOpen}>\n {dropdownActionSet.map(({ Component: DropdownActionComponent, type }) => (\n <DropdownActionComponent key={type} />\n ))}\n </DropdownBox>\n </DialogAnchor>\n </MessageActionsWrapper>\n )}\n {quickActionSet.map(({ Component: QuickActionComponent, type }) => (\n <QuickActionComponent key={type} />\n ))}\n </div>\n );\n};\n\nconst DropdownBox = ({ children, open }: PropsWithChildren<{ open: boolean }>) => {\n const { t } = useTranslationContext();\n return (\n <div\n className={clsx('str-chat__message-actions-box', {\n 'str-chat__message-actions-box--open': open,\n })}\n >\n <div\n aria-label={t('aria/Message Options')}\n className='str-chat__message-actions-list'\n role='listbox'\n >\n {children}\n </div>\n </div>\n );\n};\n", "import React, { PropsWithChildren, useContext } from 'react';\n\nimport type {\n APIErrorResponse,\n Attachment,\n ErrorFromResponse,\n Message,\n MessageResponse,\n UpdatedMessage,\n UpdateMessageAPIResponse,\n UserResponse,\n} from 'stream-chat';\n\nimport type { StreamMessage } from './ChannelStateContext';\n\nimport type { ChannelStateReducerAction } from '../components/Channel/channelState';\nimport type { CustomMentionHandler } from '../components/Message/hooks/useMentionsHandler';\n\nimport type {\n ChannelUnreadUiState,\n DefaultStreamChatGenerics,\n SendMessageOptions,\n UnknownType,\n UpdateMessageOptions,\n} from '../types/types';\n\nexport type MarkReadWrapperOptions = {\n /**\n * Signal, whether the `channelUnreadUiState` should be updated.\n * By default, the local state update is prevented when the Channel component is mounted.\n * This is in order to keep the UI indicating the original unread state, when the user opens a channel.\n */\n updateChannelUiUnreadState?: boolean;\n};\n\nexport type MessageAttachments<\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n> = Array<Attachment<StreamChatGenerics>>;\n\nexport type MessageToSend<\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n> = {\n attachments?: MessageAttachments<StreamChatGenerics>;\n error?: ErrorFromResponse<APIErrorResponse>;\n errorStatusCode?: number;\n id?: string;\n mentioned_users?: UserResponse<StreamChatGenerics>[];\n parent?: StreamMessage<StreamChatGenerics>;\n parent_id?: string;\n status?: string;\n text?: string;\n};\n\nexport type RetrySendMessage<\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n> = (message: StreamMessage<StreamChatGenerics>) => Promise<void>;\n\nexport type ChannelActionContextValue<\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n> = {\n addNotification: (text: string, type: 'success' | 'error') => void;\n closeThread: (event?: React.BaseSyntheticEvent) => void;\n deleteMessage: (\n message: StreamMessage<StreamChatGenerics>,\n ) => Promise<MessageResponse<StreamChatGenerics>>;\n dispatch: React.Dispatch<ChannelStateReducerAction<StreamChatGenerics>>;\n editMessage: (\n message: UpdatedMessage<StreamChatGenerics>,\n options?: UpdateMessageOptions,\n ) => Promise<UpdateMessageAPIResponse<StreamChatGenerics> | void>;\n jumpToFirstUnreadMessage: (\n queryMessageLimit?: number,\n highlightDuration?: number,\n ) => Promise<void>;\n jumpToLatestMessage: () => Promise<void>;\n jumpToMessage: (messageId: string, limit?: number, highlightDuration?: number) => Promise<void>;\n loadMore: (limit?: number) => Promise<number>;\n loadMoreNewer: (limit?: number) => Promise<number>;\n loadMoreThread: () => Promise<void>;\n markRead: (options?: MarkReadWrapperOptions) => void;\n onMentionsClick: CustomMentionHandler<StreamChatGenerics>;\n onMentionsHover: CustomMentionHandler<StreamChatGenerics>;\n openThread: (\n message: StreamMessage<StreamChatGenerics>,\n event?: React.BaseSyntheticEvent,\n ) => void;\n removeMessage: (message: StreamMessage<StreamChatGenerics>) => void;\n retrySendMessage: RetrySendMessage<StreamChatGenerics>;\n sendMessage: (\n message: MessageToSend<StreamChatGenerics>,\n customMessageData?: Partial<Message<StreamChatGenerics>>,\n options?: SendMessageOptions,\n ) => Promise<void>;\n setChannelUnreadUiState: React.Dispatch<React.SetStateAction<ChannelUnreadUiState | undefined>>;\n setQuotedMessage: React.Dispatch<\n React.SetStateAction<StreamMessage<StreamChatGenerics> | undefined>\n >;\n updateMessage: (message: StreamMessage<StreamChatGenerics>) => void;\n};\n\nexport const ChannelActionContext = React.createContext<ChannelActionContextValue | undefined>(\n undefined,\n);\n\nexport const ChannelActionProvider = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>({\n children,\n value,\n}: PropsWithChildren<{\n value: ChannelActionContextValue<StreamChatGenerics>;\n}>) => (\n <ChannelActionContext.Provider value={(value as unknown) as ChannelActionContextValue}>\n {children}\n </ChannelActionContext.Provider>\n);\n\nexport const useChannelActionContext = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>(\n componentName?: string,\n) => {\n const contextValue = useContext(ChannelActionContext);\n\n if (!contextValue) {\n console.warn(\n `The useChannelActionContext hook was called outside of the ChannelActionContext provider. Make sure this hook is called within a child of the Channel component. The errored call is located in the ${componentName} component.`,\n );\n\n return {} as ChannelActionContextValue<StreamChatGenerics>;\n }\n\n return (contextValue as unknown) as ChannelActionContextValue<StreamChatGenerics>;\n};\n\n/**\n * Typescript currently does not support partial inference, so if ChannelActionContext\n * typing is desired while using the HOC withChannelActionContext, the Props for the\n * wrapped component must be provided as the first generic.\n */\nexport const withChannelActionContext = <\n P extends UnknownType,\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>(\n Component: React.ComponentType<P>,\n) => {\n const WithChannelActionContextComponent = (\n props: Omit<P, keyof ChannelActionContextValue<StreamChatGenerics>>,\n ) => {\n const channelActionContext = useChannelActionContext<StreamChatGenerics>();\n\n return <Component {...(props as P)} {...channelActionContext} />;\n };\n\n WithChannelActionContextComponent.displayName = (\n Component.displayName ||\n Component.name ||\n 'Component'\n ).replace('Base', '');\n\n return WithChannelActionContextComponent;\n};\n", "import React, { PropsWithChildren, useContext } from 'react';\n\nimport type {\n Channel,\n ChannelConfigWithInfo,\n MessageResponse,\n Mute,\n ChannelState as StreamChannelState,\n} from 'stream-chat';\n\nimport type {\n ChannelUnreadUiState,\n DefaultStreamChatGenerics,\n GiphyVersions,\n ImageAttachmentSizeHandler,\n UnknownType,\n VideoAttachmentSizeHandler,\n} from '../types/types';\nimport type { URLEnrichmentConfig } from '../components/MessageInput/hooks/useLinkPreviews';\n\nexport type ChannelNotifications = Array<{\n id: string;\n text: string;\n type: 'success' | 'error';\n}>;\n\nexport type StreamMessage<\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n> =\n | ReturnType<StreamChannelState<StreamChatGenerics>['formatMessage']>\n | MessageResponse<StreamChatGenerics>;\n\nexport type ChannelState<\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n> = {\n suppressAutoscroll: boolean;\n error?: Error | null;\n hasMore?: boolean;\n hasMoreNewer?: boolean;\n highlightedMessageId?: string;\n loading?: boolean;\n loadingMore?: boolean;\n loadingMoreNewer?: boolean;\n members?: StreamChannelState<StreamChatGenerics>['members'];\n messages?: StreamMessage<StreamChatGenerics>[];\n pinnedMessages?: StreamMessage<StreamChatGenerics>[];\n quotedMessage?: StreamMessage<StreamChatGenerics>;\n read?: StreamChannelState<StreamChatGenerics>['read'];\n thread?: StreamMessage<StreamChatGenerics> | null;\n threadHasMore?: boolean;\n threadLoadingMore?: boolean;\n threadMessages?: StreamMessage<StreamChatGenerics>[];\n threadSuppressAutoscroll?: boolean;\n typing?: StreamChannelState<StreamChatGenerics>['typing'];\n watcherCount?: number;\n watchers?: StreamChannelState<StreamChatGenerics>['watchers'];\n};\n\nexport type ChannelStateContextValue<\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n> = Omit<ChannelState<StreamChatGenerics>, 'typing'> & {\n channel: Channel<StreamChatGenerics>;\n channelCapabilities: Record<string, boolean>;\n channelConfig: ChannelConfigWithInfo<StreamChatGenerics> | undefined;\n imageAttachmentSizeHandler: ImageAttachmentSizeHandler;\n multipleUploads: boolean;\n notifications: ChannelNotifications;\n shouldGenerateVideoThumbnail: boolean;\n videoAttachmentSizeHandler: VideoAttachmentSizeHandler;\n acceptedFiles?: string[];\n channelUnreadUiState?: ChannelUnreadUiState<StreamChatGenerics>;\n debounceURLEnrichmentMs?: URLEnrichmentConfig['debounceURLEnrichmentMs'];\n dragAndDropWindow?: boolean;\n enrichURLForPreview?: URLEnrichmentConfig['enrichURLForPreview'];\n findURLFn?: URLEnrichmentConfig['findURLFn'];\n giphyVersion?: GiphyVersions;\n maxNumberOfFiles?: number;\n mutes?: Array<Mute<StreamChatGenerics>>;\n onLinkPreviewDismissed?: URLEnrichmentConfig['onLinkPreviewDismissed'];\n watcher_count?: number;\n};\n\nexport const ChannelStateContext = React.createContext<ChannelStateContextValue | undefined>(\n undefined,\n);\n\nexport const ChannelStateProvider = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>({\n children,\n value,\n}: PropsWithChildren<{\n value: ChannelStateContextValue<StreamChatGenerics>;\n}>) => (\n <ChannelStateContext.Provider value={(value as unknown) as ChannelStateContextValue}>\n {children}\n </ChannelStateContext.Provider>\n);\n\nexport const useChannelStateContext = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>(\n componentName?: string,\n) => {\n const contextValue = useContext(ChannelStateContext);\n\n if (!contextValue) {\n console.warn(\n `The useChannelStateContext hook was called outside of the ChannelStateContext provider. Make sure this hook is called within a child of the Channel component. The errored call is located in the ${componentName} component.`,\n );\n\n return {} as ChannelStateContextValue<StreamChatGenerics>;\n }\n\n return (contextValue as unknown) as ChannelStateContextValue<StreamChatGenerics>;\n};\n\n/**\n * Typescript currently does not support partial inference, so if ChannelStateContext\n * typing is desired while using the HOC withChannelStateContext, the Props for the\n * wrapped component must be provided as the first generic.\n */\nexport const withChannelStateContext = <\n P extends UnknownType,\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>(\n Component: React.ComponentType<P>,\n) => {\n const WithChannelStateContextComponent = (\n props: Omit<P, keyof ChannelStateContextValue<StreamChatGenerics>>,\n ) => {\n const channelStateContext = useChannelStateContext<StreamChatGenerics>();\n\n return <Component {...(props as P)} {...channelStateContext} />;\n };\n\n WithChannelStateContextComponent.displayName = (\n Component.displayName ||\n Component.name ||\n 'Component'\n ).replace('Base', '');\n\n return WithChannelStateContextComponent;\n};\n", "import React, { PropsWithChildren, useContext } from 'react';\n\nimport type { AppSettingsAPIResponse, Channel, Mute } from 'stream-chat';\n\nimport { getDisplayName } from './utils/getDisplayName';\nimport type { ChatProps } from '../components/Chat/Chat';\nimport type { DefaultStreamChatGenerics, UnknownType } from '../types/types';\nimport type { ChannelsQueryState } from '../components/Chat/hooks/useChannelsQueryState';\n\ntype CSSClasses =\n | 'chat'\n | 'chatContainer'\n | 'channel'\n | 'channelList'\n | 'message'\n | 'messageList'\n | 'thread'\n | 'threadList'\n | 'virtualMessage'\n | 'virtualizedMessageList';\n\nexport type CustomClasses = Partial<Record<CSSClasses, string>>;\n\ntype ChannelCID = string; // e.g.: \"messaging:general\"\n\nexport type ChatContextValue<\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n> = {\n /**\n * Indicates, whether a channels query has been triggered within ChannelList by its channels pagination controller.\n */\n channelsQueryState: ChannelsQueryState;\n closeMobileNav: () => void;\n getAppSettings: () => Promise<AppSettingsAPIResponse<StreamChatGenerics>> | null;\n latestMessageDatesByChannels: Record<ChannelCID, Date>;\n mutes: Array<Mute<StreamChatGenerics>>;\n openMobileNav: () => void;\n /**\n * Sets active channel to be rendered within Channel component.\n * @param newChannel\n * @param watchers\n * @param event\n */\n setActiveChannel: (\n newChannel?: Channel<StreamChatGenerics>,\n watchers?: { limit?: number; offset?: number },\n event?: React.BaseSyntheticEvent,\n ) => void;\n useImageFlagEmojisOnWindows: boolean;\n /**\n * Active channel used to render the contents of the Channel component.\n */\n channel?: Channel<StreamChatGenerics>;\n /**\n * Object through which custom classes can be set for main container components of the SDK.\n */\n customClasses?: CustomClasses;\n navOpen?: boolean;\n} & Partial<Pick<ChatProps<StreamChatGenerics>, 'isMessageAIGenerated'>> &\n Required<Pick<ChatProps<StreamChatGenerics>, 'theme' | 'client'>>;\n\nexport const ChatContext = React.createContext<ChatContextValue | undefined>(undefined);\n\nexport const ChatProvider = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>({\n children,\n value,\n}: PropsWithChildren<{\n value: ChatContextValue<StreamChatGenerics>;\n}>) => (\n <ChatContext.Provider value={(value as unknown) as ChatContextValue}>\n {children}\n </ChatContext.Provider>\n);\n\nexport const useChatContext = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>(\n componentName?: string,\n) => {\n const contextValue = useContext(ChatContext);\n\n if (!contextValue) {\n console.warn(\n `The useChatContext hook was called outside of the ChatContext provider. Make sure this hook is called within a child of the Chat component. The errored call is located in the ${componentName} component.`,\n );\n\n return {} as ChatContextValue<StreamChatGenerics>;\n }\n\n return (contextValue as unknown) as ChatContextValue<StreamChatGenerics>;\n};\n\n/**\n * Typescript currently does not support partial inference so if ChatContext\n * typing is desired while using the HOC withChatContext the Props for the\n * wrapped component must be provided as the first generic.\n */\nexport const withChatContext = <\n P extends UnknownType,\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>(\n Component: React.ComponentType<P>,\n) => {\n const WithChatContextComponent = (props: Omit<P, keyof ChatContextValue<StreamChatGenerics>>) => {\n const chatContext = useChatContext<StreamChatGenerics>();\n\n return <Component {...(props as P)} {...chatContext} />;\n };\n WithChatContextComponent.displayName = `WithChatContext${getDisplayName(Component)}`;\n return WithChatContextComponent;\n};\n", "import React, { PropsWithChildren, useContext } from 'react';\n\nimport {\n AttachmentPreviewListProps,\n AttachmentProps,\n AvatarProps,\n BaseImageProps,\n ChannelPreviewActionButtonsProps,\n CooldownTimerProps,\n CustomMessageActionsListProps,\n DateSeparatorProps,\n EmojiSearchIndex,\n EmptyStateIndicatorProps,\n EventComponentProps,\n FixedHeightMessageProps,\n GiphyPreviewMessageProps,\n LinkPreviewListProps,\n LoadingIndicatorProps,\n MessageBouncePromptProps,\n MessageDeletedProps,\n MessageInputProps,\n MessageListNotificationsProps,\n MessageNotificationProps,\n MessageOptionsProps,\n MessageProps,\n MessageRepliesCountButtonProps,\n MessageStatusProps,\n MessageTimestampProps,\n MessageUIComponentProps,\n ModalGalleryProps,\n PinIndicatorProps,\n PollCreationDialogProps,\n PollOptionSelectorProps,\n QuotedMessagePreviewProps,\n ReactionOptions,\n ReactionSelectorProps,\n ReactionsListProps,\n RecordingPermissionDeniedNotificationProps,\n SendButtonProps,\n StartRecordingAudioButtonProps,\n StreamedMessageTextProps,\n SuggestionItemProps,\n SuggestionListProps,\n ThreadHeaderProps,\n ThreadListItemProps,\n ThreadListItemUIProps,\n TimestampProps,\n TypingIndicatorProps,\n UnreadMessagesNotificationProps,\n UnreadMessagesSeparatorProps,\n} from '../components';\n\nimport type {\n CustomTrigger,\n DefaultStreamChatGenerics,\n PropsWithChildrenOnly,\n UnknownType,\n} from '../types/types';\nimport type { StopAIGenerationButtonProps } from '../components/MessageInput/StopAIGenerationButton';\n\nexport type ComponentContextValue<\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,\n V extends CustomTrigger = CustomTrigger\n> = {\n /** Custom UI component to display a message attachment, defaults to and accepts same props as: [Attachment](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Attachment/Attachment.tsx) */\n Attachment?: React.ComponentType<AttachmentProps<StreamChatGenerics>>;\n /** Custom UI component to display an attachment previews in MessageInput, defaults to and accepts same props as: [Attachment](https://github.com/GetStream/stream-chat-react/blob/master/src/components/MessageInput/AttachmentPreviewList.tsx) */\n AttachmentPreviewList?: React.ComponentType<AttachmentPreviewListProps>;\n /** Custom UI component to control adding attachments to MessageInput, defaults to and accepts same props as: [AttachmentSelector](https://github.com/GetStream/stream-chat-react/blob/master/src/components/MessageInput/AttachmentSelector.tsx) */\n AttachmentSelector?: React.ComponentType;\n /** Custom UI component for contents of attachment selector initiation button */\n AttachmentSelectorInitiationButtonContents?: React.ComponentType;\n /** Custom UI component to display AudioRecorder in MessageInput, defaults to and accepts same props as: [AudioRecorder](https://github.com/GetStream/stream-chat-react/blob/master/src/components/MessageInput/AudioRecorder.tsx) */\n AudioRecorder?: React.ComponentType;\n /** Optional UI component to override the default suggestion Item component, defaults to and accepts same props as: [Item](https://github.com/GetStream/stream-chat-react/blob/master/src/components/AutoCompleteTextarea/Item.js) */\n AutocompleteSuggestionItem?: React.ComponentType<SuggestionItemProps<StreamChatGenerics>>;\n /** Optional UI component to override the default List component that displays suggestions, defaults to and accepts same props as: [List](https://github.com/GetStream/stream-chat-react/blob/master/src/components/AutoCompleteTextarea/List.js) */\n AutocompleteSuggestionList?: React.ComponentType<SuggestionListProps<StreamChatGenerics>>;\n /** UI component to display a user's avatar, defaults to and accepts same props as: [Avatar](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Avatar/Avatar.tsx) */\n Avatar?: React.ComponentType<AvatarProps<StreamChatGenerics>>;\n /** Custom UI component to display <img/> elements resp. a fallback in case of load error, defaults to and accepts same props as: [BaseImage](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Gallery/BaseImage.tsx) */\n BaseImage?: React.ComponentType<BaseImageProps>;\n /** Custom UI component to display set of action buttons within `ChannelPreviewMessenger` component, accepts same props as: [ChannelPreviewActionButtons](https://github.com/GetStream/stream-chat-react/blob/master/src/components/ChannelList/ChannelPreviewActionButtons.tsx) */\n ChannelPreviewActionButtons?: React.ComponentType<\n ChannelPreviewActionButtonsProps<StreamChatGenerics>\n >;\n /** Custom UI component to display the slow mode cooldown timer, defaults to and accepts same props as: [CooldownTimer](https://github.com/GetStream/stream-chat-react/blob/master/src/components/MessageInput/CooldownTimer.tsx) */\n CooldownTimer?: React.ComponentType<CooldownTimerProps>;\n /** Custom UI component to render set of buttons to be displayed in the MessageActionsBox, defaults to and accepts same props as: [CustomMessageActionsList](https://github.com/GetStream/stream-chat-react/blob/master/src/components/MessageActions/CustomMessageActionsList.tsx) */\n CustomMessageActionsList?: React.ComponentType<CustomMessageActionsListProps<StreamChatGenerics>>;\n /** Custom UI component for date separators, defaults to and accepts same props as: [DateSeparator](https://github.com/GetStream/stream-chat-react/blob/master/src/components/DateSeparator.tsx) */\n DateSeparator?: React.ComponentType<DateSeparatorProps>;\n /** Custom UI component to override default edit message input, defaults to and accepts same props as: [EditMessageForm](https://github.com/GetStream/stream-chat-react/blob/master/src/components/MessageInput/EditMessageForm.tsx) */\n EditMessageInput?: React.ComponentType<MessageInputProps<StreamChatGenerics>>;\n /** Custom UI component for rendering button with emoji picker in MessageInput */\n EmojiPicker?: React.ComponentType;\n /** Mechanism to be used with autocomplete and text replace features of the `MessageInput` component, see [emoji-mart `SearchIndex`](https://github.com/missive/emoji-mart#%EF%B8%8F%EF%B8%8F-headless-search) */\n emojiSearchIndex?: EmojiSearchIndex;\n /** Custom UI component to be displayed when the `MessageList` is empty, defaults to and accepts same props as: [EmptyStateIndicator](https://github.com/GetStream/stream-chat-react/blob/master/src/components/EmptyStateIndicator/EmptyStateIndicator.tsx) */\n EmptyStateIndicator?: React.ComponentType<EmptyStateIndicatorProps>;\n /**\n * Custom UI component for file upload icon, defaults to and accepts same props as: [FileUploadIcon](https://github.com/GetStream/stream-chat-react/blob/master/src/components/MessageInput/icons.tsx)\n * @deprecated use AttachmentSelectorInitiationButtonContents prop instead\n */\n FileUploadIcon?: React.ComponentType;\n /** Custom UI component to render a Giphy preview in the `VirtualizedMessageList` */\n GiphyPreviewMessage?: React.ComponentType<GiphyPreviewMessageProps<StreamChatGenerics>>;\n /** Custom UI component to render at the top of the `MessageList` */\n HeaderComponent?: React.ComponentType;\n /** Custom UI component handling how the message input is rendered, defaults to and accepts the same props as [MessageInputFlat](https://github.com/GetStream/stream-chat-react/blob/master/src/components/MessageInput/MessageInputFlat.tsx) */\n Input?: React.ComponentType<MessageInputProps<StreamChatGenerics, V>>;\n /** Custom component to render link previews in message input **/\n LinkPreviewList?: React.ComponentType<LinkPreviewListProps>;\n /** Custom UI component to render while the `MessageList` is loading new messages, defaults to and accepts same props as: [LoadingIndicator](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Loading/LoadingIndicator.tsx) */\n LoadingIndicator?: React.ComponentType<LoadingIndicatorProps>;\n /** Custom UI component to display a message in the standard `MessageList`, defaults to and accepts the same props as: [MessageSimple](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Message/MessageSimple.tsx) */\n Message?: React.ComponentType<MessageUIComponentProps<StreamChatGenerics>>;\n /** Custom UI component for message actions popup, accepts no props, all the defaults are set within [MessageActions (unstable)](https://github.com/GetStream/stream-chat-react/blob/master/src/experimental/MessageActions/MessageActions.tsx) */\n MessageActions?: React.ComponentType;\n /** Custom UI component to display the contents of a bounced message modal. Usually it allows to retry, edit, or delete the message. Defaults to and accepts the same props as: [MessageBouncePrompt](https://github.com/GetStream/stream-chat-react/blob/master/src/components/MessageBounce/MessageBouncePrompt.tsx) */\n MessageBouncePrompt?: React.ComponentType<MessageBouncePromptProps>;\n /** Custom UI component for a deleted message, defaults to and accepts same props as: [MessageDeleted](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Message/MessageDeleted.tsx) */\n MessageDeleted?: React.ComponentType<MessageDeletedProps<StreamChatGenerics>>;\n MessageListMainPanel?: React.ComponentType<PropsWithChildrenOnly>;\n /** Custom UI component that displays message and connection status notifications in the `MessageList`, defaults to and accepts same props as [DefaultMessageListNotifications](https://github.com/GetStream/stream-chat-react/blob/master/src/components/MessageList/MessageListNotifications.tsx) */\n MessageListNotifications?: React.ComponentType<MessageListNotificationsProps>;\n /** Custom UI component to display a notification when scrolled up the list and new messages arrive, defaults to and accepts same props as [MessageNotification](https://github.com/GetStream/stream-chat-react/blob/master/src/components/MessageList/MessageNotification.tsx) */\n MessageNotification?: React.ComponentType<MessageNotificationProps>;\n /**\n * Custom UI component for message options popup, defaults to and accepts same props as: [MessageOptions](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Message/MessageOptions.tsx)\n *\n * @deprecated Use MessageActions property instead.\n */\n MessageOptions?: React.ComponentType<MessageOptionsProps<StreamChatGenerics>>;\n /** Custom UI component to display message replies, defaults to and accepts same props as: [MessageRepliesCountButton](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Message/MessageRepliesCountButton.tsx) */\n MessageRepliesCountButton?: React.ComponentType<MessageRepliesCountButtonProps>;\n /** Custom UI component to display message delivery status, defaults to and accepts same props as: [MessageStatus](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Message/MessageStatus.tsx) */\n MessageStatus?: React.ComponentType<MessageStatusProps>;\n /** Custom UI component to display system messages, defaults to and accepts same props as: [EventComponent](https://github.com/GetStream/stream-chat-react/blob/master/src/components/EventComponent/EventComponent.tsx) */\n MessageSystem?: React.ComponentType<EventComponentProps<StreamChatGenerics>>;\n /** Custom UI component to display a timestamp on a message, defaults to and accepts same props as: [MessageTimestamp](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Message/MessageTimestamp.tsx) */\n MessageTimestamp?: React.ComponentType<MessageTimestampProps<StreamChatGenerics>>;\n /** Custom UI component for viewing message's image attachments, defaults to and accepts the same props as [ModalGallery](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Gallery/ModalGallery.tsx) */\n ModalGallery?: React.ComponentType<ModalGalleryProps>;\n /** Custom UI component to override default pinned message indicator, defaults to and accepts same props as: [PinIndicator](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Message/icons.tsx) */\n PinIndicator?: React.ComponentType<PinIndicatorProps<StreamChatGenerics>>;\n /** Custom UI component to override default poll actions rendering in a message, defaults to and accepts same props as: [PollActions](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Poll/PollActions/PollActions.tsx) */\n PollActions?: React.ComponentType;\n /** Custom UI component to override default poll rendering in a message, defaults to and accepts same props as: [PollContent](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Poll/PollContent.tsx) */\n PollContent?: React.ComponentType;\n /** Custom UI component to override default poll creation dialog contents, defaults to and accepts same props as: [PollCreationDialog](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Poll/PollCreationDialog/PollCreationDialog.tsx) */\n PollCreationDialog?: React.ComponentType<PollCreationDialogProps>;\n /** Custom UI component to override default poll header in a message, defaults to and accepts same props as: [PollHeader](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Poll/PollHeader.tsx) */\n PollHeader?: React.ComponentType;\n /** Custom UI component to override default poll option selector, defaults to and accepts same props as: [PollOptionSelector](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Poll/PollOptionSelector.tsx) */\n PollOptionSelector?: React.ComponentType<PollOptionSelectorProps<StreamChatGenerics>>;\n /** Custom UI component to override quoted message UI on a sent message, defaults to and accepts same props as: [QuotedMessage](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Message/QuotedMessage.tsx) */\n QuotedMessage?: React.ComponentType;\n /** Custom UI component to override the message input's quoted message preview, defaults to and accepts same props as: [QuotedMessagePreview](https://github.com/GetStream/stream-chat-react/blob/master/src/components/MessageInput/QuotedMessagePreview.tsx) */\n QuotedMessagePreview?: React.ComponentType<QuotedMessagePreviewProps<StreamChatGenerics>>;\n /** Custom UI component to override the rendering of quoted poll, defaults to and accepts same props as: [QuotedPoll](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Poll/QuotedPoll.tsx) */\n QuotedPoll?: React.ComponentType;\n /** Custom reaction options to be applied to ReactionSelector, ReactionList and SimpleReactionList components */\n reactionOptions?: ReactionOptions;\n /** Custom UI component to display the reaction selector, defaults to and accepts same props as: [ReactionSelector](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Reactions/ReactionSelector.tsx) */\n ReactionSelector?: React.ForwardRefExoticComponent<ReactionSelectorProps<StreamChatGenerics>>;\n /** Custom UI component to display the list of reactions on a message, defaults to and accepts same props as: [ReactionsList](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Reactions/ReactionsList.tsx) */\n ReactionsList?: React.ComponentType<ReactionsListProps<StreamChatGenerics>>;\n RecordingPermissionDeniedNotification?: React.ComponentType<RecordingPermissionDeniedNotificationProps>;\n /** Custom UI component for send button, defaults to and accepts same props as: [SendButton](https://github.com/GetStream/stream-chat-react/blob/master/src/components/MessageInput/icons.tsx) */\n SendButton?: React.ComponentType<SendButtonProps<StreamChatGenerics>>;\n /** Custom UI component button for initiating audio recording, defaults to and accepts same props as: [StartRecordingAudioButton](https://github.com/GetStream/stream-chat-react/blob/master/src/components/MediaRecorder/AudioRecorder/AudioRecordingButtons.tsx) */\n StartRecordingAudioButton?: React.ComponentType<StartRecordingAudioButtonProps>;\n StopAIGenerationButton?: React.ComponentType<StopAIGenerationButtonProps> | null;\n StreamedMessageText?: React.ComponentType<StreamedMessageTextProps>;\n /** Custom UI component that displays thread's parent or other message at the top of the `MessageList`, defaults to and accepts same props as [MessageSimple](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Message/MessageSimple.tsx) */\n ThreadHead?: React.ComponentType<MessageProps<StreamChatGenerics>>;\n /** Custom UI component to display the header of a `Thread`, defaults to and accepts same props as: [DefaultThreadHeader](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Thread/Thread.tsx) */\n ThreadHeader?: React.ComponentType<ThreadHeaderProps<StreamChatGenerics>>;\n ThreadInput?: React.ComponentType<MessageInputProps<StreamChatGenerics, V>>;\n ThreadListEmptyPlaceholder?: React.ComponentType;\n ThreadListItem?: React.ComponentType<ThreadListItemProps>;\n ThreadListItemUI?: React.ComponentType<ThreadListItemUIProps>;\n ThreadListLoadingIndicator?: React.ComponentType;\n ThreadListUnseenThreadsBanner?: React.ComponentType;\n /** Custom UI component to display the start of a threaded `MessageList`, defaults to and accepts same props as: [DefaultThreadStart](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Thread/Thread.tsx) */\n ThreadStart?: React.ComponentType;\n /** Custom UI component to display a date used in timestamps. It's used internally by the default `MessageTimestamp`, and to display a timestamp for edited messages. */\n Timestamp?: React.ComponentType<TimestampProps>;\n /** Optional context provider that lets you override the default autocomplete triggers, defaults to: [DefaultTriggerProvider](https://github.com/GetStream/stream-chat-react/blob/master/src/components/MessageInput/DefaultTriggerProvider.tsx) */\n TriggerProvider?: React.ComponentType;\n /** Custom UI component for the typing indicator, defaults to and accepts same props as: [TypingIndicator](https://github.com/GetStream/stream-chat-react/blob/master/src/components/TypingIndicator/TypingIndicator.tsx) */\n TypingIndicator?: React.ComponentType<TypingIndicatorProps>;\n /** Custom UI component that indicates a user is viewing unread messages. It disappears once the user scrolls to UnreadMessagesSeparator. Defaults to and accepts same props as: [UnreadMessagesNotification](https://github.com/GetStream/stream-chat-react/blob/master/src/components/MessageList/UnreadMessagesNotification.tsx) */\n UnreadMessagesNotification?: React.ComponentType<UnreadMessagesNotificationProps>;\n /** Custom UI component that separates read messages from unread, defaults to and accepts same props as: [UnreadMessagesSeparator](https://github.com/GetStream/stream-chat-react/blob/master/src/components/MessageList/UnreadMessagesSeparator.tsx) */\n UnreadMessagesSeparator?: React.ComponentType<UnreadMessagesSeparatorProps>;\n /** Custom UI component to display a message in the `VirtualizedMessageList`, does not have a default implementation */\n VirtualMessage?: React.ComponentType<FixedHeightMessageProps<StreamChatGenerics>>;\n};\n\nexport const ComponentContext = React.createContext<ComponentContextValue>({});\n\nexport const ComponentProvider = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,\n V extends CustomTrigger = CustomTrigger\n>({\n children,\n value,\n}: PropsWithChildren<{\n value: Partial<ComponentContextValue<StreamChatGenerics, V>>;\n}>) => (\n <ComponentContext.Provider value={(value as unknown) as ComponentContextValue}>\n {children}\n </ComponentContext.Provider>\n);\n\nexport const useComponentContext = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,\n V extends CustomTrigger = CustomTrigger\n>(\n /**\n * @deprecated\n */\n // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars\n _componentName?: string,\n) => (useContext(ComponentContext) as unknown) as ComponentContextValue<StreamChatGenerics, V>;\n\n/**\n * Typescript currently does not support partial inference, so if ComponentContext\n * typing is desired while using the HOC withComponentContext, the Props for the\n * wrapped component must be provided as the first generic.\n */\nexport const withComponentContext = <\n P extends UnknownType,\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,\n V extends CustomTrigger = CustomTrigger\n>(\n Component: React.ComponentType<P>,\n) => {\n const WithComponentContextComponent = (\n props: Omit<P, keyof ComponentContextValue<StreamChatGenerics, V>>,\n ) => {\n const componentContext = useComponentContext<StreamChatGenerics, V>();\n\n return <Component {...(props as P)} {...componentContext} />;\n };\n\n WithComponentContextComponent.displayName = (\n Component.displayName ||\n Component.name ||\n 'Component'\n ).replace('Base', '');\n\n return WithComponentContextComponent;\n};\n", "import React, { PropsWithChildren, useContext, useState } from 'react';\nimport { DialogManager } from '../components/Dialog/DialogManager';\nimport { DialogPortalDestination } from '../components/Dialog/DialogPortal';\n\ntype DialogManagerProviderContextValue = {\n dialogManager: DialogManager;\n};\n\nconst DialogManagerProviderContext = React.createContext<\n DialogManagerProviderContextValue | undefined\n>(undefined);\n\nexport const DialogManagerProvider = ({ children, id }: PropsWithChildren<{ id?: string }>) => {\n const [dialogManager] = useState<DialogManager>(() => new DialogManager({ id }));\n\n return (\n <DialogManagerProviderContext.Provider value={{ dialogManager }}>\n {children}\n <DialogPortalDestination />\n </DialogManagerProviderContext.Provider>\n );\n};\n\nexport const useDialogManager = () => {\n const value = useContext(DialogManagerProviderContext);\n return value as DialogManagerProviderContextValue;\n};\n", "import React, { PropsWithChildren, useCallback } from 'react';\nimport { useDialogIsOpen, useOpenedDialogCount } from './hooks';\nimport { Portal } from '../Portal/Portal';\nimport { useDialogManager } from '../../context';\n\nexport const DialogPortalDestination = () => {\n const { dialogManager } = useDialogManager();\n const openedDialogCount = useOpenedDialogCount();\n\n return (\n <div\n className='str-chat__dialog-overlay'\n data-str-chat__portal-id={dialogManager.id}\n data-testid='str-chat__dialog-overlay'\n onClick={() => dialogManager.closeAll()}\n style={\n {\n '--str-chat__dialog-overlay-height': openedDialogCount > 0 ? '100%' : '0',\n } as React.CSSProperties\n }\n ></div>\n );\n};\n\ntype DialogPortalEntryProps = {\n dialogId: string;\n};\n\nexport const DialogPortalEntry = ({\n children,\n dialogId,\n}: PropsWithChildren<DialogPortalEntryProps>) => {\n const { dialogManager } = useDialogManager();\n const dialogIsOpen = useDialogIsOpen(dialogId);\n\n const getPortalDestination = useCallback(\n () => document.querySelector(`div[data-str-chat__portal-id=\"${dialogManager.id}\"]`),\n [dialogManager.id],\n );\n\n return (\n <Portal getPortalDestination={getPortalDestination} isOpen={dialogIsOpen}>\n {children}\n </Portal>\n );\n};\n", "import { useCallback, useEffect } from 'react';\nimport { useDialogManager } from '../../../context';\nimport { useStateStore } from '../../../store';\n\nimport type { DialogManagerState, GetOrCreateDialogParams } from '../DialogManager';\n\nexport const useDialog = ({ id }: GetOrCreateDialogParams) => {\n const { dialogManager } = useDialogManager();\n\n useEffect(\n () => () => {\n // Since this cleanup can run even if the component is still mounted\n // and dialog id is unchanged (e.g. in <StrictMode />), it's safer to\n // mark state as unused and only remove it after a timeout, rather than\n // to remove it immediately.\n dialogManager.markForRemoval(id);\n },\n [dialogManager, id],\n );\n\n return dialogManager.getOrCreate({ id });\n};\n\nexport const useDialogIsOpen = (id: string) => {\n const { dialogManager } = useDialogManager();\n const dialogIsOpenSelector = useCallback(\n ({ dialogsById }: DialogManagerState) => ({ isOpen: !!dialogsById[id]?.isOpen }),\n [id],\n );\n return useStateStore(dialogManager.state, dialogIsOpenSelector).isOpen;\n};\n\nconst openedDialogCountSelector = (nextValue: DialogManagerState) => ({\n openedDialogCount: Object.values(nextValue.dialogsById).reduce((count, dialog) => {\n if (dialog.isOpen) return count + 1;\n return count;\n }, 0),\n});\n\nexport const useOpenedDialogCount = () => {\n const { dialogManager } = useDialogManager();\n return useStateStore(dialogManager.state, openedDialogCountSelector).openedDialogCount;\n};\n", "import { useEffect, useState } from 'react';\n\nimport type { StateStore } from 'stream-chat';\n\nexport function useStateStore<\n T extends Record<string, unknown>,\n O extends Readonly<Record<string, unknown> | Readonly<unknown[]>>\n>(store: StateStore<T>, selector: (v: T) => O): O;\nexport function useStateStore<\n T extends Record<string, unknown>,\n O extends Readonly<Record<string, unknown> | Readonly<unknown[]>>\n>(store: StateStore<T> | undefined, selector: (v: T) => O): O | undefined;\nexport function useStateStore<\n T extends Record<string, unknown>,\n O extends Readonly<Record<string, unknown> | Readonly<unknown[]>>\n>(store: StateStore<T> | undefined, selector: (v: T) => O) {\n const [state, setState] = useState<O | undefined>(() => {\n if (!store) return undefined;\n return selector(store.getLatestValue());\n });\n\n useEffect(() => {\n if (!store) return;\n\n const unsubscribe = store.subscribeWithSelector(selector, setState);\n\n return unsubscribe;\n }, [store, selector]);\n\n return state;\n}\n", "import { PropsWithChildren, ReactPortal, useLayoutEffect, useState } from 'react';\nimport { createPortal } from 'react-dom';\n\nexport type PortalProps = {\n getPortalDestination: () => Element | null;\n isOpen?: boolean;\n};\n\nexport const Portal = ({\n children,\n getPortalDestination,\n isOpen,\n}: PropsWithChildren<PortalProps>): ReactPortal | null => {\n const [portalDestination, setPortalDestination] = useState<Element | null>(null);\n\n useLayoutEffect(() => {\n const destination = getPortalDestination();\n if (!destination || !isOpen) return;\n setPortalDestination(destination);\n }, [getPortalDestination, isOpen]);\n\n if (!portalDestination) return null;\n\n return createPortal(children, portalDestination);\n};\n", "import React, { PropsWithChildren, useContext } from 'react';\n\nimport type { Mute, ReactionResponse, ReactionSort, UserResponse } from 'stream-chat';\n\nimport type { ChannelActionContextValue } from './ChannelActionContext';\nimport type { StreamMessage } from './ChannelStateContext';\n\nimport type { ActionHandlerReturnType } from '../components/Message/hooks/useActionHandler';\nimport type { PinPermissions } from '../components/Message/hooks/usePinHandler';\nimport type { ReactEventHandler } from '../components/Message/types';\nimport type { MessageActionsArray } from '../components/Message/utils';\nimport type { MessageInputProps } from '../components/MessageInput/MessageInput';\nimport type { GroupStyle } from '../components/MessageList/utils';\nimport type {\n ReactionDetailsComparator,\n ReactionsComparator,\n ReactionType,\n} from '../components/Reactions/types';\n\nimport type { RenderTextOptions } from '../components/Message/renderText';\nimport type { DefaultStreamChatGenerics, UnknownType } from '../types/types';\n\nexport type CustomMessageActions<\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n> = {\n [key: string]: (\n message: StreamMessage<StreamChatGenerics>,\n event: React.BaseSyntheticEvent,\n ) => Promise<void> | void;\n};\n\nexport type MessageContextValue<\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n> = {\n /** If actions such as edit, delete, flag, mute are enabled on Message */\n actionsEnabled: boolean;\n /** Function to exit edit state */\n clearEditingState: (event?: React.BaseSyntheticEvent) => void;\n /** If the Message is in edit state */\n editing: boolean;\n /**\n * Returns all allowed actions on message by current user e.g., ['edit', 'delete', 'flag', 'mute', 'pin', 'quote', 'react', 'reply'].\n * Please check [Message](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Message.tsx) component for default implementation.\n */\n getMessageActions: () => MessageActionsArray<string>;\n /** Function to send an action in a Channel */\n handleAction: ActionHandlerReturnType;\n /** Function to delete a message in a Channel */\n handleDelete: ReactEventHandler;\n /** Function to edit a message in a Channel */\n handleEdit: ReactEventHandler;\n /** Function to fetch the message reactions */\n handleFetchReactions: (\n reactionType?: ReactionType<StreamChatGenerics>,\n sort?: ReactionSort<StreamChatGenerics>,\n ) => Promise<Array<ReactionResponse<StreamChatGenerics>>>;\n /** Function to flag a message in a Channel */\n handleFlag: ReactEventHandler;\n /** Function to mark message and the messages that follow it as unread in a Channel */\n handleMarkUnread: ReactEventHandler;\n /** Function to mute a user in a Channel */\n handleMute: ReactEventHandler;\n /** Function to open a Thread on a Message */\n handleOpenThread: ReactEventHandler;\n /** Function to pin a Message in a Channel */\n handlePin: ReactEventHandler;\n /** Function to post a reaction on a Message */\n handleReaction: (reactionType: string, event: React.BaseSyntheticEvent) => Promise<void>;\n /** Function to retry sending a Message */\n handleRetry: ChannelActionContextValue<StreamChatGenerics>['retrySendMessage'];\n /** Function that returns whether the Message belongs to the current user */\n isMyMessage: () => boolean;\n /** The message object */\n message: StreamMessage<StreamChatGenerics>;\n /** Indicates whether a message has not been read yet or has been marked unread */\n messageIsUnread: boolean;\n /** Handler function for a click event on an @mention in Message */\n onMentionsClickMessage: ReactEventHandler;\n /** Handler function for a hover event on an @mention in Message */\n onMentionsHoverMessage: ReactEventHandler;\n /** Handler function for a click event on the user that posted the Message */\n onUserClick: ReactEventHandler;\n /** Handler function for a hover event on the user that posted the Message */\n onUserHover: ReactEventHandler;\n /** Function to toggle the edit state on a Message */\n setEditingState: ReactEventHandler;\n /** Additional props for underlying MessageInput component, [available props](https://getstream.io/chat/docs/sdk/react/message-input-components/message_input/#props) */\n additionalMessageInputProps?: MessageInputProps<StreamChatGenerics>;\n /** Call this function to keep message list scrolled to the bottom when the scroll height increases, e.g. an element appears below the last message (only used in the `VirtualizedMessageList`) */\n autoscrollToBottom?: () => void;\n /** Message component configuration prop. If true, picking a reaction from the `ReactionSelector` component will close the selector */\n closeReactionSelectorOnClick?: boolean;\n /** Object containing custom message actions and function handlers */\n customMessageActions?: CustomMessageActions<StreamChatGenerics>;\n /** If true, the message is the last one in a group sent by a specific user (only used in the `VirtualizedMessageList`) */\n endOfGroup?: boolean;\n /** If true, the message is the first one in a group sent by a specific user (only used in the `VirtualizedMessageList`) */\n firstOfGroup?: boolean;\n /** Override the default formatting of the date. This is a function that has access to the original date object, returns a string */\n formatDate?: (date: Date) => string;\n /** If true, group messages sent by each user (only used in the `VirtualizedMessageList`) */\n groupedByUser?: boolean;\n /** A list of styles to apply to this message, ie. top, bottom, single */\n groupStyles?: GroupStyle[];\n /** Whether to highlight and focus the message on load */\n highlighted?: boolean;\n /** Whether the threaded message is the first in the thread list */\n initialMessage?: boolean;\n /**\n * A factory function that determines whether a message is AI generated or not.\n */\n isMessageAIGenerated?: (message: StreamMessage<StreamChatGenerics>) => boolean;\n /** Latest message id on current channel */\n lastReceivedId?: string | null;\n /** DOMRect object for parent MessageList component */\n messageListRect?: DOMRect;\n /** Array of muted users coming from [ChannelStateContext](https://getstream.io/chat/docs/sdk/react/contexts/channel_state_context/#mutes) */\n mutes?: Mute<StreamChatGenerics>[];\n /** @deprecated in favor of `channelCapabilities - The user roles allowed to pin Messages in various channel types */\n pinPermissions?: PinPermissions;\n /** Sort options to provide to a reactions query */\n reactionDetailsSort?: ReactionSort<StreamChatGenerics>;\n /** A list of users that have read this Message */\n readBy?: UserResponse<StreamChatGenerics>[];\n /** Custom function to render message text content, defaults to the renderText function: [utils](https://github.com/GetStream/stream-chat-react/blob/master/src/utils.tsx) */\n renderText?: (\n text?: string,\n mentioned_users?: UserResponse<StreamChatGenerics>[],\n options?: RenderTextOptions,\n ) => JSX.Element | null;\n /** Comparator function to sort the list of reacted users\n * @deprecated use `reactionDetailsSort` instead\n */\n sortReactionDetails?: ReactionDetailsComparator;\n /** Comparator function to sort reactions, defaults to chronological order */\n sortReactions?: ReactionsComparator;\n /** Whether or not the Message is in a Thread */\n threadList?: boolean;\n /** render HTML instead of markdown. Posting HTML is only allowed server-side */\n unsafeHTML?: boolean;\n};\n\nexport const MessageContext = React.createContext<MessageContextValue | undefined>(undefined);\n\nexport const MessageProvider = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>({\n children,\n value,\n}: PropsWithChildren<{\n value: MessageContextValue<StreamChatGenerics>;\n}>) => (\n <MessageContext.Provider value={(value as unknown) as MessageContextValue}>\n {children}\n </MessageContext.Provider>\n);\n\nexport const useMessageContext = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>(\n // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars\n _componentName?: string,\n) => {\n const contextValue = useContext(MessageContext);\n\n if (!contextValue) {\n return {} as MessageContextValue<StreamChatGenerics>;\n }\n\n return (contextValue as unknown) as MessageContextValue<StreamChatGenerics>;\n};\n\n/**\n * Typescript currently does not support partial inference, so if MessageContext\n * typing is desired while using the HOC withMessageContext, the Props for the\n * wrapped component must be provided as the first generic.\n */\nexport const withMessageContext = <\n P extends UnknownType,\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>(\n Component: React.ComponentType<P>,\n) => {\n const WithMessageContextComponent = (\n props: Omit<P, keyof MessageContextValue<StreamChatGenerics>>,\n ) => {\n const messageContext = useMessageContext<StreamChatGenerics>();\n\n return <Component {...(props as P)} {...messageContext} />;\n };\n\n WithMessageContextComponent.displayName = (\n Component.displayName ||\n Component.name ||\n 'Component'\n ).replace('Base', '');\n\n return WithMessageContextComponent;\n};\n", "import React, { PropsWithChildren, useContext } from 'react';\nimport Dayjs from 'dayjs';\nimport calendar from 'dayjs/plugin/calendar';\nimport localizedFormat from 'dayjs/plugin/localizedFormat';\n\nimport { getDisplayName } from './utils/getDisplayName';\nimport { defaultDateTimeParser, defaultTranslatorFunction } from '../i18n/utils';\n\nimport type { TFunction } from 'i18next';\nimport type { TranslationLanguages } from 'stream-chat';\n\nimport type { UnknownType } from '../types/types';\nimport type { TDateTimeParser } from '../i18n/types';\n\nDayjs.extend(calendar);\nDayjs.extend(localizedFormat);\n\nexport type TranslationContextValue = {\n t: TFunction;\n tDateTimeParser: TDateTimeParser;\n userLanguage: TranslationLanguages;\n};\n\nexport const TranslationContext = React.createContext<TranslationContextValue>({\n t: defaultTranslatorFunction,\n tDateTimeParser: defaultDateTimeParser,\n userLanguage: 'en',\n});\n\nexport const TranslationProvider = ({\n children,\n value,\n}: PropsWithChildren<{ value: TranslationContextValue }>) => (\n <TranslationContext.Provider value={value}>{children}</TranslationContext.Provider>\n);\n\nexport const useTranslationContext = (componentName?: string) => {\n const contextValue = useContext(TranslationContext);\n\n if (!contextValue) {\n console.warn(\n `The useTranslationContext hook was called outside of the TranslationContext provider. Make sure this hook is called within a child of the Chat component. The errored call is located in the ${componentName} component.`,\n );\n\n return {} as TranslationContextValue;\n }\n\n return contextValue;\n};\n\nexport const withTranslationContext = <P extends UnknownType>(\n Component: React.ComponentType<P>,\n) => {\n const WithTranslationContextComponent = (props: Omit<P, keyof TranslationContextValue>) => {\n const translationContext = useTranslationContext();\n\n return <Component {...(props as P)} {...translationContext} />;\n };\n\n WithTranslationContextComponent.displayName = `WithTranslationContext${getDisplayName(\n Component,\n )}`;\n\n return WithTranslationContextComponent;\n};\n", "import Dayjs from 'dayjs';\n\nimport type { TFunction } from 'i18next';\nimport type { Moment } from 'moment-timezone';\nimport type {\n DateFormatterOptions,\n PredefinedFormatters,\n SupportedTranslations,\n TDateTimeParserInput,\n TDateTimeParserOutput,\n TimestampFormatterOptions,\n} from './types';\n\nexport const notValidDateWarning =\n 'MessageTimestamp was called without a message, or message has invalid created_at date.';\nexport const noParsingFunctionWarning =\n 'MessageTimestamp was called but there is no datetime parsing function available';\n\nexport const isNumberOrString = (output: TDateTimeParserOutput): output is number | string =>\n typeof output === 'string' || typeof output === 'number';\n\nexport const isDayOrMoment = (output: TDateTimeParserOutput): output is Dayjs.Dayjs | Moment =>\n !!(output as Dayjs.Dayjs | Moment)?.isSame;\n\nexport const isDate = (output: TDateTimeParserOutput): output is Date =>\n !!(output as Date)?.getMonth;\n\nexport function getDateString({\n calendar,\n calendarFormats,\n format,\n formatDate,\n messageCreatedAt,\n t,\n tDateTimeParser,\n timestampTranslationKey,\n}: DateFormatterOptions): string | number | null {\n if (\n !messageCreatedAt ||\n (typeof messageCreatedAt === 'string' && !Date.parse(messageCreatedAt))\n ) {\n console.warn(notValidDateWarning);\n return null;\n }\n\n if (typeof formatDate === 'function') {\n return formatDate(new Date(messageCreatedAt));\n }\n\n if (t && timestampTranslationKey) {\n const options: TimestampFormatterOptions = {};\n if (typeof calendar !== 'undefined' && calendar !== null) options.calendar = calendar;\n if (typeof calendarFormats !== 'undefined' && calendarFormats !== null)\n options.calendarFormats = calendarFormats;\n if (typeof format !== 'undefined' && format !== null) options.format = format;\n\n const translatedTimestamp = t(timestampTranslationKey, {\n ...options,\n timestamp: new Date(messageCreatedAt),\n });\n const translationKeyFound = timestampTranslationKey !== translatedTimestamp;\n if (translationKeyFound) return translatedTimestamp;\n }\n\n if (!tDateTimeParser) {\n console.warn(noParsingFunctionWarning);\n return null;\n }\n\n const parsedTime = tDateTimeParser(messageCreatedAt);\n\n if (isDayOrMoment(parsedTime)) {\n /**\n * parsedTime.calendar is guaranteed on the type but is only\n * available when a user calls dayjs.extend(calendar)\n */\n return calendar && parsedTime.calendar\n ? parsedTime.calendar(undefined, calendarFormats || undefined)\n : parsedTime.format(format || undefined);\n }\n\n if (isDate(parsedTime)) {\n return parsedTime.toDateString();\n }\n\n if (isNumberOrString(parsedTime)) {\n return parsedTime;\n }\n\n return null;\n}\n\nexport const predefinedFormatters: PredefinedFormatters = {\n timestampFormatter: (streamI18n) => (\n value,\n _,\n {\n calendarFormats,\n ...options\n }: Pick<TimestampFormatterOptions, 'calendar' | 'format'> & {\n calendarFormats?: Record<string, string> | string;\n },\n ) => {\n let parsedCalendarFormats;\n try {\n if (!options.calendar) {\n parsedCalendarFormats = {};\n } else if (typeof calendarFormats === 'string') {\n parsedCalendarFormats = JSON.parse(calendarFormats);\n } else if (typeof calendarFormats === 'object') {\n parsedCalendarFormats = calendarFormats;\n }\n } catch (e) {\n console.error('[TIMESTAMP FORMATTER]', e);\n }\n\n const result = getDateString({\n ...options,\n calendarFormats: parsedCalendarFormats,\n messageCreatedAt: value,\n tDateTimeParser: streamI18n.tDateTimeParser,\n });\n if (!result || typeof result === 'number') {\n return JSON.stringify(value);\n }\n return result;\n },\n};\n\nexport const defaultTranslatorFunction: TFunction = <tResult = string>(key: tResult) => key;\n\nexport const defaultDateTimeParser = (input?: TDateTimeParserInput) => Dayjs(input);\n\nexport const isLanguageSupported = (language: string): language is SupportedTranslations => {\n const translations = ['de', 'en', 'es', 'fr', 'hi', 'it', 'ja', 'ko', 'nl', 'pt', 'ru', 'tr'];\n return translations.some((translation) => language === translation);\n};\n", "import clsx from 'clsx';\nimport React, { useEffect, useState } from 'react';\n\nimport type { UserResponse } from 'stream-chat';\n\nimport { Icon } from '../Threads/icons';\nimport { getWholeChar } from '../../utils';\n\nimport type { DefaultStreamChatGenerics } from '../../types/types';\n\nexport type AvatarProps<\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n> = {\n /** Custom root element class that will be merged with the default class */\n className?: string;\n /** Image URL or default is an image of the first initial of the name if there is one */\n image?: string | null;\n /** Name of the image, used for title tag fallback */\n name?: string;\n /** click event handler attached to the component root element */\n onClick?: (event: React.BaseSyntheticEvent) => void;\n /** mouseOver event handler attached to the component root element */\n onMouseOver?: (event: React.BaseSyntheticEvent) => void;\n /** The entire user object for the chat user displayed in the component */\n user?: UserResponse<StreamChatGenerics>;\n};\n\n/**\n * A round avatar image with fallback to username's first letter\n */\nexport const Avatar = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>(\n props: AvatarProps<StreamChatGenerics>,\n) => {\n const {\n className,\n image,\n name,\n onClick = () => undefined,\n onMouseOver = () => undefined,\n } = props;\n\n const [error, setError] = useState(false);\n\n useEffect(() => {\n setError(false);\n }, [image]);\n\n const nameStr = name?.toString() || '';\n const initials = getWholeChar(nameStr, 0);\n const showImage = image && !error;\n\n return (\n <div\n className={clsx(`str-chat__avatar str-chat__message-sender-avatar`, className, {\n ['str-chat__avatar--multiple-letters']: initials.length > 1,\n ['str-chat__avatar--no-letters']: !initials.length,\n ['str-chat__avatar--one-letter']: initials.length === 1,\n })}\n data-testid='avatar'\n onClick={onClick}\n onMouseOver={onMouseOver}\n role='button'\n title={name}\n >\n {showImage ? (\n <img\n alt={initials}\n className='str-chat__avatar-image'\n data-testid='avatar-img'\n onError={() => setError(true)}\n src={image}\n />\n ) : (\n <>\n {!!initials.length && (\n <div className={clsx('str-chat__avatar-fallback')} data-testid='avatar-fallback'>\n {initials}\n </div>\n )}\n {!initials.length && <Icon.User />}\n </>\n )}\n </div>\n );\n};\n", "/* eslint-disable react/display-name */\nimport React from 'react';\nimport { ComponentPropsWithoutRef } from 'react';\n\n// TODO: unify icons across SDK\nexport const Icon = {\n MessageBubble: (props: ComponentPropsWithoutRef<'svg'>) => (\n <svg\n className='str-chat__icon str-chat__icon--message-bubble'\n fill='none'\n height='14'\n viewBox='0 0 14 14'\n width='14'\n xmlns='http://www.w3.org/2000/svg'\n {...props}\n >\n <path\n d='M1.66659 1.66665H12.3333V9.66665H2.44659L1.66659 10.4466V1.66665ZM1.66659 0.333313C0.933252 0.333313 0.339919 0.933313 0.339919 1.66665L0.333252 13.6666L2.99992 11H12.3333C13.0666 11 13.6666 10.4 13.6666 9.66665V1.66665C13.6666 0.933313 13.0666 0.333313 12.3333 0.333313H1.66659ZM2.99992 6.99998H10.9999V8.33331H2.99992V6.99998ZM2.99992 4.99998H10.9999V6.33331H2.99992V4.99998ZM2.99992 2.99998H10.9999V4.33331H2.99992V2.99998Z'\n fill='currentColor'\n />\n </svg>\n ),\n MessageBubbleEmpty: (props: ComponentPropsWithoutRef<'svg'>) => (\n <svg\n className='str-chat__icon str-chat__icon--message-bubble-empty'\n fill='none'\n height='20'\n viewBox='0 0 20 20'\n width='20'\n xmlns='http://www.w3.org/2000/svg'\n {...props}\n >\n <path\n d='M18 0H2C0.9 0 0 0.9 0 2V20L4 16H18C19.1 16 20 15.1 20 14V2C20 0.9 19.1 0 18 0ZM18 14H4L2 16V2H18V14Z'\n fill='currentColor'\n />\n </svg>\n ),\n Reload: (props: ComponentPropsWithoutRef<'svg'>) => (\n <svg\n className='str-chat__icon str-chat__icon--reload'\n fill='none'\n height='22'\n viewBox='0 0 16 22'\n width='16'\n xmlns='http://www.w3.org/2000/svg'\n {...props}\n >\n <path\n d='M8 3V0L4 4L8 8V5C11.31 5 14 7.69 14 11C14 12.01 13.75 12.97 13.3 13.8L14.76 15.26C15.54 14.03 16 12.57 16 11C16 6.58 12.42 3 8 3ZM8 17C4.69 17 2 14.31 2 11C2 9.99 2.25 9.03 2.7 8.2L1.24 6.74C0.46 7.97 0 9.43 0 11C0 15.42 3.58 19 8 19V22L12 18L8 14V17Z'\n fill='currentColor'\n />\n </svg>\n ),\n User: (props: ComponentPropsWithoutRef<'svg'>) => (\n <svg\n className='str-chat__icon str-chat__icon--user'\n fill='none'\n height='16'\n viewBox='0 0 16 16'\n width='16'\n xmlns='http://www.w3.org/2000/svg'\n {...props}\n >\n <path\n d='M8 2C9.1 2 10 2.9 10 4C10 5.1 9.1 6 8 6C6.9 6 6 5.1 6 4C6 2.9 6.9 2 8 2ZM8 12C10.7 12 13.8 13.29 14 14H2C2.23 13.28 5.31 12 8 12ZM8 0C5.79 0 4 1.79 4 4C4 6.21 5.79 8 8 8C10.21 8 12 6.21 12 4C12 1.79 10.21 0 8 0ZM8 10C5.33 10 0 11.34 0 14V16H16V14C16 11.34 10.67 10 8 10Z'\n fill='currentColor'\n />\n </svg>\n ),\n};\n", "// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/charAt#getting_whole_characters\nexport const getWholeChar = (str: string, i: number) => {\n const code = str.charCodeAt(i);\n\n if (Number.isNaN(code)) return '';\n\n if (code < 0xd800 || code > 0xdfff) return str.charAt(i);\n\n if (0xd800 <= code && code <= 0xdbff) {\n if (str.length <= i + 1) {\n throw 'High surrogate without following low surrogate';\n }\n\n const next = str.charCodeAt(i + 1);\n\n if (0xdc00 > next || next > 0xdfff) {\n throw 'High surrogate without following low surrogate';\n }\n\n return str.charAt(i) + str.charAt(i + 1);\n }\n\n if (i === 0) {\n throw 'Low surrogate without preceding high surrogate';\n }\n\n const prev = str.charCodeAt(i - 1);\n\n if (0xd800 > prev || prev > 0xdbff) {\n throw 'Low surrogate without preceding high surrogate';\n }\n\n return '';\n};\n", "import deepequal from 'react-fast-compare';\nimport emojiRegex from 'emoji-regex';\n\nimport type { TFunction } from 'i18next';\nimport type { MessageResponse, Mute, StreamChat, UserResponse } from 'stream-chat';\nimport type { PinPermissions } from './hooks';\nimport type { MessageProps } from './types';\nimport type {\n ComponentContextValue,\n CustomMessageActions,\n MessageContextValue,\n StreamMessage,\n} from '../../context';\nimport type { DefaultStreamChatGenerics } from '../../types/types';\n\n/**\n * Following function validates a function which returns notification message.\n * It validates if the first parameter is function and also if return value of function is string or no.\n */\nexport const validateAndGetMessage = <T extends unknown[]>(\n func: (...args: T) => unknown,\n args: T,\n) => {\n if (!func || typeof func !== 'function') return null;\n\n // below is due to tests passing a single argument\n // rather than an array.\n if (!(args instanceof Array)) {\n // @ts-expect-error\n args = [args];\n }\n\n const returnValue = func(...args);\n\n if (typeof returnValue !== 'string') return null;\n\n return returnValue;\n};\n\n/**\n * Tell if the owner of the current message is muted\n */\nexport const isUserMuted = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>(\n message: StreamMessage<StreamChatGenerics>,\n mutes?: Mute<StreamChatGenerics>[],\n) => {\n if (!mutes || !message) return false;\n\n const userMuted = mutes.filter((el) => el.target.id === message.user?.id);\n return !!userMuted.length;\n};\n\nexport const MESSAGE_ACTIONS = {\n delete: 'delete',\n edit: 'edit',\n flag: 'flag',\n markUnread: 'markUnread',\n mute: 'mute',\n pin: 'pin',\n quote: 'quote',\n react: 'react',\n reply: 'reply',\n};\n\nexport type MessageActionsArray<T extends string = string> = Array<\n keyof typeof MESSAGE_ACTIONS | T\n>;\n\n// @deprecated in favor of `channelCapabilities` - TODO: remove in next major release\nexport const defaultPinPermissions: PinPermissions = {\n commerce: {\n admin: true,\n anonymous: false,\n channel_member: false,\n channel_moderator: true,\n guest: false,\n member: false,\n moderator: true,\n owner: true,\n user: false,\n },\n gaming: {\n admin: true,\n anonymous: false,\n channel_member: false,\n channel_moderator: true,\n guest: false,\n member: false,\n moderator: true,\n owner: false,\n user: false,\n },\n livestream: {\n admin: true,\n anonymous: false,\n channel_member: false,\n channel_moderator: true,\n guest: false,\n member: false,\n moderator: true,\n owner: true,\n user: false,\n },\n messaging: {\n admin: true,\n anonymous: false,\n channel_member: true,\n channel_moderator: true,\n guest: false,\n member: true,\n moderator: true,\n owner: true,\n user: false,\n },\n team: {\n admin: true,\n anonymous: false,\n channel_member: true,\n channel_moderator: true,\n guest: false,\n member: true,\n moderator: true,\n owner: true,\n user: false,\n },\n};\n\nexport type Capabilities = {\n canDelete?: boolean;\n canEdit?: boolean;\n canFlag?: boolean;\n canMarkUnread?: boolean;\n canMute?: boolean;\n canPin?: boolean;\n canQuote?: boolean;\n canReact?: boolean;\n canReply?: boolean;\n};\n\nexport const getMessageActions = (\n actions: MessageActionsArray | boolean,\n {\n canDelete,\n canEdit,\n canFlag,\n canMarkUnread,\n canMute,\n canPin,\n canQuote,\n canReact,\n canReply,\n }: Capabilities,\n): MessageActionsArray => {\n const messageActionsAfterPermission: MessageActionsArray = [];\n let messageActions: MessageActionsArray = [];\n\n if (actions && typeof actions === 'boolean') {\n // If value of actions is true, then populate all the possible values\n messageActions = Object.keys(MESSAGE_ACTIONS);\n } else if (actions && actions.length > 0) {\n messageActions = [...actions];\n } else {\n return [];\n }\n\n if (canDelete && messageActions.indexOf(MESSAGE_ACTIONS.delete) > -1) {\n messageActionsAfterPermission.push(MESSAGE_ACTIONS.delete);\n }\n\n if (canEdit && messageActions.indexOf(MESSAGE_ACTIONS.edit) > -1) {\n messageActionsAfterPermission.push(MESSAGE_ACTIONS.edit);\n }\n\n if (canFlag && messageActions.indexOf(MESSAGE_ACTIONS.flag) > -1) {\n messageActionsAfterPermission.push(MESSAGE_ACTIONS.flag);\n }\n\n if (canMarkUnread && messageActions.indexOf(MESSAGE_ACTIONS.markUnread) > -1) {\n messageActionsAfterPermission.push(MESSAGE_ACTIONS.markUnread);\n }\n\n if (canMute && messageActions.indexOf(MESSAGE_ACTIONS.mute) > -1) {\n messageActionsAfterPermission.push(MESSAGE_ACTIONS.mute);\n }\n\n if (canPin && messageActions.indexOf(MESSAGE_ACTIONS.pin) > -1) {\n messageActionsAfterPermission.push(MESSAGE_ACTIONS.pin);\n }\n\n if (canQuote && messageActions.indexOf(MESSAGE_ACTIONS.quote) > -1) {\n messageActionsAfterPermission.push(MESSAGE_ACTIONS.quote);\n }\n\n if (canReact && messageActions.indexOf(MESSAGE_ACTIONS.react) > -1) {\n messageActionsAfterPermission.push(MESSAGE_ACTIONS.react);\n }\n\n if (canReply && messageActions.indexOf(MESSAGE_ACTIONS.reply) > -1) {\n messageActionsAfterPermission.push(MESSAGE_ACTIONS.reply);\n }\n\n return messageActionsAfterPermission;\n};\n\nexport const ACTIONS_NOT_WORKING_IN_THREAD = [\n MESSAGE_ACTIONS.pin,\n MESSAGE_ACTIONS.reply,\n MESSAGE_ACTIONS.markUnread,\n];\n\n/**\n * @deprecated use `shouldRenderMessageActions` instead\n */\nexport const showMessageActionsBox = (\n actions: MessageActionsArray,\n inThread?: boolean | undefined,\n) => shouldRenderMessageActions({ inThread, messageActions: actions });\n\nexport const shouldRenderMessageActions = <\n SCG extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>({\n customMessageActions,\n CustomMessageActionsList,\n inThread,\n messageActions,\n}: {\n messageActions: MessageActionsArray;\n customMessageActions?: CustomMessageActions<SCG>;\n CustomMessageActionsList?: ComponentContextValue<SCG>['CustomMessageActionsList'];\n inThread?: boolean;\n}) => {\n if (\n typeof CustomMessageActionsList !== 'undefined' ||\n typeof customMessageActions !== 'undefined'\n )\n return true;\n\n if (!messageActions.length) return false;\n\n if (\n inThread &&\n messageActions.filter((action) => !ACTIONS_NOT_WORKING_IN_THREAD.includes(action)).length === 0\n ) {\n return false;\n }\n\n if (\n messageActions.length === 1 &&\n (messageActions.includes(MESSAGE_ACTIONS.react) ||\n messageActions.includes(MESSAGE_ACTIONS.reply))\n ) {\n return false;\n }\n\n if (\n messageActions.length === 2 &&\n messageActions.includes(MESSAGE_ACTIONS.react) &&\n messageActions.includes(MESSAGE_ACTIONS.reply)\n ) {\n return false;\n }\n\n return true;\n};\n\nfunction areMessagesEqual<\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>(\n prevMessage: StreamMessage<StreamChatGenerics>,\n nextMessage: StreamMessage<StreamChatGenerics>,\n): boolean {\n return (\n prevMessage.deleted_at === nextMessage.deleted_at &&\n prevMessage.latest_reactions?.length === nextMessage.latest_reactions?.length &&\n prevMessage.own_reactions?.length === nextMessage.own_reactions?.length &&\n prevMessage.pinned === nextMessage.pinned &&\n prevMessage.reply_count === nextMessage.reply_count &&\n prevMessage.status === nextMessage.status &&\n prevMessage.text === nextMessage.text &&\n prevMessage.type === nextMessage.type &&\n prevMessage.updated_at === nextMessage.updated_at &&\n prevMessage.user?.updated_at === nextMessage.user?.updated_at &&\n Boolean(prevMessage.quoted_message) === Boolean(nextMessage.quoted_message) &&\n (!prevMessage.quoted_message ||\n areMessagesEqual(\n prevMessage.quoted_message as StreamMessage<StreamChatGenerics>,\n nextMessage.quoted_message as StreamMessage<StreamChatGenerics>,\n ))\n );\n}\n\nexport const areMessagePropsEqual = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>(\n prevProps: MessageProps<StreamChatGenerics> & {\n mutes?: Mute<StreamChatGenerics>[];\n showDetailedReactions?: boolean;\n },\n nextProps: MessageProps<StreamChatGenerics> & {\n mutes?: Mute<StreamChatGenerics>[];\n showDetailedReactions?: boolean;\n },\n) => {\n const { message: prevMessage, Message: prevMessageUI } = prevProps;\n const { message: nextMessage, Message: nextMessageUI } = nextProps;\n\n if (prevMessageUI !== nextMessageUI) return false;\n if (prevProps.endOfGroup !== nextProps.endOfGroup) return false;\n\n if (nextProps.showDetailedReactions !== prevProps.showDetailedReactions) {\n return false;\n }\n\n if (nextProps.closeReactionSelectorOnClick !== prevProps.closeReactionSelectorOnClick) {\n return false;\n }\n\n const messagesAreEqual = areMessagesEqual(prevMessage, nextMessage);\n if (!messagesAreEqual) return false;\n\n const deepEqualProps =\n deepequal(nextProps.messageActions, prevProps.messageActions) &&\n deepequal(nextProps.readBy, prevProps.readBy) &&\n deepequal(nextProps.highlighted, prevProps.highlighted) &&\n deepequal(nextProps.groupStyles, prevProps.groupStyles) && // last 3 messages can have different group styles\n deepequal(nextProps.mutes, prevProps.mutes) &&\n deepequal(nextProps.lastReceivedId, prevProps.lastReceivedId);\n\n if (!deepEqualProps) return false;\n\n return (\n prevProps.messageListRect === nextProps.messageListRect // MessageList wrapper layout changes\n );\n};\n\nexport const areMessageUIPropsEqual = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>(\n prevProps: MessageContextValue<StreamChatGenerics> & {\n showDetailedReactions?: boolean;\n },\n nextProps: MessageContextValue<StreamChatGenerics> & {\n showDetailedReactions?: boolean;\n },\n) => {\n const { lastReceivedId: prevLastReceivedId, message: prevMessage } = prevProps;\n const { lastReceivedId: nextLastReceivedId, message: nextMessage } = nextProps;\n\n if (prevProps.editing !== nextProps.editing) return false;\n if (prevProps.highlighted !== nextProps.highlighted) return false;\n if (prevProps.endOfGroup !== nextProps.endOfGroup) return false;\n if (prevProps.mutes?.length !== nextProps.mutes?.length) return false;\n if (prevProps.readBy?.length !== nextProps.readBy?.length) return false;\n if (prevProps.groupStyles !== nextProps.groupStyles) return false;\n\n if (prevProps.showDetailedReactions !== nextProps.showDetailedReactions) {\n return false;\n }\n\n if (\n (prevMessage.id === prevLastReceivedId || prevMessage.id === nextLastReceivedId) &&\n prevLastReceivedId !== nextLastReceivedId\n ) {\n return false;\n }\n\n return areMessagesEqual(prevMessage, nextMessage);\n};\n\nexport const messageHasReactions = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>(\n message?: StreamMessage<StreamChatGenerics>,\n) => Object.values(message?.reaction_groups ?? {}).some(({ count }) => count > 0);\n\nexport const messageHasAttachments = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>(\n message?: StreamMessage<StreamChatGenerics>,\n) => !!message?.attachments && !!message.attachments.length;\n\nexport const getImages = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>(\n message?: MessageResponse<StreamChatGenerics>,\n) => {\n if (!message?.attachments) {\n return [];\n }\n return message.attachments.filter((item) => item.type === 'image');\n};\n\nexport const getNonImageAttachments = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>(\n message?: MessageResponse<StreamChatGenerics>,\n) => {\n if (!message?.attachments) {\n return [];\n }\n return message.attachments.filter((item) => item.type !== 'image');\n};\n\nexport interface TooltipUsernameMapper {\n <StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics>(\n user: UserResponse<StreamChatGenerics>,\n ): string;\n}\n\n/**\n * Default Tooltip Username mapper implementation.\n *\n * @param user the user.\n */\nexport const mapToUserNameOrId: TooltipUsernameMapper = (user) => user.name || user.id;\n\nexport const getReadByTooltipText = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>(\n users: UserResponse<StreamChatGenerics>[],\n t: TFunction,\n client: StreamChat<StreamChatGenerics>,\n tooltipUserNameMapper: TooltipUsernameMapper,\n) => {\n let outStr = '';\n\n if (!t) {\n throw new Error('getReadByTooltipText was called, but translation function is not available');\n }\n\n if (!tooltipUserNameMapper) {\n throw new Error(\n 'getReadByTooltipText was called, but tooltipUserNameMapper function is not available',\n );\n }\n // first filter out client user, so restLength won't count it\n const otherUsers = users\n .filter((item) => item && client?.user && item.id !== client.user.id)\n .map(tooltipUserNameMapper);\n\n const slicedArr = otherUsers.slice(0, 5);\n const restLength = otherUsers.length - slicedArr.length;\n\n if (slicedArr.length === 1) {\n outStr = `${slicedArr[0]} `;\n } else if (slicedArr.length === 2) {\n // joins all with \"and\" but =no commas\n // example: \"bob and sam\"\n outStr = t('{{ firstUser }} and {{ secondUser }}', {\n firstUser: slicedArr[0],\n secondUser: slicedArr[1],\n });\n } else if (slicedArr.length > 2) {\n // joins all with commas, but last one gets \", and\" (oxford comma!)\n // example: \"bob, joe, sam and 4 more\"\n if (restLength === 0) {\n // mutate slicedArr to remove last user to display it separately\n const lastUser = slicedArr.splice(slicedArr.length - 1, 1);\n outStr = t('{{ commaSeparatedUsers }}, and {{ lastUser }}', {\n commaSeparatedUsers: slicedArr.join(', '),\n lastUser,\n });\n } else {\n outStr = t('{{ commaSeparatedUsers }} and {{ moreCount }} more', {\n commaSeparatedUsers: slicedArr.join(', '),\n moreCount: restLength,\n });\n }\n }\n\n return outStr;\n};\n\nexport const isOnlyEmojis = (text?: string) => {\n if (!text) return false;\n\n const noEmojis = text.replace(emojiRegex(), '');\n const noSpace = noEmojis.replace(/[\\s\\n]/gm, '');\n\n return !noSpace;\n};\n\nexport const isMessageBounced = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>(\n message: Pick<StreamMessage<StreamChatGenerics>, 'type' | 'moderation' | 'moderation_details'>,\n) =>\n message.type === 'error' &&\n (message.moderation_details?.action === 'MESSAGE_RESPONSE_ACTION_BOUNCE' ||\n message.moderation?.action === 'bounce');\n\nexport const isMessageEdited = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>(\n message: Pick<StreamMessage<StreamChatGenerics>, 'message_text_updated_at'>,\n) => !!message.message_text_updated_at;\n", "import { StreamMessage, useChannelStateContext } from '../../../context/ChannelStateContext';\nimport { useChatContext } from '../../../context/ChatContext';\n\nimport type { DefaultStreamChatGenerics } from '../../../types/types';\n\nexport const useUserRole = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>(\n message: StreamMessage<StreamChatGenerics>,\n onlySenderCanEdit?: boolean,\n disableQuotedMessages?: boolean,\n) => {\n const { channel, channelCapabilities = {} } = useChannelStateContext<StreamChatGenerics>(\n 'useUserRole',\n );\n const { client } = useChatContext<StreamChatGenerics>('useUserRole');\n\n /**\n * @deprecated as it relies on `membership.role` check which is already deprecated and shouldn't be used anymore.\n * `isAdmin` will be removed in future release. See `channelCapabilities`.\n */\n const isAdmin = client.user?.role === 'admin' || channel.state.membership.role === 'admin';\n\n /**\n * @deprecated as it relies on `membership.role` check which is already deprecated and shouldn't be used anymore.\n * `isOwner` will be removed in future release. See `channelCapabilities`.\n */\n const isOwner = channel.state.membership.role === 'owner';\n\n /**\n * @deprecated as it relies on `membership.role` check which is already deprecated and shouldn't be used anymore.\n * `isModerator` will be removed in future release. See `channelCapabilities`.\n */\n const isModerator =\n client.user?.role === 'channel_moderator' ||\n channel.state.membership.role === 'channel_moderator' ||\n channel.state.membership.role === 'moderator' ||\n channel.state.membership.is_moderator === true ||\n channel.state.membership.channel_role === 'channel_moderator';\n\n const isMyMessage = client.userID === message.user?.id;\n\n const canEdit =\n !message.poll &&\n ((!onlySenderCanEdit && channelCapabilities['update-any-message']) ||\n (isMyMessage && channelCapabilities['update-own-message']));\n\n const canDelete =\n channelCapabilities['delete-any-message'] ||\n (isMyMessage && channelCapabilities['delete-own-message']);\n\n const canFlag = !isMyMessage && channelCapabilities['flag-message'];\n const canMarkUnread = channelCapabilities['read-events'];\n const canMute = !isMyMessage && channelCapabilities['mute-channel'];\n const canQuote = !disableQuotedMessages && channelCapabilities['quote-message'];\n const canReact = channelCapabilities['send-reaction'];\n const canReply = channelCapabilities['send-reply'];\n\n return {\n canDelete,\n canEdit,\n canFlag,\n canMarkUnread,\n canMute,\n canQuote,\n canReact,\n canReply,\n isAdmin,\n isModerator,\n isMyMessage,\n isOwner,\n };\n};\n", "import React from 'react';\n\nimport type { PinIndicatorProps } from './types';\n\nimport type { DefaultStreamChatGenerics, IconProps } from '../../types/types';\n\nexport const ActionsIcon = ({ className = '' }: IconProps) => (\n <svg\n className={className}\n height='4'\n viewBox='0 0 11 4'\n width='11'\n xmlns='http://www.w3.org/2000/svg'\n >\n <path\n d='M1.5 3a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm4 0a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm4 0a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3z'\n fillRule='nonzero'\n />\n </svg>\n);\n\nexport const ReactionIcon = ({ className = '' }: IconProps) => (\n <svg\n className={className}\n height='12'\n viewBox='0 0 12 12'\n width='12'\n xmlns='http://www.w3.org/2000/svg'\n >\n <g clipRule='evenodd' fillRule='evenodd'>\n <path d='M6 1.2C3.3 1.2 1.2 3.3 1.2 6c0 2.7 2.1 4.8 4.8 4.8 2.7 0 4.8-2.1 4.8-4.8 0-2.7-2.1-4.8-4.8-4.8zM0 6c0-3.3 2.7-6 6-6s6 2.7 6 6-2.7 6-6 6-6-2.7-6-6z' />\n <path d='M5.4 4.5c0 .5-.4.9-.9.9s-.9-.4-.9-.9.4-.9.9-.9.9.4.9.9zM8.4 4.5c0 .5-.4.9-.9.9s-.9-.4-.9-.9.4-.9.9-.9.9.4.9.9zM3.3 6.7c.3-.2.6-.1.8.1.3.4.8.9 1.5 1 .6.2 1.4.1 2.4-1 .2-.2.6-.3.8 0 .2.2.3.6 0 .8-1.1 1.3-2.4 1.7-3.5 1.5-1-.2-1.8-.9-2.2-1.5-.2-.3-.1-.7.2-.9z' />\n </g>\n </svg>\n);\n\nexport const ThreadIcon = ({ className = '' }: IconProps) => (\n <svg className={className} height='10' width='14' xmlns='http://www.w3.org/2000/svg'>\n <path\n d='M8.516 3c4.78 0 4.972 6.5 4.972 6.5-1.6-2.906-2.847-3.184-4.972-3.184v2.872L3.772 4.994 8.516.5V3zM.484 5l4.5-4.237v1.78L2.416 5l2.568 2.125v1.828L.484 5z'\n fillRule='evenodd'\n />\n </svg>\n);\n\nexport const PinIcon = () => (\n <svg height='13' viewBox='0 0 14 13' width='14' xmlns='http://www.w3.org/2000/svg'>\n <path\n d='M13.3518 6.686L6.75251 0.0866699L5.80984 1.02867L6.75318 1.972V1.97334L3.45318 5.272L3.45251 5.27334L2.50984 4.32934L1.56718 5.27267L4.39584 8.10067L0.624512 11.8713L1.56718 12.814L5.33851 9.04334L8.16718 11.8713L9.10984 10.9293L8.16718 9.986L11.4672 6.686L12.4098 7.62867L13.3518 6.686ZM7.22451 9.04267L7.22385 9.04334L4.39584 6.21467L7.69518 2.91467L10.5232 5.74267L7.22451 9.04267Z'\n fillRule='evenodd'\n />\n </svg>\n);\n\nexport const PinIndicator = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>({\n message,\n t,\n}: PinIndicatorProps<StreamChatGenerics>) => {\n if (!message || !t) return null;\n\n return (\n <div style={{ alignItems: 'center', display: 'flex' }}>\n <PinIcon />\n <div\n style={{\n fontSize: '14px',\n marginBottom: '0',\n marginLeft: '8px',\n marginTop: '0',\n }}\n >\n {message.pinned_by\n ? `${t<string>('Pinned by')} ${message.pinned_by?.name || message.pinned_by?.id}`\n : t<string>('Message pinned')}\n </div>\n </div>\n );\n};\n\nexport const MessageDeliveredIcon = () => (\n <svg\n data-testid='delivered-icon'\n fill='none'\n height='24'\n viewBox='0 0 24 24'\n width='24'\n xmlns='http://www.w3.org/2000/svg'\n >\n <path\n clipRule='evenodd'\n d='M8.9999 16.2L4.7999 12L3.3999 13.4L8.9999 19L20.9999 6.99998L19.5999 5.59998L8.9999 16.2Z'\n fill='black'\n fillRule='evenodd'\n />\n </svg>\n);\n\nexport const MessageErrorIcon = () => (\n <div className='str-chat__message-error-icon'>\n <svg\n data-testid='error'\n fill='none'\n height='24'\n viewBox='0 0 24 24'\n width='24'\n xmlns='http://www.w3.org/2000/svg'\n >\n <path\n d='M12 2C6.48 2 2 6.48 2 12C2 17.52 6.48 22 12 22C17.52 22 22 17.52 22 12C22 6.48 17.52 2 12 2Z'\n fill='black'\n id='background'\n />\n <path d='M13 17H11V15H13V17ZM13 13H11V7H13V13Z' fill='white' />\n </svg>\n </div>\n);\n", "import clsx from 'clsx';\nimport React, { ElementRef, PropsWithChildren, useCallback, useRef } from 'react';\n\nimport { MessageActionsBox } from './MessageActionsBox';\n\nimport { DialogAnchor, useDialog, useDialogIsOpen } from '../Dialog';\nimport { ActionsIcon as DefaultActionsIcon } from '../Message/icons';\nimport { isUserMuted, shouldRenderMessageActions } from '../Message/utils';\n\nimport { useChatContext } from '../../context/ChatContext';\nimport { MessageContextValue, useMessageContext } from '../../context/MessageContext';\nimport { useComponentContext, useTranslationContext } from '../../context';\n\nimport type { DefaultStreamChatGenerics, IconProps } from '../../types/types';\n\ntype MessageContextPropsToPick =\n | 'getMessageActions'\n | 'handleDelete'\n | 'handleFlag'\n | 'handleMarkUnread'\n | 'handleMute'\n | 'handlePin'\n | 'message';\n\nexport type MessageActionsProps<\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n> = Partial<Pick<MessageContextValue<StreamChatGenerics>, MessageContextPropsToPick>> & {\n /* Custom component rendering the icon used in message actions button. This button invokes the message actions menu. */\n ActionsIcon?: React.ComponentType<IconProps>;\n /* Custom CSS class to be added to the `div` wrapping the component */\n customWrapperClass?: string;\n /* If true, renders the wrapper component as a `span`, not a `div` */\n inline?: boolean;\n /* Function that returns whether the message was sent by the connected user */\n mine?: () => boolean;\n};\n\nexport const MessageActions = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>(\n props: MessageActionsProps<StreamChatGenerics>,\n) => {\n const {\n ActionsIcon = DefaultActionsIcon,\n customWrapperClass = '',\n getMessageActions: propGetMessageActions,\n handleDelete: propHandleDelete,\n handleFlag: propHandleFlag,\n handleMarkUnread: propHandleMarkUnread,\n handleMute: propHandleMute,\n handlePin: propHandlePin,\n inline,\n message: propMessage,\n mine,\n } = props;\n\n const { mutes } = useChatContext<StreamChatGenerics>('MessageActions');\n\n const {\n customMessageActions,\n getMessageActions: contextGetMessageActions,\n handleDelete: contextHandleDelete,\n handleFlag: contextHandleFlag,\n handleMarkUnread: contextHandleMarkUnread,\n handleMute: contextHandleMute,\n handlePin: contextHandlePin,\n isMyMessage,\n message: contextMessage,\n setEditingState,\n threadList,\n } = useMessageContext<StreamChatGenerics>('MessageActions');\n\n const { CustomMessageActionsList } = useComponentContext<StreamChatGenerics>('MessageActions');\n\n const { t } = useTranslationContext('MessageActions');\n\n const getMessageActions = propGetMessageActions || contextGetMessageActions;\n const handleDelete = propHandleDelete || contextHandleDelete;\n const handleFlag = propHandleFlag || contextHandleFlag;\n const handleMarkUnread = propHandleMarkUnread || contextHandleMarkUnread;\n const handleMute = propHandleMute || contextHandleMute;\n const handlePin = propHandlePin || contextHandlePin;\n const message = propMessage || contextMessage;\n const isMine = mine ? mine() : isMyMessage();\n\n const isMuted = useCallback(() => isUserMuted(message, mutes), [message, mutes]);\n\n const dialogId = `message-actions--${message.id}`;\n const dialog = useDialog({ id: dialogId });\n const dialogIsOpen = useDialogIsOpen(dialogId);\n\n const messageActions = getMessageActions();\n\n const renderMessageActions = shouldRenderMessageActions<StreamChatGenerics>({\n customMessageActions,\n CustomMessageActionsList,\n inThread: threadList,\n messageActions,\n });\n\n const actionsBoxButtonRef = useRef<ElementRef<'button'>>(null);\n\n if (!renderMessageActions) return null;\n\n return (\n <MessageActionsWrapper\n customWrapperClass={customWrapperClass}\n inline={inline}\n toggleOpen={dialog?.toggle}\n >\n <DialogAnchor\n id={dialogId}\n placement={isMine ? 'top-end' : 'top-start'}\n referenceElement={actionsBoxButtonRef.current}\n trapFocus\n >\n <MessageActionsBox\n getMessageActions={getMessageActions}\n handleDelete={handleDelete}\n handleEdit={setEditingState}\n handleFlag={handleFlag}\n handleMarkUnread={handleMarkUnread}\n handleMute={handleMute}\n handlePin={handlePin}\n isUserMuted={isMuted}\n mine={isMine}\n open={dialogIsOpen}\n />\n </DialogAnchor>\n <button\n aria-expanded={dialogIsOpen}\n aria-haspopup='true'\n aria-label={t('aria/Open Message Actions Menu')}\n className='str-chat__message-actions-box-button'\n data-testid='message-actions-toggle-button'\n ref={actionsBoxButtonRef}\n >\n <ActionsIcon className='str-chat__message-action-icon' />\n </button>\n </MessageActionsWrapper>\n );\n};\n\nexport type MessageActionsWrapperProps = {\n customWrapperClass?: string;\n inline?: boolean;\n toggleOpen?: () => void;\n};\n\nexport const MessageActionsWrapper = (props: PropsWithChildren<MessageActionsWrapperProps>) => {\n const { children, customWrapperClass, inline, toggleOpen } = props;\n\n const defaultWrapperClass = clsx(\n 'str-chat__message-simple__actions__action',\n 'str-chat__message-simple__actions__action--options',\n 'str-chat__message-actions-container',\n );\n\n const wrapperProps = {\n className: customWrapperClass || defaultWrapperClass,\n 'data-testid': 'message-actions',\n onClick: toggleOpen,\n };\n\n if (inline) return <span {...wrapperProps}>{children}</span>;\n\n return <div {...wrapperProps}>{children}</div>;\n};\n", "import clsx from 'clsx';\nimport { Placement } from '@popperjs/core';\nimport React, { ComponentProps, PropsWithChildren, useEffect, useState } from 'react';\nimport { FocusScope } from '@react-aria/focus';\nimport { usePopper } from 'react-popper';\nimport { DialogPortalEntry } from './DialogPortal';\nimport { useDialog, useDialogIsOpen } from './hooks';\n\nexport interface DialogAnchorOptions {\n open: boolean;\n placement: Placement;\n referenceElement: HTMLElement | null;\n}\n\nexport function useDialogAnchor<T extends HTMLElement>({\n open,\n placement,\n referenceElement,\n}: DialogAnchorOptions) {\n const [popperElement, setPopperElement] = useState<T | null>(null);\n const { attributes, styles, update } = usePopper(referenceElement, popperElement, {\n modifiers: [\n {\n name: 'eventListeners',\n options: {\n // It's not safe to update popper position on resize and scroll, since popper's\n // reference element might not be visible at the time.\n resize: false,\n scroll: false,\n },\n },\n ],\n placement,\n });\n\n useEffect(() => {\n if (open && popperElement) {\n // Since the popper's reference element might not be (and usually is not) visible\n // all the time, it's safer to force popper update before showing it.\n // update is non-null only if popperElement is non-null\n update?.();\n }\n }, [open, popperElement, update]);\n\n if (popperElement && !open) {\n setPopperElement(null);\n }\n\n return {\n attributes,\n setPopperElement,\n styles,\n };\n}\n\nexport type DialogAnchorProps = PropsWithChildren<Partial<DialogAnchorOptions>> & {\n id: string;\n focus?: boolean;\n trapFocus?: boolean;\n} & ComponentProps<'div'>;\n\nexport const DialogAnchor = ({\n children,\n className,\n focus = true,\n id,\n placement = 'auto',\n referenceElement = null,\n trapFocus,\n ...restDivProps\n}: DialogAnchorProps) => {\n const dialog = useDialog({ id });\n const open = useDialogIsOpen(id);\n const { attributes, setPopperElement, styles } = useDialogAnchor<HTMLDivElement>({\n open,\n placement,\n referenceElement,\n });\n\n useEffect(() => {\n if (!open) return;\n const hideOnEscape = (event: KeyboardEvent) => {\n if (event.key !== 'Escape') return;\n dialog?.close();\n };\n\n document.addEventListener('keyup', hideOnEscape);\n\n return () => {\n document.removeEventListener('keyup', hideOnEscape);\n };\n }, [dialog, open]);\n\n // prevent rendering the dialog contents if the dialog should not be open / shown\n if (!open) {\n return null;\n }\n\n return (\n <DialogPortalEntry dialogId={id}>\n <FocusScope autoFocus={focus} contain={trapFocus} restoreFocus>\n <div\n {...restDivProps}\n {...attributes.popper}\n className={clsx('str-chat__dialog-contents', className)}\n data-testid='str-chat__dialog-contents'\n ref={setPopperElement}\n style={styles.popper}\n tabIndex={0}\n >\n {children}\n </div>\n </FocusScope>\n </DialogPortalEntry>\n );\n};\n", "import React, { ElementRef, useRef } from 'react';\nimport { ReactionSelector as DefaultReactionSelector } from './ReactionSelector';\nimport { DialogAnchor, useDialog, useDialogIsOpen } from '../Dialog';\nimport { useComponentContext, useMessageContext, useTranslationContext } from '../../context';\nimport type { DefaultStreamChatGenerics } from '../../types';\nimport type { IconProps } from '../../types/types';\n\ntype ReactionSelectorWithButtonProps = {\n /* Custom component rendering the icon used in a button invoking reactions selector for a given message. */\n ReactionIcon: React.ComponentType<IconProps>;\n};\n\n/**\n * Internal convenience component - not to be exported. It just groups the button and the dialog anchor and thus prevents\n * cluttering the parent component.\n */\nexport const ReactionSelectorWithButton = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>({\n ReactionIcon,\n}: ReactionSelectorWithButtonProps) => {\n const { t } = useTranslationContext('ReactionSelectorWithButton');\n const { isMyMessage, message } = useMessageContext<StreamChatGenerics>('MessageOptions');\n const { ReactionSelector = DefaultReactionSelector } = useComponentContext('MessageOptions');\n const buttonRef = useRef<ElementRef<'button'>>(null);\n const dialogId = `reaction-selector--${message.id}`;\n const dialog = useDialog({ id: dialogId });\n const dialogIsOpen = useDialogIsOpen(dialogId);\n return (\n <>\n <DialogAnchor\n id={dialogId}\n placement={isMyMessage() ? 'top-end' : 'top-start'}\n referenceElement={buttonRef.current}\n trapFocus\n >\n <ReactionSelector />\n </DialogAnchor>\n <button\n aria-expanded={dialogIsOpen}\n aria-label={t('aria/Open Reaction Selector')}\n className='str-chat__message-reactions-button'\n data-testid='message-reaction-action'\n onClick={() => dialog?.toggle()}\n ref={buttonRef}\n >\n <ReactionIcon className='str-chat__message-action-icon' />\n </button>\n </>\n );\n};\n", "import React, { useCallback, useEffect, useRef, useState } from 'react';\nimport clsx from 'clsx';\n\nimport { Avatar as DefaultAvatar } from '../Avatar';\nimport { useDialog } from '../Dialog';\nimport { defaultReactionOptions } from './reactionOptions';\nimport { isMutableRef } from './utils/utils';\n\nimport { useComponentContext } from '../../context/ComponentContext';\nimport { useMessageContext } from '../../context/MessageContext';\n\nimport type { ReactionGroupResponse, ReactionResponse } from 'stream-chat';\nimport type { AvatarProps } from '../Avatar';\nimport type { DefaultStreamChatGenerics } from '../../types/types';\nimport type { ReactionOptions } from './reactionOptions';\n\nexport type ReactionSelectorProps<\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n> = {\n /** Custom UI component to display user avatar, defaults to and accepts same props as: [Avatar](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Avatar/Avatar.tsx) */\n Avatar?: React.ElementType<AvatarProps>;\n /** If true, shows the user's avatar with the reaction */\n detailedView?: boolean;\n /** Function that adds/removes a reaction on a message (overrides the function stored in `MessageContext`) */\n handleReaction?: (reactionType: string, event: React.BaseSyntheticEvent) => Promise<void>;\n /** An array of the reaction objects to display in the list */\n latest_reactions?: ReactionResponse<StreamChatGenerics>[];\n /** An array of the own reaction objects to distinguish own reactions visually */\n own_reactions?: ReactionResponse<StreamChatGenerics>[];\n /**\n * An object that keeps track of the count of each type of reaction on a message\n * @deprecated This override value is no longer taken into account. Use `reaction_groups` to override reaction counts instead.\n * */\n reaction_counts?: Record<string, number>;\n /** An object containing summary for each reaction type on a message */\n reaction_groups?: Record<string, ReactionGroupResponse>;\n /**\n * @deprecated\n * A list of the currently supported reactions on a message\n * */\n reactionOptions?: ReactionOptions;\n /** If true, adds a CSS class that reverses the horizontal positioning of the selector */\n reverse?: boolean;\n};\n\nconst UnMemoizedReactionSelector = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>(\n props: ReactionSelectorProps<StreamChatGenerics>,\n) => {\n const {\n Avatar: propAvatar,\n detailedView = true,\n handleReaction: propHandleReaction,\n latest_reactions: propLatestReactions,\n own_reactions: propOwnReactions,\n reaction_groups: propReactionGroups,\n reactionOptions: propReactionOptions,\n reverse = false,\n } = props;\n\n const {\n Avatar: contextAvatar,\n reactionOptions: contextReactionOptions = defaultReactionOptions,\n } = useComponentContext<StreamChatGenerics>('ReactionSelector');\n const {\n closeReactionSelectorOnClick,\n handleReaction: contextHandleReaction,\n message,\n } = useMessageContext<StreamChatGenerics>('ReactionSelector');\n const dialogId = `reaction-selector--${message.id}`;\n const dialog = useDialog({ id: dialogId });\n const reactionOptions = propReactionOptions ?? contextReactionOptions;\n\n const Avatar = propAvatar || contextAvatar || DefaultAvatar;\n const handleReaction = propHandleReaction || contextHandleReaction;\n const latestReactions = propLatestReactions || message?.latest_reactions || [];\n const ownReactions = propOwnReactions || message?.own_reactions || [];\n const reactionGroups = propReactionGroups || message?.reaction_groups || {};\n\n const [tooltipReactionType, setTooltipReactionType] = useState<string | null>(null);\n const [tooltipPositions, setTooltipPositions] = useState<{\n arrow: number;\n tooltip: number;\n } | null>(null);\n\n const rootRef = useRef<HTMLDivElement | null>(null);\n const targetRef = useRef<HTMLDivElement | null>(null);\n const tooltipRef = useRef<HTMLDivElement | null>(null);\n\n const showTooltip = useCallback(\n (event: React.MouseEvent<HTMLDivElement>, reactionType: string) => {\n targetRef.current = event.currentTarget;\n setTooltipReactionType(reactionType);\n },\n [],\n );\n\n const hideTooltip = useCallback(() => {\n setTooltipReactionType(null);\n setTooltipPositions(null);\n }, []);\n\n useEffect(() => {\n if (!tooltipReactionType || !rootRef.current) return;\n const tooltip = tooltipRef.current?.getBoundingClientRect();\n const target = targetRef.current?.getBoundingClientRect();\n\n const container = isMutableRef(rootRef) ? rootRef.current?.getBoundingClientRect() : null;\n\n if (!tooltip || !target || !container) return;\n\n const tooltipPosition =\n tooltip.width === container.width || tooltip.x < container.x\n ? 0\n : target.left + target.width / 2 - container.left - tooltip.width / 2;\n\n const arrowPosition = target.x - tooltip.x + target.width / 2 - tooltipPosition;\n\n setTooltipPositions({\n arrow: arrowPosition,\n tooltip: tooltipPosition,\n });\n }, [tooltipReactionType, rootRef]);\n\n const getUsersPerReactionType = (type: string | null) =>\n latestReactions\n .map((reaction) => {\n if (reaction.type === type) {\n return reaction.user?.name || reaction.user?.id;\n }\n return null;\n })\n .filter(Boolean);\n\n const iHaveReactedWithReaction = (reactionType: string) =>\n ownReactions.find((reaction) => reaction.type === reactionType);\n\n const getLatestUserForReactionType = (type: string | null) =>\n latestReactions.find((reaction) => reaction.type === type && !!reaction.user)?.user ||\n undefined;\n\n return (\n <div\n className={clsx(\n 'str-chat__reaction-selector str-chat__message-reaction-selector str-chat-react__message-reaction-selector',\n {\n 'str-chat__reaction-selector--reverse': reverse,\n },\n )}\n data-testid='reaction-selector'\n ref={rootRef}\n >\n {!!tooltipReactionType && detailedView && (\n <div\n className='str-chat__reaction-selector-tooltip'\n ref={tooltipRef}\n style={{\n left: tooltipPositions?.tooltip,\n visibility: tooltipPositions ? 'visible' : 'hidden',\n }}\n >\n <div className='arrow' style={{ left: tooltipPositions?.arrow }} />\n {getUsersPerReactionType(tooltipReactionType)?.map((user, i, users) => (\n <span className='latest-user-username' key={`key-${i}-${user}`}>\n {`${user}${i < users.length - 1 ? ', ' : ''}`}\n </span>\n ))}\n </div>\n )}\n <ul className='str-chat__message-reactions-list str-chat__message-reactions-options'>\n {reactionOptions.map(({ Component, name: reactionName, type: reactionType }) => {\n const latestUser = getLatestUserForReactionType(reactionType);\n const count = reactionGroups[reactionType]?.count ?? 0;\n return (\n <li key={reactionType}>\n <button\n aria-label={`Select Reaction: ${reactionName || reactionType}`}\n className={clsx(\n 'str-chat__message-reactions-list-item str-chat__message-reactions-option',\n {\n 'str-chat__message-reactions-option-selected': iHaveReactedWithReaction(\n reactionType,\n ),\n },\n )}\n data-testid='select-reaction-button'\n data-text={reactionType}\n onClick={(event) => {\n handleReaction(reactionType, event);\n if (closeReactionSelectorOnClick) {\n dialog.close();\n }\n }}\n >\n {!!count && detailedView && (\n <div\n className='latest-user str-chat__message-reactions-last-user'\n onClick={hideTooltip}\n onMouseEnter={(e) => showTooltip(e, reactionType)}\n onMouseLeave={hideTooltip}\n >\n {latestUser ? (\n <Avatar\n image={latestUser.image}\n name={latestUser.name}\n size={20}\n user={latestUser}\n />\n ) : (\n <div className='latest-user-not-found' />\n )}\n </div>\n )}\n <span className='str-chat__message-reaction-emoji'>\n <Component />\n </span>\n {Boolean(count) && detailedView && (\n <span className='str-chat__message-reactions-list-item__count'>\n {count || ''}\n </span>\n )}\n </button>\n </li>\n );\n })}\n </ul>\n </div>\n );\n};\n\n/**\n * Component that allows a user to select a reaction.\n */\nexport const ReactionSelector = React.memo(\n UnMemoizedReactionSelector,\n) as typeof UnMemoizedReactionSelector;\n", "/* eslint-disable sort-keys */\n/* eslint-disable react/display-name */\nimport React from 'react';\n\nimport { StreamEmoji } from './StreamEmoji';\n\nexport type ReactionOptions = Array<{\n Component: React.ComponentType;\n type: string;\n name?: string;\n}>;\n\nexport const defaultReactionOptions: ReactionOptions = [\n { type: 'haha', Component: () => <StreamEmoji fallback='\uD83D\uDE02' type='haha' />, name: 'Joy' },\n { type: 'like', Component: () => <StreamEmoji fallback='\uD83D\uDC4D' type='like' />, name: 'Thumbs up' },\n { type: 'love', Component: () => <StreamEmoji fallback='\u2764\uFE0F' type='love' />, name: 'Heart' },\n { type: 'sad', Component: () => <StreamEmoji fallback='\uD83D\uDE14' type='sad' />, name: 'Sad' },\n { type: 'wow', Component: () => <StreamEmoji fallback='\uD83D\uDE32' type='wow' />, name: 'Astonished' },\n];\n", "import React from 'react';\n\nimport { SpriteImage, SpriteImageProps } from './SpriteImage';\n\nimport type { Readable } from '../../types/types';\n\nconst StreamSpriteEmojiPositions = {\n angry: [1, 1],\n haha: [1, 0],\n like: [0, 0],\n love: [1, 2],\n sad: [0, 1],\n wow: [0, 2],\n};\n\ntype StreamEmojiType = keyof typeof StreamSpriteEmojiPositions;\n\nconst STREAM_SPRITE_URL = 'https://getstream.imgix.net/images/emoji-sprite.png';\n\nexport const StreamEmoji = ({\n fallback,\n type,\n}: Readable<{ type: StreamEmojiType } & Pick<SpriteImageProps, 'fallback'>>) => {\n const position = StreamSpriteEmojiPositions[type] as [number, number];\n return (\n <SpriteImage\n columns={2}\n fallback={fallback}\n position={position}\n rows={3}\n spriteUrl={STREAM_SPRITE_URL}\n style={\n {\n '--str-chat__sprite-image-height': 'var(--str-chat__stream-emoji-size, 18px)',\n } as React.CSSProperties\n }\n />\n );\n};\n", "import React, { useEffect, useState } from 'react';\n\nimport { getImageDimensions } from './utils/utils';\n\nexport type SpriteImageProps = {\n columns: number;\n position: [number, number];\n rows: number;\n spriteUrl: string;\n fallback?: React.ReactNode;\n height?: number;\n style?: React.CSSProperties;\n width?: number;\n};\n\nexport const SpriteImage = ({\n columns,\n fallback,\n height,\n position,\n rows,\n spriteUrl,\n style,\n width,\n}: SpriteImageProps) => {\n const [[spriteWidth, spriteHeight], setSpriteDimensions] = useState([0, 0]);\n\n useEffect(() => {\n getImageDimensions(spriteUrl).then(setSpriteDimensions).catch(console.error);\n }, [spriteUrl]);\n\n const [x, y] = position;\n\n if (!spriteHeight || !spriteWidth) return <>{fallback}</>;\n\n return (\n <div\n data-testid='sprite-image'\n style={\n {\n ...style,\n '--str-chat__sprite-image-resize-ratio':\n 'var(--str-chat__sprite-image-resize-ratio-x, var(--str-chat__sprite-image-resize-ratio-y, 1))',\n '--str-chat__sprite-image-resize-ratio-x':\n 'calc(var(--str-chat__sprite-image-width) / var(--str-chat__sprite-item-width))',\n '--str-chat__sprite-image-resize-ratio-y':\n 'calc(var(--str-chat__sprite-image-height) / var(--str-chat__sprite-item-height))',\n '--str-chat__sprite-item-height': `${spriteHeight / rows}`,\n '--str-chat__sprite-item-width': `${spriteWidth / columns}`,\n ...(Number.isFinite(height) ? { '--str-chat__sprite-image-height': `${height}px` } : {}),\n ...(Number.isFinite(width) ? { '--str-chat__sprite-image-width': `${width}px` } : {}),\n backgroundImage: `url('${spriteUrl}')`,\n backgroundPosition: `${x * (100 / (columns - 1))}% ${y * (100 / (rows - 1))}%`,\n backgroundSize: `${columns * 100}% ${rows * 100}%`,\n height:\n 'var(--str-chat__sprite-image-height, calc(var(--str-chat__sprite-item-height) * var(--str-chat__sprite-image-resize-ratio)))',\n width:\n 'var(--str-chat__sprite-image-width, calc(var(--str-chat__sprite-item-width) * var(--str-chat__sprite-image-resize-ratio)))',\n } as React.CSSProperties\n }\n />\n );\n};\n", "import { ForwardedRef, MutableRefObject } from 'react';\n\nexport const isMutableRef = <T>(ref: ForwardedRef<T> | null): ref is MutableRefObject<T> => {\n if (ref) {\n return (ref as MutableRefObject<T>).current !== undefined;\n }\n return false;\n};\n\nexport const getImageDimensions = (source: string) =>\n new Promise<[number, number]>((resolve, reject) => {\n const image = new Image();\n\n image.addEventListener(\n 'load',\n () => {\n resolve([image.width, image.height]);\n },\n { once: true },\n );\n\n image.addEventListener('error', () => reject(`Couldn't load image from ${source}`), {\n once: true,\n });\n\n image.src = source;\n });\n", "import { useMemo } from 'react';\n\nimport { ACTIONS_NOT_WORKING_IN_THREAD, useUserRole } from '../../../components';\nimport { useMessageContext } from '../../../context';\n\nimport type { MessageActionSetItem } from '../MessageActions';\n\n/**\n * Base filter hook which covers actions of type `delete`, `edit`,\n * `flag`, `markUnread`, `mute`, `quote`, `react` and `reply`, whether\n * the rendered message is a reply (replies are limited to certain actions) and\n * whether the message has appropriate type and status.\n */\nexport const useBaseMessageActionSetFilter = (\n messageActionSet: MessageActionSetItem[],\n disable = false,\n) => {\n const { initialMessage: isInitialMessage, message } = useMessageContext();\n const {\n canDelete,\n canEdit,\n canFlag,\n canMarkUnread,\n canMute,\n canQuote,\n canReact,\n canReply,\n } = useUserRole(message);\n const isMessageThreadReply = typeof message.parent_id === 'string';\n\n return useMemo(() => {\n if (disable) return messageActionSet;\n\n // filter out all actions if any of these are true\n if (\n isInitialMessage || // not sure whether this thing even works anymore\n !message.type ||\n message.type === 'error' ||\n message.type === 'system' ||\n message.type === 'ephemeral' ||\n message.status === 'failed' ||\n message.status === 'sending'\n )\n return [];\n\n return messageActionSet.filter(({ type }: MessageActionSetItem) => {\n // filter out actions with types that do not work in thread\n if (ACTIONS_NOT_WORKING_IN_THREAD.includes(type) && isMessageThreadReply) return false;\n\n if (\n (type === 'delete' && !canDelete) ||\n (type === 'edit' && !canEdit) ||\n (type === 'flag' && !canFlag) ||\n (type === 'markUnread' && !canMarkUnread) ||\n (type === 'mute' && !canMute) ||\n (type === 'quote' && !canQuote) ||\n (type === 'react' && !canReact) ||\n (type === 'reply' && !canReply)\n )\n return false;\n\n return true;\n });\n }, [\n canDelete,\n canEdit,\n canFlag,\n canMarkUnread,\n canMute,\n canQuote,\n canReact,\n canReply,\n isInitialMessage,\n isMessageThreadReply,\n message.status,\n message.type,\n disable,\n messageActionSet,\n ]);\n};\n", "import { useMemo } from 'react';\n\nimport type { MessageActionSetItem } from '../MessageActions';\n\nexport const useSplitMessageActionSet = (messageActionSet: MessageActionSetItem[]) =>\n useMemo(() => {\n const quickActionSet: MessageActionSetItem[] = [];\n const dropdownActionSet: MessageActionSetItem[] = [];\n\n for (const action of messageActionSet) {\n if (action.placement === 'quick') quickActionSet.push(action);\n if (action.placement === 'dropdown') dropdownActionSet.push(action);\n }\n\n return { dropdownActionSet, quickActionSet };\n }, [messageActionSet]);\n", "/* eslint-disable sort-keys */\nimport React from 'react';\n\nimport { isUserMuted } from '../../components';\nimport { ReactionIcon as DefaultReactionIcon, ThreadIcon } from '../../components/Message/icons';\nimport { ReactionSelectorWithButton } from '../../components/Reactions/ReactionSelectorWithButton';\nimport {\n useChannelActionContext,\n useChatContext,\n useMessageContext,\n useTranslationContext,\n} from '../../context';\n\nimport type { ComponentPropsWithoutRef } from 'react';\n\nimport type { MessageActionSetItem } from './MessageActions';\n\nexport const DefaultDropdownActionButton = ({\n 'aria-selected': ariaSelected = 'false',\n children,\n className = 'str-chat__message-actions-list-item-button',\n role = 'option',\n ...rest\n}: ComponentPropsWithoutRef<'button'>) => (\n <button aria-selected={ariaSelected} className={className} role={role} {...rest}>\n {children}\n </button>\n);\n\nconst DefaultMessageActionComponents = {\n dropdown: {\n Quote() {\n const { setQuotedMessage } = useChannelActionContext();\n const { message } = useMessageContext();\n const { t } = useTranslationContext();\n\n const handleQuote = () => {\n setQuotedMessage(message);\n\n const elements = message.parent_id\n ? document.querySelectorAll('.str-chat__thread .str-chat__textarea__textarea')\n : document.getElementsByClassName('str-chat__textarea__textarea');\n const textarea = elements.item(0);\n\n if (textarea instanceof HTMLTextAreaElement) {\n textarea.focus();\n }\n };\n\n return (\n <DefaultDropdownActionButton onClick={handleQuote}>\n {t<string>('Quote')}\n </DefaultDropdownActionButton>\n );\n },\n Pin() {\n const { handlePin, message } = useMessageContext();\n const { t } = useTranslationContext();\n\n return (\n <DefaultDropdownActionButton onClick={handlePin}>\n {!message.pinned ? t<string>('Pin') : t<string>('Unpin')}\n </DefaultDropdownActionButton>\n );\n },\n MarkUnread() {\n const { handleMarkUnread } = useMessageContext();\n const { t } = useTranslationContext();\n\n return (\n <DefaultDropdownActionButton onClick={handleMarkUnread}>\n {t<string>('Mark as unread')}\n </DefaultDropdownActionButton>\n );\n },\n Flag() {\n const { handleFlag } = useMessageContext();\n const { t } = useTranslationContext();\n\n return (\n <DefaultDropdownActionButton onClick={handleFlag}>\n {t<string>('Flag')}\n </DefaultDropdownActionButton>\n );\n },\n Mute() {\n const { handleMute, message } = useMessageContext();\n const { mutes } = useChatContext();\n const { t } = useTranslationContext();\n\n return (\n <DefaultDropdownActionButton onClick={handleMute}>\n {isUserMuted(message, mutes) ? t<string>('Unmute') : t<string>('Mute')}\n </DefaultDropdownActionButton>\n );\n },\n Edit() {\n const { handleEdit } = useMessageContext();\n const { t } = useTranslationContext();\n\n return (\n <DefaultDropdownActionButton onClick={handleEdit}>\n {t<string>('Edit Message')}\n </DefaultDropdownActionButton>\n );\n },\n Delete() {\n const { handleDelete } = useMessageContext();\n const { t } = useTranslationContext();\n\n return (\n <DefaultDropdownActionButton onClick={handleDelete}>\n {t<string>('Delete')}\n </DefaultDropdownActionButton>\n );\n },\n },\n quick: {\n React() {\n return <ReactionSelectorWithButton ReactionIcon={DefaultReactionIcon} />;\n },\n Reply() {\n const { handleOpenThread } = useMessageContext();\n const { t } = useTranslationContext();\n\n return (\n <button\n aria-label={t('aria/Open Thread')}\n className='str-chat__message-reply-in-thread-button'\n data-testid='thread-action'\n onClick={handleOpenThread}\n >\n <ThreadIcon className='str-chat__message-action-icon' />\n </button>\n );\n },\n },\n};\n\nexport const defaultMessageActionSet: MessageActionSetItem[] = [\n // { placement: 'dropdown', type: 'block' },\n { Component: DefaultMessageActionComponents.quick.Reply, placement: 'quick', type: 'reply' },\n { Component: DefaultMessageActionComponents.quick.React, placement: 'quick', type: 'react' },\n {\n Component: DefaultMessageActionComponents.dropdown.Delete,\n placement: 'dropdown',\n type: 'delete',\n },\n { Component: DefaultMessageActionComponents.dropdown.Edit, placement: 'dropdown', type: 'edit' },\n { Component: DefaultMessageActionComponents.dropdown.Mute, placement: 'dropdown', type: 'mute' },\n { Component: DefaultMessageActionComponents.dropdown.Flag, placement: 'dropdown', type: 'flag' },\n { Component: DefaultMessageActionComponents.dropdown.Pin, placement: 'dropdown', type: 'pin' },\n {\n Component: DefaultMessageActionComponents.dropdown.Quote,\n placement: 'dropdown',\n type: 'quote',\n },\n {\n Component: DefaultMessageActionComponents.dropdown.MarkUnread,\n placement: 'dropdown',\n type: 'markUnread',\n },\n] as const;\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["export * from './MessageActions';\n", "/* eslint-disable sort-keys */\nimport clsx from 'clsx';\nimport React, { PropsWithChildren, useState } from 'react';\n\nimport { useChatContext, useMessageContext, useTranslationContext } from '../../context';\nimport { ActionsIcon } from '../../components/Message/icons';\nimport { DialogAnchor, useDialog, useDialogIsOpen } from '../../components/Dialog';\nimport { MessageActionsWrapper } from '../../components/MessageActions/MessageActions';\nimport { MESSAGE_ACTIONS } from '../../components';\n\nimport { useBaseMessageActionSetFilter, useSplitMessageActionSet } from './hooks';\nimport { defaultMessageActionSet } from './defaults';\n\nexport type MessageActionSetItem = {\n Component: React.ComponentType;\n placement: 'quick' | 'dropdown';\n type:\n | keyof typeof MESSAGE_ACTIONS\n // eslint-disable-next-line @typescript-eslint/ban-types\n | (string & {});\n};\n\nexport type MessageActionsProps = {\n disableBaseMessageActionSetFilter?: boolean;\n messageActionSet?: MessageActionSetItem[];\n};\n\n// TODO: allow passing down customWrapperClass\n/**\n * A new actions component to replace current `MessageOptions` component.\n * Exports from `stream-chat-react/experimental` __MIGHT__ change - use with caution\n * and follow release notes in case you notice unexpected behavior.\n */\nexport const MessageActions = ({\n disableBaseMessageActionSetFilter = false,\n messageActionSet = defaultMessageActionSet,\n}: MessageActionsProps) => {\n const { theme } = useChatContext();\n const { isMyMessage, message } = useMessageContext();\n const { t } = useTranslationContext();\n const [actionsBoxButtonElement, setActionsBoxButtonElement] = useState<HTMLButtonElement | null>(\n null,\n );\n\n const filteredMessageActionSet = useBaseMessageActionSetFilter(\n messageActionSet,\n disableBaseMessageActionSetFilter,\n );\n\n const { dropdownActionSet, quickActionSet } = useSplitMessageActionSet(filteredMessageActionSet);\n\n const dropdownDialogId = `message-actions--${message.id}`;\n const reactionSelectorDialogId = `reaction-selector--${message.id}`;\n const dialog = useDialog({ id: dropdownDialogId });\n const dropdownDialogIsOpen = useDialogIsOpen(dropdownDialogId);\n const reactionSelectorDialogIsOpen = useDialogIsOpen(reactionSelectorDialogId);\n\n // do not render anything if total action count is zero\n if (dropdownActionSet.length + quickActionSet.length === 0) {\n return null;\n }\n\n return (\n <div\n className={clsx(`str-chat__message-${theme}__actions str-chat__message-options`, {\n 'str-chat__message-options--active': dropdownDialogIsOpen || reactionSelectorDialogIsOpen,\n })}\n >\n {dropdownActionSet.length > 0 && (\n <MessageActionsWrapper inline={false} toggleOpen={dialog?.toggle}>\n <button\n aria-expanded={dropdownDialogIsOpen}\n aria-haspopup='true'\n aria-label={t('aria/Open Message Actions Menu')}\n className='str-chat__message-actions-box-button'\n data-testid='message-actions-toggle-button'\n ref={setActionsBoxButtonElement}\n >\n <ActionsIcon className='str-chat__message-action-icon' />\n </button>\n\n <DialogAnchor\n id={dropdownDialogId}\n placement={isMyMessage() ? 'top-end' : 'top-start'}\n referenceElement={actionsBoxButtonElement}\n trapFocus\n >\n <DropdownBox open={dropdownDialogIsOpen}>\n {dropdownActionSet.map(({ Component: DropdownActionComponent, type }) => (\n <DropdownActionComponent key={type} />\n ))}\n </DropdownBox>\n </DialogAnchor>\n </MessageActionsWrapper>\n )}\n {quickActionSet.map(({ Component: QuickActionComponent, type }) => (\n <QuickActionComponent key={type} />\n ))}\n </div>\n );\n};\n\nconst DropdownBox = ({ children, open }: PropsWithChildren<{ open: boolean }>) => {\n const { t } = useTranslationContext();\n return (\n <div\n className={clsx('str-chat__message-actions-box', {\n 'str-chat__message-actions-box--open': open,\n })}\n >\n <div\n aria-label={t('aria/Message Options')}\n className='str-chat__message-actions-list'\n role='listbox'\n >\n {children}\n </div>\n </div>\n );\n};\n", "import React, { PropsWithChildren, useContext } from 'react';\n\nimport type {\n APIErrorResponse,\n Attachment,\n ErrorFromResponse,\n Message,\n MessageResponse,\n UpdatedMessage,\n UpdateMessageAPIResponse,\n UserResponse,\n} from 'stream-chat';\n\nimport type { StreamMessage } from './ChannelStateContext';\n\nimport type { ChannelStateReducerAction } from '../components/Channel/channelState';\nimport type { CustomMentionHandler } from '../components/Message/hooks/useMentionsHandler';\n\nimport type {\n ChannelUnreadUiState,\n DefaultStreamChatGenerics,\n SendMessageOptions,\n UnknownType,\n UpdateMessageOptions,\n} from '../types/types';\n\nexport type MarkReadWrapperOptions = {\n /**\n * Signal, whether the `channelUnreadUiState` should be updated.\n * By default, the local state update is prevented when the Channel component is mounted.\n * This is in order to keep the UI indicating the original unread state, when the user opens a channel.\n */\n updateChannelUiUnreadState?: boolean;\n};\n\nexport type MessageAttachments<\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n> = Array<Attachment<StreamChatGenerics>>;\n\nexport type MessageToSend<\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n> = {\n attachments?: MessageAttachments<StreamChatGenerics>;\n error?: ErrorFromResponse<APIErrorResponse>;\n errorStatusCode?: number;\n id?: string;\n mentioned_users?: UserResponse<StreamChatGenerics>[];\n parent?: StreamMessage<StreamChatGenerics>;\n parent_id?: string;\n status?: string;\n text?: string;\n};\n\nexport type RetrySendMessage<\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n> = (message: StreamMessage<StreamChatGenerics>) => Promise<void>;\n\nexport type ChannelActionContextValue<\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n> = {\n addNotification: (text: string, type: 'success' | 'error') => void;\n closeThread: (event?: React.BaseSyntheticEvent) => void;\n deleteMessage: (\n message: StreamMessage<StreamChatGenerics>,\n ) => Promise<MessageResponse<StreamChatGenerics>>;\n dispatch: React.Dispatch<ChannelStateReducerAction<StreamChatGenerics>>;\n editMessage: (\n message: UpdatedMessage<StreamChatGenerics>,\n options?: UpdateMessageOptions,\n ) => Promise<UpdateMessageAPIResponse<StreamChatGenerics> | void>;\n jumpToFirstUnreadMessage: (\n queryMessageLimit?: number,\n highlightDuration?: number,\n ) => Promise<void>;\n jumpToLatestMessage: () => Promise<void>;\n jumpToMessage: (messageId: string, limit?: number, highlightDuration?: number) => Promise<void>;\n loadMore: (limit?: number) => Promise<number>;\n loadMoreNewer: (limit?: number) => Promise<number>;\n loadMoreThread: () => Promise<void>;\n markRead: (options?: MarkReadWrapperOptions) => void;\n onMentionsClick: CustomMentionHandler<StreamChatGenerics>;\n onMentionsHover: CustomMentionHandler<StreamChatGenerics>;\n openThread: (\n message: StreamMessage<StreamChatGenerics>,\n event?: React.BaseSyntheticEvent,\n ) => void;\n removeMessage: (message: StreamMessage<StreamChatGenerics>) => void;\n retrySendMessage: RetrySendMessage<StreamChatGenerics>;\n sendMessage: (\n message: MessageToSend<StreamChatGenerics>,\n customMessageData?: Partial<Message<StreamChatGenerics>>,\n options?: SendMessageOptions,\n ) => Promise<void>;\n setChannelUnreadUiState: React.Dispatch<React.SetStateAction<ChannelUnreadUiState | undefined>>;\n setQuotedMessage: React.Dispatch<\n React.SetStateAction<StreamMessage<StreamChatGenerics> | undefined>\n >;\n updateMessage: (message: StreamMessage<StreamChatGenerics>) => void;\n};\n\nexport const ChannelActionContext = React.createContext<ChannelActionContextValue | undefined>(\n undefined,\n);\n\nexport const ChannelActionProvider = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>({\n children,\n value,\n}: PropsWithChildren<{\n value: ChannelActionContextValue<StreamChatGenerics>;\n}>) => (\n <ChannelActionContext.Provider value={(value as unknown) as ChannelActionContextValue}>\n {children}\n </ChannelActionContext.Provider>\n);\n\nexport const useChannelActionContext = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>(\n componentName?: string,\n) => {\n const contextValue = useContext(ChannelActionContext);\n\n if (!contextValue) {\n console.warn(\n `The useChannelActionContext hook was called outside of the ChannelActionContext provider. Make sure this hook is called within a child of the Channel component. The errored call is located in the ${componentName} component.`,\n );\n\n return {} as ChannelActionContextValue<StreamChatGenerics>;\n }\n\n return (contextValue as unknown) as ChannelActionContextValue<StreamChatGenerics>;\n};\n\n/**\n * Typescript currently does not support partial inference, so if ChannelActionContext\n * typing is desired while using the HOC withChannelActionContext, the Props for the\n * wrapped component must be provided as the first generic.\n */\nexport const withChannelActionContext = <\n P extends UnknownType,\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>(\n Component: React.ComponentType<P>,\n) => {\n const WithChannelActionContextComponent = (\n props: Omit<P, keyof ChannelActionContextValue<StreamChatGenerics>>,\n ) => {\n const channelActionContext = useChannelActionContext<StreamChatGenerics>();\n\n return <Component {...(props as P)} {...channelActionContext} />;\n };\n\n WithChannelActionContextComponent.displayName = (\n Component.displayName ||\n Component.name ||\n 'Component'\n ).replace('Base', '');\n\n return WithChannelActionContextComponent;\n};\n", "import React, { PropsWithChildren, useContext } from 'react';\n\nimport type {\n Channel,\n ChannelConfigWithInfo,\n MessageResponse,\n Mute,\n ChannelState as StreamChannelState,\n} from 'stream-chat';\n\nimport type {\n ChannelUnreadUiState,\n DefaultStreamChatGenerics,\n GiphyVersions,\n ImageAttachmentSizeHandler,\n UnknownType,\n VideoAttachmentSizeHandler,\n} from '../types/types';\nimport type { URLEnrichmentConfig } from '../components/MessageInput/hooks/useLinkPreviews';\n\nexport type ChannelNotifications = Array<{\n id: string;\n text: string;\n type: 'success' | 'error';\n}>;\n\nexport type StreamMessage<\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n> =\n | ReturnType<StreamChannelState<StreamChatGenerics>['formatMessage']>\n | MessageResponse<StreamChatGenerics>;\n\nexport type ChannelState<\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n> = {\n suppressAutoscroll: boolean;\n error?: Error | null;\n hasMore?: boolean;\n hasMoreNewer?: boolean;\n highlightedMessageId?: string;\n loading?: boolean;\n loadingMore?: boolean;\n loadingMoreNewer?: boolean;\n members?: StreamChannelState<StreamChatGenerics>['members'];\n messages?: StreamMessage<StreamChatGenerics>[];\n pinnedMessages?: StreamMessage<StreamChatGenerics>[];\n quotedMessage?: StreamMessage<StreamChatGenerics>;\n read?: StreamChannelState<StreamChatGenerics>['read'];\n thread?: StreamMessage<StreamChatGenerics> | null;\n threadHasMore?: boolean;\n threadLoadingMore?: boolean;\n threadMessages?: StreamMessage<StreamChatGenerics>[];\n threadSuppressAutoscroll?: boolean;\n typing?: StreamChannelState<StreamChatGenerics>['typing'];\n watcherCount?: number;\n watchers?: StreamChannelState<StreamChatGenerics>['watchers'];\n};\n\nexport type ChannelStateContextValue<\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n> = Omit<ChannelState<StreamChatGenerics>, 'typing'> & {\n channel: Channel<StreamChatGenerics>;\n channelCapabilities: Record<string, boolean>;\n channelConfig: ChannelConfigWithInfo<StreamChatGenerics> | undefined;\n imageAttachmentSizeHandler: ImageAttachmentSizeHandler;\n multipleUploads: boolean;\n notifications: ChannelNotifications;\n shouldGenerateVideoThumbnail: boolean;\n videoAttachmentSizeHandler: VideoAttachmentSizeHandler;\n acceptedFiles?: string[];\n channelUnreadUiState?: ChannelUnreadUiState<StreamChatGenerics>;\n debounceURLEnrichmentMs?: URLEnrichmentConfig['debounceURLEnrichmentMs'];\n dragAndDropWindow?: boolean;\n enrichURLForPreview?: URLEnrichmentConfig['enrichURLForPreview'];\n findURLFn?: URLEnrichmentConfig['findURLFn'];\n giphyVersion?: GiphyVersions;\n maxNumberOfFiles?: number;\n mutes?: Array<Mute<StreamChatGenerics>>;\n onLinkPreviewDismissed?: URLEnrichmentConfig['onLinkPreviewDismissed'];\n watcher_count?: number;\n};\n\nexport const ChannelStateContext = React.createContext<ChannelStateContextValue | undefined>(\n undefined,\n);\n\nexport const ChannelStateProvider = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>({\n children,\n value,\n}: PropsWithChildren<{\n value: ChannelStateContextValue<StreamChatGenerics>;\n}>) => (\n <ChannelStateContext.Provider value={(value as unknown) as ChannelStateContextValue}>\n {children}\n </ChannelStateContext.Provider>\n);\n\nexport const useChannelStateContext = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>(\n componentName?: string,\n) => {\n const contextValue = useContext(ChannelStateContext);\n\n if (!contextValue) {\n console.warn(\n `The useChannelStateContext hook was called outside of the ChannelStateContext provider. Make sure this hook is called within a child of the Channel component. The errored call is located in the ${componentName} component.`,\n );\n\n return {} as ChannelStateContextValue<StreamChatGenerics>;\n }\n\n return (contextValue as unknown) as ChannelStateContextValue<StreamChatGenerics>;\n};\n\n/**\n * Typescript currently does not support partial inference, so if ChannelStateContext\n * typing is desired while using the HOC withChannelStateContext, the Props for the\n * wrapped component must be provided as the first generic.\n */\nexport const withChannelStateContext = <\n P extends UnknownType,\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>(\n Component: React.ComponentType<P>,\n) => {\n const WithChannelStateContextComponent = (\n props: Omit<P, keyof ChannelStateContextValue<StreamChatGenerics>>,\n ) => {\n const channelStateContext = useChannelStateContext<StreamChatGenerics>();\n\n return <Component {...(props as P)} {...channelStateContext} />;\n };\n\n WithChannelStateContextComponent.displayName = (\n Component.displayName ||\n Component.name ||\n 'Component'\n ).replace('Base', '');\n\n return WithChannelStateContextComponent;\n};\n", "import React, { PropsWithChildren, useContext } from 'react';\n\nimport type { AppSettingsAPIResponse, Channel, Mute } from 'stream-chat';\n\nimport { getDisplayName } from './utils/getDisplayName';\nimport type { ChatProps } from '../components/Chat/Chat';\nimport type { DefaultStreamChatGenerics, UnknownType } from '../types/types';\nimport type { ChannelsQueryState } from '../components/Chat/hooks/useChannelsQueryState';\n\ntype CSSClasses =\n | 'chat'\n | 'chatContainer'\n | 'channel'\n | 'channelList'\n | 'message'\n | 'messageList'\n | 'thread'\n | 'threadList'\n | 'virtualMessage'\n | 'virtualizedMessageList';\n\nexport type CustomClasses = Partial<Record<CSSClasses, string>>;\n\ntype ChannelCID = string; // e.g.: \"messaging:general\"\n\nexport type ChatContextValue<\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n> = {\n /**\n * Indicates, whether a channels query has been triggered within ChannelList by its channels pagination controller.\n */\n channelsQueryState: ChannelsQueryState;\n closeMobileNav: () => void;\n getAppSettings: () => Promise<AppSettingsAPIResponse<StreamChatGenerics>> | null;\n latestMessageDatesByChannels: Record<ChannelCID, Date>;\n mutes: Array<Mute<StreamChatGenerics>>;\n openMobileNav: () => void;\n /**\n * Sets active channel to be rendered within Channel component.\n * @param newChannel\n * @param watchers\n * @param event\n */\n setActiveChannel: (\n newChannel?: Channel<StreamChatGenerics>,\n watchers?: { limit?: number; offset?: number },\n event?: React.BaseSyntheticEvent,\n ) => void;\n useImageFlagEmojisOnWindows: boolean;\n /**\n * Active channel used to render the contents of the Channel component.\n */\n channel?: Channel<StreamChatGenerics>;\n /**\n * Object through which custom classes can be set for main container components of the SDK.\n */\n customClasses?: CustomClasses;\n navOpen?: boolean;\n} & Partial<Pick<ChatProps<StreamChatGenerics>, 'isMessageAIGenerated'>> &\n Required<Pick<ChatProps<StreamChatGenerics>, 'theme' | 'client'>>;\n\nexport const ChatContext = React.createContext<ChatContextValue | undefined>(undefined);\n\nexport const ChatProvider = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>({\n children,\n value,\n}: PropsWithChildren<{\n value: ChatContextValue<StreamChatGenerics>;\n}>) => (\n <ChatContext.Provider value={(value as unknown) as ChatContextValue}>\n {children}\n </ChatContext.Provider>\n);\n\nexport const useChatContext = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>(\n componentName?: string,\n) => {\n const contextValue = useContext(ChatContext);\n\n if (!contextValue) {\n console.warn(\n `The useChatContext hook was called outside of the ChatContext provider. Make sure this hook is called within a child of the Chat component. The errored call is located in the ${componentName} component.`,\n );\n\n return {} as ChatContextValue<StreamChatGenerics>;\n }\n\n return (contextValue as unknown) as ChatContextValue<StreamChatGenerics>;\n};\n\n/**\n * Typescript currently does not support partial inference so if ChatContext\n * typing is desired while using the HOC withChatContext the Props for the\n * wrapped component must be provided as the first generic.\n */\nexport const withChatContext = <\n P extends UnknownType,\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>(\n Component: React.ComponentType<P>,\n) => {\n const WithChatContextComponent = (props: Omit<P, keyof ChatContextValue<StreamChatGenerics>>) => {\n const chatContext = useChatContext<StreamChatGenerics>();\n\n return <Component {...(props as P)} {...chatContext} />;\n };\n WithChatContextComponent.displayName = `WithChatContext${getDisplayName(Component)}`;\n return WithChatContextComponent;\n};\n", "import React, { PropsWithChildren, useContext } from 'react';\n\nimport {\n AttachmentPreviewListProps,\n AttachmentProps,\n AvatarProps,\n BaseImageProps,\n ChannelPreviewActionButtonsProps,\n CooldownTimerProps,\n CustomMessageActionsListProps,\n DateSeparatorProps,\n EmojiSearchIndex,\n EmptyStateIndicatorProps,\n EventComponentProps,\n FixedHeightMessageProps,\n GiphyPreviewMessageProps,\n LinkPreviewListProps,\n LoadingIndicatorProps,\n MessageBouncePromptProps,\n MessageDeletedProps,\n MessageInputProps,\n MessageListNotificationsProps,\n MessageNotificationProps,\n MessageOptionsProps,\n MessageProps,\n MessageRepliesCountButtonProps,\n MessageStatusProps,\n MessageTimestampProps,\n MessageUIComponentProps,\n ModalGalleryProps,\n PinIndicatorProps,\n PollCreationDialogProps,\n PollOptionSelectorProps,\n QuotedMessagePreviewProps,\n ReactionOptions,\n ReactionSelectorProps,\n ReactionsListProps,\n RecordingPermissionDeniedNotificationProps,\n SendButtonProps,\n StartRecordingAudioButtonProps,\n StreamedMessageTextProps,\n SuggestionItemProps,\n SuggestionListProps,\n ThreadHeaderProps,\n ThreadListItemProps,\n ThreadListItemUIProps,\n TimestampProps,\n TypingIndicatorProps,\n UnreadMessagesNotificationProps,\n UnreadMessagesSeparatorProps,\n} from '../components';\n\nimport type {\n CustomTrigger,\n DefaultStreamChatGenerics,\n PropsWithChildrenOnly,\n UnknownType,\n} from '../types/types';\nimport type { StopAIGenerationButtonProps } from '../components/MessageInput/StopAIGenerationButton';\n\nexport type ComponentContextValue<\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,\n V extends CustomTrigger = CustomTrigger\n> = {\n /** Custom UI component to display a message attachment, defaults to and accepts same props as: [Attachment](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Attachment/Attachment.tsx) */\n Attachment?: React.ComponentType<AttachmentProps<StreamChatGenerics>>;\n /** Custom UI component to display an attachment previews in MessageInput, defaults to and accepts same props as: [Attachment](https://github.com/GetStream/stream-chat-react/blob/master/src/components/MessageInput/AttachmentPreviewList.tsx) */\n AttachmentPreviewList?: React.ComponentType<AttachmentPreviewListProps>;\n /** Custom UI component to control adding attachments to MessageInput, defaults to and accepts same props as: [AttachmentSelector](https://github.com/GetStream/stream-chat-react/blob/master/src/components/MessageInput/AttachmentSelector.tsx) */\n AttachmentSelector?: React.ComponentType;\n /** Custom UI component for contents of attachment selector initiation button */\n AttachmentSelectorInitiationButtonContents?: React.ComponentType;\n /** Custom UI component to display AudioRecorder in MessageInput, defaults to and accepts same props as: [AudioRecorder](https://github.com/GetStream/stream-chat-react/blob/master/src/components/MessageInput/AudioRecorder.tsx) */\n AudioRecorder?: React.ComponentType;\n /** Optional UI component to override the default suggestion Item component, defaults to and accepts same props as: [Item](https://github.com/GetStream/stream-chat-react/blob/master/src/components/AutoCompleteTextarea/Item.js) */\n AutocompleteSuggestionItem?: React.ComponentType<SuggestionItemProps<StreamChatGenerics>>;\n /** Optional UI component to override the default List component that displays suggestions, defaults to and accepts same props as: [List](https://github.com/GetStream/stream-chat-react/blob/master/src/components/AutoCompleteTextarea/List.js) */\n AutocompleteSuggestionList?: React.ComponentType<SuggestionListProps<StreamChatGenerics>>;\n /** UI component to display a user's avatar, defaults to and accepts same props as: [Avatar](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Avatar/Avatar.tsx) */\n Avatar?: React.ComponentType<AvatarProps<StreamChatGenerics>>;\n /** Custom UI component to display <img/> elements resp. a fallback in case of load error, defaults to and accepts same props as: [BaseImage](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Gallery/BaseImage.tsx) */\n BaseImage?: React.ComponentType<BaseImageProps>;\n /** Custom UI component to display set of action buttons within `ChannelPreviewMessenger` component, accepts same props as: [ChannelPreviewActionButtons](https://github.com/GetStream/stream-chat-react/blob/master/src/components/ChannelList/ChannelPreviewActionButtons.tsx) */\n ChannelPreviewActionButtons?: React.ComponentType<\n ChannelPreviewActionButtonsProps<StreamChatGenerics>\n >;\n /** Custom UI component to display the slow mode cooldown timer, defaults to and accepts same props as: [CooldownTimer](https://github.com/GetStream/stream-chat-react/blob/master/src/components/MessageInput/CooldownTimer.tsx) */\n CooldownTimer?: React.ComponentType<CooldownTimerProps>;\n /** Custom UI component to render set of buttons to be displayed in the MessageActionsBox, defaults to and accepts same props as: [CustomMessageActionsList](https://github.com/GetStream/stream-chat-react/blob/master/src/components/MessageActions/CustomMessageActionsList.tsx) */\n CustomMessageActionsList?: React.ComponentType<CustomMessageActionsListProps<StreamChatGenerics>>;\n /** Custom UI component for date separators, defaults to and accepts same props as: [DateSeparator](https://github.com/GetStream/stream-chat-react/blob/master/src/components/DateSeparator.tsx) */\n DateSeparator?: React.ComponentType<DateSeparatorProps>;\n /** Custom UI component to override default edit message input, defaults to and accepts same props as: [EditMessageForm](https://github.com/GetStream/stream-chat-react/blob/master/src/components/MessageInput/EditMessageForm.tsx) */\n EditMessageInput?: React.ComponentType<MessageInputProps<StreamChatGenerics>>;\n /** Custom UI component for rendering button with emoji picker in MessageInput */\n EmojiPicker?: React.ComponentType;\n /** Mechanism to be used with autocomplete and text replace features of the `MessageInput` component, see [emoji-mart `SearchIndex`](https://github.com/missive/emoji-mart#%EF%B8%8F%EF%B8%8F-headless-search) */\n emojiSearchIndex?: EmojiSearchIndex;\n /** Custom UI component to be displayed when the `MessageList` is empty, defaults to and accepts same props as: [EmptyStateIndicator](https://github.com/GetStream/stream-chat-react/blob/master/src/components/EmptyStateIndicator/EmptyStateIndicator.tsx) */\n EmptyStateIndicator?: React.ComponentType<EmptyStateIndicatorProps>;\n /**\n * Custom UI component for file upload icon, defaults to and accepts same props as: [FileUploadIcon](https://github.com/GetStream/stream-chat-react/blob/master/src/components/MessageInput/icons.tsx)\n * @deprecated use AttachmentSelectorInitiationButtonContents prop instead\n */\n FileUploadIcon?: React.ComponentType;\n /** Custom UI component to render a Giphy preview in the `VirtualizedMessageList` */\n GiphyPreviewMessage?: React.ComponentType<GiphyPreviewMessageProps<StreamChatGenerics>>;\n /** Custom UI component to render at the top of the `MessageList` */\n HeaderComponent?: React.ComponentType;\n /** Custom UI component handling how the message input is rendered, defaults to and accepts the same props as [MessageInputFlat](https://github.com/GetStream/stream-chat-react/blob/master/src/components/MessageInput/MessageInputFlat.tsx) */\n Input?: React.ComponentType<MessageInputProps<StreamChatGenerics, V>>;\n /** Custom component to render link previews in message input **/\n LinkPreviewList?: React.ComponentType<LinkPreviewListProps>;\n /** Custom UI component to render while the `MessageList` is loading new messages, defaults to and accepts same props as: [LoadingIndicator](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Loading/LoadingIndicator.tsx) */\n LoadingIndicator?: React.ComponentType<LoadingIndicatorProps>;\n /** Custom UI component to display a message in the standard `MessageList`, defaults to and accepts the same props as: [MessageSimple](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Message/MessageSimple.tsx) */\n Message?: React.ComponentType<MessageUIComponentProps<StreamChatGenerics>>;\n /** Custom UI component for message actions popup, accepts no props, all the defaults are set within [MessageActions (unstable)](https://github.com/GetStream/stream-chat-react/blob/master/src/experimental/MessageActions/MessageActions.tsx) */\n MessageActions?: React.ComponentType;\n /** Custom UI component to display the contents of a bounced message modal. Usually it allows to retry, edit, or delete the message. Defaults to and accepts the same props as: [MessageBouncePrompt](https://github.com/GetStream/stream-chat-react/blob/master/src/components/MessageBounce/MessageBouncePrompt.tsx) */\n MessageBouncePrompt?: React.ComponentType<MessageBouncePromptProps>;\n /** Custom UI component for a deleted message, defaults to and accepts same props as: [MessageDeleted](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Message/MessageDeleted.tsx) */\n MessageDeleted?: React.ComponentType<MessageDeletedProps<StreamChatGenerics>>;\n MessageListMainPanel?: React.ComponentType<PropsWithChildrenOnly>;\n /** Custom UI component that displays message and connection status notifications in the `MessageList`, defaults to and accepts same props as [DefaultMessageListNotifications](https://github.com/GetStream/stream-chat-react/blob/master/src/components/MessageList/MessageListNotifications.tsx) */\n MessageListNotifications?: React.ComponentType<MessageListNotificationsProps>;\n /** Custom UI component to display a notification when scrolled up the list and new messages arrive, defaults to and accepts same props as [MessageNotification](https://github.com/GetStream/stream-chat-react/blob/master/src/components/MessageList/MessageNotification.tsx) */\n MessageNotification?: React.ComponentType<MessageNotificationProps>;\n /**\n * Custom UI component for message options popup, defaults to and accepts same props as: [MessageOptions](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Message/MessageOptions.tsx)\n *\n * @deprecated Use MessageActions property instead.\n */\n MessageOptions?: React.ComponentType<MessageOptionsProps<StreamChatGenerics>>;\n /** Custom UI component to display message replies, defaults to and accepts same props as: [MessageRepliesCountButton](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Message/MessageRepliesCountButton.tsx) */\n MessageRepliesCountButton?: React.ComponentType<MessageRepliesCountButtonProps>;\n /** Custom UI component to display message delivery status, defaults to and accepts same props as: [MessageStatus](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Message/MessageStatus.tsx) */\n MessageStatus?: React.ComponentType<MessageStatusProps>;\n /** Custom UI component to display system messages, defaults to and accepts same props as: [EventComponent](https://github.com/GetStream/stream-chat-react/blob/master/src/components/EventComponent/EventComponent.tsx) */\n MessageSystem?: React.ComponentType<EventComponentProps<StreamChatGenerics>>;\n /** Custom UI component to display a timestamp on a message, defaults to and accepts same props as: [MessageTimestamp](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Message/MessageTimestamp.tsx) */\n MessageTimestamp?: React.ComponentType<MessageTimestampProps<StreamChatGenerics>>;\n /** Custom UI component for viewing message's image attachments, defaults to and accepts the same props as [ModalGallery](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Gallery/ModalGallery.tsx) */\n ModalGallery?: React.ComponentType<ModalGalleryProps>;\n /** Custom UI component to override default pinned message indicator, defaults to and accepts same props as: [PinIndicator](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Message/icons.tsx) */\n PinIndicator?: React.ComponentType<PinIndicatorProps<StreamChatGenerics>>;\n /** Custom UI component to override default poll actions rendering in a message, defaults to and accepts same props as: [PollActions](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Poll/PollActions/PollActions.tsx) */\n PollActions?: React.ComponentType;\n /** Custom UI component to override default poll rendering in a message, defaults to and accepts same props as: [PollContent](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Poll/PollContent.tsx) */\n PollContent?: React.ComponentType;\n /** Custom UI component to override default poll creation dialog contents, defaults to and accepts same props as: [PollCreationDialog](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Poll/PollCreationDialog/PollCreationDialog.tsx) */\n PollCreationDialog?: React.ComponentType<PollCreationDialogProps>;\n /** Custom UI component to override default poll header in a message, defaults to and accepts same props as: [PollHeader](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Poll/PollHeader.tsx) */\n PollHeader?: React.ComponentType;\n /** Custom UI component to override default poll option selector, defaults to and accepts same props as: [PollOptionSelector](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Poll/PollOptionSelector.tsx) */\n PollOptionSelector?: React.ComponentType<PollOptionSelectorProps<StreamChatGenerics>>;\n /** Custom UI component to override quoted message UI on a sent message, defaults to and accepts same props as: [QuotedMessage](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Message/QuotedMessage.tsx) */\n QuotedMessage?: React.ComponentType;\n /** Custom UI component to override the message input's quoted message preview, defaults to and accepts same props as: [QuotedMessagePreview](https://github.com/GetStream/stream-chat-react/blob/master/src/components/MessageInput/QuotedMessagePreview.tsx) */\n QuotedMessagePreview?: React.ComponentType<QuotedMessagePreviewProps<StreamChatGenerics>>;\n /** Custom UI component to override the rendering of quoted poll, defaults to and accepts same props as: [QuotedPoll](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Poll/QuotedPoll.tsx) */\n QuotedPoll?: React.ComponentType;\n /** Custom reaction options to be applied to ReactionSelector, ReactionList and SimpleReactionList components */\n reactionOptions?: ReactionOptions;\n /** Custom UI component to display the reaction selector, defaults to and accepts same props as: [ReactionSelector](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Reactions/ReactionSelector.tsx) */\n ReactionSelector?: React.ForwardRefExoticComponent<ReactionSelectorProps<StreamChatGenerics>>;\n /** Custom UI component to display the list of reactions on a message, defaults to and accepts same props as: [ReactionsList](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Reactions/ReactionsList.tsx) */\n ReactionsList?: React.ComponentType<ReactionsListProps<StreamChatGenerics>>;\n RecordingPermissionDeniedNotification?: React.ComponentType<RecordingPermissionDeniedNotificationProps>;\n /** Custom UI component for send button, defaults to and accepts same props as: [SendButton](https://github.com/GetStream/stream-chat-react/blob/master/src/components/MessageInput/icons.tsx) */\n SendButton?: React.ComponentType<SendButtonProps<StreamChatGenerics>>;\n /** Custom UI component button for initiating audio recording, defaults to and accepts same props as: [StartRecordingAudioButton](https://github.com/GetStream/stream-chat-react/blob/master/src/components/MediaRecorder/AudioRecorder/AudioRecordingButtons.tsx) */\n StartRecordingAudioButton?: React.ComponentType<StartRecordingAudioButtonProps>;\n StopAIGenerationButton?: React.ComponentType<StopAIGenerationButtonProps> | null;\n StreamedMessageText?: React.ComponentType<StreamedMessageTextProps>;\n /** Custom UI component that displays thread's parent or other message at the top of the `MessageList`, defaults to and accepts same props as [MessageSimple](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Message/MessageSimple.tsx) */\n ThreadHead?: React.ComponentType<MessageProps<StreamChatGenerics>>;\n /** Custom UI component to display the header of a `Thread`, defaults to and accepts same props as: [DefaultThreadHeader](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Thread/Thread.tsx) */\n ThreadHeader?: React.ComponentType<ThreadHeaderProps<StreamChatGenerics>>;\n ThreadInput?: React.ComponentType<MessageInputProps<StreamChatGenerics, V>>;\n ThreadListEmptyPlaceholder?: React.ComponentType;\n ThreadListItem?: React.ComponentType<ThreadListItemProps>;\n ThreadListItemUI?: React.ComponentType<ThreadListItemUIProps>;\n ThreadListLoadingIndicator?: React.ComponentType;\n ThreadListUnseenThreadsBanner?: React.ComponentType;\n /** Custom UI component to display the start of a threaded `MessageList`, defaults to and accepts same props as: [DefaultThreadStart](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Thread/Thread.tsx) */\n ThreadStart?: React.ComponentType;\n /** Custom UI component to display a date used in timestamps. It's used internally by the default `MessageTimestamp`, and to display a timestamp for edited messages. */\n Timestamp?: React.ComponentType<TimestampProps>;\n /** Optional context provider that lets you override the default autocomplete triggers, defaults to: [DefaultTriggerProvider](https://github.com/GetStream/stream-chat-react/blob/master/src/components/MessageInput/DefaultTriggerProvider.tsx) */\n TriggerProvider?: React.ComponentType;\n /** Custom UI component for the typing indicator, defaults to and accepts same props as: [TypingIndicator](https://github.com/GetStream/stream-chat-react/blob/master/src/components/TypingIndicator/TypingIndicator.tsx) */\n TypingIndicator?: React.ComponentType<TypingIndicatorProps>;\n /** Custom UI component that indicates a user is viewing unread messages. It disappears once the user scrolls to UnreadMessagesSeparator. Defaults to and accepts same props as: [UnreadMessagesNotification](https://github.com/GetStream/stream-chat-react/blob/master/src/components/MessageList/UnreadMessagesNotification.tsx) */\n UnreadMessagesNotification?: React.ComponentType<UnreadMessagesNotificationProps>;\n /** Custom UI component that separates read messages from unread, defaults to and accepts same props as: [UnreadMessagesSeparator](https://github.com/GetStream/stream-chat-react/blob/master/src/components/MessageList/UnreadMessagesSeparator.tsx) */\n UnreadMessagesSeparator?: React.ComponentType<UnreadMessagesSeparatorProps>;\n /** Custom UI component to display a message in the `VirtualizedMessageList`, does not have a default implementation */\n VirtualMessage?: React.ComponentType<FixedHeightMessageProps<StreamChatGenerics>>;\n};\n\nexport const ComponentContext = React.createContext<ComponentContextValue>({});\n\nexport const ComponentProvider = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,\n V extends CustomTrigger = CustomTrigger\n>({\n children,\n value,\n}: PropsWithChildren<{\n value: Partial<ComponentContextValue<StreamChatGenerics, V>>;\n}>) => (\n <ComponentContext.Provider value={(value as unknown) as ComponentContextValue}>\n {children}\n </ComponentContext.Provider>\n);\n\nexport const useComponentContext = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,\n V extends CustomTrigger = CustomTrigger\n>(\n /**\n * @deprecated\n */\n // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars\n _componentName?: string,\n) => (useContext(ComponentContext) as unknown) as ComponentContextValue<StreamChatGenerics, V>;\n\n/**\n * Typescript currently does not support partial inference, so if ComponentContext\n * typing is desired while using the HOC withComponentContext, the Props for the\n * wrapped component must be provided as the first generic.\n */\nexport const withComponentContext = <\n P extends UnknownType,\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,\n V extends CustomTrigger = CustomTrigger\n>(\n Component: React.ComponentType<P>,\n) => {\n const WithComponentContextComponent = (\n props: Omit<P, keyof ComponentContextValue<StreamChatGenerics, V>>,\n ) => {\n const componentContext = useComponentContext<StreamChatGenerics, V>();\n\n return <Component {...(props as P)} {...componentContext} />;\n };\n\n WithComponentContextComponent.displayName = (\n Component.displayName ||\n Component.name ||\n 'Component'\n ).replace('Base', '');\n\n return WithComponentContextComponent;\n};\n", "import React, { PropsWithChildren, useContext, useState } from 'react';\nimport { DialogManager } from '../components/Dialog/DialogManager';\nimport { DialogPortalDestination } from '../components/Dialog/DialogPortal';\n\ntype DialogManagerProviderContextValue = {\n dialogManager: DialogManager;\n};\n\nconst DialogManagerProviderContext = React.createContext<\n DialogManagerProviderContextValue | undefined\n>(undefined);\n\nexport const DialogManagerProvider = ({ children, id }: PropsWithChildren<{ id?: string }>) => {\n const [dialogManager] = useState<DialogManager>(() => new DialogManager({ id }));\n\n return (\n <DialogManagerProviderContext.Provider value={{ dialogManager }}>\n {children}\n <DialogPortalDestination />\n </DialogManagerProviderContext.Provider>\n );\n};\n\nexport const useDialogManager = () => {\n const value = useContext(DialogManagerProviderContext);\n return value as DialogManagerProviderContextValue;\n};\n", "import React, { PropsWithChildren, useCallback } from 'react';\nimport { useDialogIsOpen, useOpenedDialogCount } from './hooks';\nimport { Portal } from '../Portal/Portal';\nimport { useDialogManager } from '../../context';\n\nexport const DialogPortalDestination = () => {\n const { dialogManager } = useDialogManager();\n const openedDialogCount = useOpenedDialogCount();\n\n return (\n <div\n className='str-chat__dialog-overlay'\n data-str-chat__portal-id={dialogManager.id}\n data-testid='str-chat__dialog-overlay'\n onClick={() => dialogManager.closeAll()}\n style={\n {\n '--str-chat__dialog-overlay-height': openedDialogCount > 0 ? '100%' : '0',\n } as React.CSSProperties\n }\n ></div>\n );\n};\n\ntype DialogPortalEntryProps = {\n dialogId: string;\n};\n\nexport const DialogPortalEntry = ({\n children,\n dialogId,\n}: PropsWithChildren<DialogPortalEntryProps>) => {\n const { dialogManager } = useDialogManager();\n const dialogIsOpen = useDialogIsOpen(dialogId);\n\n const getPortalDestination = useCallback(\n () => document.querySelector(`div[data-str-chat__portal-id=\"${dialogManager.id}\"]`),\n [dialogManager.id],\n );\n\n return (\n <Portal getPortalDestination={getPortalDestination} isOpen={dialogIsOpen}>\n {children}\n </Portal>\n );\n};\n", "import { useCallback, useEffect } from 'react';\nimport { useDialogManager } from '../../../context';\nimport { useStateStore } from '../../../store';\n\nimport type { DialogManagerState, GetOrCreateDialogParams } from '../DialogManager';\n\nexport const useDialog = ({ id }: GetOrCreateDialogParams) => {\n const { dialogManager } = useDialogManager();\n\n useEffect(\n () => () => {\n // Since this cleanup can run even if the component is still mounted\n // and dialog id is unchanged (e.g. in <StrictMode />), it's safer to\n // mark state as unused and only remove it after a timeout, rather than\n // to remove it immediately.\n dialogManager.markForRemoval(id);\n },\n [dialogManager, id],\n );\n\n return dialogManager.getOrCreate({ id });\n};\n\nexport const useDialogIsOpen = (id: string) => {\n const { dialogManager } = useDialogManager();\n const dialogIsOpenSelector = useCallback(\n ({ dialogsById }: DialogManagerState) => ({ isOpen: !!dialogsById[id]?.isOpen }),\n [id],\n );\n return useStateStore(dialogManager.state, dialogIsOpenSelector).isOpen;\n};\n\nconst openedDialogCountSelector = (nextValue: DialogManagerState) => ({\n openedDialogCount: Object.values(nextValue.dialogsById).reduce((count, dialog) => {\n if (dialog.isOpen) return count + 1;\n return count;\n }, 0),\n});\n\nexport const useOpenedDialogCount = () => {\n const { dialogManager } = useDialogManager();\n return useStateStore(dialogManager.state, openedDialogCountSelector).openedDialogCount;\n};\n", "import { useEffect, useState } from 'react';\n\nimport type { StateStore } from 'stream-chat';\n\nexport function useStateStore<\n T extends Record<string, unknown>,\n O extends Readonly<Record<string, unknown> | Readonly<unknown[]>>\n>(store: StateStore<T>, selector: (v: T) => O): O;\nexport function useStateStore<\n T extends Record<string, unknown>,\n O extends Readonly<Record<string, unknown> | Readonly<unknown[]>>\n>(store: StateStore<T> | undefined, selector: (v: T) => O): O | undefined;\nexport function useStateStore<\n T extends Record<string, unknown>,\n O extends Readonly<Record<string, unknown> | Readonly<unknown[]>>\n>(store: StateStore<T> | undefined, selector: (v: T) => O) {\n const [state, setState] = useState<O | undefined>(() => {\n if (!store) return undefined;\n return selector(store.getLatestValue());\n });\n\n useEffect(() => {\n if (!store) return;\n\n const unsubscribe = store.subscribeWithSelector(selector, setState);\n\n return unsubscribe;\n }, [store, selector]);\n\n return state;\n}\n", "import { PropsWithChildren, ReactPortal, useLayoutEffect, useState } from 'react';\nimport { createPortal } from 'react-dom';\n\nexport type PortalProps = {\n getPortalDestination: () => Element | null;\n isOpen?: boolean;\n};\n\nexport const Portal = ({\n children,\n getPortalDestination,\n isOpen,\n}: PropsWithChildren<PortalProps>): ReactPortal | null => {\n const [portalDestination, setPortalDestination] = useState<Element | null>(null);\n\n useLayoutEffect(() => {\n const destination = getPortalDestination();\n if (!destination || !isOpen) return;\n setPortalDestination(destination);\n }, [getPortalDestination, isOpen]);\n\n if (!portalDestination) return null;\n\n return createPortal(children, portalDestination);\n};\n", "import React, { PropsWithChildren, useContext } from 'react';\n\nimport type { Mute, ReactionResponse, ReactionSort, UserResponse } from 'stream-chat';\n\nimport type { ChannelActionContextValue } from './ChannelActionContext';\nimport type { StreamMessage } from './ChannelStateContext';\n\nimport type { ActionHandlerReturnType } from '../components/Message/hooks/useActionHandler';\nimport type { PinPermissions } from '../components/Message/hooks/usePinHandler';\nimport type { ReactEventHandler } from '../components/Message/types';\nimport type { MessageActionsArray } from '../components/Message/utils';\nimport type { MessageInputProps } from '../components/MessageInput/MessageInput';\nimport type { GroupStyle } from '../components/MessageList/utils';\nimport type {\n ReactionDetailsComparator,\n ReactionsComparator,\n ReactionType,\n} from '../components/Reactions/types';\n\nimport type { RenderTextOptions } from '../components/Message/renderText';\nimport type { DefaultStreamChatGenerics, UnknownType } from '../types/types';\n\nexport type CustomMessageActions<\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n> = {\n [key: string]: (\n message: StreamMessage<StreamChatGenerics>,\n event: React.BaseSyntheticEvent,\n ) => Promise<void> | void;\n};\n\nexport type MessageContextValue<\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n> = {\n /** If actions such as edit, delete, flag, mute are enabled on Message */\n actionsEnabled: boolean;\n /** Function to exit edit state */\n clearEditingState: (event?: React.BaseSyntheticEvent) => void;\n /** If the Message is in edit state */\n editing: boolean;\n /**\n * Returns all allowed actions on message by current user e.g., ['edit', 'delete', 'flag', 'mute', 'pin', 'quote', 'react', 'reply'].\n * Please check [Message](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Message.tsx) component for default implementation.\n */\n getMessageActions: () => MessageActionsArray<string>;\n /** Function to send an action in a Channel */\n handleAction: ActionHandlerReturnType;\n /** Function to delete a message in a Channel */\n handleDelete: ReactEventHandler;\n /** Function to edit a message in a Channel */\n handleEdit: ReactEventHandler;\n /** Function to fetch the message reactions */\n handleFetchReactions: (\n reactionType?: ReactionType<StreamChatGenerics>,\n sort?: ReactionSort<StreamChatGenerics>,\n ) => Promise<Array<ReactionResponse<StreamChatGenerics>>>;\n /** Function to flag a message in a Channel */\n handleFlag: ReactEventHandler;\n /** Function to mark message and the messages that follow it as unread in a Channel */\n handleMarkUnread: ReactEventHandler;\n /** Function to mute a user in a Channel */\n handleMute: ReactEventHandler;\n /** Function to open a Thread on a Message */\n handleOpenThread: ReactEventHandler;\n /** Function to pin a Message in a Channel */\n handlePin: ReactEventHandler;\n /** Function to post a reaction on a Message */\n handleReaction: (reactionType: string, event: React.BaseSyntheticEvent) => Promise<void>;\n /** Function to retry sending a Message */\n handleRetry: ChannelActionContextValue<StreamChatGenerics>['retrySendMessage'];\n /** Function that returns whether the Message belongs to the current user */\n isMyMessage: () => boolean;\n /** The message object */\n message: StreamMessage<StreamChatGenerics>;\n /** Indicates whether a message has not been read yet or has been marked unread */\n messageIsUnread: boolean;\n /** Handler function for a click event on an @mention in Message */\n onMentionsClickMessage: ReactEventHandler;\n /** Handler function for a hover event on an @mention in Message */\n onMentionsHoverMessage: ReactEventHandler;\n /** Handler function for a click event on the user that posted the Message */\n onUserClick: ReactEventHandler;\n /** Handler function for a hover event on the user that posted the Message */\n onUserHover: ReactEventHandler;\n /** Function to toggle the edit state on a Message */\n setEditingState: ReactEventHandler;\n /** Additional props for underlying MessageInput component, [available props](https://getstream.io/chat/docs/sdk/react/message-input-components/message_input/#props) */\n additionalMessageInputProps?: MessageInputProps<StreamChatGenerics>;\n /** Call this function to keep message list scrolled to the bottom when the scroll height increases, e.g. an element appears below the last message (only used in the `VirtualizedMessageList`) */\n autoscrollToBottom?: () => void;\n /** Message component configuration prop. If true, picking a reaction from the `ReactionSelector` component will close the selector */\n closeReactionSelectorOnClick?: boolean;\n /** Object containing custom message actions and function handlers */\n customMessageActions?: CustomMessageActions<StreamChatGenerics>;\n /** If true, the message is the last one in a group sent by a specific user (only used in the `VirtualizedMessageList`) */\n endOfGroup?: boolean;\n /** If true, the message is the first one in a group sent by a specific user (only used in the `VirtualizedMessageList`) */\n firstOfGroup?: boolean;\n /** Override the default formatting of the date. This is a function that has access to the original date object, returns a string */\n formatDate?: (date: Date) => string;\n /** If true, group messages sent by each user (only used in the `VirtualizedMessageList`) */\n groupedByUser?: boolean;\n /** A list of styles to apply to this message, ie. top, bottom, single */\n groupStyles?: GroupStyle[];\n /** Whether to highlight and focus the message on load */\n highlighted?: boolean;\n /** Whether the threaded message is the first in the thread list */\n initialMessage?: boolean;\n /**\n * A factory function that determines whether a message is AI generated or not.\n */\n isMessageAIGenerated?: (message: StreamMessage<StreamChatGenerics>) => boolean;\n /** Latest message id on current channel */\n lastReceivedId?: string | null;\n /** DOMRect object for parent MessageList component */\n messageListRect?: DOMRect;\n /** Array of muted users coming from [ChannelStateContext](https://getstream.io/chat/docs/sdk/react/contexts/channel_state_context/#mutes) */\n mutes?: Mute<StreamChatGenerics>[];\n /** @deprecated in favor of `channelCapabilities - The user roles allowed to pin Messages in various channel types */\n pinPermissions?: PinPermissions;\n /** Sort options to provide to a reactions query */\n reactionDetailsSort?: ReactionSort<StreamChatGenerics>;\n /** A list of users that have read this Message */\n readBy?: UserResponse<StreamChatGenerics>[];\n /** Custom function to render message text content, defaults to the renderText function: [utils](https://github.com/GetStream/stream-chat-react/blob/master/src/utils.tsx) */\n renderText?: (\n text?: string,\n mentioned_users?: UserResponse<StreamChatGenerics>[],\n options?: RenderTextOptions,\n ) => JSX.Element | null;\n /** Comparator function to sort the list of reacted users\n * @deprecated use `reactionDetailsSort` instead\n */\n sortReactionDetails?: ReactionDetailsComparator;\n /** Comparator function to sort reactions, defaults to chronological order */\n sortReactions?: ReactionsComparator;\n /** Whether or not the Message is in a Thread */\n threadList?: boolean;\n /** render HTML instead of markdown. Posting HTML is only allowed server-side */\n unsafeHTML?: boolean;\n};\n\nexport const MessageContext = React.createContext<MessageContextValue | undefined>(undefined);\n\nexport const MessageProvider = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>({\n children,\n value,\n}: PropsWithChildren<{\n value: MessageContextValue<StreamChatGenerics>;\n}>) => (\n <MessageContext.Provider value={(value as unknown) as MessageContextValue}>\n {children}\n </MessageContext.Provider>\n);\n\nexport const useMessageContext = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>(\n // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars\n _componentName?: string,\n) => {\n const contextValue = useContext(MessageContext);\n\n if (!contextValue) {\n return {} as MessageContextValue<StreamChatGenerics>;\n }\n\n return (contextValue as unknown) as MessageContextValue<StreamChatGenerics>;\n};\n\n/**\n * Typescript currently does not support partial inference, so if MessageContext\n * typing is desired while using the HOC withMessageContext, the Props for the\n * wrapped component must be provided as the first generic.\n */\nexport const withMessageContext = <\n P extends UnknownType,\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>(\n Component: React.ComponentType<P>,\n) => {\n const WithMessageContextComponent = (\n props: Omit<P, keyof MessageContextValue<StreamChatGenerics>>,\n ) => {\n const messageContext = useMessageContext<StreamChatGenerics>();\n\n return <Component {...(props as P)} {...messageContext} />;\n };\n\n WithMessageContextComponent.displayName = (\n Component.displayName ||\n Component.name ||\n 'Component'\n ).replace('Base', '');\n\n return WithMessageContextComponent;\n};\n", "import React, { PropsWithChildren, useContext } from 'react';\nimport Dayjs from 'dayjs';\nimport calendar from 'dayjs/plugin/calendar';\nimport localizedFormat from 'dayjs/plugin/localizedFormat';\n\nimport { getDisplayName } from './utils/getDisplayName';\nimport { defaultDateTimeParser, defaultTranslatorFunction } from '../i18n/utils';\n\nimport type { TFunction } from 'i18next';\nimport type { TranslationLanguages } from 'stream-chat';\n\nimport type { UnknownType } from '../types/types';\nimport type { TDateTimeParser } from '../i18n/types';\n\nDayjs.extend(calendar);\nDayjs.extend(localizedFormat);\n\nexport type TranslationContextValue = {\n t: TFunction;\n tDateTimeParser: TDateTimeParser;\n userLanguage: TranslationLanguages;\n};\n\nexport const TranslationContext = React.createContext<TranslationContextValue>({\n t: defaultTranslatorFunction,\n tDateTimeParser: defaultDateTimeParser,\n userLanguage: 'en',\n});\n\nexport const TranslationProvider = ({\n children,\n value,\n}: PropsWithChildren<{ value: TranslationContextValue }>) => (\n <TranslationContext.Provider value={value}>{children}</TranslationContext.Provider>\n);\n\nexport const useTranslationContext = (componentName?: string) => {\n const contextValue = useContext(TranslationContext);\n\n if (!contextValue) {\n console.warn(\n `The useTranslationContext hook was called outside of the TranslationContext provider. Make sure this hook is called within a child of the Chat component. The errored call is located in the ${componentName} component.`,\n );\n\n return {} as TranslationContextValue;\n }\n\n return contextValue;\n};\n\nexport const withTranslationContext = <P extends UnknownType>(\n Component: React.ComponentType<P>,\n) => {\n const WithTranslationContextComponent = (props: Omit<P, keyof TranslationContextValue>) => {\n const translationContext = useTranslationContext();\n\n return <Component {...(props as P)} {...translationContext} />;\n };\n\n WithTranslationContextComponent.displayName = `WithTranslationContext${getDisplayName(\n Component,\n )}`;\n\n return WithTranslationContextComponent;\n};\n", "import Dayjs from 'dayjs';\n\nimport type { TFunction } from 'i18next';\nimport type { Moment } from 'moment-timezone';\nimport type {\n DateFormatterOptions,\n PredefinedFormatters,\n SupportedTranslations,\n TDateTimeParserInput,\n TDateTimeParserOutput,\n TimestampFormatterOptions,\n} from './types';\n\nexport const notValidDateWarning =\n 'MessageTimestamp was called without a message, or message has invalid created_at date.';\nexport const noParsingFunctionWarning =\n 'MessageTimestamp was called but there is no datetime parsing function available';\n\nexport const isNumberOrString = (output: TDateTimeParserOutput): output is number | string =>\n typeof output === 'string' || typeof output === 'number';\n\nexport const isDayOrMoment = (output: TDateTimeParserOutput): output is Dayjs.Dayjs | Moment =>\n !!(output as Dayjs.Dayjs | Moment)?.isSame;\n\nexport const isDate = (output: TDateTimeParserOutput): output is Date =>\n !!(output as Date)?.getMonth;\n\nexport function getDateString({\n calendar,\n calendarFormats,\n format,\n formatDate,\n messageCreatedAt,\n t,\n tDateTimeParser,\n timestampTranslationKey,\n}: DateFormatterOptions): string | number | null {\n if (\n !messageCreatedAt ||\n (typeof messageCreatedAt === 'string' && !Date.parse(messageCreatedAt))\n ) {\n console.warn(notValidDateWarning);\n return null;\n }\n\n if (typeof formatDate === 'function') {\n return formatDate(new Date(messageCreatedAt));\n }\n\n if (t && timestampTranslationKey) {\n const options: TimestampFormatterOptions = {};\n if (typeof calendar !== 'undefined' && calendar !== null) options.calendar = calendar;\n if (typeof calendarFormats !== 'undefined' && calendarFormats !== null)\n options.calendarFormats = calendarFormats;\n if (typeof format !== 'undefined' && format !== null) options.format = format;\n\n const translatedTimestamp = t(timestampTranslationKey, {\n ...options,\n timestamp: new Date(messageCreatedAt),\n });\n const translationKeyFound = timestampTranslationKey !== translatedTimestamp;\n if (translationKeyFound) return translatedTimestamp;\n }\n\n if (!tDateTimeParser) {\n console.warn(noParsingFunctionWarning);\n return null;\n }\n\n const parsedTime = tDateTimeParser(messageCreatedAt);\n\n if (isDayOrMoment(parsedTime)) {\n /**\n * parsedTime.calendar is guaranteed on the type but is only\n * available when a user calls dayjs.extend(calendar)\n */\n return calendar && parsedTime.calendar\n ? parsedTime.calendar(undefined, calendarFormats || undefined)\n : parsedTime.format(format || undefined);\n }\n\n if (isDate(parsedTime)) {\n return parsedTime.toDateString();\n }\n\n if (isNumberOrString(parsedTime)) {\n return parsedTime;\n }\n\n return null;\n}\n\nexport const predefinedFormatters: PredefinedFormatters = {\n timestampFormatter: (streamI18n) => (\n value,\n _,\n {\n calendarFormats,\n ...options\n }: Pick<TimestampFormatterOptions, 'calendar' | 'format'> & {\n calendarFormats?: Record<string, string> | string;\n },\n ) => {\n let parsedCalendarFormats;\n try {\n if (!options.calendar) {\n parsedCalendarFormats = {};\n } else if (typeof calendarFormats === 'string') {\n parsedCalendarFormats = JSON.parse(calendarFormats);\n } else if (typeof calendarFormats === 'object') {\n parsedCalendarFormats = calendarFormats;\n }\n } catch (e) {\n console.error('[TIMESTAMP FORMATTER]', e);\n }\n\n const result = getDateString({\n ...options,\n calendarFormats: parsedCalendarFormats,\n messageCreatedAt: value,\n tDateTimeParser: streamI18n.tDateTimeParser,\n });\n if (!result || typeof result === 'number') {\n return JSON.stringify(value);\n }\n return result;\n },\n};\n\nexport const defaultTranslatorFunction: TFunction = <tResult = string>(key: tResult) => key;\n\nexport const defaultDateTimeParser = (input?: TDateTimeParserInput) => Dayjs(input);\n\nexport const isLanguageSupported = (language: string): language is SupportedTranslations => {\n const translations = ['de', 'en', 'es', 'fr', 'hi', 'it', 'ja', 'ko', 'nl', 'pt', 'ru', 'tr'];\n return translations.some((translation) => language === translation);\n};\n", "import clsx from 'clsx';\nimport React, { useEffect, useState } from 'react';\n\nimport type { UserResponse } from 'stream-chat';\n\nimport { Icon } from '../Threads/icons';\nimport { getWholeChar } from '../../utils';\n\nimport type { DefaultStreamChatGenerics } from '../../types/types';\n\nexport type AvatarProps<\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n> = {\n /** Custom root element class that will be merged with the default class */\n className?: string;\n /** Image URL or default is an image of the first initial of the name if there is one */\n image?: string | null;\n /** Name of the image, used for title tag fallback */\n name?: string;\n /** click event handler attached to the component root element */\n onClick?: (event: React.BaseSyntheticEvent) => void;\n /** mouseOver event handler attached to the component root element */\n onMouseOver?: (event: React.BaseSyntheticEvent) => void;\n /** The entire user object for the chat user displayed in the component */\n user?: UserResponse<StreamChatGenerics>;\n};\n\n/**\n * A round avatar image with fallback to username's first letter\n */\nexport const Avatar = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>(\n props: AvatarProps<StreamChatGenerics>,\n) => {\n const {\n className,\n image,\n name,\n onClick = () => undefined,\n onMouseOver = () => undefined,\n } = props;\n\n const [error, setError] = useState(false);\n\n useEffect(() => {\n setError(false);\n }, [image]);\n\n const nameStr = name?.toString() || '';\n const initials = getWholeChar(nameStr, 0);\n const showImage = image && !error;\n\n return (\n <div\n className={clsx(`str-chat__avatar str-chat__message-sender-avatar`, className, {\n ['str-chat__avatar--multiple-letters']: initials.length > 1,\n ['str-chat__avatar--no-letters']: !initials.length,\n ['str-chat__avatar--one-letter']: initials.length === 1,\n })}\n data-testid='avatar'\n onClick={onClick}\n onMouseOver={onMouseOver}\n role='button'\n title={name}\n >\n {showImage ? (\n <img\n alt={initials}\n className='str-chat__avatar-image'\n data-testid='avatar-img'\n onError={() => setError(true)}\n src={image}\n />\n ) : (\n <>\n {!!initials.length && (\n <div className={clsx('str-chat__avatar-fallback')} data-testid='avatar-fallback'>\n {initials}\n </div>\n )}\n {!initials.length && <Icon.User />}\n </>\n )}\n </div>\n );\n};\n", "/* eslint-disable react/display-name */\nimport React from 'react';\nimport { ComponentPropsWithoutRef } from 'react';\n\n// TODO: unify icons across SDK\nexport const Icon = {\n MessageBubble: (props: ComponentPropsWithoutRef<'svg'>) => (\n <svg\n className='str-chat__icon str-chat__icon--message-bubble'\n fill='none'\n height='14'\n viewBox='0 0 14 14'\n width='14'\n xmlns='http://www.w3.org/2000/svg'\n {...props}\n >\n <path\n d='M1.66659 1.66665H12.3333V9.66665H2.44659L1.66659 10.4466V1.66665ZM1.66659 0.333313C0.933252 0.333313 0.339919 0.933313 0.339919 1.66665L0.333252 13.6666L2.99992 11H12.3333C13.0666 11 13.6666 10.4 13.6666 9.66665V1.66665C13.6666 0.933313 13.0666 0.333313 12.3333 0.333313H1.66659ZM2.99992 6.99998H10.9999V8.33331H2.99992V6.99998ZM2.99992 4.99998H10.9999V6.33331H2.99992V4.99998ZM2.99992 2.99998H10.9999V4.33331H2.99992V2.99998Z'\n fill='currentColor'\n />\n </svg>\n ),\n MessageBubbleEmpty: (props: ComponentPropsWithoutRef<'svg'>) => (\n <svg\n className='str-chat__icon str-chat__icon--message-bubble-empty'\n fill='none'\n height='20'\n viewBox='0 0 20 20'\n width='20'\n xmlns='http://www.w3.org/2000/svg'\n {...props}\n >\n <path\n d='M18 0H2C0.9 0 0 0.9 0 2V20L4 16H18C19.1 16 20 15.1 20 14V2C20 0.9 19.1 0 18 0ZM18 14H4L2 16V2H18V14Z'\n fill='currentColor'\n />\n </svg>\n ),\n Reload: (props: ComponentPropsWithoutRef<'svg'>) => (\n <svg\n className='str-chat__icon str-chat__icon--reload'\n fill='none'\n height='22'\n viewBox='0 0 16 22'\n width='16'\n xmlns='http://www.w3.org/2000/svg'\n {...props}\n >\n <path\n d='M8 3V0L4 4L8 8V5C11.31 5 14 7.69 14 11C14 12.01 13.75 12.97 13.3 13.8L14.76 15.26C15.54 14.03 16 12.57 16 11C16 6.58 12.42 3 8 3ZM8 17C4.69 17 2 14.31 2 11C2 9.99 2.25 9.03 2.7 8.2L1.24 6.74C0.46 7.97 0 9.43 0 11C0 15.42 3.58 19 8 19V22L12 18L8 14V17Z'\n fill='currentColor'\n />\n </svg>\n ),\n User: (props: ComponentPropsWithoutRef<'svg'>) => (\n <svg\n className='str-chat__icon str-chat__icon--user'\n fill='none'\n height='16'\n viewBox='0 0 16 16'\n width='16'\n xmlns='http://www.w3.org/2000/svg'\n {...props}\n >\n <path\n d='M8 2C9.1 2 10 2.9 10 4C10 5.1 9.1 6 8 6C6.9 6 6 5.1 6 4C6 2.9 6.9 2 8 2ZM8 12C10.7 12 13.8 13.29 14 14H2C2.23 13.28 5.31 12 8 12ZM8 0C5.79 0 4 1.79 4 4C4 6.21 5.79 8 8 8C10.21 8 12 6.21 12 4C12 1.79 10.21 0 8 0ZM8 10C5.33 10 0 11.34 0 14V16H16V14C16 11.34 10.67 10 8 10Z'\n fill='currentColor'\n />\n </svg>\n ),\n};\n", "// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/charAt#getting_whole_characters\nexport const getWholeChar = (str: string, i: number) => {\n const code = str.charCodeAt(i);\n\n if (Number.isNaN(code)) return '';\n\n if (code < 0xd800 || code > 0xdfff) return str.charAt(i);\n\n if (0xd800 <= code && code <= 0xdbff) {\n if (str.length <= i + 1) {\n throw 'High surrogate without following low surrogate';\n }\n\n const next = str.charCodeAt(i + 1);\n\n if (0xdc00 > next || next > 0xdfff) {\n throw 'High surrogate without following low surrogate';\n }\n\n return str.charAt(i) + str.charAt(i + 1);\n }\n\n if (i === 0) {\n throw 'Low surrogate without preceding high surrogate';\n }\n\n const prev = str.charCodeAt(i - 1);\n\n if (0xd800 > prev || prev > 0xdbff) {\n throw 'Low surrogate without preceding high surrogate';\n }\n\n return '';\n};\n", "import deepequal from 'react-fast-compare';\nimport emojiRegex from 'emoji-regex';\n\nimport type { TFunction } from 'i18next';\nimport type { MessageResponse, Mute, StreamChat, UserResponse } from 'stream-chat';\nimport type { PinPermissions } from './hooks';\nimport type { MessageProps } from './types';\nimport type {\n ComponentContextValue,\n CustomMessageActions,\n MessageContextValue,\n StreamMessage,\n} from '../../context';\nimport type { DefaultStreamChatGenerics } from '../../types/types';\n\n/**\n * Following function validates a function which returns notification message.\n * It validates if the first parameter is function and also if return value of function is string or no.\n */\nexport const validateAndGetMessage = <T extends unknown[]>(\n func: (...args: T) => unknown,\n args: T,\n) => {\n if (!func || typeof func !== 'function') return null;\n\n // below is due to tests passing a single argument\n // rather than an array.\n if (!(args instanceof Array)) {\n // @ts-expect-error\n args = [args];\n }\n\n const returnValue = func(...args);\n\n if (typeof returnValue !== 'string') return null;\n\n return returnValue;\n};\n\n/**\n * Tell if the owner of the current message is muted\n */\nexport const isUserMuted = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>(\n message: StreamMessage<StreamChatGenerics>,\n mutes?: Mute<StreamChatGenerics>[],\n) => {\n if (!mutes || !message) return false;\n\n const userMuted = mutes.filter((el) => el.target.id === message.user?.id);\n return !!userMuted.length;\n};\n\nexport const MESSAGE_ACTIONS = {\n delete: 'delete',\n edit: 'edit',\n flag: 'flag',\n markUnread: 'markUnread',\n mute: 'mute',\n pin: 'pin',\n quote: 'quote',\n react: 'react',\n reply: 'reply',\n};\n\nexport type MessageActionsArray<T extends string = string> = Array<\n keyof typeof MESSAGE_ACTIONS | T\n>;\n\n// @deprecated in favor of `channelCapabilities` - TODO: remove in next major release\nexport const defaultPinPermissions: PinPermissions = {\n commerce: {\n admin: true,\n anonymous: false,\n channel_member: false,\n channel_moderator: true,\n guest: false,\n member: false,\n moderator: true,\n owner: true,\n user: false,\n },\n gaming: {\n admin: true,\n anonymous: false,\n channel_member: false,\n channel_moderator: true,\n guest: false,\n member: false,\n moderator: true,\n owner: false,\n user: false,\n },\n livestream: {\n admin: true,\n anonymous: false,\n channel_member: false,\n channel_moderator: true,\n guest: false,\n member: false,\n moderator: true,\n owner: true,\n user: false,\n },\n messaging: {\n admin: true,\n anonymous: false,\n channel_member: true,\n channel_moderator: true,\n guest: false,\n member: true,\n moderator: true,\n owner: true,\n user: false,\n },\n team: {\n admin: true,\n anonymous: false,\n channel_member: true,\n channel_moderator: true,\n guest: false,\n member: true,\n moderator: true,\n owner: true,\n user: false,\n },\n};\n\nexport type Capabilities = {\n canDelete?: boolean;\n canEdit?: boolean;\n canFlag?: boolean;\n canMarkUnread?: boolean;\n canMute?: boolean;\n canPin?: boolean;\n canQuote?: boolean;\n canReact?: boolean;\n canReply?: boolean;\n};\n\nexport const getMessageActions = (\n actions: MessageActionsArray | boolean,\n {\n canDelete,\n canEdit,\n canFlag,\n canMarkUnread,\n canMute,\n canPin,\n canQuote,\n canReact,\n canReply,\n }: Capabilities,\n): MessageActionsArray => {\n const messageActionsAfterPermission: MessageActionsArray = [];\n let messageActions: MessageActionsArray = [];\n\n if (actions && typeof actions === 'boolean') {\n // If value of actions is true, then populate all the possible values\n messageActions = Object.keys(MESSAGE_ACTIONS);\n } else if (actions && actions.length > 0) {\n messageActions = [...actions];\n } else {\n return [];\n }\n\n if (canDelete && messageActions.indexOf(MESSAGE_ACTIONS.delete) > -1) {\n messageActionsAfterPermission.push(MESSAGE_ACTIONS.delete);\n }\n\n if (canEdit && messageActions.indexOf(MESSAGE_ACTIONS.edit) > -1) {\n messageActionsAfterPermission.push(MESSAGE_ACTIONS.edit);\n }\n\n if (canFlag && messageActions.indexOf(MESSAGE_ACTIONS.flag) > -1) {\n messageActionsAfterPermission.push(MESSAGE_ACTIONS.flag);\n }\n\n if (canMarkUnread && messageActions.indexOf(MESSAGE_ACTIONS.markUnread) > -1) {\n messageActionsAfterPermission.push(MESSAGE_ACTIONS.markUnread);\n }\n\n if (canMute && messageActions.indexOf(MESSAGE_ACTIONS.mute) > -1) {\n messageActionsAfterPermission.push(MESSAGE_ACTIONS.mute);\n }\n\n if (canPin && messageActions.indexOf(MESSAGE_ACTIONS.pin) > -1) {\n messageActionsAfterPermission.push(MESSAGE_ACTIONS.pin);\n }\n\n if (canQuote && messageActions.indexOf(MESSAGE_ACTIONS.quote) > -1) {\n messageActionsAfterPermission.push(MESSAGE_ACTIONS.quote);\n }\n\n if (canReact && messageActions.indexOf(MESSAGE_ACTIONS.react) > -1) {\n messageActionsAfterPermission.push(MESSAGE_ACTIONS.react);\n }\n\n if (canReply && messageActions.indexOf(MESSAGE_ACTIONS.reply) > -1) {\n messageActionsAfterPermission.push(MESSAGE_ACTIONS.reply);\n }\n\n return messageActionsAfterPermission;\n};\n\nexport const ACTIONS_NOT_WORKING_IN_THREAD = [\n MESSAGE_ACTIONS.pin,\n MESSAGE_ACTIONS.reply,\n MESSAGE_ACTIONS.markUnread,\n];\n\n/**\n * @deprecated use `shouldRenderMessageActions` instead\n */\nexport const showMessageActionsBox = (\n actions: MessageActionsArray,\n inThread?: boolean | undefined,\n) => shouldRenderMessageActions({ inThread, messageActions: actions });\n\nexport const shouldRenderMessageActions = <\n SCG extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>({\n customMessageActions,\n CustomMessageActionsList,\n inThread,\n messageActions,\n}: {\n messageActions: MessageActionsArray;\n customMessageActions?: CustomMessageActions<SCG>;\n CustomMessageActionsList?: ComponentContextValue<SCG>['CustomMessageActionsList'];\n inThread?: boolean;\n}) => {\n if (\n typeof CustomMessageActionsList !== 'undefined' ||\n typeof customMessageActions !== 'undefined'\n )\n return true;\n\n if (!messageActions.length) return false;\n\n if (\n inThread &&\n messageActions.filter((action) => !ACTIONS_NOT_WORKING_IN_THREAD.includes(action)).length === 0\n ) {\n return false;\n }\n\n if (\n messageActions.length === 1 &&\n (messageActions.includes(MESSAGE_ACTIONS.react) ||\n messageActions.includes(MESSAGE_ACTIONS.reply))\n ) {\n return false;\n }\n\n if (\n messageActions.length === 2 &&\n messageActions.includes(MESSAGE_ACTIONS.react) &&\n messageActions.includes(MESSAGE_ACTIONS.reply)\n ) {\n return false;\n }\n\n return true;\n};\n\nfunction areMessagesEqual<\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>(\n prevMessage: StreamMessage<StreamChatGenerics>,\n nextMessage: StreamMessage<StreamChatGenerics>,\n): boolean {\n return (\n prevMessage.deleted_at === nextMessage.deleted_at &&\n prevMessage.latest_reactions?.length === nextMessage.latest_reactions?.length &&\n prevMessage.own_reactions?.length === nextMessage.own_reactions?.length &&\n prevMessage.pinned === nextMessage.pinned &&\n prevMessage.reply_count === nextMessage.reply_count &&\n prevMessage.status === nextMessage.status &&\n prevMessage.text === nextMessage.text &&\n prevMessage.type === nextMessage.type &&\n prevMessage.updated_at === nextMessage.updated_at &&\n prevMessage.user?.updated_at === nextMessage.user?.updated_at &&\n Boolean(prevMessage.quoted_message) === Boolean(nextMessage.quoted_message) &&\n (!prevMessage.quoted_message ||\n areMessagesEqual(\n prevMessage.quoted_message as StreamMessage<StreamChatGenerics>,\n nextMessage.quoted_message as StreamMessage<StreamChatGenerics>,\n ))\n );\n}\n\nexport const areMessagePropsEqual = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>(\n prevProps: MessageProps<StreamChatGenerics> & {\n mutes?: Mute<StreamChatGenerics>[];\n showDetailedReactions?: boolean;\n },\n nextProps: MessageProps<StreamChatGenerics> & {\n mutes?: Mute<StreamChatGenerics>[];\n showDetailedReactions?: boolean;\n },\n) => {\n const { message: prevMessage, Message: prevMessageUI } = prevProps;\n const { message: nextMessage, Message: nextMessageUI } = nextProps;\n\n if (prevMessageUI !== nextMessageUI) return false;\n if (prevProps.endOfGroup !== nextProps.endOfGroup) return false;\n\n if (nextProps.showDetailedReactions !== prevProps.showDetailedReactions) {\n return false;\n }\n\n if (nextProps.closeReactionSelectorOnClick !== prevProps.closeReactionSelectorOnClick) {\n return false;\n }\n\n const messagesAreEqual = areMessagesEqual(prevMessage, nextMessage);\n if (!messagesAreEqual) return false;\n\n const deepEqualProps =\n deepequal(nextProps.messageActions, prevProps.messageActions) &&\n deepequal(nextProps.readBy, prevProps.readBy) &&\n deepequal(nextProps.highlighted, prevProps.highlighted) &&\n deepequal(nextProps.groupStyles, prevProps.groupStyles) && // last 3 messages can have different group styles\n deepequal(nextProps.mutes, prevProps.mutes) &&\n deepequal(nextProps.lastReceivedId, prevProps.lastReceivedId);\n\n if (!deepEqualProps) return false;\n\n return (\n prevProps.messageListRect === nextProps.messageListRect // MessageList wrapper layout changes\n );\n};\n\nexport const areMessageUIPropsEqual = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>(\n prevProps: MessageContextValue<StreamChatGenerics> & {\n showDetailedReactions?: boolean;\n },\n nextProps: MessageContextValue<StreamChatGenerics> & {\n showDetailedReactions?: boolean;\n },\n) => {\n const { lastReceivedId: prevLastReceivedId, message: prevMessage } = prevProps;\n const { lastReceivedId: nextLastReceivedId, message: nextMessage } = nextProps;\n\n if (prevProps.editing !== nextProps.editing) return false;\n if (prevProps.highlighted !== nextProps.highlighted) return false;\n if (prevProps.endOfGroup !== nextProps.endOfGroup) return false;\n if (prevProps.mutes?.length !== nextProps.mutes?.length) return false;\n if (prevProps.readBy?.length !== nextProps.readBy?.length) return false;\n if (prevProps.groupStyles !== nextProps.groupStyles) return false;\n\n if (prevProps.showDetailedReactions !== nextProps.showDetailedReactions) {\n return false;\n }\n\n if (\n (prevMessage.id === prevLastReceivedId || prevMessage.id === nextLastReceivedId) &&\n prevLastReceivedId !== nextLastReceivedId\n ) {\n return false;\n }\n\n return areMessagesEqual(prevMessage, nextMessage);\n};\n\nexport const messageHasReactions = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>(\n message?: StreamMessage<StreamChatGenerics>,\n) => Object.values(message?.reaction_groups ?? {}).some(({ count }) => count > 0);\n\nexport const messageHasAttachments = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>(\n message?: StreamMessage<StreamChatGenerics>,\n) => !!message?.attachments && !!message.attachments.length;\n\nexport const getImages = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>(\n message?: MessageResponse<StreamChatGenerics>,\n) => {\n if (!message?.attachments) {\n return [];\n }\n return message.attachments.filter((item) => item.type === 'image');\n};\n\nexport const getNonImageAttachments = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>(\n message?: MessageResponse<StreamChatGenerics>,\n) => {\n if (!message?.attachments) {\n return [];\n }\n return message.attachments.filter((item) => item.type !== 'image');\n};\n\nexport interface TooltipUsernameMapper {\n <StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics>(\n user: UserResponse<StreamChatGenerics>,\n ): string;\n}\n\n/**\n * Default Tooltip Username mapper implementation.\n *\n * @param user the user.\n */\nexport const mapToUserNameOrId: TooltipUsernameMapper = (user) => user.name || user.id;\n\nexport const getReadByTooltipText = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>(\n users: UserResponse<StreamChatGenerics>[],\n t: TFunction,\n client: StreamChat<StreamChatGenerics>,\n tooltipUserNameMapper: TooltipUsernameMapper,\n) => {\n let outStr = '';\n\n if (!t) {\n throw new Error('getReadByTooltipText was called, but translation function is not available');\n }\n\n if (!tooltipUserNameMapper) {\n throw new Error(\n 'getReadByTooltipText was called, but tooltipUserNameMapper function is not available',\n );\n }\n // first filter out client user, so restLength won't count it\n const otherUsers = users\n .filter((item) => item && client?.user && item.id !== client.user.id)\n .map(tooltipUserNameMapper);\n\n const slicedArr = otherUsers.slice(0, 5);\n const restLength = otherUsers.length - slicedArr.length;\n\n if (slicedArr.length === 1) {\n outStr = `${slicedArr[0]} `;\n } else if (slicedArr.length === 2) {\n // joins all with \"and\" but =no commas\n // example: \"bob and sam\"\n outStr = t('{{ firstUser }} and {{ secondUser }}', {\n firstUser: slicedArr[0],\n secondUser: slicedArr[1],\n });\n } else if (slicedArr.length > 2) {\n // joins all with commas, but last one gets \", and\" (oxford comma!)\n // example: \"bob, joe, sam and 4 more\"\n if (restLength === 0) {\n // mutate slicedArr to remove last user to display it separately\n const lastUser = slicedArr.splice(slicedArr.length - 1, 1);\n outStr = t('{{ commaSeparatedUsers }}, and {{ lastUser }}', {\n commaSeparatedUsers: slicedArr.join(', '),\n lastUser,\n });\n } else {\n outStr = t('{{ commaSeparatedUsers }} and {{ moreCount }} more', {\n commaSeparatedUsers: slicedArr.join(', '),\n moreCount: restLength,\n });\n }\n }\n\n return outStr;\n};\n\nexport const isOnlyEmojis = (text?: string) => {\n if (!text) return false;\n\n const noEmojis = text.replace(emojiRegex(), '');\n const noSpace = noEmojis.replace(/[\\s\\n]/gm, '');\n\n return !noSpace;\n};\n\nexport const isMessageBounced = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>(\n message: Pick<StreamMessage<StreamChatGenerics>, 'type' | 'moderation' | 'moderation_details'>,\n) =>\n message.type === 'error' &&\n (message.moderation_details?.action === 'MESSAGE_RESPONSE_ACTION_BOUNCE' ||\n message.moderation?.action === 'bounce');\n\nexport const isMessageEdited = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>(\n message: Pick<StreamMessage<StreamChatGenerics>, 'message_text_updated_at'>,\n) => !!message.message_text_updated_at;\n", "import { StreamMessage, useChannelStateContext } from '../../../context/ChannelStateContext';\nimport { useChatContext } from '../../../context/ChatContext';\n\nimport type { DefaultStreamChatGenerics } from '../../../types/types';\n\nexport const useUserRole = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>(\n message: StreamMessage<StreamChatGenerics>,\n onlySenderCanEdit?: boolean,\n disableQuotedMessages?: boolean,\n) => {\n const { channel, channelCapabilities = {} } = useChannelStateContext<StreamChatGenerics>(\n 'useUserRole',\n );\n const { client } = useChatContext<StreamChatGenerics>('useUserRole');\n\n /**\n * @deprecated as it relies on `membership.role` check which is already deprecated and shouldn't be used anymore.\n * `isAdmin` will be removed in future release. See `channelCapabilities`.\n */\n const isAdmin = client.user?.role === 'admin' || channel.state.membership.role === 'admin';\n\n /**\n * @deprecated as it relies on `membership.role` check which is already deprecated and shouldn't be used anymore.\n * `isOwner` will be removed in future release. See `channelCapabilities`.\n */\n const isOwner = channel.state.membership.role === 'owner';\n\n /**\n * @deprecated as it relies on `membership.role` check which is already deprecated and shouldn't be used anymore.\n * `isModerator` will be removed in future release. See `channelCapabilities`.\n */\n const isModerator =\n client.user?.role === 'channel_moderator' ||\n channel.state.membership.role === 'channel_moderator' ||\n channel.state.membership.role === 'moderator' ||\n channel.state.membership.is_moderator === true ||\n channel.state.membership.channel_role === 'channel_moderator';\n\n const isMyMessage = client.userID === message.user?.id;\n\n const canEdit =\n !message.poll &&\n ((!onlySenderCanEdit && channelCapabilities['update-any-message']) ||\n (isMyMessage && channelCapabilities['update-own-message']));\n\n const canDelete =\n channelCapabilities['delete-any-message'] ||\n (isMyMessage && channelCapabilities['delete-own-message']);\n\n const canFlag = !isMyMessage && channelCapabilities['flag-message'];\n const canMarkUnread = channelCapabilities['read-events'];\n const canMute = !isMyMessage && channelCapabilities['mute-channel'];\n const canQuote = !disableQuotedMessages && channelCapabilities['quote-message'];\n const canReact = channelCapabilities['send-reaction'];\n const canReply = channelCapabilities['send-reply'];\n\n return {\n canDelete,\n canEdit,\n canFlag,\n canMarkUnread,\n canMute,\n canQuote,\n canReact,\n canReply,\n isAdmin,\n isModerator,\n isMyMessage,\n isOwner,\n };\n};\n", "import React from 'react';\n\nimport type { PinIndicatorProps } from './types';\n\nimport type { DefaultStreamChatGenerics, IconProps } from '../../types/types';\n\nexport const ActionsIcon = ({ className = '' }: IconProps) => (\n <svg\n className={className}\n height='4'\n viewBox='0 0 11 4'\n width='11'\n xmlns='http://www.w3.org/2000/svg'\n >\n <path\n d='M1.5 3a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm4 0a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm4 0a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3z'\n fillRule='nonzero'\n />\n </svg>\n);\n\nexport const ReactionIcon = ({ className = '' }: IconProps) => (\n <svg\n className={className}\n height='12'\n viewBox='0 0 12 12'\n width='12'\n xmlns='http://www.w3.org/2000/svg'\n >\n <g clipRule='evenodd' fillRule='evenodd'>\n <path d='M6 1.2C3.3 1.2 1.2 3.3 1.2 6c0 2.7 2.1 4.8 4.8 4.8 2.7 0 4.8-2.1 4.8-4.8 0-2.7-2.1-4.8-4.8-4.8zM0 6c0-3.3 2.7-6 6-6s6 2.7 6 6-2.7 6-6 6-6-2.7-6-6z' />\n <path d='M5.4 4.5c0 .5-.4.9-.9.9s-.9-.4-.9-.9.4-.9.9-.9.9.4.9.9zM8.4 4.5c0 .5-.4.9-.9.9s-.9-.4-.9-.9.4-.9.9-.9.9.4.9.9zM3.3 6.7c.3-.2.6-.1.8.1.3.4.8.9 1.5 1 .6.2 1.4.1 2.4-1 .2-.2.6-.3.8 0 .2.2.3.6 0 .8-1.1 1.3-2.4 1.7-3.5 1.5-1-.2-1.8-.9-2.2-1.5-.2-.3-.1-.7.2-.9z' />\n </g>\n </svg>\n);\n\nexport const ThreadIcon = ({ className = '' }: IconProps) => (\n <svg className={className} height='10' width='14' xmlns='http://www.w3.org/2000/svg'>\n <path\n d='M8.516 3c4.78 0 4.972 6.5 4.972 6.5-1.6-2.906-2.847-3.184-4.972-3.184v2.872L3.772 4.994 8.516.5V3zM.484 5l4.5-4.237v1.78L2.416 5l2.568 2.125v1.828L.484 5z'\n fillRule='evenodd'\n />\n </svg>\n);\n\nexport const PinIcon = () => (\n <svg height='13' viewBox='0 0 14 13' width='14' xmlns='http://www.w3.org/2000/svg'>\n <path\n d='M13.3518 6.686L6.75251 0.0866699L5.80984 1.02867L6.75318 1.972V1.97334L3.45318 5.272L3.45251 5.27334L2.50984 4.32934L1.56718 5.27267L4.39584 8.10067L0.624512 11.8713L1.56718 12.814L5.33851 9.04334L8.16718 11.8713L9.10984 10.9293L8.16718 9.986L11.4672 6.686L12.4098 7.62867L13.3518 6.686ZM7.22451 9.04267L7.22385 9.04334L4.39584 6.21467L7.69518 2.91467L10.5232 5.74267L7.22451 9.04267Z'\n fillRule='evenodd'\n />\n </svg>\n);\n\nexport const PinIndicator = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>({\n message,\n t,\n}: PinIndicatorProps<StreamChatGenerics>) => {\n if (!message || !t) return null;\n\n return (\n <div style={{ alignItems: 'center', display: 'flex' }}>\n <PinIcon />\n <div\n style={{\n fontSize: '14px',\n marginBottom: '0',\n marginLeft: '8px',\n marginTop: '0',\n }}\n >\n {message.pinned_by\n ? `${t<string>('Pinned by')} ${message.pinned_by?.name || message.pinned_by?.id}`\n : t<string>('Message pinned')}\n </div>\n </div>\n );\n};\n\nexport const MessageDeliveredIcon = () => (\n <svg\n data-testid='delivered-icon'\n fill='none'\n height='24'\n viewBox='0 0 24 24'\n width='24'\n xmlns='http://www.w3.org/2000/svg'\n >\n <path\n clipRule='evenodd'\n d='M8.9999 16.2L4.7999 12L3.3999 13.4L8.9999 19L20.9999 6.99998L19.5999 5.59998L8.9999 16.2Z'\n fill='black'\n fillRule='evenodd'\n />\n </svg>\n);\n\nexport const MessageErrorIcon = () => (\n <div className='str-chat__message-error-icon'>\n <svg\n data-testid='error'\n fill='none'\n height='24'\n viewBox='0 0 24 24'\n width='24'\n xmlns='http://www.w3.org/2000/svg'\n >\n <path\n d='M12 2C6.48 2 2 6.48 2 12C2 17.52 6.48 22 12 22C17.52 22 22 17.52 22 12C22 6.48 17.52 2 12 2Z'\n fill='black'\n id='background'\n />\n <path d='M13 17H11V15H13V17ZM13 13H11V7H13V13Z' fill='white' />\n </svg>\n </div>\n);\n", "import clsx from 'clsx';\nimport React, { PropsWithChildren, useCallback, useRef } from 'react';\n\nimport { MessageActionsBox } from './MessageActionsBox';\n\nimport { DialogAnchor, useDialog, useDialogIsOpen } from '../Dialog';\nimport { ActionsIcon as DefaultActionsIcon } from '../Message/icons';\nimport { isUserMuted, shouldRenderMessageActions } from '../Message/utils';\n\nimport { useChatContext } from '../../context/ChatContext';\nimport { MessageContextValue, useMessageContext } from '../../context/MessageContext';\nimport { useComponentContext, useTranslationContext } from '../../context';\n\nimport type { DefaultStreamChatGenerics, IconProps } from '../../types/types';\n\ntype MessageContextPropsToPick =\n | 'getMessageActions'\n | 'handleDelete'\n | 'handleFlag'\n | 'handleMarkUnread'\n | 'handleMute'\n | 'handlePin'\n | 'message';\n\nexport type MessageActionsProps<\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n> = Partial<Pick<MessageContextValue<StreamChatGenerics>, MessageContextPropsToPick>> & {\n /* Custom component rendering the icon used in message actions button. This button invokes the message actions menu. */\n ActionsIcon?: React.ComponentType<IconProps>;\n /* Custom CSS class to be added to the `div` wrapping the component */\n customWrapperClass?: string;\n /* If true, renders the wrapper component as a `span`, not a `div` */\n inline?: boolean;\n /* Function that returns whether the message was sent by the connected user */\n mine?: () => boolean;\n};\n\nexport const MessageActions = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>(\n props: MessageActionsProps<StreamChatGenerics>,\n) => {\n const {\n ActionsIcon = DefaultActionsIcon,\n customWrapperClass = '',\n getMessageActions: propGetMessageActions,\n handleDelete: propHandleDelete,\n handleFlag: propHandleFlag,\n handleMarkUnread: propHandleMarkUnread,\n handleMute: propHandleMute,\n handlePin: propHandlePin,\n inline,\n message: propMessage,\n mine,\n } = props;\n\n const { mutes } = useChatContext<StreamChatGenerics>('MessageActions');\n\n const {\n customMessageActions,\n getMessageActions: contextGetMessageActions,\n handleDelete: contextHandleDelete,\n handleFlag: contextHandleFlag,\n handleMarkUnread: contextHandleMarkUnread,\n handleMute: contextHandleMute,\n handlePin: contextHandlePin,\n isMyMessage,\n message: contextMessage,\n setEditingState,\n threadList,\n } = useMessageContext<StreamChatGenerics>('MessageActions');\n\n const { CustomMessageActionsList } = useComponentContext<StreamChatGenerics>('MessageActions');\n\n const { t } = useTranslationContext('MessageActions');\n\n const getMessageActions = propGetMessageActions || contextGetMessageActions;\n const handleDelete = propHandleDelete || contextHandleDelete;\n const handleFlag = propHandleFlag || contextHandleFlag;\n const handleMarkUnread = propHandleMarkUnread || contextHandleMarkUnread;\n const handleMute = propHandleMute || contextHandleMute;\n const handlePin = propHandlePin || contextHandlePin;\n const message = propMessage || contextMessage;\n const isMine = mine ? mine() : isMyMessage();\n\n const isMuted = useCallback(() => isUserMuted(message, mutes), [message, mutes]);\n\n const dialogId = `message-actions--${message.id}`;\n const dialog = useDialog({ id: dialogId });\n const dialogIsOpen = useDialogIsOpen(dialogId);\n\n const messageActions = getMessageActions();\n\n const renderMessageActions = shouldRenderMessageActions<StreamChatGenerics>({\n customMessageActions,\n CustomMessageActionsList,\n inThread: threadList,\n messageActions,\n });\n\n const actionsBoxButtonRef = useRef<HTMLButtonElement | null>(null);\n\n if (!renderMessageActions) return null;\n\n return (\n <MessageActionsWrapper\n customWrapperClass={customWrapperClass}\n inline={inline}\n toggleOpen={dialog?.toggle}\n >\n <DialogAnchor\n id={dialogId}\n placement={isMine ? 'top-end' : 'top-start'}\n referenceElement={actionsBoxButtonRef.current}\n trapFocus\n >\n <MessageActionsBox\n getMessageActions={getMessageActions}\n handleDelete={handleDelete}\n handleEdit={setEditingState}\n handleFlag={handleFlag}\n handleMarkUnread={handleMarkUnread}\n handleMute={handleMute}\n handlePin={handlePin}\n isUserMuted={isMuted}\n mine={isMine}\n open={dialogIsOpen}\n />\n </DialogAnchor>\n <button\n aria-expanded={dialogIsOpen}\n aria-haspopup='true'\n aria-label={t('aria/Open Message Actions Menu')}\n className='str-chat__message-actions-box-button'\n data-testid='message-actions-toggle-button'\n ref={actionsBoxButtonRef}\n >\n <ActionsIcon className='str-chat__message-action-icon' />\n </button>\n </MessageActionsWrapper>\n );\n};\n\nexport type MessageActionsWrapperProps = {\n customWrapperClass?: string;\n inline?: boolean;\n toggleOpen?: () => void;\n};\n\nexport const MessageActionsWrapper = (props: PropsWithChildren<MessageActionsWrapperProps>) => {\n const { children, customWrapperClass, inline, toggleOpen } = props;\n\n const defaultWrapperClass = clsx(\n 'str-chat__message-simple__actions__action',\n 'str-chat__message-simple__actions__action--options',\n 'str-chat__message-actions-container',\n );\n\n const wrapperProps = {\n className: customWrapperClass || defaultWrapperClass,\n 'data-testid': 'message-actions',\n onClick: toggleOpen,\n };\n\n if (inline) return <span {...wrapperProps}>{children}</span>;\n\n return <div {...wrapperProps}>{children}</div>;\n};\n", "import clsx from 'clsx';\nimport { Placement } from '@popperjs/core';\nimport React, { ComponentProps, PropsWithChildren, useEffect, useState } from 'react';\nimport { FocusScope } from '@react-aria/focus';\nimport { usePopper } from 'react-popper';\nimport { DialogPortalEntry } from './DialogPortal';\nimport { useDialog, useDialogIsOpen } from './hooks';\n\nexport interface DialogAnchorOptions {\n open: boolean;\n placement: Placement;\n referenceElement: HTMLElement | null;\n}\n\nexport function useDialogAnchor<T extends HTMLElement>({\n open,\n placement,\n referenceElement,\n}: DialogAnchorOptions) {\n const [popperElement, setPopperElement] = useState<T | null>(null);\n const { attributes, styles, update } = usePopper(referenceElement, popperElement, {\n modifiers: [\n {\n name: 'eventListeners',\n options: {\n // It's not safe to update popper position on resize and scroll, since popper's\n // reference element might not be visible at the time.\n resize: false,\n scroll: false,\n },\n },\n ],\n placement,\n });\n\n useEffect(() => {\n if (open && popperElement) {\n // Since the popper's reference element might not be (and usually is not) visible\n // all the time, it's safer to force popper update before showing it.\n // update is non-null only if popperElement is non-null\n update?.();\n }\n }, [open, popperElement, update]);\n\n if (popperElement && !open) {\n setPopperElement(null);\n }\n\n return {\n attributes,\n setPopperElement,\n styles,\n };\n}\n\nexport type DialogAnchorProps = PropsWithChildren<Partial<DialogAnchorOptions>> & {\n id: string;\n focus?: boolean;\n trapFocus?: boolean;\n} & ComponentProps<'div'>;\n\nexport const DialogAnchor = ({\n children,\n className,\n focus = true,\n id,\n placement = 'auto',\n referenceElement = null,\n trapFocus,\n ...restDivProps\n}: DialogAnchorProps) => {\n const dialog = useDialog({ id });\n const open = useDialogIsOpen(id);\n const { attributes, setPopperElement, styles } = useDialogAnchor<HTMLDivElement>({\n open,\n placement,\n referenceElement,\n });\n\n useEffect(() => {\n if (!open) return;\n const hideOnEscape = (event: KeyboardEvent) => {\n if (event.key !== 'Escape') return;\n dialog?.close();\n };\n\n document.addEventListener('keyup', hideOnEscape);\n\n return () => {\n document.removeEventListener('keyup', hideOnEscape);\n };\n }, [dialog, open]);\n\n // prevent rendering the dialog contents if the dialog should not be open / shown\n if (!open) {\n return null;\n }\n\n return (\n <DialogPortalEntry dialogId={id}>\n <FocusScope autoFocus={focus} contain={trapFocus} restoreFocus>\n <div\n {...restDivProps}\n {...attributes.popper}\n className={clsx('str-chat__dialog-contents', className)}\n data-testid='str-chat__dialog-contents'\n ref={setPopperElement}\n style={styles.popper}\n tabIndex={0}\n >\n {children}\n </div>\n </FocusScope>\n </DialogPortalEntry>\n );\n};\n", "import React, { ElementRef, useRef } from 'react';\nimport { ReactionSelector as DefaultReactionSelector } from './ReactionSelector';\nimport { DialogAnchor, useDialog, useDialogIsOpen } from '../Dialog';\nimport { useComponentContext, useMessageContext, useTranslationContext } from '../../context';\nimport type { DefaultStreamChatGenerics } from '../../types';\nimport type { IconProps } from '../../types/types';\n\ntype ReactionSelectorWithButtonProps = {\n /* Custom component rendering the icon used in a button invoking reactions selector for a given message. */\n ReactionIcon: React.ComponentType<IconProps>;\n};\n\n/**\n * Internal convenience component - not to be exported. It just groups the button and the dialog anchor and thus prevents\n * cluttering the parent component.\n */\nexport const ReactionSelectorWithButton = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>({\n ReactionIcon,\n}: ReactionSelectorWithButtonProps) => {\n const { t } = useTranslationContext('ReactionSelectorWithButton');\n const { isMyMessage, message } = useMessageContext<StreamChatGenerics>('MessageOptions');\n const { ReactionSelector = DefaultReactionSelector } = useComponentContext('MessageOptions');\n const buttonRef = useRef<ElementRef<'button'>>(null);\n const dialogId = `reaction-selector--${message.id}`;\n const dialog = useDialog({ id: dialogId });\n const dialogIsOpen = useDialogIsOpen(dialogId);\n return (\n <>\n <DialogAnchor\n id={dialogId}\n placement={isMyMessage() ? 'top-end' : 'top-start'}\n referenceElement={buttonRef.current}\n trapFocus\n >\n <ReactionSelector />\n </DialogAnchor>\n <button\n aria-expanded={dialogIsOpen}\n aria-label={t('aria/Open Reaction Selector')}\n className='str-chat__message-reactions-button'\n data-testid='message-reaction-action'\n onClick={() => dialog?.toggle()}\n ref={buttonRef}\n >\n <ReactionIcon className='str-chat__message-action-icon' />\n </button>\n </>\n );\n};\n", "import React, { useCallback, useEffect, useRef, useState } from 'react';\nimport clsx from 'clsx';\n\nimport { Avatar as DefaultAvatar } from '../Avatar';\nimport { useDialog } from '../Dialog';\nimport { defaultReactionOptions } from './reactionOptions';\nimport { isMutableRef } from './utils/utils';\n\nimport { useComponentContext } from '../../context/ComponentContext';\nimport { useMessageContext } from '../../context/MessageContext';\n\nimport type { ReactionGroupResponse, ReactionResponse } from 'stream-chat';\nimport type { AvatarProps } from '../Avatar';\nimport type { DefaultStreamChatGenerics } from '../../types/types';\nimport type { ReactionOptions } from './reactionOptions';\n\nexport type ReactionSelectorProps<\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n> = {\n /** Custom UI component to display user avatar, defaults to and accepts same props as: [Avatar](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Avatar/Avatar.tsx) */\n Avatar?: React.ElementType<AvatarProps>;\n /** If true, shows the user's avatar with the reaction */\n detailedView?: boolean;\n /** Function that adds/removes a reaction on a message (overrides the function stored in `MessageContext`) */\n handleReaction?: (reactionType: string, event: React.BaseSyntheticEvent) => Promise<void>;\n /** An array of the reaction objects to display in the list */\n latest_reactions?: ReactionResponse<StreamChatGenerics>[];\n /** An array of the own reaction objects to distinguish own reactions visually */\n own_reactions?: ReactionResponse<StreamChatGenerics>[];\n /**\n * An object that keeps track of the count of each type of reaction on a message\n * @deprecated This override value is no longer taken into account. Use `reaction_groups` to override reaction counts instead.\n * */\n reaction_counts?: Record<string, number>;\n /** An object containing summary for each reaction type on a message */\n reaction_groups?: Record<string, ReactionGroupResponse>;\n /**\n * @deprecated\n * A list of the currently supported reactions on a message\n * */\n reactionOptions?: ReactionOptions;\n /** If true, adds a CSS class that reverses the horizontal positioning of the selector */\n reverse?: boolean;\n};\n\nconst UnMemoizedReactionSelector = <\n StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics\n>(\n props: ReactionSelectorProps<StreamChatGenerics>,\n) => {\n const {\n Avatar: propAvatar,\n detailedView = true,\n handleReaction: propHandleReaction,\n latest_reactions: propLatestReactions,\n own_reactions: propOwnReactions,\n reaction_groups: propReactionGroups,\n reactionOptions: propReactionOptions,\n reverse = false,\n } = props;\n\n const {\n Avatar: contextAvatar,\n reactionOptions: contextReactionOptions = defaultReactionOptions,\n } = useComponentContext<StreamChatGenerics>('ReactionSelector');\n const {\n closeReactionSelectorOnClick,\n handleReaction: contextHandleReaction,\n message,\n } = useMessageContext<StreamChatGenerics>('ReactionSelector');\n const dialogId = `reaction-selector--${message.id}`;\n const dialog = useDialog({ id: dialogId });\n const reactionOptions = propReactionOptions ?? contextReactionOptions;\n\n const Avatar = propAvatar || contextAvatar || DefaultAvatar;\n const handleReaction = propHandleReaction || contextHandleReaction;\n const latestReactions = propLatestReactions || message?.latest_reactions || [];\n const ownReactions = propOwnReactions || message?.own_reactions || [];\n const reactionGroups = propReactionGroups || message?.reaction_groups || {};\n\n const [tooltipReactionType, setTooltipReactionType] = useState<string | null>(null);\n const [tooltipPositions, setTooltipPositions] = useState<{\n arrow: number;\n tooltip: number;\n } | null>(null);\n\n const rootRef = useRef<HTMLDivElement | null>(null);\n const targetRef = useRef<HTMLDivElement | null>(null);\n const tooltipRef = useRef<HTMLDivElement | null>(null);\n\n const showTooltip = useCallback(\n (event: React.MouseEvent<HTMLDivElement>, reactionType: string) => {\n targetRef.current = event.currentTarget;\n setTooltipReactionType(reactionType);\n },\n [],\n );\n\n const hideTooltip = useCallback(() => {\n setTooltipReactionType(null);\n setTooltipPositions(null);\n }, []);\n\n useEffect(() => {\n if (!tooltipReactionType || !rootRef.current) return;\n const tooltip = tooltipRef.current?.getBoundingClientRect();\n const target = targetRef.current?.getBoundingClientRect();\n\n const container = isMutableRef(rootRef) ? rootRef.current?.getBoundingClientRect() : null;\n\n if (!tooltip || !target || !container) return;\n\n const tooltipPosition =\n tooltip.width === container.width || tooltip.x < container.x\n ? 0\n : target.left + target.width / 2 - container.left - tooltip.width / 2;\n\n const arrowPosition = target.x - tooltip.x + target.width / 2 - tooltipPosition;\n\n setTooltipPositions({\n arrow: arrowPosition,\n tooltip: tooltipPosition,\n });\n }, [tooltipReactionType, rootRef]);\n\n const getUsersPerReactionType = (type: string | null) =>\n latestReactions\n .map((reaction) => {\n if (reaction.type === type) {\n return reaction.user?.name || reaction.user?.id;\n }\n return null;\n })\n .filter(Boolean);\n\n const iHaveReactedWithReaction = (reactionType: string) =>\n ownReactions.find((reaction) => reaction.type === reactionType);\n\n const getLatestUserForReactionType = (type: string | null) =>\n latestReactions.find((reaction) => reaction.type === type && !!reaction.user)?.user ||\n undefined;\n\n return (\n <div\n className={clsx(\n 'str-chat__reaction-selector str-chat__message-reaction-selector str-chat-react__message-reaction-selector',\n {\n 'str-chat__reaction-selector--reverse': reverse,\n },\n )}\n data-testid='reaction-selector'\n ref={rootRef}\n >\n {!!tooltipReactionType && detailedView && (\n <div\n className='str-chat__reaction-selector-tooltip'\n ref={tooltipRef}\n style={{\n left: tooltipPositions?.tooltip,\n visibility: tooltipPositions ? 'visible' : 'hidden',\n }}\n >\n <div className='arrow' style={{ left: tooltipPositions?.arrow }} />\n {getUsersPerReactionType(tooltipReactionType)?.map((user, i, users) => (\n <span className='latest-user-username' key={`key-${i}-${user}`}>\n {`${user}${i < users.length - 1 ? ', ' : ''}`}\n </span>\n ))}\n </div>\n )}\n <ul className='str-chat__message-reactions-list str-chat__message-reactions-options'>\n {reactionOptions.map(({ Component, name: reactionName, type: reactionType }) => {\n const latestUser = getLatestUserForReactionType(reactionType);\n const count = reactionGroups[reactionType]?.count ?? 0;\n return (\n <li key={reactionType}>\n <button\n aria-label={`Select Reaction: ${reactionName || reactionType}`}\n className={clsx(\n 'str-chat__message-reactions-list-item str-chat__message-reactions-option',\n {\n 'str-chat__message-reactions-option-selected': iHaveReactedWithReaction(\n reactionType,\n ),\n },\n )}\n data-testid='select-reaction-button'\n data-text={reactionType}\n onClick={(event) => {\n handleReaction(reactionType, event);\n if (closeReactionSelectorOnClick) {\n dialog.close();\n }\n }}\n >\n {!!count && detailedView && (\n <div\n className='latest-user str-chat__message-reactions-last-user'\n onClick={hideTooltip}\n onMouseEnter={(e) => showTooltip(e, reactionType)}\n onMouseLeave={hideTooltip}\n >\n {latestUser ? (\n <Avatar\n image={latestUser.image}\n name={latestUser.name}\n size={20}\n user={latestUser}\n />\n ) : (\n <div className='latest-user-not-found' />\n )}\n </div>\n )}\n <span className='str-chat__message-reaction-emoji'>\n <Component />\n </span>\n {Boolean(count) && detailedView && (\n <span className='str-chat__message-reactions-list-item__count'>\n {count || ''}\n </span>\n )}\n </button>\n </li>\n );\n })}\n </ul>\n </div>\n );\n};\n\n/**\n * Component that allows a user to select a reaction.\n */\nexport const ReactionSelector = React.memo(\n UnMemoizedReactionSelector,\n) as typeof UnMemoizedReactionSelector;\n", "/* eslint-disable sort-keys */\n/* eslint-disable react/display-name */\nimport React from 'react';\n\nimport { StreamEmoji } from './StreamEmoji';\n\nexport type ReactionOptions = Array<{\n Component: React.ComponentType;\n type: string;\n name?: string;\n}>;\n\nexport const defaultReactionOptions: ReactionOptions = [\n { type: 'haha', Component: () => <StreamEmoji fallback='\uD83D\uDE02' type='haha' />, name: 'Joy' },\n { type: 'like', Component: () => <StreamEmoji fallback='\uD83D\uDC4D' type='like' />, name: 'Thumbs up' },\n { type: 'love', Component: () => <StreamEmoji fallback='\u2764\uFE0F' type='love' />, name: 'Heart' },\n { type: 'sad', Component: () => <StreamEmoji fallback='\uD83D\uDE14' type='sad' />, name: 'Sad' },\n { type: 'wow', Component: () => <StreamEmoji fallback='\uD83D\uDE32' type='wow' />, name: 'Astonished' },\n];\n", "import React from 'react';\n\nimport { SpriteImage, SpriteImageProps } from './SpriteImage';\n\nimport type { Readable } from '../../types/types';\n\nconst StreamSpriteEmojiPositions = {\n angry: [1, 1],\n haha: [1, 0],\n like: [0, 0],\n love: [1, 2],\n sad: [0, 1],\n wow: [0, 2],\n};\n\ntype StreamEmojiType = keyof typeof StreamSpriteEmojiPositions;\n\nconst STREAM_SPRITE_URL = 'https://getstream.imgix.net/images/emoji-sprite.png';\n\nexport const StreamEmoji = ({\n fallback,\n type,\n}: Readable<{ type: StreamEmojiType } & Pick<SpriteImageProps, 'fallback'>>) => {\n const position = StreamSpriteEmojiPositions[type] as [number, number];\n return (\n <SpriteImage\n columns={2}\n fallback={fallback}\n position={position}\n rows={3}\n spriteUrl={STREAM_SPRITE_URL}\n style={\n {\n '--str-chat__sprite-image-height': 'var(--str-chat__stream-emoji-size, 18px)',\n } as React.CSSProperties\n }\n />\n );\n};\n", "import React, { useEffect, useState } from 'react';\n\nimport { getImageDimensions } from './utils/utils';\n\nexport type SpriteImageProps = {\n columns: number;\n position: [number, number];\n rows: number;\n spriteUrl: string;\n fallback?: React.ReactNode;\n height?: number;\n style?: React.CSSProperties;\n width?: number;\n};\n\nexport const SpriteImage = ({\n columns,\n fallback,\n height,\n position,\n rows,\n spriteUrl,\n style,\n width,\n}: SpriteImageProps) => {\n const [[spriteWidth, spriteHeight], setSpriteDimensions] = useState([0, 0]);\n\n useEffect(() => {\n getImageDimensions(spriteUrl).then(setSpriteDimensions).catch(console.error);\n }, [spriteUrl]);\n\n const [x, y] = position;\n\n if (!spriteHeight || !spriteWidth) return <>{fallback}</>;\n\n return (\n <div\n data-testid='sprite-image'\n style={\n {\n ...style,\n '--str-chat__sprite-image-resize-ratio':\n 'var(--str-chat__sprite-image-resize-ratio-x, var(--str-chat__sprite-image-resize-ratio-y, 1))',\n '--str-chat__sprite-image-resize-ratio-x':\n 'calc(var(--str-chat__sprite-image-width) / var(--str-chat__sprite-item-width))',\n '--str-chat__sprite-image-resize-ratio-y':\n 'calc(var(--str-chat__sprite-image-height) / var(--str-chat__sprite-item-height))',\n '--str-chat__sprite-item-height': `${spriteHeight / rows}`,\n '--str-chat__sprite-item-width': `${spriteWidth / columns}`,\n ...(Number.isFinite(height) ? { '--str-chat__sprite-image-height': `${height}px` } : {}),\n ...(Number.isFinite(width) ? { '--str-chat__sprite-image-width': `${width}px` } : {}),\n backgroundImage: `url('${spriteUrl}')`,\n backgroundPosition: `${x * (100 / (columns - 1))}% ${y * (100 / (rows - 1))}%`,\n backgroundSize: `${columns * 100}% ${rows * 100}%`,\n height:\n 'var(--str-chat__sprite-image-height, calc(var(--str-chat__sprite-item-height) * var(--str-chat__sprite-image-resize-ratio)))',\n width:\n 'var(--str-chat__sprite-image-width, calc(var(--str-chat__sprite-item-width) * var(--str-chat__sprite-image-resize-ratio)))',\n } as React.CSSProperties\n }\n />\n );\n};\n", "import { ForwardedRef, MutableRefObject } from 'react';\n\nexport const isMutableRef = <T>(ref: ForwardedRef<T> | null): ref is MutableRefObject<T> => {\n if (ref) {\n return (ref as MutableRefObject<T>).current !== undefined;\n }\n return false;\n};\n\nexport const getImageDimensions = (source: string) =>\n new Promise<[number, number]>((resolve, reject) => {\n const image = new Image();\n\n image.addEventListener(\n 'load',\n () => {\n resolve([image.width, image.height]);\n },\n { once: true },\n );\n\n image.addEventListener('error', () => reject(`Couldn't load image from ${source}`), {\n once: true,\n });\n\n image.src = source;\n });\n", "import { useMemo } from 'react';\n\nimport { ACTIONS_NOT_WORKING_IN_THREAD, useUserRole } from '../../../components';\nimport { useMessageContext } from '../../../context';\n\nimport type { MessageActionSetItem } from '../MessageActions';\n\n/**\n * Base filter hook which covers actions of type `delete`, `edit`,\n * `flag`, `markUnread`, `mute`, `quote`, `react` and `reply`, whether\n * the rendered message is a reply (replies are limited to certain actions) and\n * whether the message has appropriate type and status.\n */\nexport const useBaseMessageActionSetFilter = (\n messageActionSet: MessageActionSetItem[],\n disable = false,\n) => {\n const { initialMessage: isInitialMessage, message } = useMessageContext();\n const {\n canDelete,\n canEdit,\n canFlag,\n canMarkUnread,\n canMute,\n canQuote,\n canReact,\n canReply,\n } = useUserRole(message);\n const isMessageThreadReply = typeof message.parent_id === 'string';\n\n return useMemo(() => {\n if (disable) return messageActionSet;\n\n // filter out all actions if any of these are true\n if (\n isInitialMessage || // not sure whether this thing even works anymore\n !message.type ||\n message.type === 'error' ||\n message.type === 'system' ||\n message.type === 'ephemeral' ||\n message.status === 'failed' ||\n message.status === 'sending'\n )\n return [];\n\n return messageActionSet.filter(({ type }: MessageActionSetItem) => {\n // filter out actions with types that do not work in thread\n if (ACTIONS_NOT_WORKING_IN_THREAD.includes(type) && isMessageThreadReply) return false;\n\n if (\n (type === 'delete' && !canDelete) ||\n (type === 'edit' && !canEdit) ||\n (type === 'flag' && !canFlag) ||\n (type === 'markUnread' && !canMarkUnread) ||\n (type === 'mute' && !canMute) ||\n (type === 'quote' && !canQuote) ||\n (type === 'react' && !canReact) ||\n (type === 'reply' && !canReply)\n )\n return false;\n\n return true;\n });\n }, [\n canDelete,\n canEdit,\n canFlag,\n canMarkUnread,\n canMute,\n canQuote,\n canReact,\n canReply,\n isInitialMessage,\n isMessageThreadReply,\n message.status,\n message.type,\n disable,\n messageActionSet,\n ]);\n};\n", "import { useMemo } from 'react';\n\nimport type { MessageActionSetItem } from '../MessageActions';\n\nexport const useSplitMessageActionSet = (messageActionSet: MessageActionSetItem[]) =>\n useMemo(() => {\n const quickActionSet: MessageActionSetItem[] = [];\n const dropdownActionSet: MessageActionSetItem[] = [];\n\n for (const action of messageActionSet) {\n if (action.placement === 'quick') quickActionSet.push(action);\n if (action.placement === 'dropdown') dropdownActionSet.push(action);\n }\n\n return { dropdownActionSet, quickActionSet };\n }, [messageActionSet]);\n", "/* eslint-disable sort-keys */\nimport React from 'react';\n\nimport { isUserMuted } from '../../components';\nimport { ReactionIcon as DefaultReactionIcon, ThreadIcon } from '../../components/Message/icons';\nimport { ReactionSelectorWithButton } from '../../components/Reactions/ReactionSelectorWithButton';\nimport {\n useChannelActionContext,\n useChatContext,\n useMessageContext,\n useTranslationContext,\n} from '../../context';\n\nimport type { ComponentPropsWithoutRef } from 'react';\n\nimport type { MessageActionSetItem } from './MessageActions';\n\nexport const DefaultDropdownActionButton = ({\n 'aria-selected': ariaSelected = 'false',\n children,\n className = 'str-chat__message-actions-list-item-button',\n role = 'option',\n ...rest\n}: ComponentPropsWithoutRef<'button'>) => (\n <button aria-selected={ariaSelected} className={className} role={role} {...rest}>\n {children}\n </button>\n);\n\nconst DefaultMessageActionComponents = {\n dropdown: {\n Quote() {\n const { setQuotedMessage } = useChannelActionContext();\n const { message } = useMessageContext();\n const { t } = useTranslationContext();\n\n const handleQuote = () => {\n setQuotedMessage(message);\n\n const elements = message.parent_id\n ? document.querySelectorAll('.str-chat__thread .str-chat__textarea__textarea')\n : document.getElementsByClassName('str-chat__textarea__textarea');\n const textarea = elements.item(0);\n\n if (textarea instanceof HTMLTextAreaElement) {\n textarea.focus();\n }\n };\n\n return (\n <DefaultDropdownActionButton onClick={handleQuote}>\n {t<string>('Quote')}\n </DefaultDropdownActionButton>\n );\n },\n Pin() {\n const { handlePin, message } = useMessageContext();\n const { t } = useTranslationContext();\n\n return (\n <DefaultDropdownActionButton onClick={handlePin}>\n {!message.pinned ? t<string>('Pin') : t<string>('Unpin')}\n </DefaultDropdownActionButton>\n );\n },\n MarkUnread() {\n const { handleMarkUnread } = useMessageContext();\n const { t } = useTranslationContext();\n\n return (\n <DefaultDropdownActionButton onClick={handleMarkUnread}>\n {t<string>('Mark as unread')}\n </DefaultDropdownActionButton>\n );\n },\n Flag() {\n const { handleFlag } = useMessageContext();\n const { t } = useTranslationContext();\n\n return (\n <DefaultDropdownActionButton onClick={handleFlag}>\n {t<string>('Flag')}\n </DefaultDropdownActionButton>\n );\n },\n Mute() {\n const { handleMute, message } = useMessageContext();\n const { mutes } = useChatContext();\n const { t } = useTranslationContext();\n\n return (\n <DefaultDropdownActionButton onClick={handleMute}>\n {isUserMuted(message, mutes) ? t<string>('Unmute') : t<string>('Mute')}\n </DefaultDropdownActionButton>\n );\n },\n Edit() {\n const { handleEdit } = useMessageContext();\n const { t } = useTranslationContext();\n\n return (\n <DefaultDropdownActionButton onClick={handleEdit}>\n {t<string>('Edit Message')}\n </DefaultDropdownActionButton>\n );\n },\n Delete() {\n const { handleDelete } = useMessageContext();\n const { t } = useTranslationContext();\n\n return (\n <DefaultDropdownActionButton onClick={handleDelete}>\n {t<string>('Delete')}\n </DefaultDropdownActionButton>\n );\n },\n },\n quick: {\n React() {\n return <ReactionSelectorWithButton ReactionIcon={DefaultReactionIcon} />;\n },\n Reply() {\n const { handleOpenThread } = useMessageContext();\n const { t } = useTranslationContext();\n\n return (\n <button\n aria-label={t('aria/Open Thread')}\n className='str-chat__message-reply-in-thread-button'\n data-testid='thread-action'\n onClick={handleOpenThread}\n >\n <ThreadIcon className='str-chat__message-action-icon' />\n </button>\n );\n },\n },\n};\n\nexport const defaultMessageActionSet: MessageActionSetItem[] = [\n // { placement: 'dropdown', type: 'block' },\n { Component: DefaultMessageActionComponents.quick.Reply, placement: 'quick', type: 'reply' },\n { Component: DefaultMessageActionComponents.quick.React, placement: 'quick', type: 'react' },\n {\n Component: DefaultMessageActionComponents.dropdown.Delete,\n placement: 'dropdown',\n type: 'delete',\n },\n { Component: DefaultMessageActionComponents.dropdown.Edit, placement: 'dropdown', type: 'edit' },\n { Component: DefaultMessageActionComponents.dropdown.Mute, placement: 'dropdown', type: 'mute' },\n { Component: DefaultMessageActionComponents.dropdown.Flag, placement: 'dropdown', type: 'flag' },\n { Component: DefaultMessageActionComponents.dropdown.Pin, placement: 'dropdown', type: 'pin' },\n {\n Component: DefaultMessageActionComponents.dropdown.Quote,\n placement: 'dropdown',\n type: 'quote',\n },\n {\n Component: DefaultMessageActionComponents.dropdown.MarkUnread,\n placement: 'dropdown',\n type: 'markUnread',\n },\n] as const;\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["import_clsx", "import_react", "React", "import_react", "React", "import_react", "React", "import_react", "React", "import_react", "import_react", "import_react", "import_react", "import_react", "React", "React", "import_react", "React", "import_react", "import_dayjs", "Dayjs", "Dayjs", "calendar", "localizedFormat", "React", "import_react", "import_react", "React", "React", "clsx", "import_react", "React", "import_clsx", "import_react", "import_clsx", "import_react", "React", "clsx", "clsx", "React", "import_react", "import_react", "import_clsx", "import_react", "import_react", "import_react", "React", "React", "React", "Avatar", "React", "clsx", "ReactionIcon", "ReactionSelector", "React", "import_react", "import_react", "import_react", "React", "React", "clsx"]
|
|
7
7
|
}
|