import * as React from "react"; export type PartialRecord = Partial>; type Mutable = { -readonly [P in keyof T]: T[P]; }; type KeyOf = Extract; type BuiltInValidationAttrsFunction = (fd: FormData) => T | null | undefined; type BuiltInValidationAttrString = string | BuiltInValidationAttrsFunction; type BuiltInValidationAttrNumber = number | BuiltInValidationAttrsFunction; type BuiltInValidationAttrBoolean = boolean | BuiltInValidationAttrsFunction; type InputTextValidationAttrs = { type?: "text" | "search" | "url" | "tel" | "password"; required?: BuiltInValidationAttrBoolean; minLength?: BuiltInValidationAttrNumber; maxLength?: BuiltInValidationAttrNumber; pattern?: BuiltInValidationAttrString; }; type InputEmailValidationAttrs = { type: "email"; multiple?: boolean; required?: BuiltInValidationAttrBoolean; minLength?: BuiltInValidationAttrNumber; maxLength?: BuiltInValidationAttrNumber; pattern?: BuiltInValidationAttrString; }; type InputDateValidationAttrs = { type: "date" | "month" | "week" | "time" | "datetime-local"; required?: BuiltInValidationAttrBoolean; min?: BuiltInValidationAttrString; max?: BuiltInValidationAttrString; }; type InputNumberValidationAttrs = { type: "number"; required?: BuiltInValidationAttrBoolean; min?: BuiltInValidationAttrNumber; max?: BuiltInValidationAttrNumber; }; type InputRangeValidationAttrs = { type: "range"; min?: BuiltInValidationAttrNumber; max?: BuiltInValidationAttrNumber; }; type InputCheckboxValidationAttrs = { type: "checkbox"; required?: BuiltInValidationAttrBoolean; }; type InputRadioValidationAttrs = { type: "radio"; required?: BuiltInValidationAttrBoolean; }; type TextAreaValidationAttrs = { required?: BuiltInValidationAttrBoolean; minLength?: BuiltInValidationAttrNumber; maxLength?: BuiltInValidationAttrNumber; }; type SelectValidationAttrs = { required?: BuiltInValidationAttrBoolean; multiple?: boolean; }; type InputValidationAttrs = InputTextValidationAttrs | InputEmailValidationAttrs | InputDateValidationAttrs | InputNumberValidationAttrs | InputRangeValidationAttrs | InputCheckboxValidationAttrs | InputRadioValidationAttrs; /** * Custom validation function */ export interface CustomValidations { [key: string]: (val: string, formData?: FormData) => boolean | Promise; } /** * Error message - static string or () => string */ export type ErrorMessage = string | ((attrValue: string | undefined, name: string, value: string) => string); /** * Definition for a single input in a form (validations + error messages) */ interface BaseControlDefinition { customValidations?: CustomValidations; errorMessages?: { [key: string]: ErrorMessage; }; multiple?: boolean; } export interface InputDefinition extends BaseControlDefinition { element?: "input"; validationAttrs?: InputValidationAttrs; } export interface TextAreaDefinition extends BaseControlDefinition { element: "textarea"; validationAttrs?: TextAreaValidationAttrs; } export interface SelectDefinition extends BaseControlDefinition { element: "select"; validationAttrs?: SelectValidationAttrs; } type ControlDefinition = InputDefinition | TextAreaDefinition | SelectDefinition; /** * Form information (inputs, validations, error messages) */ export interface FormDefinition { inputs: { [key: string]: ControlDefinition; }; errorMessages?: { [key: string]: ErrorMessage; }; } /** * Mutable version of ValidityState that we can write to */ type MutableValidityState = Mutable; /** * Extended ValidityState which weill also contain our custom validations */ export type ExtendedValidityState = MutableValidityState & Record; export type AsyncValidationState = "idle" | "validating" | "done"; /** * Client-side state of the input */ export interface InputInfo { value: string | null; touched: boolean; dirty: boolean; state: AsyncValidationState; validity?: ExtendedValidityState; errorMessages?: Record; } export type ServerOnlyCustomValidations = Partial<{ [key in KeyOf]: CustomValidations; }>; export type ServerFormInfo = { submittedValues: { [Key in KeyOf]: FormDefInputs[Key]["element"] extends "textarea" ? FormDefInputs[Key]["multiple"] extends true ? string[] : string : FormDefInputs[Key]["element"] extends "select" ? FormDefInputs[Key]["multiple"] extends true ? string[] : FormDefInputs[Key] extends { validationAttrs: object; } ? FormDefInputs[Key]["validationAttrs"] extends { multiple: true; } ? string[] : string : string : FormDefInputs[Key] extends { validationAttrs: object; } ? FormDefInputs[Key]["validationAttrs"] extends { type: "checkbox"; } ? FormDefInputs[Key]["validationAttrs"] extends { required: true; } ? string[] : string[] | null : FormDefInputs[Key]["validationAttrs"] extends { type: "email"; } ? FormDefInputs[Key]["multiple"] extends true ? string[] : FormDefInputs[Key]["validationAttrs"] extends { multiple: true; } ? string[] : string : FormDefInputs[Key]["multiple"] extends true ? string[] : string : FormDefInputs[Key]["multiple"] extends true ? string[] : string; }; inputs: Record, InputInfo | InputInfo[]>; valid: boolean; }; interface FormContextObject { formDefinition: T; serverFormInfo?: ServerFormInfo; forceUpdate: any; } export declare function validateServerFormData(formData: FormData, formDefinition: T, serverCustomValidations?: ServerOnlyCustomValidations): Promise>; export declare const FormContext: React.Context | null>; export declare function useOptionalFormContext(): FormContextObject | null; interface UseValidatedInputOpts { name: KeyOf; formDefinition?: T; serverFormInfo?: ServerFormInfo; ref?: React.ForwardedRef | React.Ref; index?: number; forceUpdate?: any; } export declare function useValidatedInput(opts: UseValidatedInputOpts): { info: InputInfo; ref: React.RefObject; controller: React.MutableRefObject; getLabelAttrs: ({ ...attrs }?: Omit, HTMLLabelElement>, "ref">) => Omit, HTMLLabelElement>, "ref">; getErrorsAttrs: ({ ...attrs }?: Omit, HTMLUListElement>, "ref">) => Omit, HTMLUListElement>, "ref">; getInputAttrs: ({ ...attrs }?: React.ComponentPropsWithoutRef<"input">) => React.ComponentPropsWithoutRef<"input">; }; interface UseValidatedTextAreaOpts { name: KeyOf; formDefinition?: T; serverFormInfo?: ServerFormInfo; ref?: React.ForwardedRef | React.Ref; index?: number; forceUpdate?: any; } export declare function useValidatedTextArea(opts: UseValidatedTextAreaOpts): { info: InputInfo; ref: React.RefObject; controller: React.MutableRefObject; getLabelAttrs: ({ ...attrs }?: Omit, HTMLLabelElement>, "ref">) => Omit, HTMLLabelElement>, "ref">; getErrorsAttrs: ({ ...attrs }?: Omit, HTMLUListElement>, "ref">) => Omit, HTMLUListElement>, "ref">; getTextAreaAttrs: ({ ...attrs }?: React.ComponentPropsWithoutRef<"textarea">) => React.ComponentPropsWithoutRef<"textarea">; }; interface UseValidatedSelectOpts { name: KeyOf; formDefinition?: T; serverFormInfo?: ServerFormInfo; ref?: React.ForwardedRef | React.Ref; index?: number; forceUpdate?: any; } export declare function useValidatedSelect(opts: UseValidatedSelectOpts): { info: InputInfo; ref: React.RefObject; controller: React.MutableRefObject; getLabelAttrs: ({ ...attrs }?: Omit, HTMLLabelElement>, "ref">) => Omit, HTMLLabelElement>, "ref">; getErrorsAttrs: ({ ...attrs }?: Omit, HTMLUListElement>, "ref">) => Omit, HTMLUListElement>, "ref">; getSelectAttrs: ({ ...attrs }?: React.ComponentPropsWithoutRef<"select">) => React.ComponentPropsWithoutRef<"select">; }; export interface FormProviderProps extends React.PropsWithChildren<{ formDefinition: T; serverFormInfo?: ServerFormInfo; formRef?: React.RefObject; }> { } export declare function FormProvider(props: FormProviderProps): JSX.Element; export interface ControlWrapperProps extends React.PropsWithChildren<{ name: string; label?: string; labelAttrs: React.ComponentPropsWithoutRef<"label">; errorAttrs: React.ComponentPropsWithoutRef<"ul">; formDefinition?: T; serverFormInfo?: ServerFormInfo; info: InputInfo; }> { } export interface InputProps extends UseValidatedInputOpts, Omit, "name"> { label: string; index?: number; } export declare function Input({ name, formDefinition: formDefinitionProp, serverFormInfo: serverFormInfoProp, label, index, ...inputAttrs }: InputProps): JSX.Element; export interface TextAreaProps extends UseValidatedInputOpts, Omit, "name"> { label: string; index?: number; } export declare function TextArea({ name, formDefinition: formDefinitionProp, serverFormInfo: serverFormInfoProp, label, index, ...inputAttrs }: TextAreaProps): JSX.Element; export interface SelectProps extends UseValidatedSelectOpts, Omit, "name"> { label: string; index?: number; } export declare function Select({ name, formDefinition: formDefinitionProp, serverFormInfo: serverFormInfoProp, label, index, children, ...inputAttrs }: SelectProps): JSX.Element; export interface ErrorProps { id?: string; messages?: Record; } export declare function Errors({ id, messages, ...attrs }: ErrorProps): JSX.Element | null; export {};