import { forwardRef, type PropsWithChildren, useEffect, useImperativeHandle } from 'react'; import { type FieldValues, FormProvider, useForm } from 'react-hook-form'; import type { FormerProps, FormerRef } from './Former.types'; import { FormerProvider, useFormerStore } from './Former.store'; import { FormerLayout } from './FormerLayout'; const FormerInner = forwardRef, Partial> & PropsWithChildren>( function FormerInner( props: Partial> & PropsWithChildren, ref: any ) { const { getState, onChange, onClose, onOpen, opened, primeData, reset, save, setState, useFormProps, validate, values, wrapper, } = useFormerStore((state) => ({ getState: state.getState, onChange: state.onChange, onClose: state.onClose, onOpen: state.onOpen, opened: state.opened, primeData: state.primeData, reset: state.reset, save: state.save, setState: state.setState, useFormProps: state.useFormProps, validate: state.validate, values: state.values, wrapper: state.wrapper, })); const formMethods = useForm({ defaultValues: primeData, mode: 'all', shouldUseNativeValidation: true, values: values, ...useFormProps, }); useImperativeHandle( ref, () => ({ close: async () => { //console.log('close called'); onClose?.(); setState('opened', false); }, getValue: () => { return getState('values'); }, reset: () => { reset(); }, save: async () => { return await save(); }, setValue: (value: T) => { onChange?.(value); }, show: async () => { //console.log('show called'); setState('opened', true); onOpen?.(); }, validate: async () => { return await validate(); }, }), [getState, onChange, validate, save, reset, setState, onClose, onOpen] ); useEffect(() => { setState('getFormMethods', () => formMethods); if (formMethods) { formMethods.subscribe({ callback: ({ isDirty }) => { setState('dirty', isDirty); }, formState: { isDirty: true }, }); } }, [formMethods]); return ( {typeof wrapper === 'function' ? ( wrapper({props.children}, opened, onClose, onOpen, getState) ) : ( {props.children || null} )} ); } ); export const Former = forwardRef, FormerProps & PropsWithChildren>( function Former( props: FormerProps & PropsWithChildren, ref: any ) { //if opened is false and wrapper is defined as function, do not render anything if (!props.opened && typeof props.wrapper === 'function') { return null; } return ( {props.children} ); } );