import { AutoValidationStatus, FormManager, LocatedValidationWarning, Schema, SchemaKt, SealedLocatedValidationIssue, ValidationMode } from "@kform/core";
import { DistributedOmit, MaybePromise } from "../utils/typeUtils";
import { Controller, ControllerOptions, ControllerState } from "./useController";
/**
 * Default message passed when preventing the "before unload" event.
 */
export declare const DEFAULT_CONFIRM_UNLOAD_MESSAGE = "Are you sure you want to leave?";
/**
 * Type of external issues accepted by the form manager's `addExternalIssues`
 * method.
 */
type ExternalValidationIssues = Parameters<FormManager["addExternalIssues"]>[0];
/**
 * An object which is event-like.
 */
type EventLike = Pick<Event, "preventDefault" | "defaultPrevented">;
/**
 * Options available to the {@link useForm} hook.
 */
export type FormOptions<T = unknown, TSubmitResult = unknown> = DistributedOmit<ControllerOptions<T, FormControllerState<T>>, "formManager"> & FormOwnOptions<T, TSubmitResult>;
/**
 * Own options available to the {@link useForm} hook.
 */
export interface FormOwnOptions<T = unknown, TSubmitResult = unknown> extends SubmitOptions<T, TSubmitResult> {
    /**
     * Initial form value.
     */
    initialValue?: T;
    /**
     * External contexts available to validations. This value may change over time
     * and will not cause a new form manager to be instantiated.
     */
    externalContexts?: Record<string, unknown>;
    /**
     * Form manager's validation mode. This value may change over time and will
     * not cause a new form manager to be instantiated.
     */
    validationMode?: ValidationMode;
    /**
     * Whether to display a confirmation that the page should be unloaded when the
     * form is dirty.
     * @default true
     */
    confirmUnloadWhenDirty?: boolean;
    /**
     * Message to provide when confirming a page unload due to the dirty status of
     * the form.
     *
     * Note that most recent browsers will not honour this string and will instead
     * display a predefined message (see:
     * https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeunload_event#compatibility_notes).
     */
    confirmUnloadMessage?: string;
    /**
     * Function called during reset, before actually resetting the form. Calling
     * [preventDefault()]{@link event.preventDefault} on the event will prevent
     * the reset from occurring.
     * @param event Original `onReset` event.
     */
    onReset?: (event?: EventLike) => MaybePromise<void>;
}
/**
 * Controller used to read and control the root form value, exposing properties
 * that should be set on a {@link HTMLFormElement <form>} element.
 */
export type FormController<T = unknown, TSubmitResult = unknown> = Controller<T, FormControllerState<T>> & FormOwnController<T, TSubmitResult>;
/**
 * Form's own controller.
 */
export interface FormOwnController<T = unknown, TSubmitResult = unknown> {
    /**
     * Function used to submit the form.
     * @param event Event which caused the submission.
     * @param options Options used when submitting the form.
     */
    readonly submit: (<TOptionsSubmitResult = TSubmitResult>(event: EventLike, options?: SubmitOptions<T, TOptionsSubmitResult>) => Promise<void>) & (<TOptionsSubmitResult = TSubmitResult>(options?: SubmitOptions<T, TOptionsSubmitResult>) => Promise<void>);
    /**
     * Hook returning the status of the form's automatic validations.
     */
    readonly useAutoValidationStatus: () => AutoValidationStatus;
    /**
     * Hook returning whether the form is currently being submitted.
     */
    readonly useSubmitting: () => boolean;
    /**
     * Hook returning whether the form is currently being reset.
     */
    readonly useResetting: () => boolean;
    /**
     * Properties to set on a {@link HTMLFormElement <form>} element.
     */
    readonly formProps: FormElementProps;
}
/**
 * Options available when submitting a value.
 */
export interface SubmitOptions<T = unknown, TSubmitResult = unknown> {
    /**
     * Function called during submission when the form value to submit is locally
     * valid (no validation errors were found), or always when `validateOnSubmit`
     * is set to `false`.
     *
     * This function may (possibly asynchronously) return two types of values, or
     * throw an error:
     * - Function returns external validation issues: the submission is considered
     *   invalid (even if all returned issues are warnings). Returned issues that
     *   aren't already in the form manager are added to it via
     *   {@link FormManager.addExternalIssues}. `onInvalidSubmit` is subsequently
     *   called with the returned issues.
     * - Function returns any other value: the submission is considered
     *   successful. `onSuccessfulSubmit` will be called with the returned value
     *   after setting the form as pristine (unless
     *   `setPristineOnSuccessfulSubmit` is set to `false`).
     * - Function throws: the submission is considered to have failed.
     *   `onFailedSubmit` will be called with the thrown error.
     * @param value Form value to submit.
     * @param warnings List of form warnings. `undefined` when `validateOnSubmit`
     * is set to `false`.
     * @param event Original event (with the default behaviour already prevented).
     * @returns External validation issues, or any other value (including
     * `undefined`) to indicate success; or a promise which resolves to such
     * values.
     */
    onSubmit?: (value: T, warnings?: LocatedValidationWarning[], event?: EventLike) => MaybePromise<ExternalValidationIssues | TSubmitResult>;
    /**
     * Function called during submission when the form value to submit is locally
     * invalid (validation errors were found), or after `onSubmit` if it returns
     * external validation issues.
     * @param issues List of form issues.
     * @param event Original event (with the default behaviour already prevented).
     */
    onInvalidSubmit?: (issues: SealedLocatedValidationIssue[], event?: EventLike) => void;
    /**
     * Function called after a successful submission with the result of
     * `onSubmit`, when this result isn't external validation issues.
     *
     * Unless `setPristineOnSuccessfulSubmit` is set to `false`, the form will be
     * pristine by the time this function runs, meaning that redirections that
     * cause the form to be closed should happen within this function (so that the
     * form unload confirmation isn't triggered).
     * @param submitResult Result of calling `onSubmit`, when such value isn't
     * external validation issues.
     * @param event Original event (with the default behaviour already prevented).
     */
    onSuccessfulSubmit?: (submitResult: TSubmitResult, event?: EventLike) => void;
    /**
     * Function called after a submission which resulted in an error.
     * @param error Error that occurred during the submission.
     * @param event Original event (with the default behaviour already prevented).
     */
    onFailedSubmit?: (error: unknown, event?: EventLike) => void;
    /**
     * Whether to set the whole form as touched before submitting.
     * @default true
     */
    setTouchedOnSubmit?: boolean;
    /**
     * Whether to validate the form before submitting.
     *
     * When set to `false`, `onSubmit` is always called and `onInvalidSubmit` is
     * only called if `onSubmit` returns external validation issues.
     * @default true
     */
    validateOnSubmit?: boolean;
    /**
     * Whether to set the whole form as pristine after a successful submission,
     * but before invoking `onSuccessfulSubmit`.
     * @default true
     */
    setPristineOnSuccessfulSubmit?: boolean;
    /**
     * Whether to convert table row indices into ids when processing external
     * issues returned by the `onSubmit` function.
     * @default false
     */
    convertExternalIssuesTableRowIndicesToIds?: boolean;
}
/**
 * Properties to provide to a form element to integrate it with the form
 * manager.
 */
export interface FormElementProps {
    /**
     * Disable native HTML validations.
     */
    readonly noValidate: true;
    /**
     * Function to run whenever the form is to be submitted. This function calls
     * the provided `onSubmit` option with the root value and the original form
     * element event, while preventing the default event behaviour.
     */
    readonly onSubmit: (event?: EventLike) => Promise<void>;
    /**
     * Function to run whenever the form is to be reset. This function resets the
     * whole form, while preventing the default event behaviour.
     */
    readonly onReset: (event?: EventLike) => Promise<void>;
}
/**
 * Form controller's state.
 */
export type FormControllerState<T = unknown> = ControllerState<T> & FormControllerOwnState;
/**
 * Form controller's own state.
 */
export interface FormControllerOwnState {
    /**
     * Status of the automatic validations.
     */
    readonly autoValidationStatus: AutoValidationStatus;
    /**
     * Whether the root value is currently being submitted.
     */
    readonly submitting: boolean;
    /**
     * Whether the root value is currently being reset.
     */
    readonly resetting: boolean;
}
/**
 * Hook used to create a new form managed by a form manager given its
 * {@link schema}. It provides access to the form controller, as well as
 * properties for integration with a {@link HTMLFormElement <form>} element.
 *
 * The provided external contexts and validation mode may change over time and
 * will not cause a new form manager to be instantiated.
 * @param schema Schema of the form.
 * @param options Available options.
 * @returns A controller used to read and control the root form value, exposing
 * properties that should be set on a {@link HTMLFormElement <form>} element.
 */
export declare function useForm<T = unknown, TSubmitResult = unknown>(schema: Schema<T> | SchemaKt, options?: undefined): FormController<T, TSubmitResult>;
export declare function useForm<T = unknown, TSubmitResult = unknown>(schema: Schema<T> | SchemaKt, options: FormOptions<T, TSubmitResult>): FormController<T, TSubmitResult>;
export {};
