stk-table-vue 0.8.12 → 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/lib/style.css CHANGED
@@ -1,3 +1,11 @@
1
+ /**
2
+ * name: stk-table-vue
3
+ * version: v0.8.13
4
+ * description: High performance realtime virtual table for vue3 and vue2.7
5
+ * author: japlus
6
+ * homepage: https://ja-plus.github.io/stk-table-vue/
7
+ * license: MIT
8
+ */
1
9
  @keyframes stk-table-dim{
2
10
  from{
3
11
  background-color:var(--highlight-color);
@@ -242,8 +250,6 @@
242
250
  .stk-table .vt-x-left,
243
251
  .stk-table .vt-x-right{
244
252
  padding:0;
245
- background:none;
246
- pointer-events:none;
247
253
  }
248
254
  .stk-table .column-resize-indicator{
249
255
  width:0;
package/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "stk-table-vue",
3
- "version": "0.8.12",
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,27 +115,9 @@
139
115
  <td
140
116
  v-if="!hiddenCellMap[rowKeyGen(row)]?.has(colKeyGen(col))"
141
117
  :key="colKeyGen(col)"
142
- :data-cell-key="cellKeyGen(row, col)"
143
- :style="cellStyleMap[TagType.TD].get(colKeyGen(col))"
144
- :class="[
145
- col.className,
146
- fixedColClassMap.get(colKeyGen(col)),
147
- {
148
- 'cell-hover': col.mergeCells && hoverMergedCells.has(cellKeyGen(row, col)),
149
- 'cell-active': col.mergeCells && activeMergedCells.has(cellKeyGen(row, col)),
150
- 'seq-column': col.type === 'seq',
151
- active: props.cellActive && currentSelectedCellKey === cellKeyGen(row, col),
152
- expanded: col.type === 'expand' && (row.__EXP__ ? colKeyGen(row.__EXP__) === colKeyGen(col) : false),
153
- 'tree-expanded': col.type === 'tree-node' && row.__T_EXP__,
154
- 'drag-row-cell': col.type === 'dragRow',
155
- },
156
- ]"
157
- v-bind="mergeCellsWrapper(row, col, rowIndex, colIndex)"
158
- @click="onCellClick($event, row, col, getRowIndex(rowIndex))"
159
- @mousedown="onCellMouseDown($event, row, col, getRowIndex(rowIndex))"
160
- @mouseenter="onCellMouseEnter($event, row, col)"
161
- @mouseleave="onCellMouseLeave($event, row, col)"
162
- @mouseover="onCellMouseOver($event, row, col)"
118
+ v-bind="getTDProps(row, col, rowIndex, colIndex)"
119
+ @mouseenter="onCellMouseEnter"
120
+ @mouseleave="onCellMouseLeave"
163
121
  >
164
122
  <component
165
123
  :is="col.customCell"
@@ -184,7 +142,7 @@
184
142
  v-else
185
143
  class="table-cell-wrapper"
186
144
  :title="col.type !== 'seq' ? row?.[col.dataIndex] : ''"
187
- :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` : ''"
188
146
  >
189
147
  <template v-if="col.type === 'seq'">
190
148
  {{ (props.seqConfig.startIndex || 0) + getRowIndex(rowIndex) + 1 }}
@@ -211,6 +169,7 @@
211
169
  </td>
212
170
  </template>
213
171
  </template>
172
+ <td v-if="virtualX_on" class="vt-x-right"></td>
214
173
  </tr>
215
174
  <tr v-if="virtual_on && !isSRBRActive" :style="`height: ${virtual_offsetBottom}px`"></tr>
216
175
  <tr v-if="SRBRBottomHeight" :style="`height: ${SRBRBottomHeight}px`"></tr>
@@ -275,7 +234,7 @@ import { useTrDrag } from './useTrDrag';
275
234
  import { useTree } from './useTree';
276
235
  import { useVirtualScroll } from './useVirtualScroll';
277
236
  import { createStkTableId, getCalculatedColWidth, getColWidth } from './utils/constRefUtils';
278
- import { howDeepTheHeader, isEmptyValue, tableSort, transformWidthToStr } from './utils/index';
237
+ import { getClosestColKey, getClosestTr, getClosestTrIndex, howDeepTheHeader, isEmptyValue, tableSort, transformWidthToStr } from './utils/index';
279
238
 
280
239
  /** Generic stands for DataType */
281
240
  type DT = any & PrivateRowDT;
@@ -376,7 +335,7 @@ const props = withDefaults(
376
335
  * "v" - 仅展示竖线
377
336
  * "body-v" - 仅表体展示竖线
378
337
  */
379
- bordered?: boolean | 'h' | 'v' | 'body-v';
338
+ bordered?: boolean | 'h' | 'v' | 'body-v' | 'body-h';
380
339
  /**
381
340
  * 自动重新计算虚拟滚动高度宽度。默认true
382
341
  * [非响应式]
@@ -643,7 +602,7 @@ const currentSelectedCellKey = ref<string | undefined>();
643
602
  /** 当前hover行 */
644
603
  let currentHoverRow: DT | null = null;
645
604
  /** 当前hover的行的key */
646
- const currentHoverRowKey = ref(null);
605
+ const currentHoverRowKey = ref<UniqKey | null>(null);
647
606
  /** 当前hover的列的key */
648
607
  // const currentColHoverKey = ref(null);
649
608
 
@@ -1038,9 +997,7 @@ function updateDataSource(val: DT[]) {
1038
997
  }
1039
998
  }
1040
999
 
1041
- /**
1042
- * 行唯一值生成
1043
- */
1000
+ /** tr key */
1044
1001
  function rowKeyGen(row: DT | null | undefined) {
1045
1002
  if (!row) return row;
1046
1003
  let key = rowKeyGenCache.get(row) || (row as PrivateRowDT).__ROW_K__;
@@ -1056,12 +1013,11 @@ function rowKeyGen(row: DT | null | undefined) {
1056
1013
  return key;
1057
1014
  }
1058
1015
 
1059
- /** 单元格唯一值 */
1016
+ /** td key */
1060
1017
  function cellKeyGen(row: DT | null | undefined, col: StkTableColumn<DT>) {
1061
1018
  return rowKeyGen(row) + CELL_KEY_SEPARATE + colKeyGen.value(col);
1062
1019
  }
1063
1020
 
1064
- /** 单元格样式 */
1065
1021
  const cellStyleMap = computed(() => {
1066
1022
  const thMap = new Map();
1067
1023
  const tdMap = new Map();
@@ -1092,9 +1048,8 @@ const cellStyleMap = computed(() => {
1092
1048
  });
1093
1049
 
1094
1050
  function getRowIndex(rowIndex: number) {
1095
- return rowIndex + (virtual_on.value ? virtualScroll.value.startIndex : 0);
1051
+ return rowIndex + virtualScroll.value.startIndex;
1096
1052
  }
1097
-
1098
1053
  /** th title */
1099
1054
  function getHeaderTitle(col: StkTableColumn<DT>): string {
1100
1055
  const colKey = colKeyGen.value(col);
@@ -1105,8 +1060,97 @@ function getHeaderTitle(col: StkTableColumn<DT>): string {
1105
1060
  return col.title || '';
1106
1061
  }
1107
1062
 
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) {
1110
+ const colKey = colKeyGen.value(col);
1111
+ if (!row) {
1112
+ return {
1113
+ style: cellStyleMap.value[TagType.TD].get(colKey),
1114
+ };
1115
+ }
1116
+
1117
+ const cellKey = cellKeyGen(row, col);
1118
+ const classList = [col.className, fixedColClassMap.value.get(colKey)];
1119
+ if (col.mergeCells) {
1120
+ if (hoverMergedCells.value.has(cellKey)) {
1121
+ classList.push('cell-hover');
1122
+ }
1123
+ if (activeMergedCells.value.has(cellKey)) {
1124
+ classList.push('cell-active');
1125
+ }
1126
+ }
1127
+
1128
+ if (props.cellActive && currentSelectedCellKey.value === cellKey) {
1129
+ classList.push('active');
1130
+ }
1131
+
1132
+ if (col.type === 'seq') {
1133
+ classList.push('seq-column');
1134
+ } else if (col.type === 'expand' && (row.__EXP__ ? colKeyGen.value(row.__EXP__) === colKey : false)) {
1135
+ classList.push('expanded');
1136
+ } else if (row.__T_EXP__ && col.type === 'tree-node') {
1137
+ classList.push('tree-expanded');
1138
+ } else if (col.type === 'dragRow') {
1139
+ classList.push('drag-row-cell');
1140
+ }
1141
+
1142
+ return {
1143
+ 'data-col-key': colKey,
1144
+ style: cellStyleMap.value[TagType.TD].get(colKey),
1145
+ class: classList,
1146
+ ...mergeCellsWrapper(row, col, rowIndex, colIndex),
1147
+ };
1148
+ }
1149
+
1108
1150
  /**
1109
1151
  * 表头点击排序
1152
+ *
1153
+ * en: Sort a column
1110
1154
  * @param click 是否为点击表头触发
1111
1155
  * @param options.force sort-remote 开启后是否强制排序
1112
1156
  * @param options.emit 是否触发回调
@@ -1173,7 +1217,10 @@ function onColumnSort(col: StkTableColumn<DT> | undefined | null, click = true,
1173
1217
  }
1174
1218
  }
1175
1219
 
1176
- 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;
1177
1224
  emits('row-click', e, row, { rowIndex });
1178
1225
  if (rowActiveProp.value.disabled?.(row)) return;
1179
1226
  const isCurrentRow = props.rowKey ? currentRowKey.value === rowKeyGen(row) : currentRow.value === row;
@@ -1188,50 +1235,24 @@ function onRowClick(e: MouseEvent, row: DT, rowIndex: number) {
1188
1235
  emits('current-change', e, row, { select: !isCurrentRow });
1189
1236
  }
1190
1237
 
1191
- 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;
1192
1242
  emits('row-dblclick', e, row, { rowIndex });
1193
1243
  }
1194
1244
 
1195
- /** 表头行右键 */
1196
1245
  function onHeaderMenu(e: MouseEvent) {
1197
1246
  emits('header-row-menu', e);
1198
1247
  }
1199
1248
 
1200
- /** 表体行右键 */
1201
- 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;
1202
1253
  emits('row-menu', e, row, { rowIndex });
1203
1254
  }
1204
1255
 
1205
- /**
1206
- * proxy events
1207
- */
1208
- // function onTbodyClick(e: MouseEvent, type: 1 | 2) {
1209
- // const el = (e.target as HTMLElement).closest<HTMLElement>('td,tr');
1210
- // if (!el) return;
1211
- // if (el.tagName === 'TD') {
1212
- // const [rowKey, colKey] = el.dataset.cellKey?.split(CELL_KEY_SEPARATE) || [];
1213
- // const row = dataSourceCopy.value.find(item => rowKeyGen(item) === rowKey);
1214
- // const col = tableHeaderLast.value.find(item => colKeyGen.value(item) === colKey);
1215
- // if (col) {
1216
- // if (col.type === 'expand') {
1217
- // toggleExpandRow(row, col);
1218
- // }
1219
- // if (type === 1) {
1220
- // onCellClick(e, row, col);
1221
- // } else if (type === 2) {
1222
- // onCellMouseDown(e, row, col);
1223
- // }
1224
- // }
1225
- // if (type === 1) {
1226
- // onRowClick(e, row);
1227
- // }
1228
- // } else if (el.tagName === 'TR') {
1229
- // const rowKey = el.dataset.rowKey;
1230
- // const row = dataSourceCopy.value.find(item => rowKeyGen(item) === rowKey);
1231
- // onRowClick(e, row);
1232
- // }
1233
- // }
1234
-
1235
1256
  function triangleClick(e: MouseEvent, row: DT, col: StkTableColumn<DT>) {
1236
1257
  if (col.type === 'expand') {
1237
1258
  toggleExpandRow(row, col);
@@ -1240,8 +1261,13 @@ function triangleClick(e: MouseEvent, row: DT, col: StkTableColumn<DT>) {
1240
1261
  }
1241
1262
  }
1242
1263
 
1243
- /** 单元格单击 */
1244
- 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;
1245
1271
  if (props.cellActive) {
1246
1272
  const cellKey = cellKeyGen(row, col);
1247
1273
  const result = { row, col, select: false, rowIndex };
@@ -1256,27 +1282,39 @@ function onCellClick(e: MouseEvent, row: DT, col: StkTableColumn<DT>, rowIndex:
1256
1282
  emits('cell-click', e, row, col, { rowIndex });
1257
1283
  }
1258
1284
 
1259
- /** 表头单元格单击 */
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 */
1260
1294
  function onHeaderCellClick(e: MouseEvent, col: StkTableColumn<DT>) {
1295
+ onColumnSort(col);
1261
1296
  emits('header-cell-click', e, col);
1262
1297
  }
1263
1298
 
1264
1299
  /** td mouseenter */
1265
- function onCellMouseEnter(e: MouseEvent, row: DT, col: StkTableColumn<DT>) {
1300
+ function onCellMouseEnter(e: MouseEvent) {
1301
+ const { row, col } = getCellEventData(e);
1266
1302
  emits('cell-mouseenter', e, row, col);
1267
1303
  }
1268
1304
 
1269
1305
  /** td mouseleave */
1270
- function onCellMouseLeave(e: MouseEvent, row: DT, col: StkTableColumn<DT>) {
1306
+ function onCellMouseLeave(e: MouseEvent) {
1307
+ const { row, col } = getCellEventData(e);
1271
1308
  emits('cell-mouseleave', e, row, col);
1272
1309
  }
1273
-
1274
1310
  /** td mouseover event */
1275
- function onCellMouseOver(e: MouseEvent, row: DT, col: StkTableColumn<DT>) {
1311
+ function onCellMouseOver(e: MouseEvent) {
1312
+ const { row, col } = getCellEventData(e);
1276
1313
  emits('cell-mouseover', e, row, col);
1277
1314
  }
1278
1315
 
1279
- function onCellMouseDown(e: MouseEvent, row: DT, col: StkTableColumn<DT>, rowIndex: number) {
1316
+ function onCellMouseDown(e: MouseEvent) {
1317
+ const { row, col, rowIndex } = getCellEventData(e);
1280
1318
  emits('cell-mousedown', e, row, col, { rowIndex });
1281
1319
  }
1282
1320
 
@@ -1294,22 +1332,21 @@ function onTableWheel(e: WheelEvent) {
1294
1332
  return;
1295
1333
  }
1296
1334
  const dom = tableContainerRef.value;
1297
- if (!dom) return;
1298
- if (!virtual_on.value && !virtualX_on.value) return;
1335
+ if ((!virtual_on.value && !virtualX_on.value) || !dom) return;
1299
1336
 
1300
- const { containerHeight, scrollTop, scrollHeight } = virtualScroll.value;
1301
- const { containerWidth, scrollLeft, scrollWidth } = virtualScrollX.value;
1302
- const isScrollBottom = scrollHeight - containerHeight - scrollTop < 10;
1303
- const isScrollRight = scrollWidth - containerWidth - scrollLeft < 10;
1304
1337
  const { deltaY, deltaX, shiftKey } = e;
1305
1338
 
1306
1339
  if (virtual_on.value && deltaY && !shiftKey) {
1340
+ const { containerHeight, scrollTop, scrollHeight } = virtualScroll.value;
1341
+ const isScrollBottom = scrollHeight - containerHeight - scrollTop < 10;
1307
1342
  if ((deltaY > 0 && !isScrollBottom) || (deltaY < 0 && scrollTop > 0)) {
1308
1343
  e.preventDefault(); // parent element scroll
1309
1344
  }
1310
1345
  dom.scrollTop += deltaY;
1311
1346
  }
1312
1347
  if (virtualX_on.value) {
1348
+ const { containerWidth, scrollLeft, scrollWidth } = virtualScrollX.value;
1349
+ const isScrollRight = scrollWidth - containerWidth - scrollLeft < 10;
1313
1350
  let distance = deltaX;
1314
1351
  if (shiftKey && deltaY) {
1315
1352
  distance = deltaY;
@@ -1333,12 +1370,10 @@ function onTableScroll(e: Event) {
1333
1370
  const isYScroll = scrollTop !== vScrollTop;
1334
1371
  const isXScroll = scrollLeft !== vScrollLeft;
1335
1372
 
1336
- // 纵向滚动有变化
1337
1373
  if (isYScroll) {
1338
1374
  updateVirtualScrollY(scrollTop);
1339
1375
  }
1340
1376
 
1341
- // 横向滚动有变化
1342
1377
  if (isXScroll) {
1343
1378
  if (virtualX_on.value) {
1344
1379
  updateVirtualScrollX(scrollLeft);
@@ -1359,12 +1394,16 @@ function onTableScroll(e: Event) {
1359
1394
  }
1360
1395
 
1361
1396
  /** tr hover */
1362
- 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];
1363
1402
  if (currentHoverRow === row) return;
1364
1403
  currentHoverRow = row;
1365
- const rowKey = rowKeyGen(row);
1404
+ const rowKey = tr.dataset.rowKey;
1366
1405
  if (props.showTrHoverClass) {
1367
- currentHoverRowKey.value = rowKey;
1406
+ currentHoverRowKey.value = rowKey || null;
1368
1407
  }
1369
1408
  if (props.rowHover) {
1370
1409
  updateHoverMergedCells(rowKey);
@@ -1372,7 +1411,7 @@ function onTrMouseOver(_e: MouseEvent, row: DT) {
1372
1411
  }
1373
1412
 
1374
1413
  function onTrMouseLeave(e: MouseEvent) {
1375
- if ((e.target as HTMLTableRowElement).tagName !== 'TR') return;
1414
+ if ((e.target as HTMLElement).tagName !== 'TR') return;
1376
1415
  currentHoverRow = null;
1377
1416
  if (props.showTrHoverClass) {
1378
1417
  currentHoverRowKey.value = null;
@@ -1384,6 +1423,8 @@ function onTrMouseLeave(e: MouseEvent) {
1384
1423
 
1385
1424
  /**
1386
1425
  * 选中一行
1426
+ *
1427
+ * en: Select a row
1387
1428
  * @param {string} rowKeyOrRow selected rowKey, undefined to unselect
1388
1429
  * @param {boolean} option.silent if set true not emit `current-change`. default:false
1389
1430
  * @param {boolean} option.deep if set true, deep search in children. default:false
@@ -44,7 +44,7 @@ export const DEFAULT_SORT_CONFIG = {
44
44
  } satisfies SortConfig<any>;
45
45
 
46
46
  export const DEFAULT_ROW_ACTIVE_CONFIG: Required<RowActiveOption<any>> = {
47
- enabled: false,
47
+ enabled: true,
48
48
  disabled: () => false,
49
- revokable: false,
49
+ revokable: true,
50
50
  };
@@ -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,