UNPKG

@chayns-components/emoji-input

Version:
137 lines 4.64 kB
import { AnimatePresence } from 'motion/react'; import React, { useCallback, useEffect, useRef, useState } from 'react'; import { AnchorAlignment } from '../../../../constants/alignment'; import { StyledEmoji } from './Emoji.styles'; import SkinTonePopup from './skin-tone-popup/SkinTonePopup'; import { skinTonePopupContentSize } from './skin-tone-popup/SkinTonePopup.styles'; const Emoji = ({ emoji, isSelected, name, isSkinToneSupported, onPopupVisibilityChange, onSelect, shouldShowSkinTonePopup, onRightClick, index, emojiList }) => { const [shouldShowPopup, setShouldShowPopup] = useState(false); const [skinTonePopupAnchorAlignment, setSkinTonePopupAnchorAlignment] = useState(AnchorAlignment.Top); const [skinTonePopupAnchorOffset, setSkinTonePopupAnchorOffset] = useState(0); const [skinTonePopupOverlayPosition, setSkinTonePopupOverlayPosition] = useState({ top: 0 }); const [skinTonePopupPosition, setSkinTonePopupPosition] = useState({ left: 0, top: 0 }); const emojiRef = useRef(null); const handleClick = useCallback(() => { onSelect(emoji); }, [emoji, onSelect]); const calculatePopupPosition = useCallback(() => { if (!emojiRef.current) { return; } const element = emojiRef.current; const { parentElement } = emojiRef.current; if (parentElement) { const { height: elementHeight, left: elementLeft, top: elementTop, width: elementWidth } = element.getBoundingClientRect(); const { height: parentHeight, left: parentLeft, top: parentTop, width: parentWidth } = parentElement.getBoundingClientRect(); const { scrollTop } = parentElement; let anchorAlignment = AnchorAlignment.Top; let anchorOffset = 0; let left = elementLeft - parentLeft - skinTonePopupContentSize.width / 2 + elementWidth / 2; let top = elementTop - parentTop + elementHeight + scrollTop; const maxLeft = parentWidth - skinTonePopupContentSize.width - 12; const minLeft = 12; if (left < minLeft) { anchorOffset = left - minLeft; left = minLeft; } else if (left > maxLeft) { anchorOffset = left - maxLeft; left = maxLeft; } if (top + skinTonePopupContentSize.height > parentHeight + scrollTop) { anchorAlignment = AnchorAlignment.Bottom; top -= elementHeight + skinTonePopupContentSize.height; } if (isSkinToneSupported) { setSkinTonePopupAnchorAlignment(anchorAlignment); setSkinTonePopupAnchorOffset(anchorOffset); setSkinTonePopupPosition({ left, top }); setSkinTonePopupOverlayPosition({ top: scrollTop }); setShouldShowPopup(true); } } }, [isSkinToneSupported]); const handleContextMenu = useCallback(event => { event.preventDefault(); event.stopPropagation(); if (isSkinToneSupported) { onRightClick(index); calculatePopupPosition(); } }, [calculatePopupPosition, index, isSkinToneSupported, onRightClick]); useEffect(() => { if (emojiRef.current && shouldShowSkinTonePopup && skinTonePopupPosition.top === 0 && skinTonePopupPosition.left === 0) { calculatePopupPosition(); } }, [calculatePopupPosition, index, isSkinToneSupported, shouldShowSkinTonePopup, skinTonePopupPosition]); useEffect(() => { if (shouldShowSkinTonePopup) { setShouldShowPopup(shouldShowSkinTonePopup); } }, [shouldShowSkinTonePopup]); const handleHidePopup = useCallback(() => { setShouldShowPopup(false); }, []); useEffect(() => { onPopupVisibilityChange(shouldShowPopup); }, [onPopupVisibilityChange, shouldShowPopup]); return /*#__PURE__*/React.createElement(StyledEmoji, { ref: emojiRef, $isSelected: isSelected, "data-emoji": emoji, "data-name": name, "data-skin-tone-support": isSkinToneSupported, className: "prevent-lose-focus", onClick: handleClick, onContextMenu: handleContextMenu }, emoji, /*#__PURE__*/React.createElement(AnimatePresence, { initial: false }, shouldShowPopup && /*#__PURE__*/React.createElement(SkinTonePopup, { anchorAlignment: skinTonePopupAnchorAlignment, anchorOffset: skinTonePopupAnchorOffset, emoji: emoji, key: emoji, onHidePopup: handleHidePopup, onSelect: onSelect, overlayPosition: skinTonePopupOverlayPosition, position: skinTonePopupPosition, emojiList: emojiList }))); }; Emoji.displayName = 'Emoji'; export default Emoji; //# sourceMappingURL=Emoji.js.map