stk-table-vue 0.8.13 → 0.8.14

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/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "stk-table-vue",
3
- "version": "0.8.13",
3
+ "version": "0.8.14",
4
4
  "description": "High performance realtime virtual table for vue3 and vue2.7",
5
5
  "main": "./lib/stk-table-vue.js",
6
6
  "types": "./lib/src/StkTable/index.d.ts",
7
+ "homepage": "https://ja-plus.github.io/stk-table-vue/",
7
8
  "packageManager": "pnpm@10.7.0",
8
9
  "directories": {
9
10
  "test": "test"
@@ -62,6 +63,7 @@
62
63
  "stk-table-vue": "^0.8.7",
63
64
  "typescript": "^5.8.3",
64
65
  "vite": "^7.2.2",
66
+ "vite-plugin-banner": "^0.8.1",
65
67
  "vite-plugin-dts": "3.9.1",
66
68
  "vitepress": "^1.6.4",
67
69
  "vitepress-demo-plugin": "^1.4.7",
@@ -43,6 +43,13 @@
43
43
  :class="{
44
44
  'fixed-mode': props.fixedMode,
45
45
  }"
46
+ @dragover="onTrDragOver"
47
+ @dragenter="onTrDragEnter"
48
+ @dragend="onTrDragEnd"
49
+ @click="onRowClick"
50
+ @dblclick="onRowDblclick"
51
+ @contextmenu="onRowMenu"
52
+ @mouseover="onTrMouseOver"
46
53
  >
47
54
  <thead v-if="!headless">
48
55
  <tr v-for="(row, rowIndex) in tableHeaders" :key="rowIndex" @contextmenu="onHeaderMenu($event)">
@@ -54,34 +61,18 @@
54
61
  <th
55
62
  v-for="(col, colIndex) in virtualX_on && rowIndex === tableHeaders.length - 1 ? virtualX_columnPart : row"
56
63
  :key="colKeyGen(col)"
57
- :data-col-key="colKeyGen(col)"
58
- :draggable="isHeaderDraggable(col) ? 'true' : 'false'"
59
- :rowspan="virtualX_on ? 1 : col.__R_SP__"
60
- :colspan="col.__C_SP__"
61
- :style="cellStyleMap[TagType.TH].get(colKeyGen(col))"
62
- :title="getHeaderTitle(col)"
63
- :class="[
64
- col.sorter ? 'sortable' : '',
65
- colKeyGen(col) === sortCol && sortOrderIndex !== 0 && 'sorter-' + sortSwitchOrder[sortOrderIndex],
66
- col.headerClassName,
67
- fixedColClassMap.get(colKeyGen(col)),
68
- ]"
69
- @click="
70
- e => {
71
- onColumnSort(col);
72
- onHeaderCellClick(e, col);
73
- }
74
- "
75
- @dragstart="onThDragStart"
76
- @drop="onThDrop"
77
- @dragover="onThDragOver"
64
+ v-bind="getTHProps(col)"
65
+ @click="e => onHeaderCellClick(e, col)"
66
+ @dragstart="headerDrag ? onThDragStart : void 0"
67
+ @drop="headerDrag ? onThDrop : void 0"
68
+ @dragover="headerDrag ? onThDragOver : void 0"
78
69
  >
79
70
  <div
80
71
  v-if="colResizeOn(col) && colIndex > 0"
81
72
  class="table-header-resizer left"
82
73
  @mousedown="onThResizeMouseDown($event, col, true)"
83
74
  ></div>
84
- <div class="table-header-cell-wrapper" :style="{ '--row-span': virtualX_on ? 1 : col.__R_SP__ }">
75
+ <div class="table-header-cell-wrapper" :style="`--row-span:${virtualX_on ? 1 : col.__R_SP__}`">
85
76
  <component :is="col.customHeaderCell" v-if="col.customHeaderCell" :col="col" :colIndex="colIndex" :rowIndex="rowIndex" />
86
77
  <template v-else>
87
78
  <slot name="tableHeader" :col="col">
@@ -96,7 +87,7 @@
96
87
  </tr>
97
88
  </thead>
98
89
 
99
- <tbody class="stk-tbody-main" @dragover="onTrDragOver" @dragenter="onTrDragEnter" @dragend="onTrDragEnd">
90
+ <tbody class="stk-tbody-main" @click="onCellClick" @mousedown="onCellMouseDown" @mouseover="onCellMouseOver">
100
91
  <tr v-if="virtual_on && !isSRBRActive" :style="`height:${virtualScroll.offsetTop}px`" class="padding-top-tr">
101
92
  <td v-if="virtualX_on && fixedMode && headless" class="vt-x-left"></td>
102
93
  <template v-if="fixedMode && headless">
@@ -105,26 +96,11 @@
105
96
  </tr>
106
97
  <tr
107
98
  v-for="(row, rowIndex) in virtual_dataSourcePart"
108
- :id="stkTableId + '-' + (rowKey ? rowKeyGen(row) : getRowIndex(rowIndex))"
109
99
  ref="trRef"
110
- :key="rowKey ? rowKeyGen(row) : getRowIndex(rowIndex)"
111
- :data-row-key="rowKey ? rowKeyGen(row) : getRowIndex(rowIndex)"
112
- :class="{
113
- active: rowKey ? rowKeyGen(row) === currentRowKey : row === currentRow,
114
- hover: props.showTrHoverClass && (rowKey ? rowKeyGen(row) === currentHoverRowKey : row === currentHoverRowKey),
115
- [rowClassName(row, getRowIndex(rowIndex)) || '']: true,
116
- expanded: row && row.__EXP__,
117
- 'expanded-row': row && row.__EXP_R__,
118
- }"
119
- :style="{
120
- '--row-height': row && row.__EXP_R__ && props.virtual && props.expandConfig?.height && props.expandConfig?.height + 'px',
121
- }"
122
- @click="onRowClick($event, row, getRowIndex(rowIndex))"
123
- @dblclick="onRowDblclick($event, row, getRowIndex(rowIndex))"
124
- @contextmenu="onRowMenu($event, row, getRowIndex(rowIndex))"
125
- @mouseover="onTrMouseOver($event, row)"
126
- @mouseleave="onTrMouseLeave($event)"
100
+ :key="rowKeyGen(row)"
101
+ v-bind="getTRProps(row, rowIndex)"
127
102
  @drop="onTrDrop($event, getRowIndex(rowIndex))"
103
+ @mouseleave="onTrMouseLeave"
128
104
  >
129
105
  <td v-if="virtualX_on" class="vt-x-left"></td>
130
106
  <td v-if="row && row.__EXP_R__" :colspan="virtualX_columnPart.length">
@@ -139,15 +115,9 @@
139
115
  <td
140
116
  v-if="!hiddenCellMap[rowKeyGen(row)]?.has(colKeyGen(col))"
141
117
  :key="colKeyGen(col)"
142
- v-bind="{
143
- ...getTDProps(row, col),
144
- ...mergeCellsWrapper(row, col, rowIndex, colIndex),
145
- }"
146
- @click="onCellClick($event, row, col, getRowIndex(rowIndex))"
147
- @mousedown="onCellMouseDown($event, row, col, getRowIndex(rowIndex))"
148
- @mouseenter="onCellMouseEnter($event, row, col)"
149
- @mouseleave="onCellMouseLeave($event, row, col)"
150
- @mouseover="onCellMouseOver($event, row, col)"
118
+ v-bind="getTDProps(row, col, rowIndex, colIndex)"
119
+ @mouseenter="onCellMouseEnter"
120
+ @mouseleave="onCellMouseLeave"
151
121
  >
152
122
  <component
153
123
  :is="col.customCell"
@@ -172,7 +142,7 @@
172
142
  v-else
173
143
  class="table-cell-wrapper"
174
144
  :title="col.type !== 'seq' ? row?.[col.dataIndex] : ''"
175
- :style="col.type === 'tree-node' ? { paddingLeft: row.__T_LV__ && row.__T_LV__ * 16 + 'px' } : {}"
145
+ :style="col.type === 'tree-node' && row.__T_LV__ ? `padding-left:${row.__T_LV__ * 16}px` : ''"
176
146
  >
177
147
  <template v-if="col.type === 'seq'">
178
148
  {{ (props.seqConfig.startIndex || 0) + getRowIndex(rowIndex) + 1 }}
@@ -199,6 +169,7 @@
199
169
  </td>
200
170
  </template>
201
171
  </template>
172
+ <td v-if="virtualX_on" class="vt-x-right"></td>
202
173
  </tr>
203
174
  <tr v-if="virtual_on && !isSRBRActive" :style="`height: ${virtual_offsetBottom}px`"></tr>
204
175
  <tr v-if="SRBRBottomHeight" :style="`height: ${SRBRBottomHeight}px`"></tr>
@@ -263,7 +234,7 @@ import { useTrDrag } from './useTrDrag';
263
234
  import { useTree } from './useTree';
264
235
  import { useVirtualScroll } from './useVirtualScroll';
265
236
  import { createStkTableId, getCalculatedColWidth, getColWidth } from './utils/constRefUtils';
266
- import { howDeepTheHeader, isEmptyValue, tableSort, transformWidthToStr } from './utils/index';
237
+ import { getClosestColKey, getClosestTr, getClosestTrIndex, howDeepTheHeader, isEmptyValue, tableSort, transformWidthToStr } from './utils/index';
267
238
 
268
239
  /** Generic stands for DataType */
269
240
  type DT = any & PrivateRowDT;
@@ -631,7 +602,7 @@ const currentSelectedCellKey = ref<string | undefined>();
631
602
  /** 当前hover行 */
632
603
  let currentHoverRow: DT | null = null;
633
604
  /** 当前hover的行的key */
634
- const currentHoverRowKey = ref(null);
605
+ const currentHoverRowKey = ref<UniqKey | null>(null);
635
606
  /** 当前hover的列的key */
636
607
  // const currentColHoverKey = ref(null);
637
608
 
@@ -1026,9 +997,7 @@ function updateDataSource(val: DT[]) {
1026
997
  }
1027
998
  }
1028
999
 
1029
- /**
1030
- * 行唯一值生成
1031
- */
1000
+ /** tr key */
1032
1001
  function rowKeyGen(row: DT | null | undefined) {
1033
1002
  if (!row) return row;
1034
1003
  let key = rowKeyGenCache.get(row) || (row as PrivateRowDT).__ROW_K__;
@@ -1044,12 +1013,11 @@ function rowKeyGen(row: DT | null | undefined) {
1044
1013
  return key;
1045
1014
  }
1046
1015
 
1047
- /** 单元格唯一值 */
1016
+ /** td key */
1048
1017
  function cellKeyGen(row: DT | null | undefined, col: StkTableColumn<DT>) {
1049
1018
  return rowKeyGen(row) + CELL_KEY_SEPARATE + colKeyGen.value(col);
1050
1019
  }
1051
1020
 
1052
- /** 单元格样式 */
1053
1021
  const cellStyleMap = computed(() => {
1054
1022
  const thMap = new Map();
1055
1023
  const tdMap = new Map();
@@ -1080,9 +1048,8 @@ const cellStyleMap = computed(() => {
1080
1048
  });
1081
1049
 
1082
1050
  function getRowIndex(rowIndex: number) {
1083
- return rowIndex + (virtual_on.value ? virtualScroll.value.startIndex : 0);
1051
+ return rowIndex + virtualScroll.value.startIndex;
1084
1052
  }
1085
-
1086
1053
  /** th title */
1087
1054
  function getHeaderTitle(col: StkTableColumn<DT>): string {
1088
1055
  const colKey = colKeyGen.value(col);
@@ -1093,7 +1060,53 @@ function getHeaderTitle(col: StkTableColumn<DT>): string {
1093
1060
  return col.title || '';
1094
1061
  }
1095
1062
 
1096
- function getTDProps(row: PrivateRowDT | null | undefined, col: StkTableColumn<PrivateRowDT>) {
1063
+ function getTRProps(row: PrivateRowDT | null | undefined, index: number) {
1064
+ const rowIndex = getRowIndex(index);
1065
+ const rowKey = rowKeyGen(row);
1066
+
1067
+ let classStr = props.rowClassName(row, rowIndex) || '' + ' ' + (row?.__EXP__ ? 'expanded' : '') + ' ' + (row?.__EXP_R__ ? 'expanded-row' : '');
1068
+ if (currentRowKey.value === rowKey || row === currentRow.value) {
1069
+ classStr += ' active';
1070
+ }
1071
+ if (props.showTrHoverClass && (rowKey === currentHoverRowKey.value || row === currentHoverRow)) {
1072
+ classStr += ' hover';
1073
+ }
1074
+
1075
+ const result = {
1076
+ id: stkTableId + '-' + rowKey,
1077
+ 'data-row-key': rowKey,
1078
+ 'data-row-i': rowIndex,
1079
+ class: classStr,
1080
+ style: '',
1081
+ };
1082
+
1083
+ const needRowHeight = row?.__EXP_R__ && props.virtual && props.expandConfig?.height;
1084
+
1085
+ if (needRowHeight) {
1086
+ result.style = `--row-height: ${props.expandConfig?.height}px`;
1087
+ }
1088
+ return result;
1089
+ }
1090
+
1091
+ function getTHProps(col: PrivateStkTableColumn<DT>) {
1092
+ const colKey = colKeyGen.value(col);
1093
+ return {
1094
+ 'data-col-key': colKey,
1095
+ draggable: Boolean(isHeaderDraggable(col)),
1096
+ rowspan: virtualX_on.value ? 1 : col.__R_SP__,
1097
+ colspan: col.__C_SP__,
1098
+ style: cellStyleMap.value[TagType.TH].get(colKey),
1099
+ title: getHeaderTitle(col),
1100
+ class: [
1101
+ col.sorter ? 'sortable' : '',
1102
+ colKey === sortCol.value && sortOrderIndex.value !== 0 && 'sorter-' + sortSwitchOrder[sortOrderIndex.value],
1103
+ col.headerClassName,
1104
+ fixedColClassMap.value.get(colKey),
1105
+ ],
1106
+ };
1107
+ }
1108
+
1109
+ function getTDProps(row: PrivateRowDT | null | undefined, col: StkTableColumn<PrivateRowDT>, rowIndex: number, colIndex: number) {
1097
1110
  const colKey = colKeyGen.value(col);
1098
1111
  if (!row) {
1099
1112
  return {
@@ -1102,8 +1115,7 @@ function getTDProps(row: PrivateRowDT | null | undefined, col: StkTableColumn<Pr
1102
1115
  }
1103
1116
 
1104
1117
  const cellKey = cellKeyGen(row, col);
1105
-
1106
- const classList = [col.className, fixedColClassMap.value.get(colKeyGen.value(col))];
1118
+ const classList = [col.className, fixedColClassMap.value.get(colKey)];
1107
1119
  if (col.mergeCells) {
1108
1120
  if (hoverMergedCells.value.has(cellKey)) {
1109
1121
  classList.push('cell-hover');
@@ -1119,23 +1131,26 @@ function getTDProps(row: PrivateRowDT | null | undefined, col: StkTableColumn<Pr
1119
1131
 
1120
1132
  if (col.type === 'seq') {
1121
1133
  classList.push('seq-column');
1122
- } else if (col.type === 'expand' && (row.__EXP__ ? colKeyGen.value(row.__EXP__) === colKeyGen.value(col) : false)) {
1134
+ } else if (col.type === 'expand' && (row.__EXP__ ? colKeyGen.value(row.__EXP__) === colKey : false)) {
1123
1135
  classList.push('expanded');
1124
- } else if (col.type === 'tree-node' && row.__T_EXP__) {
1136
+ } else if (row.__T_EXP__ && col.type === 'tree-node') {
1125
1137
  classList.push('tree-expanded');
1126
1138
  } else if (col.type === 'dragRow') {
1127
1139
  classList.push('drag-row-cell');
1128
1140
  }
1129
1141
 
1130
1142
  return {
1131
- 'data-cell-key': cellKey,
1143
+ 'data-col-key': colKey,
1132
1144
  style: cellStyleMap.value[TagType.TD].get(colKey),
1133
1145
  class: classList,
1146
+ ...mergeCellsWrapper(row, col, rowIndex, colIndex),
1134
1147
  };
1135
1148
  }
1136
1149
 
1137
1150
  /**
1138
1151
  * 表头点击排序
1152
+ *
1153
+ * en: Sort a column
1139
1154
  * @param click 是否为点击表头触发
1140
1155
  * @param options.force sort-remote 开启后是否强制排序
1141
1156
  * @param options.emit 是否触发回调
@@ -1202,7 +1217,10 @@ function onColumnSort(col: StkTableColumn<DT> | undefined | null, click = true,
1202
1217
  }
1203
1218
  }
1204
1219
 
1205
- function onRowClick(e: MouseEvent, row: DT, rowIndex: number) {
1220
+ function onRowClick(e: MouseEvent) {
1221
+ const rowIndex = getClosestTrIndex(e);
1222
+ const row = dataSourceCopy.value[rowIndex];
1223
+ if (!row) return;
1206
1224
  emits('row-click', e, row, { rowIndex });
1207
1225
  if (rowActiveProp.value.disabled?.(row)) return;
1208
1226
  const isCurrentRow = props.rowKey ? currentRowKey.value === rowKeyGen(row) : currentRow.value === row;
@@ -1217,50 +1235,24 @@ function onRowClick(e: MouseEvent, row: DT, rowIndex: number) {
1217
1235
  emits('current-change', e, row, { select: !isCurrentRow });
1218
1236
  }
1219
1237
 
1220
- function onRowDblclick(e: MouseEvent, row: DT, rowIndex: number) {
1238
+ function onRowDblclick(e: MouseEvent) {
1239
+ const rowIndex = getClosestTrIndex(e);
1240
+ const row = dataSourceCopy.value[rowIndex];
1241
+ if (!row) return;
1221
1242
  emits('row-dblclick', e, row, { rowIndex });
1222
1243
  }
1223
1244
 
1224
- /** 表头行右键 */
1225
1245
  function onHeaderMenu(e: MouseEvent) {
1226
1246
  emits('header-row-menu', e);
1227
1247
  }
1228
1248
 
1229
- /** 表体行右键 */
1230
- function onRowMenu(e: MouseEvent, row: DT, rowIndex: number) {
1249
+ function onRowMenu(e: MouseEvent) {
1250
+ const rowIndex = getClosestTrIndex(e);
1251
+ const row = dataSourceCopy.value[rowIndex];
1252
+ if (!row) return;
1231
1253
  emits('row-menu', e, row, { rowIndex });
1232
1254
  }
1233
1255
 
1234
- /**
1235
- * proxy events
1236
- */
1237
- // function onTbodyClick(e: MouseEvent, type: 1 | 2) {
1238
- // const el = (e.target as HTMLElement).closest<HTMLElement>('td,tr');
1239
- // if (!el) return;
1240
- // if (el.tagName === 'TD') {
1241
- // const [rowKey, colKey] = el.dataset.cellKey?.split(CELL_KEY_SEPARATE) || [];
1242
- // const row = dataSourceCopy.value.find(item => rowKeyGen(item) === rowKey);
1243
- // const col = tableHeaderLast.value.find(item => colKeyGen.value(item) === colKey);
1244
- // if (col) {
1245
- // if (col.type === 'expand') {
1246
- // toggleExpandRow(row, col);
1247
- // }
1248
- // if (type === 1) {
1249
- // onCellClick(e, row, col);
1250
- // } else if (type === 2) {
1251
- // onCellMouseDown(e, row, col);
1252
- // }
1253
- // }
1254
- // if (type === 1) {
1255
- // onRowClick(e, row);
1256
- // }
1257
- // } else if (el.tagName === 'TR') {
1258
- // const rowKey = el.dataset.rowKey;
1259
- // const row = dataSourceCopy.value.find(item => rowKeyGen(item) === rowKey);
1260
- // onRowClick(e, row);
1261
- // }
1262
- // }
1263
-
1264
1256
  function triangleClick(e: MouseEvent, row: DT, col: StkTableColumn<DT>) {
1265
1257
  if (col.type === 'expand') {
1266
1258
  toggleExpandRow(row, col);
@@ -1269,8 +1261,13 @@ function triangleClick(e: MouseEvent, row: DT, col: StkTableColumn<DT>) {
1269
1261
  }
1270
1262
  }
1271
1263
 
1272
- /** 单元格单击 */
1273
- function onCellClick(e: MouseEvent, row: DT, col: StkTableColumn<DT>, rowIndex: number) {
1264
+ function onCellClick(e: MouseEvent) {
1265
+ const rowIndex = getClosestTrIndex(e);
1266
+ const row = dataSourceCopy.value[rowIndex];
1267
+ if (!row) return;
1268
+ const colKey = getClosestColKey(e);
1269
+ const col = tableHeaderLast.value.find(item => colKeyGen.value(item) === colKey);
1270
+ if (!col) return;
1274
1271
  if (props.cellActive) {
1275
1272
  const cellKey = cellKeyGen(row, col);
1276
1273
  const result = { row, col, select: false, rowIndex };
@@ -1285,27 +1282,39 @@ function onCellClick(e: MouseEvent, row: DT, col: StkTableColumn<DT>, rowIndex:
1285
1282
  emits('cell-click', e, row, col, { rowIndex });
1286
1283
  }
1287
1284
 
1288
- /** 表头单元格单击 */
1285
+ function getCellEventData(e: MouseEvent) {
1286
+ const rowIndex = getClosestTrIndex(e) || 0;
1287
+ const row = dataSourceCopy.value[rowIndex];
1288
+ const colKey = getClosestColKey(e);
1289
+ const col = tableHeaderLast.value.find(item => colKeyGen.value(item) === colKey) as any;
1290
+ return { row, col, rowIndex };
1291
+ }
1292
+
1293
+ /** th click */
1289
1294
  function onHeaderCellClick(e: MouseEvent, col: StkTableColumn<DT>) {
1295
+ onColumnSort(col);
1290
1296
  emits('header-cell-click', e, col);
1291
1297
  }
1292
1298
 
1293
1299
  /** td mouseenter */
1294
- function onCellMouseEnter(e: MouseEvent, row: DT, col: StkTableColumn<DT>) {
1300
+ function onCellMouseEnter(e: MouseEvent) {
1301
+ const { row, col } = getCellEventData(e);
1295
1302
  emits('cell-mouseenter', e, row, col);
1296
1303
  }
1297
1304
 
1298
1305
  /** td mouseleave */
1299
- function onCellMouseLeave(e: MouseEvent, row: DT, col: StkTableColumn<DT>) {
1306
+ function onCellMouseLeave(e: MouseEvent) {
1307
+ const { row, col } = getCellEventData(e);
1300
1308
  emits('cell-mouseleave', e, row, col);
1301
1309
  }
1302
-
1303
1310
  /** td mouseover event */
1304
- function onCellMouseOver(e: MouseEvent, row: DT, col: StkTableColumn<DT>) {
1311
+ function onCellMouseOver(e: MouseEvent) {
1312
+ const { row, col } = getCellEventData(e);
1305
1313
  emits('cell-mouseover', e, row, col);
1306
1314
  }
1307
1315
 
1308
- function onCellMouseDown(e: MouseEvent, row: DT, col: StkTableColumn<DT>, rowIndex: number) {
1316
+ function onCellMouseDown(e: MouseEvent) {
1317
+ const { row, col, rowIndex } = getCellEventData(e);
1309
1318
  emits('cell-mousedown', e, row, col, { rowIndex });
1310
1319
  }
1311
1320
 
@@ -1323,22 +1332,21 @@ function onTableWheel(e: WheelEvent) {
1323
1332
  return;
1324
1333
  }
1325
1334
  const dom = tableContainerRef.value;
1326
- if (!dom) return;
1327
- if (!virtual_on.value && !virtualX_on.value) return;
1335
+ if ((!virtual_on.value && !virtualX_on.value) || !dom) return;
1328
1336
 
1329
- const { containerHeight, scrollTop, scrollHeight } = virtualScroll.value;
1330
- const { containerWidth, scrollLeft, scrollWidth } = virtualScrollX.value;
1331
- const isScrollBottom = scrollHeight - containerHeight - scrollTop < 10;
1332
- const isScrollRight = scrollWidth - containerWidth - scrollLeft < 10;
1333
1337
  const { deltaY, deltaX, shiftKey } = e;
1334
1338
 
1335
1339
  if (virtual_on.value && deltaY && !shiftKey) {
1340
+ const { containerHeight, scrollTop, scrollHeight } = virtualScroll.value;
1341
+ const isScrollBottom = scrollHeight - containerHeight - scrollTop < 10;
1336
1342
  if ((deltaY > 0 && !isScrollBottom) || (deltaY < 0 && scrollTop > 0)) {
1337
1343
  e.preventDefault(); // parent element scroll
1338
1344
  }
1339
1345
  dom.scrollTop += deltaY;
1340
1346
  }
1341
1347
  if (virtualX_on.value) {
1348
+ const { containerWidth, scrollLeft, scrollWidth } = virtualScrollX.value;
1349
+ const isScrollRight = scrollWidth - containerWidth - scrollLeft < 10;
1342
1350
  let distance = deltaX;
1343
1351
  if (shiftKey && deltaY) {
1344
1352
  distance = deltaY;
@@ -1362,12 +1370,10 @@ function onTableScroll(e: Event) {
1362
1370
  const isYScroll = scrollTop !== vScrollTop;
1363
1371
  const isXScroll = scrollLeft !== vScrollLeft;
1364
1372
 
1365
- // 纵向滚动有变化
1366
1373
  if (isYScroll) {
1367
1374
  updateVirtualScrollY(scrollTop);
1368
1375
  }
1369
1376
 
1370
- // 横向滚动有变化
1371
1377
  if (isXScroll) {
1372
1378
  if (virtualX_on.value) {
1373
1379
  updateVirtualScrollX(scrollLeft);
@@ -1388,12 +1394,16 @@ function onTableScroll(e: Event) {
1388
1394
  }
1389
1395
 
1390
1396
  /** tr hover */
1391
- function onTrMouseOver(_e: MouseEvent, row: DT) {
1397
+ function onTrMouseOver(e: MouseEvent) {
1398
+ const tr = getClosestTr(e);
1399
+ if (!tr) return;
1400
+ const rowIndex = Number(tr.dataset.rowI);
1401
+ const row = dataSourceCopy.value[rowIndex];
1392
1402
  if (currentHoverRow === row) return;
1393
1403
  currentHoverRow = row;
1394
- const rowKey = rowKeyGen(row);
1404
+ const rowKey = tr.dataset.rowKey;
1395
1405
  if (props.showTrHoverClass) {
1396
- currentHoverRowKey.value = rowKey;
1406
+ currentHoverRowKey.value = rowKey || null;
1397
1407
  }
1398
1408
  if (props.rowHover) {
1399
1409
  updateHoverMergedCells(rowKey);
@@ -1401,7 +1411,7 @@ function onTrMouseOver(_e: MouseEvent, row: DT) {
1401
1411
  }
1402
1412
 
1403
1413
  function onTrMouseLeave(e: MouseEvent) {
1404
- if ((e.target as HTMLTableRowElement).tagName !== 'TR') return;
1414
+ if ((e.target as HTMLElement).tagName !== 'TR') return;
1405
1415
  currentHoverRow = null;
1406
1416
  if (props.showTrHoverClass) {
1407
1417
  currentHoverRowKey.value = null;
@@ -1413,6 +1423,8 @@ function onTrMouseLeave(e: MouseEvent) {
1413
1423
 
1414
1424
  /**
1415
1425
  * 选中一行
1426
+ *
1427
+ * en: Select a row
1416
1428
  * @param {string} rowKeyOrRow selected rowKey, undefined to unselect
1417
1429
  * @param {boolean} option.silent if set true not emit `current-change`. default:false
1418
1430
  * @param {boolean} option.deep if set true, deep search in children. default:false
@@ -356,8 +356,6 @@
356
356
  .vt-x-left,
357
357
  .vt-x-right {
358
358
  padding: 0;
359
- background: none;
360
- pointer-events: none;
361
359
  }
362
360
 
363
361
  /** 列宽调整指示器 */
@@ -40,18 +40,20 @@ export function useFixedCol<DT extends Record<string, any>>({
40
40
  tableHeaders.value.forEach(cols => {
41
41
  cols.forEach(col => {
42
42
  const fixed = col.fixed;
43
- const showShadow = fixedColShadow && fixed && fixedShadowColsValue.includes(col);
44
- const classObj: Record<string, any> = {
45
- 'fixed-cell--active': fixedColsValue.includes(col), // 表示该列正在被固定
46
- };
43
+ const showShadow = fixed && fixedColShadow && fixedShadowColsValue.includes(col);
44
+ const classList = [];
45
+ if (fixedColsValue.includes(col)) {
46
+ // 表示该列正在被固定
47
+ classList.push('fixed-cell--active');
48
+ }
47
49
  if (fixed) {
48
- classObj['fixed-cell'] = true;
49
- classObj['fixed-cell--' + fixed] = true;
50
+ classList.push('fixed-cell');
51
+ classList.push('fixed-cell--' + fixed);
50
52
  }
51
53
  if (showShadow) {
52
- classObj['fixed-cell--shadow'] = true;
54
+ classList.push('fixed-cell--shadow');
53
55
  }
54
- colMap.set(colKey(col), classObj);
56
+ colMap.set(colKey(col), classList);
55
57
  });
56
58
  });
57
59
  return colMap;
@@ -108,7 +108,7 @@ export function useHighlight({ props, stkTableId, tableContainerRef }: Params) {
108
108
  * @param option.duration 动画时长。method='css'状态下,用于移除class,如果传入了className则需要与自定义的动画时间一致。
109
109
  */
110
110
  function setHighlightDimCell(rowKeyValue: UniqKey, colKeyValue: string, option: HighlightDimCellOption = {}) {
111
- const cellEl = tableContainerRef.value?.querySelector<HTMLElement>(`[data-cell-key="${pureCellKeyGen(rowKeyValue, colKeyValue)}"]`);
111
+ const cellEl = tableContainerRef.value?.querySelector<HTMLElement>(`[data-row-key="${rowKeyValue}"] [data-col-key="${colKeyValue}"]`);
112
112
  if (!cellEl) return;
113
113
  const { className, method, duration, keyframe } = {
114
114
  className: HIGHLIGHT_CELL_CLASS,
@@ -39,11 +39,9 @@ export function useMergeCells({ rowActiveProp, tableHeaderLast, rowKeyGen, colKe
39
39
  const startIndex = tableHeaderLast.value.findIndex(item => colKeyGen.value(item) === colKey);
40
40
 
41
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
- }
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);
47
45
  if (isSelfRow && i === startIndex) {
48
46
  // self row start cell does not need to be hidden
49
47
  continue;
@@ -53,7 +51,6 @@ export function useMergeCells({ rowActiveProp, tableHeaderLast, rowKeyGen, colKe
53
51
  const nextColKey = colKeyGen.value(nextCol);
54
52
  if (!hiddenCellMap.value[rowKey]) hiddenCellMap.value[rowKey] = new Set();
55
53
  hiddenCellMap.value[rowKey].add(nextColKey);
56
-
57
54
  }
58
55
  }
59
56
 
@@ -106,7 +103,7 @@ export function useMergeCells({ rowActiveProp, tableHeaderLast, rowKeyGen, colKe
106
103
  function updateActiveMergedCells(clear?: boolean, rowKey?: UniqKey) {
107
104
  if (!rowActiveProp.value.enabled) return;
108
105
  if (clear) {
109
- activeMergedCells.value.clear();
106
+ activeMergedCells.value = new Set();
110
107
  return;
111
108
  }
112
109
  activeMergedCells.value = (rowKey !== void 0 && hoverRowMap.value[rowKey]) || new Set(hoverMergedCells.value);