1
+ import data from "@emoji-mart/data/sets/14/twitter.json"
2
+ import Picker from "@emoji-mart/react"
3
+ import Button from "@material-ui/core/Button"
1
4
import InputAdornment from "@material-ui/core/InputAdornment"
5
+ import Popover from "@material-ui/core/Popover"
2
6
import { makeStyles } from "@material-ui/core/styles"
3
7
import TextField from "@material-ui/core/TextField"
4
8
import { Template , UpdateTemplateMeta } from "api/typesGenerated"
9
+ import { OpenDropdown } from "components/DropdownArrows/DropdownArrows"
5
10
import { FormFooter } from "components/FormFooter/FormFooter"
6
11
import { Stack } from "components/Stack/Stack"
7
12
import { FormikContextType , FormikTouched , useFormik } from "formik"
8
- import { FC } from "react"
13
+ import { FC , useRef , useState } from "react"
14
+ import { colors } from "theme/colors"
9
15
import { getFormHelpersWithError , nameValidator , onChangeTrimmed } from "util/formUtils"
10
16
import * as Yup from "yup"
11
17
@@ -17,6 +23,7 @@ export const Language = {
17
23
// This is the same from the CLI on https://github.com/coder/coder/blob/546157b63ef9204658acf58cb653aa9936b70c49/cli/templateedit.go#L59
18
24
maxTtlHelperText : "Edit the template maximum time before shutdown in milliseconds" ,
19
25
formAriaLabel : "Template settings form" ,
26
+ selectEmoji : "Select emoji" ,
20
27
}
21
28
22
29
export const validationSchema = Yup . object ( {
@@ -43,6 +50,7 @@ export const TemplateSettingsForm: FC<TemplateSettingsForm> = ({
43
50
isSubmitting,
44
51
initialTouched,
45
52
} ) => {
53
+ const [ isEmojiPickerOpen , setIsEmojiPickerOpen ] = useState ( false )
46
54
const form : FormikContextType < UpdateTemplateMeta > = useFormik < UpdateTemplateMeta > ( {
47
55
initialValues : {
48
56
name : template . name ,
@@ -59,6 +67,7 @@ export const TemplateSettingsForm: FC<TemplateSettingsForm> = ({
59
67
const getFieldHelpers = getFormHelpersWithError < UpdateTemplateMeta > ( form , error )
60
68
const styles = useStyles ( )
61
69
const hasIcon = form . values . icon && form . values . icon !== ""
70
+ const emojiButtonRef = useRef < HTMLButtonElement > ( null )
62
71
63
72
return (
64
73
< form onSubmit = { form . handleSubmit } aria-label = { Language . formAriaLabel } >
@@ -83,28 +92,61 @@ export const TemplateSettingsForm: FC<TemplateSettingsForm> = ({
83
92
rows = { 2 }
84
93
/>
85
94
86
- < TextField
87
- { ...getFieldHelpers ( "icon" ) }
88
- disabled = { isSubmitting }
89
- fullWidth
90
- label = { Language . iconLabel }
91
- variant = "outlined"
92
- InputProps = { {
93
- endAdornment : hasIcon ? (
94
- < InputAdornment position = "end" >
95
- < img
96
- alt = ""
97
- src = { form . values . icon }
98
- className = { styles . adornment }
99
- // This prevent browser to display the ugly error icon if the
100
- // image path is wrong or user didn't finish typing the url
101
- onError = { ( e ) => ( e . currentTarget . style . display = "none" ) }
102
- onLoad = { ( e ) => ( e . currentTarget . style . display = "inline" ) }
103
- />
104
- </ InputAdornment >
105
- ) : undefined ,
106
- } }
107
- />
95
+ < div className = { styles . iconField } >
96
+ < TextField
97
+ { ...getFieldHelpers ( "icon" ) }
98
+ disabled = { isSubmitting }
99
+ fullWidth
100
+ label = { Language . iconLabel }
101
+ variant = "outlined"
102
+ InputProps = { {
103
+ endAdornment : hasIcon ? (
104
+ < InputAdornment position = "end" >
105
+ < img
106
+ alt = ""
107
+ src = { form . values . icon }
108
+ className = { styles . adornment }
109
+ // This prevent browser to display the ugly error icon if the
110
+ // image path is wrong or user didn't finish typing the url
111
+ onError = { ( e ) => ( e . currentTarget . style . display = "none" ) }
112
+ onLoad = { ( e ) => ( e . currentTarget . style . display = "inline" ) }
113
+ />
114
+ </ InputAdornment >
115
+ ) : undefined ,
116
+ } }
117
+ />
118
+
119
+ < Button
120
+ fullWidth
121
+ ref = { emojiButtonRef }
122
+ variant = "outlined"
123
+ size = "small"
124
+ endIcon = { < OpenDropdown /> }
125
+ onClick = { ( ) => {
126
+ setIsEmojiPickerOpen ( ( v ) => ! v )
127
+ } }
128
+ >
129
+ { Language . selectEmoji }
130
+ </ Button >
131
+
132
+ < Popover
133
+ id = "emoji"
134
+ open = { isEmojiPickerOpen }
135
+ anchorEl = { emojiButtonRef . current }
136
+ onClose = { ( ) => {
137
+ setIsEmojiPickerOpen ( false )
138
+ } }
139
+ >
140
+ < Picker
141
+ theme = "dark"
142
+ data = { data }
143
+ onEmojiSelect = { ( emojiData ) => {
144
+ form . setFieldValue ( "icon" , `/emojis/${ emojiData . unified } .png` )
145
+ setIsEmojiPickerOpen ( false )
146
+ } }
147
+ />
148
+ </ Popover >
149
+ </ div >
108
150
109
151
< TextField
110
152
{ ...getFieldHelpers ( "max_ttl_ms" ) }
@@ -123,8 +165,18 @@ export const TemplateSettingsForm: FC<TemplateSettingsForm> = ({
123
165
}
124
166
125
167
const useStyles = makeStyles ( ( theme ) => ( {
168
+ "@global" : {
169
+ "em-emoji-picker" : {
170
+ "--rgb-background" : theme . palette . background . paper ,
171
+ "--rgb-input" : colors . gray [ 17 ] ,
172
+ "--rgb-color" : colors . gray [ 4 ] ,
173
+ } ,
174
+ } ,
126
175
adornment : {
127
176
width : theme . spacing ( 3 ) ,
128
177
height : theme . spacing ( 3 ) ,
129
178
} ,
179
+ iconField : {
180
+ paddingBottom : theme . spacing ( 0.5 ) ,
181
+ } ,
130
182
} ) )
0 commit comments