pagamio-frontend-commons-lib
Version:
Pagamio library for Frontend reusable components like the form engine and table container
312 lines (311 loc) • 10 kB
TypeScript
import type { Control, FieldErrors, FieldValues, RegisterOptions } from 'react-hook-form';
import type React from 'react';
export interface ActionProps {
field: string;
options?: SelectOption[] | string[];
value?: any;
label?: string;
hideField?: boolean;
fieldInnitialData?: Field;
validation?: ValidationRule;
}
export interface SelectOption {
label: string;
value: string;
id?: number;
}
export interface BaseInputProps {
field: Field;
error?: {
message?: string;
};
value?: any;
options?: Array<SelectOption | string>;
onChange: (value: any) => void;
onBlur?: () => void;
name: string;
ref?: React.Ref<any>;
control?: Control<any>;
}
/**
* Represents the state of a form, including validation errors and optional message
*/
export type FormState = {
errors?: {
name?: string[];
email?: string[];
password?: string[];
};
message?: string;
} | undefined;
/**
* Defines the structure of control fields used in authentication forms
*/
export type ControlFields = {
username: string;
password: string;
emailAddress?: string;
profile?: string;
role?: string;
};
/**
* Reference object exposing form control methods
*/
export interface FormRef {
reset: () => void;
setValue?: (name: string, value: any) => void;
}
/**
* Props for the FormEngine component which handles form rendering and submission
*/
export interface FormEngineProps<T extends Record<string, any>> {
/** Array of field definitions that make up the form */
fields: Field[];
/** Callback function called when the form is submitted */
onSubmit: (data: any) => Promise<void>;
/** Layout direction of the form */
layout?: 'vertical' | 'horizontal';
/** Initial values for form fields */
initialValues?: any;
/** Custom tailwind class for the Form Engine */
className?: string;
/** Custom tailwind class for the submit button */
submitButtonClass?: string;
/** Flag to disable automatic form submission trigger */
isNotTrigger?: boolean;
/** Flag to show or hide the cancel button */
showCancelButton?: boolean;
/** Flag dynamic display submit button text */
submitButtonText?: string;
/** Show submitting indicator text */
showSubmittingText?: boolean;
/** Callback function called when form cancellation is requested */
onCancel: () => void;
/** Callback function called whenever a field value changes */
getFieldValues?: (fields: T) => void;
/** Optional persistence key for form data */
persistenceKey?: string;
/**
* Optional ref to expose form control methods.
* When not provided, the form will automatically reset after successful submission.
* When provided, the parent component controls form reset behavior.
*/
formRef?: React.MutableRefObject<FormRef | undefined>;
}
/**
* Defines validation rules that can be applied to form fields
*/
export type ValidationRule = {
/** Required field validation with optional custom message */
required?: string | {
value: boolean;
message: string;
};
/** Minimum value/length validation with message */
min?: {
value: string | number;
message: string;
};
/** Pattern validation with message */
pattern?: {
value: RegExp;
message: string;
};
/** Custom validation function */
validate?: (value: any) => boolean | string;
/** Dependency validation - applies validation based on another field's value */
dependency?: DependencyValidation | DependencyValidation[];
};
/**
* Defines a dependency validation rule
*/
export interface DependencyValidation {
/** The field this validation depends on */
field: string;
/** Condition function that determines if validation should be applied */
condition: (value: any) => boolean;
/** Validation rules to apply when condition is true */
validationToApply: Omit<ValidationRule, 'dependency'>;
}
/**
* Available field types supported by the form engine
*/
export type FieldType = 'card-expiry-input' | 'checkbox' | 'credit-card' | 'date' | 'email' | 'file' | 'multi-select' | 'number' | 'password' | 'radio' | 'searchable-multi-select' | 'select' | 'switch' | 'tel' | 'text' | 'textarea' | 'time';
/**
* Defines the structure of a form field
*/
export interface Field {
/** Field identifier */
name: string;
/** Display label for the field */
label: string;
/** Type of input field */
type: FieldType;
/** Placeholder text for the field */
placeholder?: string;
/** Number of grids a field will span */
gridSpan?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
/** Whether the field is checked (for checkbox/switch types) */
checked?: boolean;
/** To hide or show the upload button when the field is type file */
hideUploadButton?: boolean;
/** To validate file types say .png, .pdf etc */
allowedFileTypes?: string[];
/** To hide or show a preview of uploaded image */
showFileUploadPreview?: boolean;
/** To display file upload helper text */
fileUploadHelperText?: string;
/** Default country for phone input */
defaultCountry?: string;
/** Disables the field */
disabled?: boolean;
/** Validation rules for the field */
validation?: ValidationRule;
/** Options for select, multi-select, and radio fields */
options?: Array<SelectOption | string>;
/** callback for searchable select, multi-select */
onSearch?: (value: string) => void;
/** callback for onChange event */
onChange?: (value: string) => void;
isHidden?: boolean;
}
export interface DependentFieldUpdate {
field: string;
dependencies?: string[];
action: (value: any, isInitialLoad?: boolean) => Promise<ActionProps> | ActionProps;
}
/**
* Props for the Form component wrapper
*/
export interface FormProps {
/** Array of field definitions */
fieldDefinitions: Field[];
/** Form submission handler */
onFormSubmit: (data: any) => void;
/** Initial form values */
initialValues?: any;
/** Form layout direction */
layout?: 'vertical' | 'horizontal';
/** Flag to disable automatic form submission */
isNotTrigger?: boolean;
/** Flag to hide or show the cancel button */
showCancelButton?: boolean;
/** Form cancellation handler */
onFormCancel: () => void;
}
/**
* Props for the FieldWrapper component that provides layout and error handling
*/
export interface FieldWrapperProps {
/** Field definition */
field: Field;
/** React Hook Form control object */
control: Control;
/** Form validation errors */
errors: FieldErrors;
/** Layout direction */
layout: 'vertical' | 'horizontal';
/** All field values for dependency tracking */
allFieldValues?: Record<string, any>;
/** Field update callbacks */
onFieldUpdate?: Record<string, DependentFieldUpdate[]>;
/** Update field options callback */
updateFieldOptions?: (field: string, options: Array<SelectOption | string>) => void;
/** Update field label callback */
updateFieldLabel?: (fieldName: string, newLabelName: string) => void;
/** Hide field callback */
hideInputField?: (fieldName: string, hidden: boolean) => void;
/** Add new field callback */
addField?: (field: Field) => void;
/** Set value function from useForm */
setValue?: (name: string, value: any) => void;
/** Clear errors function from useForm */
clearErrors?: (field: string) => void;
/** Get values function from useForm */
getValues?: () => Record<string, any>;
}
/**
* Props for basic input components
*/
export interface InputProps extends BaseInputProps {
/** Field configuration */
field: Field;
/** Validation error if any */
error?: {
message: string;
};
}
/**
* Props for input components with options (select, radio, etc.)
*/
export interface InputOptionsProps {
/** Field configuration including validation rules */
field: {
validation: Omit<RegisterOptions<FieldValues, string>, 'valueAsNumber' | 'valueAsDate' | 'setValueAs' | 'disabled'> | undefined;
name: string;
label: string;
options: SelectOption[] | string[];
disabled?: boolean;
};
/** Validation error if any */
error?: {
message: string;
};
/** React Hook Form control object */
control: Control<any>;
}
/**
* Props for select input components
*/
export interface InputSelectProps extends BaseInputProps {
/** Validation error if any */
error?: {
message: string;
};
}
/**
* Props for switch/toggle input components
*/
export interface InputSwitchProps {
/** Field configuration */
field: any;
/** Validation error if any */
error?: {
message: string;
};
value?: boolean;
onChange?: (checked: boolean) => void;
}
/**
* Option structure for the searchable multi-select
*/
export interface SearchableMultiSelectOption {
value: string;
label: string;
}
/**
* Form persistence context data structure
*/
export interface FormPersistenceData {
/** Form field values */
values: Record<string, any>;
/** Timestamp when the data was last updated */
lastUpdated: number;
/** Whether the form is dirty (has changes) */
isDirty: boolean;
}
/**
* Form persistence context type
*/
export interface FormPersistenceContextType {
/** Get persisted form data by key */
getFormData: (key: string) => FormPersistenceData | null;
/** Set persisted form data by key */
setFormData: (key: string, data: Partial<FormPersistenceData>) => void;
/** Clear persisted form data by key */
clearFormData: (key: string) => void;
/** Clear all persisted form data */
clearAllFormData: () => void;
/** Check if form has persisted data */
hasFormData: (key: string) => boolean;
}