import { Placement } from '@popperjs/core'; import clsx from 'clsx'; import React, { useEffect, useState } from 'react'; import { usePopper } from 'react-popper'; import { Emoji, HStack, IconButton } from 'soapbox/components/ui'; import { Picker } from 'soapbox/features/emoji/emoji-picker'; import { useSoapboxConfig } from 'soapbox/hooks'; interface IEmojiButton { /** Unicode emoji character. */ emoji: string /** Event handler when the emoji is clicked. */ onClick(emoji: string): void /** Extra class name on the ); }; interface IEmojiSelector { onClose?(): void /** Event handler when an emoji is clicked. */ onReact(emoji: string): void /** Element that triggers the EmojiSelector Popper */ referenceElement: HTMLElement | null placement?: Placement /** Whether the selector should be visible. */ visible?: boolean /** X/Y offset of the floating picker. */ offset?: [number, number] /** Whether to allow any emoji to be chosen. */ all?: boolean } /** Panel with a row of emoji buttons. */ const EmojiSelector: React.FC = ({ referenceElement, onClose, onReact, placement = 'top', visible = false, offset = [-10, 0], all = true, }): JSX.Element => { const soapboxConfig = useSoapboxConfig(); const [expanded, setExpanded] = useState(false); // `useRef` won't trigger a re-render, while `useState` does. // https://popper.js.org/react-popper/v2/ const [popperElement, setPopperElement] = useState(null); const handleClickOutside = (event: MouseEvent) => { if (referenceElement?.contains(event.target as Node) || popperElement?.contains(event.target as Node)) { return; } if (onClose) { onClose(); } }; const { styles, attributes, update } = usePopper(referenceElement, popperElement, { placement, modifiers: [ { name: 'offset', options: { offset, }, }, ], }); const handleExpand: React.MouseEventHandler = () => { setExpanded(true); }; useEffect(() => { setExpanded(false); }, [visible]); useEffect(() => { document.addEventListener('mousedown', handleClickOutside); return () => { document.removeEventListener('mousedown', handleClickOutside); }; }, [referenceElement]); useEffect(() => { if (visible && update) { update(); } }, [visible, update]); return (
{expanded ? ( require('emoji-datasource/img/twitter/sheets/32.png')} onClick={(emoji: any) => onReact(emoji.native)} /> ) : ( {Array.from(soapboxConfig.allowedEmoji).map((emoji, i) => ( ))} {all && ( )} )}
); }; export default EmojiSelector;