vue-formless 0.0.1 → 0.1.0

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.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const l=require("vue"),N=Symbol("vue-formless.formContext");function Y(){const e=l.inject(N,null);if(!e)throw new Error("[vue-formless] useFormContext() must be used inside <FormView>.");return e}function D(e){if(!e)return[];const t=[];let o=0;for(;o<e.length;){if(e[o]==="."){o++;continue}if(e[o]==="["){const n=e.indexOf("]",o+1);if(n===-1)throw new Error(`Invalid path "${e}": unclosed bracket`);const r=e.slice(o+1,n),s=Number(r);if(!Number.isInteger(s)||String(s)!==r||s<0)throw new Error(`Invalid path "${e}": index must be a non-negative integer`);t.push({type:"index",index:s}),o=n+1}else{const n=/^[a-zA-Z_$][a-zA-Z0-9_$]*/.exec(e.slice(o));if(!n)throw new Error(`Invalid path "${e}" at position ${o}`);t.push({type:"key",key:n[0]}),o+=n[0].length}}return t}function Ne(e,t){let o=e;for(const n of t)n.type==="key"?o=o[n.key]:o=o[n.index];return o}function _e(e,t){if(t.type==="key")return e==null||typeof e!="object"||Array.isArray(e)?void 0:e[t.key];if(Array.isArray(e))return e[t.index]}function k(e,t){const o=D(t);if(o.length===0)return;const n=o[o.length-1],r=Ne(e,o.slice(0,-1));return _e(r,n)}function J(e,t,o,n){const r=t[o],s=o===t.length-1;if(r.type==="key"){if(Array.isArray(e))throw new Error(`Cannot set "${r.key}" on an array node`);const i=e!=null&&typeof e=="object"?e:{};return s?{...i,[r.key]:n}:{...i,[r.key]:J(i[r.key],t,o+1,n)}}const u=Array.isArray(e)?[...e]:[];return s?(u[r.index]=n,u):(u[r.index]=J(u[r.index],t,o+1,n),u)}function we(e,t,o){const n=D(t);if(n.length===0)throw new Error("Cannot set an empty prop");return J(e,n,0,o)}function ye(e){return D(e).map(t=>t.type==="key"?t.key:String(t.index)).join(".")}function Me(e,t){let o=null;function n(r,s){o||(o=[],l.nextTick(()=>{if(!o?.length){o=null;return}let u=e();for(const i of o)u=we(u,i.prop,i.value);o=null,t(u)})),o.push({prop:r,value:s})}return{update:n}}const p=24,V={column:1};function Te(e){const t=Math.floor(Number(e));return t===1/0?p:Number.isFinite(t)?Math.min(p,Math.max(1,t)):V.column}function Be(...e){return Te(e.find(t=>t!=null)??V.column)}function Ue(e,t){const o=t>0?t:V.column,n=Math.max(1,Math.floor(p/o));if(e==null||e==="")return n;if(typeof e=="number")return ce(e),e;const r=e.trim();if(r==="max")return p;const s=/^(\d+)x$/.exec(r);if(s){const u=Number(s[1]);if(u<1)throw new Error(`[vue-formless] col:span "${e}" is invalid`);return Math.min(p,u*n)}if(/^\d+$/.test(r)){const u=Number(r);return ce(u),u}throw new Error(`[vue-formless] col:span "${e}" is invalid`)}function ce(e){if(!Number.isInteger(e)||e<1||e>p)throw new Error(`[vue-formless] col:span ${e} must be an integer 1–${p}`)}function We(e){if(e==null||e===""||e==="auto")return"auto";if(e==="start"||e==="end")return e;throw new Error(`[vue-formless] col:place "${String(e)}" is invalid`)}const W=Symbol("vue-formless:layout-view");function Ge(e,t,o={childList:!0}){if(typeof MutationObserver>"u")return;let n=null;function r(u){n?.disconnect(),n=null,u&&(n=new MutationObserver(t),n.observe(u,o))}l.onMounted(()=>r(l.toValue(e)));const s=l.watch(()=>l.toValue(e),r,{flush:"post"});l.onBeforeUnmount(()=>{s(),n?.disconnect(),n=null})}function Ye(e,t=0){const o=l.ref([]);function n(){const r=l.toValue(e);o.value=r?Array.from(r.children):[]}return l.watch(()=>[l.toValue(e),l.toValue(t)],n,{immediate:!0}),Ge(e,n),o}function De(e,t,o){const n=[];if(o==="auto")return e.n+t>p&&(e.n=0),n;if(o==="start")return e.n>0&&(n.push(p-e.n),e.n=0),n;e.n+t>p&&e.n>0&&(n.push(p-e.n),e.n=0);const r=p-e.n-t;return r>0&&(n.push(r),e.n+=r),n}function ze(e){return l.computed(()=>{const t={n:0},o=new Map;for(const n of l.toValue(e)){const r=De(t,n.span,n.place);o.set(n.id,r),t.n+=n.span}return o})}function ge(e){if(e==null||typeof e!="object")return null;if(typeof Element<"u"&&e instanceof Element)return e;const t=e;return U(t.vnode?.el)??U(t.subTree?.el)??U(t.subTree?.component?.vnode?.el)??U(t.$el)}function U(e){if(typeof Element<"u"&&e instanceof Element)return e;if(e&&e.nodeType===8){for(let t=e.nextSibling;t;t=t.nextSibling)if(typeof Element<"u"&&t instanceof Element)return t}return null}const Ke=l.defineComponent({name:"LayoutBlanks",inheritAttrs:!1,props:{is:{type:Object,default:void 0},spans:{type:Array,required:!0}},setup(e){return()=>{if(e.spans.length===0||e.is==null)return null;const t=e.is;return l.createVNode(l.Fragment,null,[e.spans.map((o,n)=>l.createVNode(t,{key:n,span:o},null))])}}}),qe=l.defineComponent({name:"LayoutItem",inheritAttrs:!1,props:{span:{type:[String,Number],default:void 0},place:{type:String,default:void 0}},setup(e,{slots:t}){const o=l.inject(W,null);if(!o)return()=>t.default?.()??null;const{span:n,blanks:r,itemRef:s,Col:u,disabled:i}=o(()=>e.span,()=>e.place);return()=>{if(i.value)return t.default?.()??null;const f=u;return l.createVNode(l.Fragment,null,[l.createVNode(Ke,{is:u,spans:r.value},null),l.createVNode(f,{ref:s,span:n.value},{default:()=>[t.default?.()??null]})])}}}),He=l.defineComponent({name:"LayoutItemPassThrough",inheritAttrs:!1,setup(e,{slots:t}){return()=>t.default?.()??null}});function he(){return l.inject(W,null)?qe:He}function Xe(e){const t=l.ref({});let o=0;return{get value(){return t.value},setup(n,r){const s=String(++o),u=l.computed(()=>Ue(l.toValue(n),l.toValue(e))),i=l.computed(()=>We(l.toValue(r)));return t.value[s]={span:u,place:i,el:null,mounted:!1},l.onMounted(()=>{const f=t.value[s];f&&(f.mounted=!0)}),l.onBeforeUnmount(()=>{delete t.value[s]}),s},span(n){return t.value[n]?.span??0},ref(n,r){const s=t.value[n];if(!s)return;const u=ge(r);s.el!==u&&(s.el=u)}}}function Ze(e,t){const o=new Map(Object.entries(e).filter(([,n])=>n.el).map(([n,r])=>[r.el,{id:n,span:r.span,place:r.place}]));return t.filter(n=>o.has(n)).map(n=>o.get(n))}function Je(e,t){const o=Ye(()=>ge(t.value),()=>Object.keys(e.value).filter(n=>e.value[n].mounted).join(","));return ze(()=>Ze(e.value,o.value))}function ne(e={}){const{Row:t,Col:o}=e;return l.defineComponent({name:"LayoutView",inheritAttrs:!1,props:{disabled:{type:Boolean,default:!1},column:{type:Number,default:void 0}},setup(n,{slots:r,attrs:s}){const u=l.computed(()=>!t||!o||n.disabled),i=Xe(()=>Be(n.column,e.column)),f=l.ref(null),a=Je(i,f);return l.provide(W,(m,g)=>{l.provide(W,null);const w=i.setup(m,g);return{span:l.computed(()=>i.span(w)),blanks:l.computed(()=>a.value.get(w)??[]),itemRef:b=>i.ref(w,b),Col:o,disabled:u}}),()=>{if(u.value)return r.default?.()??null;const m=t;return l.createVNode(m,l.mergeProps({ref:f},s),{default:()=>[r.default?.()??null]})}}})}const Qe=new Set(["item","layout","model","span"]),et=new Set(["component","props","model","prop","item","layout"]);function Q(e){const t={};for(const[o,n]of Object.entries(e))n!==void 0&&(t[o]=n);return t}function oe(e){const t={};for(const[o,n]of Object.entries(e))o==="span"&&n!==void 0&&console.warn("[vue-formless] fl:span is removed; use col:span"),Qe.has(o)||(t[o]=n);return t}function tt(e){const t={};for(const[o,n]of Object.entries(e))!et.has(o)&&n!==void 0&&(t[o]=n);return t}function nt(e){if(e==null||typeof e!="object")return{};const t=e.formless;if(t==null||typeof t!="object")return{};const{model:o,item:n}=t;return Q({model:o,item:n})}function ve(e){const t={};for(const[o,n]of Object.entries(e))!o.startsWith("fl:")||o.length<=3||n===void 0||(t[o.slice(3)]=n);return t}function ot(e,t){const o=new Set;for(const r of t)o.add(r),o.add(`onUpdate:${r}`);const n={};for(const[r,s]of Object.entries(e))o.has(r)||(n[r]=s);return n}function $(e,t){return e==null?{}:Q(typeof e=="function"?e(t)??{}:e)}function z(...e){const t={};for(const o of e)if(o!=null)for(const[n,r]of Object.entries(o))r!==void 0&&(t[n]=r);return t}function rt(e){const t=e.Item?l.markRaw(e.Item):void 0;return(o,n)=>t&&n.item!==!1&&(n.item===!0||(e.isItemEnabled?.()??!0))?l.h(t,z($(e.itemProps,n.fl),n.itemAttrs,n.itemOn),{...n.itemSlots,default:()=>o}):o}function ee(e){return typeof e=="string"?[e]:[...e]}function re(e,t={},o={}){if(o.prop==="")throw new Error(`[vue-formless] fl:prop cannot be an empty string (control "${e}")`);if(t.prop==="")throw new Error(`[vue-formless] prop cannot be an empty string (control "${e}")`);const n=ee(t.model??"modelValue"),r=ee(o.prop!==void 0?o.prop:t.prop??e);if(r.length>n.length)throw new Error(`createFormControls: prop cannot be longer than model (control "${e}": model has ${n.length}, prop has ${r.length})`);if(r.some(s=>s===""))throw new Error(`[vue-formless] prop cannot be an empty string (control "${e}")`);return{models:n,props:r}}function lt(e,t){return e.props.length===1?ye(e.props[0]):t}function be(e,t){const o=e.models.indexOf(t);if(o===-1)throw new Error(`[vue-formless] useFormItem("${t}"): not a v-model port of this control`);const n=e.props[o];if(n===void 0)throw new Error(`[vue-formless] useFormItem("${t}"): port is not bound to a prop`);return{models:[t],props:[n]}}function le(e,t,o){const n={};for(let r=0;r<t.props.length;r++){const s=t.models[r],u=t.props[r];n[s]=k(e,u),n[`onUpdate:${s}`]=i=>{o(u,i)}}return n}const O="item:",q="onItem:",H="fl:",X="row:",Z="col:",st=new Set(["column","gutter"]),ut=new Set(["span","place"]);function fe(e){console.warn(e)}function Ie(e){const t={},o={};for(const n of Object.keys(e)){const r=e[n];r&&(n.startsWith(O)&&n.length>O.length?t[n.slice(O.length)]=r:o[n]=r)}return{itemSlots:t,inputSlots:o}}function Ce(e){const t={},o={};for(const[n,r]of Object.entries(e))n.startsWith(H)&&n.length>H.length?t[n.slice(H.length)]=r:o[n]=r;return{fl:t,rest:o}}function Fe(e){const t={},o={},n={};for(const[r,s]of Object.entries(e))if(r.startsWith(X)&&r.length>X.length){const u=r.slice(X.length);st.has(u)?t[u]=s:fe(`[vue-formless] unknown row:${u} is ignored`)}else if(r.startsWith(Z)&&r.length>Z.length){const u=r.slice(Z.length);ut.has(u)?o[u]=s:fe(`[vue-formless] unknown col:${u} is ignored`)}else n[r]=s;return{row:t,col:o,rest:n}}function me(e){if(e==null||e==="")return;const t=typeof e=="number"?e:Number(e);if(Number.isFinite(t))return t}function Ee(e){const t={},o={},n={};for(const[r,s]of Object.entries(e))r.startsWith(q)&&r.length>q.length?o[it(r.slice(q.length))]=s:r.startsWith(O)&&r.length>O.length?t[r.slice(O.length)]=s:n[r]=s;return{itemAttrs:t,itemOn:o,inputAttrs:n}}function it(e){const t=e.indexOf(":");return t===-1?`on${de(e)}`:`on${de(e.slice(0,t))}:${e.slice(t+1)}`}function de(e){return e&&e.charAt(0).toUpperCase()+e.slice(1)}const Ve=Symbol("vue-formless.controlRuntime");function at(e){l.provide(Ve,e)}const ct={"fl:prop":{type:[String,Array],default:void 0},"col:span":{type:[String,Number],default:void 0},"col:place":{type:String,default:void 0}};function Se(e){return l.defineComponent({name:e?`FormViewItem_${e}`:"FormViewItem",inheritAttrs:!1,props:ct,setup(t,{slots:o,attrs:n}){const r=Y(),s=he(),u=l.inject(Ve,null);if(e!=null&&!u)throw new Error("[vue-formless] useFormItem(port) must be used inside a namespaced control.");return()=>ft(r,s,u,e,o,n,t)}})}const se=Se();function Ae(e){return Y(),e===void 0?se:Se(e)}function ft(e,t,o,n,r,s,u){const{fl:i,rest:f}=Ce(s),{row:a,col:m,rest:g}=Fe(f),w={...i,...ve(u)},{itemAttrs:b,itemOn:v,inputAttrs:S}=Ee(g),I={...b,...S},{itemSlots:y}=Ie(r),d=n==null&&o!=null,C=u["col:span"]??m.span,A=u["col:place"]??m.place,c=o?.getFrame(),L=C??(d?c?.colSpan:void 0),x=A??(d?c?.colPlace:void 0),_=mt(e,o,n,w),M=le(e.model,_.binding,e.update),K=r.default?.({field:M})??null;!d&&(a.column!=null||a.gutter!=null)&&console.warn("[vue-formless] :row:* is ignored on a leaf cell");let F=I,E=v,T=y;d&&c&&(F={...c.itemAttrs,...I},E={...c.itemOn,...v},T={...c.itemSlots,...y});let R,B,P=!1;d&&c&&(R=c.wrapItem,B=c.wrapCol,P=c.extraRow);let h=K;if(P&&c){const j=h;h=l.h(e.LayoutView,{disabled:!e.isLayoutEnabled(),column:c.rowColumn??e.factoryColumn,gutter:c.rowGutter??e.factoryGutter},()=>j)}if(h=e.wrap(h,{item:R===!1?!1:R===!0?!0:void 0,fl:_.fl,itemAttrs:F,itemOn:E,itemSlots:T}),B!==!1){const j=h;h=l.h(t,{span:L,place:x},()=>j)}return h}function mt(e,t,o,n){const r=oe(n);if(t){const a=t.getFrame(),m=o!=null?be(a.binding,o):a.binding,g={...a.fl,...r,controlKey:t.controlKey,binding:m,getValues:()=>m.props.map(w=>k(e.model,w))};return{binding:m,fl:g}}const s=n.prop;if(s==="")throw new Error("[vue-formless] fl:prop cannot be an empty string");const u=typeof s=="string"?s:Array.isArray(s)&&s[0]?String(s[0]):"",i=s===void 0?{models:["modelValue"],props:[]}:re(u||"field",{prop:s}),f={...r,controlKey:u,binding:i,getValues:()=>i.props.map(a=>k(e.model,a))};return{binding:i,fl:f}}function Le(e){const t=e;return t.Item=se,t}const te=0;function dt(e){return new Proxy({},{get(t,o){const n=e.value;if(n==null)return;const r=Reflect.get(n,o,n);return typeof r=="function"?r.bind(n):r},has(t,o){return e.value!=null&&o in e.value}})}const Oe={modelValue:{type:[Object,Array],default:void 0},"fl:layout":{type:Boolean,default:!1},"row:column":{type:Number,default:void 0},"row:gutter":{type:Number,default:void 0},"fl:form":{type:[Boolean,String],default:"auto"},"fl:item":{type:Boolean,default:!0}},ke={"update:modelValue":e=>!0};function G(e){if(e!=null&&typeof e=="object")throw new Error("[vue-formless] fl:layout is boolean only; use :row:column / :row:gutter");return e===!0||e===""}function pt(e,t){return e===!0||e===!1?e:!t}function wt(e){return e==null?!1:"modelValue"in e||"model-value"in e||"onUpdate:modelValue"in e||"onUpdate:model-value"in e}function xe(e){const t=rt({Item:e.Item,itemProps:e.itemProps,isItemEnabled:e.isItemEnabled}),o=e.isItemEnabled??(()=>!0);l.provide(N,l.reactive({get model(){return e.getModel()},update:e.update,wrap:t,isItemEnabled:o,isLayoutEnabled:e.isLayoutEnabled,LayoutView:l.markRaw(e.LayoutView),factoryColumn:e.factoryColumn,factoryGutter:e.factoryGutter}))}function Re(e,t){const o=l.inject(N,null);if(wt(l.getCurrentInstance()?.vnode.props)){const r=Me(e,t);return{getModel:e,update:r.update}}if(o)return{getModel:()=>o.model,update:o.update};throw new Error("[vue-formless] FormView requires v-model unless nested inside another FormView.")}function yt(e){if(e!=null){if(e.Row==null||e.Col==null)throw new Error("[vue-formless] createFormView layout requires both Row and Col.");return{Row:l.markRaw(e.Row),Col:l.markRaw(e.Col),column:e.column,gutter:e.gutter}}}function gt(e={}){const t=yt(e.layout),o=e.form?.component?l.markRaw(e.form.component):void 0,n=e.form?.props,r=e.item?.component?l.markRaw(e.item.component):void 0,s=e.item?.props,u=ne(t?{Row:t.Row,Col:t.Col}:{}),i=t?.column??V.column,f=t?.gutter??te;return Le(l.defineComponent({name:"FormView",inheritAttrs:!1,props:Oe,emits:ke,setup(a,{slots:m,emit:g,attrs:w,expose:b}){const v=l.ref(null);b(dt(v));const S=l.inject(N,null)!=null,{getModel:I,update:y}=Re(()=>a.modelValue,d=>g("update:modelValue",d));return xe({getModel:I,update:y,Item:r,itemProps:s,isItemEnabled:()=>a["fl:item"]!==!1,isLayoutEnabled:()=>G(a["fl:layout"]),LayoutView:u,factoryColumn:i,factoryGutter:f}),()=>{const d=m.default?.()??null,C=G(a["fl:layout"]),A={column:a["row:column"]??i,gutter:a["row:gutter"]??f},c=l.h(u,{disabled:!C,column:A.column,gutter:A.gutter},()=>d),L=o?pt(a["fl:form"],S):!1;if(!o||!L)return c;const x={layout:C,form:L,item:a["fl:item"]!==!1,modelValue:I()};return l.h(o,{ref:v,...z($(n,x),w)},{default:()=>c})}}}))}const pe=ne(),ht=Le(l.defineComponent({name:"FormView",inheritAttrs:!1,props:Oe,emits:ke,setup(e,{slots:t,emit:o}){const{getModel:n,update:r}=Re(()=>e.modelValue,s=>o("update:modelValue",s));return xe({getModel:n,update:r,isLayoutEnabled:()=>G(e["fl:layout"]),LayoutView:pe,factoryColumn:V.column,factoryGutter:te}),()=>l.h(pe,{disabled:!G(e["fl:layout"]),column:e["row:column"]??V.column,gutter:e["row:gutter"]??te},()=>t.default?.()??null)}}));function ue(e){return e&&e.charAt(0).toUpperCase()+e.slice(1)}function vt(e){return e&&e.charAt(0).toLowerCase()+e.slice(1)}function Pe(e,t){if(e==="self"&&t===!1||e===!1&&t==="self")throw new Error('[vue-formless] formless.item "self" conflicts with schema item: false');return e??t}function je(e){const t=e.internalItem==="self";let o;e.tagItem===!0?o=!0:e.tagItem===!1||t||e.internalItem===!1?o=!1:e.internalItem===!0?o=!0:o=e.pageItem;let n=e.pageLayoutOn;t&&e.tagItem!==!0&&(o=!1,n=!1);const r=t&&e.tagItem===!0&&e.pageLayoutOn;return{wrapItem:o,wrapCol:n,extraRow:r,self:t}}const bt={"fl:prop":{type:[String,Array],default:void 0},"fl:item":{type:Boolean,default:void 0},"col:span":{type:[String,Number],default:void 0},"col:place":{type:String,default:void 0},"row:column":{type:Number,default:void 0},"row:gutter":{type:Number,default:void 0}};function It(e,t){const o=Et(e),n={};for(const r of Object.keys(o)){const s=o[r];if(!s)continue;const u=ue(r);n[u]=Ct(r,s,t)}return n}function Ct(e,t,o){const n=nt(t.component),r=n.model??t.model,s=Pe(n.item,t.item);return l.defineComponent({name:`Control_${ue(e)}`,inheritAttrs:!1,props:bt,setup(u,{attrs:i,slots:f}){const a=Y();let m;at({controlKey:e,getFrame:()=>m});const g=Ae();return()=>{const{fl:w,rest:b}=Ce(i),{row:v,col:S,rest:I}=Fe(b),y={...w,...ve(u)},d=re(e,{model:r,prop:t.prop},{prop:y.prop}),C=t.component,{itemSlots:A,inputSlots:c}=Ie(f),{itemAttrs:L,itemOn:x,inputAttrs:_}=Ee(I),M=tt(t),K=y.item===!0?!0:y.item===!1?!1:void 0,F=je({pageItem:a.isItemEnabled(),pageLayoutOn:a.isLayoutEnabled(),internalItem:s,tagItem:K}),E=Ft(a,e,d,M,y),T=z($(o?.props,E),$(t.props,E),ot(_,d.models)),R=le(a.model,d,a.update),B=d.props[0]??e,P=typeof E.label=="string"?E.label:void 0,h=u["col:span"]??S.span,j=u["col:place"]??S.place,ie=me(u["row:column"]??v.column),ae=me(u["row:gutter"]??v.gutter);!F.extraRow&&(ie!=null||ae!=null)&&console.warn("[vue-formless] :row:* is ignored on a leaf control");const $e=C?l.h(C,{...T,...R},c):l.h("div",{class:"vue-formless-control","data-control":e},[P?l.h("label",{class:"vue-formless-control__label"},String(P)):null,String(k(a.model,B)??"")]);return m={fl:{...M,...oe(y)},binding:d,wrapItem:F.wrapItem,wrapCol:F.wrapCol,extraRow:F.extraRow,colSpan:h,colPlace:j,rowColumn:ie,rowGutter:ae,itemAttrs:L,itemOn:x,itemSlots:A},l.h(g,null,()=>$e)}}})}function Ft(e,t,o,n,r){return{...n,...oe(r),controlKey:t,binding:o,getValues:()=>o.props.map(s=>k(e.model,s))}}function Et(e){const t={...e};for(const o of Object.keys(t)){const n=t[o];n&&(t[o]={...n,component:n.component&&typeof n.component=="object"?l.markRaw(n.component):n.component})}return t}exports.DEFAULT_LAYOUT=V;exports.FormView=ht;exports.FormViewItem=se;exports.GRID_TOTAL=p;exports.applyControlBinding=le;exports.bindingForPort=be;exports.camelToPascal=ue;exports.createFormControls=It;exports.createFormView=gt;exports.createLayoutView=ne;exports.formContextKey=N;exports.formItemProp=ye;exports.getIn=k;exports.mergeInternalItem=Pe;exports.overlayProps=z;exports.parsePath=D;exports.pascalToCamel=vt;exports.resolveControlBinding=re;exports.resolveControlShell=je;exports.resolveFormItemProp=lt;exports.resolveProps=$;exports.setIn=we;exports.toBindingList=ee;exports.useFormContext=Y;exports.useFormItem=Ae;exports.useLayoutItem=he;
package/dist/index.d.ts CHANGED
@@ -1 +1,561 @@
1
+ import { AllowedComponentProps } from 'vue';
2
+ import { Component } from 'vue';
3
+ import { ComponentCustomProps } from 'vue';
4
+ import { ComponentOptionsBase } from 'vue';
5
+ import { ComponentOptionsMixin } from 'vue';
6
+ import { ComponentProvideOptions } from 'vue';
7
+ import { CreateComponentPublicInstanceWithMixins } from 'vue';
8
+ import { DefineComponent } from 'vue';
9
+ import { ExtractPropTypes } from 'vue';
10
+ import { GlobalComponents } from 'vue';
11
+ import { GlobalDirectives } from 'vue';
12
+ import { InjectionKey } from 'vue';
13
+ import { PropType } from 'vue';
14
+ import { PublicProps } from 'vue';
15
+ import { Slot } from 'vue';
16
+ import { VNodeChild } from 'vue';
17
+ import { VNodeProps } from 'vue';
18
+
19
+ export declare function applyControlBinding(formModel: unknown, binding: ResolvedControlBinding, update: (prop: string, value: unknown) => void): Record<string, unknown>;
20
+
21
+ /** Slice a multi-port binding to one v-model port (ADR-013 `useFormItem('start')`). */
22
+ export declare function bindingForPort(binding: ResolvedControlBinding, port: string): ResolvedControlBinding;
23
+
24
+ export declare type CamelToPascal<S extends string> = S extends `${infer F}${infer R}` ? `${Uppercase<F>}${R}` : S;
25
+
26
+ /** `name` → `Name`, `idCard` → `IdCard` */
27
+ export declare function camelToPascal(key: string): string;
28
+
29
+ export declare type ColPlace = 'auto' | 'start' | 'end';
30
+
31
+ /** Author-facing Col width: omit / `'Nx'` / `'max'` / absolute 1–24. */
32
+ export declare type ColSpanSpec = string | number;
33
+
34
+ /**
35
+ * Public `$props` of a Vue constructor, functional component, or SFC.
36
+ * `never` / omitted widgets yield `{}` (`never extends Constructor` is true in TS).
37
+ */
38
+ export declare type ComponentPublicProps<C> = [C] extends [never] ? {} : [C] extends [undefined] ? {} : C extends abstract new (...args: any) => {
39
+ $props: infer P;
40
+ } ? P : C extends (props: infer P, ...args: any) => unknown ? P : C extends {
41
+ $props: infer P;
42
+ } ? P : {};
43
+
44
+ export declare interface ControlBindingOverrides {
45
+ prop?: ControlProp;
46
+ }
47
+
48
+ export declare type ControlItemSetting = boolean | 'self';
49
+
50
+ export declare type ControlProp = string | readonly string[];
51
+
52
+ /**
53
+ * Control identity. Adapter extras (e.g. `label`) via `declare module 'vue-formless'`.
54
+ * Extra keys become `ItemFl` fields and optional `fl:*` tag props.
55
+ */
56
+ export declare interface ControlSchema {
57
+ /**
58
+ * Input widget only (no FormItem). Receives v-model bindings from formless.
59
+ * Widget may also declare static `formless: { model, item }`.
60
+ */
61
+ component?: Component;
62
+ /** Input defaults: static object, or derived from the cell snapshot. */
63
+ props?: HostProps<ItemFl>;
64
+ /**
65
+ * v-model names on the widget (ADR-011). Default `'modelValue'`.
66
+ * Locked with the component; tag cannot override. Prefer widget `formless.model`.
67
+ */
68
+ model?: ControlVModel;
69
+ /**
70
+ * Location(s) from FormView root (ADR-011). Default: control key.
71
+ * Overridable via `:fl:prop`. Empty string is illegal.
72
+ * Nested: `buyers[0].name`, `` `buyers[${$index}].name` ``.
73
+ */
74
+ prop?: ControlProp;
75
+ /**
76
+ * Outer wrap: FormView default, then this, then tag `:fl:item`.
77
+ * `'self'`: widget lays out cells via `useFormItem(port)` (ADR-017).
78
+ */
79
+ item?: boolean | 'self';
80
+ }
81
+
82
+ /** Adapter fields on ControlSchema (everything except kernel keys). */
83
+ declare type ControlSchemaExtras = Omit<ControlSchema, ControlSchemaKernelKey>;
84
+
85
+ /**
86
+ * Constraint for `createFormControls` only. `component` stays `unknown` so object
87
+ * literals keep `typeof ElInput` instead of widening to Vue's `Component`.
88
+ */
89
+ declare type ControlSchemaInput = Omit<ControlSchema, 'component'> & {
90
+ component?: unknown;
91
+ };
92
+
93
+ /** Kernel-owned ControlSchema keys. Not extras; tags already have matching `fl:*` where allowed. */
94
+ declare type ControlSchemaKernelKey = 'component' | 'props' | 'model' | 'prop' | 'item';
95
+
96
+ export declare type ControlVModel = string | readonly string[];
97
+
98
+ /**
99
+ * Build a static namespaced control table (ADR-009).
100
+ * Schema keys are camelCase control names → `<User.TimeRange />`.
101
+ */
102
+ export declare function createFormControls<const S extends {
103
+ [K in keyof S]: ControlSchemaInput;
104
+ }>(schema: S, options?: CreateFormControlsOptions): NamespacedControls<S>;
105
+
106
+ export declare interface CreateFormControlsOptions {
107
+ /** Defaults for every control in this cluster (static or from the cell snapshot). */
108
+ props?: HostProps<ItemFl>;
109
+ }
110
+
111
+ /**
112
+ * Bind host layout / form / item once; returns a FormView (ADR-008 / ADR-016).
113
+ *
114
+ * Host shells stay in this closure. Cells go through `useFormItem` / `FormView.Item`.
115
+ *
116
+ * @example
117
+ * ```ts
118
+ * export const FormView = createFormView({
119
+ * layout: { Row: ElRow, Col: ElCol, column: 2, gutter: 16 },
120
+ * form: { component: ElForm, props: (fl) => ({ model: fl.modelValue }) },
121
+ * item: { component: ElFormItem, props: toEpItemProps },
122
+ * })
123
+ * ```
124
+ */
125
+ export declare function createFormView(options?: CreateFormViewOptions): FormViewComponent;
126
+
127
+ export declare interface CreateFormViewOptions {
128
+ /** Row + Col for hosted grid, plus optional project density. */
129
+ layout?: FormViewLayoutBind;
130
+ /** Host form shell. Omit or `:fl:form="false"` skips wrapping. */
131
+ form?: FormViewHostBind<FormFl>;
132
+ /** Host item shell. `props` are defaults (static or from the cell snapshot). */
133
+ item?: FormViewHostBind<ItemFl>;
134
+ }
135
+
136
+ /**
137
+ * Bind host Row/Col once. Returns LayoutView.
138
+ * LayoutItem is not exported; cells call `useLayoutItem()`.
139
+ */
140
+ export declare function createLayoutView(options?: CreateLayoutViewOptions): Component;
141
+
142
+ export declare interface CreateLayoutViewOptions {
143
+ Row?: Component;
144
+ Col?: Component;
145
+ column?: number;
146
+ }
147
+
148
+ /** Kernel column when factory and the LayoutView `column` prop are omitted. */
149
+ export declare const DEFAULT_LAYOUT: {
150
+ readonly column: 1;
151
+ };
152
+
153
+ /** Tag attrs: `label?: string` → `'fl:label'?: string`. Always optional (override, not required). */
154
+ declare type FlExtraProps<T> = {
155
+ [K in keyof T as K extends string ? `fl:${K}` : never]+?: T[K];
156
+ };
157
+
158
+ export declare interface FormContext {
159
+ /** Current FormView `modelValue` (parent snapshot; do not mutate). */
160
+ model: unknown;
161
+ /** Report a field write; FormView patches and emits `update:modelValue`. */
162
+ update: (prop: string, value: unknown) => void;
163
+ /**
164
+ * FormView-owned Item shell.
165
+ * Used by `useFormItem` / `FormView.Item`, not by widget authors.
166
+ */
167
+ wrap: WrapControl;
168
+ /** This FormView layer's Item switch. */
169
+ isItemEnabled: () => boolean;
170
+ /** This FormView's `:fl:layout` switch (page, not nearest LayoutView). */
171
+ isLayoutEnabled: () => boolean;
172
+ /** Factory `createLayoutView` result; reused for gear-4 inner host. */
173
+ LayoutView: Component;
174
+ /** `createFormView({ layout })` density; inner extra rows use this, not the page `:row:*`. */
175
+ factoryColumn: number;
176
+ factoryGutter: number;
177
+ }
178
+
179
+ export declare const formContextKey: InjectionKey<FormContext>;
180
+
181
+ export declare type FormControlComponent<P = {}> = DefineComponent<FormControlProps & P>;
182
+
183
+ /** Kernel `fl:` / `col:` / `row:` keys on `<User.Xxx />`. Schema extras are prefixed automatically. */
184
+ export declare type FormControlProps = {
185
+ 'fl:prop'?: string | string[];
186
+ 'fl:item'?: boolean;
187
+ 'col:span'?: string | number;
188
+ 'col:place'?: 'auto' | 'start' | 'end';
189
+ 'row:column'?: number;
190
+ 'row:gutter'?: number;
191
+ } & FlExtraProps<ControlSchemaExtras>;
192
+
193
+ /** Loose schema bag. Prefer inferring `S` from an object literal via `createFormControls`. */
194
+ export declare type FormControlsSchema = Record<string, ControlSchema>;
195
+
196
+ export declare interface FormFl {
197
+ layout: boolean;
198
+ form: boolean;
199
+ item: boolean;
200
+ /** FormView write-model; map to the host via `form.props` (e.g. `{ model: fl.modelValue }`). */
201
+ modelValue: unknown;
202
+ }
203
+
204
+ export declare type FormFormProp = boolean | 'auto';
205
+
206
+ /** Dot-notation path for ElFormItem `prop` (e.g. `buyers.0.name`). */
207
+ export declare function formItemProp(prop: string): string;
208
+
209
+ /** Factory `layout.column` overlay; gutter lives on `FormViewLayoutBind`. */
210
+ export declare type FormLayoutOptions = Pick<FormViewLayoutBind, 'column'>;
211
+
212
+ /** FormView `:fl:layout` is a boolean switch. Density is factory / `:row:*`. */
213
+ export declare type FormLayoutProp = boolean;
214
+
215
+ /**
216
+ * Context-only FormView (no Row/Col/Form/Item). Prefer `createFormView({ layout: { Row, Col } })`.
217
+ */
218
+ export declare const FormView: {
219
+ new (...args: any[]): CreateComponentPublicInstanceWithMixins<Readonly<ExtractPropTypes< {
220
+ modelValue: {
221
+ type: PropType<unknown>;
222
+ default: undefined;
223
+ };
224
+ 'fl:layout': {
225
+ type: PropType<FormLayoutProp>;
226
+ default: boolean;
227
+ };
228
+ 'row:column': {
229
+ type: NumberConstructor;
230
+ default: undefined;
231
+ };
232
+ 'row:gutter': {
233
+ type: NumberConstructor;
234
+ default: undefined;
235
+ };
236
+ 'fl:form': {
237
+ type: PropType<FormFormProp>;
238
+ default: string;
239
+ };
240
+ 'fl:item': {
241
+ type: BooleanConstructor;
242
+ default: boolean;
243
+ };
244
+ }>> & Readonly<{
245
+ "onUpdate:modelValue"?: ((_value: unknown) => any) | undefined;
246
+ }>, () => VNodeChild, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
247
+ 'update:modelValue': (_value: unknown) => boolean;
248
+ }, PublicProps, {
249
+ modelValue: undefined;
250
+ 'fl:layout': boolean;
251
+ 'row:column': number;
252
+ 'row:gutter': number;
253
+ 'fl:form': FormFormProp;
254
+ 'fl:item': boolean;
255
+ }, true, {}, {}, GlobalComponents, GlobalDirectives, string, {}, any, ComponentProvideOptions, {
256
+ P: {};
257
+ B: {};
258
+ D: {};
259
+ C: {};
260
+ M: {};
261
+ Defaults: {};
262
+ }, Readonly<ExtractPropTypes< {
263
+ modelValue: {
264
+ type: PropType<unknown>;
265
+ default: undefined;
266
+ };
267
+ 'fl:layout': {
268
+ type: PropType<FormLayoutProp>;
269
+ default: boolean;
270
+ };
271
+ 'row:column': {
272
+ type: NumberConstructor;
273
+ default: undefined;
274
+ };
275
+ 'row:gutter': {
276
+ type: NumberConstructor;
277
+ default: undefined;
278
+ };
279
+ 'fl:form': {
280
+ type: PropType<FormFormProp>;
281
+ default: string;
282
+ };
283
+ 'fl:item': {
284
+ type: BooleanConstructor;
285
+ default: boolean;
286
+ };
287
+ }>> & Readonly<{
288
+ "onUpdate:modelValue"?: ((_value: unknown) => any) | undefined;
289
+ }>, () => VNodeChild, {}, {}, {}, {
290
+ modelValue: undefined;
291
+ 'fl:layout': boolean;
292
+ 'row:column': number;
293
+ 'row:gutter': number;
294
+ 'fl:form': FormFormProp;
295
+ 'fl:item': boolean;
296
+ }>;
297
+ __isFragment?: never;
298
+ __isTeleport?: never;
299
+ __isSuspense?: never;
300
+ } & ComponentOptionsBase<Readonly<ExtractPropTypes< {
301
+ modelValue: {
302
+ type: PropType<unknown>;
303
+ default: undefined;
304
+ };
305
+ 'fl:layout': {
306
+ type: PropType<FormLayoutProp>;
307
+ default: boolean;
308
+ };
309
+ 'row:column': {
310
+ type: NumberConstructor;
311
+ default: undefined;
312
+ };
313
+ 'row:gutter': {
314
+ type: NumberConstructor;
315
+ default: undefined;
316
+ };
317
+ 'fl:form': {
318
+ type: PropType<FormFormProp>;
319
+ default: string;
320
+ };
321
+ 'fl:item': {
322
+ type: BooleanConstructor;
323
+ default: boolean;
324
+ };
325
+ }>> & Readonly<{
326
+ "onUpdate:modelValue"?: ((_value: unknown) => any) | undefined;
327
+ }>, () => VNodeChild, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
328
+ 'update:modelValue': (_value: unknown) => boolean;
329
+ }, string, {
330
+ modelValue: undefined;
331
+ 'fl:layout': boolean;
332
+ 'row:column': number;
333
+ 'row:gutter': number;
334
+ 'fl:form': FormFormProp;
335
+ 'fl:item': boolean;
336
+ }, {}, string, {}, GlobalComponents, GlobalDirectives, string, ComponentProvideOptions> & VNodeProps & AllowedComponentProps & ComponentCustomProps & {
337
+ Item: typeof FormViewItem;
338
+ };
339
+
340
+ export declare type FormViewComponent = Component & {
341
+ Item: typeof FormViewItem;
342
+ };
343
+
344
+ export declare interface FormViewHostBind<TFl> {
345
+ component: Component;
346
+ props?: HostProps<TFl>;
347
+ }
348
+
349
+ /** Page-level anonymous cell. Same wrap as `useFormItem()`. */
350
+ export declare const FormViewItem: FormViewItemComponent;
351
+
352
+ declare type FormViewItemComponent = DefineComponent<FormViewItemProps>;
353
+
354
+ /** Kernel keys on `FormView.Item` / `useFormItem()`. Schema extras are prefixed automatically. */
355
+ export declare type FormViewItemProps = {
356
+ 'fl:prop'?: string | string[];
357
+ 'col:span'?: string | number;
358
+ 'col:place'?: 'auto' | 'start' | 'end';
359
+ } & FlExtraProps<ControlSchemaExtras>;
360
+
361
+ export declare interface FormViewItemSlotProps {
362
+ /** `applyControlBinding` result (`modelValue` + `onUpdate:modelValue` for a single leaf). */
363
+ field: Record<string, unknown>;
364
+ }
365
+
366
+ export declare interface FormViewLayoutBind {
367
+ Row: Component;
368
+ Col: Component;
369
+ column?: number;
370
+ gutter?: number;
371
+ }
372
+
373
+ export declare interface FormViewProps {
374
+ modelValue?: unknown;
375
+ /**
376
+ * Grid hosting switch. Default `false`.
377
+ * Density: this FormView's factory `layout.column/gutter` plus `:row:column` / `:row:gutter`.
378
+ * Nested FormView / extra rows do not inherit this instance overlay.
379
+ */
380
+ 'fl:layout'?: FormLayoutProp;
381
+ 'row:column'?: number;
382
+ 'row:gutter'?: number;
383
+ /**
384
+ * Wrap the factory `form`. Default `'auto'`: on at the root, off when nested.
385
+ * Explicit `true` / `false` win.
386
+ */
387
+ 'fl:form'?: FormFormProp;
388
+ /** Wrap the factory `item` per cell (default `true` when `item.component` is bound). */
389
+ 'fl:item'?: boolean;
390
+ }
391
+
392
+ export declare function getIn(root: unknown, prop: string): unknown;
393
+
394
+ /** Host Col span modulus (Element / Ant Design 24-grid). */
395
+ export declare const GRID_TOTAL = 24;
396
+
397
+ /** Static host props, or derived from that layer's snapshot. */
398
+ export declare type HostProps<TFl> = Record<string, unknown> | ((fl: TFl) => Record<string, unknown> | undefined);
399
+
400
+ /**
401
+ * Snapshot for `item.props` / control `props` functions.
402
+ * Kernel wiring + ControlSchema extras. Not passed as a host component prop.
403
+ */
404
+ export declare type ItemFl = {
405
+ controlKey: string;
406
+ binding: ResolvedControlBinding;
407
+ getValues: () => unknown[];
408
+ [extra: string]: unknown;
409
+ } & ControlSchemaExtras;
410
+
411
+ export declare interface LayoutItemProps {
412
+ span?: ColSpanSpec;
413
+ place?: ColPlace;
414
+ }
415
+
416
+ export declare interface LayoutViewProps {
417
+ disabled?: boolean;
418
+ column?: number;
419
+ }
420
+
421
+ declare type LockedKeysForDef<Def> = LockedVModelKeys<SchemaModel<Def> extends ControlVModel | undefined ? SchemaModel<Def> : undefined>;
422
+
423
+ export declare type LockedVModelKeys<M extends ControlVModel | undefined> = ModelPortNames<M> | `onUpdate:${ModelPortNames<M>}`;
424
+
425
+ /** Widget `formless.item` vs schema `item`. `'self'` vs `false` is illegal. */
426
+ export declare function mergeInternalItem(widget?: ControlItemSetting, schema?: ControlItemSetting): ControlItemSetting | undefined;
427
+
428
+ declare type ModelPortNames<M> = [M] extends [undefined] ? 'modelValue' : M extends string ? M : M extends readonly [infer F extends string, ...infer R] ? F | ModelPortNames<R> : 'modelValue';
429
+
430
+ /**
431
+ * PascalCase control tags. `S` must not be `Record<string, _>` or `keyof` collapses
432
+ * to `string` and Volar/TS lose `User.Name` / `User.IdCard` as named keys.
433
+ * Tag props are `fl:*` plus the widget's public props (v-model ports locked).
434
+ */
435
+ export declare type NamespacedControls<S> = {
436
+ [K in keyof S & string as CamelToPascal<K>]: FormControlComponent<WidgetTagProps<S[K]>>;
437
+ };
438
+
439
+ /** Later layers win. `undefined` does not override. Empty string is a value. */
440
+ export declare function overlayProps(...layers: Array<Record<string, unknown> | undefined>): Record<string, unknown>;
441
+
442
+ export declare function parsePath(prop: string): PathSegment[];
443
+
444
+ /** `Name` → `name`, `IdCard` → `idCard` */
445
+ export declare function pascalToCamel(key: string): string;
446
+
447
+ /**
448
+ * Parse `prop` location strings: object keys and `[index]` segments.
449
+ * Examples: `name`, `buyers[0].name`, `[2].title`
450
+ */
451
+ export declare type PathSegment = {
452
+ type: 'key';
453
+ key: string;
454
+ } | {
455
+ type: 'index';
456
+ index: number;
457
+ };
458
+
459
+ export declare function resolveControlBinding(controlKey: string, options?: {
460
+ model?: ControlVModel;
461
+ prop?: ControlProp;
462
+ }, overrides?: ControlBindingOverrides): ResolvedControlBinding;
463
+
464
+ /**
465
+ * FormView < internal < tag (ADR-017).
466
+ * Pure `'self'` skips outer Item+Col. `'self'` + explicit tag item true
467
+ * wraps outer Item (and Col when page layout is on) and asks for an inner Row.
468
+ * Col follows the Row host only; no control/cell layout switch.
469
+ */
470
+ export declare function resolveControlShell(input: ResolveControlShellInput): ResolvedControlShell;
471
+
472
+ declare interface ResolveControlShellInput {
473
+ pageItem: boolean;
474
+ pageLayoutOn: boolean;
475
+ internalItem?: ControlItemSetting;
476
+ /** Tag `:fl:item`. Omitted ≠ `true`. */
477
+ tagItem?: boolean;
478
+ }
479
+
480
+ export declare interface ResolvedControlBinding {
481
+ models: string[];
482
+ props: string[];
483
+ }
484
+
485
+ export declare interface ResolvedControlShell {
486
+ wrapItem: boolean;
487
+ wrapCol: boolean;
488
+ extraRow: boolean;
489
+ self: boolean;
490
+ }
491
+
492
+ /**
493
+ * Optional Element-style encoding: one location → dotted path; several →
494
+ * control key. Kernel does not put this on Item `fl` — the adapter Item
495
+ * calls this (or encodes another way) when mapping to host `prop`.
496
+ */
497
+ export declare function resolveFormItemProp(binding: ResolvedControlBinding, controlKey: string): string;
498
+
499
+ export declare function resolveProps<TFl>(spec: HostProps<TFl> | undefined, fl: TFl): Record<string, unknown>;
500
+
501
+ /**
502
+ * v-model ports locked on the tag (ADR-011). Schema `model` wins;
503
+ * omitted `model` locks the default `'modelValue'`.
504
+ * Widened `string[]` is not treated as port names (would Omit every string key).
505
+ */
506
+ declare type SchemaModel<Def> = Def extends {
507
+ model: infer M;
508
+ } ? M : undefined;
509
+
510
+ /** Immutable write at a full `prop` location (`buyers[0].name`). Arrays are cloned. */
511
+ export declare function setIn(root: unknown, prop: string, value: unknown): unknown;
512
+
513
+ export declare function toBindingList(value: ControlVModel | ControlProp): string[];
514
+
515
+ export declare function useFormContext(): FormContext;
516
+
517
+ /**
518
+ * One cell: LayoutItem? → Item? → (inner LayoutView?) → default slot.
519
+ * No arg: this control's full binding (factory outer wrap).
520
+ * Port: slice one v-model mouth.
521
+ * Outer wrap follows the merged shell (ADR-017); binding stays on the frame.
522
+ */
523
+ export declare function useFormItem(port?: string): FormViewItemComponent;
524
+
525
+ /** Nearest LayoutView's cell component; identity when no LayoutView. */
526
+ export declare function useLayoutItem(): Component;
527
+
528
+ export declare interface WidgetFormless {
529
+ model?: string | string[];
530
+ item?: boolean | 'self';
531
+ }
532
+
533
+ /** Widget props that may appear on `<User.Xxx />` (v-model ports stripped). */
534
+ export declare type WidgetTagProps<Def> = Def extends {
535
+ component?: infer C;
536
+ } ? [Exclude<C, undefined>] extends [never] ? {} : Omit<ComponentPublicProps<Exclude<C, undefined>>, LockedKeysForDef<Def>> : {};
537
+
538
+ /** FormView-owned Item shell. Col is owned by LayoutView / useLayoutItem. */
539
+ export declare type WrapControl = (body: VNodeChild, meta: WrapControlMeta) => VNodeChild;
540
+
541
+ /** Input Control hands to FormView's wrap: Item snapshot + host fallthrough. */
542
+ export declare interface WrapControlMeta {
543
+ /**
544
+ * This wrap only. `false` skips Item even when FormView `item` is on.
545
+ * `true` forces Item even when FormView `item` is off. Omit = follow FormView.
546
+ */
547
+ item?: boolean;
548
+ fl: ItemFl;
549
+ itemAttrs: Record<string, unknown>;
550
+ itemOn: Record<string, unknown>;
551
+ itemSlots: Record<string, Slot>;
552
+ }
553
+
1
554
  export { }
555
+
556
+
557
+ declare module 'vue' {
558
+ interface ComponentCustomOptions {
559
+ formless?: WidgetFormless;
560
+ }
561
+ }