@atlaskit/emoji 67.0.7 → 67.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +37 -0
- package/dist/cjs/api/EmojiResource.js +41 -25
- package/dist/cjs/api/media/TokenManager.js +4 -4
- package/dist/cjs/components/common/CachingEmoji.js +14 -6
- package/dist/cjs/components/common/Emoji.js +48 -12
- package/dist/cjs/components/common/EmojiActions.js +62 -26
- package/dist/cjs/components/common/EmojiErrorMessage.js +12 -7
- package/dist/cjs/components/common/EmojiPlaceholder.js +1 -0
- package/dist/cjs/components/common/{EmojiButton.js → EmojiRadioButton.js} +28 -19
- package/dist/cjs/components/common/EmojiUploadPicker.js +80 -37
- package/dist/cjs/components/common/EmojiUploadPreview.js +11 -2
- package/dist/cjs/components/common/FileChooser.js +2 -2
- package/dist/cjs/components/common/ResourcedEmojiComponent.js +4 -0
- package/dist/cjs/components/common/RetryableButton.js +7 -3
- package/dist/cjs/components/common/TonePreviewButton.js +44 -0
- package/dist/cjs/components/common/ToneSelector.js +53 -25
- package/dist/cjs/components/common/styles.js +45 -16
- package/dist/cjs/components/i18n.js +44 -4
- package/dist/cjs/components/picker/CategorySelector.js +112 -90
- package/dist/cjs/components/picker/CategoryTracker.js +0 -28
- package/dist/cjs/components/picker/EmojiPickerCategoryHeading.js +2 -1
- package/dist/cjs/components/picker/EmojiPickerComponent.js +33 -44
- package/dist/cjs/components/picker/EmojiPickerEmojiRow.js +32 -4
- package/dist/cjs/components/picker/EmojiPickerList.js +154 -88
- package/dist/cjs/components/picker/EmojiPickerListSearch.js +66 -117
- package/dist/cjs/components/picker/EmojiPickerVirtualItems.js +5 -2
- package/dist/cjs/components/picker/VirtualList.js +273 -171
- package/dist/cjs/components/picker/styles.js +43 -51
- package/dist/cjs/components/typeahead/EmojiTypeAheadComponent.js +0 -10
- package/dist/cjs/context/EmojiPickerListContext.js +33 -0
- package/dist/cjs/hooks/useEmojiPickerListContext.js +12 -0
- package/dist/cjs/hooks/useIsMounted.js +17 -0
- package/dist/cjs/i18n/cs.js +35 -34
- package/dist/cjs/i18n/da.js +35 -34
- package/dist/cjs/i18n/de.js +35 -34
- package/dist/cjs/i18n/en.js +35 -34
- package/dist/cjs/i18n/en_GB.js +35 -34
- package/dist/cjs/i18n/es.js +35 -34
- package/dist/cjs/i18n/fi.js +35 -34
- package/dist/cjs/i18n/fr.js +35 -34
- package/dist/cjs/i18n/hu.js +35 -34
- package/dist/cjs/i18n/it.js +35 -34
- package/dist/cjs/i18n/ja.js +35 -34
- package/dist/cjs/i18n/ko.js +35 -34
- package/dist/cjs/i18n/nb.js +35 -34
- package/dist/cjs/i18n/nl.js +35 -34
- package/dist/cjs/i18n/pl.js +35 -34
- package/dist/cjs/i18n/pt_BR.js +35 -34
- package/dist/cjs/i18n/ru.js +35 -34
- package/dist/cjs/i18n/sv.js +35 -34
- package/dist/cjs/i18n/th.js +35 -34
- package/dist/cjs/i18n/tr.js +35 -34
- package/dist/cjs/i18n/uk.js +35 -34
- package/dist/cjs/i18n/vi.js +35 -34
- package/dist/cjs/i18n/zh.js +35 -34
- package/dist/cjs/i18n/zh_TW.js +35 -34
- package/dist/cjs/types.js +7 -1
- package/dist/cjs/util/constants.js +43 -2
- package/dist/cjs/util/shared-styles.js +3 -4
- package/dist/cjs/version.json +1 -1
- package/dist/es2019/api/EmojiResource.js +42 -26
- package/dist/es2019/api/media/TokenManager.js +4 -4
- package/dist/es2019/components/common/CachingEmoji.js +10 -3
- package/dist/es2019/components/common/Emoji.js +44 -11
- package/dist/es2019/components/common/EmojiActions.js +55 -24
- package/dist/es2019/components/common/EmojiErrorMessage.js +7 -3
- package/dist/es2019/components/common/EmojiPlaceholder.js +1 -0
- package/dist/es2019/components/common/EmojiRadioButton.js +54 -0
- package/dist/es2019/components/common/EmojiUploadPicker.js +75 -36
- package/dist/es2019/components/common/EmojiUploadPreview.js +11 -2
- package/dist/es2019/components/common/FileChooser.js +1 -1
- package/dist/es2019/components/common/ResourcedEmojiComponent.js +4 -0
- package/dist/es2019/components/common/RetryableButton.js +7 -3
- package/dist/es2019/components/common/TonePreviewButton.js +34 -0
- package/dist/es2019/components/common/ToneSelector.js +55 -21
- package/dist/es2019/components/common/styles.js +41 -10
- package/dist/es2019/components/i18n.js +44 -4
- package/dist/es2019/components/picker/CategorySelector.js +114 -89
- package/dist/es2019/components/picker/CategoryTracker.js +0 -24
- package/dist/es2019/components/picker/EmojiPickerCategoryHeading.js +2 -2
- package/dist/es2019/components/picker/EmojiPickerComponent.js +36 -46
- package/dist/es2019/components/picker/EmojiPickerEmojiRow.js +51 -21
- package/dist/es2019/components/picker/EmojiPickerList.js +113 -55
- package/dist/es2019/components/picker/EmojiPickerListSearch.js +61 -98
- package/dist/es2019/components/picker/EmojiPickerVirtualItems.js +4 -1
- package/dist/es2019/components/picker/VirtualList.js +247 -108
- package/dist/es2019/components/picker/styles.js +20 -28
- package/dist/es2019/components/typeahead/EmojiTypeAheadComponent.js +0 -10
- package/dist/es2019/context/EmojiPickerListContext.js +17 -0
- package/dist/es2019/hooks/useEmojiPickerListContext.js +3 -0
- package/dist/es2019/hooks/useIsMounted.js +11 -0
- package/dist/es2019/i18n/cs.js +35 -34
- package/dist/es2019/i18n/da.js +35 -34
- package/dist/es2019/i18n/de.js +35 -34
- package/dist/es2019/i18n/en.js +35 -34
- package/dist/es2019/i18n/en_GB.js +35 -34
- package/dist/es2019/i18n/es.js +35 -34
- package/dist/es2019/i18n/fi.js +35 -34
- package/dist/es2019/i18n/fr.js +35 -34
- package/dist/es2019/i18n/hu.js +35 -34
- package/dist/es2019/i18n/it.js +35 -34
- package/dist/es2019/i18n/ja.js +35 -34
- package/dist/es2019/i18n/ko.js +35 -34
- package/dist/es2019/i18n/nb.js +35 -34
- package/dist/es2019/i18n/nl.js +35 -34
- package/dist/es2019/i18n/pl.js +35 -34
- package/dist/es2019/i18n/pt_BR.js +35 -34
- package/dist/es2019/i18n/ru.js +35 -34
- package/dist/es2019/i18n/sv.js +35 -34
- package/dist/es2019/i18n/th.js +35 -34
- package/dist/es2019/i18n/tr.js +35 -34
- package/dist/es2019/i18n/uk.js +35 -34
- package/dist/es2019/i18n/vi.js +35 -34
- package/dist/es2019/i18n/zh.js +35 -34
- package/dist/es2019/i18n/zh_TW.js +35 -34
- package/dist/es2019/types.js +5 -0
- package/dist/es2019/util/constants.js +32 -0
- package/dist/es2019/util/shared-styles.js +1 -2
- package/dist/es2019/version.json +1 -1
- package/dist/esm/api/EmojiResource.js +42 -26
- package/dist/esm/api/media/TokenManager.js +4 -4
- package/dist/esm/components/common/CachingEmoji.js +14 -6
- package/dist/esm/components/common/Emoji.js +48 -12
- package/dist/esm/components/common/EmojiActions.js +62 -26
- package/dist/esm/components/common/EmojiErrorMessage.js +7 -3
- package/dist/esm/components/common/EmojiPlaceholder.js +1 -0
- package/dist/esm/components/common/EmojiRadioButton.js +52 -0
- package/dist/esm/components/common/EmojiUploadPicker.js +77 -36
- package/dist/esm/components/common/EmojiUploadPreview.js +11 -2
- package/dist/esm/components/common/FileChooser.js +1 -1
- package/dist/esm/components/common/ResourcedEmojiComponent.js +4 -0
- package/dist/esm/components/common/RetryableButton.js +7 -3
- package/dist/esm/components/common/TonePreviewButton.js +33 -0
- package/dist/esm/components/common/ToneSelector.js +49 -18
- package/dist/esm/components/common/styles.js +40 -12
- package/dist/esm/components/i18n.js +44 -4
- package/dist/esm/components/picker/CategorySelector.js +114 -95
- package/dist/esm/components/picker/CategoryTracker.js +0 -28
- package/dist/esm/components/picker/EmojiPickerCategoryHeading.js +2 -2
- package/dist/esm/components/picker/EmojiPickerComponent.js +35 -46
- package/dist/esm/components/picker/EmojiPickerEmojiRow.js +32 -4
- package/dist/esm/components/picker/EmojiPickerList.js +156 -86
- package/dist/esm/components/picker/EmojiPickerListSearch.js +64 -117
- package/dist/esm/components/picker/EmojiPickerVirtualItems.js +5 -2
- package/dist/esm/components/picker/VirtualList.js +274 -172
- package/dist/esm/components/picker/styles.js +37 -45
- package/dist/esm/components/typeahead/EmojiTypeAheadComponent.js +0 -10
- package/dist/esm/context/EmojiPickerListContext.js +21 -0
- package/dist/esm/hooks/useEmojiPickerListContext.js +5 -0
- package/dist/esm/hooks/useIsMounted.js +11 -0
- package/dist/esm/i18n/cs.js +35 -34
- package/dist/esm/i18n/da.js +35 -34
- package/dist/esm/i18n/de.js +35 -34
- package/dist/esm/i18n/en.js +35 -34
- package/dist/esm/i18n/en_GB.js +35 -34
- package/dist/esm/i18n/es.js +35 -34
- package/dist/esm/i18n/fi.js +35 -34
- package/dist/esm/i18n/fr.js +35 -34
- package/dist/esm/i18n/hu.js +35 -34
- package/dist/esm/i18n/it.js +35 -34
- package/dist/esm/i18n/ja.js +35 -34
- package/dist/esm/i18n/ko.js +35 -34
- package/dist/esm/i18n/nb.js +35 -34
- package/dist/esm/i18n/nl.js +35 -34
- package/dist/esm/i18n/pl.js +35 -34
- package/dist/esm/i18n/pt_BR.js +35 -34
- package/dist/esm/i18n/ru.js +35 -34
- package/dist/esm/i18n/sv.js +35 -34
- package/dist/esm/i18n/th.js +35 -34
- package/dist/esm/i18n/tr.js +35 -34
- package/dist/esm/i18n/uk.js +35 -34
- package/dist/esm/i18n/vi.js +35 -34
- package/dist/esm/i18n/zh.js +35 -34
- package/dist/esm/i18n/zh_TW.js +35 -34
- package/dist/esm/types.js +5 -0
- package/dist/esm/util/constants.js +32 -0
- package/dist/esm/util/shared-styles.js +1 -2
- package/dist/esm/version.json +1 -1
- package/dist/types/api/EmojiResource.d.ts +2 -0
- package/dist/types/components/common/Emoji.d.ts +7 -1
- package/dist/types/components/common/EmojiActions.d.ts +4 -3
- package/dist/types/components/common/{EmojiButton.d.ts → EmojiRadioButton.d.ts} +3 -4
- package/dist/types/components/common/EmojiUploadPicker.d.ts +6 -4
- package/dist/types/components/common/RetryableButton.d.ts +1 -0
- package/dist/types/components/common/TonePreviewButton.d.ts +14 -0
- package/dist/types/components/common/ToneSelector.d.ts +8 -5
- package/dist/types/components/common/internal-types.d.ts +9 -0
- package/dist/types/components/common/styles.d.ts +2 -1
- package/dist/types/components/i18n.d.ts +40 -0
- package/dist/types/components/picker/CategorySelector.d.ts +3 -10
- package/dist/types/components/picker/CategoryTracker.d.ts +0 -2
- package/dist/types/components/picker/EmojiPickerCategoryHeading.d.ts +2 -1
- package/dist/types/components/picker/EmojiPickerEmojiRow.d.ts +5 -0
- package/dist/types/components/picker/EmojiPickerList.d.ts +14 -7
- package/dist/types/components/picker/EmojiPickerListSearch.d.ts +4 -8
- package/dist/types/components/picker/EmojiPickerVirtualItems.d.ts +1 -1
- package/dist/types/components/picker/VirtualList.d.ts +7 -24
- package/dist/types/components/picker/styles.d.ts +1 -1
- package/dist/types/context/EmojiPickerListContext.d.ts +10 -0
- package/dist/types/hooks/useEmojiPickerListContext.d.ts +1 -0
- package/dist/types/hooks/useIsMounted.d.ts +1 -0
- package/dist/types/i18n/cs.d.ts +34 -34
- package/dist/types/i18n/da.d.ts +34 -34
- package/dist/types/i18n/de.d.ts +34 -34
- package/dist/types/i18n/en.d.ts +34 -34
- package/dist/types/i18n/en_GB.d.ts +34 -34
- package/dist/types/i18n/es.d.ts +34 -34
- package/dist/types/i18n/fi.d.ts +34 -34
- package/dist/types/i18n/fr.d.ts +34 -34
- package/dist/types/i18n/hu.d.ts +34 -34
- package/dist/types/i18n/it.d.ts +34 -34
- package/dist/types/i18n/ja.d.ts +34 -34
- package/dist/types/i18n/ko.d.ts +34 -34
- package/dist/types/i18n/nb.d.ts +34 -34
- package/dist/types/i18n/nl.d.ts +34 -34
- package/dist/types/i18n/pl.d.ts +34 -34
- package/dist/types/i18n/pt_BR.d.ts +34 -34
- package/dist/types/i18n/ru.d.ts +34 -34
- package/dist/types/i18n/sv.d.ts +34 -34
- package/dist/types/i18n/th.d.ts +34 -34
- package/dist/types/i18n/tr.d.ts +34 -34
- package/dist/types/i18n/uk.d.ts +34 -34
- package/dist/types/i18n/vi.d.ts +34 -34
- package/dist/types/i18n/zh.d.ts +34 -34
- package/dist/types/i18n/zh_TW.d.ts +34 -34
- package/dist/types/types.d.ts +5 -0
- package/dist/types/util/constants.d.ts +28 -0
- package/dist/types/util/shared-styles.d.ts +1 -1
- package/dist/types/util/type-helpers.d.ts +1 -1
- package/package.json +12 -8
- package/report.api.md +62 -1
- package/README.md +0 -3
- package/dist/cjs/components/hooks.js +0 -14
- package/dist/es2019/components/common/EmojiButton.js +0 -49
- package/dist/es2019/components/hooks.js +0 -8
- package/dist/esm/components/common/EmojiButton.js +0 -43
- package/dist/esm/components/hooks.js +0 -8
- package/dist/types/components/hooks.d.ts +0 -1
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
import { useCallback, useEffect, useMemo, useRef, useState, createRef, memo } from 'react';
|
|
3
3
|
import { jsx } from '@emotion/react';
|
|
4
4
|
import { unstable_batchedUpdates as batchedUpdates } from 'react-dom';
|
|
5
|
-
import { FormattedMessage } from 'react-intl-next';
|
|
5
|
+
import { FormattedMessage, useIntl } from 'react-intl-next';
|
|
6
6
|
import { getEmojiVariation } from '../../api/EmojiRepository';
|
|
7
7
|
import { supportsUploadFeature } from '../../api/EmojiResource';
|
|
8
8
|
import { customCategory, defaultEmojiPickerSize, frequentCategory } from '../../util/constants';
|
|
9
9
|
import { containsEmojiId, isPromise /*, isEmojiIdEqual, isEmojiLoaded*/, isEmojiDescription } from '../../util/type-helpers';
|
|
10
|
-
import { SearchSort } from '../../types';
|
|
10
|
+
import { SearchSort, SearchSourceTypes } from '../../types';
|
|
11
11
|
import { getToneEmoji } from '../../util/filters';
|
|
12
12
|
import { uploadEmoji } from '../common/UploadEmoji';
|
|
13
13
|
import { createRecordSelectionDefault } from '../common/RecordSelectionDefault';
|
|
@@ -16,8 +16,9 @@ import EmojiPickerFooter from './EmojiPickerFooter';
|
|
|
16
16
|
import EmojiPickerList from './EmojiPickerList';
|
|
17
17
|
import { createAndFireEventInElementsChannel, categoryClickedEvent, closedPickerEvent, deleteBeginEvent, deleteCancelEvent, deleteConfirmEvent, openedPickerEvent, pickerClickedEvent, pickerSearchedEvent, selectedFileEvent, uploadBeginButton, uploadCancelButton, uploadConfirmButton, toneSelectorClosedEvent, ufoExperiences } from '../../util/analytics';
|
|
18
18
|
import { emojiPicker } from './styles';
|
|
19
|
-
import { useDidMount } from '../hooks';
|
|
20
19
|
import { useEmoji } from '../../hooks/useEmoji';
|
|
20
|
+
import { useIsMounted } from '../../hooks/useIsMounted';
|
|
21
|
+
import { messages } from '../i18n';
|
|
21
22
|
const FREQUENTLY_USED_MAX = 16;
|
|
22
23
|
const EmojiPickerComponent = ({
|
|
23
24
|
onSelection,
|
|
@@ -26,6 +27,9 @@ const EmojiPickerComponent = ({
|
|
|
26
27
|
createAnalyticsEvent,
|
|
27
28
|
size = defaultEmojiPickerSize
|
|
28
29
|
}) => {
|
|
30
|
+
const {
|
|
31
|
+
formatMessage
|
|
32
|
+
} = useIntl();
|
|
29
33
|
const {
|
|
30
34
|
emojiProvider,
|
|
31
35
|
isUploadSupported
|
|
@@ -47,12 +51,11 @@ const EmojiPickerComponent = ({
|
|
|
47
51
|
const emojiPickerList = useMemo(() => /*#__PURE__*/createRef(), []);
|
|
48
52
|
const openTime = useRef(0);
|
|
49
53
|
const isMounting = useRef(true);
|
|
50
|
-
const didMount = useDidMount();
|
|
51
|
-
const updateAfterDidMount = useRef(true);
|
|
52
54
|
const previousEmojiProvider = useRef(emojiProvider);
|
|
53
55
|
const currentUser = useMemo(() => {
|
|
54
56
|
return emojiProvider.getCurrentUser();
|
|
55
57
|
}, [emojiProvider]);
|
|
58
|
+
const isMounted = useIsMounted();
|
|
56
59
|
const fireAnalytics = useCallback(analyticsEvent => {
|
|
57
60
|
if (createAnalyticsEvent) {
|
|
58
61
|
createAndFireEventInElementsChannel(analyticsEvent)(createAnalyticsEvent);
|
|
@@ -157,7 +160,11 @@ const EmojiPickerComponent = ({
|
|
|
157
160
|
emojiToRender,
|
|
158
161
|
searchEmoji: searchResults.emojis
|
|
159
162
|
});
|
|
160
|
-
|
|
163
|
+
fireAnalytics(pickerSearchedEvent({
|
|
164
|
+
queryLength: searchQuery.length,
|
|
165
|
+
numMatches: searchResults.emojis.length
|
|
166
|
+
}));
|
|
167
|
+
}, [frequentlyUsedEmojis, query, setStateAfterEmojiChange, fireAnalytics]);
|
|
161
168
|
const onProviderChange = useMemo(() => {
|
|
162
169
|
return {
|
|
163
170
|
result: onSearchResult
|
|
@@ -242,22 +249,22 @@ const EmojiPickerComponent = ({
|
|
|
242
249
|
const onFileChooserClicked = useCallback(() => {
|
|
243
250
|
fireAnalytics(selectedFileEvent());
|
|
244
251
|
}, [fireAnalytics]);
|
|
252
|
+
const scrollToTopOfList = useCallback(() => {
|
|
253
|
+
var _emojiPickerList$curr;
|
|
254
|
+
(_emojiPickerList$curr = emojiPickerList.current) === null || _emojiPickerList$curr === void 0 ? void 0 : _emojiPickerList$curr.scrollToTop();
|
|
255
|
+
}, [emojiPickerList]);
|
|
245
256
|
const onSearch = useCallback(searchQuery => {
|
|
246
257
|
const options = {
|
|
247
|
-
skinTone: selectedTone
|
|
258
|
+
skinTone: selectedTone,
|
|
259
|
+
source: SearchSourceTypes.PICKER
|
|
248
260
|
};
|
|
249
|
-
if (query) {
|
|
250
|
-
ufoExperiences['emoji-searched'].start();
|
|
251
|
-
ufoExperiences['emoji-searched'].addMetadata({
|
|
252
|
-
queryLength: query.length,
|
|
253
|
-
source: 'EmojiPickerComponent'
|
|
254
|
-
});
|
|
255
|
-
}
|
|
256
261
|
if (searchQuery !== query) {
|
|
257
262
|
setQuery(searchQuery);
|
|
263
|
+
// scroll to top when search, which is search results section
|
|
264
|
+
scrollToTopOfList();
|
|
258
265
|
}
|
|
259
|
-
updateEmojis(
|
|
260
|
-
}, [query, selectedTone, updateEmojis]);
|
|
266
|
+
updateEmojis(searchQuery, options);
|
|
267
|
+
}, [query, selectedTone, updateEmojis, scrollToTopOfList]);
|
|
261
268
|
const onOpenUpload = useCallback(() => {
|
|
262
269
|
// Prime upload token so it's ready when the user adds
|
|
263
270
|
if (supportsUploadFeature(emojiProvider)) {
|
|
@@ -269,12 +276,12 @@ const EmojiPickerComponent = ({
|
|
|
269
276
|
});
|
|
270
277
|
fireAnalytics(uploadBeginButton());
|
|
271
278
|
}, [emojiProvider, fireAnalytics]);
|
|
272
|
-
const
|
|
279
|
+
const scrollToUploadedEmoji = useCallback(() => {
|
|
273
280
|
if (emojiPickerList.current) {
|
|
274
281
|
// Wait a tick to ensure repaint and updated height for picker list
|
|
275
282
|
window.setTimeout(() => {
|
|
276
|
-
var _emojiPickerList$
|
|
277
|
-
(_emojiPickerList$
|
|
283
|
+
var _emojiPickerList$curr2;
|
|
284
|
+
(_emojiPickerList$curr2 = emojiPickerList.current) === null || _emojiPickerList$curr2 === void 0 ? void 0 : _emojiPickerList$curr2.scrollToRecentlyUploaded();
|
|
278
285
|
}, 0);
|
|
279
286
|
}
|
|
280
287
|
}, [emojiPickerList]);
|
|
@@ -291,10 +298,10 @@ const EmojiPickerComponent = ({
|
|
|
291
298
|
setSelectedEmoji(emojiDescription);
|
|
292
299
|
setUploading(false);
|
|
293
300
|
});
|
|
294
|
-
|
|
301
|
+
scrollToUploadedEmoji();
|
|
295
302
|
};
|
|
296
303
|
uploadEmoji(upload, emojiProvider, errorSetter, onSuccess, fireAnalytics, retry);
|
|
297
|
-
}, [emojiProvider, fireAnalytics,
|
|
304
|
+
}, [emojiProvider, fireAnalytics, scrollToUploadedEmoji]);
|
|
298
305
|
const onTriggerDelete = useCallback((_emojiId, emoji) => {
|
|
299
306
|
if (_emojiId) {
|
|
300
307
|
fireAnalytics(deleteBeginEvent({
|
|
@@ -343,11 +350,10 @@ const EmojiPickerComponent = ({
|
|
|
343
350
|
}
|
|
344
351
|
useEffect(() => {
|
|
345
352
|
// componentDidMount logic
|
|
346
|
-
if (
|
|
353
|
+
if (!isMounted) {
|
|
347
354
|
onComponentDidMount();
|
|
348
|
-
updateAfterDidMount.current = false;
|
|
349
355
|
}
|
|
350
|
-
}, [
|
|
356
|
+
}, [onComponentDidMount, isMounted]);
|
|
351
357
|
useEffect(() => {
|
|
352
358
|
previousEmojiProvider.current.unsubscribe(onProviderChange);
|
|
353
359
|
previousEmojiProvider.current = emojiProvider;
|
|
@@ -356,26 +362,6 @@ const EmojiPickerComponent = ({
|
|
|
356
362
|
emojiProvider.unsubscribe(onProviderChange);
|
|
357
363
|
};
|
|
358
364
|
}, [emojiProvider, onProviderChange]);
|
|
359
|
-
useEffect(() => {
|
|
360
|
-
// We changed provider which means we subscribed to filter results for a new subscriber.
|
|
361
|
-
// So we refresh the emoji display with onSearch and we do it here, after the new props have
|
|
362
|
-
// been set since onSearch leads to filter being called on the current emojiProvider.
|
|
363
|
-
// (Calling onSearch in a '...Will...' lifecycle method would lead to filter being called on
|
|
364
|
-
// an emojiProvider we have already unsubscribed from)
|
|
365
|
-
onSearch(query);
|
|
366
|
-
}, [emojiProvider, onSearch, query]);
|
|
367
|
-
useEffect(() => {
|
|
368
|
-
// Fire analytics event whenever query changes
|
|
369
|
-
fireAnalytics(pickerSearchedEvent({
|
|
370
|
-
queryLength: query.length,
|
|
371
|
-
numMatches: filteredEmojis.length
|
|
372
|
-
}));
|
|
373
|
-
ufoExperiences['emoji-searched'].success({
|
|
374
|
-
metadata: {
|
|
375
|
-
emojisLength: filteredEmojis.length
|
|
376
|
-
}
|
|
377
|
-
});
|
|
378
|
-
}, [filteredEmojis.length, fireAnalytics, query]);
|
|
379
365
|
useEffect(() => {
|
|
380
366
|
if (!frequentlyUsedEmojis.length || query) {
|
|
381
367
|
setFilteredEmojis(searchEmojis);
|
|
@@ -413,7 +399,10 @@ const EmojiPickerComponent = ({
|
|
|
413
399
|
return jsx("div", {
|
|
414
400
|
css: emojiPicker(showPreview, size),
|
|
415
401
|
ref: onPickerRef,
|
|
416
|
-
"data-emoji-picker-container": true
|
|
402
|
+
"data-emoji-picker-container": true,
|
|
403
|
+
role: "dialog",
|
|
404
|
+
"aria-label": formatMessage(messages.emojiPickerTitle),
|
|
405
|
+
"aria-modal": true
|
|
417
406
|
}, jsx(CategorySelector, {
|
|
418
407
|
activeCategoryId: activeCategory,
|
|
419
408
|
dynamicCategories: dynamicCategories,
|
|
@@ -445,7 +434,8 @@ const EmojiPickerComponent = ({
|
|
|
445
434
|
onCloseDelete: onCloseDelete,
|
|
446
435
|
onFileChooserClicked: onFileChooserClicked,
|
|
447
436
|
onOpenUpload: onOpenUpload,
|
|
448
|
-
size: size
|
|
437
|
+
size: size,
|
|
438
|
+
activeCategoryId: activeCategory
|
|
449
439
|
}), showPreview && jsx(EmojiPickerFooter, {
|
|
450
440
|
selectedEmoji: selectedEmoji
|
|
451
441
|
}));
|
|
@@ -1,35 +1,65 @@
|
|
|
1
1
|
/** @jsx jsx */
|
|
2
2
|
import { memo } from 'react';
|
|
3
3
|
import { jsx } from '@emotion/react';
|
|
4
|
+
import { useIntl } from 'react-intl-next';
|
|
4
5
|
import CachingEmoji from '../common/CachingEmoji';
|
|
5
6
|
import { emojiItem, emojiPickerRow } from './styles';
|
|
7
|
+
import { useEmojiPickerListContext } from '../../hooks/useEmojiPickerListContext';
|
|
8
|
+
import { messages } from '../i18n';
|
|
6
9
|
const EmojiPickerEmojiRow = ({
|
|
7
10
|
emojis,
|
|
8
11
|
onSelected,
|
|
9
12
|
onMouseMove,
|
|
13
|
+
onFocus,
|
|
10
14
|
title,
|
|
11
15
|
showDelete,
|
|
12
|
-
onDelete
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}, emojis.map(emoji => {
|
|
16
|
+
onDelete,
|
|
17
|
+
virtualItemContext
|
|
18
|
+
}) => {
|
|
16
19
|
const {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
} =
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
20
|
+
currentEmojisFocus,
|
|
21
|
+
setEmojisFocus
|
|
22
|
+
} = useEmojiPickerListContext();
|
|
23
|
+
const rowIndex = (virtualItemContext === null || virtualItemContext === void 0 ? void 0 : virtualItemContext.index) || 0;
|
|
24
|
+
const {
|
|
25
|
+
formatMessage
|
|
26
|
+
} = useIntl();
|
|
27
|
+
const handleFocus = index => (emojiId, emoji, event) => {
|
|
28
|
+
setEmojisFocus({
|
|
29
|
+
rowIndex,
|
|
30
|
+
columnIndex: index
|
|
31
|
+
});
|
|
32
|
+
onFocus && onFocus(emojiId, emoji, event);
|
|
33
|
+
};
|
|
34
|
+
return jsx("div", {
|
|
35
|
+
css: emojiPickerRow,
|
|
36
|
+
role: "presentation"
|
|
37
|
+
}, emojis.map((emoji, index) => {
|
|
38
|
+
const {
|
|
39
|
+
shortName,
|
|
40
|
+
id
|
|
41
|
+
} = emoji;
|
|
42
|
+
const key = id ? `${id}-${title}` : `${shortName}-${title}`;
|
|
43
|
+
const focus = currentEmojisFocus.rowIndex === rowIndex && currentEmojisFocus.columnIndex === index;
|
|
44
|
+
return jsx("span", {
|
|
45
|
+
css: emojiItem,
|
|
46
|
+
key: key,
|
|
47
|
+
role: "gridcell",
|
|
48
|
+
"aria-colindex": index + 1 // aria-colindex is 1 based
|
|
49
|
+
}, jsx(CachingEmoji, {
|
|
50
|
+
emoji: emoji,
|
|
51
|
+
selectOnHover: true,
|
|
52
|
+
onSelected: onSelected,
|
|
53
|
+
onMouseMove: onMouseMove,
|
|
54
|
+
onFocus: handleFocus(index),
|
|
55
|
+
showDelete: showDelete,
|
|
56
|
+
onDelete: onDelete,
|
|
57
|
+
placeholderSize: 24,
|
|
58
|
+
"data-focus-index": `${rowIndex}-${index}`,
|
|
59
|
+
tabIndex: focus ? 0 : -1,
|
|
60
|
+
"aria-roledescription": formatMessage(messages.emojiButtonRoleDescription),
|
|
61
|
+
shouldBeInteractive: true
|
|
62
|
+
}));
|
|
33
63
|
}));
|
|
34
|
-
}
|
|
64
|
+
};
|
|
35
65
|
export default /*#__PURE__*/memo(EmojiPickerEmojiRow);
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
2
|
/** @jsx jsx */
|
|
3
|
-
import
|
|
3
|
+
import { createRef, PureComponent } from 'react';
|
|
4
4
|
import { jsx } from '@emotion/react';
|
|
5
|
-
import
|
|
5
|
+
import VisuallyHidden from '@atlaskit/visually-hidden';
|
|
6
|
+
import { customCategory, defaultEmojiPickerSize, frequentCategory, searchCategory, userCustomTitle, yourUploadsCategory } from '../../util/constants';
|
|
6
7
|
import { CategoryDescriptionMap } from './categories';
|
|
7
8
|
import CategoryTracker from './CategoryTracker';
|
|
8
9
|
import { sizes } from './EmojiPickerSizes';
|
|
@@ -11,25 +12,60 @@ import EmojiActions from '../common/EmojiActions';
|
|
|
11
12
|
import { emojiPickerList } from './styles';
|
|
12
13
|
import { emojiPickerHeightOffset } from './utils';
|
|
13
14
|
import { VirtualList } from './VirtualList';
|
|
15
|
+
import { injectIntl } from 'react-intl-next';
|
|
16
|
+
import { messages } from '../i18n';
|
|
17
|
+
import { EmojiPickerListContextProvider } from '../../context/EmojiPickerListContext';
|
|
18
|
+
|
|
14
19
|
/**
|
|
15
20
|
* Test id for wrapper Emoji Picker List div
|
|
16
21
|
*/
|
|
17
22
|
export const RENDER_EMOJI_PICKER_LIST_TESTID = 'render-emoji-picker-list';
|
|
18
23
|
const categoryClassname = 'emoji-category';
|
|
19
24
|
const byOrder = (orderableA, orderableB) => (orderableA.order || 0) - (orderableB.order || 0);
|
|
20
|
-
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* TODO: have to use class component here as unit test is relying on ref.root. Will refactor this whole file to functional component in future
|
|
28
|
+
* ticket: COLLAB-2317
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
class EmojiPickerTabPanelInternal extends PureComponent {
|
|
32
|
+
render() {
|
|
33
|
+
const {
|
|
34
|
+
intl: {
|
|
35
|
+
formatMessage
|
|
36
|
+
},
|
|
37
|
+
children,
|
|
38
|
+
showSearchResults
|
|
39
|
+
} = this.props;
|
|
40
|
+
return jsx("div", {
|
|
41
|
+
ref: "root",
|
|
42
|
+
css: emojiPickerList,
|
|
43
|
+
"data-testid": RENDER_EMOJI_PICKER_LIST_TESTID,
|
|
44
|
+
id: RENDER_EMOJI_PICKER_LIST_TESTID,
|
|
45
|
+
role: "tabpanel",
|
|
46
|
+
"aria-label": formatMessage(messages.emojiPickerListPanel)
|
|
47
|
+
}, jsx(VisuallyHidden, {
|
|
48
|
+
id: "emoji-picker-table-description"
|
|
49
|
+
}, formatMessage(messages.emojiPickerGrid, {
|
|
50
|
+
showSearchResults
|
|
51
|
+
})), children);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
const EmojiPickerTabPanel = injectIntl(EmojiPickerTabPanelInternal);
|
|
55
|
+
export default class EmojiPickerVirtualListInternal extends PureComponent {
|
|
21
56
|
constructor(_props) {
|
|
22
57
|
super(_props);
|
|
23
58
|
_defineProperty(this, "virtualItems", []);
|
|
24
59
|
_defineProperty(this, "categoryTracker", new CategoryTracker());
|
|
25
|
-
_defineProperty(this, "
|
|
60
|
+
_defineProperty(this, "listRef", /*#__PURE__*/createRef());
|
|
61
|
+
_defineProperty(this, "onEmojiActive", (emojiId, emoji) => {
|
|
26
62
|
if (this.props.onEmojiActive) {
|
|
27
63
|
this.props.onEmojiActive(emojiId, emoji);
|
|
28
64
|
}
|
|
29
65
|
});
|
|
30
|
-
_defineProperty(this, "onSearch",
|
|
66
|
+
_defineProperty(this, "onSearch", value => {
|
|
31
67
|
if (this.props.onSearch) {
|
|
32
|
-
this.props.onSearch(
|
|
68
|
+
this.props.onSearch(value);
|
|
33
69
|
}
|
|
34
70
|
});
|
|
35
71
|
_defineProperty(this, "buildVirtualItemFromGroup", group => {
|
|
@@ -48,12 +84,14 @@ export default class EmojiPickerVirtualList extends PureComponent {
|
|
|
48
84
|
const rowEmojis = remainingEmojis.slice(0, sizes.emojiPerRow);
|
|
49
85
|
remainingEmojis = remainingEmojis.slice(sizes.emojiPerRow);
|
|
50
86
|
items.push(new EmojisRowItem({
|
|
87
|
+
category: group.category,
|
|
51
88
|
emojis: rowEmojis,
|
|
52
89
|
title: group.title,
|
|
53
90
|
showDelete: group.title === userCustomTitle,
|
|
54
91
|
onSelected: onEmojiSelected,
|
|
55
92
|
onDelete: onEmojiDelete,
|
|
56
|
-
onMouseMove: this.
|
|
93
|
+
onMouseMove: this.onEmojiActive,
|
|
94
|
+
onFocus: this.onEmojiActive
|
|
57
95
|
}));
|
|
58
96
|
}
|
|
59
97
|
return items;
|
|
@@ -73,7 +111,7 @@ export default class EmojiPickerVirtualList extends PureComponent {
|
|
|
73
111
|
const search = CategoryDescriptionMap.SEARCH;
|
|
74
112
|
// Only a single "result" category
|
|
75
113
|
items = [...items, ...this.buildVirtualItemFromGroup({
|
|
76
|
-
category:
|
|
114
|
+
category: searchCategory,
|
|
77
115
|
title: search.name,
|
|
78
116
|
emojis,
|
|
79
117
|
order: search.order
|
|
@@ -87,22 +125,16 @@ export default class EmojiPickerVirtualList extends PureComponent {
|
|
|
87
125
|
// by not passing it to irrelevant groups
|
|
88
126
|
this.categoryTracker.add(group.emojis[0].category, items.length);
|
|
89
127
|
items = [...items, ...this.buildVirtualItemFromGroup(group)];
|
|
128
|
+
if (group.category === yourUploadsCategory) {
|
|
129
|
+
this.lastYourUploadsRow = items.length - 1;
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
this.onRowsRendered({
|
|
133
|
+
startIndex: 0
|
|
90
134
|
});
|
|
91
135
|
}
|
|
92
136
|
}
|
|
93
|
-
const rowCountChanged = this.virtualItems.length !== items.length;
|
|
94
137
|
this.virtualItems = items;
|
|
95
|
-
const list = this.refs.list;
|
|
96
|
-
if (!rowCountChanged && list) {
|
|
97
|
-
// Row count has not changed, so need to tell list to rerender.
|
|
98
|
-
list.forceUpdateGrid();
|
|
99
|
-
}
|
|
100
|
-
if (!query && list) {
|
|
101
|
-
// VirtualList can apply stale heights since it performs a shallow
|
|
102
|
-
// compare to check if the list has changed. Should manually recompute
|
|
103
|
-
// row heights for the case when frequent category come in later
|
|
104
|
-
list.recomputeRowHeights();
|
|
105
|
-
}
|
|
106
138
|
});
|
|
107
139
|
_defineProperty(this, "addToCategoryMap", (categoryToGroupMap, emoji, category) => {
|
|
108
140
|
if (!categoryToGroupMap[category]) {
|
|
@@ -121,46 +153,54 @@ export default class EmojiPickerVirtualList extends PureComponent {
|
|
|
121
153
|
this.addToCategoryMap(categoryToGroupMap, emoji, emoji.category);
|
|
122
154
|
// separate user emojis
|
|
123
155
|
if (emoji.category === customCategory && currentUser && emoji.creatorUserId === currentUser.id) {
|
|
124
|
-
this.addToCategoryMap(categoryToGroupMap, emoji,
|
|
156
|
+
this.addToCategoryMap(categoryToGroupMap, emoji, yourUploadsCategory);
|
|
125
157
|
}
|
|
126
158
|
return categoryToGroupMap;
|
|
127
159
|
});
|
|
128
160
|
_defineProperty(this, "buildEmojiGroupedByCategory", (emojis, currentUser) => {
|
|
129
161
|
const categoryToGroupMap = emojis.reduce(this.groupByCategory(currentUser), {});
|
|
130
162
|
this.allEmojiGroups = Object.keys(categoryToGroupMap).map(key => categoryToGroupMap[key]).map(group => {
|
|
131
|
-
if (group.category !==
|
|
163
|
+
if (group.category !== frequentCategory) {
|
|
132
164
|
group.emojis.sort(byOrder);
|
|
133
165
|
}
|
|
134
166
|
return group;
|
|
135
167
|
}).sort(byOrder);
|
|
136
168
|
});
|
|
137
|
-
_defineProperty(this, "
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
// we need to access offset to force repaint
|
|
144
|
-
// eslint-disable-next-line no-unused-expressions
|
|
145
|
-
root.offsetHeight;
|
|
146
|
-
root.style.display = display;
|
|
169
|
+
_defineProperty(this, "findCategoryToActivate", row => {
|
|
170
|
+
let category = null;
|
|
171
|
+
if (row instanceof CategoryHeadingItem) {
|
|
172
|
+
category = row.props.id;
|
|
173
|
+
} else if (row instanceof EmojisRowItem) {
|
|
174
|
+
category = row.props.category;
|
|
147
175
|
}
|
|
176
|
+
// your uploads is rendered, take it as upload category, so could be highlighted in category selector
|
|
177
|
+
if (category === yourUploadsCategory) {
|
|
178
|
+
return customCategory;
|
|
179
|
+
// search results is rendered, return null so won't be highlighted for category selector
|
|
180
|
+
} else if (category === searchCategory) {
|
|
181
|
+
return null;
|
|
182
|
+
}
|
|
183
|
+
return category;
|
|
148
184
|
});
|
|
149
|
-
_defineProperty(this, "
|
|
185
|
+
_defineProperty(this, "onRowsRendered", indexes => {
|
|
150
186
|
const {
|
|
151
187
|
startIndex
|
|
152
188
|
} = indexes;
|
|
189
|
+
const rowItem = this.virtualItems[startIndex];
|
|
190
|
+
const list = this.listRef.current;
|
|
153
191
|
|
|
154
|
-
//
|
|
155
|
-
if (
|
|
156
|
-
|
|
192
|
+
// update tabIndex manually, startIndex is not 0 based here
|
|
193
|
+
if (rowItem instanceof CategoryHeadingItem) {
|
|
194
|
+
// if top of row rendered is category heading, update tabIndex for the next emoji row
|
|
195
|
+
list === null || list === void 0 ? void 0 : list.updateFocusIndex(startIndex + 1);
|
|
196
|
+
} else if (rowItem instanceof EmojisRowItem) {
|
|
197
|
+
// if top of row rendered is emoji row, update it's tabIndex.
|
|
198
|
+
list === null || list === void 0 ? void 0 : list.updateFocusIndex(startIndex);
|
|
157
199
|
}
|
|
158
200
|
if (!this.props.query) {
|
|
159
201
|
// Calculate category in view - only relevant if categories shown, i.e. no query
|
|
160
|
-
const
|
|
161
|
-
|
|
162
|
-
if (currentCategory && this.activeCategoryId !== currentCategory) {
|
|
163
|
-
this.activeCategoryId = currentCategory;
|
|
202
|
+
const currentCategory = this.findCategoryToActivate(rowItem);
|
|
203
|
+
if (currentCategory !== null && this.props.activeCategoryId !== currentCategory) {
|
|
164
204
|
if (this.props.onCategoryActivated) {
|
|
165
205
|
this.props.onCategoryActivated(currentCategory);
|
|
166
206
|
}
|
|
@@ -174,6 +214,7 @@ export default class EmojiPickerVirtualList extends PureComponent {
|
|
|
174
214
|
_defineProperty(this, "renderRow", context => {
|
|
175
215
|
return virtualItemRenderer(this.virtualItems, context);
|
|
176
216
|
});
|
|
217
|
+
this.lastYourUploadsRow = 0;
|
|
177
218
|
this.buildEmojiGroupedByCategory(_props.emojis, _props.currentUser);
|
|
178
219
|
this.buildVirtualItems(_props, this.state);
|
|
179
220
|
}
|
|
@@ -191,12 +232,24 @@ export default class EmojiPickerVirtualList extends PureComponent {
|
|
|
191
232
|
*/
|
|
192
233
|
reveal(category) {
|
|
193
234
|
const row = this.categoryTracker.getRow(category);
|
|
194
|
-
|
|
195
|
-
list.scrollToRow(row);
|
|
235
|
+
this.scrollToRow(row);
|
|
196
236
|
}
|
|
197
237
|
scrollToBottom() {
|
|
198
|
-
|
|
199
|
-
|
|
238
|
+
this.scrollToRow(this.virtualItems.length);
|
|
239
|
+
}
|
|
240
|
+
scrollToTop() {
|
|
241
|
+
this.scrollToRow(0);
|
|
242
|
+
}
|
|
243
|
+
scrollToRow(index) {
|
|
244
|
+
var _this$listRef$current;
|
|
245
|
+
(_this$listRef$current = this.listRef.current) === null || _this$listRef$current === void 0 ? void 0 : _this$listRef$current.scrollToRow(index);
|
|
246
|
+
}
|
|
247
|
+
scrollToRecentlyUploaded() {
|
|
248
|
+
const row = this.lastYourUploadsRow;
|
|
249
|
+
if (row > 0) {
|
|
250
|
+
var _this$listRef$current2;
|
|
251
|
+
(_this$listRef$current2 = this.listRef.current) === null || _this$listRef$current2 === void 0 ? void 0 : _this$listRef$current2.scrollToRowAndFocusLastEmoji(this.lastYourUploadsRow);
|
|
252
|
+
}
|
|
200
253
|
}
|
|
201
254
|
render() {
|
|
202
255
|
const {
|
|
@@ -216,13 +269,12 @@ export default class EmojiPickerVirtualList extends PureComponent {
|
|
|
216
269
|
onDeleteEmoji,
|
|
217
270
|
onFileChooserClicked,
|
|
218
271
|
onOpenUpload,
|
|
219
|
-
size = defaultEmojiPickerSize
|
|
272
|
+
size = defaultEmojiPickerSize,
|
|
273
|
+
emojis
|
|
220
274
|
} = this.props;
|
|
221
275
|
const virtualListHeight = sizes.listHeight + emojiPickerHeightOffset(size);
|
|
222
|
-
return jsx(
|
|
223
|
-
|
|
224
|
-
css: emojiPickerList,
|
|
225
|
-
"data-testid": RENDER_EMOJI_PICKER_LIST_TESTID
|
|
276
|
+
return jsx(EmojiPickerTabPanel, {
|
|
277
|
+
showSearchResults: !!query
|
|
226
278
|
}, jsx(EmojiActions, {
|
|
227
279
|
selectedTone: selectedTone,
|
|
228
280
|
onToneSelected: onToneSelected,
|
|
@@ -240,9 +292,15 @@ export default class EmojiPickerVirtualList extends PureComponent {
|
|
|
240
292
|
onFileChooserClicked: onFileChooserClicked,
|
|
241
293
|
onOpenUpload: onOpenUpload,
|
|
242
294
|
query: query,
|
|
243
|
-
onChange: this.onSearch
|
|
244
|
-
|
|
245
|
-
|
|
295
|
+
onChange: this.onSearch,
|
|
296
|
+
resultsCount: emojis.length
|
|
297
|
+
}), jsx(EmojiPickerListContextProvider, {
|
|
298
|
+
initialEmojisFocus: {
|
|
299
|
+
rowIndex: 1,
|
|
300
|
+
columnIndex: 0
|
|
301
|
+
}
|
|
302
|
+
}, jsx(VirtualList, {
|
|
303
|
+
ref: this.listRef,
|
|
246
304
|
height: virtualListHeight,
|
|
247
305
|
overscanRowCount: 10,
|
|
248
306
|
rowCount: this.virtualItems.length,
|
|
@@ -250,11 +308,11 @@ export default class EmojiPickerVirtualList extends PureComponent {
|
|
|
250
308
|
rowRenderer: this.renderRow,
|
|
251
309
|
scrollToAlignment: "start",
|
|
252
310
|
width: sizes.listWidth,
|
|
253
|
-
onRowsRendered: this.
|
|
254
|
-
}));
|
|
311
|
+
onRowsRendered: this.onRowsRendered
|
|
312
|
+
})));
|
|
255
313
|
}
|
|
256
314
|
}
|
|
257
|
-
_defineProperty(
|
|
315
|
+
_defineProperty(EmojiPickerVirtualListInternal, "defaultProps", {
|
|
258
316
|
onEmojiSelected: () => {},
|
|
259
317
|
onEmojiActive: () => {},
|
|
260
318
|
onEmojiDelete: () => {},
|