emoji-picker-react 4.1.1 → 4.3.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 +33 -25
- package/dist/components/emoji/Emoji.d.ts +4 -2
- package/dist/components/emoji/ExportedEmoji.d.ts +3 -1
- package/dist/config/cdnUrls.d.ts +1 -1
- package/dist/config/config.d.ts +5 -2
- package/dist/config/useConfig.d.ts +4 -3
- package/dist/dataUtils/emojiSelectors.d.ts +1 -2
- package/dist/emoji-picker-react.cjs.development.js +289 -258
- 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 +289 -258
- package/dist/emoji-picker-react.esm.js.map +1 -1
- package/dist/hooks/preloadEmoji.d.ts +2 -1
- package/package.json +1 -1
- package/src/components/body/EmojiList.tsx +3 -0
- package/src/components/body/EmojiVariationPicker.tsx +13 -8
- package/src/components/body/Suggested.tsx +5 -2
- package/src/components/emoji/Emoji.tsx +17 -8
- package/src/components/emoji/ExportedEmoji.tsx +5 -2
- package/src/components/footer/Preview.tsx +9 -2
- package/src/components/main/PickerMain.tsx +3 -3
- package/src/config/cdnUrls.ts +1 -1
- package/src/config/config.ts +15 -9
- package/src/config/useConfig.ts +21 -4
- package/src/dataUtils/emojiSelectors.ts +3 -10
- package/src/hooks/preloadEmoji.ts +5 -7
- package/src/hooks/useMouseDownHandlers.ts +19 -13
- package/src/hooks/useOnFocus.ts +4 -3
|
@@ -1,4 +1,5 @@
|
|
|
1
|
+
import { GetEmojiUrl } from '../components/emoji/Emoji';
|
|
1
2
|
import { DataEmoji } from '../dataUtils/DataTypes';
|
|
2
3
|
import { EmojiStyle } from '../types/exposedTypes';
|
|
3
|
-
export declare function preloadEmoji(emoji: undefined | DataEmoji, emojiStyle: EmojiStyle): void;
|
|
4
|
+
export declare function preloadEmoji(getEmojiUrl: GetEmojiUrl, emoji: undefined | DataEmoji, emojiStyle: EmojiStyle): void;
|
|
4
5
|
export declare const preloadedEmojs: Set<string>;
|
package/package.json
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
import {
|
|
10
10
|
useCategoriesConfig,
|
|
11
11
|
useEmojiStyleConfig,
|
|
12
|
+
useGetEmojiUrlConfig,
|
|
12
13
|
useLazyLoadEmojisConfig,
|
|
13
14
|
} from '../../config/useConfig';
|
|
14
15
|
import { emojisByCategory, emojiUnified } from '../../dataUtils/emojiSelectors';
|
|
@@ -65,6 +66,7 @@ function RenderCategory({
|
|
|
65
66
|
const isPastInitialLoad = useIsPastInitialLoad();
|
|
66
67
|
const [activeSkinTone] = useActiveSkinToneState();
|
|
67
68
|
const disallowedEmojisRef = useDisallowedEmojisRef();
|
|
69
|
+
const getEmojiUrl = useGetEmojiUrlConfig();
|
|
68
70
|
|
|
69
71
|
// Small trick to defer the rendering of all emoji categories until the first category is visible
|
|
70
72
|
// This way the user gets to actually see something and not wait for the whole picker to render.
|
|
@@ -96,6 +98,7 @@ function RenderCategory({
|
|
|
96
98
|
hiddenOnSearch={filteredOut}
|
|
97
99
|
emojiStyle={emojiStyle}
|
|
98
100
|
lazyLoad={lazyLoadEmojis}
|
|
101
|
+
getEmojiUrl={getEmojiUrl}
|
|
99
102
|
/>
|
|
100
103
|
);
|
|
101
104
|
});
|
|
@@ -7,20 +7,23 @@ import {
|
|
|
7
7
|
buttonFromTarget,
|
|
8
8
|
elementHeight,
|
|
9
9
|
emojiTrueOffsetTop,
|
|
10
|
-
emojiTruOffsetLeft
|
|
10
|
+
emojiTruOffsetLeft,
|
|
11
11
|
} from '../../DomUtils/selectors';
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
useEmojiStyleConfig,
|
|
14
|
+
useGetEmojiUrlConfig,
|
|
15
|
+
} from '../../config/useConfig';
|
|
13
16
|
import { asEmoji } from '../../dataUtils/asEmoji';
|
|
14
17
|
import {
|
|
15
18
|
emojiHasVariations,
|
|
16
19
|
emojiUnified,
|
|
17
|
-
emojiVariations
|
|
20
|
+
emojiVariations,
|
|
18
21
|
} from '../../dataUtils/emojiSelectors';
|
|
19
22
|
import {
|
|
20
23
|
useAnchoredEmojiRef,
|
|
21
24
|
useBodyRef,
|
|
22
25
|
useSetAnchoredEmojiRef,
|
|
23
|
-
useVariationPickerRef
|
|
26
|
+
useVariationPickerRef,
|
|
24
27
|
} from '../context/ElementRefContext';
|
|
25
28
|
import { useEmojiVariationPickerState } from '../context/PickerContext';
|
|
26
29
|
import { ClickableEmoji } from '../emoji/Emoji';
|
|
@@ -28,7 +31,7 @@ import './EmojiVariationPicker.css';
|
|
|
28
31
|
|
|
29
32
|
enum Direction {
|
|
30
33
|
Up,
|
|
31
|
-
Down
|
|
34
|
+
Down,
|
|
32
35
|
}
|
|
33
36
|
|
|
34
37
|
export function EmojiVariationPicker() {
|
|
@@ -41,6 +44,7 @@ export function EmojiVariationPicker() {
|
|
|
41
44
|
);
|
|
42
45
|
const setAnchoredEmojiRef = useSetAnchoredEmojiRef();
|
|
43
46
|
const getPointerStyle = usePointerStyle(VariationPickerRef);
|
|
47
|
+
const getEmojiUrl = useGetEmojiUrlConfig();
|
|
44
48
|
|
|
45
49
|
const button = buttonFromTarget(AnchoredEmojiRef.current);
|
|
46
50
|
|
|
@@ -67,7 +71,7 @@ export function EmojiVariationPicker() {
|
|
|
67
71
|
ref={VariationPickerRef}
|
|
68
72
|
className={clsx('epr-emoji-variation-picker', {
|
|
69
73
|
visible,
|
|
70
|
-
'pointing-up': getMenuDirection() === Direction.Down
|
|
74
|
+
'pointing-up': getMenuDirection() === Direction.Down,
|
|
71
75
|
})}
|
|
72
76
|
style={{ top }}
|
|
73
77
|
>
|
|
@@ -75,13 +79,14 @@ export function EmojiVariationPicker() {
|
|
|
75
79
|
? [emojiUnified(safeEmoji)]
|
|
76
80
|
.concat(emojiVariations(safeEmoji))
|
|
77
81
|
.slice(0, 6)
|
|
78
|
-
.map(unified => (
|
|
82
|
+
.map((unified) => (
|
|
79
83
|
<ClickableEmoji
|
|
80
84
|
key={unified}
|
|
81
85
|
emoji={safeEmoji}
|
|
82
86
|
unified={unified}
|
|
83
87
|
emojiStyle={emojiStyle}
|
|
84
88
|
showVariations={false}
|
|
89
|
+
getEmojiUrl={getEmojiUrl}
|
|
85
90
|
/>
|
|
86
91
|
))
|
|
87
92
|
: null}
|
|
@@ -124,7 +129,7 @@ function useVariationPickerTop(
|
|
|
124
129
|
|
|
125
130
|
return {
|
|
126
131
|
getMenuDirection,
|
|
127
|
-
getTop
|
|
132
|
+
getTop,
|
|
128
133
|
};
|
|
129
134
|
|
|
130
135
|
function getMenuDirection() {
|
|
@@ -3,7 +3,8 @@ import * as React from 'react';
|
|
|
3
3
|
import { CategoryConfig } from '../../config/categoryConfig';
|
|
4
4
|
import {
|
|
5
5
|
useEmojiStyleConfig,
|
|
6
|
-
|
|
6
|
+
useGetEmojiUrlConfig,
|
|
7
|
+
useSuggestedEmojisModeConfig,
|
|
7
8
|
} from '../../config/useConfig';
|
|
8
9
|
import { emojiByUnified } from '../../dataUtils/emojiSelectors';
|
|
9
10
|
import { getsuggested } from '../../dataUtils/suggested';
|
|
@@ -19,6 +20,7 @@ type Props = Readonly<{
|
|
|
19
20
|
export function Suggested({ categoryConfig }: Props) {
|
|
20
21
|
const [suggestedUpdated] = useUpdateSuggested();
|
|
21
22
|
const suggestedEmojisModeConfig = useSuggestedEmojisModeConfig();
|
|
23
|
+
const getEmojiUrl = useGetEmojiUrlConfig();
|
|
22
24
|
const suggested = React.useMemo(
|
|
23
25
|
() => getsuggested(suggestedEmojisModeConfig) ?? [],
|
|
24
26
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
@@ -32,7 +34,7 @@ export function Suggested({ categoryConfig }: Props) {
|
|
|
32
34
|
hiddenOnSearch
|
|
33
35
|
hidden={suggested.length === 0}
|
|
34
36
|
>
|
|
35
|
-
{suggested.map(suggestedItem => {
|
|
37
|
+
{suggested.map((suggestedItem) => {
|
|
36
38
|
const emoji = emojiByUnified(suggestedItem.original);
|
|
37
39
|
|
|
38
40
|
if (!emoji) {
|
|
@@ -46,6 +48,7 @@ export function Suggested({ categoryConfig }: Props) {
|
|
|
46
48
|
emojiStyle={emojiStyle}
|
|
47
49
|
emoji={emoji}
|
|
48
50
|
key={suggestedItem.unified}
|
|
51
|
+
getEmojiUrl={getEmojiUrl}
|
|
49
52
|
/>
|
|
50
53
|
);
|
|
51
54
|
})}
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
emojiHasVariations,
|
|
10
10
|
emojiName,
|
|
11
11
|
emojiNames,
|
|
12
|
-
emojiUrlByUnified
|
|
12
|
+
emojiUrlByUnified,
|
|
13
13
|
} from '../../dataUtils/emojiSelectors';
|
|
14
14
|
import { parseNativeEmoji } from '../../dataUtils/parseNativeEmoji';
|
|
15
15
|
import { EmojiStyle } from '../../types/exposedTypes';
|
|
@@ -32,6 +32,7 @@ type BaseProps = {
|
|
|
32
32
|
unified: string;
|
|
33
33
|
size?: number;
|
|
34
34
|
lazyLoad?: boolean;
|
|
35
|
+
getEmojiUrl?: GetEmojiUrl;
|
|
35
36
|
};
|
|
36
37
|
|
|
37
38
|
export function ClickableEmoji({
|
|
@@ -42,7 +43,8 @@ export function ClickableEmoji({
|
|
|
42
43
|
emojiStyle,
|
|
43
44
|
showVariations = true,
|
|
44
45
|
size,
|
|
45
|
-
lazyLoad
|
|
46
|
+
lazyLoad,
|
|
47
|
+
getEmojiUrl,
|
|
46
48
|
}: ClickableEmojiProps) {
|
|
47
49
|
const hasVariations = emojiHasVariations(emoji);
|
|
48
50
|
|
|
@@ -52,7 +54,7 @@ export function ClickableEmoji({
|
|
|
52
54
|
[ClassNames.hidden]: hidden,
|
|
53
55
|
[ClassNames.hiddenOnSearch]: hiddenOnSearch,
|
|
54
56
|
[ClassNames.visible]: !hidden && !hiddenOnSearch,
|
|
55
|
-
[ClassNames.emojiHasVariatios]: hasVariations && showVariations
|
|
57
|
+
[ClassNames.emojiHasVariatios]: hasVariations && showVariations,
|
|
56
58
|
})}
|
|
57
59
|
data-unified={unified}
|
|
58
60
|
// @ts-ignore - let's ignore the fact this is not a real react ref, ok?
|
|
@@ -65,6 +67,7 @@ export function ClickableEmoji({
|
|
|
65
67
|
size={size}
|
|
66
68
|
emojiStyle={emojiStyle}
|
|
67
69
|
lazyLoad={lazyLoad}
|
|
70
|
+
getEmojiUrl={getEmojiUrl}
|
|
68
71
|
/>
|
|
69
72
|
</Button>
|
|
70
73
|
);
|
|
@@ -75,7 +78,8 @@ export function ViewOnlyEmoji({
|
|
|
75
78
|
unified,
|
|
76
79
|
emojiStyle,
|
|
77
80
|
size,
|
|
78
|
-
lazyLoad
|
|
81
|
+
lazyLoad,
|
|
82
|
+
getEmojiUrl = emojiUrlByUnified,
|
|
79
83
|
}: BaseProps) {
|
|
80
84
|
const style = {} as React.CSSProperties;
|
|
81
85
|
if (size) {
|
|
@@ -95,6 +99,7 @@ export function ViewOnlyEmoji({
|
|
|
95
99
|
emoji={asEmoji(emojiToRender)}
|
|
96
100
|
emojiStyle={emojiStyle}
|
|
97
101
|
lazyLoad={lazyLoad}
|
|
102
|
+
getEmojiUrl={getEmojiUrl}
|
|
98
103
|
/>
|
|
99
104
|
)}
|
|
100
105
|
</>
|
|
@@ -103,7 +108,7 @@ export function ViewOnlyEmoji({
|
|
|
103
108
|
|
|
104
109
|
function NativeEmoji({
|
|
105
110
|
unified,
|
|
106
|
-
style
|
|
111
|
+
style,
|
|
107
112
|
}: {
|
|
108
113
|
unified: string;
|
|
109
114
|
style: React.CSSProperties;
|
|
@@ -124,19 +129,21 @@ function EmojiImg({
|
|
|
124
129
|
unified,
|
|
125
130
|
emojiStyle,
|
|
126
131
|
style,
|
|
127
|
-
lazyLoad = false
|
|
132
|
+
lazyLoad = false,
|
|
133
|
+
getEmojiUrl,
|
|
128
134
|
}: {
|
|
129
135
|
emoji: DataEmoji;
|
|
130
136
|
unified: string;
|
|
131
137
|
emojiStyle: EmojiStyle;
|
|
132
138
|
style: React.CSSProperties;
|
|
133
139
|
lazyLoad?: boolean;
|
|
140
|
+
getEmojiUrl: GetEmojiUrl;
|
|
134
141
|
}) {
|
|
135
142
|
const [, setEmojisThatFailedToLoad] = useEmojisThatFailedToLoadState();
|
|
136
143
|
|
|
137
144
|
return (
|
|
138
145
|
<img
|
|
139
|
-
src={
|
|
146
|
+
src={getEmojiUrl(unified, emojiStyle)}
|
|
140
147
|
alt={emojiName(emoji)}
|
|
141
148
|
className={clsx(ClassNames.external, 'epr-emoji-img')}
|
|
142
149
|
loading={lazyLoad ? 'lazy' : 'eager'}
|
|
@@ -146,6 +153,8 @@ function EmojiImg({
|
|
|
146
153
|
);
|
|
147
154
|
|
|
148
155
|
function onError() {
|
|
149
|
-
setEmojisThatFailedToLoad(prev => new Set(prev).add(unified));
|
|
156
|
+
setEmojisThatFailedToLoad((prev) => new Set(prev).add(unified));
|
|
150
157
|
}
|
|
151
158
|
}
|
|
159
|
+
|
|
160
|
+
export type GetEmojiUrl = (unified: string, style: EmojiStyle) => string;
|
|
@@ -2,18 +2,20 @@ import * as React from 'react';
|
|
|
2
2
|
|
|
3
3
|
import { EmojiStyle } from '../../types/exposedTypes';
|
|
4
4
|
|
|
5
|
-
import { ViewOnlyEmoji } from './Emoji';
|
|
5
|
+
import { GetEmojiUrl, ViewOnlyEmoji } from './Emoji';
|
|
6
6
|
|
|
7
7
|
export function ExportedEmoji({
|
|
8
8
|
unified,
|
|
9
9
|
size = 32,
|
|
10
10
|
emojiStyle = EmojiStyle.APPLE,
|
|
11
|
-
lazyLoad = false
|
|
11
|
+
lazyLoad = false,
|
|
12
|
+
getEmojiUrl,
|
|
12
13
|
}: {
|
|
13
14
|
unified: string;
|
|
14
15
|
emojiStyle?: EmojiStyle;
|
|
15
16
|
size?: number;
|
|
16
17
|
lazyLoad?: boolean;
|
|
18
|
+
getEmojiUrl?: GetEmojiUrl;
|
|
17
19
|
}) {
|
|
18
20
|
if (!unified) {
|
|
19
21
|
return null;
|
|
@@ -25,6 +27,7 @@ export function ExportedEmoji({
|
|
|
25
27
|
size={size}
|
|
26
28
|
emojiStyle={emojiStyle}
|
|
27
29
|
lazyLoad={lazyLoad}
|
|
30
|
+
getEmojiUrl={getEmojiUrl}
|
|
28
31
|
/>
|
|
29
32
|
);
|
|
30
33
|
}
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { useState } from 'react';
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
useEmojiStyleConfig,
|
|
6
|
+
useGetEmojiUrlConfig,
|
|
7
|
+
usePreviewConfig,
|
|
8
|
+
} from '../../config/useConfig';
|
|
5
9
|
import { asEmoji } from '../../dataUtils/asEmoji';
|
|
6
10
|
import {
|
|
7
11
|
emojiByUnified,
|
|
8
12
|
emojiName,
|
|
9
|
-
emojiUnified
|
|
13
|
+
emojiUnified,
|
|
10
14
|
} from '../../dataUtils/emojiSelectors';
|
|
11
15
|
import { useEmojiPreviewEvents } from '../../hooks/useEmojiPreviewEvents';
|
|
12
16
|
import Flex from '../Layout/Flex';
|
|
@@ -19,6 +23,7 @@ export function Preview() {
|
|
|
19
23
|
const [previewEmoji, setPreviewEmoji] = useState<PreviewEmoji>(null);
|
|
20
24
|
const emojiStyle = useEmojiStyleConfig();
|
|
21
25
|
const [variationPickerEmoji] = useEmojiVariationPickerState();
|
|
26
|
+
const getEmojiUrl = useGetEmojiUrlConfig();
|
|
22
27
|
|
|
23
28
|
useEmojiPreviewEvents(previewConfig.showPreview, setPreviewEmoji);
|
|
24
29
|
|
|
@@ -53,6 +58,7 @@ export function Preview() {
|
|
|
53
58
|
emoji={asEmoji(emoji)}
|
|
54
59
|
emojiStyle={emojiStyle}
|
|
55
60
|
size={45}
|
|
61
|
+
getEmojiUrl={getEmojiUrl}
|
|
56
62
|
/>
|
|
57
63
|
) : defaultEmoji ? (
|
|
58
64
|
<ViewOnlyEmoji
|
|
@@ -60,6 +66,7 @@ export function Preview() {
|
|
|
60
66
|
emoji={defaultEmoji}
|
|
61
67
|
emojiStyle={emojiStyle}
|
|
62
68
|
size={45}
|
|
69
|
+
getEmojiUrl={getEmojiUrl}
|
|
63
70
|
/>
|
|
64
71
|
) : null}
|
|
65
72
|
</div>
|
|
@@ -37,15 +37,15 @@ function PickerRootElement({ children }: RootProps) {
|
|
|
37
37
|
useOnFocus();
|
|
38
38
|
|
|
39
39
|
const style = {
|
|
40
|
-
height
|
|
41
|
-
width
|
|
40
|
+
height,
|
|
41
|
+
width
|
|
42
42
|
};
|
|
43
43
|
|
|
44
44
|
return (
|
|
45
45
|
<aside
|
|
46
46
|
className={clsx(ClassNames.emojiPicker, 'epr-main', {
|
|
47
47
|
[ClassNames.searchActive]: searchModeActive,
|
|
48
|
-
'epr-dark-theme': theme === Theme.DARK
|
|
48
|
+
'epr-dark-theme': theme === Theme.DARK
|
|
49
49
|
})}
|
|
50
50
|
ref={PickerMainRef}
|
|
51
51
|
style={style}
|
package/src/config/cdnUrls.ts
CHANGED
package/src/config/config.ts
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
|
+
import { GetEmojiUrl } from '../components/emoji/Emoji';
|
|
2
|
+
import { emojiUrlByUnified } from '../dataUtils/emojiSelectors';
|
|
1
3
|
import {
|
|
2
4
|
EmojiClickData,
|
|
3
5
|
EmojiStyle,
|
|
4
6
|
SkinTones,
|
|
5
7
|
SuggestionMode,
|
|
6
|
-
Theme
|
|
8
|
+
Theme
|
|
7
9
|
} from '../types/exposedTypes';
|
|
8
10
|
|
|
9
11
|
import {
|
|
10
12
|
CategoriesConfig,
|
|
11
13
|
baseCategoriesConfig,
|
|
12
|
-
mergeCategoriesConfig
|
|
14
|
+
mergeCategoriesConfig
|
|
13
15
|
} from './categoryConfig';
|
|
14
16
|
|
|
15
17
|
export function mergeConfig(
|
|
@@ -24,13 +26,13 @@ export function mergeConfig(
|
|
|
24
26
|
const config = Object.assign(base, userConfig);
|
|
25
27
|
|
|
26
28
|
const categories = mergeCategoriesConfig(userConfig.categories, {
|
|
27
|
-
suggestionMode: config.suggestedEmojisMode
|
|
29
|
+
suggestionMode: config.suggestedEmojisMode
|
|
28
30
|
});
|
|
29
31
|
|
|
30
32
|
return {
|
|
31
33
|
...config,
|
|
32
34
|
categories,
|
|
33
|
-
previewConfig
|
|
35
|
+
previewConfig
|
|
34
36
|
};
|
|
35
37
|
}
|
|
36
38
|
|
|
@@ -41,6 +43,7 @@ export function basePickerConfig(): PickerConfigInternal {
|
|
|
41
43
|
defaultSkinTone: SkinTones.NEUTRAL,
|
|
42
44
|
emojiStyle: EmojiStyle.APPLE,
|
|
43
45
|
emojiVersion: null,
|
|
46
|
+
getEmojiUrl: emojiUrlByUnified,
|
|
44
47
|
height: 450,
|
|
45
48
|
lazyLoadEmojis: false,
|
|
46
49
|
onEmojiClick: function defaultOnClickHandler(
|
|
@@ -52,13 +55,13 @@ export function basePickerConfig(): PickerConfigInternal {
|
|
|
52
55
|
event: MouseEvent
|
|
53
56
|
) {},
|
|
54
57
|
previewConfig: {
|
|
55
|
-
...basePreviewConfig
|
|
58
|
+
...basePreviewConfig
|
|
56
59
|
},
|
|
57
60
|
searchPlaceHolder: 'Search',
|
|
58
61
|
skinTonesDisabled: false,
|
|
59
62
|
suggestedEmojisMode: SuggestionMode.FREQUENT,
|
|
60
63
|
theme: Theme.LIGHT,
|
|
61
|
-
width: 350
|
|
64
|
+
width: 350
|
|
62
65
|
};
|
|
63
66
|
}
|
|
64
67
|
|
|
@@ -75,8 +78,9 @@ export type PickerConfigInternal = {
|
|
|
75
78
|
suggestedEmojisMode: SuggestionMode;
|
|
76
79
|
lazyLoadEmojis: boolean;
|
|
77
80
|
previewConfig: PreviewConfig;
|
|
78
|
-
height:
|
|
79
|
-
width:
|
|
81
|
+
height: PickerDimensions;
|
|
82
|
+
width: PickerDimensions;
|
|
83
|
+
getEmojiUrl: GetEmojiUrl;
|
|
80
84
|
};
|
|
81
85
|
|
|
82
86
|
export type PreviewConfig = {
|
|
@@ -88,7 +92,7 @@ export type PreviewConfig = {
|
|
|
88
92
|
const basePreviewConfig: PreviewConfig = {
|
|
89
93
|
defaultEmoji: '1f60a',
|
|
90
94
|
defaultCaption: "What's your mood?",
|
|
91
|
-
showPreview: true
|
|
95
|
+
showPreview: true
|
|
92
96
|
};
|
|
93
97
|
|
|
94
98
|
type ConfigExternal = {
|
|
@@ -96,3 +100,5 @@ type ConfigExternal = {
|
|
|
96
100
|
} & Omit<PickerConfigInternal, 'previewConfig'>;
|
|
97
101
|
|
|
98
102
|
export type PickerConfig = Partial<ConfigExternal>;
|
|
103
|
+
|
|
104
|
+
export type PickerDimensions = string | number;
|
package/src/config/useConfig.ts
CHANGED
|
@@ -5,11 +5,11 @@ import {
|
|
|
5
5
|
EmojiStyle,
|
|
6
6
|
SkinTones,
|
|
7
7
|
SuggestionMode,
|
|
8
|
-
Theme
|
|
8
|
+
Theme
|
|
9
9
|
} from '../types/exposedTypes';
|
|
10
10
|
|
|
11
11
|
import { CategoriesConfig } from './categoryConfig';
|
|
12
|
-
import { PreviewConfig } from './config';
|
|
12
|
+
import { PickerDimensions, PreviewConfig } from './config';
|
|
13
13
|
|
|
14
14
|
export function useSearchPlaceHolderConfig(): string {
|
|
15
15
|
const { searchPlaceHolder } = usePickerConfig();
|
|
@@ -74,12 +74,29 @@ export function useLazyLoadEmojisConfig(): boolean {
|
|
|
74
74
|
return lazyLoadEmojis;
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
export function usePickerSizeConfig(): {
|
|
77
|
+
export function usePickerSizeConfig(): {
|
|
78
|
+
height: PickerDimensions;
|
|
79
|
+
width: PickerDimensions;
|
|
80
|
+
} {
|
|
78
81
|
const { height, width } = usePickerConfig();
|
|
79
|
-
return { height, width };
|
|
82
|
+
return { height: getDimension(height), width: getDimension(width) };
|
|
80
83
|
}
|
|
81
84
|
|
|
82
85
|
export function useEmojiVersionConfig(): string | null {
|
|
83
86
|
const { emojiVersion } = usePickerConfig();
|
|
84
87
|
return emojiVersion;
|
|
85
88
|
}
|
|
89
|
+
|
|
90
|
+
export function useGetEmojiUrlConfig(): (
|
|
91
|
+
unified: string,
|
|
92
|
+
style: EmojiStyle
|
|
93
|
+
) => string {
|
|
94
|
+
const { getEmojiUrl } = usePickerConfig();
|
|
95
|
+
return getEmojiUrl;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function getDimension(dimensionConfig: PickerDimensions): PickerDimensions {
|
|
99
|
+
return typeof dimensionConfig === 'number'
|
|
100
|
+
? `${dimensionConfig}px`
|
|
101
|
+
: dimensionConfig;
|
|
102
|
+
}
|
|
@@ -38,14 +38,6 @@ export function unifiedWithoutSkinTone(unified: string): string {
|
|
|
38
38
|
return unified;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
export function emojiUrl(
|
|
42
|
-
emojiStyle: EmojiStyle,
|
|
43
|
-
emoji: DataEmoji,
|
|
44
|
-
skinTone?: string
|
|
45
|
-
): string {
|
|
46
|
-
return emojiUrlByUnified(emojiStyle, emojiUnified(emoji, skinTone));
|
|
47
|
-
}
|
|
48
|
-
|
|
49
41
|
export function emojiUnified(emoji: DataEmoji, skinTone?: string): string {
|
|
50
42
|
const unified = emoji[EmojiProperties.unified];
|
|
51
43
|
|
|
@@ -61,9 +53,10 @@ export function emojisByCategory(category: Categories): DataEmojis {
|
|
|
61
53
|
return emojis?.[category] ?? [];
|
|
62
54
|
}
|
|
63
55
|
|
|
56
|
+
// WARNING: DO NOT USE DIRECTLY
|
|
64
57
|
export function emojiUrlByUnified(
|
|
65
|
-
|
|
66
|
-
|
|
58
|
+
unified: string,
|
|
59
|
+
emojiStyle: EmojiStyle
|
|
67
60
|
): string {
|
|
68
61
|
return `${cdnUrl(emojiStyle)}${unified}.png`;
|
|
69
62
|
}
|
|
@@ -1,12 +1,10 @@
|
|
|
1
|
+
import { GetEmojiUrl } from '../components/emoji/Emoji';
|
|
1
2
|
import { DataEmoji } from '../dataUtils/DataTypes';
|
|
2
|
-
import {
|
|
3
|
-
emojiUnified,
|
|
4
|
-
emojiUrlByUnified,
|
|
5
|
-
emojiVariations
|
|
6
|
-
} from '../dataUtils/emojiSelectors';
|
|
3
|
+
import { emojiUnified, emojiVariations } from '../dataUtils/emojiSelectors';
|
|
7
4
|
import { EmojiStyle } from '../types/exposedTypes';
|
|
8
5
|
|
|
9
6
|
export function preloadEmoji(
|
|
7
|
+
getEmojiUrl: GetEmojiUrl,
|
|
10
8
|
emoji: undefined | DataEmoji,
|
|
11
9
|
emojiStyle: EmojiStyle
|
|
12
10
|
): void {
|
|
@@ -24,8 +22,8 @@ export function preloadEmoji(
|
|
|
24
22
|
return;
|
|
25
23
|
}
|
|
26
24
|
|
|
27
|
-
emojiVariations(emoji).forEach(variation => {
|
|
28
|
-
const emojiUrl =
|
|
25
|
+
emojiVariations(emoji).forEach((variation) => {
|
|
26
|
+
const emojiUrl = getEmojiUrl(variation, emojiStyle);
|
|
29
27
|
preloadImage(emojiUrl);
|
|
30
28
|
});
|
|
31
29
|
|
|
@@ -4,22 +4,25 @@ import { useEffect, useRef } from 'react';
|
|
|
4
4
|
import {
|
|
5
5
|
emojiFromElement,
|
|
6
6
|
isEmojiElement,
|
|
7
|
-
NullableElement
|
|
7
|
+
NullableElement,
|
|
8
8
|
} from '../DomUtils/selectors';
|
|
9
9
|
import {
|
|
10
10
|
useActiveSkinToneState,
|
|
11
11
|
useDisallowClickRef,
|
|
12
12
|
useEmojiVariationPickerState,
|
|
13
|
-
useUpdateSuggested
|
|
13
|
+
useUpdateSuggested,
|
|
14
14
|
} from '../components/context/PickerContext';
|
|
15
|
-
import {
|
|
15
|
+
import { GetEmojiUrl } from '../components/emoji/Emoji';
|
|
16
|
+
import {
|
|
17
|
+
useGetEmojiUrlConfig,
|
|
18
|
+
useOnEmojiClickConfig,
|
|
19
|
+
} from '../config/useConfig';
|
|
16
20
|
import { DataEmoji } from '../dataUtils/DataTypes';
|
|
17
21
|
import {
|
|
18
22
|
activeVariationFromUnified,
|
|
19
23
|
emojiHasVariations,
|
|
20
24
|
emojiNames,
|
|
21
25
|
emojiUnified,
|
|
22
|
-
emojiUrlByUnified
|
|
23
26
|
} from '../dataUtils/emojiSelectors';
|
|
24
27
|
import { parseNativeEmoji } from '../dataUtils/parseNativeEmoji';
|
|
25
28
|
import { setsuggested } from '../dataUtils/suggested';
|
|
@@ -39,6 +42,7 @@ export function useMouseDownHandlers(
|
|
|
39
42
|
const [activeSkinTone] = useActiveSkinToneState();
|
|
40
43
|
const onEmojiClick = useOnEmojiClickConfig();
|
|
41
44
|
const [, updateSuggested] = useUpdateSuggested();
|
|
45
|
+
const getEmojiUrl = useGetEmojiUrlConfig();
|
|
42
46
|
|
|
43
47
|
const onClick = React.useCallback(
|
|
44
48
|
function onClick(event: MouseEvent) {
|
|
@@ -59,14 +63,15 @@ export function useMouseDownHandlers(
|
|
|
59
63
|
|
|
60
64
|
updateSuggested();
|
|
61
65
|
setsuggested(emoji, skinToneToUse);
|
|
62
|
-
onEmojiClick(emojiClickOutput(emoji, skinToneToUse), event);
|
|
66
|
+
onEmojiClick(emojiClickOutput(emoji, skinToneToUse, getEmojiUrl), event);
|
|
63
67
|
},
|
|
64
68
|
[
|
|
65
69
|
activeSkinTone,
|
|
66
70
|
closeAllOpenToggles,
|
|
67
71
|
disallowClickRef,
|
|
68
72
|
onEmojiClick,
|
|
69
|
-
updateSuggested
|
|
73
|
+
updateSuggested,
|
|
74
|
+
getEmojiUrl,
|
|
70
75
|
]
|
|
71
76
|
);
|
|
72
77
|
|
|
@@ -94,7 +99,7 @@ export function useMouseDownHandlers(
|
|
|
94
99
|
disallowClickRef,
|
|
95
100
|
closeAllOpenToggles,
|
|
96
101
|
setVariationPicker,
|
|
97
|
-
setEmojiVariationPicker
|
|
102
|
+
setEmojiVariationPicker,
|
|
98
103
|
]
|
|
99
104
|
);
|
|
100
105
|
const onMouseUp = React.useCallback(
|
|
@@ -123,14 +128,14 @@ export function useMouseDownHandlers(
|
|
|
123
128
|
}
|
|
124
129
|
const bodyRef = BodyRef.current;
|
|
125
130
|
bodyRef.addEventListener('click', onClick, {
|
|
126
|
-
passive: true
|
|
131
|
+
passive: true,
|
|
127
132
|
});
|
|
128
133
|
|
|
129
134
|
bodyRef.addEventListener('mousedown', onMouseDown, {
|
|
130
|
-
passive: true
|
|
135
|
+
passive: true,
|
|
131
136
|
});
|
|
132
137
|
bodyRef.addEventListener('mouseup', onMouseUp, {
|
|
133
|
-
passive: true
|
|
138
|
+
passive: true,
|
|
134
139
|
});
|
|
135
140
|
|
|
136
141
|
return () => {
|
|
@@ -152,17 +157,18 @@ function emojiFromEvent(event: MouseEvent): [DataEmoji, string] | [] {
|
|
|
152
157
|
|
|
153
158
|
function emojiClickOutput(
|
|
154
159
|
emoji: DataEmoji,
|
|
155
|
-
activeSkinTone: SkinTones
|
|
160
|
+
activeSkinTone: SkinTones,
|
|
161
|
+
getEmojiUrl: GetEmojiUrl
|
|
156
162
|
): EmojiClickData {
|
|
157
163
|
const unified = emojiUnified(emoji, activeSkinTone);
|
|
158
164
|
return {
|
|
159
165
|
activeSkinTone,
|
|
160
166
|
emoji: parseNativeEmoji(unified),
|
|
161
167
|
getImageUrl(emojiStyle: EmojiStyle) {
|
|
162
|
-
return
|
|
168
|
+
return getEmojiUrl(unified, emojiStyle);
|
|
163
169
|
},
|
|
164
170
|
names: emojiNames(emoji),
|
|
165
171
|
unified,
|
|
166
|
-
unifiedWithoutSkinTone: emojiUnified(emoji)
|
|
172
|
+
unifiedWithoutSkinTone: emojiUnified(emoji),
|
|
167
173
|
};
|
|
168
174
|
}
|
package/src/hooks/useOnFocus.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { useEffect } from 'react';
|
|
|
2
2
|
|
|
3
3
|
import { buttonFromTarget, emojiFromElement } from '../DomUtils/selectors';
|
|
4
4
|
import { useBodyRef } from '../components/context/ElementRefContext';
|
|
5
|
-
import { useEmojiStyleConfig } from '../config/useConfig';
|
|
5
|
+
import { useEmojiStyleConfig, useGetEmojiUrlConfig } from '../config/useConfig';
|
|
6
6
|
import { emojiHasVariations } from '../dataUtils/emojiSelectors';
|
|
7
7
|
import { EmojiStyle } from '../types/exposedTypes';
|
|
8
8
|
|
|
@@ -11,6 +11,7 @@ import { preloadEmoji } from './preloadEmoji';
|
|
|
11
11
|
export function useOnFocus() {
|
|
12
12
|
const BodyRef = useBodyRef();
|
|
13
13
|
const emojiStyle = useEmojiStyleConfig();
|
|
14
|
+
const getEmojiUrl = useGetEmojiUrlConfig();
|
|
14
15
|
|
|
15
16
|
useEffect(() => {
|
|
16
17
|
if (emojiStyle === EmojiStyle.NATIVE) {
|
|
@@ -39,8 +40,8 @@ export function useOnFocus() {
|
|
|
39
40
|
}
|
|
40
41
|
|
|
41
42
|
if (emojiHasVariations(emoji)) {
|
|
42
|
-
preloadEmoji(emoji, emojiStyle);
|
|
43
|
+
preloadEmoji(getEmojiUrl, emoji, emojiStyle);
|
|
43
44
|
}
|
|
44
45
|
}
|
|
45
|
-
}, [BodyRef, emojiStyle]);
|
|
46
|
+
}, [BodyRef, emojiStyle, getEmojiUrl]);
|
|
46
47
|
}
|