@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.
@@ -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.