form-builder-pro 1.4.2 → 1.4.4
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/index.css +20 -0
- package/dist/index.d.mts +19 -1
- package/dist/index.d.ts +19 -1
- package/dist/index.js +124 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +124 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.css
CHANGED
|
@@ -1033,6 +1033,9 @@ body {
|
|
|
1033
1033
|
.max-h-32 {
|
|
1034
1034
|
max-height: 8rem;
|
|
1035
1035
|
}
|
|
1036
|
+
.max-h-40 {
|
|
1037
|
+
max-height: 10rem;
|
|
1038
|
+
}
|
|
1036
1039
|
.max-h-48 {
|
|
1037
1040
|
max-height: 12rem;
|
|
1038
1041
|
}
|
|
@@ -1197,6 +1200,15 @@ body {
|
|
|
1197
1200
|
margin-top: calc(1.5rem * calc(1 - var(--tw-space-y-reverse)));
|
|
1198
1201
|
margin-bottom: calc(1.5rem * var(--tw-space-y-reverse));
|
|
1199
1202
|
}
|
|
1203
|
+
.divide-y > :not([hidden]) ~ :not([hidden]) {
|
|
1204
|
+
--tw-divide-y-reverse: 0;
|
|
1205
|
+
border-top-width: calc(1px * calc(1 - var(--tw-divide-y-reverse)));
|
|
1206
|
+
border-bottom-width: calc(1px * var(--tw-divide-y-reverse));
|
|
1207
|
+
}
|
|
1208
|
+
.divide-gray-100 > :not([hidden]) ~ :not([hidden]) {
|
|
1209
|
+
--tw-divide-opacity: 1;
|
|
1210
|
+
border-color: rgb(243 244 246 / var(--tw-divide-opacity, 1));
|
|
1211
|
+
}
|
|
1200
1212
|
.overflow-hidden {
|
|
1201
1213
|
overflow: hidden;
|
|
1202
1214
|
}
|
|
@@ -1597,6 +1609,9 @@ body {
|
|
|
1597
1609
|
--tw-text-opacity: 1;
|
|
1598
1610
|
color: rgb(202 138 4 / var(--tw-text-opacity, 1));
|
|
1599
1611
|
}
|
|
1612
|
+
.accent-blue-600 {
|
|
1613
|
+
accent-color: #2563eb;
|
|
1614
|
+
}
|
|
1600
1615
|
.opacity-100 {
|
|
1601
1616
|
opacity: 1;
|
|
1602
1617
|
}
|
|
@@ -2050,6 +2065,11 @@ input[type="radio"]:checked::after {
|
|
|
2050
2065
|
opacity: 0.7;
|
|
2051
2066
|
}
|
|
2052
2067
|
|
|
2068
|
+
.dark\:divide-gray-700:is(.dark *) > :not([hidden]) ~ :not([hidden]) {
|
|
2069
|
+
--tw-divide-opacity: 1;
|
|
2070
|
+
border-color: rgb(55 65 81 / var(--tw-divide-opacity, 1));
|
|
2071
|
+
}
|
|
2072
|
+
|
|
2053
2073
|
.dark\:border-\[\#019FA2\]:is(.dark *) {
|
|
2054
2074
|
--tw-border-opacity: 1;
|
|
2055
2075
|
border-color: rgb(1 159 162 / var(--tw-border-opacity, 1));
|
package/dist/index.d.mts
CHANGED
|
@@ -66,6 +66,23 @@ interface AsyncOptionSource {
|
|
|
66
66
|
}
|
|
67
67
|
/** Lookup (Entity Fields) — source category for optionSource LOOKUP */
|
|
68
68
|
type LookupSourceType = 'MODULE' | 'MASTER_TYPE' | 'SETTINGS';
|
|
69
|
+
/**
|
|
70
|
+
* Configuration for the auto-populate fields feature on LOOKUP dropdowns.
|
|
71
|
+
* When `enabled` is true and a user selects a lookup record, the fields listed
|
|
72
|
+
* in `fields` are automatically populated from the corresponding lookup record data.
|
|
73
|
+
*
|
|
74
|
+
* `fields` contains the field keys (e.g. column/property names) that are present
|
|
75
|
+
* in both the Lookup Value Field and the Lookup Label Field response objects.
|
|
76
|
+
*/
|
|
77
|
+
interface AutoPopulateFieldsConfig {
|
|
78
|
+
/** Whether auto-population is active for this dropdown */
|
|
79
|
+
enabled: boolean;
|
|
80
|
+
/**
|
|
81
|
+
* List of field keys from the lookup response that should be auto-populated
|
|
82
|
+
* into other form fields when the user selects a value.
|
|
83
|
+
*/
|
|
84
|
+
fields: string[];
|
|
85
|
+
}
|
|
69
86
|
interface FormField {
|
|
70
87
|
id: string;
|
|
71
88
|
type: FieldType;
|
|
@@ -136,6 +153,7 @@ interface FormField {
|
|
|
136
153
|
nameGeneratorSuffix?: string;
|
|
137
154
|
nameGeneratorIdPadding?: number;
|
|
138
155
|
formulaConfig?: FormulaConfig;
|
|
156
|
+
autoPopulateFields?: AutoPopulateFieldsConfig;
|
|
139
157
|
}
|
|
140
158
|
/**
|
|
141
159
|
* Conditional date constraint — evaluated at runtime against the current date or another field's value.
|
|
@@ -596,4 +614,4 @@ declare const initFormBuilder: (options: FormBuilderOptions & {
|
|
|
596
614
|
containerId: string;
|
|
597
615
|
}) => FormBuilder;
|
|
598
616
|
|
|
599
|
-
export { type AsyncOptionSource, type DateConstraint, type FieldType, type FieldValidations, type FieldWidth, FormBuilder, type FormBuilderOptions, type FormField, FormRenderer, type FormSchema, FormSchemaValidation, type FormSection, type FormulaCondition, type FormulaConfig, type GroupPosition, type ISDConfig, LOOKUP_SOURCE_TYPE_OPTIONS, type LookupSourceType, type MasterType, type NameGeneratorFormat, type ValidationObject, type ValidationRule, builderToPlatform, cleanFormSchema, convertValidationObjectToArray, detectCircularDependency, detectFormulaFieldCircularDependency, evaluateFormula, evaluateFormulaConfig, evaluateFormulaExpression, extractBracketFields, formStore, generateName, getColSpanFromWidth, getFieldsForFormula, getNumericFieldsForFormula, getValidationConfigForAngular, initFormBuilder, parseFormulaDependencies, parseWidth, platformToBuilder, resetNameGeneratorCounter, validateFormula, validateFormulaExpression };
|
|
617
|
+
export { type AsyncOptionSource, type AutoPopulateFieldsConfig, type DateConstraint, type FieldType, type FieldValidations, type FieldWidth, FormBuilder, type FormBuilderOptions, type FormField, FormRenderer, type FormSchema, FormSchemaValidation, type FormSection, type FormulaCondition, type FormulaConfig, type GroupPosition, type ISDConfig, LOOKUP_SOURCE_TYPE_OPTIONS, type LookupSourceType, type MasterType, type NameGeneratorFormat, type ValidationObject, type ValidationRule, builderToPlatform, cleanFormSchema, convertValidationObjectToArray, detectCircularDependency, detectFormulaFieldCircularDependency, evaluateFormula, evaluateFormulaConfig, evaluateFormulaExpression, extractBracketFields, formStore, generateName, getColSpanFromWidth, getFieldsForFormula, getNumericFieldsForFormula, getValidationConfigForAngular, initFormBuilder, parseFormulaDependencies, parseWidth, platformToBuilder, resetNameGeneratorCounter, validateFormula, validateFormulaExpression };
|
package/dist/index.d.ts
CHANGED
|
@@ -66,6 +66,23 @@ interface AsyncOptionSource {
|
|
|
66
66
|
}
|
|
67
67
|
/** Lookup (Entity Fields) — source category for optionSource LOOKUP */
|
|
68
68
|
type LookupSourceType = 'MODULE' | 'MASTER_TYPE' | 'SETTINGS';
|
|
69
|
+
/**
|
|
70
|
+
* Configuration for the auto-populate fields feature on LOOKUP dropdowns.
|
|
71
|
+
* When `enabled` is true and a user selects a lookup record, the fields listed
|
|
72
|
+
* in `fields` are automatically populated from the corresponding lookup record data.
|
|
73
|
+
*
|
|
74
|
+
* `fields` contains the field keys (e.g. column/property names) that are present
|
|
75
|
+
* in both the Lookup Value Field and the Lookup Label Field response objects.
|
|
76
|
+
*/
|
|
77
|
+
interface AutoPopulateFieldsConfig {
|
|
78
|
+
/** Whether auto-population is active for this dropdown */
|
|
79
|
+
enabled: boolean;
|
|
80
|
+
/**
|
|
81
|
+
* List of field keys from the lookup response that should be auto-populated
|
|
82
|
+
* into other form fields when the user selects a value.
|
|
83
|
+
*/
|
|
84
|
+
fields: string[];
|
|
85
|
+
}
|
|
69
86
|
interface FormField {
|
|
70
87
|
id: string;
|
|
71
88
|
type: FieldType;
|
|
@@ -136,6 +153,7 @@ interface FormField {
|
|
|
136
153
|
nameGeneratorSuffix?: string;
|
|
137
154
|
nameGeneratorIdPadding?: number;
|
|
138
155
|
formulaConfig?: FormulaConfig;
|
|
156
|
+
autoPopulateFields?: AutoPopulateFieldsConfig;
|
|
139
157
|
}
|
|
140
158
|
/**
|
|
141
159
|
* Conditional date constraint — evaluated at runtime against the current date or another field's value.
|
|
@@ -596,4 +614,4 @@ declare const initFormBuilder: (options: FormBuilderOptions & {
|
|
|
596
614
|
containerId: string;
|
|
597
615
|
}) => FormBuilder;
|
|
598
616
|
|
|
599
|
-
export { type AsyncOptionSource, type DateConstraint, type FieldType, type FieldValidations, type FieldWidth, FormBuilder, type FormBuilderOptions, type FormField, FormRenderer, type FormSchema, FormSchemaValidation, type FormSection, type FormulaCondition, type FormulaConfig, type GroupPosition, type ISDConfig, LOOKUP_SOURCE_TYPE_OPTIONS, type LookupSourceType, type MasterType, type NameGeneratorFormat, type ValidationObject, type ValidationRule, builderToPlatform, cleanFormSchema, convertValidationObjectToArray, detectCircularDependency, detectFormulaFieldCircularDependency, evaluateFormula, evaluateFormulaConfig, evaluateFormulaExpression, extractBracketFields, formStore, generateName, getColSpanFromWidth, getFieldsForFormula, getNumericFieldsForFormula, getValidationConfigForAngular, initFormBuilder, parseFormulaDependencies, parseWidth, platformToBuilder, resetNameGeneratorCounter, validateFormula, validateFormulaExpression };
|
|
617
|
+
export { type AsyncOptionSource, type AutoPopulateFieldsConfig, type DateConstraint, type FieldType, type FieldValidations, type FieldWidth, FormBuilder, type FormBuilderOptions, type FormField, FormRenderer, type FormSchema, FormSchemaValidation, type FormSection, type FormulaCondition, type FormulaConfig, type GroupPosition, type ISDConfig, LOOKUP_SOURCE_TYPE_OPTIONS, type LookupSourceType, type MasterType, type NameGeneratorFormat, type ValidationObject, type ValidationRule, builderToPlatform, cleanFormSchema, convertValidationObjectToArray, detectCircularDependency, detectFormulaFieldCircularDependency, evaluateFormula, evaluateFormulaConfig, evaluateFormulaExpression, extractBracketFields, formStore, generateName, getColSpanFromWidth, getFieldsForFormula, getNumericFieldsForFormula, getValidationConfigForAngular, initFormBuilder, parseFormulaDependencies, parseWidth, platformToBuilder, resetNameGeneratorCounter, validateFormula, validateFormulaExpression };
|
package/dist/index.js
CHANGED
|
@@ -4083,6 +4083,7 @@ var LOOKUP_SOURCE_TYPE_OPTIONS = [
|
|
|
4083
4083
|
{ value: "SETTINGS", label: "Settings Entity" }
|
|
4084
4084
|
];
|
|
4085
4085
|
var generateId = () => Math.random().toString(36).substring(2, 9);
|
|
4086
|
+
var generateFieldName = () => `field_${Date.now()}_${Math.random().toString(36).substring(2, 5)}`;
|
|
4086
4087
|
var FIELD_TYPES = [
|
|
4087
4088
|
{ type: "text", label: "Text Input", icon: "Type" },
|
|
4088
4089
|
{ type: "textarea", label: "Text Area", icon: "DocumentText" },
|
|
@@ -4357,6 +4358,8 @@ var cloneField = (field) => {
|
|
|
4357
4358
|
return {
|
|
4358
4359
|
...field,
|
|
4359
4360
|
id: generateId(),
|
|
4361
|
+
fieldName: generateFieldName(),
|
|
4362
|
+
// Always generate a fresh unique name on clone
|
|
4360
4363
|
// Ensure options are also cloned if present
|
|
4361
4364
|
options: field.options ? field.options.map((opt) => ({ ...opt })) : void 0,
|
|
4362
4365
|
validation: field.validation ? field.validation.map((v) => ({ ...v })) : void 0,
|
|
@@ -4784,6 +4787,13 @@ function transformField(field) {
|
|
|
4784
4787
|
transformed.nameGeneratorSuffix = field.nameGeneratorSuffix;
|
|
4785
4788
|
if (field.nameGeneratorIdPadding !== void 0)
|
|
4786
4789
|
transformed.nameGeneratorIdPadding = field.nameGeneratorIdPadding;
|
|
4790
|
+
if (field.autoPopulateFields !== void 0 && field.autoPopulateFields !== null) {
|
|
4791
|
+
const apf = field.autoPopulateFields;
|
|
4792
|
+
transformed.autoPopulateFields = {
|
|
4793
|
+
enabled: typeof apf.enabled === "boolean" ? apf.enabled : false,
|
|
4794
|
+
fields: Array.isArray(apf.fields) ? apf.fields : []
|
|
4795
|
+
};
|
|
4796
|
+
}
|
|
4787
4797
|
if (field.css !== void 0)
|
|
4788
4798
|
transformed.css = field.css;
|
|
4789
4799
|
if (field.optionsSource !== void 0)
|
|
@@ -5042,6 +5052,12 @@ function fieldToPayload(field, opts) {
|
|
|
5042
5052
|
parentFieldName: field.lookupParentFieldName ?? null
|
|
5043
5053
|
};
|
|
5044
5054
|
}
|
|
5055
|
+
if (field.optionSource === "LOOKUP" && field.autoPopulateFields !== void 0 && field.autoPopulateFields !== null) {
|
|
5056
|
+
payload.autoPopulateFields = {
|
|
5057
|
+
enabled: field.autoPopulateFields.enabled,
|
|
5058
|
+
fields: Array.isArray(field.autoPopulateFields.fields) ? field.autoPopulateFields.fields : []
|
|
5059
|
+
};
|
|
5060
|
+
}
|
|
5045
5061
|
if (field.isd !== void 0)
|
|
5046
5062
|
payload.isd = field.isd;
|
|
5047
5063
|
if (field.imageUrl !== void 0)
|
|
@@ -5741,6 +5757,7 @@ var formStore = createStore((set, get) => ({
|
|
|
5741
5757
|
const baseField = {
|
|
5742
5758
|
id: generateId(),
|
|
5743
5759
|
type,
|
|
5760
|
+
fieldName: generateFieldName(),
|
|
5744
5761
|
...DEFAULT_FIELD_CONFIG[type]
|
|
5745
5762
|
};
|
|
5746
5763
|
let newField = { ...baseField };
|
|
@@ -12402,6 +12419,35 @@ var FormBuilder = class {
|
|
|
12402
12419
|
}, [getIcon("X", 20)]));
|
|
12403
12420
|
panel.appendChild(header);
|
|
12404
12421
|
const body = createElement("div", { className: "flex-1 overflow-y-auto p-4 px-2 space-y-3", id: "config-panel-body" });
|
|
12422
|
+
const nameGroup = createElement("div");
|
|
12423
|
+
nameGroup.appendChild(createElement("label", { className: "block text-sm font-normal text-gray-700 dark:text-gray-300 mb-1", text: "Name" }));
|
|
12424
|
+
const currentFieldName = selectedField.fieldName || generateFieldName();
|
|
12425
|
+
if (!selectedField.fieldName) {
|
|
12426
|
+
formStore.getState().updateField(selectedField.id, { fieldName: currentFieldName });
|
|
12427
|
+
}
|
|
12428
|
+
const nameInput = createElement("input", {
|
|
12429
|
+
className: "w-full px-3 py-2 border border-gray-200 dark:border-gray-700 rounded-md bg-transparent font-mono text-xs",
|
|
12430
|
+
value: currentFieldName,
|
|
12431
|
+
"data-focus-id": `field-name-${selectedField.id}`,
|
|
12432
|
+
placeholder: "field_...",
|
|
12433
|
+
oninput: (e) => {
|
|
12434
|
+
const fieldId2 = selectedField.id;
|
|
12435
|
+
const value = e.target.value.trim();
|
|
12436
|
+
const key = `fieldname-${fieldId2}`;
|
|
12437
|
+
const existing = labelUpdateTimeouts.get(key);
|
|
12438
|
+
if (existing)
|
|
12439
|
+
clearTimeout(existing);
|
|
12440
|
+
const timeoutId = setTimeout(() => {
|
|
12441
|
+
labelUpdateTimeouts.delete(key);
|
|
12442
|
+
if (value) {
|
|
12443
|
+
formStore.getState().updateField(fieldId2, { fieldName: value });
|
|
12444
|
+
}
|
|
12445
|
+
}, LABEL_DEBOUNCE_MS);
|
|
12446
|
+
labelUpdateTimeouts.set(key, timeoutId);
|
|
12447
|
+
}
|
|
12448
|
+
});
|
|
12449
|
+
nameGroup.appendChild(nameInput);
|
|
12450
|
+
body.appendChild(nameGroup);
|
|
12405
12451
|
const labelGroup = createElement("div");
|
|
12406
12452
|
labelGroup.appendChild(createElement("label", { className: "block text-sm font-normal text-gray-700 dark:text-gray-300 mb-1", text: "Label" }));
|
|
12407
12453
|
labelGroup.appendChild(createElement("input", {
|
|
@@ -13563,6 +13609,84 @@ var FormBuilder = class {
|
|
|
13563
13609
|
});
|
|
13564
13610
|
parentFieldGroup.appendChild(parentFieldSelect);
|
|
13565
13611
|
body.appendChild(parentFieldGroup);
|
|
13612
|
+
const autoPopHeader = createElement("h3", {
|
|
13613
|
+
className: "text-xs font-semibold text-gray-500 uppercase tracking-wider mb-3 mt-6",
|
|
13614
|
+
text: "Auto Populate Fields"
|
|
13615
|
+
});
|
|
13616
|
+
body.appendChild(autoPopHeader);
|
|
13617
|
+
const autoPopEnabled = selectedField.autoPopulateFields?.enabled === true;
|
|
13618
|
+
body.appendChild(this.createCheckboxField(
|
|
13619
|
+
"Enable automation for selected records",
|
|
13620
|
+
autoPopEnabled,
|
|
13621
|
+
(checked) => {
|
|
13622
|
+
const current = formStore.getState().schema.sections.flatMap((s) => s.fields).find((f) => f.id === selectedField.id);
|
|
13623
|
+
formStore.getState().updateField(selectedField.id, {
|
|
13624
|
+
autoPopulateFields: {
|
|
13625
|
+
enabled: checked,
|
|
13626
|
+
fields: current?.autoPopulateFields?.fields ?? []
|
|
13627
|
+
}
|
|
13628
|
+
});
|
|
13629
|
+
this.render();
|
|
13630
|
+
},
|
|
13631
|
+
`auto-populate-enabled-${selectedField.id}`
|
|
13632
|
+
));
|
|
13633
|
+
{
|
|
13634
|
+
const autoPopFieldsGroup = createElement("div", { className: "mb-4 mt-2" });
|
|
13635
|
+
autoPopFieldsGroup.appendChild(createElement("label", {
|
|
13636
|
+
className: "block text-sm font-normal text-gray-700 dark:text-gray-300 mb-1",
|
|
13637
|
+
text: "Fields to auto-populate"
|
|
13638
|
+
}));
|
|
13639
|
+
const lookupFieldOptionsMapForAP = formStore.getState().lookupFieldOptionsMap;
|
|
13640
|
+
const availableAutoPopFields = selectedField.lookupSource ? lookupFieldOptionsMapForAP[selectedField.lookupSource] || [] : [];
|
|
13641
|
+
const selectedAutoPopFields = selectedField.autoPopulateFields?.fields ?? [];
|
|
13642
|
+
const isAutoPopDisabled = !autoPopEnabled || !selectedField.lookupSource;
|
|
13643
|
+
if (availableAutoPopFields.length === 0) {
|
|
13644
|
+
const emptyNote = createElement("p", {
|
|
13645
|
+
className: "text-xs text-gray-400 dark:text-gray-500 mt-1",
|
|
13646
|
+
text: selectedField.lookupSource ? "No fields available for this lookup source." : "Select a Lookup Source first."
|
|
13647
|
+
});
|
|
13648
|
+
autoPopFieldsGroup.appendChild(emptyNote);
|
|
13649
|
+
} else {
|
|
13650
|
+
const fieldList = createElement("div", {
|
|
13651
|
+
className: `border border-gray-200 dark:border-gray-700 rounded-md divide-y divide-gray-100 dark:divide-gray-700 overflow-y-auto max-h-40 ${isAutoPopDisabled ? "opacity-50 pointer-events-none" : ""}`
|
|
13652
|
+
});
|
|
13653
|
+
availableAutoPopFields.forEach((fieldKey) => {
|
|
13654
|
+
const isChecked = selectedAutoPopFields.includes(fieldKey);
|
|
13655
|
+
const row = createElement("label", {
|
|
13656
|
+
className: "flex items-center gap-2 px-3 py-2 cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 text-sm text-gray-700 dark:text-gray-300"
|
|
13657
|
+
});
|
|
13658
|
+
const cb = createElement("input", {
|
|
13659
|
+
type: "checkbox",
|
|
13660
|
+
className: "w-4 h-4 accent-blue-600",
|
|
13661
|
+
checked: isChecked,
|
|
13662
|
+
disabled: isAutoPopDisabled,
|
|
13663
|
+
onchange: (e) => {
|
|
13664
|
+
const target = e.target;
|
|
13665
|
+
const latestField = formStore.getState().schema.sections.flatMap((s) => s.fields).find((f) => f.id === selectedField.id);
|
|
13666
|
+
const latestSelected = latestField?.autoPopulateFields?.fields ?? [];
|
|
13667
|
+
const updatedFields = target.checked ? [.../* @__PURE__ */ new Set([...latestSelected, fieldKey])] : latestSelected.filter((k) => k !== fieldKey);
|
|
13668
|
+
formStore.getState().updateField(selectedField.id, {
|
|
13669
|
+
autoPopulateFields: {
|
|
13670
|
+
enabled: latestField?.autoPopulateFields?.enabled ?? true,
|
|
13671
|
+
fields: updatedFields
|
|
13672
|
+
}
|
|
13673
|
+
});
|
|
13674
|
+
}
|
|
13675
|
+
});
|
|
13676
|
+
row.appendChild(cb);
|
|
13677
|
+
row.appendChild(createElement("span", { text: fieldKey }));
|
|
13678
|
+
fieldList.appendChild(row);
|
|
13679
|
+
});
|
|
13680
|
+
autoPopFieldsGroup.appendChild(fieldList);
|
|
13681
|
+
if (selectedAutoPopFields.length > 0) {
|
|
13682
|
+
autoPopFieldsGroup.appendChild(createElement("p", {
|
|
13683
|
+
className: "text-xs text-gray-400 dark:text-gray-500 mt-1",
|
|
13684
|
+
text: `${selectedAutoPopFields.length} field(s) selected`
|
|
13685
|
+
}));
|
|
13686
|
+
}
|
|
13687
|
+
}
|
|
13688
|
+
body.appendChild(autoPopFieldsGroup);
|
|
13689
|
+
}
|
|
13566
13690
|
body.appendChild(this.createCheckboxField(
|
|
13567
13691
|
"Visibility",
|
|
13568
13692
|
selectedField.visible !== false,
|