You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			138 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			TypeScript
		
	
			
		
		
	
	
			138 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			TypeScript
		
	
| import React, { forwardRef, MutableRefObject, useEffect } from 'react';
 | |
| import classNames from 'classnames';
 | |
| import styled from 'styled-components';
 | |
| import data from '@emoji-mart/data';
 | |
| // @ts-ignore
 | |
| import { Picker } from '../../../node_modules/emoji-mart/dist/index.cjs';
 | |
| import { useSelector } from 'react-redux';
 | |
| import { getTheme } from '../../state/selectors/theme';
 | |
| import { noop } from 'lodash';
 | |
| import { loadEmojiPanelI18n } from '../../util/i18n';
 | |
| import { FixedBaseEmoji, FixedPickerProps } from '../../types/Reaction';
 | |
| 
 | |
| export const StyledEmojiPanel = styled.div<{ isModal: boolean; theme: 'light' | 'dark' }>`
 | |
|   padding: var(--margins-lg);
 | |
|   z-index: 5;
 | |
|   opacity: 0;
 | |
|   visibility: hidden;
 | |
|   transition: var(--default-duration);
 | |
| 
 | |
|   button:focus {
 | |
|     outline: none;
 | |
|   }
 | |
| 
 | |
|   &.show {
 | |
|     opacity: 1;
 | |
|     visibility: visible;
 | |
|   }
 | |
| 
 | |
|   em-emoji-picker {
 | |
|     background-color: var(--color-cell-background);
 | |
|     border: 1px solid var(--color-session-border);
 | |
|     padding-bottom: var(--margins-sm);
 | |
|     --shadow: none;
 | |
|     --border-radius: 8px;
 | |
|     --color-border: var(--color-session-border);
 | |
|     --font-family: var(--font-default);
 | |
|     --font-size: var(--font-size-sm);
 | |
|     --rgb-accent: 0, 247, 130; // Constants.UI.COLORS.GREEN
 | |
| 
 | |
|     ${props => {
 | |
|       switch (props.theme) {
 | |
|         case 'dark':
 | |
|           return `
 | |
|             --background-rgb: 27, 27, 27; // var(--color-cell-background)
 | |
|             --rgb-background: 27, 27, 27;
 | |
|             --rgb-color: 255, 255, 255; // var(--color-text)
 | |
|             --rgb-input: 27, 27, 27;
 | |
|           `;
 | |
|         case 'light':
 | |
|         default:
 | |
|           return `
 | |
|             --background-rgb: 249, 249, 249; // var(--color-cell-background)
 | |
|             --rgb-background: 249, 249, 249;
 | |
|             --rgb-color: 0, 0, 0; // var(--color-text)
 | |
|             --rgb-input: 249, 249, 249;
 | |
|         `;
 | |
|       }
 | |
|     }}
 | |
| 
 | |
|     ${props =>
 | |
|       !props.isModal &&
 | |
|       `
 | |
|       &:after {
 | |
|         content: '';
 | |
|         position: absolute;
 | |
|         top: calc(100% - 40px);
 | |
|         left: calc(100% - 79px);
 | |
|         width: 22px;
 | |
|         height: 22px;
 | |
|         background-color: var(--color-cell-background);
 | |
|         transform: rotate(45deg);
 | |
|         border-radius: 3px;
 | |
|         transform: scaleY(1.4) rotate(45deg);
 | |
|         border: 0.7px solid var(--color-session-border);
 | |
|         clip-path: polygon(100% 100%, 7.2px 100%, 100% 7.2px);
 | |
|       }
 | |
|     `}
 | |
|   }
 | |
| `;
 | |
| 
 | |
| type Props = {
 | |
|   onEmojiClicked: (emoji: FixedBaseEmoji) => void;
 | |
|   show: boolean;
 | |
|   isModal?: boolean;
 | |
|   onKeyDown?: (event: any) => void;
 | |
| };
 | |
| 
 | |
| const pickerProps: FixedPickerProps = {
 | |
|   title: '',
 | |
|   showPreview: true,
 | |
|   autoFocus: true,
 | |
|   skinTonePosition: 'preview',
 | |
| };
 | |
| 
 | |
| export const SessionEmojiPanel = forwardRef<HTMLDivElement, Props>((props: Props, ref) => {
 | |
|   const { onEmojiClicked, show, isModal = false, onKeyDown } = props;
 | |
|   const theme = useSelector(getTheme);
 | |
|   const pickerRef = ref as MutableRefObject<HTMLDivElement>;
 | |
| 
 | |
|   useEffect(() => {
 | |
|     let isCancelled = false;
 | |
|     if (pickerRef.current !== null) {
 | |
|       if (pickerRef.current.children.length === 0) {
 | |
|         loadEmojiPanelI18n()
 | |
|           .then(async i18n => {
 | |
|             if (isCancelled) {
 | |
|               return;
 | |
|             }
 | |
|             // tslint:disable-next-line: no-unused-expression
 | |
|             new Picker({
 | |
|               data,
 | |
|               ref,
 | |
|               i18n,
 | |
|               theme,
 | |
|               onEmojiSelect: onEmojiClicked,
 | |
|               onKeyDown,
 | |
|               ...pickerProps,
 | |
|             });
 | |
|           })
 | |
|           .catch(noop);
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     return () => {
 | |
|       isCancelled = true;
 | |
|     };
 | |
|   }, [data, pickerProps]);
 | |
| 
 | |
|   return (
 | |
|     <StyledEmojiPanel
 | |
|       isModal={isModal}
 | |
|       theme={theme}
 | |
|       className={classNames(show && 'show')}
 | |
|       ref={ref}
 | |
|     />
 | |
|   );
 | |
| });
 |