feat: show required field for object
This commit is contained in:
parent
2891dd2a15
commit
63081e8d21
|
|
@ -20,8 +20,6 @@ const props = defineProps<{
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const fieldContext = useField(props.fieldName)
|
|
||||||
|
|
||||||
function isZodArray(
|
function isZodArray(
|
||||||
item: z.ZodArray<any> | z.ZodDefault<any>,
|
item: z.ZodArray<any> | z.ZodDefault<any>,
|
||||||
): item is z.ZodArray<any> {
|
): item is z.ZodArray<any> {
|
||||||
|
|
@ -51,6 +49,7 @@ const itemShape = computed(() => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const fieldContext = useField(props.fieldName)
|
||||||
// @ts-expect-error ignore missing `id`
|
// @ts-expect-error ignore missing `id`
|
||||||
provide(FieldContextKey, fieldContext)
|
provide(FieldContextKey, fieldContext)
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,13 @@
|
||||||
<script setup lang="ts" generic="T extends ZodRawShape">
|
<script setup lang="ts" generic="T extends ZodRawShape">
|
||||||
import type { ZodAny, ZodObject, ZodRawShape } from 'zod'
|
import type { ZodAny, ZodObject, ZodRawShape } from 'zod'
|
||||||
import { computed } from 'vue'
|
import { computed, provide } from 'vue'
|
||||||
|
import { FieldContextKey, useField } from 'vee-validate'
|
||||||
import AutoFormField from './AutoFormField.vue'
|
import AutoFormField from './AutoFormField.vue'
|
||||||
import type { Config, ConfigItem, Shape } from './interface'
|
import type { Config, ConfigItem, Shape } from './interface'
|
||||||
import { beautifyObjectName, getBaseSchema, getBaseType, getDefaultValueInZodStack } from './utils'
|
import { beautifyObjectName, getBaseSchema, getBaseType, getDefaultValueInZodStack } from './utils'
|
||||||
|
import AutoFormLabel from './AutoFormLabel.vue'
|
||||||
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@/lib/registry/default/ui/accordion'
|
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@/lib/registry/default/ui/accordion'
|
||||||
|
import { FormItem } from '@/lib/registry/default/ui/form'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
fieldName: string
|
fieldName: string
|
||||||
|
|
@ -39,27 +42,35 @@ const shapes = computed(() => {
|
||||||
})
|
})
|
||||||
return val
|
return val
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const fieldContext = useField(props.fieldName)
|
||||||
|
// @ts-expect-error ignore missing `id`
|
||||||
|
provide(FieldContextKey, fieldContext)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<section>
|
<section>
|
||||||
<slot v-bind="props">
|
<slot v-bind="props">
|
||||||
<Accordion type="multiple" class="w-full" collapsible :disabled="disabled">
|
<Accordion type="single" as-child class="w-full" collapsible :disabled="disabled">
|
||||||
<AccordionItem :value="fieldName" class="border-none">
|
<FormItem>
|
||||||
<AccordionTrigger class="text-base">
|
<AccordionItem :value="fieldName" class="border-none">
|
||||||
{{ schema?.description || beautifyObjectName(fieldName) }}
|
<AccordionTrigger>
|
||||||
</AccordionTrigger>
|
<AutoFormLabel class="text-base" :required="required">
|
||||||
<AccordionContent class="p-1 space-y-5">
|
{{ schema?.description || beautifyObjectName(fieldName) }}
|
||||||
<template v-for="(shape, key) in shapes" :key="key">
|
</AutoFormLabel>
|
||||||
<AutoFormField
|
</AccordionTrigger>
|
||||||
:config="config?.[key as keyof typeof config] as ConfigItem"
|
<AccordionContent class="p-1 space-y-5">
|
||||||
:field-name="`${fieldName}.${key.toString()}`"
|
<template v-for="(shape, key) in shapes" :key="key">
|
||||||
:label="key.toString()"
|
<AutoFormField
|
||||||
:shape="shape"
|
:config="config?.[key as keyof typeof config] as ConfigItem"
|
||||||
/>
|
:field-name="`${fieldName}.${key.toString()}`"
|
||||||
</template>
|
:label="key.toString()"
|
||||||
</AccordionContent>
|
:shape="shape"
|
||||||
</AccordionItem>
|
/>
|
||||||
|
</template>
|
||||||
|
</AccordionContent>
|
||||||
|
</AccordionItem>
|
||||||
|
</FormItem>
|
||||||
</Accordion>
|
</Accordion>
|
||||||
</slot>
|
</slot>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,6 @@ const props = defineProps<{
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const fieldContext = useField(props.fieldName)
|
|
||||||
|
|
||||||
function isZodArray(
|
function isZodArray(
|
||||||
item: z.ZodArray<any> | z.ZodDefault<any>,
|
item: z.ZodArray<any> | z.ZodDefault<any>,
|
||||||
): item is z.ZodArray<any> {
|
): item is z.ZodArray<any> {
|
||||||
|
|
@ -51,6 +49,7 @@ const itemShape = computed(() => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const fieldContext = useField(props.fieldName)
|
||||||
// @ts-expect-error ignore missing `id`
|
// @ts-expect-error ignore missing `id`
|
||||||
provide(FieldContextKey, fieldContext)
|
provide(FieldContextKey, fieldContext)
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,13 @@
|
||||||
<script setup lang="ts" generic="T extends ZodRawShape">
|
<script setup lang="ts" generic="T extends ZodRawShape">
|
||||||
import type { ZodAny, ZodObject, ZodRawShape } from 'zod'
|
import type { ZodAny, ZodObject, ZodRawShape } from 'zod'
|
||||||
import { computed } from 'vue'
|
import { computed, provide } from 'vue'
|
||||||
|
import { FieldContextKey, useField } from 'vee-validate'
|
||||||
import AutoFormField from './AutoFormField.vue'
|
import AutoFormField from './AutoFormField.vue'
|
||||||
import type { Config, ConfigItem, Shape } from './interface'
|
import type { Config, ConfigItem, Shape } from './interface'
|
||||||
import { beautifyObjectName, getBaseSchema, getBaseType, getDefaultValueInZodStack } from './utils'
|
import { beautifyObjectName, getBaseSchema, getBaseType, getDefaultValueInZodStack } from './utils'
|
||||||
|
import AutoFormLabel from './AutoFormLabel.vue'
|
||||||
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@/lib/registry/new-york/ui/accordion'
|
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@/lib/registry/new-york/ui/accordion'
|
||||||
|
import { FormItem } from '@/lib/registry/new-york/ui/form'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
fieldName: string
|
fieldName: string
|
||||||
|
|
@ -39,27 +42,35 @@ const shapes = computed(() => {
|
||||||
})
|
})
|
||||||
return val
|
return val
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const fieldContext = useField(props.fieldName)
|
||||||
|
// @ts-expect-error ignore missing `id`
|
||||||
|
provide(FieldContextKey, fieldContext)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<section>
|
<section>
|
||||||
<slot v-bind="props">
|
<slot v-bind="props">
|
||||||
<Accordion type="multiple" class="w-full" collapsible :disabled="disabled">
|
<Accordion type="single" as-child class="w-full" collapsible :disabled="disabled">
|
||||||
<AccordionItem :value="fieldName" class="border-none">
|
<FormItem>
|
||||||
<AccordionTrigger class="text-base">
|
<AccordionItem :value="fieldName" class="border-none">
|
||||||
{{ schema?.description || beautifyObjectName(fieldName) }}
|
<AccordionTrigger>
|
||||||
</AccordionTrigger>
|
<AutoFormLabel class="text-base" :required="required">
|
||||||
<AccordionContent class="p-[1px] space-y-5">
|
{{ schema?.description || beautifyObjectName(fieldName) }}
|
||||||
<template v-for="(shape, key) in shapes" :key="key">
|
</AutoFormLabel>
|
||||||
<AutoFormField
|
</AccordionTrigger>
|
||||||
:config="config?.[key as keyof typeof config] as ConfigItem"
|
<AccordionContent class="p-1 space-y-5">
|
||||||
:field-name="`${fieldName}.${key.toString()}`"
|
<template v-for="(shape, key) in shapes" :key="key">
|
||||||
:label="key.toString()"
|
<AutoFormField
|
||||||
:shape="shape"
|
:config="config?.[key as keyof typeof config] as ConfigItem"
|
||||||
/>
|
:field-name="`${fieldName}.${key.toString()}`"
|
||||||
</template>
|
:label="key.toString()"
|
||||||
</AccordionContent>
|
:shape="shape"
|
||||||
</AccordionItem>
|
/>
|
||||||
|
</template>
|
||||||
|
</AccordionContent>
|
||||||
|
</AccordionItem>
|
||||||
|
</FormItem>
|
||||||
</Accordion>
|
</Accordion>
|
||||||
</slot>
|
</slot>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "AutoFormFieldArray.vue",
|
"name": "AutoFormFieldArray.vue",
|
||||||
"content": "<script setup lang=\"ts\" generic=\"T extends z.ZodAny\">\nimport * as z from 'zod'\nimport { computed, provide } from 'vue'\nimport { PlusIcon, TrashIcon } from 'lucide-vue-next'\nimport { FieldArray, FieldContextKey, useField } from 'vee-validate'\nimport type { Config, ConfigItem } from './interface'\nimport { beautifyObjectName, getBaseType } from './utils'\nimport AutoFormField from './AutoFormField.vue'\nimport AutoFormLabel from './AutoFormLabel.vue'\nimport { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@/lib/registry/default/ui/accordion'\nimport { Button } from '@/lib/registry/default/ui/button'\nimport { Separator } from '@/lib/registry/default/ui/separator'\nimport { FormItem, FormMessage } from '@/lib/registry/default/ui/form'\n\nconst props = defineProps<{\n fieldName: string\n required?: boolean\n config?: Config<T>\n schema?: z.ZodArray<T>\n disabled?: boolean\n}>()\n\nconst fieldContext = useField(props.fieldName)\n\nfunction isZodArray(\n item: z.ZodArray<any> | z.ZodDefault<any>,\n): item is z.ZodArray<any> {\n return item instanceof z.ZodArray\n}\n\nfunction isZodDefault(\n item: z.ZodArray<any> | z.ZodDefault<any>,\n): item is z.ZodDefault<any> {\n return item instanceof z.ZodDefault\n}\n\nconst itemShape = computed(() => {\n if (!props.schema)\n return\n\n const schema: z.ZodAny = isZodArray(props.schema)\n ? props.schema._def.type\n : isZodDefault(props.schema)\n // @ts-expect-error missing schema\n ? props.schema._def.innerType._def.type\n : null\n\n return {\n type: getBaseType(schema),\n schema,\n }\n})\n\n// @ts-expect-error ignore missing `id`\nprovide(FieldContextKey, fieldContext)\n</script>\n\n<template>\n <FieldArray v-slot=\"{ fields, remove, push }\" as=\"section\" :name=\"fieldName\">\n <slot v-bind=\"props\">\n <Accordion type=\"multiple\" class=\"w-full\" collapsible :disabled=\"disabled\" as-child>\n <FormItem>\n <AccordionItem :value=\"fieldName\" class=\"border-none\">\n <AccordionTrigger>\n <AutoFormLabel class=\"text-base\" :required=\"required\">\n {{ schema?.description || beautifyObjectName(fieldName) }}\n </AutoFormLabel>\n </AccordionTrigger>\n\n <AccordionContent>\n <template v-for=\"(field, index) of fields\" :key=\"field.key\">\n <div class=\"mb-4 p-1\">\n <AutoFormField\n :field-name=\"`${fieldName}[${index}]`\"\n :label=\"fieldName\"\n :shape=\"itemShape!\"\n :config=\"config as ConfigItem\"\n />\n\n <div class=\"!my-4 flex justify-end\">\n <Button\n type=\"button\"\n size=\"icon\"\n variant=\"secondary\"\n @click=\"remove(index)\"\n >\n <TrashIcon :size=\"16\" />\n </Button>\n </div>\n <Separator v-if=\"!field.isLast\" />\n </div>\n </template>\n\n <Button\n type=\"button\"\n variant=\"secondary\"\n class=\"mt-4 flex items-center\"\n @click=\"push(null)\"\n >\n <PlusIcon class=\"mr-2\" :size=\"16\" />\n Add\n </Button>\n </AccordionContent>\n\n <FormMessage />\n </AccordionItem>\n </FormItem>\n </Accordion>\n </slot>\n </FieldArray>\n</template>\n"
|
"content": "<script setup lang=\"ts\" generic=\"T extends z.ZodAny\">\nimport * as z from 'zod'\nimport { computed, provide } from 'vue'\nimport { PlusIcon, TrashIcon } from 'lucide-vue-next'\nimport { FieldArray, FieldContextKey, useField } from 'vee-validate'\nimport type { Config, ConfigItem } from './interface'\nimport { beautifyObjectName, getBaseType } from './utils'\nimport AutoFormField from './AutoFormField.vue'\nimport AutoFormLabel from './AutoFormLabel.vue'\nimport { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@/lib/registry/default/ui/accordion'\nimport { Button } from '@/lib/registry/default/ui/button'\nimport { Separator } from '@/lib/registry/default/ui/separator'\nimport { FormItem, FormMessage } from '@/lib/registry/default/ui/form'\n\nconst props = defineProps<{\n fieldName: string\n required?: boolean\n config?: Config<T>\n schema?: z.ZodArray<T>\n disabled?: boolean\n}>()\n\nfunction isZodArray(\n item: z.ZodArray<any> | z.ZodDefault<any>,\n): item is z.ZodArray<any> {\n return item instanceof z.ZodArray\n}\n\nfunction isZodDefault(\n item: z.ZodArray<any> | z.ZodDefault<any>,\n): item is z.ZodDefault<any> {\n return item instanceof z.ZodDefault\n}\n\nconst itemShape = computed(() => {\n if (!props.schema)\n return\n\n const schema: z.ZodAny = isZodArray(props.schema)\n ? props.schema._def.type\n : isZodDefault(props.schema)\n // @ts-expect-error missing schema\n ? props.schema._def.innerType._def.type\n : null\n\n return {\n type: getBaseType(schema),\n schema,\n }\n})\n\nconst fieldContext = useField(props.fieldName)\n// @ts-expect-error ignore missing `id`\nprovide(FieldContextKey, fieldContext)\n</script>\n\n<template>\n <FieldArray v-slot=\"{ fields, remove, push }\" as=\"section\" :name=\"fieldName\">\n <slot v-bind=\"props\">\n <Accordion type=\"multiple\" class=\"w-full\" collapsible :disabled=\"disabled\" as-child>\n <FormItem>\n <AccordionItem :value=\"fieldName\" class=\"border-none\">\n <AccordionTrigger>\n <AutoFormLabel class=\"text-base\" :required=\"required\">\n {{ schema?.description || beautifyObjectName(fieldName) }}\n </AutoFormLabel>\n </AccordionTrigger>\n\n <AccordionContent>\n <template v-for=\"(field, index) of fields\" :key=\"field.key\">\n <div class=\"mb-4 p-1\">\n <AutoFormField\n :field-name=\"`${fieldName}[${index}]`\"\n :label=\"fieldName\"\n :shape=\"itemShape!\"\n :config=\"config as ConfigItem\"\n />\n\n <div class=\"!my-4 flex justify-end\">\n <Button\n type=\"button\"\n size=\"icon\"\n variant=\"secondary\"\n @click=\"remove(index)\"\n >\n <TrashIcon :size=\"16\" />\n </Button>\n </div>\n <Separator v-if=\"!field.isLast\" />\n </div>\n </template>\n\n <Button\n type=\"button\"\n variant=\"secondary\"\n class=\"mt-4 flex items-center\"\n @click=\"push(null)\"\n >\n <PlusIcon class=\"mr-2\" :size=\"16\" />\n Add\n </Button>\n </AccordionContent>\n\n <FormMessage />\n </AccordionItem>\n </FormItem>\n </Accordion>\n </slot>\n </FieldArray>\n</template>\n"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "AutoFormFieldBoolean.vue",
|
"name": "AutoFormFieldBoolean.vue",
|
||||||
|
|
@ -60,7 +60,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "AutoFormFieldObject.vue",
|
"name": "AutoFormFieldObject.vue",
|
||||||
"content": "<script setup lang=\"ts\" generic=\"T extends ZodRawShape\">\nimport type { ZodAny, ZodObject, ZodRawShape } from 'zod'\nimport { computed } from 'vue'\nimport AutoFormField from './AutoFormField.vue'\nimport type { Config, ConfigItem, Shape } from './interface'\nimport { beautifyObjectName, getBaseSchema, getBaseType, getDefaultValueInZodStack } from './utils'\nimport { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@/lib/registry/default/ui/accordion'\n\nconst props = defineProps<{\n fieldName: string\n required?: boolean\n config?: Config<T>\n schema?: ZodObject<T>\n disabled?: boolean\n}>()\n\nconst shapes = computed(() => {\n // @ts-expect-error ignore {} not assignable to object\n const val: { [key in keyof T]: Shape } = {}\n\n if (!props.schema)\n return\n const shape = getBaseSchema(props.schema)?.shape\n if (!shape)\n return\n Object.keys(shape).forEach((name) => {\n const item = shape[name] as ZodAny\n let options = 'values' in item._def ? item._def.values as string[] : undefined\n if (!Array.isArray(options) && typeof options === 'object')\n options = Object.values(options)\n\n val[name as keyof T] = {\n type: getBaseType(item),\n default: getDefaultValueInZodStack(item),\n options,\n required: !['ZodOptional', 'ZodNullable'].includes(item._def.typeName),\n schema: item,\n }\n })\n return val\n})\n</script>\n\n<template>\n <section>\n <slot v-bind=\"props\">\n <Accordion type=\"multiple\" class=\"w-full\" collapsible :disabled=\"disabled\">\n <AccordionItem :value=\"fieldName\" class=\"border-none\">\n <AccordionTrigger class=\"text-base\">\n {{ schema?.description || beautifyObjectName(fieldName) }}\n </AccordionTrigger>\n <AccordionContent class=\"p-1 space-y-5\">\n <template v-for=\"(shape, key) in shapes\" :key=\"key\">\n <AutoFormField\n :config=\"config?.[key as keyof typeof config] as ConfigItem\"\n :field-name=\"`${fieldName}.${key.toString()}`\"\n :label=\"key.toString()\"\n :shape=\"shape\"\n />\n </template>\n </AccordionContent>\n </AccordionItem>\n </Accordion>\n </slot>\n </section>\n</template>\n"
|
"content": "<script setup lang=\"ts\" generic=\"T extends ZodRawShape\">\nimport type { ZodAny, ZodObject, ZodRawShape } from 'zod'\nimport { computed, provide } from 'vue'\nimport { FieldContextKey, useField } from 'vee-validate'\nimport AutoFormField from './AutoFormField.vue'\nimport type { Config, ConfigItem, Shape } from './interface'\nimport { beautifyObjectName, getBaseSchema, getBaseType, getDefaultValueInZodStack } from './utils'\nimport AutoFormLabel from './AutoFormLabel.vue'\nimport { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@/lib/registry/default/ui/accordion'\nimport { FormItem } from '@/lib/registry/default/ui/form'\n\nconst props = defineProps<{\n fieldName: string\n required?: boolean\n config?: Config<T>\n schema?: ZodObject<T>\n disabled?: boolean\n}>()\n\nconst shapes = computed(() => {\n // @ts-expect-error ignore {} not assignable to object\n const val: { [key in keyof T]: Shape } = {}\n\n if (!props.schema)\n return\n const shape = getBaseSchema(props.schema)?.shape\n if (!shape)\n return\n Object.keys(shape).forEach((name) => {\n const item = shape[name] as ZodAny\n let options = 'values' in item._def ? item._def.values as string[] : undefined\n if (!Array.isArray(options) && typeof options === 'object')\n options = Object.values(options)\n\n val[name as keyof T] = {\n type: getBaseType(item),\n default: getDefaultValueInZodStack(item),\n options,\n required: !['ZodOptional', 'ZodNullable'].includes(item._def.typeName),\n schema: item,\n }\n })\n return val\n})\n\nconst fieldContext = useField(props.fieldName)\n// @ts-expect-error ignore missing `id`\nprovide(FieldContextKey, fieldContext)\n</script>\n\n<template>\n <section>\n <slot v-bind=\"props\">\n <Accordion type=\"single\" as-child class=\"w-full\" collapsible :disabled=\"disabled\">\n <FormItem>\n <AccordionItem :value=\"fieldName\" class=\"border-none\">\n <AccordionTrigger>\n <AutoFormLabel class=\"text-base\" :required=\"required\">\n {{ schema?.description || beautifyObjectName(fieldName) }}\n </AutoFormLabel>\n </AccordionTrigger>\n <AccordionContent class=\"p-1 space-y-5\">\n <template v-for=\"(shape, key) in shapes\" :key=\"key\">\n <AutoFormField\n :config=\"config?.[key as keyof typeof config] as ConfigItem\"\n :field-name=\"`${fieldName}.${key.toString()}`\"\n :label=\"key.toString()\"\n :shape=\"shape\"\n />\n </template>\n </AccordionContent>\n </AccordionItem>\n </FormItem>\n </Accordion>\n </slot>\n </section>\n</template>\n"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "AutoFormLabel.vue",
|
"name": "AutoFormLabel.vue",
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "AutoFormFieldArray.vue",
|
"name": "AutoFormFieldArray.vue",
|
||||||
"content": "<script setup lang=\"ts\" generic=\"T extends z.ZodAny\">\nimport * as z from 'zod'\nimport { computed, provide } from 'vue'\nimport { PlusIcon, TrashIcon } from 'lucide-vue-next'\nimport { FieldArray, FieldContextKey, useField } from 'vee-validate'\nimport type { Config, ConfigItem } from './interface'\nimport { beautifyObjectName, getBaseType } from './utils'\nimport AutoFormField from './AutoFormField.vue'\nimport AutoFormLabel from './AutoFormLabel.vue'\nimport { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@/lib/registry/new-york/ui/accordion'\nimport { Button } from '@/lib/registry/new-york/ui/button'\nimport { Separator } from '@/lib/registry/new-york/ui/separator'\nimport { FormItem, FormMessage } from '@/lib/registry/new-york/ui/form'\n\nconst props = defineProps<{\n fieldName: string\n required?: boolean\n config?: Config<T>\n schema?: z.ZodArray<T>\n disabled?: boolean\n}>()\n\nconst fieldContext = useField(props.fieldName)\n\nfunction isZodArray(\n item: z.ZodArray<any> | z.ZodDefault<any>,\n): item is z.ZodArray<any> {\n return item instanceof z.ZodArray\n}\n\nfunction isZodDefault(\n item: z.ZodArray<any> | z.ZodDefault<any>,\n): item is z.ZodDefault<any> {\n return item instanceof z.ZodDefault\n}\n\nconst itemShape = computed(() => {\n if (!props.schema)\n return\n\n const schema: z.ZodAny = isZodArray(props.schema)\n ? props.schema._def.type\n : isZodDefault(props.schema)\n // @ts-expect-error missing schema\n ? props.schema._def.innerType._def.type\n : null\n\n return {\n type: getBaseType(schema),\n schema,\n }\n})\n\n// @ts-expect-error ignore missing `id`\nprovide(FieldContextKey, fieldContext)\n</script>\n\n<template>\n <FieldArray v-slot=\"{ fields, remove, push }\" as=\"section\" :name=\"fieldName\">\n <slot v-bind=\"props\">\n <Accordion type=\"multiple\" class=\"w-full\" collapsible :disabled=\"disabled\" as-child>\n <FormItem>\n <AccordionItem :value=\"fieldName\" class=\"border-none\">\n <AccordionTrigger>\n <AutoFormLabel class=\"text-base\" :required=\"required\">\n {{ schema?.description || beautifyObjectName(fieldName) }}\n </AutoFormLabel>\n </AccordionTrigger>\n\n <AccordionContent>\n <template v-for=\"(field, index) of fields\" :key=\"field.key\">\n <div class=\"mb-4 p-1\">\n <AutoFormField\n :field-name=\"`${fieldName}[${index}]`\"\n :label=\"fieldName\"\n :shape=\"itemShape!\"\n :config=\"config as ConfigItem\"\n />\n\n <div class=\"!my-4 flex justify-end\">\n <Button\n type=\"button\"\n size=\"icon\"\n variant=\"secondary\"\n @click=\"remove(index)\"\n >\n <TrashIcon :size=\"16\" />\n </Button>\n </div>\n <Separator v-if=\"!field.isLast\" />\n </div>\n </template>\n\n <Button\n type=\"button\"\n variant=\"secondary\"\n class=\"mt-4 flex items-center\"\n @click=\"push(null)\"\n >\n <PlusIcon class=\"mr-2\" :size=\"16\" />\n Add\n </Button>\n </AccordionContent>\n\n <FormMessage />\n </AccordionItem>\n </FormItem>\n </Accordion>\n </slot>\n </FieldArray>\n</template>\n"
|
"content": "<script setup lang=\"ts\" generic=\"T extends z.ZodAny\">\nimport * as z from 'zod'\nimport { computed, provide } from 'vue'\nimport { PlusIcon, TrashIcon } from 'lucide-vue-next'\nimport { FieldArray, FieldContextKey, useField } from 'vee-validate'\nimport type { Config, ConfigItem } from './interface'\nimport { beautifyObjectName, getBaseType } from './utils'\nimport AutoFormField from './AutoFormField.vue'\nimport AutoFormLabel from './AutoFormLabel.vue'\nimport { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@/lib/registry/new-york/ui/accordion'\nimport { Button } from '@/lib/registry/new-york/ui/button'\nimport { Separator } from '@/lib/registry/new-york/ui/separator'\nimport { FormItem, FormMessage } from '@/lib/registry/new-york/ui/form'\n\nconst props = defineProps<{\n fieldName: string\n required?: boolean\n config?: Config<T>\n schema?: z.ZodArray<T>\n disabled?: boolean\n}>()\n\nfunction isZodArray(\n item: z.ZodArray<any> | z.ZodDefault<any>,\n): item is z.ZodArray<any> {\n return item instanceof z.ZodArray\n}\n\nfunction isZodDefault(\n item: z.ZodArray<any> | z.ZodDefault<any>,\n): item is z.ZodDefault<any> {\n return item instanceof z.ZodDefault\n}\n\nconst itemShape = computed(() => {\n if (!props.schema)\n return\n\n const schema: z.ZodAny = isZodArray(props.schema)\n ? props.schema._def.type\n : isZodDefault(props.schema)\n // @ts-expect-error missing schema\n ? props.schema._def.innerType._def.type\n : null\n\n return {\n type: getBaseType(schema),\n schema,\n }\n})\n\nconst fieldContext = useField(props.fieldName)\n// @ts-expect-error ignore missing `id`\nprovide(FieldContextKey, fieldContext)\n</script>\n\n<template>\n <FieldArray v-slot=\"{ fields, remove, push }\" as=\"section\" :name=\"fieldName\">\n <slot v-bind=\"props\">\n <Accordion type=\"multiple\" class=\"w-full\" collapsible :disabled=\"disabled\" as-child>\n <FormItem>\n <AccordionItem :value=\"fieldName\" class=\"border-none\">\n <AccordionTrigger>\n <AutoFormLabel class=\"text-base\" :required=\"required\">\n {{ schema?.description || beautifyObjectName(fieldName) }}\n </AutoFormLabel>\n </AccordionTrigger>\n\n <AccordionContent>\n <template v-for=\"(field, index) of fields\" :key=\"field.key\">\n <div class=\"mb-4 p-1\">\n <AutoFormField\n :field-name=\"`${fieldName}[${index}]`\"\n :label=\"fieldName\"\n :shape=\"itemShape!\"\n :config=\"config as ConfigItem\"\n />\n\n <div class=\"!my-4 flex justify-end\">\n <Button\n type=\"button\"\n size=\"icon\"\n variant=\"secondary\"\n @click=\"remove(index)\"\n >\n <TrashIcon :size=\"16\" />\n </Button>\n </div>\n <Separator v-if=\"!field.isLast\" />\n </div>\n </template>\n\n <Button\n type=\"button\"\n variant=\"secondary\"\n class=\"mt-4 flex items-center\"\n @click=\"push(null)\"\n >\n <PlusIcon class=\"mr-2\" :size=\"16\" />\n Add\n </Button>\n </AccordionContent>\n\n <FormMessage />\n </AccordionItem>\n </FormItem>\n </Accordion>\n </slot>\n </FieldArray>\n</template>\n"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "AutoFormFieldBoolean.vue",
|
"name": "AutoFormFieldBoolean.vue",
|
||||||
|
|
@ -60,7 +60,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "AutoFormFieldObject.vue",
|
"name": "AutoFormFieldObject.vue",
|
||||||
"content": "<script setup lang=\"ts\" generic=\"T extends ZodRawShape\">\nimport type { ZodAny, ZodObject, ZodRawShape } from 'zod'\nimport { computed } from 'vue'\nimport AutoFormField from './AutoFormField.vue'\nimport type { Config, ConfigItem, Shape } from './interface'\nimport { beautifyObjectName, getBaseSchema, getBaseType, getDefaultValueInZodStack } from './utils'\nimport { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@/lib/registry/new-york/ui/accordion'\n\nconst props = defineProps<{\n fieldName: string\n required?: boolean\n config?: Config<T>\n schema?: ZodObject<T>\n disabled?: boolean\n}>()\n\nconst shapes = computed(() => {\n // @ts-expect-error ignore {} not assignable to object\n const val: { [key in keyof T]: Shape } = {}\n\n if (!props.schema)\n return\n const shape = getBaseSchema(props.schema)?.shape\n if (!shape)\n return\n Object.keys(shape).forEach((name) => {\n const item = shape[name] as ZodAny\n let options = 'values' in item._def ? item._def.values as string[] : undefined\n if (!Array.isArray(options) && typeof options === 'object')\n options = Object.values(options)\n\n val[name as keyof T] = {\n type: getBaseType(item),\n default: getDefaultValueInZodStack(item),\n options,\n required: !['ZodOptional', 'ZodNullable'].includes(item._def.typeName),\n schema: item,\n }\n })\n return val\n})\n</script>\n\n<template>\n <section>\n <slot v-bind=\"props\">\n <Accordion type=\"multiple\" class=\"w-full\" collapsible :disabled=\"disabled\">\n <AccordionItem :value=\"fieldName\" class=\"border-none\">\n <AccordionTrigger class=\"text-base\">\n {{ schema?.description || beautifyObjectName(fieldName) }}\n </AccordionTrigger>\n <AccordionContent class=\"p-[1px] space-y-5\">\n <template v-for=\"(shape, key) in shapes\" :key=\"key\">\n <AutoFormField\n :config=\"config?.[key as keyof typeof config] as ConfigItem\"\n :field-name=\"`${fieldName}.${key.toString()}`\"\n :label=\"key.toString()\"\n :shape=\"shape\"\n />\n </template>\n </AccordionContent>\n </AccordionItem>\n </Accordion>\n </slot>\n </section>\n</template>\n"
|
"content": "<script setup lang=\"ts\" generic=\"T extends ZodRawShape\">\nimport type { ZodAny, ZodObject, ZodRawShape } from 'zod'\nimport { computed, provide } from 'vue'\nimport { FieldContextKey, useField } from 'vee-validate'\nimport AutoFormField from './AutoFormField.vue'\nimport type { Config, ConfigItem, Shape } from './interface'\nimport { beautifyObjectName, getBaseSchema, getBaseType, getDefaultValueInZodStack } from './utils'\nimport AutoFormLabel from './AutoFormLabel.vue'\nimport { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@/lib/registry/new-york/ui/accordion'\nimport { FormItem } from '@/lib/registry/new-york/ui/form'\n\nconst props = defineProps<{\n fieldName: string\n required?: boolean\n config?: Config<T>\n schema?: ZodObject<T>\n disabled?: boolean\n}>()\n\nconst shapes = computed(() => {\n // @ts-expect-error ignore {} not assignable to object\n const val: { [key in keyof T]: Shape } = {}\n\n if (!props.schema)\n return\n const shape = getBaseSchema(props.schema)?.shape\n if (!shape)\n return\n Object.keys(shape).forEach((name) => {\n const item = shape[name] as ZodAny\n let options = 'values' in item._def ? item._def.values as string[] : undefined\n if (!Array.isArray(options) && typeof options === 'object')\n options = Object.values(options)\n\n val[name as keyof T] = {\n type: getBaseType(item),\n default: getDefaultValueInZodStack(item),\n options,\n required: !['ZodOptional', 'ZodNullable'].includes(item._def.typeName),\n schema: item,\n }\n })\n return val\n})\n\nconst fieldContext = useField(props.fieldName)\n// @ts-expect-error ignore missing `id`\nprovide(FieldContextKey, fieldContext)\n</script>\n\n<template>\n <section>\n <slot v-bind=\"props\">\n <Accordion type=\"single\" as-child class=\"w-full\" collapsible :disabled=\"disabled\">\n <FormItem>\n <AccordionItem :value=\"fieldName\" class=\"border-none\">\n <AccordionTrigger>\n <AutoFormLabel class=\"text-base\" :required=\"required\">\n {{ schema?.description || beautifyObjectName(fieldName) }}\n </AutoFormLabel>\n </AccordionTrigger>\n <AccordionContent class=\"p-1 space-y-5\">\n <template v-for=\"(shape, key) in shapes\" :key=\"key\">\n <AutoFormField\n :config=\"config?.[key as keyof typeof config] as ConfigItem\"\n :field-name=\"`${fieldName}.${key.toString()}`\"\n :label=\"key.toString()\"\n :shape=\"shape\"\n />\n </template>\n </AccordionContent>\n </AccordionItem>\n </FormItem>\n </Accordion>\n </slot>\n </section>\n</template>\n"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "AutoFormLabel.vue",
|
"name": "AutoFormLabel.vue",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user