@finema/core 1.4.201 → 1.4.203

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/README.md +60 -60
  2. package/dist/module.d.mts +1 -0
  3. package/dist/module.d.ts +1 -0
  4. package/dist/module.json +1 -1
  5. package/dist/module.mjs +2 -1
  6. package/dist/runtime/components/Alert.vue +48 -48
  7. package/dist/runtime/components/Avatar.vue +27 -27
  8. package/dist/runtime/components/Badge.vue +11 -11
  9. package/dist/runtime/components/Breadcrumb.vue +44 -44
  10. package/dist/runtime/components/Button/Group.vue +37 -37
  11. package/dist/runtime/components/Button/index.vue +75 -75
  12. package/dist/runtime/components/Card.vue +38 -38
  13. package/dist/runtime/components/Core.vue +45 -45
  14. package/dist/runtime/components/Dialog/index.vue +108 -108
  15. package/dist/runtime/components/Dropdown/index.vue +70 -70
  16. package/dist/runtime/components/FlexDeck/Base.vue +152 -152
  17. package/dist/runtime/components/FlexDeck/index.vue +68 -68
  18. package/dist/runtime/components/Form/FieldWrapper.vue +23 -23
  19. package/dist/runtime/components/Form/Fields.vue +230 -230
  20. package/dist/runtime/components/Form/InputCheckbox/index.vue +28 -28
  21. package/dist/runtime/components/Form/InputDateTime/index.vue +61 -61
  22. package/dist/runtime/components/Form/InputDateTimeRange/index.vue +83 -83
  23. package/dist/runtime/components/Form/InputNumber/index.vue +27 -27
  24. package/dist/runtime/components/Form/InputRadio/index.vue +27 -27
  25. package/dist/runtime/components/Form/InputSelect/index.vue +45 -45
  26. package/dist/runtime/components/Form/InputSelectMultiple/index.vue +54 -54
  27. package/dist/runtime/components/Form/InputStatic/index.vue +16 -16
  28. package/dist/runtime/components/Form/InputTags/index.vue +141 -141
  29. package/dist/runtime/components/Form/InputText/index.vue +68 -68
  30. package/dist/runtime/components/Form/InputTextarea/index.vue +25 -25
  31. package/dist/runtime/components/Form/InputToggle/index.vue +27 -27
  32. package/dist/runtime/components/Form/InputUploadDropzone/index.vue +206 -206
  33. package/dist/runtime/components/Form/InputUploadDropzoneAuto/index.vue +342 -342
  34. package/dist/runtime/components/Form/InputUploadDropzoneAutoMultiple/ItemUpload.vue +241 -241
  35. package/dist/runtime/components/Form/InputUploadDropzoneAutoMultiple/ItemView.vue +89 -89
  36. package/dist/runtime/components/Form/InputUploadDropzoneAutoMultiple/index.vue +170 -170
  37. package/dist/runtime/components/Form/InputUploadDropzoneImageAutoMultiple/ItemUpload.vue +161 -161
  38. package/dist/runtime/components/Form/InputUploadDropzoneImageAutoMultiple/ItemView.vue +64 -64
  39. package/dist/runtime/components/Form/InputUploadDropzoneImageAutoMultiple/index.vue +178 -178
  40. package/dist/runtime/components/Form/InputUploadFileClassic/index.vue +95 -95
  41. package/dist/runtime/components/Form/InputUploadFileClassicAuto/index.vue +151 -151
  42. package/dist/runtime/components/Form/InputUploadImageAuto/index.vue +219 -219
  43. package/dist/runtime/components/Form/InputWYSIWYG/UploadImageForm.vue +55 -55
  44. package/dist/runtime/components/Form/InputWYSIWYG/index.vue +228 -228
  45. package/dist/runtime/components/Form/index.vue +6 -6
  46. package/dist/runtime/components/Icon.vue +23 -23
  47. package/dist/runtime/components/Image.vue +36 -36
  48. package/dist/runtime/components/Loader.vue +27 -27
  49. package/dist/runtime/components/Modal/index.vue +146 -146
  50. package/dist/runtime/components/QRCode.vue +22 -22
  51. package/dist/runtime/components/SimplePagination.vue +96 -96
  52. package/dist/runtime/components/Slideover/index.vue +110 -110
  53. package/dist/runtime/components/Table/Base.vue +153 -153
  54. package/dist/runtime/components/Table/ColumnDate.vue +16 -16
  55. package/dist/runtime/components/Table/ColumnDateTime.vue +18 -18
  56. package/dist/runtime/components/Table/ColumnImage.vue +15 -15
  57. package/dist/runtime/components/Table/ColumnNumber.vue +14 -14
  58. package/dist/runtime/components/Table/ColumnText.vue +29 -29
  59. package/dist/runtime/components/Table/Simple.vue +69 -69
  60. package/dist/runtime/components/Table/index.vue +65 -65
  61. package/dist/runtime/components/Tabs/index.vue +64 -64
  62. package/dist/runtime/components/TeleportSafe.vue +40 -40
  63. package/dist/runtime/core.config.d.ts +1 -0
  64. package/dist/runtime/core.config.mjs +2 -1
  65. package/dist/runtime/ui.config/notifications.d.ts +3 -0
  66. package/dist/runtime/ui.config/notifications.mjs +3 -0
  67. package/dist/runtime/utils/TimeHelper.mjs +15 -10
  68. package/dist/runtime/utils/TimeHelper.spec.mjs +11 -4
  69. package/dist/runtime/utils/TimeHelper.thai.spec.mjs +2 -1
  70. package/package.json +102 -101
  71. package/dist/runtime/components/Form/InputDateTime/index.vue~ +0 -61
  72. package/dist/runtime/ui.config/table.ts~ +0 -48
@@ -1,219 +1,219 @@
1
- <template>
2
- <FieldWrapper v-bind="wrapperProps">
3
- <div :class="[ui.base]">
4
- <input
5
- ref="fileInputRef"
6
- type="file"
7
- class="hidden"
8
- :name="name"
9
- :accept="acceptFile"
10
- :disabled="isDisabled"
11
- @change="handleChange"
12
- />
13
-
14
- <div :class="[ui.imageItem.wrapper]">
15
- <div v-if="!selectedFile && !value" class="w-full">
16
- <div :class="[ui.action.addingWrapper]" @click="handleOpenFile">
17
- <Icon :name="ui.action.addingIcon" :class="[ui.action.addingBtnClass]" />
18
- <p :class="[ui.action.addingTextClass]">{{ uploadAddLabel }}</p>
19
- </div>
20
- </div>
21
-
22
- <!-- Loading State -->
23
- <div v-if="selectedFile && upload.status.value.isLoading" class="w-full">
24
- <div :class="[ui.imageItem.onLoading.wrapper]">
25
- <div :class="[ui.imageItem.onLoading.percentClass]">{{ percent }}%</div>
26
- <UProgress :value="percent" />
27
- </div>
28
- </div>
29
-
30
- <!-- Success State -->
31
- <div v-if="(selectedFile && upload.status.value.isSuccess) || value" class="w-full">
32
- <div :class="[ui.imageItem.onPreview.wrapper]">
33
- <img :class="[ui.imageItem.onPreview.previewImgClass]" :src="value?.url" alt="img" />
34
- <div :class="[ui.imageItem.onPreview.previewActionWrapper]">
35
- <Icon
36
- title="ดูตัวอย่าง"
37
- :name="ui.action.previewIcon"
38
- :class="[ui.imageItem.onPreview.actionBtnClass]"
39
- @click="() => (isPreviewOpen = true)"
40
- />
41
- <Icon
42
- title="ลบไฟล์"
43
- :name="ui.action.deleteIcon"
44
- :class="[ui.imageItem.onPreview.actionBtnClass]"
45
- @click="handleDeleteFile"
46
- />
47
- <Modal v-model="isPreviewOpen" size="xl">
48
- <div class="absolute -top-8 left-0 flex w-full justify-between text-gray-600">
49
- <p>{{ selectedFile?.name }}</p>
50
- <Icon
51
- name="i-heroicons-x-mark"
52
- class="size-6 cursor-pointer hover:text-gray-400"
53
- @click="() => (isPreviewOpen = false)"
54
- />
55
- </div>
56
- <img :src="value?.url" alt="img-preview" class="w-full rounded-lg" />
57
- </Modal>
58
- </div>
59
- </div>
60
-
61
- <div v-if="selectedFile" :class="[ui.imageItem.onPreview.previewTextWrapper]">
62
- <p :class="[ui.imageItem.onPreview.previewText]">{{ selectedFile.name }}</p>
63
- </div>
64
- </div>
65
-
66
- <!-- Failed State -->
67
- <div v-if="selectedFile && upload.status.value.isError" class="w-full">
68
- <div :class="[ui.imageItem.onFailed.wrapper]">
69
- <img
70
- :class="[ui.imageItem.onFailed.failedImgClass]"
71
- :src="generateURL(selectedFile)"
72
- alt="img"
73
- />
74
- <div :class="[ui.imageItem.onFailed.failedActionWrapper]">
75
- <Icon
76
- title="ลบไฟล์"
77
- :name="ui.action.deleteIcon"
78
- :class="[ui.imageItem.onFailed.actionBtnClass]"
79
- @click="handleDeleteFile"
80
- />
81
- </div>
82
- </div>
83
- </div>
84
- </div>
85
- </div>
86
- </FieldWrapper>
87
- </template>
88
-
89
- <script lang="ts" setup>
90
- import { type IUploadImageAutoProps } from './types'
91
- import FieldWrapper from '#core/components/Form/FieldWrapper.vue'
92
- import { useFieldHOC } from '#core/composables/useForm'
93
- import {
94
- computed,
95
- ref,
96
- toRef,
97
- useUI,
98
- useUiConfig,
99
- useWatchTrue,
100
- useUploadLoader,
101
- _get,
102
- type IUploadRequest,
103
- } from '#imports'
104
- import { uploadImage } from '#core/ui.config'
105
- import {
106
- checkMaxSize,
107
- generateURL,
108
- useFileAllocate,
109
- useFileProgress,
110
- } from '#core/helpers/componentHelper'
111
- import type { IFileValue } from '#core/components/Form/types'
112
- import i18next from 'i18next'
113
-
114
- const config = useUiConfig<typeof uploadImage>(uploadImage, 'uploadImage')
115
-
116
- const props = withDefaults(defineProps<IUploadImageAutoProps>(), {
117
- accept: 'image/*',
118
- bodyKey: 'file',
119
- responseURL: 'url',
120
- responsePath: 'path',
121
- uploadAddLabel: 'อัพโหลด',
122
- })
123
-
124
- const emits = defineEmits(['change', 'success', 'delete', 'error'])
125
-
126
- const request: IUploadRequest = {
127
- pathURL: props.uploadPathURL,
128
- requestOptions: props.requestOptions,
129
- }
130
-
131
- const selectedFile = ref<File>()
132
- const isPreviewOpen = ref<boolean>(false)
133
-
134
- const { wrapperProps, value, errorMessage } = useFieldHOC<IFileValue | undefined>(props)
135
-
136
- const upload = useUploadLoader(request)
137
- const { ui } = useUI('uploadImage', toRef(props, 'ui'), config)
138
-
139
- const fileInputRef = ref<HTMLInputElement | null>()
140
-
141
- const fileAllocate = useFileAllocate(toRef(selectedFile), props)
142
- const { onUploadProgress, onDownloadProgress, percent } = useFileProgress()
143
- const acceptFile = computed(() =>
144
- typeof props.accept === 'string' ? props.accept : props.accept?.join(',')
145
- )
146
-
147
- const handleChange = (e: Event) => {
148
- if (props.isDisabled) return
149
-
150
- const file = (e.target as HTMLInputElement).files?.[0]
151
- const result = handleCheckFileCondition(file)
152
-
153
- if (result && file) {
154
- selectedFile.value = file
155
- emits('change', selectedFile.value)
156
- const formData = new FormData()
157
-
158
- formData.append(props.bodyKey, file)
159
- upload.run(formData, { data: { onUploadProgress, onDownloadProgress } })
160
- }
161
- }
162
-
163
- const handleCheckFileCondition = (file: File | undefined): boolean => {
164
- if (!file) return false
165
- const maxSize = checkMaxSize(file, fileAllocate.acceptFileSizeKb.value)
166
-
167
- if (!maxSize) {
168
- if (fileAllocate.isAcceptFileUseMb.value) {
169
- errorMessage.value = i18next.t('custom:invalid_file_size_mb', {
170
- size: fileAllocate.acceptFileSizeMb.value,
171
- })
172
- } else {
173
- errorMessage.value = i18next.t('custom:invalid_file_size_kb', {
174
- size: fileAllocate.acceptFileSizeKb.value,
175
- })
176
- }
177
-
178
- return false
179
- }
180
-
181
- errorMessage.value = ''
182
-
183
- return true
184
- }
185
-
186
- const handleOpenFile = () => {
187
- fileInputRef.value?.click()
188
- }
189
-
190
- const handleDeleteFile = () => {
191
- fileInputRef.value!.value = ''
192
- selectedFile.value = undefined
193
- value.value = undefined
194
- emits('change', undefined)
195
-
196
- emits('delete')
197
- }
198
-
199
- useWatchTrue(
200
- () => upload.status.value.isSuccess,
201
- () => {
202
- value.value = {
203
- url: _get(upload.data.value, props.responseURL),
204
- path: _get(upload.data.value, props.responsePath),
205
- name: upload.data.value.name,
206
- size: upload.data.value.size,
207
- }
208
-
209
- emits('success', value.value)
210
- }
211
- )
212
-
213
- useWatchTrue(
214
- () => upload.status.value.isError,
215
- () => {
216
- emits('error', upload.status.value.errorData)
217
- }
218
- )
219
- </script>
1
+ <template>
2
+ <FieldWrapper v-bind="wrapperProps">
3
+ <div :class="[ui.base]">
4
+ <input
5
+ ref="fileInputRef"
6
+ type="file"
7
+ class="hidden"
8
+ :name="name"
9
+ :accept="acceptFile"
10
+ :disabled="isDisabled"
11
+ @change="handleChange"
12
+ />
13
+
14
+ <div :class="[ui.imageItem.wrapper]">
15
+ <div v-if="!selectedFile && !value" class="w-full">
16
+ <div :class="[ui.action.addingWrapper]" @click="handleOpenFile">
17
+ <Icon :name="ui.action.addingIcon" :class="[ui.action.addingBtnClass]" />
18
+ <p :class="[ui.action.addingTextClass]">{{ uploadAddLabel }}</p>
19
+ </div>
20
+ </div>
21
+
22
+ <!-- Loading State -->
23
+ <div v-if="selectedFile && upload.status.value.isLoading" class="w-full">
24
+ <div :class="[ui.imageItem.onLoading.wrapper]">
25
+ <div :class="[ui.imageItem.onLoading.percentClass]">{{ percent }}%</div>
26
+ <UProgress :value="percent" />
27
+ </div>
28
+ </div>
29
+
30
+ <!-- Success State -->
31
+ <div v-if="(selectedFile && upload.status.value.isSuccess) || value" class="w-full">
32
+ <div :class="[ui.imageItem.onPreview.wrapper]">
33
+ <img :class="[ui.imageItem.onPreview.previewImgClass]" :src="value?.url" alt="img" />
34
+ <div :class="[ui.imageItem.onPreview.previewActionWrapper]">
35
+ <Icon
36
+ title="ดูตัวอย่าง"
37
+ :name="ui.action.previewIcon"
38
+ :class="[ui.imageItem.onPreview.actionBtnClass]"
39
+ @click="() => (isPreviewOpen = true)"
40
+ />
41
+ <Icon
42
+ title="ลบไฟล์"
43
+ :name="ui.action.deleteIcon"
44
+ :class="[ui.imageItem.onPreview.actionBtnClass]"
45
+ @click="handleDeleteFile"
46
+ />
47
+ <Modal v-model="isPreviewOpen" size="xl">
48
+ <div class="absolute -top-8 left-0 flex w-full justify-between text-gray-600">
49
+ <p>{{ selectedFile?.name }}</p>
50
+ <Icon
51
+ name="i-heroicons-x-mark"
52
+ class="size-6 cursor-pointer hover:text-gray-400"
53
+ @click="() => (isPreviewOpen = false)"
54
+ />
55
+ </div>
56
+ <img :src="value?.url" alt="img-preview" class="w-full rounded-lg" />
57
+ </Modal>
58
+ </div>
59
+ </div>
60
+
61
+ <div v-if="selectedFile" :class="[ui.imageItem.onPreview.previewTextWrapper]">
62
+ <p :class="[ui.imageItem.onPreview.previewText]">{{ selectedFile.name }}</p>
63
+ </div>
64
+ </div>
65
+
66
+ <!-- Failed State -->
67
+ <div v-if="selectedFile && upload.status.value.isError" class="w-full">
68
+ <div :class="[ui.imageItem.onFailed.wrapper]">
69
+ <img
70
+ :class="[ui.imageItem.onFailed.failedImgClass]"
71
+ :src="generateURL(selectedFile)"
72
+ alt="img"
73
+ />
74
+ <div :class="[ui.imageItem.onFailed.failedActionWrapper]">
75
+ <Icon
76
+ title="ลบไฟล์"
77
+ :name="ui.action.deleteIcon"
78
+ :class="[ui.imageItem.onFailed.actionBtnClass]"
79
+ @click="handleDeleteFile"
80
+ />
81
+ </div>
82
+ </div>
83
+ </div>
84
+ </div>
85
+ </div>
86
+ </FieldWrapper>
87
+ </template>
88
+
89
+ <script lang="ts" setup>
90
+ import { type IUploadImageAutoProps } from './types'
91
+ import FieldWrapper from '#core/components/Form/FieldWrapper.vue'
92
+ import { useFieldHOC } from '#core/composables/useForm'
93
+ import {
94
+ computed,
95
+ ref,
96
+ toRef,
97
+ useUI,
98
+ useUiConfig,
99
+ useWatchTrue,
100
+ useUploadLoader,
101
+ _get,
102
+ type IUploadRequest,
103
+ } from '#imports'
104
+ import { uploadImage } from '#core/ui.config'
105
+ import {
106
+ checkMaxSize,
107
+ generateURL,
108
+ useFileAllocate,
109
+ useFileProgress,
110
+ } from '#core/helpers/componentHelper'
111
+ import type { IFileValue } from '#core/components/Form/types'
112
+ import i18next from 'i18next'
113
+
114
+ const config = useUiConfig<typeof uploadImage>(uploadImage, 'uploadImage')
115
+
116
+ const props = withDefaults(defineProps<IUploadImageAutoProps>(), {
117
+ accept: 'image/*',
118
+ bodyKey: 'file',
119
+ responseURL: 'url',
120
+ responsePath: 'path',
121
+ uploadAddLabel: 'อัพโหลด',
122
+ })
123
+
124
+ const emits = defineEmits(['change', 'success', 'delete', 'error'])
125
+
126
+ const request: IUploadRequest = {
127
+ pathURL: props.uploadPathURL,
128
+ requestOptions: props.requestOptions,
129
+ }
130
+
131
+ const selectedFile = ref<File>()
132
+ const isPreviewOpen = ref<boolean>(false)
133
+
134
+ const { wrapperProps, value, errorMessage } = useFieldHOC<IFileValue | undefined>(props)
135
+
136
+ const upload = useUploadLoader(request)
137
+ const { ui } = useUI('uploadImage', toRef(props, 'ui'), config)
138
+
139
+ const fileInputRef = ref<HTMLInputElement | null>()
140
+
141
+ const fileAllocate = useFileAllocate(toRef(selectedFile), props)
142
+ const { onUploadProgress, onDownloadProgress, percent } = useFileProgress()
143
+ const acceptFile = computed(() =>
144
+ typeof props.accept === 'string' ? props.accept : props.accept?.join(',')
145
+ )
146
+
147
+ const handleChange = (e: Event) => {
148
+ if (props.isDisabled) return
149
+
150
+ const file = (e.target as HTMLInputElement).files?.[0]
151
+ const result = handleCheckFileCondition(file)
152
+
153
+ if (result && file) {
154
+ selectedFile.value = file
155
+ emits('change', selectedFile.value)
156
+ const formData = new FormData()
157
+
158
+ formData.append(props.bodyKey, file)
159
+ upload.run(formData, { data: { onUploadProgress, onDownloadProgress } })
160
+ }
161
+ }
162
+
163
+ const handleCheckFileCondition = (file: File | undefined): boolean => {
164
+ if (!file) return false
165
+ const maxSize = checkMaxSize(file, fileAllocate.acceptFileSizeKb.value)
166
+
167
+ if (!maxSize) {
168
+ if (fileAllocate.isAcceptFileUseMb.value) {
169
+ errorMessage.value = i18next.t('custom:invalid_file_size_mb', {
170
+ size: fileAllocate.acceptFileSizeMb.value,
171
+ })
172
+ } else {
173
+ errorMessage.value = i18next.t('custom:invalid_file_size_kb', {
174
+ size: fileAllocate.acceptFileSizeKb.value,
175
+ })
176
+ }
177
+
178
+ return false
179
+ }
180
+
181
+ errorMessage.value = ''
182
+
183
+ return true
184
+ }
185
+
186
+ const handleOpenFile = () => {
187
+ fileInputRef.value?.click()
188
+ }
189
+
190
+ const handleDeleteFile = () => {
191
+ fileInputRef.value!.value = ''
192
+ selectedFile.value = undefined
193
+ value.value = undefined
194
+ emits('change', undefined)
195
+
196
+ emits('delete')
197
+ }
198
+
199
+ useWatchTrue(
200
+ () => upload.status.value.isSuccess,
201
+ () => {
202
+ value.value = {
203
+ url: _get(upload.data.value, props.responseURL),
204
+ path: _get(upload.data.value, props.responsePath),
205
+ name: upload.data.value.name,
206
+ size: upload.data.value.size,
207
+ }
208
+
209
+ emits('success', value.value)
210
+ }
211
+ )
212
+
213
+ useWatchTrue(
214
+ () => upload.status.value.isError,
215
+ () => {
216
+ emits('error', upload.status.value.errorData)
217
+ }
218
+ )
219
+ </script>
@@ -1,55 +1,55 @@
1
- <template>
2
- <FormFields :options="formFields" :form="form" />
3
- </template>
4
- <script lang="ts" setup>
5
- import { toTypedSchema, useForm, createFormFields, watch } from '#imports'
6
- import * as z from 'zod'
7
- import { INPUT_TYPES } from '#core/components/Form/types'
8
- import type { IWYSIWYGFieldProps } from '#core/components/Form/InputWYSIWYG/types'
9
-
10
- const emits = defineEmits(['submit'])
11
- const props = defineProps<{
12
- options: IWYSIWYGFieldProps['image']
13
- }>()
14
-
15
- const form = useForm({
16
- validationSchema: toTypedSchema(
17
- z.object({
18
- file: z
19
- .object({
20
- url: z.string(),
21
- path: z.string().optional(),
22
- name: z.string().optional(),
23
- size: z.string().optional(),
24
- })
25
- .optional()
26
- .nullable(),
27
- })
28
- ),
29
- initialValues: {
30
- file: null,
31
- },
32
- })
33
-
34
- const formFields = createFormFields(() => [
35
- {
36
- type: INPUT_TYPES.UPLOAD_IMAGE_AUTO,
37
- props: {
38
- name: 'file',
39
- ...((props.options || {}) as any),
40
- },
41
- },
42
- ])
43
-
44
- watch(
45
- () => form.values,
46
- () => {
47
- if (form.values.file?.url) {
48
- emits('submit', form.values.file?.url)
49
- }
50
- },
51
- {
52
- deep: true,
53
- }
54
- )
55
- </script>
1
+ <template>
2
+ <FormFields :options="formFields" :form="form" />
3
+ </template>
4
+ <script lang="ts" setup>
5
+ import { toTypedSchema, useForm, createFormFields, watch } from '#imports'
6
+ import * as z from 'zod'
7
+ import { INPUT_TYPES } from '#core/components/Form/types'
8
+ import type { IWYSIWYGFieldProps } from '#core/components/Form/InputWYSIWYG/types'
9
+
10
+ const emits = defineEmits(['submit'])
11
+ const props = defineProps<{
12
+ options: IWYSIWYGFieldProps['image']
13
+ }>()
14
+
15
+ const form = useForm({
16
+ validationSchema: toTypedSchema(
17
+ z.object({
18
+ file: z
19
+ .object({
20
+ url: z.string(),
21
+ path: z.string().optional(),
22
+ name: z.string().optional(),
23
+ size: z.string().optional(),
24
+ })
25
+ .optional()
26
+ .nullable(),
27
+ })
28
+ ),
29
+ initialValues: {
30
+ file: null,
31
+ },
32
+ })
33
+
34
+ const formFields = createFormFields(() => [
35
+ {
36
+ type: INPUT_TYPES.UPLOAD_IMAGE_AUTO,
37
+ props: {
38
+ name: 'file',
39
+ ...((props.options || {}) as any),
40
+ },
41
+ },
42
+ ])
43
+
44
+ watch(
45
+ () => form.values,
46
+ () => {
47
+ if (form.values.file?.url) {
48
+ emits('submit', form.values.file?.url)
49
+ }
50
+ },
51
+ {
52
+ deep: true,
53
+ }
54
+ )
55
+ </script>