@dmitryvim/form-builder 0.1.35 → 0.1.37
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/dist/demo.js +164 -22
- package/dist/elements.html +588 -160
- package/dist/elements.js +270 -232
- package/dist/form-builder.js +261 -85
- package/dist/index.html +70 -20
- package/package.json +1 -1
package/dist/demo.js
CHANGED
|
@@ -113,7 +113,7 @@ const EXAMPLE_SCHEMA = {
|
|
|
113
113
|
maxCount: 5,
|
|
114
114
|
minLength: 2,
|
|
115
115
|
maxLength: 20,
|
|
116
|
-
default: "popular"
|
|
116
|
+
default: "popular",
|
|
117
117
|
},
|
|
118
118
|
{
|
|
119
119
|
type: "textarea",
|
|
@@ -127,13 +127,14 @@ const EXAMPLE_SCHEMA = {
|
|
|
127
127
|
maxCount: 4,
|
|
128
128
|
minLength: 10,
|
|
129
129
|
maxLength: 200,
|
|
130
|
-
rows: 3
|
|
130
|
+
rows: 3,
|
|
131
131
|
},
|
|
132
132
|
{
|
|
133
133
|
type: "number",
|
|
134
134
|
key: "dimensions",
|
|
135
135
|
label: "Размеры (см)",
|
|
136
|
-
description:
|
|
136
|
+
description:
|
|
137
|
+
"Укажите размеры товара в сантиметрах: длина, ширина, высота",
|
|
137
138
|
placeholder: "0",
|
|
138
139
|
required: false,
|
|
139
140
|
multiple: true,
|
|
@@ -142,7 +143,7 @@ const EXAMPLE_SCHEMA = {
|
|
|
142
143
|
min: 0,
|
|
143
144
|
max: 500,
|
|
144
145
|
step: 0.1,
|
|
145
|
-
decimals: 1
|
|
146
|
+
decimals: 1,
|
|
146
147
|
},
|
|
147
148
|
{
|
|
148
149
|
type: "select",
|
|
@@ -159,9 +160,9 @@ const EXAMPLE_SCHEMA = {
|
|
|
159
160
|
{ value: "red", label: "Красный" },
|
|
160
161
|
{ value: "blue", label: "Синий" },
|
|
161
162
|
{ value: "green", label: "Зеленый" },
|
|
162
|
-
{ value: "gray", label: "Серый" }
|
|
163
|
+
{ value: "gray", label: "Серый" },
|
|
163
164
|
],
|
|
164
|
-
default: "white"
|
|
165
|
+
default: "white",
|
|
165
166
|
},
|
|
166
167
|
{
|
|
167
168
|
type: "file",
|
|
@@ -214,7 +215,7 @@ const EXAMPLE_SCHEMA = {
|
|
|
214
215
|
label: "Session ID",
|
|
215
216
|
description: "Hidden session identifier for tracking purposes",
|
|
216
217
|
hidden: true,
|
|
217
|
-
default:
|
|
218
|
+
default: `session_${Math.random().toString(36).substr(2, 9)}`,
|
|
218
219
|
},
|
|
219
220
|
],
|
|
220
221
|
};
|
|
@@ -328,10 +329,10 @@ let actionLabelMap = new Map();
|
|
|
328
329
|
// Build action value -> label mapping from schema for efficient lookup
|
|
329
330
|
function buildActionLabelMap(schema) {
|
|
330
331
|
const map = new Map();
|
|
331
|
-
|
|
332
|
+
|
|
332
333
|
function processElements(elements) {
|
|
333
334
|
if (!Array.isArray(elements)) return;
|
|
334
|
-
|
|
335
|
+
|
|
335
336
|
for (const element of elements) {
|
|
336
337
|
if (element.actions && Array.isArray(element.actions)) {
|
|
337
338
|
for (const action of element.actions) {
|
|
@@ -340,18 +341,18 @@ function buildActionLabelMap(schema) {
|
|
|
340
341
|
}
|
|
341
342
|
}
|
|
342
343
|
}
|
|
343
|
-
|
|
344
|
+
|
|
344
345
|
// Process nested group elements
|
|
345
346
|
if (element.elements && Array.isArray(element.elements)) {
|
|
346
347
|
processElements(element.elements);
|
|
347
348
|
}
|
|
348
349
|
}
|
|
349
350
|
}
|
|
350
|
-
|
|
351
|
+
|
|
351
352
|
if (schema && schema.elements) {
|
|
352
353
|
processElements(schema.elements);
|
|
353
354
|
}
|
|
354
|
-
|
|
355
|
+
|
|
355
356
|
return map;
|
|
356
357
|
}
|
|
357
358
|
|
|
@@ -372,6 +373,10 @@ const el = {
|
|
|
372
373
|
copyDataBtn: document.getElementById("copyDataBtn"),
|
|
373
374
|
downloadDataBtn: document.getElementById("downloadDataBtn"),
|
|
374
375
|
dataErrors: document.getElementById("dataErrors"),
|
|
376
|
+
actionsTextarea: document.getElementById("actionsTextarea"),
|
|
377
|
+
formatActionsBtn: document.getElementById("formatActionsBtn"),
|
|
378
|
+
clearActionsBtn: document.getElementById("clearActionsBtn"),
|
|
379
|
+
actionsErrors: document.getElementById("actionsErrors"),
|
|
375
380
|
};
|
|
376
381
|
|
|
377
382
|
// Utility functions
|
|
@@ -405,6 +410,44 @@ function downloadFile(filename, content) {
|
|
|
405
410
|
URL.revokeObjectURL(url);
|
|
406
411
|
}
|
|
407
412
|
|
|
413
|
+
// Parse and validate external actions
|
|
414
|
+
function parseActions(actionsText) {
|
|
415
|
+
if (!actionsText || actionsText.trim() === "") {
|
|
416
|
+
return [];
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
try {
|
|
420
|
+
const actions = JSON.parse(actionsText);
|
|
421
|
+
|
|
422
|
+
if (!Array.isArray(actions)) {
|
|
423
|
+
throw new Error("Actions must be an array");
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
// Validate each action
|
|
427
|
+
for (let i = 0; i < actions.length; i++) {
|
|
428
|
+
const action = actions[i];
|
|
429
|
+
if (!action || typeof action !== "object") {
|
|
430
|
+
throw new Error(`Action at index ${i} must be an object`);
|
|
431
|
+
}
|
|
432
|
+
if (!action.related_field || typeof action.related_field !== "string") {
|
|
433
|
+
throw new Error(
|
|
434
|
+
`Action at index ${i} missing valid 'related_field' property`,
|
|
435
|
+
);
|
|
436
|
+
}
|
|
437
|
+
if (!action.value || typeof action.value !== "string") {
|
|
438
|
+
throw new Error(`Action at index ${i} missing valid 'value' property`);
|
|
439
|
+
}
|
|
440
|
+
if (!action.label || typeof action.label !== "string") {
|
|
441
|
+
throw new Error(`Action at index ${i} missing valid 'label' property`);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
return actions;
|
|
446
|
+
} catch (error) {
|
|
447
|
+
throw new Error(`Actions JSON error: ${error.message}`);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
|
|
408
451
|
// Configure FormBuilder with in-memory handlers
|
|
409
452
|
function setupFormBuilder() {
|
|
410
453
|
// Set form container
|
|
@@ -437,17 +480,44 @@ function setupFormBuilder() {
|
|
|
437
480
|
});
|
|
438
481
|
|
|
439
482
|
// Action handler - display message when action button is clicked
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
483
|
+
// Updated to support both old system (1 param) and new system (2 params)
|
|
484
|
+
FormBuilder.setActionHandler((relatedFieldOrValue, value) => {
|
|
485
|
+
let actionLabel, actionValue, relatedField;
|
|
486
|
+
|
|
487
|
+
// Determine if this is the old system (1 param) or new system (2 params)
|
|
488
|
+
if (arguments.length === 1) {
|
|
489
|
+
// Old system: only value parameter
|
|
490
|
+
actionValue = relatedFieldOrValue;
|
|
491
|
+
actionLabel = actionLabelMap.get(actionValue) || actionValue;
|
|
492
|
+
relatedField = null;
|
|
493
|
+
} else {
|
|
494
|
+
// New system: related_field and value parameters
|
|
495
|
+
relatedField = relatedFieldOrValue;
|
|
496
|
+
actionValue = value;
|
|
497
|
+
actionLabel = `Action for ${relatedField}`;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
console.log("Action clicked:", {
|
|
501
|
+
label: actionLabel,
|
|
502
|
+
value: actionValue,
|
|
503
|
+
relatedField,
|
|
504
|
+
system: arguments.length === 1 ? "schema-based" : "external",
|
|
505
|
+
});
|
|
443
506
|
|
|
444
|
-
console.log("Action clicked:", { label: actionLabel, value });
|
|
445
|
-
|
|
446
507
|
// Show message to user (compatible with all environments)
|
|
447
508
|
if (typeof window !== "undefined" && window.alert) {
|
|
448
|
-
|
|
509
|
+
if (relatedField) {
|
|
510
|
+
window.alert(
|
|
511
|
+
`External Action: "${actionLabel}" clicked for field "${relatedField}" with value: ${actionValue}`,
|
|
512
|
+
);
|
|
513
|
+
} else {
|
|
514
|
+
window.alert(`Schema Action: "${actionLabel}" clicked: ${actionValue}`);
|
|
515
|
+
}
|
|
449
516
|
} else {
|
|
450
|
-
console.log(
|
|
517
|
+
console.log(
|
|
518
|
+
`Demo action: ${actionLabel} clicked: ${actionValue}`,
|
|
519
|
+
relatedField ? ` for field: ${relatedField}` : "",
|
|
520
|
+
);
|
|
451
521
|
}
|
|
452
522
|
});
|
|
453
523
|
|
|
@@ -460,6 +530,7 @@ function setupFormBuilder() {
|
|
|
460
530
|
function applyCurrentSchema() {
|
|
461
531
|
clearError(el.schemaErrors);
|
|
462
532
|
clearError(el.formErrors);
|
|
533
|
+
clearError(el.actionsErrors);
|
|
463
534
|
|
|
464
535
|
try {
|
|
465
536
|
const schema = JSON.parse(el.schemaInput.value);
|
|
@@ -473,6 +544,15 @@ function applyCurrentSchema() {
|
|
|
473
544
|
return false;
|
|
474
545
|
}
|
|
475
546
|
|
|
547
|
+
// Parse external actions
|
|
548
|
+
let externalActions = [];
|
|
549
|
+
try {
|
|
550
|
+
externalActions = parseActions(el.actionsTextarea.value);
|
|
551
|
+
} catch (error) {
|
|
552
|
+
showError(el.actionsErrors, error.message);
|
|
553
|
+
return false;
|
|
554
|
+
}
|
|
555
|
+
|
|
476
556
|
// Build action value -> label map for efficient lookup
|
|
477
557
|
actionLabelMap = buildActionLabelMap(schema);
|
|
478
558
|
|
|
@@ -491,10 +571,12 @@ function applyCurrentSchema() {
|
|
|
491
571
|
// Ignore errors when getting current data
|
|
492
572
|
}
|
|
493
573
|
|
|
494
|
-
// Render form with current data
|
|
495
|
-
FormBuilder.renderForm(schema, currentData);
|
|
574
|
+
// Render form with current data and external actions
|
|
575
|
+
FormBuilder.renderForm(schema, currentData, externalActions);
|
|
496
576
|
|
|
497
577
|
console.log(`Form rendered in ${isReadOnly ? "readonly" : "edit"} mode`);
|
|
578
|
+
console.log(`External actions:`, externalActions);
|
|
579
|
+
|
|
498
580
|
return true;
|
|
499
581
|
} catch (e) {
|
|
500
582
|
showError(el.schemaErrors, `JSON parse error: ${e.message}`);
|
|
@@ -512,7 +594,9 @@ el.resetSchemaBtn.addEventListener("click", () => {
|
|
|
512
594
|
clearError(el.schemaErrors);
|
|
513
595
|
clearError(el.formErrors);
|
|
514
596
|
clearError(el.dataErrors);
|
|
597
|
+
clearError(el.actionsErrors);
|
|
515
598
|
el.dataTextarea.value = "";
|
|
599
|
+
el.actionsTextarea.value = "";
|
|
516
600
|
|
|
517
601
|
// Clear file storage
|
|
518
602
|
fileStorage.clear();
|
|
@@ -617,6 +701,15 @@ el.prefillBtn.addEventListener("click", () => {
|
|
|
617
701
|
const prefillData = JSON.parse(el.dataTextarea.value || "{}");
|
|
618
702
|
const currentSchema = JSON.parse(el.schemaInput.value);
|
|
619
703
|
|
|
704
|
+
// Parse external actions
|
|
705
|
+
let externalActions = [];
|
|
706
|
+
try {
|
|
707
|
+
externalActions = parseActions(el.actionsTextarea.value);
|
|
708
|
+
} catch (error) {
|
|
709
|
+
showError(el.actionsErrors, error.message);
|
|
710
|
+
return;
|
|
711
|
+
}
|
|
712
|
+
|
|
620
713
|
// Convert enhanced data back to raw format for prefilling
|
|
621
714
|
const processedData = JSON.parse(JSON.stringify(prefillData));
|
|
622
715
|
|
|
@@ -657,9 +750,10 @@ el.prefillBtn.addEventListener("click", () => {
|
|
|
657
750
|
const isReadOnly = el.readOnlyToggle.checked;
|
|
658
751
|
FormBuilder.setMode(isReadOnly ? "readonly" : "edit");
|
|
659
752
|
|
|
660
|
-
FormBuilder.renderForm(currentSchema, processedData);
|
|
753
|
+
FormBuilder.renderForm(currentSchema, processedData, externalActions);
|
|
661
754
|
console.log("Form prefilled with data");
|
|
662
755
|
console.log("Processed prefill data:", processedData);
|
|
756
|
+
console.log("External actions:", externalActions);
|
|
663
757
|
} catch (e) {
|
|
664
758
|
showError(el.dataErrors, `JSON parse error: ${e.message}`);
|
|
665
759
|
console.error("Prefill error:", e);
|
|
@@ -684,6 +778,51 @@ el.downloadDataBtn.addEventListener("click", () => {
|
|
|
684
778
|
console.log("Data downloaded");
|
|
685
779
|
});
|
|
686
780
|
|
|
781
|
+
// Actions management handlers
|
|
782
|
+
el.formatActionsBtn.addEventListener("click", () => {
|
|
783
|
+
try {
|
|
784
|
+
const actions = parseActions(el.actionsTextarea.value);
|
|
785
|
+
el.actionsTextarea.value = pretty(actions);
|
|
786
|
+
clearError(el.actionsErrors);
|
|
787
|
+
console.log("Actions formatted");
|
|
788
|
+
} catch (e) {
|
|
789
|
+
showError(el.actionsErrors, e.message);
|
|
790
|
+
console.error("Format actions error:", e);
|
|
791
|
+
}
|
|
792
|
+
});
|
|
793
|
+
|
|
794
|
+
el.clearActionsBtn.addEventListener("click", () => {
|
|
795
|
+
el.actionsTextarea.value = "";
|
|
796
|
+
clearError(el.actionsErrors);
|
|
797
|
+
// Re-apply schema to remove external actions from the form
|
|
798
|
+
applyCurrentSchema();
|
|
799
|
+
console.log("Actions cleared");
|
|
800
|
+
});
|
|
801
|
+
|
|
802
|
+
// Example external actions for demonstration
|
|
803
|
+
const EXAMPLE_ACTIONS = [
|
|
804
|
+
{
|
|
805
|
+
related_field: "title[0]",
|
|
806
|
+
value: "generate-title",
|
|
807
|
+
label: "🤖 Generate Title",
|
|
808
|
+
},
|
|
809
|
+
{
|
|
810
|
+
related_field: "description",
|
|
811
|
+
value: "improve-description",
|
|
812
|
+
label: "✨ Improve Description",
|
|
813
|
+
},
|
|
814
|
+
{
|
|
815
|
+
related_field: "slides[0].title",
|
|
816
|
+
value: "optimize-slide-title",
|
|
817
|
+
label: "🎯 Optimize Slide Title",
|
|
818
|
+
},
|
|
819
|
+
{
|
|
820
|
+
related_field: "cover",
|
|
821
|
+
value: "analyze-image",
|
|
822
|
+
label: "🔍 Analyze Image",
|
|
823
|
+
},
|
|
824
|
+
];
|
|
825
|
+
|
|
687
826
|
// Initialize demo application
|
|
688
827
|
function initDemo() {
|
|
689
828
|
// Set up FormBuilder
|
|
@@ -692,6 +831,9 @@ function initDemo() {
|
|
|
692
831
|
// Initialize with example schema
|
|
693
832
|
el.schemaInput.value = pretty(EXAMPLE_SCHEMA);
|
|
694
833
|
|
|
834
|
+
// Initialize with example actions
|
|
835
|
+
el.actionsTextarea.value = pretty(EXAMPLE_ACTIONS);
|
|
836
|
+
|
|
695
837
|
// Apply initial schema
|
|
696
838
|
applyCurrentSchema();
|
|
697
839
|
|