@moonmangit/vue-autoform 0.1.4 → 0.1.7

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 CHANGED
@@ -149,11 +149,81 @@ defineEmits<{ (e: "update:modelValue", v: string): void; (e: "blur"): void }>();
149
149
 
150
150
  ```ts
151
151
  type FieldConfig = {
152
- component: Component; // your Vue component
153
- props?: Record<string, unknown>; // extra props passed through
152
+ component: Component;
153
+ // plain object OR a getter function (for reactive/async values)
154
+ props?: Record<string, unknown> | (() => Record<string, unknown>);
154
155
  };
155
156
  ```
156
157
 
158
+ ### Async options (props as a getter function)
159
+
160
+ When your field needs options loaded from a server, pass `props` as a **getter function** instead of a plain object. The function is called at render time so reactive refs inside it stay live — no need to rebuild the `fields` object when data arrives.
161
+
162
+ ```vue
163
+ <script setup lang="ts">
164
+ import { ref } from "vue";
165
+ import { z } from "zod";
166
+ import { AutoForm } from "@moonmangit/vue-autoform";
167
+ import SelectInput from "./components/SelectInput.vue";
168
+ import TextInput from "./components/TextInput.vue";
169
+
170
+ const loading = ref(false);
171
+ const options = ref<{ value: string; label: string }[]>([]);
172
+
173
+ // Fetch however you like — the library doesn't care
174
+ async function loadOptions() {
175
+ loading.value = true;
176
+ const res = await fetch("/api/frameworks");
177
+ options.value = await res.json();
178
+ loading.value = false;
179
+ }
180
+ loadOptions();
181
+
182
+ const schema = z.object({
183
+ name: z.string().min(1),
184
+ framework: z.string().min(1, "Please select a framework"),
185
+ // array-of-object field — Zod validates each item's shape
186
+ tags: z.array(z.object({ value: z.string(), label: z.string() })).min(1),
187
+ });
188
+
189
+ const fields = {
190
+ name: { component: TextInput, props: { label: "Name" } },
191
+
192
+ framework: {
193
+ component: SelectInput,
194
+ // getter — reads `loading` and `options` reactively at render time
195
+ props: () => ({
196
+ label: "Framework",
197
+ disabled: loading.value,
198
+ options: options.value,
199
+ }),
200
+ },
201
+
202
+ tags: {
203
+ component: SelectInput,
204
+ props: () => ({
205
+ label: "Tags",
206
+ disabled: loading.value,
207
+ options: options.value,
208
+ }),
209
+ },
210
+ };
211
+
212
+ const formData = ref({ name: "", framework: "", tags: [] });
213
+ </script>
214
+
215
+ <template>
216
+ <AutoForm v-model="formData" :schema="schema" :fields="fields" />
217
+ </template>
218
+ ```
219
+
220
+ **Key points:**
221
+
222
+ - Your component receives `disabled` and `options` as normal props — the library passes them through unchanged
223
+ - `tags` value is whatever your component emits via `update:modelValue` — pass an array of objects, receive an array of objects
224
+ - Zod validates the array contents exactly as defined in the schema
225
+ - The library has **no opinion on how you fetch** — use `fetch`, Axios, TanStack Query, Pinia, anything
226
+
157
227
  ---
158
228
 
159
229
  ## Layout
package/dist/style.css CHANGED
@@ -1 +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}
1
+ .autoform{width:100%}.autoform-flat-grid{display:grid;grid-template-columns:repeat(1,minmax(0,1fr));column-gap:var(--autoform-gap, 1rem);row-gap:var(--autoform-row-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}
@@ -1,5 +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;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("vue");function j(a,v,F,n){const d=e.reactive({}),$=e.computed(()=>Object.keys(a.shape));function m(o,s){var t;const i=a.shape;if(!(o in i))return;const u=i[o].safeParse(s);if(!u.success)return((t=u.error.errors[0])==null?void 0:t.message)??"Invalid value"}function E(){const o=a.safeParse(v.value);return o.success?(Object.keys(d).forEach(s=>delete d[s]),!0):(o.error.errors.forEach(s=>{const i=String(s.path[0]);d[i]=s.message}),!1)}const p={};function g(o,s){p[o]=s;const i={...v.value,[o]:s};if(F("update:modelValue",i),n.value==="input"){const r=m(o,s);r?d[o]=r:delete d[o]}}function V(o){if(n.value==="blur"){const s=o in p?p[o]:v.value[o],i=m(o,s);i?d[o]=i:delete d[o]}}return{errors:d,schemaKeys:$,onFieldInput:g,onFieldBlur:V,validateAll:E}}const C={sm:640,md:768,lg:1024,xl:1280,"2xl":1536};function O(a){return typeof a.default=="number"}function x(a){return Array.isArray(a.default)}const N=["data-autoform-id"],w={class:"autoform-flat-grid"},D=["data-field-key"],R=["value","onInput","onBlur"],U=e.defineComponent({__name:"AutoForm",props:{schema:{},layout:{},fields:{},modelValue:{},validateOn:{default:"blur"},breakpoints:{}},emits:["update:modelValue"],setup(a,{expose:v,emit:F}){const n=a,d=F,$=e.ref(`autoform-${Math.random().toString(36).slice(2,9)}`),{errors:m,schemaKeys:E,onFieldInput:p,onFieldBlur:g,validateAll:V}=j(n.schema,e.toRef(n,"modelValue"),(r,u)=>d(r,u),e.toRef(n,"validateOn")),o=e.computed(()=>n.layout?x(n.layout):!0);function s(r){const u=n.fields[r];if(!u)return{};const t=u.props;return typeof t=="function"?t():t??{}}const i=e.computed(()=>{if(!n.layout)return"";const r={...C,...n.breakpoints},u=$.value,t=[];if(O(n.layout)){const l=n.layout;t.push(`[data-autoform-id="${u}"] .autoform-flat-grid {`,` grid-template-columns: repeat(${l.default}, minmax(0, 1fr));`,"}");const S=Object.keys(l).filter(B=>B!=="default");for(const B of S){const b=r[B],c=l[B];b&&c&&t.push(`@media (min-width: ${b}px) {`,` [data-autoform-id="${u}"] .autoform-flat-grid {`,` grid-template-columns: repeat(${c}, minmax(0, 1fr));`," }","}")}}else if(x(n.layout)){const l=n.layout,S=(c,h)=>{const y=Math.max(...c.map(f=>f.length)),L=E.value,P=new Set(c.flat()),k=[];k.push(`[data-autoform-id="${u}"] .autoform-flat-grid { grid-template-columns: repeat(${y}, minmax(0, 1fr)); }`),L.forEach(f=>{P.has(f)||k.push(`[data-autoform-id="${u}"] [data-field-key="${f}"] { display: none; }`)});let A=1;return c.forEach(f=>{let I=1;f.forEach(T=>{k.push(`[data-autoform-id="${u}"] [data-field-key="${T}"] { display: block; grid-row: ${A}; grid-column: ${I}; }`),I++}),A++}),h?[`@media (min-width: ${h}px) {`,...k.map(f=>` ${f}`),"}"].join(`
2
+ `):k.join(`
3
+ `)};t.push(S(l.default));const b=Object.keys(l).filter(c=>c!=="default").sort((c,h)=>(r[c]??0)-(r[h]??0));for(const c of b){const h=r[c],y=l[c];h&&y&&t.push(S(y,String(h)))}}return t.join(`
4
+ `)});return v({validateAll:V,errors:m}),(r,u)=>(e.openBlock(),e.createElementBlock("div",{class:"autoform","data-autoform-id":$.value},[i.value?(e.openBlock(),e.createBlock(e.resolveDynamicComponent("style"),{key:0},{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(i.value),1)]),_:1})):e.createCommentVNode("",!0),e.createElementVNode("div",w,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(e.unref(E),t=>(e.openBlock(),e.createElementBlock("div",{key:t,class:"autoform-cell","data-field-key":o.value?t:void 0},[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(m)[t]},{ref_for:!0},s(t),{"onUpdate:modelValue":l=>e.unref(p)(t,l),onBlur:()=>e.unref(g)(t)}),null,16,["modelValue","error","onUpdate:modelValue","onBlur"])),e.renderSlot(r.$slots,"error",{fieldKey:t,error:e.unref(m)[t]})],64)):(e.openBlock(),e.createElementBlock(e.Fragment,{key:1},[e.renderSlot(r.$slots,`field-${t}`,{fieldKey:t,value:a.modelValue[t],error:e.unref(m)[t],onUpdate:l=>e.unref(p)(t,l),onBlur:()=>e.unref(g)(t)},()=>[e.createElementVNode("input",{class:"autoform-default-input",value:String(a.modelValue[t]??""),onInput:l=>e.unref(p)(t,l.target.value),onBlur:()=>e.unref(g)(t)},null,40,R)]),e.renderSlot(r.$slots,"error",{fieldKey:t,error:e.unref(m)[t]})],64))],8,D))),128))])],8,N))}});exports.AutoForm=U;exports.DEFAULT_BREAKPOINTS=C;exports.isExplicitLayout=x;exports.isShorthandLayout=O;exports.useAutoForm=j;
5
5
  //# sourceMappingURL=vue-autoform.cjs.js.map
@@ -1 +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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"}
1
+ {"version":3,"file":"vue-autoform.cjs.js","sources":["../src/composables/useAutoForm.ts","../src/types.ts","../src/components/AutoForm.vue"],"sourcesContent":["import { reactive, computed } from 'vue'\nimport type { Ref } from 'vue'\nimport type { ZodObject, ZodRawShape } from 'zod'\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) {\n const errors = reactive<Record<string, string>>({})\n\n const schemaKeys = computed<string[]>(() => Object.keys(schema.shape))\n\n function validateField(key: string, value: unknown): string | undefined {\n const shape = schema.shape\n if (!(key in shape)) 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 const lastValue: Record<string, unknown> = {}\n\n function onFieldInput(key: string, value: unknown) {\n lastValue[key] = value\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 // Use lastValue if available — modelValue prop may not have propagated yet\n // when blur fires immediately after update:modelValue (e.g. checkbox toggles)\n const value = key in lastValue ? lastValue[key] : modelValue.value[key]\n const msg = validateField(key, value)\n if (msg) {\n errors[key] = msg\n } else {\n delete errors[key]\n }\n }\n }\n\n return {\n errors,\n schemaKeys,\n onFieldInput,\n onFieldBlur,\n validateAll,\n }\n}\n","import type { Component } from 'vue'\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> | (() => Record<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 FieldRenderInfo {\n key: string\n config: FieldConfig | undefined\n value: unknown\n error: string | undefined\n}\n","<template>\n <div class=\"autoform\" :data-autoform-id=\"formId\">\n <component :is=\"'style'\" v-if=\"mediaQueryCss\">{{\n mediaQueryCss\n }}</component>\n\n <!-- Flat grid: CSS handles column count (shorthand) or per-field position (explicit/none) -->\n <div class=\"autoform-flat-grid\">\n <div\n v-for=\"fieldKey in schemaKeys\"\n :key=\"fieldKey\"\n class=\"autoform-cell\"\n :data-field-key=\"isExplicit ? fieldKey : undefined\"\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=\"resolveProps(fieldKey)\"\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 (event, val) => emit(event, val),\n toRef(props, \"validateOn\"),\n );\n\nconst isExplicit = computed(() =>\n props.layout ? isExplicitLayout(props.layout) : true,\n);\n\nfunction resolveProps(fieldKey: string): Record<string, unknown> {\n const cfg = props.fields[fieldKey];\n if (!cfg) return {};\n const p = cfg.props;\n return typeof p === \"function\" ? p() : (p ?? {});\n}\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}\n\n.autoform-flat-grid {\n display: grid;\n grid-template-columns: repeat(1, minmax(0, 1fr));\n column-gap: var(--autoform-gap, 1rem);\n row-gap: var(--autoform-row-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"],"names":["useAutoForm","schema","modelValue","emit","validateOn","errors","reactive","schemaKeys","computed","validateField","key","value","shape","result","_a","validateAll","k","err","lastValue","onFieldInput","updated","msg","onFieldBlur","DEFAULT_BREAKPOINTS","isShorthandLayout","layout","isExplicitLayout","props","__props","__emit","formId","ref","toRef","event","val","isExplicit","resolveProps","fieldKey","cfg","p","mediaQueryCss","bps","id","lines","bpKeys","bpKey","minWidth","cols","gridToCss","grid","wrap","maxCols","r","allKeys","keysInGrid","fieldRules","rowStart","row","colStart","sortedBpKeys","a","b","__expose","_createElementBlock","_openBlock","_createBlock","_resolveDynamicComponent","_createElementVNode","_hoisted_2","_Fragment","_renderList","_unref","_mergeProps","_renderSlot","_ctx","e"],"mappings":"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"}
@@ -39,16 +39,8 @@ validateOn: string;
39
39
  validateOn: "blur" | "input" | "submit";
40
40
  }, {}, {}, {}, string, ComponentProvideOptions, true, {}, any>;
41
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
42
  declare type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;
49
43
 
50
- declare type __VLS_NonUndefinedable_2<T> = T extends undefined ? never : T;
51
-
52
44
  declare type __VLS_Prettify<T> = {
53
45
  [K in keyof T]: T[K];
54
46
  } & {};
@@ -59,12 +51,6 @@ declare function __VLS_template(): Partial<Record<`field-${string}`, (_: {
59
51
  error: string;
60
52
  onUpdate: (val: unknown) => void;
61
53
  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
54
  }) => any>> & {
69
55
  error?(_: {
70
56
  fieldKey: string;
@@ -72,12 +58,6 @@ declare function __VLS_template(): Partial<Record<`field-${string}`, (_: {
72
58
  }): any;
73
59
  };
74
60
 
75
- declare function __VLS_template_2(): {
76
- default?(_: {
77
- fieldKey: string;
78
- }): any;
79
- };
80
-
81
61
  declare type __VLS_TypePropsToRuntimeProps<T> = {
82
62
  [K in keyof T]-?: {} extends Pick<T, K> ? {
83
63
  type: PropType<__VLS_NonUndefinedable<T[K]>>;
@@ -87,15 +67,6 @@ declare type __VLS_TypePropsToRuntimeProps<T> = {
87
67
  };
88
68
  };
89
69
 
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
70
  declare type __VLS_WithDefaults<P, D> = {
100
71
  [K in keyof Pick<P, keyof P>]: K extends keyof D ? __VLS_Prettify<P[K] & {
101
72
  default: D[K];
@@ -108,27 +79,10 @@ declare type __VLS_WithTemplateSlots<T, S> = T & {
108
79
  };
109
80
  };
110
81
 
111
- declare type __VLS_WithTemplateSlots_2<T, S> = T & {
112
- new (): {
113
- $slots: S;
114
- };
115
- };
116
-
117
82
  export declare const AutoForm: __VLS_WithTemplateSlots<typeof __VLS_component, ReturnType<typeof __VLS_template>>;
118
83
 
119
84
  export declare type AutoFormLayout = ShorthandLayout | ExplicitLayout;
120
85
 
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
86
  export declare type BreakpointKey = 'sm' | 'md' | 'lg' | 'xl' | '2xl';
133
87
 
134
88
  export declare type BreakpointMap = Record<BreakpointKey, number>;
@@ -141,15 +95,7 @@ export declare type ExplicitLayout = {
141
95
 
142
96
  export declare interface FieldConfig {
143
97
  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;
98
+ props?: Record<string, unknown> | (() => Record<string, unknown>);
153
99
  }
154
100
 
155
101
  export declare function isExplicitLayout(layout: AutoFormLayout): layout is ExplicitLayout;
@@ -164,18 +110,12 @@ export declare type ShorthandLayout = {
164
110
  default: number;
165
111
  } & Partial<Record<BreakpointKey, number>>;
166
112
 
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>): {
113
+ 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'>): {
168
114
  errors: Record<string, string>;
169
- resolvedLayout: ComputedRef<LayoutGrid>;
170
115
  schemaKeys: ComputedRef<string[]>;
171
116
  onFieldInput: (key: string, value: unknown) => void;
172
117
  onFieldBlur: (key: string) => void;
173
118
  validateAll: () => boolean;
174
- getBreakpointLayouts: () => Array<{
175
- minWidth: number;
176
- grid: LayoutGrid;
177
- key: string;
178
- }>;
179
119
  };
180
120
 
181
121
  export { }
@@ -1,104 +1,58 @@
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";
1
+ import { reactive as M, computed as C, defineComponent as W, ref as G, toRef as P, openBlock as v, createElementBlock as y, createBlock as L, resolveDynamicComponent as N, withCtx as Q, createTextVNode as q, toDisplayString as z, createCommentVNode as H, createElementVNode as T, Fragment as I, renderList as J, unref as c, mergeProps as X, renderSlot as j } from "vue";
2
+ function Y(a, g, k, r) {
3
+ const d = M({}), S = C(() => Object.keys(a.shape));
4
+ function m(o, n) {
5
+ var t;
6
+ const i = a.shape;
7
+ if (!(o in i)) return;
8
+ const s = i[o].safeParse(n);
9
+ if (!s.success)
10
+ return ((t = s.error.errors[0]) == null ? void 0 : t.message) ?? "Invalid value";
40
11
  }
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;
12
+ function V() {
13
+ const o = a.safeParse(g.value);
14
+ return o.success ? (Object.keys(d).forEach((n) => delete d[n]), !0) : (o.error.errors.forEach((n) => {
15
+ const i = String(n.path[0]);
16
+ d[i] = n.message;
46
17
  }), !1);
47
18
  }
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];
19
+ const p = {};
20
+ function $(o, n) {
21
+ p[o] = n;
22
+ const i = { ...g.value, [o]: n };
23
+ if (k("update:modelValue", i), r.value === "input") {
24
+ const e = m(o, n);
25
+ e ? d[o] = e : delete d[o];
59
26
  }
60
27
  }
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
- }
28
+ function A(o) {
29
+ if (r.value === "blur") {
30
+ const n = o in p ? p[o] : g.value[o], i = m(o, n);
31
+ i ? d[o] = i : delete d[o];
82
32
  }
83
- return e.sort((c, r) => c.minWidth - r.minWidth);
84
33
  }
85
34
  return {
86
- errors: l,
87
- resolvedLayout: v,
88
- schemaKeys: p,
89
- onFieldInput: j,
90
- onFieldBlur: x,
91
- validateAll: U,
92
- getBreakpointLayouts: m
35
+ errors: d,
36
+ schemaKeys: S,
37
+ onFieldInput: $,
38
+ onFieldBlur: A,
39
+ validateAll: V
93
40
  };
94
41
  }
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({
42
+ const Z = {
43
+ sm: 640,
44
+ md: 768,
45
+ lg: 1024,
46
+ xl: 1280,
47
+ "2xl": 1536
48
+ };
49
+ function K(a) {
50
+ return typeof a.default == "number";
51
+ }
52
+ function U(a) {
53
+ return Array.isArray(a.default);
54
+ }
55
+ const tt = ["data-autoform-id"], ot = { class: "autoform-flat-grid" }, et = ["data-field-key"], rt = ["value", "onInput", "onBlur"], nt = /* @__PURE__ */ W({
102
56
  __name: "AutoForm",
103
57
  props: {
104
58
  schema: {},
@@ -109,190 +63,138 @@ const ot = ["data-autoform-id"], et = {
109
63
  breakpoints: {}
110
64
  },
111
65
  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;
66
+ setup(a, { expose: g, emit: k }) {
67
+ const r = a, d = k, S = G(`autoform-${Math.random().toString(36).slice(2, 9)}`), { errors: m, schemaKeys: V, onFieldInput: p, onFieldBlur: $, validateAll: A } = Y(
68
+ r.schema,
69
+ P(r, "modelValue"),
70
+ (e, s) => d(e, s),
71
+ P(r, "validateOn")
72
+ ), o = C(
73
+ () => r.layout ? U(r.layout) : !0
74
+ );
75
+ function n(e) {
76
+ const s = r.fields[e];
77
+ if (!s) return {};
78
+ const t = s.props;
79
+ return typeof t == "function" ? t() : t ?? {};
80
+ }
81
+ const i = C(() => {
82
+ if (!r.layout) return "";
83
+ const e = { ...Z, ...r.breakpoints }, s = S.value, t = [];
84
+ if (K(r.layout)) {
85
+ const u = r.layout;
127
86
  t.push(
128
- `[data-autoform-id="${o}"] .autoform-flat-grid {`,
129
- ` grid-template-columns: repeat(${e.default}, minmax(0, 1fr));`,
87
+ `[data-autoform-id="${s}"] .autoform-flat-grid {`,
88
+ ` grid-template-columns: repeat(${u.default}, minmax(0, 1fr));`,
130
89
  "}"
131
90
  );
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));`,
91
+ const B = Object.keys(u).filter((b) => b !== "default");
92
+ for (const b of B) {
93
+ const E = e[b], l = u[b];
94
+ E && l && t.push(
95
+ `@media (min-width: ${E}px) {`,
96
+ ` [data-autoform-id="${s}"] .autoform-flat-grid {`,
97
+ ` grid-template-columns: repeat(${l}, minmax(0, 1fr));`,
139
98
  " }",
140
99
  "}"
141
100
  );
142
101
  }
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; }`
102
+ } else if (U(r.layout)) {
103
+ const u = r.layout, B = (l, h) => {
104
+ const F = Math.max(...l.map((f) => f.length)), _ = V.value, D = new Set(l.flat()), x = [];
105
+ x.push(
106
+ `[data-autoform-id="${s}"] .autoform-flat-grid { grid-template-columns: repeat(${F}, minmax(0, 1fr)); }`
107
+ ), _.forEach((f) => {
108
+ D.has(f) || x.push(
109
+ `[data-autoform-id="${s}"] [data-field-key="${f}"] { display: none; }`
151
110
  );
152
111
  });
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++;
112
+ let O = 1;
113
+ return l.forEach((f) => {
114
+ let w = 1;
115
+ f.forEach((R) => {
116
+ x.push(
117
+ `[data-autoform-id="${s}"] [data-field-key="${R}"] { display: block; grid-row: ${O}; grid-column: ${w}; }`
118
+ ), w++;
119
+ }), O++;
161
120
  }), h ? [
162
121
  `@media (min-width: ${h}px) {`,
163
- ...y.map((g) => ` ${g}`),
122
+ ...x.map((f) => ` ${f}`),
164
123
  "}"
165
124
  ].join(`
166
- `) : y.join(`
125
+ `) : x.join(`
167
126
  `);
168
127
  };
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)
128
+ t.push(B(u.default));
129
+ const E = Object.keys(u).filter((l) => l !== "default").sort(
130
+ (l, h) => (e[l] ?? 0) - (e[h] ?? 0)
172
131
  );
173
- for (const s of f) {
174
- const h = m[s], $ = e[s];
175
- h && $ && t.push(c($, String(h)));
132
+ for (const l of E) {
133
+ const h = e[l], F = u[l];
134
+ h && F && t.push(B(F, String(h)));
176
135
  }
177
136
  }
178
137
  return t.join(`
179
138
  `);
180
139
  });
181
- return k({ validateAll: I, errors: l }), (m, o) => (i(), d("div", {
140
+ return g({ validateAll: A, errors: m }), (e, s) => (v(), y("div", {
182
141
  class: "autoform",
183
- "data-autoform-id": A.value
142
+ "data-autoform-id": S.value
184
143
  }, [
185
- x.value ? (i(), L(W("style"), { key: 0 }, {
186
- default: X(() => [
187
- Y(Z(x.value), 1)
144
+ i.value ? (v(), L(N("style"), { key: 0 }, {
145
+ default: Q(() => [
146
+ q(z(i.value), 1)
188
147
  ]),
189
148
  _: 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", {
149
+ })) : H("", !0),
150
+ T("div", ot, [
151
+ (v(!0), y(I, null, J(c(V), (t) => (v(), y("div", {
231
152
  key: t,
232
153
  class: "autoform-cell",
233
- "data-field-key": t
154
+ "data-field-key": o.value ? t : void 0
234
155
  }, [
235
- a.fields[t] ? (i(), d(b, { key: 0 }, [
236
- (i(), L(W(a.fields[t].component), D({
156
+ a.fields[t] ? (v(), y(I, { key: 0 }, [
157
+ (v(), L(N(a.fields[t].component), X({
237
158
  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)
159
+ error: c(m)[t]
160
+ }, { ref_for: !0 }, n(t), {
161
+ "onUpdate:modelValue": (u) => c(p)(t, u),
162
+ onBlur: () => c($)(t)
242
163
  }), null, 16, ["modelValue", "error", "onUpdate:modelValue", "onBlur"])),
243
- V(m.$slots, "error", {
164
+ j(e.$slots, "error", {
244
165
  fieldKey: t,
245
- error: n(l)[t]
166
+ error: c(m)[t]
246
167
  })
247
- ], 64)) : (i(), d(b, { key: 1 }, [
248
- V(m.$slots, `field-${t}`, {
168
+ ], 64)) : (v(), y(I, { key: 1 }, [
169
+ j(e.$slots, `field-${t}`, {
249
170
  fieldKey: t,
250
171
  value: a.modelValue[t],
251
- error: n(l)[t],
252
- onUpdate: (e) => n(p)(t, e),
253
- onBlur: () => n(v)(t)
172
+ error: c(m)[t],
173
+ onUpdate: (u) => c(p)(t, u),
174
+ onBlur: () => c($)(t)
254
175
  }, () => [
255
- M("input", {
176
+ T("input", {
256
177
  class: "autoform-default-input",
257
178
  value: String(a.modelValue[t] ?? ""),
258
- onInput: (e) => n(p)(t, e.target.value),
259
- onBlur: () => n(v)(t)
260
- }, null, 40, nt)
179
+ onInput: (u) => c(p)(t, u.target.value),
180
+ onBlur: () => c($)(t)
181
+ }, null, 40, rt)
261
182
  ]),
262
- V(m.$slots, "error", {
183
+ j(e.$slots, "error", {
263
184
  fieldKey: t,
264
- error: n(l)[t]
185
+ error: c(m)[t]
265
186
  })
266
187
  ], 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));
188
+ ], 8, et))), 128))
189
+ ])
190
+ ], 8, tt));
288
191
  }
289
192
  });
290
193
  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
194
+ nt as AutoForm,
195
+ Z as DEFAULT_BREAKPOINTS,
196
+ U as isExplicitLayout,
197
+ K as isShorthandLayout,
198
+ Y as useAutoForm
297
199
  };
298
200
  //# sourceMappingURL=vue-autoform.es.js.map
@@ -1 +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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"}
1
+ {"version":3,"file":"vue-autoform.es.js","sources":["../src/composables/useAutoForm.ts","../src/types.ts","../src/components/AutoForm.vue"],"sourcesContent":["import { reactive, computed } from 'vue'\nimport type { Ref } from 'vue'\nimport type { ZodObject, ZodRawShape } from 'zod'\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) {\n const errors = reactive<Record<string, string>>({})\n\n const schemaKeys = computed<string[]>(() => Object.keys(schema.shape))\n\n function validateField(key: string, value: unknown): string | undefined {\n const shape = schema.shape\n if (!(key in shape)) 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 const lastValue: Record<string, unknown> = {}\n\n function onFieldInput(key: string, value: unknown) {\n lastValue[key] = value\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 // Use lastValue if available — modelValue prop may not have propagated yet\n // when blur fires immediately after update:modelValue (e.g. checkbox toggles)\n const value = key in lastValue ? lastValue[key] : modelValue.value[key]\n const msg = validateField(key, value)\n if (msg) {\n errors[key] = msg\n } else {\n delete errors[key]\n }\n }\n }\n\n return {\n errors,\n schemaKeys,\n onFieldInput,\n onFieldBlur,\n validateAll,\n }\n}\n","import type { Component } from 'vue'\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> | (() => Record<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 FieldRenderInfo {\n key: string\n config: FieldConfig | undefined\n value: unknown\n error: string | undefined\n}\n","<template>\n <div class=\"autoform\" :data-autoform-id=\"formId\">\n <component :is=\"'style'\" v-if=\"mediaQueryCss\">{{\n mediaQueryCss\n }}</component>\n\n <!-- Flat grid: CSS handles column count (shorthand) or per-field position (explicit/none) -->\n <div class=\"autoform-flat-grid\">\n <div\n v-for=\"fieldKey in schemaKeys\"\n :key=\"fieldKey\"\n class=\"autoform-cell\"\n :data-field-key=\"isExplicit ? fieldKey : undefined\"\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=\"resolveProps(fieldKey)\"\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 (event, val) => emit(event, val),\n toRef(props, \"validateOn\"),\n );\n\nconst isExplicit = computed(() =>\n props.layout ? isExplicitLayout(props.layout) : true,\n);\n\nfunction resolveProps(fieldKey: string): Record<string, unknown> {\n const cfg = props.fields[fieldKey];\n if (!cfg) return {};\n const p = cfg.props;\n return typeof p === \"function\" ? p() : (p ?? {});\n}\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}\n\n.autoform-flat-grid {\n display: grid;\n grid-template-columns: repeat(1, minmax(0, 1fr));\n column-gap: var(--autoform-gap, 1rem);\n row-gap: var(--autoform-row-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"],"names":["useAutoForm","schema","modelValue","emit","validateOn","errors","reactive","schemaKeys","computed","validateField","key","value","shape","result","_a","validateAll","k","err","lastValue","onFieldInput","updated","msg","onFieldBlur","DEFAULT_BREAKPOINTS","isShorthandLayout","layout","isExplicitLayout","props","__props","__emit","formId","ref","toRef","event","val","isExplicit","resolveProps","fieldKey","cfg","p","mediaQueryCss","bps","id","lines","bpKeys","bpKey","minWidth","cols","gridToCss","grid","wrap","maxCols","r","allKeys","keysInGrid","fieldRules","rowStart","row","colStart","sortedBpKeys","a","b","__expose","_createElementBlock","_openBlock","_createBlock","_resolveDynamicComponent","_createElementVNode","_hoisted_2","_Fragment","_renderList","_unref","_mergeProps","_renderSlot","_ctx","e"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moonmangit/vue-autoform",
3
- "version": "0.1.4",
3
+ "version": "0.1.7",
4
4
  "description": "Headless Vue 3 auto-rendering form library with Zod schema validation and responsive grid layout",
5
5
  "type": "module",
6
6
  "main": "./dist/vue-autoform.cjs.js",