@moonmangit/vue-autoform 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/README.md +233 -0
- package/dist/style.css +1 -0
- package/dist/vue-autoform.cjs.js +5 -0
- package/dist/vue-autoform.cjs.js.map +1 -0
- package/dist/vue-autoform.d.ts +181 -0
- package/dist/vue-autoform.es.js +298 -0
- package/dist/vue-autoform.es.js.map +1 -0
- package/package.json +57 -0
package/README.md
ADDED
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
# vue-autoform
|
|
2
|
+
|
|
3
|
+
Headless Vue 3 auto-rendering form library with Zod schema validation, responsive CSS grid layout, and fully customisable field components.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Schema-driven** — define fields with Zod; validation is automatic
|
|
8
|
+
- **Headless** — bring your own UI components; no styles imposed
|
|
9
|
+
- **Responsive grid** — shorthand col-counts or explicit per-breakpoint layouts, CSS-only
|
|
10
|
+
- **Flexible validation** — run on `blur`, `input`, or `submit`
|
|
11
|
+
- **Full TypeScript support**
|
|
12
|
+
|
|
13
|
+
## Install
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pnpm add vue-autoform zod
|
|
17
|
+
# or
|
|
18
|
+
npm install vue-autoform zod
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
> `vue` and `zod` are peer dependencies and must be installed in your project.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Basic Usage
|
|
26
|
+
|
|
27
|
+
```vue
|
|
28
|
+
<template>
|
|
29
|
+
<AutoForm
|
|
30
|
+
:schema="schema"
|
|
31
|
+
:fields="fields"
|
|
32
|
+
v-model="formData"
|
|
33
|
+
validate-on="blur"
|
|
34
|
+
/>
|
|
35
|
+
</template>
|
|
36
|
+
|
|
37
|
+
<script setup lang="ts">
|
|
38
|
+
import { reactive } from 'vue'
|
|
39
|
+
import { z } from 'zod'
|
|
40
|
+
import { AutoForm } from 'vue-autoform'
|
|
41
|
+
import MyTextInput from './MyTextInput.vue'
|
|
42
|
+
|
|
43
|
+
const schema = z.object({
|
|
44
|
+
email: z.string().email('Invalid email'),
|
|
45
|
+
password: z.string().min(8, 'Min 8 characters'),
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
const fields = {
|
|
49
|
+
email: {
|
|
50
|
+
component: MyTextInput,
|
|
51
|
+
props: { label: 'Email', type: 'email' },
|
|
52
|
+
},
|
|
53
|
+
password: {
|
|
54
|
+
component: MyTextInput,
|
|
55
|
+
props: { label: 'Password', type: 'password' },
|
|
56
|
+
},
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const formData = reactive({ email: '', password: '' })
|
|
60
|
+
</script>
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Field Component Contract
|
|
66
|
+
|
|
67
|
+
Your custom field components receive these props automatically:
|
|
68
|
+
|
|
69
|
+
| Prop | Type | Description |
|
|
70
|
+
|---|---|---|
|
|
71
|
+
| `modelValue` | `unknown` | Current field value |
|
|
72
|
+
| `error` | `string \| undefined` | Zod validation error message |
|
|
73
|
+
| `...props` | — | Any extra props from `FieldConfig.props` |
|
|
74
|
+
|
|
75
|
+
They should emit `update:modelValue` for v-model binding and `blur` for blur-based validation.
|
|
76
|
+
|
|
77
|
+
```vue
|
|
78
|
+
<!-- Example field component -->
|
|
79
|
+
<template>
|
|
80
|
+
<div>
|
|
81
|
+
<input :value="modelValue" @input="emit('update:modelValue', $event.target.value)" @blur="emit('blur')" />
|
|
82
|
+
<span v-if="error">{{ error }}</span>
|
|
83
|
+
</div>
|
|
84
|
+
</template>
|
|
85
|
+
<script setup lang="ts">
|
|
86
|
+
defineProps<{ modelValue?: string; error?: string; label?: string }>()
|
|
87
|
+
const emit = defineEmits(['update:modelValue', 'blur'])
|
|
88
|
+
</script>
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Layout
|
|
94
|
+
|
|
95
|
+
`layout` is optional. Omitting it renders all fields in a single column in schema-key order.
|
|
96
|
+
|
|
97
|
+
### Shorthand — column count per breakpoint
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
const layout = {
|
|
101
|
+
default: 1, // 1 column on mobile
|
|
102
|
+
md: 2, // 2 columns at ≥768px
|
|
103
|
+
lg: 3, // 3 columns at ≥1024px
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Fields auto-flow into columns following schema-key order.
|
|
108
|
+
|
|
109
|
+
### Explicit — full grid per breakpoint
|
|
110
|
+
|
|
111
|
+
```ts
|
|
112
|
+
const layout = {
|
|
113
|
+
default: [
|
|
114
|
+
['firstName'],
|
|
115
|
+
['lastName'],
|
|
116
|
+
['email'],
|
|
117
|
+
],
|
|
118
|
+
md: [
|
|
119
|
+
['firstName', 'lastName'],
|
|
120
|
+
['email'],
|
|
121
|
+
],
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Each inner array is a row; each string is a field key matching the Zod schema.
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## Breakpoints
|
|
130
|
+
|
|
131
|
+
Default breakpoints (Tailwind-compatible):
|
|
132
|
+
|
|
133
|
+
| Key | Min-width |
|
|
134
|
+
|---|---|
|
|
135
|
+
| `sm` | 640px |
|
|
136
|
+
| `md` | 768px |
|
|
137
|
+
| `lg` | 1024px |
|
|
138
|
+
| `xl` | 1280px |
|
|
139
|
+
| `2xl` | 1536px |
|
|
140
|
+
|
|
141
|
+
Override per form with the `breakpoints` prop:
|
|
142
|
+
|
|
143
|
+
```vue
|
|
144
|
+
<AutoForm
|
|
145
|
+
:schema="schema"
|
|
146
|
+
:layout="{ default: 1, tablet: 2 }"
|
|
147
|
+
:breakpoints="{ tablet: 900 }"
|
|
148
|
+
:fields="fields"
|
|
149
|
+
v-model="formData"
|
|
150
|
+
/>
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## Validation
|
|
156
|
+
|
|
157
|
+
```vue
|
|
158
|
+
<!-- Validate on blur (default) -->
|
|
159
|
+
<AutoForm validate-on="blur" ... />
|
|
160
|
+
|
|
161
|
+
<!-- Validate on every keystroke -->
|
|
162
|
+
<AutoForm validate-on="input" ... />
|
|
163
|
+
|
|
164
|
+
<!-- Validate only on submit -->
|
|
165
|
+
<AutoForm ref="form" validate-on="submit" ... />
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
For `submit` mode, call `validateAll()` via template ref:
|
|
169
|
+
|
|
170
|
+
```ts
|
|
171
|
+
const form = ref()
|
|
172
|
+
function handleSubmit() {
|
|
173
|
+
const valid = form.value.validateAll() // returns true/false
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
## Error Slot
|
|
180
|
+
|
|
181
|
+
Use the `#error` scoped slot for custom error rendering:
|
|
182
|
+
|
|
183
|
+
```vue
|
|
184
|
+
<AutoForm :schema="schema" :fields="fields" v-model="formData">
|
|
185
|
+
<template #error="{ fieldKey, error }">
|
|
186
|
+
<p v-if="error" class="my-error">{{ fieldKey }}: {{ error }}</p>
|
|
187
|
+
</template>
|
|
188
|
+
</AutoForm>
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## Props Reference
|
|
194
|
+
|
|
195
|
+
| Prop | Type | Default | Description |
|
|
196
|
+
|---|---|---|---|
|
|
197
|
+
| `schema` | `ZodObject` | required | Zod object schema |
|
|
198
|
+
| `fields` | `Record<string, FieldConfig>` | required | Field component map |
|
|
199
|
+
| `modelValue` | `Record<string, unknown>` | required | Form data (`v-model`) |
|
|
200
|
+
| `layout` | `AutoFormLayout` | undefined | Grid layout config |
|
|
201
|
+
| `validateOn` | `'blur' \| 'input' \| 'submit'` | `'blur'` | Validation trigger |
|
|
202
|
+
| `breakpoints` | `Partial<BreakpointMap>` | Tailwind defaults | Custom breakpoint widths |
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
## CSS Variables
|
|
207
|
+
|
|
208
|
+
Customise spacing without overriding component styles:
|
|
209
|
+
|
|
210
|
+
```css
|
|
211
|
+
.autoform {
|
|
212
|
+
--autoform-gap: 1rem; /* gap between fields in a row */
|
|
213
|
+
--autoform-row-gap: 1rem; /* gap between rows */
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## Development
|
|
220
|
+
|
|
221
|
+
```bash
|
|
222
|
+
# Install dependencies
|
|
223
|
+
pnpm install
|
|
224
|
+
|
|
225
|
+
# Run playground (port 5174)
|
|
226
|
+
pnpm playground
|
|
227
|
+
|
|
228
|
+
# Build library
|
|
229
|
+
pnpm build
|
|
230
|
+
|
|
231
|
+
# Type check
|
|
232
|
+
pnpm type-check
|
|
233
|
+
```
|
package/dist/style.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.autoform{width:100%;display:flex;flex-direction:column;gap:var(--autoform-row-gap, 1rem)}.autoform-flat-grid{display:grid;grid-template-columns:repeat(1,minmax(0,1fr));gap:var(--autoform-gap, 1rem);width:100%}.autoform-flat-grid .autoform-cell{min-width:0}.autoform-default-input{width:100%;padding:.5rem .75rem;border:1px solid #d1d5db;border-radius:.375rem;font-size:1rem;outline:none;box-sizing:border-box}.autoform-default-input:focus{border-color:#6366f1;box-shadow:0 0 0 2px #6366f133}.autoform-row{display:grid;grid-template-columns:repeat(var(--autoform-cols, 1),minmax(0,1fr));gap:var(--autoform-gap, 1rem);width:100%}.autoform-cell{min-width:0}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("vue"),L={sm:640,md:768,lg:1024,xl:1280,"2xl":1536};function b(a){return typeof a.default=="number"}function w(a){return Array.isArray(a.default)}function O(a,h,E,u,S,$){const s=e.reactive({}),y=e.computed(()=>({...L,...$.value})),d=e.computed(()=>Object.keys(a.shape)),p=e.computed(()=>{const o=S.value;if(!o)return d.value.map(t=>[t]);if(w(o))return o.default;if(b(o)){const t=o.default,r=d.value,c=[];for(let n=0;n<r.length;n+=t)c.push(r.slice(n,n+t));return c}return d.value.map(t=>[t])});function V(o,t){var i;const r=a.shape;if(!r[o])return;const n=r[o].safeParse(t);if(!n.success)return((i=n.error.errors[0])==null?void 0:i.message)??"Invalid value"}function I(){const o=a.safeParse(h.value);return o.success?(Object.keys(s).forEach(t=>delete s[t]),!0):(o.error.errors.forEach(t=>{const r=String(t.path[0]);s[r]=t.message}),!1)}function F(o,t){const r={...h.value,[o]:t};if(E("update:modelValue",r),u.value==="input"){const c=V(o,t);c?s[o]=c:delete s[o]}}function A(o){if(u.value==="blur"){const t=V(o,h.value[o]);t?s[o]=t:delete s[o]}}function m(){const o=S.value;if(!o)return[];const t=y.value,r=[];if(w(o)){const c=Object.keys(o).filter(n=>n!=="default");for(const n of c){const i=t[n],l=o[n];i&&l&&r.push({minWidth:i,grid:l,key:n})}}else if(b(o)){const c=Object.keys(o).filter(n=>n!=="default");for(const n of c){const i=t[n],l=o[n];if(i&&l){const f=d.value,v=[];for(let B=0;B<f.length;B+=l)v.push(f.slice(B,B+l));r.push({minWidth:i,grid:v,key:n})}}}return r.sort((c,n)=>c.minWidth-n.minWidth)}return{errors:s,resolvedLayout:p,schemaKeys:d,onFieldInput:F,onFieldBlur:A,validateAll:I,getBreakpointLayouts:m}}const U=["data-autoform-id"],P={key:1,class:"autoform-flat-grid"},T=["value","onInput","onBlur"],D={key:2,class:"autoform-flat-grid"},N=["data-field-key"],W=["value","onInput","onBlur"],M=e.defineComponent({__name:"AutoForm",props:{schema:{},layout:{},fields:{},modelValue:{},validateOn:{default:"blur"},breakpoints:{}},emits:["update:modelValue"],setup(a,{expose:h,emit:E}){const u=a,S=E,$=e.ref(`autoform-${Math.random().toString(36).slice(2,9)}`),{errors:s,schemaKeys:y,onFieldInput:d,onFieldBlur:p,validateAll:V}=O(u.schema,e.toRef(u,"modelValue"),(m,o)=>S("update:modelValue",o),e.toRef(u,"validateOn"),e.toRef(u,"layout"),e.toRef(u,"breakpoints")),I=e.computed(()=>u.layout?b(u.layout):!1),F=e.computed(()=>y.value),A=e.computed(()=>{if(!u.layout)return"";const m={...L,...u.breakpoints},o=$.value,t=[];if(b(u.layout)){const r=u.layout;t.push(`[data-autoform-id="${o}"] .autoform-flat-grid {`,` grid-template-columns: repeat(${r.default}, minmax(0, 1fr));`,"}");const c=Object.keys(r).filter(n=>n!=="default");for(const n of c){const i=m[n],l=r[n];i&&l&&t.push(`@media (min-width: ${i}px) {`,` [data-autoform-id="${o}"] .autoform-flat-grid {`,` grid-template-columns: repeat(${l}, minmax(0, 1fr));`," }","}")}}else if(w(u.layout)){const r=u.layout,c=(l,f)=>{const v=Math.max(...l.map(k=>k.length)),B=y.value,x=new Set(l.flat()),g=[];g.push(`[data-autoform-id="${o}"] .autoform-flat-grid { grid-template-columns: repeat(${v}, minmax(0, 1fr)); }`),B.forEach(k=>{x.has(k)||g.push(`[data-autoform-id="${o}"] [data-field-key="${k}"] { display: none; }`)});let j=1;return l.forEach(k=>{let C=1;k.forEach(R=>{g.push(`[data-autoform-id="${o}"] [data-field-key="${R}"] { display: block; grid-row: ${j}; grid-column: ${C}; }`),C++}),j++}),f?[`@media (min-width: ${f}px) {`,...g.map(k=>` ${k}`),"}"].join(`
|
|
2
|
+
`):g.join(`
|
|
3
|
+
`)};t.push(c(r.default));const i=Object.keys(r).filter(l=>l!=="default").sort((l,f)=>(m[l]??0)-(m[f]??0));for(const l of i){const f=m[l],v=r[l];f&&v&&t.push(c(v,String(f)))}}return t.join(`
|
|
4
|
+
`)});return h({validateAll:V,errors:s}),(m,o)=>(e.openBlock(),e.createElementBlock("div",{class:"autoform","data-autoform-id":$.value},[A.value?(e.openBlock(),e.createBlock(e.resolveDynamicComponent("style"),{key:0},{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(A.value),1)]),_:1})):e.createCommentVNode("",!0),I.value?(e.openBlock(),e.createElementBlock("div",P,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(F.value,t=>(e.openBlock(),e.createElementBlock("div",{key:t,class:"autoform-cell"},[a.fields[t]?(e.openBlock(),e.createElementBlock(e.Fragment,{key:0},[(e.openBlock(),e.createBlock(e.resolveDynamicComponent(a.fields[t].component),e.mergeProps({modelValue:a.modelValue[t],error:e.unref(s)[t]},{ref_for:!0},a.fields[t].props??{},{"onUpdate:modelValue":r=>e.unref(d)(t,r),onBlur:()=>e.unref(p)(t)}),null,16,["modelValue","error","onUpdate:modelValue","onBlur"])),e.renderSlot(m.$slots,"error",{fieldKey:t,error:e.unref(s)[t]})],64)):(e.openBlock(),e.createElementBlock(e.Fragment,{key:1},[e.renderSlot(m.$slots,`field-${t}`,{fieldKey:t,value:a.modelValue[t],error:e.unref(s)[t],onUpdate:r=>e.unref(d)(t,r),onBlur:()=>e.unref(p)(t)},()=>[e.createElementVNode("input",{class:"autoform-default-input",value:String(a.modelValue[t]??""),onInput:r=>e.unref(d)(t,r.target.value),onBlur:()=>e.unref(p)(t)},null,40,T)]),e.renderSlot(m.$slots,"error",{fieldKey:t,error:e.unref(s)[t]})],64))]))),128))])):(e.openBlock(),e.createElementBlock("div",D,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(F.value,t=>(e.openBlock(),e.createElementBlock("div",{key:t,class:"autoform-cell","data-field-key":t},[a.fields[t]?(e.openBlock(),e.createElementBlock(e.Fragment,{key:0},[(e.openBlock(),e.createBlock(e.resolveDynamicComponent(a.fields[t].component),e.mergeProps({modelValue:a.modelValue[t],error:e.unref(s)[t]},{ref_for:!0},a.fields[t].props??{},{"onUpdate:modelValue":r=>e.unref(d)(t,r),onBlur:()=>e.unref(p)(t)}),null,16,["modelValue","error","onUpdate:modelValue","onBlur"])),e.renderSlot(m.$slots,"error",{fieldKey:t,error:e.unref(s)[t]})],64)):(e.openBlock(),e.createElementBlock(e.Fragment,{key:1},[e.renderSlot(m.$slots,`field-${t}`,{fieldKey:t,value:a.modelValue[t],error:e.unref(s)[t],onUpdate:r=>e.unref(d)(t,r),onBlur:()=>e.unref(p)(t)},()=>[e.createElementVNode("input",{class:"autoform-default-input",value:String(a.modelValue[t]??""),onInput:r=>e.unref(d)(t,r.target.value),onBlur:()=>e.unref(p)(t)},null,40,W)]),e.renderSlot(m.$slots,"error",{fieldKey:t,error:e.unref(s)[t]})],64))],8,N))),128))]))],8,U))}}),q=e.defineComponent({__name:"AutoFormRow",props:{row:{}},setup(a){return(h,E)=>(e.openBlock(),e.createElementBlock("div",{class:"autoform-row",style:e.normalizeStyle({"--autoform-cols":a.row.length})},[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(a.row,u=>(e.openBlock(),e.createElementBlock("div",{key:u,class:"autoform-cell"},[e.renderSlot(h.$slots,"default",{fieldKey:u})]))),128))],4))}});exports.AutoForm=M;exports.AutoFormRow=q;exports.DEFAULT_BREAKPOINTS=L;exports.isExplicitLayout=w;exports.isShorthandLayout=b;exports.useAutoForm=O;
|
|
5
|
+
//# sourceMappingURL=vue-autoform.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vue-autoform.cjs.js","sources":["../src/types.ts","../src/composables/useAutoForm.ts","../src/components/AutoForm.vue","../src/components/AutoFormRow.vue"],"sourcesContent":["import type { Component } from 'vue'\nimport type { ZodObject, ZodRawShape } from 'zod'\n\nexport type BreakpointKey = 'sm' | 'md' | 'lg' | 'xl' | '2xl'\n\nexport type BreakpointMap = Record<BreakpointKey, number>\n\nexport const DEFAULT_BREAKPOINTS: BreakpointMap = {\n sm: 640,\n md: 768,\n lg: 1024,\n xl: 1280,\n '2xl': 1536,\n}\n\nexport interface FieldConfig {\n component: Component\n props?: Record<string, unknown>\n [key: string]: unknown\n}\n\nexport type LayoutRow = string[]\n\nexport type LayoutGrid = LayoutRow[]\n\nexport type ShorthandLayout = { default: number } & Partial<Record<BreakpointKey, number>>\n\nexport type ExplicitLayout = { default: LayoutGrid } & Partial<Record<BreakpointKey, LayoutGrid>>\n\nexport type AutoFormLayout = ShorthandLayout | ExplicitLayout\n\nexport function isShorthandLayout(layout: AutoFormLayout): layout is ShorthandLayout {\n return typeof layout.default === 'number'\n}\n\nexport function isExplicitLayout(layout: AutoFormLayout): layout is ExplicitLayout {\n return Array.isArray(layout.default)\n}\n\nexport interface AutoFormProps {\n schema: ZodObject<ZodRawShape>\n layout?: AutoFormLayout\n fields: Record<string, FieldConfig>\n modelValue: Record<string, unknown>\n validateOn?: 'blur' | 'input' | 'submit'\n breakpoints?: Partial<BreakpointMap>\n}\n\nexport interface FieldRenderInfo {\n key: string\n config: FieldConfig | undefined\n value: unknown\n error: string | undefined\n}\n","import { reactive, computed } from 'vue'\nimport type { Ref } from 'vue'\nimport type { ZodObject, ZodRawShape } from 'zod'\nimport type { BreakpointMap, AutoFormLayout, LayoutGrid } from '../types'\nimport {\n DEFAULT_BREAKPOINTS,\n isShorthandLayout,\n isExplicitLayout,\n} from '../types'\n\nexport function useAutoForm(\n schema: ZodObject<ZodRawShape>,\n modelValue: Ref<Record<string, unknown>>,\n emit: (event: 'update:modelValue', value: Record<string, unknown>) => void,\n validateOn: Ref<'blur' | 'input' | 'submit'>,\n layout: Ref<AutoFormLayout | undefined>,\n breakpointsOverride: Ref<Partial<BreakpointMap> | undefined>,\n) {\n const errors = reactive<Record<string, string>>({})\n\n const breakpoints = computed<BreakpointMap>(() => ({\n ...DEFAULT_BREAKPOINTS,\n ...breakpointsOverride.value,\n }))\n\n const schemaKeys = computed<string[]>(() => Object.keys(schema.shape))\n\n const resolvedLayout = computed<LayoutGrid>(() => {\n const l = layout.value\n if (!l) {\n return schemaKeys.value.map((key: string) => [key])\n }\n if (isExplicitLayout(l)) {\n return l.default\n }\n if (isShorthandLayout(l)) {\n const cols = l.default\n const keys = schemaKeys.value\n const rows: LayoutGrid = []\n for (let i = 0; i < keys.length; i += cols) {\n rows.push(keys.slice(i, i + cols))\n }\n return rows\n }\n return schemaKeys.value.map((key: string) => [key])\n })\n\n function validateField(key: string, value: unknown): string | undefined {\n const shape = schema.shape\n if (!shape[key]) return undefined\n const fieldSchema = shape[key]\n const result = fieldSchema.safeParse(value)\n if (!result.success) {\n return result.error.errors[0]?.message ?? 'Invalid value'\n }\n return undefined\n }\n\n function validateAll(): boolean {\n const result = schema.safeParse(modelValue.value)\n if (!result.success) {\n result.error.errors.forEach((err) => {\n const key = String(err.path[0])\n errors[key] = err.message\n })\n return false\n }\n Object.keys(errors).forEach((k: string) => delete errors[k])\n return true\n }\n\n function onFieldInput(key: string, value: unknown) {\n const updated = { ...modelValue.value, [key]: value }\n emit('update:modelValue', updated)\n if (validateOn.value === 'input') {\n const msg = validateField(key, value)\n if (msg) {\n errors[key] = msg\n } else {\n delete errors[key]\n }\n }\n }\n\n function onFieldBlur(key: string) {\n if (validateOn.value === 'blur') {\n const msg = validateField(key, modelValue.value[key])\n if (msg) {\n errors[key] = msg\n } else {\n delete errors[key]\n }\n }\n }\n\n function getBreakpointLayouts(): Array<{ minWidth: number; grid: LayoutGrid; key: string }> {\n const l = layout.value\n if (!l) return []\n\n const bps = breakpoints.value\n const result: Array<{ minWidth: number; grid: LayoutGrid; key: string }> = []\n\n if (isExplicitLayout(l)) {\n const bpKeys = Object.keys(l).filter((k) => k !== 'default') as Array<keyof typeof l>\n for (const bpKey of bpKeys) {\n const minWidth = bps[bpKey as keyof BreakpointMap]\n const grid = l[bpKey as keyof typeof l] as LayoutGrid\n if (minWidth && grid) {\n result.push({ minWidth, grid, key: bpKey })\n }\n }\n } else if (isShorthandLayout(l)) {\n const bpKeys = Object.keys(l).filter((k) => k !== 'default') as Array<keyof typeof l>\n for (const bpKey of bpKeys) {\n const minWidth = bps[bpKey as keyof BreakpointMap]\n const cols = l[bpKey as keyof typeof l] as number\n if (minWidth && cols) {\n const keys = schemaKeys.value\n const rows: LayoutGrid = []\n for (let i = 0; i < keys.length; i += cols) {\n rows.push(keys.slice(i, i + cols))\n }\n result.push({ minWidth, grid: rows, key: bpKey })\n }\n }\n }\n\n return result.sort((a, b) => a.minWidth - b.minWidth)\n }\n\n return {\n errors,\n resolvedLayout,\n schemaKeys,\n onFieldInput,\n onFieldBlur,\n validateAll,\n getBreakpointLayouts,\n }\n}\n","<template>\n <div class=\"autoform\" :data-autoform-id=\"formId\">\n <component :is=\"'style'\" v-if=\"mediaQueryCss\">{{\n mediaQueryCss\n }}</component>\n\n <!-- Shorthand layout: single flat grid, CSS handles column count per breakpoint -->\n <div v-if=\"isShorthand\" class=\"autoform-flat-grid\">\n <div v-for=\"fieldKey in flatKeys\" :key=\"fieldKey\" class=\"autoform-cell\">\n <template v-if=\"fields[fieldKey]\">\n <component\n :is=\"fields[fieldKey].component\"\n :modelValue=\"modelValue[fieldKey]\"\n :error=\"errors[fieldKey]\"\n v-bind=\"fields[fieldKey].props ?? {}\"\n @update:modelValue=\"(val: unknown) => onFieldInput(fieldKey, val)\"\n @blur=\"() => onFieldBlur(fieldKey)\"\n />\n <slot name=\"error\" :fieldKey=\"fieldKey\" :error=\"errors[fieldKey]\" />\n </template>\n <template v-else>\n <slot\n :name=\"`field-${fieldKey}`\"\n :fieldKey=\"fieldKey\"\n :value=\"modelValue[fieldKey]\"\n :error=\"errors[fieldKey]\"\n :onUpdate=\"(val: unknown) => onFieldInput(fieldKey, val)\"\n :onBlur=\"() => onFieldBlur(fieldKey)\"\n >\n <input\n class=\"autoform-default-input\"\n :value=\"String(modelValue[fieldKey] ?? '')\"\n @input=\"\n (e: Event) =>\n onFieldInput(fieldKey, (e.target as HTMLInputElement).value)\n \"\n @blur=\"() => onFieldBlur(fieldKey)\"\n />\n </slot>\n <slot name=\"error\" :fieldKey=\"fieldKey\" :error=\"errors[fieldKey]\" />\n </template>\n </div>\n </div>\n\n <!-- Explicit layout / no layout: flat grid, CSS positions each field per breakpoint -->\n <div v-else class=\"autoform-flat-grid\">\n <div\n v-for=\"fieldKey in flatKeys\"\n :key=\"fieldKey\"\n class=\"autoform-cell\"\n :data-field-key=\"fieldKey\"\n >\n <template v-if=\"fields[fieldKey]\">\n <component\n :is=\"fields[fieldKey].component\"\n :modelValue=\"modelValue[fieldKey]\"\n :error=\"errors[fieldKey]\"\n v-bind=\"fields[fieldKey].props ?? {}\"\n @update:modelValue=\"(val: unknown) => onFieldInput(fieldKey, val)\"\n @blur=\"() => onFieldBlur(fieldKey)\"\n />\n <slot name=\"error\" :fieldKey=\"fieldKey\" :error=\"errors[fieldKey]\" />\n </template>\n <template v-else>\n <slot\n :name=\"`field-${fieldKey}`\"\n :fieldKey=\"fieldKey\"\n :value=\"modelValue[fieldKey]\"\n :error=\"errors[fieldKey]\"\n :onUpdate=\"(val: unknown) => onFieldInput(fieldKey, val)\"\n :onBlur=\"() => onFieldBlur(fieldKey)\"\n >\n <input\n class=\"autoform-default-input\"\n :value=\"String(modelValue[fieldKey] ?? '')\"\n @input=\"\n (e: Event) =>\n onFieldInput(fieldKey, (e.target as HTMLInputElement).value)\n \"\n @blur=\"() => onFieldBlur(fieldKey)\"\n />\n </slot>\n <slot name=\"error\" :fieldKey=\"fieldKey\" :error=\"errors[fieldKey]\" />\n </template>\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, ref, toRef } from \"vue\";\nimport type { ZodObject, ZodRawShape } from \"zod\";\nimport { useAutoForm } from \"../composables/useAutoForm\";\nimport type {\n AutoFormLayout,\n BreakpointMap,\n FieldConfig,\n LayoutGrid,\n} from \"../types\";\nimport {\n isExplicitLayout,\n isShorthandLayout,\n DEFAULT_BREAKPOINTS,\n} from \"../types\";\n\nconst props = withDefaults(\n defineProps<{\n schema: ZodObject<ZodRawShape>;\n layout?: AutoFormLayout;\n fields: Record<string, FieldConfig>;\n modelValue: Record<string, unknown>;\n validateOn?: \"blur\" | \"input\" | \"submit\";\n breakpoints?: Partial<BreakpointMap>;\n }>(),\n {\n validateOn: \"blur\",\n },\n);\n\nconst emit = defineEmits<{\n (e: \"update:modelValue\", value: Record<string, unknown>): void;\n}>();\n\nconst formId = ref(`autoform-${Math.random().toString(36).slice(2, 9)}`);\n\nconst { errors, schemaKeys, onFieldInput, onFieldBlur, validateAll } =\n useAutoForm(\n props.schema,\n toRef(props, \"modelValue\"),\n (_, val) => emit(\"update:modelValue\", val),\n toRef(props, \"validateOn\"),\n toRef(props, \"layout\"),\n toRef(props, \"breakpoints\"),\n );\n\nconst isShorthand = computed(() =>\n props.layout ? isShorthandLayout(props.layout) : false,\n);\n\nconst flatKeys = computed(() => schemaKeys.value);\n\nconst mediaQueryCss = computed<string>(() => {\n if (!props.layout) return \"\";\n\n const bps: BreakpointMap = { ...DEFAULT_BREAKPOINTS, ...props.breakpoints };\n const id = formId.value;\n const lines: string[] = [];\n\n if (isShorthandLayout(props.layout)) {\n const layout = props.layout;\n // Base columns for the flat grid\n lines.push(\n `[data-autoform-id=\"${id}\"] .autoform-flat-grid {`,\n ` grid-template-columns: repeat(${layout.default}, minmax(0, 1fr));`,\n `}`,\n );\n const bpKeys = Object.keys(layout).filter((k) => k !== \"default\") as Array<\n keyof typeof layout\n >;\n for (const bpKey of bpKeys) {\n const minWidth = bps[bpKey as keyof BreakpointMap];\n const cols = layout[bpKey as keyof typeof layout] as number;\n if (minWidth && cols) {\n lines.push(\n `@media (min-width: ${minWidth}px) {`,\n ` [data-autoform-id=\"${id}\"] .autoform-flat-grid {`,\n ` grid-template-columns: repeat(${cols}, minmax(0, 1fr));`,\n ` }`,\n `}`,\n );\n }\n }\n } else if (isExplicitLayout(props.layout)) {\n const layout = props.layout;\n // Helper: build CSS rules for a given grid at a given scope (media query or base)\n const gridToCss = (grid: LayoutGrid, wrap?: string): string => {\n const maxCols = Math.max(...grid.map((r: string[]) => r.length));\n const allKeys = schemaKeys.value;\n const keysInGrid = new Set(grid.flat());\n const fieldRules: string[] = [];\n\n // Set grid column count\n fieldRules.push(\n `[data-autoform-id=\"${id}\"] .autoform-flat-grid { grid-template-columns: repeat(${maxCols}, minmax(0, 1fr)); }`,\n );\n\n // Hide fields not in this layout\n allKeys.forEach((key: string) => {\n if (!keysInGrid.has(key)) {\n fieldRules.push(\n `[data-autoform-id=\"${id}\"] [data-field-key=\"${key}\"] { display: none; }`,\n );\n }\n });\n\n // Position each field\n let rowStart = 1;\n grid.forEach((row: string[]) => {\n let colStart = 1;\n row.forEach((key: string) => {\n fieldRules.push(\n `[data-autoform-id=\"${id}\"] [data-field-key=\"${key}\"] { display: block; grid-row: ${rowStart}; grid-column: ${colStart}; }`,\n );\n colStart++;\n });\n rowStart++;\n });\n\n if (wrap) {\n return [\n `@media (min-width: ${wrap}px) {`,\n ...fieldRules.map((r) => ` ${r}`),\n `}`,\n ].join(\"\\n\");\n }\n return fieldRules.join(\"\\n\");\n };\n\n // Default layout base styles\n lines.push(gridToCss(layout.default));\n\n // Per-breakpoint overrides\n const bpKeys = Object.keys(layout).filter((k) => k !== \"default\") as Array<\n keyof typeof layout\n >;\n const sortedBpKeys = bpKeys.sort(\n (a, b) =>\n (bps[a as keyof BreakpointMap] ?? 0) -\n (bps[b as keyof BreakpointMap] ?? 0),\n );\n for (const bpKey of sortedBpKeys) {\n const minWidth = bps[bpKey as keyof BreakpointMap];\n const grid = layout[bpKey as keyof typeof layout] as LayoutGrid;\n if (minWidth && grid) {\n lines.push(gridToCss(grid, String(minWidth)));\n }\n }\n }\n\n return lines.join(\"\\n\");\n});\n\ndefineExpose({ validateAll, errors });\n</script>\n\n<style>\n.autoform {\n width: 100%;\n display: flex;\n flex-direction: column;\n gap: var(--autoform-row-gap, 1rem);\n}\n\n.autoform-flat-grid {\n display: grid;\n grid-template-columns: repeat(1, minmax(0, 1fr));\n gap: var(--autoform-gap, 1rem);\n width: 100%;\n}\n\n.autoform-flat-grid .autoform-cell {\n min-width: 0;\n}\n\n.autoform-default-input {\n width: 100%;\n padding: 0.5rem 0.75rem;\n border: 1px solid #d1d5db;\n border-radius: 0.375rem;\n font-size: 1rem;\n outline: none;\n box-sizing: border-box;\n}\n\n.autoform-default-input:focus {\n border-color: #6366f1;\n box-shadow: 0 0 0 2px rgba(99, 102, 241, 0.2);\n}\n</style>\n","<template>\n <div\n class=\"autoform-row\"\n :style=\"{ '--autoform-cols': row.length }\"\n >\n <div\n v-for=\"fieldKey in row\"\n :key=\"fieldKey\"\n class=\"autoform-cell\"\n >\n <slot :fieldKey=\"fieldKey\" />\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\ndefineProps<{\n row: string[]\n}>()\n</script>\n\n<style>\n.autoform-row {\n display: grid;\n grid-template-columns: repeat(var(--autoform-cols, 1), minmax(0, 1fr));\n gap: var(--autoform-gap, 1rem);\n width: 100%;\n}\n\n.autoform-cell {\n min-width: 0;\n}\n</style>\n"],"names":["DEFAULT_BREAKPOINTS","isShorthandLayout","layout","isExplicitLayout","useAutoForm","schema","modelValue","emit","validateOn","breakpointsOverride","errors","reactive","breakpoints","computed","schemaKeys","resolvedLayout","l","key","cols","keys","rows","i","validateField","value","shape","result","_a","validateAll","k","err","onFieldInput","updated","msg","onFieldBlur","getBreakpointLayouts","bps","bpKeys","bpKey","minWidth","grid","a","b","props","__props","__emit","formId","ref","toRef","_","val","isShorthand","flatKeys","mediaQueryCss","id","lines","gridToCss","wrap","maxCols","r","allKeys","keysInGrid","fieldRules","rowStart","row","colStart","sortedBpKeys","__expose","_createElementBlock","_openBlock","_createBlock","_resolveDynamicComponent","_hoisted_2","_Fragment","_renderList","fieldKey","_mergeProps","_unref","_renderSlot","_ctx","_createElementVNode","e","_hoisted_4","_normalizeStyle"],"mappings":"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"}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { Component } from 'vue';
|
|
2
|
+
import { ComponentOptionsMixin } from 'vue';
|
|
3
|
+
import { ComponentProvideOptions } from 'vue';
|
|
4
|
+
import { ComputedRef } from 'vue';
|
|
5
|
+
import { DefineComponent } from 'vue';
|
|
6
|
+
import { ExtractPropTypes } from 'vue';
|
|
7
|
+
import { PropType } from 'vue';
|
|
8
|
+
import { PublicProps } from 'vue';
|
|
9
|
+
import { Ref } from 'vue';
|
|
10
|
+
import { ZodObject } from 'zod';
|
|
11
|
+
import { ZodRawShape } from 'zod';
|
|
12
|
+
|
|
13
|
+
declare const __VLS_component: DefineComponent<ExtractPropTypes<__VLS_WithDefaults<__VLS_TypePropsToRuntimeProps<{
|
|
14
|
+
schema: ZodObject<ZodRawShape>;
|
|
15
|
+
layout?: AutoFormLayout;
|
|
16
|
+
fields: Record<string, FieldConfig>;
|
|
17
|
+
modelValue: Record<string, unknown>;
|
|
18
|
+
validateOn?: "blur" | "input" | "submit";
|
|
19
|
+
breakpoints?: Partial<BreakpointMap>;
|
|
20
|
+
}>, {
|
|
21
|
+
validateOn: string;
|
|
22
|
+
}>>, {
|
|
23
|
+
validateAll: () => boolean;
|
|
24
|
+
errors: Record<string, string>;
|
|
25
|
+
}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
|
|
26
|
+
"update:modelValue": (value: Record<string, unknown>) => void;
|
|
27
|
+
}, string, PublicProps, Readonly<ExtractPropTypes<__VLS_WithDefaults<__VLS_TypePropsToRuntimeProps<{
|
|
28
|
+
schema: ZodObject<ZodRawShape>;
|
|
29
|
+
layout?: AutoFormLayout;
|
|
30
|
+
fields: Record<string, FieldConfig>;
|
|
31
|
+
modelValue: Record<string, unknown>;
|
|
32
|
+
validateOn?: "blur" | "input" | "submit";
|
|
33
|
+
breakpoints?: Partial<BreakpointMap>;
|
|
34
|
+
}>, {
|
|
35
|
+
validateOn: string;
|
|
36
|
+
}>>> & Readonly<{
|
|
37
|
+
"onUpdate:modelValue"?: ((value: Record<string, unknown>) => any) | undefined;
|
|
38
|
+
}>, {
|
|
39
|
+
validateOn: "blur" | "input" | "submit";
|
|
40
|
+
}, {}, {}, {}, string, ComponentProvideOptions, true, {}, any>;
|
|
41
|
+
|
|
42
|
+
declare const __VLS_component_2: DefineComponent<ExtractPropTypes<__VLS_TypePropsToRuntimeProps_2<{
|
|
43
|
+
row: string[];
|
|
44
|
+
}>>, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {}, string, PublicProps, Readonly<ExtractPropTypes<__VLS_TypePropsToRuntimeProps_2<{
|
|
45
|
+
row: string[];
|
|
46
|
+
}>>> & Readonly<{}>, {}, {}, {}, {}, string, ComponentProvideOptions, true, {}, any>;
|
|
47
|
+
|
|
48
|
+
declare type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;
|
|
49
|
+
|
|
50
|
+
declare type __VLS_NonUndefinedable_2<T> = T extends undefined ? never : T;
|
|
51
|
+
|
|
52
|
+
declare type __VLS_Prettify<T> = {
|
|
53
|
+
[K in keyof T]: T[K];
|
|
54
|
+
} & {};
|
|
55
|
+
|
|
56
|
+
declare function __VLS_template(): Partial<Record<`field-${string}`, (_: {
|
|
57
|
+
fieldKey: string;
|
|
58
|
+
value: unknown;
|
|
59
|
+
error: string;
|
|
60
|
+
onUpdate: (val: unknown) => void;
|
|
61
|
+
onBlur: () => void;
|
|
62
|
+
}) => any>> & Partial<Record<`field-${string}`, (_: {
|
|
63
|
+
fieldKey: string;
|
|
64
|
+
value: unknown;
|
|
65
|
+
error: string;
|
|
66
|
+
onUpdate: (val: unknown) => void;
|
|
67
|
+
onBlur: () => void;
|
|
68
|
+
}) => any>> & {
|
|
69
|
+
error?(_: {
|
|
70
|
+
fieldKey: string;
|
|
71
|
+
error: string;
|
|
72
|
+
}): any;
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
declare function __VLS_template_2(): {
|
|
76
|
+
default?(_: {
|
|
77
|
+
fieldKey: string;
|
|
78
|
+
}): any;
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
declare type __VLS_TypePropsToRuntimeProps<T> = {
|
|
82
|
+
[K in keyof T]-?: {} extends Pick<T, K> ? {
|
|
83
|
+
type: PropType<__VLS_NonUndefinedable<T[K]>>;
|
|
84
|
+
} : {
|
|
85
|
+
type: PropType<T[K]>;
|
|
86
|
+
required: true;
|
|
87
|
+
};
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
declare type __VLS_TypePropsToRuntimeProps_2<T> = {
|
|
91
|
+
[K in keyof T]-?: {} extends Pick<T, K> ? {
|
|
92
|
+
type: PropType<__VLS_NonUndefinedable_2<T[K]>>;
|
|
93
|
+
} : {
|
|
94
|
+
type: PropType<T[K]>;
|
|
95
|
+
required: true;
|
|
96
|
+
};
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
declare type __VLS_WithDefaults<P, D> = {
|
|
100
|
+
[K in keyof Pick<P, keyof P>]: K extends keyof D ? __VLS_Prettify<P[K] & {
|
|
101
|
+
default: D[K];
|
|
102
|
+
}> : P[K];
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
declare type __VLS_WithTemplateSlots<T, S> = T & {
|
|
106
|
+
new (): {
|
|
107
|
+
$slots: S;
|
|
108
|
+
};
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
declare type __VLS_WithTemplateSlots_2<T, S> = T & {
|
|
112
|
+
new (): {
|
|
113
|
+
$slots: S;
|
|
114
|
+
};
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
export declare const AutoForm: __VLS_WithTemplateSlots<typeof __VLS_component, ReturnType<typeof __VLS_template>>;
|
|
118
|
+
|
|
119
|
+
export declare type AutoFormLayout = ShorthandLayout | ExplicitLayout;
|
|
120
|
+
|
|
121
|
+
export declare interface AutoFormProps {
|
|
122
|
+
schema: ZodObject<ZodRawShape>;
|
|
123
|
+
layout?: AutoFormLayout;
|
|
124
|
+
fields: Record<string, FieldConfig>;
|
|
125
|
+
modelValue: Record<string, unknown>;
|
|
126
|
+
validateOn?: 'blur' | 'input' | 'submit';
|
|
127
|
+
breakpoints?: Partial<BreakpointMap>;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export declare const AutoFormRow: __VLS_WithTemplateSlots_2<typeof __VLS_component_2, ReturnType<typeof __VLS_template_2>>;
|
|
131
|
+
|
|
132
|
+
export declare type BreakpointKey = 'sm' | 'md' | 'lg' | 'xl' | '2xl';
|
|
133
|
+
|
|
134
|
+
export declare type BreakpointMap = Record<BreakpointKey, number>;
|
|
135
|
+
|
|
136
|
+
export declare const DEFAULT_BREAKPOINTS: BreakpointMap;
|
|
137
|
+
|
|
138
|
+
export declare type ExplicitLayout = {
|
|
139
|
+
default: LayoutGrid;
|
|
140
|
+
} & Partial<Record<BreakpointKey, LayoutGrid>>;
|
|
141
|
+
|
|
142
|
+
export declare interface FieldConfig {
|
|
143
|
+
component: Component;
|
|
144
|
+
props?: Record<string, unknown>;
|
|
145
|
+
[key: string]: unknown;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export declare interface FieldRenderInfo {
|
|
149
|
+
key: string;
|
|
150
|
+
config: FieldConfig | undefined;
|
|
151
|
+
value: unknown;
|
|
152
|
+
error: string | undefined;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export declare function isExplicitLayout(layout: AutoFormLayout): layout is ExplicitLayout;
|
|
156
|
+
|
|
157
|
+
export declare function isShorthandLayout(layout: AutoFormLayout): layout is ShorthandLayout;
|
|
158
|
+
|
|
159
|
+
export declare type LayoutGrid = LayoutRow[];
|
|
160
|
+
|
|
161
|
+
export declare type LayoutRow = string[];
|
|
162
|
+
|
|
163
|
+
export declare type ShorthandLayout = {
|
|
164
|
+
default: number;
|
|
165
|
+
} & Partial<Record<BreakpointKey, number>>;
|
|
166
|
+
|
|
167
|
+
export declare function useAutoForm(schema: ZodObject<ZodRawShape>, modelValue: Ref<Record<string, unknown>>, emit: (event: 'update:modelValue', value: Record<string, unknown>) => void, validateOn: Ref<'blur' | 'input' | 'submit'>, layout: Ref<AutoFormLayout | undefined>, breakpointsOverride: Ref<Partial<BreakpointMap> | undefined>): {
|
|
168
|
+
errors: Record<string, string>;
|
|
169
|
+
resolvedLayout: ComputedRef<LayoutGrid>;
|
|
170
|
+
schemaKeys: ComputedRef<string[]>;
|
|
171
|
+
onFieldInput: (key: string, value: unknown) => void;
|
|
172
|
+
onFieldBlur: (key: string) => void;
|
|
173
|
+
validateAll: () => boolean;
|
|
174
|
+
getBreakpointLayouts: () => Array<{
|
|
175
|
+
minWidth: number;
|
|
176
|
+
grid: LayoutGrid;
|
|
177
|
+
key: string;
|
|
178
|
+
}>;
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
export { }
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
import { reactive as H, computed as S, defineComponent as z, ref as J, toRef as O, openBlock as i, createElementBlock as d, createBlock as L, resolveDynamicComponent as W, withCtx as X, createTextVNode as Y, toDisplayString as Z, createCommentVNode as _, Fragment as b, renderList as R, mergeProps as D, unref as n, renderSlot as V, createElementVNode as M, normalizeStyle as K } from "vue";
|
|
2
|
+
const G = {
|
|
3
|
+
sm: 640,
|
|
4
|
+
md: 768,
|
|
5
|
+
lg: 1024,
|
|
6
|
+
xl: 1280,
|
|
7
|
+
"2xl": 1536
|
|
8
|
+
};
|
|
9
|
+
function C(a) {
|
|
10
|
+
return typeof a.default == "number";
|
|
11
|
+
}
|
|
12
|
+
function N(a) {
|
|
13
|
+
return Array.isArray(a.default);
|
|
14
|
+
}
|
|
15
|
+
function tt(a, k, w, u, F, A) {
|
|
16
|
+
const l = H({}), E = S(() => ({
|
|
17
|
+
...G,
|
|
18
|
+
...A.value
|
|
19
|
+
})), p = S(() => Object.keys(a.shape)), v = S(() => {
|
|
20
|
+
const o = F.value;
|
|
21
|
+
if (!o)
|
|
22
|
+
return p.value.map((t) => [t]);
|
|
23
|
+
if (N(o))
|
|
24
|
+
return o.default;
|
|
25
|
+
if (C(o)) {
|
|
26
|
+
const t = o.default, e = p.value, c = [];
|
|
27
|
+
for (let r = 0; r < e.length; r += t)
|
|
28
|
+
c.push(e.slice(r, r + t));
|
|
29
|
+
return c;
|
|
30
|
+
}
|
|
31
|
+
return p.value.map((t) => [t]);
|
|
32
|
+
});
|
|
33
|
+
function I(o, t) {
|
|
34
|
+
var f;
|
|
35
|
+
const e = a.shape;
|
|
36
|
+
if (!e[o]) return;
|
|
37
|
+
const r = e[o].safeParse(t);
|
|
38
|
+
if (!r.success)
|
|
39
|
+
return ((f = r.error.errors[0]) == null ? void 0 : f.message) ?? "Invalid value";
|
|
40
|
+
}
|
|
41
|
+
function U() {
|
|
42
|
+
const o = a.safeParse(k.value);
|
|
43
|
+
return o.success ? (Object.keys(l).forEach((t) => delete l[t]), !0) : (o.error.errors.forEach((t) => {
|
|
44
|
+
const e = String(t.path[0]);
|
|
45
|
+
l[e] = t.message;
|
|
46
|
+
}), !1);
|
|
47
|
+
}
|
|
48
|
+
function j(o, t) {
|
|
49
|
+
const e = { ...k.value, [o]: t };
|
|
50
|
+
if (w("update:modelValue", e), u.value === "input") {
|
|
51
|
+
const c = I(o, t);
|
|
52
|
+
c ? l[o] = c : delete l[o];
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
function x(o) {
|
|
56
|
+
if (u.value === "blur") {
|
|
57
|
+
const t = I(o, k.value[o]);
|
|
58
|
+
t ? l[o] = t : delete l[o];
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function m() {
|
|
62
|
+
const o = F.value;
|
|
63
|
+
if (!o) return [];
|
|
64
|
+
const t = E.value, e = [];
|
|
65
|
+
if (N(o)) {
|
|
66
|
+
const c = Object.keys(o).filter((r) => r !== "default");
|
|
67
|
+
for (const r of c) {
|
|
68
|
+
const f = t[r], s = o[r];
|
|
69
|
+
f && s && e.push({ minWidth: f, grid: s, key: r });
|
|
70
|
+
}
|
|
71
|
+
} else if (C(o)) {
|
|
72
|
+
const c = Object.keys(o).filter((r) => r !== "default");
|
|
73
|
+
for (const r of c) {
|
|
74
|
+
const f = t[r], s = o[r];
|
|
75
|
+
if (f && s) {
|
|
76
|
+
const h = p.value, $ = [];
|
|
77
|
+
for (let B = 0; B < h.length; B += s)
|
|
78
|
+
$.push(h.slice(B, B + s));
|
|
79
|
+
e.push({ minWidth: f, grid: $, key: r });
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return e.sort((c, r) => c.minWidth - r.minWidth);
|
|
84
|
+
}
|
|
85
|
+
return {
|
|
86
|
+
errors: l,
|
|
87
|
+
resolvedLayout: v,
|
|
88
|
+
schemaKeys: p,
|
|
89
|
+
onFieldInput: j,
|
|
90
|
+
onFieldBlur: x,
|
|
91
|
+
validateAll: U,
|
|
92
|
+
getBreakpointLayouts: m
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
const ot = ["data-autoform-id"], et = {
|
|
96
|
+
key: 1,
|
|
97
|
+
class: "autoform-flat-grid"
|
|
98
|
+
}, rt = ["value", "onInput", "onBlur"], at = {
|
|
99
|
+
key: 2,
|
|
100
|
+
class: "autoform-flat-grid"
|
|
101
|
+
}, st = ["data-field-key"], nt = ["value", "onInput", "onBlur"], lt = /* @__PURE__ */ z({
|
|
102
|
+
__name: "AutoForm",
|
|
103
|
+
props: {
|
|
104
|
+
schema: {},
|
|
105
|
+
layout: {},
|
|
106
|
+
fields: {},
|
|
107
|
+
modelValue: {},
|
|
108
|
+
validateOn: { default: "blur" },
|
|
109
|
+
breakpoints: {}
|
|
110
|
+
},
|
|
111
|
+
emits: ["update:modelValue"],
|
|
112
|
+
setup(a, { expose: k, emit: w }) {
|
|
113
|
+
const u = a, F = w, A = J(`autoform-${Math.random().toString(36).slice(2, 9)}`), { errors: l, schemaKeys: E, onFieldInput: p, onFieldBlur: v, validateAll: I } = tt(
|
|
114
|
+
u.schema,
|
|
115
|
+
O(u, "modelValue"),
|
|
116
|
+
(m, o) => F("update:modelValue", o),
|
|
117
|
+
O(u, "validateOn"),
|
|
118
|
+
O(u, "layout"),
|
|
119
|
+
O(u, "breakpoints")
|
|
120
|
+
), U = S(
|
|
121
|
+
() => u.layout ? C(u.layout) : !1
|
|
122
|
+
), j = S(() => E.value), x = S(() => {
|
|
123
|
+
if (!u.layout) return "";
|
|
124
|
+
const m = { ...G, ...u.breakpoints }, o = A.value, t = [];
|
|
125
|
+
if (C(u.layout)) {
|
|
126
|
+
const e = u.layout;
|
|
127
|
+
t.push(
|
|
128
|
+
`[data-autoform-id="${o}"] .autoform-flat-grid {`,
|
|
129
|
+
` grid-template-columns: repeat(${e.default}, minmax(0, 1fr));`,
|
|
130
|
+
"}"
|
|
131
|
+
);
|
|
132
|
+
const c = Object.keys(e).filter((r) => r !== "default");
|
|
133
|
+
for (const r of c) {
|
|
134
|
+
const f = m[r], s = e[r];
|
|
135
|
+
f && s && t.push(
|
|
136
|
+
`@media (min-width: ${f}px) {`,
|
|
137
|
+
` [data-autoform-id="${o}"] .autoform-flat-grid {`,
|
|
138
|
+
` grid-template-columns: repeat(${s}, minmax(0, 1fr));`,
|
|
139
|
+
" }",
|
|
140
|
+
"}"
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
} else if (N(u.layout)) {
|
|
144
|
+
const e = u.layout, c = (s, h) => {
|
|
145
|
+
const $ = Math.max(...s.map((g) => g.length)), B = E.value, Q = new Set(s.flat()), y = [];
|
|
146
|
+
y.push(
|
|
147
|
+
`[data-autoform-id="${o}"] .autoform-flat-grid { grid-template-columns: repeat(${$}, minmax(0, 1fr)); }`
|
|
148
|
+
), B.forEach((g) => {
|
|
149
|
+
Q.has(g) || y.push(
|
|
150
|
+
`[data-autoform-id="${o}"] [data-field-key="${g}"] { display: none; }`
|
|
151
|
+
);
|
|
152
|
+
});
|
|
153
|
+
let P = 1;
|
|
154
|
+
return s.forEach((g) => {
|
|
155
|
+
let T = 1;
|
|
156
|
+
g.forEach((q) => {
|
|
157
|
+
y.push(
|
|
158
|
+
`[data-autoform-id="${o}"] [data-field-key="${q}"] { display: block; grid-row: ${P}; grid-column: ${T}; }`
|
|
159
|
+
), T++;
|
|
160
|
+
}), P++;
|
|
161
|
+
}), h ? [
|
|
162
|
+
`@media (min-width: ${h}px) {`,
|
|
163
|
+
...y.map((g) => ` ${g}`),
|
|
164
|
+
"}"
|
|
165
|
+
].join(`
|
|
166
|
+
`) : y.join(`
|
|
167
|
+
`);
|
|
168
|
+
};
|
|
169
|
+
t.push(c(e.default));
|
|
170
|
+
const f = Object.keys(e).filter((s) => s !== "default").sort(
|
|
171
|
+
(s, h) => (m[s] ?? 0) - (m[h] ?? 0)
|
|
172
|
+
);
|
|
173
|
+
for (const s of f) {
|
|
174
|
+
const h = m[s], $ = e[s];
|
|
175
|
+
h && $ && t.push(c($, String(h)));
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return t.join(`
|
|
179
|
+
`);
|
|
180
|
+
});
|
|
181
|
+
return k({ validateAll: I, errors: l }), (m, o) => (i(), d("div", {
|
|
182
|
+
class: "autoform",
|
|
183
|
+
"data-autoform-id": A.value
|
|
184
|
+
}, [
|
|
185
|
+
x.value ? (i(), L(W("style"), { key: 0 }, {
|
|
186
|
+
default: X(() => [
|
|
187
|
+
Y(Z(x.value), 1)
|
|
188
|
+
]),
|
|
189
|
+
_: 1
|
|
190
|
+
})) : _("", !0),
|
|
191
|
+
U.value ? (i(), d("div", et, [
|
|
192
|
+
(i(!0), d(b, null, R(j.value, (t) => (i(), d("div", {
|
|
193
|
+
key: t,
|
|
194
|
+
class: "autoform-cell"
|
|
195
|
+
}, [
|
|
196
|
+
a.fields[t] ? (i(), d(b, { key: 0 }, [
|
|
197
|
+
(i(), L(W(a.fields[t].component), D({
|
|
198
|
+
modelValue: a.modelValue[t],
|
|
199
|
+
error: n(l)[t]
|
|
200
|
+
}, { ref_for: !0 }, a.fields[t].props ?? {}, {
|
|
201
|
+
"onUpdate:modelValue": (e) => n(p)(t, e),
|
|
202
|
+
onBlur: () => n(v)(t)
|
|
203
|
+
}), null, 16, ["modelValue", "error", "onUpdate:modelValue", "onBlur"])),
|
|
204
|
+
V(m.$slots, "error", {
|
|
205
|
+
fieldKey: t,
|
|
206
|
+
error: n(l)[t]
|
|
207
|
+
})
|
|
208
|
+
], 64)) : (i(), d(b, { key: 1 }, [
|
|
209
|
+
V(m.$slots, `field-${t}`, {
|
|
210
|
+
fieldKey: t,
|
|
211
|
+
value: a.modelValue[t],
|
|
212
|
+
error: n(l)[t],
|
|
213
|
+
onUpdate: (e) => n(p)(t, e),
|
|
214
|
+
onBlur: () => n(v)(t)
|
|
215
|
+
}, () => [
|
|
216
|
+
M("input", {
|
|
217
|
+
class: "autoform-default-input",
|
|
218
|
+
value: String(a.modelValue[t] ?? ""),
|
|
219
|
+
onInput: (e) => n(p)(t, e.target.value),
|
|
220
|
+
onBlur: () => n(v)(t)
|
|
221
|
+
}, null, 40, rt)
|
|
222
|
+
]),
|
|
223
|
+
V(m.$slots, "error", {
|
|
224
|
+
fieldKey: t,
|
|
225
|
+
error: n(l)[t]
|
|
226
|
+
})
|
|
227
|
+
], 64))
|
|
228
|
+
]))), 128))
|
|
229
|
+
])) : (i(), d("div", at, [
|
|
230
|
+
(i(!0), d(b, null, R(j.value, (t) => (i(), d("div", {
|
|
231
|
+
key: t,
|
|
232
|
+
class: "autoform-cell",
|
|
233
|
+
"data-field-key": t
|
|
234
|
+
}, [
|
|
235
|
+
a.fields[t] ? (i(), d(b, { key: 0 }, [
|
|
236
|
+
(i(), L(W(a.fields[t].component), D({
|
|
237
|
+
modelValue: a.modelValue[t],
|
|
238
|
+
error: n(l)[t]
|
|
239
|
+
}, { ref_for: !0 }, a.fields[t].props ?? {}, {
|
|
240
|
+
"onUpdate:modelValue": (e) => n(p)(t, e),
|
|
241
|
+
onBlur: () => n(v)(t)
|
|
242
|
+
}), null, 16, ["modelValue", "error", "onUpdate:modelValue", "onBlur"])),
|
|
243
|
+
V(m.$slots, "error", {
|
|
244
|
+
fieldKey: t,
|
|
245
|
+
error: n(l)[t]
|
|
246
|
+
})
|
|
247
|
+
], 64)) : (i(), d(b, { key: 1 }, [
|
|
248
|
+
V(m.$slots, `field-${t}`, {
|
|
249
|
+
fieldKey: t,
|
|
250
|
+
value: a.modelValue[t],
|
|
251
|
+
error: n(l)[t],
|
|
252
|
+
onUpdate: (e) => n(p)(t, e),
|
|
253
|
+
onBlur: () => n(v)(t)
|
|
254
|
+
}, () => [
|
|
255
|
+
M("input", {
|
|
256
|
+
class: "autoform-default-input",
|
|
257
|
+
value: String(a.modelValue[t] ?? ""),
|
|
258
|
+
onInput: (e) => n(p)(t, e.target.value),
|
|
259
|
+
onBlur: () => n(v)(t)
|
|
260
|
+
}, null, 40, nt)
|
|
261
|
+
]),
|
|
262
|
+
V(m.$slots, "error", {
|
|
263
|
+
fieldKey: t,
|
|
264
|
+
error: n(l)[t]
|
|
265
|
+
})
|
|
266
|
+
], 64))
|
|
267
|
+
], 8, st))), 128))
|
|
268
|
+
]))
|
|
269
|
+
], 8, ot));
|
|
270
|
+
}
|
|
271
|
+
}), ct = /* @__PURE__ */ z({
|
|
272
|
+
__name: "AutoFormRow",
|
|
273
|
+
props: {
|
|
274
|
+
row: {}
|
|
275
|
+
},
|
|
276
|
+
setup(a) {
|
|
277
|
+
return (k, w) => (i(), d("div", {
|
|
278
|
+
class: "autoform-row",
|
|
279
|
+
style: K({ "--autoform-cols": a.row.length })
|
|
280
|
+
}, [
|
|
281
|
+
(i(!0), d(b, null, R(a.row, (u) => (i(), d("div", {
|
|
282
|
+
key: u,
|
|
283
|
+
class: "autoform-cell"
|
|
284
|
+
}, [
|
|
285
|
+
V(k.$slots, "default", { fieldKey: u })
|
|
286
|
+
]))), 128))
|
|
287
|
+
], 4));
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
export {
|
|
291
|
+
lt as AutoForm,
|
|
292
|
+
ct as AutoFormRow,
|
|
293
|
+
G as DEFAULT_BREAKPOINTS,
|
|
294
|
+
N as isExplicitLayout,
|
|
295
|
+
C as isShorthandLayout,
|
|
296
|
+
tt as useAutoForm
|
|
297
|
+
};
|
|
298
|
+
//# sourceMappingURL=vue-autoform.es.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vue-autoform.es.js","sources":["../src/types.ts","../src/composables/useAutoForm.ts","../src/components/AutoForm.vue","../src/components/AutoFormRow.vue"],"sourcesContent":["import type { Component } from 'vue'\nimport type { ZodObject, ZodRawShape } from 'zod'\n\nexport type BreakpointKey = 'sm' | 'md' | 'lg' | 'xl' | '2xl'\n\nexport type BreakpointMap = Record<BreakpointKey, number>\n\nexport const DEFAULT_BREAKPOINTS: BreakpointMap = {\n sm: 640,\n md: 768,\n lg: 1024,\n xl: 1280,\n '2xl': 1536,\n}\n\nexport interface FieldConfig {\n component: Component\n props?: Record<string, unknown>\n [key: string]: unknown\n}\n\nexport type LayoutRow = string[]\n\nexport type LayoutGrid = LayoutRow[]\n\nexport type ShorthandLayout = { default: number } & Partial<Record<BreakpointKey, number>>\n\nexport type ExplicitLayout = { default: LayoutGrid } & Partial<Record<BreakpointKey, LayoutGrid>>\n\nexport type AutoFormLayout = ShorthandLayout | ExplicitLayout\n\nexport function isShorthandLayout(layout: AutoFormLayout): layout is ShorthandLayout {\n return typeof layout.default === 'number'\n}\n\nexport function isExplicitLayout(layout: AutoFormLayout): layout is ExplicitLayout {\n return Array.isArray(layout.default)\n}\n\nexport interface AutoFormProps {\n schema: ZodObject<ZodRawShape>\n layout?: AutoFormLayout\n fields: Record<string, FieldConfig>\n modelValue: Record<string, unknown>\n validateOn?: 'blur' | 'input' | 'submit'\n breakpoints?: Partial<BreakpointMap>\n}\n\nexport interface FieldRenderInfo {\n key: string\n config: FieldConfig | undefined\n value: unknown\n error: string | undefined\n}\n","import { reactive, computed } from 'vue'\nimport type { Ref } from 'vue'\nimport type { ZodObject, ZodRawShape } from 'zod'\nimport type { BreakpointMap, AutoFormLayout, LayoutGrid } from '../types'\nimport {\n DEFAULT_BREAKPOINTS,\n isShorthandLayout,\n isExplicitLayout,\n} from '../types'\n\nexport function useAutoForm(\n schema: ZodObject<ZodRawShape>,\n modelValue: Ref<Record<string, unknown>>,\n emit: (event: 'update:modelValue', value: Record<string, unknown>) => void,\n validateOn: Ref<'blur' | 'input' | 'submit'>,\n layout: Ref<AutoFormLayout | undefined>,\n breakpointsOverride: Ref<Partial<BreakpointMap> | undefined>,\n) {\n const errors = reactive<Record<string, string>>({})\n\n const breakpoints = computed<BreakpointMap>(() => ({\n ...DEFAULT_BREAKPOINTS,\n ...breakpointsOverride.value,\n }))\n\n const schemaKeys = computed<string[]>(() => Object.keys(schema.shape))\n\n const resolvedLayout = computed<LayoutGrid>(() => {\n const l = layout.value\n if (!l) {\n return schemaKeys.value.map((key: string) => [key])\n }\n if (isExplicitLayout(l)) {\n return l.default\n }\n if (isShorthandLayout(l)) {\n const cols = l.default\n const keys = schemaKeys.value\n const rows: LayoutGrid = []\n for (let i = 0; i < keys.length; i += cols) {\n rows.push(keys.slice(i, i + cols))\n }\n return rows\n }\n return schemaKeys.value.map((key: string) => [key])\n })\n\n function validateField(key: string, value: unknown): string | undefined {\n const shape = schema.shape\n if (!shape[key]) return undefined\n const fieldSchema = shape[key]\n const result = fieldSchema.safeParse(value)\n if (!result.success) {\n return result.error.errors[0]?.message ?? 'Invalid value'\n }\n return undefined\n }\n\n function validateAll(): boolean {\n const result = schema.safeParse(modelValue.value)\n if (!result.success) {\n result.error.errors.forEach((err) => {\n const key = String(err.path[0])\n errors[key] = err.message\n })\n return false\n }\n Object.keys(errors).forEach((k: string) => delete errors[k])\n return true\n }\n\n function onFieldInput(key: string, value: unknown) {\n const updated = { ...modelValue.value, [key]: value }\n emit('update:modelValue', updated)\n if (validateOn.value === 'input') {\n const msg = validateField(key, value)\n if (msg) {\n errors[key] = msg\n } else {\n delete errors[key]\n }\n }\n }\n\n function onFieldBlur(key: string) {\n if (validateOn.value === 'blur') {\n const msg = validateField(key, modelValue.value[key])\n if (msg) {\n errors[key] = msg\n } else {\n delete errors[key]\n }\n }\n }\n\n function getBreakpointLayouts(): Array<{ minWidth: number; grid: LayoutGrid; key: string }> {\n const l = layout.value\n if (!l) return []\n\n const bps = breakpoints.value\n const result: Array<{ minWidth: number; grid: LayoutGrid; key: string }> = []\n\n if (isExplicitLayout(l)) {\n const bpKeys = Object.keys(l).filter((k) => k !== 'default') as Array<keyof typeof l>\n for (const bpKey of bpKeys) {\n const minWidth = bps[bpKey as keyof BreakpointMap]\n const grid = l[bpKey as keyof typeof l] as LayoutGrid\n if (minWidth && grid) {\n result.push({ minWidth, grid, key: bpKey })\n }\n }\n } else if (isShorthandLayout(l)) {\n const bpKeys = Object.keys(l).filter((k) => k !== 'default') as Array<keyof typeof l>\n for (const bpKey of bpKeys) {\n const minWidth = bps[bpKey as keyof BreakpointMap]\n const cols = l[bpKey as keyof typeof l] as number\n if (minWidth && cols) {\n const keys = schemaKeys.value\n const rows: LayoutGrid = []\n for (let i = 0; i < keys.length; i += cols) {\n rows.push(keys.slice(i, i + cols))\n }\n result.push({ minWidth, grid: rows, key: bpKey })\n }\n }\n }\n\n return result.sort((a, b) => a.minWidth - b.minWidth)\n }\n\n return {\n errors,\n resolvedLayout,\n schemaKeys,\n onFieldInput,\n onFieldBlur,\n validateAll,\n getBreakpointLayouts,\n }\n}\n","<template>\n <div class=\"autoform\" :data-autoform-id=\"formId\">\n <component :is=\"'style'\" v-if=\"mediaQueryCss\">{{\n mediaQueryCss\n }}</component>\n\n <!-- Shorthand layout: single flat grid, CSS handles column count per breakpoint -->\n <div v-if=\"isShorthand\" class=\"autoform-flat-grid\">\n <div v-for=\"fieldKey in flatKeys\" :key=\"fieldKey\" class=\"autoform-cell\">\n <template v-if=\"fields[fieldKey]\">\n <component\n :is=\"fields[fieldKey].component\"\n :modelValue=\"modelValue[fieldKey]\"\n :error=\"errors[fieldKey]\"\n v-bind=\"fields[fieldKey].props ?? {}\"\n @update:modelValue=\"(val: unknown) => onFieldInput(fieldKey, val)\"\n @blur=\"() => onFieldBlur(fieldKey)\"\n />\n <slot name=\"error\" :fieldKey=\"fieldKey\" :error=\"errors[fieldKey]\" />\n </template>\n <template v-else>\n <slot\n :name=\"`field-${fieldKey}`\"\n :fieldKey=\"fieldKey\"\n :value=\"modelValue[fieldKey]\"\n :error=\"errors[fieldKey]\"\n :onUpdate=\"(val: unknown) => onFieldInput(fieldKey, val)\"\n :onBlur=\"() => onFieldBlur(fieldKey)\"\n >\n <input\n class=\"autoform-default-input\"\n :value=\"String(modelValue[fieldKey] ?? '')\"\n @input=\"\n (e: Event) =>\n onFieldInput(fieldKey, (e.target as HTMLInputElement).value)\n \"\n @blur=\"() => onFieldBlur(fieldKey)\"\n />\n </slot>\n <slot name=\"error\" :fieldKey=\"fieldKey\" :error=\"errors[fieldKey]\" />\n </template>\n </div>\n </div>\n\n <!-- Explicit layout / no layout: flat grid, CSS positions each field per breakpoint -->\n <div v-else class=\"autoform-flat-grid\">\n <div\n v-for=\"fieldKey in flatKeys\"\n :key=\"fieldKey\"\n class=\"autoform-cell\"\n :data-field-key=\"fieldKey\"\n >\n <template v-if=\"fields[fieldKey]\">\n <component\n :is=\"fields[fieldKey].component\"\n :modelValue=\"modelValue[fieldKey]\"\n :error=\"errors[fieldKey]\"\n v-bind=\"fields[fieldKey].props ?? {}\"\n @update:modelValue=\"(val: unknown) => onFieldInput(fieldKey, val)\"\n @blur=\"() => onFieldBlur(fieldKey)\"\n />\n <slot name=\"error\" :fieldKey=\"fieldKey\" :error=\"errors[fieldKey]\" />\n </template>\n <template v-else>\n <slot\n :name=\"`field-${fieldKey}`\"\n :fieldKey=\"fieldKey\"\n :value=\"modelValue[fieldKey]\"\n :error=\"errors[fieldKey]\"\n :onUpdate=\"(val: unknown) => onFieldInput(fieldKey, val)\"\n :onBlur=\"() => onFieldBlur(fieldKey)\"\n >\n <input\n class=\"autoform-default-input\"\n :value=\"String(modelValue[fieldKey] ?? '')\"\n @input=\"\n (e: Event) =>\n onFieldInput(fieldKey, (e.target as HTMLInputElement).value)\n \"\n @blur=\"() => onFieldBlur(fieldKey)\"\n />\n </slot>\n <slot name=\"error\" :fieldKey=\"fieldKey\" :error=\"errors[fieldKey]\" />\n </template>\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, ref, toRef } from \"vue\";\nimport type { ZodObject, ZodRawShape } from \"zod\";\nimport { useAutoForm } from \"../composables/useAutoForm\";\nimport type {\n AutoFormLayout,\n BreakpointMap,\n FieldConfig,\n LayoutGrid,\n} from \"../types\";\nimport {\n isExplicitLayout,\n isShorthandLayout,\n DEFAULT_BREAKPOINTS,\n} from \"../types\";\n\nconst props = withDefaults(\n defineProps<{\n schema: ZodObject<ZodRawShape>;\n layout?: AutoFormLayout;\n fields: Record<string, FieldConfig>;\n modelValue: Record<string, unknown>;\n validateOn?: \"blur\" | \"input\" | \"submit\";\n breakpoints?: Partial<BreakpointMap>;\n }>(),\n {\n validateOn: \"blur\",\n },\n);\n\nconst emit = defineEmits<{\n (e: \"update:modelValue\", value: Record<string, unknown>): void;\n}>();\n\nconst formId = ref(`autoform-${Math.random().toString(36).slice(2, 9)}`);\n\nconst { errors, schemaKeys, onFieldInput, onFieldBlur, validateAll } =\n useAutoForm(\n props.schema,\n toRef(props, \"modelValue\"),\n (_, val) => emit(\"update:modelValue\", val),\n toRef(props, \"validateOn\"),\n toRef(props, \"layout\"),\n toRef(props, \"breakpoints\"),\n );\n\nconst isShorthand = computed(() =>\n props.layout ? isShorthandLayout(props.layout) : false,\n);\n\nconst flatKeys = computed(() => schemaKeys.value);\n\nconst mediaQueryCss = computed<string>(() => {\n if (!props.layout) return \"\";\n\n const bps: BreakpointMap = { ...DEFAULT_BREAKPOINTS, ...props.breakpoints };\n const id = formId.value;\n const lines: string[] = [];\n\n if (isShorthandLayout(props.layout)) {\n const layout = props.layout;\n // Base columns for the flat grid\n lines.push(\n `[data-autoform-id=\"${id}\"] .autoform-flat-grid {`,\n ` grid-template-columns: repeat(${layout.default}, minmax(0, 1fr));`,\n `}`,\n );\n const bpKeys = Object.keys(layout).filter((k) => k !== \"default\") as Array<\n keyof typeof layout\n >;\n for (const bpKey of bpKeys) {\n const minWidth = bps[bpKey as keyof BreakpointMap];\n const cols = layout[bpKey as keyof typeof layout] as number;\n if (minWidth && cols) {\n lines.push(\n `@media (min-width: ${minWidth}px) {`,\n ` [data-autoform-id=\"${id}\"] .autoform-flat-grid {`,\n ` grid-template-columns: repeat(${cols}, minmax(0, 1fr));`,\n ` }`,\n `}`,\n );\n }\n }\n } else if (isExplicitLayout(props.layout)) {\n const layout = props.layout;\n // Helper: build CSS rules for a given grid at a given scope (media query or base)\n const gridToCss = (grid: LayoutGrid, wrap?: string): string => {\n const maxCols = Math.max(...grid.map((r: string[]) => r.length));\n const allKeys = schemaKeys.value;\n const keysInGrid = new Set(grid.flat());\n const fieldRules: string[] = [];\n\n // Set grid column count\n fieldRules.push(\n `[data-autoform-id=\"${id}\"] .autoform-flat-grid { grid-template-columns: repeat(${maxCols}, minmax(0, 1fr)); }`,\n );\n\n // Hide fields not in this layout\n allKeys.forEach((key: string) => {\n if (!keysInGrid.has(key)) {\n fieldRules.push(\n `[data-autoform-id=\"${id}\"] [data-field-key=\"${key}\"] { display: none; }`,\n );\n }\n });\n\n // Position each field\n let rowStart = 1;\n grid.forEach((row: string[]) => {\n let colStart = 1;\n row.forEach((key: string) => {\n fieldRules.push(\n `[data-autoform-id=\"${id}\"] [data-field-key=\"${key}\"] { display: block; grid-row: ${rowStart}; grid-column: ${colStart}; }`,\n );\n colStart++;\n });\n rowStart++;\n });\n\n if (wrap) {\n return [\n `@media (min-width: ${wrap}px) {`,\n ...fieldRules.map((r) => ` ${r}`),\n `}`,\n ].join(\"\\n\");\n }\n return fieldRules.join(\"\\n\");\n };\n\n // Default layout base styles\n lines.push(gridToCss(layout.default));\n\n // Per-breakpoint overrides\n const bpKeys = Object.keys(layout).filter((k) => k !== \"default\") as Array<\n keyof typeof layout\n >;\n const sortedBpKeys = bpKeys.sort(\n (a, b) =>\n (bps[a as keyof BreakpointMap] ?? 0) -\n (bps[b as keyof BreakpointMap] ?? 0),\n );\n for (const bpKey of sortedBpKeys) {\n const minWidth = bps[bpKey as keyof BreakpointMap];\n const grid = layout[bpKey as keyof typeof layout] as LayoutGrid;\n if (minWidth && grid) {\n lines.push(gridToCss(grid, String(minWidth)));\n }\n }\n }\n\n return lines.join(\"\\n\");\n});\n\ndefineExpose({ validateAll, errors });\n</script>\n\n<style>\n.autoform {\n width: 100%;\n display: flex;\n flex-direction: column;\n gap: var(--autoform-row-gap, 1rem);\n}\n\n.autoform-flat-grid {\n display: grid;\n grid-template-columns: repeat(1, minmax(0, 1fr));\n gap: var(--autoform-gap, 1rem);\n width: 100%;\n}\n\n.autoform-flat-grid .autoform-cell {\n min-width: 0;\n}\n\n.autoform-default-input {\n width: 100%;\n padding: 0.5rem 0.75rem;\n border: 1px solid #d1d5db;\n border-radius: 0.375rem;\n font-size: 1rem;\n outline: none;\n box-sizing: border-box;\n}\n\n.autoform-default-input:focus {\n border-color: #6366f1;\n box-shadow: 0 0 0 2px rgba(99, 102, 241, 0.2);\n}\n</style>\n","<template>\n <div\n class=\"autoform-row\"\n :style=\"{ '--autoform-cols': row.length }\"\n >\n <div\n v-for=\"fieldKey in row\"\n :key=\"fieldKey\"\n class=\"autoform-cell\"\n >\n <slot :fieldKey=\"fieldKey\" />\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\ndefineProps<{\n row: string[]\n}>()\n</script>\n\n<style>\n.autoform-row {\n display: grid;\n grid-template-columns: repeat(var(--autoform-cols, 1), minmax(0, 1fr));\n gap: var(--autoform-gap, 1rem);\n width: 100%;\n}\n\n.autoform-cell {\n min-width: 0;\n}\n</style>\n"],"names":["DEFAULT_BREAKPOINTS","isShorthandLayout","layout","isExplicitLayout","useAutoForm","schema","modelValue","emit","validateOn","breakpointsOverride","errors","reactive","breakpoints","computed","schemaKeys","resolvedLayout","l","key","cols","keys","rows","i","validateField","value","shape","result","_a","validateAll","k","err","onFieldInput","updated","msg","onFieldBlur","getBreakpointLayouts","bps","bpKeys","bpKey","minWidth","grid","a","b","props","__props","__emit","formId","ref","toRef","_","val","isShorthand","flatKeys","mediaQueryCss","id","lines","gridToCss","wrap","maxCols","r","allKeys","keysInGrid","fieldRules","rowStart","row","colStart","sortedBpKeys","__expose","_createElementBlock","_openBlock","_createBlock","_resolveDynamicComponent","_hoisted_2","_Fragment","_renderList","fieldKey","_mergeProps","_unref","_renderSlot","_ctx","_createElementVNode","_hoisted_4","_normalizeStyle"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@moonmangit/vue-autoform",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Headless Vue 3 auto-rendering form library with Zod schema validation and responsive grid layout",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/vue-autoform.cjs.js",
|
|
7
|
+
"module": "./dist/vue-autoform.es.js",
|
|
8
|
+
"types": "./dist/vue-autoform.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": "./dist/vue-autoform.es.js",
|
|
12
|
+
"require": "./dist/vue-autoform.cjs.js",
|
|
13
|
+
"types": "./dist/vue-autoform.d.ts"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist"
|
|
18
|
+
],
|
|
19
|
+
"peerDependencies": {
|
|
20
|
+
"vue": "^3.3.0",
|
|
21
|
+
"zod": "^3.22.0"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@eslint/js": "^10.0.1",
|
|
25
|
+
"@types/node": "^25.9.2",
|
|
26
|
+
"@vitejs/plugin-vue": "^5.0.0",
|
|
27
|
+
"eslint": "^10.4.1",
|
|
28
|
+
"eslint-plugin-vue": "^10.9.2",
|
|
29
|
+
"jiti": "^2.7.0",
|
|
30
|
+
"typescript": "^5.3.0",
|
|
31
|
+
"typescript-eslint": "^8.60.1",
|
|
32
|
+
"vite": "^5.0.0",
|
|
33
|
+
"vite-plugin-dts": "^3.7.0",
|
|
34
|
+
"vue": "^3.4.0",
|
|
35
|
+
"vue-eslint-parser": "^10.4.1",
|
|
36
|
+
"vue-tsc": "^2.0.0",
|
|
37
|
+
"zod": "^3.22.0"
|
|
38
|
+
},
|
|
39
|
+
"keywords": [
|
|
40
|
+
"vue",
|
|
41
|
+
"vue3",
|
|
42
|
+
"form",
|
|
43
|
+
"autoform",
|
|
44
|
+
"zod",
|
|
45
|
+
"schema",
|
|
46
|
+
"headless"
|
|
47
|
+
],
|
|
48
|
+
"license": "MIT",
|
|
49
|
+
"scripts": {
|
|
50
|
+
"dev": "vite",
|
|
51
|
+
"build": "vite build",
|
|
52
|
+
"playground": "vite --config playground/vite.config.ts",
|
|
53
|
+
"type-check": "vue-tsc --noEmit --project tsconfig.lib.json",
|
|
54
|
+
"lint": "eslint .",
|
|
55
|
+
"lint:fix": "eslint . --fix"
|
|
56
|
+
}
|
|
57
|
+
}
|