stk-table-vue 0.8.7 → 0.8.8
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 +2 -1
- package/lib/src/StkTable/StkTable.vue.d.ts +749 -745
- package/lib/src/StkTable/const.d.ts +33 -28
- package/lib/src/StkTable/types/index.d.ts +263 -256
- package/lib/stk-table-vue.js +2839 -2806
- package/package.json +5 -5
- package/src/StkTable/StkTable.vue +30 -14
- package/src/StkTable/const.ts +8 -1
- package/src/StkTable/types/index.ts +21 -14
- package/src/StkTable/useKeyboardArrowScroll.ts +10 -10
- package/src/StkTable/utils/index.ts +24 -11
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "stk-table-vue",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.8",
|
|
4
4
|
"description": "Simple 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",
|
|
@@ -59,15 +59,15 @@
|
|
|
59
59
|
"postcss-discard-comments": "^6.0.2",
|
|
60
60
|
"postcss-preset-env": "^9.5.11",
|
|
61
61
|
"prettier": "^3.2.5",
|
|
62
|
-
"stk-table-vue": "^0.8.
|
|
62
|
+
"stk-table-vue": "^0.8.7",
|
|
63
63
|
"typescript": "^5.8.3",
|
|
64
|
-
"vite": "^7.
|
|
64
|
+
"vite": "^7.1.7",
|
|
65
65
|
"vite-plugin-dts": "3.9.1",
|
|
66
66
|
"vitepress": "^1.6.4",
|
|
67
|
-
"vitepress-demo-plugin": "^1.4.
|
|
67
|
+
"vitepress-demo-plugin": "^1.4.7",
|
|
68
68
|
"vitepress-plugin-llms": "^1.7.5",
|
|
69
69
|
"vitest": "^3.2.4",
|
|
70
|
-
"vue": "^3.5.
|
|
70
|
+
"vue": "^3.5.22",
|
|
71
71
|
"vue-eslint-parser": "^9.4.2"
|
|
72
72
|
}
|
|
73
73
|
}
|
|
@@ -253,7 +253,7 @@ import { CSSProperties, computed, nextTick, onMounted, ref, shallowRef, toRaw, w
|
|
|
253
253
|
import DragHandle from './components/DragHandle.vue';
|
|
254
254
|
import SortIcon from './components/SortIcon.vue';
|
|
255
255
|
import TriangleIcon from './components/TriangleIcon.vue';
|
|
256
|
-
import { CELL_KEY_SEPARATE, DEFAULT_ROW_HEIGHT, DEFAULT_SMOOTH_SCROLL, IS_LEGACY_MODE } from './const';
|
|
256
|
+
import { CELL_KEY_SEPARATE, DEFAULT_ROW_HEIGHT, DEFAULT_SMOOTH_SCROLL, DEFAULT_SORT_CONFIG, IS_LEGACY_MODE } from './const';
|
|
257
257
|
import {
|
|
258
258
|
AutoRowHeightConfig,
|
|
259
259
|
ColResizableConfig,
|
|
@@ -473,10 +473,7 @@ const props = withDefaults(
|
|
|
473
473
|
autoResize: true,
|
|
474
474
|
fixedColShadow: false,
|
|
475
475
|
optimizeVue2Scroll: false,
|
|
476
|
-
sortConfig: () =>
|
|
477
|
-
emptyToBottom: false,
|
|
478
|
-
stringLocaleCompare: false,
|
|
479
|
-
}),
|
|
476
|
+
sortConfig: () => DEFAULT_SORT_CONFIG,
|
|
480
477
|
hideHeaderTitle: false,
|
|
481
478
|
highlightConfig: () => ({}),
|
|
482
479
|
seqConfig: () => ({}),
|
|
@@ -749,7 +746,8 @@ const SRBRTotalHeight = computed(() => {
|
|
|
749
746
|
});
|
|
750
747
|
const SRBRBottomHeight = computed(() => {
|
|
751
748
|
if (!isSRBRActive.value || !props.virtual) return 0;
|
|
752
|
-
|
|
749
|
+
const { containerHeight, rowHeight } = virtualScroll.value;
|
|
750
|
+
return (containerHeight - tableHeaderHeight.value) % rowHeight;
|
|
753
751
|
});
|
|
754
752
|
|
|
755
753
|
const rowKeyGenCache = new WeakMap();
|
|
@@ -1131,8 +1129,8 @@ function onColumnSort(col: StkTableColumn<DT> | undefined | null, click = true,
|
|
|
1131
1129
|
sortOrderIndex.value = sortOrderIndex.value % 3;
|
|
1132
1130
|
|
|
1133
1131
|
let order = sortSwitchOrder[sortOrderIndex.value];
|
|
1134
|
-
const sortConfig = { ...props.sortConfig, ...col.sortConfig };
|
|
1135
|
-
const defaultSort = sortConfig
|
|
1132
|
+
const sortConfig: SortConfig<any> = { ...DEFAULT_SORT_CONFIG, ...props.sortConfig, ...col.sortConfig };
|
|
1133
|
+
const { defaultSort } = sortConfig;
|
|
1136
1134
|
const colKeyGenValue = colKeyGen.value;
|
|
1137
1135
|
|
|
1138
1136
|
if (!order && defaultSort) {
|
|
@@ -1158,15 +1156,17 @@ function onColumnSort(col: StkTableColumn<DT> | undefined | null, click = true,
|
|
|
1158
1156
|
}
|
|
1159
1157
|
}
|
|
1160
1158
|
}
|
|
1159
|
+
let dataSourceTemp: any[] = props.dataSource.slice();
|
|
1161
1160
|
if (!props.sortRemote || options.force) {
|
|
1162
1161
|
const sortOption = col || defaultSort;
|
|
1163
1162
|
if (sortOption) {
|
|
1164
|
-
|
|
1163
|
+
dataSourceTemp = tableSort(sortOption, order, dataSourceTemp, sortConfig);
|
|
1164
|
+
dataSourceCopy.value = isTreeData.value ? flatTreeData(dataSourceTemp) : dataSourceTemp;
|
|
1165
1165
|
}
|
|
1166
1166
|
}
|
|
1167
|
-
// 只有点击才触发事件
|
|
1167
|
+
// 只有点击才触发事件 en: only emit sort-change event when click
|
|
1168
1168
|
if (click || options.emit) {
|
|
1169
|
-
emits('sort-change', col, order, toRaw(
|
|
1169
|
+
emits('sort-change', col, order, toRaw(dataSourceTemp), sortConfig);
|
|
1170
1170
|
}
|
|
1171
1171
|
}
|
|
1172
1172
|
|
|
@@ -1391,15 +1391,32 @@ function onTrMouseLeave(e: MouseEvent) {
|
|
|
1391
1391
|
* 选中一行
|
|
1392
1392
|
* @param {string} rowKeyOrRow selected rowKey, undefined to unselect
|
|
1393
1393
|
* @param {boolean} option.silent if set true not emit `current-change`. default:false
|
|
1394
|
+
* @param {boolean} option.deep if set true, deep search in children. default:false
|
|
1394
1395
|
*/
|
|
1395
|
-
function setCurrentRow(rowKeyOrRow: string | undefined | DT, option = { silent: false }) {
|
|
1396
|
+
function setCurrentRow(rowKeyOrRow: string | undefined | DT, option = { silent: false, deep: false }) {
|
|
1396
1397
|
if (!dataSourceCopy.value.length) return;
|
|
1397
1398
|
const select = rowKeyOrRow !== void 0;
|
|
1398
1399
|
if (!select) {
|
|
1399
1400
|
currentRow.value = void 0;
|
|
1400
1401
|
currentRowKey.value = void 0;
|
|
1401
1402
|
} else if (typeof rowKeyOrRow === 'string') {
|
|
1402
|
-
const
|
|
1403
|
+
const findRowByKey = (data: DT[], key: string): DT | null => {
|
|
1404
|
+
for (let i = 0; i < data.length; i++) {
|
|
1405
|
+
const item = data[i];
|
|
1406
|
+
if (rowKeyGen(item) === key) {
|
|
1407
|
+
return item;
|
|
1408
|
+
}
|
|
1409
|
+
if (option.deep && item.children?.length) {
|
|
1410
|
+
const found = findRowByKey(item.children, key);
|
|
1411
|
+
if (found) {
|
|
1412
|
+
return found;
|
|
1413
|
+
}
|
|
1414
|
+
}
|
|
1415
|
+
}
|
|
1416
|
+
return null;
|
|
1417
|
+
};
|
|
1418
|
+
|
|
1419
|
+
const row = findRowByKey(dataSourceCopy.value, rowKeyOrRow);
|
|
1403
1420
|
if (!row) {
|
|
1404
1421
|
console.warn('setCurrentRow failed.rowKey:', rowKeyOrRow);
|
|
1405
1422
|
return;
|
|
@@ -1447,7 +1464,6 @@ function setSorter(colKey: string, order: Order, option: { sortOption?: SortOpti
|
|
|
1447
1464
|
const colKeyGenValue = colKeyGen.value;
|
|
1448
1465
|
|
|
1449
1466
|
if (newOption.sort && dataSourceCopy.value?.length) {
|
|
1450
|
-
// 如果表格有数据,则进行排序
|
|
1451
1467
|
const column = newOption.sortOption || tableHeaderLast.value.find(it => colKeyGenValue(it) === sortCol.value);
|
|
1452
1468
|
if (column) onColumnSort(column, false, { force: option.force ?? true, emit: !newOption.silent });
|
|
1453
1469
|
else console.warn('Can not find column by key:', sortCol.value);
|
package/src/StkTable/const.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { SortConfig } from './types';
|
|
1
2
|
import { getBrowsersVersion } from './utils';
|
|
2
3
|
|
|
3
4
|
export const DEFAULT_COL_WIDTH = '100';
|
|
@@ -33,5 +34,11 @@ export const STK_ID_PREFIX = 'stk';
|
|
|
33
34
|
/** expanded row key prefix */
|
|
34
35
|
export const EXPANDED_ROW_KEY_PREFIX = 'expanded-';
|
|
35
36
|
|
|
36
|
-
/** cell key
|
|
37
|
+
/** cell key split str */
|
|
37
38
|
export const CELL_KEY_SEPARATE = '--';
|
|
39
|
+
|
|
40
|
+
export const DEFAULT_SORT_CONFIG = {
|
|
41
|
+
emptyToBottom: false,
|
|
42
|
+
stringLocaleCompare: false,
|
|
43
|
+
sortChildren: false,
|
|
44
|
+
} satisfies SortConfig<any>;
|
|
@@ -88,7 +88,7 @@ export type StkTableColumn<T extends Record<string, any>> = {
|
|
|
88
88
|
/** 排序方式。按数字/字符串 */
|
|
89
89
|
sortType?: 'number' | 'string';
|
|
90
90
|
/** 配置当前列的排序规则 */
|
|
91
|
-
sortConfig?:
|
|
91
|
+
sortConfig?: Omit<SortConfig<T>, 'defaultSort'>;
|
|
92
92
|
/** 固定列 */
|
|
93
93
|
fixed?: 'left' | 'right' | null;
|
|
94
94
|
/**
|
|
@@ -176,17 +176,17 @@ export type UniqKeyFun = (param: any) => UniqKey;
|
|
|
176
176
|
export type UniqKeyProp = UniqKey | UniqKeyFun;
|
|
177
177
|
|
|
178
178
|
export type SortConfig<T extends Record<string, any>> = {
|
|
179
|
-
/** 空值始终排在列表末尾 */
|
|
180
|
-
emptyToBottom?: boolean;
|
|
181
179
|
/**
|
|
182
|
-
*
|
|
183
|
-
*
|
|
180
|
+
* 1. trigger when init
|
|
181
|
+
* 2. trigger when sort direction is null
|
|
184
182
|
*/
|
|
185
183
|
defaultSort?: {
|
|
186
184
|
/**
|
|
187
|
-
*
|
|
185
|
+
* colKey
|
|
186
|
+
*
|
|
187
|
+
* if set `props.colKey`
|
|
188
188
|
*
|
|
189
|
-
*
|
|
189
|
+
* default: StkTableColumn<T>['dataIndex']
|
|
190
190
|
*/
|
|
191
191
|
key?: StkTableColumn<T>['key'];
|
|
192
192
|
dataIndex: StkTableColumn<T>['dataIndex'];
|
|
@@ -194,14 +194,22 @@ export type SortConfig<T extends Record<string, any>> = {
|
|
|
194
194
|
sortField?: StkTableColumn<T>['sortField'];
|
|
195
195
|
sortType?: StkTableColumn<T>['sortType'];
|
|
196
196
|
sorter?: StkTableColumn<T>['sorter'];
|
|
197
|
-
/**
|
|
197
|
+
/**
|
|
198
|
+
* whether to disable trigger`sort-change` event. default: false
|
|
199
|
+
*/
|
|
198
200
|
silent?: boolean;
|
|
199
201
|
};
|
|
202
|
+
/** empty value always sort to bottom */
|
|
203
|
+
emptyToBottom?: boolean;
|
|
200
204
|
/**
|
|
201
205
|
* string sort if use `String.prototype.localCompare`
|
|
202
206
|
* default: false
|
|
203
207
|
*/
|
|
204
208
|
stringLocaleCompare?: boolean;
|
|
209
|
+
/**
|
|
210
|
+
* whether to sort children when sort current column. default: false
|
|
211
|
+
*/
|
|
212
|
+
sortChildren?: boolean;
|
|
205
213
|
};
|
|
206
214
|
|
|
207
215
|
/** th td type */
|
|
@@ -242,7 +250,6 @@ export type DragRowConfig = {
|
|
|
242
250
|
// disabled?: (row: T, rowIndex: number) => boolean;
|
|
243
251
|
};
|
|
244
252
|
|
|
245
|
-
/** 树形配置 */
|
|
246
253
|
export type TreeConfig = {
|
|
247
254
|
// childrenField?: string;
|
|
248
255
|
defaultExpandAll?: boolean;
|
|
@@ -253,13 +260,13 @@ export type TreeConfig = {
|
|
|
253
260
|
/** header drag config */
|
|
254
261
|
export type HeaderDragConfig<DT extends Record<string, any> = any> = {
|
|
255
262
|
/**
|
|
256
|
-
*
|
|
257
|
-
* - none
|
|
258
|
-
* - insert -
|
|
259
|
-
* - swap
|
|
263
|
+
* col switch mode
|
|
264
|
+
* - none
|
|
265
|
+
* - insert - (default)
|
|
266
|
+
* - swap
|
|
260
267
|
*/
|
|
261
268
|
mode?: 'none' | 'insert' | 'swap';
|
|
262
|
-
/**
|
|
269
|
+
/** disabled drag col */
|
|
263
270
|
disabled?: (col: StkTableColumn<DT>) => boolean;
|
|
264
271
|
};
|
|
265
272
|
|
|
@@ -64,7 +64,8 @@ export function useKeyboardArrowScroll<DT extends Record<string, any>>(
|
|
|
64
64
|
/** 键盘按下事件 */
|
|
65
65
|
function handleKeydown(e: KeyboardEvent) {
|
|
66
66
|
if (!virtual_on.value) return; // 非虚拟滚动使用浏览器默认滚动
|
|
67
|
-
|
|
67
|
+
const keyCode = e.code;
|
|
68
|
+
if (!ScrollCodesValues.includes(keyCode as any)) return;
|
|
68
69
|
if (!isMouseOver) return; // 不悬浮还是要触发键盘事件的
|
|
69
70
|
e.preventDefault(); // 不触发键盘默认的箭头事件
|
|
70
71
|
|
|
@@ -76,22 +77,21 @@ export function useKeyboardArrowScroll<DT extends Record<string, any>>(
|
|
|
76
77
|
const headerHeight = headless ? 0 : tableHeaders.value.length * (headerRowHeight || rowHeight);
|
|
77
78
|
/** 表体的page */
|
|
78
79
|
const bodyPageSize = Math.floor((containerHeight - headerHeight) / rowHeight);
|
|
79
|
-
|
|
80
|
-
if (e.code === ScrollCodes.ArrowUp) {
|
|
80
|
+
if (keyCode=== ScrollCodes.ArrowUp) {
|
|
81
81
|
scrollTo(scrollTop - rowHeight, null);
|
|
82
|
-
} else if (
|
|
82
|
+
} else if (keyCode=== ScrollCodes.ArrowRight) {
|
|
83
83
|
scrollTo(null, scrollLeft + 50);
|
|
84
|
-
} else if (
|
|
84
|
+
} else if (keyCode=== ScrollCodes.ArrowDown) {
|
|
85
85
|
scrollTo(scrollTop + rowHeight, null);
|
|
86
|
-
} else if (
|
|
86
|
+
} else if (keyCode=== ScrollCodes.ArrowLeft) {
|
|
87
87
|
scrollTo(null, scrollLeft - 50);
|
|
88
|
-
} else if (
|
|
88
|
+
} else if (keyCode=== ScrollCodes.PageUp) {
|
|
89
89
|
scrollTo(scrollTop - rowHeight * bodyPageSize + headerHeight, null);
|
|
90
|
-
} else if (
|
|
90
|
+
} else if (keyCode=== ScrollCodes.PageDown) {
|
|
91
91
|
scrollTo(scrollTop + rowHeight * bodyPageSize - headerHeight, null);
|
|
92
|
-
} else if (
|
|
92
|
+
} else if (keyCode=== ScrollCodes.Home) {
|
|
93
93
|
scrollTo(0, null);
|
|
94
|
-
} else if (
|
|
94
|
+
} else if (keyCode=== ScrollCodes.End) {
|
|
95
95
|
scrollTo(scrollHeight, null);
|
|
96
96
|
}
|
|
97
97
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CELL_KEY_SEPARATE } from '../const';
|
|
1
|
+
import { CELL_KEY_SEPARATE, DEFAULT_SORT_CONFIG } from '../const';
|
|
2
2
|
import { Order, SortConfig, SortOption, SortState, StkTableColumn, UniqKey } from '../types';
|
|
3
3
|
|
|
4
4
|
/** 是否空值 */
|
|
@@ -158,19 +158,28 @@ export function tableSort<T extends Record<string, any>>(
|
|
|
158
158
|
): T[] {
|
|
159
159
|
if (!dataSource?.length || !sortOption) return dataSource || [];
|
|
160
160
|
|
|
161
|
-
sortConfig = {
|
|
161
|
+
sortConfig = { ...DEFAULT_SORT_CONFIG, ...sortConfig };
|
|
162
162
|
let targetDataSource = dataSource.slice();
|
|
163
163
|
let sortField = sortOption.sortField || sortOption.dataIndex;
|
|
164
|
+
const { defaultSort, stringLocaleCompare, emptyToBottom, sortChildren } = sortConfig;
|
|
164
165
|
|
|
165
|
-
if (!order &&
|
|
166
|
+
if (!order && defaultSort) {
|
|
166
167
|
// 默认排序
|
|
167
|
-
order =
|
|
168
|
-
sortField =
|
|
168
|
+
order = defaultSort.order;
|
|
169
|
+
sortField = defaultSort.dataIndex;
|
|
169
170
|
}
|
|
170
171
|
|
|
171
172
|
if (typeof sortOption.sorter === 'function') {
|
|
172
173
|
const customSorterData = sortOption.sorter(targetDataSource, { order, column: sortOption });
|
|
173
174
|
if (customSorterData) targetDataSource = customSorterData;
|
|
175
|
+
|
|
176
|
+
// 如果开启了子节点排序且使用了自定义排序器,递归排序children
|
|
177
|
+
if (sortChildren) {
|
|
178
|
+
targetDataSource.forEach(item => {
|
|
179
|
+
if (!item.children?.length) return;
|
|
180
|
+
(item as any).children = tableSort(sortOption, order, item.children, sortConfig);
|
|
181
|
+
});
|
|
182
|
+
}
|
|
174
183
|
} else if (order) {
|
|
175
184
|
let { sortType } = sortOption;
|
|
176
185
|
if (!sortType) sortType = typeof dataSource[0][sortField] as 'number' | 'string';
|
|
@@ -179,15 +188,19 @@ export function tableSort<T extends Record<string, any>>(
|
|
|
179
188
|
const [valueArr, emptyArr] = separatedData(sortOption, targetDataSource, isNumber);
|
|
180
189
|
|
|
181
190
|
if (order === 'asc') {
|
|
182
|
-
valueArr.sort((a, b) => strCompare(a[sortField], b[sortField], isNumber,
|
|
191
|
+
valueArr.sort((a, b) => strCompare(a[sortField], b[sortField], isNumber, stringLocaleCompare));
|
|
183
192
|
} else {
|
|
184
|
-
valueArr.sort((a, b) => strCompare(b[sortField], a[sortField], isNumber,
|
|
193
|
+
valueArr.sort((a, b) => strCompare(b[sortField], a[sortField], isNumber, stringLocaleCompare));
|
|
185
194
|
}
|
|
186
195
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
196
|
+
targetDataSource = order === 'desc' || emptyToBottom ? valueArr.concat(emptyArr) : emptyArr.concat(valueArr);
|
|
197
|
+
|
|
198
|
+
// 递归排序子节点
|
|
199
|
+
if (sortChildren) {
|
|
200
|
+
targetDataSource.forEach(item => {
|
|
201
|
+
if (!item.children?.length) return;
|
|
202
|
+
(item as any).children = tableSort(sortOption, order, item.children, sortConfig);
|
|
203
|
+
});
|
|
191
204
|
}
|
|
192
205
|
}
|
|
193
206
|
return targetDataSource;
|