@atlaskit/emoji 65.0.0 → 65.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/dist/cjs/components/common/CachingEmoji.js +84 -151
  3. package/dist/cjs/components/common/Emoji.js +2 -2
  4. package/dist/cjs/components/common/EmojiActions.js +129 -175
  5. package/dist/cjs/components/common/EmojiErrorMessage.js +23 -59
  6. package/dist/cjs/components/common/EmojiPreviewComponent.js +1 -0
  7. package/dist/cjs/components/common/EmojiUploadPicker.js +235 -293
  8. package/dist/cjs/components/common/FileChooser.js +34 -71
  9. package/dist/cjs/components/common/Popup.js +105 -154
  10. package/dist/cjs/components/common/ResourcedEmojiComponent.js +10 -5
  11. package/dist/cjs/components/common/RetryableButton.js +43 -64
  12. package/dist/cjs/components/common/ToneSelector.js +50 -89
  13. package/dist/cjs/components/common/styles.js +14 -16
  14. package/dist/cjs/components/hooks.js +16 -0
  15. package/dist/cjs/components/picker/EmojiPickerCategoryHeading.js +16 -48
  16. package/dist/cjs/components/picker/EmojiPickerComponent.js +496 -508
  17. package/dist/cjs/components/picker/EmojiPickerEmojiRow.js +33 -60
  18. package/dist/cjs/components/picker/EmojiPickerFooter.js +13 -46
  19. package/dist/cjs/components/picker/styles.js +16 -13
  20. package/dist/cjs/components/uploader/EmojiUploadComponent.js +124 -109
  21. package/dist/cjs/hooks/useEmojiContext.js +16 -0
  22. package/dist/cjs/hooks/usePrevious.js +16 -0
  23. package/dist/cjs/index.js +16 -0
  24. package/dist/cjs/util/constants.js +3 -1
  25. package/dist/cjs/version.json +1 -1
  26. package/dist/es2019/components/common/CachingEmoji.js +65 -112
  27. package/dist/es2019/components/common/Emoji.js +2 -2
  28. package/dist/es2019/components/common/EmojiActions.js +124 -150
  29. package/dist/es2019/components/common/EmojiErrorMessage.js +22 -26
  30. package/dist/es2019/components/common/EmojiPreviewComponent.js +1 -0
  31. package/dist/es2019/components/common/EmojiUploadPicker.js +190 -253
  32. package/dist/es2019/components/common/FileChooser.js +37 -40
  33. package/dist/es2019/components/common/Popup.js +89 -109
  34. package/dist/es2019/components/common/ResourcedEmojiComponent.js +5 -4
  35. package/dist/es2019/components/common/RetryableButton.js +43 -34
  36. package/dist/es2019/components/common/ToneSelector.js +46 -59
  37. package/dist/es2019/components/common/styles.js +9 -9
  38. package/dist/es2019/components/hooks.js +8 -0
  39. package/dist/es2019/components/picker/EmojiPickerCategoryHeading.js +13 -17
  40. package/dist/es2019/components/picker/EmojiPickerComponent.js +417 -497
  41. package/dist/es2019/components/picker/EmojiPickerEmojiRow.js +32 -35
  42. package/dist/es2019/components/picker/EmojiPickerFooter.js +11 -19
  43. package/dist/es2019/components/picker/styles.js +16 -14
  44. package/dist/es2019/components/uploader/EmojiUploadComponent.js +81 -91
  45. package/dist/es2019/hooks/useEmojiContext.js +3 -0
  46. package/dist/es2019/hooks/usePrevious.js +8 -0
  47. package/dist/es2019/index.js +4 -1
  48. package/dist/es2019/util/constants.js +1 -0
  49. package/dist/es2019/version.json +1 -1
  50. package/dist/esm/components/common/CachingEmoji.js +86 -156
  51. package/dist/esm/components/common/Emoji.js +2 -2
  52. package/dist/esm/components/common/EmojiActions.js +129 -176
  53. package/dist/esm/components/common/EmojiErrorMessage.js +21 -56
  54. package/dist/esm/components/common/EmojiPreviewComponent.js +1 -0
  55. package/dist/esm/components/common/EmojiUploadPicker.js +233 -299
  56. package/dist/esm/components/common/FileChooser.js +34 -70
  57. package/dist/esm/components/common/Popup.js +104 -155
  58. package/dist/esm/components/common/ResourcedEmojiComponent.js +8 -4
  59. package/dist/esm/components/common/RetryableButton.js +40 -60
  60. package/dist/esm/components/common/ToneSelector.js +50 -87
  61. package/dist/esm/components/common/styles.js +10 -10
  62. package/dist/esm/components/hooks.js +8 -0
  63. package/dist/esm/components/picker/EmojiPickerCategoryHeading.js +14 -43
  64. package/dist/esm/components/picker/EmojiPickerComponent.js +486 -526
  65. package/dist/esm/components/picker/EmojiPickerEmojiRow.js +31 -59
  66. package/dist/esm/components/picker/EmojiPickerFooter.js +14 -47
  67. package/dist/esm/components/picker/styles.js +16 -14
  68. package/dist/esm/components/uploader/EmojiUploadComponent.js +119 -113
  69. package/dist/esm/hooks/useEmojiContext.js +5 -0
  70. package/dist/esm/hooks/usePrevious.js +8 -0
  71. package/dist/esm/index.js +4 -1
  72. package/dist/esm/util/constants.js +1 -0
  73. package/dist/esm/version.json +1 -1
  74. package/dist/types/api/EmojiResource.d.ts +2 -3
  75. package/dist/types/components/common/CachingEmoji.d.ts +3 -13
  76. package/dist/types/components/common/Emoji.d.ts +1 -2
  77. package/dist/types/components/common/EmojiActions.d.ts +6 -17
  78. package/dist/types/components/common/EmojiErrorMessage.d.ts +3 -6
  79. package/dist/types/components/common/EmojiPreviewComponent.d.ts +2 -2
  80. package/dist/types/components/common/EmojiUploadPicker.d.ts +3 -27
  81. package/dist/types/components/common/FileChooser.d.ts +3 -5
  82. package/dist/types/components/common/LoadingEmojiComponent.d.ts +3 -0
  83. package/dist/types/components/common/Popup.d.ts +3 -20
  84. package/dist/types/components/common/ResourcedEmojiComponent.d.ts +23 -11
  85. package/dist/types/components/common/RetryableButton.d.ts +3 -7
  86. package/dist/types/components/common/ToneSelector.d.ts +4 -10
  87. package/dist/types/components/common/setSkinToneAriaLabelText.d.ts +1 -1
  88. package/dist/types/components/common/styles.d.ts +1 -3
  89. package/dist/types/components/hooks.d.ts +1 -0
  90. package/dist/types/components/picker/CategorySelector.d.ts +1 -1
  91. package/dist/types/components/picker/EmojiPicker.d.ts +12 -3
  92. package/dist/types/components/picker/EmojiPickerCategoryHeading.d.ts +3 -4
  93. package/dist/types/components/picker/EmojiPickerComponent.d.ts +14 -76
  94. package/dist/types/components/picker/EmojiPickerEmojiRow.d.ts +3 -4
  95. package/dist/types/components/picker/EmojiPickerFooter.d.ts +3 -5
  96. package/dist/types/components/picker/styles.d.ts +1 -1
  97. package/dist/types/components/typeahead/EmojiTypeAheadComponent.d.ts +18 -0
  98. package/dist/types/components/uploader/EmojiUploadComponent.d.ts +3 -17
  99. package/dist/types/components/uploader/EmojiUploader.d.ts +5 -7
  100. package/dist/types/hooks/useEmojiContext.d.ts +1 -0
  101. package/dist/types/hooks/usePrevious.d.ts +1 -0
  102. package/dist/types/index.d.ts +3 -1
  103. package/dist/types/types.d.ts +2 -1
  104. package/dist/types/util/constants.d.ts +1 -0
  105. package/docs/0-intro.tsx +35 -27
  106. package/docs/1-resourced-emoji.tsx +74 -0
  107. package/docs/2-emoji-picker.tsx +56 -0
  108. package/docs/3-typeahead.tsx +20 -0
  109. package/docs/4-emoji-provider.tsx +98 -0
  110. package/local-config-example.ts +3 -1
  111. package/package.json +19 -6
  112. package/dist/cjs/components/common/EmojiPreview.js +0 -194
  113. package/dist/es2019/components/common/EmojiPreview.js +0 -152
  114. package/dist/esm/components/common/EmojiPreview.js +0 -170
  115. package/dist/types/components/common/EmojiPreview.d.ts +0 -31
@@ -1,7 +1,5 @@
1
1
  import _extends from "@babel/runtime/helpers/extends";
2
- import _defineProperty from "@babel/runtime/helpers/defineProperty";
3
- import React, { useEffect } from 'react';
4
- import { PureComponent } from 'react';
2
+ import React, { useEffect, useState } from 'react';
5
3
  import { isMediaEmoji } from '../../util/type-helpers';
6
4
  import { UfoEmojiTimings } from '../../types';
7
5
  import debug from '../../util/logger';
@@ -10,37 +8,37 @@ import EmojiPlaceholder from './EmojiPlaceholder';
10
8
  import { UfoErrorBoundary } from './UfoErrorBoundary';
11
9
  import { sampledUfoRenderedEmoji, ufoExperiences, useSampledUFOComponentExperience } from '../../util/analytics';
12
10
  import { SAMPLING_RATE_EMOJI_RENDERED_EXP } from '../../util/constants';
13
- import { EmojiContext } from '../../context/EmojiContext';
14
11
  import { hasUfoMarked } from '../../util/analytics/ufoExperiences';
12
+ import { useEmojiContext } from '../../hooks/useEmojiContext';
13
+ import { useCallback } from 'react';
15
14
 
16
15
  /**
17
16
  * Renders an emoji from a cached image, if required.
18
17
  */
19
18
  export const CachingEmoji = props => {
20
- // Optimisation to only render the class based CachingMediaEmoji if necessary
19
+ // Optimisation to only render CachingMediaEmoji if necessary
21
20
  // slight performance hit, which accumulates for a large number of emoji.
22
21
  const {
23
- placeholderSize,
24
- ...emojiProps
22
+ emoji
25
23
  } = props; // start emoji rendered experience, it may have already started earlier in ResourcedEmoji
26
24
 
27
- useSampledUFOComponentExperience(ufoExperiences['emoji-rendered'].getInstance(emojiProps.emoji.id || emojiProps.emoji.shortName), SAMPLING_RATE_EMOJI_RENDERED_EXP, {
25
+ useSampledUFOComponentExperience(ufoExperiences['emoji-rendered'].getInstance(emoji.id || emoji.shortName), SAMPLING_RATE_EMOJI_RENDERED_EXP, {
28
26
  source: 'caching-emoji',
29
- emoji: emojiProps.emoji.shortName
27
+ emoji: emoji.shortName
30
28
  });
31
29
  useEffect(() => {
32
- if (!hasUfoMarked(sampledUfoRenderedEmoji(emojiProps.emoji), 'fmp')) {
33
- sampledUfoRenderedEmoji(emojiProps.emoji).markFMP();
30
+ if (!hasUfoMarked(sampledUfoRenderedEmoji(emoji), 'fmp')) {
31
+ sampledUfoRenderedEmoji(emoji).markFMP();
34
32
  } // eslint-disable-next-line react-hooks/exhaustive-deps
35
33
 
36
34
  }, []);
37
35
 
38
36
  const emojiNode = () => {
39
- if (isMediaEmoji(props.emoji)) {
37
+ if (isMediaEmoji(emoji)) {
40
38
  return /*#__PURE__*/React.createElement(CachingMediaEmoji, props);
41
39
  }
42
40
 
43
- return /*#__PURE__*/React.createElement(Emoji, emojiProps);
41
+ return /*#__PURE__*/React.createElement(Emoji, props);
44
42
  };
45
43
 
46
44
  return /*#__PURE__*/React.createElement(UfoErrorBoundary, {
@@ -52,70 +50,32 @@ export const CachingEmoji = props => {
52
50
  * rendering paths depending on caching strategy.
53
51
  */
54
52
 
55
- export class CachingMediaEmoji extends PureComponent {
56
- constructor(props, context) {
57
- super(props);
58
-
59
- _defineProperty(this, "handleLoadError", _emojiId => {
60
- sampledUfoRenderedEmoji(_emojiId).failure({
61
- metadata: {
62
- reason: 'load error',
63
- source: 'CachingMediaEmoji',
64
- emoji: {
65
- id: _emojiId.id,
66
- shortName: _emojiId.shortName
67
- }
68
- }
69
- });
70
- this.setState({
71
- invalidImage: true
72
- });
73
- });
74
-
75
- this.state = {
76
- cachedEmoji: undefined
77
- };
78
- this.loadEmoji(props.emoji, context);
79
- }
80
-
81
- componentDidUpdate() {
82
- var _this$state$cachedEmo;
83
-
84
- if (this.props.emoji.shortName !== ((_this$state$cachedEmo = this.state.cachedEmoji) === null || _this$state$cachedEmo === void 0 ? void 0 : _this$state$cachedEmo.shortName)) {
85
- this.loadEmoji(this.props.emoji, this.context);
86
- }
87
- }
88
-
89
- loadEmoji(emoji, context) {
90
- if (!context) {
91
- return;
92
- }
93
-
94
- if (!context.emoji) {
95
- return undefined;
96
- }
97
-
98
- const {
99
- emojiProvider
100
- } = context.emoji;
101
-
102
- if (!emojiProvider) {
103
- return undefined;
104
- }
105
-
53
+ export const CachingMediaEmoji = props => {
54
+ const {
55
+ emoji,
56
+ placeholderSize,
57
+ showTooltip,
58
+ fitToHeight,
59
+ children,
60
+ ...restProps
61
+ } = props;
62
+ const {
63
+ shortName,
64
+ representation
65
+ } = emoji;
66
+ const [cachedEmoji, setCachedEmoji] = useState();
67
+ const [inValidImage, setInvalidImage] = useState(false);
68
+ const context = useEmojiContext();
69
+ const loadEmoji = useCallback(emojiProvider => {
106
70
  debug('Loading image via media cache', emoji.shortName);
107
71
  sampledUfoRenderedEmoji(emoji).mark(UfoEmojiTimings.MEDIA_START);
108
72
  emojiProvider.getMediaEmojiDescriptionURLWithInlineToken(emoji).then(cachedEmoji => {
109
- this.setState({
110
- cachedEmoji,
111
- invalidImage: false
112
- });
73
+ setCachedEmoji(cachedEmoji);
74
+ setInvalidImage(false);
113
75
  sampledUfoRenderedEmoji(emoji).mark(UfoEmojiTimings.MEDIA_END);
114
76
  }).catch(() => {
115
- this.setState({
116
- cachedEmoji: undefined,
117
- invalidImage: true
118
- });
77
+ setCachedEmoji(undefined);
78
+ setInvalidImage(true);
119
79
  sampledUfoRenderedEmoji(emoji).failure({
120
80
  metadata: {
121
81
  reason: 'failed to load media emoji',
@@ -130,48 +90,41 @@ export class CachingMediaEmoji extends PureComponent {
130
90
  }
131
91
  });
132
92
  });
133
- }
134
-
135
- render() {
136
- const {
137
- cachedEmoji,
138
- invalidImage
139
- } = this.state;
140
- const {
141
- children,
142
- ...otherProps
143
- } = this.props;
144
- let emojiComponent;
145
-
146
- if (cachedEmoji && !invalidImage) {
147
- emojiComponent = /*#__PURE__*/React.createElement(Emoji, _extends({}, otherProps, {
148
- emoji: cachedEmoji,
149
- onLoadError: this.handleLoadError
150
- }));
151
- } else {
152
- const {
153
- emoji,
154
- placeholderSize,
155
- showTooltip,
156
- fitToHeight
157
- } = this.props;
158
- const {
159
- shortName,
160
- representation
161
- } = emoji;
162
- emojiComponent = /*#__PURE__*/React.createElement(EmojiPlaceholder, {
163
- size: fitToHeight || placeholderSize,
164
- shortName: shortName,
165
- showTooltip: showTooltip,
166
- representation: representation
167
- });
93
+ }, [emoji]);
94
+ useEffect(() => {
95
+ if (context && context.emoji.emojiProvider) {
96
+ loadEmoji(context.emoji.emojiProvider);
168
97
  }
98
+ }, [context, loadEmoji]);
99
+
100
+ const handleLoadError = _emojiId => {
101
+ sampledUfoRenderedEmoji(_emojiId).failure({
102
+ metadata: {
103
+ reason: 'load error',
104
+ source: 'CachingMediaEmoji',
105
+ emoji: {
106
+ id: _emojiId.id,
107
+ shortName: _emojiId.shortName
108
+ }
109
+ }
110
+ });
111
+ setInvalidImage(true);
112
+ };
169
113
 
170
- return emojiComponent;
114
+ if (cachedEmoji && !inValidImage) {
115
+ return /*#__PURE__*/React.createElement(Emoji, _extends({}, restProps, {
116
+ showTooltip: showTooltip,
117
+ fitToHeight: fitToHeight,
118
+ emoji: cachedEmoji,
119
+ onLoadError: handleLoadError
120
+ }));
171
121
  }
172
122
 
173
- }
174
-
175
- _defineProperty(CachingMediaEmoji, "contextType", EmojiContext);
176
-
123
+ return /*#__PURE__*/React.createElement(EmojiPlaceholder, {
124
+ size: fitToHeight || placeholderSize,
125
+ shortName: shortName,
126
+ showTooltip: showTooltip,
127
+ representation: representation
128
+ });
129
+ };
177
130
  export default CachingEmoji;
@@ -133,7 +133,7 @@ export const SpriteEmoji = props => {
133
133
  onMouseDown: event => {
134
134
  handleMouseDown(props, event);
135
135
  },
136
- onMouseMove: event => {
136
+ onMouseEnter: event => {
137
137
  handleMouseMove(props, event);
138
138
  },
139
139
  "aria-label": emoji.shortName,
@@ -257,7 +257,7 @@ export const ImageEmoji = props => {
257
257
  onMouseDown: event => {
258
258
  handleMouseDown(props, event);
259
259
  },
260
- onMouseMove: event => {
260
+ onMouseEnter: event => {
261
261
  handleMouseMove(props, event);
262
262
  },
263
263
  "aria-label": emoji.shortName,
@@ -1,8 +1,8 @@
1
- import _defineProperty from "@babel/runtime/helpers/defineProperty";
1
+ import _extends from "@babel/runtime/helpers/extends";
2
2
 
3
3
  /** @jsx jsx */
4
4
  import { jsx } from '@emotion/core';
5
- import { PureComponent } from 'react';
5
+ import { Fragment, useState } from 'react';
6
6
  import { FormattedMessage, injectIntl } from 'react-intl-next';
7
7
  import EmojiDeletePreview from '../common/EmojiDeletePreview';
8
8
  import EmojiUploadPicker from '../common/EmojiUploadPicker';
@@ -13,168 +13,142 @@ import { messages } from '../i18n';
13
13
  import AkButton from '@atlaskit/button/standard-button';
14
14
  import AddIcon from '@atlaskit/icon/glyph/add';
15
15
  import { setSkinToneAriaLabelText } from './setSkinToneAriaLabelText';
16
- import { addCustomEmoji, addCustomEmojiButton, emojiPickerAddEmoji, emojiToneSelectorContainer } from './styles';
16
+ import { addCustomEmoji, addCustomEmojiButton, emojiActionsWrapper, emojiPickerAddEmoji, emojiToneSelectorContainer } from './styles';
17
17
  import { emojiActionsContainerWithBottomShadow, emojiPickerFooter } from '../picker/styles';
18
- export class EmojiActions extends PureComponent {
19
- constructor(...args) {
20
- super(...args);
21
-
22
- _defineProperty(this, "state", {
23
- selectingTone: false
24
- });
25
-
26
- _defineProperty(this, "onToneButtonClick", () => {
27
- this.setState({
28
- selectingTone: !this.state.selectingTone
29
- });
30
- });
31
-
32
- _defineProperty(this, "onToneSelected", toneValue => {
33
- this.setState({
34
- selectingTone: false
35
- });
36
-
37
- if (this.props.onToneSelected) {
38
- this.props.onToneSelected(toneValue);
39
- }
40
- });
41
-
42
- _defineProperty(this, "onMouseLeave", () => {
43
- const {
44
- selectingTone
45
- } = this.state;
46
- const {
47
- onToneSelectorCancelled
48
- } = this.props;
49
-
50
- if (selectingTone && onToneSelectorCancelled) {
51
- onToneSelectorCancelled();
52
- }
53
-
54
- this.setState({
55
- selectingTone: false
56
- });
57
- });
58
- }
59
18
 
60
- renderTones() {
61
- const {
62
- toneEmoji,
63
- selectedTone,
64
- intl
65
- } = this.props;
66
- const {
19
+ const AddOwnEmoji = props => {
20
+ const {
21
+ onOpenUpload,
22
+ uploadEnabled,
23
+ intl: {
67
24
  formatMessage
68
- } = intl;
69
-
70
- if (!toneEmoji) {
71
- return null;
72
- }
73
-
74
- let previewEmoji = toneEmoji;
75
-
76
- if (selectedTone && previewEmoji.skinVariations) {
77
- previewEmoji = previewEmoji.skinVariations[(selectedTone || 1) - 1];
78
25
  }
26
+ } = props;
27
+ return jsx(Fragment, null, uploadEnabled && jsx("div", {
28
+ css: addCustomEmoji
29
+ }, jsx(FormattedMessage, messages.addCustomEmojiLabel, label => jsx(AkButton, {
30
+ onClick: onOpenUpload,
31
+ iconBefore: jsx(AddIcon, {
32
+ label: formatMessage(messages.addCustomEmojiLabel),
33
+ size: "small"
34
+ }),
35
+ appearance: "subtle",
36
+ css: addCustomEmojiButton,
37
+ className: emojiPickerAddEmoji
38
+ }, label))));
39
+ };
40
+
41
+ const TonesWrapper = props => {
42
+ const {
43
+ toneEmoji,
44
+ selectedTone,
45
+ intl,
46
+ onToneSelected,
47
+ onToneOpen,
48
+ showToneSelector
49
+ } = props;
50
+ const {
51
+ formatMessage
52
+ } = intl;
53
+
54
+ if (!toneEmoji) {
55
+ return null;
56
+ }
79
57
 
80
- return jsx("div", {
81
- css: emojiToneSelectorContainer
82
- }, this.state.selectingTone && jsx(ToneSelector, {
83
- emoji: toneEmoji,
84
- onToneSelected: this.onToneSelected,
85
- previewEmojiId: previewEmoji.id
86
- }), jsx(EmojiButton, {
87
- ariaExpanded: this.state.selectingTone,
88
- emoji: previewEmoji,
89
- selectOnHover: true,
90
- onSelected: this.onToneButtonClick,
91
- ariaLabelText: formatMessage(messages.emojiSelectSkinToneButtonAriaLabelText, {
92
- selectedTone: `${setSkinToneAriaLabelText(previewEmoji.name)} selected`
93
- })
94
- }));
95
- } // note: emoji-picker-add-emoji className is used by pollinator synthetic checks
58
+ let previewEmoji = toneEmoji;
96
59
 
60
+ if (selectedTone && previewEmoji.skinVariations) {
61
+ previewEmoji = previewEmoji.skinVariations[(selectedTone || 1) - 1];
62
+ }
97
63
 
98
- renderAddOwnEmoji() {
99
- const {
100
- onOpenUpload,
101
- uploadEnabled,
102
- intl
103
- } = this.props;
104
- const {
105
- formatMessage
106
- } = intl;
64
+ return jsx("div", {
65
+ css: emojiToneSelectorContainer
66
+ }, showToneSelector && jsx(ToneSelector, {
67
+ emoji: toneEmoji,
68
+ onToneSelected: onToneSelected,
69
+ previewEmojiId: previewEmoji.id
70
+ }), jsx(EmojiButton, {
71
+ ariaExpanded: showToneSelector,
72
+ emoji: previewEmoji,
73
+ selectOnHover: true,
74
+ onSelected: onToneOpen,
75
+ ariaLabelText: formatMessage(messages.emojiSelectSkinToneButtonAriaLabelText, {
76
+ selectedTone: `${setSkinToneAriaLabelText(previewEmoji.name)} selected`
77
+ })
78
+ }));
79
+ };
80
+
81
+ export const EmojiActions = props => {
82
+ const {
83
+ onToneSelected,
84
+ onToneSelectorCancelled,
85
+ initialUploadName,
86
+ onUploadCancelled,
87
+ onCloseDelete,
88
+ onDeleteEmoji,
89
+ onUploadEmoji,
90
+ uploadErrorMessage,
91
+ uploading,
92
+ onFileChooserClicked,
93
+ emojiToDelete,
94
+ onChange,
95
+ query
96
+ } = props;
97
+ const [showToneSelector, setShowToneSelector] = useState(false);
98
+ const previewFooterClassnames = [emojiPickerFooter, emojiActionsContainerWithBottomShadow];
99
+
100
+ const onToneOpenHandler = () => setShowToneSelector(true);
101
+
102
+ const onToneSelectedHandler = toneValue => {
103
+ setShowToneSelector(false);
104
+
105
+ if (onToneSelected) {
106
+ onToneSelected(toneValue);
107
+ }
108
+ };
107
109
 
108
- if (!uploadEnabled) {
109
- return null;
110
+ const onMouseLeaveHandler = () => {
111
+ if (showToneSelector && onToneSelectorCancelled) {
112
+ onToneSelectorCancelled();
110
113
  }
111
114
 
115
+ setShowToneSelector(false);
116
+ };
117
+
118
+ if (uploading) {
112
119
  return jsx("div", {
113
- css: addCustomEmoji
114
- }, jsx(FormattedMessage, messages.addCustomEmojiLabel, label => jsx(AkButton, {
115
- onClick: onOpenUpload,
116
- iconBefore: jsx(AddIcon, {
117
- label: formatMessage(messages.addCustomEmojiLabel),
118
- size: "small"
119
- }),
120
- appearance: "subtle",
121
- css: addCustomEmojiButton,
122
- className: emojiPickerAddEmoji
123
- }, label)));
120
+ css: previewFooterClassnames
121
+ }, jsx(EmojiUploadPicker, {
122
+ onUploadCancelled: onUploadCancelled,
123
+ onUploadEmoji: onUploadEmoji,
124
+ onFileChooserClicked: onFileChooserClicked,
125
+ errorMessage: uploadErrorMessage,
126
+ initialUploadName: initialUploadName
127
+ }));
124
128
  }
125
129
 
126
- render() {
127
- const {
128
- initialUploadName,
129
- onUploadCancelled,
130
- onUploadEmoji,
131
- onCloseDelete,
132
- onDeleteEmoji,
133
- uploadErrorMessage,
134
- uploading,
135
- onFileChooserClicked,
136
- emojiToDelete,
137
- onChange,
138
- query
139
- } = this.props;
140
- const previewFooterClassnames = [emojiPickerFooter, emojiActionsContainerWithBottomShadow];
141
-
142
- if (uploading) {
143
- return jsx("div", {
144
- css: previewFooterClassnames
145
- }, jsx(EmojiUploadPicker, {
146
- onUploadCancelled: onUploadCancelled,
147
- onUploadEmoji: onUploadEmoji,
148
- onFileChooserClicked: onFileChooserClicked,
149
- errorMessage: uploadErrorMessage,
150
- initialUploadName: initialUploadName
151
- }));
152
- }
153
-
154
- if (emojiToDelete) {
155
- return jsx("div", {
156
- css: previewFooterClassnames
157
- }, jsx(EmojiDeletePreview, {
158
- emoji: emojiToDelete,
159
- onDeleteEmoji: onDeleteEmoji,
160
- onCloseDelete: onCloseDelete
161
- }));
162
- }
163
-
130
+ if (emojiToDelete) {
164
131
  return jsx("div", {
165
- css: previewFooterClassnames,
166
- onMouseLeave: this.onMouseLeave
167
- }, jsx("div", {
168
- style: {
169
- display: 'flex',
170
- justifyContent: 'flex-end',
171
- alignItems: 'center'
172
- }
173
- }, !this.state.selectingTone && jsx(EmojiPickerListSearch, {
174
- onChange: onChange,
175
- query: query
176
- }), this.renderTones()), this.renderAddOwnEmoji());
132
+ css: previewFooterClassnames
133
+ }, jsx(EmojiDeletePreview, {
134
+ emoji: emojiToDelete,
135
+ onDeleteEmoji: onDeleteEmoji,
136
+ onCloseDelete: onCloseDelete
137
+ }));
177
138
  }
178
139
 
179
- }
140
+ return jsx("div", {
141
+ css: previewFooterClassnames,
142
+ onMouseLeave: onMouseLeaveHandler
143
+ }, jsx("div", {
144
+ css: emojiActionsWrapper
145
+ }, !showToneSelector && jsx(EmojiPickerListSearch, {
146
+ onChange: onChange,
147
+ query: query
148
+ }), jsx(TonesWrapper, _extends({}, props, {
149
+ onToneOpen: onToneOpenHandler,
150
+ onToneSelected: onToneSelectedHandler,
151
+ showToneSelector: showToneSelector
152
+ }))), jsx(AddOwnEmoji, props));
153
+ };
180
154
  export default injectIntl(EmojiActions);
@@ -1,32 +1,28 @@
1
1
  /** @jsx jsx */
2
2
  import { jsx } from '@emotion/core';
3
3
  import ErrorIcon from '@atlaskit/icon/glyph/error';
4
- import { PureComponent } from 'react';
5
4
  import Tooltip from '@atlaskit/tooltip';
6
- export default class EmojiErrorMessage extends PureComponent {
7
- renderWithTooltip() {
8
- return jsx("div", {
9
- css: this.props.messageStyles
10
- }, jsx(Tooltip, {
11
- content: this.props.message,
12
- position: "top"
13
- }, jsx(ErrorIcon, {
14
- label: "Error",
15
- size: "medium"
16
- })));
17
- }
18
5
 
19
- renderInline() {
20
- return jsx("div", {
21
- css: this.props.messageStyles
22
- }, jsx(ErrorIcon, {
23
- label: "Error",
24
- size: "small"
25
- }), " ", this.props.message);
26
- }
6
+ const EmojiErrorMessage = props => {
7
+ const {
8
+ messageStyles,
9
+ message,
10
+ tooltip
11
+ } = props;
12
+ return tooltip ? jsx("div", {
13
+ css: messageStyles
14
+ }, jsx(Tooltip, {
15
+ content: message,
16
+ position: "top"
17
+ }, jsx(ErrorIcon, {
18
+ label: "Error",
19
+ size: "medium"
20
+ }))) : jsx("div", {
21
+ css: messageStyles
22
+ }, jsx(ErrorIcon, {
23
+ label: "Error",
24
+ size: "small"
25
+ }), " ", message);
26
+ };
27
27
 
28
- render() {
29
- return this.props.tooltip ? this.renderWithTooltip() : this.renderInline();
30
- }
31
-
32
- }
28
+ export default EmojiErrorMessage;
@@ -10,6 +10,7 @@ export const EmojiPreviewComponent = ({
10
10
  }, jsx("span", {
11
11
  css: previewImg
12
12
  }, jsx(CachingEmoji, {
13
+ key: emoji.id || emoji.shortName,
13
14
  emoji: emoji
14
15
  })), jsx("div", {
15
16
  css: previewText