stream-chat-react 13.6.6 → 13.8.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/Channel/Channel.d.ts +1 -1
- package/dist/components/Channel/Channel.js +2 -0
- package/dist/components/ChannelPreview/ChannelPreview.js +13 -2
- package/dist/components/ChannelPreview/utils.js +3 -1
- package/dist/components/Chat/hooks/useChat.js +1 -1
- package/dist/components/Message/MessageSimple.js +2 -2
- package/dist/components/Message/QuotedMessage.js +3 -1
- package/dist/components/Message/hooks/useActionHandler.js +6 -5
- package/dist/components/Message/renderText/remarkPlugins/imageToLink.d.ts +12 -0
- package/dist/components/Message/renderText/remarkPlugins/imageToLink.js +27 -0
- package/dist/components/Message/renderText/remarkPlugins/index.d.ts +2 -0
- package/dist/components/Message/renderText/remarkPlugins/index.js +2 -0
- package/dist/components/Message/renderText/remarkPlugins/plusPlusToEmphasis.d.ts +6 -0
- package/dist/components/Message/renderText/remarkPlugins/plusPlusToEmphasis.js +64 -0
- package/dist/components/Message/renderText/renderText.js +4 -1
- package/dist/components/MessageInput/EditMessageForm.d.ts +2 -1
- package/dist/components/MessageInput/hooks/useMessageComposer.js +3 -1
- package/dist/components/Poll/PollActions/PollActions.js +2 -1
- package/dist/components/TextareaComposer/TextareaComposer.js +4 -1
- package/dist/context/ComponentContext.d.ts +3 -1
- package/dist/experimental/index.browser.cjs +125 -49
- package/dist/experimental/index.browser.cjs.map +4 -4
- package/dist/experimental/index.node.cjs +125 -49
- package/dist/experimental/index.node.cjs.map +4 -4
- package/dist/i18n/TranslationBuilder/notifications/NotificationTranslationTopic.js +2 -1
- package/dist/i18n/TranslationBuilder/notifications/attachmentUpload.d.ts +1 -0
- package/dist/i18n/TranslationBuilder/notifications/attachmentUpload.js +5 -0
- package/dist/index.browser.cjs +1414 -1314
- package/dist/index.browser.cjs.map +4 -4
- package/dist/index.node.cjs +1416 -1314
- package/dist/index.node.cjs.map +4 -4
- package/dist/plugins/Emojis/index.browser.cjs +4 -1
- package/dist/plugins/Emojis/index.browser.cjs.map +2 -2
- package/dist/plugins/Emojis/index.node.cjs +4 -1
- package/dist/plugins/Emojis/index.node.cjs.map +2 -2
- package/dist/types/defaultDataInterfaces.d.ts +2 -0
- package/dist/utils/useStableCallback.d.ts +25 -0
- package/dist/utils/useStableCallback.js +29 -0
- package/package.json +3 -4
|
@@ -159,7 +159,10 @@ var useMessageComposer = () => {
|
|
|
159
159
|
if (editing && cachedEditedMessage) {
|
|
160
160
|
const tag = import_stream_chat.MessageComposer.constructTag(cachedEditedMessage);
|
|
161
161
|
const cachedComposer = queueCache.get(tag);
|
|
162
|
-
if (cachedComposer)
|
|
162
|
+
if (cachedComposer) {
|
|
163
|
+
cachedComposer.editedMessage = cachedEditedMessage;
|
|
164
|
+
return cachedComposer;
|
|
165
|
+
}
|
|
163
166
|
return new import_stream_chat.MessageComposer({
|
|
164
167
|
client,
|
|
165
168
|
composition: cachedEditedMessage,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/plugins/Emojis/index.ts", "../../../src/plugins/Emojis/EmojiPicker.tsx", "../../../src/plugins/Emojis/icons.tsx", "../../../src/context/ChannelStateContext.tsx", "../../../src/context/ChatContext.tsx", "../../../src/context/MessageContext.tsx", "../../../src/context/TranslationContext.tsx", "../../../src/i18n/utils.ts", "../../../src/components/MessageInput/hooks/useMessageComposer.ts", "../../../src/components/Threads/ThreadContext.tsx", "../../../src/components/Thread/LegacyThreadContext.ts", "../../../src/context/MessageInputContext.tsx", "../../../src/plugins/Emojis/middleware/textComposerEmojiMiddleware.ts"],
|
|
4
|
-
"sourcesContent": ["export * from './EmojiPicker';\nexport * from './middleware';\nexport { EmojiPickerIcon } from './icons';\n", "import React, { useEffect, useState } from 'react';\nimport { usePopper } from 'react-popper';\nimport Picker from '@emoji-mart/react';\n\nimport type { Options } from '@popperjs/core';\n\nimport { EmojiPickerIcon } from './icons';\nimport { useMessageInputContext, useTranslationContext } from '../../context';\nimport { useMessageComposer } from '../../components';\n\nconst isShadowRoot = (node: Node): node is ShadowRoot => !!(node as ShadowRoot).host;\n\nexport type EmojiPickerProps = {\n ButtonIconComponent?: React.ComponentType;\n buttonClassName?: string;\n pickerContainerClassName?: string;\n wrapperClassName?: string;\n closeOnEmojiSelect?: boolean;\n /**\n * Untyped [properties](https://github.com/missive/emoji-mart/tree/v5.5.2#options--props) to be\n * passed down to the [emoji-mart `Picker`](https://github.com/missive/emoji-mart/tree/v5.5.2#-picker) component\n */\n pickerProps?: Partial<{ theme: 'auto' | 'light' | 'dark' } & Record<string, unknown>>;\n /**\n * [React Popper options](https://popper.js.org/docs/v2/constructors/#options) to be\n * passed down to the [react-popper `usePopper`](https://popper.js.org/react-popper/v2/hook/) hook\n */\n popperOptions?: Partial<Options>;\n};\n\nconst classNames: EmojiPickerProps = {\n buttonClassName: 'str-chat__emoji-picker-button',\n pickerContainerClassName: 'str-chat__message-textarea-emoji-picker-container',\n wrapperClassName: 'str-chat__message-textarea-emoji-picker',\n};\n\nexport const EmojiPicker = (props: EmojiPickerProps) => {\n const { t } = useTranslationContext('EmojiPicker');\n const { textareaRef } = useMessageInputContext('EmojiPicker');\n const { textComposer } = useMessageComposer();\n const [displayPicker, setDisplayPicker] = useState(false);\n const [referenceElement, setReferenceElement] = useState<HTMLButtonElement | null>(\n null,\n );\n const [popperElement, setPopperElement] = useState<HTMLDivElement | null>(null);\n const { attributes, styles } = usePopper(referenceElement, popperElement, {\n placement: 'top-end',\n ...props.popperOptions,\n });\n\n const { buttonClassName, pickerContainerClassName, wrapperClassName } = classNames;\n\n const { ButtonIconComponent = EmojiPickerIcon } = props;\n\n useEffect(() => {\n if (!popperElement || !referenceElement) return;\n\n const handlePointerDown = (e: PointerEvent) => {\n const target = e.target as HTMLElement;\n\n const rootNode = target.getRootNode();\n\n if (\n popperElement.contains(isShadowRoot(rootNode) ? rootNode.host : target) ||\n referenceElement.contains(target)\n ) {\n return;\n }\n\n setDisplayPicker(false);\n };\n\n window.addEventListener('pointerdown', handlePointerDown);\n return () => window.removeEventListener('pointerdown', handlePointerDown);\n }, [referenceElement, popperElement]);\n\n return (\n <div className={props.wrapperClassName ?? wrapperClassName}>\n {displayPicker && (\n <div\n className={props.pickerContainerClassName ?? pickerContainerClassName}\n style={styles.popper}\n {...attributes.popper}\n ref={setPopperElement}\n >\n <Picker\n data={async () => (await import('@emoji-mart/data')).default}\n onEmojiSelect={(e: { native: string }) => {\n const textarea = textareaRef.current;\n if (!textarea) return;\n textComposer.insertText({ text: e.native });\n textarea.focus();\n if (props.closeOnEmojiSelect) {\n setDisplayPicker(false);\n }\n }}\n {...props.pickerProps}\n />\n </div>\n )}\n <button\n aria-expanded={displayPicker}\n aria-label={t('aria/Emoji picker')}\n className={props.buttonClassName ?? buttonClassName}\n onClick={() => setDisplayPicker((cv) => !cv)}\n ref={setReferenceElement}\n type='button'\n >\n {ButtonIconComponent && <ButtonIconComponent />}\n </button>\n </div>\n );\n};\n", "import React from 'react';\n\nexport const EmojiPickerIcon = () => (\n <svg\n preserveAspectRatio='xMinYMin'\n viewBox='0 0 28 28'\n width='100%'\n xmlns='http://www.w3.org/2000/svg'\n >\n <g clipRule='evenodd' fillRule='evenodd'>\n <path d='M14 4.4C8.6 4.4 4.4 8.6 4.4 14c0 5.4 4.2 9.6 9.6 9.6c5.4 0 9.6-4.2 9.6-9.6c0-5.4-4.2-9.6-9.6-9.6zM2 14c0-6.6 5.4-12 12-12s12 5.4 12 12s-5.4 12-12 12s-12-5.4-12-12zM12.8 11c0 1-.8 1.8-1.8 1.8s-1.8-.8-1.8-1.8s.8-1.8 1.8-1.8s1.8.8 1.8 1.8zM18.8 11c0 1-.8 1.8-1.8 1.8s-1.8-.8-1.8-1.8s.8-1.8 1.8-1.8s1.8.8 1.8 1.8zM8.6 15.4c.6-.4 1.2-.2 1.6.2c.6.8 1.6 1.8 3 2c1.2.4 2.8.2 4.8-2c.4-.4 1.2-.6 1.6 0c.4.4.6 1.2 0 1.6c-2.2 2.6-4.8 3.4-7 3c-2-.4-3.6-1.8-4.4-3c-.4-.6-.2-1.2.4-1.8z'></path>\n </g>\n </svg>\n);\n", "import type { PropsWithChildren } from 'react';\nimport React, { useContext } from 'react';\nimport type {\n Channel,\n ChannelConfigWithInfo,\n LocalMessage,\n Mute,\n ChannelState as StreamChannelState,\n} from 'stream-chat';\n\nimport type {\n ChannelUnreadUiState,\n GiphyVersions,\n ImageAttachmentSizeHandler,\n UnknownType,\n VideoAttachmentSizeHandler,\n} from '../types/types';\n\nexport type ChannelNotifications = Array<{\n id: string;\n text: string;\n type: 'success' | 'error';\n}>;\n\nexport type ChannelState = {\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['members'];\n messages?: LocalMessage[];\n pinnedMessages?: LocalMessage[];\n read?: StreamChannelState['read'];\n thread?: LocalMessage | null;\n threadHasMore?: boolean;\n threadLoadingMore?: boolean;\n threadMessages?: LocalMessage[];\n threadSuppressAutoscroll?: boolean;\n typing?: StreamChannelState['typing'];\n watcherCount?: number;\n watchers?: StreamChannelState['watchers'];\n};\n\nexport type ChannelStateContextValue = Omit<ChannelState, 'typing'> & {\n channel: Channel;\n channelCapabilities: Record<string, boolean>;\n channelConfig: ChannelConfigWithInfo | undefined;\n imageAttachmentSizeHandler: ImageAttachmentSizeHandler;\n notifications: ChannelNotifications;\n shouldGenerateVideoThumbnail: boolean;\n videoAttachmentSizeHandler: VideoAttachmentSizeHandler;\n channelUnreadUiState?: ChannelUnreadUiState;\n giphyVersion?: GiphyVersions;\n mutes?: Array<Mute>;\n watcher_count?: number;\n};\n\nexport const ChannelStateContext = React.createContext<\n ChannelStateContextValue | undefined\n>(undefined);\n\nexport const ChannelStateProvider = ({\n children,\n value,\n}: PropsWithChildren<{\n value: ChannelStateContextValue;\n}>) => (\n <ChannelStateContext.Provider value={value as unknown as ChannelStateContextValue}>\n {children}\n </ChannelStateContext.Provider>\n);\n\nexport const useChannelStateContext = (componentName?: string) => {\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;\n }\n\n return contextValue as unknown as ChannelStateContextValue;\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 = <P extends UnknownType>(\n Component: React.ComponentType<P>,\n) => {\n const WithChannelStateContextComponent = (\n props: Omit<P, keyof ChannelStateContextValue>,\n ) => {\n const channelStateContext = useChannelStateContext();\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, { useContext } from 'react';\nimport type { PropsWithChildren } from 'react';\nimport type {\n AppSettingsAPIResponse,\n Channel,\n Mute,\n SearchController,\n} from 'stream-chat';\n\nimport { getDisplayName } from './utils/getDisplayName';\nimport type { ChatProps } from '../components/Chat/Chat';\nimport type { 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 ChannelConfId = string; // e.g.: \"messaging:general\"\n\nexport type ChatContextValue = {\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> | null;\n latestMessageDatesByChannels: Record<ChannelConfId, Date>;\n mutes: Array<Mute>;\n openMobileNav: () => void;\n /** Instance of SearchController class that allows to control all the search operations. */\n searchController: SearchController;\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,\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;\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, 'isMessageAIGenerated'>> &\n Required<Pick<ChatProps, 'theme' | 'client'>>;\n\nexport const ChatContext = React.createContext<ChatContextValue | undefined>(undefined);\n\nexport const ChatProvider = ({\n children,\n value,\n}: PropsWithChildren<{\n value: ChatContextValue;\n}>) => (\n <ChatContext.Provider value={value as unknown as ChatContextValue}>\n {children}\n </ChatContext.Provider>\n);\n\nexport const useChatContext = (componentName?: string) => {\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;\n }\n\n return contextValue as unknown as ChatContextValue;\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 = <P extends UnknownType>(\n Component: React.ComponentType<P>,\n) => {\n const WithChatContextComponent = (props: Omit<P, keyof ChatContextValue>) => {\n const chatContext = useChatContext();\n\n return <Component {...(props as P)} {...chatContext} />;\n };\n WithChatContextComponent.displayName = `WithChatContext${getDisplayName(Component)}`;\n return WithChatContextComponent;\n};\n", "import type { PropsWithChildren, ReactNode } from 'react';\nimport React, { useContext } from 'react';\n\nimport type {\n LocalMessage,\n Mute,\n ReactionResponse,\n ReactionSort,\n UserResponse,\n} from 'stream-chat';\n\nimport type { ChannelActionContextValue } from './ChannelActionContext';\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 { UnknownType } from '../types/types';\n\nexport type CustomMessageActions = {\n [key: string]: (\n message: LocalMessage,\n event: React.BaseSyntheticEvent,\n ) => Promise<void> | void;\n};\n\nexport type MessageContextValue = {\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,\n sort?: ReactionSort,\n ) => Promise<Array<ReactionResponse>>;\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: (\n reactionType: string,\n event: React.BaseSyntheticEvent,\n ) => Promise<void>;\n /** Function to retry sending a Message */\n handleRetry: ChannelActionContextValue['retrySendMessage'];\n /** Function that returns whether the Message belongs to the current user */\n isMyMessage: () => boolean;\n /** The message object */\n message: LocalMessage;\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;\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;\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: LocalMessage) => 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[];\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;\n /** A list of users that have read this Message */\n readBy?: UserResponse[];\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[],\n options?: RenderTextOptions,\n ) => ReactNode;\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>(\n undefined,\n);\n\nexport const MessageProvider = ({\n children,\n value,\n}: PropsWithChildren<{\n value: MessageContextValue;\n}>) => (\n <MessageContext.Provider value={value as unknown as MessageContextValue}>\n {children}\n </MessageContext.Provider>\n);\n\nexport const useMessageContext = (\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n _componentName?: string,\n) => {\n const contextValue = useContext(MessageContext);\n\n if (!contextValue) {\n return {} as MessageContextValue;\n }\n\n return contextValue as unknown as MessageContextValue;\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 = <P extends UnknownType>(\n Component: React.ComponentType<P>,\n) => {\n const WithMessageContextComponent = (props: Omit<P, keyof MessageContextValue>) => {\n const messageContext = useMessageContext();\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, { useContext } from 'react';\nimport Dayjs from 'dayjs';\nimport calendar from 'dayjs/plugin/calendar';\nimport localizedFormat from 'dayjs/plugin/localizedFormat';\nimport type { PropsWithChildren } from 'react';\nimport type { TFunction } from 'i18next';\nimport type { TranslationLanguages } from 'stream-chat';\n\nimport { getDisplayName } from './utils/getDisplayName';\nimport { defaultDateTimeParser, defaultTranslatorFunction } from '../i18n/utils';\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 = (\n props: Omit<P, keyof TranslationContextValue>,\n ) => {\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, { isDayjs } from 'dayjs';\nimport type { Duration as DayjsDuration } from 'dayjs/plugin/duration';\n\nimport type { TFunction } from 'i18next';\nimport type { Moment } from 'moment-timezone';\nimport type {\n DateFormatterOptions,\n DurationFormatterOptions,\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 = (\n output: TDateTimeParserOutput,\n): output is number | string => typeof output === 'string' || typeof output === 'number';\n\nexport const isDayOrMoment = (\n output: TDateTimeParserOutput,\n): output is Dayjs.Dayjs | Moment => !!(output as Dayjs.Dayjs | Moment)?.isSame;\n\nexport const isDate = (output: unknown): output is Date =>\n output !== null &&\n typeof output === 'object' &&\n typeof (output as Date).getTime === 'function';\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 durationFormatter:\n (streamI18n) =>\n (value, _, { format, withSuffix }: DurationFormatterOptions) => {\n if (format && isDayjs(streamI18n.DateTimeParser)) {\n return (streamI18n.DateTimeParser.duration(value) as DayjsDuration).format(\n format,\n );\n }\n return streamI18n.DateTimeParser.duration(value).humanize(!!withSuffix);\n },\n timestampFormatter:\n (streamI18n) =>\n (\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 = ((key: string) => key) as TFunction;\n\nexport const defaultDateTimeParser = (input?: TDateTimeParserInput) => Dayjs(input);\n\nexport const isLanguageSupported = (\n language: string,\n): language is SupportedTranslations => {\n const translations = [\n 'de',\n 'en',\n 'es',\n 'fr',\n 'hi',\n 'it',\n 'ja',\n 'ko',\n 'nl',\n 'pt',\n 'ru',\n 'tr',\n ];\n return translations.some((translation) => language === translation);\n};\n", "import { useEffect, useMemo } from 'react';\nimport { FixedSizeQueueCache, MessageComposer } from 'stream-chat';\nimport { useThreadContext } from '../../Threads';\nimport {\n useChannelStateContext,\n useChatContext,\n useMessageContext,\n} from '../../../context';\nimport { useLegacyThreadContext } from '../../Thread';\n\nconst queueCache = new FixedSizeQueueCache<string, MessageComposer>(64);\n\nexport const useMessageComposer = () => {\n const { client } = useChatContext();\n const { channel } = useChannelStateContext();\n const { editing, message: editedMessage } = useMessageContext();\n // legacy thread will receive new composer\n const { legacyThread: parentMessage } = useLegacyThreadContext();\n const threadInstance = useThreadContext();\n\n const cachedEditedMessage = useMemo(() => {\n if (!editedMessage) return undefined;\n\n return editedMessage;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [editedMessage?.id]);\n\n const cachedParentMessage = useMemo(() => {\n if (!parentMessage) return undefined;\n\n return parentMessage;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [parentMessage?.id]);\n\n // composer hierarchy\n // edited message (always new) -> thread instance (own) -> thread message (always new) -> channel (own)\n // editedMessage ?? thread ?? parentMessage ?? channel;\n const messageComposer = useMemo(() => {\n if (editing && cachedEditedMessage) {\n const tag = MessageComposer.constructTag(cachedEditedMessage);\n\n const cachedComposer = queueCache.get(tag);\n if (cachedComposer) return cachedComposer;\n\n return new MessageComposer({\n client,\n composition: cachedEditedMessage,\n compositionContext: cachedEditedMessage,\n });\n } else if (threadInstance) {\n return threadInstance.messageComposer;\n } else if (cachedParentMessage) {\n const compositionContext = {\n ...cachedParentMessage,\n legacyThreadId: cachedParentMessage.id,\n };\n\n const tag = MessageComposer.constructTag(compositionContext);\n\n const cachedComposer = queueCache.get(tag);\n if (cachedComposer) return cachedComposer;\n\n return new MessageComposer({\n client,\n compositionContext,\n });\n } else {\n return channel.messageComposer;\n }\n }, [\n cachedEditedMessage,\n cachedParentMessage,\n channel,\n client,\n editing,\n threadInstance,\n ]);\n\n if (\n (['legacy_thread', 'message'] as MessageComposer['contextType'][]).includes(\n messageComposer.contextType,\n ) &&\n !queueCache.peek(messageComposer.tag)\n ) {\n queueCache.add(messageComposer.tag, messageComposer);\n }\n\n useEffect(() => {\n const unsubscribe = messageComposer.registerSubscriptions();\n return () => {\n unsubscribe();\n };\n }, [messageComposer]);\n\n return messageComposer;\n};\n", "import React, { createContext, useContext } from 'react';\n\nimport { Channel } from '../../components';\n\nimport type { PropsWithChildren } from 'react';\nimport type { Thread } from 'stream-chat';\n\nexport type ThreadContextValue = Thread | undefined;\n\nexport const ThreadContext = createContext<ThreadContextValue>(undefined);\n\nexport const useThreadContext = () => useContext(ThreadContext);\n\nexport const ThreadProvider = ({\n children,\n thread,\n}: PropsWithChildren<{ thread?: Thread }>) => (\n <ThreadContext.Provider value={thread}>\n <Channel channel={thread?.channel}>{children}</Channel>\n </ThreadContext.Provider>\n);\n", "import React, { useContext } from 'react';\nimport type { LocalMessage } from 'stream-chat';\n\nexport const LegacyThreadContext = React.createContext<{\n legacyThread: LocalMessage | undefined;\n}>({ legacyThread: undefined });\n\nexport const useLegacyThreadContext = () => useContext(LegacyThreadContext);\n", "import React, { createContext, useContext } from 'react';\nimport type { PropsWithChildren } from 'react';\n\nimport type { CooldownTimerState, MessageInputProps } from '../components/MessageInput';\nimport type { MessageInputHookProps } from '../components/MessageInput/hooks/useMessageInputControls';\n\nexport type MessageInputContextValue = MessageInputHookProps &\n Omit<MessageInputProps, 'Input'> &\n CooldownTimerState;\n\nexport const MessageInputContext = createContext<MessageInputHookProps | undefined>(\n undefined,\n);\n\nexport const MessageInputContextProvider = ({\n children,\n value,\n}: PropsWithChildren<{\n value: MessageInputContextValue;\n}>) => (\n <MessageInputContext.Provider value={value as unknown as MessageInputContextValue}>\n {children}\n </MessageInputContext.Provider>\n);\n\nexport const useMessageInputContext = (\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n componentName?: string,\n) => {\n const contextValue = useContext(MessageInputContext);\n\n if (!contextValue) {\n return {} as MessageInputContextValue;\n }\n\n return contextValue as unknown as MessageInputContextValue;\n};\n", "import mergeWith from 'lodash.mergewith';\nimport type {\n Middleware,\n SearchSourceOptions,\n SearchSourceType,\n TextComposerMiddlewareExecutorState,\n TextComposerMiddlewareOptions,\n TextComposerSuggestion,\n} from 'stream-chat';\nimport {\n BaseSearchSource,\n getTokenizedSuggestionDisplayName,\n getTriggerCharWithToken,\n insertItemWithTrigger,\n replaceWordWithEntity,\n} from 'stream-chat';\nimport type {\n EmojiSearchIndex,\n EmojiSearchIndexResult,\n} from '../../../components/MessageInput';\n\nexport type EmojiSuggestion<T extends EmojiSearchIndexResult = EmojiSearchIndexResult> =\n TextComposerSuggestion<T>;\n\nclass EmojiSearchSource<\n T extends TextComposerSuggestion<EmojiSearchIndexResult>,\n> extends BaseSearchSource<T> {\n readonly type: SearchSourceType = 'emoji';\n private emojiSearchIndex: EmojiSearchIndex;\n\n constructor(emojiSearchIndex: EmojiSearchIndex, options?: SearchSourceOptions) {\n super(options);\n this.emojiSearchIndex = emojiSearchIndex;\n }\n\n async query(searchQuery: string) {\n if (searchQuery.length === 0) {\n return { items: [] as T[], next: null };\n }\n const emojis = (await this.emojiSearchIndex.search(searchQuery)) ?? [];\n\n // emojiIndex.search sometimes returns undefined values, so filter those out first\n return {\n items: emojis\n .filter(Boolean)\n .slice(0, 7)\n .map(({ emoticons = [], id, name, native, skins = [] }) => {\n const [firstSkin] = skins;\n\n return {\n emoticons,\n id,\n name,\n native: native ?? firstSkin.native,\n };\n }) as T[],\n next: null, // todo: generate cursor\n };\n }\n\n protected filterQueryResults(items: T[]): T[] | Promise<T[]> {\n return items.map((item) => ({\n ...item,\n ...getTokenizedSuggestionDisplayName({\n displayName: item.id,\n searchToken: this.searchQuery,\n }),\n }));\n }\n}\n\nconst DEFAULT_OPTIONS: TextComposerMiddlewareOptions = { minChars: 1, trigger: ':' };\n\nexport type EmojiMiddleware<T extends EmojiSearchIndexResult = EmojiSearchIndexResult> =\n Middleware<\n TextComposerMiddlewareExecutorState<EmojiSuggestion<T>>,\n 'onChange' | 'onSuggestionItemSelect'\n >;\n\n/**\n * TextComposer middleware for mentions\n * Usage:\n *\n * const textComposer = new TextComposer(options);\n *\n * textComposer.use(new createTextComposerEmojiMiddleware(emojiSearchIndex, {\n * minChars: 2\n * }));\n *\n * @param emojiSearchIndex\n * @param {{\n * minChars: number;\n * trigger: string;\n * }} options\n * @returns\n */\nexport const createTextComposerEmojiMiddleware = (\n emojiSearchIndex: EmojiSearchIndex,\n options?: Partial<TextComposerMiddlewareOptions>,\n): EmojiMiddleware => {\n const finalOptions = mergeWith(DEFAULT_OPTIONS, options ?? {});\n const emojiSearchSource = new EmojiSearchSource(emojiSearchIndex);\n emojiSearchSource.activate();\n\n return {\n id: 'stream-io/emoji-middleware',\n // eslint-disable-next-line sort-keys\n handlers: {\n onChange: async ({ complete, forward, next, state }) => {\n if (!state.selection) return forward();\n\n const triggerWithToken = getTriggerCharWithToken({\n acceptTrailingSpaces: false,\n text: state.text.slice(0, state.selection.end),\n trigger: finalOptions.trigger,\n });\n\n const triggerWasRemoved =\n !triggerWithToken || triggerWithToken.length < finalOptions.minChars;\n\n if (triggerWasRemoved) {\n const hasSuggestionsForTrigger =\n state.suggestions?.trigger === finalOptions.trigger;\n const newState = { ...state };\n if (hasSuggestionsForTrigger && newState.suggestions) {\n delete newState.suggestions;\n }\n return next(newState);\n }\n\n const newSearchTriggerred =\n triggerWithToken && triggerWithToken === finalOptions.trigger;\n\n if (newSearchTriggerred) {\n emojiSearchSource.resetStateAndActivate();\n }\n\n const textWithReplacedWord = await replaceWordWithEntity({\n caretPosition: state.selection.end,\n getEntityString: async (word: string) => {\n const { items } = await emojiSearchSource.query(word);\n\n const emoji = items\n .filter(Boolean)\n .slice(0, 10)\n .find(({ emoticons }) => !!emoticons?.includes(word));\n\n if (!emoji) return null;\n\n const [firstSkin] = emoji.skins ?? [];\n\n return emoji.native ?? firstSkin.native;\n },\n text: state.text,\n });\n\n if (textWithReplacedWord !== state.text) {\n return complete({\n ...state,\n suggestions: undefined, // to prevent the TextComposerMiddlewareExecutor to run the first page query\n text: textWithReplacedWord,\n });\n }\n\n return complete({\n ...state,\n suggestions: {\n query: triggerWithToken.slice(1),\n searchSource: emojiSearchSource,\n trigger: finalOptions.trigger,\n },\n });\n },\n onSuggestionItemSelect: ({ complete, forward, state }) => {\n const { selectedSuggestion } = state.change ?? {};\n if (!selectedSuggestion || state.suggestions?.trigger !== finalOptions.trigger)\n return forward();\n\n emojiSearchSource.resetStateAndActivate();\n return complete({\n ...state,\n ...insertItemWithTrigger({\n insertText: `${'native' in selectedSuggestion ? selectedSuggestion.native : ''} `,\n selection: state.selection,\n text: state.text,\n trigger: finalOptions.trigger,\n }),\n suggestions: undefined, // Clear suggestions after selection\n });\n },\n },\n };\n};\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,IAAAA,iBAA2C;AAC3C,0BAA0B;AAC1B,IAAAA,iBAAmB;;;ACFnB,mBAAkB;AAEX,IAAM,kBAAkB,MAC7B,6BAAAC,QAAA;AAAA,EAAC;AAAA;AAAA,IACC,qBAAoB;AAAA,IACpB,SAAQ;AAAA,IACR,OAAM;AAAA,IACN,OAAM;AAAA;AAAA,EAEN,6BAAAA,QAAA,cAAC,OAAE,UAAS,WAAU,UAAS,aAC7B,6BAAAA,QAAA,cAAC,UAAK,GAAE,0dAAyd,CACne;AACF;;;ACXF,IAAAC,gBAAkC;AA4D3B,IAAM,sBAAsB,cAAAC,QAAM,cAEvC,MAAS;AAaJ,IAAM,yBAAyB,CAAC,kBAA2B;AAChE,QAAM,mBAAe,0BAAW,mBAAmB;AAEnD,MAAI,CAAC,cAAc;AACjB,YAAQ;AAAA,MACN,qMAAqM,aAAa;AAAA,IACpN;AAEA,WAAO,CAAC;AAAA,EACV;AAEA,SAAO;AACT;;;ACxFA,IAAAC,gBAAkC;AAkE3B,IAAM,cAAc,cAAAC,QAAM,cAA4C,MAAS;AAa/E,IAAM,iBAAiB,CAAC,kBAA2B;AACxD,QAAM,mBAAe,0BAAW,WAAW;AAE3C,MAAI,CAAC,cAAc;AACjB,YAAQ;AAAA,MACN,kLAAkL,aAAa;AAAA,IACjM;AAEA,WAAO,CAAC;AAAA,EACV;AAEA,SAAO;AACT;;;AC1FA,IAAAC,gBAAkC;AAkJ3B,IAAM,iBAAiB,cAAAC,QAAM;AAAA,EAClC;AACF;AAaO,IAAM,oBAAoB,CAE/B,mBACG;AACH,QAAM,mBAAe,0BAAW,cAAc;AAE9C,MAAI,CAAC,cAAc;AACjB,WAAO,CAAC;AAAA,EACV;AAEA,SAAO;AACT;;;AC7KA,IAAAC,gBAAkC;AAClC,IAAAC,gBAAkB;AAClB,sBAAqB;AACrB,6BAA4B;;;ACH5B,mBAA+B;AAmJxB,IAAM,4BAA6B,CAAC,QAAgB;AAEpD,IAAM,wBAAwB,CAAC,cAAiC,aAAAC,SAAM,KAAK;;;ADxIlF,cAAAC,QAAM,OAAO,gBAAAC,OAAQ;AACrB,cAAAD,QAAM,OAAO,uBAAAE,OAAe;AAQrB,IAAM,qBAAqB,cAAAC,QAAM,cAAuC;AAAA,EAC7E,GAAG;AAAA,EACH,iBAAiB;AAAA,EACjB,cAAc;AAChB,CAAC;AASM,IAAM,wBAAwB,CAAC,kBAA2B;AAC/D,QAAM,mBAAe,0BAAW,kBAAkB;AAElD,MAAI,CAAC,cAAc;AACjB,YAAQ;AAAA,MACN,gMAAgM,aAAa;AAAA,IAC/M;AAEA,WAAO,CAAC;AAAA,EACV;AAEA,SAAO;AACT;;;AE/CA,IAAAC,gBAAmC;AACnC,yBAAqD;;;ACDrD,IAAAC,gBAAiD;AAS1C,IAAM,oBAAgB,6BAAkC,MAAS;AAEjE,IAAM,mBAAmB,UAAM,0BAAW,aAAa;;;ACX9D,IAAAC,gBAAkC;AAG3B,IAAM,sBAAsB,cAAAC,QAAM,cAEtC,EAAE,cAAc,OAAU,CAAC;AAEvB,IAAM,yBAAyB,UAAM,0BAAW,mBAAmB;;;AFG1E,IAAM,aAAa,IAAI,uCAA6C,EAAE;AAE/D,IAAM,qBAAqB,MAAM;AACtC,QAAM,EAAE,OAAO,IAAI,eAAe;AAClC,QAAM,EAAE,QAAQ,IAAI,uBAAuB;AAC3C,QAAM,EAAE,SAAS,SAAS,cAAc,IAAI,kBAAkB;AAE9D,QAAM,EAAE,cAAc,cAAc,IAAI,uBAAuB;AAC/D,QAAM,iBAAiB,iBAAiB;AAExC,QAAM,0BAAsB,uBAAQ,MAAM;AACxC,QAAI,CAAC,cAAe,QAAO;AAE3B,WAAO;AAAA,EAET,GAAG,CAAC,eAAe,EAAE,CAAC;AAEtB,QAAM,0BAAsB,uBAAQ,MAAM;AACxC,QAAI,CAAC,cAAe,QAAO;AAE3B,WAAO;AAAA,EAET,GAAG,CAAC,eAAe,EAAE,CAAC;AAKtB,QAAM,sBAAkB,uBAAQ,MAAM;AACpC,QAAI,WAAW,qBAAqB;AAClC,YAAM,MAAM,mCAAgB,aAAa,mBAAmB;AAE5D,YAAM,iBAAiB,WAAW,IAAI,GAAG;AACzC,UAAI,
|
|
4
|
+
"sourcesContent": ["export * from './EmojiPicker';\nexport * from './middleware';\nexport { EmojiPickerIcon } from './icons';\n", "import React, { useEffect, useState } from 'react';\nimport { usePopper } from 'react-popper';\nimport Picker from '@emoji-mart/react';\n\nimport type { Options } from '@popperjs/core';\n\nimport { EmojiPickerIcon } from './icons';\nimport { useMessageInputContext, useTranslationContext } from '../../context';\nimport { useMessageComposer } from '../../components';\n\nconst isShadowRoot = (node: Node): node is ShadowRoot => !!(node as ShadowRoot).host;\n\nexport type EmojiPickerProps = {\n ButtonIconComponent?: React.ComponentType;\n buttonClassName?: string;\n pickerContainerClassName?: string;\n wrapperClassName?: string;\n closeOnEmojiSelect?: boolean;\n /**\n * Untyped [properties](https://github.com/missive/emoji-mart/tree/v5.5.2#options--props) to be\n * passed down to the [emoji-mart `Picker`](https://github.com/missive/emoji-mart/tree/v5.5.2#-picker) component\n */\n pickerProps?: Partial<{ theme: 'auto' | 'light' | 'dark' } & Record<string, unknown>>;\n /**\n * [React Popper options](https://popper.js.org/docs/v2/constructors/#options) to be\n * passed down to the [react-popper `usePopper`](https://popper.js.org/react-popper/v2/hook/) hook\n */\n popperOptions?: Partial<Options>;\n};\n\nconst classNames: EmojiPickerProps = {\n buttonClassName: 'str-chat__emoji-picker-button',\n pickerContainerClassName: 'str-chat__message-textarea-emoji-picker-container',\n wrapperClassName: 'str-chat__message-textarea-emoji-picker',\n};\n\nexport const EmojiPicker = (props: EmojiPickerProps) => {\n const { t } = useTranslationContext('EmojiPicker');\n const { textareaRef } = useMessageInputContext('EmojiPicker');\n const { textComposer } = useMessageComposer();\n const [displayPicker, setDisplayPicker] = useState(false);\n const [referenceElement, setReferenceElement] = useState<HTMLButtonElement | null>(\n null,\n );\n const [popperElement, setPopperElement] = useState<HTMLDivElement | null>(null);\n const { attributes, styles } = usePopper(referenceElement, popperElement, {\n placement: 'top-end',\n ...props.popperOptions,\n });\n\n const { buttonClassName, pickerContainerClassName, wrapperClassName } = classNames;\n\n const { ButtonIconComponent = EmojiPickerIcon } = props;\n\n useEffect(() => {\n if (!popperElement || !referenceElement) return;\n\n const handlePointerDown = (e: PointerEvent) => {\n const target = e.target as HTMLElement;\n\n const rootNode = target.getRootNode();\n\n if (\n popperElement.contains(isShadowRoot(rootNode) ? rootNode.host : target) ||\n referenceElement.contains(target)\n ) {\n return;\n }\n\n setDisplayPicker(false);\n };\n\n window.addEventListener('pointerdown', handlePointerDown);\n return () => window.removeEventListener('pointerdown', handlePointerDown);\n }, [referenceElement, popperElement]);\n\n return (\n <div className={props.wrapperClassName ?? wrapperClassName}>\n {displayPicker && (\n <div\n className={props.pickerContainerClassName ?? pickerContainerClassName}\n style={styles.popper}\n {...attributes.popper}\n ref={setPopperElement}\n >\n <Picker\n data={async () => (await import('@emoji-mart/data')).default}\n onEmojiSelect={(e: { native: string }) => {\n const textarea = textareaRef.current;\n if (!textarea) return;\n textComposer.insertText({ text: e.native });\n textarea.focus();\n if (props.closeOnEmojiSelect) {\n setDisplayPicker(false);\n }\n }}\n {...props.pickerProps}\n />\n </div>\n )}\n <button\n aria-expanded={displayPicker}\n aria-label={t('aria/Emoji picker')}\n className={props.buttonClassName ?? buttonClassName}\n onClick={() => setDisplayPicker((cv) => !cv)}\n ref={setReferenceElement}\n type='button'\n >\n {ButtonIconComponent && <ButtonIconComponent />}\n </button>\n </div>\n );\n};\n", "import React from 'react';\n\nexport const EmojiPickerIcon = () => (\n <svg\n preserveAspectRatio='xMinYMin'\n viewBox='0 0 28 28'\n width='100%'\n xmlns='http://www.w3.org/2000/svg'\n >\n <g clipRule='evenodd' fillRule='evenodd'>\n <path d='M14 4.4C8.6 4.4 4.4 8.6 4.4 14c0 5.4 4.2 9.6 9.6 9.6c5.4 0 9.6-4.2 9.6-9.6c0-5.4-4.2-9.6-9.6-9.6zM2 14c0-6.6 5.4-12 12-12s12 5.4 12 12s-5.4 12-12 12s-12-5.4-12-12zM12.8 11c0 1-.8 1.8-1.8 1.8s-1.8-.8-1.8-1.8s.8-1.8 1.8-1.8s1.8.8 1.8 1.8zM18.8 11c0 1-.8 1.8-1.8 1.8s-1.8-.8-1.8-1.8s.8-1.8 1.8-1.8s1.8.8 1.8 1.8zM8.6 15.4c.6-.4 1.2-.2 1.6.2c.6.8 1.6 1.8 3 2c1.2.4 2.8.2 4.8-2c.4-.4 1.2-.6 1.6 0c.4.4.6 1.2 0 1.6c-2.2 2.6-4.8 3.4-7 3c-2-.4-3.6-1.8-4.4-3c-.4-.6-.2-1.2.4-1.8z'></path>\n </g>\n </svg>\n);\n", "import type { PropsWithChildren } from 'react';\nimport React, { useContext } from 'react';\nimport type {\n Channel,\n ChannelConfigWithInfo,\n LocalMessage,\n Mute,\n ChannelState as StreamChannelState,\n} from 'stream-chat';\n\nimport type {\n ChannelUnreadUiState,\n GiphyVersions,\n ImageAttachmentSizeHandler,\n UnknownType,\n VideoAttachmentSizeHandler,\n} from '../types/types';\n\nexport type ChannelNotifications = Array<{\n id: string;\n text: string;\n type: 'success' | 'error';\n}>;\n\nexport type ChannelState = {\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['members'];\n messages?: LocalMessage[];\n pinnedMessages?: LocalMessage[];\n read?: StreamChannelState['read'];\n thread?: LocalMessage | null;\n threadHasMore?: boolean;\n threadLoadingMore?: boolean;\n threadMessages?: LocalMessage[];\n threadSuppressAutoscroll?: boolean;\n typing?: StreamChannelState['typing'];\n watcherCount?: number;\n watchers?: StreamChannelState['watchers'];\n};\n\nexport type ChannelStateContextValue = Omit<ChannelState, 'typing'> & {\n channel: Channel;\n channelCapabilities: Record<string, boolean>;\n channelConfig: ChannelConfigWithInfo | undefined;\n imageAttachmentSizeHandler: ImageAttachmentSizeHandler;\n notifications: ChannelNotifications;\n shouldGenerateVideoThumbnail: boolean;\n videoAttachmentSizeHandler: VideoAttachmentSizeHandler;\n channelUnreadUiState?: ChannelUnreadUiState;\n giphyVersion?: GiphyVersions;\n mutes?: Array<Mute>;\n watcher_count?: number;\n};\n\nexport const ChannelStateContext = React.createContext<\n ChannelStateContextValue | undefined\n>(undefined);\n\nexport const ChannelStateProvider = ({\n children,\n value,\n}: PropsWithChildren<{\n value: ChannelStateContextValue;\n}>) => (\n <ChannelStateContext.Provider value={value as unknown as ChannelStateContextValue}>\n {children}\n </ChannelStateContext.Provider>\n);\n\nexport const useChannelStateContext = (componentName?: string) => {\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;\n }\n\n return contextValue as unknown as ChannelStateContextValue;\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 = <P extends UnknownType>(\n Component: React.ComponentType<P>,\n) => {\n const WithChannelStateContextComponent = (\n props: Omit<P, keyof ChannelStateContextValue>,\n ) => {\n const channelStateContext = useChannelStateContext();\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, { useContext } from 'react';\nimport type { PropsWithChildren } from 'react';\nimport type {\n AppSettingsAPIResponse,\n Channel,\n Mute,\n SearchController,\n} from 'stream-chat';\n\nimport { getDisplayName } from './utils/getDisplayName';\nimport type { ChatProps } from '../components/Chat/Chat';\nimport type { 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 ChannelConfId = string; // e.g.: \"messaging:general\"\n\nexport type ChatContextValue = {\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> | null;\n latestMessageDatesByChannels: Record<ChannelConfId, Date>;\n mutes: Array<Mute>;\n openMobileNav: () => void;\n /** Instance of SearchController class that allows to control all the search operations. */\n searchController: SearchController;\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,\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;\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, 'isMessageAIGenerated'>> &\n Required<Pick<ChatProps, 'theme' | 'client'>>;\n\nexport const ChatContext = React.createContext<ChatContextValue | undefined>(undefined);\n\nexport const ChatProvider = ({\n children,\n value,\n}: PropsWithChildren<{\n value: ChatContextValue;\n}>) => (\n <ChatContext.Provider value={value as unknown as ChatContextValue}>\n {children}\n </ChatContext.Provider>\n);\n\nexport const useChatContext = (componentName?: string) => {\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;\n }\n\n return contextValue as unknown as ChatContextValue;\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 = <P extends UnknownType>(\n Component: React.ComponentType<P>,\n) => {\n const WithChatContextComponent = (props: Omit<P, keyof ChatContextValue>) => {\n const chatContext = useChatContext();\n\n return <Component {...(props as P)} {...chatContext} />;\n };\n WithChatContextComponent.displayName = `WithChatContext${getDisplayName(Component)}`;\n return WithChatContextComponent;\n};\n", "import type { PropsWithChildren, ReactNode } from 'react';\nimport React, { useContext } from 'react';\n\nimport type {\n LocalMessage,\n Mute,\n ReactionResponse,\n ReactionSort,\n UserResponse,\n} from 'stream-chat';\n\nimport type { ChannelActionContextValue } from './ChannelActionContext';\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 { UnknownType } from '../types/types';\n\nexport type CustomMessageActions = {\n [key: string]: (\n message: LocalMessage,\n event: React.BaseSyntheticEvent,\n ) => Promise<void> | void;\n};\n\nexport type MessageContextValue = {\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,\n sort?: ReactionSort,\n ) => Promise<Array<ReactionResponse>>;\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: (\n reactionType: string,\n event: React.BaseSyntheticEvent,\n ) => Promise<void>;\n /** Function to retry sending a Message */\n handleRetry: ChannelActionContextValue['retrySendMessage'];\n /** Function that returns whether the Message belongs to the current user */\n isMyMessage: () => boolean;\n /** The message object */\n message: LocalMessage;\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;\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;\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: LocalMessage) => 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[];\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;\n /** A list of users that have read this Message */\n readBy?: UserResponse[];\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[],\n options?: RenderTextOptions,\n ) => ReactNode;\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>(\n undefined,\n);\n\nexport const MessageProvider = ({\n children,\n value,\n}: PropsWithChildren<{\n value: MessageContextValue;\n}>) => (\n <MessageContext.Provider value={value as unknown as MessageContextValue}>\n {children}\n </MessageContext.Provider>\n);\n\nexport const useMessageContext = (\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n _componentName?: string,\n) => {\n const contextValue = useContext(MessageContext);\n\n if (!contextValue) {\n return {} as MessageContextValue;\n }\n\n return contextValue as unknown as MessageContextValue;\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 = <P extends UnknownType>(\n Component: React.ComponentType<P>,\n) => {\n const WithMessageContextComponent = (props: Omit<P, keyof MessageContextValue>) => {\n const messageContext = useMessageContext();\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, { useContext } from 'react';\nimport Dayjs from 'dayjs';\nimport calendar from 'dayjs/plugin/calendar';\nimport localizedFormat from 'dayjs/plugin/localizedFormat';\nimport type { PropsWithChildren } from 'react';\nimport type { TFunction } from 'i18next';\nimport type { TranslationLanguages } from 'stream-chat';\n\nimport { getDisplayName } from './utils/getDisplayName';\nimport { defaultDateTimeParser, defaultTranslatorFunction } from '../i18n/utils';\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 = (\n props: Omit<P, keyof TranslationContextValue>,\n ) => {\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, { isDayjs } from 'dayjs';\nimport type { Duration as DayjsDuration } from 'dayjs/plugin/duration';\n\nimport type { TFunction } from 'i18next';\nimport type { Moment } from 'moment-timezone';\nimport type {\n DateFormatterOptions,\n DurationFormatterOptions,\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 = (\n output: TDateTimeParserOutput,\n): output is number | string => typeof output === 'string' || typeof output === 'number';\n\nexport const isDayOrMoment = (\n output: TDateTimeParserOutput,\n): output is Dayjs.Dayjs | Moment => !!(output as Dayjs.Dayjs | Moment)?.isSame;\n\nexport const isDate = (output: unknown): output is Date =>\n output !== null &&\n typeof output === 'object' &&\n typeof (output as Date).getTime === 'function';\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 durationFormatter:\n (streamI18n) =>\n (value, _, { format, withSuffix }: DurationFormatterOptions) => {\n if (format && isDayjs(streamI18n.DateTimeParser)) {\n return (streamI18n.DateTimeParser.duration(value) as DayjsDuration).format(\n format,\n );\n }\n return streamI18n.DateTimeParser.duration(value).humanize(!!withSuffix);\n },\n timestampFormatter:\n (streamI18n) =>\n (\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 = ((key: string) => key) as TFunction;\n\nexport const defaultDateTimeParser = (input?: TDateTimeParserInput) => Dayjs(input);\n\nexport const isLanguageSupported = (\n language: string,\n): language is SupportedTranslations => {\n const translations = [\n 'de',\n 'en',\n 'es',\n 'fr',\n 'hi',\n 'it',\n 'ja',\n 'ko',\n 'nl',\n 'pt',\n 'ru',\n 'tr',\n ];\n return translations.some((translation) => language === translation);\n};\n", "import { useEffect, useMemo } from 'react';\nimport { FixedSizeQueueCache, MessageComposer } from 'stream-chat';\nimport { useThreadContext } from '../../Threads';\nimport {\n useChannelStateContext,\n useChatContext,\n useMessageContext,\n} from '../../../context';\nimport { useLegacyThreadContext } from '../../Thread';\n\nconst queueCache = new FixedSizeQueueCache<string, MessageComposer>(64);\n\nexport const useMessageComposer = () => {\n const { client } = useChatContext();\n const { channel } = useChannelStateContext();\n const { editing, message: editedMessage } = useMessageContext();\n // legacy thread will receive new composer\n const { legacyThread: parentMessage } = useLegacyThreadContext();\n const threadInstance = useThreadContext();\n\n const cachedEditedMessage = useMemo(() => {\n if (!editedMessage) return undefined;\n\n return editedMessage;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [editedMessage?.id]);\n\n const cachedParentMessage = useMemo(() => {\n if (!parentMessage) return undefined;\n\n return parentMessage;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [parentMessage?.id]);\n\n // composer hierarchy\n // edited message (always new) -> thread instance (own) -> thread message (always new) -> channel (own)\n // editedMessage ?? thread ?? parentMessage ?? channel;\n const messageComposer = useMemo(() => {\n if (editing && cachedEditedMessage) {\n const tag = MessageComposer.constructTag(cachedEditedMessage);\n\n const cachedComposer = queueCache.get(tag);\n if (cachedComposer) {\n cachedComposer.editedMessage = cachedEditedMessage;\n return cachedComposer;\n }\n\n return new MessageComposer({\n client,\n composition: cachedEditedMessage,\n compositionContext: cachedEditedMessage,\n });\n } else if (threadInstance) {\n return threadInstance.messageComposer;\n } else if (cachedParentMessage) {\n const compositionContext = {\n ...cachedParentMessage,\n legacyThreadId: cachedParentMessage.id,\n };\n\n const tag = MessageComposer.constructTag(compositionContext);\n\n const cachedComposer = queueCache.get(tag);\n if (cachedComposer) return cachedComposer;\n\n return new MessageComposer({\n client,\n compositionContext,\n });\n } else {\n return channel.messageComposer;\n }\n }, [\n cachedEditedMessage,\n cachedParentMessage,\n channel,\n client,\n editing,\n threadInstance,\n ]);\n\n if (\n (['legacy_thread', 'message'] as MessageComposer['contextType'][]).includes(\n messageComposer.contextType,\n ) &&\n !queueCache.peek(messageComposer.tag)\n ) {\n queueCache.add(messageComposer.tag, messageComposer);\n }\n\n useEffect(() => {\n const unsubscribe = messageComposer.registerSubscriptions();\n return () => {\n unsubscribe();\n };\n }, [messageComposer]);\n\n return messageComposer;\n};\n", "import React, { createContext, useContext } from 'react';\n\nimport { Channel } from '../../components';\n\nimport type { PropsWithChildren } from 'react';\nimport type { Thread } from 'stream-chat';\n\nexport type ThreadContextValue = Thread | undefined;\n\nexport const ThreadContext = createContext<ThreadContextValue>(undefined);\n\nexport const useThreadContext = () => useContext(ThreadContext);\n\nexport const ThreadProvider = ({\n children,\n thread,\n}: PropsWithChildren<{ thread?: Thread }>) => (\n <ThreadContext.Provider value={thread}>\n <Channel channel={thread?.channel}>{children}</Channel>\n </ThreadContext.Provider>\n);\n", "import React, { useContext } from 'react';\nimport type { LocalMessage } from 'stream-chat';\n\nexport const LegacyThreadContext = React.createContext<{\n legacyThread: LocalMessage | undefined;\n}>({ legacyThread: undefined });\n\nexport const useLegacyThreadContext = () => useContext(LegacyThreadContext);\n", "import React, { createContext, useContext } from 'react';\nimport type { PropsWithChildren } from 'react';\n\nimport type { CooldownTimerState, MessageInputProps } from '../components/MessageInput';\nimport type { MessageInputHookProps } from '../components/MessageInput/hooks/useMessageInputControls';\n\nexport type MessageInputContextValue = MessageInputHookProps &\n Omit<MessageInputProps, 'Input'> &\n CooldownTimerState;\n\nexport const MessageInputContext = createContext<MessageInputHookProps | undefined>(\n undefined,\n);\n\nexport const MessageInputContextProvider = ({\n children,\n value,\n}: PropsWithChildren<{\n value: MessageInputContextValue;\n}>) => (\n <MessageInputContext.Provider value={value as unknown as MessageInputContextValue}>\n {children}\n </MessageInputContext.Provider>\n);\n\nexport const useMessageInputContext = (\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n componentName?: string,\n) => {\n const contextValue = useContext(MessageInputContext);\n\n if (!contextValue) {\n return {} as MessageInputContextValue;\n }\n\n return contextValue as unknown as MessageInputContextValue;\n};\n", "import mergeWith from 'lodash.mergewith';\nimport type {\n Middleware,\n SearchSourceOptions,\n SearchSourceType,\n TextComposerMiddlewareExecutorState,\n TextComposerMiddlewareOptions,\n TextComposerSuggestion,\n} from 'stream-chat';\nimport {\n BaseSearchSource,\n getTokenizedSuggestionDisplayName,\n getTriggerCharWithToken,\n insertItemWithTrigger,\n replaceWordWithEntity,\n} from 'stream-chat';\nimport type {\n EmojiSearchIndex,\n EmojiSearchIndexResult,\n} from '../../../components/MessageInput';\n\nexport type EmojiSuggestion<T extends EmojiSearchIndexResult = EmojiSearchIndexResult> =\n TextComposerSuggestion<T>;\n\nclass EmojiSearchSource<\n T extends TextComposerSuggestion<EmojiSearchIndexResult>,\n> extends BaseSearchSource<T> {\n readonly type: SearchSourceType = 'emoji';\n private emojiSearchIndex: EmojiSearchIndex;\n\n constructor(emojiSearchIndex: EmojiSearchIndex, options?: SearchSourceOptions) {\n super(options);\n this.emojiSearchIndex = emojiSearchIndex;\n }\n\n async query(searchQuery: string) {\n if (searchQuery.length === 0) {\n return { items: [] as T[], next: null };\n }\n const emojis = (await this.emojiSearchIndex.search(searchQuery)) ?? [];\n\n // emojiIndex.search sometimes returns undefined values, so filter those out first\n return {\n items: emojis\n .filter(Boolean)\n .slice(0, 7)\n .map(({ emoticons = [], id, name, native, skins = [] }) => {\n const [firstSkin] = skins;\n\n return {\n emoticons,\n id,\n name,\n native: native ?? firstSkin.native,\n };\n }) as T[],\n next: null, // todo: generate cursor\n };\n }\n\n protected filterQueryResults(items: T[]): T[] | Promise<T[]> {\n return items.map((item) => ({\n ...item,\n ...getTokenizedSuggestionDisplayName({\n displayName: item.id,\n searchToken: this.searchQuery,\n }),\n }));\n }\n}\n\nconst DEFAULT_OPTIONS: TextComposerMiddlewareOptions = { minChars: 1, trigger: ':' };\n\nexport type EmojiMiddleware<T extends EmojiSearchIndexResult = EmojiSearchIndexResult> =\n Middleware<\n TextComposerMiddlewareExecutorState<EmojiSuggestion<T>>,\n 'onChange' | 'onSuggestionItemSelect'\n >;\n\n/**\n * TextComposer middleware for mentions\n * Usage:\n *\n * const textComposer = new TextComposer(options);\n *\n * textComposer.use(new createTextComposerEmojiMiddleware(emojiSearchIndex, {\n * minChars: 2\n * }));\n *\n * @param emojiSearchIndex\n * @param {{\n * minChars: number;\n * trigger: string;\n * }} options\n * @returns\n */\nexport const createTextComposerEmojiMiddleware = (\n emojiSearchIndex: EmojiSearchIndex,\n options?: Partial<TextComposerMiddlewareOptions>,\n): EmojiMiddleware => {\n const finalOptions = mergeWith(DEFAULT_OPTIONS, options ?? {});\n const emojiSearchSource = new EmojiSearchSource(emojiSearchIndex);\n emojiSearchSource.activate();\n\n return {\n id: 'stream-io/emoji-middleware',\n // eslint-disable-next-line sort-keys\n handlers: {\n onChange: async ({ complete, forward, next, state }) => {\n if (!state.selection) return forward();\n\n const triggerWithToken = getTriggerCharWithToken({\n acceptTrailingSpaces: false,\n text: state.text.slice(0, state.selection.end),\n trigger: finalOptions.trigger,\n });\n\n const triggerWasRemoved =\n !triggerWithToken || triggerWithToken.length < finalOptions.minChars;\n\n if (triggerWasRemoved) {\n const hasSuggestionsForTrigger =\n state.suggestions?.trigger === finalOptions.trigger;\n const newState = { ...state };\n if (hasSuggestionsForTrigger && newState.suggestions) {\n delete newState.suggestions;\n }\n return next(newState);\n }\n\n const newSearchTriggerred =\n triggerWithToken && triggerWithToken === finalOptions.trigger;\n\n if (newSearchTriggerred) {\n emojiSearchSource.resetStateAndActivate();\n }\n\n const textWithReplacedWord = await replaceWordWithEntity({\n caretPosition: state.selection.end,\n getEntityString: async (word: string) => {\n const { items } = await emojiSearchSource.query(word);\n\n const emoji = items\n .filter(Boolean)\n .slice(0, 10)\n .find(({ emoticons }) => !!emoticons?.includes(word));\n\n if (!emoji) return null;\n\n const [firstSkin] = emoji.skins ?? [];\n\n return emoji.native ?? firstSkin.native;\n },\n text: state.text,\n });\n\n if (textWithReplacedWord !== state.text) {\n return complete({\n ...state,\n suggestions: undefined, // to prevent the TextComposerMiddlewareExecutor to run the first page query\n text: textWithReplacedWord,\n });\n }\n\n return complete({\n ...state,\n suggestions: {\n query: triggerWithToken.slice(1),\n searchSource: emojiSearchSource,\n trigger: finalOptions.trigger,\n },\n });\n },\n onSuggestionItemSelect: ({ complete, forward, state }) => {\n const { selectedSuggestion } = state.change ?? {};\n if (!selectedSuggestion || state.suggestions?.trigger !== finalOptions.trigger)\n return forward();\n\n emojiSearchSource.resetStateAndActivate();\n return complete({\n ...state,\n ...insertItemWithTrigger({\n insertText: `${'native' in selectedSuggestion ? selectedSuggestion.native : ''} `,\n selection: state.selection,\n text: state.text,\n trigger: finalOptions.trigger,\n }),\n suggestions: undefined, // Clear suggestions after selection\n });\n },\n },\n };\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["import_react", "React", "import_react", "React", "import_react", "React", "import_react", "React", "import_react", "import_dayjs", "Dayjs", "Dayjs", "calendar", "localizedFormat", "React", "import_react", "import_react", "import_react", "React", "import_react", "React", "Picker", "import_stream_chat", "mergeWith"]
|
|
7
7
|
}
|
|
@@ -159,7 +159,10 @@ var useMessageComposer = () => {
|
|
|
159
159
|
if (editing && cachedEditedMessage) {
|
|
160
160
|
const tag = import_stream_chat.MessageComposer.constructTag(cachedEditedMessage);
|
|
161
161
|
const cachedComposer = queueCache.get(tag);
|
|
162
|
-
if (cachedComposer)
|
|
162
|
+
if (cachedComposer) {
|
|
163
|
+
cachedComposer.editedMessage = cachedEditedMessage;
|
|
164
|
+
return cachedComposer;
|
|
165
|
+
}
|
|
163
166
|
return new import_stream_chat.MessageComposer({
|
|
164
167
|
client,
|
|
165
168
|
composition: cachedEditedMessage,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/plugins/Emojis/index.ts", "../../../src/plugins/Emojis/EmojiPicker.tsx", "../../../src/plugins/Emojis/icons.tsx", "../../../src/context/ChannelStateContext.tsx", "../../../src/context/ChatContext.tsx", "../../../src/context/MessageContext.tsx", "../../../src/context/TranslationContext.tsx", "../../../src/i18n/utils.ts", "../../../src/components/MessageInput/hooks/useMessageComposer.ts", "../../../src/components/Threads/ThreadContext.tsx", "../../../src/components/Thread/LegacyThreadContext.ts", "../../../src/context/MessageInputContext.tsx", "../../../src/plugins/Emojis/middleware/textComposerEmojiMiddleware.ts"],
|
|
4
|
-
"sourcesContent": ["export * from './EmojiPicker';\nexport * from './middleware';\nexport { EmojiPickerIcon } from './icons';\n", "import React, { useEffect, useState } from 'react';\nimport { usePopper } from 'react-popper';\nimport Picker from '@emoji-mart/react';\n\nimport type { Options } from '@popperjs/core';\n\nimport { EmojiPickerIcon } from './icons';\nimport { useMessageInputContext, useTranslationContext } from '../../context';\nimport { useMessageComposer } from '../../components';\n\nconst isShadowRoot = (node: Node): node is ShadowRoot => !!(node as ShadowRoot).host;\n\nexport type EmojiPickerProps = {\n ButtonIconComponent?: React.ComponentType;\n buttonClassName?: string;\n pickerContainerClassName?: string;\n wrapperClassName?: string;\n closeOnEmojiSelect?: boolean;\n /**\n * Untyped [properties](https://github.com/missive/emoji-mart/tree/v5.5.2#options--props) to be\n * passed down to the [emoji-mart `Picker`](https://github.com/missive/emoji-mart/tree/v5.5.2#-picker) component\n */\n pickerProps?: Partial<{ theme: 'auto' | 'light' | 'dark' } & Record<string, unknown>>;\n /**\n * [React Popper options](https://popper.js.org/docs/v2/constructors/#options) to be\n * passed down to the [react-popper `usePopper`](https://popper.js.org/react-popper/v2/hook/) hook\n */\n popperOptions?: Partial<Options>;\n};\n\nconst classNames: EmojiPickerProps = {\n buttonClassName: 'str-chat__emoji-picker-button',\n pickerContainerClassName: 'str-chat__message-textarea-emoji-picker-container',\n wrapperClassName: 'str-chat__message-textarea-emoji-picker',\n};\n\nexport const EmojiPicker = (props: EmojiPickerProps) => {\n const { t } = useTranslationContext('EmojiPicker');\n const { textareaRef } = useMessageInputContext('EmojiPicker');\n const { textComposer } = useMessageComposer();\n const [displayPicker, setDisplayPicker] = useState(false);\n const [referenceElement, setReferenceElement] = useState<HTMLButtonElement | null>(\n null,\n );\n const [popperElement, setPopperElement] = useState<HTMLDivElement | null>(null);\n const { attributes, styles } = usePopper(referenceElement, popperElement, {\n placement: 'top-end',\n ...props.popperOptions,\n });\n\n const { buttonClassName, pickerContainerClassName, wrapperClassName } = classNames;\n\n const { ButtonIconComponent = EmojiPickerIcon } = props;\n\n useEffect(() => {\n if (!popperElement || !referenceElement) return;\n\n const handlePointerDown = (e: PointerEvent) => {\n const target = e.target as HTMLElement;\n\n const rootNode = target.getRootNode();\n\n if (\n popperElement.contains(isShadowRoot(rootNode) ? rootNode.host : target) ||\n referenceElement.contains(target)\n ) {\n return;\n }\n\n setDisplayPicker(false);\n };\n\n window.addEventListener('pointerdown', handlePointerDown);\n return () => window.removeEventListener('pointerdown', handlePointerDown);\n }, [referenceElement, popperElement]);\n\n return (\n <div className={props.wrapperClassName ?? wrapperClassName}>\n {displayPicker && (\n <div\n className={props.pickerContainerClassName ?? pickerContainerClassName}\n style={styles.popper}\n {...attributes.popper}\n ref={setPopperElement}\n >\n <Picker\n data={async () => (await import('@emoji-mart/data')).default}\n onEmojiSelect={(e: { native: string }) => {\n const textarea = textareaRef.current;\n if (!textarea) return;\n textComposer.insertText({ text: e.native });\n textarea.focus();\n if (props.closeOnEmojiSelect) {\n setDisplayPicker(false);\n }\n }}\n {...props.pickerProps}\n />\n </div>\n )}\n <button\n aria-expanded={displayPicker}\n aria-label={t('aria/Emoji picker')}\n className={props.buttonClassName ?? buttonClassName}\n onClick={() => setDisplayPicker((cv) => !cv)}\n ref={setReferenceElement}\n type='button'\n >\n {ButtonIconComponent && <ButtonIconComponent />}\n </button>\n </div>\n );\n};\n", "import React from 'react';\n\nexport const EmojiPickerIcon = () => (\n <svg\n preserveAspectRatio='xMinYMin'\n viewBox='0 0 28 28'\n width='100%'\n xmlns='http://www.w3.org/2000/svg'\n >\n <g clipRule='evenodd' fillRule='evenodd'>\n <path d='M14 4.4C8.6 4.4 4.4 8.6 4.4 14c0 5.4 4.2 9.6 9.6 9.6c5.4 0 9.6-4.2 9.6-9.6c0-5.4-4.2-9.6-9.6-9.6zM2 14c0-6.6 5.4-12 12-12s12 5.4 12 12s-5.4 12-12 12s-12-5.4-12-12zM12.8 11c0 1-.8 1.8-1.8 1.8s-1.8-.8-1.8-1.8s.8-1.8 1.8-1.8s1.8.8 1.8 1.8zM18.8 11c0 1-.8 1.8-1.8 1.8s-1.8-.8-1.8-1.8s.8-1.8 1.8-1.8s1.8.8 1.8 1.8zM8.6 15.4c.6-.4 1.2-.2 1.6.2c.6.8 1.6 1.8 3 2c1.2.4 2.8.2 4.8-2c.4-.4 1.2-.6 1.6 0c.4.4.6 1.2 0 1.6c-2.2 2.6-4.8 3.4-7 3c-2-.4-3.6-1.8-4.4-3c-.4-.6-.2-1.2.4-1.8z'></path>\n </g>\n </svg>\n);\n", "import type { PropsWithChildren } from 'react';\nimport React, { useContext } from 'react';\nimport type {\n Channel,\n ChannelConfigWithInfo,\n LocalMessage,\n Mute,\n ChannelState as StreamChannelState,\n} from 'stream-chat';\n\nimport type {\n ChannelUnreadUiState,\n GiphyVersions,\n ImageAttachmentSizeHandler,\n UnknownType,\n VideoAttachmentSizeHandler,\n} from '../types/types';\n\nexport type ChannelNotifications = Array<{\n id: string;\n text: string;\n type: 'success' | 'error';\n}>;\n\nexport type ChannelState = {\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['members'];\n messages?: LocalMessage[];\n pinnedMessages?: LocalMessage[];\n read?: StreamChannelState['read'];\n thread?: LocalMessage | null;\n threadHasMore?: boolean;\n threadLoadingMore?: boolean;\n threadMessages?: LocalMessage[];\n threadSuppressAutoscroll?: boolean;\n typing?: StreamChannelState['typing'];\n watcherCount?: number;\n watchers?: StreamChannelState['watchers'];\n};\n\nexport type ChannelStateContextValue = Omit<ChannelState, 'typing'> & {\n channel: Channel;\n channelCapabilities: Record<string, boolean>;\n channelConfig: ChannelConfigWithInfo | undefined;\n imageAttachmentSizeHandler: ImageAttachmentSizeHandler;\n notifications: ChannelNotifications;\n shouldGenerateVideoThumbnail: boolean;\n videoAttachmentSizeHandler: VideoAttachmentSizeHandler;\n channelUnreadUiState?: ChannelUnreadUiState;\n giphyVersion?: GiphyVersions;\n mutes?: Array<Mute>;\n watcher_count?: number;\n};\n\nexport const ChannelStateContext = React.createContext<\n ChannelStateContextValue | undefined\n>(undefined);\n\nexport const ChannelStateProvider = ({\n children,\n value,\n}: PropsWithChildren<{\n value: ChannelStateContextValue;\n}>) => (\n <ChannelStateContext.Provider value={value as unknown as ChannelStateContextValue}>\n {children}\n </ChannelStateContext.Provider>\n);\n\nexport const useChannelStateContext = (componentName?: string) => {\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;\n }\n\n return contextValue as unknown as ChannelStateContextValue;\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 = <P extends UnknownType>(\n Component: React.ComponentType<P>,\n) => {\n const WithChannelStateContextComponent = (\n props: Omit<P, keyof ChannelStateContextValue>,\n ) => {\n const channelStateContext = useChannelStateContext();\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, { useContext } from 'react';\nimport type { PropsWithChildren } from 'react';\nimport type {\n AppSettingsAPIResponse,\n Channel,\n Mute,\n SearchController,\n} from 'stream-chat';\n\nimport { getDisplayName } from './utils/getDisplayName';\nimport type { ChatProps } from '../components/Chat/Chat';\nimport type { 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 ChannelConfId = string; // e.g.: \"messaging:general\"\n\nexport type ChatContextValue = {\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> | null;\n latestMessageDatesByChannels: Record<ChannelConfId, Date>;\n mutes: Array<Mute>;\n openMobileNav: () => void;\n /** Instance of SearchController class that allows to control all the search operations. */\n searchController: SearchController;\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,\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;\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, 'isMessageAIGenerated'>> &\n Required<Pick<ChatProps, 'theme' | 'client'>>;\n\nexport const ChatContext = React.createContext<ChatContextValue | undefined>(undefined);\n\nexport const ChatProvider = ({\n children,\n value,\n}: PropsWithChildren<{\n value: ChatContextValue;\n}>) => (\n <ChatContext.Provider value={value as unknown as ChatContextValue}>\n {children}\n </ChatContext.Provider>\n);\n\nexport const useChatContext = (componentName?: string) => {\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;\n }\n\n return contextValue as unknown as ChatContextValue;\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 = <P extends UnknownType>(\n Component: React.ComponentType<P>,\n) => {\n const WithChatContextComponent = (props: Omit<P, keyof ChatContextValue>) => {\n const chatContext = useChatContext();\n\n return <Component {...(props as P)} {...chatContext} />;\n };\n WithChatContextComponent.displayName = `WithChatContext${getDisplayName(Component)}`;\n return WithChatContextComponent;\n};\n", "import type { PropsWithChildren, ReactNode } from 'react';\nimport React, { useContext } from 'react';\n\nimport type {\n LocalMessage,\n Mute,\n ReactionResponse,\n ReactionSort,\n UserResponse,\n} from 'stream-chat';\n\nimport type { ChannelActionContextValue } from './ChannelActionContext';\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 { UnknownType } from '../types/types';\n\nexport type CustomMessageActions = {\n [key: string]: (\n message: LocalMessage,\n event: React.BaseSyntheticEvent,\n ) => Promise<void> | void;\n};\n\nexport type MessageContextValue = {\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,\n sort?: ReactionSort,\n ) => Promise<Array<ReactionResponse>>;\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: (\n reactionType: string,\n event: React.BaseSyntheticEvent,\n ) => Promise<void>;\n /** Function to retry sending a Message */\n handleRetry: ChannelActionContextValue['retrySendMessage'];\n /** Function that returns whether the Message belongs to the current user */\n isMyMessage: () => boolean;\n /** The message object */\n message: LocalMessage;\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;\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;\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: LocalMessage) => 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[];\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;\n /** A list of users that have read this Message */\n readBy?: UserResponse[];\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[],\n options?: RenderTextOptions,\n ) => ReactNode;\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>(\n undefined,\n);\n\nexport const MessageProvider = ({\n children,\n value,\n}: PropsWithChildren<{\n value: MessageContextValue;\n}>) => (\n <MessageContext.Provider value={value as unknown as MessageContextValue}>\n {children}\n </MessageContext.Provider>\n);\n\nexport const useMessageContext = (\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n _componentName?: string,\n) => {\n const contextValue = useContext(MessageContext);\n\n if (!contextValue) {\n return {} as MessageContextValue;\n }\n\n return contextValue as unknown as MessageContextValue;\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 = <P extends UnknownType>(\n Component: React.ComponentType<P>,\n) => {\n const WithMessageContextComponent = (props: Omit<P, keyof MessageContextValue>) => {\n const messageContext = useMessageContext();\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, { useContext } from 'react';\nimport Dayjs from 'dayjs';\nimport calendar from 'dayjs/plugin/calendar';\nimport localizedFormat from 'dayjs/plugin/localizedFormat';\nimport type { PropsWithChildren } from 'react';\nimport type { TFunction } from 'i18next';\nimport type { TranslationLanguages } from 'stream-chat';\n\nimport { getDisplayName } from './utils/getDisplayName';\nimport { defaultDateTimeParser, defaultTranslatorFunction } from '../i18n/utils';\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 = (\n props: Omit<P, keyof TranslationContextValue>,\n ) => {\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, { isDayjs } from 'dayjs';\nimport type { Duration as DayjsDuration } from 'dayjs/plugin/duration';\n\nimport type { TFunction } from 'i18next';\nimport type { Moment } from 'moment-timezone';\nimport type {\n DateFormatterOptions,\n DurationFormatterOptions,\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 = (\n output: TDateTimeParserOutput,\n): output is number | string => typeof output === 'string' || typeof output === 'number';\n\nexport const isDayOrMoment = (\n output: TDateTimeParserOutput,\n): output is Dayjs.Dayjs | Moment => !!(output as Dayjs.Dayjs | Moment)?.isSame;\n\nexport const isDate = (output: unknown): output is Date =>\n output !== null &&\n typeof output === 'object' &&\n typeof (output as Date).getTime === 'function';\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 durationFormatter:\n (streamI18n) =>\n (value, _, { format, withSuffix }: DurationFormatterOptions) => {\n if (format && isDayjs(streamI18n.DateTimeParser)) {\n return (streamI18n.DateTimeParser.duration(value) as DayjsDuration).format(\n format,\n );\n }\n return streamI18n.DateTimeParser.duration(value).humanize(!!withSuffix);\n },\n timestampFormatter:\n (streamI18n) =>\n (\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 = ((key: string) => key) as TFunction;\n\nexport const defaultDateTimeParser = (input?: TDateTimeParserInput) => Dayjs(input);\n\nexport const isLanguageSupported = (\n language: string,\n): language is SupportedTranslations => {\n const translations = [\n 'de',\n 'en',\n 'es',\n 'fr',\n 'hi',\n 'it',\n 'ja',\n 'ko',\n 'nl',\n 'pt',\n 'ru',\n 'tr',\n ];\n return translations.some((translation) => language === translation);\n};\n", "import { useEffect, useMemo } from 'react';\nimport { FixedSizeQueueCache, MessageComposer } from 'stream-chat';\nimport { useThreadContext } from '../../Threads';\nimport {\n useChannelStateContext,\n useChatContext,\n useMessageContext,\n} from '../../../context';\nimport { useLegacyThreadContext } from '../../Thread';\n\nconst queueCache = new FixedSizeQueueCache<string, MessageComposer>(64);\n\nexport const useMessageComposer = () => {\n const { client } = useChatContext();\n const { channel } = useChannelStateContext();\n const { editing, message: editedMessage } = useMessageContext();\n // legacy thread will receive new composer\n const { legacyThread: parentMessage } = useLegacyThreadContext();\n const threadInstance = useThreadContext();\n\n const cachedEditedMessage = useMemo(() => {\n if (!editedMessage) return undefined;\n\n return editedMessage;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [editedMessage?.id]);\n\n const cachedParentMessage = useMemo(() => {\n if (!parentMessage) return undefined;\n\n return parentMessage;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [parentMessage?.id]);\n\n // composer hierarchy\n // edited message (always new) -> thread instance (own) -> thread message (always new) -> channel (own)\n // editedMessage ?? thread ?? parentMessage ?? channel;\n const messageComposer = useMemo(() => {\n if (editing && cachedEditedMessage) {\n const tag = MessageComposer.constructTag(cachedEditedMessage);\n\n const cachedComposer = queueCache.get(tag);\n if (cachedComposer) return cachedComposer;\n\n return new MessageComposer({\n client,\n composition: cachedEditedMessage,\n compositionContext: cachedEditedMessage,\n });\n } else if (threadInstance) {\n return threadInstance.messageComposer;\n } else if (cachedParentMessage) {\n const compositionContext = {\n ...cachedParentMessage,\n legacyThreadId: cachedParentMessage.id,\n };\n\n const tag = MessageComposer.constructTag(compositionContext);\n\n const cachedComposer = queueCache.get(tag);\n if (cachedComposer) return cachedComposer;\n\n return new MessageComposer({\n client,\n compositionContext,\n });\n } else {\n return channel.messageComposer;\n }\n }, [\n cachedEditedMessage,\n cachedParentMessage,\n channel,\n client,\n editing,\n threadInstance,\n ]);\n\n if (\n (['legacy_thread', 'message'] as MessageComposer['contextType'][]).includes(\n messageComposer.contextType,\n ) &&\n !queueCache.peek(messageComposer.tag)\n ) {\n queueCache.add(messageComposer.tag, messageComposer);\n }\n\n useEffect(() => {\n const unsubscribe = messageComposer.registerSubscriptions();\n return () => {\n unsubscribe();\n };\n }, [messageComposer]);\n\n return messageComposer;\n};\n", "import React, { createContext, useContext } from 'react';\n\nimport { Channel } from '../../components';\n\nimport type { PropsWithChildren } from 'react';\nimport type { Thread } from 'stream-chat';\n\nexport type ThreadContextValue = Thread | undefined;\n\nexport const ThreadContext = createContext<ThreadContextValue>(undefined);\n\nexport const useThreadContext = () => useContext(ThreadContext);\n\nexport const ThreadProvider = ({\n children,\n thread,\n}: PropsWithChildren<{ thread?: Thread }>) => (\n <ThreadContext.Provider value={thread}>\n <Channel channel={thread?.channel}>{children}</Channel>\n </ThreadContext.Provider>\n);\n", "import React, { useContext } from 'react';\nimport type { LocalMessage } from 'stream-chat';\n\nexport const LegacyThreadContext = React.createContext<{\n legacyThread: LocalMessage | undefined;\n}>({ legacyThread: undefined });\n\nexport const useLegacyThreadContext = () => useContext(LegacyThreadContext);\n", "import React, { createContext, useContext } from 'react';\nimport type { PropsWithChildren } from 'react';\n\nimport type { CooldownTimerState, MessageInputProps } from '../components/MessageInput';\nimport type { MessageInputHookProps } from '../components/MessageInput/hooks/useMessageInputControls';\n\nexport type MessageInputContextValue = MessageInputHookProps &\n Omit<MessageInputProps, 'Input'> &\n CooldownTimerState;\n\nexport const MessageInputContext = createContext<MessageInputHookProps | undefined>(\n undefined,\n);\n\nexport const MessageInputContextProvider = ({\n children,\n value,\n}: PropsWithChildren<{\n value: MessageInputContextValue;\n}>) => (\n <MessageInputContext.Provider value={value as unknown as MessageInputContextValue}>\n {children}\n </MessageInputContext.Provider>\n);\n\nexport const useMessageInputContext = (\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n componentName?: string,\n) => {\n const contextValue = useContext(MessageInputContext);\n\n if (!contextValue) {\n return {} as MessageInputContextValue;\n }\n\n return contextValue as unknown as MessageInputContextValue;\n};\n", "import mergeWith from 'lodash.mergewith';\nimport type {\n Middleware,\n SearchSourceOptions,\n SearchSourceType,\n TextComposerMiddlewareExecutorState,\n TextComposerMiddlewareOptions,\n TextComposerSuggestion,\n} from 'stream-chat';\nimport {\n BaseSearchSource,\n getTokenizedSuggestionDisplayName,\n getTriggerCharWithToken,\n insertItemWithTrigger,\n replaceWordWithEntity,\n} from 'stream-chat';\nimport type {\n EmojiSearchIndex,\n EmojiSearchIndexResult,\n} from '../../../components/MessageInput';\n\nexport type EmojiSuggestion<T extends EmojiSearchIndexResult = EmojiSearchIndexResult> =\n TextComposerSuggestion<T>;\n\nclass EmojiSearchSource<\n T extends TextComposerSuggestion<EmojiSearchIndexResult>,\n> extends BaseSearchSource<T> {\n readonly type: SearchSourceType = 'emoji';\n private emojiSearchIndex: EmojiSearchIndex;\n\n constructor(emojiSearchIndex: EmojiSearchIndex, options?: SearchSourceOptions) {\n super(options);\n this.emojiSearchIndex = emojiSearchIndex;\n }\n\n async query(searchQuery: string) {\n if (searchQuery.length === 0) {\n return { items: [] as T[], next: null };\n }\n const emojis = (await this.emojiSearchIndex.search(searchQuery)) ?? [];\n\n // emojiIndex.search sometimes returns undefined values, so filter those out first\n return {\n items: emojis\n .filter(Boolean)\n .slice(0, 7)\n .map(({ emoticons = [], id, name, native, skins = [] }) => {\n const [firstSkin] = skins;\n\n return {\n emoticons,\n id,\n name,\n native: native ?? firstSkin.native,\n };\n }) as T[],\n next: null, // todo: generate cursor\n };\n }\n\n protected filterQueryResults(items: T[]): T[] | Promise<T[]> {\n return items.map((item) => ({\n ...item,\n ...getTokenizedSuggestionDisplayName({\n displayName: item.id,\n searchToken: this.searchQuery,\n }),\n }));\n }\n}\n\nconst DEFAULT_OPTIONS: TextComposerMiddlewareOptions = { minChars: 1, trigger: ':' };\n\nexport type EmojiMiddleware<T extends EmojiSearchIndexResult = EmojiSearchIndexResult> =\n Middleware<\n TextComposerMiddlewareExecutorState<EmojiSuggestion<T>>,\n 'onChange' | 'onSuggestionItemSelect'\n >;\n\n/**\n * TextComposer middleware for mentions\n * Usage:\n *\n * const textComposer = new TextComposer(options);\n *\n * textComposer.use(new createTextComposerEmojiMiddleware(emojiSearchIndex, {\n * minChars: 2\n * }));\n *\n * @param emojiSearchIndex\n * @param {{\n * minChars: number;\n * trigger: string;\n * }} options\n * @returns\n */\nexport const createTextComposerEmojiMiddleware = (\n emojiSearchIndex: EmojiSearchIndex,\n options?: Partial<TextComposerMiddlewareOptions>,\n): EmojiMiddleware => {\n const finalOptions = mergeWith(DEFAULT_OPTIONS, options ?? {});\n const emojiSearchSource = new EmojiSearchSource(emojiSearchIndex);\n emojiSearchSource.activate();\n\n return {\n id: 'stream-io/emoji-middleware',\n // eslint-disable-next-line sort-keys\n handlers: {\n onChange: async ({ complete, forward, next, state }) => {\n if (!state.selection) return forward();\n\n const triggerWithToken = getTriggerCharWithToken({\n acceptTrailingSpaces: false,\n text: state.text.slice(0, state.selection.end),\n trigger: finalOptions.trigger,\n });\n\n const triggerWasRemoved =\n !triggerWithToken || triggerWithToken.length < finalOptions.minChars;\n\n if (triggerWasRemoved) {\n const hasSuggestionsForTrigger =\n state.suggestions?.trigger === finalOptions.trigger;\n const newState = { ...state };\n if (hasSuggestionsForTrigger && newState.suggestions) {\n delete newState.suggestions;\n }\n return next(newState);\n }\n\n const newSearchTriggerred =\n triggerWithToken && triggerWithToken === finalOptions.trigger;\n\n if (newSearchTriggerred) {\n emojiSearchSource.resetStateAndActivate();\n }\n\n const textWithReplacedWord = await replaceWordWithEntity({\n caretPosition: state.selection.end,\n getEntityString: async (word: string) => {\n const { items } = await emojiSearchSource.query(word);\n\n const emoji = items\n .filter(Boolean)\n .slice(0, 10)\n .find(({ emoticons }) => !!emoticons?.includes(word));\n\n if (!emoji) return null;\n\n const [firstSkin] = emoji.skins ?? [];\n\n return emoji.native ?? firstSkin.native;\n },\n text: state.text,\n });\n\n if (textWithReplacedWord !== state.text) {\n return complete({\n ...state,\n suggestions: undefined, // to prevent the TextComposerMiddlewareExecutor to run the first page query\n text: textWithReplacedWord,\n });\n }\n\n return complete({\n ...state,\n suggestions: {\n query: triggerWithToken.slice(1),\n searchSource: emojiSearchSource,\n trigger: finalOptions.trigger,\n },\n });\n },\n onSuggestionItemSelect: ({ complete, forward, state }) => {\n const { selectedSuggestion } = state.change ?? {};\n if (!selectedSuggestion || state.suggestions?.trigger !== finalOptions.trigger)\n return forward();\n\n emojiSearchSource.resetStateAndActivate();\n return complete({\n ...state,\n ...insertItemWithTrigger({\n insertText: `${'native' in selectedSuggestion ? selectedSuggestion.native : ''} `,\n selection: state.selection,\n text: state.text,\n trigger: finalOptions.trigger,\n }),\n suggestions: undefined, // Clear suggestions after selection\n });\n },\n },\n };\n};\n"],
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["export * from './EmojiPicker';\nexport * from './middleware';\nexport { EmojiPickerIcon } from './icons';\n", "import React, { useEffect, useState } from 'react';\nimport { usePopper } from 'react-popper';\nimport Picker from '@emoji-mart/react';\n\nimport type { Options } from '@popperjs/core';\n\nimport { EmojiPickerIcon } from './icons';\nimport { useMessageInputContext, useTranslationContext } from '../../context';\nimport { useMessageComposer } from '../../components';\n\nconst isShadowRoot = (node: Node): node is ShadowRoot => !!(node as ShadowRoot).host;\n\nexport type EmojiPickerProps = {\n ButtonIconComponent?: React.ComponentType;\n buttonClassName?: string;\n pickerContainerClassName?: string;\n wrapperClassName?: string;\n closeOnEmojiSelect?: boolean;\n /**\n * Untyped [properties](https://github.com/missive/emoji-mart/tree/v5.5.2#options--props) to be\n * passed down to the [emoji-mart `Picker`](https://github.com/missive/emoji-mart/tree/v5.5.2#-picker) component\n */\n pickerProps?: Partial<{ theme: 'auto' | 'light' | 'dark' } & Record<string, unknown>>;\n /**\n * [React Popper options](https://popper.js.org/docs/v2/constructors/#options) to be\n * passed down to the [react-popper `usePopper`](https://popper.js.org/react-popper/v2/hook/) hook\n */\n popperOptions?: Partial<Options>;\n};\n\nconst classNames: EmojiPickerProps = {\n buttonClassName: 'str-chat__emoji-picker-button',\n pickerContainerClassName: 'str-chat__message-textarea-emoji-picker-container',\n wrapperClassName: 'str-chat__message-textarea-emoji-picker',\n};\n\nexport const EmojiPicker = (props: EmojiPickerProps) => {\n const { t } = useTranslationContext('EmojiPicker');\n const { textareaRef } = useMessageInputContext('EmojiPicker');\n const { textComposer } = useMessageComposer();\n const [displayPicker, setDisplayPicker] = useState(false);\n const [referenceElement, setReferenceElement] = useState<HTMLButtonElement | null>(\n null,\n );\n const [popperElement, setPopperElement] = useState<HTMLDivElement | null>(null);\n const { attributes, styles } = usePopper(referenceElement, popperElement, {\n placement: 'top-end',\n ...props.popperOptions,\n });\n\n const { buttonClassName, pickerContainerClassName, wrapperClassName } = classNames;\n\n const { ButtonIconComponent = EmojiPickerIcon } = props;\n\n useEffect(() => {\n if (!popperElement || !referenceElement) return;\n\n const handlePointerDown = (e: PointerEvent) => {\n const target = e.target as HTMLElement;\n\n const rootNode = target.getRootNode();\n\n if (\n popperElement.contains(isShadowRoot(rootNode) ? rootNode.host : target) ||\n referenceElement.contains(target)\n ) {\n return;\n }\n\n setDisplayPicker(false);\n };\n\n window.addEventListener('pointerdown', handlePointerDown);\n return () => window.removeEventListener('pointerdown', handlePointerDown);\n }, [referenceElement, popperElement]);\n\n return (\n <div className={props.wrapperClassName ?? wrapperClassName}>\n {displayPicker && (\n <div\n className={props.pickerContainerClassName ?? pickerContainerClassName}\n style={styles.popper}\n {...attributes.popper}\n ref={setPopperElement}\n >\n <Picker\n data={async () => (await import('@emoji-mart/data')).default}\n onEmojiSelect={(e: { native: string }) => {\n const textarea = textareaRef.current;\n if (!textarea) return;\n textComposer.insertText({ text: e.native });\n textarea.focus();\n if (props.closeOnEmojiSelect) {\n setDisplayPicker(false);\n }\n }}\n {...props.pickerProps}\n />\n </div>\n )}\n <button\n aria-expanded={displayPicker}\n aria-label={t('aria/Emoji picker')}\n className={props.buttonClassName ?? buttonClassName}\n onClick={() => setDisplayPicker((cv) => !cv)}\n ref={setReferenceElement}\n type='button'\n >\n {ButtonIconComponent && <ButtonIconComponent />}\n </button>\n </div>\n );\n};\n", "import React from 'react';\n\nexport const EmojiPickerIcon = () => (\n <svg\n preserveAspectRatio='xMinYMin'\n viewBox='0 0 28 28'\n width='100%'\n xmlns='http://www.w3.org/2000/svg'\n >\n <g clipRule='evenodd' fillRule='evenodd'>\n <path d='M14 4.4C8.6 4.4 4.4 8.6 4.4 14c0 5.4 4.2 9.6 9.6 9.6c5.4 0 9.6-4.2 9.6-9.6c0-5.4-4.2-9.6-9.6-9.6zM2 14c0-6.6 5.4-12 12-12s12 5.4 12 12s-5.4 12-12 12s-12-5.4-12-12zM12.8 11c0 1-.8 1.8-1.8 1.8s-1.8-.8-1.8-1.8s.8-1.8 1.8-1.8s1.8.8 1.8 1.8zM18.8 11c0 1-.8 1.8-1.8 1.8s-1.8-.8-1.8-1.8s.8-1.8 1.8-1.8s1.8.8 1.8 1.8zM8.6 15.4c.6-.4 1.2-.2 1.6.2c.6.8 1.6 1.8 3 2c1.2.4 2.8.2 4.8-2c.4-.4 1.2-.6 1.6 0c.4.4.6 1.2 0 1.6c-2.2 2.6-4.8 3.4-7 3c-2-.4-3.6-1.8-4.4-3c-.4-.6-.2-1.2.4-1.8z'></path>\n </g>\n </svg>\n);\n", "import type { PropsWithChildren } from 'react';\nimport React, { useContext } from 'react';\nimport type {\n Channel,\n ChannelConfigWithInfo,\n LocalMessage,\n Mute,\n ChannelState as StreamChannelState,\n} from 'stream-chat';\n\nimport type {\n ChannelUnreadUiState,\n GiphyVersions,\n ImageAttachmentSizeHandler,\n UnknownType,\n VideoAttachmentSizeHandler,\n} from '../types/types';\n\nexport type ChannelNotifications = Array<{\n id: string;\n text: string;\n type: 'success' | 'error';\n}>;\n\nexport type ChannelState = {\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['members'];\n messages?: LocalMessage[];\n pinnedMessages?: LocalMessage[];\n read?: StreamChannelState['read'];\n thread?: LocalMessage | null;\n threadHasMore?: boolean;\n threadLoadingMore?: boolean;\n threadMessages?: LocalMessage[];\n threadSuppressAutoscroll?: boolean;\n typing?: StreamChannelState['typing'];\n watcherCount?: number;\n watchers?: StreamChannelState['watchers'];\n};\n\nexport type ChannelStateContextValue = Omit<ChannelState, 'typing'> & {\n channel: Channel;\n channelCapabilities: Record<string, boolean>;\n channelConfig: ChannelConfigWithInfo | undefined;\n imageAttachmentSizeHandler: ImageAttachmentSizeHandler;\n notifications: ChannelNotifications;\n shouldGenerateVideoThumbnail: boolean;\n videoAttachmentSizeHandler: VideoAttachmentSizeHandler;\n channelUnreadUiState?: ChannelUnreadUiState;\n giphyVersion?: GiphyVersions;\n mutes?: Array<Mute>;\n watcher_count?: number;\n};\n\nexport const ChannelStateContext = React.createContext<\n ChannelStateContextValue | undefined\n>(undefined);\n\nexport const ChannelStateProvider = ({\n children,\n value,\n}: PropsWithChildren<{\n value: ChannelStateContextValue;\n}>) => (\n <ChannelStateContext.Provider value={value as unknown as ChannelStateContextValue}>\n {children}\n </ChannelStateContext.Provider>\n);\n\nexport const useChannelStateContext = (componentName?: string) => {\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;\n }\n\n return contextValue as unknown as ChannelStateContextValue;\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 = <P extends UnknownType>(\n Component: React.ComponentType<P>,\n) => {\n const WithChannelStateContextComponent = (\n props: Omit<P, keyof ChannelStateContextValue>,\n ) => {\n const channelStateContext = useChannelStateContext();\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, { useContext } from 'react';\nimport type { PropsWithChildren } from 'react';\nimport type {\n AppSettingsAPIResponse,\n Channel,\n Mute,\n SearchController,\n} from 'stream-chat';\n\nimport { getDisplayName } from './utils/getDisplayName';\nimport type { ChatProps } from '../components/Chat/Chat';\nimport type { 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 ChannelConfId = string; // e.g.: \"messaging:general\"\n\nexport type ChatContextValue = {\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> | null;\n latestMessageDatesByChannels: Record<ChannelConfId, Date>;\n mutes: Array<Mute>;\n openMobileNav: () => void;\n /** Instance of SearchController class that allows to control all the search operations. */\n searchController: SearchController;\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,\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;\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, 'isMessageAIGenerated'>> &\n Required<Pick<ChatProps, 'theme' | 'client'>>;\n\nexport const ChatContext = React.createContext<ChatContextValue | undefined>(undefined);\n\nexport const ChatProvider = ({\n children,\n value,\n}: PropsWithChildren<{\n value: ChatContextValue;\n}>) => (\n <ChatContext.Provider value={value as unknown as ChatContextValue}>\n {children}\n </ChatContext.Provider>\n);\n\nexport const useChatContext = (componentName?: string) => {\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;\n }\n\n return contextValue as unknown as ChatContextValue;\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 = <P extends UnknownType>(\n Component: React.ComponentType<P>,\n) => {\n const WithChatContextComponent = (props: Omit<P, keyof ChatContextValue>) => {\n const chatContext = useChatContext();\n\n return <Component {...(props as P)} {...chatContext} />;\n };\n WithChatContextComponent.displayName = `WithChatContext${getDisplayName(Component)}`;\n return WithChatContextComponent;\n};\n", "import type { PropsWithChildren, ReactNode } from 'react';\nimport React, { useContext } from 'react';\n\nimport type {\n LocalMessage,\n Mute,\n ReactionResponse,\n ReactionSort,\n UserResponse,\n} from 'stream-chat';\n\nimport type { ChannelActionContextValue } from './ChannelActionContext';\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 { UnknownType } from '../types/types';\n\nexport type CustomMessageActions = {\n [key: string]: (\n message: LocalMessage,\n event: React.BaseSyntheticEvent,\n ) => Promise<void> | void;\n};\n\nexport type MessageContextValue = {\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,\n sort?: ReactionSort,\n ) => Promise<Array<ReactionResponse>>;\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: (\n reactionType: string,\n event: React.BaseSyntheticEvent,\n ) => Promise<void>;\n /** Function to retry sending a Message */\n handleRetry: ChannelActionContextValue['retrySendMessage'];\n /** Function that returns whether the Message belongs to the current user */\n isMyMessage: () => boolean;\n /** The message object */\n message: LocalMessage;\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;\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;\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: LocalMessage) => 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[];\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;\n /** A list of users that have read this Message */\n readBy?: UserResponse[];\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[],\n options?: RenderTextOptions,\n ) => ReactNode;\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>(\n undefined,\n);\n\nexport const MessageProvider = ({\n children,\n value,\n}: PropsWithChildren<{\n value: MessageContextValue;\n}>) => (\n <MessageContext.Provider value={value as unknown as MessageContextValue}>\n {children}\n </MessageContext.Provider>\n);\n\nexport const useMessageContext = (\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n _componentName?: string,\n) => {\n const contextValue = useContext(MessageContext);\n\n if (!contextValue) {\n return {} as MessageContextValue;\n }\n\n return contextValue as unknown as MessageContextValue;\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 = <P extends UnknownType>(\n Component: React.ComponentType<P>,\n) => {\n const WithMessageContextComponent = (props: Omit<P, keyof MessageContextValue>) => {\n const messageContext = useMessageContext();\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, { useContext } from 'react';\nimport Dayjs from 'dayjs';\nimport calendar from 'dayjs/plugin/calendar';\nimport localizedFormat from 'dayjs/plugin/localizedFormat';\nimport type { PropsWithChildren } from 'react';\nimport type { TFunction } from 'i18next';\nimport type { TranslationLanguages } from 'stream-chat';\n\nimport { getDisplayName } from './utils/getDisplayName';\nimport { defaultDateTimeParser, defaultTranslatorFunction } from '../i18n/utils';\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 = (\n props: Omit<P, keyof TranslationContextValue>,\n ) => {\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, { isDayjs } from 'dayjs';\nimport type { Duration as DayjsDuration } from 'dayjs/plugin/duration';\n\nimport type { TFunction } from 'i18next';\nimport type { Moment } from 'moment-timezone';\nimport type {\n DateFormatterOptions,\n DurationFormatterOptions,\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 = (\n output: TDateTimeParserOutput,\n): output is number | string => typeof output === 'string' || typeof output === 'number';\n\nexport const isDayOrMoment = (\n output: TDateTimeParserOutput,\n): output is Dayjs.Dayjs | Moment => !!(output as Dayjs.Dayjs | Moment)?.isSame;\n\nexport const isDate = (output: unknown): output is Date =>\n output !== null &&\n typeof output === 'object' &&\n typeof (output as Date).getTime === 'function';\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 durationFormatter:\n (streamI18n) =>\n (value, _, { format, withSuffix }: DurationFormatterOptions) => {\n if (format && isDayjs(streamI18n.DateTimeParser)) {\n return (streamI18n.DateTimeParser.duration(value) as DayjsDuration).format(\n format,\n );\n }\n return streamI18n.DateTimeParser.duration(value).humanize(!!withSuffix);\n },\n timestampFormatter:\n (streamI18n) =>\n (\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 = ((key: string) => key) as TFunction;\n\nexport const defaultDateTimeParser = (input?: TDateTimeParserInput) => Dayjs(input);\n\nexport const isLanguageSupported = (\n language: string,\n): language is SupportedTranslations => {\n const translations = [\n 'de',\n 'en',\n 'es',\n 'fr',\n 'hi',\n 'it',\n 'ja',\n 'ko',\n 'nl',\n 'pt',\n 'ru',\n 'tr',\n ];\n return translations.some((translation) => language === translation);\n};\n", "import { useEffect, useMemo } from 'react';\nimport { FixedSizeQueueCache, MessageComposer } from 'stream-chat';\nimport { useThreadContext } from '../../Threads';\nimport {\n useChannelStateContext,\n useChatContext,\n useMessageContext,\n} from '../../../context';\nimport { useLegacyThreadContext } from '../../Thread';\n\nconst queueCache = new FixedSizeQueueCache<string, MessageComposer>(64);\n\nexport const useMessageComposer = () => {\n const { client } = useChatContext();\n const { channel } = useChannelStateContext();\n const { editing, message: editedMessage } = useMessageContext();\n // legacy thread will receive new composer\n const { legacyThread: parentMessage } = useLegacyThreadContext();\n const threadInstance = useThreadContext();\n\n const cachedEditedMessage = useMemo(() => {\n if (!editedMessage) return undefined;\n\n return editedMessage;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [editedMessage?.id]);\n\n const cachedParentMessage = useMemo(() => {\n if (!parentMessage) return undefined;\n\n return parentMessage;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [parentMessage?.id]);\n\n // composer hierarchy\n // edited message (always new) -> thread instance (own) -> thread message (always new) -> channel (own)\n // editedMessage ?? thread ?? parentMessage ?? channel;\n const messageComposer = useMemo(() => {\n if (editing && cachedEditedMessage) {\n const tag = MessageComposer.constructTag(cachedEditedMessage);\n\n const cachedComposer = queueCache.get(tag);\n if (cachedComposer) {\n cachedComposer.editedMessage = cachedEditedMessage;\n return cachedComposer;\n }\n\n return new MessageComposer({\n client,\n composition: cachedEditedMessage,\n compositionContext: cachedEditedMessage,\n });\n } else if (threadInstance) {\n return threadInstance.messageComposer;\n } else if (cachedParentMessage) {\n const compositionContext = {\n ...cachedParentMessage,\n legacyThreadId: cachedParentMessage.id,\n };\n\n const tag = MessageComposer.constructTag(compositionContext);\n\n const cachedComposer = queueCache.get(tag);\n if (cachedComposer) return cachedComposer;\n\n return new MessageComposer({\n client,\n compositionContext,\n });\n } else {\n return channel.messageComposer;\n }\n }, [\n cachedEditedMessage,\n cachedParentMessage,\n channel,\n client,\n editing,\n threadInstance,\n ]);\n\n if (\n (['legacy_thread', 'message'] as MessageComposer['contextType'][]).includes(\n messageComposer.contextType,\n ) &&\n !queueCache.peek(messageComposer.tag)\n ) {\n queueCache.add(messageComposer.tag, messageComposer);\n }\n\n useEffect(() => {\n const unsubscribe = messageComposer.registerSubscriptions();\n return () => {\n unsubscribe();\n };\n }, [messageComposer]);\n\n return messageComposer;\n};\n", "import React, { createContext, useContext } from 'react';\n\nimport { Channel } from '../../components';\n\nimport type { PropsWithChildren } from 'react';\nimport type { Thread } from 'stream-chat';\n\nexport type ThreadContextValue = Thread | undefined;\n\nexport const ThreadContext = createContext<ThreadContextValue>(undefined);\n\nexport const useThreadContext = () => useContext(ThreadContext);\n\nexport const ThreadProvider = ({\n children,\n thread,\n}: PropsWithChildren<{ thread?: Thread }>) => (\n <ThreadContext.Provider value={thread}>\n <Channel channel={thread?.channel}>{children}</Channel>\n </ThreadContext.Provider>\n);\n", "import React, { useContext } from 'react';\nimport type { LocalMessage } from 'stream-chat';\n\nexport const LegacyThreadContext = React.createContext<{\n legacyThread: LocalMessage | undefined;\n}>({ legacyThread: undefined });\n\nexport const useLegacyThreadContext = () => useContext(LegacyThreadContext);\n", "import React, { createContext, useContext } from 'react';\nimport type { PropsWithChildren } from 'react';\n\nimport type { CooldownTimerState, MessageInputProps } from '../components/MessageInput';\nimport type { MessageInputHookProps } from '../components/MessageInput/hooks/useMessageInputControls';\n\nexport type MessageInputContextValue = MessageInputHookProps &\n Omit<MessageInputProps, 'Input'> &\n CooldownTimerState;\n\nexport const MessageInputContext = createContext<MessageInputHookProps | undefined>(\n undefined,\n);\n\nexport const MessageInputContextProvider = ({\n children,\n value,\n}: PropsWithChildren<{\n value: MessageInputContextValue;\n}>) => (\n <MessageInputContext.Provider value={value as unknown as MessageInputContextValue}>\n {children}\n </MessageInputContext.Provider>\n);\n\nexport const useMessageInputContext = (\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n componentName?: string,\n) => {\n const contextValue = useContext(MessageInputContext);\n\n if (!contextValue) {\n return {} as MessageInputContextValue;\n }\n\n return contextValue as unknown as MessageInputContextValue;\n};\n", "import mergeWith from 'lodash.mergewith';\nimport type {\n Middleware,\n SearchSourceOptions,\n SearchSourceType,\n TextComposerMiddlewareExecutorState,\n TextComposerMiddlewareOptions,\n TextComposerSuggestion,\n} from 'stream-chat';\nimport {\n BaseSearchSource,\n getTokenizedSuggestionDisplayName,\n getTriggerCharWithToken,\n insertItemWithTrigger,\n replaceWordWithEntity,\n} from 'stream-chat';\nimport type {\n EmojiSearchIndex,\n EmojiSearchIndexResult,\n} from '../../../components/MessageInput';\n\nexport type EmojiSuggestion<T extends EmojiSearchIndexResult = EmojiSearchIndexResult> =\n TextComposerSuggestion<T>;\n\nclass EmojiSearchSource<\n T extends TextComposerSuggestion<EmojiSearchIndexResult>,\n> extends BaseSearchSource<T> {\n readonly type: SearchSourceType = 'emoji';\n private emojiSearchIndex: EmojiSearchIndex;\n\n constructor(emojiSearchIndex: EmojiSearchIndex, options?: SearchSourceOptions) {\n super(options);\n this.emojiSearchIndex = emojiSearchIndex;\n }\n\n async query(searchQuery: string) {\n if (searchQuery.length === 0) {\n return { items: [] as T[], next: null };\n }\n const emojis = (await this.emojiSearchIndex.search(searchQuery)) ?? [];\n\n // emojiIndex.search sometimes returns undefined values, so filter those out first\n return {\n items: emojis\n .filter(Boolean)\n .slice(0, 7)\n .map(({ emoticons = [], id, name, native, skins = [] }) => {\n const [firstSkin] = skins;\n\n return {\n emoticons,\n id,\n name,\n native: native ?? firstSkin.native,\n };\n }) as T[],\n next: null, // todo: generate cursor\n };\n }\n\n protected filterQueryResults(items: T[]): T[] | Promise<T[]> {\n return items.map((item) => ({\n ...item,\n ...getTokenizedSuggestionDisplayName({\n displayName: item.id,\n searchToken: this.searchQuery,\n }),\n }));\n }\n}\n\nconst DEFAULT_OPTIONS: TextComposerMiddlewareOptions = { minChars: 1, trigger: ':' };\n\nexport type EmojiMiddleware<T extends EmojiSearchIndexResult = EmojiSearchIndexResult> =\n Middleware<\n TextComposerMiddlewareExecutorState<EmojiSuggestion<T>>,\n 'onChange' | 'onSuggestionItemSelect'\n >;\n\n/**\n * TextComposer middleware for mentions\n * Usage:\n *\n * const textComposer = new TextComposer(options);\n *\n * textComposer.use(new createTextComposerEmojiMiddleware(emojiSearchIndex, {\n * minChars: 2\n * }));\n *\n * @param emojiSearchIndex\n * @param {{\n * minChars: number;\n * trigger: string;\n * }} options\n * @returns\n */\nexport const createTextComposerEmojiMiddleware = (\n emojiSearchIndex: EmojiSearchIndex,\n options?: Partial<TextComposerMiddlewareOptions>,\n): EmojiMiddleware => {\n const finalOptions = mergeWith(DEFAULT_OPTIONS, options ?? {});\n const emojiSearchSource = new EmojiSearchSource(emojiSearchIndex);\n emojiSearchSource.activate();\n\n return {\n id: 'stream-io/emoji-middleware',\n // eslint-disable-next-line sort-keys\n handlers: {\n onChange: async ({ complete, forward, next, state }) => {\n if (!state.selection) return forward();\n\n const triggerWithToken = getTriggerCharWithToken({\n acceptTrailingSpaces: false,\n text: state.text.slice(0, state.selection.end),\n trigger: finalOptions.trigger,\n });\n\n const triggerWasRemoved =\n !triggerWithToken || triggerWithToken.length < finalOptions.minChars;\n\n if (triggerWasRemoved) {\n const hasSuggestionsForTrigger =\n state.suggestions?.trigger === finalOptions.trigger;\n const newState = { ...state };\n if (hasSuggestionsForTrigger && newState.suggestions) {\n delete newState.suggestions;\n }\n return next(newState);\n }\n\n const newSearchTriggerred =\n triggerWithToken && triggerWithToken === finalOptions.trigger;\n\n if (newSearchTriggerred) {\n emojiSearchSource.resetStateAndActivate();\n }\n\n const textWithReplacedWord = await replaceWordWithEntity({\n caretPosition: state.selection.end,\n getEntityString: async (word: string) => {\n const { items } = await emojiSearchSource.query(word);\n\n const emoji = items\n .filter(Boolean)\n .slice(0, 10)\n .find(({ emoticons }) => !!emoticons?.includes(word));\n\n if (!emoji) return null;\n\n const [firstSkin] = emoji.skins ?? [];\n\n return emoji.native ?? firstSkin.native;\n },\n text: state.text,\n });\n\n if (textWithReplacedWord !== state.text) {\n return complete({\n ...state,\n suggestions: undefined, // to prevent the TextComposerMiddlewareExecutor to run the first page query\n text: textWithReplacedWord,\n });\n }\n\n return complete({\n ...state,\n suggestions: {\n query: triggerWithToken.slice(1),\n searchSource: emojiSearchSource,\n trigger: finalOptions.trigger,\n },\n });\n },\n onSuggestionItemSelect: ({ complete, forward, state }) => {\n const { selectedSuggestion } = state.change ?? {};\n if (!selectedSuggestion || state.suggestions?.trigger !== finalOptions.trigger)\n return forward();\n\n emojiSearchSource.resetStateAndActivate();\n return complete({\n ...state,\n ...insertItemWithTrigger({\n insertText: `${'native' in selectedSuggestion ? selectedSuggestion.native : ''} `,\n selection: state.selection,\n text: state.text,\n trigger: finalOptions.trigger,\n }),\n suggestions: undefined, // Clear suggestions after selection\n });\n },\n },\n };\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["import_react", "React", "import_react", "React", "import_react", "React", "import_react", "React", "import_react", "import_dayjs", "Dayjs", "Dayjs", "calendar", "localizedFormat", "React", "import_react", "import_react", "import_react", "React", "import_react", "React", "Picker", "import_stream_chat", "mergeWith"]
|
|
7
7
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export type StableCallback<A extends unknown[], R> = (...args: A) => R;
|
|
2
|
+
/**
|
|
3
|
+
* A utility hook implementing a stable callback. It takes in an unstable method that
|
|
4
|
+
* is supposed to be invoked somewhere deeper in the DOM tree without making it
|
|
5
|
+
* change its reference every time the parent component rerenders. It will also return
|
|
6
|
+
* the value of the callback if it does return one.
|
|
7
|
+
* A common use-case would be having a function whose invocation depends on state
|
|
8
|
+
* somewhere high up in the DOM tree and wanting to use the same function deeper
|
|
9
|
+
* down, for example in a leaf node and simply using useCallback results in
|
|
10
|
+
* cascading dependency hell. If we wrap it in useStableCallback, we would be able
|
|
11
|
+
* to:
|
|
12
|
+
* - Use the same function as a dependency of another hook (since it is stable)
|
|
13
|
+
* - Still invoke it and get the latest state
|
|
14
|
+
*
|
|
15
|
+
* **Caveats:**
|
|
16
|
+
* - Never wrap a function that is supposed to return a React.ReactElement in
|
|
17
|
+
* useStableCallback, since React will not know that the DOM needs to be updated
|
|
18
|
+
* whenever the callback value changes (for example, renderItem from FlatList must
|
|
19
|
+
* never be wrapped in this hook)
|
|
20
|
+
* - Always prefer using a standard useCallback/stable function wherever possible
|
|
21
|
+
* (the purpose of useStableCallback is to bridge the gap between top level contexts
|
|
22
|
+
* and cascading rereders in downstream components - **not** as an escape hatch)
|
|
23
|
+
* @param callback - the callback we want to stabilize
|
|
24
|
+
*/
|
|
25
|
+
export declare const useStableCallback: <A extends unknown[], R>(callback: StableCallback<A, R>) => StableCallback<A, R>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { useCallback, useRef } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* A utility hook implementing a stable callback. It takes in an unstable method that
|
|
4
|
+
* is supposed to be invoked somewhere deeper in the DOM tree without making it
|
|
5
|
+
* change its reference every time the parent component rerenders. It will also return
|
|
6
|
+
* the value of the callback if it does return one.
|
|
7
|
+
* A common use-case would be having a function whose invocation depends on state
|
|
8
|
+
* somewhere high up in the DOM tree and wanting to use the same function deeper
|
|
9
|
+
* down, for example in a leaf node and simply using useCallback results in
|
|
10
|
+
* cascading dependency hell. If we wrap it in useStableCallback, we would be able
|
|
11
|
+
* to:
|
|
12
|
+
* - Use the same function as a dependency of another hook (since it is stable)
|
|
13
|
+
* - Still invoke it and get the latest state
|
|
14
|
+
*
|
|
15
|
+
* **Caveats:**
|
|
16
|
+
* - Never wrap a function that is supposed to return a React.ReactElement in
|
|
17
|
+
* useStableCallback, since React will not know that the DOM needs to be updated
|
|
18
|
+
* whenever the callback value changes (for example, renderItem from FlatList must
|
|
19
|
+
* never be wrapped in this hook)
|
|
20
|
+
* - Always prefer using a standard useCallback/stable function wherever possible
|
|
21
|
+
* (the purpose of useStableCallback is to bridge the gap between top level contexts
|
|
22
|
+
* and cascading rereders in downstream components - **not** as an escape hatch)
|
|
23
|
+
* @param callback - the callback we want to stabilize
|
|
24
|
+
*/
|
|
25
|
+
export const useStableCallback = (callback) => {
|
|
26
|
+
const ref = useRef(callback);
|
|
27
|
+
ref.current = callback;
|
|
28
|
+
return useCallback((...args) => ref.current(...args), []);
|
|
29
|
+
};
|