@dmitryvim/form-builder 0.1.42 → 0.2.1
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 +260 -22
- package/dist/browser/formbuilder.min.js +184 -0
- package/dist/browser/formbuilder.v0.2.1.min.js +184 -0
- package/dist/cjs/index.cjs +3652 -0
- package/dist/cjs/index.cjs.map +1 -0
- package/dist/esm/index.js +3603 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/form-builder.js +154 -3369
- package/dist/types/components/container.d.ts +15 -0
- package/dist/types/components/file.d.ts +26 -0
- package/dist/types/components/group.d.ts +24 -0
- package/dist/types/components/index.d.ts +11 -0
- package/dist/types/components/number.d.ts +11 -0
- package/dist/types/components/registry.d.ts +15 -0
- package/dist/types/components/select.d.ts +11 -0
- package/dist/types/components/text.d.ts +11 -0
- package/dist/types/components/textarea.d.ts +11 -0
- package/dist/types/index.d.ts +33 -0
- package/dist/types/instance/FormBuilderInstance.d.ts +134 -0
- package/dist/types/instance/state.d.ts +13 -0
- package/dist/types/styles/theme.d.ts +63 -0
- package/dist/types/types/component-operations.d.ts +45 -0
- package/dist/types/types/config.d.ts +47 -0
- package/dist/types/types/index.d.ts +4 -0
- package/dist/types/types/schema.d.ts +115 -0
- package/dist/types/types/state.d.ts +11 -0
- package/dist/types/utils/helpers.d.ts +4 -0
- package/dist/types/utils/styles.d.ts +21 -0
- package/dist/types/utils/translation.d.ts +8 -0
- package/dist/types/utils/validation.d.ts +2 -0
- package/package.json +32 -15
- package/dist/demo.js +0 -861
- package/dist/elements.html +0 -1130
- package/dist/elements.js +0 -488
- package/dist/index.html +0 -315
package/README.md
CHANGED
|
@@ -35,6 +35,22 @@ Try it now: **[https://picazru.github.io/form-builder/dist/index.html](https://p
|
|
|
35
35
|
npm install @dmitryvim/form-builder
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
+
### TypeScript Setup
|
|
39
|
+
|
|
40
|
+
This package ships with complete TypeScript definitions. Ensure your `tsconfig.json` is configured for modern module resolution:
|
|
41
|
+
|
|
42
|
+
```json
|
|
43
|
+
{
|
|
44
|
+
"compilerOptions": {
|
|
45
|
+
"moduleResolution": "NodeNext", // or "Bundler" for Vite/Webpack
|
|
46
|
+
"esModuleInterop": true,
|
|
47
|
+
"skipLibCheck": false
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**No need for custom `.d.ts` files** - types are auto-resolved from the package at `dist/types/index.d.ts`.
|
|
53
|
+
|
|
38
54
|
## Core Features
|
|
39
55
|
|
|
40
56
|
- **🎯 Schema-driven forms**: JSON Schema v0.3 → Interactive forms with live preview
|
|
@@ -48,6 +64,16 @@ npm install @dmitryvim/form-builder
|
|
|
48
64
|
- **🔧 Framework agnostic**: Works with any web stack (React, Vue, Angular, vanilla JS)
|
|
49
65
|
- **📦 Zero dependencies**: Self-contained HTML/CSS/JavaScript
|
|
50
66
|
- **📱 Responsive design**: Mobile-friendly with Tailwind CSS styling
|
|
67
|
+
- **🏗️ Instance-based architecture**: Multiple independent forms with isolated state
|
|
68
|
+
|
|
69
|
+
### New in v0.2.0
|
|
70
|
+
|
|
71
|
+
- **🔄 onChange Events**: Real-time change notifications with debouncing (eliminates polling)
|
|
72
|
+
- **🎨 CSS Theming**: 43 configurable theme properties (no `!important` overrides)
|
|
73
|
+
- **📝 Partial Updates**: Update fields without re-rendering (`setFormData`, `updateField`)
|
|
74
|
+
- **⚡ Async Thumbnails**: Dynamic thumbnail loading with async-only `getThumbnail`
|
|
75
|
+
|
|
76
|
+
**Impact**: Eliminates ~280+ lines of workaround code for Klein integration
|
|
51
77
|
|
|
52
78
|
## Quick Examples
|
|
53
79
|
|
|
@@ -144,24 +170,52 @@ npm install @dmitryvim/form-builder
|
|
|
144
170
|
|
|
145
171
|
```javascript
|
|
146
172
|
// ES6 imports
|
|
147
|
-
import
|
|
148
|
-
|
|
149
|
-
//
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
173
|
+
import { createFormBuilder } from "@dmitryvim/form-builder";
|
|
174
|
+
|
|
175
|
+
// Create form instance with v0.3.0 features
|
|
176
|
+
const formBuilder = createFormBuilder({
|
|
177
|
+
uploadFile: async (file) => {
|
|
178
|
+
// Your upload logic - return resource ID
|
|
179
|
+
return "resource-123";
|
|
180
|
+
},
|
|
181
|
+
downloadFile: (resourceId, fileName) => {
|
|
182
|
+
// Handle file download
|
|
183
|
+
window.open(`/api/files/${resourceId}`, '_blank');
|
|
184
|
+
},
|
|
185
|
+
getThumbnail: async (resourceId) => {
|
|
186
|
+
// v0.2.0: Async-only thumbnail loading
|
|
187
|
+
const url = await fetchThumbnailUrl(resourceId);
|
|
188
|
+
return url;
|
|
189
|
+
},
|
|
190
|
+
actionHandler: (value, key, field) => {
|
|
191
|
+
// Handle action button clicks
|
|
192
|
+
console.log("Action clicked:", { value, key, field });
|
|
193
|
+
},
|
|
194
|
+
// v0.2.0: Real-time change events
|
|
195
|
+
onChange: (formData) => {
|
|
196
|
+
console.log("Form changed:", formData);
|
|
197
|
+
if (formData.valid) autoSave(formData.data);
|
|
198
|
+
},
|
|
199
|
+
// v0.2.0: CSS theming
|
|
200
|
+
theme: {
|
|
201
|
+
primaryColor: '#0066cc',
|
|
202
|
+
borderRadius: '4px',
|
|
162
203
|
}
|
|
163
204
|
});
|
|
164
|
-
|
|
205
|
+
|
|
206
|
+
// Render form
|
|
207
|
+
const rootElement = document.getElementById("form-container");
|
|
208
|
+
formBuilder.renderForm(rootElement, schema, prefillData);
|
|
209
|
+
|
|
210
|
+
// Get form data
|
|
211
|
+
const result = formBuilder.getFormData();
|
|
212
|
+
if (result.valid) {
|
|
213
|
+
console.log("Form data:", result.data);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// v0.2.0: Update fields without re-rendering
|
|
217
|
+
formBuilder.updateField('email', 'newemail@example.com');
|
|
218
|
+
formBuilder.setFormData({ name: 'John', email: 'john@example.com' });
|
|
165
219
|
```
|
|
166
220
|
|
|
167
221
|
### 2. CDN Integration
|
|
@@ -170,7 +224,15 @@ FormBuilder.renderForm(schema, prefillData);
|
|
|
170
224
|
<!-- Direct script include (npm CDN) -->
|
|
171
225
|
<script src="https://cdn.jsdelivr.net/npm/@dmitryvim/form-builder@latest/dist/form-builder.js"></script>
|
|
172
226
|
<script>
|
|
173
|
-
window.FormBuilder
|
|
227
|
+
const { createFormBuilder } = window.FormBuilder;
|
|
228
|
+
|
|
229
|
+
const formBuilder = createFormBuilder({
|
|
230
|
+
uploadFile: async (file) => "resource-id",
|
|
231
|
+
downloadFile: (resourceId) => { /* download */ }
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
const rootElement = document.getElementById("form-container");
|
|
235
|
+
formBuilder.renderForm(rootElement, schema);
|
|
174
236
|
</script>
|
|
175
237
|
|
|
176
238
|
<!-- Or use our S3 CDN -->
|
|
@@ -222,12 +284,188 @@ See [Integration Guide](docs/integration.md) for detailed setup instructions.
|
|
|
222
284
|
- **Read-only mode**: Display data without editing
|
|
223
285
|
- **Action buttons**: Custom buttons in readonly mode with configurable handlers
|
|
224
286
|
|
|
287
|
+
## API Reference
|
|
288
|
+
|
|
289
|
+
### Core Methods
|
|
290
|
+
|
|
291
|
+
```typescript
|
|
292
|
+
import { createFormBuilder } from '@dmitryvim/form-builder';
|
|
293
|
+
|
|
294
|
+
// Create form instance
|
|
295
|
+
const form = createFormBuilder({
|
|
296
|
+
// Required handlers
|
|
297
|
+
uploadFile: async (file: File) => string, // Upload file, return resource ID
|
|
298
|
+
downloadFile: (resourceId: string, fileName: string) => void,
|
|
299
|
+
|
|
300
|
+
// Optional handlers
|
|
301
|
+
getThumbnail?: async (resourceId: string) => string | null, // v0.2.0: Async-only, for preview thumbnails
|
|
302
|
+
getDownloadUrl?: (resourceId: string) => string | null, // Optional: URL for downloading full file
|
|
303
|
+
actionHandler?: (value: any, key: string, field: any) => void,
|
|
304
|
+
|
|
305
|
+
// v0.2.0: onChange events
|
|
306
|
+
onChange?: (formData: FormResult) => void,
|
|
307
|
+
onFieldChange?: (fieldPath: string, value: any, formData: FormResult) => void,
|
|
308
|
+
debounceMs?: number, // Default: 300ms
|
|
309
|
+
|
|
310
|
+
// v0.2.0: CSS theming
|
|
311
|
+
theme?: {
|
|
312
|
+
primaryColor?: string,
|
|
313
|
+
borderRadius?: string,
|
|
314
|
+
fontSize?: string,
|
|
315
|
+
fontFamily?: string,
|
|
316
|
+
// ... 39 more theme properties
|
|
317
|
+
}
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
// Render form
|
|
321
|
+
form.renderForm(rootElement, schema, prefillData);
|
|
322
|
+
|
|
323
|
+
// Get form data
|
|
324
|
+
const result = form.getFormData(); // { valid, errors, data }
|
|
325
|
+
|
|
326
|
+
// v0.2.0: Update data without re-rendering
|
|
327
|
+
form.setFormData({ name: 'John', email: 'john@example.com' });
|
|
328
|
+
form.updateField('email', 'newemail@example.com');
|
|
329
|
+
form.updateField('address.city', 'New York'); // Nested paths
|
|
330
|
+
|
|
331
|
+
// Switch modes
|
|
332
|
+
form.setMode('readonly'); // or 'edit'
|
|
333
|
+
|
|
334
|
+
// Cleanup
|
|
335
|
+
form.destroy();
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
### Migration from v0.1.x
|
|
339
|
+
|
|
340
|
+
**Breaking Changes in v0.2.0:**
|
|
341
|
+
|
|
342
|
+
1. **Instance-Only API** - Global static methods removed
|
|
343
|
+
```typescript
|
|
344
|
+
// OLD (v0.1.x)
|
|
345
|
+
FormBuilder.configure({ uploadFile: async (file) => "id" });
|
|
346
|
+
FormBuilder.renderForm(root, schema);
|
|
347
|
+
|
|
348
|
+
// NEW (v0.2.0)
|
|
349
|
+
const form = createFormBuilder({ uploadFile: async (file) => "id" });
|
|
350
|
+
form.renderForm(root, schema);
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
2. **Async getThumbnail** - Must return Promise
|
|
354
|
+
```typescript
|
|
355
|
+
// OLD (v0.1.x)
|
|
356
|
+
getThumbnail: (resourceId) => `/thumbs/${resourceId}.jpg`
|
|
357
|
+
|
|
358
|
+
// NEW (v0.2.0)
|
|
359
|
+
getThumbnail: async (resourceId) => `/thumbs/${resourceId}.jpg`
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
See [CHANGELOG.md](CHANGELOG.md) for complete migration details.
|
|
363
|
+
|
|
364
|
+
### Theming
|
|
365
|
+
|
|
366
|
+
Customize appearance with 43 theme properties:
|
|
367
|
+
|
|
368
|
+
```typescript
|
|
369
|
+
const form = createFormBuilder({
|
|
370
|
+
theme: {
|
|
371
|
+
// Colors
|
|
372
|
+
primaryColor: '#0066cc',
|
|
373
|
+
borderColor: '#e0e0e0',
|
|
374
|
+
errorColor: '#d32f2f',
|
|
375
|
+
|
|
376
|
+
// Typography
|
|
377
|
+
fontSize: '16px',
|
|
378
|
+
fontFamily: '"Roboto", sans-serif',
|
|
379
|
+
|
|
380
|
+
// Spacing
|
|
381
|
+
borderRadius: '4px',
|
|
382
|
+
inputPaddingX: '12px',
|
|
383
|
+
|
|
384
|
+
// Buttons
|
|
385
|
+
buttonBgColor: '#0066cc',
|
|
386
|
+
buttonTextColor: '#ffffff',
|
|
387
|
+
}
|
|
388
|
+
});
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
**Most Common Properties:**
|
|
392
|
+
- `primaryColor` - Primary brand color
|
|
393
|
+
- `borderRadius` - Border radius for inputs/buttons
|
|
394
|
+
- `fontSize` - Base font size
|
|
395
|
+
- `fontFamily` - Font family
|
|
396
|
+
- `borderColor` - Input border color
|
|
397
|
+
|
|
398
|
+
No `!important` overrides needed. See [CHANGELOG.md](CHANGELOG.md) for all 43 properties.
|
|
399
|
+
|
|
400
|
+
### File Handling
|
|
401
|
+
|
|
402
|
+
The form builder provides flexible file handling with separate hooks for uploads, downloads, and previews:
|
|
403
|
+
|
|
404
|
+
```typescript
|
|
405
|
+
const form = createFormBuilder({
|
|
406
|
+
// Required: Upload handler
|
|
407
|
+
uploadFile: async (file) => {
|
|
408
|
+
const formData = new FormData();
|
|
409
|
+
formData.append('file', file);
|
|
410
|
+
const response = await fetch('/api/upload', {
|
|
411
|
+
method: 'POST',
|
|
412
|
+
body: formData
|
|
413
|
+
});
|
|
414
|
+
const data = await response.json();
|
|
415
|
+
return data.resourceId; // Return unique resource ID
|
|
416
|
+
},
|
|
417
|
+
|
|
418
|
+
// Required: Download handler
|
|
419
|
+
downloadFile: (resourceId, fileName) => {
|
|
420
|
+
// Option 1: Direct download
|
|
421
|
+
window.open(`/api/files/${resourceId}/download`, '_blank');
|
|
422
|
+
|
|
423
|
+
// Option 2: Programmatic download
|
|
424
|
+
fetch(`/api/files/${resourceId}/download`)
|
|
425
|
+
.then(response => response.blob())
|
|
426
|
+
.then(blob => {
|
|
427
|
+
const url = URL.createObjectURL(blob);
|
|
428
|
+
const a = document.createElement('a');
|
|
429
|
+
a.href = url;
|
|
430
|
+
a.download = fileName;
|
|
431
|
+
a.click();
|
|
432
|
+
URL.revokeObjectURL(url);
|
|
433
|
+
});
|
|
434
|
+
},
|
|
435
|
+
|
|
436
|
+
// Optional: Thumbnail URLs for preview (async-only in v0.2.0)
|
|
437
|
+
getThumbnail: async (resourceId) => {
|
|
438
|
+
const response = await fetch(`/api/files/${resourceId}/thumbnail`);
|
|
439
|
+
const data = await response.json();
|
|
440
|
+
return data.thumbnailUrl; // Return URL or null
|
|
441
|
+
},
|
|
442
|
+
|
|
443
|
+
// Optional: Full file download URL (used instead of getThumbnail for downloads)
|
|
444
|
+
getDownloadUrl: (resourceId) => {
|
|
445
|
+
return `/api/files/${resourceId}/download`;
|
|
446
|
+
}
|
|
447
|
+
});
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
**Handler Priority for Downloads:**
|
|
451
|
+
|
|
452
|
+
When a user clicks the download button in readonly mode, the form builder uses this priority:
|
|
453
|
+
|
|
454
|
+
1. **`getDownloadUrl`** - If provided, this URL is used for downloads
|
|
455
|
+
2. **`getThumbnail`** - If `getDownloadUrl` is not provided, falls back to thumbnail URL
|
|
456
|
+
3. **`downloadFile`** - If neither URL hook is provided, calls the download handler
|
|
457
|
+
|
|
458
|
+
**Use Cases:**
|
|
459
|
+
|
|
460
|
+
- **Separate thumbnail and download URLs**: Provide both `getThumbnail` (for optimized previews) and `getDownloadUrl` (for full files)
|
|
461
|
+
- **Same URL for both**: Provide only `getThumbnail` if thumbnail URL is also the download URL
|
|
462
|
+
- **Programmatic download**: Provide only `downloadFile` for custom download logic
|
|
463
|
+
|
|
225
464
|
## Documentation
|
|
226
465
|
|
|
227
|
-
-
|
|
228
|
-
- [
|
|
229
|
-
- [
|
|
230
|
-
- [Development Guide](CLAUDE.md) - Architecture and development workflow
|
|
466
|
+
- **API Reference** - See above for core methods and theming
|
|
467
|
+
- **Development Guide** - [CLAUDE.md](CLAUDE.md) for architecture and workflow
|
|
468
|
+
- **Changelog** - [CHANGELOG.md](CHANGELOG.md) for version history and migration
|
|
231
469
|
|
|
232
470
|
## Live Demo
|
|
233
471
|
|
|
@@ -246,7 +484,7 @@ Features a 3-column interface:
|
|
|
246
484
|
- **GitHub**: [picazru/form-builder](https://github.com/picazru/form-builder)
|
|
247
485
|
- **NPM Package**: [@dmitryvim/form-builder](https://www.npmjs.com/package/@dmitryvim/form-builder)
|
|
248
486
|
- **CDN**: [picaz-form-builder.website.yandexcloud.net](https://picaz-form-builder.website.yandexcloud.net/)
|
|
249
|
-
- **Version**: 0.
|
|
487
|
+
- **Version**: 0.2.0 (Unreleased - Breaking Changes + New Features)
|
|
250
488
|
- **License**: MIT - see [LICENSE](LICENSE) file
|
|
251
489
|
|
|
252
490
|
Built with ❤️ for the web development community.
|