@abaktiar/ql-input
Version:
React QL input component with intelligent autocomplete, parameterized functions, and query validation. Framework-independent with zero external dependencies.
342 lines (299 loc) • 9.53 kB
TypeScript
import { FC } from 'react';
import * as React_2 from 'react';
export declare const CheckIcon: FC<IconProps>;
export declare const ChevronDownIcon: FC<IconProps>;
/**
* Simple class name combiner - framework independent
*/
export declare function classNames(...classes: (string | undefined | null | false)[]): string;
/**
* Count total conditions in an expression
*/
export declare function countConditions(expr: QLExpression): number;
export declare type FieldType = 'text' | 'number' | 'date' | 'datetime' | 'boolean' | 'option' | 'multiselect' | 'user';
/**
* Get all field names used in an expression
*/
export declare function getUsedFields(expr: QLExpression): string[];
declare interface IconProps {
className?: string;
size?: number;
}
/**
* Helper functions to work with QL expressions and convert them to database queries
*/
export declare function isCondition(expr: QLExpression): expr is QLCondition;
export declare function isLogicalGroup(expr: QLExpression): expr is QLLogicalGroup;
export declare const LoaderIcon: FC<IconProps>;
export declare type LogicalOperatorType = 'AND' | 'OR' | 'NOT';
export declare type OperatorType = '=' | '!=' | '>' | '<' | '>=' | '<=' | '~' | '!~' | 'IN' | 'NOT IN' | 'IS EMPTY' | 'IS NOT EMPTY' | 'WAS' | 'WAS IN' | 'WAS NOT IN' | 'CHANGED';
export declare interface ParseContext {
input: string;
position: number;
tokens: QLToken[];
currentToken?: QLToken;
expectingField: boolean;
expectingOperator: boolean;
expectingValue: boolean;
expectingLogical: boolean;
parenthesesLevel: number;
inOrderBy: boolean;
lastField?: string;
}
/**
* Pretty print expression for debugging
*/
export declare function printExpression(expr: QLExpression, indent?: number): string;
export declare interface QLCondition {
field: string;
operator: OperatorType;
value?: string | string[];
not?: boolean;
}
export declare type QLExpression = QLCondition | QLLogicalGroup;
/**
* Enhanced QL Expression Parser
* Builds hierarchical expression trees that properly represent logical grouping
*/
export declare class QLExpressionParser {
private tokens;
private position;
parse(tokens: QLToken[]): QLExpression | null;
private parseExpression;
private parseOrExpression;
private parseAndExpression;
private parsePrimaryExpression;
private parseCondition;
private parseValue;
private parseFunctionCall;
private parseInList;
private operatorRequiresValue;
private current;
private advance;
private isLogicalGroup;
}
export declare interface QLField {
name: string;
displayName: string;
type: FieldType;
operators: OperatorType[];
sortable?: boolean;
description?: string;
options?: QLValue[];
asyncValueSuggestions?: boolean;
}
export declare interface QLFunction {
name: string;
displayName: string;
description?: string;
parameters?: {
name: string;
type: FieldType;
required: boolean;
description?: string;
}[];
}
export declare const QLInput: React_2.ForwardRefExoticComponent<QLInputProps & React_2.RefAttributes<HTMLInputElement>>;
export declare interface QLInputConfig {
fields: QLField[];
functions?: QLFunction[];
operators?: OperatorType[];
logicalOperators?: LogicalOperatorType[];
keywords?: string[];
maxSuggestions?: number;
debounceMs?: number;
caseSensitive?: boolean;
allowParentheses?: boolean;
allowOrderBy?: boolean;
allowFunctions?: boolean;
}
export declare interface QLInputProps {
value?: string;
onChange?: (value: string, query: QLQuery) => void;
onExecute?: (query: QLQuery) => void;
config: QLInputConfig;
placeholder?: string;
disabled?: boolean;
className?: string;
showSearchIcon?: boolean;
showClearIcon?: boolean;
getAsyncValueSuggestions?: (field: string, typedValue: string) => Promise<QLValue[]>;
getPredefinedValueSuggestions?: (field: string) => QLValue[];
}
export declare interface QLInputState {
value: string;
tokens: QLToken[];
suggestions: QLSuggestion[];
showSuggestions: boolean;
selectedSuggestionIndex: number;
cursorPosition: number;
query: QLQuery;
validationErrors: ValidationError[];
isLoading: boolean;
justSelectedSuggestion: boolean;
}
export declare interface QLLogicalGroup {
operator: LogicalOperatorType;
conditions: (QLCondition | QLLogicalGroup)[];
not?: boolean;
}
export declare interface QLOrderBy {
field: string;
direction: SortDirection;
}
export declare class QLParser {
constructor(_config: QLInputConfig);
/**
* Tokenize the input string into QL tokens
*/
tokenize(input: string): QLToken[];
/**
* Classify unknown tokens based on context
*/
private classifyTokens;
/**
* Parse tokens into a QL query object
*/
parse(input: string): QLQuery;
private splitQuery;
private parseOrderBy;
}
export declare interface QLQuery {
where?: QLExpression;
orderBy?: QLOrderBy[];
raw: string;
valid: boolean;
errors: string[];
}
export declare interface QLSuggestion {
type: 'field' | 'operator' | 'value' | 'logical' | 'keyword' | 'function' | 'parenthesis' | 'comma';
value: string;
displayValue?: string;
description?: string;
insertText?: string;
category?: string;
}
export declare class QLSuggestionEngine {
private config;
constructor(config: QLInputConfig);
/**
* Get suggestions based on current context
*/
getSuggestions(context: SuggestionContext): QLSuggestion[];
/**
* Get field suggestions
*/
private getFieldSuggestions;
/**
* Get operator suggestions for a specific field
*/
private getOperatorSuggestions;
/**
* Get value suggestions for a specific field
*/
private getValueSuggestions;
/**
* Get operator description
*/
private getOperatorDescription;
/**
* Get logical operator suggestions
*/
private getLogicalOperatorSuggestions;
/**
* Get sortable field suggestions for ORDER BY
*/
private getSortableFieldSuggestions;
/**
* Get sort direction suggestions
*/
private getSortDirectionSuggestions;
/**
* Get function suggestions
*/
private getFunctionSuggestions;
/**
* Get value suggestions for IN lists (inside parentheses)
*/
private getInListValueSuggestions;
/**
* Get logical operator description
*/
private getLogicalOperatorDescription;
/**
* Filter suggestions based on partial input
*/
private filterSuggestions;
/**
* Get suggestion context from input and cursor position
*/
getSuggestionContext(input: string, cursorPosition: number, tokens: QLToken[]): SuggestionContext;
}
export declare interface QLToken {
type: 'field' | 'operator' | 'value' | 'logical' | 'keyword' | 'function' | 'parenthesis' | 'comma' | 'whitespace' | 'unknown';
value: string;
start: number;
end: number;
valid?: boolean;
error?: string;
}
export declare interface QLValue {
value: string;
displayValue?: string;
description?: string;
}
export declare const SearchIcon: FC<IconProps>;
export declare type SortDirection = 'ASC' | 'DESC';
export declare interface SuggestionContext {
input: string;
cursorPosition: number;
tokens: QLToken[];
currentToken?: QLToken;
previousToken?: QLToken;
nextToken?: QLToken;
expectingField: boolean;
expectingOperator: boolean;
expectingValue: boolean;
expectingLogical: boolean;
inOrderBy: boolean;
parenthesesLevel: number;
inInList: boolean;
lastField?: string;
lastOperator?: string;
partialInput?: string;
}
/**
* Convert QL expression to Mongoose query
*/
export declare function toMongooseQuery(expr: QLExpression): any;
/**
* Convert QL expression to SQL WHERE clause
*/
export declare function toSQLQuery(expr: QLExpression): string;
/**
* Custom hook for debouncing values
*/
export declare function useDebounce<T>(value: T, delay: number): T;
export declare function useQLInput({ config, initialValue, onChange, onExecute, getAsyncValueSuggestions, getPredefinedValueSuggestions, }: UseQLInputProps): {
state: QLInputState;
handleInputChange: (value: string, cursorPosition: number) => void;
handleKeyDown: (event: React.KeyboardEvent) => void;
selectSuggestion: (suggestion: QLSuggestion) => void;
hideSuggestions: () => void;
};
declare interface UseQLInputProps {
config: QLInputConfig;
initialValue?: string;
onChange?: (value: string, query: QLQuery) => void;
onExecute?: (query: QLQuery) => void;
getAsyncValueSuggestions?: (field: string, typedValue: string) => Promise<QLValue[]>;
getPredefinedValueSuggestions?: (field: string) => QLValue[];
}
export declare interface ValidationError {
message: string;
start: number;
end: number;
severity: 'error' | 'warning';
}
export declare const XIcon: FC<IconProps>;
export { }