mirror of
https://github.com/LukeHagar/better-auth.git
synced 2025-12-06 12:27:44 +00:00
120 lines
3.2 KiB
Vue
120 lines
3.2 KiB
Vue
<script setup lang="ts" generic="T extends ZodObjectOrWrapped">
|
|
import { computed, toRefs } from "vue";
|
|
import type { ZodAny, z } from "zod";
|
|
import { toTypedSchema } from "@vee-validate/zod";
|
|
import type { FormContext, GenericObject } from "vee-validate";
|
|
import {
|
|
type ZodObjectOrWrapped,
|
|
getBaseSchema,
|
|
getBaseType,
|
|
getDefaultValueInZodStack,
|
|
getObjectFormSchema,
|
|
} from "./utils";
|
|
import type { Config, ConfigItem, Dependency, Shape } from "./interface";
|
|
import AutoFormField from "./AutoFormField.vue";
|
|
import { provideDependencies } from "./dependencies";
|
|
import { Form } from "@/components/ui/form";
|
|
|
|
const props = defineProps<{
|
|
schema: T;
|
|
form?: FormContext<GenericObject>;
|
|
fieldConfig?: Config<z.infer<T>>;
|
|
dependencies?: Dependency<z.infer<T>>[];
|
|
}>();
|
|
|
|
const emits = defineEmits<{
|
|
submit: [event: z.infer<T>];
|
|
}>();
|
|
|
|
const { dependencies } = toRefs(props);
|
|
provideDependencies(dependencies);
|
|
|
|
const shapes = computed(() => {
|
|
// @ts-expect-error ignore {} not assignable to object
|
|
const val: { [key in keyof T]: Shape } = {};
|
|
const baseSchema = getObjectFormSchema(props.schema);
|
|
const shape = baseSchema.shape;
|
|
Object.keys(shape).forEach((name) => {
|
|
const item = shape[name] as ZodAny;
|
|
const baseItem = getBaseSchema(item) as ZodAny;
|
|
let options =
|
|
baseItem && "values" in baseItem._def
|
|
? (baseItem._def.values as string[])
|
|
: undefined;
|
|
if (!Array.isArray(options) && typeof options === "object")
|
|
options = Object.values(options);
|
|
|
|
val[name as keyof T] = {
|
|
type: getBaseType(item),
|
|
default: getDefaultValueInZodStack(item),
|
|
options,
|
|
required: !["ZodOptional", "ZodNullable"].includes(item._def.typeName),
|
|
schema: baseItem,
|
|
};
|
|
});
|
|
return val;
|
|
});
|
|
|
|
const fields = computed(() => {
|
|
// @ts-expect-error ignore {} not assignable to object
|
|
const val: {
|
|
[key in keyof z.infer<T>]: {
|
|
shape: Shape;
|
|
fieldName: string;
|
|
config: ConfigItem;
|
|
};
|
|
} = {};
|
|
for (const key in shapes.value) {
|
|
const shape = shapes.value[key];
|
|
val[key as keyof z.infer<T>] = {
|
|
shape,
|
|
config: props.fieldConfig?.[key] as ConfigItem,
|
|
fieldName: key,
|
|
};
|
|
}
|
|
return val;
|
|
});
|
|
|
|
const formComponent = computed(() => (props.form ? "form" : Form));
|
|
const formComponentProps = computed(() => {
|
|
if (props.form) {
|
|
return {
|
|
onSubmit: props.form.handleSubmit((val) => emits("submit", val)),
|
|
};
|
|
} else {
|
|
const formSchema = toTypedSchema(props.schema);
|
|
return {
|
|
keepValues: true,
|
|
validationSchema: formSchema,
|
|
onSubmit: (val: GenericObject) => emits("submit", val),
|
|
};
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<component
|
|
:is="formComponent"
|
|
v-bind="formComponentProps"
|
|
>
|
|
<slot name="customAutoForm" :fields="fields">
|
|
<template v-for="(shape, key) of shapes" :key="key">
|
|
<slot
|
|
:shape="shape"
|
|
:name="key.toString() as keyof z.infer<T>"
|
|
:field-name="key.toString()"
|
|
:config="fieldConfig?.[key as keyof typeof fieldConfig] as ConfigItem"
|
|
>
|
|
<AutoFormField
|
|
:config="fieldConfig?.[key as keyof typeof fieldConfig] as ConfigItem"
|
|
:field-name="key.toString()"
|
|
:shape="shape"
|
|
/>
|
|
</slot>
|
|
</template>
|
|
</slot>
|
|
|
|
<slot :shapes="shapes" />
|
|
</component>
|
|
</template>
|