import { getFormAction, getFormEncType, getFormMethod } from './dom';
import { type Intent, type Submission, type SubmissionResult } from './submission';
type BaseCombine<T, K extends PropertyKey = T extends unknown ? keyof T : never> = T extends unknown ? T & Partial<Record<Exclude<K, keyof T>, never>> : never;
export type Combine<T> = {
    [K in keyof BaseCombine<T>]: BaseCombine<T>[K];
};
export type DefaultValue<Schema> = Schema extends string | number | boolean | Date | bigint | null | undefined ? Schema | string | null | undefined : Schema extends File ? null | undefined : Schema extends Array<infer Item> ? Array<DefaultValue<Item>> | null | undefined : Schema extends Record<string, any> ? {
    [Key in keyof Schema]?: DefaultValue<Schema[Key]>;
} | null | undefined : string | null | undefined;
export type FormValue<Schema> = Schema extends string | number | boolean | Date | bigint | null | undefined ? string | undefined : Schema extends File ? File | undefined : Schema extends File[] ? File | Array<File> | undefined : Schema extends Array<infer Item> ? string | Array<FormValue<Item>> | undefined : Schema extends Record<string, any> ? {
    [Key in keyof Schema]?: FormValue<Schema[Key]>;
} | null | undefined : unknown;
declare const error: unique symbol;
declare const field: unique symbol;
declare const form: unique symbol;
export type FormId<Schema extends Record<string, unknown> = Record<string, unknown>, Error = string[]> = string & {
    [error]?: Error;
    [form]?: Schema;
};
export type FieldName<FieldSchema, FormSchema extends Record<string, unknown> = Record<string, unknown>, Error = string[]> = string & {
    [field]?: FieldSchema;
    [error]?: Error;
    [form]?: FormSchema;
};
export type Constraint = {
    required?: boolean;
    minLength?: number;
    maxLength?: number;
    min?: string | number;
    max?: string | number;
    step?: string | number;
    multiple?: boolean;
    pattern?: string;
};
export type FormMeta<FormError> = {
    submissionStatus?: 'error' | 'success';
    defaultValue: Record<string, unknown>;
    initialValue: Record<string, unknown>;
    value: Record<string, unknown>;
    error: Record<string, FormError>;
    constraint: Record<string, Constraint>;
    key: Record<string, string | undefined>;
    validated: Record<string, boolean>;
};
export type FormState<FormError> = FormMeta<FormError> & {
    valid: Record<string, boolean>;
    dirty: Record<string, boolean>;
};
export type FormOptions<Schema, FormError = string[], FormValue = Schema> = {
    /**
     * The id of the form.
     */
    formId: string;
    /**
     * An object representing the initial value of the form.
     */
    defaultValue?: DefaultValue<Schema>;
    /**
     * An object describing the constraint of each field
     */
    constraint?: Record<string, Constraint>;
    /**
     * An object describing the result of the last submission
     */
    lastResult?: SubmissionResult<FormError> | null | undefined;
    /**
     * Define when conform should start validation.
     * Support "onSubmit", "onInput", "onBlur".
     *
     * @default "onSubmit"
     */
    shouldValidate?: 'onSubmit' | 'onBlur' | 'onInput';
    /**
     * Define when conform should revalidate again.
     * Support "onSubmit", "onInput", "onBlur".
     *
     * @default Same as shouldValidate, or "onSubmit" if shouldValidate is not provided.
     */
    shouldRevalidate?: 'onSubmit' | 'onBlur' | 'onInput';
    /**
     * Define if conform should considered the field for dirty state.
     * e.g. Excluding form fields that are not managed by Conform, such as CSRF token
     */
    shouldDirtyConsider?: (name: string) => boolean;
    /**
     * A function to be called when the form should be (re)validated.
     */
    onValidate?: (context: {
        form: HTMLFormElement;
        submitter: HTMLInputElement | HTMLButtonElement | null;
        formData: FormData;
    }) => Submission<Schema, FormError, FormValue>;
    /**
     * To schedule when an intent should be dispatched.
     */
    onSchedule?: (callback: () => void) => void;
};
export type SubscriptionSubject = {
    [key in 'error' | 'initialValue' | 'value' | 'key' | 'valid' | 'dirty']?: SubscriptionScope;
} & {
    status?: boolean;
};
export type SubscriptionScope = {
    prefix?: string[];
    name?: string[];
};
export type ControlButtonProps = {
    name: string;
    value: string;
    form: string;
    formNoValidate: boolean;
};
export type FormContext<Schema extends Record<string, any> = any, FormError = string[], FormValue = Schema> = {
    formId: string;
    submit(event: SubmitEvent): {
        formData: FormData;
        action: ReturnType<typeof getFormAction>;
        encType: ReturnType<typeof getFormEncType>;
        method: ReturnType<typeof getFormMethod>;
        submission?: Submission<Schema, FormError, FormValue>;
    };
    onReset(event: Event): void;
    onInput(event: Event): void;
    onBlur(event: Event): void;
    onUpdate(options: Partial<FormOptions<Schema, FormError, FormValue>>): void;
    subscribe(callback: () => void, getSubject?: () => SubscriptionSubject | undefined): () => void;
    getState(): FormState<FormError>;
    getSerializedState(): string;
} & {
    [Type in Intent['type']]: {} extends Extract<Intent, {
        type: Type;
    }>['payload'] ? (<FieldSchema = Schema>(payload?: Extract<Intent<FieldSchema>, {
        type: Type;
    }>['payload']) => void) & {
        getButtonProps<FieldSchema = Schema>(payload?: Extract<Intent<FieldSchema>, {
            type: Type;
        }>['payload']): ControlButtonProps;
    } : (<FieldSchema = Schema>(payload: Extract<Intent<FieldSchema>, {
        type: Type;
    }>['payload']) => void) & {
        getButtonProps<FieldSchema = Schema>(payload: Extract<Intent<FieldSchema>, {
            type: Type;
        }>['payload']): ControlButtonProps;
    };
};
export declare function createFormContext<Schema extends Record<string, any>, FormError = string[], FormValue = Schema>(options: FormOptions<Schema, FormError, FormValue>): FormContext<Schema, FormError, FormValue>;
export {};
