@finema/core 2.15.1 → 2.15.3

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": "2.15.1",
3
+ "version": "2.15.3",
4
4
  "configKey": "core",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.1",
package/dist/module.mjs CHANGED
@@ -3,7 +3,7 @@ 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.15.1";
6
+ const version = "2.15.3";
7
7
 
8
8
  const nuxtAppOptions = {
9
9
  head: {
@@ -10,34 +10,72 @@
10
10
  :placeholder="options.searchPlaceholder || '\u0E04\u0E49\u0E19\u0E2B\u0E32...'"
11
11
  />
12
12
  </div>
13
- <Base
14
- :raw-data="options.rawData"
15
- :status="options.status"
16
- :page-options="options.pageOptions"
17
- :is-simple-pagination="isShowSimplePagination"
18
- :is-hide-top-pagination="options.isHideTopPagination"
19
- :is-hide-bottom-pagination="options.isHideBottomPagination"
20
- :is-enable-infinite-scroll="options.isEnableInfiniteScroll"
21
- :container-class="containerClass"
22
- @page-change="onPageChange"
13
+
14
+ <slot
15
+ v-if="options.status.isSuccess && options.rawData.length === 0"
16
+ name="empty-state"
17
+ >
18
+ <Empty />
19
+ </slot>
20
+
21
+ <div
22
+ v-if="options.pageOptions && options.isEnableInfiniteScroll"
23
+ class="mb-4 flex items-center justify-end"
24
+ >
25
+ <p class="text-xs text-gray-500">
26
+ {{ totalInnerRawData }} รายการ จากทั้งหมด {{ totalCountWithComma }} รายการ
27
+ </p>
28
+ </div>
29
+
30
+ <div :class="containerClass">
31
+ <slot
32
+ v-for="(row, index) in displayData"
33
+ :key="index"
34
+ :row="row"
35
+ />
36
+ <div ref="bottomEdgeElement" />
37
+ </div>
38
+
39
+ <slot
40
+ v-if="options.status.isLoading"
41
+ name="loading-state"
42
+ >
43
+ <Loader
44
+ :loading="true"
45
+ />
46
+ </slot>
47
+
48
+ <div
49
+ v-if="options.pageOptions && !options.isEnableInfiniteScroll && !options.isHidePagination"
50
+ class="mt-4 flex justify-between px-3"
23
51
  >
24
- <template
25
- v-for="(_, slot) of $slots"
26
- #[slot]="slotProps"
27
- >
28
- <slot
29
- :name="slot"
30
- v-bind="slotProps || {}"
31
- />
32
- </template>
33
- </Base>
52
+ <p class="text-xs text-gray-500">
53
+ {{ pageBetween }} รายการ จากทั้งหมด {{ totalCountWithComma }} รายการ
54
+ </p>
55
+ <Pagination
56
+ v-if="options.pageOptions.totalPage > 1 && !isShowSimplePagination"
57
+ :default-page="options.pageOptions?.currentPage || 1"
58
+ :items-per-page="options.pageOptions.limit"
59
+ :total="options.pageOptions.totalCount"
60
+ @update:page="onPageChange"
61
+ />
62
+ <SimplePagination
63
+ v-if="options.pageOptions.totalPage > 1 && isShowSimplePagination"
64
+ v-model="page"
65
+ :page-count="options.pageOptions.limit"
66
+ :total="options.pageOptions.totalCount"
67
+ />
68
+ </div>
34
69
  </div>
35
70
  </template>
36
71
 
37
72
  <script setup>
38
- import { _debounce, computed, ref, watch } from "#imports";
73
+ import { computed, ref, watch } from "vue";
74
+ import { useElementVisibility } from "@vueuse/core";
75
+ import { StringHelper } from "#core/utils/StringHelper";
76
+ import { _debounce, useWatchChange, useWatchTrue } from "#imports";
39
77
  import { useCoreConfig } from "#core/composables/useConfig";
40
- import Base from "#core/components/FlexDeck/Base.vue";
78
+ import Empty from "#core/components/Empty.vue";
41
79
  defineSlots();
42
80
  const emits = defineEmits(["pageChange", "search"]);
43
81
  const props = defineProps({
@@ -52,16 +90,60 @@ const props = defineProps({
52
90
  });
53
91
  const coreConfig = useCoreConfig();
54
92
  const q = ref(props.options?.pageOptions.search ?? "");
93
+ const bottomEdgeElement = ref(null);
94
+ const page = ref(props.options.pageOptions?.currentPage || 1);
95
+ const innerRawData = ref([]);
96
+ const targetElement = useElementVisibility(bottomEdgeElement);
55
97
  const isShowSimplePagination = computed(
56
98
  () => props.options.isSimplePagination ?? coreConfig.is_simple_pagination
57
99
  );
100
+ const displayData = computed(() => {
101
+ return props.options.isEnableInfiniteScroll ? innerRawData.value : props.options.rawData;
102
+ });
103
+ const pageBetween = computed(() => {
104
+ const length = props.options.rawData?.length;
105
+ if (length === 0) {
106
+ return "0";
107
+ }
108
+ const start = (props.options.pageOptions.currentPage - 1) * props.options.pageOptions.limit + 1;
109
+ const end = start + length - 1;
110
+ return `${start} - ${end}`;
111
+ });
112
+ const totalCountWithComma = computed(() => {
113
+ return !props.options.pageOptions.totalCount ? "0" : StringHelper.withComma(props.options.pageOptions.totalCount);
114
+ });
115
+ const totalInnerRawData = computed(() => {
116
+ return innerRawData.value?.length || 0;
117
+ });
58
118
  watch(
59
119
  q,
60
120
  _debounce((value) => {
61
121
  emits("search", value);
62
122
  }, 500)
63
123
  );
64
- const onPageChange = (page) => {
65
- emits("pageChange", page);
124
+ useWatchChange(
125
+ () => props.options.pageOptions?.currentPage,
126
+ (value) => {
127
+ page.value = value;
128
+ }
129
+ );
130
+ useWatchTrue(
131
+ () => props.options.status.isSuccess,
132
+ () => {
133
+ if (props.options.isEnableInfiniteScroll) {
134
+ innerRawData.value = [...innerRawData.value || [], ...props.options.rawData];
135
+ return;
136
+ }
137
+ innerRawData.value = props.options.rawData;
138
+ }
139
+ );
140
+ watch(targetElement, (value) => {
141
+ if (props.options.status.isLoading || !props.options.isEnableInfiniteScroll) return;
142
+ if (page.value < props.options.pageOptions.totalPage && value) {
143
+ page.value++;
144
+ }
145
+ });
146
+ const onPageChange = (page2) => {
147
+ emits("pageChange", page2);
66
148
  };
67
149
  </script>
@@ -1,8 +1,9 @@
1
- import type { PropType } from 'vue';
1
+ import { type PropType } from 'vue';
2
2
  import type { IFlexDeckOptions } from '#core/components/FlexDeck/types';
3
3
  type __VLS_Slots = {
4
4
  'default': (props: {
5
5
  row: any;
6
+ key?: number | string;
6
7
  }) => any;
7
8
  'empty-state': () => any;
8
9
  'loading-state': () => any;
@@ -4,13 +4,10 @@ export interface IFlexDeckOptions<T = object> {
4
4
  primary: string;
5
5
  status: IStatus;
6
6
  pageOptions: IPageOptions;
7
- isHideToolbar?: boolean;
8
7
  isEnabledSearch?: boolean;
9
8
  searchPlaceholder?: string;
10
9
  isPreventRouteChange: boolean;
11
- isHideCaption?: boolean;
12
- isHideBottomPagination?: boolean;
13
- isHideTopPagination?: boolean;
10
+ isHidePagination?: boolean;
14
11
  isSimplePagination?: boolean;
15
12
  isEnableInfiniteScroll?: boolean;
16
13
  }
@@ -67,9 +67,9 @@ declare const __VLS_component: import("vue").DefineComponent<import("vue").Extra
67
67
  }>> & Readonly<{
68
68
  onPageChange?: ((...args: any[]) => any) | undefined;
69
69
  }>, {
70
- isHideCaption: boolean | undefined;
71
- isSimplePagination: boolean | undefined;
72
70
  isHidePagination: boolean | undefined;
71
+ isSimplePagination: boolean | undefined;
72
+ isHideCaption: boolean | undefined;
73
73
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
74
74
  declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
75
75
  export default _default;
@@ -12,27 +12,6 @@
12
12
  :placeholder="options.searchPlaceholder || '\u0E04\u0E49\u0E19\u0E2B\u0E32....'"
13
13
  />
14
14
  </div>
15
- <div
16
- v-if="!options.isHideCaption || !options.isHidePagination"
17
- :class="theme.captionContainer({
18
- class: [ui?.captionContainer]
19
- })"
20
- >
21
- <span
22
- :class="theme.captionBoldText({
23
- class: [ui?.captionBoldText]
24
- })"
25
- >
26
- ผลลัพธ์ทั้งหมด:</span>
27
- จำนวน
28
- <span
29
- :class="theme.captionBoldText({
30
- class: [ui?.captionBoldText]
31
- })"
32
- >{{ options.pageOptions?.totalCount || 0 }}</span>
33
- รายการ
34
- </div>
35
-
36
15
  <UTable
37
16
  v-bind="$attrs"
38
17
  :loading="options.status.isLoading"
@@ -104,6 +83,7 @@
104
83
  {{ pageBetween }} รายการ จากทั้งหมด {{ totalCountWithComma }} รายการ
105
84
  </p>
106
85
  <Pagination
86
+ v-if="options.pageOptions.totalPage > 1"
107
87
  v-model:page="page"
108
88
  :default-page="options.pageOptions?.currentPage || 1"
109
89
  :items-per-page="options.pageOptions.limit"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@finema/core",
3
- "version": "2.15.1",
3
+ "version": "2.15.3",
4
4
  "repository": "https://gitlab.finema.co/finema/ui-kit",
5
5
  "license": "MIT",
6
6
  "author": "Finema Dev Core Team",
@@ -28,7 +28,7 @@
28
28
  "dev": "nuxi dev playground -o",
29
29
  "dev:build": "nuxi build playground",
30
30
  "dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground",
31
- "release": "npm run prepack && changelogen --release && npm publish && git push --follow-tags",
31
+ "release": "npm run lint && npm run test && npm run prepack && changelogen --release && npm publish && git push --follow-tags",
32
32
  "lint": "eslint .",
33
33
  "lint:fix": "eslint --fix .",
34
34
  "test": "vitest run",
@@ -64,6 +64,7 @@
64
64
  "@iconify-json/heroicons": "^1.2.2",
65
65
  "@iconify-json/ph": "^1.2.2",
66
66
  "@iconify-json/svg-spinners": "^1.2.2",
67
+ "@tailwindcss/typography": "^0.5.0-alpha.3",
67
68
  "url-join": "^5.0.0"
68
69
  },
69
70
  "devDependencies": {
@@ -74,7 +75,6 @@
74
75
  "@nuxt/module-builder": "^1.0.1",
75
76
  "@nuxt/schema": "^3.17.3",
76
77
  "@nuxt/test-utils": "^3.19.0",
77
- "@tailwindcss/typography": "^0.5.0-alpha.3",
78
78
  "@types/node": "latest",
79
79
  "changelogen": "^0.5.7",
80
80
  "eslint": "^9.26.0",
@@ -1,156 +0,0 @@
1
- <template>
2
- <div
3
- v-if="!isHideCaption || !isHideBottomPagination"
4
- class="mb-4 text-gray-500"
5
- >
6
- <span class="font-bold">ผลลัพธ์ทั้งหมด:</span>
7
- จำนวน
8
- <span class="font-bold">{{ pageOptions?.totalCount || 0 }}</span>
9
- รายการ
10
- </div>
11
- <slot
12
- v-if="!status.isLoading && rawData.length === 0"
13
- name="empty-state"
14
- >
15
- <Empty />
16
- </slot>
17
-
18
- <div
19
- v-if="pageOptions && isEnableInfiniteScroll && !isHideTopPagination"
20
- class="mb-4 flex items-center justify-end"
21
- >
22
- <p class="text-xs text-gray-500">
23
- ผลลัพธ์ {{ totalInnerRawData }} ของ {{ totalCountWithComma }} รายการ
24
- </p>
25
- </div>
26
-
27
- <div :class="containerClass">
28
- <slot
29
- v-for="(row, index) in rawData"
30
- :key="index"
31
- :row="row"
32
- />
33
- <div ref="bottomEdgeElement" />
34
- </div>
35
-
36
- <slot
37
- v-if="status.isLoading"
38
- name="loading-state"
39
- >
40
- <div class="flex h-60 items-center justify-center">
41
- <Icon
42
- name="i-svg-spinners:180-ring-with-bg"
43
- class="size-8 text-primary"
44
- />
45
- </div>
46
- </slot>
47
-
48
- <div
49
- v-if="pageOptions && !isEnableInfiniteScroll"
50
- class="mt-4 flex justify-between px-3"
51
- >
52
- <p class="text-xs text-gray-500">
53
- ผลลัพธ์ {{ pageBetween }} ของ {{ totalCountWithComma }} รายการ
54
- </p>
55
- <Pagination
56
- v-if="pageOptions.totalPage > 1 && !isSimplePagination && !isHideBottomPagination"
57
- :default-page="pageOptions?.currentPage || 1"
58
- :items-per-page="pageOptions.limit"
59
- :total="pageOptions.totalCount"
60
- @update:page="emits('pageChange', $event)"
61
- />
62
- <SimplePagination
63
- v-if="pageOptions.totalPage > 1 && isSimplePagination"
64
- v-model="page"
65
- :page-count="pageOptions.limit"
66
- :total="pageOptions.totalCount"
67
- />
68
- </div>
69
- </template>
70
-
71
- <script setup>
72
- import { computed } from "vue";
73
- import { useElementVisibility } from "@vueuse/core";
74
- import { StringHelper } from "#core/utils/StringHelper";
75
- import { ref, useWatchChange, useWatchTrue, watch } from "#imports";
76
- import Empty from "#core/components/Empty.vue";
77
- const emits = defineEmits(["pageChange"]);
78
- const props = defineProps({
79
- status: {
80
- type: Object,
81
- required: true
82
- },
83
- pageOptions: {
84
- type: Object,
85
- required: false
86
- },
87
- rawData: {
88
- type: Array,
89
- required: true
90
- },
91
- isSimplePagination: {
92
- type: Boolean,
93
- default: false
94
- },
95
- isHideTopPagination: {
96
- type: Boolean,
97
- default: false
98
- },
99
- isHideBottomPagination: {
100
- type: Boolean,
101
- default: false
102
- },
103
- isEnableInfiniteScroll: {
104
- type: Boolean,
105
- default: false
106
- },
107
- isHideCaption: {
108
- type: Boolean,
109
- default: false
110
- },
111
- containerClass: {
112
- type: [String, Array, Object]
113
- }
114
- });
115
- const bottomEdgeElement = ref(null);
116
- const page = ref(props.pageOptions?.currentPage || 1);
117
- const innerRawData = ref([]);
118
- const targetElement = useElementVisibility(bottomEdgeElement);
119
- const pageBetween = computed(() => {
120
- const length = props.rawData?.length;
121
- if (length === 0) {
122
- return "0";
123
- }
124
- const start = (props.pageOptions.currentPage - 1) * props.pageOptions.limit + 1;
125
- const end = start + length - 1;
126
- return `${start} - ${end}`;
127
- });
128
- const totalCountWithComma = computed(() => {
129
- return !props.pageOptions.totalCount ? "0" : StringHelper.withComma(props.pageOptions.totalCount);
130
- });
131
- const totalInnerRawData = computed(() => {
132
- return innerRawData.value?.length || 0;
133
- });
134
- useWatchChange(
135
- () => props.pageOptions?.currentPage,
136
- (value) => {
137
- page.value = value;
138
- }
139
- );
140
- useWatchTrue(
141
- () => props.status.isSuccess,
142
- () => {
143
- if (props.isEnableInfiniteScroll) {
144
- innerRawData.value = [...innerRawData.value || [], ...props.rawData];
145
- return;
146
- }
147
- innerRawData.value = props.rawData;
148
- }
149
- );
150
- watch(targetElement, (value) => {
151
- if (props.status.isLoading || !props.isEnableInfiniteScroll) return;
152
- if (page.value < props.pageOptions.totalPage && value) {
153
- page.value++;
154
- }
155
- });
156
- </script>
@@ -1,103 +0,0 @@
1
- import { type PropType } from 'vue';
2
- import type { IFlexDeckOptions } from '#core/components/FlexDeck/types';
3
- declare var __VLS_1: {}, __VLS_6: {
4
- key: number;
5
- row: object;
6
- }, __VLS_8: {};
7
- type __VLS_Slots = {} & {
8
- 'empty-state'?: (props: typeof __VLS_1) => any;
9
- } & {
10
- default?: (props: typeof __VLS_6) => any;
11
- } & {
12
- 'loading-state'?: (props: typeof __VLS_8) => any;
13
- };
14
- declare const __VLS_component: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
15
- status: {
16
- type: PropType<IFlexDeckOptions["status"]>;
17
- required: true;
18
- };
19
- pageOptions: {
20
- type: PropType<IFlexDeckOptions["pageOptions"]>;
21
- required: false;
22
- };
23
- rawData: {
24
- type: PropType<IFlexDeckOptions["rawData"]>;
25
- required: true;
26
- };
27
- isSimplePagination: {
28
- type: PropType<IFlexDeckOptions["isSimplePagination"]>;
29
- default: boolean;
30
- };
31
- isHideTopPagination: {
32
- type: PropType<IFlexDeckOptions["isHideTopPagination"]>;
33
- default: boolean;
34
- };
35
- isHideBottomPagination: {
36
- type: PropType<IFlexDeckOptions["isHideBottomPagination"]>;
37
- default: boolean;
38
- };
39
- isEnableInfiniteScroll: {
40
- type: PropType<IFlexDeckOptions["isEnableInfiniteScroll"]>;
41
- default: boolean;
42
- };
43
- isHideCaption: {
44
- type: PropType<IFlexDeckOptions["isHideCaption"]>;
45
- default: boolean;
46
- };
47
- containerClass: {
48
- type: (ArrayConstructor | ObjectConstructor | StringConstructor)[];
49
- };
50
- }>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
51
- pageChange: (...args: any[]) => void;
52
- }, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
53
- status: {
54
- type: PropType<IFlexDeckOptions["status"]>;
55
- required: true;
56
- };
57
- pageOptions: {
58
- type: PropType<IFlexDeckOptions["pageOptions"]>;
59
- required: false;
60
- };
61
- rawData: {
62
- type: PropType<IFlexDeckOptions["rawData"]>;
63
- required: true;
64
- };
65
- isSimplePagination: {
66
- type: PropType<IFlexDeckOptions["isSimplePagination"]>;
67
- default: boolean;
68
- };
69
- isHideTopPagination: {
70
- type: PropType<IFlexDeckOptions["isHideTopPagination"]>;
71
- default: boolean;
72
- };
73
- isHideBottomPagination: {
74
- type: PropType<IFlexDeckOptions["isHideBottomPagination"]>;
75
- default: boolean;
76
- };
77
- isEnableInfiniteScroll: {
78
- type: PropType<IFlexDeckOptions["isEnableInfiniteScroll"]>;
79
- default: boolean;
80
- };
81
- isHideCaption: {
82
- type: PropType<IFlexDeckOptions["isHideCaption"]>;
83
- default: boolean;
84
- };
85
- containerClass: {
86
- type: (ArrayConstructor | ObjectConstructor | StringConstructor)[];
87
- };
88
- }>> & Readonly<{
89
- onPageChange?: ((...args: any[]) => any) | undefined;
90
- }>, {
91
- isHideCaption: boolean | undefined;
92
- isHideBottomPagination: boolean | undefined;
93
- isHideTopPagination: boolean | undefined;
94
- isSimplePagination: boolean | undefined;
95
- isEnableInfiniteScroll: boolean | undefined;
96
- }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
97
- declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
98
- export default _default;
99
- type __VLS_WithSlots<T, S> = T & {
100
- new (): {
101
- $slots: S;
102
- };
103
- };