@finema/core 1.4.107 → 1.4.109
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.
- package/dist/module.json +1 -1
- package/dist/module.mjs +7 -2
- package/dist/runtime/components/Form/Fields.vue +15 -0
- package/dist/runtime/components/Form/InputTags/index.vue +134 -0
- package/dist/runtime/components/Form/InputTags/types.d.ts +11 -0
- package/dist/runtime/components/Form/InputTags/types.mjs +0 -0
- package/dist/runtime/components/Form/InputUploadDropzoneImageAutoMultiple/item.vue +2 -2
- package/dist/runtime/components/Form/InputUploadImageAuto/index.vue +222 -0
- package/dist/runtime/components/Form/InputUploadImageAuto/types.d.ts +19 -0
- package/dist/runtime/components/Form/InputUploadImageAuto/types.mjs +0 -0
- package/dist/runtime/components/Form/types.d.ts +5 -1
- package/dist/runtime/components/Form/types.mjs +2 -0
- package/dist/runtime/types/config.d.ts +1 -1
- package/dist/runtime/ui.config/index.d.ts +2 -0
- package/dist/runtime/ui.config/index.mjs +2 -0
- package/dist/runtime/ui.config/tags.d.ts +25 -0
- package/dist/runtime/ui.config/tags.mjs +25 -0
- package/dist/runtime/ui.config/uploadDropzoneImage.mjs +2 -2
- package/dist/runtime/ui.config/uploadImage.d.ts +34 -0
- package/dist/runtime/ui.config/uploadImage.mjs +36 -0
- package/package.json +2 -2
package/dist/module.json
CHANGED
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.
|
|
4
|
+
const version = "1.4.109";
|
|
5
5
|
|
|
6
6
|
const colors = {
|
|
7
7
|
black: "#20243E",
|
|
@@ -394,7 +394,12 @@ const module = defineNuxtModule({
|
|
|
394
394
|
);
|
|
395
395
|
nuxt.options.build = {
|
|
396
396
|
...nuxt.options.build || {},
|
|
397
|
-
transpile: [
|
|
397
|
+
transpile: [
|
|
398
|
+
...nuxt.options.build?.transpile || [],
|
|
399
|
+
"date-fns",
|
|
400
|
+
"@vuepic/vue-datepicker",
|
|
401
|
+
"quill"
|
|
402
|
+
]
|
|
398
403
|
};
|
|
399
404
|
await installModule("@pinia/nuxt");
|
|
400
405
|
await installModule("@vee-validate/nuxt", veeValidateNuxtOptions);
|
|
@@ -123,6 +123,14 @@
|
|
|
123
123
|
v-bind="getFieldBinding(option)"
|
|
124
124
|
v-on="option.on ?? {}"
|
|
125
125
|
/>
|
|
126
|
+
<FormInputUploadImageAuto
|
|
127
|
+
v-else-if="option.type === INPUT_TYPES.UPLOAD_IMAGE_AUTO"
|
|
128
|
+
:class="option.class"
|
|
129
|
+
:form="form"
|
|
130
|
+
:request-options="option.props.requestOptions"
|
|
131
|
+
v-bind="getFieldBinding(option)"
|
|
132
|
+
v-on="option.on ?? {}"
|
|
133
|
+
/>
|
|
126
134
|
<FormInputUploadDropzone
|
|
127
135
|
v-else-if="option.type === INPUT_TYPES.UPLOAD_DROPZONE"
|
|
128
136
|
:class="option.class"
|
|
@@ -161,6 +169,13 @@
|
|
|
161
169
|
v-bind="getFieldBinding(option)"
|
|
162
170
|
v-on="option.on ?? {}"
|
|
163
171
|
/>
|
|
172
|
+
<FormInputTags
|
|
173
|
+
v-else-if="option.type === INPUT_TYPES.TAGS"
|
|
174
|
+
:class="option.class"
|
|
175
|
+
:form="form"
|
|
176
|
+
v-bind="getFieldBinding(option)"
|
|
177
|
+
v-on="option.on ?? {}"
|
|
178
|
+
/>
|
|
164
179
|
<component
|
|
165
180
|
:is="option.component"
|
|
166
181
|
v-else-if="option.type === INPUT_TYPES.COMPONENT"
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<FieldWrapper v-bind="wrapperProps">
|
|
3
|
+
<div
|
|
4
|
+
:class="[
|
|
5
|
+
ui.base,
|
|
6
|
+
ui.border,
|
|
7
|
+
ui.shadow,
|
|
8
|
+
ui.padding,
|
|
9
|
+
{
|
|
10
|
+
[ui.stages.default]: !wrapperProps.errorMessage,
|
|
11
|
+
[ui.stages.error]: wrapperProps.errorMessage,
|
|
12
|
+
},
|
|
13
|
+
]"
|
|
14
|
+
>
|
|
15
|
+
<p
|
|
16
|
+
v-if="wrapperProps.placeholder && !innerValue && (!value || value.length === 0)"
|
|
17
|
+
:class="[ui.placeholder]"
|
|
18
|
+
@click="focusInput"
|
|
19
|
+
>
|
|
20
|
+
{{ wrapperProps.placeholder }}
|
|
21
|
+
</p>
|
|
22
|
+
<div :class="[ui.innerWrapper]">
|
|
23
|
+
<Badge
|
|
24
|
+
v-for="(text, index) in value"
|
|
25
|
+
:key="index"
|
|
26
|
+
:size="ui.tag.size || (ui.default.tag.size as any)"
|
|
27
|
+
:color="ui.tag.color || (ui.default.tag.color as any)"
|
|
28
|
+
:variant="ui.tag.variant || (ui.default.tag.variant as any)"
|
|
29
|
+
:ui="badgeUi"
|
|
30
|
+
>
|
|
31
|
+
{{ tagPrefix + text }}
|
|
32
|
+
</Badge>
|
|
33
|
+
<input
|
|
34
|
+
ref="inputRef"
|
|
35
|
+
v-model="innerValue"
|
|
36
|
+
:class="[ui.input]"
|
|
37
|
+
:disabled="wrapperProps.isDisabled"
|
|
38
|
+
:name="name"
|
|
39
|
+
:readonly="isReadonly"
|
|
40
|
+
:autofocus="!!autoFocus"
|
|
41
|
+
@blur="onBlur"
|
|
42
|
+
@keyup.delete="onDelete"
|
|
43
|
+
@keyup.enter="onEnter"
|
|
44
|
+
@keyup.space="onSpace"
|
|
45
|
+
/>
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
</FieldWrapper>
|
|
49
|
+
</template>
|
|
50
|
+
|
|
51
|
+
<script lang="ts" setup>
|
|
52
|
+
import { ref, toRef, useUI, useUiConfig } from '#imports'
|
|
53
|
+
import { type ITagsFieldProps } from '#core/components/Form/InputTags/types'
|
|
54
|
+
import { tags } from '#core/ui.config'
|
|
55
|
+
import { useFieldHOC } from '#core/composables/useForm'
|
|
56
|
+
import FieldWrapper from '#core/components/Form/FieldWrapper.vue'
|
|
57
|
+
|
|
58
|
+
const config = useUiConfig<typeof tags>(tags, 'tags')
|
|
59
|
+
|
|
60
|
+
const props = withDefaults(defineProps<ITagsFieldProps>(), {
|
|
61
|
+
tagPrefix: '#',
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
const emits = defineEmits(['change', 'blur'])
|
|
65
|
+
|
|
66
|
+
const { value, wrapperProps } = useFieldHOC<string[]>(props)
|
|
67
|
+
|
|
68
|
+
const { ui } = useUI('tags', toRef(props, 'ui'), config)
|
|
69
|
+
|
|
70
|
+
const inputRef = ref<HTMLInputElement | null>(null)
|
|
71
|
+
const innerValue = ref<string>('')
|
|
72
|
+
const backspaceCount = ref<number>(0)
|
|
73
|
+
|
|
74
|
+
const operateValue = (input: string) => {
|
|
75
|
+
const tagSet = splitBySpace(input)
|
|
76
|
+
|
|
77
|
+
if (value.value && value.value.length > 0) {
|
|
78
|
+
value.value = [...value.value, ...tagSet]
|
|
79
|
+
} else {
|
|
80
|
+
value.value = tagSet
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
innerValue.value = ''
|
|
84
|
+
|
|
85
|
+
emits('change', value.value)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const onBlur = (e: FocusEvent) => {
|
|
89
|
+
const eventValue = e.target as HTMLInputElement
|
|
90
|
+
|
|
91
|
+
if (!eventValue.value || eventValue.value === '') return
|
|
92
|
+
|
|
93
|
+
operateValue(eventValue.value)
|
|
94
|
+
|
|
95
|
+
emits('blur', eventValue.value)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const onDelete = (e: KeyboardEvent) => {
|
|
99
|
+
if (e.key === 'Backspace') {
|
|
100
|
+
if (innerValue.value === '') {
|
|
101
|
+
backspaceCount.value += 1
|
|
102
|
+
} else {
|
|
103
|
+
backspaceCount.value = 0
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (backspaceCount.value >= 2 && value.value.length > 0) {
|
|
107
|
+
value.value.pop()
|
|
108
|
+
backspaceCount.value = 0
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const onEnter = (e: KeyboardEvent) => {
|
|
114
|
+
if (e.key === 'Enter') {
|
|
115
|
+
operateValue(innerValue.value)
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const onSpace = (e: KeyboardEvent) => {
|
|
120
|
+
if (e.key === ' ') {
|
|
121
|
+
operateValue(innerValue.value)
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const splitBySpace = (input: string): string[] => {
|
|
126
|
+
const spited = input.split(' ')
|
|
127
|
+
|
|
128
|
+
return spited.filter((item) => item !== '')
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const focusInput = () => {
|
|
132
|
+
inputRef.value?.focus()
|
|
133
|
+
}
|
|
134
|
+
</script>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type IFieldProps, type IFormFieldBase, type INPUT_TYPES } from '#core/components/Form/types';
|
|
2
|
+
export interface ITagsFieldProps extends IFieldProps {
|
|
3
|
+
leadingIcon?: string;
|
|
4
|
+
trailingIcon?: string;
|
|
5
|
+
tagPrefix?: string;
|
|
6
|
+
badgeUi?: object | any;
|
|
7
|
+
}
|
|
8
|
+
export type ITagsField = IFormFieldBase<INPUT_TYPES.TAGS, ITagsFieldProps, {
|
|
9
|
+
change?: (value: string[]) => void;
|
|
10
|
+
blur?: (value: string) => void;
|
|
11
|
+
}>;
|
|
File without changes
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
<div :class="[ui.imageItem.onPreview.wrapper]">
|
|
21
21
|
<img
|
|
22
22
|
:class="[ui.imageItem.onPreview.previewImgClass]"
|
|
23
|
-
:src="upload.data.value[responseKey]"
|
|
23
|
+
:src="upload.data.value[responseKey || 'url']"
|
|
24
24
|
alt="img"
|
|
25
25
|
/>
|
|
26
26
|
<div :class="[ui.imageItem.onPreview.previewActionWrapper]">
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
/>
|
|
47
47
|
</div>
|
|
48
48
|
<img
|
|
49
|
-
:src="upload.data.value[responseKey]"
|
|
49
|
+
:src="upload.data.value[responseKey || 'url']"
|
|
50
50
|
alt="image-preview"
|
|
51
51
|
class="w-full rounded-lg"
|
|
52
52
|
/>
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<FieldWrapper v-bind="wrapperProps">
|
|
3
|
+
<div :class="[ui.base]">
|
|
4
|
+
<input
|
|
5
|
+
ref="fileInputRef"
|
|
6
|
+
type="file"
|
|
7
|
+
class="hidden"
|
|
8
|
+
:name="name"
|
|
9
|
+
:accept="acceptFile"
|
|
10
|
+
:disabled="isDisabled"
|
|
11
|
+
@change="handleChange"
|
|
12
|
+
/>
|
|
13
|
+
|
|
14
|
+
<div :class="[ui.imageItem.wrapper]">
|
|
15
|
+
<div v-if="!selectedFile" class="w-full">
|
|
16
|
+
<div :class="[ui.action.addingWrapper]" @click="handleOpenFile">
|
|
17
|
+
<Icon :name="ui.action.addingIcon" :class="[ui.action.addingBtnClass]" />
|
|
18
|
+
<p :class="[ui.action.addingTextClass]">{{ uploadAddLabel }}</p>
|
|
19
|
+
</div>
|
|
20
|
+
</div>
|
|
21
|
+
|
|
22
|
+
<!-- Loading State -->
|
|
23
|
+
<div v-if="selectedFile && upload.status.value.isLoading" class="w-full">
|
|
24
|
+
<div :class="[ui.imageItem.onLoading.wrapper]">
|
|
25
|
+
<div :class="[ui.imageItem.onLoading.percentClass]">{{ percent }}%</div>
|
|
26
|
+
<UProgress :value="percent" />
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
<!-- Success State -->
|
|
31
|
+
<div v-if="selectedFile && upload.status.value.isSuccess" class="w-full">
|
|
32
|
+
<div :class="[ui.imageItem.onPreview.wrapper]">
|
|
33
|
+
<img
|
|
34
|
+
:class="[ui.imageItem.onPreview.previewImgClass]"
|
|
35
|
+
:src="upload.data.value[responseKey || 'url']"
|
|
36
|
+
alt="img"
|
|
37
|
+
/>
|
|
38
|
+
<div :class="[ui.imageItem.onPreview.previewActionWrapper]">
|
|
39
|
+
<Icon
|
|
40
|
+
title="ดูตัวอย่าง"
|
|
41
|
+
:name="ui.action.previewIcon"
|
|
42
|
+
:class="[ui.imageItem.onPreview.actionBtnClass]"
|
|
43
|
+
@click="() => (isPreviewOpen = true)"
|
|
44
|
+
/>
|
|
45
|
+
<Icon
|
|
46
|
+
title="ลบไฟล์"
|
|
47
|
+
:name="ui.action.deleteIcon"
|
|
48
|
+
:class="[ui.imageItem.onPreview.actionBtnClass]"
|
|
49
|
+
@click="handleDeleteFile"
|
|
50
|
+
/>
|
|
51
|
+
<Modal v-model="isPreviewOpen" size="xl">
|
|
52
|
+
<div class="absolute -top-8 left-0 flex w-full justify-between text-gray-600">
|
|
53
|
+
<p>{{ selectedFile?.name }}</p>
|
|
54
|
+
<Icon
|
|
55
|
+
name="i-heroicons-x-mark"
|
|
56
|
+
class="size-6 cursor-pointer hover:text-gray-400"
|
|
57
|
+
@click="() => (isPreviewOpen = false)"
|
|
58
|
+
/>
|
|
59
|
+
</div>
|
|
60
|
+
<img
|
|
61
|
+
:src="upload.data.value[responseKey || 'url']"
|
|
62
|
+
alt="img-preview"
|
|
63
|
+
class="w-full rounded-lg"
|
|
64
|
+
/>
|
|
65
|
+
</Modal>
|
|
66
|
+
</div>
|
|
67
|
+
</div>
|
|
68
|
+
|
|
69
|
+
<div :class="[ui.imageItem.onPreview.previewTextWrapper]">
|
|
70
|
+
<p :class="[ui.imageItem.onPreview.previewText]">{{ selectedFile.name }}</p>
|
|
71
|
+
</div>
|
|
72
|
+
</div>
|
|
73
|
+
|
|
74
|
+
<!-- Failed State -->
|
|
75
|
+
<div v-if="selectedFile && upload.status.value.isError" class="w-full">
|
|
76
|
+
<div :class="[ui.imageItem.onFailed.wrapper]">
|
|
77
|
+
<img
|
|
78
|
+
:class="[ui.imageItem.onFailed.failedImgClass]"
|
|
79
|
+
:src="generateURL(selectedFile)"
|
|
80
|
+
alt="img"
|
|
81
|
+
/>
|
|
82
|
+
<div :class="[ui.imageItem.onFailed.failedActionWrapper]">
|
|
83
|
+
<Icon
|
|
84
|
+
title="ลบไฟล์"
|
|
85
|
+
:name="ui.action.deleteIcon"
|
|
86
|
+
:class="[ui.imageItem.onFailed.actionBtnClass]"
|
|
87
|
+
@click="handleDeleteFile"
|
|
88
|
+
/>
|
|
89
|
+
</div>
|
|
90
|
+
</div>
|
|
91
|
+
</div>
|
|
92
|
+
</div>
|
|
93
|
+
</div>
|
|
94
|
+
</FieldWrapper>
|
|
95
|
+
</template>
|
|
96
|
+
|
|
97
|
+
<script lang="ts" setup>
|
|
98
|
+
import { type IUploadImageAutoProps } from './types'
|
|
99
|
+
import FieldWrapper from '#core/components/Form/FieldWrapper.vue'
|
|
100
|
+
import { useFieldHOC } from '#core/composables/useForm'
|
|
101
|
+
import {
|
|
102
|
+
computed,
|
|
103
|
+
ref,
|
|
104
|
+
toRef,
|
|
105
|
+
useUI,
|
|
106
|
+
useUiConfig,
|
|
107
|
+
useWatchTrue,
|
|
108
|
+
useUploadLoader,
|
|
109
|
+
_get,
|
|
110
|
+
type IUploadRequest,
|
|
111
|
+
} from '#imports'
|
|
112
|
+
import { uploadImage } from '#core/ui.config'
|
|
113
|
+
import {
|
|
114
|
+
checkMaxSize,
|
|
115
|
+
generateURL,
|
|
116
|
+
useFileAllocate,
|
|
117
|
+
useFileProgress,
|
|
118
|
+
} from '#core/helpers/componentHelper'
|
|
119
|
+
import i18next from 'i18next'
|
|
120
|
+
|
|
121
|
+
const config = useUiConfig<typeof uploadImage>(uploadImage, 'uploadImage')
|
|
122
|
+
|
|
123
|
+
const props = withDefaults(defineProps<IUploadImageAutoProps>(), {
|
|
124
|
+
accept: 'image/*',
|
|
125
|
+
bodyKey: 'file',
|
|
126
|
+
responseKey: 'url',
|
|
127
|
+
uploadAddLabel: 'อัพโหลด',
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
const emits = defineEmits(['change', 'success', 'delete', 'error'])
|
|
131
|
+
|
|
132
|
+
const request: IUploadRequest = {
|
|
133
|
+
pathURL: props.uploadPathURL,
|
|
134
|
+
requestOptions: props.requestOptions,
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const selectedFile = ref<File>()
|
|
138
|
+
const isPreviewOpen = ref<boolean>(false)
|
|
139
|
+
|
|
140
|
+
const { wrapperProps, value, errorMessage } = useFieldHOC<string | undefined>(props)
|
|
141
|
+
|
|
142
|
+
const upload = useUploadLoader(request)
|
|
143
|
+
const { ui } = useUI('uploadImage', toRef(props, 'ui'), config)
|
|
144
|
+
|
|
145
|
+
const fileInputRef = ref<HTMLInputElement | null>()
|
|
146
|
+
|
|
147
|
+
const fileAllocate = useFileAllocate(toRef(selectedFile), props)
|
|
148
|
+
const { onUploadProgress, onDownloadProgress, percent } = useFileProgress()
|
|
149
|
+
const acceptFile = computed(() =>
|
|
150
|
+
typeof props.accept === 'string' ? props.accept : props.accept?.join(',')
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
const handleChange = (e: Event) => {
|
|
154
|
+
if (props.isDisabled) return
|
|
155
|
+
|
|
156
|
+
const file = (e.target as HTMLInputElement).files?.[0]
|
|
157
|
+
const result = handleCheckFileCondition(file)
|
|
158
|
+
|
|
159
|
+
if (result && file) {
|
|
160
|
+
selectedFile.value = file
|
|
161
|
+
emits('change', selectedFile.value)
|
|
162
|
+
const formData = new FormData()
|
|
163
|
+
|
|
164
|
+
formData.append(props.bodyKey, file)
|
|
165
|
+
upload.run(formData, { data: { onUploadProgress, onDownloadProgress } })
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const handleCheckFileCondition = (file: File | undefined): boolean => {
|
|
170
|
+
if (!file) return false
|
|
171
|
+
const maxSize = checkMaxSize(file, fileAllocate.acceptFileSizeKb.value)
|
|
172
|
+
|
|
173
|
+
if (!maxSize) {
|
|
174
|
+
if (fileAllocate.isAcceptFileUseMb.value) {
|
|
175
|
+
errorMessage.value = i18next.t('custom:invalid_file_size_mb', {
|
|
176
|
+
size: fileAllocate.acceptFileSizeMb.value,
|
|
177
|
+
})
|
|
178
|
+
} else {
|
|
179
|
+
errorMessage.value = i18next.t('custom:invalid_file_size_kb', {
|
|
180
|
+
size: fileAllocate.acceptFileSizeKb.value,
|
|
181
|
+
})
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return false
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
errorMessage.value = ''
|
|
188
|
+
|
|
189
|
+
return true
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const handleOpenFile = () => {
|
|
193
|
+
fileInputRef.value?.click()
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const handleDeleteFile = () => {
|
|
197
|
+
fileInputRef.value!.value = ''
|
|
198
|
+
selectedFile.value = undefined
|
|
199
|
+
value.value = undefined
|
|
200
|
+
emits('change', undefined)
|
|
201
|
+
|
|
202
|
+
emits('delete')
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
useWatchTrue(
|
|
206
|
+
() => upload.status.value.isSuccess,
|
|
207
|
+
() => {
|
|
208
|
+
const response = _get(upload.data.value, props.responseKey, '')
|
|
209
|
+
|
|
210
|
+
value.value = response
|
|
211
|
+
|
|
212
|
+
emits('success', response)
|
|
213
|
+
}
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
useWatchTrue(
|
|
217
|
+
() => upload.status.value.isError,
|
|
218
|
+
() => {
|
|
219
|
+
emits('error', upload.status.value.errorData)
|
|
220
|
+
}
|
|
221
|
+
)
|
|
222
|
+
</script>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type AxiosRequestConfig } from 'axios';
|
|
2
|
+
import { type IFieldProps, type IFormFieldBase, type INPUT_TYPES } from '../types';
|
|
3
|
+
export interface IUploadImageAutoProps extends IFieldProps {
|
|
4
|
+
requestOptions: Omit<AxiosRequestConfig, 'baseURL'> & {
|
|
5
|
+
baseURL: string;
|
|
6
|
+
};
|
|
7
|
+
uploadPathURL?: string;
|
|
8
|
+
uploadAddLabel?: string;
|
|
9
|
+
accept?: string[] | string;
|
|
10
|
+
bodyKey?: string;
|
|
11
|
+
responseKey?: string;
|
|
12
|
+
maxSize?: number;
|
|
13
|
+
}
|
|
14
|
+
export type IUploadImageAutoField = IFormFieldBase<INPUT_TYPES.UPLOAD_IMAGE_AUTO, IUploadImageAutoProps, {
|
|
15
|
+
change: (value: File | undefined) => void;
|
|
16
|
+
success: (res: any) => void;
|
|
17
|
+
delete: () => void;
|
|
18
|
+
error: (err: any) => void;
|
|
19
|
+
}>;
|
|
File without changes
|
|
@@ -11,12 +11,14 @@ import { type IDateTimeField } from '#core/components/Form/InputDateTime/date_ti
|
|
|
11
11
|
import { type IDateTimeRangeField } from '#core/components/Form/InputDateTimeRange/date_range_time_field.types';
|
|
12
12
|
import { type IUploadFileClassicField } from '#core/components/Form/InputUploadFileClassic/types';
|
|
13
13
|
import { type IUploadFileField } from '#core/components/Form/InputUploadFileClassicAuto/types';
|
|
14
|
+
import { type IUploadImageAutoField } from '#core/components/Form/InputUploadImageAuto/types';
|
|
14
15
|
import { type IUploadDropzoneField } from '#core/components/Form/InputUploadDropzone/types';
|
|
15
16
|
import { type IUploadDropzoneAutoField } from '#core/components/Form/InputUploadDropzoneAuto/types';
|
|
16
17
|
import type { INumberField } from '#core/components/Form/InputNumber/types';
|
|
17
18
|
import type { IUploadDropzoneAutoMultipleField } from '#core/components/Form/InputUploadDropzoneAutoMultiple/types';
|
|
18
19
|
import type { IUploadDropzoneImageAutoMultipleField } from '#core/components/Form/InputUploadDropzoneImageAutoMultiple/types';
|
|
19
20
|
import type { IWYSIWYGField } from '#core/components/Form/InputWYSIWYG/types';
|
|
21
|
+
import type { ITagsField } from '#core/components/Form/InputTags/types';
|
|
20
22
|
export declare const enum INPUT_TYPES {
|
|
21
23
|
TEXT = "TEXT",
|
|
22
24
|
NUMBER = "NUMBER",
|
|
@@ -34,11 +36,13 @@ export declare const enum INPUT_TYPES {
|
|
|
34
36
|
DATE_TIME_RANGE = "DATE_TIME_RANGE",
|
|
35
37
|
UPLOAD_FILE_CLASSIC = "UPLOAD_FILE_CLASSIC",
|
|
36
38
|
UPLOAD_FILE_CLASSIC_AUTO = "UPLOAD_FILE_CLASSIC_AUTO",
|
|
39
|
+
UPLOAD_IMAGE_AUTO = "UPLOAD_IMAGE_AUTO",
|
|
37
40
|
UPLOAD_DROPZONE = "UPLOAD_DROPZONE",
|
|
38
41
|
UPLOAD_DROPZONE_AUTO = "UPLOAD_DROPZONE_AUTO",
|
|
39
42
|
UPLOAD_DROPZONE_AUTO_MULTIPLE = "UPLOAD_DROPZONE_AUTO_MULTIPLE",
|
|
40
43
|
UPLOAD_DROPZONE_IMAGE_AUTO_MULTIPLE = "UPLOAD_DROPZONE_IMAGE_AUTO_MULTIPLE",
|
|
41
44
|
WYSIWYG = "WYSIWYG",
|
|
45
|
+
TAGS = "TAGS",
|
|
42
46
|
COMPONENT = "COMPONENT"
|
|
43
47
|
}
|
|
44
48
|
export interface IFieldProps {
|
|
@@ -68,4 +72,4 @@ export interface IFormFieldBase<I extends INPUT_TYPES, P extends IFieldProps, O>
|
|
|
68
72
|
props: P;
|
|
69
73
|
on?: O;
|
|
70
74
|
}
|
|
71
|
-
export type IFormField = ITextField | INumberField | IStaticField | ICheckboxField | IRadioField | ISelectField | IToggleField | ITextareaField | IDateTimeField | IDateTimeRangeField | IUploadFileClassicField | IUploadFileField | IUploadDropzoneField | IUploadDropzoneAutoField | IUploadDropzoneAutoMultipleField | IUploadDropzoneImageAutoMultipleField | IWYSIWYGField | IFormFieldBase<INPUT_TYPES.COMPONENT, any, any>;
|
|
75
|
+
export type IFormField = ITextField | INumberField | IStaticField | ICheckboxField | IRadioField | ISelectField | IToggleField | ITextareaField | IDateTimeField | IDateTimeRangeField | IUploadFileClassicField | IUploadFileField | IUploadImageAutoField | IUploadDropzoneField | IUploadDropzoneAutoField | IUploadDropzoneAutoMultipleField | IUploadDropzoneImageAutoMultipleField | IWYSIWYGField | ITagsField | IFormFieldBase<INPUT_TYPES.COMPONENT, any, any>;
|
|
@@ -15,11 +15,13 @@ export var INPUT_TYPES = /* @__PURE__ */ ((INPUT_TYPES2) => {
|
|
|
15
15
|
INPUT_TYPES2["DATE_TIME_RANGE"] = "DATE_TIME_RANGE";
|
|
16
16
|
INPUT_TYPES2["UPLOAD_FILE_CLASSIC"] = "UPLOAD_FILE_CLASSIC";
|
|
17
17
|
INPUT_TYPES2["UPLOAD_FILE_CLASSIC_AUTO"] = "UPLOAD_FILE_CLASSIC_AUTO";
|
|
18
|
+
INPUT_TYPES2["UPLOAD_IMAGE_AUTO"] = "UPLOAD_IMAGE_AUTO";
|
|
18
19
|
INPUT_TYPES2["UPLOAD_DROPZONE"] = "UPLOAD_DROPZONE";
|
|
19
20
|
INPUT_TYPES2["UPLOAD_DROPZONE_AUTO"] = "UPLOAD_DROPZONE_AUTO";
|
|
20
21
|
INPUT_TYPES2["UPLOAD_DROPZONE_AUTO_MULTIPLE"] = "UPLOAD_DROPZONE_AUTO_MULTIPLE";
|
|
21
22
|
INPUT_TYPES2["UPLOAD_DROPZONE_IMAGE_AUTO_MULTIPLE"] = "UPLOAD_DROPZONE_IMAGE_AUTO_MULTIPLE";
|
|
22
23
|
INPUT_TYPES2["WYSIWYG"] = "WYSIWYG";
|
|
24
|
+
INPUT_TYPES2["TAGS"] = "TAGS";
|
|
23
25
|
INPUT_TYPES2["COMPONENT"] = "COMPONENT";
|
|
24
26
|
return INPUT_TYPES2;
|
|
25
27
|
})(INPUT_TYPES || {});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export type UIComponentList = 'modal' | 'slideover' | 'dropdown' | 'icon' | 'button' | 'buttonGroup' | 'tabs' | 'card' | 'breadcrumb' | 'badge' | 'input' | 'pagination' | 'notification' | 'uploadFileInputClassicAuto' | 'uploadFileDropzone' | 'uploadFileDropzoneImage';
|
|
1
|
+
export type UIComponentList = 'modal' | 'slideover' | 'dropdown' | 'icon' | 'button' | 'buttonGroup' | 'tabs' | 'card' | 'breadcrumb' | 'badge' | 'input' | 'pagination' | 'notification' | 'uploadFileInputClassicAuto' | 'uploadFileDropzone' | 'uploadFileDropzoneImage' | 'uploadImage' | 'tags';
|
|
@@ -12,3 +12,5 @@ export { breadcrumb } from './breadcrumb';
|
|
|
12
12
|
export { uploadFileInputClassicAuto } from './uploadFileInputClassicAuto';
|
|
13
13
|
export { uploadFileDropzone } from './uploadFileDropzone';
|
|
14
14
|
export { uploadFileDropzoneImage } from './uploadDropzoneImage';
|
|
15
|
+
export { uploadImage } from './uploadImage';
|
|
16
|
+
export { tags } from './tags';
|
|
@@ -12,3 +12,5 @@ export { breadcrumb } from "./breadcrumb.mjs";
|
|
|
12
12
|
export { uploadFileInputClassicAuto } from "./uploadFileInputClassicAuto.mjs";
|
|
13
13
|
export { uploadFileDropzone } from "./uploadFileDropzone.mjs";
|
|
14
14
|
export { uploadFileDropzoneImage } from "./uploadDropzoneImage.mjs";
|
|
15
|
+
export { uploadImage } from "./uploadImage.mjs";
|
|
16
|
+
export { tags } from "./tags.mjs";
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export declare const tags: {
|
|
2
|
+
base: string;
|
|
3
|
+
border: string;
|
|
4
|
+
shadow: string;
|
|
5
|
+
padding: string;
|
|
6
|
+
stages: {
|
|
7
|
+
default: string;
|
|
8
|
+
error: string;
|
|
9
|
+
};
|
|
10
|
+
placeholder: string;
|
|
11
|
+
innerWrapper: string;
|
|
12
|
+
input: string;
|
|
13
|
+
tag: {
|
|
14
|
+
size: string;
|
|
15
|
+
color: string;
|
|
16
|
+
variant: string;
|
|
17
|
+
};
|
|
18
|
+
default: {
|
|
19
|
+
tag: {
|
|
20
|
+
size: string;
|
|
21
|
+
color: string;
|
|
22
|
+
variant: string;
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export const tags = {
|
|
2
|
+
base: "relative flex w-full flex-wrap items-center bg-white ring-1 ring-inset",
|
|
3
|
+
border: "rounded-md border-0",
|
|
4
|
+
shadow: "shadow-sm",
|
|
5
|
+
padding: "px-3.5 py-2.5",
|
|
6
|
+
stages: {
|
|
7
|
+
default: "has-[:focus]:ring-primary-500 ring-gray-300 has-[:focus]:ring-2",
|
|
8
|
+
error: "has-[:focus]:ring-danger-500 ring-danger-500 ring-danger-300 has-[:focus]:ring-2"
|
|
9
|
+
},
|
|
10
|
+
placeholder: "absolute left-3.5 top-2.5 text-sm text-gray-400",
|
|
11
|
+
innerWrapper: "mr-2 flex w-full flex-wrap items-center gap-2",
|
|
12
|
+
input: "m-0 grow p-0 text-sm text-gray-900 outline-none",
|
|
13
|
+
tag: {
|
|
14
|
+
size: "",
|
|
15
|
+
color: "",
|
|
16
|
+
variant: ""
|
|
17
|
+
},
|
|
18
|
+
default: {
|
|
19
|
+
tag: {
|
|
20
|
+
size: "sm",
|
|
21
|
+
color: "primary",
|
|
22
|
+
variant: "solid"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
};
|
|
@@ -9,7 +9,7 @@ export const uploadFileDropzoneImage = {
|
|
|
9
9
|
percentClass: "text-primary"
|
|
10
10
|
},
|
|
11
11
|
onPreview: {
|
|
12
|
-
wrapper: "relative size-24 overflow-hidden rounded-lg
|
|
12
|
+
wrapper: "relative size-24 overflow-hidden rounded-lg border-[1px] border-gray-100",
|
|
13
13
|
previewImgClass: "size-full object-cover",
|
|
14
14
|
previewActionWrapper: "absolute inset-0 z-10 flex items-center justify-center space-x-2 opacity-0 transition hover:bg-black/50 hover:opacity-100",
|
|
15
15
|
actionBtnClass: "size-7 cursor-pointer text-white",
|
|
@@ -17,7 +17,7 @@ export const uploadFileDropzoneImage = {
|
|
|
17
17
|
previewText: "truncate text-center text-sm"
|
|
18
18
|
},
|
|
19
19
|
onFailed: {
|
|
20
|
-
wrapper: "
|
|
20
|
+
wrapper: "border-danger border-dashed relative size-24 overflow-hidden rounded-lg border-[1px]",
|
|
21
21
|
failedImgClass: "size-full object-cover",
|
|
22
22
|
failedActionWrapper: "absolute inset-0 z-10 flex items-center justify-center space-x-2 bg-white/50",
|
|
23
23
|
actionBtnClass: "text-danger size-7 cursor-pointer"
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export declare const uploadImage: {
|
|
2
|
+
base: string;
|
|
3
|
+
imageItemWrapper: string;
|
|
4
|
+
imageItem: {
|
|
5
|
+
wrapper: string;
|
|
6
|
+
onLoading: {
|
|
7
|
+
wrapper: string;
|
|
8
|
+
percentClass: string;
|
|
9
|
+
};
|
|
10
|
+
onPreview: {
|
|
11
|
+
wrapper: string;
|
|
12
|
+
previewImgClass: string;
|
|
13
|
+
previewActionWrapper: string;
|
|
14
|
+
actionBtnClass: string;
|
|
15
|
+
previewTextWrapper: string;
|
|
16
|
+
previewText: string;
|
|
17
|
+
};
|
|
18
|
+
onFailed: {
|
|
19
|
+
wrapper: string;
|
|
20
|
+
failedImgClass: string;
|
|
21
|
+
failedActionWrapper: string;
|
|
22
|
+
actionBtnClass: string;
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
action: {
|
|
26
|
+
addingWrapper: string;
|
|
27
|
+
deleteIconClass: string;
|
|
28
|
+
addingBtnClass: string;
|
|
29
|
+
addingTextClass: string;
|
|
30
|
+
previewIcon: string;
|
|
31
|
+
deleteIcon: string;
|
|
32
|
+
addingIcon: string;
|
|
33
|
+
};
|
|
34
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export const uploadImage = {
|
|
2
|
+
base: "w-full overflow-hidden",
|
|
3
|
+
imageItemWrapper: "flex w-full flex-wrap gap-4",
|
|
4
|
+
imageItem: {
|
|
5
|
+
wrapper: "max-w-[96px]",
|
|
6
|
+
onLoading: {
|
|
7
|
+
wrapper: "flex size-24 flex-col items-center justify-center overflow-hidden rounded-lg border-[1px] border-dashed p-2",
|
|
8
|
+
percentClass: "text-primary"
|
|
9
|
+
},
|
|
10
|
+
onPreview: {
|
|
11
|
+
wrapper: "relative size-24 overflow-hidden rounded-lg border-[1px] border-gray-100",
|
|
12
|
+
previewImgClass: "size-full object-cover",
|
|
13
|
+
previewActionWrapper: "absolute inset-0 z-10 flex items-center justify-center space-x-2 opacity-0 transition hover:bg-black/50 hover:opacity-100",
|
|
14
|
+
actionBtnClass: "size-7 cursor-pointer text-white",
|
|
15
|
+
previewTextWrapper: "mt-2 truncate",
|
|
16
|
+
previewText: "truncate text-center text-sm"
|
|
17
|
+
},
|
|
18
|
+
onFailed: {
|
|
19
|
+
wrapper: "relative size-24 overflow-hidden rounded-lg border-[1px] border-dashed border-danger",
|
|
20
|
+
failedImgClass: "size-full object-cover",
|
|
21
|
+
failedActionWrapper: "absolute inset-0 z-10 flex items-center justify-center space-x-2 bg-white/50",
|
|
22
|
+
actionBtnClass: "text-danger size-7 cursor-pointer"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
action: {
|
|
26
|
+
// wrapper: 'flex items-center space-x-4',
|
|
27
|
+
addingWrapper: "flex size-24 flex-col items-center justify-center overflow-hidden rounded-lg border-[1px] border-dashed p-2 cursor-pointer transition hover:bg-gray-100",
|
|
28
|
+
// iconClass: 'size-6 text-gray-400 cursor-pointer',
|
|
29
|
+
deleteIconClass: "size-6 text-danger cursor-pointer",
|
|
30
|
+
addingBtnClass: "size-7 text-gray-500",
|
|
31
|
+
addingTextClass: "text-center text-sm text-gray-500",
|
|
32
|
+
previewIcon: "i-ic:outline-remove-red-eye",
|
|
33
|
+
deleteIcon: "ph:trash",
|
|
34
|
+
addingIcon: "i-material-symbols:add"
|
|
35
|
+
}
|
|
36
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@finema/core",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.109",
|
|
4
4
|
"repository": "https://gitlab.finema.co/finema/ui-kit",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Finema Dev Core Team",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@nuxt/kit": "^3.11.1",
|
|
39
|
-
"@nuxt/ui": "^2.15.
|
|
39
|
+
"@nuxt/ui": "^2.15.1",
|
|
40
40
|
"@pinia/nuxt": "^0.5.1",
|
|
41
41
|
"@vee-validate/nuxt": "^4.12.6",
|
|
42
42
|
"@vee-validate/zod": "^4.12.6",
|