@app-studio/web 0.9.31 → 0.9.33

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.
Files changed (61) hide show
  1. package/docs/components/Accordion.mdx +158 -0
  2. package/docs/components/Alert.mdx +123 -0
  3. package/docs/components/AspectRatio.mdx +55 -0
  4. package/docs/components/Avatar.mdx +85 -0
  5. package/docs/components/Background.mdx +522 -0
  6. package/docs/components/Badge.mdx +220 -0
  7. package/docs/components/Button.mdx +272 -0
  8. package/docs/components/Calendar.mdx +274 -0
  9. package/docs/components/Card.mdx +341 -0
  10. package/docs/components/Carousel.mdx +411 -0
  11. package/docs/components/Center.mdx +474 -0
  12. package/docs/components/Chart.mdx +232 -0
  13. package/docs/components/ChatInput.mdx +373 -0
  14. package/docs/components/Checkbox.mdx +66 -0
  15. package/docs/components/ColorInput.mdx +209 -0
  16. package/docs/components/ComboBox.mdx +364 -0
  17. package/docs/components/Command.mdx +252 -0
  18. package/docs/components/ContextMenu.mdx +219 -0
  19. package/docs/components/CountryPicker.mdx +123 -0
  20. package/docs/components/DatePicker.mdx +77 -0
  21. package/docs/components/DragAndDrop.mdx +539 -0
  22. package/docs/components/DropdownMenu.mdx +205 -0
  23. package/docs/components/File.mdx +8 -0
  24. package/docs/components/Flow.mdx +257 -0
  25. package/docs/components/Form.mdx +681 -0
  26. package/docs/components/Formik.mdx +621 -0
  27. package/docs/components/Gradient.mdx +271 -0
  28. package/docs/components/Horizontal.mdx +40 -0
  29. package/docs/components/HoverCard.mdx +140 -0
  30. package/docs/components/Icon.mdx +438 -0
  31. package/docs/components/Label.mdx +438 -0
  32. package/docs/components/Link.mdx +83 -0
  33. package/docs/components/Loader.mdx +527 -0
  34. package/docs/components/Menubar.mdx +124 -0
  35. package/docs/components/Message.mdx +571 -0
  36. package/docs/components/Modal.mdx +533 -0
  37. package/docs/components/NavigationMenu.mdx +165 -0
  38. package/docs/components/Pagination.mdx +150 -0
  39. package/docs/components/Password.mdx +121 -0
  40. package/docs/components/Resizable.mdx +148 -0
  41. package/docs/components/Select.mdx +126 -0
  42. package/docs/components/Separator.mdx +121 -0
  43. package/docs/components/Sidebar.mdx +147 -0
  44. package/docs/components/Slider.mdx +232 -0
  45. package/docs/components/Switch.mdx +62 -0
  46. package/docs/components/Table.mdx +409 -0
  47. package/docs/components/Tabs.mdx +215 -0
  48. package/docs/components/TagInput.mdx +528 -0
  49. package/docs/components/Text.mdx +163 -0
  50. package/docs/components/TextArea.mdx +136 -0
  51. package/docs/components/TextField.mdx +225 -0
  52. package/docs/components/Title.mdx +535 -0
  53. package/docs/components/Toast.mdx +165 -0
  54. package/docs/components/Toggle.mdx +141 -0
  55. package/docs/components/ToggleGroup.mdx +165 -0
  56. package/docs/components/Tooltip.mdx +191 -0
  57. package/docs/components/Tree.mdx +340 -0
  58. package/docs/components/Uploader.mdx +426 -0
  59. package/docs/components/Vertical.mdx +566 -0
  60. package/docs/components.md +285 -0
  61. package/package.json +1 -1
@@ -0,0 +1,681 @@
1
+ # Form
2
+
3
+ A comprehensive form system with Formik integration, providing powerful form state management, validation, and a complete set of form components. Includes support for complex forms, real-time validation, and seamless user experience.
4
+
5
+ ### **Import**
6
+ ```tsx
7
+ // Form components
8
+ import {
9
+ FormikForm,
10
+ FormikTextField,
11
+ FormikTextArea,
12
+ FormikCheckbox,
13
+ FormikSwitch,
14
+ FormikSelect,
15
+ FormikDatePicker,
16
+ FormikCountryPicker,
17
+ FormikColorInput,
18
+ FormikPassword,
19
+ FormikComboBox,
20
+ FormikSlider,
21
+ FormikChatInput,
22
+ FormikTagInput
23
+ } from '@app-studio/web';
24
+
25
+ // Individual form components
26
+ import {
27
+ TextField,
28
+ TextArea,
29
+ Checkbox,
30
+ Switch,
31
+ Select,
32
+ DatePicker,
33
+ CountryPicker,
34
+ ColorInput,
35
+ Password,
36
+ ComboBox,
37
+ Slider,
38
+ Label
39
+ } from '@app-studio/web';
40
+ ```
41
+
42
+ ### **Basic Form with Formik**
43
+ ```tsx
44
+ import React from 'react';
45
+ import { Formik } from 'formik';
46
+ import * as Yup from 'yup';
47
+ import { FormikForm, FormikTextField, FormikCheckbox } from '@app-studio/web';
48
+ import { Button } from '@app-studio/web';
49
+ import { Vertical } from 'app-studio';
50
+
51
+ export const BasicForm = () => {
52
+ const initialValues = {
53
+ firstName: '',
54
+ lastName: '',
55
+ email: '',
56
+ agreeToTerms: false,
57
+ };
58
+
59
+ const validationSchema = Yup.object().shape({
60
+ firstName: Yup.string().required('First name is required'),
61
+ lastName: Yup.string().required('Last name is required'),
62
+ email: Yup.string().email('Invalid email').required('Email is required'),
63
+ agreeToTerms: Yup.boolean().oneOf([true], 'You must agree to the terms'),
64
+ });
65
+
66
+ const handleSubmit = (values: any, { setSubmitting }: any) => {
67
+ console.log('Form values:', values);
68
+ setTimeout(() => {
69
+ alert(JSON.stringify(values, null, 2));
70
+ setSubmitting(false);
71
+ }, 1000);
72
+ };
73
+
74
+ return (
75
+ <Formik
76
+ initialValues={initialValues}
77
+ validationSchema={validationSchema}
78
+ onSubmit={handleSubmit}
79
+ >
80
+ {({ handleSubmit, isSubmitting }) => (
81
+ <FormikForm>
82
+ <Vertical gap={16} width="100%" maxWidth={400}>
83
+ <FormikTextField
84
+ name="firstName"
85
+ label="First Name"
86
+ placeholder="Enter your first name"
87
+ />
88
+ <FormikTextField
89
+ name="lastName"
90
+ label="Last Name"
91
+ placeholder="Enter your last name"
92
+ />
93
+ <FormikTextField
94
+ name="email"
95
+ label="Email"
96
+ placeholder="Enter your email"
97
+ type="email"
98
+ />
99
+ <FormikCheckbox
100
+ name="agreeToTerms"
101
+ label="I agree to the terms and conditions"
102
+ />
103
+ <Button
104
+ type="submit"
105
+ onClick={handleSubmit}
106
+ isLoading={isSubmitting}
107
+ disabled={isSubmitting}
108
+ >
109
+ Submit
110
+ </Button>
111
+ </Vertical>
112
+ </FormikForm>
113
+ )}
114
+ </Formik>
115
+ );
116
+ };
117
+ ```
118
+
119
+ ### **Advanced Form with Multiple Field Types**
120
+ ```tsx
121
+ import React from 'react';
122
+ import { Formik } from 'formik';
123
+ import * as Yup from 'yup';
124
+ import {
125
+ FormikForm,
126
+ FormikTextField,
127
+ FormikTextArea,
128
+ FormikSelect,
129
+ FormikDatePicker,
130
+ FormikCountryPicker,
131
+ FormikColorInput,
132
+ FormikSlider,
133
+ FormikSwitch,
134
+ FormikTagInput
135
+ } from '@app-studio/web';
136
+ import { Button } from '@app-studio/web';
137
+ import { Vertical } from 'app-studio';
138
+
139
+ export const AdvancedForm = () => {
140
+ const initialValues = {
141
+ title: '',
142
+ description: '',
143
+ category: '',
144
+ publishDate: null,
145
+ country: '',
146
+ themeColor: '#3B82F6',
147
+ priority: 5,
148
+ isPublished: false,
149
+ tags: ['react', 'typescript'],
150
+ };
151
+
152
+ const validationSchema = Yup.object().shape({
153
+ title: Yup.string().required('Title is required'),
154
+ description: Yup.string().min(10, 'Description must be at least 10 characters'),
155
+ category: Yup.string().required('Category is required'),
156
+ publishDate: Yup.date().required('Publish date is required'),
157
+ country: Yup.string().required('Country is required'),
158
+ priority: Yup.number().min(1).max(10),
159
+ tags: Yup.array().min(1, 'At least one tag is required'),
160
+ });
161
+
162
+ const categoryOptions = [
163
+ { label: 'Technology', value: 'tech' },
164
+ { label: 'Design', value: 'design' },
165
+ { label: 'Business', value: 'business' },
166
+ { label: 'Marketing', value: 'marketing' },
167
+ ];
168
+
169
+ const handleSubmit = (values: any) => {
170
+ console.log('Advanced form values:', values);
171
+ alert(JSON.stringify(values, null, 2));
172
+ };
173
+
174
+ return (
175
+ <Formik
176
+ initialValues={initialValues}
177
+ validationSchema={validationSchema}
178
+ onSubmit={handleSubmit}
179
+ >
180
+ {({ handleSubmit }) => (
181
+ <FormikForm>
182
+ <Vertical gap={20} width="100%" maxWidth={500}>
183
+ <FormikTextField
184
+ name="title"
185
+ label="Title"
186
+ placeholder="Enter article title"
187
+ />
188
+
189
+ <FormikTextArea
190
+ name="description"
191
+ label="Description"
192
+ placeholder="Enter article description"
193
+ maxRows={4}
194
+ />
195
+
196
+ <FormikSelect
197
+ name="category"
198
+ label="Category"
199
+ placeholder="Select a category"
200
+ options={categoryOptions}
201
+ />
202
+
203
+ <FormikDatePicker
204
+ name="publishDate"
205
+ label="Publish Date"
206
+ placeholder="Select publish date"
207
+ />
208
+
209
+ <FormikCountryPicker
210
+ name="country"
211
+ label="Target Country"
212
+ placeholder="Select target country"
213
+ />
214
+
215
+ <FormikColorInput
216
+ name="themeColor"
217
+ label="Theme Color"
218
+ />
219
+
220
+ <FormikSlider
221
+ name="priority"
222
+ label="Priority (1-10)"
223
+ min={1}
224
+ max={10}
225
+ step={1}
226
+ />
227
+
228
+ <FormikTagInput
229
+ name="tags"
230
+ label="Tags"
231
+ placeholder="Add tags..."
232
+ />
233
+
234
+ <FormikSwitch
235
+ name="isPublished"
236
+ label="Publish immediately"
237
+ />
238
+
239
+ <Button type="submit" onClick={handleSubmit}>
240
+ Create Article
241
+ </Button>
242
+ </Vertical>
243
+ </FormikForm>
244
+ )}
245
+ </Formik>
246
+ );
247
+ };
248
+ ```
249
+
250
+ ### **Form Validation Examples**
251
+ ```tsx
252
+ import React from 'react';
253
+ import { Formik } from 'formik';
254
+ import * as Yup from 'yup';
255
+ import { FormikForm, FormikTextField, FormikPassword } from '@app-studio/web';
256
+ import { Button } from '@app-studio/web';
257
+ import { Vertical } from 'app-studio';
258
+
259
+ export const ValidationForm = () => {
260
+ const initialValues = {
261
+ username: '',
262
+ email: '',
263
+ password: '',
264
+ confirmPassword: '',
265
+ };
266
+
267
+ const validationSchema = Yup.object().shape({
268
+ username: Yup.string()
269
+ .min(3, 'Username must be at least 3 characters')
270
+ .max(20, 'Username must be less than 20 characters')
271
+ .matches(/^[a-zA-Z0-9_]+$/, 'Username can only contain letters, numbers, and underscores')
272
+ .required('Username is required'),
273
+ email: Yup.string()
274
+ .email('Invalid email format')
275
+ .required('Email is required'),
276
+ password: Yup.string()
277
+ .min(8, 'Password must be at least 8 characters')
278
+ .matches(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/, 'Password must contain uppercase, lowercase, and number')
279
+ .required('Password is required'),
280
+ confirmPassword: Yup.string()
281
+ .oneOf([Yup.ref('password')], 'Passwords must match')
282
+ .required('Please confirm your password'),
283
+ });
284
+
285
+ const handleSubmit = (values: any) => {
286
+ console.log('Registration values:', values);
287
+ };
288
+
289
+ return (
290
+ <Formik
291
+ initialValues={initialValues}
292
+ validationSchema={validationSchema}
293
+ onSubmit={handleSubmit}
294
+ >
295
+ {({ handleSubmit, errors, touched }) => (
296
+ <FormikForm>
297
+ <Vertical gap={16} width="100%" maxWidth={400}>
298
+ <FormikTextField
299
+ name="username"
300
+ label="Username"
301
+ placeholder="Enter username"
302
+ error={touched.username && errors.username}
303
+ />
304
+
305
+ <FormikTextField
306
+ name="email"
307
+ label="Email"
308
+ type="email"
309
+ placeholder="Enter email"
310
+ error={touched.email && errors.email}
311
+ />
312
+
313
+ <FormikPassword
314
+ name="password"
315
+ label="Password"
316
+ placeholder="Enter password"
317
+ error={touched.password && errors.password}
318
+ />
319
+
320
+ <FormikPassword
321
+ name="confirmPassword"
322
+ label="Confirm Password"
323
+ placeholder="Confirm password"
324
+ error={touched.confirmPassword && errors.confirmPassword}
325
+ />
326
+
327
+ <Button type="submit" onClick={handleSubmit}>
328
+ Register
329
+ </Button>
330
+ </Vertical>
331
+ </FormikForm>
332
+ )}
333
+ </Formik>
334
+ );
335
+ };
336
+ ```
337
+
338
+ ### **Dynamic Form Fields**
339
+ ```tsx
340
+ import React from 'react';
341
+ import { Formik, FieldArray } from 'formik';
342
+ import * as Yup from 'yup';
343
+ import { FormikForm, FormikTextField } from '@app-studio/web';
344
+ import { Button } from '@app-studio/web';
345
+ import { Vertical, Horizontal } from 'app-studio';
346
+ import { PlusIcon, MinusIcon } from '@app-studio/web';
347
+
348
+ export const DynamicForm = () => {
349
+ const initialValues = {
350
+ projectName: '',
351
+ tasks: [{ name: '', description: '' }],
352
+ };
353
+
354
+ const validationSchema = Yup.object().shape({
355
+ projectName: Yup.string().required('Project name is required'),
356
+ tasks: Yup.array().of(
357
+ Yup.object().shape({
358
+ name: Yup.string().required('Task name is required'),
359
+ description: Yup.string().required('Task description is required'),
360
+ })
361
+ ).min(1, 'At least one task is required'),
362
+ });
363
+
364
+ const handleSubmit = (values: any) => {
365
+ console.log('Project values:', values);
366
+ };
367
+
368
+ return (
369
+ <Formik
370
+ initialValues={initialValues}
371
+ validationSchema={validationSchema}
372
+ onSubmit={handleSubmit}
373
+ >
374
+ {({ handleSubmit, values }) => (
375
+ <FormikForm>
376
+ <Vertical gap={20} width="100%" maxWidth={600}>
377
+ <FormikTextField
378
+ name="projectName"
379
+ label="Project Name"
380
+ placeholder="Enter project name"
381
+ />
382
+
383
+ <FieldArray name="tasks">
384
+ {({ push, remove }) => (
385
+ <Vertical gap={16}>
386
+ <Horizontal justifyContent="space-between" alignItems="center">
387
+ <h3>Tasks</h3>
388
+ <Button
389
+ type="button"
390
+ icon={<PlusIcon widthHeight={16} />}
391
+ onClick={() => push({ name: '', description: '' })}
392
+ variant="outline"
393
+ size="sm"
394
+ >
395
+ Add Task
396
+ </Button>
397
+ </Horizontal>
398
+
399
+ {values.tasks.map((task, index) => (
400
+ <Vertical
401
+ key={index}
402
+ gap={12}
403
+ padding={16}
404
+ border="1px solid"
405
+ borderColor="color.gray.200"
406
+ borderRadius={8}
407
+ >
408
+ <Horizontal justifyContent="space-between" alignItems="center">
409
+ <h4>Task {index + 1}</h4>
410
+ {values.tasks.length > 1 && (
411
+ <Button
412
+ type="button"
413
+ icon={<MinusIcon widthHeight={16} />}
414
+ onClick={() => remove(index)}
415
+ variant="ghost"
416
+ size="sm"
417
+ colorScheme="theme.error"
418
+ >
419
+ Remove
420
+ </Button>
421
+ )}
422
+ </Horizontal>
423
+
424
+ <FormikTextField
425
+ name={`tasks.${index}.name`}
426
+ label="Task Name"
427
+ placeholder="Enter task name"
428
+ />
429
+
430
+ <FormikTextField
431
+ name={`tasks.${index}.description`}
432
+ label="Task Description"
433
+ placeholder="Enter task description"
434
+ />
435
+ </Vertical>
436
+ ))}
437
+ </Vertical>
438
+ )}
439
+ </FieldArray>
440
+
441
+ <Button type="submit" onClick={handleSubmit}>
442
+ Create Project
443
+ </Button>
444
+ </Vertical>
445
+ </FormikForm>
446
+ )}
447
+ </Formik>
448
+ );
449
+ };
450
+ ```
451
+
452
+ ### **Form Components**
453
+
454
+ **FormikForm**
455
+ - Main form wrapper with Formik integration
456
+ - Provides form context and state management
457
+ - Supports auto-focus and form navigation
458
+
459
+ **FormikTextField**
460
+ - Single-line text input with validation
461
+ - Supports various input types (text, email, password, etc.)
462
+ - Built-in error display and styling
463
+
464
+ **FormikTextArea**
465
+ - Multi-line text input
466
+ - Configurable rows and columns
467
+ - Auto-resize functionality
468
+
469
+ **FormikCheckbox**
470
+ - Boolean input for yes/no choices
471
+ - Custom styling and label positioning
472
+ - Indeterminate state support
473
+
474
+ **FormikSwitch**
475
+ - Toggle switch for boolean values
476
+ - Smooth animations and transitions
477
+ - Customizable colors and sizes
478
+
479
+ **FormikSelect**
480
+ - Dropdown selection component
481
+ - Single and multi-select support
482
+ - Search and filter capabilities
483
+
484
+ **FormikDatePicker**
485
+ - Date selection with calendar popup
486
+ - Date range selection
487
+ - Customizable date formats
488
+
489
+ **FormikCountryPicker**
490
+ - Country selection with flags
491
+ - Search functionality
492
+ - Localized country names
493
+
494
+ **FormikColorInput**
495
+ - Color picker with preview
496
+ - Hex, RGB, and HSL support
497
+ - Predefined color palettes
498
+
499
+ **FormikPassword**
500
+ - Password input with visibility toggle
501
+ - Strength indicator
502
+ - Custom validation rules
503
+
504
+ **FormikComboBox**
505
+ - Searchable dropdown with custom options
506
+ - Multi-select capabilities
507
+ - Tag-style selection display
508
+
509
+ **FormikSlider**
510
+ - Range input with visual feedback
511
+ - Step configuration
512
+ - Min/max value constraints
513
+
514
+ **FormikTagInput**
515
+ - Tag-based input for multiple values
516
+ - Auto-completion support
517
+ - Custom tag validation
518
+
519
+ ### **Props Reference**
520
+
521
+ **Common Formik Props (inherited by all Formik components):**
522
+
523
+ | Prop | Type | Description |
524
+ | ---- | ---- | ----------- |
525
+ | name | string | Field name for Formik state management |
526
+ | label | string | Field label text |
527
+ | placeholder | string | Placeholder text |
528
+ | error | string \| boolean | Error message or error state |
529
+ | disabled | boolean | Whether the field is disabled |
530
+ | required | boolean | Whether the field is required |
531
+
532
+ **FormikForm Props:**
533
+
534
+ | Prop | Type | Default | Description |
535
+ | ---- | ---- | ------- | ----------- |
536
+ | autoFocus | boolean | false | Auto-focus first field |
537
+ | initFocus | string | undefined | Specific field to focus initially |
538
+ | onChange | function | undefined | Callback when form values change |
539
+
540
+ ### **Validation Patterns**
541
+
542
+ **Email Validation:**
543
+ ```tsx
544
+ email: Yup.string()
545
+ .email('Invalid email format')
546
+ .required('Email is required')
547
+ ```
548
+
549
+ **Password Validation:**
550
+ ```tsx
551
+ password: Yup.string()
552
+ .min(8, 'Password must be at least 8 characters')
553
+ .matches(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/, 'Password must contain uppercase, lowercase, and number')
554
+ .required('Password is required')
555
+ ```
556
+
557
+ **Phone Number Validation:**
558
+ ```tsx
559
+ phone: Yup.string()
560
+ .matches(/^\+?[1-9]\d{1,14}$/, 'Invalid phone number')
561
+ .required('Phone number is required')
562
+ ```
563
+
564
+ **URL Validation:**
565
+ ```tsx
566
+ website: Yup.string()
567
+ .url('Invalid URL format')
568
+ .required('Website URL is required')
569
+ ```
570
+
571
+ ### **Form State Management**
572
+
573
+ **Accessing Form State:**
574
+ ```tsx
575
+ import { useFormikContext } from 'formik';
576
+
577
+ const FormStatus = () => {
578
+ const { values, errors, touched, isSubmitting, isValid } = useFormikContext();
579
+
580
+ return (
581
+ <div>
582
+ <p>Form Valid: {isValid ? 'Yes' : 'No'}</p>
583
+ <p>Submitting: {isSubmitting ? 'Yes' : 'No'}</p>
584
+ <p>Values: {JSON.stringify(values)}</p>
585
+ </div>
586
+ );
587
+ };
588
+ ```
589
+
590
+ **Custom Field Component:**
591
+ ```tsx
592
+ import { useFormikInput } from '@app-studio/web';
593
+
594
+ const CustomFormikField = (props) => {
595
+ const formProps = useFormikInput(props);
596
+
597
+ return (
598
+ <input
599
+ {...formProps}
600
+ style={{
601
+ border: formProps.error ? '1px solid red' : '1px solid gray',
602
+ }}
603
+ />
604
+ );
605
+ };
606
+ ```
607
+
608
+ ### **Best Practices**
609
+
610
+ **Form Structure:**
611
+ - Use semantic HTML structure
612
+ - Group related fields logically
613
+ - Provide clear labels and instructions
614
+ - Use appropriate field types for data
615
+
616
+ **Validation:**
617
+ - Validate on both client and server side
618
+ - Provide real-time feedback
619
+ - Use clear, actionable error messages
620
+ - Validate on blur for better UX
621
+
622
+ **Accessibility:**
623
+ - Use proper labels and ARIA attributes
624
+ - Ensure keyboard navigation works
625
+ - Provide error announcements
626
+ - Maintain focus management
627
+
628
+ **Performance:**
629
+ - Use field-level validation for complex forms
630
+ - Debounce validation for expensive operations
631
+ - Minimize re-renders with proper state management
632
+ - Use lazy validation when appropriate
633
+
634
+ ### **Integration Examples**
635
+
636
+ **With API Calls:**
637
+ ```tsx
638
+ const handleSubmit = async (values, { setSubmitting, setFieldError }) => {
639
+ try {
640
+ setSubmitting(true);
641
+ const response = await api.createUser(values);
642
+ console.log('User created:', response);
643
+ // Handle success
644
+ } catch (error) {
645
+ if (error.field) {
646
+ setFieldError(error.field, error.message);
647
+ }
648
+ // Handle error
649
+ } finally {
650
+ setSubmitting(false);
651
+ }
652
+ };
653
+ ```
654
+
655
+ **With File Uploads:**
656
+ ```tsx
657
+ import { FormikForm, FormikTextField } from '@app-studio/web';
658
+ import { Uploader } from '@app-studio/web';
659
+
660
+ const FormWithUpload = () => {
661
+ const [uploadedFile, setUploadedFile] = useState(null);
662
+
663
+ return (
664
+ <Formik
665
+ initialValues={{ name: '', file: null }}
666
+ onSubmit={(values) => {
667
+ const formData = new FormData();
668
+ formData.append('name', values.name);
669
+ formData.append('file', uploadedFile);
670
+ // Submit form data
671
+ }}
672
+ >
673
+ <FormikForm>
674
+ <FormikTextField name="name" label="Name" />
675
+ <Uploader onFileSelect={setUploadedFile} />
676
+ <Button type="submit">Submit</Button>
677
+ </FormikForm>
678
+ </Formik>
679
+ );
680
+ };
681
+ ```