stk-table-vue 0.6.17 → 0.7.1

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.
Files changed (40) hide show
  1. package/README.md +211 -213
  2. package/lib/src/StkTable/StkTable.vue.d.ts +43 -24
  3. package/lib/src/StkTable/components/TriangleIcon.vue.d.ts +2 -0
  4. package/lib/src/StkTable/const.d.ts +0 -1
  5. package/lib/src/StkTable/types/highlightDimOptions.d.ts +1 -5
  6. package/lib/src/StkTable/types/index.d.ts +27 -7
  7. package/lib/src/StkTable/useHighlight.d.ts +1 -1
  8. package/lib/src/StkTable/useRowExpand.d.ts +17 -0
  9. package/lib/src/StkTable/useTree.d.ts +20 -0
  10. package/lib/src/StkTable/utils/index.d.ts +3 -1
  11. package/lib/stk-table-vue.js +320 -167
  12. package/lib/style.css +29 -20
  13. package/package.json +74 -75
  14. package/src/StkTable/StkTable.vue +1557 -1550
  15. package/src/StkTable/components/DragHandle.vue +9 -9
  16. package/src/StkTable/components/SortIcon.vue +6 -6
  17. package/src/StkTable/components/TriangleIcon.vue +3 -0
  18. package/src/StkTable/const.ts +37 -37
  19. package/src/StkTable/index.ts +4 -4
  20. package/src/StkTable/style.less +567 -553
  21. package/src/StkTable/types/highlightDimOptions.ts +26 -26
  22. package/src/StkTable/types/index.ts +260 -239
  23. package/src/StkTable/useAutoResize.ts +91 -91
  24. package/src/StkTable/useColResize.ts +216 -216
  25. package/src/StkTable/useFixedCol.ts +148 -148
  26. package/src/StkTable/useFixedStyle.ts +75 -75
  27. package/src/StkTable/useGetFixedColPosition.ts +65 -65
  28. package/src/StkTable/useHighlight.ts +320 -318
  29. package/src/StkTable/useKeyboardArrowScroll.ts +112 -112
  30. package/src/StkTable/useRowExpand.ts +78 -0
  31. package/src/StkTable/useThDrag.ts +102 -102
  32. package/src/StkTable/useTrDrag.ts +118 -118
  33. package/src/StkTable/useTree.ts +158 -0
  34. package/src/StkTable/useVirtualScroll.ts +462 -462
  35. package/src/StkTable/utils/constRefUtils.ts +29 -29
  36. package/src/StkTable/utils/index.ts +224 -212
  37. package/src/StkTable/utils/useTriggerRef.ts +33 -33
  38. package/src/VirtualTree.vue +622 -622
  39. package/src/VirtualTreeSelect.vue +367 -367
  40. package/src/vite-env.d.ts +10 -10
@@ -1,5 +1,4 @@
1
- import { createElementBlock, openBlock, createElementVNode, watch, onMounted, onBeforeUnmount, ref, computed, shallowRef, defineComponent, nextTick, toRaw, normalizeStyle, normalizeClass, unref, createCommentVNode, renderSlot, Fragment, renderList, createBlock, resolveDynamicComponent, toDisplayString, createTextVNode, createVNode } from "vue";
2
- import { interpolateRgb } from "d3-interpolate";
1
+ import { createElementBlock, openBlock, createElementVNode, watch, onMounted, onBeforeUnmount, ref, computed, shallowRef, defineComponent, nextTick, toRaw, normalizeStyle, normalizeClass, unref, createCommentVNode, renderSlot, Fragment, renderList, createBlock, resolveDynamicComponent, toDisplayString, createTextVNode, withCtx, createVNode } from "vue";
3
2
  const _export_sfc = (sfc, props) => {
4
3
  const target = sfc.__vccOpts || sfc;
5
4
  for (const [key, val] of props) {
@@ -7,13 +6,13 @@ const _export_sfc = (sfc, props) => {
7
6
  }
8
7
  return target;
9
8
  };
10
- const _sfc_main$2 = {};
11
- const _hoisted_1$2 = {
9
+ const _sfc_main$3 = {};
10
+ const _hoisted_1$3 = {
12
11
  class: "drag-row-handle",
13
12
  draggable: "true"
14
13
  };
15
- function _sfc_render$1(_ctx, _cache) {
16
- return openBlock(), createElementBlock("span", _hoisted_1$2, _cache[0] || (_cache[0] = [
14
+ function _sfc_render$2(_ctx, _cache) {
15
+ return openBlock(), createElementBlock("span", _hoisted_1$3, _cache[0] || (_cache[0] = [
17
16
  createElementVNode("svg", {
18
17
  viewBox: "0 0 1024 1024",
19
18
  width: "16",
@@ -24,16 +23,16 @@ function _sfc_render$1(_ctx, _cache) {
24
23
  ], -1)
25
24
  ]));
26
25
  }
27
- const DragHandle = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["render", _sfc_render$1]]);
28
- const _sfc_main$1 = {};
29
- const _hoisted_1$1 = {
26
+ const DragHandle = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["render", _sfc_render$2]]);
27
+ const _sfc_main$2 = {};
28
+ const _hoisted_1$2 = {
30
29
  xmlns: "http://www.w3.org/2000/svg",
31
30
  width: "16px",
32
31
  height: "16px",
33
32
  viewBox: "0 0 16 16"
34
33
  };
35
- function _sfc_render(_ctx, _cache) {
36
- return openBlock(), createElementBlock("svg", _hoisted_1$1, _cache[0] || (_cache[0] = [
34
+ function _sfc_render$1(_ctx, _cache) {
35
+ return openBlock(), createElementBlock("svg", _hoisted_1$2, _cache[0] || (_cache[0] = [
37
36
  createElementVNode("polygon", {
38
37
  class: "arrow-up",
39
38
  fill: "#757699",
@@ -46,7 +45,13 @@ function _sfc_render(_ctx, _cache) {
46
45
  }, null, -1)
47
46
  ]));
48
47
  }
49
- const SortIcon = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["render", _sfc_render]]);
48
+ const SortIcon = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["render", _sfc_render$1]]);
49
+ const _sfc_main$1 = {};
50
+ const _hoisted_1$1 = { class: "stk-fold-icon" };
51
+ function _sfc_render(_ctx, _cache) {
52
+ return openBlock(), createElementBlock("div", _hoisted_1$1);
53
+ }
54
+ const TriangleIcon = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["render", _sfc_render]]);
50
55
  function isEmptyValue(val, isNumber) {
51
56
  let isEmpty = val === null || val === void 0;
52
57
  if (isNumber) {
@@ -55,24 +60,28 @@ function isEmptyValue(val, isNumber) {
55
60
  return isEmpty;
56
61
  }
57
62
  function insertToOrderedArray(sortState, newItem, targetArray, sortConfig = {}) {
58
- const { dataIndex, order } = sortState;
59
- sortConfig = { emptyToBottom: false, ...sortConfig };
63
+ const { dataIndex, sortField, order } = sortState;
60
64
  let { sortType } = sortState;
61
- if (!sortType) sortType = typeof newItem[dataIndex];
65
+ const field = sortField || dataIndex;
66
+ if (!sortType) sortType = typeof newItem[field];
62
67
  const data = targetArray.slice();
63
68
  if (!order || !data.length) {
64
69
  data.unshift(newItem);
65
70
  return data;
66
71
  }
67
- const targetVal = newItem[dataIndex];
68
- if (sortConfig.emptyToBottom && isEmptyValue(targetVal)) {
72
+ const { emptyToBottom, customCompare, stringLocaleCompare } = { emptyToBottom: false, ...sortConfig };
73
+ const targetVal = newItem[field];
74
+ if (emptyToBottom && isEmptyValue(targetVal)) {
69
75
  data.push(newItem);
70
76
  } else {
77
+ const customCompareFn = customCompare || ((a, b) => {
78
+ const midVal = a[field];
79
+ const compareRes = strCompare(midVal, targetVal, isNumber, stringLocaleCompare);
80
+ return order === "asc" ? compareRes : -compareRes;
81
+ });
71
82
  const isNumber = sortType === "number";
72
83
  const sIndex = binarySearch(data, (midIndex) => {
73
- const midVal = data[midIndex][dataIndex];
74
- const compareRes = strCompare(midVal, targetVal, isNumber, sortConfig.stringLocaleCompare);
75
- return order === "asc" ? compareRes : -compareRes;
84
+ return customCompareFn(data[midIndex], newItem);
76
85
  });
77
86
  data.splice(sIndex, 0, newItem);
78
87
  }
@@ -189,7 +198,6 @@ const HIGHLIGHT_COLOR = {
189
198
  dark: { from: "#1e4c99", to: "#181c21" }
190
199
  };
191
200
  const HIGHLIGHT_DURATION = 2e3;
192
- const HIGHLIGHT_FREQ = 1e3 / 30;
193
201
  const HIGHLIGHT_ROW_CLASS = "highlight-row";
194
202
  const HIGHLIGHT_CELL_CLASS = "highlight-cell";
195
203
  const _chromeVersion = getBrowsersVersion("chrome");
@@ -610,25 +618,21 @@ function useHighlight({ props, stkTableId, tableContainerRef }) {
610
618
  light: HIGHLIGHT_COLOR.light,
611
619
  dark: HIGHLIGHT_COLOR.dark
612
620
  };
613
- const highlightDuration = config.duration ? config.duration * 1e3 : HIGHLIGHT_DURATION;
614
- const highlightFrequency = config.fps && config.fps > 0 ? 1e3 / config.fps : null;
615
- const highlightSteps = highlightFrequency ? Math.round(highlightDuration / highlightFrequency) : null;
621
+ const highlightDuration = computed(() => config.duration ? config.duration * 1e3 : HIGHLIGHT_DURATION);
622
+ const highlightFrequency = computed(() => config.fps && config.fps > 0 ? 1e3 / config.fps : null);
623
+ const highlightSteps = computed(() => highlightFrequency.value ? Math.round(highlightDuration.value / highlightFrequency.value) : null);
616
624
  const highlightFrom = computed(() => highlightColor[props.theme].from);
617
- const highlightTo = computed(() => highlightColor[props.theme].to);
618
- const highlightInter = computed(() => interpolateRgb(highlightFrom.value, highlightTo.value));
619
- const highlightDimRowsJs = /* @__PURE__ */ new Map();
620
- let calcHighlightDimLoopJs = false;
621
625
  const highlightDimRowsAnimation = /* @__PURE__ */ new Map();
622
626
  let calcHighlightDimLoopAnimation = false;
623
627
  const highlightDimRowsTimeout = /* @__PURE__ */ new Map();
624
628
  const highlightDimCellsTimeout = /* @__PURE__ */ new Map();
625
- const defaultHighlightDimOption = (() => {
629
+ const defaultHighlightDimOption = computed(() => {
626
630
  const keyframe = { backgroundColor: [highlightFrom.value, ""] };
627
- if (highlightSteps) {
628
- keyframe.easing = `steps(${highlightSteps})`;
631
+ if (highlightSteps.value) {
632
+ keyframe.easing = `steps(${highlightSteps.value})`;
629
633
  }
630
- return { duration: highlightDuration, keyframe };
631
- })();
634
+ return { duration: highlightDuration.value, keyframe };
635
+ });
632
636
  function calcRowHighlightLoop() {
633
637
  if (calcHighlightDimLoopAnimation) return;
634
638
  calcHighlightDimLoopAnimation = true;
@@ -656,39 +660,13 @@ function useHighlight({ props, stkTableId, tableContainerRef }) {
656
660
  };
657
661
  recursion();
658
662
  }
659
- function calcRowHighlightLoopJs() {
660
- if (calcHighlightDimLoopJs) return;
661
- calcHighlightDimLoopJs = true;
662
- const recursion = () => {
663
- window.setTimeout(() => {
664
- const nowTs = Date.now();
665
- highlightDimRowsJs.forEach((highlightStart, rowKeyValue) => {
666
- const progress = (nowTs - highlightStart) / highlightDuration;
667
- let bgc = "";
668
- if (0 <= progress && progress <= 1) {
669
- bgc = highlightInter.value(progress);
670
- } else {
671
- highlightDimRowsJs.delete(rowKeyValue);
672
- }
673
- updateRowBgcJs(rowKeyValue, bgc);
674
- });
675
- if (highlightDimRowsJs.size > 0) {
676
- recursion();
677
- } else {
678
- calcHighlightDimLoopJs = false;
679
- highlightDimRowsJs.clear();
680
- }
681
- }, highlightFrequency || HIGHLIGHT_FREQ);
682
- };
683
- recursion();
684
- }
685
663
  function setHighlightDimCell(rowKeyValue, colKeyValue, option = {}) {
686
664
  var _a;
687
665
  const cellEl = (_a = tableContainerRef.value) == null ? void 0 : _a.querySelector(`[data-cell-key="${rowKeyValue}--${colKeyValue}"]`);
688
666
  const { className, method, duration, keyframe } = {
689
667
  className: HIGHLIGHT_CELL_CLASS,
690
668
  method: "animation",
691
- ...defaultHighlightDimOption,
669
+ ...defaultHighlightDimOption.value,
692
670
  ...option
693
671
  };
694
672
  if (!cellEl) return;
@@ -703,7 +681,7 @@ function useHighlight({ props, stkTableId, tableContainerRef }) {
703
681
  const { className, method, keyframe, duration } = {
704
682
  className: HIGHLIGHT_ROW_CLASS,
705
683
  method: "animation",
706
- ...defaultHighlightDimOption,
684
+ ...defaultHighlightDimOption.value,
707
685
  ...option
708
686
  };
709
687
  if (method === "css") {
@@ -725,14 +703,6 @@ function useHighlight({ props, stkTableId, tableContainerRef }) {
725
703
  rowEl.animate(keyframe, duration);
726
704
  }
727
705
  }
728
- } else if (method === "js") {
729
- const nowTs = Date.now();
730
- for (let i = 0; i < rowKeyValues.length; i++) {
731
- const rowKeyValue = rowKeyValues[i];
732
- highlightDimRowsJs.set(rowKeyValue, nowTs);
733
- updateRowBgcJs(rowKeyValue, highlightFrom.value);
734
- }
735
- calcRowHighlightLoopJs();
736
706
  }
737
707
  }
738
708
  function highlightRowsInCssKeyframe(rowKeyValues, className, duration) {
@@ -798,11 +768,6 @@ function useHighlight({ props, stkTableId, tableContainerRef }) {
798
768
  });
799
769
  }
800
770
  }
801
- function updateRowBgcJs(rowKeyValue, color) {
802
- const rowEl = document.getElementById(stkTableId + "-" + String(rowKeyValue));
803
- if (!rowEl) return;
804
- rowEl.style.backgroundColor = color;
805
- }
806
771
  return {
807
772
  highlightSteps,
808
773
  setHighlightDimRow,
@@ -884,6 +849,57 @@ function useKeyboardArrowScroll(targetElement, { props, scrollTo, virtualScroll,
884
849
  if (!isMouseOver) isMouseOver = true;
885
850
  }
886
851
  }
852
+ function useRowExpand({ dataSourceCopy, rowKeyGen, emits }) {
853
+ function toggleExpandRow(row, col) {
854
+ const isExpand = (row == null ? void 0 : row.__EXPANDED__) === col ? !(row == null ? void 0 : row.__EXPANDED__) : true;
855
+ setRowExpand(row, isExpand, { col });
856
+ }
857
+ function setRowExpand(rowKeyOrRow, expand, data) {
858
+ let rowKey;
859
+ if (typeof rowKeyOrRow === "string") {
860
+ rowKey = rowKeyOrRow;
861
+ } else {
862
+ rowKey = rowKeyGen(rowKeyOrRow);
863
+ }
864
+ const tempData = dataSourceCopy.value.slice();
865
+ const index = tempData.findIndex((it) => rowKeyGen(it) === rowKey);
866
+ if (index === -1) {
867
+ console.warn("expandRow failed.rowKey:", rowKey);
868
+ return;
869
+ }
870
+ for (let i = index + 1; i < tempData.length; i++) {
871
+ const item = tempData[i];
872
+ const rowKey2 = item.__ROW_KEY__;
873
+ if (rowKey2 == null ? void 0 : rowKey2.startsWith(EXPANDED_ROW_KEY_PREFIX)) {
874
+ tempData.splice(i, 1);
875
+ i--;
876
+ } else {
877
+ break;
878
+ }
879
+ }
880
+ const row = tempData[index];
881
+ const col = (data == null ? void 0 : data.col) || null;
882
+ if (expand) {
883
+ const newExpandRow = {
884
+ __ROW_KEY__: EXPANDED_ROW_KEY_PREFIX + rowKey,
885
+ __EXPANDED_ROW__: row,
886
+ __EXPANDED_COL__: col
887
+ };
888
+ tempData.splice(index + 1, 0, newExpandRow);
889
+ }
890
+ if (row) {
891
+ row.__EXPANDED__ = expand ? col : null;
892
+ }
893
+ dataSourceCopy.value = tempData;
894
+ if (!(data == null ? void 0 : data.silent)) {
895
+ emits("toggle-row-expand", { expanded: Boolean(expand), row, col });
896
+ }
897
+ }
898
+ return {
899
+ toggleExpandRow,
900
+ setRowExpand
901
+ };
902
+ }
887
903
  function useThDrag({ props, emits, colKeyGen }) {
888
904
  const findParentTH = (e) => e.target.closest("th");
889
905
  const dragConfig = computed(() => {
@@ -1364,6 +1380,125 @@ function useVirtualScroll({
1364
1380
  clearAllAutoHeight
1365
1381
  };
1366
1382
  }
1383
+ function useTree({ props, dataSourceCopy, rowKeyGen, emits }) {
1384
+ const { defaultExpandAll, defaultExpandKeys, defaultExpandLevel } = props.treeConfig;
1385
+ function toggleTreeNode(row, col) {
1386
+ const expand = row ? !row.__T_EXPANDED__ : false;
1387
+ privateSetTreeExpand(row, { expand, col, isClick: true });
1388
+ }
1389
+ function privateSetTreeExpand(row, option) {
1390
+ const rowKeyOrRowArr = Array.isArray(row) ? row : [row];
1391
+ const tempData = dataSourceCopy.value.slice();
1392
+ for (let i = 0; i < rowKeyOrRowArr.length; i++) {
1393
+ const rowKeyOrRow = rowKeyOrRowArr[i];
1394
+ let rowKey;
1395
+ if (typeof rowKeyOrRow === "string") {
1396
+ rowKey = rowKeyOrRow;
1397
+ } else {
1398
+ rowKey = rowKeyGen(rowKeyOrRow);
1399
+ }
1400
+ const index = tempData.findIndex((it) => rowKeyGen(it) === rowKey);
1401
+ if (index === -1) {
1402
+ console.warn("treeExpandRow failed.rowKey:", rowKey);
1403
+ return;
1404
+ }
1405
+ const row2 = tempData[index];
1406
+ const level = row2.__T_LV__ || 0;
1407
+ let expanded = option == null ? void 0 : option.expand;
1408
+ if (expanded === void 0) {
1409
+ expanded = !row2.__T_EXPANDED__;
1410
+ }
1411
+ if (expanded) {
1412
+ const children = expandNode(row2, level);
1413
+ tempData.splice(index + 1, 0, ...children);
1414
+ } else {
1415
+ const deleteCount = foldNode(index, tempData, level);
1416
+ tempData.splice(index + 1, deleteCount);
1417
+ }
1418
+ setNodeExpanded(row2, expanded, level);
1419
+ if (option.isClick) {
1420
+ emits("toggle-tree-expand", { expanded: Boolean(expanded), row: row2, col: option.col });
1421
+ }
1422
+ }
1423
+ dataSourceCopy.value = tempData;
1424
+ }
1425
+ function setTreeExpand(row, option) {
1426
+ privateSetTreeExpand(row, { ...option, isClick: false });
1427
+ }
1428
+ function setNodeExpanded(row, expanded, level, parent) {
1429
+ row.__T_EXPANDED__ = expanded;
1430
+ if (level !== void 0) {
1431
+ row.__T_LV__ = level;
1432
+ }
1433
+ if (parent) {
1434
+ row.__T_PARENT_K__ = rowKeyGen(parent);
1435
+ }
1436
+ }
1437
+ function flatTreeData(data) {
1438
+ const result = [];
1439
+ (function recursion(data2, level, parent) {
1440
+ if (!data2) return;
1441
+ for (let i = 0; i < data2.length; i++) {
1442
+ const item = data2[i];
1443
+ result.push(item);
1444
+ const isExpanded = Boolean(item.__T_EXPANDED__);
1445
+ setNodeExpanded(item, isExpanded, level, parent);
1446
+ if (!isExpanded) {
1447
+ if (defaultExpandAll) {
1448
+ setNodeExpanded(item, true);
1449
+ } else {
1450
+ if (defaultExpandLevel) {
1451
+ if (level < defaultExpandLevel) {
1452
+ setNodeExpanded(item, true);
1453
+ }
1454
+ }
1455
+ if (defaultExpandKeys) {
1456
+ if (defaultExpandKeys.includes(rowKeyGen(item))) {
1457
+ setNodeExpanded(item, true);
1458
+ }
1459
+ }
1460
+ if (!item.__T_EXPANDED__) {
1461
+ continue;
1462
+ }
1463
+ }
1464
+ }
1465
+ recursion(item.children, level + 1, item);
1466
+ }
1467
+ })(data, 0);
1468
+ return result;
1469
+ }
1470
+ function expandNode(row, level) {
1471
+ let result = [];
1472
+ row.children && row.children.forEach((child) => {
1473
+ result.push(child);
1474
+ const childLv = level + 1;
1475
+ if (child.__T_EXPANDED__ && child.children) {
1476
+ const res = expandNode(child, childLv);
1477
+ result = result.concat(res);
1478
+ } else {
1479
+ setNodeExpanded(child, false, childLv, row);
1480
+ }
1481
+ });
1482
+ return result;
1483
+ }
1484
+ function foldNode(index, tempData, level) {
1485
+ let deleteCount = 0;
1486
+ for (let i = index + 1; i < tempData.length; i++) {
1487
+ const child = tempData[i];
1488
+ if (child.__T_LV__ && child.__T_LV__ > level) {
1489
+ deleteCount++;
1490
+ } else {
1491
+ break;
1492
+ }
1493
+ }
1494
+ return deleteCount;
1495
+ }
1496
+ return {
1497
+ toggleTreeNode,
1498
+ setTreeExpand,
1499
+ flatTreeData
1500
+ };
1501
+ }
1367
1502
  const _hoisted_1 = ["data-col-key", "draggable", "rowspan", "colspan", "title", "onClick"];
1368
1503
  const _hoisted_2 = ["onMousedown"];
1369
1504
  const _hoisted_3 = { class: "table-header-title" };
@@ -1381,7 +1516,7 @@ const _hoisted_8 = ["colspan"];
1381
1516
  const _hoisted_9 = { class: "table-cell-wrapper" };
1382
1517
  const _hoisted_10 = ["data-cell-key", "onClick", "onMousedown", "onMouseenter", "onMouseleave", "onMouseover"];
1383
1518
  const _hoisted_11 = ["title"];
1384
- const _hoisted_12 = { key: 1 };
1519
+ const _hoisted_12 = ["title"];
1385
1520
  const _sfc_main = /* @__PURE__ */ defineComponent({
1386
1521
  __name: "StkTable",
1387
1522
  props: {
@@ -1403,7 +1538,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1403
1538
  columns: { default: () => [] },
1404
1539
  dataSource: { default: () => [] },
1405
1540
  rowKey: { type: [String, Number, Function], default: "" },
1406
- colKey: { type: [String, Number, Function], default: "dataIndex" },
1541
+ colKey: {},
1407
1542
  emptyCellText: { type: [String, Function], default: "--" },
1408
1543
  noDataFull: { type: Boolean, default: false },
1409
1544
  showNoData: { type: Boolean, default: true },
@@ -1414,7 +1549,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1414
1549
  cellHover: { type: Boolean, default: false },
1415
1550
  cellActive: { type: Boolean, default: false },
1416
1551
  selectedCellRevokable: { type: Boolean, default: true },
1417
- headerDrag: { default: false },
1552
+ headerDrag: { type: Boolean, default: false },
1418
1553
  rowClassName: { type: Function, default: () => "" },
1419
1554
  colResizable: { type: Boolean, default: false },
1420
1555
  colMinWidth: { default: 10 },
@@ -1431,11 +1566,12 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1431
1566
  seqConfig: { default: () => ({}) },
1432
1567
  expandConfig: { default: () => ({}) },
1433
1568
  dragRowConfig: { default: () => ({}) },
1569
+ treeConfig: { default: () => ({}) },
1434
1570
  cellFixedMode: { default: "sticky" },
1435
1571
  smoothScroll: { type: Boolean, default: DEFAULT_SMOOTH_SCROLL },
1436
1572
  scrollRowByRow: { type: Boolean, default: false }
1437
1573
  },
1438
- emits: ["sort-change", "row-click", "current-change", "cell-selected", "row-dblclick", "header-row-menu", "row-menu", "cell-click", "cell-mouseenter", "cell-mouseleave", "cell-mouseover", "cell-mousedown", "header-cell-click", "scroll", "scroll-x", "col-order-change", "th-drag-start", "th-drop", "row-order-change", "col-resize", "toggle-row-expand", "update:columns"],
1574
+ emits: ["sort-change", "row-click", "current-change", "cell-selected", "row-dblclick", "header-row-menu", "row-menu", "cell-click", "cell-mouseenter", "cell-mouseleave", "cell-mouseover", "cell-mousedown", "header-cell-click", "scroll", "scroll-x", "col-order-change", "th-drag-start", "th-drop", "row-order-change", "col-resize", "toggle-row-expand", "toggle-tree-expand", "update:columns"],
1439
1575
  setup(__props, { expose: __expose, emit: __emit }) {
1440
1576
  const stkTableId = createStkTableId();
1441
1577
  const props = __props;
@@ -1456,7 +1592,10 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1456
1592
  const tableHeaders = shallowRef([]);
1457
1593
  const tableHeadersForCalc = shallowRef([]);
1458
1594
  const tableHeaderLast = computed(() => tableHeadersForCalc.value.slice(-1)[0] || []);
1459
- const dataSourceCopy = shallowRef(props.dataSource.slice());
1595
+ const isTreeData = computed(() => {
1596
+ return props.columns.some((col) => col.type === "tree-node");
1597
+ });
1598
+ const dataSourceCopy = shallowRef([]);
1460
1599
  const rowKeyGenComputed = computed(() => {
1461
1600
  const { rowKey } = props;
1462
1601
  if (typeof rowKey === "function") {
@@ -1467,7 +1606,9 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1467
1606
  });
1468
1607
  const colKeyGen = computed(() => {
1469
1608
  const { colKey } = props;
1470
- if (typeof colKey === "function") {
1609
+ if (colKey === void 0) {
1610
+ return (col) => col.key || col.dataIndex;
1611
+ } else if (typeof colKey === "function") {
1471
1612
  return (col) => colKey(col);
1472
1613
  } else {
1473
1614
  return (col) => col[colKey];
@@ -1481,7 +1622,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1481
1622
  return (col, row) => emptyCellText({ row, col });
1482
1623
  }
1483
1624
  });
1484
- const rowKeyGenStore = /* @__PURE__ */ new WeakMap();
1625
+ const rowKeyGenCache = /* @__PURE__ */ new WeakMap();
1485
1626
  const { onThDragStart, onThDragOver, onThDrop, isHeaderDraggable } = useThDrag({ props, emits, colKeyGen });
1486
1627
  const { onTrDragStart, onTrDrop, onTrDragOver, onTrDragEnd, onTrDragEnter } = useTrDrag({ props, emits, dataSourceCopy });
1487
1628
  const {
@@ -1540,6 +1681,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1540
1681
  tableHeaderLast,
1541
1682
  fixedCols
1542
1683
  });
1684
+ const { toggleExpandRow, setRowExpand } = useRowExpand({ dataSourceCopy, rowKeyGen, emits });
1685
+ const { toggleTreeNode, setTreeExpand, flatTreeData } = useTree({ props, dataSourceCopy, rowKeyGen, emits });
1543
1686
  watch(
1544
1687
  () => props.columns,
1545
1688
  () => {
@@ -1558,6 +1701,12 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1558
1701
  });
1559
1702
  }
1560
1703
  );
1704
+ watch(
1705
+ () => props.rowHeight,
1706
+ () => {
1707
+ initVirtualScrollY();
1708
+ }
1709
+ );
1561
1710
  watch(
1562
1711
  () => props.virtualX,
1563
1712
  () => {
@@ -1571,7 +1720,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1571
1720
  watch(
1572
1721
  () => props.dataSource,
1573
1722
  (val) => {
1574
- if (!val) {
1723
+ if (!Array.isArray(val)) {
1575
1724
  console.warn("invalid dataSource");
1576
1725
  return;
1577
1726
  }
@@ -1579,7 +1728,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1579
1728
  if (dataSourceCopy.value.length !== val.length) {
1580
1729
  needInitVirtualScrollY = true;
1581
1730
  }
1582
- dataSourceCopy.value = val.slice();
1731
+ initDataSource(val);
1583
1732
  if (needInitVirtualScrollY) {
1584
1733
  nextTick(() => initVirtualScrollY());
1585
1734
  }
@@ -1596,11 +1745,19 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1596
1745
  () => updateFixedShadow()
1597
1746
  );
1598
1747
  dealColumns();
1748
+ initDataSource();
1599
1749
  onMounted(() => {
1600
1750
  initVirtualScroll();
1601
1751
  updateFixedShadow();
1602
1752
  dealDefaultSorter();
1603
1753
  });
1754
+ function initDataSource(v = props.dataSource) {
1755
+ let dataSourceTemp = v.slice();
1756
+ if (isTreeData.value) {
1757
+ dataSourceTemp = flatTreeData(dataSourceTemp);
1758
+ }
1759
+ dataSourceCopy.value = dataSourceTemp;
1760
+ }
1604
1761
  function dealDefaultSorter() {
1605
1762
  if (!props.sortConfig.defaultSort) return;
1606
1763
  const { key, dataIndex, order, silent } = { silent: false, ...props.sortConfig.defaultSort };
@@ -1677,13 +1834,13 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1677
1834
  }
1678
1835
  function rowKeyGen(row) {
1679
1836
  if (!row) return row;
1680
- let key = rowKeyGenStore.get(row) || row.__ROW_KEY__;
1837
+ let key = rowKeyGenCache.get(row) || row.__ROW_KEY__;
1681
1838
  if (!key) {
1682
1839
  key = rowKeyGenComputed.value(row);
1683
1840
  if (key === void 0) {
1684
1841
  key = Math.random().toString();
1685
1842
  }
1686
- rowKeyGenStore.set(row, key);
1843
+ rowKeyGenCache.set(row, key);
1687
1844
  }
1688
1845
  return key;
1689
1846
  }
@@ -1804,10 +1961,14 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1804
1961
  function onRowMenu(e, row, rowIndex) {
1805
1962
  emits("row-menu", e, row, { rowIndex });
1806
1963
  }
1807
- function onCellClick(e, row, col, rowIndex) {
1964
+ function triangleClick(e, row, col) {
1808
1965
  if (col.type === "expand") {
1809
1966
  toggleExpandRow(row, col);
1967
+ } else if (col.type === "tree-node") {
1968
+ toggleTreeNode(row, col);
1810
1969
  }
1970
+ }
1971
+ function onCellClick(e, row, col, rowIndex) {
1811
1972
  if (props.cellActive) {
1812
1973
  const cellKey = cellKeyGen(row, col);
1813
1974
  const result = { row, col, select: false, rowIndex };
@@ -1966,51 +2127,6 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1966
2127
  if (!sortOrder) return [];
1967
2128
  return [{ key: sortCol.value, order: sortOrder }];
1968
2129
  }
1969
- function toggleExpandRow(row, col) {
1970
- const isExpand = (row == null ? void 0 : row.__EXPANDED__) === col ? !(row == null ? void 0 : row.__EXPANDED__) : true;
1971
- setRowExpand(row, isExpand, { col });
1972
- }
1973
- function setRowExpand(rowKeyOrRow, expand, data) {
1974
- let rowKey;
1975
- if (typeof rowKeyOrRow === "string") {
1976
- rowKey = rowKeyOrRow;
1977
- } else {
1978
- rowKey = rowKeyGen(rowKeyOrRow);
1979
- }
1980
- const tempData = dataSourceCopy.value.slice();
1981
- const index = tempData.findIndex((it) => rowKeyGen(it) === rowKey);
1982
- if (index === -1) {
1983
- console.warn("expandRow failed.rowKey:", rowKey);
1984
- return;
1985
- }
1986
- for (let i = index + 1; i < tempData.length; i++) {
1987
- const item = tempData[i];
1988
- const rowKey2 = item.__ROW_KEY__;
1989
- if (rowKey2 == null ? void 0 : rowKey2.startsWith(EXPANDED_ROW_KEY_PREFIX)) {
1990
- tempData.splice(i, 1);
1991
- i--;
1992
- } else {
1993
- break;
1994
- }
1995
- }
1996
- const row = tempData[index];
1997
- const col = (data == null ? void 0 : data.col) || null;
1998
- if (expand) {
1999
- const newExpandRow = {
2000
- __ROW_KEY__: EXPANDED_ROW_KEY_PREFIX + rowKey,
2001
- __EXPANDED_ROW__: row,
2002
- __EXPANDED_COL__: col
2003
- };
2004
- tempData.splice(index + 1, 0, newExpandRow);
2005
- }
2006
- if (row) {
2007
- row.__EXPANDED__ = expand ? col : null;
2008
- }
2009
- dataSourceCopy.value = tempData;
2010
- if (!(data == null ? void 0 : data.silent)) {
2011
- emits("toggle-row-expand", { expanded: Boolean(expand), row, col });
2012
- }
2013
- }
2014
2130
  __expose({
2015
2131
  /**
2016
2132
  * 重新计算虚拟列表宽高
@@ -2122,7 +2238,14 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
2122
2238
  * en: Clear all row heights
2123
2239
  * @see {@link clearAllAutoHeight}
2124
2240
  */
2125
- clearAllAutoHeight
2241
+ clearAllAutoHeight,
2242
+ /**
2243
+ * 设置树节点展开状态
2244
+ *
2245
+ * en: Set tree node expand state
2246
+ * @see {@link setTreeExpand}
2247
+ */
2248
+ setTreeExpand
2126
2249
  });
2127
2250
  return (_ctx, _cache) => {
2128
2251
  return openBlock(), createElementBlock("div", {
@@ -2186,7 +2309,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
2186
2309
  (openBlock(true), createElementBlock(Fragment, null, renderList(tableHeaders.value, (row, rowIndex) => {
2187
2310
  return openBlock(), createElementBlock("tr", {
2188
2311
  key: rowIndex,
2189
- onContextmenu: _cache[3] || (_cache[3] = (e) => onHeaderMenu(e))
2312
+ onContextmenu: _cache[3] || (_cache[3] = ($event) => onHeaderMenu($event))
2190
2313
  }, [
2191
2314
  unref(virtualX_on) ? (openBlock(), createElementBlock("th", {
2192
2315
  key: 0,
@@ -2222,7 +2345,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
2222
2345
  unref(colResizeOn)(col) && colIndex > 0 ? (openBlock(), createElementBlock("div", {
2223
2346
  key: 0,
2224
2347
  class: "table-header-resizer left",
2225
- onMousedown: (e) => unref(onThResizeMouseDown)(e, col, true)
2348
+ onMousedown: ($event) => unref(onThResizeMouseDown)($event, col, true)
2226
2349
  }, null, 40, _hoisted_2)) : createCommentVNode("", true),
2227
2350
  createElementVNode("div", {
2228
2351
  class: "table-header-cell-wrapper",
@@ -2247,7 +2370,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
2247
2370
  unref(colResizeOn)(col) ? (openBlock(), createElementBlock("div", {
2248
2371
  key: 1,
2249
2372
  class: "table-header-resizer right",
2250
- onMousedown: (e) => unref(onThResizeMouseDown)(e, col)
2373
+ onMousedown: ($event) => unref(onThResizeMouseDown)($event, col)
2251
2374
  }, null, 40, _hoisted_4)) : createCommentVNode("", true)
2252
2375
  ], 46, _hoisted_1);
2253
2376
  }), 128)),
@@ -2300,11 +2423,11 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
2300
2423
  style: normalizeStyle({
2301
2424
  "--row-height": row && row.__EXPANDED_ROW__ && props.virtual && ((_a = props.expandConfig) == null ? void 0 : _a.height) && ((_b = props.expandConfig) == null ? void 0 : _b.height) + "px"
2302
2425
  }),
2303
- onClick: (e) => onRowClick(e, row, getRowIndex(rowIndex)),
2304
- onDblclick: (e) => onRowDblclick(e, row, getRowIndex(rowIndex)),
2305
- onContextmenu: (e) => onRowMenu(e, row, getRowIndex(rowIndex)),
2306
- onMouseover: (e) => onTrMouseOver(e, row),
2307
- onDrop: (e) => unref(onTrDrop)(e, getRowIndex(rowIndex))
2426
+ onClick: ($event) => onRowClick($event, row, getRowIndex(rowIndex)),
2427
+ onDblclick: ($event) => onRowDblclick($event, row, getRowIndex(rowIndex)),
2428
+ onContextmenu: ($event) => onRowMenu($event, row, getRowIndex(rowIndex)),
2429
+ onMouseover: ($event) => onTrMouseOver($event, row),
2430
+ onDrop: ($event) => unref(onTrDrop)($event, getRowIndex(rowIndex))
2308
2431
  }, [
2309
2432
  unref(virtualX_on) ? (openBlock(), createElementBlock("td", _hoisted_7)) : createCommentVNode("", true),
2310
2433
  row && row.__EXPANDED_ROW__ ? (openBlock(), createElementBlock("td", {
@@ -2333,42 +2456,72 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
2333
2456
  {
2334
2457
  "seq-column": col.type === "seq",
2335
2458
  active: currentSelectedCellKey.value === cellKeyGen(row, col),
2336
- "expand-cell": col.type === "expand",
2337
2459
  expanded: col.type === "expand" && (row.__EXPANDED__ ? colKeyGen.value(row.__EXPANDED__) === colKeyGen.value(col) : false),
2460
+ "tree-expanded": col.type === "tree-node" && row.__T_EXPANDED__,
2338
2461
  "drag-row-cell": col.type === "dragRow"
2339
2462
  }
2340
2463
  ]),
2341
- onClick: (e) => onCellClick(e, row, col, getRowIndex(rowIndex)),
2342
- onMousedown: (e) => onCellMouseDown(e, row, col, getRowIndex(rowIndex)),
2343
- onMouseenter: (e) => onCellMouseEnter(e, row, col),
2344
- onMouseleave: (e) => onCellMouseLeave(e, row, col),
2345
- onMouseover: (e) => onCellMouseOver(e, row, col)
2464
+ onClick: ($event) => onCellClick($event, row, col, getRowIndex(rowIndex)),
2465
+ onMousedown: ($event) => onCellMouseDown($event, row, col, getRowIndex(rowIndex)),
2466
+ onMouseenter: ($event) => onCellMouseEnter($event, row, col),
2467
+ onMouseleave: ($event) => onCellMouseLeave($event, row, col),
2468
+ onMouseover: ($event) => onCellMouseOver($event, row, col)
2346
2469
  }, [
2347
- col.customCell ? (openBlock(), createBlock(resolveDynamicComponent(col.customCell), {
2470
+ col.type === "expand" || col.type === "tree-node" ? (openBlock(), createElementBlock("div", {
2348
2471
  key: 0,
2349
2472
  class: "table-cell-wrapper",
2350
- col,
2351
- row,
2352
- rowIndex: getRowIndex(rowIndex),
2353
- colIndex,
2354
- cellValue: row && row[col.dataIndex],
2355
- expanded: row && row.__EXPANDED__ || null
2356
- }, null, 8, ["col", "row", "rowIndex", "colIndex", "cellValue", "expanded"])) : (openBlock(), createElementBlock("div", {
2357
- key: 1,
2358
- class: normalizeClass(["table-cell-wrapper", { "expanded-cell-wrapper": col.type === "expand" }]),
2359
- title: col.type !== "seq" ? row == null ? void 0 : row[col.dataIndex] : ""
2473
+ title: row == null ? void 0 : row[col.dataIndex],
2474
+ style: normalizeStyle({ paddingLeft: row.__T_LV__ && row.__T_LV__ * 16 + "px" })
2360
2475
  }, [
2361
- col.type === "seq" ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
2362
- createTextVNode(toDisplayString((props.seqConfig.startIndex || 0) + getRowIndex(rowIndex) + 1), 1)
2363
- ], 64)) : col.type === "expand" ? (openBlock(), createElementBlock("span", _hoisted_12, toDisplayString((row == null ? void 0 : row[col.dataIndex]) ?? ""), 1)) : col.type === "dragRow" ? (openBlock(), createElementBlock(Fragment, { key: 2 }, [
2364
- createVNode(DragHandle, {
2365
- onDragstart: (e) => unref(onTrDragStart)(e, getRowIndex(rowIndex))
2366
- }, null, 8, ["onDragstart"]),
2367
- createElementVNode("span", null, toDisplayString((row == null ? void 0 : row[col.dataIndex]) ?? ""), 1)
2368
- ], 64)) : (openBlock(), createElementBlock(Fragment, { key: 3 }, [
2369
- createTextVNode(toDisplayString((row == null ? void 0 : row[col.dataIndex]) ?? getEmptyCellText.value(col, row)), 1)
2476
+ col.customCell ? (openBlock(), createBlock(resolveDynamicComponent(col.customCell), {
2477
+ key: 0,
2478
+ col,
2479
+ row,
2480
+ rowIndex: getRowIndex(rowIndex),
2481
+ colIndex,
2482
+ cellValue: row && row[col.dataIndex],
2483
+ expanded: row && row.__EXPANDED__ || null,
2484
+ "tree-expanded": row && row.__T_EXPANDED__ || null
2485
+ }, {
2486
+ foldIcon: withCtx(() => [
2487
+ createVNode(TriangleIcon)
2488
+ ]),
2489
+ _: 2
2490
+ }, 1032, ["col", "row", "rowIndex", "colIndex", "cellValue", "expanded", "tree-expanded"])) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
2491
+ col.type === "expand" || col.type === "tree-node" && row.children !== void 0 ? (openBlock(), createBlock(TriangleIcon, {
2492
+ key: 0,
2493
+ onClick: ($event) => triangleClick($event, row, col)
2494
+ }, null, 8, ["onClick"])) : createCommentVNode("", true),
2495
+ createElementVNode("span", {
2496
+ style: normalizeStyle(col.type === "tree-node" && !row.children ? "padding-left: 16px;" : "")
2497
+ }, toDisplayString((row == null ? void 0 : row[col.dataIndex]) ?? ""), 5)
2370
2498
  ], 64))
2371
- ], 10, _hoisted_11))
2499
+ ], 12, _hoisted_11)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
2500
+ col.customCell ? (openBlock(), createBlock(resolveDynamicComponent(col.customCell), {
2501
+ key: 0,
2502
+ class: "table-cell-wrapper",
2503
+ col,
2504
+ row,
2505
+ rowIndex: getRowIndex(rowIndex),
2506
+ colIndex,
2507
+ cellValue: row && row[col.dataIndex]
2508
+ }, null, 8, ["col", "row", "rowIndex", "colIndex", "cellValue"])) : (openBlock(), createElementBlock("div", {
2509
+ key: 1,
2510
+ class: "table-cell-wrapper",
2511
+ title: col.type !== "seq" ? row == null ? void 0 : row[col.dataIndex] : ""
2512
+ }, [
2513
+ col.type === "seq" ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
2514
+ createTextVNode(toDisplayString((props.seqConfig.startIndex || 0) + getRowIndex(rowIndex) + 1), 1)
2515
+ ], 64)) : col.type === "dragRow" ? (openBlock(), createElementBlock(Fragment, { key: 1 }, [
2516
+ createVNode(DragHandle, {
2517
+ onDragstart: ($event) => unref(onTrDragStart)($event, getRowIndex(rowIndex))
2518
+ }, null, 8, ["onDragstart"]),
2519
+ createElementVNode("span", null, toDisplayString((row == null ? void 0 : row[col.dataIndex]) ?? ""), 1)
2520
+ ], 64)) : (openBlock(), createElementBlock(Fragment, { key: 2 }, [
2521
+ createTextVNode(toDisplayString((row == null ? void 0 : row[col.dataIndex]) ?? getEmptyCellText.value(col, row)), 1)
2522
+ ], 64))
2523
+ ], 8, _hoisted_12))
2524
+ ], 64))
2372
2525
  ], 46, _hoisted_10);
2373
2526
  }), 128))
2374
2527
  ], 46, _hoisted_6);