feat: add file component

This commit is contained in:
zernonia 2024-04-17 14:21:15 +08:00
parent ed054e0736
commit 9f37b12c21
5 changed files with 62 additions and 4 deletions

View File

@ -153,6 +153,9 @@ const onSubmit = handleSubmit((values) => {
bio: { bio: {
component: 'textarea', component: 'textarea',
}, },
file: {
component: 'file',
},
subObject: { subObject: {

View File

@ -57,7 +57,7 @@ const shapes = computed(() => {
/> />
</slot> </slot>
{{ shape.schema }} <!-- {{ shape.schema }} -->
</template> </template>
<slot :shapes="shapes" /> <slot :shapes="shapes" />

View File

@ -18,7 +18,7 @@ defineProps<{
<template> <template>
<component <component
:is="INPUT_COMPONENTS[DEFAULT_ZOD_HANDLERS[shape.type]] " :is="INPUT_COMPONENTS[config?.component ?? DEFAULT_ZOD_HANDLERS[shape.type]] "
:name="name" :name="name"
:required="shape.required" :required="shape.required"
:options="shape.options" :options="shape.options"

View File

@ -1,8 +1,9 @@
import FieldNumber from './fields/Number.vue'
import FieldInput from './fields/Input.vue'
import FieldBoolean from './fields/Boolean.vue' import FieldBoolean from './fields/Boolean.vue'
import FieldDate from './fields/Date.vue' import FieldDate from './fields/Date.vue'
import FieldEnum from './fields/Enum.vue' import FieldEnum from './fields/Enum.vue'
import FieldFile from './fields/File.vue'
import FieldInput from './fields/Input.vue'
import FieldNumber from './fields/Number.vue'
export const INPUT_COMPONENTS = { export const INPUT_COMPONENTS = {
date: FieldDate, date: FieldDate,
@ -13,6 +14,7 @@ export const INPUT_COMPONENTS = {
textarea: FieldInput, textarea: FieldInput,
number: FieldNumber, number: FieldNumber,
string: FieldInput, string: FieldInput,
file: FieldFile,
} }
/** /**

View File

@ -0,0 +1,53 @@
<script setup lang="ts">
import { beautifyObjectName } from '../utils'
import type { Config } from '../interface'
import AutoFormLabel from '../AutoFormLabel.vue'
import { FormControl, FormDescription, FormField, FormItem, FormMessage } from '@/lib/registry/new-york/ui/form'
import { Input } from '@/lib/registry/new-york/ui/input'
defineProps<{
name: string
required?: boolean
config?: Config
}>()
async function parseFileAsString(file: File | undefined): Promise<string> {
return new Promise((resolve, reject) => {
if (file) {
const reader = new FileReader()
reader.onloadend = () => {
resolve(reader.result as string)
}
reader.onerror = (err) => {
reject(err)
}
reader.readAsDataURL(file)
}
})
}
</script>
<template>
<FormField v-slot="{ componentField }" :name="name">
<FormItem v-bind="$attrs">
<AutoFormLabel :required="required">
{{ config?.label || beautifyObjectName(name) }}
</AutoFormLabel>
<FormControl>
<Input
type="file"
v-bind="{ ...config?.inputProps }"
@change="async (ev: InputEvent) => {
const file = (ev.target as HTMLInputElement).files?.[0]
const parsed = await parseFileAsString(file)
componentField.onInput(parsed)
}"
/>
</FormControl>
<FormDescription v-if="config?.description">
{{ config.description }}
</FormDescription>
<FormMessage />
</FormItem>
</FormField>
</template>