@atlaskit/emoji 69.0.1 → 69.0.3

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.
Files changed (125) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/afm-cc/tsconfig.json +3 -0
  3. package/afm-jira/tsconfig.json +3 -0
  4. package/afm-post-office/tsconfig.json +3 -0
  5. package/dist/cjs/components/compiled/common/EmojiActions.js +1 -1
  6. package/dist/cjs/components/compiled/common/EmojiPreviewComponent.compiled.css +0 -1
  7. package/dist/cjs/components/compiled/common/EmojiPreviewComponent.js +1 -1
  8. package/dist/cjs/components/compiled/picker/CategorySelector.compiled.css +24 -0
  9. package/dist/cjs/components/compiled/picker/CategorySelector.js +161 -0
  10. package/dist/cjs/components/compiled/picker/EmojiPicker.compiled.css +12 -0
  11. package/dist/cjs/components/compiled/picker/EmojiPicker.js +109 -0
  12. package/dist/cjs/components/compiled/picker/EmojiPickerCategoryHeading.compiled.css +9 -0
  13. package/dist/cjs/components/compiled/picker/EmojiPickerCategoryHeading.js +43 -0
  14. package/dist/cjs/components/compiled/picker/EmojiPickerComponent.compiled.css +20 -0
  15. package/dist/cjs/components/compiled/picker/EmojiPickerComponent.js +574 -0
  16. package/dist/cjs/components/compiled/picker/EmojiPickerEmojiRow.compiled.css +35 -0
  17. package/dist/cjs/components/compiled/picker/EmojiPickerEmojiRow.js +76 -0
  18. package/dist/cjs/components/compiled/picker/EmojiPickerFooter.compiled.css +5 -0
  19. package/dist/cjs/components/compiled/picker/EmojiPickerFooter.js +33 -0
  20. package/dist/cjs/components/compiled/picker/EmojiPickerListSearch.compiled.css +23 -0
  21. package/dist/cjs/components/compiled/picker/EmojiPickerListSearch.js +93 -0
  22. package/dist/cjs/components/compiled/picker/EmojiPickerTabPanel.compiled.css +6 -0
  23. package/dist/cjs/components/compiled/picker/EmojiPickerTabPanel.js +60 -0
  24. package/dist/cjs/components/compiled/picker/EmojiPickerVirtualItems.compiled.css +8 -0
  25. package/dist/cjs/components/compiled/picker/EmojiPickerVirtualItems.js +86 -0
  26. package/dist/cjs/components/compiled/picker/VirtualList.compiled.css +10 -0
  27. package/dist/cjs/components/compiled/picker/VirtualList.js +303 -0
  28. package/dist/cjs/components/picker/EmojiPickerFooter.js +0 -2
  29. package/dist/cjs/components/picker/EmojiPickerList.js +219 -145
  30. package/dist/cjs/components/picker/EmojiPickerTabPanel.js +67 -0
  31. package/dist/cjs/components/picker/styles.js +1 -10
  32. package/dist/cjs/index.js +4 -6
  33. package/dist/cjs/picker.js +5 -7
  34. package/dist/cjs/util/analytics/analytics.js +1 -1
  35. package/dist/es2019/components/compiled/common/EmojiActions.js +1 -1
  36. package/dist/es2019/components/compiled/common/EmojiPreviewComponent.compiled.css +0 -1
  37. package/dist/es2019/components/compiled/common/EmojiPreviewComponent.js +1 -1
  38. package/dist/es2019/components/compiled/picker/CategorySelector.compiled.css +24 -0
  39. package/dist/es2019/components/compiled/picker/CategorySelector.js +136 -0
  40. package/dist/es2019/components/compiled/picker/EmojiPicker.compiled.css +12 -0
  41. package/dist/es2019/components/compiled/picker/EmojiPicker.js +67 -0
  42. package/dist/es2019/components/compiled/picker/EmojiPickerCategoryHeading.compiled.css +9 -0
  43. package/dist/es2019/components/compiled/picker/EmojiPickerCategoryHeading.js +30 -0
  44. package/dist/es2019/components/compiled/picker/EmojiPickerComponent.compiled.css +19 -0
  45. package/dist/es2019/components/compiled/picker/EmojiPickerComponent.js +506 -0
  46. package/dist/es2019/components/compiled/picker/EmojiPickerEmojiRow.compiled.css +35 -0
  47. package/dist/es2019/components/compiled/picker/EmojiPickerEmojiRow.js +69 -0
  48. package/dist/es2019/components/compiled/picker/EmojiPickerFooter.compiled.css +5 -0
  49. package/dist/es2019/components/compiled/picker/EmojiPickerFooter.js +19 -0
  50. package/dist/es2019/components/compiled/picker/EmojiPickerListSearch.compiled.css +23 -0
  51. package/dist/es2019/components/compiled/picker/EmojiPickerListSearch.js +79 -0
  52. package/dist/es2019/components/compiled/picker/EmojiPickerTabPanel.compiled.css +6 -0
  53. package/dist/es2019/components/compiled/picker/EmojiPickerTabPanel.js +39 -0
  54. package/dist/es2019/components/compiled/picker/EmojiPickerVirtualItems.compiled.css +8 -0
  55. package/dist/es2019/components/compiled/picker/EmojiPickerVirtualItems.js +51 -0
  56. package/dist/es2019/components/compiled/picker/VirtualList.compiled.css +10 -0
  57. package/dist/es2019/components/compiled/picker/VirtualList.js +288 -0
  58. package/dist/es2019/components/picker/EmojiPickerFooter.js +1 -1
  59. package/dist/es2019/components/picker/EmojiPickerList.js +186 -114
  60. package/dist/es2019/components/picker/EmojiPickerTabPanel.js +48 -0
  61. package/dist/es2019/components/picker/styles.js +0 -9
  62. package/dist/es2019/index.js +2 -1
  63. package/dist/es2019/picker.js +5 -1
  64. package/dist/es2019/util/analytics/analytics.js +1 -1
  65. package/dist/esm/components/compiled/common/EmojiActions.js +1 -1
  66. package/dist/esm/components/compiled/common/EmojiPreviewComponent.compiled.css +0 -1
  67. package/dist/esm/components/compiled/common/EmojiPreviewComponent.js +1 -1
  68. package/dist/esm/components/compiled/picker/CategorySelector.compiled.css +24 -0
  69. package/dist/esm/components/compiled/picker/CategorySelector.js +151 -0
  70. package/dist/esm/components/compiled/picker/EmojiPicker.compiled.css +12 -0
  71. package/dist/esm/components/compiled/picker/EmojiPicker.js +97 -0
  72. package/dist/esm/components/compiled/picker/EmojiPickerCategoryHeading.compiled.css +9 -0
  73. package/dist/esm/components/compiled/picker/EmojiPickerCategoryHeading.js +34 -0
  74. package/dist/esm/components/compiled/picker/EmojiPickerComponent.compiled.css +20 -0
  75. package/dist/esm/components/compiled/picker/EmojiPickerComponent.js +564 -0
  76. package/dist/esm/components/compiled/picker/EmojiPickerEmojiRow.compiled.css +35 -0
  77. package/dist/esm/components/compiled/picker/EmojiPickerEmojiRow.js +66 -0
  78. package/dist/esm/components/compiled/picker/EmojiPickerFooter.compiled.css +5 -0
  79. package/dist/esm/components/compiled/picker/EmojiPickerFooter.js +24 -0
  80. package/dist/esm/components/compiled/picker/EmojiPickerListSearch.compiled.css +23 -0
  81. package/dist/esm/components/compiled/picker/EmojiPickerListSearch.js +83 -0
  82. package/dist/esm/components/compiled/picker/EmojiPickerTabPanel.compiled.css +6 -0
  83. package/dist/esm/components/compiled/picker/EmojiPickerTabPanel.js +50 -0
  84. package/dist/esm/components/compiled/picker/EmojiPickerVirtualItems.compiled.css +8 -0
  85. package/dist/esm/components/compiled/picker/EmojiPickerVirtualItems.js +76 -0
  86. package/dist/esm/components/compiled/picker/VirtualList.compiled.css +10 -0
  87. package/dist/esm/components/compiled/picker/VirtualList.js +293 -0
  88. package/dist/esm/components/picker/EmojiPickerFooter.js +1 -1
  89. package/dist/esm/components/picker/EmojiPickerList.js +219 -147
  90. package/dist/esm/components/picker/EmojiPickerTabPanel.js +59 -0
  91. package/dist/esm/components/picker/styles.js +0 -9
  92. package/dist/esm/index.js +2 -1
  93. package/dist/esm/picker.js +5 -1
  94. package/dist/esm/util/analytics/analytics.js +1 -1
  95. package/dist/types/components/compiled/picker/CategorySelector.d.ts +17 -0
  96. package/dist/types/components/compiled/picker/EmojiPicker.d.ts +44 -0
  97. package/dist/types/components/compiled/picker/EmojiPickerCategoryHeading.d.ts +13 -0
  98. package/dist/types/components/compiled/picker/EmojiPickerComponent.d.ts +24 -0
  99. package/dist/types/components/compiled/picker/EmojiPickerEmojiRow.d.ts +17 -0
  100. package/dist/types/components/compiled/picker/EmojiPickerFooter.d.ts +8 -0
  101. package/dist/types/components/compiled/picker/EmojiPickerListSearch.d.ts +11 -0
  102. package/dist/types/components/compiled/picker/EmojiPickerTabPanel.d.ts +21 -0
  103. package/dist/types/components/compiled/picker/EmojiPickerVirtualItems.d.ts +35 -0
  104. package/dist/types/components/compiled/picker/VirtualList.d.ts +42 -0
  105. package/dist/types/components/picker/EmojiPickerList.d.ts +1 -6
  106. package/dist/types/components/picker/EmojiPickerTabPanel.d.ts +21 -0
  107. package/dist/types/components/picker/styles.d.ts +0 -1
  108. package/dist/types/index.d.ts +2 -1
  109. package/dist/types/picker.d.ts +3 -1
  110. package/dist/types-ts4.5/components/compiled/picker/CategorySelector.d.ts +17 -0
  111. package/dist/types-ts4.5/components/compiled/picker/EmojiPicker.d.ts +44 -0
  112. package/dist/types-ts4.5/components/compiled/picker/EmojiPickerCategoryHeading.d.ts +13 -0
  113. package/dist/types-ts4.5/components/compiled/picker/EmojiPickerComponent.d.ts +24 -0
  114. package/dist/types-ts4.5/components/compiled/picker/EmojiPickerEmojiRow.d.ts +17 -0
  115. package/dist/types-ts4.5/components/compiled/picker/EmojiPickerFooter.d.ts +8 -0
  116. package/dist/types-ts4.5/components/compiled/picker/EmojiPickerListSearch.d.ts +11 -0
  117. package/dist/types-ts4.5/components/compiled/picker/EmojiPickerTabPanel.d.ts +21 -0
  118. package/dist/types-ts4.5/components/compiled/picker/EmojiPickerVirtualItems.d.ts +35 -0
  119. package/dist/types-ts4.5/components/compiled/picker/VirtualList.d.ts +42 -0
  120. package/dist/types-ts4.5/components/picker/EmojiPickerList.d.ts +1 -6
  121. package/dist/types-ts4.5/components/picker/EmojiPickerTabPanel.d.ts +21 -0
  122. package/dist/types-ts4.5/components/picker/styles.d.ts +0 -1
  123. package/dist/types-ts4.5/index.d.ts +2 -1
  124. package/dist/types-ts4.5/picker.d.ts +3 -1
  125. package/package.json +4 -3
@@ -0,0 +1,506 @@
1
+ /* EmojiPickerComponent.tsx generated by @compiled/babel-plugin v0.36.1 */
2
+ import "./EmojiPickerComponent.compiled.css";
3
+ import * as React from 'react';
4
+ import { ax, ix } from "@compiled/react/runtime";
5
+ import { useCallback, useEffect, useMemo, useRef, useState, createRef, memo } from 'react';
6
+ import { N40 } from '@atlaskit/theme/colors';
7
+ import { unstable_batchedUpdates as batchedUpdates } from 'react-dom';
8
+ import { FormattedMessage, useIntl } from 'react-intl-next';
9
+ import { getEmojiVariation } from '../../../api/EmojiRepository';
10
+ import { supportsUploadFeature } from '../../../api/EmojiResource';
11
+ import { KeyboardKeys, customCategory, defaultEmojiPickerSize, frequentCategory } from '../../../util/constants';
12
+ import { containsEmojiId, isPromise /*, isEmojiIdEqual, isEmojiLoaded*/, isEmojiDescription } from '../../../util/type-helpers';
13
+ import { SearchSort, SearchSourceTypes } from '../../../types';
14
+ import { getToneEmoji } from '../../../util/filters';
15
+ import { uploadEmoji } from '../../common/UploadEmoji';
16
+ import { createRecordSelectionDefault } from '../../common/RecordSelectionDefault';
17
+ import CategorySelector from './CategorySelector';
18
+ import EmojiPickerFooter from './EmojiPickerFooter';
19
+ import { EmojiPickerVirtualListInternalOld as EmojiPickerListOld, EmojiPickerVirtualListInternalNew as EmojiPickerListNew } from '../../picker/EmojiPickerList';
20
+ import { createAndFireEventInElementsChannel, categoryClickedEvent, closedPickerEvent, deleteBeginEvent, deleteCancelEvent, deleteConfirmEvent, openedPickerEvent, pickerClickedEvent, pickerSearchedEvent, selectedFileEvent, uploadBeginButton, uploadCancelButton, uploadConfirmButton, toneSelectorClosedEvent, ufoExperiences } from '../../../util/analytics';
21
+ import { useEmoji } from '../../../hooks/useEmoji';
22
+ import { useIsMounted } from '../../../hooks/useIsMounted';
23
+ import { messages } from '../../i18n';
24
+ import { fg } from '@atlaskit/platform-feature-flags';
25
+ const emojiPickerBoxShadow = "var(--ds-shadow-overlay, 0 3px 6px rgba(0, 0, 0, 0.2))";
26
+ const emojiPickerHeight = 295;
27
+ const emojiPickerHeightWithPreview = 349; // emojiPickerHeight + emojiPickerPreviewHeight;
28
+ const emojiPickerWidth = 350;
29
+ const emojiPickerMinHeight = 260;
30
+ const heightOffset = 80;
31
+ const emojiPicker = null;
32
+ const withPreviewHeight = {
33
+ small: "_4t3ivixp _1tkegx0z",
34
+ medium: "_4t3i2300 _1tke5x59",
35
+ large: "_4t3ixt2k _1tke1pna"
36
+ };
37
+ const withoutPreviewHeight = {
38
+ small: "_4t3iaq3k _1tkegx0z",
39
+ medium: "_4t3iixjv _1tke5x59",
40
+ large: "_4t3i1ckg _1tke1pna"
41
+ };
42
+ const FREQUENTLY_USED_MAX = 16;
43
+ const EmojiPickerComponent = ({
44
+ onSelection,
45
+ onPickerRef,
46
+ hideToneSelector,
47
+ createAnalyticsEvent,
48
+ size = defaultEmojiPickerSize
49
+ }) => {
50
+ const {
51
+ formatMessage
52
+ } = useIntl();
53
+ const {
54
+ emojiProvider,
55
+ isUploadSupported
56
+ } = useEmoji();
57
+ const [filteredEmojis, setFilteredEmojis] = useState([]);
58
+ const [searchEmojis, setSearchEmojis] = useState([]);
59
+ const [frequentlyUsedEmojis, setFrequentlyUsedEmojis] = useState([]);
60
+ const [query, setQuery] = useState('');
61
+ const [dynamicCategories, setDynamicCategories] = useState([]);
62
+ const [selectedTone, setSelectedTone] = useState(!hideToneSelector ? emojiProvider.getSelectedTone() : undefined);
63
+ const [loading, setLoading] = useState(true);
64
+ const [uploading, setUploading] = useState(false);
65
+ const [selectedEmoji, setSelectedEmoji] = useState();
66
+ const [activeCategory, setActiveCategory] = useState(null);
67
+ const [disableCategories, setDisableCategories] = useState(false);
68
+ const [uploadErrorMessage, setUploadErrorMessage] = useState();
69
+ const [emojiToDelete, setEmojiToDelete] = useState();
70
+ const [toneEmoji, setToneEmoji] = useState();
71
+ const emojiPickerList = useMemo(() => fg('platform_editor_react18_elements_emoji') ? /*#__PURE__*/createRef() : /*#__PURE__*/createRef(), []);
72
+ const openTime = useRef(0);
73
+ const isMounting = useRef(true);
74
+ const previousEmojiProvider = useRef(emojiProvider);
75
+ const currentUser = useMemo(() => {
76
+ return emojiProvider.getCurrentUser();
77
+ }, [emojiProvider]);
78
+ const isMounted = useIsMounted();
79
+ const fireAnalytics = useCallback(analyticsEvent => {
80
+ if (createAnalyticsEvent) {
81
+ createAndFireEventInElementsChannel(analyticsEvent)(createAnalyticsEvent);
82
+ }
83
+ }, [createAnalyticsEvent]);
84
+ const onEmojiActive = useCallback((emojiId, emoji) => {
85
+ if (!selectedEmoji || selectedEmoji.id !== (emojiId === null || emojiId === void 0 ? void 0 : emojiId.id)) {
86
+ setSelectedEmoji(emoji);
87
+ }
88
+ }, [selectedEmoji]);
89
+ const onCategoryActivated = useCallback(category => {
90
+ if (activeCategory !== category) {
91
+ setActiveCategory(category);
92
+ }
93
+ }, [activeCategory]);
94
+ const calculateElapsedTime = () => {
95
+ return Date.now() - openTime.current;
96
+ };
97
+ const onDynamicCategoryChange = useCallback(categories => {
98
+ setDynamicCategories(categories);
99
+ }, []);
100
+ const onUploadCancelled = useCallback(() => {
101
+ batchedUpdates(() => {
102
+ setUploading(false);
103
+ setUploadErrorMessage(undefined);
104
+ });
105
+ fireAnalytics(uploadCancelButton());
106
+ }, [fireAnalytics]);
107
+ const getDynamicCategories = useCallback(() => {
108
+ if (!emojiProvider.calculateDynamicCategories) {
109
+ return Promise.resolve([]);
110
+ }
111
+ return emojiProvider.calculateDynamicCategories();
112
+ }, [emojiProvider]);
113
+
114
+ /**
115
+ * Calculate and set the new state of the component in response to the list of emoji changing for some reason (a search has returned
116
+ * or the frequently used emoji have updated.)
117
+ */
118
+ const setStateAfterEmojiChange = useCallback(({
119
+ searchQuery,
120
+ emojiToRender,
121
+ searchEmoji,
122
+ frequentEmoji
123
+ }) => {
124
+ // Only enable categories for full emoji list (non-search)
125
+ const disableCategories = !!searchQuery;
126
+ if (!disableCategories && emojiToRender && emojiToRender.length !== filteredEmojis.length) {
127
+ getDynamicCategories().then(categories => {
128
+ onDynamicCategoryChange(categories);
129
+ });
130
+ }
131
+ if (emojiToRender && !containsEmojiId(emojiToRender, selectedEmoji)) {
132
+ batchedUpdates(() => {
133
+ setSelectedEmoji(undefined);
134
+ });
135
+ }
136
+ batchedUpdates(() => {
137
+ if (emojiToRender) {
138
+ setFilteredEmojis(emojiToRender);
139
+ }
140
+ if (searchEmoji) {
141
+ setSearchEmojis(searchEmoji);
142
+ }
143
+ if (frequentEmoji) {
144
+ setFrequentlyUsedEmojis(frequentEmoji);
145
+ }
146
+ setLoading(false);
147
+ setDisableCategories(disableCategories);
148
+ });
149
+ }, [filteredEmojis.length, getDynamicCategories, onDynamicCategoryChange, selectedEmoji]);
150
+ const onFrequentEmojiResult = useCallback(frequentEmoji => {
151
+ // change the category of each of the featured emoji
152
+ const recategorised = frequentEmoji.map(emoji => {
153
+ const clone = JSON.parse(JSON.stringify(emoji));
154
+ clone.category = frequentCategory;
155
+ return clone;
156
+ });
157
+ setStateAfterEmojiChange({
158
+ frequentEmoji: recategorised
159
+ });
160
+ }, [setStateAfterEmojiChange]);
161
+ const onSearchResult = useCallback(searchResults => {
162
+ const frequentlyUsedEmoji = frequentlyUsedEmojis || [];
163
+ const searchQuery = searchResults.query || '';
164
+
165
+ /**
166
+ * If there is no user search in the EmojiPicker then it should display all emoji received from the EmojiRepository and should
167
+ * also include a special category of most frequently used emoji (if there are any). This method decides if we are in this 'no search'
168
+ * state and appends the frequent emoji if necessary.
169
+ */
170
+ let emojiToRender;
171
+ if (!frequentlyUsedEmoji.length || query) {
172
+ emojiToRender = searchResults.emojis;
173
+ } else {
174
+ emojiToRender = [...searchResults.emojis, ...frequentlyUsedEmoji];
175
+ }
176
+ setStateAfterEmojiChange({
177
+ searchQuery,
178
+ emojiToRender,
179
+ searchEmoji: searchResults.emojis
180
+ });
181
+ fireAnalytics(pickerSearchedEvent({
182
+ queryLength: searchQuery.length,
183
+ numMatches: searchResults.emojis.length
184
+ }));
185
+ }, [frequentlyUsedEmojis, query, setStateAfterEmojiChange, fireAnalytics]);
186
+ const onProviderChange = useMemo(() => {
187
+ return {
188
+ result: onSearchResult
189
+ };
190
+ }, [onSearchResult]);
191
+
192
+ /**
193
+ * Updates the emoji displayed by the picker. If there is no query specified then we expect to retrieve all emoji for display,
194
+ * by category, in the picker. This differs from when there is a query in which case we expect to receive a sorted result matching
195
+ * the search.
196
+ */
197
+ const updateEmojis = useCallback((query, options) => {
198
+ // if the query is empty then we want the emoji to be in service defined order, unless specified otherwise
199
+ // and we want emoji for the 'frequently used' category to be refreshed as well.
200
+ if (!query) {
201
+ if (!options) {
202
+ options = {};
203
+ }
204
+ if (!options.sort) {
205
+ options.sort = SearchSort.None;
206
+ }
207
+
208
+ // take a copy of search options so that the frequently used can be limited to 16 without affecting the full emoji query
209
+ const frequentOptions = {
210
+ ...options,
211
+ sort: SearchSort.None,
212
+ limit: FREQUENTLY_USED_MAX
213
+ };
214
+ emojiProvider.getFrequentlyUsed(frequentOptions).then(onFrequentEmojiResult);
215
+ }
216
+ emojiProvider.filter(query, options);
217
+ }, [emojiProvider, onFrequentEmojiResult]);
218
+ const onToneSelected = useCallback(toneValue => {
219
+ emojiProvider.setSelectedTone(toneValue);
220
+ updateEmojis(query, {
221
+ skinTone: toneValue
222
+ });
223
+ setSelectedTone(toneValue);
224
+ }, [emojiProvider, query, updateEmojis]);
225
+ const onToneSelectorCancelled = useCallback(() => {
226
+ fireAnalytics(toneSelectorClosedEvent());
227
+ }, [fireAnalytics]);
228
+ const onSelectWrapper = useCallback((emojiId, emoji, event) => {
229
+ if (onSelection) {
230
+ onSelection(emojiId, emoji, event);
231
+ fireAnalytics(pickerClickedEvent({
232
+ duration: calculateElapsedTime(),
233
+ emojiId: (emojiId === null || emojiId === void 0 ? void 0 : emojiId.id) || '',
234
+ category: emoji && emoji.category || '',
235
+ type: emoji && emoji.type || '',
236
+ queryLength: query && query.length || 0
237
+ }));
238
+ }
239
+ }, [fireAnalytics, onSelection, query]);
240
+ const onCategorySelected = useCallback(categoryId => {
241
+ if (!categoryId) {
242
+ return;
243
+ }
244
+ emojiProvider.findInCategory(categoryId).then(emojisInCategory => {
245
+ if (!disableCategories) {
246
+ let newSelectedEmoji;
247
+ if (emojisInCategory && emojisInCategory.length > 0) {
248
+ newSelectedEmoji = getEmojiVariation(emojisInCategory[0], {
249
+ skinTone: selectedTone
250
+ });
251
+ }
252
+ if (emojiPickerList.current) {
253
+ emojiPickerList.current.reveal(categoryId);
254
+ }
255
+ batchedUpdates(() => {
256
+ setActiveCategory(categoryId);
257
+ setSelectedEmoji(newSelectedEmoji);
258
+ });
259
+ fireAnalytics(categoryClickedEvent({
260
+ category: categoryId
261
+ }));
262
+ }
263
+ });
264
+ }, [disableCategories, emojiPickerList, emojiProvider, fireAnalytics, selectedTone]);
265
+ const recordUsageOnSelection = useMemo(() => createRecordSelectionDefault(emojiProvider, onSelectWrapper, analytic => fireAnalytics(analytic(SearchSourceTypes.PICKER))), [emojiProvider, fireAnalytics, onSelectWrapper]);
266
+ const formattedErrorMessage = useMemo(() => uploadErrorMessage ? /*#__PURE__*/React.createElement(FormattedMessage, uploadErrorMessage) : null, [uploadErrorMessage]);
267
+ const onFileChooserClicked = useCallback(() => {
268
+ fireAnalytics(selectedFileEvent());
269
+ }, [fireAnalytics]);
270
+ const scrollToTopOfList = useCallback(() => {
271
+ var _emojiPickerList$curr;
272
+ (_emojiPickerList$curr = emojiPickerList.current) === null || _emojiPickerList$curr === void 0 ? void 0 : _emojiPickerList$curr.scrollToTop();
273
+ }, [emojiPickerList]);
274
+ const onSearch = useCallback(searchQuery => {
275
+ const options = {
276
+ skinTone: selectedTone,
277
+ source: SearchSourceTypes.PICKER
278
+ };
279
+ if (searchQuery !== query) {
280
+ setQuery(searchQuery);
281
+ }
282
+ updateEmojis(searchQuery, options);
283
+ if (filteredEmojis.length > 0) {
284
+ // scroll to top when search, which is search results section
285
+ scrollToTopOfList();
286
+ }
287
+ }, [query, filteredEmojis, selectedTone, updateEmojis, scrollToTopOfList]);
288
+ const onOpenUpload = useCallback(() => {
289
+ // Prime upload token so it's ready when the user adds
290
+ if (supportsUploadFeature(emojiProvider)) {
291
+ emojiProvider.prepareForUpload();
292
+ }
293
+ batchedUpdates(() => {
294
+ setUploadErrorMessage(undefined);
295
+ setUploading(true);
296
+ });
297
+ fireAnalytics(uploadBeginButton());
298
+ }, [emojiProvider, fireAnalytics]);
299
+ const scrollToUploadedEmoji = useCallback(emojiDescription => {
300
+ if (emojiPickerList.current) {
301
+ // Wait a tick to ensure repaint and updated height for picker list
302
+ window.setTimeout(() => {
303
+ var _emojiPickerList$curr2;
304
+ (_emojiPickerList$curr2 = emojiPickerList.current) === null || _emojiPickerList$curr2 === void 0 ? void 0 : _emojiPickerList$curr2.scrollToRecentlyUploaded(emojiDescription);
305
+ }, 0);
306
+ }
307
+ }, [emojiPickerList]);
308
+ const onUploadEmoji = useCallback((upload, retry) => {
309
+ fireAnalytics(uploadConfirmButton({
310
+ retry
311
+ }));
312
+ const errorSetter = message => {
313
+ setUploadErrorMessage(message);
314
+ };
315
+ const onSuccess = emojiDescription => {
316
+ batchedUpdates(() => {
317
+ setActiveCategory(customCategory);
318
+ setSelectedEmoji(emojiDescription);
319
+ setUploading(false);
320
+ });
321
+ scrollToUploadedEmoji(emojiDescription);
322
+ };
323
+ uploadEmoji(upload, emojiProvider, errorSetter, onSuccess, fireAnalytics, retry);
324
+ }, [emojiProvider, fireAnalytics, scrollToUploadedEmoji]);
325
+ const onTriggerDelete = useCallback((_emojiId, emoji) => {
326
+ if (_emojiId) {
327
+ fireAnalytics(deleteBeginEvent({
328
+ emojiId: _emojiId.id
329
+ }));
330
+ setEmojiToDelete(emoji);
331
+ }
332
+ }, [fireAnalytics]);
333
+ const onCloseDelete = useCallback(() => {
334
+ fireAnalytics(deleteCancelEvent({
335
+ emojiId: emojiToDelete && emojiToDelete.id
336
+ }));
337
+ setEmojiToDelete(undefined);
338
+ }, [emojiToDelete, fireAnalytics]);
339
+ const onDeleteEmoji = useCallback(emoji => {
340
+ fireAnalytics(deleteConfirmEvent({
341
+ emojiId: emojiToDelete && emojiToDelete.id
342
+ }));
343
+ return emojiProvider.deleteSiteEmoji(emoji).then(success => {
344
+ if (success) {
345
+ updateEmojis(query, {
346
+ skinTone: selectedTone
347
+ });
348
+ }
349
+ return success;
350
+ });
351
+ }, [emojiProvider, emojiToDelete, fireAnalytics, query, selectedTone, updateEmojis]);
352
+ const onComponentDidMount = useCallback(() => {
353
+ emojiProvider.subscribe(onProviderChange);
354
+ onSearch(query);
355
+ if (!hideToneSelector) {
356
+ const toneEmoji = getToneEmoji(emojiProvider);
357
+ if (isPromise(toneEmoji)) {
358
+ toneEmoji.then(emoji => setToneEmoji(emoji));
359
+ } else if (toneEmoji === undefined || isEmojiDescription(toneEmoji)) {
360
+ setToneEmoji(toneEmoji);
361
+ }
362
+ }
363
+ }, [emojiProvider, hideToneSelector, onProviderChange, onSearch, query]);
364
+ if (isMounting.current) {
365
+ // componentWillMount equivalent
366
+ ufoExperiences['emoji-picker-opened'].success();
367
+ openTime.current = Date.now();
368
+ fireAnalytics(openedPickerEvent());
369
+ isMounting.current = false;
370
+ }
371
+
372
+ // stop all key propagation to other event listeners
373
+ const suppressKeyPress = e => {
374
+ e.stopPropagation();
375
+ // We prevent default for enter keypresses
376
+ // since products like Bitbucket might have parent forms
377
+ // that listen for keydown events to trigger form submission
378
+ // https://product-fabric.atlassian.net/browse/ED-19532
379
+ if (e.key === KeyboardKeys.Enter) {
380
+ e.preventDefault();
381
+ }
382
+ };
383
+ useEffect(() => {
384
+ // componentDidMount logic
385
+ if (!isMounted) {
386
+ onComponentDidMount();
387
+ }
388
+ }, [onComponentDidMount, isMounted]);
389
+ useEffect(() => {
390
+ previousEmojiProvider.current.unsubscribe(onProviderChange);
391
+ previousEmojiProvider.current = emojiProvider;
392
+ emojiProvider.subscribe(onProviderChange);
393
+ return () => {
394
+ emojiProvider.unsubscribe(onProviderChange);
395
+ };
396
+ }, [emojiProvider, onProviderChange]);
397
+ useEffect(() => {
398
+ if (!frequentlyUsedEmojis.length || query) {
399
+ setFilteredEmojis(searchEmojis);
400
+ } else {
401
+ setFilteredEmojis([...searchEmojis, ...frequentlyUsedEmojis]);
402
+ }
403
+ }, [frequentlyUsedEmojis, query, searchEmojis]);
404
+ useEffect(() => {
405
+ // Fire analytics on component unmount
406
+ return () => {
407
+ fireAnalytics(closedPickerEvent({
408
+ duration: calculateElapsedTime()
409
+ }));
410
+ ufoExperiences['emoji-picker-opened'].abort({
411
+ metadata: {
412
+ source: 'EmojiPickerComponent',
413
+ reason: 'unmount'
414
+ }
415
+ });
416
+ ufoExperiences['emoji-searched'].abort({
417
+ metadata: {
418
+ source: 'EmojiPickerComponent',
419
+ reason: 'unmount'
420
+ }
421
+ });
422
+ };
423
+ }, [fireAnalytics]);
424
+ useEffect(() => {
425
+ // Unsubscribe emojiProvider on component unmount
426
+ return () => {
427
+ emojiProvider.unsubscribe(onProviderChange);
428
+ };
429
+ }, [emojiProvider, onProviderChange]);
430
+ const showPreview = selectedEmoji && !uploading;
431
+ return /*#__PURE__*/React.createElement("div", {
432
+ ref: onPickerRef,
433
+ "data-emoji-picker-container": true,
434
+ role: "dialog",
435
+ "aria-label": formatMessage(messages.emojiPickerTitle),
436
+ "aria-modal": true,
437
+ onKeyPress: suppressKeyPress,
438
+ onKeyUp: suppressKeyPress,
439
+ onKeyDown: suppressKeyPress,
440
+ className: ax(["_19itcyqh _2rkosqtm _1e0c1txw _2lx21bp4 _1bah1yb4 _bfhk1bhr _16qsp2xt _4t3iaq3k _1bsb1edt _1ul91edt _c71l1y6z", showPreview && withPreviewHeight[size], !showPreview && withoutPreviewHeight[size]])
441
+ }, /*#__PURE__*/React.createElement(CategorySelector, {
442
+ activeCategoryId: activeCategory,
443
+ dynamicCategories: dynamicCategories,
444
+ disableCategories: disableCategories,
445
+ onCategorySelected: onCategorySelected
446
+ }), fg('platform_editor_react18_elements_emoji') ? /*#__PURE__*/React.createElement(EmojiPickerListNew, {
447
+ emojis: filteredEmojis,
448
+ currentUser: currentUser,
449
+ onEmojiSelected: recordUsageOnSelection,
450
+ onEmojiActive: onEmojiActive,
451
+ onEmojiDelete: onTriggerDelete,
452
+ onCategoryActivated: onCategoryActivated,
453
+ onSearch: onSearch,
454
+ query: query,
455
+ selectedTone: selectedTone,
456
+ loading: loading,
457
+ ref: emojiPickerList,
458
+ initialUploadName: query,
459
+ onToneSelected: onToneSelected,
460
+ onToneSelectorCancelled: onToneSelectorCancelled,
461
+ toneEmoji: toneEmoji,
462
+ uploading: uploading,
463
+ emojiToDelete: emojiToDelete,
464
+ uploadErrorMessage: formattedErrorMessage,
465
+ uploadEnabled: isUploadSupported && !uploading,
466
+ onUploadEmoji: onUploadEmoji,
467
+ onUploadCancelled: onUploadCancelled,
468
+ onDeleteEmoji: onDeleteEmoji,
469
+ onCloseDelete: onCloseDelete,
470
+ onFileChooserClicked: onFileChooserClicked,
471
+ onOpenUpload: onOpenUpload,
472
+ size: size,
473
+ activeCategoryId: activeCategory
474
+ }) : /*#__PURE__*/React.createElement(EmojiPickerListOld, {
475
+ emojis: filteredEmojis,
476
+ currentUser: currentUser,
477
+ onEmojiSelected: recordUsageOnSelection,
478
+ onEmojiActive: onEmojiActive,
479
+ onEmojiDelete: onTriggerDelete,
480
+ onCategoryActivated: onCategoryActivated,
481
+ onSearch: onSearch,
482
+ query: query,
483
+ selectedTone: selectedTone,
484
+ loading: loading,
485
+ ref: emojiPickerList,
486
+ initialUploadName: query,
487
+ onToneSelected: onToneSelected,
488
+ onToneSelectorCancelled: onToneSelectorCancelled,
489
+ toneEmoji: toneEmoji,
490
+ uploading: uploading,
491
+ emojiToDelete: emojiToDelete,
492
+ uploadErrorMessage: formattedErrorMessage,
493
+ uploadEnabled: isUploadSupported && !uploading,
494
+ onUploadEmoji: onUploadEmoji,
495
+ onUploadCancelled: onUploadCancelled,
496
+ onDeleteEmoji: onDeleteEmoji,
497
+ onCloseDelete: onCloseDelete,
498
+ onFileChooserClicked: onFileChooserClicked,
499
+ onOpenUpload: onOpenUpload,
500
+ size: size,
501
+ activeCategoryId: activeCategory
502
+ }), showPreview && /*#__PURE__*/React.createElement(EmojiPickerFooter, {
503
+ selectedEmoji: selectedEmoji
504
+ }));
505
+ };
506
+ export default /*#__PURE__*/memo(EmojiPickerComponent);
@@ -0,0 +1,35 @@
1
+
2
+ ._1wcg14y2 .emoji-common-node{border-radius:5px}._115ch2mm .emoji-common-node>img{position:relative}
3
+ ._1678tlke .emoji-common-node{cursor:pointer}
4
+ ._17dz1tcg .emoji-common-node>img{max-width:24px}
5
+ ._18u0u2gc{margin-left:var(--ds-space-100,8px)}
6
+ ._18x3u2gc .emoji-common-placeholder{margin-right:var(--ds-space-100,8px)}
7
+ ._1909ze3t .emoji-common-placeholder{padding-right:var(--ds-space-0,0)}
8
+ ._1bsb1ylp{width:40px}
9
+ ._1cf71tcg .emoji-common-node{height:24px}
10
+ ._1e0c1o8l{display:inline-block}
11
+ ._1k8z1tcg .emoji-common-node>img{max-height:24px}
12
+ ._1lvc1tcg .emoji-common-node{width:24px}
13
+ ._1mc3ze3t .emoji-common-node .emoji-common-placeholder{margin-left:var(--ds-space-0,0)}
14
+ ._1mn81tcg .emoji-common-node>.emoji-common-emoji-sprite{height:24px}
15
+ ._1rf4u2gc .emoji-common-node{padding-right:var(--ds-space-100,8px)}
16
+ ._1tcfze3t .emoji-common-placeholder{padding-bottom:var(--ds-space-0,0)}
17
+ ._29jju2gc .emoji-common-placeholder{margin-left:var(--ds-space-100,8px)}
18
+ ._4ubfu2gc .emoji-common-placeholder{margin-top:var(--ds-space-100,8px)}
19
+ ._5mfndbra .emoji-common-node>img{transform:translateX(-50%) translateY(-50%)}
20
+ ._7b50u2gc .emoji-common-node{padding-top:var(--ds-space-100,8px)}
21
+ ._85ft1ssb .emoji-common-node>img{top:50%}
22
+ ._8vlfze3t .emoji-common-placeholder{padding-top:var(--ds-space-0,0)}
23
+ ._b4kiu2gc .emoji-common-node{padding-bottom:var(--ds-space-100,8px)}
24
+ ._bm9mu2gc .emoji-common-node{padding-left:var(--ds-space-100,8px)}
25
+ ._elsp1tcg .emoji-common-placeholder{max-width:24px}
26
+ ._fw9su2gc .emoji-common-placeholder{margin-bottom:var(--ds-space-100,8px)}
27
+ ._n7xcze3t .emoji-common-placeholder{padding-left:var(--ds-space-0,0)}
28
+ ._o5kcze3t .emoji-common-node .emoji-common-placeholder{margin-bottom:var(--ds-space-0,0)}
29
+ ._qpkw1tcg .emoji-common-placeholder{min-width:24px}
30
+ ._u5ah1tcg .emoji-common-node>.emoji-common-emoji-sprite{width:24px}
31
+ ._vtzrze3t .emoji-common-node .emoji-common-placeholder{margin-top:var(--ds-space-0,0)}
32
+ ._w2q0ze3t .emoji-common-node .emoji-common-placeholder{margin-right:var(--ds-space-0,0)}
33
+ ._y3gn1h6o{text-align:center}
34
+ ._yrst1ssb .emoji-common-node>img{left:50%}
35
+ ._zdyf1ule .emoji-common-node>img{display:block}
@@ -0,0 +1,69 @@
1
+ /* EmojiPickerEmojiRow.tsx generated by @compiled/babel-plugin v0.36.1 */
2
+ import "./EmojiPickerEmojiRow.compiled.css";
3
+ import * as React from 'react';
4
+ import { ax, ix } from "@compiled/react/runtime";
5
+ import { memo } from 'react';
6
+ import { useIntl } from 'react-intl-next';
7
+ import CachingEmoji from '../../common/CachingEmoji';
8
+ import { useEmojiPickerListContext } from '../../../hooks/useEmojiPickerListContext';
9
+ import { messages } from '../../i18n';
10
+ const emojiItem = null;
11
+ const emojiPickerRow = null;
12
+ const EmojiPickerEmojiRow = ({
13
+ emojis,
14
+ onSelected,
15
+ onMouseMove,
16
+ onFocus,
17
+ title,
18
+ showDelete,
19
+ onDelete,
20
+ virtualItemContext
21
+ }) => {
22
+ const {
23
+ currentEmojisFocus,
24
+ setEmojisFocus
25
+ } = useEmojiPickerListContext();
26
+ const rowIndex = (virtualItemContext === null || virtualItemContext === void 0 ? void 0 : virtualItemContext.index) || 0;
27
+ const {
28
+ formatMessage
29
+ } = useIntl();
30
+ const handleFocus = index => (emojiId, emoji, event) => {
31
+ setEmojisFocus({
32
+ rowIndex,
33
+ columnIndex: index
34
+ });
35
+ onFocus && onFocus(emojiId, emoji, event);
36
+ };
37
+ return /*#__PURE__*/React.createElement("div", {
38
+ role: "presentation",
39
+ className: ax(["_18u0u2gc"])
40
+ }, emojis.map((emoji, index) => {
41
+ const {
42
+ shortName,
43
+ id
44
+ } = emoji;
45
+ const key = id ? `${id}-${title}` : `${shortName}-${title}`;
46
+ const focus = currentEmojisFocus.rowIndex === rowIndex && currentEmojisFocus.columnIndex === index;
47
+ return /*#__PURE__*/React.createElement("span", {
48
+ key: key,
49
+ role: "gridcell",
50
+ "aria-colindex": index + 1 // aria-colindex is 1 based
51
+ ,
52
+ className: ax(["_1e0c1o8l _y3gn1h6o _1bsb1ylp _1wcg14y2 _1678tlke _7b50u2gc _1rf4u2gc _b4kiu2gc _bm9mu2gc _1lvc1tcg _1cf71tcg _8vlfze3t _1909ze3t _1tcfze3t _n7xcze3t _4ubfu2gc _18x3u2gc _fw9su2gc _29jju2gc _qpkw1tcg _elsp1tcg _vtzrze3t _w2q0ze3t _o5kcze3t _1mc3ze3t _115ch2mm _yrst1ssb _85ft1ssb _5mfndbra _1k8z1tcg _17dz1tcg _zdyf1ule _1mn81tcg _u5ah1tcg"])
53
+ }, /*#__PURE__*/React.createElement(CachingEmoji, {
54
+ emoji: emoji,
55
+ selectOnHover: true,
56
+ onSelected: onSelected,
57
+ onMouseMove: onMouseMove,
58
+ onFocus: handleFocus(index),
59
+ showDelete: showDelete,
60
+ onDelete: onDelete,
61
+ placeholderSize: 24,
62
+ "data-focus-index": `${rowIndex}-${index}`,
63
+ tabIndex: focus ? 0 : -1,
64
+ "aria-roledescription": formatMessage(messages.emojiButtonRoleDescription),
65
+ shouldBeInteractive: true
66
+ }));
67
+ }));
68
+ };
69
+ export default /*#__PURE__*/memo(EmojiPickerEmojiRow);
@@ -0,0 +1,5 @@
1
+
2
+ ._x3do1kuc{border-top:2px solid var(--ds-border,rgba(9,30,66,.08))}._16jlidpf{flex-grow:0}
3
+ ._16qs2hsd{box-shadow:0 -1px 1px 0 var(--ds-border,rgba(0,0,0,.1))}
4
+ ._1o9zidpf{flex-shrink:0}
5
+ ._i0dl1wug{flex-basis:auto}
@@ -0,0 +1,19 @@
1
+ /* EmojiPickerFooter.tsx generated by @compiled/babel-plugin v0.36.1 */
2
+ import "./EmojiPickerFooter.compiled.css";
3
+ import * as React from 'react';
4
+ import { ax, ix } from "@compiled/react/runtime";
5
+ import { memo } from 'react';
6
+ import { N30A } from '@atlaskit/theme/colors';
7
+ import { EmojiPreviewComponent } from '../common/EmojiPreviewComponent';
8
+ const emojiPickerFooter = null;
9
+ const emojiPickerFooterWithTopShadow = null;
10
+ export const emojiPickerFooterTestId = 'emoji-picker-footer';
11
+ const EmojiPickerFooter = ({
12
+ selectedEmoji
13
+ }) => /*#__PURE__*/React.createElement("div", {
14
+ "data-testid": emojiPickerFooterTestId,
15
+ className: ax(["_16jlidpf _1o9zidpf _i0dl1wug", "_x3do1kuc _16qs2hsd"])
16
+ }, selectedEmoji && /*#__PURE__*/React.createElement(EmojiPreviewComponent, {
17
+ emoji: selectedEmoji
18
+ }));
19
+ export default /*#__PURE__*/memo(EmojiPickerFooter);
@@ -0,0 +1,23 @@
1
+ ._11c82smr{font:var(--ds-font-body,normal 400 14px/20px ui-sans-serif,-apple-system,BlinkMacSystemFont,"Segoe UI",Ubuntu,"Helvetica Neue",sans-serif)}
2
+ ._12ji1r31{outline-color:currentColor}
3
+ ._12y31o36{outline-width:medium}
4
+ ._13xeglyw:invalid{box-shadow:none}
5
+ ._18u01i6y{margin-left:var(--ds-space-negative-025,-2px)}
6
+ ._19bvutpp{padding-left:var(--ds-space-150,9pt)}
7
+ ._1bsb1osq{width:100%}
8
+ ._1e0cglyw{display:none}
9
+ ._1goxglyw::-ms-clear{display:none}
10
+ ._1q51t94y{padding-block-start:1px}
11
+ ._1qu2glyw{outline-style:none}
12
+ ._3um015vq{visibility:hidden}
13
+ ._80om1kw7{cursor:inherit}
14
+ ._85i5v77o{padding-block-end:var(--ds-space-025,2px)}
15
+ ._bozg12x7{padding-inline-start:var(--ds-space-075,6px)}
16
+ ._ca0qutpp{padding-top:var(--ds-space-150,9pt)}
17
+ ._n3tdutpp{padding-bottom:var(--ds-space-150,9pt)}
18
+ ._syaz1kw7{color:inherit}
19
+ ._tzy4105o{opacity:.5}
20
+ ._tzy4idpf{opacity:0}
21
+ ._u5f3utpp{padding-right:var(--ds-space-150,9pt)}
22
+ ._vchhusvi{box-sizing:border-box}
23
+ ._y4tize3t{padding-inline-end:var(--ds-space-0,0)}