@refinedev/react-hook-form 4.4.2 → 4.6.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.
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- var se=Object.create;var P=Object.defineProperty;var oe=Object.getOwnPropertyDescriptor;var te=Object.getOwnPropertyNames;var ae=Object.getPrototypeOf,ne=Object.prototype.hasOwnProperty;var Te=(r,s)=>{for(var e in s)P(r,e,{get:s[e],enumerable:!0})},z=(r,s,e,x)=>{if(s&&typeof s=="object"||typeof s=="function")for(let t of te(s))!ne.call(r,t)&&t!==e&&P(r,t,{get:()=>s[t],enumerable:!(x=oe(s,t))||x.enumerable});return r};var de=(r,s,e)=>(e=r!=null?se(ae(r)):{},z(s||!r||!r.__esModule?P(e,"default",{value:r,enumerable:!0}):e,r)),pe=r=>z(P({},"__esModule",{value:!0}),r);var ie={};Te(ie,{useForm:()=>V,useModalForm:()=>X,useStepsForm:()=>J});module.exports=pe(ie);var W=require("react"),I=require("react-hook-form"),Q=require("@refinedev/core"),V=({refineCoreProps:r,warnWhenUnsavedChanges:s,...e}={})=>{let{warnWhenUnsavedChanges:x,setWarnWhen:t}=(0,Q.useWarnAboutChange)(),C=s??x,E=(0,Q.useForm)({...r}),{queryResult:m,onFinish:f,formLoading:T}=E,y=(0,I.useForm)({...e}),{watch:u,setValue:a,getValues:D,handleSubmit:o}=y;(0,W.useEffect)(()=>{var R;let d=(R=m==null?void 0:m.data)==null?void 0:R.data;if(!d)return;let c=Object.keys(D());Object.entries(d).forEach(([v,k])=>{let b=v;c.includes(b)&&a(b,k)})},[m==null?void 0:m.data,a,D]),(0,W.useEffect)(()=>{let d=u((c,{type:R})=>{R==="change"&&l(c)});return()=>d.unsubscribe()},[u]);let l=d=>(C&&t(!0),d),n=(d,c)=>async R=>(t(!1),o(d,c)(R));return{...y,handleSubmit:n,refineCore:E,saveButtonProps:{disabled:T,onClick:d=>{n(f,()=>!1)(d)}}}};var S=require("react");var J=({stepsProps:r,...s}={})=>{let{defaultStep:e=0,isBackValidate:x=!1}=r??{},[t,C]=(0,S.useState)(e),E=V({...s}),{trigger:m,getValues:f,setValue:T,formState:{dirtyFields:y},refineCore:{queryResult:u}}=E;(0,S.useEffect)(()=>{var n;let o=(n=u==null?void 0:u.data)==null?void 0:n.data;if(!o)return;let l=Object.keys(f());Object.entries(o).forEach(([B,d])=>{let c=B;l.includes(c)&&(y[c]||T(c,d))})},[u==null?void 0:u.data,t,T,f]);let a=o=>{let l=o;o<0&&(l=0),C(l)};return{...E,steps:{currentStep:t,gotoStep:async o=>{if(o===t)return;if(o<t&&!x){a(o);return}await m()&&a(o)}}}};var M=require("react"),i=require("@refinedev/core");var g=de(require("react")),X=({modalProps:r,refineCoreProps:s,syncWithLocation:e,...x}={})=>{var A,G;let[t,C]=g.default.useState(!1),E=(0,i.useTranslate)(),{resource:m,action:f}=s??{},{resource:T,action:y,identifier:u}=(0,i.useResource)(m),a=(0,i.useParsed)(),D=(0,i.useGo)(),o=f??y??"",l=!(typeof e=="object"&&(e==null?void 0:e.syncId)===!1),n=typeof e=="object"&&"key"in e?e.key:T&&o&&e?`modal-${u}-${o}`:void 0,{defaultVisible:B=!1,autoSubmitClose:d=!0,autoResetForm:c=!0}=r??{},R=V({refineCoreProps:s,...x}),{reset:v,refineCore:{onFinish:k,id:b,setId:F},saveButtonProps:Z,handleSubmit:_}=R,{visible:U,show:h,close:$}=(0,i.useModal)({defaultVisible:B});g.default.useEffect(()=>{var p,w,j,N;if(t===!1&&n){let H=(w=(p=a==null?void 0:a.params)==null?void 0:p[n])==null?void 0:w.open;if(typeof H=="boolean"?H&&h():typeof H=="string"&&H==="true"&&h(),l){let Y=(N=(j=a==null?void 0:a.params)==null?void 0:j[n])==null?void 0:N.id;Y&&(F==null||F(Y))}C(!0)}},[n,a,l,F]),g.default.useEffect(()=>{var p;t===!0&&(U&&n?D({query:{[n]:{...(p=a==null?void 0:a.params)==null?void 0:p[n],open:!0,...l&&b&&{id:b}}},options:{keepQuery:!0},type:"replace"}):n&&!U&&D({query:{[n]:void 0},options:{keepQuery:!0},type:"replace"}))},[b,U,h,n,l]);let O=async p=>{await k(p),d&&$(),c&&v()},{warnWhen:K,setWarnWhen:q}=(0,i.useWarnAboutChange)(),L=(0,M.useCallback)(()=>{if(K)if(window.confirm(E("warnWhenUnsavedChanges","Are you sure you want to leave? You have unsaved changes.")))q(!1);else return;F==null||F(void 0),$()},[K]),ee=(0,M.useCallback)(p=>{typeof p<"u"&&(F==null||F(p)),(!(o==="edit"||o==="clone")||(typeof p<"u"||typeof b<"u"))&&h()},[b]),re=E(`${u}.titles.${f}`,void 0,`${(0,i.userFriendlyResourceName)(`${f} ${((A=T==null?void 0:T.meta)==null?void 0:A.label)??((G=T==null?void 0:T.options)==null?void 0:G.label)??(T==null?void 0:T.label)??u}`,"singular")}`);return{modal:{submit:O,close:L,show:ee,visible:U,title:re},...R,saveButtonProps:{...Z,onClick:p=>_(O)(p)}}};
1
+ var se=Object.create;var M=Object.defineProperty;var oe=Object.getOwnPropertyDescriptor;var ae=Object.getOwnPropertyNames;var ne=Object.getPrototypeOf,de=Object.prototype.hasOwnProperty;var Te=(e,a)=>{for(var s in a)M(e,s,{get:a[s],enumerable:!0})},_=(e,a,s,y)=>{if(a&&typeof a=="object"||typeof a=="function")for(let n of ae(a))!de.call(e,n)&&n!==s&&M(e,n,{get:()=>a[n],enumerable:!(y=oe(a,n))||y.enumerable});return e};var ie=(e,a,s)=>(s=e!=null?se(ne(e)):{},_(a||!e||!e.__esModule?M(s,"default",{value:e,enumerable:!0}):s,e)),le=e=>_(M({},"__esModule",{value:!0}),e);var ue={};Te(ue,{useForm:()=>Q,useModalForm:()=>ee,useStepsForm:()=>L});module.exports=le(ue);var I=require("react"),q=require("react-hook-form"),f=require("@refinedev/core"),Q=({refineCoreProps:e,warnWhenUnsavedChanges:a,disableServerSideValidation:s=!1,...y}={})=>{let{options:n}=(0,f.useRefineContext)(),g=(n==null?void 0:n.disableServerSideValidation)||s,V=(0,f.useTranslate)(),{warnWhenUnsavedChanges:v,setWarnWhen:R}=(0,f.useWarnAboutChange)(),T=a??v,U=(0,q.useForm)({...y}),{watch:c,setValue:d,getValues:S,handleSubmit:i,setError:F}=U,E=(0,f.useForm)({...e,onMutationError:(r,t,l)=>{var b,x;if(g){(b=e==null?void 0:e.onMutationError)==null||b.call(e,r,t,l);return}let h=r==null?void 0:r.errors;for(let H in h){if(!Object.keys(t).includes(H.split(".")[0]))continue;let m=h[H],B="";Array.isArray(m)&&(B=m.join(" ")),typeof m=="string"&&(B=m),typeof m=="boolean"&&m&&(B="Field is not valid."),typeof m=="object"&&"key"in m&&(B=V(m.key,m.message)),F(H,{message:B})}(x=e==null?void 0:e.onMutationError)==null||x.call(e,r,t,l)}}),{queryResult:o,onFinish:C,formLoading:D,onFinishAutoSave:k}=E;(0,I.useEffect)(()=>{var l;let r=(l=o==null?void 0:o.data)==null?void 0:l.data;if(!r)return;let t=Object.keys(S());Object.entries(r).forEach(([h,b])=>{let x=h;t.includes(x)&&d(x,b)})},[o==null?void 0:o.data,d,S]),(0,I.useEffect)(()=>{let r=c((t,{type:l})=>{l==="change"&&j(t)});return()=>r.unsubscribe()},[c]);let j=r=>{var t;if(T&&R(!0),e!=null&&e.autoSave){R(!1);let l=(t=e.autoSave)==null?void 0:t.onFinish;return k(l?l(r):r)}return r},w=(r,t)=>async l=>(R(!1),i(r,t)(l));return{...U,handleSubmit:w,refineCore:E,saveButtonProps:{disabled:D,onClick:r=>{w(C,()=>!1)(r)}}}};var W=require("react");var L=({stepsProps:e,...a}={})=>{let{defaultStep:s=0,isBackValidate:y=!1}=e??{},[n,g]=(0,W.useState)(s),V=Q({...a}),{trigger:v,getValues:R,setValue:T,formState:{dirtyFields:U},refineCore:{queryResult:c}}=V;(0,W.useEffect)(()=>{var E;let i=(E=c==null?void 0:c.data)==null?void 0:E.data;if(!i)return;let F=Object.keys(R());Object.entries(i).forEach(([o,C])=>{let D=o;F.includes(D)&&(U[D]||T(D,C))})},[c==null?void 0:c.data,n,T,R]);let d=i=>{let F=i;i<0&&(F=0),g(F)};return{...V,steps:{currentStep:n,gotoStep:async i=>{if(i===n)return;if(i<n&&!y){d(i);return}await v()&&d(i)}}}};var N=require("react"),p=require("@refinedev/core");var O=ie(require("react")),ee=({modalProps:e,refineCoreProps:a,syncWithLocation:s,...y}={})=>{var z,J;let[n,g]=O.default.useState(!1),V=(0,p.useTranslate)(),{resource:v,action:R}=a??{},{resource:T,action:U,identifier:c}=(0,p.useResource)(v),d=(0,p.useParsed)(),S=(0,p.useGo)(),i=(0,p.useUserFriendlyName)(),F=R??U??"",E=!(typeof s=="object"&&(s==null?void 0:s.syncId)===!1),o=typeof s=="object"&&"key"in s?s.key:T&&F&&s?`modal-${c}-${F}`:void 0,{defaultVisible:C=!1,autoSubmitClose:D=!0,autoResetForm:k=!0}=e??{},j=Q({refineCoreProps:a,...y}),{reset:w,refineCore:{onFinish:G,id:r,setId:t},saveButtonProps:l,handleSubmit:h}=j,{visible:b,show:x,close:H}=(0,p.useModal)({defaultVisible:C});O.default.useEffect(()=>{var u,A,K,X;if(n===!1&&o){let P=(A=(u=d==null?void 0:d.params)==null?void 0:u[o])==null?void 0:A.open;if(typeof P=="boolean"?P&&x():typeof P=="string"&&P==="true"&&x(),E){let Z=(X=(K=d==null?void 0:d.params)==null?void 0:K[o])==null?void 0:X.id;Z&&(t==null||t(Z))}g(!0)}},[o,d,E,t]),O.default.useEffect(()=>{var u;n===!0&&(b&&o?S({query:{[o]:{...(u=d==null?void 0:d.params)==null?void 0:u[o],open:!0,...E&&r&&{id:r}}},options:{keepQuery:!0},type:"replace"}):o&&!b&&S({query:{[o]:void 0},options:{keepQuery:!0},type:"replace"}))},[r,b,x,o,E]);let $=async u=>{await G(u),D&&H(),k&&w()},{warnWhen:m,setWarnWhen:B}=(0,p.useWarnAboutChange)(),Y=(0,N.useCallback)(()=>{if(m)if(window.confirm(V("warnWhenUnsavedChanges","Are you sure you want to leave? You have unsaved changes.")))B(!1);else return;t==null||t(void 0),H()},[m]),re=(0,N.useCallback)(u=>{typeof u<"u"&&(t==null||t(u)),(!(F==="edit"||F==="clone")||(typeof u<"u"||typeof r<"u"))&&x()},[r]),te=V(`${c}.titles.${R}`,void 0,`${i(`${R} ${((z=T==null?void 0:T.meta)==null?void 0:z.label)??((J=T==null?void 0:T.options)==null?void 0:J.label)??(T==null?void 0:T.label)??c}`,"singular")}`);return{modal:{submit:$,close:Y,show:re,visible:b,title:te},...j,saveButtonProps:{...l,onClick:u=>h($)(u)}}};
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +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 Path,\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 TQueryFnData extends BaseRecord = BaseRecord,\n TError extends HttpError = HttpError,\n TVariables extends FieldValues = FieldValues,\n TContext extends object = {},\n TData extends BaseRecord = TQueryFnData,\n TResponse extends BaseRecord = TData,\n TResponseError extends HttpError = TError,\n> = UseFormReturn<TVariables, TContext> & {\n refineCore: UseFormReturnTypeCore<\n TQueryFnData,\n TError,\n TVariables,\n TData,\n TResponse,\n TResponseError\n >;\n saveButtonProps: {\n disabled: boolean;\n onClick: (e: React.BaseSyntheticEvent) => void;\n };\n};\n\nexport type UseFormProps<\n TQueryFnData extends BaseRecord = BaseRecord,\n TError extends HttpError = HttpError,\n TVariables extends FieldValues = FieldValues,\n TContext extends object = {},\n TData extends BaseRecord = TQueryFnData,\n TResponse extends BaseRecord = TData,\n TResponseError extends HttpError = TError,\n> = {\n /**\n * Configuration object for the core of the [useForm](/docs/api-reference/core/hooks/useForm/)\n * @type [`UseFormCoreProps<TQueryFnData, TError, TVariables, TData, TResponse, TResponseError>`](/docs/api-reference/core/hooks/useForm/#properties)\n */\n refineCoreProps?: UseFormCoreProps<\n TQueryFnData,\n TError,\n TVariables,\n TData,\n TResponse,\n TResponseError\n >;\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 TQueryFnData extends BaseRecord = BaseRecord,\n TError extends HttpError = HttpError,\n TVariables extends FieldValues = FieldValues,\n TContext extends object = {},\n TData extends BaseRecord = TQueryFnData,\n TResponse extends BaseRecord = TData,\n TResponseError extends HttpError = TError,\n>({\n refineCoreProps,\n warnWhenUnsavedChanges: warnWhenUnsavedChangesProp,\n ...rest\n}: UseFormProps<\n TQueryFnData,\n TError,\n TVariables,\n TContext,\n TData,\n TResponse,\n TResponseError\n> = {}): UseFormReturnType<\n TQueryFnData,\n TError,\n TVariables,\n TContext,\n TData,\n TResponse,\n TResponseError\n> => {\n const {\n warnWhenUnsavedChanges: warnWhenUnsavedChangesRefine,\n setWarnWhen,\n } = useWarnAboutChange();\n const warnWhenUnsavedChanges =\n warnWhenUnsavedChangesProp ?? warnWhenUnsavedChangesRefine;\n\n const useFormCoreResult = useFormCore<\n TQueryFnData,\n TError,\n TVariables,\n TData,\n TResponse,\n TResponseError\n >({\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 setValue,\n getValues,\n handleSubmit: handleSubmitReactHookForm,\n } = useHookFormResult;\n\n useEffect(() => {\n const data = queryResult?.data?.data;\n if (!data) return;\n\n const registeredFields = Object.keys(getValues());\n Object.entries(data).forEach(([key, value]) => {\n const name = key as Path<TVariables>;\n\n if (registeredFields.includes(name)) {\n setValue(name, value);\n }\n });\n }, [queryResult?.data, setValue, getValues]);\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 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, Path } from \"react-hook-form\";\nimport { BaseRecord, HttpError } from \"@refinedev/core\";\n\nimport { useForm, UseFormProps, UseFormReturnType } from \"../useForm\";\n\nexport type UseStepsFormReturnType<\n TQueryFnData extends BaseRecord = BaseRecord,\n TError extends HttpError = HttpError,\n TVariables extends FieldValues = FieldValues,\n TContext extends object = {},\n TData extends BaseRecord = TQueryFnData,\n TResponse extends BaseRecord = TData,\n TResponseError extends HttpError = TError,\n> = UseFormReturnType<\n TQueryFnData,\n TError,\n TVariables,\n TContext,\n TData,\n TResponse,\n TResponseError\n> & {\n steps: {\n currentStep: number;\n gotoStep: (step: number) => void;\n };\n};\n\nexport type UseStepsFormProps<\n TQueryFnData extends BaseRecord = BaseRecord,\n TError extends HttpError = HttpError,\n TVariables extends FieldValues = FieldValues,\n TContext extends object = {},\n TData extends BaseRecord = TQueryFnData,\n TResponse extends BaseRecord = TData,\n TResponseError extends HttpError = TError,\n> = UseFormProps<\n TQueryFnData,\n TError,\n TVariables,\n TContext,\n TData,\n TResponse,\n TResponseError\n> & {\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 TQueryFnData extends BaseRecord = BaseRecord,\n TError extends HttpError = HttpError,\n TVariables extends FieldValues = FieldValues,\n TContext extends object = {},\n TData extends BaseRecord = TQueryFnData,\n TResponse extends BaseRecord = TData,\n TResponseError extends HttpError = TError,\n>({\n stepsProps,\n ...rest\n}: UseStepsFormProps<\n TQueryFnData,\n TError,\n TVariables,\n TContext,\n TData,\n TResponse,\n TResponseError\n> = {}): UseStepsFormReturnType<\n TQueryFnData,\n TError,\n TVariables,\n TContext,\n TData,\n TResponse,\n TResponseError\n> => {\n const { defaultStep = 0, isBackValidate = false } = stepsProps ?? {};\n const [current, setCurrent] = useState(defaultStep);\n\n const useHookFormResult = useForm<\n TQueryFnData,\n TError,\n TVariables,\n TContext,\n TData,\n TResponse,\n TResponseError\n >({\n ...rest,\n });\n\n const {\n trigger,\n getValues,\n setValue,\n formState: { dirtyFields },\n refineCore: { queryResult },\n } = useHookFormResult;\n\n useEffect(() => {\n const data = queryResult?.data?.data;\n if (!data) return;\n\n const registeredFields = Object.keys(getValues());\n Object.entries(data).forEach(([key, value]) => {\n const name = key as Path<TVariables>;\n\n if (registeredFields.includes(name)) {\n if (!dirtyFields[name]) {\n setValue(name, value);\n }\n }\n });\n }, [queryResult?.data, current, setValue, getValues]);\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 TQueryFnData extends BaseRecord = BaseRecord,\n TError extends HttpError = HttpError,\n TVariables extends FieldValues = FieldValues,\n TContext extends object = {},\n TData extends BaseRecord = TQueryFnData,\n TResponse extends BaseRecord = TData,\n TResponseError extends HttpError = TError,\n> = UseFormReturnType<\n TQueryFnData,\n TError,\n TVariables,\n TContext,\n TData,\n TResponse,\n TResponseError\n> & {\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 TQueryFnData extends BaseRecord = BaseRecord,\n TError extends HttpError = HttpError,\n TVariables extends FieldValues = FieldValues,\n TContext extends object = {},\n TData extends BaseRecord = TQueryFnData,\n TResponse extends BaseRecord = TData,\n TResponseError extends HttpError = TError,\n> = UseFormProps<\n TQueryFnData,\n TError,\n TVariables,\n TContext,\n TData,\n TResponse,\n TResponseError\n> & {\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 TQueryFnData extends BaseRecord = BaseRecord,\n TError extends HttpError = HttpError,\n TVariables extends FieldValues = FieldValues,\n TContext extends object = {},\n TData extends BaseRecord = TQueryFnData,\n TResponse extends BaseRecord = TData,\n TResponseError extends HttpError = TError,\n>({\n modalProps,\n refineCoreProps,\n syncWithLocation,\n ...rest\n}: UseModalFormProps<\n TQueryFnData,\n TError,\n TVariables,\n TContext,\n TData,\n TResponse,\n TResponseError\n> = {}): UseModalFormReturnType<\n TQueryFnData,\n TError,\n TVariables,\n TContext,\n TData,\n TResponse,\n TResponseError\n> => {\n const [initiallySynced, setInitiallySynced] = React.useState(false);\n\n const translate = useTranslate();\n\n const { resource: resourceProp, action: actionProp } =\n refineCoreProps ?? {};\n\n const {\n resource,\n action: actionFromParams,\n identifier,\n } = 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\" &&\n syncWithLocation?.syncId === false\n );\n\n const syncWithLocationKey =\n typeof syncWithLocation === \"object\" && \"key\" in syncWithLocation\n ? syncWithLocation.key\n : resource && action && syncWithLocation\n ? `modal-${identifier}-${action}`\n : undefined;\n\n const {\n defaultVisible = false,\n autoSubmitClose = true,\n autoResetForm = true,\n } = modalProps ?? {};\n\n const useHookFormResult = useForm<\n TQueryFnData,\n TError,\n TVariables,\n TContext,\n TData,\n TResponse,\n TResponseError\n >({\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 === 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 setInitiallySynced(true);\n }\n }, [syncWithLocationKey, parsed, syncingId, setId]);\n\n React.useEffect(() => {\n if (initiallySynced === 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(\n (showId?: BaseKey) => {\n if (typeof showId !== \"undefined\") {\n setId?.(showId);\n }\n const needsIdToOpen = action === \"edit\" || action === \"clone\";\n const hasId =\n typeof showId !== \"undefined\" || typeof id !== \"undefined\";\n if (needsIdToOpen ? hasId : true) {\n show();\n }\n },\n [id],\n );\n\n const title = translate(\n `${identifier}.titles.${actionProp}`,\n undefined,\n `${userFriendlyResourceName(\n `${actionProp} ${\n resource?.meta?.label ??\n resource?.options?.label ??\n resource?.label ??\n identifier\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":"0jBAAA,IAAAA,GAAA,GAAAC,GAAAD,GAAA,aAAAE,EAAA,iBAAAC,EAAA,iBAAAC,IAAA,eAAAC,GAAAL,ICAA,IAAAM,EAAiC,iBACjCC,EAOO,2BACPC,EAOO,2BAqDMC,EAAU,CAQrB,CACE,gBAAAC,EACA,uBAAwBC,EACxB,GAAGC,CACP,EAQI,CAAC,IAQA,CACD,GAAM,CACF,uBAAwBC,EACxB,YAAAC,CACJ,KAAI,sBAAmB,EACjBC,EACFJ,GAA8BE,EAE5BG,KAAoB,EAAAC,SAOxB,CACE,GAAGP,CACP,CAAC,EAEK,CAAE,YAAAQ,EAAa,SAAAC,EAAU,YAAAC,CAAY,EAAIJ,EAEzCK,KAAoB,EAAAC,SAAkC,CACxD,GAAGV,CACP,CAAC,EAEK,CACF,MAAAW,EACA,SAAAC,EACA,UAAAC,EACA,aAAcC,CAClB,EAAIL,KAEJ,aAAU,IAAM,CAjIpB,IAAAM,EAkIQ,IAAMC,GAAOD,EAAAT,GAAA,YAAAA,EAAa,OAAb,YAAAS,EAAmB,KAChC,GAAI,CAACC,EAAM,OAEX,IAAMC,EAAmB,OAAO,KAAKJ,EAAU,CAAC,EAChD,OAAO,QAAQG,CAAI,EAAE,QAAQ,CAAC,CAACE,EAAKC,CAAK,IAAM,CAC3C,IAAMC,EAAOF,EAETD,EAAiB,SAASG,CAAI,GAC9BR,EAASQ,EAAMD,CAAK,CAE5B,CAAC,CACL,EAAG,CAACb,GAAA,YAAAA,EAAa,KAAMM,EAAUC,CAAS,CAAC,KAE3C,aAAU,IAAM,CACZ,IAAMQ,EAAeV,EAAM,CAACW,EAAa,CAAE,KAAAC,CAAK,IAAsB,CAC9DA,IAAS,UACTC,EAAeF,CAAM,CAE7B,CAAC,EACD,MAAO,IAAMD,EAAa,YAAY,CAC1C,EAAG,CAACV,CAAK,CAAC,EAEV,IAAMa,EAAkBC,IAChBtB,GACAD,EAAY,EAAI,EAEbuB,GAGLC,EACF,CAACC,EAASC,IAAc,MAAOC,IAC3B3B,EAAY,EAAK,EACVY,EAA0Ba,EAASC,CAAS,EAAEC,CAAC,GAU9D,MAAO,CACH,GAAGpB,EACH,aAAAiB,EACA,WAAYtB,EACZ,gBAXoB,CACpB,SAAUI,EACV,QAAUqB,GAAgC,CACtCH,EAAanB,EAAU,IAAM,EAAK,EAAEsB,CAAC,CACzC,CACJ,CAOA,CACJ,EClLA,IAAAC,EAAoC,iBA+D7B,IAAMC,EAAe,CAQ1B,CACE,WAAAC,EACA,GAAGC,CACP,EAQI,CAAC,IAQA,CACD,GAAM,CAAE,YAAAC,EAAc,EAAG,eAAAC,EAAiB,EAAM,EAAIH,GAAc,CAAC,EAC7D,CAACI,EAASC,CAAU,KAAI,YAASH,CAAW,EAE5CI,EAAoBC,EAQxB,CACE,GAAGN,CACP,CAAC,EAEK,CACF,QAAAO,EACA,UAAAC,EACA,SAAAC,EACA,UAAW,CAAE,YAAAC,CAAY,EACzB,WAAY,CAAE,YAAAC,CAAY,CAC9B,EAAIN,KAEJ,aAAU,IAAM,CAlHpB,IAAAO,EAmHQ,IAAMC,GAAOD,EAAAD,GAAA,YAAAA,EAAa,OAAb,YAAAC,EAAmB,KAChC,GAAI,CAACC,EAAM,OAEX,IAAMC,EAAmB,OAAO,KAAKN,EAAU,CAAC,EAChD,OAAO,QAAQK,CAAI,EAAE,QAAQ,CAAC,CAACE,EAAKC,CAAK,IAAM,CAC3C,IAAMC,EAAOF,EAETD,EAAiB,SAASG,CAAI,IACzBP,EAAYO,CAAI,GACjBR,EAASQ,EAAMD,CAAK,EAGhC,CAAC,CACL,EAAG,CAACL,GAAA,YAAAA,EAAa,KAAMR,EAASM,EAAUD,CAAS,CAAC,EAEpD,IAAMU,EAAMC,GAAiB,CACzB,IAAIC,EAAaD,EAEbA,EAAO,IACPC,EAAa,GAGjBhB,EAAWgB,CAAU,CACzB,EAkBA,MAAO,CACH,GAAGf,EACH,MAAO,CACH,YAAaF,EACb,SApBS,MAAOgB,GAAiB,CACrC,GAAIA,IAAShB,EACT,OAGJ,GAAIgB,EAAOhB,GAAW,CAACD,EAAgB,CACnCgB,EAAGC,CAAI,EACP,OAGY,MAAMZ,EAAQ,GAE1BW,EAAGC,CAAI,CAEf,CAOI,CACJ,CACJ,ECnKA,IAAAE,EAA4B,iBAC5BC,EAYO,2BAIP,IAAAC,EAAkB,qBAkELC,EAAe,CAQ1B,CACE,WAAAC,EACA,gBAAAC,EACA,iBAAAC,EACA,GAAGC,CACP,EAQI,CAAC,IAQA,CAhHL,IAAAC,EAAAC,EAiHI,GAAM,CAACC,EAAiBC,CAAkB,EAAI,EAAAC,QAAM,SAAS,EAAK,EAE5DC,KAAY,gBAAa,EAEzB,CAAE,SAAUC,EAAc,OAAQC,CAAW,EAC/CV,GAAmB,CAAC,EAElB,CACF,SAAAW,EACA,OAAQC,EACR,WAAAC,CACJ,KAAI,eAAYJ,CAAY,EAEtBK,KAAS,aAAU,EACnBC,KAAK,SAAM,EAEXC,EAASN,GAAcE,GAAoB,GAE3CK,EAAY,EACd,OAAOhB,GAAqB,WAC5BA,GAAA,YAAAA,EAAkB,UAAW,IAG3BiB,EACF,OAAOjB,GAAqB,UAAY,QAASA,EAC3CA,EAAiB,IACjBU,GAAYK,GAAUf,EACtB,SAASY,KAAcG,IACvB,OAEJ,CACF,eAAAG,EAAiB,GACjB,gBAAAC,EAAkB,GAClB,cAAAC,EAAgB,EACpB,EAAItB,GAAc,CAAC,EAEbuB,EAAoBC,EAQxB,CACE,gBAAAvB,EACA,GAAGE,CACP,CAAC,EAEK,CACF,MAAAsB,EACA,WAAY,CAAE,SAAAC,EAAU,GAAAC,EAAI,MAAAC,CAAM,EAClC,gBAAAC,EACA,aAAAC,CACJ,EAAIP,EAEE,CAAE,QAAAQ,EAAS,KAAAC,EAAM,MAAAC,CAAM,KAAI,YAAS,CACtC,eAAAb,CACJ,CAAC,EAED,EAAAZ,QAAM,UAAU,IAAM,CA7K1B,IAAAJ,EAAAC,EAAA6B,EAAAC,EA8KQ,GAAI7B,IAAoB,IAASa,EAAqB,CAClD,IAAMiB,GAAa/B,GAAAD,EAAAW,GAAA,YAAAA,EAAQ,SAAR,YAAAX,EAAiBe,KAAjB,YAAAd,EAAuC,KAW1D,GAVI,OAAO+B,GAAe,UAClBA,GACAJ,EAAK,EAEF,OAAOI,GAAe,UACzBA,IAAe,QACfJ,EAAK,EAITd,EAAW,CACX,IAAMmB,GAAeF,GAAAD,EAAAnB,GAAA,YAAAA,EAAQ,SAAR,YAAAmB,EAAiBf,KAAjB,YAAAgB,EAAuC,GACxDE,IACAT,GAAA,MAAAA,EAAQS,IAIhB9B,EAAmB,EAAI,EAE/B,EAAG,CAACY,EAAqBJ,EAAQG,EAAWU,CAAK,CAAC,EAElD,EAAApB,QAAM,UAAU,IAAM,CArM1B,IAAAJ,EAsMYE,IAAoB,KAChByB,GAAWZ,EACXH,EAAG,CACC,MAAO,CACH,CAACG,CAAmB,EAAG,CACnB,IAAGf,EAAAW,GAAA,YAAAA,EAAQ,SAAR,YAAAX,EAAiBe,GACpB,KAAM,GACN,GAAID,GAAaS,GAAM,CAAE,GAAAA,CAAG,CAChC,CACJ,EACA,QAAS,CAAE,UAAW,EAAK,EAC3B,KAAM,SACV,CAAC,EACMR,GAAuB,CAACY,GAC/Bf,EAAG,CACC,MAAO,CACH,CAACG,CAAmB,EAAG,MAC3B,EACA,QAAS,CAAE,UAAW,EAAK,EAC3B,KAAM,SACV,CAAC,EAGb,EAAG,CAACQ,EAAII,EAASC,EAAMb,EAAqBD,CAAS,CAAC,EAEtD,IAAMoB,EAAS,MAAOC,GAAuB,CACzC,MAAMb,EAASa,CAAM,EAEjBlB,GACAY,EAAM,EAGNX,GACAG,EAAM,CAEd,EAEM,CAAE,SAAAe,EAAU,YAAAC,CAAY,KAAI,sBAAmB,EAC/CC,KAAc,eAAY,IAAM,CAClC,GAAIF,EAQA,GAPwB,OAAO,QAC3B/B,EACI,yBACA,2DACJ,CACJ,EAGIgC,EAAY,EAAK,MAEjB,QAIRb,GAAA,MAAAA,EAAQ,QACRK,EAAM,CACV,EAAG,CAACO,CAAQ,CAAC,EAEPG,MAAa,eACdC,GAAqB,CACd,OAAOA,EAAW,MAClBhB,GAAA,MAAAA,EAAQgB,KAKR,EAHkB3B,IAAW,QAAUA,IAAW,WAElD,OAAO2B,EAAW,KAAe,OAAOjB,EAAO,OAE/CK,EAAK,CAEb,EACA,CAACL,CAAE,CACP,EAEMkB,GAAQpC,EACV,GAAGK,YAAqBH,IACxB,OACA,MAAG,4BACC,GAAGA,OACCP,EAAAQ,GAAA,YAAAA,EAAU,OAAV,YAAAR,EAAgB,UAChBC,EAAAO,GAAA,YAAAA,EAAU,UAAV,YAAAP,EAAmB,SACnBO,GAAA,YAAAA,EAAU,QACVE,IAEJ,UACJ,GACJ,EAEA,MAAO,CACH,MAAO,CACH,OAAAwB,EACA,MAAOI,EACP,KAAMC,GACN,QAAAZ,EACA,MAAAc,EACJ,EACA,GAAGtB,EACH,gBAAiB,CACb,GAAGM,EACH,QAAUiB,GAAMhB,EAAaQ,CAAM,EAAEQ,CAAC,CAC1C,CACJ,CACJ","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","setValue","getValues","handleSubmitReactHookForm","_a","data","registeredFields","key","value","name","subscription","values","type","onValuesChange","changeValues","handleSubmit","onValid","onInvalid","e","import_react","useStepsForm","stepsProps","rest","defaultStep","isBackValidate","current","setCurrent","useHookFormResult","useForm","trigger","getValues","setValue","dirtyFields","queryResult","_a","data","registeredFields","key","value","name","go","step","targetStep","import_react","import_core","import_react","useModalForm","modalProps","refineCoreProps","syncWithLocation","rest","_a","_b","initiallySynced","setInitiallySynced","React","translate","resourceProp","actionProp","resource","actionFromParams","identifier","parsed","go","action","syncingId","syncWithLocationKey","defaultVisible","autoSubmitClose","autoResetForm","useHookFormResult","useForm","reset","onFinish","id","setId","saveButtonProps","handleSubmit","visible","show","close","_c","_d","openStatus","idFromParams","submit","values","warnWhen","setWarnWhen","handleClose","handleShow","showId","title","e"]}
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 Path,\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 useTranslate,\n useRefineContext,\n} from \"@refinedev/core\";\n\nexport type UseFormReturnType<\n TQueryFnData extends BaseRecord = BaseRecord,\n TError extends HttpError = HttpError,\n TVariables extends FieldValues = FieldValues,\n TContext extends object = {},\n TData extends BaseRecord = TQueryFnData,\n TResponse extends BaseRecord = TData,\n TResponseError extends HttpError = TError,\n> = UseFormReturn<TVariables, TContext> & {\n refineCore: UseFormReturnTypeCore<\n TQueryFnData,\n TError,\n TVariables,\n TData,\n TResponse,\n TResponseError\n >;\n saveButtonProps: {\n disabled: boolean;\n onClick: (e: React.BaseSyntheticEvent) => void;\n };\n};\n\nexport type UseFormProps<\n TQueryFnData extends BaseRecord = BaseRecord,\n TError extends HttpError = HttpError,\n TVariables extends FieldValues = FieldValues,\n TContext extends object = {},\n TData extends BaseRecord = TQueryFnData,\n TResponse extends BaseRecord = TData,\n TResponseError extends HttpError = TError,\n> = {\n /**\n * Configuration object for the core of the [useForm](/docs/api-reference/core/hooks/useForm/)\n * @type [`UseFormCoreProps<TQueryFnData, TError, TVariables, TData, TResponse, TResponseError>`](/docs/api-reference/core/hooks/useForm/#properties)\n */\n refineCoreProps?: UseFormCoreProps<\n TQueryFnData,\n TError,\n TVariables,\n TData,\n TResponse,\n TResponseError\n >;\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 /**\n * Disables server-side validation\n * @default false\n * @see {@link https://refine.dev/docs/advanced-tutorials/forms/server-side-form-validation/}\n */\n disableServerSideValidation?: boolean;\n} & UseHookFormProps<TVariables, TContext>;\n\nexport const useForm = <\n TQueryFnData extends BaseRecord = BaseRecord,\n TError extends HttpError = HttpError,\n TVariables extends FieldValues = FieldValues,\n TContext extends object = {},\n TData extends BaseRecord = TQueryFnData,\n TResponse extends BaseRecord = TData,\n TResponseError extends HttpError = TError,\n>({\n refineCoreProps,\n warnWhenUnsavedChanges: warnWhenUnsavedChangesProp,\n disableServerSideValidation: disableServerSideValidationProp = false,\n ...rest\n}: UseFormProps<\n TQueryFnData,\n TError,\n TVariables,\n TContext,\n TData,\n TResponse,\n TResponseError\n> = {}): UseFormReturnType<\n TQueryFnData,\n TError,\n TVariables,\n TContext,\n TData,\n TResponse,\n TResponseError\n> => {\n const { options } = useRefineContext();\n const disableServerSideValidation =\n options?.disableServerSideValidation || disableServerSideValidationProp;\n\n const translate = useTranslate();\n\n const {\n warnWhenUnsavedChanges: warnWhenUnsavedChangesRefine,\n setWarnWhen,\n } = useWarnAboutChange();\n const warnWhenUnsavedChanges =\n warnWhenUnsavedChangesProp ?? warnWhenUnsavedChangesRefine;\n\n const useHookFormResult = useHookForm<TVariables, TContext>({\n ...rest,\n });\n\n const {\n watch,\n setValue,\n getValues,\n handleSubmit: handleSubmitReactHookForm,\n setError,\n } = useHookFormResult;\n\n const useFormCoreResult = useFormCore<\n TQueryFnData,\n TError,\n TVariables,\n TData,\n TResponse,\n TResponseError\n >({\n ...refineCoreProps,\n onMutationError: (error, _variables, _context) => {\n if (disableServerSideValidation) {\n refineCoreProps?.onMutationError?.(error, _variables, _context);\n return;\n }\n\n const errors = error?.errors;\n\n for (const key in errors) {\n // when the key is not registered in the form, react-hook-form not working\n const isKeyInVariables = Object.keys(_variables).includes(\n key.split(\".\")[0],\n );\n if (!isKeyInVariables) {\n continue;\n }\n\n const fieldError = errors[key];\n\n let newError = \"\";\n\n if (Array.isArray(fieldError)) {\n newError = fieldError.join(\" \");\n }\n\n if (typeof fieldError === \"string\") {\n newError = fieldError;\n }\n\n if (typeof fieldError === \"boolean\" && fieldError) {\n newError = \"Field is not valid.\";\n }\n\n if (typeof fieldError === \"object\" && \"key\" in fieldError) {\n const translatedMessage = translate(\n fieldError.key,\n fieldError.message,\n );\n\n newError = translatedMessage;\n }\n\n setError(key as Path<TVariables>, {\n message: newError,\n });\n }\n\n refineCoreProps?.onMutationError?.(error, _variables, _context);\n },\n });\n\n const { queryResult, onFinish, formLoading, onFinishAutoSave } =\n useFormCoreResult;\n\n useEffect(() => {\n const data = queryResult?.data?.data;\n if (!data) return;\n\n const registeredFields = Object.keys(getValues());\n\n Object.entries(data).forEach(([key, value]) => {\n const name = key as Path<TVariables>;\n\n if (registeredFields.includes(name)) {\n setValue(name, value);\n }\n });\n }, [queryResult?.data, setValue, getValues]);\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: TVariables) => {\n if (warnWhenUnsavedChanges) {\n setWarnWhen(true);\n }\n\n if (refineCoreProps?.autoSave) {\n setWarnWhen(false);\n\n const onFinishProps = refineCoreProps.autoSave?.onFinish;\n\n if (onFinishProps) {\n return onFinishAutoSave(onFinishProps(changeValues));\n }\n\n return onFinishAutoSave(changeValues);\n }\n\n return changeValues;\n };\n\n const handleSubmit: UseFormHandleSubmit<TVariables> =\n (onValid, onInvalid) => async (e) => {\n setWarnWhen(false);\n return 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, Path } from \"react-hook-form\";\nimport { BaseRecord, HttpError } from \"@refinedev/core\";\n\nimport { useForm, UseFormProps, UseFormReturnType } from \"../useForm\";\n\nexport type UseStepsFormReturnType<\n TQueryFnData extends BaseRecord = BaseRecord,\n TError extends HttpError = HttpError,\n TVariables extends FieldValues = FieldValues,\n TContext extends object = {},\n TData extends BaseRecord = TQueryFnData,\n TResponse extends BaseRecord = TData,\n TResponseError extends HttpError = TError,\n> = UseFormReturnType<\n TQueryFnData,\n TError,\n TVariables,\n TContext,\n TData,\n TResponse,\n TResponseError\n> & {\n steps: {\n currentStep: number;\n gotoStep: (step: number) => void;\n };\n};\n\nexport type UseStepsFormProps<\n TQueryFnData extends BaseRecord = BaseRecord,\n TError extends HttpError = HttpError,\n TVariables extends FieldValues = FieldValues,\n TContext extends object = {},\n TData extends BaseRecord = TQueryFnData,\n TResponse extends BaseRecord = TData,\n TResponseError extends HttpError = TError,\n> = UseFormProps<\n TQueryFnData,\n TError,\n TVariables,\n TContext,\n TData,\n TResponse,\n TResponseError\n> & {\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 TQueryFnData extends BaseRecord = BaseRecord,\n TError extends HttpError = HttpError,\n TVariables extends FieldValues = FieldValues,\n TContext extends object = {},\n TData extends BaseRecord = TQueryFnData,\n TResponse extends BaseRecord = TData,\n TResponseError extends HttpError = TError,\n>({\n stepsProps,\n ...rest\n}: UseStepsFormProps<\n TQueryFnData,\n TError,\n TVariables,\n TContext,\n TData,\n TResponse,\n TResponseError\n> = {}): UseStepsFormReturnType<\n TQueryFnData,\n TError,\n TVariables,\n TContext,\n TData,\n TResponse,\n TResponseError\n> => {\n const { defaultStep = 0, isBackValidate = false } = stepsProps ?? {};\n const [current, setCurrent] = useState(defaultStep);\n\n const useHookFormResult = useForm<\n TQueryFnData,\n TError,\n TVariables,\n TContext,\n TData,\n TResponse,\n TResponseError\n >({\n ...rest,\n });\n\n const {\n trigger,\n getValues,\n setValue,\n formState: { dirtyFields },\n refineCore: { queryResult },\n } = useHookFormResult;\n\n useEffect(() => {\n const data = queryResult?.data?.data;\n if (!data) return;\n\n const registeredFields = Object.keys(getValues());\n Object.entries(data).forEach(([key, value]) => {\n const name = key as Path<TVariables>;\n\n if (registeredFields.includes(name)) {\n if (!dirtyFields[name]) {\n setValue(name, value);\n }\n }\n });\n }, [queryResult?.data, current, setValue, getValues]);\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 useUserFriendlyName,\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 TQueryFnData extends BaseRecord = BaseRecord,\n TError extends HttpError = HttpError,\n TVariables extends FieldValues = FieldValues,\n TContext extends object = {},\n TData extends BaseRecord = TQueryFnData,\n TResponse extends BaseRecord = TData,\n TResponseError extends HttpError = TError,\n> = UseFormReturnType<\n TQueryFnData,\n TError,\n TVariables,\n TContext,\n TData,\n TResponse,\n TResponseError\n> & {\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 TQueryFnData extends BaseRecord = BaseRecord,\n TError extends HttpError = HttpError,\n TVariables extends FieldValues = FieldValues,\n TContext extends object = {},\n TData extends BaseRecord = TQueryFnData,\n TResponse extends BaseRecord = TData,\n TResponseError extends HttpError = TError,\n> = UseFormProps<\n TQueryFnData,\n TError,\n TVariables,\n TContext,\n TData,\n TResponse,\n TResponseError\n> & {\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 TQueryFnData extends BaseRecord = BaseRecord,\n TError extends HttpError = HttpError,\n TVariables extends FieldValues = FieldValues,\n TContext extends object = {},\n TData extends BaseRecord = TQueryFnData,\n TResponse extends BaseRecord = TData,\n TResponseError extends HttpError = TError,\n>({\n modalProps,\n refineCoreProps,\n syncWithLocation,\n ...rest\n}: UseModalFormProps<\n TQueryFnData,\n TError,\n TVariables,\n TContext,\n TData,\n TResponse,\n TResponseError\n> = {}): UseModalFormReturnType<\n TQueryFnData,\n TError,\n TVariables,\n TContext,\n TData,\n TResponse,\n TResponseError\n> => {\n const [initiallySynced, setInitiallySynced] = React.useState(false);\n\n const translate = useTranslate();\n\n const { resource: resourceProp, action: actionProp } =\n refineCoreProps ?? {};\n\n const {\n resource,\n action: actionFromParams,\n identifier,\n } = useResource(resourceProp);\n\n const parsed = useParsed();\n const go = useGo();\n const getUserFriendlyName = useUserFriendlyName();\n\n const action = actionProp ?? actionFromParams ?? \"\";\n\n const syncingId = !(\n typeof syncWithLocation === \"object\" &&\n syncWithLocation?.syncId === false\n );\n\n const syncWithLocationKey =\n typeof syncWithLocation === \"object\" && \"key\" in syncWithLocation\n ? syncWithLocation.key\n : resource && action && syncWithLocation\n ? `modal-${identifier}-${action}`\n : undefined;\n\n const {\n defaultVisible = false,\n autoSubmitClose = true,\n autoResetForm = true,\n } = modalProps ?? {};\n\n const useHookFormResult = useForm<\n TQueryFnData,\n TError,\n TVariables,\n TContext,\n TData,\n TResponse,\n TResponseError\n >({\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 === 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 setInitiallySynced(true);\n }\n }, [syncWithLocationKey, parsed, syncingId, setId]);\n\n React.useEffect(() => {\n if (initiallySynced === 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(\n (showId?: BaseKey) => {\n if (typeof showId !== \"undefined\") {\n setId?.(showId);\n }\n const needsIdToOpen = action === \"edit\" || action === \"clone\";\n const hasId =\n typeof showId !== \"undefined\" || typeof id !== \"undefined\";\n if (needsIdToOpen ? hasId : true) {\n show();\n }\n },\n [id],\n );\n\n const title = translate(\n `${identifier}.titles.${actionProp}`,\n undefined,\n `${getUserFriendlyName(\n `${actionProp} ${\n resource?.meta?.label ??\n resource?.options?.label ??\n resource?.label ??\n identifier\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","disableServerSideValidationProp","rest","options","disableServerSideValidation","translate","warnWhenUnsavedChangesRefine","setWarnWhen","warnWhenUnsavedChanges","useHookFormResult","useHookForm","watch","setValue","getValues","handleSubmitReactHookForm","setError","useFormCoreResult","useFormCore","error","_variables","_context","_a","_b","errors","key","fieldError","newError","queryResult","onFinish","formLoading","onFinishAutoSave","data","registeredFields","value","name","subscription","values","type","onValuesChange","changeValues","onFinishProps","handleSubmit","onValid","onInvalid","e","import_react","useStepsForm","stepsProps","rest","defaultStep","isBackValidate","current","setCurrent","useHookFormResult","useForm","trigger","getValues","setValue","dirtyFields","queryResult","_a","data","registeredFields","key","value","name","go","step","targetStep","import_react","import_core","import_react","useModalForm","modalProps","refineCoreProps","syncWithLocation","rest","_a","_b","initiallySynced","setInitiallySynced","React","translate","resourceProp","actionProp","resource","actionFromParams","identifier","parsed","go","getUserFriendlyName","action","syncingId","syncWithLocationKey","defaultVisible","autoSubmitClose","autoResetForm","useHookFormResult","useForm","reset","onFinish","id","setId","saveButtonProps","handleSubmit","visible","show","close","_c","_d","openStatus","idFromParams","submit","values","warnWhen","setWarnWhen","handleClose","handleShow","showId","title","e"]}
@@ -19,6 +19,12 @@ export declare type UseFormProps<TQueryFnData extends BaseRecord = BaseRecord, T
19
19
  * @default `false*`
20
20
  */
21
21
  warnWhenUnsavedChanges?: boolean;
22
+ /**
23
+ * Disables server-side validation
24
+ * @default false
25
+ * @see {@link https://refine.dev/docs/advanced-tutorials/forms/server-side-form-validation/}
26
+ */
27
+ disableServerSideValidation?: boolean;
22
28
  } & UseHookFormProps<TVariables, TContext>;
23
- export declare const useForm: <TQueryFnData extends BaseRecord = BaseRecord, TError extends HttpError = HttpError, TVariables extends FieldValues = FieldValues, TContext extends object = {}, TData extends BaseRecord = TQueryFnData, TResponse extends BaseRecord = TData, TResponseError extends HttpError = TError>({ refineCoreProps, warnWhenUnsavedChanges: warnWhenUnsavedChangesProp, ...rest }?: UseFormProps<TQueryFnData, TError, TVariables, TContext, TData, TResponse, TResponseError>) => UseFormReturnType<TQueryFnData, TError, TVariables, TContext, TData, TResponse, TResponseError>;
29
+ export declare const useForm: <TQueryFnData extends BaseRecord = BaseRecord, TError extends HttpError = HttpError, TVariables extends FieldValues = FieldValues, TContext extends object = {}, TData extends BaseRecord = TQueryFnData, TResponse extends BaseRecord = TData, TResponseError extends HttpError = TError>({ refineCoreProps, warnWhenUnsavedChanges: warnWhenUnsavedChangesProp, disableServerSideValidation: disableServerSideValidationProp, ...rest }?: UseFormProps<TQueryFnData, TError, TVariables, TContext, TData, TResponse, TResponseError>) => UseFormReturnType<TQueryFnData, TError, TVariables, TContext, TData, TResponse, TResponseError>;
24
30
  //# sourceMappingURL=index.d.ts.map
@@ -1 +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,EAGd,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,YAAY,SAAS,UAAU,GAAG,UAAU,EAC5C,MAAM,SAAS,SAAS,GAAG,SAAS,EACpC,UAAU,SAAS,WAAW,GAAG,WAAW,EAC5C,QAAQ,SAAS,MAAM,GAAG,EAAE,EAC5B,KAAK,SAAS,UAAU,GAAG,YAAY,EACvC,SAAS,SAAS,UAAU,GAAG,KAAK,EACpC,cAAc,SAAS,SAAS,GAAG,MAAM,IACzC,aAAa,CAAC,UAAU,EAAE,QAAQ,CAAC,GAAG;IACtC,UAAU,EAAE,qBAAqB,CAC7B,YAAY,EACZ,MAAM,EACN,UAAU,EACV,KAAK,EACL,SAAS,EACT,cAAc,CACjB,CAAC;IACF,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,YAAY,SAAS,UAAU,GAAG,UAAU,EAC5C,MAAM,SAAS,SAAS,GAAG,SAAS,EACpC,UAAU,SAAS,WAAW,GAAG,WAAW,EAC5C,QAAQ,SAAS,MAAM,GAAG,EAAE,EAC5B,KAAK,SAAS,UAAU,GAAG,YAAY,EACvC,SAAS,SAAS,UAAU,GAAG,KAAK,EACpC,cAAc,SAAS,SAAS,GAAG,MAAM,IACzC;IACA;;;OAGG;IACH,eAAe,CAAC,EAAE,gBAAgB,CAC9B,YAAY,EACZ,MAAM,EACN,UAAU,EACV,KAAK,EACL,SAAS,EACT,cAAc,CACjB,CAAC;IACF;;;OAGG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;CACpC,GAAG,gBAAgB,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;AAE3C,eAAO,MAAM,OAAO,8iBA6GnB,CAAC"}
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,EAGd,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACH,UAAU,EACV,SAAS,EAGT,YAAY,IAAI,gBAAgB,EAChC,iBAAiB,IAAI,qBAAqB,EAG7C,MAAM,iBAAiB,CAAC;AAEzB,oBAAY,iBAAiB,CACzB,YAAY,SAAS,UAAU,GAAG,UAAU,EAC5C,MAAM,SAAS,SAAS,GAAG,SAAS,EACpC,UAAU,SAAS,WAAW,GAAG,WAAW,EAC5C,QAAQ,SAAS,MAAM,GAAG,EAAE,EAC5B,KAAK,SAAS,UAAU,GAAG,YAAY,EACvC,SAAS,SAAS,UAAU,GAAG,KAAK,EACpC,cAAc,SAAS,SAAS,GAAG,MAAM,IACzC,aAAa,CAAC,UAAU,EAAE,QAAQ,CAAC,GAAG;IACtC,UAAU,EAAE,qBAAqB,CAC7B,YAAY,EACZ,MAAM,EACN,UAAU,EACV,KAAK,EACL,SAAS,EACT,cAAc,CACjB,CAAC;IACF,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,YAAY,SAAS,UAAU,GAAG,UAAU,EAC5C,MAAM,SAAS,SAAS,GAAG,SAAS,EACpC,UAAU,SAAS,WAAW,GAAG,WAAW,EAC5C,QAAQ,SAAS,MAAM,GAAG,EAAE,EAC5B,KAAK,SAAS,UAAU,GAAG,YAAY,EACvC,SAAS,SAAS,UAAU,GAAG,KAAK,EACpC,cAAc,SAAS,SAAS,GAAG,MAAM,IACzC;IACA;;;OAGG;IACH,eAAe,CAAC,EAAE,gBAAgB,CAC9B,YAAY,EACZ,MAAM,EACN,UAAU,EACV,KAAK,EACL,SAAS,EACT,cAAc,CACjB,CAAC;IACF;;;OAGG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC;;;;OAIG;IACH,2BAA2B,CAAC,EAAE,OAAO,CAAC;CACzC,GAAG,gBAAgB,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;AAE3C,eAAO,MAAM,OAAO,4mBAqLnB,CAAC"}
@@ -1 +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,YAAY,SAAS,UAAU,GAAG,UAAU,EAC5C,MAAM,SAAS,SAAS,GAAG,SAAS,EACpC,UAAU,SAAS,WAAW,GAAG,WAAW,EAC5C,QAAQ,SAAS,MAAM,GAAG,EAAE,EAC5B,KAAK,SAAS,UAAU,GAAG,YAAY,EACvC,SAAS,SAAS,UAAU,GAAG,KAAK,EACpC,cAAc,SAAS,SAAS,GAAG,MAAM,IACzC,iBAAiB,CACjB,YAAY,EACZ,MAAM,EACN,UAAU,EACV,QAAQ,EACR,KAAK,EACL,SAAS,EACT,cAAc,CACjB,GAAG;IACA,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,YAAY,SAAS,UAAU,GAAG,UAAU,EAC5C,MAAM,SAAS,SAAS,GAAG,SAAS,EACpC,UAAU,SAAS,WAAW,GAAG,WAAW,EAC5C,QAAQ,SAAS,MAAM,GAAG,EAAE,EAC5B,KAAK,SAAS,UAAU,GAAG,YAAY,EACvC,SAAS,SAAS,UAAU,GAAG,KAAK,EACpC,cAAc,SAAS,SAAS,GAAG,MAAM,IACzC,YAAY,CACZ,YAAY,EACZ,MAAM,EACN,UAAU,EACV,QAAQ,EACR,KAAK,EACL,SAAS,EACT,cAAc,CACjB,GAAG;IACA;;;;;;;;;;;;;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,kiBAwNxB,CAAC"}
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,YAAY,SAAS,UAAU,GAAG,UAAU,EAC5C,MAAM,SAAS,SAAS,GAAG,SAAS,EACpC,UAAU,SAAS,WAAW,GAAG,WAAW,EAC5C,QAAQ,SAAS,MAAM,GAAG,EAAE,EAC5B,KAAK,SAAS,UAAU,GAAG,YAAY,EACvC,SAAS,SAAS,UAAU,GAAG,KAAK,EACpC,cAAc,SAAS,SAAS,GAAG,MAAM,IACzC,iBAAiB,CACjB,YAAY,EACZ,MAAM,EACN,UAAU,EACV,QAAQ,EACR,KAAK,EACL,SAAS,EACT,cAAc,CACjB,GAAG;IACA,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,YAAY,SAAS,UAAU,GAAG,UAAU,EAC5C,MAAM,SAAS,SAAS,GAAG,SAAS,EACpC,UAAU,SAAS,WAAW,GAAG,WAAW,EAC5C,QAAQ,SAAS,MAAM,GAAG,EAAE,EAC5B,KAAK,SAAS,UAAU,GAAG,YAAY,EACvC,SAAS,SAAS,UAAU,GAAG,KAAK,EACpC,cAAc,SAAS,SAAS,GAAG,MAAM,IACzC,YAAY,CACZ,YAAY,EACZ,MAAM,EACN,UAAU,EACV,QAAQ,EACR,KAAK,EACL,SAAS,EACT,cAAc,CACjB,GAAG;IACA;;;;;;;;;;;;;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,kiBAyNxB,CAAC"}
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "4.4.2",
2
+ "version": "4.6.0",
3
3
  "license": "MIT",
4
4
  "main": "dist/index.js",
5
5
  "typings": "dist/index.d.ts",
@@ -30,7 +30,8 @@
30
30
  "@types/react-dom": "^17.0.0 || ^18.0.0"
31
31
  },
32
32
  "devDependencies": {
33
- "@refinedev/core": "^4.24.0",
33
+ "@testing-library/jest-dom": "^5.16.4",
34
+ "@refinedev/core": "^4.28.0",
34
35
  "@esbuild-plugins/node-resolve": "^0.1.4",
35
36
  "@types/jest": "^29.2.4",
36
37
  "jest": "^29.3.1",
@@ -0,0 +1,249 @@
1
+ import React from "react";
2
+
3
+ import { useForm } from ".";
4
+ import { HttpError } from "@refinedev/core";
5
+ import { MockJSONServer, TestWrapper, act, render, waitFor } from "../../test";
6
+ import { Route, Routes } from "react-router-dom";
7
+ import { IRefineOptions } from "@refinedev/core/dist/interfaces";
8
+
9
+ interface IPost {
10
+ title: string;
11
+ content: string;
12
+ slug: string;
13
+ category: { id: number };
14
+ tags: string[];
15
+ }
16
+
17
+ const renderForm = ({
18
+ refineCoreProps,
19
+ refineOptions,
20
+ useFormProps,
21
+ }: {
22
+ useFormProps?: any;
23
+ refineCoreProps?: any;
24
+ refineOptions?: IRefineOptions;
25
+ }) => {
26
+ const EditPage = () => {
27
+ const {
28
+ refineCore: { formLoading },
29
+ saveButtonProps,
30
+ register,
31
+ formState: { errors },
32
+ } = useForm<IPost, HttpError, IPost>({
33
+ ...useFormProps,
34
+ refineCoreProps: {
35
+ resource: "posts",
36
+ ...refineCoreProps,
37
+ },
38
+ });
39
+
40
+ return (
41
+ <div>
42
+ {formLoading && <p>loading</p>}
43
+ <input {...register("title")} />
44
+ {errors.title && (
45
+ <span>{errors?.title?.message?.toString()}</span>
46
+ )}
47
+
48
+ <input {...register("content")} />
49
+ {errors.content && (
50
+ <span>{errors?.content?.message?.toString()}</span>
51
+ )}
52
+
53
+ <input {...register("slug")} />
54
+ {errors.slug && (
55
+ <span>{errors?.slug?.message?.toString()}</span>
56
+ )}
57
+
58
+ <select
59
+ {...register("category.id", {
60
+ required: true,
61
+ })}
62
+ >
63
+ {["1", "2", "3"]?.map((category) => (
64
+ <option key={category} value={category}>
65
+ {category}
66
+ </option>
67
+ ))}
68
+ </select>
69
+ {errors.category && (
70
+ <span>{`${errors.category?.id?.message}`}</span>
71
+ )}
72
+
73
+ <button
74
+ {...saveButtonProps}
75
+ onClick={(e) => {
76
+ console.log("clicked");
77
+ saveButtonProps?.onClick(e);
78
+ }}
79
+ data-testid="refine-save-button"
80
+ type="submit"
81
+ >
82
+ save
83
+ </button>
84
+ </div>
85
+ );
86
+ };
87
+
88
+ return render(
89
+ <Routes>
90
+ <Route path="/" element={<EditPage />} />
91
+ </Routes>,
92
+ {
93
+ wrapper: TestWrapper({
94
+ options: refineOptions,
95
+ i18nProvider: {
96
+ changeLocale: () => Promise.resolve(),
97
+ getLocale: () => "en",
98
+ translate: (key: string) => {
99
+ if (key === "form.error.content") {
100
+ return "Translated content error";
101
+ }
102
+
103
+ return key;
104
+ },
105
+ },
106
+ dataProvider: {
107
+ ...MockJSONServer,
108
+ update: async () => {
109
+ const error: HttpError = {
110
+ message:
111
+ "An error occurred while updating the record.",
112
+ statusCode: 400,
113
+ errors: {
114
+ title: ["Title is required"],
115
+ "category.id": ["Category is required"],
116
+ slug: true,
117
+ content: {
118
+ key: "form.error.content",
119
+ message: "Content is required",
120
+ },
121
+ },
122
+ };
123
+
124
+ return Promise.reject(error);
125
+ },
126
+ create: async () => {
127
+ const error: HttpError = {
128
+ message:
129
+ "An error occurred while creating the record.",
130
+ statusCode: 400,
131
+ slug: true,
132
+ errors: {
133
+ title: ["Title is required"],
134
+ "category.id": ["Category is required"],
135
+ slug: true,
136
+ content: {
137
+ key: "form.error.content",
138
+ message: "Content is required",
139
+ },
140
+ },
141
+ };
142
+
143
+ return Promise.reject(error);
144
+ },
145
+ },
146
+ }),
147
+ },
148
+ );
149
+ };
150
+
151
+ describe("useForm hook", () => {
152
+ it.each(["edit", "create"] as const)(
153
+ "should set %s-form errors from data provider",
154
+ async (action) => {
155
+ const onMutationError = jest.fn();
156
+
157
+ const { getByText, getByTestId } = renderForm({
158
+ refineCoreProps: {
159
+ onMutationError,
160
+ action: action,
161
+ id: action === "edit" ? "1" : undefined,
162
+ },
163
+ });
164
+
165
+ await waitFor(() => {
166
+ expect(document.body).not.toHaveTextContent("loading");
167
+ });
168
+
169
+ await act(() => {
170
+ getByTestId("refine-save-button").click();
171
+ return Promise.resolve();
172
+ });
173
+
174
+ await waitFor(() => {
175
+ expect(document.body).not.toHaveTextContent("loading");
176
+ });
177
+
178
+ expect(onMutationError).toBeCalledTimes(1);
179
+
180
+ expect(getByText("Title is required")).toBeInTheDocument();
181
+ expect(getByText("Category is required")).toBeInTheDocument();
182
+ expect(getByText("Translated content error")).toBeInTheDocument();
183
+ expect(getByText("Field is not valid.")).toBeInTheDocument();
184
+ },
185
+ );
186
+
187
+ it.each([
188
+ {
189
+ action: "edit",
190
+ disableFromRefineOption: false,
191
+ disableFromHook: true,
192
+ },
193
+ {
194
+ action: "edit",
195
+ disableFromRefineOption: true,
196
+ disableFromHook: false,
197
+ },
198
+ {
199
+ action: "create",
200
+ disableFromRefineOption: false,
201
+ disableFromHook: true,
202
+ },
203
+ {
204
+ action: "create",
205
+ disableFromRefineOption: true,
206
+ disableFromHook: false,
207
+ },
208
+ ] as const)("should disable server-side validation", async (testCase) => {
209
+ const onMutationErrorMock = jest.fn();
210
+
211
+ const { getByTestId, queryByText } = renderForm({
212
+ refineOptions: {
213
+ disableServerSideValidation: testCase.disableFromRefineOption,
214
+ },
215
+ useFormProps: {
216
+ disableServerSideValidation: testCase.disableFromHook,
217
+ },
218
+
219
+ refineCoreProps: {
220
+ action: testCase.action,
221
+ onMutationError: onMutationErrorMock,
222
+ id: testCase.action === "edit" ? "1" : undefined,
223
+ },
224
+ });
225
+
226
+ await waitFor(() => {
227
+ expect(document.body).not.toHaveTextContent("loading");
228
+ });
229
+
230
+ await act(() => {
231
+ getByTestId("refine-save-button").click();
232
+ return Promise.resolve();
233
+ });
234
+
235
+ await waitFor(() => {
236
+ expect(document.body).not.toHaveTextContent("loading");
237
+ expect(onMutationErrorMock).toBeCalledTimes(1);
238
+ });
239
+
240
+ await waitFor(() => {
241
+ expect(queryByText("Title is required")).not.toBeInTheDocument();
242
+ expect(queryByText("Category is required")).not.toBeInTheDocument();
243
+ expect(
244
+ queryByText("Translated content error"),
245
+ ).not.toBeInTheDocument();
246
+ expect(queryByText("Field is not valid.")).not.toBeInTheDocument();
247
+ });
248
+ });
249
+ });
@@ -14,6 +14,8 @@ import {
14
14
  useWarnAboutChange,
15
15
  UseFormProps as UseFormCoreProps,
16
16
  UseFormReturnType as UseFormReturnTypeCore,
17
+ useTranslate,
18
+ useRefineContext,
17
19
  } from "@refinedev/core";
18
20
 
19
21
  export type UseFormReturnType<
@@ -65,6 +67,12 @@ export type UseFormProps<
65
67
  * @default `false*`
66
68
  */
67
69
  warnWhenUnsavedChanges?: boolean;
70
+ /**
71
+ * Disables server-side validation
72
+ * @default false
73
+ * @see {@link https://refine.dev/docs/advanced-tutorials/forms/server-side-form-validation/}
74
+ */
75
+ disableServerSideValidation?: boolean;
68
76
  } & UseHookFormProps<TVariables, TContext>;
69
77
 
70
78
  export const useForm = <
@@ -78,6 +86,7 @@ export const useForm = <
78
86
  >({
79
87
  refineCoreProps,
80
88
  warnWhenUnsavedChanges: warnWhenUnsavedChangesProp,
89
+ disableServerSideValidation: disableServerSideValidationProp = false,
81
90
  ...rest
82
91
  }: UseFormProps<
83
92
  TQueryFnData,
@@ -96,6 +105,12 @@ export const useForm = <
96
105
  TResponse,
97
106
  TResponseError
98
107
  > => {
108
+ const { options } = useRefineContext();
109
+ const disableServerSideValidation =
110
+ options?.disableServerSideValidation || disableServerSideValidationProp;
111
+
112
+ const translate = useTranslate();
113
+
99
114
  const {
100
115
  warnWhenUnsavedChanges: warnWhenUnsavedChangesRefine,
101
116
  setWarnWhen,
@@ -103,6 +118,18 @@ export const useForm = <
103
118
  const warnWhenUnsavedChanges =
104
119
  warnWhenUnsavedChangesProp ?? warnWhenUnsavedChangesRefine;
105
120
 
121
+ const useHookFormResult = useHookForm<TVariables, TContext>({
122
+ ...rest,
123
+ });
124
+
125
+ const {
126
+ watch,
127
+ setValue,
128
+ getValues,
129
+ handleSubmit: handleSubmitReactHookForm,
130
+ setError,
131
+ } = useHookFormResult;
132
+
106
133
  const useFormCoreResult = useFormCore<
107
134
  TQueryFnData,
108
135
  TError,
@@ -112,26 +139,66 @@ export const useForm = <
112
139
  TResponseError
113
140
  >({
114
141
  ...refineCoreProps,
115
- });
142
+ onMutationError: (error, _variables, _context) => {
143
+ if (disableServerSideValidation) {
144
+ refineCoreProps?.onMutationError?.(error, _variables, _context);
145
+ return;
146
+ }
116
147
 
117
- const { queryResult, onFinish, formLoading } = useFormCoreResult;
148
+ const errors = error?.errors;
118
149
 
119
- const useHookFormResult = useHookForm<TVariables, TContext>({
120
- ...rest,
150
+ for (const key in errors) {
151
+ // when the key is not registered in the form, react-hook-form not working
152
+ const isKeyInVariables = Object.keys(_variables).includes(
153
+ key.split(".")[0],
154
+ );
155
+ if (!isKeyInVariables) {
156
+ continue;
157
+ }
158
+
159
+ const fieldError = errors[key];
160
+
161
+ let newError = "";
162
+
163
+ if (Array.isArray(fieldError)) {
164
+ newError = fieldError.join(" ");
165
+ }
166
+
167
+ if (typeof fieldError === "string") {
168
+ newError = fieldError;
169
+ }
170
+
171
+ if (typeof fieldError === "boolean" && fieldError) {
172
+ newError = "Field is not valid.";
173
+ }
174
+
175
+ if (typeof fieldError === "object" && "key" in fieldError) {
176
+ const translatedMessage = translate(
177
+ fieldError.key,
178
+ fieldError.message,
179
+ );
180
+
181
+ newError = translatedMessage;
182
+ }
183
+
184
+ setError(key as Path<TVariables>, {
185
+ message: newError,
186
+ });
187
+ }
188
+
189
+ refineCoreProps?.onMutationError?.(error, _variables, _context);
190
+ },
121
191
  });
122
192
 
123
- const {
124
- watch,
125
- setValue,
126
- getValues,
127
- handleSubmit: handleSubmitReactHookForm,
128
- } = useHookFormResult;
193
+ const { queryResult, onFinish, formLoading, onFinishAutoSave } =
194
+ useFormCoreResult;
129
195
 
130
196
  useEffect(() => {
131
197
  const data = queryResult?.data?.data;
132
198
  if (!data) return;
133
199
 
134
200
  const registeredFields = Object.keys(getValues());
201
+
135
202
  Object.entries(data).forEach(([key, value]) => {
136
203
  const name = key as Path<TVariables>;
137
204
 
@@ -150,10 +217,23 @@ export const useForm = <
150
217
  return () => subscription.unsubscribe();
151
218
  }, [watch]);
152
219
 
153
- const onValuesChange = (changeValues: Record<string, any>) => {
220
+ const onValuesChange = (changeValues: TVariables) => {
154
221
  if (warnWhenUnsavedChanges) {
155
222
  setWarnWhen(true);
156
223
  }
224
+
225
+ if (refineCoreProps?.autoSave) {
226
+ setWarnWhen(false);
227
+
228
+ const onFinishProps = refineCoreProps.autoSave?.onFinish;
229
+
230
+ if (onFinishProps) {
231
+ return onFinishAutoSave(onFinishProps(changeValues));
232
+ }
233
+
234
+ return onFinishAutoSave(changeValues);
235
+ }
236
+
157
237
  return changeValues;
158
238
  };
159
239