@atlaskit/emoji 65.1.1 → 65.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.
Files changed (95) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/cjs/components/common/CachingEmoji.js +84 -151
  3. package/dist/cjs/components/common/Emoji.js +2 -2
  4. package/dist/cjs/components/common/EmojiActions.js +129 -175
  5. package/dist/cjs/components/common/EmojiErrorMessage.js +23 -59
  6. package/dist/cjs/components/common/EmojiPreviewComponent.js +1 -0
  7. package/dist/cjs/components/common/EmojiUploadPicker.js +235 -293
  8. package/dist/cjs/components/common/FileChooser.js +34 -71
  9. package/dist/cjs/components/common/Popup.js +105 -154
  10. package/dist/cjs/components/common/RetryableButton.js +43 -64
  11. package/dist/cjs/components/common/ToneSelector.js +50 -89
  12. package/dist/cjs/components/common/styles.js +14 -16
  13. package/dist/cjs/components/hooks.js +16 -0
  14. package/dist/cjs/components/picker/EmojiPickerCategoryHeading.js +16 -48
  15. package/dist/cjs/components/picker/EmojiPickerComponent.js +496 -516
  16. package/dist/cjs/components/picker/EmojiPickerEmojiRow.js +33 -60
  17. package/dist/cjs/components/picker/EmojiPickerFooter.js +13 -48
  18. package/dist/cjs/components/uploader/EmojiUploadComponent.js +124 -109
  19. package/dist/cjs/hooks/useEmojiContext.js +16 -0
  20. package/dist/cjs/hooks/{index.js → usePrevious.js} +0 -0
  21. package/dist/cjs/index.js +16 -0
  22. package/dist/cjs/version.json +1 -1
  23. package/dist/es2019/components/common/CachingEmoji.js +65 -112
  24. package/dist/es2019/components/common/Emoji.js +2 -2
  25. package/dist/es2019/components/common/EmojiActions.js +124 -150
  26. package/dist/es2019/components/common/EmojiErrorMessage.js +22 -26
  27. package/dist/es2019/components/common/EmojiPreviewComponent.js +1 -0
  28. package/dist/es2019/components/common/EmojiUploadPicker.js +190 -253
  29. package/dist/es2019/components/common/FileChooser.js +37 -40
  30. package/dist/es2019/components/common/Popup.js +89 -109
  31. package/dist/es2019/components/common/RetryableButton.js +43 -34
  32. package/dist/es2019/components/common/ToneSelector.js +46 -59
  33. package/dist/es2019/components/common/styles.js +9 -9
  34. package/dist/es2019/components/hooks.js +8 -0
  35. package/dist/es2019/components/picker/EmojiPickerCategoryHeading.js +13 -17
  36. package/dist/es2019/components/picker/EmojiPickerComponent.js +417 -506
  37. package/dist/es2019/components/picker/EmojiPickerEmojiRow.js +32 -35
  38. package/dist/es2019/components/picker/EmojiPickerFooter.js +11 -21
  39. package/dist/es2019/components/uploader/EmojiUploadComponent.js +81 -91
  40. package/dist/es2019/hooks/useEmojiContext.js +3 -0
  41. package/dist/es2019/hooks/{index.js → usePrevious.js} +0 -0
  42. package/dist/es2019/index.js +4 -1
  43. package/dist/es2019/version.json +1 -1
  44. package/dist/esm/components/common/CachingEmoji.js +86 -156
  45. package/dist/esm/components/common/Emoji.js +2 -2
  46. package/dist/esm/components/common/EmojiActions.js +129 -176
  47. package/dist/esm/components/common/EmojiErrorMessage.js +21 -56
  48. package/dist/esm/components/common/EmojiPreviewComponent.js +1 -0
  49. package/dist/esm/components/common/EmojiUploadPicker.js +233 -299
  50. package/dist/esm/components/common/FileChooser.js +34 -70
  51. package/dist/esm/components/common/Popup.js +104 -155
  52. package/dist/esm/components/common/RetryableButton.js +40 -60
  53. package/dist/esm/components/common/ToneSelector.js +50 -87
  54. package/dist/esm/components/common/styles.js +10 -10
  55. package/dist/esm/components/hooks.js +8 -0
  56. package/dist/esm/components/picker/EmojiPickerCategoryHeading.js +14 -43
  57. package/dist/esm/components/picker/EmojiPickerComponent.js +486 -535
  58. package/dist/esm/components/picker/EmojiPickerEmojiRow.js +31 -59
  59. package/dist/esm/components/picker/EmojiPickerFooter.js +14 -49
  60. package/dist/esm/components/uploader/EmojiUploadComponent.js +119 -113
  61. package/dist/esm/hooks/useEmojiContext.js +5 -0
  62. package/dist/esm/hooks/{index.js → usePrevious.js} +0 -0
  63. package/dist/esm/index.js +4 -1
  64. package/dist/esm/version.json +1 -1
  65. package/dist/types/components/common/CachingEmoji.d.ts +3 -13
  66. package/dist/types/components/common/Emoji.d.ts +1 -1
  67. package/dist/types/components/common/EmojiActions.d.ts +6 -17
  68. package/dist/types/components/common/EmojiErrorMessage.d.ts +3 -6
  69. package/dist/types/components/common/EmojiPreviewComponent.d.ts +2 -2
  70. package/dist/types/components/common/EmojiUploadPicker.d.ts +3 -27
  71. package/dist/types/components/common/FileChooser.d.ts +3 -5
  72. package/dist/types/components/common/Popup.d.ts +3 -20
  73. package/dist/types/components/common/RetryableButton.d.ts +3 -7
  74. package/dist/types/components/common/ToneSelector.d.ts +4 -10
  75. package/dist/types/components/common/setSkinToneAriaLabelText.d.ts +1 -1
  76. package/dist/types/components/common/styles.d.ts +1 -3
  77. package/dist/types/components/hooks.d.ts +1 -0
  78. package/dist/types/components/picker/CategorySelector.d.ts +1 -1
  79. package/dist/types/components/picker/EmojiPicker.d.ts +3 -3
  80. package/dist/types/components/picker/EmojiPickerCategoryHeading.d.ts +3 -4
  81. package/dist/types/components/picker/EmojiPickerComponent.d.ts +4 -80
  82. package/dist/types/components/picker/EmojiPickerEmojiRow.d.ts +3 -4
  83. package/dist/types/components/picker/EmojiPickerFooter.d.ts +3 -6
  84. package/dist/types/components/uploader/EmojiUploadComponent.d.ts +3 -17
  85. package/dist/types/components/uploader/EmojiUploader.d.ts +5 -7
  86. package/dist/types/hooks/useEmojiContext.d.ts +1 -0
  87. package/dist/types/hooks/{index.d.ts → usePrevious.d.ts} +0 -0
  88. package/dist/types/index.d.ts +3 -1
  89. package/dist/types/types.d.ts +2 -1
  90. package/local-config-example.ts +3 -1
  91. package/package.json +17 -4
  92. package/dist/cjs/components/common/EmojiPreview.js +0 -194
  93. package/dist/es2019/components/common/EmojiPreview.js +0 -152
  94. package/dist/esm/components/common/EmojiPreview.js +0 -170
  95. package/dist/types/components/common/EmojiPreview.d.ts +0 -31
@@ -7,26 +7,18 @@ Object.defineProperty(exports, "__esModule", {
7
7
  });
8
8
  exports.default = void 0;
9
9
 
10
- var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
11
-
12
- var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
13
-
14
- var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
15
-
16
- var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized"));
17
-
18
- var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
19
-
20
- var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));
10
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
21
11
 
22
- var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));
12
+ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
23
13
 
24
- var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
14
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
25
15
 
26
16
  var _core = require("@emotion/core");
27
17
 
28
18
  var _react = require("react");
29
19
 
20
+ var _reactDom = require("react-dom");
21
+
30
22
  var _reactIntlNext = require("react-intl-next");
31
23
 
32
24
  var _EmojiRepository = require("../../api/EmojiRepository");
@@ -57,387 +49,505 @@ var _styles = require("./styles");
57
49
 
58
50
  var _LegacyEmojiContextProvider = _interopRequireDefault(require("../../context/LegacyEmojiContextProvider"));
59
51
 
52
+ var _hooks = require("../hooks");
53
+
60
54
  function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
61
55
 
62
56
  function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
63
57
 
64
- function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = (0, _getPrototypeOf2.default)(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = (0, _getPrototypeOf2.default)(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return (0, _possibleConstructorReturn2.default)(this, result); }; }
65
-
66
- function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
67
-
68
58
  var FREQUENTLY_USED_MAX = 16;
69
59
 
70
- var EmojiPickerComponent = /*#__PURE__*/function (_PureComponent) {
71
- (0, _inherits2.default)(EmojiPickerComponent, _PureComponent);
72
-
73
- var _super = _createSuper(EmojiPickerComponent);
74
-
75
- function EmojiPickerComponent(props) {
76
- var _this;
77
-
78
- (0, _classCallCheck2.default)(this, EmojiPickerComponent);
79
- _this = _super.call(this, props);
80
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "onEmojiActive", function (_emojiId, emoji) {
81
- if (_this.state.selectedEmoji !== emoji) {
82
- _this.setState({
83
- selectedEmoji: emoji
84
- });
85
- }
86
- });
87
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "onCategoryActivated", function (category) {
88
- if (_this.state.activeCategory !== category) {
89
- _this.setState({
90
- activeCategory: category
91
- });
92
- }
60
+ var EmojiPickerComponent = function EmojiPickerComponent(_ref) {
61
+ var emojiProvider = _ref.emojiProvider,
62
+ onSelection = _ref.onSelection,
63
+ onPickerRef = _ref.onPickerRef,
64
+ hideToneSelector = _ref.hideToneSelector,
65
+ createAnalyticsEvent = _ref.createAnalyticsEvent;
66
+
67
+ var _useState = (0, _react.useState)([]),
68
+ _useState2 = (0, _slicedToArray2.default)(_useState, 2),
69
+ filteredEmojis = _useState2[0],
70
+ setFilteredEmojis = _useState2[1];
71
+
72
+ var _useState3 = (0, _react.useState)([]),
73
+ _useState4 = (0, _slicedToArray2.default)(_useState3, 2),
74
+ searchEmojis = _useState4[0],
75
+ setSearchEmojis = _useState4[1];
76
+
77
+ var _useState5 = (0, _react.useState)([]),
78
+ _useState6 = (0, _slicedToArray2.default)(_useState5, 2),
79
+ frequentlyUsedEmojis = _useState6[0],
80
+ setFrequentlyUsedEmojis = _useState6[1];
81
+
82
+ var _useState7 = (0, _react.useState)(''),
83
+ _useState8 = (0, _slicedToArray2.default)(_useState7, 2),
84
+ query = _useState8[0],
85
+ setQuery = _useState8[1];
86
+
87
+ var _useState9 = (0, _react.useState)([]),
88
+ _useState10 = (0, _slicedToArray2.default)(_useState9, 2),
89
+ dynamicCategories = _useState10[0],
90
+ setDynamicCategories = _useState10[1];
91
+
92
+ var _useState11 = (0, _react.useState)(!hideToneSelector ? emojiProvider.getSelectedTone() : undefined),
93
+ _useState12 = (0, _slicedToArray2.default)(_useState11, 2),
94
+ selectedTone = _useState12[0],
95
+ setSelectedTone = _useState12[1];
96
+
97
+ var _useState13 = (0, _react.useState)(true),
98
+ _useState14 = (0, _slicedToArray2.default)(_useState13, 2),
99
+ loading = _useState14[0],
100
+ setLoading = _useState14[1];
101
+
102
+ var _useState15 = (0, _react.useState)(false),
103
+ _useState16 = (0, _slicedToArray2.default)(_useState15, 2),
104
+ uploadSupported = _useState16[0],
105
+ setUploadSupported = _useState16[1];
106
+
107
+ var _useState17 = (0, _react.useState)(false),
108
+ _useState18 = (0, _slicedToArray2.default)(_useState17, 2),
109
+ uploading = _useState18[0],
110
+ setUploading = _useState18[1];
111
+
112
+ var _useState19 = (0, _react.useState)(),
113
+ _useState20 = (0, _slicedToArray2.default)(_useState19, 2),
114
+ selectedEmoji = _useState20[0],
115
+ setSelectedEmoji = _useState20[1];
116
+
117
+ var _useState21 = (0, _react.useState)(null),
118
+ _useState22 = (0, _slicedToArray2.default)(_useState21, 2),
119
+ activeCategory = _useState22[0],
120
+ setActiveCategory = _useState22[1];
121
+
122
+ var _useState23 = (0, _react.useState)(false),
123
+ _useState24 = (0, _slicedToArray2.default)(_useState23, 2),
124
+ disableCategories = _useState24[0],
125
+ setDisableCategories = _useState24[1];
126
+
127
+ var _useState25 = (0, _react.useState)(),
128
+ _useState26 = (0, _slicedToArray2.default)(_useState25, 2),
129
+ uploadErrorMessage = _useState26[0],
130
+ setUploadErrorMessage = _useState26[1];
131
+
132
+ var _useState27 = (0, _react.useState)(),
133
+ _useState28 = (0, _slicedToArray2.default)(_useState27, 2),
134
+ emojiToDelete = _useState28[0],
135
+ setEmojiToDelete = _useState28[1];
136
+
137
+ var _useState29 = (0, _react.useState)(),
138
+ _useState30 = (0, _slicedToArray2.default)(_useState29, 2),
139
+ toneEmoji = _useState30[0],
140
+ setToneEmoji = _useState30[1];
141
+
142
+ var emojiPickerList = (0, _react.useMemo)(function () {
143
+ return /*#__PURE__*/(0, _react.createRef)();
144
+ }, []);
145
+ var openTime = (0, _react.useRef)(0);
146
+ var isMounting = (0, _react.useRef)(true);
147
+ var didMount = (0, _hooks.useDidMount)();
148
+ var updateAfterDidMount = (0, _react.useRef)(true);
149
+ var previousEmojiProvider = (0, _react.useRef)(emojiProvider);
150
+ var currentUser = (0, _react.useMemo)(function () {
151
+ return emojiProvider.getCurrentUser();
152
+ }, [emojiProvider]);
153
+ var fireAnalytics = (0, _react.useCallback)(function (analyticsEvent) {
154
+ if (createAnalyticsEvent) {
155
+ (0, _analytics.createAndFireEventInElementsChannel)(analyticsEvent)(createAnalyticsEvent);
156
+ }
157
+ }, [createAnalyticsEvent]);
158
+ var onEmojiActive = (0, _react.useCallback)(function (emojiId, emoji) {
159
+ if (!selectedEmoji || selectedEmoji.id !== (emojiId === null || emojiId === void 0 ? void 0 : emojiId.id)) {
160
+ setSelectedEmoji(emoji);
161
+ }
162
+ }, [selectedEmoji]);
163
+ var onCategoryActivated = (0, _react.useCallback)(function (category) {
164
+ if (activeCategory !== category) {
165
+ setActiveCategory(category);
166
+ }
167
+ }, [activeCategory]);
168
+
169
+ var calculateElapsedTime = function calculateElapsedTime() {
170
+ return Date.now() - openTime.current;
171
+ };
172
+
173
+ var onUploadSupported = (0, _react.useCallback)(function (supported) {
174
+ setUploadSupported(supported);
175
+ }, []);
176
+ var onDynamicCategoryChange = (0, _react.useCallback)(function (categories) {
177
+ setDynamicCategories(categories);
178
+ }, []);
179
+ var onUploadCancelled = (0, _react.useCallback)(function () {
180
+ (0, _reactDom.unstable_batchedUpdates)(function () {
181
+ setUploading(false);
182
+ setUploadErrorMessage(undefined);
93
183
  });
94
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "onCategorySelected", function (categoryId) {
95
- var emojiProvider = _this.props.emojiProvider;
96
-
97
- if (!categoryId) {
98
- return;
99
- }
184
+ fireAnalytics((0, _analytics.uploadCancelButton)());
185
+ }, [fireAnalytics]);
186
+ var getDynamicCategories = (0, _react.useCallback)(function () {
187
+ if (!emojiProvider.calculateDynamicCategories) {
188
+ return Promise.resolve([]);
189
+ }
100
190
 
101
- emojiProvider.findInCategory(categoryId).then(function (emojisInCategory) {
102
- var disableCategories = _this.state.disableCategories;
191
+ return emojiProvider.calculateDynamicCategories();
192
+ }, [emojiProvider]);
193
+ /**
194
+ * Calculate and set the new state of the component in response to the list of emoji changing for some reason (a search has returned
195
+ * or the frequently used emoji have updated.)
196
+ */
197
+
198
+ var setStateAfterEmojiChange = (0, _react.useCallback)(function (_ref2) {
199
+ var searchQuery = _ref2.searchQuery,
200
+ emojiToRender = _ref2.emojiToRender,
201
+ searchEmoji = _ref2.searchEmoji,
202
+ frequentEmoji = _ref2.frequentEmoji;
203
+ // Only enable categories for full emoji list (non-search)
204
+ var disableCategories = !!searchQuery;
205
+
206
+ if (!disableCategories && emojiToRender && emojiToRender.length !== filteredEmojis.length) {
207
+ getDynamicCategories().then(function (categories) {
208
+ onDynamicCategoryChange(categories);
209
+ });
210
+ }
103
211
 
104
- if (!disableCategories) {
105
- var selectedEmoji;
212
+ if (emojiToRender && !(0, _typeHelpers.containsEmojiId)(emojiToRender, selectedEmoji)) {
213
+ (0, _reactDom.unstable_batchedUpdates)(function () {
214
+ setSelectedEmoji(undefined); // Only enable categories for full emoji list (non-search)
106
215
 
107
- if (emojisInCategory && emojisInCategory.length > 0) {
108
- selectedEmoji = (0, _EmojiRepository.getEmojiVariation)(emojisInCategory[0], {
109
- skinTone: _this.state.selectedTone
110
- });
111
- }
216
+ setActiveCategory(null);
217
+ });
218
+ }
112
219
 
113
- var emojiPickerList = _this.refs.emojiPickerList;
220
+ (0, _reactDom.unstable_batchedUpdates)(function () {
221
+ if (emojiToRender) {
222
+ setFilteredEmojis(emojiToRender);
223
+ }
114
224
 
115
- if (emojiPickerList) {
116
- emojiPickerList.reveal(categoryId);
117
- }
225
+ if (searchEmoji) {
226
+ setSearchEmojis(searchEmoji);
227
+ }
118
228
 
119
- _this.setState({
120
- activeCategory: categoryId,
121
- selectedEmoji: selectedEmoji
122
- });
229
+ if (frequentEmoji) {
230
+ setFrequentlyUsedEmojis(frequentEmoji);
231
+ }
123
232
 
124
- _this.fireAnalytics((0, _analytics.categoryClickedEvent)({
125
- category: categoryId
126
- }));
127
- }
128
- });
129
- });
130
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "onPreviewDisplayed", function (isDisplayed) {
131
- _this.setState({
132
- isPreviewDisplayed: isDisplayed
133
- });
233
+ setLoading(false);
234
+ setDisableCategories(disableCategories);
134
235
  });
135
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "onFileChooserClicked", function () {
136
- _this.fireAnalytics((0, _analytics.selectedFileEvent)());
236
+ }, [filteredEmojis.length, getDynamicCategories, onDynamicCategoryChange, selectedEmoji]);
237
+ var onFrequentEmojiResult = (0, _react.useCallback)(function (frequentEmoji) {
238
+ // change the category of each of the featured emoji
239
+ var recategorised = frequentEmoji.map(function (emoji) {
240
+ var clone = JSON.parse(JSON.stringify(emoji));
241
+ clone.category = _constants.frequentCategory;
242
+ return clone;
137
243
  });
138
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "fireAnalytics", function (analyticsEvent) {
139
- var createAnalyticsEvent = _this.props.createAnalyticsEvent;
140
-
141
- if (createAnalyticsEvent) {
142
- (0, _analytics.createAndFireEventInElementsChannel)(analyticsEvent)(createAnalyticsEvent);
143
- }
244
+ setStateAfterEmojiChange({
245
+ frequentEmoji: recategorised
144
246
  });
145
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "calculateElapsedTime", function () {
146
- return Date.now() - _this.openTime;
147
- });
148
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "onUploadSupported", function (supported) {
149
- _this.setState({
150
- uploadSupported: supported
151
- });
152
- });
153
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "onSearch", function (query) {
154
- var options = {
155
- skinTone: _this.state.selectedTone
156
- };
247
+ }, [setStateAfterEmojiChange]);
248
+ var onSearchResult = (0, _react.useCallback)(function (searchResults) {
249
+ var frequentlyUsedEmoji = frequentlyUsedEmojis || [];
250
+ var searchQuery = searchResults.query || '';
251
+ /**
252
+ * If there is no user search in the EmojiPicker then it should display all emoji received from the EmojiRepository and should
253
+ * also include a special category of most frequently used emoji (if there are any). This method decides if we are in this 'no search'
254
+ * state and appends the frequent emoji if necessary.
255
+ */
157
256
 
158
- if (query !== _this.state.query) {
159
- _analytics.ufoExperiences['emoji-searched'].start();
257
+ var emojiToRender;
160
258
 
161
- _analytics.ufoExperiences['emoji-searched'].addMetadata({
162
- queryLength: query.length,
163
- source: 'picker'
164
- });
165
- }
259
+ if (!frequentlyUsedEmoji.length || query) {
260
+ emojiToRender = searchResults.emojis;
261
+ } else {
262
+ emojiToRender = [].concat((0, _toConsumableArray2.default)(searchResults.emojis), (0, _toConsumableArray2.default)(frequentlyUsedEmoji));
263
+ }
166
264
 
167
- _this.updateEmojis(query, options);
265
+ setStateAfterEmojiChange({
266
+ searchQuery: searchQuery,
267
+ emojiToRender: emojiToRender,
268
+ searchEmoji: searchResults.emojis
168
269
  });
169
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "onSearchResult", function (searchResults) {
170
- var frequentlyUsedEmoji = _this.state.frequentlyUsedEmojis || [];
171
- var searchQuery = searchResults.query || '';
172
-
173
- var emojiToRender = _this.buildQuerySpecificEmojiList(searchQuery, searchResults.emojis, frequentlyUsedEmoji);
270
+ }, [frequentlyUsedEmojis, query, setStateAfterEmojiChange]);
271
+ var onProviderChange = (0, _react.useMemo)(function () {
272
+ return {
273
+ result: onSearchResult
274
+ };
275
+ }, [onSearchResult]);
276
+ /**
277
+ * Updates the emoji displayed by the picker. If there is no query specified then we expect to retrieve all emoji for display,
278
+ * by category, in the picker. This differs from when there is a query in which case we expect to receive a sorted result matching
279
+ * the search.
280
+ */
281
+
282
+ var updateEmojis = (0, _react.useCallback)(function (query, options) {
283
+ // if the query is empty then we want the emoji to be in service defined order, unless specified otherwise
284
+ // and we want emoji for the 'frequently used' category to be refreshed as well.
285
+ if (!query) {
286
+ if (!options) {
287
+ options = {};
288
+ }
174
289
 
175
- if (searchQuery !== _this.state.query) {
176
- _this.fireAnalytics((0, _analytics.pickerSearchedEvent)({
177
- queryLength: searchQuery.length,
178
- numMatches: emojiToRender.length
179
- }));
290
+ if (!options.sort) {
291
+ options.sort = _types.SearchSort.None;
292
+ } // take a copy of search options so that the frequently used can be limited to 16 without affecting the full emoji query
180
293
 
181
- _analytics.ufoExperiences['emoji-searched'].success({
182
- metadata: {
183
- emojisLength: emojiToRender.length
184
- }
185
- });
186
- }
187
294
 
188
- _this.setStateAfterEmojiChange(searchQuery, emojiToRender, searchResults.emojis, frequentlyUsedEmoji);
189
- });
190
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "onFrequentEmojiResult", function (frequentEmoji) {
191
- var _this$state = _this.state,
192
- query = _this$state.query,
193
- searchEmojis = _this$state.searchEmojis; // change the category of each of the featured emoji
194
-
195
- var recategorised = frequentEmoji.map(function (emoji) {
196
- var clone = JSON.parse(JSON.stringify(emoji));
197
- clone.category = _constants.frequentCategory;
198
- return clone;
295
+ var frequentOptions = _objectSpread(_objectSpread({}, options), {}, {
296
+ sort: _types.SearchSort.None,
297
+ limit: FREQUENTLY_USED_MAX
199
298
  });
200
299
 
201
- var emojiToRender = _this.buildQuerySpecificEmojiList(query, searchEmojis, recategorised);
300
+ emojiProvider.getFrequentlyUsed(frequentOptions).then(onFrequentEmojiResult);
301
+ }
202
302
 
203
- _this.setStateAfterEmojiChange(query, emojiToRender, searchEmojis, recategorised);
204
- });
205
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "onDynamicCategoryChange", function (categories) {
206
- _this.setState({
207
- dynamicCategories: categories
208
- });
303
+ emojiProvider.filter(query, options);
304
+ }, [emojiProvider, onFrequentEmojiResult]);
305
+ var onToneSelected = (0, _react.useCallback)(function (toneValue) {
306
+ emojiProvider.setSelectedTone(toneValue);
307
+ updateEmojis(query, {
308
+ skinTone: toneValue
209
309
  });
210
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "onProviderChange", {
211
- result: _this.onSearchResult
212
- });
213
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "onToneSelected", function (toneValue) {
214
- _this.setState({
215
- selectedTone: toneValue
216
- });
217
-
218
- _this.props.emojiProvider.setSelectedTone(toneValue);
310
+ setSelectedTone(toneValue);
311
+ }, [emojiProvider, query, updateEmojis]);
312
+ var onToneSelectorCancelled = (0, _react.useCallback)(function () {
313
+ fireAnalytics((0, _analytics.toneSelectorClosedEvent)());
314
+ }, [fireAnalytics]);
315
+ var onSelectWrapper = (0, _react.useCallback)(function (emojiId, emoji, event) {
316
+ if (onSelection) {
317
+ onSelection(emojiId, emoji, event);
318
+ fireAnalytics((0, _analytics.pickerClickedEvent)({
319
+ duration: calculateElapsedTime(),
320
+ emojiId: (emojiId === null || emojiId === void 0 ? void 0 : emojiId.id) || '',
321
+ category: emoji && emoji.category || '',
322
+ type: emoji && emoji.type || '',
323
+ queryLength: query && query.length || 0
324
+ }));
325
+ }
326
+ }, [fireAnalytics, onSelection, query]);
327
+ var onCategorySelected = (0, _react.useCallback)(function (categoryId) {
328
+ if (!categoryId) {
329
+ return;
330
+ }
219
331
 
220
- var _this$state$query = _this.state.query,
221
- query = _this$state$query === void 0 ? '' : _this$state$query;
332
+ emojiProvider.findInCategory(categoryId).then(function (emojisInCategory) {
333
+ if (!disableCategories) {
334
+ var newSelectedEmoji;
222
335
 
223
- _this.updateEmojis(query, {
224
- skinTone: toneValue
225
- });
226
- });
227
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "onToneSelectorCancelled", function () {
228
- _this.fireAnalytics((0, _analytics.toneSelectorClosedEvent)());
229
- });
230
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "updateEmojis", function (query, options) {
231
- // if the query is empty then we want the emoji to be in service defined order, unless specified otherwise
232
- // and we want emoji for the 'frequently used' category to be refreshed as well.
233
- if (!query) {
234
- if (!options) {
235
- options = {};
336
+ if (emojisInCategory && emojisInCategory.length > 0) {
337
+ newSelectedEmoji = (0, _EmojiRepository.getEmojiVariation)(emojisInCategory[0], {
338
+ skinTone: selectedTone
339
+ });
236
340
  }
237
341
 
238
- if (!options.sort) {
239
- options.sort = _types.SearchSort.None;
240
- } // take a copy of search options so that the frequently used can be limited to 16 without affecting the full emoji query
241
-
342
+ if (emojiPickerList.current) {
343
+ emojiPickerList.current.reveal(categoryId);
344
+ }
242
345
 
243
- var frequentOptions = _objectSpread(_objectSpread({}, options), {}, {
244
- sort: _types.SearchSort.None,
245
- limit: FREQUENTLY_USED_MAX
346
+ (0, _reactDom.unstable_batchedUpdates)(function () {
347
+ setActiveCategory(categoryId);
348
+ setSelectedEmoji(newSelectedEmoji);
246
349
  });
247
-
248
- _this.props.emojiProvider.getFrequentlyUsed(frequentOptions).then(_this.onFrequentEmojiResult);
350
+ fireAnalytics((0, _analytics.categoryClickedEvent)({
351
+ category: categoryId
352
+ }));
249
353
  }
250
-
251
- _this.props.emojiProvider.filter(query, options);
252
354
  });
253
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "onOpenUpload", function () {
254
- // Prime upload token so it's ready when the user adds
255
- var emojiProvider = _this.props.emojiProvider;
256
-
257
- if ((0, _EmojiResource.supportsUploadFeature)(emojiProvider)) {
258
- emojiProvider.prepareForUpload();
355
+ }, [disableCategories, emojiPickerList, emojiProvider, fireAnalytics, selectedTone]);
356
+ var recordUsageOnSelection = (0, _react.useMemo)(function () {
357
+ return (0, _RecordSelectionDefault.createRecordSelectionDefault)(emojiProvider, onSelectWrapper, function (analytic) {
358
+ return fireAnalytics(analytic('picker'));
359
+ });
360
+ }, [emojiProvider, fireAnalytics, onSelectWrapper]);
361
+ var formattedErrorMessage = (0, _react.useMemo)(function () {
362
+ return uploadErrorMessage ? (0, _core.jsx)(_reactIntlNext.FormattedMessage, uploadErrorMessage) : null;
363
+ }, [uploadErrorMessage]);
364
+ var emojiContextValue = (0, _react.useMemo)(function () {
365
+ return {
366
+ emoji: {
367
+ emojiProvider: emojiProvider
259
368
  }
369
+ };
370
+ }, [emojiProvider]);
371
+ var onFileChooserClicked = (0, _react.useCallback)(function () {
372
+ fireAnalytics((0, _analytics.selectedFileEvent)());
373
+ }, [fireAnalytics]);
374
+ var onSearch = (0, _react.useCallback)(function (searchQuery) {
375
+ var options = {
376
+ skinTone: selectedTone
377
+ };
260
378
 
261
- _this.setState({
262
- uploadErrorMessage: undefined,
263
- uploading: true
264
- });
265
-
266
- _this.fireAnalytics((0, _analytics.uploadBeginButton)());
267
- });
268
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "onUploadEmoji", function (upload, retry) {
269
- var emojiProvider = _this.props.emojiProvider;
379
+ if (query) {
380
+ _analytics.ufoExperiences['emoji-searched'].start();
270
381
 
271
- _this.fireAnalytics((0, _analytics.uploadConfirmButton)({
272
- retry: retry
273
- }));
382
+ _analytics.ufoExperiences['emoji-searched'].addMetadata({
383
+ queryLength: query.length,
384
+ source: 'picker'
385
+ });
386
+ }
274
387
 
275
- var errorSetter = function errorSetter(message) {
276
- _this.setState({
277
- uploadErrorMessage: message
278
- });
279
- };
388
+ if (searchQuery !== query) {
389
+ setQuery(searchQuery);
390
+ }
280
391
 
281
- var onSuccess = function onSuccess(emojiDescription) {
282
- _this.setState({
283
- activeCategory: _constants.customCategory,
284
- selectedEmoji: emojiDescription,
285
- uploading: false
286
- }); // this.loadEmoji(emojiProvider, emojiDescription);
392
+ updateEmojis(query, options);
393
+ }, [query, selectedTone, updateEmojis]);
394
+ var onOpenUpload = (0, _react.useCallback)(function () {
395
+ // Prime upload token so it's ready when the user adds
396
+ if ((0, _EmojiResource.supportsUploadFeature)(emojiProvider)) {
397
+ emojiProvider.prepareForUpload();
398
+ }
287
399
 
400
+ (0, _reactDom.unstable_batchedUpdates)(function () {
401
+ setUploadErrorMessage(undefined);
402
+ setUploading(true);
403
+ });
404
+ fireAnalytics((0, _analytics.uploadBeginButton)());
405
+ }, [emojiProvider, fireAnalytics]);
406
+ var scrollToEndOfList = (0, _react.useCallback)(function () {
407
+ if (typeof window === 'undefined') {
408
+ return;
409
+ }
288
410
 
289
- _this.scrollToEndOfList();
290
- };
411
+ if (emojiPickerList.current) {
412
+ // Wait a tick to ensure repaint and updated height for picker list
413
+ window.setTimeout(function () {
414
+ var _emojiPickerList$curr;
291
415
 
292
- (0, _UploadEmoji.uploadEmoji)(upload, emojiProvider, errorSetter, onSuccess, _this.fireAnalytics, retry);
293
- });
294
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "onTriggerDelete", function (_emojiId, emoji) {
295
- _this.fireAnalytics((0, _analytics.deleteBeginEvent)({
296
- emojiId: _emojiId.id
297
- }));
416
+ (_emojiPickerList$curr = emojiPickerList.current) === null || _emojiPickerList$curr === void 0 ? void 0 : _emojiPickerList$curr.scrollToBottom();
417
+ }, 0);
418
+ }
419
+ }, [emojiPickerList]);
420
+ var onUploadEmoji = (0, _react.useCallback)(function (upload, retry) {
421
+ fireAnalytics((0, _analytics.uploadConfirmButton)({
422
+ retry: retry
423
+ }));
424
+
425
+ var errorSetter = function errorSetter(message) {
426
+ setUploadErrorMessage(message);
427
+ };
298
428
 
299
- _this.setState({
300
- emojiToDelete: emoji
429
+ var onSuccess = function onSuccess(emojiDescription) {
430
+ (0, _reactDom.unstable_batchedUpdates)(function () {
431
+ setActiveCategory(_constants.customCategory);
432
+ setSelectedEmoji(emojiDescription);
433
+ setUploading(false);
301
434
  });
302
- });
303
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "onCloseDelete", function () {
304
- var emojiToDelete = _this.state.emojiToDelete;
435
+ scrollToEndOfList();
436
+ };
305
437
 
306
- _this.fireAnalytics((0, _analytics.deleteCancelEvent)({
307
- emojiId: emojiToDelete && emojiToDelete.id
438
+ (0, _UploadEmoji.uploadEmoji)(upload, emojiProvider, errorSetter, onSuccess, fireAnalytics, retry);
439
+ }, [emojiProvider, fireAnalytics, scrollToEndOfList]);
440
+ var onTriggerDelete = (0, _react.useCallback)(function (_emojiId, emoji) {
441
+ if (_emojiId) {
442
+ fireAnalytics((0, _analytics.deleteBeginEvent)({
443
+ emojiId: _emojiId.id
308
444
  }));
445
+ setEmojiToDelete(emoji);
446
+ }
447
+ }, [fireAnalytics]);
448
+ var onCloseDelete = (0, _react.useCallback)(function () {
449
+ fireAnalytics((0, _analytics.deleteCancelEvent)({
450
+ emojiId: emojiToDelete && emojiToDelete.id
451
+ }));
452
+ setEmojiToDelete(undefined);
453
+ }, [emojiToDelete, fireAnalytics]);
454
+ var onDeleteEmoji = (0, _react.useCallback)(function (emoji) {
455
+ fireAnalytics((0, _analytics.deleteConfirmEvent)({
456
+ emojiId: emojiToDelete && emojiToDelete.id
457
+ }));
458
+ return emojiProvider.deleteSiteEmoji(emoji).then(function (success) {
459
+ if (success) {
460
+ updateEmojis(query, {
461
+ skinTone: selectedTone
462
+ });
463
+ }
309
464
 
310
- _this.setState({
311
- emojiToDelete: undefined
312
- });
465
+ return success;
313
466
  });
314
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "onDeleteEmoji", function (emoji) {
315
- var _this$state2 = _this.state,
316
- emojiToDelete = _this$state2.emojiToDelete,
317
- query = _this$state2.query,
318
- selectedTone = _this$state2.selectedTone;
319
-
320
- _this.fireAnalytics((0, _analytics.deleteConfirmEvent)({
321
- emojiId: emojiToDelete && emojiToDelete.id
322
- }));
467
+ }, [emojiProvider, emojiToDelete, fireAnalytics, query, selectedTone, updateEmojis]);
468
+ var onComponentDidMount = (0, _react.useCallback)(function () {
469
+ emojiProvider.subscribe(onProviderChange);
470
+ onSearch(query);
323
471
 
324
- return _this.props.emojiProvider.deleteSiteEmoji(emoji).then(function (success) {
325
- if (success) {
326
- _this.updateEmojis(query, {
327
- skinTone: selectedTone
328
- });
329
- }
472
+ if ((0, _EmojiResource.supportsUploadFeature)(emojiProvider)) {
473
+ emojiProvider.isUploadSupported().then(onUploadSupported);
474
+ }
330
475
 
331
- return success;
332
- });
333
- });
334
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "scrollToEndOfList", function () {
335
- var emojiPickerList = _this.refs.emojiPickerList;
476
+ if (!hideToneSelector) {
477
+ var _toneEmoji = (0, _filters.getToneEmoji)(emojiProvider);
336
478
 
337
- if (typeof window === 'undefined') {
338
- return;
479
+ if ((0, _typeHelpers.isPromise)(_toneEmoji)) {
480
+ _toneEmoji.then(function (emoji) {
481
+ return setToneEmoji(emoji);
482
+ });
483
+ } else if (_toneEmoji === undefined || (0, _typeHelpers.isEmojiDescription)(_toneEmoji)) {
484
+ setToneEmoji(_toneEmoji);
339
485
  }
486
+ }
487
+ }, [emojiProvider, hideToneSelector, onProviderChange, onSearch, onUploadSupported, query]);
340
488
 
341
- if (emojiPickerList) {
342
- // Wait a tick to ensure repaint and updated height for picker list
343
- window.setTimeout(function () {
344
- emojiPickerList.scrollToBottom();
345
- }, 0);
346
- }
347
- });
348
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "onUploadCancelled", function () {
349
- _this.setState({
350
- uploading: false,
351
- uploadErrorMessage: undefined
352
- });
489
+ if (isMounting.current) {
490
+ // componentWillMount equivalent
491
+ _analytics.ufoExperiences['emoji-picker-opened'].success();
353
492
 
354
- _this.fireAnalytics((0, _analytics.uploadCancelButton)());
355
- });
356
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "handlePickerRef", function (ref) {
357
- if (_this.props.onPickerRef) {
358
- _this.props.onPickerRef(ref);
359
- }
360
- });
361
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "onSelectWrapper", function (emojiId, emoji, event) {
362
- var onSelection = _this.props.onSelection;
363
- var query = _this.state.query;
364
-
365
- if (onSelection) {
366
- onSelection(emojiId, emoji, event);
367
-
368
- _this.fireAnalytics((0, _analytics.pickerClickedEvent)({
369
- duration: _this.calculateElapsedTime(),
370
- emojiId: emojiId.id || '',
371
- category: emoji && emoji.category || '',
372
- type: emoji && emoji.type || '',
373
- queryLength: query && query.length || 0
374
- }));
375
- }
376
- });
377
- var _emojiProvider = props.emojiProvider,
378
- hideToneSelector = props.hideToneSelector;
379
- _this.state = {
380
- filteredEmojis: [],
381
- searchEmojis: [],
382
- frequentlyUsedEmojis: [],
383
- query: '',
384
- dynamicCategories: [],
385
- selectedTone: !hideToneSelector ? _emojiProvider.getSelectedTone() : undefined,
386
- loading: true,
387
- uploadSupported: false,
388
- uploading: false,
389
- isPreviewDisplayed: false
390
- };
391
- _this.openTime = 0;
392
- return _this;
493
+ openTime.current = Date.now();
494
+ fireAnalytics((0, _analytics.openedPickerEvent)());
495
+ isMounting.current = false;
393
496
  }
394
497
 
395
- (0, _createClass2.default)(EmojiPickerComponent, [{
396
- key: "UNSAFE_componentWillMount",
397
- value: function UNSAFE_componentWillMount() {
398
- _analytics.ufoExperiences['emoji-picker-opened'].success();
399
-
400
- this.openTime = Date.now();
401
- this.fireAnalytics((0, _analytics.openedPickerEvent)());
498
+ (0, _react.useEffect)(function () {
499
+ // componentDidMount logic
500
+ if (didMount && updateAfterDidMount.current) {
501
+ onComponentDidMount();
502
+ updateAfterDidMount.current = false;
503
+ }
504
+ }, [didMount, onComponentDidMount]);
505
+ (0, _react.useEffect)(function () {
506
+ previousEmojiProvider.current.unsubscribe(onProviderChange);
507
+ previousEmojiProvider.current = emojiProvider;
508
+ emojiProvider.subscribe(onProviderChange);
509
+
510
+ if ((0, _EmojiResource.supportsUploadFeature)(emojiProvider)) {
511
+ emojiProvider.isUploadSupported().then(onUploadSupported);
402
512
  }
403
- }, {
404
- key: "componentDidMount",
405
- value: function componentDidMount() {
406
- var _this2 = this;
407
-
408
- var _this$props = this.props,
409
- emojiProvider = _this$props.emojiProvider,
410
- hideToneSelector = _this$props.hideToneSelector;
411
- emojiProvider.subscribe(this.onProviderChange);
412
- this.onSearch(this.state.query);
413
-
414
- if ((0, _EmojiResource.supportsUploadFeature)(emojiProvider)) {
415
- emojiProvider.isUploadSupported().then(this.onUploadSupported);
416
- }
417
-
418
- if (!hideToneSelector) {
419
- var toneEmoji = (0, _filters.getToneEmoji)(emojiProvider);
420
513
 
421
- if ((0, _typeHelpers.isPromise)(toneEmoji)) {
422
- toneEmoji.then(function (emoji) {
423
- return _this2.setState({
424
- toneEmoji: emoji
425
- });
426
- });
427
- } else if (toneEmoji === undefined || (0, _typeHelpers.isEmojiDescription)(toneEmoji)) {
428
- this.setState({
429
- toneEmoji: toneEmoji
430
- });
431
- }
514
+ return function () {
515
+ emojiProvider.unsubscribe(onProviderChange);
516
+ };
517
+ }, [emojiProvider, onProviderChange, onUploadSupported]);
518
+ (0, _react.useEffect)(function () {
519
+ // We changed provider which means we subscribed to filter results for a new subscriber.
520
+ // So we refresh the emoji display with onSearch and we do it here, after the new props have
521
+ // been set since onSearch leads to filter being called on the current emojiProvider.
522
+ // (Calling onSearch in a '...Will...' lifecycle method would lead to filter being called on
523
+ // an emojiProvider we have already unsubscribed from)
524
+ onSearch(query);
525
+ }, [emojiProvider, onSearch, query]);
526
+ (0, _react.useEffect)(function () {
527
+ // Fire analytics event whenever query changes
528
+ fireAnalytics((0, _analytics.pickerSearchedEvent)({
529
+ queryLength: query.length,
530
+ numMatches: filteredEmojis.length
531
+ }));
532
+
533
+ _analytics.ufoExperiences['emoji-searched'].success({
534
+ metadata: {
535
+ emojisLength: filteredEmojis.length
432
536
  }
537
+ });
538
+ }, [filteredEmojis.length, fireAnalytics, query]);
539
+ (0, _react.useEffect)(function () {
540
+ if (!frequentlyUsedEmojis.length || query) {
541
+ setFilteredEmojis(searchEmojis);
542
+ } else {
543
+ setFilteredEmojis([].concat((0, _toConsumableArray2.default)(searchEmojis), (0, _toConsumableArray2.default)(frequentlyUsedEmojis)));
433
544
  }
434
- }, {
435
- key: "componentWillUnmount",
436
- value: function componentWillUnmount() {
437
- var emojiProvider = this.props.emojiProvider;
438
- emojiProvider.unsubscribe(this.onProviderChange);
439
- this.fireAnalytics((0, _analytics.closedPickerEvent)({
440
- duration: this.calculateElapsedTime()
545
+ }, [frequentlyUsedEmojis, query, searchEmojis]);
546
+ (0, _react.useEffect)(function () {
547
+ // Fire analytics on component unmount
548
+ return function () {
549
+ fireAnalytics((0, _analytics.closedPickerEvent)({
550
+ duration: calculateElapsedTime()
441
551
  }));
442
552
 
443
553
  _analytics.ufoExperiences['emoji-picker-opened'].abort({
@@ -453,187 +563,57 @@ var EmojiPickerComponent = /*#__PURE__*/function (_PureComponent) {
453
563
  reason: 'unmount'
454
564
  }
455
565
  });
456
- }
457
- }, {
458
- key: "UNSAFE_componentWillReceiveProps",
459
- value: function UNSAFE_componentWillReceiveProps(nextProps) {
460
- var prevEmojiProvider = this.props.emojiProvider;
461
- var nextEmojiProvider = nextProps.emojiProvider;
462
-
463
- if (prevEmojiProvider !== nextEmojiProvider) {
464
- if ((0, _EmojiResource.supportsUploadFeature)(nextEmojiProvider)) {
465
- nextEmojiProvider.isUploadSupported().then(this.onUploadSupported);
466
- }
467
- }
468
- }
469
- }, {
470
- key: "componentDidUpdate",
471
- value: function componentDidUpdate(prevProps) {
472
- var prevEmojiProvider = prevProps.emojiProvider;
473
- var currentEmojiProvider = this.props.emojiProvider;
474
-
475
- if (prevEmojiProvider !== currentEmojiProvider) {
476
- prevEmojiProvider.unsubscribe(this.onProviderChange);
477
- currentEmojiProvider.subscribe(this.onProviderChange); // We changed provider which means we subscribed to filter results for a new subscriber.
478
- // So we refresh the emoji display with onSearch and we do it here, after the new props have
479
- // been set since onSearch leads to filter being called on the current emojiProvider.
480
- // (Calling onSearch in a '...Will...' lifecycle method would lead to filter being called on
481
- // an emojiProvider we have already unsubscribed from)
482
-
483
- this.onSearch(this.state.query);
484
- }
485
- }
486
- }, {
487
- key: "buildQuerySpecificEmojiList",
488
- value:
489
- /**
490
- * If there is no user search in the EmojiPicker then it should display all emoji received from the EmojiRepository and should
491
- * also include a special category of most frequently used emoji (if there are any). This method decides if we are in this 'no search'
492
- * state and appends the frequent emoji if necessary.
493
- *
494
- * @param searchEmoji the emoji last received from the EmojiRepository after a search (may be empty)
495
- * @param frequentEmoji the frequently used emoji last received from the EmojiRepository (may be empty)
496
- */
497
- function buildQuerySpecificEmojiList(query, searchEmoji, frequentEmoji) {
498
- // If there are no frequent emoji, or if there was a search query then we want to take the search result exactly as is.
499
- if (!frequentEmoji.length || query) {
500
- return searchEmoji;
501
- }
502
-
503
- return [].concat((0, _toConsumableArray2.default)(searchEmoji), (0, _toConsumableArray2.default)(frequentEmoji));
504
- }
505
- /**
506
- * Calculate and set the new state of the component in response to the list of emoji changing for some reason (a search has returned
507
- * or the frequently used emoji have updated.)
508
- */
509
-
510
- }, {
511
- key: "setStateAfterEmojiChange",
512
- value: function setStateAfterEmojiChange(query, emojiToRender, searchEmoji, frequentEmoji) {
513
- var _this3 = this;
514
-
515
- var filteredEmojis = this.state.filteredEmojis; // Only enable categories for full emoji list (non-search)
516
-
517
- var disableCategories = !!query;
518
-
519
- if (!disableCategories && emojiToRender.length !== filteredEmojis.length) {
520
- this.getDynamicCategories().then(function (categories) {
521
- _this3.onDynamicCategoryChange(categories);
522
- });
523
- }
524
-
525
- var selectedEmoji;
526
- var activeCategory;
527
-
528
- if ((0, _typeHelpers.containsEmojiId)(emojiToRender, this.state.selectedEmoji)) {
529
- // Keep existing emoji selected if still in results
530
- selectedEmoji = this.state.selectedEmoji;
531
- activeCategory = this.state.activeCategory;
532
- } else {
533
- selectedEmoji = undefined; // Only enable categories for full emoji list (non-search)
534
-
535
- activeCategory = undefined;
536
- }
537
-
538
- this.setState({
539
- filteredEmojis: emojiToRender,
540
- searchEmojis: searchEmoji,
541
- frequentlyUsedEmojis: frequentEmoji,
542
- selectedEmoji: selectedEmoji,
543
- activeCategory: activeCategory,
544
- disableCategories: disableCategories,
545
- query: query,
546
- loading: false
547
- });
548
- }
549
- }, {
550
- key: "getDynamicCategories",
551
- value: function getDynamicCategories() {
552
- if (!this.props.emojiProvider.calculateDynamicCategories) {
553
- return Promise.resolve([]);
554
- }
555
-
556
- return this.props.emojiProvider.calculateDynamicCategories();
557
- }
558
- }, {
559
- key: "render",
560
- value: function render() {
561
- var _this4 = this;
562
-
563
- var emojiProvider = this.props.emojiProvider;
564
- var _this$state3 = this.state,
565
- activeCategory = _this$state3.activeCategory,
566
- disableCategories = _this$state3.disableCategories,
567
- dynamicCategories = _this$state3.dynamicCategories,
568
- filteredEmojis = _this$state3.filteredEmojis,
569
- loading = _this$state3.loading,
570
- query = _this$state3.query,
571
- selectedEmoji = _this$state3.selectedEmoji,
572
- selectedTone = _this$state3.selectedTone,
573
- toneEmoji = _this$state3.toneEmoji,
574
- emojiToDelete = _this$state3.emojiToDelete,
575
- uploading = _this$state3.uploading,
576
- uploadErrorMessage = _this$state3.uploadErrorMessage,
577
- uploadSupported = _this$state3.uploadSupported,
578
- isPreviewDisplayed = _this$state3.isPreviewDisplayed;
579
- var recordUsageOnSelection = (0, _RecordSelectionDefault.createRecordSelectionDefault)(emojiProvider, this.onSelectWrapper, function (analytic) {
580
- return _this4.fireAnalytics(analytic('picker'));
581
- });
582
- var formattedErrorMessage = uploadErrorMessage ? (0, _core.jsx)(_reactIntlNext.FormattedMessage, uploadErrorMessage) : null;
583
- var emojiContextValue = {
584
- emoji: {
585
- emojiProvider: this.props.emojiProvider
586
- }
587
- };
588
- var picker = (0, _core.jsx)(_LegacyEmojiContextProvider.default, {
589
- emojiContextValue: emojiContextValue
590
- }, (0, _core.jsx)("div", {
591
- css: (0, _styles.emojiPicker)(isPreviewDisplayed),
592
- ref: this.handlePickerRef,
593
- "data-emoji-picker-container": true
594
- }, (0, _core.jsx)(_CategorySelector.default, {
595
- activeCategoryId: activeCategory,
596
- dynamicCategories: dynamicCategories,
597
- disableCategories: disableCategories,
598
- onCategorySelected: this.onCategorySelected
599
- }), (0, _core.jsx)(_EmojiPickerList.default, {
600
- emojis: filteredEmojis,
601
- currentUser: emojiProvider.getCurrentUser(),
602
- onEmojiSelected: recordUsageOnSelection,
603
- onEmojiActive: this.onEmojiActive,
604
- onEmojiDelete: this.onTriggerDelete,
605
- onCategoryActivated: this.onCategoryActivated,
606
- onSearch: this.onSearch,
607
- query: query,
608
- selectedTone: selectedTone,
609
- loading: loading,
610
- ref: "emojiPickerList",
611
- initialUploadName: query,
612
- onToneSelected: this.onToneSelected,
613
- onToneSelectorCancelled: this.onToneSelectorCancelled,
614
- toneEmoji: toneEmoji,
615
- uploading: uploading,
616
- emojiToDelete: emojiToDelete,
617
- uploadErrorMessage: formattedErrorMessage,
618
- uploadEnabled: uploadSupported && !uploading,
619
- onUploadEmoji: this.onUploadEmoji,
620
- onUploadCancelled: this.onUploadCancelled,
621
- onDeleteEmoji: this.onDeleteEmoji,
622
- onCloseDelete: this.onCloseDelete,
623
- onFileChooserClicked: this.onFileChooserClicked,
624
- onOpenUpload: this.onOpenUpload
625
- }), (0, _core.jsx)(_EmojiPickerFooter.default, {
626
- selectedEmoji: selectedEmoji,
627
- isUploading: uploading,
628
- onPreviewDisplayed: this.onPreviewDisplayed
629
- })));
630
- return picker;
631
- }
632
- }]);
633
- return EmojiPickerComponent;
634
- }(_react.PureComponent);
635
-
636
- exports.default = EmojiPickerComponent;
637
- (0, _defineProperty2.default)(EmojiPickerComponent, "defaultProps", {
638
- onSelection: function onSelection() {}
639
- });
566
+ };
567
+ }, [fireAnalytics]);
568
+ (0, _react.useEffect)(function () {
569
+ // Unsubscribe emojiProvider on component unmount
570
+ return function () {
571
+ emojiProvider.unsubscribe(onProviderChange);
572
+ };
573
+ }, [emojiProvider, onProviderChange]);
574
+ var showPreview = selectedEmoji && !uploading;
575
+ return (0, _core.jsx)(_LegacyEmojiContextProvider.default, {
576
+ emojiContextValue: emojiContextValue
577
+ }, (0, _core.jsx)("div", {
578
+ css: (0, _styles.emojiPicker)(showPreview),
579
+ ref: onPickerRef,
580
+ "data-emoji-picker-container": true
581
+ }, (0, _core.jsx)(_CategorySelector.default, {
582
+ activeCategoryId: activeCategory,
583
+ dynamicCategories: dynamicCategories,
584
+ disableCategories: disableCategories,
585
+ onCategorySelected: onCategorySelected
586
+ }), (0, _core.jsx)(_EmojiPickerList.default, {
587
+ emojis: filteredEmojis,
588
+ currentUser: currentUser,
589
+ onEmojiSelected: recordUsageOnSelection,
590
+ onEmojiActive: onEmojiActive,
591
+ onEmojiDelete: onTriggerDelete,
592
+ onCategoryActivated: onCategoryActivated,
593
+ onSearch: onSearch,
594
+ query: query,
595
+ selectedTone: selectedTone,
596
+ loading: loading,
597
+ ref: emojiPickerList,
598
+ initialUploadName: query,
599
+ onToneSelected: onToneSelected,
600
+ onToneSelectorCancelled: onToneSelectorCancelled,
601
+ toneEmoji: toneEmoji,
602
+ uploading: uploading,
603
+ emojiToDelete: emojiToDelete,
604
+ uploadErrorMessage: formattedErrorMessage,
605
+ uploadEnabled: uploadSupported && !uploading,
606
+ onUploadEmoji: onUploadEmoji,
607
+ onUploadCancelled: onUploadCancelled,
608
+ onDeleteEmoji: onDeleteEmoji,
609
+ onCloseDelete: onCloseDelete,
610
+ onFileChooserClicked: onFileChooserClicked,
611
+ onOpenUpload: onOpenUpload
612
+ }), showPreview && (0, _core.jsx)(_EmojiPickerFooter.default, {
613
+ selectedEmoji: selectedEmoji
614
+ })));
615
+ };
616
+
617
+ var _default = /*#__PURE__*/(0, _react.memo)(EmojiPickerComponent);
618
+
619
+ exports.default = _default;