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.
@@ -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 = { emptyToBottom: false, ...sortConfig };
137
+ sortConfig = { ...DEFAULT_SORT_CONFIG, ...sortConfig };
138
138
  let targetDataSource = dataSource.slice();
139
139
  let sortField = sortOption.sortField || sortOption.dataIndex;
140
- if (!order && sortConfig.defaultSort) {
141
- order = sortConfig.defaultSort.order;
142
- sortField = sortConfig.defaultSort.dataIndex;
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, sortConfig.stringLocaleCompare));
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
- targetDataSource = emptyArr.concat(valueArr);
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
- if (!ScrollCodesValues.includes(e.code)) return;
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 (e.code === "ArrowUp") {
845
+ if (keyCode === "ArrowUp") {
829
846
  scrollTo(scrollTop - rowHeight, null);
830
- } else if (e.code === "ArrowRight") {
847
+ } else if (keyCode === "ArrowRight") {
831
848
  scrollTo(null, scrollLeft + 50);
832
- } else if (e.code === "ArrowDown") {
849
+ } else if (keyCode === "ArrowDown") {
833
850
  scrollTo(scrollTop + rowHeight, null);
834
- } else if (e.code === "ArrowLeft") {
851
+ } else if (keyCode === "ArrowLeft") {
835
852
  scrollTo(null, scrollLeft - 50);
836
- } else if (e.code === "PageUp") {
853
+ } else if (keyCode === "PageUp") {
837
854
  scrollTo(scrollTop - rowHeight * bodyPageSize + headerHeight, null);
838
- } else if (e.code === "PageDown") {
855
+ } else if (keyCode === "PageDown") {
839
856
  scrollTo(scrollTop + rowHeight * bodyPageSize - headerHeight, null);
840
- } else if (e.code === "Home") {
857
+ } else if (keyCode === "Home") {
841
858
  scrollTo(0, null);
842
- } else if (e.code === "End") {
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 = ref(props.headerRowHeight);
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 { offsetHeight, scrollHeight } = tableContainerRef.value || {};
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 || offsetHeight || DEFAULT_TABLE_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(headerHeight / rowHeight);
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.defaultSort;
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
- dataSourceCopy.value = tableSort(sortOption, order, props.dataSource, sortConfig);
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(dataSourceCopy.value), sortConfig);
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 row = dataSourceCopy.value.find((it) => rowKeyGen(it) === rowKeyOrRow);
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
- unref(isSRBRActive) && _ctx.virtual ? (openBlock(), createElementBlock("div", {
2555
+ SRBRTotalHeight.value ? (openBlock(), createElementBlock("div", {
2518
2556
  key: 0,
2519
2557
  class: "row-by-row-table-height",
2520
- style: normalizeStyle({ height: dataSourceCopy.value.length * unref(virtualScroll).rowHeight + "px" })
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
@@ -184,8 +184,10 @@
184
184
  }
185
185
  .stk-table .row-by-row-table-height{
186
186
  width:1px;
187
+ flex-shrink:0;
187
188
  position:absolute;
188
189
  left:0;
190
+ top:0;
189
191
  }
190
192
  .stk-table th,
191
193
  .stk-table td{
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stk-table-vue",
3
- "version": "0.8.6",
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.1",
62
+ "stk-table-vue": "^0.8.7",
63
63
  "typescript": "^5.8.3",
64
- "vite": "^7.0.2",
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.5",
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.17",
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.defaultSort;
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
- dataSourceCopy.value = tableSort(sortOption, order, props.dataSource, sortConfig);
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(dataSourceCopy.value), sortConfig);
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 { startIndex, endIndex } = virtualScroll.value;
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 row = dataSourceCopy.value.find(it => rowKeyGen(it) === rowKeyOrRow);
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);
@@ -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>;
@@ -275,8 +275,10 @@
275
275
 
276
276
  .row-by-row-table-height {
277
277
  width: 1px;
278
+ flex-shrink: 0;
278
279
  position: absolute;
279
280
  left: 0;
281
+ top: 0;
280
282
  }
281
283
 
282
284
  th,
@@ -88,7 +88,7 @@ export type StkTableColumn<T extends Record<string, any>> = {
88
88
  /** 排序方式。按数字/字符串 */
89
89
  sortType?: 'number' | 'string';
90
90
  /** 配置当前列的排序规则 */
91
- sortConfig?: Pick<SortConfig<T>, 'emptyToBottom' | 'stringLocaleCompare'>;
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
- * 默认排序(1.初始化时触发 2.排序方向为null时触发)
183
- * 类似onMounted时,调用setSorter点了下表头。
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
- * 如果您配了 `props.colKey` 则这里表示的列唯一键的值
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
- /** 是否禁止触发sort-change事件。默认false,表示触发事件。 */
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
- if (!ScrollCodesValues.includes(e.code as any)) return;
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 (e.code === ScrollCodes.ArrowRight) {
82
+ } else if (keyCode=== ScrollCodes.ArrowRight) {
83
83
  scrollTo(null, scrollLeft + 50);
84
- } else if (e.code === ScrollCodes.ArrowDown) {
84
+ } else if (keyCode=== ScrollCodes.ArrowDown) {
85
85
  scrollTo(scrollTop + rowHeight, null);
86
- } else if (e.code === ScrollCodes.ArrowLeft) {
86
+ } else if (keyCode=== ScrollCodes.ArrowLeft) {
87
87
  scrollTo(null, scrollLeft - 50);
88
- } else if (e.code === ScrollCodes.PageUp) {
88
+ } else if (keyCode=== ScrollCodes.PageUp) {
89
89
  scrollTo(scrollTop - rowHeight * bodyPageSize + headerHeight, null);
90
- } else if (e.code === ScrollCodes.PageDown) {
90
+ } else if (keyCode=== ScrollCodes.PageDown) {
91
91
  scrollTo(scrollTop + rowHeight * bodyPageSize - headerHeight, null);
92
- } else if (e.code === ScrollCodes.Home) {
92
+ } else if (keyCode=== ScrollCodes.Home) {
93
93
  scrollTo(0, null);
94
- } else if (e.code === ScrollCodes.End) {
94
+ } else if (keyCode=== ScrollCodes.End) {
95
95
  scrollTo(scrollHeight, null);
96
96
  }
97
97
  }