@shopify/react-form
Version:
Manage react forms tersely and safely-typed with no magic using React hooks.
80 lines (79 loc) • 2.67 kB
TypeScript
import { ChangeEvent } from 'react';
export declare type ErrorValue = string | undefined;
export interface Validator<Value, Context> {
(value: Value, context: Context): ErrorValue;
}
export interface ListValidationContext<Item extends object> {
listItem: FieldStates<Item>;
siblings: FieldStates<Item>[];
}
export declare type Validates<Value, Context extends object = {}> = Validator<Value, Context> | Validator<Value, Context>[];
export declare type NormalizedValidationDictionary<ListItem extends object> = {
[Key in keyof ListItem]: Validator<ListItem[Key], ListValidationContext<ListItem>>[];
};
export declare type ValidationDictionary<ListItem extends object, Context extends object = {}> = {
[Key in keyof ListItem]: Validates<ListItem[Key], Context>;
};
export interface FieldState<Value> {
value: Value;
defaultValue: Value;
error: ErrorValue;
touched: boolean;
dirty: boolean;
}
export declare type FieldStates<Record extends object> = {
[Key in keyof Record]: FieldState<Record[Key]>;
};
export interface Field<Value> {
value: Value;
error: ErrorValue;
defaultValue: Value;
touched: boolean;
dirty: boolean;
onBlur(): void;
onChange(value: Value | ChangeEvent<HTMLInputElement>): void;
runValidation(): ErrorValue;
setError(value: ErrorValue): void;
newDefaultValue(value: Value): void;
reset(): void;
}
export declare type FieldDictionary<Record extends object> = {
[Key in keyof Record]: Field<Record[Key]>;
};
export interface Form<T extends FieldBag> {
fields: T;
dirty: boolean;
submitting: boolean;
submitErrors: FormError[];
validate(): FormError[];
reset(): void;
submit(event?: React.FormEvent): void;
}
export interface FormError {
fieldPath?: string[];
message: string;
}
export declare type SubmitResult = {
status: 'fail';
errors: FormError[];
} | {
status: 'success';
};
export declare type FieldOutput<T extends object> = FieldDictionary<T> | Field<T> | FieldDictionary<T>[];
export interface FieldBag {
[key: string]: FieldOutput<any>;
}
export interface SubmitHandler<Fields> {
(fields: Fields): Promise<SubmitResult>;
}
declare type FieldProp<T, K extends keyof Field<any>> = T extends Field<any> ? T[K] : T extends FieldDictionary<any> ? {
[InnerKey in keyof T]: T[InnerKey][K];
} : T;
export declare type FormMapping<Bag extends {
[key: string]: FieldOutput<any>;
}, FieldKey extends keyof Field<any>> = {
[Key in keyof Bag]: Bag[Key] extends any[] ? {
[Index in keyof Bag[Key]]: FieldProp<Bag[Key][Index], FieldKey>;
} : FieldProp<Bag[Key], FieldKey>;
};
export {};