ConditionGroup
Edits nested all, any, or none conditions without the RuleBuilder action sections.
Component behavior
ConditionGroup edits a boolean predicate tree with condition rows and nested groups. RuleBuilder adds actions and WHEN/THEN sections.
- Saved filters or audience definitions with nested boolean conditions.
- Condition editors embedded in dialogs, forms, or change reviews.
- Predicates serialized as JSON.
RuleBuilder: the editor needs condition sections, actions, and built-in controlled/uncontrolled value handling.
FilterChip: filters form a flat conjunction without nested groups.
SearchInput: the task requires a text query only.
TokenField: the field accepts several values without predicate logic.
Props
A RuleGroup is { id, kind: "group", combinator, children }, where each child is another group or a { id, kind: "condition", field, operator, value?, values? }. Conditions reference a RuleField by its key, and the field’s type decides which operators are offered and which editor the value gets, unless the field narrows the list itself with operators. Build nodes with createGroup and createCondition; both mint ids from a module-level counter (c_1, g_2), unique within a page load rather than globally.
| Prop | Type | Default | Description |
|---|---|---|---|
group | RuleGroup | — | The controlled group value. The component does not keep an internal copy. |
fields | RuleField[] | — | Fields conditions may test. Order matters: fields[0] is what new rows and new nested groups are seeded with. |
onChange | (group: RuleGroup) => void | — | Called with the updated root tree after each edit, including nested edits. |
onRemove | () => void | — | Displays a remove button. Omit for the root group. |
depth | number | 0 | Group nesting depth. Nested groups receive this value automatically. |
maxDepth | number | 3 | Deepest level that still offers the “Group” button. A group at depth === maxDepth can hold conditions but cannot nest further. |
readOnly | boolean | — | Displays static values and hides remove and add buttons. |
Examples
Standalone group
Pass a group, field definitions, and a change handler. New conditions use fields[0]. A new nested group contains one condition and uses any under an all parent, or all otherwise.
Editors follow the operator
The value editor is chosen by the operator’s arity, not the field: is any of takes many values and renders a TokenField suggesting the field’s options; single-value operators render a Select for enums and an Input otherwise (numeric for number fields, with the field’s unit pinned inside); operators like is present and is false take nothing and show an em dash. Switching operator keeps the typed value when the arity is unchanged and clears it when it is not; switching field always clears it, and falls back to the first valid operator if the current one does not apply to the new type.
Nesting and maxDepth
maxDepth hides the Group button at the specified nesting depth. With maxDepth={1}, the root can add one nested group. An empty group evaluates to true in evaluateRule.
Read-only
readOnly renders combinators and values as static text, renders multiple values as tokens, and hides add/remove controls. This setting propagates to nested groups.
import { ConditionGroup, createGroup, createCondition } from "@solarius/onset";
import type {
ConditionGroupProps,
RuleGroup,
RuleField,
} from "@solarius/onset";
const [group, setGroup] = useState<RuleGroup>(
createGroup("any", [createCondition(fields[0])]),
);
<ConditionGroup group={group} fields={fields} onChange={setGroup} />;