emoji-picker-react 4.6.14 → 4.7.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 (51) hide show
  1. package/README.md +37 -12
  2. package/dist/components/Reactions/BtnPlus.d.ts +2 -0
  3. package/dist/components/Reactions/DEFAULT_REACTIONS.d.ts +1 -0
  4. package/dist/components/Reactions/Reactions.d.ts +2 -0
  5. package/dist/components/context/ElementRefContext.d.ts +1 -0
  6. package/dist/components/context/PickerContext.d.ts +1 -0
  7. package/dist/components/emoji/ClickableEmojiButton.d.ts +2 -1
  8. package/dist/components/emoji/Emoji.d.ts +2 -1
  9. package/dist/components/header/Search/BtnClearSearch.d.ts +2 -0
  10. package/dist/components/header/Search/IcnSearch.d.ts +2 -0
  11. package/dist/components/header/SkinTonePicker/BtnSkinToneVariation.d.ts +11 -0
  12. package/dist/components/navigation/CategoryButton.d.ts +11 -0
  13. package/dist/config/config.d.ts +2 -0
  14. package/dist/config/useConfig.d.ts +2 -0
  15. package/dist/emoji-picker-react.cjs.development.js +1265 -963
  16. package/dist/emoji-picker-react.cjs.development.js.map +1 -1
  17. package/dist/emoji-picker-react.cjs.production.min.js +1 -1
  18. package/dist/emoji-picker-react.cjs.production.min.js.map +1 -1
  19. package/dist/emoji-picker-react.esm.js +1266 -964
  20. package/dist/emoji-picker-react.esm.js.map +1 -1
  21. package/package.json +5 -2
  22. package/src/EmojiPickerReact.tsx +28 -3
  23. package/src/Stylesheet/stylesheet.tsx +14 -2
  24. package/src/components/Reactions/BtnPlus.tsx +78 -0
  25. package/src/components/Reactions/DEFAULT_REACTIONS.ts +9 -0
  26. package/src/components/Reactions/Reactions.tsx +62 -0
  27. package/src/components/Reactions/svg/plus.svg +17 -0
  28. package/src/components/body/Body.tsx +8 -2
  29. package/src/components/body/EmojiVariationPicker.tsx +6 -7
  30. package/src/components/context/ElementRefContext.tsx +10 -2
  31. package/src/components/context/PickerContext.tsx +16 -3
  32. package/src/components/emoji/ClickableEmojiButton.tsx +13 -3
  33. package/src/components/emoji/Emoji.tsx +4 -1
  34. package/src/components/footer/Preview.tsx +11 -8
  35. package/src/components/header/Header.tsx +6 -2
  36. package/src/components/header/Search/BtnClearSearch.tsx +91 -0
  37. package/src/components/header/{CssSearch.tsx → Search/CssSearch.tsx} +2 -2
  38. package/src/components/header/Search/IcnSearch.tsx +39 -0
  39. package/src/components/header/{Search.tsx → Search/Search.tsx} +14 -49
  40. package/src/components/header/SkinTonePicker/BtnSkinToneVariation.tsx +80 -0
  41. package/src/components/header/{SkinTonePicker.tsx → SkinTonePicker/SkinTonePicker.tsx} +25 -67
  42. package/src/components/main/PickerMain.tsx +27 -2
  43. package/src/components/navigation/CategoryButton.tsx +141 -0
  44. package/src/components/navigation/CategoryNavigation.tsx +10 -129
  45. package/src/config/config.ts +7 -2
  46. package/src/config/useConfig.ts +16 -3
  47. /package/dist/components/header/{CssSearch.d.ts → Search/CssSearch.d.ts} +0 -0
  48. /package/dist/components/header/{Search.d.ts → Search/Search.d.ts} +0 -0
  49. /package/dist/components/header/{SkinTonePicker.d.ts → SkinTonePicker/SkinTonePicker.d.ts} +0 -0
  50. /package/src/components/header/{svg → Search/svg}/magnifier.svg +0 -0
  51. /package/src/components/header/{svg → Search/svg}/times.svg +0 -0
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "4.6.14",
2
+ "version": "4.7.0",
3
3
  "license": "MIT",
4
4
  "main": "dist/index.js",
5
5
  "typings": "dist/index.d.ts",
@@ -12,7 +12,10 @@
12
12
  "emoji-picker",
13
13
  "react-emoji-picker",
14
14
  "emoji",
15
- "emojis"
15
+ "emojis",
16
+ "reactions",
17
+ "reactions-picker",
18
+ "emoji-reactions"
16
19
  ],
17
20
  "engines": {
18
21
  "node": ">=10"
@@ -1,8 +1,10 @@
1
1
  import * as React from 'react';
2
2
 
3
+ import { Reactions } from './components/Reactions/Reactions';
3
4
  import { Body } from './components/body/Body';
4
5
  import { ElementRefContextProvider } from './components/context/ElementRefContext';
5
6
  import { PickerConfigProvider } from './components/context/PickerConfigContext';
7
+ import { useReactionsModeState } from './components/context/PickerContext';
6
8
  import { Preview } from './components/footer/Preview';
7
9
  import { Header } from './components/header/Header';
8
10
  import PickerMain from './components/main/PickerMain';
@@ -14,21 +16,44 @@ function EmojiPicker(props: PickerProps) {
14
16
  <ElementRefContextProvider>
15
17
  <PickerConfigProvider {...props}>
16
18
  <PickerMain>
17
- <Header />
18
- <Body />
19
- <Preview />
19
+ <ContentControl />
20
20
  </PickerMain>
21
21
  </PickerConfigProvider>
22
22
  </ElementRefContextProvider>
23
23
  );
24
24
  }
25
25
 
26
+ function ContentControl() {
27
+ const [reactionsDefaultOpen] = useReactionsModeState();
28
+ const [renderAll, setRenderAll] = React.useState(!reactionsDefaultOpen);
29
+
30
+ React.useEffect(() => {
31
+ if (!renderAll) {
32
+ setRenderAll(true);
33
+ }
34
+ }, []);
35
+
36
+ return (
37
+ <>
38
+ <Reactions />
39
+ {renderAll ? (
40
+ <>
41
+ <Header />
42
+ <Body />
43
+ <Preview />
44
+ </>
45
+ ) : null}
46
+ </>
47
+ );
48
+ }
49
+
26
50
  // eslint-disable-next-line complexity
27
51
  export default React.memo(EmojiPicker, (prev, next) => {
28
52
  const prevCustomEmojis = prev.customEmojis ?? [];
29
53
  const nextCustomEmojis = next.customEmojis ?? [];
30
54
  return (
31
55
  prev.emojiVersion === next.emojiVersion &&
56
+ prev.reactionsDefaultOpen === next.reactionsDefaultOpen &&
32
57
  prev.searchPlaceHolder === next.searchPlaceHolder &&
33
58
  prev.searchPlaceholder === next.searchPlaceholder &&
34
59
  prev.defaultSkinTone === next.defaultSkinTone &&
@@ -10,7 +10,8 @@ const hidden = {
10
10
  display: 'none',
11
11
  opacity: '0',
12
12
  pointerEvents: 'none',
13
- visibility: 'hidden'
13
+ visibility: 'hidden',
14
+ overflow: 'hidden'
14
15
  };
15
16
 
16
17
  export const commonStyles = stylesheet.create({
@@ -53,7 +54,18 @@ export const commonInteractionStyles = stylesheet.create({
53
54
  visibleOnSearchOnly: hidden
54
55
  }
55
56
  },
56
-
57
+ hiddenOnReactions: {
58
+ transition: 'all 0.5s ease-in-out'
59
+ },
60
+ '.epr-reactions': {
61
+ hiddenOnReactions: {
62
+ height: '0px',
63
+ width: '0px',
64
+ opacity: '0',
65
+ pointerEvents: 'none',
66
+ overflow: 'hidden'
67
+ }
68
+ },
57
69
  '.EmojiPickerReact:not(.epr-search-active)': {
58
70
  categoryBtn: {
59
71
  ':hover': {
@@ -0,0 +1,78 @@
1
+ import { cx } from 'flairup';
2
+ import * as React from 'react';
3
+
4
+ import { stylesheet } from '../../Stylesheet/stylesheet';
5
+ import { Button } from '../atoms/Button';
6
+ import { useReactionsModeState } from '../context/PickerContext';
7
+
8
+ import Plus from './svg/plus.svg';
9
+
10
+ export function BtnPlus() {
11
+ const [, setReactionsMode] = useReactionsModeState();
12
+ return (
13
+ <Button
14
+ aria-label="Show all Emojis"
15
+ title="Show all Emojis"
16
+ tabIndex={0}
17
+ className={cx(styles.plusSign)}
18
+ onClick={() => setReactionsMode(false)}
19
+ />
20
+ );
21
+ }
22
+
23
+ const styles = stylesheet.create({
24
+ plusSign: {
25
+ fontSize: '20px',
26
+ padding: '18px',
27
+ color: 'var(--epr-text-color)',
28
+ borderRadius: '50%',
29
+ textAlign: 'center',
30
+ lineHeight: '100%',
31
+ width: '20px',
32
+ height: '20px',
33
+ display: 'flex',
34
+ justifyContent: 'center',
35
+ alignItems: 'center',
36
+ transition: 'background-color 0.1s ease-in-out',
37
+ ':after': {
38
+ content: '',
39
+ minWidth: '20px',
40
+ minHeight: '20px',
41
+ backgroundImage: `url(${Plus})`,
42
+ backgroundColor: 'transparent',
43
+ backgroundRepeat: 'no-repeat',
44
+ backgroundSize: '20px',
45
+ backgroundPositionY: '0'
46
+ },
47
+ ':hover': {
48
+ color: 'var(--epr-highlight-color)',
49
+ backgroundColor: 'var(--epr-hover-bg-color)',
50
+ // @ts-ignore
51
+ ':after': {
52
+ backgroundPositionY: '-20px'
53
+ }
54
+ },
55
+ ':focus': {
56
+ color: 'var(--epr-highlight-color)',
57
+ backgroundColor: 'var(--epr-hover-bg-color)',
58
+ // @ts-ignore
59
+ ':after': {
60
+ backgroundPositionY: '-40px'
61
+ }
62
+ }
63
+ },
64
+ '.epr-dark-theme': {
65
+ plusSign: {
66
+ ':after': { backgroundPositionY: '-40px' },
67
+ ':hover:after': { backgroundPositionY: '-60px' }
68
+ }
69
+ },
70
+ '.epr-auto-theme': {
71
+ plusSign: {
72
+ '@media (prefers-color-scheme: dark)': {
73
+ ':after': { backgroundPositionY: '-40px' },
74
+ ':hover:after': { backgroundPositionY: '-60px' }
75
+ }
76
+ }
77
+ }
78
+ });
@@ -0,0 +1,9 @@
1
+ export const DEFAULT_REACTIONS = [
2
+ '1f44d', // 👍
3
+ '2764-fe0f', // ❤️
4
+ '1f603', // 😃
5
+ '1f622', // 😢
6
+ '1f64f', // 🙏
7
+ '1f44e', // 👎
8
+ '1f621' // 😡
9
+ ];
@@ -0,0 +1,62 @@
1
+ import { cx } from 'flairup';
2
+ import * as React from 'react';
3
+
4
+ import { commonStyles, stylesheet } from '../../Stylesheet/stylesheet';
5
+ import {
6
+ useEmojiStyleConfig,
7
+ useReactionsConfig
8
+ } from '../../config/useConfig';
9
+ import { DataEmoji } from '../../dataUtils/DataTypes';
10
+ import { emojiByUnified } from '../../dataUtils/emojiSelectors';
11
+ import { useMouseDownHandlers } from '../../hooks/useMouseDownHandlers';
12
+ import { useReactionsRef } from '../context/ElementRefContext';
13
+ import { useReactionsModeState } from '../context/PickerContext';
14
+ import { ClickableEmoji } from '../emoji/Emoji';
15
+
16
+ import { BtnPlus } from './BtnPlus';
17
+
18
+ export function Reactions() {
19
+ const [reactionsOpen] = useReactionsModeState();
20
+ const ReactionsRef = useReactionsRef();
21
+ const reactions = useReactionsConfig();
22
+ useMouseDownHandlers(ReactionsRef);
23
+ const emojiStyle = useEmojiStyleConfig();
24
+
25
+ if (!reactionsOpen) {
26
+ return null;
27
+ }
28
+
29
+ return (
30
+ <ul
31
+ className={cx(styles.list, !reactionsOpen && commonStyles.hidden)}
32
+ ref={ReactionsRef}
33
+ >
34
+ {reactions.map(reaction => (
35
+ <li key={reaction}>
36
+ <ClickableEmoji
37
+ emoji={emojiByUnified(reaction) as DataEmoji}
38
+ emojiStyle={emojiStyle}
39
+ unified={reaction}
40
+ showVariations={false}
41
+ round
42
+ />
43
+ </li>
44
+ ))}
45
+ <li>
46
+ <BtnPlus />
47
+ </li>
48
+ </ul>
49
+ );
50
+ }
51
+
52
+ const styles = stylesheet.create({
53
+ list: {
54
+ listStyle: 'none',
55
+ margin: '0',
56
+ padding: '0 5px',
57
+ display: 'flex',
58
+ justifyContent: 'space-between',
59
+ alignItems: 'center',
60
+ height: '100%'
61
+ }
62
+ });
@@ -0,0 +1,17 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!-- Generator: Adobe Illustrator 28.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
3
+ <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
4
+ width="20px" height="80px" viewBox="0 0 20 80" enable-background="new 0 0 20 80" xml:space="preserve">
5
+ <path fill="#868686" d="M5.7,10.4c0,0.1,0.1,0.3,0.2,0.4C6,10.9,6.1,11,6.3,11h3.4v3.4c0,0.1,0.1,0.3,0.2,0.4
6
+ c0.1,0.1,0.2,0.2,0.4,0.2c0.3,0,0.5-0.2,0.5-0.5v-3.4h3.4c0.3,0,0.5-0.2,0.5-0.5s-0.2-0.5-0.5-0.5h-3.4V6.7c0-0.3-0.2-0.5-0.5-0.5
7
+ C9.8,6,9.6,6.2,9.6,6.5v3.4H6.2C5.9,9.9,5.7,10.1,5.7,10.4L5.7,10.4z"/>
8
+ <path fill="#3371B7" d="M5.7,30.4c0,0.1,0.1,0.3,0.2,0.4S6.1,31,6.3,31h3.4v3.4c0,0.1,0.1,0.3,0.2,0.4c0.1,0.1,0.2,0.2,0.4,0.2
9
+ c0.3,0,0.5-0.2,0.5-0.5v-3.4h3.4c0.3,0,0.5-0.2,0.5-0.5s-0.2-0.5-0.5-0.5h-3.4v-3.4c0-0.3-0.2-0.5-0.5-0.5s-0.5,0.2-0.5,0.5v3.4H6.2
10
+ C5.9,29.9,5.7,30.1,5.7,30.4L5.7,30.4z"/>
11
+ <path fill="#C0C0BF" d="M5.7,50.4c0,0.1,0.1,0.3,0.2,0.4C6,50.9,6.1,51,6.3,51h3.4v3.4c0,0.1,0.1,0.3,0.2,0.4
12
+ c0.1,0.1,0.2,0.2,0.4,0.2c0.3,0,0.5-0.2,0.5-0.5v-3.4h3.4c0.3,0,0.5-0.2,0.5-0.5s-0.2-0.5-0.5-0.5h-3.4v-3.4c0-0.3-0.2-0.5-0.5-0.5
13
+ s-0.5,0.2-0.5,0.5v3.4H6.2C5.9,49.9,5.7,50.1,5.7,50.4L5.7,50.4z"/>
14
+ <path fill="#6AA9DD" d="M5.7,70.4c0,0.1,0.1,0.3,0.2,0.4S6.1,71,6.3,71h3.4v3.4c0,0.1,0.1,0.3,0.2,0.4c0.1,0.1,0.2,0.2,0.4,0.2
15
+ c0.3,0,0.5-0.2,0.5-0.5v-3.4h3.4c0.3,0,0.5-0.2,0.5-0.5s-0.2-0.5-0.5-0.5h-3.4v-3.4c0-0.3-0.2-0.5-0.5-0.5s-0.5,0.2-0.5,0.5v3.4H6.4
16
+ C5.9,69.9,5.7,70.1,5.7,70.4L5.7,70.4z"/>
17
+ </svg>
@@ -2,7 +2,10 @@ import { cx } from 'flairup';
2
2
  import * as React from 'react';
3
3
 
4
4
  import { ClassNames } from '../../DomUtils/classNames';
5
- import { stylesheet } from '../../Stylesheet/stylesheet';
5
+ import {
6
+ commonInteractionStyles,
7
+ stylesheet
8
+ } from '../../Stylesheet/stylesheet';
6
9
  import { useOnMouseMove } from '../../hooks/useDisallowMouseMove';
7
10
  import { useMouseDownHandlers } from '../../hooks/useMouseDownHandlers';
8
11
  import { useOnScroll } from '../../hooks/useOnScroll';
@@ -18,7 +21,10 @@ export function Body() {
18
21
  useOnMouseMove();
19
22
 
20
23
  return (
21
- <div className={cx(styles.body)} ref={BodyRef}>
24
+ <div
25
+ className={cx(styles.body, commonInteractionStyles.hiddenOnReactions)}
26
+ ref={BodyRef}
27
+ >
22
28
  <EmojiVariationPicker />
23
29
  <EmojiList />
24
30
  </div>
@@ -200,6 +200,12 @@ const styles = stylesheet.create({
200
200
  transform: 'scale(0.9)',
201
201
  transition: 'transform 0.1s ease-out, opacity 0.2s ease-out'
202
202
  },
203
+ visible: {
204
+ opacity: '1',
205
+ visibility: 'visible',
206
+ pointerEvents: 'all',
207
+ transform: 'scale(1)'
208
+ },
203
209
  pointingUp: {
204
210
  '.': 'pointing-up',
205
211
  transformOrigin: 'center 0%',
@@ -211,12 +217,6 @@ const styles = stylesheet.create({
211
217
  transform: 'rotate(180deg) translateY(100%) translateX(18px)'
212
218
  }
213
219
  },
214
- visible: {
215
- opacity: '1',
216
- visibility: 'visible',
217
- pointerEvents: 'all',
218
- transform: 'scale(1)'
219
- },
220
220
  pointer: {
221
221
  '.': 'epr-emoji-pointer',
222
222
  content: '',
@@ -237,7 +237,6 @@ const styles = stylesheet.create({
237
237
  },
238
238
  '.epr-auto-theme': {
239
239
  pointer: {
240
- // @ts-ignore
241
240
  '@media (prefers-color-scheme: dark)': {
242
241
  backgroundPosition: '-25px 0'
243
242
  }
@@ -15,6 +15,7 @@ export function ElementRefContextProvider({
15
15
  const SkinTonePickerRef = React.useRef<HTMLDivElement>(null);
16
16
  const CategoryNavigationRef = React.useRef<HTMLDivElement>(null);
17
17
  const VariationPickerRef = React.useRef<HTMLDivElement>(null);
18
+ const ReactionsRef = React.useRef<HTMLUListElement>(null);
18
19
 
19
20
  return (
20
21
  <ElementRefContext.Provider
@@ -25,7 +26,8 @@ export function ElementRefContextProvider({
25
26
  PickerMainRef,
26
27
  SearchInputRef,
27
28
  SkinTonePickerRef,
28
- VariationPickerRef
29
+ VariationPickerRef,
30
+ ReactionsRef
29
31
  }}
30
32
  >
31
33
  {children}
@@ -45,6 +47,7 @@ type ElementRefs = {
45
47
  BodyRef: ElementRef<HTMLDivElement>;
46
48
  CategoryNavigationRef: ElementRef<HTMLDivElement>;
47
49
  VariationPickerRef: ElementRef<HTMLDivElement>;
50
+ ReactionsRef: ElementRef<HTMLUListElement>;
48
51
  };
49
52
 
50
53
  const ElementRefContext = React.createContext<ElementRefs>({
@@ -54,7 +57,8 @@ const ElementRefContext = React.createContext<ElementRefs>({
54
57
  PickerMainRef: React.createRef(),
55
58
  SearchInputRef: React.createRef(),
56
59
  SkinTonePickerRef: React.createRef(),
57
- VariationPickerRef: React.createRef()
60
+ VariationPickerRef: React.createRef(),
61
+ ReactionsRef: React.createRef()
58
62
  });
59
63
 
60
64
  function useElementRef() {
@@ -84,6 +88,10 @@ export function useBodyRef() {
84
88
  return useElementRef()['BodyRef'];
85
89
  }
86
90
 
91
+ export function useReactionsRef() {
92
+ return useElementRef()['ReactionsRef'];
93
+ }
94
+
87
95
  export function useSearchInputRef() {
88
96
  return useElementRef()['SearchInputRef'];
89
97
  }
@@ -1,7 +1,10 @@
1
1
  import * as React from 'react';
2
2
  import { useState } from 'react';
3
3
 
4
- import { useDefaultSkinToneConfig } from '../../config/useConfig';
4
+ import {
5
+ useDefaultSkinToneConfig,
6
+ useReactionsOpenConfig
7
+ } from '../../config/useConfig';
5
8
  import { DataEmoji } from '../../dataUtils/DataTypes';
6
9
  import { alphaNumericEmojiIndex } from '../../dataUtils/alphaNumericEmojiIndex';
7
10
  import { useDebouncedState } from '../../hooks/useDebouncedState';
@@ -13,6 +16,7 @@ import { SkinTones } from '../../types/exposedTypes';
13
16
  export function PickerContextProvider({ children }: Props) {
14
17
  const disallowedEmojis = useDisallowedEmojis();
15
18
  const defaultSkinTone = useDefaultSkinToneConfig();
19
+ const reactionsDefaultOpen = useReactionsOpenConfig();
16
20
 
17
21
  // Initialize the filter with the inititial dictionary
18
22
  const filterRef = React.useRef<FilterState>(alphaNumericEmojiIndex);
@@ -29,6 +33,7 @@ export function PickerContextProvider({ children }: Props) {
29
33
  const activeCategoryState = useState<ActiveCategoryState>(null);
30
34
  const emojisThatFailedToLoadState = useState<Set<string>>(new Set());
31
35
  const emojiVariationPickerState = useState<DataEmoji | null>(null);
36
+ const reactionsModeState = useState(reactionsDefaultOpen);
32
37
  const [isPastInitialLoad, setIsPastInitialLoad] = useState(false);
33
38
 
34
39
  useMarkInitialLoad(setIsPastInitialLoad);
@@ -47,7 +52,8 @@ export function PickerContextProvider({ children }: Props) {
47
52
  isPastInitialLoad,
48
53
  searchTerm,
49
54
  skinToneFanOpenState,
50
- suggestedUpdateState
55
+ suggestedUpdateState,
56
+ reactionsModeState
51
57
  }}
52
58
  >
53
59
  {children}
@@ -70,6 +76,7 @@ const PickerContext = React.createContext<{
70
76
  disallowClickRef: React.MutableRefObject<boolean>;
71
77
  disallowMouseRef: React.MutableRefObject<boolean>;
72
78
  disallowedEmojisRef: React.MutableRefObject<Record<string, boolean>>;
79
+ reactionsModeState: ReactState<boolean>;
73
80
  }>({
74
81
  activeCategoryState: [null, () => {}],
75
82
  activeSkinTone: [SkinTones.NEUTRAL, () => {}],
@@ -82,7 +89,8 @@ const PickerContext = React.createContext<{
82
89
  isPastInitialLoad: true,
83
90
  searchTerm: ['', () => new Promise<string>(() => undefined)],
84
91
  skinToneFanOpenState: [false, () => {}],
85
- suggestedUpdateState: [Date.now(), () => {}]
92
+ suggestedUpdateState: [Date.now(), () => {}],
93
+ reactionsModeState: [false, () => {}]
86
94
  });
87
95
 
88
96
  type Props = Readonly<{
@@ -104,6 +112,11 @@ export function useDisallowMouseRef() {
104
112
  return disallowMouseRef;
105
113
  }
106
114
 
115
+ export function useReactionsModeState() {
116
+ const { reactionsModeState } = React.useContext(PickerContext);
117
+ return reactionsModeState;
118
+ }
119
+
107
120
  export function useSearchTermState() {
108
121
  const { searchTerm } = React.useContext(PickerContext);
109
122
  return searchTerm;
@@ -2,7 +2,11 @@ import { cx } from 'flairup';
2
2
  import * as React from 'react';
3
3
 
4
4
  import { ClassNames } from '../../DomUtils/classNames';
5
- import { commonInteractionStyles, commonStyles, stylesheet } from '../../Stylesheet/stylesheet';
5
+ import {
6
+ commonInteractionStyles,
7
+ commonStyles,
8
+ stylesheet
9
+ } from '../../Stylesheet/stylesheet';
6
10
  import { Button } from '../atoms/Button';
7
11
 
8
12
  type ClickableEmojiButtonProps = Readonly<{
@@ -13,6 +17,7 @@ type ClickableEmojiButtonProps = Readonly<{
13
17
  children: React.ReactNode;
14
18
  hasVariations: boolean;
15
19
  unified?: string;
20
+ round?: boolean;
16
21
  }>;
17
22
 
18
23
  export function ClickableEmojiButton({
@@ -22,7 +27,8 @@ export function ClickableEmojiButton({
22
27
  hiddenOnSearch,
23
28
  showVariations = true,
24
29
  hasVariations,
25
- children
30
+ children,
31
+ round = false
26
32
  }: ClickableEmojiButtonProps) {
27
33
  return (
28
34
  <Button
@@ -33,7 +39,8 @@ export function ClickableEmojiButton({
33
39
  {
34
40
  [ClassNames.visible]: !hidden && !hiddenOnSearch
35
41
  },
36
- !!(hasVariations && showVariations) && styles.hasVariations
42
+ !!(hasVariations && showVariations) && styles.hasVariations,
43
+ round && styles.round
37
44
  )}
38
45
  data-unified={unified}
39
46
  aria-label={emojiNames[0]}
@@ -66,6 +73,9 @@ const styles = stylesheet.create({
66
73
  backgroundColor: 'var(--epr-focus-bg-color)'
67
74
  }
68
75
  },
76
+ round: {
77
+ borderRadius: '50%'
78
+ },
69
79
  hasVariations: {
70
80
  '.': ClassNames.emojiHasVariations,
71
81
  ':after': {
@@ -14,6 +14,7 @@ type ClickableEmojiProps = Readonly<
14
14
  hiddenOnSearch?: boolean;
15
15
  emoji: DataEmoji;
16
16
  className?: string;
17
+ round?: boolean;
17
18
  }
18
19
  >;
19
20
 
@@ -26,7 +27,8 @@ export function ClickableEmoji({
26
27
  showVariations = true,
27
28
  size,
28
29
  lazyLoad,
29
- getEmojiUrl
30
+ getEmojiUrl,
31
+ round = false
30
32
  }: ClickableEmojiProps) {
31
33
  const hasVariations = emojiHasVariations(emoji);
32
34
 
@@ -38,6 +40,7 @@ export function ClickableEmoji({
38
40
  hiddenOnSearch={hiddenOnSearch}
39
41
  emojiNames={emojiNames(emoji)}
40
42
  unified={unified}
43
+ round={round}
41
44
  >
42
45
  <ViewOnlyEmoji
43
46
  unified={unified}
@@ -2,7 +2,10 @@ import { cx } from 'flairup';
2
2
  import * as React from 'react';
3
3
  import { useState } from 'react';
4
4
 
5
- import { stylesheet } from '../../Stylesheet/stylesheet';
5
+ import {
6
+ commonInteractionStyles,
7
+ stylesheet
8
+ } from '../../Stylesheet/stylesheet';
6
9
  import {
7
10
  useEmojiStyleConfig,
8
11
  useGetEmojiUrlConfig,
@@ -19,7 +22,7 @@ import Flex from '../Layout/Flex';
19
22
  import Space from '../Layout/Space';
20
23
  import { useEmojiVariationPickerState } from '../context/PickerContext';
21
24
  import { ViewOnlyEmoji } from '../emoji/ViewOnlyEmoji';
22
- import { SkinTonePickerMenu } from '../header/SkinTonePicker';
25
+ import { SkinTonePickerMenu } from '../header/SkinTonePicker/SkinTonePicker';
23
26
 
24
27
  export function Preview() {
25
28
  const previewConfig = usePreviewConfig();
@@ -30,7 +33,9 @@ export function Preview() {
30
33
  }
31
34
 
32
35
  return (
33
- <Flex className={cx(styles.preview)}>
36
+ <Flex
37
+ className={cx(styles.preview, commonInteractionStyles.hiddenOnReactions)}
38
+ >
34
39
  <PreviewBody />
35
40
  <Space />
36
41
  {isSkinToneInPreview ? <SkinTonePickerMenu /> : null}
@@ -88,11 +93,9 @@ export function PreviewBody() {
88
93
  />
89
94
  ) : null}
90
95
  </div>
91
- {show ? (
92
- <div className={cx(styles.label)}>{emojiName(emoji)}</div>
93
- ) : (
94
- <div className={cx(styles.label)}>{defaultText}</div>
95
- )}
96
+ <div className={cx(styles.label)}>
97
+ {show ? emojiName(emoji) : defaultText}
98
+ </div>
96
99
  </>
97
100
  );
98
101
  }
@@ -1,13 +1,17 @@
1
+ import { cx } from 'flairup';
1
2
  import * as React from 'react';
2
3
 
4
+ import { commonInteractionStyles } from '../../Stylesheet/stylesheet';
3
5
  import Relative from '../Layout/Relative';
4
6
  import { CategoryNavigation } from '../navigation/CategoryNavigation';
5
7
 
6
- import { SearchContainer } from './Search';
8
+ import { SearchContainer } from './Search/Search';
7
9
 
8
10
  export function Header() {
9
11
  return (
10
- <Relative className="epr-header">
12
+ <Relative
13
+ className={cx('epr-header', commonInteractionStyles.hiddenOnReactions)}
14
+ >
11
15
  <SearchContainer />
12
16
  <CategoryNavigation />
13
17
  </Relative>
@@ -0,0 +1,91 @@
1
+ import { cx } from 'flairup';
2
+ import * as React from 'react';
3
+
4
+ import {
5
+ commonInteractionStyles,
6
+ stylesheet
7
+ } from '../../../Stylesheet/stylesheet';
8
+ import { useClearSearch } from '../../../hooks/useFilter';
9
+ import { Button } from '../../atoms/Button';
10
+
11
+ import SVGTimes from './svg/times.svg';
12
+
13
+ export function BtnClearSearch() {
14
+ const clearSearch = useClearSearch();
15
+
16
+ return (
17
+ <Button
18
+ className={cx(
19
+ styles.btnClearSearch,
20
+ commonInteractionStyles.visibleOnSearchOnly
21
+ )}
22
+ onClick={clearSearch}
23
+ aria-label="Clear"
24
+ title="Clear"
25
+ >
26
+ <div className={cx(styles.icnClearnSearch)} />
27
+ </Button>
28
+ );
29
+ }
30
+
31
+ const HoverDark = {
32
+ ':hover': {
33
+ '> .epr-icn-clear-search': {
34
+ backgroundPositionY: '-60px'
35
+ }
36
+ }
37
+ };
38
+
39
+ const styles = stylesheet.create({
40
+ btnClearSearch: {
41
+ '.': 'epr-btn-clear-search',
42
+ position: 'absolute',
43
+ right: 'var(--epr-search-bar-inner-padding)',
44
+ height: '30px',
45
+ width: '30px',
46
+ display: 'flex',
47
+ alignItems: 'center',
48
+ justifyContent: 'center',
49
+ top: '50%',
50
+ transform: 'translateY(-50%)',
51
+ padding: '0',
52
+ borderRadius: '50%',
53
+ ':hover': {
54
+ background: 'var(--epr-hover-bg-color)'
55
+ },
56
+ ':focus': {
57
+ background: 'var(--epr-hover-bg-color)'
58
+ }
59
+ },
60
+ icnClearnSearch: {
61
+ '.': 'epr-icn-clear-search',
62
+ backgroundColor: 'transparent',
63
+ backgroundRepeat: 'no-repeat',
64
+ backgroundSize: '20px',
65
+ height: '20px',
66
+ width: '20px',
67
+ backgroundImage: `url(${SVGTimes})`,
68
+ ':hover': {
69
+ backgroundPositionY: '-20px'
70
+ },
71
+ ':focus': {
72
+ backgroundPositionY: '-20px'
73
+ }
74
+ },
75
+ '.epr-dark-theme': {
76
+ icnClearnSearch: {
77
+ backgroundPositionY: '-40px'
78
+ },
79
+ btnClearSearch: HoverDark
80
+ },
81
+ '.epr-auto-theme': {
82
+ icnClearnSearch: {
83
+ '@media (prefers-color-scheme: dark)': {
84
+ backgroundPositionY: '-40px'
85
+ }
86
+ },
87
+ btnClearSearch: {
88
+ '@media (prefers-color-scheme: dark)': HoverDark
89
+ }
90
+ }
91
+ });