@cosva-lab/form-builder
Version:
React form builder.
148 lines (147 loc) • 7.97 kB
TypeScript
import { JSXElementConstructor, ReactNode } from 'react';
import { GridSize } from '@mui/material/Grid';
import { OutlinedInputProps } from '@mui/material/OutlinedInput';
import { Breakpoint } from '@mui/material/styles';
import { TextFieldProps } from '@mui/material/TextField';
import type { FieldsBuilder, FieldBuilder } from './utils/builders';
import { validators, InputValidator, InputsValidator } from './utils/validate';
import { Reducer } from './utils/types';
export type NameField = PropertyKey;
export type GetArrayValues<T> = T[keyof T][];
export type GetFields<FieldsObject> = {
[Field in keyof FieldsObject]: FieldBuilder<FieldsObject[Field], Field, LabelPropsField>;
};
export interface Message {
ns?: string;
message: string;
/**
* @description Properties to be passed to translate
*/
props?: any;
}
export interface EventField<V, Name extends NameField> {
name: Name;
value: V;
type?: string;
}
export interface EventChangeValue<V = value, Name = string> {
name: Name;
value: V;
}
export type OnChangeFieldEvent<V, Name extends NameField, Label extends LabelPropsField> = EventField<V, Name> & {
field: FieldBuilder<V, Name, Label>;
};
export type OnChangeField<V, Name extends NameField, Label extends LabelPropsField> = (e: OnChangeFieldEvent<V, Name, Label>, nativeEvent?: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => void | (() => void);
export type OnSetValue<V, Name extends NameField, Label extends LabelPropsField> = (e: {
lastValue: V;
newValue: V;
field: FieldBuilder<V, Name, Label>;
}) => void;
export type value = any;
export type GlobalProps = () => {
[key: string]: any;
};
export type transPosition = string | boolean;
export type ActiveStep = number;
export interface InitialState {
ns?: string;
}
export interface GlobalPropsInterface {
globalProps?: GlobalProps;
children?: ReactNode;
}
export type ValidateInputsValidator<Name extends NameField = string, Item extends PropsField<value, Name> = PropsField<value, Name>, Fields extends Item[] = Item[], FieldsObject = Reducer<Fields>> = ValidationsFields<Name, Item, Fields, FieldsObject>['validate'];
export interface GridRender {
/**
* @default true
*/
grid?: boolean;
}
export interface FieldsProps<Name extends NameField = string, Item extends PropsField<value, Name> = PropsField<value, Name>, Fields extends Item[] = Item[], FieldsObject = Reducer<Fields>> extends InitialState, GlobalPropsInterface, ValidationsFields<Name, Item, Fields, FieldsObject>, GridRender {
fields: [...Fields];
}
export type Rules = keyof typeof validators;
export interface Validation extends Message {
rule: Rules;
args?: any;
}
export type GenericFieldsBuilder = FieldsBuilder<string, PropsField<value, any, any>, PropsField<value, any, any>[], Record<string, value>, true>;
export interface AllPropsValidationFunction<V, Name extends NameField, Label extends LabelPropsField> extends Partial<Validate<V, Name, Label>> {
fieldsBuilder?: GenericFieldsBuilder;
field: FieldBuilder<V, Name, Label>;
activeStep?: ActiveStep;
}
/**
* @description
* Defines the map of errors returned from failed validation checks.
*
* @publicApi
*/
export type ValidationError = string | React.ReactElement<any> | Message;
export type ValidationErrors = ValidationError[];
export type ReturnValidationError = undefined | void | ValidationError;
export type ValidationFunction<V, Name extends NameField, Label extends LabelPropsField> = (all: AllPropsValidationFunction<V, Name, Label>) => ReturnValidationError | Promise<ReturnValidationError>;
export interface Validations<V, Name extends NameField, Label extends LabelPropsField> {
validate?: boolean | ((arg: any) => boolean);
value: V;
validations?: (Validation | ValidationFunction<V, Name, Label>)[];
}
export interface ValidationsField<V, Name extends NameField, Label extends LabelPropsField> extends Validations<V, Name, Label> {
validate?: boolean | ((inputValidator: InputValidator<V, Name, Label>) => boolean);
}
export interface ValidationsFields<Name extends NameField = string, Item extends PropsField<value, Name> = PropsField<value, Name>, Fields extends Item[] = Item[], FieldsObject = Reducer<Fields>> {
validate?: boolean | ((inputsValidator: InputsValidator<Name, Item, Fields, FieldsObject>) => boolean);
}
export type ChildrenRender = React.ReactElement<FieldProps<unknown, string, LabelPropsField>, JSXElementConstructor<FieldProps<unknown, string, LabelPropsField>>>;
export type RenderField<V, Name extends NameField, Label extends LabelPropsField> = (element: {
children: ChildrenRender;
props: FieldProps<V, Name, Label>;
}) => React.CElement<any, any>;
export type ComponentField<V, Name extends NameField, Label extends LabelPropsField> = React.ElementType<FieldProps<V, Name, Label>>;
export interface ComponentErrorsProps<V, Name extends NameField, Label extends LabelPropsField> {
errors: ValidationErrors;
field?: FieldBuilder<V, Name, Label>;
}
export type ComponentErrors<V, Name extends NameField, Label extends LabelPropsField> = React.ElementType<ComponentErrorsProps<V, Name, Label>>;
export type TypeTextField = 'date' | 'email' | 'number' | 'password' | 'search' | 'tel' | 'text' | 'time' | 'url' | 'week' | 'datetime-local';
export type TypeField = 'component' | TypeTextField;
export type TextFieldPropsField = Pick<TextFieldProps, 'multiline' | 'rows' | 'autoComplete' | 'autoFocus' | 'color' | 'defaultValue' | 'disabled' | 'FormHelperTextProps' | 'fullWidth' | 'helperText' | 'id' | 'InputLabelProps' | 'inputRef' | 'label' | 'margin' | 'placeholder' | 'required' | 'select' | 'SelectProps'>;
export type LabelPropsField = string | null | undefined | React.ReactElement<any> | Message;
export type InputPropsField<V, Name extends NameField, Label extends LabelPropsField> = ((a: {
type: InputProps<V, Name, Label>['type'];
changeType: (type: InputProps<V, Name, Label>['type'], callback?: () => void) => void;
} & BaseRender<V, Name, Label>) => Partial<OutlinedInputProps>) | Partial<OutlinedInputProps>;
export type BreakpointsField = Partial<Record<Breakpoint, boolean | GridSize>>;
export interface PropsFieldBase<V, Name extends NameField, Label extends LabelPropsField> extends GlobalPropsInterface {
type?: TypeField;
name: Name;
value: V;
disabled?: boolean;
defaultInputValue?: V;
label?: Label;
onChange?: OnChangeField<V, Name, Label>;
onSetValue?: OnSetValue<V, Name, Label>;
}
export interface PropsField<V, Name extends NameField, Label extends LabelPropsField = LabelPropsField> extends PropsFieldBase<V, Name, Label>, ValidationsField<V, Name, Label>, InitialState, GridRender {
render?: RenderField<V, Name, Label>;
fullWidth?: boolean;
errors?: ValidationErrors;
autoComplete?: string;
InputProps?: InputPropsField<V, Name, Label>;
textFieldProps?: TextFieldPropsField;
breakpoints?: BreakpointsField;
component?: ComponentField<V, Name, Label>;
renderErrors?: ComponentErrors<V, Name, Label>;
}
export interface Validate<V, Name extends NameField, Label extends LabelPropsField> extends Validations<V, Name, Label> {
state?: boolean;
}
export interface BaseRender<V, Name extends NameField, Label extends LabelPropsField> {
field: FieldBuilder<V, Name, Label>;
}
export interface FieldProps<V, Name extends NameField, Label extends LabelPropsField> extends BaseRender<V, Name, Label>, GridRender {
onChangeField?(event: EventField<V, Name>, nativeEvent?: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>): void | (() => void);
}
export interface InputProps<V, Name extends NameField, Label extends LabelPropsField> extends FieldProps<V, Name, Label> {
type?: TypeTextField;
}