@finema/core 1.4.152 → 1.4.154

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 +10 -2
  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,164 +1,164 @@
1
- <template>
2
- <FieldWrapper v-bind="wrapperProps">
3
- <div class="space-y-3">
4
- <div
5
- ref="dropzoneRef"
6
- :class="[
7
- ui.base,
8
- {
9
- [ui.disabled]: isDisabled,
10
- [ui.background.default]: !isOverDropZone && !isDisabled,
11
- [ui.background.dragover]: isOverDropZone && !isDisabled,
12
- },
13
- ]"
14
- >
15
- <input
16
- ref="fileInputRef"
17
- type="file"
18
- class="hidden"
19
- :name="name"
20
- :accept="acceptFile"
21
- :disabled="isDisabled"
22
- multiple
23
- @change="handleChange"
24
- />
25
- <div :class="[ui.wrapper]">
26
- <div :class="[ui.placeholderWrapper]">
27
- <Icon :name="ui.default.uploadIcon" :class="[ui.labelIcon]" />
28
- <div :class="[ui.labelWrapper]">
29
- <p class="text-primary cursor-pointer" @click="handleOpenFile">
30
- {{ selectFileLabel }}
31
- </p>
32
- <p>{{ selectFileSubLabel }}</p>
33
- </div>
34
- <p v-if="placeholder" :class="[ui.placeholder]">{{ placeholder }}</p>
35
- </div>
36
- </div>
37
- </div>
38
- <ItemView
39
- v-for="(file, index) in value"
40
- :key="file.url"
41
- v-bind="$props"
42
- :ui="ui"
43
- :selected-file="file"
44
- @delete="handleDeleteFileView(index)"
45
- />
46
- <ItemUpload
47
- v-for="(file, index) in selectedFiles"
48
- :key="file.key"
49
- v-bind="$props"
50
- :ui="ui"
51
- :selected-file="file.file"
52
- @success="handleSuccess(index, $event)"
53
- @delete="handleDeleteFile(index)"
54
- @error="handleError(index, $event)"
55
- />
56
- </div>
57
- </FieldWrapper>
58
- </template>
59
-
60
- <script lang="ts" setup>
61
- import { useDropZone } from '@vueuse/core'
62
- import { type IUploadDropzoneAutoMultipleProps } from './types'
63
- import FieldWrapper from '#core/components/Form/FieldWrapper.vue'
64
- import { useFieldHOC } from '#core/composables/useForm'
65
- import { _get, computed, ref, toRef, useUI, useUiConfig, StringHelper, ArrayHelper } from '#imports'
66
- import { uploadFileDropzone } from '#core/ui.config'
67
- import ItemView from './ItemView.vue'
68
- import ItemUpload from './ItemUpload.vue'
69
- import type { IFileValue } from '#core/components/Form/types'
70
-
71
- const config = useUiConfig<typeof uploadFileDropzone>(uploadFileDropzone, 'uploadFileDropzone')
72
- const props = withDefaults(defineProps<IUploadDropzoneAutoMultipleProps>(), {
73
- bodyKey: 'file',
74
- responseURL: 'url',
75
- responsePath: 'path',
76
- selectFileLabel: 'คลิกเพื่อเลือกไฟล์',
77
- selectFileSubLabel: 'หรือ ลากและวางที่นี่',
78
- retryLabel: 'ลองอีกครั้ง',
79
- uploadingLabel: 'กำลังอัพโหลด...',
80
- uploadFailedLabel: 'อัพโหลดล้มเหลว, กรุณาลองอีกครั้ง',
81
- })
82
-
83
- const emits = defineEmits(['change', 'success', 'delete'])
84
- const selectedFiles = ref<Array<{ file: File; key: string }>>([])
85
- const { wrapperProps, handleChange: onChange, setErrors, value } = useFieldHOC<IFileValue[]>(props)
86
-
87
- const { ui } = useUI('uploadFileDropzone', toRef(props, 'ui'), config)
88
-
89
- const fileInputRef = ref<HTMLInputElement | null>()
90
- const dropzoneRef = ref<HTMLDivElement>()
91
-
92
- const acceptFile = computed(() =>
93
- typeof props.accept === 'string' ? props.accept : props.accept?.join(',')
94
- )
95
-
96
- const onDrop = (files: File[] | null) => {
97
- if (props.isDisabled || files?.length === 0 || !files) return
98
-
99
- for (const file of files) {
100
- selectedFiles.value = [
101
- {
102
- file,
103
- key: StringHelper.genString(),
104
- },
105
- ...selectedFiles.value,
106
- ]
107
-
108
- emits('change', value.value)
109
- }
110
- }
111
-
112
- const { isOverDropZone } = useDropZone(dropzoneRef as unknown as HTMLElement, {
113
- onDrop,
114
- })
115
-
116
- const handleChange = (e: Event) => {
117
- if (props.isDisabled) return
118
-
119
- for (const file of (e.target as HTMLInputElement).files ?? []) {
120
- selectedFiles.value = [
121
- {
122
- file,
123
- key: StringHelper.genString(),
124
- },
125
- ...selectedFiles.value,
126
- ]
127
-
128
- emits('change', value.value)
129
- }
130
-
131
- fileInputRef.value?.value && (fileInputRef.value.value = '')
132
- }
133
-
134
- const handleOpenFile = () => {
135
- fileInputRef.value?.click()
136
- }
137
-
138
- const handleDeleteFile = (index: number) => {
139
- selectedFiles.value.splice(index, 1)
140
- }
141
-
142
- const handleDeleteFileView = (index: number) => {
143
- value.value.splice(index, 1)
144
- emits('delete')
145
- }
146
-
147
- const handleError = (index: number, error: any) => {}
148
-
149
- const handleSuccess = (index: number, res: any) => {
150
- value.value = [
151
- {
152
- url: _get(res, props.responseURL),
153
- path: _get(res, props.responsePath),
154
- name: res.name,
155
- size: res.size,
156
- },
157
- ...ArrayHelper.toArray(value.value),
158
- ]
159
-
160
- selectedFiles.value.splice(index, 1)
161
- emits('change', value.value)
162
- emits('success', value.value)
163
- }
164
- </script>
1
+ <template>
2
+ <FieldWrapper v-bind="wrapperProps">
3
+ <div class="space-y-3">
4
+ <div
5
+ ref="dropzoneRef"
6
+ :class="[
7
+ ui.base,
8
+ {
9
+ [ui.disabled]: isDisabled,
10
+ [ui.background.default]: !isOverDropZone && !isDisabled,
11
+ [ui.background.dragover]: isOverDropZone && !isDisabled,
12
+ },
13
+ ]"
14
+ >
15
+ <input
16
+ ref="fileInputRef"
17
+ type="file"
18
+ class="hidden"
19
+ :name="name"
20
+ :accept="acceptFile"
21
+ :disabled="isDisabled"
22
+ multiple
23
+ @change="handleChange"
24
+ />
25
+ <div :class="[ui.wrapper]">
26
+ <div :class="[ui.placeholderWrapper]">
27
+ <Icon :name="ui.default.uploadIcon" :class="[ui.labelIcon]" />
28
+ <div :class="[ui.labelWrapper]">
29
+ <p class="text-primary cursor-pointer" @click="handleOpenFile">
30
+ {{ selectFileLabel }}
31
+ </p>
32
+ <p>{{ selectFileSubLabel }}</p>
33
+ </div>
34
+ <p v-if="placeholder" :class="[ui.placeholder]">{{ placeholder }}</p>
35
+ </div>
36
+ </div>
37
+ </div>
38
+ <ItemView
39
+ v-for="(file, index) in value"
40
+ :key="file.url"
41
+ v-bind="$props"
42
+ :ui="ui"
43
+ :selected-file="file"
44
+ @delete="handleDeleteFileView(index)"
45
+ />
46
+ <ItemUpload
47
+ v-for="(file, index) in selectedFiles"
48
+ :key="file.key"
49
+ v-bind="$props"
50
+ :ui="ui"
51
+ :selected-file="file.file"
52
+ @success="handleSuccess(index, $event)"
53
+ @delete="handleDeleteFile(index)"
54
+ @error="handleError(index, $event)"
55
+ />
56
+ </div>
57
+ </FieldWrapper>
58
+ </template>
59
+
60
+ <script lang="ts" setup>
61
+ import { useDropZone } from '@vueuse/core'
62
+ import { type IUploadDropzoneAutoMultipleProps } from './types'
63
+ import FieldWrapper from '#core/components/Form/FieldWrapper.vue'
64
+ import { useFieldHOC } from '#core/composables/useForm'
65
+ import { _get, computed, ref, toRef, useUI, useUiConfig, StringHelper, ArrayHelper } from '#imports'
66
+ import { uploadFileDropzone } from '#core/ui.config'
67
+ import ItemView from './ItemView.vue'
68
+ import ItemUpload from './ItemUpload.vue'
69
+ import type { IFileValue } from '#core/components/Form/types'
70
+
71
+ const config = useUiConfig<typeof uploadFileDropzone>(uploadFileDropzone, 'uploadFileDropzone')
72
+ const props = withDefaults(defineProps<IUploadDropzoneAutoMultipleProps>(), {
73
+ bodyKey: 'file',
74
+ responseURL: 'url',
75
+ responsePath: 'path',
76
+ selectFileLabel: 'คลิกเพื่อเลือกไฟล์',
77
+ selectFileSubLabel: 'หรือ ลากและวางที่นี่',
78
+ retryLabel: 'ลองอีกครั้ง',
79
+ uploadingLabel: 'กำลังอัพโหลด...',
80
+ uploadFailedLabel: 'อัพโหลดล้มเหลว, กรุณาลองอีกครั้ง',
81
+ })
82
+
83
+ const emits = defineEmits(['change', 'success', 'delete'])
84
+ const selectedFiles = ref<Array<{ file: File; key: string }>>([])
85
+ const { wrapperProps, handleChange: onChange, setErrors, value } = useFieldHOC<IFileValue[]>(props)
86
+
87
+ const { ui } = useUI('uploadFileDropzone', toRef(props, 'ui'), config)
88
+
89
+ const fileInputRef = ref<HTMLInputElement | null>()
90
+ const dropzoneRef = ref<HTMLDivElement>()
91
+
92
+ const acceptFile = computed(() =>
93
+ typeof props.accept === 'string' ? props.accept : props.accept?.join(',')
94
+ )
95
+
96
+ const onDrop = (files: File[] | null) => {
97
+ if (props.isDisabled || files?.length === 0 || !files) return
98
+
99
+ for (const file of files) {
100
+ selectedFiles.value = [
101
+ {
102
+ file,
103
+ key: StringHelper.genString(),
104
+ },
105
+ ...selectedFiles.value,
106
+ ]
107
+
108
+ emits('change', value.value)
109
+ }
110
+ }
111
+
112
+ const { isOverDropZone } = useDropZone(dropzoneRef as unknown as HTMLElement, {
113
+ onDrop,
114
+ })
115
+
116
+ const handleChange = (e: Event) => {
117
+ if (props.isDisabled) return
118
+
119
+ for (const file of (e.target as HTMLInputElement).files ?? []) {
120
+ selectedFiles.value = [
121
+ {
122
+ file,
123
+ key: StringHelper.genString(),
124
+ },
125
+ ...selectedFiles.value,
126
+ ]
127
+
128
+ emits('change', value.value)
129
+ }
130
+
131
+ fileInputRef.value?.value && (fileInputRef.value.value = '')
132
+ }
133
+
134
+ const handleOpenFile = () => {
135
+ fileInputRef.value?.click()
136
+ }
137
+
138
+ const handleDeleteFile = (index: number) => {
139
+ selectedFiles.value.splice(index, 1)
140
+ }
141
+
142
+ const handleDeleteFileView = (index: number) => {
143
+ value.value.splice(index, 1)
144
+ emits('delete')
145
+ }
146
+
147
+ const handleError = (index: number, error: any) => {}
148
+
149
+ const handleSuccess = (index: number, res: any) => {
150
+ value.value = [
151
+ {
152
+ url: _get(res, props.responseURL),
153
+ path: _get(res, props.responsePath),
154
+ name: res.name,
155
+ size: res.size,
156
+ },
157
+ ...ArrayHelper.toArray(value.value),
158
+ ]
159
+
160
+ selectedFiles.value.splice(index, 1)
161
+ emits('change', value.value)
162
+ emits('success', value.value)
163
+ }
164
+ </script>
@@ -1,5 +1,5 @@
1
1
  import { type AxiosRequestConfig } from 'axios';
2
- import { type IFieldProps, type IFileValue, type IFormFieldBase, type INPUT_TYPES } from '../types.js';
2
+ import { type IFieldProps, type IFileValue, type IFormFieldBase, type INPUT_TYPES } from '../types';
3
3
  export interface IUploadDropzoneAutoMultipleProps extends IFieldProps {
4
4
  requestOptions: Omit<AxiosRequestConfig, 'baseURL'> & {
5
5
  baseURL: string;
@@ -1,161 +1,161 @@
1
- <template>
2
- <div :class="[ui.imageItem.wrapper]">
3
- <div v-if="isAddingBtn" class="w-full">
4
- <div :class="[ui.action.addingWrapper]" @click="$emit('add')">
5
- <Icon :name="ui.action.addingIcon" :class="[ui.action.addingBtnClass]" />
6
- <p :class="[ui.action.addingTextClass]">{{ uploadAddLabel }}</p>
7
- </div>
8
- </div>
9
-
10
- <!-- Loading State -->
11
- <div v-if="selectedFile && upload.status.value.isLoading" class="w-full">
12
- <div :class="[ui.imageItem.onLoading.wrapper]">
13
- <div :class="[ui.imageItem.onLoading.percentClass]">{{ percent }}%</div>
14
- <UProgress :value="percent" />
15
- </div>
16
- </div>
17
-
18
- <!-- Success State -->
19
- <div v-if="selectedFile && upload.status.value.isSuccess" class="w-full">
20
- <div :class="[ui.imageItem.onPreview.wrapper]">
21
- <img
22
- :class="[ui.imageItem.onPreview.previewImgClass]"
23
- :src="upload.data.value[responseURL!]"
24
- alt="img"
25
- />
26
- <div :class="[ui.imageItem.onPreview.previewActionWrapper]">
27
- <Icon
28
- title="ลบไฟล์"
29
- :name="ui.action.deleteIcon"
30
- :class="[ui.imageItem.onPreview.actionBtnClass]"
31
- @click="handleDeleteFile"
32
- />
33
- </div>
34
- </div>
35
-
36
- <div :class="[ui.imageItem.onPreview.previewTextWrapper]">
37
- <p :class="[ui.imageItem.onPreview.previewText]">{{ selectedFile.name }}</p>
38
- </div>
39
- </div>
40
-
41
- <!-- Failed State -->
42
- <div v-if="selectedFile && upload.status.value.isError" class="w-full">
43
- <div :class="[ui.imageItem.onFailed.wrapper]">
44
- <img
45
- :class="[ui.imageItem.onFailed.failedImgClass]"
46
- :src="generateURL(selectedFile)"
47
- alt="img"
48
- />
49
- <div :class="[ui.imageItem.onFailed.failedActionWrapper]">
50
- <Icon
51
- title="ลบไฟล์"
52
- :name="ui.action.deleteIcon"
53
- :class="[ui.imageItem.onFailed.actionBtnClass]"
54
- @click="handleDeleteFile"
55
- />
56
- </div>
57
- </div>
58
- </div>
59
- </div>
60
- </template>
61
-
62
- <script lang="ts" setup>
63
- import {
64
- checkFileType,
65
- checkMaxSize,
66
- generateURL,
67
- useFileAllocate,
68
- useFileProgress,
69
- } from '#core/helpers/componentHelper'
70
- import { type uploadFileDropzoneImage } from '#core/ui.config'
71
- import type { IUploadDropzoneImageAutoMultipleProps } from '#core/components/Form/InputUploadDropzoneImageAutoMultiple/types'
72
- import { type IUploadRequest, onMounted, ref, toRef, useUploadLoader, useWatchTrue } from '#imports'
73
- import i18next from 'i18next'
74
-
75
- const emits = defineEmits(['success', 'error', 'delete', 'add'])
76
- const props = defineProps<
77
- {
78
- ui: typeof uploadFileDropzoneImage
79
- selectedFile?: File
80
- isAddingBtn?: boolean
81
- } & IUploadDropzoneImageAutoMultipleProps
82
- >()
83
-
84
- const request: IUploadRequest = {
85
- pathURL: props.uploadPathURL,
86
- requestOptions: props.requestOptions,
87
- }
88
-
89
- const upload = useUploadLoader(request)
90
- const errMsg = ref<string>('')
91
-
92
- const { onUploadProgress, onDownloadProgress, percent } = useFileProgress()
93
- const fileAllocate = useFileAllocate(toRef(props.selectedFile), props)
94
-
95
- const handleDeleteFile = () => {
96
- emits('delete')
97
- }
98
-
99
- const handleCheckFileCondition = (file: File | undefined): boolean => {
100
- if (!file) return false
101
-
102
- const fileType = checkFileType(file, fileAllocate.acceptFile.value ?? '')
103
-
104
- if (!fileType) {
105
- errMsg.value = i18next.t('custom:invalid_file_type')
106
-
107
- return false
108
- }
109
-
110
- const maxSize = checkMaxSize(file, fileAllocate.acceptFileSizeKb.value)
111
-
112
- if (!maxSize) {
113
- if (fileAllocate.isAcceptFileUseMb.value) {
114
- errMsg.value = i18next.t('custom:invalid_file_size_mb', {
115
- size: fileAllocate.acceptFileSizeMb.value,
116
- })
117
- } else {
118
- errMsg.value = i18next.t('custom:invalid_file_size_kb', {
119
- size: fileAllocate.acceptFileSizeKb.value,
120
- })
121
- }
122
-
123
- return false
124
- }
125
-
126
- errMsg.value = ''
127
-
128
- return true
129
- }
130
-
131
- onMounted(() => {
132
- if (props.isAddingBtn) return
133
-
134
- const result = handleCheckFileCondition(props.selectedFile)
135
-
136
- if (result) {
137
- const formData = new FormData()
138
-
139
- formData.append(props.bodyKey!, props.selectedFile!)
140
- upload.run(formData, { data: { onUploadProgress, onDownloadProgress } })
141
- }
142
- })
143
-
144
- useWatchTrue(
145
- () => upload.status.value.isSuccess,
146
- () => {
147
- emits('success', {
148
- ...upload.data.value,
149
- name: props.selectedFile?.name,
150
- size: +(props.selectedFile?.size || 0),
151
- })
152
- }
153
- )
154
-
155
- useWatchTrue(
156
- () => upload.status.value.isError,
157
- () => {
158
- emits('error', upload.status.value.errorData)
159
- }
160
- )
161
- </script>
1
+ <template>
2
+ <div :class="[ui.imageItem.wrapper]">
3
+ <div v-if="isAddingBtn" class="w-full">
4
+ <div :class="[ui.action.addingWrapper]" @click="$emit('add')">
5
+ <Icon :name="ui.action.addingIcon" :class="[ui.action.addingBtnClass]" />
6
+ <p :class="[ui.action.addingTextClass]">{{ uploadAddLabel }}</p>
7
+ </div>
8
+ </div>
9
+
10
+ <!-- Loading State -->
11
+ <div v-if="selectedFile && upload.status.value.isLoading" class="w-full">
12
+ <div :class="[ui.imageItem.onLoading.wrapper]">
13
+ <div :class="[ui.imageItem.onLoading.percentClass]">{{ percent }}%</div>
14
+ <UProgress :value="percent" />
15
+ </div>
16
+ </div>
17
+
18
+ <!-- Success State -->
19
+ <div v-if="selectedFile && upload.status.value.isSuccess" class="w-full">
20
+ <div :class="[ui.imageItem.onPreview.wrapper]">
21
+ <img
22
+ :class="[ui.imageItem.onPreview.previewImgClass]"
23
+ :src="upload.data.value[responseURL!]"
24
+ alt="img"
25
+ />
26
+ <div :class="[ui.imageItem.onPreview.previewActionWrapper]">
27
+ <Icon
28
+ title="ลบไฟล์"
29
+ :name="ui.action.deleteIcon"
30
+ :class="[ui.imageItem.onPreview.actionBtnClass]"
31
+ @click="handleDeleteFile"
32
+ />
33
+ </div>
34
+ </div>
35
+
36
+ <div :class="[ui.imageItem.onPreview.previewTextWrapper]">
37
+ <p :class="[ui.imageItem.onPreview.previewText]">{{ selectedFile.name }}</p>
38
+ </div>
39
+ </div>
40
+
41
+ <!-- Failed State -->
42
+ <div v-if="selectedFile && upload.status.value.isError" class="w-full">
43
+ <div :class="[ui.imageItem.onFailed.wrapper]">
44
+ <img
45
+ :class="[ui.imageItem.onFailed.failedImgClass]"
46
+ :src="generateURL(selectedFile)"
47
+ alt="img"
48
+ />
49
+ <div :class="[ui.imageItem.onFailed.failedActionWrapper]">
50
+ <Icon
51
+ title="ลบไฟล์"
52
+ :name="ui.action.deleteIcon"
53
+ :class="[ui.imageItem.onFailed.actionBtnClass]"
54
+ @click="handleDeleteFile"
55
+ />
56
+ </div>
57
+ </div>
58
+ </div>
59
+ </div>
60
+ </template>
61
+
62
+ <script lang="ts" setup>
63
+ import {
64
+ checkFileType,
65
+ checkMaxSize,
66
+ generateURL,
67
+ useFileAllocate,
68
+ useFileProgress,
69
+ } from '#core/helpers/componentHelper'
70
+ import { type uploadFileDropzoneImage } from '#core/ui.config'
71
+ import type { IUploadDropzoneImageAutoMultipleProps } from '#core/components/Form/InputUploadDropzoneImageAutoMultiple/types'
72
+ import { type IUploadRequest, onMounted, ref, toRef, useUploadLoader, useWatchTrue } from '#imports'
73
+ import i18next from 'i18next'
74
+
75
+ const emits = defineEmits(['success', 'error', 'delete', 'add'])
76
+ const props = defineProps<
77
+ {
78
+ ui: typeof uploadFileDropzoneImage
79
+ selectedFile?: File
80
+ isAddingBtn?: boolean
81
+ } & IUploadDropzoneImageAutoMultipleProps
82
+ >()
83
+
84
+ const request: IUploadRequest = {
85
+ pathURL: props.uploadPathURL,
86
+ requestOptions: props.requestOptions,
87
+ }
88
+
89
+ const upload = useUploadLoader(request)
90
+ const errMsg = ref<string>('')
91
+
92
+ const { onUploadProgress, onDownloadProgress, percent } = useFileProgress()
93
+ const fileAllocate = useFileAllocate(toRef(props.selectedFile), props)
94
+
95
+ const handleDeleteFile = () => {
96
+ emits('delete')
97
+ }
98
+
99
+ const handleCheckFileCondition = (file: File | undefined): boolean => {
100
+ if (!file) return false
101
+
102
+ const fileType = checkFileType(file, fileAllocate.acceptFile.value ?? '')
103
+
104
+ if (!fileType) {
105
+ errMsg.value = i18next.t('custom:invalid_file_type')
106
+
107
+ return false
108
+ }
109
+
110
+ const maxSize = checkMaxSize(file, fileAllocate.acceptFileSizeKb.value)
111
+
112
+ if (!maxSize) {
113
+ if (fileAllocate.isAcceptFileUseMb.value) {
114
+ errMsg.value = i18next.t('custom:invalid_file_size_mb', {
115
+ size: fileAllocate.acceptFileSizeMb.value,
116
+ })
117
+ } else {
118
+ errMsg.value = i18next.t('custom:invalid_file_size_kb', {
119
+ size: fileAllocate.acceptFileSizeKb.value,
120
+ })
121
+ }
122
+
123
+ return false
124
+ }
125
+
126
+ errMsg.value = ''
127
+
128
+ return true
129
+ }
130
+
131
+ onMounted(() => {
132
+ if (props.isAddingBtn) return
133
+
134
+ const result = handleCheckFileCondition(props.selectedFile)
135
+
136
+ if (result) {
137
+ const formData = new FormData()
138
+
139
+ formData.append(props.bodyKey!, props.selectedFile!)
140
+ upload.run(formData, { data: { onUploadProgress, onDownloadProgress } })
141
+ }
142
+ })
143
+
144
+ useWatchTrue(
145
+ () => upload.status.value.isSuccess,
146
+ () => {
147
+ emits('success', {
148
+ ...upload.data.value,
149
+ name: props.selectedFile?.name,
150
+ size: +(props.selectedFile?.size || 0),
151
+ })
152
+ }
153
+ )
154
+
155
+ useWatchTrue(
156
+ () => upload.status.value.isError,
157
+ () => {
158
+ emits('error', upload.status.value.errorData)
159
+ }
160
+ )
161
+ </script>