@macrulez/vue-form-schema 0.1.0 → 0.1.5

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.
Files changed (51) hide show
  1. package/README.md +707 -410
  2. package/dist/MaskEngine-BqJQYybS.js +233 -0
  3. package/dist/MaskEngine-BwAs2Zb0.cjs +1 -0
  4. package/dist/__tests__/phase3.test.d.ts +2 -0
  5. package/dist/__tests__/phase3.test.d.ts.map +1 -0
  6. package/dist/__tests__/phase4.test.d.ts +2 -0
  7. package/dist/__tests__/phase4.test.d.ts.map +1 -0
  8. package/dist/__tests__/useFieldArray.test.d.ts +2 -0
  9. package/dist/__tests__/useFieldArray.test.d.ts.map +1 -0
  10. package/dist/__tests__/useMultiStepForm.test.d.ts +2 -0
  11. package/dist/__tests__/useMultiStepForm.test.d.ts.map +1 -0
  12. package/dist/core/ConditionEvaluator.d.ts +1 -1
  13. package/dist/core/ConditionEvaluator.d.ts.map +1 -1
  14. package/dist/core/ValidationEngine.d.ts +3 -1
  15. package/dist/core/ValidationEngine.d.ts.map +1 -1
  16. package/dist/core/inferTypes.d.ts +39 -0
  17. package/dist/core/inferTypes.d.ts.map +1 -0
  18. package/dist/core/registry.d.ts +17 -0
  19. package/dist/core/registry.d.ts.map +1 -0
  20. package/dist/core/schemaUtils.d.ts +20 -0
  21. package/dist/core/schemaUtils.d.ts.map +1 -0
  22. package/dist/core/types.d.ts +43 -3
  23. package/dist/core/types.d.ts.map +1 -1
  24. package/dist/core/useFieldArray.d.ts +21 -0
  25. package/dist/core/useFieldArray.d.ts.map +1 -0
  26. package/dist/core/useForm.d.ts.map +1 -1
  27. package/dist/core/useFormDebug.d.ts +29 -0
  28. package/dist/core/useFormDebug.d.ts.map +1 -0
  29. package/dist/core/useFormField.d.ts +18 -0
  30. package/dist/core/useFormField.d.ts.map +1 -0
  31. package/dist/core/useMultiStepForm.d.ts +30 -0
  32. package/dist/core/useMultiStepForm.d.ts.map +1 -0
  33. package/dist/index.cjs +1 -1
  34. package/dist/index.d.ts +14 -2
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +386 -196
  37. package/dist/parsers/valibot.d.ts +20 -0
  38. package/dist/parsers/valibot.d.ts.map +1 -0
  39. package/dist/ui/index.d.ts +2 -0
  40. package/dist/ui/index.d.ts.map +1 -1
  41. package/dist/ui.cjs +1 -1
  42. package/dist/ui.d.ts +114 -18
  43. package/dist/ui.js +360 -193
  44. package/dist/valibot.cjs +1 -0
  45. package/dist/valibot.d.ts +84 -0
  46. package/dist/valibot.js +43 -0
  47. package/dist/yup.d.ts +26 -2
  48. package/dist/zod.d.ts +26 -2
  49. package/package.json +39 -4
  50. package/dist/MaskEngine-D22m29OM.js +0 -157
  51. package/dist/MaskEngine-hd5xHed7.cjs +0 -1
@@ -0,0 +1,20 @@
1
+ import type { FieldDefinition } from '../core/types';
2
+ type ValibotSchema = any;
3
+ /**
4
+ * Convert a Valibot `v.object(...)` schema into a `FieldDefinition[]`.
5
+ *
6
+ * Supported field types: string → text, number, boolean → checkbox,
7
+ * picklist/enum → select, array, object → group.
8
+ * `v.optional()` / `v.nullable()` wrappers set `required: false`.
9
+ * `v.pipe(v.string(), v.email())` sets `type: 'email'`.
10
+ *
11
+ * @example
12
+ * import * as v from 'valibot'
13
+ * import { parseValibot } from '@macrulez/vue-form-schema/valibot'
14
+ *
15
+ * const schema = v.object({ email: v.pipe(v.string(), v.email()), age: v.number() })
16
+ * const fields = parseValibot(schema)
17
+ */
18
+ export declare function parseValibot(schema: ValibotSchema): FieldDefinition[];
19
+ export {};
20
+ //# sourceMappingURL=valibot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"valibot.d.ts","sourceRoot":"","sources":["../../src/parsers/valibot.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAA0B,MAAM,eAAe,CAAA;AAI5E,KAAK,aAAa,GAAG,GAAG,CAAA;AAExB;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,aAAa,GAAG,eAAe,EAAE,CAQrE"}
@@ -1,4 +1,5 @@
1
1
  export { default as FormRenderer } from './FormRenderer.vue';
2
+ export { default as MultiStepFormRenderer } from './MultiStepFormRenderer.vue';
2
3
  export { default as TextField } from './fields/TextField.vue';
3
4
  export { default as NumberField } from './fields/NumberField.vue';
4
5
  export { default as TextareaField } from './fields/TextareaField.vue';
@@ -6,4 +7,5 @@ export { default as SelectField } from './fields/SelectField.vue';
6
7
  export { default as CheckboxField } from './fields/CheckboxField.vue';
7
8
  export { default as RadioField } from './fields/RadioField.vue';
8
9
  export { default as DateField } from './fields/DateField.vue';
10
+ export { default as ArrayField } from './fields/ArrayField.vue';
9
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ui/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAC5D,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,wBAAwB,CAAA;AAC7D,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,0BAA0B,CAAA;AACjE,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,4BAA4B,CAAA;AACrE,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,0BAA0B,CAAA;AACjE,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,4BAA4B,CAAA;AACrE,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,yBAAyB,CAAA;AAC/D,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,wBAAwB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ui/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAC5D,OAAO,EAAE,OAAO,IAAI,qBAAqB,EAAE,MAAM,6BAA6B,CAAA;AAC9E,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,wBAAwB,CAAA;AAC7D,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,0BAA0B,CAAA;AACjE,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,4BAA4B,CAAA;AACrE,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,0BAA0B,CAAA;AACjE,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,4BAA4B,CAAA;AACrE,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,yBAAyB,CAAA;AAC/D,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,wBAAwB,CAAA;AAC7D,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,yBAAyB,CAAA"}
package/dist/ui.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("vue"),V=require("./MaskEngine-hd5xHed7.cjs"),N=["for"],q={key:0,class:"vfs-field__required","aria-hidden":"true"},D={key:1,class:"vfs-field__errors",role:"alert"},f=e.defineComponent({__name:"BaseField",props:{field:{},error:{},touched:{type:Boolean}},setup(t){const d=t;return(n,c)=>{var o,l;return e.openBlock(),e.createElementBlock("div",{class:e.normalizeClass(["vfs-field",[`vfs-field--${d.field.type}`,{"vfs-field--error":t.touched&&((o=t.error)==null?void 0:o.length)}]])},[d.field.label?(e.openBlock(),e.createElementBlock("label",{key:0,for:d.field.name,class:"vfs-field__label"},[e.createTextVNode(e.toDisplayString(d.field.label)+" ",1),d.field.required?(e.openBlock(),e.createElementBlock("span",q,"*")):e.createCommentVNode("",!0)],8,N)):e.createCommentVNode("",!0),e.renderSlot(n.$slots,"default"),t.touched&&((l=t.error)!=null&&l.length)?(e.openBlock(),e.createElementBlock("ul",D,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(t.error,(u,i)=>(e.openBlock(),e.createElementBlock("li",{key:i,class:"vfs-field__error"},e.toDisplayString(u),1))),128))])):e.createCommentVNode("",!0)],2)}}}),w=["id","type","name","value","placeholder","disabled","required"],k=e.defineComponent({__name:"TextField",props:{field:{},modelValue:{},error:{},touched:{type:Boolean}},emits:["update:modelValue","blur"],setup(t,{emit:d}){const n=t,c=d,o=e.ref(null);let l=null;e.onMounted(()=>{o.value&&n.field.mask&&(l=V.bindMask(o.value,n.field.mask))}),e.onUnmounted(()=>l==null?void 0:l());function u(i){c("update:modelValue",i.target.value)}return(i,s)=>(e.openBlock(),e.createBlock(f,{field:t.field,error:t.error,touched:t.touched},{default:e.withCtx(()=>[e.createElementVNode("input",{id:t.field.name,ref_key:"inputRef",ref:o,type:t.field.type==="email"?"email":"text",name:t.field.name,value:t.modelValue,placeholder:t.field.placeholder,disabled:t.field.disabled===!0,required:t.field.required,class:"vfs-input",onInput:u,onBlur:s[0]||(s[0]=b=>c("blur"))},null,40,w)]),_:1},8,["field","error","touched"]))}}),p=["id","name","value","placeholder","disabled","required"],y=e.defineComponent({__name:"NumberField",props:{field:{},modelValue:{},error:{},touched:{type:Boolean}},emits:["update:modelValue","blur"],setup(t,{emit:d}){const n=d;function c(o){const l=o.target.value;n("update:modelValue",l===""?null:Number(l))}return(o,l)=>(e.openBlock(),e.createBlock(f,{field:t.field,error:t.error,touched:t.touched},{default:e.withCtx(()=>[e.createElementVNode("input",{id:t.field.name,type:"number",name:t.field.name,value:t.modelValue??"",placeholder:t.field.placeholder,disabled:t.field.disabled===!0,required:t.field.required,class:"vfs-input",onInput:c,onBlur:l[0]||(l[0]=u=>n("blur"))},null,40,p)]),_:1},8,["field","error","touched"]))}}),R=["id","name","value","placeholder","disabled","required"],$=e.defineComponent({__name:"TextareaField",props:{field:{},modelValue:{},error:{},touched:{type:Boolean}},emits:["update:modelValue","blur"],setup(t,{emit:d}){const n=d;return(c,o)=>(e.openBlock(),e.createBlock(f,{field:t.field,error:t.error,touched:t.touched},{default:e.withCtx(()=>[e.createElementVNode("textarea",{id:t.field.name,name:t.field.name,value:t.modelValue,placeholder:t.field.placeholder,disabled:t.field.disabled===!0,required:t.field.required,class:"vfs-textarea",onInput:o[0]||(o[0]=l=>n("update:modelValue",l.target.value)),onBlur:o[1]||(o[1]=l=>n("blur"))},null,40,R)]),_:1},8,["field","error","touched"]))}}),T=["id","name","disabled","required"],L=["selected"],I=["value","selected"],g=e.defineComponent({__name:"SelectField",props:{field:{},modelValue:{},error:{},touched:{type:Boolean}},emits:["update:modelValue","blur"],setup(t,{emit:d}){const n=t,c=d;function o(l){var s;const u=l.target,i=(s=n.field.options)==null?void 0:s.find(b=>String(b.value)===u.value);c("update:modelValue",(i==null?void 0:i.value)??u.value)}return(l,u)=>(e.openBlock(),e.createBlock(f,{field:t.field,error:t.error,touched:t.touched},{default:e.withCtx(()=>[e.createElementVNode("select",{id:t.field.name,name:t.field.name,disabled:t.field.disabled===!0,required:t.field.required,class:"vfs-select",onChange:o,onBlur:u[0]||(u[0]=i=>c("blur"))},[e.createElementVNode("option",{value:"",disabled:"",selected:t.modelValue===null||t.modelValue===void 0||t.modelValue===""},e.toDisplayString(t.field.placeholder??"Select an option"),9,L),(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(t.field.options,i=>(e.openBlock(),e.createElementBlock("option",{key:String(i.value),value:String(i.value),selected:t.modelValue===i.value},e.toDisplayString(i.label),9,I))),128))],40,T)]),_:1},8,["field","error","touched"]))}}),M={class:"vfs-checkbox-label"},U=["id","name","checked","disabled","required"],P={key:0,class:"vfs-checkbox-text"},C=e.defineComponent({__name:"CheckboxField",props:{field:{},modelValue:{type:Boolean},error:{},touched:{type:Boolean}},emits:["update:modelValue","blur"],setup(t,{emit:d}){const n=d;return(c,o)=>(e.openBlock(),e.createBlock(f,{field:{...t.field,label:void 0},error:t.error,touched:t.touched},{default:e.withCtx(()=>[e.createElementVNode("label",M,[e.createElementVNode("input",{id:t.field.name,type:"checkbox",name:t.field.name,checked:t.modelValue,disabled:t.field.disabled===!0,required:t.field.required,class:"vfs-checkbox",onChange:o[0]||(o[0]=l=>n("update:modelValue",l.target.checked)),onBlur:o[1]||(o[1]=l=>n("blur"))},null,40,U),t.field.label?(e.openBlock(),e.createElementBlock("span",P,e.toDisplayString(t.field.label),1)):e.createCommentVNode("",!0)])]),_:1},8,["field","error","touched"]))}}),j=["aria-labelledby"],z=["name","value","checked","disabled","onChange"],x=e.defineComponent({__name:"RadioField",props:{field:{},modelValue:{},error:{},touched:{type:Boolean}},emits:["update:modelValue","blur"],setup(t,{emit:d}){const n=d;return(c,o)=>(e.openBlock(),e.createBlock(f,{field:t.field,error:t.error,touched:t.touched},{default:e.withCtx(()=>[e.createElementVNode("div",{class:"vfs-radio-group",role:"radiogroup","aria-labelledby":t.field.name+"-label"},[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(t.field.options,l=>(e.openBlock(),e.createElementBlock("label",{key:String(l.value),class:"vfs-radio-label"},[e.createElementVNode("input",{type:"radio",name:t.field.name,value:String(l.value),checked:t.modelValue===l.value,disabled:t.field.disabled===!0,class:"vfs-radio",onChange:u=>n("update:modelValue",l.value),onBlur:o[0]||(o[0]=u=>n("blur"))},null,40,z),e.createTextVNode(" "+e.toDisplayString(l.label),1)]))),128))],8,j)]),_:1},8,["field","error","touched"]))}}),O=["id","name","value","disabled","required"],E=e.defineComponent({__name:"DateField",props:{field:{},modelValue:{},error:{},touched:{type:Boolean}},emits:["update:modelValue","blur"],setup(t,{emit:d}){const n=d;return(c,o)=>(e.openBlock(),e.createBlock(f,{field:t.field,error:t.error,touched:t.touched},{default:e.withCtx(()=>[e.createElementVNode("input",{id:t.field.name,type:"date",name:t.field.name,value:t.modelValue,disabled:t.field.disabled===!0,required:t.field.required,class:"vfs-input",onInput:o[0]||(o[0]=l=>n("update:modelValue",l.target.value)),onBlur:o[1]||(o[1]=l=>n("blur"))},null,40,O)]),_:1},8,["field","error","touched"]))}}),A={key:1,class:"vfs-group"},G={key:0},H=["disabled"],J=e.defineComponent({__name:"FormRenderer",props:{form:{},components:{},submitLabel:{}},emits:["submit"],setup(t,{emit:d}){const n=t,c=d,o={text:k,email:k,number:y,textarea:$,select:g,checkbox:C,radio:x,date:E};function l(a){var m;return((m=n.components)==null?void 0:m[a])??o[a]??null}function u(a){return V.getByPath(n.form.values.value,a.name)}function i(a,m){n.form.setField(a.name,m)}function s(a){var v;const m=n.form;(v=m.touchField)==null||v.call(m,a.name)}function b(a){return n.form.errors.value[a.name]??[]}function B(a){return n.form.touched.value[a.name]??!1}const S=e.computed(()=>n.form.fields.value.filter(a=>a.visible!==!1));async function F(a){a.preventDefault(),await n.form.submit(),c("submit")}return(a,m)=>{const v=e.resolveComponent("FormRenderer",!0);return e.openBlock(),e.createElementBlock("form",{class:"vfs-form",novalidate:"",onSubmit:F},[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(S.value,r=>(e.openBlock(),e.createElementBlock(e.Fragment,{key:r.name},[a.$slots[`field-${r.name}`]?e.renderSlot(a.$slots,`field-${r.name}`,{key:0,field:r,value:u(r),error:b(r),touched:B(r),setValue:h=>i(r,h),touch:()=>s(r)}):r.type==="group"?(e.openBlock(),e.createElementBlock("fieldset",A,[r.label?(e.openBlock(),e.createElementBlock("legend",G,e.toDisplayString(r.label),1)):e.createCommentVNode("",!0),r.fields?(e.openBlock(),e.createBlock(v,{key:1,form:t.form,components:t.components},null,8,["form","components"])):e.createCommentVNode("",!0)])):l(r.type)?(e.openBlock(),e.createBlock(e.resolveDynamicComponent(l(r.type)),{key:2,field:r,"model-value":u(r),error:b(r),touched:B(r),"onUpdate:modelValue":h=>i(r,h),onBlur:h=>s(r)},e.createSlots({_:2},[a.$slots[`label-${r.name}`]?{name:"label",fn:e.withCtx(()=>[e.renderSlot(a.$slots,`label-${r.name}`,{field:r})]),key:"0"}:void 0,a.$slots[`error-${r.name}`]?{name:"error",fn:e.withCtx(()=>[e.renderSlot(a.$slots,`error-${r.name}`,{field:r,error:b(r)})]),key:"1"}:void 0]),1064,["field","model-value","error","touched","onUpdate:modelValue","onBlur"])):e.createCommentVNode("",!0)],64))),128)),e.renderSlot(a.$slots,"submit",{isSubmitting:t.form.isSubmitting.value,isValid:t.form.isValid.value},()=>[e.createElementVNode("button",{type:"submit",disabled:t.form.isSubmitting.value,class:"vfs-submit"},e.toDisplayString(t.submitLabel??"Submit"),9,H)])],32)}}});exports.CheckboxField=C;exports.DateField=E;exports.FormRenderer=J;exports.NumberField=y;exports.RadioField=x;exports.SelectField=g;exports.TextField=k;exports.TextareaField=$;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("vue"),h=require("./MaskEngine-BwAs2Zb0.cjs"),L=["for"],D={key:0,class:"vfs-field__required","aria-hidden":"true"},w=["id"],B=e.defineComponent({__name:"BaseField",props:{field:{},error:{},touched:{type:Boolean}},setup(t){const a=t;return(n,u)=>{var o,r;return e.openBlock(),e.createElementBlock("div",{class:e.normalizeClass(["vfs-field",[`vfs-field--${a.field.type}`,{"vfs-field--error":t.touched&&((o=t.error)==null?void 0:o.length)}]])},[a.field.label?(e.openBlock(),e.createElementBlock("label",{key:0,for:a.field.name,class:"vfs-field__label"},[e.createTextVNode(e.toDisplayString(a.field.label)+" ",1),a.field.required?(e.openBlock(),e.createElementBlock("span",D,"*")):e.createCommentVNode("",!0)],8,L)):e.createCommentVNode("",!0),e.renderSlot(n.$slots,"default"),t.touched&&((r=t.error)!=null&&r.length)?(e.openBlock(),e.createElementBlock("ul",{key:1,id:`${a.field.name}-error`,class:"vfs-field__errors",role:"alert","aria-live":"polite"},[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(t.error,(f,c)=>(e.openBlock(),e.createElementBlock("li",{key:c,class:"vfs-field__error"},e.toDisplayString(f),1))),128))],8,w)):e.createCommentVNode("",!0)],2)}}}),R=["id","type","name","value","placeholder","disabled","required"],y=e.defineComponent({__name:"TextField",props:{field:{},modelValue:{},error:{},touched:{type:Boolean}},emits:["update:modelValue","blur"],setup(t,{emit:a}){const n=t,u=a,o=e.ref(null);let r=null;e.onMounted(()=>{o.value&&n.field.mask&&(r=h.bindMask(o.value,n.field.mask))}),e.onUnmounted(()=>r==null?void 0:r());function f(c){u("update:modelValue",c.target.value)}return(c,i)=>(e.openBlock(),e.createBlock(B,{field:t.field,error:t.error,touched:t.touched},{default:e.withCtx(()=>[e.createElementVNode("input",{id:t.field.name,ref_key:"inputRef",ref:o,type:t.field.type==="email"?"email":"text",name:t.field.name,value:t.modelValue,placeholder:t.field.placeholder,disabled:t.field.disabled===!0,required:t.field.required,class:"vfs-input",onInput:f,onBlur:i[0]||(i[0]=k=>u("blur"))},null,40,R)]),_:1},8,["field","error","touched"]))}}),T=["id","name","value","placeholder","disabled","required"],$=e.defineComponent({__name:"NumberField",props:{field:{},modelValue:{},error:{},touched:{type:Boolean}},emits:["update:modelValue","blur"],setup(t,{emit:a}){const n=a;function u(o){const r=o.target.value;n("update:modelValue",r===""?null:Number(r))}return(o,r)=>(e.openBlock(),e.createBlock(B,{field:t.field,error:t.error,touched:t.touched},{default:e.withCtx(()=>[e.createElementVNode("input",{id:t.field.name,type:"number",name:t.field.name,value:t.modelValue??"",placeholder:t.field.placeholder,disabled:t.field.disabled===!0,required:t.field.required,class:"vfs-input",onInput:u,onBlur:r[0]||(r[0]=f=>n("blur"))},null,40,T)]),_:1},8,["field","error","touched"]))}}),A=["id","name","value","placeholder","disabled","required"],C=e.defineComponent({__name:"TextareaField",props:{field:{},modelValue:{},error:{},touched:{type:Boolean}},emits:["update:modelValue","blur"],setup(t,{emit:a}){const n=a;return(u,o)=>(e.openBlock(),e.createBlock(B,{field:t.field,error:t.error,touched:t.touched},{default:e.withCtx(()=>[e.createElementVNode("textarea",{id:t.field.name,name:t.field.name,value:t.modelValue,placeholder:t.field.placeholder,disabled:t.field.disabled===!0,required:t.field.required,class:"vfs-textarea",onInput:o[0]||(o[0]=r=>n("update:modelValue",r.target.value)),onBlur:o[1]||(o[1]=r=>n("blur"))},null,40,A)]),_:1},8,["field","error","touched"]))}}),M={key:0,class:"vfs-select-loading"},U=["id","name","disabled","required"],I=["selected"],P=["value","selected"],E=e.defineComponent({__name:"SelectField",props:{field:{},modelValue:{},error:{},touched:{type:Boolean}},emits:["update:modelValue","blur"],setup(t,{emit:a}){const n=t,u=a,o=e.computed(()=>Array.isArray(n.field.options)?n.field.options:[]);function r(f){const c=f.target,i=o.value.find(k=>String(k.value)===c.value);u("update:modelValue",(i==null?void 0:i.value)??c.value)}return(f,c)=>(e.openBlock(),e.createBlock(B,{field:t.field,error:t.error,touched:t.touched},{default:e.withCtx(()=>[t.field.optionsLoading?(e.openBlock(),e.createElementBlock("div",M,"Loading…")):(e.openBlock(),e.createElementBlock("select",{key:1,id:t.field.name,name:t.field.name,disabled:t.field.disabled===!0||t.field.optionsLoading,required:t.field.required,class:"vfs-select",onChange:r,onBlur:c[0]||(c[0]=i=>u("blur"))},[e.createElementVNode("option",{value:"",disabled:"",selected:t.modelValue===null||t.modelValue===void 0||t.modelValue===""},e.toDisplayString(t.field.placeholder??"Select an option"),9,I),(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(o.value,i=>(e.openBlock(),e.createElementBlock("option",{key:String(i.value),value:String(i.value),selected:t.modelValue===i.value},e.toDisplayString(i.label),9,P))),128))],40,U))]),_:1},8,["field","error","touched"]))}}),z={class:"vfs-checkbox-label"},j=["id","name","checked","disabled","required"],O={key:0,class:"vfs-checkbox-text"},S=e.defineComponent({__name:"CheckboxField",props:{field:{},modelValue:{type:Boolean},error:{},touched:{type:Boolean}},emits:["update:modelValue","blur"],setup(t,{emit:a}){const n=a;return(u,o)=>(e.openBlock(),e.createBlock(B,{field:{...t.field,label:void 0},error:t.error,touched:t.touched},{default:e.withCtx(()=>[e.createElementVNode("label",z,[e.createElementVNode("input",{id:t.field.name,type:"checkbox",name:t.field.name,checked:t.modelValue,disabled:t.field.disabled===!0,required:t.field.required,class:"vfs-checkbox",onChange:o[0]||(o[0]=r=>n("update:modelValue",r.target.checked)),onBlur:o[1]||(o[1]=r=>n("blur"))},null,40,j),t.field.label?(e.openBlock(),e.createElementBlock("span",O,e.toDisplayString(t.field.label),1)):e.createCommentVNode("",!0)])]),_:1},8,["field","error","touched"]))}}),G=["aria-labelledby"],H=["name","value","checked","disabled","onChange"],x=e.defineComponent({__name:"RadioField",props:{field:{},modelValue:{},error:{},touched:{type:Boolean}},emits:["update:modelValue","blur"],setup(t,{emit:a}){const n=a;return(u,o)=>(e.openBlock(),e.createBlock(B,{field:t.field,error:t.error,touched:t.touched},{default:e.withCtx(()=>[e.createElementVNode("div",{class:"vfs-radio-group",role:"radiogroup","aria-labelledby":t.field.name+"-label"},[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(t.field.options,r=>(e.openBlock(),e.createElementBlock("label",{key:String(r.value),class:"vfs-radio-label"},[e.createElementVNode("input",{type:"radio",name:t.field.name,value:String(r.value),checked:t.modelValue===r.value,disabled:t.field.disabled===!0,class:"vfs-radio",onChange:f=>n("update:modelValue",r.value),onBlur:o[0]||(o[0]=f=>n("blur"))},null,40,H),e.createTextVNode(" "+e.toDisplayString(r.label),1)]))),128))],8,G)]),_:1},8,["field","error","touched"]))}}),J=["id","name","value","disabled","required"],N=e.defineComponent({__name:"DateField",props:{field:{},modelValue:{},error:{},touched:{type:Boolean}},emits:["update:modelValue","blur"],setup(t,{emit:a}){const n=a;return(u,o)=>(e.openBlock(),e.createBlock(B,{field:t.field,error:t.error,touched:t.touched},{default:e.withCtx(()=>[e.createElementVNode("input",{id:t.field.name,type:"date",name:t.field.name,value:t.modelValue,disabled:t.field.disabled===!0,required:t.field.required,class:"vfs-input",onInput:o[0]||(o[0]=r=>n("update:modelValue",r.target.value)),onBlur:o[1]||(o[1]=r=>n("blur"))},null,40,J)]),_:1},8,["field","error","touched"]))}}),K={class:"vfs-array"},Q={key:0,class:"vfs-field__label"},W=["onClick"],F=e.defineComponent({__name:"ArrayField",props:{field:{},form:{},components:{}},setup(t){const a=t,n=h.useRegistry(),u={text:y,email:y,number:$,textarea:C,select:E,checkbox:S,radio:x,date:N};function o(s){var l;return s.component?s.component:((l=a.components)==null?void 0:l[s.type])??n[s.type]??u[s.type]??null}const{rows:r,append:f,remove:c}=h.useFieldArray(a.form,a.field.name);function i(s){return h.getByPath(a.form.values.value,s.name)}function k(s,l){a.form.setField(s.name,l)}function b(s){var m;const l=a.form;(m=l.touchField)==null||m.call(l,s.name)}function V(s){return a.form.errors.value[s.name]??[]}function p(s){return a.form.touched.value[s.name]??!1}return(s,l)=>(e.openBlock(),e.createElementBlock("div",K,[e.createVNode(B,{field:{...t.field,label:void 0},error:[],touched:!1},{default:e.withCtx(()=>[t.field.label?(e.openBlock(),e.createElementBlock("div",Q,e.toDisplayString(t.field.label),1)):e.createCommentVNode("",!0),(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(e.unref(r),m=>(e.openBlock(),e.createElementBlock("div",{key:m.key,class:"vfs-array__row"},[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(m.fields,v=>(e.openBlock(),e.createElementBlock(e.Fragment,{key:v.name},[o(v)?(e.openBlock(),e.createBlock(e.resolveDynamicComponent(o(v)),{key:0,field:v,"model-value":i(v),error:V(v),touched:p(v),"onUpdate:modelValue":d=>k(v,d),onBlur:d=>b(v)},null,40,["field","model-value","error","touched","onUpdate:modelValue","onBlur"])):e.createCommentVNode("",!0)],64))),128)),e.createElementVNode("button",{type:"button",class:"vfs-array__remove",onClick:v=>e.unref(c)(m.index)}," Remove ",8,W)]))),128)),e.createElementVNode("button",{type:"button",class:"vfs-array__add",onClick:l[0]||(l[0]=m=>e.unref(f)())}," + Add row ")]),_:1},8,["field"])]))}}),X={key:1,class:"vfs-group"},Y={key:0},Z=["disabled"],q=e.defineComponent({__name:"FormRenderer",props:{form:{},components:{},submitLabel:{}},emits:["submit"],setup(t,{emit:a}){const n=t,u=h.useRegistry(),o=a,r={text:y,email:y,number:$,textarea:C,select:E,checkbox:S,radio:x,date:N};function f(l){var m;return l.component?l.component:((m=n.components)==null?void 0:m[l.type])??u[l.type]??r[l.type]??null}function c(l){return h.getByPath(n.form.values.value,l.name)}function i(l,m){n.form.setField(l.name,m)}function k(l){var v;const m=n.form;(v=m.touchField)==null||v.call(m,l.name)}function b(l){return n.form.errors.value[l.name]??[]}function V(l){return n.form.touched.value[l.name]??!1}const p=e.computed(()=>n.form.fields.value.filter(l=>l.visible!==!1));async function s(l){l.preventDefault(),await n.form.submit(),o("submit")}return(l,m)=>{const v=e.resolveComponent("FormRenderer",!0);return e.openBlock(),e.createElementBlock("form",{class:"vfs-form",novalidate:"",onSubmit:s},[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(p.value,d=>(e.openBlock(),e.createElementBlock(e.Fragment,{key:d.name},[l.$slots[`field-${d.name}`]?e.renderSlot(l.$slots,`field-${d.name}`,{key:0,field:d,value:c(d),error:b(d),touched:V(d),setValue:g=>i(d,g),touch:()=>k(d)}):d.type==="group"?(e.openBlock(),e.createElementBlock("fieldset",X,[d.label?(e.openBlock(),e.createElementBlock("legend",Y,e.toDisplayString(d.label),1)):e.createCommentVNode("",!0),d.fields?(e.openBlock(),e.createBlock(v,{key:1,form:t.form,components:t.components},null,8,["form","components"])):e.createCommentVNode("",!0)])):d.type==="array"?(e.openBlock(),e.createBlock(F,{key:2,field:d,form:t.form,components:t.components},null,8,["field","form","components"])):f(d)?(e.openBlock(),e.createBlock(e.resolveDynamicComponent(f(d)),{key:3,field:d,"model-value":c(d),error:b(d),touched:V(d),"onUpdate:modelValue":g=>i(d,g),onBlur:g=>k(d)},e.createSlots({_:2},[l.$slots[`label-${d.name}`]?{name:"label",fn:e.withCtx(()=>[e.renderSlot(l.$slots,`label-${d.name}`,{field:d})]),key:"0"}:void 0,l.$slots[`error-${d.name}`]?{name:"error",fn:e.withCtx(()=>[e.renderSlot(l.$slots,`error-${d.name}`,{field:d,error:b(d)})]),key:"1"}:void 0]),1064,["field","model-value","error","touched","onUpdate:modelValue","onBlur"])):e.createCommentVNode("",!0)],64))),128)),e.renderSlot(l.$slots,"submit",{isSubmitting:t.form.isSubmitting.value,isValid:t.form.isValid.value},()=>[e.createElementVNode("button",{type:"submit",disabled:t.form.isSubmitting.value,class:"vfs-submit"},e.toDisplayString(t.submitLabel??"Submit"),9,Z)])],32)}}}),_={class:"vfs-multistep"},ee={class:"vfs-multistep__steps"},te={class:"vfs-multistep__step-number"},le={key:0,class:"vfs-multistep__step-label"},oe={class:"vfs-multistep__progress"},ne={class:"vfs-multistep__nav"},re=["disabled"],ae=e.defineComponent({__name:"MultiStepFormRenderer",props:{form:{},components:{},submitLabel:{},nextLabel:{},backLabel:{},stepLabels:{}},emits:["submit"],setup(t,{emit:a}){const n=t,u=a;async function o(){await n.form.next()}async function r(){await n.form.submit(),u("submit")}return(f,c)=>(e.openBlock(),e.createElementBlock("div",_,[e.createElementVNode("div",ee,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(t.form.steps,(i,k)=>{var b;return e.openBlock(),e.createElementBlock("div",{key:k,class:e.normalizeClass(["vfs-multistep__step",{"vfs-multistep__step--active":k===t.form.currentStep.value,"vfs-multistep__step--done":k<t.form.currentStep.value}])},[e.createElementVNode("span",te,e.toDisplayString(k+1),1),(b=t.stepLabels)!=null&&b[k]?(e.openBlock(),e.createElementBlock("span",le,e.toDisplayString(t.stepLabels[k]),1)):e.createCommentVNode("",!0)],2)}),128))]),e.createElementVNode("div",oe," Step "+e.toDisplayString(t.form.currentStep.value+1)+" of "+e.toDisplayString(t.form.totalSteps),1),e.createVNode(q,{form:t.form.form.value,components:t.components},{submit:e.withCtx(()=>[e.createElementVNode("div",ne,[t.form.isFirstStep.value?e.createCommentVNode("",!0):(e.openBlock(),e.createElementBlock("button",{key:0,type:"button",class:"vfs-multistep__back",onClick:c[0]||(c[0]=i=>t.form.back())},e.toDisplayString(t.backLabel??"← Back"),1)),t.form.isLastStep.value?(e.openBlock(),e.createElementBlock("button",{key:2,type:"button",class:"vfs-submit",disabled:t.form.isSubmitting.value,onClick:r},e.toDisplayString(t.submitLabel??"Submit"),9,re)):(e.openBlock(),e.createElementBlock("button",{key:1,type:"button",class:"vfs-multistep__next",onClick:o},e.toDisplayString(t.nextLabel??"Next →"),1))])]),_:1},8,["form","components"])]))}});exports.ArrayField=F;exports.CheckboxField=S;exports.DateField=N;exports.FormRenderer=q;exports.MultiStepFormRenderer=ae;exports.NumberField=$;exports.RadioField=x;exports.SelectField=E;exports.TextField=y;exports.TextareaField=C;
package/dist/ui.d.ts CHANGED
@@ -11,7 +11,7 @@ import { Ref } from 'vue';
11
11
  declare const __VLS_component: DefineComponent<ExtractPropTypes<__VLS_TypePropsToRuntimeProps<{
12
12
  form: UseFormReturn;
13
13
  /** Override individual field renderers: { text: MyTextInput, ... } */
14
- components?: Partial<Record<FieldDefinition["type"], Component>>;
14
+ components?: Partial<Record<FieldDefinition["type"], Component | string>>;
15
15
  /** Label for the submit button */
16
16
  submitLabel?: string;
17
17
  }>>, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
@@ -19,7 +19,7 @@ submit: () => void;
19
19
  }, string, PublicProps, Readonly<ExtractPropTypes<__VLS_TypePropsToRuntimeProps<{
20
20
  form: UseFormReturn;
21
21
  /** Override individual field renderers: { text: MyTextInput, ... } */
22
- components?: Partial<Record<FieldDefinition["type"], Component>>;
22
+ components?: Partial<Record<FieldDefinition["type"], Component | string>>;
23
23
  /** Label for the submit button */
24
24
  submitLabel?: string;
25
25
  }>>> & Readonly<{
@@ -28,6 +28,8 @@ onSubmit?: (() => any) | undefined;
28
28
 
29
29
  declare type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;
30
30
 
31
+ declare type __VLS_NonUndefinedable_10<T> = T extends undefined ? never : T;
32
+
31
33
  declare type __VLS_NonUndefinedable_2<T> = T extends undefined ? never : T;
32
34
 
33
35
  declare type __VLS_NonUndefinedable_3<T> = T extends undefined ? never : T;
@@ -42,6 +44,8 @@ declare type __VLS_NonUndefinedable_7<T> = T extends undefined ? never : T;
42
44
 
43
45
  declare type __VLS_NonUndefinedable_8<T> = T extends undefined ? never : T;
44
46
 
47
+ declare type __VLS_NonUndefinedable_9<T> = T extends undefined ? never : T;
48
+
45
49
  declare function __VLS_template(): Partial<Record<`field-${string}`, (_: {
46
50
  field: FieldDefinition;
47
51
  value: unknown;
@@ -70,6 +74,15 @@ declare type __VLS_TypePropsToRuntimeProps<T> = {
70
74
  };
71
75
  };
72
76
 
77
+ declare type __VLS_TypePropsToRuntimeProps_10<T> = {
78
+ [K in keyof T]-?: {} extends Pick<T, K> ? {
79
+ type: PropType<__VLS_NonUndefinedable_10<T[K]>>;
80
+ } : {
81
+ type: PropType<T[K]>;
82
+ required: true;
83
+ };
84
+ };
85
+
73
86
  declare type __VLS_TypePropsToRuntimeProps_2<T> = {
74
87
  [K in keyof T]-?: {} extends Pick<T, K> ? {
75
88
  type: PropType<__VLS_NonUndefinedable_2<T[K]>>;
@@ -133,15 +146,34 @@ declare type __VLS_TypePropsToRuntimeProps_8<T> = {
133
146
  };
134
147
  };
135
148
 
149
+ declare type __VLS_TypePropsToRuntimeProps_9<T> = {
150
+ [K in keyof T]-?: {} extends Pick<T, K> ? {
151
+ type: PropType<__VLS_NonUndefinedable_9<T[K]>>;
152
+ } : {
153
+ type: PropType<T[K]>;
154
+ required: true;
155
+ };
156
+ };
157
+
136
158
  declare type __VLS_WithTemplateSlots<T, S> = T & {
137
159
  new (): {
138
160
  $slots: S;
139
161
  };
140
162
  };
141
163
 
164
+ export declare const ArrayField: DefineComponent<ExtractPropTypes<__VLS_TypePropsToRuntimeProps_10<{
165
+ field: FieldDefinition;
166
+ form: UseFormReturn;
167
+ components?: Partial<Record<FieldDefinition["type"], Component | string>>;
168
+ }>>, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {}, string, PublicProps, Readonly<ExtractPropTypes<__VLS_TypePropsToRuntimeProps_10<{
169
+ field: FieldDefinition;
170
+ form: UseFormReturn;
171
+ components?: Partial<Record<FieldDefinition["type"], Component | string>>;
172
+ }>>> & Readonly<{}>, {}, {}, {}, {}, string, ComponentProvideOptions, true, {}, any>;
173
+
142
174
  declare type AsyncValidatorFn = (value: unknown, values: Record<string, unknown>) => Promise<string | null>;
143
175
 
144
- export declare const CheckboxField: DefineComponent<ExtractPropTypes<__VLS_TypePropsToRuntimeProps_6<{
176
+ export declare const CheckboxField: DefineComponent<ExtractPropTypes<__VLS_TypePropsToRuntimeProps_7<{
145
177
  field: FieldDefinition;
146
178
  modelValue: boolean;
147
179
  error?: string[];
@@ -149,7 +181,7 @@ touched?: boolean;
149
181
  }>>, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
150
182
  blur: () => void;
151
183
  "update:modelValue": (value: boolean) => void;
152
- }, string, PublicProps, Readonly<ExtractPropTypes<__VLS_TypePropsToRuntimeProps_6<{
184
+ }, string, PublicProps, Readonly<ExtractPropTypes<__VLS_TypePropsToRuntimeProps_7<{
153
185
  field: FieldDefinition;
154
186
  modelValue: boolean;
155
187
  error?: string[];
@@ -159,7 +191,7 @@ onBlur?: (() => any) | undefined;
159
191
  "onUpdate:modelValue"?: ((value: boolean) => any) | undefined;
160
192
  }>, {}, {}, {}, {}, string, ComponentProvideOptions, true, {}, any>;
161
193
 
162
- export declare const DateField: DefineComponent<ExtractPropTypes<__VLS_TypePropsToRuntimeProps_8<{
194
+ export declare const DateField: DefineComponent<ExtractPropTypes<__VLS_TypePropsToRuntimeProps_9<{
163
195
  field: FieldDefinition;
164
196
  modelValue: string;
165
197
  error?: string[];
@@ -167,7 +199,7 @@ touched?: boolean;
167
199
  }>>, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
168
200
  blur: () => void;
169
201
  "update:modelValue": (value: string) => void;
170
- }, string, PublicProps, Readonly<ExtractPropTypes<__VLS_TypePropsToRuntimeProps_8<{
202
+ }, string, PublicProps, Readonly<ExtractPropTypes<__VLS_TypePropsToRuntimeProps_9<{
171
203
  field: FieldDefinition;
172
204
  modelValue: string;
173
205
  error?: string[];
@@ -192,10 +224,32 @@ declare interface FieldDefinition {
192
224
  validators?: ValidatorFn[];
193
225
  asyncValidators?: AsyncValidatorFn[];
194
226
  mask?: string | MaskConfig;
195
- /** For select / radio */
196
- options?: FieldOption[];
227
+ /** For select / radio — static list, sync function, or async function */
228
+ options?: FieldOption[] | ((values: Record<string, unknown>) => FieldOption[] | Promise<FieldOption[]>);
229
+ /**
230
+ * Field names whose values trigger re-fetching of async options.
231
+ * Only relevant when `options` is an async function.
232
+ */
233
+ optionsDeps?: string[];
234
+ /** Internal: set by useForm when async options are loading. Read-only for consumers. */
235
+ optionsLoading?: boolean;
197
236
  /** For group and array */
198
237
  fields?: FieldDefinition[];
238
+ /**
239
+ * Applied on every setField call before the value is stored.
240
+ * Use for trimming, type coercion, formatting, etc.
241
+ */
242
+ transform?: (value: unknown, values: Record<string, unknown>) => unknown;
243
+ /**
244
+ * Applied at submit time to produce the final payload value.
245
+ * Runs after all validation passes.
246
+ */
247
+ parse?: (raw: unknown) => unknown;
248
+ /**
249
+ * Custom Vue component to render this field.
250
+ * Receives FormFieldProps and must emit 'update:modelValue' and 'blur'.
251
+ */
252
+ component?: Component | string;
199
253
  }
200
254
 
201
255
  declare interface FieldOption {
@@ -215,7 +269,47 @@ declare interface MaskConfig {
215
269
 
216
270
  declare type MaskPreset = 'phone-ru' | 'phone-eu' | 'date' | 'inn' | 'iban';
217
271
 
218
- export declare const NumberField: DefineComponent<ExtractPropTypes<__VLS_TypePropsToRuntimeProps_3<{
272
+ export declare const MultiStepFormRenderer: DefineComponent<ExtractPropTypes<__VLS_TypePropsToRuntimeProps_2<{
273
+ form: MultiStepFormReturn;
274
+ components?: Partial<Record<FieldDefinition["type"], Component | string>>;
275
+ submitLabel?: string;
276
+ nextLabel?: string;
277
+ backLabel?: string;
278
+ stepLabels?: string[];
279
+ }>>, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
280
+ submit: () => void;
281
+ }, string, PublicProps, Readonly<ExtractPropTypes<__VLS_TypePropsToRuntimeProps_2<{
282
+ form: MultiStepFormReturn;
283
+ components?: Partial<Record<FieldDefinition["type"], Component | string>>;
284
+ submitLabel?: string;
285
+ nextLabel?: string;
286
+ backLabel?: string;
287
+ stepLabels?: string[];
288
+ }>>> & Readonly<{
289
+ onSubmit?: (() => any) | undefined;
290
+ }>, {}, {}, {}, {}, string, ComponentProvideOptions, true, {}, any>;
291
+
292
+ declare interface MultiStepFormReturn {
293
+ currentStep: Ref<number>;
294
+ totalSteps: number;
295
+ isFirstStep: ComputedRef<boolean>;
296
+ isLastStep: ComputedRef<boolean>;
297
+ /** The active step's form instance */
298
+ form: ComputedRef<UseFormReturn>;
299
+ /** All step form instances */
300
+ steps: UseFormReturn[];
301
+ /** Merged values from all steps */
302
+ values: ComputedRef<Record<string, unknown>>;
303
+ isValid: ComputedRef<boolean>;
304
+ isSubmitting: ComputedRef<boolean>;
305
+ /** Validate current step and advance. Returns false if validation fails. */
306
+ next(): Promise<boolean>;
307
+ back(): void;
308
+ goTo(step: number): void;
309
+ submit(): Promise<void>;
310
+ }
311
+
312
+ export declare const NumberField: DefineComponent<ExtractPropTypes<__VLS_TypePropsToRuntimeProps_4<{
219
313
  field: FieldDefinition;
220
314
  modelValue: number | null;
221
315
  error?: string[];
@@ -223,7 +317,7 @@ touched?: boolean;
223
317
  }>>, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
224
318
  blur: () => void;
225
319
  "update:modelValue": (value: number | null) => void;
226
- }, string, PublicProps, Readonly<ExtractPropTypes<__VLS_TypePropsToRuntimeProps_3<{
320
+ }, string, PublicProps, Readonly<ExtractPropTypes<__VLS_TypePropsToRuntimeProps_4<{
227
321
  field: FieldDefinition;
228
322
  modelValue: number | null;
229
323
  error?: string[];
@@ -233,7 +327,7 @@ onBlur?: (() => any) | undefined;
233
327
  "onUpdate:modelValue"?: ((value: number | null) => any) | undefined;
234
328
  }>, {}, {}, {}, {}, string, ComponentProvideOptions, true, {}, any>;
235
329
 
236
- export declare const RadioField: DefineComponent<ExtractPropTypes<__VLS_TypePropsToRuntimeProps_7<{
330
+ export declare const RadioField: DefineComponent<ExtractPropTypes<__VLS_TypePropsToRuntimeProps_8<{
237
331
  field: FieldDefinition;
238
332
  modelValue: unknown;
239
333
  error?: string[];
@@ -241,7 +335,7 @@ touched?: boolean;
241
335
  }>>, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
242
336
  blur: () => void;
243
337
  "update:modelValue": (value: unknown) => void;
244
- }, string, PublicProps, Readonly<ExtractPropTypes<__VLS_TypePropsToRuntimeProps_7<{
338
+ }, string, PublicProps, Readonly<ExtractPropTypes<__VLS_TypePropsToRuntimeProps_8<{
245
339
  field: FieldDefinition;
246
340
  modelValue: unknown;
247
341
  error?: string[];
@@ -251,7 +345,7 @@ onBlur?: (() => any) | undefined;
251
345
  "onUpdate:modelValue"?: ((value: unknown) => any) | undefined;
252
346
  }>, {}, {}, {}, {}, string, ComponentProvideOptions, true, {}, any>;
253
347
 
254
- export declare const SelectField: DefineComponent<ExtractPropTypes<__VLS_TypePropsToRuntimeProps_5<{
348
+ export declare const SelectField: DefineComponent<ExtractPropTypes<__VLS_TypePropsToRuntimeProps_6<{
255
349
  field: FieldDefinition;
256
350
  modelValue: unknown;
257
351
  error?: string[];
@@ -259,7 +353,7 @@ touched?: boolean;
259
353
  }>>, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
260
354
  blur: () => void;
261
355
  "update:modelValue": (value: unknown) => void;
262
- }, string, PublicProps, Readonly<ExtractPropTypes<__VLS_TypePropsToRuntimeProps_5<{
356
+ }, string, PublicProps, Readonly<ExtractPropTypes<__VLS_TypePropsToRuntimeProps_6<{
263
357
  field: FieldDefinition;
264
358
  modelValue: unknown;
265
359
  error?: string[];
@@ -269,7 +363,7 @@ onBlur?: (() => any) | undefined;
269
363
  "onUpdate:modelValue"?: ((value: unknown) => any) | undefined;
270
364
  }>, {}, {}, {}, {}, string, ComponentProvideOptions, true, {}, any>;
271
365
 
272
- export declare const TextareaField: DefineComponent<ExtractPropTypes<__VLS_TypePropsToRuntimeProps_4<{
366
+ export declare const TextareaField: DefineComponent<ExtractPropTypes<__VLS_TypePropsToRuntimeProps_5<{
273
367
  field: FieldDefinition;
274
368
  modelValue: string;
275
369
  error?: string[];
@@ -277,7 +371,7 @@ touched?: boolean;
277
371
  }>>, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
278
372
  blur: () => void;
279
373
  "update:modelValue": (value: string) => void;
280
- }, string, PublicProps, Readonly<ExtractPropTypes<__VLS_TypePropsToRuntimeProps_4<{
374
+ }, string, PublicProps, Readonly<ExtractPropTypes<__VLS_TypePropsToRuntimeProps_5<{
281
375
  field: FieldDefinition;
282
376
  modelValue: string;
283
377
  error?: string[];
@@ -287,7 +381,7 @@ onBlur?: (() => any) | undefined;
287
381
  "onUpdate:modelValue"?: ((value: string) => any) | undefined;
288
382
  }>, {}, {}, {}, {}, string, ComponentProvideOptions, true, {}, any>;
289
383
 
290
- export declare const TextField: DefineComponent<ExtractPropTypes<__VLS_TypePropsToRuntimeProps_2<{
384
+ export declare const TextField: DefineComponent<ExtractPropTypes<__VLS_TypePropsToRuntimeProps_3<{
291
385
  field: FieldDefinition;
292
386
  modelValue: string;
293
387
  error?: string[];
@@ -295,7 +389,7 @@ touched?: boolean;
295
389
  }>>, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
296
390
  blur: () => void;
297
391
  "update:modelValue": (value: string) => void;
298
- }, string, PublicProps, Readonly<ExtractPropTypes<__VLS_TypePropsToRuntimeProps_2<{
392
+ }, string, PublicProps, Readonly<ExtractPropTypes<__VLS_TypePropsToRuntimeProps_3<{
299
393
  field: FieldDefinition;
300
394
  modelValue: string;
301
395
  error?: string[];
@@ -310,6 +404,8 @@ declare interface UseFormReturn<T extends Record<string, unknown> = Record<strin
310
404
  values: Ref<T>;
311
405
  errors: Ref<Record<string, string[]>>;
312
406
  touched: Ref<Record<string, boolean>>;
407
+ /** Per-field async options loading state */
408
+ optionsLoading: Ref<Record<string, boolean>>;
313
409
  isDirty: ComputedRef<boolean>;
314
410
  isValid: ComputedRef<boolean>;
315
411
  isSubmitting: Ref<boolean>;