@bolttech/form-engine
Version:
A react adapter for bolttech form engine
327 lines (308 loc) • 14.4 kB
TypeScript
import * as react from 'react';
import { PropsWithChildren, ReactElement, ElementType, ReactNode } from 'react';
import { TEventProps, TFieldEvent, TEventDataProps, TFormValues, TFormValidationPayload, TFormEntry, IComponentSchemaAsFormField, IComponentSchema, OneOf, TMapper, TFormGroupOnDataEventPayload, FormCore, TFormGroup, TSchemaFormConfig, FormField, TFormGroupOnValidEventPayload, TFormGroupOnSubmitEventPayload, TValueChangeEvent } from '@bolttech/form-engine-core';
/**
* Represents a field wrapper containing the name of the field and its index in the form.
*
* @property {string} name - The name of the field.
* @property {string} formIndex - The index of the field within the form.
*/
type TFieldWrapper = {
name: string;
formIndex: string;
};
/**
* Represents the content inside onData payload action.
*/
type TFormData<T> = {
field: string;
data: TFormValues<T>;
};
/**
*
* @property {(payload: TFormValues<T>) => void} onFormMount - triggered when form mounts
* @property {(payload: TFormValues<T>) => void} onData - triggered when any field change value
* @property {(payload: TFormValues<T>) => void} onSubmit - triggered when submit button is pressed
* @property {(payload: TFormValues<T>) => void} onValid - triggered when form valid status changes
* @interface
*
*/
type TEventsCallbackProps<T> = Partial<Record<TEventProps, ((payload: TFieldEvent) => void) | null | undefined>> & Partial<Record<Extract<TEventDataProps, 'onFormMount' | 'onSubmit'>, (payload: TFormValues<T>) => void>> & Partial<Record<Extract<TEventDataProps, 'onData'>, (payload: {
field: string;
data: TFormValues<T>;
}) => void>> & Partial<Record<Extract<TEventDataProps, 'onValid'>, (payload: TFormValidationPayload) => void>>;
/**
* Form props, inherits the form instance constructor implementation except the mapper
* along with all event callback register props shared with other implementations
* @see {@link TFormEntry}
* @see {@link TEventsCallbackProps}
* @interface
* @example
* ```typescript
* import { Form } from '@bolttech/form-engine';
*
* <Form index={'foo'} schema={schema} onData={console.log} />
* ```
*/
type TFormProps<T> = Omit<TFormEntry, 'mappers' | 'dataSubject$' | 'formValidSubject$' | 'submitSubject$'> & TEventsCallbackProps<T>;
/**
*
* @param {TFormProps} param form properties initializor
* @returns {ReactElement}
*/
declare function Form<T>({ schema, index, initialValues, iVars, action, method, config, prefetchedData, onSubmit, onFormMount, onData, onBlur, onChange, onApiResponse, onClick, onFocus, onKeyDown, onKeyUp, onMount, onValid, stopEventsOnSubmit, children, }: PropsWithChildren<TFormProps<T>>): ReactElement;
/**
* AsFormField props, inherits all schema field implementation except the children
* property and has mappers property to pass a custom component, that will be a ReactNode
* @see {@link IComponentSchemaAsFormField}
*/
type TAsFormFieldProps = PropsWithChildren<Omit<IComponentSchemaAsFormField<ElementType>, 'children'>>;
/**
* Component wrapper to aid building schemas with react without writting a JSON schema
* along with BuildAsFormFieldTree inside a Form component, FieldWrapper gets this props
* to build the component as it does with a JSON schema, this component only works inside
* the Form component
*
* @param {TAsFormFieldProps} props JSON schema props
* @returns {ReactNode}
*/
declare const AsFormField: (props: TAsFormFieldProps) => ReactNode;
/**
* AsFormField props, inherits all schema field implementation except the children
* property, that will be a ReactNode
* also gets the formIndex for form identification and the mapper to build the component
* @property {TMapper} mapper element mapper to use
* @property {boolean} visibility element controlled visibility
* @property {(data: TFieldEvent) => void} onSelected element callback on selected option
* @see {@link TMapper}
* @see {@link IComponentSchema}
* @see {@link TFieldWrapper}
* @interface
*/
type TAsFormFieldBuilderProps = PropsWithChildren<Omit<IComponentSchema, 'component' | 'children' | 'name'> & Required<TFieldWrapper> & {
onSelected?: (data: TFieldEvent) => void;
formMounted?: boolean;
} & OneOf<{
mapper: TMapper<ElementType>;
component: string;
}>>;
/**
* Component Wrapper to render form fields without the Form component, gets additional formId and mapper since
* it won't rely on them and needs to be manually declared
*
* @param {TAsFormFieldBuilderProps} props JSON schema props along with FieldWrapper props and mapper props
* @returns {ReactElement}
*/
declare const AsFormFieldBuilder: (props: TAsFormFieldBuilderProps) => ReactElement;
type TRepeaterProps = {
formIndex: string;
index: number;
};
type TRepeaterFooterProps = Pick<TRepeaterProps, 'formIndex'>;
/**
* AsFormFieldRepeater props needed to build a repeater to build forms
* @property {ElementType<TRepeaterProps>} RepeaterComponent element to use as repeater
* @property {string} addFieldName field name button that will add an element on a position on a repeater
* @property {string} removeFieldName field name button that will remove an element on a position on a repeater
* @property {Record<string, unknown>[]} existingElements elements to restore a repeater list
* @property {number} initialElements elements to be pre-rendered when the form is presented
* @property {(payload: TFormGroupOnDataEventPayload<unknown>) => void} stateUpdater similar to onData for the group of form managed by the repeater
* @property {string} formPrefix prefix to use on the repeated forms ex: (person- will go person-1, person-2, ...)
* @property {ElementType<TRepeaterFooterProps>} RepeaterFooter component with a button that will add an element to the bottom of the list
* @see {@link TMapper}
* @see {@link IComponentSchema}
* @see {@link TFieldWrapper}
* @interface
* @example
* ```typescript
* import { AsFormFieldRepeater } from '@bolttech/form-engine';
*
* <AsFormFieldRepeater
* RepeaterComponent={FormElement}
* RepeaterFooter={FormElementFooter}
* addFieldName="addForm"
* removeFieldName="removeForm"
* formPrefix="insured"
* stateUpdater={(payload) => {
* console.log(payload);
* }}
* />
* ```
*/
type TAsFormFieldRepeaterProps = {
RepeaterComponent: ElementType<TRepeaterProps>;
addFieldName?: string;
removeFieldName?: string;
stateUpdater?: (payload: TFormGroupOnDataEventPayload<unknown>) => void;
formPrefix?: string;
RepeaterFooter: ElementType<TRepeaterFooterProps>;
} & OneOf<{
existingElements?: Record<string, unknown>[];
initialElements?: number;
}>;
/**
* Adapter do manage repeated list elements on form
*
* @param {TAsFormFieldRepeaterProps} props Repeater properties to configure the elements repeater
* @returns {ReactElement}
*/
declare const AsFormFieldRepeater: ({ RepeaterComponent, addFieldName, removeFieldName, existingElements, initialElements, stateUpdater, formPrefix, RepeaterFooter, }: TAsFormFieldRepeaterProps) => ReactNode;
/**
* Represents the context for managing forms within a form group.
*
* @property {function(string): void} addFormWithIndex - Adds a form to the form group by its index.
* @property {function({ key: string, formInstance: TFormCore }): void} addForm - Adds a form to the form group using a payload containing the key and form instance.
* @property {function({ key: string }): (FormCore | undefined)} getForm - Retrieves a form from the form group using a payload containing the key.
* @property {function({ key: string }): void} removeForm - Removes a form from the form group using a payload containing the key.
* @property {TFormGroup} formGroupInstance - The instance of the form group.
* @property {TMapper<ElementType>[]} [mappers] - Optional array of mappers for elements.
* @property {function(): void} printFormGroupInstance - Prints the form group instance.
* @property {function(string[]): TFormValues} submitMultipleFormsByIndex - Submits multiple forms by their indexes and returns the form values.
* @property {boolean} debugMode - Indicates if debug mode is active.
* @property {boolean} active - Indicates if the form context is active (if the context provider is defined above).
*
* @example
* ```typescript
* import React from 'react';
* import { useFormGroupContext } from '@bolttech/form-engine';
*
* const FormComponent = (): React.ReactElement => {
* const {
* addForm,
* removeForm,
* getForm,
* printFormGroupInstance,
* submitMultipleFormsByIndex,
* debugMode
* } = useFormGroupContext();
*
* // (...)
* };
* ```
*
*/
type TFormContext = {
addFormWithIndex: (index: string) => void;
addForm: (payload: {
key: string;
params: TFormEntry;
}) => void;
getForm: (payload: {
key: string;
}) => FormCore | undefined;
removeForm: (payload: {
key: string;
}) => void;
formGroupInstance: TFormGroup<ElementType>;
mappers?: TMapper<ElementType>[];
printFormGroupInstance: () => void;
submitMultipleFormsByIndex: <T>(indexes: string[], callback?: (payload: TFormValues<T>) => void) => void;
debugMode: boolean;
active: boolean;
config?: TSchemaFormConfig;
};
/**
* Represents the props for a form context provider.
*
* @property {TMapper<ElementType>[]} [mappers] - Optional array of mappers for elements.
* @property {boolean} [debugMode] - Optional flag indicating if debug mode should be enabled.
* @property {TSchemaFormConfig} config - Optional config settings for debounce times and client logging
*
* * @example
* ```tsx
* import { FormGroupContextProvider } from '@bolttech/form-engine';
*
* <FormGroupContextProvider mappers={mappers} debugMode={true}>
* {children}
* </FormGroupContextProvider>
* ```
*/
type TFormContextProvider = {
mappers?: TMapper<ElementType>[];
debugMode?: boolean;
config?: TSchemaFormConfig;
};
declare const FormGroupContext: react.Context<TFormContext>;
/**
* context provider to wrap form-engine adapter elements
*
* @param {PropsWithChildren<TFormContextProvider>} param context parameters
* @returns {ReactElement}
*/
declare const FormGroupContextProvider: ({ children, mappers, debugMode, config, }: PropsWithChildren<TFormContextProvider>) => ReactElement;
/**
* FormGroup context hook to handle context or isolated context implementations
*
* @param {TFormContextProvider} props form group context parameters
* @returns {TFormContext}
*/
declare const useFormGroupContext: (props?: TFormContextProvider) => TFormContext;
/**
* Represents the props for a field wrapper component, including children.
*
* @property {Record<string, unknown>} [props] - Additional properties for the field.
* @property {TFormContext | null} [context] - The context of the form, which may be null.
* @property {React.ReactNode} children - The child elements of the component.
* @see {@link TFieldWrapper}
*/
type TFieldWrapperProps = PropsWithChildren<TFieldWrapper & {
props?: Record<string, unknown>;
context?: TFormContext | null;
mounted?: boolean;
mapper?: TMapper<ElementType>;
component?: string;
visibility?: boolean;
}>;
/**
* Represents the props for rendering a field wrapper component, including children.
*
* @property {Record<string, unknown>} props - Additional properties for the field.
* @property {FormField} [fieldInstance] - The instance of the form field, which may be undefined.
* @property {React.ReactNode} children - The child elements of the component.
*/
type TFieldWrapperComponentRenderProps = PropsWithChildren<{
props: Record<string, unknown>;
fieldInstance?: FormField;
mapper?: TMapper<ElementType>;
}>;
/**
* Represents the properties for the useForm hook, including an ID and event callback properties.
*
* @property {string} id - The unique identifier for the form. Deprecated, use 'index' instead
* @property {string} index - The unique identifier for the form.
*
* @see {@link TEventsCallbackProps}
* @interface
*/
type TUseFormProps<T> = Pick<TFormEntry, 'index' | 'initialValues' | 'iVars' | 'stopEventsOnSubmit'> & TEventsCallbackProps<T> & OneOf<{
id: string;
index: string;
}>;
/**
* Hook to register events callback functions
*/
declare function useForm<T>({ id, index, onData, onSubmit, onFormMount, onValid, iVars, initialValues, stopEventsOnSubmit, ...rest }: TUseFormProps<T>, deps?: React.DependencyList): void;
/**
* Represents the properties for the useFormGroup hook, including a list of ID's and event callback properties.
*
* @property {string} ids - The unique identifier for the forms.
* @property {payload: TFormGroupOnDataEventPayload<T>} onData - callback event occurring when a value is changing via input or logic.
* @property {payload: TFormGroupOnValidEventPayload} onData - callback event occurring when validation status changes on the form.
* @property {payload: TFormGroupOnSubmitEventPayload<T>} onData - event occurring when form submission is trigger.
*
*/
type TUseFormGroup<T> = {
ids: string[];
onData?: (payload: TFormGroupOnDataEventPayload<T>) => void;
onValid?: (payload: TFormGroupOnValidEventPayload) => void;
onSubmit?: (payload: TFormGroupOnSubmitEventPayload<T>) => void;
};
declare function useFormGroup<T>({ ids, onData, onValid, onSubmit }: TUseFormGroup<T>, deps?: React.DependencyList): void;
declare const defaultChangeEvent: TValueChangeEvent;
declare const checkedChangeEvent: TValueChangeEvent;
declare const valueChangeEvent: TValueChangeEvent;
declare const numberInputChangeEvent: TValueChangeEvent;
declare const datepickerChangeEvent: TValueChangeEvent;
declare const dropdownChangeEvent: TValueChangeEvent;
export { AsFormField, AsFormFieldBuilder, AsFormFieldRepeater, Form, FormGroupContext, FormGroupContextProvider, checkedChangeEvent, datepickerChangeEvent, defaultChangeEvent, dropdownChangeEvent, numberInputChangeEvent, useForm, useFormGroup, useFormGroupContext, valueChangeEvent };
export type { TAsFormFieldBuilderProps, TAsFormFieldProps, TAsFormFieldRepeaterProps, TEventsCallbackProps, TFieldWrapper, TFieldWrapperComponentRenderProps, TFieldWrapperProps, TFormContext, TFormContextProvider, TFormData, TFormProps, TRepeaterFooterProps, TRepeaterProps };