@dmitryvim/form-builder 0.1.34 → 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 +151 -10
- package/dist/elements.html +1 -22
- package/dist/elements.js +1 -1
- package/dist/form-builder.js +325 -621
- package/dist/index.html +66 -41
- package/package.json +3 -8
package/dist/demo.js
CHANGED
|
@@ -215,7 +215,7 @@ const EXAMPLE_SCHEMA = {
|
|
|
215
215
|
label: "Session ID",
|
|
216
216
|
description: "Hidden session identifier for tracking purposes",
|
|
217
217
|
hidden: true,
|
|
218
|
-
default:
|
|
218
|
+
default: `session_${Math.random().toString(36).substr(2, 9)}`,
|
|
219
219
|
},
|
|
220
220
|
],
|
|
221
221
|
};
|
|
@@ -373,6 +373,10 @@ const el = {
|
|
|
373
373
|
copyDataBtn: document.getElementById("copyDataBtn"),
|
|
374
374
|
downloadDataBtn: document.getElementById("downloadDataBtn"),
|
|
375
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"),
|
|
376
380
|
};
|
|
377
381
|
|
|
378
382
|
// Utility functions
|
|
@@ -406,6 +410,44 @@ function downloadFile(filename, content) {
|
|
|
406
410
|
URL.revokeObjectURL(url);
|
|
407
411
|
}
|
|
408
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
|
+
|
|
409
451
|
// Configure FormBuilder with in-memory handlers
|
|
410
452
|
function setupFormBuilder() {
|
|
411
453
|
// Set form container
|
|
@@ -438,17 +480,44 @@ function setupFormBuilder() {
|
|
|
438
480
|
});
|
|
439
481
|
|
|
440
482
|
// Action handler - display message when action button is clicked
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
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
|
+
}
|
|
444
499
|
|
|
445
|
-
console.log("Action clicked:", {
|
|
500
|
+
console.log("Action clicked:", {
|
|
501
|
+
label: actionLabel,
|
|
502
|
+
value: actionValue,
|
|
503
|
+
relatedField,
|
|
504
|
+
system: arguments.length === 1 ? "schema-based" : "external",
|
|
505
|
+
});
|
|
446
506
|
|
|
447
507
|
// Show message to user (compatible with all environments)
|
|
448
508
|
if (typeof window !== "undefined" && window.alert) {
|
|
449
|
-
|
|
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
|
+
}
|
|
450
516
|
} else {
|
|
451
|
-
console.log(
|
|
517
|
+
console.log(
|
|
518
|
+
`Demo action: ${actionLabel} clicked: ${actionValue}`,
|
|
519
|
+
relatedField ? ` for field: ${relatedField}` : "",
|
|
520
|
+
);
|
|
452
521
|
}
|
|
453
522
|
});
|
|
454
523
|
|
|
@@ -461,6 +530,7 @@ function setupFormBuilder() {
|
|
|
461
530
|
function applyCurrentSchema() {
|
|
462
531
|
clearError(el.schemaErrors);
|
|
463
532
|
clearError(el.formErrors);
|
|
533
|
+
clearError(el.actionsErrors);
|
|
464
534
|
|
|
465
535
|
try {
|
|
466
536
|
const schema = JSON.parse(el.schemaInput.value);
|
|
@@ -474,6 +544,15 @@ function applyCurrentSchema() {
|
|
|
474
544
|
return false;
|
|
475
545
|
}
|
|
476
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
|
+
|
|
477
556
|
// Build action value -> label map for efficient lookup
|
|
478
557
|
actionLabelMap = buildActionLabelMap(schema);
|
|
479
558
|
|
|
@@ -492,10 +571,12 @@ function applyCurrentSchema() {
|
|
|
492
571
|
// Ignore errors when getting current data
|
|
493
572
|
}
|
|
494
573
|
|
|
495
|
-
// Render form with current data
|
|
496
|
-
FormBuilder.renderForm(schema, currentData);
|
|
574
|
+
// Render form with current data and external actions
|
|
575
|
+
FormBuilder.renderForm(schema, currentData, externalActions);
|
|
497
576
|
|
|
498
577
|
console.log(`Form rendered in ${isReadOnly ? "readonly" : "edit"} mode`);
|
|
578
|
+
console.log(`External actions:`, externalActions);
|
|
579
|
+
|
|
499
580
|
return true;
|
|
500
581
|
} catch (e) {
|
|
501
582
|
showError(el.schemaErrors, `JSON parse error: ${e.message}`);
|
|
@@ -513,7 +594,9 @@ el.resetSchemaBtn.addEventListener("click", () => {
|
|
|
513
594
|
clearError(el.schemaErrors);
|
|
514
595
|
clearError(el.formErrors);
|
|
515
596
|
clearError(el.dataErrors);
|
|
597
|
+
clearError(el.actionsErrors);
|
|
516
598
|
el.dataTextarea.value = "";
|
|
599
|
+
el.actionsTextarea.value = "";
|
|
517
600
|
|
|
518
601
|
// Clear file storage
|
|
519
602
|
fileStorage.clear();
|
|
@@ -618,6 +701,15 @@ el.prefillBtn.addEventListener("click", () => {
|
|
|
618
701
|
const prefillData = JSON.parse(el.dataTextarea.value || "{}");
|
|
619
702
|
const currentSchema = JSON.parse(el.schemaInput.value);
|
|
620
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
|
+
|
|
621
713
|
// Convert enhanced data back to raw format for prefilling
|
|
622
714
|
const processedData = JSON.parse(JSON.stringify(prefillData));
|
|
623
715
|
|
|
@@ -658,9 +750,10 @@ el.prefillBtn.addEventListener("click", () => {
|
|
|
658
750
|
const isReadOnly = el.readOnlyToggle.checked;
|
|
659
751
|
FormBuilder.setMode(isReadOnly ? "readonly" : "edit");
|
|
660
752
|
|
|
661
|
-
FormBuilder.renderForm(currentSchema, processedData);
|
|
753
|
+
FormBuilder.renderForm(currentSchema, processedData, externalActions);
|
|
662
754
|
console.log("Form prefilled with data");
|
|
663
755
|
console.log("Processed prefill data:", processedData);
|
|
756
|
+
console.log("External actions:", externalActions);
|
|
664
757
|
} catch (e) {
|
|
665
758
|
showError(el.dataErrors, `JSON parse error: ${e.message}`);
|
|
666
759
|
console.error("Prefill error:", e);
|
|
@@ -685,6 +778,51 @@ el.downloadDataBtn.addEventListener("click", () => {
|
|
|
685
778
|
console.log("Data downloaded");
|
|
686
779
|
});
|
|
687
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
|
+
|
|
688
826
|
// Initialize demo application
|
|
689
827
|
function initDemo() {
|
|
690
828
|
// Set up FormBuilder
|
|
@@ -693,6 +831,9 @@ function initDemo() {
|
|
|
693
831
|
// Initialize with example schema
|
|
694
832
|
el.schemaInput.value = pretty(EXAMPLE_SCHEMA);
|
|
695
833
|
|
|
834
|
+
// Initialize with example actions
|
|
835
|
+
el.actionsTextarea.value = pretty(EXAMPLE_ACTIONS);
|
|
836
|
+
|
|
696
837
|
// Apply initial schema
|
|
697
838
|
applyCurrentSchema();
|
|
698
839
|
|
package/dist/elements.html
CHANGED
|
@@ -4,28 +4,7 @@
|
|
|
4
4
|
<meta charset="utf-8" />
|
|
5
5
|
<title>Form Builder - Element Types Documentation</title>
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
7
|
-
|
|
8
|
-
<script>
|
|
9
|
-
if (
|
|
10
|
-
location.hostname === "localhost" ||
|
|
11
|
-
location.hostname === "127.0.0.1" ||
|
|
12
|
-
location.protocol === "file:"
|
|
13
|
-
) {
|
|
14
|
-
// Development environment - load Tailwind CDN
|
|
15
|
-
const script = document.createElement("script");
|
|
16
|
-
script.src = "https://cdn.tailwindcss.com";
|
|
17
|
-
document.head.appendChild(script);
|
|
18
|
-
} else {
|
|
19
|
-
// Production environment - load local CSS (implement local build)
|
|
20
|
-
console.warn(
|
|
21
|
-
"Production mode: Please implement local Tailwind CSS build",
|
|
22
|
-
);
|
|
23
|
-
const link = document.createElement("link");
|
|
24
|
-
link.rel = "stylesheet";
|
|
25
|
-
link.href = "./tailwind.min.css"; // Local build file
|
|
26
|
-
document.head.appendChild(link);
|
|
27
|
-
}
|
|
28
|
-
</script>
|
|
7
|
+
<script src="https://cdn.tailwindcss.com"></script>
|
|
29
8
|
<script>
|
|
30
9
|
tailwind.config = {
|
|
31
10
|
darkMode: "media",
|