* Refactor Former components to streamline functionality * Update stories to reflect changes in form structure
125 lines
3.2 KiB
TypeScript
125 lines
3.2 KiB
TypeScript
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<FormerRef<any>, Partial<FormerProps<any>> & PropsWithChildren>(
|
|
function FormerInner<T extends FieldValues>(
|
|
props: Partial<FormerProps<T>> & PropsWithChildren<T>,
|
|
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<T>({
|
|
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 (
|
|
<FormProvider {...formMethods}>
|
|
{typeof wrapper === 'function' ? (
|
|
wrapper(<FormerLayout>{props.children}</FormerLayout>, opened, onClose, onOpen, getState)
|
|
) : (
|
|
<FormerLayout>{props.children || null}</FormerLayout>
|
|
)}
|
|
</FormProvider>
|
|
);
|
|
}
|
|
);
|
|
|
|
export const Former = forwardRef<FormerRef<any>, FormerProps<any> & PropsWithChildren>(
|
|
function Former<T extends FieldValues = any>(
|
|
props: FormerProps<T> & PropsWithChildren<T>,
|
|
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 (
|
|
<FormerProvider {...props}>
|
|
<FormerInner ref={ref}>{props.children}</FormerInner>
|
|
</FormerProvider>
|
|
);
|
|
}
|
|
);
|