emoji-picker-react 4.3.0 → 4.4.0-rc.2

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 (36) hide show
  1. package/README.md +26 -16
  2. package/dist/DomUtils/classNames.d.ts +4 -1
  3. package/dist/components/Layout/Absolute.d.ts +8 -0
  4. package/dist/components/Layout/Relative.d.ts +2 -1
  5. package/dist/components/Layout/Space.d.ts +7 -0
  6. package/dist/components/footer/Preview.d.ts +1 -0
  7. package/dist/components/header/Search.d.ts +1 -0
  8. package/dist/components/header/SkinTonePicker.d.ts +10 -1
  9. package/dist/config/config.d.ts +3 -1
  10. package/dist/config/useConfig.d.ts +3 -1
  11. package/dist/emoji-picker-react.cjs.development.css +4 -4
  12. package/dist/emoji-picker-react.cjs.development.js +252 -106
  13. package/dist/emoji-picker-react.cjs.development.js.map +1 -1
  14. package/dist/emoji-picker-react.cjs.production.min.js +1 -1
  15. package/dist/emoji-picker-react.cjs.production.min.js.map +1 -1
  16. package/dist/emoji-picker-react.esm.js +264 -118
  17. package/dist/emoji-picker-react.esm.js.map +1 -1
  18. package/dist/hooks/useShouldShowSkinTonePicker.d.ts +4 -0
  19. package/dist/types/exposedTypes.d.ts +4 -0
  20. package/package.json +1 -1
  21. package/src/DomUtils/classNames.ts +4 -1
  22. package/src/EmojiPickerReact.css +3 -0
  23. package/src/components/Layout/Absolute.tsx +15 -0
  24. package/src/components/Layout/Relative.tsx +3 -2
  25. package/src/components/Layout/Space.tsx +11 -0
  26. package/src/components/footer/Preview.css +2 -0
  27. package/src/components/footer/Preview.tsx +23 -11
  28. package/src/components/header/Header.tsx +2 -7
  29. package/src/components/header/Search.tsx +25 -3
  30. package/src/components/header/SkinTonePicker.css +19 -9
  31. package/src/components/header/SkinTonePicker.tsx +41 -4
  32. package/src/config/config.ts +11 -1
  33. package/src/config/useConfig.ts +11 -0
  34. package/src/hooks/useKeyboardNavigation.ts +69 -26
  35. package/src/hooks/useShouldShowSkinTonePicker.ts +22 -0
  36. package/src/types/exposedTypes.ts +10 -5
@@ -0,0 +1,4 @@
1
+ import { SkinTonePickerLocation } from '../types/exposedTypes';
2
+ export declare function useShouldShowSkinTonePicker(): (location: SkinTonePickerLocation) => boolean;
3
+ export declare function useIsSkinToneInSearch(): boolean;
4
+ export declare function useIsSkinToneInPreview(): boolean;
@@ -41,3 +41,7 @@ export declare enum Categories {
41
41
  SYMBOLS = "symbols",
42
42
  FLAGS = "flags"
43
43
  }
44
+ export declare enum SkinTonePickerLocation {
45
+ SEARCH = "SEARCH",
46
+ PREVIEW = "PREVIEW"
47
+ }
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "4.3.0",
2
+ "version": "4.4.0-rc.2",
3
3
  "license": "MIT",
4
4
  "main": "dist/index.js",
5
5
  "typings": "dist/index.d.ts",
@@ -13,8 +13,11 @@ export enum ClassNames {
13
13
  emojiList = 'epr-emoji-list',
14
14
  external = '__EmojiPicker__',
15
15
  emojiPicker = 'EmojiPickerReact',
16
+ open = 'epr-open',
17
+ vertical = 'epr-vertical',
18
+ horizontal = 'epr-horizontal'
16
19
  }
17
20
 
18
21
  export function asSelectors(...classNames: ClassNames[]): string {
19
- return classNames.map((c) => `.${c}`).join('');
22
+ return classNames.map(c => `.${c}`).join('');
20
23
  }
@@ -7,6 +7,7 @@
7
7
  --epr-picker-border-color: #e7e7e7;
8
8
  --epr-bg-color: #fff;
9
9
  --epr-category-icon-active-color: #6aa8de;
10
+ --epr-skin-tone-picker-menu-color: #ffffff95;
10
11
 
11
12
  --epr-horizontal-padding: 10px;
12
13
 
@@ -67,6 +68,7 @@
67
68
  --epr-emoji-variations-indictator-z-index: 1;
68
69
  --epr-category-label-z-index: 2;
69
70
  --epr-skin-variation-picker-z-index: 5;
71
+ --epr-preview-z-index: 6;
70
72
  }
71
73
 
72
74
  .EmojiPickerReact.epr-dark-theme {
@@ -83,6 +85,7 @@
83
85
  --epr-search-input-bg-color-active: var(--epr-dark);
84
86
  --epr-emoji-variation-indicator-color: #444;
85
87
  --epr-category-icon-active-color: #3271b7;
88
+ --epr-skin-tone-picker-menu-color: #22222295;
86
89
  }
87
90
 
88
91
  .EmojiPickerReact {
@@ -0,0 +1,15 @@
1
+ import * as React from 'react';
2
+
3
+ type Props = Readonly<{
4
+ children: React.ReactNode;
5
+ className?: string;
6
+ style?: React.CSSProperties;
7
+ }>;
8
+
9
+ export default function Absolute({ children, className, style }: Props) {
10
+ return (
11
+ <div style={{ ...style, position: 'absolute' }} className={className}>
12
+ {children}
13
+ </div>
14
+ );
15
+ }
@@ -3,11 +3,12 @@ import * as React from 'react';
3
3
  type Props = Readonly<{
4
4
  children: React.ReactNode;
5
5
  className?: string;
6
+ style?: React.CSSProperties;
6
7
  }>;
7
8
 
8
- export default function Relative({ children, className }: Props) {
9
+ export default function Relative({ children, className, style }: Props) {
9
10
  return (
10
- <div style={{ position: 'relative' }} className={className}>
11
+ <div style={{ ...style, position: 'relative' }} className={className}>
11
12
  {children}
12
13
  </div>
13
14
  );
@@ -0,0 +1,11 @@
1
+ import clsx from 'clsx';
2
+ import * as React from 'react';
3
+
4
+ type Props = Readonly<{
5
+ className?: string;
6
+ style?: React.CSSProperties;
7
+ }>;
8
+
9
+ export default function Space({ className, style = {} }: Props) {
10
+ return <div style={{ flex: 1, ...style }} className={clsx(className)} />;
11
+ }
@@ -4,6 +4,8 @@
4
4
  align-items: center;
5
5
  border-top: 1px solid var(--epr-preview-border-color);
6
6
  height: var(--epr-preview-height);
7
+ position: relative;
8
+ z-index: var(--epr-preview-z-index);
7
9
  }
8
10
 
9
11
  .EmojiPickerReact .epr-preview .epr-preview-emoji-label {
@@ -4,21 +4,41 @@ import { useState } from 'react';
4
4
  import {
5
5
  useEmojiStyleConfig,
6
6
  useGetEmojiUrlConfig,
7
- usePreviewConfig,
7
+ usePreviewConfig
8
8
  } from '../../config/useConfig';
9
9
  import { asEmoji } from '../../dataUtils/asEmoji';
10
10
  import {
11
11
  emojiByUnified,
12
12
  emojiName,
13
- emojiUnified,
13
+ emojiUnified
14
14
  } from '../../dataUtils/emojiSelectors';
15
15
  import { useEmojiPreviewEvents } from '../../hooks/useEmojiPreviewEvents';
16
+ import { useIsSkinToneInPreview } from '../../hooks/useShouldShowSkinTonePicker';
16
17
  import Flex from '../Layout/Flex';
18
+ import Space from '../Layout/Space';
17
19
  import { useEmojiVariationPickerState } from '../context/PickerContext';
18
20
  import { ViewOnlyEmoji } from '../emoji/Emoji';
19
21
  import './Preview.css';
22
+ import { SkinTonePickerMenu } from '../header/SkinTonePicker';
20
23
 
21
24
  export function Preview() {
25
+ const previewConfig = usePreviewConfig();
26
+ const isSkinToneInPreview = useIsSkinToneInPreview();
27
+
28
+ if (!previewConfig.showPreview) {
29
+ return null;
30
+ }
31
+
32
+ return (
33
+ <Flex className="epr-preview">
34
+ <PreviewBody />
35
+ <Space />
36
+ {isSkinToneInPreview ? <SkinTonePickerMenu /> : null}
37
+ </Flex>
38
+ );
39
+ }
40
+
41
+ export function PreviewBody() {
22
42
  const previewConfig = usePreviewConfig();
23
43
  const [previewEmoji, setPreviewEmoji] = useState<PreviewEmoji>(null);
24
44
  const emojiStyle = useEmojiStyleConfig();
@@ -27,19 +47,11 @@ export function Preview() {
27
47
 
28
48
  useEmojiPreviewEvents(previewConfig.showPreview, setPreviewEmoji);
29
49
 
30
- if (!previewConfig.showPreview) {
31
- return null;
32
- }
33
-
34
50
  const emoji = emojiByUnified(previewEmoji?.originalUnified);
35
51
 
36
52
  const show = emoji != null && previewEmoji != null;
37
53
 
38
- return (
39
- <Flex className="epr-preview">
40
- <PreviewContent />
41
- </Flex>
42
- );
54
+ return <PreviewContent />;
43
55
 
44
56
  function PreviewContent() {
45
57
  const defaultEmoji = asEmoji(
@@ -1,20 +1,15 @@
1
1
  import * as React from 'react';
2
2
 
3
- import Flex from '../Layout/Flex';
4
3
  import Relative from '../Layout/Relative';
5
4
  import { CategoryNavigation } from '../navigation/CategoryNavigation';
6
5
 
7
- import { Search } from './Search';
8
- import { SkinTonePicker } from './SkinTonePicker';
9
6
  import './Header.css';
7
+ import { SearchContainer } from './Search';
10
8
 
11
9
  export function Header() {
12
10
  return (
13
11
  <Relative className="epr-header">
14
- <Flex className="epr-header-overlay">
15
- <Search />
16
- <SkinTonePicker />
17
- </Flex>
12
+ <SearchContainer />
18
13
  <CategoryNavigation />
19
14
  </Relative>
20
15
  );
@@ -5,19 +5,41 @@ import { useState } from 'react';
5
5
  import { asSelectors, ClassNames } from '../../DomUtils/classNames';
6
6
  import {
7
7
  useAutoFocusSearchConfig,
8
- useSearchPlaceHolderConfig,
8
+ useSearchDisabledConfig,
9
+ useSearchPlaceHolderConfig
9
10
  } from '../../config/useConfig';
10
11
  import { useCloseAllOpenToggles } from '../../hooks/useCloseAllOpenToggles';
11
12
  import {
12
13
  getNormalizedSearchTerm,
13
14
  useClearSearch,
14
- useFilter,
15
+ useFilter
15
16
  } from '../../hooks/useFilter';
17
+ import { useIsSkinToneInSearch } from '../../hooks/useShouldShowSkinTonePicker';
18
+ import Flex from '../Layout/Flex';
16
19
  import Relative from '../Layout/Relative';
17
20
  import { Button } from '../atoms/Button';
18
21
  import { useSearchInputRef } from '../context/ElementRefContext';
19
22
 
20
23
  import './Search.css';
24
+ import { SkinTonePicker } from './SkinTonePicker';
25
+
26
+ export function SearchContainer() {
27
+ const searchDisabled = useSearchDisabledConfig();
28
+
29
+ const isSkinToneInSearch = useIsSkinToneInSearch();
30
+
31
+ if (searchDisabled) {
32
+ return null;
33
+ }
34
+
35
+ return (
36
+ <Flex className="epr-header-overlay">
37
+ <Search />
38
+
39
+ {isSkinToneInSearch ? <SkinTonePicker /> : null}
40
+ </Flex>
41
+ );
42
+ }
21
43
 
22
44
  export function Search() {
23
45
  const [inc, setInc] = useState(0);
@@ -42,7 +64,7 @@ export function Search() {
42
64
  className="epr-search"
43
65
  type="text"
44
66
  placeholder={placeholder}
45
- onChange={(event) => {
67
+ onChange={event => {
46
68
  setInc(inc + 1);
47
69
  setTimeout(() => {
48
70
  onChange(event?.target?.value ?? value);
@@ -1,5 +1,5 @@
1
1
  .EmojiPickerReact .epr-skin-tones {
2
- --epr-skin-tone-size: 16px;
2
+ --epr-skin-tone-size: 15px;
3
3
  }
4
4
 
5
5
  .EmojiPickerReact .epr-skin-tones {
@@ -7,11 +7,21 @@
7
7
  align-items: center;
8
8
  justify-content: flex-end;
9
9
  transition: all 0.3s ease-in-out;
10
- flex-basis: 30px;
10
+ padding: 10px 0;
11
11
  }
12
12
 
13
- .EmojiPickerReact .epr-skin-tones.open {
14
- flex-basis: 170px;
13
+ .EmojiPickerReact .epr-skin-tones.epr-vertical {
14
+ padding: 5px;
15
+ align-items: flex-end;
16
+ flex-direction: column;
17
+ border-radius: 6px;
18
+ border: 1px solid var(--epr-bg-color);
19
+ }
20
+
21
+ .EmojiPickerReact .epr-skin-tones.epr-vertical.epr-open {
22
+ border: 1px solid var(--epr-picker-border-color);
23
+ backdrop-filter: blur(5px);
24
+ background: var(--epr-skin-tone-picker-menu-color);
15
25
  }
16
26
 
17
27
  .EmojiPickerReact .epr-skin-tone-select {
@@ -20,11 +30,11 @@
20
30
  height: var(--epr-skin-tone-size);
21
31
  }
22
32
 
23
- .EmojiPickerReact .epr-skin-tones.open .epr-tone {
33
+ .EmojiPickerReact .epr-skin-tones.epr-open .epr-tone {
24
34
  transition: transform 0.3s ease-in-out, opacity 0.3s ease-in-out;
25
35
  }
26
36
 
27
- .EmojiPickerReact .epr-skin-tones:not(.open) .epr-tone {
37
+ .EmojiPickerReact .epr-skin-tones:not(.epr-open) .epr-tone {
28
38
  z-index: 0;
29
39
  opacity: 0;
30
40
  }
@@ -47,15 +57,15 @@
47
57
  }
48
58
 
49
59
  .EmojiPickerReact .epr-skin-tones .epr-tone:hover {
50
- box-shadow: 0 0 0 5px var(--epr-active-skin-hover-color);
60
+ box-shadow: 0 0 0 3px var(--epr-active-skin-hover-color);
51
61
  }
52
62
 
53
63
  .EmojiPickerReact .epr-skin-tones .epr-tone:focus {
54
- box-shadow: 0 0 0 5px var(--epr-focus-bg-color);
64
+ box-shadow: 0 0 0 3px var(--epr-focus-bg-color);
55
65
  }
56
66
 
57
67
  .EmojiPickerReact
58
- .epr-skin-tones.open
68
+ .epr-skin-tones.epr-open
59
69
  .epr-skin-tone-select
60
70
  .epr-tone.epr-active:after {
61
71
  content: '';
@@ -9,6 +9,7 @@ import skinToneVariations, {
9
9
  import { useCloseAllOpenToggles } from '../../hooks/useCloseAllOpenToggles';
10
10
  import { useFocusSearchInput } from '../../hooks/useFocus';
11
11
  import { SkinTones } from '../../types/exposedTypes';
12
+ import Absolute from '../Layout/Absolute';
12
13
  import Relative from '../Layout/Relative';
13
14
  import { Button } from '../atoms/Button';
14
15
  import { useSkinTonePickerRef } from '../context/ElementRefContext';
@@ -18,7 +19,25 @@ import {
18
19
  } from '../context/PickerContext';
19
20
  import './SkinTonePicker.css';
20
21
 
21
- export function SkinTonePicker() {
22
+ const ITEM_SIZE = 28;
23
+
24
+ type Props = {
25
+ direction?: SkinTonePickerDirection;
26
+ };
27
+
28
+ export function SkinTonePickerMenu() {
29
+ return (
30
+ <Relative style={{ height: ITEM_SIZE }}>
31
+ <Absolute style={{ bottom: 0, right: 0 }}>
32
+ <SkinTonePicker direction={SkinTonePickerDirection.VERTICAL} />
33
+ </Absolute>
34
+ </Relative>
35
+ );
36
+ }
37
+
38
+ export function SkinTonePicker({
39
+ direction = SkinTonePickerDirection.HORIZONTAL
40
+ }: Props) {
22
41
  const SkinTonePickerRef = useSkinTonePickerRef();
23
42
  const isDisabled = useSkinTonesDisabledConfig();
24
43
  const [isOpen, setIsOpen] = useSkinToneFanOpenState();
@@ -30,11 +49,22 @@ export function SkinTonePicker() {
30
49
  return null;
31
50
  }
32
51
 
52
+ const fullWidth = `${ITEM_SIZE * skinToneVariations.length}px`;
53
+
54
+ const expandedSize = isOpen ? fullWidth : ITEM_SIZE + 'px';
55
+
56
+ const vertical = direction === SkinTonePickerDirection.VERTICAL;
57
+
33
58
  return (
34
59
  <Relative
35
- className={clsx('epr-skin-tones', {
36
- open: isOpen
60
+ className={clsx('epr-skin-tones', direction, {
61
+ [ClassNames.open]: isOpen
37
62
  })}
63
+ style={
64
+ vertical
65
+ ? { flexBasis: expandedSize, height: expandedSize }
66
+ : { flexBasis: expandedSize }
67
+ }
38
68
  >
39
69
  <div className="epr-skin-tone-select" ref={SkinTonePickerRef}>
40
70
  {skinToneVariations.map((skinToneVariation, i) => {
@@ -43,7 +73,9 @@ export function SkinTonePicker() {
43
73
  <Button
44
74
  style={{
45
75
  transform: clsx(
46
- `translateX(-${i * (isOpen ? 28 : 0)}px)`,
76
+ vertical
77
+ ? `translateY(-${i * (isOpen ? ITEM_SIZE : 0)}px)`
78
+ : `translateX(-${i * (isOpen ? ITEM_SIZE : 0)}px)`,
47
79
  isOpen && active && 'scale(1.3)'
48
80
  )
49
81
  }}
@@ -72,3 +104,8 @@ export function SkinTonePicker() {
72
104
  </Relative>
73
105
  );
74
106
  }
107
+
108
+ export enum SkinTonePickerDirection {
109
+ VERTICAL = ClassNames.vertical,
110
+ HORIZONTAL = ClassNames.horizontal
111
+ }
@@ -3,6 +3,7 @@ import { emojiUrlByUnified } from '../dataUtils/emojiSelectors';
3
3
  import {
4
4
  EmojiClickData,
5
5
  EmojiStyle,
6
+ SkinTonePickerLocation,
6
7
  SkinTones,
7
8
  SuggestionMode,
8
9
  Theme
@@ -29,10 +30,15 @@ export function mergeConfig(
29
30
  suggestionMode: config.suggestedEmojisMode
30
31
  });
31
32
 
33
+ const skinTonePickerLocation = config.searchDisabled
34
+ ? SkinTonePickerLocation.PREVIEW
35
+ : config.skinTonePickerLocation;
36
+
32
37
  return {
33
38
  ...config,
34
39
  categories,
35
- previewConfig
40
+ previewConfig,
41
+ skinTonePickerLocation
36
42
  };
37
43
  }
38
44
 
@@ -57,7 +63,9 @@ export function basePickerConfig(): PickerConfigInternal {
57
63
  previewConfig: {
58
64
  ...basePreviewConfig
59
65
  },
66
+ searchDisabled: false,
60
67
  searchPlaceHolder: 'Search',
68
+ skinTonePickerLocation: SkinTonePickerLocation.SEARCH,
61
69
  skinTonesDisabled: false,
62
70
  suggestedEmojisMode: SuggestionMode.FREQUENT,
63
71
  theme: Theme.LIGHT,
@@ -81,6 +89,8 @@ export type PickerConfigInternal = {
81
89
  height: PickerDimensions;
82
90
  width: PickerDimensions;
83
91
  getEmojiUrl: GetEmojiUrl;
92
+ searchDisabled: boolean;
93
+ skinTonePickerLocation: SkinTonePickerLocation;
84
94
  };
85
95
 
86
96
  export type PreviewConfig = {
@@ -3,6 +3,7 @@ import { usePickerConfig } from '../components/context/PickerConfigContext';
3
3
  import {
4
4
  EmojiClickData,
5
5
  EmojiStyle,
6
+ SkinTonePickerLocation,
6
7
  SkinTones,
7
8
  SuggestionMode,
8
9
  Theme
@@ -87,6 +88,16 @@ export function useEmojiVersionConfig(): string | null {
87
88
  return emojiVersion;
88
89
  }
89
90
 
91
+ export function useSearchDisabledConfig(): boolean {
92
+ const { searchDisabled } = usePickerConfig();
93
+ return searchDisabled;
94
+ }
95
+
96
+ export function useSkinTonePickerLocationConfig(): SkinTonePickerLocation {
97
+ const { skinTonePickerLocation } = usePickerConfig();
98
+ return skinTonePickerLocation;
99
+ }
100
+
90
101
  export function useGetEmojiUrlConfig(): (
91
102
  unified: string,
92
103
  style: EmojiStyle
@@ -38,6 +38,10 @@ import {
38
38
  } from './useFocus';
39
39
  import useIsSearchMode from './useIsSearchMode';
40
40
  import useSetVariationPicker from './useSetVariationPicker';
41
+ import {
42
+ useIsSkinToneInPreview,
43
+ useIsSkinToneInSearch
44
+ } from './useShouldShowSkinTonePicker';
41
45
 
42
46
  enum KeyboardEvents {
43
47
  ArrowDown = 'ArrowDown',
@@ -120,6 +124,7 @@ function useSearchInputKeyboardEvents() {
120
124
  const SearchInputRef = useSearchInputRef();
121
125
  const [, setSkinToneFanOpenState] = useSkinToneFanOpenState();
122
126
  const goDownFromSearchInput = useGoDownFromSearchInput();
127
+ const isSkinToneInSearch = useIsSkinToneInSearch();
123
128
 
124
129
  const onKeyDown = useMemo(
125
130
  () =>
@@ -128,6 +133,9 @@ function useSearchInputKeyboardEvents() {
128
133
 
129
134
  switch (key) {
130
135
  case KeyboardEvents.ArrowRight:
136
+ if (!isSkinToneInSearch) {
137
+ return;
138
+ }
131
139
  event.preventDefault();
132
140
  setSkinToneFanOpenState(true);
133
141
  focusSkinTonePicker();
@@ -171,41 +179,76 @@ function useSkinTonePickerKeyboardEvents() {
171
179
  const SearchInputRef = useSearchInputRef();
172
180
  const goDownFromSearchInput = useGoDownFromSearchInput();
173
181
  const [isOpen, setIsOpen] = useSkinToneFanOpenState();
182
+ const isSkinToneInPreview = useIsSkinToneInPreview();
183
+ const isSkinToneInSearch = useIsSkinToneInSearch();
174
184
  const onType = useOnType();
175
185
 
176
186
  const onKeyDown = useMemo(
177
187
  () =>
188
+ // eslint-disable-next-line complexity
178
189
  function onKeyDown(event: KeyboardEvent) {
179
190
  const { key } = event;
180
191
 
181
- switch (key) {
182
- case KeyboardEvents.ArrowLeft:
183
- event.preventDefault();
184
- if (!isOpen) {
185
- return focusSearchInput();
186
- }
187
- focusNextSkinTone(focusSearchInput);
188
- break;
189
- case KeyboardEvents.ArrowRight:
190
- event.preventDefault();
191
- if (!isOpen) {
192
- return focusSearchInput();
193
- }
194
- focusPrevSkinTone();
195
- break;
196
- case KeyboardEvents.ArrowDown:
197
- event.preventDefault();
198
- if (isOpen) {
199
- setIsOpen(false);
200
- }
201
- goDownFromSearchInput();
202
- break;
203
- default:
204
- onType(event);
205
- break;
192
+ if (isSkinToneInSearch) {
193
+ switch (key) {
194
+ case KeyboardEvents.ArrowLeft:
195
+ event.preventDefault();
196
+ if (!isOpen) {
197
+ return focusSearchInput();
198
+ }
199
+ focusNextSkinTone(focusSearchInput);
200
+ break;
201
+ case KeyboardEvents.ArrowRight:
202
+ event.preventDefault();
203
+ if (!isOpen) {
204
+ return focusSearchInput();
205
+ }
206
+ focusPrevSkinTone();
207
+ break;
208
+ case KeyboardEvents.ArrowDown:
209
+ event.preventDefault();
210
+ if (isOpen) {
211
+ setIsOpen(false);
212
+ }
213
+ goDownFromSearchInput();
214
+ break;
215
+ default:
216
+ onType(event);
217
+ break;
218
+ }
219
+ }
220
+
221
+ if (isSkinToneInPreview) {
222
+ switch (key) {
223
+ case KeyboardEvents.ArrowUp:
224
+ event.preventDefault();
225
+ if (!isOpen) {
226
+ return focusSearchInput();
227
+ }
228
+ focusNextSkinTone(focusSearchInput);
229
+ break;
230
+ case KeyboardEvents.ArrowDown:
231
+ event.preventDefault();
232
+ if (!isOpen) {
233
+ return focusSearchInput();
234
+ }
235
+ focusPrevSkinTone();
236
+ break;
237
+ default:
238
+ onType(event);
239
+ break;
240
+ }
206
241
  }
207
242
  },
208
- [isOpen, focusSearchInput, setIsOpen, goDownFromSearchInput, onType]
243
+ [
244
+ isOpen,
245
+ focusSearchInput,
246
+ setIsOpen,
247
+ goDownFromSearchInput,
248
+ onType,
249
+ isSkinToneInPreview,
250
+ isSkinToneInSearch
251
+ ]
209
252
  );
210
253
 
211
254
  useEffect(() => {
@@ -0,0 +1,22 @@
1
+ import { useSkinTonePickerLocationConfig } from '../config/useConfig';
2
+ import { SkinTonePickerLocation } from '../types/exposedTypes';
3
+
4
+ export function useShouldShowSkinTonePicker() {
5
+ const skinTonePickerLocationConfig = useSkinTonePickerLocationConfig();
6
+
7
+ return function shouldShowSkinTonePicker(location: SkinTonePickerLocation) {
8
+ return skinTonePickerLocationConfig === location;
9
+ };
10
+ }
11
+
12
+ export function useIsSkinToneInSearch() {
13
+ const skinTonePickerLocationConfig = useSkinTonePickerLocationConfig();
14
+
15
+ return skinTonePickerLocationConfig === SkinTonePickerLocation.SEARCH;
16
+ }
17
+
18
+ export function useIsSkinToneInPreview() {
19
+ const skinTonePickerLocationConfig = useSkinTonePickerLocationConfig();
20
+
21
+ return skinTonePickerLocationConfig === SkinTonePickerLocation.PREVIEW;
22
+ }
@@ -9,7 +9,7 @@ export type EmojiClickData = {
9
9
 
10
10
  export enum SuggestionMode {
11
11
  RECENT = 'recent',
12
- FREQUENT = 'frequent',
12
+ FREQUENT = 'frequent'
13
13
  }
14
14
 
15
15
  export enum EmojiStyle {
@@ -17,13 +17,13 @@ export enum EmojiStyle {
17
17
  APPLE = 'apple',
18
18
  TWITTER = 'twitter',
19
19
  GOOGLE = 'google',
20
- FACEBOOK = 'facebook',
20
+ FACEBOOK = 'facebook'
21
21
  }
22
22
 
23
23
  export enum Theme {
24
24
  DARK = 'dark',
25
25
  LIGHT = 'light',
26
- AUTO = 'auto',
26
+ AUTO = 'auto'
27
27
  }
28
28
 
29
29
  export enum SkinTones {
@@ -32,7 +32,7 @@ export enum SkinTones {
32
32
  MEDIUM_LIGHT = '1f3fc',
33
33
  MEDIUM = '1f3fd',
34
34
  MEDIUM_DARK = '1f3fe',
35
- DARK = '1f3ff',
35
+ DARK = '1f3ff'
36
36
  }
37
37
 
38
38
  export enum Categories {
@@ -44,5 +44,10 @@ export enum Categories {
44
44
  ACTIVITIES = 'activities',
45
45
  OBJECTS = 'objects',
46
46
  SYMBOLS = 'symbols',
47
- FLAGS = 'flags',
47
+ FLAGS = 'flags'
48
+ }
49
+
50
+ export enum SkinTonePickerLocation {
51
+ SEARCH = 'SEARCH',
52
+ PREVIEW = 'PREVIEW'
48
53
  }