emoji-picker-react 4.1.1 → 4.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,5 @@
1
+ import { GetEmojiUrl } from '../components/emoji/Emoji';
1
2
  import { DataEmoji } from '../dataUtils/DataTypes';
2
3
  import { EmojiStyle } from '../types/exposedTypes';
3
- export declare function preloadEmoji(emoji: undefined | DataEmoji, emojiStyle: EmojiStyle): void;
4
+ export declare function preloadEmoji(getEmojiUrl: GetEmojiUrl, emoji: undefined | DataEmoji, emojiStyle: EmojiStyle): void;
4
5
  export declare const preloadedEmojs: Set<string>;
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "4.1.1",
2
+ "version": "4.2.0",
3
3
  "license": "MIT",
4
4
  "main": "dist/index.js",
5
5
  "typings": "dist/index.d.ts",
@@ -9,6 +9,7 @@ import {
9
9
  import {
10
10
  useCategoriesConfig,
11
11
  useEmojiStyleConfig,
12
+ useGetEmojiUrlConfig,
12
13
  useLazyLoadEmojisConfig,
13
14
  } from '../../config/useConfig';
14
15
  import { emojisByCategory, emojiUnified } from '../../dataUtils/emojiSelectors';
@@ -65,6 +66,7 @@ function RenderCategory({
65
66
  const isPastInitialLoad = useIsPastInitialLoad();
66
67
  const [activeSkinTone] = useActiveSkinToneState();
67
68
  const disallowedEmojisRef = useDisallowedEmojisRef();
69
+ const getEmojiUrl = useGetEmojiUrlConfig();
68
70
 
69
71
  // Small trick to defer the rendering of all emoji categories until the first category is visible
70
72
  // This way the user gets to actually see something and not wait for the whole picker to render.
@@ -96,6 +98,7 @@ function RenderCategory({
96
98
  hiddenOnSearch={filteredOut}
97
99
  emojiStyle={emojiStyle}
98
100
  lazyLoad={lazyLoadEmojis}
101
+ getEmojiUrl={getEmojiUrl}
99
102
  />
100
103
  );
101
104
  });
@@ -7,20 +7,23 @@ import {
7
7
  buttonFromTarget,
8
8
  elementHeight,
9
9
  emojiTrueOffsetTop,
10
- emojiTruOffsetLeft
10
+ emojiTruOffsetLeft,
11
11
  } from '../../DomUtils/selectors';
12
- import { useEmojiStyleConfig } from '../../config/useConfig';
12
+ import {
13
+ useEmojiStyleConfig,
14
+ useGetEmojiUrlConfig,
15
+ } from '../../config/useConfig';
13
16
  import { asEmoji } from '../../dataUtils/asEmoji';
14
17
  import {
15
18
  emojiHasVariations,
16
19
  emojiUnified,
17
- emojiVariations
20
+ emojiVariations,
18
21
  } from '../../dataUtils/emojiSelectors';
19
22
  import {
20
23
  useAnchoredEmojiRef,
21
24
  useBodyRef,
22
25
  useSetAnchoredEmojiRef,
23
- useVariationPickerRef
26
+ useVariationPickerRef,
24
27
  } from '../context/ElementRefContext';
25
28
  import { useEmojiVariationPickerState } from '../context/PickerContext';
26
29
  import { ClickableEmoji } from '../emoji/Emoji';
@@ -28,7 +31,7 @@ import './EmojiVariationPicker.css';
28
31
 
29
32
  enum Direction {
30
33
  Up,
31
- Down
34
+ Down,
32
35
  }
33
36
 
34
37
  export function EmojiVariationPicker() {
@@ -41,6 +44,7 @@ export function EmojiVariationPicker() {
41
44
  );
42
45
  const setAnchoredEmojiRef = useSetAnchoredEmojiRef();
43
46
  const getPointerStyle = usePointerStyle(VariationPickerRef);
47
+ const getEmojiUrl = useGetEmojiUrlConfig();
44
48
 
45
49
  const button = buttonFromTarget(AnchoredEmojiRef.current);
46
50
 
@@ -67,7 +71,7 @@ export function EmojiVariationPicker() {
67
71
  ref={VariationPickerRef}
68
72
  className={clsx('epr-emoji-variation-picker', {
69
73
  visible,
70
- 'pointing-up': getMenuDirection() === Direction.Down
74
+ 'pointing-up': getMenuDirection() === Direction.Down,
71
75
  })}
72
76
  style={{ top }}
73
77
  >
@@ -75,13 +79,14 @@ export function EmojiVariationPicker() {
75
79
  ? [emojiUnified(safeEmoji)]
76
80
  .concat(emojiVariations(safeEmoji))
77
81
  .slice(0, 6)
78
- .map(unified => (
82
+ .map((unified) => (
79
83
  <ClickableEmoji
80
84
  key={unified}
81
85
  emoji={safeEmoji}
82
86
  unified={unified}
83
87
  emojiStyle={emojiStyle}
84
88
  showVariations={false}
89
+ getEmojiUrl={getEmojiUrl}
85
90
  />
86
91
  ))
87
92
  : null}
@@ -124,7 +129,7 @@ function useVariationPickerTop(
124
129
 
125
130
  return {
126
131
  getMenuDirection,
127
- getTop
132
+ getTop,
128
133
  };
129
134
 
130
135
  function getMenuDirection() {
@@ -3,7 +3,8 @@ import * as React from 'react';
3
3
  import { CategoryConfig } from '../../config/categoryConfig';
4
4
  import {
5
5
  useEmojiStyleConfig,
6
- useSuggestedEmojisModeConfig
6
+ useGetEmojiUrlConfig,
7
+ useSuggestedEmojisModeConfig,
7
8
  } from '../../config/useConfig';
8
9
  import { emojiByUnified } from '../../dataUtils/emojiSelectors';
9
10
  import { getsuggested } from '../../dataUtils/suggested';
@@ -19,6 +20,7 @@ type Props = Readonly<{
19
20
  export function Suggested({ categoryConfig }: Props) {
20
21
  const [suggestedUpdated] = useUpdateSuggested();
21
22
  const suggestedEmojisModeConfig = useSuggestedEmojisModeConfig();
23
+ const getEmojiUrl = useGetEmojiUrlConfig();
22
24
  const suggested = React.useMemo(
23
25
  () => getsuggested(suggestedEmojisModeConfig) ?? [],
24
26
  // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -32,7 +34,7 @@ export function Suggested({ categoryConfig }: Props) {
32
34
  hiddenOnSearch
33
35
  hidden={suggested.length === 0}
34
36
  >
35
- {suggested.map(suggestedItem => {
37
+ {suggested.map((suggestedItem) => {
36
38
  const emoji = emojiByUnified(suggestedItem.original);
37
39
 
38
40
  if (!emoji) {
@@ -46,6 +48,7 @@ export function Suggested({ categoryConfig }: Props) {
46
48
  emojiStyle={emojiStyle}
47
49
  emoji={emoji}
48
50
  key={suggestedItem.unified}
51
+ getEmojiUrl={getEmojiUrl}
49
52
  />
50
53
  );
51
54
  })}
@@ -9,7 +9,7 @@ import {
9
9
  emojiHasVariations,
10
10
  emojiName,
11
11
  emojiNames,
12
- emojiUrlByUnified
12
+ emojiUrlByUnified,
13
13
  } from '../../dataUtils/emojiSelectors';
14
14
  import { parseNativeEmoji } from '../../dataUtils/parseNativeEmoji';
15
15
  import { EmojiStyle } from '../../types/exposedTypes';
@@ -32,6 +32,7 @@ type BaseProps = {
32
32
  unified: string;
33
33
  size?: number;
34
34
  lazyLoad?: boolean;
35
+ getEmojiUrl?: GetEmojiUrl;
35
36
  };
36
37
 
37
38
  export function ClickableEmoji({
@@ -42,7 +43,8 @@ export function ClickableEmoji({
42
43
  emojiStyle,
43
44
  showVariations = true,
44
45
  size,
45
- lazyLoad
46
+ lazyLoad,
47
+ getEmojiUrl,
46
48
  }: ClickableEmojiProps) {
47
49
  const hasVariations = emojiHasVariations(emoji);
48
50
 
@@ -52,7 +54,7 @@ export function ClickableEmoji({
52
54
  [ClassNames.hidden]: hidden,
53
55
  [ClassNames.hiddenOnSearch]: hiddenOnSearch,
54
56
  [ClassNames.visible]: !hidden && !hiddenOnSearch,
55
- [ClassNames.emojiHasVariatios]: hasVariations && showVariations
57
+ [ClassNames.emojiHasVariatios]: hasVariations && showVariations,
56
58
  })}
57
59
  data-unified={unified}
58
60
  // @ts-ignore - let's ignore the fact this is not a real react ref, ok?
@@ -65,6 +67,7 @@ export function ClickableEmoji({
65
67
  size={size}
66
68
  emojiStyle={emojiStyle}
67
69
  lazyLoad={lazyLoad}
70
+ getEmojiUrl={getEmojiUrl}
68
71
  />
69
72
  </Button>
70
73
  );
@@ -75,7 +78,8 @@ export function ViewOnlyEmoji({
75
78
  unified,
76
79
  emojiStyle,
77
80
  size,
78
- lazyLoad
81
+ lazyLoad,
82
+ getEmojiUrl = emojiUrlByUnified,
79
83
  }: BaseProps) {
80
84
  const style = {} as React.CSSProperties;
81
85
  if (size) {
@@ -95,6 +99,7 @@ export function ViewOnlyEmoji({
95
99
  emoji={asEmoji(emojiToRender)}
96
100
  emojiStyle={emojiStyle}
97
101
  lazyLoad={lazyLoad}
102
+ getEmojiUrl={getEmojiUrl}
98
103
  />
99
104
  )}
100
105
  </>
@@ -103,7 +108,7 @@ export function ViewOnlyEmoji({
103
108
 
104
109
  function NativeEmoji({
105
110
  unified,
106
- style
111
+ style,
107
112
  }: {
108
113
  unified: string;
109
114
  style: React.CSSProperties;
@@ -124,19 +129,21 @@ function EmojiImg({
124
129
  unified,
125
130
  emojiStyle,
126
131
  style,
127
- lazyLoad = false
132
+ lazyLoad = false,
133
+ getEmojiUrl,
128
134
  }: {
129
135
  emoji: DataEmoji;
130
136
  unified: string;
131
137
  emojiStyle: EmojiStyle;
132
138
  style: React.CSSProperties;
133
139
  lazyLoad?: boolean;
140
+ getEmojiUrl: GetEmojiUrl;
134
141
  }) {
135
142
  const [, setEmojisThatFailedToLoad] = useEmojisThatFailedToLoadState();
136
143
 
137
144
  return (
138
145
  <img
139
- src={emojiUrlByUnified(emojiStyle, unified)}
146
+ src={getEmojiUrl(unified, emojiStyle)}
140
147
  alt={emojiName(emoji)}
141
148
  className={clsx(ClassNames.external, 'epr-emoji-img')}
142
149
  loading={lazyLoad ? 'lazy' : 'eager'}
@@ -146,6 +153,8 @@ function EmojiImg({
146
153
  );
147
154
 
148
155
  function onError() {
149
- setEmojisThatFailedToLoad(prev => new Set(prev).add(unified));
156
+ setEmojisThatFailedToLoad((prev) => new Set(prev).add(unified));
150
157
  }
151
158
  }
159
+
160
+ export type GetEmojiUrl = (unified: string, style: EmojiStyle) => string;
@@ -2,18 +2,20 @@ import * as React from 'react';
2
2
 
3
3
  import { EmojiStyle } from '../../types/exposedTypes';
4
4
 
5
- import { ViewOnlyEmoji } from './Emoji';
5
+ import { GetEmojiUrl, ViewOnlyEmoji } from './Emoji';
6
6
 
7
7
  export function ExportedEmoji({
8
8
  unified,
9
9
  size = 32,
10
10
  emojiStyle = EmojiStyle.APPLE,
11
- lazyLoad = false
11
+ lazyLoad = false,
12
+ getEmojiUrl,
12
13
  }: {
13
14
  unified: string;
14
15
  emojiStyle?: EmojiStyle;
15
16
  size?: number;
16
17
  lazyLoad?: boolean;
18
+ getEmojiUrl?: GetEmojiUrl;
17
19
  }) {
18
20
  if (!unified) {
19
21
  return null;
@@ -25,6 +27,7 @@ export function ExportedEmoji({
25
27
  size={size}
26
28
  emojiStyle={emojiStyle}
27
29
  lazyLoad={lazyLoad}
30
+ getEmojiUrl={getEmojiUrl}
28
31
  />
29
32
  );
30
33
  }
@@ -1,12 +1,16 @@
1
1
  import * as React from 'react';
2
2
  import { useState } from 'react';
3
3
 
4
- import { useEmojiStyleConfig, usePreviewConfig } from '../../config/useConfig';
4
+ import {
5
+ useEmojiStyleConfig,
6
+ useGetEmojiUrlConfig,
7
+ usePreviewConfig,
8
+ } from '../../config/useConfig';
5
9
  import { asEmoji } from '../../dataUtils/asEmoji';
6
10
  import {
7
11
  emojiByUnified,
8
12
  emojiName,
9
- emojiUnified
13
+ emojiUnified,
10
14
  } from '../../dataUtils/emojiSelectors';
11
15
  import { useEmojiPreviewEvents } from '../../hooks/useEmojiPreviewEvents';
12
16
  import Flex from '../Layout/Flex';
@@ -19,6 +23,7 @@ export function Preview() {
19
23
  const [previewEmoji, setPreviewEmoji] = useState<PreviewEmoji>(null);
20
24
  const emojiStyle = useEmojiStyleConfig();
21
25
  const [variationPickerEmoji] = useEmojiVariationPickerState();
26
+ const getEmojiUrl = useGetEmojiUrlConfig();
22
27
 
23
28
  useEmojiPreviewEvents(previewConfig.showPreview, setPreviewEmoji);
24
29
 
@@ -53,6 +58,7 @@ export function Preview() {
53
58
  emoji={asEmoji(emoji)}
54
59
  emojiStyle={emojiStyle}
55
60
  size={45}
61
+ getEmojiUrl={getEmojiUrl}
56
62
  />
57
63
  ) : defaultEmoji ? (
58
64
  <ViewOnlyEmoji
@@ -60,6 +66,7 @@ export function Preview() {
60
66
  emoji={defaultEmoji}
61
67
  emojiStyle={emojiStyle}
62
68
  size={45}
69
+ getEmojiUrl={getEmojiUrl}
63
70
  />
64
71
  ) : null}
65
72
  </div>
@@ -1,4 +1,4 @@
1
- import { EmojiStyle } from "../types/exposedTypes";
1
+ import { EmojiStyle } from '../types/exposedTypes';
2
2
 
3
3
  const CDN_URL_APPLE =
4
4
  'https://cdn.jsdelivr.net/npm/emoji-datasource-apple/img/apple/64/';
@@ -1,3 +1,5 @@
1
+ import { GetEmojiUrl } from '../components/emoji/Emoji';
2
+ import { emojiUrlByUnified } from '../dataUtils/emojiSelectors';
1
3
  import {
2
4
  EmojiClickData,
3
5
  EmojiStyle,
@@ -41,6 +43,7 @@ export function basePickerConfig(): PickerConfigInternal {
41
43
  defaultSkinTone: SkinTones.NEUTRAL,
42
44
  emojiStyle: EmojiStyle.APPLE,
43
45
  emojiVersion: null,
46
+ getEmojiUrl: emojiUrlByUnified,
44
47
  height: 450,
45
48
  lazyLoadEmojis: false,
46
49
  onEmojiClick: function defaultOnClickHandler(
@@ -77,6 +80,7 @@ export type PickerConfigInternal = {
77
80
  previewConfig: PreviewConfig;
78
81
  height: number;
79
82
  width: number;
83
+ getEmojiUrl: GetEmojiUrl;
80
84
  };
81
85
 
82
86
  export type PreviewConfig = {
@@ -83,3 +83,11 @@ export function useEmojiVersionConfig(): string | null {
83
83
  const { emojiVersion } = usePickerConfig();
84
84
  return emojiVersion;
85
85
  }
86
+
87
+ export function useGetEmojiUrlConfig(): (
88
+ unified: string,
89
+ style: EmojiStyle
90
+ ) => string {
91
+ const { getEmojiUrl } = usePickerConfig();
92
+ return getEmojiUrl;
93
+ }
@@ -38,14 +38,6 @@ export function unifiedWithoutSkinTone(unified: string): string {
38
38
  return unified;
39
39
  }
40
40
 
41
- export function emojiUrl(
42
- emojiStyle: EmojiStyle,
43
- emoji: DataEmoji,
44
- skinTone?: string
45
- ): string {
46
- return emojiUrlByUnified(emojiStyle, emojiUnified(emoji, skinTone));
47
- }
48
-
49
41
  export function emojiUnified(emoji: DataEmoji, skinTone?: string): string {
50
42
  const unified = emoji[EmojiProperties.unified];
51
43
 
@@ -61,9 +53,10 @@ export function emojisByCategory(category: Categories): DataEmojis {
61
53
  return emojis?.[category] ?? [];
62
54
  }
63
55
 
56
+ // WARNING: DO NOT USE DIRECTLY
64
57
  export function emojiUrlByUnified(
65
- emojiStyle: EmojiStyle,
66
- unified: string
58
+ unified: string,
59
+ emojiStyle: EmojiStyle
67
60
  ): string {
68
61
  return `${cdnUrl(emojiStyle)}${unified}.png`;
69
62
  }
@@ -1,12 +1,10 @@
1
+ import { GetEmojiUrl } from '../components/emoji/Emoji';
1
2
  import { DataEmoji } from '../dataUtils/DataTypes';
2
- import {
3
- emojiUnified,
4
- emojiUrlByUnified,
5
- emojiVariations
6
- } from '../dataUtils/emojiSelectors';
3
+ import { emojiUnified, emojiVariations } from '../dataUtils/emojiSelectors';
7
4
  import { EmojiStyle } from '../types/exposedTypes';
8
5
 
9
6
  export function preloadEmoji(
7
+ getEmojiUrl: GetEmojiUrl,
10
8
  emoji: undefined | DataEmoji,
11
9
  emojiStyle: EmojiStyle
12
10
  ): void {
@@ -24,8 +22,8 @@ export function preloadEmoji(
24
22
  return;
25
23
  }
26
24
 
27
- emojiVariations(emoji).forEach(variation => {
28
- const emojiUrl = emojiUrlByUnified(emojiStyle, variation);
25
+ emojiVariations(emoji).forEach((variation) => {
26
+ const emojiUrl = getEmojiUrl(variation, emojiStyle);
29
27
  preloadImage(emojiUrl);
30
28
  });
31
29
 
@@ -4,22 +4,25 @@ import { useEffect, useRef } from 'react';
4
4
  import {
5
5
  emojiFromElement,
6
6
  isEmojiElement,
7
- NullableElement
7
+ NullableElement,
8
8
  } from '../DomUtils/selectors';
9
9
  import {
10
10
  useActiveSkinToneState,
11
11
  useDisallowClickRef,
12
12
  useEmojiVariationPickerState,
13
- useUpdateSuggested
13
+ useUpdateSuggested,
14
14
  } from '../components/context/PickerContext';
15
- import { useOnEmojiClickConfig } from '../config/useConfig';
15
+ import { GetEmojiUrl } from '../components/emoji/Emoji';
16
+ import {
17
+ useGetEmojiUrlConfig,
18
+ useOnEmojiClickConfig,
19
+ } from '../config/useConfig';
16
20
  import { DataEmoji } from '../dataUtils/DataTypes';
17
21
  import {
18
22
  activeVariationFromUnified,
19
23
  emojiHasVariations,
20
24
  emojiNames,
21
25
  emojiUnified,
22
- emojiUrlByUnified
23
26
  } from '../dataUtils/emojiSelectors';
24
27
  import { parseNativeEmoji } from '../dataUtils/parseNativeEmoji';
25
28
  import { setsuggested } from '../dataUtils/suggested';
@@ -39,6 +42,7 @@ export function useMouseDownHandlers(
39
42
  const [activeSkinTone] = useActiveSkinToneState();
40
43
  const onEmojiClick = useOnEmojiClickConfig();
41
44
  const [, updateSuggested] = useUpdateSuggested();
45
+ const getEmojiUrl = useGetEmojiUrlConfig();
42
46
 
43
47
  const onClick = React.useCallback(
44
48
  function onClick(event: MouseEvent) {
@@ -59,14 +63,15 @@ export function useMouseDownHandlers(
59
63
 
60
64
  updateSuggested();
61
65
  setsuggested(emoji, skinToneToUse);
62
- onEmojiClick(emojiClickOutput(emoji, skinToneToUse), event);
66
+ onEmojiClick(emojiClickOutput(emoji, skinToneToUse, getEmojiUrl), event);
63
67
  },
64
68
  [
65
69
  activeSkinTone,
66
70
  closeAllOpenToggles,
67
71
  disallowClickRef,
68
72
  onEmojiClick,
69
- updateSuggested
73
+ updateSuggested,
74
+ getEmojiUrl,
70
75
  ]
71
76
  );
72
77
 
@@ -94,7 +99,7 @@ export function useMouseDownHandlers(
94
99
  disallowClickRef,
95
100
  closeAllOpenToggles,
96
101
  setVariationPicker,
97
- setEmojiVariationPicker
102
+ setEmojiVariationPicker,
98
103
  ]
99
104
  );
100
105
  const onMouseUp = React.useCallback(
@@ -123,14 +128,14 @@ export function useMouseDownHandlers(
123
128
  }
124
129
  const bodyRef = BodyRef.current;
125
130
  bodyRef.addEventListener('click', onClick, {
126
- passive: true
131
+ passive: true,
127
132
  });
128
133
 
129
134
  bodyRef.addEventListener('mousedown', onMouseDown, {
130
- passive: true
135
+ passive: true,
131
136
  });
132
137
  bodyRef.addEventListener('mouseup', onMouseUp, {
133
- passive: true
138
+ passive: true,
134
139
  });
135
140
 
136
141
  return () => {
@@ -152,17 +157,18 @@ function emojiFromEvent(event: MouseEvent): [DataEmoji, string] | [] {
152
157
 
153
158
  function emojiClickOutput(
154
159
  emoji: DataEmoji,
155
- activeSkinTone: SkinTones
160
+ activeSkinTone: SkinTones,
161
+ getEmojiUrl: GetEmojiUrl
156
162
  ): EmojiClickData {
157
163
  const unified = emojiUnified(emoji, activeSkinTone);
158
164
  return {
159
165
  activeSkinTone,
160
166
  emoji: parseNativeEmoji(unified),
161
167
  getImageUrl(emojiStyle: EmojiStyle) {
162
- return emojiUrlByUnified(emojiStyle, unified);
168
+ return getEmojiUrl(unified, emojiStyle);
163
169
  },
164
170
  names: emojiNames(emoji),
165
171
  unified,
166
- unifiedWithoutSkinTone: emojiUnified(emoji)
172
+ unifiedWithoutSkinTone: emojiUnified(emoji),
167
173
  };
168
174
  }
@@ -2,7 +2,7 @@ import { useEffect } from 'react';
2
2
 
3
3
  import { buttonFromTarget, emojiFromElement } from '../DomUtils/selectors';
4
4
  import { useBodyRef } from '../components/context/ElementRefContext';
5
- import { useEmojiStyleConfig } from '../config/useConfig';
5
+ import { useEmojiStyleConfig, useGetEmojiUrlConfig } from '../config/useConfig';
6
6
  import { emojiHasVariations } from '../dataUtils/emojiSelectors';
7
7
  import { EmojiStyle } from '../types/exposedTypes';
8
8
 
@@ -11,6 +11,7 @@ import { preloadEmoji } from './preloadEmoji';
11
11
  export function useOnFocus() {
12
12
  const BodyRef = useBodyRef();
13
13
  const emojiStyle = useEmojiStyleConfig();
14
+ const getEmojiUrl = useGetEmojiUrlConfig();
14
15
 
15
16
  useEffect(() => {
16
17
  if (emojiStyle === EmojiStyle.NATIVE) {
@@ -39,8 +40,8 @@ export function useOnFocus() {
39
40
  }
40
41
 
41
42
  if (emojiHasVariations(emoji)) {
42
- preloadEmoji(emoji, emojiStyle);
43
+ preloadEmoji(getEmojiUrl, emoji, emojiStyle);
43
44
  }
44
45
  }
45
- }, [BodyRef, emojiStyle]);
46
+ }, [BodyRef, emojiStyle, getEmojiUrl]);
46
47
  }