@atlaskit/emoji 67.2.1 → 67.3.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 (99) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/cjs/api/EmojiResource.js +6 -0
  3. package/dist/cjs/components/common/DeletableEmojiTooltipContent.js +34 -0
  4. package/dist/cjs/components/common/DeleteButton.js +2 -1
  5. package/dist/cjs/components/common/Emoji.js +94 -81
  6. package/dist/cjs/components/common/EmojiActions.js +8 -6
  7. package/dist/cjs/components/common/EmojiDeletePreview.js +19 -6
  8. package/dist/cjs/components/common/EmojiErrorMessage.js +13 -5
  9. package/dist/cjs/components/common/EmojiRadioButton.js +1 -0
  10. package/dist/cjs/components/common/EmojiUploadPicker.js +30 -29
  11. package/dist/cjs/components/common/EmojiUploadPreview.js +12 -5
  12. package/dist/cjs/components/common/FileChooser.js +7 -1
  13. package/dist/cjs/components/common/RetryableButton.js +9 -3
  14. package/dist/cjs/components/common/ToolTipContentWithKeymap.js +25 -0
  15. package/dist/cjs/components/common/styles.js +50 -20
  16. package/dist/cjs/components/i18n.js +17 -2
  17. package/dist/cjs/components/picker/CategorySelector.js +2 -1
  18. package/dist/cjs/components/picker/CategoryTracker.js +5 -0
  19. package/dist/cjs/components/picker/EmojiPickerComponent.js +12 -6
  20. package/dist/cjs/components/picker/EmojiPickerList.js +49 -8
  21. package/dist/cjs/components/picker/EmojiPickerListSearch.js +4 -1
  22. package/dist/cjs/components/picker/VirtualList.js +8 -3
  23. package/dist/cjs/{util → hooks}/useInView.js +3 -2
  24. package/dist/cjs/util/browser-support.js +11 -3
  25. package/dist/cjs/util/constants.js +4 -1
  26. package/dist/cjs/util/keymaps.js +55 -0
  27. package/dist/cjs/version.json +1 -1
  28. package/dist/es2019/api/EmojiResource.js +6 -0
  29. package/dist/es2019/components/common/DeletableEmojiTooltipContent.js +27 -0
  30. package/dist/es2019/components/common/DeleteButton.js +2 -1
  31. package/dist/es2019/components/common/Emoji.js +90 -72
  32. package/dist/es2019/components/common/EmojiActions.js +9 -7
  33. package/dist/es2019/components/common/EmojiDeletePreview.js +17 -7
  34. package/dist/es2019/components/common/EmojiErrorMessage.js +10 -4
  35. package/dist/es2019/components/common/EmojiRadioButton.js +1 -0
  36. package/dist/es2019/components/common/EmojiUploadPicker.js +32 -27
  37. package/dist/es2019/components/common/EmojiUploadPreview.js +9 -5
  38. package/dist/es2019/components/common/FileChooser.js +7 -1
  39. package/dist/es2019/components/common/RetryableButton.js +9 -3
  40. package/dist/es2019/components/common/ToolTipContentWithKeymap.js +15 -0
  41. package/dist/es2019/components/common/styles.js +44 -16
  42. package/dist/es2019/components/i18n.js +17 -2
  43. package/dist/es2019/components/picker/CategorySelector.js +2 -1
  44. package/dist/es2019/components/picker/CategoryTracker.js +3 -0
  45. package/dist/es2019/components/picker/EmojiPickerComponent.js +12 -6
  46. package/dist/es2019/components/picker/EmojiPickerList.js +48 -8
  47. package/dist/es2019/components/picker/EmojiPickerListSearch.js +3 -1
  48. package/dist/es2019/components/picker/VirtualList.js +7 -3
  49. package/dist/es2019/{util → hooks}/useInView.js +2 -2
  50. package/dist/es2019/util/browser-support.js +9 -1
  51. package/dist/es2019/util/constants.js +2 -0
  52. package/dist/es2019/util/keymaps.js +43 -0
  53. package/dist/es2019/version.json +1 -1
  54. package/dist/esm/api/EmojiResource.js +6 -0
  55. package/dist/esm/components/common/DeletableEmojiTooltipContent.js +25 -0
  56. package/dist/esm/components/common/DeleteButton.js +2 -1
  57. package/dist/esm/components/common/Emoji.js +94 -82
  58. package/dist/esm/components/common/EmojiActions.js +9 -7
  59. package/dist/esm/components/common/EmojiDeletePreview.js +17 -7
  60. package/dist/esm/components/common/EmojiErrorMessage.js +11 -4
  61. package/dist/esm/components/common/EmojiRadioButton.js +1 -0
  62. package/dist/esm/components/common/EmojiUploadPicker.js +32 -31
  63. package/dist/esm/components/common/EmojiUploadPreview.js +9 -5
  64. package/dist/esm/components/common/FileChooser.js +7 -1
  65. package/dist/esm/components/common/RetryableButton.js +9 -3
  66. package/dist/esm/components/common/ToolTipContentWithKeymap.js +14 -0
  67. package/dist/esm/components/common/styles.js +43 -17
  68. package/dist/esm/components/i18n.js +17 -2
  69. package/dist/esm/components/picker/CategorySelector.js +2 -1
  70. package/dist/esm/components/picker/CategoryTracker.js +5 -0
  71. package/dist/esm/components/picker/EmojiPickerComponent.js +12 -6
  72. package/dist/esm/components/picker/EmojiPickerList.js +49 -8
  73. package/dist/esm/components/picker/EmojiPickerListSearch.js +4 -1
  74. package/dist/esm/components/picker/VirtualList.js +8 -3
  75. package/dist/esm/{util → hooks}/useInView.js +2 -2
  76. package/dist/esm/util/browser-support.js +9 -1
  77. package/dist/esm/util/constants.js +2 -0
  78. package/dist/esm/util/keymaps.js +43 -0
  79. package/dist/esm/version.json +1 -1
  80. package/dist/types/components/common/DeletableEmojiTooltipContent.d.ts +6 -0
  81. package/dist/types/components/common/Emoji.d.ts +6 -0
  82. package/dist/types/components/common/EmojiErrorMessage.d.ts +1 -0
  83. package/dist/types/components/common/FileChooser.d.ts +1 -0
  84. package/dist/types/components/common/RetryableButton.d.ts +2 -1
  85. package/dist/types/components/common/ToolTipContentWithKeymap.d.ts +9 -0
  86. package/dist/types/components/common/styles.d.ts +6 -2
  87. package/dist/types/components/i18n.d.ts +15 -0
  88. package/dist/types/components/picker/CategoryTracker.d.ts +1 -0
  89. package/dist/types/components/picker/EmojiPickerList.d.ts +8 -1
  90. package/dist/types/components/picker/EmojiPickerListSearch.d.ts +1 -0
  91. package/dist/types/components/picker/VirtualList.d.ts +21 -1
  92. package/dist/types/types.d.ts +1 -1
  93. package/dist/types/util/browser-support.d.ts +6 -1
  94. package/dist/types/util/constants.d.ts +3 -1
  95. package/dist/types/util/keymaps.d.ts +14 -0
  96. package/dist/types/util/type-helpers.d.ts +1 -1
  97. package/package.json +2 -2
  98. package/report.api.md +16 -1
  99. /package/dist/types/{util → hooks}/useInView.d.ts +0 -0
@@ -157,8 +157,6 @@ var EmojiPickerComponent = function EmojiPickerComponent(_ref) {
157
157
  if (emojiToRender && !containsEmojiId(emojiToRender, selectedEmoji)) {
158
158
  batchedUpdates(function () {
159
159
  setSelectedEmoji(undefined);
160
- // Only enable categories for full emoji list (non-search)
161
- setActiveCategory(null);
162
160
  });
163
161
  }
164
162
  batchedUpdates(function () {
@@ -327,12 +325,12 @@ var EmojiPickerComponent = function EmojiPickerComponent(_ref) {
327
325
  });
328
326
  fireAnalytics(uploadBeginButton());
329
327
  }, [emojiProvider, fireAnalytics]);
330
- var scrollToUploadedEmoji = useCallback(function () {
328
+ var scrollToUploadedEmoji = useCallback(function (emojiDescription) {
331
329
  if (emojiPickerList.current) {
332
330
  // Wait a tick to ensure repaint and updated height for picker list
333
331
  window.setTimeout(function () {
334
332
  var _emojiPickerList$curr2;
335
- (_emojiPickerList$curr2 = emojiPickerList.current) === null || _emojiPickerList$curr2 === void 0 ? void 0 : _emojiPickerList$curr2.scrollToRecentlyUploaded();
333
+ (_emojiPickerList$curr2 = emojiPickerList.current) === null || _emojiPickerList$curr2 === void 0 ? void 0 : _emojiPickerList$curr2.scrollToRecentlyUploaded(emojiDescription);
336
334
  }, 0);
337
335
  }
338
336
  }, [emojiPickerList]);
@@ -349,7 +347,7 @@ var EmojiPickerComponent = function EmojiPickerComponent(_ref) {
349
347
  setSelectedEmoji(emojiDescription);
350
348
  setUploading(false);
351
349
  });
352
- scrollToUploadedEmoji();
350
+ scrollToUploadedEmoji(emojiDescription);
353
351
  };
354
352
  uploadEmoji(upload, emojiProvider, errorSetter, onSuccess, fireAnalytics, retry);
355
353
  }, [emojiProvider, fireAnalytics, scrollToUploadedEmoji]);
@@ -401,6 +399,11 @@ var EmojiPickerComponent = function EmojiPickerComponent(_ref) {
401
399
  fireAnalytics(openedPickerEvent());
402
400
  isMounting.current = false;
403
401
  }
402
+
403
+ // stop all key propagation to other event listeners
404
+ var suppressKeyPress = function suppressKeyPress(e) {
405
+ e.stopPropagation();
406
+ };
404
407
  useEffect(function () {
405
408
  // componentDidMount logic
406
409
  if (!isMounted) {
@@ -455,7 +458,10 @@ var EmojiPickerComponent = function EmojiPickerComponent(_ref) {
455
458
  "data-emoji-picker-container": true,
456
459
  role: "dialog",
457
460
  "aria-label": formatMessage(messages.emojiPickerTitle),
458
- "aria-modal": true
461
+ "aria-modal": true,
462
+ onKeyPress: suppressKeyPress,
463
+ onKeyUp: suppressKeyPress,
464
+ onKeyDown: suppressKeyPress
459
465
  }, jsx(CategorySelector, {
460
466
  activeCategoryId: activeCategory,
461
467
  dynamicCategories: dynamicCategories,
@@ -89,6 +89,24 @@ var EmojiPickerVirtualListInternal = /*#__PURE__*/function (_PureComponent2) {
89
89
  _this.props.onSearch(value);
90
90
  }
91
91
  });
92
+ _defineProperty(_assertThisInitialized(_this), "findEmojiRowAndColumnById", function (emojiId) {
93
+ var columnIndex = -1;
94
+ // for most of cases, it'd be in first emoji row, so should be quite fast to find in real world
95
+ var rowIndex = _this.virtualItems.findIndex(function (rowItem) {
96
+ if (rowItem instanceof EmojisRowItem) {
97
+ // find uploaded emoji in each emoji row
98
+ columnIndex = rowItem.props.emojis.findIndex(function (emoji) {
99
+ return emoji.id === emojiId;
100
+ });
101
+ return columnIndex !== -1;
102
+ }
103
+ return false;
104
+ });
105
+ return {
106
+ rowIndex: rowIndex,
107
+ columnIndex: columnIndex
108
+ };
109
+ });
92
110
  _defineProperty(_assertThisInitialized(_this), "buildVirtualItemFromGroup", function (group) {
93
111
  var _this$props2 = _this.props,
94
112
  onEmojiSelected = _this$props2.onEmojiSelected,
@@ -121,6 +139,7 @@ var EmojiPickerVirtualListInternal = /*#__PURE__*/function (_PureComponent2) {
121
139
  loading = props.loading,
122
140
  query = props.query;
123
141
  var items = [];
142
+ var prevFirstCategory = _this.categoryTracker.getFirstCategory();
124
143
  _this.categoryTracker.reset();
125
144
  if (loading) {
126
145
  items.push(new LoadingItem());
@@ -147,12 +166,18 @@ var EmojiPickerVirtualListInternal = /*#__PURE__*/function (_PureComponent2) {
147
166
  _this.lastYourUploadsRow = items.length - 1;
148
167
  }
149
168
  });
169
+ }
170
+ }
171
+
172
+ // make sure virtualItems is up-to-date before calling onRowsRendered
173
+ _this.virtualItems = items;
174
+ if (!loading && !query) {
175
+ if (_this.categoryTracker.getFirstCategory() !== prevFirstCategory) {
150
176
  _this.onRowsRendered({
151
177
  startIndex: 0
152
178
  });
153
179
  }
154
180
  }
155
- _this.virtualItems = items;
156
181
  });
157
182
  _defineProperty(_assertThisInitialized(_this), "addToCategoryMap", function (categoryToGroupMap, emoji, category) {
158
183
  if (!categoryToGroupMap[category]) {
@@ -234,6 +259,11 @@ var EmojiPickerVirtualListInternal = /*#__PURE__*/function (_PureComponent2) {
234
259
  _defineProperty(_assertThisInitialized(_this), "renderRow", function (context) {
235
260
  return virtualItemRenderer(_this.virtualItems, context);
236
261
  });
262
+ _defineProperty(_assertThisInitialized(_this), "handleOnCloseDelete", function () {
263
+ var list = _this.listRef.current;
264
+ list === null || list === void 0 ? void 0 : list.updateFocusIndex(_this.lastYourUploadsRow);
265
+ _this.props.onCloseDelete();
266
+ });
237
267
  _this.lastYourUploadsRow = 0;
238
268
  _this.buildEmojiGroupedByCategory(_props.emojis, _props.currentUser);
239
269
  _this.buildVirtualItems(_props, _this.state);
@@ -278,11 +308,23 @@ var EmojiPickerVirtualListInternal = /*#__PURE__*/function (_PureComponent2) {
278
308
  }
279
309
  }, {
280
310
  key: "scrollToRecentlyUploaded",
281
- value: function scrollToRecentlyUploaded() {
282
- var row = this.lastYourUploadsRow;
283
- if (row > 0) {
284
- var _this$listRef$current2;
285
- (_this$listRef$current2 = this.listRef.current) === null || _this$listRef$current2 === void 0 ? void 0 : _this$listRef$current2.scrollToRowAndFocusLastEmoji(this.lastYourUploadsRow);
311
+ value: function scrollToRecentlyUploaded(uploadedEmoji) {
312
+ // when search results is shown
313
+ if (this.props.query) {
314
+ var _this$findEmojiRowAnd = this.findEmojiRowAndColumnById(uploadedEmoji.id),
315
+ rowIndex = _this$findEmojiRowAnd.rowIndex,
316
+ columnIndex = _this$findEmojiRowAnd.columnIndex;
317
+ if (rowIndex !== -1) {
318
+ var _this$listRef$current2;
319
+ (_this$listRef$current2 = this.listRef.current) === null || _this$listRef$current2 === void 0 ? void 0 : _this$listRef$current2.scrollToEmojiAndFocus(rowIndex, columnIndex);
320
+ }
321
+ } else {
322
+ // when seeing all emojis
323
+ var row = this.lastYourUploadsRow;
324
+ if (row > 0) {
325
+ var _this$listRef$current3;
326
+ (_this$listRef$current3 = this.listRef.current) === null || _this$listRef$current3 === void 0 ? void 0 : _this$listRef$current3.scrollToRowAndFocusLastEmoji(this.lastYourUploadsRow);
327
+ }
286
328
  }
287
329
  }
288
330
  }, {
@@ -301,7 +343,6 @@ var EmojiPickerVirtualListInternal = /*#__PURE__*/function (_PureComponent2) {
301
343
  uploadErrorMessage = _this$props3.uploadErrorMessage,
302
344
  onUploadCancelled = _this$props3.onUploadCancelled,
303
345
  onUploadEmoji = _this$props3.onUploadEmoji,
304
- onCloseDelete = _this$props3.onCloseDelete,
305
346
  onDeleteEmoji = _this$props3.onDeleteEmoji,
306
347
  onFileChooserClicked = _this$props3.onFileChooserClicked,
307
348
  onOpenUpload = _this$props3.onOpenUpload,
@@ -323,7 +364,7 @@ var EmojiPickerVirtualListInternal = /*#__PURE__*/function (_PureComponent2) {
323
364
  uploadErrorMessage: uploadErrorMessage,
324
365
  onUploadCancelled: onUploadCancelled,
325
366
  onUploadEmoji: onUploadEmoji,
326
- onCloseDelete: onCloseDelete,
367
+ onCloseDelete: this.handleOnCloseDelete,
327
368
  onDeleteEmoji: onDeleteEmoji,
328
369
  onFileChooserClicked: onFileChooserClicked,
329
370
  onOpenUpload: onOpenUpload,
@@ -10,10 +10,13 @@ import { messages } from '../i18n';
10
10
  import { input, pickerSearch, searchIcon } from './styles';
11
11
  import { EMOJI_SEARCH_DEBOUNCE } from '../../util/constants';
12
12
  import { useDebouncedCallback } from 'use-debounce';
13
+ import { hidden } from '../common/styles';
13
14
  export var emojiPickerSearchTestId = 'emoji-picker-serach';
14
15
  export var EmojiPickerListSearch = function EmojiPickerListSearch(props) {
15
16
  var style = props.style,
16
17
  query = props.query,
18
+ _props$isVisible = props.isVisible,
19
+ isVisible = _props$isVisible === void 0 ? true : _props$isVisible,
17
20
  resultsCount = props.resultsCount,
18
21
  onChange = props.onChange;
19
22
  var textRef = useRef(null);
@@ -45,7 +48,7 @@ export var EmojiPickerListSearch = function EmojiPickerListSearch(props) {
45
48
  });
46
49
  }, []);
47
50
  return jsx("div", {
48
- css: pickerSearch,
51
+ css: [pickerSearch, !isVisible && hidden],
49
52
  style: style
50
53
  }, jsx(VisuallyHidden, {
51
54
  id: "emoji-search-results-status",
@@ -177,6 +177,7 @@ export var VirtualList = /*#__PURE__*/React.forwardRef(function (props, ref) {
177
177
  return;
178
178
  }
179
179
  e.preventDefault();
180
+ e.stopPropagation();
180
181
  var lastRowIndex = rowCount - 1;
181
182
  var lastColumnIndex = EMOJI_LIST_COLUMNS - 1;
182
183
 
@@ -245,13 +246,17 @@ export var VirtualList = /*#__PURE__*/React.forwardRef(function (props, ref) {
245
246
  focusEmoji(index, EMOJI_LIST_COLUMNS, KeyboardNavigationDirection.Left, true);
246
247
  }
247
248
  },
248
- updateFocusIndex: function updateFocusIndex(index) {
249
+ scrollToEmojiAndFocus: function scrollToEmojiAndFocus(rowIndex, columnIndex) {
250
+ focusEmoji(rowIndex, columnIndex, KeyboardNavigationDirection.Left, true);
251
+ },
252
+ updateFocusIndex: function updateFocusIndex(rowIndex) {
249
253
  var _virtualistItemsRef$c2;
254
+ var columnIndex = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
250
255
  // row could be removed from virtual list after scrolling, we'll update emoji cell tabIndex after losing focus
251
256
  if (!((_virtualistItemsRef$c2 = virtualistItemsRef.current) !== null && _virtualistItemsRef$c2 !== void 0 && _virtualistItemsRef$c2.contains(document.activeElement))) {
252
257
  setEmojisFocus({
253
- rowIndex: index,
254
- columnIndex: 0
258
+ rowIndex: rowIndex,
259
+ columnIndex: columnIndex
255
260
  });
256
261
  }
257
262
  }
@@ -1,8 +1,8 @@
1
1
  import { useInView as useInViewLib } from 'react-intersection-observer';
2
- import { isIntersectionObserverSupported } from './browser-support';
2
+ import browserSupport from '../util/browser-support';
3
3
  export var useInView = function useInView(options) {
4
4
  var hookResult = useInViewLib(options);
5
- if (!isIntersectionObserverSupported) {
5
+ if (!browserSupport.supportsIntersectionObserver) {
6
6
  // Unsupported, return no `ref` and default `inView` true value
7
7
  return [undefined, true];
8
8
  }
@@ -1 +1,9 @@
1
- export var isIntersectionObserverSupported = typeof window !== 'undefined' && 'IntersectionObserver' in window && 'IntersectionObserverEntry' in window && 'intersectionRatio' in window.IntersectionObserverEntry.prototype;
1
+ var result = {
2
+ mac: false,
3
+ supportsIntersectionObserver: false
4
+ };
5
+ if (typeof navigator !== 'undefined') {
6
+ result.mac = /Mac/.test(navigator.platform);
7
+ result.supportsIntersectionObserver = typeof window !== 'undefined' && 'IntersectionObserver' in window && 'IntersectionObserverEntry' in window && 'intersectionRatio' in window.IntersectionObserverEntry.prototype;
8
+ }
9
+ export default result;
@@ -41,6 +41,7 @@ export var KeyboardKeys;
41
41
  KeyboardKeys["Enter"] = "Enter";
42
42
  KeyboardKeys["Tab"] = "Tab";
43
43
  KeyboardKeys["Space"] = " ";
44
+ KeyboardKeys["Backspace"] = "Backspace";
44
45
  })(KeyboardKeys || (KeyboardKeys = {}));
45
46
  export var KeyboardNavigationDirection;
46
47
  (function (KeyboardNavigationDirection) {
@@ -50,6 +51,7 @@ export var KeyboardNavigationDirection;
50
51
  KeyboardNavigationDirection["Right"] = "Right";
51
52
  })(KeyboardNavigationDirection || (KeyboardNavigationDirection = {}));
52
53
  export var CATEGORYSELECTOR_KEYBOARD_KEYS_SUPPORTED = [KeyboardKeys.ArrowRight, KeyboardKeys.ArrowLeft, KeyboardKeys.Home, KeyboardKeys.End];
54
+ export var EMOJI_KEYBOARD_KEYS_SUPPORTED = [KeyboardKeys.Enter, KeyboardKeys.Backspace, KeyboardKeys.Space];
53
55
  export var TONESELECTOR_KEYBOARD_KEYS_SUPPORTED = [KeyboardKeys.Enter, KeyboardKeys.Tab, KeyboardKeys.Space];
54
56
  export var EMOJIPICKERLIST_KEYBOARD_KEYS_SUPPORTED = [KeyboardKeys.ArrowRight, KeyboardKeys.ArrowLeft, KeyboardKeys.Home, KeyboardKeys.End, KeyboardKeys.ArrowUp, KeyboardKeys.ArrowDown, KeyboardKeys.PageUp, KeyboardKeys.PageDown];
55
57
  export var DEFAULT_TONE = 0;
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Copied from editor-common: https://bitbucket.org/atlassian/atlassian-frontend/src/d01430a20500d720791d0667fd7cfe25d254f2e3/packages/editor/editor-common/src/keymaps/index.tsx
3
+ */
4
+
5
+ import browserSupport from './browser-support';
6
+ export var backspace = makeKeyMapWithCommon('Backspace', 'Backspace');
7
+ export function makeKeymap(description, windows, mac, common) {
8
+ return {
9
+ description: description,
10
+ windows: windows.replace(/Mod/i, 'Ctrl'),
11
+ mac: mac.replace(/Mod/i, 'Cmd'),
12
+ common: common
13
+ };
14
+ }
15
+ export function makeKeyMapWithCommon(description, common) {
16
+ var windows = common.replace(/Mod/i, 'Ctrl');
17
+ var mac = common.replace(/Mod/i, 'Cmd');
18
+ return makeKeymap(description, windows, mac, common);
19
+ }
20
+ export var arrowKeysMap = {
21
+ // for reference: https://wincent.com/wiki/Unicode_representations_of_modifier_keys
22
+ ARROWLEFT: "\u2190",
23
+ ARROWRIGHT: "\u2192",
24
+ ARROWUP: "\u2191",
25
+ ARROWDOWN: "\u2193"
26
+ };
27
+ export function formatShortcut(keymap) {
28
+ var shortcut;
29
+ if (browserSupport.mac) {
30
+ // for reference: https://wincent.com/wiki/Unicode_representations_of_modifier_keys
31
+ shortcut = keymap.mac.replace(/Cmd/i, "\u2318").replace(/Shift/i, "\u21E7").replace(/Ctrl/i, "\u2303").replace(/Alt/i, "\u2325").replace(/Backspace/i, "\u232B").replace(/Enter/i, "\u23CE");
32
+ } else {
33
+ shortcut = keymap.windows.replace(/Backspace/i, "\u232B");
34
+ }
35
+ var keys = shortcut.split('-');
36
+ var lastKey = keys[keys.length - 1];
37
+ if (lastKey.length === 1) {
38
+ // capitalise single letters
39
+ lastKey = lastKey.toUpperCase();
40
+ }
41
+ keys[keys.length - 1] = arrowKeysMap[lastKey.toUpperCase()] || lastKey;
42
+ return keys.join(browserSupport.mac ? '' : '+');
43
+ }
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/emoji",
3
- "version": "67.2.1",
3
+ "version": "67.3.1",
4
4
  "sideEffects": false
5
5
  }
@@ -0,0 +1,6 @@
1
+ /// <reference types="react" />
2
+ import { EmojiDescription } from '../../types';
3
+ export declare const DeletableEmojiTooltipContent: () => JSX.Element;
4
+ export declare const DeletableEmojiTooltipContentForScreenReader: ({ emoji, }: {
5
+ emoji: EmojiDescription;
6
+ }) => JSX.Element;
@@ -77,5 +77,11 @@ export interface Props extends Omit<React.HTMLAttributes<HTMLSpanElement>, 'onMo
77
77
  }
78
78
  export declare const SpriteEmoji: (props: Props) => jsx.JSX.Element;
79
79
  export declare const ImageEmoji: (props: Props) => jsx.JSX.Element;
80
+ interface EmojiNodeWrapperProps extends Props {
81
+ type: 'sprite' | 'image';
82
+ }
83
+ export declare const EmojiNodeWrapper: React.ForwardRefExoticComponent<EmojiNodeWrapperProps & {
84
+ children?: React.ReactNode;
85
+ } & React.RefAttributes<HTMLSpanElement>>;
80
86
  export declare const Emoji: (props: Props) => jsx.JSX.Element;
81
87
  export default Emoji;
@@ -7,6 +7,7 @@ export interface Props {
7
7
  tooltip?: boolean;
8
8
  messageStyles: SerializedStyles;
9
9
  }
10
+ export declare const emojiErrorScreenreaderTestId = "emoji-error-screenreader-message";
10
11
  export declare const emojiErrorMessageTestId = "emoji-error-message";
11
12
  export declare const emojiErrorMessageTooltipTestId = "emoji-error-message-tooltip";
12
13
  export declare const emojiErrorIconTestId = "emoji-error-icon";
@@ -1,6 +1,7 @@
1
1
  import { FC, ChangeEventHandler } from 'react';
2
2
  export interface Props {
3
3
  label: string;
4
+ ariaLabelledBy?: string;
4
5
  ariaDescribedBy?: string;
5
6
  onChange?: ChangeEventHandler<any>;
6
7
  onClick?: () => void;
@@ -6,7 +6,8 @@ export interface Props {
6
6
  error: boolean;
7
7
  onSubmit: () => void;
8
8
  loading: boolean;
9
- ariaDescribedby?: string;
9
+ ariaDescribedBy?: string;
10
+ ariaLabelledBy?: string;
10
11
  }
11
12
  export declare const retryUploadButtonTestId = "retry-upload-button";
12
13
  export declare const uploadEmojiButtonTestId = "upload-emoji-button";
@@ -0,0 +1,9 @@
1
+ /** @jsx jsx */
2
+ import React from 'react';
3
+ import { jsx } from '@emotion/react';
4
+ import { Keymap } from '../../util/keymaps';
5
+ export declare const ToolTipContentWithKeymap: React.MemoExoticComponent<({ description, shortcutOverride, keymap, }: {
6
+ description?: string | React.ReactNode;
7
+ keymap?: Keymap | undefined;
8
+ shortcutOverride?: string | undefined;
9
+ }) => jsx.JSX.Element | null>;
@@ -5,10 +5,11 @@ export declare const emojiNodeStyles = "emoji-common-node";
5
5
  export declare const emojiImage = "emoji-common-emoji-image";
6
6
  export declare const emojiDeleteButton = "emoji-common-deleteButton";
7
7
  export declare const emojiMainStyle = "emoji-common-main-styles";
8
+ export declare const deletableEmoji = "emoji-common-deletable";
8
9
  export declare const deleteButton: import("@emotion/react").SerializedStyles;
9
10
  export declare const emojiToneSelectorContainer: import("@emotion/react").SerializedStyles;
10
- export declare const emojiStyles: import("@emotion/react").SerializedStyles;
11
- export declare const emojiContainer: import("@emotion/react").SerializedStyles;
11
+ export declare const emojiImageContainer: import("@emotion/react").SerializedStyles;
12
+ export declare const emojiSpriteContainer: import("@emotion/react").SerializedStyles;
12
13
  export declare const placeholder = "emoji-common-placeholder";
13
14
  export declare const placeholderContainer: import("@emotion/react").SerializedStyles;
14
15
  export declare const placeholderContainerAnimated: import("@emotion/react").SerializedStyles;
@@ -39,6 +40,8 @@ export declare const addCustomEmoji: import("@emotion/react").SerializedStyles;
39
40
  export declare const submitDelete = "emoji-submit-delete";
40
41
  export declare const deletePreview: import("@emotion/react").SerializedStyles;
41
42
  export declare const deleteText: import("@emotion/react").SerializedStyles;
43
+ export declare const headingH5: import("@emotion/react").SerializedStyles;
44
+ export declare const requiredSymbol: import("@emotion/react").SerializedStyles;
42
45
  export declare const previewButtonGroup: import("@emotion/react").SerializedStyles;
43
46
  export declare const deleteFooter: import("@emotion/react").SerializedStyles;
44
47
  export declare const emojiDeleteErrorMessage: import("@emotion/react").SerializedStyles;
@@ -50,3 +53,4 @@ export declare const uploadEmojiButton: import("@emotion/react").SerializedStyle
50
53
  export declare const cancelButton: import("@emotion/react").SerializedStyles;
51
54
  export declare const buttonSpinner: import("@emotion/react").SerializedStyles;
52
55
  export declare const emojiActionsWrapper: import("@emotion/react").SerializedStyles;
56
+ export declare const tooltipShortcutStyle: import("@emotion/react").SerializedStyles;
@@ -1,4 +1,14 @@
1
1
  export declare const messages: {
2
+ deleteEmojiTooltip: {
3
+ id: string;
4
+ defaultMessage: string;
5
+ description: string;
6
+ };
7
+ deleteEmojiTooltipForScreenreader: {
8
+ id: string;
9
+ defaultMessage: string;
10
+ description: string;
11
+ };
2
12
  deleteEmojiTitle: {
3
13
  id: string;
4
14
  defaultMessage: string;
@@ -209,4 +219,9 @@ export declare const messages: {
209
219
  defaultMessage: string;
210
220
  description: string;
211
221
  };
222
+ error: {
223
+ id: string;
224
+ defaultMessage: string;
225
+ description: string;
226
+ };
212
227
  };
@@ -12,4 +12,5 @@ export default class CategoryTracker {
12
12
  reset(): void;
13
13
  add(category: CategoryId, row: number): void;
14
14
  getRow(category: CategoryId): number | undefined;
15
+ getFirstCategory(): CategoryId | undefined;
15
16
  }
@@ -60,6 +60,7 @@ export default class EmojiPickerVirtualListInternal extends PureComponent<Props,
60
60
  UNSAFE_componentWillUpdate(nextProps: Props, nextState: State): void;
61
61
  private onEmojiActive;
62
62
  private onSearch;
63
+ private findEmojiRowAndColumnById;
63
64
  /**
64
65
  * Scrolls to a category in the list view
65
66
  */
@@ -67,7 +68,7 @@ export default class EmojiPickerVirtualListInternal extends PureComponent<Props,
67
68
  scrollToBottom(): void;
68
69
  scrollToTop(): void;
69
70
  scrollToRow(index?: number): void;
70
- scrollToRecentlyUploaded(): void;
71
+ scrollToRecentlyUploaded(uploadedEmoji: EmojiDescription): void;
71
72
  private buildVirtualItemFromGroup;
72
73
  private buildVirtualItems;
73
74
  private addToCategoryMap;
@@ -83,5 +84,11 @@ export default class EmojiPickerVirtualListInternal extends PureComponent<Props,
83
84
  private onRowsRendered;
84
85
  private rowSize;
85
86
  private renderRow;
87
+ /**
88
+ * After deleting emoji, we'll update the focus index to the first emoji of last row of your uploads, so when user navigate back focus will still work
89
+ * if last emoji in your uploads is deleted, the updated focus index will be outdated, as there will be no your uploads section
90
+ * however, it'll trigger onChange from VirtualList, which will update focus index automatically for us
91
+ */
92
+ private handleOnCloseDelete;
86
93
  render(): jsx.JSX.Element;
87
94
  }
@@ -3,6 +3,7 @@ import { Styles } from '../../types';
3
3
  export interface Props {
4
4
  style?: Styles;
5
5
  query?: string;
6
+ isVisible?: boolean;
6
7
  onChange: (value: string) => void;
7
8
  resultsCount: number;
8
9
  }
@@ -13,9 +13,29 @@ declare type Props = {
13
13
  height: number;
14
14
  };
15
15
  export declare type ListRef = {
16
+ /**
17
+ * Scroll to the row by row index
18
+ * @param index row index of virtual list
19
+ */
16
20
  scrollToRow: (index?: number) => void;
21
+ /**
22
+ * Scroll to the row by row index, and focus on last emoji in that row
23
+ * @param index row index of virtual list
24
+ * @returns
25
+ */
17
26
  scrollToRowAndFocusLastEmoji: (index?: number) => void;
18
- updateFocusIndex: (index: number) => void;
27
+ /**
28
+ * Scroll to a emoji in virtual list and focus on it
29
+ * @param rIndex row index of virtual list
30
+ * @param cIndex column index of virtual list
31
+ */
32
+ scrollToEmojiAndFocus: (rIndex: number, cIndex: number) => void;
33
+ /**
34
+ * Update the focus index of virtual list, which will manage tabIndex via EmojiPickerListContext
35
+ * @param rIndex row index of virtual list
36
+ * @param cIndex column index of virtual list
37
+ */
38
+ updateFocusIndex: (rIndex: number, cIndex?: number) => void;
19
39
  };
20
40
  export declare const virtualListScrollContainerTestId = "virtual-list-scroll-container";
21
41
  export declare const VirtualList: React.ForwardRefExoticComponent<Props & React.RefAttributes<ListRef>>;
@@ -322,7 +322,7 @@ export interface User {
322
322
  id: string;
323
323
  }
324
324
  export declare type OptionalUser = User | undefined;
325
- export declare type Message = React.ReactNode;
325
+ export declare type Message = React.ReactNode | string;
326
326
  export declare enum ProviderTypes {
327
327
  SITE = "SITE",
328
328
  STANDARD = "STANDARD",
@@ -1 +1,6 @@
1
- export declare const isIntersectionObserverSupported: boolean;
1
+ declare type BrowserSupport = {
2
+ mac: boolean;
3
+ supportsIntersectionObserver: boolean;
4
+ };
5
+ declare const result: BrowserSupport;
6
+ export default result;
@@ -36,7 +36,8 @@ export declare enum KeyboardKeys {
36
36
  End = "End",
37
37
  Enter = "Enter",
38
38
  Tab = "Tab",
39
- Space = " "
39
+ Space = " ",
40
+ Backspace = "Backspace"
40
41
  }
41
42
  export declare enum KeyboardNavigationDirection {
42
43
  Down = "Down",
@@ -45,6 +46,7 @@ export declare enum KeyboardNavigationDirection {
45
46
  Right = "Right"
46
47
  }
47
48
  export declare const CATEGORYSELECTOR_KEYBOARD_KEYS_SUPPORTED: string[];
49
+ export declare const EMOJI_KEYBOARD_KEYS_SUPPORTED: string[];
48
50
  export declare const TONESELECTOR_KEYBOARD_KEYS_SUPPORTED: string[];
49
51
  export declare const EMOJIPICKERLIST_KEYBOARD_KEYS_SUPPORTED: string[];
50
52
  export declare const DEFAULT_TONE = 0;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Copied from editor-common: https://bitbucket.org/atlassian/atlassian-frontend/src/d01430a20500d720791d0667fd7cfe25d254f2e3/packages/editor/editor-common/src/keymaps/index.tsx
3
+ */
4
+ export declare const backspace: Keymap;
5
+ export interface Keymap {
6
+ description: string;
7
+ windows: string;
8
+ mac: string;
9
+ common?: string;
10
+ }
11
+ export declare function makeKeymap(description: string, windows: string, mac: string, common?: string): Keymap;
12
+ export declare function makeKeyMapWithCommon(description: string, common: string): Keymap;
13
+ export declare const arrowKeysMap: Record<string, string>;
14
+ export declare function formatShortcut(keymap: Keymap): string | undefined;
@@ -11,7 +11,7 @@ export declare const hasDataURLImage: (rep: EmojiRepresentation) => boolean;
11
11
  export declare const isLoadedMediaEmoji: (emoji: EmojiDescription) => boolean;
12
12
  export declare const isEmojiDescriptionWithVariations: (emoji: OptionalEmojiDescription) => emoji is EmojiDescriptionWithVariations;
13
13
  export declare const isEmojiVariationDescription: (object: any) => object is EmojiVariationDescription;
14
- export declare const isMessagesKey: (key: string) => key is "deleteEmojiTitle" | "deleteEmojiDescription" | "deleteEmojiLabel" | "addCustomEmojiLabel" | "emojiPlaceholder" | "emojiNameAriaLabel" | "emojiChooseFileTitle" | "emojiChooseFileScreenReaderDescription" | "emojiSelectSkinToneButtonAriaLabelText" | "emojiSelectSkinToneListAriaLabelText" | "emojiImageRequirements" | "emojiPreviewTitle" | "emojiPreview" | "addEmojiLabel" | "retryLabel" | "cancelLabel" | "searchPlaceholder" | "searchLabel" | "searchResultsStatus" | "searchResultsStatusSeeAll" | "categoriesSelectorLabel" | "categoriesSearchResults" | "frequentCategory" | "peopleCategory" | "natureCategory" | "foodsCategory" | "activityCategory" | "placesCategory" | "objectsCategory" | "symbolsCategory" | "flagsCategory" | "productivityCategory" | "userUploadsCustomCategory" | "allUploadsCustomCategory" | "deleteEmojiFailed" | "emojiInvalidImage" | "emojiUploadFailed" | "emojiImageTooBig" | "emojiPickerTitle" | "emojiPickerListPanel" | "emojiPickerGrid" | "emojiButtonRoleDescription";
14
+ export declare const isMessagesKey: (key: string) => key is "deleteEmojiTooltip" | "deleteEmojiTooltipForScreenreader" | "deleteEmojiTitle" | "deleteEmojiDescription" | "deleteEmojiLabel" | "addCustomEmojiLabel" | "emojiPlaceholder" | "emojiNameAriaLabel" | "emojiChooseFileTitle" | "emojiChooseFileScreenReaderDescription" | "emojiSelectSkinToneButtonAriaLabelText" | "emojiSelectSkinToneListAriaLabelText" | "emojiImageRequirements" | "emojiPreviewTitle" | "emojiPreview" | "addEmojiLabel" | "retryLabel" | "cancelLabel" | "searchPlaceholder" | "searchLabel" | "searchResultsStatus" | "searchResultsStatusSeeAll" | "categoriesSelectorLabel" | "categoriesSearchResults" | "frequentCategory" | "peopleCategory" | "natureCategory" | "foodsCategory" | "activityCategory" | "placesCategory" | "objectsCategory" | "symbolsCategory" | "flagsCategory" | "productivityCategory" | "userUploadsCustomCategory" | "allUploadsCustomCategory" | "deleteEmojiFailed" | "emojiInvalidImage" | "emojiUploadFailed" | "emojiImageTooBig" | "emojiPickerTitle" | "emojiPickerListPanel" | "emojiPickerGrid" | "emojiButtonRoleDescription" | "error";
15
15
  export declare const toEmojiId: (emoji: EmojiDescription) => EmojiId;
16
16
  export declare const toOptionalEmojiId: (emoji: OptionalEmojiDescription) => EmojiId | undefined;
17
17
  export declare const isEmojiIdEqual: (l?: EmojiId | undefined, r?: EmojiId | undefined) => boolean | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/emoji",
3
- "version": "67.2.1",
3
+ "version": "67.3.1",
4
4
  "description": "Fabric emoji React components",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/"
@@ -56,7 +56,7 @@
56
56
  },
57
57
  "devDependencies": {
58
58
  "@atlaskit/docs": "*",
59
- "@atlaskit/editor-test-helpers": "^18.1.0",
59
+ "@atlaskit/editor-test-helpers": "^18.2.0",
60
60
  "@atlaskit/elements-test-helpers": "^0.7.0",
61
61
  "@atlaskit/media-core": "^34.0.0",
62
62
  "@atlaskit/popup": "^1.5.0",
package/report.api.md CHANGED
@@ -696,10 +696,20 @@ export interface MediaApiToken {
696
696
  }
697
697
 
698
698
  // @public (undocumented)
699
- export type Message = React.ReactNode;
699
+ export type Message = React.ReactNode | string;
700
700
 
701
701
  // @public (undocumented)
702
702
  const messages: {
703
+ deleteEmojiTooltip: {
704
+ id: string;
705
+ defaultMessage: string;
706
+ description: string;
707
+ };
708
+ deleteEmojiTooltipForScreenreader: {
709
+ id: string;
710
+ defaultMessage: string;
711
+ description: string;
712
+ };
703
713
  deleteEmojiTitle: {
704
714
  id: string;
705
715
  defaultMessage: string;
@@ -910,6 +920,11 @@ const messages: {
910
920
  defaultMessage: string;
911
921
  description: string;
912
922
  };
923
+ error: {
924
+ id: string;
925
+ defaultMessage: string;
926
+ description: string;
927
+ };
913
928
  };
914
929
 
915
930
  // @public (undocumented)
File without changes