Pre-alpha: React with any emoji, behind flag
This commit is contained in:
parent
d13c3d3350
commit
0865a5481c
31 changed files with 572 additions and 234 deletions
|
@ -1,56 +0,0 @@
|
|||
#### Default
|
||||
|
||||
```jsx
|
||||
<util.ConversationContext theme={util.theme}>
|
||||
<div
|
||||
style={{
|
||||
height: '500px',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'flex-end',
|
||||
}}
|
||||
>
|
||||
<EmojiButton
|
||||
i18n={util.i18n}
|
||||
onPickEmoji={e => console.log('onPickEmoji', e)}
|
||||
skinTone={0}
|
||||
onSetSkinTone={t => console.log('onSetSkinTone', t)}
|
||||
onClose={() => console.log('onClose')}
|
||||
recentEmojis={[
|
||||
'grinning',
|
||||
'grin',
|
||||
'joy',
|
||||
'rolling_on_the_floor_laughing',
|
||||
'smiley',
|
||||
'smile',
|
||||
'sweat_smile',
|
||||
'laughing',
|
||||
'wink',
|
||||
'blush',
|
||||
'yum',
|
||||
'sunglasses',
|
||||
'heart_eyes',
|
||||
'kissing_heart',
|
||||
'kissing',
|
||||
'kissing_smiling_eyes',
|
||||
'kissing_closed_eyes',
|
||||
'relaxed',
|
||||
'slightly_smiling_face',
|
||||
'hugging_face',
|
||||
'grinning_face_with_star_eyes',
|
||||
'thinking_face',
|
||||
'face_with_one_eyebrow_raised',
|
||||
'neutral_face',
|
||||
'expressionless',
|
||||
'no_mouth',
|
||||
'face_with_rolling_eyes',
|
||||
'smirk',
|
||||
'persevere',
|
||||
'disappointed_relieved',
|
||||
'open_mouth',
|
||||
'zipper_mouth_face',
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
</util.ConversationContext>
|
||||
```
|
66
ts/components/emoji/EmojiButton.stories.tsx
Normal file
66
ts/components/emoji/EmojiButton.stories.tsx
Normal file
|
@ -0,0 +1,66 @@
|
|||
import * as React from 'react';
|
||||
|
||||
// @ts-ignore
|
||||
import { setup as setupI18n } from '../../../js/modules/i18n';
|
||||
// @ts-ignore
|
||||
import enMessages from '../../../_locales/en/messages.json';
|
||||
|
||||
import { storiesOf } from '@storybook/react';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
import { EmojiButton } from './EmojiButton';
|
||||
|
||||
const i18n = setupI18n('en', enMessages);
|
||||
|
||||
storiesOf('Components/emojis/EmojiButton', module).add('Base', () => {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
height: '500px',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'flex-end',
|
||||
}}
|
||||
>
|
||||
<EmojiButton
|
||||
i18n={i18n}
|
||||
onPickEmoji={action('onPickEmoji')}
|
||||
skinTone={0}
|
||||
onSetSkinTone={action('onSetSkinTone')}
|
||||
recentEmojis={[
|
||||
'grinning',
|
||||
'grin',
|
||||
'joy',
|
||||
'rolling_on_the_floor_laughing',
|
||||
'smiley',
|
||||
'smile',
|
||||
'sweat_smile',
|
||||
'laughing',
|
||||
'wink',
|
||||
'blush',
|
||||
'yum',
|
||||
'sunglasses',
|
||||
'heart_eyes',
|
||||
'kissing_heart',
|
||||
'kissing',
|
||||
'kissing_smiling_eyes',
|
||||
'kissing_closed_eyes',
|
||||
'relaxed',
|
||||
'slightly_smiling_face',
|
||||
'hugging_face',
|
||||
'grinning_face_with_star_eyes',
|
||||
'thinking_face',
|
||||
'face_with_one_eyebrow_raised',
|
||||
'neutral_face',
|
||||
'expressionless',
|
||||
'no_mouth',
|
||||
'face_with_rolling_eyes',
|
||||
'smirk',
|
||||
'persevere',
|
||||
'disappointed_relieved',
|
||||
'open_mouth',
|
||||
'zipper_mouth_face',
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
});
|
|
@ -1,60 +0,0 @@
|
|||
#### Default
|
||||
|
||||
```jsx
|
||||
<util.ConversationContext theme={util.theme}>
|
||||
<EmojiPicker
|
||||
i18n={util.i18n}
|
||||
onPickEmoji={e => console.log('onPickEmoji', e)}
|
||||
onSetSkinTone={t => console.log('onSetSkinTone', t)}
|
||||
onClose={() => console.log('onClose')}
|
||||
recentEmojis={[
|
||||
'grinning',
|
||||
'grin',
|
||||
'joy',
|
||||
'rolling_on_the_floor_laughing',
|
||||
'smiley',
|
||||
'smile',
|
||||
'sweat_smile',
|
||||
'laughing',
|
||||
'wink',
|
||||
'blush',
|
||||
'yum',
|
||||
'sunglasses',
|
||||
'heart_eyes',
|
||||
'kissing_heart',
|
||||
'kissing',
|
||||
'kissing_smiling_eyes',
|
||||
'kissing_closed_eyes',
|
||||
'relaxed',
|
||||
'slightly_smiling_face',
|
||||
'hugging_face',
|
||||
'grinning_face_with_star_eyes',
|
||||
'thinking_face',
|
||||
'face_with_one_eyebrow_raised',
|
||||
'neutral_face',
|
||||
'expressionless',
|
||||
'no_mouth',
|
||||
'face_with_rolling_eyes',
|
||||
'smirk',
|
||||
'persevere',
|
||||
'disappointed_relieved',
|
||||
'open_mouth',
|
||||
'zipper_mouth_face',
|
||||
]}
|
||||
/>
|
||||
</util.ConversationContext>
|
||||
```
|
||||
|
||||
#### No Recents
|
||||
|
||||
```jsx
|
||||
<util.ConversationContext theme={util.theme}>
|
||||
<EmojiPicker
|
||||
i18n={util.i18n}
|
||||
onPickEmoji={e => console.log('onPickEmoji', e)}
|
||||
onSetSkinTone={t => console.log('onSetSkinTone', t)}
|
||||
onClose={() => console.log('onClose')}
|
||||
recentEmojis={[]}
|
||||
/>
|
||||
</util.ConversationContext>
|
||||
```
|
71
ts/components/emoji/EmojiPicker.stories.tsx
Normal file
71
ts/components/emoji/EmojiPicker.stories.tsx
Normal file
|
@ -0,0 +1,71 @@
|
|||
import * as React from 'react';
|
||||
|
||||
// @ts-ignore
|
||||
import { setup as setupI18n } from '../../../js/modules/i18n';
|
||||
// @ts-ignore
|
||||
import enMessages from '../../../_locales/en/messages.json';
|
||||
|
||||
import { storiesOf } from '@storybook/react';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
import { EmojiPicker } from './EmojiPicker';
|
||||
|
||||
const i18n = setupI18n('en', enMessages);
|
||||
|
||||
storiesOf('Components/emojis/EmojiPicker', module)
|
||||
.add('Base', () => {
|
||||
return (
|
||||
<EmojiPicker
|
||||
i18n={i18n}
|
||||
onPickEmoji={action('onPickEmoji')}
|
||||
onSetSkinTone={action('onSetSkinTone')}
|
||||
onClose={action('onClose')}
|
||||
skinTone={0}
|
||||
recentEmojis={[
|
||||
'grinning',
|
||||
'grin',
|
||||
'joy',
|
||||
'rolling_on_the_floor_laughing',
|
||||
'smiley',
|
||||
'smile',
|
||||
'sweat_smile',
|
||||
'laughing',
|
||||
'wink',
|
||||
'blush',
|
||||
'yum',
|
||||
'sunglasses',
|
||||
'heart_eyes',
|
||||
'kissing_heart',
|
||||
'kissing',
|
||||
'kissing_smiling_eyes',
|
||||
'kissing_closed_eyes',
|
||||
'relaxed',
|
||||
'slightly_smiling_face',
|
||||
'hugging_face',
|
||||
'grinning_face_with_star_eyes',
|
||||
'thinking_face',
|
||||
'face_with_one_eyebrow_raised',
|
||||
'neutral_face',
|
||||
'expressionless',
|
||||
'no_mouth',
|
||||
'face_with_rolling_eyes',
|
||||
'smirk',
|
||||
'persevere',
|
||||
'disappointed_relieved',
|
||||
'open_mouth',
|
||||
'zipper_mouth_face',
|
||||
]}
|
||||
/>
|
||||
);
|
||||
})
|
||||
.add('No Recents', () => {
|
||||
return (
|
||||
<EmojiPicker
|
||||
i18n={i18n}
|
||||
onPickEmoji={action('onPickEmoji')}
|
||||
onSetSkinTone={action('onSetSkinTone')}
|
||||
onClose={action('onClose')}
|
||||
skinTone={0}
|
||||
recentEmojis={[]}
|
||||
/>
|
||||
);
|
||||
});
|
|
@ -17,7 +17,7 @@ import {
|
|||
} from 'lodash';
|
||||
import { Emoji } from './Emoji';
|
||||
import { dataByCategory, search } from './lib';
|
||||
import { useRestoreFocus } from '../hooks';
|
||||
import { useRestoreFocus } from '../../util/hooks';
|
||||
import { LocalizerType } from '../../types/Util';
|
||||
|
||||
export type EmojiPickDataType = { skinTone?: number; shortName: string };
|
||||
|
@ -29,7 +29,7 @@ export type OwnProps = {
|
|||
readonly skinTone: number;
|
||||
readonly onSetSkinTone: (tone: number) => unknown;
|
||||
readonly recentEmojis?: Array<string>;
|
||||
readonly onClose: () => unknown;
|
||||
readonly onClose?: () => unknown;
|
||||
};
|
||||
|
||||
export type Props = OwnProps & Pick<React.HTMLProps<HTMLDivElement>, 'style'>;
|
||||
|
@ -83,11 +83,15 @@ export const EmojiPicker = React.memo(
|
|||
const [scrollToRow, setScrollToRow] = React.useState(0);
|
||||
const [selectedTone, setSelectedTone] = React.useState(skinTone);
|
||||
|
||||
const handleToggleSearch = React.useCallback(() => {
|
||||
setSearchText('');
|
||||
setSelectedCategory(categories[0]);
|
||||
setSearchMode(m => !m);
|
||||
}, [setSearchText, setSearchMode]);
|
||||
const handleToggleSearch = React.useCallback(
|
||||
(e: React.MouseEvent) => {
|
||||
e.stopPropagation();
|
||||
setSearchText('');
|
||||
setSelectedCategory(categories[0]);
|
||||
setSearchMode(m => !m);
|
||||
},
|
||||
[setSearchText, setSearchMode]
|
||||
);
|
||||
|
||||
const debounceSearchChange = React.useMemo(
|
||||
() =>
|
||||
|
@ -122,15 +126,16 @@ export const EmojiPicker = React.memo(
|
|||
| React.KeyboardEvent<HTMLButtonElement>
|
||||
) => {
|
||||
if ('key' in e) {
|
||||
if (e.key === 'Enter') {
|
||||
if (e.key === 'Enter' && doSend) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
if (doSend) {
|
||||
doSend();
|
||||
}
|
||||
doSend();
|
||||
}
|
||||
} else {
|
||||
const { shortName } = e.currentTarget.dataset;
|
||||
if (shortName) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
onPickEmoji({ skinTone: selectedTone, shortName });
|
||||
}
|
||||
}
|
||||
|
@ -160,7 +165,9 @@ export const EmojiPicker = React.memo(
|
|||
' ', // Space
|
||||
].includes(event.key)
|
||||
) {
|
||||
onClose();
|
||||
if (onClose) {
|
||||
onClose();
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
@ -224,8 +231,9 @@ export const EmojiPicker = React.memo(
|
|||
);
|
||||
|
||||
const handleSelectCategory = React.useCallback(
|
||||
({ currentTarget }: React.MouseEvent<HTMLButtonElement>) => {
|
||||
const { category } = currentTarget.dataset;
|
||||
(e: React.MouseEvent<HTMLButtonElement>) => {
|
||||
e.stopPropagation();
|
||||
const { category } = e.currentTarget.dataset;
|
||||
if (category) {
|
||||
setSelectedCategory(category);
|
||||
setScrollToRow(catToRowOffsets[category]);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue