emoji-picker-react 4.0.0-rc.9 → 4.0.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 (117) hide show
  1. package/README.md +176 -43
  2. package/dist/DomUtils/classNames.d.ts +9 -1
  3. package/dist/DomUtils/elementPositionInRow.d.ts +10 -0
  4. package/dist/DomUtils/focusElement.d.ts +5 -0
  5. package/dist/DomUtils/getActiveElement.d.ts +2 -0
  6. package/dist/DomUtils/isDarkTheme.d.ts +1 -0
  7. package/dist/DomUtils/keyboardNavigation.d.ts +8 -0
  8. package/dist/DomUtils/scrollTo.d.ts +3 -1
  9. package/dist/DomUtils/selectors.d.ts +24 -11
  10. package/dist/EmojiPickerReact.d.ts +6 -0
  11. package/dist/components/ErrorBoundary.d.ts +15 -0
  12. package/dist/components/body/{RecentlyUsed.d.ts → Suggested.d.ts} +1 -1
  13. package/dist/components/context/ElementRefContext.d.ts +10 -13
  14. package/dist/components/context/PickerContext.d.ts +3 -3
  15. package/dist/components/emoji/Emoji.d.ts +11 -7
  16. package/dist/components/emoji/ExportedEmoji.d.ts +8 -0
  17. package/dist/components/footer/Preview.d.ts +1 -1
  18. package/dist/config/categoryConfig.d.ts +7 -3
  19. package/dist/config/config.d.ts +18 -15
  20. package/dist/config/useConfig.d.ts +11 -4
  21. package/dist/data/skinToneVariations.d.ts +2 -0
  22. package/dist/dataUtils/emojiSelectors.d.ts +3 -2
  23. package/dist/dataUtils/suggested.d.ts +11 -0
  24. package/dist/emoji-picker-react.cjs.development.css +9 -9
  25. package/dist/emoji-picker-react.cjs.development.js +3771 -3068
  26. package/dist/emoji-picker-react.cjs.development.js.map +1 -1
  27. package/dist/emoji-picker-react.cjs.production.min.js +1 -1
  28. package/dist/emoji-picker-react.cjs.production.min.js.map +1 -1
  29. package/dist/emoji-picker-react.esm.js +3781 -3078
  30. package/dist/emoji-picker-react.esm.js.map +1 -1
  31. package/dist/hooks/preloadEmoji.d.ts +1 -1
  32. package/dist/hooks/useActiveCategoryScrollDetection.d.ts +1 -2
  33. package/dist/hooks/useCloseAllOpenToggles.d.ts +2 -4
  34. package/dist/hooks/useDebouncedState.d.ts +1 -1
  35. package/dist/hooks/useDisallowMouseMove.d.ts +4 -0
  36. package/dist/hooks/useEmojiPreviewEvents.d.ts +3 -0
  37. package/dist/hooks/useFilter.d.ts +3 -3
  38. package/dist/hooks/useFocus.d.ts +3 -0
  39. package/dist/hooks/useInitialLoad.d.ts +1 -1
  40. package/dist/hooks/useIsEmojiHidden.d.ts +7 -1
  41. package/dist/hooks/useKeyboardNavigation.d.ts +1 -0
  42. package/dist/hooks/useMouseDownHandlers.d.ts +3 -2
  43. package/dist/hooks/useOnFocus.d.ts +1 -0
  44. package/dist/hooks/useScrollCategoryIntoView.d.ts +1 -0
  45. package/dist/hooks/useSetVariationPicker.d.ts +2 -0
  46. package/dist/index.d.ts +2 -2
  47. package/dist/types/exposedTypes.d.ts +5 -1
  48. package/package.json +13 -5
  49. package/src/DomUtils/classNames.ts +12 -1
  50. package/src/DomUtils/elementPositionInRow.ts +167 -0
  51. package/src/DomUtils/focusElement.ts +35 -0
  52. package/src/DomUtils/getActiveElement.ts +5 -0
  53. package/src/DomUtils/isDarkTheme.ts +7 -0
  54. package/src/DomUtils/keyboardNavigation.ts +161 -0
  55. package/src/DomUtils/scrollTo.ts +22 -1
  56. package/src/DomUtils/selectors.ts +200 -41
  57. package/src/EmojiPickerReact.css +99 -48
  58. package/src/EmojiPickerReact.tsx +26 -0
  59. package/src/components/ErrorBoundary.tsx +28 -0
  60. package/src/components/body/Body.tsx +3 -2
  61. package/src/components/body/EmojiCategory.css +14 -28
  62. package/src/components/body/EmojiCategory.tsx +5 -4
  63. package/src/components/body/EmojiList.tsx +13 -13
  64. package/src/components/body/EmojiVariationPicker.css +13 -5
  65. package/src/components/body/EmojiVariationPicker.tsx +25 -17
  66. package/src/components/body/Suggested.tsx +54 -0
  67. package/src/components/context/ElementRefContext.tsx +54 -19
  68. package/src/components/context/PickerContext.tsx +36 -33
  69. package/src/components/emoji/Emoji.css +42 -12
  70. package/src/components/emoji/Emoji.tsx +73 -34
  71. package/src/components/emoji/ExportedEmoji.tsx +30 -0
  72. package/src/components/footer/Preview.css +1 -1
  73. package/src/components/footer/Preview.tsx +16 -23
  74. package/src/components/header/Search.css +7 -7
  75. package/src/components/header/Search.tsx +31 -7
  76. package/src/components/header/SkinTonePicker.css +15 -8
  77. package/src/components/header/SkinTonePicker.tsx +23 -5
  78. package/src/components/main/PickerMain.css +0 -2
  79. package/src/components/main/PickerMain.tsx +14 -1
  80. package/src/components/navigation/CategoryNavigation.css +41 -10
  81. package/src/components/navigation/CategoryNavigation.tsx +22 -10
  82. package/src/components/navigation/svg/CategoryNav.svg +343 -379
  83. package/src/config/categoryConfig.ts +40 -14
  84. package/src/config/config.ts +59 -13
  85. package/src/config/useConfig.ts +35 -7
  86. package/src/data/emojis.json +1 -1
  87. package/src/data/skinToneVariations.ts +19 -0
  88. package/src/dataUtils/emojiSelectors.ts +24 -4
  89. package/src/dataUtils/{recentlyUsed.ts → suggested.ts} +20 -18
  90. package/src/hooks/preloadEmoji.ts +13 -2
  91. package/src/hooks/useActiveCategoryScrollDetection.ts +10 -8
  92. package/src/hooks/useCloseAllOpenToggles.ts +15 -4
  93. package/src/hooks/useDebouncedState.ts +10 -7
  94. package/src/hooks/useDisallowMouseMove.ts +47 -0
  95. package/src/hooks/useEmojiPreviewEvents.ts +103 -0
  96. package/src/hooks/useFilter.ts +46 -47
  97. package/src/hooks/useFocus.ts +40 -0
  98. package/src/hooks/useInitialLoad.ts +1 -0
  99. package/src/hooks/useIsEmojiHidden.ts +16 -3
  100. package/src/hooks/useKeyboardNavigation.ts +438 -0
  101. package/src/hooks/useMouseDownHandlers.ts +97 -89
  102. package/src/hooks/useOnFocus.ts +46 -0
  103. package/src/hooks/useOnScroll.ts +2 -2
  104. package/src/hooks/useScrollCategoryIntoView.ts +28 -0
  105. package/src/hooks/useSetVariationPicker.ts +28 -0
  106. package/src/index.tsx +9 -17
  107. package/src/types/exposedTypes.ts +6 -1
  108. package/dist/DomUtils/emojiElementRef.d.ts +0 -10
  109. package/dist/DomUtils/scrollCategoryIntoView.d.ts +0 -1
  110. package/dist/dataUtils/recentlyUsed.d.ts +0 -11
  111. package/dist/hooks/useEmojiElements.d.ts +0 -1
  112. package/dist/hooks/useEmojiMouseEnter.d.ts +0 -3
  113. package/src/DomUtils/emojiElementRef.ts +0 -42
  114. package/src/DomUtils/scrollCategoryIntoView.ts +0 -18
  115. package/src/components/body/RecentlyUsed.tsx +0 -50
  116. package/src/hooks/useEmojiElements.ts +0 -7
  117. package/src/hooks/useEmojiMouseEnter.ts +0 -59
@@ -5,7 +5,7 @@ import { ElementRef } from '../components/context/ElementRefContext';
5
5
  import { useCloseAllOpenToggles } from './useCloseAllOpenToggles';
6
6
 
7
7
  export function useOnScroll(BodyRef: ElementRef) {
8
- const { closeAllOpenToggles, dependencyArray } = useCloseAllOpenToggles();
8
+ const closeAllOpenToggles = useCloseAllOpenToggles();
9
9
 
10
10
  useEffect(() => {
11
11
  const bodyRef = BodyRef.current;
@@ -24,5 +24,5 @@ export function useOnScroll(BodyRef: ElementRef) {
24
24
  return () => {
25
25
  bodyRef?.removeEventListener('scroll', onScroll);
26
26
  };
27
- }, [...dependencyArray, BodyRef, closeAllOpenToggles]);
27
+ }, [BodyRef, closeAllOpenToggles]);
28
28
  }
@@ -0,0 +1,28 @@
1
+ import { scrollTo } from '../DomUtils/scrollTo';
2
+ import { NullableElement } from '../DomUtils/selectors';
3
+ import {
4
+ useBodyRef,
5
+ usePickerMainRef
6
+ } from '../components/context/ElementRefContext';
7
+
8
+ export function useScrollCategoryIntoView() {
9
+ const BodyRef = useBodyRef();
10
+ const PickerMainRef = usePickerMainRef();
11
+
12
+ return function scrollCategoryIntoView(category: string): void {
13
+ if (!BodyRef.current) {
14
+ return;
15
+ }
16
+ const $category = BodyRef.current?.querySelector(
17
+ `[data-name="${category}"]`
18
+ ) as NullableElement;
19
+
20
+ if (!$category) {
21
+ return;
22
+ }
23
+
24
+ const offsetTop = $category.offsetTop || 0;
25
+
26
+ scrollTo(PickerMainRef.current, offsetTop);
27
+ };
28
+ }
@@ -0,0 +1,28 @@
1
+ import { focusFirstVisibleEmoji } from '../DomUtils/keyboardNavigation';
2
+ import { emojiFromElement, NullableElement } from '../DomUtils/selectors';
3
+ import {
4
+ useSetAnchoredEmojiRef,
5
+ useVariationPickerRef
6
+ } from '../components/context/ElementRefContext';
7
+ import { useEmojiVariationPickerState } from '../components/context/PickerContext';
8
+
9
+ export default function useSetVariationPicker() {
10
+ const setAnchoredEmojiRef = useSetAnchoredEmojiRef();
11
+ const [, setEmojiVariationPicker] = useEmojiVariationPickerState();
12
+ const VariationPickerRef = useVariationPickerRef();
13
+
14
+ return function setVariationPicker(element: NullableElement) {
15
+ const [emoji] = emojiFromElement(element);
16
+
17
+ if (!emoji) {
18
+ return;
19
+ }
20
+
21
+ setAnchoredEmojiRef(element);
22
+ setEmojiVariationPicker(emoji);
23
+
24
+ requestAnimationFrame(() => {
25
+ focusFirstVisibleEmoji(VariationPickerRef.current);
26
+ });
27
+ };
28
+ }
package/src/index.tsx CHANGED
@@ -1,13 +1,11 @@
1
1
  import * as React from 'react';
2
2
 
3
- import { Body } from './components/body/Body';
4
- import { ElementRefContextProvider } from './components/context/ElementRefContext';
5
- import { PickerConfigProvider } from './components/context/PickerConfigContext';
6
- import { Preview } from './components/footer/Preview';
7
- import { Header } from './components/header/Header';
8
- import PickerMain from './components/main/PickerMain';
3
+ import EmojiPickerReact from './EmojiPickerReact';
4
+ import ErrorBoundary from './components/ErrorBoundary';
9
5
  import { PickerConfig } from './config/config';
10
- import './EmojiPickerReact.css';
6
+
7
+ export { ExportedEmoji as Emoji } from './components/emoji/ExportedEmoji';
8
+
11
9
  export {
12
10
  EmojiStyle,
13
11
  SkinTones,
@@ -18,16 +16,10 @@ export {
18
16
 
19
17
  export interface Props extends PickerConfig {}
20
18
 
21
- export function EmojiPicker(props: Props) {
19
+ export default function EmojiPicker(props: Props) {
22
20
  return (
23
- <ElementRefContextProvider>
24
- <PickerConfigProvider {...props}>
25
- <PickerMain>
26
- <Header />
27
- <Body />
28
- <Preview />
29
- </PickerMain>
30
- </PickerConfigProvider>
31
- </ElementRefContextProvider>
21
+ <ErrorBoundary>
22
+ <EmojiPickerReact {...props} />
23
+ </ErrorBoundary>
32
24
  );
33
25
  }
@@ -7,6 +7,11 @@ export type EmojiClickData = {
7
7
  getImageUrl: (emojiStyle: EmojiStyle) => string;
8
8
  };
9
9
 
10
+ export enum SuggestionMode {
11
+ RECENT = 'recent',
12
+ FREQUENT = 'frequent'
13
+ }
14
+
10
15
  export enum EmojiStyle {
11
16
  NATIVE = 'native',
12
17
  APPLE = 'apple',
@@ -31,7 +36,7 @@ export enum SkinTones {
31
36
  }
32
37
 
33
38
  export enum Categories {
34
- RECENTLY_USED = 'recently_used',
39
+ SUGGESTED = 'suggested',
35
40
  SMILEYS_PEOPLE = 'smileys_people',
36
41
  ANIMALS_NATURE = 'animals_nature',
37
42
  FOOD_DRINK = 'food_drink',
@@ -1,10 +0,0 @@
1
- export declare type EmojiRef = {
2
- current: null | HTMLElement;
3
- };
4
- export declare const emojiRef: Record<string, EmojiRef>;
5
- export declare function getEmojiRef(unified: string): EmojiRef;
6
- export declare function iterateEmojiRef(callback: (ref: HTMLElement, unified: string) => void): void;
7
- export declare function hideEmoji(unified: string): void;
8
- export declare function showEmoji(unified: string): void;
9
- export declare function hideElement(element: HTMLElement | null): void;
10
- export declare function showElement(element: HTMLElement | null): void;
@@ -1 +0,0 @@
1
- export declare function scrollCategoryIntoView(root: HTMLElement | null, category: string): void;
@@ -1,11 +0,0 @@
1
- import { SkinTones } from '../types/exposedTypes';
2
- import { DataEmoji } from './DataTypes';
3
- declare type RecentlyUsedItem = {
4
- unified: string;
5
- original: string;
6
- count: number;
7
- };
8
- declare type RecentlyUsed = RecentlyUsedItem[];
9
- export declare function getRecentlyUsed(): RecentlyUsed;
10
- export declare function setRecentlyUsed(emoji: DataEmoji, skinTone: SkinTones): void;
11
- export {};
@@ -1 +0,0 @@
1
- export declare function useEmojiElements(): NodeListOf<Element> | undefined;
@@ -1,3 +0,0 @@
1
- /// <reference types="react" />
2
- import { HoveredEmoji } from '../components/footer/Preview';
3
- export declare function useEmojiMouseEnter(allow: boolean, setHoveredEmoji: React.Dispatch<React.SetStateAction<HoveredEmoji>>): void;
@@ -1,42 +0,0 @@
1
- import { ClassNames } from './classNames';
2
-
3
- export type EmojiRef = { current: null | HTMLElement };
4
-
5
- export const emojiRef: Record<string, EmojiRef> = {};
6
-
7
- export function getEmojiRef(unified: string): EmojiRef {
8
- emojiRef[unified] = emojiRef[unified] || { current: null };
9
- return emojiRef[unified];
10
- }
11
-
12
- export function iterateEmojiRef(
13
- callback: (ref: HTMLElement, unified: string) => void
14
- ): void {
15
- for (const unified in emojiRef) {
16
- if (!emojiRef[unified] || emojiRef[unified].current === null) {
17
- continue;
18
- }
19
-
20
- callback(emojiRef[unified].current as HTMLElement, unified);
21
- }
22
- }
23
-
24
- export function hideEmoji(unified: string): void {
25
- hideElement(getEmojiRef(unified).current);
26
- }
27
-
28
- export function showEmoji(unified: string): void {
29
- showElement(getEmojiRef(unified).current);
30
- }
31
-
32
- export function hideElement(element: HTMLElement | null): void {
33
- if (!element) return;
34
- element.classList.add(ClassNames.hidden);
35
- element.classList.remove(ClassNames.visible);
36
- }
37
-
38
- export function showElement(element: HTMLElement | null): void {
39
- if (!element) return;
40
- element.classList.remove(ClassNames.hidden);
41
- element.classList.add(ClassNames.visible);
42
- }
@@ -1,18 +0,0 @@
1
- import { scrollTo } from './scrollTo';
2
-
3
- export function scrollCategoryIntoView(
4
- root: HTMLElement | null,
5
- category: string
6
- ) {
7
- const $category = root?.querySelector(
8
- `[data-name="${category}"]`
9
- ) as HTMLElement;
10
-
11
- if (!$category) {
12
- return;
13
- }
14
-
15
- const offsetTop = $category.offsetTop || 0;
16
-
17
- scrollTo(root, offsetTop);
18
- }
@@ -1,50 +0,0 @@
1
- import * as React from 'react';
2
-
3
- import { CategoryConfig } from '../../config/categoryConfig';
4
- import { useEmojiStyleConfig } from '../../config/useConfig';
5
- import { emojiByUnified } from '../../dataUtils/emojiSelectors';
6
- import { getRecentlyUsed } from '../../dataUtils/recentlyUsed';
7
- import { useSearchTermState } from '../context/PickerContext';
8
- import { Emoji } from '../emoji/Emoji';
9
-
10
- import { EmojiCategory } from './EmojiCategory';
11
-
12
- type Props = Readonly<{
13
- categoryConfig: CategoryConfig;
14
- }>;
15
-
16
- export function RecentlyUsed({ categoryConfig }: Props) {
17
- const [searchTerm] = useSearchTermState();
18
- const recentlyUsed = getRecentlyUsed();
19
- const emojiStyle = useEmojiStyleConfig();
20
-
21
- if (searchTerm) {
22
- return null;
23
- }
24
-
25
- if (recentlyUsed.length === 0) {
26
- return null;
27
- }
28
-
29
- return (
30
- <EmojiCategory categoryConfig={categoryConfig} hiddenOnSearch>
31
- {recentlyUsed.map(recentlyUsedItem => {
32
- const emoji = emojiByUnified(recentlyUsedItem.original);
33
-
34
- if (!emoji) {
35
- return null;
36
- }
37
-
38
- return (
39
- <Emoji
40
- showVariations={false}
41
- unified={recentlyUsedItem.unified}
42
- emojiStyle={emojiStyle}
43
- emoji={emoji}
44
- key={recentlyUsedItem.unified}
45
- />
46
- );
47
- })}
48
- </EmojiCategory>
49
- );
50
- }
@@ -1,7 +0,0 @@
1
- import { usePickerMainRef } from '../components/context/ElementRefContext';
2
-
3
- export function useEmojiElements() {
4
- const PickerMainRef = usePickerMainRef();
5
-
6
- return PickerMainRef.current?.querySelectorAll('button.epr-emoji');
7
- }
@@ -1,59 +0,0 @@
1
- import { useEffect } from 'react';
2
-
3
- import {
4
- buttonFromEmoji,
5
- originalUnifiedFromEmojiElement,
6
- unifiedFromEmojiElement
7
- } from '../DomUtils/selectors';
8
- import { useBodyRef } from '../components/context/ElementRefContext';
9
- import { HoveredEmoji } from '../components/footer/Preview';
10
-
11
- export function useEmojiMouseEnter(
12
- allow: boolean,
13
- setHoveredEmoji: React.Dispatch<React.SetStateAction<HoveredEmoji>>
14
- ) {
15
- const BodyRef = useBodyRef();
16
-
17
- useEffect(() => {
18
- if (!allow) {
19
- return;
20
- }
21
- const bodyRef = BodyRef.current;
22
-
23
- bodyRef?.addEventListener('mouseover', onMouseOver, {
24
- passive: true
25
- });
26
-
27
- bodyRef?.addEventListener('mouseout', onMouseOut, {
28
- passive: true
29
- });
30
-
31
- return () => {
32
- bodyRef?.removeEventListener('mouseover', onMouseOver);
33
- bodyRef?.removeEventListener('mouseout', onMouseOut);
34
- };
35
- }, [BodyRef.current]);
36
-
37
- function onMouseOver(e: MouseEvent) {
38
- const button = buttonFromEmoji(e.target as HTMLElement);
39
-
40
- if (!button) {
41
- return onMouseOut();
42
- }
43
- const unified = unifiedFromEmojiElement(button);
44
- const originalUnified = originalUnifiedFromEmojiElement(button);
45
-
46
- if (!unified || !originalUnified) {
47
- return onMouseOut();
48
- }
49
-
50
- setHoveredEmoji({
51
- unified,
52
- originalUnified
53
- });
54
- }
55
-
56
- function onMouseOut() {
57
- setHoveredEmoji(null);
58
- }
59
- }