@dmitryvim/form-builder 0.1.1 → 0.1.5
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 +34 -125
- package/dist/README.md +193 -0
- package/dist/example.html +108 -0
- package/dist/form-builder.js +972 -0
- package/dist/index.html +446 -171
- package/dist/sample.html +1615 -0
- package/docs/13_form_builder.html +663 -0
- package/docs/REQUIREMENTS.md +281 -0
- package/docs/integration.md +445 -0
- package/docs/schema.md +425 -0
- package/package.json +9 -4
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
# Product & Business Requirements
|
|
2
|
+
|
|
3
|
+
Core requirements and specifications for the Form Builder library.
|
|
4
|
+
|
|
5
|
+
## Product Overview
|
|
6
|
+
|
|
7
|
+
**Form Builder** transforms JSON schemas into dynamic, interactive web forms with real-time validation and structured data output. Designed as a framework-agnostic, zero-dependency library for easy integration.
|
|
8
|
+
|
|
9
|
+
**Primary Goal**: Provide a reusable form generation solution that eliminates custom form development overhead.
|
|
10
|
+
|
|
11
|
+
## Business Requirements
|
|
12
|
+
|
|
13
|
+
### Core Value Propositions
|
|
14
|
+
|
|
15
|
+
1. **Rapid Form Development**: Schema → Form in minutes, not hours
|
|
16
|
+
2. **Consistent UX**: Standardized form behavior across applications
|
|
17
|
+
3. **Zero Dependencies**: No framework lock-in or bundle bloat
|
|
18
|
+
4. **File Upload Ready**: Built-in support for modern file workflows
|
|
19
|
+
5. **Deployment Flexibility**: CDN, NPM, or self-hosted options
|
|
20
|
+
|
|
21
|
+
### Target Users
|
|
22
|
+
|
|
23
|
+
- **Developers**: Need forms for SPA applications
|
|
24
|
+
- **Product Teams**: Require consistent form experiences
|
|
25
|
+
- **Startups**: Want rapid prototyping capabilities
|
|
26
|
+
- **Enterprise**: Need standardized form solutions
|
|
27
|
+
|
|
28
|
+
## Functional Requirements
|
|
29
|
+
|
|
30
|
+
### 1. Form Generation Engine
|
|
31
|
+
|
|
32
|
+
**MUST support field types:**
|
|
33
|
+
- `text` - Single line input with validation
|
|
34
|
+
- `textarea` - Multi-line text input
|
|
35
|
+
- `number` - Numeric input with constraints
|
|
36
|
+
- `select` - Dropdown with options
|
|
37
|
+
- `file` - Single file upload with preview
|
|
38
|
+
- `files` - Multiple file upload with limits
|
|
39
|
+
- `group` - Nested objects with repeat support
|
|
40
|
+
|
|
41
|
+
```javascript
|
|
42
|
+
// Example schema
|
|
43
|
+
{
|
|
44
|
+
"version": "0.3",
|
|
45
|
+
"title": "Asset Upload",
|
|
46
|
+
"elements": [
|
|
47
|
+
{
|
|
48
|
+
"type": "files",
|
|
49
|
+
"key": "assets",
|
|
50
|
+
"label": "Images",
|
|
51
|
+
"maxCount": 10,
|
|
52
|
+
"accept": { "extensions": ["jpg", "png"] }
|
|
53
|
+
}
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### 2. Validation System
|
|
59
|
+
|
|
60
|
+
**MUST provide:**
|
|
61
|
+
- Real-time field validation
|
|
62
|
+
- Required field checking
|
|
63
|
+
- String length limits (minLength/maxLength)
|
|
64
|
+
- Numeric ranges (min/max)
|
|
65
|
+
- Pattern matching (regex)
|
|
66
|
+
- File type restrictions
|
|
67
|
+
- Custom validation rules
|
|
68
|
+
|
|
69
|
+
**MUST support:**
|
|
70
|
+
- Form submission with full validation
|
|
71
|
+
- Draft saving without validation
|
|
72
|
+
- Field-level error display
|
|
73
|
+
|
|
74
|
+
### 3. File Upload System
|
|
75
|
+
|
|
76
|
+
**Upload Handler Requirements:**
|
|
77
|
+
```javascript
|
|
78
|
+
// Handler MUST return resource ID for download/submission
|
|
79
|
+
uploadHandler: async (file) => {
|
|
80
|
+
// Upload logic...
|
|
81
|
+
return resourceId; // NOT file URL
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
**MUST provide:**
|
|
86
|
+
- Visual file previews (thumbnails + icons)
|
|
87
|
+
- Upload progress indicators
|
|
88
|
+
- Individual file removal
|
|
89
|
+
- Drag & drop support
|
|
90
|
+
- File metadata display (name, size, type)
|
|
91
|
+
|
|
92
|
+
### 4. Form Modes
|
|
93
|
+
|
|
94
|
+
**Submission Mode** (default):
|
|
95
|
+
- Full editing capabilities
|
|
96
|
+
- Real-time validation
|
|
97
|
+
- Submit button requires all validation to pass
|
|
98
|
+
|
|
99
|
+
**Read-Only Mode**:
|
|
100
|
+
- Display form data without editing
|
|
101
|
+
- Show file download links
|
|
102
|
+
- Disable all form interactions
|
|
103
|
+
- Support nested object display
|
|
104
|
+
|
|
105
|
+
**Draft Mode**:
|
|
106
|
+
- Save incomplete forms
|
|
107
|
+
- Skip required field validation
|
|
108
|
+
- Preserve user input
|
|
109
|
+
- Enable resume functionality
|
|
110
|
+
|
|
111
|
+
### 5. Integration Capabilities
|
|
112
|
+
|
|
113
|
+
**MUST support:**
|
|
114
|
+
- CDN via iframe embedding
|
|
115
|
+
- NPM package installation
|
|
116
|
+
- Direct HTML integration
|
|
117
|
+
- Schema loading via URL parameters
|
|
118
|
+
- Form data prefilling
|
|
119
|
+
- Event-based communication
|
|
120
|
+
|
|
121
|
+
```html
|
|
122
|
+
<!-- CDN Integration -->
|
|
123
|
+
<iframe src="https://picazru.github.io/form-builder/dist/index.html"
|
|
124
|
+
width="100%" height="600px"></iframe>
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### 6. Styling System
|
|
128
|
+
|
|
129
|
+
**MUST use Tailwind CSS** for all styling:
|
|
130
|
+
- Consistent design system
|
|
131
|
+
- Responsive layouts
|
|
132
|
+
- Dark/light theme support
|
|
133
|
+
- Custom CSS property integration
|
|
134
|
+
- Framework compatibility
|
|
135
|
+
|
|
136
|
+
## Technical Requirements
|
|
137
|
+
|
|
138
|
+
### 1. Architecture
|
|
139
|
+
|
|
140
|
+
**Core Stack:**
|
|
141
|
+
- HTML5 semantic markup
|
|
142
|
+
- CSS3 with custom properties
|
|
143
|
+
- Vanilla JavaScript (ES6+)
|
|
144
|
+
- Web APIs (FormData, PostMessage, Crypto)
|
|
145
|
+
|
|
146
|
+
**Performance:**
|
|
147
|
+
- Library size <500KB uncompressed
|
|
148
|
+
- Form rendering <2s for 1000 fields
|
|
149
|
+
- Real-time validation without UI blocking
|
|
150
|
+
|
|
151
|
+
### 2. Browser Support
|
|
152
|
+
|
|
153
|
+
**MUST support:**
|
|
154
|
+
- Chrome 80+, Firefox 75+, Safari 13+, Edge 80+
|
|
155
|
+
- Mobile browsers with touch interfaces
|
|
156
|
+
- Progressive enhancement for older browsers
|
|
157
|
+
|
|
158
|
+
### 3. Security
|
|
159
|
+
|
|
160
|
+
**MUST implement:**
|
|
161
|
+
- Input sanitization for all user data
|
|
162
|
+
- File type validation (MIME + extension)
|
|
163
|
+
- Secure resource ID generation
|
|
164
|
+
- CSP-compatible code (no inline scripts)
|
|
165
|
+
- Origin validation for iframe communication
|
|
166
|
+
|
|
167
|
+
### 4. Data Formats
|
|
168
|
+
|
|
169
|
+
**Schema Format (v0.3):**
|
|
170
|
+
```typescript
|
|
171
|
+
interface FormSchema {
|
|
172
|
+
version: "0.3";
|
|
173
|
+
title: string;
|
|
174
|
+
elements: FormElement[];
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
**Output Format:**
|
|
179
|
+
```json
|
|
180
|
+
{
|
|
181
|
+
"textField": "value",
|
|
182
|
+
"fileField": "res_abc123",
|
|
183
|
+
"multipleFiles": ["res_def456", "res_ghi789"],
|
|
184
|
+
"nestedGroup": {
|
|
185
|
+
"subField": "value"
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
## Quality Requirements
|
|
191
|
+
|
|
192
|
+
### Performance Metrics
|
|
193
|
+
- **Form Rendering**: <2 seconds for 1000 fields
|
|
194
|
+
- **File Upload**: >95% success rate under size limits
|
|
195
|
+
- **Validation Speed**: <100ms per field
|
|
196
|
+
- **Memory Usage**: <50MB for large forms
|
|
197
|
+
|
|
198
|
+
### Reliability
|
|
199
|
+
- **Browser Compatibility**: >99% success rate on target browsers
|
|
200
|
+
- **Error Recovery**: Graceful fallback for all error conditions
|
|
201
|
+
- **Data Integrity**: No data loss during form interactions
|
|
202
|
+
|
|
203
|
+
### Usability
|
|
204
|
+
- **Accessibility**: WCAG 2.1 AA compliance
|
|
205
|
+
- **Mobile Support**: Touch-friendly interfaces
|
|
206
|
+
- **Error Messages**: Clear, actionable feedback
|
|
207
|
+
- **Loading States**: Visual feedback for all operations
|
|
208
|
+
|
|
209
|
+
## Deployment Requirements
|
|
210
|
+
|
|
211
|
+
### 1. CDN Distribution
|
|
212
|
+
- GitHub Pages hosting for global availability
|
|
213
|
+
- Versioned URLs for stable integration
|
|
214
|
+
- Automatic deployment on releases
|
|
215
|
+
|
|
216
|
+
### 2. NPM Package
|
|
217
|
+
- Published as `@dmitryvim/form-builder`
|
|
218
|
+
- ES6 module support
|
|
219
|
+
- CommonJS compatibility
|
|
220
|
+
- TypeScript definitions
|
|
221
|
+
|
|
222
|
+
### 3. Versioning
|
|
223
|
+
- Semantic versioning (SemVer)
|
|
224
|
+
- Backwards compatibility within major versions
|
|
225
|
+
- Migration guides for breaking changes
|
|
226
|
+
|
|
227
|
+
## Success Criteria
|
|
228
|
+
|
|
229
|
+
### Acceptance Criteria
|
|
230
|
+
- [ ] All field types render and validate correctly
|
|
231
|
+
- [ ] File uploads work with custom handlers
|
|
232
|
+
- [ ] Read-only mode displays data properly
|
|
233
|
+
- [ ] Draft saving works without validation
|
|
234
|
+
- [ ] Tailwind CSS styling applies correctly
|
|
235
|
+
- [ ] Cross-browser compatibility verified
|
|
236
|
+
- [ ] >80% test coverage achieved
|
|
237
|
+
- [ ] Performance benchmarks met
|
|
238
|
+
|
|
239
|
+
### Business Metrics
|
|
240
|
+
- **Developer Adoption**: Measurable NPM downloads
|
|
241
|
+
- **Integration Success**: Working implementations in production
|
|
242
|
+
- **Performance Goals**: Sub-2-second form rendering
|
|
243
|
+
- **Error Rates**: <1% form submission failures
|
|
244
|
+
|
|
245
|
+
## Constraints & Assumptions
|
|
246
|
+
|
|
247
|
+
### Technical Constraints
|
|
248
|
+
- No external dependencies allowed
|
|
249
|
+
- Must work in iframe sandboxes
|
|
250
|
+
- File handling delegated to integrating application
|
|
251
|
+
- Cannot make direct network requests (CORS limitations)
|
|
252
|
+
|
|
253
|
+
### Business Constraints
|
|
254
|
+
- Open source MIT license
|
|
255
|
+
- Community-driven development
|
|
256
|
+
- GitHub-only deployment pipeline
|
|
257
|
+
- No specific backend requirements
|
|
258
|
+
|
|
259
|
+
### Assumptions
|
|
260
|
+
- Integrating applications handle file storage
|
|
261
|
+
- Modern browser environment (ES6+ support)
|
|
262
|
+
- Developers familiar with JSON Schema concepts
|
|
263
|
+
- Basic understanding of iframe communication
|
|
264
|
+
|
|
265
|
+
## Future Considerations
|
|
266
|
+
|
|
267
|
+
### Potential Enhancements
|
|
268
|
+
- Conditional field logic (show/hide based on values)
|
|
269
|
+
- Custom field type plugins
|
|
270
|
+
- Advanced file processing (image cropping, etc.)
|
|
271
|
+
- Internationalization support
|
|
272
|
+
- Real-time collaboration features
|
|
273
|
+
|
|
274
|
+
### Not In Scope
|
|
275
|
+
- Backend file storage implementation
|
|
276
|
+
- Database integration
|
|
277
|
+
- User authentication/authorization
|
|
278
|
+
- Advanced form analytics
|
|
279
|
+
- Multi-page form wizards
|
|
280
|
+
|
|
281
|
+
This requirements document defines the core functionality and quality standards for the Form Builder library, ensuring it meets both current needs and provides a foundation for future growth.
|
|
@@ -0,0 +1,445 @@
|
|
|
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 src="https://picazru.github.io/form-builder/dist/index.html"
|
|
11
|
+
width="100%" height="600px" frameborder="0"></iframe>
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
### With Custom Schema
|
|
15
|
+
|
|
16
|
+
```html
|
|
17
|
+
<iframe src="https://picazru.github.io/form-builder/dist/index.html?schema=BASE64_SCHEMA"
|
|
18
|
+
width="100%" height="600px"></iframe>
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
**Encoding Schema:**
|
|
22
|
+
```javascript
|
|
23
|
+
const schema = { version: "0.3", title: "My Form", elements: [...] };
|
|
24
|
+
const encodedSchema = btoa(JSON.stringify(schema));
|
|
25
|
+
const url = `https://picazru.github.io/form-builder/dist/index.html?schema=${encodedSchema}`;
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## NPM Integration
|
|
29
|
+
|
|
30
|
+
### Installation
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npm install @dmitryvim/form-builder
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Direct HTML Integration
|
|
37
|
+
|
|
38
|
+
Copy the form builder HTML directly into your application:
|
|
39
|
+
|
|
40
|
+
```javascript
|
|
41
|
+
import formBuilderHTML from '@dmitryvim/form-builder/dist/index.html';
|
|
42
|
+
|
|
43
|
+
// Insert into your page
|
|
44
|
+
document.getElementById('form-container').innerHTML = formBuilderHTML;
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Configuration
|
|
48
|
+
|
|
49
|
+
### File Upload Handler
|
|
50
|
+
|
|
51
|
+
The upload handler **must return a resource ID** that can be used for downloads and form submission:
|
|
52
|
+
|
|
53
|
+
```javascript
|
|
54
|
+
window.addEventListener('message', (event) => {
|
|
55
|
+
if (event.origin !== 'https://picazru.github.io') return;
|
|
56
|
+
|
|
57
|
+
if (event.data.type === 'formBuilderReady') {
|
|
58
|
+
const iframe = document.getElementById('formBuilder');
|
|
59
|
+
iframe.contentWindow.postMessage({
|
|
60
|
+
type: 'configure',
|
|
61
|
+
config: {
|
|
62
|
+
uploadHandler: async (file) => {
|
|
63
|
+
const formData = new FormData();
|
|
64
|
+
formData.append('file', file);
|
|
65
|
+
|
|
66
|
+
const response = await fetch('/api/upload', {
|
|
67
|
+
method: 'POST',
|
|
68
|
+
body: formData
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
const result = await response.json();
|
|
72
|
+
return result.resourceId; // Return ID, not URL
|
|
73
|
+
},
|
|
74
|
+
downloadHandler: async (resourceId) => {
|
|
75
|
+
window.open(`/api/download/${resourceId}`, '_blank');
|
|
76
|
+
},
|
|
77
|
+
thumbnailHandler: async (resourceId) => {
|
|
78
|
+
return `/api/thumbnail/${resourceId}`;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}, 'https://picazru.github.io');
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Read-Only Mode
|
|
87
|
+
|
|
88
|
+
Display form data without editing capabilities:
|
|
89
|
+
|
|
90
|
+
```javascript
|
|
91
|
+
iframe.contentWindow.postMessage({
|
|
92
|
+
type: 'configure',
|
|
93
|
+
options: {
|
|
94
|
+
readonly: true
|
|
95
|
+
}
|
|
96
|
+
}, 'https://picazru.github.io');
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Tailwind CSS Integration
|
|
100
|
+
|
|
101
|
+
Always uses Tailwind CSS styling. Add to your CSS:
|
|
102
|
+
|
|
103
|
+
```css
|
|
104
|
+
/* Custom properties for consistent styling */
|
|
105
|
+
:root {
|
|
106
|
+
--form-primary: 59 130 246; /* Blue */
|
|
107
|
+
--form-secondary: 100 116 139; /* Gray */
|
|
108
|
+
--form-accent: 16 185 129; /* Green */
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/* Override form builder styles if needed */
|
|
112
|
+
.form-builder-container {
|
|
113
|
+
@apply max-w-none; /* Remove max-width constraints */
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Events
|
|
118
|
+
|
|
119
|
+
### Form Submission
|
|
120
|
+
|
|
121
|
+
Listen for form submissions:
|
|
122
|
+
|
|
123
|
+
```javascript
|
|
124
|
+
window.addEventListener('message', (event) => {
|
|
125
|
+
if (event.data.type === 'formSubmit') {
|
|
126
|
+
const { data, schema } = event.data;
|
|
127
|
+
console.log('Form submitted:', data);
|
|
128
|
+
|
|
129
|
+
// Handle the submission
|
|
130
|
+
handleFormSubmission(data);
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Draft Saving
|
|
136
|
+
|
|
137
|
+
Listen for draft save events:
|
|
138
|
+
|
|
139
|
+
```javascript
|
|
140
|
+
window.addEventListener('message', (event) => {
|
|
141
|
+
if (event.data.type === 'draftSave') {
|
|
142
|
+
const { data, schema } = event.data;
|
|
143
|
+
console.log('Draft saved:', data);
|
|
144
|
+
|
|
145
|
+
// Save draft without validation
|
|
146
|
+
saveDraft(data);
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## API Communication
|
|
152
|
+
|
|
153
|
+
### Send Schema
|
|
154
|
+
|
|
155
|
+
```javascript
|
|
156
|
+
iframe.contentWindow.postMessage({
|
|
157
|
+
type: 'setSchema',
|
|
158
|
+
schema: {
|
|
159
|
+
version: "0.3",
|
|
160
|
+
title: "Contact Form",
|
|
161
|
+
elements: [...]
|
|
162
|
+
}
|
|
163
|
+
}, 'https://picazru.github.io');
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Prefill Form Data
|
|
167
|
+
|
|
168
|
+
```javascript
|
|
169
|
+
iframe.contentWindow.postMessage({
|
|
170
|
+
type: 'setData',
|
|
171
|
+
data: {
|
|
172
|
+
name: "John Doe",
|
|
173
|
+
email: "john@example.com"
|
|
174
|
+
}
|
|
175
|
+
}, 'https://picazru.github.io');
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Get Current Data
|
|
179
|
+
|
|
180
|
+
```javascript
|
|
181
|
+
// Request data
|
|
182
|
+
iframe.contentWindow.postMessage({
|
|
183
|
+
type: 'getData'
|
|
184
|
+
}, 'https://picazru.github.io');
|
|
185
|
+
|
|
186
|
+
// Listen for response
|
|
187
|
+
window.addEventListener('message', (event) => {
|
|
188
|
+
if (event.data.type === 'currentData') {
|
|
189
|
+
console.log('Current form data:', event.data.data);
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### Validate Form
|
|
195
|
+
|
|
196
|
+
```javascript
|
|
197
|
+
// Request validation
|
|
198
|
+
iframe.contentWindow.postMessage({
|
|
199
|
+
type: 'validate'
|
|
200
|
+
}, 'https://picazru.github.io');
|
|
201
|
+
|
|
202
|
+
// Listen for result
|
|
203
|
+
window.addEventListener('message', (event) => {
|
|
204
|
+
if (event.data.type === 'validationResult') {
|
|
205
|
+
console.log('Form is valid:', event.data.isValid);
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
## Backend Integration
|
|
211
|
+
|
|
212
|
+
### File Upload Endpoint
|
|
213
|
+
|
|
214
|
+
Your backend must handle file uploads and return resource IDs:
|
|
215
|
+
|
|
216
|
+
```javascript
|
|
217
|
+
// Express.js example
|
|
218
|
+
app.post('/api/upload', upload.single('file'), (req, res) => {
|
|
219
|
+
const file = req.file;
|
|
220
|
+
|
|
221
|
+
// Store file (S3, local storage, etc.)
|
|
222
|
+
const resourceId = generateResourceId();
|
|
223
|
+
storeFile(resourceId, file);
|
|
224
|
+
|
|
225
|
+
res.json({
|
|
226
|
+
resourceId: resourceId,
|
|
227
|
+
filename: file.originalname,
|
|
228
|
+
size: file.size,
|
|
229
|
+
mimetype: file.mimetype
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### File Download Endpoint
|
|
235
|
+
|
|
236
|
+
```javascript
|
|
237
|
+
app.get('/api/download/:resourceId', (req, res) => {
|
|
238
|
+
const { resourceId } = req.params;
|
|
239
|
+
|
|
240
|
+
// Retrieve file info
|
|
241
|
+
const fileInfo = getFileInfo(resourceId);
|
|
242
|
+
if (!fileInfo) {
|
|
243
|
+
return res.status(404).json({ error: 'File not found' });
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Stream file to client
|
|
247
|
+
const fileStream = getFileStream(resourceId);
|
|
248
|
+
res.setHeader('Content-Disposition', `attachment; filename="${fileInfo.filename}"`);
|
|
249
|
+
res.setHeader('Content-Type', fileInfo.mimetype);
|
|
250
|
+
fileStream.pipe(res);
|
|
251
|
+
});
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### Form Submission Handler
|
|
255
|
+
|
|
256
|
+
```javascript
|
|
257
|
+
app.post('/api/forms/submit', (req, res) => {
|
|
258
|
+
const { schema, data } = req.body;
|
|
259
|
+
|
|
260
|
+
// Process form data
|
|
261
|
+
// File fields will contain resource IDs
|
|
262
|
+
|
|
263
|
+
console.log('Received form:', data);
|
|
264
|
+
// Example: { name: "John", avatar: "res_abc123", documents: ["res_def456", "res_ghi789"] }
|
|
265
|
+
|
|
266
|
+
// Validate and save
|
|
267
|
+
const result = processFormSubmission(schema, data);
|
|
268
|
+
|
|
269
|
+
res.json({ success: true, id: result.id });
|
|
270
|
+
});
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
## Framework-Specific Examples
|
|
274
|
+
|
|
275
|
+
### React Integration
|
|
276
|
+
|
|
277
|
+
```jsx
|
|
278
|
+
import { useEffect, useRef } from 'react';
|
|
279
|
+
|
|
280
|
+
function FormBuilder({ schema, onSubmit }) {
|
|
281
|
+
const iframeRef = useRef(null);
|
|
282
|
+
|
|
283
|
+
useEffect(() => {
|
|
284
|
+
const handleMessage = (event) => {
|
|
285
|
+
if (event.data.type === 'formBuilderReady') {
|
|
286
|
+
// Configure form builder
|
|
287
|
+
iframeRef.current.contentWindow.postMessage({
|
|
288
|
+
type: 'setSchema',
|
|
289
|
+
schema: schema
|
|
290
|
+
}, 'https://picazru.github.io');
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
if (event.data.type === 'formSubmit') {
|
|
294
|
+
onSubmit(event.data.data);
|
|
295
|
+
}
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
window.addEventListener('message', handleMessage);
|
|
299
|
+
return () => window.removeEventListener('message', handleMessage);
|
|
300
|
+
}, [schema, onSubmit]);
|
|
301
|
+
|
|
302
|
+
return (
|
|
303
|
+
<iframe
|
|
304
|
+
ref={iframeRef}
|
|
305
|
+
src="https://picazru.github.io/form-builder/dist/index.html"
|
|
306
|
+
width="100%"
|
|
307
|
+
height="600px"
|
|
308
|
+
frameBorder="0"
|
|
309
|
+
/>
|
|
310
|
+
);
|
|
311
|
+
}
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### Vue.js Integration
|
|
315
|
+
|
|
316
|
+
```vue
|
|
317
|
+
<template>
|
|
318
|
+
<iframe
|
|
319
|
+
ref="formBuilder"
|
|
320
|
+
src="https://picazru.github.io/form-builder/dist/index.html"
|
|
321
|
+
width="100%"
|
|
322
|
+
height="600px"
|
|
323
|
+
frameborder="0"
|
|
324
|
+
@load="onIframeLoad"
|
|
325
|
+
/>
|
|
326
|
+
</template>
|
|
327
|
+
|
|
328
|
+
<script>
|
|
329
|
+
export default {
|
|
330
|
+
props: ['schema'],
|
|
331
|
+
|
|
332
|
+
mounted() {
|
|
333
|
+
window.addEventListener('message', this.handleMessage);
|
|
334
|
+
},
|
|
335
|
+
|
|
336
|
+
beforeUnmount() {
|
|
337
|
+
window.removeEventListener('message', this.handleMessage);
|
|
338
|
+
},
|
|
339
|
+
|
|
340
|
+
methods: {
|
|
341
|
+
handleMessage(event) {
|
|
342
|
+
if (event.data.type === 'formBuilderReady') {
|
|
343
|
+
this.$refs.formBuilder.contentWindow.postMessage({
|
|
344
|
+
type: 'setSchema',
|
|
345
|
+
schema: this.schema
|
|
346
|
+
}, 'https://picazru.github.io');
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
if (event.data.type === 'formSubmit') {
|
|
350
|
+
this.$emit('submit', event.data.data);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
};
|
|
355
|
+
</script>
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
## Security Considerations
|
|
359
|
+
|
|
360
|
+
### Origin Validation
|
|
361
|
+
|
|
362
|
+
Always validate message origins:
|
|
363
|
+
|
|
364
|
+
```javascript
|
|
365
|
+
window.addEventListener('message', (event) => {
|
|
366
|
+
// Only accept messages from form builder origin
|
|
367
|
+
if (event.origin !== 'https://picazru.github.io') {
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// Process message...
|
|
372
|
+
});
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
### File Upload Security
|
|
376
|
+
|
|
377
|
+
- **Validate file types** on server
|
|
378
|
+
- **Limit file sizes** appropriately
|
|
379
|
+
- **Scan for viruses** if possible
|
|
380
|
+
- **Use secure file storage** (S3 with proper permissions)
|
|
381
|
+
- **Generate secure resource IDs** (UUID, crypto.randomUUID())
|
|
382
|
+
|
|
383
|
+
### Content Security Policy
|
|
384
|
+
|
|
385
|
+
Add to your CSP headers:
|
|
386
|
+
|
|
387
|
+
```
|
|
388
|
+
Content-Security-Policy:
|
|
389
|
+
default-src 'self';
|
|
390
|
+
frame-src https://picazru.github.io;
|
|
391
|
+
connect-src 'self' https://your-api.com;
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
## Troubleshooting
|
|
395
|
+
|
|
396
|
+
### Common Issues
|
|
397
|
+
|
|
398
|
+
**Form builder not loading**: Check CSP settings and iframe src URL
|
|
399
|
+
|
|
400
|
+
**File uploads failing**: Verify upload handler returns resource ID, not URL
|
|
401
|
+
|
|
402
|
+
**Messages not working**: Confirm origin validation and message format
|
|
403
|
+
|
|
404
|
+
**Schema not applying**: Check schema format against [Schema Reference](schema.md)
|
|
405
|
+
|
|
406
|
+
### Debugging
|
|
407
|
+
|
|
408
|
+
Enable console logging in iframe:
|
|
409
|
+
|
|
410
|
+
```javascript
|
|
411
|
+
iframe.contentWindow.postMessage({
|
|
412
|
+
type: 'configure',
|
|
413
|
+
config: {
|
|
414
|
+
debug: true
|
|
415
|
+
}
|
|
416
|
+
}, 'https://picazru.github.io');
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
This will log all form builder events to the browser console.
|
|
420
|
+
|
|
421
|
+
## Migration
|
|
422
|
+
|
|
423
|
+
### From v0.1.x to v0.2.x
|
|
424
|
+
|
|
425
|
+
- Upload handlers must return resource IDs instead of URLs
|
|
426
|
+
- Added support for draft saving
|
|
427
|
+
- Improved Tailwind CSS integration
|
|
428
|
+
|
|
429
|
+
### Updating Handlers
|
|
430
|
+
|
|
431
|
+
```javascript
|
|
432
|
+
// Old (v0.1.x)
|
|
433
|
+
uploadHandler: async (file) => {
|
|
434
|
+
// ... upload logic
|
|
435
|
+
return result.fileUrl; // URL
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
// New (v0.2.x)
|
|
439
|
+
uploadHandler: async (file) => {
|
|
440
|
+
// ... upload logic
|
|
441
|
+
return result.resourceId; // ID
|
|
442
|
+
}
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
This integration guide covers all aspects of using Form Builder in production applications.
|