@dmitryvim/form-builder 0.1.37 → 0.1.38
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 +10 -5
- package/dist/demo.js +60 -74
- package/dist/form-builder.js +201 -85
- package/dist/index.html +1 -1
- package/package.json +1 -1
- package/docs/13_form_builder.html +0 -1337
- package/docs/REQUIREMENTS.md +0 -313
- package/docs/integration.md +0 -480
- package/docs/schema.md +0 -433
package/docs/integration.md
DELETED
|
@@ -1,480 +0,0 @@
|
|
|
1
|
-
# Integration Guide
|
|
2
|
-
|
|
3
|
-
Complete guide for integrating Form Builder into your application.
|
|
4
|
-
|
|
5
|
-
## CDN Integration
|
|
6
|
-
|
|
7
|
-
### Basic Iframe Embedding
|
|
8
|
-
|
|
9
|
-
```html
|
|
10
|
-
<iframe
|
|
11
|
-
src="https://picazru.github.io/form-builder/dist/index.html"
|
|
12
|
-
width="100%"
|
|
13
|
-
height="600px"
|
|
14
|
-
frameborder="0"
|
|
15
|
-
></iframe>
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
### With Custom Schema
|
|
19
|
-
|
|
20
|
-
```html
|
|
21
|
-
<iframe
|
|
22
|
-
src="https://picazru.github.io/form-builder/dist/index.html?schema=BASE64_SCHEMA"
|
|
23
|
-
width="100%"
|
|
24
|
-
height="600px"
|
|
25
|
-
></iframe>
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
**Encoding Schema:**
|
|
29
|
-
|
|
30
|
-
```javascript
|
|
31
|
-
const schema = { version: "0.3", title: "My Form", elements: [...] };
|
|
32
|
-
const encodedSchema = btoa(JSON.stringify(schema));
|
|
33
|
-
const url = `https://picazru.github.io/form-builder/dist/index.html?schema=${encodedSchema}`;
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
## NPM Integration
|
|
37
|
-
|
|
38
|
-
### Installation
|
|
39
|
-
|
|
40
|
-
```bash
|
|
41
|
-
npm install @dmitryvim/form-builder
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
### Direct HTML Integration
|
|
45
|
-
|
|
46
|
-
Copy the form builder HTML directly into your application:
|
|
47
|
-
|
|
48
|
-
```javascript
|
|
49
|
-
import formBuilderHTML from "@dmitryvim/form-builder/dist/index.html";
|
|
50
|
-
|
|
51
|
-
// Insert into your page
|
|
52
|
-
document.getElementById("form-container").innerHTML = formBuilderHTML;
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
## Configuration
|
|
56
|
-
|
|
57
|
-
### File Upload Handler
|
|
58
|
-
|
|
59
|
-
The upload handler **must return a resource ID** that can be used for downloads and form submission:
|
|
60
|
-
|
|
61
|
-
```javascript
|
|
62
|
-
window.addEventListener("message", (event) => {
|
|
63
|
-
if (event.origin !== "https://picazru.github.io") return;
|
|
64
|
-
|
|
65
|
-
if (event.data.type === "formBuilderReady") {
|
|
66
|
-
const iframe = document.getElementById("formBuilder");
|
|
67
|
-
iframe.contentWindow.postMessage(
|
|
68
|
-
{
|
|
69
|
-
type: "configure",
|
|
70
|
-
config: {
|
|
71
|
-
uploadHandler: async (file) => {
|
|
72
|
-
const formData = new FormData();
|
|
73
|
-
formData.append("file", file);
|
|
74
|
-
|
|
75
|
-
const response = await fetch("/api/upload", {
|
|
76
|
-
method: "POST",
|
|
77
|
-
body: formData,
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
const result = await response.json();
|
|
81
|
-
return result.resourceId; // Return ID, not URL
|
|
82
|
-
},
|
|
83
|
-
downloadHandler: async (resourceId) => {
|
|
84
|
-
window.open(`/api/download/${resourceId}`, "_blank");
|
|
85
|
-
},
|
|
86
|
-
thumbnailHandler: async (resourceId) => {
|
|
87
|
-
return `/api/thumbnail/${resourceId}`;
|
|
88
|
-
},
|
|
89
|
-
},
|
|
90
|
-
},
|
|
91
|
-
"https://picazru.github.io",
|
|
92
|
-
);
|
|
93
|
-
}
|
|
94
|
-
});
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
### Read-Only Mode
|
|
98
|
-
|
|
99
|
-
Display form data without editing capabilities:
|
|
100
|
-
|
|
101
|
-
```javascript
|
|
102
|
-
iframe.contentWindow.postMessage(
|
|
103
|
-
{
|
|
104
|
-
type: "configure",
|
|
105
|
-
options: {
|
|
106
|
-
readonly: true,
|
|
107
|
-
},
|
|
108
|
-
},
|
|
109
|
-
"https://picazru.github.io",
|
|
110
|
-
);
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
### Tailwind CSS Integration
|
|
114
|
-
|
|
115
|
-
Always uses Tailwind CSS styling. Add to your CSS:
|
|
116
|
-
|
|
117
|
-
```css
|
|
118
|
-
/* Custom properties for consistent styling */
|
|
119
|
-
:root {
|
|
120
|
-
--form-primary: 59 130 246; /* Blue */
|
|
121
|
-
--form-secondary: 100 116 139; /* Gray */
|
|
122
|
-
--form-accent: 16 185 129; /* Green */
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/* Override form builder styles if needed */
|
|
126
|
-
.form-builder-container {
|
|
127
|
-
@apply max-w-none; /* Remove max-width constraints */
|
|
128
|
-
}
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
## Events
|
|
132
|
-
|
|
133
|
-
### Form Submission
|
|
134
|
-
|
|
135
|
-
Listen for form submissions:
|
|
136
|
-
|
|
137
|
-
```javascript
|
|
138
|
-
window.addEventListener("message", (event) => {
|
|
139
|
-
if (event.data.type === "formSubmit") {
|
|
140
|
-
const { data, schema } = event.data;
|
|
141
|
-
console.log("Form submitted:", data);
|
|
142
|
-
|
|
143
|
-
// Handle the submission
|
|
144
|
-
handleFormSubmission(data);
|
|
145
|
-
}
|
|
146
|
-
});
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
### Draft Saving
|
|
150
|
-
|
|
151
|
-
Listen for draft save events:
|
|
152
|
-
|
|
153
|
-
```javascript
|
|
154
|
-
window.addEventListener("message", (event) => {
|
|
155
|
-
if (event.data.type === "draftSave") {
|
|
156
|
-
const { data, schema } = event.data;
|
|
157
|
-
console.log("Draft saved:", data);
|
|
158
|
-
|
|
159
|
-
// Save draft without validation
|
|
160
|
-
saveDraft(data);
|
|
161
|
-
}
|
|
162
|
-
});
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
## API Communication
|
|
166
|
-
|
|
167
|
-
### Send Schema
|
|
168
|
-
|
|
169
|
-
```javascript
|
|
170
|
-
iframe.contentWindow.postMessage({
|
|
171
|
-
type: 'setSchema',
|
|
172
|
-
schema: {
|
|
173
|
-
version: "0.3",
|
|
174
|
-
title: "Contact Form",
|
|
175
|
-
elements: [...]
|
|
176
|
-
}
|
|
177
|
-
}, 'https://picazru.github.io');
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
### Prefill Form Data
|
|
181
|
-
|
|
182
|
-
```javascript
|
|
183
|
-
iframe.contentWindow.postMessage(
|
|
184
|
-
{
|
|
185
|
-
type: "setData",
|
|
186
|
-
data: {
|
|
187
|
-
name: "John Doe",
|
|
188
|
-
email: "john@example.com",
|
|
189
|
-
},
|
|
190
|
-
},
|
|
191
|
-
"https://picazru.github.io",
|
|
192
|
-
);
|
|
193
|
-
```
|
|
194
|
-
|
|
195
|
-
### Get Current Data
|
|
196
|
-
|
|
197
|
-
```javascript
|
|
198
|
-
// Request data
|
|
199
|
-
iframe.contentWindow.postMessage(
|
|
200
|
-
{
|
|
201
|
-
type: "getData",
|
|
202
|
-
},
|
|
203
|
-
"https://picazru.github.io",
|
|
204
|
-
);
|
|
205
|
-
|
|
206
|
-
// Listen for response
|
|
207
|
-
window.addEventListener("message", (event) => {
|
|
208
|
-
if (event.data.type === "currentData") {
|
|
209
|
-
console.log("Current form data:", event.data.data);
|
|
210
|
-
}
|
|
211
|
-
});
|
|
212
|
-
```
|
|
213
|
-
|
|
214
|
-
### Validate Form
|
|
215
|
-
|
|
216
|
-
```javascript
|
|
217
|
-
// Request validation
|
|
218
|
-
iframe.contentWindow.postMessage(
|
|
219
|
-
{
|
|
220
|
-
type: "validate",
|
|
221
|
-
},
|
|
222
|
-
"https://picazru.github.io",
|
|
223
|
-
);
|
|
224
|
-
|
|
225
|
-
// Listen for result
|
|
226
|
-
window.addEventListener("message", (event) => {
|
|
227
|
-
if (event.data.type === "validationResult") {
|
|
228
|
-
console.log("Form is valid:", event.data.isValid);
|
|
229
|
-
}
|
|
230
|
-
});
|
|
231
|
-
```
|
|
232
|
-
|
|
233
|
-
## Backend Integration
|
|
234
|
-
|
|
235
|
-
### File Upload Endpoint
|
|
236
|
-
|
|
237
|
-
Your backend must handle file uploads and return resource IDs:
|
|
238
|
-
|
|
239
|
-
```javascript
|
|
240
|
-
// Express.js example
|
|
241
|
-
app.post("/api/upload", upload.single("file"), (req, res) => {
|
|
242
|
-
const file = req.file;
|
|
243
|
-
|
|
244
|
-
// Store file (S3, local storage, etc.)
|
|
245
|
-
const resourceId = generateResourceId();
|
|
246
|
-
storeFile(resourceId, file);
|
|
247
|
-
|
|
248
|
-
res.json({
|
|
249
|
-
resourceId: resourceId,
|
|
250
|
-
filename: file.originalname,
|
|
251
|
-
size: file.size,
|
|
252
|
-
mimetype: file.mimetype,
|
|
253
|
-
});
|
|
254
|
-
});
|
|
255
|
-
```
|
|
256
|
-
|
|
257
|
-
### File Download Endpoint
|
|
258
|
-
|
|
259
|
-
```javascript
|
|
260
|
-
app.get("/api/download/:resourceId", (req, res) => {
|
|
261
|
-
const { resourceId } = req.params;
|
|
262
|
-
|
|
263
|
-
// Retrieve file info
|
|
264
|
-
const fileInfo = getFileInfo(resourceId);
|
|
265
|
-
if (!fileInfo) {
|
|
266
|
-
return res.status(404).json({ error: "File not found" });
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
// Stream file to client
|
|
270
|
-
const fileStream = getFileStream(resourceId);
|
|
271
|
-
res.setHeader(
|
|
272
|
-
"Content-Disposition",
|
|
273
|
-
`attachment; filename="${fileInfo.filename}"`,
|
|
274
|
-
);
|
|
275
|
-
res.setHeader("Content-Type", fileInfo.mimetype);
|
|
276
|
-
fileStream.pipe(res);
|
|
277
|
-
});
|
|
278
|
-
```
|
|
279
|
-
|
|
280
|
-
### Form Submission Handler
|
|
281
|
-
|
|
282
|
-
```javascript
|
|
283
|
-
app.post("/api/forms/submit", (req, res) => {
|
|
284
|
-
const { schema, data } = req.body;
|
|
285
|
-
|
|
286
|
-
// Process form data
|
|
287
|
-
// File fields will contain resource IDs
|
|
288
|
-
|
|
289
|
-
console.log("Received form:", data);
|
|
290
|
-
// Example: { name: "John", avatar: "res_abc123", documents: ["res_def456", "res_ghi789"] }
|
|
291
|
-
|
|
292
|
-
// Validate and save
|
|
293
|
-
const result = processFormSubmission(schema, data);
|
|
294
|
-
|
|
295
|
-
res.json({ success: true, id: result.id });
|
|
296
|
-
});
|
|
297
|
-
```
|
|
298
|
-
|
|
299
|
-
## Framework-Specific Examples
|
|
300
|
-
|
|
301
|
-
### React Integration
|
|
302
|
-
|
|
303
|
-
```jsx
|
|
304
|
-
import { useEffect, useRef } from "react";
|
|
305
|
-
|
|
306
|
-
function FormBuilder({ schema, onSubmit }) {
|
|
307
|
-
const iframeRef = useRef(null);
|
|
308
|
-
|
|
309
|
-
useEffect(() => {
|
|
310
|
-
const handleMessage = (event) => {
|
|
311
|
-
if (event.data.type === "formBuilderReady") {
|
|
312
|
-
// Configure form builder
|
|
313
|
-
iframeRef.current.contentWindow.postMessage(
|
|
314
|
-
{
|
|
315
|
-
type: "setSchema",
|
|
316
|
-
schema: schema,
|
|
317
|
-
},
|
|
318
|
-
"https://picazru.github.io",
|
|
319
|
-
);
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
if (event.data.type === "formSubmit") {
|
|
323
|
-
onSubmit(event.data.data);
|
|
324
|
-
}
|
|
325
|
-
};
|
|
326
|
-
|
|
327
|
-
window.addEventListener("message", handleMessage);
|
|
328
|
-
return () => window.removeEventListener("message", handleMessage);
|
|
329
|
-
}, [schema, onSubmit]);
|
|
330
|
-
|
|
331
|
-
return (
|
|
332
|
-
<iframe
|
|
333
|
-
ref={iframeRef}
|
|
334
|
-
src="https://picazru.github.io/form-builder/dist/index.html"
|
|
335
|
-
width="100%"
|
|
336
|
-
height="600px"
|
|
337
|
-
frameBorder="0"
|
|
338
|
-
/>
|
|
339
|
-
);
|
|
340
|
-
}
|
|
341
|
-
```
|
|
342
|
-
|
|
343
|
-
### Vue.js Integration
|
|
344
|
-
|
|
345
|
-
```vue
|
|
346
|
-
<template>
|
|
347
|
-
<iframe
|
|
348
|
-
ref="formBuilder"
|
|
349
|
-
src="https://picazru.github.io/form-builder/dist/index.html"
|
|
350
|
-
width="100%"
|
|
351
|
-
height="600px"
|
|
352
|
-
frameborder="0"
|
|
353
|
-
@load="onIframeLoad"
|
|
354
|
-
/>
|
|
355
|
-
</template>
|
|
356
|
-
|
|
357
|
-
<script>
|
|
358
|
-
export default {
|
|
359
|
-
props: ["schema"],
|
|
360
|
-
|
|
361
|
-
mounted() {
|
|
362
|
-
window.addEventListener("message", this.handleMessage);
|
|
363
|
-
},
|
|
364
|
-
|
|
365
|
-
beforeUnmount() {
|
|
366
|
-
window.removeEventListener("message", this.handleMessage);
|
|
367
|
-
},
|
|
368
|
-
|
|
369
|
-
methods: {
|
|
370
|
-
handleMessage(event) {
|
|
371
|
-
if (event.data.type === "formBuilderReady") {
|
|
372
|
-
this.$refs.formBuilder.contentWindow.postMessage(
|
|
373
|
-
{
|
|
374
|
-
type: "setSchema",
|
|
375
|
-
schema: this.schema,
|
|
376
|
-
},
|
|
377
|
-
"https://picazru.github.io",
|
|
378
|
-
);
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
if (event.data.type === "formSubmit") {
|
|
382
|
-
this.$emit("submit", event.data.data);
|
|
383
|
-
}
|
|
384
|
-
},
|
|
385
|
-
},
|
|
386
|
-
};
|
|
387
|
-
</script>
|
|
388
|
-
```
|
|
389
|
-
|
|
390
|
-
## Security Considerations
|
|
391
|
-
|
|
392
|
-
### Origin Validation
|
|
393
|
-
|
|
394
|
-
Always validate message origins:
|
|
395
|
-
|
|
396
|
-
```javascript
|
|
397
|
-
window.addEventListener("message", (event) => {
|
|
398
|
-
// Only accept messages from form builder origin
|
|
399
|
-
if (event.origin !== "https://picazru.github.io") {
|
|
400
|
-
return;
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
// Process message...
|
|
404
|
-
});
|
|
405
|
-
```
|
|
406
|
-
|
|
407
|
-
### File Upload Security
|
|
408
|
-
|
|
409
|
-
- **Validate file types** on server
|
|
410
|
-
- **Limit file sizes** appropriately
|
|
411
|
-
- **Scan for viruses** if possible
|
|
412
|
-
- **Use secure file storage** (S3 with proper permissions)
|
|
413
|
-
- **Generate secure resource IDs** (UUID, crypto.randomUUID())
|
|
414
|
-
|
|
415
|
-
### Content Security Policy
|
|
416
|
-
|
|
417
|
-
Add to your CSP headers:
|
|
418
|
-
|
|
419
|
-
```
|
|
420
|
-
Content-Security-Policy:
|
|
421
|
-
default-src 'self';
|
|
422
|
-
frame-src https://picazru.github.io;
|
|
423
|
-
connect-src 'self' https://your-api.com;
|
|
424
|
-
```
|
|
425
|
-
|
|
426
|
-
## Troubleshooting
|
|
427
|
-
|
|
428
|
-
### Common Issues
|
|
429
|
-
|
|
430
|
-
**Form builder not loading**: Check CSP settings and iframe src URL
|
|
431
|
-
|
|
432
|
-
**File uploads failing**: Verify upload handler returns resource ID, not URL
|
|
433
|
-
|
|
434
|
-
**Messages not working**: Confirm origin validation and message format
|
|
435
|
-
|
|
436
|
-
**Schema not applying**: Check schema format against [Schema Reference](schema.md)
|
|
437
|
-
|
|
438
|
-
### Debugging
|
|
439
|
-
|
|
440
|
-
Enable console logging in iframe:
|
|
441
|
-
|
|
442
|
-
```javascript
|
|
443
|
-
iframe.contentWindow.postMessage(
|
|
444
|
-
{
|
|
445
|
-
type: "configure",
|
|
446
|
-
config: {
|
|
447
|
-
debug: true,
|
|
448
|
-
},
|
|
449
|
-
},
|
|
450
|
-
"https://picazru.github.io",
|
|
451
|
-
);
|
|
452
|
-
```
|
|
453
|
-
|
|
454
|
-
This will log all form builder events to the browser console.
|
|
455
|
-
|
|
456
|
-
## Migration
|
|
457
|
-
|
|
458
|
-
### From v0.1.x to v0.2.x
|
|
459
|
-
|
|
460
|
-
- Upload handlers must return resource IDs instead of URLs
|
|
461
|
-
- Added support for draft saving
|
|
462
|
-
- Improved Tailwind CSS integration
|
|
463
|
-
|
|
464
|
-
### Updating Handlers
|
|
465
|
-
|
|
466
|
-
```javascript
|
|
467
|
-
// Old (v0.1.x)
|
|
468
|
-
uploadHandler: async (file) => {
|
|
469
|
-
// ... upload logic
|
|
470
|
-
return result.fileUrl; // URL
|
|
471
|
-
};
|
|
472
|
-
|
|
473
|
-
// New (v0.2.x)
|
|
474
|
-
uploadHandler: async (file) => {
|
|
475
|
-
// ... upload logic
|
|
476
|
-
return result.resourceId; // ID
|
|
477
|
-
};
|
|
478
|
-
```
|
|
479
|
-
|
|
480
|
-
This integration guide covers all aspects of using Form Builder in production applications.
|