stk-table-vue 0.6.4 → 0.6.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 +11 -3
- package/lib/src/StkTable/StkTable.vue.d.ts +12 -7
- package/lib/src/StkTable/index.d.ts +1 -1
- package/lib/src/StkTable/types/index.d.ts +4 -0
- package/lib/src/StkTable/useColResize.d.ts +1 -0
- package/lib/src/StkTable/useFixedCol.d.ts +2 -2
- package/lib/src/StkTable/utils/index.d.ts +10 -2
- package/lib/stk-table-vue.js +97 -72
- package/lib/style.css +14 -12
- package/package.json +9 -5
- package/src/StkTable/StkTable.vue +15 -8
- package/src/StkTable/index.ts +1 -1
- package/src/StkTable/style.less +18 -13
- package/src/StkTable/types/index.ts +5 -0
- package/src/StkTable/useColResize.ts +11 -2
- package/src/StkTable/useFixedCol.ts +46 -40
- package/src/StkTable/useHighlight.ts +3 -3
- package/src/StkTable/useThDrag.ts +2 -2
- package/src/StkTable/useVirtualScroll.ts +44 -18
- package/src/StkTable/utils/index.ts +28 -16
package/README.md
CHANGED
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
# StkTable (Sticky Table)
|
|
2
|
+

|
|
3
|
+

|
|
4
|
+

|
|
5
|
+

|
|
2
6
|
|
|
3
7
|
Vue3 简易虚拟滚动表格。用于实时数据展示,新数据行高亮渐暗动效。
|
|
4
8
|
|
|
5
9
|
Vue2.7支持引入源码(**ts**)使用。
|
|
6
10
|
|
|
7
|
-
|
|
11
|
+
[Stk Table Vue 文档](https://ja-plus.github.io/stk-table-vue/)
|
|
12
|
+
|
|
13
|
+
## License
|
|
14
|
+
MIT
|
|
15
|
+
repo(求 star🌟):
|
|
8
16
|
- [Github](https://github.com/ja-plus/stk-table-vue)
|
|
9
17
|
- [Gitee](https://gitee.com/japlus/stk-table-vue) 🇨🇳
|
|
10
18
|
|
|
@@ -227,7 +235,7 @@ export type StkProps = {
|
|
|
227
235
|
* 列宽拖动时,每一列都必须要有width,且minWidth/maxWidth不生效。table width会变为"fit-content"。
|
|
228
236
|
* - 会自动更新props.columns中的with属性
|
|
229
237
|
*/
|
|
230
|
-
colResizable?: boolean;
|
|
238
|
+
colResizable?: boolean | ColResizableConfig;
|
|
231
239
|
/** 可拖动至最小的列宽 */
|
|
232
240
|
colMinWidth?: number;
|
|
233
241
|
/**
|
|
@@ -281,7 +289,7 @@ export type StkProps = {
|
|
|
281
289
|
expandConfig?: {
|
|
282
290
|
height?: number;
|
|
283
291
|
};
|
|
284
|
-
/**
|
|
292
|
+
/** 行拖动配置 */
|
|
285
293
|
dragRowConfig?: {
|
|
286
294
|
mode?: 'none' | 'insert' | 'swap';
|
|
287
295
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AutoRowHeightConfig, DragRowConfig, ExpandConfig, HeaderDragConfig, HighlightConfig, Order, PrivateRowDT, SeqConfig, SortConfig, SortOption, StkTableColumn, UniqKeyProp } from './types/index';
|
|
1
|
+
import { AutoRowHeightConfig, DragRowConfig, ExpandConfig, HeaderDragConfig, HighlightConfig, Order, PrivateRowDT, SeqConfig, SortConfig, SortOption, StkTableColumn, UniqKeyProp, ColResizableConfig } from './types/index';
|
|
2
2
|
/** Generic stands for DataType */
|
|
3
3
|
type DT = any & PrivateRowDT;
|
|
4
4
|
/**
|
|
@@ -26,6 +26,7 @@ declare function setSelectedCell(row?: DT, col?: StkTableColumn<DT>, option?: {
|
|
|
26
26
|
* @param option.sort 是否触发排序-默认true
|
|
27
27
|
* @param option.silent 是否禁止触发回调-默认true
|
|
28
28
|
* @param option.force 是否触发排序-默认true
|
|
29
|
+
* @return 表格数据
|
|
29
30
|
*/
|
|
30
31
|
declare function setSorter(colKey: string, order: Order, option?: {
|
|
31
32
|
sortOption?: SortOption<DT>;
|
|
@@ -42,7 +43,10 @@ declare function resetSorter(): void;
|
|
|
42
43
|
declare function scrollTo(top?: number | null, left?: number | null): void;
|
|
43
44
|
/** get current table data */
|
|
44
45
|
declare function getTableData(): any[];
|
|
45
|
-
/**
|
|
46
|
+
/**
|
|
47
|
+
* get current sort info
|
|
48
|
+
* @return {{key:string,order:Order}[]}
|
|
49
|
+
*/
|
|
46
50
|
declare function getSortColumns(): {
|
|
47
51
|
key: string | number | symbol | undefined;
|
|
48
52
|
order: "desc" | "asc";
|
|
@@ -138,7 +142,7 @@ declare const _default: __VLS_WithTemplateSlots<import('vue').DefineComponent<{
|
|
|
138
142
|
* 列宽拖动时,每一列都必须要有width,且minWidth/maxWidth不生效。table width会变为"fit-content"。
|
|
139
143
|
* - 会自动更新props.columns中的with属性
|
|
140
144
|
*/
|
|
141
|
-
colResizable?: boolean | undefined;
|
|
145
|
+
colResizable?: boolean | ColResizableConfig<any> | undefined;
|
|
142
146
|
/** 可拖动至最小的列宽 */
|
|
143
147
|
colMinWidth?: number | undefined;
|
|
144
148
|
/**
|
|
@@ -169,7 +173,7 @@ declare const _default: __VLS_WithTemplateSlots<import('vue').DefineComponent<{
|
|
|
169
173
|
seqConfig?: SeqConfig | undefined;
|
|
170
174
|
/** 展开行配置 */
|
|
171
175
|
expandConfig?: ExpandConfig | undefined;
|
|
172
|
-
/**
|
|
176
|
+
/** 行拖动配置 */
|
|
173
177
|
dragRowConfig?: DragRowConfig | undefined;
|
|
174
178
|
/**
|
|
175
179
|
* 固定头,固定列实现方式。(非响应式)
|
|
@@ -383,7 +387,7 @@ declare const _default: __VLS_WithTemplateSlots<import('vue').DefineComponent<{
|
|
|
383
387
|
* 列宽拖动时,每一列都必须要有width,且minWidth/maxWidth不生效。table width会变为"fit-content"。
|
|
384
388
|
* - 会自动更新props.columns中的with属性
|
|
385
389
|
*/
|
|
386
|
-
colResizable?: boolean | undefined;
|
|
390
|
+
colResizable?: boolean | ColResizableConfig<any> | undefined;
|
|
387
391
|
/** 可拖动至最小的列宽 */
|
|
388
392
|
colMinWidth?: number | undefined;
|
|
389
393
|
/**
|
|
@@ -414,7 +418,7 @@ declare const _default: __VLS_WithTemplateSlots<import('vue').DefineComponent<{
|
|
|
414
418
|
seqConfig?: SeqConfig | undefined;
|
|
415
419
|
/** 展开行配置 */
|
|
416
420
|
expandConfig?: ExpandConfig | undefined;
|
|
417
|
-
/**
|
|
421
|
+
/** 行拖动配置 */
|
|
418
422
|
dragRowConfig?: DragRowConfig | undefined;
|
|
419
423
|
/**
|
|
420
424
|
* 固定头,固定列实现方式。(非响应式)
|
|
@@ -471,7 +475,7 @@ declare const _default: __VLS_WithTemplateSlots<import('vue').DefineComponent<{
|
|
|
471
475
|
selectedCellRevokable: boolean;
|
|
472
476
|
headerDrag: HeaderDragConfig;
|
|
473
477
|
rowClassName: (row: any, i: number) => string;
|
|
474
|
-
colResizable: boolean
|
|
478
|
+
colResizable: boolean | ColResizableConfig<any>;
|
|
475
479
|
colMinWidth: number;
|
|
476
480
|
bordered: boolean | "h" | "v" | "body-v";
|
|
477
481
|
autoResize: boolean | (() => void);
|
|
@@ -492,6 +496,7 @@ declare const _default: __VLS_WithTemplateSlots<import('vue').DefineComponent<{
|
|
|
492
496
|
col: any;
|
|
493
497
|
}): any;
|
|
494
498
|
empty?(_: {}): any;
|
|
499
|
+
customBottom?(_: {}): any;
|
|
495
500
|
}>;
|
|
496
501
|
export default _default;
|
|
497
502
|
type __VLS_WithTemplateSlots<T, S> = T & {
|
|
@@ -185,6 +185,7 @@ export type SeqConfig = {
|
|
|
185
185
|
};
|
|
186
186
|
/** Configuration options for the expand column */
|
|
187
187
|
export type ExpandConfig = {
|
|
188
|
+
/** worked in virtual mode */
|
|
188
189
|
height?: number;
|
|
189
190
|
};
|
|
190
191
|
export type ExpandedRow = PrivateRowDT & {
|
|
@@ -211,4 +212,7 @@ export type AutoRowHeightConfig<DT> = {
|
|
|
211
212
|
/** Estimated row height */
|
|
212
213
|
expectedHeight?: number | ((row: DT, index: number) => number);
|
|
213
214
|
};
|
|
215
|
+
export type ColResizableConfig<DT extends Record<string, any>> = {
|
|
216
|
+
disabled: (col: StkTableColumn<DT>) => boolean;
|
|
217
|
+
};
|
|
214
218
|
export {};
|
|
@@ -11,6 +11,7 @@ type Params<DT extends Record<string, any>> = {
|
|
|
11
11
|
};
|
|
12
12
|
/** 列宽拖动 */
|
|
13
13
|
export declare function useColResize<DT extends Record<string, any>>({ tableContainerRef, tableHeaderLast, colResizeIndicatorRef, props, emits, colKeyGen, fixedCols, }: Params<DT>): {
|
|
14
|
+
colResizeOn: ComputedRef<((col: StkTableColumn<DT>) => boolean) | (() => any)>;
|
|
14
15
|
isColResizing: Ref<boolean, boolean>;
|
|
15
16
|
onThResizeMouseDown: (e: MouseEvent, col: StkTableColumn<DT>, leftHandle?: boolean) => void;
|
|
16
17
|
};
|
|
@@ -6,14 +6,14 @@ type Params<T extends Record<string, any>> = {
|
|
|
6
6
|
colKeyGen: ComputedRef<(col: StkTableColumn<T>) => UniqKey>;
|
|
7
7
|
getFixedColPosition: ComputedRef<(col: StkTableColumn<T>) => number>;
|
|
8
8
|
tableHeaders: ShallowRef<StkTableColumn<T>[][]>;
|
|
9
|
-
|
|
9
|
+
tableHeadersForCalc: ShallowRef<StkTableColumn<T>[][]>;
|
|
10
10
|
tableContainerRef: Ref<HTMLDivElement | undefined>;
|
|
11
11
|
};
|
|
12
12
|
/**
|
|
13
13
|
* 固定列处理
|
|
14
14
|
* @returns
|
|
15
15
|
*/
|
|
16
|
-
export declare function useFixedCol<DT extends Record<string, any>>({ props, colKeyGen, getFixedColPosition, tableHeaders,
|
|
16
|
+
export declare function useFixedCol<DT extends Record<string, any>>({ props, colKeyGen, getFixedColPosition, tableHeaders, tableHeadersForCalc, tableContainerRef, }: Params<DT>): {
|
|
17
17
|
/** 正在被固定的列 */
|
|
18
18
|
fixedCols: ShallowRef<StkTableColumn<DT>[], StkTableColumn<DT>[]>;
|
|
19
19
|
/** 固定列class */
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { Order, SortConfig, SortOption, SortState, StkTableColumn } from '../types';
|
|
2
|
+
/** 是否空值 */
|
|
3
|
+
export declare function isEmptyValue(val: any, isNumber?: boolean): boolean;
|
|
2
4
|
/**
|
|
3
5
|
* 对有序数组插入新数据
|
|
4
6
|
*
|
|
@@ -12,6 +14,12 @@ import { Order, SortConfig, SortOption, SortState, StkTableColumn } from '../typ
|
|
|
12
14
|
* @return targetArray 的浅拷贝
|
|
13
15
|
*/
|
|
14
16
|
export declare function insertToOrderedArray<T extends object>(sortState: SortState<T>, newItem: T, targetArray: T[], sortConfig?: SortConfig<T>): T[];
|
|
17
|
+
/**
|
|
18
|
+
* 二分查找
|
|
19
|
+
* @param searchArray 查找数组
|
|
20
|
+
* @param compareCallback 比较函数,返回 -1|0|1
|
|
21
|
+
*/
|
|
22
|
+
export declare function binarySearch(searchArray: any[], compareCallback: (midIndex: number) => number): number;
|
|
15
23
|
/**
|
|
16
24
|
* 字符串比较
|
|
17
25
|
* @param a
|
|
@@ -19,7 +27,7 @@ export declare function insertToOrderedArray<T extends object>(sortState: SortSt
|
|
|
19
27
|
* @param type 类型
|
|
20
28
|
* @param isNumber 是否是数字类型
|
|
21
29
|
* @param localeCompare 是否 使用Array.prototyshpe.localeCompare
|
|
22
|
-
* @return {
|
|
30
|
+
* @return {number} <0: a < b, 0: a = b, >0: a > b
|
|
23
31
|
*/
|
|
24
32
|
export declare function strCompare(a: string, b: string, isNumber: boolean, localeCompare?: boolean): number;
|
|
25
33
|
/**
|
|
@@ -37,5 +45,5 @@ export declare function tableSort<T extends Record<string, any>>(sortOption: Sor
|
|
|
37
45
|
/** 多级表头深度 从0开始为一级*/
|
|
38
46
|
export declare function howDeepTheHeader(arr: StkTableColumn<any>[], level?: number): number;
|
|
39
47
|
/** number width +px */
|
|
40
|
-
export declare function transformWidthToStr(width?: string | number): string;
|
|
48
|
+
export declare function transformWidthToStr(width?: string | number): string | undefined;
|
|
41
49
|
export declare function getBrowsersVersion(browserName: string): number;
|
package/lib/stk-table-vue.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { openBlock, createElementBlock, createElementVNode, watch, onMounted, onBeforeUnmount, ref,
|
|
1
|
+
import { openBlock, createElementBlock, createElementVNode, watch, onMounted, onBeforeUnmount, ref, computed, shallowRef, defineComponent, nextTick, toRaw, normalizeClass, unref, normalizeStyle, createCommentVNode, Fragment, renderList, createBlock, resolveDynamicComponent, toDisplayString, renderSlot, createVNode, createTextVNode } from "vue";
|
|
2
2
|
import { interpolateRgb } from "d3-interpolate";
|
|
3
3
|
const _export_sfc = (sfc, props) => {
|
|
4
4
|
const target = sfc.__vccOpts || sfc;
|
|
@@ -48,7 +48,7 @@ function _sfc_render(_ctx, _cache) {
|
|
|
48
48
|
}
|
|
49
49
|
const SortIcon = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["render", _sfc_render]]);
|
|
50
50
|
function isEmptyValue(val, isNumber) {
|
|
51
|
-
let isEmpty = val === null || val ===
|
|
51
|
+
let isEmpty = val === null || val === void 0;
|
|
52
52
|
if (isNumber) {
|
|
53
53
|
isEmpty = isEmpty || typeof val === "boolean" || Number.isNaN(+val);
|
|
54
54
|
}
|
|
@@ -59,7 +59,6 @@ function insertToOrderedArray(sortState, newItem, targetArray, sortConfig = {})
|
|
|
59
59
|
sortConfig = { emptyToBottom: false, ...sortConfig };
|
|
60
60
|
let { sortType } = sortState;
|
|
61
61
|
if (!sortType) sortType = typeof newItem[dataIndex];
|
|
62
|
-
const isNumber = sortType === "number";
|
|
63
62
|
const data = [...targetArray];
|
|
64
63
|
if (!order || !data.length) {
|
|
65
64
|
data.unshift(newItem);
|
|
@@ -68,26 +67,32 @@ function insertToOrderedArray(sortState, newItem, targetArray, sortConfig = {})
|
|
|
68
67
|
if (sortConfig.emptyToBottom && isEmptyValue(newItem)) {
|
|
69
68
|
data.push(newItem);
|
|
70
69
|
}
|
|
71
|
-
|
|
72
|
-
let eIndex = data.length - 1;
|
|
70
|
+
const isNumber = sortType === "number";
|
|
73
71
|
const targetVal = newItem[dataIndex];
|
|
74
|
-
|
|
75
|
-
const midIndex = Math.floor((sIndex + eIndex) / 2);
|
|
72
|
+
const sIndex = binarySearch(data, (midIndex) => {
|
|
76
73
|
const midVal = data[midIndex][dataIndex];
|
|
77
74
|
const compareRes = strCompare(midVal, targetVal, isNumber, sortConfig.stringLocaleCompare);
|
|
75
|
+
return order === "asc" ? compareRes : -compareRes;
|
|
76
|
+
});
|
|
77
|
+
data.splice(sIndex, 0, newItem);
|
|
78
|
+
return data;
|
|
79
|
+
}
|
|
80
|
+
function binarySearch(searchArray, compareCallback) {
|
|
81
|
+
let sIndex = 0;
|
|
82
|
+
let eIndex = searchArray.length - 1;
|
|
83
|
+
while (sIndex <= eIndex) {
|
|
84
|
+
const midIndex = Math.floor((sIndex + eIndex) / 2);
|
|
85
|
+
const compareRes = compareCallback(midIndex);
|
|
78
86
|
if (compareRes === 0) {
|
|
79
87
|
sIndex = midIndex;
|
|
80
88
|
break;
|
|
81
|
-
} else if (compareRes
|
|
82
|
-
|
|
83
|
-
else eIndex = midIndex - 1;
|
|
89
|
+
} else if (compareRes < 0) {
|
|
90
|
+
sIndex = midIndex + 1;
|
|
84
91
|
} else {
|
|
85
|
-
|
|
86
|
-
else sIndex = midIndex + 1;
|
|
92
|
+
eIndex = midIndex - 1;
|
|
87
93
|
}
|
|
88
94
|
}
|
|
89
|
-
|
|
90
|
-
return data;
|
|
95
|
+
return sIndex;
|
|
91
96
|
}
|
|
92
97
|
function strCompare(a, b, isNumber, localeCompare = false) {
|
|
93
98
|
let _a = a;
|
|
@@ -158,6 +163,7 @@ function howDeepTheHeader(arr, level = 0) {
|
|
|
158
163
|
return Math.max(...levels);
|
|
159
164
|
}
|
|
160
165
|
function transformWidthToStr(width) {
|
|
166
|
+
if (width === void 0) return;
|
|
161
167
|
const numberWidth = Number(width);
|
|
162
168
|
return width + (!Number.isNaN(numberWidth) ? "px" : "");
|
|
163
169
|
}
|
|
@@ -303,6 +309,12 @@ function useColResize({
|
|
|
303
309
|
startOffsetTableX: 0,
|
|
304
310
|
revertMoveX: false
|
|
305
311
|
};
|
|
312
|
+
const colResizeOn = computed(() => {
|
|
313
|
+
if (Object.prototype.toString.call(props.colResizable) === "[object Object]") {
|
|
314
|
+
return (col) => !props.colResizable.disabled(col);
|
|
315
|
+
}
|
|
316
|
+
return () => props.colResizable;
|
|
317
|
+
});
|
|
306
318
|
onMounted(() => {
|
|
307
319
|
initColResizeEvent();
|
|
308
320
|
});
|
|
@@ -411,6 +423,7 @@ function useColResize({
|
|
|
411
423
|
return column;
|
|
412
424
|
}
|
|
413
425
|
return {
|
|
426
|
+
colResizeOn,
|
|
414
427
|
isColResizing,
|
|
415
428
|
onThResizeMouseDown
|
|
416
429
|
};
|
|
@@ -420,7 +433,7 @@ function useFixedCol({
|
|
|
420
433
|
colKeyGen,
|
|
421
434
|
getFixedColPosition,
|
|
422
435
|
tableHeaders,
|
|
423
|
-
|
|
436
|
+
tableHeadersForCalc,
|
|
424
437
|
tableContainerRef
|
|
425
438
|
}) {
|
|
426
439
|
const fixedShadowCols = shallowRef([]);
|
|
@@ -443,23 +456,8 @@ function useFixedCol({
|
|
|
443
456
|
});
|
|
444
457
|
return colMap;
|
|
445
458
|
});
|
|
446
|
-
function getColAndParentCols(col, type = 1) {
|
|
447
|
-
if (!col) return [];
|
|
448
|
-
const colsTemp = [];
|
|
449
|
-
let node = { __PARENT__: col };
|
|
450
|
-
while (node = node.__PARENT__) {
|
|
451
|
-
if (type === 1 && node.fixed) {
|
|
452
|
-
colsTemp.push(node);
|
|
453
|
-
}
|
|
454
|
-
if (type === 2) {
|
|
455
|
-
colsTemp.push(node);
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
return colsTemp;
|
|
459
|
-
}
|
|
460
459
|
function updateFixedShadow(virtualScrollX) {
|
|
461
460
|
const fixedColsTemp = [];
|
|
462
|
-
const fixedShadowColsTemp = [];
|
|
463
461
|
let clientWidth, scrollLeft;
|
|
464
462
|
if (virtualScrollX == null ? void 0 : virtualScrollX.value) {
|
|
465
463
|
const {
|
|
@@ -478,26 +476,29 @@ function useFixedCol({
|
|
|
478
476
|
clientWidth = cw;
|
|
479
477
|
scrollLeft = sl;
|
|
480
478
|
}
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
479
|
+
const leftShadowCol = [];
|
|
480
|
+
const rightShadowCol = [];
|
|
481
|
+
tableHeadersForCalc.value.forEach((row, level) => {
|
|
482
|
+
let left = 0;
|
|
483
|
+
row.forEach((col) => {
|
|
484
|
+
const position = getFixedColPosition.value(col);
|
|
485
|
+
const isFixedLeft = col.fixed === "left";
|
|
486
|
+
const isFixedRight = col.fixed === "right";
|
|
487
|
+
if (isFixedLeft && position + scrollLeft > left) {
|
|
488
|
+
fixedColsTemp.push(col);
|
|
489
|
+
leftShadowCol[level] = col;
|
|
490
|
+
}
|
|
491
|
+
left += getCalculatedColWidth(col);
|
|
492
|
+
if (isFixedRight && scrollLeft + clientWidth - left < position) {
|
|
493
|
+
fixedColsTemp.push(col);
|
|
494
|
+
if (!rightShadowCol[level]) {
|
|
495
|
+
rightShadowCol[level] = col;
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
});
|
|
497
499
|
});
|
|
498
500
|
if (props.fixedColShadow) {
|
|
499
|
-
|
|
500
|
-
fixedShadowCols.value = fixedShadowColsTemp.filter(Boolean);
|
|
501
|
+
fixedShadowCols.value = [...leftShadowCol, ...rightShadowCol].filter(Boolean);
|
|
501
502
|
}
|
|
502
503
|
fixedCols.value = fixedColsTemp;
|
|
503
504
|
}
|
|
@@ -633,7 +634,7 @@ function useHighlight({ props, stkTableId, tableContainerRef }) {
|
|
|
633
634
|
const { ts, duration } = store;
|
|
634
635
|
const timeOffset = nowTs - ts;
|
|
635
636
|
if (nowTs - ts < duration) {
|
|
636
|
-
|
|
637
|
+
updateRowAnimation(rowKeyValue, store, timeOffset);
|
|
637
638
|
} else {
|
|
638
639
|
highlightDimRowsAnimation.delete(rowKeyValue);
|
|
639
640
|
}
|
|
@@ -708,7 +709,7 @@ function useHighlight({ props, stkTableId, tableContainerRef }) {
|
|
|
708
709
|
const rowKeyValue = rowKeyValues[i];
|
|
709
710
|
const store = { ts: nowTs, visible: false, keyframe, duration };
|
|
710
711
|
highlightDimRowsAnimation.set(rowKeyValue, store);
|
|
711
|
-
|
|
712
|
+
updateRowAnimation(rowKeyValue, store, 0);
|
|
712
713
|
}
|
|
713
714
|
calcRowHighlightLoop();
|
|
714
715
|
} else {
|
|
@@ -770,7 +771,7 @@ function useHighlight({ props, stkTableId, tableContainerRef }) {
|
|
|
770
771
|
}, duration)
|
|
771
772
|
);
|
|
772
773
|
}
|
|
773
|
-
function
|
|
774
|
+
function updateRowAnimation(rowKeyValue, store, timeOffset) {
|
|
774
775
|
const rowEl = document.getElementById(stkTableId + "-" + String(rowKeyValue));
|
|
775
776
|
const { visible, keyframe, duration: initialDuration } = store;
|
|
776
777
|
if (!rowEl) {
|
|
@@ -916,7 +917,7 @@ function useThDrag({ props, emits, colKeyGen }) {
|
|
|
916
917
|
emits("th-drop", th.dataset.colKey);
|
|
917
918
|
}
|
|
918
919
|
function handleColOrderChange(dragStartKey, dragEndKey) {
|
|
919
|
-
if (
|
|
920
|
+
if (isEmptyValue(dragStartKey) || isEmptyValue(dragEndKey)) return;
|
|
920
921
|
if (dragConfig.value.mode !== "none") {
|
|
921
922
|
const columns = [...props.columns];
|
|
922
923
|
const dragStartIndex = columns.findIndex((col) => colKeyGen.value(col) === dragStartKey);
|
|
@@ -1064,6 +1065,9 @@ function useVirtualScroll({
|
|
|
1064
1065
|
offsetLeft: 0,
|
|
1065
1066
|
scrollLeft: 0
|
|
1066
1067
|
});
|
|
1068
|
+
const hasExpandCol = computed(() => {
|
|
1069
|
+
return tableHeaderLast.value.some((col) => col.type === "expand");
|
|
1070
|
+
});
|
|
1067
1071
|
const virtual_on = computed(() => {
|
|
1068
1072
|
return props.virtual && dataSourceCopy.value.length > virtualScroll.value.pageSize * 2;
|
|
1069
1073
|
});
|
|
@@ -1170,7 +1174,8 @@ function useVirtualScroll({
|
|
|
1170
1174
|
let expectedHeight;
|
|
1171
1175
|
if (storedHeight) {
|
|
1172
1176
|
return storedHeight;
|
|
1173
|
-
}
|
|
1177
|
+
}
|
|
1178
|
+
if (expectedHeight = (_a = props.autoRowHeight) == null ? void 0 : _a.expectedHeight) {
|
|
1174
1179
|
if (typeof expectedHeight === "function") {
|
|
1175
1180
|
return expectedHeight(row);
|
|
1176
1181
|
} else {
|
|
@@ -1179,6 +1184,18 @@ function useVirtualScroll({
|
|
|
1179
1184
|
}
|
|
1180
1185
|
return props.rowHeight || DEFAULT_ROW_HEIGHT;
|
|
1181
1186
|
};
|
|
1187
|
+
const createGetRowHeightFn = () => {
|
|
1188
|
+
var _a;
|
|
1189
|
+
if (props.autoRowHeight) {
|
|
1190
|
+
return (row) => getAutoRowHeight(row);
|
|
1191
|
+
}
|
|
1192
|
+
if (hasExpandCol.value) {
|
|
1193
|
+
const { rowHeight } = virtualScroll.value;
|
|
1194
|
+
const expandedRowHeight = ((_a = props.expandConfig) == null ? void 0 : _a.height) || rowHeight;
|
|
1195
|
+
return (row) => row.__EXPANDED_ROW__ ? expandedRowHeight : rowHeight;
|
|
1196
|
+
}
|
|
1197
|
+
return () => props.rowHeight || DEFAULT_ROW_HEIGHT;
|
|
1198
|
+
};
|
|
1182
1199
|
function updateVirtualScrollY(sTop = 0) {
|
|
1183
1200
|
var _a;
|
|
1184
1201
|
const { rowHeight, pageSize, scrollTop, startIndex: oldStartIndex, endIndex: oldEndIndex } = virtualScroll.value;
|
|
@@ -1186,21 +1203,27 @@ function useVirtualScroll({
|
|
|
1186
1203
|
if (!virtual_on.value) {
|
|
1187
1204
|
return;
|
|
1188
1205
|
}
|
|
1206
|
+
const dataSourceCopyTemp = dataSourceCopy.value;
|
|
1189
1207
|
const { autoRowHeight, stripe, optimizeVue2Scroll } = props;
|
|
1190
1208
|
let startIndex = 0;
|
|
1191
1209
|
let autoRowHeightTop = 0;
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1210
|
+
let getRowHeight = null;
|
|
1211
|
+
const dataLength = dataSourceCopyTemp.length;
|
|
1212
|
+
if (autoRowHeight || hasExpandCol.value) {
|
|
1213
|
+
if (autoRowHeight) {
|
|
1214
|
+
(_a = trRef.value) == null ? void 0 : _a.forEach((tr) => {
|
|
1215
|
+
const { rowKey } = tr.dataset;
|
|
1216
|
+
if (!rowKey || autoRowHeightMap.has(rowKey)) return;
|
|
1217
|
+
autoRowHeightMap.set(rowKey, tr.offsetHeight);
|
|
1218
|
+
});
|
|
1219
|
+
}
|
|
1220
|
+
getRowHeight = createGetRowHeightFn();
|
|
1221
|
+
for (let i = 0; i < dataLength; i++) {
|
|
1222
|
+
const height = getRowHeight(dataSourceCopyTemp[i]);
|
|
1200
1223
|
autoRowHeightTop += height;
|
|
1201
1224
|
if (autoRowHeightTop >= sTop) {
|
|
1202
1225
|
startIndex = i;
|
|
1203
|
-
autoRowHeightTop
|
|
1226
|
+
autoRowHeightTop -= height;
|
|
1204
1227
|
break;
|
|
1205
1228
|
}
|
|
1206
1229
|
}
|
|
@@ -1210,13 +1233,13 @@ function useVirtualScroll({
|
|
|
1210
1233
|
let endIndex = startIndex + pageSize;
|
|
1211
1234
|
if (stripe && startIndex > 0 && startIndex % 2) {
|
|
1212
1235
|
startIndex -= 1;
|
|
1213
|
-
if (autoRowHeight) {
|
|
1214
|
-
const height =
|
|
1236
|
+
if (autoRowHeight || hasExpandCol.value) {
|
|
1237
|
+
const height = getRowHeight(dataSourceCopyTemp[startIndex]);
|
|
1215
1238
|
autoRowHeightTop -= height;
|
|
1216
1239
|
}
|
|
1217
1240
|
}
|
|
1218
1241
|
startIndex = Math.max(0, startIndex);
|
|
1219
|
-
endIndex = Math.min(endIndex,
|
|
1242
|
+
endIndex = Math.min(endIndex, dataLength);
|
|
1220
1243
|
if (startIndex >= endIndex) {
|
|
1221
1244
|
startIndex = endIndex - pageSize;
|
|
1222
1245
|
}
|
|
@@ -1224,7 +1247,7 @@ function useVirtualScroll({
|
|
|
1224
1247
|
window.clearTimeout(vue2ScrollYTimeout);
|
|
1225
1248
|
}
|
|
1226
1249
|
let offsetTop = 0;
|
|
1227
|
-
if (autoRowHeight) {
|
|
1250
|
+
if (autoRowHeight || hasExpandCol.value) {
|
|
1228
1251
|
offsetTop = autoRowHeightTop;
|
|
1229
1252
|
} else {
|
|
1230
1253
|
if (oldStartIndex === startIndex && oldEndIndex === endIndex) {
|
|
@@ -1473,9 +1496,9 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
1473
1496
|
getFixedColPosition,
|
|
1474
1497
|
tableContainerRef,
|
|
1475
1498
|
tableHeaders,
|
|
1476
|
-
|
|
1499
|
+
tableHeadersForCalc
|
|
1477
1500
|
});
|
|
1478
|
-
const { isColResizing, onThResizeMouseDown } = useColResize({
|
|
1501
|
+
const { isColResizing, onThResizeMouseDown, colResizeOn } = useColResize({
|
|
1479
1502
|
props,
|
|
1480
1503
|
emits,
|
|
1481
1504
|
colKeyGen,
|
|
@@ -2175,12 +2198,12 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
2175
2198
|
col.sorter ? (openBlock(), createElementBlock("span", _hoisted_4, [
|
|
2176
2199
|
createVNode(SortIcon)
|
|
2177
2200
|
])) : createCommentVNode("", true),
|
|
2178
|
-
|
|
2201
|
+
unref(colResizeOn)(col) && colIndex > 0 ? (openBlock(), createElementBlock("div", {
|
|
2179
2202
|
key: 4,
|
|
2180
2203
|
class: "table-header-resizer left",
|
|
2181
2204
|
onMousedown: (e) => unref(onThResizeMouseDown)(e, col, true)
|
|
2182
2205
|
}, null, 40, _hoisted_5)) : createCommentVNode("", true),
|
|
2183
|
-
|
|
2206
|
+
unref(colResizeOn)(col) ? (openBlock(), createElementBlock("div", {
|
|
2184
2207
|
key: 5,
|
|
2185
2208
|
class: "table-header-resizer right",
|
|
2186
2209
|
onMousedown: (e) => unref(onThResizeMouseDown)(e, col)
|
|
@@ -2235,7 +2258,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
2235
2258
|
"expanded-row": row && row.__EXPANDED_ROW__
|
|
2236
2259
|
}),
|
|
2237
2260
|
style: normalizeStyle({
|
|
2238
|
-
"--row-height": row && row.__EXPANDED_ROW__ &&
|
|
2261
|
+
"--row-height": row && row.__EXPANDED_ROW__ && props.virtual && ((_a = props.expandConfig) == null ? void 0 : _a.height) && ((_b = props.expandConfig) == null ? void 0 : _b.height) + "px"
|
|
2239
2262
|
}),
|
|
2240
2263
|
onClick: (e) => onRowClick(e, row),
|
|
2241
2264
|
onDblclick: (e) => onRowDblclick(e, row),
|
|
@@ -2325,13 +2348,15 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
2325
2348
|
renderSlot(_ctx.$slots, "empty", {}, () => [
|
|
2326
2349
|
_cache[7] || (_cache[7] = createTextVNode("暂无数据"))
|
|
2327
2350
|
])
|
|
2328
|
-
], 2)) : createCommentVNode("", true)
|
|
2351
|
+
], 2)) : createCommentVNode("", true),
|
|
2352
|
+
renderSlot(_ctx.$slots, "customBottom")
|
|
2329
2353
|
], 38);
|
|
2330
2354
|
};
|
|
2331
2355
|
}
|
|
2332
2356
|
});
|
|
2333
2357
|
export {
|
|
2334
2358
|
_sfc_main as StkTable,
|
|
2359
|
+
binarySearch,
|
|
2335
2360
|
insertToOrderedArray,
|
|
2336
2361
|
strCompare,
|
|
2337
2362
|
tableSort
|
package/lib/style.css
CHANGED
|
@@ -38,8 +38,6 @@
|
|
|
38
38
|
display:flex;
|
|
39
39
|
flex-direction:column;
|
|
40
40
|
box-sizing:border-box;
|
|
41
|
-
background-image:linear-gradient(180deg, #e8e8f4 1px, transparent 1px), linear-gradient(270deg, #e8e8f4 1px, transparent 1px), linear-gradient(0deg, #e8e8f4 1px, transparent 1px);
|
|
42
|
-
background-image:var(--bg-border-top), var(--bg-border-right), var(--bg-border-bottom);
|
|
43
41
|
}
|
|
44
42
|
.stk-table.dark{
|
|
45
43
|
--th-bgc:#202029;
|
|
@@ -63,21 +61,22 @@
|
|
|
63
61
|
--drag-handle-hover-color:#5d6064;
|
|
64
62
|
color:#d1d1e0;
|
|
65
63
|
}
|
|
66
|
-
.stk-table.headless{
|
|
64
|
+
.stk-table.headless.border{
|
|
67
65
|
border-top:1px solid var(--border-color);
|
|
68
66
|
background-image:var(--bg-border-right), var(--bg-border-bottom);
|
|
69
67
|
}
|
|
70
68
|
.stk-table.col-resizable .stk-table-main{
|
|
71
|
-
width:-moz-fit-content
|
|
72
|
-
width:fit-content
|
|
73
|
-
min-width:-moz-min-content
|
|
74
|
-
min-width:min-content
|
|
69
|
+
width:-moz-fit-content;
|
|
70
|
+
width:fit-content;
|
|
71
|
+
min-width:-moz-min-content;
|
|
72
|
+
min-width:min-content;
|
|
75
73
|
}
|
|
76
74
|
.stk-table.is-col-resizing th{
|
|
77
75
|
pointer-events:none;
|
|
78
76
|
}
|
|
79
77
|
.stk-table.border{
|
|
80
78
|
border-left:1px solid var(--border-color);
|
|
79
|
+
background-image:var(--bg-border-top), var(--bg-border-right), var(--bg-border-bottom);
|
|
81
80
|
}
|
|
82
81
|
.stk-table.border th,
|
|
83
82
|
.stk-table.border td{
|
|
@@ -104,13 +103,13 @@
|
|
|
104
103
|
.stk-table.stripe.vt-on .stk-tbody-main tr:nth-child(odd){
|
|
105
104
|
background-color:var(--stripe-bgc);
|
|
106
105
|
}
|
|
107
|
-
.stk-table.stripe.row-hover .stk-tbody-main tr:hover{
|
|
106
|
+
.stk-table.stripe.row-hover .stk-table-main .stk-tbody-main tr:hover{
|
|
108
107
|
background-color:var(--tr-hover-bgc);
|
|
109
108
|
}
|
|
110
|
-
.stk-table.stripe.row-active .stk-tbody-main tr.active{
|
|
109
|
+
.stk-table.stripe.row-active .stk-table-main .stk-tbody-main tr.active{
|
|
111
110
|
background-color:var(--tr-active-bgc);
|
|
112
111
|
}
|
|
113
|
-
.stk-table.row-hover .stk-tbody-main tr:hover{
|
|
112
|
+
.stk-table.row-hover .stk-table-main .stk-tbody-main tr:hover{
|
|
114
113
|
background-color:var(--tr-hover-bgc);
|
|
115
114
|
}
|
|
116
115
|
.stk-table.row-active .stk-tbody-main tr.active{
|
|
@@ -142,6 +141,9 @@
|
|
|
142
141
|
max-height:calc(var(--header-row-height) * 1);
|
|
143
142
|
max-height:calc(var(--header-row-height) * var(--row-span, 1));
|
|
144
143
|
}
|
|
144
|
+
.stk-table.virtual .table-header-cell-wrapper .table-header-title{
|
|
145
|
+
max-height:inherit;
|
|
146
|
+
}
|
|
145
147
|
.stk-table.virtual tbody td{
|
|
146
148
|
height:var(--row-height);
|
|
147
149
|
}
|
|
@@ -258,7 +260,7 @@
|
|
|
258
260
|
.stk-table .expand-cell{
|
|
259
261
|
cursor:pointer;
|
|
260
262
|
}
|
|
261
|
-
.stk-table .expand-cell .
|
|
263
|
+
.stk-table .expand-cell .expanded-cell-wrapper::before{
|
|
262
264
|
content:'';
|
|
263
265
|
display:inline-block;
|
|
264
266
|
margin:0 2px;
|
|
@@ -269,7 +271,7 @@
|
|
|
269
271
|
border-bottom:4px solid transparent;
|
|
270
272
|
transition:transform 0.2s ease;
|
|
271
273
|
}
|
|
272
|
-
.stk-table .expand-cell .
|
|
274
|
+
.stk-table .expand-cell .expanded-cell-wrapper > span{
|
|
273
275
|
margin-left:var(--cell-padding-x);
|
|
274
276
|
}
|
|
275
277
|
.stk-table .expand-cell.expanded .table-cell-wrapper::before{
|