@atlaskit/emoji 64.2.0 → 64.4.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 (184) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/dist/cjs/api/EmojiResource.js +36 -1
  3. package/dist/cjs/api/media/SiteEmojiResource.js +10 -2
  4. package/dist/cjs/components/common/CachingEmoji.js +38 -12
  5. package/dist/cjs/components/common/DeleteButton.js +9 -13
  6. package/dist/cjs/components/common/Emoji.js +25 -36
  7. package/dist/cjs/components/common/EmojiActions.js +26 -31
  8. package/dist/cjs/components/common/EmojiButton.js +7 -7
  9. package/dist/cjs/components/common/EmojiDeletePreview.js +20 -26
  10. package/dist/cjs/components/common/EmojiErrorMessage.js +10 -14
  11. package/dist/cjs/components/common/EmojiPlaceholder.js +5 -12
  12. package/dist/cjs/components/common/EmojiPreview.js +20 -40
  13. package/dist/cjs/components/common/EmojiPreviewComponent.js +34 -0
  14. package/dist/cjs/components/common/EmojiUploadPicker.js +26 -24
  15. package/dist/cjs/components/common/EmojiUploadPreview.js +22 -28
  16. package/dist/cjs/components/common/RecordSelectionDefault.js +8 -2
  17. package/dist/cjs/components/common/ResourcedEmoji.js +25 -9
  18. package/dist/cjs/components/common/ResourcedEmojiComponent.js +33 -11
  19. package/dist/cjs/components/common/RetryableButton.js +12 -18
  20. package/dist/cjs/components/common/Scrollable.js +5 -10
  21. package/dist/cjs/components/common/UfoErrorBoundary.js +52 -0
  22. package/dist/cjs/components/common/UploadEmoji.js +8 -0
  23. package/dist/cjs/components/common/styles.js +210 -266
  24. package/dist/cjs/components/picker/CategorySelector.js +13 -12
  25. package/dist/cjs/components/picker/EmojiPicker.js +17 -6
  26. package/dist/cjs/components/picker/EmojiPickerCategoryHeading.js +8 -14
  27. package/dist/cjs/components/picker/EmojiPickerComponent.js +51 -30
  28. package/dist/cjs/components/picker/EmojiPickerEmojiRow.js +8 -12
  29. package/dist/cjs/components/picker/EmojiPickerFooter.js +8 -14
  30. package/dist/cjs/components/picker/EmojiPickerList.js +28 -9
  31. package/dist/cjs/components/picker/EmojiPickerListSearch.js +10 -8
  32. package/dist/cjs/components/picker/EmojiPickerVirtualItems.js +9 -15
  33. package/dist/cjs/components/picker/styles.js +113 -161
  34. package/dist/cjs/components/typeahead/EmojiTypeAheadComponent.js +40 -24
  35. package/dist/cjs/components/typeahead/EmojiTypeAheadItem.js +10 -13
  36. package/dist/cjs/components/typeahead/EmojiTypeAheadList.js +17 -22
  37. package/dist/cjs/components/typeahead/styles.js +17 -19
  38. package/dist/cjs/components/uploader/EmojiUploadComponent.js +22 -15
  39. package/dist/cjs/components/uploader/styles.js +4 -4
  40. package/dist/cjs/index.js +9 -3
  41. package/dist/cjs/types.js +12 -2
  42. package/dist/cjs/util/{analytics.js → analytics/analytics.js} +12 -10
  43. package/dist/cjs/util/analytics/index.js +205 -0
  44. package/dist/cjs/util/analytics/samplingUfo.js +278 -0
  45. package/dist/cjs/util/analytics/ufoExperiences.js +46 -0
  46. package/dist/cjs/util/analytics/useSampledUFOComponentExperience.js +49 -0
  47. package/dist/cjs/util/constants.js +10 -3
  48. package/dist/cjs/version.json +1 -1
  49. package/dist/es2019/api/EmojiResource.js +28 -1
  50. package/dist/es2019/api/media/SiteEmojiResource.js +10 -2
  51. package/dist/es2019/components/common/CachingEmoji.js +34 -12
  52. package/dist/es2019/components/common/DeleteButton.js +8 -6
  53. package/dist/es2019/components/common/Emoji.js +27 -36
  54. package/dist/es2019/components/common/EmojiActions.js +26 -24
  55. package/dist/es2019/components/common/EmojiButton.js +6 -6
  56. package/dist/es2019/components/common/EmojiDeletePreview.js +20 -20
  57. package/dist/es2019/components/common/EmojiErrorMessage.js +9 -8
  58. package/dist/es2019/components/common/EmojiPlaceholder.js +5 -8
  59. package/dist/es2019/components/common/EmojiPreview.js +19 -35
  60. package/dist/es2019/components/common/EmojiPreviewComponent.js +21 -0
  61. package/dist/es2019/components/common/EmojiUploadPicker.js +25 -22
  62. package/dist/es2019/components/common/EmojiUploadPreview.js +22 -22
  63. package/dist/es2019/components/common/RecordSelectionDefault.js +9 -2
  64. package/dist/es2019/components/common/ResourcedEmoji.js +22 -5
  65. package/dist/es2019/components/common/ResourcedEmojiComponent.js +32 -11
  66. package/dist/es2019/components/common/RetryableButton.js +10 -11
  67. package/dist/es2019/components/common/Scrollable.js +6 -10
  68. package/dist/es2019/components/common/UfoErrorBoundary.js +11 -0
  69. package/dist/es2019/components/common/UploadEmoji.js +4 -0
  70. package/dist/es2019/components/common/styles.js +195 -262
  71. package/dist/es2019/components/picker/CategorySelector.js +15 -12
  72. package/dist/es2019/components/picker/EmojiPicker.js +15 -6
  73. package/dist/es2019/components/picker/EmojiPickerCategoryHeading.js +8 -8
  74. package/dist/es2019/components/picker/EmojiPickerComponent.js +46 -22
  75. package/dist/es2019/components/picker/EmojiPickerEmojiRow.js +8 -7
  76. package/dist/es2019/components/picker/EmojiPickerFooter.js +8 -8
  77. package/dist/es2019/components/picker/EmojiPickerList.js +28 -8
  78. package/dist/es2019/components/picker/EmojiPickerListSearch.js +11 -8
  79. package/dist/es2019/components/picker/EmojiPickerVirtualItems.js +10 -8
  80. package/dist/es2019/components/picker/styles.js +112 -160
  81. package/dist/es2019/components/typeahead/EmojiTypeAheadComponent.js +35 -17
  82. package/dist/es2019/components/typeahead/EmojiTypeAheadItem.js +12 -13
  83. package/dist/es2019/components/typeahead/EmojiTypeAheadList.js +18 -19
  84. package/dist/es2019/components/typeahead/styles.js +14 -15
  85. package/dist/es2019/components/uploader/EmojiUploadComponent.js +19 -9
  86. package/dist/es2019/components/uploader/styles.js +4 -4
  87. package/dist/es2019/index.js +4 -3
  88. package/dist/es2019/types.js +10 -1
  89. package/dist/es2019/util/{analytics.js → analytics/analytics.js} +17 -11
  90. package/dist/es2019/util/analytics/index.js +4 -0
  91. package/dist/es2019/util/analytics/samplingUfo.js +147 -0
  92. package/dist/es2019/util/analytics/ufoExperiences.js +34 -0
  93. package/dist/es2019/util/analytics/useSampledUFOComponentExperience.js +39 -0
  94. package/dist/es2019/util/constants.js +5 -1
  95. package/dist/es2019/version.json +1 -1
  96. package/dist/esm/api/EmojiResource.js +32 -1
  97. package/dist/esm/api/media/SiteEmojiResource.js +10 -2
  98. package/dist/esm/components/common/CachingEmoji.js +36 -12
  99. package/dist/esm/components/common/DeleteButton.js +8 -6
  100. package/dist/esm/components/common/Emoji.js +26 -29
  101. package/dist/esm/components/common/EmojiActions.js +26 -25
  102. package/dist/esm/components/common/EmojiButton.js +6 -6
  103. package/dist/esm/components/common/EmojiDeletePreview.js +19 -20
  104. package/dist/esm/components/common/EmojiErrorMessage.js +9 -8
  105. package/dist/esm/components/common/EmojiPlaceholder.js +5 -8
  106. package/dist/esm/components/common/EmojiPreview.js +19 -33
  107. package/dist/esm/components/common/EmojiPreviewComponent.js +20 -0
  108. package/dist/esm/components/common/EmojiUploadPicker.js +27 -25
  109. package/dist/esm/components/common/EmojiUploadPreview.js +21 -22
  110. package/dist/esm/components/common/RecordSelectionDefault.js +6 -3
  111. package/dist/esm/components/common/ResourcedEmoji.js +22 -9
  112. package/dist/esm/components/common/ResourcedEmojiComponent.js +32 -10
  113. package/dist/esm/components/common/RetryableButton.js +11 -12
  114. package/dist/esm/components/common/Scrollable.js +6 -10
  115. package/dist/esm/components/common/UfoErrorBoundary.js +38 -0
  116. package/dist/esm/components/common/UploadEmoji.js +4 -0
  117. package/dist/esm/components/common/styles.js +192 -242
  118. package/dist/esm/components/picker/CategorySelector.js +14 -12
  119. package/dist/esm/components/picker/EmojiPicker.js +13 -6
  120. package/dist/esm/components/picker/EmojiPickerCategoryHeading.js +8 -8
  121. package/dist/esm/components/picker/EmojiPickerComponent.js +47 -22
  122. package/dist/esm/components/picker/EmojiPickerEmojiRow.js +8 -7
  123. package/dist/esm/components/picker/EmojiPickerFooter.js +8 -8
  124. package/dist/esm/components/picker/EmojiPickerList.js +29 -8
  125. package/dist/esm/components/picker/EmojiPickerListSearch.js +10 -8
  126. package/dist/esm/components/picker/EmojiPickerVirtualItems.js +9 -8
  127. package/dist/esm/components/picker/styles.js +108 -149
  128. package/dist/esm/components/typeahead/EmojiTypeAheadComponent.js +35 -17
  129. package/dist/esm/components/typeahead/EmojiTypeAheadItem.js +11 -13
  130. package/dist/esm/components/typeahead/EmojiTypeAheadList.js +17 -19
  131. package/dist/esm/components/typeahead/styles.js +14 -14
  132. package/dist/esm/components/uploader/EmojiUploadComponent.js +19 -9
  133. package/dist/esm/components/uploader/styles.js +4 -4
  134. package/dist/esm/index.js +4 -3
  135. package/dist/esm/types.js +10 -1
  136. package/dist/esm/util/{analytics.js → analytics/analytics.js} +9 -7
  137. package/dist/esm/util/analytics/index.js +4 -0
  138. package/dist/esm/util/analytics/samplingUfo.js +259 -0
  139. package/dist/esm/util/analytics/ufoExperiences.js +34 -0
  140. package/dist/esm/util/analytics/useSampledUFOComponentExperience.js +39 -0
  141. package/dist/esm/util/constants.js +5 -1
  142. package/dist/esm/version.json +1 -1
  143. package/dist/types/api/EmojiResource.d.ts +1 -0
  144. package/dist/types/components/common/CachingEmoji.d.ts +8 -6
  145. package/dist/types/components/common/EmojiActions.d.ts +2 -3
  146. package/dist/types/components/common/EmojiDeletePreview.d.ts +3 -3
  147. package/dist/types/components/common/EmojiErrorMessage.d.ts +2 -1
  148. package/dist/types/components/common/EmojiPreview.d.ts +2 -3
  149. package/dist/types/components/common/EmojiPreviewComponent.d.ts +7 -0
  150. package/dist/types/components/common/EmojiUploadPreview.d.ts +3 -3
  151. package/dist/types/components/common/ResourcedEmoji.d.ts +2 -0
  152. package/dist/types/components/common/ResourcedEmojiComponent.d.ts +6 -0
  153. package/dist/types/components/common/RetryableButton.d.ts +0 -2
  154. package/dist/types/components/common/UfoErrorBoundary.d.ts +8 -0
  155. package/dist/types/components/common/styles.d.ts +44 -44
  156. package/dist/types/components/picker/EmojiPicker.d.ts +2 -3
  157. package/dist/types/components/picker/EmojiPickerComponent.d.ts +6 -0
  158. package/dist/types/components/picker/EmojiPickerList.d.ts +10 -0
  159. package/dist/types/components/picker/styles.d.ts +17 -18
  160. package/dist/types/components/typeahead/EmojiTypeAheadComponent.d.ts +6 -0
  161. package/dist/types/components/typeahead/styles.d.ts +8 -7
  162. package/dist/types/components/uploader/EmojiUploadComponent.d.ts +1 -0
  163. package/dist/types/components/uploader/styles.d.ts +2 -2
  164. package/dist/types/index.d.ts +3 -3
  165. package/dist/types/types.d.ts +6 -0
  166. package/dist/types/util/{analytics.d.ts → analytics/analytics.d.ts} +7 -7
  167. package/dist/types/util/analytics/index.d.ts +6 -0
  168. package/dist/types/util/analytics/samplingUfo.d.ts +31 -0
  169. package/dist/types/util/analytics/ufoExperiences.d.ts +12 -0
  170. package/dist/types/util/analytics/useSampledUFOComponentExperience.d.ts +8 -0
  171. package/dist/types/util/constants.d.ts +2 -0
  172. package/package.json +10 -9
  173. package/dist/cjs/components/picker/EmojiPickerPreview.js +0 -87
  174. package/dist/cjs/context/EmojiContext.js +0 -11
  175. package/dist/cjs/context/EmojiContextProvider.js +0 -22
  176. package/dist/es2019/components/picker/EmojiPickerPreview.js +0 -43
  177. package/dist/es2019/context/EmojiContext.js +0 -2
  178. package/dist/es2019/context/EmojiContextProvider.js +0 -10
  179. package/dist/esm/components/picker/EmojiPickerPreview.js +0 -67
  180. package/dist/esm/context/EmojiContext.js +0 -2
  181. package/dist/esm/context/EmojiContextProvider.js +0 -9
  182. package/dist/types/components/picker/EmojiPickerPreview.d.ts +0 -9
  183. package/dist/types/context/EmojiContext.d.ts +0 -4
  184. package/dist/types/context/EmojiContextProvider.d.ts +0 -7
@@ -1,13 +1,15 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
- import React from 'react';
2
+
3
+ /** @jsx jsx */
4
+ import { jsx } from '@emotion/core';
3
5
  import { PureComponent } from 'react';
4
6
  import { FormattedMessage } from 'react-intl-next';
5
- import classNames from 'classnames';
6
- import * as styles from './styles';
7
7
  import { supportsUploadFeature } from '../../api/EmojiResource';
8
8
  import EmojiUploadPickerWithIntl from '../common/EmojiUploadPicker';
9
9
  import { uploadEmoji } from '../common/UploadEmoji';
10
10
  import { createAndFireEventInElementsChannel, selectedFileEvent, uploadCancelButton, uploadConfirmButton } from '../../util/analytics';
11
+ import { emojiUploadFooter, emojiUploadWidget } from './styles';
12
+ import { ufoExperiences } from '../../util/analytics/ufoExperiences';
11
13
  export default class EmojiUploadComponent extends PureComponent {
12
14
  constructor(props) {
13
15
  super(props);
@@ -16,6 +18,10 @@ export default class EmojiUploadComponent extends PureComponent {
16
18
  const {
17
19
  emojiProvider
18
20
  } = this.props;
21
+ ufoExperiences['emoji-uploaded'].start();
22
+ ufoExperiences['emoji-uploaded'].addMetadata({
23
+ retry
24
+ });
19
25
  this.fireAnalytics(uploadConfirmButton({
20
26
  retry
21
27
  }));
@@ -77,17 +83,21 @@ export default class EmojiUploadComponent extends PureComponent {
77
83
  this.state = {};
78
84
  }
79
85
 
86
+ componentWillUnmount() {
87
+ ufoExperiences['emoji-uploaded'].abort();
88
+ }
89
+
80
90
  render() {
81
91
  const {
82
92
  uploadErrorMessage
83
93
  } = this.state;
84
- const errorMessage = uploadErrorMessage ? /*#__PURE__*/React.createElement(FormattedMessage, uploadErrorMessage) : null;
85
- return /*#__PURE__*/React.createElement("div", {
86
- className: classNames([styles.emojiUploadWidget]),
94
+ const errorMessage = uploadErrorMessage ? jsx(FormattedMessage, uploadErrorMessage) : null;
95
+ return jsx("div", {
96
+ css: emojiUploadWidget,
87
97
  ref: this.props.onUploaderRef
88
- }, /*#__PURE__*/React.createElement("div", {
89
- className: classNames([styles.emojiUploadFooter])
90
- }, /*#__PURE__*/React.createElement(EmojiUploadPickerWithIntl, {
98
+ }, jsx("div", {
99
+ css: emojiUploadFooter
100
+ }, jsx(EmojiUploadPickerWithIntl, {
91
101
  ref: this.onUploaderRef,
92
102
  onFileChooserClicked: this.onFileChooserClicked,
93
103
  onUploadCancelled: this.onUploadCancelled,
@@ -1,8 +1,8 @@
1
- import { style } from 'typestyle';
2
1
  import { token } from '@atlaskit/tokens';
3
- import { emojiPickerWidth } from '../../util/constants'; // Uploader
2
+ import { emojiPickerWidth } from '../../util/constants';
3
+ import { css } from '@emotion/core'; // Uploader
4
4
 
5
- export const emojiUploadWidget = style({
5
+ export const emojiUploadWidget = css({
6
6
  display: 'flex',
7
7
  flexDirection: 'column',
8
8
  justifyContent: 'center',
@@ -16,6 +16,6 @@ export const emojiUploadWidget = style({
16
16
  marginTop: '-16px'
17
17
  }); /// Footer
18
18
 
19
- export const emojiUploadFooter = style({
19
+ export const emojiUploadFooter = css({
20
20
  flex: '0 0 auto'
21
21
  });
@@ -6,18 +6,19 @@ import EmojiPicker from './components/picker/EmojiPicker';
6
6
  import EmojiUploader from './components/uploader/EmojiUploader';
7
7
  import EmojiTypeAhead from './components/typeahead/EmojiTypeAhead';
8
8
  import EmojiTypeAheadItem from './components/typeahead/EmojiTypeAheadItem';
9
- export { selected, selectOnHover, emojiSprite, emojiNode, emojiImage } from './components/common/styles';
9
+ export { // renaming exports to prevent breaking changes due to renaming
10
+ commonSelectedStyles as selected, selectOnHoverStyles as selectOnHover, emojiSprite, emojiNodeStyles as emojiNode, emojiImage } from './components/common/styles';
10
11
  import EmojiResource from './api/EmojiResource';
11
12
  import EmojiRepository from './api/EmojiRepository';
12
13
  import EmojiLoader from './api/EmojiLoader';
13
14
  import { denormaliseEmojiServiceResponse } from './api/EmojiUtils';
14
15
  import { toEmojiId, toOptionalEmojiId } from './util/type-helpers';
15
- import { recordSelectionFailedSli, recordSelectionSucceededSli } from './util/analytics';
16
+ import { recordSelectionFailedSli, recordSelectionSucceededSli, ufoExperiences } from './util/analytics';
16
17
  import { customCategory, defaultEmojiHeight, emojiPickerWidth, emojiPickerHeight } from './util/constants';
17
18
  import { UsageFrequencyTracker } from './api/internal/UsageFrequencyTracker';
18
19
  export { // Classes
19
20
  AbstractResource, Emoji, EmojiPlaceholder, EmojiLoader, EmojiPicker, EmojiUploader, EmojiResource, EmojiRepository, EmojiTypeAhead, ResourcedEmoji, // functions
20
- denormaliseEmojiServiceResponse, toEmojiId, toOptionalEmojiId, recordSelectionFailedSli, recordSelectionSucceededSli, // Constants
21
+ denormaliseEmojiServiceResponse, toEmojiId, toOptionalEmojiId, recordSelectionFailedSli, recordSelectionSucceededSli, ufoExperiences, // Constants
21
22
  emojiPickerWidth, emojiPickerHeight, defaultEmojiHeight, customCategory, UsageFrequencyTracker, EmojiTypeAheadItem };
22
23
  export { // Enums
23
24
  SearchSort } from './types';
@@ -33,4 +33,13 @@ export let SearchSort;
33
33
  SearchSort[SearchSort["None"] = 0] = "None";
34
34
  SearchSort[SearchSort["Default"] = 1] = "Default";
35
35
  SearchSort[SearchSort["UsageFrequency"] = 2] = "UsageFrequency";
36
- })(SearchSort || (SearchSort = {}));
36
+ })(SearchSort || (SearchSort = {}));
37
+
38
+ export let ProviderTypes;
39
+
40
+ (function (ProviderTypes) {
41
+ ProviderTypes["SITE"] = "SITE";
42
+ ProviderTypes["STANDARD"] = "STANDARD";
43
+ ProviderTypes["ATLASSIAN"] = "ATLASSIAN";
44
+ ProviderTypes["UNKNOWN"] = "UNKNOWN";
45
+ })(ProviderTypes || (ProviderTypes = {}));
@@ -1,5 +1,5 @@
1
1
  import { createAndFireEvent } from '@atlaskit/analytics-next';
2
- import { name as packageName, version as packageVersion } from '../version.json';
2
+ import { name as packageName, version as packageVersion } from '../../version.json';
3
3
  export const createAndFireEventInElementsChannel = createAndFireEvent('fabric-elements');
4
4
 
5
5
  const createEvent = (eventType, action, actionSubject, actionSubjectId, attributes = {}) => ({
@@ -14,12 +14,16 @@ const createEvent = (eventType, action, actionSubject, actionSubjectId, attribut
14
14
  }
15
15
  });
16
16
 
17
- export const insertionSucceeded = source => createEvent('operational', 'succeeded', 'recordEmojiSelection', undefined, {
18
- source
19
- });
20
- export const insertionFailed = source => createEvent('operational', 'failed', 'recordEmojiSelection', undefined, {
21
- source
22
- });
17
+ export const recordSucceeded = source => {
18
+ return createEvent('operational', 'succeeded', 'recordEmojiSelection', undefined, {
19
+ source
20
+ });
21
+ };
22
+ export const recordFailed = source => {
23
+ return createEvent('operational', 'failed', 'recordEmojiSelection', undefined, {
24
+ source
25
+ });
26
+ };
23
27
 
24
28
  const emojiPickerEvent = (action, attributes = {}, actionSubjectId) => createEvent('ui', action, 'emojiPicker', actionSubjectId, attributes);
25
29
 
@@ -119,15 +123,17 @@ export const typeaheadSelectedEvent = (pressed, duration, emoji, emojiList, quer
119
123
  export const typeaheadRenderedEvent = (duration, query, emojiList) => createEvent('operational', 'rendered', 'emojiTypeahead', undefined, {
120
124
  duration,
121
125
  ...extractCommonAttributes(query, emojiList)
122
- });
126
+ }); // it's used in editor typeahead to fire success record analytics
127
+
123
128
  export const recordSelectionSucceededSli = options => () => {
124
129
  if (options && options.createAnalyticsEvent) {
125
- createAndFireEvent('editor')(insertionSucceeded('typeahead'))(options.createAnalyticsEvent);
130
+ createAndFireEvent('editor')(recordSucceeded('typeahead'))(options.createAnalyticsEvent);
126
131
  }
127
- };
132
+ }; // it's used in editor typeahead to fire failure record analytics
133
+
128
134
  export const recordSelectionFailedSli = options => err => {
129
135
  if (options && options.createAnalyticsEvent) {
130
- createAndFireEvent('editor')(insertionFailed('typeahead'))(options.createAnalyticsEvent);
136
+ createAndFireEvent('editor')(recordFailed('typeahead'))(options.createAnalyticsEvent);
131
137
  }
132
138
 
133
139
  return Promise.reject(err);
@@ -0,0 +1,4 @@
1
+ export { ufoExperiencesSampled, clearSampled, isExperienceSampled, withSampling } from './samplingUfo';
2
+ export { categoryClickedEvent, createAndFireEventInElementsChannel, closedPickerEvent, deleteBeginEvent, deleteCancelEvent, deleteConfirmEvent, recordFailed, recordSucceeded, openedPickerEvent, pickerClickedEvent, pickerSearchedEvent, recordSelectionFailedSli, recordSelectionSucceededSli, selectedFileEvent, toneSelectedEvent, toneSelectorClosedEvent, toneSelectorOpenedEvent, typeaheadCancelledEvent, typeaheadRenderedEvent, typeaheadSelectedEvent, uploadBeginButton, uploadCancelButton, uploadConfirmButton, uploadFailedEvent, uploadSucceededEvent } from './analytics';
3
+ export { sampledUfoRenderedEmoji, ufoExperiences } from './ufoExperiences';
4
+ export { useSampledUFOComponentExperience } from './useSampledUFOComponentExperience';
@@ -0,0 +1,147 @@
1
+ export const ufoExperiencesSampled = {};
2
+
3
+ const sampleChance = (min, max) => {
4
+ // min and max included
5
+ return Math.floor(Math.random() * (max - min + 1) + min);
6
+ };
7
+
8
+ export const clearSampled = () => {
9
+ for (const prop of Object.getOwnPropertyNames(ufoExperiencesSampled)) {
10
+ delete ufoExperiencesSampled[prop];
11
+ }
12
+ }; // default sampling function to determine which one to be sampled
13
+
14
+ export const isExperienceSampled = rate => {
15
+ // if invalid sampling rate provided, we sample it
16
+ if (rate > 1 || rate < 0) {
17
+ return true;
18
+ }
19
+
20
+ if (rate === 1) {
21
+ return true;
22
+ }
23
+
24
+ if (rate === 0) {
25
+ return false;
26
+ }
27
+
28
+ const maxCount = Math.ceil(1 / rate);
29
+ const chance = sampleChance(1, maxCount);
30
+ return chance === maxCount;
31
+ };
32
+
33
+ const hasSampledFromStart = experience => {
34
+ if (!ufoExperiencesSampled[experience.id]) {
35
+ return false;
36
+ }
37
+
38
+ if (experience.instanceId) {
39
+ // if the instance of concurrent exp has been sampled from start, allow it.
40
+ return ufoExperiencesSampled[experience.id].sampledInstance[experience.instanceId];
41
+ }
42
+
43
+ return ufoExperiencesSampled[experience.id].sampled;
44
+ };
45
+
46
+ /**
47
+ * This function is a temp solution to reduce the event traffic, as UFO package does not support it.
48
+ *
49
+ * e.g. Emoji Picker contains thousands of emojis, which means will trigger a large number of renderred events without sampling
50
+ * @param ufoExperience
51
+ * @returns
52
+ */
53
+ export const withSampling = ufoExperience => {
54
+ const init = () => {
55
+ if (!ufoExperiencesSampled[ufoExperience.id]) {
56
+ ufoExperiencesSampled[ufoExperience.id] = {
57
+ sampled: false,
58
+ sampledInstance: {}
59
+ };
60
+ }
61
+ };
62
+
63
+ const start = async options => {
64
+ // check if the experience has already sampled before
65
+ if (hasSampledFromStart(ufoExperience)) {
66
+ return;
67
+ }
68
+
69
+ const isSampled = options.samplingFunc || isExperienceSampled;
70
+
71
+ if (!isSampled(options.samplingRate)) {
72
+ if (ufoExperience.instanceId) {
73
+ ufoExperiencesSampled[ufoExperience.id].sampledInstance[ufoExperience.instanceId] = false;
74
+ }
75
+
76
+ ufoExperiencesSampled[ufoExperience.id].sampled = false;
77
+ return;
78
+ } // update sampled records
79
+
80
+
81
+ if (ufoExperience.instanceId) {
82
+ ufoExperiencesSampled[ufoExperience.id].sampledInstance[ufoExperience.instanceId] = true;
83
+ ufoExperiencesSampled[ufoExperience.id].sampled = true;
84
+ }
85
+
86
+ return ufoExperience.start(options.startTime);
87
+ };
88
+
89
+ const success = async config => {
90
+ if (!hasSampledFromStart(ufoExperience)) {
91
+ return null;
92
+ }
93
+
94
+ return ufoExperience.success(config);
95
+ };
96
+
97
+ const failure = async config => {
98
+ if (!hasSampledFromStart(ufoExperience)) {
99
+ return null;
100
+ }
101
+
102
+ return ufoExperience.failure(config);
103
+ };
104
+
105
+ const abort = async config => {
106
+ if (!hasSampledFromStart(ufoExperience)) {
107
+ return null;
108
+ }
109
+
110
+ return ufoExperience.abort(config);
111
+ };
112
+
113
+ const mark = (name, timestamp) => {
114
+ if (!hasSampledFromStart(ufoExperience)) {
115
+ return;
116
+ }
117
+
118
+ return ufoExperience.mark(name, timestamp);
119
+ };
120
+
121
+ const markFMP = timestamp => {
122
+ if (!hasSampledFromStart(ufoExperience)) {
123
+ return;
124
+ }
125
+
126
+ return ufoExperience.markFMP(timestamp);
127
+ };
128
+
129
+ const markInlineResponse = timestamp => {
130
+ if (!hasSampledFromStart(ufoExperience)) {
131
+ return;
132
+ }
133
+
134
+ return ufoExperience.markInlineResponse(timestamp);
135
+ };
136
+
137
+ init();
138
+ return { ...ufoExperience,
139
+ start,
140
+ success,
141
+ failure,
142
+ abort,
143
+ mark,
144
+ markFMP,
145
+ markInlineResponse
146
+ };
147
+ };
@@ -0,0 +1,34 @@
1
+ import { ExperiencePerformanceTypes, ExperienceTypes, ConcurrentExperience, UFOExperience } from '@atlaskit/ufo';
2
+ import { withSampling } from './samplingUfo'; // TODO: clean up as not needed
3
+
4
+ const createRenderExperience = componentName => {
5
+ return {
6
+ platform: {
7
+ component: componentName
8
+ },
9
+ type: ExperienceTypes.Load,
10
+ performanceType: ExperiencePerformanceTypes.PageSegmentLoad
11
+ };
12
+ };
13
+
14
+ const createInlineExperience = componentName => {
15
+ return {
16
+ platform: {
17
+ component: componentName
18
+ },
19
+ type: ExperienceTypes.Experience,
20
+ performanceType: ExperiencePerformanceTypes.InlineResult
21
+ };
22
+ };
23
+
24
+ export const ufoExperiences = {
25
+ 'emoji-rendered': new ConcurrentExperience('emoji-rendered', createRenderExperience('emoji')),
26
+ 'emoji-resource-fetched': new ConcurrentExperience('emoji-resource-fetched', createRenderExperience('emoji-provider')),
27
+ 'emoji-picker-opened': new UFOExperience('emoji-picker-opened', createRenderExperience('emoji-picker')),
28
+ 'emoji-selection-recorded': new UFOExperience('emoji-selection-recorded', createInlineExperience('emoji-picker')),
29
+ 'emoji-uploaded': new UFOExperience('emoji-uploaded', createInlineExperience('emoji-picker')),
30
+ 'emoji-searched': new UFOExperience('emoji-searched', createInlineExperience('emoji-picker'))
31
+ };
32
+ export const sampledUfoRenderedEmoji = emojiId => {
33
+ return withSampling(ufoExperiences['emoji-rendered'].getInstance(emojiId.id || emojiId.shortName));
34
+ };
@@ -0,0 +1,39 @@
1
+ import { useEffect, useRef } from 'react';
2
+ import { withSampling } from './samplingUfo';
3
+
4
+ const useConstructor = callback => {
5
+ const hasBeenFired = useRef(false);
6
+
7
+ if (!hasBeenFired.current) {
8
+ callback();
9
+ hasBeenFired.current = true;
10
+ }
11
+
12
+ return null;
13
+ };
14
+ /**
15
+ * A hook to start an experience and to auto abort the experience when the parent component is unmounted.
16
+ * Use this instead of a direct call to `experience.start`. If you need to restart the experience
17
+ * simply trigger an unmount and remount of the parent component.
18
+ * @param experience the experience to start and abort
19
+ */
20
+
21
+
22
+ export const useSampledUFOComponentExperience = (experience, samplingRate, metadata) => {
23
+ useEffect(() => {
24
+ return () => {
25
+ withSampling(experience).abort();
26
+ }; // we want this cleanup to only happen on unmount so this is a legit use of empty array
27
+ // eslint-disable-next-line react-hooks/exhaustive-deps
28
+ }, []);
29
+ useConstructor(() => {
30
+ withSampling(experience).start({
31
+ samplingRate
32
+ });
33
+
34
+ if (metadata) {
35
+ experience.addMetadata(metadata);
36
+ }
37
+ });
38
+ return null;
39
+ };
@@ -19,4 +19,8 @@ export const selectedToneStorageKey = `${localStoragePrefix}.selectedTone`;
19
19
  export const defaultCategories = ['PEOPLE', 'NATURE', 'FOODS', 'ACTIVITY', 'PLACES', 'OBJECTS', 'SYMBOLS', 'FLAGS'];
20
20
  export const defaultListLimit = 50;
21
21
  export const migrationUserId = 'hipchat_migration_emoticons';
22
- export const analyticsEmojiPrefix = 'atlassian.fabric.emoji.picker';
22
+ export const analyticsEmojiPrefix = 'atlassian.fabric.emoji.picker'; // This is the base sampling rate in Emoji
23
+
24
+ export const SAMPLING_RATE_EMOJI_RENDERED_EXP = 0.05; // This rate is used in ResourceEmoji which will be used in stead of base sampling rate above
25
+
26
+ export const SAMPLING_RATE_EMOJI_RENDERED_EXP_RESOURCEEMOJI = 0.1; // add more sampling rate in parent components like EmojiTypeAheadItem.
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/emoji",
3
- "version": "64.2.0",
3
+ "version": "64.4.0",
4
4
  "sideEffects": false
5
5
  }
@@ -15,10 +15,12 @@ import { AbstractResource, utils as serviceUtils } from '@atlaskit/util-service-
15
15
  import { selectedToneStorageKey } from '../util/constants';
16
16
  import { isMediaEmoji, isPromise, toEmojiId } from '../util/type-helpers';
17
17
  import storageAvailable from '../util/storage-available';
18
+ import { ProviderTypes } from '../types';
18
19
  import debug from '../util/logger';
19
20
  import EmojiLoader from './EmojiLoader';
20
21
  import EmojiRepository from './EmojiRepository';
21
22
  import SiteEmojiResource from './media/SiteEmojiResource';
23
+ import { ufoExperiences } from '../util/analytics';
22
24
 
23
25
  /**
24
26
  * Checks if the emojiProvider can support uploading at a feature level.
@@ -59,6 +61,12 @@ export var EmojiResource = /*#__PURE__*/function (_AbstractResource) {
59
61
  var emojiResponses = [];
60
62
  _this.activeLoaders = config.providers.length;
61
63
  config.providers.forEach(function (provider, index) {
64
+ var providerType = _this.getProviderType(provider);
65
+
66
+ ufoExperiences['emoji-resource-fetched'].getInstance(providerType).start();
67
+ ufoExperiences['emoji-resource-fetched'].getInstance(providerType).addMetadata({
68
+ type: providerType
69
+ });
62
70
  var loader = new EmojiLoader(provider);
63
71
  var emojis = loader.loadEmoji();
64
72
  emojis.then(function (emojiResponse) {
@@ -71,12 +79,22 @@ export var EmojiResource = /*#__PURE__*/function (_AbstractResource) {
71
79
 
72
80
  _this.performRetries();
73
81
 
74
- _this.refreshLastFilter();
82
+ _this.refreshLastFilter(); // if not site emoji it would still resolve
83
+ // TODO: improve the logic in future
84
+
85
+
86
+ ufoExperiences['emoji-resource-fetched'].getInstance(providerType).success();
75
87
  });
76
88
  }).catch(function (reason) {
77
89
  _this.activeLoaders--;
78
90
 
79
91
  _this.notifyError(reason);
92
+
93
+ ufoExperiences['emoji-resource-fetched'].getInstance(providerType).failure({
94
+ metadata: {
95
+ reason: reason
96
+ }
97
+ });
80
98
  });
81
99
  });
82
100
 
@@ -92,6 +110,19 @@ export var EmojiResource = /*#__PURE__*/function (_AbstractResource) {
92
110
  }
93
111
 
94
112
  _createClass(EmojiResource, [{
113
+ key: "getProviderType",
114
+ value: function getProviderType(provider) {
115
+ if (provider.url.includes('/site')) {
116
+ return ProviderTypes.SITE;
117
+ } else if (provider.url.includes('/standard')) {
118
+ return ProviderTypes.STANDARD;
119
+ } else if (provider.url.includes('/atlassian')) {
120
+ return ProviderTypes.ATLASSIAN;
121
+ }
122
+
123
+ return ProviderTypes.UNKNOWN;
124
+ }
125
+ }, {
95
126
  key: "initEmojiRepository",
96
127
  value: function initEmojiRepository(emojiResponses) {
97
128
  var emojis = [];
@@ -178,7 +178,11 @@ var SiteEmojiResource = /*#__PURE__*/function () {
178
178
  }, {
179
179
  key: "findEmoji",
180
180
  value: function findEmoji(emojiId) {
181
- var path = "../".concat(emojiId.id);
181
+ if (!emojiId.id) {
182
+ return Promise.reject(false);
183
+ }
184
+
185
+ var path = "../".concat(encodeURIComponent(emojiId.id));
182
186
  return emojiRequest(this.siteServiceConfig, {
183
187
  path: path
184
188
  }).then(function (serviceResponse) {
@@ -202,7 +206,11 @@ var SiteEmojiResource = /*#__PURE__*/function () {
202
206
  return Promise.reject(false);
203
207
  }
204
208
 
205
- var path = "".concat(emoji.id);
209
+ if (!emoji.id) {
210
+ return Promise.reject(false);
211
+ }
212
+
213
+ var path = "".concat(encodeURIComponent(emoji.id));
206
214
  var requestInit = {
207
215
  method: 'DELETE'
208
216
  };
@@ -14,6 +14,7 @@ function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflec
14
14
 
15
15
  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; } }
16
16
 
17
+ import PropTypes from 'prop-types';
17
18
  import React from 'react';
18
19
  import { PureComponent } from 'react';
19
20
  import { shouldUseAltRepresentation } from '../../api/EmojiUtils';
@@ -21,7 +22,9 @@ import { isEmojiDescription, isMediaEmoji, isPromise } from '../../util/type-hel
21
22
  import debug from '../../util/logger';
22
23
  import Emoji from './Emoji';
23
24
  import EmojiPlaceholder from './EmojiPlaceholder';
24
- import { EmojiContext } from '../../context/EmojiContext';
25
+ import { UfoErrorBoundary } from './UfoErrorBoundary';
26
+ import { sampledUfoRenderedEmoji, ufoExperiences, useSampledUFOComponentExperience } from '../../util/analytics';
27
+ import { SAMPLING_RATE_EMOJI_RENDERED_EXP } from '../../util/constants';
25
28
 
26
29
  /**
27
30
  * Renders an emoji from a cached image, if required.
@@ -30,13 +33,24 @@ export var CachingEmoji = function CachingEmoji(props) {
30
33
  // Optimisation to only render the class based CachingMediaEmoji if necessary
31
34
  // slight performance hit, which accumulates for a large number of emoji.
32
35
  var placeholderSize = props.placeholderSize,
33
- emojiProps = _objectWithoutProperties(props, _excluded);
36
+ emojiProps = _objectWithoutProperties(props, _excluded); // start emoji rendered experience, it may have already started earlier in ResourcedEmoji
34
37
 
35
- if (isMediaEmoji(props.emoji)) {
36
- return /*#__PURE__*/React.createElement(CachingMediaEmoji, props);
37
- }
38
38
 
39
- return /*#__PURE__*/React.createElement(Emoji, emojiProps);
39
+ useSampledUFOComponentExperience(ufoExperiences['emoji-rendered'].getInstance(emojiProps.emoji.id || emojiProps.emoji.shortName), SAMPLING_RATE_EMOJI_RENDERED_EXP, {
40
+ source: 'caching-emoji'
41
+ });
42
+
43
+ var emojiNode = function emojiNode() {
44
+ if (isMediaEmoji(props.emoji)) {
45
+ return /*#__PURE__*/React.createElement(CachingMediaEmoji, props);
46
+ }
47
+
48
+ return /*#__PURE__*/React.createElement(Emoji, emojiProps);
49
+ };
50
+
51
+ return /*#__PURE__*/React.createElement(UfoErrorBoundary, {
52
+ experiences: [ufoExperiences['emoji-rendered'].getInstance(props.emoji.id || props.emoji.shortName)]
53
+ }, emojiNode());
40
54
  };
41
55
  /**
42
56
  * Rendering a media emoji image from a cache for media emoji, with different
@@ -53,12 +67,17 @@ export var CachingMediaEmoji = /*#__PURE__*/function (_PureComponent) {
53
67
 
54
68
  _classCallCheck(this, CachingMediaEmoji);
55
69
 
56
- _this = _super.call(this, props);
70
+ _this = _super.call(this, props, context);
57
71
 
58
72
  _defineProperty(_assertThisInitialized(_this), "mounted", false);
59
73
 
60
74
  _defineProperty(_assertThisInitialized(_this), "handleLoadError", function (_emojiId, emoji) {
61
75
  var invalidImage = _this.state.invalidImage;
76
+ sampledUfoRenderedEmoji(_emojiId).failure({
77
+ metadata: {
78
+ reason: 'load error'
79
+ }
80
+ });
62
81
 
63
82
  if (invalidImage || !emoji) {
64
83
  // do nothing, bad image
@@ -80,6 +99,7 @@ export var CachingMediaEmoji = /*#__PURE__*/function (_PureComponent) {
80
99
  key: "componentDidMount",
81
100
  value: function componentDidMount() {
82
101
  this.mounted = true;
102
+ sampledUfoRenderedEmoji(this.props.emoji).markFMP();
83
103
  }
84
104
  }, {
85
105
  key: "componentWillUnmount",
@@ -102,10 +122,6 @@ export var CachingMediaEmoji = /*#__PURE__*/function (_PureComponent) {
102
122
  value: function loadEmoji(emoji, context, forceLoad) {
103
123
  var _this2 = this;
104
124
 
105
- if (!context) {
106
- return;
107
- }
108
-
109
125
  if (!context.emoji) {
110
126
  return undefined;
111
127
  }
@@ -142,6 +158,12 @@ export var CachingMediaEmoji = /*#__PURE__*/function (_PureComponent) {
142
158
  cachedEmoji: undefined,
143
159
  invalidImage: true
144
160
  });
161
+
162
+ sampledUfoRenderedEmoji(emoji).failure({
163
+ metadata: {
164
+ reason: 'failed to load media emoji'
165
+ }
166
+ });
145
167
  }
146
168
  });
147
169
  return undefined;
@@ -193,6 +215,8 @@ export var CachingMediaEmoji = /*#__PURE__*/function (_PureComponent) {
193
215
  return CachingMediaEmoji;
194
216
  }(PureComponent);
195
217
 
196
- _defineProperty(CachingMediaEmoji, "contextType", EmojiContext);
218
+ _defineProperty(CachingMediaEmoji, "contextTypes", {
219
+ emoji: PropTypes.object
220
+ });
197
221
 
198
222
  export default CachingEmoji;
@@ -1,16 +1,18 @@
1
+ /** @jsx jsx */
2
+ import { jsx } from '@emotion/core';
1
3
  import Button from '@atlaskit/button/custom-theme-button';
2
4
  import CrossCircleIcon from '@atlaskit/icon/glyph/cross-circle';
3
- import React from 'react';
4
5
  import { token } from '@atlaskit/tokens';
5
6
  import { N500 } from '@atlaskit/theme/colors';
6
7
  import { deleteEmojiLabel } from '../../util/constants';
7
- import * as styles from './styles';
8
+ import { emojiDeleteButton, deleteButton } from './styles';
8
9
 
9
10
  var DeleteButton = function DeleteButton(props) {
10
- return /*#__PURE__*/React.createElement("span", {
11
- className: styles.deleteButton
12
- }, /*#__PURE__*/React.createElement(Button, {
13
- iconBefore: /*#__PURE__*/React.createElement(CrossCircleIcon, {
11
+ return jsx("span", {
12
+ css: deleteButton,
13
+ className: emojiDeleteButton
14
+ }, jsx(Button, {
15
+ iconBefore: jsx(CrossCircleIcon, {
14
16
  label: deleteEmojiLabel,
15
17
  primaryColor: token('color.text.subtle', N500),
16
18
  size: "small"