/// <reference types="react" />
import { JinjaContextValue } from '../context/JinjaContextValue.js';
import { JinjaExpression } from '../context/JinjaVariable.js';
import { FormVariable } from './FormVariable.js';
export interface FieldComponentProps<T = any> {
    value: T | undefined;
    onChange: (value: T | undefined) => void;
    name: string;
    disabled?: boolean;
    onBlur?: () => void;
    variable: FormVariable;
}
export type FieldComponent<T = any, Props = any> = (props: FieldComponentProps<T> & Props) => React.ReactElement | null | undefined;
export interface ConditionalObject {
    variable: string;
    operator: '==' | '!=' | '>=' | '<=' | '>' | '<' | 'containsAny' | 'containsAll' | 'containsOnly';
    value: any;
}
export interface JinjaConfig {
    mode: 'replace-variable' | 'python';
}
interface BaseFieldConfig {
    jinja?: boolean | JinjaConfig;
    name: string;
    label?: string;
    shouldRender?: JinjaExpression | ConditionalObject;
    props?: any;
    repeat?: string[];
    startRepeating?: boolean;
    default?: any;
    disabled?: boolean | Record<string, boolean>;
    /**
     * @default true
     */
    controlled?: boolean;
    /**
     * If this form field should ascend to one of the Jinja Contexts above this form. `ascend` must correspond to the name of one
     * of the parent contexts, if it doesn't, the field doesn't ascend and a warning is logged to the console.
     *
     * Context names should be unique, but if they aren't, this picks the closest context with this name.
     */
    ascend?: string;
    metadata?: any;
}
export interface FieldGroupConfig extends BaseFieldConfig {
    children: FieldConfig[];
}
export interface FieldListConfig extends BaseFieldConfig {
    model: FieldConfig;
}
export interface GenericFieldConfig<Props = Record<string, any>> extends BaseFieldConfig {
    required?: boolean;
    help?: string;
    component: (props: Props & FieldComponentProps) => React.ReactElement | null | undefined;
    props?: Partial<Props>;
    validation?: (value: any) => string | undefined | Promise<string | undefined>;
}
export interface VariableFieldConfig<Props = any> extends GenericFieldConfig<Props> {
    jinja: boolean | JinjaConfig;
    component: FieldComponent<Props>;
}
export interface StaticFieldConfig<Props = Record<string, any>> extends GenericFieldConfig<Props> {
    jinja: false;
    component: FieldComponent<Props>;
}
export type FieldConfig<Props = Record<string, any>> = (VariableFieldConfig<Props> | StaticFieldConfig<Props> | FieldGroupConfig | FieldListConfig);
export interface FormConfig {
    name: string;
    fields: FieldConfig[];
    computed?: Record<string, JinjaExpression>;
    onSubmit: (form: FormModel) => any;
    parent?: JinjaContextValue;
}
export interface FieldState {
    readonly error?: string;
    readonly touched: boolean;
    readonly disabled: boolean;
    readonly visible: boolean;
}
export type FieldListener = (event: FieldState & {
    value: any;
}) => void;
export type RenderedFieldComponent = React.FC<any> & {
    fields?: RenderedFieldComponent[];
    repeat?: RenderedFieldComponent[];
    variable?: FormVariable;
};
export interface FormModel {
    readonly fields: RenderedFieldComponent[];
    get: (name: string) => any;
    getResolved: (name: string) => Promise<any>;
    set: (name: string, value: any) => void;
    getAll: () => Record<string, any>;
    getAllResolved: () => Promise<any>;
    setAll: (value: Record<string, any>) => void;
    onChange: (name: string, listener: FieldListener) => () => void;
    submit: () => Promise<any>;
    isValid: () => Promise<boolean>;
    reset: (value?: Record<string, any>) => void;
    isRepeating: (name: string) => boolean;
}
export type FormInitStatus = 'pending' | 'success' | 'error';
export {};
//# sourceMappingURL=types.d.ts.map