UNPKG

react-querybuilder

Version:

React Query Builder component for constructing queries and filters, with utilities for executing them in various database and evaluation contexts

1,439 lines (1,431 loc) 65.1 kB
import { AccessibleDescriptionGenerator, ActionElementEventHandler, BaseOption, BaseOptionMap, BaseTranslation, BaseTranslationWithLabel, BaseTranslationWithPlaceholders, BaseTranslations, Classname, Classnames, CommonRuleSubComponentProps, DropEffect, FlexibleOption, FlexibleOptionList, FlexibleOptionListProp, FullCombinator, FullField, FullOperator, FullOption, FullOptionList, FullOptionMap, FullOptionRecord, GenericizeRuleGroupType, GetOptionIdentifierType, GetRuleTypeFromGroupWithFieldAndOperator, GroupOptions, InputType, MatchConfig, MatchMode, MatchModeOptions, MoveOptions, Option, OptionGroup, OptionList, ParseNumberMethod, ParseNumbersPropConfig, Path, PrepareOptionListParams, PreparedOptionList, QueryActions, QueryBuilderFlags, QueryValidator, RemoveNullability, RuleGroupType, RuleGroupTypeAny, RuleGroupTypeIC, RuleOrGroupArray, RuleType, ToFullOption, ValidationMap, ValidationResult, ValueChangeEventHandler, ValueEditorType, ValueSource, ValueSourceFlexibleOptions, ValueSourceFullOptions, ValueSources, WithUnknownIndex } from "@react-querybuilder/core"; import * as React from "react"; import { ChangeEvent, ComponentType, Context, ForwardRefExoticComponent, MouseEvent, ReactNode, Ref, RefAttributes } from "react"; import { EnhancedStore, Slice, StoreEnhancer, ThunkDispatch, Tuple, UnknownAction } from "@reduxjs/toolkit"; import { ReactReduxContextValue, TypedUseSelectorHook } from "react-redux"; //#region ../../node_modules/type-fest/source/set-non-nullable.d.ts /** Create a type that makes the given keys non-nullable, while keeping the remaining keys as is. If no keys are given, all keys will be made non-nullable. Use-case: You want to define a single model where the only thing that changes is whether or not some or all of the keys are non-nullable. @example ``` import type {SetNonNullable} from 'type-fest'; type Foo = { a: number | null; b: string | undefined; c?: boolean | null; }; // Note: In the following example, `c` can no longer be `null`, but it's still optional. type SomeNonNullable = SetNonNullable<Foo, 'b' | 'c'>; //=> {a: null | number; b: string; c?: boolean} type AllNonNullable = SetNonNullable<Foo>; //=> {a: number; b: string; c?: boolean} ``` @category Object */ type SetNonNullable<BaseType, Keys extends keyof BaseType = keyof BaseType> = { [Key in keyof BaseType]: Key extends Keys ? NonNullable<BaseType[Key]> : BaseType[Key] }; //#endregion //#region src/components/RuleGroup.d.ts /** * Default component to display {@link RuleGroupType} and {@link RuleGroupTypeIC} * objects. This is actually a small wrapper around {@link RuleGroupHeaderComponents} * and {@link RuleGroupBodyComponents}. * * @group Components */ declare const RuleGroup: React.MemoExoticComponent<(props: RuleGroupProps) => React.JSX.Element>; /** * Renders a `React.Fragment` containing an array of form controls for managing * a {@link RuleGroupType} or {@link RuleGroupTypeIC}. * * @group Components */ declare const RuleGroupHeaderComponents: React.MemoExoticComponent<(rg: UseRuleGroup) => React.JSX.Element>; /** * Renders a `React.Fragment` containing an array of either (1) {@link Rule} and * {@link RuleGroup}, or (2) {@link Rule}, {@link RuleGroup}, and {@link InlineCombinator}. * * @group Components */ declare const RuleGroupBodyComponents: React.MemoExoticComponent<(rg: UseRuleGroup) => React.JSX.Element>; interface UseRuleGroup extends RuleGroupProps { addGroup: ActionElementEventHandler; addRule: ActionElementEventHandler; accessibleDescription: string; muted?: boolean; classNames: Pick<{ [k in keyof Classnames]: string }, "header" | "shiftActions" | "dragHandle" | "combinators" | "notToggle" | "addRule" | "addGroup" | "cloneGroup" | "lockGroup" | "muteGroup" | "removeGroup" | "body">; cloneGroup: ActionElementEventHandler; onCombinatorChange: ValueChangeEventHandler; onGroupAdd: (group: RuleGroupTypeAny, parentPath: Path, context?: any) => void; onIndependentCombinatorChange: (value: any, index: number, context?: any) => void; onNotToggleChange: (checked: boolean, context?: any) => void; outerClassName: string; pathsMemo: { path: Path; disabled: boolean; }[]; removeGroup: ActionElementEventHandler; ruleGroup: RuleGroupType | RuleGroupTypeIC; shiftGroupDown: (event?: MouseEvent, context?: any) => void; shiftGroupUp: (event?: MouseEvent, context?: any) => void; toggleLockGroup: ActionElementEventHandler; toggleMuteGroup: ActionElementEventHandler; validationClassName: string; validationResult: boolean | ValidationResult; } /** * Prepares all values and methods used by the {@link RuleGroup} component. * * @group Hooks */ declare const useRuleGroup: (props: RuleGroupProps) => UseRuleGroup; //#endregion //#region src/types/props.d.ts /** * Base interface for all subcomponents. * * @group Props */ interface CommonSubComponentProps<F extends FullOption = FullField, O extends string = string> { /** * CSS classNames to be applied. * * This is `string` and not {@link Classname} because the {@link Rule} * and {@link RuleGroup} components run `clsx()` to produce the `className` * that gets passed to each subcomponent. */ className?: string; /** * Path to this subcomponent's rule/group within the query. */ path: Path; /** * The level of the current group. Always equal to `path.length`. */ level: number; /** * The title/tooltip for this control. */ title?: string; /** * Disables the control. */ disabled?: boolean; /** * Container for custom props that are passed to all components. */ context?: any; /** * Validation result of the parent rule/group. */ validation?: boolean | ValidationResult; /** * Test ID for this component. */ testID?: string; /** * All subcomponents receive the configuration schema as a prop. */ schema: Schema<F, O>; } /** * Base interface for selectors and editors. * * @group Props */ interface SelectorOrEditorProps<F extends FullOption = FullField, O extends string = string> extends CommonSubComponentProps<F, O> { value?: string; handleOnChange(value: any): void; } /** * Base interface for selector components. */ interface BaseSelectorProps<OptType extends Option> extends SelectorOrEditorProps<ToFullOption<OptType>> { options: FullOptionList<OptType>; } /** * Props for all `value` selector components. * * @group Props */ interface ValueSelectorProps<OptType extends Option = FullOption> extends BaseSelectorProps<OptType> { multiple?: boolean; listsAsArrays?: boolean; } /** * Props for `combinatorSelector` components. * * @group Props */ interface CombinatorSelectorProps extends BaseSelectorProps<FullOption> { options: FullOptionList<FullCombinator>; rules: RuleOrGroupArray; ruleGroup: RuleGroupTypeAny; } /** * Props for `fieldSelector` components. * * @group Props */ interface FieldSelectorProps<F extends FullField = FullField> extends BaseSelectorProps<F>, CommonRuleSubComponentProps { operator?: F extends FullField<string, infer OperatorName> ? OperatorName : string; } /** * Props for `matchModeEditor` components. * * @group Props */ interface MatchModeEditorProps extends BaseSelectorProps<FullOption>, CommonRuleSubComponentProps { match: MatchConfig; selectorComponent?: ComponentType<ValueSelectorProps>; numericEditorComponent?: ComponentType<ValueEditorProps>; thresholdPlaceholder?: string; classNames: { matchMode: string; matchThreshold: string; }; options: FullOptionList<FullOption<MatchMode>>; field: string; fieldData: FullField; } /** * Props for `operatorSelector` components. * * @group Props */ interface OperatorSelectorProps extends BaseSelectorProps<FullOption>, CommonRuleSubComponentProps { options: FullOptionList<FullOperator>; field: string; fieldData: FullField; } /** * Props for `valueSourceSelector` components. * * @group Props */ interface ValueSourceSelectorProps extends BaseSelectorProps<FullOption>, CommonRuleSubComponentProps { options: FullOptionList<FullOption<ValueSource>>; field: string; fieldData: FullField; } /** * Utility type representing props for selector components * that could potentially be any of the standard selector types. * * @group Props */ type VersatileSelectorProps = ValueSelectorProps & Partial<FieldSelectorProps> & Partial<OperatorSelectorProps> & Partial<CombinatorSelectorProps>; /** * A translation for a component with `title` and `label`. * * @group Props */ interface TranslationWithLabel extends BaseTranslationWithLabel<ReactNode> {} /** * A translation for a component with `title` only. * * @group Props */ interface Translation extends BaseTranslation {} /** * A translation for a component with `title` and a placeholder. * * @group Props */ interface TranslationWithPlaceholders extends BaseTranslationWithPlaceholders {} /** * The shape of the `translations` prop. * * @group Props */ interface Translations extends BaseTranslations<ReactNode> {} /** * The full `translations` interface with all properties required. * * @group Props */ type TranslationsFull = { [K in keyof Translations]: { [T in keyof Translations[K]]-?: Translations[K][T] } }; /** * Props passed to every action component (rendered as `<button>` by default). * * @group Props */ interface ActionProps extends CommonSubComponentProps { /** Visible text. */ label?: ReactNode; /** * Triggers the action, e.g. the addition of a new rule or group. The second parameter * will be forwarded to the `onAddRule` or `onAddGroup` callback if appropriate. */ handleOnClick(e?: MouseEvent, context?: any): void; /** * Translation which overrides the regular `label`/`title` props when * the element is disabled. */ disabledTranslation?: TranslationWithLabel; /** * The {@link RuleType} or {@link RuleGroupType}/{@link RuleGroupTypeIC} * associated with this element. */ ruleOrGroup: RuleGroupTypeAny | RuleType; /** * Rules in this group (if the action element is for a group). */ rules?: RuleOrGroupArray; } /** * Props passed to every group action component. * * @deprecated Use {@link ActionProps} instead. * @group Props */ interface ActionWithRulesProps extends ActionProps {} /** * Props passed to every action component that adds a rule or group. * * @deprecated Use {@link ActionProps} instead. * @group Props */ interface ActionWithRulesAndAddersProps extends ActionProps {} /** * Props for `notToggle` components. * * @group Props */ interface NotToggleProps extends CommonSubComponentProps { checked?: boolean; handleOnChange(checked: boolean): void; label?: ReactNode; ruleGroup: RuleGroupTypeAny; } /** * Props passed to `shiftActions` components. * * @group Props */ interface ShiftActionsProps extends CommonSubComponentProps { /** * Visible text for "shift up"/"shift down" elements. */ labels?: { shiftUp?: ReactNode; shiftDown?: ReactNode; }; /** * Tooltips for "shift up"/"shift down" elements. */ titles?: { shiftUp?: string; shiftDown?: string; }; /** * The {@link RuleType} or {@link RuleGroupType}/{@link RuleGroupTypeIC} * associated with this element. */ ruleOrGroup: RuleGroupTypeAny | RuleType; /** * Method to shift the rule/group up one place. */ shiftUp?: () => void; /** * Method to shift the rule/group down one place. */ shiftDown?: () => void; /** * Whether shifting the rule/group up is disallowed. */ shiftUpDisabled?: boolean; /** * Whether shifting the rule/group down is disallowed. */ shiftDownDisabled?: boolean; } /** * Props for `dragHandle` components. * * @group Props */ interface DragHandleProps extends CommonSubComponentProps { label?: ReactNode; ruleOrGroup: RuleGroupTypeAny | RuleType; } /** * Props passed to `inlineCombinator` components. * * @group Props */ interface InlineCombinatorProps extends CombinatorSelectorProps { component: ComponentType<CombinatorSelectorProps>; } /** * Props passed to `valueEditor` components. * * @group Props */ interface ValueEditorProps<F extends FullField = FullField, O extends string = string> extends SelectorOrEditorProps<F, O>, CommonRuleSubComponentProps { field: GetOptionIdentifierType<F>; operator: O; value?: any; valueSource: ValueSource; /** The entire {@link FullField} object. */ fieldData: F; type?: ValueEditorType; inputType?: InputType | null; values?: any[]; listsAsArrays?: boolean; parseNumbers?: ParseNumbersPropConfig; separator?: ReactNode; selectorComponent?: ComponentType<ValueSelectorProps>; /** * Only pass `true` if the {@link useValueEditor} hook has already run * in a parent/ancestor component. See usage in the compatibility packages. */ skipHook?: boolean; schema: Schema<F, O>; } /** * All subcomponents. * * @group Props */ type Controls<F extends FullField, O extends string> = Required<SetNonNullable<ControlElementsProp<F, O>, keyof ControlElementsProp<F, O>>>; /** * Subcomponents. * * @group Props */ type ControlElementsProp<F extends FullField, O extends string> = Partial<{ /** * Default component for all button-type controls. * * @default ActionElement */ actionElement: ComponentType<ActionProps>; /** * Adds a sub-group to the current group. * * @default ActionElement */ addGroupAction: ComponentType<ActionProps> | null; /** * Adds a rule to the current group. * * @default ActionElement */ addRuleAction: ComponentType<ActionProps> | null; /** * Clones the current group. * * @default ActionElement */ cloneGroupAction: ComponentType<ActionProps> | null; /** * Clones the current rule. * * @default ActionElement */ cloneRuleAction: ComponentType<ActionProps> | null; /** * Selects the `combinator` property for the current group, or the current independent combinator value. * * @default ValueSelector */ combinatorSelector: ComponentType<CombinatorSelectorProps> | null; /** * Provides a draggable handle for reordering rules and groups. * * @default DragHandle */ dragHandle: ForwardRefExoticComponent<DragHandleProps & RefAttributes<HTMLElement>> | null; /** * Selects the `field` property for the current rule. * * @default ValueSelector */ fieldSelector: ComponentType<FieldSelectorProps<F>> | null; /** * A small wrapper around the `combinatorSelector` component. * * @default InlineCombinator */ inlineCombinator: ComponentType<InlineCombinatorProps> | null; /** * Locks the current group (sets the `disabled` property to `true`). * * @default ActionElement */ lockGroupAction: ComponentType<ActionProps> | null; /** * Locks the current rule (sets the `disabled` property to `true`). * * @default ActionElement */ lockRuleAction: ComponentType<ActionProps> | null; /** * Mutes the current group (sets the `muted` property to `true`). * * @default ActionElement */ muteGroupAction: ComponentType<ActionProps> | null; /** * Mutes the current rule (sets the `muted` property to `true`). * * @default ActionElement */ muteRuleAction: ComponentType<ActionProps> | null; /** * Selects the `match` property for the current rule. * * @default MatchModeEditor */ matchModeEditor: ComponentType<MatchModeEditorProps> | null; /** * Toggles the `not` property of the current group between `true` and `false`. * * @default NotToggle */ notToggle: ComponentType<NotToggleProps> | null; /** * Selects the `operator` property for the current rule. * * @default ValueSelector */ operatorSelector: ComponentType<OperatorSelectorProps> | null; /** * Removes the current group from its parent group's `rules` array. * * @default ActionElement */ removeGroupAction: ComponentType<ActionProps> | null; /** * Removes the current rule from its parent group's `rules` array. * * @default ActionElement */ removeRuleAction: ComponentType<ActionProps> | null; /** * Rule layout component. * * @default Rule */ rule: ComponentType<RuleProps>; /** * Rule group layout component. * * @default RuleGroup */ ruleGroup: ComponentType<RuleGroupProps<F, O>>; /** * Rule group body components. * * @default RuleGroupBodyComponents */ ruleGroupBodyElements: ComponentType<RuleGroupProps & UseRuleGroup>; /** * Rule group header components. * * @default RuleGroupHeaderComponents */ ruleGroupHeaderElements: ComponentType<RuleGroupProps & UseRuleGroup>; /** * Shifts the current rule/group up or down in the query hierarchy. * * @default ShiftActions */ shiftActions: ComponentType<ShiftActionsProps> | null; /** * Updates the `value` property for the current rule. * * @default ValueEditor */ valueEditor: ComponentType<ValueEditorProps<F, O>> | null; /** * Default component for all value selector controls. * * @default ValueSelector */ valueSelector: ComponentType<ValueSelectorProps>; /** * Selects the `valueSource` property for the current rule. * * @default ValueSelector */ valueSourceSelector: ComponentType<ValueSourceSelectorProps> | null; }>; /** * Configuration options passed in the `schema` prop from * {@link QueryBuilder} to each subcomponent. * * @group Props */ interface Schema<F extends FullField, O extends string> { qbId: string; fields: FullOptionList<F>; fieldMap: Partial<Record<GetOptionIdentifierType<F>, F>>; classNames: Classnames; combinators: FullOptionList<FullCombinator>; controls: Controls<F, O>; createRule(): RuleType; createRuleGroup(ic?: boolean): RuleGroupTypeAny; dispatchQuery(query: RuleGroupTypeAny): void; getQuery(): RuleGroupTypeAny; getOperators(field: string, meta: { fieldData: F; }): FullOptionList<FullOperator>; getValueEditorType(field: string, operator: string, meta: { fieldData: F; }): ValueEditorType; getValueEditorSeparator(field: string, operator: string, meta: { fieldData: F; }): ReactNode; getValueSources(field: string, operator: string, meta: { fieldData: F; }): ValueSourceFullOptions; getInputType(field: string, operator: string, meta: { fieldData: F; }): InputType | null; getValues(field: string, operator: string, meta: { fieldData: F; }): FullOptionList<Option>; getMatchModes(field: string, misc: { fieldData: F; }): MatchModeOptions; getSubQueryBuilderProps(field: GetOptionIdentifierType<F>, misc: { fieldData: F; }): QueryBuilderProps<RuleGroupTypeAny, FullOption, FullOption, FullOption>; getRuleClassname(rule: RuleType, misc: { fieldData: F; }): Classname; getRuleGroupClassname(ruleGroup: RuleGroupTypeAny): Classname; accessibleDescriptionGenerator: AccessibleDescriptionGenerator; showCombinatorsBetweenRules: boolean; showNotToggle: boolean; showShiftActions: boolean; showCloneButtons: boolean; showLockButtons: boolean; showMuteButtons: boolean; autoSelectField: boolean; autoSelectOperator: boolean; autoSelectValue: boolean; addRuleToNewGroups: boolean; enableDragAndDrop: boolean; validationMap: ValidationMap; independentCombinators: boolean; listsAsArrays: boolean; parseNumbers: ParseNumbersPropConfig; disabledPaths: Path[]; suppressStandardClassnames: boolean; maxLevels: number; } /** * Common props between {@link Rule} and {@link RuleGroup}. */ interface CommonRuleAndGroupProps<F extends FullField = FullField, O extends string = string> { id?: string; path: Path; parentDisabled?: boolean; parentMuted?: boolean; translations: Translations; schema: Schema<F, O>; actions: QueryActions; disabled?: boolean; shiftUpDisabled?: boolean; shiftDownDisabled?: boolean; context?: any; } /** * Return type of {@link @react-querybuilder/dnd!useRuleGroupDnD} hook. */ interface UseRuleGroupDnD { isDragging: boolean; dragMonitorId: string | symbol; isOver: boolean; dropMonitorId: string | symbol; previewRef: Ref<HTMLDivElement>; dragRef: Ref<HTMLSpanElement>; dropRef: Ref<HTMLDivElement>; /** `"move"` by default; `"copy"` if the modifier key is pressed. */ dropEffect?: DropEffect; /** True if the dragged and hovered items should form a new group. */ groupItems?: boolean; dropNotAllowed?: boolean; } /** * {@link RuleGroup} props. * * @group Props */ interface RuleGroupProps<F extends FullOption = FullOption, O extends string = string> extends CommonRuleAndGroupProps<F, O>, Partial<UseRuleGroupDnD> { ruleGroup: RuleGroupTypeAny<RuleType<GetOptionIdentifierType<F>, O>>; /** * @deprecated Use the `combinator` property of the `ruleGroup` prop instead */ combinator?: string; /** * @deprecated Use the `rules` property of the `ruleGroup` prop instead */ rules?: RuleOrGroupArray; /** * @deprecated Use the `not` property of the `ruleGroup` prop instead */ not?: boolean; } /** * Return type of {@link @react-querybuilder/dnd!useRuleDnD} hook. */ interface UseRuleDnD { isDragging: boolean; dragMonitorId: string | symbol; isOver: boolean; dropMonitorId: string | symbol; dragRef: Ref<HTMLSpanElement>; dndRef: Ref<HTMLDivElement>; /** `"move"` by default; `"copy"` if the modifier key is pressed. */ dropEffect?: DropEffect; /** True if the dragged and hovered items should form a new group. */ groupItems?: boolean; dropNotAllowed?: boolean; } /** * {@link Rule} props. * * @group Props */ interface RuleProps<F extends string = string, O extends string = string> extends CommonRuleAndGroupProps<FullOption<F>, O>, Partial<UseRuleDnD> { rule: RuleType<F, O>; /** * @deprecated Use the `field` property of the `rule` prop instead */ field?: string; /** * @deprecated Use the `operator` property of the `rule` prop instead */ operator?: string; /** * @deprecated Use the `value` property of the `rule` prop instead */ value?: any; /** * @deprecated Use the `valueSource` property of the `rule` prop instead */ valueSource?: ValueSource; } /** * Props passed down through context from a {@link QueryBuilderContextProvider}. * * @group Props */ interface QueryBuilderContextProps<F extends FullField = FullField, O extends string = string> extends QueryBuilderFlags { /** * Defines replacement components. */ controlElements?: ControlElementsProp<F, O>; /** * This can be used to assign specific CSS classes to various controls * that are rendered by {@link QueryBuilder}. */ controlClassnames?: Partial<Classnames>; /** * This can be used to override translatable texts applied to the various * controls that are rendered by {@link QueryBuilder}. */ translations?: Partial<Translations>; } /** * @group Props */ interface QueryBuilderContextProviderProps extends QueryBuilderContextProps { children?: ReactNode; } /** * @group Components */ type QueryBuilderContextProvider<ExtraProps extends object = Record<string, any>> = ComponentType<QueryBuilderContextProviderProps & ExtraProps>; /** * Props for {@link QueryBuilder}. * * Notes: * - Only one of `query` or `defaultQuery` should be provided. If `query` is present, * then `defaultQuery` should be undefined and vice versa. * - If rendered initially with a `query` prop, then `query` must be defined in every * subsequent render or warnings will be logged (in non-production modes only). * * @typeParam RG - The type of the query object, inferred from either the `query` or `defaultQuery` prop. * Must extend {@link RuleGroupType} or {@link RuleGroupTypeIC}. * @typeParam F - The field type (see {@link Field}). * @typeParam O - The operator type (see {@link Operator}). * @typeParam C - The combinator type (see {@link Combinator}). * * @group Props */ type QueryBuilderProps<RG extends RuleGroupTypeAny, F extends FullField, O extends FullOperator, C extends FullCombinator> = RG extends RuleGroupType<infer R> | RuleGroupTypeIC<infer R> ? QueryBuilderContextProps<F, GetOptionIdentifierType<O>> & { /** * Initial query object for uncontrolled components. */ defaultQuery?: RG; /** * Query object for controlled components. */ query?: RG; /** * List of valid {@link FullField}s. * * @default [] */ fields?: FlexibleOptionListProp<F> | BaseOptionMap<F>; /** * List of valid {@link FullOperator}s. * * @see {@link DefaultOperatorName} * * @default * [ * { name: '=', label: '=' }, * { name: '!=', label: '!=' }, * { name: '<', label: '<' }, * { name: '>', label: '>' }, * { name: '<=', label: '<=' }, * { name: '>=', label: '>=' }, * { name: 'contains', label: 'contains' }, * { name: 'beginsWith', label: 'begins with' }, * { name: 'endsWith', label: 'ends with' }, * { name: 'doesNotContain', label: 'does not contain' }, * { name: 'doesNotBeginWith', label: 'does not begin with' }, * { name: 'doesNotEndWith', label: 'does not end with' }, * { name: 'null', label: 'is null' }, * { name: 'notNull', label: 'is not null' }, * { name: 'in', label: 'in' }, * { name: 'notIn', label: 'not in' }, * { name: 'between', label: 'between' }, * { name: 'notBetween', label: 'not between' }, * ] */ operators?: FlexibleOptionListProp<O>; /** * List of valid {@link FullCombinator}s. * * @see {@link DefaultCombinatorName} * * @default * [ * {name: 'and', label: 'AND'}, * {name: 'or', label: 'OR'}, * ] */ combinators?: FlexibleOptionListProp<C>; /** * Default properties applied to all objects in the `fields` prop. Properties on * individual field definitions will override these. */ baseField?: Record<string, unknown>; /** * Default properties applied to all objects in the `operators` prop. Properties on * individual operator definitions will override these. */ baseOperator?: Record<string, unknown>; /** * Default properties applied to all objects in the `combinators` prop. Properties on * individual combinator definitions will override these. */ baseCombinator?: Record<string, unknown>; /** * The default `field` value for new rules. This can be the field `name` * itself or a function that returns a valid {@link FullField} `name` given * the `fields` list. */ getDefaultField?: GetOptionIdentifierType<F> | ((fieldsData: FullOptionList<F>) => string); /** * The default `operator` value for new rules. This can be the operator * `name` or a function that returns a valid {@link FullOperator} `name` for * a given field name. */ getDefaultOperator?: GetOptionIdentifierType<O> | ((field: GetOptionIdentifierType<F>, misc: { fieldData: F; }) => string); /** * Returns the default `value` for new rules. */ getDefaultValue?(rule: R, misc: { fieldData: F; }): any; /** * This function should return the list of allowed {@link FullOperator}s * for the given {@link FullField} `name`. If `null` is returned, the * {@link DefaultOperator}s are used. */ getOperators?(field: GetOptionIdentifierType<F>, misc: { fieldData: F; }): FlexibleOptionListProp<FullOperator> | null; /** * This function should return the type of {@link ValueEditor} (see * {@link ValueEditorType}) for the given field `name` and operator `name`. */ getValueEditorType?(field: GetOptionIdentifierType<F>, operator: GetOptionIdentifierType<O>, misc: { fieldData: F; }): ValueEditorType; /** * This function should return the separator element for a given field * `name` and operator `name`. The element can be any valid React element, * including a bare string (e.g., "and" or "to") or an HTML element like * `<span />`. It will be placed in between value editors when multiple * editors are rendered, such as when the `operator` is `"between"`. */ getValueEditorSeparator?(field: GetOptionIdentifierType<F>, operator: GetOptionIdentifierType<O>, misc: { fieldData: F; }): ReactNode; /** * This function should return the list of valid {@link ValueSources} * for a given field `name` and operator `name`. The return value must * be an array that includes at least one valid {@link ValueSource} * (i.e. `["value"]`, `["field"]`, `["value", "field"]`, or * `["field", "value"]`). */ getValueSources?(field: GetOptionIdentifierType<F>, operator: GetOptionIdentifierType<O>, misc: { fieldData: F; }): ValueSources | ValueSourceFlexibleOptions; /** * This function should return the `type` of `<input />` * for the given field `name` and operator `name` (only applicable when * `getValueEditorType` returns `"text"` or a falsy value). If no * function is provided, `"text"` is used as the default. */ getInputType?(field: GetOptionIdentifierType<F>, operator: GetOptionIdentifierType<O>, misc: { fieldData: F; }): InputType | null; /** * This function should return the list of allowed values for the * given field `name` and operator `name` (only applicable when * `getValueEditorType` returns `"select"` or `"radio"`). If no * function is provided, an empty array is used as the default. */ getValues?(field: GetOptionIdentifierType<F>, operator: GetOptionIdentifierType<O>, misc: { fieldData: F; }): FlexibleOptionListProp<Option>; /** * This function should return the list of valid {@link MatchMode}s or * {@link MatchConfig}s for a given field `name`. The return value must * be an array that includes at least one valid {@link MatchMode}, or `true` * to indicate that all match modes are allowed. Any other return value * will be ignored (no match modes will be allowed). */ getMatchModes?(field: GetOptionIdentifierType<F>, misc: { fieldData: F; }): boolean | MatchMode[] | FlexibleOption<MatchMode>[]; /** * This function should return any props that a subquery (see {@link MatchMode}) * should override from the props provided to this query builder. Note that certain * props like `query`, `onQueryChange`, and `enableDragAndDrop` will be ignored. */ getSubQueryBuilderProps?(field: GetOptionIdentifierType<F>, misc: { fieldData: F; }): QueryBuilderProps<GenericizeRuleGroupType<RG>, FullOption, FullOption, FullOption>; /** * The return value of this function will be used to apply classnames to the * outer `<div>` of the given {@link Rule}. */ getRuleClassname?(rule: R, misc: { fieldData: F; }): Classname; /** * The return value of this function will be used to apply classnames to the * outer `<div>` of the given {@link RuleGroup}. */ getRuleGroupClassname?(ruleGroup: RG): Classname; /** * This callback is invoked before a new rule is added. The function should either manipulate * the rule and return the new object, return `true` to allow the addition to proceed as normal, * or return `false` to cancel the addition of the rule. */ onAddRule?(rule: R, parentPath: Path, query: RG, context?: any): RuleType | boolean; /** * This callback is invoked before a new group is added. The function should either manipulate * the group and return the new object, return `true` to allow the addition to proceed as normal, * or return `false` to cancel the addition of the group. */ onAddGroup?(ruleGroup: RG, parentPath: Path, query: RG, context?: any): RG | boolean; /** * This callback is invoked before a rule is moved or shifted. The function should return * `true` to allow the move/shift to proceed as normal, `false` to cancel the move/shift, or * a new query object (presumably based on `query` or `nextQuery`) which will become the new * query state. */ onMoveRule?(rule: R, fromPath: Path, toPath: Path | "up" | "down", query: RG, nextQuery: RG, options: MoveOptions, context?: any): RG | boolean; /** * This callback is invoked before a group is moved or shifted. The function should return * `true` to allow the move/shift to proceed as normal, `false` to cancel the move/shift, or * a new query object (presumably based on `query` or `nextQuery`) which will become the new * query state. */ onMoveGroup?(ruleGroup: RG, fromPath: Path, toPath: Path | "up" | "down", query: RG, nextQuery: RG, options: MoveOptions, context?: any): RG | boolean; /** * This callback is invoked before a rule is grouped with another object. The function should * return `true` to allow the grouping to proceed as normal, `false` to cancel the grouping, * or a new query object (presumably based on `query` or `nextQuery`) which will become the new * query state. */ onGroupRule?(rule: R, fromPath: Path, toPath: Path, query: RG, nextQuery: RG, options: GroupOptions, context?: any): RG | boolean; /** * This callback is invoked before a group is grouped with another object. The function should * return `true` to allow the grouping to proceed as normal, `false` to cancel the grouping, * or a new query object (presumably based on `query` or `nextQuery`) which will become the new * query state. */ onGroupGroup?(ruleGroup: RG, fromPath: Path, toPath: Path, query: RG, nextQuery: RG, options: GroupOptions, context?: any): RG | boolean; /** * This callback is invoked before a rule or group is removed. The function should return * `true` if the rule or group should be removed or `false` if it should not be removed. */ onRemove?(ruleOrGroup: R | RG, path: Path, query: RG, context?: any): boolean; /** * This callback is invoked anytime the query state is updated. */ onQueryChange?(query: RG): void; /** * Each log object will be passed to this function when `debugMode` is `true`. * * @default console.log */ onLog?(obj: any): void; /** * @deprecated As of v7, this prop is ignored. To enable independent combinators, use * {@link RuleGroupTypeIC} for the `query` or `defaultQuery` prop. The query builder * will detect the query type and behave accordingly. */ independentCombinators?: boolean; /** * Disables the entire query builder if true, or the rules and groups at * the specified paths (as well as all child rules/groups and subcomponents) * if an array of paths is provided. If the root path is specified (`disabled={[[]]}`), * no changes to the query are allowed. * * @default false */ disabled?: boolean | Path[]; /** * Store values as numbers whenever possible. * * _**TIP: Try `"strict-limited"` first.**_ * * Options include `true`, `false`, `"enhanced"`, `"native"`, and `"strict"`. The `string` options * can be suffixed with `"-limited"`. * * - `false` avoids numeric parsing * - `true` or `"strict"` parses values using `numeric-quantity`, bailing out (returning the original * string) when trailing invalid characters are present * - `"enhanced"` is the same as `true`/`"strict"`, but ignores trailing invalid characters (CAUTION: * this can lead to information loss) * - `"native"` parses values using `parseFloat`, returning `NaN` when parsing fails * * When the value is `true` or a string without the "-limited" suffix, the default {@link ValueEditor} * will attempt to parse *all* inputs as numbers. **CAUTION: This can lead to unexpected behavior.** * * When the value is a string with the "-limited" suffix, the default {@link ValueEditor} will * only attempt to parse inputs as numbers when the `inputType` is `"number"`. * * @default false */ parseNumbers?: ParseNumbersPropConfig; /** * Query validation function. */ validator?: QueryValidator; /** * `id` generator function. Should always produce a unique/random value. * * @default crypto.randomUUID */ idGenerator?: () => string; /** * Generator function for the `title` attribute applied to the outermost `<div>` of each * rule group. As this is intended to help with accessibility, the text output from this * function should be meaningful, descriptive, and unique within the page. */ accessibleDescriptionGenerator?: AccessibleDescriptionGenerator; /** * Maximum number of levels deep the query is allowed to go. The minimum is 1; values * less than 1 will be ignored. */ maxLevels?: number; /** * Container for custom props that are passed to all components. */ context?: any; } : never; //#endregion //#region src/components/ActionElement.d.ts /** * Default `<button>` component used by {@link QueryBuilder}. * * @group Components */ declare const ActionElement: (props: ActionProps) => React.JSX.Element; //#endregion //#region src/components/DragHandle.d.ts /** * Default drag handle component used by {@link QueryBuilder} when `enableDragAndDrop` is `true`. * * @group Components */ declare const DragHandle: React.ForwardRefExoticComponent<DragHandleProps & React.RefAttributes<HTMLSpanElement>>; //#endregion //#region src/components/InlineCombinator.d.ts /** * Default `inlineCombinator` component used by {@link QueryBuilder}. A small `<div>` * wrapper around the `combinatorSelector` component, used when either * `showCombinatorsBetweenRules` or `independentCombinators` are `true`. * * @group Components */ declare const InlineCombinator: (allProps: InlineCombinatorProps) => React.JSX.Element; //#endregion //#region src/components/MatchModeEditor.d.ts /** * Default `matchModeEditor` component used by {@link QueryBuilder}. * * @group Components */ declare const MatchModeEditor: (props: MatchModeEditorProps) => React.JSX.Element | null; interface UseMatchModeEditor { thresholdNum: number; thresholdRule: RuleType; thresholdSchema: Schema<FullField, string>; handleChangeMode: (mode: MatchMode) => void; handleChangeThreshold: (threshold: number) => void; } declare const useMatchModeEditor: (props: MatchModeEditorProps) => UseMatchModeEditor; //#endregion //#region src/components/NotToggle.d.ts /** * Default `notToggle` (aka inversion) component used by {@link QueryBuilder}. * * @group Components */ declare const NotToggle: (props: NotToggleProps) => React.JSX.Element; //#endregion //#region src/hooks/useControlledOrUncontrolled.d.ts interface UseControlledOrUncontrolledParams { defaultQuery?: RuleGroupTypeAny; queryProp?: RuleGroupTypeAny; } /** * Logs a warning when the component changes from controlled to uncontrolled, * vice versa, or both `query` and `defaultQuery` are provided. * * @group Hooks */ declare const useControlledOrUncontrolled: (params: UseControlledOrUncontrolledParams) => void; //#endregion //#region src/hooks/useDeprecatedProps.d.ts /** * Logs an error to the console if any of the following are true: * - `QueryBuilder` is rendered with an `independentCombinators` prop * - `RuleGroup` is rendered with `combinator` or `rules` props (deprecated in favor of `ruleGroup`) * - `Rule` is rendered with `field`, `operator`, or `value` props (deprecated in favor of `rule`) * * @group Hooks */ declare function useDeprecatedProps(type: "independentCombinators", logWarning: boolean, otherParams: "invalid" | "unnecessary"): void; declare function useDeprecatedProps(type: "rule" | "ruleGroup", logWarning: boolean): void; //#endregion //#region src/hooks/useFields.d.ts interface UseFields<F extends FullField> { defaultField: FullField; fields: FullOptionList<F>; fieldMap: Partial<FullOptionRecord<FullField>>; } declare const useFields: <F extends FullField>(props: { translations: TranslationsFull; } & Pick<QueryBuilderProps<RuleGroupTypeAny, F, FullOperator, FullCombinator>, "fields" | "baseField" | "autoSelectField">) => UseFields<F>; //#endregion //#region src/hooks/useMergedContext.d.ts type UseMergedContextParams<F extends FullField = FullField, O extends string = string, Finalize extends boolean | undefined = undefined> = QueryBuilderContextProps<F, O> & { initialQuery?: RuleGroupTypeAny; qbId?: string; /** * When true, props and context are merged with defaults to ensure all properties * are defined. Action elements and value selectors are merged with their respective * bulk override components. Only needs to be true when run from `QueryBuilder`. */ finalize?: Finalize; }; interface UseMergedContext<F extends FullField = FullField, O extends string = string, Finalize extends boolean | undefined = undefined> extends QueryBuilderContextProps<F, O>, QueryBuilderFlags { enableDragAndDrop: Finalize extends true ? boolean : boolean | undefined; initialQuery?: RuleGroupTypeAny; qbId?: string; controlElements: Finalize extends true ? Controls<F, O> : Partial<Controls<F, O>>; controlClassnames: Classnames; translations: Finalize extends true ? TranslationsFull : Partial<Translations>; } /** * Merges inherited context values with props, giving precedence to props. * * @group Hooks */ declare const useMergedContext: <F extends FullField = FullField, O extends string = string, Finalize extends boolean | undefined = undefined>({ finalize, ...props }: UseMergedContextParams<F, O, Finalize>) => UseMergedContext<F, O, Finalize>; //#endregion //#region src/hooks/useOptionListProp.d.ts interface UseOptionListProp<O extends FullOption> extends PreparedOptionList<O> {} interface UseOptionListPropParams<O extends FullOption> extends PrepareOptionListParams<O> {} /** * @group Hooks * @deprecated Memoize the result of `prepareOptionList` instead. */ declare const useOptionListProp: <O extends FullOption>(props: UseOptionListPropParams<O>) => UseOptionListProp<O>; //#endregion //#region src/hooks/usePathsMemo.d.ts interface PathInfo { path: Path; disabled: boolean; } declare const usePathsMemo: ({ disabled, path, nestedArray, disabledPaths }: { disabled: boolean; path: Path; nestedArray: unknown[]; disabledPaths: Path[]; }) => PathInfo[]; //#endregion //#region src/hooks/usePreferProp.d.ts /** * For given default, prop, and context values, return the first provided of prop, * context, and default, in that order. * * @group Hooks */ declare const usePreferProp: (def: boolean, prop?: boolean, context?: boolean, doNotFinalize?: boolean) => boolean; /** * For given default, prop, and context values, return the first provided of prop, * context, and default, in that order. * * @group Hooks */ declare const usePreferAnyProp: (def?: any, prop?: any, context?: any) => any; //#endregion //#region src/hooks/usePrevious.d.ts /** * Returns the prop value from the last render. * * Adapted from https://usehooks.com/usePrevious/. * * @group Hooks */ declare const usePrevious: <T>(value: T) => T | null; //#endregion //#region src/hooks/useReactDndWarning.d.ts /** * Logs a warning if drag-and-drop is enabled but the required dependencies * (`react-dnd` and either `react-dnd-html5-backend` or `react-dnd-touch-backend`) * were not detected. * * @group Hooks */ declare const useReactDndWarning: (enableDragAndDrop: boolean, dndRefs: boolean) => void; //#endregion //#region src/hooks/useSelectElementChangeHandler.d.ts interface UseSelectElementChangeHandlerParams { onChange: (v: string | string[]) => void; multiple?: boolean; } /** * Returns a memoized change handler for HTML `<select>` elements. * * @group Hooks */ declare const useSelectElementChangeHandler: (params: UseSelectElementChangeHandlerParams) => ((e: ChangeEvent<HTMLSelectElement>) => void); //#endregion //#region src/hooks/useStopEventPropagation.d.ts interface RQBMouseEventHandler { (event?: MouseEvent, context?: any): void; } /** * Wraps an event handler function in another function that calls * `event.preventDefault()` and `event.stopPropagation()` first. The * returned function accepts and forwards a second `context` argument. * * @group Hooks */ declare const useStopEventPropagation: (method: RQBMouseEventHandler) => RQBMouseEventHandler; //#endregion //#region src/components/Rule.d.ts /** * Default component to display {@link RuleType} objects. This is * actually a small wrapper around {@link RuleComponents}. * * @group Components */ declare const Rule: React.MemoExoticComponent<(r: RuleProps) => React.JSX.Element>; interface RuleComponentsProps extends UseRule { subQuery?: UseRuleGroup; groupComponentsWrapper?: React.ComponentType<{ children: React.ReactNode; className: string; }>; } /** * Renders a `React.Fragment` containing an array of form controls for managing a {@link RuleType}. * * @group Components */ declare const RuleComponents: React.MemoExoticComponent<(r: RuleComponentsProps) => React.JSX.Element>; /** * @group Components */ declare const RuleWithSubQueryGroupComponentsWrapper: (props: React.PropsWithChildren) => React.JSX.Element; /** * @group Components */ declare const RuleComponentsWithSubQuery: React.MemoExoticComponent<(r: RuleComponentsProps) => React.JSX.Element>; interface UseRule extends RuleProps { classNames: { shiftActions: string; dragHandle: string; fields: string; matchMode: string; matchThreshold: string; operators: string; valueSource: string; value: string; cloneRule: string; lockRule: string; muteRule: string; removeRule: string; }; muted?: boolean; parentMuted?: boolean; cloneRule: ActionElementEventHandler; fieldData: FullField<string, string, string, FullOption, FullOption>; generateOnChangeHandler: (prop: Exclude<keyof RuleType, "id" | "path">) => ValueChangeEventHandler; onChangeValueSource: ValueChangeEventHandler; onChangeField: ValueChangeEventHandler; onChangeMatchMode: ValueChangeEventHandler; onChangeOperator: ValueChangeEventHandler; onChangeValue: ValueChangeEventHandler; hideValueControls: boolean; inputType: InputType | null; matchModes: MatchModeOptions; operators: OptionList<FullOperator>; outerClassName: string; removeRule: ActionElementEventHandler; shiftRuleUp: (event?: MouseEvent, _context?: any) => void; shiftRuleDown: (event?: MouseEvent, _context?: any) => void; subproperties: UseFields<FullField>; subQueryBuilderProps: Record<string, unknown>; toggleLockRule: ActionElementEventHandler; toggleMuteRule: ActionElementEventHandler; validationResult: boolean | ValidationResult; valueEditorSeparator: React.ReactNode; valueEditorType: ValueEditorType; values: FlexibleOptionList<Option>; valueSourceOptions: ValueSourceFullOptions; valueSources: ValueSources; } /** * Prepares all values and methods used by the {@link Rule} component. * * @group Hooks */ declare const useRule: (props: RuleProps) => UseRule; //#endregion //#region src/components/ShiftActions.d.ts /** * Default "shift up"/"shift down" buttons used by {@link QueryBuilder}. * * @group Components */ declare const ShiftActions: (props: ShiftActionsProps) => React.JSX.Element; //#endregion //#region src/components/ValueEditor.d.ts /** * Default `valueEditor` component used by {@link QueryBuilder}. * * @group Components */ declare const ValueEditor: <F extends FullField>(allProps: ValueEditorProps<F>) => React.JSX.Element | null; interface UseValueEditor { /** * Array of values for when the main value represents a list, e.g. when operator * is "between" or "in". */ valueAsArray: any[]; /** * An update handler for a series of value editors, e.g. when operator is "between". * Calling this function will update a single element of the value array and leave * the rest of the array as is. * * @param {string} val The new value for the editor * @param {number} idx The index of the editor (and the array element to update) */ multiValueHandler: (val: unknown, idx: number) => void; /** * An update handler for bigint editors, e.g. when `inputType` is "bigint" and * `parseNumbersMethod` is truthy. */ bigIntValueHandler: (val: unknown) => void; /** * Evaluated `parseNumber` method based on `parseNumbers` prop. This property ends up * being the same as the `parseNumbers` prop minus the "-limited" suffix, unless * the "-limited" suffix is present and the `inputType` is not "number", in which case * it's set to `false`. */ parseNumberMethod: ParseNumberMethod; /** * Class for items in a value editor series (e.g. "between" value editors). */ valueListItemClassName: string; /** * Coerced `inputType` based on `inputType` and `operator`. */ inputTypeCoerced: InputType; } /** * This hook is primarily concerned with multi-value editors like date range * pickers, editors for 'in' and 'between' operators, etc. * * @returns The value as an array (`valueAsArray`), a change handler for * series of editors (`multiValueHandler`), a processed version of the * `parseNumbers` prop (`parseNumberMethod`), and the classname(s) to be applied * to each editor in editor series (`valueListItemClassName`). * * **NOTE:** The following logic only applies if `skipHook` is not `true`. To avoid * automatically updating the `value`, pass `{ skipHook: true }`. * * If the `value` is an array of non-zero length, the `operator` is _not_ one of * the known multi-value operators ("between", "notBetween", "in", "notIn"), and * the `type` is not "multiselect", then the `value` will be set to the first * element of the array (i.e., `value[0]`). * * The same thing will happen if `inputType` is "number" and `value` is a string * containing a comma, since `<input type="number">` doesn't handle commas. * * @example * // Consider the following rule: * `{ field: "f1", operator: "in", value: ["twelve","fourteen"] }` * // If `operator` changes to "=", the value will be reset to "twelve". * * @example * // Consider the following rule: * `{ field: "f1", operator: "between", value: "12,14" }` * // If `operator` changes to "=", the value will be reset to "12". * * @group Hooks */ declare const useValueEditor: <F extends FullField = FullField, O extends string = string>(props: ValueEditorProps<F, O>) => UseValueEditor; //#endregion //#region src/components/ValueSelector.d.ts /** * Default `<select>` component used by {@link QueryBuilder}. * * @group Components */ declare const ValueSelector: <Opt extends FullOption = FullOption>(props: ValueSelectorProps<Opt>) => React.JSX.Element; type UseValueSelectorParams = Pick<ValueSelectorProps, "handleOnChange" | "listsAsArrays" | "multiple" | "value">; /** * Transforms a value into an array when appropriate and provides a memoized change hand