dynamic-formik-form 1.0.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 ADDED
@@ -0,0 +1,810 @@
1
+ # dynamic-formik-form
2
+
3
+ > **A production-ready, adapter-based React form library that generates dynamic forms from JSON configuration using Formik and Yup. Works with Material-UI, Bootstrap, Ant Design, or plain CSS.**
4
+
5
+ [![npm version](https://img.shields.io/npm/v/dynamic-formik-form.svg)](https://www.npmjs.com/package/dynamic-formik-form)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+ [![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/)
8
+
9
+ ## Why This Library?
10
+
11
+ Building forms in React is repetitive and error-prone. `dynamic-formik-form` solves this by:
12
+
13
+ - **🎯 JSON-Driven Forms**: Define forms as data, not code. Perfect for admin panels, CMSs, and dynamic UIs
14
+ - **🎨 UI Library Agnostic**: Use Material-UI, Bootstrap, Ant Design, or your own CSSβ€”switch adapters without changing form logic
15
+ - **βœ… Built on Battle-Tested Libraries**: Leverages Formik for state management and Yup for validation
16
+ - **πŸ”§ Production-Ready**: Extracted from production code, handling edge cases like conditional fields, nested arrays, and complex validation
17
+ - **πŸ“¦ Zero Bloat**: Tree-shakeable, modular architecture. Only bundle what you use
18
+ - **πŸ”Œ Fully Extensible**: Create custom adapters for any UI library or design system
19
+
20
+ ## Features
21
+
22
+ - 🎨 **Extensible UI Libraries** - Material-UI, Bootstrap, Ant Design, or plain CSS
23
+ - 🎯 **22 Field Types** - Input, textarea, select, checkbox, radio, date picker, file upload, and more
24
+ - πŸ”Œ **Icon Flexibility** - Use any icon library (default SVG icons included)
25
+ - πŸ“¦ **TypeScript First** - Full TypeScript support with comprehensive types
26
+ - 🧩 **Modular Architecture** - Small, focused, reusable components
27
+ - βœ… **Production Ready** - Extracted from production code, battle-tested
28
+ - πŸ”„ **Conditional Fields** - Show/hide fields based on form values
29
+ - πŸ“‹ **Field Arrays** - Dynamic key-value pairs and simple arrays
30
+ - πŸŽ›οΈ **Nested Attributes** - Complex nested form structures
31
+ - πŸ” **Async Select** - Load options from API endpoints
32
+ - 🎨 **Custom Components** - Inject custom React components anywhere
33
+
34
+ ## Installation
35
+
36
+ ### Core Package
37
+
38
+ ```bash
39
+ npm install dynamic-formik-form formik yup react react-dom
40
+ ```
41
+
42
+ ### Peer Dependencies
43
+
44
+ The library requires these peer dependencies (you control the versions):
45
+
46
+ - `react` >= 18.0.0
47
+ - `react-dom` >= 18.0.0
48
+ - `formik` ^2.0.0 || ^3.0.0
49
+ - `yup` ^1.0.0
50
+
51
+ ### UI Library Adapters (Optional)
52
+
53
+ Choose one or more UI libraries:
54
+
55
+ ```bash
56
+ # Material-UI
57
+ npm install @mui/material @mui/x-date-pickers @mui/icons-material
58
+
59
+ # Bootstrap React
60
+ npm install react-bootstrap react-bootstrap-icons bootstrap
61
+
62
+ # Ant Design
63
+ npm install antd @ant-design/icons
64
+
65
+ # Or use plain CSS - no additional dependencies needed!
66
+ ```
67
+
68
+ ## Quick Start
69
+
70
+ ### Minimal Example
71
+
72
+ ```typescript
73
+ import React from 'react';
74
+ import { useFormik } from 'formik';
75
+ import * as Yup from 'yup';
76
+ import { DynamicForm } from 'dynamic-formik-form';
77
+
78
+ const MyForm = () => {
79
+ const formik = useFormik({
80
+ initialValues: {
81
+ email: '',
82
+ password: '',
83
+ },
84
+ validationSchema: Yup.object({
85
+ email: Yup.string().email('Invalid email').required('Email is required'),
86
+ password: Yup.string().min(8, 'Password must be at least 8 characters').required(),
87
+ }),
88
+ onSubmit: (values) => {
89
+ console.log('Form submitted:', values);
90
+ },
91
+ });
92
+
93
+ const fields = [
94
+ {
95
+ type: 'inputfield' as const,
96
+ name: 'email',
97
+ label: 'Email Address',
98
+ placeholder: 'Enter your email',
99
+ required: true,
100
+ fieldType: 'email',
101
+ },
102
+ {
103
+ type: 'inputfield' as const,
104
+ name: 'password',
105
+ label: 'Password',
106
+ fieldType: 'password',
107
+ required: true,
108
+ isVisibleEnable: true, // Show password visibility toggle
109
+ },
110
+ ];
111
+
112
+ return (
113
+ <form onSubmit={formik.handleSubmit}>
114
+ <DynamicForm fields={fields} formik={formik} />
115
+ <button type="submit">Submit</button>
116
+ </form>
117
+ );
118
+ };
119
+ ```
120
+
121
+ ### JSON-Driven Form Example
122
+
123
+ ```typescript
124
+ // Define form structure as JSON (can come from API, config file, etc.)
125
+ const formConfig = [
126
+ {
127
+ type: 'inputfield',
128
+ name: 'username',
129
+ label: 'Username',
130
+ required: true,
131
+ },
132
+ {
133
+ type: 'dropdown',
134
+ name: 'country',
135
+ label: 'Country',
136
+ values: {
137
+ '': 'Select a country',
138
+ us: 'United States',
139
+ uk: 'United Kingdom',
140
+ ca: 'Canada',
141
+ },
142
+ required: true,
143
+ },
144
+ {
145
+ type: 'textarea',
146
+ name: 'comments',
147
+ label: 'Comments',
148
+ rows: 4,
149
+ },
150
+ ];
151
+
152
+ // Render the form
153
+ <DynamicForm fields={formConfig} formik={formik} />
154
+ ```
155
+
156
+ ## UI Library Adapters
157
+
158
+ ### With Material-UI
159
+
160
+ ```typescript
161
+ import { DynamicForm, createMUIAdapter, createMUIIcons } from 'dynamic-formik-form';
162
+ import {
163
+ Box,
164
+ Button,
165
+ TextField,
166
+ Checkbox,
167
+ FormControlLabel,
168
+ FormHelperText,
169
+ Radio,
170
+ RadioGroup,
171
+ Switch,
172
+ Typography,
173
+ Popover,
174
+ MenuItem,
175
+ Paper,
176
+ IconButton,
177
+ } from '@mui/material';
178
+ import { DatePicker } from '@mui/x-date-pickers';
179
+ import {
180
+ Info as InfoIcon,
181
+ Visibility as VisibilityIcon,
182
+ VisibilityOff as VisibilityOffIcon,
183
+ ContentCopy as CopyIcon,
184
+ Add as AddIcon,
185
+ Delete as DeleteIcon,
186
+ } from '@mui/icons-material';
187
+
188
+ const muiAdapter = createMUIAdapter(
189
+ Box,
190
+ Button,
191
+ Checkbox,
192
+ FormControlLabel,
193
+ FormHelperText,
194
+ IconButton,
195
+ MenuItem,
196
+ Paper,
197
+ Popover,
198
+ Radio,
199
+ RadioGroup,
200
+ Switch,
201
+ TextField,
202
+ Typography,
203
+ DatePicker
204
+ );
205
+
206
+ const muiIcons = createMUIIcons(
207
+ InfoIcon,
208
+ VisibilityIcon,
209
+ VisibilityOffIcon,
210
+ CopyIcon,
211
+ AddIcon,
212
+ DeleteIcon
213
+ );
214
+
215
+ <DynamicForm
216
+ fields={fields}
217
+ formik={formik}
218
+ uiLibrary={{
219
+ adapter: muiAdapter,
220
+ icons: muiIcons,
221
+ name: 'mui',
222
+ }}
223
+ />
224
+ ```
225
+
226
+ ### With Bootstrap
227
+
228
+ ```typescript
229
+ import { DynamicForm, createBootstrapAdapter, createBootstrapIcons } from 'dynamic-formik-form';
230
+ import {
231
+ Form,
232
+ FormControl,
233
+ FormLabel,
234
+ FormText,
235
+ FormCheck,
236
+ FormSelect,
237
+ Button,
238
+ InputGroup,
239
+ OverlayTrigger,
240
+ Popover,
241
+ ListGroup,
242
+ ListGroupItem,
243
+ } from 'react-bootstrap';
244
+ import {
245
+ InfoCircle as InfoIcon,
246
+ Eye as VisibilityIcon,
247
+ EyeSlash as VisibilityOffIcon,
248
+ Clipboard as CopyIcon,
249
+ PlusCircle as AddIcon,
250
+ Trash as DeleteIcon,
251
+ } from 'react-bootstrap-icons';
252
+ import 'bootstrap/dist/css/bootstrap.min.css';
253
+
254
+ const bootstrapAdapter = createBootstrapAdapter(
255
+ Form,
256
+ FormControl,
257
+ FormLabel,
258
+ FormText,
259
+ FormCheck,
260
+ FormSelect,
261
+ Button,
262
+ InputGroup,
263
+ OverlayTrigger,
264
+ Popover,
265
+ ListGroup,
266
+ ListGroupItem
267
+ );
268
+
269
+ const bootstrapIcons = createBootstrapIcons(
270
+ InfoIcon,
271
+ VisibilityIcon,
272
+ VisibilityOffIcon,
273
+ CopyIcon,
274
+ AddIcon,
275
+ DeleteIcon
276
+ );
277
+
278
+ <DynamicForm
279
+ fields={fields}
280
+ formik={formik}
281
+ uiLibrary={{
282
+ adapter: bootstrapAdapter,
283
+ icons: bootstrapIcons,
284
+ name: 'bootstrap',
285
+ }}
286
+ />
287
+ ```
288
+
289
+ ### With Ant Design
290
+
291
+ ```typescript
292
+ import { DynamicForm, createAntDesignAdapter, createAntDesignIcons } from 'dynamic-formik-form';
293
+ import {
294
+ Input,
295
+ Button,
296
+ Checkbox,
297
+ Radio,
298
+ Switch,
299
+ Select,
300
+ Form,
301
+ Typography,
302
+ Popover,
303
+ DatePicker,
304
+ } from 'antd';
305
+ import {
306
+ InfoCircleOutlined as InfoIcon,
307
+ EyeOutlined as VisibilityIcon,
308
+ EyeInvisibleOutlined as VisibilityOffIcon,
309
+ CopyOutlined as CopyIcon,
310
+ PlusCircleOutlined as AddIcon,
311
+ DeleteOutlined as DeleteIcon,
312
+ } from '@ant-design/icons';
313
+
314
+ const antdAdapter = createAntDesignAdapter(
315
+ Input,
316
+ Button,
317
+ Checkbox,
318
+ Radio,
319
+ Switch,
320
+ Select,
321
+ Form,
322
+ Typography,
323
+ Popover,
324
+ DatePicker
325
+ );
326
+
327
+ const antdIcons = createAntDesignIcons(
328
+ InfoIcon,
329
+ VisibilityIcon,
330
+ VisibilityOffIcon,
331
+ CopyIcon,
332
+ AddIcon,
333
+ DeleteIcon
334
+ );
335
+
336
+ <DynamicForm
337
+ fields={fields}
338
+ formik={formik}
339
+ uiLibrary={{
340
+ adapter: antdAdapter,
341
+ icons: antdIcons,
342
+ name: 'antd',
343
+ }}
344
+ />
345
+ ```
346
+
347
+ ### With Plain CSS (No UI Library)
348
+
349
+ The library works out-of-the-box with native HTML elements. Just style them with your own CSS!
350
+
351
+ ```typescript
352
+ import { DynamicForm } from 'dynamic-formik-form';
353
+ import './my-custom-styles.css';
354
+
355
+ // No uiLibrary prop needed - uses default HTML adapter
356
+ <DynamicForm fields={fields} formik={formik} />
357
+ ```
358
+
359
+ ```css
360
+ /* my-custom-styles.css */
361
+ input[type="text"],
362
+ input[type="email"],
363
+ input[type="password"] {
364
+ padding: 8px 12px;
365
+ border: 1px solid #ccc;
366
+ border-radius: 4px;
367
+ font-size: 14px;
368
+ width: 100%;
369
+ }
370
+
371
+ input.error {
372
+ border-color: #dc3545;
373
+ }
374
+
375
+ .form-control {
376
+ margin-bottom: 16px;
377
+ }
378
+
379
+ label {
380
+ display: block;
381
+ margin-bottom: 4px;
382
+ font-weight: 500;
383
+ }
384
+ ```
385
+
386
+ ## API Reference
387
+
388
+ ### `<DynamicForm />`
389
+
390
+ The main component that renders fields dynamically based on configuration.
391
+
392
+ #### Props
393
+
394
+ | Prop Name | Type | Required | Default | Description |
395
+ |-----------|------|----------|---------|-------------|
396
+ | `fields` | `(FieldConfig \| false)[]` | Yes | - | Array of field configurations. Use `false` for conditional fields. |
397
+ | `formik` | `FormikProps<T>` | Yes | - | Formik instance from `useFormik()` hook. Must include `values`, `errors`, `touched`, `handleChange`, `handleBlur`, `setFieldValue`, etc. |
398
+ | `uiLibrary` | `UILibraryConfig` | No | `{ adapter: defaultAdapter, icons: defaultIcons }` | UI library adapter and icons configuration. See [Adapter Configuration](#adapter-configuration). |
399
+ | `firstInitialValues` | `T` | No | - | Initial values for the form. Used for resetting child fields. |
400
+ | `customFormChange` | `(event: ChangeEvent, type: string) => void` | No | - | Custom change handler that receives the event and field type. Overrides default Formik handlers. |
401
+ | `fieldCount` | `number` | No | - | Total number of fields. Used for field array management. |
402
+ | `attributeFields` | `FieldConfig[]` | No | - | Additional fields for attribute field type. |
403
+ | `onUpdateFormFields` | `(fields: FieldConfig[]) => void` | No | - | Callback when fields are updated dynamically. |
404
+ | `handleDeleteChange` | `(count: number) => void` | No | - | Callback when field array items are deleted. |
405
+ | `RadiusTab` | `boolean` | No | `false` | Enable rounded tab styling for attribute fields. |
406
+ | `value` | `number` | No | - | Tab index value for attribute fields. |
407
+
408
+ #### Example
409
+
410
+ ```typescript
411
+ <DynamicForm
412
+ fields={fields}
413
+ formik={formik}
414
+ uiLibrary={{
415
+ adapter: muiAdapter,
416
+ icons: muiIcons,
417
+ name: 'mui',
418
+ }}
419
+ customFormChange={(event, type) => {
420
+ console.log('Field changed:', type, event.target.value);
421
+ }}
422
+ />
423
+ ```
424
+
425
+ ### Field Configuration (`FieldConfig`)
426
+
427
+ All field types extend `BaseFieldConfig` with type-specific properties.
428
+
429
+ #### BaseFieldConfig
430
+
431
+ Common properties available on all field types:
432
+
433
+ | Prop Name | Type | Required | Default | Description |
434
+ |-----------|------|----------|---------|-------------|
435
+ | `name` | `string` | Yes | - | Field name (must match Formik field name). |
436
+ | `type` | `FieldType` | Yes | - | Field type. See [Field Types](#field-types). |
437
+ | `label` | `string` | No | - | Field label displayed above the input. |
438
+ | `placeholder` | `string` | No | - | Placeholder text for input fields. |
439
+ | `desc` | `string` | No | - | Description/helper text displayed below the field. |
440
+ | `info` | `string` | No | - | Info tooltip text. Shows info icon when provided. |
441
+ | `required` | `boolean` | No | `false` | Whether the field is required. Shows asterisk (*) indicator. |
442
+ | `disabled` | `boolean` | No | `false` | Whether the field is disabled. |
443
+ | `hidden` | `boolean` | No | `false` | Whether the field is hidden (not rendered). |
444
+ | `readonly` | `boolean` | No | `false` | Whether the field is read-only. |
445
+ | `customClass` | `string` | No | - | Custom CSS class for the field wrapper. |
446
+ | `customLabelClass` | `string` | No | - | Custom CSS class for the label. |
447
+ | `customComponentClass` | `string` | No | - | Custom CSS class for the input component. |
448
+ | `customDescClass` | `string` | No | - | Custom CSS class for the description text. |
449
+ | `customAttrClass` | `string` | No | - | Custom CSS class for attribute fields. |
450
+ | `dataTestId` | `string` | No | - | Data test ID for testing. Auto-generated if not provided. |
451
+ | `noIndent` | `boolean` | No | `false` | Remove indentation for nested/child fields. |
452
+ | `showOptional` | `boolean` | No | `false` | Show "(optional)" text for non-required fields. |
453
+ | `isButtonVisible` | `boolean` | No | `false` | Show action button (field-specific). |
454
+ | `showCustomError` | `boolean` | No | `false` | Always show error message even if field is not touched. |
455
+ | `shouldHide` | `(params: { formik, name, index? }) => boolean` | No | - | Function to conditionally hide field based on form state. |
456
+ | `child` | `FieldConfig[]` | No | - | Child fields shown conditionally based on parent value. |
457
+ | `hiddenlabel` | `string` | No | - | Value that triggers child field visibility (for dropdown/select). |
458
+ | `targetType` | `string` | No | - | Value that triggers child field visibility (for radio buttons). |
459
+ | `component` | `ReactNode` | No | - | Custom React component rendered after the field. |
460
+ | `blockComponent` | `ReactNode` | No | - | Custom React component rendered as a block element. |
461
+ | `customHandleChange` | `(event, type, index?) => void` | No | - | Custom change handler for this specific field. |
462
+ | `customFormChange` | `(event, type) => void` | No | - | Custom form-level change handler. |
463
+ | `onBlur` | `(e: FocusEvent) => void` | No | - | Custom blur handler. |
464
+ | `onClickLink` | `() => void` | No | - | Click handler for link fields. |
465
+ | `isVisibleEnable` | `boolean` | No | `false` | Show password visibility toggle (for password fields). |
466
+ | `isCopyEnable` | `boolean` | No | `false` | Show copy button (for text fields). |
467
+ | `customIcon` | `ReactNode` | No | - | Custom icon component. |
468
+ | `ref` | `Ref<HTMLElement>` | No | - | React ref forwarded to the input element. |
469
+
470
+ #### Field Type-Specific Configurations
471
+
472
+ ##### InputField (`type: 'inputfield'`)
473
+
474
+ | Prop Name | Type | Required | Default | Description |
475
+ |-----------|------|----------|---------|-------------|
476
+ | `fieldType` | `'text' \| 'email' \| 'password' \| 'number' \| 'tel' \| 'url'` | No | `'text'` | HTML input type. |
477
+ | `autocomplete` | `string` | No | - | Autocomplete attribute value. |
478
+ | `min` | `number` | No | - | Minimum value (for number type). |
479
+ | `max` | `number` | No | - | Maximum value (for number type). |
480
+ | `suffix` | `string` | No | - | Suffix text displayed after input. |
481
+ | `ignoreChar` | `boolean` | No | `false` | Ignore special characters in input. |
482
+
483
+ ##### TextareaField (`type: 'textarea'`)
484
+
485
+ | Prop Name | Type | Required | Default | Description |
486
+ |-----------|------|----------|---------|-------------|
487
+ | `rows` | `number` | No | `4` | Number of visible text rows. |
488
+
489
+ ##### SelectField (`type: 'dropdown' \| 'singleSelect' \| 'multiSelect' \| 'asyncSelect'`)
490
+
491
+ | Prop Name | Type | Required | Default | Description |
492
+ |-----------|------|----------|---------|-------------|
493
+ | `values` | `Array<{value, label, desc?}> \| Record<string, string>` | No | `{}` | Options for select. Array format for react-select, object for native select. |
494
+ | `isSearchable` | `boolean` | No | `false` | Enable search/filter (react-select only). |
495
+ | `isMulti` | `boolean` | No | `false` | Allow multiple selections (react-select only). |
496
+ | `loaderCall` | `(inputValue: string) => Promise<{apps, error?}>` | No | - | Async function to load options (asyncSelect only). |
497
+ | `headerKey` | `string` | No | - | Header key for grouped options. |
498
+ | `optionsLabel` | `boolean` | No | `false` | Show label in options. |
499
+ | `disabledDropdownOption` | `boolean` | No | `false` | Disable dropdown option selection. |
500
+ | `disabledOptionText` | `string` | No | - | Text shown for disabled options. |
501
+ | `searchField` | `string` | No | - | Field name to search in async options. |
502
+ | `resetChild` | `boolean` | No | `false` | Reset child fields when selection changes. |
503
+ | `ignoreChar` | `boolean` | No | `false` | Ignore special characters (dropdown only). |
504
+
505
+ ##### CheckboxField (`type: 'checkbox'`)
506
+
507
+ | Prop Name | Type | Required | Default | Description |
508
+ |-----------|------|----------|---------|-------------|
509
+ | `values` | `Record<string, string>` | No | `{}` | Checkbox options (for multiple checkboxes). |
510
+
511
+ ##### RadioField (`type: 'radiobtn'`)
512
+
513
+ | Prop Name | Type | Required | Default | Description |
514
+ |-----------|------|----------|---------|-------------|
515
+ | `values` | `Record<string, string>` | No | `{}` | Radio button options. Key is value, value is label. |
516
+
517
+ ##### DatePickerField (`type: 'datePicker' \| 'dateTimePicker'`)
518
+
519
+ | Prop Name | Type | Required | Default | Description |
520
+ |-----------|------|----------|---------|-------------|
521
+ | `dateFormat` | `string` | No | - | Date format string. |
522
+ | `disablePast` | `boolean` | No | `false` | Disable past dates. |
523
+ | `views` | `string[]` | No | - | Date picker views (MUI only). |
524
+
525
+ ##### FieldArrayField (`type: 'fieldArray'`)
526
+
527
+ | Prop Name | Type | Required | Default | Description |
528
+ |-----------|------|----------|---------|-------------|
529
+ | `properties` | `{isKeyValue?: boolean, keyPlaceholder?: string, valuePlaceholder?: string}` | No | - | Configuration for key-value pairs or simple arrays. |
530
+ | `buttonLabel` | `string` | No | - | Label for add/remove buttons. |
531
+ | `addNewFieldBtnLabel` | `string` | No | `'Add New'` | Label for add button. |
532
+ | `minimumValuePresent` | `boolean` | No | `false` | Require at least one item. |
533
+ | `showAddNewFieldBtn` | `boolean` | No | `true` | Show add button. |
534
+
535
+ ##### AttributeField (`type: 'attribute'`)
536
+
537
+ | Prop Name | Type | Required | Default | Description |
538
+ |-----------|------|----------|---------|-------------|
539
+ | `properties` | `FieldConfig[]` | No | `[]` | Fields within each attribute item. |
540
+ | `addNewField` | `Record<string, unknown>` | No | `{}` | Default values for new attribute items. |
541
+ | `showIllustration` | `boolean` | No | `false` | Show visual illustration. |
542
+ | `showAddNewFieldBtn` | `boolean` | No | `true` | Show add button. |
543
+ | `addNewFieldBtnLabel` | `string` | No | `'Add New'` | Label for add button. |
544
+ | `minimumValuePresent` | `boolean` | No | `false` | Require at least one item. |
545
+
546
+ ##### CounterField (`type: 'counter'`)
547
+
548
+ | Prop Name | Type | Required | Default | Description |
549
+ |-----------|------|----------|---------|-------------|
550
+ | `min` | `number` | No | - | Minimum value. |
551
+ | `max` | `number` | No | - | Maximum value. |
552
+ | `suffix` | `string` | No | - | Suffix text displayed after counter. |
553
+
554
+ ##### EditableDivField (`type: 'editablediv'`)
555
+
556
+ | Prop Name | Type | Required | Default | Description |
557
+ |-----------|------|----------|---------|-------------|
558
+ | `availableFields` | `Array<{key: string, label: string}>` | No | `[]` | Fields available for insertion into editable div. |
559
+
560
+ ## Field Types
561
+
562
+ The library supports 22 field types:
563
+
564
+ 1. **`inputfield`** - Text inputs (text, email, password, number, tel, url)
565
+ 2. **`textarea`** - Multi-line text input
566
+ 3. **`dropdown`** - Native HTML select dropdown
567
+ 4. **`singleSelect`** - Single-select dropdown (react-select compatible)
568
+ 5. **`multiSelect`** - Multi-select dropdown (react-select compatible)
569
+ 6. **`asyncSelect`** - Async-loading select (react-select compatible)
570
+ 7. **`checkbox`** - Checkbox input
571
+ 8. **`radiobtn`** - Radio button group
572
+ 9. **`toggle`** - Switch/toggle component
573
+ 10. **`fileupload`** - File upload input
574
+ 11. **`datePicker`** - Date picker
575
+ 12. **`dateTimePicker`** - Date-time picker
576
+ 13. **`counter`** - Counter with increment/decrement
577
+ 14. **`fieldArray`** - Dynamic array fields (key-value or simple)
578
+ 15. **`attribute`** - Complex nested attribute mapping
579
+ 16. **`editablediv`** - ContentEditable with field insertion
580
+ 17. **`text`** - Display text (read-only)
581
+ 18. **`link`** - Clickable link field
582
+ 19. **`component`** - Custom component wrapper
583
+ 20. **`custom`** - Custom field with label/description
584
+ 21. **`emptyField`** - Hidden input field
585
+ 22. **`delete`** - Delete button/icon
586
+
587
+ ## Advanced Usage
588
+
589
+ ### Conditional Fields
590
+
591
+ Show/hide fields based on form values:
592
+
593
+ ```typescript
594
+ const fields = [
595
+ {
596
+ type: 'dropdown',
597
+ name: 'userType',
598
+ label: 'User Type',
599
+ values: {
600
+ '': 'Select',
601
+ admin: 'Admin',
602
+ user: 'User',
603
+ },
604
+ child: [
605
+ {
606
+ type: 'inputfield',
607
+ name: 'adminCode',
608
+ label: 'Admin Code',
609
+ hiddenlabel: 'admin', // Shown when userType === 'admin'
610
+ },
611
+ ],
612
+ },
613
+ ];
614
+ ```
615
+
616
+ ### Dynamic Validation
617
+
618
+ Use Yup's dynamic validation:
619
+
620
+ ```typescript
621
+ const validationSchema = Yup.object({
622
+ email: Yup.string().email().required(),
623
+ password: Yup.string()
624
+ .min(8)
625
+ .when('confirmPassword', {
626
+ is: (value: string) => value,
627
+ then: (schema) => schema.required('Password is required'),
628
+ }),
629
+ confirmPassword: Yup.string()
630
+ .oneOf([Yup.ref('password')], 'Passwords must match')
631
+ .required(),
632
+ });
633
+ ```
634
+
635
+ ### Custom Field Renderers
636
+
637
+ Inject custom React components:
638
+
639
+ ```typescript
640
+ const fields = [
641
+ {
642
+ type: 'inputfield',
643
+ name: 'email',
644
+ label: 'Email',
645
+ component: <CustomEmailValidator />, // Rendered after field
646
+ },
647
+ {
648
+ type: 'custom',
649
+ name: 'customSection',
650
+ label: 'Custom Section',
651
+ blockComponent: <MyCustomComponent />, // Rendered as block
652
+ },
653
+ ];
654
+ ```
655
+
656
+ ### Field Arrays
657
+
658
+ Dynamic key-value pairs:
659
+
660
+ ```typescript
661
+ const fields = [
662
+ {
663
+ type: 'fieldArray',
664
+ name: 'metadata',
665
+ label: 'Metadata',
666
+ properties: {
667
+ isKeyValue: true,
668
+ keyPlaceholder: 'Key',
669
+ valuePlaceholder: 'Value',
670
+ },
671
+ addNewFieldBtnLabel: 'Add Metadata',
672
+ },
673
+ ];
674
+ ```
675
+
676
+ ### Async Select
677
+
678
+ Load options from API:
679
+
680
+ ```typescript
681
+ const fields = [
682
+ {
683
+ type: 'asyncSelect',
684
+ name: 'user',
685
+ label: 'Select User',
686
+ loaderCall: async (inputValue: string) => {
687
+ const response = await fetch(`/api/users?search=${inputValue}`);
688
+ const data = await response.json();
689
+ return {
690
+ apps: data.users.map((user: any) => ({
691
+ value: user.id,
692
+ label: user.name,
693
+ })),
694
+ };
695
+ },
696
+ },
697
+ ];
698
+ ```
699
+
700
+ ### Custom Adapters
701
+
702
+ Create adapters for any UI library. See [ADAPTER_GUIDE.md](./ADAPTER_GUIDE.md) for detailed instructions.
703
+
704
+ ```typescript
705
+ import { UILibraryAdapter } from 'dynamic-formik-form';
706
+
707
+ export const createMyLibraryAdapter = (
708
+ Input,
709
+ Button,
710
+ // ... your UI components
711
+ ): UILibraryAdapter => {
712
+ return {
713
+ Input: ({ error, ...props }) => (
714
+ <Input {...props} hasError={error} />
715
+ ),
716
+ // ... map other components
717
+ };
718
+ };
719
+ ```
720
+
721
+ ## Architecture
722
+
723
+ ### Core vs Adapter Responsibility
724
+
725
+ - **Core Library**: Handles form logic, validation, field rendering, conditional logic, and state management
726
+ - **Adapters**: Map UI library components to a common interface. No form logic.
727
+
728
+ ### Why Adapter Pattern?
729
+
730
+ 1. **Flexibility**: Users choose their UI library without vendor lock-in
731
+ 2. **Tree-Shaking**: Only bundle the adapter you use
732
+ 3. **Version Control**: Users control UI library versions (peer dependencies)
733
+ 4. **Extensibility**: Easy to add new UI libraries without modifying core
734
+ 5. **Testing**: Adapters can be mocked/swapped easily
735
+
736
+ ### Adding New UI Library Support
737
+
738
+ 1. Create adapter factory function (see `src/adapters/`)
739
+ 2. Create icon factory function (see `src/icons/`)
740
+ 3. Export from `src/adapters/index.ts` and `src/icons/index.ts`
741
+ 4. Document usage in README
742
+
743
+ See [ADAPTER_GUIDE.md](./ADAPTER_GUIDE.md) for complete guide.
744
+
745
+ ## Limitations & Roadmap
746
+
747
+ ### Current Limitations
748
+
749
+ - Date pickers require UI library adapters (MUI DatePicker, Ant Design DatePicker, etc.)
750
+ - File uploads are basic (no drag-and-drop, preview, or progress)
751
+ - Async select requires react-select (not included as dependency)
752
+ - Some advanced field types (editablediv, attribute) are complex and may need customization
753
+
754
+ ### Roadmap
755
+
756
+ - [ ] Built-in drag-and-drop file upload
757
+ - [ ] More date picker adapters
758
+ - [ ] Form builder UI component
759
+ - [ ] Form schema validator
760
+ - [ ] Performance optimizations for large forms
761
+ - [ ] Accessibility improvements
762
+ - [ ] More examples and recipes
763
+
764
+ ## Contributing
765
+
766
+ Contributions are welcome! Please:
767
+
768
+ 1. Fork the repository
769
+ 2. Create a feature branch (`git checkout -b feature/amazing-feature`)
770
+ 3. Make your changes
771
+ 4. Add tests if applicable
772
+ 5. Ensure all tests pass (`npm test`)
773
+ 6. Commit your changes (`git commit -m 'Add amazing feature'`)
774
+ 7. Push to the branch (`git push origin feature/amazing-feature`)
775
+ 8. Open a Pull Request
776
+
777
+ ### Development Setup
778
+
779
+ ```bash
780
+ # Clone repository
781
+ git clone <repository-url>
782
+ cd dynamic-form
783
+
784
+ # Install dependencies
785
+ npm install
786
+
787
+ # Run tests
788
+ npm test
789
+
790
+ # Build
791
+ npm run build
792
+
793
+ # Development mode
794
+ npm run dev
795
+ ```
796
+
797
+ ## License
798
+
799
+ MIT Β© Ambar Bidkar
800
+
801
+ ## Support
802
+
803
+ - πŸ“– [Documentation](./README.md)
804
+ - πŸ› [Report Bug](https://github.com/yourusername/dynamic-form/issues)
805
+ - πŸ’‘ [Request Feature](https://github.com/yourusername/dynamic-form/issues)
806
+ - πŸ“§ [Email Support](mailto:support@example.com)
807
+
808
+ ---
809
+
810
+ **Made with ❀️ for the React community**