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