All-in-one component: input field + parsed condition output with editing and drag-and-drop.
import { ConditionalUI } from "react-conditional-ui";
<ConditionalUI
fields={[
{ label: "Status", value: "status" },
{ label: "Age", value: "age", type: "number" },
]}
onConditionsChange={(groups) => console.log(groups)}
/>;Standalone text input with fuzzy parsing, ghost autocomplete, and inline diagnostics.
import { Input } from "react-conditional-ui";
<Input fields={fields} operators={operators} onSubmit={(group) => console.log(group)} />;Also supports a fully controlled mode via useConditionalInput:
import { Input, useConditionalInput } from "react-conditional-ui";
const { text, diagnostics, handleChange, handleSubmit, getSuggestion } = useConditionalInput({
fields,
onSubmit: handleGroup,
});
<Input
value={text}
onChange={handleChange}
onSubmit={handleSubmit}
getSuggestion={getSuggestion}
diagnostics={diagnostics}
/>;Renders parsed condition groups as interactive chip rows with drag-and-drop reordering, chip editing via popovers, connector toggling, and entry removal.
Uncontrolled (manages its own state):
import { Output } from "react-conditional-ui";
<Output fields={fields} operators={operators} />;Controlled:
<Output groups={groups} fields={fields} operators={operators} onGroupsChange={setGroups} />Read-only (pass groups without onGroupsChange):
<Output groups={groups} fields={fields} operators={operators} />The <Input /> parser converts free-text into a ConditionGroup which the <Output /> renders. The full type hierarchy:
ConditionGroup
├── id: string
├── config?: GroupConfig
└── entries: ConditionEntry[]
├── id: string
├── connector: "and" | "or"
└── condition: ParsedCondition
├── field: { raw, value, label, isValid }
├── operator: { raw, value, label, isValid }
└── value: { raw, value, label, isValid, errorMessage?, matchedOption? }
For example, typing "status is active and age greater than 18" produces:
{
"id": "g1",
"entries": [
{
"id": "e1",
"connector": "and",
"condition": {
"field": { "raw": "status", "value": "status", "label": "Status", "isValid": true },
"operator": { "raw": "is", "value": "is", "label": "is", "isValid": true },
"value": { "raw": "active", "value": "active", "label": "active", "isValid": true }
}
},
{
"id": "e2",
"connector": "and",
"condition": {
"field": { "raw": "age", "value": "age", "label": "Age", "isValid": true },
"operator": { "raw": "greater than", "value": "gt", "label": "greater than", "isValid": true },
"value": { "raw": "18", "value": "18", "label": "18", "isValid": true }
}
}
]
}This is the same object surfaced by onConditionsChange (as an array of groups), onSubmit on the <Input />, and useConditionalOutput's groups state.
Use these when you want to keep parser behavior but tailor UI/interaction details.
<ConditionalUI />: passInputComponentand/orOutputComponentto replace either half of the default UI.<Input />: customizeplaceholder,className, andstyle.<Output />: customizedefaultGroupConfig,className, andstyle.- All components support controlled patterns (
value/onChange,groups/onGroupsChange) where applicable.
<ConditionalUI
fields={fields}
InputComponent={MyInput}
OutputComponent={MyOutput}
onConditionsChange={setGroups}
/>FieldOption supports per-field parsing behavior:
operators: override allowed operators for a specific fieldfieldValues: provide known values (useful for enum-like suggestions)type: built-in value checks ("text" | "number" | "enum")validateValue: custom validator (trueor error string)
Each ConditionGroup can define config:
const group: ConditionGroup = {
id: "1",
entries: [...],
config: {
editable: false,
removable: false,
variant: "filled", // "outlined" (default) or "filled"
label: "Filters",
},
};Set defaults for all groups with defaultGroupConfig on <Output />.
Use hooks when you want your own input/output rendering and state wiring.
Lowest-level API: returns parseComplexCondition, getSuggestion, getCompletions, diagnose, and provider. Use it when you already control input state and submit flow.
import { useConditionDataProvider, DEFAULT_OPERATORS } from "react-conditional-ui";
const { parseComplexCondition, getSuggestion, diagnose } = useConditionDataProvider({
fields,
operators: DEFAULT_OPERATORS,
});
const group = parseComplexCondition(raw);
const issues = diagnose(raw);Input-state helper for controlled/uncontrolled text, submit validation, and diagnostics.
Group-state + mutations without rendering <Output />; use this to build your own chips/list/table UI.
Includes helpers like addGroup, removeEntry, toggleConnector, updateCondition, updateGroupConfig, reordering/move helpers, and setGroups.
import { useConditionalOutput } from "react-conditional-ui";
const { groups, mutations } = useConditionalOutput({
onGroupsChange: (groups) => console.log(groups),
});
mutations.addGroup(parsedGroup);All components accept className and style props. Internal elements use rcui-* CSS classes that can be overridden.
- Parsing/validation issues are exposed as
Diagnostic[](start,end,message) viauseConditionalInputand controlled<Input />mode. - Managed input submit is fail-safe: invalid conditions are not emitted via
onSubmit; diagnostics are shown instead. - Use
useConditionDataProvider().diagnose(text)when building custom UIs andFieldOption.validateValuefor field-specific validation rules.
The library uses the debug package. Logs are silent by default. Enable them to see how the fuzzy parser resolves fields, operators, and values:
// Browser — enable all library logs
localStorage.debug = "react-conditional-ui:*";
// Browser — specific namespace only
localStorage.debug = "react-conditional-ui:parser";# Node / SSR
DEBUG=react-conditional-ui:* node app.jsAvailable namespaces: parser, match-engine.
npm install
npm run dev
npm run build
npm test
npm run lint
npm run format