@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.
- package/README.md +1054 -17
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,27 @@
|
|
|
1
1
|
# @enerjisaformlibrary/formbuilder-react
|
|
2
2
|
|
|
3
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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.",
|