@atlaskit/emoji 67.1.0 → 67.2.1

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 (134) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/dist/cjs/api/EmojiResource.js +29 -24
  3. package/dist/cjs/api/media/TokenManager.js +4 -4
  4. package/dist/cjs/components/common/CachingEmoji.js +14 -6
  5. package/dist/cjs/components/common/Emoji.js +48 -12
  6. package/dist/cjs/components/common/EmojiActions.js +60 -24
  7. package/dist/cjs/components/common/EmojiErrorMessage.js +12 -7
  8. package/dist/cjs/components/common/EmojiPlaceholder.js +1 -0
  9. package/dist/cjs/components/common/{EmojiButton.js → EmojiRadioButton.js} +28 -19
  10. package/dist/cjs/components/common/EmojiUploadPicker.js +80 -37
  11. package/dist/cjs/components/common/EmojiUploadPreview.js +11 -2
  12. package/dist/cjs/components/common/FileChooser.js +2 -2
  13. package/dist/cjs/components/common/ResourcedEmoji.js +5 -3
  14. package/dist/cjs/components/common/ResourcedEmojiComponent.js +4 -0
  15. package/dist/cjs/components/common/RetryableButton.js +7 -3
  16. package/dist/cjs/components/common/TonePreviewButton.js +44 -0
  17. package/dist/cjs/components/common/ToneSelector.js +53 -25
  18. package/dist/cjs/components/common/styles.js +45 -16
  19. package/dist/cjs/components/i18n.js +44 -4
  20. package/dist/cjs/components/picker/CategorySelector.js +112 -90
  21. package/dist/cjs/components/picker/CategoryTracker.js +0 -28
  22. package/dist/cjs/components/picker/EmojiPickerCategoryHeading.js +2 -1
  23. package/dist/cjs/components/picker/EmojiPickerComponent.js +13 -7
  24. package/dist/cjs/components/picker/EmojiPickerEmojiRow.js +32 -4
  25. package/dist/cjs/components/picker/EmojiPickerList.js +140 -51
  26. package/dist/cjs/components/picker/EmojiPickerListSearch.js +16 -3
  27. package/dist/cjs/components/picker/EmojiPickerVirtualItems.js +5 -2
  28. package/dist/cjs/components/picker/VirtualList.js +196 -14
  29. package/dist/cjs/components/picker/styles.js +43 -51
  30. package/dist/cjs/context/EmojiPickerListContext.js +33 -0
  31. package/dist/cjs/hooks/useEmojiPickerListContext.js +12 -0
  32. package/dist/cjs/util/constants.js +40 -1
  33. package/dist/cjs/util/shared-styles.js +3 -4
  34. package/dist/cjs/version.json +1 -1
  35. package/dist/es2019/api/EmojiResource.js +29 -24
  36. package/dist/es2019/api/media/TokenManager.js +4 -4
  37. package/dist/es2019/components/common/CachingEmoji.js +10 -3
  38. package/dist/es2019/components/common/Emoji.js +44 -11
  39. package/dist/es2019/components/common/EmojiActions.js +54 -23
  40. package/dist/es2019/components/common/EmojiErrorMessage.js +7 -3
  41. package/dist/es2019/components/common/EmojiPlaceholder.js +1 -0
  42. package/dist/es2019/components/common/EmojiRadioButton.js +54 -0
  43. package/dist/es2019/components/common/EmojiUploadPicker.js +75 -36
  44. package/dist/es2019/components/common/EmojiUploadPreview.js +11 -2
  45. package/dist/es2019/components/common/FileChooser.js +1 -1
  46. package/dist/es2019/components/common/ResourcedEmoji.js +5 -3
  47. package/dist/es2019/components/common/ResourcedEmojiComponent.js +4 -0
  48. package/dist/es2019/components/common/RetryableButton.js +7 -3
  49. package/dist/es2019/components/common/TonePreviewButton.js +34 -0
  50. package/dist/es2019/components/common/ToneSelector.js +55 -21
  51. package/dist/es2019/components/common/styles.js +41 -10
  52. package/dist/es2019/components/i18n.js +44 -4
  53. package/dist/es2019/components/picker/CategorySelector.js +114 -89
  54. package/dist/es2019/components/picker/CategoryTracker.js +0 -24
  55. package/dist/es2019/components/picker/EmojiPickerCategoryHeading.js +2 -2
  56. package/dist/es2019/components/picker/EmojiPickerComponent.js +14 -7
  57. package/dist/es2019/components/picker/EmojiPickerEmojiRow.js +51 -21
  58. package/dist/es2019/components/picker/EmojiPickerList.js +102 -21
  59. package/dist/es2019/components/picker/EmojiPickerListSearch.js +14 -4
  60. package/dist/es2019/components/picker/EmojiPickerVirtualItems.js +4 -1
  61. package/dist/es2019/components/picker/VirtualList.js +193 -12
  62. package/dist/es2019/components/picker/styles.js +20 -28
  63. package/dist/es2019/context/EmojiPickerListContext.js +17 -0
  64. package/dist/es2019/hooks/useEmojiPickerListContext.js +3 -0
  65. package/dist/es2019/util/constants.js +31 -0
  66. package/dist/es2019/util/shared-styles.js +1 -2
  67. package/dist/es2019/version.json +1 -1
  68. package/dist/esm/api/EmojiResource.js +29 -24
  69. package/dist/esm/api/media/TokenManager.js +4 -4
  70. package/dist/esm/components/common/CachingEmoji.js +14 -6
  71. package/dist/esm/components/common/Emoji.js +48 -12
  72. package/dist/esm/components/common/EmojiActions.js +61 -25
  73. package/dist/esm/components/common/EmojiErrorMessage.js +7 -3
  74. package/dist/esm/components/common/EmojiPlaceholder.js +1 -0
  75. package/dist/esm/components/common/EmojiRadioButton.js +52 -0
  76. package/dist/esm/components/common/EmojiUploadPicker.js +77 -36
  77. package/dist/esm/components/common/EmojiUploadPreview.js +11 -2
  78. package/dist/esm/components/common/FileChooser.js +1 -1
  79. package/dist/esm/components/common/ResourcedEmoji.js +5 -3
  80. package/dist/esm/components/common/ResourcedEmojiComponent.js +4 -0
  81. package/dist/esm/components/common/RetryableButton.js +7 -3
  82. package/dist/esm/components/common/TonePreviewButton.js +33 -0
  83. package/dist/esm/components/common/ToneSelector.js +49 -18
  84. package/dist/esm/components/common/styles.js +40 -12
  85. package/dist/esm/components/i18n.js +44 -4
  86. package/dist/esm/components/picker/CategorySelector.js +114 -95
  87. package/dist/esm/components/picker/CategoryTracker.js +0 -28
  88. package/dist/esm/components/picker/EmojiPickerCategoryHeading.js +2 -2
  89. package/dist/esm/components/picker/EmojiPickerComponent.js +13 -7
  90. package/dist/esm/components/picker/EmojiPickerEmojiRow.js +32 -4
  91. package/dist/esm/components/picker/EmojiPickerList.js +141 -52
  92. package/dist/esm/components/picker/EmojiPickerListSearch.js +17 -4
  93. package/dist/esm/components/picker/EmojiPickerVirtualItems.js +5 -2
  94. package/dist/esm/components/picker/VirtualList.js +195 -12
  95. package/dist/esm/components/picker/styles.js +37 -45
  96. package/dist/esm/context/EmojiPickerListContext.js +21 -0
  97. package/dist/esm/hooks/useEmojiPickerListContext.js +5 -0
  98. package/dist/esm/util/constants.js +31 -0
  99. package/dist/esm/util/shared-styles.js +1 -2
  100. package/dist/esm/version.json +1 -1
  101. package/dist/types/api/EmojiResource.d.ts +2 -0
  102. package/dist/types/components/common/Emoji.d.ts +7 -1
  103. package/dist/types/components/common/EmojiActions.d.ts +3 -2
  104. package/dist/types/components/common/{EmojiButton.d.ts → EmojiRadioButton.d.ts} +3 -4
  105. package/dist/types/components/common/EmojiUploadPicker.d.ts +6 -4
  106. package/dist/types/components/common/RetryableButton.d.ts +1 -0
  107. package/dist/types/components/common/TonePreviewButton.d.ts +14 -0
  108. package/dist/types/components/common/ToneSelector.d.ts +8 -5
  109. package/dist/types/components/common/internal-types.d.ts +9 -0
  110. package/dist/types/components/common/styles.d.ts +2 -1
  111. package/dist/types/components/i18n.d.ts +40 -0
  112. package/dist/types/components/picker/CategorySelector.d.ts +3 -10
  113. package/dist/types/components/picker/CategoryTracker.d.ts +0 -2
  114. package/dist/types/components/picker/EmojiPickerCategoryHeading.d.ts +2 -1
  115. package/dist/types/components/picker/EmojiPickerEmojiRow.d.ts +5 -0
  116. package/dist/types/components/picker/EmojiPickerList.d.ts +10 -5
  117. package/dist/types/components/picker/EmojiPickerListSearch.d.ts +1 -0
  118. package/dist/types/components/picker/EmojiPickerVirtualItems.d.ts +1 -1
  119. package/dist/types/components/picker/VirtualList.d.ts +2 -0
  120. package/dist/types/components/picker/styles.d.ts +1 -1
  121. package/dist/types/context/EmojiPickerListContext.d.ts +10 -0
  122. package/dist/types/hooks/useEmojiPickerListContext.d.ts +1 -0
  123. package/dist/types/util/constants.d.ts +27 -0
  124. package/dist/types/util/shared-styles.d.ts +1 -1
  125. package/dist/types/util/type-helpers.d.ts +1 -1
  126. package/package.json +9 -6
  127. package/report.api.md +52 -1
  128. package/README.md +0 -3
  129. package/dist/es2019/components/common/EmojiButton.js +0 -49
  130. package/dist/esm/components/common/EmojiButton.js +0 -43
  131. /package/dist/cjs/{components/hooks.js → hooks/useIsMounted.js} +0 -0
  132. /package/dist/es2019/{components/hooks.js → hooks/useIsMounted.js} +0 -0
  133. /package/dist/esm/{components/hooks.js → hooks/useIsMounted.js} +0 -0
  134. /package/dist/types/{components/hooks.d.ts → hooks/useIsMounted.d.ts} +0 -0
@@ -1,22 +1,25 @@
1
1
  "use strict";
2
2
 
3
3
  var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
- var _typeof = require("@babel/runtime/helpers/typeof");
5
4
  Object.defineProperty(exports, "__esModule", {
6
5
  value: true
7
6
  });
8
- exports.default = exports.ToneSelectorInternal = void 0;
7
+ exports.toneSelectorTestId = exports.default = exports.ToneSelectorInternal = void 0;
9
8
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
10
9
  var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
11
- var _react = _interopRequireWildcard(require("react"));
12
- var _EmojiButton = _interopRequireDefault(require("./EmojiButton"));
10
+ var _react = require("@emotion/react");
11
+ var _react2 = require("react");
13
12
  var _analyticsNext = require("@atlaskit/analytics-next");
14
13
  var _analytics = require("../../util/analytics");
15
14
  var _setSkinToneAriaLabelText = require("./setSkinToneAriaLabelText");
16
- function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
17
- function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
15
+ var _EmojiRadioButton = _interopRequireDefault(require("./EmojiRadioButton"));
16
+ var _reactIntlNext = require("react-intl-next");
17
+ var _i18n = require("../i18n");
18
+ var _styles = require("./styles");
18
19
  function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
19
20
  function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
21
+ var toneSelectorTestId = 'tone-selector';
22
+ exports.toneSelectorTestId = toneSelectorTestId;
20
23
  var extractAllTones = function extractAllTones(emoji) {
21
24
  if (emoji.skinVariations) {
22
25
  return [emoji].concat((0, _toConsumableArray2.default)(emoji.skinVariations));
@@ -26,24 +29,39 @@ var extractAllTones = function extractAllTones(emoji) {
26
29
  var ToneSelectorInternal = function ToneSelectorInternal(props) {
27
30
  var createAnalyticsEvent = props.createAnalyticsEvent,
28
31
  emoji = props.emoji,
29
- previewEmojiId = props.previewEmojiId,
30
- onToneSelected = props.onToneSelected;
31
- var isMounted = (0, _react.useRef)(false);
32
- var firstToneButtonRef = (0, _react.useRef)(null);
33
- var emojiToneCollection = (0, _react.useMemo)(function () {
34
- return extractAllTones(emoji).map(function (tone, index) {
32
+ onToneSelected = props.onToneSelected,
33
+ onToneClose = props.onToneClose,
34
+ selectedTone = props.selectedTone,
35
+ isVisible = props.isVisible;
36
+ var isMounted = (0, _react2.useRef)(false);
37
+ var selectedToneRadioRef = (0, _react2.useRef)(null);
38
+ var _useIntl = (0, _reactIntlNext.useIntl)(),
39
+ formatMessage = _useIntl.formatMessage;
40
+ var emojiToneCollection = (0, _react2.useMemo)(function () {
41
+ var selectedToneIndex = -1;
42
+ var toneColletion = extractAllTones(emoji).map(function (tone, index) {
43
+ var isSelected = index === selectedTone;
44
+ if (isSelected) {
45
+ selectedToneIndex = index;
46
+ }
35
47
  return _objectSpread(_objectSpread({}, tone), {}, {
36
- focused: tone.id !== previewEmojiId,
48
+ isSelected: isSelected,
37
49
  label: (0, _setSkinToneAriaLabelText.setSkinToneAriaLabelText)(tone.name),
38
- toneId: index
50
+ toneIndex: index
39
51
  });
40
52
  });
41
- }, [emoji, previewEmojiId]);
42
- (0, _react.useEffect)(function () {
43
- if (firstToneButtonRef.current) {
44
- firstToneButtonRef.current.focus();
53
+
54
+ // push description of selected tone to the end of the array
55
+ // so that it gets rendered last/rightmost
56
+ toneColletion.push(toneColletion.splice(selectedToneIndex, 1)[0]);
57
+ return toneColletion;
58
+ }, [emoji, selectedTone]);
59
+ (0, _react2.useEffect)(function () {
60
+ if (isVisible) {
61
+ var _selectedToneRadioRef;
62
+ (_selectedToneRadioRef = selectedToneRadioRef.current) === null || _selectedToneRadioRef === void 0 ? void 0 : _selectedToneRadioRef.focus();
45
63
  }
46
- }, [firstToneButtonRef]);
64
+ }, [isVisible, selectedToneRadioRef]);
47
65
  var fireAnalyticsEvent = function fireAnalyticsEvent(event) {
48
66
  if (createAnalyticsEvent) {
49
67
  (0, _analytics.createAndFireEventInElementsChannel)(event)(createAnalyticsEvent);
@@ -51,6 +69,10 @@ var ToneSelectorInternal = function ToneSelectorInternal(props) {
51
69
  };
52
70
  var onToneSelectedHandler = function onToneSelectedHandler(toneValue) {
53
71
  return function () {
72
+ if (selectedTone === toneValue && onToneClose) {
73
+ onToneClose();
74
+ return;
75
+ }
54
76
  onToneSelected(toneValue);
55
77
  var toneList = ['default', 'light', 'mediumLight', 'medium', 'mediumDark', 'dark'];
56
78
  fireAnalyticsEvent((0, _analytics.toneSelectedEvent)({
@@ -62,19 +84,25 @@ var ToneSelectorInternal = function ToneSelectorInternal(props) {
62
84
  fireAnalyticsEvent((0, _analytics.toneSelectorOpenedEvent)({}));
63
85
  }
64
86
  isMounted.current = true;
65
- return /*#__PURE__*/_react.default.createElement("div", null, emojiToneCollection.map(function (tone) {
66
- return /*#__PURE__*/_react.default.createElement(_EmojiButton.default, {
67
- ref: tone.focused ? firstToneButtonRef : null,
68
- shouldHideButton: tone.id === previewEmojiId,
87
+ return (0, _react.jsx)("div", {
88
+ role: "radiogroup",
89
+ "data-testid": toneSelectorTestId,
90
+ id: "emoji-picker-tone-selector",
91
+ "aria-label": formatMessage(_i18n.messages.emojiSelectSkinToneListAriaLabelText),
92
+ css: !isVisible && _styles.hidden
93
+ }, emojiToneCollection.map(function (tone) {
94
+ return (0, _react.jsx)(_EmojiRadioButton.default, {
95
+ ref: tone.isSelected ? selectedToneRadioRef : null,
96
+ defaultChecked: tone.isSelected,
69
97
  ariaLabelText: tone.label,
70
98
  key: "".concat(tone.id),
71
- onSelected: onToneSelectedHandler(tone.toneId),
72
99
  emoji: tone,
100
+ onSelected: onToneSelectedHandler(tone.toneIndex),
73
101
  selectOnHover: true
74
102
  });
75
103
  }));
76
104
  };
77
105
  exports.ToneSelectorInternal = ToneSelectorInternal;
78
106
  var ToneSelector = (0, _analyticsNext.withAnalyticsEvents)()(ToneSelectorInternal);
79
- var _default = ToneSelector;
107
+ var _default = /*#__PURE__*/(0, _react2.memo)(ToneSelector);
80
108
  exports.default = _default;
@@ -4,12 +4,11 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
- exports.uploadRetryButton = exports.uploadPreviewText = exports.uploadPreviewFooter = exports.uploadPreview = exports.uploadEmojiButton = exports.uploadChooseFileRow = exports.uploadChooseFileMessage = exports.uploadChooseFileEmojiName = exports.uploadChooseFileBrowse = exports.uploadAddRow = exports.submitDelete = exports.selectOnHoverStyles = exports.previewText = exports.previewImg = exports.previewButtonGroup = exports.preview = exports.placeholderContainerAnimated = exports.placeholderContainer = exports.placeholder = exports.hiddenToneButton = exports.emojiUploadTop = exports.emojiUploadBottom = exports.emojiUpload = exports.emojiToneSelectorContainer = exports.emojiStyles = exports.emojiSprite = exports.emojiShortName = exports.emojiScrollable = exports.emojiPreviewErrorMessage = exports.emojiPickerAddEmoji = exports.emojiNodeStyles = exports.emojiName = exports.emojiMainStyle = exports.emojiImage = exports.emojiDeleteErrorMessage = exports.emojiDeleteButton = exports.emojiContainer = exports.emojiChooseFileErrorMessage = exports.emojiButton = exports.emojiActionsWrapper = exports.deleteText = exports.deletePreview = exports.deleteFooter = exports.deleteButton = exports.commonSelectedStyles = exports.closeEmojiUploadButton = exports.cancelButton = exports.buttonSpinner = exports.bigEmojiPreview = exports.addCustomEmojiButton = exports.addCustomEmoji = void 0;
7
+ exports.uploadRetryButton = exports.uploadPreviewText = exports.uploadPreviewFooter = exports.uploadPreview = exports.uploadEmojiButton = exports.uploadChooseFileRow = exports.uploadChooseFileMessage = exports.uploadChooseFileEmojiName = exports.uploadChooseFileBrowse = exports.uploadAddRow = exports.submitDelete = exports.selectOnHoverStyles = exports.previewText = exports.previewImg = exports.previewButtonGroup = exports.preview = exports.placeholderContainerAnimated = exports.placeholderContainer = exports.placeholder = exports.hidden = exports.emojiUploadTop = exports.emojiUploadBottom = exports.emojiUpload = exports.emojiToneSelectorContainer = exports.emojiStyles = exports.emojiSprite = exports.emojiShortName = exports.emojiScrollable = exports.emojiRadio = exports.emojiPreviewErrorMessage = exports.emojiPickerAddEmoji = exports.emojiNodeStyles = exports.emojiName = exports.emojiMainStyle = exports.emojiImage = exports.emojiDeleteErrorMessage = exports.emojiDeleteButton = exports.emojiContainer = exports.emojiChooseFileErrorMessage = exports.emojiButton = exports.emojiActionsWrapper = exports.deleteText = exports.deletePreview = exports.deleteFooter = exports.deleteButton = exports.commonSelectedStyles = exports.closeEmojiUploadButton = exports.cancelButton = exports.buttonSpinner = exports.bigEmojiPreview = exports.addCustomEmojiButton = exports.addCustomEmoji = void 0;
8
8
  var _taggedTemplateLiteral2 = _interopRequireDefault(require("@babel/runtime/helpers/taggedTemplateLiteral"));
9
9
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
10
10
  var _react = require("@emotion/react");
11
- var _constants = require("@atlaskit/theme/constants");
12
- var _constants2 = require("../../util/constants");
11
+ var _constants = require("../../util/constants");
13
12
  var _sharedStyles = require("../../util/shared-styles");
14
13
  var _colors = require("@atlaskit/theme/colors");
15
14
  var _css, _css2, _templateObject, _span, _css3, _css6, _input;
@@ -49,7 +48,7 @@ var emojiToneSelectorContainer = (0, _react.css)({
49
48
  });
50
49
  exports.emojiToneSelectorContainer = emojiToneSelectorContainer;
51
50
  var emojiStyles = (0, _react.css)((_css = {
52
- borderRadius: "".concat((0, _constants.borderRadius)(), "px"),
51
+ borderRadius: "var(--ds-radius-100, 3px)",
53
52
  backgroundColor: 'transparent',
54
53
  display: 'inline-block',
55
54
  verticalAlign: 'middle',
@@ -64,6 +63,10 @@ var emojiStyles = (0, _react.css)((_css = {
64
63
  visibility: 'visible'
65
64
  }), (0, _defineProperty2.default)(_css, "img", {
66
65
  display: 'block'
66
+ }), (0, _defineProperty2.default)(_css, '&:focus', {
67
+ boxShadow: "0 0 0 2px ".concat("var(--ds-border-focused, ".concat(_colors.B100, ")")),
68
+ transitionDuration: '0s, 0.2s',
69
+ outline: 'none'
67
70
  }), _css));
68
71
  exports.emojiStyles = emojiStyles;
69
72
  var emojiContainer = (0, _react.css)((_css2 = {
@@ -75,9 +78,13 @@ var emojiContainer = (0, _react.css)((_css2 = {
75
78
  }), (0, _defineProperty2.default)(_css2, ".".concat(emojiSprite), {
76
79
  background: 'transparent no-repeat',
77
80
  display: 'inline-block',
78
- minHeight: "".concat(_constants2.defaultEmojiHeight, "px"),
79
- minWidth: "".concat(_constants2.defaultEmojiHeight, "px"),
81
+ minHeight: "".concat(_constants.defaultEmojiHeight, "px"),
82
+ minWidth: "".concat(_constants.defaultEmojiHeight, "px"),
80
83
  verticalAlign: 'middle'
84
+ }), (0, _defineProperty2.default)(_css2, '&:focus', {
85
+ boxShadow: "0 0 0 2px ".concat("var(--ds-border-focused, ".concat(_colors.B100, ")")),
86
+ transitionDuration: '0s, 0.2s',
87
+ outline: 'none'
81
88
  }), _css2));
82
89
  exports.emojiContainer = emojiContainer;
83
90
  var placeholder = 'emoji-common-placeholder';
@@ -87,7 +94,7 @@ var placeholderContainer = (0, _react.css)({
87
94
  margin: '-1px 0',
88
95
  display: 'inline-block',
89
96
  background: "var(--ds-border, #f7f7f7)",
90
- borderRadius: "".concat((0, _constants.borderRadius)(), "px"),
97
+ borderRadius: "var(--ds-radius-100, 3px)",
91
98
  overflow: 'hidden',
92
99
  verticalAlign: 'middle',
93
100
  whiteSpace: 'nowrap',
@@ -107,16 +114,24 @@ var placeholderContainerAnimated = (0, _react.css)({
107
114
  }
108
115
  });
109
116
  exports.placeholderContainerAnimated = placeholderContainerAnimated;
117
+ var hidden = (0, _react.css)({
118
+ opacity: 0,
119
+ visibility: 'hidden',
120
+ display: 'none'
121
+ });
122
+ exports.hidden = hidden;
110
123
  var emojiButton = (0, _react.css)((_css3 = {
111
124
  backgroundColor: 'transparent',
112
125
  border: '0',
126
+ borderRadius: "var(--ds-radius-100, 3px)",
113
127
  cursor: 'pointer',
114
- padding: 0
128
+ padding: 0,
129
+ position: 'relative',
130
+ display: 'inline-block'
115
131
  }, (0, _defineProperty2.default)(_css3, '&::-moz-focus-inner', {
116
132
  border: '0 none',
117
133
  padding: 0
118
134
  }), (0, _defineProperty2.default)(_css3, '&>span', (_span = {
119
- borderRadius: "".concat((0, _constants.borderRadius)(), "px"),
120
135
  padding: '6px'
121
136
  }, (0, _defineProperty2.default)(_span, "&>.".concat(emojiSprite), {
122
137
  height: '24px',
@@ -124,15 +139,29 @@ var emojiButton = (0, _react.css)((_css3 = {
124
139
  }), (0, _defineProperty2.default)(_span, "&>img", {
125
140
  height: '24px',
126
141
  width: '24px'
127
- }), _span)), _css3));
142
+ }), _span)), (0, _defineProperty2.default)(_css3, '&:focus', {
143
+ boxShadow: "0 0 0 2px ".concat("var(--ds-border-focused, ".concat(_colors.B100, ")")),
144
+ transitionDuration: '0s, 0.2s',
145
+ outline: 'none'
146
+ }), _css3));
128
147
  exports.emojiButton = emojiButton;
129
- var hiddenToneButton = (0, _react.css)({
130
- // Hide currently selected tone that rendered in the ToneSelector to avoid duplication
131
- display: 'none'
148
+ var emojiRadio = (0, _react.css)({
149
+ opacity: 0,
150
+ position: 'absolute',
151
+ top: '-10px',
152
+ left: '-10px',
153
+ '+span': {
154
+ borderRadius: "var(--ds-radius-100, 3px)"
155
+ },
156
+ '&:focus + span': {
157
+ boxShadow: "0 0 0 2px ".concat("var(--ds-border-focused, ".concat(_colors.B100, ")")),
158
+ transitionDuration: '0s, 0.2s',
159
+ outline: 'none'
160
+ }
132
161
  });
133
162
 
134
163
  // Emoji Preview
135
- exports.hiddenToneButton = hiddenToneButton;
164
+ exports.emojiRadio = emojiRadio;
136
165
  var emojiPickerAddEmoji = 'emoji-picker-add-emoji';
137
166
  exports.emojiPickerAddEmoji = emojiPickerAddEmoji;
138
167
  var previewText = (0, _react.css)({
@@ -205,7 +234,7 @@ var previewImg = (0, _react.css)((_css6 = {
205
234
  exports.previewImg = previewImg;
206
235
  var emojiScrollable = (0, _react.css)({
207
236
  border: "1px solid ".concat("var(--ds-border, #fff)"),
208
- borderRadius: "".concat((0, _constants.borderRadius)(), "px"),
237
+ borderRadius: "var(--ds-radius-100, 3px)",
209
238
  display: 'block',
210
239
  margin: '0',
211
240
  overflowX: 'hidden',
@@ -279,7 +308,7 @@ var uploadPreview = (0, _react.css)({
279
308
  justifyContent: 'space-between',
280
309
  alignItems: 'center',
281
310
  background: "var(--ds-background-neutral, ".concat(_colors.N20, ")"),
282
- borderRadius: "".concat((0, _constants.borderRadius)(), "px"),
311
+ borderRadius: "var(--ds-radius-100, 3px)",
283
312
  padding: '10px'
284
313
  });
285
314
  exports.uploadPreview = uploadPreview;
@@ -28,8 +28,8 @@ var messages = (0, _reactIntlNext.defineMessages)({
28
28
  },
29
29
  emojiPlaceholder: {
30
30
  id: 'fabric.emoji.placeholder',
31
- defaultMessage: 'Emoji name',
32
- description: 'Placeholder for emoji'
31
+ defaultMessage: 'e.g. hello',
32
+ description: 'Placeholder for emoji that provides an example for emoji name'
33
33
  },
34
34
  emojiNameAriaLabel: {
35
35
  id: 'fabric.emoji.name.ariaLabel',
@@ -48,9 +48,14 @@ var messages = (0, _reactIntlNext.defineMessages)({
48
48
  },
49
49
  emojiSelectSkinToneButtonAriaLabelText: {
50
50
  id: 'fabric.emoji.select.skin.tone.ariaLabel',
51
- defaultMessage: 'Select skin tone, {selectedTone}',
51
+ defaultMessage: 'Choose your skin tone, {selectedTone} selected',
52
52
  description: 'Message indicating the purpose of the skin tone selection button and the selected tone'
53
53
  },
54
+ emojiSelectSkinToneListAriaLabelText: {
55
+ id: 'fabric.emoji.select.skin.list.ariaLabel',
56
+ defaultMessage: 'Skin tone selector',
57
+ description: 'Message indicating the purpose of the skin tone list and make user to choose one tone'
58
+ },
54
59
  emojiImageRequirements: {
55
60
  id: 'fabric.emoji.image.requirements',
56
61
  defaultMessage: 'JPG, PNG or GIF. Max size 1 MB.',
@@ -88,9 +93,24 @@ var messages = (0, _reactIntlNext.defineMessages)({
88
93
  },
89
94
  searchLabel: {
90
95
  id: 'fabric.emoji.search.label',
91
- defaultMessage: 'Search emoji',
96
+ defaultMessage: 'Emoji name',
92
97
  description: 'verb - button label to search'
93
98
  },
99
+ searchResultsStatus: {
100
+ id: 'fabric.emoji.search.status',
101
+ defaultMessage: 'Found {count} emojis',
102
+ description: 'search results status for screenreader to read out'
103
+ },
104
+ searchResultsStatusSeeAll: {
105
+ id: 'fabric.emoji.search.status',
106
+ defaultMessage: 'Seeing all emojis',
107
+ description: 'search results status when no search query for screenreader to read out'
108
+ },
109
+ categoriesSelectorLabel: {
110
+ id: 'fabric.emoji.categories.label',
111
+ defaultMessage: 'Choose a emoji category',
112
+ description: 'Aria label for Emoji categories selector at the top of emoji picker'
113
+ },
94
114
  categoriesSearchResults: {
95
115
  id: 'fabric.emoji.categories.search.results',
96
116
  defaultMessage: 'Search results',
@@ -175,6 +195,26 @@ var messages = (0, _reactIntlNext.defineMessages)({
175
195
  id: 'fabric.emoji.error.image.too.big',
176
196
  defaultMessage: 'Selected image is more than 1 MB',
177
197
  description: 'Error message for image too big, beyond the size limit'
198
+ },
199
+ emojiPickerTitle: {
200
+ id: 'fabric.emoji.picker',
201
+ defaultMessage: 'Emoji picker',
202
+ description: 'Aria label for emoji picker'
203
+ },
204
+ emojiPickerListPanel: {
205
+ id: 'fabric.emoji.pickerlist.tabpanel',
206
+ defaultMessage: 'Emojis actions and list panel',
207
+ description: 'Aria lable for tabpanel of emoji picker, which shows emojis actions and list'
208
+ },
209
+ emojiPickerGrid: {
210
+ id: 'fabric.emoji.pickerlist.grid',
211
+ defaultMessage: '{showSearchResults, select, true{Search results} other{Emojis}}',
212
+ description: "Aria label for emoji picker grid, showSearchResults is a boolean variable, message will be \"Entering Emojis table\", or \"Leaving Emojis\""
213
+ },
214
+ emojiButtonRoleDescription: {
215
+ id: 'fabric.emoji.emojipicker.emoi.roledescription',
216
+ defaultMessage: 'emoji button',
217
+ description: "Aria roledescription for emoji button, used in emoji picker."
178
218
  }
179
219
  });
180
220
  exports.messages = messages;
@@ -6,24 +6,21 @@ Object.defineProperty(exports, "__esModule", {
6
6
  value: true
7
7
  });
8
8
  exports.sortCategories = exports.default = exports.categorySelectorComponentTestId = exports.categorySelectorCategoryTestId = void 0;
9
- var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
10
- var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
11
- var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized"));
12
- var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
13
- var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));
14
- var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));
15
- var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
16
10
  var _react = _interopRequireWildcard(require("react"));
17
11
  var _react2 = require("@emotion/react");
18
12
  var _reactIntlNext = require("react-intl-next");
13
+ var _tooltip = _interopRequireDefault(require("@atlaskit/tooltip"));
19
14
  var _constants = require("../../util/constants");
20
15
  var _i18n = require("../i18n");
21
16
  var _categories = require("./categories");
22
17
  var _styles = require("./styles");
18
+ var _usePrevious = require("../../hooks/usePrevious");
19
+ var _EmojiPickerList = require("./EmojiPickerList");
23
20
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
24
21
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
25
- function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = (0, _getPrototypeOf2.default)(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = (0, _getPrototypeOf2.default)(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return (0, _possibleConstructorReturn2.default)(this, result); }; }
26
- function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
22
+ /** @jsx jsx */
23
+
27
24
  var sortCategories = function sortCategories(c1, c2) {
28
25
  return _categories.CategoryDescriptionMap[c1].order - _categories.CategoryDescriptionMap[c2].order;
29
26
  };
@@ -42,95 +39,120 @@ var categorySelectorCategoryTestId = function categorySelectorCategoryTestId(cat
42
39
  return "category-selector-".concat(categoryId);
43
40
  };
44
41
  exports.categorySelectorCategoryTestId = categorySelectorCategoryTestId;
45
- var CategorySelector = /*#__PURE__*/function (_PureComponent) {
46
- (0, _inherits2.default)(CategorySelector, _PureComponent);
47
- var _super = _createSuper(CategorySelector);
48
- function CategorySelector(props) {
49
- var _this;
50
- (0, _classCallCheck2.default)(this, CategorySelector);
51
- _this = _super.call(this, props);
52
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "onClick", function (event) {
53
- var _this$props = _this.props,
54
- onCategorySelected = _this$props.onCategorySelected,
55
- disableCategories = _this$props.disableCategories;
42
+ var CategorySelector = function CategorySelector(props) {
43
+ var disableCategories = props.disableCategories,
44
+ dynamicCategories = props.dynamicCategories,
45
+ activeCategoryId = props.activeCategoryId,
46
+ onCategorySelected = props.onCategorySelected;
47
+ var _useState = (0, _react.useState)(addNewCategories(_constants.defaultCategories, dynamicCategories)),
48
+ _useState2 = (0, _slicedToArray2.default)(_useState, 2),
49
+ categories = _useState2[0],
50
+ setCategories = _useState2[1];
51
+ var _useState3 = (0, _react.useState)(0),
52
+ _useState4 = (0, _slicedToArray2.default)(_useState3, 2),
53
+ currentFocus = _useState4[0],
54
+ setCurrentFocus = _useState4[1];
55
+ var categoryRef = (0, _react.useRef)(null);
56
+ var prevDynamicCategories = (0, _usePrevious.usePrevious)(dynamicCategories);
57
+ var _useIntl = (0, _reactIntlNext.useIntl)(),
58
+ formatMessage = _useIntl.formatMessage;
59
+ var updateCategories = (0, _react.useCallback)(function () {
60
+ var newCategories = addNewCategories(_constants.defaultCategories, dynamicCategories);
61
+ setCategories(newCategories);
62
+ }, [dynamicCategories]);
63
+ (0, _react.useEffect)(function () {
64
+ if (prevDynamicCategories !== dynamicCategories) {
65
+ updateCategories();
66
+ }
67
+ }, [prevDynamicCategories, dynamicCategories, updateCategories]);
68
+ var focusCategory = (0, _react.useCallback)(function (index) {
69
+ var _categoryRef$current;
70
+ var categoryToFocus = (_categoryRef$current = categoryRef.current) === null || _categoryRef$current === void 0 ? void 0 : _categoryRef$current.querySelector("[data-focus-index=\"".concat(index, "\"]"));
71
+ categoryToFocus && categoryToFocus.focus();
72
+ setCurrentFocus(index);
73
+ }, [categoryRef, setCurrentFocus]);
74
+ var handleKeyDown = function handleKeyDown(e) {
75
+ if (!_constants.CATEGORYSELECTOR_KEYBOARD_KEYS_SUPPORTED.includes(e.key)) {
76
+ return;
77
+ }
78
+ e.preventDefault();
79
+ var lastCategoryIndex = categories.length - 1;
80
+ switch (e.key) {
81
+ // navigate to the right category
82
+ case _constants.KeyboardKeys.ArrowRight:
83
+ focusCategory(currentFocus === lastCategoryIndex ? 0 : currentFocus + 1);
84
+ break;
85
+ // navigate to the left category
86
+ case _constants.KeyboardKeys.ArrowLeft:
87
+ focusCategory(currentFocus === 0 ? lastCategoryIndex : currentFocus - 1);
88
+ break;
89
+ // navigate to the first category
90
+ case _constants.KeyboardKeys.Home:
91
+ focusCategory(0);
92
+ break;
93
+ // navigate to the last category
94
+ case _constants.KeyboardKeys.End:
95
+ focusCategory(lastCategoryIndex);
96
+ break;
97
+ }
98
+ };
99
+ var handleClick = function handleClick(categoryId, index) {
100
+ return function (event) {
56
101
  if (disableCategories) {
57
102
  event.preventDefault();
58
103
  return;
59
104
  }
60
- var categoryId = event.currentTarget.getAttribute('data-category-id');
61
105
  if (onCategorySelected) {
62
106
  onCategorySelected(categoryId);
63
107
  }
64
- });
65
- var dynamicCategories = props.dynamicCategories;
66
- var categories = _constants.defaultCategories;
67
- if (dynamicCategories) {
68
- categories = addNewCategories(categories, dynamicCategories);
69
- }
70
- _this.state = {
71
- categories: categories
108
+ setCurrentFocus(index);
72
109
  };
73
- return _this;
74
- }
75
- (0, _createClass2.default)(CategorySelector, [{
76
- key: "UNSAFE_componentWillUpdate",
77
- value: function UNSAFE_componentWillUpdate(nextProps) {
78
- if (this.props.dynamicCategories !== nextProps.dynamicCategories) {
79
- this.setState({
80
- categories: addNewCategories(_constants.defaultCategories, nextProps.dynamicCategories)
81
- });
110
+ };
111
+ var categoriesSection;
112
+ if (categories) {
113
+ categoriesSection = (0, _react2.jsx)("div", {
114
+ role: "tablist",
115
+ "aria-label": formatMessage(_i18n.messages.categoriesSelectorLabel),
116
+ "data-testid": categorySelectorComponentTestId,
117
+ ref: categoryRef,
118
+ css: _styles.categorySelectorTablist
119
+ }, categories.map(function (categoryId, index) {
120
+ var category = _categories.CategoryDescriptionMap[categoryId];
121
+ var categoryClasses = [_styles.categoryStyles];
122
+ if (categoryId === activeCategoryId) {
123
+ categoryClasses.push(_styles.active);
82
124
  }
83
- }
84
- }, {
85
- key: "render",
86
- value: function render() {
87
- var _this2 = this;
88
- var _this$props2 = this.props,
89
- disableCategories = _this$props2.disableCategories,
90
- intl = _this$props2.intl;
91
- var categories = this.state.categories;
92
- var categoriesSection;
93
- if (categories) {
94
- var formatMessage = intl.formatMessage;
95
- categoriesSection = (0, _react2.jsx)("ul", {
96
- "data-testid": categorySelectorComponentTestId
97
- }, categories.map(function (categoryId) {
98
- var category = _categories.CategoryDescriptionMap[categoryId];
99
- var categoryClasses = [_styles.categoryStyles];
100
- if (categoryId === _this2.props.activeCategoryId) {
101
- categoryClasses.push(_styles.active);
102
- }
103
- if (disableCategories) {
104
- categoryClasses.push(_styles.disable);
105
- }
106
- var Icon = category.icon;
107
- var categoryName = formatMessage(_i18n.messages[category.name]);
108
- return (0, _react2.jsx)("li", {
109
- key: category.id
110
- }, (0, _react2.jsx)("button", {
111
- "aria-label": categoryName,
112
- "data-category-id": category.id,
113
- disabled: disableCategories,
114
- css: categoryClasses,
115
- onClick: _this2.onClick,
116
- title: categoryName,
117
- type: "button",
118
- "data-testid": categorySelectorCategoryTestId(categoryId)
119
- }, (0, _react2.jsx)(Icon, {
120
- label: categoryName
121
- })));
122
- }));
125
+ if (disableCategories) {
126
+ categoryClasses.push(_styles.disable);
123
127
  }
124
- return (0, _react2.jsx)("div", {
125
- css: _styles.categorySelector
126
- }, categoriesSection);
127
- }
128
- }]);
129
- return CategorySelector;
130
- }(_react.PureComponent);
131
- (0, _defineProperty2.default)(CategorySelector, "defaultProps", {
132
- onCategorySelected: function onCategorySelected() {},
133
- dynamicCategories: []
134
- });
135
- var _default = (0, _reactIntlNext.injectIntl)(CategorySelector);
128
+ var Icon = category.icon;
129
+ var categoryName = formatMessage(_i18n.messages[category.name]);
130
+ return (0, _react2.jsx)(_tooltip.default, {
131
+ content: categoryName,
132
+ position: "bottom",
133
+ key: category.id
134
+ }, (0, _react2.jsx)("button", {
135
+ type: "button",
136
+ id: "category-selector-".concat(category.id),
137
+ "data-focus-index": index,
138
+ "aria-label": categoryName,
139
+ "aria-controls": currentFocus === index ? _EmojiPickerList.RENDER_EMOJI_PICKER_LIST_TESTID : undefined,
140
+ "aria-selected": currentFocus === index ? true : false,
141
+ css: categoryClasses,
142
+ disabled: disableCategories,
143
+ onClick: handleClick(categoryId, index),
144
+ "data-testid": categorySelectorCategoryTestId(categoryId),
145
+ tabIndex: currentFocus === index ? 0 : -1,
146
+ onKeyDown: handleKeyDown,
147
+ role: "tab"
148
+ }, (0, _react2.jsx)(Icon, {
149
+ label: categoryName
150
+ })));
151
+ }));
152
+ }
153
+ return (0, _react2.jsx)("div", {
154
+ css: _styles.categorySelector
155
+ }, categoriesSection);
156
+ };
157
+ var _default = CategorySelector;
136
158
  exports.default = _default;
@@ -37,34 +37,6 @@ var CategoryTracker = /*#__PURE__*/function () {
37
37
  value: function getRow(category) {
38
38
  return this.categoryToRow.get(category);
39
39
  }
40
- }, {
41
- key: "findNearestCategoryAbove",
42
- value: function findNearestCategoryAbove(startIndex, list) {
43
- var rows = Array.from(this.rowToCategory.keys()).sort(function (a, b) {
44
- return a - b;
45
- });
46
- if (rows.length === 0) {
47
- return;
48
- }
49
-
50
- // Return first category if list not yet rendered
51
- // or the top row is above the first category
52
- if (!list || rows[0] > startIndex) {
53
- return this.rowToCategory.get(rows[0]);
54
- }
55
- var bounds = [0, rows.length - 1];
56
- var index = Math.floor(rows.length / 2);
57
- while (rows[index] !== startIndex && bounds[0] < bounds[1]) {
58
- if (rows[index] > startIndex) {
59
- bounds[1] = Math.max(index - 1, 0);
60
- } else {
61
- bounds[0] = index + 1;
62
- }
63
- index = Math.floor((bounds[0] + bounds[1]) / 2);
64
- }
65
- var headerRow = rows[rows[index] > startIndex ? Math.max(index - 1, 0) : index];
66
- return this.rowToCategory.get(headerRow);
67
- }
68
40
  }]);
69
41
  return CategoryTracker;
70
42
  }();
@@ -24,7 +24,8 @@ var EmojiPickerCategoryHeading = function EmojiPickerCategoryHeading(_ref) {
24
24
  id: id,
25
25
  "data-category-id": id,
26
26
  className: className,
27
- "data-testid": RENDER_EMOJI_PICKER_CATEGORY_HEADING_TESTID
27
+ "data-testid": RENDER_EMOJI_PICKER_CATEGORY_HEADING_TESTID,
28
+ role: "rowheader"
28
29
  }, (0, _react.jsx)("div", {
29
30
  css: _styles.emojiCategoryTitle
30
31
  }, (0, _typeHelpers.isMessagesKey)(title) ? (0, _react.jsx)(_reactIntlNext.FormattedMessage, _i18n.messages[title]) : title));