stk-table-vue 0.6.10 → 0.6.13

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 CHANGED
@@ -1,19 +1,31 @@
1
- # StkTable (Sticky Table)
2
- ![NPM License](https://img.shields.io/npm/l/stk-table-vue)
3
- ![NPM Version](https://img.shields.io/npm/v/stk-table-vue)
4
- ![NPM Type Definitions](https://img.shields.io/npm/types/stk-table-vue)
5
- ![NPM Downloads](https://img.shields.io/npm/dw/stk-table-vue)
6
-
7
- Vue3 简易虚拟滚动表格。用于实时数据展示,新数据行高亮渐暗动效。
8
-
9
- Vue2.7支持引入源码(**ts**)使用。
10
-
11
- [Stk Table Vue Doc](https://ja-plus.github.io/stk-table-vue/)
12
-
13
- repo(求 star🌟):
1
+ <p align="center">
2
+ <a href="https://ja-plus.github.io/stk-table-vue/">
3
+ <img src="./docs-src/public/assets/logo.svg" width="152">
4
+ </a>
5
+ <h3 align='center'>Stk Table Vue</h3>
6
+ <p align="center">
7
+ <a href="https://www.npmjs.com/package/stk-table-vue"><img src="https://img.shields.io/npm/v/stk-table-vue"></a>
8
+ <a href="https://www.npmjs.com/package/stk-table-vue"><img src="https://img.shields.io/npm/dw/stk-table-vue"></a>
9
+ <a href="https://github.com/ja-plus/stk-table-vue/stargazers"><img src="https://img.shields.io/github/stars/ja-plus/stk-table-vue.svg"></a>
10
+ <a href="https://raw.githubusercontent.com/ja-plus/stk-table-vue/master/LICENSE"><img src="https://img.shields.io/npm/l/stk-table-vue"></a>
11
+ <a href="https://github.com/ja-plus/stk-table-vue"><img src="https://img.shields.io/npm/types/stk-table-vue"></a>
12
+ </p>
13
+ </p>
14
+
15
+ > StK Table (Sticky Table) 是一个基于Vue 的高性能虚拟列表组件。
16
+ > 用于实时数据展示,数据高亮动效。
17
+
18
+ > Vue2.7支持引入源码(**ts**)使用。
19
+
20
+ ## Doc
21
+ 文档: [Stk Table Vue 高性能虚拟表格](https://ja-plus.github.io/stk-table-vue/)
22
+
23
+ ## Repo:
14
24
  - [Github](https://github.com/ja-plus/stk-table-vue)
15
25
  - [Gitee](https://gitee.com/japlus/stk-table-vue) 🇨🇳
16
26
 
27
+ ## Demo
28
+
17
29
  [<span style="font-size: 16px;font-weight: bold;">Online Demo</span>](https://stackblitz.com/edit/vitejs-vite-ad91hh?file=src%2FDemo%2Findex.vue)
18
30
 
19
31
  ## Feature TODO:
@@ -369,7 +369,9 @@ declare const __VLS_component: import('vue').DefineComponent<import('vue').Extra
369
369
  clearAllAutoHeight: () => void;
370
370
  }, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
371
371
  "sort-change": (col: StkTableColumn<any> | null, order: Order, data: any[], sortConfig: SortConfig<any>) => void;
372
- "row-click": (ev: MouseEvent, row: any) => void;
372
+ "row-click": (ev: MouseEvent, row: any, data: {
373
+ rowIndex: number;
374
+ }) => void;
373
375
  "current-change": (ev: MouseEvent | null, row: any, data: {
374
376
  select: boolean;
375
377
  }) => void;
@@ -378,14 +380,22 @@ declare const __VLS_component: import('vue').DefineComponent<import('vue').Extra
378
380
  row: DT | undefined;
379
381
  col: StkTableColumn<DT> | undefined;
380
382
  }) => void;
381
- "row-dblclick": (ev: MouseEvent, row: any) => void;
383
+ "row-dblclick": (ev: MouseEvent, row: any, data: {
384
+ rowIndex: number;
385
+ }) => void;
382
386
  "header-row-menu": (ev: MouseEvent) => void;
383
- "row-menu": (ev: MouseEvent, row: any) => void;
384
- "cell-click": (ev: MouseEvent, row: any, col: StkTableColumn<any>) => void;
387
+ "row-menu": (ev: MouseEvent, row: any, data: {
388
+ rowIndex: number;
389
+ }) => void;
390
+ "cell-click": (ev: MouseEvent, row: any, col: StkTableColumn<any>, data: {
391
+ rowIndex: number;
392
+ }) => void;
385
393
  "cell-mouseenter": (ev: MouseEvent, row: any, col: StkTableColumn<any>) => void;
386
394
  "cell-mouseleave": (ev: MouseEvent, row: any, col: StkTableColumn<any>) => void;
387
395
  "cell-mouseover": (ev: MouseEvent, row: any, col: StkTableColumn<any>) => void;
388
- "cell-mousedown": (ev: MouseEvent, row: any, col: StkTableColumn<any>) => void;
396
+ "cell-mousedown": (ev: MouseEvent, row: any, col: StkTableColumn<any>, data: {
397
+ rowIndex: number;
398
+ }) => void;
389
399
  "header-cell-click": (ev: MouseEvent, col: StkTableColumn<any>) => void;
390
400
  scroll: (ev: Event, data: {
391
401
  startIndex: number;
@@ -596,7 +606,9 @@ declare const __VLS_component: import('vue').DefineComponent<import('vue').Extra
596
606
  "onCol-order-change"?: ((dragStartKey: string, targetColKey: string) => any) | undefined;
597
607
  "onRow-order-change"?: ((dragStartKey: string, targetRowKey: string) => any) | undefined;
598
608
  "onSort-change"?: ((col: StkTableColumn<any> | null, order: Order, data: any[], sortConfig: SortConfig<any>) => any) | undefined;
599
- "onRow-click"?: ((ev: MouseEvent, row: any) => any) | undefined;
609
+ "onRow-click"?: ((ev: MouseEvent, row: any, data: {
610
+ rowIndex: number;
611
+ }) => any) | undefined;
600
612
  "onCurrent-change"?: ((ev: MouseEvent | null, row: any, data: {
601
613
  select: boolean;
602
614
  }) => any) | undefined;
@@ -605,14 +617,22 @@ declare const __VLS_component: import('vue').DefineComponent<import('vue').Extra
605
617
  row: DT | undefined;
606
618
  col: StkTableColumn<DT> | undefined;
607
619
  }) => any) | undefined;
608
- "onRow-dblclick"?: ((ev: MouseEvent, row: any) => any) | undefined;
620
+ "onRow-dblclick"?: ((ev: MouseEvent, row: any, data: {
621
+ rowIndex: number;
622
+ }) => any) | undefined;
609
623
  "onHeader-row-menu"?: ((ev: MouseEvent) => any) | undefined;
610
- "onRow-menu"?: ((ev: MouseEvent, row: any) => any) | undefined;
611
- "onCell-click"?: ((ev: MouseEvent, row: any, col: StkTableColumn<any>) => any) | undefined;
624
+ "onRow-menu"?: ((ev: MouseEvent, row: any, data: {
625
+ rowIndex: number;
626
+ }) => any) | undefined;
627
+ "onCell-click"?: ((ev: MouseEvent, row: any, col: StkTableColumn<any>, data: {
628
+ rowIndex: number;
629
+ }) => any) | undefined;
612
630
  "onCell-mouseenter"?: ((ev: MouseEvent, row: any, col: StkTableColumn<any>) => any) | undefined;
613
631
  "onCell-mouseleave"?: ((ev: MouseEvent, row: any, col: StkTableColumn<any>) => any) | undefined;
614
632
  "onCell-mouseover"?: ((ev: MouseEvent, row: any, col: StkTableColumn<any>) => any) | undefined;
615
- "onCell-mousedown"?: ((ev: MouseEvent, row: any, col: StkTableColumn<any>) => any) | undefined;
633
+ "onCell-mousedown"?: ((ev: MouseEvent, row: any, col: StkTableColumn<any>, data: {
634
+ rowIndex: number;
635
+ }) => any) | undefined;
616
636
  "onHeader-cell-click"?: ((ev: MouseEvent, col: StkTableColumn<any>) => any) | undefined;
617
637
  "onScroll-x"?: ((ev: Event) => any) | undefined;
618
638
  "onToggle-row-expand"?: ((data: {
@@ -420,7 +420,7 @@ function useColResize({
420
420
  function findLastChildCol(column) {
421
421
  var _a;
422
422
  if ((_a = column == null ? void 0 : column.children) == null ? void 0 : _a.length) {
423
- const lastChild = column.children.at(-1);
423
+ const lastChild = column.children.slice(-1)[0];
424
424
  return findLastChildCol(lastChild);
425
425
  }
426
426
  return column;
@@ -815,6 +815,8 @@ var ScrollCodes = /* @__PURE__ */ ((ScrollCodes2) => {
815
815
  ScrollCodes2["ArrowLeft"] = "ArrowLeft";
816
816
  ScrollCodes2["PageUp"] = "PageUp";
817
817
  ScrollCodes2["PageDown"] = "PageDown";
818
+ ScrollCodes2["Home"] = "Home";
819
+ ScrollCodes2["End"] = "End";
818
820
  return ScrollCodes2;
819
821
  })(ScrollCodes || {});
820
822
  const ScrollCodesValues = Object.values(ScrollCodes);
@@ -848,7 +850,7 @@ function useKeyboardArrowScroll(targetElement, { props, scrollTo, virtualScroll,
848
850
  if (!ScrollCodesValues.includes(e.code)) return;
849
851
  if (!isMouseOver) return;
850
852
  e.preventDefault();
851
- const { scrollTop, rowHeight, containerHeight } = virtualScroll.value;
853
+ const { scrollTop, rowHeight, containerHeight, scrollHeight } = virtualScroll.value;
852
854
  const { scrollLeft } = virtualScrollX.value;
853
855
  const { headless, headerRowHeight } = props;
854
856
  const headerHeight = headless ? 0 : tableHeaders.value.length * (headerRowHeight || rowHeight);
@@ -856,15 +858,19 @@ function useKeyboardArrowScroll(targetElement, { props, scrollTo, virtualScroll,
856
858
  if (e.code === "ArrowUp") {
857
859
  scrollTo(scrollTop - rowHeight, null);
858
860
  } else if (e.code === "ArrowRight") {
859
- scrollTo(null, scrollLeft + rowHeight);
861
+ scrollTo(null, scrollLeft + 50);
860
862
  } else if (e.code === "ArrowDown") {
861
863
  scrollTo(scrollTop + rowHeight, null);
862
864
  } else if (e.code === "ArrowLeft") {
863
- scrollTo(null, scrollLeft - rowHeight);
865
+ scrollTo(null, scrollLeft - 50);
864
866
  } else if (e.code === "PageUp") {
865
867
  scrollTo(scrollTop - rowHeight * bodyPageSize + headerHeight, null);
866
868
  } else if (e.code === "PageDown") {
867
869
  scrollTo(scrollTop + rowHeight * bodyPageSize - headerHeight, null);
870
+ } else if (e.code === "Home") {
871
+ scrollTo(0, null);
872
+ } else if (e.code === "End") {
873
+ scrollTo(scrollHeight, null);
868
874
  }
869
875
  }
870
876
  function handleMouseEnter() {
@@ -1430,7 +1436,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1430
1436
  const sortSwitchOrder = [null, "desc", "asc"];
1431
1437
  const tableHeaders = shallowRef([]);
1432
1438
  const tableHeadersForCalc = shallowRef([]);
1433
- const tableHeaderLast = computed(() => tableHeadersForCalc.value.at(-1) || []);
1439
+ const tableHeaderLast = computed(() => tableHeadersForCalc.value.slice(-1)[0] || []);
1434
1440
  const dataSourceCopy = shallowRef(props.dataSource.slice());
1435
1441
  const rowKeyGenComputed = computed(() => {
1436
1442
  const { rowKey } = props;
@@ -1671,7 +1677,6 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1671
1677
  const { virtualX, colResizable } = props;
1672
1678
  tableHeaders.value.forEach((cols, depth) => {
1673
1679
  cols.forEach((col) => {
1674
- const colKey = colKeyGen.value(col);
1675
1680
  const width = virtualX ? getCalculatedColWidth(col) + "px" : transformWidthToStr(col.width);
1676
1681
  const style = {
1677
1682
  width
@@ -1683,8 +1688,9 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1683
1688
  style.minWidth = transformWidthToStr(col.minWidth) ?? width;
1684
1689
  style.maxWidth = transformWidthToStr(col.maxWidth) ?? width;
1685
1690
  }
1691
+ const colKey = colKeyGen.value(col);
1686
1692
  thMap.set(colKey, Object.assign({ textAlign: col.headerAlign }, style, getFixedStyle(TagType.TH, col, depth)));
1687
- tdMap.set(colKey, Object.assign({ textAlign: col.align }, style, getFixedStyle(TagType.TD, col, depth), { textAlign: col.align }));
1693
+ tdMap.set(colKey, Object.assign({ textAlign: col.align }, style, getFixedStyle(TagType.TD, col, depth)));
1688
1694
  });
1689
1695
  });
1690
1696
  return {
@@ -1692,6 +1698,9 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1692
1698
  [TagType.TD]: tdMap
1693
1699
  };
1694
1700
  });
1701
+ function getRowIndex(rowIndex) {
1702
+ return rowIndex + (virtual_on ? virtualScroll.value.startIndex : 0);
1703
+ }
1695
1704
  function getHeaderTitle(col) {
1696
1705
  const colKey = colKeyGen.value(col);
1697
1706
  if (props.hideHeaderTitle === true || Array.isArray(props.hideHeaderTitle) && props.hideHeaderTitle.includes(colKey)) {
@@ -1713,6 +1722,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1713
1722
  sortCol.value = colKey;
1714
1723
  sortOrderIndex.value = 0;
1715
1724
  }
1725
+ const prevOrder = sortSwitchOrder[sortOrderIndex.value];
1716
1726
  if (click) sortOrderIndex.value++;
1717
1727
  sortOrderIndex.value = sortOrderIndex.value % 3;
1718
1728
  let order = sortSwitchOrder[sortOrderIndex.value];
@@ -1720,17 +1730,21 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1720
1730
  const defaultSort = sortConfig.defaultSort;
1721
1731
  const colKeyGenValue = colKeyGen.value;
1722
1732
  if (!order && defaultSort) {
1723
- const colKey2 = defaultSort.key || defaultSort.dataIndex;
1724
- if (!colKey2) {
1733
+ const defaultColKey = defaultSort.key || defaultSort.dataIndex;
1734
+ if (!defaultColKey) {
1725
1735
  console.error("sortConfig.defaultSort key or dataIndex is required");
1726
1736
  return;
1727
1737
  }
1728
- order = defaultSort.order || "desc";
1738
+ if (colKey === defaultColKey && prevOrder === defaultSort.order) {
1739
+ order = sortSwitchOrder.find((o) => o !== defaultSort.order && o);
1740
+ } else {
1741
+ order = defaultSort.order;
1742
+ }
1729
1743
  sortOrderIndex.value = sortSwitchOrder.indexOf(order);
1730
- sortCol.value = colKey2;
1744
+ sortCol.value = defaultColKey;
1731
1745
  col = null;
1732
1746
  for (const row of tableHeaders.value) {
1733
- const c = row.find((item) => colKeyGenValue(item) === colKey2);
1747
+ const c = row.find((item) => colKeyGenValue(item) === defaultColKey);
1734
1748
  if (c) {
1735
1749
  col = c;
1736
1750
  break;
@@ -1747,8 +1761,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1747
1761
  emits("sort-change", col, order, toRaw(dataSourceCopy.value), sortConfig);
1748
1762
  }
1749
1763
  }
1750
- function onRowClick(e, row) {
1751
- emits("row-click", e, row);
1764
+ function onRowClick(e, row, rowIndex) {
1765
+ emits("row-click", e, row, { rowIndex });
1752
1766
  const isCurrentRow = props.rowKey ? currentRowKey.value === rowKeyGen(row) : currentRow.value === row;
1753
1767
  if (isCurrentRow) {
1754
1768
  if (!props.rowCurrentRevokable) {
@@ -1762,22 +1776,22 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1762
1776
  }
1763
1777
  emits("current-change", e, row, { select: !isCurrentRow });
1764
1778
  }
1765
- function onRowDblclick(e, row) {
1766
- emits("row-dblclick", e, row);
1779
+ function onRowDblclick(e, row, rowIndex) {
1780
+ emits("row-dblclick", e, row, { rowIndex });
1767
1781
  }
1768
1782
  function onHeaderMenu(e) {
1769
1783
  emits("header-row-menu", e);
1770
1784
  }
1771
- function onRowMenu(e, row) {
1772
- emits("row-menu", e, row);
1785
+ function onRowMenu(e, row, rowIndex) {
1786
+ emits("row-menu", e, row, { rowIndex });
1773
1787
  }
1774
- function onCellClick(e, row, col) {
1788
+ function onCellClick(e, row, col, rowIndex) {
1775
1789
  if (col.type === "expand") {
1776
1790
  toggleExpandRow(row, col);
1777
1791
  }
1778
1792
  if (props.cellActive) {
1779
1793
  const cellKey = cellKeyGen(row, col);
1780
- const result = { row, col, select: false };
1794
+ const result = { row, col, select: false, rowIndex };
1781
1795
  if (props.selectedCellRevokable && currentSelectedCellKey.value === cellKey) {
1782
1796
  currentSelectedCellKey.value = void 0;
1783
1797
  } else {
@@ -1786,7 +1800,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1786
1800
  }
1787
1801
  emits("cell-selected", e, result);
1788
1802
  }
1789
- emits("cell-click", e, row, col);
1803
+ emits("cell-click", e, row, col, { rowIndex });
1790
1804
  }
1791
1805
  function onHeaderCellClick(e, col) {
1792
1806
  emits("header-cell-click", e, col);
@@ -1800,8 +1814,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1800
1814
  function onCellMouseOver(e, row, col) {
1801
1815
  emits("cell-mouseover", e, row, col);
1802
1816
  }
1803
- function onCellMouseDown(e, row, col) {
1804
- emits("cell-mousedown", e, row, col);
1817
+ function onCellMouseDown(e, row, col, rowIndex) {
1818
+ emits("cell-mousedown", e, row, col, { rowIndex });
1805
1819
  }
1806
1820
  function onTableWheel(e) {
1807
1821
  if (props.smoothScroll) {
@@ -2099,6 +2113,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
2099
2113
  virtual: _ctx.virtual,
2100
2114
  "virtual-x": _ctx.virtualX,
2101
2115
  "vt-on": unref(virtual_on),
2116
+ light: _ctx.theme === "light",
2102
2117
  dark: _ctx.theme === "dark",
2103
2118
  headless: _ctx.headless,
2104
2119
  "is-col-resizing": unref(isColResizing),
@@ -2250,27 +2265,27 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
2250
2265
  (openBlock(true), createElementBlock(Fragment, null, renderList(unref(virtual_dataSourcePart), (row, rowIndex) => {
2251
2266
  var _a, _b;
2252
2267
  return openBlock(), createElementBlock("tr", {
2253
- id: unref(stkTableId) + "-" + (_ctx.rowKey ? rowKeyGen(row) : (unref(virtual_on) ? unref(virtualScroll).startIndex : 0) + rowIndex),
2268
+ id: unref(stkTableId) + "-" + (_ctx.rowKey ? rowKeyGen(row) : getRowIndex(rowIndex)),
2254
2269
  ref_for: true,
2255
2270
  ref_key: "trRef",
2256
2271
  ref: trRef,
2257
- key: _ctx.rowKey ? rowKeyGen(row) : (unref(virtual_on) ? unref(virtualScroll).startIndex : 0) + rowIndex,
2258
- "data-row-key": _ctx.rowKey ? rowKeyGen(row) : (unref(virtual_on) ? unref(virtualScroll).startIndex : 0) + rowIndex,
2272
+ key: _ctx.rowKey ? rowKeyGen(row) : getRowIndex(rowIndex),
2273
+ "data-row-key": _ctx.rowKey ? rowKeyGen(row) : getRowIndex(rowIndex),
2259
2274
  class: normalizeClass({
2260
2275
  active: _ctx.rowKey ? rowKeyGen(row) === currentRowKey.value : row === currentRow.value,
2261
2276
  hover: props.showTrHoverClass && (_ctx.rowKey ? rowKeyGen(row) === currentHoverRowKey.value : row === currentHoverRowKey.value),
2262
- [_ctx.rowClassName(row, (unref(virtual_on) ? unref(virtualScroll).startIndex : 0) + rowIndex)]: true,
2277
+ [_ctx.rowClassName(row, getRowIndex(rowIndex))]: true,
2263
2278
  expanded: row == null ? void 0 : row.__EXPANDED__,
2264
2279
  "expanded-row": row && row.__EXPANDED_ROW__
2265
2280
  }),
2266
2281
  style: normalizeStyle({
2267
2282
  "--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"
2268
2283
  }),
2269
- onClick: (e) => onRowClick(e, row),
2270
- onDblclick: (e) => onRowDblclick(e, row),
2271
- onContextmenu: (e) => onRowMenu(e, row),
2284
+ onClick: (e) => onRowClick(e, row, getRowIndex(rowIndex)),
2285
+ onDblclick: (e) => onRowDblclick(e, row, getRowIndex(rowIndex)),
2286
+ onContextmenu: (e) => onRowMenu(e, row, getRowIndex(rowIndex)),
2272
2287
  onMouseover: (e) => onTrMouseOver(e, row),
2273
- onDrop: (e) => unref(onTrDrop)(e, (unref(virtual_on) ? unref(virtualScroll).startIndex : 0) + rowIndex)
2288
+ onDrop: (e) => unref(onTrDrop)(e, getRowIndex(rowIndex))
2274
2289
  }, [
2275
2290
  unref(virtualX_on) ? (openBlock(), createElementBlock("td", _hoisted_7)) : createCommentVNode("", true),
2276
2291
  row && row.__EXPANDED_ROW__ ? (openBlock(), createElementBlock("td", {
@@ -2300,12 +2315,12 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
2300
2315
  "seq-column": col.type === "seq",
2301
2316
  active: currentSelectedCellKey.value === cellKeyGen(row, col),
2302
2317
  "expand-cell": col.type === "expand",
2303
- expanded: col.type === "expand" && colKeyGen.value(row == null ? void 0 : row.__EXPANDED__) === colKeyGen.value(col),
2318
+ expanded: col.type === "expand" && (row.__EXPANDED__ ? colKeyGen.value(row.__EXPANDED__) === colKeyGen.value(col) : false),
2304
2319
  "drag-row-cell": col.type === "dragRow"
2305
2320
  }
2306
2321
  ]),
2307
- onClick: (e) => onCellClick(e, row, col),
2308
- onMousedown: (e) => onCellMouseDown(e, row, col),
2322
+ onClick: (e) => onCellClick(e, row, col, getRowIndex(rowIndex)),
2323
+ onMousedown: (e) => onCellMouseDown(e, row, col, getRowIndex(rowIndex)),
2309
2324
  onMouseenter: (e) => onCellMouseEnter(e, row, col),
2310
2325
  onMouseleave: (e) => onCellMouseLeave(e, row, col),
2311
2326
  onMouseover: (e) => onCellMouseOver(e, row, col)
@@ -2315,20 +2330,20 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
2315
2330
  class: "table-cell-wrapper",
2316
2331
  col,
2317
2332
  row,
2318
- rowIndex: (unref(virtual_on) ? unref(virtualScroll).startIndex : 0) + rowIndex,
2333
+ rowIndex: getRowIndex(rowIndex),
2319
2334
  colIndex,
2320
- cellValue: row == null ? void 0 : row[col.dataIndex],
2321
- expanded: (row == null ? void 0 : row.__EXPANDED__) || null
2335
+ cellValue: row && row[col.dataIndex],
2336
+ expanded: row && row.__EXPANDED__ || null
2322
2337
  }, null, 8, ["col", "row", "rowIndex", "colIndex", "cellValue", "expanded"])) : (openBlock(), createElementBlock("div", {
2323
2338
  key: 1,
2324
2339
  class: normalizeClass(["table-cell-wrapper", { "expanded-cell-wrapper": col.type === "expand" }]),
2325
2340
  title: col.type !== "seq" ? row == null ? void 0 : row[col.dataIndex] : ""
2326
2341
  }, [
2327
2342
  col.type === "seq" ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
2328
- createTextVNode(toDisplayString((props.seqConfig.startIndex || 0) + (unref(virtual_on) ? unref(virtualScroll).startIndex : 0) + rowIndex + 1), 1)
2343
+ createTextVNode(toDisplayString((props.seqConfig.startIndex || 0) + getRowIndex(rowIndex) + 1), 1)
2329
2344
  ], 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 }, [
2330
2345
  createVNode(DragHandle, {
2331
- onDragstart: (e) => unref(onTrDragStart)(e, (unref(virtual_on) ? unref(virtualScroll).startIndex : 0) + rowIndex)
2346
+ onDragstart: (e) => unref(onTrDragStart)(e, getRowIndex(rowIndex))
2332
2347
  }, null, 8, ["onDragstart"]),
2333
2348
  createElementVNode("span", null, toDisplayString((row == null ? void 0 : row[col.dataIndex]) ?? ""), 1)
2334
2349
  ], 64)) : (openBlock(), createElementBlock(Fragment, { key: 3 }, [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stk-table-vue",
3
- "version": "0.6.10",
3
+ "version": "0.6.13",
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",
@@ -7,6 +7,7 @@
7
7
  virtual,
8
8
  'virtual-x': virtualX,
9
9
  'vt-on': virtual_on,
10
+ light: theme === 'light',
10
11
  dark: theme === 'dark',
11
12
  headless,
12
13
  'is-col-resizing': isColResizing,
@@ -60,7 +61,7 @@
60
61
  class="vt-x-left"
61
62
  :style="`min-width:${virtualScrollX.offsetLeft}px;width:${virtualScrollX.offsetLeft}px`"
62
63
  ></th>
63
- <!-- v for中最后一行才用 切割。TODO:不支持多级表头虚拟横向滚动 -->
64
+ <!-- v for中最后一行才用 切割。-->
64
65
  <th
65
66
  v-for="(col, colIndex) in virtualX_on && rowIndex === tableHeaders.length - 1 ? virtualX_columnPart : row"
66
67
  :key="colKeyGen(col)"
@@ -122,14 +123,14 @@
122
123
  </tr>
123
124
  <tr
124
125
  v-for="(row, rowIndex) in virtual_dataSourcePart"
125
- :id="stkTableId + '-' + (rowKey ? rowKeyGen(row) : (virtual_on ? virtualScroll.startIndex : 0) + rowIndex)"
126
+ :id="stkTableId + '-' + (rowKey ? rowKeyGen(row) : getRowIndex(rowIndex))"
126
127
  ref="trRef"
127
- :key="rowKey ? rowKeyGen(row) : (virtual_on ? virtualScroll.startIndex : 0) + rowIndex"
128
- :data-row-key="rowKey ? rowKeyGen(row) : (virtual_on ? virtualScroll.startIndex : 0) + rowIndex"
128
+ :key="rowKey ? rowKeyGen(row) : getRowIndex(rowIndex)"
129
+ :data-row-key="rowKey ? rowKeyGen(row) : getRowIndex(rowIndex)"
129
130
  :class="{
130
131
  active: rowKey ? rowKeyGen(row) === currentRowKey : row === currentRow,
131
132
  hover: props.showTrHoverClass && (rowKey ? rowKeyGen(row) === currentHoverRowKey : row === currentHoverRowKey),
132
- [rowClassName(row, (virtual_on ? virtualScroll.startIndex : 0) + rowIndex)]: true,
133
+ [rowClassName(row, getRowIndex(rowIndex))]: true,
133
134
  expanded: row?.__EXPANDED__,
134
135
  'expanded-row': row && row.__EXPANDED_ROW__,
135
136
  }"
@@ -137,11 +138,11 @@
137
138
  '--row-height':
138
139
  row && row.__EXPANDED_ROW__ && props.virtual && props.expandConfig?.height && props.expandConfig?.height + 'px',
139
140
  }"
140
- @click="e => onRowClick(e, row)"
141
- @dblclick="e => onRowDblclick(e, row)"
142
- @contextmenu="e => onRowMenu(e, row)"
141
+ @click="e => onRowClick(e, row, getRowIndex(rowIndex))"
142
+ @dblclick="e => onRowDblclick(e, row, getRowIndex(rowIndex))"
143
+ @contextmenu="e => onRowMenu(e, row, getRowIndex(rowIndex))"
143
144
  @mouseover="e => onTrMouseOver(e, row)"
144
- @drop="e => onTrDrop(e, (virtual_on ? virtualScroll.startIndex : 0) + rowIndex)"
145
+ @drop="e => onTrDrop(e, getRowIndex(rowIndex))"
145
146
  >
146
147
  <!--这个td用于配合虚拟滚动的th对应,防止列错位-->
147
148
  <td v-if="virtualX_on" class="vt-x-left"></td>
@@ -166,12 +167,12 @@
166
167
  'seq-column': col.type === 'seq',
167
168
  active: currentSelectedCellKey === cellKeyGen(row, col),
168
169
  'expand-cell': col.type === 'expand',
169
- expanded: col.type === 'expand' && colKeyGen(row?.__EXPANDED__) === colKeyGen(col),
170
+ expanded: col.type === 'expand' && (row.__EXPANDED__ ? colKeyGen(row.__EXPANDED__) === colKeyGen(col) : false),
170
171
  'drag-row-cell': col.type === 'dragRow',
171
172
  },
172
173
  ]"
173
- @click="e => onCellClick(e, row, col)"
174
- @mousedown="e => onCellMouseDown(e, row, col)"
174
+ @click="e => onCellClick(e, row, col, getRowIndex(rowIndex))"
175
+ @mousedown="e => onCellMouseDown(e, row, col, getRowIndex(rowIndex))"
175
176
  @mouseenter="e => onCellMouseEnter(e, row, col)"
176
177
  @mouseleave="e => onCellMouseLeave(e, row, col)"
177
178
  @mouseover="e => onCellMouseOver(e, row, col)"
@@ -182,10 +183,10 @@
182
183
  class="table-cell-wrapper"
183
184
  :col="col"
184
185
  :row="row"
185
- :rowIndex="(virtual_on ? virtualScroll.startIndex : 0) + rowIndex"
186
+ :rowIndex="getRowIndex(rowIndex)"
186
187
  :colIndex="colIndex"
187
- :cellValue="row?.[col.dataIndex]"
188
- :expanded="row?.__EXPANDED__ || null"
188
+ :cellValue="row && row[col.dataIndex]"
189
+ :expanded="(row && row.__EXPANDED__) || null"
189
190
  />
190
191
  <div
191
192
  v-else
@@ -194,13 +195,13 @@
194
195
  :title="col.type !== 'seq' ? row?.[col.dataIndex] : ''"
195
196
  >
196
197
  <template v-if="col.type === 'seq'">
197
- {{ (props.seqConfig.startIndex || 0) + (virtual_on ? virtualScroll.startIndex : 0) + rowIndex + 1 }}
198
+ {{ (props.seqConfig.startIndex || 0) + getRowIndex(rowIndex) + 1 }}
198
199
  </template>
199
200
  <span v-else-if="col.type === 'expand'">
200
201
  {{ row?.[col.dataIndex] ?? '' }}
201
202
  </span>
202
203
  <template v-else-if="col.type === 'dragRow'">
203
- <DragHandle @dragstart="e => onTrDragStart(e, (virtual_on ? virtualScroll.startIndex : 0) + rowIndex)" />
204
+ <DragHandle @dragstart="e => onTrDragStart(e, getRowIndex(rowIndex))" />
204
205
  <span>
205
206
  {{ row?.[col.dataIndex] ?? '' }}
206
207
  </span>
@@ -463,13 +464,13 @@ const emits = defineEmits<{
463
464
  /**
464
465
  * 一行点击事件
465
466
  *
466
- * ```(ev: MouseEvent, row: DT)```
467
+ * ```(ev: MouseEvent, row: DT, data: { rowIndex: number })```
467
468
  */
468
- (e: 'row-click', ev: MouseEvent, row: DT): void;
469
+ (e: 'row-click', ev: MouseEvent, row: DT, data: { rowIndex: number }): void;
469
470
  /**
470
471
  * 选中一行触发。ev返回null表示不是点击事件触发的
471
472
  *
472
- * ```(ev: MouseEvent | null, row: DT | undefined, data: { select: boolean })```
473
+ * ```(ev: MouseEvent | null, row: DT | undefined, data: { select: boolean} })```
473
474
  */
474
475
  (e: 'current-change', ev: MouseEvent | null, row: DT | undefined, data: { select: boolean }): void;
475
476
  /**
@@ -481,9 +482,9 @@ const emits = defineEmits<{
481
482
  /**
482
483
  * 行双击事件
483
484
  *
484
- * ```(ev: MouseEvent, row: DT)```
485
+ * ```(ev: MouseEvent, row: DT, data: { rowIndex: number })```
485
486
  */
486
- (e: 'row-dblclick', ev: MouseEvent, row: DT): void;
487
+ (e: 'row-dblclick', ev: MouseEvent, row: DT, data: { rowIndex: number }): void;
487
488
  /**
488
489
  * 表头右键事件
489
490
  *
@@ -493,15 +494,15 @@ const emits = defineEmits<{
493
494
  /**
494
495
  * 表体行右键点击事件
495
496
  *
496
- * ```(ev: MouseEvent, row: DT)```
497
+ * ```(ev: MouseEvent, row: DT, data: { rowIndex: number })```
497
498
  */
498
- (e: 'row-menu', ev: MouseEvent, row: DT): void;
499
+ (e: 'row-menu', ev: MouseEvent, row: DT, data: { rowIndex: number }): void;
499
500
  /**
500
501
  * 单元格点击事件
501
502
  *
502
- * ```(ev: MouseEvent, row: DT, col: StkTableColumn<DT>)```
503
+ * ```(ev: MouseEvent, row: DT, col: StkTableColumn<DT>, data: { rowIndex: number })```
503
504
  */
504
- (e: 'cell-click', ev: MouseEvent, row: DT, col: StkTableColumn<DT>): void;
505
+ (e: 'cell-click', ev: MouseEvent, row: DT, col: StkTableColumn<DT>, data: { rowIndex: number }): void;
505
506
  /**
506
507
  * 单元格鼠标进入事件
507
508
  *
@@ -523,9 +524,9 @@ const emits = defineEmits<{
523
524
  /**
524
525
  * 单元格鼠标按下事件
525
526
  *
526
- * ```(ev: MouseEvent, row: DT, col: StkTableColumn<DT>)```
527
+ * ```(ev: MouseEvent, row: DT, col: StkTableColumn<DT>, data: { rowIndex: number })```
527
528
  */
528
- (e: 'cell-mousedown', ev: MouseEvent, row: DT, col: StkTableColumn<DT>): void;
529
+ (e: 'cell-mousedown', ev: MouseEvent, row: DT, col: StkTableColumn<DT>, data: { rowIndex: number }): void;
529
530
  /**
530
531
  * 表头单元格点击事件
531
532
  *
@@ -662,7 +663,7 @@ const tableHeaders = shallowRef<StkTableColumn<DT>[][]>([]);
662
663
  const tableHeadersForCalc = shallowRef<PrivateStkTableColumn<DT>[][]>([]);
663
664
 
664
665
  /** 最后一行的tableHeaders.内容是 props.columns 的引用集合 */
665
- const tableHeaderLast = computed(() => tableHeadersForCalc.value.at(-1) || []);
666
+ const tableHeaderLast = computed(() => tableHeadersForCalc.value.slice(-1)[0] || []);
666
667
 
667
668
  const dataSourceCopy = shallowRef<DT[]>(props.dataSource.slice());
668
669
 
@@ -976,7 +977,6 @@ const cellStyleMap = computed(() => {
976
977
  const { virtualX, colResizable } = props;
977
978
  tableHeaders.value.forEach((cols, depth) => {
978
979
  cols.forEach(col => {
979
- const colKey = colKeyGen.value(col);
980
980
  const width = virtualX ? getCalculatedColWidth(col) + 'px' : transformWidthToStr(col.width);
981
981
  const style: CSSProperties = {
982
982
  width,
@@ -989,9 +989,9 @@ const cellStyleMap = computed(() => {
989
989
  style.minWidth = transformWidthToStr(col.minWidth) ?? width;
990
990
  style.maxWidth = transformWidthToStr(col.maxWidth) ?? width;
991
991
  }
992
-
992
+ const colKey = colKeyGen.value(col);
993
993
  thMap.set(colKey, Object.assign({ textAlign: col.headerAlign }, style, getFixedStyle(TagType.TH, col, depth)));
994
- tdMap.set(colKey, Object.assign({ textAlign: col.align }, style, getFixedStyle(TagType.TD, col, depth), { textAlign: col.align }));
994
+ tdMap.set(colKey, Object.assign({ textAlign: col.align }, style, getFixedStyle(TagType.TD, col, depth)));
995
995
  });
996
996
  });
997
997
  return {
@@ -1000,10 +1000,14 @@ const cellStyleMap = computed(() => {
1000
1000
  };
1001
1001
  });
1002
1002
 
1003
+ function getRowIndex(rowIndex: number) {
1004
+ return rowIndex + (virtual_on ? virtualScroll.value.startIndex : 0);
1005
+ }
1006
+
1003
1007
  /** th title */
1004
1008
  function getHeaderTitle(col: StkTableColumn<DT>): string {
1005
1009
  const colKey = colKeyGen.value(col);
1006
- // 不展示title
1010
+ // hide title
1007
1011
  if (props.hideHeaderTitle === true || (Array.isArray(props.hideHeaderTitle) && props.hideHeaderTitle.includes(colKey))) {
1008
1012
  return '';
1009
1013
  }
@@ -1032,6 +1036,7 @@ function onColumnSort(col: StkTableColumn<DT> | undefined | null, click = true,
1032
1036
  sortCol.value = colKey;
1033
1037
  sortOrderIndex.value = 0;
1034
1038
  }
1039
+ const prevOrder = sortSwitchOrder[sortOrderIndex.value];
1035
1040
  if (click) sortOrderIndex.value++;
1036
1041
  sortOrderIndex.value = sortOrderIndex.value % 3;
1037
1042
 
@@ -1042,17 +1047,21 @@ function onColumnSort(col: StkTableColumn<DT> | undefined | null, click = true,
1042
1047
 
1043
1048
  if (!order && defaultSort) {
1044
1049
  // if no order ,use default order
1045
- const colKey = defaultSort.key || defaultSort.dataIndex;
1046
- if (!colKey) {
1050
+ const defaultColKey = defaultSort.key || defaultSort.dataIndex;
1051
+ if (!defaultColKey) {
1047
1052
  console.error('sortConfig.defaultSort key or dataIndex is required');
1048
1053
  return;
1049
1054
  }
1050
- order = defaultSort.order || 'desc';
1055
+ if (colKey === defaultColKey && prevOrder === defaultSort.order) {
1056
+ order = sortSwitchOrder.find(o => o !== defaultSort.order && o) as Order;
1057
+ } else {
1058
+ order = defaultSort.order;
1059
+ }
1051
1060
  sortOrderIndex.value = sortSwitchOrder.indexOf(order);
1052
- sortCol.value = colKey as string;
1061
+ sortCol.value = defaultColKey as string;
1053
1062
  col = null;
1054
1063
  for (const row of tableHeaders.value) {
1055
- const c = row.find(item => colKeyGenValue(item) === colKey);
1064
+ const c = row.find(item => colKeyGenValue(item) === defaultColKey);
1056
1065
  if (c) {
1057
1066
  col = c;
1058
1067
  break;
@@ -1071,8 +1080,8 @@ function onColumnSort(col: StkTableColumn<DT> | undefined | null, click = true,
1071
1080
  }
1072
1081
  }
1073
1082
 
1074
- function onRowClick(e: MouseEvent, row: DT) {
1075
- emits('row-click', e, row);
1083
+ function onRowClick(e: MouseEvent, row: DT, rowIndex: number) {
1084
+ emits('row-click', e, row, { rowIndex });
1076
1085
  const isCurrentRow = props.rowKey ? currentRowKey.value === rowKeyGen(row) : currentRow.value === row;
1077
1086
  if (isCurrentRow) {
1078
1087
  if (!props.rowCurrentRevokable) {
@@ -1089,8 +1098,8 @@ function onRowClick(e: MouseEvent, row: DT) {
1089
1098
  emits('current-change', e, row, { select: !isCurrentRow });
1090
1099
  }
1091
1100
 
1092
- function onRowDblclick(e: MouseEvent, row: DT) {
1093
- emits('row-dblclick', e, row);
1101
+ function onRowDblclick(e: MouseEvent, row: DT, rowIndex: number) {
1102
+ emits('row-dblclick', e, row, { rowIndex });
1094
1103
  }
1095
1104
 
1096
1105
  /** 表头行右键 */
@@ -1099,8 +1108,8 @@ function onHeaderMenu(e: MouseEvent) {
1099
1108
  }
1100
1109
 
1101
1110
  /** 表体行右键 */
1102
- function onRowMenu(e: MouseEvent, row: DT) {
1103
- emits('row-menu', e, row);
1111
+ function onRowMenu(e: MouseEvent, row: DT, rowIndex: number) {
1112
+ emits('row-menu', e, row, { rowIndex });
1104
1113
  }
1105
1114
 
1106
1115
  /**
@@ -1134,13 +1143,13 @@ function onRowMenu(e: MouseEvent, row: DT) {
1134
1143
  // }
1135
1144
 
1136
1145
  /** 单元格单击 */
1137
- function onCellClick(e: MouseEvent, row: DT, col: StkTableColumn<DT>) {
1146
+ function onCellClick(e: MouseEvent, row: DT, col: StkTableColumn<DT>, rowIndex: number) {
1138
1147
  if (col.type === 'expand') {
1139
1148
  toggleExpandRow(row, col);
1140
1149
  }
1141
1150
  if (props.cellActive) {
1142
1151
  const cellKey = cellKeyGen(row, col);
1143
- const result = { row, col, select: false };
1152
+ const result = { row, col, select: false, rowIndex };
1144
1153
  if (props.selectedCellRevokable && currentSelectedCellKey.value === cellKey) {
1145
1154
  currentSelectedCellKey.value = void 0;
1146
1155
  } else {
@@ -1149,7 +1158,7 @@ function onCellClick(e: MouseEvent, row: DT, col: StkTableColumn<DT>) {
1149
1158
  }
1150
1159
  emits('cell-selected', e, result);
1151
1160
  }
1152
- emits('cell-click', e, row, col);
1161
+ emits('cell-click', e, row, col, { rowIndex });
1153
1162
  }
1154
1163
 
1155
1164
  /** 表头单元格单击 */
@@ -1172,8 +1181,8 @@ function onCellMouseOver(e: MouseEvent, row: DT, col: StkTableColumn<DT>) {
1172
1181
  emits('cell-mouseover', e, row, col);
1173
1182
  }
1174
1183
 
1175
- function onCellMouseDown(e: MouseEvent, row: DT, col: StkTableColumn<DT>) {
1176
- emits('cell-mousedown', e, row, col);
1184
+ function onCellMouseDown(e: MouseEvent, row: DT, col: StkTableColumn<DT>, rowIndex: number) {
1185
+ emits('cell-mousedown', e, row, col, { rowIndex });
1177
1186
  }
1178
1187
 
1179
1188
  /**
@@ -202,7 +202,7 @@ export function useColResize<DT extends Record<string, any>>({
202
202
  /**获取最后一个叶子 */
203
203
  function findLastChildCol(column: StkTableColumn<DT> | null) {
204
204
  if (column?.children?.length) {
205
- const lastChild = column.children.at(-1) as StkTableColumn<DT>;
205
+ const lastChild = column.children.slice(-1)[0] as StkTableColumn<DT>;
206
206
  return findLastChildCol(lastChild);
207
207
  }
208
208
  return column;
@@ -10,6 +10,8 @@ enum ScrollCodes {
10
10
  ArrowLeft = 'ArrowLeft',
11
11
  PageUp = 'PageUp',
12
12
  PageDown = 'PageDown',
13
+ Home = 'Home',
14
+ End = 'End',
13
15
  }
14
16
  /** 所有翻页按键数组 */
15
17
  const ScrollCodesValues = Object.values(ScrollCodes);
@@ -66,7 +68,7 @@ export function useKeyboardArrowScroll<DT extends Record<string, any>>(
66
68
  if (!isMouseOver) return; // 不悬浮还是要触发键盘事件的
67
69
  e.preventDefault(); // 不触发键盘默认的箭头事件
68
70
 
69
- const { scrollTop, rowHeight, containerHeight } = virtualScroll.value;
71
+ const { scrollTop, rowHeight, containerHeight, scrollHeight } = virtualScroll.value;
70
72
  const { scrollLeft } = virtualScrollX.value;
71
73
  const { headless, headerRowHeight } = props;
72
74
 
@@ -78,15 +80,19 @@ export function useKeyboardArrowScroll<DT extends Record<string, any>>(
78
80
  if (e.code === ScrollCodes.ArrowUp) {
79
81
  scrollTo(scrollTop - rowHeight, null);
80
82
  } else if (e.code === ScrollCodes.ArrowRight) {
81
- scrollTo(null, scrollLeft + rowHeight);
83
+ scrollTo(null, scrollLeft + 50);
82
84
  } else if (e.code === ScrollCodes.ArrowDown) {
83
85
  scrollTo(scrollTop + rowHeight, null);
84
86
  } else if (e.code === ScrollCodes.ArrowLeft) {
85
- scrollTo(null, scrollLeft - rowHeight);
87
+ scrollTo(null, scrollLeft - 50);
86
88
  } else if (e.code === ScrollCodes.PageUp) {
87
89
  scrollTo(scrollTop - rowHeight * bodyPageSize + headerHeight, null);
88
90
  } else if (e.code === ScrollCodes.PageDown) {
89
91
  scrollTo(scrollTop + rowHeight * bodyPageSize - headerHeight, null);
92
+ } else if (e.code === ScrollCodes.Home) {
93
+ scrollTo(0, null);
94
+ } else if (e.code === ScrollCodes.End) {
95
+ scrollTo(scrollHeight, null);
90
96
  }
91
97
  }
92
98