Builder Ref
Builder ref API
export interface IBuilderRef {cloneNode: (nodeId: string) => boolean;deleteNode: (nodeId: string) => boolean;replaceNode: (nodeId: string, node: NormalizedNode) => boolean;updateNode: (nodeId: string,updater: (node: NormalizedNode) => NormalizedNode) => boolean;insertNodes: (nodes: NormalizedQuery,index: number,parentId?: string) => boolean;addNode: (node: NormalizedNode, parentId?: string, index?: number) => boolean;addGroup: (groupType?: QueryGroupType,parentId?: string,index?: number) => boolean;addRule: (rule?: Partial<INormalizedRuleNode>,parentId?: string,index?: number) => boolean;moveNode: (nodeId: string, index: number, parentId?: string) => boolean;setNodeLock: (nodeId: string,state: 'unlocked' | 'self' | 'all') => boolean;lockNode: (nodeId: string, state?: 'self' | 'all') => boolean;unlockNode: (nodeId: string) => boolean;getNodeById: (nodeId: string) => NormalizedNode | undefined;getNearestField: (currentNodeId: string,targetFieldName: string) => INearestFieldMatch | undefined;isFieldInUse: (field: string) => boolean;getFieldOptionState: (field: string) => IBuilderFieldOptionState;getRuleOptionState: (ruleId: string) => IBuilderFieldOptionState;subscribeToFieldOptionState: (field: string,listener: BuilderFieldOptionStateListener) => () => void;subscribeToRuleOptionState: (ruleId: string,listener: BuilderFieldOptionStateListener) => () => void;setFieldOptions: (field: string,options:| BuilderFieldOption[]| ((current: BuilderFieldOption[]) => BuilderFieldOption[])) => void;setRuleOptions: (ruleId: string,options:| BuilderFieldOption[]| ((current: BuilderFieldOption[]) => BuilderFieldOption[])) => void;setFieldOptionsStatus: (field: string,status: BuilderFieldOptionsStatus) => void;setRuleOptionsStatus: (ruleId: string,status: BuilderFieldOptionsStatus) => void;invalidateFieldOptions: (field: string) => void;reloadFieldOptions: (field: string) => void;clearFieldOptions: (field: string) => void;invalidateRuleOptions: (ruleId: string) => void;reloadRuleOptions: (ruleId: string) => void;clearRuleOptions: (ruleId: string) => void;reconcileRuleValueWithOptions: (ruleId: string,config: IBuilderRuleValueReconciliationConfig) => boolean;getNodes: () => NormalizedQuery;getData: () => DenormalizedQuery;getHistory: () => IBuilderHistoryState;setHistory: (history: IBuilderHistoryState) => void;undo: () => void;redo: () => void;}export type BuilderRefListener = (builder: IBuilderRef | null) => void;export type BuilderRuleDependenciesListener = (entries: IBuilderRuleDependencyEntry[]) => void;export type BuilderFieldDependenciesListener = BuilderRuleDependenciesListener;export type BuilderFieldOptionStateListener = (state: IBuilderFieldOptionState) => void;export type BuilderRef = React.MutableRefObject<IBuilderRef | null> & {subscribe: (listener: BuilderRefListener) => () => void;bindRuleOptions: (field: string,config: IBuilderRuleOptionsBindingConfig) => () => void;subscribeToRuleDependencies: (field: string,dependencyFields: string[],listener: BuilderRuleDependenciesListener) => () => void;subscribeToFieldDependencies: (field: string,dependencyFields: string[],listener: BuilderFieldDependenciesListener) => () => void;subscribeToFieldOptionState: (field: string,listener: BuilderFieldOptionStateListener) => () => void;subscribeToRuleOptionState: (ruleId: string,listener: BuilderFieldOptionStateListener) => () => void;reconcileRuleValueWithOptions: (ruleId: string,config: IBuilderRuleValueReconciliationConfig) => boolean;};export const useBuilderRef = (): BuilderRef;
Rule dependencies hook
export const useBuilderRuleDependencies = (builderRef: BuilderRef,field: string,dependencyFields: string[]): IBuilderRuleDependencyEntry[];
Rule options binding
export interface IBuilderRuleOptionsResolverContext {ruleId: string;field: string;dependencies: Record<string, INearestFieldMatch | undefined>;signal: AbortSignal;}export interface IBuilderRuleOptionsBindingConfig {dependencies: string[];resolve: (context: IBuilderRuleOptionsResolverContext) => Promise<BuilderFieldOption[]>;onError?: (error: unknown,context: Omit<IBuilderRuleOptionsResolverContext, 'signal'>) => void;onOptionsResolved?: (context: {ruleId: string;field: string;dependencies: Record<string, INearestFieldMatch | undefined>;options: BuilderFieldOption[];}) => void;clearOnMissingDependencies?: boolean;}
How to attach it
useBuilderRef()Returns a typed React ref controller for the builder instance.useBuilderRuleDependencies(builderRef, field, dependencyFields)Returns one dependency snapshot per matching rule and is the recommended React-first integration for React Query or similar hook-based data layers.<Builder ref={builderRef} />Attaches the ref to the builder sobuilderRef.currentexposes the imperative methods.builderRef.subscribe(listener)Subscribes to builder handle updates. The listener fires immediately with the current handle and then again whenever committed builder state replaces that handle.builderRef.bindRuleOptions(field, config)Automatically hydrates and refreshes rule-scoped options for dependency-aware fields. This is the recommended entrypoint when you do not need an external query library to own the orchestration, andonOptionsResolvedis the clean place for follow-up work such as explicit value reconciliation.builderRef.subscribeToRuleDependencies(field, dependencyFields, listener)Subscribes to dependency snapshots for one field. The listener receives one entry per matching rule and only re-runs when that rule's dependency context changes.builderRef.subscribeToFieldOptionState(field, listener)andbuilderRef.subscribeToRuleOptionState(ruleId, listener)Subscribe to reactive loading and option snapshots for external UI such as badges, spinners, or helper text.
Reactive option state
getFieldOptionState() and getRuleOptionState() return snapshots. Use subscribeToFieldOptionState() or subscribeToRuleOptionState() when surrounding React UI should rerender as the state changes.Read methods
getNodeById(nodeId)Returns one normalized node by id, orundefinedwhen it does not exist.getNodes()Returns the current normalized query array.getData()Returns the current denormalized query tree in the same shape emitted byonChange.getHistory()Returns the current history object withpastandfuturestacks.getNearestField(currentNodeId, targetFieldName)Returns the nearest matching rule in the current ancestor chain. This is especially useful for dependency-aware rule options.isFieldInUse(field)Returnstruewhen at least one rule currently targets the given field.getFieldOptionState(field)Returns the shared runtime option list and loading status for a field.getRuleOptionState(ruleId)Returns the rule-scoped runtime option list and loading status for one rule instance.bindRuleOptions(field, config)Resolves dependency-aware options, setsloading,success, anderrorstates, aborts stale requests, and clears removed rules automatically. UseonOptionsResolvedwhen you want to run post-load logic such asreconcileRuleValueWithOptions(...).subscribeToRuleDependencies(field, dependencyFields, listener)Emits dependency entries such as the nearest country for every city rule, which is ideal for dependency-aware dynamic options.subscribeToFieldOptionState(field, listener)andsubscribeToRuleOptionState(ruleId, listener)Emit reactive option-state snapshots so external UI can reflectidle,loading,success, orerrorwithout waiting for unrelated renders.reconcileRuleValueWithOptions(ruleId, { strategy } )Reconciles the current rule value against the effective option list. The built-inclear-if-missingstrategy is useful when a value should be cleared once it is no longer available after a dependency-driven reload.
Mutation methods
cloneNode(nodeId)Clones a rule or group subtree directly below the original node and preserves its read-only configuration.deleteNode(nodeId)Removes a node subtree unless the node itself or one of its descendants is protected by effective read-only state.replaceNode(nodeId, node)Replaces a normalized node directly.updateNode(nodeId, updater)Reads the current normalized node, passes it to an updater, and replaces it with the updater result.insertNodes(nodes, index, parentId?)Inserts one or more normalized nodes at the target index, either at the root or inside a group.addNode(node, parentId?, index?)Inserts one normalized node and appends it whenindexis omitted.addGroup(groupType?, parentId?, index?)Creates and inserts a new group node.addRule(rule?, parentId?, index?)Creates and inserts a new rule node with optional initial values.moveNode(nodeId, index, parentId?)Moves a node to a new index and optional parent group.
Field Option Methods
setFieldOptions(field, options)Replaces the shared runtime option set for a field without changing the originalfieldsprop.setFieldOptionsStatus(field, status)Stores a shared option loading state of'idle','loading','success', or'error'.invalidateFieldOptions(field)Clears the shared runtime cache and falls back to the static options defined infield.value.reloadFieldOptions(field)Invalidates the shared runtime cache and then callsonFieldOptionsReload(field)so the surrounding app can trigger a refetch.clearFieldOptions(field)Removes the shared runtime option state entirely.
Rule Option Methods
setRuleOptions(ruleId, options)Replaces the runtime option set for one specific rule instance.setRuleOptionsStatus(ruleId, status)Stores a loading state for one specific rule instance.invalidateRuleOptions(ruleId)Clears the rule-scoped runtime cache and falls back to field-scoped or static options.reloadRuleOptions(ruleId)Invalidates the rule-scoped runtime cache and then callsonRuleOptionsReload(ruleId).clearRuleOptions(ruleId)Removes the rule-scoped runtime option state entirely.reconcileRuleValueWithOptions(ruleId, { strategy: 'clear-if-missing' })Compares the current rule value against the effective option list for that rule and clears missing selections explicitly instead of doing it automatically on every reload.
Lock and history methods
setNodeLock(nodeId, state)Sets the explicit lock state for a rule or group. Groups additionally support'all'for descendant inheritance.lockNode(nodeId, state?)Convenience wrapper for locking a node. For rules, the effective lock state is always'self'.unlockNode(nodeId)Clears the node's lock state while preserving object-basedreadOnly.targetsmetadata so it can be restored by later lock toggles.undo()andredo()Replay history steps when history is enabled.setHistory(history)Replaces the current history state. This is useful for clearing or restoring custom history snapshots.
Documentation