emoji-picker-react 4.4.12 → 4.5.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 (55) hide show
  1. package/README.md +64 -26
  2. package/dist/components/emoji/BaseEmojiProps.d.ts +12 -0
  3. package/dist/components/emoji/ClickableEmojiButton.d.ts +13 -0
  4. package/dist/components/emoji/Emoji.d.ts +3 -13
  5. package/dist/components/emoji/EmojiImg.d.ts +10 -0
  6. package/dist/components/emoji/ExportedEmoji.d.ts +2 -2
  7. package/dist/components/emoji/NativeEmoji.d.ts +5 -0
  8. package/dist/components/emoji/ViewOnlyEmoji.d.ts +3 -0
  9. package/dist/config/categoryConfig.d.ts +4 -0
  10. package/dist/config/config.d.ts +3 -1
  11. package/dist/config/customEmojiConfig.d.ts +6 -0
  12. package/dist/config/useConfig.d.ts +2 -0
  13. package/dist/data/emojis.d.ts +1 -0
  14. package/dist/dataUtils/DataTypes.d.ts +16 -6
  15. package/dist/dataUtils/alphaNumericEmojiIndex.d.ts +1 -0
  16. package/dist/dataUtils/emojiSelectors.d.ts +5 -3
  17. package/dist/emoji-picker-react.cjs.development.css +2 -2
  18. package/dist/emoji-picker-react.cjs.development.js +284 -184
  19. package/dist/emoji-picker-react.cjs.development.js.map +1 -1
  20. package/dist/emoji-picker-react.cjs.production.min.js +1 -1
  21. package/dist/emoji-picker-react.cjs.production.min.js.map +1 -1
  22. package/dist/emoji-picker-react.esm.js +294 -194
  23. package/dist/emoji-picker-react.esm.js.map +1 -1
  24. package/dist/hooks/preloadEmoji.d.ts +1 -1
  25. package/dist/hooks/useShouldHideCustomEmojis.d.ts +1 -0
  26. package/dist/typeRefinements/typeRefinements.d.ts +5 -0
  27. package/dist/types/exposedTypes.d.ts +1 -0
  28. package/package.json +5 -5
  29. package/src/components/context/PickerConfigContext.tsx +2 -1
  30. package/src/components/emoji/BaseEmojiProps.ts +13 -0
  31. package/src/components/emoji/ClickableEmojiButton.tsx +42 -0
  32. package/src/components/emoji/Emoji.css +2 -0
  33. package/src/components/emoji/Emoji.tsx +15 -125
  34. package/src/components/emoji/EmojiImg.tsx +31 -0
  35. package/src/components/emoji/ExportedEmoji.tsx +3 -2
  36. package/src/components/emoji/NativeEmoji.tsx +23 -0
  37. package/src/components/emoji/ViewOnlyEmoji.tsx +70 -0
  38. package/src/components/footer/Preview.tsx +1 -1
  39. package/src/components/navigation/CategoryNavigation.css +3 -0
  40. package/src/components/navigation/CategoryNavigation.tsx +8 -0
  41. package/src/config/categoryConfig.ts +10 -0
  42. package/src/config/config.ts +10 -2
  43. package/src/config/customEmojiConfig.ts +7 -0
  44. package/src/config/useConfig.ts +8 -2
  45. package/src/data/emojis.json +1 -1
  46. package/src/data/emojis.ts +1 -1
  47. package/src/dataUtils/DataTypes.ts +19 -6
  48. package/src/dataUtils/alphaNumericEmojiIndex.ts +16 -11
  49. package/src/dataUtils/emojiSelectors.ts +30 -11
  50. package/src/hooks/preloadEmoji.ts +1 -1
  51. package/src/hooks/useEmojiPreviewEvents.ts +0 -2
  52. package/src/hooks/useMouseDownHandlers.ts +1 -1
  53. package/src/hooks/useShouldHideCustomEmojis.ts +11 -0
  54. package/src/typeRefinements/typeRefinements.ts +17 -0
  55. package/src/types/exposedTypes.ts +1 -0
@@ -1,4 +1,4 @@
1
- import { GetEmojiUrl } from '../components/emoji/Emoji';
1
+ import { GetEmojiUrl } from '../components/emoji/BaseEmojiProps';
2
2
  import { DataEmoji } from '../dataUtils/DataTypes';
3
3
  import { EmojiStyle } from '../types/exposedTypes';
4
4
  export declare function preloadEmoji(getEmojiUrl: GetEmojiUrl, emoji: undefined | DataEmoji, emojiStyle: EmojiStyle): void;
@@ -0,0 +1 @@
1
+ export declare function useShouldHideCustomEmojis(): boolean;
@@ -0,0 +1,5 @@
1
+ import { CategoryConfig, CustomCategoryConfig } from '../config/categoryConfig';
2
+ import { CustomEmoji } from '../config/customEmojiConfig';
3
+ import { DataEmoji } from '../dataUtils/DataTypes';
4
+ export declare function isCustomCategory(category: CategoryConfig | CustomCategoryConfig): category is CustomCategoryConfig;
5
+ export declare function isCustomEmoji(emoji: Partial<DataEmoji>): emoji is CustomEmoji;
@@ -32,6 +32,7 @@ export declare enum SkinTones {
32
32
  }
33
33
  export declare enum Categories {
34
34
  SUGGESTED = "suggested",
35
+ CUSTOM = "custom",
35
36
  SMILEYS_PEOPLE = "smileys_people",
36
37
  ANIMALS_NATURE = "animals_nature",
37
38
  FOOD_DRINK = "food_drink",
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "4.4.12",
2
+ "version": "4.5.0",
3
3
  "license": "MIT",
4
4
  "main": "dist/index.js",
5
5
  "typings": "dist/index.d.ts",
@@ -77,6 +77,9 @@
77
77
  "emoji-datasource": "^14.0.0",
78
78
  "eslint-import-resolver-typescript": "^3.3.0",
79
79
  "eslint-plugin-import": "^2.26.0",
80
+ "eslint-plugin-jsx-a11y": "^6.6.1",
81
+ "eslint-plugin-react": "^7.31.8",
82
+ "eslint-plugin-react-hooks": "^4.6.0",
80
83
  "fs-extra": "^10.1.0",
81
84
  "glob": "^8.0.3",
82
85
  "husky": "^8.0.1",
@@ -92,10 +95,7 @@
92
95
  "tiny-invariant": "^1.2.0",
93
96
  "tsdx": "^0.14.1",
94
97
  "tslib": "^2.4.0",
95
- "typescript": "^4.7.4",
96
- "eslint-plugin-jsx-a11y": "^6.6.1",
97
- "eslint-plugin-react": "^7.31.8",
98
- "eslint-plugin-react-hooks": "^4.6.0"
98
+ "typescript": "^4.7.4"
99
99
  },
100
100
  "dependencies": {
101
101
  "clsx": "^1.2.1"
@@ -17,8 +17,9 @@ const ConfigContext = React.createContext<PickerConfigInternal>(
17
17
  );
18
18
 
19
19
  export function PickerConfigProvider({ children, ...config }: Props) {
20
+ const [mergedConfig] = React.useState(() => mergeConfig(config));
20
21
  return (
21
- <ConfigContext.Provider value={mergeConfig(config)}>
22
+ <ConfigContext.Provider value={mergedConfig}>
22
23
  {children}
23
24
  </ConfigContext.Provider>
24
25
  );
@@ -0,0 +1,13 @@
1
+ import { CustomEmoji } from '../../config/customEmojiConfig';
2
+ import { DataEmoji } from '../../dataUtils/DataTypes';
3
+ import { EmojiStyle } from '../../types/exposedTypes';
4
+
5
+ export type BaseEmojiProps = {
6
+ emoji?: DataEmoji | CustomEmoji;
7
+ emojiStyle: EmojiStyle;
8
+ unified: string;
9
+ size?: number;
10
+ lazyLoad?: boolean;
11
+ getEmojiUrl?: GetEmojiUrl;
12
+ };
13
+ export type GetEmojiUrl = (unified: string, style: EmojiStyle) => string;
@@ -0,0 +1,42 @@
1
+ import clsx from 'clsx';
2
+ import * as React from 'react';
3
+
4
+ import { ClassNames } from '../../DomUtils/classNames';
5
+ import { Button } from '../atoms/Button';
6
+ import './Emoji.css';
7
+
8
+ type ClickableEmojiButtonProps = Readonly<{
9
+ hidden?: boolean;
10
+ showVariations?: boolean;
11
+ hiddenOnSearch?: boolean;
12
+ emojiNames: string[];
13
+ children: React.ReactNode;
14
+ hasVariations: boolean;
15
+ unified?: string;
16
+ }>;
17
+
18
+ export function ClickableEmojiButton({
19
+ emojiNames,
20
+ unified,
21
+ hidden,
22
+ hiddenOnSearch,
23
+ showVariations = true,
24
+ hasVariations,
25
+ children
26
+ }: ClickableEmojiButtonProps) {
27
+ return (
28
+ <Button
29
+ className={clsx(ClassNames.emoji, {
30
+ [ClassNames.hidden]: hidden,
31
+ [ClassNames.hiddenOnSearch]: hiddenOnSearch,
32
+ [ClassNames.visible]: !hidden && !hiddenOnSearch,
33
+ [ClassNames.emojiHasVariations]: hasVariations && showVariations
34
+ })}
35
+ data-unified={unified}
36
+ aria-label={emojiNames[0]}
37
+ data-full-name={emojiNames}
38
+ >
39
+ {children}
40
+ </Button>
41
+ );
42
+ }
@@ -30,6 +30,8 @@
30
30
  .EmojiPickerReact button.epr-emoji .epr-emoji-img {
31
31
  max-width: var(--epr-emoji-fullsize);
32
32
  max-height: var(--epr-emoji-fullsize);
33
+ min-width: var(--epr-emoji-fullsize);
34
+ min-height: var(--epr-emoji-fullsize);
33
35
  padding: var(--epr-emoji-padding);
34
36
  }
35
37
 
@@ -1,23 +1,15 @@
1
- import clsx from 'clsx';
2
1
  import * as React from 'react';
3
2
 
4
- import { ClassNames } from '../../DomUtils/classNames';
5
3
  import { DataEmoji } from '../../dataUtils/DataTypes';
6
- import {
7
- emojiByUnified,
8
- emojiHasVariations,
9
- emojiName,
10
- emojiNames,
11
- emojiUrlByUnified,
12
- } from '../../dataUtils/emojiSelectors';
13
- import { parseNativeEmoji } from '../../dataUtils/parseNativeEmoji';
14
- import { EmojiStyle } from '../../types/exposedTypes';
15
- import { Button } from '../atoms/Button';
16
- import { useEmojisThatFailedToLoadState } from '../context/PickerContext';
4
+ import { emojiHasVariations, emojiNames } from '../../dataUtils/emojiSelectors';
5
+
17
6
  import './Emoji.css';
7
+ import { BaseEmojiProps } from './BaseEmojiProps';
8
+ import { ClickableEmojiButton } from './ClickableEmojiButton';
9
+ import { ViewOnlyEmoji } from './ViewOnlyEmoji';
18
10
 
19
11
  type ClickableEmojiProps = Readonly<
20
- BaseProps & {
12
+ BaseEmojiProps & {
21
13
  hidden?: boolean;
22
14
  showVariations?: boolean;
23
15
  hiddenOnSearch?: boolean;
@@ -25,15 +17,6 @@ type ClickableEmojiProps = Readonly<
25
17
  }
26
18
  >;
27
19
 
28
- type BaseProps = {
29
- emoji?: DataEmoji;
30
- emojiStyle: EmojiStyle;
31
- unified: string;
32
- size?: number;
33
- lazyLoad?: boolean;
34
- getEmojiUrl?: GetEmojiUrl;
35
- };
36
-
37
20
  export function ClickableEmoji({
38
21
  emoji,
39
22
  unified,
@@ -43,22 +26,18 @@ export function ClickableEmoji({
43
26
  showVariations = true,
44
27
  size,
45
28
  lazyLoad,
46
- getEmojiUrl,
29
+ getEmojiUrl
47
30
  }: ClickableEmojiProps) {
48
31
  const hasVariations = emojiHasVariations(emoji);
49
32
 
50
33
  return (
51
- <Button
52
- className={clsx(ClassNames.emoji, {
53
- [ClassNames.hidden]: hidden,
54
- [ClassNames.hiddenOnSearch]: hiddenOnSearch,
55
- [ClassNames.visible]: !hidden && !hiddenOnSearch,
56
- [ClassNames.emojiHasVariations]: hasVariations && showVariations,
57
- })}
58
- data-unified={unified}
59
- // @ts-ignore - let's ignore the fact this is not a real react ref, ok?
60
- aria-label={emojiName(emoji)}
61
- data-full-name={emojiNames(emoji)}
34
+ <ClickableEmojiButton
35
+ hasVariations={hasVariations}
36
+ showVariations={showVariations}
37
+ hidden={hidden}
38
+ hiddenOnSearch={hiddenOnSearch}
39
+ emojiNames={emojiNames(emoji)}
40
+ unified={unified}
62
41
  >
63
42
  <ViewOnlyEmoji
64
43
  unified={unified}
@@ -68,95 +47,6 @@ export function ClickableEmoji({
68
47
  lazyLoad={lazyLoad}
69
48
  getEmojiUrl={getEmojiUrl}
70
49
  />
71
- </Button>
72
- );
73
- }
74
-
75
- export function ViewOnlyEmoji({
76
- emoji,
77
- unified,
78
- emojiStyle,
79
- size,
80
- lazyLoad,
81
- getEmojiUrl = emojiUrlByUnified,
82
- }: BaseProps) {
83
- const style = {} as React.CSSProperties;
84
- if (size) {
85
- style.width = style.height = style.fontSize = `${size}px`;
86
- }
87
-
88
- const emojiToRender = emoji ? emoji : emojiByUnified(unified);
89
- if(!emojiToRender) {
90
- return null
91
- }
92
-
93
- return (
94
- <>
95
- {emojiStyle === EmojiStyle.NATIVE ? (
96
- <NativeEmoji unified={unified} style={style} />
97
- ) : (
98
- <EmojiImg
99
- unified={unified}
100
- style={style}
101
- emoji={emojiToRender}
102
- emojiStyle={emojiStyle}
103
- lazyLoad={lazyLoad}
104
- getEmojiUrl={getEmojiUrl}
105
- />
106
- )}
107
- </>
108
- );
109
- }
110
-
111
- function NativeEmoji({
112
- unified,
113
- style,
114
- }: {
115
- unified: string;
116
- style: React.CSSProperties;
117
- }) {
118
- return (
119
- <span
120
- className={clsx(ClassNames.external, 'epr-emoji-native')}
121
- data-unified={unified}
122
- style={style}
123
- >
124
- {parseNativeEmoji(unified)}
125
- </span>
126
- );
127
- }
128
-
129
- function EmojiImg({
130
- emoji,
131
- unified,
132
- emojiStyle,
133
- style,
134
- lazyLoad = false,
135
- getEmojiUrl,
136
- }: {
137
- emoji: DataEmoji;
138
- unified: string;
139
- emojiStyle: EmojiStyle;
140
- style: React.CSSProperties;
141
- lazyLoad?: boolean;
142
- getEmojiUrl: GetEmojiUrl;
143
- }) {
144
- const [, setEmojisThatFailedToLoad] = useEmojisThatFailedToLoadState();
145
-
146
- return (
147
- <img
148
- src={getEmojiUrl(unified, emojiStyle)}
149
- alt={emojiName(emoji)}
150
- className={clsx(ClassNames.external, 'epr-emoji-img')}
151
- loading={lazyLoad ? 'lazy' : 'eager'}
152
- onError={onError}
153
- style={style}
154
- />
50
+ </ClickableEmojiButton>
155
51
  );
156
-
157
- function onError() {
158
- setEmojisThatFailedToLoad((prev) => new Set(prev).add(unified));
159
- }
160
52
  }
161
-
162
- export type GetEmojiUrl = (unified: string, style: EmojiStyle) => string;
@@ -0,0 +1,31 @@
1
+ import clsx from 'clsx';
2
+ import * as React from 'react';
3
+
4
+ import { ClassNames } from '../../DomUtils/classNames';
5
+ import { EmojiStyle } from '../../types/exposedTypes';
6
+
7
+ export function EmojiImg({
8
+ emojiName,
9
+ style,
10
+ lazyLoad = false,
11
+ imgUrl,
12
+ onError
13
+ }: {
14
+ emojiName: string;
15
+ emojiStyle: EmojiStyle;
16
+ style: React.CSSProperties;
17
+ lazyLoad?: boolean;
18
+ imgUrl: string;
19
+ onError: () => void;
20
+ }) {
21
+ return (
22
+ <img
23
+ src={imgUrl}
24
+ alt={emojiName}
25
+ className={clsx(ClassNames.external, 'epr-emoji-img')}
26
+ loading={lazyLoad ? 'lazy' : 'eager'}
27
+ onError={onError}
28
+ style={style}
29
+ />
30
+ );
31
+ }
@@ -2,14 +2,15 @@ import * as React from 'react';
2
2
 
3
3
  import { EmojiStyle } from '../../types/exposedTypes';
4
4
 
5
- import { GetEmojiUrl, ViewOnlyEmoji } from './Emoji';
5
+ import { GetEmojiUrl } from './BaseEmojiProps';
6
+ import { ViewOnlyEmoji } from './ViewOnlyEmoji';
6
7
 
7
8
  export function ExportedEmoji({
8
9
  unified,
9
10
  size = 32,
10
11
  emojiStyle = EmojiStyle.APPLE,
11
12
  lazyLoad = false,
12
- getEmojiUrl,
13
+ getEmojiUrl
13
14
  }: {
14
15
  unified: string;
15
16
  emojiStyle?: EmojiStyle;
@@ -0,0 +1,23 @@
1
+ import clsx from 'clsx';
2
+ import * as React from 'react';
3
+
4
+ import { ClassNames } from '../../DomUtils/classNames';
5
+ import { parseNativeEmoji } from '../../dataUtils/parseNativeEmoji';
6
+
7
+ export function NativeEmoji({
8
+ unified,
9
+ style
10
+ }: {
11
+ unified: string;
12
+ style: React.CSSProperties;
13
+ }) {
14
+ return (
15
+ <span
16
+ className={clsx(ClassNames.external, 'epr-emoji-native')}
17
+ data-unified={unified}
18
+ style={style}
19
+ >
20
+ {parseNativeEmoji(unified)}
21
+ </span>
22
+ );
23
+ }
@@ -0,0 +1,70 @@
1
+ import * as React from 'react';
2
+
3
+ import {
4
+ emojiByUnified,
5
+ emojiName,
6
+ emojiUrlByUnified
7
+ } from '../../dataUtils/emojiSelectors';
8
+ import { isCustomEmoji } from '../../typeRefinements/typeRefinements';
9
+ import { EmojiStyle } from '../../types/exposedTypes';
10
+ import { useEmojisThatFailedToLoadState } from '../context/PickerContext';
11
+
12
+ import { BaseEmojiProps } from './BaseEmojiProps';
13
+ import { EmojiImg } from './EmojiImg';
14
+ import { NativeEmoji } from './NativeEmoji';
15
+
16
+ export function ViewOnlyEmoji({
17
+ emoji,
18
+ unified,
19
+ emojiStyle,
20
+ size,
21
+ lazyLoad,
22
+ getEmojiUrl = emojiUrlByUnified
23
+ }: BaseEmojiProps) {
24
+ const [, setEmojisThatFailedToLoad] = useEmojisThatFailedToLoadState();
25
+
26
+ const style = {} as React.CSSProperties;
27
+ if (size) {
28
+ style.width = style.height = style.fontSize = `${size}px`;
29
+ }
30
+
31
+ const emojiToRender = emoji ? emoji : emojiByUnified(unified);
32
+
33
+ if (!emojiToRender) {
34
+ return null;
35
+ }
36
+
37
+ if (isCustomEmoji(emojiToRender)) {
38
+ return (
39
+ <EmojiImg
40
+ style={style}
41
+ emojiName={unified}
42
+ emojiStyle={emojiStyle}
43
+ lazyLoad={lazyLoad}
44
+ imgUrl={emojiToRender.imgUrl}
45
+ onError={onError}
46
+ />
47
+ );
48
+ }
49
+
50
+ return (
51
+ <>
52
+ {emojiStyle === EmojiStyle.NATIVE ? (
53
+ <NativeEmoji unified={unified} style={style} />
54
+ ) : (
55
+ <EmojiImg
56
+ style={style}
57
+ emojiName={emojiName(emojiToRender)}
58
+ emojiStyle={emojiStyle}
59
+ lazyLoad={lazyLoad}
60
+ imgUrl={getEmojiUrl(unified, emojiStyle)}
61
+ onError={onError}
62
+ />
63
+ )}
64
+ </>
65
+ );
66
+
67
+ function onError() {
68
+ setEmojisThatFailedToLoad(prev => new Set(prev).add(unified));
69
+ }
70
+ }
@@ -16,9 +16,9 @@ import { useIsSkinToneInPreview } from '../../hooks/useShouldShowSkinTonePicker'
16
16
  import Flex from '../Layout/Flex';
17
17
  import Space from '../Layout/Space';
18
18
  import { useEmojiVariationPickerState } from '../context/PickerContext';
19
- import { ViewOnlyEmoji } from '../emoji/Emoji';
20
19
  import './Preview.css';
21
20
  import { SkinTonePickerMenu } from '../header/SkinTonePicker';
21
+ import { ViewOnlyEmoji } from '../emoji/ViewOnlyEmoji';
22
22
 
23
23
  export function Preview() {
24
24
  const previewConfig = usePreviewConfig();
@@ -87,6 +87,9 @@ aside.EmojiPickerReact.epr-main:has(input:placeholder-shown) .epr-category-nav {
87
87
  .EmojiPickerReact button.epr-cat-btn.epr-icn-suggested {
88
88
  background-position-x: calc(var(--epr-category-navigation-button-size) * -8);
89
89
  }
90
+ .EmojiPickerReact button.epr-cat-btn.epr-icn-custom {
91
+ background-position-x: calc(var(--epr-category-navigation-button-size) * -9);
92
+ }
90
93
  .EmojiPickerReact button.epr-cat-btn.epr-icn-activities {
91
94
  background-position-x: calc(var(--epr-category-navigation-button-size) * -4);
92
95
  }
@@ -12,6 +12,8 @@ import { useCategoriesConfig } from '../../config/useConfig';
12
12
  import { useActiveCategoryScrollDetection } from '../../hooks/useActiveCategoryScrollDetection';
13
13
  import useIsSearchMode from '../../hooks/useIsSearchMode';
14
14
  import { useScrollCategoryIntoView } from '../../hooks/useScrollCategoryIntoView';
15
+ import { useShouldHideCustomEmojis } from '../../hooks/useShouldHideCustomEmojis';
16
+ import { isCustomCategory } from '../../typeRefinements/typeRefinements';
15
17
  import { Button } from '../atoms/Button';
16
18
  import { useCategoryNavigationRef } from '../context/ElementRefContext';
17
19
 
@@ -23,11 +25,17 @@ export function CategoryNavigation() {
23
25
 
24
26
  const categoriesConfig = useCategoriesConfig();
25
27
  const CategoryNavigationRef = useCategoryNavigationRef();
28
+ const hideCustomCategory = useShouldHideCustomEmojis();
26
29
 
27
30
  return (
28
31
  <div className="epr-category-nav" ref={CategoryNavigationRef}>
29
32
  {categoriesConfig.map(categoryConfig => {
30
33
  const category = categoryFromCategoryConfig(categoryConfig);
34
+
35
+ if (isCustomCategory(categoryConfig) && hideCustomCategory) {
36
+ return null;
37
+ }
38
+
31
39
  return (
32
40
  <Button
33
41
  tabIndex={isSearchMode ? -1 : 0}
@@ -4,6 +4,7 @@ export { Categories };
4
4
 
5
5
  const categoriesOrdered: Categories[] = [
6
6
  Categories.SUGGESTED,
7
+ Categories.CUSTOM,
7
8
  Categories.SMILEYS_PEOPLE,
8
9
  Categories.ANIMALS_NATURE,
9
10
  Categories.FOOD_DRINK,
@@ -19,11 +20,20 @@ export const SuggestedRecent: CategoryConfig = {
19
20
  category: Categories.SUGGESTED
20
21
  };
21
22
 
23
+ export type CustomCategoryConfig = {
24
+ category: Categories.CUSTOM;
25
+ name: string;
26
+ };
27
+
22
28
  const configByCategory: Record<Categories, CategoryConfig> = {
23
29
  [Categories.SUGGESTED]: {
24
30
  category: Categories.SUGGESTED,
25
31
  name: 'Frequently Used'
26
32
  },
33
+ [Categories.CUSTOM]: {
34
+ category: Categories.CUSTOM,
35
+ name: 'Custom Emojis'
36
+ },
27
37
  [Categories.SMILEYS_PEOPLE]: {
28
38
  category: Categories.SMILEYS_PEOPLE,
29
39
  name: 'Smileys & People'
@@ -1,5 +1,8 @@
1
- import { GetEmojiUrl } from '../components/emoji/Emoji';
2
- import { emojiUrlByUnified } from '../dataUtils/emojiSelectors';
1
+ import { GetEmojiUrl } from '../components/emoji/BaseEmojiProps';
2
+ import {
3
+ addCustomEmojis,
4
+ emojiUrlByUnified
5
+ } from '../dataUtils/emojiSelectors';
3
6
  import {
4
7
  EmojiClickData,
5
8
  EmojiStyle,
@@ -14,6 +17,7 @@ import {
14
17
  baseCategoriesConfig,
15
18
  mergeCategoriesConfig
16
19
  } from './categoryConfig';
20
+ import { CustomEmoji } from './customEmojiConfig';
17
21
 
18
22
  const KNOWN_FAILING_EMOJIS = ['2640-fe0f', '2642-fe0f', '2695-fe0f'];
19
23
 
@@ -34,6 +38,8 @@ export function mergeConfig(
34
38
  suggestionMode: config.suggestedEmojisMode
35
39
  });
36
40
 
41
+ addCustomEmojis(config.customEmojis ?? []);
42
+
37
43
  const skinTonePickerLocation = config.searchDisabled
38
44
  ? SkinTonePickerLocation.PREVIEW
39
45
  : config.skinTonePickerLocation;
@@ -50,6 +56,7 @@ export function basePickerConfig(): PickerConfigInternal {
50
56
  return {
51
57
  autoFocusSearch: true,
52
58
  categories: baseCategoriesConfig(),
59
+ customEmojis: [],
53
60
  defaultSkinTone: SkinTones.NEUTRAL,
54
61
  emojiStyle: EmojiStyle.APPLE,
55
62
  emojiVersion: null,
@@ -99,6 +106,7 @@ export type PickerConfigInternal = {
99
106
  searchDisabled: boolean;
100
107
  skinTonePickerLocation: SkinTonePickerLocation;
101
108
  unicodeToHide: Set<string>;
109
+ customEmojis: CustomEmoji[];
102
110
  };
103
111
 
104
112
  export type PreviewConfig = {
@@ -0,0 +1,7 @@
1
+ import { EmojiProperties } from '../dataUtils/DataTypes';
2
+
3
+ export type CustomEmoji = {
4
+ names: string[];
5
+ [EmojiProperties.imgUrl]: string;
6
+ id: string;
7
+ };
@@ -13,14 +13,15 @@ import { CategoriesConfig } from './categoryConfig';
13
13
  import {
14
14
  DEFAULT_SEARCH_PLACEHOLDER,
15
15
  PickerDimensions,
16
- PreviewConfig,
16
+ PreviewConfig
17
17
  } from './config';
18
+ import { CustomEmoji } from './customEmojiConfig';
18
19
 
19
20
  export function useSearchPlaceHolderConfig(): string {
20
21
  const { searchPlaceHolder, searchPlaceholder } = usePickerConfig();
21
22
  return (
22
23
  [searchPlaceHolder, searchPlaceholder].find(
23
- (p) => p !== DEFAULT_SEARCH_PLACEHOLDER
24
+ p => p !== DEFAULT_SEARCH_PLACEHOLDER
24
25
  ) ?? DEFAULT_SEARCH_PLACEHOLDER
25
26
  );
26
27
  }
@@ -50,6 +51,11 @@ export function useCategoriesConfig(): CategoriesConfig {
50
51
  return categories;
51
52
  }
52
53
 
54
+ export function useCustomEmojisConfig(): CustomEmoji[] {
55
+ const { customEmojis } = usePickerConfig();
56
+ return customEmojis;
57
+ }
58
+
53
59
  export function useOnEmojiClickConfig(): (
54
60
  emoji: EmojiClickData,
55
61
  event: MouseEvent