emoji-picker-react 4.4.0-rc.1 → 4.4.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.
- 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 -3
- package/dist/config/useConfig.d.ts +3 -3
- package/dist/emoji-picker-react.cjs.development.css +4 -4
- package/dist/emoji-picker-react.cjs.development.js +254 -128
- 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 +266 -140
- 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 -4
- package/src/config/useConfig.ts +11 -8
- package/src/hooks/useDisallowedEmojis.ts +4 -17
- package/src/hooks/useFilter.ts +9 -10
- package/src/hooks/useKeyboardNavigation.ts +69 -26
- package/src/hooks/useShouldShowSkinTonePicker.ts +22 -0
- package/src/types/exposedTypes.ts +10 -5
- package/dist/predicates/isFunction.d.ts +0 -1
- package/src/predicates/isFunction.ts +0 -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
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { GetEmojiUrl } from '../components/emoji/Emoji';
|
|
2
|
-
import { DataEmoji } from '../dataUtils/DataTypes';
|
|
3
2
|
import { emojiUrlByUnified } from '../dataUtils/emojiSelectors';
|
|
4
3
|
import {
|
|
5
4
|
EmojiClickData,
|
|
6
5
|
EmojiStyle,
|
|
6
|
+
SkinTonePickerLocation,
|
|
7
7
|
SkinTones,
|
|
8
8
|
SuggestionMode,
|
|
9
9
|
Theme
|
|
@@ -30,10 +30,15 @@ export function mergeConfig(
|
|
|
30
30
|
suggestionMode: config.suggestedEmojisMode
|
|
31
31
|
});
|
|
32
32
|
|
|
33
|
+
const skinTonePickerLocation = config.searchDisabled
|
|
34
|
+
? SkinTonePickerLocation.PREVIEW
|
|
35
|
+
: config.skinTonePickerLocation;
|
|
36
|
+
|
|
33
37
|
return {
|
|
34
38
|
...config,
|
|
35
39
|
categories,
|
|
36
|
-
previewConfig
|
|
40
|
+
previewConfig,
|
|
41
|
+
skinTonePickerLocation
|
|
37
42
|
};
|
|
38
43
|
}
|
|
39
44
|
|
|
@@ -58,8 +63,9 @@ export function basePickerConfig(): PickerConfigInternal {
|
|
|
58
63
|
previewConfig: {
|
|
59
64
|
...basePreviewConfig
|
|
60
65
|
},
|
|
66
|
+
searchDisabled: false,
|
|
61
67
|
searchPlaceHolder: 'Search',
|
|
62
|
-
|
|
68
|
+
skinTonePickerLocation: SkinTonePickerLocation.SEARCH,
|
|
63
69
|
skinTonesDisabled: false,
|
|
64
70
|
suggestedEmojisMode: SuggestionMode.FREQUENT,
|
|
65
71
|
theme: Theme.LIGHT,
|
|
@@ -83,7 +89,8 @@ export type PickerConfigInternal = {
|
|
|
83
89
|
height: PickerDimensions;
|
|
84
90
|
width: PickerDimensions;
|
|
85
91
|
getEmojiUrl: GetEmojiUrl;
|
|
86
|
-
|
|
92
|
+
searchDisabled: boolean;
|
|
93
|
+
skinTonePickerLocation: SkinTonePickerLocation;
|
|
87
94
|
};
|
|
88
95
|
|
|
89
96
|
export type PreviewConfig = {
|
package/src/config/useConfig.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { isSystemDarkTheme } from '../DomUtils/isDarkTheme';
|
|
2
2
|
import { usePickerConfig } from '../components/context/PickerConfigContext';
|
|
3
|
-
import { DataEmoji } from '../dataUtils/DataTypes';
|
|
4
3
|
import {
|
|
5
4
|
EmojiClickData,
|
|
6
5
|
EmojiStyle,
|
|
6
|
+
SkinTonePickerLocation,
|
|
7
7
|
SkinTones,
|
|
8
8
|
SuggestionMode,
|
|
9
9
|
Theme
|
|
@@ -88,6 +88,16 @@ export function useEmojiVersionConfig(): string | null {
|
|
|
88
88
|
return emojiVersion;
|
|
89
89
|
}
|
|
90
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
|
+
|
|
91
101
|
export function useGetEmojiUrlConfig(): (
|
|
92
102
|
unified: string,
|
|
93
103
|
style: EmojiStyle
|
|
@@ -96,13 +106,6 @@ export function useGetEmojiUrlConfig(): (
|
|
|
96
106
|
return getEmojiUrl;
|
|
97
107
|
}
|
|
98
108
|
|
|
99
|
-
export function useShowEmojiConfig():
|
|
100
|
-
| undefined
|
|
101
|
-
| ((emoji: DataEmoji) => boolean) {
|
|
102
|
-
const { showEmoji } = usePickerConfig();
|
|
103
|
-
return showEmoji;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
109
|
function getDimension(dimensionConfig: PickerDimensions): PickerDimensions {
|
|
107
110
|
return typeof dimensionConfig === 'number'
|
|
108
111
|
? `${dimensionConfig}px`
|
|
@@ -1,41 +1,28 @@
|
|
|
1
1
|
import { useRef, useMemo } from 'react';
|
|
2
2
|
|
|
3
|
-
import { useEmojiVersionConfig
|
|
3
|
+
import { useEmojiVersionConfig } 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';
|
|
7
6
|
|
|
8
7
|
export function useDisallowedEmojis() {
|
|
9
8
|
const DisallowedEmojisRef = useRef<Record<string, boolean>>({});
|
|
10
9
|
const emojiVersionConfig = useEmojiVersionConfig();
|
|
11
|
-
const shouldShowEmoji = useShowEmojiConfig();
|
|
12
10
|
|
|
13
11
|
return useMemo(() => {
|
|
14
12
|
const emojiVersion = parseFloat(`${emojiVersionConfig}`);
|
|
15
13
|
|
|
16
|
-
if (
|
|
17
|
-
(!emojiVersionConfig || Number.isNaN(emojiVersion)) &&
|
|
18
|
-
!shouldShowEmoji
|
|
19
|
-
) {
|
|
14
|
+
if (!emojiVersionConfig || Number.isNaN(emojiVersion)) {
|
|
20
15
|
return DisallowedEmojisRef.current;
|
|
21
16
|
}
|
|
22
17
|
|
|
23
18
|
return allEmojis.reduce((disallowedEmojis, emoji) => {
|
|
24
|
-
if (isFunction(shouldShowEmoji) && !shouldShowEmoji(emoji)) {
|
|
25
|
-
disallowEmoji();
|
|
26
|
-
}
|
|
27
|
-
|
|
28
19
|
if (addedInNewerVersion(emoji, emojiVersion)) {
|
|
29
|
-
|
|
20
|
+
disallowedEmojis[emojiUnified(emoji)] = true;
|
|
30
21
|
}
|
|
31
22
|
|
|
32
23
|
return disallowedEmojis;
|
|
33
|
-
|
|
34
|
-
function disallowEmoji() {
|
|
35
|
-
disallowedEmojis[emojiUnified(emoji)] = true;
|
|
36
|
-
}
|
|
37
24
|
}, DisallowedEmojisRef.current);
|
|
38
|
-
}, [emojiVersionConfig
|
|
25
|
+
}, [emojiVersionConfig]);
|
|
39
26
|
}
|
|
40
27
|
|
|
41
28
|
function addedInNewerVersion(
|
package/src/hooks/useFilter.ts
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
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';
|
|
14
13
|
|
|
15
14
|
import { useFocusSearchInput } from './useFocus';
|
|
16
15
|
|
|
@@ -20,7 +19,7 @@ function useSetFilterRef() {
|
|
|
20
19
|
return function setFilter(
|
|
21
20
|
setter: FilterState | ((current: FilterState) => FilterState)
|
|
22
21
|
): void {
|
|
23
|
-
if (
|
|
22
|
+
if (typeof setter === 'function') {
|
|
24
23
|
return setFilter(setter(filterRef.current));
|
|
25
24
|
}
|
|
26
25
|
|
|
@@ -68,7 +67,7 @@ export function useFilter() {
|
|
|
68
67
|
return {
|
|
69
68
|
onChange,
|
|
70
69
|
searchTerm,
|
|
71
|
-
SearchInputRef
|
|
70
|
+
SearchInputRef,
|
|
72
71
|
};
|
|
73
72
|
|
|
74
73
|
function onChange(inputValue: string) {
|
|
@@ -88,9 +87,9 @@ export function useFilter() {
|
|
|
88
87
|
return applySearch(nextValue);
|
|
89
88
|
}
|
|
90
89
|
|
|
91
|
-
setFilterRef(current =>
|
|
90
|
+
setFilterRef((current) =>
|
|
92
91
|
Object.assign(current, {
|
|
93
|
-
[nextValue]: filterEmojiObjectByKeyword(longestMatch, nextValue)
|
|
92
|
+
[nextValue]: filterEmojiObjectByKeyword(longestMatch, nextValue),
|
|
94
93
|
})
|
|
95
94
|
);
|
|
96
95
|
applySearch(nextValue);
|
|
@@ -130,14 +129,14 @@ function filterEmojiObjectByKeyword(
|
|
|
130
129
|
}
|
|
131
130
|
|
|
132
131
|
function hasMatch(emoji: DataEmoji, keyword: string): boolean {
|
|
133
|
-
return emojiNames(emoji).some(name => name.includes(keyword));
|
|
132
|
+
return emojiNames(emoji).some((name) => name.includes(keyword));
|
|
134
133
|
}
|
|
135
134
|
|
|
136
135
|
export function useIsEmojiFiltered(): (unified: string) => boolean {
|
|
137
136
|
const { current: filter } = useFilterRef();
|
|
138
137
|
const [searchTerm] = useSearchTermState();
|
|
139
138
|
|
|
140
|
-
return unified => isEmojiFilteredBySearchTerm(unified, filter, searchTerm);
|
|
139
|
+
return (unified) => isEmojiFilteredBySearchTerm(unified, filter, searchTerm);
|
|
141
140
|
}
|
|
142
141
|
|
|
143
142
|
function isEmojiFilteredBySearchTerm(
|
|
@@ -168,7 +167,7 @@ function findLongestMatch(
|
|
|
168
167
|
|
|
169
168
|
const longestMatchingKey = Object.keys(dict)
|
|
170
169
|
.sort((a, b) => b.length - a.length)
|
|
171
|
-
.find(key => keyword.includes(key));
|
|
170
|
+
.find((key) => keyword.includes(key));
|
|
172
171
|
|
|
173
172
|
if (longestMatchingKey) {
|
|
174
173
|
return dict[longestMatchingKey];
|