@@ -2,12 +2,11 @@ import { css, Global, useTheme } from "@emotion/react";
2
2
import Button from "@mui/material/Button" ;
3
3
import InputAdornment from "@mui/material/InputAdornment" ;
4
4
import TextField , { type TextFieldProps } from "@mui/material/TextField" ;
5
- import Picker from "@emoji-mart/react" ;
6
- import { type FC } from "react" ;
5
+ import { visuallyHidden } from "@mui/utils" ;
6
+ import { type FC , lazy , Suspense } from "react" ;
7
+ import { Loader } from "components/Loader/Loader" ;
7
8
import { DropdownArrow } from "components/DropdownArrow/DropdownArrow" ;
8
9
import { Stack } from "components/Stack/Stack" ;
9
- import data from "@emoji-mart/data/sets/14/twitter.json" ;
10
- import icons from "theme/icons.json" ;
11
10
import {
12
11
Popover ,
13
12
PopoverContent ,
@@ -22,24 +21,12 @@ type IconFieldProps = TextFieldProps & {
22
21
onPickEmoji :( value :string ) => void ;
23
22
} ;
24
23
25
- const custom = [
26
- {
27
- id :"icons" ,
28
- name :"Icons" ,
29
- emojis :icons . map ( ( icon ) => {
30
- const id = icon . split ( "." ) [ 0 ] ;
24
+ const EmojiPicker = lazy ( ( ) => import ( "./EmojiPicker" ) ) ;
31
25
32
- return {
33
- id,
34
- name :id ,
35
- keywords :id . split ( "-" ) ,
36
- skins :[ { src :`/icon/${ icon } ` } ] ,
37
- } ;
38
- } ) ,
39
- } ,
40
- ] ;
41
-
42
- const IconField :FC < IconFieldProps > = ( { onPickEmoji, ...textFieldProps } ) => {
26
+ export const IconField :FC < IconFieldProps > = ( {
27
+ onPickEmoji,
28
+ ...textFieldProps
29
+ } ) => {
43
30
if (
44
31
typeof textFieldProps . value !== "string" &&
45
32
typeof textFieldProps . value !== "undefined"
@@ -53,9 +40,9 @@ const IconField: FC<IconFieldProps> = ({ onPickEmoji, ...textFieldProps }) => {
53
40
return (
54
41
< Stack spacing = { 1 } >
55
42
< TextField
56
- { ...textFieldProps }
57
43
fullWidth
58
44
label = "Icon"
45
+ { ...textFieldProps }
59
46
InputProps = { {
60
47
endAdornment :hasIcon ?(
61
48
< InputAdornment
@@ -86,6 +73,18 @@ const IconField: FC<IconFieldProps> = ({ onPickEmoji, ...textFieldProps }) => {
86
73
} }
87
74
/>
88
75
76
+ < Global
77
+ styles = { css `
78
+ em-emoji-picker {
79
+ --rgb-background : ${ theme . palette . background . paper } ;
80
+ --rgb-input : ${ theme . palette . primary . main } ;
81
+ --rgb-color : ${ theme . palette . text . primary } ;
82
+
83
+ // Hack to prevent the right side from being cut off
84
+ width : 350px ;
85
+ }
86
+ ` }
87
+ />
89
88
< Popover >
90
89
{ ( popover ) => (
91
90
< >
@@ -98,35 +97,36 @@ const IconField: FC<IconFieldProps> = ({ onPickEmoji, ...textFieldProps }) => {
98
97
id = "emoji"
99
98
css = { { marginTop :0 , ".MuiPaper-root" :{ width :"auto" } } }
100
99
>
101
- < Global
102
- styles = { css `
103
- em-emoji-picker {
104
- --rgb-background : ${ theme . palette . background . paper } ;
105
- --rgb-input : ${ theme . palette . primary . main } ;
106
- --rgb-color : ${ theme . palette . text . primary } ;
107
-
108
- // Hack to prevent the right side from being cut off
109
- width : 350px ;
110
- }
111
- ` }
112
- />
113
- < Picker
114
- set = "twitter"
115
- theme = "dark"
116
- data = { data }
117
- custom = { custom }
118
- onEmojiSelect = { ( emoji ) => {
119
- const value = emoji . src ?? urlFromUnifiedCode ( emoji . unified ) ;
120
- onPickEmoji ( value ) ;
121
- popover . setIsOpen ( false ) ;
122
- } }
123
- />
100
+ < Suspense fallback = { < Loader /> } >
101
+ < EmojiPicker
102
+ onEmojiSelect = { ( emoji ) => {
103
+ const value =
104
+ emoji . src ?? urlFromUnifiedCode ( emoji . unified ) ;
105
+ onPickEmoji ( value ) ;
106
+ popover . setIsOpen ( false ) ;
107
+ } }
108
+ />
109
+ </ Suspense >
124
110
</ PopoverContent >
125
111
</ >
126
112
) }
127
113
</ Popover >
114
+
115
+ { /*
116
+ - This component takes a long time to load (easily several seconds), so we
117
+ don't want to wait until the user actually clicks the button to start loading.
118
+ Unfortunately, React doesn't provide an API to start warming a lazy component,
119
+ so we just have to sneak it into the DOM, which is kind of annoying, but means
120
+ that users shouldn't ever spend time waiting for it to load.
121
+ - Except we don't do it when running tests, because Jest doesn't define
122
+ `IntersectionObserver`, and it would make them slower anyway. */ }
123
+ { process . env . NODE_ENV !== "test" && (
124
+ < div css = { { ...visuallyHidden } } >
125
+ < Suspense >
126
+ < EmojiPicker onEmojiSelect = { ( ) => { } } />
127
+ </ Suspense >
128
+ </ div >
129
+ ) }
128
130
</ Stack >
129
131
) ;
130
132
} ;
131
-
132
- export default IconField ;