Skip to content

Commit b0f88e2

Browse files
committed
feat(logic): finalize Advanced panels + Logic Groups, non-destructive save, renderer autoload, VE polish
Builder (field panel) - Mount Advanced (JSON) first, then VE to ensure preload/save works. - Move Add rule next to Save to JSON; late-bind fields/choices. - Null-safe preload/save of logic JSON. Logic Groups - Modal “Add group” wired reliably. - No rebuild on save (stop calling setData) → prevents panel disappearing. - Patch getData('json') to inject hidden __logicGroups at export time only. - Keep UI tweaks; backdrop alpha fixed. Renderer - On setup(), auto-load groups from hidden __logicGroups before target discovery. - Improved watcher set and first-run evaluation. - No breaking schema/UI changes. Existing forms remain compatible. Signed-off-by: Jaimon Orlé <jaimon.orle@orleindustries.com>
1 parent 76aedbd commit b0f88e2

11 files changed

Lines changed: 942 additions & 815 deletions

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog
22

3+
✅ Field-level conditional logic (Visual + Advanced JSON) fully functional.
4+
✅ Logic Groups authoring modal; persisted via hidden __logicGroups; autoloaded by renderer.
5+
✅ Stable builder UX (no stage rebuild on save).
6+
🧩 Minor UI polish (clean headers, spacing, modal overlay).
37

48
## 0.2.2 — Public demos & polish
59

demo/composed.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ <h1>Composed Demo</h1>
2727
window.__FB_LOGIC_DEBUG__ = true;
2828

2929
// IMPORTANT: Make sure the radio values match the rule ("yes"/"no"), or update the rule accordingly.
30-
const formData = [{ "type": "radio-group", "required": false, "label": "Do you have a vehicle?", "inline": false, "name": "hasVehicle", "access": false, "other": false, "logicApplyTo": "self", "values": [{ "label": "Yes", "value": "yes", "selected": false }, { "label": "No", "value": "no", "selected": true }] }, { "type": "text", "required": false, "label": "Vehicle Make", "className": "form-control", "name": "vehicleMake", "access": false, "subtype": "text", "logic": "{\n \"groups\": [\n {\n \"mode\": \"any\",\n \"rules\": [\n {\n \"field\": \"hasVehicle\",\n \"op\": \"equals\",\n \"value\": \"yes\"\n }\n ],\n \"actions\": [\n \"show\",\n \"require\"\n ]\n }\n ]\n}", "logicApplyTo": "container" }, { "type": "text", "required": false, "label": "Vehicle Model", "className": "form-control", "name": "vehicleModel", "access": false, "subtype": "text", "logic": "{\n \"groups\": [\n {\n \"mode\": \"any\",\n \"rules\": [\n {\n \"field\": \"hasVehicle\",\n \"op\": \"equals\",\n \"value\": \"yes\"\n }\n ],\n \"actions\": [\n \"show\",\n \"require\"\n ]\n }\n ]\n}", "logicApplyTo": "container" }];
30+
const formData = [{ "type": "radio-group", "required": false, "label": "Radio Group", "inline": false, "name": "radio-group-1762553349633-0", "access": false, "other": false, "logicApplyTo": "self", "values": [{ "label": "Option 1", "value": "option-1", "selected": false }, { "label": "Option 2", "value": "option-2", "selected": false }, { "label": "Option 3", "value": "option-3", "selected": false }] }, { "type": "text", "required": false, "label": "Text Field", "className": "form-control", "name": "text-1762553351518-0", "access": false, "subtype": "text", "logic": "{\n \"groups\": [\n {\n \"mode\": \"any\",\n \"rules\": [\n {\n \"field\": \"radio-group-1762553349633-0\",\n \"op\": \"equals\",\n \"value\": \"option-1\"\n }\n ],\n \"actions\": [\n \"show\",\n \"require\",\n \"enable\"\n ]\n }\n ]\n}", "logicApplyTo": "self" }, { "type": "select", "required": false, "label": "Select", "className": "form-control", "name": "select-1762553352518-0", "access": false, "multiple": false, "logicApplyTo": "self", "values": [{ "label": "Option 1", "value": "option-1", "selected": true }, { "label": "Option 2", "value": "option-2", "selected": false }, { "label": "Option 3", "value": "option-3", "selected": false }] }, { "type": "textarea", "required": false, "label": "Text Area", "className": "form-control", "name": "textarea-1762553353324-0", "access": false, "subtype": "textarea", "logicApplyTo": "group", "logicGroup": "asdf" }, { "type": "hidden", "name": "__logicGroups", "value": "{\"asdf\":{\"mode\":\"any\",\"rules\":[{\"field\":\"select-1762553352518-0\",\"op\":\"equals\",\"value\":\"option-3\"}],\"actions\":[\"show\",\"require\",\"enable\"]}}", "label": " ", "access": false, "className": "d-none" }];
3131

3232
const $root = window.jQuery('#render');
3333
$root.formRender({ formData }); // 1) render

dist/formbuilder-conditional-logic.es.js

Lines changed: 480 additions & 462 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/formbuilder-conditional-logic.es.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/formbuilder-conditional-logic.umd.cjs

Lines changed: 29 additions & 46 deletions
Large diffs are not rendered by default.

dist/formbuilder-conditional-logic.umd.cjs.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/plugin/builder.d.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
/**
2-
* Builder-side plugin helpers for formBuilder.
3-
* Adds:
4-
* - typeUserAttrs for logic JSON, applyTo, logicGroup
5-
* - onOpenFieldEdit panel that groups these controls
6-
* - Visual Rules Editor (optional) that populates the logic JSON without typing
2+
* Builder plugin for formBuilder: adds Conditional Logic panel and Groups modal.
3+
* Exports:
4+
* - withConditionalLogic(opts) → formBuilder options extension
5+
* - attachLogicGroupsManager(toolbarEl, hooks)
76
*/
87
type UserAttrs = Record<string, any>;
98
export interface FieldMeta {
@@ -25,13 +24,12 @@ export interface BuilderInitOptions {
2524
}> | null;
2625
enableVisualEditor?: boolean;
2726
}
27+
/** Build the options object to pass into $('.build-wrap').formBuilder(...) */
2828
export declare function withConditionalLogic(opts?: BuilderInitOptions): {
2929
typeUserAttrs: Record<string, UserAttrs>;
3030
onOpenFieldEdit: (editPanel: HTMLElement) => void;
3131
};
32-
/**
33-
* Form-level groups JSON manager (as before)
34-
*/
32+
/** Minimal Groups GUI living in a modal attached to a toolbar element */
3533
export declare function attachLogicGroupsManager(targetContainer: HTMLElement, initialOrOpts?: string | {
3634
initialJson?: string;
3735
getAvailableFields?: () => FieldMeta[];

dist/renderer/setup.d.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,6 @@ declare global {
1010
};
1111
}
1212
}
13-
export declare function setup(formEl: HTMLElement | Element, _formData?: any, options?: SetupOptions): {
14-
refresh: () => void;
15-
destroy: () => void;
16-
};
13+
export declare function setup(formEl: HTMLElement | Element, _formData?: any, options?: SetupOptions): void;
1714
export declare function refresh(formEl: HTMLElement | Element): void;
1815
export declare function evaluateField(formEl: HTMLElement | Element, _name: string): void;

src.zip

12 KB
Binary file not shown.

0 commit comments

Comments
 (0)