emoji-picker-react 4.0.0-rc.10 → 4.0.0-rc.13

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/README.md CHANGED
@@ -6,7 +6,7 @@ An emoji picker component for React applications.
6
6
 
7
7
  ## What to know before using
8
8
 
9
- - This package assumes it runs in the browser. I have taken many steps to prevent it from failing on the server, but still, it is recommended to only render the component on the client.
9
+ - This package assumes it runs in the browser. I have taken many steps to prevent it from failing on the server, but still, it is recommended to only render the component on the client. See troubleshooting section for more information.
10
10
 
11
11
  ## Installation
12
12
 
@@ -14,6 +14,20 @@ An emoji picker component for React applications.
14
14
  npm install emoji-picker-react
15
15
  ```
16
16
 
17
+ ## Usage:
18
+
19
+ ```jsx
20
+ import EmojiPicker from 'emoji-picker-react';
21
+
22
+ function App() {
23
+ return (
24
+ <div>
25
+ <EmojiPicker />
26
+ </div>
27
+ );
28
+ }
29
+ ```
30
+
17
31
  ## Features
18
32
 
19
33
  - Custom click handler
@@ -24,46 +38,47 @@ npm install emoji-picker-react
24
38
  - Different emoji sets (Google, Apple, Facebook, Twitter)
25
39
  - Native Emoji support
26
40
 
27
- ## Config Props
41
+ # Props
42
+
43
+ The following props are accepted by them picker:
28
44
 
29
- - _onEmojiClick_ `(event: MouseEvent, emoji: EmojiClickData) => void` - Callback function when an emoji is clicked. The callback receives the event and the emoji data. The emoji data is comprised of the following properties:
45
+ - `onEmojiClick`: `(emojiData: EmojiClickData, event: MouseEvent) => void` - Callback function when an emoji is clicked. The callback receives the event and the emoji data. The emoji data is comprised of the following properties:
30
46
 
31
- ```ts{
32
- activeSkinTone: SkinTones;
33
- unified: string;
34
- unifiedWithoutSkinTone: string;
35
- emoji: string;
36
- names: string[];
37
- getImageUrl: (emojiStyle: EmojiStyle) => string;
47
+ ```ts
48
+ {
49
+ activeSkinTone: SkinTones;
50
+ unified: string;
51
+ unifiedWithoutSkinTone: string;
52
+ emoji: string;
53
+ names: string[];
54
+ getImageUrl: (emojiStyle: EmojiStyle) => string;
38
55
  }
39
56
  ```
40
57
 
41
- - _theme_ `Theme` - The theme of the picker. Can be either `light` or `dark`. Default is `light`.
58
+ - `theme`: `Theme` - The theme of the picker. Can be `light`, `dark` or auto. Default is `light`.
42
59
  The `Theme` enum can be imported from the package.
43
60
 
44
61
  ```ts
45
62
  import { Theme } from 'emoji-picker-react';
46
63
  ```
47
64
 
48
- - _emojiStyle_ `EmojiStyle` - The emoji style to use. Can be either `apple`, `google`, `facebook`, `twitter` or `native`. Default is `apple`.
65
+ - `emojiStyle`: `EmojiStyle` - The emoji style to use. Can be either `apple`, `google`, `facebook`, `twitter` or `native`. Default is `apple`.
49
66
  The `EmojiStyle` enum can be imported from the package.
50
67
 
51
68
  ```ts
52
69
  import { EmojiStyle } from 'emoji-picker-react';
53
70
  ```
54
71
 
55
- * _autoFocusSearch_: `boolean` - Whether to focus the search input on mount. Defaults to `true`.
72
+ * `autoFocusSearch`: `boolean` - Whether to focus the search input on mount. Defaults to `true`.
56
73
 
57
- * _defaultSkinTone_: `SkinTones` - The default skin tone to use when an emoji is clicked. Defaults to `SkinTones.Neutral`. Possible skin tones are:
74
+ * `defaultSkinTone`: `SkinTones` - The default skin tone to use when an emoji is clicked. Defaults to `SkinTones.Neutral`. Possible skin tones are:
58
75
 
59
- ```
60
- ✋ NEUTRAL = 'neutral'
61
- ✋🏻 LIGHT = '1f3fb'
62
- ✋🏼 MEDIUM_LIGHT = '1f3fc'
63
- ✋🏽 MEDIUM = '1f3fd'
64
- ✋🏾 MEDIUM_DARK = '1f3fe'
65
- ✋🏿 DARK = '1f3ff'
66
- ```
76
+ - ✋ 'neutral'
77
+ - ✋🏻 '1f3fb'
78
+ - ✋🏼 '1f3fc'
79
+ - ✋🏽 '1f3fd'
80
+ - ✋🏾 '1f3fe'
81
+ - ✋🏿 '1f3ff'
67
82
 
68
83
  The skin tones typescript enum can be imported directly from the package:
69
84
 
@@ -71,35 +86,63 @@ The skin tones typescript enum can be imported directly from the package:
71
86
  import { SkinTones } from 'emoji-picker-react';
72
87
  ```
73
88
 
74
- - _skinTonesDisabled_: `boolean` - Whether to disable the skin tone selection. Defaults to `false`.
89
+ - `skinTonesDisabled`: `boolean` - Whether to disable the skin tone selection. Defaults to `false`.
75
90
 
76
- - _showPreview_: `boolean` - Whether to show the preview of the selected emoji. Defaults to `true`.
91
+ - `showPreview`: `boolean` - Whether to show the preview of the selected emoji. Defaults to `true`.
77
92
 
78
- - _searchPlaceholder_: `string` - The placeholder text for the search input. Defaults to `Search`.
93
+ - `searchPlaceholder`: `string` - The placeholder text for the search input. Defaults to `Search`.
79
94
 
80
95
  - categories: Allows full config over ordering, naming and display of categories.
81
96
  To only sort/omit categories, you can simply pass an array of category names to display:
82
97
 
83
- ```
84
- RECENTLY_USED = 'recently_used',
85
- SMILEYS_PEOPLE = 'smileys_people',
86
- ANIMALS_NATURE = 'animals_nature',
87
- FOOD_DRINK = 'food_drink',
88
- TRAVEL_PLACES = 'travel_places',
89
- ACTIVITIES = 'activities',
90
- OBJECTS = 'objects',
91
- SYMBOLS = 'symbols',
92
- FLAGS = 'flags'
98
+ - 'recently_used',
99
+ - 'smileys_people',
100
+ - 'animals_nature',
101
+ - 'food_drink',
102
+ - 'travel_places',
103
+ - 'activities',
104
+ - 'objects',
105
+ - 'symbols',
106
+ - 'flags'
107
+
108
+ For a more in-depth configuration, you can pass an array with category config:
109
+
110
+ ```ts
111
+ [
112
+ {
113
+ category: 'recently_used',
114
+ name: 'Recently Used'
115
+ },
116
+ {
117
+ category: 'smileys_people',
118
+ name: 'Faces...'
119
+ }
120
+ ];
121
+ ```
122
+
123
+ # Troubleshooting
124
+
125
+ ## Next.js
126
+
127
+ To avoid errors such as "document is not defined" on the server side, you should make sure the library is only imported on the client side. Here is how to do that:
128
+
129
+ ```javascript
130
+ import dynamic from 'next/dynamic';
131
+
132
+ const Picker = dynamic(
133
+ () => {
134
+ return import('emoji-picker-react');
135
+ },
136
+ { ssr: false }
137
+ );
93
138
  ```
94
139
 
95
- For a more in-depth configuration, you can pass an array with category config:
140
+ ## Vite
96
141
 
97
- ```ts
98
- [{
99
- category: Categories.RECENTLY_USED;
100
- name: "Recently Used";
101
- }, {
102
- category: Categories.SMILEYS_PEOPLE;
103
- name: "Faces...";
104
- }]
142
+ For reference, if you only need to shim global, you can add
143
+
144
+ ```html
145
+ <script>
146
+ window.global = window;
147
+ </script>
105
148
  ```
@@ -0,0 +1 @@
1
+ export declare function isSystemDarkTheme(): boolean;
@@ -16,6 +16,7 @@ export declare function useEmojisThatFailedToLoadState(): ReactState<Set<string>
16
16
  export declare function useIsPastInitialLoad(): boolean;
17
17
  export declare function useEmojiVariationPickerState(): ReactState<DataEmoji | null>;
18
18
  export declare function useSkinToneFanOpenState(): ReactState<boolean>;
19
+ export declare function useUpdateRecentlyUsed(): [number, () => void];
19
20
  export declare type FilterState = Record<string, FilterDict>;
20
21
  declare type ActiveCategoryState = null | string;
21
22
  export {};
@@ -7,7 +7,7 @@ export declare function mergeConfig(userConfig?: PickerConfig): {
7
7
  skinTonesDisabled: boolean;
8
8
  autoFocusSearch: boolean;
9
9
  emojiStyle: EmojiStyle;
10
- onEmojiClick: (event: MouseEvent, emoji: EmojiClickData) => void;
10
+ onEmojiClick: (emoji: EmojiClickData, event: MouseEvent) => void;
11
11
  showPreview: boolean;
12
12
  theme: Theme;
13
13
  };
@@ -19,7 +19,7 @@ export declare type PickerConfigInternal = {
19
19
  autoFocusSearch: boolean;
20
20
  emojiStyle: EmojiStyle;
21
21
  categories: CategoriesConfig;
22
- onEmojiClick: (event: MouseEvent, emoji: EmojiClickData) => void;
22
+ onEmojiClick: (emoji: EmojiClickData, event: MouseEvent) => void;
23
23
  showPreview: boolean;
24
24
  theme: Theme;
25
25
  };
@@ -1,4 +1,4 @@
1
- import { EmojiClickData, EmojiStyle, SkinTones } from '../types/exposedTypes';
1
+ import { EmojiClickData, EmojiStyle, SkinTones, Theme } from '../types/exposedTypes';
2
2
  import { CategoriesConfig } from './categoryConfig';
3
3
  export declare function useSearchPlaceHolderConfig(): string;
4
4
  export declare function useDefaultSkinToneConfig(): SkinTones;
@@ -6,6 +6,6 @@ export declare function useSkinTonesDisabledConfig(): boolean;
6
6
  export declare function useEmojiStyleConfig(): EmojiStyle;
7
7
  export declare function useAutoFocusSearchConfig(): boolean;
8
8
  export declare function useCategoriesConfig(): CategoriesConfig;
9
- export declare function useOnEmojiClickConfig(): (event: MouseEvent, emoji: EmojiClickData) => void;
9
+ export declare function useOnEmojiClickConfig(): (emoji: EmojiClickData, event: MouseEvent) => void;
10
10
  export declare function useShowPreviewConfig(): boolean;
11
- export declare function useThemeConfig(): string;
11
+ export declare function useThemeConfig(): Theme;
@@ -200,8 +200,8 @@ function basePickerConfig() {
200
200
  defaultSkinTone: exports.SkinTones.NEUTRAL,
201
201
  emojiStyle: exports.EmojiStyle.APPLE,
202
202
  onEmojiClick: function defaultOnClickHandler( // @ts-ignore
203
- event, // @ts-ignore
204
- emoji) {},
203
+ emoji, // @ts-ignore
204
+ event) {},
205
205
  searchPlaceHolder: 'Search',
206
206
  showPreview: true,
207
207
  skinTonesDisabled: false,
@@ -223,6 +223,14 @@ function usePickerConfig() {
223
223
  return React.useContext(ConfigContext);
224
224
  }
225
225
 
226
+ function isSystemDarkTheme() {
227
+ if (typeof window === 'undefined') {
228
+ return false;
229
+ }
230
+
231
+ return !!window.matchMedia('(prefers-color-scheme: dark)').matches;
232
+ }
233
+
226
234
  function useSearchPlaceHolderConfig() {
227
235
  var _usePickerConfig = usePickerConfig(),
228
236
  searchPlaceHolder = _usePickerConfig.searchPlaceHolder;
@@ -275,6 +283,10 @@ function useThemeConfig() {
275
283
  var _usePickerConfig9 = usePickerConfig(),
276
284
  theme = _usePickerConfig9.theme;
277
285
 
286
+ if (theme === exports.Theme.AUTO) {
287
+ return isSystemDarkTheme() ? exports.Theme.DARK : exports.Theme.LIGHT;
288
+ }
289
+
278
290
  return theme;
279
291
  }
280
292
 
@@ -15474,6 +15486,7 @@ function PickerContextProvider(_ref) {
15474
15486
 
15475
15487
  var filterRef = React.useRef(alphaNumericEmojiIndex);
15476
15488
  var disallowClickRef = React.useRef(false);
15489
+ var recentlyUsedUpdateState = useDebouncedState(Date.now(), 250);
15477
15490
  var searchTerm = useDebouncedState('', 100);
15478
15491
  var skinToneFanOpenState = React.useState(false);
15479
15492
  var activeSkinTone = React.useState(defaultSkinTone);
@@ -15488,6 +15501,7 @@ function PickerContextProvider(_ref) {
15488
15501
  useMarkInitialLoad(setIsPastInitialLoad);
15489
15502
  return React.createElement(PickerContext.Provider, {
15490
15503
  value: {
15504
+ recentlyUsedUpdateState: recentlyUsedUpdateState,
15491
15505
  filterRef: filterRef,
15492
15506
  searchTerm: searchTerm,
15493
15507
  activeCategoryState: activeCategoryState,
@@ -15501,6 +15515,7 @@ function PickerContextProvider(_ref) {
15501
15515
  }, children);
15502
15516
  }
15503
15517
  var PickerContext = /*#__PURE__*/React.createContext({
15518
+ recentlyUsedUpdateState: [/*#__PURE__*/Date.now(), function () {}],
15504
15519
  searchTerm: ['', function () {}],
15505
15520
  activeCategoryState: [null, function () {}],
15506
15521
  activeSkinTone: [exports.SkinTones.NEUTRAL, function () {}],
@@ -15581,6 +15596,16 @@ function useSkinToneFanOpenState() {
15581
15596
 
15582
15597
  return skinToneFanOpenState;
15583
15598
  }
15599
+ function useUpdateRecentlyUsed() {
15600
+ var _React$useContext10 = React.useContext(PickerContext),
15601
+ recentlyUsedUpdateState = _React$useContext10.recentlyUsedUpdateState;
15602
+
15603
+ var recentlyUsedUpdated = recentlyUsedUpdateState[0],
15604
+ setRecentlyUsedUpdate = recentlyUsedUpdateState[1];
15605
+ return [recentlyUsedUpdated, function updateRecentlyUsed() {
15606
+ setRecentlyUsedUpdate(Date.now());
15607
+ }];
15608
+ }
15584
15609
 
15585
15610
  function useActiveCategoryScrollDetection(bodyRef) {
15586
15611
  var _useActiveCategorySta = useActiveCategoryState(),
@@ -15755,11 +15780,9 @@ function setRecentlyUsed(emoji, skinTone) {
15755
15780
  nextList.length = Math.min(nextList.length, 14);
15756
15781
 
15757
15782
  try {
15758
- setTimeout(function () {
15759
- var _window3;
15783
+ var _window3;
15760
15784
 
15761
- (_window3 = window) == null ? void 0 : _window3.localStorage.setItem(RECENTLY_USED_LS_KEY, JSON.stringify(nextList)); // Prevents the change from being seen immediately.
15762
- }, 10);
15785
+ (_window3 = window) == null ? void 0 : _window3.localStorage.setItem(RECENTLY_USED_LS_KEY, JSON.stringify(nextList)); // Prevents the change from being seen immediately.
15763
15786
  } catch (_unused2) {// ignore
15764
15787
  }
15765
15788
  }
@@ -15826,6 +15849,10 @@ function useMouseDownHandlers(BodyRef) {
15826
15849
 
15827
15850
  var onEmojiClick = useOnEmojiClickConfig();
15828
15851
  var emojiStyle = useEmojiStyleConfig();
15852
+
15853
+ var _useUpdateRecentlyUse = useUpdateRecentlyUsed(),
15854
+ updateRecentlyUsed = _useUpdateRecentlyUse[1];
15855
+
15829
15856
  React.useEffect(function () {
15830
15857
  if (!BodyRef.current) {
15831
15858
  return;
@@ -15862,8 +15889,9 @@ function useMouseDownHandlers(BodyRef) {
15862
15889
 
15863
15890
  var unified = emojiUnified(emoji);
15864
15891
  var skinToneToUse = activeVariationFromUnified(unified) || activeSkinTone;
15892
+ updateRecentlyUsed();
15865
15893
  setRecentlyUsed(emoji, skinToneToUse);
15866
- onEmojiClick(event, emojiClickOutput(emoji, skinToneToUse));
15894
+ onEmojiClick(emojiClickOutput(emoji, skinToneToUse), event);
15867
15895
  }
15868
15896
 
15869
15897
  function onMouseDown(event) {
@@ -15892,7 +15920,7 @@ function useMouseDownHandlers(BodyRef) {
15892
15920
  closeAllOpenToggles();
15893
15921
  setAnchoredEmojiRef(event.target);
15894
15922
  setEmojiVariationPicker(emoji);
15895
- }, 250);
15923
+ }, 500);
15896
15924
  }
15897
15925
 
15898
15926
  function onMouseUp() {
@@ -16252,10 +16280,15 @@ function EmojiCategory(_ref) {
16252
16280
  function RecentlyUsed(_ref) {
16253
16281
  var categoryConfig = _ref.categoryConfig;
16254
16282
 
16283
+ var _useUpdateRecentlyUse = useUpdateRecentlyUsed(),
16284
+ recentlyUsedUpdated = _useUpdateRecentlyUse[0];
16285
+
16255
16286
  var _useSearchTermState = useSearchTermState(),
16256
16287
  searchTerm = _useSearchTermState[0];
16257
16288
 
16258
- var recentlyUsed = getRecentlyUsed();
16289
+ var recentlyUsed = React.useMemo(function () {
16290
+ return getRecentlyUsed();
16291
+ }, [recentlyUsedUpdated]);
16259
16292
  var emojiStyle = useEmojiStyleConfig();
16260
16293
 
16261
16294
  if (searchTerm) {