UNPKG

@chayns-components/emoji-input

Version:
120 lines (118 loc) 3.98 kB
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import emojiComponents from 'unicode-emoji-json/data-emoji-components.json'; import { addSkinToneToEmoji } from '../../../../../utils/emoji'; import { StyledMotionSkinTonePopup, StyledSkinTonePopupContent, StyledSkinTonePopupContentEmoji, StyledSkinTonePopupOverlay } from './SkinTonePopup.styles'; const SkinTonePopup = ({ anchorAlignment, anchorOffset, emoji, onHidePopup, onSelect, overlayPosition, position, emojiList }) => { const [focusedIndex, setFocusedIndex] = useState(0); const skinToneRef = useRef(null); const handleOverlayClick = useCallback(event => { event.preventDefault(); event.stopPropagation(); onHidePopup(); }, [onHidePopup]); useEffect(() => { const handleKeyDown = event => { if (event.key === 'ArrowLeft' || event.key === 'ArrowRight') { event.preventDefault(); const children = skinToneRef.current?.children; if (children && children.length > 0) { let newIndex = focusedIndex !== null ? focusedIndex : 0; if (event.key === 'ArrowLeft') { newIndex = (newIndex - 1) % children.length; } else if (event.key === 'ArrowRight') { newIndex = (newIndex + 1) % children.length; } // remove focus from the old element if (focusedIndex !== null) { const prevElement = children[focusedIndex]; prevElement.tabIndex = -1; } if (newIndex < 0) { newIndex = children.length - 1; } else if (newIndex > children.length - 1) { newIndex = 0; } setFocusedIndex(newIndex); // Set focus to the element const newElement = children[newIndex]; newElement.tabIndex = 0; newElement.focus(); } } else if (event.key === 'Enter' && focusedIndex !== null) { const { dataset } = skinToneRef.current?.children[focusedIndex]; const { skinTone } = dataset; if (!skinTone) { return; } onSelect(skinTone); onHidePopup(); } else if (event.key === 'Escape' && event.shiftKey) { event.preventDefault(); onHidePopup(); } }; document.addEventListener('keydown', handleKeyDown); return () => { document.removeEventListener('keydown', handleKeyDown); }; }, [focusedIndex, onHidePopup, onSelect]); const emojis = useMemo(() => { const result = []; Object.entries(emojiComponents).forEach(([key, value], index) => { if (key.includes('skin_tone')) { const emojiWithSkinTone = addSkinToneToEmoji(emojiList, emoji, value); const handleClick = event => { event.preventDefault(); event.stopPropagation(); onSelect(emojiWithSkinTone); onHidePopup(); }; result.push(/*#__PURE__*/React.createElement(StyledSkinTonePopupContentEmoji, { key: key, "data-skin-tone": emojiWithSkinTone, $isSelected: index === focusedIndex, onClick: handleClick }, emojiWithSkinTone)); } }); return result; }, [emoji, emojiList, focusedIndex, onHidePopup, onSelect]); return /*#__PURE__*/React.createElement(StyledMotionSkinTonePopup, { animate: { opacity: 1 }, exit: { opacity: 0 }, initial: { opacity: 0 }, transition: { duration: 0.1 } }, /*#__PURE__*/React.createElement(StyledSkinTonePopupContent, { ref: skinToneRef, $anchorAlignment: anchorAlignment, $anchorOffset: anchorOffset, style: position }, emojis), /*#__PURE__*/React.createElement(StyledSkinTonePopupOverlay, { onClick: handleOverlayClick, style: overlayPosition })); }; SkinTonePopup.displayName = 'SkinTonePopup'; export default SkinTonePopup; //# sourceMappingURL=SkinTonePopup.js.map