@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/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
- });