stk-table-vue 0.0.1-beta.4 → 0.0.1-beta.6
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 +14 -8
- package/lib/src/StkTable/StkTable.vue.d.ts +19 -13
- package/lib/src/StkTable/index.d.ts +1 -0
- package/lib/src/StkTable/types/index.d.ts +5 -0
- package/lib/src/StkTable/useAutoResize.d.ts +15 -0
- package/lib/stk-table-vue.js +91 -28
- package/lib/style.css +68 -59
- package/lib/test/utils/DragResize.d.ts +28 -0
- package/lib/test/utils/h.d.ts +10 -0
- package/package.json +59 -59
- package/src/StkTable/StkTable.vue +34 -8
- package/src/StkTable/index.ts +1 -0
- package/src/StkTable/types/index.ts +6 -0
- package/src/StkTable/useAutoResize.ts +67 -0
- package/src/StkTable/useVirtualScroll.ts +9 -20
- package/src/StkTable/utils.ts +1 -0
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
# StkTable
|
|
1
|
+
# StkTable (Sticky Table)
|
|
2
2
|
|
|
3
3
|
Vue3 简易虚拟滚动表格。用于实时数据展示,新数据行高亮渐暗动效。
|
|
4
|
-
js体积(
|
|
4
|
+
js体积(未压缩41kb)
|
|
5
5
|
|
|
6
6
|
## 功能
|
|
7
7
|
* [x] 高亮行,单元格。
|
|
@@ -109,6 +109,18 @@ export type StkProps = Partial<{
|
|
|
109
109
|
|
|
110
110
|
/** 可拖动至最小的列宽 */
|
|
111
111
|
colMinWidth: number;
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* 单元格分割线。
|
|
115
|
+
* 默认横竖都有
|
|
116
|
+
* "h" - 仅展示横线
|
|
117
|
+
* "v" - 仅展示竖线
|
|
118
|
+
* "body-v" - 仅表体展示竖线
|
|
119
|
+
*/
|
|
120
|
+
bordered: boolean | 'h' | 'v' | 'body-v';
|
|
121
|
+
|
|
122
|
+
/** 自动重新计算虚拟滚动高度宽度。默认true */
|
|
123
|
+
autoResize: boolean;
|
|
112
124
|
}>;
|
|
113
125
|
```
|
|
114
126
|
|
|
@@ -151,12 +163,6 @@ export type StkTableColumn<T extends Record<string, any>> = {
|
|
|
151
163
|
customHeaderCell?: Component | VNode | CustomHeaderCellFunc<T>;
|
|
152
164
|
/** 二级表头 */
|
|
153
165
|
children?: StkTableColumn<T>[];
|
|
154
|
-
/**
|
|
155
|
-
* 单元格分割线。
|
|
156
|
-
* 默认横竖都有
|
|
157
|
-
* horizontal - 仅展示横线
|
|
158
|
-
*/
|
|
159
|
-
border: boolean | 'horizontal';
|
|
160
166
|
};
|
|
161
167
|
```
|
|
162
168
|
|
|
@@ -1,12 +1,9 @@
|
|
|
1
|
+
import { SortOption, StkTableColumn } from './types/index';
|
|
1
2
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* TODO:存在的问题:
|
|
5
|
-
* [] column.dataIndex 作为唯一键,不能重复
|
|
6
|
-
* [] 计算的高亮颜色,挂在数据源上对象上,若多个表格使用同一个数据源对象会有问题。需要深拷贝。(解决方案:获取组件uid)
|
|
7
|
-
* [] highlight-row 颜色不能恢复到active的颜色
|
|
3
|
+
* 初始化虚拟滚动参数
|
|
4
|
+
* @param {number} [height] 虚拟滚动的高度
|
|
8
5
|
*/
|
|
9
|
-
|
|
6
|
+
declare function initVirtualScroll(height?: number): void;
|
|
10
7
|
/**
|
|
11
8
|
* 选中一行,
|
|
12
9
|
* @param {string} rowKey
|
|
@@ -49,8 +46,8 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
|
|
|
49
46
|
virtualX: boolean;
|
|
50
47
|
columns: StkTableColumn<any>[];
|
|
51
48
|
dataSource: any[];
|
|
52
|
-
rowKey: import(
|
|
53
|
-
colKey: import(
|
|
49
|
+
rowKey: import("./types/index").UniqKey;
|
|
50
|
+
colKey: import("./types/index").UniqKey;
|
|
54
51
|
emptyCellText: string;
|
|
55
52
|
noDataFull: boolean;
|
|
56
53
|
showNoData: boolean;
|
|
@@ -63,6 +60,7 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
|
|
|
63
60
|
colResizable: boolean;
|
|
64
61
|
colMinWidth: number;
|
|
65
62
|
bordered: boolean | "h" | "v" | "body-v";
|
|
63
|
+
autoResize: boolean;
|
|
66
64
|
}>>, {
|
|
67
65
|
width: string;
|
|
68
66
|
fixedMode: boolean;
|
|
@@ -88,10 +86,15 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
|
|
|
88
86
|
colResizable: boolean;
|
|
89
87
|
colMinWidth: number;
|
|
90
88
|
bordered: boolean;
|
|
89
|
+
autoResize: boolean;
|
|
91
90
|
}>, {
|
|
91
|
+
initVirtualScroll: typeof initVirtualScroll;
|
|
92
|
+
initVirtualScrollX: () => void;
|
|
93
|
+
initVirtualScrollY: (height?: number | undefined) => void;
|
|
92
94
|
setCurrentRow: typeof setCurrentRow;
|
|
93
95
|
setHighlightDimCell: (rowKeyValue: string, dataIndex: string) => void;
|
|
94
96
|
setHighlightDimRow: (rowKeyValues: (string | number)[]) => void;
|
|
97
|
+
sortCol: import("vue").Ref<string | null | undefined>;
|
|
95
98
|
setSorter: typeof setSorter;
|
|
96
99
|
resetSorter: typeof resetSorter;
|
|
97
100
|
scrollTo: typeof scrollTo;
|
|
@@ -121,8 +124,8 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
|
|
|
121
124
|
virtualX: boolean;
|
|
122
125
|
columns: StkTableColumn<any>[];
|
|
123
126
|
dataSource: any[];
|
|
124
|
-
rowKey: import(
|
|
125
|
-
colKey: import(
|
|
127
|
+
rowKey: import("./types/index").UniqKey;
|
|
128
|
+
colKey: import("./types/index").UniqKey;
|
|
126
129
|
emptyCellText: string;
|
|
127
130
|
noDataFull: boolean;
|
|
128
131
|
showNoData: boolean;
|
|
@@ -135,6 +138,7 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
|
|
|
135
138
|
colResizable: boolean;
|
|
136
139
|
colMinWidth: number;
|
|
137
140
|
bordered: boolean | "h" | "v" | "body-v";
|
|
141
|
+
autoResize: boolean;
|
|
138
142
|
}>>, {
|
|
139
143
|
width: string;
|
|
140
144
|
fixedMode: boolean;
|
|
@@ -160,6 +164,7 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
|
|
|
160
164
|
colResizable: boolean;
|
|
161
165
|
colMinWidth: number;
|
|
162
166
|
bordered: boolean;
|
|
167
|
+
autoResize: boolean;
|
|
163
168
|
}>>> & {
|
|
164
169
|
onScroll?: ((...args: any[]) => any) | undefined;
|
|
165
170
|
"onTh-drag-start"?: ((...args: any[]) => any) | undefined;
|
|
@@ -178,7 +183,7 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
|
|
|
178
183
|
width: string;
|
|
179
184
|
minWidth: string;
|
|
180
185
|
maxWidth: string;
|
|
181
|
-
colKey: import(
|
|
186
|
+
colKey: import("./types/index").UniqKey;
|
|
182
187
|
fixedMode: boolean;
|
|
183
188
|
headless: boolean;
|
|
184
189
|
theme: "light" | "dark";
|
|
@@ -186,7 +191,7 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
|
|
|
186
191
|
virtualX: boolean;
|
|
187
192
|
columns: StkTableColumn<any>[];
|
|
188
193
|
dataSource: any[];
|
|
189
|
-
rowKey: import(
|
|
194
|
+
rowKey: import("./types/index").UniqKey;
|
|
190
195
|
emptyCellText: string;
|
|
191
196
|
noDataFull: boolean;
|
|
192
197
|
showNoData: boolean;
|
|
@@ -199,6 +204,7 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
|
|
|
199
204
|
colResizable: boolean;
|
|
200
205
|
colMinWidth: number;
|
|
201
206
|
bordered: boolean | "h" | "v" | "body-v";
|
|
207
|
+
autoResize: boolean;
|
|
202
208
|
}, {}>, {
|
|
203
209
|
tableHeader?(_: {
|
|
204
210
|
column: StkTableColumn<any>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Ref } from 'vue';
|
|
2
|
+
type Options = {
|
|
3
|
+
tableContainer: Ref<HTMLElement | undefined>;
|
|
4
|
+
initVirtualScroll: () => void;
|
|
5
|
+
scrollTo: () => void;
|
|
6
|
+
props: any;
|
|
7
|
+
/** 防抖延时 */
|
|
8
|
+
debounceMs: number;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* 窗口变化自动重置虚拟滚动
|
|
12
|
+
* @param param0
|
|
13
|
+
*/
|
|
14
|
+
export declare function useAutoResize({ tableContainer, initVirtualScroll, scrollTo, props, debounceMs }: Options): void;
|
|
15
|
+
export {};
|
package/lib/stk-table-vue.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { onMounted, onBeforeUnmount, watch, ref, computed, defineComponent, shallowRef, toRaw, openBlock, createElementBlock, normalizeClass, unref, normalizeStyle, withDirectives, createElementVNode, vShow, Fragment, renderList, createCommentVNode, createBlock, resolveDynamicComponent, renderSlot, toDisplayString, createTextVNode } from "vue";
|
|
2
2
|
import { interpolateRgb } from "d3-interpolate";
|
|
3
3
|
const Default_Col_Width = "100";
|
|
4
4
|
const Default_Table_Height = 100;
|
|
@@ -19,6 +19,54 @@ try {
|
|
|
19
19
|
console.error("Cannot get Chrome version", e);
|
|
20
20
|
}
|
|
21
21
|
const Is_Legacy_Mode = _chromeVersion < 56;
|
|
22
|
+
function useAutoResize({ tableContainer, initVirtualScroll, scrollTo, props, debounceMs }) {
|
|
23
|
+
let resizeObserver = null;
|
|
24
|
+
onMounted(() => {
|
|
25
|
+
initResizeObserver();
|
|
26
|
+
});
|
|
27
|
+
onBeforeUnmount(() => {
|
|
28
|
+
removeResizeObserver();
|
|
29
|
+
});
|
|
30
|
+
function initResizeObserver() {
|
|
31
|
+
if (window.ResizeObserver) {
|
|
32
|
+
if (!tableContainer.value) {
|
|
33
|
+
const watchDom = watch(
|
|
34
|
+
() => tableContainer,
|
|
35
|
+
() => {
|
|
36
|
+
initResizeObserver();
|
|
37
|
+
watchDom();
|
|
38
|
+
}
|
|
39
|
+
);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
resizeObserver = new ResizeObserver(resizeCallback);
|
|
43
|
+
resizeObserver.observe(tableContainer.value);
|
|
44
|
+
} else {
|
|
45
|
+
window.addEventListener("resize", resizeCallback);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function removeResizeObserver() {
|
|
49
|
+
if (resizeObserver) {
|
|
50
|
+
resizeObserver.disconnect();
|
|
51
|
+
resizeObserver = null;
|
|
52
|
+
} else {
|
|
53
|
+
window.removeEventListener("resize", resizeCallback);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
let debounceTime = 0;
|
|
57
|
+
function resizeCallback() {
|
|
58
|
+
if (debounceTime) {
|
|
59
|
+
window.clearTimeout(debounceTime);
|
|
60
|
+
}
|
|
61
|
+
debounceTime = window.setTimeout(() => {
|
|
62
|
+
if (props.autoResize) {
|
|
63
|
+
scrollTo();
|
|
64
|
+
initVirtualScroll();
|
|
65
|
+
}
|
|
66
|
+
debounceTime = 0;
|
|
67
|
+
}, debounceMs);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
22
70
|
function useColResize({ tableContainer, tableHeaderLast, colResizeIndicator, props, emit, colKeyGen }) {
|
|
23
71
|
const isColResizing = ref(false);
|
|
24
72
|
let colResizeState = {
|
|
@@ -328,17 +376,17 @@ function useVirtualScroll({ tableContainer, props, dataSourceCopy, tableHeaderLa
|
|
|
328
376
|
});
|
|
329
377
|
function initVirtualScrollY(height) {
|
|
330
378
|
var _a, _b;
|
|
331
|
-
if (virtual_on.value)
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
379
|
+
if (!virtual_on.value)
|
|
380
|
+
return;
|
|
381
|
+
virtualScroll.value.containerHeight = typeof height === "number" ? height : ((_a = tableContainer.value) == null ? void 0 : _a.offsetHeight) || Default_Table_Height;
|
|
382
|
+
updateVirtualScrollY((_b = tableContainer.value) == null ? void 0 : _b.scrollTop);
|
|
335
383
|
}
|
|
336
384
|
function initVirtualScrollX() {
|
|
337
|
-
if (props.virtualX)
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
385
|
+
if (!props.virtualX)
|
|
386
|
+
return;
|
|
387
|
+
const { offsetWidth, scrollLeft } = tableContainer.value || {};
|
|
388
|
+
virtualScrollX.value.containerWidth = offsetWidth || Default_Table_Width;
|
|
389
|
+
updateVirtualScrollX(scrollLeft);
|
|
342
390
|
}
|
|
343
391
|
function updateVirtualScrollY(sTop = 0) {
|
|
344
392
|
const { rowHeight } = virtualScroll.value;
|
|
@@ -444,6 +492,8 @@ function strCompare(a, b, type) {
|
|
|
444
492
|
}
|
|
445
493
|
}
|
|
446
494
|
function tableSort(sortOption, order, dataSource) {
|
|
495
|
+
if (!(dataSource == null ? void 0 : dataSource.length))
|
|
496
|
+
return dataSource || [];
|
|
447
497
|
let targetDataSource = [...dataSource];
|
|
448
498
|
if (typeof sortOption.sorter === "function") {
|
|
449
499
|
const customSorterData = sortOption.sorter(targetDataSource, { order, column: sortOption });
|
|
@@ -492,7 +542,6 @@ function howDeepTheColumn(arr, level = 1) {
|
|
|
492
542
|
});
|
|
493
543
|
return Math.max(...levels);
|
|
494
544
|
}
|
|
495
|
-
const _withScopeId = (n) => (pushScopeId("data-v-0aa41491"), n = n(), popScopeId(), n);
|
|
496
545
|
const _hoisted_1 = { key: 0 };
|
|
497
546
|
const _hoisted_2 = ["data-col-key", "draggable", "rowspan", "colspan", "title", "onClick"];
|
|
498
547
|
const _hoisted_3 = { class: "table-header-cell-wrapper" };
|
|
@@ -501,7 +550,7 @@ const _hoisted_5 = {
|
|
|
501
550
|
key: 2,
|
|
502
551
|
class: "table-header-sorter"
|
|
503
552
|
};
|
|
504
|
-
const _hoisted_6 = /* @__PURE__ */
|
|
553
|
+
const _hoisted_6 = /* @__PURE__ */ createElementVNode("svg", {
|
|
505
554
|
xmlns: "http://www.w3.org/2000/svg",
|
|
506
555
|
width: "16px",
|
|
507
556
|
height: "16px",
|
|
@@ -519,7 +568,7 @@ const _hoisted_6 = /* @__PURE__ */ _withScopeId(() => /* @__PURE__ */ createElem
|
|
|
519
568
|
points: "8 10 4.8 14 11.2 14"
|
|
520
569
|
})
|
|
521
570
|
])
|
|
522
|
-
], -1)
|
|
571
|
+
], -1);
|
|
523
572
|
const _hoisted_7 = [
|
|
524
573
|
_hoisted_6
|
|
525
574
|
];
|
|
@@ -564,7 +613,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
564
613
|
rowClassName: { type: Function, default: () => "" },
|
|
565
614
|
colResizable: { type: Boolean, default: false },
|
|
566
615
|
colMinWidth: { default: 10 },
|
|
567
|
-
bordered: { type: [Boolean, String], default: true }
|
|
616
|
+
bordered: { type: [Boolean, String], default: true },
|
|
617
|
+
autoResize: { type: Boolean, default: true }
|
|
568
618
|
},
|
|
569
619
|
emits: [
|
|
570
620
|
"sort-change",
|
|
@@ -608,15 +658,19 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
608
658
|
const store = {};
|
|
609
659
|
const cols = [...tableHeaderLast.value];
|
|
610
660
|
let left = 0;
|
|
661
|
+
let rightStartIndex = 0;
|
|
611
662
|
for (let i = 0; i < cols.length; i++) {
|
|
612
663
|
const item = cols[i];
|
|
613
664
|
if (item.fixed === "left") {
|
|
614
665
|
store[item.dataIndex] = left;
|
|
615
666
|
left += parseInt(item.width || Default_Col_Width);
|
|
616
667
|
}
|
|
668
|
+
if (!rightStartIndex && item.fixed === "right") {
|
|
669
|
+
rightStartIndex = i;
|
|
670
|
+
}
|
|
617
671
|
}
|
|
618
672
|
let right = 0;
|
|
619
|
-
for (let i = cols.length - 1; i >=
|
|
673
|
+
for (let i = cols.length - 1; i >= rightStartIndex; i--) {
|
|
620
674
|
const item = cols[i];
|
|
621
675
|
if (item.fixed === "right") {
|
|
622
676
|
store[item.dataIndex] = right;
|
|
@@ -649,6 +703,9 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
649
703
|
updateVirtualScrollX
|
|
650
704
|
} = useVirtualScroll({ tableContainer, props, dataSourceCopy, tableHeaderLast });
|
|
651
705
|
const { setHighlightDimCell, setHighlightDimRow } = useHighlight({ props, tableContainer, rowKeyGen });
|
|
706
|
+
if (props.autoResize) {
|
|
707
|
+
useAutoResize({ tableContainer, initVirtualScroll, scrollTo, props, debounceMs: 500 });
|
|
708
|
+
}
|
|
652
709
|
watch(
|
|
653
710
|
() => props.columns,
|
|
654
711
|
() => {
|
|
@@ -660,6 +717,10 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
660
717
|
watch(
|
|
661
718
|
() => props.dataSource,
|
|
662
719
|
(val) => {
|
|
720
|
+
if (!val) {
|
|
721
|
+
console.warn("invalid dataSource");
|
|
722
|
+
return;
|
|
723
|
+
}
|
|
663
724
|
let needInitVirtualScrollY = false;
|
|
664
725
|
if (dataSourceCopy.value.length !== val.length) {
|
|
665
726
|
needInitVirtualScrollY = true;
|
|
@@ -904,9 +965,13 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
904
965
|
return toRaw(dataSourceCopy.value);
|
|
905
966
|
}
|
|
906
967
|
__expose({
|
|
968
|
+
initVirtualScroll,
|
|
969
|
+
initVirtualScrollX,
|
|
970
|
+
initVirtualScrollY,
|
|
907
971
|
setCurrentRow,
|
|
908
972
|
setHighlightDimCell,
|
|
909
973
|
setHighlightDimRow,
|
|
974
|
+
sortCol,
|
|
910
975
|
setSorter,
|
|
911
976
|
resetSorter,
|
|
912
977
|
scrollTo,
|
|
@@ -972,7 +1037,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
972
1037
|
col.dataIndex === unref(sortCol) && unref(sortOrderIndex) !== 0 && "sorter-" + sortSwitchOrder[unref(sortOrderIndex)],
|
|
973
1038
|
_ctx.showHeaderOverflow ? "text-overflow" : "",
|
|
974
1039
|
col.headerClassName,
|
|
975
|
-
col.fixed ? "fixed-cell" : ""
|
|
1040
|
+
col.fixed ? "fixed-cell" : "",
|
|
1041
|
+
col.fixed ? "fixed-cell--" + col.fixed : ""
|
|
976
1042
|
]),
|
|
977
1043
|
onClick: (e) => {
|
|
978
1044
|
onColumnSort(col);
|
|
@@ -994,7 +1060,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
994
1060
|
column: col
|
|
995
1061
|
}, () => [
|
|
996
1062
|
createElementVNode("span", _hoisted_4, toDisplayString(col.title), 1)
|
|
997
|
-
]
|
|
1063
|
+
]),
|
|
998
1064
|
col.sorter ? (openBlock(), createElementBlock("span", _hoisted_5, _hoisted_7)) : createCommentVNode("", true),
|
|
999
1065
|
_ctx.colResizable && colIndex > 0 ? (openBlock(), createElementBlock("div", {
|
|
1000
1066
|
key: 3,
|
|
@@ -1055,7 +1121,12 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
1055
1121
|
return openBlock(), createElementBlock("td", {
|
|
1056
1122
|
key: col.dataIndex,
|
|
1057
1123
|
"data-index": col.dataIndex,
|
|
1058
|
-
class: normalizeClass([
|
|
1124
|
+
class: normalizeClass([
|
|
1125
|
+
col.className,
|
|
1126
|
+
_ctx.showOverflow ? "text-overflow" : "",
|
|
1127
|
+
col.fixed ? "fixed-cell" : "",
|
|
1128
|
+
col.fixed ? "fixed-cell--" + col.fixed : ""
|
|
1129
|
+
]),
|
|
1059
1130
|
style: normalizeStyle(getCellStyle(2, col)),
|
|
1060
1131
|
onClick: (e) => onCellClick(e, row, col)
|
|
1061
1132
|
}, [
|
|
@@ -1085,22 +1156,14 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
1085
1156
|
}, [
|
|
1086
1157
|
renderSlot(_ctx.$slots, "empty", {}, () => [
|
|
1087
1158
|
createTextVNode("暂无数据")
|
|
1088
|
-
]
|
|
1159
|
+
])
|
|
1089
1160
|
], 2)) : createCommentVNode("", true)
|
|
1090
1161
|
], 38);
|
|
1091
1162
|
};
|
|
1092
1163
|
}
|
|
1093
1164
|
});
|
|
1094
|
-
const _export_sfc = (sfc, props) => {
|
|
1095
|
-
const target = sfc.__vccOpts || sfc;
|
|
1096
|
-
for (const [key, val] of props) {
|
|
1097
|
-
target[key] = val;
|
|
1098
|
-
}
|
|
1099
|
-
return target;
|
|
1100
|
-
};
|
|
1101
|
-
const StkTable = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-0aa41491"]]);
|
|
1102
1165
|
export {
|
|
1103
|
-
StkTable,
|
|
1166
|
+
_sfc_main as StkTable,
|
|
1104
1167
|
insertToOrderedArray,
|
|
1105
1168
|
tableSort
|
|
1106
1169
|
};
|
package/lib/style.css
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
.stk-table
|
|
1
|
+
.stk-table {
|
|
2
2
|
--row-height: 28px;
|
|
3
3
|
--cell-padding-x: 8px;
|
|
4
4
|
--resize-handle-width: 4px;
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
/** 列宽调整指示器 */
|
|
29
29
|
/**虚拟滚动模式 */
|
|
30
30
|
}
|
|
31
|
-
.stk-table.dark
|
|
31
|
+
.stk-table.dark {
|
|
32
32
|
--th-bgc: #181c21;
|
|
33
33
|
--td-bgc: #181c21;
|
|
34
34
|
--border-color: #26292e;
|
|
@@ -43,45 +43,45 @@
|
|
|
43
43
|
--col-resize-indicator-color: #5d6064;
|
|
44
44
|
color: #d0d1d2;
|
|
45
45
|
}
|
|
46
|
-
.stk-table.headless
|
|
46
|
+
.stk-table.headless {
|
|
47
47
|
border-top: 1px solid var(--border-color);
|
|
48
48
|
}
|
|
49
|
-
.stk-table.is-col-resizing th
|
|
49
|
+
.stk-table.is-col-resizing th {
|
|
50
50
|
pointer-events: none;
|
|
51
51
|
}
|
|
52
|
-
.stk-table.border-h
|
|
52
|
+
.stk-table.border-h {
|
|
53
53
|
--bg-border-right: linear-gradient(transparent, transparent);
|
|
54
54
|
--bg-border-left: linear-gradient(transparent, transparent);
|
|
55
55
|
}
|
|
56
|
-
.stk-table.border-v
|
|
56
|
+
.stk-table.border-v {
|
|
57
57
|
--bg-border-bottom: linear-gradient(transparent, transparent);
|
|
58
58
|
}
|
|
59
|
-
.stk-table.border .stk-table-main th
|
|
60
|
-
.stk-table.border .stk-table-main td
|
|
59
|
+
.stk-table.border .stk-table-main th,
|
|
60
|
+
.stk-table.border .stk-table-main td {
|
|
61
61
|
background-image: var(--bg-border-right), var(--bg-border-bottom);
|
|
62
62
|
}
|
|
63
|
-
.stk-table.border .stk-table-main thead tr:first-child th
|
|
63
|
+
.stk-table.border .stk-table-main thead tr:first-child th {
|
|
64
64
|
background-image: var(--bg-border-top), var(--bg-border-right), var(--bg-border-bottom);
|
|
65
65
|
}
|
|
66
|
-
.stk-table.border .stk-table-main thead tr:first-child th
|
|
66
|
+
.stk-table.border .stk-table-main thead tr:first-child th:first-child {
|
|
67
67
|
background-image: var(--bg-border-top), var(--bg-border-right), var(--bg-border-bottom), var(--bg-border-left);
|
|
68
68
|
}
|
|
69
|
-
.stk-table.border .stk-table-main thead tr th
|
|
69
|
+
.stk-table.border .stk-table-main thead tr th:first-child {
|
|
70
70
|
background-image: var(--bg-border-right), var(--bg-border-bottom), var(--bg-border-left);
|
|
71
71
|
}
|
|
72
|
-
.stk-table.border .stk-table-main tbody td
|
|
72
|
+
.stk-table.border .stk-table-main tbody td:first-child {
|
|
73
73
|
background-image: var(--bg-border-right), var(--bg-border-bottom), var(--bg-border-left);
|
|
74
74
|
}
|
|
75
|
-
.stk-table.border.virtual-x .stk-table-main thead tr:first-child .virtual-x-left + th
|
|
75
|
+
.stk-table.border.virtual-x .stk-table-main thead tr:first-child .virtual-x-left + th {
|
|
76
76
|
background-image: var(--bg-border-top), var(--bg-border-right), var(--bg-border-bottom), var(--bg-border-left);
|
|
77
77
|
}
|
|
78
|
-
.stk-table.border.virtual-x .stk-table-main tr .virtual-x-left + th
|
|
78
|
+
.stk-table.border.virtual-x .stk-table-main tr .virtual-x-left + th {
|
|
79
79
|
background-image: var(--bg-border-right), var(--bg-border-bottom), var(--bg-border-left);
|
|
80
80
|
}
|
|
81
|
-
.stk-table.border-body-v .stk-table-main tbody
|
|
81
|
+
.stk-table.border-body-v .stk-table-main tbody {
|
|
82
82
|
--bg-border-bottom: linear-gradient(transparent, transparent);
|
|
83
83
|
}
|
|
84
|
-
.stk-table .column-resize-indicator
|
|
84
|
+
.stk-table .column-resize-indicator {
|
|
85
85
|
width: 0;
|
|
86
86
|
height: 100%;
|
|
87
87
|
border-left: 1px dashed var(--col-resize-indicator-color);
|
|
@@ -90,122 +90,131 @@
|
|
|
90
90
|
display: none;
|
|
91
91
|
pointer-events: none;
|
|
92
92
|
}
|
|
93
|
-
.stk-table .stk-table-main
|
|
93
|
+
.stk-table .stk-table-main {
|
|
94
94
|
border-spacing: 0;
|
|
95
95
|
border-collapse: separate;
|
|
96
|
+
width: fit-content;
|
|
97
|
+
min-width: 100%;
|
|
96
98
|
}
|
|
97
|
-
.stk-table .stk-table-main.fixed-mode
|
|
99
|
+
.stk-table .stk-table-main.fixed-mode {
|
|
98
100
|
table-layout: fixed;
|
|
99
101
|
}
|
|
100
|
-
.stk-table .stk-table-main th
|
|
101
|
-
.stk-table .stk-table-main td
|
|
102
|
+
.stk-table .stk-table-main th,
|
|
103
|
+
.stk-table .stk-table-main td {
|
|
102
104
|
z-index: 1;
|
|
103
105
|
height: var(--row-height);
|
|
104
106
|
font-size: 14px;
|
|
105
107
|
box-sizing: border-box;
|
|
106
108
|
padding: 0 var(--cell-padding-x);
|
|
107
109
|
}
|
|
108
|
-
.stk-table .stk-table-main thead tr:first-child th
|
|
110
|
+
.stk-table .stk-table-main thead tr:first-child th {
|
|
109
111
|
position: sticky;
|
|
110
112
|
top: 0;
|
|
111
113
|
}
|
|
112
|
-
.stk-table .stk-table-main thead tr th
|
|
114
|
+
.stk-table .stk-table-main thead tr th {
|
|
113
115
|
background-color: var(--th-bgc);
|
|
114
116
|
}
|
|
115
|
-
.stk-table .stk-table-main thead tr th.sortable
|
|
117
|
+
.stk-table .stk-table-main thead tr th.sortable {
|
|
116
118
|
cursor: pointer;
|
|
117
119
|
}
|
|
118
|
-
.stk-table .stk-table-main thead tr th.text-overflow .table-header-cell-wrapper
|
|
120
|
+
.stk-table .stk-table-main thead tr th.text-overflow .table-header-cell-wrapper {
|
|
119
121
|
white-space: nowrap;
|
|
120
122
|
overflow: hidden;
|
|
121
123
|
}
|
|
122
|
-
.stk-table .stk-table-main thead tr th.text-overflow .table-header-cell-wrapper .table-header-title
|
|
124
|
+
.stk-table .stk-table-main thead tr th.text-overflow .table-header-cell-wrapper .table-header-title {
|
|
123
125
|
text-overflow: ellipsis;
|
|
124
126
|
overflow: hidden;
|
|
125
127
|
}
|
|
126
|
-
.stk-table .stk-table-main thead tr th:not(.sorter-desc):not(.sorter-asc):hover .table-header-cell-wrapper .table-header-sorter #arrow-up
|
|
128
|
+
.stk-table .stk-table-main thead tr th:not(.sorter-desc):not(.sorter-asc):hover .table-header-cell-wrapper .table-header-sorter #arrow-up {
|
|
127
129
|
fill: var(--sort-arrow-hover-color);
|
|
128
130
|
}
|
|
129
|
-
.stk-table .stk-table-main thead tr th:not(.sorter-desc):not(.sorter-asc):hover .table-header-cell-wrapper .table-header-sorter #arrow-down
|
|
131
|
+
.stk-table .stk-table-main thead tr th:not(.sorter-desc):not(.sorter-asc):hover .table-header-cell-wrapper .table-header-sorter #arrow-down {
|
|
130
132
|
fill: var(--sort-arrow-hover-color);
|
|
131
133
|
}
|
|
132
|
-
.stk-table .stk-table-main thead tr th.sorter-desc .table-header-cell-wrapper .table-header-sorter
|
|
134
|
+
.stk-table .stk-table-main thead tr th.sorter-desc .table-header-cell-wrapper .table-header-sorter {
|
|
135
|
+
display: initial;
|
|
136
|
+
}
|
|
137
|
+
.stk-table .stk-table-main thead tr th.sorter-desc .table-header-cell-wrapper .table-header-sorter #arrow-up {
|
|
133
138
|
fill: var(--sort-arrow-active-sub-color);
|
|
134
139
|
}
|
|
135
|
-
.stk-table .stk-table-main thead tr th.sorter-desc .table-header-cell-wrapper .table-header-sorter #arrow-down
|
|
140
|
+
.stk-table .stk-table-main thead tr th.sorter-desc .table-header-cell-wrapper .table-header-sorter #arrow-down {
|
|
136
141
|
fill: var(--sort-arrow-active-color);
|
|
137
142
|
}
|
|
138
|
-
.stk-table .stk-table-main thead tr th.sorter-asc .table-header-cell-wrapper .table-header-sorter
|
|
143
|
+
.stk-table .stk-table-main thead tr th.sorter-asc .table-header-cell-wrapper .table-header-sorter {
|
|
144
|
+
display: initial;
|
|
145
|
+
}
|
|
146
|
+
.stk-table .stk-table-main thead tr th.sorter-asc .table-header-cell-wrapper .table-header-sorter #arrow-up {
|
|
139
147
|
fill: var(--sort-arrow-active-color);
|
|
140
148
|
}
|
|
141
|
-
.stk-table .stk-table-main thead tr th.sorter-asc .table-header-cell-wrapper .table-header-sorter #arrow-down
|
|
149
|
+
.stk-table .stk-table-main thead tr th.sorter-asc .table-header-cell-wrapper .table-header-sorter #arrow-down {
|
|
142
150
|
fill: var(--sort-arrow-active-sub-color);
|
|
143
151
|
}
|
|
144
|
-
.stk-table .stk-table-main thead tr th .table-header-cell-wrapper
|
|
152
|
+
.stk-table .stk-table-main thead tr th .table-header-cell-wrapper {
|
|
145
153
|
max-width: 100%;
|
|
146
154
|
display: inline-flex;
|
|
147
155
|
align-items: center;
|
|
148
156
|
}
|
|
149
|
-
.stk-table .stk-table-main thead tr th .table-header-cell-wrapper .table-header-title
|
|
157
|
+
.stk-table .stk-table-main thead tr th .table-header-cell-wrapper .table-header-title {
|
|
150
158
|
overflow: hidden;
|
|
151
159
|
align-self: flex-start;
|
|
152
160
|
}
|
|
153
|
-
.stk-table .stk-table-main thead tr th .table-header-cell-wrapper .table-header-sorter
|
|
161
|
+
.stk-table .stk-table-main thead tr th .table-header-cell-wrapper .table-header-sorter {
|
|
154
162
|
flex-shrink: 0;
|
|
155
163
|
margin-left: 4px;
|
|
156
164
|
width: 16px;
|
|
157
165
|
height: 16px;
|
|
166
|
+
display: none;
|
|
158
167
|
}
|
|
159
|
-
.stk-table .stk-table-main thead tr th .table-header-cell-wrapper .table-header-sorter #arrow-up
|
|
160
|
-
.stk-table .stk-table-main thead tr th .table-header-cell-wrapper .table-header-sorter #arrow-down
|
|
168
|
+
.stk-table .stk-table-main thead tr th .table-header-cell-wrapper .table-header-sorter #arrow-up,
|
|
169
|
+
.stk-table .stk-table-main thead tr th .table-header-cell-wrapper .table-header-sorter #arrow-down {
|
|
161
170
|
fill: var(--sort-arrow-color);
|
|
162
171
|
}
|
|
163
|
-
.stk-table .stk-table-main thead tr th .table-header-cell-wrapper .table-header-resizer
|
|
172
|
+
.stk-table .stk-table-main thead tr th .table-header-cell-wrapper .table-header-resizer {
|
|
164
173
|
position: absolute;
|
|
165
174
|
top: 0;
|
|
166
175
|
bottom: 0;
|
|
167
176
|
cursor: col-resize;
|
|
168
177
|
width: var(--resize-handle-width);
|
|
169
178
|
}
|
|
170
|
-
.stk-table .stk-table-main thead tr th .table-header-cell-wrapper .table-header-resizer.left
|
|
179
|
+
.stk-table .stk-table-main thead tr th .table-header-cell-wrapper .table-header-resizer.left {
|
|
171
180
|
left: 0;
|
|
172
181
|
}
|
|
173
|
-
.stk-table .stk-table-main thead tr th .table-header-cell-wrapper .table-header-resizer.right
|
|
182
|
+
.stk-table .stk-table-main thead tr th .table-header-cell-wrapper .table-header-resizer.right {
|
|
174
183
|
right: 0;
|
|
175
184
|
}
|
|
176
|
-
.stk-table .stk-table-main tbody
|
|
185
|
+
.stk-table .stk-table-main tbody {
|
|
177
186
|
/**高亮渐暗 */
|
|
178
187
|
}
|
|
179
|
-
@keyframes dim
|
|
188
|
+
@keyframes dim {
|
|
180
189
|
from {
|
|
181
190
|
background-color: var(--highlight-color);
|
|
182
191
|
}
|
|
183
192
|
}
|
|
184
|
-
.stk-table .stk-table-main tbody tr
|
|
193
|
+
.stk-table .stk-table-main tbody tr {
|
|
185
194
|
background-color: var(--td-bgc);
|
|
186
195
|
}
|
|
187
|
-
.stk-table .stk-table-main tbody tr.highlight-row
|
|
188
|
-
animation: dim
|
|
196
|
+
.stk-table .stk-table-main tbody tr.highlight-row {
|
|
197
|
+
animation: dim 2s linear;
|
|
189
198
|
}
|
|
190
|
-
.stk-table .stk-table-main tbody tr.hover
|
|
191
|
-
.stk-table .stk-table-main tbody tr
|
|
199
|
+
.stk-table .stk-table-main tbody tr.hover,
|
|
200
|
+
.stk-table .stk-table-main tbody tr:hover {
|
|
192
201
|
background-color: var(--tr-hover-bgc);
|
|
193
202
|
}
|
|
194
|
-
.stk-table .stk-table-main tbody tr.active
|
|
203
|
+
.stk-table .stk-table-main tbody tr.active {
|
|
195
204
|
background-color: var(--tr-active-bgc);
|
|
196
205
|
}
|
|
197
|
-
.stk-table .stk-table-main tbody tr td.fixed-cell
|
|
206
|
+
.stk-table .stk-table-main tbody tr td.fixed-cell {
|
|
198
207
|
background-color: inherit;
|
|
199
208
|
}
|
|
200
|
-
.stk-table .stk-table-main tbody tr td.highlight-cell
|
|
201
|
-
animation: dim
|
|
209
|
+
.stk-table .stk-table-main tbody tr td.highlight-cell {
|
|
210
|
+
animation: dim 2s linear;
|
|
202
211
|
}
|
|
203
|
-
.stk-table .stk-table-main tbody tr td.text-overflow .table-cell-wrapper
|
|
212
|
+
.stk-table .stk-table-main tbody tr td.text-overflow .table-cell-wrapper {
|
|
204
213
|
white-space: nowrap;
|
|
205
214
|
overflow: hidden;
|
|
206
215
|
text-overflow: ellipsis;
|
|
207
216
|
}
|
|
208
|
-
.stk-table .stk-table-no-data
|
|
217
|
+
.stk-table .stk-table-no-data {
|
|
209
218
|
background-color: var(--table-bgc);
|
|
210
219
|
line-height: var(--row-height);
|
|
211
220
|
text-align: center;
|
|
@@ -220,27 +229,27 @@ from {
|
|
|
220
229
|
align-items: center;
|
|
221
230
|
justify-content: center;
|
|
222
231
|
}
|
|
223
|
-
.stk-table .stk-table-no-data.no-data-full
|
|
232
|
+
.stk-table .stk-table-no-data.no-data-full {
|
|
224
233
|
flex: 1;
|
|
225
234
|
}
|
|
226
|
-
.stk-table.virtual .stk-table-main thead tr th .table-header-cell-wrapper
|
|
235
|
+
.stk-table.virtual .stk-table-main thead tr th .table-header-cell-wrapper {
|
|
227
236
|
overflow: hidden;
|
|
228
237
|
max-height: var(--row-height);
|
|
229
238
|
}
|
|
230
|
-
.stk-table.virtual .stk-table-main tbody
|
|
239
|
+
.stk-table.virtual .stk-table-main tbody {
|
|
231
240
|
position: relative;
|
|
232
241
|
}
|
|
233
|
-
.stk-table.virtual .stk-table-main tbody tr.padding-top-tr td
|
|
242
|
+
.stk-table.virtual .stk-table-main tbody tr.padding-top-tr td {
|
|
234
243
|
height: 0;
|
|
235
244
|
}
|
|
236
|
-
.stk-table.virtual .stk-table-main tbody tr td
|
|
245
|
+
.stk-table.virtual .stk-table-main tbody tr td {
|
|
237
246
|
height: var(--row-height);
|
|
238
247
|
line-height: 1;
|
|
239
248
|
}
|
|
240
|
-
.stk-table.virtual .stk-table-main tbody tr td .table-cell-wrapper
|
|
249
|
+
.stk-table.virtual .stk-table-main tbody tr td .table-cell-wrapper {
|
|
241
250
|
max-height: var(--row-height);
|
|
242
251
|
overflow: hidden;
|
|
243
252
|
}
|
|
244
|
-
.stk-table.virtual-x .stk-table-main .virtual-x-left
|
|
253
|
+
.stk-table.virtual-x .stk-table-main .virtual-x-left {
|
|
245
254
|
padding: 0;
|
|
246
255
|
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export default class DragResize {
|
|
2
|
+
/**
|
|
3
|
+
*
|
|
4
|
+
* @param {HTMLElement} el
|
|
5
|
+
*/
|
|
6
|
+
constructor(el: HTMLElement);
|
|
7
|
+
buttonSize: {
|
|
8
|
+
width: number;
|
|
9
|
+
height: number;
|
|
10
|
+
};
|
|
11
|
+
/** @type {ResizeObserver} */
|
|
12
|
+
resizeObserver: ResizeObserver;
|
|
13
|
+
/** @type {DOMRect} */
|
|
14
|
+
targetDOMRect: DOMRect;
|
|
15
|
+
/** @type {{left:number,top:number}} */
|
|
16
|
+
resizeButtonStyle: {
|
|
17
|
+
left: number;
|
|
18
|
+
top: number;
|
|
19
|
+
};
|
|
20
|
+
el: HTMLElement;
|
|
21
|
+
initData(): void;
|
|
22
|
+
createResizeButton(): void;
|
|
23
|
+
resizeButton: HTMLElement | undefined;
|
|
24
|
+
/** 监听元素大小改变 */
|
|
25
|
+
onResize(): void;
|
|
26
|
+
addButtonHoverStyle(): void;
|
|
27
|
+
addEvent(): void;
|
|
28
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* createElement function
|
|
3
|
+
* h(tag[, text[,children]])
|
|
4
|
+
* h(tag[, attrs[,children]])
|
|
5
|
+
* h(tag[, children])
|
|
6
|
+
* @param {String} tag 标签名称,支持tag#id.class emmet写法,暂支持id ,class
|
|
7
|
+
* @param {Object | String | Number | Array<HTMLElement>} attrs 传Object为属性,传String为textContent,传数组为children
|
|
8
|
+
* @param {Array<HTMLElement>} children
|
|
9
|
+
*/
|
|
10
|
+
export default function h(tag: string, attrs: Object | string | number | Array<HTMLElement>, children: Array<HTMLElement>): HTMLElement;
|
package/package.json
CHANGED
|
@@ -1,60 +1,60 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "stk-table-vue",
|
|
3
|
-
"version": "0.0.1-beta.
|
|
4
|
-
"description": "simple realtime virtual table for vue3",
|
|
5
|
-
"main": "./lib/stk-table-vue.js",
|
|
6
|
-
"types": "./lib/StkTable/index.d.ts",
|
|
7
|
-
"packageManager": "pnpm@8.11.0",
|
|
8
|
-
"directories": {
|
|
9
|
-
"test": "test"
|
|
10
|
-
},
|
|
11
|
-
"type": "module",
|
|
12
|
-
"scripts": {
|
|
13
|
-
"dev": "vite",
|
|
14
|
-
"build": "vite build",
|
|
15
|
-
"test": "vitest"
|
|
16
|
-
},
|
|
17
|
-
"keywords": [
|
|
18
|
-
"virtual table",
|
|
19
|
-
"vue",
|
|
20
|
-
"highlight",
|
|
21
|
-
"sticky"
|
|
22
|
-
],
|
|
23
|
-
"files": [
|
|
24
|
-
"lib",
|
|
25
|
-
"src"
|
|
26
|
-
],
|
|
27
|
-
"author": "japlus",
|
|
28
|
-
"repository": {
|
|
29
|
-
"type": "git",
|
|
30
|
-
"url": "https://gitee.com/japlus/stk-table-vue"
|
|
31
|
-
},
|
|
32
|
-
"license": "MIT",
|
|
33
|
-
"devDependencies": {
|
|
34
|
-
"@types/d3-interpolate": "^3.0.4",
|
|
35
|
-
"@typescript-eslint/eslint-plugin": "^6.14.0",
|
|
36
|
-
"@typescript-eslint/parser": "^6.14.0",
|
|
37
|
-
"@vitejs/plugin-vue": "^4.5.0",
|
|
38
|
-
"@vitejs/plugin-vue-jsx": "^3.1.0",
|
|
39
|
-
"@vue/test-utils": "2.4.0-alpha.2",
|
|
40
|
-
"eslint": "^8.55.0",
|
|
41
|
-
"eslint-config-prettier": "^9.1.0",
|
|
42
|
-
"eslint-plugin-html": "^7.1.0",
|
|
43
|
-
"eslint-plugin-prettier": "^5.0.1",
|
|
44
|
-
"eslint-plugin-vue": "^9.19.2",
|
|
45
|
-
"happy-dom": "^12.10.3",
|
|
46
|
-
"less": "^4.2.0",
|
|
47
|
-
"prettier": "^3.1.1",
|
|
48
|
-
"pug": "^3.0.2",
|
|
49
|
-
"typescript": "^5.3.3",
|
|
50
|
-
"vite": "^5.0.6",
|
|
51
|
-
"vite-plugin-dts": "^3.6.4",
|
|
52
|
-
"vitest": "^1.1.0",
|
|
53
|
-
"vue": "^3.3.9",
|
|
54
|
-
"vue-eslint-parser": "^9.3.2",
|
|
55
|
-
"vue-loader": "^17.2.2"
|
|
56
|
-
},
|
|
57
|
-
"dependencies": {
|
|
58
|
-
"d3-interpolate": "^3.0.1"
|
|
59
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "stk-table-vue",
|
|
3
|
+
"version": "0.0.1-beta.6",
|
|
4
|
+
"description": "simple realtime virtual table for vue3",
|
|
5
|
+
"main": "./lib/stk-table-vue.js",
|
|
6
|
+
"types": "./lib/StkTable/index.d.ts",
|
|
7
|
+
"packageManager": "pnpm@8.11.0",
|
|
8
|
+
"directories": {
|
|
9
|
+
"test": "test"
|
|
10
|
+
},
|
|
11
|
+
"type": "module",
|
|
12
|
+
"scripts": {
|
|
13
|
+
"dev": "vite",
|
|
14
|
+
"build": "vite build",
|
|
15
|
+
"test": "vitest"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"virtual table",
|
|
19
|
+
"vue",
|
|
20
|
+
"highlight",
|
|
21
|
+
"sticky"
|
|
22
|
+
],
|
|
23
|
+
"files": [
|
|
24
|
+
"lib",
|
|
25
|
+
"src"
|
|
26
|
+
],
|
|
27
|
+
"author": "japlus",
|
|
28
|
+
"repository": {
|
|
29
|
+
"type": "git",
|
|
30
|
+
"url": "https://gitee.com/japlus/stk-table-vue"
|
|
31
|
+
},
|
|
32
|
+
"license": "MIT",
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@types/d3-interpolate": "^3.0.4",
|
|
35
|
+
"@typescript-eslint/eslint-plugin": "^6.14.0",
|
|
36
|
+
"@typescript-eslint/parser": "^6.14.0",
|
|
37
|
+
"@vitejs/plugin-vue": "^4.5.0",
|
|
38
|
+
"@vitejs/plugin-vue-jsx": "^3.1.0",
|
|
39
|
+
"@vue/test-utils": "2.4.0-alpha.2",
|
|
40
|
+
"eslint": "^8.55.0",
|
|
41
|
+
"eslint-config-prettier": "^9.1.0",
|
|
42
|
+
"eslint-plugin-html": "^7.1.0",
|
|
43
|
+
"eslint-plugin-prettier": "^5.0.1",
|
|
44
|
+
"eslint-plugin-vue": "^9.19.2",
|
|
45
|
+
"happy-dom": "^12.10.3",
|
|
46
|
+
"less": "^4.2.0",
|
|
47
|
+
"prettier": "^3.1.1",
|
|
48
|
+
"pug": "^3.0.2",
|
|
49
|
+
"typescript": "^5.3.3",
|
|
50
|
+
"vite": "^5.0.6",
|
|
51
|
+
"vite-plugin-dts": "^3.6.4",
|
|
52
|
+
"vitest": "^1.1.0",
|
|
53
|
+
"vue": "^3.3.9",
|
|
54
|
+
"vue-eslint-parser": "^9.3.2",
|
|
55
|
+
"vue-loader": "^17.2.2"
|
|
56
|
+
},
|
|
57
|
+
"dependencies": {
|
|
58
|
+
"d3-interpolate": "^3.0.1"
|
|
59
|
+
}
|
|
60
60
|
}
|
|
@@ -66,6 +66,7 @@
|
|
|
66
66
|
showHeaderOverflow ? 'text-overflow' : '',
|
|
67
67
|
col.headerClassName,
|
|
68
68
|
col.fixed ? 'fixed-cell' : '',
|
|
69
|
+
col.fixed ? 'fixed-cell--' + col.fixed : '',
|
|
69
70
|
]"
|
|
70
71
|
@click="
|
|
71
72
|
e => {
|
|
@@ -161,7 +162,12 @@
|
|
|
161
162
|
v-for="col in virtualX_columnPart"
|
|
162
163
|
:key="col.dataIndex"
|
|
163
164
|
:data-index="col.dataIndex"
|
|
164
|
-
:class="[
|
|
165
|
+
:class="[
|
|
166
|
+
col.className,
|
|
167
|
+
showOverflow ? 'text-overflow' : '',
|
|
168
|
+
col.fixed ? 'fixed-cell' : '',
|
|
169
|
+
col.fixed ? 'fixed-cell--' + col.fixed : '',
|
|
170
|
+
]"
|
|
165
171
|
:style="getCellStyle(2, col)"
|
|
166
172
|
@click="e => onCellClick(e, row, col)"
|
|
167
173
|
>
|
|
@@ -189,9 +195,10 @@
|
|
|
189
195
|
* [] 计算的高亮颜色,挂在数据源上对象上,若多个表格使用同一个数据源对象会有问题。需要深拷贝。(解决方案:获取组件uid)
|
|
190
196
|
* [] highlight-row 颜色不能恢复到active的颜色
|
|
191
197
|
*/
|
|
192
|
-
import { Order, SortOption, StkProps, StkTableColumn } from '@/StkTable/types/index';
|
|
193
198
|
import { CSSProperties, computed, onMounted, ref, shallowRef, toRaw, watch } from 'vue';
|
|
194
199
|
import { Default_Col_Width, Is_Legacy_Mode } from './const';
|
|
200
|
+
import { Order, SortOption, StkProps, StkTableColumn } from './types/index';
|
|
201
|
+
import { useAutoResize } from './useAutoResize';
|
|
195
202
|
import { useColResize } from './useColResize';
|
|
196
203
|
import { useHighlight } from './useHighlight';
|
|
197
204
|
import { useThDrag } from './useThDrag';
|
|
@@ -223,6 +230,7 @@ const props = withDefaults(defineProps<StkProps>(), {
|
|
|
223
230
|
colResizable: false,
|
|
224
231
|
colMinWidth: 10,
|
|
225
232
|
bordered: true,
|
|
233
|
+
autoResize: true,
|
|
226
234
|
});
|
|
227
235
|
|
|
228
236
|
const emit = defineEmits([
|
|
@@ -283,15 +291,20 @@ const fixedColumnsPositionStore = computed(() => {
|
|
|
283
291
|
const store: Record<string, number> = {};
|
|
284
292
|
const cols = [...tableHeaderLast.value];
|
|
285
293
|
let left = 0;
|
|
294
|
+
/**遍历右侧fixed时,因为left已经遍历过一次了。所以,可以拿到right遍历边界 */
|
|
295
|
+
let rightStartIndex = 0;
|
|
286
296
|
for (let i = 0; i < cols.length; i++) {
|
|
287
297
|
const item = cols[i];
|
|
288
298
|
if (item.fixed === 'left') {
|
|
289
299
|
store[item.dataIndex] = left;
|
|
290
300
|
left += parseInt(item.width || Default_Col_Width);
|
|
291
301
|
}
|
|
302
|
+
if (!rightStartIndex && item.fixed === 'right') {
|
|
303
|
+
rightStartIndex = i;
|
|
304
|
+
}
|
|
292
305
|
}
|
|
293
306
|
let right = 0;
|
|
294
|
-
for (let i = cols.length - 1; i >=
|
|
307
|
+
for (let i = cols.length - 1; i >= rightStartIndex; i--) {
|
|
295
308
|
const item = cols[i];
|
|
296
309
|
if (item.fixed === 'right') {
|
|
297
310
|
store[item.dataIndex] = right;
|
|
@@ -333,6 +346,10 @@ const {
|
|
|
333
346
|
*/
|
|
334
347
|
const { setHighlightDimCell, setHighlightDimRow } = useHighlight({ props, tableContainer, rowKeyGen });
|
|
335
348
|
|
|
349
|
+
if (props.autoResize) {
|
|
350
|
+
useAutoResize({ tableContainer, initVirtualScroll, scrollTo, props, debounceMs: 500 });
|
|
351
|
+
}
|
|
352
|
+
|
|
336
353
|
watch(
|
|
337
354
|
() => props.columns,
|
|
338
355
|
() => {
|
|
@@ -346,6 +363,10 @@ dealColumns();
|
|
|
346
363
|
watch(
|
|
347
364
|
() => props.dataSource,
|
|
348
365
|
val => {
|
|
366
|
+
if (!val) {
|
|
367
|
+
console.warn('invalid dataSource');
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
349
370
|
// dealColumns(val);
|
|
350
371
|
let needInitVirtualScrollY = false;
|
|
351
372
|
if (dataSourceCopy.value.length !== val.length) {
|
|
@@ -694,9 +715,13 @@ function getTableData() {
|
|
|
694
715
|
}
|
|
695
716
|
|
|
696
717
|
defineExpose({
|
|
718
|
+
initVirtualScroll,
|
|
719
|
+
initVirtualScrollX,
|
|
720
|
+
initVirtualScrollY,
|
|
697
721
|
setCurrentRow,
|
|
698
722
|
setHighlightDimCell,
|
|
699
723
|
setHighlightDimRow,
|
|
724
|
+
sortCol,
|
|
700
725
|
setSorter,
|
|
701
726
|
resetSorter,
|
|
702
727
|
scrollTo,
|
|
@@ -704,7 +729,7 @@ defineExpose({
|
|
|
704
729
|
});
|
|
705
730
|
</script>
|
|
706
731
|
|
|
707
|
-
<style lang="less"
|
|
732
|
+
<style lang="less">
|
|
708
733
|
.stk-table {
|
|
709
734
|
// contain: strict;
|
|
710
735
|
--row-height: 28px;
|
|
@@ -846,6 +871,8 @@ defineExpose({
|
|
|
846
871
|
.stk-table-main {
|
|
847
872
|
border-spacing: 0;
|
|
848
873
|
border-collapse: separate;
|
|
874
|
+
width: fit-content; // 用于兼容低版本,低版本width超过100%的时候还是100%,导致sticky错误。
|
|
875
|
+
min-width: 100%; // 用于兼容低版本chrome。低版本min-width 是min-content;
|
|
849
876
|
&.fixed-mode {
|
|
850
877
|
table-layout: fixed;
|
|
851
878
|
}
|
|
@@ -896,7 +923,7 @@ defineExpose({
|
|
|
896
923
|
}
|
|
897
924
|
|
|
898
925
|
&.sorter-desc .table-header-cell-wrapper .table-header-sorter {
|
|
899
|
-
|
|
926
|
+
display: initial;
|
|
900
927
|
#arrow-up {
|
|
901
928
|
fill: var(--sort-arrow-active-sub-color);
|
|
902
929
|
}
|
|
@@ -907,7 +934,7 @@ defineExpose({
|
|
|
907
934
|
}
|
|
908
935
|
|
|
909
936
|
&.sorter-asc .table-header-cell-wrapper .table-header-sorter {
|
|
910
|
-
|
|
937
|
+
display: initial;
|
|
911
938
|
#arrow-up {
|
|
912
939
|
fill: var(--sort-arrow-active-color);
|
|
913
940
|
}
|
|
@@ -932,8 +959,7 @@ defineExpose({
|
|
|
932
959
|
margin-left: 4px;
|
|
933
960
|
width: 16px;
|
|
934
961
|
height: 16px;
|
|
935
|
-
|
|
936
|
-
// display:none;
|
|
962
|
+
display: none;
|
|
937
963
|
#arrow-up,
|
|
938
964
|
#arrow-down {
|
|
939
965
|
fill: var(--sort-arrow-color);
|
package/src/StkTable/index.ts
CHANGED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { Ref, onBeforeUnmount, onMounted, watch } from 'vue';
|
|
2
|
+
|
|
3
|
+
type Options = {
|
|
4
|
+
tableContainer: Ref<HTMLElement | undefined>;
|
|
5
|
+
initVirtualScroll: () => void;
|
|
6
|
+
scrollTo: () => void;
|
|
7
|
+
props: any;
|
|
8
|
+
/** 防抖延时 */
|
|
9
|
+
debounceMs: number;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* 窗口变化自动重置虚拟滚动
|
|
13
|
+
* @param param0
|
|
14
|
+
*/
|
|
15
|
+
export function useAutoResize({ tableContainer, initVirtualScroll, scrollTo, props, debounceMs }: Options) {
|
|
16
|
+
let resizeObserver: ResizeObserver | null = null;
|
|
17
|
+
|
|
18
|
+
onMounted(() => {
|
|
19
|
+
initResizeObserver();
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
onBeforeUnmount(() => {
|
|
23
|
+
removeResizeObserver();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
function initResizeObserver() {
|
|
27
|
+
if (window.ResizeObserver) {
|
|
28
|
+
if (!tableContainer.value) {
|
|
29
|
+
const watchDom = watch(
|
|
30
|
+
() => tableContainer,
|
|
31
|
+
() => {
|
|
32
|
+
initResizeObserver();
|
|
33
|
+
watchDom();
|
|
34
|
+
},
|
|
35
|
+
);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
resizeObserver = new ResizeObserver(resizeCallback);
|
|
39
|
+
resizeObserver.observe(tableContainer.value);
|
|
40
|
+
} else {
|
|
41
|
+
window.addEventListener('resize', resizeCallback);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function removeResizeObserver() {
|
|
46
|
+
if (resizeObserver) {
|
|
47
|
+
resizeObserver.disconnect();
|
|
48
|
+
resizeObserver = null;
|
|
49
|
+
} else {
|
|
50
|
+
window.removeEventListener('resize', resizeCallback);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
let debounceTime = 0;
|
|
55
|
+
function resizeCallback() {
|
|
56
|
+
if (debounceTime) {
|
|
57
|
+
window.clearTimeout(debounceTime);
|
|
58
|
+
}
|
|
59
|
+
debounceTime = window.setTimeout(() => {
|
|
60
|
+
if (props.autoResize) {
|
|
61
|
+
scrollTo();
|
|
62
|
+
initVirtualScroll();
|
|
63
|
+
}
|
|
64
|
+
debounceTime = 0;
|
|
65
|
+
}, debounceMs);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -91,29 +91,18 @@ export function useVirtualScroll({ tableContainer, props, dataSourceCopy, tableH
|
|
|
91
91
|
* @param {number} [height] 虚拟滚动的高度
|
|
92
92
|
*/
|
|
93
93
|
function initVirtualScrollY(height?: number) {
|
|
94
|
-
if (virtual_on.value)
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
// const tableAllHeight = dataSourceCopy.value.length * rowHeight;
|
|
99
|
-
// const overflowHeight = tableAllHeight - containerHeight;
|
|
100
|
-
// if (overflowHeight < offsetTop && overflowHeight > 0) {
|
|
101
|
-
// virtualScroll.value.offsetTop = overflowHeight;
|
|
102
|
-
// virtualScroll.value.startIndex = Math.ceil(overflowHeight / rowHeight);
|
|
103
|
-
// } else if (overflowHeight <= 0) {
|
|
104
|
-
// virtualScroll.value.offsetTop = 0;
|
|
105
|
-
// virtualScroll.value.startIndex = 0;
|
|
106
|
-
// }
|
|
107
|
-
}
|
|
94
|
+
if (!virtual_on.value) return;
|
|
95
|
+
// FIXME: 可能多次获取offsetHeight 会导致浏览器频繁重排
|
|
96
|
+
virtualScroll.value.containerHeight = typeof height === 'number' ? height : tableContainer.value?.offsetHeight || Default_Table_Height;
|
|
97
|
+
updateVirtualScrollY(tableContainer.value?.scrollTop);
|
|
108
98
|
}
|
|
109
99
|
|
|
110
100
|
function initVirtualScrollX() {
|
|
111
|
-
if (props.virtualX)
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
}
|
|
101
|
+
if (!props.virtualX) return;
|
|
102
|
+
const { offsetWidth, scrollLeft } = tableContainer.value || {};
|
|
103
|
+
// scrollTo(null, 0);
|
|
104
|
+
virtualScrollX.value.containerWidth = offsetWidth || Default_Table_Width;
|
|
105
|
+
updateVirtualScrollX(scrollLeft);
|
|
117
106
|
}
|
|
118
107
|
|
|
119
108
|
/** 通过滚动条位置,计算虚拟滚动的参数 */
|
package/src/StkTable/utils.ts
CHANGED
|
@@ -72,6 +72,7 @@ function strCompare(a: string, b: string, type: 'number' | 'string'): number {
|
|
|
72
72
|
* @param dataSource 排序的数组
|
|
73
73
|
*/
|
|
74
74
|
export function tableSort(sortOption: SortOption, order: Order, dataSource: any[]): any[] {
|
|
75
|
+
if (!dataSource?.length) return dataSource || [];
|
|
75
76
|
let targetDataSource = [...dataSource];
|
|
76
77
|
if (typeof sortOption.sorter === 'function') {
|
|
77
78
|
const customSorterData = sortOption.sorter(targetDataSource, { order, column: sortOption });
|