@finema/core 1.4.5 → 1.4.7
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 +2 -1
- package/dist/runtime/components/QRCode.vue +21 -0
- package/dist/runtime/components/Table/Base.vue +92 -0
- package/dist/runtime/components/Table/Simple.vue +53 -0
- package/dist/runtime/components/Table/index.vue +20 -84
- package/dist/runtime/components/Table/types.d.ts +14 -19
- package/dist/runtime/composables/useConfig.mjs +1 -1
- package/dist/runtime/composables/useTable.d.ts +2 -2
- package/dist/runtime/composables/useTable.mjs +1 -1
- package/dist/runtime/ui.config/pagination.mjs +1 -0
- package/package.json +2 -1
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -2,7 +2,7 @@ import { defineNuxtModule, createResolver, installModule, addPlugin, addComponen
|
|
|
2
2
|
import 'lodash-es';
|
|
3
3
|
|
|
4
4
|
const name = "@finema/core";
|
|
5
|
-
const version = "1.4.
|
|
5
|
+
const version = "1.4.7";
|
|
6
6
|
|
|
7
7
|
const colors = {
|
|
8
8
|
black: "#20243E",
|
|
@@ -87,6 +87,7 @@ const _deepMerge = (target, ...sources) => {
|
|
|
87
87
|
};
|
|
88
88
|
|
|
89
89
|
const pagination = {
|
|
90
|
+
wrapper: "flex items-center space-x-1",
|
|
90
91
|
default: {
|
|
91
92
|
activeButton: {
|
|
92
93
|
color: "primary",
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<QrcodeVue :value="value" :level="level" :render-as="renderAs" class="h-[350px] w-[350px]" />
|
|
3
|
+
</template>
|
|
4
|
+
<script lang="ts" setup>
|
|
5
|
+
import QrcodeVue from 'qrcode.vue'
|
|
6
|
+
|
|
7
|
+
defineProps({
|
|
8
|
+
value: {
|
|
9
|
+
type: String,
|
|
10
|
+
required: true,
|
|
11
|
+
},
|
|
12
|
+
level: {
|
|
13
|
+
type: String,
|
|
14
|
+
default: 'M',
|
|
15
|
+
},
|
|
16
|
+
renderAs: {
|
|
17
|
+
type: String,
|
|
18
|
+
default: 'svg',
|
|
19
|
+
},
|
|
20
|
+
})
|
|
21
|
+
</script>
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<UTable :loading="status.isLoading" :columns="columns" :rows="rawData" v-bind="$attrs">
|
|
3
|
+
<template #empty-state>
|
|
4
|
+
<div class="flex flex-col items-center justify-center gap-3 py-6">
|
|
5
|
+
<span class="text-sm italic">ไม่พบข้อมูล!</span>
|
|
6
|
+
</div>
|
|
7
|
+
</template>
|
|
8
|
+
<template v-for="column in columns" #[`${column.key}-data`]="{ row }" :key="column.key">
|
|
9
|
+
<ColumnNumber
|
|
10
|
+
v-if="column.type === COLUMN_TYPES.NUMBER"
|
|
11
|
+
:value="row[column.key]"
|
|
12
|
+
:column="column"
|
|
13
|
+
:row="row"
|
|
14
|
+
/>
|
|
15
|
+
<ColumnImage
|
|
16
|
+
v-if="column.type === COLUMN_TYPES.IMAGE"
|
|
17
|
+
:value="row[column.key]"
|
|
18
|
+
:column="column"
|
|
19
|
+
:row="row"
|
|
20
|
+
/>
|
|
21
|
+
<template v-else>
|
|
22
|
+
<span :title="row[column.key]">{{ row[column.key] ?? '-' }}</span>
|
|
23
|
+
</template>
|
|
24
|
+
</template>
|
|
25
|
+
<template v-for="(_, slot) of $slots" #[slot]="scope">
|
|
26
|
+
<slot :name="slot" v-bind="scope" />
|
|
27
|
+
</template>
|
|
28
|
+
</UTable>
|
|
29
|
+
<div v-if="pageOptions" class="mt-4 flex justify-between">
|
|
30
|
+
<p class="text-xs text-gray-500">
|
|
31
|
+
ผลลัพธ์ {{ pageBetween }} ของ {{ totalCountWithComma }} รายการ
|
|
32
|
+
</p>
|
|
33
|
+
<UPagination
|
|
34
|
+
v-if="pageOptions.totalPage > 1"
|
|
35
|
+
v-model="page"
|
|
36
|
+
:page-count="pageOptions.limit"
|
|
37
|
+
:total="pageOptions.totalCount"
|
|
38
|
+
/>
|
|
39
|
+
</div>
|
|
40
|
+
</template>
|
|
41
|
+
<script lang="ts" setup>
|
|
42
|
+
import { COLUMN_TYPES, type ITableOptions } from '#core/components/Table/types'
|
|
43
|
+
import ColumnNumber from '#core/components/Table/ColumnNumber.vue'
|
|
44
|
+
import ColumnImage from '#core/components/Table/ColumnImage.vue'
|
|
45
|
+
import { computed, type PropType } from 'vue'
|
|
46
|
+
import { StringHelper } from '#core/utils/StringHelper'
|
|
47
|
+
import { ref, watch } from '#imports'
|
|
48
|
+
|
|
49
|
+
const emits = defineEmits(['pageChange'])
|
|
50
|
+
|
|
51
|
+
const props = defineProps({
|
|
52
|
+
status: {
|
|
53
|
+
type: Object as PropType<ITableOptions['status']>,
|
|
54
|
+
required: true,
|
|
55
|
+
},
|
|
56
|
+
pageOptions: {
|
|
57
|
+
type: Object as PropType<ITableOptions['pageOptions']>,
|
|
58
|
+
required: false,
|
|
59
|
+
},
|
|
60
|
+
columns: {
|
|
61
|
+
type: Array as PropType<ITableOptions['columns']>,
|
|
62
|
+
required: true,
|
|
63
|
+
},
|
|
64
|
+
rawData: {
|
|
65
|
+
type: Array as PropType<ITableOptions['rawData']>,
|
|
66
|
+
required: true,
|
|
67
|
+
},
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
const page = ref(props.pageOptions?.currentPage || 1)
|
|
71
|
+
|
|
72
|
+
const pageBetween = computed((): string => {
|
|
73
|
+
const length = props.rawData?.length
|
|
74
|
+
|
|
75
|
+
if (length === 0) {
|
|
76
|
+
return '0'
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const start = (props.pageOptions.currentPage - 1) * props.pageOptions.limit + 1
|
|
80
|
+
const end = start + length - 1
|
|
81
|
+
|
|
82
|
+
return `${start} - ${end}`
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
const totalCountWithComma = computed((): string => {
|
|
86
|
+
return !props.pageOptions.totalCount ? '0' : StringHelper.withComma(props.pageOptions.totalCount)
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
watch(page, () => {
|
|
90
|
+
emits('pageChange', page.value)
|
|
91
|
+
})
|
|
92
|
+
</script>
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<Base
|
|
3
|
+
v-bind="$attrs"
|
|
4
|
+
:columns="options.columns"
|
|
5
|
+
:raw-data="itemsByPage"
|
|
6
|
+
:status="options.status"
|
|
7
|
+
:page-options="pageOptions"
|
|
8
|
+
@page-change="onPageChange"
|
|
9
|
+
/>
|
|
10
|
+
</template>
|
|
11
|
+
<script lang="ts" setup>
|
|
12
|
+
import { computed, type PropType, ref } from 'vue'
|
|
13
|
+
import { type ISimpleTableOptions } from '#core/components/Table/types'
|
|
14
|
+
import Base from '#core/components/Table/Base.vue'
|
|
15
|
+
import { initPageOptions } from '#core/composables/loaderPage'
|
|
16
|
+
|
|
17
|
+
const props = defineProps({
|
|
18
|
+
options: { type: Object as PropType<ISimpleTableOptions>, required: true },
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
const currentPage = ref(1)
|
|
22
|
+
|
|
23
|
+
const pageOptions = computed(() => {
|
|
24
|
+
if (!props.options?.limit) {
|
|
25
|
+
return undefined
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
...initPageOptions({
|
|
30
|
+
limit: props.options.limit,
|
|
31
|
+
primary: props.options.primary,
|
|
32
|
+
}),
|
|
33
|
+
totalCount: props.options.rawData.length,
|
|
34
|
+
totalPage: Math.ceil(props.options.rawData.length / props.options.limit),
|
|
35
|
+
currentPage: currentPage.value,
|
|
36
|
+
}
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
const onPageChange = (page: number) => {
|
|
40
|
+
currentPage.value = page
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const itemsByPage = computed(() => {
|
|
44
|
+
if (!pageOptions.value) {
|
|
45
|
+
return props.options?.rawData
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const start = (pageOptions.value.currentPage - 1) * pageOptions.value.limit
|
|
49
|
+
const end = start + pageOptions.value.limit
|
|
50
|
+
|
|
51
|
+
return props.options?.rawData.slice(start, end)
|
|
52
|
+
})
|
|
53
|
+
</script>
|
|
@@ -1,66 +1,27 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div>
|
|
3
|
-
<div
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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">ไม่พบข้อมูล!</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-between">
|
|
46
|
-
<p class="text-xs text-gray-500">
|
|
47
|
-
ผลลัพธ์ {{ pageBetween }} ของ {{ totalCountWithComma }} รายการ
|
|
48
|
-
</p>
|
|
49
|
-
<UPagination
|
|
50
|
-
v-if="options.pageOptions.totalPage > 1"
|
|
51
|
-
v-model="page"
|
|
52
|
-
:page-count="options.pageOptions.totalPage"
|
|
53
|
-
:total="options.pageOptions.totalCount"
|
|
3
|
+
<div v-if="options.isEnabledSearch" class="mb-4 flex justify-end">
|
|
4
|
+
<UInput
|
|
5
|
+
v-model="q"
|
|
6
|
+
icon="i-heroicons-magnifying-glass"
|
|
7
|
+
:placeholder="options.searchPlaceholder || 'ค้นหา...'"
|
|
54
8
|
/>
|
|
55
9
|
</div>
|
|
10
|
+
<Base
|
|
11
|
+
v-bind="$attrs"
|
|
12
|
+
:columns="options.columns"
|
|
13
|
+
:raw-data="options.rawData"
|
|
14
|
+
:status="options.status"
|
|
15
|
+
:page-options="options.pageOptions"
|
|
16
|
+
@page-change="onPageChange"
|
|
17
|
+
/>
|
|
56
18
|
</div>
|
|
57
19
|
</template>
|
|
58
20
|
<script lang="ts" setup>
|
|
59
|
-
import {
|
|
60
|
-
import {
|
|
61
|
-
import { _debounce, ref,
|
|
62
|
-
import
|
|
63
|
-
import ColumnImage from '#core/components/Table/ColumnImage.vue'
|
|
21
|
+
import { type PropType } from 'vue'
|
|
22
|
+
import { type ITableOptions } from '#core/components/Table/types'
|
|
23
|
+
import { _debounce, ref, watch } from '#imports'
|
|
24
|
+
import Base from '#core/components/Table/Base.vue'
|
|
64
25
|
|
|
65
26
|
const emits = defineEmits<{
|
|
66
27
|
(event: 'pageChange', page: number): void
|
|
@@ -69,16 +30,10 @@ const emits = defineEmits<{
|
|
|
69
30
|
|
|
70
31
|
const props = defineProps({
|
|
71
32
|
options: { type: Object as PropType<ITableOptions>, required: true },
|
|
72
|
-
class: {
|
|
73
|
-
type: [String, Array, Object] as PropType<any>,
|
|
74
|
-
default: undefined,
|
|
75
|
-
},
|
|
76
33
|
})
|
|
77
34
|
|
|
78
35
|
const q = ref(props.options?.pageOptions.search ?? '')
|
|
79
36
|
|
|
80
|
-
const page = ref(props.options?.pageOptions.currentPage)
|
|
81
|
-
|
|
82
37
|
watch(
|
|
83
38
|
q,
|
|
84
39
|
_debounce((value) => {
|
|
@@ -86,26 +41,7 @@ watch(
|
|
|
86
41
|
}, 500)
|
|
87
42
|
)
|
|
88
43
|
|
|
89
|
-
|
|
90
|
-
emits('pageChange', page
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
const pageBetween = computed((): string => {
|
|
94
|
-
const length = props.options?.rawData?.length
|
|
95
|
-
|
|
96
|
-
if (length === 0) {
|
|
97
|
-
return '0'
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
const start = (props.options.pageOptions.currentPage - 1) * props.options.pageOptions.limit + 1
|
|
101
|
-
const end = start + length - 1
|
|
102
|
-
|
|
103
|
-
return `${start} - ${end}`
|
|
104
|
-
})
|
|
105
|
-
|
|
106
|
-
const totalCountWithComma = computed((): string => {
|
|
107
|
-
return !props.options.pageOptions.totalCount
|
|
108
|
-
? '0'
|
|
109
|
-
: StringHelper.withComma(props.options.pageOptions.totalCount)
|
|
110
|
-
})
|
|
44
|
+
const onPageChange = (page: number) => {
|
|
45
|
+
emits('pageChange', page)
|
|
46
|
+
}
|
|
111
47
|
</script>
|
|
@@ -16,7 +16,7 @@ export interface IColumn {
|
|
|
16
16
|
class?: string;
|
|
17
17
|
type?: COLUMN_TYPES;
|
|
18
18
|
}
|
|
19
|
-
export interface IRowItem
|
|
19
|
+
export interface IRowItem {
|
|
20
20
|
value: string | any;
|
|
21
21
|
type?: COLUMN_TYPES;
|
|
22
22
|
title?: string;
|
|
@@ -25,34 +25,29 @@ export interface IRowItem<T = object> {
|
|
|
25
25
|
props?: Record<string, any>;
|
|
26
26
|
on?: Record<string, any>;
|
|
27
27
|
}
|
|
28
|
-
export type IRow
|
|
29
|
-
export interface
|
|
28
|
+
export type IRow = Record<number, IRowItem>;
|
|
29
|
+
export interface IBaseTableOptions<T = object> {
|
|
30
30
|
rawData: T[];
|
|
31
31
|
primary: string;
|
|
32
|
-
isHideBottomPagination?: boolean;
|
|
33
|
-
isHideTopPagination?: boolean;
|
|
34
|
-
isNotChangeRoute: boolean;
|
|
35
32
|
status: IStatus;
|
|
36
|
-
pageOptions: IPageOptions;
|
|
37
33
|
columns: IColumn[];
|
|
38
|
-
isHideToolbar?: boolean;
|
|
39
|
-
isEnabledSearch?: boolean;
|
|
40
34
|
isShowCheckbox?: boolean;
|
|
41
|
-
deleteStatus?: IStatus;
|
|
42
35
|
onRowClick?: (index: number, columns: Array<{
|
|
43
36
|
value: string;
|
|
44
37
|
}>) => void;
|
|
45
38
|
onCheckBoxClick?: (index: number[]) => void;
|
|
46
39
|
disabledCheckIndexes?: number[];
|
|
47
40
|
}
|
|
48
|
-
export interface
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
41
|
+
export interface ITableOptions<T = object> extends IBaseTableOptions<T> {
|
|
42
|
+
pageOptions: IPageOptions;
|
|
43
|
+
isHideToolbar?: boolean;
|
|
44
|
+
isEnabledSearch?: boolean;
|
|
45
|
+
searchPlaceholder?: string;
|
|
46
|
+
deleteStatus?: IStatus;
|
|
53
47
|
isHideBottomPagination?: boolean;
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
48
|
+
isHideTopPagination?: boolean;
|
|
49
|
+
isNotChangeRoute: boolean;
|
|
50
|
+
}
|
|
51
|
+
export interface ISimpleTableOptions<T = object> extends IBaseTableOptions<T> {
|
|
52
|
+
limit?: number;
|
|
58
53
|
}
|
|
@@ -2,7 +2,7 @@ import { mergeConfig } from "#ui/utils";
|
|
|
2
2
|
import { core } from "#core/core.config";
|
|
3
3
|
import appConfig from "#build/app.config";
|
|
4
4
|
export const useCoreConfig = () => {
|
|
5
|
-
return mergeConfig(
|
|
5
|
+
return mergeConfig("override", appConfig.core, core);
|
|
6
6
|
};
|
|
7
7
|
export const useUiConfig = (config, name) => {
|
|
8
8
|
return mergeConfig(appConfig.ui.strategy, appConfig.ui[name], config);
|
|
@@ -7,12 +7,12 @@ export interface IUseTable<T = object> {
|
|
|
7
7
|
columns: () => IColumn[];
|
|
8
8
|
options?: (() => Partial<ITableOptions<T>>) | Partial<ITableOptions<T>>;
|
|
9
9
|
}
|
|
10
|
-
export interface
|
|
10
|
+
export interface IUseTableSimple<T = object> {
|
|
11
11
|
items: () => T[];
|
|
12
12
|
status?: () => IStatus;
|
|
13
13
|
columns: () => IColumn[];
|
|
14
14
|
options?: (() => Partial<ISimpleTableOptions<T>>) | Partial<ISimpleTableOptions<T>>;
|
|
15
15
|
}
|
|
16
16
|
export declare const useTable: <T = object>(options: IUseTable<T>) => ComputedRef<ITableOptions<T>>;
|
|
17
|
-
export declare const
|
|
17
|
+
export declare const useTableSimple: <T = object>(options: IUseTableSimple<T>) => ComputedRef<ISimpleTableOptions<T>>;
|
|
18
18
|
export declare const createTableOptions: <T = object>(repo: IUsePageLoader<T>, columns: IColumn[], rows: IRow[], options: ITableOptions<T>) => ITableOptions<T>;
|
|
@@ -9,7 +9,7 @@ export const useTable = (options) => computed(() => {
|
|
|
9
9
|
typeof options.options === "function" ? options.options() : options.options ?? {}
|
|
10
10
|
);
|
|
11
11
|
});
|
|
12
|
-
export const
|
|
12
|
+
export const useTableSimple = (options) => computed(() => {
|
|
13
13
|
const config = useCoreConfig();
|
|
14
14
|
return {
|
|
15
15
|
items: options.items(),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@finema/core",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.7",
|
|
4
4
|
"repository": "https://gitlab.finema.co/finema/ui-kit",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Finema Dev Core Team",
|
|
@@ -45,6 +45,7 @@
|
|
|
45
45
|
"lodash-es": "^4.17.21",
|
|
46
46
|
"nuxt-security": "^1.0.0",
|
|
47
47
|
"pinia": "^2.1.7",
|
|
48
|
+
"qrcode.vue": "^3.4.1",
|
|
48
49
|
"url-join": "^5.0.0",
|
|
49
50
|
"zod": "^3.22.4",
|
|
50
51
|
"zod-i18n-map": "^2.23.0"
|