import { Ref, UnwrapNestedRefs, WritableComputedRef, ComputedRef } from 'vue';

type MaybeRef<T> = T | Ref<T>;
type FormValues = Record<string, any>;
type FieldValidator<Value> = (value: Value) => string | void | Promise<string | void>;
type FieldArrayValidator<Value extends Array<any>> = (value: Value) => FormErrors<Value> | void | Promise<FormErrors<Value> | void>;
type FormTouched<Values> = {
    [K in keyof Values]?: Values[K] extends any[] ? Values[K][number] extends object ? FormTouched<Values[K][number]>[] | boolean : boolean | boolean[] : Values[K] extends object ? FormTouched<Values[K]> : boolean;
};
type FormErrors<Values> = {
    [K in keyof Values]?: Values[K] extends any[] ? Values[K][number] extends object ? FormErrors<Values[K][number]>[] | string | string[] : string | string[] : Values[K] extends object ? FormErrors<Values[K]> : string;
};
interface FormState<Values extends FormValues> {
    values: UnwrapNestedRefs<Values>;
    touched: Ref<FormTouched<Values>>;
    errors: Ref<FormErrors<Values>>;
    submitCount: Ref<number>;
    isSubmitting: Ref<boolean>;
    isValidating: Ref<boolean>;
}
interface FormEventHandler {
    handleBlur: {
        (event: Event, name?: string): void;
        <T = string | Event>(name: T): T extends string ? () => void : void;
    };
    handleChange: () => void;
    handleInput: () => void;
}
interface FieldRegisterOptions<Values> {
    validate?: FieldValidator<Values>;
}
type UseFormRegisterReturn<Value> = FieldMeta & {
    value: WritableComputedRef<Value>;
    attrs: ComputedRef<FieldAttrs>;
};
type SetFieldArrayValue = <T extends (...args: any) => any>(name: string, value: any[], method?: T, args?: Partial<{
    argA: Parameters<T>[1];
    argB: Parameters<T>[2];
}>, shouldSetValue?: boolean) => void;
type UseFormRegister<Values extends FormValues> = <Name extends Path<Values>, Value = PathValue<Values, Name>>(name: MaybeRef<Name>, options?: FieldRegisterOptions<Value>) => UseFormRegisterReturn<Value>;
type UseFormSetFieldValue<Values extends FormValues> = <Name extends Path<Values>, FieldValue extends PathValue<Values, Name>>(name: Name, value: FieldValue, shouldValidate?: boolean) => void;
type ValidateForm<Values extends FormValues> = (values?: Values) => Promise<FormErrors<Values>>;
type ValidateField<Values extends FormValues> = <Name extends Path<Values>>(name: Name) => Promise<void>;
interface FormResetState<Values extends FormValues = FormValues> {
    values: Values;
    touched: FormTouched<Values>;
    errors: FormErrors<Values>;
    submitCount: number;
}
type ResetForm<Values extends FormValues> = (nextState?: Partial<FormResetState<Values>>) => void;
interface UseFormReturn<Values extends FormValues> {
    values: UnwrapNestedRefs<Values>;
    touched: ComputedRef<FormTouched<Values>>;
    errors: ComputedRef<FormErrors<Values>>;
    submitCount: ComputedRef<number>;
    isSubmitting: Ref<boolean>;
    isValidating: ComputedRef<boolean>;
    dirty: ComputedRef<boolean>;
    register: UseFormRegister<Values>;
    setValues: (values: Values, shouldValidate?: boolean) => void;
    setFieldValue: UseFormSetFieldValue<Values>;
    handleSubmit: (event?: Event) => void;
    handleReset: (event?: Event) => void;
    resetForm: ResetForm<Values>;
    validateForm: ValidateForm<Values>;
    validateField: ValidateField<Values>;
}
type FieldAttrs = {
    name: string;
    onBlur: (event: Event) => void;
    onChange: () => void;
    onInput: () => void;
};
type FieldMeta = {
    dirty: ComputedRef<boolean>;
    error: ComputedRef<string | undefined>;
    touched: ComputedRef<boolean | undefined>;
};
type Primitive = null | undefined | string | number | boolean | symbol | bigint;
type IsTuple<T extends ReadonlyArray<any>> = number extends T['length'] ? false : true;
type PathImpl<K extends string | number, V> = V extends Primitive ? `${K}` : `${K}` | `${K}.${Path<V>}`;
type TupleKeys<T extends ReadonlyArray<any>> = Exclude<keyof T, keyof any[]>;
type Path<T> = T extends ReadonlyArray<infer V> ? IsTuple<T> extends true ? {
    [K in TupleKeys<T>]-?: PathImpl<K & string, T[K]>;
}[TupleKeys<T>] : PathImpl<number, V> : {
    [K in keyof T]-?: PathImpl<K & string, T[K]>;
}[keyof T];
type ArrayPathImpl<K extends string | number, V> = V extends Primitive ? never : V extends ReadonlyArray<infer U> ? U extends Primitive ? never : `${K}` | `${K}.${ArrayPath<V>}` : `${K}.${ArrayPath<V>}`;
type ArrayPath<T> = T extends ReadonlyArray<infer V> ? IsTuple<T> extends true ? {
    [K in TupleKeys<T>]-?: ArrayPathImpl<K & string, T[K]>;
}[TupleKeys<T>] : ArrayPathImpl<number, V> : {
    [K in keyof T]-?: ArrayPathImpl<K & string, T[K]>;
}[keyof T];
type PathValue<T, P extends Path<T> | ArrayPath<T>> = T extends any ? P extends `${infer Key}.${infer Rest}` ? Key extends keyof T ? Rest extends Path<T[Key]> ? PathValue<T[Key], Rest> : never : Key extends `${number}` ? T extends ReadonlyArray<infer V> ? PathValue<V, Rest & Path<V>> : never : never : P extends keyof T ? T[P] : P extends `${number}` ? T extends ReadonlyArray<infer V> ? V : never : never : never;

interface FormSubmitHelper<Values extends FormValues> {
    setSubmitting: (isSubmitting: boolean) => void;
    readonly initialValues: Values;
}
type ValidateMode = 'blur' | 'input' | 'change' | 'submit';
interface UseFormOptions<Values extends FormValues> {
    initialValues: Values;
    initialErrors?: FormErrors<Values>;
    initialTouched?: FormTouched<Values>;
    validateMode?: ValidateMode;
    reValidateMode?: ValidateMode;
    validateOnMounted?: boolean;
    onSubmit: (values: Values, helper: FormSubmitHelper<Values>) => void | Promise<any>;
    onInvalid?: (errors: FormErrors<Values>) => void;
    validate?: (values: Values) => void | object | Promise<FormErrors<Values>>;
}
/**
 * Custom composition API to mange the entire form.
 *
 * @param options - form configuration and validation parameters. {@link UseFormOptions}
 *
 * @returns methods and state of this form. {@link UseFormReturn}
 *
 * @example
 * ```vue
 * <script setup lang="ts">
 * const { register, handleSubmit } = useForm({
 *   initialValues: {
 *     name: 'Alex',
 *     age: 18,
 *   },
 *   onSubmit (values) {
 *     console.log({ values })
 *   },
 * });
 *
 * const { value: name, attrs: nameAttrs } = register('name')
 * const { value: age, attrs: ageAttrs } = register('name')
 * </script>
 *
 * <template>
 *   <form v-on:submit="handleSubmit">
 *     <input v-model="name" type="text" v-bind="nameAttrs" />
 *     <input v-model.number="age" type="text" v-bind="ageAttrs" />
 *     <input type="submit" />
 *   </form>
 * </template>
 * ```
 */
declare function useForm<Values extends FormValues = FormValues>(options: UseFormOptions<Values>): UseFormReturn<Values>;

type UseFieldOptions<Value> = {
    validate?: FieldValidator<Value>;
};
/**
 * Custom composition API that will return specific field value, meta (state) and attributes.
 *
 * @param name - field name
 *
 * @param options - field configuration and validation parameters. {@link UseFieldOptions}
 *
 * @returns field value, meta (state) and attributes. {@link UseFormRegisterReturn}
 *
 * @example
 * ```vue
 * <script setup lang="ts">
 * const { handleSubmit } = useForm({
 *   initialValues: {
 *     name: '',
 *   },
 *   onSubmit(values) {
 *     console.log({ values });
 *   },
 * });
 *
 * const { value: name, attrs: nameAttrs } = useField('name')
 * </script>
 *
 * <template>
 *   <form v-on:submit="handleSubmit">
 *     <input v-model="name" type="text" v-bind="nameAttrs" />
 *     <input type="submit" />
 *   </form>
 * </template>
 * ```
 */
declare function useField<Value>(name: MaybeRef<string>, options?: UseFieldOptions<Value>): UseFormRegisterReturn<Value>;

interface FieldEntry<Value> {
    key: number;
    value: Value;
    name: string;
    error: FormErrors<Value>;
    touched: Value extends Primitive ? boolean : FormTouched<Value> | undefined;
    dirty: boolean;
    attrs: Omit<FieldAttrs, 'name'>;
}
interface UseFieldArrayOptions<Value> {
    validate?: FieldArrayValidator<Value[]>;
}
type UseFieldArrayReturn<Value> = {
    fields: Ref<FieldEntry<Value>[]>;
    append: (value: Value) => void;
    prepend: (value: Value) => void;
    swap: (indexA: number, indexB: number) => void;
    remove: (index?: number) => void;
    move: (from: number, to: number) => void;
    insert: (index: number, value: Value) => void;
    update: (index: number, value: Value) => void;
    replace: (values: Value[]) => void;
};
/**
 * Custom composition API that exposes convenient to perform operations with a list of fields.
 *
 * @param name - field name
 *
 * @param options - field array configuration and validation parameters {@link UseFieldArrayOptions}
 *
 * @returns fields state and methods. {@link UseFieldArrayReturn}
 *
 * @example
 * ```vue
 * <script setup lang="ts">
 * import { useForm, useFieldArray } from '@vorms/core';
 *
 * const { values, handleSubmit } = useForm({
 *   initialValues: {
 *     list: ['vue', 'vue-router'],
 *   },
 *   onSubmit(values) {
 *     console.log({ values });
 *   },
 * });
 *
 * const { fields, append } = useFieldArray('list');
 * </script>
 *
 * <template>
 *   <pre>{{ values }}</pre>
 *   <form v-on:submit="handleSubmit">
 *     <template v-for="field in fields" :key="field.key">
 *       <input v-model="field.value" :name="field.name" v-bind="field.attrs" />
 *     </template>
 *     <button type="button" v-on:click="append('pinia')">Append</button>
 *     <input type="submit" />
 *   </form>
 * </template>
 * ```
 */
declare function useFieldArray<Value>(name: MaybeRef<string>, options?: UseFieldArrayOptions<Value>): UseFieldArrayReturn<Value>;

type FormContextValues<Values extends FormValues = FormValues> = UseFormReturn<Values>;
/**
 * Custom composition API that return form context
 *
 * @returns methods and state of form (As same as useForm). {@link FormContextValues}
 *
 * @example
 * ```vue
 * <script setup lang="ts">
 * import { useFormContext } from '@vorms/core'
 *
 * const { validateField } = useFormContext()
 * const { value, attrs } = useField('drink') // You can also use `register` return from `useFormContext()`
 * </script>
 *
 * <template>
 *   <input v-model="value" type="text" v-bind="attrs" />
 * </template>
 * ```
 */
declare function useFormContext<Values extends FormValues = FormValues>(): FormContextValues<Values>;

declare const _default$1: (obj: Record<string, any>, path: string, value?: any) => Record<string, any>;

declare const _default: <T>(obj: T, path: string, defaultValue?: unknown) => any;

export { ArrayPath, FieldArrayValidator, FieldAttrs, FieldMeta, FieldRegisterOptions, FieldValidator, FormErrors, FormEventHandler, FormResetState, FormState, FormSubmitHelper, FormTouched, FormValues, IsTuple, MaybeRef, Path, PathValue, Primitive, ResetForm, SetFieldArrayValue, TupleKeys, UseFieldArrayOptions, UseFormOptions, UseFormRegister, UseFormRegisterReturn, UseFormReturn, UseFormSetFieldValue, ValidateField, ValidateForm, ValidateMode, _default as get, _default$1 as set, useField, useFieldArray, useForm, useFormContext };
