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.
- package/README.md +26 -16
- package/dist/DomUtils/classNames.d.ts +4 -1
- package/dist/components/Layout/Absolute.d.ts +8 -0
- package/dist/components/Layout/Relative.d.ts +2 -1
- package/dist/components/Layout/Space.d.ts +7 -0
- package/dist/components/footer/Preview.d.ts +1 -0
- package/dist/components/header/Search.d.ts +1 -0
- package/dist/components/header/SkinTonePicker.d.ts +10 -1
- package/dist/config/config.d.ts +3 -1
- package/dist/config/useConfig.d.ts +3 -1
- package/dist/emoji-picker-react.cjs.development.css +4 -4
- package/dist/emoji-picker-react.cjs.development.js +252 -106
- package/dist/emoji-picker-react.cjs.development.js.map +1 -1
- package/dist/emoji-picker-react.cjs.production.min.js +1 -1
- package/dist/emoji-picker-react.cjs.production.min.js.map +1 -1
- package/dist/emoji-picker-react.esm.js +264 -118
- package/dist/emoji-picker-react.esm.js.map +1 -1
- package/dist/hooks/useShouldShowSkinTonePicker.d.ts +4 -0
- package/dist/types/exposedTypes.d.ts +4 -0
- package/package.json +1 -1
- package/src/DomUtils/classNames.ts +4 -1
- package/src/EmojiPickerReact.css +3 -0
- package/src/components/Layout/Absolute.tsx +15 -0
- package/src/components/Layout/Relative.tsx +3 -2
- package/src/components/Layout/Space.tsx +11 -0
- package/src/components/footer/Preview.css +2 -0
- package/src/components/footer/Preview.tsx +23 -11
- package/src/components/header/Header.tsx +2 -7
- package/src/components/header/Search.tsx +25 -3
- package/src/components/header/SkinTonePicker.css +19 -9
- package/src/components/header/SkinTonePicker.tsx +41 -4
- package/src/config/config.ts +11 -1
- package/src/config/useConfig.ts +11 -0
- package/src/hooks/useKeyboardNavigation.ts +69 -26
- package/src/hooks/useShouldShowSkinTonePicker.ts +22 -0
- 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;
|
package/package.json
CHANGED
|
@@ -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(
|
|
22
|
+
return classNames.map(c => `.${c}`).join('');
|
|
20
23
|
}
|
package/src/EmojiPickerReact.css
CHANGED
|
@@ -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,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
|
-
<
|
|
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
|
-
|
|
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={
|
|
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:
|
|
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
|
-
|
|
10
|
+
padding: 10px 0;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
.EmojiPickerReact .epr-skin-tones.
|
|
14
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
+
}
|
package/src/config/config.ts
CHANGED
|
@@ -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 = {
|
package/src/config/useConfig.ts
CHANGED
|
@@ -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
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
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
|
-
[
|
|
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
|
}
|