vue-formless 0.1.1 → 0.2.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/README.en.md +58 -14
- package/README.md +57 -14
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +278 -422
- package/dist/index.js +618 -834
- package/package.json +1 -1
package/README.en.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
English | [简体中文](./README.md)
|
|
4
4
|
|
|
5
|
-
> Vue 3 form library: a page-level control table plus FormView, with layout kept off the inputs. **0.
|
|
5
|
+
> Vue 3 form library: a page-level control table plus FormView, with layout kept off the inputs. **0.2.0** — APIs may still change in 0.x.
|
|
6
6
|
|
|
7
7
|
Same mixed layout: Element Row/Col/Item on the left, `<User.*>` plus nested `FormView` density on the right.
|
|
8
8
|
|
|
@@ -25,30 +25,64 @@ Bind host Form / Item / Row / Col once in the project (no official Element adapt
|
|
|
25
25
|
|
|
26
26
|
```ts
|
|
27
27
|
import { ElCol, ElForm, ElFormItem, ElInput, ElRow } from 'element-plus'
|
|
28
|
-
import {
|
|
28
|
+
import { defineComponent, h, ref, type PropType } from 'vue'
|
|
29
|
+
import { createFormFields, createFormView, type FormFieldFormless } from 'vue-formless'
|
|
29
30
|
|
|
30
31
|
declare module 'vue-formless' {
|
|
31
|
-
interface
|
|
32
|
+
interface FormFieldCustomOptions {
|
|
32
33
|
label?: string
|
|
33
34
|
}
|
|
34
35
|
}
|
|
35
36
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
37
|
+
// ElFormItem `prop` speaks dot paths; the kernel location (`buyers[0].name`)
|
|
38
|
+
// is encoded here, in the adapter (design.md §20.9). One host `prop` cannot hold
|
|
39
|
+
// several ports, so such a field stays unbound (`undefined`) — use
|
|
40
|
+
// `fl:field="wrap-embed"` (one port per field) when the host must validate it.
|
|
41
|
+
function toItemProp(prop: FormFieldFormless['prop']): string | undefined {
|
|
42
|
+
if (prop == null || prop.length !== 1) return undefined
|
|
43
|
+
const [location] = prop
|
|
44
|
+
if (location == null) return undefined
|
|
45
|
+
const dotted = location.replace(/\[(\d+)\]/g, '.$1').replace(/^\./, '')
|
|
46
|
+
if (!dotted || /[[\]]/.test(dotted)) return undefined // unencodable: leave unbound
|
|
47
|
+
return dotted
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// The no-prefix write model `modelValue` falls through to the host Form, but
|
|
51
|
+
// ElForm names its model port `model`: the adapter wraps it in a MyForm that
|
|
52
|
+
// maps the port and forwards ElForm's exposed instance methods (validate /
|
|
53
|
+
// resetFields) up to FormView's ref proxy. The factory no longer takes a
|
|
54
|
+
// functional `form.props`.
|
|
55
|
+
const MyForm = defineComponent({
|
|
56
|
+
inheritAttrs: false,
|
|
57
|
+
props: { modelValue: { type: [Object, Array] as PropType<unknown>, default: undefined } },
|
|
58
|
+
setup(props, { attrs, slots, expose }) {
|
|
59
|
+
const form = ref<Record<string, unknown> | null>(null)
|
|
60
|
+
expose(new Proxy({}, {
|
|
61
|
+
get: (_, key) => {
|
|
62
|
+
const inner = form.value
|
|
63
|
+
if (inner == null) return undefined
|
|
64
|
+
const value = Reflect.get(inner, key, inner)
|
|
65
|
+
return typeof value === 'function' ? value.bind(inner) : value
|
|
66
|
+
},
|
|
67
|
+
has: (_, key) => form.value != null && key in form.value,
|
|
68
|
+
}))
|
|
69
|
+
return () => h(ElForm, { ...attrs, ref: form, model: props.modelValue }, slots)
|
|
41
70
|
},
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
export const FormView = createFormView({
|
|
74
|
+
layout: { Row: ElRow, Col: ElCol, props: { column: 2 } },
|
|
75
|
+
form: { component: MyForm },
|
|
42
76
|
item: {
|
|
43
77
|
component: ElFormItem,
|
|
44
|
-
props: (fl:
|
|
78
|
+
props: (fl: FormFieldFormless) => ({
|
|
45
79
|
label: fl.label,
|
|
46
|
-
prop:
|
|
80
|
+
prop: toItemProp(fl.prop),
|
|
47
81
|
}),
|
|
48
82
|
},
|
|
49
83
|
})
|
|
50
84
|
|
|
51
|
-
export const User =
|
|
85
|
+
export const User = createFormFields({
|
|
52
86
|
name: { label: 'Name', component: ElInput },
|
|
53
87
|
})
|
|
54
88
|
```
|
|
@@ -56,11 +90,20 @@ export const User = createFormControls({
|
|
|
56
90
|
```vue
|
|
57
91
|
<FormView ref="formRef" v-model="form" fl:layout label-width="96px">
|
|
58
92
|
<User.Name />
|
|
59
|
-
<User.Name
|
|
93
|
+
<User.Name layout-item:span="max" />
|
|
60
94
|
</FormView>
|
|
61
95
|
```
|
|
62
96
|
|
|
63
|
-
`validate()` / `resetFields()` go through the FormView ref (proxied host Form). Layout details: [docs/adr](./docs/adr
|
|
97
|
+
`validate()` / `resetFields()` go through the FormView ref (proxied host Form). Layout details: [docs/adr](./docs/adr.md).
|
|
98
|
+
|
|
99
|
+
## Live playgrounds
|
|
100
|
+
|
|
101
|
+
GitHub Pages (set **Settings → Pages → Source** to GitHub Actions; deploys from `main`):
|
|
102
|
+
|
|
103
|
+
- Forms: [https://xuyimingwork.github.io/vue-formx/](https://xuyimingwork.github.io/vue-formx/)
|
|
104
|
+
- 24-col layout: [https://xuyimingwork.github.io/vue-formx/layout/](https://xuyimingwork.github.io/vue-formx/layout/)
|
|
105
|
+
|
|
106
|
+
Local preview of the Pages bundle: `PAGES_BASE=/vue-formx/ pnpm build:pages`, then serve `site/`.
|
|
64
107
|
|
|
65
108
|
## Layout
|
|
66
109
|
|
|
@@ -68,7 +111,8 @@ export const User = createFormControls({
|
|
|
68
111
|
packages/vue-formless # kernel (npm: vue-formless)
|
|
69
112
|
packages/layout # internal grid, bundled into the kernel
|
|
70
113
|
playground # Element Plus baseline vs Formless
|
|
71
|
-
|
|
114
|
+
playground-layout # 24-col layout studio
|
|
115
|
+
docs/adr.md # architecture decisions (single doc)
|
|
72
116
|
```
|
|
73
117
|
|
|
74
118
|
## Development
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
简体中文 | [English](./README.en.md)
|
|
4
4
|
|
|
5
|
-
> Vue 3 表单组合式库:控件表 + FormView,布局与输入拆开。当前 **0.
|
|
5
|
+
> Vue 3 表单组合式库:控件表 + FormView,布局与输入拆开。当前 **0.2.0**,`0.x` 期间 API 仍可能调整。
|
|
6
6
|
|
|
7
7
|
同一套混合布局:左边手写 Element Row/Col/Item,右边 `<User.*>` + 嵌套 `FormView` 换密度。
|
|
8
8
|
|
|
@@ -25,30 +25,61 @@ peer:`vue` ^3.3。
|
|
|
25
25
|
|
|
26
26
|
```ts
|
|
27
27
|
import { ElCol, ElForm, ElFormItem, ElInput, ElRow } from 'element-plus'
|
|
28
|
-
import {
|
|
28
|
+
import { defineComponent, h, ref, type PropType } from 'vue'
|
|
29
|
+
import { createFormFields, createFormView, type FormFieldFormless } from 'vue-formless'
|
|
29
30
|
|
|
30
31
|
declare module 'vue-formless' {
|
|
31
|
-
interface
|
|
32
|
+
interface FormFieldCustomOptions {
|
|
32
33
|
label?: string
|
|
33
34
|
}
|
|
34
35
|
}
|
|
35
36
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
37
|
+
// ElFormItem 的 `prop` 用点分路径;内核位置(`buyers[0].name`)由本层编码(design.md §20.9)。
|
|
38
|
+
// 一个宿主 `prop` 装不下多个口 → 多口一格不绑宿主(`undefined`),
|
|
39
|
+
// 需要宿主校验就用 `fl:field="wrap-embed"` 拆成一格一口。
|
|
40
|
+
function toItemProp(prop: FormFieldFormless['prop']): string | undefined {
|
|
41
|
+
if (prop == null || prop.length !== 1) return undefined
|
|
42
|
+
const [location] = prop
|
|
43
|
+
if (location == null) return undefined
|
|
44
|
+
const dotted = location.replace(/\[(\d+)\]/g, '.$1').replace(/^\./, '')
|
|
45
|
+
if (!dotted || /[[\]]/.test(dotted)) return undefined // 编不出来:不绑宿主
|
|
46
|
+
return dotted
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// 无前缀的写口 `modelValue` 按 no-prefix 规则透传到宿主 Form,而 ElForm 的 model
|
|
50
|
+
// 口叫 `model`:适配层用一个 MyForm 包住 ElForm 完成映射,并把 ElForm 实例的
|
|
51
|
+
// validate / resetFields 透出给 FormView 的 ref 代理。工厂不再接受 form.props 函数。
|
|
52
|
+
const MyForm = defineComponent({
|
|
53
|
+
inheritAttrs: false,
|
|
54
|
+
props: { modelValue: { type: [Object, Array] as PropType<unknown>, default: undefined } },
|
|
55
|
+
setup(props, { attrs, slots, expose }) {
|
|
56
|
+
const form = ref<Record<string, unknown> | null>(null)
|
|
57
|
+
expose(new Proxy({}, {
|
|
58
|
+
get: (_, key) => {
|
|
59
|
+
const inner = form.value
|
|
60
|
+
if (inner == null) return undefined
|
|
61
|
+
const value = Reflect.get(inner, key, inner)
|
|
62
|
+
return typeof value === 'function' ? value.bind(inner) : value
|
|
63
|
+
},
|
|
64
|
+
has: (_, key) => form.value != null && key in form.value,
|
|
65
|
+
}))
|
|
66
|
+
return () => h(ElForm, { ...attrs, ref: form, model: props.modelValue }, slots)
|
|
41
67
|
},
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
export const FormView = createFormView({
|
|
71
|
+
layout: { Row: ElRow, Col: ElCol, props: { column: 2 } },
|
|
72
|
+
form: { component: MyForm },
|
|
42
73
|
item: {
|
|
43
74
|
component: ElFormItem,
|
|
44
|
-
props: (fl:
|
|
75
|
+
props: (fl: FormFieldFormless) => ({
|
|
45
76
|
label: fl.label,
|
|
46
|
-
prop:
|
|
77
|
+
prop: toItemProp(fl.prop),
|
|
47
78
|
}),
|
|
48
79
|
},
|
|
49
80
|
})
|
|
50
81
|
|
|
51
|
-
export const User =
|
|
82
|
+
export const User = createFormFields({
|
|
52
83
|
name: { label: '姓名', component: ElInput },
|
|
53
84
|
})
|
|
54
85
|
```
|
|
@@ -56,11 +87,20 @@ export const User = createFormControls({
|
|
|
56
87
|
```vue
|
|
57
88
|
<FormView ref="formRef" v-model="form" fl:layout label-width="96px">
|
|
58
89
|
<User.Name />
|
|
59
|
-
<User.Name
|
|
90
|
+
<User.Name layout-item:span="max" />
|
|
60
91
|
</FormView>
|
|
61
92
|
```
|
|
62
93
|
|
|
63
|
-
`validate()` / `resetFields()` 走 FormView 的 ref(代理内层 Form)。栅格细节见 [docs/adr](./docs/adr
|
|
94
|
+
`validate()` / `resetFields()` 走 FormView 的 ref(代理内层 Form)。栅格细节见 [docs/adr](./docs/adr.md)。
|
|
95
|
+
|
|
96
|
+
## 在线 Playground
|
|
97
|
+
|
|
98
|
+
GitHub Pages(仓库需在 **Settings → Pages → Source** 选 GitHub Actions,推 `main` 后生成):
|
|
99
|
+
|
|
100
|
+
- 表单对照:[https://xuyimingwork.github.io/vue-formx/](https://xuyimingwork.github.io/vue-formx/)
|
|
101
|
+
- 24 格布局:[https://xuyimingwork.github.io/vue-formx/layout/](https://xuyimingwork.github.io/vue-formx/layout/)
|
|
102
|
+
|
|
103
|
+
本地预览打包结果:`PAGES_BASE=/vue-formx/ pnpm build:pages`,再用任意静态服务器打开 `site/`。
|
|
64
104
|
|
|
65
105
|
## 仓库结构
|
|
66
106
|
|
|
@@ -68,7 +108,8 @@ export const User = createFormControls({
|
|
|
68
108
|
packages/vue-formless # 内核(npm:vue-formless)
|
|
69
109
|
packages/layout # 内部栅格,打进内核 dist
|
|
70
110
|
playground # Element Plus 基线 vs Formless
|
|
71
|
-
|
|
111
|
+
playground-layout # 24 格布局工作台
|
|
112
|
+
docs/adr.md # 架构决策(单篇汇总)
|
|
72
113
|
```
|
|
73
114
|
|
|
74
115
|
## 开发
|
|
@@ -86,6 +127,8 @@ Playground 对照:基础表单、筛选条、只读详情、混合布局、Dat
|
|
|
86
127
|
```bash
|
|
87
128
|
pnpm playground
|
|
88
129
|
# http://localhost:5173
|
|
130
|
+
pnpm playground:layout
|
|
131
|
+
# http://localhost:5174
|
|
89
132
|
```
|
|
90
133
|
|
|
91
134
|
## License
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
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;
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const u=require("vue"),F=24,Y=1;function E(e){return Math.min(F,Math.max(1,e))}function G(e){return Math.floor(F/R(e))}function R(e){const t=Math.floor(Number(e));return Number.isNaN(t)?Y:E(t)}function Z(...e){return R([...e].reverse().find(t=>t!=null))}function X(e,t){const n=G(t);if(typeof e!="number"&&typeof e!="string"||(e=typeof e=="string"?e.trim().toLowerCase():e,e===""))return n;if(e==="max")return F;if(typeof e=="string"&&e.endsWith("x")){const r=Math.floor(Number(e.substring(0,e.length-1)));return Number.isNaN(r)?n:E(E(r)*n)}return e=Math.floor(Number(e)),Number.isNaN(e)?n:E(e)}function J(e){return e=typeof e=="string"?e.trim().toLowerCase():e,e==="start"||e==="end"?e:"auto"}const w=Symbol("vue-formless:layout-view");function Q(e){return e.reduce((t,n,r)=>{const o=t[r-1],i=o?o.$start+o.$occupied:0,c=i%F,d=ee({cursor:c,span:n.span,place:n.place});return t.push({...n,$start:i,$occupied:d}),t},[])}function ee({cursor:e,place:t,span:n}){const r=F-e;return t==="start"?e===0?n:r+n:t==="end"?r>=n?r:r+F:r>=n?n:r+n}function te(e,t,n){const r=e%F,o=r+t>F?F-r:0,i=t-o-n;return[o,i].filter(c=>c>0)}function ne(e,t,n={childList:!0}){if(typeof MutationObserver>"u")return;let r=null;function o(c){r?.disconnect(),r=null,c&&(r=new MutationObserver(t),r.observe(c,n))}u.onMounted(()=>o(u.toValue(e)));const i=u.watch(()=>u.toValue(e),o,{flush:"post"});u.onBeforeUnmount(()=>{i(),r?.disconnect(),r=null})}function re(e,t=0){const n=u.ref([]);function r(){const o=u.toValue(e);n.value=o?Array.from(o.children):[]}return u.watch(()=>[u.toValue(e),u.toValue(t)],r,{immediate:!0}),ne(e,r),n}function S(e){if(e==null||typeof e!="object")return null;if(typeof Element<"u"&&e instanceof Element)return e;const t=e.$el;return typeof Element<"u"&&t instanceof Element?t:null}const j=u.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 u.createVNode(u.Fragment,null,[e.spans.map((n,r)=>u.createVNode(t,{key:r,span:n,"aria-hidden":"true","data-layout-blank":""},null))])}}}),T=u.defineComponent({name:"LayoutItem",inheritAttrs:!1,props:{span:{type:[String,Number],default:void 0},place:{type:String,default:void 0}},setup(e,{slots:t,attrs:n,expose:r}){const o=u.inject(w,null);if(!o)return()=>t.default?.()??null;const{span:i,blank:c,ref:d,Col:a,disabled:s,place:f}=o(()=>e.span,()=>e.place),m=u.ref(null);r({el:u.computed(()=>S(m.value))});function y(p){m.value=p,d(p)}return()=>{if(s.value)return t.default?.()??null;const p=a;return u.createVNode(u.Fragment,null,[u.createVNode(j,{is:a,spans:c.value.before},null),u.createVNode(p,u.mergeProps(n,{ref:y,span:i.value,"data-layout-item":"","data-layout-place":f.value}),{default:()=>[t.default?.()??null]}),u.createVNode(j,{is:a,spans:c.value.after},null)])}}});function ue({column:e,rowRef:t}){let n=0;const r=u.ref({}),o=re(()=>S(t.value),()=>Object.keys(r.value).filter(a=>r.value[a].mounted).join(",")),i=u.computed(()=>oe(r.value,o.value)),c=u.computed(()=>Q(i.value)),d=u.computed(()=>new Map(c.value.map(a=>[a.id,te(a.$start,a.$occupied,a.span)])));return{setup(a,s){const f=String(++n);return r.value[f]={span:u.computed(()=>X(u.toValue(a),u.toValue(e))),place:u.computed(()=>J(u.toValue(s))),el:null,mounted:!1},u.onMounted(()=>{const m=r.value[f];m&&(m.mounted=!0)}),u.onBeforeUnmount(()=>{delete r.value[f]}),f},span(a){return r.value[a]?.span??0},blank(a){return{before:d.value.get(a)??[],after:[]}},place(a){return r.value[a]?.place??"unknown"},ref(a,s){const f=r.value[a];if(!f)return;const m=S(s);f.el!==m&&(f.el=m)},placed(a){return c.value.findIndex(s=>s.id===a)>-1}}}function oe(e,t){const n=new Map(Object.entries(e).filter(([,r])=>r.el).map(([r,o])=>[o.el,{id:r,span:o.span,place:o.place}]));return t.filter(r=>n.has(r)).map(r=>n.get(r))}function P(e={}){const{Row:t,Col:n}=e;return u.defineComponent({name:"LayoutView",inheritAttrs:!1,props:{disabled:{type:Boolean,default:!1},column:{type:Number,default:void 0}},setup(r,{slots:o,attrs:i}){const c=u.computed(()=>!t||!n||r.disabled),d=u.computed(()=>Z(e.column,r.column)),a=u.ref(null),s=ue({column:d,rowRef:a});return u.provide(w,(f,m)=>{u.provide(w,null);const y=s.setup(f,m);return{span:u.computed(()=>s.span(y)),blank:u.computed(()=>s.blank(y)),ref:p=>s.ref(y,p),place:u.computed(()=>s.place(y)),placed:u.computed(()=>s.placed(y)),Col:n,disabled:c}}),()=>{if(c.value)return o.default?.()??null;const f=t;return u.createVNode(f,u.mergeProps({ref:a},i,{"data-layout-row":""}),{default:()=>[o.default?.()??null]})}}})}function le(e={}){const t=e.component?u.markRaw(e.component):void 0;return u.defineComponent({name:"FormItem",inheritAttrs:!1,props:{fl:{type:Object,required:!0},item:{type:Object,required:!0}},setup(n,{slots:r}){return()=>{if(!t||!n.fl?.item)return r.default?.()??null;const o=t,i=typeof e.props=="function"?e.props(n.fl):e.props;return u.createVNode(o,{...i,...n.item},r)}}})}const k=Symbol("vue-formless:form-view"),_=Symbol("vue-formless:form-field"),A=Symbol("EOF"),g=Symbol("failed"),ae=/[a-zA-Z_$0-9]/,ie=/[a-zA-Z0-9_$]/,ce=/[0-9]/;function $(e){if(!e)return;const t=[];let n="",r="",o=0;function i(l){if(l==="[")return s;if(l!==A)return typeof l=="string"&&ae.test(l)?(n=l,a):g}function c(l){return l==="."?d:i(l)}function d(l){return l===A||l==="."?g:i(l)}function a(l){return typeof l=="string"&&ie.test(l)?(n+=l,a):(t.push({type:"key",key:n}),n="",c(l))}function s(l){if(l===A)return g;if(typeof l=="string"&&(l==='"'||l==="'"))return r=l,n="",f;if(typeof l=="string"&&ce.test(l))return n+=l,s;if(l!=="]")return g;const v=Number(n);return n===""||String(v)!==n||v<0?g:(t.push({type:"index",index:v}),n="",c)}function f(l){return l===A?g:l==="\\"?m:l===r?y:(n+=l,f)}function m(l){return l===A?g:(n+=l,f)}function y(l){return l===A||l!=="]"?g:(t.push({type:"key",key:n}),n="",c)}let p=i;for(;o<e.length;o++){const l=p(e[o]);if(l===g)return;p=l}if(p(A)!==g)return t}function H(e){return typeof e=="object"&&e!==null}const se=Object.prototype.hasOwnProperty;function fe(e,t){return se.call(e,t)?e[t]:void 0}function q(e,t){if(H(e)){if(t.type==="key")return Array.isArray(e)?void 0:fe(e,t.key);if(t.type==="index")return Array.isArray(e)?e[t.index]:void 0}}function de(e,t){let n=e;for(const r of t)n=q(n,r);return n}function me(e,t){const n=$(t);return n?de(e,n):void 0}function pe(e,t,n){const r=$(t);return r?D(e,r,n):e}function D(e,t,n){if(!t.length)return e;if(t.length===1)return x(e,t[0],n);const[r,...o]=t;return x(e,r,D(q(e,r),o,n))}function x(e,t,n){if(t.type==="key")return{...H(e)&&!Array.isArray(e)?e:{},[t.key]:n};if(t.type==="index"){const r=Array.isArray(e)?[...e]:[];return r[t.index]=n,r}return e}function ye(e){let t=null;function n(o){return me(e.value,o)}function r(o,i){t||(t=[],u.nextTick(()=>{const c=t;if(t=null,!c?.length)return;let d=e.value;for(const a of c)d=pe(d,a.path,a.value);e.value=d})),t.push({path:o,value:i})}return{getIn:n,setIn:r}}const ve=["modelValue","model-value"],be=["onUpdate:modelValue","onUpdate:model-value"];function ge(e,t){const n=u.computed(()=>ve.find(i=>i in e)),r=u.computed(()=>be.find(i=>typeof e[i]=="function")),o=u.computed(()=>n.value?"controlled":t?"inherit":"local");return{key:n,event:r,source:o}}function Fe(){const e=u.useAttrs(),t=u.inject(k,null),{source:n,key:r,event:o}=ge(e,!!t),i=u.ref(),c=u.computed({get:()=>n.value==="controlled"?e[r.value]:i.value,set:m=>{n.value==="local"&&(i.value=m),o.value&&e[o.value](m)}}),d=ye(c),a=u.computed(()=>n.value==="inherit"?t.value.value:c.value);function s(m){return n.value==="inherit"?t.getIn(m):d.getIn(m)}function f(m,y){return n.value==="inherit"?t.setIn(m,y):d.setIn(m,y)}return u.provide(k,{value:a,getIn:s,setIn:f}),{value:a,getIn:s,setIn:f}}function C(e){return e&&e.charAt(0).toUpperCase()+e.slice(1)}function B(...e){const t=n=>{if(n!==void 0)return n===""?!0:!!n};return e.reduce((n,r)=>typeof t(r)=="boolean"?t(r):n,void 0)}function L(e){return e.replace(/-([a-z])/g,(t,n)=>n.toUpperCase())}const Ve=["fl","layout-item","layout","item"],Ie=new Map(Ve.map(e=>{const t=L(e);return[[`${e}:`,{channel:e,type:"prop"}],[`${t}:`,{channel:e,type:"prop"}],[`on${C(e)}:`,{channel:e,type:"listener"}],[`on${C(t)}:`,{channel:e,type:"listener"}]]}).flat());function U(e,t,n={}){const r=n.prefix==="keep",o={};for(const c of[...t,"default"])o[c]=Object.create(null);const i=Object.entries(e).map(([c,d])=>({...Ne(c,t),rawKey:c,value:d}));for(const{rawKey:c,key:d,value:a,channel:s,type:f}of i)f!=="listener"&&(o[s||"default"][r&&s?c:d]=a);for(const{rawKey:c,key:d,value:a,channel:s,type:f}of i)f==="listener"&&(o[s||"default"][r&&s?c:d]=a);return o}function Ne(e,t){const n=e.indexOf(":");if(n===-1)return{key:e};const r=e.substring(0,n+1);if(e.length===r.length)return{key:e};const o=Ie.get(r);return!o||!t.includes(o.channel)?{key:e}:{key:o.type==="listener"?`on${C(e.replace(r,""))}`:e.replace(r,""),channel:o.channel,type:o.type}}const he=["fl","layout"],Ae=["fl","layout","layout-item","item"],Oe=["item"];function z(e,t,n){const r=u.computed(()=>U(e,t,n)),o={};for(const i of t)o[L(i)]=u.computed(()=>r.value[i]);return o.default=u.computed(()=>r.value.default),o}function Ce(e){return new Proxy({},{get(t,n){const r=e.value;if(r==null)return;const o=Reflect.get(r,n,r);return typeof o=="function"?o.bind(r):o},has(t,n){return e.value!=null&&n in e.value}})}function Ee(e={}){const{Row:t,Col:n}=e.layout??{},r=P({Row:t,Col:n}),o=e.form?.component?u.markRaw(e.form.component):void 0,i=le(e.item);return u.defineComponent({name:"FormView",inheritAttrs:!1,setup(c,{slots:d,attrs:a,expose:s}){const f=u.ref(null);s(Ce(f));const y=u.inject(k,null)!=null,{fl:p,layout:l,default:v}=z(a,he),N=u.computed(()=>B(!1,p.value.layout)),V=u.computed(()=>{const b=p.value.form;return b===void 0||b==="auto"?!y:b===""?!0:!!b}),{getIn:I,setIn:h}=Fe();return u.provide(_,{access(b){return{value:u.computed(()=>I(u.toValue(b))),update:O=>h(u.toValue(b),O)}},FormItem:u.markRaw(i),LayoutView:u.markRaw(r),fl:p}),()=>{const b=r,O=u.createVNode(b,u.mergeProps({...e.layout?.props,...l.value},{disabled:!N.value}),{default:d.default});if(!o||!V.value)return O;const W=o;return u.createVNode(W,u.mergeProps({ref:f},{...e.form?.props,...v.value}),{default:()=>O})}}})}function Le(e){return typeof e=="function"||Object.prototype.toString.call(e)==="[object Object]"&&!u.isVNode(e)}function M(e){if(!(typeof e>"u"))return(Array.isArray(e)?e:[e]).map(t=>{if(typeof t=="string")return t})}function we(e){if(!(typeof e>"u"))return(Array.isArray(e)?e:[e]).map(t=>{if(typeof t=="string")return t})}const Se=u.defineComponent({name:"FormFieldCore",inheritAttrs:!1,props:{preset:{type:Object},fl:{type:Object,required:!0},layoutItem:{type:Object,required:!0},layout:{type:Object,required:!0},item:{type:Object,required:!0},control:{type:[Object,Function],required:!0}},setup(e,{slots:t}){const n=u.inject(_,null),r=u.computed(()=>e.fl?.component?.formless),o=u.computed(()=>({...e.preset?.fl,...e.fl})),i=u.computed(()=>M(o.value?.model)||M(r.value?.model)||["modelValue"]),c=u.computed(()=>we(o.value?.prop)||n?.getProp?.(i.value)),d=u.computed(()=>{const p={},l={};return i.value.forEach((v,N)=>{if(typeof v!="string"||v.trim()==="")return;const V=c.value?.[N];if(typeof V!="string"||V.trim()==="")return;const I=n?.access(V);if(!I)return;const h=L(v);p[h]=I.value.value,l[`onUpdate:${h}`]=I.update}),{values:p,events:l}}),a=u.computed(()=>({...d.value.values,...d.value.events}));u.provide(_,{...n,getProp(p){return p.map(l=>{if(typeof l!="string")return;const v=i.value.indexOf(l);return v!==-1?c.value?.[v]:void 0})}});const s=u.computed(()=>{const p=r.value?.field==="embed"?"embed":"auto",l=o.value?.field==="embed"?"embed":o.value?.field==="wrap-embed"?"wrap-embed":"auto";return p==="auto"?l==="auto"?"wrap":l:l==="auto"?"embed":l}),f=u.computed(()=>B(!0,u.toValue(n?.fl)?.item,o.value?.item)),m=u.computed(()=>({...o.value,model:i.value,prop:c.value,field:s.value,item:f.value})),y=u.computed(()=>{const p=typeof e.preset?.props=="function"?e.preset?.props(m.value):e.preset?.props;return u.mergeProps(d.value.events,{...p,...e.control},d.value.values)});return()=>{const{item:p,default:l}=U(t,Oe),v=e.fl.component,N=v?u.createVNode(v,y.value,l):t.default?.({$bindings:a.value})??null;if(s.value==="embed")return N;const V=n?.LayoutView,I=s.value==="wrap-embed"&&V?u.createVNode(V,e.layout,{default:()=>N}):N,h=n?.FormItem,b=h?u.createVNode(h,{fl:m.value,item:e.item},{...p,default:()=>I}):I;return u.createVNode(T,e.layoutItem,Le(b)?b:{default:()=>[b]})}}});function K(e={}){const{name:t,component:n,props:r,...o}=e;return u.defineComponent({name:t?`FormField${C(t)}`:"FormField",inheritAttrs:!1,setup(i,{attrs:c,slots:d}){const{fl:a,layoutItem:s,layout:f,item:m,default:y}=z(c,Ae);return()=>u.createVNode(Se,{preset:{fl:o,props:r},fl:{...a.value,component:n??a.value.component},layoutItem:s.value,layout:f.value,item:m.value,control:y.value},d)}})}const ke=K();function _e(e){const t={};for(const n of Object.keys(e)){const r=e[n];if(!r)continue;const o=C(L(n));t[o]=K({name:o,prop:n,...r})}return t}exports.FormField=ke;exports.LayoutItem=T;exports.createFormFields=_e;exports.createFormView=Ee;exports.createLayoutView=P;
|