stk-table-vue 0.8.6 → 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/src/StkTable/useVirtualScroll.d.ts +1 -0
- package/lib/stk-table-vue.js +83 -41
- package/lib/style.css +2 -0
- package/package.json +5 -5
- package/src/StkTable/StkTable.vue +46 -21
- package/src/StkTable/const.ts +8 -1
- package/src/StkTable/style.less +2 -0
- package/src/StkTable/types/index.ts +21 -14
- package/src/StkTable/useKeyboardArrowScroll.ts +10 -10
- package/src/StkTable/useVirtualScroll.ts +6 -10
- package/src/StkTable/utils/index.ts +24 -11
package/lib/stk-table-vue.js
CHANGED
|
@@ -134,30 +134,41 @@ function separatedData(sortOption, targetDataSource, isNumber) {
|
|
|
134
134
|
}
|
|
135
135
|
function tableSort(sortOption, order, dataSource, sortConfig = {}) {
|
|
136
136
|
if (!(dataSource == null ? void 0 : dataSource.length) || !sortOption) return dataSource || [];
|
|
137
|
-
sortConfig = {
|
|
137
|
+
sortConfig = { ...DEFAULT_SORT_CONFIG, ...sortConfig };
|
|
138
138
|
let targetDataSource = dataSource.slice();
|
|
139
139
|
let sortField = sortOption.sortField || sortOption.dataIndex;
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
140
|
+
const { defaultSort, stringLocaleCompare, emptyToBottom, sortChildren } = sortConfig;
|
|
141
|
+
if (!order && defaultSort) {
|
|
142
|
+
order = defaultSort.order;
|
|
143
|
+
sortField = defaultSort.dataIndex;
|
|
143
144
|
}
|
|
144
145
|
if (typeof sortOption.sorter === "function") {
|
|
145
146
|
const customSorterData = sortOption.sorter(targetDataSource, { order, column: sortOption });
|
|
146
147
|
if (customSorterData) targetDataSource = customSorterData;
|
|
148
|
+
if (sortChildren) {
|
|
149
|
+
targetDataSource.forEach((item) => {
|
|
150
|
+
var _a;
|
|
151
|
+
if (!((_a = item.children) == null ? void 0 : _a.length)) return;
|
|
152
|
+
item.children = tableSort(sortOption, order, item.children, sortConfig);
|
|
153
|
+
});
|
|
154
|
+
}
|
|
147
155
|
} else if (order) {
|
|
148
156
|
let { sortType } = sortOption;
|
|
149
157
|
if (!sortType) sortType = typeof dataSource[0][sortField];
|
|
150
158
|
const isNumber = sortType === "number";
|
|
151
159
|
const [valueArr, emptyArr] = separatedData(sortOption, targetDataSource, isNumber);
|
|
152
160
|
if (order === "asc") {
|
|
153
|
-
valueArr.sort((a, b) => strCompare(a[sortField], b[sortField], isNumber,
|
|
154
|
-
} else {
|
|
155
|
-
valueArr.sort((a, b) => strCompare(b[sortField], a[sortField], isNumber, sortConfig.stringLocaleCompare));
|
|
156
|
-
}
|
|
157
|
-
if (order === "desc" || sortConfig.emptyToBottom) {
|
|
158
|
-
targetDataSource = valueArr.concat(emptyArr);
|
|
161
|
+
valueArr.sort((a, b) => strCompare(a[sortField], b[sortField], isNumber, stringLocaleCompare));
|
|
159
162
|
} else {
|
|
160
|
-
|
|
163
|
+
valueArr.sort((a, b) => strCompare(b[sortField], a[sortField], isNumber, stringLocaleCompare));
|
|
164
|
+
}
|
|
165
|
+
targetDataSource = order === "desc" || emptyToBottom ? valueArr.concat(emptyArr) : emptyArr.concat(valueArr);
|
|
166
|
+
if (sortChildren) {
|
|
167
|
+
targetDataSource.forEach((item) => {
|
|
168
|
+
var _a;
|
|
169
|
+
if (!((_a = item.children) == null ? void 0 : _a.length)) return;
|
|
170
|
+
item.children = tableSort(sortOption, order, item.children, sortConfig);
|
|
171
|
+
});
|
|
161
172
|
}
|
|
162
173
|
}
|
|
163
174
|
return targetDataSource;
|
|
@@ -210,6 +221,11 @@ const DEFAULT_SMOOTH_SCROLL = _chromeVersion < 85;
|
|
|
210
221
|
const STK_ID_PREFIX = "stk";
|
|
211
222
|
const EXPANDED_ROW_KEY_PREFIX = "expanded-";
|
|
212
223
|
const CELL_KEY_SEPARATE = "--";
|
|
224
|
+
const DEFAULT_SORT_CONFIG = {
|
|
225
|
+
emptyToBottom: false,
|
|
226
|
+
stringLocaleCompare: false,
|
|
227
|
+
sortChildren: false
|
|
228
|
+
};
|
|
213
229
|
var TagType = /* @__PURE__ */ ((TagType2) => {
|
|
214
230
|
TagType2[TagType2["TH"] = 0] = "TH";
|
|
215
231
|
TagType2[TagType2["TD"] = 1] = "TD";
|
|
@@ -817,7 +833,8 @@ function useKeyboardArrowScroll(targetElement, { props, scrollTo, virtualScroll,
|
|
|
817
833
|
}
|
|
818
834
|
function handleKeydown(e) {
|
|
819
835
|
if (!virtual_on.value) return;
|
|
820
|
-
|
|
836
|
+
const keyCode = e.code;
|
|
837
|
+
if (!ScrollCodesValues.includes(keyCode)) return;
|
|
821
838
|
if (!isMouseOver) return;
|
|
822
839
|
e.preventDefault();
|
|
823
840
|
const { scrollTop, rowHeight, containerHeight, scrollHeight } = virtualScroll.value;
|
|
@@ -825,21 +842,21 @@ function useKeyboardArrowScroll(targetElement, { props, scrollTo, virtualScroll,
|
|
|
825
842
|
const { headless, headerRowHeight } = props;
|
|
826
843
|
const headerHeight = headless ? 0 : tableHeaders.value.length * (headerRowHeight || rowHeight);
|
|
827
844
|
const bodyPageSize = Math.floor((containerHeight - headerHeight) / rowHeight);
|
|
828
|
-
if (
|
|
845
|
+
if (keyCode === "ArrowUp") {
|
|
829
846
|
scrollTo(scrollTop - rowHeight, null);
|
|
830
|
-
} else if (
|
|
847
|
+
} else if (keyCode === "ArrowRight") {
|
|
831
848
|
scrollTo(null, scrollLeft + 50);
|
|
832
|
-
} else if (
|
|
849
|
+
} else if (keyCode === "ArrowDown") {
|
|
833
850
|
scrollTo(scrollTop + rowHeight, null);
|
|
834
|
-
} else if (
|
|
851
|
+
} else if (keyCode === "ArrowLeft") {
|
|
835
852
|
scrollTo(null, scrollLeft - 50);
|
|
836
|
-
} else if (
|
|
853
|
+
} else if (keyCode === "PageUp") {
|
|
837
854
|
scrollTo(scrollTop - rowHeight * bodyPageSize + headerHeight, null);
|
|
838
|
-
} else if (
|
|
855
|
+
} else if (keyCode === "PageDown") {
|
|
839
856
|
scrollTo(scrollTop + rowHeight * bodyPageSize - headerHeight, null);
|
|
840
|
-
} else if (
|
|
857
|
+
} else if (keyCode === "Home") {
|
|
841
858
|
scrollTo(0, null);
|
|
842
|
-
} else if (
|
|
859
|
+
} else if (keyCode === "End") {
|
|
843
860
|
scrollTo(scrollHeight, null);
|
|
844
861
|
}
|
|
845
862
|
}
|
|
@@ -1364,7 +1381,7 @@ function useVirtualScroll({
|
|
|
1364
1381
|
rowKeyGen,
|
|
1365
1382
|
maxRowSpan
|
|
1366
1383
|
}) {
|
|
1367
|
-
const tableHeaderHeight =
|
|
1384
|
+
const tableHeaderHeight = computed(() => props.headerRowHeight * tableHeaders.value.length);
|
|
1368
1385
|
const virtualScroll = ref({
|
|
1369
1386
|
containerHeight: 0,
|
|
1370
1387
|
rowHeight: props.rowHeight,
|
|
@@ -1457,9 +1474,6 @@ function useVirtualScroll({
|
|
|
1457
1474
|
}
|
|
1458
1475
|
return rowHeightFn;
|
|
1459
1476
|
});
|
|
1460
|
-
function getTableHeaderHeight() {
|
|
1461
|
-
return props.headerRowHeight * tableHeaders.value.length;
|
|
1462
|
-
}
|
|
1463
1477
|
function initVirtualScroll(height) {
|
|
1464
1478
|
initVirtualScrollY(height);
|
|
1465
1479
|
initVirtualScrollX();
|
|
@@ -1470,16 +1484,14 @@ function useVirtualScroll({
|
|
|
1470
1484
|
console.warn("initVirtualScrollY: height must be a number");
|
|
1471
1485
|
height = 0;
|
|
1472
1486
|
}
|
|
1473
|
-
const {
|
|
1487
|
+
const { clientHeight, scrollHeight } = tableContainerRef.value || {};
|
|
1474
1488
|
let scrollTop = ((_a = tableContainerRef.value) == null ? void 0 : _a.scrollTop) || 0;
|
|
1475
1489
|
const rowHeight = getRowHeightFn.value();
|
|
1476
|
-
const containerHeight = height ||
|
|
1490
|
+
const containerHeight = height || clientHeight || DEFAULT_TABLE_HEIGHT;
|
|
1477
1491
|
const { headless } = props;
|
|
1478
1492
|
let pageSize = Math.ceil(containerHeight / rowHeight);
|
|
1479
|
-
const headerHeight = getTableHeaderHeight();
|
|
1480
|
-
tableHeaderHeight.value = headerHeight;
|
|
1481
1493
|
if (!headless) {
|
|
1482
|
-
const headerToBodyRowHeightCount = Math.floor(
|
|
1494
|
+
const headerToBodyRowHeightCount = Math.floor(tableHeaderHeight.value / rowHeight);
|
|
1483
1495
|
pageSize -= headerToBodyRowHeightCount;
|
|
1484
1496
|
}
|
|
1485
1497
|
const maxScrollTop = dataSourceCopy.value.length * rowHeight + tableHeaderHeight.value - containerHeight;
|
|
@@ -1687,6 +1699,7 @@ function useVirtualScroll({
|
|
|
1687
1699
|
virtualX_on,
|
|
1688
1700
|
virtualX_columnPart,
|
|
1689
1701
|
virtualX_offsetRight,
|
|
1702
|
+
tableHeaderHeight,
|
|
1690
1703
|
initVirtualScroll,
|
|
1691
1704
|
initVirtualScrollY,
|
|
1692
1705
|
initVirtualScrollX,
|
|
@@ -1755,10 +1768,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
1755
1768
|
autoResize: { type: [Boolean, Function], default: true },
|
|
1756
1769
|
fixedColShadow: { type: Boolean, default: false },
|
|
1757
1770
|
optimizeVue2Scroll: { type: Boolean, default: false },
|
|
1758
|
-
sortConfig: { default: () =>
|
|
1759
|
-
emptyToBottom: false,
|
|
1760
|
-
stringLocaleCompare: false
|
|
1761
|
-
}) },
|
|
1771
|
+
sortConfig: { default: () => DEFAULT_SORT_CONFIG },
|
|
1762
1772
|
hideHeaderTitle: { type: [Boolean, Array], default: false },
|
|
1763
1773
|
highlightConfig: { default: () => ({}) },
|
|
1764
1774
|
seqConfig: { default: () => ({}) },
|
|
@@ -1819,6 +1829,15 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
1819
1829
|
return (col, row) => emptyCellText({ row, col });
|
|
1820
1830
|
}
|
|
1821
1831
|
});
|
|
1832
|
+
const SRBRTotalHeight = computed(() => {
|
|
1833
|
+
if (!isSRBRActive.value || !props.virtual) return 0;
|
|
1834
|
+
return dataSourceCopy.value.length * virtualScroll.value.rowHeight + tableHeaderHeight.value;
|
|
1835
|
+
});
|
|
1836
|
+
const SRBRBottomHeight = computed(() => {
|
|
1837
|
+
if (!isSRBRActive.value || !props.virtual) return 0;
|
|
1838
|
+
const { containerHeight, rowHeight } = virtualScroll.value;
|
|
1839
|
+
return (containerHeight - tableHeaderHeight.value) % rowHeight;
|
|
1840
|
+
});
|
|
1822
1841
|
const rowKeyGenCache = /* @__PURE__ */ new WeakMap();
|
|
1823
1842
|
const { isSRBRActive } = useScrollRowByRow({ props, tableContainerRef });
|
|
1824
1843
|
const { onThDragStart, onThDragOver, onThDrop, isHeaderDraggable } = useThDrag({ props, emits, colKeyGen });
|
|
@@ -1833,6 +1852,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
1833
1852
|
virtualX_on,
|
|
1834
1853
|
virtualX_columnPart,
|
|
1835
1854
|
virtualX_offsetRight,
|
|
1855
|
+
tableHeaderHeight,
|
|
1836
1856
|
initVirtualScroll,
|
|
1837
1857
|
initVirtualScrollY,
|
|
1838
1858
|
initVirtualScrollX,
|
|
@@ -2113,8 +2133,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
2113
2133
|
if (click) sortOrderIndex.value++;
|
|
2114
2134
|
sortOrderIndex.value = sortOrderIndex.value % 3;
|
|
2115
2135
|
let order = sortSwitchOrder[sortOrderIndex.value];
|
|
2116
|
-
const sortConfig = { ...props.sortConfig, ...col.sortConfig };
|
|
2117
|
-
const defaultSort = sortConfig
|
|
2136
|
+
const sortConfig = { ...DEFAULT_SORT_CONFIG, ...props.sortConfig, ...col.sortConfig };
|
|
2137
|
+
const { defaultSort } = sortConfig;
|
|
2118
2138
|
const colKeyGenValue = colKeyGen.value;
|
|
2119
2139
|
if (!order && defaultSort) {
|
|
2120
2140
|
const defaultColKey = defaultSort.key || defaultSort.dataIndex;
|
|
@@ -2138,14 +2158,16 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
2138
2158
|
}
|
|
2139
2159
|
}
|
|
2140
2160
|
}
|
|
2161
|
+
let dataSourceTemp = props.dataSource.slice();
|
|
2141
2162
|
if (!props.sortRemote || options.force) {
|
|
2142
2163
|
const sortOption = col || defaultSort;
|
|
2143
2164
|
if (sortOption) {
|
|
2144
|
-
|
|
2165
|
+
dataSourceTemp = tableSort(sortOption, order, dataSourceTemp, sortConfig);
|
|
2166
|
+
dataSourceCopy.value = isTreeData.value ? flatTreeData(dataSourceTemp) : dataSourceTemp;
|
|
2145
2167
|
}
|
|
2146
2168
|
}
|
|
2147
2169
|
if (click || options.emit) {
|
|
2148
|
-
emits("sort-change", col, order, toRaw(
|
|
2170
|
+
emits("sort-change", col, order, toRaw(dataSourceTemp), sortConfig);
|
|
2149
2171
|
}
|
|
2150
2172
|
}
|
|
2151
2173
|
function onRowClick(e, row, rowIndex) {
|
|
@@ -2285,14 +2307,30 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
2285
2307
|
updateHoverMergedCells(void 0);
|
|
2286
2308
|
}
|
|
2287
2309
|
}
|
|
2288
|
-
function setCurrentRow(rowKeyOrRow, option = { silent: false }) {
|
|
2310
|
+
function setCurrentRow(rowKeyOrRow, option = { silent: false, deep: false }) {
|
|
2289
2311
|
if (!dataSourceCopy.value.length) return;
|
|
2290
2312
|
const select = rowKeyOrRow !== void 0;
|
|
2291
2313
|
if (!select) {
|
|
2292
2314
|
currentRow.value = void 0;
|
|
2293
2315
|
currentRowKey.value = void 0;
|
|
2294
2316
|
} else if (typeof rowKeyOrRow === "string") {
|
|
2295
|
-
const
|
|
2317
|
+
const findRowByKey = (data, key) => {
|
|
2318
|
+
var _a;
|
|
2319
|
+
for (let i = 0; i < data.length; i++) {
|
|
2320
|
+
const item = data[i];
|
|
2321
|
+
if (rowKeyGen(item) === key) {
|
|
2322
|
+
return item;
|
|
2323
|
+
}
|
|
2324
|
+
if (option.deep && ((_a = item.children) == null ? void 0 : _a.length)) {
|
|
2325
|
+
const found = findRowByKey(item.children, key);
|
|
2326
|
+
if (found) {
|
|
2327
|
+
return found;
|
|
2328
|
+
}
|
|
2329
|
+
}
|
|
2330
|
+
}
|
|
2331
|
+
return null;
|
|
2332
|
+
};
|
|
2333
|
+
const row = findRowByKey(dataSourceCopy.value, rowKeyOrRow);
|
|
2296
2334
|
if (!row) {
|
|
2297
2335
|
console.warn("setCurrentRow failed.rowKey:", rowKeyOrRow);
|
|
2298
2336
|
return;
|
|
@@ -2514,10 +2552,10 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
2514
2552
|
onScroll: onTableScroll,
|
|
2515
2553
|
onWheel: onTableWheel
|
|
2516
2554
|
}, [
|
|
2517
|
-
|
|
2555
|
+
SRBRTotalHeight.value ? (openBlock(), createElementBlock("div", {
|
|
2518
2556
|
key: 0,
|
|
2519
2557
|
class: "row-by-row-table-height",
|
|
2520
|
-
style: normalizeStyle(
|
|
2558
|
+
style: normalizeStyle(`height: ${SRBRTotalHeight.value}px`)
|
|
2521
2559
|
}, null, 4)) : createCommentVNode("", true),
|
|
2522
2560
|
_ctx.colResizable ? (openBlock(), createElementBlock("div", {
|
|
2523
2561
|
key: 1,
|
|
@@ -2772,6 +2810,10 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
2772
2810
|
unref(virtual_on) && !unref(isSRBRActive) ? (openBlock(), createElementBlock("tr", {
|
|
2773
2811
|
key: 1,
|
|
2774
2812
|
style: normalizeStyle(`height: ${unref(virtual_offsetBottom)}px`)
|
|
2813
|
+
}, null, 4)) : createCommentVNode("", true),
|
|
2814
|
+
SRBRBottomHeight.value ? (openBlock(), createElementBlock("tr", {
|
|
2815
|
+
key: 2,
|
|
2816
|
+
style: normalizeStyle(`height: ${SRBRBottomHeight.value}px`)
|
|
2775
2817
|
}, null, 4)) : createCommentVNode("", true)
|
|
2776
2818
|
], 32)
|
|
2777
2819
|
], 6),
|
package/lib/style.css
CHANGED
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
|
}
|
|
@@ -36,12 +36,7 @@
|
|
|
36
36
|
@scroll="onTableScroll"
|
|
37
37
|
@wheel="onTableWheel"
|
|
38
38
|
>
|
|
39
|
-
|
|
40
|
-
<div
|
|
41
|
-
v-if="isSRBRActive && virtual"
|
|
42
|
-
class="row-by-row-table-height"
|
|
43
|
-
:style="{ height: dataSourceCopy.length * virtualScroll.rowHeight + 'px' }"
|
|
44
|
-
></div>
|
|
39
|
+
<div v-if="SRBRTotalHeight" class="row-by-row-table-height" :style="`height: ${SRBRTotalHeight}px`"></div>
|
|
45
40
|
|
|
46
41
|
<div v-if="colResizable" ref="colResizeIndicatorRef" class="column-resize-indicator"></div>
|
|
47
42
|
<table
|
|
@@ -240,6 +235,7 @@
|
|
|
240
235
|
</template>
|
|
241
236
|
</tr>
|
|
242
237
|
<tr v-if="virtual_on && !isSRBRActive" :style="`height: ${virtual_offsetBottom}px`"></tr>
|
|
238
|
+
<tr v-if="SRBRBottomHeight" :style="`height: ${SRBRBottomHeight}px`"></tr>
|
|
243
239
|
</tbody>
|
|
244
240
|
</table>
|
|
245
241
|
<div v-if="(!dataSourceCopy || !dataSourceCopy.length) && showNoData" class="stk-table-no-data" :class="{ 'no-data-full': noDataFull }">
|
|
@@ -257,7 +253,7 @@ import { CSSProperties, computed, nextTick, onMounted, ref, shallowRef, toRaw, w
|
|
|
257
253
|
import DragHandle from './components/DragHandle.vue';
|
|
258
254
|
import SortIcon from './components/SortIcon.vue';
|
|
259
255
|
import TriangleIcon from './components/TriangleIcon.vue';
|
|
260
|
-
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';
|
|
261
257
|
import {
|
|
262
258
|
AutoRowHeightConfig,
|
|
263
259
|
ColResizableConfig,
|
|
@@ -477,10 +473,7 @@ const props = withDefaults(
|
|
|
477
473
|
autoResize: true,
|
|
478
474
|
fixedColShadow: false,
|
|
479
475
|
optimizeVue2Scroll: false,
|
|
480
|
-
sortConfig: () =>
|
|
481
|
-
emptyToBottom: false,
|
|
482
|
-
stringLocaleCompare: false,
|
|
483
|
-
}),
|
|
476
|
+
sortConfig: () => DEFAULT_SORT_CONFIG,
|
|
484
477
|
hideHeaderTitle: false,
|
|
485
478
|
highlightConfig: () => ({}),
|
|
486
479
|
seqConfig: () => ({}),
|
|
@@ -744,6 +737,19 @@ const getEmptyCellText = computed(() => {
|
|
|
744
737
|
}
|
|
745
738
|
});
|
|
746
739
|
|
|
740
|
+
/** scroll-row-by-row total-height */
|
|
741
|
+
const SRBRTotalHeight = computed(() => {
|
|
742
|
+
if (!isSRBRActive.value || !props.virtual) return 0;
|
|
743
|
+
return (
|
|
744
|
+
dataSourceCopy.value.length * virtualScroll.value.rowHeight + tableHeaderHeight.value //+
|
|
745
|
+
);
|
|
746
|
+
});
|
|
747
|
+
const SRBRBottomHeight = computed(() => {
|
|
748
|
+
if (!isSRBRActive.value || !props.virtual) return 0;
|
|
749
|
+
const { containerHeight, rowHeight } = virtualScroll.value;
|
|
750
|
+
return (containerHeight - tableHeaderHeight.value) % rowHeight;
|
|
751
|
+
});
|
|
752
|
+
|
|
747
753
|
const rowKeyGenCache = new WeakMap();
|
|
748
754
|
|
|
749
755
|
const { isSRBRActive } = useScrollRowByRow({ props, tableContainerRef });
|
|
@@ -763,6 +769,7 @@ const {
|
|
|
763
769
|
virtualX_on,
|
|
764
770
|
virtualX_columnPart,
|
|
765
771
|
virtualX_offsetRight,
|
|
772
|
+
tableHeaderHeight,
|
|
766
773
|
initVirtualScroll,
|
|
767
774
|
initVirtualScrollY,
|
|
768
775
|
initVirtualScrollX,
|
|
@@ -880,7 +887,7 @@ watch(
|
|
|
880
887
|
console.warn('invalid dataSource');
|
|
881
888
|
return;
|
|
882
889
|
}
|
|
883
|
-
|
|
890
|
+
|
|
884
891
|
let needInitVirtualScrollY = false;
|
|
885
892
|
if (dataSourceCopy.value.length !== val.length) {
|
|
886
893
|
needInitVirtualScrollY = true;
|
|
@@ -1122,8 +1129,8 @@ function onColumnSort(col: StkTableColumn<DT> | undefined | null, click = true,
|
|
|
1122
1129
|
sortOrderIndex.value = sortOrderIndex.value % 3;
|
|
1123
1130
|
|
|
1124
1131
|
let order = sortSwitchOrder[sortOrderIndex.value];
|
|
1125
|
-
const sortConfig = { ...props.sortConfig, ...col.sortConfig };
|
|
1126
|
-
const defaultSort = sortConfig
|
|
1132
|
+
const sortConfig: SortConfig<any> = { ...DEFAULT_SORT_CONFIG, ...props.sortConfig, ...col.sortConfig };
|
|
1133
|
+
const { defaultSort } = sortConfig;
|
|
1127
1134
|
const colKeyGenValue = colKeyGen.value;
|
|
1128
1135
|
|
|
1129
1136
|
if (!order && defaultSort) {
|
|
@@ -1149,15 +1156,17 @@ function onColumnSort(col: StkTableColumn<DT> | undefined | null, click = true,
|
|
|
1149
1156
|
}
|
|
1150
1157
|
}
|
|
1151
1158
|
}
|
|
1159
|
+
let dataSourceTemp: any[] = props.dataSource.slice();
|
|
1152
1160
|
if (!props.sortRemote || options.force) {
|
|
1153
1161
|
const sortOption = col || defaultSort;
|
|
1154
1162
|
if (sortOption) {
|
|
1155
|
-
|
|
1163
|
+
dataSourceTemp = tableSort(sortOption, order, dataSourceTemp, sortConfig);
|
|
1164
|
+
dataSourceCopy.value = isTreeData.value ? flatTreeData(dataSourceTemp) : dataSourceTemp;
|
|
1156
1165
|
}
|
|
1157
1166
|
}
|
|
1158
|
-
// 只有点击才触发事件
|
|
1167
|
+
// 只有点击才触发事件 en: only emit sort-change event when click
|
|
1159
1168
|
if (click || options.emit) {
|
|
1160
|
-
emits('sort-change', col, order, toRaw(
|
|
1169
|
+
emits('sort-change', col, order, toRaw(dataSourceTemp), sortConfig);
|
|
1161
1170
|
}
|
|
1162
1171
|
}
|
|
1163
1172
|
|
|
@@ -1346,7 +1355,7 @@ function onTableScroll(e: Event) {
|
|
|
1346
1355
|
}
|
|
1347
1356
|
|
|
1348
1357
|
if (isYScroll) {
|
|
1349
|
-
const {
|
|
1358
|
+
const { startIndex, endIndex } = virtualScroll.value;
|
|
1350
1359
|
emits('scroll', e, { startIndex, endIndex });
|
|
1351
1360
|
}
|
|
1352
1361
|
if (isXScroll) {
|
|
@@ -1382,15 +1391,32 @@ function onTrMouseLeave(e: MouseEvent) {
|
|
|
1382
1391
|
* 选中一行
|
|
1383
1392
|
* @param {string} rowKeyOrRow selected rowKey, undefined to unselect
|
|
1384
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
|
|
1385
1395
|
*/
|
|
1386
|
-
function setCurrentRow(rowKeyOrRow: string | undefined | DT, option = { silent: false }) {
|
|
1396
|
+
function setCurrentRow(rowKeyOrRow: string | undefined | DT, option = { silent: false, deep: false }) {
|
|
1387
1397
|
if (!dataSourceCopy.value.length) return;
|
|
1388
1398
|
const select = rowKeyOrRow !== void 0;
|
|
1389
1399
|
if (!select) {
|
|
1390
1400
|
currentRow.value = void 0;
|
|
1391
1401
|
currentRowKey.value = void 0;
|
|
1392
1402
|
} else if (typeof rowKeyOrRow === 'string') {
|
|
1393
|
-
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);
|
|
1394
1420
|
if (!row) {
|
|
1395
1421
|
console.warn('setCurrentRow failed.rowKey:', rowKeyOrRow);
|
|
1396
1422
|
return;
|
|
@@ -1438,7 +1464,6 @@ function setSorter(colKey: string, order: Order, option: { sortOption?: SortOpti
|
|
|
1438
1464
|
const colKeyGenValue = colKeyGen.value;
|
|
1439
1465
|
|
|
1440
1466
|
if (newOption.sort && dataSourceCopy.value?.length) {
|
|
1441
|
-
// 如果表格有数据,则进行排序
|
|
1442
1467
|
const column = newOption.sortOption || tableHeaderLast.value.find(it => colKeyGenValue(it) === sortCol.value);
|
|
1443
1468
|
if (column) onColumnSort(column, false, { force: option.force ?? true, emit: !newOption.silent });
|
|
1444
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>;
|
package/src/StkTable/style.less
CHANGED
|
@@ -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
|
}
|