@finema/core 1.4.152 → 1.4.153

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 (168) hide show
  1. package/README.md +60 -60
  2. package/dist/module.json +1 -5
  3. package/dist/module.mjs +1 -1
  4. package/dist/runtime/components/Alert.vue +48 -48
  5. package/dist/runtime/components/Avatar.vue +27 -27
  6. package/dist/runtime/components/Badge.vue +11 -11
  7. package/dist/runtime/components/Breadcrumb.vue +44 -44
  8. package/dist/runtime/components/Button/Group.vue +37 -37
  9. package/dist/runtime/components/Button/index.vue +75 -75
  10. package/dist/runtime/components/Card.vue +38 -38
  11. package/dist/runtime/components/Core.vue +37 -37
  12. package/dist/runtime/components/Dialog/index.vue +108 -108
  13. package/dist/runtime/components/Dropdown/index.vue +70 -70
  14. package/dist/runtime/components/FlexDeck/Base.vue +143 -143
  15. package/dist/runtime/components/FlexDeck/index.vue +68 -68
  16. package/dist/runtime/components/Form/FieldWrapper.vue +23 -23
  17. package/dist/runtime/components/Form/Fields.vue +230 -230
  18. package/dist/runtime/components/Form/InputCheckbox/index.vue +28 -28
  19. package/dist/runtime/components/Form/InputDateTime/index.vue +60 -60
  20. package/dist/runtime/components/Form/InputDateTimeRange/date_range_time_field.types.d.ts +1 -1
  21. package/dist/runtime/components/Form/InputDateTimeRange/index.vue +83 -83
  22. package/dist/runtime/components/Form/InputNumber/index.vue +27 -27
  23. package/dist/runtime/components/Form/InputRadio/index.vue +27 -27
  24. package/dist/runtime/components/Form/InputSelect/index.vue +45 -45
  25. package/dist/runtime/components/Form/InputSelectMultiple/index.vue +54 -54
  26. package/dist/runtime/components/Form/InputStatic/index.vue +16 -16
  27. package/dist/runtime/components/Form/InputTags/index.vue +145 -145
  28. package/dist/runtime/components/Form/InputText/index.vue +67 -67
  29. package/dist/runtime/components/Form/InputTextarea/index.vue +25 -25
  30. package/dist/runtime/components/Form/InputToggle/index.vue +14 -14
  31. package/dist/runtime/components/Form/InputUploadDropzone/index.vue +206 -206
  32. package/dist/runtime/components/Form/InputUploadDropzone/types.d.ts +1 -1
  33. package/dist/runtime/components/Form/InputUploadDropzoneAuto/index.vue +342 -342
  34. package/dist/runtime/components/Form/InputUploadDropzoneAuto/types.d.ts +1 -1
  35. package/dist/runtime/components/Form/InputUploadDropzoneAutoMultiple/ItemUpload.vue +241 -241
  36. package/dist/runtime/components/Form/InputUploadDropzoneAutoMultiple/ItemView.vue +89 -89
  37. package/dist/runtime/components/Form/InputUploadDropzoneAutoMultiple/index.vue +164 -164
  38. package/dist/runtime/components/Form/InputUploadDropzoneAutoMultiple/types.d.ts +1 -1
  39. package/dist/runtime/components/Form/InputUploadDropzoneImageAutoMultiple/ItemUpload.vue +161 -161
  40. package/dist/runtime/components/Form/InputUploadDropzoneImageAutoMultiple/ItemView.vue +64 -64
  41. package/dist/runtime/components/Form/InputUploadDropzoneImageAutoMultiple/index.vue +172 -172
  42. package/dist/runtime/components/Form/InputUploadDropzoneImageAutoMultiple/types.d.ts +1 -1
  43. package/dist/runtime/components/Form/InputUploadFileClassic/index.vue +95 -95
  44. package/dist/runtime/components/Form/InputUploadFileClassicAuto/index.vue +151 -151
  45. package/dist/runtime/components/Form/InputUploadFileClassicAuto/types.d.ts +1 -1
  46. package/dist/runtime/components/Form/InputUploadImageAuto/index.vue +219 -219
  47. package/dist/runtime/components/Form/InputUploadImageAuto/types.d.ts +1 -1
  48. package/dist/runtime/components/Form/InputWYSIWYG/index.vue +53 -53
  49. package/dist/runtime/components/Form/index.vue +6 -6
  50. package/dist/runtime/components/Icon.vue +23 -23
  51. package/dist/runtime/components/Image.vue +36 -36
  52. package/dist/runtime/components/Loader.vue +27 -27
  53. package/dist/runtime/components/Modal/index.vue +146 -146
  54. package/dist/runtime/components/QRCode.vue +22 -22
  55. package/dist/runtime/components/SimplePagination.vue +96 -96
  56. package/dist/runtime/components/Slideover/index.vue +110 -110
  57. package/dist/runtime/components/Table/Base.vue +139 -139
  58. package/dist/runtime/components/Table/ColumnDate.vue +16 -16
  59. package/dist/runtime/components/Table/ColumnDateTime.vue +18 -18
  60. package/dist/runtime/components/Table/ColumnImage.vue +15 -15
  61. package/dist/runtime/components/Table/ColumnNumber.vue +14 -14
  62. package/dist/runtime/components/Table/ColumnText.vue +25 -25
  63. package/dist/runtime/components/Table/Simple.vue +69 -69
  64. package/dist/runtime/components/Table/index.vue +65 -65
  65. package/dist/runtime/components/Tabs/index.vue +64 -64
  66. package/dist/runtime/components/TeleportSafe.vue +40 -40
  67. package/dist/runtime/composables/loaderList.d.ts +2 -2
  68. package/dist/runtime/composables/{loaderList.js → loaderList.mjs} +2 -2
  69. package/dist/runtime/composables/loaderObject.d.ts +1 -1
  70. package/dist/runtime/composables/{loaderObject.js → loaderObject.mjs} +2 -2
  71. package/dist/runtime/composables/loaderPage.d.ts +1 -1
  72. package/dist/runtime/composables/{loaderPage.js → loaderPage.mjs} +3 -3
  73. package/dist/runtime/composables/useConfig.d.ts +1 -1
  74. package/dist/runtime/composables/useForm.d.ts +1 -1
  75. package/dist/runtime/composables/useTable.d.ts +2 -2
  76. package/dist/runtime/composables/{useTable.js → useTable.mjs} +1 -1
  77. package/dist/runtime/composables/{useUpload.js → useUpload.mjs} +1 -1
  78. package/dist/runtime/helpers/{apiListHelper.js → apiListHelper.mjs} +1 -1
  79. package/dist/runtime/helpers/{apiObjectHelper.js → apiObjectHelper.mjs} +1 -1
  80. package/dist/runtime/helpers/apiPageHelper.d.ts +1 -1
  81. package/dist/runtime/helpers/{apiPageHelper.js → apiPageHelper.mjs} +4 -4
  82. package/dist/runtime/ui.config/index.d.ts +16 -16
  83. package/dist/runtime/ui.config/index.mjs +16 -0
  84. package/dist/runtime/ui.config/{uploadDropzoneImage.js → uploadDropzoneImage.mjs} +1 -1
  85. package/dist/runtime/utils/ArrayHelper.d.ts +1 -1
  86. package/dist/runtime/utils/{ArrayHelper.spec.js → ArrayHelper.spec.mjs} +1 -1
  87. package/dist/runtime/utils/{FileHelper.spec.js → FileHelper.spec.mjs} +1 -1
  88. package/dist/runtime/utils/ObjectHelper.d.ts +2 -2
  89. package/dist/runtime/utils/{ObjectHelper.js → ObjectHelper.mjs} +2 -2
  90. package/dist/runtime/utils/{ObjectHelper.spec.js → ObjectHelper.spec.mjs} +1 -1
  91. package/dist/runtime/utils/ParamHelper.d.ts +1 -1
  92. package/dist/runtime/utils/{ParamHelper.spec.js → ParamHelper.spec.mjs} +1 -1
  93. package/dist/runtime/utils/{StringHelper.spec.js → StringHelper.spec.mjs} +1 -1
  94. package/dist/runtime/utils/{TimeHelper.spec.js → TimeHelper.spec.mjs} +1 -1
  95. package/dist/runtime/utils/{TimeHelper.thai.spec.js → TimeHelper.thai.spec.mjs} +1 -1
  96. package/dist/types.d.mts +16 -1
  97. package/dist/types.d.ts +16 -1
  98. package/package.json +92 -93
  99. package/dist/runtime/ui.config/index.js +0 -16
  100. /package/dist/runtime/components/Dropdown/{types.js → types.mjs} +0 -0
  101. /package/dist/runtime/components/FlexDeck/{types.js → types.mjs} +0 -0
  102. /package/dist/runtime/components/Form/InputCheckbox/{types.js → types.mjs} +0 -0
  103. /package/dist/runtime/components/Form/InputDateTime/{date_time_field.types.js → date_time_field.types.mjs} +0 -0
  104. /package/dist/runtime/components/Form/InputDateTimeRange/{date_range_time_field.types.js → date_range_time_field.types.mjs} +0 -0
  105. /package/dist/runtime/components/Form/InputNumber/{types.js → types.mjs} +0 -0
  106. /package/dist/runtime/components/Form/InputRadio/{types.js → types.mjs} +0 -0
  107. /package/dist/runtime/components/Form/InputSelect/{types.js → types.mjs} +0 -0
  108. /package/dist/runtime/components/Form/InputSelectMultiple/{types.js → types.mjs} +0 -0
  109. /package/dist/runtime/components/Form/InputStatic/{types.js → types.mjs} +0 -0
  110. /package/dist/runtime/components/Form/InputTags/{types.js → types.mjs} +0 -0
  111. /package/dist/runtime/components/Form/InputText/{types.js → types.mjs} +0 -0
  112. /package/dist/runtime/components/Form/InputTextarea/{types.js → types.mjs} +0 -0
  113. /package/dist/runtime/components/Form/InputToggle/{types.js → types.mjs} +0 -0
  114. /package/dist/runtime/components/Form/InputUploadDropzone/{types.js → types.mjs} +0 -0
  115. /package/dist/runtime/components/Form/InputUploadDropzoneAuto/{types.js → types.mjs} +0 -0
  116. /package/dist/runtime/components/Form/InputUploadDropzoneAutoMultiple/{types.js → types.mjs} +0 -0
  117. /package/dist/runtime/components/Form/InputUploadDropzoneImageAutoMultiple/{types.js → types.mjs} +0 -0
  118. /package/dist/runtime/components/Form/InputUploadFileClassic/{types.js → types.mjs} +0 -0
  119. /package/dist/runtime/components/Form/InputUploadFileClassicAuto/{types.js → types.mjs} +0 -0
  120. /package/dist/runtime/components/Form/InputUploadImageAuto/{types.js → types.mjs} +0 -0
  121. /package/dist/runtime/components/Form/InputWYSIWYG/{types.js → types.mjs} +0 -0
  122. /package/dist/runtime/components/Form/{types.js → types.mjs} +0 -0
  123. /package/dist/runtime/components/Table/{types.js → types.mjs} +0 -0
  124. /package/dist/runtime/composables/{useApp.js → useApp.mjs} +0 -0
  125. /package/dist/runtime/composables/{useConfig.js → useConfig.mjs} +0 -0
  126. /package/dist/runtime/composables/{useDialog.js → useDialog.mjs} +0 -0
  127. /package/dist/runtime/composables/{useFlexDeck.js → useFlexDeck.mjs} +0 -0
  128. /package/dist/runtime/composables/{useForm.js → useForm.mjs} +0 -0
  129. /package/dist/runtime/composables/{useNotification.js → useNotification.mjs} +0 -0
  130. /package/dist/runtime/composables/{useWatch.js → useWatch.mjs} +0 -0
  131. /package/dist/runtime/{core.config.js → core.config.mjs} +0 -0
  132. /package/dist/runtime/helpers/{componentHelper.js → componentHelper.mjs} +0 -0
  133. /package/dist/runtime/lib/{Requester.js → Requester.mjs} +0 -0
  134. /package/dist/runtime/{plugin.js → plugin.mjs} +0 -0
  135. /package/dist/runtime/{quill.plugin.js → quill.plugin.mjs} +0 -0
  136. /package/dist/runtime/types/{common.js → common.mjs} +0 -0
  137. /package/dist/runtime/types/{config.js → config.mjs} +0 -0
  138. /package/dist/runtime/types/{lib.js → lib.mjs} +0 -0
  139. /package/dist/runtime/ui.config/{alert.js → alert.mjs} +0 -0
  140. /package/dist/runtime/ui.config/{badge.js → badge.mjs} +0 -0
  141. /package/dist/runtime/ui.config/{breadcrumb.js → breadcrumb.mjs} +0 -0
  142. /package/dist/runtime/ui.config/{button.js → button.mjs} +0 -0
  143. /package/dist/runtime/ui.config/{buttonGroup.js → buttonGroup.mjs} +0 -0
  144. /package/dist/runtime/ui.config/{card.js → card.mjs} +0 -0
  145. /package/dist/runtime/ui.config/{checkbox.js → checkbox.mjs} +0 -0
  146. /package/dist/runtime/ui.config/{formGroup.js → formGroup.mjs} +0 -0
  147. /package/dist/runtime/ui.config/{icon.js → icon.mjs} +0 -0
  148. /package/dist/runtime/ui.config/{input.js → input.mjs} +0 -0
  149. /package/dist/runtime/ui.config/{modal.js → modal.mjs} +0 -0
  150. /package/dist/runtime/ui.config/{notification.js → notification.mjs} +0 -0
  151. /package/dist/runtime/ui.config/{pagination.js → pagination.mjs} +0 -0
  152. /package/dist/runtime/ui.config/{select.js → select.mjs} +0 -0
  153. /package/dist/runtime/ui.config/{selectMenu.js → selectMenu.mjs} +0 -0
  154. /package/dist/runtime/ui.config/{slideover.js → slideover.mjs} +0 -0
  155. /package/dist/runtime/ui.config/{table.js → table.mjs} +0 -0
  156. /package/dist/runtime/ui.config/{tabs.js → tabs.mjs} +0 -0
  157. /package/dist/runtime/ui.config/{tags.js → tags.mjs} +0 -0
  158. /package/dist/runtime/ui.config/{textarea.js → textarea.mjs} +0 -0
  159. /package/dist/runtime/ui.config/{toggle.js → toggle.mjs} +0 -0
  160. /package/dist/runtime/ui.config/{uploadFileDropzone.js → uploadFileDropzone.mjs} +0 -0
  161. /package/dist/runtime/ui.config/{uploadFileInputClassicAuto.js → uploadFileInputClassicAuto.mjs} +0 -0
  162. /package/dist/runtime/ui.config/{uploadImage.js → uploadImage.mjs} +0 -0
  163. /package/dist/runtime/utils/{ArrayHelper.js → ArrayHelper.mjs} +0 -0
  164. /package/dist/runtime/utils/{FileHelper.js → FileHelper.mjs} +0 -0
  165. /package/dist/runtime/utils/{ParamHelper.js → ParamHelper.mjs} +0 -0
  166. /package/dist/runtime/utils/{StringHelper.js → StringHelper.mjs} +0 -0
  167. /package/dist/runtime/utils/{TimeHelper.js → TimeHelper.mjs} +0 -0
  168. /package/dist/runtime/utils/{lodash.js → lodash.mjs} +0 -0
@@ -1,5 +1,5 @@
1
1
  import { type AxiosRequestConfig } from 'axios';
2
- import { type IFieldProps, type IFormFieldBase, type INPUT_TYPES } from '../types.js';
2
+ import { type IFieldProps, type IFormFieldBase, type INPUT_TYPES } from '../types';
3
3
  export interface IUploadDropzoneAutoProps extends IFieldProps {
4
4
  requestOptions: Omit<AxiosRequestConfig, 'baseURL'> & {
5
5
  baseURL: string;
@@ -1,241 +1,241 @@
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.value
29
- ? `${fileAllocate.selectedFileSizeMb.value} MB`
30
- : `${fileAllocate.selectedFileSizeKb.value} 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[responseURL!]"
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.value
69
- ? `${fileAllocate.selectedFileSizeMb.value} MB`
70
- : `${fileAllocate.selectedFileSizeKb.value} KB`
71
- }}
72
- </p>
73
- </div>
74
- <div :class="[ui.action.wrapper]">
75
- <Icon
76
- :name="ui.action.deleteIcon"
77
- :class="[ui.action.iconClass]"
78
- title="ลบไฟล์"
79
- @click="handleDeleteFile"
80
- />
81
- </div>
82
- </div>
83
- </div>
84
-
85
- <!-- Failed State -->
86
- <div
87
- v-if="selectedFile && (upload.status.value.isError || errMsg)"
88
- :class="[ui.onFailed.wrapper]"
89
- >
90
- <div :class="[ui.onFailed.failedImgWrapper]">
91
- <Icon
92
- :name="
93
- isImage(selectedFile)
94
- ? ui.onFailed.failedImgIcon || ui.default.placeholderImgIcon
95
- : ui.onFailed.failedFileIcon || ui.default.filePreviewIcon
96
- "
97
- :class="[ui.onFailed.failedIconClass]"
98
- />
99
- </div>
100
- <div :class="[ui.onFailed.textWrapper]">
101
- <div class="truncate">
102
- <h1 class="truncate font-bold" :title="selectedFile?.name">
103
- {{ StringHelper.truncate(selectedFile?.name, 40) }}
104
- </h1>
105
- <p class="text-danger truncate font-light">
106
- {{ errMsg ? errMsg : uploadFailedLabel }}
107
- </p>
108
- <Button
109
- v-if="upload.status.value.isError"
110
- variant="ghost"
111
- :label="retryLabel"
112
- :leading-icon="ui.action.retryIcon"
113
- :class="[ui.action.retryBtnClass]"
114
- size="sm"
115
- @click="handleRetryUpload"
116
- />
117
- </div>
118
- <div :class="[ui.action.wrapper]">
119
- <Icon
120
- title="ลบไฟล์"
121
- :name="ui.action.deleteIcon"
122
- :class="[ui.action.deleteIconClass]"
123
- @click="handleDeleteFile"
124
- />
125
- </div>
126
- </div>
127
- </div>
128
- </div>
129
- </template>
130
- <script lang="ts" setup>
131
- import {
132
- checkFileType,
133
- checkMaxSize,
134
- isImage,
135
- useFileAllocate,
136
- useFileProgress,
137
- } from '#core/helpers/componentHelper'
138
- import { type uploadFileDropzone } from '#core/ui.config'
139
- import type { IUploadDropzoneAutoMultipleProps } from '#core/components/Form/InputUploadDropzoneAutoMultiple/types'
140
- import {
141
- type IUploadRequest,
142
- onMounted,
143
- ref,
144
- toRef,
145
- StringHelper,
146
- useUploadLoader,
147
- useWatchTrue,
148
- } from '#imports'
149
- import i18next from 'i18next'
150
-
151
- const emits = defineEmits(['success', 'error', 'delete'])
152
- const props = defineProps<
153
- {
154
- ui: typeof uploadFileDropzone
155
- selectedFile: File
156
- } & IUploadDropzoneAutoMultipleProps
157
- >()
158
-
159
- const request: IUploadRequest = {
160
- pathURL: props.uploadPathURL,
161
- requestOptions: props.requestOptions,
162
- }
163
-
164
- const upload = useUploadLoader(request)
165
- const errMsg = ref<string>('')
166
-
167
- const { onUploadProgress, onDownloadProgress, percent } = useFileProgress()
168
- const fileAllocate = useFileAllocate(toRef(props.selectedFile), props)
169
-
170
- const handleDeleteFile = () => {
171
- emits('delete')
172
- }
173
-
174
- const handleRetryUpload = () => {
175
- const formData = new FormData()
176
-
177
- formData.append(props.bodyKey!, props.selectedFile)
178
- upload.run(formData, { data: { onUploadProgress, onDownloadProgress } })
179
- }
180
-
181
- const handleCheckFileCondition = (file: File | undefined): boolean => {
182
- if (!file) return false
183
-
184
- const fileType = checkFileType(file, fileAllocate.acceptFile.value ?? '')
185
-
186
- if (!fileType) {
187
- errMsg.value = i18next.t('custom:invalid_file_type')
188
-
189
- return false
190
- }
191
-
192
- const maxSize = checkMaxSize(file, fileAllocate.acceptFileSizeKb.value)
193
-
194
- if (!maxSize) {
195
- if (fileAllocate.isAcceptFileUseMb.value) {
196
- errMsg.value = i18next.t('custom:invalid_file_size_mb', {
197
- size: fileAllocate.acceptFileSizeMb.value,
198
- })
199
- } else {
200
- errMsg.value = i18next.t('custom:invalid_file_size_kb', {
201
- size: fileAllocate.acceptFileSizeKb.value,
202
- })
203
- }
204
-
205
- return false
206
- }
207
-
208
- errMsg.value = ''
209
-
210
- return true
211
- }
212
-
213
- onMounted(() => {
214
- const result = handleCheckFileCondition(props.selectedFile)
215
-
216
- if (result) {
217
- const formData = new FormData()
218
-
219
- formData.append(props.bodyKey!, props.selectedFile)
220
- upload.run(formData, { data: { onUploadProgress, onDownloadProgress } })
221
- }
222
- })
223
-
224
- useWatchTrue(
225
- () => upload.status.value.isSuccess,
226
- () => {
227
- emits('success', {
228
- ...upload.data.value,
229
- name: props.selectedFile.name,
230
- size: +props.selectedFile.size,
231
- })
232
- }
233
- )
234
-
235
- useWatchTrue(
236
- () => upload.status.value.isError,
237
- () => {
238
- emits('error', upload.status.value.errorData)
239
- }
240
- )
241
- </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.value
29
+ ? `${fileAllocate.selectedFileSizeMb.value} MB`
30
+ : `${fileAllocate.selectedFileSizeKb.value} 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[responseURL!]"
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.value
69
+ ? `${fileAllocate.selectedFileSizeMb.value} MB`
70
+ : `${fileAllocate.selectedFileSizeKb.value} KB`
71
+ }}
72
+ </p>
73
+ </div>
74
+ <div :class="[ui.action.wrapper]">
75
+ <Icon
76
+ :name="ui.action.deleteIcon"
77
+ :class="[ui.action.iconClass]"
78
+ title="ลบไฟล์"
79
+ @click="handleDeleteFile"
80
+ />
81
+ </div>
82
+ </div>
83
+ </div>
84
+
85
+ <!-- Failed State -->
86
+ <div
87
+ v-if="selectedFile && (upload.status.value.isError || errMsg)"
88
+ :class="[ui.onFailed.wrapper]"
89
+ >
90
+ <div :class="[ui.onFailed.failedImgWrapper]">
91
+ <Icon
92
+ :name="
93
+ isImage(selectedFile)
94
+ ? ui.onFailed.failedImgIcon || ui.default.placeholderImgIcon
95
+ : ui.onFailed.failedFileIcon || ui.default.filePreviewIcon
96
+ "
97
+ :class="[ui.onFailed.failedIconClass]"
98
+ />
99
+ </div>
100
+ <div :class="[ui.onFailed.textWrapper]">
101
+ <div class="truncate">
102
+ <h1 class="truncate font-bold" :title="selectedFile?.name">
103
+ {{ StringHelper.truncate(selectedFile?.name, 40) }}
104
+ </h1>
105
+ <p class="text-danger truncate font-light">
106
+ {{ errMsg ? errMsg : uploadFailedLabel }}
107
+ </p>
108
+ <Button
109
+ v-if="upload.status.value.isError"
110
+ variant="ghost"
111
+ :label="retryLabel"
112
+ :leading-icon="ui.action.retryIcon"
113
+ :class="[ui.action.retryBtnClass]"
114
+ size="sm"
115
+ @click="handleRetryUpload"
116
+ />
117
+ </div>
118
+ <div :class="[ui.action.wrapper]">
119
+ <Icon
120
+ title="ลบไฟล์"
121
+ :name="ui.action.deleteIcon"
122
+ :class="[ui.action.deleteIconClass]"
123
+ @click="handleDeleteFile"
124
+ />
125
+ </div>
126
+ </div>
127
+ </div>
128
+ </div>
129
+ </template>
130
+ <script lang="ts" setup>
131
+ import {
132
+ checkFileType,
133
+ checkMaxSize,
134
+ isImage,
135
+ useFileAllocate,
136
+ useFileProgress,
137
+ } from '#core/helpers/componentHelper'
138
+ import { type uploadFileDropzone } from '#core/ui.config'
139
+ import type { IUploadDropzoneAutoMultipleProps } from '#core/components/Form/InputUploadDropzoneAutoMultiple/types'
140
+ import {
141
+ type IUploadRequest,
142
+ onMounted,
143
+ ref,
144
+ toRef,
145
+ StringHelper,
146
+ useUploadLoader,
147
+ useWatchTrue,
148
+ } from '#imports'
149
+ import i18next from 'i18next'
150
+
151
+ const emits = defineEmits(['success', 'error', 'delete'])
152
+ const props = defineProps<
153
+ {
154
+ ui: typeof uploadFileDropzone
155
+ selectedFile: File
156
+ } & IUploadDropzoneAutoMultipleProps
157
+ >()
158
+
159
+ const request: IUploadRequest = {
160
+ pathURL: props.uploadPathURL,
161
+ requestOptions: props.requestOptions,
162
+ }
163
+
164
+ const upload = useUploadLoader(request)
165
+ const errMsg = ref<string>('')
166
+
167
+ const { onUploadProgress, onDownloadProgress, percent } = useFileProgress()
168
+ const fileAllocate = useFileAllocate(toRef(props.selectedFile), props)
169
+
170
+ const handleDeleteFile = () => {
171
+ emits('delete')
172
+ }
173
+
174
+ const handleRetryUpload = () => {
175
+ const formData = new FormData()
176
+
177
+ formData.append(props.bodyKey!, props.selectedFile)
178
+ upload.run(formData, { data: { onUploadProgress, onDownloadProgress } })
179
+ }
180
+
181
+ const handleCheckFileCondition = (file: File | undefined): boolean => {
182
+ if (!file) return false
183
+
184
+ const fileType = checkFileType(file, fileAllocate.acceptFile.value ?? '')
185
+
186
+ if (!fileType) {
187
+ errMsg.value = i18next.t('custom:invalid_file_type')
188
+
189
+ return false
190
+ }
191
+
192
+ const maxSize = checkMaxSize(file, fileAllocate.acceptFileSizeKb.value)
193
+
194
+ if (!maxSize) {
195
+ if (fileAllocate.isAcceptFileUseMb.value) {
196
+ errMsg.value = i18next.t('custom:invalid_file_size_mb', {
197
+ size: fileAllocate.acceptFileSizeMb.value,
198
+ })
199
+ } else {
200
+ errMsg.value = i18next.t('custom:invalid_file_size_kb', {
201
+ size: fileAllocate.acceptFileSizeKb.value,
202
+ })
203
+ }
204
+
205
+ return false
206
+ }
207
+
208
+ errMsg.value = ''
209
+
210
+ return true
211
+ }
212
+
213
+ onMounted(() => {
214
+ const result = handleCheckFileCondition(props.selectedFile)
215
+
216
+ if (result) {
217
+ const formData = new FormData()
218
+
219
+ formData.append(props.bodyKey!, props.selectedFile)
220
+ upload.run(formData, { data: { onUploadProgress, onDownloadProgress } })
221
+ }
222
+ })
223
+
224
+ useWatchTrue(
225
+ () => upload.status.value.isSuccess,
226
+ () => {
227
+ emits('success', {
228
+ ...upload.data.value,
229
+ name: props.selectedFile.name,
230
+ size: +props.selectedFile.size,
231
+ })
232
+ }
233
+ )
234
+
235
+ useWatchTrue(
236
+ () => upload.status.value.isError,
237
+ () => {
238
+ emits('error', upload.status.value.errorData)
239
+ }
240
+ )
241
+ </script>
@@ -1,89 +1,89 @@
1
- <template>
2
- <div :class="[ui.base, ui.background.default]">
3
- <div :class="[ui.onPreview.wrapper]">
4
- <div :class="[ui.onPreview.previewImgWrapper]">
5
- <div v-if="isImageFromPath(selectedFile.path)" class="size-full overflow-hidden">
6
- <img
7
- :src="selectedFile.url"
8
- :class="[ui.onPreview.previewImgClass]"
9
- alt="image-preview"
10
- />
11
- </div>
12
- <div v-else>
13
- <Icon
14
- :name="ui.onPreview.previewFileIcon || ui.default.filePreviewIcon"
15
- :class="[ui.onPreview.previewFileClass]"
16
- />
17
- </div>
18
- </div>
19
- <div :class="[ui.onPreview.textWrapper]">
20
- <div class="truncate">
21
- <h1 class="truncate font-bold" :title="selectedFile?.name">
22
- {{ StringHelper.truncate(selectedFile?.name, 40) }}
23
- </h1>
24
- <p class="truncate text-sm font-light text-gray-400">
25
- {{
26
- fileAllocate.isSelectedFileUseMb.value
27
- ? `${fileAllocate.selectedFileSizeMb.value} MB`
28
- : `${fileAllocate.selectedFileSizeKb.value} KB`
29
- }}
30
- </p>
31
- </div>
32
- <div :class="[ui.action.wrapper]">
33
- <Icon
34
- v-if="isImageFromPath(selectedFile.path)"
35
- :name="ui.action.previewIcon"
36
- :class="[ui.action.iconClass]"
37
- title="ดูตัวอย่าง"
38
- @click="() => (isPreviewOpen = true)"
39
- />
40
- <Icon
41
- :name="ui.action.downloadIcon"
42
- :class="[ui.action.iconClass]"
43
- title="ดาวน์โหลดไฟล์"
44
- @click="handleDownloadFile"
45
- />
46
- <Icon
47
- :name="ui.action.deleteIcon"
48
- :class="[ui.action.iconClass]"
49
- title="ลบไฟล์"
50
- @click="handleDeleteFile"
51
- />
52
- <Modal v-model="isPreviewOpen" :title="selectedFile?.name">
53
- <img
54
- :src="selectedFile.url"
55
- alt="image-preview"
56
- class="mx-auto max-w-full rounded-lg"
57
- />
58
- </Modal>
59
- </div>
60
- </div>
61
- </div>
62
- </div>
63
- </template>
64
- <script lang="ts" setup>
65
- import { downloadFileFromURL, isImageFromPath, useFileSize } from '#core/helpers/componentHelper'
66
- import { type uploadFileDropzone } from '#core/ui.config'
67
- import type { IUploadDropzoneAutoMultipleProps } from '#core/components/Form/InputUploadDropzoneAutoMultiple/types'
68
- import { ref, StringHelper } from '#imports'
69
- import type { IFileValue } from '#core/components/Form/types'
70
-
71
- const emits = defineEmits(['delete'])
72
- const props = defineProps<
73
- {
74
- ui: typeof uploadFileDropzone
75
- selectedFile: IFileValue
76
- } & IUploadDropzoneAutoMultipleProps
77
- >()
78
-
79
- const isPreviewOpen = ref<boolean>(false)
80
- const fileAllocate = useFileSize(props.selectedFile.size)
81
-
82
- const handleDeleteFile = () => {
83
- emits('delete')
84
- }
85
-
86
- const handleDownloadFile = () => {
87
- downloadFileFromURL(props.selectedFile.url, props.selectedFile.name)
88
- }
89
- </script>
1
+ <template>
2
+ <div :class="[ui.base, ui.background.default]">
3
+ <div :class="[ui.onPreview.wrapper]">
4
+ <div :class="[ui.onPreview.previewImgWrapper]">
5
+ <div v-if="isImageFromPath(selectedFile.path)" class="size-full overflow-hidden">
6
+ <img
7
+ :src="selectedFile.url"
8
+ :class="[ui.onPreview.previewImgClass]"
9
+ alt="image-preview"
10
+ />
11
+ </div>
12
+ <div v-else>
13
+ <Icon
14
+ :name="ui.onPreview.previewFileIcon || ui.default.filePreviewIcon"
15
+ :class="[ui.onPreview.previewFileClass]"
16
+ />
17
+ </div>
18
+ </div>
19
+ <div :class="[ui.onPreview.textWrapper]">
20
+ <div class="truncate">
21
+ <h1 class="truncate font-bold" :title="selectedFile?.name">
22
+ {{ StringHelper.truncate(selectedFile?.name, 40) }}
23
+ </h1>
24
+ <p class="truncate text-sm font-light text-gray-400">
25
+ {{
26
+ fileAllocate.isSelectedFileUseMb.value
27
+ ? `${fileAllocate.selectedFileSizeMb.value} MB`
28
+ : `${fileAllocate.selectedFileSizeKb.value} KB`
29
+ }}
30
+ </p>
31
+ </div>
32
+ <div :class="[ui.action.wrapper]">
33
+ <Icon
34
+ v-if="isImageFromPath(selectedFile.path)"
35
+ :name="ui.action.previewIcon"
36
+ :class="[ui.action.iconClass]"
37
+ title="ดูตัวอย่าง"
38
+ @click="() => (isPreviewOpen = true)"
39
+ />
40
+ <Icon
41
+ :name="ui.action.downloadIcon"
42
+ :class="[ui.action.iconClass]"
43
+ title="ดาวน์โหลดไฟล์"
44
+ @click="handleDownloadFile"
45
+ />
46
+ <Icon
47
+ :name="ui.action.deleteIcon"
48
+ :class="[ui.action.iconClass]"
49
+ title="ลบไฟล์"
50
+ @click="handleDeleteFile"
51
+ />
52
+ <Modal v-model="isPreviewOpen" :title="selectedFile?.name">
53
+ <img
54
+ :src="selectedFile.url"
55
+ alt="image-preview"
56
+ class="mx-auto max-w-full rounded-lg"
57
+ />
58
+ </Modal>
59
+ </div>
60
+ </div>
61
+ </div>
62
+ </div>
63
+ </template>
64
+ <script lang="ts" setup>
65
+ import { downloadFileFromURL, isImageFromPath, useFileSize } from '#core/helpers/componentHelper'
66
+ import { type uploadFileDropzone } from '#core/ui.config'
67
+ import type { IUploadDropzoneAutoMultipleProps } from '#core/components/Form/InputUploadDropzoneAutoMultiple/types'
68
+ import { ref, StringHelper } from '#imports'
69
+ import type { IFileValue } from '#core/components/Form/types'
70
+
71
+ const emits = defineEmits(['delete'])
72
+ const props = defineProps<
73
+ {
74
+ ui: typeof uploadFileDropzone
75
+ selectedFile: IFileValue
76
+ } & IUploadDropzoneAutoMultipleProps
77
+ >()
78
+
79
+ const isPreviewOpen = ref<boolean>(false)
80
+ const fileAllocate = useFileSize(props.selectedFile.size)
81
+
82
+ const handleDeleteFile = () => {
83
+ emits('delete')
84
+ }
85
+
86
+ const handleDownloadFile = () => {
87
+ downloadFileFromURL(props.selectedFile.url, props.selectedFile.name)
88
+ }
89
+ </script>