@dmitryvim/form-builder 0.1.41 → 0.2.0

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