Merge branch 'react-any-emoji' into 'develop'

React with any emoji

See merge request soapbox-pub/soapbox!2271
environments/review-develop-3zknud/deployments/2600
Alex Gleason 2023-02-13 02:48:01 +00:00
commit 998ff44e80
5 zmienionych plików z 56 dodań i 20 usunięć

Wyświetl plik

@ -1,3 +1,4 @@
import { Portal } from '@reach/portal';
import React, { useState, useEffect, useRef } from 'react'; import React, { useState, useEffect, useRef } from 'react';
import { simpleEmojiReact } from 'soapbox/actions/emoji-reacts'; import { simpleEmojiReact } from 'soapbox/actions/emoji-reacts';
@ -105,12 +106,14 @@ const StatusReactionWrapper: React.FC<IStatusReactionWrapper> = ({ statusId, chi
ref: setReferenceElement, ref: setReferenceElement,
})} })}
<EmojiSelector <Portal>
placement='top-start' <EmojiSelector
referenceElement={referenceElement} placement='top-start'
onReact={handleReact} referenceElement={referenceElement}
visible={visible} onReact={handleReact}
/> visible={visible}
/>
</Portal>
</div> </div>
); );
}; };

Wyświetl plik

@ -3,7 +3,8 @@ import clsx from 'clsx';
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { usePopper } from 'react-popper'; import { usePopper } from 'react-popper';
import { Emoji, HStack } from 'soapbox/components/ui'; import { Emoji, HStack, IconButton } from 'soapbox/components/ui';
import { Picker } from 'soapbox/features/emoji/emoji-picker';
import { useSoapboxConfig } from 'soapbox/hooks'; import { useSoapboxConfig } from 'soapbox/hooks';
interface IEmojiButton { interface IEmojiButton {
@ -42,6 +43,8 @@ interface IEmojiSelector {
placement?: Placement placement?: Placement
/** Whether the selector should be visible. */ /** Whether the selector should be visible. */
visible?: boolean visible?: boolean
/** Whether to allow any emoji to be chosen. */
all?: boolean
} }
/** Panel with a row of emoji buttons. */ /** Panel with a row of emoji buttons. */
@ -51,9 +54,12 @@ const EmojiSelector: React.FC<IEmojiSelector> = ({
onReact, onReact,
placement = 'top', placement = 'top',
visible = false, visible = false,
all = true,
}): JSX.Element => { }): JSX.Element => {
const soapboxConfig = useSoapboxConfig(); const soapboxConfig = useSoapboxConfig();
const [expanded, setExpanded] = useState(false);
// `useRef` won't trigger a re-render, while `useState` does. // `useRef` won't trigger a re-render, while `useState` does.
// https://popper.js.org/react-popper/v2/ // https://popper.js.org/react-popper/v2/
const [popperElement, setPopperElement] = useState<HTMLDivElement | null>(null); const [popperElement, setPopperElement] = useState<HTMLDivElement | null>(null);
@ -80,6 +86,14 @@ const EmojiSelector: React.FC<IEmojiSelector> = ({
], ],
}); });
const handleExpand: React.MouseEventHandler = () => {
setExpanded(true);
};
useEffect(() => {
setExpanded(false);
}, [visible]);
useEffect(() => { useEffect(() => {
document.addEventListener('mousedown', handleClickOutside); document.addEventListener('mousedown', handleClickOutside);
@ -103,18 +117,34 @@ const EmojiSelector: React.FC<IEmojiSelector> = ({
style={styles.popper} style={styles.popper}
{...attributes.popper} {...attributes.popper}
> >
<HStack {expanded ? (
className={clsx('z-[999] flex w-max max-w-[100vw] flex-wrap space-x-3 rounded-full bg-white px-3 py-2.5 shadow-lg focus:outline-none dark:bg-gray-900 dark:ring-2 dark:ring-primary-700')} <Picker
> set='twitter'
{Array.from(soapboxConfig.allowedEmoji).map((emoji, i) => ( backgroundImageFn={() => require('emoji-datasource/img/twitter/sheets/32.png')}
<EmojiButton onClick={(emoji: any) => onReact(emoji.native)}
key={i} />
emoji={emoji} ) : (
onClick={onReact} <HStack
tabIndex={visible ? 0 : -1} className={clsx('z-[999] flex w-max max-w-[100vw] flex-wrap space-x-3 rounded-full bg-white px-3 py-2.5 shadow-lg focus:outline-none dark:bg-gray-900 dark:ring-2 dark:ring-primary-700')}
/> >
))} {Array.from(soapboxConfig.allowedEmoji).map((emoji, i) => (
</HStack> <EmojiButton
key={i}
emoji={emoji}
onClick={onReact}
tabIndex={visible ? 0 : -1}
/>
))}
{all && (
<IconButton
className='text-gray-600 hover:text-gray-600 dark:hover:text-white'
src={require('@tabler/icons/dots.svg')}
onClick={handleExpand}
/>
)}
</HStack>
)}
</div> </div>
); );
}; };

Wyświetl plik

@ -41,6 +41,7 @@ function ChatMessageReactionWrapper(props: IChatMessageReactionWrapper) {
referenceElement={referenceElement} referenceElement={referenceElement}
onReact={handleSelect} onReact={handleSelect}
onClose={() => setIsOpen(false)} onClose={() => setIsOpen(false)}
all={false}
/> />
</React.Fragment> </React.Fragment>
); );

Wyświetl plik

@ -1,4 +1,6 @@
// @ts-ignore no types
import Emoji from 'emoji-mart/dist-es/components/emoji/emoji'; import Emoji from 'emoji-mart/dist-es/components/emoji/emoji';
// @ts-ignore no types
import Picker from 'emoji-mart/dist-es/components/picker/picker'; import Picker from 'emoji-mart/dist-es/components/picker/picker';
export { export {

Wyświetl plik

@ -39,7 +39,7 @@ module.exports = {
'transformIgnorePatterns': [ 'transformIgnorePatterns': [
// FIXME: react-sticky-box doesn't provide a CJS build, so transform it for now // FIXME: react-sticky-box doesn't provide a CJS build, so transform it for now
// https://github.com/codecks-io/react-sticky-box/issues/79 // https://github.com/codecks-io/react-sticky-box/issues/79
`/node_modules/(?!(react-sticky-box|blurhash|.+\\.(${ASSET_EXTS})$))`, `/node_modules/(?!(react-sticky-box|blurhash|emoji-mart|.+\\.(${ASSET_EXTS})$))`,
// Ignore node_modules, except static assets // Ignore node_modules, except static assets
// `/node_modules/(?!.+\\.(${ASSET_EXTS})$)`, // `/node_modules/(?!.+\\.(${ASSET_EXTS})$)`,
], ],