stream-chat-react
Version:
React components to create chat conversations or livestream style chat
55 lines (54 loc) • 3.08 kB
JavaScript
import React, { useEffect, useState } from 'react';
import { usePopper } from 'react-popper';
import Picker from '@emoji-mart/react';
import { EmojiPickerIcon } from './icons';
import { useMessageInputContext, useTranslationContext } from '../../context';
import { useMessageComposer } from '../../components';
const isShadowRoot = (node) => !!node.host;
const classNames = {
buttonClassName: 'str-chat__emoji-picker-button',
pickerContainerClassName: 'str-chat__message-textarea-emoji-picker-container',
wrapperClassName: 'str-chat__message-textarea-emoji-picker',
};
export const EmojiPicker = (props) => {
const { t } = useTranslationContext('EmojiPicker');
const { textareaRef } = useMessageInputContext('EmojiPicker');
const { textComposer } = useMessageComposer();
const [displayPicker, setDisplayPicker] = useState(false);
const [referenceElement, setReferenceElement] = useState(null);
const [popperElement, setPopperElement] = useState(null);
const { attributes, styles } = usePopper(referenceElement, popperElement, {
placement: 'top-end',
...props.popperOptions,
});
const { buttonClassName, pickerContainerClassName, wrapperClassName } = classNames;
const { ButtonIconComponent = EmojiPickerIcon } = props;
useEffect(() => {
if (!popperElement || !referenceElement)
return;
const handlePointerDown = (e) => {
const target = e.target;
const rootNode = target.getRootNode();
if (popperElement.contains(isShadowRoot(rootNode) ? rootNode.host : target) ||
referenceElement.contains(target)) {
return;
}
setDisplayPicker(false);
};
window.addEventListener('pointerdown', handlePointerDown);
return () => window.removeEventListener('pointerdown', handlePointerDown);
}, [referenceElement, popperElement]);
return (React.createElement("div", { className: props.wrapperClassName ?? wrapperClassName },
displayPicker && (React.createElement("div", { className: props.pickerContainerClassName ?? pickerContainerClassName, style: styles.popper, ...attributes.popper, ref: setPopperElement },
React.createElement(Picker, { data: async () => (await import('@emoji-mart/data')).default, onEmojiSelect: (e) => {
const textarea = textareaRef.current;
if (!textarea)
return;
textComposer.insertText({ text: e.native });
textarea.focus();
if (props.closeOnEmojiSelect) {
setDisplayPicker(false);
}
}, ...props.pickerProps }))),
React.createElement("button", { "aria-expanded": displayPicker, "aria-label": t('aria/Emoji picker'), className: props.buttonClassName ?? buttonClassName, onClick: () => setDisplayPicker((cv) => !cv), ref: setReferenceElement, type: 'button' }, ButtonIconComponent && React.createElement(ButtonIconComponent, null))));
};