@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@finema/core",
3
- "version": "1.4.5",
3
+ "version": "1.4.7",
4
4
  "configKey": "core",
5
5
  "compatibility": {
6
6
  "nuxt": "^3.7.4"
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";
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
- v-if="options.isEnabledSearch"
5
- class="flex border-b border-gray-200 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">ไม่พบข้อมูล!</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 { computed, type PropType } from 'vue'
60
- import { COLUMN_TYPES, type ITableOptions } from '#core/components/Table/types'
61
- import { _debounce, ref, StringHelper, watch } from '#imports'
62
- import ColumnNumber from '#core/components/Table/ColumnNumber.vue'
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
- watch(page, () => {
90
- emits('pageChange', page.value)
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<T = object> {
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<T = object> = Record<number, IRowItem<T>>;
29
- export interface ITableOptions<T = object> {
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 ISimpleTableOptions<T = object> {
49
- rawData: T[];
50
- primary: string;
51
- status: IStatus;
52
- columns: IColumn[];
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
- onRowClick?: (index: number, columns: Array<{
55
- value: string;
56
- }>) => void;
57
- onCheckBoxClick?: (index: number[]) => void;
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(appConfig.core.strategy, appConfig.core, core);
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 IUseSimpleTable<T = object> {
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 useSimpleTable: <T = object>(options: IUseSimpleTable<T>) => ComputedRef<ISimpleTableOptions<T>>;
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 useSimpleTable = (options) => computed(() => {
12
+ export const useTableSimple = (options) => computed(() => {
13
13
  const config = useCoreConfig();
14
14
  return {
15
15
  items: options.items(),
@@ -1,4 +1,5 @@
1
1
  export const pagination = {
2
+ wrapper: "flex items-center space-x-1",
2
3
  default: {
3
4
  activeButton: {
4
5
  color: "primary",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@finema/core",
3
- "version": "1.4.5",
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"