@finema/core 1.4.159 → 1.4.161

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 (62) hide show
  1. package/README.md +60 -60
  2. package/dist/module.json +1 -1
  3. package/dist/module.mjs +59 -17
  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 +45 -45
  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/index.vue +83 -83
  21. package/dist/runtime/components/Form/InputNumber/index.vue +27 -27
  22. package/dist/runtime/components/Form/InputRadio/index.vue +27 -27
  23. package/dist/runtime/components/Form/InputSelect/index.vue +45 -45
  24. package/dist/runtime/components/Form/InputSelectMultiple/index.vue +54 -54
  25. package/dist/runtime/components/Form/InputStatic/index.vue +16 -16
  26. package/dist/runtime/components/Form/InputTags/index.vue +145 -145
  27. package/dist/runtime/components/Form/InputText/index.vue +67 -67
  28. package/dist/runtime/components/Form/InputTextarea/index.vue +25 -25
  29. package/dist/runtime/components/Form/InputToggle/index.vue +14 -14
  30. package/dist/runtime/components/Form/InputUploadDropzone/index.vue +206 -206
  31. package/dist/runtime/components/Form/InputUploadDropzoneAuto/index.vue +342 -342
  32. package/dist/runtime/components/Form/InputUploadDropzoneAutoMultiple/ItemUpload.vue +241 -241
  33. package/dist/runtime/components/Form/InputUploadDropzoneAutoMultiple/ItemView.vue +89 -89
  34. package/dist/runtime/components/Form/InputUploadDropzoneAutoMultiple/index.vue +164 -164
  35. package/dist/runtime/components/Form/InputUploadDropzoneImageAutoMultiple/ItemUpload.vue +161 -161
  36. package/dist/runtime/components/Form/InputUploadDropzoneImageAutoMultiple/ItemView.vue +64 -64
  37. package/dist/runtime/components/Form/InputUploadDropzoneImageAutoMultiple/index.vue +172 -172
  38. package/dist/runtime/components/Form/InputUploadFileClassic/index.vue +95 -95
  39. package/dist/runtime/components/Form/InputUploadFileClassicAuto/index.vue +151 -151
  40. package/dist/runtime/components/Form/InputUploadImageAuto/index.vue +219 -219
  41. package/dist/runtime/components/Form/InputWYSIWYG/index.vue +53 -53
  42. package/dist/runtime/components/Form/index.vue +6 -6
  43. package/dist/runtime/components/Icon.vue +23 -23
  44. package/dist/runtime/components/Image.vue +36 -36
  45. package/dist/runtime/components/Loader.vue +27 -27
  46. package/dist/runtime/components/Modal/index.vue +146 -146
  47. package/dist/runtime/components/QRCode.vue +22 -22
  48. package/dist/runtime/components/SimplePagination.vue +96 -96
  49. package/dist/runtime/components/Slideover/index.vue +110 -110
  50. package/dist/runtime/components/Table/Base.vue +139 -139
  51. package/dist/runtime/components/Table/ColumnDate.vue +16 -16
  52. package/dist/runtime/components/Table/ColumnDateTime.vue +18 -18
  53. package/dist/runtime/components/Table/ColumnImage.vue +15 -15
  54. package/dist/runtime/components/Table/ColumnNumber.vue +14 -14
  55. package/dist/runtime/components/Table/ColumnText.vue +25 -25
  56. package/dist/runtime/components/Table/Simple.vue +69 -69
  57. package/dist/runtime/components/Table/index.vue +65 -65
  58. package/dist/runtime/components/Tabs/index.vue +64 -64
  59. package/dist/runtime/components/TeleportSafe.vue +40 -40
  60. package/dist/runtime/composables/useNotification.mjs +13 -4
  61. package/dist/runtime/ui.config/notification.mjs +4 -0
  62. package/package.json +95 -95
@@ -1,64 +1,64 @@
1
- <template>
2
- <div :class="[ui.imageItem.wrapper]">
3
- <div class="w-full">
4
- <div :class="[ui.imageItem.onPreview.wrapper]">
5
- <img :class="[ui.imageItem.onPreview.previewImgClass]" :src="selectedFile.url" alt="img" />
6
- <div :class="[ui.imageItem.onPreview.previewActionWrapper]">
7
- <Icon
8
- title="ดูตัวอย่าง"
9
- :name="ui.action.previewIcon"
10
- :class="[ui.imageItem.onPreview.actionBtnClass]"
11
- @click="() => (isPreviewOpen = true)"
12
- />
13
- <Icon
14
- title="ลบไฟล์"
15
- :name="ui.action.deleteIcon"
16
- :class="[ui.imageItem.onPreview.actionBtnClass]"
17
- @click="handleDeleteFile"
18
- />
19
- <Modal v-model="isPreviewOpen" size="xl">
20
- <div class="absolute -top-8 left-0 flex w-full justify-between text-gray-600">
21
- <p v-if="selectedFile?.name">{{ selectedFile?.name }}</p>
22
- <Icon
23
- name="i-heroicons-x-mark"
24
- class="size-6 cursor-pointer hover:text-gray-400"
25
- @click="() => (isPreviewOpen = false)"
26
- />
27
- </div>
28
- <img
29
- :src="selectedFile.url"
30
- alt="image-preview"
31
- class="mx-auto max-w-full rounded-lg"
32
- />
33
- </Modal>
34
- </div>
35
- </div>
36
-
37
- <div :class="[ui.imageItem.onPreview.previewTextWrapper]">
38
- <p :class="[ui.imageItem.onPreview.previewText]">{{ selectedFile.name }}</p>
39
- </div>
40
- </div>
41
- </div>
42
- </template>
43
-
44
- <script lang="ts" setup>
45
- import { type uploadFileDropzoneImage } from '#core/ui.config'
46
- import type { IUploadDropzoneImageAutoMultipleProps } from '#core/components/Form/InputUploadDropzoneImageAutoMultiple/types'
47
- import { ref } from '#imports'
48
- import type { IFileValue } from '#core/components/Form/types'
49
-
50
- const emits = defineEmits(['delete'])
51
-
52
- defineProps<
53
- {
54
- ui: typeof uploadFileDropzoneImage
55
- selectedFile: IFileValue
56
- } & IUploadDropzoneImageAutoMultipleProps
57
- >()
58
-
59
- const isPreviewOpen = ref<boolean>(false)
60
-
61
- const handleDeleteFile = () => {
62
- emits('delete')
63
- }
64
- </script>
1
+ <template>
2
+ <div :class="[ui.imageItem.wrapper]">
3
+ <div class="w-full">
4
+ <div :class="[ui.imageItem.onPreview.wrapper]">
5
+ <img :class="[ui.imageItem.onPreview.previewImgClass]" :src="selectedFile.url" alt="img" />
6
+ <div :class="[ui.imageItem.onPreview.previewActionWrapper]">
7
+ <Icon
8
+ title="ดูตัวอย่าง"
9
+ :name="ui.action.previewIcon"
10
+ :class="[ui.imageItem.onPreview.actionBtnClass]"
11
+ @click="() => (isPreviewOpen = true)"
12
+ />
13
+ <Icon
14
+ title="ลบไฟล์"
15
+ :name="ui.action.deleteIcon"
16
+ :class="[ui.imageItem.onPreview.actionBtnClass]"
17
+ @click="handleDeleteFile"
18
+ />
19
+ <Modal v-model="isPreviewOpen" size="xl">
20
+ <div class="absolute -top-8 left-0 flex w-full justify-between text-gray-600">
21
+ <p v-if="selectedFile?.name">{{ selectedFile?.name }}</p>
22
+ <Icon
23
+ name="i-heroicons-x-mark"
24
+ class="size-6 cursor-pointer hover:text-gray-400"
25
+ @click="() => (isPreviewOpen = false)"
26
+ />
27
+ </div>
28
+ <img
29
+ :src="selectedFile.url"
30
+ alt="image-preview"
31
+ class="mx-auto max-w-full rounded-lg"
32
+ />
33
+ </Modal>
34
+ </div>
35
+ </div>
36
+
37
+ <div :class="[ui.imageItem.onPreview.previewTextWrapper]">
38
+ <p :class="[ui.imageItem.onPreview.previewText]">{{ selectedFile.name }}</p>
39
+ </div>
40
+ </div>
41
+ </div>
42
+ </template>
43
+
44
+ <script lang="ts" setup>
45
+ import { type uploadFileDropzoneImage } from '#core/ui.config'
46
+ import type { IUploadDropzoneImageAutoMultipleProps } from '#core/components/Form/InputUploadDropzoneImageAutoMultiple/types'
47
+ import { ref } from '#imports'
48
+ import type { IFileValue } from '#core/components/Form/types'
49
+
50
+ const emits = defineEmits(['delete'])
51
+
52
+ defineProps<
53
+ {
54
+ ui: typeof uploadFileDropzoneImage
55
+ selectedFile: IFileValue
56
+ } & IUploadDropzoneImageAutoMultipleProps
57
+ >()
58
+
59
+ const isPreviewOpen = ref<boolean>(false)
60
+
61
+ const handleDeleteFile = () => {
62
+ emits('delete')
63
+ }
64
+ </script>
@@ -1,172 +1,172 @@
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 v-if="value && value.length === 0" :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
-
37
- <div v-else :class="ui.imageItemWrapper">
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
- <itemUpload v-bind="$props" is-adding-btn :ui="ui" @add="handleOpenFile" />
57
- </div>
58
- </div>
59
- </div>
60
- </div>
61
- </FieldWrapper>
62
- </template>
63
-
64
- <script lang="ts" setup>
65
- import { useDropZone } from '@vueuse/core'
66
- import { type IUploadDropzoneImageAutoMultipleProps } from './types'
67
- import FieldWrapper from '#core/components/Form/FieldWrapper.vue'
68
- import { useFieldHOC } from '#core/composables/useForm'
69
- import { _get, computed, ref, toRef, StringHelper, useUI, useUiConfig, ArrayHelper } from '#imports'
70
- import { uploadFileDropzoneImage } from '#core/ui.config'
71
- import ItemUpload from './ItemUpload.vue'
72
- import ItemView from './ItemView.vue'
73
- import type { IFileValue } from '#core/components/Form/types'
74
-
75
- const config = useUiConfig<typeof uploadFileDropzoneImage>(
76
- uploadFileDropzoneImage,
77
- 'uploadFileDropzoneImage'
78
- )
79
-
80
- const props = withDefaults(defineProps<IUploadDropzoneImageAutoMultipleProps>(), {
81
- accept: 'image/*',
82
- bodyKey: 'file',
83
- responseURL: 'url',
84
- responsePath: 'path',
85
- selectFileLabel: 'คลิกเพื่อเลือกไฟล์',
86
- selectFileSubLabel: 'หรือ ลากและวางที่นี่',
87
- uploadAddLabel: 'อัพโหลด',
88
- })
89
-
90
- const emits = defineEmits(['change', 'success', 'delete'])
91
- const selectedFiles = ref<Array<{ file: File; key: string }>>([])
92
-
93
- const { wrapperProps, handleChange: onChange, value } = useFieldHOC<IFileValue[]>(props)
94
-
95
- const { ui } = useUI('uploadFileDropzoneImage', toRef(props, 'ui'), config)
96
-
97
- const fileInputRef = ref<HTMLInputElement | null>()
98
- const dropzoneRef = ref<HTMLDivElement>()
99
-
100
- const acceptFile = computed(() =>
101
- typeof props.accept === 'string' ? props.accept : props.accept?.join(',')
102
- )
103
-
104
- const onDrop = (files: File[] | null) => {
105
- if (props.isDisabled || files?.length === 0 || !files) return
106
-
107
- for (const file of files) {
108
- selectedFiles.value = [
109
- ...selectedFiles.value,
110
- {
111
- file,
112
- key: StringHelper.genString(),
113
- },
114
- ]
115
-
116
- emits('change', value.value)
117
- }
118
- }
119
-
120
- const { isOverDropZone } = useDropZone(dropzoneRef as unknown as HTMLElement, {
121
- onDrop,
122
- })
123
-
124
- const handleChange = (e: Event) => {
125
- if (props.isDisabled) return
126
-
127
- for (const file of (e.target as HTMLInputElement).files ?? []) {
128
- selectedFiles.value = [
129
- ...selectedFiles.value,
130
- {
131
- file,
132
- key: StringHelper.genString(),
133
- },
134
- ]
135
-
136
- emits('change', value.value)
137
- }
138
-
139
- fileInputRef.value?.value && (fileInputRef.value.value = '')
140
- }
141
-
142
- const handleOpenFile = () => {
143
- fileInputRef.value?.click()
144
- }
145
-
146
- const handleDeleteFile = (index: number) => {
147
- selectedFiles.value.splice(index, 1)
148
- }
149
-
150
- const handleDeleteFileView = (index: number) => {
151
- value.value.splice(index, 1)
152
- emits('delete')
153
- }
154
-
155
- const handleError = (index: number, error: any) => {}
156
-
157
- const handleSuccess = (index: number, res: any) => {
158
- value.value = [
159
- {
160
- url: _get(res, props.responseURL),
161
- path: _get(res, props.responsePath),
162
- name: res.name,
163
- size: res.size,
164
- },
165
- ...ArrayHelper.toArray(value.value),
166
- ]
167
-
168
- selectedFiles.value.splice(index, 1)
169
- emits('change', value.value)
170
- emits('success', value.value)
171
- }
172
- </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 v-if="value && value.length === 0" :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
+
37
+ <div v-else :class="ui.imageItemWrapper">
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
+ <itemUpload v-bind="$props" is-adding-btn :ui="ui" @add="handleOpenFile" />
57
+ </div>
58
+ </div>
59
+ </div>
60
+ </div>
61
+ </FieldWrapper>
62
+ </template>
63
+
64
+ <script lang="ts" setup>
65
+ import { useDropZone } from '@vueuse/core'
66
+ import { type IUploadDropzoneImageAutoMultipleProps } from './types'
67
+ import FieldWrapper from '#core/components/Form/FieldWrapper.vue'
68
+ import { useFieldHOC } from '#core/composables/useForm'
69
+ import { _get, computed, ref, toRef, StringHelper, useUI, useUiConfig, ArrayHelper } from '#imports'
70
+ import { uploadFileDropzoneImage } from '#core/ui.config'
71
+ import ItemUpload from './ItemUpload.vue'
72
+ import ItemView from './ItemView.vue'
73
+ import type { IFileValue } from '#core/components/Form/types'
74
+
75
+ const config = useUiConfig<typeof uploadFileDropzoneImage>(
76
+ uploadFileDropzoneImage,
77
+ 'uploadFileDropzoneImage'
78
+ )
79
+
80
+ const props = withDefaults(defineProps<IUploadDropzoneImageAutoMultipleProps>(), {
81
+ accept: 'image/*',
82
+ bodyKey: 'file',
83
+ responseURL: 'url',
84
+ responsePath: 'path',
85
+ selectFileLabel: 'คลิกเพื่อเลือกไฟล์',
86
+ selectFileSubLabel: 'หรือ ลากและวางที่นี่',
87
+ uploadAddLabel: 'อัพโหลด',
88
+ })
89
+
90
+ const emits = defineEmits(['change', 'success', 'delete'])
91
+ const selectedFiles = ref<Array<{ file: File; key: string }>>([])
92
+
93
+ const { wrapperProps, handleChange: onChange, value } = useFieldHOC<IFileValue[]>(props)
94
+
95
+ const { ui } = useUI('uploadFileDropzoneImage', toRef(props, 'ui'), config)
96
+
97
+ const fileInputRef = ref<HTMLInputElement | null>()
98
+ const dropzoneRef = ref<HTMLDivElement>()
99
+
100
+ const acceptFile = computed(() =>
101
+ typeof props.accept === 'string' ? props.accept : props.accept?.join(',')
102
+ )
103
+
104
+ const onDrop = (files: File[] | null) => {
105
+ if (props.isDisabled || files?.length === 0 || !files) return
106
+
107
+ for (const file of files) {
108
+ selectedFiles.value = [
109
+ ...selectedFiles.value,
110
+ {
111
+ file,
112
+ key: StringHelper.genString(),
113
+ },
114
+ ]
115
+
116
+ emits('change', value.value)
117
+ }
118
+ }
119
+
120
+ const { isOverDropZone } = useDropZone(dropzoneRef as unknown as HTMLElement, {
121
+ onDrop,
122
+ })
123
+
124
+ const handleChange = (e: Event) => {
125
+ if (props.isDisabled) return
126
+
127
+ for (const file of (e.target as HTMLInputElement).files ?? []) {
128
+ selectedFiles.value = [
129
+ ...selectedFiles.value,
130
+ {
131
+ file,
132
+ key: StringHelper.genString(),
133
+ },
134
+ ]
135
+
136
+ emits('change', value.value)
137
+ }
138
+
139
+ fileInputRef.value?.value && (fileInputRef.value.value = '')
140
+ }
141
+
142
+ const handleOpenFile = () => {
143
+ fileInputRef.value?.click()
144
+ }
145
+
146
+ const handleDeleteFile = (index: number) => {
147
+ selectedFiles.value.splice(index, 1)
148
+ }
149
+
150
+ const handleDeleteFileView = (index: number) => {
151
+ value.value.splice(index, 1)
152
+ emits('delete')
153
+ }
154
+
155
+ const handleError = (index: number, error: any) => {}
156
+
157
+ const handleSuccess = (index: number, res: any) => {
158
+ value.value = [
159
+ {
160
+ url: _get(res, props.responseURL),
161
+ path: _get(res, props.responsePath),
162
+ name: res.name,
163
+ size: res.size,
164
+ },
165
+ ...ArrayHelper.toArray(value.value),
166
+ ]
167
+
168
+ selectedFiles.value.splice(index, 1)
169
+ emits('change', value.value)
170
+ emits('success', value.value)
171
+ }
172
+ </script>
@@ -1,95 +1,95 @@
1
- <template>
2
- <FieldWrapper v-bind="wrapperProps">
3
- <div :class="[ui.base]">
4
- <input
5
- ref="fileInput"
6
- type="file"
7
- class="hidden"
8
- :name="name"
9
- :accept="fileAllocate.acceptFile.value"
10
- :disabled="isDisabled"
11
- @change="handleChange"
12
- />
13
- <div :class="[ui.wrapper]">
14
- <div :class="[ui.selectFileBox]">
15
- <Button size="2xs" @click="handleOpenFile">{{ selectFileLabel }}</Button>
16
- <p :class="ui.placeholder">
17
- {{ value?.name ?? placeholder ?? 'ยังไม่ได้เลือกไฟล์' }}
18
- </p>
19
- <Badge v-if="value" size="xs" variant="outline">
20
- {{
21
- fileAllocate.isSelectedFileUseMb.value
22
- ? `${fileAllocate.selectedFileSizeMb.value} MB`
23
- : `${fileAllocate.selectedFileSizeKb.value} KB`
24
- }}
25
- </Badge>
26
- </div>
27
- </div>
28
- </div>
29
- </FieldWrapper>
30
- </template>
31
- <script lang="ts" setup>
32
- import { useFieldHOC } from '#core/composables/useForm'
33
- import FieldWrapper from '#core/components/Form/FieldWrapper.vue'
34
- import { type IUploadFileClassicFieldProps } from '#core/components/Form/InputUploadFileClassic/types'
35
- import { useUiConfig } from '#core/composables/useConfig'
36
- import { uploadFileInputClassicAuto } from '#core/ui.config'
37
- import { ref, toRef, useUI } from '#imports'
38
- import i18next from 'i18next'
39
- import { checkMaxSize, useFileAllocate } from '#core/helpers/componentHelper'
40
-
41
- const config = useUiConfig<typeof uploadFileInputClassicAuto>(
42
- uploadFileInputClassicAuto,
43
- 'uploadFileInputClassicAuto'
44
- )
45
-
46
- const emits = defineEmits(['change'])
47
- const props = withDefaults(defineProps<IUploadFileClassicFieldProps>(), {
48
- selectFileLabel: 'เลือกไฟล์',
49
- })
50
-
51
- const { value, wrapperProps, setErrors } = useFieldHOC<File | undefined>(props)
52
- const fileAllocate = useFileAllocate(value, props)
53
-
54
- const fileInput = ref<HTMLInputElement>()
55
-
56
- const handleOpenFile = () => {
57
- fileInput.value?.click()
58
- }
59
-
60
- const { ui } = useUI('uploadFileInputClassicAuto', toRef(props, 'ui'), config)
61
-
62
- const handleCheckFileCondition = (file: File | undefined): boolean => {
63
- if (!file) return false
64
-
65
- const maxSize = checkMaxSize(file, props.maxSize)
66
-
67
- if (!maxSize) {
68
- if (fileAllocate.isAcceptFileUseMb.value) {
69
- setErrors(
70
- i18next.t('custom:invalid_file_size_mb', { size: fileAllocate.acceptFileSizeMb.value })
71
- )
72
- } else {
73
- setErrors(
74
- i18next.t('custom:invalid_file_size_kb', { size: fileAllocate.acceptFileSizeKb.value })
75
- )
76
- }
77
-
78
- return false
79
- }
80
-
81
- setErrors('')
82
-
83
- return true
84
- }
85
-
86
- const handleChange = (e: Event) => {
87
- const file = (e.target as HTMLInputElement).files?.[0]
88
- const result = handleCheckFileCondition(file)
89
-
90
- if (result && file) {
91
- value.value = file
92
- emits('change', file)
93
- }
94
- }
95
- </script>
1
+ <template>
2
+ <FieldWrapper v-bind="wrapperProps">
3
+ <div :class="[ui.base]">
4
+ <input
5
+ ref="fileInput"
6
+ type="file"
7
+ class="hidden"
8
+ :name="name"
9
+ :accept="fileAllocate.acceptFile.value"
10
+ :disabled="isDisabled"
11
+ @change="handleChange"
12
+ />
13
+ <div :class="[ui.wrapper]">
14
+ <div :class="[ui.selectFileBox]">
15
+ <Button size="2xs" @click="handleOpenFile">{{ selectFileLabel }}</Button>
16
+ <p :class="ui.placeholder">
17
+ {{ value?.name ?? placeholder ?? 'ยังไม่ได้เลือกไฟล์' }}
18
+ </p>
19
+ <Badge v-if="value" size="xs" variant="outline">
20
+ {{
21
+ fileAllocate.isSelectedFileUseMb.value
22
+ ? `${fileAllocate.selectedFileSizeMb.value} MB`
23
+ : `${fileAllocate.selectedFileSizeKb.value} KB`
24
+ }}
25
+ </Badge>
26
+ </div>
27
+ </div>
28
+ </div>
29
+ </FieldWrapper>
30
+ </template>
31
+ <script lang="ts" setup>
32
+ import { useFieldHOC } from '#core/composables/useForm'
33
+ import FieldWrapper from '#core/components/Form/FieldWrapper.vue'
34
+ import { type IUploadFileClassicFieldProps } from '#core/components/Form/InputUploadFileClassic/types'
35
+ import { useUiConfig } from '#core/composables/useConfig'
36
+ import { uploadFileInputClassicAuto } from '#core/ui.config'
37
+ import { ref, toRef, useUI } from '#imports'
38
+ import i18next from 'i18next'
39
+ import { checkMaxSize, useFileAllocate } from '#core/helpers/componentHelper'
40
+
41
+ const config = useUiConfig<typeof uploadFileInputClassicAuto>(
42
+ uploadFileInputClassicAuto,
43
+ 'uploadFileInputClassicAuto'
44
+ )
45
+
46
+ const emits = defineEmits(['change'])
47
+ const props = withDefaults(defineProps<IUploadFileClassicFieldProps>(), {
48
+ selectFileLabel: 'เลือกไฟล์',
49
+ })
50
+
51
+ const { value, wrapperProps, setErrors } = useFieldHOC<File | undefined>(props)
52
+ const fileAllocate = useFileAllocate(value, props)
53
+
54
+ const fileInput = ref<HTMLInputElement>()
55
+
56
+ const handleOpenFile = () => {
57
+ fileInput.value?.click()
58
+ }
59
+
60
+ const { ui } = useUI('uploadFileInputClassicAuto', toRef(props, 'ui'), config)
61
+
62
+ const handleCheckFileCondition = (file: File | undefined): boolean => {
63
+ if (!file) return false
64
+
65
+ const maxSize = checkMaxSize(file, props.maxSize)
66
+
67
+ if (!maxSize) {
68
+ if (fileAllocate.isAcceptFileUseMb.value) {
69
+ setErrors(
70
+ i18next.t('custom:invalid_file_size_mb', { size: fileAllocate.acceptFileSizeMb.value })
71
+ )
72
+ } else {
73
+ setErrors(
74
+ i18next.t('custom:invalid_file_size_kb', { size: fileAllocate.acceptFileSizeKb.value })
75
+ )
76
+ }
77
+
78
+ return false
79
+ }
80
+
81
+ setErrors('')
82
+
83
+ return true
84
+ }
85
+
86
+ const handleChange = (e: Event) => {
87
+ const file = (e.target as HTMLInputElement).files?.[0]
88
+ const result = handleCheckFileCondition(file)
89
+
90
+ if (result && file) {
91
+ value.value = file
92
+ emits('change', file)
93
+ }
94
+ }
95
+ </script>