emoji-picker-react 4.2.0 → 4.4.0-rc.1

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.
@@ -0,0 +1 @@
1
+ export default function isFunction(value: any): value is (...args: any[]) => any;
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "4.2.0",
2
+ "version": "4.4.0-rc.1",
3
3
  "license": "MIT",
4
4
  "main": "dist/index.js",
5
5
  "typings": "dist/index.d.ts",
@@ -37,15 +37,15 @@ function PickerRootElement({ children }: RootProps) {
37
37
  useOnFocus();
38
38
 
39
39
  const style = {
40
- height: `${height}px`,
41
- width: `${width}px`,
40
+ height,
41
+ width
42
42
  };
43
43
 
44
44
  return (
45
45
  <aside
46
46
  className={clsx(ClassNames.emojiPicker, 'epr-main', {
47
47
  [ClassNames.searchActive]: searchModeActive,
48
- 'epr-dark-theme': theme === Theme.DARK,
48
+ 'epr-dark-theme': theme === Theme.DARK
49
49
  })}
50
50
  ref={PickerMainRef}
51
51
  style={style}
@@ -1,17 +1,18 @@
1
1
  import { GetEmojiUrl } from '../components/emoji/Emoji';
2
+ import { DataEmoji } from '../dataUtils/DataTypes';
2
3
  import { emojiUrlByUnified } from '../dataUtils/emojiSelectors';
3
4
  import {
4
5
  EmojiClickData,
5
6
  EmojiStyle,
6
7
  SkinTones,
7
8
  SuggestionMode,
8
- Theme,
9
+ Theme
9
10
  } from '../types/exposedTypes';
10
11
 
11
12
  import {
12
13
  CategoriesConfig,
13
14
  baseCategoriesConfig,
14
- mergeCategoriesConfig,
15
+ mergeCategoriesConfig
15
16
  } from './categoryConfig';
16
17
 
17
18
  export function mergeConfig(
@@ -26,13 +27,13 @@ export function mergeConfig(
26
27
  const config = Object.assign(base, userConfig);
27
28
 
28
29
  const categories = mergeCategoriesConfig(userConfig.categories, {
29
- suggestionMode: config.suggestedEmojisMode,
30
+ suggestionMode: config.suggestedEmojisMode
30
31
  });
31
32
 
32
33
  return {
33
34
  ...config,
34
35
  categories,
35
- previewConfig,
36
+ previewConfig
36
37
  };
37
38
  }
38
39
 
@@ -55,13 +56,14 @@ export function basePickerConfig(): PickerConfigInternal {
55
56
  event: MouseEvent
56
57
  ) {},
57
58
  previewConfig: {
58
- ...basePreviewConfig,
59
+ ...basePreviewConfig
59
60
  },
60
61
  searchPlaceHolder: 'Search',
62
+ showEmoji: undefined,
61
63
  skinTonesDisabled: false,
62
64
  suggestedEmojisMode: SuggestionMode.FREQUENT,
63
65
  theme: Theme.LIGHT,
64
- width: 350,
66
+ width: 350
65
67
  };
66
68
  }
67
69
 
@@ -78,9 +80,10 @@ export type PickerConfigInternal = {
78
80
  suggestedEmojisMode: SuggestionMode;
79
81
  lazyLoadEmojis: boolean;
80
82
  previewConfig: PreviewConfig;
81
- height: number;
82
- width: number;
83
+ height: PickerDimensions;
84
+ width: PickerDimensions;
83
85
  getEmojiUrl: GetEmojiUrl;
86
+ showEmoji: undefined | ((emoji: DataEmoji) => boolean);
84
87
  };
85
88
 
86
89
  export type PreviewConfig = {
@@ -92,7 +95,7 @@ export type PreviewConfig = {
92
95
  const basePreviewConfig: PreviewConfig = {
93
96
  defaultEmoji: '1f60a',
94
97
  defaultCaption: "What's your mood?",
95
- showPreview: true,
98
+ showPreview: true
96
99
  };
97
100
 
98
101
  type ConfigExternal = {
@@ -100,3 +103,5 @@ type ConfigExternal = {
100
103
  } & Omit<PickerConfigInternal, 'previewConfig'>;
101
104
 
102
105
  export type PickerConfig = Partial<ConfigExternal>;
106
+
107
+ export type PickerDimensions = string | number;
@@ -1,15 +1,16 @@
1
1
  import { isSystemDarkTheme } from '../DomUtils/isDarkTheme';
2
2
  import { usePickerConfig } from '../components/context/PickerConfigContext';
3
+ import { DataEmoji } from '../dataUtils/DataTypes';
3
4
  import {
4
5
  EmojiClickData,
5
6
  EmojiStyle,
6
7
  SkinTones,
7
8
  SuggestionMode,
8
- Theme,
9
+ Theme
9
10
  } from '../types/exposedTypes';
10
11
 
11
12
  import { CategoriesConfig } from './categoryConfig';
12
- import { PreviewConfig } from './config';
13
+ import { PickerDimensions, PreviewConfig } from './config';
13
14
 
14
15
  export function useSearchPlaceHolderConfig(): string {
15
16
  const { searchPlaceHolder } = usePickerConfig();
@@ -74,9 +75,12 @@ export function useLazyLoadEmojisConfig(): boolean {
74
75
  return lazyLoadEmojis;
75
76
  }
76
77
 
77
- export function usePickerSizeConfig(): { height: number; width: number } {
78
+ export function usePickerSizeConfig(): {
79
+ height: PickerDimensions;
80
+ width: PickerDimensions;
81
+ } {
78
82
  const { height, width } = usePickerConfig();
79
- return { height, width };
83
+ return { height: getDimension(height), width: getDimension(width) };
80
84
  }
81
85
 
82
86
  export function useEmojiVersionConfig(): string | null {
@@ -91,3 +95,16 @@ export function useGetEmojiUrlConfig(): (
91
95
  const { getEmojiUrl } = usePickerConfig();
92
96
  return getEmojiUrl;
93
97
  }
98
+
99
+ export function useShowEmojiConfig():
100
+ | undefined
101
+ | ((emoji: DataEmoji) => boolean) {
102
+ const { showEmoji } = usePickerConfig();
103
+ return showEmoji;
104
+ }
105
+
106
+ function getDimension(dimensionConfig: PickerDimensions): PickerDimensions {
107
+ return typeof dimensionConfig === 'number'
108
+ ? `${dimensionConfig}px`
109
+ : dimensionConfig;
110
+ }
@@ -1,28 +1,41 @@
1
1
  import { useRef, useMemo } from 'react';
2
2
 
3
- import { useEmojiVersionConfig } from '../config/useConfig';
3
+ import { useEmojiVersionConfig, useShowEmojiConfig } from '../config/useConfig';
4
4
  import { DataEmoji } from '../dataUtils/DataTypes';
5
5
  import { addedIn, allEmojis, emojiUnified } from '../dataUtils/emojiSelectors';
6
+ import isFunction from '../predicates/isFunction';
6
7
 
7
8
  export function useDisallowedEmojis() {
8
9
  const DisallowedEmojisRef = useRef<Record<string, boolean>>({});
9
10
  const emojiVersionConfig = useEmojiVersionConfig();
11
+ const shouldShowEmoji = useShowEmojiConfig();
10
12
 
11
13
  return useMemo(() => {
12
14
  const emojiVersion = parseFloat(`${emojiVersionConfig}`);
13
15
 
14
- if (!emojiVersionConfig || Number.isNaN(emojiVersion)) {
16
+ if (
17
+ (!emojiVersionConfig || Number.isNaN(emojiVersion)) &&
18
+ !shouldShowEmoji
19
+ ) {
15
20
  return DisallowedEmojisRef.current;
16
21
  }
17
22
 
18
23
  return allEmojis.reduce((disallowedEmojis, emoji) => {
24
+ if (isFunction(shouldShowEmoji) && !shouldShowEmoji(emoji)) {
25
+ disallowEmoji();
26
+ }
27
+
19
28
  if (addedInNewerVersion(emoji, emojiVersion)) {
20
- disallowedEmojis[emojiUnified(emoji)] = true;
29
+ disallowEmoji();
21
30
  }
22
31
 
23
32
  return disallowedEmojis;
33
+
34
+ function disallowEmoji() {
35
+ disallowedEmojis[emojiUnified(emoji)] = true;
36
+ }
24
37
  }, DisallowedEmojisRef.current);
25
- }, [emojiVersionConfig]);
38
+ }, [emojiVersionConfig, shouldShowEmoji]);
26
39
  }
27
40
 
28
41
  function addedInNewerVersion(
@@ -1,15 +1,16 @@
1
1
  import { scrollTo } from '../DomUtils/scrollTo';
2
2
  import {
3
3
  usePickerMainRef,
4
- useSearchInputRef,
4
+ useSearchInputRef
5
5
  } from '../components/context/ElementRefContext';
6
6
  import {
7
7
  FilterState,
8
8
  useFilterRef,
9
- useSearchTermState,
9
+ useSearchTermState
10
10
  } from '../components/context/PickerContext';
11
11
  import { DataEmoji } from '../dataUtils/DataTypes';
12
12
  import { emojiNames } from '../dataUtils/emojiSelectors';
13
+ import isFunction from '../predicates/isFunction';
13
14
 
14
15
  import { useFocusSearchInput } from './useFocus';
15
16
 
@@ -19,7 +20,7 @@ function useSetFilterRef() {
19
20
  return function setFilter(
20
21
  setter: FilterState | ((current: FilterState) => FilterState)
21
22
  ): void {
22
- if (typeof setter === 'function') {
23
+ if (isFunction(setter)) {
23
24
  return setFilter(setter(filterRef.current));
24
25
  }
25
26
 
@@ -67,7 +68,7 @@ export function useFilter() {
67
68
  return {
68
69
  onChange,
69
70
  searchTerm,
70
- SearchInputRef,
71
+ SearchInputRef
71
72
  };
72
73
 
73
74
  function onChange(inputValue: string) {
@@ -87,9 +88,9 @@ export function useFilter() {
87
88
  return applySearch(nextValue);
88
89
  }
89
90
 
90
- setFilterRef((current) =>
91
+ setFilterRef(current =>
91
92
  Object.assign(current, {
92
- [nextValue]: filterEmojiObjectByKeyword(longestMatch, nextValue),
93
+ [nextValue]: filterEmojiObjectByKeyword(longestMatch, nextValue)
93
94
  })
94
95
  );
95
96
  applySearch(nextValue);
@@ -129,14 +130,14 @@ function filterEmojiObjectByKeyword(
129
130
  }
130
131
 
131
132
  function hasMatch(emoji: DataEmoji, keyword: string): boolean {
132
- return emojiNames(emoji).some((name) => name.includes(keyword));
133
+ return emojiNames(emoji).some(name => name.includes(keyword));
133
134
  }
134
135
 
135
136
  export function useIsEmojiFiltered(): (unified: string) => boolean {
136
137
  const { current: filter } = useFilterRef();
137
138
  const [searchTerm] = useSearchTermState();
138
139
 
139
- return (unified) => isEmojiFilteredBySearchTerm(unified, filter, searchTerm);
140
+ return unified => isEmojiFilteredBySearchTerm(unified, filter, searchTerm);
140
141
  }
141
142
 
142
143
  function isEmojiFilteredBySearchTerm(
@@ -167,7 +168,7 @@ function findLongestMatch(
167
168
 
168
169
  const longestMatchingKey = Object.keys(dict)
169
170
  .sort((a, b) => b.length - a.length)
170
- .find((key) => keyword.includes(key));
171
+ .find(key => keyword.includes(key));
171
172
 
172
173
  if (longestMatchingKey) {
173
174
  return dict[longestMatchingKey];
@@ -0,0 +1,5 @@
1
+ export default function isFunction(
2
+ value: any
3
+ ): value is (...args: any[]) => any {
4
+ return typeof value === 'function';
5
+ }