@mantine/form
Version:
Mantine form management library
168 lines (167 loc) • 10.5 kB
TypeScript
import type { FormArrayElement, FormPathValue, LooseKeys } from './paths.types';
import type { formRootRule } from './validate/validate-values';
export type GetInputPropsType = 'input' | 'checkbox' | 'radio';
export type FormMode = 'controlled' | 'uncontrolled';
export type FormStatus = Record<string, boolean>;
export interface FormFieldValidationResult {
hasError: boolean;
error: React.ReactNode;
}
export interface FormValidationResult {
hasErrors: boolean;
errors: FormErrors;
}
export type FormErrors = Record<string, React.ReactNode>;
export interface ReorderPayload {
from: number;
to: number;
}
type Rule<Value, Values> = (value: Value, values: Values, path: string, signal?: AbortSignal) => React.ReactNode | Promise<React.ReactNode>;
type SetSubmitting = React.Dispatch<React.SetStateAction<boolean>>;
export type FormRule<Value, Values> = NonNullable<Value> extends ReadonlyArray<infer ListValue> ? Partial<{
[Key in keyof ListValue]: ListValue[Key] extends ReadonlyArray<infer NestedListItem> ? FormRulesRecord<NestedListItem, Values> | Rule<ListValue[Key], Values> : FormRulesRecord<ListValue[Key], Values> | Rule<ListValue[Key], Values>;
} & {
[formRootRule]?: Rule<Value, Values>;
}> | Rule<Value, Values> : NonNullable<Value> extends Record<string, any> ? FormRulesRecord<Value, Values> | Rule<Value, Values> : Rule<Value, Values>;
export type FormRulesRecord<Values, InitValues = Values> = Partial<{
[Key in keyof Values]: FormRule<Values[Key], InitValues>;
}> & {
[formRootRule]?: Rule<Values, InitValues>;
};
export type FormValidateInput<Values> = FormRulesRecord<Values> | ((values: Values) => FormErrors | Promise<FormErrors>);
export type SetValues<out Values> = <TValues extends Values>(value: Partial<TValues> | ((prevState: Partial<TValues>) => Partial<TValues>)) => void;
export type SetInitialValues<out Values> = <TValues extends Values>(values: TValues) => void;
export type SetErrors = React.Dispatch<React.SetStateAction<FormErrors>>;
export type SetFormStatus = React.Dispatch<React.SetStateAction<FormStatus>>;
export type OnSubmit<Values, TransformedValues = Values> = (handleSubmit: (values: TransformedValues, event: React.SyntheticEvent<HTMLFormElement> | undefined) => void | Promise<any>, handleValidationFailure?: (errors: FormErrors, values: Values, event: React.SyntheticEvent<HTMLFormElement> | undefined) => void) => (event?: React.SyntheticEvent<HTMLFormElement>) => void;
export type GetTransformedValues<out Values, TransformedValues = Values> = <TValues extends Values>(values?: TValues) => TransformedValues;
export type OnReset = (event: React.SyntheticEvent<HTMLFormElement>) => void;
export interface GetInputPropsOptions {
type?: GetInputPropsType;
withError?: boolean;
withFocus?: boolean;
[key: string]: any;
}
export interface GetInputPropsReturnType {
onChange: any;
value?: any;
defaultValue?: any;
checked?: any;
defaultChecked?: any;
error?: any;
onFocus?: any;
onBlur?: any;
}
export type GetInputProps<Values> = <Field extends LooseKeys<Values>>(path: Field, options?: GetInputPropsOptions) => GetInputPropsReturnType;
export type SetFieldValue<out Values> = <TValues extends Values, Field extends LooseKeys<TValues>>(path: Field, value: FormPathValue<TValues, Field> | ((prevValue: FormPathValue<TValues, Field>) => FormPathValue<TValues, Field>), options?: {
forceUpdate: boolean;
}) => void;
export type ClearFieldError<Values = unknown> = <Field extends LooseKeys<Values>>(path: Field) => void;
export type ClearFieldDirty<Values = unknown> = <Field extends LooseKeys<Values>>(path: Field) => void;
export type ClearErrors = () => void;
export type Reset = () => void;
type IsAsyncFn<R> = R extends (...args: any[]) => infer Ret ? [Extract<Ret, Promise<any>>] extends [never] ? false : true : false;
type HasAsyncInRecord<V> = V extends object ? true extends {
[K in keyof V]: V[K] extends (...args: any[]) => any ? IsAsyncFn<V[K]> : V[K] extends object ? true extends {
[J in keyof V[K]]: IsAsyncFn<V[K][J]>;
}[keyof V[K]] ? true : false : false;
}[keyof V] ? true : false : false;
export type HasAsyncRules<V> = V extends undefined ? false : V extends (...args: any[]) => infer R ? [Extract<R, Promise<any>>] extends [never] ? false : true : V extends object ? HasAsyncInRecord<V> : false;
export type Validate<Rules = any> = () => [HasAsyncRules<Rules>] extends [true] ? Promise<FormValidationResult> : [HasAsyncRules<Rules>] extends [false] ? FormValidationResult : FormValidationResult | Promise<FormValidationResult>;
export type ValidateField<Values, Rules = any> = <Field extends LooseKeys<Values>>(path: Field) => [HasAsyncRules<Rules>] extends [true] ? Promise<FormFieldValidationResult> : [HasAsyncRules<Rules>] extends [false] ? FormFieldValidationResult : FormFieldValidationResult | Promise<FormFieldValidationResult>;
export type SetFieldError<Values> = <Field extends LooseKeys<Values>>(path: Field, error: React.ReactNode) => void;
export type SetFieldTouched<Values> = <Field extends LooseKeys<Values>>(path: Field, touched: boolean) => void;
export type SetFieldDirty<Values> = <Field extends LooseKeys<Values>>(path: Field, dirty: boolean, forceUpdate?: boolean) => void;
export type SetCalculatedFieldDirty<out Values> = <TValues extends Values, Field extends LooseKeys<Values>>(path: Field, value: FormPathValue<TValues, Field>) => void;
export type ReorderListItem<out Values> = <Field extends LooseKeys<Values>>(path: Field, payload: ReorderPayload) => void;
export type InsertListItem<out Values> = <Field extends LooseKeys<Values>, Element extends FormArrayElement<Values, Field>>(path: Field, item: Element, index?: number) => void;
export type ReplaceListItem<out Values> = <Field extends LooseKeys<Values>, Element extends FormArrayElement<Values, Field>>(path: Field, index: number, item: Element) => void;
export type RemoveListItem<out Values> = <Field extends LooseKeys<Values>>(path: Field, index: number) => void;
export type GetFieldStatus<Values> = <Field extends LooseKeys<Values>>(path?: Field) => boolean;
export type ResetStatus = () => void;
export type GetStatus = () => FormStatus;
export type ResetDirty<out Values> = <TValues extends Values>(values?: TValues) => void;
export type IsValid<Values, Rules = any> = <Field extends LooseKeys<Values>>(path?: Field) => [HasAsyncRules<Rules>] extends [true] ? Promise<boolean> : [HasAsyncRules<Rules>] extends [false] ? boolean : boolean | Promise<boolean>;
export type IsValidating<Values> = <Field extends LooseKeys<Values>>(path?: Field) => boolean;
export type Initialize<out Values> = <TValues extends Values>(values: TValues) => void;
export type FormFieldSubscriber<out Values, out Field extends LooseKeys<Values>> = <TValues extends Values>(input: {
previousValue: FormPathValue<TValues, Field>;
value: FormPathValue<TValues, Field>;
touched: boolean;
dirty: boolean;
}) => void;
export type Watch<out Values, out Field extends LooseKeys<Values> = LooseKeys<Values>> = <TValues extends Values, TField extends Field>(path: TField, subscriber: FormFieldSubscriber<TValues, TField>) => void;
export type Key<Values> = <Field extends LooseKeys<Values>>(path: Field) => string;
export type GetInputNode<Values> = <NodeType extends HTMLElement, Field extends LooseKeys<Values>>(path: Field) => NodeType | null;
export interface UseFormInput<Values, TransformedValues = Values> {
name?: string;
mode?: FormMode;
initialValues?: Values;
initialErrors?: FormErrors;
initialTouched?: FormStatus;
initialDirty?: FormStatus;
transformValues?: (values: Values) => TransformedValues;
validate?: FormValidateInput<Values>;
clearInputErrorOnChange?: boolean;
validateInputOnChange?: boolean | LooseKeys<Values>[];
validateInputOnBlur?: boolean | LooseKeys<Values>[];
onValuesChange?: (values: Values, previous: Values) => void;
enhanceGetInputProps?: (payload: {
inputProps: GetInputPropsReturnType;
field: LooseKeys<Values>;
options: GetInputPropsOptions;
form: UseFormReturnType<Values, TransformedValues>;
}) => Record<string, any> | undefined | void;
onSubmitPreventDefault?: 'always' | 'never' | 'validation-failed';
touchTrigger?: 'focus' | 'change';
cascadeUpdates?: boolean;
validateDebounce?: number;
resolveValidationError?: (error: unknown) => React.ReactNode;
}
interface _UseFormReturnType<out Values, out TransformedValues = Values, Rules = any> {
values: Values;
submitting: boolean;
initialized: boolean;
errors: FormErrors;
setSubmitting: SetSubmitting;
initialize: Initialize<Values>;
setValues: SetValues<Values>;
setInitialValues: SetInitialValues<Values>;
setErrors: SetErrors;
setFieldValue: SetFieldValue<Values>;
setFieldError: SetFieldError<Values>;
clearFieldError: ClearFieldError<Values>;
clearErrors: ClearErrors;
reset: Reset;
validate: Validate<Rules>;
validateField: ValidateField<Values, Rules>;
reorderListItem: ReorderListItem<Values>;
removeListItem: RemoveListItem<Values>;
replaceListItem: ReplaceListItem<Values>;
insertListItem: InsertListItem<Values>;
getInputProps: GetInputProps<Values>;
onSubmit: OnSubmit<Values, TransformedValues>;
onReset: OnReset;
isDirty: GetFieldStatus<Values>;
isTouched: GetFieldStatus<Values>;
setTouched: SetFormStatus;
setDirty: SetFormStatus;
resetTouched: ResetStatus;
resetDirty: ResetDirty<Values>;
isValid: IsValid<Values, Rules>;
validating: boolean;
isValidating: IsValidating<Values>;
getTransformedValues: GetTransformedValues<Values, TransformedValues>;
getValues: () => Values;
getInitialValues: () => Values;
getTouched: GetStatus;
getDirty: GetStatus;
watch: Watch<Values>;
key: Key<Values>;
getInputNode: GetInputNode<Values>;
resetField: <Field extends LooseKeys<Values>>(path: Field) => void;
}
export type UseFormReturnType<Values, TransformedValues = Values, Rules = any> = _UseFormReturnType<Values, TransformedValues, Rules>;
export type UseForm<Values = Record<string, unknown>, TransformedValues = Values, Rules = any> = (input?: UseFormInput<Values, TransformedValues>) => UseFormReturnType<Values, TransformedValues, Rules>;
export type TransformedValues<Form extends UseFormReturnType<any, any, any>> = Parameters<Parameters<Form['onSubmit']>[0]>[0];
export {};