@enerjisaformlibrary/formbuilder-react 1.0.8 → 1.0.9

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 (2) hide show
  1. package/README.md +1054 -17
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,6 +1,27 @@
1
1
  # @enerjisaformlibrary/formbuilder-react
2
2
 
3
- Standalone drag-and-drop form builder React component with CSS included. No additional dependencies required!
3
+ A comprehensive, standalone drag-and-drop form builder React component. All UI components, styles, and dependencies are bundled - only React is required as a peer dependency.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Installation](#installation)
8
+ - [Quick Start](#quick-start)
9
+ - [FormBuilder Props](#formbuilder-props)
10
+ - [Exported Components](#exported-components)
11
+ - [Form Schema Structure](#form-schema-structure)
12
+ - [Field Types](#field-types)
13
+ - [Validation Rules](#validation-rules)
14
+ - [Conditional Logic](#conditional-logic)
15
+ - [Multi-Step Forms](#multi-step-forms)
16
+ - [Container Fields](#container-fields)
17
+ - [Custom Styling](#custom-styling)
18
+ - [Events & Actions](#events--actions)
19
+ - [Zustand Store API](#zustand-store-api)
20
+ - [TypeScript Types](#typescript-types)
21
+ - [Complete JSON Example](#complete-json-example)
22
+ - [Extracting Form Values](#extracting-form-values)
23
+
24
+ ---
4
25
 
5
26
  ## Installation
6
27
 
@@ -8,7 +29,13 @@ Standalone drag-and-drop form builder React component with CSS included. No addi
8
29
  npm install @enerjisaformlibrary/formbuilder-react
9
30
  ```
10
31
 
11
- ## Usage
32
+ **Peer Dependencies:**
33
+ - `react`: ^18.0.0
34
+ - `react-dom`: ^18.0.0
35
+
36
+ ---
37
+
38
+ ## Quick Start
12
39
 
13
40
  ```tsx
14
41
  import { FormBuilder, useFormStore } from '@enerjisaformlibrary/formbuilder-react';
@@ -16,39 +43,1049 @@ import '@enerjisaformlibrary/formbuilder-react/styles.css';
16
43
 
17
44
  function App() {
18
45
  const handleChange = (form) => {
19
- console.log('Form changed:', form);
46
+ // Called on every form schema change
47
+ console.log('Form schema updated:', form);
20
48
  };
21
49
 
22
50
  const handleSave = (form) => {
23
51
  // Save form JSON to your database
24
- console.log('Save form:', JSON.stringify(form));
52
+ const jsonString = JSON.stringify(form, null, 2);
53
+ saveToDatabase(jsonString);
25
54
  };
26
55
 
27
56
  return (
28
- <div style={{ height: '100vh' }}>
57
+ <div style={{ height: '100vh', width: '100%' }}>
29
58
  <FormBuilder
30
59
  onChange={handleChange}
31
60
  onSave={handleSave}
32
61
  theme="light"
62
+ showToolbar={true}
63
+ showComponentLibrary={true}
64
+ showPropertiesPanel={true}
33
65
  />
34
66
  </div>
35
67
  );
36
68
  }
37
69
  ```
38
70
 
39
- ## Features
71
+ ### Loading Existing Form
72
+
73
+ ```tsx
74
+ import { FormBuilder } from '@enerjisaformlibrary/formbuilder-react';
75
+ import '@enerjisaformlibrary/formbuilder-react/styles.css';
76
+
77
+ function EditForm({ existingFormJson }) {
78
+ // Parse JSON string if needed
79
+ const initialForm = typeof existingFormJson === 'string'
80
+ ? JSON.parse(existingFormJson)
81
+ : existingFormJson;
82
+
83
+ return (
84
+ <FormBuilder
85
+ initialForm={initialForm}
86
+ onSave={(form) => updateInDatabase(form)}
87
+ />
88
+ );
89
+ }
90
+ ```
91
+
92
+ ---
93
+
94
+ ## FormBuilder Props
95
+
96
+ | Prop | Type | Default | Description |
97
+ |------|------|---------|-------------|
98
+ | `initialForm` | `FormSchema` | `undefined` | Pre-existing form schema to load |
99
+ | `onSave` | `(form: FormSchema) => void` | `undefined` | Callback when save button clicked |
100
+ | `onChange` | `(form: FormSchema) => void` | `undefined` | Callback on every form change |
101
+ | `className` | `string` | `''` | Additional CSS class for container |
102
+ | `theme` | `'light' \| 'dark'` | `'light'` | Color theme |
103
+ | `showToolbar` | `boolean` | `true` | Show/hide top toolbar |
104
+ | `showComponentLibrary` | `boolean` | `true` | Show/hide left component panel |
105
+ | `showPropertiesPanel` | `boolean` | `true` | Show/hide right properties panel |
106
+
107
+ ---
108
+
109
+ ## Exported Components
110
+
111
+ ```tsx
112
+ // Main wrapper component (recommended)
113
+ import { FormBuilder } from '@enerjisaformlibrary/formbuilder-react';
114
+
115
+ // Individual components for custom layouts
116
+ import {
117
+ FormCanvas, // Central form editing canvas
118
+ PropertiesPanel, // Right-side property editor
119
+ ComponentLibrary, // Left-side component palette
120
+ Toolbar, // Top toolbar with actions
121
+ CanvasField, // Individual field renderer
122
+ DragOverlayContent, // Drag preview overlay
123
+ JsonViewerModal, // JSON preview modal
124
+ } from '@enerjisaformlibrary/formbuilder-react';
125
+
126
+ // Zustand store for state management
127
+ import { useFormStore } from '@enerjisaformlibrary/formbuilder-react';
128
+
129
+ // All TypeScript types and schemas
130
+ import type {
131
+ FormSchema,
132
+ FormField,
133
+ FormRow,
134
+ FormColumn,
135
+ Step,
136
+ FieldProps,
137
+ Validation,
138
+ ConditionalLogic,
139
+ CustomStyle,
140
+ SubmissionConfig,
141
+ } from '@enerjisaformlibrary/formbuilder-react';
142
+ ```
143
+
144
+ ---
145
+
146
+ ## Form Schema Structure
147
+
148
+ The form is represented as a hierarchical JSON structure:
149
+
150
+ ```typescript
151
+ interface FormSchema {
152
+ id: string; // Unique form identifier
153
+ name: string; // Form display name
154
+ description?: string; // Optional description
155
+ rows: FormRow[]; // Array of rows (single-page mode)
156
+ steps?: Step[]; // Array of steps (multi-step mode)
157
+ isMultiStep?: boolean; // Enable multi-step wizard
158
+ submissionConfig?: SubmissionConfig; // Webhook/submission settings
159
+ settings?: FormSettings; // Global form settings
160
+ versions?: FormVersion[]; // Version history
161
+ currentVersion?: number; // Current version number
162
+ createdAt?: string; // ISO date string
163
+ updatedAt?: string; // ISO date string
164
+ }
165
+
166
+ interface FormRow {
167
+ id: string;
168
+ columns: FormColumn[]; // 12-column grid system
169
+ conditionalLogic?: ConditionalLogic; // Row-level conditions
170
+ fieldSize?: 'compact' | 'normal' | 'comfortable';
171
+ spacing?: number; // 0-16
172
+ padding?: number; // 0-16
173
+ }
174
+
175
+ interface FormColumn {
176
+ id: string;
177
+ width: number; // 1-12 (grid columns)
178
+ responsiveWidth?: ResponsiveWidth; // Mobile/tablet overrides
179
+ fields: FormField[]; // Fields in this column
180
+ }
181
+
182
+ interface FormField {
183
+ id: string; // Unique field identifier
184
+ type: string; // Field type (see Field Types)
185
+ props: FieldProps; // Field properties
186
+ validation?: Validation; // Validation rules
187
+ conditionalLogic?: ConditionalLogic; // Field conditions
188
+ customStyle?: CustomStyle; // CSS customization
189
+ localization?: Localization; // Multi-language support
190
+ computed?: ComputedField; // Calculated fields
191
+ responsiveWidth?: ResponsiveWidth; // Responsive breakpoints
192
+ events?: FieldEvents; // Event handlers
193
+ }
194
+ ```
195
+
196
+ ---
197
+
198
+ ## Field Types
199
+
200
+ ### Basic Input Fields
201
+
202
+ | Type | Description | Key Props |
203
+ |------|-------------|-----------|
204
+ | `input` | Single-line text input | `placeholder`, `maxLength` |
205
+ | `textarea` | Multi-line text area | `placeholder`, `rows` |
206
+ | `number` | Numeric input | `min`, `max`, `step` |
207
+ | `email` | Email input with validation | `placeholder` |
208
+ | `password` | Password input (masked) | `placeholder` |
209
+ | `phone` | Phone number input | `placeholder` |
210
+ | `url` | URL input with validation | `placeholder` |
211
+
212
+ ### Selection Fields
213
+
214
+ | Type | Description | Key Props |
215
+ |------|-------------|-----------|
216
+ | `dropdown` | Single select dropdown | `options`, `optionsString` |
217
+ | `checkbox` | Single checkbox | `defaultValue` |
218
+ | `radio` | Radio button group | `options`, `optionsString` |
219
+ | `toggle` | On/off toggle switch | `defaultValue` |
220
+ | `multiselect` | Multi-select with tags | `options`, `multiSelectConfig` |
221
+
222
+ ### Date & Time Fields
223
+
224
+ | Type | Description | Key Props |
225
+ |------|-------------|-----------|
226
+ | `date` | Date picker | `defaultValue` |
227
+ | `time` | Time picker | `timeConfig.format` |
228
+ | `daterange` | Date range picker | `dateRangeConfig` |
229
+
230
+ ### Advanced Fields
231
+
232
+ | Type | Description | Key Props |
233
+ |------|-------------|-----------|
234
+ | `file` | File upload with drag-drop | `fileConfig` |
235
+ | `signature` | Signature pad (canvas) | `signatureConfig` |
236
+ | `rating` | Star rating | `ratingConfig.maxRating` |
237
+ | `richtext` | Rich text editor | `richTextConfig` |
238
+ | `autocomplete` | Autocomplete input | `autocompleteConfig`, `options` |
239
+ | `slider` | Range slider | `min`, `max`, `step` |
240
+ | `pattern` | Input masking | `patternConfig.format` |
241
+ | `qrcode` | QR code display | `qrCodeConfig.value`, `qrCodeConfig.size` |
242
+ | `table` | Data table input | `tableConfig` |
243
+ | `color` | Color picker | `defaultValue` |
244
+
245
+ ### Static/Display Elements
246
+
247
+ | Type | Description | Key Props |
248
+ |------|-------------|-----------|
249
+ | `header` | H1 heading | `label` |
250
+ | `subheader` | H2/H3 heading | `label` |
251
+ | `label` | Text label | `label` |
252
+ | `paragraph` | Paragraph text | `label` |
253
+ | `divider` | Horizontal divider | `dividerMargin` |
254
+ | `spacer` | Vertical spacer | `spacerHeight` |
255
+ | `image` | Image display | `imageUrl`, `imageWidth`, `imageHeight` |
256
+ | `button` | Action button | `buttonConfig` |
257
+
258
+ ### Structure Elements
259
+
260
+ | Type | Description | Key Props |
261
+ |------|-------------|-----------|
262
+ | `container` | Grouping container | `containerConfig` |
263
+ | `row` | Grid row | - |
264
+
265
+ ---
266
+
267
+ ## Field Props (FieldProps)
268
+
269
+ ```typescript
270
+ interface FieldProps {
271
+ key: string; // Unique field key (for form values)
272
+ label: string; // Display label
273
+ placeholder?: string; // Input placeholder
274
+ value?: any; // Current value
275
+ defaultValue?: any; // Default value
276
+ helpText?: string; // Help text below field
277
+ tooltip?: string; // Tooltip on hover
278
+ size?: 'small' | 'medium' | 'large';
279
+ containerWidth?: 'auto' | '25' | '33' | '50' | '66' | '75' | '100';
280
+ disabled?: boolean; // Disable field
281
+ readOnly?: boolean; // Read-only mode
282
+ hidden?: boolean; // Hide field
283
+ autoFocus?: boolean; // Auto-focus on mount
284
+ tabIndex?: number; // Tab order
285
+ htmlAttributes?: Record<string, string>; // Custom HTML attributes
286
+
287
+ // Options for selection fields
288
+ options?: Array<{ label: string; value: string }>;
289
+ optionsString?: string[]; // Simple string array for options
290
+
291
+ // Field-specific configs
292
+ fileConfig?: FileUploadConfig;
293
+ ratingConfig?: RatingConfig;
294
+ autocompleteConfig?: AutocompleteConfig;
295
+ richTextConfig?: RichTextConfig;
296
+ dateRangeConfig?: DateRangeConfig;
297
+ timeConfig?: TimeConfig;
298
+ signatureConfig?: SignatureConfig;
299
+ multiSelectConfig?: MultiSelectConfig;
300
+ patternConfig?: PatternConfig;
301
+ buttonConfig?: ButtonConfig;
302
+ qrCodeConfig?: QRCodeConfig;
303
+ containerConfig?: ContainerConfig;
304
+ tableConfig?: TableConfig;
305
+
306
+ // Layout
307
+ spacerHeight?: number; // For spacer type
308
+ dividerMargin?: number; // For divider type
309
+ imageUrl?: string; // For image type
310
+ imageWidth?: string;
311
+ imageHeight?: string;
312
+ }
313
+ ```
314
+
315
+ ---
316
+
317
+ ## Validation Rules
318
+
319
+ ```typescript
320
+ interface Validation {
321
+ required?: boolean; // Field is required
322
+ minLength?: number; // Minimum text length
323
+ maxLength?: number; // Maximum text length
324
+ min?: number; // Minimum numeric value
325
+ max?: number; // Maximum numeric value
326
+ pattern?: string; // Regex pattern
327
+ errorMessage?: string; // Custom error message
328
+ customValidation?: string; // Custom validation code
329
+ validationType?: 'email' | 'url' | 'phone' | 'creditCard' | 'custom';
330
+ autoValidate?: boolean; // Validate automatically
331
+ validateOnBlur?: boolean; // Validate on blur
332
+ validateOnChange?: boolean; // Validate on change
333
+ }
334
+ ```
335
+
336
+ **Example:**
337
+ ```json
338
+ {
339
+ "validation": {
340
+ "required": true,
341
+ "minLength": 3,
342
+ "maxLength": 100,
343
+ "pattern": "^[a-zA-Z]+$",
344
+ "errorMessage": "Only letters allowed, 3-100 characters"
345
+ }
346
+ }
347
+ ```
348
+
349
+ ---
350
+
351
+ ## Conditional Logic
352
+
353
+ Show, hide, enable, disable, or require fields based on other field values:
354
+
355
+ ```typescript
356
+ interface ConditionalLogic {
357
+ enabled: boolean; // Enable/disable conditional logic
358
+ action: 'show' | 'hide' | 'enable' | 'disable' | 'require';
359
+ logicType: 'all' | 'any'; // Match all or any condition
360
+ conditions: Condition[];
361
+ }
362
+
363
+ interface Condition {
364
+ fieldKey: string; // Key of field to check
365
+ operator: ConditionOperator; // Comparison operator
366
+ value?: any; // Value to compare against
367
+ }
368
+
369
+ type ConditionOperator =
370
+ | 'equals'
371
+ | 'notEquals'
372
+ | 'contains'
373
+ | 'notContains'
374
+ | 'greaterThan'
375
+ | 'lessThan'
376
+ | 'greaterThanOrEqual'
377
+ | 'lessThanOrEqual'
378
+ | 'isEmpty'
379
+ | 'isNotEmpty'
380
+ | 'startsWith'
381
+ | 'endsWith';
382
+ ```
383
+
384
+ **Example: Show field when another field equals "yes":**
385
+ ```json
386
+ {
387
+ "conditionalLogic": {
388
+ "enabled": true,
389
+ "action": "show",
390
+ "logicType": "all",
391
+ "conditions": [
392
+ {
393
+ "fieldKey": "has_experience",
394
+ "operator": "equals",
395
+ "value": "yes"
396
+ }
397
+ ]
398
+ }
399
+ }
400
+ ```
401
+
402
+ ---
403
+
404
+ ## Multi-Step Forms
405
+
406
+ Enable wizard-style forms with multiple steps:
407
+
408
+ ```typescript
409
+ interface Step {
410
+ id: string;
411
+ title: string; // Step title
412
+ description?: string; // Step description
413
+ icon?: string; // Lucide icon name
414
+ rows: FormRow[]; // Rows in this step
415
+ validation?: {
416
+ validateOnNext?: boolean; // Validate before next step
417
+ allowSkip?: boolean; // Allow skipping this step
418
+ };
419
+ }
420
+ ```
421
+
422
+ **Example Multi-Step Form:**
423
+ ```json
424
+ {
425
+ "id": "registration-form",
426
+ "name": "User Registration",
427
+ "isMultiStep": true,
428
+ "steps": [
429
+ {
430
+ "id": "step-1",
431
+ "title": "Personal Info",
432
+ "description": "Enter your personal details",
433
+ "rows": [...]
434
+ },
435
+ {
436
+ "id": "step-2",
437
+ "title": "Contact",
438
+ "description": "How can we reach you?",
439
+ "rows": [...]
440
+ },
441
+ {
442
+ "id": "step-3",
443
+ "title": "Preferences",
444
+ "validation": { "allowSkip": true },
445
+ "rows": [...]
446
+ }
447
+ ],
448
+ "rows": []
449
+ }
450
+ ```
451
+
452
+ ---
453
+
454
+ ## Container Fields
455
+
456
+ Containers allow nested layouts with their own grid system:
457
+
458
+ ```typescript
459
+ interface ContainerConfig {
460
+ direction?: 'row' | 'column';
461
+ gap?: number; // Gap between items
462
+ padding?: number; // Internal padding
463
+ background?: string; // Background color
464
+ border?: boolean; // Show border
465
+ flexWrap?: 'wrap' | 'nowrap';
466
+ justifyContent?: 'flex-start' | 'flex-end' | 'center' | 'space-between' | 'space-around' | 'space-evenly';
467
+ alignItems?: 'flex-start' | 'flex-end' | 'center' | 'stretch' | 'baseline';
468
+ fieldSize?: 'compact' | 'normal' | 'comfortable';
469
+ rows?: ContainerRow[]; // Nested rows structure
470
+ }
471
+
472
+ interface ContainerRow {
473
+ id: string;
474
+ width: number; // 1-12 grid width
475
+ height?: number; // 40-500 pixels or auto
476
+ columns: ContainerColumn[];
477
+ }
478
+
479
+ interface ContainerColumn {
480
+ id: string;
481
+ width: number; // 1-12 grid width
482
+ fieldId?: string; // ID of field in this column
483
+ fields?: FormField[]; // Fields in this column
484
+ }
485
+ ```
486
+
487
+ ---
488
+
489
+ ## Custom Styling
490
+
491
+ Per-field CSS customization:
492
+
493
+ ```typescript
494
+ interface CustomStyle {
495
+ className?: string; // Additional CSS class
496
+ labelClassName?: string; // CSS class for label
497
+ inputClassName?: string; // CSS class for input
498
+ containerClassName?: string; // CSS class for container
499
+ css?: string; // Custom inline CSS
500
+ wrapperCss?: string; // Wrapper element CSS
501
+ deviceTarget?: 'any' | 'mobile' | 'tablet' | 'desktop';
502
+ width?: { value?: number; unit?: string };
503
+ height?: string;
504
+ marginTop?: string;
505
+ marginRight?: string;
506
+ marginBottom?: string;
507
+ marginLeft?: string;
508
+ color?: string;
509
+ backgroundColor?: string;
510
+ }
511
+ ```
512
+
513
+ **Example:**
514
+ ```json
515
+ {
516
+ "customStyle": {
517
+ "containerClassName": "my-field-wrapper",
518
+ "labelClassName": "text-lg font-bold",
519
+ "inputClassName": "border-2 border-blue-500",
520
+ "backgroundColor": "#f0f0f0"
521
+ }
522
+ }
523
+ ```
524
+
525
+ ---
526
+
527
+ ## Events & Actions
528
+
529
+ Define event handlers for field interactions:
530
+
531
+ ```typescript
532
+ interface FieldEvents {
533
+ onClick?: EventAction[];
534
+ onChange?: EventAction[];
535
+ onFocus?: EventAction[];
536
+ onBlur?: EventAction[];
537
+ onMount?: EventAction[];
538
+ onUnmount?: EventAction[];
539
+ }
540
+
541
+ interface EventAction {
542
+ type: 'common' | 'code' | 'custom';
543
+ name: string; // Action name
544
+ code?: string; // JavaScript code (for code type)
545
+ args?: Record<string, any>; // Action arguments
546
+ }
547
+ ```
548
+
549
+ ---
550
+
551
+ ## Submission Config
552
+
553
+ Configure form submission behavior:
554
+
555
+ ```typescript
556
+ interface SubmissionConfig {
557
+ enabled: boolean;
558
+ webhookUrl?: string; // Webhook endpoint
559
+ webhookMethod?: 'POST' | 'PUT' | 'PATCH';
560
+ webhookHeaders?: Record<string, string>;
561
+ emailNotification?: {
562
+ enabled?: boolean;
563
+ to?: string[];
564
+ subject?: string;
565
+ template?: string;
566
+ };
567
+ apiEndpoint?: {
568
+ url?: string;
569
+ method?: 'POST' | 'PUT' | 'PATCH';
570
+ headers?: Record<string, string>;
571
+ };
572
+ redirectUrl?: string; // Redirect after submit
573
+ successMessage?: string; // Success message
574
+ errorMessage?: string; // Error message
575
+ }
576
+ ```
577
+
578
+ ---
579
+
580
+ ## Zustand Store API
581
+
582
+ Access and manipulate form state programmatically:
583
+
584
+ ```tsx
585
+ import { useFormStore } from '@enerjisaformlibrary/formbuilder-react';
586
+
587
+ function MyComponent() {
588
+ const {
589
+ // State
590
+ form, // Current FormSchema
591
+ selection, // Selected element
592
+ previewMode, // Preview mode state
593
+ formValues, // Form values (in preview)
594
+
595
+ // Form Actions
596
+ loadForm, // Load form schema
597
+ setFormName, // Set form name
598
+ resetForm, // Reset to empty form
599
+
600
+ // Row Actions
601
+ addRow, // Add empty row
602
+ addRowWithField, // Add row with a field
603
+ updateRow, // Update row properties
604
+ deleteRow, // Delete row
605
+ moveRow, // Move/reorder row
606
+
607
+ // Column Actions
608
+ addColumn, // Add column to row
609
+ updateColumn, // Update column properties
610
+ deleteColumn, // Delete column
611
+
612
+ // Field Actions
613
+ addField, // Add field to column
614
+ updateField, // Update field properties
615
+ deleteField, // Delete field
616
+ moveField, // Move field between columns
617
+
618
+ // Container Actions
619
+ addFieldToContainer, // Add field to container column
620
+ addFieldToContainerDirect, // Add field to container
621
+
622
+ // Selection
623
+ setSelection, // Set selected element
624
+ clearSelection, // Clear selection
625
+
626
+ // Preview
627
+ setPreviewMode, // Toggle preview mode
628
+ setFormValue, // Set field value in preview
629
+
630
+ // Multi-step
631
+ addStep, // Add wizard step
632
+ updateStep, // Update step
633
+ deleteStep, // Delete step
634
+ moveStep, // Reorder step
635
+ setCurrentStep, // Navigate to step
636
+
637
+ // Version Control
638
+ saveVersion, // Save form version
639
+ restoreVersion, // Restore previous version
640
+
641
+ // Undo/Redo
642
+ undo, // Undo last action
643
+ redo, // Redo undone action
644
+ canUndo, // Check if undo available
645
+ canRedo, // Check if redo available
646
+
647
+ } = useFormStore();
648
+
649
+ // Example: Get current form JSON
650
+ const formJson = JSON.stringify(form, null, 2);
651
+
652
+ // Example: Load existing form
653
+ useEffect(() => {
654
+ loadForm(existingFormData);
655
+ }, []);
656
+ }
657
+ ```
658
+
659
+ ---
660
+
661
+ ## TypeScript Types
662
+
663
+ All types are exported for TypeScript usage:
664
+
665
+ ```typescript
666
+ import type {
667
+ // Core Types
668
+ FormSchema,
669
+ FormField,
670
+ FormRow,
671
+ FormColumn,
672
+ Step,
673
+
674
+ // Field Configuration
675
+ FieldProps,
676
+ Validation,
677
+ ConditionalLogic,
678
+ Condition,
679
+ ConditionOperator,
680
+ CustomStyle,
681
+ ResponsiveWidth,
682
+ FieldEvents,
683
+ EventAction,
684
+
685
+ // Field-Specific Configs
686
+ FileUploadConfig,
687
+ RatingConfig,
688
+ AutocompleteConfig,
689
+ SignatureConfig,
690
+ PatternConfig,
691
+ ButtonConfig,
692
+ QRCodeConfig,
693
+ ContainerConfig,
694
+ TableConfig,
695
+
696
+ // Form Settings
697
+ FormSettings,
698
+ SubmissionConfig,
699
+ FormVersion,
700
+ Localization,
701
+ ComputedField,
702
+
703
+ // Selection
704
+ Selection,
705
+ SelectionType,
706
+
707
+ // Field Type Constants
708
+ FieldType,
709
+ StructureType,
710
+ StaticType,
711
+ } from '@enerjisaformlibrary/formbuilder-react';
712
+ ```
713
+
714
+ ---
715
+
716
+ ## Complete JSON Example
717
+
718
+ Here's a complete form with various field types:
719
+
720
+ ```json
721
+ {
722
+ "id": "contact-form-001",
723
+ "name": "Contact Form",
724
+ "description": "A sample contact form",
725
+ "isMultiStep": false,
726
+ "rows": [
727
+ {
728
+ "id": "row-1",
729
+ "columns": [
730
+ {
731
+ "id": "col-1",
732
+ "width": 6,
733
+ "fields": [
734
+ {
735
+ "id": "field-1",
736
+ "type": "input",
737
+ "props": {
738
+ "key": "first_name",
739
+ "label": "First Name",
740
+ "placeholder": "Enter your first name"
741
+ },
742
+ "validation": {
743
+ "required": true,
744
+ "minLength": 2
745
+ }
746
+ }
747
+ ]
748
+ },
749
+ {
750
+ "id": "col-2",
751
+ "width": 6,
752
+ "fields": [
753
+ {
754
+ "id": "field-2",
755
+ "type": "input",
756
+ "props": {
757
+ "key": "last_name",
758
+ "label": "Last Name",
759
+ "placeholder": "Enter your last name"
760
+ },
761
+ "validation": {
762
+ "required": true
763
+ }
764
+ }
765
+ ]
766
+ }
767
+ ]
768
+ },
769
+ {
770
+ "id": "row-2",
771
+ "columns": [
772
+ {
773
+ "id": "col-3",
774
+ "width": 12,
775
+ "fields": [
776
+ {
777
+ "id": "field-3",
778
+ "type": "email",
779
+ "props": {
780
+ "key": "email",
781
+ "label": "Email Address",
782
+ "placeholder": "you@example.com"
783
+ },
784
+ "validation": {
785
+ "required": true,
786
+ "validationType": "email"
787
+ }
788
+ }
789
+ ]
790
+ }
791
+ ]
792
+ },
793
+ {
794
+ "id": "row-3",
795
+ "columns": [
796
+ {
797
+ "id": "col-4",
798
+ "width": 12,
799
+ "fields": [
800
+ {
801
+ "id": "field-4",
802
+ "type": "dropdown",
803
+ "props": {
804
+ "key": "inquiry_type",
805
+ "label": "Inquiry Type",
806
+ "options": [
807
+ { "label": "General Question", "value": "general" },
808
+ { "label": "Technical Support", "value": "support" },
809
+ { "label": "Sales", "value": "sales" },
810
+ { "label": "Other", "value": "other" }
811
+ ]
812
+ },
813
+ "validation": {
814
+ "required": true
815
+ }
816
+ }
817
+ ]
818
+ }
819
+ ]
820
+ },
821
+ {
822
+ "id": "row-4",
823
+ "columns": [
824
+ {
825
+ "id": "col-5",
826
+ "width": 12,
827
+ "fields": [
828
+ {
829
+ "id": "field-5",
830
+ "type": "textarea",
831
+ "props": {
832
+ "key": "message",
833
+ "label": "Message",
834
+ "placeholder": "Type your message here..."
835
+ },
836
+ "validation": {
837
+ "required": true,
838
+ "minLength": 10,
839
+ "maxLength": 1000
840
+ },
841
+ "conditionalLogic": {
842
+ "enabled": true,
843
+ "action": "show",
844
+ "logicType": "all",
845
+ "conditions": [
846
+ {
847
+ "fieldKey": "inquiry_type",
848
+ "operator": "isNotEmpty"
849
+ }
850
+ ]
851
+ }
852
+ }
853
+ ]
854
+ }
855
+ ]
856
+ },
857
+ {
858
+ "id": "row-5",
859
+ "columns": [
860
+ {
861
+ "id": "col-6",
862
+ "width": 12,
863
+ "fields": [
864
+ {
865
+ "id": "field-6",
866
+ "type": "checkbox",
867
+ "props": {
868
+ "key": "agree_terms",
869
+ "label": "I agree to the terms and conditions"
870
+ },
871
+ "validation": {
872
+ "required": true,
873
+ "errorMessage": "You must agree to continue"
874
+ }
875
+ }
876
+ ]
877
+ }
878
+ ]
879
+ },
880
+ {
881
+ "id": "row-6",
882
+ "columns": [
883
+ {
884
+ "id": "col-7",
885
+ "width": 12,
886
+ "fields": [
887
+ {
888
+ "id": "field-7",
889
+ "type": "button",
890
+ "props": {
891
+ "key": "submit_btn",
892
+ "label": "Submit",
893
+ "buttonConfig": {
894
+ "action": "submit",
895
+ "variant": "default"
896
+ }
897
+ }
898
+ }
899
+ ]
900
+ }
901
+ ]
902
+ }
903
+ ],
904
+ "submissionConfig": {
905
+ "enabled": true,
906
+ "webhookUrl": "https://api.example.com/forms/submit",
907
+ "webhookMethod": "POST",
908
+ "successMessage": "Thank you! Your message has been sent.",
909
+ "redirectUrl": "/thank-you"
910
+ },
911
+ "settings": {
912
+ "defaultLanguage": "en",
913
+ "layout": {
914
+ "labelPosition": "top",
915
+ "spacing": "normal"
916
+ }
917
+ }
918
+ }
919
+ ```
920
+
921
+ ---
922
+
923
+ ## Extracting Form Values
924
+
925
+ When rendering this form to end users, you'll need to:
926
+
927
+ 1. **Parse the JSON** to get field structure
928
+ 2. **Render fields** based on their `type`
929
+ 3. **Collect values** using field `props.key` as the key
930
+ 4. **Apply validation** from `validation` object
931
+ 5. **Handle conditional logic** to show/hide fields
932
+
933
+ **Expected form values output:**
934
+ ```json
935
+ {
936
+ "first_name": "John",
937
+ "last_name": "Doe",
938
+ "email": "john@example.com",
939
+ "inquiry_type": "support",
940
+ "message": "I need help with...",
941
+ "agree_terms": true
942
+ }
943
+ ```
944
+
945
+ **Iterating through fields:**
946
+ ```typescript
947
+ function extractFieldsFromForm(form: FormSchema): FormField[] {
948
+ const fields: FormField[] = [];
949
+
950
+ const processRows = (rows: FormRow[]) => {
951
+ for (const row of rows) {
952
+ for (const column of row.columns) {
953
+ for (const field of column.fields) {
954
+ fields.push(field);
955
+
956
+ // Handle container fields (nested)
957
+ if (field.type === 'container' && field.props.containerConfig?.rows) {
958
+ for (const containerRow of field.props.containerConfig.rows) {
959
+ for (const containerCol of containerRow.columns) {
960
+ if (containerCol.fields) {
961
+ fields.push(...containerCol.fields);
962
+ }
963
+ }
964
+ }
965
+ }
966
+ }
967
+ }
968
+ }
969
+ };
970
+
971
+ if (form.isMultiStep && form.steps) {
972
+ for (const step of form.steps) {
973
+ processRows(step.rows);
974
+ }
975
+ } else {
976
+ processRows(form.rows);
977
+ }
978
+
979
+ return fields;
980
+ }
981
+
982
+ // Get field keys for form values
983
+ const fields = extractFieldsFromForm(formSchema);
984
+ const fieldKeys = fields
985
+ .filter(f => !['header', 'subheader', 'label', 'paragraph', 'divider', 'spacer', 'image', 'button'].includes(f.type))
986
+ .map(f => f.props.key);
987
+ ```
988
+
989
+ ---
990
+
991
+ ## Responsive Width
992
+
993
+ Fields support responsive grid widths:
994
+
995
+ ```typescript
996
+ interface ResponsiveWidth {
997
+ mobile?: number; // 1-12 columns on mobile
998
+ tablet?: number; // 1-12 columns on tablet
999
+ desktop?: number; // 1-12 columns on desktop
1000
+ }
1001
+ ```
1002
+
1003
+ **Example:**
1004
+ ```json
1005
+ {
1006
+ "responsiveWidth": {
1007
+ "mobile": 12,
1008
+ "tablet": 6,
1009
+ "desktop": 4
1010
+ }
1011
+ }
1012
+ ```
1013
+
1014
+ ---
1015
+
1016
+ ## Version History
1017
+
1018
+ The form supports versioning:
1019
+
1020
+ ```typescript
1021
+ interface FormVersion {
1022
+ id: string;
1023
+ version: number;
1024
+ createdAt: string; // ISO date
1025
+ createdBy?: string; // User identifier
1026
+ changelog?: string; // Description of changes
1027
+ snapshot: FormSchema; // Complete form state
1028
+ }
1029
+ ```
1030
+
1031
+ ---
1032
+
1033
+ ## Localization
1034
+
1035
+ Multi-language support per field:
1036
+
1037
+ ```typescript
1038
+ interface Localization {
1039
+ translations?: Record<string, {
1040
+ label?: string;
1041
+ placeholder?: string;
1042
+ helpText?: string;
1043
+ errorMessages?: Record<string, string>;
1044
+ }>;
1045
+ }
1046
+ ```
1047
+
1048
+ **Example:**
1049
+ ```json
1050
+ {
1051
+ "localization": {
1052
+ "translations": {
1053
+ "tr": {
1054
+ "label": "Ad",
1055
+ "placeholder": "Adınızı girin"
1056
+ },
1057
+ "de": {
1058
+ "label": "Vorname",
1059
+ "placeholder": "Geben Sie Ihren Vornamen ein"
1060
+ }
1061
+ }
1062
+ }
1063
+ }
1064
+ ```
1065
+
1066
+ ---
1067
+
1068
+ ## Supported Languages
1069
+
1070
+ ```typescript
1071
+ const SUPPORTED_LANGUAGES = [
1072
+ { code: 'en', name: 'English' },
1073
+ { code: 'tr', name: 'Turkish' },
1074
+ { code: 'de', name: 'German' },
1075
+ { code: 'fr', name: 'French' },
1076
+ { code: 'es', name: 'Spanish' },
1077
+ { code: 'pt', name: 'Portuguese' },
1078
+ { code: 'it', name: 'Italian' },
1079
+ { code: 'nl', name: 'Dutch' },
1080
+ { code: 'ru', name: 'Russian' },
1081
+ { code: 'zh', name: 'Chinese' },
1082
+ { code: 'ja', name: 'Japanese' },
1083
+ { code: 'ko', name: 'Korean' },
1084
+ { code: 'ar', name: 'Arabic' },
1085
+ ];
1086
+ ```
40
1087
 
41
- - 20+ field types (input, textarea, dropdown, checkbox, radio, date, file, signature, rating, etc.)
42
- - Drag-and-drop interface
43
- - Multi-step wizard forms
44
- - Conditional logic (show/hide/enable/disable fields)
45
- - Custom styling per field
46
- - Form versioning
47
- - JSON export/import
48
- - Responsive grid system (12-column)
49
- - Dark/Light theme support
50
- - **Container support**: Drop fields into containers with multiple columns
51
- - **Column support**: Drop fields into existing columns
1088
+ ---
52
1089
 
53
1090
  ## License
54
1091
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@enerjisaformlibrary/formbuilder-react",
3
- "version": "1.0.8",
3
+ "version": "1.0.9",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "Standalone drag-and-drop form builder React component with CSS included. 20+ field types, conditional logic, multi-step forms.",