@volverjs/form-vue 0.0.14-beta.1 → 0.0.14-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.umd.js CHANGED
@@ -1 +1 @@
1
- (function(y,r){typeof exports=="object"&&typeof module<"u"?r(exports,require("vue"),require("@vueuse/core"),require("zod")):typeof define=="function"&&define.amd?define(["exports","vue","@vueuse/core","zod"],r):(y=typeof globalThis<"u"?globalThis:y||self,r(y["@volverjs/form-vue"]={},y.Vue,y.VueUseCore,y.zod))})(this,function(y,r,M,V){"use strict";function _(e){return Array.isArray(e)}function T(e){return typeof e<"u"}function N(e){return e===null}function G(e){return typeof e=="object"}function L(e){return typeof e=="string"}function C(e){return typeof e>"u"}const U=/^[0-9]+$/,J=["__proto__","prototype","constructor"];function k(e,s,f){const u=T(f)?f:void 0;if(!G(e)||!L(s))return u;const o=Z(s);if(o.length!==0){for(const t of o){if(t==="*")continue;const i=function(a){return a.map(l=>C(l)||N(l)?l:_(l)?i(l):l[t])};if(_(e)&&!U.test(t)?e=i(e):e=e[t],C(e)||N(e))break}return C(e)?u:e}}function W(e,s,f){if(!G(e)||!L(s))return;const u=Z(s);if(u.length===0)return;const o=u.length;for(let t=0;t<o;t++){const i=u[t];if(t===o-1){e[i]=f;return}if(i==="*"&&_(e)){const a=u.slice(t+1).join(".");for(const l of e)W(l,a,f);return}C(e[i])&&(e[i]={}),e=e[i]}}function Z(e){const s=e.split(/[.]|(?:\[(\d|\*)\])/).filter(f=>!!f);return s.some(f=>J.indexOf(f)!==-1)?[]:s}var d=(e=>(e.text="text",e.number="number",e.email="email",e.password="password",e.tel="tel",e.url="url",e.search="search",e.date="date",e.time="time",e.datetimeLocal="datetime-local",e.month="month",e.week="week",e.color="color",e.select="select",e.checkbox="checkbox",e.radio="radio",e.textarea="textarea",e.radioGroup="radioGroup",e.checkboxGroup="checkboxGroup",e.combobox="combobox",e.custom="custom",e))(d||{}),S=(e=>(e.invalid="invalid",e.valid="valid",e))(S||{});const P=(e,s,f,u)=>r.defineComponent({name:"FieldComponent",props:{type:{type:String,validator:o=>Object.values(d).includes(o),default:d.custom},is:{type:[Object,String],default:void 0},name:{type:[String,Number,Boolean,Symbol],required:!0},props:{type:[Object,Function],default:()=>({})},showValid:{type:Boolean,default:!1},defaultValue:{type:[String,Number,Boolean,Array,Object],default:void 0},lazyLoad:{type:Boolean,default:!1}},emits:["invalid","valid","update:formData","update:modelValue"],expose:["invalid","invalidLabel","errors"],setup(o,{slots:t,emit:i}){const a=r.computed({get(){if(n!=null&&n.formData)return k(Object(n.formData.value),String(o.name))},set(c){n!=null&&n.formData&&(W(Object(n.formData.value),String(o.name),c),i("update:modelValue",{newValue:a.value,formData:n==null?void 0:n.formData}))}});r.onMounted(()=>{a.value===void 0&&o.defaultValue!==void 0&&(a.value=o.defaultValue)}),r.onBeforeUnmount(()=>{O(),x()});const l=r.inject(s,void 0);l&&l.fields.value.add(o.name);const n=r.inject(e),{props:h,name:p}=r.toRefs(o),m=r.computed(()=>{if(n!=null&&n.errors.value)return k(n.errors.value,String(o.name))}),v=r.computed(()=>{var c;return(c=m.value)==null?void 0:c._errors}),b=r.computed(()=>m.value!==void 0),O=r.watch(b,()=>{b.value?(i("invalid",v.value),l&&l.errors.value.set(o.name,{_errors:v.value})):(i("valid",a.value),l&&l.errors.value.delete(o.name))}),x=r.watch(()=>n==null?void 0:n.formData,()=>{i("update:formData",n==null?void 0:n.formData)},{deep:!0}),g=c=>{a.value=c},A=r.computed(()=>{let c=h.value;return typeof c=="function"&&(c=c(n==null?void 0:n.formData)),Object.keys(c).reduce((w,q)=>(w[q]=r.unref(c[q]),w),{})}),B=r.computed(()=>({...A.value,name:A.value.name??o.name,invalid:b.value,valid:o.showValid?!!(!b.value&&a.value):void 0,type:(c=>{if([d.text,d.number,d.email,d.password,d.tel,d.url,d.search,d.date,d.time,d.datetimeLocal,d.month,d.week,d.color].includes(c))return c})(o.type),invalidLabel:v.value,modelValue:a.value,"onUpdate:modelValue":g}));return r.provide(f,{name:r.readonly(p),errors:r.readonly(m)}),{component:r.computed(()=>{if(o.type===d.custom)return{render(){var c;return((c=t.default)==null?void 0:c.call(t,{modelValue:a.value,onUpdate:g,submit:n==null?void 0:n.submit,validate:n==null?void 0:n.validate,invalid:b.value,invalidLabel:v.value,formData:n==null?void 0:n.formData.value,formErrors:n==null?void 0:n.errors.value,errors:m.value}))??t.defalut}};if(!((u==null?void 0:u.lazyLoad)??o.lazyLoad)){let c;switch(o.type){case d.select:c=r.resolveComponent("VvSelect");break;case d.checkbox:c=r.resolveComponent("VvCheckbox");break;case d.radio:c=r.resolveComponent("VvRadio");break;case d.textarea:c=r.resolveComponent("VvTextarea");break;case d.radioGroup:c=r.resolveComponent("VvRadioGroup");break;case d.checkboxGroup:c=r.resolveComponent("VvCheckboxGroup");break;case d.combobox:c=r.resolveComponent("VvCombobox");break;default:c=r.resolveComponent("VvInputText")}if(typeof c!="string")return c;console.warn(`[form-vue warn]: ${c} not found, the component will be loaded asynchronously. To avoid this warning, please set "lazyLoad" option.`)}return r.defineAsyncComponent(async()=>{switch(u!=null&&u.sideEffects&&await Promise.resolve(u.sideEffects(o.type)),o.type){case d.textarea:return import("@volverjs/ui-vue/vv-textarea");case d.radio:return import("@volverjs/ui-vue/vv-radio");case d.radioGroup:return import("@volverjs/ui-vue/vv-radio-group");case d.checkbox:return import("@volverjs/ui-vue/vv-checkbox");case d.checkboxGroup:return import("@volverjs/ui-vue/vv-checkbox-group");case d.select:return import("@volverjs/ui-vue/vv-select");case d.combobox:return import("@volverjs/ui-vue/vv-combobox")}return import("@volverjs/ui-vue/vv-input-text")})}),hasProps:B,invalid:b}},render(){return this.is?r.h(this.is,this.hasProps,this.$slots):this.type===d.custom?r.h(this.component,null,this.$slots):r.h(this.component,this.hasProps,this.$slots)}}),E=(e,s={})=>{const f=t=>{let i=t;for(;i instanceof V.ZodEffects;)i=i.innerType();return i instanceof V.ZodOptional&&(i=i._def.innerType),i},u=f(e);return{...(u instanceof V.ZodObject?u._def.unknownKeys==="passthrough":!1)?s:{},...Object.fromEntries(Object.entries(u.shape).map(([t,i])=>{const a=s[t];let l=f(i),n;if(l instanceof V.ZodDefault&&(n=l._def.defaultValue(),l=l._def.innerType),a===null&&l instanceof V.ZodNullable)return[t,a];if(l instanceof V.ZodSchema){const h=i.safeParse(a);if(h.success)return[t,h.data??n]}if(l instanceof V.ZodArray&&Array.isArray(a)&&a.length){const h=l._def.type;if(h instanceof V.ZodObject)return[t,a.map(p=>E(h,p&&typeof p=="object"?p:void 0))??n]}return l instanceof V.ZodObject?[t,E(l,a&&typeof a=="object"?a:n)]:[t,n]}))}},z=(e,s,f)=>{const u=r.ref(),o=r.ref(),t=r.ref(),i=r.defineComponent({name:"FormComponent",props:{modelValue:{type:Object,default:()=>({})},updateThrottle:{type:Number,default:500},continuosValidation:{type:Boolean,default:!1}},emits:["invalid","valid","submit","update:modelValue"],expose:["submit","validate","errors","status","valid","invalid"],setup(a,{emit:l}){t.value=E(e,r.toRaw(a.modelValue)),r.watch(()=>a.modelValue,m=>{if(m){const v=r.isProxy(m)?r.toRaw(m):m;t.value=typeof(v==null?void 0:v.clone)=="function"?v.clone():JSON.parse(JSON.stringify(v))}},{deep:!0}),M.watchThrottled(t,m=>{((u.value||(f==null?void 0:f.continuosValidation))??a.continuosValidation)&&n(),(!m||!a.modelValue||JSON.stringify(m)!==JSON.stringify(a.modelValue))&&l("update:modelValue",m)},{deep:!0,throttle:(f==null?void 0:f.updateThrottle)??a.updateThrottle});const n=(m=t.value)=>{const v=e.safeParse(m);return v.success?(u.value=void 0,o.value=S.valid,t.value=v.data,l("update:modelValue",t.value),l("valid",v.data),!0):(u.value=v.error.format(),o.value=S.invalid,l("invalid",u.value),!1)},h=()=>n()?(l("submit",t.value),!0):!1,p=r.computed(()=>o.value===S.invalid);return r.provide(s,{formData:t,submit:h,validate:n,errors:r.readonly(u),status:r.readonly(o),invalid:p}),{formData:t,submit:h,validate:n,errors:r.readonly(u),status:r.readonly(o),invalid:p}},render(){return r.h("form",{onSubmit:r.withModifiers(this.submit,["prevent"])},{default:()=>{var a,l;return((l=(a=this.$slots)==null?void 0:a.default)==null?void 0:l.call(a,{formData:this.formData,submit:this.submit,validate:this.validate,errors:this.errors,status:this.status,invalid:this.invalid}))??this.$slots.default}})}});return{errors:u,status:o,formData:t,VvForm:i}},R=(e,s)=>r.defineComponent({name:"WrapperComponent",props:{name:{type:String,required:!0},tag:{type:String,default:void 0}},emits:["invalid","valid"],expose:["fields","invalid"],setup(u,{emit:o}){const t=r.inject(e),i=r.inject(s,void 0),a=r.ref(new Set),l=r.ref(new Map),{name:n}=r.toRefs(u);r.provide(s,{name:r.readonly(n),errors:l,fields:a}),r.watch(a,p=>{i!=null&&i.fields&&p.forEach(m=>{i==null||i.fields.value.add(m)})},{deep:!0}),r.watch(()=>new Map(l.value),(p,m)=>{i!=null&&i.errors&&(Array.from(m.keys()).forEach(v=>{i.errors.value.delete(v)}),Array.from(p.keys()).forEach(v=>{const b=p.get(v);b&&i.errors.value.set(v,b)}))},{deep:!0});const h=r.computed(()=>t!=null&&t.invalid.value?l.value.size>0:!1);return r.watch(h,()=>{h.value?o("invalid"):o("valid")}),{formData:t==null?void 0:t.formData,errors:t==null?void 0:t.errors,submit:t==null?void 0:t.submit,validate:t==null?void 0:t.validate,invalid:h,fields:a,fieldsErrors:l}},render(){var u,o;return this.tag?r.h(this.tag,null,{default:()=>{var t,i;return((i=(t=this.$slots).default)==null?void 0:i.call(t,{invalid:this.invalid,formData:this.formData,submit:this.submit,validate:this.validate,errors:this.errors,fieldsErrors:this.fieldsErrors}))??this.$slots.defalut}}):((o=(u=this.$slots).default)==null?void 0:o.call(u,{invalid:this.invalid,formData:this.formData,submit:this.submit,validate:this.validate,errors:this.errors,fieldsErrors:this.fieldsErrors}))??this.$slots.defalut}}),H=(e,s)=>{const f=r.defineComponent({props:{schema:{type:[Array,Function],required:!0}},setup(u,{slots:o}){const t=r.inject(e);if(!(t!=null&&t.formData))return;const i=typeof u.schema=="function"?u.schema(t):u.schema;let a;return()=>{var l;return i.reduce((n,h)=>{const p=typeof h=="function"?h(t):h,{vvIs:m,vvName:v,vvSlots:b,vvChildren:O,vvIf:x,vvElseIf:g,vvType:A,vvDefaultValue:B,vvShowValid:K,...c}=p;if(x!==void 0){if(typeof x=="string"?a=!!k(Object(t.formData.value),x):typeof x=="function"?a=r.unref(x(t)):a=r.unref(x),!a)return n}else if(g!==void 0&&a!==void 0){if(a||(typeof g=="string"?a=!!k(Object(t.formData.value),g):typeof g=="function"?a=r.unref(g(t)):a=r.unref(g),!a))return n}else a=void 0;const w=O?r.h(f,{schema:O}):void 0;return v?(n.push(r.h(s,{name:v,is:m,type:A,defaultValue:B,showValid:K,props:c},b??w)),n):m?(n.push(r.h(m,c,b??w)),n):(O&&n.push(w),n)},[(l=o==null?void 0:o.default)==null?void 0:l.call(o,{formData:t==null?void 0:t.formData.value,submit:t==null?void 0:t.submit,validate:t==null?void 0:t.validate,errors:t==null?void 0:t.errors.value,status:t==null?void 0:t.status.value,invalid:t==null?void 0:t.invalid.value})])}}});return f},I=(e,s={})=>{const f=Symbol(),u=Symbol(),o=Symbol(),{VvForm:t,errors:i,status:a,formData:l}=z(e,f,s),n=R(f,u),h=P(f,u,o,s),p=H(f,h);return{VvForm:t,VvFormWrapper:n,VvFormField:h,VvFormTemplate:p,formInjectionKey:f,formWrapperInjectionKey:u,formFieldInjectionKey:o,errors:i,status:a,formData:l}},$=Symbol(),Q=e=>{let s={};return e.schema&&(s=I(e.schema,e)),{...s,install(f,{global:u=!1}={}){f.provide($,e),u&&(f.config.globalProperties.$vvForm=e,s!=null&&s.VvForm&&f.component("VvForm",s.VvForm),s!=null&&s.VvFormWrapper&&f.component("VvFormWrapper",s.VvFormWrapper),s!=null&&s.VvFormField&&f.component("VvFormField",s.VvFormField),s!=null&&s.VvFormTemplate&&f.component("VvFormTemplate",s.VvFormTemplate))}}},X=(e,s={})=>r.getCurrentInstance()?I(e,{...r.inject($,{}),...s}):I(e,s),Y=(e,s={})=>I(e,s);y.FormFieldType=d,y.createForm=Q,y.defaultObjectBySchema=E,y.formFactory=Y,y.pluginInjectionKey=$,y.useForm=X,Object.defineProperty(y,Symbol.toStringTag,{value:"Module"})});
1
+ (function(V,r){typeof exports=="object"&&typeof module<"u"?r(exports,require("vue"),require("@vueuse/core"),require("zod")):typeof define=="function"&&define.amd?define(["exports","vue","@vueuse/core","zod"],r):(V=typeof globalThis<"u"?globalThis:V||self,r(V["@volverjs/form-vue"]={},V.Vue,V.VueUseCore,V.zod))})(this,function(V,r,U,w){"use strict";function $(e){return Array.isArray(e)}function q(e){return typeof e<"u"}function G(e){return e===null}function L(e){return typeof e=="object"}function W(e){return typeof e=="string"}function k(e){return typeof e>"u"}const M=/^[0-9]+$/,J=["__proto__","prototype","constructor"];function S(e,u,a){const f=q(a)?a:void 0;if(!L(e)||!W(u))return f;const s=K(u);if(s.length!==0){for(const t of s){if(t==="*")continue;const l=function(o){return o.map(i=>k(i)||G(i)?i:$(i)?l(i):i[t])};if($(e)&&!M.test(t)?e=l(e):e=e[t],k(e)||G(e))break}return k(e)?f:e}}function Z(e,u,a){if(!L(e)||!W(u))return;const f=K(u);if(f.length===0)return;const s=f.length;for(let t=0;t<s;t++){const l=f[t];if(t===s-1){e[l]=a;return}if(l==="*"&&$(e)){const o=f.slice(t+1).join(".");for(const i of e)Z(i,o,a);return}k(e[l])&&(e[l]={}),e=e[l]}}function K(e){const u=e.split(/[.]|(?:\[(\d|\*)\])/).filter(a=>!!a);return u.some(a=>J.indexOf(a)!==-1)?[]:u}var d=(e=>(e.text="text",e.number="number",e.email="email",e.password="password",e.tel="tel",e.url="url",e.search="search",e.date="date",e.time="time",e.datetimeLocal="datetime-local",e.month="month",e.week="week",e.color="color",e.select="select",e.checkbox="checkbox",e.radio="radio",e.textarea="textarea",e.radioGroup="radioGroup",e.checkboxGroup="checkboxGroup",e.combobox="combobox",e.custom="custom",e))(d||{}),I=(e=>(e.invalid="invalid",e.valid="valid",e))(I||{});const P=(e,u,a,f)=>r.defineComponent({name:"FieldComponent",props:{type:{type:String,validator:s=>Object.values(d).includes(s),default:d.custom},is:{type:[Object,String],default:void 0},name:{type:[String,Number,Boolean,Symbol],required:!0},props:{type:[Object,Function],default:()=>({})},showValid:{type:Boolean,default:!1},defaultValue:{type:[String,Number,Boolean,Array,Object],default:void 0},lazyLoad:{type:Boolean,default:!1}},emits:["invalid","valid","update:formData","update:modelValue"],expose:["invalid","invalidLabel","errors"],setup(s,{slots:t,emit:l}){const o=r.computed({get(){if(n!=null&&n.formData)return S(Object(n.formData.value),String(s.name))},set(c){n!=null&&n.formData&&(Z(Object(n.formData.value),String(s.name),c),l("update:modelValue",{newValue:o.value,formData:n==null?void 0:n.formData}))}});r.onMounted(()=>{o.value===void 0&&s.defaultValue!==void 0&&(o.value=s.defaultValue)}),r.onBeforeUnmount(()=>{x(),p()});const i=r.inject(u,void 0);i&&i.fields.value.add(s.name);const n=r.inject(e),{props:h,name:y}=r.toRefs(s),b=r.computed(()=>{if(n!=null&&n.errors.value)return S(n.errors.value,String(s.name))}),m=r.computed(()=>{var c;return(c=b.value)==null?void 0:c._errors}),v=r.computed(()=>b.value!==void 0),x=r.watch(v,()=>{v.value?(l("invalid",m.value),i&&i.errors.value.set(s.name,{_errors:m.value})):(l("valid",o.value),i&&i.errors.value.delete(s.name))}),p=r.watch(()=>n==null?void 0:n.formData,()=>{l("update:formData",n==null?void 0:n.formData)},{deep:!0}),g=c=>{o.value=c},_=r.computed(()=>{let c=h.value;return typeof c=="function"&&(c=c(n==null?void 0:n.formData)),Object.keys(c).reduce((C,O)=>(C[O]=r.unref(c[O]),C),{})}),N=r.computed(()=>({..._.value,name:_.value.name??s.name,invalid:v.value,valid:s.showValid?!!(!v.value&&o.value):void 0,type:(c=>{if([d.text,d.number,d.email,d.password,d.tel,d.url,d.search,d.date,d.time,d.datetimeLocal,d.month,d.week,d.color].includes(c))return c})(s.type),invalidLabel:m.value,modelValue:o.value,"onUpdate:modelValue":g}));return r.provide(a,{name:r.readonly(y),errors:r.readonly(b)}),{component:r.computed(()=>{if(s.type===d.custom)return{render(){var c;return((c=t.default)==null?void 0:c.call(t,{modelValue:o.value,onUpdate:g,submit:n==null?void 0:n.submit,validate:n==null?void 0:n.validate,invalid:v.value,invalidLabel:m.value,formData:n==null?void 0:n.formData.value,formErrors:n==null?void 0:n.errors.value,errors:b.value}))??t.defalut}};if(!((f==null?void 0:f.lazyLoad)??s.lazyLoad)){let c;switch(s.type){case d.select:c=r.resolveComponent("VvSelect");break;case d.checkbox:c=r.resolveComponent("VvCheckbox");break;case d.radio:c=r.resolveComponent("VvRadio");break;case d.textarea:c=r.resolveComponent("VvTextarea");break;case d.radioGroup:c=r.resolveComponent("VvRadioGroup");break;case d.checkboxGroup:c=r.resolveComponent("VvCheckboxGroup");break;case d.combobox:c=r.resolveComponent("VvCombobox");break;default:c=r.resolveComponent("VvInputText")}if(typeof c!="string")return c;console.warn(`[form-vue warn]: ${c} not found, the component will be loaded asynchronously. To avoid this warning, please set "lazyLoad" option.`)}return r.defineAsyncComponent(async()=>{switch(f!=null&&f.sideEffects&&await Promise.resolve(f.sideEffects(s.type)),s.type){case d.textarea:return import("@volverjs/ui-vue/vv-textarea");case d.radio:return import("@volverjs/ui-vue/vv-radio");case d.radioGroup:return import("@volverjs/ui-vue/vv-radio-group");case d.checkbox:return import("@volverjs/ui-vue/vv-checkbox");case d.checkboxGroup:return import("@volverjs/ui-vue/vv-checkbox-group");case d.select:return import("@volverjs/ui-vue/vv-select");case d.combobox:return import("@volverjs/ui-vue/vv-combobox")}return import("@volverjs/ui-vue/vv-input-text")})}),hasProps:N,invalid:v}},render(){return this.is?r.h(this.is,this.hasProps,this.$slots):this.type===d.custom?r.h(this.component,null,this.$slots):r.h(this.component,this.hasProps,this.$slots)}}),E=(e,u={})=>{const a=t=>{let l=t;for(;l instanceof w.ZodEffects;)l=l.innerType();return l instanceof w.ZodOptional&&(l=l._def.innerType),l},f=a(e);return{...(f instanceof w.ZodObject?f._def.unknownKeys==="passthrough":!1)?u:{},...Object.fromEntries(Object.entries(f.shape).map(([t,l])=>{const o=u[t];let i=a(l),n;if(i instanceof w.ZodDefault&&(n=i._def.defaultValue(),i=i._def.innerType),o===null&&i instanceof w.ZodNullable)return[t,o];if(i instanceof w.ZodSchema){const h=l.safeParse(o);if(h.success)return[t,h.data??n]}if(i instanceof w.ZodArray&&Array.isArray(o)&&o.length){const h=a(i._def.type);if(h instanceof w.ZodObject)return[t,o.map(y=>E(h,y&&typeof y=="object"?y:void 0))??n]}return i instanceof w.ZodObject?[t,E(i,o&&typeof o=="object"?o:n)]:[t,n]}))}},T=(e,u,a,f)=>{const s=r.ref(),t=r.ref(),l=r.ref(),o=r.defineComponent({name:"FormComponent",props:{modelValue:{type:Object,default:()=>({})},updateThrottle:{type:Number,default:500},continuosValidation:{type:Boolean,default:!1},template:{type:[Array,Function]}},emits:["invalid","valid","submit","update:modelValue"],expose:["submit","validate","errors","status","valid","invalid"],setup(i,{emit:n}){l.value=E(e,r.toRaw(i.modelValue)),r.watch(()=>i.modelValue,m=>{if(m){const v=r.isProxy(m)?r.toRaw(m):m;l.value=typeof(v==null?void 0:v.clone)=="function"?v.clone():JSON.parse(JSON.stringify(v))}},{deep:!0}),U.watchThrottled(l,m=>{var v;((s.value||(a==null?void 0:a.continuosValidation))??i.continuosValidation)&&h(),(!m||!i.modelValue||JSON.stringify(m)!==JSON.stringify(i.modelValue))&&(n("update:modelValue",m),(v=a==null?void 0:a.onUpdate)==null||v.call(a,r.toRaw(m)))},{deep:!0,throttle:(a==null?void 0:a.updateThrottle)??i.updateThrottle});const h=(m=l.value)=>{var x,p,g;const v=e.safeParse(m);return v.success?(s.value=void 0,t.value=I.valid,l.value=v.data,n("update:modelValue",l.value),(p=a==null?void 0:a.onUpdate)==null||p.call(a,r.toRaw(l.value)),n("valid",v.data),(g=a==null?void 0:a.onValid)==null||g.call(a,r.toRaw(l.value)),!0):(s.value=v.error.format(),t.value=I.invalid,n("invalid",s.value),(x=a==null?void 0:a.onInvalid)==null||x.call(a,r.toRaw(s.value)),!1)},y=()=>{var m;return h()?(n("submit",l.value),(m=a==null?void 0:a.onSubmit)==null||m.call(a,r.toRaw(l.value)),!0):!1},b=r.computed(()=>t.value===I.invalid);return r.provide(u,{formData:l,submit:y,validate:h,errors:r.readonly(s),status:r.readonly(t),invalid:b}),{formData:l,submit:y,validate:h,errors:r.readonly(s),status:r.readonly(t),invalid:b}},render(){return r.h("form",{onSubmit:r.withModifiers(this.submit,["prevent"])},(this.template??(a==null?void 0:a.template))&&f?[r.h(f,{schema:this.template??(a==null?void 0:a.template)})]:{default:()=>{var i,n;return((n=(i=this.$slots)==null?void 0:i.default)==null?void 0:n.call(i,{formData:this.formData,submit:this.submit,validate:this.validate,errors:this.errors,status:this.status,invalid:this.invalid}))??this.$slots.default}})}});return{errors:s,status:t,formData:l,VvForm:o}},z=(e,u)=>r.defineComponent({name:"WrapperComponent",props:{name:{type:String,required:!0},tag:{type:String,default:void 0}},emits:["invalid","valid"],expose:["fields","invalid"],setup(f,{emit:s}){const t=r.inject(e),l=r.inject(u,void 0),o=r.ref(new Set),i=r.ref(new Map),{name:n}=r.toRefs(f);r.provide(u,{name:r.readonly(n),errors:i,fields:o}),r.watch(o,y=>{l!=null&&l.fields&&y.forEach(b=>{l==null||l.fields.value.add(b)})},{deep:!0}),r.watch(()=>new Map(i.value),(y,b)=>{l!=null&&l.errors&&(Array.from(b.keys()).forEach(m=>{l.errors.value.delete(m)}),Array.from(y.keys()).forEach(m=>{const v=y.get(m);v&&l.errors.value.set(m,v)}))},{deep:!0});const h=r.computed(()=>t!=null&&t.invalid.value?i.value.size>0:!1);return r.watch(h,()=>{h.value?s("invalid"):s("valid")}),{formData:t==null?void 0:t.formData,errors:t==null?void 0:t.errors,submit:t==null?void 0:t.submit,validate:t==null?void 0:t.validate,invalid:h,fields:o,fieldsErrors:i}},render(){var f,s;return this.tag?r.h(this.tag,null,{default:()=>{var t,l;return((l=(t=this.$slots).default)==null?void 0:l.call(t,{invalid:this.invalid,formData:this.formData,submit:this.submit,validate:this.validate,errors:this.errors,fieldsErrors:this.fieldsErrors}))??this.$slots.defalut}}):((s=(f=this.$slots).default)==null?void 0:s.call(f,{invalid:this.invalid,formData:this.formData,submit:this.submit,validate:this.validate,errors:this.errors,fieldsErrors:this.fieldsErrors}))??this.$slots.defalut}}),H=(e,u)=>{const a=r.defineComponent({props:{schema:{type:[Array,Function],required:!0}},setup(f,{slots:s}){const t=r.inject(e);if(t!=null&&t.formData)return()=>{var i;const l=typeof f.schema=="function"?f.schema(t):f.schema;let o;return l.reduce((n,h)=>{const y=typeof h=="function"?h(t):h,{vvIs:b,vvName:m,vvSlots:v,vvChildren:x,vvIf:p,vvElseIf:g,vvType:_,vvDefaultValue:N,vvShowValid:R,vvContent:c,...C}=y;if(p!==void 0){if(typeof p=="string"?o=!!S(Object(t.formData.value),p):typeof p=="function"?o=r.unref(p(t)):o=r.unref(p),!o)return n}else if(g!==void 0&&o!==void 0){if(o||(typeof g=="string"?o=!!S(Object(t.formData.value),g):typeof g=="function"?o=r.unref(g(t)):o=r.unref(g),!o))return n}else o=void 0;const O=x?r.h(a,{schema:x}):void 0;return m?(n.push(r.h(u,{name:m,is:b,type:_,defaultValue:N,showValid:R,props:C},v??O??c)),n):b?(n.push(r.h(b,C,v??O??c)),n):(x&&n.push(O),n)},[(i=s==null?void 0:s.default)==null?void 0:i.call(s,{formData:t==null?void 0:t.formData.value,submit:t==null?void 0:t.submit,validate:t==null?void 0:t.validate,errors:t==null?void 0:t.errors.value,status:t==null?void 0:t.status.value,invalid:t==null?void 0:t.invalid.value})])}}});return a},A=(e,u={})=>{const a=Symbol(),f=Symbol(),s=Symbol(),t=z(a,f),l=P(a,f,s,u),o=H(a,l),{VvForm:i,errors:n,status:h,formData:y}=T(e,a,u,o);return{VvForm:i,VvFormWrapper:t,VvFormField:l,VvFormTemplate:o,formInjectionKey:a,formWrapperInjectionKey:f,formFieldInjectionKey:s,errors:n,status:h,formData:y}},B=Symbol(),Q=e=>{let u={};return e.schema&&(u=A(e.schema,e)),{...u,install(a,{global:f=!1}={}){a.provide(B,e),f&&(a.config.globalProperties.$vvForm=e,u!=null&&u.VvForm&&a.component("VvForm",u.VvForm),u!=null&&u.VvFormWrapper&&a.component("VvFormWrapper",u.VvFormWrapper),u!=null&&u.VvFormField&&a.component("VvFormField",u.VvFormField),u!=null&&u.VvFormTemplate&&a.component("VvFormTemplate",u.VvFormTemplate))}}},X=(e,u={})=>r.getCurrentInstance()?A(e,{...r.inject(B,{}),...u}):A(e,u),Y=(e,u={})=>A(e,u);V.FormFieldType=d,V.createForm=Q,V.defaultObjectBySchema=E,V.formFactory=Y,V.pluginInjectionKey=B,V.useForm=X,Object.defineProperty(V,Symbol.toStringTag,{value:"Module"})});
package/dist/types.d.ts CHANGED
@@ -1,132 +1,66 @@
1
- import type { Ref } from 'vue'
2
- import type { z, AnyZodObject, ZodEffects } from 'zod'
3
- import type { FormFieldType, FormStatus } from './enums'
4
-
5
- export type FormSchema =
6
- | AnyZodObject
7
- | ZodEffects<AnyZodObject>
8
- | ZodEffects<ZodEffects<AnyZodObject>>
9
-
1
+ import { type Component, type DeepReadonly, type Ref } from 'vue';
2
+ import type { z, AnyZodObject, ZodEffects, inferFormattedError } from 'zod';
3
+ import type { FormFieldType, FormStatus } from './enums';
4
+ export type FormSchema = AnyZodObject | ZodEffects<AnyZodObject> | ZodEffects<ZodEffects<AnyZodObject>>;
10
5
  export type FormFieldComponentOptions = {
11
- lazyLoad?: boolean
12
- sideEffects?: (type: `${FormFieldType}`) => Promise | void
13
- }
14
-
15
- export type FormComponentOptions = {
16
- updateThrottle?: number
17
- continuosValidation?: boolean
18
- }
19
-
20
- export type FormComposableOptions = FormFieldComponentOptions &
21
- FormComponentOptions
22
-
23
- export type FormPluginOptions = {
24
- schema?: ZodSchema
25
- } & FormComposableOptions
26
-
6
+ lazyLoad?: boolean;
7
+ sideEffects?: (type: `${FormFieldType}`) => Promise<void> | void;
8
+ };
9
+ export type FormComponentOptions<Schema> = {
10
+ updateThrottle?: number;
11
+ continuosValidation?: boolean;
12
+ template?: Schema extends FormSchema ? FormTemplate<Schema> : never;
13
+ onUpdate?: Schema extends FormSchema ? (data: Partial<z.infer<Schema> | undefined>) => void : never;
14
+ onSubmit?: Schema extends FormSchema ? (data: z.infer<Schema>) => void : never;
15
+ onInvalid?: Schema extends FormSchema ? (error: inferFormattedError<Schema, string>) => void : never;
16
+ onValid?: Schema extends FormSchema ? (data: z.infer<Schema>) => void : never;
17
+ };
18
+ export type FormComposableOptions<Schema> = FormFieldComponentOptions & FormComponentOptions<Schema>;
19
+ type FormPluginOptionsSchema = {
20
+ schema?: FormSchema;
21
+ };
22
+ export type FormPluginOptions = FormPluginOptionsSchema & FormComposableOptions<FormPluginOptionsSchema['schema']>;
27
23
  export type InjectedFormData<Schema extends FormSchema> = {
28
- formData: Ref<Partial<z.infer<Schema>> | undefined>
29
- errors: Readonly<Ref<DeepReadonly<z.inferFormattedError<Schema>>>>
30
- submit: () => boolean
31
- validate: () => boolean
32
- status: Readonly<Ref<FormStatus | undefined>>
33
- invalid: Readonly<Ref<boolean>>
34
- }
35
-
24
+ formData: Ref<Partial<z.infer<Schema>> | undefined>;
25
+ errors: Readonly<Ref<DeepReadonly<z.inferFormattedError<Schema>> | undefined>>;
26
+ submit: () => boolean;
27
+ validate: () => boolean;
28
+ status: Readonly<Ref<FormStatus | undefined>>;
29
+ invalid: Readonly<Ref<boolean>>;
30
+ };
36
31
  export type InjectedFormWrapperData<Schema extends FormSchema> = {
37
- name: Ref<string>
38
- fields: Ref<Set<string>>
39
- errors: Readonly<Ref<DeepReadonly<z.inferFormattedError<Schema>>>>
40
- }
41
-
32
+ name: Ref<string>;
33
+ fields: Ref<Set<string>>;
34
+ errors: Ref<Map<string, z.inferFormattedError<Schema, string>>>;
35
+ };
42
36
  export type InjectedFormFieldData<Schema extends FormSchema> = {
43
- name: Ref<string>
44
- errors: Readonly<Ref<DeepReadonly<z.inferFormattedError<Schema>>>>
45
- }
46
-
47
- export type Primitive =
48
- | null
49
- | undefined
50
- | string
51
- | number
52
- | boolean
53
- | symbol
54
- | bigint
55
-
56
- type ArrayKey = number
57
-
58
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
59
- type IsTuple<T extends readonly any[]> = number extends T['length']
60
- ? false
61
- : true
62
-
63
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
64
- type TupleKeys<T extends readonly any[]> = Exclude<keyof T, keyof any[]>
65
-
66
- export type PathConcat<
67
- TKey extends string | number,
68
- TValue,
69
- > = TValue extends Primitive ? `${TKey}` : `${TKey}` | `${TKey}.${Path<TValue>}`
70
-
71
- export type Path<T> = T extends readonly (infer V)[]
72
- ? IsTuple<T> extends true
73
- ? {
74
- [K in TupleKeys<T>]-?: PathConcat<K & string, T[K]>
75
- }[TupleKeys<T>]
76
- : PathConcat<ArrayKey, V>
77
- : {
78
- [K in keyof T]-?: PathConcat<K & string, T[K]>
79
- }[keyof T]
80
-
81
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
82
- export type PathValue<T, TPath extends Path<T> | ArrayPath<T>> = T extends any
83
- ? TPath extends `${infer K}.${infer R}`
84
- ? K extends keyof T
85
- ? R extends Path<T[K]>
86
- ? undefined extends T[K]
87
- ? PathValue<T[K], R> | undefined
88
- : PathValue<T[K], R>
89
- : never
90
- : K extends `${ArrayKey}`
91
- ? T extends readonly (infer V)[]
92
- ? PathValue<V, R & Path<V>>
93
- : never
94
- : never
95
- : TPath extends keyof T
96
- ? T[TPath]
97
- : TPath extends `${ArrayKey}`
98
- ? T extends readonly (infer V)[]
99
- ? V
100
- : never
101
- : never
102
- : never
103
-
104
- export type AnyBoolean<Schema> =
105
- | boolean
106
- | Ref<boolean>
107
- | ((data?: InjectedFormData<Schema>) => boolean | Ref<boolean>)
108
-
109
- export type SimpleFormTemplateItem<Schema extends FormSchema> = Record<
110
- string,
111
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
112
- any
113
- > & {
114
- vvIs?: string | Component
115
- vvName?: Path<z.infer<Schema>>
116
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
117
- vvSlots?: Record<string, any>
118
- vvChildren?: Array<
119
- | SimpleFormTemplateItem<Schema>
120
- | ((data?: InjectedFormData<Schema>) => SimpleFormTemplateItem<Schema>)
121
- >
122
- vvIf?: AnyBoolean<Schema> | Path<z.infer<Schema>>
123
- vvElseIf?: AnyBoolean<Schema> | Path<z.infer<Schema>>
124
- vvType?: `${FormFieldType}`
125
- vvShowValid?: boolean
126
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
127
- vvDefaultValue?: any
128
- }
129
-
130
- export type FormTemplateItem<Schema extends FormSchema> =
131
- | SimpleFormTemplateItem<Schema>
132
- | ((data?: InjectedFormData<Schema>) => SimpleFormTemplateItem<Schema>)
37
+ name: Ref<string>;
38
+ errors: Readonly<Ref<DeepReadonly<z.inferFormattedError<Schema>>>>;
39
+ };
40
+ export type Primitive = null | undefined | string | number | boolean | symbol | bigint;
41
+ type ArrayKey = number;
42
+ type IsTuple<T extends readonly any[]> = number extends T['length'] ? false : true;
43
+ type TupleKeys<T extends readonly any[]> = Exclude<keyof T, keyof any[]>;
44
+ export type PathConcat<TKey extends string | number, TValue> = TValue extends Primitive ? `${TKey}` : `${TKey}` | `${TKey}.${Path<TValue>}`;
45
+ export type Path<T> = T extends readonly (infer V)[] ? IsTuple<T> extends true ? {
46
+ [K in TupleKeys<T>]-?: PathConcat<K & string, T[K]>;
47
+ }[TupleKeys<T>] : PathConcat<ArrayKey, V> : {
48
+ [K in keyof T]-?: PathConcat<K & string, T[K]>;
49
+ }[keyof T];
50
+ export type PathValue<T, TPath extends Path<T> | Path<T>[]> = T extends any ? TPath extends `${infer K}.${infer R}` ? K extends keyof T ? R extends Path<T[K]> ? undefined extends T[K] ? PathValue<T[K], R> | undefined : PathValue<T[K], R> : never : K extends `${ArrayKey}` ? T extends readonly (infer V)[] ? PathValue<V, R & Path<V>> : never : never : TPath extends keyof T ? T[TPath] : TPath extends `${ArrayKey}` ? T extends readonly (infer V)[] ? V : never : never : never;
51
+ export type AnyBoolean<Schema extends FormSchema> = boolean | Ref<boolean> | ((data?: InjectedFormData<Schema>) => boolean | Ref<boolean>);
52
+ export type SimpleFormTemplateItem<Schema extends FormSchema> = Record<string, any> & {
53
+ vvIs?: string | Component;
54
+ vvName?: Path<z.infer<Schema>>;
55
+ vvSlots?: Record<string, any>;
56
+ vvChildren?: Array<SimpleFormTemplateItem<Schema> | ((data?: InjectedFormData<Schema>) => SimpleFormTemplateItem<Schema>)>;
57
+ vvIf?: AnyBoolean<Schema> | Path<z.infer<Schema>>;
58
+ vvElseIf?: AnyBoolean<Schema> | Path<z.infer<Schema>>;
59
+ vvType?: `${FormFieldType}`;
60
+ vvShowValid?: boolean;
61
+ vvContent?: string;
62
+ vvDefaultValue?: any;
63
+ };
64
+ export type FormTemplateItem<Schema extends FormSchema> = SimpleFormTemplateItem<Schema> | ((data?: InjectedFormData<Schema>) => SimpleFormTemplateItem<Schema>);
65
+ export type FormTemplate<Schema extends FormSchema> = FormTemplateItem<Schema>[] | ((data?: InjectedFormData<Schema>) => FormTemplateItem<Schema>[]);
66
+ export {};
package/package.json CHANGED
@@ -19,11 +19,11 @@
19
19
  "bugs": {
20
20
  "url": "https://github.com/volverjs/form-vue/issues"
21
21
  },
22
- "version": "0.0.14-beta.1",
22
+ "version": "0.0.14-beta.3",
23
23
  "engines": {
24
24
  "node": ">= 16.x"
25
25
  },
26
- "packageManager": "pnpm@7.8.0",
26
+ "packageManager": "pnpm@8.6.12",
27
27
  "type": "module",
28
28
  "main": "./dist/index.js",
29
29
  "module": "./dist/index.js",
@@ -35,34 +35,34 @@
35
35
  "*.d.ts"
36
36
  ],
37
37
  "dependencies": {
38
- "@volverjs/ui-vue": "^0.0.8",
39
- "@vueuse/core": "^10.3.0",
38
+ "@volverjs/ui-vue": "^0.0.9",
39
+ "@vueuse/core": "^10.4.1",
40
40
  "ts-dot-prop": "^2.1.3",
41
41
  "vue": "^3.3.4",
42
- "zod": "^3.21.4"
42
+ "zod": "^3.22.2"
43
43
  },
44
44
  "devDependencies": {
45
- "@playwright/experimental-ct-vue": "1.36.2",
45
+ "@playwright/experimental-ct-vue": "1.37.1",
46
46
  "@testing-library/vue": "^7.0.0",
47
- "@typescript-eslint/eslint-plugin": "^6.2.1",
48
- "@typescript-eslint/parser": "^6.2.1",
49
- "@vitejs/plugin-vue": "^4.2.3",
47
+ "@typescript-eslint/eslint-plugin": "^6.5.0",
48
+ "@typescript-eslint/parser": "^6.5.0",
49
+ "@vitejs/plugin-vue": "^4.3.4",
50
50
  "@volverjs/style": "^0.1.11",
51
51
  "@vue/compiler-sfc": "^3.3.4",
52
52
  "@vue/runtime-core": "^3.3.4",
53
53
  "@vue/test-utils": "^2.4.1",
54
54
  "copy": "^0.3.2",
55
- "eslint": "^8.46.0",
56
- "eslint-config-prettier": "^8.10.0",
55
+ "eslint": "^8.48.0",
56
+ "eslint-config-prettier": "^9.0.0",
57
57
  "eslint-plugin-prettier": "^5.0.0",
58
- "happy-dom": "^10.6.3",
59
- "prettier": "^3.0.1",
60
- "typescript": "^5.1.6",
61
- "vite": "^4.4.8",
58
+ "happy-dom": "^10.11.2",
59
+ "prettier": "^3.0.3",
60
+ "typescript": "^5.2.2",
61
+ "vite": "^4.4.9",
62
+ "vite-plugin-dts": "^3.5.3",
62
63
  "vite-plugin-eslint": "^1.8.1",
63
64
  "vite-plugin-externalize-deps": "^0.7.0",
64
- "vitest": "^0.34.1",
65
- "vue-tsc": "^1.8.8"
65
+ "vitest": "^0.34.3"
66
66
  },
67
67
  "typesVersions": {
68
68
  "*": {
@@ -83,7 +83,8 @@
83
83
  "scripts": {
84
84
  "lint": "eslint . --ext .js,.jsx,.ts,.tsx",
85
85
  "type-check": "tsc --noEmit",
86
- "build": "vite build && vue-tsc --declaration --emitDeclarationOnly && copy src/**/types.d.ts dist",
86
+ "build": "vite build",
87
+ "dev": "vite build --watch",
87
88
  "test": "pnpm run test-vitest && pnpm run test-playwright",
88
89
  "test-vitest": "vitest run",
89
90
  "test-vitest-watch": "vitest",
package/src/VvForm.ts CHANGED
@@ -1,7 +1,9 @@
1
1
  import {
2
+ type Component,
2
3
  type InjectionKey,
3
4
  type DeepReadonly,
4
5
  type Ref,
6
+ type PropType,
5
7
  withModifiers,
6
8
  defineComponent,
7
9
  ref,
@@ -18,6 +20,7 @@ import type { z, ZodFormattedError, TypeOf } from 'zod'
18
20
  import type {
19
21
  FormComponentOptions,
20
22
  FormSchema,
23
+ FormTemplate,
21
24
  InjectedFormData,
22
25
  } from './types'
23
26
  import { FormStatus } from './enums'
@@ -26,9 +29,10 @@ import { defaultObjectBySchema } from './utils'
26
29
  export const defineForm = <Schema extends FormSchema>(
27
30
  schema: Schema,
28
31
  provideKey: InjectionKey<InjectedFormData<Schema>>,
29
- options?: FormComponentOptions,
32
+ options?: FormComponentOptions<Schema>,
33
+ VvFormTemplate?: Component,
30
34
  ) => {
31
- const errors = ref<ZodFormattedError<z.infer<Schema>>>()
35
+ const errors = ref<z.inferFormattedError<Schema> | undefined>()
32
36
  const status = ref<FormStatus | undefined>()
33
37
  const formData = ref<Partial<z.infer<Schema> | undefined>>()
34
38
  const component = defineComponent({
@@ -46,6 +50,9 @@ export const defineForm = <Schema extends FormSchema>(
46
50
  type: Boolean,
47
51
  default: false,
48
52
  },
53
+ template: {
54
+ type: [Array, Function] as PropType<FormTemplate<Schema>>,
55
+ },
49
56
  },
50
57
  emits: ['invalid', 'valid', 'submit', 'update:modelValue'],
51
58
  expose: ['submit', 'validate', 'errors', 'status', 'valid', 'invalid'],
@@ -89,6 +96,7 @@ export const defineForm = <Schema extends FormSchema>(
89
96
  JSON.stringify(props.modelValue)
90
97
  ) {
91
98
  emit('update:modelValue', newValue)
99
+ options?.onUpdate?.(toRaw(newValue))
92
100
  }
93
101
  },
94
102
  {
@@ -107,13 +115,16 @@ export const defineForm = <Schema extends FormSchema>(
107
115
  >
108
116
  status.value = FormStatus.invalid
109
117
  emit('invalid', errors.value)
118
+ options?.onInvalid?.(toRaw(errors.value))
110
119
  return false
111
120
  }
112
121
  errors.value = undefined
113
122
  status.value = FormStatus.valid
114
123
  formData.value = parseResult.data
115
124
  emit('update:modelValue', formData.value)
125
+ options?.onUpdate?.(toRaw(formData.value))
116
126
  emit('valid', parseResult.data)
127
+ options?.onValid?.(toRaw(formData.value))
117
128
  return true
118
129
  }
119
130
 
@@ -122,7 +133,8 @@ export const defineForm = <Schema extends FormSchema>(
122
133
  if (!validate()) {
123
134
  return false
124
135
  }
125
- emit('submit', formData.value)
136
+ emit('submit', formData.value as z.infer<Schema>)
137
+ options?.onSubmit?.(toRaw(formData.value) as z.infer<Schema>)
126
138
  return true
127
139
  }
128
140
 
@@ -153,17 +165,23 @@ export const defineForm = <Schema extends FormSchema>(
153
165
  {
154
166
  onSubmit: withModifiers(this.submit, ['prevent']),
155
167
  },
156
- {
157
- default: () =>
158
- this.$slots?.default?.({
159
- formData: this.formData,
160
- submit: this.submit,
161
- validate: this.validate,
162
- errors: this.errors,
163
- status: this.status,
164
- invalid: this.invalid,
165
- }) ?? this.$slots.default,
166
- },
168
+ (this.template ?? options?.template) && VvFormTemplate
169
+ ? [
170
+ h(VvFormTemplate, {
171
+ schema: this.template ?? options?.template,
172
+ }),
173
+ ]
174
+ : {
175
+ default: () =>
176
+ this.$slots?.default?.({
177
+ formData: this.formData,
178
+ submit: this.submit,
179
+ validate: this.validate,
180
+ errors: this.errors,
181
+ status: this.status,
182
+ invalid: this.invalid,
183
+ }) ?? this.$slots.default,
184
+ },
167
185
  )
168
186
  },
169
187
  })
@@ -151,7 +151,7 @@ export const defineFormField = <Schema extends FormSchema>(
151
151
  props.name as string,
152
152
  {
153
153
  _errors: invalidLabel.value,
154
- },
154
+ } as z.inferFormattedError<Schema>,
155
155
  )
156
156
  }
157
157
  } else {
@@ -12,35 +12,30 @@ import {
12
12
  unref,
13
13
  } from 'vue'
14
14
  import type { TypeOf, z } from 'zod'
15
- import type { FormSchema, InjectedFormData, FormTemplateItem } from './types'
15
+ import type { FormSchema, InjectedFormData, FormTemplate } from './types'
16
16
  import type { FormStatus } from './enums'
17
17
 
18
18
  export const defineFormTemplate = <Schema extends FormSchema>(
19
19
  formProvideKey: InjectionKey<InjectedFormData<Schema>>,
20
20
  VvFormField: Component,
21
21
  ) => {
22
- const VvFormTemplate: Component = defineComponent({
22
+ const VvFormTemplate = defineComponent({
23
23
  props: {
24
24
  schema: {
25
- type: [Array, Function] as PropType<
26
- | FormTemplateItem<Schema>[]
27
- | ((
28
- data?: InjectedFormData<Schema>,
29
- ) => FormTemplateItem<Schema>[])
30
- >,
25
+ type: [Array, Function] as PropType<FormTemplate<Schema>>,
31
26
  required: true,
32
27
  },
33
28
  },
34
29
  setup(templateProps, { slots: templateSlots }) {
35
30
  const injectedFormData = inject(formProvideKey)
36
31
  if (!injectedFormData?.formData) return
37
- const normalizedSchema =
38
- typeof templateProps.schema === 'function'
39
- ? templateProps.schema(injectedFormData)
40
- : templateProps.schema
41
- let lastIf: boolean | undefined = undefined
42
- return () =>
43
- normalizedSchema.reduce<(VNode | VNode[] | undefined)[]>(
32
+ return () => {
33
+ const normalizedSchema =
34
+ typeof templateProps.schema === 'function'
35
+ ? templateProps.schema(injectedFormData)
36
+ : templateProps.schema
37
+ let lastIf: boolean | undefined = undefined
38
+ return normalizedSchema.reduce<(VNode | VNode[] | undefined)[]>(
44
39
  (acc, field) => {
45
40
  const normalizedField =
46
41
  typeof field === 'function'
@@ -56,6 +51,7 @@ export const defineFormTemplate = <Schema extends FormSchema>(
56
51
  vvType,
57
52
  vvDefaultValue,
58
53
  vvShowValid,
54
+ vvContent,
59
55
  ...props
60
56
  } = normalizedField
61
57
 
@@ -120,7 +116,7 @@ export const defineFormTemplate = <Schema extends FormSchema>(
120
116
  showValid: vvShowValid,
121
117
  props,
122
118
  },
123
- vvSlots ?? hChildren,
119
+ vvSlots ?? hChildren ?? vvContent,
124
120
  ),
125
121
  )
126
122
  return acc
@@ -130,7 +126,7 @@ export const defineFormTemplate = <Schema extends FormSchema>(
130
126
  h(
131
127
  vvIs as Component,
132
128
  props,
133
- vvSlots ?? hChildren,
129
+ vvSlots ?? hChildren ?? vvContent,
134
130
  ),
135
131
  )
136
132
  return acc
@@ -152,6 +148,7 @@ export const defineFormTemplate = <Schema extends FormSchema>(
152
148
  }),
153
149
  ],
154
150
  )
151
+ }
155
152
  },
156
153
  })
157
154
 
@@ -42,7 +42,7 @@ export const defineFormWrapper = <Schema extends FormSchema>(
42
42
  const wrapperProvided = inject(wrapperProvideKey, undefined)
43
43
  const fields = ref(new Set<string>())
44
44
  const fieldsErrors: Ref<
45
- Map<string, Record<string, { _errors: string[] }>>
45
+ Map<string, z.inferFormattedError<Schema>>
46
46
  > = ref(new Map())
47
47
  const { name } = toRefs(props)
48
48
 
package/src/index.ts CHANGED
@@ -19,11 +19,13 @@ import type {
19
19
  Path,
20
20
  PathValue,
21
21
  FormSchema,
22
+ FormTemplate,
22
23
  } from './types'
24
+ import type { AnyZodObject } from 'zod'
23
25
 
24
26
  const _formFactory = <Schema extends FormSchema>(
25
27
  schema: Schema,
26
- options: FormComposableOptions = {},
28
+ options: FormComposableOptions<Schema> = {},
27
29
  ) => {
28
30
  // create injection keys
29
31
  const formInjectionKey = Symbol() as InjectionKey<InjectedFormData<Schema>>
@@ -35,11 +37,6 @@ const _formFactory = <Schema extends FormSchema>(
35
37
  >
36
38
 
37
39
  // create components
38
- const { VvForm, errors, status, formData } = defineForm(
39
- schema,
40
- formInjectionKey,
41
- options,
42
- )
43
40
  const VvFormWrapper = defineFormWrapper(
44
41
  formInjectionKey,
45
42
  formWrapperInjectionKey,
@@ -51,6 +48,12 @@ const _formFactory = <Schema extends FormSchema>(
51
48
  options,
52
49
  )
53
50
  const VvFormTemplate = defineFormTemplate(formInjectionKey, VvFormField)
51
+ const { VvForm, errors, status, formData } = defineForm(
52
+ schema,
53
+ formInjectionKey,
54
+ options,
55
+ VvFormTemplate,
56
+ )
54
57
 
55
58
  return {
56
59
  VvForm,
@@ -73,7 +76,7 @@ export const createForm = (
73
76
  ): Plugin & Partial<ReturnType<typeof useForm>> => {
74
77
  let toReturn: Partial<ReturnType<typeof useForm>> = {}
75
78
  if (options.schema) {
76
- toReturn = _formFactory(options.schema, options)
79
+ toReturn = _formFactory(options.schema as AnyZodObject, options)
77
80
  }
78
81
  return {
79
82
  ...toReturn,
@@ -102,15 +105,18 @@ export const createForm = (
102
105
 
103
106
  export const useForm = <Schema extends FormSchema>(
104
107
  schema: Schema,
105
- options: FormComposableOptions = {},
108
+ options: FormComposableOptions<Schema> = {},
106
109
  ) => {
107
110
  if (!getCurrentInstance()) {
108
111
  return _formFactory(schema, options)
109
112
  }
110
- return _formFactory(schema, {
111
- ...inject(pluginInjectionKey, {}),
112
- ...options,
113
- })
113
+ return _formFactory(
114
+ schema as AnyZodObject,
115
+ {
116
+ ...inject(pluginInjectionKey, {}),
117
+ ...options,
118
+ } as FormComposableOptions<AnyZodObject>,
119
+ )
114
120
  }
115
121
 
116
122
  export { FormFieldType } from './enums'
@@ -130,6 +136,7 @@ export type {
130
136
  FormComponent,
131
137
  FormWrapperComponent,
132
138
  FormFieldComponent,
139
+ FormTemplate,
133
140
  FormTemplateComponent,
134
141
  FormTemplateItem,
135
142
  Path,
@@ -141,7 +148,7 @@ export type {
141
148
  */
142
149
  export const formFactory = <Schema extends FormSchema>(
143
150
  schema: Schema,
144
- options: FormComposableOptions = {},
151
+ options: FormComposableOptions<Schema> = {},
145
152
  ) => {
146
153
  return _formFactory(schema, options)
147
154
  }