react-form-krafter
Version:
A flexible form engine for React powered by Standard Schema
2 lines (1 loc) • 9.87 kB
JavaScript
;Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const k=require("react/jsx-runtime"),t=require("react"),H=t.createContext(null),Y=({children:e,components:n,settings:a={}})=>{const S=t.useMemo(()=>({components:n,settings:a}),[n,a]);return k.jsx(H.Provider,{value:S,children:e})},W=()=>{const e=t.useContext(H);if(!e)throw new Error("useRegister must be used within a Register");return e};async function Q(e,n){let a=e["~standard"].validate(n);return a instanceof Promise&&(a=await a),a.issues?a.issues:!0}const T=t.createContext(null),$=t.createContext(null),z=t.createContext(null);function Z(){const e=t.useContext(T);if(!e)throw new Error("useInternalForm must be used within a Form");return e}function G({field:e}){const{components:n,settings:a}=W(),{onUpdate:S,onChange:E,setFieldsState:b,setFieldsInfo:f,fieldsState:v,fieldsInfo:r,schema:h,didSubmitOnce:M}=Z(),R=t.useRef(null),y=t.useRef(null),p=t.useMemo(()=>n?.find(s=>s.type===e.type)?.render,[n,e.type]),u=t.useCallback(async(s,m,o,d)=>{if((d==null||d=="")&&o.required)f(c=>({...c,errors:{...c.errors,[o.name]:a?.labels?.required||"REQUIRED_FIELD_ERROR"}}));else if(h){const c=await Q(h,s);if(c instanceof Array){const l=c.reduce((g,N)=>{const _=N.path.join(".");return _!==o.name||d!=null&&(g[_]=N.message),g},{...m.errors,[o.name]:null});f(g=>({...g,errors:l}))}else c===!0&&f(l=>({...l,errors:{}}))}},[h,f,a?.labels?.required]),F=t.useCallback(async({isBlur:s})=>{await R.current,y.current&&(clearTimeout(y.current),y.current=null),s&&f(l=>({...l,blurred:l.blurred.includes(e.name)?l.blurred:[...l.blurred||[],e.name]}));const m=await new Promise(l=>{b(g=>(l(g),g))}),o=await new Promise(l=>{f(g=>(l(g),g))}),d=m[e.name];if(o.previousState[e.name]===d)return;u(m,o,e,d);const c=await S?.({fieldName:e.name,value:d,previousState:o.previousState,currentState:m});if(c&&"preventUpdate"in c&&c.preventUpdate){b(l=>({...l,[e.name]:o.previousState[e.name]||e.initialValue})),u(o.previousState,o,e,d);return}f(l=>({...l,previousState:{...l.previousState,[e.name]:d}}))},[u,e,S,f,b]),I=t.useCallback(()=>{F({isBlur:!0})},[F]),i=t.useCallback(async s=>{let m=()=>{};R.current=new Promise(o=>{m=o});try{f(c=>({...c,dirty:c.dirty.includes(e.name)?c.dirty:[...c.dirty||[],e.name]})),b(c=>({...c,[e.name]:s}));const o=await new Promise(c=>{f(l=>(c(l),l))}),d=await new Promise(c=>{b(l=>(c(l),l))});E?.({fieldName:e.name,value:s,previousState:o.previousState,currentState:d}),a?.disableErrorCheckOnChange||u(d,o,e,s),a?.updateDebounce&&(y.current&&clearTimeout(y.current),y.current=setTimeout(async()=>{await F({isBlur:!1}),y.current=null},a.updateDebounce))}finally{R.current&&(R.current=null,m())}},[u,e,F,E,f,b,a?.disableErrorCheckOnChange,a?.updateDebounce]),C=t.useCallback(()=>{f(s=>({...s,focused:s.focused.includes(e.name)?s.focused:[...s.focused||[],e.name]}))},[e.name,f]),w=t.useMemo(()=>v[e.name],[v,e.name]),x=t.useMemo(()=>r.touched?.includes(e.name),[r,e.name]),j=t.useMemo(()=>r.dirty?.includes(e.name),[r,e.name]),V=t.useMemo(()=>!j,[j]),A=t.useMemo(()=>r.blurred?.includes(e.name),[r,e.name]),O=t.useMemo(()=>r.focused?.includes(e.name),[r,e.name]),L=t.useMemo(()=>w===e.initialValue,[w,e.initialValue]),D=t.useMemo(()=>r.disabled?.includes(e.name),[r,e.name]),P=t.useMemo(()=>r.manualErrors?.[e.name]||r.errors?.[e.name]||null,[r.errors,r.manualErrors,e.name]),q=t.useMemo(()=>({...e,value:w,isTouched:x,isDirty:j,isFocused:O,isDefaultValue:L,isPristine:V,isBlurred:A,isDisabled:D||e.disabled||!1,error:P,isErrorVisible:A||M}),[e,w,x,j,O,L,V,A,D,P,M]),U=t.useMemo(()=>({onChange:i,onBlur:I,onFocus:C}),[i,I,C]);return p?k.jsx(ee,{Component:p,field:q,methods:U}):(console.error(`Component for field type "${e.type}" was not found.`),null)}const ee=t.memo(({Component:e,field:n,methods:a})=>k.jsx(e,{field:n,methods:a})),B=({formApi:e,formClassName:n,initialDisabledFields:a,forceFieldChangeState:S,fieldWrapper:E,...b})=>{const f=t.useRef(null),v=t.useMemo(()=>Object.fromEntries(b.fields.map(s=>[s.name,s.initialValue])),[b.fields]),[r,h]=t.useState(v),[M,R]=t.useState(!1),[y,p]=t.useState(!1);t.useEffect(()=>{S&&h(S)},[S]);const[u,F]=t.useState({dirty:[],focused:[],touched:[],blurred:[],manualErrors:{},initialState:v,errors:{},disabled:a??[],previousState:v}),I=t.useMemo(()=>Object.keys(u.errors).some(s=>u.errors[s]!=null)||Object.keys(u.manualErrors).some(s=>u.manualErrors[s]!=null),[u.errors,u.manualErrors]),i=t.useCallback(()=>{h(u.initialState),F(s=>({...s,previousState:u.initialState,dirty:[],focused:[],touched:[],blurred:[],errors:{},manualErrors:{},disabled:[],initialState:u.initialState})),p(!1)},[u.initialState,F,h]),C=t.useCallback(s=>{h(m=>{const o={...m,...s};return F(d=>({...d,previousState:{...d.previousState,...Object.entries(s).reduce((c,[l,g])=>({...c,[l]:g}),{})}})),o})},[F,h]),w=t.useCallback((s,m)=>{F(o=>{const d=m?[...o.disabled,s]:o.disabled.filter(c=>c!==s);return{...o,disabled:d}})},[F]),x=t.useCallback((s,m)=>{F(o=>{const d={...o.manualErrors};return m===null?delete d[s]:d[s]=m,{...o,manualErrors:d}})},[F]),j=t.useCallback(async()=>{let s=!1;const m=await Q(b.schema,r);if(m instanceof Array){const o=m.reduce((d,c)=>{const l=c.path.join(".");return d[l]=c.message,d},{});F(d=>({...d,errors:o})),s=!0}return s||(s=Object.keys(u.manualErrors).some(o=>u.manualErrors[o]!=null)),{hasError:s}},[b.schema,r,u.manualErrors]),V=t.useCallback(async s=>{try{s.preventDefault(),s.stopPropagation();const{hasError:m}=await j();R(!0),p(!0),b.onSubmit&&await b.onSubmit({state:r,errors:u.errors,success:!m})}finally{R(!1)}},[j,b,r,u.errors]),A=t.useCallback(async(s,m)=>{if(!s){console.warn("Field name is required to set value");return}h(o=>({...o,[s]:m}))},[h]),O=t.useCallback(()=>{f.current&&f.current.requestSubmit()},[]),L=t.useMemo(()=>({...b,fieldsInfo:u,setFieldsInfo:F,fieldsState:r,setFieldsState:h,reset:i,updateFieldsState:C,didSubmitOnce:y,isSubmitting:M,setFieldValue:A}),[y,u,r,M,b,i,A,C]),D=t.useMemo(()=>({reset:i,updateFieldsState:C,setFieldsInfo:F,setFieldsState:h,fieldsState:r,fieldsInfo:u,setDisabled:w,setError:x,requestSubmit:O,formRef:f,onFormSubmit:V,isSubmitting:M,setFieldValue:A,didSubmitOnce:y,hasSomeError:I,checkForErrors:j,setDidSubmitOnce:p}),[j,y,u,r,I,M,V,O,i,w,x,A,C]),P=t.useCallback(({children:s,field:m})=>E?E(s,m):s,[E]);t.useImperativeHandle(e,()=>D,[D]);const q=t.useMemo(()=>r,[r]),U=t.useMemo(()=>u,[u]);return k.jsx($.Provider,{value:q,children:k.jsx(z.Provider,{value:U,children:k.jsx(T.Provider,{value:L,children:k.jsxs("form",{className:n,onSubmit:V,ref:f,children:[b.fields?.map((s,m)=>k.jsx(P,{field:s,children:k.jsx(G,{field:s})},m)),b.children&&typeof b.children=="function"?b.children(D):b.children]})})})})};function te(){const e=t.useContext(T);if(!e)throw new Error("useForm must be used within a Form");return e}function J(){const e=t.useContext($);if(!e)throw new Error("useFieldsState must be used within a Form");return e}function K(){const e=t.useContext(z);if(!e)throw new Error("useFieldsInfo must be used within a Form");return e}function se(){const e=K();return t.useMemo(()=>e.errors,[e.errors])}function re(e){const n=J();return t.useMemo(()=>n[e],[n,e])}const ne=t.createContext(null),X=t.createContext(null),ae=()=>{const e=t.useContext(X);if(!e)throw new Error("useListApi must be used within a List component");return e},oe=({children:e,...n})=>{const[a,S]=t.useState(n.initialItems||[]),E=t.useRef(null),[b,f]=t.useState(null),v=t.useMemo(()=>({userProps:n}),[n]),r=t.useCallback(async()=>{if(E.current.setDidSubmitOnce(!0),await E.current.checkForErrors(),E.current.hasSomeError){n.addProps.onError?.(E.current.fieldsInfo.errors);return}const i=E.current.fieldsState,{item:C}=await n.addProps.onSuccess?.(i)??{},w=C||i;E.current.reset(),f(null),S(x=>[...x,w])},[n.addProps]),h=t.useCallback(i=>{S(C=>C.filter((w,x)=>x!==i))},[]),M=t.useCallback((i,C)=>{S(w=>w.map((x,j)=>j===i?C:x))},[]),R=t.useCallback(i=>{S(C=>[...C,...i])},[]),y=t.useCallback(i=>{S(C=>C.filter((w,x)=>!i.includes(x)))},[]),p=t.useCallback(i=>{S(C=>{const w=[...C];return i.forEach(({index:x,item:j})=>{w[x]&&(w[x]=j)}),w})},[]),u=t.useMemo(()=>({items:a,addItem:r,removeItem:h,updateItem:M,insertItems:R,removeItems:y,updateItems:p}),[a,r,h,M,R,y,p]),F=t.useMemo(()=>n.fields.map(i=>({...i,metadata:{...i.metadata||{},isListField:!0}})),[n.fields]);t.useImperativeHandle(n.listApi,()=>({addItem:r,removeItem:h,updateItem:M,items:a,insertItems:R,removeItems:y,updateItems:p}),[r,h,M,a,R,y,p]);const I=t.useMemo(()=>F.map(i=>({...i,metadata:{...i.metadata||{},isAddRow:!0}})),[F]);return k.jsx(ne.Provider,{value:v,children:k.jsxs(X.Provider,{value:u,children:[k.jsx(n.addProps.rowComponent,{add:r,formApi:E,form:k.jsx(B,{forceFieldChangeState:b,formApi:E,fields:I,fieldWrapper:n.formProps?.fieldWrapper,schema:n.schema,formClassName:n.formProps?.formClassName,onChange:({currentState:i,value:C,fieldName:w})=>{f(()=>({...i,[w]:C}))}})}),a.map((i,C)=>k.jsx(ue,{fieldsFormProps:F,userProps:n,item:i,index:C,updateItem:M,removeItem:h},C)),typeof e=="function"?e(u):e]})})},ue=({fieldsFormProps:e,userProps:n,item:a,index:S,updateItem:E,removeItem:b})=>{const f=t.useRef(null),v=t.useMemo(()=>e.map(r=>({...r,initialValue:a[r.name],metadata:{...r.metadata||{},listIndex:S}})),[e,S,a]);return k.jsx(n.itemsProps.rowComponent,{item:a,index:S,formApi:f,remove:b,form:k.jsx(B,{forceFieldChangeState:a,formApi:f,fields:v,schema:n.schema,formClassName:n.formProps?.formClassName,onChange:r=>{const{currentState:h,fieldName:M,value:R}=r;E(S,{...h,[M]:R}),n.itemsProps.onChange?.({...r,item:a,index:S})},onUpdate:r=>n.itemsProps.onUpdate?.({...r,item:a,index:S})})})};exports.FieldComponent=G;exports.Form=B;exports.List=oe;exports.Register=Y;exports.useFieldValue=re;exports.useFieldsErrors=se;exports.useFieldsInfo=K;exports.useFieldsState=J;exports.useForm=te;exports.useListApi=ae;exports.useRegister=W;