@finema/core 1.4.92 → 1.4.93

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 (24) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/module.mjs +1 -1
  3. package/dist/runtime/components/Form/Fields.vue +9 -0
  4. package/dist/runtime/components/Form/InputUploadDropzoneAuto/index.vue +7 -1
  5. package/dist/runtime/components/Form/InputUploadDropzoneAutoMultiple/Item.vue +283 -282
  6. package/dist/runtime/components/Form/InputUploadDropzoneAutoMultiple/index.vue +13 -4
  7. package/dist/runtime/components/Form/InputUploadDropzoneImageAutoMultiple/index.vue +134 -0
  8. package/dist/runtime/components/Form/InputUploadDropzoneImageAutoMultiple/item.vue +198 -0
  9. package/dist/runtime/components/Form/InputUploadDropzoneImageAutoMultiple/types.d.ts +20 -0
  10. package/dist/runtime/components/Form/InputUploadDropzoneImageAutoMultiple/types.mjs +0 -0
  11. package/dist/runtime/components/Form/InputUploadFileClassic/index.vue +5 -3
  12. package/dist/runtime/components/Form/InputUploadFileClassicAuto/index.vue +9 -5
  13. package/dist/runtime/components/Form/types.d.ts +4 -2
  14. package/dist/runtime/components/Form/types.mjs +1 -0
  15. package/dist/runtime/composables/useNotification.d.ts +7 -0
  16. package/dist/runtime/composables/useNotification.mjs +39 -0
  17. package/dist/runtime/types/config.d.ts +1 -1
  18. package/dist/runtime/ui.config/index.d.ts +1 -0
  19. package/dist/runtime/ui.config/index.mjs +1 -0
  20. package/dist/runtime/ui.config/uploadDropzoneImage.d.ts +83 -0
  21. package/dist/runtime/ui.config/uploadDropzoneImage.mjs +26 -0
  22. package/dist/runtime/ui.config/uploadFileDropzone.d.ts +4 -0
  23. package/dist/runtime/ui.config/uploadFileDropzone.mjs +5 -1
  24. package/package.json +1 -1
package/dist/module.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@finema/core",
3
- "version": "1.4.92",
3
+ "version": "1.4.93",
4
4
  "configKey": "core",
5
5
  "compatibility": {
6
6
  "nuxt": "^3.7.4"
package/dist/module.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import { defineNuxtModule, createResolver, installModule, addPlugin, addComponentsDir, addImportsDir } from '@nuxt/kit';
2
2
 
3
3
  const name = "@finema/core";
4
- const version = "1.4.92";
4
+ const version = "1.4.93";
5
5
 
6
6
  const colors = {
7
7
  black: "#20243E",
@@ -104,6 +104,7 @@
104
104
  v-else-if="option.type === INPUT_TYPES.UPLOAD_FILE_CLASSIC_AUTO"
105
105
  :class="option.class"
106
106
  :form="form"
107
+ :request-options="option.props.requestOptions"
107
108
  v-bind="getFieldBinding(option)"
108
109
  v-on="option.on ?? {}"
109
110
  />
@@ -130,6 +131,14 @@
130
131
  v-bind="getFieldBinding(option)"
131
132
  v-on="option.on ?? {}"
132
133
  />
134
+ <FormInputUploadDropzoneImageAutoMultiple
135
+ v-else-if="option.type === INPUT_TYPES.UPLOAD_DROPZONE_IMAGE_AUTO_MULTIPLE"
136
+ :class="option.class"
137
+ :form="form"
138
+ :request-options="option.props.requestOptions"
139
+ v-bind="getFieldBinding(option)"
140
+ v-on="option.on ?? {}"
141
+ />
133
142
  </template>
134
143
  </div>
135
144
  </template>
@@ -192,7 +192,13 @@ import i18next from 'i18next'
192
192
 
193
193
  const config = useUiConfig<typeof uploadFileDropzone>(uploadFileDropzone, 'uploadFileDropzone')
194
194
 
195
- const props = withDefaults(defineProps<IUploadDropzoneAutoProps>(), {})
195
+ const props = withDefaults(defineProps<IUploadDropzoneAutoProps>(), {
196
+ bodyKey: 'file',
197
+ responseKey: 'url',
198
+ selectFileLabel: 'คลิกเพื่อเลือกไฟล์',
199
+ selectFileSubLabel: 'หรือ ลากและวางที่นี่',
200
+ })
201
+
196
202
  const emits = defineEmits(['change', 'success', 'delete'])
197
203
 
198
204
  const { wrapperProps, handleChange: onChange, setErrors, value } = useFieldHOC<File>(props)
@@ -1,282 +1,283 @@
1
- <template>
2
- <div
3
- :class="[
4
- ui.base,
5
- ui.background.default,
6
- {
7
- [ui.failed]: upload.status.value.isError || errMsg,
8
- },
9
- ]"
10
- >
11
- <!-- Loading State -->
12
- <div v-if="selectedFile && upload.status.value.isLoading" :class="[ui.onLoading.wrapper]">
13
- <div :class="[ui.onLoading.placeholderWrapper]">
14
- <Icon
15
- :name="
16
- isImage(selectedFile)
17
- ? ui.onLoading.placeholderImgIcon || ui.default.placeholderImgIcon
18
- : ui.onLoading.placeholderFileIcon || ui.default.filePreviewIcon
19
- "
20
- :class="[ui.onLoading.placeholderIconClass]"
21
- />
22
- </div>
23
- <div :class="[ui.onLoading.textWrapper]">
24
- <div class="truncate">
25
- <h1 class="truncate font-bold">{{ selectedFile?.name }}</h1>
26
- <p class="truncate font-light text-gray-400">
27
- {{
28
- fileAllocate.isSelectedFileUseMb
29
- ? `${fileAllocate.selectedFileSizeMb} MB`
30
- : `${fileAllocate.selectedFileSizeKb} KB`
31
- }}
32
- - {{ percent }}% {{ uploadingLabel ?? 'กำลังอัพโหลด...' }}
33
- </p>
34
- </div>
35
- <div>
36
- <Icon
37
- :name="ui.onLoading.loadingIcon || ui.default.loadingIcon"
38
- :class="[ui.onLoading.loadingIconClass]"
39
- />
40
- </div>
41
- </div>
42
- </div>
43
-
44
- <!-- Success State -->
45
- <div v-if="selectedFile && upload.status.value.isSuccess" :class="[ui.onPreview.wrapper]">
46
- <div :class="[ui.onPreview.previewImgWrapper]">
47
- <div v-if="isImage(selectedFile)" class="size-full overflow-hidden">
48
- <img
49
- :src="upload.data.value[responseKey || 'url']"
50
- :class="[ui.onPreview.previewImgClass]"
51
- alt="image-preview"
52
- />
53
- </div>
54
- <div v-else>
55
- <Icon
56
- :name="ui.onPreview.previewFileIcon || ui.default.filePreviewIcon"
57
- :class="[ui.onPreview.previewFileClass]"
58
- />
59
- </div>
60
- </div>
61
- <div :class="[ui.onPreview.textWrapper]">
62
- <div class="truncate">
63
- <h1 class="truncate font-bold" :title="selectedFile?.name">
64
- {{ StringHelper.truncate(selectedFile?.name, 40) }}
65
- </h1>
66
- <p class="truncate text-sm font-light text-gray-400">
67
- {{
68
- fileAllocate.isSelectedFileUseMb
69
- ? `${fileAllocate.selectedFileSizeMb} MB`
70
- : `${fileAllocate.selectedFileSizeKb} KB`
71
- }}
72
- </p>
73
- </div>
74
- <div :class="[ui.action.wrapper]">
75
- <Icon
76
- v-if="isImage(selectedFile)"
77
- :name="ui.action.previewIcon"
78
- :class="[ui.action.iconClass]"
79
- title="ดูตัวอย่าง"
80
- @click="() => (isPreviewOpen = true)"
81
- />
82
- <Icon
83
- :name="ui.action.downloadIcon"
84
- :class="[ui.action.iconClass]"
85
- title="ดาวน์โหลดไฟล์"
86
- @click="handleDownloadFile"
87
- />
88
- <Icon
89
- :name="ui.action.deleteIcon"
90
- :class="[ui.action.iconClass]"
91
- title="ลบไฟล์"
92
- @click="handleDeleteFile"
93
- />
94
- <Modal v-model="isPreviewOpen" :title="selectedFile?.name">
95
- <img :src="URL.createObjectURL(props.selectedFile)" alt="image-preview" />
96
- </Modal>
97
- </div>
98
- </div>
99
- </div>
100
-
101
- <!-- Failed State -->
102
- <div
103
- v-if="selectedFile && (upload.status.value.isError || errMsg)"
104
- :class="[ui.onFailed.wrapper]"
105
- >
106
- <div :class="[ui.onFailed.failedImgWrapper]">
107
- <Icon
108
- :name="
109
- isImage(selectedFile)
110
- ? ui.onFailed.failedImgIcon || ui.default.placeholderImgIcon
111
- : ui.onFailed.failedFileIcon || ui.default.filePreviewIcon
112
- "
113
- :class="[ui.onFailed.failedIconClass]"
114
- />
115
- </div>
116
- <div :class="[ui.onFailed.textWrapper]">
117
- <div class="truncate">
118
- <h1 class="truncate font-bold" :title="selectedFile?.name">
119
- {{ StringHelper.truncate(selectedFile?.name, 40) }}
120
- </h1>
121
- <p class="text-danger truncate font-light">
122
- {{ errMsg ? errMsg : uploadFailedLabel || 'อัพโหลดล้มเหลว, กรุณาลองอีกครั้ง' }}
123
- </p>
124
- <Button
125
- v-if="upload.status.value.isError"
126
- variant="ghost"
127
- :label="retryLabel || 'ลองอีกครั้ง'"
128
- :leading-icon="ui.action.retryIcon"
129
- :class="[ui.action.retryBtnClass]"
130
- size="sm"
131
- @click="handleRetryUpload"
132
- />
133
- </div>
134
- <div :class="[ui.action.wrapper]">
135
- <Icon
136
- title="ลบไฟล์"
137
- :name="ui.action.deleteIcon"
138
- :class="[ui.action.deleteIconClass]"
139
- @click="handleDeleteFile"
140
- />
141
- </div>
142
- </div>
143
- </div>
144
- </div>
145
- </template>
146
- <script lang="ts" setup>
147
- import {
148
- checkFileType,
149
- checkMaxSize,
150
- downloadFileFromURL,
151
- getFileAllocate,
152
- isImage,
153
- } from '#core/helpers/componentHelper'
154
- import { type uploadFileDropzone } from '#core/ui.config'
155
- import type { IUploadDropzoneAutoMultipleProps } from '#core/components/Form/InputUploadDropzoneAutoMultiple/types'
156
- import {
157
- computed,
158
- type IUploadRequest,
159
- onMounted,
160
- ref,
161
- StringHelper,
162
- useUploadLoader,
163
- useWatchTrue,
164
- } from '#imports'
165
- import i18next from 'i18next'
166
-
167
- const emits = defineEmits(['success', 'error', 'delete'])
168
- const props = defineProps<
169
- {
170
- ui: typeof uploadFileDropzone
171
- selectedFile: File
172
- } & IUploadDropzoneAutoMultipleProps
173
- >()
174
-
175
- const request: IUploadRequest = {
176
- pathURL: props.uploadPathURL,
177
- requestOptions: props.requestOptions,
178
- }
179
-
180
- const isPreviewOpen = ref<boolean>(false)
181
- const percent = ref<number | string>(0)
182
- const upload = useUploadLoader(request)
183
- const errMsg = ref<string>('')
184
-
185
- const acceptFile = computed(() =>
186
- typeof props.accept === 'string' ? props.accept : props.accept?.join(',')
187
- )
188
-
189
- const fileAllocate = computed(() =>
190
- getFileAllocate(props.maxSize ?? 0, props.selectedFile?.size ?? 0)
191
- )
192
-
193
- const handleDeleteFile = () => {
194
- emits('delete')
195
- }
196
-
197
- const handleRetryUpload = () => {
198
- const formData = new FormData()
199
-
200
- formData.append(props.bodyKey || 'file', props.selectedFile)
201
- upload.run(formData, { data: { onUploadProgress, onDownloadProgress } })
202
- }
203
-
204
- const handleDownloadFile = () => {
205
- downloadFileFromURL(URL.createObjectURL(props.selectedFile), props.selectedFile.name)
206
- }
207
-
208
- const onUploadProgress = (progressEvent: ProgressEvent) => {
209
- percent.value = StringHelper.withFixed(
210
- (Math.floor((progressEvent.loaded * 100) / progressEvent.total) || 0) * 0.8
211
- )
212
- }
213
-
214
- const onDownloadProgress = (progressEvent: ProgressEvent) => {
215
- if (progressEvent.total === 0) {
216
- percent.value = 100
217
-
218
- return
219
- }
220
-
221
- percent.value = StringHelper.withFixed(
222
- (Math.floor((progressEvent.loaded * 100) / progressEvent.total) || 0) * 0.2 + 80
223
- )
224
- }
225
-
226
- const handleCheckFileCondition = (file: File | undefined): boolean => {
227
- if (!file) return false
228
-
229
- const fileType = checkFileType(file, acceptFile.value ?? '')
230
-
231
- if (!fileType) {
232
- errMsg.value = i18next.t('custom:invalid_file_type')
233
-
234
- return false
235
- }
236
-
237
- const maxSize = checkMaxSize(file, fileAllocate.value.acceptFileSizeKb ?? 0)
238
-
239
- if (!maxSize) {
240
- if (fileAllocate.value.isAcceptFileUseMb) {
241
- errMsg.value = i18next.t('custom:invalid_file_size_mb', {
242
- size: fileAllocate.value.acceptFileSizeMb,
243
- })
244
- } else {
245
- errMsg.value = i18next.t('custom:invalid_file_size_kb', {
246
- size: fileAllocate.value.acceptFileSizeKb,
247
- })
248
- }
249
-
250
- return false
251
- }
252
-
253
- errMsg.value = ''
254
-
255
- return true
256
- }
257
-
258
- onMounted(() => {
259
- const result = handleCheckFileCondition(props.selectedFile)
260
-
261
- if (result) {
262
- const formData = new FormData()
263
-
264
- formData.append(props.bodyKey || 'file', props.selectedFile)
265
- upload.run(formData, { data: { onUploadProgress, onDownloadProgress } })
266
- }
267
- })
268
-
269
- useWatchTrue(
270
- () => upload.status.value.isSuccess,
271
- () => {
272
- emits('success', upload.data.value)
273
- }
274
- )
275
-
276
- useWatchTrue(
277
- () => upload.status.value.isError,
278
- () => {
279
- emits('error', upload.status.value.errorData)
280
- }
281
- )
282
- </script>
1
+ <template>
2
+ <div
3
+ :class="[
4
+ ui.base,
5
+ ui.background.default,
6
+ {
7
+ [ui.failed]: upload.status.value.isError || errMsg,
8
+ },
9
+ ]"
10
+ >
11
+ <!-- Loading State -->
12
+ <div v-if="selectedFile && upload.status.value.isLoading" :class="[ui.onLoading.wrapper]">
13
+ <div :class="[ui.onLoading.placeholderWrapper]">
14
+ <Icon
15
+ :name="
16
+ isImage(selectedFile)
17
+ ? ui.onLoading.placeholderImgIcon || ui.default.placeholderImgIcon
18
+ : ui.onLoading.placeholderFileIcon || ui.default.filePreviewIcon
19
+ "
20
+ :class="[ui.onLoading.placeholderIconClass]"
21
+ />
22
+ </div>
23
+ <div :class="[ui.onLoading.textWrapper]">
24
+ <div class="truncate">
25
+ <h1 class="truncate font-bold">{{ selectedFile?.name }}</h1>
26
+ <p class="truncate font-light text-gray-400">
27
+ {{
28
+ fileAllocate.isSelectedFileUseMb
29
+ ? `${fileAllocate.selectedFileSizeMb} MB`
30
+ : `${fileAllocate.selectedFileSizeKb} KB`
31
+ }}
32
+ - {{ percent }}% {{ uploadingLabel }}
33
+ </p>
34
+ </div>
35
+ <div>
36
+ <Icon
37
+ :name="ui.onLoading.loadingIcon || ui.default.loadingIcon"
38
+ :class="[ui.onLoading.loadingIconClass]"
39
+ />
40
+ </div>
41
+ </div>
42
+ </div>
43
+
44
+ <!-- Success State -->
45
+ <div v-if="selectedFile && upload.status.value.isSuccess" :class="[ui.onPreview.wrapper]">
46
+ <div :class="[ui.onPreview.previewImgWrapper]">
47
+ <div v-if="isImage(selectedFile)" class="size-full overflow-hidden">
48
+ <img
49
+ :src="upload.data.value[responseKey]"
50
+ :class="[ui.onPreview.previewImgClass]"
51
+ alt="image-preview"
52
+ />
53
+ </div>
54
+ <div v-else>
55
+ <Icon
56
+ :name="ui.onPreview.previewFileIcon || ui.default.filePreviewIcon"
57
+ :class="[ui.onPreview.previewFileClass]"
58
+ />
59
+ </div>
60
+ </div>
61
+ <div :class="[ui.onPreview.textWrapper]">
62
+ <div class="truncate">
63
+ <h1 class="truncate font-bold" :title="selectedFile?.name">
64
+ {{ StringHelper.truncate(selectedFile?.name, 40) }}
65
+ </h1>
66
+ <p class="truncate text-sm font-light text-gray-400">
67
+ {{
68
+ fileAllocate.isSelectedFileUseMb
69
+ ? `${fileAllocate.selectedFileSizeMb} MB`
70
+ : `${fileAllocate.selectedFileSizeKb} KB`
71
+ }}
72
+ </p>
73
+ </div>
74
+ <div :class="[ui.action.wrapper]">
75
+ <Icon
76
+ v-if="isImage(selectedFile)"
77
+ :name="ui.action.previewIcon"
78
+ :class="[ui.action.iconClass]"
79
+ title="ดูตัวอย่าง"
80
+ @click="() => (isPreviewOpen = true)"
81
+ />
82
+ <Icon
83
+ :name="ui.action.downloadIcon"
84
+ :class="[ui.action.iconClass]"
85
+ title="ดาวน์โหลดไฟล์"
86
+ @click="handleDownloadFile"
87
+ />
88
+ <Icon
89
+ :name="ui.action.deleteIcon"
90
+ :class="[ui.action.iconClass]"
91
+ title="ลบไฟล์"
92
+ @click="handleDeleteFile"
93
+ />
94
+ <Modal v-model="isPreviewOpen" :title="selectedFile?.name">
95
+ <img :src="generateURL(selectedFile)" alt="image-preview" />
96
+ </Modal>
97
+ </div>
98
+ </div>
99
+ </div>
100
+
101
+ <!-- Failed State -->
102
+ <div
103
+ v-if="selectedFile && (upload.status.value.isError || errMsg)"
104
+ :class="[ui.onFailed.wrapper]"
105
+ >
106
+ <div :class="[ui.onFailed.failedImgWrapper]">
107
+ <Icon
108
+ :name="
109
+ isImage(selectedFile)
110
+ ? ui.onFailed.failedImgIcon || ui.default.placeholderImgIcon
111
+ : ui.onFailed.failedFileIcon || ui.default.filePreviewIcon
112
+ "
113
+ :class="[ui.onFailed.failedIconClass]"
114
+ />
115
+ </div>
116
+ <div :class="[ui.onFailed.textWrapper]">
117
+ <div class="truncate">
118
+ <h1 class="truncate font-bold" :title="selectedFile?.name">
119
+ {{ StringHelper.truncate(selectedFile?.name, 40) }}
120
+ </h1>
121
+ <p class="text-danger truncate font-light">
122
+ {{ errMsg ? errMsg : uploadFailedLabel }}
123
+ </p>
124
+ <Button
125
+ v-if="upload.status.value.isError"
126
+ variant="ghost"
127
+ :label="retryLabel"
128
+ :leading-icon="ui.action.retryIcon"
129
+ :class="[ui.action.retryBtnClass]"
130
+ size="sm"
131
+ @click="handleRetryUpload"
132
+ />
133
+ </div>
134
+ <div :class="[ui.action.wrapper]">
135
+ <Icon
136
+ title="ลบไฟล์"
137
+ :name="ui.action.deleteIcon"
138
+ :class="[ui.action.deleteIconClass]"
139
+ @click="handleDeleteFile"
140
+ />
141
+ </div>
142
+ </div>
143
+ </div>
144
+ </div>
145
+ </template>
146
+ <script lang="ts" setup>
147
+ import {
148
+ checkFileType,
149
+ checkMaxSize,
150
+ downloadFileFromURL,
151
+ getFileAllocate,
152
+ generateURL,
153
+ isImage,
154
+ } from '#core/helpers/componentHelper'
155
+ import { type uploadFileDropzone } from '#core/ui.config'
156
+ import type { IUploadDropzoneAutoMultipleProps } from '#core/components/Form/InputUploadDropzoneAutoMultiple/types'
157
+ import {
158
+ computed,
159
+ type IUploadRequest,
160
+ onMounted,
161
+ ref,
162
+ StringHelper,
163
+ useUploadLoader,
164
+ useWatchTrue,
165
+ } from '#imports'
166
+ import i18next from 'i18next'
167
+
168
+ const emits = defineEmits(['success', 'error', 'delete'])
169
+ const props = defineProps<
170
+ {
171
+ ui: typeof uploadFileDropzone
172
+ selectedFile: File
173
+ } & IUploadDropzoneAutoMultipleProps
174
+ >()
175
+
176
+ const request: IUploadRequest = {
177
+ pathURL: props.uploadPathURL,
178
+ requestOptions: props.requestOptions,
179
+ }
180
+
181
+ const isPreviewOpen = ref<boolean>(false)
182
+ const percent = ref<number | string>(0)
183
+ const upload = useUploadLoader(request)
184
+ const errMsg = ref<string>('')
185
+
186
+ const acceptFile = computed(() =>
187
+ typeof props.accept === 'string' ? props.accept : props.accept?.join(',')
188
+ )
189
+
190
+ const fileAllocate = computed(() =>
191
+ getFileAllocate(props.maxSize ?? 0, props.selectedFile?.size ?? 0)
192
+ )
193
+
194
+ const handleDeleteFile = () => {
195
+ emits('delete')
196
+ }
197
+
198
+ const handleRetryUpload = () => {
199
+ const formData = new FormData()
200
+
201
+ formData.append(props.bodyKey!, props.selectedFile)
202
+ upload.run(formData, { data: { onUploadProgress, onDownloadProgress } })
203
+ }
204
+
205
+ const handleDownloadFile = () => {
206
+ downloadFileFromURL(URL.createObjectURL(props.selectedFile), props.selectedFile.name)
207
+ }
208
+
209
+ const onUploadProgress = (progressEvent: ProgressEvent) => {
210
+ percent.value = StringHelper.withFixed(
211
+ (Math.floor((progressEvent.loaded * 100) / progressEvent.total) || 0) * 0.8
212
+ )
213
+ }
214
+
215
+ const onDownloadProgress = (progressEvent: ProgressEvent) => {
216
+ if (progressEvent.total === 0) {
217
+ percent.value = 100
218
+
219
+ return
220
+ }
221
+
222
+ percent.value = StringHelper.withFixed(
223
+ (Math.floor((progressEvent.loaded * 100) / progressEvent.total) || 0) * 0.2 + 80
224
+ )
225
+ }
226
+
227
+ const handleCheckFileCondition = (file: File | undefined): boolean => {
228
+ if (!file) return false
229
+
230
+ const fileType = checkFileType(file, acceptFile.value ?? '')
231
+
232
+ if (!fileType) {
233
+ errMsg.value = i18next.t('custom:invalid_file_type')
234
+
235
+ return false
236
+ }
237
+
238
+ const maxSize = checkMaxSize(file, fileAllocate.value.acceptFileSizeKb ?? 0)
239
+
240
+ if (!maxSize) {
241
+ if (fileAllocate.value.isAcceptFileUseMb) {
242
+ errMsg.value = i18next.t('custom:invalid_file_size_mb', {
243
+ size: fileAllocate.value.acceptFileSizeMb,
244
+ })
245
+ } else {
246
+ errMsg.value = i18next.t('custom:invalid_file_size_kb', {
247
+ size: fileAllocate.value.acceptFileSizeKb,
248
+ })
249
+ }
250
+
251
+ return false
252
+ }
253
+
254
+ errMsg.value = ''
255
+
256
+ return true
257
+ }
258
+
259
+ onMounted(() => {
260
+ const result = handleCheckFileCondition(props.selectedFile)
261
+
262
+ if (result) {
263
+ const formData = new FormData()
264
+
265
+ formData.append(props.bodyKey!, props.selectedFile)
266
+ upload.run(formData, { data: { onUploadProgress, onDownloadProgress } })
267
+ }
268
+ })
269
+
270
+ useWatchTrue(
271
+ () => upload.status.value.isSuccess,
272
+ () => {
273
+ emits('success', upload.data.value)
274
+ }
275
+ )
276
+
277
+ useWatchTrue(
278
+ () => upload.status.value.isError,
279
+ () => {
280
+ emits('error', upload.status.value.errorData)
281
+ }
282
+ )
283
+ </script>
@@ -27,9 +27,9 @@
27
27
  <Icon :name="ui.default.uploadIcon" :class="[ui.labelIcon]" />
28
28
  <div :class="[ui.labelWrapper]">
29
29
  <p class="text-primary cursor-pointer" @click="handleOpenFile">
30
- {{ selectFileLabel ?? 'คลิกเพื่อเลือกไฟล์' }}
30
+ {{ selectFileLabel }}
31
31
  </p>
32
- <p>{{ selectFileSubLabel ?? 'หรือ ลากและวางที่นี่' }}</p>
32
+ <p>{{ selectFileSubLabel }}</p>
33
33
  </div>
34
34
  <p v-if="placeholder" :class="[ui.placeholder]">{{ placeholder }}</p>
35
35
  </div>
@@ -60,7 +60,16 @@ import Item from './Item.vue'
60
60
 
61
61
  const config = useUiConfig<typeof uploadFileDropzone>(uploadFileDropzone, 'uploadFileDropzone')
62
62
 
63
- const props = withDefaults(defineProps<IUploadDropzoneAutoMultipleProps>(), {})
63
+ const props = withDefaults(defineProps<IUploadDropzoneAutoMultipleProps>(), {
64
+ bodyKey: 'file',
65
+ responseKey: 'url',
66
+ selectFileLabel: 'คลิกเพื่อเลือกไฟล์',
67
+ selectFileSubLabel: 'หรือ ลากและวางที่นี่',
68
+ retryLabel: 'ลองอีกครั้ง',
69
+ uploadingLabel: 'กำลังอัพโหลด...',
70
+ uploadFailedLabel: 'อัพโหลดล้มเหลว, กรุณาลองอีกครั้ง',
71
+ })
72
+
64
73
  const emits = defineEmits(['change', 'success', 'delete'])
65
74
  const selectedFiles = ref<File[]>([])
66
75
 
@@ -110,7 +119,7 @@ const handleDeleteFile = (index: number) => {
110
119
  const handleError = (index: number, error: any) => {}
111
120
 
112
121
  const handleSuccess = (index: number, any: any) => {
113
- value.value = [_get(any, props.responseKey || 'url'), ...(value.value || [])]
122
+ value.value = [_get(any, props.responseKey), ...(value.value || [])]
114
123
  emits('change', value.value)
115
124
  emits('success', value.value)
116
125
  }