@finema/core 1.2.5 → 1.3.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/README.md +88 -94
- package/dist/module.d.mts +3 -3
- package/dist/module.d.ts +3 -3
- package/dist/module.json +1 -1
- package/dist/module.mjs +98 -75
- package/dist/runtime/components/Button/Group.vue +31 -0
- package/dist/runtime/components/Button/index.vue +17 -0
- package/dist/runtime/components/Dialog/index.vue +63 -0
- package/dist/runtime/components/Form/FieldWrapper.vue +10 -0
- package/dist/runtime/components/Form/Fields.vue +41 -0
- package/dist/runtime/components/Form/InputSelect/SelectMenu.vue +11 -0
- package/dist/runtime/components/Form/InputSelect/index.vue +11 -0
- package/dist/runtime/components/Form/InputStatic/index.vue +16 -0
- package/dist/runtime/components/Form/InputStatic/types.d.ts +4 -0
- package/dist/runtime/components/Form/InputStatic/types.mjs +0 -0
- package/dist/runtime/components/Form/InputText/index.vue +28 -0
- package/dist/runtime/components/Form/InputText/types.d.ts +10 -0
- package/dist/runtime/components/Form/InputText/types.mjs +0 -0
- package/dist/runtime/components/Form/InputToggle/index.vue +14 -0
- package/dist/runtime/components/Form/InputToggle/types.d.ts +6 -0
- package/dist/runtime/components/Form/InputToggle/types.mjs +0 -0
- package/dist/runtime/components/Form/index.vue +6 -0
- package/dist/runtime/components/Form/types.d.ts +47 -0
- package/dist/runtime/components/Form/types.mjs +8 -0
- package/dist/runtime/components/Icon.vue +11 -0
- package/dist/runtime/components/Loader.vue +6 -0
- package/dist/runtime/components/Modal/index.vue +145 -0
- package/dist/runtime/components/Slideover/index.vue +109 -0
- package/dist/runtime/components/Table/ColumnImage.vue +13 -0
- package/dist/runtime/components/Table/ColumnNumber.vue +14 -0
- package/dist/runtime/components/Table/index.vue +84 -11
- package/dist/runtime/components/Table/types.d.ts +2 -17
- package/dist/runtime/components/Table/types.mjs +1 -6
- package/dist/runtime/composables/loaderPage.mjs +2 -4
- package/dist/runtime/composables/useConfig.d.ts +3 -0
- package/dist/runtime/composables/useConfig.mjs +9 -0
- package/dist/runtime/composables/useDialog.d.ts +26 -0
- package/dist/runtime/composables/useDialog.mjs +81 -0
- package/dist/runtime/composables/useForm.d.ts +24 -0
- package/dist/runtime/composables/useForm.mjs +44 -0
- package/dist/runtime/composables/useTable.d.ts +0 -2
- package/dist/runtime/composables/useTable.mjs +4 -8
- package/dist/runtime/core.config.d.ts +1 -1
- package/dist/runtime/core.config.mjs +1 -1
- package/dist/runtime/helpers/apiPageHelper.mjs +2 -4
- package/dist/runtime/plugin.mjs +1 -1
- package/dist/runtime/types/common.d.ts +3 -0
- package/dist/runtime/types/config.d.ts +1 -0
- package/dist/runtime/types/config.mjs +0 -0
- package/dist/runtime/ui.config.d.ts +2 -0
- package/dist/runtime/ui.config.mjs +44 -0
- package/dist/runtime/ui.css +14 -0
- package/dist/runtime/utils/ParamHelper.d.ts +2 -2
- package/dist/runtime/utils/StringHelper.mjs +1 -1
- package/dist/runtime/utils/lodash.d.ts +7 -0
- package/dist/runtime/utils/lodash.mjs +1 -0
- package/dist/types.d.mts +1 -1
- package/dist/types.d.ts +1 -1
- package/package.json +10 -12
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type IFieldProps, type IFormFieldBase, type INPUT_TYPES } from '#core/components/Form/types';
|
|
2
|
+
export interface ITextFieldProps extends IFieldProps {
|
|
3
|
+
type?: 'text' | 'password' | 'email';
|
|
4
|
+
prependIcon?: any;
|
|
5
|
+
appendIcon?: any;
|
|
6
|
+
}
|
|
7
|
+
export type ITextField = IFormFieldBase<INPUT_TYPES.TEXT | INPUT_TYPES.PASSWORD, ITextFieldProps, {
|
|
8
|
+
change?: (value: string) => void;
|
|
9
|
+
blur?: (value: string) => void;
|
|
10
|
+
}>;
|
|
File without changes
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<FieldWrapper v-bind="wrapperProps">
|
|
3
|
+
<UToggle v-model="value" :disabled="disabled" :name="name" />
|
|
4
|
+
</FieldWrapper>
|
|
5
|
+
</template>
|
|
6
|
+
|
|
7
|
+
<script lang="ts" setup>
|
|
8
|
+
import { useFieldHOC } from '#core/composables/useForm'
|
|
9
|
+
import { type IToggleFieldProps } from '#core/components/Form/InputToggle/types'
|
|
10
|
+
import FieldWrapper from '#core/components/Form/FieldWrapper.vue'
|
|
11
|
+
|
|
12
|
+
const props = withDefaults(defineProps<IToggleFieldProps>(), {})
|
|
13
|
+
const { value, wrapperProps, disabled, handleChange } = useFieldHOC<boolean>(props)
|
|
14
|
+
</script>
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type IFieldProps, type IFormFieldBase, type INPUT_TYPES } from '#core/components/Form/types';
|
|
2
|
+
export interface IToggleFieldProps extends IFieldProps {
|
|
3
|
+
}
|
|
4
|
+
export type IToggleField = IFormFieldBase<INPUT_TYPES.TOGGLE, IToggleFieldProps, {
|
|
5
|
+
change?: (value: string) => void;
|
|
6
|
+
}>;
|
|
File without changes
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { type Component } from '@nuxt/schema';
|
|
2
|
+
import { type FormContext, type RuleExpression } from 'vee-validate';
|
|
3
|
+
import { type ITextField } from '#core/components/Form/InputText/types';
|
|
4
|
+
import { type IStaticField } from '#core/components/Form/InputStatic/types';
|
|
5
|
+
export declare const enum INPUT_TYPES {
|
|
6
|
+
TEXT = "TEXT",
|
|
7
|
+
PASSWORD = "PASSWORD",
|
|
8
|
+
STATIC = "STATIC",
|
|
9
|
+
TOGGLE = "TOGGLE",
|
|
10
|
+
SELECT = "SELECT"
|
|
11
|
+
}
|
|
12
|
+
export interface IOption {
|
|
13
|
+
label: string;
|
|
14
|
+
value: any;
|
|
15
|
+
}
|
|
16
|
+
export interface IRadioOption {
|
|
17
|
+
label: string | any;
|
|
18
|
+
value: any;
|
|
19
|
+
}
|
|
20
|
+
export interface IFieldProps {
|
|
21
|
+
form?: FormContext;
|
|
22
|
+
name: string;
|
|
23
|
+
label?: string | any;
|
|
24
|
+
rules?: RuleExpression<any> | any;
|
|
25
|
+
autoFocus?: boolean;
|
|
26
|
+
class?: any;
|
|
27
|
+
classInner?: any;
|
|
28
|
+
classInputInner?: any;
|
|
29
|
+
placeholder?: string;
|
|
30
|
+
isDisabled?: boolean;
|
|
31
|
+
isReadOnly?: boolean;
|
|
32
|
+
isLoading?: boolean;
|
|
33
|
+
help?: string;
|
|
34
|
+
isHideLabel?: boolean;
|
|
35
|
+
customErrorMessage?: string | any;
|
|
36
|
+
transform?: (value: any, oldValue: any, e: InputEvent) => any;
|
|
37
|
+
getInstance?: (el: HTMLElement) => void;
|
|
38
|
+
}
|
|
39
|
+
export interface IFormFieldBase<I extends INPUT_TYPES, P extends object = never, O extends object = never> {
|
|
40
|
+
type: I | INPUT_TYPES;
|
|
41
|
+
component?: Component;
|
|
42
|
+
class?: any;
|
|
43
|
+
isHide?: boolean;
|
|
44
|
+
props: IFieldProps & P;
|
|
45
|
+
on?: O;
|
|
46
|
+
}
|
|
47
|
+
export type IFormField = ITextField | IStaticField;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export var INPUT_TYPES = /* @__PURE__ */ ((INPUT_TYPES2) => {
|
|
2
|
+
INPUT_TYPES2["TEXT"] = "TEXT";
|
|
3
|
+
INPUT_TYPES2["PASSWORD"] = "PASSWORD";
|
|
4
|
+
INPUT_TYPES2["STATIC"] = "STATIC";
|
|
5
|
+
INPUT_TYPES2["TOGGLE"] = "TOGGLE";
|
|
6
|
+
INPUT_TYPES2["SELECT"] = "SELECT";
|
|
7
|
+
return INPUT_TYPES2;
|
|
8
|
+
})(INPUT_TYPES || {});
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<UModal
|
|
3
|
+
v-bind="attrs"
|
|
4
|
+
:model-value="modelValue"
|
|
5
|
+
:overlay="overlay"
|
|
6
|
+
:transition="transition"
|
|
7
|
+
:prevent-close="preventClose"
|
|
8
|
+
:fullscreen="fullscreen"
|
|
9
|
+
:initial-focus="modalWrapper"
|
|
10
|
+
:ui="ui"
|
|
11
|
+
@update:model-value="$emit('update:modelValue', $event)"
|
|
12
|
+
>
|
|
13
|
+
<div
|
|
14
|
+
v-if="title"
|
|
15
|
+
:class="[ui.header, { 'flex items-center justify-between': !isHideCloseBtn }]"
|
|
16
|
+
>
|
|
17
|
+
<h1 class="text-xl font-medium">{{ title }}</h1>
|
|
18
|
+
<Icon
|
|
19
|
+
v-if="!isHideCloseBtn"
|
|
20
|
+
name="i-heroicons-x-mark"
|
|
21
|
+
class="h-6 w-6 cursor-pointer"
|
|
22
|
+
@click="close"
|
|
23
|
+
/>
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
<div
|
|
27
|
+
v-if="(!title && !isHideCloseBtn && preventClose) || fullscreen"
|
|
28
|
+
class="absolute right-0 m-4"
|
|
29
|
+
>
|
|
30
|
+
<Icon
|
|
31
|
+
v-if="!isHideCloseBtn"
|
|
32
|
+
name="i-heroicons-x-mark"
|
|
33
|
+
class="h-6 w-6 cursor-pointer"
|
|
34
|
+
@click="close"
|
|
35
|
+
/>
|
|
36
|
+
</div>
|
|
37
|
+
|
|
38
|
+
<div ref="modalWrapper" :class="['overflow-y-auto', ui.innerWrapper]">
|
|
39
|
+
<slot />
|
|
40
|
+
</div>
|
|
41
|
+
</UModal>
|
|
42
|
+
</template>
|
|
43
|
+
|
|
44
|
+
<script lang="ts" setup>
|
|
45
|
+
import { type PropType, defineShortcuts, ref, toRef, watch } from '#imports'
|
|
46
|
+
import type { Strategy } from '#core/types/utils'
|
|
47
|
+
import { useUI } from '#ui/composables/useUI'
|
|
48
|
+
import { modal } from '#core/ui.config'
|
|
49
|
+
import { useUiConfig } from '#core/composables/useConfig'
|
|
50
|
+
|
|
51
|
+
const config = useUiConfig<typeof modal>(modal, 'modal')
|
|
52
|
+
|
|
53
|
+
const props = defineProps({
|
|
54
|
+
modelValue: {
|
|
55
|
+
type: Boolean,
|
|
56
|
+
default: false,
|
|
57
|
+
},
|
|
58
|
+
overlay: {
|
|
59
|
+
type: Boolean,
|
|
60
|
+
default: true,
|
|
61
|
+
},
|
|
62
|
+
transition: {
|
|
63
|
+
type: Boolean,
|
|
64
|
+
default: true,
|
|
65
|
+
},
|
|
66
|
+
preventClose: {
|
|
67
|
+
type: Boolean,
|
|
68
|
+
default: false,
|
|
69
|
+
},
|
|
70
|
+
fullscreen: {
|
|
71
|
+
type: Boolean,
|
|
72
|
+
default: false,
|
|
73
|
+
},
|
|
74
|
+
scrollable: {
|
|
75
|
+
type: Boolean,
|
|
76
|
+
default: false,
|
|
77
|
+
},
|
|
78
|
+
title: {
|
|
79
|
+
type: String,
|
|
80
|
+
default: '',
|
|
81
|
+
},
|
|
82
|
+
isHideCloseBtn: {
|
|
83
|
+
type: Boolean,
|
|
84
|
+
default: false,
|
|
85
|
+
},
|
|
86
|
+
size: {
|
|
87
|
+
type: String as PropType<keyof typeof modal.size>,
|
|
88
|
+
default: () => modal.default.size,
|
|
89
|
+
},
|
|
90
|
+
position: {
|
|
91
|
+
type: String as PropType<keyof typeof modal.position>,
|
|
92
|
+
default: () => modal.default.position,
|
|
93
|
+
},
|
|
94
|
+
fixHeightSize: {
|
|
95
|
+
type: String as PropType<keyof typeof modal.fixHeightSize>,
|
|
96
|
+
default: () => modal.default.fixHeightSize,
|
|
97
|
+
},
|
|
98
|
+
class: {
|
|
99
|
+
type: [String, Array, Object] as PropType<any>,
|
|
100
|
+
default: undefined,
|
|
101
|
+
},
|
|
102
|
+
ui: {
|
|
103
|
+
type: Object as PropType<Partial<typeof config & { strategy?: Strategy }>>,
|
|
104
|
+
default: undefined,
|
|
105
|
+
},
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
const emits = defineEmits(['update:modelValue'])
|
|
109
|
+
|
|
110
|
+
defineShortcuts({
|
|
111
|
+
escape: {
|
|
112
|
+
usingInput: true,
|
|
113
|
+
handler: () => {
|
|
114
|
+
if (props.preventClose) return
|
|
115
|
+
emits('update:modelValue', false)
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
const modalWrapper = ref<HTMLElement | null>(null)
|
|
121
|
+
|
|
122
|
+
const close = () => {
|
|
123
|
+
emits('update:modelValue', false)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const { ui, attrs } = useUI('modal', toRef(props, 'ui'), config, toRef(props, 'class'))
|
|
127
|
+
|
|
128
|
+
watch(
|
|
129
|
+
() => props.modelValue,
|
|
130
|
+
() => {
|
|
131
|
+
if (props.modelValue) {
|
|
132
|
+
const size = config.size[props.size]
|
|
133
|
+
const fixHeightSize = config.fixHeightSize[props.fixHeightSize]
|
|
134
|
+
const position = config.position[props.position]
|
|
135
|
+
|
|
136
|
+
ui.value.width = size
|
|
137
|
+
ui.value.container = position
|
|
138
|
+
|
|
139
|
+
if (props.scrollable) {
|
|
140
|
+
ui.value.height = fixHeightSize
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
)
|
|
145
|
+
</script>
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<USlideover
|
|
3
|
+
v-bind="attrs"
|
|
4
|
+
:model-value="modelValue"
|
|
5
|
+
:prevent-close="preventClose"
|
|
6
|
+
:overlay="overlay"
|
|
7
|
+
:transition="transition"
|
|
8
|
+
:side="side"
|
|
9
|
+
:initial-focus="emptyFocusRef"
|
|
10
|
+
:ui="ui"
|
|
11
|
+
@update:model-value="$emit('update:modelValue', $event)"
|
|
12
|
+
>
|
|
13
|
+
<div v-if="!isHideCloseBtn && preventClose" class="absolute right-0 m-4">
|
|
14
|
+
<Icon
|
|
15
|
+
v-if="!isHideCloseBtn"
|
|
16
|
+
name="i-heroicons-x-mark"
|
|
17
|
+
class="h-6 w-6 cursor-pointer"
|
|
18
|
+
@click="close"
|
|
19
|
+
/>
|
|
20
|
+
</div>
|
|
21
|
+
|
|
22
|
+
<div :class="['overflow-y-auto', ui.bodyWrapper]">
|
|
23
|
+
<slot />
|
|
24
|
+
</div>
|
|
25
|
+
</USlideover>
|
|
26
|
+
|
|
27
|
+
<div ref="emptyFocusRef" />
|
|
28
|
+
</template>
|
|
29
|
+
|
|
30
|
+
<script lang="ts" setup>
|
|
31
|
+
import { ref, type PropType, toRef, defineShortcuts, watch } from '#imports'
|
|
32
|
+
import type { Strategy } from '#core/types/utils'
|
|
33
|
+
import { useUI } from '#ui/composables/useUI'
|
|
34
|
+
import { slideover } from '#core/ui.config'
|
|
35
|
+
import { useUiConfig } from '#core/composables/useConfig'
|
|
36
|
+
|
|
37
|
+
const config = useUiConfig<typeof slideover>(slideover, 'slideover')
|
|
38
|
+
|
|
39
|
+
const props = defineProps({
|
|
40
|
+
modelValue: {
|
|
41
|
+
type: Boolean as PropType<boolean>,
|
|
42
|
+
default: false,
|
|
43
|
+
},
|
|
44
|
+
side: {
|
|
45
|
+
type: String as PropType<'left' | 'right'>,
|
|
46
|
+
default: 'right',
|
|
47
|
+
validator: (value: string) => ['left', 'right'].includes(value),
|
|
48
|
+
},
|
|
49
|
+
overlay: {
|
|
50
|
+
type: Boolean,
|
|
51
|
+
default: true,
|
|
52
|
+
},
|
|
53
|
+
preventClose: {
|
|
54
|
+
type: Boolean,
|
|
55
|
+
default: false,
|
|
56
|
+
},
|
|
57
|
+
isHideCloseBtn: {
|
|
58
|
+
type: Boolean,
|
|
59
|
+
default: false,
|
|
60
|
+
},
|
|
61
|
+
transition: {
|
|
62
|
+
type: Boolean,
|
|
63
|
+
default: true,
|
|
64
|
+
},
|
|
65
|
+
size: {
|
|
66
|
+
type: String as PropType<keyof typeof slideover.size>,
|
|
67
|
+
default: () => slideover.default.size,
|
|
68
|
+
},
|
|
69
|
+
class: {
|
|
70
|
+
type: [String, Array, Object] as PropType<any>,
|
|
71
|
+
default: undefined,
|
|
72
|
+
},
|
|
73
|
+
ui: {
|
|
74
|
+
type: Object as PropType<Partial<typeof config & { strategy?: Strategy }>>,
|
|
75
|
+
default: undefined,
|
|
76
|
+
},
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
const emits = defineEmits(['update:modelValue'])
|
|
80
|
+
|
|
81
|
+
const emptyFocusRef = ref<HTMLElement | null>(null)
|
|
82
|
+
|
|
83
|
+
defineShortcuts({
|
|
84
|
+
escape: {
|
|
85
|
+
usingInput: true,
|
|
86
|
+
handler: () => {
|
|
87
|
+
if (props.preventClose) return
|
|
88
|
+
emits('update:modelValue', false)
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
const close = () => {
|
|
94
|
+
emits('update:modelValue', false)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const { ui, attrs } = useUI('slideover', toRef(props, 'ui'), config, toRef(props, 'class'))
|
|
98
|
+
|
|
99
|
+
watch(
|
|
100
|
+
() => props.modelValue,
|
|
101
|
+
() => {
|
|
102
|
+
if (props.modelValue) {
|
|
103
|
+
const size = config.size[props.size]
|
|
104
|
+
|
|
105
|
+
ui.value.width = size
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
)
|
|
109
|
+
</script>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<template><img class="h-12" :src="getValue" /></template>
|
|
2
|
+
<script lang="ts" setup>
|
|
3
|
+
import { computed } from 'vue'
|
|
4
|
+
import { type IColumn } from '#core/components/Table/types'
|
|
5
|
+
|
|
6
|
+
const props = defineProps<{
|
|
7
|
+
value: any
|
|
8
|
+
row: any
|
|
9
|
+
column: IColumn
|
|
10
|
+
}>()
|
|
11
|
+
|
|
12
|
+
const getValue = computed(() => props.value)
|
|
13
|
+
</script>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<template>{{ getValue }}</template>
|
|
2
|
+
<script lang="ts" setup>
|
|
3
|
+
import { StringHelper } from '../../utils/StringHelper'
|
|
4
|
+
import { computed } from 'vue'
|
|
5
|
+
import { type IColumn } from '#core/components/Table/types'
|
|
6
|
+
|
|
7
|
+
const props = defineProps<{
|
|
8
|
+
value: any
|
|
9
|
+
row: any
|
|
10
|
+
column: IColumn
|
|
11
|
+
}>()
|
|
12
|
+
|
|
13
|
+
const getValue = computed(() => StringHelper.withComma(props.value))
|
|
14
|
+
</script>
|
|
@@ -1,11 +1,84 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
<template>
|
|
2
|
+
<div>
|
|
3
|
+
<div
|
|
4
|
+
v-if="!options.isHideToolbar"
|
|
5
|
+
class="flex border-b border-gray-200 px-3 py-3.5 dark:border-gray-700"
|
|
6
|
+
>
|
|
7
|
+
<UInput v-model="q" placeholder="Search..." />
|
|
8
|
+
</div>
|
|
9
|
+
<UTable
|
|
10
|
+
:loading="options.status.isLoading"
|
|
11
|
+
:columns="options.columns"
|
|
12
|
+
:rows="options.rawData"
|
|
13
|
+
v-bind="$attrs"
|
|
14
|
+
>
|
|
15
|
+
<template #empty-state>
|
|
16
|
+
<div class="flex flex-col items-center justify-center gap-3 py-6">
|
|
17
|
+
<span class="text-sm italic">No one here!</span>
|
|
18
|
+
</div>
|
|
19
|
+
</template>
|
|
20
|
+
<template
|
|
21
|
+
v-for="column in options.columns"
|
|
22
|
+
#[`${column.key}-data`]="{ row }"
|
|
23
|
+
:key="column.key"
|
|
24
|
+
>
|
|
25
|
+
<ColumnNumber
|
|
26
|
+
v-if="column.type === COLUMN_TYPES.NUMBER"
|
|
27
|
+
:value="row[column.key]"
|
|
28
|
+
:column="column"
|
|
29
|
+
:row="row"
|
|
30
|
+
/>
|
|
31
|
+
<ColumnImage
|
|
32
|
+
v-if="column.type === COLUMN_TYPES.IMAGE"
|
|
33
|
+
:value="row[column.key]"
|
|
34
|
+
:column="column"
|
|
35
|
+
:row="row"
|
|
36
|
+
/>
|
|
37
|
+
<template v-else>
|
|
38
|
+
<span :title="row[column.key]">{{ row[column.key] ?? '-' }}</span>
|
|
39
|
+
</template>
|
|
40
|
+
</template>
|
|
41
|
+
<template v-for="(_, slot) of $slots" #[slot]="scope">
|
|
42
|
+
<slot :name="slot" v-bind="scope" />
|
|
43
|
+
</template>
|
|
44
|
+
</UTable>
|
|
45
|
+
<div class="mt-4 flex justify-end">
|
|
46
|
+
<UPagination
|
|
47
|
+
v-model="page"
|
|
48
|
+
:page-count="options.pageOptions.totalPage"
|
|
49
|
+
:total="options.pageOptions.totalCount"
|
|
50
|
+
/>
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
</template>
|
|
54
|
+
<script lang="ts" setup>
|
|
55
|
+
import { type PropType } from 'vue'
|
|
56
|
+
import { COLUMN_TYPES, type ITableOptions } from '#core/components/Table/types'
|
|
57
|
+
import { _debounce, ref, watch } from '#imports'
|
|
58
|
+
import ColumnNumber from '#core/components/Table/ColumnNumber.vue'
|
|
59
|
+
import ColumnImage from '#core/components/Table/ColumnImage.vue'
|
|
60
|
+
|
|
61
|
+
const emits = defineEmits<{
|
|
62
|
+
(event: 'pageChange', page: number): void
|
|
63
|
+
(event: 'search', q: string): void
|
|
64
|
+
}>()
|
|
65
|
+
|
|
66
|
+
const props = defineProps({
|
|
67
|
+
options: { type: Object as PropType<ITableOptions>, required: true },
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
const q = ref(props.options?.pageOptions.search ?? '')
|
|
71
|
+
|
|
72
|
+
const page = ref(props.options?.pageOptions.currentPage)
|
|
73
|
+
|
|
74
|
+
watch(
|
|
75
|
+
q,
|
|
76
|
+
_debounce((value) => {
|
|
77
|
+
emits('search', value)
|
|
78
|
+
}, 500)
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
watch(page, () => {
|
|
82
|
+
emits('pageChange', page.value)
|
|
83
|
+
})
|
|
84
|
+
</script>
|
|
@@ -5,27 +5,16 @@ export declare const enum COLUMN_TYPES {
|
|
|
5
5
|
DATE = "DATE",
|
|
6
6
|
DATE_TIME = "DATE_TIME",
|
|
7
7
|
NUMBER = "NUMBER",
|
|
8
|
+
IMAGE = "IMAGE",
|
|
8
9
|
ACTION = "ACTION"
|
|
9
10
|
}
|
|
10
|
-
export declare const enum SORT_STATUS {
|
|
11
|
-
ASC = "asc",
|
|
12
|
-
DESC = "desc",
|
|
13
|
-
NONE = "none"
|
|
14
|
-
}
|
|
15
11
|
export interface IColumn {
|
|
16
12
|
[key: string]: any;
|
|
17
13
|
key: string;
|
|
18
14
|
sortable?: boolean;
|
|
19
15
|
direction?: 'asc' | 'desc';
|
|
20
16
|
class?: string;
|
|
21
|
-
|
|
22
|
-
export interface IColumnItem extends IColumn {
|
|
23
|
-
sortStatus?: SORT_STATUS;
|
|
24
|
-
}
|
|
25
|
-
export interface IColumnSortStatus {
|
|
26
|
-
value: string | any;
|
|
27
|
-
sortKey?: string;
|
|
28
|
-
sortStatus: SORT_STATUS;
|
|
17
|
+
type?: COLUMN_TYPES;
|
|
29
18
|
}
|
|
30
19
|
export interface IRowItem<T = object> {
|
|
31
20
|
value: string | any;
|
|
@@ -46,7 +35,6 @@ export interface ITableOptions<T = object> {
|
|
|
46
35
|
status: IStatus;
|
|
47
36
|
pageOptions: IPageOptions;
|
|
48
37
|
columns: IColumn[];
|
|
49
|
-
rows: any[];
|
|
50
38
|
isHideToolbar?: boolean;
|
|
51
39
|
isShowCheckbox?: boolean;
|
|
52
40
|
deleteStatus?: IStatus;
|
|
@@ -54,7 +42,6 @@ export interface ITableOptions<T = object> {
|
|
|
54
42
|
value: string;
|
|
55
43
|
}>) => void;
|
|
56
44
|
onCheckBoxClick?: (index: number[]) => void;
|
|
57
|
-
onSortChange?: (sortStatus: IColumnSortStatus[]) => void;
|
|
58
45
|
disabledCheckIndexes?: number[];
|
|
59
46
|
}
|
|
60
47
|
export interface ISimpleTableOptions<T = object> {
|
|
@@ -62,11 +49,9 @@ export interface ISimpleTableOptions<T = object> {
|
|
|
62
49
|
primary: string;
|
|
63
50
|
status: IStatus;
|
|
64
51
|
columns: IColumn[];
|
|
65
|
-
rows: Array<IRow<T>>;
|
|
66
52
|
isHideBottomPagination?: boolean;
|
|
67
53
|
onRowClick?: (index: number, columns: Array<{
|
|
68
54
|
value: string;
|
|
69
55
|
}>) => void;
|
|
70
56
|
onCheckBoxClick?: (index: number[]) => void;
|
|
71
|
-
onSortChange?: (sortStatus: IColumnSortStatus[]) => void;
|
|
72
57
|
}
|
|
@@ -4,12 +4,7 @@ export var COLUMN_TYPES = /* @__PURE__ */ ((COLUMN_TYPES2) => {
|
|
|
4
4
|
COLUMN_TYPES2["DATE"] = "DATE";
|
|
5
5
|
COLUMN_TYPES2["DATE_TIME"] = "DATE_TIME";
|
|
6
6
|
COLUMN_TYPES2["NUMBER"] = "NUMBER";
|
|
7
|
+
COLUMN_TYPES2["IMAGE"] = "IMAGE";
|
|
7
8
|
COLUMN_TYPES2["ACTION"] = "ACTION";
|
|
8
9
|
return COLUMN_TYPES2;
|
|
9
10
|
})(COLUMN_TYPES || {});
|
|
10
|
-
export var SORT_STATUS = /* @__PURE__ */ ((SORT_STATUS2) => {
|
|
11
|
-
SORT_STATUS2["ASC"] = "asc";
|
|
12
|
-
SORT_STATUS2["DESC"] = "desc";
|
|
13
|
-
SORT_STATUS2["NONE"] = "none";
|
|
14
|
-
return SORT_STATUS2;
|
|
15
|
-
})(SORT_STATUS || {});
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { ref } from "vue";
|
|
2
2
|
import { ObjectHelper } from "../utils/ObjectHelper.mjs";
|
|
3
|
-
import { mergeConfig } from "#ui/utils";
|
|
4
|
-
import { app } from "#core/core.config";
|
|
5
3
|
import {
|
|
6
4
|
apiAddHelper,
|
|
7
5
|
apiDeleteHelper,
|
|
@@ -9,7 +7,7 @@ import {
|
|
|
9
7
|
apiFindHelper,
|
|
10
8
|
updateHelper
|
|
11
9
|
} from "#core/helpers/apiPageHelper";
|
|
12
|
-
import
|
|
10
|
+
import { useCoreConfig } from "./useConfig.mjs";
|
|
13
11
|
export const initPageOptions = (options) => ({
|
|
14
12
|
currentPageCount: 0,
|
|
15
13
|
currentPage: 1,
|
|
@@ -20,7 +18,7 @@ export const initPageOptions = (options) => ({
|
|
|
20
18
|
primary: options.primary
|
|
21
19
|
});
|
|
22
20
|
export const usePageLoader = (loaderOptions) => {
|
|
23
|
-
const config =
|
|
21
|
+
const config = useCoreConfig();
|
|
24
22
|
const fetchStatus = ref(ObjectHelper.createStatus());
|
|
25
23
|
const fetchItems = ref([]);
|
|
26
24
|
const findItem = ref(null);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { mergeConfig } from "#ui/utils";
|
|
2
|
+
import { core } from "#core/core.config";
|
|
3
|
+
import appConfig from "#build/app.config";
|
|
4
|
+
export const useCoreConfig = () => {
|
|
5
|
+
return mergeConfig(appConfig.core.strategy, appConfig.core, core);
|
|
6
|
+
};
|
|
7
|
+
export const useUiConfig = (config, name) => {
|
|
8
|
+
return mergeConfig(appConfig.ui.strategy, appConfig.ui[name], config);
|
|
9
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export declare const enum DialogType {
|
|
2
|
+
ERROR = "error",
|
|
3
|
+
INFO = "info",
|
|
4
|
+
SUCCESS = "success",
|
|
5
|
+
WARNING = "warning"
|
|
6
|
+
}
|
|
7
|
+
export interface IDialogMetaItem {
|
|
8
|
+
title: string;
|
|
9
|
+
message?: string;
|
|
10
|
+
type?: DialogType;
|
|
11
|
+
confirmText?: string;
|
|
12
|
+
cancelText?: string;
|
|
13
|
+
isShowCancelBtn?: boolean;
|
|
14
|
+
}
|
|
15
|
+
export interface IDialog {
|
|
16
|
+
isShow: boolean;
|
|
17
|
+
meta: IDialogMetaItem | undefined;
|
|
18
|
+
openDialog: (meta: IDialogMetaItem) => void;
|
|
19
|
+
closeDialogCancel: () => void;
|
|
20
|
+
closeDialogProceed: () => void;
|
|
21
|
+
error: (payload: IDialogMetaItem) => Promise<boolean>;
|
|
22
|
+
info: (payload: IDialogMetaItem) => Promise<boolean>;
|
|
23
|
+
success: (payload: IDialogMetaItem) => Promise<boolean>;
|
|
24
|
+
warning: (payload: IDialogMetaItem) => Promise<boolean>;
|
|
25
|
+
}
|
|
26
|
+
export declare const useDialog: () => IDialog;
|