UNPKG

@bolttech/form-engine

Version:

A react adapter for bolttech form engine

327 lines (308 loc) 14.4 kB
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 };