import * as react from 'react';
import { FormBinding, FormField, Form } from '@mobx-sentinel/form';

declare namespace CheckBoxBinding {
    type Attrs = React.InputHTMLAttributes<HTMLInputElement>;
    type AttrsRequired = Required<Attrs>;
    type Config = {
        /** Get the value from the model @computed */
        getter: () => boolean;
        /** Set the value to the model @action */
        setter: (value: boolean) => void;
        /** [Override] ID of the input element */
        id?: Attrs["id"];
        /** [Extend] Change handler */
        onChange?: Attrs["onChange"];
        /** [Extend] Focus handler */
        onFocus?: Attrs["onFocus"];
    };
}
declare class CheckBoxBinding implements FormBinding {
    private readonly field;
    config: CheckBoxBinding.Config;
    constructor(field: FormField, config: CheckBoxBinding.Config);
    get checked(): CheckBoxBinding.AttrsRequired["checked"];
    onChange: CheckBoxBinding.AttrsRequired["onChange"];
    onFocus: CheckBoxBinding.AttrsRequired["onFocus"];
    get errorMessages(): string | null;
    get props(): {
        type: "checkbox";
        id: string;
        checked: boolean;
        onChange: react.ChangeEventHandler<HTMLInputElement>;
        onFocus: react.FocusEventHandler<HTMLInputElement>;
        "aria-invalid": boolean | undefined;
        "aria-errormessage": string | undefined;
    };
}

declare namespace InputBinding {
    export type Attrs = React.InputHTMLAttributes<HTMLInputElement>;
    export type AttrsRequired = Required<Attrs>;
    type DateValueType = "date" | "datetime-local" | "month" | "time" | "week";
    type NumericValueType = "number" | "range" | DateValueType;
    type StringType = "color" | "text" | "tel" | "url" | "email" | "password" | "search" | DateValueType | NumericValueType;
    export type Config = {
        /** [Override] ID of the input element */
        id?: Attrs["id"];
        /** [Extend] Change handler */
        onChange?: Attrs["onChange"];
        /** [Extend] Focus handler */
        onFocus?: Attrs["onFocus"];
        /** [Extend] Blur handler */
        onBlur?: Attrs["onBlur"];
    } & ({
        /**
         * Type of form control.
         *
         * When unspecified, it is deduced from the valueAs.
         * @default "text" - when valueAs is undefined or "string"
         */
        type?: StringType;
        /**
         * Value type of the input element.
         * It determines how getter/setter should handle the value.
         */
        valueAs?: "string";
        /** Get the value from the model @computed */
        getter: () => string | null;
        /** Set the value to the model @action */
        setter: (value: string) => void;
    } | {
        /**
         * Type of form control.
         *
         * When unspecified, it is deduced from the valueAs.
         * @default "number" - when valueAs is "number"
         */
        type?: NumericValueType;
        /**
         * Value type of the input element.
         * It determines how getter/setter should handle the value.
         */
        valueAs: "number";
        /** Get the value from the model @computed */
        getter: () => number | null;
        /** Set the value to the model @action */
        setter: (value: number | null) => void;
    } | {
        /**
         * Type of form control.
         *
         * When unspecified, it is deduced from the valueAs.
         * @default "date" - when valueAs is "date"
         */
        type?: DateValueType;
        /**
         * Value type of the input element.
         * It determines how getter/setter should handle the value.
         */
        valueAs: "date";
        /**
         * Get the value from the model @computed
         *
         * String representation of the date.
         * As Date instance has no distinction between date and datetime,
         * it's developers' responsibility to format the date correctly.
         *
         * | `type` attr    | Expected format   | Example           |
         * |----------------|-------------------|-------------------|
         * | date           | YYYY-MM-DD        | 2024-12-31        |
         * | datetime-local | YYYY-MM-DDTHH:mm  | 2024-12-31T23:59  |
         * | time           | HH:mm or HH:mm:ss | 23:59 or 23:59:59 |
         * | week           | YYYY-Www          | 2024-W52          |
         * | month          | YYYY-MM           | 2024-12           |
         *
         * @example
         * ```
         * date.toISOString().split("T")[0]
         * ```
         */
        getter: () => string | null;
        /** Set the value to the model @action */
        setter: (value: Date | null) => void;
    });
    export {  };
}
declare class InputBinding implements FormBinding {
    private readonly field;
    config: InputBinding.Config;
    constructor(field: FormField, config: InputBinding.Config);
    get value(): InputBinding.AttrsRequired["value"];
    get type(): InputBinding.AttrsRequired["type"];
    onChange: InputBinding.AttrsRequired["onChange"];
    onBlur: InputBinding.AttrsRequired["onBlur"];
    onFocus: InputBinding.AttrsRequired["onFocus"];
    get errorMessages(): string | null;
    get props(): {
        type: react.HTMLInputTypeAttribute;
        value: string | number | readonly string[];
        id: string;
        onChange: react.ChangeEventHandler<HTMLInputElement>;
        onFocus: react.FocusEventHandler<HTMLInputElement>;
        onBlur: react.FocusEventHandler<HTMLInputElement>;
        "aria-invalid": boolean | undefined;
        "aria-errormessage": string | undefined;
    };
}

declare namespace RadioButtonBinding {
    type Attrs = React.InputHTMLAttributes<HTMLInputElement>;
    type AttrsRequired = Required<Attrs>;
    type Config = {
        /** Get the value from the model */
        getter: () => string | null;
        /** Set the value to the model */
        setter: (value: string) => void;
        /** [Extend] Change handler */
        onChange?: Attrs["onChange"];
        /** [Extend] Focus handler */
        onFocus?: Attrs["onFocus"];
    };
}
declare class RadioButtonBinding implements FormBinding {
    private readonly field;
    config: RadioButtonBinding.Config;
    constructor(field: FormField, config: RadioButtonBinding.Config);
    get value(): RadioButtonBinding.AttrsRequired["value"];
    onChange: RadioButtonBinding.AttrsRequired["onChange"];
    onFocus: RadioButtonBinding.AttrsRequired["onFocus"];
    get errorMessages(): string | null;
    props: (value: string | null, opt?: {
        /**
         * [Override] ID of the input element.
         *
         * - `true`: Use the field ID as the ID.
         * - `false`: No ID.
         * - `string`: Use the given string as the ID.
         */
        id?: string | boolean;
        /** [Override] Name attribute of the input element */
        name?: string;
    }) => {
        type: "radio";
        id: string | undefined;
        value: string;
        name: string;
        checked: boolean;
        onChange: react.ChangeEventHandler<HTMLInputElement>;
        onFocus: react.FocusEventHandler<HTMLInputElement>;
        "aria-invalid": boolean | undefined;
        "aria-errormessage": string | undefined;
    };
}

declare namespace SelectBoxBinding {
    type Attrs = React.SelectHTMLAttributes<HTMLSelectElement>;
    type AttrsRequired = Required<Attrs>;
    type Config = {
        /** [Override] ID of the input element */
        id?: Attrs["id"];
        /** [Extend] Change handler */
        onChange?: Attrs["onChange"];
        /** [Extend] Focus handler */
        onFocus?: Attrs["onFocus"];
    } & ({
        /** Whether multiple options can be selected in the list */
        multiple?: false;
        /** Get the value from the model */
        getter: () => string;
        /** Set the value to the model */
        setter: (value: string) => void;
    } | {
        /** Whether multiple options can be selected in the list */
        multiple: true;
        /** Get the value from the model */
        getter: () => string[];
        /** Set the value to the model */
        setter: (value: string[]) => void;
    });
}
declare class SelectBoxBinding implements FormBinding {
    private readonly field;
    config: SelectBoxBinding.Config;
    constructor(field: FormField, config: SelectBoxBinding.Config);
    get value(): SelectBoxBinding.AttrsRequired["value"];
    onChange: SelectBoxBinding.AttrsRequired["onChange"];
    onFocus: SelectBoxBinding.AttrsRequired["onFocus"];
    get errorMessages(): string | null;
    get props(): {
        id: string;
        multiple: boolean | undefined;
        value: string | number | readonly string[];
        onChange: react.ChangeEventHandler<HTMLSelectElement>;
        onFocus: react.FocusEventHandler<HTMLSelectElement>;
        "aria-invalid": boolean | undefined;
        "aria-errormessage": string | undefined;
    };
}

declare namespace SubmitButtonBinding {
    type Attrs = React.ButtonHTMLAttributes<HTMLButtonElement>;
    type AttrsRequired = Required<Attrs>;
    type Config = {
        /** [Extend] Click handler */
        onClick?: Attrs["onClick"];
        /** [Extend] Mouse enter handler */
        onMouseOver?: Attrs["onMouseOver"];
    };
}
declare class SubmitButtonBinding implements FormBinding {
    private readonly form;
    config: SubmitButtonBinding.Config;
    constructor(form: Form<unknown>, config: SubmitButtonBinding.Config);
    get busy(): boolean;
    onClick: SubmitButtonBinding.AttrsRequired["onClick"];
    onMouseOver: SubmitButtonBinding.AttrsRequired["onMouseOver"];
    get props(): {
        onClick: react.MouseEventHandler<HTMLButtonElement>;
        onMouseOver: react.MouseEventHandler<HTMLButtonElement>;
        disabled: boolean;
        "aria-busy": boolean;
        "aria-invalid": boolean;
    };
}

declare namespace LabelBinding {
    type Attrs = React.LabelHTMLAttributes<HTMLLabelElement>;
    type AttrsRequired = Required<Attrs>;
    type Config = {
        /** [Override] ID of the target element */
        htmlFor?: Attrs["htmlFor"];
    };
}
declare class LabelBinding implements FormBinding {
    private readonly fields;
    config: LabelBinding.Config;
    constructor(fields: FormField[], config: LabelBinding.Config);
    get firstFieldId(): string | undefined;
    get firstErrorMessage(): string | null;
    get props(): {
        htmlFor: string | undefined;
        "aria-invalid": boolean;
        "aria-errormessage": string | undefined;
    };
}

export { CheckBoxBinding as C, InputBinding as I, LabelBinding as L, RadioButtonBinding as R, SelectBoxBinding as S, SubmitButtonBinding as a };
