@atlaskit/emoji 71.0.0 → 71.1.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.
- package/CHANGELOG.md +16 -0
- package/afm-cc/tsconfig.json +3 -0
- package/afm-products/tsconfig.json +3 -0
- package/dist/cjs/components/common/Emoji.js +141 -5
- package/dist/cjs/components/common/EmojiActions.compiled.css +8 -0
- package/dist/cjs/components/common/EmojiActions.js +69 -3
- package/dist/cjs/components/common/Popup.js +20 -5
- package/dist/cjs/components/common/ProductivityColorSelector.compiled.css +59 -0
- package/dist/cjs/components/common/ProductivityColorSelector.js +112 -0
- package/dist/cjs/components/common/ResourcedEmojiComponent.js +4 -1
- package/dist/cjs/components/common/TonePreviewButton.js +4 -2
- package/dist/cjs/components/i18n.js +10 -0
- package/dist/cjs/components/picker/EmojiPickerComponent.js +51 -36
- package/dist/cjs/components/picker/EmojiPickerList.js +36 -14
- package/dist/cjs/components/picker/VirtualList.js +4 -5
- package/dist/cjs/util/analytics/analytics.js +1 -1
- package/dist/cjs/util/hidden-emojis.js +33 -0
- package/dist/cjs/util/productivity-colors.js +51 -0
- package/dist/es2019/components/common/Emoji.js +115 -5
- package/dist/es2019/components/common/EmojiActions.compiled.css +8 -0
- package/dist/es2019/components/common/EmojiActions.js +67 -3
- package/dist/es2019/components/common/Popup.js +19 -5
- package/dist/es2019/components/common/ProductivityColorSelector.compiled.css +59 -0
- package/dist/es2019/components/common/ProductivityColorSelector.js +98 -0
- package/dist/es2019/components/common/ResourcedEmojiComponent.js +3 -1
- package/dist/es2019/components/common/TonePreviewButton.js +3 -2
- package/dist/es2019/components/i18n.js +10 -0
- package/dist/es2019/components/picker/EmojiPickerComponent.js +26 -14
- package/dist/es2019/components/picker/EmojiPickerList.js +32 -14
- package/dist/es2019/components/picker/VirtualList.js +4 -5
- package/dist/es2019/util/analytics/analytics.js +1 -1
- package/dist/es2019/util/hidden-emojis.js +25 -0
- package/dist/es2019/util/productivity-colors.js +37 -0
- package/dist/esm/components/common/Emoji.js +142 -6
- package/dist/esm/components/common/EmojiActions.compiled.css +8 -0
- package/dist/esm/components/common/EmojiActions.js +70 -4
- package/dist/esm/components/common/Popup.js +20 -5
- package/dist/esm/components/common/ProductivityColorSelector.compiled.css +59 -0
- package/dist/esm/components/common/ProductivityColorSelector.js +103 -0
- package/dist/esm/components/common/ResourcedEmojiComponent.js +4 -1
- package/dist/esm/components/common/TonePreviewButton.js +4 -2
- package/dist/esm/components/i18n.js +10 -0
- package/dist/esm/components/picker/EmojiPickerComponent.js +51 -36
- package/dist/esm/components/picker/EmojiPickerList.js +36 -14
- package/dist/esm/components/picker/VirtualList.js +4 -5
- package/dist/esm/util/analytics/analytics.js +1 -1
- package/dist/esm/util/hidden-emojis.js +27 -0
- package/dist/esm/util/productivity-colors.js +45 -0
- package/dist/types/components/common/Emoji.d.ts +5 -0
- package/dist/types/components/common/EmojiActions.d.ts +6 -0
- package/dist/types/components/common/Popup.d.ts +1 -0
- package/dist/types/components/common/ProductivityColorSelector.d.ts +17 -0
- package/dist/types/components/common/ResourcedEmojiComponent.d.ts +6 -1
- package/dist/types/components/common/TonePreviewButton.d.ts +1 -0
- package/dist/types/components/i18n.d.ts +10 -0
- package/dist/types/components/picker/EmojiPickerList.d.ts +3 -0
- package/dist/types/types.d.ts +7 -0
- package/dist/types/util/hidden-emojis.d.ts +3 -0
- package/dist/types/util/productivity-colors.d.ts +8 -0
- package/package.json +3 -2
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import _extends from "@babel/runtime/helpers/extends";
|
|
3
3
|
import "./Emoji.compiled.css";
|
|
4
4
|
import { ax, ix } from "@compiled/react/runtime";
|
|
5
|
-
import React, { useEffect, useCallback, useContext, useMemo, forwardRef } from 'react';
|
|
5
|
+
import React, { useEffect, useCallback, useContext, useMemo, useState, forwardRef } from 'react';
|
|
6
6
|
import { IntlContext } from 'react-intl';
|
|
7
7
|
import Tooltip from '@atlaskit/tooltip';
|
|
8
8
|
import { shouldUseAltRepresentation } from '../../api/EmojiUtils';
|
|
@@ -21,6 +21,8 @@ import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
|
21
21
|
import { getDocument } from '@atlaskit/browser-apis';
|
|
22
22
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
23
23
|
import { messages } from '../i18n';
|
|
24
|
+
import { isSSR } from '../../util/is-ssr';
|
|
25
|
+
import EmojiPlaceholder from './EmojiPlaceholder';
|
|
24
26
|
const emojiSpriteContainer = null;
|
|
25
27
|
const emojiImageContainer = null;
|
|
26
28
|
|
|
@@ -151,17 +153,123 @@ export const SpriteEmoji = props => {
|
|
|
151
153
|
}))
|
|
152
154
|
);
|
|
153
155
|
};
|
|
154
|
-
|
|
156
|
+
const unicodeEmojiCanvasSize = 128;
|
|
157
|
+
const unicodeEmojiCanvasFontSize = 124;
|
|
158
|
+
const unicodeEmojiCanvasTopPadding = 8;
|
|
159
|
+
const renderUnicodeEmojiToImagePath = async unicodeEmoji => {
|
|
160
|
+
const OffscreenCanvasCtor = globalThis['OffscreenCanvas'];
|
|
161
|
+
if (isSSR() || !OffscreenCanvasCtor || typeof URL === 'undefined') {
|
|
162
|
+
return undefined;
|
|
163
|
+
}
|
|
164
|
+
const canvas = new OffscreenCanvasCtor(unicodeEmojiCanvasSize, unicodeEmojiCanvasSize);
|
|
165
|
+
const context = canvas.getContext('2d');
|
|
166
|
+
if (!context) {
|
|
167
|
+
return undefined;
|
|
168
|
+
}
|
|
169
|
+
context.clearRect(0, 0, unicodeEmojiCanvasSize, unicodeEmojiCanvasSize);
|
|
170
|
+
context.textAlign = 'center';
|
|
171
|
+
context.textBaseline = 'middle';
|
|
172
|
+
context.font = `${unicodeEmojiCanvasFontSize}px sans-serif`;
|
|
173
|
+
context.fillText(unicodeEmoji, unicodeEmojiCanvasSize / 2, unicodeEmojiCanvasSize / 2 + unicodeEmojiCanvasTopPadding);
|
|
174
|
+
const blob = await canvas.convertToBlob({
|
|
175
|
+
type: 'image/png'
|
|
176
|
+
});
|
|
177
|
+
return URL.createObjectURL(blob);
|
|
178
|
+
};
|
|
179
|
+
const useUnicodeEmojiImage = unicodeEmoji => {
|
|
180
|
+
const [state, setState] = useState({
|
|
181
|
+
status: 'loading'
|
|
182
|
+
});
|
|
183
|
+
useEffect(() => {
|
|
184
|
+
let cancelled = false;
|
|
185
|
+
let imagePathToRevoke;
|
|
186
|
+
setState({
|
|
187
|
+
status: 'loading',
|
|
188
|
+
unicodeEmoji
|
|
189
|
+
});
|
|
190
|
+
void renderUnicodeEmojiToImagePath(unicodeEmoji).then(imagePath => {
|
|
191
|
+
if (cancelled) {
|
|
192
|
+
if (imagePath) {
|
|
193
|
+
URL.revokeObjectURL(imagePath);
|
|
194
|
+
}
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
imagePathToRevoke = imagePath;
|
|
198
|
+
setState(imagePath ? {
|
|
199
|
+
status: 'ready',
|
|
200
|
+
unicodeEmoji,
|
|
201
|
+
imagePath
|
|
202
|
+
} : {
|
|
203
|
+
status: 'failed',
|
|
204
|
+
unicodeEmoji
|
|
205
|
+
});
|
|
206
|
+
}).catch(() => {
|
|
207
|
+
if (!cancelled) {
|
|
208
|
+
setState({
|
|
209
|
+
status: 'failed',
|
|
210
|
+
unicodeEmoji
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
return () => {
|
|
215
|
+
cancelled = true;
|
|
216
|
+
if (imagePathToRevoke) {
|
|
217
|
+
URL.revokeObjectURL(imagePathToRevoke);
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
}, [unicodeEmoji]);
|
|
221
|
+
return state;
|
|
222
|
+
};
|
|
223
|
+
const UnicodeEmojiImage = props => {
|
|
155
224
|
const {
|
|
156
225
|
emoji,
|
|
157
226
|
fitToHeight,
|
|
227
|
+
showTooltip
|
|
228
|
+
} = props;
|
|
229
|
+
const emojiText = emoji.representation.unicodeEmoji;
|
|
230
|
+
const unicodeEmojiImage = useUnicodeEmojiImage(emojiText);
|
|
231
|
+
const hasCurrentEmojiImage = unicodeEmojiImage.unicodeEmoji === emojiText;
|
|
232
|
+
if (isSSR() || !hasCurrentEmojiImage || unicodeEmojiImage.status === 'loading') {
|
|
233
|
+
return /*#__PURE__*/React.createElement(EmojiPlaceholder, {
|
|
234
|
+
shortName: emoji.shortName,
|
|
235
|
+
showTooltip: showTooltip,
|
|
236
|
+
size: fitToHeight,
|
|
237
|
+
loading: true
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
if (unicodeEmojiImage.status === 'ready') {
|
|
241
|
+
return /*#__PURE__*/React.createElement(ImageEmoji, _extends({}, props, {
|
|
242
|
+
emoji: {
|
|
243
|
+
...emoji,
|
|
244
|
+
representation: {
|
|
245
|
+
imagePath: unicodeEmojiImage.imagePath,
|
|
246
|
+
width: unicodeEmojiCanvasSize,
|
|
247
|
+
height: unicodeEmojiCanvasSize
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}));
|
|
251
|
+
}
|
|
252
|
+
return /*#__PURE__*/React.createElement(EmojiPlaceholder, {
|
|
253
|
+
shortName: emoji.shortName,
|
|
254
|
+
showTooltip: showTooltip,
|
|
255
|
+
size: fitToHeight
|
|
256
|
+
});
|
|
257
|
+
};
|
|
258
|
+
export const UnicodeEmoji = props => {
|
|
259
|
+
var _props$fitToHeight;
|
|
260
|
+
const {
|
|
261
|
+
emoji,
|
|
158
262
|
selected,
|
|
159
263
|
selectOnHover,
|
|
160
|
-
className
|
|
264
|
+
className,
|
|
265
|
+
renderUnicodeEmojiAsImage = true
|
|
161
266
|
} = props;
|
|
267
|
+
if (renderUnicodeEmojiAsImage) {
|
|
268
|
+
return /*#__PURE__*/React.createElement(UnicodeEmojiImage, props);
|
|
269
|
+
}
|
|
162
270
|
const classes = `${emojiNodeStyles} ${selected ? commonSelectedStyles : ''} ${selectOnHover ? selectOnHoverStyles : ''} ${className ? className : ''}`;
|
|
163
271
|
const emojiText = emoji.representation.unicodeEmoji;
|
|
164
|
-
const size = fitToHeight !== null && fitToHeight !== void 0 ? fitToHeight : defaultEmojiHeight;
|
|
272
|
+
const size = (_props$fitToHeight = props.fitToHeight) !== null && _props$fitToHeight !== void 0 ? _props$fitToHeight : defaultEmojiHeight;
|
|
165
273
|
const style = {
|
|
166
274
|
display: 'inline-block',
|
|
167
275
|
// eslint-disable-next-line @atlaskit/design-system/use-tokens-typography
|
|
@@ -334,6 +442,7 @@ export const ImageEmoji = props => {
|
|
|
334
442
|
);
|
|
335
443
|
};
|
|
336
444
|
export const EmojiNodeWrapper = /*#__PURE__*/forwardRef((props, ref) => {
|
|
445
|
+
var _emoji$name;
|
|
337
446
|
const {
|
|
338
447
|
emoji,
|
|
339
448
|
fitToHeight,
|
|
@@ -355,11 +464,12 @@ export const EmojiNodeWrapper = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
355
464
|
children,
|
|
356
465
|
type,
|
|
357
466
|
editorEmoji,
|
|
467
|
+
renderUnicodeEmojiAsImage,
|
|
358
468
|
...other
|
|
359
469
|
} = props;
|
|
360
470
|
const intl = useContext(IntlContext);
|
|
361
471
|
const ariaLabel = intl && fg('platform_change_emoji_button_label') ? intl.formatMessage(messages.changeEmojiShortnameButtonLabel, {
|
|
362
|
-
shortName: emoji.shortName
|
|
472
|
+
shortName: (_emoji$name = emoji.name) !== null && _emoji$name !== void 0 ? _emoji$name : emoji.shortName
|
|
363
473
|
}) : editorEmoji ? undefined : emoji.shortName;
|
|
364
474
|
return /*#__PURE__*/React.createElement("span", _extends({
|
|
365
475
|
role: editorEmoji ? undefined : shouldBeInteractive ? 'button' : ariaLabel ? 'img' : 'presentation',
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
|
|
2
|
+
._19itia51{border:var(--ds-border-width,1px) solid var(--ds-border,#0b120e24)}
|
|
3
|
+
._2rkofajl{border-radius:var(--ds-radius-small,3px)}
|
|
2
4
|
._n7zl1uh4{border-bottom:var(--ds-border-width-selected,2px) solid var(--ds-border,#0b120e24)}._16jlidpf{flex-grow:0}
|
|
3
5
|
._16jlkb7n{flex-grow:1}
|
|
6
|
+
._16qs130s{box-shadow:var(--ds-shadow-overlay,0 8px 9pt #1e1f2126,0 0 1px #1e1f214f)}
|
|
4
7
|
._16qsjgpa{box-shadow:0 1px 1px 0 var(--ds-border,#0b120e24)}
|
|
5
8
|
._18u019bv{margin-left:10px}
|
|
6
9
|
._18u0r5cr{margin-left:var(--ds-space-negative-050,-4px)}
|
|
10
|
+
._19bv12x7{padding-left:var(--ds-space-075,6px)}
|
|
7
11
|
._19bvidpf{padding-left:0}
|
|
8
12
|
._1bahesu3{justify-content:flex-end}
|
|
9
13
|
._1e0c1txw{display:flex}
|
|
@@ -12,10 +16,14 @@
|
|
|
12
16
|
._1wpz1h6o{align-self:center}
|
|
13
17
|
._2hwx1i6y{margin-right:var(--ds-space-negative-025,-2px)}
|
|
14
18
|
._4cvr1h6o{align-items:center}
|
|
19
|
+
._bfhk1bhr{background-color:var(--ds-surface-overlay,#fff)}
|
|
20
|
+
._ca0q12x7{padding-top:var(--ds-space-075,6px)}
|
|
15
21
|
._ca0q1skh{padding-top:11px}
|
|
16
22
|
._i0dl1wug{flex-basis:auto}
|
|
17
23
|
._i0dlf1ug{flex-basis:0%}
|
|
24
|
+
._n3td12x7{padding-bottom:var(--ds-space-075,6px)}
|
|
18
25
|
._n3td1crf{padding-bottom:9pt}
|
|
19
26
|
._otyr19bv{margin-bottom:10px}
|
|
20
27
|
._p12f3sup{max-width:285px}
|
|
28
|
+
._u5f312x7{padding-right:var(--ds-space-075,6px)}
|
|
21
29
|
._u5f319bv{padding-right:10px}
|
|
@@ -3,13 +3,15 @@ import _extends from "@babel/runtime/helpers/extends";
|
|
|
3
3
|
import "./EmojiActions.compiled.css";
|
|
4
4
|
import * as React from 'react';
|
|
5
5
|
import { ax, ix } from "@compiled/react/runtime";
|
|
6
|
-
import { Fragment, useState, useRef, memo, useLayoutEffect, useCallback } from 'react';
|
|
6
|
+
import { Fragment, useState, useRef, memo, useLayoutEffect, useCallback, useEffect } from 'react';
|
|
7
7
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
8
8
|
import { FormattedMessage, injectIntl } from 'react-intl';
|
|
9
9
|
import EmojiDeletePreview from './EmojiDeletePreview';
|
|
10
10
|
import EmojiUploadPicker from './EmojiUploadPicker';
|
|
11
11
|
import TonePreviewButton from './TonePreviewButton';
|
|
12
12
|
import ToneSelector from './ToneSelector';
|
|
13
|
+
import ProductivityColorSelector, { productivityColorSelectorId } from './ProductivityColorSelector';
|
|
14
|
+
import Popup from './Popup';
|
|
13
15
|
import { EmojiPickerListSearch } from '../picker/EmojiPickerListSearch';
|
|
14
16
|
import { messages } from '../i18n';
|
|
15
17
|
import AkButton from '@atlaskit/button/standard-button';
|
|
@@ -26,6 +28,7 @@ const addCustomEmoji = null;
|
|
|
26
28
|
const addCustomEmojiButton = null;
|
|
27
29
|
const emojiActionsWrapper = null;
|
|
28
30
|
const emojiToneSelectorContainer = null;
|
|
31
|
+
const productivityColorPopup = null;
|
|
29
32
|
const previewFooter = null;
|
|
30
33
|
const previewFooterNew = null;
|
|
31
34
|
export const emojiActionsTestId = 'emoji-actions';
|
|
@@ -68,10 +71,16 @@ export const AddOwnEmoji = props => {
|
|
|
68
71
|
};
|
|
69
72
|
const TonesWrapper = props => {
|
|
70
73
|
const {
|
|
74
|
+
activeCategoryId,
|
|
75
|
+
onProductivityColorSelected,
|
|
76
|
+
productivityColorPreviewEmojis,
|
|
77
|
+
selectedProductivityColor,
|
|
71
78
|
toneEmoji,
|
|
72
79
|
selectedTone = DEFAULT_TONE,
|
|
73
80
|
intl,
|
|
81
|
+
onToneClose,
|
|
74
82
|
onToneOpen,
|
|
83
|
+
onToneToggle,
|
|
75
84
|
showToneSelector
|
|
76
85
|
} = props;
|
|
77
86
|
const {
|
|
@@ -102,6 +111,41 @@ const TonesWrapper = props => {
|
|
|
102
111
|
onToneSelected(toneValue);
|
|
103
112
|
setFocusTonePreviewButton(true);
|
|
104
113
|
}, [props]);
|
|
114
|
+
const onProductivityColorSelectedHandler = useCallback(color => {
|
|
115
|
+
onProductivityColorSelected === null || onProductivityColorSelected === void 0 ? void 0 : onProductivityColorSelected(color);
|
|
116
|
+
onToneClose();
|
|
117
|
+
setFocusTonePreviewButton(true);
|
|
118
|
+
}, [onProductivityColorSelected, onToneClose]);
|
|
119
|
+
const shouldShowProductivityColorSelector = !!(activeCategoryId === 'ATLASSIAN' && productivityColorPreviewEmojis && selectedProductivityColor && onProductivityColorSelected && FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false));
|
|
120
|
+
if (shouldShowProductivityColorSelector) {
|
|
121
|
+
const previewEmoji = (productivityColorPreviewEmojis === null || productivityColorPreviewEmojis === void 0 ? void 0 : productivityColorPreviewEmojis[selectedProductivityColor]) || Object.values(productivityColorPreviewEmojis || {})[0];
|
|
122
|
+
if (!previewEmoji) {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
126
|
+
className: ax(["_16jlkb7n _1o9zkb7n _i0dlf1ug _ca0q1skh _u5f319bv _n3td1crf _19bvidpf _1e0c1txw _1bahesu3"])
|
|
127
|
+
}, showToneSelector && tonePreviewButtonRef.current && /*#__PURE__*/React.createElement(Popup, {
|
|
128
|
+
target: tonePreviewButtonRef.current,
|
|
129
|
+
relativePosition: "below",
|
|
130
|
+
horizontalAlign: "end-to-start",
|
|
131
|
+
offsetY: 4,
|
|
132
|
+
zIndex: 510
|
|
133
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
134
|
+
className: ax(["_19itia51 _2rkofajl _bfhk1bhr _16qs130s _ca0q12x7 _u5f312x7 _n3td12x7 _19bv12x7"])
|
|
135
|
+
}, /*#__PURE__*/React.createElement(ProductivityColorSelector, {
|
|
136
|
+
colorPreviewEmojis: productivityColorPreviewEmojis,
|
|
137
|
+
selectedColor: selectedProductivityColor,
|
|
138
|
+
onColorSelected: onProductivityColorSelectedHandler
|
|
139
|
+
}))), /*#__PURE__*/React.createElement(TonePreviewButton, {
|
|
140
|
+
ref: tonePreviewButtonRef,
|
|
141
|
+
ariaControls: productivityColorSelectorId,
|
|
142
|
+
ariaExpanded: showToneSelector,
|
|
143
|
+
emoji: previewEmoji,
|
|
144
|
+
selectOnHover: true,
|
|
145
|
+
onSelected: onToneToggle,
|
|
146
|
+
ariaLabelText: formatMessage(messages.emojiSelectColorButtonAriaLabelText)
|
|
147
|
+
}));
|
|
148
|
+
}
|
|
105
149
|
if (!toneEmoji) {
|
|
106
150
|
return null;
|
|
107
151
|
}
|
|
@@ -148,8 +192,13 @@ export const EmojiActions = props => {
|
|
|
148
192
|
resultsCount = 0
|
|
149
193
|
} = props;
|
|
150
194
|
const [showToneSelector, setShowToneSelector] = useState(false);
|
|
195
|
+
const wasProductivityColorSelectorOpen = useRef(false);
|
|
196
|
+
const shouldUseProductivityColorControl = !!(props.activeCategoryId === 'ATLASSIAN' && props.productivityColorPreviewEmojis && props.selectedProductivityColor && props.onProductivityColorSelected && FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false));
|
|
151
197
|
const onToneOpenHandler = useCallback(() => setShowToneSelector(true), []);
|
|
152
198
|
const onToneCloseHandler = useCallback(() => setShowToneSelector(false), []);
|
|
199
|
+
const onToneToggleHandler = useCallback(() => {
|
|
200
|
+
setShowToneSelector(isOpen => !isOpen);
|
|
201
|
+
}, []);
|
|
153
202
|
const onToneSelectedHandler = useCallback(toneValue => {
|
|
154
203
|
setShowToneSelector(false);
|
|
155
204
|
if (onToneSelected) {
|
|
@@ -157,11 +206,24 @@ export const EmojiActions = props => {
|
|
|
157
206
|
}
|
|
158
207
|
}, [onToneSelected]);
|
|
159
208
|
const onMouseLeaveHandler = useCallback(() => {
|
|
209
|
+
if (shouldUseProductivityColorControl) {
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
160
212
|
if (showToneSelector && onToneSelectorCancelled) {
|
|
161
213
|
onToneSelectorCancelled();
|
|
162
214
|
}
|
|
163
215
|
setShowToneSelector(false);
|
|
164
|
-
}, [showToneSelector, onToneSelectorCancelled]);
|
|
216
|
+
}, [shouldUseProductivityColorControl, showToneSelector, onToneSelectorCancelled]);
|
|
217
|
+
useEffect(() => {
|
|
218
|
+
if (shouldUseProductivityColorControl && showToneSelector) {
|
|
219
|
+
wasProductivityColorSelectorOpen.current = true;
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
if (!shouldUseProductivityColorControl && wasProductivityColorSelectorOpen.current) {
|
|
223
|
+
setShowToneSelector(false);
|
|
224
|
+
wasProductivityColorSelectorOpen.current = false;
|
|
225
|
+
}
|
|
226
|
+
}, [shouldUseProductivityColorControl, showToneSelector]);
|
|
165
227
|
if (uploading) {
|
|
166
228
|
return FeatureGates.getExperimentValue('platform_teamoji_26_refresh_emoji_picker', 'isEnabled', false) ? /*#__PURE__*/React.createElement("div", {
|
|
167
229
|
className: ax(["_16jlidpf _1o9zidpf _i0dl1wug"])
|
|
@@ -207,11 +269,12 @@ export const EmojiActions = props => {
|
|
|
207
269
|
onChange: onChange,
|
|
208
270
|
query: query,
|
|
209
271
|
resultsCount: resultsCount,
|
|
210
|
-
isVisible: !showToneSelector
|
|
272
|
+
isVisible: !showToneSelector || shouldUseProductivityColorControl
|
|
211
273
|
}), /*#__PURE__*/React.createElement(TonesWrapper, _extends({}, props, {
|
|
212
274
|
onToneOpen: onToneOpenHandler,
|
|
213
275
|
onToneClose: onToneCloseHandler,
|
|
214
276
|
onToneSelected: onToneSelectedHandler,
|
|
277
|
+
onToneToggle: onToneToggleHandler,
|
|
215
278
|
showToneSelector: showToneSelector
|
|
216
279
|
})))) : /*#__PURE__*/React.createElement("div", {
|
|
217
280
|
"data-testid": emojiActionsTestId,
|
|
@@ -229,6 +292,7 @@ export const EmojiActions = props => {
|
|
|
229
292
|
onToneOpen: onToneOpenHandler,
|
|
230
293
|
onToneClose: onToneCloseHandler,
|
|
231
294
|
onToneSelected: onToneSelectedHandler,
|
|
295
|
+
onToneToggle: onToneToggleHandler,
|
|
232
296
|
showToneSelector: showToneSelector
|
|
233
297
|
}))), /*#__PURE__*/React.createElement(AddOwnEmoji, props));
|
|
234
298
|
};
|
|
@@ -10,6 +10,7 @@ const getTargetNode = target => {
|
|
|
10
10
|
const Popup = props => {
|
|
11
11
|
const {
|
|
12
12
|
relativePosition = 'auto',
|
|
13
|
+
horizontalAlign = 'start',
|
|
13
14
|
offsetX = 0,
|
|
14
15
|
offsetY = 0,
|
|
15
16
|
zIndex = 9,
|
|
@@ -18,17 +19,27 @@ const Popup = props => {
|
|
|
18
19
|
} = props;
|
|
19
20
|
const popup = useRef();
|
|
20
21
|
const [debounced, setDebounced] = useState(null);
|
|
22
|
+
const getLeftPosition = useCallback(box => {
|
|
23
|
+
if (horizontalAlign === 'end-to-start') {
|
|
24
|
+
return box.left - 152;
|
|
25
|
+
}
|
|
26
|
+
if (horizontalAlign === 'end') {
|
|
27
|
+
var _popup$current;
|
|
28
|
+
return box.right - (((_popup$current = popup.current) === null || _popup$current === void 0 ? void 0 : _popup$current.offsetWidth) || 0) + (offsetX || 0);
|
|
29
|
+
}
|
|
30
|
+
return box.left + (offsetX || 0);
|
|
31
|
+
}, [horizontalAlign, offsetX]);
|
|
21
32
|
const applyBelowPosition = useCallback(() => {
|
|
22
33
|
const targetNode = getTargetNode(target);
|
|
23
34
|
if (targetNode && popup.current) {
|
|
24
35
|
const box = targetNode.getBoundingClientRect();
|
|
25
36
|
const top = box.bottom + (offsetY || 0);
|
|
26
|
-
const left = box
|
|
37
|
+
const left = getLeftPosition(box);
|
|
27
38
|
popup.current.style.top = `${top}px`;
|
|
28
39
|
popup.current.style.bottom = '';
|
|
29
40
|
popup.current.style.left = `${left}px`;
|
|
30
41
|
}
|
|
31
|
-
}, [
|
|
42
|
+
}, [getLeftPosition, offsetY, target]);
|
|
32
43
|
const applyAbovePosition = useCallback(() => {
|
|
33
44
|
if (typeof window === 'undefined') {
|
|
34
45
|
return;
|
|
@@ -37,12 +48,12 @@ const Popup = props => {
|
|
|
37
48
|
if (targetNode && popup.current) {
|
|
38
49
|
const box = targetNode.getBoundingClientRect();
|
|
39
50
|
const bottom = window.innerHeight - box.top + (offsetY || 0);
|
|
40
|
-
const left = box
|
|
51
|
+
const left = getLeftPosition(box);
|
|
41
52
|
popup.current.style.top = '';
|
|
42
53
|
popup.current.style.bottom = `${bottom}px`;
|
|
43
54
|
popup.current.style.left = `${left}px`;
|
|
44
55
|
}
|
|
45
|
-
}, [
|
|
56
|
+
}, [getLeftPosition, offsetY, target]);
|
|
46
57
|
const applyAbsolutePosition = useCallback(() => {
|
|
47
58
|
if (typeof window === 'undefined') {
|
|
48
59
|
return;
|
|
@@ -97,6 +108,9 @@ const Popup = props => {
|
|
|
97
108
|
}
|
|
98
109
|
applyAbsolutePosition();
|
|
99
110
|
renderPopup();
|
|
111
|
+
if (horizontalAlign !== 'start') {
|
|
112
|
+
applyAbsolutePosition();
|
|
113
|
+
}
|
|
100
114
|
return () => {
|
|
101
115
|
if (typeof window === 'undefined') {
|
|
102
116
|
return;
|
|
@@ -107,7 +121,7 @@ const Popup = props => {
|
|
|
107
121
|
document.body.removeChild(popup.current);
|
|
108
122
|
}
|
|
109
123
|
};
|
|
110
|
-
}, [applyAbsolutePosition, handleResize, renderPopup]);
|
|
124
|
+
}, [applyAbsolutePosition, handleResize, horizontalAlign, renderPopup]);
|
|
111
125
|
return /*#__PURE__*/React.createElement("div", null);
|
|
112
126
|
};
|
|
113
127
|
export default Popup;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
|
|
2
|
+
._1355fajl input+span{border-radius:var(--ds-radius-small,3px)}
|
|
3
|
+
._19itidpf{border:0}
|
|
4
|
+
._zulp1b66{gap:var(--ds-space-050,4px)}._1030zwfg input+span{height:2pc}
|
|
5
|
+
._12hvze3t input{margin-right:var(--ds-space-0,0)}
|
|
6
|
+
._12ultlke input{cursor:pointer}
|
|
7
|
+
._13yj1o36 input:focus+span{outline-width:medium}
|
|
8
|
+
._17muzwfg label{height:2pc}
|
|
9
|
+
._18m915vq{overflow-y:hidden}
|
|
10
|
+
._18u0ze3t{margin-left:var(--ds-space-0,0)}
|
|
11
|
+
._19bvidpf{padding-left:0}
|
|
12
|
+
._19pkze3t{margin-top:var(--ds-space-0,0)}
|
|
13
|
+
._1bah1h6o{justify-content:center}
|
|
14
|
+
._1bsbt94y{width:1px}
|
|
15
|
+
._1bsbzwfg{width:2pc}
|
|
16
|
+
._1e0c11p5{display:grid}
|
|
17
|
+
._1e0c1txw{display:flex}
|
|
18
|
+
._1e7sidpf input{opacity:0}
|
|
19
|
+
._1eq11h6o label{align-items:center}
|
|
20
|
+
._1nn0kb7n input{z-index:1}
|
|
21
|
+
._1p1fzwfg label{width:2pc}
|
|
22
|
+
._1pi91y54 input:focus+span{box-shadow:0 0 0 2px var(--ds-border-focused,#4688ec)}
|
|
23
|
+
._1reo15vq{overflow-x:hidden}
|
|
24
|
+
._1rgfze3t input{margin-left:var(--ds-space-0,0)}
|
|
25
|
+
._1rgq13zc input:focus+span{transition-duration:0s,.2s}
|
|
26
|
+
._1ul9idpf{min-width:0}
|
|
27
|
+
._1vzltlke label{cursor:pointer}
|
|
28
|
+
._1wqq1h6o label{justify-content:center}
|
|
29
|
+
._2hwxze3t{margin-right:var(--ds-space-0,0)}
|
|
30
|
+
._2x4gze3t input{margin-top:var(--ds-space-0,0)}
|
|
31
|
+
._2z051y6t{grid-template-rows:repeat(2,2pc)}
|
|
32
|
+
._4cvr1h6o{align-items:center}
|
|
33
|
+
._4t3it94y{height:1px}
|
|
34
|
+
._4t3izwfg{height:2pc}
|
|
35
|
+
._5hv9zwfg input{width:2pc}
|
|
36
|
+
._6rawzwfg input+span{width:2pc}
|
|
37
|
+
._6vsr1h6o input+span{justify-content:center}
|
|
38
|
+
._7kzvidpf input+span{padding-inline-end:0}
|
|
39
|
+
._8qdiidpf input+span{padding-block-start:0}
|
|
40
|
+
._ca0qidpf{padding-top:0}
|
|
41
|
+
._ecyuidpf input+span{padding-block-end:0}
|
|
42
|
+
._ev8ridpf input+span{padding-inline-start:0}
|
|
43
|
+
._hxs6glyw input:focus+span{outline-style:none}
|
|
44
|
+
._khufstnw input{position:absolute}
|
|
45
|
+
._kqswh2mm{position:relative}
|
|
46
|
+
._kqswstnw{position:absolute}
|
|
47
|
+
._n3tdidpf{padding-bottom:0}
|
|
48
|
+
._ngzz1txw input+span{display:flex}
|
|
49
|
+
._o5721q9c{white-space:nowrap}
|
|
50
|
+
._ogtohxbz{clip:rect(0 0 0 0)}
|
|
51
|
+
._otyrze3t{margin-bottom:var(--ds-space-0,0)}
|
|
52
|
+
._pytkzwfg input{height:2pc}
|
|
53
|
+
._smb7plhp input:hover+span{background-color:var(--ds-background-neutral-hovered,#0b120e24)}
|
|
54
|
+
._soq51h6o input+span{align-items:center}
|
|
55
|
+
._szw2w5lj input:checked+span{box-shadow:0 0 0 2px var(--ds-border-selected,#1868db)}
|
|
56
|
+
._tnsm1r31 input:focus+span{outline-color:currentColor}
|
|
57
|
+
._u5f3idpf{padding-right:0}
|
|
58
|
+
._x5bdze3t input{margin-bottom:var(--ds-space-0,0)}
|
|
59
|
+
._yv0e1bbt{grid-template-columns:repeat(5,2pc)}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/* ProductivityColorSelector.tsx generated by @compiled/babel-plugin v0.39.1 */
|
|
2
|
+
import "./ProductivityColorSelector.compiled.css";
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { ax, ix } from "@compiled/react/runtime";
|
|
5
|
+
import { memo, useContext, useRef } from 'react';
|
|
6
|
+
import { IntlContext } from 'react-intl';
|
|
7
|
+
import { Radio } from '@atlaskit/radio';
|
|
8
|
+
import { productivityColors } from '../../util/productivity-colors';
|
|
9
|
+
import { messages } from '../i18n';
|
|
10
|
+
import Emoji from './Emoji';
|
|
11
|
+
export const productivityColorSelectorTestId = 'productivity-color-selector';
|
|
12
|
+
export const productivityColorSelectorId = 'emoji-picker-productivity-color-selector';
|
|
13
|
+
const selectorGrid = null;
|
|
14
|
+
const visuallyHiddenLegend = null;
|
|
15
|
+
const colorOption = null;
|
|
16
|
+
const colorOptionEmoji = null;
|
|
17
|
+
const getColorLabel = color => `${color.charAt(0).toUpperCase()}${color.slice(1)} productivity emoji colour`;
|
|
18
|
+
export const ProductivityColorSelector = ({
|
|
19
|
+
colorPreviewEmojis,
|
|
20
|
+
onColorSelected,
|
|
21
|
+
selectedColor
|
|
22
|
+
}) => {
|
|
23
|
+
const intl = useContext(IntlContext);
|
|
24
|
+
const radioRefs = useRef([]);
|
|
25
|
+
const hasFocusedSelectedColor = useRef(false);
|
|
26
|
+
const availableColors = productivityColors.filter(color => colorPreviewEmojis[color]);
|
|
27
|
+
const colorSelectorAriaLabel = intl ? intl.formatMessage(messages.emojiSelectColorListAriaLabelText) : messages.emojiSelectColorListAriaLabelText.defaultMessage;
|
|
28
|
+
if (!availableColors.length) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
const onArrowKey = (currentIndex, direction) => {
|
|
32
|
+
var _radioRefs$current$ne;
|
|
33
|
+
const nextIndex = (currentIndex + direction + availableColors.length) % availableColors.length;
|
|
34
|
+
(_radioRefs$current$ne = radioRefs.current[nextIndex]) === null || _radioRefs$current$ne === void 0 ? void 0 : _radioRefs$current$ne.focus();
|
|
35
|
+
};
|
|
36
|
+
const stopPickerDismissal = event => {
|
|
37
|
+
event.stopPropagation();
|
|
38
|
+
};
|
|
39
|
+
return /*#__PURE__*/React.createElement("fieldset", {
|
|
40
|
+
id: productivityColorSelectorId,
|
|
41
|
+
"data-testid": productivityColorSelectorTestId,
|
|
42
|
+
className: ax(["_19itidpf _zulp1b66 _ca0qidpf _u5f3idpf _n3tdidpf _19bvidpf _1e0c11p5 _yv0e1bbt _2z051y6t _19pkze3t _2hwxze3t _otyrze3t _18u0ze3t _1ul9idpf"])
|
|
43
|
+
}, /*#__PURE__*/React.createElement("legend", {
|
|
44
|
+
className: ax(["_19itidpf _1reo15vq _18m915vq _ca0qidpf _u5f3idpf _n3tdidpf _19bvidpf _ogtohxbz _4t3it94y _kqswstnw _o5721q9c _1bsbt94y"])
|
|
45
|
+
}, colorSelectorAriaLabel), availableColors.map((color, index) => {
|
|
46
|
+
const emoji = colorPreviewEmojis[color];
|
|
47
|
+
if (!emoji) {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
const handleKeyDown = event => {
|
|
51
|
+
if (event.key === 'ArrowLeft' || event.key === 'ArrowUp') {
|
|
52
|
+
event.preventDefault();
|
|
53
|
+
onArrowKey(index, -1);
|
|
54
|
+
}
|
|
55
|
+
if (event.key === 'ArrowRight' || event.key === 'ArrowDown') {
|
|
56
|
+
event.preventDefault();
|
|
57
|
+
onArrowKey(index, 1);
|
|
58
|
+
}
|
|
59
|
+
if (event.key === 'Enter') {
|
|
60
|
+
event.preventDefault();
|
|
61
|
+
onColorSelected(color);
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
65
|
+
key: color,
|
|
66
|
+
className: ax(["_4t3izwfg _kqswh2mm _1bsbzwfg _1355fajl _soq51h6o _ngzz1txw _1030zwfg _6vsr1h6o _ecyuidpf _8qdiidpf _7kzvidpf _ev8ridpf _6rawzwfg _tnsm1r31 _hxs6glyw _13yj1o36 _1pi91y54 _1rgq13zc _1eq11h6o _1vzltlke _17muzwfg _1wqq1h6o _1p1fzwfg _12ultlke _pytkzwfg _2x4gze3t _12hvze3t _x5bdze3t _1rgfze3t _1e7sidpf _khufstnw _5hv9zwfg _1nn0kb7n _smb7plhp _szw2w5lj"])
|
|
67
|
+
}, /*#__PURE__*/React.createElement(Radio, {
|
|
68
|
+
ref: el => {
|
|
69
|
+
radioRefs.current[index] = el;
|
|
70
|
+
if (selectedColor === color) {
|
|
71
|
+
if (el && !hasFocusedSelectedColor.current) {
|
|
72
|
+
el.focus();
|
|
73
|
+
hasFocusedSelectedColor.current = true;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
ariaLabel: getColorLabel(color),
|
|
78
|
+
name: "productivity-emoji-colour",
|
|
79
|
+
isChecked: selectedColor === color,
|
|
80
|
+
onChange: () => onColorSelected(color),
|
|
81
|
+
onClick: stopPickerDismissal,
|
|
82
|
+
onKeyDown: handleKeyDown,
|
|
83
|
+
onMouseDown: stopPickerDismissal,
|
|
84
|
+
testId: `productivity-color-${color}`,
|
|
85
|
+
value: color,
|
|
86
|
+
label: /*#__PURE__*/React.createElement("span", {
|
|
87
|
+
className: ax(["_4cvr1h6o _1e0c1txw _4t3izwfg _1bah1h6o _1bsbzwfg"])
|
|
88
|
+
}, /*#__PURE__*/React.createElement(Emoji, {
|
|
89
|
+
emoji: emoji,
|
|
90
|
+
shouldBeInteractive: false,
|
|
91
|
+
"aria-hidden": true,
|
|
92
|
+
fitToHeight: 24
|
|
93
|
+
}))
|
|
94
|
+
}));
|
|
95
|
+
}));
|
|
96
|
+
};
|
|
97
|
+
const _default_1 = /*#__PURE__*/memo(ProductivityColorSelector);
|
|
98
|
+
export default _default_1;
|
|
@@ -24,6 +24,7 @@ export const ResourcedEmojiComponent = ({
|
|
|
24
24
|
optimistic = false,
|
|
25
25
|
optimisticImageURL = undefined,
|
|
26
26
|
editorEmoji,
|
|
27
|
+
renderUnicodeEmojiAsImage = true,
|
|
27
28
|
pageTitleEmoji = false,
|
|
28
29
|
placeholderXcss,
|
|
29
30
|
onEmojiLoadSuccess,
|
|
@@ -259,7 +260,8 @@ export const ResourcedEmojiComponent = ({
|
|
|
259
260
|
showTooltip: showTooltip,
|
|
260
261
|
fitToHeight: fitToHeight,
|
|
261
262
|
autoWidth: autoWidth,
|
|
262
|
-
editorEmoji: editorEmoji
|
|
263
|
+
editorEmoji: editorEmoji,
|
|
264
|
+
renderUnicodeEmojiAsImage: renderUnicodeEmojiAsImage
|
|
263
265
|
})));
|
|
264
266
|
};
|
|
265
267
|
export default ResourcedEmojiComponent;
|
|
@@ -14,6 +14,7 @@ export const TonePreviewButton = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
14
14
|
const {
|
|
15
15
|
emoji,
|
|
16
16
|
selectOnHover,
|
|
17
|
+
ariaControls = 'emoji-picker-tone-selector',
|
|
17
18
|
ariaLabelText,
|
|
18
19
|
ariaExpanded,
|
|
19
20
|
onSelected,
|
|
@@ -25,7 +26,7 @@ export const TonePreviewButton = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
25
26
|
onClick: onSelected,
|
|
26
27
|
"aria-label": ariaLabelText,
|
|
27
28
|
"aria-expanded": ariaExpanded,
|
|
28
|
-
"aria-controls":
|
|
29
|
+
"aria-controls": ariaControls
|
|
29
30
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
|
|
30
31
|
,
|
|
31
32
|
style: {
|
|
@@ -45,7 +46,7 @@ export const TonePreviewButton = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
45
46
|
onClick: onSelected,
|
|
46
47
|
"aria-label": ariaLabelText,
|
|
47
48
|
"aria-expanded": ariaExpanded,
|
|
48
|
-
"aria-controls":
|
|
49
|
+
"aria-controls": ariaControls
|
|
49
50
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
|
|
50
51
|
,
|
|
51
52
|
style: {
|
|
@@ -65,6 +65,16 @@ export const messages = defineMessages({
|
|
|
65
65
|
defaultMessage: 'Choose your skin tone, {selectedTone} selected',
|
|
66
66
|
description: 'Message indicating the purpose of the skin tone selection button and the selected tone'
|
|
67
67
|
},
|
|
68
|
+
emojiSelectColorButtonAriaLabelText: {
|
|
69
|
+
id: 'fabric.emoji.select.color.ariaLabel',
|
|
70
|
+
defaultMessage: 'Productivity emoji color selector',
|
|
71
|
+
description: 'Message indicating the purpose of the color selection button and the selected color'
|
|
72
|
+
},
|
|
73
|
+
emojiSelectColorListAriaLabelText: {
|
|
74
|
+
id: 'fabric.emoji.select.color.list.ariaLabel',
|
|
75
|
+
defaultMessage: 'Productivity emoji colour selector',
|
|
76
|
+
description: 'Message indicating the purpose of the productivity emoji color list selector'
|
|
77
|
+
},
|
|
68
78
|
emojiSelectSkinToneListAriaLabelText: {
|
|
69
79
|
id: 'fabric.emoji.select.skin.list.ariaLabel',
|
|
70
80
|
defaultMessage: 'Skin tone selector',
|