@dmitryvim/form-builder 0.2.9 → 0.2.11
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 +104 -40
- package/dist/browser/formbuilder.min.js +51 -51
- package/dist/browser/formbuilder.v0.2.11.min.js +322 -0
- package/dist/cjs/index.cjs +542 -138
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/esm/index.js +534 -134
- package/dist/esm/index.js.map +1 -1
- package/dist/form-builder.js +51 -51
- package/dist/types/instance/FormBuilderInstance.d.ts +5 -1
- package/dist/types/types/index.d.ts +1 -1
- package/dist/types/types/schema.d.ts +6 -3
- package/dist/types/utils/enable-conditions.d.ts +18 -0
- package/package.json +1 -1
- package/dist/browser/formbuilder.v0.2.9.min.js +0 -322
- package/dist/types/utils/display-conditions.d.ts +0 -17
package/README.md
CHANGED
|
@@ -42,7 +42,7 @@ This package ships with complete TypeScript definitions. Ensure your `tsconfig.j
|
|
|
42
42
|
```json
|
|
43
43
|
{
|
|
44
44
|
"compilerOptions": {
|
|
45
|
-
"moduleResolution": "NodeNext",
|
|
45
|
+
"moduleResolution": "NodeNext", // or "Bundler" for Vite/Webpack
|
|
46
46
|
"esModuleInterop": true,
|
|
47
47
|
"skipLibCheck": false
|
|
48
48
|
}
|
|
@@ -77,6 +77,33 @@ This package ships with complete TypeScript definitions. Ensure your `tsconfig.j
|
|
|
77
77
|
|
|
78
78
|
## Quick Examples
|
|
79
79
|
|
|
80
|
+
### Root-Level Properties (v0.2.9+)
|
|
81
|
+
|
|
82
|
+
The root schema now supports container-like properties:
|
|
83
|
+
|
|
84
|
+
- **`columns`** - Grid layout for root-level fields (1-4 columns)
|
|
85
|
+
- **`prefillHints`** - Quick-fill templates for entire form
|
|
86
|
+
|
|
87
|
+
**Example:**
|
|
88
|
+
|
|
89
|
+
```json
|
|
90
|
+
{
|
|
91
|
+
"version": "0.3",
|
|
92
|
+
"title": "Contact Form",
|
|
93
|
+
"columns": 2,
|
|
94
|
+
"prefillHints": [
|
|
95
|
+
{"label": "Work", "values": {"email": "work@company.com"}, "icon": "💼"},
|
|
96
|
+
{"label": "Personal", "values": {"email": "personal@email.com"}, "icon": "🏠"}
|
|
97
|
+
],
|
|
98
|
+
"elements": [
|
|
99
|
+
{"type": "text", "key": "name", "label": "Name"},
|
|
100
|
+
{"type": "text", "key": "email", "label": "Email"}
|
|
101
|
+
]
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
See [CLAUDE.md](CLAUDE.md) for complete documentation.
|
|
106
|
+
|
|
80
107
|
### Simple Contact Form
|
|
81
108
|
|
|
82
109
|
```json
|
|
@@ -178,7 +205,7 @@ const formBuilder = createFormBuilder({
|
|
|
178
205
|
},
|
|
179
206
|
downloadFile: (resourceId, fileName) => {
|
|
180
207
|
// Handle file download
|
|
181
|
-
window.open(`/api/files/${resourceId}`,
|
|
208
|
+
window.open(`/api/files/${resourceId}`, "_blank");
|
|
182
209
|
},
|
|
183
210
|
getThumbnail: async (resourceId) => {
|
|
184
211
|
// v0.2.0: Async-only thumbnail loading
|
|
@@ -196,9 +223,9 @@ const formBuilder = createFormBuilder({
|
|
|
196
223
|
},
|
|
197
224
|
// v0.2.0: CSS theming
|
|
198
225
|
theme: {
|
|
199
|
-
primaryColor:
|
|
200
|
-
borderRadius:
|
|
201
|
-
}
|
|
226
|
+
primaryColor: "#0066cc",
|
|
227
|
+
borderRadius: "4px",
|
|
228
|
+
},
|
|
202
229
|
});
|
|
203
230
|
|
|
204
231
|
// Render form
|
|
@@ -212,8 +239,8 @@ if (result.valid) {
|
|
|
212
239
|
}
|
|
213
240
|
|
|
214
241
|
// v0.2.0: Update fields without re-rendering
|
|
215
|
-
formBuilder.updateField(
|
|
216
|
-
formBuilder.setFormData({ name:
|
|
242
|
+
formBuilder.updateField("email", "newemail@example.com");
|
|
243
|
+
formBuilder.setFormData({ name: "John", email: "john@example.com" });
|
|
217
244
|
```
|
|
218
245
|
|
|
219
246
|
### 2. CDN Integration
|
|
@@ -226,7 +253,9 @@ formBuilder.setFormData({ name: 'John', email: 'john@example.com' });
|
|
|
226
253
|
|
|
227
254
|
const formBuilder = createFormBuilder({
|
|
228
255
|
uploadFile: async (file) => "resource-id",
|
|
229
|
-
downloadFile: (resourceId) => {
|
|
256
|
+
downloadFile: (resourceId) => {
|
|
257
|
+
/* download */
|
|
258
|
+
},
|
|
230
259
|
});
|
|
231
260
|
|
|
232
261
|
const rootElement = document.getElementById("form-container");
|
|
@@ -343,6 +372,7 @@ form.destroy();
|
|
|
343
372
|
**Breaking Changes in v0.2.0:**
|
|
344
373
|
|
|
345
374
|
1. **Instance-Only API** - Global static methods removed
|
|
375
|
+
|
|
346
376
|
```typescript
|
|
347
377
|
// OLD (v0.1.x)
|
|
348
378
|
FormBuilder.configure({ uploadFile: async (file) => "id" });
|
|
@@ -354,12 +384,13 @@ form.renderForm(root, schema);
|
|
|
354
384
|
```
|
|
355
385
|
|
|
356
386
|
2. **Async getThumbnail** - Must return Promise
|
|
387
|
+
|
|
357
388
|
```typescript
|
|
358
389
|
// OLD (v0.1.x)
|
|
359
|
-
getThumbnail: (resourceId) => `/thumbs/${resourceId}.jpg
|
|
390
|
+
getThumbnail: (resourceId) => `/thumbs/${resourceId}.jpg`;
|
|
360
391
|
|
|
361
392
|
// NEW (v0.2.0)
|
|
362
|
-
getThumbnail: async (resourceId) => `/thumbs/${resourceId}.jpg
|
|
393
|
+
getThumbnail: async (resourceId) => `/thumbs/${resourceId}.jpg`;
|
|
363
394
|
```
|
|
364
395
|
|
|
365
396
|
See [CHANGELOG.md](CHANGELOG.md) for complete migration details.
|
|
@@ -372,26 +403,27 @@ Customize appearance with 43 theme properties:
|
|
|
372
403
|
const form = createFormBuilder({
|
|
373
404
|
theme: {
|
|
374
405
|
// Colors
|
|
375
|
-
primaryColor:
|
|
376
|
-
borderColor:
|
|
377
|
-
errorColor:
|
|
406
|
+
primaryColor: "#0066cc",
|
|
407
|
+
borderColor: "#e0e0e0",
|
|
408
|
+
errorColor: "#d32f2f",
|
|
378
409
|
|
|
379
410
|
// Typography
|
|
380
|
-
fontSize:
|
|
411
|
+
fontSize: "16px",
|
|
381
412
|
fontFamily: '"Roboto", sans-serif',
|
|
382
413
|
|
|
383
414
|
// Spacing
|
|
384
|
-
borderRadius:
|
|
385
|
-
inputPaddingX:
|
|
415
|
+
borderRadius: "4px",
|
|
416
|
+
inputPaddingX: "12px",
|
|
386
417
|
|
|
387
418
|
// Buttons
|
|
388
|
-
buttonBgColor:
|
|
389
|
-
buttonTextColor:
|
|
390
|
-
}
|
|
419
|
+
buttonBgColor: "#0066cc",
|
|
420
|
+
buttonTextColor: "#ffffff",
|
|
421
|
+
},
|
|
391
422
|
});
|
|
392
423
|
```
|
|
393
424
|
|
|
394
425
|
**Most Common Properties:**
|
|
426
|
+
|
|
395
427
|
- `primaryColor` - Primary brand color
|
|
396
428
|
- `borderRadius` - Border radius for inputs/buttons
|
|
397
429
|
- `fontSize` - Base font size
|
|
@@ -409,10 +441,10 @@ const form = createFormBuilder({
|
|
|
409
441
|
// Required: Upload handler
|
|
410
442
|
uploadFile: async (file) => {
|
|
411
443
|
const formData = new FormData();
|
|
412
|
-
formData.append(
|
|
413
|
-
const response = await fetch(
|
|
414
|
-
method:
|
|
415
|
-
body: formData
|
|
444
|
+
formData.append("file", file);
|
|
445
|
+
const response = await fetch("/api/upload", {
|
|
446
|
+
method: "POST",
|
|
447
|
+
body: formData,
|
|
416
448
|
});
|
|
417
449
|
const data = await response.json();
|
|
418
450
|
return data.resourceId; // Return unique resource ID
|
|
@@ -421,14 +453,14 @@ const form = createFormBuilder({
|
|
|
421
453
|
// Required: Download handler
|
|
422
454
|
downloadFile: (resourceId, fileName) => {
|
|
423
455
|
// Option 1: Direct download
|
|
424
|
-
window.open(`/api/files/${resourceId}/download`,
|
|
456
|
+
window.open(`/api/files/${resourceId}/download`, "_blank");
|
|
425
457
|
|
|
426
458
|
// Option 2: Programmatic download
|
|
427
459
|
fetch(`/api/files/${resourceId}/download`)
|
|
428
|
-
.then(response => response.blob())
|
|
429
|
-
.then(blob => {
|
|
460
|
+
.then((response) => response.blob())
|
|
461
|
+
.then((blob) => {
|
|
430
462
|
const url = URL.createObjectURL(blob);
|
|
431
|
-
const a = document.createElement(
|
|
463
|
+
const a = document.createElement("a");
|
|
432
464
|
a.href = url;
|
|
433
465
|
a.download = fileName;
|
|
434
466
|
a.click();
|
|
@@ -446,7 +478,7 @@ const form = createFormBuilder({
|
|
|
446
478
|
// Optional: Full file download URL (used instead of getThumbnail for downloads)
|
|
447
479
|
getDownloadUrl: (resourceId) => {
|
|
448
480
|
return `/api/files/${resourceId}/download`;
|
|
449
|
-
}
|
|
481
|
+
},
|
|
450
482
|
});
|
|
451
483
|
```
|
|
452
484
|
|
|
@@ -470,17 +502,25 @@ When a user clicks the download button in readonly mode, the form builder uses t
|
|
|
470
502
|
|
|
471
503
|
### Conditional Field Visibility
|
|
472
504
|
|
|
473
|
-
Show or hide fields based on form data values using the `
|
|
505
|
+
Show or hide fields based on form data values using the `enableIf` property:
|
|
474
506
|
|
|
475
507
|
```typescript
|
|
476
|
-
interface
|
|
477
|
-
key: string;
|
|
478
|
-
equals?: any;
|
|
508
|
+
interface EnableCondition {
|
|
509
|
+
key: string; // Field key to check (supports nested paths)
|
|
510
|
+
equals?: any; // Value to compare (initial operator)
|
|
511
|
+
scope?: "relative" | "absolute"; // v0.2.9: Evaluation context (default: "relative")
|
|
479
512
|
// Future: notEquals, in, exists, greaterThan, lessThan, and/or
|
|
480
513
|
}
|
|
481
514
|
```
|
|
482
515
|
|
|
516
|
+
**Scope Behavior (v0.2.9+):**
|
|
517
|
+
|
|
518
|
+
- **`scope: "relative"`** (default): Checks fields within current container
|
|
519
|
+
- **`scope: "absolute"`**: Checks fields in root-level form data
|
|
520
|
+
- Use absolute scope when referencing root-level fields from inside containers
|
|
521
|
+
|
|
483
522
|
**Simple Condition:**
|
|
523
|
+
|
|
484
524
|
```json
|
|
485
525
|
{
|
|
486
526
|
"type": "select",
|
|
@@ -495,7 +535,7 @@ interface DisplayCondition {
|
|
|
495
535
|
"type": "text",
|
|
496
536
|
"key": "background_image",
|
|
497
537
|
"label": "Background Image URL",
|
|
498
|
-
"
|
|
538
|
+
"enableIf": {
|
|
499
539
|
"key": "background_mode",
|
|
500
540
|
"equals": "use_image"
|
|
501
541
|
}
|
|
@@ -503,12 +543,13 @@ interface DisplayCondition {
|
|
|
503
543
|
```
|
|
504
544
|
|
|
505
545
|
**Nested Path:**
|
|
546
|
+
|
|
506
547
|
```json
|
|
507
548
|
{
|
|
508
549
|
"type": "text",
|
|
509
550
|
"key": "city_details",
|
|
510
551
|
"label": "City-Specific Information",
|
|
511
|
-
"
|
|
552
|
+
"enableIf": {
|
|
512
553
|
"key": "address.city",
|
|
513
554
|
"equals": "New York"
|
|
514
555
|
}
|
|
@@ -516,25 +557,48 @@ interface DisplayCondition {
|
|
|
516
557
|
```
|
|
517
558
|
|
|
518
559
|
**Array Indices:**
|
|
560
|
+
|
|
519
561
|
```json
|
|
520
562
|
{
|
|
521
563
|
"type": "text",
|
|
522
564
|
"key": "first_item_note",
|
|
523
565
|
"label": "Note for First Item",
|
|
524
|
-
"
|
|
566
|
+
"enableIf": {
|
|
525
567
|
"key": "items[0].quantity",
|
|
526
568
|
"equals": 1
|
|
527
569
|
}
|
|
528
570
|
}
|
|
529
571
|
```
|
|
530
572
|
|
|
573
|
+
**Absolute Scope (v0.2.9+):**
|
|
574
|
+
|
|
575
|
+
```json
|
|
576
|
+
{
|
|
577
|
+
"type": "container",
|
|
578
|
+
"key": "shipping_options",
|
|
579
|
+
"elements": [
|
|
580
|
+
{
|
|
581
|
+
"type": "text",
|
|
582
|
+
"key": "express_note",
|
|
583
|
+
"label": "Express Shipping Note",
|
|
584
|
+
"enableIf": {
|
|
585
|
+
"key": "shipping_type",
|
|
586
|
+
"equals": "express",
|
|
587
|
+
"scope": "absolute"
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
]
|
|
591
|
+
}
|
|
592
|
+
```
|
|
593
|
+
|
|
531
594
|
**Hide Entire Sections:**
|
|
595
|
+
|
|
532
596
|
```json
|
|
533
597
|
{
|
|
534
598
|
"type": "container",
|
|
535
599
|
"key": "advanced_settings",
|
|
536
600
|
"label": "Advanced Settings",
|
|
537
|
-
"
|
|
601
|
+
"enableIf": {
|
|
538
602
|
"key": "mode",
|
|
539
603
|
"equals": "advanced"
|
|
540
604
|
},
|
|
@@ -560,19 +624,19 @@ interface DisplayCondition {
|
|
|
560
624
|
|
|
561
625
|
**Future Extensibility:**
|
|
562
626
|
|
|
563
|
-
The `
|
|
627
|
+
The `enableIf` system is designed for future expansion:
|
|
564
628
|
|
|
565
629
|
```typescript
|
|
566
630
|
// Future operators (planned)
|
|
567
631
|
{
|
|
568
|
-
"
|
|
632
|
+
"enableIf": {
|
|
569
633
|
"key": "age",
|
|
570
634
|
"greaterThan": 18
|
|
571
635
|
}
|
|
572
636
|
}
|
|
573
637
|
|
|
574
638
|
{
|
|
575
|
-
"
|
|
639
|
+
"enableIf": {
|
|
576
640
|
"key": "status",
|
|
577
641
|
"in": ["active", "pending"]
|
|
578
642
|
}
|
|
@@ -580,7 +644,7 @@ The `displayIf` system is designed for future expansion:
|
|
|
580
644
|
|
|
581
645
|
// Future complex conditions (planned)
|
|
582
646
|
{
|
|
583
|
-
"
|
|
647
|
+
"enableIf": {
|
|
584
648
|
"and": [
|
|
585
649
|
{ "key": "role", "equals": "admin" },
|
|
586
650
|
{ "key": "verified", "equals": true }
|