A visual interface for building conditional logic rules without writing JSON manually.
The system currently supports JSONLogic for conditional field and step visibility:
// Example: Show email field only when contact method is 'email'
{
id: 'email-field',
type: 'email',
conditionalLogic: {
'==': [{ var: 'contact_method' }, 'email']
}
}A drag-and-drop interface for building logic rules, similar to query builders in database tools.
// packages/builder/src/components/logic-builder.ts
@customElement('logic-builder')
export class LogicBuilder extends LitElement {
@property({ type: Object })
logic: RulesLogic | null = null;
@property({ type: Array })
availableFields: FormField[] = [];
// Renders a visual tree of conditions
// Allows adding/removing/editing conditions
// Converts to/from JSONLogic format
}@customElement('condition-row')
export class ConditionRow extends LitElement {
@property({ type: String })
field: string = '';
@property({ type: String })
operator: '==' | '!=' | '>' | '<' | '>=' | '<=' = '==';
@property({ type: String })
value: string = '';
}@customElement('condition-group')
export class ConditionGroup extends LitElement {
@property({ type: String })
operator: 'and' | 'or' = 'and';
@property({ type: Array })
conditions: LogicNode[] = [];
}┌────────────────────────────────────────────────┐
│ Conditional Logic Builder │
├────────────────────────────────────────────────┤
│ │
│ Show this field when: │
│ │
│ ┌──────────────────────────────────────────┐ │
│ │ ● All (AND) ○ Any (OR) │ │
│ │ │ │
│ │ [field_name ▼] [equals ▼] [value ] │ │
│ │ [×] │ │
│ │ [age ▼] [>= ▼] [18 ] │ │
│ │ [×] │ │
│ │ │ │
│ │ [+ Add Condition] [+ Add Group] │ │
│ └──────────────────────────────────────────┘ │
│ │
│ [Toggle Advanced Mode] │
│ │
└────────────────────────────────────────────────┘
Allows editing raw JSONLogic for complex scenarios:
┌────────────────────────────────────────────────┐
│ Advanced: JSONLogic Editor │
├────────────────────────────────────────────────┤
│ │
│ { │
│ "and": [ │
│ { │
│ "==": [ │
│ { "var": "contact_method" }, │
│ "email" │
│ ] │
│ }, │
│ { │
│ ">=": [ │
│ { "var": "age" }, │
│ 18 │
│ ] │
│ } │
│ ] │
│ } │
│ │
│ [Validate] [Back to Visual Mode] │
└────────────────────────────────────────────────┘
Create the visual builder components in packages/builder/src/components/logic/:
logic-builder.ts- Main logic builder interfacecondition-row.ts- Single condition editorcondition-group.ts- Group of conditions with AND/ORlogic-preview.ts- Shows resulting JSONLogic
Modify field-editor.ts to include the logic builder:
private renderConditionalLogic() {
return html`
<div class="form-group">
<label class="form-label">Conditional Logic</label>
<logic-builder
.logic="${this.field?.conditionalLogic}"
.availableFields="${this.availableFields}"
@logic-change="${this.handleLogicChange}"
></logic-builder>
</div>
`;
}Allow conditional logic for entire steps in multi-step forms.
Show preview of when condition will be true based on current form state.
- ✅ Field comparison operators (==, !=, >, <, >=, <=)
- ✅ AND/OR grouping
- ✅ Add/remove conditions
- ✅ Field selector dropdown
- ✅ Operator selector
- ✅ Value input
- □ Nested groups (e.g., (A AND B) OR (C AND D))
- □ NOT operator
- □ Complex JSONLogic functions (map, filter, reduce)
- □ Variable references
- □ Custom functions
- □ Import/export logic templates
- □ Logic testing/preview mode
- □ Drag and drop to reorder conditions
- □ Collapse/expand groups
- □ Color coding for different operators
- □ Real-time validation
- □ Error highlighting
- □ Tooltips for operators
- □ Keyboard shortcuts
- □ Undo/redo
// Visual: If "contact_method" equals "email"
{
"==": [{ "var": "contact_method" }, "email"]
}// Visual: If "age" is greater than or equal to 18
{
">=": [{ "var": "age" }, 18]
}// Visual: If "country" is "US" AND "age" >= 21
// OR "country" is not "US" AND "age" >= 18
{
"or": [
{
"and": [
{ "==": [{ "var": "country" }, "US"] },
{ ">=": [{ "var": "age" }, 21] }
]
},
{
"and": [
{ "!=": [{ "var": "country" }, "US"] },
{ ">=": [{ "var": "age" }, 18] }
]
}
]
}// Visual: Show "other_reason" field if "reason" equals "other"
{
"==": [{ "var": "reason" }, "other"]
}Test logic conversion:
describe('LogicBuilder', () => {
it('converts visual conditions to JSONLogic', () => {
const node: LogicNode = {
id: '1',
operator: '==',
field: 'age',
value: 18
};
const result = nodeToJsonLogic(node);
expect(result).toEqual({
'==': [{ var: 'age' }, 18]
});
});
it('converts JSONLogic to visual nodes', () => {
const logic = {
'==': [{ var: 'age' }, 18]
};
const node = jsonLogicToNode(logic);
expect(node.operator).toBe('==');
expect(node.field).toBe('age');
expect(node.value).toBe(18);
});
});Test in the form builder:
- Add a condition in visual mode
- Switch to advanced mode
- Verify JSONLogic is correct
- Edit in advanced mode
- Switch back to visual mode
- Verify visual representation is correct
- Logic Templates: Pre-built logic patterns for common scenarios
- AI Assistance: Natural language to JSONLogic conversion
- Logic Visualization: Flow diagram of conditional logic
- Testing Mode: Test conditions with sample data
- Version History: Track changes to conditional logic
- Logic Sharing: Share logic patterns across forms
- Performance Analysis: Show which conditions slow down forms
- Accessibility: Ensure logic builder is keyboard and screen reader accessible