fielder
Version:
A field-first form library for React and React Native
3 lines (2 loc) • 6.96 kB
JavaScript
import{createContext as e,useContext as t,useLayoutEffect as n,useEffect as a,useRef as i,useMemo as r,useCallback as o,useState as s}from"react";const l=e(null),u=()=>t(l),d=l.Provider,c="undefined"!=typeof window?n:a,m=({name:e,validate:n,initialValue:a,destroyOnUnmount:s=!1})=>{const u=i(s),d=i(!0),{fields:m,blurField:v,premountField:f,mountField:g,unmountField:_,setFieldValue:E,setFieldValidation:p}=t(l),y=r((()=>({name:e,value:a,validate:n})),[]),V=r((()=>d.current?f({name:y.name,initialValue:y.value,validate:y.validate}):m[y.name]),[y.name,y.value,y.validate,f,m]);c((()=>{g({name:y.name,initialValue:y.value,validate:y.validate})}),[y.name,y.validate,y.value,g]),c((()=>()=>{d.current=!1}),[]),r((()=>u.current=s),[s]),c((()=>()=>{_({name:y.name,destroy:u.current})}),[_,y.name]),c((()=>{d.current?d.current=!1:p({name:y.name,validation:n})}),[n,y.name,p]);const h=o((()=>v({name:y.name})),[y.name,v]),I=o((e=>{if("boolean"==typeof y.value)return E({name:y.name,value:e=>!e});const t="object"==typeof e&&"currentTarget"in e?e.currentTarget.value:e;return E({name:y.name,value:e=>Array.isArray(e)?e.includes(t)?e.filter((e=>e!==t)):[...e,t]:t})}),[y.name,y.value,E]),{value:L,error:F,isValid:A,isValidating:T,hasChanged:D,hasBlurred:S}=V;return r((()=>[{name:y.name,value:L,onBlur:h,onChange:I},{error:F,isValid:A,isValidating:T,hasBlurred:S,hasChanged:D}]),[y.name,L,h,I,F,A,T,D,S])},v=e=>{const[n,a]=s({isValidating:!1,hasSubmitted:!1}),{validateSubmission:i}=t(l),u=o((async()=>{const t=i();a({isValidating:t instanceof Promise,hasSubmitted:!0});const{state:n,errors:r}=await t;a((e=>({...e,isValidating:!1}))),0===Object.keys(r).length&&e(f(n))}),[i,e]);return r((()=>({...n,handleSubmit:u})),[n,u])},f=e=>Object.entries(e).reduce(((e,[t,n])=>({...e,[t]:n.value})),{}),g=(e,t)=>Object.keys(e).reduce((({state:e,promises:n},a)=>{const i=e[a],r=E(t,i),o=_(r,i);if(!o||!r)return{state:e,promises:n};try{const t=o({trigger:r,value:i.value,form:e});return t instanceof Promise?{promises:{...n,[a]:t},state:{...e,[a]:{...i,isValidating:!0}}}:{promises:n,state:{...e,[a]:{...i,isValid:!0,isValidating:!1,error:void 0}}}}catch(t){return{promises:n,state:{...e,[a]:{...i,isValid:!1,isValidating:!1,error:t&&t.message?t.message:t}}}}}),{state:e,promises:{}}),_=(e,t)=>{if(e)return"function"==typeof t._validate?t._validate:"object"==typeof t._validate?t._validate[e]:void 0},E=(e,t)=>{if(t&&t._isActive&&t._validate){if("VALIDATE_SUBMISSION"===e.type)return"submit";if("SET_FIELD_VALUE"===e.type&&e.config.name!==t.name)return"update";if(e.config.name===t.name)return"MOUNT_FIELD"===e.type?"mount":"BLUR_FIELD"===e.type?"blur":"SET_FIELD_VALUE"===e.type?"change":"SET_FIELD_VALIDATION"===e.type&&t.hasBlurred?"blur":"SET_FIELD_VALIDATION"===e.type&&t.hasChanged?"change":"SET_FIELD_VALIDATION"===e.type?"mount":"VALIDATE_FIELD"===e.type?e.config.trigger||"change":void 0}},p=e=>Object.entries(e).reduce(((e,[t,n])=>n._isActive&&n.error?{...e,[t]:n.error}:e),{}),y=async e=>(await Promise.all(Object.entries(e).map((([e,t])=>t.then((()=>({key:e,error:void 0}))).catch((t=>({key:e,error:t.message}))))))).reduce(((e,t)=>({...e,[t.key]:t.error})),{}),V=e=>Object.entries(e).reduce(((e,[t,n])=>void 0===n?e:{...e,[t]:n}),{}),h=(e={})=>{const t=i(),n=i(),a=r((()=>L(n)),[]),l=r((()=>e.fromState?Object.entries(e.fromState).reduce(((e,[t,n])=>({...e,[t]:{_isActive:!1,name:t,value:n,isValid:!1,isValidating:!1,hasBlurred:!1,hasChanged:!1}})),{}):{}),[]),[u,d]=((e,t)=>{const n=i(t),[a,r]=s(n.current);return[a,o((t=>(n.current=e(n.current,t),r(n.current),n.current)),[])]})(((e,n)=>{const i=I(e,n),{state:r,promises:o}=g(i,n);return Object.keys(o).length>0&&Object.entries(o).map((([e,t])=>a(e,t))),t.current=o,r}),l);r((()=>n.current=d),[d]);const c=o((e=>{const t={type:"MOUNT_FIELD",config:e},n=I(u,t),{state:a}=g(n,t);return a[e.name]}),[u]),m=o((e=>d({type:"MOUNT_FIELD",config:e})[e.name]),[d]),v=o((e=>d({type:"UNMOUNT_FIELD",config:e})),[d]),f=o((e=>d({type:"SET_FIELD_VALUE",config:e})),[d]),_=o((e=>d({type:"SET_FIELD_STATE",config:e})),[d]),E=o((e=>d({type:"BLUR_FIELD",config:e})),[d]),h=o((e=>d({type:"SET_FIELD_VALIDATION",config:e})),[d]),F=o((e=>d({type:"VALIDATE_FIELD",config:e})),[d]),A=o((()=>{const e=d({type:"VALIDATE_SUBMISSION"}),n=(({state:e,promises:t})=>{const n=p(e);return t&&0!==Object.keys(t).length?y(t).then((e=>V({...n,...e}))):n})({state:e,promises:t.current});return n instanceof Promise?n.then((t=>({state:e,errors:t}))):{state:e,errors:n}}),[d]),T=r((()=>Object.values(u).filter((e=>!(void 0===e||!e._isActive)))),[u]),D=r((()=>T.every((e=>e.isValid))),[T]),S=r((()=>T.some((e=>e.isValidating))),[T]);return r((()=>({fields:u,isValid:D,isValidating:S,premountField:c,setFieldValue:f,blurField:E,validateField:F,validateSubmission:A,mountField:m,unmountField:v,setFieldState:_,setFieldValidation:h})),[u,D,S,c,f,E,F,A,m,v,_,h])},I=(e,t)=>{return"MOUNT_FIELD"===t.type?(n=e,({name:e,validate:t,initialValue:a})=>{const i=n[e]||{};return i&&i._isActive&&console.warn("Field is already mounted"),{...n,[e]:{...i,name:e,_isActive:!0,_validate:t,isValid:!0,isValidating:!1,value:void 0!==i.value?i.value:a,error:i.error,hasBlurred:!1,hasChanged:!1}}})(t.config):"UNMOUNT_FIELD"===t.type?(e=>({name:t,destroy:n=!1})=>{const a=e[t];if(void 0===a)throw Error("Cannot unmount non-mounted field");return n?Object.entries(e).reduce(((e,[n,a])=>n===t?e:{...e,[n]:a}),{}):{...e,[t]:{...a,_isActive:!1}}})(e)(t.config):"SET_FIELD_VALUE"===t.type?(e=>({name:t,value:n})=>{const a=e[t];if(void 0===a)throw Error("Cannot set value on non-mounted field");return a._isActive||console.warn("Setting field value for inactive field."),{...e,[t]:{...a,value:"function"==typeof n?n(a.value):n,hasChanged:!0}}})(e)(t.config):"BLUR_FIELD"===t.type?(e=>({name:t})=>{const n=e[t];if(void 0===n)throw Error("Cannot unmount non-mounted field");return n._isActive||console.warn("Setting field attribute on inactive field."),{...e,[t]:{...n,hasBlurred:!0}}})(e)(t.config):"SET_FIELD_STATE"===t.type?(e=>({name:t,state:n})=>{const a=e[t];if(void 0===a)throw Error("Cannot unmount non-mounted field");const i="function"==typeof n?n(a):n;return i===a?e:{...e,[t]:i}})(e)(t.config):"SET_FIELD_VALIDATION"===t.type?(e=>({name:t,validation:n})=>{const a=e[t];if(void 0===a)throw Error("Cannot set validation on non-mounted field");return a._isActive||console.warn("Setting field validation for inactive field."),{...e,[t]:{...a,_validate:n}}})(e)(t.config):e;var n},L=e=>{let t={};return(n,a)=>{t={...t,[n]:a};const i=i=>r=>{if(!e||!e.current)return void console.warn("Unable to update validation state. Dispatch not available.");if(t[n]!==a)return;const o=!i;e.current({type:"SET_FIELD_STATE",config:{name:n,state:e=>({...e,isValidating:!1,isValid:o,error:o?void 0:r.message})}})};a.then(i(!1)).catch(i(!0))}};export{l as FielderContext,d as FielderProvider,m as useField,h as useForm,u as useFormContext,v as useSubmit};
//# sourceMappingURL=index.es.js.map