import { shift, useFloating, Placement, offset, OffsetOptions } from '@floating-ui/react'; import clsx from 'clsx'; import React, { useEffect, useState } from 'react'; import { Emoji as EmojiComponent, HStack, IconButton } from 'soapbox/components/ui'; import EmojiPickerDropdown from 'soapbox/features/emoji/components/emoji-picker-dropdown'; import { useClickOutside, useFeatures, useSoapboxConfig } from 'soapbox/hooks'; import type { Emoji } from 'soapbox/features/emoji'; 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, custom?: string): void /** Element that triggers the EmojiSelector Popper */ referenceElement: HTMLElement | null placement?: Placement /** Whether the selector should be visible. */ visible?: boolean offsetOptions?: OffsetOptions /** 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, offsetOptions, all = true, }): JSX.Element => { const soapboxConfig = useSoapboxConfig(); const { customEmojiReacts } = useFeatures(); const [expanded, setExpanded] = useState(false); const { x, y, strategy, refs, update } = useFloating({ placement, middleware: [offset(offsetOptions), shift()], }); const handleExpand: React.MouseEventHandler = () => { setExpanded(true); }; const handlePickEmoji = (emoji: Emoji) => { onReact(emoji.custom ? emoji.id : emoji.native, emoji.custom ? emoji.imageUrl : undefined); }; useEffect(() => { refs.setReference(referenceElement); }, [referenceElement]); useEffect(() => () => { document.body.style.overflow = ''; }, []); useEffect(() => { setExpanded(false); }, [visible]); useClickOutside(refs, () => { if (onClose) { onClose(); } }); return (
{expanded ? ( ) : ( {Array.from(soapboxConfig.allowedEmoji).map((emoji, i) => ( ))} {all && ( )} )}
); }; export default EmojiSelector;