stream-chat-react 14.10.0 → 14.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -1
- package/dist/cjs/{useNotificationApi.bf76a16b.js → NotificationList.6abbee1c.js} +4935 -1232
- package/dist/cjs/NotificationList.6abbee1c.js.map +1 -0
- package/dist/cjs/{ReactPlayerWrapper.60a93742.js → ReactPlayerWrapper.a94a0cd1.js} +3 -3
- package/dist/cjs/{ReactPlayerWrapper.60a93742.js.map → ReactPlayerWrapper.a94a0cd1.js.map} +1 -1
- package/dist/cjs/channel-detail.js +263 -200
- package/dist/cjs/channel-detail.js.map +1 -1
- package/dist/cjs/emojis.js +31 -15
- package/dist/cjs/emojis.js.map +1 -1
- package/dist/cjs/index.js +2098 -7648
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/useChannelHeaderOnlineStatus.7e17671e.js +961 -0
- package/dist/cjs/useChannelHeaderOnlineStatus.7e17671e.js.map +1 -0
- package/dist/cjs/useInertWhenHidden.22151beb.js +6426 -0
- package/dist/cjs/useInertWhenHidden.22151beb.js.map +1 -0
- package/dist/es/{useNotificationApi.ed6bff88.mjs → NotificationList.db01a56d.mjs} +4556 -1258
- package/dist/es/NotificationList.db01a56d.mjs.map +1 -0
- package/dist/es/channel-detail.mjs +86 -23
- package/dist/es/channel-detail.mjs.map +1 -1
- package/dist/es/emojis.mjs +25 -8
- package/dist/es/emojis.mjs.map +1 -1
- package/dist/es/index.mjs +1033 -6583
- package/dist/es/index.mjs.map +1 -1
- package/dist/es/useChannelHeaderOnlineStatus.a9357343.mjs +771 -0
- package/dist/es/useChannelHeaderOnlineStatus.a9357343.mjs.map +1 -0
- package/dist/es/useInertWhenHidden.3d5fbdba.mjs +5765 -0
- package/dist/es/useInertWhenHidden.3d5fbdba.mjs.map +1 -0
- package/dist/types/components/Attachment/Geolocation.d.ts.map +1 -1
- package/dist/types/components/Attachment/LinkPreview/Card.d.ts.map +1 -1
- package/dist/types/components/Attachment/LinkPreview/CardAudio.d.ts.map +1 -1
- package/dist/types/components/Attachment/ModalGallery.d.ts.map +1 -1
- package/dist/types/components/Attachment/UnsupportedAttachment.d.ts.map +1 -1
- package/dist/types/components/Attachment/VisibilityDisclaimer.d.ts.map +1 -1
- package/dist/types/components/Attachment/components/DownloadButton.d.ts.map +1 -1
- package/dist/types/components/Avatar/Avatar.d.ts +5 -1
- package/dist/types/components/Avatar/Avatar.d.ts.map +1 -1
- package/dist/types/components/Badge/Badge.d.ts.map +1 -1
- package/dist/types/components/Badge/MediaBadge.d.ts.map +1 -1
- package/dist/types/components/BaseImage/ImagePlaceholder.d.ts.map +1 -1
- package/dist/types/components/Button/PlayButton.d.ts.map +1 -1
- package/dist/types/components/Channel/Channel.d.ts.map +1 -1
- package/dist/types/components/ChannelListItem/ChannelListItem.d.ts.map +1 -1
- package/dist/types/components/ChannelListItem/ChannelListItemActionButtons.defaults.d.ts.map +1 -1
- package/dist/types/components/ChannelListItem/ChannelListItemUI.d.ts.map +1 -1
- package/dist/types/components/ChannelListItem/hooks/useMessageDeliveryStatus.d.ts.map +1 -1
- package/dist/types/components/ChatView/ChatView.d.ts.map +1 -1
- package/dist/types/components/Dialog/components/Callout.d.ts.map +1 -1
- package/dist/types/components/Dialog/components/ContextMenu.d.ts +4 -0
- package/dist/types/components/Dialog/components/ContextMenu.d.ts.map +1 -1
- package/dist/types/components/Dialog/components/Prompt.d.ts.map +1 -1
- package/dist/types/components/Dialog/components/Viewer.d.ts.map +1 -1
- package/dist/types/components/EmptyStateIndicator/EmptyStateIndicator.d.ts.map +1 -1
- package/dist/types/components/Form/NumericInput.d.ts.map +1 -1
- package/dist/types/components/Form/TextInput.d.ts.map +1 -1
- package/dist/types/components/Gallery/GalleryHeader.d.ts.map +1 -1
- package/dist/types/components/Gallery/GalleryUI.d.ts.map +1 -1
- package/dist/types/components/Icons/index.d.ts +1 -0
- package/dist/types/components/Icons/index.d.ts.map +1 -1
- package/dist/types/components/Icons/slots.d.ts +10 -0
- package/dist/types/components/Icons/slots.d.ts.map +1 -0
- package/dist/types/components/Loading/LoadingIndicator.d.ts +2 -2
- package/dist/types/components/Loading/LoadingIndicator.d.ts.map +1 -1
- package/dist/types/components/Location/ShareLocationDialog.d.ts.map +1 -1
- package/dist/types/components/MediaRecorder/AudioRecorder/AudioRecorderRecordingControls.d.ts.map +1 -1
- package/dist/types/components/MediaRecorder/AudioRecorder/AudioRecordingButtonWithNotification.d.ts.map +1 -1
- package/dist/types/components/MediaRecorder/AudioRecorder/AudioRecordingPlayback.d.ts.map +1 -1
- package/dist/types/components/MediaRecorder/AudioRecorder/AudioRecordingPreview.d.ts.map +1 -1
- package/dist/types/components/Message/MessageAlsoSentInChannelIndicator.d.ts.map +1 -1
- package/dist/types/components/Message/MessageDeletedBubble.d.ts.map +1 -1
- package/dist/types/components/Message/MessageStatus.d.ts.map +1 -1
- package/dist/types/components/Message/MessageTranslationIndicator.d.ts.map +1 -1
- package/dist/types/components/Message/PinIndicator.d.ts.map +1 -1
- package/dist/types/components/Message/ReminderNotification.d.ts.map +1 -1
- package/dist/types/components/MessageActions/DownloadSubmenu.d.ts.map +1 -1
- package/dist/types/components/MessageActions/MessageActions.defaults.d.ts.map +1 -1
- package/dist/types/components/MessageActions/RemindMeSubmenu.d.ts.map +1 -1
- package/dist/types/components/MessageBounce/MessageBouncePrompt.d.ts.map +1 -1
- package/dist/types/components/MessageComposer/AttachmentPreviewList/AudioAttachmentPreview.d.ts.map +1 -1
- package/dist/types/components/MessageComposer/AttachmentPreviewList/FileAttachmentPreview.d.ts.map +1 -1
- package/dist/types/components/MessageComposer/AttachmentPreviewList/GeolocationPreview.d.ts.map +1 -1
- package/dist/types/components/MessageComposer/AttachmentPreviewList/MediaAttachmentPreview.d.ts.map +1 -1
- package/dist/types/components/MessageComposer/AttachmentPreviewList/UnsupportedAttachmentPreview.d.ts.map +1 -1
- package/dist/types/components/MessageComposer/AttachmentSelector/AttachmentSelector.d.ts.map +1 -1
- package/dist/types/components/MessageComposer/AttachmentSelector/CommandsMenu.d.ts.map +1 -1
- package/dist/types/components/MessageComposer/CommandChip.d.ts.map +1 -1
- package/dist/types/components/MessageComposer/LinkPreviewList.d.ts.map +1 -1
- package/dist/types/components/MessageComposer/MessageComposer.d.ts +10 -1
- package/dist/types/components/MessageComposer/MessageComposer.d.ts.map +1 -1
- package/dist/types/components/MessageComposer/MessageComposerActions.d.ts.map +1 -1
- package/dist/types/components/MessageComposer/QuotedMessagePreview.d.ts.map +1 -1
- package/dist/types/components/MessageComposer/RemoveAttachmentPreviewButton.d.ts.map +1 -1
- package/dist/types/components/MessageComposer/SendButton.d.ts.map +1 -1
- package/dist/types/components/MessageComposer/SendToChannelCheckbox.d.ts.map +1 -1
- package/dist/types/components/MessageComposer/WithDragAndDropUpload.d.ts.map +1 -1
- package/dist/types/components/MessageComposer/hooks/useMessageComposerCommands.d.ts.map +1 -1
- package/dist/types/components/MessageComposer/hooks/useMessageComposerController.d.ts.map +1 -1
- package/dist/types/components/MessageList/ScrollToLatestMessageButton.d.ts.map +1 -1
- package/dist/types/components/MessageList/UnreadMessagesNotification.d.ts.map +1 -1
- package/dist/types/components/MessageList/UnreadMessagesSeparator.d.ts.map +1 -1
- package/dist/types/components/MessageList/hooks/useMarkRead.d.ts.map +1 -1
- package/dist/types/components/Modal/CloseButtonOnModalOverlay.d.ts.map +1 -1
- package/dist/types/components/Notifications/Notification.d.ts.map +1 -1
- package/dist/types/components/Poll/PollActions/PollResults/PollOptionWithVotesHeader.d.ts.map +1 -1
- package/dist/types/components/Poll/PollCreationDialog/OptionFieldSet.d.ts.map +1 -1
- package/dist/types/components/Poll/PollCreationDialog/PollCreationDialogControls.d.ts.map +1 -1
- package/dist/types/components/Poll/PollCreationDialog/PollOptionReorderHandle.d.ts.map +1 -1
- package/dist/types/components/Reactions/MessageReactionsDetail.d.ts.map +1 -1
- package/dist/types/components/Reactions/ReactionSelector.d.ts.map +1 -1
- package/dist/types/components/Reactions/ReactionSelectorWithButton.d.ts +6 -1
- package/dist/types/components/Reactions/ReactionSelectorWithButton.d.ts.map +1 -1
- package/dist/types/components/SummarizedMessagePreview/SummarizedMessagePreview.d.ts.map +1 -1
- package/dist/types/components/TextareaComposer/SuggestionList/MentionItem/BroadcastMentionItem.d.ts.map +1 -1
- package/dist/types/components/TextareaComposer/SuggestionList/MentionItem/RoleItem.d.ts.map +1 -1
- package/dist/types/components/TextareaComposer/SuggestionList/MentionItem/UserGroupItem.d.ts.map +1 -1
- package/dist/types/components/Thread/ThreadHeader.d.ts.map +1 -1
- package/dist/types/components/Threads/ThreadList/ThreadListEmptyPlaceholder.d.ts.map +1 -1
- package/dist/types/components/Threads/ThreadList/ThreadListUnseenThreadsBanner.d.ts.map +1 -1
- package/dist/types/components/VideoPlayer/VideoThumbnail.d.ts.map +1 -1
- package/dist/types/context/ComponentContext.d.ts +3 -0
- package/dist/types/context/ComponentContext.d.ts.map +1 -1
- package/dist/types/context/WithComponents.d.ts.map +1 -1
- package/dist/types/context/index.d.ts +1 -0
- package/dist/types/context/index.d.ts.map +1 -1
- package/dist/types/context/useComponentContextIcons.d.ts +16 -0
- package/dist/types/context/useComponentContextIcons.d.ts.map +1 -0
- package/dist/types/plugins/ChannelDetail/ChannelDetail.d.ts.map +1 -1
- package/dist/types/plugins/ChannelDetail/ChannelDetailEmptyList.d.ts.map +1 -1
- package/dist/types/plugins/ChannelDetail/ChannelDetailSearchInput.d.ts.map +1 -1
- package/dist/types/plugins/ChannelDetail/SectionNavigator/SectionNavigatorHeader.d.ts.map +1 -1
- package/dist/types/plugins/ChannelDetail/Views/ChannelFilesView/ChannelFilesEmptyList.d.ts.map +1 -1
- package/dist/types/plugins/ChannelDetail/Views/ChannelManagementView/ChannelManagementActions.defaults.d.ts.map +1 -1
- package/dist/types/plugins/ChannelDetail/Views/ChannelManagementView/ChannelManagementView.d.ts.map +1 -1
- package/dist/types/plugins/ChannelDetail/Views/ChannelMediaView/ChannelMediaEmptyList.d.ts.map +1 -1
- package/dist/types/plugins/ChannelDetail/Views/ChannelMediaView/ChannelMediaView.d.ts.map +1 -1
- package/dist/types/plugins/ChannelDetail/Views/ChannelMemberDetailView/ChannelMemberActions.defaults.d.ts.map +1 -1
- package/dist/types/plugins/ChannelDetail/Views/ChannelMembersView/ChannelMembersAddView.d.ts.map +1 -1
- package/dist/types/plugins/ChannelDetail/Views/ChannelMembersView/ChannelMembersBrowseView.d.ts.map +1 -1
- package/dist/types/plugins/ChannelDetail/Views/ChannelMembersView/ChannelMembersHeaderActions.defaults.d.ts.map +1 -1
- package/dist/types/plugins/ChannelDetail/Views/PinnedMessagesView/PinnedMessagesEmptyList.d.ts.map +1 -1
- package/dist/types/plugins/Emojis/EmojiPicker.d.ts +6 -1
- package/dist/types/plugins/Emojis/EmojiPicker.d.ts.map +1 -1
- package/dist/types/plugins/Emojis/Picker.d.ts +7 -0
- package/dist/types/plugins/Emojis/Picker.d.ts.map +1 -0
- package/dist/types/utils/getChannelConfig.d.ts +8 -0
- package/dist/types/utils/getChannelConfig.d.ts.map +1 -0
- package/package.json +3 -9
- package/AI.md +0 -423
- package/dist/cjs/useChannelHeaderOnlineStatus.6ace991c.js +0 -4485
- package/dist/cjs/useChannelHeaderOnlineStatus.6ace991c.js.map +0 -1
- package/dist/cjs/useMessageComposerController.f8f20e3d.js +0 -99
- package/dist/cjs/useMessageComposerController.f8f20e3d.js.map +0 -1
- package/dist/cjs/useNotificationApi.bf76a16b.js.map +0 -1
- package/dist/es/useChannelHeaderOnlineStatus.d6065c22.mjs +0 -3899
- package/dist/es/useChannelHeaderOnlineStatus.d6065c22.mjs.map +0 -1
- package/dist/es/useMessageComposerController.d50f6168.mjs +0 -69
- package/dist/es/useMessageComposerController.d50f6168.mjs.map +0 -1
- package/dist/es/useNotificationApi.ed6bff88.mjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useChannelHeaderOnlineStatus.7e17671e.js","names":[],"sources":["../../src/context/MessageTranslationViewContext.tsx","../../src/utils/useStableCallback.ts","../../src/components/Dialog/components/Alert.tsx","../../src/components/Badge/Badge.tsx","../../src/components/Avatar/ChannelAvatar.tsx","../../src/components/Avatar/GroupAvatar.tsx","../../src/components/Message/renderText/remarkPlugins/htmlToTextPlugin.ts","../../src/components/Message/renderText/remarkPlugins/imageToLink.ts","../../src/components/Message/renderText/remarkPlugins/plusPlusToEmphasis.ts","../../src/components/Form/Checkbox.tsx","../../src/components/ChannelListItem/utils.tsx","../../src/components/ChannelListItem/hooks/useChannelDisplayName.ts","../../src/components/ChannelListItem/hooks/useChannelPreviewInfo.ts","../../src/utils/isDmChannel.ts","../../src/components/ChannelList/hooks/useSelectedChannelState.ts","../../src/components/ChannelList/hooks/useChannelMembershipState.ts","../../src/components/ChannelListItem/hooks/useIsChannelMuted.ts","../../src/components/ChannelListItem/hooks/useIsUserMuted.ts","../../src/components/ChannelHeader/hooks/useChannelHasMembersOnline.ts","../../src/components/ChannelHeader/hooks/useChannelHeaderOnlineStatus.ts"],"sourcesContent":["/**\n * Message translation view context: user-specific state for whether each message\n * shows original text or a translation.\n *\n * ## Spec\n *\n * - **State**: Per message list (channel vs thread), we store a map\n * `messageId → 'original' | 'translated'`. Default for messages with `message.i18n`\n * is `'translated'`; otherwise `'original'`.\n *\n * - **Provider placement**: The provider is tied to the **message list**, not the channel.\n * It is rendered inside `MessageList` and `VirtualizedMessageList`. That way the\n * main channel list and the thread list each have their own translation view state\n * (e.g. Thread.tsx gets correct behavior without sharing channel state).\n *\n * - **Multiple translations**: `message.i18n` can contain multiple languages, e.g.:\n * `{ en_text: \"Good morning\", fr_text: \"Bonjour\", it_text: \"Buongiorno\", language: \"en\" }`.\n * Which translation is shown is determined by the app’s **user language**\n * (`useTranslationContext().userLanguage`). We use `message.i18n[userLanguage + '_text']`;\n * if missing, we fall back to `message.text`. Only one translation is shown at a time.\n *\n * - **Source language**: When present, `message.i18n.language` is the original/source\n * language of `message.text`. It can be used for the indicator label, e.g.\n * \"Translated from English · View original\".\n *\n * - **Invariants**: The original message content, layout, grouping, and order stay\n * unchanged. Removing or toggling translation only changes the annotation and which\n * text is displayed. \"View original\" / \"View translation\" switch the displayed\n * text and update the annotation (e.g. \"Original · View translation\" when showing\n * original).\n *\n * - **Translation indicator visibility**: The translation indicator (e.g. \"Translated ·\n * View original\") is **not** shown when the currently viewed text already corresponds\n * to `userLanguage` — for example when viewing original and the original text is the\n * user-language version (i.e. `getTranslatedMessageText({ language: userLanguage, message })`\n * equals `message.text`). In that case there is no meaningful original/translated choice,\n * so the indicator is hidden.\n */\n\nimport React, { createContext, useCallback, useContext, useState } from 'react';\nimport type { LocalMessage, TranslationLanguages } from 'stream-chat';\n\n/**\n * Returns the translated message text for a given language from `message.i18n`, or\n * undefined if not present. Used to resolve which of the multiple translations to show.\n */\nexport const getTranslatedMessageText = ({\n language,\n message,\n}: {\n language: string;\n message?: LocalMessage;\n}): string | undefined =>\n message?.i18n?.[`${language}_text` as `${TranslationLanguages}_text`];\n\n/**\n * Which message text to show.\n * - `'original'`: `message.text` (source language).\n * - `'translated'`: translation for the **current user language** (TranslationContext’s\n * `userLanguage`), i.e. `getTranslatedMessageText({ language: userLanguage, message })`\n * or fallback to `message.text`.\n */\nexport type TranslationView = 'original' | 'translated';\n\nexport type MessageTranslationViewContextValue = {\n getTranslationView: (messageId: string, hasI18n: boolean) => TranslationView;\n setTranslationView: (messageId: string, view: TranslationView) => void;\n};\n\nconst defaultContextValue: MessageTranslationViewContextValue = {\n getTranslationView: (_messageId, hasI18n) => (hasI18n ? 'translated' : 'original'),\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n setTranslationView: () => {},\n};\n\nexport const MessageTranslationViewContext =\n createContext<MessageTranslationViewContextValue>(defaultContextValue);\n\nexport const MessageTranslationViewProvider = ({\n children,\n}: {\n children: React.ReactNode;\n}) => {\n const [viewByMessageId, setViewByMessageId] = useState<Record<string, TranslationView>>(\n {},\n );\n\n const setTranslationView = useCallback((messageId: string, view: TranslationView) => {\n setViewByMessageId((prev) => ({ ...prev, [messageId]: view }));\n }, []);\n\n const getTranslationView = useCallback(\n (messageId: string, hasI18n: boolean): TranslationView =>\n viewByMessageId[messageId] ?? (hasI18n ? 'translated' : 'original'),\n [viewByMessageId],\n );\n\n const stableValue = React.useMemo(\n () => ({ getTranslationView, setTranslationView }),\n [getTranslationView, setTranslationView],\n );\n\n return (\n <MessageTranslationViewContext.Provider value={stableValue}>\n {children}\n </MessageTranslationViewContext.Provider>\n );\n};\n\nexport const useMessageTranslationViewContext =\n (): MessageTranslationViewContextValue => {\n const context = useContext(MessageTranslationViewContext);\n return context ?? defaultContextValue;\n };\n","import { useCallback, useRef } from 'react';\n\nexport type StableCallback<A extends unknown[], R> = (...args: A) => R;\n\n/**\n * A utility hook implementing a stable callback. It takes in an unstable method that\n * is supposed to be invoked somewhere deeper in the DOM tree without making it\n * change its reference every time the parent component rerenders. It will also return\n * the value of the callback if it does return one.\n * A common use-case would be having a function whose invocation depends on state\n * somewhere high up in the DOM tree and wanting to use the same function deeper\n * down, for example in a leaf node and simply using useCallback results in\n * cascading dependency hell. If we wrap it in useStableCallback, we would be able\n * to:\n * - Use the same function as a dependency of another hook (since it is stable)\n * - Still invoke it and get the latest state\n *\n * **Caveats:**\n * - Never wrap a function that is supposed to return a React.ReactElement in\n * useStableCallback, since React will not know that the DOM needs to be updated\n * whenever the callback value changes (for example, renderItem from FlatList must\n * never be wrapped in this hook)\n * - Always prefer using a standard useCallback/stable function wherever possible\n * (the purpose of useStableCallback is to bridge the gap between top level contexts\n * and cascading rereders in downstream components - **not** as an escape hatch)\n * @param callback - the callback we want to stabilize\n */\nexport const useStableCallback = <A extends unknown[], R>(\n callback: StableCallback<A, R>,\n): StableCallback<A, R> => {\n const ref = useRef(callback);\n ref.current = callback;\n\n return useCallback<StableCallback<A, R>>((...args) => ref.current(...args), []);\n};\n","import React, { type ComponentProps, type ComponentType, forwardRef } from 'react';\nimport clsx from 'clsx';\nimport { useModalContext } from '../../../context';\nimport { useAriaIdentifiers } from '../../../a11y/hooks/useAriaIdentifiers';\n\nexport const Root = forwardRef<HTMLDivElement, ComponentProps<'div'>>(function AlertRoot(\n { children, className, ...props }: ComponentProps<'div'>,\n ref,\n) {\n return (\n <div {...props} className={clsx('str-chat__alert-root', className)} ref={ref}>\n {children}\n </div>\n );\n});\n\nexport type AlertHeaderProps = ComponentProps<'div'> & {\n description?: string;\n descriptionId?: string;\n Icon?: ComponentType;\n title?: string;\n titleId?: string;\n};\n\nexport const Header = forwardRef<HTMLDivElement, AlertHeaderProps>(function AlertHeader(\n { children, className, description, descriptionId, Icon, title, titleId, ...props },\n ref,\n) {\n const { dialogId } = useModalContext();\n const { descriptionId: derivedDescriptionId, titleId: derivedTitleId } =\n useAriaIdentifiers(dialogId);\n const resolvedTitleId = titleId ?? derivedTitleId;\n const resolvedDescriptionId = descriptionId ?? derivedDescriptionId;\n\n return (\n <div {...props} className={clsx('str-chat__alert-header', className)} ref={ref}>\n {title ? (\n <>\n {Icon && <Icon />}\n <div className='str-chat__alert-header__copy'>\n <h2 className='str-chat__alert-header__title' id={resolvedTitleId}>\n {title}\n </h2>\n {description && (\n <p\n className='str-chat__alert-header__description'\n id={resolvedDescriptionId}\n >\n {description}\n </p>\n )}\n </div>\n </>\n ) : (\n children\n )}\n </div>\n );\n});\n\nconst Actions = forwardRef<HTMLDivElement, ComponentProps<'div'>>(function AlertActions(\n { children, className, ...props },\n ref,\n) {\n return (\n <div {...props} className={clsx('str-chat__alert-actions', className)} ref={ref}>\n {children}\n </div>\n );\n});\n\nexport const Alert = {\n Actions,\n Header,\n Root,\n};\n","import clsx from 'clsx';\nimport React, { type ComponentProps } from 'react';\nimport { useComponentContextIcons } from '../../context';\n\nexport type BadgeVariant =\n | 'default'\n | 'primary'\n | 'error'\n | 'neutral'\n | 'counter'\n | 'inverse';\n\nexport type BadgeSize = 'xs' | 'sm' | 'md' | 'lg' | null;\n\nexport type BadgeProps = ComponentProps<'div'> & {\n /** Visual variant mapping to design tokens */\n variant?: BadgeVariant;\n /** Size preset (typography and padding) */\n size?: BadgeSize;\n};\n\n/**\n * Compact pill/circle badge for counts and labels.\n * Uses design tokens: --badge-bg-*, --badge-text-*, --badge-border.\n */\nexport const Badge = ({\n children,\n className,\n size = 'md',\n variant = 'default',\n ...spanProps\n}: BadgeProps) => (\n <div\n {...spanProps}\n className={clsx(\n 'str-chat__badge',\n `str-chat__badge--variant-${variant}`,\n { [`str-chat__badge--size-${size}`]: size },\n className,\n )}\n >\n {children}\n </div>\n);\n\nexport const ErrorBadge = ({\n className,\n size = 'sm',\n ...rest\n}: Omit<BadgeProps, 'variant'>) => {\n const { IconExclamationMarkFill } = useComponentContextIcons();\n return (\n <Badge {...rest} className={className} size={size} variant='error'>\n <IconExclamationMarkFill />\n </Badge>\n );\n};\n","import React, { useMemo } from 'react';\n\nimport { GroupAvatar } from './';\nimport type { AvatarProps, GroupAvatarProps } from './';\n\nexport type ChannelAvatarProps = Partial<Omit<GroupAvatarProps & AvatarProps, 'size'>> & {\n size: GroupAvatarProps['size'] | AvatarProps['size'];\n};\n\nexport const ChannelAvatar = ({\n displayMembers,\n imageUrl,\n size,\n userName,\n ...sharedProps\n}: ChannelAvatarProps) => {\n const displayInfo = useMemo(() => {\n // Prefer the channel's own image; only derive the avatar from members when\n // there is no channel imageUrl to display.\n if (!imageUrl && displayMembers && displayMembers.length > 0) {\n return displayMembers;\n }\n\n return [\n {\n imageUrl,\n userName,\n },\n ];\n }, [displayMembers, imageUrl, userName]);\n\n return <GroupAvatar displayMembers={displayInfo} size={size} {...sharedProps} />;\n};\n","import clsx from 'clsx';\nimport React, { type ComponentPropsWithoutRef, useMemo } from 'react';\nimport { Avatar, type AvatarProps } from './Avatar';\nimport { Badge, type BadgeSize } from '../Badge';\n\nexport type GroupAvatarMember = {\n imageUrl?: string;\n userName?: string;\n id?: string;\n};\n\nexport type GroupAvatarProps = {\n /** List of members to show as avatars; at most 2 when there's more than 4 members, otherwise 4. Defaults to [] when omitted. */\n displayMembers?: GroupAvatarMember[];\n size: '2xl' | 'xl' | 'lg' | (string & {}) | null;\n badgeSize?: BadgeSize;\n isOnline?: boolean;\n} & ComponentPropsWithoutRef<'div'>;\n\n/**\n * Avatar component to display multiple users' avatars in a group.\n * Renders a single Avatar if fewer than 2 members. Otherwise, renders up to 2 avatars (when overflowCount is set) or 4, plus an optional +N badge.\n */\nexport const GroupAvatar = ({\n badgeSize,\n className,\n displayMembers = [],\n isOnline,\n size,\n ...rest\n}: GroupAvatarProps) => {\n const displayMembersToRender = useMemo(\n () => (displayMembers.length > 4 ? displayMembers.slice(0, 2) : displayMembers),\n [displayMembers],\n );\n const overflowCount = displayMembers.length - displayMembersToRender.length;\n\n if (displayMembers.length < 2) {\n const firstUser = displayMembers[0];\n\n return (\n <Avatar\n imageUrl={firstUser?.imageUrl}\n isOnline={isOnline}\n size={size}\n userName={firstUser?.userName}\n {...rest}\n />\n );\n }\n\n let avatarSize: AvatarProps['size'] = null;\n if (size === '2xl') {\n avatarSize = 'lg';\n } else if (size === 'xl') {\n avatarSize = 'md';\n } else if (size === 'lg') {\n avatarSize = 'sm';\n }\n\n return (\n <div\n className={clsx(\n 'str-chat__avatar-group',\n {\n 'str-chat__avatar-group--offline': typeof isOnline === 'boolean' && !isOnline,\n 'str-chat__avatar-group--online': typeof isOnline === 'boolean' && isOnline,\n [`str-chat__avatar-group--size-${size}`]: typeof size === 'string',\n },\n className,\n )}\n data-testid='group-avatar'\n role='button'\n {...rest}\n >\n {displayMembersToRender.map(({ id, imageUrl, userName }, index) => (\n <Avatar\n imageUrl={imageUrl}\n key={id || `${userName}-${imageUrl}-${index}`}\n size={avatarSize}\n userName={userName}\n />\n ))}\n {typeof overflowCount === 'number' && overflowCount > 0 && (\n <Badge\n className='str-chat__avatar-group__count-badge'\n data-testid='group-avatar-count-badge'\n size={badgeSize}\n variant='counter'\n >\n +{overflowCount}\n </Badge>\n )}\n </div>\n );\n};\n","import type { Visitor } from 'unist-util-visit';\nimport { visit } from 'unist-util-visit';\n\n// `Nodes` is not part of hast-util-find-and-replace's public surface; derive\n// the visit-compatible tree type from `visit` itself.\ntype Nodes = Parameters<typeof visit>[0];\n\nconst visitor: Visitor = (node) => {\n if (node.type !== 'html') return;\n\n node.type = 'text';\n};\nconst transform = (tree: Nodes) => {\n visit(tree, visitor);\n};\n\nexport const htmlToTextPlugin = () => transform;\n","import { SKIP, visit, type VisitorResult } from 'unist-util-visit';\nimport type { Image, Link, Parent, Text } from 'mdast';\nimport type { Node } from 'unist';\n\ntype ImgVisitor = (\n node: Image,\n index: number | null,\n parent: Parent | null,\n) => VisitorResult;\n\nexport type ImageToLinkPluginOptions = {\n getTextLabelFrom?: 'alt' | 'title' | 'url';\n};\n\nconst text = (value: string): Text => ({ type: 'text', value });\n\n/**\n * Converts image Markdown links ()\n * to HTML <a href={url}>{url | title | alt}</a>\n *\n * By default, the anchor text content is the image url so that image preview can be generated / enriched on the server.\n * @param getTextLabelFrom\n */\nexport function imageToLink({ getTextLabelFrom = 'url' }: ImageToLinkPluginOptions = {}) {\n return (tree: Node) => {\n const visitor: ImgVisitor = (node, index, parent) => {\n if (parent == null || index == null) return;\n\n const label = node[getTextLabelFrom] ?? node.url; // node.alt || node.title || node.url;\n const link: Link = {\n children: [text(label)],\n title: node.title ?? node.alt ?? node.url,\n type: 'link',\n url: node.url,\n };\n\n parent.children.splice(index, 1, link);\n return [SKIP, index + 1] as const;\n };\n\n visit(tree, 'image', visitor);\n };\n}\n","// remark-plusplus-ins.ts\nimport type { Plugin } from 'unified';\nimport { SKIP, visit } from 'unist-util-visit';\nimport type { Visitor } from 'unist-util-visit';\nimport type { Parent, PhrasingContent, Text } from 'mdast';\n\n/**\n * \\S → first char must be non-whitespace\n * (?:...)?→ optional middle+closing when length > 1\n * [\\s\\S]*?→ anything (including newlines), lazy\n * final \\S→ last char non-whitespace (only required when there’s more than 1)\n *\n * Matches:\n * ++a++\n * Does not match:\n * ++++\n * ++ ++\n */\nconst INS_REGEX = /\\+\\+(\\S(?:[\\s\\S]*?\\S)?)\\+\\+/g;\nconst IGNORE_NODE_TYPES = new Set([\n 'code',\n 'inlineCode',\n 'link',\n 'linkReference',\n 'definition',\n 'math',\n 'inlineMath',\n]);\n\n/**\n * Converts MD \"++Some text++\" to inserted text element rendered in HTML as <ins>Some text</ins>\n * https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/ins\n */\nexport const plusPlusToEmphasis: Plugin<[]> = () => {\n const visitor: Visitor = (node, index, parent) => {\n // 1) Don’t traverse inside ignored nodes\n if (IGNORE_NODE_TYPES.has(node.type)) return SKIP;\n\n // 2) Only transform text nodes with a valid parent + index\n if (node.type !== 'text' || parent == null || typeof index !== 'number') return;\n\n const value = (node as Text).value;\n\n // Reset lastIndex to 0 per node so each node is scanned from the beginning\n INS_REGEX.lastIndex = 0;\n\n let match: RegExpExecArray | null;\n let last = 0;\n const out: PhrasingContent[] = [];\n\n while ((match = INS_REGEX.exec(value))) {\n const [full, inner] = match;\n const start = match.index;\n\n if (start > last) out.push({ type: 'text', value: value.slice(last, start) });\n\n // Render as <ins>…</ins> (remark-rehype respects data.hName)\n out.push({\n children: [{ type: 'text', value: inner }],\n data: { hName: 'ins' },\n type: 'emphasis',\n });\n\n last = start + full.length;\n }\n\n if (out.length === 0) return; // nothing to change\n if (last < value.length) out.push({ type: 'text', value: value.slice(last) });\n\n (parent as Parent).children.splice(index, 1, ...out);\n\n // Skip re-visiting the replaced range; continue after inserted nodes\n return [SKIP, index + out.length];\n };\n\n return (tree) => visit(tree, visitor);\n};\n","import clsx from 'clsx';\nimport type { HTMLAttributes } from 'react';\n\nexport type CheckboxProps = HTMLAttributes<HTMLElement> & { checked?: boolean };\n\nexport const Checkbox = ({ checked, ...props }: CheckboxProps) => (\n <div\n {...props}\n className={clsx('str-chat__checkmark str-chat__checkbox', {\n 'str-chat__checkbox--checked': checked,\n 'str-chat__checkmark--checked': checked,\n })}\n />\n);\n\n// fixme: remove str-chat__checkmark class with next major release v15\nexport type CheckmarkProps = CheckboxProps;\n// fixme: remove str-chat__checkmark class with next major release v15\nexport const Checkmark = Checkbox;\n","import type { ReactNode } from 'react';\nimport React from 'react';\nimport ReactMarkdown from 'react-markdown';\nimport type { Channel, LocalMessage, PollVote } from 'stream-chat';\nimport { toString as mdastToString } from 'mdast-util-to-string';\nimport remarkParse from 'remark-parse';\nimport { unified } from 'unified';\n\nimport type { ChatContextValue } from '../../context';\nimport { getTranslatedMessageText } from '../../context/MessageTranslationViewContext';\nimport type { TranslationContextValue } from '../../context/TranslationContext';\nimport type { PluggableList } from 'unified';\nimport { htmlToTextPlugin, imageToLink, plusPlusToEmphasis } from '../Message';\nimport { isMessageDeleted } from '../Message/utils';\nimport remarkGfm from 'remark-gfm';\nimport { extractDisplayInfo } from '../Avatar/utils';\n\nconst remarkPlugins: PluggableList = [\n htmlToTextPlugin,\n [remarkGfm, { singleTilde: false }],\n plusPlusToEmphasis,\n imageToLink,\n];\n\nexport const renderPreviewText = (text: string) => (\n <ReactMarkdown remarkPlugins={remarkPlugins} skipHtml>\n {text}\n </ReactMarkdown>\n);\n\n// Strips markdown to plain text for screen-reader announcements, using the SAME remark plugins as\n// the visible preview so the announced text matches what is shown (e.g. \"**hi**\" -> \"hi\"). The\n// processor is built lazily (not at module load) so importing this file never evaluates\n// `remarkPlugins` — mirroring `renderPreviewText`, and avoiding import-time failures in test files\n// that mock the plugin modules. Falls back to the raw text if processing throws.\nconst createPlainTextProcessor = () => unified().use(remarkParse).use(remarkPlugins);\nlet plainTextProcessor: ReturnType<typeof createPlainTextProcessor> | undefined;\n\nconst stripMarkdownToText = (text: string): string => {\n try {\n const processor = (plainTextProcessor ??= createPlainTextProcessor());\n return mdastToString(processor.runSync(processor.parse(text))) || text;\n } catch {\n return text;\n }\n};\n\nconst getLatestPollVote = (latestVotesByOption: Record<string, PollVote[]>) => {\n let latestVote: PollVote | undefined;\n for (const optionVotes of Object.values(latestVotesByOption)) {\n optionVotes.forEach((vote) => {\n if (latestVote && new Date(latestVote.updated_at) >= new Date(vote.created_at))\n return;\n latestVote = vote;\n });\n }\n\n return latestVote;\n};\n\ntype LatestMessagePreviewKind =\n | 'attachment'\n | 'command'\n | 'deleted'\n | 'empty'\n | 'location'\n | 'poll'\n | 'text';\n\ntype LatestMessagePreviewParts = {\n /**\n * True only for the plain user-message-text branch — the one the display variant renders as\n * markdown (unless AI-generated). Every other branch (deleted/poll/attachment/etc.) is a\n * localized phrase used verbatim.\n */\n isUserMessageText: boolean;\n /** What the latest message is, so consumers can phrase it (display vs. announcement) differently. */\n kind: LatestMessagePreviewKind;\n latestMessage?: LocalMessage;\n /** Poll question, for the `poll` kind. */\n pollName?: string;\n /** The localized DISPLAY preview as a plain string. */\n text: string;\n};\n\n/**\n * Resolves the channel's latest-message preview once: the localized DISPLAY string, a `kind`\n * discriminant, and the bits announcements need (poll question, attachment type). Single source of\n * truth for the display variant ({@link getLatestMessagePreview}) and the announcement variant\n * ({@link getLatestMessagePreviewText}), so the translation lookup and branching run once per call.\n */\nconst getLatestMessagePreviewParts = (\n channel: Channel,\n t: TranslationContextValue['t'],\n userLanguage: TranslationContextValue['userLanguage'] = 'en',\n latestMessageArg?: LocalMessage,\n): LatestMessagePreviewParts => {\n // Prefer an explicitly supplied message so the preview stays consistent with the sender/status/\n // time a caller derives from the same message; fall back to the channel's latest.\n const latestMessage =\n latestMessageArg ??\n channel.state.latestMessages[channel.state.latestMessages.length - 1];\n\n const previewTextToRender =\n getTranslatedMessageText({ language: userLanguage, message: latestMessage }) ||\n latestMessage?.text;\n const poll = latestMessage?.poll;\n\n if (!latestMessage) {\n return {\n isUserMessageText: false,\n kind: 'empty',\n latestMessage,\n text: t('Nothing yet...'),\n };\n }\n\n if (isMessageDeleted(latestMessage)) {\n return {\n isUserMessageText: false,\n kind: 'deleted',\n latestMessage,\n text: t('Message deleted'),\n };\n }\n\n if (poll) {\n if (!poll.vote_count) {\n const createdBy =\n poll.created_by?.id === channel.getClient().userID\n ? t('You')\n : (poll.created_by?.name ?? t('Poll'));\n return {\n isUserMessageText: false,\n kind: 'poll',\n latestMessage,\n pollName: poll.name,\n text: t('📊 {{createdBy}} created: {{ pollName}}', {\n createdBy,\n pollName: poll.name,\n }),\n };\n } else {\n const latestVote = getLatestPollVote(\n poll.latest_votes_by_option as Record<string, PollVote[]>,\n );\n const option =\n latestVote && poll.options.find((opt) => opt.id === latestVote.option_id);\n\n if (option && latestVote) {\n return {\n isUserMessageText: false,\n kind: 'poll',\n latestMessage,\n pollName: poll.name,\n text: t('📊 {{votedBy}} voted: {{pollOptionText}}', {\n pollOptionText: option.text,\n votedBy:\n latestVote?.user?.id === channel.getClient().userID\n ? t('You')\n : (latestVote.user?.name ?? t('Poll')),\n }),\n };\n }\n }\n }\n\n if (previewTextToRender) {\n return {\n isUserMessageText: true,\n kind: 'text',\n latestMessage,\n text: previewTextToRender,\n };\n }\n\n if (latestMessage.command) {\n return {\n isUserMessageText: false,\n kind: 'command',\n latestMessage,\n text: `/${latestMessage.command}`,\n };\n }\n\n if (latestMessage.attachments?.length) {\n return {\n isUserMessageText: false,\n kind: 'attachment',\n latestMessage,\n text: t('🏙 Attachment...'),\n };\n }\n\n if (latestMessage.shared_location) {\n return {\n isUserMessageText: false,\n kind: 'location',\n latestMessage,\n text: t('📍Shared location'),\n };\n }\n\n return {\n isUserMessageText: false,\n kind: 'text',\n latestMessage,\n text: t('Empty message...'),\n };\n};\n\n/**\n * Maps a known attachment `type` to a localized, human-readable word (e.g. \"image\" → \"Image\"). The\n * cases are literal `t('aria/…')` calls so `i18next-cli` extracts them. Unknown/custom types return\n * `undefined`, so the announcement falls back to a generic \"Attachment\".\n */\nconst getAttachmentTypeLabel = (\n type: string | undefined,\n t: TranslationContextValue['t'],\n): string | undefined => {\n switch (type) {\n case 'audio':\n return t('aria/audio');\n case 'file':\n return t('aria/file');\n case 'giphy':\n return t('aria/GIF');\n case 'image':\n return t('aria/image');\n case 'video':\n return t('aria/video');\n case 'voiceRecording':\n return t('aria/voice message');\n default:\n return undefined;\n }\n};\n\n/**\n * The text announced for the channel's latest message (for an accessible name / live region).\n * Non-text content gets a concise, screen-reader-friendly phrasing that may differ from the visible\n * preview: a poll announces its question, an attachment its type, a shared location and a deleted\n * message a plain phrase. User-message text is stripped of markdown so the words are read, not the\n * syntax (AI-generated text is returned verbatim, matching the display path).\n */\nexport const getLatestMessagePreviewText = (\n channel: Channel,\n t: TranslationContextValue['t'],\n userLanguage: TranslationContextValue['userLanguage'] = 'en',\n isMessageAIGenerated?: ChatContextValue['isMessageAIGenerated'],\n latestMessage?: LocalMessage,\n): string => {\n const {\n isUserMessageText,\n kind,\n latestMessage: resolvedLatestMessage,\n pollName,\n text,\n } = getLatestMessagePreviewParts(channel, t, userLanguage, latestMessage);\n\n switch (kind) {\n case 'poll':\n return t('aria/Poll: {{ pollName }}', { pollName: pollName ?? '' });\n case 'attachment': {\n // Link previews are announced separately (see the `linkPreview` label part); decide by the\n // count of real attachments. Multiple → a generic phrase (the count is announced alongside);\n // a single one → its localized type.\n const realAttachments =\n resolvedLatestMessage?.attachments?.filter(\n (attachment) => !attachment.og_scrape_url,\n ) ?? [];\n if (realAttachments.length > 1) return t('aria/Message with attachments');\n const typeLabel = getAttachmentTypeLabel(realAttachments[0]?.type, t);\n return typeLabel\n ? t('aria/Attachment {{ attachmentType }}', { attachmentType: typeLabel })\n : t('aria/Attachment');\n }\n case 'location':\n return t('aria/Shared location');\n case 'empty':\n // The visible preview says \"Nothing yet...\"; spell it out for assistive tech.\n return t('aria/There are no messages in this chat.');\n case 'text':\n // `resolvedLatestMessage` guard is redundant at runtime (isUserMessageText implies it) but\n // narrows the optional type for `isMessageAIGenerated`.\n return isUserMessageText &&\n resolvedLatestMessage &&\n !isMessageAIGenerated?.(resolvedLatestMessage)\n ? stripMarkdownToText(text)\n : text;\n default:\n // 'deleted' (\"Message deleted\") and 'command' (\"/cmd\") read as-is.\n return text;\n }\n};\n\nexport const getLatestMessagePreview = (\n channel: Channel,\n t: TranslationContextValue['t'],\n userLanguage: TranslationContextValue['userLanguage'] = 'en',\n isMessageAIGenerated?: ChatContextValue['isMessageAIGenerated'],\n latestMessage?: LocalMessage,\n): ReactNode => {\n const {\n isUserMessageText,\n latestMessage: resolvedLatestMessage,\n text,\n } = getLatestMessagePreviewParts(channel, t, userLanguage, latestMessage);\n\n // Only the plain user-message text is rendered as markdown — unless it is AI-generated, which is\n // returned verbatim. Every other branch is a localized phrase used as-is. (guard is redundant at\n // runtime but narrows the optional type for `isMessageAIGenerated`.)\n return isUserMessageText &&\n resolvedLatestMessage &&\n !isMessageAIGenerated?.(resolvedLatestMessage)\n ? renderPreviewText(text)\n : text;\n};\n\nexport type GroupChannelDisplayInfoMember = {\n imageUrl?: string;\n userName?: string;\n};\n\nexport type GroupChannelDisplayInfo = {\n members: GroupChannelDisplayInfoMember[];\n /** When members.length > 4, count for the \"+N\" badge (members.length - 2). */\n overflowCount?: number;\n};\n\n/**\n * Channel display image: channel.data.image, or for DM (2 members) the other member's user.image.\n */\nexport const getChannelDisplayImage = (\n channel: Channel,\n currentUserId?: string,\n): string | undefined => {\n const data = channel.data as { image?: string } | undefined;\n if (data?.image && typeof data.image === 'string') return data.image;\n\n const memberList = Object.values(channel.state.members);\n if (memberList.length === 2) {\n const other = memberList.find((m) => m.user?.id !== currentUserId);\n const image = other?.user?.image;\n if (image && typeof image === 'string') return image;\n }\n return undefined;\n};\n\nexport const getGroupChannelDisplayInfo = (\n channel: Channel,\n): GroupChannelDisplayInfo | undefined => {\n const members = Object.values(channel.state.members);\n if (members.length <= 2) return;\n\n const memberList: GroupChannelDisplayInfoMember[] = [];\n for (const member of members) {\n const { user } = member;\n\n if (!user?.name && !user?.image) continue;\n\n memberList.push(extractDisplayInfo(member));\n }\n return {\n members: memberList,\n };\n};\n","import { useEffect, useState } from 'react';\nimport type { Channel } from 'stream-chat';\n\nimport { useChatContext } from '../../../context';\nimport { useTranslationContext } from '../../../context/TranslationContext';\n\n/**\n * 1. channel.data.name\n * 2. DM (exactly 2 members): other member's name, then directMessageLabel\n * 3. Group (3+ members): comma-separated list of 2 other members' names (no ellipsis)\n * 4. undefined otherwise\n */\nfunction computeChannelDisplayName(\n channel: Channel,\n directMessageLabel: string,\n currentUserId: string | undefined,\n): string | undefined {\n const data = channel.data as { name?: string } | undefined;\n if (data?.name && typeof data.name === 'string') return data.name;\n\n const memberList = Object.values(channel.state.members);\n const otherMembers = memberList.filter((m) => m.user?.id !== currentUserId);\n\n if (memberList.length === 2 && otherMembers.length === 1) {\n const name = otherMembers[0].user?.name;\n return name || directMessageLabel;\n }\n if (otherMembers.length >= 2) {\n const names = otherMembers\n .map((m) => m.user?.name)\n .filter(Boolean)\n .slice(0, 2) as string[];\n if (names.length > 0) return names.join(', ');\n }\n return undefined;\n}\n\n/**\n * Channel display name with translation context.\n * 1. channel.data.name\n * 2. DM (exactly 2 members): other member's name, then translated \"Direct message\"\n * 3. Group (3+ members): comma-separated list of 2 other members' names (no ellipsis)\n * 4. undefined otherwise\n */\nexport const useChannelDisplayName = (\n channel: Channel | undefined,\n): string | undefined => {\n const { client } = useChatContext('useChannelDisplayName');\n const { t } = useTranslationContext('useChannelDisplayName');\n const directMessageLabel = t('Direct message');\n\n const [displayName, setDisplayName] = useState<string | undefined>(() =>\n channel\n ? computeChannelDisplayName(channel, directMessageLabel, client.userID ?? undefined)\n : undefined,\n );\n\n useEffect(() => {\n if (!channel) {\n setDisplayName(undefined);\n return;\n }\n const updateDisplayName = () =>\n setDisplayName(\n computeChannelDisplayName(\n channel,\n directMessageLabel,\n client.userID ?? undefined,\n ),\n );\n updateDisplayName();\n client.on('user.updated', updateDisplayName);\n return () => {\n client.off('user.updated', updateDisplayName);\n };\n }, [channel, channel?.data, client, directMessageLabel]);\n\n return displayName;\n};\n","import { useEffect, useMemo, useState } from 'react';\nimport type { Channel } from 'stream-chat';\n\nimport { useChatContext } from '../../../context';\nimport {\n getChannelDisplayImage,\n getGroupChannelDisplayInfo,\n type GroupChannelDisplayInfo,\n} from '../utils';\nimport { useChannelDisplayName } from './useChannelDisplayName';\n\nconst emptyGroupInfo: GroupChannelDisplayInfo = {\n members: [],\n overflowCount: undefined,\n};\n\nexport type ChannelPreviewInfoParams = {\n /** Channel to read display info from; when undefined, returns undefined display title/image */\n channel?: Channel;\n /** Manually set the image to render, defaults to the Channel image */\n overrideImage?: string;\n /** Set title manually */\n overrideTitle?: string;\n};\n\nexport const useChannelPreviewInfo = (props: ChannelPreviewInfoParams) => {\n const { channel, overrideImage, overrideTitle } = props;\n const { client } = useChatContext();\n\n const channelDisplayName = useChannelDisplayName(channel);\n const displayTitle = overrideTitle ?? channelDisplayName;\n\n const [displayImage, setDisplayImage] = useState<string | undefined>(() =>\n channel\n ? (overrideImage ?? getChannelDisplayImage(channel, client.userID ?? undefined))\n : undefined,\n );\n const [groupChannelDisplayInfo, setGroupChannelDisplayInfo] =\n useState<GroupChannelDisplayInfo>(() =>\n channel ? (getGroupChannelDisplayInfo(channel) ?? emptyGroupInfo) : emptyGroupInfo,\n );\n\n useEffect(() => {\n if (!channel) return;\n if (overrideImage) return;\n\n const updateInfo = () => {\n setDisplayImage(getChannelDisplayImage(channel, client.userID ?? undefined));\n setGroupChannelDisplayInfo(getGroupChannelDisplayInfo(channel) ?? emptyGroupInfo);\n };\n\n updateInfo();\n const { unsubscribe: unsubscribeChannelUpdated } = channel.on(\n 'channel.updated',\n updateInfo,\n );\n const { unsubscribe: unsubscribeUserUpdated } = client.on('user.updated', updateInfo);\n return () => {\n unsubscribeChannelUpdated();\n unsubscribeUserUpdated();\n };\n }, [channel, channel?.data, client, overrideImage]);\n\n return useMemo(\n () => ({\n displayImage: overrideImage ?? displayImage,\n displayTitle,\n groupChannelDisplayInfo,\n }),\n [displayImage, displayTitle, groupChannelDisplayInfo, overrideImage],\n );\n};\n","import type { Channel } from 'stream-chat';\n\nexport const isDmChannel = ({\n channel,\n ownUserId,\n}: {\n channel: Channel;\n ownUserId?: string;\n}) => {\n const memberCount = channel.data?.member_count ?? 0;\n return (\n memberCount === 1 ||\n (memberCount === 2 &&\n !!ownUserId &&\n Object.values(channel.state?.members ?? {}).some(\n ({ user }) => user?.id === ownUserId,\n ))\n );\n};\n","import { useCallback } from 'react';\nimport { useSyncExternalStore } from 'use-sync-external-store/shim';\nimport type { Channel, EventTypes } from 'stream-chat';\n\n// eslint-disable-next-line @typescript-eslint/no-empty-function\nconst noop = () => {};\n\nexport function useSelectedChannelState<O>(_: {\n channel: Channel;\n selector: (channel: Channel) => O;\n stateChangeEventKeys?: EventTypes[];\n}): O;\nexport function useSelectedChannelState<O>(_: {\n selector: (channel: Channel) => O;\n channel?: Channel | undefined;\n stateChangeEventKeys?: EventTypes[];\n}): O | undefined;\nexport function useSelectedChannelState<O>({\n channel,\n selector,\n stateChangeEventKeys = ['all'],\n}: {\n selector: (channel: Channel) => O;\n channel?: Channel;\n stateChangeEventKeys?: EventTypes[];\n}): O | undefined {\n const subscribe = useCallback(\n (onStoreChange: (value: O) => void) => {\n if (!channel) return noop;\n\n const subscriptions = stateChangeEventKeys.map((et) =>\n channel.on(et, () => {\n onStoreChange(selector(channel));\n }),\n );\n\n return () => subscriptions.forEach((subscription) => subscription.unsubscribe());\n },\n [channel, selector, stateChangeEventKeys],\n );\n\n const getSnapshot = useCallback(() => {\n if (!channel) return undefined;\n\n return selector(channel);\n }, [channel, selector]);\n\n return useSyncExternalStore(subscribe, getSnapshot);\n}\n","import type { Channel, ChannelMemberResponse, EventTypes } from 'stream-chat';\nimport { useSelectedChannelState } from './useSelectedChannelState';\n\nconst selector = (c: Channel) => c.state.membership;\nconst keys: EventTypes[] = ['member.updated'];\n\nexport function useChannelMembershipState(channel: Channel): ChannelMemberResponse;\nexport function useChannelMembershipState(\n channel?: Channel | undefined,\n): ChannelMemberResponse | undefined;\nexport function useChannelMembershipState(channel?: Channel) {\n return useSelectedChannelState({ channel, selector, stateChangeEventKeys: keys });\n}\n","import { useEffect, useState } from 'react';\n\nimport { useChatContext } from '../../../context/ChatContext';\n\nimport type { Channel } from 'stream-chat';\n\n/**\n * `channel.muteStatus()` throws in two cases:\n * - the channel has not been initialized yet (i.e. `.watch()`/`.query()` has not\n * resolved) - the ChannelList can briefly hold such channels, e.g. a\n * `message.new` for a channel that has not been watched yet (#2474);\n * - the channel is disconnected (e.g. after `client.disconnectUser()`), in which\n * case `channel.getClient()` throws even though the channel stays initialized\n * (#2393 failure class).\n * Guard against both to avoid crashing the whole app.\n */\nconst getMuteStatus = (channel: Channel) =>\n channel.initialized && !channel.disconnected\n ? channel.muteStatus()\n : { createdAt: null, expiresAt: null, muted: false };\n\nexport const useIsChannelMuted = (channel: Channel) => {\n const { client } = useChatContext('useIsChannelMuted');\n\n const [muted, setMuted] = useState(() => getMuteStatus(channel));\n\n useEffect(() => {\n const handleEvent = () => {\n setMuted(getMuteStatus(channel));\n };\n\n return client.on('notification.channel_mutes_updated', handleEvent).unsubscribe;\n }, [channel, client]);\n\n return muted;\n};\n","import { useMemo } from 'react';\n\nimport { useChatContext } from '../../../context/ChatContext';\n\nexport const useIsUserMuted = (targetUserId?: string) => {\n const { mutes } = useChatContext();\n\n return useMemo(\n () => !!targetUserId && mutes.some((mute) => mute.target.id === targetUserId),\n [mutes, targetUserId],\n );\n};\n","import { useEffect, useState } from 'react';\nimport type { Channel, ChannelState } from 'stream-chat';\n\nimport { useChannelStateContext } from '../../../context/ChannelStateContext';\nimport { useChatContext } from '../../../context/ChatContext';\n\nexport type UseChannelHasMembersOnlineParams = {\n channel?: Channel;\n enabled?: boolean;\n};\n\n// Watchers include the current user, but \"are other members online\" must reflect\n// only other users — otherwise (e.g. in a DM) the other participant looks online\n// as soon as the local user starts watching.\nconst getOtherWatchers = (\n watchers: ChannelState['watchers'] | undefined,\n ownUserId?: string,\n) => {\n const next = Object.assign({}, watchers ?? {});\n if (ownUserId) delete next[ownUserId];\n return next;\n};\n\nexport const useChannelHasMembersOnline = ({\n channel: channelOverride,\n enabled = true,\n}: UseChannelHasMembersOnlineParams = {}) => {\n const { channel: contextChannel } = useChannelStateContext();\n const { client } = useChatContext();\n const channel = channelOverride ?? contextChannel;\n const ownUserId = client.user?.id;\n const [watchers, setWatchers] = useState<ChannelState['watchers']>(() =>\n getOtherWatchers(channel?.state?.watchers, ownUserId),\n );\n\n useEffect(() => {\n setWatchers(getOtherWatchers(channel?.state?.watchers, ownUserId));\n }, [channel, ownUserId]);\n\n useEffect(() => {\n if (!enabled || !channel) return;\n\n const startSubscription = channel.on('user.watching.start', (event) => {\n setWatchers((prev) => {\n if (!event.user?.id || event.user.id === ownUserId) return prev;\n if (prev[event.user.id]) return prev;\n return Object.assign({ [event.user.id]: event.user }, prev);\n });\n });\n const stopSubscription = channel.on('user.watching.stop', (event) => {\n setWatchers((prev) => {\n if (!event.user?.id || !prev[event.user.id]) return prev;\n\n const next = Object.assign({}, prev);\n delete next[event.user.id];\n return next;\n });\n });\n\n return () => {\n startSubscription.unsubscribe();\n stopSubscription.unsubscribe();\n };\n }, [channel, enabled, ownUserId]);\n\n if (!enabled) return false;\n\n return Object.keys(watchers).length > 0;\n};\n","import { useChannelStateContext } from '../../../context/ChannelStateContext';\nimport { useChatContext } from '../../../context/ChatContext';\nimport { useTranslationContext } from '../../../context/TranslationContext';\nimport { isDmChannel } from '../../../utils';\nimport { useChannelHasMembersOnline } from './useChannelHasMembersOnline';\nimport type { Channel } from 'stream-chat';\n\nexport type UseChannelHeaderOnlineStatusParams = {\n channel?: Channel;\n watcherCount?: number;\n};\n\n/**\n * Returns the channel header online status text (e.g. \"Online\", \"Offline\", or \"X members, Y online\").\n * Returns null when the channel has no members (nothing to show).\n */\nexport function useChannelHeaderOnlineStatus({\n channel: channelOverride,\n watcherCount: watcherCountOverride,\n}: UseChannelHeaderOnlineStatusParams = {}): string | null {\n const { t } = useTranslationContext();\n const { client } = useChatContext();\n const { channel: contextChannel, watcherCount: contextWatcherCount = 0 } =\n useChannelStateContext();\n const channel = channelOverride ?? contextChannel;\n const watcherCount = watcherCountOverride ?? contextWatcherCount;\n const { member_count: memberCount = 0 } = channel?.data || {};\n const isDirectMessagingChannel = isDmChannel({\n channel,\n ownUserId: client.user?.id,\n });\n const hasMembersOnline = useChannelHasMembersOnline({\n channel,\n enabled: isDirectMessagingChannel,\n });\n\n if (!memberCount) return null;\n\n if (isDirectMessagingChannel) {\n return hasMembersOnline ? t('Online') : t('Offline');\n }\n\n return `${t('{{ memberCount }} members', { memberCount })} · ${t('{{ watcherCount }} online', { watcherCount })}`;\n}\n"],"mappings":"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"}
|