1
- import { IModalProps , Modal , useDialogSize } from "." ;
2
- import { Form , Formik } from "formik" ;
3
- import { Button } from "../Buttons/Button" ;
4
- import { Fragment , createContext , useContext , useEffect , useRef , useState } from "react" ;
5
1
import { Dialog , Transition } from "@headlessui/react" ;
6
2
import { XIcon } from "@heroicons/react/solid" ;
7
3
import clsx from "clsx" ;
4
+ import { Form , Formik } from "formik" ;
5
+ import { Fragment , createContext , useContext , useRef , useState } from "react" ;
8
6
import { BsArrowsFullscreen , BsFullscreenExit } from "react-icons/bs" ;
7
+ import { IModalProps , useDialogSize } from "." ;
8
+ import { Button } from "../Buttons/Button" ;
9
9
import DialogButton from "../Buttons/DialogButton" ;
10
10
import HelpLink from "../Buttons/HelpLink" ;
11
11
12
- interface FormikModalProps extends IModalProps {
13
- initialValues ?: Record < string , any > ;
12
+ interface FormikFormModalProps {
14
13
showBack ?: boolean ;
15
14
showDelete ?: boolean ;
16
15
showSave ?: boolean ;
@@ -25,33 +24,73 @@ interface FormikModalProps extends IModalProps {
25
24
onDelete ?: ( values : Record < string , any > ) => void | Promise < any > ;
26
25
}
27
26
28
-
29
27
export type FormikModalContextProps = {
30
- props : FormikModalProps ;
31
- setProps : ( props : FormikModalProps ) => void ;
28
+ props : FormikFormModalProps ;
29
+ setProps : ( props : FormikFormModalProps ) => void ;
32
30
values : Record < string , any > ;
33
- }
31
+ } ;
34
32
35
33
export function useFormikModal ( ) {
36
- let { props, setProps : set , values } = useContext ( FormikModalContext )
37
- let setProps = ( p : FormikModalProps ) => {
38
- console . log ( p , props )
39
- set ( p )
40
- }
34
+ const { props, setProps : set , values } = useContext ( FormikModalContext ) ;
35
+ const setProps = ( p : FormikFormModalProps ) => {
36
+ set ( p ) ;
37
+ } ;
41
38
return {
42
- props, setProps, values
43
- }
39
+ props,
40
+ setProps,
41
+ values
42
+ } ;
44
43
}
45
44
46
- export const FormikModalContext = createContext < FormikModalContextProps > ( undefined ! ) ;
45
+ export const FormikModalContext = createContext < FormikModalContextProps > (
46
+ undefined !
47
+ ) ;
47
48
48
- export default function FormikModal ( initialProps : FormikModalProps ) {
49
- console . log ( 'initial' , initialProps . open )
50
- const [ props , setProps ] = useState ( initialProps ) ;
51
- console . log ( 'state' , props . open )
52
- const sizeClass = useDialogSize ( props . size ) ;
53
- const formRef = useRef < HTMLFormElement > ( null ) ;
49
+ type FormikModalProps = IModalProps & {
50
+ formikFormProps : FormikFormModalProps ;
51
+ /**
52
+ * Can only be used during the initial render of the modal, after that, you
53
+ * can use Formik's setFieldValue to update the form values.
54
+ */
55
+ initialValues ?: Record < string , any > ;
56
+ } ;
57
+
58
+ export default function FormikModal ( {
59
+ onClose = ( ) => { } ,
60
+ formikFormProps,
61
+ size = "medium" ,
62
+ helpLink,
63
+ showExpand,
64
+ bodyClass,
65
+ initialValues,
66
+ title,
67
+ titleClass,
68
+ hideCloseButton,
69
+ childClassName,
70
+ ...props
71
+ } : FormikModalProps ) {
72
+ const [ formikProps , setFormikProps ] = useState < FormikFormModalProps > ( ( ) => {
73
+ // set default values for formikFormProps
74
+ const {
75
+ saveTitle = "Save" ,
76
+ backTitle = "Back" ,
77
+ deleteTitle = "Delete" ,
78
+ closeTitle = "Close" ,
79
+ ...props
80
+ } = formikFormProps ;
54
81
82
+ return {
83
+ ...props ,
84
+ saveTitle,
85
+ backTitle,
86
+ deleteTitle,
87
+ closeTitle
88
+ } ;
89
+ } ) ;
90
+
91
+ const [ _size , _setSize ] = useState ( size ) ;
92
+ const sizeClass = useDialogSize ( _size ) ;
93
+ const formRef = useRef < HTMLFormElement > ( null ) ;
55
94
56
95
const touchAllFormFields = (
57
96
setFieldTouched : (
@@ -70,11 +109,19 @@ export default function FormikModal(initialProps: FormikModalProps) {
70
109
as = "div"
71
110
auto-reopen = "true"
72
111
className = { props . dialogClassName }
73
- onClose = { props . allowBackgroundClose ? ( ) => props . onClose ?.( ) : ( ) => { } }
112
+ onClose = { ( e ) => {
113
+ if ( props . allowBackgroundClose ) {
114
+ onClose ( ) ;
115
+ }
116
+ } }
74
117
{ ...props }
75
118
>
76
119
< div
77
- className = { clsx ( "flex items-center justify-center mx-auto my-auto" , sizeClass ) } >
120
+ className = { clsx (
121
+ "flex items-center justify-center mx-auto my-auto" ,
122
+ sizeClass
123
+ ) }
124
+ >
78
125
{ /* @ts -ignore */ }
79
126
< Transition . Child
80
127
as = { Fragment as any }
@@ -97,54 +144,66 @@ export default function FormikModal(initialProps: FormikModalProps) {
97
144
leaveFrom = "opacity-100 translate-y-0 sm:scale-100"
98
145
leaveTo = "opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
99
146
>
100
- < div className = { clsx (
101
- props . size !== "small" && props . childClassName ,
102
- "mt-20 mb-10 justify-between overflow-auto bg-white rounded-lg text-left shadow-xl transform transition-all flex flex-col" ) }
147
+ < div
148
+ className = { clsx (
149
+ _size !== "small" && childClassName ,
150
+ "mt-20 mb-10 justify-between overflow-auto bg-white rounded-lg text-left shadow-xl transform transition-all flex flex-col"
151
+ ) }
103
152
>
104
153
< div className = "py-4 px-4 gap-2 flex item-center rounded-t-lg justify-between bg-gray-100" >
105
154
< h1
106
155
className = { clsx (
107
156
"font-semibold flex-1 overflow-x-auto text-lg" ,
108
- props . titleClass
157
+ titleClass
109
158
) }
110
159
>
111
- { props . title }
160
+ { title }
112
161
</ h1 >
113
162
114
- { props . helpLink && < HelpLink link = { props . helpLink } /> }
115
- { props . showExpand && props . size !== 'full' && props . size !== 'small' &&
116
- < DialogButton icon = { BsArrowsFullscreen } onClick = { ( ) => setProps ( {
117
- ...props ,
118
- size : 'full'
119
- } ) } /> }
163
+ { helpLink && < HelpLink link = { helpLink } /> }
164
+ { showExpand && _size !== "full" && _size !== "small" && (
165
+ < DialogButton
166
+ icon = { BsArrowsFullscreen }
167
+ onClick = { ( ) => _setSize ( "full" ) }
168
+ />
169
+ ) }
120
170
121
- { props . showExpand && props . size === 'full' && < DialogButton icon = { BsFullscreenExit } onClick = { ( ) => setProps ( {
122
- ...props ,
123
- size : 'medium'
124
- } ) } /> }
171
+ { showExpand && _size === "full" && (
172
+ < DialogButton
173
+ icon = { BsFullscreenExit }
174
+ onClick = { ( ) => _setSize ( "medium" ) }
175
+ />
176
+ ) }
125
177
126
- { ! props . hideCloseButton && < DialogButton icon = { XIcon } onClick = { props . onClose } /> }
178
+ { ! hideCloseButton && (
179
+ < DialogButton icon = { XIcon } onClick = { onClose } />
180
+ ) }
127
181
</ div >
128
182
129
- < div className = { clsx ( "flex flex-col flex-1 mb-auto " , props . bodyClass ) } >
130
-
183
+ < div className = { clsx ( "flex flex-col flex-1 mb-auto " , bodyClass ) } >
131
184
< Formik
132
- initialValues = { props . initialValues ! }
185
+ initialValues = { initialValues ! }
133
186
enableReinitialize = { true }
134
- onSubmit = { ( values ) => {
135
- if ( props . onSave ) {
136
- props . onSave ( values ) ;
187
+ onSubmit = { ( values ) : void => {
188
+ if ( formikProps . onSave ) {
189
+ formikProps . onSave ( values ) ;
137
190
}
138
191
} }
139
192
validateOnBlur
140
193
validateOnChange
141
194
>
142
- { ( { handleSubmit, handleReset, setFieldTouched, validateField, values } ) => (
143
- < FormikModalContext . Provider value = { { props, setProps, values } } >
195
+ { ( { handleSubmit, handleReset, setFieldTouched, values } ) => (
196
+ < FormikModalContext . Provider
197
+ value = { {
198
+ props : formikProps ,
199
+ setProps : setFormikProps ,
200
+ values
201
+ } }
202
+ >
144
203
< Form
145
204
onSubmit = { ( e ) => {
146
205
handleSubmit ( e ) ;
147
- if ( props . touchAllOnSubmit ) {
206
+ if ( formikProps . touchAllOnSubmit ) {
148
207
touchAllFormFields ( setFieldTouched ) ;
149
208
}
150
209
} }
@@ -156,46 +215,64 @@ export default function FormikModal(initialProps: FormikModalProps) {
156
215
{ props . children }
157
216
</ div >
158
217
159
- { ( props . showBack || props . showSave || props . showDelete || props . showClose ) &&
218
+ { ( formikProps . showBack ||
219
+ formikProps . showSave ||
220
+ formikProps . showDelete ||
221
+ formikProps . showClose ) && (
160
222
< div className = "flex flex-row bg-gray-100 p-4" >
161
223
< div className = "flex flex-1 flex-row items-center space-x-4 " >
162
- { props . showBack && props . onBack && (
224
+ { formikProps . showBack && formikProps . onBack && (
163
225
< div className = "flex flex-1 flex-row" >
164
- < Button className = "btn-default btn-btn-secondary-base btn-secondary"
226
+ < Button
227
+ className = "btn-default btn-btn-secondary-base btn-secondary"
165
228
onClick = { ( e ) => {
166
- props . onBack ?.( )
167
- } } > { props . backTitle } </ Button >
229
+ formikProps . onBack ?.( ) ;
230
+ } }
231
+ >
232
+ { formikProps . backTitle }
233
+ </ Button >
168
234
</ div >
169
235
) }
170
- { props . showDelete && props . onDelete &&
171
- < Button className = "btn-default btn-btn-secondary-base btn-secondary"
172
- onClick = { ( ) => {
173
- props . onDelete ?.( values )
174
- } } > { props . deleteTitle } </ Button >
175
- }
176
-
177
- { props . showClose && props . onClose &&
178
- < Button className = "btn-primary"
179
- onClick = { ( ) => {
180
- props . onClose ?.( )
181
- } } > { props . closeTitle } </ Button >
182
- }
183
- { props . showSave &&
184
- < Button type = "submit" className = "btn-default btn-primary" > { props . saveTitle } </ Button >
185
- }
236
+ { formikProps . showDelete &&
237
+ formikProps . onDelete && (
238
+ < Button
239
+ className = "btn-default btn-btn-secondary-base btn-secondary"
240
+ onClick = { ( ) => {
241
+ formikProps . onDelete ?.( values ) ;
242
+ } }
243
+ >
244
+ { formikProps . deleteTitle }
245
+ </ Button >
246
+ ) }
247
+
248
+ { formikProps . showClose && onClose && (
249
+ < Button
250
+ className = "btn-primary"
251
+ onClick = { ( ) => onClose ( ) }
252
+ >
253
+ { formikProps . closeTitle }
254
+ </ Button >
255
+ ) }
256
+ { formikProps . showSave && (
257
+ < Button
258
+ type = "submit"
259
+ className = "btn-default btn-primary"
260
+ >
261
+ { formikProps . saveTitle }
262
+ </ Button >
263
+ ) }
186
264
</ div >
187
265
</ div >
188
- }
266
+ ) }
189
267
</ Form >
190
268
</ FormikModalContext . Provider >
191
269
) }
192
- </ Formik >
270
+ </ Formik >
193
271
</ div >
194
-
195
272
</ div >
196
273
</ Transition . Child >
197
274
</ div >
198
275
</ Dialog >
199
- </ Transition . Root >
200
- )
276
+ </ Transition . Root >
277
+ ) ;
201
278
}
0 commit comments