@atlaskit/emoji 71.0.1 → 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 CHANGED
@@ -1,5 +1,13 @@
1
1
  # @atlaskit/emoji
2
2
 
3
+ ## 71.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`1abdd6ae1f4aa`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/1abdd6ae1f4aa) -
8
+ Add renderUnicodeEmojiAsImage prop to render unicode emojis as images via OffscreenCanvas, with
9
+ override to text as alternative
10
+
3
11
  ## 71.0.1
4
12
 
5
13
  ### Patch Changes
@@ -10,7 +10,9 @@ exports.default = exports.UnicodeEmoji = exports.SpriteEmoji = exports.ImageEmoj
10
10
  require("./Emoji.compiled.css");
11
11
  var _runtime = require("@compiled/react/runtime");
12
12
  var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
13
+ var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
13
14
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
15
+ var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
14
16
  var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
15
17
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
16
18
  var _react = _interopRequireWildcard(require("react"));
@@ -32,7 +34,9 @@ var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
32
34
  var _browserApis = require("@atlaskit/browser-apis");
33
35
  var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
34
36
  var _i18n = require("../i18n");
35
- var _excluded = ["emoji", "fitToHeight", "selected", "selectOnHover", "className", "showTooltip", "showDelete", "shouldBeInteractive", "tabIndex", "onSelected", "onMouseMove", "onFocus", "onDelete", "onLoadError", "onLoadSuccess", "disableLazyLoad", "autoWidth", "children", "type", "editorEmoji"];
37
+ var _isSsr = require("../../util/is-ssr");
38
+ var _EmojiPlaceholder = _interopRequireDefault(require("./EmojiPlaceholder"));
39
+ var _excluded = ["emoji", "fitToHeight", "selected", "selectOnHover", "className", "showTooltip", "showDelete", "shouldBeInteractive", "tabIndex", "onSelected", "onMouseMove", "onFocus", "onDelete", "onLoadError", "onLoadSuccess", "disableLazyLoad", "autoWidth", "children", "type", "editorEmoji", "renderUnicodeEmojiAsImage"];
36
40
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
37
41
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
38
42
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
@@ -151,15 +155,145 @@ var SpriteEmoji = exports.SpriteEmoji = function SpriteEmoji(props) {
151
155
  }))
152
156
  );
153
157
  };
154
- var UnicodeEmoji = exports.UnicodeEmoji = function UnicodeEmoji(props) {
158
+ var unicodeEmojiCanvasSize = 128;
159
+ var unicodeEmojiCanvasFontSize = 124;
160
+ var unicodeEmojiCanvasTopPadding = 8;
161
+ var renderUnicodeEmojiToImagePath = /*#__PURE__*/function () {
162
+ var _ref = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(unicodeEmoji) {
163
+ var OffscreenCanvasCtor, canvas, context, blob;
164
+ return _regenerator.default.wrap(function (_context) {
165
+ while (1) switch (_context.prev = _context.next) {
166
+ case 0:
167
+ OffscreenCanvasCtor = globalThis['OffscreenCanvas'];
168
+ if (!((0, _isSsr.isSSR)() || !OffscreenCanvasCtor || typeof URL === 'undefined')) {
169
+ _context.next = 1;
170
+ break;
171
+ }
172
+ return _context.abrupt("return", undefined);
173
+ case 1:
174
+ canvas = new OffscreenCanvasCtor(unicodeEmojiCanvasSize, unicodeEmojiCanvasSize);
175
+ context = canvas.getContext('2d');
176
+ if (context) {
177
+ _context.next = 2;
178
+ break;
179
+ }
180
+ return _context.abrupt("return", undefined);
181
+ case 2:
182
+ context.clearRect(0, 0, unicodeEmojiCanvasSize, unicodeEmojiCanvasSize);
183
+ context.textAlign = 'center';
184
+ context.textBaseline = 'middle';
185
+ context.font = "".concat(unicodeEmojiCanvasFontSize, "px sans-serif");
186
+ context.fillText(unicodeEmoji, unicodeEmojiCanvasSize / 2, unicodeEmojiCanvasSize / 2 + unicodeEmojiCanvasTopPadding);
187
+ _context.next = 3;
188
+ return canvas.convertToBlob({
189
+ type: 'image/png'
190
+ });
191
+ case 3:
192
+ blob = _context.sent;
193
+ return _context.abrupt("return", URL.createObjectURL(blob));
194
+ case 4:
195
+ case "end":
196
+ return _context.stop();
197
+ }
198
+ }, _callee);
199
+ }));
200
+ return function renderUnicodeEmojiToImagePath(_x) {
201
+ return _ref.apply(this, arguments);
202
+ };
203
+ }();
204
+ var useUnicodeEmojiImage = function useUnicodeEmojiImage(unicodeEmoji) {
205
+ var _useState = (0, _react.useState)({
206
+ status: 'loading'
207
+ }),
208
+ _useState2 = (0, _slicedToArray2.default)(_useState, 2),
209
+ state = _useState2[0],
210
+ setState = _useState2[1];
211
+ (0, _react.useEffect)(function () {
212
+ var cancelled = false;
213
+ var imagePathToRevoke;
214
+ setState({
215
+ status: 'loading',
216
+ unicodeEmoji: unicodeEmoji
217
+ });
218
+ void renderUnicodeEmojiToImagePath(unicodeEmoji).then(function (imagePath) {
219
+ if (cancelled) {
220
+ if (imagePath) {
221
+ URL.revokeObjectURL(imagePath);
222
+ }
223
+ return;
224
+ }
225
+ imagePathToRevoke = imagePath;
226
+ setState(imagePath ? {
227
+ status: 'ready',
228
+ unicodeEmoji: unicodeEmoji,
229
+ imagePath: imagePath
230
+ } : {
231
+ status: 'failed',
232
+ unicodeEmoji: unicodeEmoji
233
+ });
234
+ }).catch(function () {
235
+ if (!cancelled) {
236
+ setState({
237
+ status: 'failed',
238
+ unicodeEmoji: unicodeEmoji
239
+ });
240
+ }
241
+ });
242
+ return function () {
243
+ cancelled = true;
244
+ if (imagePathToRevoke) {
245
+ URL.revokeObjectURL(imagePathToRevoke);
246
+ }
247
+ };
248
+ }, [unicodeEmoji]);
249
+ return state;
250
+ };
251
+ var UnicodeEmojiImage = function UnicodeEmojiImage(props) {
155
252
  var emoji = props.emoji,
156
253
  fitToHeight = props.fitToHeight,
254
+ showTooltip = props.showTooltip;
255
+ var emojiText = emoji.representation.unicodeEmoji;
256
+ var unicodeEmojiImage = useUnicodeEmojiImage(emojiText);
257
+ var hasCurrentEmojiImage = unicodeEmojiImage.unicodeEmoji === emojiText;
258
+ if ((0, _isSsr.isSSR)() || !hasCurrentEmojiImage || unicodeEmojiImage.status === 'loading') {
259
+ return /*#__PURE__*/_react.default.createElement(_EmojiPlaceholder.default, {
260
+ shortName: emoji.shortName,
261
+ showTooltip: showTooltip,
262
+ size: fitToHeight,
263
+ loading: true
264
+ });
265
+ }
266
+ if (unicodeEmojiImage.status === 'ready') {
267
+ return /*#__PURE__*/_react.default.createElement(ImageEmoji, (0, _extends2.default)({}, props, {
268
+ emoji: _objectSpread(_objectSpread({}, emoji), {}, {
269
+ representation: {
270
+ imagePath: unicodeEmojiImage.imagePath,
271
+ width: unicodeEmojiCanvasSize,
272
+ height: unicodeEmojiCanvasSize
273
+ }
274
+ })
275
+ }));
276
+ }
277
+ return /*#__PURE__*/_react.default.createElement(_EmojiPlaceholder.default, {
278
+ shortName: emoji.shortName,
279
+ showTooltip: showTooltip,
280
+ size: fitToHeight
281
+ });
282
+ };
283
+ var UnicodeEmoji = exports.UnicodeEmoji = function UnicodeEmoji(props) {
284
+ var _props$fitToHeight;
285
+ var emoji = props.emoji,
157
286
  selected = props.selected,
158
287
  selectOnHover = props.selectOnHover,
159
- className = props.className;
288
+ className = props.className,
289
+ _props$renderUnicodeE = props.renderUnicodeEmojiAsImage,
290
+ renderUnicodeEmojiAsImage = _props$renderUnicodeE === void 0 ? true : _props$renderUnicodeE;
291
+ if (renderUnicodeEmojiAsImage) {
292
+ return /*#__PURE__*/_react.default.createElement(UnicodeEmojiImage, props);
293
+ }
160
294
  var classes = "".concat(_styles.emojiNodeStyles, " ").concat(selected ? _styles.commonSelectedStyles : '', " ").concat(selectOnHover ? _styles.selectOnHoverStyles : '', " ").concat(className ? className : '');
161
295
  var emojiText = emoji.representation.unicodeEmoji;
162
- var size = fitToHeight !== null && fitToHeight !== void 0 ? fitToHeight : _constants.defaultEmojiHeight;
296
+ var size = (_props$fitToHeight = props.fitToHeight) !== null && _props$fitToHeight !== void 0 ? _props$fitToHeight : _constants.defaultEmojiHeight;
163
297
  var style = {
164
298
  display: 'inline-block',
165
299
  // eslint-disable-next-line @atlaskit/design-system/use-tokens-typography
@@ -363,6 +497,7 @@ var EmojiNodeWrapper = exports.EmojiNodeWrapper = /*#__PURE__*/(0, _react.forwar
363
497
  children = props.children,
364
498
  type = props.type,
365
499
  editorEmoji = props.editorEmoji,
500
+ renderUnicodeEmojiAsImage = props.renderUnicodeEmojiAsImage,
366
501
  other = (0, _objectWithoutProperties2.default)(props, _excluded);
367
502
  var intl = (0, _react.useContext)(_reactIntl.IntlContext);
368
503
  var ariaLabel = intl && (0, _platformFeatureFlags.fg)('platform_change_emoji_button_label') ? intl.formatMessage(_i18n.messages.changeEmojiShortnameButtonLabel, {
@@ -44,6 +44,8 @@ var ResourcedEmojiComponent = exports.ResourcedEmojiComponent = function Resourc
44
44
  _ref$optimisticImageU = _ref.optimisticImageURL,
45
45
  optimisticImageURL = _ref$optimisticImageU === void 0 ? undefined : _ref$optimisticImageU,
46
46
  editorEmoji = _ref.editorEmoji,
47
+ _ref$renderUnicodeEmo = _ref.renderUnicodeEmojiAsImage,
48
+ renderUnicodeEmojiAsImage = _ref$renderUnicodeEmo === void 0 ? true : _ref$renderUnicodeEmo,
47
49
  _ref$pageTitleEmoji = _ref.pageTitleEmoji,
48
50
  pageTitleEmoji = _ref$pageTitleEmoji === void 0 ? false : _ref$pageTitleEmoji,
49
51
  placeholderXcss = _ref.placeholderXcss,
@@ -304,7 +306,8 @@ var ResourcedEmojiComponent = exports.ResourcedEmojiComponent = function Resourc
304
306
  showTooltip: showTooltip,
305
307
  fitToHeight: fitToHeight,
306
308
  autoWidth: autoWidth,
307
- editorEmoji: editorEmoji
309
+ editorEmoji: editorEmoji,
310
+ renderUnicodeEmojiAsImage: renderUnicodeEmojiAsImage
308
311
  })));
309
312
  };
310
313
  var _default = exports.default = ResourcedEmojiComponent;
@@ -20,7 +20,7 @@ var createEvent = function createEvent(eventType, action, actionSubject, actionS
20
20
  actionSubjectId: actionSubjectId,
21
21
  attributes: _objectSpread({
22
22
  packageName: "@atlaskit/emoji",
23
- packageVersion: "71.0.0"
23
+ packageVersion: "71.0.1"
24
24
  }, attributes)
25
25
  };
26
26
  };
@@ -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
- export const UnicodeEmoji = props => {
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
@@ -356,6 +464,7 @@ export const EmojiNodeWrapper = /*#__PURE__*/forwardRef((props, ref) => {
356
464
  children,
357
465
  type,
358
466
  editorEmoji,
467
+ renderUnicodeEmojiAsImage,
359
468
  ...other
360
469
  } = props;
361
470
  const intl = useContext(IntlContext);
@@ -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;
@@ -9,7 +9,7 @@ const createEvent = (eventType, action, actionSubject, actionSubjectId, attribut
9
9
  actionSubjectId,
10
10
  attributes: {
11
11
  packageName: "@atlaskit/emoji",
12
- packageVersion: "71.0.0",
12
+ packageVersion: "71.0.1",
13
13
  ...attributes
14
14
  }
15
15
  });
@@ -1,14 +1,16 @@
1
1
  /* Emoji.tsx generated by @compiled/babel-plugin v0.39.1 */
2
2
  import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
3
3
  import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
4
+ import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
4
5
  import _extends from "@babel/runtime/helpers/extends";
5
6
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
6
- var _excluded = ["emoji", "fitToHeight", "selected", "selectOnHover", "className", "showTooltip", "showDelete", "shouldBeInteractive", "tabIndex", "onSelected", "onMouseMove", "onFocus", "onDelete", "onLoadError", "onLoadSuccess", "disableLazyLoad", "autoWidth", "children", "type", "editorEmoji"];
7
+ var _excluded = ["emoji", "fitToHeight", "selected", "selectOnHover", "className", "showTooltip", "showDelete", "shouldBeInteractive", "tabIndex", "onSelected", "onMouseMove", "onFocus", "onDelete", "onLoadError", "onLoadSuccess", "disableLazyLoad", "autoWidth", "children", "type", "editorEmoji", "renderUnicodeEmojiAsImage"];
7
8
  import "./Emoji.compiled.css";
8
9
  import { ax, ix } from "@compiled/react/runtime";
10
+ import _regeneratorRuntime from "@babel/runtime/regenerator";
9
11
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
10
12
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
11
- import React, { useEffect, useCallback, useContext, useMemo, forwardRef } from 'react';
13
+ import React, { useEffect, useCallback, useContext, useMemo, useState, forwardRef } from 'react';
12
14
  import { IntlContext } from 'react-intl';
13
15
  import Tooltip from '@atlaskit/tooltip';
14
16
  import { shouldUseAltRepresentation } from '../../api/EmojiUtils';
@@ -27,6 +29,8 @@ import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
27
29
  import { getDocument } from '@atlaskit/browser-apis';
28
30
  import { fg } from '@atlaskit/platform-feature-flags';
29
31
  import { messages } from '../i18n';
32
+ import { isSSR } from '../../util/is-ssr';
33
+ import EmojiPlaceholder from './EmojiPlaceholder';
30
34
  var emojiSpriteContainer = null;
31
35
  var emojiImageContainer = null;
32
36
 
@@ -142,15 +146,145 @@ export var SpriteEmoji = function SpriteEmoji(props) {
142
146
  }))
143
147
  );
144
148
  };
145
- export var UnicodeEmoji = function UnicodeEmoji(props) {
149
+ var unicodeEmojiCanvasSize = 128;
150
+ var unicodeEmojiCanvasFontSize = 124;
151
+ var unicodeEmojiCanvasTopPadding = 8;
152
+ var renderUnicodeEmojiToImagePath = /*#__PURE__*/function () {
153
+ var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(unicodeEmoji) {
154
+ var OffscreenCanvasCtor, canvas, context, blob;
155
+ return _regeneratorRuntime.wrap(function (_context) {
156
+ while (1) switch (_context.prev = _context.next) {
157
+ case 0:
158
+ OffscreenCanvasCtor = globalThis['OffscreenCanvas'];
159
+ if (!(isSSR() || !OffscreenCanvasCtor || typeof URL === 'undefined')) {
160
+ _context.next = 1;
161
+ break;
162
+ }
163
+ return _context.abrupt("return", undefined);
164
+ case 1:
165
+ canvas = new OffscreenCanvasCtor(unicodeEmojiCanvasSize, unicodeEmojiCanvasSize);
166
+ context = canvas.getContext('2d');
167
+ if (context) {
168
+ _context.next = 2;
169
+ break;
170
+ }
171
+ return _context.abrupt("return", undefined);
172
+ case 2:
173
+ context.clearRect(0, 0, unicodeEmojiCanvasSize, unicodeEmojiCanvasSize);
174
+ context.textAlign = 'center';
175
+ context.textBaseline = 'middle';
176
+ context.font = "".concat(unicodeEmojiCanvasFontSize, "px sans-serif");
177
+ context.fillText(unicodeEmoji, unicodeEmojiCanvasSize / 2, unicodeEmojiCanvasSize / 2 + unicodeEmojiCanvasTopPadding);
178
+ _context.next = 3;
179
+ return canvas.convertToBlob({
180
+ type: 'image/png'
181
+ });
182
+ case 3:
183
+ blob = _context.sent;
184
+ return _context.abrupt("return", URL.createObjectURL(blob));
185
+ case 4:
186
+ case "end":
187
+ return _context.stop();
188
+ }
189
+ }, _callee);
190
+ }));
191
+ return function renderUnicodeEmojiToImagePath(_x) {
192
+ return _ref.apply(this, arguments);
193
+ };
194
+ }();
195
+ var useUnicodeEmojiImage = function useUnicodeEmojiImage(unicodeEmoji) {
196
+ var _useState = useState({
197
+ status: 'loading'
198
+ }),
199
+ _useState2 = _slicedToArray(_useState, 2),
200
+ state = _useState2[0],
201
+ setState = _useState2[1];
202
+ useEffect(function () {
203
+ var cancelled = false;
204
+ var imagePathToRevoke;
205
+ setState({
206
+ status: 'loading',
207
+ unicodeEmoji: unicodeEmoji
208
+ });
209
+ void renderUnicodeEmojiToImagePath(unicodeEmoji).then(function (imagePath) {
210
+ if (cancelled) {
211
+ if (imagePath) {
212
+ URL.revokeObjectURL(imagePath);
213
+ }
214
+ return;
215
+ }
216
+ imagePathToRevoke = imagePath;
217
+ setState(imagePath ? {
218
+ status: 'ready',
219
+ unicodeEmoji: unicodeEmoji,
220
+ imagePath: imagePath
221
+ } : {
222
+ status: 'failed',
223
+ unicodeEmoji: unicodeEmoji
224
+ });
225
+ }).catch(function () {
226
+ if (!cancelled) {
227
+ setState({
228
+ status: 'failed',
229
+ unicodeEmoji: unicodeEmoji
230
+ });
231
+ }
232
+ });
233
+ return function () {
234
+ cancelled = true;
235
+ if (imagePathToRevoke) {
236
+ URL.revokeObjectURL(imagePathToRevoke);
237
+ }
238
+ };
239
+ }, [unicodeEmoji]);
240
+ return state;
241
+ };
242
+ var UnicodeEmojiImage = function UnicodeEmojiImage(props) {
146
243
  var emoji = props.emoji,
147
244
  fitToHeight = props.fitToHeight,
245
+ showTooltip = props.showTooltip;
246
+ var emojiText = emoji.representation.unicodeEmoji;
247
+ var unicodeEmojiImage = useUnicodeEmojiImage(emojiText);
248
+ var hasCurrentEmojiImage = unicodeEmojiImage.unicodeEmoji === emojiText;
249
+ if (isSSR() || !hasCurrentEmojiImage || unicodeEmojiImage.status === 'loading') {
250
+ return /*#__PURE__*/React.createElement(EmojiPlaceholder, {
251
+ shortName: emoji.shortName,
252
+ showTooltip: showTooltip,
253
+ size: fitToHeight,
254
+ loading: true
255
+ });
256
+ }
257
+ if (unicodeEmojiImage.status === 'ready') {
258
+ return /*#__PURE__*/React.createElement(ImageEmoji, _extends({}, props, {
259
+ emoji: _objectSpread(_objectSpread({}, emoji), {}, {
260
+ representation: {
261
+ imagePath: unicodeEmojiImage.imagePath,
262
+ width: unicodeEmojiCanvasSize,
263
+ height: unicodeEmojiCanvasSize
264
+ }
265
+ })
266
+ }));
267
+ }
268
+ return /*#__PURE__*/React.createElement(EmojiPlaceholder, {
269
+ shortName: emoji.shortName,
270
+ showTooltip: showTooltip,
271
+ size: fitToHeight
272
+ });
273
+ };
274
+ export var UnicodeEmoji = function UnicodeEmoji(props) {
275
+ var _props$fitToHeight;
276
+ var emoji = props.emoji,
148
277
  selected = props.selected,
149
278
  selectOnHover = props.selectOnHover,
150
- className = props.className;
279
+ className = props.className,
280
+ _props$renderUnicodeE = props.renderUnicodeEmojiAsImage,
281
+ renderUnicodeEmojiAsImage = _props$renderUnicodeE === void 0 ? true : _props$renderUnicodeE;
282
+ if (renderUnicodeEmojiAsImage) {
283
+ return /*#__PURE__*/React.createElement(UnicodeEmojiImage, props);
284
+ }
151
285
  var classes = "".concat(emojiNodeStyles, " ").concat(selected ? commonSelectedStyles : '', " ").concat(selectOnHover ? selectOnHoverStyles : '', " ").concat(className ? className : '');
152
286
  var emojiText = emoji.representation.unicodeEmoji;
153
- var size = fitToHeight !== null && fitToHeight !== void 0 ? fitToHeight : defaultEmojiHeight;
287
+ var size = (_props$fitToHeight = props.fitToHeight) !== null && _props$fitToHeight !== void 0 ? _props$fitToHeight : defaultEmojiHeight;
154
288
  var style = {
155
289
  display: 'inline-block',
156
290
  // eslint-disable-next-line @atlaskit/design-system/use-tokens-typography
@@ -354,6 +488,7 @@ export var EmojiNodeWrapper = /*#__PURE__*/forwardRef(function (props, ref) {
354
488
  children = props.children,
355
489
  type = props.type,
356
490
  editorEmoji = props.editorEmoji,
491
+ renderUnicodeEmojiAsImage = props.renderUnicodeEmojiAsImage,
357
492
  other = _objectWithoutProperties(props, _excluded);
358
493
  var intl = useContext(IntlContext);
359
494
  var ariaLabel = intl && fg('platform_change_emoji_button_label') ? intl.formatMessage(messages.changeEmojiShortnameButtonLabel, {
@@ -35,6 +35,8 @@ export var ResourcedEmojiComponent = function ResourcedEmojiComponent(_ref) {
35
35
  _ref$optimisticImageU = _ref.optimisticImageURL,
36
36
  optimisticImageURL = _ref$optimisticImageU === void 0 ? undefined : _ref$optimisticImageU,
37
37
  editorEmoji = _ref.editorEmoji,
38
+ _ref$renderUnicodeEmo = _ref.renderUnicodeEmojiAsImage,
39
+ renderUnicodeEmojiAsImage = _ref$renderUnicodeEmo === void 0 ? true : _ref$renderUnicodeEmo,
38
40
  _ref$pageTitleEmoji = _ref.pageTitleEmoji,
39
41
  pageTitleEmoji = _ref$pageTitleEmoji === void 0 ? false : _ref$pageTitleEmoji,
40
42
  placeholderXcss = _ref.placeholderXcss,
@@ -295,7 +297,8 @@ export var ResourcedEmojiComponent = function ResourcedEmojiComponent(_ref) {
295
297
  showTooltip: showTooltip,
296
298
  fitToHeight: fitToHeight,
297
299
  autoWidth: autoWidth,
298
- editorEmoji: editorEmoji
300
+ editorEmoji: editorEmoji,
301
+ renderUnicodeEmojiAsImage: renderUnicodeEmojiAsImage
299
302
  })));
300
303
  };
301
304
  export default ResourcedEmojiComponent;
@@ -14,7 +14,7 @@ var createEvent = function createEvent(eventType, action, actionSubject, actionS
14
14
  actionSubjectId: actionSubjectId,
15
15
  attributes: _objectSpread({
16
16
  packageName: "@atlaskit/emoji",
17
- packageVersion: "71.0.0"
17
+ packageVersion: "71.0.1"
18
18
  }, attributes)
19
19
  };
20
20
  };
@@ -59,6 +59,11 @@ export interface Props extends Omit<React.HTMLAttributes<HTMLSpanElement>, 'onMo
59
59
  * Called when an emoji is selected
60
60
  */
61
61
  onSelected?: OnEmojiEvent;
62
+ /**
63
+ * Renders unicode emoji through an image representation when a fixed height is supplied.
64
+ * Defaults to `true`.
65
+ */
66
+ renderUnicodeEmojiAsImage?: boolean;
62
67
  /**
63
68
  * Show the emoji as selected
64
69
  */
@@ -50,6 +50,11 @@ export interface BaseResourcedEmojiProps {
50
50
  * allows custom styling to the placeholder component while the emoji is loading.
51
51
  */
52
52
  placeholderXcss?: StrictXCSSProp<'backgroundColor', never>;
53
+ /**
54
+ * Renders unicode emoji through an image representation when a fixed height is supplied.
55
+ * Defaults to `true`.
56
+ */
57
+ renderUnicodeEmojiAsImage?: boolean;
53
58
  /**
54
59
  * Allows to show the tooltip.
55
60
  * Defaults to `false`.
@@ -70,5 +75,5 @@ export interface Props extends BaseResourcedEmojiProps {
70
75
  */
71
76
  onEmojiLoadSuccess?: EmojiLoadSuccessCallback;
72
77
  }
73
- export declare const ResourcedEmojiComponent: ({ emojiProvider, emojiId, showTooltip, customFallback, fitToHeight, optimistic, optimisticImageURL, editorEmoji, pageTitleEmoji, placeholderXcss, onEmojiLoadSuccess, onEmojiLoadFail, }: Props) => React.JSX.Element;
78
+ export declare const ResourcedEmojiComponent: ({ emojiProvider, emojiId, showTooltip, customFallback, fitToHeight, optimistic, optimisticImageURL, editorEmoji, renderUnicodeEmojiAsImage, pageTitleEmoji, placeholderXcss, onEmojiLoadSuccess, onEmojiLoadFail, }: Props) => React.JSX.Element;
74
79
  export default ResourcedEmojiComponent;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/emoji",
3
- "version": "71.0.1",
3
+ "version": "71.1.0",
4
4
  "description": "Fabric emoji React components",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/"