@mptw/skylens-ui 1.2.14 → 1.2.16
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/components/SLTable.vue +231 -386
- package/interface/ITableField.ts +5 -2
- package/package.json +1 -1
package/components/SLTable.vue
CHANGED
|
@@ -1,409 +1,254 @@
|
|
|
1
1
|
<template lang="pug">
|
|
2
|
-
div
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
slot(name="thead")
|
|
2
|
+
div
|
|
3
|
+
.table(
|
|
4
|
+
:class="{ 'table-responsive': responsive }"
|
|
5
|
+
@mousemove="onMousemoved"
|
|
6
|
+
)
|
|
7
|
+
table
|
|
8
|
+
thead
|
|
10
9
|
tr
|
|
11
|
-
template(v-for="field, index in fields")
|
|
10
|
+
template(v-for="field, index in fields" :key="field.key")
|
|
12
11
|
slot(
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
v-if="$slots[`${field.key}-header`]"
|
|
13
|
+
:name="`${field.key}-header`"
|
|
14
|
+
:field="field"
|
|
15
|
+
:index="index"
|
|
16
|
+
)
|
|
18
17
|
th(
|
|
19
18
|
v-else
|
|
20
19
|
:style="field._style"
|
|
21
|
-
:class="[field._class, { sortable: field.sortable, sorting: field.key === sortBy,
|
|
20
|
+
:class="[field._class, { sortable: field.sortable, sorting: field.key === sortBy, 'sort-desc': sortDesc}]"
|
|
22
21
|
:colspan="headerColumnSpans[index]"
|
|
23
|
-
@click.prevent="onClickedHeaderCol(field.key)"
|
|
24
22
|
:key="field.key"
|
|
25
|
-
:name="`${field.key}-header`"
|
|
26
23
|
)
|
|
27
|
-
.inline-flex.items-center
|
|
28
|
-
SLElementWithTitle(:title="field.
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
:
|
|
53
|
-
:
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
:
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
import type { PropType } from "vue";
|
|
93
|
-
import { fromEvent, Subscription } from "rxjs";
|
|
94
|
-
import { createPopper } from "@popperjs/core";
|
|
95
|
-
import type { Instance as PopperInstance } from "@popperjs/core";
|
|
96
|
-
import type ITableField from "~ui/interface/ITableField";
|
|
97
|
-
|
|
98
|
-
export default defineComponent({
|
|
99
|
-
name: "SLTable",
|
|
100
|
-
components: {},
|
|
101
|
-
props: {
|
|
102
|
-
items: {
|
|
103
|
-
type: Array,
|
|
104
|
-
default: () => [],
|
|
105
|
-
},
|
|
106
|
-
fields: {
|
|
107
|
-
type: Array as PropType<Array<ITableField>>,
|
|
108
|
-
default: () => [],
|
|
109
|
-
},
|
|
110
|
-
sortBy: {
|
|
111
|
-
type: String,
|
|
112
|
-
default: "",
|
|
113
|
-
},
|
|
114
|
-
sortDesc: {
|
|
115
|
-
type: Boolean,
|
|
116
|
-
default: false,
|
|
117
|
-
},
|
|
118
|
-
filterBy: {
|
|
119
|
-
type: String,
|
|
120
|
-
default: "",
|
|
121
|
-
},
|
|
122
|
-
hoverableRows: {
|
|
123
|
-
type: Boolean,
|
|
124
|
-
default: false,
|
|
125
|
-
},
|
|
126
|
-
clickableRows: {
|
|
127
|
-
type: Boolean,
|
|
128
|
-
default: false,
|
|
129
|
-
},
|
|
130
|
-
loading: {
|
|
131
|
-
type: Boolean,
|
|
132
|
-
default: false,
|
|
133
|
-
},
|
|
134
|
-
responsive: {
|
|
135
|
-
type: Boolean,
|
|
136
|
-
default: true,
|
|
137
|
-
},
|
|
138
|
-
tdBorderColor: {
|
|
139
|
-
type: String,
|
|
140
|
-
default: "border-border",
|
|
141
|
-
},
|
|
142
|
-
tdHoverColor: {
|
|
143
|
-
type: String,
|
|
144
|
-
default: "bg-bg",
|
|
145
|
-
},
|
|
146
|
-
noItems: {
|
|
147
|
-
type: String,
|
|
148
|
-
default: "無資料",
|
|
24
|
+
.inline-flex.items-center.space-x-1
|
|
25
|
+
SLElementWithTitle(v-if='field.info', :title="field.info")
|
|
26
|
+
SLIcon.text-primary(icon='info-circle')
|
|
27
|
+
component(:is='field.sortable ? "a" : "div"', href='javascript:;' class='inline-flex items-center', @click="field.sortable && sort(field.key)")
|
|
28
|
+
span {{ field.label }}
|
|
29
|
+
SLIcon.sort-icon.ml-2(v-if="field.sortable" :icon="sortDesc ? 'descending' : 'ascending'")
|
|
30
|
+
tbody(:class="{ 'hoverable': hoverableRows, 'clickable': clickableRows }")
|
|
31
|
+
template(v-for="(item, itemIndex) in bodyHeaderItems" :key="itemIndex")
|
|
32
|
+
tr.body-header-row(
|
|
33
|
+
@click="rowClicked(item, itemIndex, $event)"
|
|
34
|
+
@mouseenter="rowMouseEntered(item, itemIndex, $event)"
|
|
35
|
+
@mouseleave="rowMouseLeaved(item, itemIndex, $event)"
|
|
36
|
+
:tabindex="clickableRows ? 0 : undefined"
|
|
37
|
+
:class="[hoverableRows ? `hover:${tdHoverColor}` : '', `${hoverRowIndex === itemIndex ? tdHoverColor : ''}`, { hover: hoverRowIndex === itemIndex }]"
|
|
38
|
+
)
|
|
39
|
+
template(v-for="(field, index) in fields" :key="field.key")
|
|
40
|
+
slot(
|
|
41
|
+
v-if="$slots[`body-header-${field.key}`]"
|
|
42
|
+
:name="field.key"
|
|
43
|
+
:item="item"
|
|
44
|
+
:index="itemIndex"
|
|
45
|
+
).border-border
|
|
46
|
+
td(
|
|
47
|
+
v-else
|
|
48
|
+
:colspan="columnSpans[index]"
|
|
49
|
+
:key="`${itemIndex}-${field.key}`"
|
|
50
|
+
:class='[tdBorderColor, field._class, { sortable: field.sortable }]'
|
|
51
|
+
) {{ item[field.key] }}
|
|
52
|
+
template(v-for="(item, itemIndex) in items" :key="itemIndex")
|
|
53
|
+
tr(
|
|
54
|
+
@click="rowClicked(item, itemIndex, $event)"
|
|
55
|
+
@mouseenter="rowMouseEntered(item, itemIndex, $event)"
|
|
56
|
+
@mouseleave="rowMouseLeaved(item, itemIndex, $event)"
|
|
57
|
+
:tabindex="clickableRows ? 0 : undefined"
|
|
58
|
+
:class="[hoverableRows ? `hover:${tdHoverColor}` : '', `${hoverRowIndex === itemIndex ? tdHoverColor : ''}`, { hover: hoverRowIndex === itemIndex }]"
|
|
59
|
+
)
|
|
60
|
+
template(v-for="(field, index) in fields" :key="field.key")
|
|
61
|
+
slot(
|
|
62
|
+
v-if="$slots[field.key]"
|
|
63
|
+
:name="field.key"
|
|
64
|
+
:item="item"
|
|
65
|
+
:index="itemIndex"
|
|
66
|
+
).border-border
|
|
67
|
+
td(
|
|
68
|
+
v-else
|
|
69
|
+
:colspan="columnSpans[index]"
|
|
70
|
+
:key="`${itemIndex}-${field.key}`"
|
|
71
|
+
:class='[tdBorderColor, field._class, { sortable: field.sortable }]'
|
|
72
|
+
) {{ item[field.key] }}
|
|
73
|
+
tr(v-if="items.length === 0")
|
|
74
|
+
td(:colspan="fields.length")
|
|
75
|
+
.my-28.text-base.text-gray-2.text-center {{ noItems }}
|
|
76
|
+
SLLoading(
|
|
77
|
+
v-if="loading"
|
|
78
|
+
:boundaries="[{ sides: ['top'], query: 'td' }, { sides: ['bottom'], query: 'tbody' }]"
|
|
79
|
+
)
|
|
80
|
+
</template>
|
|
81
|
+
|
|
82
|
+
<script lang="ts">
|
|
83
|
+
import type { PropType } from 'vue';
|
|
84
|
+
import type ITableField from '@/interface/ITableField';
|
|
85
|
+
|
|
86
|
+
export default defineComponent({
|
|
87
|
+
name: 'SLTable',
|
|
88
|
+
components: {
|
|
149
89
|
},
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
90
|
+
props: {
|
|
91
|
+
items: {
|
|
92
|
+
type: Array,
|
|
93
|
+
default: () => [],
|
|
94
|
+
},
|
|
95
|
+
bodyHeaderItems: {
|
|
96
|
+
type: Array,
|
|
97
|
+
default: () => [],
|
|
98
|
+
},
|
|
99
|
+
fields: {
|
|
100
|
+
type: Array as PropType<Array<ITableField>>,
|
|
101
|
+
default: () => [],
|
|
102
|
+
},
|
|
103
|
+
sortBy: {
|
|
104
|
+
type: String,
|
|
105
|
+
default: '',
|
|
106
|
+
},
|
|
107
|
+
sortDesc: {
|
|
108
|
+
type: Boolean,
|
|
109
|
+
default: false,
|
|
110
|
+
},
|
|
111
|
+
hoverableRows: {
|
|
112
|
+
type: Boolean,
|
|
113
|
+
default: false,
|
|
114
|
+
},
|
|
115
|
+
clickableRows: {
|
|
116
|
+
type: Boolean,
|
|
117
|
+
default: false,
|
|
118
|
+
},
|
|
119
|
+
loading: {
|
|
120
|
+
type: Boolean,
|
|
121
|
+
default: false,
|
|
122
|
+
},
|
|
123
|
+
responsive: {
|
|
124
|
+
type: Boolean,
|
|
125
|
+
default: true,
|
|
126
|
+
},
|
|
127
|
+
tdBorderColor: {
|
|
128
|
+
type: String,
|
|
129
|
+
default: 'border-border',
|
|
130
|
+
},
|
|
131
|
+
tdHoverColor: {
|
|
132
|
+
type: String,
|
|
133
|
+
default: 'bg-bg',
|
|
134
|
+
},
|
|
135
|
+
noItems: {
|
|
136
|
+
type: String,
|
|
137
|
+
default: 'No Items',
|
|
138
|
+
},
|
|
153
139
|
},
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
const { fields, sortBy, sortDesc, clickableRows, hoverableRows } =
|
|
166
|
-
toRefs(props);
|
|
167
|
-
|
|
168
|
-
const el = shallowRef<HTMLElement | null>(null);
|
|
169
|
-
const popupEl = shallowRef<HTMLElement | null>(null);
|
|
170
|
-
const hoverRowIndex = ref(-1);
|
|
171
|
-
const filterOptions = ref<
|
|
172
|
-
{
|
|
173
|
-
key: string;
|
|
174
|
-
label?: string;
|
|
175
|
-
icon?: string;
|
|
176
|
-
}[]
|
|
177
|
-
>([]);
|
|
178
|
-
|
|
179
|
-
let popperInstance: PopperInstance | null = null;
|
|
180
|
-
let clickSubscriber: Subscription | null = null;
|
|
181
|
-
let filterHeaderCol: HTMLElement | null = null;
|
|
182
|
-
|
|
183
|
-
const headerColumnSpans = computed(() => {
|
|
184
|
-
return fields.value.map((field) => {
|
|
185
|
-
if (!field.colspan) return 1;
|
|
186
|
-
return field.colspan;
|
|
140
|
+
setup(props, { emit }) {
|
|
141
|
+
const { fields, sortBy, sortDesc, clickableRows, hoverableRows } =
|
|
142
|
+
toRefs(props);
|
|
143
|
+
|
|
144
|
+
const hoverRowIndex = ref(-1);
|
|
145
|
+
|
|
146
|
+
const headerColumnSpans = computed(() => {
|
|
147
|
+
return fields.value.map((field) => {
|
|
148
|
+
if (!field.colspan) return 1;
|
|
149
|
+
return field.colspan;
|
|
150
|
+
});
|
|
187
151
|
});
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
152
|
+
const columnSpans = computed(() => {
|
|
153
|
+
return fields.value.map((field) => {
|
|
154
|
+
if (!field.col) return 1;
|
|
155
|
+
if (!field.col.span) return 1;
|
|
156
|
+
return field.col.span;
|
|
157
|
+
});
|
|
194
158
|
});
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
emit("update:sortBy", fieldKey);
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
function onClickedHeaderCol(fieldKey: string) {
|
|
206
|
-
const field = fields.value.find((f) => f.key === fieldKey);
|
|
207
|
-
if (!field || (!field.sortable && !field.filterable)) return;
|
|
208
|
-
|
|
209
|
-
if (field.sortable) {
|
|
210
|
-
sort(field.key);
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
if (field.filterable) {
|
|
214
|
-
filterOptions.value = [...field.filterOptions];
|
|
215
|
-
filterHeaderCol = el.value.querySelector(`th[name=${field.key}-header]`)
|
|
216
|
-
.children[0] as HTMLElement;
|
|
217
|
-
show();
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
function rowClicked(item: any, index: number, e: Event) {
|
|
222
|
-
if (!clickableRows.value) return;
|
|
223
|
-
|
|
224
|
-
emit("row-clicked", item, index, e);
|
|
225
|
-
e.preventDefault();
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
function rowMouseEntered(item: any, index: number, e: Event) {
|
|
229
|
-
if (!hoverableRows.value) return;
|
|
230
|
-
|
|
231
|
-
hoverRowIndex.value = index;
|
|
232
|
-
emit("row-mouseentered", item, index, e);
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
function rowMouseLeaved(item: any, index: number, e: Event) {
|
|
236
|
-
if (!hoverableRows.value) return;
|
|
237
|
-
|
|
238
|
-
hoverRowIndex.value = -1;
|
|
239
|
-
emit("row-mouseleaved", item, index, e);
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
function onMousemoved(e: Event) {
|
|
243
|
-
if (!hoverableRows.value) return;
|
|
244
|
-
|
|
245
|
-
emit("table-mousemoved", e);
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
function subscribeClick() {
|
|
249
|
-
clickSubscriber = fromEvent(window, "click").subscribe((e) => {
|
|
250
|
-
const { target } = e;
|
|
251
|
-
if (
|
|
252
|
-
filterHeaderCol &&
|
|
253
|
-
popupEl.value &&
|
|
254
|
-
!filterHeaderCol.contains(target as HTMLElement) &&
|
|
255
|
-
!popupEl.value.contains(target as HTMLElement)
|
|
256
|
-
) {
|
|
257
|
-
hide();
|
|
159
|
+
|
|
160
|
+
function sort(fieldKey: string) {
|
|
161
|
+
if (fieldKey === sortBy.value) {
|
|
162
|
+
emit('update:sortDesc', !sortDesc.value);
|
|
163
|
+
} else {
|
|
164
|
+
emit('update:sortBy', fieldKey);
|
|
258
165
|
}
|
|
259
|
-
});
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
function unsubscribeClick() {
|
|
263
|
-
if (clickSubscriber) {
|
|
264
|
-
clickSubscriber.unsubscribe();
|
|
265
166
|
}
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
popupEl.value.setAttribute("data-show", "");
|
|
273
|
-
|
|
274
|
-
subscribeClick();
|
|
275
|
-
popperInstance.state.elements.reference = filterHeaderCol;
|
|
276
|
-
popperInstance.setOptions({
|
|
277
|
-
modifiers: [
|
|
278
|
-
{
|
|
279
|
-
name: "offset",
|
|
280
|
-
options: {
|
|
281
|
-
offset: [0, 4],
|
|
282
|
-
},
|
|
283
|
-
},
|
|
284
|
-
{ name: "eventListeners", enabled: true },
|
|
285
|
-
],
|
|
286
|
-
});
|
|
287
|
-
popperInstance.update();
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
function hide() {
|
|
291
|
-
if (
|
|
292
|
-
!popupEl.value ||
|
|
293
|
-
popupEl.value.getAttribute("data-show") === null ||
|
|
294
|
-
!popperInstance
|
|
295
|
-
)
|
|
296
|
-
return;
|
|
297
|
-
|
|
298
|
-
unsubscribeClick();
|
|
299
|
-
|
|
300
|
-
if (popupEl.value) {
|
|
301
|
-
popupEl.value.removeAttribute("data-show");
|
|
167
|
+
|
|
168
|
+
function rowClicked(item: any, index: number, e: Event) {
|
|
169
|
+
if (!clickableRows.value) return;
|
|
170
|
+
|
|
171
|
+
emit('row-clicked', item, index, e);
|
|
302
172
|
}
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
function onClickedFilter(filterKey: string) {
|
|
310
|
-
emit("update:filterBy", filterKey);
|
|
311
|
-
hide();
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
onMounted(() => {
|
|
315
|
-
if (el.value && popupEl.value) {
|
|
316
|
-
popperInstance = createPopper(el.value, popupEl.value, {
|
|
317
|
-
placement: "bottom-end",
|
|
318
|
-
modifiers: [{ name: "eventListeners", enabled: false }],
|
|
319
|
-
});
|
|
173
|
+
|
|
174
|
+
function rowMouseEntered(item: any, index: number, e: Event) {
|
|
175
|
+
if (!hoverableRows.value) return;
|
|
176
|
+
|
|
177
|
+
hoverRowIndex.value = index;
|
|
178
|
+
emit('row-mouseentered', item, index, e);
|
|
320
179
|
}
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
180
|
+
|
|
181
|
+
function rowMouseLeaved(item: any, index: number, e: Event) {
|
|
182
|
+
if (!hoverableRows.value) return;
|
|
183
|
+
|
|
184
|
+
hoverRowIndex.value = -1;
|
|
185
|
+
emit('row-mouseleaved', item, index, e);
|
|
326
186
|
}
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
});
|
|
346
|
-
</script>
|
|
347
|
-
|
|
348
|
-
<style lang="stylus">
|
|
349
|
-
.table
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
187
|
+
|
|
188
|
+
function onMousemoved(e: Event) {
|
|
189
|
+
if (!hoverableRows.value) return;
|
|
190
|
+
|
|
191
|
+
emit('table-mousemoved', e);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return {
|
|
195
|
+
hoverRowIndex,
|
|
196
|
+
headerColumnSpans,
|
|
197
|
+
columnSpans,
|
|
198
|
+
sort,
|
|
199
|
+
rowClicked,
|
|
200
|
+
rowMouseEntered,
|
|
201
|
+
rowMouseLeaved,
|
|
202
|
+
onMousemoved,
|
|
203
|
+
};
|
|
204
|
+
},
|
|
205
|
+
});
|
|
206
|
+
</script>
|
|
207
|
+
|
|
208
|
+
<style lang="stylus">
|
|
209
|
+
.table
|
|
210
|
+
@apply block relative w-full overflow-hidden
|
|
211
|
+
|
|
212
|
+
&.table-responsive
|
|
213
|
+
@apply overflow-auto
|
|
214
|
+
|
|
215
|
+
table
|
|
216
|
+
@apply table-auto
|
|
217
|
+
|
|
355
218
|
table
|
|
356
|
-
@apply table-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
&.sortable, &.filterable
|
|
368
|
-
@apply cursor-pointer
|
|
369
|
-
.sort-icon, .filter-icon
|
|
370
|
-
@apply opacity-0
|
|
371
|
-
&:hover,
|
|
372
|
-
&.sorting
|
|
219
|
+
@apply w-full table-fixed
|
|
220
|
+
|
|
221
|
+
thead
|
|
222
|
+
tr
|
|
223
|
+
@apply border-b border-primary-light bg-white
|
|
224
|
+
|
|
225
|
+
th
|
|
226
|
+
@apply px-2 pb-2 text-base font-normal text-primary whitespace-nowrap
|
|
227
|
+
|
|
228
|
+
&.sortable
|
|
229
|
+
cursor pointer
|
|
373
230
|
.sort-icon
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
231
|
+
opacity 0
|
|
232
|
+
transition transform 0.2s ease, opacity 0.1s ease
|
|
233
|
+
&:hover,
|
|
234
|
+
&.sorting
|
|
235
|
+
.sort-icon
|
|
236
|
+
opacity 1
|
|
237
|
+
|
|
238
|
+
tbody
|
|
239
|
+
&.clickable
|
|
240
|
+
tr
|
|
241
|
+
@apply cursor-pointer
|
|
242
|
+
|
|
381
243
|
tr
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
td
|
|
386
|
-
@apply p-2 border-b text-sm text-gray-2
|
|
387
|
-
|
|
388
|
-
.table-header-filter-popup
|
|
389
|
-
@apply z-10 flex border border-primary-light rounded overflow-hidden invisible pointer-events-none
|
|
390
|
-
|
|
391
|
-
&[data-show]
|
|
392
|
-
@apply visible pointer-events-auto
|
|
393
|
-
|
|
394
|
-
&-content
|
|
395
|
-
@apply flex flex-col
|
|
396
|
-
|
|
397
|
-
.table-header-filter-item
|
|
398
|
-
@apply inline-flex justify-center p-2 bg-white text-sm text-gray-3
|
|
399
|
-
@apply s('hover:bg-bg-middle')
|
|
400
|
-
|
|
401
|
-
&.active
|
|
402
|
-
@apply bg-bg text-primary
|
|
244
|
+
&.body-header-row
|
|
245
|
+
td
|
|
246
|
+
@apply bg-bg-middle text-lg font-bold shadow-inline
|
|
403
247
|
|
|
404
|
-
|
|
405
|
-
|
|
248
|
+
td
|
|
249
|
+
@apply p-2 border-b border-opacity-50 text-base text-gray-2
|
|
406
250
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
</style>
|
|
251
|
+
&.text-right.sortable
|
|
252
|
+
@apply pr-8
|
|
253
|
+
</style>
|
|
254
|
+
|
package/interface/ITableField.ts
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
|
+
import type { StyleValue } from "vue";
|
|
2
|
+
|
|
1
3
|
export default interface ITableField {
|
|
2
4
|
key: string;
|
|
3
5
|
label: string;
|
|
4
|
-
_style?:
|
|
6
|
+
_style?: StyleValue;
|
|
5
7
|
_class?: string | Object | Array<string | Object>;
|
|
6
8
|
sortable?: boolean;
|
|
7
9
|
filterable?: boolean;
|
|
8
10
|
colspan?: number;
|
|
9
11
|
col?: {
|
|
10
|
-
span?:number,
|
|
12
|
+
span?: number,
|
|
11
13
|
};
|
|
12
14
|
filterOptions?: {
|
|
13
15
|
key: string;
|
|
@@ -16,4 +18,5 @@ export default interface ITableField {
|
|
|
16
18
|
_iconClass?: string;
|
|
17
19
|
}[];
|
|
18
20
|
tooltip?: string;
|
|
21
|
+
info?: string;
|
|
19
22
|
}
|