kopia lustrzana https://gitlab.com/soapbox-pub/soapbox
Merge branch 'react-any-emoji' into 'develop'
React with any emoji See merge request soapbox-pub/soapbox!2271environments/review-develop-3zknud/deployments/2600
commit
998ff44e80
|
@ -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>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -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>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -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>
|
||||||
);
|
);
|
||||||
|
|
|
@ -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 {
|
|
@ -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})$)`,
|
||||||
],
|
],
|
||||||
|
|
Ładowanie…
Reference in New Issue