@refinedev/react-hook-form 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,4 @@
1
+ export { useForm, UseFormProps, UseFormReturnType } from "./useForm";
2
+ export { useStepsForm, UseStepsFormProps, UseStepsFormReturnType, } from "./useStepsForm";
3
+ export { useModalForm, UseModalFormProps, UseModalFormReturnType, } from "./useModalForm";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AACrE,OAAO,EACH,YAAY,EACZ,iBAAiB,EACjB,sBAAsB,GACzB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACH,YAAY,EACZ,iBAAiB,EACjB,sBAAsB,GACzB,MAAM,gBAAgB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ var ne=Object.create;var g=Object.defineProperty;var ie=Object.getOwnPropertyDescriptor;var le=Object.getOwnPropertyNames;var de=Object.getPrototypeOf,ue=Object.prototype.hasOwnProperty;var me=(t,o)=>{for(var s in o)g(t,s,{get:o[s],enumerable:!0})},_=(t,o,s,p)=>{if(o&&typeof o=="object"||typeof o=="function")for(let a of le(o))!ue.call(t,a)&&a!==s&&g(t,a,{get:()=>o[a],enumerable:!(p=ie(o,a))||p.enumerable});return t};var ce=(t,o,s)=>(s=t!=null?ne(de(t)):{},_(o||!t||!t.__esModule?g(s,"default",{value:t,enumerable:!0}):s,t)),Te=t=>_(g({},"__esModule",{value:!0}),t);var pe={};me(pe,{useForm:()=>U,useModalForm:()=>q,useStepsForm:()=>I});module.exports=Te(pe);var w=require("react"),L=require("react-hook-form"),D=require("@refinedev/core"),U=({refineCoreProps:t,warnWhenUnsavedChanges:o,...s}={})=>{let{warnWhenUnsavedChanges:p,setWarnWhen:a}=(0,D.useWarnAboutChange)(),y=o!=null?o:p,f=(0,D.useForm)({...t}),{queryResult:n,onFinish:e,formLoading:S}=f,i=(0,L.useForm)({...s}),{watch:l,reset:x,getValues:V,handleSubmit:r}=i;(0,w.useEffect)(()=>{var d;if(typeof(n==null?void 0:n.data)<"u"){let b={},E=Object.keys(V());Object.entries(((d=n==null?void 0:n.data)==null?void 0:d.data)||{}).forEach(([C,m])=>{E.includes(C)&&(b[C]=m)}),x(b)}},[n==null?void 0:n.data]),(0,w.useEffect)(()=>{let d=l((b,{type:E})=>{E==="change"&&T(b)});return()=>d.unsubscribe()},[l]);let T=d=>(y&&a(!0),d),R=(d,b)=>async E=>(a(!1),await r(d,b)(E));return{...i,handleSubmit:R,refineCore:f,saveButtonProps:{disabled:S,onClick:d=>{R(e,()=>!1)(d)}}}};var v=require("react");var I=({stepsProps:t,...o}={})=>{let{defaultStep:s=0,isBackValidate:p=!1}=t!=null?t:{},[a,y]=(0,v.useState)(s),f=U({...o}),{trigger:n,getValues:e,reset:S,formState:{dirtyFields:i},refineCore:{queryResult:l}}=f;(0,v.useEffect)(()=>{var r;if(l!=null&&l.data){let T={},R=Object.keys(e());Object.entries((r=l==null?void 0:l.data)==null?void 0:r.data).forEach(([F,d])=>{R.includes(F)&&(i[F]?T[F]=e(F):T[F]=d)}),S(T,{keepDirty:!0,keepValues:!0})}},[l==null?void 0:l.data,a]);let x=r=>{let T=r;r<0&&(T=0),y(T)};return{...f,steps:{currentStep:a,gotoStep:async r=>{if(r===a)return;if(r<a&&!p){x(r);return}await n()&&x(r)}}}};var P=require("react"),u=require("@refinedev/core");var k=ce(require("react")),q=({modalProps:t,refineCoreProps:o,syncWithLocation:s,...p}={})=>{var K,O,A,Q,G,N,Y;let a=k.default.useRef(!1),y=(0,u.useTranslate)(),{resource:f,action:n}=o!=null?o:{},{resource:e,action:S}=(0,u.useResource)(f),i=(0,u.useParsed)(),l=(0,u.useGo)(),x=(K=n!=null?n:S)!=null?K:"",V=typeof s=="object"&&s.syncId,r=typeof s=="object"&&"key"in s?s.key:e&&x&&s?`modal-${(O=e==null?void 0:e.identifier)!=null?O:e==null?void 0:e.name}-${x}`:void 0,{defaultVisible:T=!1,autoSubmitClose:R=!0,autoResetForm:F=!0}=t!=null?t:{},d=U({refineCoreProps:o,...p}),{reset:b,refineCore:{onFinish:E,id:C,setId:m},saveButtonProps:ee,handleSubmit:te}=d,{visible:B,show:h,close:W}=(0,u.useModal)({defaultVisible:T});k.default.useEffect(()=>{var c,z,J,X;if(a.current===!1&&r){let H=(z=(c=i==null?void 0:i.params)==null?void 0:c[r])==null?void 0:z.open;if(typeof H=="boolean"?H&&h():typeof H=="string"&&H==="true"&&h(),V){let Z=(X=(J=i==null?void 0:i.params)==null?void 0:J[r])==null?void 0:X.id;Z&&(m==null||m(Z))}a.current=!0}},[r,i,V,m]),k.default.useEffect(()=>{var c;a.current===!0&&(B&&r?l({query:{[r]:{...(c=i==null?void 0:i.params)==null?void 0:c[r],open:!0,...V&&C&&{id:C}}},options:{keepQuery:!0},type:"replace"}):r&&!B&&l({query:{[r]:void 0},options:{keepQuery:!0},type:"replace"}))},[C,B,h,r,V]);let M=async c=>{await E(c),R&&W(),F&&b()},{warnWhen:$,setWarnWhen:re}=(0,u.useWarnAboutChange)(),oe=(0,P.useCallback)(()=>{if($)if(window.confirm(y("warnWhenUnsavedChanges","Are you sure you want to leave? You have unsaved changes.")))re(!1);else return;m==null||m(void 0),W()},[$]),se=(0,P.useCallback)(c=>{m==null||m(c),h()},[]),ae=y(`${e==null?void 0:e.name}.titles.${n}`,void 0,`${(0,u.userFriendlyResourceName)(`${n} ${(Y=(N=(G=(A=e==null?void 0:e.meta)==null?void 0:A.label)!=null?G:(Q=e==null?void 0:e.options)==null?void 0:Q.label)!=null?N:e==null?void 0:e.label)!=null?Y:e==null?void 0:e.name}`,"singular")}`);return{modal:{submit:M,close:oe,show:se,visible:B,title:ae},...d,saveButtonProps:{...ee,onClick:c=>te(M)(c)}}};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/useForm/index.ts","../src/useStepsForm/index.ts","../src/useModalForm/index.ts"],"sourcesContent":["export { useForm, UseFormProps, UseFormReturnType } from \"./useForm\";\nexport {\n useStepsForm,\n UseStepsFormProps,\n UseStepsFormReturnType,\n} from \"./useStepsForm\";\nexport {\n useModalForm,\n UseModalFormProps,\n UseModalFormReturnType,\n} from \"./useModalForm\";\n","import React, { useEffect } from \"react\";\nimport {\n useForm as useHookForm,\n UseFormProps as UseHookFormProps,\n UseFormReturn,\n FieldValues,\n UseFormHandleSubmit,\n SubmitHandler,\n SubmitErrorHandler,\n} from \"react-hook-form\";\nimport {\n BaseRecord,\n HttpError,\n useForm as useFormCore,\n useWarnAboutChange,\n UseFormProps as UseFormCoreProps,\n UseFormReturnType as UseFormReturnTypeCore,\n} from \"@refinedev/core\";\n\nexport type UseFormReturnType<\n TData extends BaseRecord = BaseRecord,\n TError extends HttpError = HttpError,\n TVariables extends FieldValues = FieldValues,\n TContext extends object = {},\n> = UseFormReturn<TVariables, TContext> & {\n refineCore: UseFormReturnTypeCore<TData, TError, TVariables>;\n saveButtonProps: {\n disabled: boolean;\n onClick: (e: React.BaseSyntheticEvent) => void;\n };\n};\n\nexport type UseFormProps<\n TData extends BaseRecord = BaseRecord,\n TError extends HttpError = HttpError,\n TVariables extends FieldValues = FieldValues,\n TContext extends object = {},\n> = {\n /**\n * Configuration object for the core of the [useForm](/docs/api-reference/core/hooks/useForm/)\n * @type [`UseFormCoreProps<TData, TError, TVariables>`](/docs/api-reference/core/hooks/useForm/#properties)\n */\n refineCoreProps?: UseFormCoreProps<TData, TError, TVariables>;\n /**\n * When you have unsaved changes and try to leave the current page, **refine** shows a confirmation modal box.\n * @default `false*`\n */\n warnWhenUnsavedChanges?: boolean;\n} & UseHookFormProps<TVariables, TContext>;\n\nexport const useForm = <\n TData extends BaseRecord = BaseRecord,\n TError extends HttpError = HttpError,\n TVariables extends FieldValues = FieldValues,\n TContext extends object = {},\n>({\n refineCoreProps,\n warnWhenUnsavedChanges: warnWhenUnsavedChangesProp,\n ...rest\n}: UseFormProps<TData, TError, TVariables, TContext> = {}): UseFormReturnType<\n TData,\n TError,\n TVariables,\n TContext\n> => {\n const {\n warnWhenUnsavedChanges: warnWhenUnsavedChangesRefine,\n setWarnWhen,\n } = useWarnAboutChange();\n const warnWhenUnsavedChanges =\n warnWhenUnsavedChangesProp ?? warnWhenUnsavedChangesRefine;\n\n const useFormCoreResult = useFormCore<TData, TError, TVariables>({\n ...refineCoreProps,\n });\n\n const { queryResult, onFinish, formLoading } = useFormCoreResult;\n\n const useHookFormResult = useHookForm<TVariables, TContext>({\n ...rest,\n });\n\n const {\n watch,\n reset,\n getValues,\n handleSubmit: handleSubmitReactHookForm,\n } = useHookFormResult;\n\n useEffect(() => {\n if (typeof queryResult?.data !== \"undefined\") {\n const fields: any = {};\n const registeredFields = Object.keys(getValues());\n Object.entries(queryResult?.data?.data || {}).forEach(\n ([key, value]) => {\n if (registeredFields.includes(key)) {\n fields[key] = value;\n }\n },\n );\n\n reset(fields as any);\n }\n }, [queryResult?.data]);\n\n useEffect(() => {\n const subscription = watch((values: any, { type }: { type?: any }) => {\n if (type === \"change\") {\n onValuesChange(values);\n }\n });\n return () => subscription.unsubscribe();\n }, [watch]);\n\n const onValuesChange = (changeValues: Record<string, any>) => {\n if (warnWhenUnsavedChanges) {\n setWarnWhen(true);\n }\n return changeValues;\n };\n\n const handleSubmit: UseFormHandleSubmit<TVariables> =\n (onValid, onInvalid) => async (e) => {\n setWarnWhen(false);\n return await handleSubmitReactHookForm(onValid, onInvalid)(e);\n };\n\n const saveButtonProps = {\n disabled: formLoading,\n onClick: (e: React.BaseSyntheticEvent) => {\n handleSubmit(onFinish, () => false)(e);\n },\n };\n\n return {\n ...useHookFormResult,\n handleSubmit,\n refineCore: useFormCoreResult,\n saveButtonProps,\n };\n};\n","import { useEffect, useState } from \"react\";\nimport { FieldValues } from \"react-hook-form\";\nimport { BaseRecord, HttpError } from \"@refinedev/core\";\n\nimport { useForm, UseFormProps, UseFormReturnType } from \"../useForm\";\n\nexport type UseStepsFormReturnType<\n TData extends BaseRecord = BaseRecord,\n TError extends HttpError = HttpError,\n TVariables extends FieldValues = FieldValues,\n TContext extends object = {},\n> = UseFormReturnType<TData, TError, TVariables, TContext> & {\n steps: {\n currentStep: number;\n gotoStep: (step: number) => void;\n };\n};\n\nexport type UseStepsFormProps<\n TData extends BaseRecord = BaseRecord,\n TError extends HttpError = HttpError,\n TVariables extends FieldValues = FieldValues,\n TContext extends object = {},\n> = UseFormProps<TData, TError, TVariables, TContext> & {\n /**\n * @description Configuration object for the steps.\n * `defaultStep`: Allows you to set the initial step.\n * \n * `isBackValidate`: Whether to validation the current step when going back.\n * @type `{\n defaultStep?: number;\n isBackValidate?: boolean;\n }`\n * @default `defaultStep = 0` `isBackValidate = false`\n */\n stepsProps?: {\n defaultStep?: number;\n isBackValidate?: boolean;\n };\n};\n\nexport const useStepsForm = <\n TData extends BaseRecord = BaseRecord,\n TError extends HttpError = HttpError,\n TVariables extends FieldValues = FieldValues,\n TContext extends object = {},\n>({\n stepsProps,\n ...rest\n}: UseStepsFormProps<\n TData,\n TError,\n TVariables,\n TContext\n> = {}): UseStepsFormReturnType<TData, TError, TVariables, TContext> => {\n const { defaultStep = 0, isBackValidate = false } = stepsProps ?? {};\n const [current, setCurrent] = useState(defaultStep);\n\n const useHookFormResult = useForm({\n ...rest,\n });\n const {\n trigger,\n getValues,\n reset,\n formState: { dirtyFields },\n refineCore: { queryResult },\n } = useHookFormResult;\n\n useEffect(() => {\n if (queryResult?.data) {\n const fields: any = {};\n const registeredFields = Object.keys(getValues());\n Object.entries(queryResult?.data?.data).forEach(([key, value]) => {\n if (registeredFields.includes(key)) {\n if (dirtyFields[key]) {\n fields[key] = getValues(key as any);\n } else {\n fields[key] = value;\n }\n }\n });\n\n reset(fields as any, {\n keepDirty: true,\n keepValues: true,\n });\n }\n }, [queryResult?.data, current]);\n\n const go = (step: number) => {\n let targetStep = step;\n\n if (step < 0) {\n targetStep = 0;\n }\n\n setCurrent(targetStep);\n };\n\n const gotoStep = async (step: number) => {\n if (step === current) {\n return;\n }\n\n if (step < current && !isBackValidate) {\n go(step);\n return;\n }\n\n const isValid = await trigger();\n if (isValid) {\n go(step);\n }\n };\n\n return {\n ...useHookFormResult,\n steps: {\n currentStep: current,\n gotoStep,\n },\n };\n};\n","import { useCallback } from \"react\";\nimport {\n BaseKey,\n BaseRecord,\n FormWithSyncWithLocationParams,\n HttpError,\n useGo,\n useModal,\n useParsed,\n useResource,\n userFriendlyResourceName,\n useTranslate,\n useWarnAboutChange,\n} from \"@refinedev/core\";\nimport { FieldValues } from \"react-hook-form\";\n\nimport { useForm, UseFormProps, UseFormReturnType } from \"../useForm\";\nimport React from \"react\";\n\nexport type UseModalFormReturnType<\n TData extends BaseRecord = BaseRecord,\n TError extends HttpError = HttpError,\n TVariables extends FieldValues = FieldValues,\n TContext extends object = {},\n> = UseFormReturnType<TData, TError, TVariables, TContext> & {\n modal: {\n submit: (values: TVariables) => void;\n close: () => void;\n show: (id?: BaseKey) => void;\n visible: boolean;\n title: string;\n };\n};\n\nexport type UseModalFormProps<\n TData extends BaseRecord = BaseRecord,\n TError extends HttpError = HttpError,\n TVariables extends FieldValues = FieldValues,\n TContext extends object = {},\n> = UseFormProps<TData, TError, TVariables, TContext> & {\n /**\n * @description Configuration object for the modal.\n * `defaultVisible`: Initial visibility state of the modal.\n * \n * `autoSubmitClose`: Whether the form should be submitted when the modal is closed.\n * \n * `autoResetForm`: Whether the form should be reset when the form is submitted.\n * @type `{\n defaultVisible?: boolean;\n autoSubmitClose?: boolean;\n autoResetForm?: boolean;\n }`\n * @default `defaultVisible = false` `autoSubmitClose = true` `autoResetForm = true`\n */\n modalProps?: {\n defaultVisible?: boolean;\n autoSubmitClose?: boolean;\n autoResetForm?: boolean;\n };\n} & FormWithSyncWithLocationParams;\n\nexport const useModalForm = <\n TData extends BaseRecord = BaseRecord,\n TError extends HttpError = HttpError,\n TVariables extends FieldValues = FieldValues,\n TContext extends object = {},\n>({\n modalProps,\n refineCoreProps,\n syncWithLocation,\n ...rest\n}: UseModalFormProps<\n TData,\n TError,\n TVariables,\n TContext\n> = {}): UseModalFormReturnType<TData, TError, TVariables, TContext> => {\n const initiallySynced = React.useRef(false);\n\n const translate = useTranslate();\n\n const { resource: resourceProp, action: actionProp } =\n refineCoreProps ?? {};\n\n const { resource, action: actionFromParams } = useResource(resourceProp);\n\n const parsed = useParsed();\n const go = useGo();\n\n const action = actionProp ?? actionFromParams ?? \"\";\n\n const syncingId =\n typeof syncWithLocation === \"object\" && syncWithLocation.syncId;\n\n const syncWithLocationKey =\n typeof syncWithLocation === \"object\" && \"key\" in syncWithLocation\n ? syncWithLocation.key\n : resource && action && syncWithLocation\n ? `modal-${resource?.identifier ?? resource?.name}-${action}`\n : undefined;\n\n const {\n defaultVisible = false,\n autoSubmitClose = true,\n autoResetForm = true,\n } = modalProps ?? {};\n\n const useHookFormResult = useForm<TData, TError, TVariables, TContext>({\n refineCoreProps,\n ...rest,\n });\n\n const {\n reset,\n refineCore: { onFinish, id, setId },\n saveButtonProps,\n handleSubmit,\n } = useHookFormResult;\n\n const { visible, show, close } = useModal({\n defaultVisible,\n });\n\n React.useEffect(() => {\n if (initiallySynced.current === false && syncWithLocationKey) {\n const openStatus = parsed?.params?.[syncWithLocationKey]?.open;\n if (typeof openStatus === \"boolean\") {\n if (openStatus) {\n show();\n }\n } else if (typeof openStatus === \"string\") {\n if (openStatus === \"true\") {\n show();\n }\n }\n\n if (syncingId) {\n const idFromParams = parsed?.params?.[syncWithLocationKey]?.id;\n if (idFromParams) {\n setId?.(idFromParams);\n }\n }\n\n initiallySynced.current = true;\n }\n }, [syncWithLocationKey, parsed, syncingId, setId]);\n\n React.useEffect(() => {\n if (initiallySynced.current === true) {\n if (visible && syncWithLocationKey) {\n go({\n query: {\n [syncWithLocationKey]: {\n ...parsed?.params?.[syncWithLocationKey],\n open: true,\n ...(syncingId && id && { id }),\n },\n },\n options: { keepQuery: true },\n type: \"replace\",\n });\n } else if (syncWithLocationKey && !visible) {\n go({\n query: {\n [syncWithLocationKey]: undefined,\n },\n options: { keepQuery: true },\n type: \"replace\",\n });\n }\n }\n }, [id, visible, show, syncWithLocationKey, syncingId]);\n\n const submit = async (values: TVariables) => {\n await onFinish(values);\n\n if (autoSubmitClose) {\n close();\n }\n\n if (autoResetForm) {\n reset();\n }\n };\n\n const { warnWhen, setWarnWhen } = useWarnAboutChange();\n const handleClose = useCallback(() => {\n if (warnWhen) {\n const warnWhenConfirm = window.confirm(\n translate(\n \"warnWhenUnsavedChanges\",\n \"Are you sure you want to leave? You have unsaved changes.\",\n ),\n );\n\n if (warnWhenConfirm) {\n setWarnWhen(false);\n } else {\n return;\n }\n }\n\n setId?.(undefined);\n close();\n }, [warnWhen]);\n\n const handleShow = useCallback((id?: BaseKey) => {\n setId?.(id);\n\n show();\n }, []);\n\n const title = translate(\n `${resource?.name}.titles.${actionProp}`,\n undefined,\n `${userFriendlyResourceName(\n `${actionProp} ${\n resource?.meta?.label ??\n resource?.options?.label ??\n resource?.label ??\n resource?.name\n }`,\n \"singular\",\n )}`,\n );\n\n return {\n modal: {\n submit,\n close: handleClose,\n show: handleShow,\n visible,\n title,\n },\n ...useHookFormResult,\n saveButtonProps: {\n ...saveButtonProps,\n onClick: (e) => handleSubmit(submit)(e),\n },\n };\n};\n"],"mappings":"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","names":["src_exports","__export","useForm","useModalForm","useStepsForm","__toCommonJS","import_react","import_react_hook_form","import_core","useForm","refineCoreProps","warnWhenUnsavedChangesProp","rest","warnWhenUnsavedChangesRefine","setWarnWhen","warnWhenUnsavedChanges","useFormCoreResult","useFormCore","queryResult","onFinish","formLoading","useHookFormResult","useHookForm","watch","reset","getValues","handleSubmitReactHookForm","_a","fields","registeredFields","key","value","subscription","values","type","onValuesChange","changeValues","handleSubmit","onValid","onInvalid","e","import_react","useStepsForm","stepsProps","rest","defaultStep","isBackValidate","current","setCurrent","useHookFormResult","useForm","trigger","getValues","reset","dirtyFields","queryResult","_a","fields","registeredFields","key","value","go","step","targetStep","import_react","import_core","import_react","useModalForm","modalProps","refineCoreProps","syncWithLocation","rest","_a","_b","_c","_d","_e","_f","_g","initiallySynced","React","translate","resourceProp","actionProp","resource","actionFromParams","parsed","go","action","syncingId","syncWithLocationKey","defaultVisible","autoSubmitClose","autoResetForm","useHookFormResult","useForm","reset","onFinish","id","setId","saveButtonProps","handleSubmit","visible","show","close","openStatus","idFromParams","submit","values","warnWhen","setWarnWhen","handleClose","handleShow","title","e"]}
@@ -0,0 +1,24 @@
1
+ import React from "react";
2
+ import { UseFormProps as UseHookFormProps, UseFormReturn, FieldValues } from "react-hook-form";
3
+ import { BaseRecord, HttpError, UseFormProps as UseFormCoreProps, UseFormReturnType as UseFormReturnTypeCore } from "@refinedev/core";
4
+ export declare type UseFormReturnType<TData extends BaseRecord = BaseRecord, TError extends HttpError = HttpError, TVariables extends FieldValues = FieldValues, TContext extends object = {}> = UseFormReturn<TVariables, TContext> & {
5
+ refineCore: UseFormReturnTypeCore<TData, TError, TVariables>;
6
+ saveButtonProps: {
7
+ disabled: boolean;
8
+ onClick: (e: React.BaseSyntheticEvent) => void;
9
+ };
10
+ };
11
+ export declare type UseFormProps<TData extends BaseRecord = BaseRecord, TError extends HttpError = HttpError, TVariables extends FieldValues = FieldValues, TContext extends object = {}> = {
12
+ /**
13
+ * Configuration object for the core of the [useForm](/docs/api-reference/core/hooks/useForm/)
14
+ * @type [`UseFormCoreProps<TData, TError, TVariables>`](/docs/api-reference/core/hooks/useForm/#properties)
15
+ */
16
+ refineCoreProps?: UseFormCoreProps<TData, TError, TVariables>;
17
+ /**
18
+ * When you have unsaved changes and try to leave the current page, **refine** shows a confirmation modal box.
19
+ * @default `false*`
20
+ */
21
+ warnWhenUnsavedChanges?: boolean;
22
+ } & UseHookFormProps<TVariables, TContext>;
23
+ export declare const useForm: <TData extends BaseRecord = BaseRecord, TError extends HttpError = HttpError, TVariables extends FieldValues = FieldValues, TContext extends object = {}>({ refineCoreProps, warnWhenUnsavedChanges: warnWhenUnsavedChangesProp, ...rest }?: UseFormProps<TData, TError, TVariables, TContext>) => UseFormReturnType<TData, TError, TVariables, TContext>;
24
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/useForm/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAoB,MAAM,OAAO,CAAC;AACzC,OAAO,EAEH,YAAY,IAAI,gBAAgB,EAChC,aAAa,EACb,WAAW,EAId,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACH,UAAU,EACV,SAAS,EAGT,YAAY,IAAI,gBAAgB,EAChC,iBAAiB,IAAI,qBAAqB,EAC7C,MAAM,iBAAiB,CAAC;AAEzB,oBAAY,iBAAiB,CACzB,KAAK,SAAS,UAAU,GAAG,UAAU,EACrC,MAAM,SAAS,SAAS,GAAG,SAAS,EACpC,UAAU,SAAS,WAAW,GAAG,WAAW,EAC5C,QAAQ,SAAS,MAAM,GAAG,EAAE,IAC5B,aAAa,CAAC,UAAU,EAAE,QAAQ,CAAC,GAAG;IACtC,UAAU,EAAE,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC;IAC7D,eAAe,EAAE;QACb,QAAQ,EAAE,OAAO,CAAC;QAClB,OAAO,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,kBAAkB,KAAK,IAAI,CAAC;KAClD,CAAC;CACL,CAAC;AAEF,oBAAY,YAAY,CACpB,KAAK,SAAS,UAAU,GAAG,UAAU,EACrC,MAAM,SAAS,SAAS,GAAG,SAAS,EACpC,UAAU,SAAS,WAAW,GAAG,WAAW,EAC5C,QAAQ,SAAS,MAAM,GAAG,EAAE,IAC5B;IACA;;;OAGG;IACH,eAAe,CAAC,EAAE,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC;IAC9D;;;OAGG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;CACpC,GAAG,gBAAgB,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;AAE3C,eAAO,MAAM,OAAO,2VA0FnB,CAAC"}
@@ -0,0 +1,35 @@
1
+ import { BaseKey, BaseRecord, FormWithSyncWithLocationParams, HttpError } from "@refinedev/core";
2
+ import { FieldValues } from "react-hook-form";
3
+ import { UseFormProps, UseFormReturnType } from "../useForm";
4
+ export declare type UseModalFormReturnType<TData extends BaseRecord = BaseRecord, TError extends HttpError = HttpError, TVariables extends FieldValues = FieldValues, TContext extends object = {}> = UseFormReturnType<TData, TError, TVariables, TContext> & {
5
+ modal: {
6
+ submit: (values: TVariables) => void;
7
+ close: () => void;
8
+ show: (id?: BaseKey) => void;
9
+ visible: boolean;
10
+ title: string;
11
+ };
12
+ };
13
+ export declare type UseModalFormProps<TData extends BaseRecord = BaseRecord, TError extends HttpError = HttpError, TVariables extends FieldValues = FieldValues, TContext extends object = {}> = UseFormProps<TData, TError, TVariables, TContext> & {
14
+ /**
15
+ * @description Configuration object for the modal.
16
+ * `defaultVisible`: Initial visibility state of the modal.
17
+ *
18
+ * `autoSubmitClose`: Whether the form should be submitted when the modal is closed.
19
+ *
20
+ * `autoResetForm`: Whether the form should be reset when the form is submitted.
21
+ * @type `{
22
+ defaultVisible?: boolean;
23
+ autoSubmitClose?: boolean;
24
+ autoResetForm?: boolean;
25
+ }`
26
+ * @default `defaultVisible = false` `autoSubmitClose = true` `autoResetForm = true`
27
+ */
28
+ modalProps?: {
29
+ defaultVisible?: boolean;
30
+ autoSubmitClose?: boolean;
31
+ autoResetForm?: boolean;
32
+ };
33
+ } & FormWithSyncWithLocationParams;
34
+ export declare const useModalForm: <TData extends BaseRecord = BaseRecord, TError extends HttpError = HttpError, TVariables extends FieldValues = FieldValues, TContext extends object = {}>({ modalProps, refineCoreProps, syncWithLocation, ...rest }?: UseModalFormProps<TData, TError, TVariables, TContext>) => UseModalFormReturnType<TData, TError, TVariables, TContext>;
35
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/useModalForm/index.ts"],"names":[],"mappings":"AACA,OAAO,EACH,OAAO,EACP,UAAU,EACV,8BAA8B,EAC9B,SAAS,EAQZ,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE9C,OAAO,EAAW,YAAY,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAGtE,oBAAY,sBAAsB,CAC9B,KAAK,SAAS,UAAU,GAAG,UAAU,EACrC,MAAM,SAAS,SAAS,GAAG,SAAS,EACpC,UAAU,SAAS,WAAW,GAAG,WAAW,EAC5C,QAAQ,SAAS,MAAM,GAAG,EAAE,IAC5B,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,CAAC,GAAG;IACzD,KAAK,EAAE;QACH,MAAM,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;QACrC,KAAK,EAAE,MAAM,IAAI,CAAC;QAClB,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;QAC7B,OAAO,EAAE,OAAO,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;KACjB,CAAC;CACL,CAAC;AAEF,oBAAY,iBAAiB,CACzB,KAAK,SAAS,UAAU,GAAG,UAAU,EACrC,MAAM,SAAS,SAAS,GAAG,SAAS,EACpC,UAAU,SAAS,WAAW,GAAG,WAAW,EAC5C,QAAQ,SAAS,MAAM,GAAG,EAAE,IAC5B,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,CAAC,GAAG;IACpD;;;;;;;;;;;;;OAaG;IACH,UAAU,CAAC,EAAE;QACT,cAAc,CAAC,EAAE,OAAO,CAAC;QACzB,eAAe,CAAC,EAAE,OAAO,CAAC;QAC1B,aAAa,CAAC,EAAE,OAAO,CAAC;KAC3B,CAAC;CACL,GAAG,8BAA8B,CAAC;AAEnC,eAAO,MAAM,YAAY,+UAmLxB,CAAC"}
@@ -0,0 +1,28 @@
1
+ import { FieldValues } from "react-hook-form";
2
+ import { BaseRecord, HttpError } from "@refinedev/core";
3
+ import { UseFormProps, UseFormReturnType } from "../useForm";
4
+ export declare type UseStepsFormReturnType<TData extends BaseRecord = BaseRecord, TError extends HttpError = HttpError, TVariables extends FieldValues = FieldValues, TContext extends object = {}> = UseFormReturnType<TData, TError, TVariables, TContext> & {
5
+ steps: {
6
+ currentStep: number;
7
+ gotoStep: (step: number) => void;
8
+ };
9
+ };
10
+ export declare type UseStepsFormProps<TData extends BaseRecord = BaseRecord, TError extends HttpError = HttpError, TVariables extends FieldValues = FieldValues, TContext extends object = {}> = UseFormProps<TData, TError, TVariables, TContext> & {
11
+ /**
12
+ * @description Configuration object for the steps.
13
+ * `defaultStep`: Allows you to set the initial step.
14
+ *
15
+ * `isBackValidate`: Whether to validation the current step when going back.
16
+ * @type `{
17
+ defaultStep?: number;
18
+ isBackValidate?: boolean;
19
+ }`
20
+ * @default `defaultStep = 0` `isBackValidate = false`
21
+ */
22
+ stepsProps?: {
23
+ defaultStep?: number;
24
+ isBackValidate?: boolean;
25
+ };
26
+ };
27
+ export declare const useStepsForm: <TData extends BaseRecord = BaseRecord, TError extends HttpError = HttpError, TVariables extends FieldValues = FieldValues, TContext extends object = {}>({ stepsProps, ...rest }?: UseStepsFormProps<TData, TError, TVariables, TContext>) => UseStepsFormReturnType<TData, TError, TVariables, TContext>;
28
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/useStepsForm/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAExD,OAAO,EAAW,YAAY,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEtE,oBAAY,sBAAsB,CAC9B,KAAK,SAAS,UAAU,GAAG,UAAU,EACrC,MAAM,SAAS,SAAS,GAAG,SAAS,EACpC,UAAU,SAAS,WAAW,GAAG,WAAW,EAC5C,QAAQ,SAAS,MAAM,GAAG,EAAE,IAC5B,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,CAAC,GAAG;IACzD,KAAK,EAAE;QACH,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;KACpC,CAAC;CACL,CAAC;AAEF,oBAAY,iBAAiB,CACzB,KAAK,SAAS,UAAU,GAAG,UAAU,EACrC,MAAM,SAAS,SAAS,GAAG,SAAS,EACpC,UAAU,SAAS,WAAW,GAAG,WAAW,EAC5C,QAAQ,SAAS,MAAM,GAAG,EAAE,IAC5B,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,CAAC,GAAG;IACpD;;;;;;;;;;OAUG;IACH,UAAU,CAAC,EAAE;QACT,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,cAAc,CAAC,EAAE,OAAO,CAAC;KAC5B,CAAC;CACL,CAAC;AAEF,eAAO,MAAM,YAAY,4SAkFxB,CAAC"}
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "version": "4.0.0",
3
+ "license": "MIT",
4
+ "main": "dist/index.js",
5
+ "typings": "dist/index.d.ts",
6
+ "private": false,
7
+ "files": [
8
+ "dist",
9
+ "src"
10
+ ],
11
+ "engines": {
12
+ "node": ">=10"
13
+ },
14
+ "scripts": {
15
+ "start": "tsup --watch --format esm,cjs,iife --legacy-output",
16
+ "build": "tsup --format esm,cjs,iife --minify --legacy-output",
17
+ "test": "jest --passWithNoTests --runInBand",
18
+ "prepare": "npm run build"
19
+ },
20
+ "name": "@refinedev/react-hook-form",
21
+ "description": "refine offers a React Hook Form adapter that allows you to use the React Hook Form library with refine.",
22
+ "author": "refine",
23
+ "module": "dist/esm/index.js",
24
+ "peerDependencies": {
25
+ "@refinedev/core": "^4.0.0",
26
+ "react-hook-form": "^7.30.0",
27
+ "react": "^17.0.0 || ^18.0.0",
28
+ "react-dom": "^17.0.0 || ^18.0.0",
29
+ "@types/react": "^17.0.0 || ^18.0.0",
30
+ "@types/react-dom": "^17.0.0 || ^18.0.0"
31
+ },
32
+ "devDependencies": {
33
+ "@refinedev/core": "^4.0.0",
34
+ "@esbuild-plugins/node-resolve": "^0.1.4",
35
+ "@types/jest": "^29.2.4",
36
+ "jest": "^29.3.1",
37
+ "jest-environment-jsdom": "^29.3.1",
38
+ "react-router-dom": "^6.8.1",
39
+ "ts-jest": "^29.0.3",
40
+ "tslib": "^2.3.1",
41
+ "tsup": "^5.11.13"
42
+ },
43
+ "dependencies": {
44
+ "react-hook-form": "^7.30.0"
45
+ },
46
+ "repository": {
47
+ "type": "git",
48
+ "url": "https://github.com/refinedev/refine.git",
49
+ "directory": "packages/react-hook-form"
50
+ },
51
+ "gitHead": "829f5a516f98c06f666d6be3e6e6099c75c07719",
52
+ "publishConfig": {
53
+ "access": "public"
54
+ }
55
+ }
package/src/index.ts ADDED
@@ -0,0 +1,11 @@
1
+ export { useForm, UseFormProps, UseFormReturnType } from "./useForm";
2
+ export {
3
+ useStepsForm,
4
+ UseStepsFormProps,
5
+ UseStepsFormReturnType,
6
+ } from "./useStepsForm";
7
+ export {
8
+ useModalForm,
9
+ UseModalFormProps,
10
+ UseModalFormReturnType,
11
+ } from "./useModalForm";
@@ -0,0 +1,141 @@
1
+ import React, { useEffect } from "react";
2
+ import {
3
+ useForm as useHookForm,
4
+ UseFormProps as UseHookFormProps,
5
+ UseFormReturn,
6
+ FieldValues,
7
+ UseFormHandleSubmit,
8
+ SubmitHandler,
9
+ SubmitErrorHandler,
10
+ } from "react-hook-form";
11
+ import {
12
+ BaseRecord,
13
+ HttpError,
14
+ useForm as useFormCore,
15
+ useWarnAboutChange,
16
+ UseFormProps as UseFormCoreProps,
17
+ UseFormReturnType as UseFormReturnTypeCore,
18
+ } from "@refinedev/core";
19
+
20
+ export type UseFormReturnType<
21
+ TData extends BaseRecord = BaseRecord,
22
+ TError extends HttpError = HttpError,
23
+ TVariables extends FieldValues = FieldValues,
24
+ TContext extends object = {},
25
+ > = UseFormReturn<TVariables, TContext> & {
26
+ refineCore: UseFormReturnTypeCore<TData, TError, TVariables>;
27
+ saveButtonProps: {
28
+ disabled: boolean;
29
+ onClick: (e: React.BaseSyntheticEvent) => void;
30
+ };
31
+ };
32
+
33
+ export type UseFormProps<
34
+ TData extends BaseRecord = BaseRecord,
35
+ TError extends HttpError = HttpError,
36
+ TVariables extends FieldValues = FieldValues,
37
+ TContext extends object = {},
38
+ > = {
39
+ /**
40
+ * Configuration object for the core of the [useForm](/docs/api-reference/core/hooks/useForm/)
41
+ * @type [`UseFormCoreProps<TData, TError, TVariables>`](/docs/api-reference/core/hooks/useForm/#properties)
42
+ */
43
+ refineCoreProps?: UseFormCoreProps<TData, TError, TVariables>;
44
+ /**
45
+ * When you have unsaved changes and try to leave the current page, **refine** shows a confirmation modal box.
46
+ * @default `false*`
47
+ */
48
+ warnWhenUnsavedChanges?: boolean;
49
+ } & UseHookFormProps<TVariables, TContext>;
50
+
51
+ export const useForm = <
52
+ TData extends BaseRecord = BaseRecord,
53
+ TError extends HttpError = HttpError,
54
+ TVariables extends FieldValues = FieldValues,
55
+ TContext extends object = {},
56
+ >({
57
+ refineCoreProps,
58
+ warnWhenUnsavedChanges: warnWhenUnsavedChangesProp,
59
+ ...rest
60
+ }: UseFormProps<TData, TError, TVariables, TContext> = {}): UseFormReturnType<
61
+ TData,
62
+ TError,
63
+ TVariables,
64
+ TContext
65
+ > => {
66
+ const {
67
+ warnWhenUnsavedChanges: warnWhenUnsavedChangesRefine,
68
+ setWarnWhen,
69
+ } = useWarnAboutChange();
70
+ const warnWhenUnsavedChanges =
71
+ warnWhenUnsavedChangesProp ?? warnWhenUnsavedChangesRefine;
72
+
73
+ const useFormCoreResult = useFormCore<TData, TError, TVariables>({
74
+ ...refineCoreProps,
75
+ });
76
+
77
+ const { queryResult, onFinish, formLoading } = useFormCoreResult;
78
+
79
+ const useHookFormResult = useHookForm<TVariables, TContext>({
80
+ ...rest,
81
+ });
82
+
83
+ const {
84
+ watch,
85
+ reset,
86
+ getValues,
87
+ handleSubmit: handleSubmitReactHookForm,
88
+ } = useHookFormResult;
89
+
90
+ useEffect(() => {
91
+ if (typeof queryResult?.data !== "undefined") {
92
+ const fields: any = {};
93
+ const registeredFields = Object.keys(getValues());
94
+ Object.entries(queryResult?.data?.data || {}).forEach(
95
+ ([key, value]) => {
96
+ if (registeredFields.includes(key)) {
97
+ fields[key] = value;
98
+ }
99
+ },
100
+ );
101
+
102
+ reset(fields as any);
103
+ }
104
+ }, [queryResult?.data]);
105
+
106
+ useEffect(() => {
107
+ const subscription = watch((values: any, { type }: { type?: any }) => {
108
+ if (type === "change") {
109
+ onValuesChange(values);
110
+ }
111
+ });
112
+ return () => subscription.unsubscribe();
113
+ }, [watch]);
114
+
115
+ const onValuesChange = (changeValues: Record<string, any>) => {
116
+ if (warnWhenUnsavedChanges) {
117
+ setWarnWhen(true);
118
+ }
119
+ return changeValues;
120
+ };
121
+
122
+ const handleSubmit: UseFormHandleSubmit<TVariables> =
123
+ (onValid, onInvalid) => async (e) => {
124
+ setWarnWhen(false);
125
+ return await handleSubmitReactHookForm(onValid, onInvalid)(e);
126
+ };
127
+
128
+ const saveButtonProps = {
129
+ disabled: formLoading,
130
+ onClick: (e: React.BaseSyntheticEvent) => {
131
+ handleSubmit(onFinish, () => false)(e);
132
+ },
133
+ };
134
+
135
+ return {
136
+ ...useHookFormResult,
137
+ handleSubmit,
138
+ refineCore: useFormCoreResult,
139
+ saveButtonProps,
140
+ };
141
+ };
@@ -0,0 +1,208 @@
1
+ import { renderHook, waitFor } from "@testing-library/react";
2
+
3
+ import { act, TestWrapper } from "../../test";
4
+
5
+ import { useModalForm } from "./";
6
+
7
+ describe("useModalForm Hook", () => {
8
+ it("should return correct initial value of 'visible'", async () => {
9
+ const { result } = renderHook(() => useModalForm(), {
10
+ wrapper: TestWrapper({}),
11
+ });
12
+
13
+ expect(result.current.modal.visible).toBe(false);
14
+ });
15
+
16
+ it("'visible' initial value should be set with 'defaultVisible'", async () => {
17
+ const { result } = renderHook(
18
+ () =>
19
+ useModalForm({
20
+ refineCoreProps: {
21
+ resource: "posts",
22
+ },
23
+ modalProps: {
24
+ defaultVisible: true,
25
+ },
26
+ }),
27
+ {
28
+ wrapper: TestWrapper({}),
29
+ },
30
+ );
31
+
32
+ expect(result.current.modal.visible).toBe(true);
33
+ });
34
+
35
+ it("'visible' value should be false when 'close' is called", async () => {
36
+ const { result } = renderHook(
37
+ () =>
38
+ useModalForm({
39
+ modalProps: {
40
+ defaultVisible: true,
41
+ },
42
+ }),
43
+ {
44
+ wrapper: TestWrapper({}),
45
+ },
46
+ );
47
+
48
+ await act(async () => {
49
+ result.current.modal.close();
50
+ });
51
+
52
+ expect(result.current.modal.visible).toBe(false);
53
+ });
54
+
55
+ it("'visible' value should be true when 'show' is called", async () => {
56
+ const { result } = renderHook(
57
+ () =>
58
+ useModalForm({
59
+ modalProps: {
60
+ defaultVisible: false,
61
+ },
62
+ }),
63
+ {
64
+ wrapper: TestWrapper({}),
65
+ },
66
+ );
67
+
68
+ await act(async () => {
69
+ result.current.modal.show();
70
+ });
71
+
72
+ expect(result.current.modal.visible).toBe(true);
73
+ });
74
+
75
+ it("'id' should be updated when 'show' is called with 'id'", async () => {
76
+ const { result } = renderHook(() => useModalForm(), {
77
+ wrapper: TestWrapper({}),
78
+ });
79
+
80
+ const id = "5";
81
+
82
+ await act(async () => {
83
+ result.current.modal.show(id);
84
+ });
85
+
86
+ expect(result.current.refineCore.id).toBe(id);
87
+ });
88
+
89
+ it("'title' should be set with 'action' and 'resource'", async () => {
90
+ const { result } = renderHook(
91
+ () =>
92
+ useModalForm({
93
+ refineCoreProps: {
94
+ resource: "test",
95
+ action: "edit",
96
+ },
97
+ }),
98
+ {
99
+ wrapper: TestWrapper({}),
100
+ },
101
+ );
102
+
103
+ expect(result.current.modal.title).toBe("Edit test");
104
+ });
105
+
106
+ it("when 'autoSubmitClose' is true, 'close' should be called when 'submit' is called", async () => {
107
+ const { result } = renderHook(
108
+ () =>
109
+ useModalForm({
110
+ refineCoreProps: {
111
+ resource: "posts",
112
+ },
113
+ modalProps: {
114
+ autoSubmitClose: true,
115
+ },
116
+ }),
117
+ {
118
+ wrapper: TestWrapper({}),
119
+ },
120
+ );
121
+
122
+ await act(async () => {
123
+ result.current.modal.close();
124
+ result.current.modal.submit({});
125
+ });
126
+
127
+ expect(result.current.modal.visible).toBe(false);
128
+ });
129
+
130
+ it("when 'autoSubmitClose' is false, 'close' should not be called when 'submit' is called", async () => {
131
+ const { result } = renderHook(
132
+ () =>
133
+ useModalForm({
134
+ refineCoreProps: {
135
+ resource: "posts",
136
+ },
137
+ modalProps: {
138
+ autoSubmitClose: false,
139
+ },
140
+ }),
141
+ {
142
+ wrapper: TestWrapper({}),
143
+ },
144
+ );
145
+
146
+ await act(async () => {
147
+ result.current.modal.show();
148
+ result.current.modal.submit({});
149
+ });
150
+
151
+ expect(result.current.modal.visible).toBe(true);
152
+ });
153
+
154
+ it("autoResetForm is true, 'reset' should be called when 'submit' is called", async () => {
155
+ const { result } = renderHook(
156
+ () =>
157
+ useModalForm({
158
+ refineCoreProps: {
159
+ resource: "posts",
160
+ action: "create",
161
+ },
162
+ modalProps: {
163
+ autoResetForm: true,
164
+ },
165
+ }),
166
+ {
167
+ wrapper: TestWrapper({}),
168
+ },
169
+ );
170
+
171
+ await act(async () => {
172
+ result.current.modal.show();
173
+ result.current.register("test");
174
+ result.current.setValue("test", "test");
175
+ result.current.modal.submit({ test: "test" });
176
+ });
177
+
178
+ await waitFor(() => result.current.refineCore.mutationResult.isSuccess);
179
+
180
+ expect(result.current.getValues()).toStrictEqual({});
181
+ });
182
+
183
+ it("autoResetForm is false, 'reset' should not be called when 'submit' is called", async () => {
184
+ const { result } = renderHook(
185
+ () =>
186
+ useModalForm({
187
+ refineCoreProps: {
188
+ resource: "posts",
189
+ },
190
+ modalProps: {
191
+ autoResetForm: false,
192
+ },
193
+ }),
194
+ {
195
+ wrapper: TestWrapper({}),
196
+ },
197
+ );
198
+
199
+ await act(async () => {
200
+ result.current.modal.show();
201
+ result.current.register("test");
202
+ result.current.setValue("test", "test");
203
+ result.current.modal.submit({ test: "test" });
204
+ });
205
+
206
+ expect(result.current.getValues()).toStrictEqual({ test: "test" });
207
+ });
208
+ });