@v1nt1248/3nclient-lib 0.1.1 → 0.1.2
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 +2 -0
- package/dist/components/index.d.ts +3 -3
- package/dist/components/ui3n-badge-simple.vue.d.ts +13 -13
- package/dist/components/ui3n-badge.vue.d.ts +18 -16
- package/dist/components/ui3n-breadcrumb.vue.d.ts +15 -13
- package/dist/components/ui3n-breadcrumbs.vue.d.ts +17 -15
- package/dist/components/ui3n-button.vue.d.ts +22 -19
- package/dist/components/ui3n-checkbox.vue.d.ts +17 -15
- package/dist/components/ui3n-chip.vue.d.ts +18 -16
- package/dist/components/ui3n-dialog.vue.d.ts +4 -5
- package/dist/components/ui3n-drop-files.vue.d.ts +16 -14
- package/dist/components/ui3n-emoji.vue.d.ts +11 -11
- package/dist/components/ui3n-icon.vue.d.ts +12 -12
- package/dist/components/ui3n-input.vue.d.ts +4 -4
- package/dist/components/ui3n-list.vue.d.ts +12 -39
- package/dist/components/ui3n-menu.vue.d.ts +14 -12
- package/dist/components/ui3n-notification.vue.d.ts +14 -15
- package/dist/components/ui3n-progress-circular.vue.d.ts +13 -13
- package/dist/components/ui3n-progress-linear.vue.d.ts +13 -13
- package/dist/components/ui3n-step-line-bar.vue.d.ts +11 -11
- package/dist/components/ui3n-switch.vue.d.ts +15 -13
- package/dist/components/ui3n-table/composables/useTable.d.ts +26 -0
- package/dist/components/ui3n-table/types.d.ts +65 -0
- package/dist/components/ui3n-table/ui3n-table.vue.d.ts +22 -0
- package/dist/components/ui3n-table-sort-icon.vue.d.ts +2 -2
- package/dist/components/ui3n-tabs.vue.d.ts +18 -16
- package/dist/components/ui3n-text.vue.d.ts +13 -13
- package/dist/components/ui3n-virtual-scroll.vue.d.ts +6 -28
- package/dist/directives/index.d.ts +0 -1
- package/dist/directives/ui3n-click-outside.d.ts +0 -1
- package/dist/directives/ui3n-html.d.ts +0 -1
- package/dist/index.d.ts +4 -1
- package/dist/plugins/dialogs.d.ts +0 -1
- package/dist/plugins/i18n.d.ts +0 -1
- package/dist/plugins/icons.d.ts +0 -1
- package/dist/plugins/index.d.ts +0 -1
- package/dist/plugins/notifications.d.ts +0 -1
- package/dist/plugins/store-dialogs.d.ts +0 -1
- package/dist/plugins/store-notifications.d.ts +0 -1
- package/dist/plugins/store-vue-bus.d.ts +0 -1
- package/dist/plugins/vue-bus.d.ts +0 -1
- package/dist/style.css +1 -1
- package/dist/tools/sqlite-on-3nstorage/index.d.ts +0 -1
- package/dist/tools/ui.helpers.d.ts +0 -1
- package/dist/ui-3n-lib.js +5471 -5634
- package/package.json +28 -27
- package/src/components/index.ts +34 -4
- package/src/components/ui3n-checkbox.vue +1 -1
- package/src/components/ui3n-dialog.vue +6 -1
- package/src/components/ui3n-table/composables/useTable.ts +206 -0
- package/src/components/ui3n-table/types.ts +80 -0
- package/src/components/ui3n-table/ui3n-table.vue +319 -0
- package/src/components/ui3n-table-sort-icon.vue +9 -6
- package/dist/components/ui3n-table.vue.d.ts +0 -36
- /package/src/components/{ui3n-table.vue → ui3n-table-simple.vue} +0 -0
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@v1nt1248/3nclient-lib",
|
|
3
3
|
"license": "AGPL-3.0-or-later",
|
|
4
4
|
"author": "v1nt1248",
|
|
5
|
-
"version": "0.1.
|
|
5
|
+
"version": "0.1.2",
|
|
6
6
|
"description": "Library for 3NWeb clients",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"files": [
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"@iconify-icons/ic": "1.2.13",
|
|
38
38
|
"@iconify/vue": "4.1.2",
|
|
39
|
-
"dayjs": "1.11.
|
|
39
|
+
"dayjs": "1.11.12",
|
|
40
40
|
"lodash": "4.17.21",
|
|
41
41
|
"mitt": "3.0.1",
|
|
42
42
|
"sanitize-html": "2.13.0",
|
|
@@ -44,47 +44,48 @@
|
|
|
44
44
|
"vuedraggable": "^4.1.0"
|
|
45
45
|
},
|
|
46
46
|
"peerDependencies": {
|
|
47
|
-
"pinia": "2.1
|
|
48
|
-
"vue": "3.4.
|
|
47
|
+
"pinia": "2.2.1",
|
|
48
|
+
"vue": "3.4.37"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@types/lodash": "4.17.5",
|
|
52
52
|
"@types/node": "20.14.2",
|
|
53
53
|
"@types/sanitize-html": "2.11.0",
|
|
54
|
-
"@typescript-eslint/eslint-plugin": "
|
|
55
|
-
"@typescript-eslint/parser": "
|
|
56
|
-
"@vitejs/plugin-vue": "5.
|
|
57
|
-
"@vue/compiler-core": "3.4.
|
|
54
|
+
"@typescript-eslint/eslint-plugin": "8.0.1",
|
|
55
|
+
"@typescript-eslint/parser": "8.0.1",
|
|
56
|
+
"@vitejs/plugin-vue": "5.1.2",
|
|
57
|
+
"@vue/compiler-core": "3.4.37",
|
|
58
58
|
"@vue/eslint-config-typescript": "13.0.0",
|
|
59
|
-
"@vue/runtime-core": "3.4.
|
|
59
|
+
"@vue/runtime-core": "3.4.37",
|
|
60
60
|
"@vuedx/typescript-plugin-vue": "0.7.6",
|
|
61
|
-
"eslint": "9.
|
|
61
|
+
"eslint": "9.9.0",
|
|
62
62
|
"eslint-config-prettier": "^9.1.0",
|
|
63
63
|
"eslint-plugin-import": "2.29.1",
|
|
64
64
|
"eslint-plugin-node": "11.1.0",
|
|
65
|
-
"eslint-plugin-prettier": "^5.1
|
|
66
|
-
"eslint-plugin-promise": "
|
|
67
|
-
"eslint-plugin-vue": "9.
|
|
68
|
-
"jackspeak": "
|
|
65
|
+
"eslint-plugin-prettier": "^5.2.1",
|
|
66
|
+
"eslint-plugin-promise": "7.1.0",
|
|
67
|
+
"eslint-plugin-vue": "9.27.0",
|
|
68
|
+
"jackspeak": "4.0.1",
|
|
69
69
|
"path": "0.12.7",
|
|
70
|
-
"pinia": "2.1
|
|
70
|
+
"pinia": "2.2.1",
|
|
71
71
|
"postcss-html": "1.7.0",
|
|
72
72
|
"prettier": "^3.3.3",
|
|
73
|
-
"sass": "1.77.
|
|
74
|
-
"stylelint": "16.
|
|
75
|
-
"stylelint-config-recommended-scss": "14.
|
|
73
|
+
"sass": "1.77.8",
|
|
74
|
+
"stylelint": "16.8.1",
|
|
75
|
+
"stylelint-config-recommended-scss": "14.1.0",
|
|
76
76
|
"stylelint-config-recommended-vue": "1.5.0",
|
|
77
|
-
"stylelint-config-standard": "36.0.
|
|
78
|
-
"stylelint-scss": "6.
|
|
79
|
-
"typescript": "5.4
|
|
80
|
-
"vite": "5.
|
|
77
|
+
"stylelint-config-standard": "36.0.1",
|
|
78
|
+
"stylelint-scss": "6.5.0",
|
|
79
|
+
"typescript": "5.5.4",
|
|
80
|
+
"vite": "5.4.0",
|
|
81
81
|
"vite-plugin-css-injected-by-js": "3.5.1",
|
|
82
|
-
"vite-plugin-dts": "
|
|
83
|
-
"
|
|
84
|
-
"
|
|
85
|
-
"vue
|
|
82
|
+
"vite-plugin-dts": "4.0.2",
|
|
83
|
+
"vite-plugin-vue-devtools": "^7.3.7",
|
|
84
|
+
"vitepress": "1.3.2",
|
|
85
|
+
"vue": "3.4.37",
|
|
86
|
+
"vue-tsc": "2.0.29"
|
|
86
87
|
},
|
|
87
|
-
"packageManager": "pnpm@9.
|
|
88
|
+
"packageManager": "pnpm@9.7.0",
|
|
88
89
|
"pnpm": {
|
|
89
90
|
"peerDependencyRules": {
|
|
90
91
|
"ignoreMissing": [
|
package/src/components/index.ts
CHANGED
|
@@ -17,10 +17,29 @@ import type { Ui3nCheckboxProps, Ui3nCheckboxEmits, Ui3nCheckboxSlots } from './
|
|
|
17
17
|
import Ui3nNotification from './ui3n-notification.vue';
|
|
18
18
|
import Ui3nTableSortIcon from './ui3n-table-sort-icon.vue';
|
|
19
19
|
import type { Ui3nTableSortIconProps } from './ui3n-table-sort-icon.vue';
|
|
20
|
-
import Ui3nTable from './ui3n-table.vue';
|
|
21
|
-
import type {
|
|
20
|
+
import Ui3nTable from './ui3n-table/ui3n-table.vue';
|
|
21
|
+
import type {
|
|
22
|
+
Ui3nTableSort,
|
|
23
|
+
Ui3nTableConfig,
|
|
24
|
+
Ui3nTableHeadProps,
|
|
25
|
+
Ui3nTableBodyProps,
|
|
26
|
+
Ui3nTableGroupActionsSlot,
|
|
27
|
+
Ui3nTableHeaderCellSlot,
|
|
28
|
+
Ui3nTableBodyRowSlotScope,
|
|
29
|
+
Ui3nTableBodyRowSlot,
|
|
30
|
+
Ui3nTableBodyRowCellSlotScope,
|
|
31
|
+
Ui3nTableBodyRowCellSlot,
|
|
32
|
+
Ui3nTableSlots,
|
|
33
|
+
Ui3nTableProps,
|
|
34
|
+
Ui3nTableEmits,
|
|
35
|
+
} from './ui3n-table/types';
|
|
22
36
|
import Ui3nDialog from './ui3n-dialog.vue';
|
|
23
|
-
import type {
|
|
37
|
+
import type {
|
|
38
|
+
Ui3nDialogComponentProps,
|
|
39
|
+
Ui3nDialogComponentEmits,
|
|
40
|
+
Ui3nDialogProps,
|
|
41
|
+
Ui3nDialogEvent,
|
|
42
|
+
} from './ui3n-dialog.vue';
|
|
24
43
|
import Ui3nMenu from './ui3n-menu.vue';
|
|
25
44
|
import type { Ui3nMenuProps, Ui3nMenuEmits, Ui3nMenuSlots } from './ui3n-menu.vue';
|
|
26
45
|
import Ui3nList from './ui3n-list.vue';
|
|
@@ -75,6 +94,17 @@ export {
|
|
|
75
94
|
Ui3nTableSortIcon,
|
|
76
95
|
Ui3nTableSortIconProps,
|
|
77
96
|
Ui3nTable,
|
|
97
|
+
Ui3nTableSort,
|
|
98
|
+
Ui3nTableConfig,
|
|
99
|
+
Ui3nTableHeadProps,
|
|
100
|
+
Ui3nTableBodyProps,
|
|
101
|
+
Ui3nTableGroupActionsSlot,
|
|
102
|
+
Ui3nTableHeaderCellSlot,
|
|
103
|
+
Ui3nTableBodyRowSlotScope,
|
|
104
|
+
Ui3nTableBodyRowSlot,
|
|
105
|
+
Ui3nTableBodyRowCellSlotScope,
|
|
106
|
+
Ui3nTableBodyRowCellSlot,
|
|
107
|
+
Ui3nTableSlots,
|
|
78
108
|
Ui3nTableProps,
|
|
79
109
|
Ui3nTableEmits,
|
|
80
110
|
Ui3nDialog,
|
|
@@ -115,4 +145,4 @@ export {
|
|
|
115
145
|
Ui3nProgressLinearProps,
|
|
116
146
|
Ui3nProgressCircular,
|
|
117
147
|
Ui3nProgressCircularProps,
|
|
118
|
-
}
|
|
148
|
+
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
2
|
import { computed, onMounted, watch, onBeforeMount, ref, useSlots } from 'vue';
|
|
3
3
|
|
|
4
|
-
type Ui3nCheckboxValue = boolean | string | number;
|
|
4
|
+
export type Ui3nCheckboxValue = boolean | string | number;
|
|
5
5
|
|
|
6
6
|
export interface Ui3nCheckboxProps {
|
|
7
7
|
modelValue: Ui3nCheckboxValue;
|
|
@@ -36,10 +36,15 @@ export interface Ui3nDialogComponentProps {
|
|
|
36
36
|
|
|
37
37
|
export interface Ui3nDialogComponentEmits {
|
|
38
38
|
(ev: 'open', value?: any): void;
|
|
39
|
+
|
|
39
40
|
(ev: 'before-close', value?: any): void;
|
|
41
|
+
|
|
40
42
|
(ev: 'close', value?: any): void;
|
|
43
|
+
|
|
41
44
|
(ev: 'confirm', value?: any): void;
|
|
45
|
+
|
|
42
46
|
(ev: 'cancel', value?: any): void;
|
|
47
|
+
|
|
43
48
|
(ev: 'click-overlay', value?: any): void;
|
|
44
49
|
}
|
|
45
50
|
|
|
@@ -52,7 +57,7 @@ const data = ref(null);
|
|
|
52
57
|
const isValid = ref(true);
|
|
53
58
|
const dialogElement = ref<HTMLDivElement | null>(null);
|
|
54
59
|
|
|
55
|
-
const dialogProps = computed<Ui3nDialogProps
|
|
60
|
+
const dialogProps = computed<Required<Omit<Ui3nDialogProps, 'onClose' | 'onConfirm' | 'onCancel'>>>(() => ({
|
|
56
61
|
teleport: props.dialogProps?.teleport ?? 'body',
|
|
57
62
|
title: props.dialogProps?.title ?? '',
|
|
58
63
|
width: props.dialogProps?.width ?? 380,
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { computed, onMounted, type Ref, ref, watch, UnwrapRef } from 'vue';
|
|
2
|
+
import { get, isEmpty, size } from 'lodash';
|
|
3
|
+
import {
|
|
4
|
+
Ui3nTableBodyBaseItem,
|
|
5
|
+
Ui3nTableConfig,
|
|
6
|
+
Ui3nTableEmits,
|
|
7
|
+
Ui3nTableProps,
|
|
8
|
+
Ui3nTableSort,
|
|
9
|
+
} from '@/components/ui3n-table/types';
|
|
10
|
+
import type { Ui3nCheckboxValue } from '../../ui3n-checkbox.vue';
|
|
11
|
+
|
|
12
|
+
export function useTable<T extends Ui3nTableBodyBaseItem>(props: Ui3nTableProps<T>, emits: Ui3nTableEmits<T>) {
|
|
13
|
+
const tableEl = ref<HTMLDivElement | null>(null);
|
|
14
|
+
const currentConfig = ref<Pick<Ui3nTableConfig<T>, 'sortOrder' | 'fieldAsRowKey'>>({
|
|
15
|
+
sortOrder: setInitialSortOrder(),
|
|
16
|
+
fieldAsRowKey: setFieldAsRowKey(),
|
|
17
|
+
});
|
|
18
|
+
const selectedRows: Ref<Set<T> | Array<T[keyof T]>> = !!currentConfig.value?.fieldAsRowKey
|
|
19
|
+
? ref([])
|
|
20
|
+
: (ref(new Set()) as Ref<Set<T>>);
|
|
21
|
+
const hasGroupActionsRow = ref(false);
|
|
22
|
+
|
|
23
|
+
const isRowKeyUsed = computed(() => !!currentConfig.value.fieldAsRowKey);
|
|
24
|
+
const visibleColumns = computed(() => props.head.filter(h => !h.hidden));
|
|
25
|
+
const selectedRowsArray = computed(() =>
|
|
26
|
+
isRowKeyUsed.value
|
|
27
|
+
? props.body.content.filter(row =>
|
|
28
|
+
(selectedRows.value as Array<T[keyof T]>).includes(row[currentConfig.value.fieldAsRowKey as keyof T]),
|
|
29
|
+
)
|
|
30
|
+
: Array.from(selectedRows.value as Set<T>),
|
|
31
|
+
);
|
|
32
|
+
const selectedRowsSize = computed(() =>
|
|
33
|
+
isRowKeyUsed.value ? size(selectedRows.value) : (selectedRows.value as Set<T>).size,
|
|
34
|
+
);
|
|
35
|
+
const showGroupActionsRow = computed(() => props.config?.selectable === 'multiple' && hasGroupActionsRow.value);
|
|
36
|
+
|
|
37
|
+
onMounted(() => {
|
|
38
|
+
tableEl.value && setColumnWidth(tableEl.value);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
function setColumnWidth(el: HTMLDivElement) {
|
|
42
|
+
const { config = {}, head } = props;
|
|
43
|
+
const { columnStyle } = config;
|
|
44
|
+
const keys = head.map(h => h.key);
|
|
45
|
+
const columnsWidthValue = keys.reduce((res, key, index) => {
|
|
46
|
+
const width = get(columnStyle, [key, 'width'], '1fr');
|
|
47
|
+
res = index === 0 ? `${width}` : `${res} ${width}`;
|
|
48
|
+
return res;
|
|
49
|
+
}, '');
|
|
50
|
+
el && el.style.setProperty('--ui3n-table-columns-width', columnsWidthValue);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function setFieldAsRowKey() {
|
|
54
|
+
const { config = {}, body } = props;
|
|
55
|
+
const { fieldAsRowKey } = config;
|
|
56
|
+
if (fieldAsRowKey && fieldAsRowKey in get(body, ['content', 0], {})) return fieldAsRowKey;
|
|
57
|
+
|
|
58
|
+
if ('id' in get(body, ['content', 0], {})) return 'id';
|
|
59
|
+
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function setInitialSortOrder(): Ui3nTableSort<T> {
|
|
64
|
+
const { config = {}, head } = props;
|
|
65
|
+
const { sortOrder } = config;
|
|
66
|
+
if (!isEmpty(sortOrder)) {
|
|
67
|
+
return sortOrder;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
for (const h of head) {
|
|
71
|
+
const { key, sortable } = h;
|
|
72
|
+
if (sortable) {
|
|
73
|
+
return {
|
|
74
|
+
field: key,
|
|
75
|
+
direction: 'desc',
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return {} as Ui3nTableSort<T>;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function getRowKey(row: T, index: number) {
|
|
84
|
+
return isRowKeyUsed.value ? (row[currentConfig.value.fieldAsRowKey as keyof T] as string | number) : index;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function isRowSelected(row: T): boolean {
|
|
88
|
+
if (isRowKeyUsed.value) {
|
|
89
|
+
return !!(selectedRows.value as Array<T[keyof T]>).find(
|
|
90
|
+
keyValue => keyValue === row[currentConfig.value.fieldAsRowKey as keyof T],
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return (selectedRows.value as Set<T>).has(row);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function getRowStyle(row: T): Record<string, string> {
|
|
98
|
+
if (isEmpty(props.body.rowsStyle) || !isRowKeyUsed.value) return {};
|
|
99
|
+
|
|
100
|
+
const rowKey = row[currentConfig.value.fieldAsRowKey as keyof T] as string | number;
|
|
101
|
+
return get(props, ['body', 'rowsStyle', rowKey], {});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function closeGroupActionsRow() {
|
|
105
|
+
hasGroupActionsRow.value = false;
|
|
106
|
+
toggleSelectedRows(false);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function selectInSingleMode(row: T) {
|
|
110
|
+
if (isRowSelected(row)) {
|
|
111
|
+
isRowKeyUsed.value && ((selectedRows.value as Array<T[keyof T]>) = []);
|
|
112
|
+
!isRowKeyUsed.value && (selectedRows.value as Set<T>).clear();
|
|
113
|
+
} else {
|
|
114
|
+
if (isRowKeyUsed.value) {
|
|
115
|
+
(selectedRows.value as Array<T[keyof T]>) = [row[currentConfig.value?.fieldAsRowKey as keyof T]];
|
|
116
|
+
} else {
|
|
117
|
+
(selectedRows.value as Set<T>).clear();
|
|
118
|
+
(selectedRows.value as Set<T>).add(row);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function selectInMultipleMode(row: T) {
|
|
124
|
+
if (isRowSelected(row)) {
|
|
125
|
+
if (!isRowKeyUsed.value) {
|
|
126
|
+
(selectedRows.value as Set<T>).delete(row);
|
|
127
|
+
} else {
|
|
128
|
+
const index = (selectedRows.value as Array<T[keyof T]>).findIndex(
|
|
129
|
+
keyValue => keyValue === row[currentConfig.value.fieldAsRowKey as keyof T],
|
|
130
|
+
);
|
|
131
|
+
(selectedRows.value as Array<T[keyof T]>).splice(index, 1);
|
|
132
|
+
}
|
|
133
|
+
} else {
|
|
134
|
+
isRowKeyUsed.value &&
|
|
135
|
+
(selectedRows.value as Array<T[keyof T]>).push(row[currentConfig.value.fieldAsRowKey as keyof T]);
|
|
136
|
+
!isRowKeyUsed.value && (selectedRows.value as Set<T>).add(row);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function processSelection(row: T, withoutEvents?: boolean) {
|
|
141
|
+
const { selectable } = props.config;
|
|
142
|
+
|
|
143
|
+
if (selectable === 'single') {
|
|
144
|
+
selectInSingleMode(row);
|
|
145
|
+
} else {
|
|
146
|
+
selectInMultipleMode(row);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
!withoutEvents && emits('select:row', selectedRowsArray.value);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function toggleSelectedRows(val: Ui3nCheckboxValue) {
|
|
153
|
+
if (props.config.selectable !== 'multiple') return;
|
|
154
|
+
|
|
155
|
+
if (!!val) {
|
|
156
|
+
for (const item of props.body.content) {
|
|
157
|
+
if (!isRowSelected(item)) {
|
|
158
|
+
processSelection(item, true);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
} else {
|
|
162
|
+
isRowKeyUsed.value && ((selectedRows.value as Array<T[keyof T]>) = []);
|
|
163
|
+
!isRowKeyUsed.value && (selectedRows.value as Set<T>).clear();
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
emits('select:row', selectedRowsArray.value);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function changeSortOrder(field: keyof T) {
|
|
170
|
+
if (currentConfig.value.sortOrder?.field === field) {
|
|
171
|
+
currentConfig.value.sortOrder.direction = currentConfig.value.sortOrder?.direction === 'asc' ? 'desc' : 'asc';
|
|
172
|
+
} else {
|
|
173
|
+
currentConfig.value.sortOrder!.field = field as UnwrapRef<keyof T>;
|
|
174
|
+
currentConfig.value.sortOrder!.direction = 'desc';
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
currentConfig.value.sortOrder?.field && emits('change:sort', currentConfig.value.sortOrder as Ui3nTableSort<T>);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
watch(
|
|
181
|
+
() => selectedRowsSize.value,
|
|
182
|
+
(val, oldVal) => {
|
|
183
|
+
if (val && val > oldVal && props.config.selectable === 'multiple' && !showGroupActionsRow.value) {
|
|
184
|
+
hasGroupActionsRow.value = true;
|
|
185
|
+
}
|
|
186
|
+
},
|
|
187
|
+
);
|
|
188
|
+
|
|
189
|
+
return {
|
|
190
|
+
tableEl,
|
|
191
|
+
currentConfig,
|
|
192
|
+
visibleColumns,
|
|
193
|
+
hasGroupActionsRow,
|
|
194
|
+
showGroupActionsRow,
|
|
195
|
+
selectedRows,
|
|
196
|
+
selectedRowsArray,
|
|
197
|
+
selectedRowsSize,
|
|
198
|
+
closeGroupActionsRow,
|
|
199
|
+
getRowKey,
|
|
200
|
+
isRowSelected,
|
|
201
|
+
getRowStyle,
|
|
202
|
+
processSelection,
|
|
203
|
+
toggleSelectedRows,
|
|
204
|
+
changeSortOrder,
|
|
205
|
+
};
|
|
206
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { VNode } from 'vue';
|
|
2
|
+
|
|
3
|
+
export interface Ui3nTableBodyBaseItem {
|
|
4
|
+
id?: string | number | symbol;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export type Ui3nTableSort<T extends Ui3nTableBodyBaseItem> = {
|
|
8
|
+
field: keyof T;
|
|
9
|
+
direction: 'asc' | 'desc';
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export type Ui3nTableConfig<T extends Ui3nTableBodyBaseItem, K extends keyof T = keyof T> = {
|
|
13
|
+
tableName?: string;
|
|
14
|
+
sortOrder?: Ui3nTableSort<T>;
|
|
15
|
+
selectable?: 'single' | 'multiple';
|
|
16
|
+
// draggebleRows?: boolean; // ToDo this will be done in the next version
|
|
17
|
+
// draggebleColumns?: boolean; // ToDo this will be done in the next version
|
|
18
|
+
columnStyle?: { [P in Omit<K, 'id'> as string | number]: Record<string, string> };
|
|
19
|
+
fieldAsRowKey?: keyof T;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export type Ui3nTableHeadProps<T extends Ui3nTableBodyBaseItem> = {
|
|
23
|
+
key: keyof T;
|
|
24
|
+
text: string;
|
|
25
|
+
sortable?: boolean;
|
|
26
|
+
headCellStyle?: Record<string, string>;
|
|
27
|
+
format?: (content: unknown) => string;
|
|
28
|
+
hidden?: boolean;
|
|
29
|
+
index?: number;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export type Ui3nTableBodyProps<T extends Ui3nTableBodyBaseItem, K extends keyof T = keyof T> = {
|
|
33
|
+
content: T[];
|
|
34
|
+
rowsStyle?: { [P in T[K] as string | number]: Record<string, string> };
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export interface Ui3nTableProps<T extends Ui3nTableBodyBaseItem> {
|
|
38
|
+
config: Ui3nTableConfig<T>;
|
|
39
|
+
head: Ui3nTableHeadProps<T>[];
|
|
40
|
+
body: Ui3nTableBodyProps<T>;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface Ui3nTableEmits<T extends Ui3nTableBodyBaseItem> {
|
|
44
|
+
(ev: 'change:sort', val: Ui3nTableSort<T>): void;
|
|
45
|
+
(ev: 'select:row', val: T[]): void;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export type Ui3nTableGroupActionsSlot = {
|
|
49
|
+
'group-actions': () => VNode;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export type Ui3nTableHeaderCellSlot<T extends Ui3nTableBodyBaseItem, K extends string & keyof T> = {
|
|
53
|
+
[p in `header-cell-${K}`]: () => VNode;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export type Ui3nTableBodyRowSlotScope<T extends Ui3nTableBodyBaseItem> = {
|
|
57
|
+
row: T;
|
|
58
|
+
rowStyle?: Record<string, string>;
|
|
59
|
+
rowIndex: number;
|
|
60
|
+
events?: Record<string, (value: unknown) => unknown>;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export type Ui3nTableBodyRowSlot<T extends Ui3nTableBodyBaseItem> = {
|
|
64
|
+
'body-row': (scope: Ui3nTableBodyRowSlotScope<T>) => VNode;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export type Ui3nTableBodyRowCellSlotScope<T extends Ui3nTableBodyBaseItem, K extends string & keyof T> = {
|
|
68
|
+
row: T;
|
|
69
|
+
rowIndex: number;
|
|
70
|
+
cell: T[K];
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export type Ui3nTableBodyRowCellSlot<T extends Ui3nTableBodyBaseItem, K extends string & keyof T> = {
|
|
74
|
+
[p in `body-row-cell-${K}`]: (scope: Ui3nTableBodyRowCellSlotScope<T, K>) => VNode;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export type Ui3nTableSlots<T extends Ui3nTableBodyBaseItem, K extends string & keyof T> = Ui3nTableGroupActionsSlot &
|
|
78
|
+
Ui3nTableHeaderCellSlot<T, K> &
|
|
79
|
+
Ui3nTableBodyRowSlot<T> &
|
|
80
|
+
Ui3nTableBodyRowCellSlot<T, K>;
|