feat: improve array
This commit is contained in:
parent
1120f044e2
commit
1c562463b2
|
|
@ -18,23 +18,18 @@ const schema = z.object({
|
||||||
}),
|
}),
|
||||||
).default([
|
).default([
|
||||||
{ name: '123', age: 30 },
|
{ name: '123', age: 30 },
|
||||||
|
{ name: '456', age: 30 },
|
||||||
]).describe('How many guests'),
|
]).describe('How many guests'),
|
||||||
|
|
||||||
list: z.array(z.string()).describe('test the config'),
|
list: z.array(z.string()).describe('test the config').min(1, 'Please add some item').default([]),
|
||||||
})
|
})
|
||||||
|
|
||||||
const formSchema = toTypedSchema(schema)
|
function onSubmit(values: Record<string, any>) {
|
||||||
|
|
||||||
const { handleSubmit } = useForm({
|
|
||||||
validationSchema: formSchema,
|
|
||||||
})
|
|
||||||
|
|
||||||
const onSubmit = handleSubmit((values) => {
|
|
||||||
toast({
|
toast({
|
||||||
title: 'You submitted the following values:',
|
title: 'You submitted the following values:',
|
||||||
description: h('pre', { class: 'mt-2 w-[340px] rounded-md bg-slate-950 p-4' }, h('code', { class: 'text-white' }, JSON.stringify(values, null, 2))),
|
description: h('pre', { class: 'mt-2 w-[340px] rounded-md bg-slate-950 p-4' }, h('code', { class: 'text-white' }, JSON.stringify(values, null, 2))),
|
||||||
})
|
})
|
||||||
})
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
<script setup lang="ts" generic="U extends ZodRawShape, T extends ZodObject<U>">
|
<script setup lang="ts" generic="U extends ZodRawShape, T extends ZodObject<U>">
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import type { ZodAny, ZodObject, ZodRawShape, z } from 'zod'
|
import type { ZodAny, ZodObject, ZodRawShape, z } from 'zod'
|
||||||
|
import { toTypedSchema } from '@vee-validate/zod'
|
||||||
|
import type { GenericObject } from 'vee-validate'
|
||||||
import { getBaseType, getDefaultValueInZodStack } from './utils'
|
import { getBaseType, getDefaultValueInZodStack } from './utils'
|
||||||
import type { Config, ConfigItem, Shape } from './interface'
|
import type { Config, ConfigItem, Shape } from './interface'
|
||||||
import AutoFormField from './AutoFormField.vue'
|
import AutoFormField from './AutoFormField.vue'
|
||||||
import { Accordion } from '@/lib/registry/new-york/ui/accordion'
|
import { Form } from '@/lib/registry/new-york/ui/form'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
schema: T
|
schema: T
|
||||||
|
|
@ -12,7 +14,7 @@ const props = defineProps<{
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const emits = defineEmits<{
|
const emits = defineEmits<{
|
||||||
submit: [event: Event]
|
submit: [event: GenericObject]
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const shapes = computed(() => {
|
const shapes = computed(() => {
|
||||||
|
|
@ -35,10 +37,16 @@ const shapes = computed(() => {
|
||||||
})
|
})
|
||||||
return val
|
return val
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const formSchema = computed(() => toTypedSchema(props.schema))
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<form @submit="emits('submit', $event)">
|
<Form
|
||||||
|
:keep-values="true"
|
||||||
|
:validation-schema="formSchema"
|
||||||
|
@submit="emits('submit', $event)"
|
||||||
|
>
|
||||||
<template v-for="(shape, key) of shapes" :key="key">
|
<template v-for="(shape, key) of shapes" :key="key">
|
||||||
<slot
|
<slot
|
||||||
:shape="shape"
|
:shape="shape"
|
||||||
|
|
@ -54,5 +62,5 @@ const shapes = computed(() => {
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<slot :shapes="shapes" />
|
<slot :shapes="shapes" />
|
||||||
</form>
|
</Form>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,16 @@
|
||||||
<script setup lang="ts" generic="T extends z.ZodAny">
|
<script setup lang="ts" generic="T extends z.ZodAny">
|
||||||
import * as z from 'zod'
|
import * as z from 'zod'
|
||||||
import { computed } from 'vue'
|
import { computed, provide } from 'vue'
|
||||||
import { PlusIcon, TrashIcon } from '@radix-icons/vue'
|
import { PlusIcon, TrashIcon } from '@radix-icons/vue'
|
||||||
import { useFieldArray } from 'vee-validate'
|
import { FieldArray, FieldContextKey, useField, useFieldArray } from 'vee-validate'
|
||||||
import type { Config, ConfigItem } from '../interface'
|
import type { Config, ConfigItem } from '../interface'
|
||||||
import { beautifyObjectName, getBaseType } from '../utils'
|
import { beautifyObjectName, getBaseType } from '../utils'
|
||||||
import AutoFormField from '../AutoFormField.vue'
|
import AutoFormField from '../AutoFormField.vue'
|
||||||
|
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 { Button } from '@/lib/registry/new-york/ui/button'
|
import { Button } from '@/lib/registry/new-york/ui/button'
|
||||||
import { Separator } from '@/lib/registry/new-york/ui/separator'
|
import { Separator } from '@/lib/registry/new-york/ui/separator'
|
||||||
|
import { FormMessage } from '@/lib/registry/new-york/ui/form'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
name: string
|
name: string
|
||||||
|
|
@ -17,7 +19,7 @@ const props = defineProps<{
|
||||||
schema?: z.ZodArray<T>
|
schema?: z.ZodArray<T>
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const { remove, push, fields } = useFieldArray(props.name)
|
const fieldContext = useField(props.name)
|
||||||
|
|
||||||
function isZodArray(
|
function isZodArray(
|
||||||
item: z.ZodArray<any> | z.ZodDefault<any>,
|
item: z.ZodArray<any> | z.ZodDefault<any>,
|
||||||
|
|
@ -47,19 +49,25 @@ const itemShape = computed(() => {
|
||||||
schema,
|
schema,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// @ts-expect-error ignore missing `id`
|
||||||
|
provide(FieldContextKey, fieldContext)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<section>
|
<FieldArray v-slot="{ fields, remove, push }" as="section" :name="name">
|
||||||
<slot v-bind="props">
|
<slot v-bind="props">
|
||||||
<Accordion type="multiple" class="w-full" collapsible>
|
<Accordion type="multiple" class="w-full" collapsible>
|
||||||
<AccordionItem :value="name" class="border-none">
|
<AccordionItem :value="name" class="border-none">
|
||||||
<AccordionTrigger class="text-base">
|
<AccordionTrigger>
|
||||||
|
<AutoFormLabel class="text-base" :required="required">
|
||||||
{{ schema?.description || beautifyObjectName(name) }}
|
{{ schema?.description || beautifyObjectName(name) }}
|
||||||
|
</AutoFormLabel>
|
||||||
</AccordionTrigger>
|
</AccordionTrigger>
|
||||||
{{ fields }}
|
|
||||||
<AccordionContent class="p-2 space-y-5">
|
<AccordionContent>
|
||||||
<template v-for="(field, index) of fields" :key="field.key">
|
<template v-for="(field, index) of fields" :key="field.key">
|
||||||
|
<div class="mb-4 p-[1px]">
|
||||||
<AutoFormField
|
<AutoFormField
|
||||||
:name="`${name}[${index}]`"
|
:name="`${name}[${index}]`"
|
||||||
:label="name"
|
:label="name"
|
||||||
|
|
@ -67,7 +75,7 @@ const itemShape = computed(() => {
|
||||||
:config="config as ConfigItem"
|
:config="config as ConfigItem"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="!mt-2 flex justify-end">
|
<div class="!my-4 flex justify-end">
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
size="icon"
|
size="icon"
|
||||||
|
|
@ -77,7 +85,8 @@ const itemShape = computed(() => {
|
||||||
<TrashIcon />
|
<TrashIcon />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<Separator />
|
<Separator v-if="!field.isLast" />
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
|
|
@ -90,8 +99,10 @@ const itemShape = computed(() => {
|
||||||
Add
|
Add
|
||||||
</Button>
|
</Button>
|
||||||
</AccordionContent>
|
</AccordionContent>
|
||||||
|
|
||||||
|
<FormMessage />
|
||||||
</AccordionItem>
|
</AccordionItem>
|
||||||
</Accordion>
|
</Accordion>
|
||||||
</slot>
|
</slot>
|
||||||
</section>
|
</FieldArray>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ const shapes = computed(() => {
|
||||||
<AccordionTrigger class="text-base">
|
<AccordionTrigger class="text-base">
|
||||||
{{ schema?.description || beautifyObjectName(name) }}
|
{{ schema?.description || beautifyObjectName(name) }}
|
||||||
</AccordionTrigger>
|
</AccordionTrigger>
|
||||||
<AccordionContent class="p-2 space-y-5">
|
<AccordionContent class="p-[1px] space-y-5">
|
||||||
<template v-for="(shape, key) in shapes" :key="key">
|
<template v-for="(shape, key) in shapes" :key="key">
|
||||||
<AutoFormField
|
<AutoFormField
|
||||||
:config="config?.[key as keyof typeof config] as ConfigItem"
|
:config="config?.[key as keyof typeof config] as ConfigItem"
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
export { Form, Field as FormField } from 'vee-validate'
|
export { Form, Field as FormField, FieldArray as FormFieldArray } from 'vee-validate'
|
||||||
export { default as FormItem } from './FormItem.vue'
|
export { default as FormItem } from './FormItem.vue'
|
||||||
export { default as FormLabel } from './FormLabel.vue'
|
export { default as FormLabel } from './FormLabel.vue'
|
||||||
export { default as FormControl } from './FormControl.vue'
|
export { default as FormControl } from './FormControl.vue'
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ import { FORM_ITEM_INJECTION_KEY } from './FormItem.vue'
|
||||||
export function useFormField() {
|
export function useFormField() {
|
||||||
const fieldContext = inject(FieldContextKey)
|
const fieldContext = inject(FieldContextKey)
|
||||||
const fieldItemContext = inject(FORM_ITEM_INJECTION_KEY)
|
const fieldItemContext = inject(FORM_ITEM_INJECTION_KEY)
|
||||||
|
|
||||||
const fieldState = {
|
const fieldState = {
|
||||||
valid: useIsFieldValid(),
|
valid: useIsFieldValid(),
|
||||||
isDirty: useIsFieldDirty(),
|
isDirty: useIsFieldDirty(),
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user