@atlaskit/emoji 70.16.5 → 70.17.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 CHANGED
@@ -1,5 +1,25 @@
1
1
  # @atlaskit/emoji
2
2
 
3
+ ## 70.17.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`074057d77ce64`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/074057d77ce64) -
8
+ Display Atlassian emoji subcategories
9
+
10
+ ### Patch Changes
11
+
12
+ - [`5dd8cc218e393`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/5dd8cc218e393) -
13
+ Release packages affected by an issue blocking you from installing <@compiled>/react due to a yarn
14
+ patch.
15
+ - Updated dependencies
16
+
17
+ ## 70.16.6
18
+
19
+ ### Patch Changes
20
+
21
+ - Updated dependencies
22
+
3
23
  ## 70.16.5
4
24
 
5
25
  ### Patch Changes
@@ -17,6 +17,7 @@ var _EmojiRepositoryRegex = require("./EmojiRepositoryRegex");
17
17
  var _Comparators = require("./internal/Comparators");
18
18
  var _UsageFrequencyTracker = require("./internal/UsageFrequencyTracker");
19
19
  var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
20
+ var _expVal = require("@atlaskit/tmp-editor-statsig/expVal");
20
21
  // FS-1097 - duplicated in mentions - extract at some point into a shared library
21
22
  var Tokenizer = /*#__PURE__*/function () {
22
23
  function Tokenizer() {
@@ -114,6 +115,7 @@ var findEmojiIndex = function findEmojiIndex(emojis, toFind) {
114
115
  });
115
116
  return match;
116
117
  };
118
+ var teamojiRefreshExperimentName = 'platform_teamoji_26_refresh_emoji_picker';
117
119
  var EmojiRepository = exports.default = /*#__PURE__*/function () {
118
120
  // protected to allow subclasses to access (for testing and storybooks).
119
121
 
@@ -203,6 +205,10 @@ var EmojiRepository = exports.default = /*#__PURE__*/function () {
203
205
  value: function findInCategory(categoryId) {
204
206
  if (categoryId === _constants.frequentCategory) {
205
207
  return this.getFrequentlyUsed();
208
+ } else if ((0, _expVal.expVal)(teamojiRefreshExperimentName, 'isEnabled', false) && categoryId === 'ATLASSIAN') {
209
+ return this.all().emojis.filter(function (emoji) {
210
+ return emoji.type === 'ATLASSIAN';
211
+ });
206
212
  } else {
207
213
  return this.all().emojis.filter(function (emoji) {
208
214
  return emoji.category === categoryId;
@@ -352,7 +358,7 @@ var EmojiRepository = exports.default = /*#__PURE__*/function () {
352
358
  this.asciiMap = new Map();
353
359
  var categorySet = new Set();
354
360
  this.emojis.forEach(function (emoji) {
355
- categorySet.add(emoji.category);
361
+ categorySet.add(_this3.getDynamicCategoryForEmoji(emoji, (0, _expVal.expVal)(teamojiRefreshExperimentName, 'isEnabled', false)));
356
362
  _this3.addToMaps(emoji);
357
363
  });
358
364
  if (this.usageTracker.getOrder().length) {
@@ -414,11 +420,20 @@ var EmojiRepository = exports.default = /*#__PURE__*/function () {
414
420
  }, {
415
421
  key: "addToDynamicCategories",
416
422
  value: function addToDynamicCategories(emoji) {
417
- var category = (0, _typeHelpers.getCategoryId)(emoji);
423
+ var category = this.getDynamicCategoryForEmoji(emoji, (0, _expVal.expVal)(teamojiRefreshExperimentName, 'isEnabled', false));
418
424
  if (_constants.defaultCategories.indexOf(category) === -1 && this.dynamicCategoryList.indexOf(category) === -1) {
419
425
  this.dynamicCategoryList.push(category);
420
426
  }
421
427
  }
428
+ }, {
429
+ key: "getDynamicCategoryForEmoji",
430
+ value: function getDynamicCategoryForEmoji(emoji, isTeamojiRefreshEnabled) {
431
+ var category = (0, _typeHelpers.getCategoryId)(emoji);
432
+ if (isTeamojiRefreshEnabled && emoji.type === 'ATLASSIAN' && category !== _constants.frequentCategory) {
433
+ return 'ATLASSIAN';
434
+ }
435
+ return category;
436
+ }
422
437
  }]);
423
438
  }();
424
439
  (0, _defineProperty2.default)(EmojiRepository, "defaultEmojiWeight", 1000000);
@@ -28,6 +28,9 @@ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r
28
28
  */
29
29
  var RENDER_EMOJI_PICKER_LIST_TESTID = exports.RENDER_EMOJI_PICKER_LIST_TESTID = 'render-emoji-picker-list';
30
30
  var categoryClassname = 'emoji-category';
31
+ var teamojiRefreshExperimentName = 'platform_teamoji_26_refresh_emoji_picker';
32
+ var atlassianCategory = 'ATLASSIAN';
33
+ var atlassianSubcategoryOrder = ['Faces', 'Hands', 'Reactions', 'Objects', 'Productivity', 'Logos'];
31
34
 
32
35
  /**
33
36
  * Emoji grouped by a category title ie. Frequent, Your Uploads, All Uploads
@@ -36,20 +39,27 @@ var categoryClassname = 'emoji-category';
36
39
  var byOrder = function byOrder(orderableA, orderableB) {
37
40
  return (orderableA.order || 0) - (orderableB.order || 0);
38
41
  };
42
+ var noop = function noop() {};
43
+ var getAtlassianSubcategoryTitle = function getAtlassianSubcategoryTitle(category) {
44
+ if (!category) {
45
+ return 'Other';
46
+ }
47
+ return category.charAt(0).toUpperCase() + category.slice(1).toLowerCase();
48
+ };
39
49
  var EmojiPickerVirtualListInternal = exports.EmojiPickerVirtualListInternal = /*#__PURE__*/_react.default.forwardRef(function (props, ref) {
40
50
  var emojis = props.emojis,
41
51
  currentUser = props.currentUser,
42
52
  _props$onEmojiSelecte = props.onEmojiSelected,
43
- onEmojiSelected = _props$onEmojiSelecte === void 0 ? function () {} : _props$onEmojiSelecte,
53
+ onEmojiSelected = _props$onEmojiSelecte === void 0 ? noop : _props$onEmojiSelecte,
44
54
  _props$onEmojiActive = props.onEmojiActive,
45
- onEmojiActive = _props$onEmojiActive === void 0 ? function () {} : _props$onEmojiActive,
55
+ onEmojiActive = _props$onEmojiActive === void 0 ? noop : _props$onEmojiActive,
46
56
  onEmojiLeave = props.onEmojiLeave,
47
57
  _props$onEmojiDelete = props.onEmojiDelete,
48
- onEmojiDelete = _props$onEmojiDelete === void 0 ? function () {} : _props$onEmojiDelete,
58
+ onEmojiDelete = _props$onEmojiDelete === void 0 ? noop : _props$onEmojiDelete,
49
59
  _props$onCategoryActi = props.onCategoryActivated,
50
- onCategoryActivated = _props$onCategoryActi === void 0 ? function () {} : _props$onCategoryActi,
60
+ onCategoryActivated = _props$onCategoryActi === void 0 ? noop : _props$onCategoryActi,
51
61
  _props$onSearch = props.onSearch,
52
- onSearch = _props$onSearch === void 0 ? function () {} : _props$onSearch,
62
+ onSearch = _props$onSearch === void 0 ? noop : _props$onSearch,
53
63
  _props$size = props.size,
54
64
  size = _props$size === void 0 ? _constants.defaultEmojiPickerSize : _props$size,
55
65
  query = props.query,
@@ -92,16 +102,52 @@ var EmojiPickerVirtualListInternal = exports.EmojiPickerVirtualListInternal = /*
92
102
  _useState8 = (0, _slicedToArray2.default)(_useState7, 2),
93
103
  categoriesChanged = _useState8[0],
94
104
  setCategoriesChanged = _useState8[1];
105
+ var isTeamojiExperimentEnabled = _featureGateJsClient.default.getExperimentValue(teamojiRefreshExperimentName, 'isEnabled', false);
106
+ var addToCategoryMap = (0, _react.useCallback)(function (categoryToGroupMap, emoji, category) {
107
+ if (!categoryToGroupMap[category]) {
108
+ var categoryDefinition = isTeamojiExperimentEnabled ? _categories.CategoryDescriptionMapNew[category] : _categories.CategoryDescriptionMap[category];
109
+ categoryToGroupMap[category] = {
110
+ emojis: [],
111
+ title: categoryDefinition.name,
112
+ category: category,
113
+ order: categoryDefinition.order
114
+ };
115
+ }
116
+ categoryToGroupMap[category].emojis.push(emoji);
117
+ return categoryToGroupMap;
118
+ }, [isTeamojiExperimentEnabled]);
95
119
  var groupByCategory = (0, _react.useCallback)(function (currentUser) {
96
120
  return function (categoryToGroupMap, emoji) {
97
- addToCategoryMap(categoryToGroupMap, emoji, emoji.category);
121
+ if (isTeamojiExperimentEnabled && emoji.type === 'ATLASSIAN' && emoji.category !== _constants.frequentCategory) {
122
+ addToCategoryMap(categoryToGroupMap, emoji, atlassianCategory);
123
+ var group = categoryToGroupMap[atlassianCategory];
124
+ if (group) {
125
+ if (!group.subcategories) {
126
+ group.subcategories = [];
127
+ }
128
+ var subcategoryTitle = getAtlassianSubcategoryTitle(emoji.category);
129
+ var subcategory = group.subcategories.find(function (existingSubcategory) {
130
+ return existingSubcategory.title === subcategoryTitle;
131
+ });
132
+ if (!subcategory) {
133
+ subcategory = {
134
+ title: subcategoryTitle,
135
+ emojis: []
136
+ };
137
+ group.subcategories.push(subcategory);
138
+ }
139
+ subcategory.emojis.push(emoji);
140
+ }
141
+ } else {
142
+ addToCategoryMap(categoryToGroupMap, emoji, emoji.category);
143
+ }
98
144
  // separate user emojis
99
145
  if (emoji.category === _constants.customCategory && currentUser && emoji.creatorUserId === currentUser.id) {
100
146
  addToCategoryMap(categoryToGroupMap, emoji, _constants.yourUploadsCategory);
101
147
  }
102
148
  return categoryToGroupMap;
103
149
  };
104
- }, []);
150
+ }, [addToCategoryMap, isTeamojiExperimentEnabled]);
105
151
 
106
152
  /**
107
153
  * onRowsRendered callback function
@@ -138,49 +184,72 @@ var EmojiPickerVirtualListInternal = exports.EmojiPickerVirtualListInternal = /*
138
184
  return categoryToGroupMap[key];
139
185
  }).map(function (group) {
140
186
  if (group.category !== _constants.frequentCategory) {
187
+ var _group$subcategories;
141
188
  group.emojis.sort(byOrder);
189
+ (_group$subcategories = group.subcategories) === null || _group$subcategories === void 0 || _group$subcategories.forEach(function (subcategory) {
190
+ subcategory.emojis.sort(byOrder);
191
+ });
142
192
  }
143
193
  return group;
144
194
  }).sort(byOrder));
145
195
  }, [groupByCategory]);
146
- var addToCategoryMap = function addToCategoryMap(categoryToGroupMap, emoji, category) {
147
- if (!categoryToGroupMap[category]) {
148
- var categoryDefinition = _featureGateJsClient.default.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? _categories.CategoryDescriptionMapNew[category] : _categories.CategoryDescriptionMap[category];
149
- categoryToGroupMap[category] = {
150
- emojis: [],
151
- title: categoryDefinition.name,
152
- category: category,
153
- order: categoryDefinition.order
154
- };
155
- }
156
- categoryToGroupMap[category].emojis.push(emoji);
157
- return categoryToGroupMap;
158
- };
159
- var buildVirtualItemFromGroup = (0, _react.useCallback)(function (group) {
160
- var items = [];
161
- items.push(new _EmojiPickerVirtualItems.CategoryHeadingItem({
162
- id: group.category,
163
- title: group.title,
164
- className: categoryClassname
165
- }));
166
- var remainingEmojis = group.emojis;
196
+ var buildEmojiRows = (0, _react.useCallback)(function (items, category, title, emojis, showDelete) {
197
+ var remainingEmojis = emojis;
167
198
  while (remainingEmojis.length > 0) {
168
199
  var rowEmojis = remainingEmojis.slice(0, _EmojiPickerSizes.sizes.emojiPerRow);
169
200
  remainingEmojis = remainingEmojis.slice(_EmojiPickerSizes.sizes.emojiPerRow);
170
201
  items.push(new _EmojiPickerVirtualItems.EmojisRowItem({
171
- category: group.category,
202
+ category: category,
172
203
  emojis: rowEmojis,
173
- title: group.title,
174
- showDelete: group.title === _constants.userCustomTitle,
204
+ title: title,
205
+ showDelete: showDelete,
175
206
  onSelected: onEmojiSelected,
176
207
  onDelete: onEmojiDelete,
177
208
  onMouseMove: onEmojiActive,
178
209
  onFocus: onEmojiActive,
179
- onMouseLeave: _featureGateJsClient.default.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? onEmojiLeave : undefined
210
+ onMouseLeave: isTeamojiExperimentEnabled ? onEmojiLeave : undefined
211
+ }));
212
+ }
213
+ }, [isTeamojiExperimentEnabled, onEmojiActive, onEmojiDelete, onEmojiLeave, onEmojiSelected]);
214
+ var buildVirtualItemFromGroup = (0, _react.useCallback)(function (group) {
215
+ var _group$subcategories2;
216
+ var items = [];
217
+ var hasAtlassianSubcategories = isTeamojiExperimentEnabled && group.category === atlassianCategory && !!((_group$subcategories2 = group.subcategories) !== null && _group$subcategories2 !== void 0 && _group$subcategories2.length);
218
+ if (!hasAtlassianSubcategories) {
219
+ items.push(new _EmojiPickerVirtualItems.CategoryHeadingItem({
220
+ id: group.category,
221
+ title: group.title,
222
+ className: categoryClassname
180
223
  }));
181
224
  }
225
+ if (hasAtlassianSubcategories && group.subcategories) {
226
+ var sortedSubcategories = (0, _toConsumableArray2.default)(group.subcategories).sort(function (a, b) {
227
+ var aIndex = atlassianSubcategoryOrder.indexOf(a.title);
228
+ var bIndex = atlassianSubcategoryOrder.indexOf(b.title);
229
+ if (aIndex !== -1 && bIndex !== -1) {
230
+ return aIndex - bIndex;
231
+ }
232
+ if (aIndex !== -1) {
233
+ return -1;
234
+ }
235
+ if (bIndex !== -1) {
236
+ return 1;
237
+ }
238
+ return a.title.localeCompare(b.title);
239
+ });
240
+ sortedSubcategories.forEach(function (subcategory) {
241
+ items.push(new _EmojiPickerVirtualItems.CategoryHeadingItem({
242
+ id: group.category,
243
+ title: subcategory.title,
244
+ className: categoryClassname
245
+ }));
246
+ buildEmojiRows(items, group.category, subcategory.title, subcategory.emojis, false);
247
+ });
248
+ } else {
249
+ buildEmojiRows(items, group.category, group.title, group.emojis, group.title === _constants.userCustomTitle);
250
+ }
182
251
  return items;
183
- }, [onEmojiSelected, onEmojiDelete, onEmojiActive, onEmojiLeave]);
252
+ }, [buildEmojiRows, isTeamojiExperimentEnabled]);
184
253
  var buildVirtualItems = (0, _react.useCallback)(function () {
185
254
  var items = [];
186
255
  var prevFirstCategory = categoryTracker.getFirstCategory();
@@ -189,8 +258,8 @@ var EmojiPickerVirtualListInternal = exports.EmojiPickerVirtualListInternal = /*
189
258
  items.push(new _EmojiPickerVirtualItems.LoadingItem());
190
259
  } else {
191
260
  if (query) {
192
- var search = _featureGateJsClient.default.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? _categories.CategoryDescriptionMapNew.SEARCH : _categories.CategoryDescriptionMap.SEARCH;
193
- if (emojis.length === 0 && _featureGateJsClient.default.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false)) {
261
+ var search = isTeamojiExperimentEnabled ? _categories.CategoryDescriptionMapNew.SEARCH : _categories.CategoryDescriptionMap.SEARCH;
262
+ if (emojis.length === 0 && isTeamojiExperimentEnabled) {
194
263
  // Show a "No results" category heading, then a no-results illustration below it
195
264
  items.push(new _EmojiPickerVirtualItems.CategoryHeadingItem({
196
265
  id: _constants.searchCategory,
@@ -217,7 +286,7 @@ var EmojiPickerVirtualListInternal = exports.EmojiPickerVirtualListInternal = /*
217
286
  allEmojiGroups.forEach(function (group) {
218
287
  // Optimisation - avoid re-rendering unaffected groups for the current selectedShortcut
219
288
  // by not passing it to irrelevant groups
220
- categoryTracker.add(group.emojis[0].category, items.length);
289
+ categoryTracker.add(isTeamojiExperimentEnabled ? group.category : group.emojis[0].category, items.length);
221
290
  items = [].concat((0, _toConsumableArray2.default)(items), (0, _toConsumableArray2.default)(buildVirtualItemFromGroup(group)));
222
291
  if (group.category === _constants.yourUploadsCategory) {
223
292
  setLastYourUploadsRow(items.length - 1);
@@ -234,7 +303,7 @@ var EmojiPickerVirtualListInternal = exports.EmojiPickerVirtualListInternal = /*
234
303
  }
235
304
  }
236
305
  // eslint-disable-next-line react-hooks/exhaustive-deps
237
- }, [allEmojiGroups, loading, query, emojis, onOpenUpload, uploadEnabled, formatMessage]);
306
+ }, [allEmojiGroups, buildVirtualItemFromGroup, emojis, formatMessage, isTeamojiExperimentEnabled, loading, onOpenUpload, query, uploadEnabled]);
238
307
  var findCategoryToActivate = function findCategoryToActivate(row) {
239
308
  var category = null;
240
309
  if (row instanceof _EmojiPickerVirtualItems.CategoryHeadingItem) {
@@ -344,12 +413,12 @@ var EmojiPickerVirtualListInternal = exports.EmojiPickerVirtualListInternal = /*
344
413
  // eslint-disable-next-line react-hooks/exhaustive-deps
345
414
  }, [virtualItems, categoriesChanged]);
346
415
  var virtualListHeight = (0, _react.useMemo)(function () {
347
- if (query && emojis.length === 0 && _featureGateJsClient.default.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false)) {
416
+ if (query && emojis.length === 0 && isTeamojiExperimentEnabled) {
348
417
  // No-results state: expand the list height to fit heading + illustration without scrolling
349
418
  return _EmojiPickerSizes.sizes.categoryHeadingHeight + _EmojiPickerSizes.sizes.noResultsHeight + (0, _utils.emojiPickerHeightOffset)(size);
350
419
  }
351
- return _featureGateJsClient.default.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? _EmojiPickerSizes.sizes.listHeightNew + (0, _utils.emojiPickerHeightOffset)(size) : _EmojiPickerSizes.sizes.listHeight + (0, _utils.emojiPickerHeightOffset)(size);
352
- }, [size, query, emojis.length]);
420
+ return isTeamojiExperimentEnabled ? _EmojiPickerSizes.sizes.listHeightNew + (0, _utils.emojiPickerHeightOffset)(size) : _EmojiPickerSizes.sizes.listHeight + (0, _utils.emojiPickerHeightOffset)(size);
421
+ }, [size, query, emojis.length, isTeamojiExperimentEnabled]);
353
422
  return /*#__PURE__*/_react.default.createElement(_EmojiPickerTabPanel.default, {
354
423
  showSearchResults: !!query
355
424
  }, /*#__PURE__*/_react.default.createElement(_EmojiActions.default, {
@@ -20,7 +20,7 @@ var createEvent = function createEvent(eventType, action, actionSubject, actionS
20
20
  actionSubjectId: actionSubjectId,
21
21
  attributes: _objectSpread({
22
22
  packageName: "@atlaskit/emoji",
23
- packageVersion: "70.16.4"
23
+ packageVersion: "70.16.6"
24
24
  }, attributes)
25
25
  };
26
26
  };
@@ -7,6 +7,7 @@ import { tokenizerRegex } from './EmojiRepositoryRegex';
7
7
  import { createSearchEmojiComparator, createUsageOnlyEmojiComparator } from './internal/Comparators';
8
8
  import { UsageFrequencyTracker } from './internal/UsageFrequencyTracker';
9
9
  import { fg } from '@atlaskit/platform-feature-flags';
10
+ import { expVal } from '@atlaskit/tmp-editor-statsig/expVal';
10
11
  // FS-1097 - duplicated in mentions - extract at some point into a shared library
11
12
  class Tokenizer {
12
13
  tokenize(text) {
@@ -91,6 +92,7 @@ const findEmojiIndex = (emojis, toFind) => {
91
92
  });
92
93
  return match;
93
94
  };
95
+ const teamojiRefreshExperimentName = 'platform_teamoji_26_refresh_emoji_picker';
94
96
  export default class EmojiRepository {
95
97
  // protected to allow subclasses to access (for testing and storybooks).
96
98
 
@@ -166,6 +168,8 @@ export default class EmojiRepository {
166
168
  findInCategory(categoryId) {
167
169
  if (categoryId === frequentCategory) {
168
170
  return this.getFrequentlyUsed();
171
+ } else if (expVal(teamojiRefreshExperimentName, 'isEnabled', false) && categoryId === 'ATLASSIAN') {
172
+ return this.all().emojis.filter(emoji => emoji.type === 'ATLASSIAN');
169
173
  } else {
170
174
  return this.all().emojis.filter(emoji => emoji.category === categoryId);
171
175
  }
@@ -284,7 +288,7 @@ export default class EmojiRepository {
284
288
  this.asciiMap = new Map();
285
289
  const categorySet = new Set();
286
290
  this.emojis.forEach(emoji => {
287
- categorySet.add(emoji.category);
291
+ categorySet.add(this.getDynamicCategoryForEmoji(emoji, expVal(teamojiRefreshExperimentName, 'isEnabled', false)));
288
292
  this.addToMaps(emoji);
289
293
  });
290
294
  if (this.usageTracker.getOrder().length) {
@@ -325,10 +329,17 @@ export default class EmojiRepository {
325
329
  }
326
330
  }
327
331
  addToDynamicCategories(emoji) {
328
- const category = getCategoryId(emoji);
332
+ const category = this.getDynamicCategoryForEmoji(emoji, expVal(teamojiRefreshExperimentName, 'isEnabled', false));
329
333
  if (defaultCategories.indexOf(category) === -1 && this.dynamicCategoryList.indexOf(category) === -1) {
330
334
  this.dynamicCategoryList.push(category);
331
335
  }
332
336
  }
337
+ getDynamicCategoryForEmoji(emoji, isTeamojiRefreshEnabled) {
338
+ const category = getCategoryId(emoji);
339
+ if (isTeamojiRefreshEnabled && emoji.type === 'ATLASSIAN' && category !== frequentCategory) {
340
+ return 'ATLASSIAN';
341
+ }
342
+ return category;
343
+ }
333
344
  }
334
345
  _defineProperty(EmojiRepository, "defaultEmojiWeight", 1000000);
@@ -18,22 +18,32 @@ import { messages } from '../i18n';
18
18
  */
19
19
  export const RENDER_EMOJI_PICKER_LIST_TESTID = 'render-emoji-picker-list';
20
20
  const categoryClassname = 'emoji-category';
21
+ const teamojiRefreshExperimentName = 'platform_teamoji_26_refresh_emoji_picker';
22
+ const atlassianCategory = 'ATLASSIAN';
23
+ const atlassianSubcategoryOrder = ['Faces', 'Hands', 'Reactions', 'Objects', 'Productivity', 'Logos'];
21
24
 
22
25
  /**
23
26
  * Emoji grouped by a category title ie. Frequent, Your Uploads, All Uploads
24
27
  */
25
28
 
26
29
  const byOrder = (orderableA, orderableB) => (orderableA.order || 0) - (orderableB.order || 0);
30
+ const noop = () => {};
31
+ const getAtlassianSubcategoryTitle = category => {
32
+ if (!category) {
33
+ return 'Other';
34
+ }
35
+ return category.charAt(0).toUpperCase() + category.slice(1).toLowerCase();
36
+ };
27
37
  export const EmojiPickerVirtualListInternal = /*#__PURE__*/React.forwardRef((props, ref) => {
28
38
  const {
29
39
  emojis,
30
40
  currentUser,
31
- onEmojiSelected = () => {},
32
- onEmojiActive = () => {},
41
+ onEmojiSelected = noop,
42
+ onEmojiActive = noop,
33
43
  onEmojiLeave,
34
- onEmojiDelete = () => {},
35
- onCategoryActivated = () => {},
36
- onSearch = () => {},
44
+ onEmojiDelete = noop,
45
+ onCategoryActivated = noop,
46
+ onSearch = noop,
37
47
  size = defaultEmojiPickerSize,
38
48
  query,
39
49
  loading,
@@ -63,14 +73,48 @@ export const EmojiPickerVirtualListInternal = /*#__PURE__*/React.forwardRef((pro
63
73
  const [lastYourUploadsRow, setLastYourUploadsRow] = useState(0);
64
74
  const categoryTracker = useMemo(() => new CategoryTracker(), []);
65
75
  const [categoriesChanged, setCategoriesChanged] = useState(false);
76
+ const isTeamojiExperimentEnabled = FeatureGates.getExperimentValue(teamojiRefreshExperimentName, 'isEnabled', false);
77
+ const addToCategoryMap = useCallback((categoryToGroupMap, emoji, category) => {
78
+ if (!categoryToGroupMap[category]) {
79
+ const categoryDefinition = isTeamojiExperimentEnabled ? CategoryDescriptionMapNew[category] : CategoryDescriptionMap[category];
80
+ categoryToGroupMap[category] = {
81
+ emojis: [],
82
+ title: categoryDefinition.name,
83
+ category,
84
+ order: categoryDefinition.order
85
+ };
86
+ }
87
+ categoryToGroupMap[category].emojis.push(emoji);
88
+ return categoryToGroupMap;
89
+ }, [isTeamojiExperimentEnabled]);
66
90
  const groupByCategory = useCallback(currentUser => (categoryToGroupMap, emoji) => {
67
- addToCategoryMap(categoryToGroupMap, emoji, emoji.category);
91
+ if (isTeamojiExperimentEnabled && emoji.type === 'ATLASSIAN' && emoji.category !== frequentCategory) {
92
+ addToCategoryMap(categoryToGroupMap, emoji, atlassianCategory);
93
+ const group = categoryToGroupMap[atlassianCategory];
94
+ if (group) {
95
+ if (!group.subcategories) {
96
+ group.subcategories = [];
97
+ }
98
+ const subcategoryTitle = getAtlassianSubcategoryTitle(emoji.category);
99
+ let subcategory = group.subcategories.find(existingSubcategory => existingSubcategory.title === subcategoryTitle);
100
+ if (!subcategory) {
101
+ subcategory = {
102
+ title: subcategoryTitle,
103
+ emojis: []
104
+ };
105
+ group.subcategories.push(subcategory);
106
+ }
107
+ subcategory.emojis.push(emoji);
108
+ }
109
+ } else {
110
+ addToCategoryMap(categoryToGroupMap, emoji, emoji.category);
111
+ }
68
112
  // separate user emojis
69
113
  if (emoji.category === customCategory && currentUser && emoji.creatorUserId === currentUser.id) {
70
114
  addToCategoryMap(categoryToGroupMap, emoji, yourUploadsCategory);
71
115
  }
72
116
  return categoryToGroupMap;
73
- }, []);
117
+ }, [addToCategoryMap, isTeamojiExperimentEnabled]);
74
118
 
75
119
  /**
76
120
  * onRowsRendered callback function
@@ -107,49 +151,72 @@ export const EmojiPickerVirtualListInternal = /*#__PURE__*/React.forwardRef((pro
107
151
  const categoryToGroupMap = emojis.reduce(groupByCategory(currentUser), {});
108
152
  setAllEmojiGroups(Object.keys(categoryToGroupMap).map(key => categoryToGroupMap[key]).map(group => {
109
153
  if (group.category !== frequentCategory) {
154
+ var _group$subcategories;
110
155
  group.emojis.sort(byOrder);
156
+ (_group$subcategories = group.subcategories) === null || _group$subcategories === void 0 ? void 0 : _group$subcategories.forEach(subcategory => {
157
+ subcategory.emojis.sort(byOrder);
158
+ });
111
159
  }
112
160
  return group;
113
161
  }).sort(byOrder));
114
162
  }, [groupByCategory]);
115
- const addToCategoryMap = (categoryToGroupMap, emoji, category) => {
116
- if (!categoryToGroupMap[category]) {
117
- const categoryDefinition = FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? CategoryDescriptionMapNew[category] : CategoryDescriptionMap[category];
118
- categoryToGroupMap[category] = {
119
- emojis: [],
120
- title: categoryDefinition.name,
121
- category,
122
- order: categoryDefinition.order
123
- };
124
- }
125
- categoryToGroupMap[category].emojis.push(emoji);
126
- return categoryToGroupMap;
127
- };
128
- const buildVirtualItemFromGroup = useCallback(group => {
129
- const items = [];
130
- items.push(new CategoryHeadingItem({
131
- id: group.category,
132
- title: group.title,
133
- className: categoryClassname
134
- }));
135
- let remainingEmojis = group.emojis;
163
+ const buildEmojiRows = useCallback((items, category, title, emojis, showDelete) => {
164
+ let remainingEmojis = emojis;
136
165
  while (remainingEmojis.length > 0) {
137
166
  const rowEmojis = remainingEmojis.slice(0, sizes.emojiPerRow);
138
167
  remainingEmojis = remainingEmojis.slice(sizes.emojiPerRow);
139
168
  items.push(new EmojisRowItem({
140
- category: group.category,
169
+ category,
141
170
  emojis: rowEmojis,
142
- title: group.title,
143
- showDelete: group.title === userCustomTitle,
171
+ title,
172
+ showDelete,
144
173
  onSelected: onEmojiSelected,
145
174
  onDelete: onEmojiDelete,
146
175
  onMouseMove: onEmojiActive,
147
176
  onFocus: onEmojiActive,
148
- onMouseLeave: FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? onEmojiLeave : undefined
177
+ onMouseLeave: isTeamojiExperimentEnabled ? onEmojiLeave : undefined
149
178
  }));
150
179
  }
180
+ }, [isTeamojiExperimentEnabled, onEmojiActive, onEmojiDelete, onEmojiLeave, onEmojiSelected]);
181
+ const buildVirtualItemFromGroup = useCallback(group => {
182
+ var _group$subcategories2;
183
+ const items = [];
184
+ const hasAtlassianSubcategories = isTeamojiExperimentEnabled && group.category === atlassianCategory && !!((_group$subcategories2 = group.subcategories) !== null && _group$subcategories2 !== void 0 && _group$subcategories2.length);
185
+ if (!hasAtlassianSubcategories) {
186
+ items.push(new CategoryHeadingItem({
187
+ id: group.category,
188
+ title: group.title,
189
+ className: categoryClassname
190
+ }));
191
+ }
192
+ if (hasAtlassianSubcategories && group.subcategories) {
193
+ const sortedSubcategories = [...group.subcategories].sort((a, b) => {
194
+ const aIndex = atlassianSubcategoryOrder.indexOf(a.title);
195
+ const bIndex = atlassianSubcategoryOrder.indexOf(b.title);
196
+ if (aIndex !== -1 && bIndex !== -1) {
197
+ return aIndex - bIndex;
198
+ }
199
+ if (aIndex !== -1) {
200
+ return -1;
201
+ }
202
+ if (bIndex !== -1) {
203
+ return 1;
204
+ }
205
+ return a.title.localeCompare(b.title);
206
+ });
207
+ sortedSubcategories.forEach(subcategory => {
208
+ items.push(new CategoryHeadingItem({
209
+ id: group.category,
210
+ title: subcategory.title,
211
+ className: categoryClassname
212
+ }));
213
+ buildEmojiRows(items, group.category, subcategory.title, subcategory.emojis, false);
214
+ });
215
+ } else {
216
+ buildEmojiRows(items, group.category, group.title, group.emojis, group.title === userCustomTitle);
217
+ }
151
218
  return items;
152
- }, [onEmojiSelected, onEmojiDelete, onEmojiActive, onEmojiLeave]);
219
+ }, [buildEmojiRows, isTeamojiExperimentEnabled]);
153
220
  const buildVirtualItems = useCallback(() => {
154
221
  let items = [];
155
222
  const prevFirstCategory = categoryTracker.getFirstCategory();
@@ -158,8 +225,8 @@ export const EmojiPickerVirtualListInternal = /*#__PURE__*/React.forwardRef((pro
158
225
  items.push(new LoadingItem());
159
226
  } else {
160
227
  if (query) {
161
- const search = FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? CategoryDescriptionMapNew.SEARCH : CategoryDescriptionMap.SEARCH;
162
- if (emojis.length === 0 && FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false)) {
228
+ const search = isTeamojiExperimentEnabled ? CategoryDescriptionMapNew.SEARCH : CategoryDescriptionMap.SEARCH;
229
+ if (emojis.length === 0 && isTeamojiExperimentEnabled) {
163
230
  // Show a "No results" category heading, then a no-results illustration below it
164
231
  items.push(new CategoryHeadingItem({
165
232
  id: searchCategory,
@@ -186,7 +253,7 @@ export const EmojiPickerVirtualListInternal = /*#__PURE__*/React.forwardRef((pro
186
253
  allEmojiGroups.forEach(group => {
187
254
  // Optimisation - avoid re-rendering unaffected groups for the current selectedShortcut
188
255
  // by not passing it to irrelevant groups
189
- categoryTracker.add(group.emojis[0].category, items.length);
256
+ categoryTracker.add(isTeamojiExperimentEnabled ? group.category : group.emojis[0].category, items.length);
190
257
  items = [...items, ...buildVirtualItemFromGroup(group)];
191
258
  if (group.category === yourUploadsCategory) {
192
259
  setLastYourUploadsRow(items.length - 1);
@@ -203,7 +270,7 @@ export const EmojiPickerVirtualListInternal = /*#__PURE__*/React.forwardRef((pro
203
270
  }
204
271
  }
205
272
  // eslint-disable-next-line react-hooks/exhaustive-deps
206
- }, [allEmojiGroups, loading, query, emojis, onOpenUpload, uploadEnabled, formatMessage]);
273
+ }, [allEmojiGroups, buildVirtualItemFromGroup, emojis, formatMessage, isTeamojiExperimentEnabled, loading, onOpenUpload, query, uploadEnabled]);
207
274
  const findCategoryToActivate = row => {
208
275
  let category = null;
209
276
  if (row instanceof CategoryHeadingItem) {
@@ -312,12 +379,12 @@ export const EmojiPickerVirtualListInternal = /*#__PURE__*/React.forwardRef((pro
312
379
  // eslint-disable-next-line react-hooks/exhaustive-deps
313
380
  }, [virtualItems, categoriesChanged]);
314
381
  const virtualListHeight = useMemo(() => {
315
- if (query && emojis.length === 0 && FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false)) {
382
+ if (query && emojis.length === 0 && isTeamojiExperimentEnabled) {
316
383
  // No-results state: expand the list height to fit heading + illustration without scrolling
317
384
  return sizes.categoryHeadingHeight + sizes.noResultsHeight + emojiPickerHeightOffset(size);
318
385
  }
319
- return FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? sizes.listHeightNew + emojiPickerHeightOffset(size) : sizes.listHeight + emojiPickerHeightOffset(size);
320
- }, [size, query, emojis.length]);
386
+ return isTeamojiExperimentEnabled ? sizes.listHeightNew + emojiPickerHeightOffset(size) : sizes.listHeight + emojiPickerHeightOffset(size);
387
+ }, [size, query, emojis.length, isTeamojiExperimentEnabled]);
321
388
  return /*#__PURE__*/React.createElement(EmojiPickerTabPanel, {
322
389
  showSearchResults: !!query
323
390
  }, /*#__PURE__*/React.createElement(EmojiActions, {
@@ -9,7 +9,7 @@ const createEvent = (eventType, action, actionSubject, actionSubjectId, attribut
9
9
  actionSubjectId,
10
10
  attributes: {
11
11
  packageName: "@atlaskit/emoji",
12
- packageVersion: "70.16.4",
12
+ packageVersion: "70.16.6",
13
13
  ...attributes
14
14
  }
15
15
  });
@@ -10,6 +10,7 @@ import { tokenizerRegex } from './EmojiRepositoryRegex';
10
10
  import { createSearchEmojiComparator, createUsageOnlyEmojiComparator } from './internal/Comparators';
11
11
  import { UsageFrequencyTracker } from './internal/UsageFrequencyTracker';
12
12
  import { fg } from '@atlaskit/platform-feature-flags';
13
+ import { expVal } from '@atlaskit/tmp-editor-statsig/expVal';
13
14
  // FS-1097 - duplicated in mentions - extract at some point into a shared library
14
15
  var Tokenizer = /*#__PURE__*/function () {
15
16
  function Tokenizer() {
@@ -107,6 +108,7 @@ var findEmojiIndex = function findEmojiIndex(emojis, toFind) {
107
108
  });
108
109
  return match;
109
110
  };
111
+ var teamojiRefreshExperimentName = 'platform_teamoji_26_refresh_emoji_picker';
110
112
  var EmojiRepository = /*#__PURE__*/function () {
111
113
  // protected to allow subclasses to access (for testing and storybooks).
112
114
 
@@ -196,6 +198,10 @@ var EmojiRepository = /*#__PURE__*/function () {
196
198
  value: function findInCategory(categoryId) {
197
199
  if (categoryId === frequentCategory) {
198
200
  return this.getFrequentlyUsed();
201
+ } else if (expVal(teamojiRefreshExperimentName, 'isEnabled', false) && categoryId === 'ATLASSIAN') {
202
+ return this.all().emojis.filter(function (emoji) {
203
+ return emoji.type === 'ATLASSIAN';
204
+ });
199
205
  } else {
200
206
  return this.all().emojis.filter(function (emoji) {
201
207
  return emoji.category === categoryId;
@@ -345,7 +351,7 @@ var EmojiRepository = /*#__PURE__*/function () {
345
351
  this.asciiMap = new Map();
346
352
  var categorySet = new Set();
347
353
  this.emojis.forEach(function (emoji) {
348
- categorySet.add(emoji.category);
354
+ categorySet.add(_this3.getDynamicCategoryForEmoji(emoji, expVal(teamojiRefreshExperimentName, 'isEnabled', false)));
349
355
  _this3.addToMaps(emoji);
350
356
  });
351
357
  if (this.usageTracker.getOrder().length) {
@@ -407,11 +413,20 @@ var EmojiRepository = /*#__PURE__*/function () {
407
413
  }, {
408
414
  key: "addToDynamicCategories",
409
415
  value: function addToDynamicCategories(emoji) {
410
- var category = getCategoryId(emoji);
416
+ var category = this.getDynamicCategoryForEmoji(emoji, expVal(teamojiRefreshExperimentName, 'isEnabled', false));
411
417
  if (defaultCategories.indexOf(category) === -1 && this.dynamicCategoryList.indexOf(category) === -1) {
412
418
  this.dynamicCategoryList.push(category);
413
419
  }
414
420
  }
421
+ }, {
422
+ key: "getDynamicCategoryForEmoji",
423
+ value: function getDynamicCategoryForEmoji(emoji, isTeamojiRefreshEnabled) {
424
+ var category = getCategoryId(emoji);
425
+ if (isTeamojiRefreshEnabled && emoji.type === 'ATLASSIAN' && category !== frequentCategory) {
426
+ return 'ATLASSIAN';
427
+ }
428
+ return category;
429
+ }
415
430
  }]);
416
431
  }();
417
432
  _defineProperty(EmojiRepository, "defaultEmojiWeight", 1000000);
@@ -20,6 +20,9 @@ import { messages } from '../i18n';
20
20
  */
21
21
  export var RENDER_EMOJI_PICKER_LIST_TESTID = 'render-emoji-picker-list';
22
22
  var categoryClassname = 'emoji-category';
23
+ var teamojiRefreshExperimentName = 'platform_teamoji_26_refresh_emoji_picker';
24
+ var atlassianCategory = 'ATLASSIAN';
25
+ var atlassianSubcategoryOrder = ['Faces', 'Hands', 'Reactions', 'Objects', 'Productivity', 'Logos'];
23
26
 
24
27
  /**
25
28
  * Emoji grouped by a category title ie. Frequent, Your Uploads, All Uploads
@@ -28,20 +31,27 @@ var categoryClassname = 'emoji-category';
28
31
  var byOrder = function byOrder(orderableA, orderableB) {
29
32
  return (orderableA.order || 0) - (orderableB.order || 0);
30
33
  };
34
+ var noop = function noop() {};
35
+ var getAtlassianSubcategoryTitle = function getAtlassianSubcategoryTitle(category) {
36
+ if (!category) {
37
+ return 'Other';
38
+ }
39
+ return category.charAt(0).toUpperCase() + category.slice(1).toLowerCase();
40
+ };
31
41
  export var EmojiPickerVirtualListInternal = /*#__PURE__*/React.forwardRef(function (props, ref) {
32
42
  var emojis = props.emojis,
33
43
  currentUser = props.currentUser,
34
44
  _props$onEmojiSelecte = props.onEmojiSelected,
35
- onEmojiSelected = _props$onEmojiSelecte === void 0 ? function () {} : _props$onEmojiSelecte,
45
+ onEmojiSelected = _props$onEmojiSelecte === void 0 ? noop : _props$onEmojiSelecte,
36
46
  _props$onEmojiActive = props.onEmojiActive,
37
- onEmojiActive = _props$onEmojiActive === void 0 ? function () {} : _props$onEmojiActive,
47
+ onEmojiActive = _props$onEmojiActive === void 0 ? noop : _props$onEmojiActive,
38
48
  onEmojiLeave = props.onEmojiLeave,
39
49
  _props$onEmojiDelete = props.onEmojiDelete,
40
- onEmojiDelete = _props$onEmojiDelete === void 0 ? function () {} : _props$onEmojiDelete,
50
+ onEmojiDelete = _props$onEmojiDelete === void 0 ? noop : _props$onEmojiDelete,
41
51
  _props$onCategoryActi = props.onCategoryActivated,
42
- onCategoryActivated = _props$onCategoryActi === void 0 ? function () {} : _props$onCategoryActi,
52
+ onCategoryActivated = _props$onCategoryActi === void 0 ? noop : _props$onCategoryActi,
43
53
  _props$onSearch = props.onSearch,
44
- onSearch = _props$onSearch === void 0 ? function () {} : _props$onSearch,
54
+ onSearch = _props$onSearch === void 0 ? noop : _props$onSearch,
45
55
  _props$size = props.size,
46
56
  size = _props$size === void 0 ? defaultEmojiPickerSize : _props$size,
47
57
  query = props.query,
@@ -84,16 +94,52 @@ export var EmojiPickerVirtualListInternal = /*#__PURE__*/React.forwardRef(functi
84
94
  _useState8 = _slicedToArray(_useState7, 2),
85
95
  categoriesChanged = _useState8[0],
86
96
  setCategoriesChanged = _useState8[1];
97
+ var isTeamojiExperimentEnabled = FeatureGates.getExperimentValue(teamojiRefreshExperimentName, 'isEnabled', false);
98
+ var addToCategoryMap = useCallback(function (categoryToGroupMap, emoji, category) {
99
+ if (!categoryToGroupMap[category]) {
100
+ var categoryDefinition = isTeamojiExperimentEnabled ? CategoryDescriptionMapNew[category] : CategoryDescriptionMap[category];
101
+ categoryToGroupMap[category] = {
102
+ emojis: [],
103
+ title: categoryDefinition.name,
104
+ category: category,
105
+ order: categoryDefinition.order
106
+ };
107
+ }
108
+ categoryToGroupMap[category].emojis.push(emoji);
109
+ return categoryToGroupMap;
110
+ }, [isTeamojiExperimentEnabled]);
87
111
  var groupByCategory = useCallback(function (currentUser) {
88
112
  return function (categoryToGroupMap, emoji) {
89
- addToCategoryMap(categoryToGroupMap, emoji, emoji.category);
113
+ if (isTeamojiExperimentEnabled && emoji.type === 'ATLASSIAN' && emoji.category !== frequentCategory) {
114
+ addToCategoryMap(categoryToGroupMap, emoji, atlassianCategory);
115
+ var group = categoryToGroupMap[atlassianCategory];
116
+ if (group) {
117
+ if (!group.subcategories) {
118
+ group.subcategories = [];
119
+ }
120
+ var subcategoryTitle = getAtlassianSubcategoryTitle(emoji.category);
121
+ var subcategory = group.subcategories.find(function (existingSubcategory) {
122
+ return existingSubcategory.title === subcategoryTitle;
123
+ });
124
+ if (!subcategory) {
125
+ subcategory = {
126
+ title: subcategoryTitle,
127
+ emojis: []
128
+ };
129
+ group.subcategories.push(subcategory);
130
+ }
131
+ subcategory.emojis.push(emoji);
132
+ }
133
+ } else {
134
+ addToCategoryMap(categoryToGroupMap, emoji, emoji.category);
135
+ }
90
136
  // separate user emojis
91
137
  if (emoji.category === customCategory && currentUser && emoji.creatorUserId === currentUser.id) {
92
138
  addToCategoryMap(categoryToGroupMap, emoji, yourUploadsCategory);
93
139
  }
94
140
  return categoryToGroupMap;
95
141
  };
96
- }, []);
142
+ }, [addToCategoryMap, isTeamojiExperimentEnabled]);
97
143
 
98
144
  /**
99
145
  * onRowsRendered callback function
@@ -130,49 +176,72 @@ export var EmojiPickerVirtualListInternal = /*#__PURE__*/React.forwardRef(functi
130
176
  return categoryToGroupMap[key];
131
177
  }).map(function (group) {
132
178
  if (group.category !== frequentCategory) {
179
+ var _group$subcategories;
133
180
  group.emojis.sort(byOrder);
181
+ (_group$subcategories = group.subcategories) === null || _group$subcategories === void 0 || _group$subcategories.forEach(function (subcategory) {
182
+ subcategory.emojis.sort(byOrder);
183
+ });
134
184
  }
135
185
  return group;
136
186
  }).sort(byOrder));
137
187
  }, [groupByCategory]);
138
- var addToCategoryMap = function addToCategoryMap(categoryToGroupMap, emoji, category) {
139
- if (!categoryToGroupMap[category]) {
140
- var categoryDefinition = FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? CategoryDescriptionMapNew[category] : CategoryDescriptionMap[category];
141
- categoryToGroupMap[category] = {
142
- emojis: [],
143
- title: categoryDefinition.name,
144
- category: category,
145
- order: categoryDefinition.order
146
- };
147
- }
148
- categoryToGroupMap[category].emojis.push(emoji);
149
- return categoryToGroupMap;
150
- };
151
- var buildVirtualItemFromGroup = useCallback(function (group) {
152
- var items = [];
153
- items.push(new CategoryHeadingItem({
154
- id: group.category,
155
- title: group.title,
156
- className: categoryClassname
157
- }));
158
- var remainingEmojis = group.emojis;
188
+ var buildEmojiRows = useCallback(function (items, category, title, emojis, showDelete) {
189
+ var remainingEmojis = emojis;
159
190
  while (remainingEmojis.length > 0) {
160
191
  var rowEmojis = remainingEmojis.slice(0, sizes.emojiPerRow);
161
192
  remainingEmojis = remainingEmojis.slice(sizes.emojiPerRow);
162
193
  items.push(new EmojisRowItem({
163
- category: group.category,
194
+ category: category,
164
195
  emojis: rowEmojis,
165
- title: group.title,
166
- showDelete: group.title === userCustomTitle,
196
+ title: title,
197
+ showDelete: showDelete,
167
198
  onSelected: onEmojiSelected,
168
199
  onDelete: onEmojiDelete,
169
200
  onMouseMove: onEmojiActive,
170
201
  onFocus: onEmojiActive,
171
- onMouseLeave: FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? onEmojiLeave : undefined
202
+ onMouseLeave: isTeamojiExperimentEnabled ? onEmojiLeave : undefined
203
+ }));
204
+ }
205
+ }, [isTeamojiExperimentEnabled, onEmojiActive, onEmojiDelete, onEmojiLeave, onEmojiSelected]);
206
+ var buildVirtualItemFromGroup = useCallback(function (group) {
207
+ var _group$subcategories2;
208
+ var items = [];
209
+ var hasAtlassianSubcategories = isTeamojiExperimentEnabled && group.category === atlassianCategory && !!((_group$subcategories2 = group.subcategories) !== null && _group$subcategories2 !== void 0 && _group$subcategories2.length);
210
+ if (!hasAtlassianSubcategories) {
211
+ items.push(new CategoryHeadingItem({
212
+ id: group.category,
213
+ title: group.title,
214
+ className: categoryClassname
172
215
  }));
173
216
  }
217
+ if (hasAtlassianSubcategories && group.subcategories) {
218
+ var sortedSubcategories = _toConsumableArray(group.subcategories).sort(function (a, b) {
219
+ var aIndex = atlassianSubcategoryOrder.indexOf(a.title);
220
+ var bIndex = atlassianSubcategoryOrder.indexOf(b.title);
221
+ if (aIndex !== -1 && bIndex !== -1) {
222
+ return aIndex - bIndex;
223
+ }
224
+ if (aIndex !== -1) {
225
+ return -1;
226
+ }
227
+ if (bIndex !== -1) {
228
+ return 1;
229
+ }
230
+ return a.title.localeCompare(b.title);
231
+ });
232
+ sortedSubcategories.forEach(function (subcategory) {
233
+ items.push(new CategoryHeadingItem({
234
+ id: group.category,
235
+ title: subcategory.title,
236
+ className: categoryClassname
237
+ }));
238
+ buildEmojiRows(items, group.category, subcategory.title, subcategory.emojis, false);
239
+ });
240
+ } else {
241
+ buildEmojiRows(items, group.category, group.title, group.emojis, group.title === userCustomTitle);
242
+ }
174
243
  return items;
175
- }, [onEmojiSelected, onEmojiDelete, onEmojiActive, onEmojiLeave]);
244
+ }, [buildEmojiRows, isTeamojiExperimentEnabled]);
176
245
  var buildVirtualItems = useCallback(function () {
177
246
  var items = [];
178
247
  var prevFirstCategory = categoryTracker.getFirstCategory();
@@ -181,8 +250,8 @@ export var EmojiPickerVirtualListInternal = /*#__PURE__*/React.forwardRef(functi
181
250
  items.push(new LoadingItem());
182
251
  } else {
183
252
  if (query) {
184
- var search = FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? CategoryDescriptionMapNew.SEARCH : CategoryDescriptionMap.SEARCH;
185
- if (emojis.length === 0 && FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false)) {
253
+ var search = isTeamojiExperimentEnabled ? CategoryDescriptionMapNew.SEARCH : CategoryDescriptionMap.SEARCH;
254
+ if (emojis.length === 0 && isTeamojiExperimentEnabled) {
186
255
  // Show a "No results" category heading, then a no-results illustration below it
187
256
  items.push(new CategoryHeadingItem({
188
257
  id: searchCategory,
@@ -209,7 +278,7 @@ export var EmojiPickerVirtualListInternal = /*#__PURE__*/React.forwardRef(functi
209
278
  allEmojiGroups.forEach(function (group) {
210
279
  // Optimisation - avoid re-rendering unaffected groups for the current selectedShortcut
211
280
  // by not passing it to irrelevant groups
212
- categoryTracker.add(group.emojis[0].category, items.length);
281
+ categoryTracker.add(isTeamojiExperimentEnabled ? group.category : group.emojis[0].category, items.length);
213
282
  items = [].concat(_toConsumableArray(items), _toConsumableArray(buildVirtualItemFromGroup(group)));
214
283
  if (group.category === yourUploadsCategory) {
215
284
  setLastYourUploadsRow(items.length - 1);
@@ -226,7 +295,7 @@ export var EmojiPickerVirtualListInternal = /*#__PURE__*/React.forwardRef(functi
226
295
  }
227
296
  }
228
297
  // eslint-disable-next-line react-hooks/exhaustive-deps
229
- }, [allEmojiGroups, loading, query, emojis, onOpenUpload, uploadEnabled, formatMessage]);
298
+ }, [allEmojiGroups, buildVirtualItemFromGroup, emojis, formatMessage, isTeamojiExperimentEnabled, loading, onOpenUpload, query, uploadEnabled]);
230
299
  var findCategoryToActivate = function findCategoryToActivate(row) {
231
300
  var category = null;
232
301
  if (row instanceof CategoryHeadingItem) {
@@ -336,12 +405,12 @@ export var EmojiPickerVirtualListInternal = /*#__PURE__*/React.forwardRef(functi
336
405
  // eslint-disable-next-line react-hooks/exhaustive-deps
337
406
  }, [virtualItems, categoriesChanged]);
338
407
  var virtualListHeight = useMemo(function () {
339
- if (query && emojis.length === 0 && FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false)) {
408
+ if (query && emojis.length === 0 && isTeamojiExperimentEnabled) {
340
409
  // No-results state: expand the list height to fit heading + illustration without scrolling
341
410
  return sizes.categoryHeadingHeight + sizes.noResultsHeight + emojiPickerHeightOffset(size);
342
411
  }
343
- return FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? sizes.listHeightNew + emojiPickerHeightOffset(size) : sizes.listHeight + emojiPickerHeightOffset(size);
344
- }, [size, query, emojis.length]);
412
+ return isTeamojiExperimentEnabled ? sizes.listHeightNew + emojiPickerHeightOffset(size) : sizes.listHeight + emojiPickerHeightOffset(size);
413
+ }, [size, query, emojis.length, isTeamojiExperimentEnabled]);
345
414
  return /*#__PURE__*/React.createElement(EmojiPickerTabPanel, {
346
415
  showSearchResults: !!query
347
416
  }, /*#__PURE__*/React.createElement(EmojiActions, {
@@ -14,7 +14,7 @@ var createEvent = function createEvent(eventType, action, actionSubject, actionS
14
14
  actionSubjectId: actionSubjectId,
15
15
  attributes: _objectSpread({
16
16
  packageName: "@atlaskit/emoji",
17
- packageVersion: "70.16.4"
17
+ packageVersion: "70.16.6"
18
18
  }, attributes)
19
19
  };
20
20
  };
@@ -71,4 +71,5 @@ export default class EmojiRepository {
71
71
  private getAllSearchableEmojis;
72
72
  private addToMaps;
73
73
  private addToDynamicCategories;
74
+ private getDynamicCategoryForEmoji;
74
75
  }
@@ -71,4 +71,5 @@ export default class EmojiRepository {
71
71
  private getAllSearchableEmojis;
72
72
  private addToMaps;
73
73
  private addToDynamicCategories;
74
+ private getDynamicCategoryForEmoji;
74
75
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/emoji",
3
- "version": "70.16.5",
3
+ "version": "70.17.0",
4
4
  "description": "Fabric emoji React components",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/"
@@ -55,14 +55,14 @@
55
55
  "@atlaskit/primitives": "^19.0.0",
56
56
  "@atlaskit/spinner": "^19.1.0",
57
57
  "@atlaskit/textfield": "^8.3.0",
58
- "@atlaskit/tmp-editor-statsig": "^92.0.0",
58
+ "@atlaskit/tmp-editor-statsig": "^94.0.0",
59
59
  "@atlaskit/tokens": "^13.3.0",
60
60
  "@atlaskit/tooltip": "^22.6.0",
61
61
  "@atlaskit/ufo": "^0.5.0",
62
62
  "@atlaskit/util-service-support": "^6.4.0",
63
63
  "@atlaskit/visually-hidden": "^3.1.0",
64
64
  "@babel/runtime": "^7.0.0",
65
- "@compiled/react": "patch:@compiled/react@npm%3A0.20.0#~/.yarn/patches/@compiled-react-npm-0.20.0-a771aa67a6.patch",
65
+ "@compiled/react": "^0.20.0",
66
66
  "@tanstack/react-virtual": "3.0.0-beta.60",
67
67
  "js-search": "^2.0.0",
68
68
  "lru_map": "^0.4.1",