@dmitryvim/form-builder 0.1.42 → 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.
- package/README.md +244 -22
- package/dist/browser/formbuilder.min.js +179 -0
- package/dist/browser/formbuilder.v0.2.0.min.js +179 -0
- package/dist/cjs/index.cjs +3582 -0
- package/dist/cjs/index.cjs.map +1 -0
- package/dist/esm/index.js +3534 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/form-builder.js +152 -3372
- 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 +44 -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/dist/elements.js
DELETED
|
@@ -1,488 +0,0 @@
|
|
|
1
|
-
// Elements Documentation Page Logic
|
|
2
|
-
|
|
3
|
-
// Initialize FormBuilder with demo handlers
|
|
4
|
-
function initializeFormBuilder() {
|
|
5
|
-
// Simple in-memory file storage for demo
|
|
6
|
-
const fileStorage = new Map();
|
|
7
|
-
let fileCounter = 0;
|
|
8
|
-
|
|
9
|
-
// Mock upload handler
|
|
10
|
-
FormBuilder.setUploadHandler(async (file) => {
|
|
11
|
-
const resourceId = `file-${++fileCounter}`;
|
|
12
|
-
const fileUrl = URL.createObjectURL(file);
|
|
13
|
-
|
|
14
|
-
fileStorage.set(resourceId, {
|
|
15
|
-
file,
|
|
16
|
-
url: fileUrl,
|
|
17
|
-
name: file.name,
|
|
18
|
-
type: file.type,
|
|
19
|
-
size: file.size,
|
|
20
|
-
uploadDate: new Date().toISOString(),
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
return resourceId;
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
// Mock download handler
|
|
27
|
-
FormBuilder.setDownloadHandler((resourceId, fileName) => {
|
|
28
|
-
const fileData = fileStorage.get(resourceId);
|
|
29
|
-
if (fileData && fileData.url) {
|
|
30
|
-
const a = document.createElement("a");
|
|
31
|
-
a.href = fileData.url;
|
|
32
|
-
a.download = fileName || fileData.name;
|
|
33
|
-
document.body.appendChild(a);
|
|
34
|
-
a.click();
|
|
35
|
-
document.body.removeChild(a);
|
|
36
|
-
}
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
// Mock thumbnail handler
|
|
40
|
-
FormBuilder.setThumbnailHandler((resourceId) => {
|
|
41
|
-
const fileData = fileStorage.get(resourceId);
|
|
42
|
-
return fileData ? fileData.url : null;
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
// Mock action handler
|
|
46
|
-
FormBuilder.setActionHandler((actionValue) => {
|
|
47
|
-
alert(`Action triggered: ${actionValue}`);
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// Element data and demo schemas
|
|
52
|
-
const elementSchemas = {
|
|
53
|
-
text: {
|
|
54
|
-
schema: {
|
|
55
|
-
version: "0.3",
|
|
56
|
-
elements: [
|
|
57
|
-
{
|
|
58
|
-
type: "text",
|
|
59
|
-
key: "username",
|
|
60
|
-
label: "Username",
|
|
61
|
-
placeholder: "Enter your username",
|
|
62
|
-
required: true,
|
|
63
|
-
minLength: 3,
|
|
64
|
-
maxLength: 20,
|
|
65
|
-
pattern: "^[a-zA-Z0-9_]+$",
|
|
66
|
-
description:
|
|
67
|
-
"Username must be 3-20 characters, alphanumeric and underscore only",
|
|
68
|
-
default: "",
|
|
69
|
-
actions: [
|
|
70
|
-
{
|
|
71
|
-
value: "check_availability",
|
|
72
|
-
label: "Check Availability",
|
|
73
|
-
},
|
|
74
|
-
],
|
|
75
|
-
},
|
|
76
|
-
],
|
|
77
|
-
},
|
|
78
|
-
prefill: { username: "john_doe" },
|
|
79
|
-
},
|
|
80
|
-
|
|
81
|
-
"text-multiple": {
|
|
82
|
-
schema: {
|
|
83
|
-
version: "0.3",
|
|
84
|
-
elements: [
|
|
85
|
-
{
|
|
86
|
-
type: "text",
|
|
87
|
-
key: "keywords",
|
|
88
|
-
label: "Keywords",
|
|
89
|
-
placeholder: "Enter keyword",
|
|
90
|
-
required: true,
|
|
91
|
-
multiple: true,
|
|
92
|
-
minCount: 2,
|
|
93
|
-
maxCount: 5,
|
|
94
|
-
minLength: 2,
|
|
95
|
-
maxLength: 30,
|
|
96
|
-
description:
|
|
97
|
-
"Add multiple keywords, minimum 2 required, maximum 5 allowed",
|
|
98
|
-
default: "example",
|
|
99
|
-
},
|
|
100
|
-
],
|
|
101
|
-
},
|
|
102
|
-
prefill: { keywords: ["javascript", "react", "nodejs"] },
|
|
103
|
-
},
|
|
104
|
-
|
|
105
|
-
textarea: {
|
|
106
|
-
schema: {
|
|
107
|
-
version: "0.3",
|
|
108
|
-
elements: [
|
|
109
|
-
{
|
|
110
|
-
type: "textarea",
|
|
111
|
-
key: "description",
|
|
112
|
-
label: "Description",
|
|
113
|
-
placeholder: "Enter detailed description...",
|
|
114
|
-
rows: 6,
|
|
115
|
-
required: false,
|
|
116
|
-
minLength: 10,
|
|
117
|
-
maxLength: 500,
|
|
118
|
-
description: "Provide a detailed description of your project",
|
|
119
|
-
},
|
|
120
|
-
],
|
|
121
|
-
},
|
|
122
|
-
prefill: {
|
|
123
|
-
description:
|
|
124
|
-
"This is a sample project description that demonstrates the textarea field with multiple lines of text.",
|
|
125
|
-
},
|
|
126
|
-
},
|
|
127
|
-
|
|
128
|
-
"textarea-multiple": {
|
|
129
|
-
schema: {
|
|
130
|
-
version: "0.3",
|
|
131
|
-
elements: [
|
|
132
|
-
{
|
|
133
|
-
type: "textarea",
|
|
134
|
-
key: "features",
|
|
135
|
-
label: "Product Features",
|
|
136
|
-
placeholder: "Describe a feature...",
|
|
137
|
-
rows: 4,
|
|
138
|
-
required: true,
|
|
139
|
-
multiple: true,
|
|
140
|
-
minCount: 2,
|
|
141
|
-
maxCount: 4,
|
|
142
|
-
minLength: 20,
|
|
143
|
-
maxLength: 200,
|
|
144
|
-
description: "List key product features, minimum 2 required",
|
|
145
|
-
},
|
|
146
|
-
],
|
|
147
|
-
},
|
|
148
|
-
prefill: {
|
|
149
|
-
features: [
|
|
150
|
-
"High-quality materials ensure durability and long-lasting performance",
|
|
151
|
-
"User-friendly interface makes it easy to operate for all skill levels",
|
|
152
|
-
],
|
|
153
|
-
},
|
|
154
|
-
},
|
|
155
|
-
|
|
156
|
-
number: {
|
|
157
|
-
schema: {
|
|
158
|
-
version: "0.3",
|
|
159
|
-
elements: [
|
|
160
|
-
{
|
|
161
|
-
type: "number",
|
|
162
|
-
key: "price",
|
|
163
|
-
label: "Price (USD)",
|
|
164
|
-
placeholder: "0.00",
|
|
165
|
-
required: true,
|
|
166
|
-
min: 0,
|
|
167
|
-
max: 10000,
|
|
168
|
-
step: 0.01,
|
|
169
|
-
default: 99.99,
|
|
170
|
-
description: "Product price in US dollars",
|
|
171
|
-
},
|
|
172
|
-
],
|
|
173
|
-
},
|
|
174
|
-
prefill: { price: 149.99 },
|
|
175
|
-
},
|
|
176
|
-
|
|
177
|
-
"number-multiple": {
|
|
178
|
-
schema: {
|
|
179
|
-
version: "0.3",
|
|
180
|
-
elements: [
|
|
181
|
-
{
|
|
182
|
-
type: "number",
|
|
183
|
-
key: "dimensions",
|
|
184
|
-
label: "Dimensions (cm)",
|
|
185
|
-
placeholder: "0.0",
|
|
186
|
-
required: true,
|
|
187
|
-
multiple: true,
|
|
188
|
-
minCount: 2,
|
|
189
|
-
maxCount: 3,
|
|
190
|
-
min: 0.1,
|
|
191
|
-
max: 500,
|
|
192
|
-
step: 0.1,
|
|
193
|
-
decimals: 1,
|
|
194
|
-
default: 10.0,
|
|
195
|
-
description:
|
|
196
|
-
"Enter product dimensions: width, height, and optionally depth",
|
|
197
|
-
},
|
|
198
|
-
],
|
|
199
|
-
},
|
|
200
|
-
prefill: { dimensions: [25.5, 30.0, 15.2] },
|
|
201
|
-
},
|
|
202
|
-
|
|
203
|
-
select: {
|
|
204
|
-
schema: {
|
|
205
|
-
version: "0.3",
|
|
206
|
-
elements: [
|
|
207
|
-
{
|
|
208
|
-
type: "select",
|
|
209
|
-
key: "category",
|
|
210
|
-
label: "Product Category",
|
|
211
|
-
required: true,
|
|
212
|
-
options: [
|
|
213
|
-
{ value: "electronics", label: "Electronics" },
|
|
214
|
-
{ value: "clothing", label: "Clothing & Apparel" },
|
|
215
|
-
{ value: "books", label: "Books & Media" },
|
|
216
|
-
{ value: "home", label: "Home & Garden" },
|
|
217
|
-
{ value: "sports", label: "Sports & Recreation" },
|
|
218
|
-
],
|
|
219
|
-
default: "electronics",
|
|
220
|
-
description: "Select the primary category for your product",
|
|
221
|
-
},
|
|
222
|
-
],
|
|
223
|
-
},
|
|
224
|
-
prefill: { category: "books" },
|
|
225
|
-
},
|
|
226
|
-
|
|
227
|
-
"select-multiple": {
|
|
228
|
-
schema: {
|
|
229
|
-
version: "0.3",
|
|
230
|
-
elements: [
|
|
231
|
-
{
|
|
232
|
-
type: "select",
|
|
233
|
-
key: "tags",
|
|
234
|
-
label: "Product Tags",
|
|
235
|
-
required: true,
|
|
236
|
-
multiple: true,
|
|
237
|
-
minCount: 1,
|
|
238
|
-
maxCount: 3,
|
|
239
|
-
options: [
|
|
240
|
-
{ value: "new", label: "New" },
|
|
241
|
-
{ value: "popular", label: "Popular" },
|
|
242
|
-
{ value: "sale", label: "On Sale" },
|
|
243
|
-
{ value: "featured", label: "Featured" },
|
|
244
|
-
{ value: "limited", label: "Limited Edition" },
|
|
245
|
-
{ value: "bestseller", label: "Bestseller" },
|
|
246
|
-
],
|
|
247
|
-
default: "new",
|
|
248
|
-
description:
|
|
249
|
-
"Select relevant tags for the product, maximum 3 allowed",
|
|
250
|
-
},
|
|
251
|
-
],
|
|
252
|
-
},
|
|
253
|
-
prefill: { tags: ["popular", "featured"] },
|
|
254
|
-
},
|
|
255
|
-
|
|
256
|
-
file: {
|
|
257
|
-
schema: {
|
|
258
|
-
version: "0.3",
|
|
259
|
-
elements: [
|
|
260
|
-
{
|
|
261
|
-
type: "file",
|
|
262
|
-
key: "avatar",
|
|
263
|
-
label: "Profile Picture",
|
|
264
|
-
required: false,
|
|
265
|
-
accept: {
|
|
266
|
-
extensions: ["jpg", "jpeg", "png", "gif", "webp"],
|
|
267
|
-
maxSize: 5242880,
|
|
268
|
-
},
|
|
269
|
-
description: "Upload your profile picture (max 5MB, images only)",
|
|
270
|
-
},
|
|
271
|
-
],
|
|
272
|
-
},
|
|
273
|
-
prefill: { avatar: null },
|
|
274
|
-
},
|
|
275
|
-
|
|
276
|
-
files: {
|
|
277
|
-
schema: {
|
|
278
|
-
version: "0.3",
|
|
279
|
-
elements: [
|
|
280
|
-
{
|
|
281
|
-
type: "files",
|
|
282
|
-
key: "attachments",
|
|
283
|
-
label: "Project Attachments",
|
|
284
|
-
required: false,
|
|
285
|
-
min: 1,
|
|
286
|
-
max: 10,
|
|
287
|
-
accept: {
|
|
288
|
-
extensions: ["jpg", "png", "pdf", "doc", "docx", "mp4"],
|
|
289
|
-
maxSize: 10485760,
|
|
290
|
-
},
|
|
291
|
-
description: "Upload project files (max 10MB each, 1-10 files)",
|
|
292
|
-
},
|
|
293
|
-
],
|
|
294
|
-
},
|
|
295
|
-
prefill: { attachments: [] },
|
|
296
|
-
},
|
|
297
|
-
|
|
298
|
-
group: {
|
|
299
|
-
schema: {
|
|
300
|
-
version: "0.3",
|
|
301
|
-
elements: [
|
|
302
|
-
{
|
|
303
|
-
type: "group",
|
|
304
|
-
key: "contacts",
|
|
305
|
-
label: "Contact Information",
|
|
306
|
-
repeat: {
|
|
307
|
-
min: 1,
|
|
308
|
-
max: 5,
|
|
309
|
-
},
|
|
310
|
-
elements: [
|
|
311
|
-
{
|
|
312
|
-
type: "text",
|
|
313
|
-
key: "name",
|
|
314
|
-
label: "Contact Name",
|
|
315
|
-
required: true,
|
|
316
|
-
},
|
|
317
|
-
{
|
|
318
|
-
type: "text",
|
|
319
|
-
key: "email",
|
|
320
|
-
label: "Email Address",
|
|
321
|
-
required: true,
|
|
322
|
-
pattern: "^[^@]+@[^@]+\\.[^@]+$",
|
|
323
|
-
},
|
|
324
|
-
{
|
|
325
|
-
type: "select",
|
|
326
|
-
key: "role",
|
|
327
|
-
label: "Role",
|
|
328
|
-
options: [
|
|
329
|
-
{ value: "primary", label: "Primary Contact" },
|
|
330
|
-
{ value: "secondary", label: "Secondary Contact" },
|
|
331
|
-
{ value: "technical", label: "Technical Contact" },
|
|
332
|
-
],
|
|
333
|
-
default: "primary",
|
|
334
|
-
},
|
|
335
|
-
],
|
|
336
|
-
description: "Add contact information for your project",
|
|
337
|
-
},
|
|
338
|
-
],
|
|
339
|
-
},
|
|
340
|
-
prefill: {
|
|
341
|
-
contacts: [
|
|
342
|
-
{ name: "John Smith", email: "john@company.com", role: "primary" },
|
|
343
|
-
{ name: "Jane Doe", email: "jane@company.com", role: "technical" },
|
|
344
|
-
],
|
|
345
|
-
},
|
|
346
|
-
},
|
|
347
|
-
};
|
|
348
|
-
|
|
349
|
-
// Update preview for an element
|
|
350
|
-
function updatePreview(elementType) {
|
|
351
|
-
const elementData = elementSchemas[elementType];
|
|
352
|
-
if (!elementData) return;
|
|
353
|
-
|
|
354
|
-
const previewContainer = document.getElementById(`${elementType}-preview`);
|
|
355
|
-
const readonlyToggle = document.querySelector(
|
|
356
|
-
`input[data-element="${elementType}"]`,
|
|
357
|
-
);
|
|
358
|
-
|
|
359
|
-
if (!previewContainer) return;
|
|
360
|
-
|
|
361
|
-
// Set form root and mode
|
|
362
|
-
FormBuilder.setFormRoot(previewContainer);
|
|
363
|
-
FormBuilder.setMode(readonlyToggle?.checked ? "readonly" : "edit");
|
|
364
|
-
|
|
365
|
-
// Render the form
|
|
366
|
-
FormBuilder.renderForm(elementData.schema, elementData.prefill);
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
// Update schema textarea from element data
|
|
370
|
-
function updateSchemaTextarea(elementType) {
|
|
371
|
-
const elementData = elementSchemas[elementType];
|
|
372
|
-
const textarea = document.getElementById(`${elementType}-schema`);
|
|
373
|
-
|
|
374
|
-
if (elementData && textarea) {
|
|
375
|
-
textarea.value = JSON.stringify(elementData.schema.elements[0], null, 2);
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
// Apply schema changes from textarea
|
|
380
|
-
function applySchemaChanges(elementType) {
|
|
381
|
-
const textarea = document.getElementById(`${elementType}-schema`);
|
|
382
|
-
if (!textarea) return;
|
|
383
|
-
|
|
384
|
-
try {
|
|
385
|
-
const elementSchema = JSON.parse(textarea.value);
|
|
386
|
-
elementSchemas[elementType].schema.elements[0] = elementSchema;
|
|
387
|
-
updatePreview(elementType);
|
|
388
|
-
} catch (error) {
|
|
389
|
-
console.error("Invalid JSON in schema:", error);
|
|
390
|
-
// Reset to original if invalid
|
|
391
|
-
updateSchemaTextarea(elementType);
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
// Initialize navigation
|
|
396
|
-
function initializeNavigation() {
|
|
397
|
-
const navItems = document.querySelectorAll(".nav-item");
|
|
398
|
-
|
|
399
|
-
// Set initial active state
|
|
400
|
-
if (navItems.length > 0) {
|
|
401
|
-
navItems[0].classList.add("active");
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
navItems.forEach((item) => {
|
|
405
|
-
item.addEventListener("click", (e) => {
|
|
406
|
-
e.preventDefault();
|
|
407
|
-
|
|
408
|
-
// Remove active class from all items
|
|
409
|
-
navItems.forEach((nav) => nav.classList.remove("active"));
|
|
410
|
-
|
|
411
|
-
// Add active class to clicked item
|
|
412
|
-
item.classList.add("active");
|
|
413
|
-
|
|
414
|
-
// Scroll to element
|
|
415
|
-
const elementId = item.getAttribute("href").substring(1);
|
|
416
|
-
const element = document.getElementById(elementId);
|
|
417
|
-
if (element) {
|
|
418
|
-
element.scrollIntoView({ behavior: "smooth", block: "start" });
|
|
419
|
-
}
|
|
420
|
-
});
|
|
421
|
-
});
|
|
422
|
-
|
|
423
|
-
// Handle scroll-based active states
|
|
424
|
-
const sections = document.querySelectorAll(".element-section");
|
|
425
|
-
const observer = new IntersectionObserver(
|
|
426
|
-
(entries) => {
|
|
427
|
-
entries.forEach((entry) => {
|
|
428
|
-
if (entry.isIntersecting) {
|
|
429
|
-
const id = entry.target.id;
|
|
430
|
-
navItems.forEach((nav) => {
|
|
431
|
-
nav.classList.remove("active");
|
|
432
|
-
if (nav.getAttribute("href") === `#${id}`) {
|
|
433
|
-
nav.classList.add("active");
|
|
434
|
-
}
|
|
435
|
-
});
|
|
436
|
-
}
|
|
437
|
-
});
|
|
438
|
-
},
|
|
439
|
-
{
|
|
440
|
-
rootMargin: "-20% 0% -20% 0%",
|
|
441
|
-
threshold: 0.1,
|
|
442
|
-
},
|
|
443
|
-
);
|
|
444
|
-
|
|
445
|
-
sections.forEach((section) => {
|
|
446
|
-
observer.observe(section);
|
|
447
|
-
});
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
// Initialize all elements
|
|
451
|
-
function initializeElements() {
|
|
452
|
-
Object.keys(elementSchemas).forEach((elementType) => {
|
|
453
|
-
// Update textarea with schema
|
|
454
|
-
updateSchemaTextarea(elementType);
|
|
455
|
-
|
|
456
|
-
// Setup textarea change listener
|
|
457
|
-
const textarea = document.getElementById(`${elementType}-schema`);
|
|
458
|
-
if (textarea) {
|
|
459
|
-
let debounceTimer;
|
|
460
|
-
textarea.addEventListener("input", () => {
|
|
461
|
-
clearTimeout(debounceTimer);
|
|
462
|
-
debounceTimer = setTimeout(() => {
|
|
463
|
-
applySchemaChanges(elementType);
|
|
464
|
-
}, 1000); // 1 second delay
|
|
465
|
-
});
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
// Setup readonly toggle
|
|
469
|
-
const readonlyToggle = document.querySelector(
|
|
470
|
-
`input[data-element="${elementType}"]`,
|
|
471
|
-
);
|
|
472
|
-
if (readonlyToggle) {
|
|
473
|
-
readonlyToggle.addEventListener("change", () => {
|
|
474
|
-
updatePreview(elementType);
|
|
475
|
-
});
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
// Initial preview render
|
|
479
|
-
updatePreview(elementType);
|
|
480
|
-
});
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
// Initialize everything when DOM is loaded
|
|
484
|
-
document.addEventListener("DOMContentLoaded", () => {
|
|
485
|
-
initializeFormBuilder();
|
|
486
|
-
initializeNavigation();
|
|
487
|
-
initializeElements();
|
|
488
|
-
});
|