feat: add file component
This commit is contained in:
parent
ed054e0736
commit
9f37b12c21
|
|
@ -153,6 +153,9 @@ const onSubmit = handleSubmit((values) => {
|
|||
bio: {
|
||||
component: 'textarea',
|
||||
},
|
||||
file: {
|
||||
component: 'file',
|
||||
},
|
||||
|
||||
subObject: {
|
||||
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ const shapes = computed(() => {
|
|||
/>
|
||||
</slot>
|
||||
|
||||
{{ shape.schema }}
|
||||
<!-- {{ shape.schema }} -->
|
||||
</template>
|
||||
|
||||
<slot :shapes="shapes" />
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ defineProps<{
|
|||
|
||||
<template>
|
||||
<component
|
||||
:is="INPUT_COMPONENTS[DEFAULT_ZOD_HANDLERS[shape.type]] "
|
||||
:is="INPUT_COMPONENTS[config?.component ?? DEFAULT_ZOD_HANDLERS[shape.type]] "
|
||||
:name="name"
|
||||
:required="shape.required"
|
||||
:options="shape.options"
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
import FieldNumber from './fields/Number.vue'
|
||||
import FieldInput from './fields/Input.vue'
|
||||
import FieldBoolean from './fields/Boolean.vue'
|
||||
import FieldDate from './fields/Date.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 = {
|
||||
date: FieldDate,
|
||||
|
|
@ -13,6 +14,7 @@ export const INPUT_COMPONENTS = {
|
|||
textarea: FieldInput,
|
||||
number: FieldNumber,
|
||||
string: FieldInput,
|
||||
file: FieldFile,
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
Loading…
Reference in New Issue
Block a user