useeform
Version:
useeform is a custom React hook designed to simplify form handling in React applications. It provides an easy way to manage form state, handle form submissions, and validate form data. This hook is built to be flexible and can be integrated into any form
3 lines (2 loc) • 5.22 kB
JavaScript
import e,{useEffect as r,useState as a,useCallback as t}from"react";import{ZodError as n}from"zod";function l({props:{type:a,className:t,name:n,value:l,autoFocus:o,disabled:m,formElement:s,loadingComponent:u},addError:d,clearForm:i,loading:c}){return r((()=>{n||d("Name is required","name"),"button"!==s&&d("Invalid form element","formElement")}),[n,l,d,s]),e.createElement("button",{type:a||"button",className:t,name:n,autoFocus:o,disabled:m,onClick:"reset"===a?i:void 0},c?u||"Loading...":l)}function o({props:{type:a,className:t,autoFocus:n,disabled:l,maxLength:o,minLength:m,multiple:s,pattern:u,placeholder:d,readOnly:i,required:c,value:p,min:h,max:f,step:E,checked:b,onChange:g,name:F},addError:V,setFormValues:v,formValues:y}){r((()=>{"number"!==a&&V("NumberInput only supports type: number",F),(o||m)&&V(m?"maxLength and minLength":"maxLength",F),p&&h&&p.length>h&&V(`NumberInput value is less than ${h}`,F),p&&h&&p.length>h&&V(`NumberInput value is less than ${h}`,F)}),[]);return e.createElement("input",{type:"number",className:t,autoFocus:n,disabled:l,multiple:s,pattern:u,placeholder:d,readOnly:i,required:c,value:y[F]?y[F]:p,min:h,max:f,step:E,checked:b,onChange:e=>{v((r=>(console.log("prevValues",r),console.log({...r,[F]:Number(e.target.value)}),{...r}))),g&&g(e)}})}function m({props:{type:a,className:t,autoFocus:n,disabled:l,maxLength:o,minLength:m,multiple:s,pattern:u,placeholder:d,readOnly:i,required:c,value:p,min:h,max:f,step:E,checked:b,defaultChecked:g,onChange:F,name:V},addError:v,setFormValues:y,formValues:N}){r((()=>{(f||h)&&v(h?"max and min":"max",V),p&&o&&p.length>o&&v("TextInput value is longer than maxLength",V),p&&m&&p.length<m&&v("TextInput value is longer than maxLength",V)}),[]);return e.createElement("input",{type:a||"text",className:t,autoFocus:n,disabled:l,multiple:s,pattern:u,placeholder:d,readOnly:i,required:c,value:N[V],min:h,max:f,step:E,checked:b,defaultChecked:g,onChange:e=>{y((r=>{const a={...r};return a[V]=e.target.value,a})),F&&F(e)}})}function s({props:a,addError:t,setFormValues:n,formValues:l}){return r((()=>{a.name||t("Name is required","name")}),[a.name,a.placeholder,t]),"number"===a.type?e.createElement(o,{props:a,addError:t,setFormValues:n,formValues:l}):e.createElement(m,{props:a,addError:t,setFormValues:n,formValues:l})}function u({props:{children:a,formElement:t,name:n,className:l,htmlFor:o,value:m},addError:u,setFormValues:d,formValues:i}){return r((()=>{"label"!==t&&u("Invalid form element",n),o||a||u("Label must have a for attribute or children",n)}),[]),e.createElement("label",{className:l,htmlFor:o},m,e.createElement(s,{props:a,addError:u,setFormValues:d,formValues:i}))}function d({form:{children:r,className:a,id:t,noValidate:n,autoComplete:o,name:m,ref:d,style:i},addError:c,setFormValues:p,submiForm:h,clearForm:f,formValues:E,loading:b,setLoading:g}){return e.createElement("form",{onSubmit:h,className:a,id:t,noValidate:n,autoComplete:o,style:i,ref:d,name:m},r?.map(((r,a)=>"input"===r.formElement?e.createElement(s,{key:a,props:r,addError:c,setFormValues:p,formValues:E}):"button"===r.formElement?"submit"===r.name?e.createElement(l,{props:r,addError:c,clearForm:f,key:a,loading:b}):e.createElement(l,{props:r,addError:c,clearForm:f,key:a}):"label"===r.formElement?e.createElement(u,{key:a,addError:c,setFormValues:p,props:r,formValues:E}):null)))}function i(e){const[l,o]=a(e),[m,s]=a([]),[u,i]=a(!1),c={};l.children&&l.children.filter((e=>"input"===e.formElement||"label"===e.formElement&&e.children)).map((e=>{"label"===e.formElement?c[e.children.name]=e.children.value?e.children.value:"":c[e.name]=e.value?e.value:""}));const p=a(c),[h,f]=p,E=t(((e,r)=>{s((a=>[...a,{error:e,name:r}]))}),[]),b=t((e=>{s((r=>[...r.slice(0,e),...r.slice(e+1)]))}),[]),g=t((()=>{s([])}),[]),F=t((e=>{if(!e||!e.children)return;let r=null;const a=[];e.children.map((e=>{"label"===e.formElement&&e.children?(a.push(e.children.name),a.push(e.name)):a.push(e.name)})),a.reduce(((e,a)=>(e[a]&&(r=a),{...e,[a]:!0})),{}),r&&E("Form has duplicate names",r)}),[E]),V=t((()=>{const e=[];if(l&&l.children)for(const r of l.children)if("input"===r.formElement){if(r.zodValidation)try{r.zodValidation.parse(h[r.name])}catch(r){r instanceof n&&e.push(r)}}else if("label"===r.formElement&&r.children&&r.children.zodValidation)try{r.children.zodValidation.parse(h[r.children.name])}catch(r){r instanceof n&&e.push(r)}return e}),[l,h]),v=t((async e=>{l&&l.preventDefault&&e.preventDefault();const r=V();i(!0);try{l&&l.onSubmit&&await l.onSubmit(e,h,m,r)}catch(e){}i(!1)}),[m,l,h,V]),y=t((()=>{o(e),s([]),f({})}),[e,f]);r((()=>{if(!l||!l.children)return;F({...l});const e={};l.children.filter((e=>"input"===e.formElement||"label"===e.formElement&&e.children)).map((r=>{"label"===r.formElement?e[r.children.name]=r.children.value:e[r.name]=r.value})),Object.keys(e).forEach((r=>{e[r]=e[r]||""})),f(e)}),[F,l,f]);const N=d({form:l,setForm:o,addError:E,setFormValues:f,submiForm:v,clearForm:y,formValues:h,loading:u,setLoading:i});return{formState:p,errors:m,addError:E,removeError:b,clearErrors:g,formUI:N,validateFormZod:V,clearForm:y}}export{l as Button,d as Form,s as Input,u as Label,o as NumberInput,m as TextInput,i as default};
//# sourceMappingURL=index.js.map