import React, { PropsWithChildren, useContext, useState } from 'react'; import { getDisplayName } from '../utils/getDisplayName'; import type { CommandResponse, UserResponse } from 'stream-chat'; import type { Emoji } from '../../emoji-data/compiled'; import type { DefaultCommandType, DefaultUserType, UnknownType } from '../../types/types'; export type SuggestionComponentType< Co extends string = DefaultCommandType, Us extends UnknownType = DefaultUserType, > = string | React.ReactElement<{ item: Suggestion }>; export const isSuggestionCommand = < Co extends string = DefaultCommandType, Us extends UnknownType = DefaultUserType, >( suggestion: Suggestion, ): suggestion is SuggestionCommand => 'args' in suggestion; export const isSuggestionEmoji = < Co extends string = DefaultCommandType, Us extends UnknownType = DefaultUserType, >( suggestion: Suggestion, ): suggestion is Emoji => 'unicode' in suggestion; export const isSuggestionUser = < Co extends string = DefaultCommandType, Us extends UnknownType = DefaultUserType, >( suggestion: Suggestion, ): suggestion is SuggestionUser => 'id' in suggestion; export type Suggestion< Co extends string = DefaultCommandType, Us extends UnknownType = DefaultUserType, > = SuggestionCommand | SuggestionUser | Emoji; export type SuggestionCommand = CommandResponse; export type SuggestionUser = UserResponse; export type Suggestions< Co extends string = DefaultCommandType, Us extends UnknownType = DefaultUserType, > = { data: Suggestion[]; onSelect: (item: Suggestion) => void; }; export type SuggestionsContextValue< Co extends string = DefaultCommandType, Us extends UnknownType = DefaultUserType, > = { /** Override handler for closing suggestions (mentions, command autocomplete etc) */ closeSuggestions: () => void; /** * Override handler for opening suggestions (mentions, command autocomplete etc) * * @param component {Component|element} UI Component for suggestion item. * @param title {string} Title for suggestions box * * @overrideType Function */ openSuggestions: ( component: SuggestionComponentType, title?: React.ReactElement, ) => Promise; /** * Override handler for updating suggestions (mentions, command autocomplete etc) * * @param newSuggestions {Component|element} UI Component for suggestion item. * @param newSuggestionsTitle {string} Title for suggestions box * * @overrideType Function */ updateSuggestions: ( newSuggestions: Suggestions, newSuggestionsTitle?: React.ReactElement, ) => void; componentType?: SuggestionComponentType; suggestions?: Suggestions; suggestionsTitle?: React.ReactElement; suggestionsViewActive?: boolean; }; export const SuggestionsContext = React.createContext({} as SuggestionsContextValue); /** * This provider component exposes the properties stored within the SuggestionsContext. */ export const SuggestionsProvider = < Co extends string = DefaultCommandType, Us extends UnknownType = DefaultUserType, >({ children, value, }: PropsWithChildren<{ value?: Partial> }>) => { const [componentType, setComponentType] = useState>(''); const [suggestions, setSuggestions] = useState>(); const [suggestionsTitle, setSuggestionsTitle] = useState(); const [suggestionsViewActive, setSuggestionsViewActive] = useState(false); const openSuggestions = ( component: SuggestionComponentType, title?: React.ReactElement, ) => { setComponentType(component); setSuggestionsTitle(title); setSuggestionsViewActive(true); }; const updateSuggestions = ( newSuggestions: Suggestions, newSuggestionsTitle?: React.ReactElement, ) => { setSuggestions(newSuggestions); if (newSuggestionsTitle) { setSuggestionsTitle(newSuggestionsTitle); } setSuggestionsViewActive(!!componentType); }; const closeSuggestions = () => { setComponentType(''); setSuggestions(undefined); setSuggestionsTitle(undefined); setSuggestionsViewActive(false); }; const suggestionsContext = { closeSuggestions: value?.closeSuggestions || closeSuggestions, componentType, openSuggestions: value?.openSuggestions || openSuggestions, suggestions, suggestionsTitle, suggestionsViewActive, updateSuggestions: value?.updateSuggestions || updateSuggestions, }; return ( {children} ); }; export const useSuggestionsContext = < Co extends string = DefaultCommandType, Us extends UnknownType = DefaultUserType, >() => useContext(SuggestionsContext) as unknown as SuggestionsContextValue; export const withSuggestionsContext = < P extends UnknownType, Co extends string = DefaultCommandType, Us extends UnknownType = DefaultUserType, >( Component: React.ComponentType

, ): React.FC>> => { const WithSuggestionsContextComponent = ( props: Omit>, ) => { const suggestionsContext = useSuggestionsContext(); return ; }; WithSuggestionsContextComponent.displayName = `WithSuggestionsContext${getDisplayName( Component, )}`; return WithSuggestionsContextComponent; };