@finema/core 2.6.2 → 2.7.0
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 +18 -6
- package/dist/runtime/components/DevToolsWindow/index.vue +6 -4
- package/dist/runtime/components/FlexDeck/Base.vue +4 -2
- package/dist/runtime/components/Form/Fields.vue +28 -19
- package/dist/runtime/components/Form/InputUploadDropzoneAuto/index.vue +114 -0
- package/dist/runtime/components/Form/InputUploadDropzoneAuto/index.vue.d.ts +19 -0
- package/dist/runtime/components/Form/InputUploadDropzoneAuto/types.d.ts +23 -0
- package/dist/runtime/components/Form/InputUploadDropzoneAuto/types.js +0 -0
- package/dist/runtime/components/Form/types.d.ts +2 -1
- package/dist/runtime/components/Image.vue +3 -3
- package/dist/runtime/components/Table/Base.vue +1 -1
- package/dist/runtime/components/Table/index.vue +4 -2
- package/dist/runtime/composables/useConfig.d.ts +1 -0
- package/dist/runtime/composables/useConfig.js +3 -0
- package/dist/runtime/composables/useDialog.js +3 -1
- package/dist/runtime/composables/useForm.d.ts +1 -1
- package/dist/runtime/composables/useForm.js +6 -2
- package/dist/runtime/helpers/apiBaseHelper.js +3 -1
- package/dist/runtime/helpers/componentHelper.d.ts +1 -0
- package/dist/runtime/helpers/componentHelper.js +5 -0
- package/dist/runtime/theme/button.js +5 -1
- package/dist/runtime/theme/dialog.js +15 -5
- package/dist/runtime/theme/form.js +3 -1
- package/dist/runtime/theme/icons.js +3 -1
- package/dist/runtime/theme/index.d.ts +1 -0
- package/dist/runtime/theme/index.js +1 -0
- package/dist/runtime/theme/input.js +6 -2
- package/dist/runtime/theme/inputNumber.js +6 -2
- package/dist/runtime/theme/loader.js +14 -4
- package/dist/runtime/theme/selectMenu.js +3 -1
- package/dist/runtime/theme/textarea.js +5 -1
- package/dist/runtime/theme/uploadFileDropzone.d.ts +24 -0
- package/dist/runtime/theme/uploadFileDropzone.js +24 -0
- package/dist/runtime/utils/FileHelper.js +3 -1
- package/package.json +5 -3
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -3,13 +3,17 @@ import defu from 'defu';
|
|
|
3
3
|
import * as theme from '../dist/runtime/theme/index.js';
|
|
4
4
|
|
|
5
5
|
const name = "@finema/core";
|
|
6
|
-
const version = "2.
|
|
6
|
+
const version = "2.7.0";
|
|
7
7
|
|
|
8
8
|
const nuxtAppOptions = {
|
|
9
9
|
head: {
|
|
10
|
-
htmlAttrs: {
|
|
10
|
+
htmlAttrs: {
|
|
11
|
+
lang: "en"
|
|
12
|
+
},
|
|
11
13
|
meta: [
|
|
12
|
-
{
|
|
14
|
+
{
|
|
15
|
+
charset: "utf-8"
|
|
16
|
+
},
|
|
13
17
|
{
|
|
14
18
|
name: "viewport",
|
|
15
19
|
content: "width=device-width, initial-scale=1"
|
|
@@ -68,7 +72,9 @@ const module = defineNuxtModule({
|
|
|
68
72
|
// Default configuration options of the Nuxt module
|
|
69
73
|
defaults: {},
|
|
70
74
|
async setup(_options, _nuxt) {
|
|
71
|
-
const {
|
|
75
|
+
const {
|
|
76
|
+
resolve
|
|
77
|
+
} = createResolver(import.meta.url);
|
|
72
78
|
const runtimeDir = resolve("./runtime");
|
|
73
79
|
_nuxt.options.build.transpile.push(runtimeDir);
|
|
74
80
|
_nuxt.options.alias["#core"] = runtimeDir;
|
|
@@ -82,7 +88,9 @@ const module = defineNuxtModule({
|
|
|
82
88
|
_nuxt.options.appConfig.core || {},
|
|
83
89
|
core
|
|
84
90
|
);
|
|
85
|
-
_nuxt.options.colorMode = {
|
|
91
|
+
_nuxt.options.colorMode = {
|
|
92
|
+
preference: "light"
|
|
93
|
+
};
|
|
86
94
|
_nuxt.options.appConfig.ui = {
|
|
87
95
|
colors: {
|
|
88
96
|
primary: "main",
|
|
@@ -109,7 +117,11 @@ const module = defineNuxtModule({
|
|
|
109
117
|
_nuxt.options.build
|
|
110
118
|
);
|
|
111
119
|
_nuxt.options.vite = defu(
|
|
112
|
-
{
|
|
120
|
+
{
|
|
121
|
+
optimizeDeps: {
|
|
122
|
+
include: [..._nuxt.options.vite?.optimizeDeps?.include || [], "@wdns/vue-code-block"]
|
|
123
|
+
}
|
|
124
|
+
},
|
|
113
125
|
_nuxt.options.vite
|
|
114
126
|
);
|
|
115
127
|
await installModule("@nuxt/ui", {
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
<!-- Draggable Title Bar -->
|
|
9
9
|
<div class="flex items-center justify-between px-2 py-1 select-none">
|
|
10
10
|
<p
|
|
11
|
-
class="text-sm font-semibold
|
|
11
|
+
class="flex-grow cursor-move text-sm font-semibold"
|
|
12
12
|
@mousedown.prevent="handleDragStart"
|
|
13
13
|
>
|
|
14
14
|
Debug Tools
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
<!-- Content Area Target for Logs -->
|
|
38
38
|
<div
|
|
39
39
|
id="dev-logs"
|
|
40
|
-
class="flex flex-
|
|
40
|
+
class="flex flex-1 flex-col space-y-1 overflow-auto p-2"
|
|
41
41
|
:style="{ height: `calc(${devToolsHeight} - 40px)` }"
|
|
42
42
|
/>
|
|
43
43
|
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
|
|
84
84
|
<!-- Toggle button for this DevToolsWindow -->
|
|
85
85
|
<div
|
|
86
|
-
class="fixed
|
|
86
|
+
class="fixed right-1 bottom-1 z-[99999]"
|
|
87
87
|
>
|
|
88
88
|
<Button
|
|
89
89
|
:icon="isShowDevTools ? 'heroicons:x-mark' : 'heroicons:information-circle'"
|
|
@@ -299,7 +299,9 @@ onMounted(() => {
|
|
|
299
299
|
}
|
|
300
300
|
});
|
|
301
301
|
}
|
|
302
|
-
}, {
|
|
302
|
+
}, {
|
|
303
|
+
immediate: true
|
|
304
|
+
});
|
|
303
305
|
});
|
|
304
306
|
onUnmounted(() => {
|
|
305
307
|
if (isDragging.value) handleDragEnd();
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
<div class="flex h-60 items-center justify-center">
|
|
41
41
|
<Icon
|
|
42
42
|
name="i-svg-spinners:180-ring-with-bg"
|
|
43
|
-
class="text-primary
|
|
43
|
+
class="size-8 text-primary"
|
|
44
44
|
/>
|
|
45
45
|
</div>
|
|
46
46
|
</slot>
|
|
@@ -108,7 +108,9 @@ const props = defineProps({
|
|
|
108
108
|
type: Boolean,
|
|
109
109
|
default: false
|
|
110
110
|
},
|
|
111
|
-
containerClass: {
|
|
111
|
+
containerClass: {
|
|
112
|
+
type: [String, Array, Object]
|
|
113
|
+
}
|
|
112
114
|
});
|
|
113
115
|
const bottomEdgeElement = ref(null);
|
|
114
116
|
const page = ref(props.pageOptions?.currentPage || 1);
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div
|
|
2
|
+
<div
|
|
3
3
|
:class="[theme.base({
|
|
4
4
|
class: [$props.class, ui?.base]
|
|
5
|
-
})]"
|
|
6
|
-
>
|
|
7
|
-
<component
|
|
8
|
-
:is="componentMap[option.type] || option.component"
|
|
9
|
-
v-for="option in options.filter((item) => !item.isHide)"
|
|
10
|
-
:key="option.props.name"
|
|
11
|
-
:class="option.class"
|
|
12
|
-
:form="form"
|
|
13
|
-
v-bind="getFieldBinding(option)"
|
|
14
|
-
:type="option.type === INPUT_TYPES.PASSWORD ? 'password' : void 0"
|
|
15
|
-
v-on="option.on ?? {}"
|
|
16
|
-
/>
|
|
17
|
-
</div>
|
|
5
|
+
})]"
|
|
6
|
+
>
|
|
7
|
+
<component
|
|
8
|
+
:is="componentMap[option.type] || option.component"
|
|
9
|
+
v-for="option in options.filter((item) => !item.isHide)"
|
|
10
|
+
:key="option.props.name"
|
|
11
|
+
:class="option.class"
|
|
12
|
+
:form="form"
|
|
13
|
+
v-bind="getFieldBinding(option)"
|
|
14
|
+
:type="option.type === INPUT_TYPES.PASSWORD ? 'password' : void 0"
|
|
15
|
+
v-on="option.on ?? {}"
|
|
16
|
+
/>
|
|
17
|
+
</div>
|
|
18
18
|
</template>
|
|
19
19
|
|
|
20
20
|
<script setup>
|
|
@@ -27,6 +27,7 @@ import FormInputCheckbox from "./InputCheckbox/index.vue";
|
|
|
27
27
|
import FormInputSelect from "./InputSelect/index.vue";
|
|
28
28
|
import FormInputSelectMultiple from "./InputSelectMultiple/index.vue";
|
|
29
29
|
import FormInputDateTime from "./InputDateTime/index.vue";
|
|
30
|
+
import FormInputUploadDropzoneAuto from "./InputUploadDropzoneAuto/index.vue";
|
|
30
31
|
import { INPUT_TYPES } from "#core/components/Form/types";
|
|
31
32
|
import { formTheme } from "#core/theme/form";
|
|
32
33
|
import { useUiConfig } from "#core/composables/useConfig";
|
|
@@ -63,13 +64,15 @@ const componentMap = {
|
|
|
63
64
|
[INPUT_TYPES.UPLOAD_FILE_CLASSIC_AUTO]: void 0,
|
|
64
65
|
[INPUT_TYPES.UPLOAD_IMAGE_AUTO]: void 0,
|
|
65
66
|
[INPUT_TYPES.UPLOAD_DROPZONE]: void 0,
|
|
66
|
-
[INPUT_TYPES.UPLOAD_DROPZONE_AUTO]:
|
|
67
|
+
[INPUT_TYPES.UPLOAD_DROPZONE_AUTO]: FormInputUploadDropzoneAuto,
|
|
67
68
|
[INPUT_TYPES.UPLOAD_DROPZONE_AUTO_MULTIPLE]: void 0,
|
|
68
69
|
[INPUT_TYPES.UPLOAD_DROPZONE_IMAGE_AUTO_MULTIPLE]: void 0,
|
|
69
70
|
[INPUT_TYPES.WYSIWYG]: void 0,
|
|
70
71
|
[INPUT_TYPES.TAGS]: void 0
|
|
71
72
|
};
|
|
72
|
-
const theme = computed(() => useUiConfig(formTheme, "form")({
|
|
73
|
+
const theme = computed(() => useUiConfig(formTheme, "form")({
|
|
74
|
+
orientation: props.orientation
|
|
75
|
+
}));
|
|
73
76
|
const getFieldBinding = (field) => {
|
|
74
77
|
const {
|
|
75
78
|
props: fieldProps,
|
|
@@ -77,14 +80,20 @@ const getFieldBinding = (field) => {
|
|
|
77
80
|
} = field;
|
|
78
81
|
const allProps = {
|
|
79
82
|
...fieldProps,
|
|
80
|
-
containerUi: {
|
|
83
|
+
containerUi: {
|
|
84
|
+
...fieldUi
|
|
85
|
+
}
|
|
81
86
|
};
|
|
82
87
|
if (props.orientation === "horizontal") {
|
|
83
88
|
return {
|
|
84
89
|
...allProps,
|
|
85
90
|
containerUi: {
|
|
86
|
-
root: theme.value.wrapper({
|
|
87
|
-
|
|
91
|
+
root: theme.value.wrapper({
|
|
92
|
+
class: [props.ui?.wrapper]
|
|
93
|
+
}),
|
|
94
|
+
labelWrapper: theme.value.container({
|
|
95
|
+
class: [props.ui?.container]
|
|
96
|
+
})
|
|
88
97
|
}
|
|
89
98
|
};
|
|
90
99
|
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<FieldWrapper v-bind="wrapperProps">
|
|
3
|
+
<div
|
|
4
|
+
ref="dropZoneRef"
|
|
5
|
+
:class="theme.base()"
|
|
6
|
+
>
|
|
7
|
+
<div :class="theme.wrapper()">
|
|
8
|
+
<div
|
|
9
|
+
v-if="!selectedFile && !value"
|
|
10
|
+
:class="[theme.placeholderWrapper()]"
|
|
11
|
+
>
|
|
12
|
+
<Icon
|
|
13
|
+
:name="useUiConfigStatic('uploadFileDropzone').uploadIcon"
|
|
14
|
+
:class="[theme.labelIcon()]"
|
|
15
|
+
/>
|
|
16
|
+
<div :class="[theme.labelWrapper()]">
|
|
17
|
+
<p
|
|
18
|
+
class="text-primary bg-primary-50 cursor-pointer"
|
|
19
|
+
@click="fileDialog.open"
|
|
20
|
+
>
|
|
21
|
+
{{ selectFileLabel }}
|
|
22
|
+
</p>
|
|
23
|
+
<p>{{ selectFileSubLabel }}</p>
|
|
24
|
+
</div>
|
|
25
|
+
<p
|
|
26
|
+
v-if="placeholder"
|
|
27
|
+
:class="theme.placeholder()"
|
|
28
|
+
>
|
|
29
|
+
{{ placeholder }}
|
|
30
|
+
</p>
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|
|
33
|
+
</div>
|
|
34
|
+
</FieldWrapper>
|
|
35
|
+
</template>
|
|
36
|
+
|
|
37
|
+
<script setup>
|
|
38
|
+
import { useDropZone, useFileDialog } from "@vueuse/core";
|
|
39
|
+
import { computed, ref, useTemplateRef } from "vue";
|
|
40
|
+
import FieldWrapper from "#core/components/Form/FieldWrapper.vue";
|
|
41
|
+
import { useFieldHOC } from "#core/composables/useForm";
|
|
42
|
+
import { uploadFileDropzoneTheme } from "#core/theme/uploadFileDropzone";
|
|
43
|
+
import { useUiConfig, useUiConfigStatic } from "#core/composables/useConfig";
|
|
44
|
+
import { useFileAllocate, useFileProgress, useFileSize } from "#core/helpers/componentHelper";
|
|
45
|
+
const props = defineProps({
|
|
46
|
+
requestOptions: { type: Object, required: true },
|
|
47
|
+
uploadPathURL: { type: String, required: false },
|
|
48
|
+
selectFileLabel: { type: String, required: false, default: "\u0E04\u0E25\u0E34\u0E01\u0E40\u0E1E\u0E37\u0E48\u0E2D\u0E40\u0E25\u0E37\u0E2D\u0E01\u0E44\u0E1F\u0E25\u0E4C" },
|
|
49
|
+
selectFileSubLabel: { type: String, required: false, default: "\u0E2B\u0E23\u0E37\u0E2D \u0E25\u0E32\u0E01\u0E41\u0E25\u0E30\u0E27\u0E32\u0E07\u0E17\u0E35\u0E48\u0E19\u0E35\u0E48" },
|
|
50
|
+
uploadingLabel: { type: String, required: false, default: "\u0E01\u0E33\u0E25\u0E31\u0E07\u0E2D\u0E31\u0E1E\u0E42\u0E2B\u0E25\u0E14..." },
|
|
51
|
+
uploadFailedLabel: { type: String, required: false, default: "\u0E2D\u0E31\u0E1E\u0E42\u0E2B\u0E25\u0E14\u0E25\u0E49\u0E21\u0E40\u0E2B\u0E25\u0E27, \u0E01\u0E23\u0E38\u0E13\u0E32\u0E25\u0E2D\u0E07\u0E2D\u0E35\u0E01\u0E04\u0E23\u0E31\u0E49\u0E07" },
|
|
52
|
+
retryLabel: { type: String, required: false },
|
|
53
|
+
accept: { type: [Array, String], required: false },
|
|
54
|
+
bodyKey: { type: String, required: false, default: "file" },
|
|
55
|
+
responseURL: { type: String, required: false, default: "url" },
|
|
56
|
+
responsePath: { type: String, required: false, default: "path" },
|
|
57
|
+
maxSize: { type: Number, required: false },
|
|
58
|
+
form: { type: Object, required: false },
|
|
59
|
+
name: { type: String, required: true },
|
|
60
|
+
errorMessage: { type: String, required: false },
|
|
61
|
+
label: { type: null, required: false },
|
|
62
|
+
description: { type: String, required: false },
|
|
63
|
+
hint: { type: String, required: false },
|
|
64
|
+
rules: { type: null, required: false },
|
|
65
|
+
autoFocus: { type: Boolean, required: false },
|
|
66
|
+
placeholder: { type: String, required: false },
|
|
67
|
+
disabled: { type: Boolean, required: false },
|
|
68
|
+
readonly: { type: Boolean, required: false },
|
|
69
|
+
required: { type: Boolean, required: false },
|
|
70
|
+
help: { type: String, required: false },
|
|
71
|
+
ui: { type: null, required: false }
|
|
72
|
+
});
|
|
73
|
+
const emits = defineEmits(["change", "success", "delete"]);
|
|
74
|
+
const {
|
|
75
|
+
wrapperProps,
|
|
76
|
+
handleChange: onChange,
|
|
77
|
+
setErrors,
|
|
78
|
+
value
|
|
79
|
+
} = useFieldHOC(props);
|
|
80
|
+
const dropZoneRef = useTemplateRef("dropZoneRef");
|
|
81
|
+
const theme = computed(() => useUiConfig(uploadFileDropzoneTheme, "uploadFileDropzone")({
|
|
82
|
+
dragover: dropzone.isOverDropZone.value
|
|
83
|
+
}));
|
|
84
|
+
const fileDialog = useFileDialog({
|
|
85
|
+
accept: typeof props.accept === "string" ? props.accept : props.accept?.join(","),
|
|
86
|
+
// Set to accept only image files
|
|
87
|
+
directory: false
|
|
88
|
+
// Select directories instead of files if set true
|
|
89
|
+
});
|
|
90
|
+
const selectedFile = ref();
|
|
91
|
+
const isPreviewOpen = ref(false);
|
|
92
|
+
const {
|
|
93
|
+
onUploadProgress,
|
|
94
|
+
onDownloadProgress,
|
|
95
|
+
percent
|
|
96
|
+
} = useFileProgress();
|
|
97
|
+
const fileAllocate = useFileAllocate(selectedFile, props);
|
|
98
|
+
const fileAllocateFromPath = computed(() => useFileSize(value.value?.size));
|
|
99
|
+
fileDialog.onChange((files) => {
|
|
100
|
+
console.log("Selected files:", files);
|
|
101
|
+
});
|
|
102
|
+
const onDrop = (files) => {
|
|
103
|
+
console.log("Selected files drop:", files);
|
|
104
|
+
};
|
|
105
|
+
const dropzone = useDropZone(dropZoneRef, {
|
|
106
|
+
onDrop,
|
|
107
|
+
// specify the types of data to be received.
|
|
108
|
+
dataTypes: typeof props.accept === "string" ? [props.accept] : props.accept,
|
|
109
|
+
// control multi-file drop
|
|
110
|
+
multiple: false,
|
|
111
|
+
// whether to prevent default behavior for unhandled events
|
|
112
|
+
preventDefaultForUnhandled: false
|
|
113
|
+
});
|
|
114
|
+
</script>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { IUploadDropzoneAutoProps } from './types.js';
|
|
2
|
+
declare const _default: import("vue").DefineComponent<IUploadDropzoneAutoProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
3
|
+
success: (...args: any[]) => void;
|
|
4
|
+
delete: (...args: any[]) => void;
|
|
5
|
+
change: (...args: any[]) => void;
|
|
6
|
+
}, string, import("vue").PublicProps, Readonly<IUploadDropzoneAutoProps> & Readonly<{
|
|
7
|
+
onSuccess?: ((...args: any[]) => any) | undefined;
|
|
8
|
+
onDelete?: ((...args: any[]) => any) | undefined;
|
|
9
|
+
onChange?: ((...args: any[]) => any) | undefined;
|
|
10
|
+
}>, {
|
|
11
|
+
selectFileLabel: string;
|
|
12
|
+
selectFileSubLabel: string;
|
|
13
|
+
uploadingLabel: string;
|
|
14
|
+
uploadFailedLabel: string;
|
|
15
|
+
bodyKey: string;
|
|
16
|
+
responseURL: string;
|
|
17
|
+
responsePath: string;
|
|
18
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
19
|
+
export default _default;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { AxiosRequestConfig } from 'axios';
|
|
2
|
+
import type { IFieldProps, IFormFieldBase, INPUT_TYPES } from '../types.js';
|
|
3
|
+
export interface IUploadDropzoneAutoProps extends IFieldProps {
|
|
4
|
+
requestOptions: Omit<AxiosRequestConfig, 'baseURL'> & {
|
|
5
|
+
baseURL: string;
|
|
6
|
+
};
|
|
7
|
+
uploadPathURL?: string;
|
|
8
|
+
selectFileLabel?: string;
|
|
9
|
+
selectFileSubLabel?: string;
|
|
10
|
+
uploadingLabel?: string;
|
|
11
|
+
uploadFailedLabel?: string;
|
|
12
|
+
retryLabel?: string;
|
|
13
|
+
accept?: string[] | string;
|
|
14
|
+
bodyKey?: string;
|
|
15
|
+
responseURL?: string;
|
|
16
|
+
responsePath?: string;
|
|
17
|
+
maxSize?: number;
|
|
18
|
+
}
|
|
19
|
+
export type IUploadDropzoneAutoField = IFormFieldBase<INPUT_TYPES.UPLOAD_DROPZONE_AUTO, IUploadDropzoneAutoProps, {
|
|
20
|
+
change: (value: File | undefined) => void;
|
|
21
|
+
success: (res: any) => void;
|
|
22
|
+
delete: () => void;
|
|
23
|
+
}>;
|
|
File without changes
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Component } from '@nuxt/schema';
|
|
2
2
|
import type { FormContext } from 'vee-validate';
|
|
3
|
+
import type { IUploadDropzoneAutoField } from './InputUploadDropzoneAuto/types.js';
|
|
3
4
|
import type { ITextField } from '#core/components/Form/InputText/types';
|
|
4
5
|
import type { ITextareaField } from '#core/components/Form/InputTextarea/types';
|
|
5
6
|
import type { IToggleField } from '#core/components/Form/InputToggle/types';
|
|
@@ -60,7 +61,7 @@ export interface IFormFieldBase<I extends INPUT_TYPES, P extends IFieldProps, O>
|
|
|
60
61
|
props: P;
|
|
61
62
|
on?: O;
|
|
62
63
|
}
|
|
63
|
-
export type IFormField = ITextField | INumberField | ITextareaField | IToggleField | ISelectField | ICheckboxField | ISelectMultipleField | IDateTimeField | IFormFieldBase<INPUT_TYPES.COMPONENT, any, any>;
|
|
64
|
+
export type IFormField = ITextField | INumberField | ITextareaField | IToggleField | ISelectField | ICheckboxField | ISelectMultipleField | IDateTimeField | IUploadDropzoneAutoField | IFormFieldBase<INPUT_TYPES.COMPONENT, any, any>;
|
|
64
65
|
export interface IFileValue {
|
|
65
66
|
url: string;
|
|
66
67
|
path?: string;
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<template #loading>
|
|
4
4
|
<slot name="loading">
|
|
5
5
|
<div
|
|
6
|
-
class="
|
|
6
|
+
class="flex h-full w-full items-center justify-center"
|
|
7
7
|
>
|
|
8
8
|
<Loader
|
|
9
9
|
:loading="true"
|
|
@@ -15,12 +15,12 @@
|
|
|
15
15
|
<template #error>
|
|
16
16
|
<slot name="error">
|
|
17
17
|
<div
|
|
18
|
-
class="
|
|
18
|
+
class="flex h-full w-full items-center justify-center"
|
|
19
19
|
>
|
|
20
20
|
<p class="text-error-400">
|
|
21
21
|
<Icon
|
|
22
22
|
name="i-heroicons:exclamation-circle-solid"
|
|
23
|
-
class="text-error-400
|
|
23
|
+
class="size-8 text-error-400"
|
|
24
24
|
/>
|
|
25
25
|
</p>
|
|
26
26
|
</div>
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
name="error"
|
|
54
54
|
>
|
|
55
55
|
<div
|
|
56
|
-
class="
|
|
56
|
+
class="flex h-[200px] items-center justify-center text-2xl text-error-400"
|
|
57
57
|
>
|
|
58
58
|
{{ StringHelper.getError(options.status.errorData) }}
|
|
59
59
|
</div>
|
|
@@ -173,6 +173,8 @@ const totalCountWithComma = computed(() => {
|
|
|
173
173
|
return StringHelper.withComma(total);
|
|
174
174
|
});
|
|
175
175
|
const transformValue = (column, row) => {
|
|
176
|
-
return column.cell ? column.cell({
|
|
176
|
+
return column.cell ? column.cell({
|
|
177
|
+
row
|
|
178
|
+
}) : row.getValue(column.accessorKey);
|
|
177
179
|
};
|
|
178
180
|
</script>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { core as Core } from '../../core.config.js';
|
|
2
2
|
export declare const useCoreConfig: () => typeof Core;
|
|
3
3
|
export declare const useUiConfig: (config: object, name: string) => any;
|
|
4
|
+
export declare const useUiConfigStatic: (name: string) => any;
|
|
4
5
|
export declare const useUiAllConfig: () => any;
|
|
@@ -10,7 +10,9 @@ export var DialogType = /* @__PURE__ */ ((DialogType2) => {
|
|
|
10
10
|
export const useDialog = () => {
|
|
11
11
|
const overlay = useOverlay();
|
|
12
12
|
const openDialog = async (payload) => {
|
|
13
|
-
const modal = overlay.create(Dialog, {
|
|
13
|
+
const modal = overlay.create(Dialog, {
|
|
14
|
+
props: payload
|
|
15
|
+
});
|
|
14
16
|
const result = await modal.open();
|
|
15
17
|
const res = await result.result;
|
|
16
18
|
return new Promise((resolve, reject) => {
|
|
@@ -6,7 +6,7 @@ interface IFieldContext<TValue> extends FieldContext<TValue> {
|
|
|
6
6
|
}
|
|
7
7
|
export declare const useFieldHOC: <TValue = unknown>(newFormProps: IFieldProps, opts?: Partial<FieldOptions<TValue>>) => IFieldContext<TValue>;
|
|
8
8
|
export declare const createFormFields: (fields: () => IFormField[]) => ComputedRef<IFormField[]>;
|
|
9
|
-
export declare const moveToError: ({ errors }: {
|
|
9
|
+
export declare const moveToError: ({ errors, }: {
|
|
10
10
|
errors: any;
|
|
11
11
|
}) => void;
|
|
12
12
|
export {};
|
|
@@ -21,11 +21,15 @@ export const useFieldHOC = (newFormProps, opts) => {
|
|
|
21
21
|
};
|
|
22
22
|
};
|
|
23
23
|
export const createFormFields = (fields) => computed(fields);
|
|
24
|
-
export const moveToError = ({
|
|
24
|
+
export const moveToError = ({
|
|
25
|
+
errors
|
|
26
|
+
}) => {
|
|
25
27
|
const firstErrorFieldName = Object.keys(errors)[0];
|
|
26
28
|
const el = document.querySelector(`[name="${firstErrorFieldName}"]`);
|
|
27
29
|
if (el) {
|
|
28
|
-
el.focus({
|
|
30
|
+
el.focus({
|
|
31
|
+
preventScroll: true
|
|
32
|
+
});
|
|
29
33
|
const elementRect = el.getBoundingClientRect();
|
|
30
34
|
const absoluteElementTop = elementRect.top + window.scrollY;
|
|
31
35
|
const paddingTop = 60;
|
|
@@ -17,7 +17,9 @@ export const prepareRequestOptions = (baseOptions, requestOptions, params) => {
|
|
|
17
17
|
...baseOptions || {},
|
|
18
18
|
...requestOptions || {}
|
|
19
19
|
};
|
|
20
|
-
options.params = ParamHelper.getParams({
|
|
20
|
+
options.params = ParamHelper.getParams({
|
|
21
|
+
params
|
|
22
|
+
}, options);
|
|
21
23
|
return options;
|
|
22
24
|
};
|
|
23
25
|
export const handleApiRequest = async (requestContext, mockData, callbacks) => {
|
|
@@ -4,6 +4,7 @@ export declare const checkFileType: (file: File, acceptFileType: string | string
|
|
|
4
4
|
export declare const generateURL: (file: File) => string;
|
|
5
5
|
export declare const isImage: (file: File) => boolean;
|
|
6
6
|
export declare const isImageFromPath: (path?: string) => boolean;
|
|
7
|
+
export declare const isVideoFromPath: (path?: string) => boolean;
|
|
7
8
|
export declare const isPDFFromPath: (path?: string) => boolean;
|
|
8
9
|
export declare const useFileAllocate: (selectedFile: Ref<File | undefined | null>, props: {
|
|
9
10
|
accept?: string | string[];
|
|
@@ -41,6 +41,11 @@ export const isImageFromPath = (path = "") => {
|
|
|
41
41
|
const extension = path.toLowerCase().substring(path.lastIndexOf("."));
|
|
42
42
|
return imageExtensions.includes(extension);
|
|
43
43
|
};
|
|
44
|
+
export const isVideoFromPath = (path = "") => {
|
|
45
|
+
const imageExtensions = [".mp4"];
|
|
46
|
+
const extension = path.toLowerCase().substring(path.lastIndexOf("."));
|
|
47
|
+
return imageExtensions.includes(extension);
|
|
48
|
+
};
|
|
44
49
|
export const isPDFFromPath = (path = "") => {
|
|
45
50
|
const imageExtensions = [".pdf"];
|
|
46
51
|
const extension = path.toLowerCase().substring(path.lastIndexOf("."));
|
|
@@ -18,13 +18,23 @@ export const dialogTheme = {
|
|
|
18
18
|
},
|
|
19
19
|
variants: {
|
|
20
20
|
color: {
|
|
21
|
-
success: {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
success: {
|
|
22
|
+
icon: "text-success"
|
|
23
|
+
},
|
|
24
|
+
info: {
|
|
25
|
+
icon: "text-info"
|
|
26
|
+
},
|
|
27
|
+
warning: {
|
|
28
|
+
icon: "text-warning"
|
|
29
|
+
},
|
|
30
|
+
error: {
|
|
31
|
+
icon: "text-error"
|
|
32
|
+
}
|
|
25
33
|
},
|
|
26
34
|
confirm: {
|
|
27
|
-
true: {
|
|
35
|
+
true: {
|
|
36
|
+
icon: "text-info"
|
|
37
|
+
},
|
|
28
38
|
false: {}
|
|
29
39
|
}
|
|
30
40
|
},
|
|
@@ -9,3 +9,4 @@ export { tableTheme as table } from './table.js';
|
|
|
9
9
|
export { formTheme as form } from './form.js';
|
|
10
10
|
export { inputNumberTheme as inputNumber } from './inputNumber.js';
|
|
11
11
|
export { iconsTheme as icons } from './icons.js';
|
|
12
|
+
export { uploadFileDropzoneTheme as uploadFileDropzone } from './uploadFileDropzone.js';
|
|
@@ -9,3 +9,4 @@ export { tableTheme as table } from "./table.js";
|
|
|
9
9
|
export { formTheme as form } from "./form.js";
|
|
10
10
|
export { inputNumberTheme as inputNumber } from "./inputNumber.js";
|
|
11
11
|
export { iconsTheme as icons } from "./icons.js";
|
|
12
|
+
export { uploadFileDropzoneTheme as uploadFileDropzone } from "./uploadFileDropzone.js";
|
|
@@ -5,11 +5,21 @@ export const loaderTheme = {
|
|
|
5
5
|
},
|
|
6
6
|
variants: {
|
|
7
7
|
size: {
|
|
8
|
-
sm: {
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
sm: {
|
|
9
|
+
icon: "text-2xl"
|
|
10
|
+
},
|
|
11
|
+
md: {
|
|
12
|
+
icon: "text-4xl"
|
|
13
|
+
},
|
|
14
|
+
lg: {
|
|
15
|
+
icon: "text-6xl"
|
|
16
|
+
}
|
|
11
17
|
},
|
|
12
|
-
color: {
|
|
18
|
+
color: {
|
|
19
|
+
primary: {
|
|
20
|
+
icon: "text-primary"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
13
23
|
},
|
|
14
24
|
defaultVariants: {
|
|
15
25
|
size: "md",
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export declare const uploadFileDropzoneTheme: {
|
|
2
|
+
slots: {
|
|
3
|
+
base: string;
|
|
4
|
+
wrapper: string;
|
|
5
|
+
disabled: string;
|
|
6
|
+
failed: string;
|
|
7
|
+
placeholderWrapper: string;
|
|
8
|
+
placeholder: string;
|
|
9
|
+
labelWrapper: string;
|
|
10
|
+
filePreviewIcon: string;
|
|
11
|
+
uploadIcon: string;
|
|
12
|
+
placeholderImgIcon: string;
|
|
13
|
+
failedImgIcon: string;
|
|
14
|
+
loadingIcon: string;
|
|
15
|
+
labelIcon: string;
|
|
16
|
+
};
|
|
17
|
+
variants: {
|
|
18
|
+
dragover: {
|
|
19
|
+
true: {
|
|
20
|
+
base: string;
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export const uploadFileDropzoneTheme = {
|
|
2
|
+
slots: {
|
|
3
|
+
base: "relative w-full p-4 transition rounded-lg flex items-center justify-center ring-1 bg-white ring-gray-300",
|
|
4
|
+
wrapper: "flex flex-col items-center w-full",
|
|
5
|
+
disabled: "bg-gray-100 border-none grayscale cursor-not-allowed",
|
|
6
|
+
failed: "border-danger",
|
|
7
|
+
placeholderWrapper: "py-4 flex flex-col items-center justify-center",
|
|
8
|
+
placeholder: "text-gray-400 text-center font-light text-sm truncate",
|
|
9
|
+
labelWrapper: "flex items-center space-x-2 text-gray-400 text-center",
|
|
10
|
+
filePreviewIcon: "i-heroicons:document-text-solid",
|
|
11
|
+
uploadIcon: "i-ph:cloud-arrow-up",
|
|
12
|
+
placeholderImgIcon: "i-material-symbols:imagesmode-outline",
|
|
13
|
+
failedImgIcon: "i-material-symbols:imagesmode-outline",
|
|
14
|
+
loadingIcon: "i-svg-spinners:180-ring-with-bg",
|
|
15
|
+
labelIcon: "w-6 h-6 text-gray-400 text-center mb-4"
|
|
16
|
+
},
|
|
17
|
+
variants: {
|
|
18
|
+
dragover: {
|
|
19
|
+
true: {
|
|
20
|
+
base: "ring-primary bg-primary-50"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
};
|
|
@@ -24,6 +24,8 @@ export class FileHelper {
|
|
|
24
24
|
static dataURLtoFile = async (dataUrl, filename) => {
|
|
25
25
|
const res = await fetch(dataUrl);
|
|
26
26
|
const blob = await res.blob();
|
|
27
|
-
return new File([blob], filename, {
|
|
27
|
+
return new File([blob], filename, {
|
|
28
|
+
type: "image/png"
|
|
29
|
+
});
|
|
28
30
|
};
|
|
29
31
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@finema/core",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.7.0",
|
|
4
4
|
"repository": "https://gitlab.finema.co/finema/ui-kit",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Finema Dev Core Team",
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
"exports": {
|
|
9
9
|
".": {
|
|
10
10
|
"types": "./dist/types.d.mts",
|
|
11
|
+
"style": "./dist/runtime/styles/main.css",
|
|
11
12
|
"default": "./dist/module.mjs"
|
|
12
13
|
}
|
|
13
14
|
},
|
|
@@ -38,7 +39,7 @@
|
|
|
38
39
|
"dependencies": {
|
|
39
40
|
"@nuxt/kit": "^3.17.4",
|
|
40
41
|
"@nuxt/ui": "^3.1.3",
|
|
41
|
-
"@pinia/nuxt": "
|
|
42
|
+
"@pinia/nuxt": "0.7.0",
|
|
42
43
|
"@tiptap/extension-image": "^2.8.0",
|
|
43
44
|
"@tiptap/extension-link": "^2.8.0",
|
|
44
45
|
"@tiptap/extension-text-align": "^2.8.0",
|
|
@@ -66,6 +67,7 @@
|
|
|
66
67
|
"url-join": "^5.0.0"
|
|
67
68
|
},
|
|
68
69
|
"devDependencies": {
|
|
70
|
+
"@hyoban/eslint-plugin-tailwindcss": "^4.0.0-alpha.12",
|
|
69
71
|
"@eslint/js": "^9.26.0",
|
|
70
72
|
"@nuxt/devtools": "^2.4.1",
|
|
71
73
|
"@nuxt/eslint-config": "^1.3.1",
|
|
@@ -89,6 +91,6 @@
|
|
|
89
91
|
"vue-tsc": "^2.2.10"
|
|
90
92
|
},
|
|
91
93
|
"lint-staged": {
|
|
92
|
-
"*": "eslint --fix
|
|
94
|
+
"*": "eslint --fix"
|
|
93
95
|
}
|
|
94
96
|
}
|