lkt-table 1.0.13
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 +219 -0
- package/dist/lkt-table.es.js +373 -0
- package/dist/lkt-table.umd.js +1 -0
- package/dist/types/components/LktHiddenRow.vue.d.ts +209 -0
- package/dist/types/components/LktTableRow.vue.d.ts +194 -0
- package/dist/types/functions/table-functions.d.ts +52 -0
- package/dist/types/index.d.ts +6 -0
- package/dist/types/instances/LktTableColumn.d.ts +16 -0
- package/dist/types/interfaces/TableColumn.d.ts +9 -0
- package/dist/types/lib-components/LktTable.vue.d.ts +214 -0
- package/lkt-table.css +114 -0
- package/package.json +71 -0
- package/src/components/LktHiddenRow.vue +59 -0
- package/src/components/LktTableRow.vue +60 -0
- package/src/index.ts +13 -0
- package/src/lib-components/LktTable.vue +260 -0
package/lkt-table.css
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
.lkt-table {
|
|
2
|
+
width: var(--table-width);
|
|
3
|
+
overflow-x: auto;
|
|
4
|
+
font-family: var(--table-font-family);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.lkt-table > table {
|
|
8
|
+
width: 100%;
|
|
9
|
+
max-width: 100%;
|
|
10
|
+
border-collapse: separate;
|
|
11
|
+
border-radius: var(--table-border-radius);
|
|
12
|
+
border-spacing: 0;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.lkt-table th,
|
|
16
|
+
.lkt-table td {
|
|
17
|
+
vertical-align: middle;
|
|
18
|
+
text-align: var(--table-text-align);
|
|
19
|
+
padding: var(--table-row-padding);
|
|
20
|
+
font-size: var(--table-row-font-size);
|
|
21
|
+
color: var(--table-row-color);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.lkt-table th {
|
|
25
|
+
font-family: var(--table-header-font-family);
|
|
26
|
+
padding: var(--table-header-padding);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.lkt-table thead tr {
|
|
30
|
+
background-color: var(--table-header-background)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.lkt-table tbody tr {
|
|
34
|
+
background-color: var(--table-row-background);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.lkt-table tbody tr:nth-child(odd) {
|
|
38
|
+
background-color: var(--table-row-background-odd);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.lkt-table [data-sort="asc"] > div,
|
|
42
|
+
.lkt-table [data-sort="desc"] > div {
|
|
43
|
+
display: inline-block;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.lkt-table [data-sort="asc"] > div:after,
|
|
47
|
+
.lkt-table [data-sort="desc"] > div:after {
|
|
48
|
+
font-family: var(--table-sort-icon-font-family);
|
|
49
|
+
display: inline-block;
|
|
50
|
+
font-size: var(--table-sort-icon-font-size);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.lkt-table [data-sort="asc"] > div:after {
|
|
54
|
+
content: var(--table-sort-asc-icon-content);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.lkt-table [data-sort="desc"] > div:after {
|
|
58
|
+
content: var(--table-sort-desc-icon-content);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.lkt-table td[data-role="drag-indicator"],
|
|
62
|
+
.lkt-table td[data-role="invalid-drag-indicator"] {
|
|
63
|
+
width: var(--table-drag-indicator-width);
|
|
64
|
+
height: 40px;
|
|
65
|
+
padding: 0 !important;
|
|
66
|
+
position: relative;
|
|
67
|
+
background: #eeeeee;
|
|
68
|
+
cursor: pointer;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.lkt-table td[data-role="drag-indicator"]:before,
|
|
72
|
+
.lkt-table td[data-role="invalid-drag-indicator"]:before {
|
|
73
|
+
content: '';
|
|
74
|
+
display: block;
|
|
75
|
+
background: #eeeeee;
|
|
76
|
+
width: 18px;
|
|
77
|
+
height: 36px;
|
|
78
|
+
margin: auto;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.lkt-table td[data-role="drag-indicator"]:after,
|
|
82
|
+
.lkt-table td[data-role="invalid-drag-indicator"]:after {
|
|
83
|
+
content: "\2026";
|
|
84
|
+
color: #000000;
|
|
85
|
+
display: block;
|
|
86
|
+
position: absolute;
|
|
87
|
+
top: 50%;
|
|
88
|
+
left: 50%;
|
|
89
|
+
font-weight: 700;
|
|
90
|
+
width: 15px;
|
|
91
|
+
height: 7px;
|
|
92
|
+
transform: rotate(90deg);
|
|
93
|
+
transform-origin: center center;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
[data-lkt="empty-table"] {
|
|
97
|
+
border: 1px solid #ddd;
|
|
98
|
+
border-radius: var(--table-border-radius);
|
|
99
|
+
width: 100%;
|
|
100
|
+
padding: 10px;
|
|
101
|
+
background-color: #f8f7e5;
|
|
102
|
+
font-family: var(--table-font-family);
|
|
103
|
+
font-size: 13px;
|
|
104
|
+
color: #444;
|
|
105
|
+
text-align: var(--table-text-align);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.sortable-chosen {
|
|
109
|
+
border: var(--table-sortable-chosen-border);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.sortable-chosen.ghost {
|
|
113
|
+
background: var(--table-sortable-chosen-ghost-background);
|
|
114
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "lkt-table",
|
|
3
|
+
"version": "1.0.13",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "src/index.ts",
|
|
6
|
+
"module": "src/index.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"lkt-table.css",
|
|
9
|
+
"dist/*",
|
|
10
|
+
"src/**/*.vue"
|
|
11
|
+
],
|
|
12
|
+
"sideEffects": false,
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"import": "./dist/lkt-table.es.js",
|
|
16
|
+
"require": "./dist/lkt-table.umd.js"
|
|
17
|
+
},
|
|
18
|
+
"./dist/style.css": "./dist/style.css"
|
|
19
|
+
},
|
|
20
|
+
"types": "./dist/types/index.d.ts",
|
|
21
|
+
"scripts": {
|
|
22
|
+
"serve": "vite",
|
|
23
|
+
"build": "vite build && vue-tsc --emitDeclarationOnly --project tsconfig.json && mv dist/src dist/types && rm dist/README.md.d.ts && rm dist/vite.config.d.ts",
|
|
24
|
+
"build2": "vite build",
|
|
25
|
+
"preview": "vite preview",
|
|
26
|
+
"test": "vitest",
|
|
27
|
+
"test-coverage": "vitest run --coverage"
|
|
28
|
+
},
|
|
29
|
+
"author": "Antonio Ibáñez",
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@babel/core": "^7.13.13",
|
|
32
|
+
"@babel/preset-env": "^7.13.12",
|
|
33
|
+
"@babel/types": "^7.18.9",
|
|
34
|
+
"@testing-library/cypress": "^7.0.4",
|
|
35
|
+
"@testing-library/dom": "^7.30.1",
|
|
36
|
+
"@testing-library/jest-dom": "^5.11.10",
|
|
37
|
+
"@types/jest": "^29.0.1",
|
|
38
|
+
"@types/node": "^18.6.2",
|
|
39
|
+
"@typescript-eslint/eslint-plugin": "^5.36.2",
|
|
40
|
+
"@typescript-eslint/parser": "^5.36.2",
|
|
41
|
+
"@vitejs/plugin-vue": "^3.0.1",
|
|
42
|
+
"babel-eslint": "^10.1.0",
|
|
43
|
+
"babel-jest": "^29.0.3",
|
|
44
|
+
"babel-loader": "^8.2.2",
|
|
45
|
+
"cypress": "^6.8.0",
|
|
46
|
+
"eslint": "8.22.0",
|
|
47
|
+
"eslint-config-prettier": "^8.1.0",
|
|
48
|
+
"eslint-plugin-cypress": "^2.11.2",
|
|
49
|
+
"eslint-plugin-html": "^7.1.0",
|
|
50
|
+
"eslint-plugin-import": "^2.22.1",
|
|
51
|
+
"eslint-plugin-jest": "^24.3.2",
|
|
52
|
+
"eslint-plugin-prettier": "^3.3.1",
|
|
53
|
+
"eslint-plugin-simple-import-sort": "^7.0.0",
|
|
54
|
+
"jest": "^29.0.3",
|
|
55
|
+
"prettier": "^2.7.1",
|
|
56
|
+
"ts-jest": "^29.0.0",
|
|
57
|
+
"typescript": "^4.8.3",
|
|
58
|
+
"vite": "^3.1.2",
|
|
59
|
+
"vue-tsc": "^0.38.9"
|
|
60
|
+
},
|
|
61
|
+
"dependencies": {
|
|
62
|
+
"lkt-events": "^1.0.2",
|
|
63
|
+
"lkt-string-tools": "^1.0.3",
|
|
64
|
+
"lkt-ts-interfaces": "^1.0.2",
|
|
65
|
+
"vue": "^3.3",
|
|
66
|
+
"vuedraggable": "^4.1.0"
|
|
67
|
+
},
|
|
68
|
+
"engines": {
|
|
69
|
+
"node": ">=18"
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
export default {name: "LktHiddenRow", inheritAttrs: false}
|
|
3
|
+
</script>
|
|
4
|
+
|
|
5
|
+
<script lang="ts" setup>
|
|
6
|
+
import {createLktEvent} from "lkt-events";
|
|
7
|
+
import {getColumnDisplayContent} from "../functions/table-functions";
|
|
8
|
+
import {LktTableColumn} from "../instances/LktTableColumn";
|
|
9
|
+
import {PropType} from "vue/dist/vue";
|
|
10
|
+
|
|
11
|
+
const emit = defineEmits(['click']);
|
|
12
|
+
|
|
13
|
+
const props = defineProps({
|
|
14
|
+
isDraggable: {type: Boolean, default: true},
|
|
15
|
+
sortable: {type: Boolean, default: true},
|
|
16
|
+
i: {type: [Number], default: 0},
|
|
17
|
+
hiddenColumnsColSpan: {type: Number, default: 0},
|
|
18
|
+
visibleColumns: {type: Array as PropType<LktTableColumn[]>, default: (): LktTableColumn[] => []},
|
|
19
|
+
hiddenColumns: {type: Array as PropType<LktTableColumn[]>, default: (): LktTableColumn[] => []},
|
|
20
|
+
emptyColumns: {type: Array as PropType<string[]>, default: (): string[] => []},
|
|
21
|
+
hiddenIsVisible: {type: Boolean, default: false},
|
|
22
|
+
item: {type: Object as PropType<any>, default: () => ({})},
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const onClick = ($event: any, item: any, column: LktTableColumn) => {
|
|
26
|
+
emit('click', $event, createLktEvent('', {item, column}))
|
|
27
|
+
};
|
|
28
|
+
</script>
|
|
29
|
+
|
|
30
|
+
<template>
|
|
31
|
+
<tr v-show="hiddenIsVisible" data-role="hidden-row">
|
|
32
|
+
<td :colspan="hiddenColumnsColSpan">
|
|
33
|
+
<table>
|
|
34
|
+
<tr>
|
|
35
|
+
<th v-for="column in hiddenColumns" :data-column="column.key">
|
|
36
|
+
<div>{{ column.label }}</div>
|
|
37
|
+
</th>
|
|
38
|
+
</tr>
|
|
39
|
+
<tr :data-i="i">
|
|
40
|
+
<td v-for="(column, i) in hiddenColumns"
|
|
41
|
+
v-bind:data-column="column.key"
|
|
42
|
+
v-bind:title="getColumnDisplayContent (column, item, i)"
|
|
43
|
+
v-on:click="onClick($event, item, column)">
|
|
44
|
+
<template v-if="!!$slots[column.key]">
|
|
45
|
+
<slot v-bind:name="column.key"
|
|
46
|
+
v-bind:value="item[column.key]"
|
|
47
|
+
v-bind:item="item"
|
|
48
|
+
v-bind:column="column"
|
|
49
|
+
v-bind:i="i"></slot>
|
|
50
|
+
</template>
|
|
51
|
+
<template v-else>
|
|
52
|
+
{{ getColumnDisplayContent(column, item, i) }}
|
|
53
|
+
</template>
|
|
54
|
+
</td>
|
|
55
|
+
</tr>
|
|
56
|
+
</table>
|
|
57
|
+
</td>
|
|
58
|
+
</tr>
|
|
59
|
+
</template>
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
export default {name: "LktTableRow", inheritAttrs: false}
|
|
3
|
+
</script>
|
|
4
|
+
|
|
5
|
+
<script lang="ts" setup>
|
|
6
|
+
import {createLktEvent} from "lkt-events";
|
|
7
|
+
import {getColumnDisplayContent, getHorizontalColSpan, canRenderColumn} from "../functions/table-functions";
|
|
8
|
+
import {LktTableColumn} from "../instances/LktTableColumn";
|
|
9
|
+
import {PropType} from "vue/dist/vue";
|
|
10
|
+
|
|
11
|
+
const emit = defineEmits(['click', 'show']);
|
|
12
|
+
|
|
13
|
+
const props = defineProps({
|
|
14
|
+
isDraggable: {type: Boolean, default: true},
|
|
15
|
+
sortable: {type: Boolean, default: true},
|
|
16
|
+
i: {type: [Number], default: 0},
|
|
17
|
+
displayHiddenColumnsIndicator: {type: Boolean, default: false},
|
|
18
|
+
visibleColumns: {type: Array as PropType<LktTableColumn[]>, default: (): LktTableColumn[] => []},
|
|
19
|
+
emptyColumns: {type: Array as PropType<string[]>, default: (): string[] => []},
|
|
20
|
+
hiddenIsVisible: {type: Boolean, default: false},
|
|
21
|
+
item: {type: Object as PropType<any>, default: () => ({})},
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const onClick = ($event: any, item: any, column: LktTableColumn) => {
|
|
25
|
+
emit('click', $event, createLktEvent('', {item, column}))
|
|
26
|
+
};
|
|
27
|
+
const onShow = ($event: any, i: any) => {
|
|
28
|
+
emit('show', $event, createLktEvent('', {i}))
|
|
29
|
+
};
|
|
30
|
+
</script>
|
|
31
|
+
|
|
32
|
+
<template>
|
|
33
|
+
<tr :data-i="i" :data-handle-drag="isDraggable">
|
|
34
|
+
<td v-if="sortable && isDraggable" data-role="drag-indicator"></td>
|
|
35
|
+
<td v-else-if="sortable" data-role="invalid-drag-indicator"></td>
|
|
36
|
+
<td v-if="displayHiddenColumnsIndicator"
|
|
37
|
+
v-on:click="onShow($event, i)" data-role="show-more"
|
|
38
|
+
v-bind:class="hiddenIsVisible ? 'state-open' : ''"></td>
|
|
39
|
+
<template v-for="column in visibleColumns">
|
|
40
|
+
<td v-if="canRenderColumn(column, emptyColumns, item)"
|
|
41
|
+
v-bind:data-column="column.key"
|
|
42
|
+
v-bind:colspan="getHorizontalColSpan(column,item)"
|
|
43
|
+
v-bind:title="getColumnDisplayContent (column, item, i)"
|
|
44
|
+
v-on:click="onClick($event, item, column)"
|
|
45
|
+
>
|
|
46
|
+
<template v-if="!!$slots[column.key]">
|
|
47
|
+
<slot v-bind:name="column.key"
|
|
48
|
+
v-bind:value="item[column.key]"
|
|
49
|
+
v-bind:item="item"
|
|
50
|
+
v-bind:column="column"
|
|
51
|
+
v-bind:i="i"></slot>
|
|
52
|
+
</template>
|
|
53
|
+
<template v-else-if="item">
|
|
54
|
+
{{ getColumnDisplayContent(column, item, i) }}
|
|
55
|
+
</template>
|
|
56
|
+
</td>
|
|
57
|
+
</template>
|
|
58
|
+
</tr>
|
|
59
|
+
|
|
60
|
+
</template>
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/* eslint-disable import/prefer-default-export */
|
|
2
|
+
import {default as table} from "./lib-components/LktTable.vue";
|
|
3
|
+
import {App} from "vue";
|
|
4
|
+
|
|
5
|
+
export {createColumn, createHiddenColumn} from "./functions/table-functions";
|
|
6
|
+
|
|
7
|
+
const LktTable = {
|
|
8
|
+
install: (app: App) => {
|
|
9
|
+
app.component('lkt-table', table);
|
|
10
|
+
},
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export default LktTable;
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
export default {name: "LktTable", inheritAttrs: false}
|
|
3
|
+
</script>
|
|
4
|
+
|
|
5
|
+
<script lang="ts" setup>
|
|
6
|
+
import draggable from "vuedraggable";
|
|
7
|
+
import {
|
|
8
|
+
defaultTableSorter,
|
|
9
|
+
getVerticalColSpan,
|
|
10
|
+
getDefaultSortColumn,
|
|
11
|
+
getColumnByKey
|
|
12
|
+
} from "../functions/table-functions";
|
|
13
|
+
import LktTableRow from "../components/LktTableRow.vue";
|
|
14
|
+
import {computed, onMounted, PropType, ref, useSlots, watch} from "vue";
|
|
15
|
+
import {LktTableColumn} from "../instances/LktTableColumn";
|
|
16
|
+
import {LktEvent} from "lkt-events/dist/types/classes/LktEvent";
|
|
17
|
+
import LktHiddenRow from "../components/LktHiddenRow.vue";
|
|
18
|
+
import {generateRandomString} from "lkt-string-tools";
|
|
19
|
+
import {LktObject} from "lkt-ts-interfaces";
|
|
20
|
+
|
|
21
|
+
const emit = defineEmits(['update:modelValue', 'sort', 'click']);
|
|
22
|
+
|
|
23
|
+
const slots = useSlots();
|
|
24
|
+
|
|
25
|
+
const props = defineProps({
|
|
26
|
+
modelValue: {type: Array as PropType<LktObject[]>, default: (): any[] => []},
|
|
27
|
+
columns: {type: Array as PropType<LktTableColumn[]>, default: (): LktTableColumn[] => []},
|
|
28
|
+
sorter: {type: Function, default: defaultTableSorter},
|
|
29
|
+
sortable: {type: Boolean, default: false},
|
|
30
|
+
hideEmptyColumns: {type: Boolean, default: false},
|
|
31
|
+
draggableChecker: {type: Function, default: (item: any) => true},
|
|
32
|
+
checkValidDrag: {type: Function, default: (evt: any) => true},
|
|
33
|
+
draggableItemKey: {type: String, default: 'name'}
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
const hiddenColumnsStack: LktObject = {};
|
|
37
|
+
|
|
38
|
+
const Sorter = ref(typeof props.sorter === 'function' ? props.sorter : defaultTableSorter),
|
|
39
|
+
SortBy = ref(getDefaultSortColumn(props.columns)),
|
|
40
|
+
SortDirection = ref('asc'),
|
|
41
|
+
Items = ref(props.modelValue),
|
|
42
|
+
Hidden = ref(hiddenColumnsStack),
|
|
43
|
+
drag = ref(false);
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
const uniqueId = generateRandomString(12);
|
|
47
|
+
|
|
48
|
+
const hasData = computed(() => {
|
|
49
|
+
return Items.value.length > 0;
|
|
50
|
+
}),
|
|
51
|
+
emptyColumns = computed(() => {
|
|
52
|
+
if (!props.hideEmptyColumns) return [];
|
|
53
|
+
let r: string[] = [];
|
|
54
|
+
props.columns.forEach((column: LktTableColumn) => {
|
|
55
|
+
let key = column.key;
|
|
56
|
+
|
|
57
|
+
let ok = false;
|
|
58
|
+
Items.value.forEach((item: any) => {
|
|
59
|
+
if (typeof item.checkEmpty === 'function') {
|
|
60
|
+
return item.checkEmpty(item);
|
|
61
|
+
}
|
|
62
|
+
if (item[key]) ok = true;
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
if (!ok) r.push(key);
|
|
66
|
+
});
|
|
67
|
+
return r;
|
|
68
|
+
}),
|
|
69
|
+
visibleColumns = computed(() => {
|
|
70
|
+
return props.columns.filter((c: LktTableColumn) => !c.hidden);
|
|
71
|
+
}),
|
|
72
|
+
hiddenColumns = computed(() => {
|
|
73
|
+
return props.columns.filter((c: LktTableColumn) => c.hidden);
|
|
74
|
+
}),
|
|
75
|
+
hiddenColumnsColSpan = computed(() => {
|
|
76
|
+
let r = visibleColumns.value.length + 1;
|
|
77
|
+
if (props.sortable) ++r;
|
|
78
|
+
return r;
|
|
79
|
+
}),
|
|
80
|
+
displayHiddenColumnsIndicator = computed(() => {
|
|
81
|
+
return hiddenColumns.value.length > 0 && !props.sortable;
|
|
82
|
+
}),
|
|
83
|
+
columnKeys = computed((): string[] => {
|
|
84
|
+
return props.columns.map(c => c.key);
|
|
85
|
+
|
|
86
|
+
}),
|
|
87
|
+
colSlots = computed((): LktObject => {
|
|
88
|
+
let r = [];
|
|
89
|
+
for (let k in slots) if (columnKeys.value.indexOf(k) !== -1) r.push(k);
|
|
90
|
+
return r;
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
const getItemByEvent = (e: any) => {
|
|
95
|
+
let t = e.target;
|
|
96
|
+
if (typeof t.dataset.column === 'undefined') {
|
|
97
|
+
do {
|
|
98
|
+
t = t.parentNode;
|
|
99
|
+
} while (typeof t.dataset.column === 'undefined' && t.tagName !== 'TABLE' && t.tagName !== 'body');
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (t.tagName === 'TD') {
|
|
103
|
+
t = t.parentNode;
|
|
104
|
+
t = t.dataset.i;
|
|
105
|
+
if (typeof t !== 'undefined') return Items.value[t];
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return undefined;
|
|
109
|
+
},
|
|
110
|
+
isVisible = (index: number) => {
|
|
111
|
+
return Hidden.value['tr_' + index] === true;
|
|
112
|
+
},
|
|
113
|
+
sort = (column: LktTableColumn | null) => {
|
|
114
|
+
if (!column) return;
|
|
115
|
+
if (column.sortable) {
|
|
116
|
+
Items.value = Items.value.sort((a: any, b: any) => {
|
|
117
|
+
return Sorter.value(a, b, column, SortDirection.value);
|
|
118
|
+
});
|
|
119
|
+
SortDirection.value = SortDirection.value === 'asc' ? 'desc' : 'asc';
|
|
120
|
+
SortBy.value = column.key;
|
|
121
|
+
emit('sort', [SortBy.value, SortDirection.value]);
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
onClick = ($event: any, $lkt: LktEvent) => {
|
|
125
|
+
emit('click', $event, $lkt);
|
|
126
|
+
},
|
|
127
|
+
show = ($event: any, $lkt: LktEvent) => {
|
|
128
|
+
let k = 'tr_' + $lkt.value.i;
|
|
129
|
+
Hidden.value[k] = typeof Hidden.value[k] === 'undefined' ? true : !Hidden.value[k];
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
onMounted(() => {
|
|
133
|
+
sort(getColumnByKey(props.columns, SortBy.value));
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
watch(() => props.modelValue, (v) => Items.value = v);
|
|
137
|
+
watch(Items, (v: any) => emit('update:modelValue', v));
|
|
138
|
+
|
|
139
|
+
defineExpose({getItemByEvent});
|
|
140
|
+
|
|
141
|
+
</script>
|
|
142
|
+
|
|
143
|
+
<template>
|
|
144
|
+
<div v-if="hasData" class="lkt-table" :data-sortable="sortable">
|
|
145
|
+
<table>
|
|
146
|
+
<thead>
|
|
147
|
+
<tr>
|
|
148
|
+
<th v-if="sortable" data-role="drag-indicator"></th>
|
|
149
|
+
<th v-if="displayHiddenColumnsIndicator"></th>
|
|
150
|
+
<template v-for="column in visibleColumns">
|
|
151
|
+
<th :data-column="column.key"
|
|
152
|
+
v-if="emptyColumns.indexOf(column.key) === -1"
|
|
153
|
+
v-bind:data-sortable="column.sortable === true"
|
|
154
|
+
v-bind:data-sort="column.sortable === true && SortBy === column.key ? SortDirection : ''"
|
|
155
|
+
v-bind:colspan="getVerticalColSpan(column, columns.length, Items)"
|
|
156
|
+
v-bind:title="column.label"
|
|
157
|
+
v-on:click="sort(column)"
|
|
158
|
+
>
|
|
159
|
+
<div>{{ column.label }}</div>
|
|
160
|
+
</th>
|
|
161
|
+
</template>
|
|
162
|
+
</tr>
|
|
163
|
+
</thead>
|
|
164
|
+
<draggable v-if="sortable"
|
|
165
|
+
v-model="Items"
|
|
166
|
+
v-bind:move="checkValidDrag"
|
|
167
|
+
v-bind:itemKey="draggableItemKey"
|
|
168
|
+
v-on:start="drag=true"
|
|
169
|
+
v-on:end="drag=false"
|
|
170
|
+
tag="tbody"
|
|
171
|
+
class="lkt-sortable-table"
|
|
172
|
+
handle="[data-handle-drag]">
|
|
173
|
+
<template #item="{element, index}">
|
|
174
|
+
<lkt-table-row
|
|
175
|
+
v-bind:key="uniqueId + '-' + index"
|
|
176
|
+
v-bind:i="index"
|
|
177
|
+
v-bind:item="element"
|
|
178
|
+
v-bind:display-hidden-columns-indicator="displayHiddenColumnsIndicator"
|
|
179
|
+
v-bind:is-draggable="draggableChecker ? draggableChecker(element) : true"
|
|
180
|
+
v-bind:sortable="sortable"
|
|
181
|
+
v-bind:visible-columns="visibleColumns"
|
|
182
|
+
v-bind:empty-columns="emptyColumns"
|
|
183
|
+
v-bind:hidden-is-visible="isVisible(index)"
|
|
184
|
+
v-on:click="onClick"
|
|
185
|
+
v-on:show="show"
|
|
186
|
+
>
|
|
187
|
+
<template
|
|
188
|
+
v-for="column in colSlots"
|
|
189
|
+
v-slot:[column]="row">
|
|
190
|
+
<slot
|
|
191
|
+
v-bind:name="column"
|
|
192
|
+
v-bind:item="row.item"
|
|
193
|
+
v-bind:value="row.value"
|
|
194
|
+
v-bind:column="row.column"
|
|
195
|
+
></slot>
|
|
196
|
+
</template>
|
|
197
|
+
</lkt-table-row>
|
|
198
|
+
</template>
|
|
199
|
+
</draggable>
|
|
200
|
+
|
|
201
|
+
<tbody v-else>
|
|
202
|
+
<lkt-table-row
|
|
203
|
+
v-for="(item, i) in Items"
|
|
204
|
+
v-bind:key="uniqueId + '-' + i"
|
|
205
|
+
v-bind:i="i"
|
|
206
|
+
v-bind:item="item"
|
|
207
|
+
v-bind:display-hidden-columns-indicator="displayHiddenColumnsIndicator"
|
|
208
|
+
v-bind:is-draggable="draggableChecker ? draggableChecker(item) : true"
|
|
209
|
+
v-bind:sortable="sortable"
|
|
210
|
+
v-bind:visible-columns="visibleColumns"
|
|
211
|
+
v-bind:empty-columns="emptyColumns"
|
|
212
|
+
v-bind:hidden-is-visible="isVisible(i)"
|
|
213
|
+
v-on:click="onClick"
|
|
214
|
+
v-on:show="show"
|
|
215
|
+
>
|
|
216
|
+
<template
|
|
217
|
+
v-for="column in colSlots"
|
|
218
|
+
v-slot:[column]="row">
|
|
219
|
+
<slot
|
|
220
|
+
v-bind:name="column"
|
|
221
|
+
v-bind:item="row.item"
|
|
222
|
+
v-bind:value="row.value"
|
|
223
|
+
v-bind:column="row.column"
|
|
224
|
+
></slot>
|
|
225
|
+
</template>
|
|
226
|
+
</lkt-table-row>
|
|
227
|
+
<lkt-hidden-row
|
|
228
|
+
v-if="hiddenColumns.length > 0"
|
|
229
|
+
v-for="(item, i) in Items"
|
|
230
|
+
v-bind:key="uniqueId + '-' + i"
|
|
231
|
+
v-bind:i="i"
|
|
232
|
+
v-bind:item="item"
|
|
233
|
+
v-bind:hidden-columns="hiddenColumns"
|
|
234
|
+
v-bind:hidden-columns-col-span="hiddenColumnsColSpan"
|
|
235
|
+
v-bind:is-draggable="draggableChecker ? draggableChecker(item) : true"
|
|
236
|
+
v-bind:sortable="sortable"
|
|
237
|
+
v-bind:visible-columns="visibleColumns"
|
|
238
|
+
v-bind:empty-columns="emptyColumns"
|
|
239
|
+
v-bind:hidden-is-visible="isVisible(i)"
|
|
240
|
+
v-on:click="onClick"
|
|
241
|
+
v-on:show="show"
|
|
242
|
+
>
|
|
243
|
+
<template
|
|
244
|
+
v-for="column in colSlots"
|
|
245
|
+
v-slot:[column]="row">
|
|
246
|
+
<slot
|
|
247
|
+
v-bind:name="column"
|
|
248
|
+
v-bind:item="row.item"
|
|
249
|
+
v-bind:value="row.value"
|
|
250
|
+
v-bind:column="row.column"
|
|
251
|
+
></slot>
|
|
252
|
+
</template>
|
|
253
|
+
</lkt-hidden-row>
|
|
254
|
+
</tbody>
|
|
255
|
+
</table>
|
|
256
|
+
</div>
|
|
257
|
+
<div v-else-if="!!$slots['no-items']" class="lkt-empty-table">
|
|
258
|
+
<slot name="no-items"></slot>
|
|
259
|
+
</div>
|
|
260
|
+
</template>
|