stk-table-vue 0.8.13 → 0.9.0-beta.1

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.
Files changed (38) hide show
  1. package/README.md +172 -180
  2. package/lib/src/StkTable/StkTable.vue.d.ts +22 -2
  3. package/lib/src/StkTable/useScrollbar.d.ts +57 -0
  4. package/lib/src/StkTable/utils/index.d.ts +10 -0
  5. package/lib/stk-table-vue.js +563 -294
  6. package/lib/style.css +49 -2
  7. package/package.json +74 -72
  8. package/src/StkTable/StkTable.vue +1730 -1653
  9. package/src/StkTable/components/DragHandle.vue +9 -9
  10. package/src/StkTable/components/SortIcon.vue +6 -6
  11. package/src/StkTable/components/TriangleIcon.vue +3 -3
  12. package/src/StkTable/const.ts +50 -50
  13. package/src/StkTable/index.ts +4 -4
  14. package/src/StkTable/style.less +627 -580
  15. package/src/StkTable/types/highlightDimOptions.ts +26 -26
  16. package/src/StkTable/types/index.ts +297 -297
  17. package/src/StkTable/useAutoResize.ts +91 -91
  18. package/src/StkTable/useColResize.ts +216 -216
  19. package/src/StkTable/useFixedCol.ts +150 -148
  20. package/src/StkTable/useFixedStyle.ts +75 -75
  21. package/src/StkTable/useGetFixedColPosition.ts +65 -65
  22. package/src/StkTable/useHighlight.ts +257 -257
  23. package/src/StkTable/useKeyboardArrowScroll.ts +112 -112
  24. package/src/StkTable/useMaxRowSpan.ts +55 -55
  25. package/src/StkTable/useMergeCells.ts +120 -123
  26. package/src/StkTable/useRowExpand.ts +88 -88
  27. package/src/StkTable/useScrollRowByRow.ts +114 -79
  28. package/src/StkTable/useScrollbar.ts +187 -0
  29. package/src/StkTable/useThDrag.ts +102 -102
  30. package/src/StkTable/useTrDrag.ts +113 -118
  31. package/src/StkTable/useTree.ts +161 -161
  32. package/src/StkTable/useVirtualScroll.ts +494 -494
  33. package/src/StkTable/utils/constRefUtils.ts +29 -29
  34. package/src/StkTable/utils/index.ts +287 -242
  35. package/src/StkTable/utils/useTriggerRef.ts +33 -33
  36. package/src/VirtualTree.vue +622 -622
  37. package/src/VirtualTreeSelect.vue +367 -367
  38. package/src/vite-env.d.ts +10 -10
@@ -1,112 +1,112 @@
1
- import { ComputedRef, Ref, ShallowRef, onBeforeUnmount, onMounted, watch } from 'vue';
2
- import { StkTableColumn } from './types';
3
- import { VirtualScrollStore, VirtualScrollXStore } from './useVirtualScroll';
4
-
5
- /** 翻页按键 */
6
- enum ScrollCodes {
7
- ArrowUp = 'ArrowUp',
8
- ArrowRight = 'ArrowRight',
9
- ArrowDown = 'ArrowDown',
10
- ArrowLeft = 'ArrowLeft',
11
- PageUp = 'PageUp',
12
- PageDown = 'PageDown',
13
- Home = 'Home',
14
- End = 'End',
15
- }
16
- /** 所有翻页按键数组 */
17
- const ScrollCodesValues = Object.values(ScrollCodes);
18
-
19
- type Options<DT extends Record<string, any>> = {
20
- props: any;
21
- scrollTo: (y: number | null, x: number | null) => void;
22
- virtualScroll: Ref<VirtualScrollStore>;
23
- virtualScrollX: Ref<VirtualScrollXStore>;
24
- tableHeaders: ShallowRef<StkTableColumn<DT>[][]>;
25
- virtual_on: ComputedRef<boolean>;
26
- };
27
- /**
28
- * 按下键盘箭头滚动。只有悬浮在表体上才能生效键盘。
29
- *
30
- * 在低版本浏览器中,虚拟滚动时,使用键盘滚动,等选中的行消失在视口外时,滚动会失效。
31
- */
32
- export function useKeyboardArrowScroll<DT extends Record<string, any>>(
33
- targetElement: Ref<HTMLElement | undefined>,
34
- { props, scrollTo, virtualScroll, virtualScrollX, tableHeaders, virtual_on }: Options<DT>,
35
- ) {
36
- /** 检测鼠标是否悬浮在表格体上 */
37
- let isMouseOver = false;
38
- watch(virtual_on, val => {
39
- if (!val) {
40
- removeListeners();
41
- } else {
42
- addEventListeners();
43
- }
44
- });
45
-
46
- onMounted(addEventListeners);
47
-
48
- onBeforeUnmount(removeListeners);
49
-
50
- function addEventListeners() {
51
- window.addEventListener('keydown', handleKeydown);
52
- targetElement.value?.addEventListener('mouseenter', handleMouseEnter);
53
- targetElement.value?.addEventListener('mouseleave', handleMouseLeave);
54
- targetElement.value?.addEventListener('mousedown', handleMouseDown);
55
- }
56
-
57
- function removeListeners() {
58
- window.removeEventListener('keydown', handleKeydown);
59
- targetElement.value?.removeEventListener('mouseenter', handleMouseEnter);
60
- targetElement.value?.removeEventListener('mouseleave', handleMouseLeave);
61
- targetElement.value?.removeEventListener('mousedown', handleMouseDown);
62
- }
63
-
64
- /** 键盘按下事件 */
65
- function handleKeydown(e: KeyboardEvent) {
66
- if (!virtual_on.value) return; // 非虚拟滚动使用浏览器默认滚动
67
- const keyCode = e.code;
68
- if (!ScrollCodesValues.includes(keyCode as any)) return;
69
- if (!isMouseOver) return; // 不悬浮还是要触发键盘事件的
70
- e.preventDefault(); // 不触发键盘默认的箭头事件
71
-
72
- const { scrollTop, rowHeight, containerHeight, scrollHeight } = virtualScroll.value;
73
- const { scrollLeft } = virtualScrollX.value;
74
- const { headless, headerRowHeight } = props;
75
-
76
- // 这里不用virtualScroll 中的pageSize,因为我需要上一页的最后一条放在下一页的第一条
77
- const headerHeight = headless ? 0 : tableHeaders.value.length * (headerRowHeight || rowHeight);
78
- /** 表体的page */
79
- const bodyPageSize = Math.floor((containerHeight - headerHeight) / rowHeight);
80
- if (keyCode=== ScrollCodes.ArrowUp) {
81
- scrollTo(scrollTop - rowHeight, null);
82
- } else if (keyCode=== ScrollCodes.ArrowRight) {
83
- scrollTo(null, scrollLeft + 50);
84
- } else if (keyCode=== ScrollCodes.ArrowDown) {
85
- scrollTo(scrollTop + rowHeight, null);
86
- } else if (keyCode=== ScrollCodes.ArrowLeft) {
87
- scrollTo(null, scrollLeft - 50);
88
- } else if (keyCode=== ScrollCodes.PageUp) {
89
- scrollTo(scrollTop - rowHeight * bodyPageSize + headerHeight, null);
90
- } else if (keyCode=== ScrollCodes.PageDown) {
91
- scrollTo(scrollTop + rowHeight * bodyPageSize - headerHeight, null);
92
- } else if (keyCode=== ScrollCodes.Home) {
93
- scrollTo(0, null);
94
- } else if (keyCode=== ScrollCodes.End) {
95
- scrollTo(scrollHeight, null);
96
- }
97
- }
98
-
99
- function handleMouseEnter() {
100
- isMouseOver = true;
101
- }
102
- function handleMouseLeave() {
103
- isMouseOver = false;
104
- }
105
- /**
106
- * 兜底。
107
- * 是否存在不触发mouseEnter的时候?
108
- */
109
- function handleMouseDown() {
110
- if (!isMouseOver) isMouseOver = true;
111
- }
112
- }
1
+ import { ComputedRef, Ref, ShallowRef, onBeforeUnmount, onMounted, watch } from 'vue';
2
+ import { StkTableColumn } from './types';
3
+ import { VirtualScrollStore, VirtualScrollXStore } from './useVirtualScroll';
4
+
5
+ /** 翻页按键 */
6
+ enum ScrollCodes {
7
+ ArrowUp = 'ArrowUp',
8
+ ArrowRight = 'ArrowRight',
9
+ ArrowDown = 'ArrowDown',
10
+ ArrowLeft = 'ArrowLeft',
11
+ PageUp = 'PageUp',
12
+ PageDown = 'PageDown',
13
+ Home = 'Home',
14
+ End = 'End',
15
+ }
16
+ /** 所有翻页按键数组 */
17
+ const ScrollCodesValues = Object.values(ScrollCodes);
18
+
19
+ type Options<DT extends Record<string, any>> = {
20
+ props: any;
21
+ scrollTo: (y: number | null, x: number | null) => void;
22
+ virtualScroll: Ref<VirtualScrollStore>;
23
+ virtualScrollX: Ref<VirtualScrollXStore>;
24
+ tableHeaders: ShallowRef<StkTableColumn<DT>[][]>;
25
+ virtual_on: ComputedRef<boolean>;
26
+ };
27
+ /**
28
+ * 按下键盘箭头滚动。只有悬浮在表体上才能生效键盘。
29
+ *
30
+ * 在低版本浏览器中,虚拟滚动时,使用键盘滚动,等选中的行消失在视口外时,滚动会失效。
31
+ */
32
+ export function useKeyboardArrowScroll<DT extends Record<string, any>>(
33
+ targetElement: Ref<HTMLElement | undefined>,
34
+ { props, scrollTo, virtualScroll, virtualScrollX, tableHeaders, virtual_on }: Options<DT>,
35
+ ) {
36
+ /** 检测鼠标是否悬浮在表格体上 */
37
+ let isMouseOver = false;
38
+ watch(virtual_on, val => {
39
+ if (!val) {
40
+ removeListeners();
41
+ } else {
42
+ addEventListeners();
43
+ }
44
+ });
45
+
46
+ onMounted(addEventListeners);
47
+
48
+ onBeforeUnmount(removeListeners);
49
+
50
+ function addEventListeners() {
51
+ window.addEventListener('keydown', handleKeydown);
52
+ targetElement.value?.addEventListener('mouseenter', handleMouseEnter);
53
+ targetElement.value?.addEventListener('mouseleave', handleMouseLeave);
54
+ targetElement.value?.addEventListener('mousedown', handleMouseDown);
55
+ }
56
+
57
+ function removeListeners() {
58
+ window.removeEventListener('keydown', handleKeydown);
59
+ targetElement.value?.removeEventListener('mouseenter', handleMouseEnter);
60
+ targetElement.value?.removeEventListener('mouseleave', handleMouseLeave);
61
+ targetElement.value?.removeEventListener('mousedown', handleMouseDown);
62
+ }
63
+
64
+ /** 键盘按下事件 */
65
+ function handleKeydown(e: KeyboardEvent) {
66
+ if (!virtual_on.value) return; // 非虚拟滚动使用浏览器默认滚动
67
+ const keyCode = e.code;
68
+ if (!ScrollCodesValues.includes(keyCode as any)) return;
69
+ if (!isMouseOver) return; // 不悬浮还是要触发键盘事件的
70
+ e.preventDefault(); // 不触发键盘默认的箭头事件
71
+
72
+ const { scrollTop, rowHeight, containerHeight, scrollHeight } = virtualScroll.value;
73
+ const { scrollLeft } = virtualScrollX.value;
74
+ const { headless, headerRowHeight } = props;
75
+
76
+ // 这里不用virtualScroll 中的pageSize,因为我需要上一页的最后一条放在下一页的第一条
77
+ const headerHeight = headless ? 0 : tableHeaders.value.length * (headerRowHeight || rowHeight);
78
+ /** 表体的page */
79
+ const bodyPageSize = Math.floor((containerHeight - headerHeight) / rowHeight);
80
+ if (keyCode=== ScrollCodes.ArrowUp) {
81
+ scrollTo(scrollTop - rowHeight, null);
82
+ } else if (keyCode=== ScrollCodes.ArrowRight) {
83
+ scrollTo(null, scrollLeft + 50);
84
+ } else if (keyCode=== ScrollCodes.ArrowDown) {
85
+ scrollTo(scrollTop + rowHeight, null);
86
+ } else if (keyCode=== ScrollCodes.ArrowLeft) {
87
+ scrollTo(null, scrollLeft - 50);
88
+ } else if (keyCode=== ScrollCodes.PageUp) {
89
+ scrollTo(scrollTop - rowHeight * bodyPageSize + headerHeight, null);
90
+ } else if (keyCode=== ScrollCodes.PageDown) {
91
+ scrollTo(scrollTop + rowHeight * bodyPageSize - headerHeight, null);
92
+ } else if (keyCode=== ScrollCodes.Home) {
93
+ scrollTo(0, null);
94
+ } else if (keyCode=== ScrollCodes.End) {
95
+ scrollTo(scrollHeight, null);
96
+ }
97
+ }
98
+
99
+ function handleMouseEnter() {
100
+ isMouseOver = true;
101
+ }
102
+ function handleMouseLeave() {
103
+ isMouseOver = false;
104
+ }
105
+ /**
106
+ * 兜底。
107
+ * 是否存在不触发mouseEnter的时候?
108
+ */
109
+ function handleMouseDown() {
110
+ if (!isMouseOver) isMouseOver = true;
111
+ }
112
+ }
@@ -1,56 +1,56 @@
1
- import { ShallowRef } from "vue";
2
- import { PrivateStkTableColumn, RowKeyGen, UniqKey } from "./types";
3
-
4
- type Options = {
5
- props:any,
6
- tableHeaderLast: ShallowRef<PrivateStkTableColumn<any>[]>;
7
- rowKeyGen: RowKeyGen;
8
- dataSourceCopy: ShallowRef<any[]>;
9
- }
10
-
11
- export function useMaxRowSpan({ props, tableHeaderLast, rowKeyGen, dataSourceCopy }: Options) {
12
- /** max rowspan of each row */
13
- const maxRowSpan = new Map<UniqKey, number>();
14
-
15
- /**
16
- * Use dataSourceCopy and tableHeaderLast to calculate maxRowSpan
17
- * @link {maxRowSpan}
18
- */
19
- function updateMaxRowSpan() {
20
- if(!props.virtual) {
21
- if(maxRowSpan.size) maxRowSpan.clear();
22
- return;
23
- }
24
- maxRowSpan.clear();
25
-
26
- const data = dataSourceCopy.value;
27
- const columns = tableHeaderLast.value;
28
-
29
- const columnsWithMerge = columns.filter(col => col.mergeCells);
30
- if (!columnsWithMerge.length) return;
31
-
32
- const dataLength = data.length;
33
- const mergeColumnsLength = columnsWithMerge.length;
34
-
35
- for (let rowIndex = 0; rowIndex < dataLength; rowIndex++) {
36
- const row = data[rowIndex];
37
- const rowKey = rowKeyGen(row);
38
- let currentMax = maxRowSpan.get(rowKey) || 0;
39
-
40
- for (let colIndex = 0; colIndex < mergeColumnsLength; colIndex++) {
41
- const col = columnsWithMerge[colIndex];
42
- const { rowspan = 1 } = col.mergeCells!({ row, col, rowIndex, colIndex }) || {};
43
-
44
- if (rowspan > 1 && rowspan > currentMax) {
45
- currentMax = rowspan;
46
- maxRowSpan.set(rowKey, currentMax);
47
- }
48
- }
49
- }
50
- }
51
-
52
- return {
53
- maxRowSpan,
54
- updateMaxRowSpan
55
- }
1
+ import { ShallowRef } from "vue";
2
+ import { PrivateStkTableColumn, RowKeyGen, UniqKey } from "./types";
3
+
4
+ type Options = {
5
+ props:any,
6
+ tableHeaderLast: ShallowRef<PrivateStkTableColumn<any>[]>;
7
+ rowKeyGen: RowKeyGen;
8
+ dataSourceCopy: ShallowRef<any[]>;
9
+ }
10
+
11
+ export function useMaxRowSpan({ props, tableHeaderLast, rowKeyGen, dataSourceCopy }: Options) {
12
+ /** max rowspan of each row */
13
+ const maxRowSpan = new Map<UniqKey, number>();
14
+
15
+ /**
16
+ * Use dataSourceCopy and tableHeaderLast to calculate maxRowSpan
17
+ * @link {maxRowSpan}
18
+ */
19
+ function updateMaxRowSpan() {
20
+ if(!props.virtual) {
21
+ if(maxRowSpan.size) maxRowSpan.clear();
22
+ return;
23
+ }
24
+ maxRowSpan.clear();
25
+
26
+ const data = dataSourceCopy.value;
27
+ const columns = tableHeaderLast.value;
28
+
29
+ const columnsWithMerge = columns.filter(col => col.mergeCells);
30
+ if (!columnsWithMerge.length) return;
31
+
32
+ const dataLength = data.length;
33
+ const mergeColumnsLength = columnsWithMerge.length;
34
+
35
+ for (let rowIndex = 0; rowIndex < dataLength; rowIndex++) {
36
+ const row = data[rowIndex];
37
+ const rowKey = rowKeyGen(row);
38
+ let currentMax = maxRowSpan.get(rowKey) || 0;
39
+
40
+ for (let colIndex = 0; colIndex < mergeColumnsLength; colIndex++) {
41
+ const col = columnsWithMerge[colIndex];
42
+ const { rowspan = 1 } = col.mergeCells!({ row, col, rowIndex, colIndex }) || {};
43
+
44
+ if (rowspan > 1 && rowspan > currentMax) {
45
+ currentMax = rowspan;
46
+ maxRowSpan.set(rowKey, currentMax);
47
+ }
48
+ }
49
+ }
50
+ }
51
+
52
+ return {
53
+ maxRowSpan,
54
+ updateMaxRowSpan
55
+ }
56
56
  }
@@ -1,123 +1,120 @@
1
- import { Ref, ref, ShallowRef, watch } from 'vue';
2
- import { ColKeyGen, MergeCellsParam, PrivateStkTableColumn, RowActiveOption, RowKeyGen, UniqKey } from './types';
3
- import { pureCellKeyGen } from './utils';
4
- type Options = {
5
- rowActiveProp: Ref<RowActiveOption<any>>;
6
- tableHeaderLast: ShallowRef<PrivateStkTableColumn<any>[]>;
7
- rowKeyGen: RowKeyGen;
8
- colKeyGen: ColKeyGen;
9
- virtual_dataSourcePart: ShallowRef<any[]>;
10
- };
11
- export function useMergeCells({ rowActiveProp, tableHeaderLast, rowKeyGen, colKeyGen, virtual_dataSourcePart }: Options) {
12
- /**
13
- * which cell need be hidden
14
- * - key: rowKey
15
- * - value: colKey Set
16
- */
17
- const hiddenCellMap = ref<Record<UniqKey, Set<UniqKey>>>({});
18
- /**
19
- * hover other row and rowspan cell should be highlighted
20
- * - key: rowKey
21
- * - value: cellKey Set
22
- */
23
- const hoverRowMap = ref<Record<UniqKey, Set<string>>>({});
24
-
25
- /** hover current row , which rowspan cells should be highlight */
26
- const hoverMergedCells = ref(new Set<string>());
27
- /** click current row , which rowspan cells should be highlight */
28
- const activeMergedCells = ref(new Set<string>());
29
-
30
- watch([virtual_dataSourcePart, tableHeaderLast], () => {
31
- hiddenCellMap.value = {};
32
- hoverRowMap.value = {};
33
- });
34
-
35
- /**
36
- * abstract the logic of hiding cells
37
- */
38
- function hideCells(rowKey: UniqKey, colKey: UniqKey, colspan: number, isSelfRow = false, mergeCellKey: string) {
39
- const startIndex = tableHeaderLast.value.findIndex(item => colKeyGen.value(item) === colKey);
40
-
41
- for (let i = startIndex; i < startIndex + colspan; i++) {
42
- if(!isSelfRow) {
43
- // if other row hovered, the rowspan cell need to be highlight
44
- if (!hoverRowMap.value[rowKey]) hoverRowMap.value[rowKey] = new Set();
45
- hoverRowMap.value[rowKey].add(mergeCellKey);
46
- }
47
- if (isSelfRow && i === startIndex) {
48
- // self row start cell does not need to be hidden
49
- continue;
50
- }
51
- const nextCol = tableHeaderLast.value[i];
52
- if (!nextCol) break;
53
- const nextColKey = colKeyGen.value(nextCol);
54
- if (!hiddenCellMap.value[rowKey]) hiddenCellMap.value[rowKey] = new Set();
55
- hiddenCellMap.value[rowKey].add(nextColKey);
56
-
57
- }
58
- }
59
-
60
- /**
61
- * calculate colspan and rowspan
62
- * @param row
63
- * @param col
64
- * @param rowIndex
65
- * @param colIndex
66
- * @returns
67
- */
68
- function mergeCellsWrapper(
69
- row: MergeCellsParam<any>['row'],
70
- col: MergeCellsParam<any>['col'],
71
- rowIndex: MergeCellsParam<any>['rowIndex'],
72
- colIndex: MergeCellsParam<any>['colIndex'],
73
- ): { colspan?: number; rowspan?: number } | undefined {
74
- if (!col.mergeCells) return;
75
-
76
- let { colspan, rowspan } = col.mergeCells({ row, col, rowIndex, colIndex }) || {};
77
-
78
- // default colspan and rowspan is 1
79
- colspan = colspan || 1;
80
- rowspan = rowspan || 1;
81
-
82
- if (colspan === 1 && rowspan === 1) return;
83
-
84
- const rowKey = rowKeyGen(row);
85
-
86
- const curRowIndex = virtual_dataSourcePart.value.findIndex(item => rowKeyGen(item) === rowKey);
87
- if (curRowIndex === -1) return;
88
-
89
- const colKey = colKeyGen.value(col);
90
- const mergedCellKey = pureCellKeyGen(rowKey, colKey);
91
-
92
- for (let i = curRowIndex; i < curRowIndex + rowspan; i++) {
93
- const row = virtual_dataSourcePart.value[i];
94
- if (!row) break;
95
- hideCells(rowKeyGen(row), colKey, colspan, i === curRowIndex, mergedCellKey);
96
- }
97
-
98
- return { colspan, rowspan };
99
- }
100
-
101
- const emptySet = new Set<string>();
102
- function updateHoverMergedCells(rowKey: UniqKey | undefined) {
103
- hoverMergedCells.value = rowKey === void 0 ? emptySet : hoverRowMap.value[rowKey] || emptySet;
104
- }
105
-
106
- function updateActiveMergedCells(clear?: boolean, rowKey?: UniqKey) {
107
- if (!rowActiveProp.value.enabled) return;
108
- if (clear) {
109
- activeMergedCells.value.clear();
110
- return;
111
- }
112
- activeMergedCells.value = (rowKey !== void 0 && hoverRowMap.value[rowKey]) || new Set(hoverMergedCells.value);
113
- }
114
-
115
- return {
116
- hiddenCellMap,
117
- mergeCellsWrapper,
118
- hoverMergedCells,
119
- updateHoverMergedCells,
120
- activeMergedCells,
121
- updateActiveMergedCells,
122
- };
123
- }
1
+ import { Ref, ref, ShallowRef, watch } from 'vue';
2
+ import { ColKeyGen, MergeCellsParam, PrivateStkTableColumn, RowActiveOption, RowKeyGen, UniqKey } from './types';
3
+ import { pureCellKeyGen } from './utils';
4
+ type Options = {
5
+ rowActiveProp: Ref<RowActiveOption<any>>;
6
+ tableHeaderLast: ShallowRef<PrivateStkTableColumn<any>[]>;
7
+ rowKeyGen: RowKeyGen;
8
+ colKeyGen: ColKeyGen;
9
+ virtual_dataSourcePart: ShallowRef<any[]>;
10
+ };
11
+ export function useMergeCells({ rowActiveProp, tableHeaderLast, rowKeyGen, colKeyGen, virtual_dataSourcePart }: Options) {
12
+ /**
13
+ * which cell need be hidden
14
+ * - key: rowKey
15
+ * - value: colKey Set
16
+ */
17
+ const hiddenCellMap = ref<Record<UniqKey, Set<UniqKey>>>({});
18
+ /**
19
+ * hover other row and rowspan cell should be highlighted
20
+ * - key: rowKey
21
+ * - value: cellKey Set
22
+ */
23
+ const hoverRowMap = ref<Record<UniqKey, Set<string>>>({});
24
+
25
+ /** hover current row , which rowspan cells should be highlight */
26
+ const hoverMergedCells = ref(new Set<string>());
27
+ /** click current row , which rowspan cells should be highlight */
28
+ const activeMergedCells = ref(new Set<string>());
29
+
30
+ watch([virtual_dataSourcePart, tableHeaderLast], () => {
31
+ hiddenCellMap.value = {};
32
+ hoverRowMap.value = {};
33
+ });
34
+
35
+ /**
36
+ * abstract the logic of hiding cells
37
+ */
38
+ function hideCells(rowKey: UniqKey, colKey: UniqKey, colspan: number, isSelfRow = false, mergeCellKey: string) {
39
+ const startIndex = tableHeaderLast.value.findIndex(item => colKeyGen.value(item) === colKey);
40
+
41
+ for (let i = startIndex; i < startIndex + colspan; i++) {
42
+ // if other row hovered, the rowspan cell need to be highlight
43
+ if (!hoverRowMap.value[rowKey]) hoverRowMap.value[rowKey] = new Set();
44
+ hoverRowMap.value[rowKey].add(mergeCellKey);
45
+ if (isSelfRow && i === startIndex) {
46
+ // self row start cell does not need to be hidden
47
+ continue;
48
+ }
49
+ const nextCol = tableHeaderLast.value[i];
50
+ if (!nextCol) break;
51
+ const nextColKey = colKeyGen.value(nextCol);
52
+ if (!hiddenCellMap.value[rowKey]) hiddenCellMap.value[rowKey] = new Set();
53
+ hiddenCellMap.value[rowKey].add(nextColKey);
54
+ }
55
+ }
56
+
57
+ /**
58
+ * calculate colspan and rowspan
59
+ * @param row
60
+ * @param col
61
+ * @param rowIndex
62
+ * @param colIndex
63
+ * @returns
64
+ */
65
+ function mergeCellsWrapper(
66
+ row: MergeCellsParam<any>['row'],
67
+ col: MergeCellsParam<any>['col'],
68
+ rowIndex: MergeCellsParam<any>['rowIndex'],
69
+ colIndex: MergeCellsParam<any>['colIndex'],
70
+ ): { colspan?: number; rowspan?: number } | undefined {
71
+ if (!col.mergeCells) return;
72
+
73
+ let { colspan, rowspan } = col.mergeCells({ row, col, rowIndex, colIndex }) || {};
74
+
75
+ // default colspan and rowspan is 1
76
+ colspan = colspan || 1;
77
+ rowspan = rowspan || 1;
78
+
79
+ if (colspan === 1 && rowspan === 1) return;
80
+
81
+ const rowKey = rowKeyGen(row);
82
+
83
+ const curRowIndex = virtual_dataSourcePart.value.findIndex(item => rowKeyGen(item) === rowKey);
84
+ if (curRowIndex === -1) return;
85
+
86
+ const colKey = colKeyGen.value(col);
87
+ const mergedCellKey = pureCellKeyGen(rowKey, colKey);
88
+
89
+ for (let i = curRowIndex; i < curRowIndex + rowspan; i++) {
90
+ const row = virtual_dataSourcePart.value[i];
91
+ if (!row) break;
92
+ hideCells(rowKeyGen(row), colKey, colspan, i === curRowIndex, mergedCellKey);
93
+ }
94
+
95
+ return { colspan, rowspan };
96
+ }
97
+
98
+ const emptySet = new Set<string>();
99
+ function updateHoverMergedCells(rowKey: UniqKey | undefined) {
100
+ hoverMergedCells.value = rowKey === void 0 ? emptySet : hoverRowMap.value[rowKey] || emptySet;
101
+ }
102
+
103
+ function updateActiveMergedCells(clear?: boolean, rowKey?: UniqKey) {
104
+ if (!rowActiveProp.value.enabled) return;
105
+ if (clear) {
106
+ activeMergedCells.value = new Set();
107
+ return;
108
+ }
109
+ activeMergedCells.value = (rowKey !== void 0 && hoverRowMap.value[rowKey]) || new Set(hoverMergedCells.value);
110
+ }
111
+
112
+ return {
113
+ hiddenCellMap,
114
+ mergeCellsWrapper,
115
+ hoverMergedCells,
116
+ updateHoverMergedCells,
117
+ activeMergedCells,
118
+ updateActiveMergedCells,
119
+ };
120
+ }