UNPKG

react-form-krafter

Version:

A flexible form engine for React powered by Standard Schema

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