UNPKG

stream-chat-react

Version:

React components to create chat conversations or livestream style chat

51 lines (50 loc) 2.98 kB
import clsx from 'clsx'; import React, { useEffect, useState } from 'react'; import { CommandItem } from './CommandItem'; import { EmoticonItem } from './EmoticonItem'; import { SuggestionListItem as DefaultSuggestionListItem } from './SuggestionListItem'; import { UserItem } from './UserItem'; import { useComponentContext } from '../../../context/ComponentContext'; import { useStateStore } from '../../../store'; import { InfiniteScrollPaginator } from '../../InfiniteScrollPaginator/InfiniteScrollPaginator'; import { useMessageComposer } from '../../MessageInput'; const textComposerStateSelector = (state) => ({ suggestions: state.suggestions, }); const searchSourceStateSelector = (nextValue) => ({ items: nextValue.items ?? [], }); export const defaultComponents = { '/': (props) => (React.createElement(CommandItem, { entity: props.entity })), ':': (props) => (React.createElement(EmoticonItem, { entity: props.entity })), '@': (props) => (React.createElement(UserItem, { entity: props.entity })), }; export const SuggestionList = ({ className, closeOnClickOutside = true, containerClassName, focusedItemIndex, setFocusedItemIndex, suggestionItemComponents = defaultComponents, }) => { const { AutocompleteSuggestionItem = DefaultSuggestionListItem } = useComponentContext(); const messageComposer = useMessageComposer(); const { textComposer } = messageComposer; const { suggestions } = useStateStore(textComposer.state, textComposerStateSelector); const { items } = useStateStore(suggestions?.searchSource.state, searchSourceStateSelector) ?? {}; const [container, setContainer] = useState(null); const component = suggestions?.trigger ? suggestionItemComponents[suggestions?.trigger] : undefined; useEffect(() => { if (!closeOnClickOutside || !suggestions || !container) return; const handleClick = (event) => { if (container.contains(event.target)) return; textComposer.closeSuggestions(); }; document.addEventListener('click', handleClick); return () => { document.removeEventListener('click', handleClick); }; }, [closeOnClickOutside, suggestions, container, textComposer]); if (!suggestions || !items?.length || !component) return null; return (React.createElement("div", { className: clsx('str-chat__suggestion-list-container', containerClassName), ref: setContainer }, React.createElement(InfiniteScrollPaginator, { loadNextOnScrollToBottom: suggestions.searchSource.search, threshold: 100 }, React.createElement("ul", { className: clsx('str-chat__suggestion-list str-chat__suggestion-list--react', className) }, items.map((item, i) => (React.createElement(AutocompleteSuggestionItem, { component: component, focused: focusedItemIndex === i, item: item, key: item.id.toString(), onMouseEnter: () => setFocusedItemIndex?.(i) }))))))); };