@atlaskit/emoji 71.4.2 → 71.4.4

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 (64) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/cjs/components/common/DeleteButton.js +2 -2
  3. package/dist/cjs/components/common/Emoji.js +15 -7
  4. package/dist/cjs/components/common/EmojiActions.js +6 -14
  5. package/dist/cjs/components/common/EmojiDeletePreview.js +2 -2
  6. package/dist/cjs/components/common/EmojiErrorMessage.js +2 -2
  7. package/dist/cjs/components/common/EmojiRadioButton.js +2 -3
  8. package/dist/cjs/components/common/EmojiUploadPicker.js +9 -9
  9. package/dist/cjs/components/common/FileChooser.js +3 -3
  10. package/dist/cjs/components/common/TonePreviewButton.js +1 -2
  11. package/dist/cjs/components/common/ToneSelector.js +2 -2
  12. package/dist/cjs/components/picker/CategorySelector.js +7 -7
  13. package/dist/cjs/components/picker/EmojiPicker.js +2 -2
  14. package/dist/cjs/components/picker/EmojiPickerComponent.js +15 -15
  15. package/dist/cjs/components/picker/EmojiPickerEmojiRow.js +1 -3
  16. package/dist/cjs/components/picker/EmojiPickerFooter.js +2 -3
  17. package/dist/cjs/components/picker/EmojiPickerList.js +2 -2
  18. package/dist/cjs/components/picker/EmojiPickerListSearch.js +2 -2
  19. package/dist/cjs/components/picker/VirtualList.js +3 -3
  20. package/dist/cjs/util/analytics/analytics.js +1 -1
  21. package/dist/cjs/util/emojiIdToEmoji.js +61 -49
  22. package/dist/es2019/components/common/DeleteButton.js +2 -2
  23. package/dist/es2019/components/common/Emoji.js +14 -6
  24. package/dist/es2019/components/common/EmojiActions.js +6 -14
  25. package/dist/es2019/components/common/EmojiDeletePreview.js +2 -2
  26. package/dist/es2019/components/common/EmojiErrorMessage.js +2 -2
  27. package/dist/es2019/components/common/EmojiRadioButton.js +2 -3
  28. package/dist/es2019/components/common/EmojiUploadPicker.js +9 -9
  29. package/dist/es2019/components/common/FileChooser.js +3 -3
  30. package/dist/es2019/components/common/TonePreviewButton.js +1 -2
  31. package/dist/es2019/components/common/ToneSelector.js +2 -2
  32. package/dist/es2019/components/picker/CategorySelector.js +6 -6
  33. package/dist/es2019/components/picker/EmojiPicker.js +2 -2
  34. package/dist/es2019/components/picker/EmojiPickerComponent.js +15 -15
  35. package/dist/es2019/components/picker/EmojiPickerEmojiRow.js +1 -3
  36. package/dist/es2019/components/picker/EmojiPickerFooter.js +2 -2
  37. package/dist/es2019/components/picker/EmojiPickerList.js +2 -2
  38. package/dist/es2019/components/picker/EmojiPickerListSearch.js +2 -2
  39. package/dist/es2019/components/picker/VirtualList.js +3 -3
  40. package/dist/es2019/util/analytics/analytics.js +1 -1
  41. package/dist/es2019/util/emojiIdToEmoji.js +46 -40
  42. package/dist/esm/components/common/DeleteButton.js +2 -2
  43. package/dist/esm/components/common/Emoji.js +15 -7
  44. package/dist/esm/components/common/EmojiActions.js +6 -14
  45. package/dist/esm/components/common/EmojiDeletePreview.js +2 -2
  46. package/dist/esm/components/common/EmojiErrorMessage.js +2 -2
  47. package/dist/esm/components/common/EmojiRadioButton.js +2 -3
  48. package/dist/esm/components/common/EmojiUploadPicker.js +9 -9
  49. package/dist/esm/components/common/FileChooser.js +3 -3
  50. package/dist/esm/components/common/TonePreviewButton.js +1 -2
  51. package/dist/esm/components/common/ToneSelector.js +2 -2
  52. package/dist/esm/components/picker/CategorySelector.js +7 -7
  53. package/dist/esm/components/picker/EmojiPicker.js +2 -2
  54. package/dist/esm/components/picker/EmojiPickerComponent.js +15 -15
  55. package/dist/esm/components/picker/EmojiPickerEmojiRow.js +1 -3
  56. package/dist/esm/components/picker/EmojiPickerFooter.js +2 -2
  57. package/dist/esm/components/picker/EmojiPickerList.js +2 -2
  58. package/dist/esm/components/picker/EmojiPickerListSearch.js +2 -2
  59. package/dist/esm/components/picker/VirtualList.js +3 -3
  60. package/dist/esm/util/analytics/analytics.js +1 -1
  61. package/dist/esm/util/emojiIdToEmoji.js +61 -49
  62. package/dist/types/components/picker/EmojiPickerComponent.d.ts +0 -4
  63. package/dist/types/util/emojiIdToEmoji.d.ts +2 -2
  64. package/package.json +6 -6
@@ -1,8 +1,8 @@
1
1
  /* ToneSelector.tsx generated by @compiled/babel-plugin v0.39.1 */
2
2
  import "./ToneSelector.compiled.css";
3
3
  import { ax, ix } from "@compiled/react/runtime";
4
+ import { expVal } from '@atlaskit/tmp-editor-statsig/expVal';
4
5
  import React, { memo, useCallback, useEffect, useMemo, useRef } from 'react';
5
- import FeatureGates from '@atlaskit/feature-gate-js-client';
6
6
  import { withAnalyticsEvents } from '@atlaskit/analytics-next';
7
7
  import { createAndFireEventInElementsChannel, toneSelectedEvent, toneSelectorOpenedEvent } from '../../util/analytics';
8
8
  import { setSkinToneAriaLabelText } from './setSkinToneAriaLabelText';
@@ -92,7 +92,7 @@ export const ToneSelectorInternal = props => {
92
92
  "aria-label": formatMessage(messages.emojiSelectSkinToneListAriaLabelText),
93
93
  className: ax([!isVisible && "_tzy4idpf _3um015vq _1e0cglyw"])
94
94
  }, emojiToneCollection.map((tone, renderIndex) => {
95
- return FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? /*#__PURE__*/React.createElement(EmojiRadioButton, {
95
+ return expVal('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? /*#__PURE__*/React.createElement(EmojiRadioButton, {
96
96
  ref: el => {
97
97
  radioRefs.current[renderIndex] = el;
98
98
  if (tone.isSelected && selectedToneRadioRef) {
@@ -7,8 +7,8 @@ import { cx } from '@atlaskit/css';
7
7
  import { useIntl } from 'react-intl';
8
8
  import { Pressable } from '@atlaskit/primitives/compiled';
9
9
  import Tooltip from '@atlaskit/tooltip';
10
+ import { expVal } from '@atlaskit/tmp-editor-statsig/expVal';
10
11
  import { CATEGORYSELECTOR_KEYBOARD_KEYS_SUPPORTED, defaultCategories, KeyboardKeys } from '../../util/constants';
11
- import FeatureGates from '@atlaskit/feature-gate-js-client';
12
12
  import { messages } from '../i18n';
13
13
  import { CategoryDescriptionMap, CategoryDescriptionMapNew } from './categories';
14
14
  import { usePrevious } from '../../hooks/usePrevious';
@@ -32,7 +32,7 @@ const addNewCategories = (oldCategories, newCategories) => {
32
32
  if (!newCategories) {
33
33
  return oldCategories;
34
34
  }
35
- return oldCategories.concat(newCategories.filter(category => !!(FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? CategoryDescriptionMapNew : CategoryDescriptionMap)[category])).sort(FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? sortCategoriesNew : sortCategories);
35
+ return oldCategories.concat(newCategories.filter(category => !!(expVal('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? CategoryDescriptionMapNew : CategoryDescriptionMap)[category])).sort(expVal('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? sortCategoriesNew : sortCategories);
36
36
  };
37
37
  export const categorySelectorComponentTestId = 'category-selector-component';
38
38
  export const categorySelectorCategoryTestId = categoryId => `category-selector-${categoryId}`;
@@ -103,14 +103,14 @@ const CategorySelector = props => {
103
103
  };
104
104
  let categoriesSection;
105
105
  if (categories) {
106
- categoriesSection = FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? /*#__PURE__*/React.createElement("div", {
106
+ categoriesSection = expVal('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? /*#__PURE__*/React.createElement("div", {
107
107
  role: "tablist",
108
108
  "aria-label": formatMessage(messages.categoriesSelectorLabel),
109
109
  "data-testid": categorySelectorComponentTestId,
110
110
  ref: categoryRef,
111
111
  className: ax(["_ca0qze3t _n3tdze3t _19bvu2gc _u5f3u2gc _1e0c1txw _2lx2vrvc _1bah1b1v _4cvr1fhb"])
112
112
  }, categories.map((categoryId, index) => {
113
- const category = FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? CategoryDescriptionMapNew[categoryId] : CategoryDescriptionMap[categoryId];
113
+ const category = expVal('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? CategoryDescriptionMapNew[categoryId] : CategoryDescriptionMap[categoryId];
114
114
  const Icon = category.icon;
115
115
  const categoryName = formatMessage(messages[category.name]);
116
116
  return /*#__PURE__*/React.createElement(Tooltip, {
@@ -140,7 +140,7 @@ const CategorySelector = props => {
140
140
  ref: categoryRef,
141
141
  className: ax(["_ca0q12x7 _n3td12x7 _19bvu2gc _u5f3u2gc _1e0c1txw _2lx2vrvc _1bah1b1v _4cvr1h6o"])
142
142
  }, categories.map((categoryId, index) => {
143
- const category = FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? CategoryDescriptionMapNew[categoryId] : CategoryDescriptionMap[categoryId];
143
+ const category = expVal('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? CategoryDescriptionMapNew[categoryId] : CategoryDescriptionMap[categoryId];
144
144
  const Icon = category.icon;
145
145
  const categoryName = formatMessage(messages[category.name]);
146
146
  return /*#__PURE__*/React.createElement(Tooltip, {
@@ -165,7 +165,7 @@ const CategorySelector = props => {
165
165
  })));
166
166
  }));
167
167
  }
168
- return FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? /*#__PURE__*/React.createElement("div", {
168
+ return expVal('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? /*#__PURE__*/React.createElement("div", {
169
169
  className: ax(["_16jlidpf _1o9zidpf _i0dl1wug _bfhkvuon _13li1mok _qrwq1mok _ca0qze3t _n3tdze3t _1doce4h9 _1il9nqa1 _1o3i1l7x _dpd31txw"])
170
170
  }, categoriesSection) : /*#__PURE__*/React.createElement("div", {
171
171
  className: ax(["_16jlidpf _1o9zidpf _i0dl1wug _bfhkhfxm _dpd31txw"])
@@ -5,7 +5,7 @@ import { ax, ix } from "@compiled/react/runtime";
5
5
  import React from 'react';
6
6
  import { withAnalyticsEvents } from '@atlaskit/analytics-next';
7
7
  import { ufoExperiences } from '../../util/analytics';
8
- import FeatureGates from '@atlaskit/feature-gate-js-client';
8
+ import { expVal } from '@atlaskit/tmp-editor-statsig/expVal';
9
9
  import LoadingEmojiComponent from '../common/LoadingEmojiComponent';
10
10
  import { LoadingItem } from './EmojiPickerVirtualItems';
11
11
  import { UfoErrorBoundary } from '../common/UfoErrorBoundary';
@@ -42,7 +42,7 @@ export class EmojiPickerInternal extends LoadingEmojiComponent {
42
42
  }
43
43
  };
44
44
  ufoExperiences['emoji-picker-opened'].markFMP();
45
- return FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? /*#__PURE__*/React.createElement("div", {
45
+ return expVal('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? /*#__PURE__*/React.createElement("div", {
46
46
  ref: handlePickerRef,
47
47
  className: ax(["_19itahnd _2rko1mok _1e0c1txw _2lx21bp4 _1bah1yb4 _bfhk1bhr _16qs130s _4t3iixjv _1bsb1edt _1ul91edt _1tke5x59 _c71l1y6z"])
48
48
  }, item.renderItem()) : /*#__PURE__*/React.createElement("div", {
@@ -2,8 +2,8 @@
2
2
  import "./EmojiPickerComponent.compiled.css";
3
3
  import * as React from 'react';
4
4
  import { ax, ix } from "@compiled/react/runtime";
5
+ import { expVal } from '@atlaskit/tmp-editor-statsig/expVal';
5
6
  import { useCallback, useEffect, useMemo, useRef, useState, createRef, memo } from 'react';
6
- import FeatureGates from '@atlaskit/feature-gate-js-client';
7
7
  import { getDocument } from '@atlaskit/browser-apis';
8
8
  import { dropTargetForExternal, monitorForExternal } from '@atlaskit/pragmatic-drag-and-drop/external/adapter';
9
9
  import { containsFiles } from '@atlaskit/pragmatic-drag-and-drop/external/file';
@@ -80,7 +80,7 @@ const EmojiPickerComponent = ({
80
80
  emojiProvider,
81
81
  isUploadSupported
82
82
  } = useEmoji();
83
- const isTeamojiExperimentEnabled = FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false);
83
+ const isTeamojiExperimentEnabled = expVal('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false);
84
84
  const [filteredEmojis, setFilteredEmojis] = useState([]);
85
85
  const [searchEmojis, setSearchEmojis] = useState([]);
86
86
  const [frequentlyUsedEmojis, setFrequentlyUsedEmojis] = useState([]);
@@ -124,7 +124,7 @@ const EmojiPickerComponent = ({
124
124
  }
125
125
  }, [selectedEmoji]);
126
126
  const onEmojiLeave = useCallback(() => {
127
- if (FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false)) {
127
+ if (expVal('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false)) {
128
128
  setSelectedEmoji(undefined);
129
129
  }
130
130
  }, []);
@@ -132,16 +132,16 @@ const EmojiPickerComponent = ({
132
132
  // Ignore scroll-driven category changes while a programmatic reveal()
133
133
  // scroll is in progress — they would flicker the indicator through
134
134
  // intermediate categories before landing on the correct one.
135
- if (isProgrammaticScroll.current && FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false)) {
135
+ if (isProgrammaticScroll.current && expVal('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false)) {
136
136
  return;
137
137
  }
138
138
  // Ignore scroll-driven category changes while the upload or delete screen is open
139
- if ((uploading || emojiToDelete) && FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false)) {
139
+ if ((uploading || emojiToDelete) && expVal('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false)) {
140
140
  return;
141
141
  }
142
142
  if (activeCategory !== category) {
143
143
  setActiveCategory(category);
144
- if (!query && FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false)) {
144
+ if (!query && expVal('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false)) {
145
145
  lastNonSearchCategory.current = category;
146
146
  }
147
147
  }
@@ -158,7 +158,7 @@ const EmojiPickerComponent = ({
158
158
  setUploadErrorMessage(undefined);
159
159
  });
160
160
  fireAnalytics(uploadCancelButton());
161
- if (FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false)) {
161
+ if (expVal('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false)) {
162
162
  setTimeout(() => {
163
163
  var _getDocument, _getDocument$getEleme;
164
164
  (_getDocument = getDocument()) === null || _getDocument === void 0 ? void 0 : (_getDocument$getEleme = _getDocument.getElementById('add-custom-emoji')) === null || _getDocument$getEleme === void 0 ? void 0 : _getDocument$getEleme.focus();
@@ -310,7 +310,7 @@ const EmojiPickerComponent = ({
310
310
  }
311
311
 
312
312
  // If the upload or delete screen is open, close it when a category is selected
313
- if (FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false)) {
313
+ if (expVal('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false)) {
314
314
  if (uploading) {
315
315
  setUploading(false);
316
316
  setUploadErrorMessage(undefined);
@@ -366,7 +366,7 @@ const EmojiPickerComponent = ({
366
366
  };
367
367
  if (searchQuery !== query) {
368
368
  // Capture the active category before entering search so we can keep it highlighted
369
- if (!query && searchQuery && FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false)) {
369
+ if (!query && searchQuery && expVal('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false)) {
370
370
  lastNonSearchCategory.current = activeCategory;
371
371
  }
372
372
  setQuery(searchQuery);
@@ -382,7 +382,7 @@ const EmojiPickerComponent = ({
382
382
  // cannot reach underlying page drop handlers (e.g. the Confluence editor).
383
383
  useEffect(() => {
384
384
  var _getDocument2;
385
- if (!uploading || !FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false)) {
385
+ if (!uploading || !expVal('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false)) {
386
386
  return;
387
387
  }
388
388
  const body = (_getDocument2 = getDocument()) === null || _getDocument2 === void 0 ? void 0 : _getDocument2.body;
@@ -442,7 +442,7 @@ const EmojiPickerComponent = ({
442
442
  });
443
443
  scrollToUploadedEmoji(emojiDescription);
444
444
  };
445
- if (FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false)) {
445
+ if (expVal('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false)) {
446
446
  const uploadShortName = `:${upload.name.toLowerCase()}:`;
447
447
  const existing = await emojiProvider.findByShortName(uploadShortName);
448
448
  if (existing) {
@@ -561,14 +561,14 @@ const EmojiPickerComponent = ({
561
561
  emojiProvider.unsubscribe(onProviderChange);
562
562
  };
563
563
  }, [emojiProvider, onProviderChange]);
564
- const showPreview = FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? !uploading : selectedEmoji && !uploading;
564
+ const showPreview = expVal('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? !uploading : selectedEmoji && !uploading;
565
565
  return /*#__PURE__*/React.createElement("div", {
566
566
  ref: setPickerRef,
567
567
  "data-emoji-picker-container": true,
568
568
  role: "dialog",
569
569
  "aria-label": formatMessage(messages.emojiPickerTitle),
570
570
  "aria-modal": true,
571
- className: ax([FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? "_19itahnd _2rko1mok _1e0c1txw _2lx21bp4 _1bah1yb4 _bfhk1bhr _16qs130s _4t3iaq3k _1bsb1edt _1ul91edt _c71l1y6z _kqswh2mm" : "_19itahnd _2rkofajl _1e0c1txw _2lx21bp4 _1bah1yb4 _bfhk1bhr _16qs130s _4t3iaq3k _1bsb1edt _1ul91edt _c71l1y6z _kqswh2mm", !!emojiToDelete && FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? withDeleteRefreshHeight[size] : uploading && FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? withUploadRefreshHeight[size] : query && filteredEmojis.length === 0 && FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? withNoResultsRefreshHeight[size] : showPreview ? withPreviewHeight[size] : withoutPreviewHeight[size]])
571
+ className: ax([expVal('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? "_19itahnd _2rko1mok _1e0c1txw _2lx21bp4 _1bah1yb4 _bfhk1bhr _16qs130s _4t3iaq3k _1bsb1edt _1ul91edt _c71l1y6z _kqswh2mm" : "_19itahnd _2rkofajl _1e0c1txw _2lx21bp4 _1bah1yb4 _bfhk1bhr _16qs130s _4t3iaq3k _1bsb1edt _1ul91edt _c71l1y6z _kqswh2mm", !!emojiToDelete && expVal('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? withDeleteRefreshHeight[size] : uploading && expVal('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? withUploadRefreshHeight[size] : query && filteredEmojis.length === 0 && expVal('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? withNoResultsRefreshHeight[size] : showPreview ? withPreviewHeight[size] : withoutPreviewHeight[size]])
572
572
  }, /*#__PURE__*/React.createElement("div", {
573
573
  role: "presentation",
574
574
  onKeyPress: suppressKeyPress,
@@ -576,7 +576,7 @@ const EmojiPickerComponent = ({
576
576
  onKeyDown: suppressKeyPress,
577
577
  className: ax(["_16jlkb7n _1o9zkb7n _i0dlf1ug _1reo15vq _18m915vq _1e0c1txw _2lx21bp4 _1bah1yb4 _1tkeidpf"])
578
578
  }, /*#__PURE__*/React.createElement(CategorySelector, {
579
- activeCategoryId: (uploading || emojiToDelete) && FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? null : activeCategory,
579
+ activeCategoryId: (uploading || emojiToDelete) && expVal('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? null : activeCategory,
580
580
  dynamicCategories: dynamicCategories,
581
581
  disableCategories: disableCategories,
582
582
  onCategorySelected: onCategorySelected
@@ -611,7 +611,7 @@ const EmojiPickerComponent = ({
611
611
  onOpenUpload: onOpenUpload,
612
612
  size: size,
613
613
  activeCategoryId: activeCategory
614
- }), showPreview && !(emojiToDelete && FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false)) && !(query && filteredEmojis.length === 0 && FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false)) && /*#__PURE__*/React.createElement(EmojiPickerFooter, {
614
+ }), showPreview && !(emojiToDelete && expVal('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false)) && !(query && filteredEmojis.length === 0 && expVal('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false)) && /*#__PURE__*/React.createElement(EmojiPickerFooter, {
615
615
  selectedEmoji: selectedEmoji,
616
616
  uploadEnabled: isUploadSupported && !uploading,
617
617
  onOpenUpload: onOpenUpload
@@ -5,7 +5,6 @@ import * as React from 'react';
5
5
  import { ax, ix } from "@compiled/react/runtime";
6
6
  import { memo } from 'react';
7
7
  import { fg } from '@atlaskit/platform-feature-flags';
8
- import FeatureGates from '@atlaskit/feature-gate-js-client';
9
8
  import { useIntl } from 'react-intl';
10
9
  import CachingEmoji from '../common/CachingEmoji';
11
10
  import { useEmojiPickerListContext } from '../../hooks/useEmojiPickerListContext';
@@ -14,7 +13,6 @@ import { messages } from '../i18n';
14
13
  const emojiItem = null;
15
14
  const emojiPickerRow = null;
16
15
  const emojiPickerRowList = null;
17
- const teamojiRefreshExperimentName = 'platform_teamoji_26_refresh_emoji_picker';
18
16
  const EmojiPickerEmojiRow = ({
19
17
  emojis,
20
18
  onSelected,
@@ -35,7 +33,7 @@ const EmojiPickerEmojiRow = ({
35
33
  formatMessage
36
34
  } = useIntl();
37
35
  const fitToHeight = expValEqualsNoExposure('platform_use_unicode_emojis', 'isEnabled', true) ? 24 : undefined;
38
- const preventFocusOnMouseDown = FeatureGates.getExperimentValue(teamojiRefreshExperimentName, 'isEnabled', false);
36
+ const preventFocusOnMouseDown = expValEqualsNoExposure('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', true);
39
37
  const handleFocus = index => (emojiId, emoji, event) => {
40
38
  setEmojisFocus({
41
39
  rowIndex,
@@ -5,9 +5,9 @@ import { ax, ix } from "@compiled/react/runtime";
5
5
  import { memo } from 'react';
6
6
  import { useIntl } from 'react-intl';
7
7
  import { Box } from '@atlaskit/primitives/compiled';
8
- import FeatureGates from '@atlaskit/feature-gate-js-client';
9
8
  import { EmojiPreviewComponent } from '../common/EmojiPreviewComponent';
10
9
  import { AddOwnEmoji } from '../common/AddEmoji';
10
+ import { expVal } from '@atlaskit/tmp-editor-statsig/expVal';
11
11
  const emojiPickerFooter = null;
12
12
  const emojiPickerFooterWithTopShadow = null;
13
13
  const emojiPickerFooterWithTopShadowNew = null;
@@ -21,7 +21,7 @@ const EmojiPickerFooter = ({
21
21
  uploadEnabled
22
22
  }) => {
23
23
  const intl = useIntl();
24
- return FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? /*#__PURE__*/React.createElement("div", {
24
+ return expVal('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? /*#__PURE__*/React.createElement("div", {
25
25
  "data-testid": emojiPickerFooterTestId,
26
26
  className: ax(["_16jlidpf _1o9zidpf _i0dl1wug", "_x3doia51"])
27
27
  }, selectedEmoji ? /*#__PURE__*/React.createElement(Box, {
@@ -1,6 +1,6 @@
1
1
  import { useIntl } from 'react-intl';
2
+ import { expVal } from '@atlaskit/tmp-editor-statsig/expVal';
2
3
  import React, { useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react';
3
- import FeatureGates from '@atlaskit/feature-gate-js-client';
4
4
  import { customCategory, defaultEmojiPickerSize, frequentCategory, searchCategory, userCustomTitle, yourUploadsCategory } from '../../util/constants';
5
5
  import { filterProductivityEmojisByColor, getProductivityColorPreviewEmojis } from '../../util/productivity-colors';
6
6
  import { filterHiddenEmojis } from '../../util/hidden-emojis';
@@ -77,7 +77,7 @@ export const EmojiPickerVirtualListInternal = /*#__PURE__*/React.forwardRef((pro
77
77
  const [lastYourUploadsRow, setLastYourUploadsRow] = useState(0);
78
78
  const categoryTracker = useMemo(() => new CategoryTracker(), []);
79
79
  const [categoriesChanged, setCategoriesChanged] = useState(false);
80
- const isTeamojiExperimentEnabled = FeatureGates.getExperimentValue(teamojiRefreshExperimentName, 'isEnabled', false);
80
+ const isTeamojiExperimentEnabled = expVal(teamojiRefreshExperimentName, 'isEnabled', false);
81
81
  const visibleEmojis = useMemo(() => isTeamojiExperimentEnabled ? filterHiddenEmojis(emojis) : emojis, [emojis, isTeamojiExperimentEnabled]);
82
82
  const productivityColorPreviewEmojis = useMemo(() => isTeamojiExperimentEnabled ? getProductivityColorPreviewEmojis(visibleEmojis) : {}, [isTeamojiExperimentEnabled, visibleEmojis]);
83
83
  const addToCategoryMap = useCallback((categoryToGroupMap, emoji, category) => {
@@ -8,8 +8,8 @@ import React, { useLayoutEffect, useRef, useState } from 'react';
8
8
  import { useIntl } from 'react-intl';
9
9
  import { useDebouncedCallback } from 'use-debounce';
10
10
  import { EMOJI_SEARCH_DEBOUNCE } from '../../util/constants';
11
- import FeatureGates from '@atlaskit/feature-gate-js-client';
12
11
  import { messages } from '../i18n';
12
+ import { expVal } from '@atlaskit/tmp-editor-statsig/expVal';
13
13
  const input = null;
14
14
  const inputNew = null;
15
15
  const textFieldWrapperNew = null;
@@ -58,7 +58,7 @@ export const EmojiPickerListSearch = props => {
58
58
  role: "status"
59
59
  }, dirty ? query === '' ? formatMessage(messages.searchResultsStatusSeeAll) : formatMessage(messages.searchResultsStatus, {
60
60
  count: resultsCount
61
- }) : null), FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? /*#__PURE__*/React.createElement("div", {
61
+ }) : null), expVal('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? /*#__PURE__*/React.createElement("div", {
62
62
  className: ax(["_n6341l7x _18z11b66"])
63
63
  }, /*#__PURE__*/React.createElement(TextField, {
64
64
  role: "searchbox",
@@ -5,7 +5,7 @@ import { ax, ix } from "@compiled/react/runtime";
5
5
  import React, { useCallback, useImperativeHandle } from 'react';
6
6
  import { useVirtualizer } from '@tanstack/react-virtual';
7
7
  import { fg } from '@atlaskit/platform-feature-flags';
8
- import FeatureGates from '@atlaskit/feature-gate-js-client';
8
+ import { expVal } from '@atlaskit/tmp-editor-statsig/expVal';
9
9
  import { useEmojiPickerListContext } from '../../hooks/useEmojiPickerListContext';
10
10
  import { EMOJIPICKERLIST_KEYBOARD_KEYS_SUPPORTED, EMOJI_LIST_COLUMNS, EMOJI_LIST_PAGE_COUNT, KeyboardNavigationDirection, KeyboardKeys } from '../../util/constants';
11
11
  const virtualList = null;
@@ -56,7 +56,7 @@ export const VirtualList = /*#__PURE__*/React.forwardRef((props, ref) => {
56
56
  const elemBottom = elementRect.bottom;
57
57
  const parentTop = parentRect.top;
58
58
  const parentBottom = parentRect.bottom;
59
- const isVisible = FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? elemTop >= parentTop && elemBottom <= parentBottom : elemBottom > parentTop && elemTop < parentBottom;
59
+ const isVisible = expVal('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? elemTop >= parentTop && elemBottom <= parentBottom : elemBottom > parentTop && elemTop < parentBottom;
60
60
  return isVisible;
61
61
  };
62
62
  const getFirstVisibleListElementIndex = useCallback(() => {
@@ -73,7 +73,7 @@ export const VirtualList = /*#__PURE__*/React.forwardRef((props, ref) => {
73
73
  var _virtualList$firstVis;
74
74
  return ((_virtualList$firstVis = virtualList[firstVisibleIndex]) === null || _virtualList$firstVis === void 0 ? void 0 : _virtualList$firstVis.index) || 0;
75
75
  }
76
- return FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? ((_virtualList$ = virtualList[0]) === null || _virtualList$ === void 0 ? void 0 : _virtualList$.index) || 0 : 0;
76
+ return expVal('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? ((_virtualList$ = virtualList[0]) === null || _virtualList$ === void 0 ? void 0 : _virtualList$.index) || 0 : 0;
77
77
  }, [rowVirtualizer]);
78
78
 
79
79
  /**
@@ -9,7 +9,7 @@ const createEvent = (eventType, action, actionSubject, actionSubjectId, attribut
9
9
  actionSubjectId,
10
10
  attributes: {
11
11
  packageName: "@atlaskit/emoji",
12
- packageVersion: "71.4.1",
12
+ packageVersion: "71.4.3",
13
13
  ...attributes
14
14
  }
15
15
  });
@@ -2,17 +2,40 @@ import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equ
2
2
  const KEYCAP_COMBINING = 0x20e3;
3
3
  const VARIATION_SELECTOR_16 = 0xfe0f;
4
4
  const VARIATION_SELECTOR_15 = 0xfe0e;
5
+ const EMOJI_MODIFIER_START = 0x1f3fb;
6
+ const EMOJI_MODIFIER_END = 0x1f3ff;
7
+ const REGIONAL_INDICATOR_START = 0x1f1e6;
8
+ const REGIONAL_INDICATOR_END = 0x1f1ff;
9
+ const FLAG_BASES = new Set([0x1f38c, 0x1f3c1, 0x1f3f3, 0x1f3f4, 0x1f6a9]);
5
10
 
6
- // Text-presentation-default emoji: BMP characters (U+0000–U+FFFF) that are
7
- // valid emoji but lack the Emoji_Presentation property render as text without
8
- // U+FE0F. Supplementary-plane characters (U+10000+) always render as emoji
9
- // regardless of the Emoji_Presentation property, so we skip those.
10
- //
11
- // This set is derived from Unicode 14.0 emoji-data.txt: all BMP code points
12
- // that have the Emoji property but NOT the Emoji_Presentation property.
13
- // Using an explicit lookup table avoids the \p{} Unicode property escape
14
- // syntax (TS1501) which requires a specific TypeScript build target.
15
- const TEXT_DEFAULT_EMOJI = new Set([0x0023, 0x002a, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x00a9, 0x00ae, 0x203c, 0x2049, 0x2122, 0x2139, 0x2194, 0x2195, 0x2196, 0x2197, 0x2198, 0x2199, 0x21a9, 0x21aa, 0x2328, 0x23cf, 0x23ed, 0x23ee, 0x23ef, 0x23f1, 0x23f2, 0x23f8, 0x23f9, 0x23fa, 0x24c2, 0x25aa, 0x25ab, 0x25b6, 0x25c0, 0x25fb, 0x25fc, 0x2600, 0x2601, 0x2602, 0x2603, 0x2604, 0x260e, 0x2611, 0x2618, 0x261d, 0x2620, 0x2622, 0x2623, 0x2626, 0x262a, 0x262e, 0x262f, 0x2638, 0x2639, 0x263a, 0x2640, 0x2642, 0x265f, 0x2660, 0x2663, 0x2665, 0x2666, 0x2668, 0x267b, 0x267e, 0x2692, 0x2694, 0x2695, 0x2696, 0x2697, 0x2699, 0x269b, 0x269c, 0x26a0, 0x26a7, 0x26b0, 0x26b1, 0x26c8, 0x26cf, 0x26d1, 0x26d3, 0x26e9, 0x26f0, 0x26f1, 0x26f4, 0x26f7, 0x26f8, 0x26f9, 0x2702, 0x2708, 0x2709, 0x270c, 0x270d, 0x270f, 0x2712, 0x2714, 0x2716, 0x271d, 0x2721, 0x2733, 0x2734, 0x2744, 0x2747, 0x2763, 0x2764, 0x27a1, 0x2934, 0x2935, 0x2b05, 0x2b06, 0x2b07, 0x3030, 0x303d, 0x3297, 0x3299]);
11
+ // Emoji variation bases from Unicode 14.0 emoji-variation-sequences.txt.
12
+ // These are the code points with a defined U+FE0F emoji-style variant.
13
+ const EMOJI_VARIATION_BASES = new Set([0x0023, 0x002a, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x00a9, 0x00ae, 0x203c, 0x2049, 0x2122, 0x2139, 0x2194, 0x2195, 0x2196, 0x2197, 0x2198, 0x2199, 0x21a9, 0x21aa, 0x2328, 0x23cf, 0x23ed, 0x23ee, 0x23ef, 0x23f1, 0x23f2, 0x23f8, 0x23f9, 0x23fa, 0x24c2, 0x25aa, 0x25ab, 0x25b6, 0x25c0, 0x25fb, 0x25fc, 0x2600, 0x2601, 0x2602, 0x2603, 0x2604, 0x260e, 0x2611, 0x2618, 0x261d, 0x2620, 0x2622, 0x2623, 0x2626, 0x262a, 0x262e, 0x262f, 0x2638, 0x2639, 0x263a, 0x2640, 0x2642, 0x265f, 0x2660, 0x2663, 0x2665, 0x2666, 0x2668, 0x267b, 0x267e, 0x2692, 0x2694, 0x2695, 0x2696, 0x2697, 0x2699, 0x269b, 0x269c, 0x26a0, 0x26a7, 0x26b0, 0x26b1, 0x26c8, 0x26cf, 0x26d1, 0x26d3, 0x26e9, 0x26f0, 0x26f1, 0x26f4, 0x26f7, 0x26f8, 0x26f9, 0x2702, 0x2708, 0x2709, 0x270c, 0x270d, 0x270f, 0x2712, 0x2714, 0x2716, 0x271d, 0x2721, 0x2733, 0x2734, 0x2744, 0x2747, 0x2763, 0x2764, 0x27a1, 0x2934, 0x2935, 0x2b05, 0x2b06, 0x2b07, 0x3030, 0x303d, 0x3297, 0x3299, 0x1f170, 0x1f171, 0x1f17e, 0x1f17f, 0x1f202, 0x1f237, 0x1f321, 0x1f324, 0x1f325, 0x1f326, 0x1f327, 0x1f328, 0x1f329, 0x1f32a, 0x1f32b, 0x1f32c, 0x1f336, 0x1f37d, 0x1f396, 0x1f397, 0x1f399, 0x1f39a, 0x1f39b, 0x1f39e, 0x1f39f, 0x1f3cb, 0x1f3cc, 0x1f3cd, 0x1f3ce, 0x1f3d4, 0x1f3d5, 0x1f3d6, 0x1f3d7, 0x1f3d8, 0x1f3d9, 0x1f3da, 0x1f3db, 0x1f3dc, 0x1f3dd, 0x1f3de, 0x1f3df, 0x1f3f3, 0x1f3f5, 0x1f3f7, 0x1f43f, 0x1f441, 0x1f4fd, 0x1f549, 0x1f54a, 0x1f56f, 0x1f570, 0x1f573, 0x1f574, 0x1f575, 0x1f576, 0x1f577, 0x1f578, 0x1f579, 0x1f587, 0x1f58a, 0x1f58b, 0x1f58c, 0x1f58d, 0x1f590, 0x1f5a5, 0x1f5a8, 0x1f5b1, 0x1f5b2, 0x1f5bc, 0x1f5c2, 0x1f5c3, 0x1f5c4, 0x1f5d1, 0x1f5d2, 0x1f5d3, 0x1f5dc, 0x1f5dd, 0x1f5de, 0x1f5e1, 0x1f5e3, 0x1f5e8, 0x1f5ef, 0x1f5f3, 0x1f5fa, 0x1f6cb, 0x1f6cd, 0x1f6ce, 0x1f6cf, 0x1f6e0, 0x1f6e1, 0x1f6e2, 0x1f6e3, 0x1f6e4, 0x1f6e5, 0x1f6e9, 0x1f6f0, 0x1f6f3, 0x231a, 0x231b, 0x23e9, 0x23ea, 0x23f3, 0x25fd, 0x25fe, 0x2614, 0x2615, 0x2648, 0x2649, 0x264a, 0x264b, 0x264c, 0x264d, 0x264e, 0x264f, 0x2650, 0x2651, 0x2652, 0x2653, 0x267f, 0x2693, 0x26a1, 0x26aa, 0x26ab, 0x26bd, 0x26be, 0x26c4, 0x26c5, 0x26d4, 0x26ea, 0x26f2, 0x26f3, 0x26f5, 0x26fa, 0x26fd, 0x2753, 0x2757, 0x2b1b, 0x2b1c, 0x2b50, 0x2b55, 0x1f004, 0x1f21a, 0x1f22f, 0x1f30d, 0x1f30e, 0x1f30f, 0x1f315, 0x1f31c, 0x1f378, 0x1f393, 0x1f3a7, 0x1f3ac, 0x1f3ad, 0x1f3ae, 0x1f3c2, 0x1f3c4, 0x1f3c6, 0x1f3ca, 0x1f3e0, 0x1f3ed, 0x1f408, 0x1f415, 0x1f41f, 0x1f426, 0x1f442, 0x1f446, 0x1f447, 0x1f448, 0x1f449, 0x1f44d, 0x1f44e, 0x1f453, 0x1f46a, 0x1f47d, 0x1f4a3, 0x1f4b0, 0x1f4b3, 0x1f4bb, 0x1f4bf, 0x1f4cb, 0x1f4da, 0x1f4df, 0x1f4e4, 0x1f4e5, 0x1f4e6, 0x1f4ea, 0x1f4eb, 0x1f4ec, 0x1f4ed, 0x1f4f7, 0x1f4f9, 0x1f4fa, 0x1f4fb, 0x1f508, 0x1f50d, 0x1f512, 0x1f513, 0x1f550, 0x1f551, 0x1f552, 0x1f553, 0x1f554, 0x1f555, 0x1f556, 0x1f557, 0x1f558, 0x1f559, 0x1f55a, 0x1f55b, 0x1f55c, 0x1f55d, 0x1f55e, 0x1f55f, 0x1f560, 0x1f561, 0x1f562, 0x1f563, 0x1f564, 0x1f565, 0x1f566, 0x1f567, 0x1f610, 0x1f687, 0x1f68d, 0x1f691, 0x1f694, 0x1f698, 0x1f6ad, 0x1f6b2, 0x1f6b9, 0x1f6ba, 0x1f6bc]);
14
+ const isEmojiModifier = codePoint => typeof codePoint === 'number' && codePoint >= EMOJI_MODIFIER_START && codePoint <= EMOJI_MODIFIER_END;
15
+ const shouldAddEmojiPresentationSelector = (codePoint, nextCodePoint) => EMOJI_VARIATION_BASES.has(codePoint) && nextCodePoint !== VARIATION_SELECTOR_16 && nextCodePoint !== VARIATION_SELECTOR_15 && nextCodePoint !== KEYCAP_COMBINING && !isEmojiModifier(nextCodePoint);
16
+ const isRegionalIndicator = codePoint => codePoint >= REGIONAL_INDICATOR_START && codePoint <= REGIONAL_INDICATOR_END;
17
+ const parseEmojiIdCodePoints = id => {
18
+ const segments = id.split('-');
19
+ const codePoints = [];
20
+ for (const segment of segments) {
21
+ if (!/^[0-9a-fA-F]+$/.test(segment)) {
22
+ return undefined;
23
+ }
24
+ const cp = parseInt(segment, 16);
25
+ // Valid Unicode scalar values: U+0000–U+10FFFF, excluding surrogates.
26
+ if (isNaN(cp) || cp < 0 || cp > 0x10ffff || cp >= 0xd800 && cp <= 0xdfff) {
27
+ return undefined;
28
+ }
29
+ codePoints.push(cp);
30
+ }
31
+ return codePoints.length ? codePoints : undefined;
32
+ };
33
+ const isFlagEmoji = codePoints => {
34
+ if (codePoints.length === 2 && codePoints.every(isRegionalIndicator)) {
35
+ return true;
36
+ }
37
+ return FLAG_BASES.has(codePoints[0]);
38
+ };
16
39
 
17
40
  /**
18
41
  * Converts an emoji ID (a hyphen-separated string of hex Unicode code points,
@@ -22,30 +45,24 @@ const TEXT_DEFAULT_EMOJI = new Set([0x0023, 0x002a, 0x0030, 0x0031, 0x0032, 0x00
22
45
  * Special handling:
23
46
  * - Keycap sequences: U+20E3 (COMBINING ENCLOSING KEYCAP) must be preceded by
24
47
  * U+FE0F (VARIATION SELECTOR-16) to form a well-defined keycap emoji.
25
- * - Text-default emoji (characters whose default presentation is text) must be
26
- * followed by U+FE0F to force emoji presentation.
48
+ * - Emoji variation bases are followed by U+FE0F to force emoji presentation.
49
+ * - Flags return `undefined` so callers use Twemoji instead of native emoji.
27
50
  *
28
51
  * @returns The Unicode string for the emoji, or `undefined` if the input is
29
52
  * invalid (empty string, non-hex segments, or out-of-range code points).
30
53
  */
31
54
  export function emojiIdToEmoji(id) {
55
+ if (!expValEqualsNoExposure('platform_use_unicode_emojis', 'isEnabled', true)) {
56
+ return undefined;
57
+ }
32
58
  if (!id) {
33
59
  return undefined;
34
60
  }
35
- const segments = id.split('-');
36
- const codePoints = [];
37
- for (const segment of segments) {
38
- if (!/^[0-9a-fA-F]+$/.test(segment)) {
39
- return undefined;
40
- }
41
- const cp = parseInt(segment, 16);
42
- // Valid Unicode scalar values: 0x0000–0x10FFFF, excluding surrogates 0xD800–0xDFFF
43
- if (isNaN(cp) || cp < 0 || cp > 0x10ffff || cp >= 0xd800 && cp <= 0xdfff) {
44
- return undefined;
45
- }
46
- codePoints.push(cp);
61
+ const codePoints = parseEmojiIdCodePoints(id);
62
+ if (!codePoints) {
63
+ return undefined;
47
64
  }
48
- if (codePoints.length === 0) {
65
+ if (isFlagEmoji(codePoints)) {
49
66
  return undefined;
50
67
  }
51
68
  const processedCodePoints = [];
@@ -59,22 +76,11 @@ export function emojiIdToEmoji(id) {
59
76
  if (next === KEYCAP_COMBINING && cp !== VARIATION_SELECTOR_16) {
60
77
  processedCodePoints.push(VARIATION_SELECTOR_16);
61
78
  }
62
- }
63
79
 
64
- // Text-presentation-default emoji: characters that are valid emoji but whose
65
- // default rendering is text (e.g. etc.) must be followed by
66
- // U+FE0F (VARIATION SELECTOR-16) to force emoji presentation.
67
- if (expValEqualsNoExposure('platform_use_unicode_emojis', 'isEnabled', true)) {
68
- const lastCodePoint = processedCodePoints[processedCodePoints.length - 1];
69
- const alreadyHasVariationSelector = lastCodePoint === VARIATION_SELECTOR_16 || lastCodePoint === VARIATION_SELECTOR_15 ||
70
- // Keycap sequences end with U+20E3 — they already have U+FE0F inserted inline
71
- // and must not have another variation selector appended at the end.
72
- lastCodePoint === KEYCAP_COMBINING;
73
- if (!alreadyHasVariationSelector) {
74
- const baseCodePoint = codePoints[0];
75
- if (codePoints.length === 1 && baseCodePoint <= 0xffff && TEXT_DEFAULT_EMOJI.has(baseCodePoint)) {
76
- processedCodePoints.push(VARIATION_SELECTOR_16);
77
- }
80
+ // Emoji variation bases need U+FE0F immediately after the base code point,
81
+ // including when the base appears inside a ZWJ sequence.
82
+ if (shouldAddEmojiPresentationSelector(cp, next)) {
83
+ processedCodePoints.push(VARIATION_SELECTOR_16);
78
84
  }
79
85
  }
80
86
  try {
@@ -5,9 +5,9 @@ import { ax, ix } from "@compiled/react/runtime";
5
5
  import Button from '@atlaskit/button/standard-button';
6
6
  import CrossCircleIcon from '@atlaskit/icon/core/cross-circle';
7
7
  import { deleteEmojiLabel } from '../../util/constants';
8
- import FeatureGates from '@atlaskit/feature-gate-js-client';
9
8
  import { emojiDeleteButton } from './styles';
10
9
  import { Box } from '@atlaskit/primitives/compiled';
10
+ import { expVal } from '@atlaskit/tmp-editor-statsig/expVal';
11
11
  var styles = {
12
12
  boxWrapperStyle: "_1bsbf6fq _4t3if6fq"
13
13
  };
@@ -19,7 +19,7 @@ var refreshedDeleteButton = null;
19
19
  */
20
20
  export var RENDER_EMOJI_DELETE_BUTTON_TESTID = 'render-emoji-delete-button';
21
21
  var DeleteButton = function DeleteButton(props) {
22
- var isRefreshEnabled = FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false);
22
+ var isRefreshEnabled = expVal('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false);
23
23
  return /*#__PURE__*/React.createElement("span", {
24
24
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
25
25
  className: ax(["_3um015vq _1e0c1txw _kqswstnw _154ix0bf _1xi2x0bf _1pbykb7n _13t3idpf", isRefreshEnabled && "_154ir5cr _1xi2r5cr", emojiDeleteButton]),
@@ -492,29 +492,37 @@ export var EmojiNodeWrapper = /*#__PURE__*/forwardRef(function (props, ref) {
492
492
  var ariaLabel = intl && fg('platform_change_emoji_button_label') ? intl.formatMessage(messages.changeEmojiShortnameButtonLabel, {
493
493
  shortName: (_emoji$name = emoji.name) !== null && _emoji$name !== void 0 ? _emoji$name : emoji.shortName
494
494
  }) : editorEmoji ? undefined : emoji.shortName;
495
- return /*#__PURE__*/React.createElement("span", _extends({
495
+ var tooltipContent = showTooltip && expValEquals('platform_editor_emoji_hover_show_tooltip', 'isEnabled', true) ? emoji.shortName || emoji.name || undefined : undefined;
496
+ var emojiSpan = /*#__PURE__*/React.createElement("span", _extends({
496
497
  role: editorEmoji ? undefined : shouldBeInteractive ? 'button' : ariaLabel ? 'img' : 'presentation',
497
498
  "aria-label": ariaLabel,
498
499
  ref: ref,
499
500
  "data-testid": "".concat(type, "-emoji-").concat(emoji.shortName),
500
501
  "data-emoji-type": type,
501
- tabIndex: shouldBeInteractive ? tabIndex || 0 : undefined,
502
+ tabIndex: shouldBeInteractive ? tabIndex || 0 : tooltipContent ? 0 : undefined,
502
503
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
503
504
  className: ax([type === 'sprite' ? "_19pk1n1a _2hwxidpf _otyr1n1a _18u0idpf _1e0c1o8l _jr50g2xd _ylp71o8l _pkaxgktf _1hdcgktf _109tnkob _tn8j1dpa _3naf1dpa _nt751r31 _49pcglyw _1hvw1o36 _7ehi1y54 _491113zc" : type === 'unicode' ? "_19pk1n1a _2hwxidpf _otyr1n1a _18u0idpf _bfhk1j28 _1e0c1o8l _s7n4nkob _tn8j1dpa _3naf1dpa _160jewfl _1theewfl _1kogh2mm _qyp0ewfl _nt751r31 _49pcglyw _1hvw1o36 _7ehi1y54 _491113zc" : "_2rkofajl _19pk1n1a _2hwxidpf _otyr1n1a _18u0idpf _bfhk1j28 _1e0c1o8l _s7n4nkob _v4pn1ule _tn8j1dpa _3naf1dpa _160jewfl _1theewfl _1kogh2mm _qyp0ewfl _nt751r31 _49pcglyw _1hvw1o36 _7ehi1y54 _491113zc", className]),
504
- onKeyDown: function onKeyDown(event) {
505
+ onKeyDown: shouldBeInteractive || !expValEquals('platform_editor_emoji_hover_show_tooltip', 'isEnabled', true) ? function (event) {
505
506
  return handleKeyDown(props, event);
506
- },
507
- onMouseDown: function onMouseDown(event) {
507
+ } : undefined,
508
+ onMouseDown: shouldBeInteractive || !expValEquals('platform_editor_emoji_hover_show_tooltip', 'isEnabled', true) ? function (event) {
508
509
  handleMouseDown(props, event);
509
- },
510
+ } : undefined,
510
511
  onMouseEnter: function onMouseEnter(event) {
511
512
  handleMouseMove(props, event);
512
513
  },
513
514
  onFocus: function onFocus(event) {
514
515
  handleFocus(props, event);
515
516
  },
516
- title: showTooltip ? emoji.shortName : undefined // TODO: COLLAB-2351 - use @atlaskit/Tooltip in future for non-deletable emoji if enabled showTooltip
517
+ title: showTooltip && !expValEquals('platform_editor_emoji_hover_show_tooltip', 'isEnabled', true) ? emoji.shortName : undefined
517
518
  }, other), children);
519
+ if (tooltipContent) {
520
+ return /*#__PURE__*/React.createElement(Tooltip, {
521
+ content: tooltipContent,
522
+ tag: "span"
523
+ }, emojiSpan);
524
+ }
525
+ return emojiSpan;
518
526
  });
519
527
  export var Emoji = function Emoji(props) {
520
528
  var emoji = props.emoji;
@@ -6,6 +6,7 @@ import * as React from 'react';
6
6
  import { ax, ix } from "@compiled/react/runtime";
7
7
  import { Fragment, useState, useRef, memo, useLayoutEffect, useCallback, useEffect } from 'react';
8
8
  import { fg } from '@atlaskit/platform-feature-flags';
9
+ import { expVal } from '@atlaskit/tmp-editor-statsig/expVal';
9
10
  import { FormattedMessage, injectIntl } from 'react-intl';
10
11
  import EmojiDeletePreview from './EmojiDeletePreview';
11
12
  import EmojiUploadPicker from './EmojiUploadPicker';
@@ -20,7 +21,6 @@ import AddIcon from '@atlaskit/icon/core/add';
20
21
  import { setSkinToneAriaLabelText } from './setSkinToneAriaLabelText';
21
22
  import { emojiPickerAddEmoji } from './styles';
22
23
  import { DEFAULT_TONE } from '../../util/constants';
23
- import FeatureGates from '@atlaskit/feature-gate-js-client';
24
24
  import { Box } from '@atlaskit/primitives/compiled';
25
25
  import { layers } from '@atlaskit/theme/constants';
26
26
  var styles = {
@@ -131,9 +131,7 @@ var TonesWrapper = function TonesWrapper(props) {
131
131
  openProductivityColorSelectorWithKeyboard.current = true;
132
132
  }
133
133
  }, []);
134
- var shouldShowProductivityColorSelector = !!(activeCategoryId === 'ATLASSIAN' && productivityColorPreviewEmojis && selectedProductivityColor && onProductivityColorSelected &&
135
- // eslint-disable-next-line @atlaskit/platform/use-recommended-utils
136
- FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false));
134
+ var shouldShowProductivityColorSelector = !!(activeCategoryId === 'ATLASSIAN' && productivityColorPreviewEmojis && selectedProductivityColor && onProductivityColorSelected && expVal('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false));
137
135
  if (shouldShowProductivityColorSelector) {
138
136
  var previewEmoji = (productivityColorPreviewEmojis === null || productivityColorPreviewEmojis === void 0 ? void 0 : productivityColorPreviewEmojis[selectedProductivityColor]) || Object.values(productivityColorPreviewEmojis || {})[0];
139
137
  if (!previewEmoji) {
@@ -214,9 +212,7 @@ export var EmojiActions = function EmojiActions(props) {
214
212
  showToneSelector = _useState6[0],
215
213
  setShowToneSelector = _useState6[1];
216
214
  var wasProductivityColorSelectorOpen = useRef(false);
217
- var shouldUseProductivityColorControl = !!(props.activeCategoryId === 'ATLASSIAN' && props.productivityColorPreviewEmojis && props.selectedProductivityColor && props.onProductivityColorSelected &&
218
- // eslint-disable-next-line @atlaskit/platform/use-recommended-utils
219
- FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false));
215
+ var shouldUseProductivityColorControl = !!(props.activeCategoryId === 'ATLASSIAN' && props.productivityColorPreviewEmojis && props.selectedProductivityColor && props.onProductivityColorSelected && expVal('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false));
220
216
  var onToneOpenHandler = useCallback(function () {
221
217
  return setShowToneSelector(true);
222
218
  }, []);
@@ -254,8 +250,7 @@ export var EmojiActions = function EmojiActions(props) {
254
250
  }
255
251
  }, [shouldUseProductivityColorControl, showToneSelector]);
256
252
  if (uploading) {
257
- // eslint-disable-next-line @atlaskit/platform/use-recommended-utils
258
- return FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? /*#__PURE__*/React.createElement("div", {
253
+ return expVal('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? /*#__PURE__*/React.createElement("div", {
259
254
  className: ax(["_16jlidpf _1o9zidpf _i0dl1wug"])
260
255
  }, /*#__PURE__*/React.createElement(EmojiUploadPicker, {
261
256
  onUploadCancelled: onUploadCancelled,
@@ -274,8 +269,7 @@ export var EmojiActions = function EmojiActions(props) {
274
269
  }));
275
270
  }
276
271
  if (emojiToDelete) {
277
- // eslint-disable-next-line @atlaskit/platform/use-recommended-utils
278
- return FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? /*#__PURE__*/React.createElement("div", {
272
+ return expVal('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? /*#__PURE__*/React.createElement("div", {
279
273
  className: ax(["_16jlidpf _1o9zidpf _i0dl1wug"])
280
274
  }, /*#__PURE__*/React.createElement(EmojiDeletePreview, {
281
275
  emoji: emojiToDelete,
@@ -289,9 +283,7 @@ export var EmojiActions = function EmojiActions(props) {
289
283
  onCloseDelete: onCloseDelete
290
284
  }));
291
285
  }
292
-
293
- // eslint-disable-next-line @atlaskit/platform/use-recommended-utils
294
- return FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? /*#__PURE__*/React.createElement("div", {
286
+ return expVal('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? /*#__PURE__*/React.createElement("div", {
295
287
  "data-testid": emojiActionsTestId,
296
288
  onMouseLeave: onMouseLeaveHandler,
297
289
  onBlur: fg('platform_suppression_removal_fix_reactions') ? onMouseLeaveHandler : undefined,