stk-table-vue 1.0.0-beta.2 → 1.0.0-beta.4

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/lib/{Dropdown-BIGxWVTR.js → Dropdown-CtiuG-7-.js} +5 -6
  2. package/lib/{StkTable-BugG7a1E.js → StkTable-Bz-71TiQ.js} +127 -79
  3. package/lib/src/StkTable/StkTable.vue.d.ts +1 -1
  4. package/lib/src/StkTable/custom-cells/CheckboxCell/Checkbox.vue.d.ts +29 -0
  5. package/lib/src/StkTable/custom-cells/CheckboxCell/createCheckboxCell.d.ts +82 -0
  6. package/lib/src/StkTable/custom-cells/CheckboxCell/index.d.ts +2 -0
  7. package/lib/src/StkTable/custom-cells/{Filter → FilterCell}/Dropdown/index.vue.d.ts +1 -1
  8. package/lib/src/StkTable/custom-cells/{Filter → FilterCell}/Filter.vue.d.ts +2 -2
  9. package/lib/src/StkTable/custom-cells/{Filter/createFilter.d.ts → FilterCell/createFilterCell.d.ts} +4 -4
  10. package/lib/src/StkTable/custom-cells/FilterCell/index.d.ts +2 -0
  11. package/lib/src/StkTable/custom-cells/{Filter → FilterCell}/types.d.ts +1 -1
  12. package/lib/src/StkTable/features/useAreaSelection.bak.d.ts +25 -0
  13. package/lib/src/StkTable/features/useAreaSelection.d.ts +1 -3
  14. package/lib/src/StkTable/index.d.ts +4 -2
  15. package/lib/src/StkTable/types/index.d.ts +4 -4
  16. package/lib/stk-table-vue.js +182 -20
  17. package/lib/style.css +14 -1
  18. package/package.json +1 -1
  19. package/src/StkTable/StkTable.vue +20 -30
  20. package/src/StkTable/custom-cells/CheckboxCell/Checkbox.less +14 -0
  21. package/src/StkTable/custom-cells/CheckboxCell/Checkbox.vue +41 -0
  22. package/src/StkTable/custom-cells/CheckboxCell/createCheckboxCell.ts +146 -0
  23. package/src/StkTable/custom-cells/CheckboxCell/index.ts +5 -0
  24. package/src/StkTable/custom-cells/{Filter → FilterCell}/Dropdown/index.vue +2 -2
  25. package/src/StkTable/custom-cells/{Filter → FilterCell}/Filter.vue +2 -2
  26. package/src/StkTable/custom-cells/{Filter/createFilter.ts → FilterCell/createFilterCell.ts} +23 -11
  27. package/src/StkTable/custom-cells/FilterCell/index.ts +6 -0
  28. package/src/StkTable/custom-cells/{Filter → FilterCell}/types.ts +1 -1
  29. package/src/StkTable/features/useAreaSelection.bak.ts +951 -0
  30. package/src/StkTable/features/useAreaSelection.ts +178 -51
  31. package/src/StkTable/index.ts +4 -2
  32. package/src/StkTable/registerFeature.ts +2 -2
  33. package/src/StkTable/types/index.ts +4 -4
  34. package/src/StkTable/useTableColumns.ts +2 -2
  35. package/src/StkTable/useVirtualScroll.ts +21 -15
  36. package/lib/src/StkTable/custom-cells/Filter/index.d.ts +0 -2
  37. package/src/StkTable/custom-cells/Filter/index.ts +0 -6
  38. /package/lib/src/StkTable/custom-cells/{Filter → FilterCell}/Dropdown/index.d.ts +0 -0
  39. /package/src/StkTable/custom-cells/{Filter → FilterCell}/Dropdown/index.ts +0 -0
  40. /package/src/StkTable/custom-cells/{Filter → FilterCell}/Filter.less +0 -0
@@ -1,19 +1,19 @@
1
1
  /**
2
2
  * name: stk-table-vue
3
- * version: v1.0.0-beta.2
3
+ * version: v1.0.0-beta.4
4
4
  * description: High performance realtime virtual table for vue3 and vue2.7
5
5
  * author: japlus
6
6
  * homepage: https://ja-plus.github.io/stk-table-vue/
7
7
  * license: MIT
8
8
  */
9
- import { t as StkTable_default } from "./StkTable-BugG7a1E.js";
9
+ import { t as StkTable_default } from "./StkTable-Bz-71TiQ.js";
10
10
  import { createElementBlock, createElementVNode, createVNode, defineComponent, h, nextTick, normalizeClass, normalizeStyle, onMounted, onUnmounted, openBlock, reactive, ref, withModifiers } from "vue";
11
- //#region src/StkTable/custom-cells/Filter/Dropdown/index.vue?vue&type=script&setup=true&lang.ts
11
+ //#region src/StkTable/custom-cells/FilterCell/Dropdown/index.vue?vue&type=script&setup=true&lang.ts
12
12
  var DROPDOWN_DEFAULT_WIDTH = 300;
13
13
  var DROPDOWN_DEFAULT_HEIGHT = 400;
14
14
  var PADDING = 6;
15
15
  //#endregion
16
- //#region src/StkTable/custom-cells/Filter/Dropdown/index.vue
16
+ //#region src/StkTable/custom-cells/FilterCell/Dropdown/index.vue
17
17
  var Dropdown_default = /* @__PURE__ */ defineComponent({
18
18
  __name: "index",
19
19
  setup(__props, { expose: __expose }) {
@@ -30,8 +30,7 @@ var Dropdown_default = /* @__PURE__ */ defineComponent({
30
30
  })
31
31
  }, {
32
32
  title: "",
33
- dataIndex: "label",
34
- customCell: ({ row }) => h("span", [row.label])
33
+ dataIndex: "label"
35
34
  }]);
36
35
  const visible = ref(false);
37
36
  const position = ref({
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * name: stk-table-vue
3
- * version: v1.0.0-beta.2
3
+ * version: v1.0.0-beta.4
4
4
  * description: High performance realtime virtual table for vue3 and vue2.7
5
5
  * author: japlus
6
6
  * homepage: https://ja-plus.github.io/stk-table-vue/
@@ -352,6 +352,7 @@ function useAreaSelection(props, emits, tableContainerRef, dataSourceCopy, table
352
352
  const CELL_RANGE_BOTTOM = "cell-range-b";
353
353
  const CELL_RANGE_LEFT = "cell-range-l";
354
354
  const CELL_RANGE_RIGHT = "cell-range-r";
355
+ const ROW_RANGE_SELECTED = "row-range-selected";
355
356
  const selectionRanges = ref([]);
356
357
  const isSelecting = ref(false);
357
358
  /** start cell */
@@ -441,10 +442,15 @@ function useAreaSelection(props, emits, tableContainerRef, dataSourceCopy, table
441
442
  return [leftWidths[colIndex] ?? 0, rightWidths[colIndex + 1] ?? 0];
442
443
  };
443
444
  });
444
- /** 根据 selectionRanges 计算所有选区内 cellKey 的并集 */
445
- const selectedCellKeys = computed(() => {
445
+ /** 根据 selectionRanges 计算所有选区内 cellKey 的并集(非响应式,用于 DOM 操作) */
446
+ let selectedCellKeys = /* @__PURE__ */ new Set();
447
+ /** 重新计算 selectedCellKeys */
448
+ function recomputeSelectedCellKeys() {
446
449
  const ranges = selectionRanges.value;
447
- if (!ranges.length) return /* @__PURE__ */ new Set();
450
+ if (!ranges.length) {
451
+ selectedCellKeys = /* @__PURE__ */ new Set();
452
+ return;
453
+ }
448
454
  const keys = /* @__PURE__ */ new Set();
449
455
  const cols = tableHeaderLast.value;
450
456
  const data = dataSourceCopy.value;
@@ -461,8 +467,92 @@ function useAreaSelection(props, emits, tableContainerRef, dataSourceCopy, table
461
467
  }
462
468
  }
463
469
  }
464
- return keys;
465
- });
470
+ selectedCellKeys = keys;
471
+ }
472
+ /**
473
+ * 直接操作 DOM 更新选区样式(不触发 Vue re-render)
474
+ * 用于替代在渲染函数中读取响应式选区数据,避免拖选时频繁触发整个表格重渲染
475
+ */
476
+ function updateSelectionDOM() {
477
+ const container = tableContainerRef.value;
478
+ if (!container) return;
479
+ const cellHighlight = highlightCellEnabled.value;
480
+ const rowHighlight = highlightRowEnabled.value;
481
+ const oldSelectedCells = container.querySelectorAll(`.${CELL_RANGE_SELECTED}`);
482
+ for (let i = 0; i < oldSelectedCells.length; i++) oldSelectedCells[i].classList.remove(CELL_RANGE_SELECTED, CELL_RANGE_TOP, CELL_RANGE_BOTTOM, CELL_RANGE_LEFT, CELL_RANGE_RIGHT);
483
+ const oldSelectedRows = container.querySelectorAll(`.${ROW_RANGE_SELECTED}`);
484
+ for (let i = 0; i < oldSelectedRows.length; i++) oldSelectedRows[i].classList.remove(ROW_RANGE_SELECTED);
485
+ recomputeSelectedCellKeys();
486
+ const ranges = selectionRanges.value;
487
+ if (!ranges.length) return;
488
+ const tbody = container.querySelector(".stk-tbody-main");
489
+ if (!tbody) return;
490
+ if (rowHighlight) for (const range of ranges) {
491
+ const { minRow, maxRow } = normalizeRange(range);
492
+ for (let r = minRow; r <= maxRow; r++) {
493
+ const tr = tbody.querySelector(`tr[data-row-i="${r}"]`);
494
+ if (tr) tr.classList.add(ROW_RANGE_SELECTED);
495
+ }
496
+ }
497
+ if (cellHighlight) {
498
+ const lastRange = ranges[ranges.length - 1];
499
+ const { minRow: lrMinRow, maxRow: lrMaxRow, minCol: lrMinCol, maxCol: lrMaxCol } = normalizeRange(lastRange);
500
+ const trs = tbody.querySelectorAll("tr[data-row-i]");
501
+ for (let t = 0; t < trs.length; t++) {
502
+ const tr = trs[t];
503
+ const rowIndex = parseInt(tr.getAttribute("data-row-i"), 10);
504
+ let inAnyRange = false;
505
+ for (const range of ranges) {
506
+ const { minRow, maxRow } = normalizeRange(range);
507
+ if (rowIndex >= minRow && rowIndex <= maxRow) {
508
+ inAnyRange = true;
509
+ break;
510
+ }
511
+ }
512
+ if (!inAnyRange) continue;
513
+ const tds = tr.querySelectorAll("td[data-col-key]");
514
+ for (let d = 0; d < tds.length; d++) {
515
+ const td = tds[d];
516
+ const colKey = td.getAttribute("data-col-key");
517
+ const colIndex = colKeyToIndexMap.value.get(colKey);
518
+ if (colIndex === void 0 || colIndex < 0) continue;
519
+ const row = dataSourceCopy.value[rowIndex];
520
+ const cols = tableHeaderLast.value;
521
+ if (!row || !cols[colIndex]) continue;
522
+ const ck = cellKeyGen(row, cols[colIndex]);
523
+ if (!selectedCellKeys.has(ck)) continue;
524
+ td.classList.add(CELL_RANGE_SELECTED);
525
+ if (rowIndex >= lrMinRow && rowIndex <= lrMaxRow && colIndex >= lrMinCol && colIndex <= lrMaxCol) {
526
+ if (rowIndex === lrMinRow) td.classList.add(CELL_RANGE_TOP);
527
+ if (rowIndex === lrMaxRow) td.classList.add(CELL_RANGE_BOTTOM);
528
+ if (colIndex === lrMinCol) td.classList.add(CELL_RANGE_LEFT);
529
+ if (colIndex === lrMaxCol) td.classList.add(CELL_RANGE_RIGHT);
530
+ }
531
+ }
532
+ }
533
+ }
534
+ }
535
+ /**
536
+ * 监听 selectionRanges 变化,在 DOM 更新后直接操作选区 class
537
+ * 同时在虚拟滚动等导致 DOM 重建时也能重新应用选区样式
538
+ */
539
+ watch(() => {
540
+ const ranges = selectionRanges.value;
541
+ const vs = virtualScroll.value;
542
+ const vsx = virtualScrollX.value;
543
+ return [
544
+ ranges.length,
545
+ ranges.length > 0 ? JSON.stringify(ranges.map((r) => r.index)) : "",
546
+ vs.startIndex,
547
+ vs.endIndex,
548
+ vsx.startIndex,
549
+ vsx.endIndex,
550
+ dataSourceCopy.value.length,
551
+ tableHeaderLast.value.length
552
+ ];
553
+ }, () => {
554
+ nextTick(updateSelectionDOM);
555
+ }, { flush: "post" });
466
556
  onMounted(() => {
467
557
  addListener();
468
558
  });
@@ -907,40 +997,11 @@ function useAreaSelection(props, emits, tableContainerRef, dataSourceCopy, table
907
997
  * @param colKey 列唯一键
908
998
  * @returns 样式类名数组
909
999
  */
910
- function getAreaSelectionClasses(cellKey, absoluteRowIndex, colKey) {
911
- if (!highlightCellEnabled.value) return [];
912
- if (!selectedCellKeys.value.has(cellKey)) return [];
913
- const colIndex = colKeyToIndexMap.value.get(colKey);
914
- if (colIndex === void 0 || colIndex < 0) return [];
915
- const classes = [CELL_RANGE_SELECTED];
916
- const ranges = selectionRanges.value;
917
- if (!ranges.length) return classes;
918
- const lastRange = ranges[ranges.length - 1];
919
- const { minRow, maxRow, minCol, maxCol } = normalizeRange(lastRange);
920
- if (absoluteRowIndex >= minRow && absoluteRowIndex <= maxRow && colIndex >= minCol && colIndex <= maxCol) {
921
- if (absoluteRowIndex === minRow) classes.push(CELL_RANGE_TOP);
922
- if (absoluteRowIndex === maxRow) classes.push(CELL_RANGE_BOTTOM);
923
- if (colIndex === minCol) classes.push(CELL_RANGE_LEFT);
924
- if (colIndex === maxCol) classes.push(CELL_RANGE_RIGHT);
925
- }
926
- return classes;
927
- }
928
1000
  /**
929
1001
  * 判断一行的选区样式类名(行高亮)
930
1002
  * @param absoluteRowIndex 行在 dataSourceCopy 中的绝对索引
931
1003
  * @returns 样式类名数组
932
1004
  */
933
- function getAreaSelectionRowClasses(absoluteRowIndex) {
934
- if (!highlightRowEnabled.value) return [];
935
- const ranges = selectionRanges.value;
936
- if (!ranges.length) return [];
937
- for (const range of ranges) {
938
- const { begin: { row: r1 }, end: { row: r2 } } = range.index;
939
- const [minRow, maxRow] = r1 < r2 ? [r1, r2] : [r2, r1];
940
- if (absoluteRowIndex >= minRow && absoluteRowIndex <= maxRow) return ["row-range-selected"];
941
- }
942
- return [];
943
- }
944
1005
  /** 获取选中的单元格信息 */
945
1006
  function getSelectedArea() {
946
1007
  const ranges = selectionRanges.value;
@@ -1018,8 +1079,6 @@ function useAreaSelection(props, emits, tableContainerRef, dataSourceCopy, table
1018
1079
  return {
1019
1080
  config,
1020
1081
  isSelecting,
1021
- getClass: getAreaSelectionClasses,
1022
- getRowClass: getAreaSelectionRowClasses,
1023
1082
  get: getSelectedArea,
1024
1083
  set: setAreaSelection,
1025
1084
  clear: clearSelectedArea,
@@ -1037,8 +1096,6 @@ var ON_DEMAND_FEATURE = { [useAreaSelectionName]: ((props) => {
1037
1096
  config: computed(() => ({ enabled: false })),
1038
1097
  isSelecting: ref(false),
1039
1098
  onMD: () => {},
1040
- getClass: () => [],
1041
- getRowClass: () => [],
1042
1099
  get: () => ({
1043
1100
  rows: [],
1044
1101
  cols: [],
@@ -2528,7 +2585,7 @@ function useTableColumns(virtualX, isRelativeMode) {
2528
2585
  const col = arr[i];
2529
2586
  if (col.hidden) continue;
2530
2587
  col.__P__ = parent;
2531
- col.__LEAF_START__ = leafIndex;
2588
+ col.__LF_S__ = leafIndex;
2532
2589
  /** 一列中的子节点数量 */
2533
2590
  let colChildrenLen = 1;
2534
2591
  /** 多级表头的父节点宽度,通过叶子节点宽度计算得到 */
@@ -2543,7 +2600,7 @@ function useTableColumns(virtualX, isRelativeMode) {
2543
2600
  leafIndex++;
2544
2601
  for (let j = depth; j <= maxDeep; j++) tableHeadersForCalcTemp[j].push(col);
2545
2602
  }
2546
- col.__LEAF_END__ = leafIndex;
2603
+ col.__LF_E__ = leafIndex;
2547
2604
  col.__W__ = colWidth;
2548
2605
  tableHeadersTemp[depth].push(col);
2549
2606
  const rowSpan = col.children ? 1 : maxDeep - depth + 1;
@@ -2985,11 +3042,11 @@ function useVirtualScroll(props, tableContainerRef, trRef, dataSourceCopy, table
2985
3042
  const groupRight = cumLeft + groupWidth;
2986
3043
  if (!foundStart && groupRight > scrollLeft) {
2987
3044
  foundStart = true;
2988
- theadStartIndex = col.__LEAF_START__ ?? 0;
3045
+ theadStartIndex = col.__LF_S__ ?? 0;
2989
3046
  theadOffsetLeft = cumLeft;
2990
3047
  }
2991
3048
  cumLeft = groupRight;
2992
- theadEndIndex = col.__LEAF_END__ ?? totalLeafCount;
3049
+ theadEndIndex = col.__LF_E__ ?? totalLeafCount;
2993
3050
  if (foundStart && groupRight >= scrollLeft + containerWidth) break;
2994
3051
  }
2995
3052
  if (!foundStart) {
@@ -3023,19 +3080,11 @@ function useVirtualScroll(props, tableContainerRef, trRef, dataSourceCopy, table
3023
3080
  result.push(...leftFixedCols);
3024
3081
  const theadStart = theadVirtualX.value.startIndex;
3025
3082
  const leftSpacerColspan = Math.max(0, startIndex - theadStart);
3026
- if (leftSpacerColspan) result.push({
3027
- type: "spacer",
3028
- __COLSPAN__: leftSpacerColspan
3029
- });
3083
+ if (leftSpacerColspan) result.push({ __VT_C_SP__: leftSpacerColspan });
3030
3084
  result.push(...visibleCols);
3031
- if (rightFixedCols.length) {
3032
- const rightSpacerColspan = Math.max(0, theadVirtualX.value.endIndex - endIndex);
3033
- result.push({
3034
- type: "spacer",
3035
- __COLSPAN__: rightSpacerColspan
3036
- });
3037
- result.push(...rightFixedCols);
3038
- }
3085
+ const rightSpacerColspan = Math.max(0, theadVirtualX.value.endIndex - endIndex);
3086
+ if (rightSpacerColspan) result.push({ __VT_C_SP__: rightSpacerColspan });
3087
+ result.push(...rightFixedCols);
3039
3088
  return result;
3040
3089
  }
3041
3090
  const leftCols = [];
@@ -3065,8 +3114,8 @@ function useVirtualScroll(props, tableContainerRef, trRef, dataSourceCopy, table
3065
3114
  return tableHeaders.value.map((row) => {
3066
3115
  return row.filter((col) => {
3067
3116
  if (col.fixed === "left" || col.fixed === "right") return true;
3068
- const leafStart = col.__LEAF_START__ ?? 0;
3069
- return (col.__LEAF_END__ ?? leafStart + 1) > startIndex && leafStart < endIndex;
3117
+ const leafStart = col.__LF_S__ ?? 0;
3118
+ return (col.__LF_E__ ?? leafStart + 1) > startIndex && leafStart < endIndex;
3070
3119
  });
3071
3120
  });
3072
3121
  }
@@ -3076,8 +3125,8 @@ function useVirtualScroll(props, tableContainerRef, trRef, dataSourceCopy, table
3076
3125
  /** 展开行 colspan:虚拟滚动时等于所有 td 元素数量(含 spacer)之和 */
3077
3126
  const expandRowColspan = computed(() => {
3078
3127
  if (!virtualX_on.value) return tableHeaderLast.value.length;
3079
- const spacers = virtualX_columnPart.value.filter((c) => c.type === "spacer");
3080
- return 2 + virtualX_columnPart.value.length + spacers.reduce((sum, s) => sum + Math.max(0, (s.__COLSPAN__ ?? 0) - 1), 0);
3128
+ const spacers = virtualX_columnPart.value.filter((c) => c.__VT_C_SP__);
3129
+ return 2 + virtualX_columnPart.value.length + spacers.reduce((sum, s) => sum + Math.max(0, (s.__VT_C_SP__ ?? 0) - 1), 0);
3081
3130
  });
3082
3131
  const virtualX_offsetRight = computed(() => {
3083
3132
  if (!virtualX_on.value) return 0;
@@ -3314,7 +3363,6 @@ function useVirtualScroll(props, tableContainerRef, trRef, dataSourceCopy, table
3314
3363
  offsetLeft = idx > 0 ? nonFixedCols[idx - 1].cumWidth : 0;
3315
3364
  leftFirstColRestWidth = nonFixedCols[idx].cumWidth - sLeft;
3316
3365
  } else if (nonFixedCols.length > 0) startIndex = nonFixedCols[0].index;
3317
- let endColWidthSum = leftFirstColRestWidth;
3318
3366
  let actualLeftColWidthSum = 0;
3319
3367
  for (const leftCol of leftFixedCols) {
3320
3368
  if (leftCol.index >= startIndex) break;
@@ -3322,7 +3370,12 @@ function useVirtualScroll(props, tableContainerRef, trRef, dataSourceCopy, table
3322
3370
  }
3323
3371
  const containerW = containerWidth - actualLeftColWidthSum;
3324
3372
  let endIndex = headerLength;
3325
- for (let colIndex = startIndex + 1; colIndex < headerLength; colIndex++) {
3373
+ let endColWidthSum = leftFirstColRestWidth;
3374
+ /**
3375
+ * 这里根据 leftFirstColRestWidth 如果为0 说明开始位置恰好在单元格边界,则计算endIndex 需要从当前单元格开始。
3376
+ * 如果有值,则说明开始位置的单元格已经切了一半,需要从下一个单元格开始计算 因此startIndex + 1。
3377
+ */
3378
+ for (let colIndex = leftFirstColRestWidth ? startIndex + 1 : startIndex; colIndex < headerLength; colIndex++) {
3326
3379
  const col = tableHeaderLastValue[colIndex];
3327
3380
  endColWidthSum += getCalculatedColWidth(col);
3328
3381
  if (endColWidthSum >= containerW) {
@@ -3745,7 +3798,7 @@ var StkTable_default = /* @__PURE__ */ defineComponent({
3745
3798
  const targetKey = colKeyGen.value(column);
3746
3799
  return tableHeaderLast.value.findIndex((item) => colKeyGen.value(item) === targetKey);
3747
3800
  }
3748
- const { config: areaSelectionConfig, isSelecting: isAreaSelecting, onMD: onSelectionMouseDown, getClass: getAreaSelectionClasses, getRowClass: getAreaSelectionRowClass, get: getSelectedArea, set: setAreaSelection, clear: clearSelectedArea, copy: copySelectedArea } = ON_DEMAND_FEATURE[useAreaSelectionName](props, emits, tableContainerRef, dataSourceCopy, tableHeaderLast, colKeyGen, cellKeyGen, scrollTo, virtualScroll, virtualScrollX, getRowIndex, getColumnIndex);
3801
+ const { config: areaSelectionConfig, isSelecting: isAreaSelecting, onMD: onSelectionMouseDown, get: getSelectedArea, set: setAreaSelection, clear: clearSelectedArea, copy: copySelectedArea } = ON_DEMAND_FEATURE[useAreaSelectionName](props, emits, tableContainerRef, dataSourceCopy, tableHeaderLast, colKeyGen, cellKeyGen, scrollTo, virtualScroll, virtualScrollX, getRowIndex, getColumnIndex);
3749
3802
  /** 键盘箭头滚动 */
3750
3803
  useKeyboardArrowScroll(tableContainerRef, props, scrollTo, virtualScroll, virtualScrollX, tableHeaders, virtual_on, areaSelectionConfig);
3751
3804
  /** 固定列处理 */
@@ -3917,7 +3970,6 @@ var StkTable_default = /* @__PURE__ */ defineComponent({
3917
3970
  (row === null || row === void 0 ? void 0 : row.__EXP__) ? "expanded" : "",
3918
3971
  (row === null || row === void 0 ? void 0 : row.__EXP_R__) ? "expanded-row" : ""
3919
3972
  ];
3920
- if (areaSelectionConfig.value.enabled) classList.push(...getAreaSelectionRowClass(rowIndex));
3921
3973
  if (currentRowKey.value === rowKey || row === currentRow.value) classList.push("active");
3922
3974
  if (props.showTrHoverClass && (rowKey === currentHoverRowKey.value || row === currentHoverRow)) classList.push("hover");
3923
3975
  const result = {
@@ -3978,10 +4030,6 @@ var StkTable_default = /* @__PURE__ */ defineComponent({
3978
4030
  if (activeMergedCells.value.has(cellKey)) classList.push("cell-active");
3979
4031
  }
3980
4032
  if (props.cellActive && currentSelectedCellKey.value === cellKey) classList.push("active");
3981
- if (areaSelectionConfig.value.enabled) {
3982
- const absRowIndex = getAbsoluteRowIndex(rowIndex);
3983
- classList.push(...getAreaSelectionClasses(cellKey, absRowIndex, colKey));
3984
- }
3985
4033
  if (col.type === "seq") classList.push("seq-column");
3986
4034
  else if (col.type === "expand" && (row.__EXP__ ? colKeyGen.value(row.__EXP__) === colKey : false)) classList.push("expanded");
3987
4035
  else if (row.__T_EXP__ && col.type === "tree-node") classList.push("tree-expanded");
@@ -3990,7 +4038,7 @@ var StkTable_default = /* @__PURE__ */ defineComponent({
3990
4038
  "data-col-key": colKey,
3991
4039
  style: cellStyleMap.value[TagType.TD].get(colKey),
3992
4040
  class: classList,
3993
- ...mergeCellsWrapper(row, col, rowIndex, col.__LEAF_START__ ?? 0)
4041
+ ...mergeCellsWrapper(row, col, rowIndex, col.__LF_S__ ?? 0)
3994
4042
  };
3995
4043
  }
3996
4044
  function onRowClick(e) {
@@ -4584,11 +4632,11 @@ var StkTable_default = /* @__PURE__ */ defineComponent({
4584
4632
  style: normalizeStyle(`min-width:${unref(theadVirtualX).offsetLeft}px;width:${unref(theadVirtualX).offsetLeft}px`)
4585
4633
  }, null, 4)) : createCommentVNode("", true),
4586
4634
  (openBlock(true), createElementBlock(Fragment, null, renderList(unref(virtualX_columnPart), (col) => {
4587
- return openBlock(), createElementBlock(Fragment, { key: col.type === "spacer" ? "spacer" : colKeyGen.value(col) }, [col.type === "spacer" ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [col.__COLSPAN__ ? (openBlock(), createElementBlock("td", {
4635
+ return openBlock(), createElementBlock(Fragment, { key: col.__VT_C_SP__ ? "spacer" : colKeyGen.value(col) }, [col.__VT_C_SP__ ? (openBlock(), createElementBlock("td", {
4588
4636
  key: 0,
4589
4637
  class: "vt-x-spacer",
4590
- colspan: col.__COLSPAN__
4591
- }, null, 8, _hoisted_8)) : createCommentVNode("", true)], 64)) : (openBlock(), createElementBlock("td", mergeProps({
4638
+ colspan: col.__VT_C_SP__
4639
+ }, null, 8, _hoisted_8)) : (openBlock(), createElementBlock("td", mergeProps({
4592
4640
  key: 1,
4593
4641
  ref_for: true
4594
4642
  }, getTFProps(col)), [col.customFooterCell ? (openBlock(), createBlock(resolveDynamicComponent(col.customFooterCell), {
@@ -4639,11 +4687,11 @@ var StkTable_default = /* @__PURE__ */ defineComponent({
4639
4687
  style: normalizeStyle(`min-width:${unref(theadVirtualX).offsetLeft}px;width:${unref(theadVirtualX).offsetLeft}px`)
4640
4688
  }, null, 4)) : createCommentVNode("", true),
4641
4689
  (openBlock(true), createElementBlock(Fragment, null, renderList(unref(virtualX_columnPart), (col) => {
4642
- return openBlock(), createElementBlock(Fragment, { key: col.type === "spacer" ? "spacer" : colKeyGen.value(col) }, [col.type === "spacer" ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [col.__COLSPAN__ ? (openBlock(), createElementBlock("td", {
4690
+ return openBlock(), createElementBlock(Fragment, { key: col.__VT_C_SP__ ? "spacer" : colKeyGen.value(col) }, [col.__VT_C_SP__ ? (openBlock(), createElementBlock("td", {
4643
4691
  key: 0,
4644
4692
  class: "vt-x-spacer",
4645
- colspan: col.__COLSPAN__
4646
- }, null, 8, _hoisted_11)) : createCommentVNode("", true)], 64)) : (openBlock(), createElementBlock("td", {
4693
+ colspan: col.__VT_C_SP__
4694
+ }, null, 8, _hoisted_11)) : (openBlock(), createElementBlock("td", {
4647
4695
  key: 1,
4648
4696
  style: normalizeStyle(cellStyleMap.value[unref(TagType).TD].get(colKeyGen.value(col)))
4649
4697
  }, null, 4))], 64);
@@ -4669,21 +4717,21 @@ var StkTable_default = /* @__PURE__ */ defineComponent({
4669
4717
  }, () => [createTextVNode(toDisplayString(row.__EXP_R__ && row.__EXP_C__ && row.__EXP_R__[row.__EXP_C__.dataIndex] || ""), 1)])])], 8, _hoisted_12)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
4670
4718
  unref(virtualX_on) ? (openBlock(), createElementBlock("td", _hoisted_14)) : createCommentVNode("", true),
4671
4719
  (openBlock(true), createElementBlock(Fragment, null, renderList(unref(virtualX_columnPart), (col) => {
4672
- return openBlock(), createElementBlock(Fragment, { key: col.type === "spacer" ? "spacer" : colKeyGen.value(col) }, [col.type === "spacer" ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [col.__COLSPAN__ ? (openBlock(), createElementBlock("td", {
4720
+ return openBlock(), createElementBlock(Fragment, { key: col.__VT_C_SP__ ? "spacer" : colKeyGen.value(col) }, [col.__VT_C_SP__ ? (openBlock(), createElementBlock("td", {
4673
4721
  key: 0,
4674
4722
  class: "vt-x-spacer",
4675
- colspan: col.__COLSPAN__
4676
- }, null, 8, _hoisted_15)) : createCommentVNode("", true)], 64)) : !shouldHideCell(row, col) ? (openBlock(), createElementBlock("td", mergeProps({
4723
+ colspan: col.__VT_C_SP__
4724
+ }, null, 8, _hoisted_15)) : !shouldHideCell(row, col) ? (openBlock(), createElementBlock("td", mergeProps({
4677
4725
  key: 1,
4678
4726
  ref_for: true
4679
- }, getTDProps(row, col, rowIndex, col.__LEAF_START__ ?? 0)), [col.customCell ? (openBlock(), createBlock(resolveDynamicComponent(col.customCell), {
4727
+ }, getTDProps(row, col, rowIndex, col.__LF_S__ ?? 0)), [col.customCell ? (openBlock(), createBlock(resolveDynamicComponent(col.customCell), {
4680
4728
  key: 0,
4681
4729
  class: "table-cell-wrapper",
4682
4730
  tabindex: "-1",
4683
4731
  col,
4684
4732
  row,
4685
4733
  rowIndex: getAbsoluteRowIndex(rowIndex),
4686
- colIndex: col.__LEAF_START__ ?? 0,
4734
+ colIndex: col.__LF_S__ ?? 0,
4687
4735
  cellValue: row && row[col.dataIndex],
4688
4736
  expanded: row && row.__EXP__,
4689
4737
  "tree-expanded": row && row.__T_EXP__
@@ -1,4 +1,4 @@
1
- import { FilterStatus } from './custom-cells/Filter/types';
1
+ import { FilterStatus } from './custom-cells/FilterCell/types';
2
2
  import { AreaSelectionConfig, AreaSelectionRange, AutoRowHeightConfig, ColResizableConfig, DragRowConfig, ExpandConfig, ExperimentalConfig, FooterConfig, HeaderDragConfig, HighlightConfig, Order, PrivateRowDT, PrivateStkTableColumn, RowActiveOption, SeqConfig, SortConfig, StkTableColumn, TreeConfig, UniqKey, UniqKeyProp } from './types/index';
3
3
  import { ScrollbarOptions } from './useScrollbar';
4
4
 
@@ -0,0 +1,29 @@
1
+ declare const _default: import('vue').DefineComponent<import('vue').ExtractPropTypes<__VLS_TypePropsToRuntimeProps<{
2
+ /** 当前是否选中 */
3
+ checked?: boolean;
4
+ /** 是否半选状态 */
5
+ indeterminate?: boolean;
6
+ /** 自定义 checkbox 组件(如 Element Plus / Ant Design Vue 的 Checkbox) */
7
+ customComponent?: any;
8
+ }>>, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
9
+ change: (checked: boolean) => void;
10
+ }, string, import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<__VLS_TypePropsToRuntimeProps<{
11
+ /** 当前是否选中 */
12
+ checked?: boolean;
13
+ /** 是否半选状态 */
14
+ indeterminate?: boolean;
15
+ /** 自定义 checkbox 组件(如 Element Plus / Ant Design Vue 的 Checkbox) */
16
+ customComponent?: any;
17
+ }>>> & Readonly<{
18
+ onChange?: ((checked: boolean) => any) | undefined;
19
+ }>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
20
+ export default _default;
21
+ type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;
22
+ type __VLS_TypePropsToRuntimeProps<T> = {
23
+ [K in keyof T]-?: {} extends Pick<T, K> ? {
24
+ type: import('vue').PropType<__VLS_NonUndefinedable<T[K]>>;
25
+ } : {
26
+ type: import('vue').PropType<T[K]>;
27
+ required: true;
28
+ };
29
+ };
@@ -0,0 +1,82 @@
1
+ /** createCheckboxCell 配置选项 */
2
+ export interface createCheckboxCellOptions<T = any> {
3
+ /**
4
+ * 行数据中表示选中状态的字段名
5
+ * @default '_isChecked'
6
+ */
7
+ field?: string;
8
+ /**
9
+ * 自定义 checkbox 组件(如 Element Plus / Ant Design Vue 的 Checkbox)
10
+ * 不传则使用原生 input[type=checkbox]
11
+ */
12
+ checkboxComponent?: any;
13
+ /**
14
+ * 单元格 checkbox 状态变更回调
15
+ * @param checked 是否选中
16
+ * @param row 当前行数据
17
+ */
18
+ onChange?: (checked: boolean, row: T) => void;
19
+ /**
20
+ * 全选 checkbox 状态变更回调
21
+ * @param checked 是否全选
22
+ */
23
+ onSelectAll?: (checked: boolean) => void;
24
+ }
25
+ /**
26
+ * Checkbox 工厂函数
27
+ *
28
+ * 用于快速创建多选框单元格和表头单元格组件。
29
+ *
30
+ * @param options 配置选项
31
+ * @returns 包含 CheckboxCell 和 CheckboxAllCell 组件的对象
32
+ *
33
+ * @example
34
+ * ```ts
35
+ * const { CheckboxCell, CheckboxAllCell } = createCheckboxCell({
36
+ * field: '_isChecked',
37
+ * onChange: (checked, row) => { row._isChecked = checked },
38
+ * });
39
+ *
40
+ * const columns = [
41
+ * {
42
+ * dataIndex: 'checkbox',
43
+ * width: 50,
44
+ * customCell: CheckboxCell,
45
+ * customHeaderCell: CheckboxAllCell,
46
+ * },
47
+ * // ...other columns
48
+ * ];
49
+ * ```
50
+ */
51
+ export declare function createCheckboxCell<T extends Record<string, any> = any>(options?: createCheckboxCellOptions<T>): {
52
+ CheckboxCell: () => import('vue').Raw<import('vue').DefineComponent<{
53
+ row: any;
54
+ col: import('../..').StkTableColumn<any>;
55
+ cellValue: any;
56
+ rowIndex: number;
57
+ colIndex: number;
58
+ expanded?: import('../..').StkTableColumn<any> | undefined;
59
+ treeExpanded?: boolean | undefined;
60
+ }, () => import('vue').VNode<import('vue').RendererNode, import('vue').RendererElement, {
61
+ [key: string]: any;
62
+ }>, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{
63
+ row: any;
64
+ col: import('../..').StkTableColumn<any>;
65
+ cellValue: any;
66
+ rowIndex: number;
67
+ colIndex: number;
68
+ expanded?: import('../..').StkTableColumn<any> | undefined;
69
+ treeExpanded?: boolean | undefined;
70
+ }> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>>;
71
+ CheckboxAllCell: () => import('vue').Raw<import('vue').DefineComponent<{
72
+ col?: any;
73
+ rowIndex?: any;
74
+ colIndex?: any;
75
+ }, () => import('vue').VNode<import('vue').RendererNode, import('vue').RendererElement, {
76
+ [key: string]: any;
77
+ }>, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{
78
+ col?: any;
79
+ rowIndex?: any;
80
+ colIndex?: any;
81
+ }> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>>;
82
+ };
@@ -0,0 +1,2 @@
1
+ export { createCheckboxCell } from './createCheckboxCell';
2
+ export type { createCheckboxCellOptions } from './createCheckboxCell';
@@ -1,4 +1,4 @@
1
- import { FilterOption } from '../types';
1
+ import { FilterOption } from '../types.js';
2
2
 
3
3
  declare function show(pos: {
4
4
  x: number;
@@ -7,13 +7,13 @@ declare function __VLS_template(): {
7
7
  declare const __VLS_component: import('vue').DefineComponent<import('vue').ExtractPropTypes<__VLS_TypePropsToRuntimeProps<CustomHeaderCellProps<any> & {
8
8
  theme?: "light" | "dark";
9
9
  active?: boolean;
10
- options: FilterOption[];
10
+ getOptions: () => FilterOption[];
11
11
  }>>, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
12
12
  change: (value: any[]) => void;
13
13
  }, string, import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<__VLS_TypePropsToRuntimeProps<CustomHeaderCellProps<any> & {
14
14
  theme?: "light" | "dark";
15
15
  active?: boolean;
16
- options: FilterOption[];
16
+ getOptions: () => FilterOption[];
17
17
  }>>> & Readonly<{
18
18
  onChange?: ((value: any[]) => any) | undefined;
19
19
  }>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
@@ -1,16 +1,16 @@
1
1
  import { CustomHeaderCellProps, UniqKey } from '../../types';
2
2
  import { VNode } from 'vue';
3
- import { CreateFilterOption, FilterComponentConfig, FilterStatus } from './types';
3
+ import { CreateFilterCellOption, FilterComponentConfig, FilterStatus } from './types.js';
4
4
 
5
5
  /**
6
6
  * 表格筛选功能工厂函数 (BETA)
7
7
  *
8
- * Q: 为什么要通过 stkTableInstance 来设置筛选状态,而不是直接在 createFilter 中传入dataSource。
9
- * A: 因为 createFilter 不一定有 dataSource的上下文,它可能在独立的js/ts 中使用,而非Vue SFC。而通过 stkTableInstance 可以获取到 dataSource
8
+ * Q: 为什么要通过 stkTableInstance 来设置筛选状态,而不是直接在 createFilterCell 中传入dataSource。
9
+ * A: 因为 createFilterCell 不一定有 dataSource的上下文,它可能在独立的js/ts 中使用,而非Vue SFC。而通过 stkTableInstance 可以获取到 dataSource
10
10
  * @beta
11
11
  * @returns
12
12
  */
13
- export declare function createFilter(option?: CreateFilterOption): {
13
+ export declare function createFilterCell(option?: CreateFilterCellOption): {
14
14
  Filter: (config?: FilterComponentConfig, component?: VNode | ((props: CustomHeaderCellProps<any>) => VNode)) => import('vue').Raw<import('vue').DefineComponent<{
15
15
  col: import('../../types').StkTableColumn<any>;
16
16
  rowIndex: number;
@@ -0,0 +1,2 @@
1
+ export { createFilterCell } from './createFilterCell';
2
+ export type { FilterStatus, CreateFilterCellOption } from './types';
@@ -34,7 +34,7 @@ export interface FilterComponentConfig {
34
34
  autoOptions?: boolean;
35
35
  }
36
36
  /** createFilter选项接口 */
37
- export interface CreateFilterOption {
37
+ export interface CreateFilterCellOption {
38
38
  /** 是否远程筛选 */
39
39
  remote?: boolean;
40
40
  /** 筛选状态改变时触发 */
@@ -0,0 +1,25 @@
1
+ import { Ref, ShallowRef } from 'vue';
2
+ import { AreaSelectionConfig, AreaSelectionRange, CellKeyGen, ColKeyGen, StkTableColumn, UniqKey, AreaSelectionSetterRange, AreaSelectionSetterOption } from '../types';
3
+ import { VirtualScrollStore, VirtualScrollXStore } from '../useVirtualScroll';
4
+
5
+ /**
6
+ * 单元格区域选择功能
7
+ * 支持鼠标拖拽选择、键盘导航、复制粘贴等功能
8
+ * en: Cell area selection feature with mouse drag, keyboard navigation, copy-paste, etc.
9
+ */
10
+ export declare function useAreaSelection<DT extends Record<string, any>>(props: any, emits: any, tableContainerRef: Ref<HTMLDivElement | undefined>, dataSourceCopy: ShallowRef<DT[]>, tableHeaderLast: ShallowRef<StkTableColumn<DT>[]>, colKeyGen: ColKeyGen, cellKeyGen: CellKeyGen, scrollTo: (top: number | null, left: number | null) => void, virtualScroll: Ref<VirtualScrollStore>, virtualScrollX: Ref<VirtualScrollXStore>, getRowIndex: (row: DT) => number, getColumnIndex: (col: StkTableColumn<DT>) => number): {
11
+ config: import('vue').ComputedRef<AreaSelectionConfig>;
12
+ isSelecting: Ref<boolean, boolean>;
13
+ getClass: (cellKey: string, absoluteRowIndex: number, colKey: UniqKey) => string[];
14
+ getRowClass: (absoluteRowIndex: number) => string[];
15
+ get: () => {
16
+ rows: DT[];
17
+ cols: StkTableColumn<DT>[];
18
+ ranges: AreaSelectionRange[];
19
+ };
20
+ set: (ranges?: AreaSelectionSetterRange<DT>, option?: AreaSelectionSetterOption) => AreaSelectionRange[];
21
+ clear: () => void;
22
+ copy: () => string;
23
+ onMD: (e: MouseEvent) => void;
24
+ };
25
+ export declare const useAreaSelectionName = "useAreaSelection";
@@ -1,5 +1,5 @@
1
1
  import { Ref, ShallowRef } from 'vue';
2
- import { AreaSelectionConfig, AreaSelectionRange, CellKeyGen, ColKeyGen, StkTableColumn, UniqKey, AreaSelectionSetterRange, AreaSelectionSetterOption } from '../types';
2
+ import { AreaSelectionConfig, AreaSelectionRange, CellKeyGen, ColKeyGen, StkTableColumn, AreaSelectionSetterRange, AreaSelectionSetterOption } from '../types';
3
3
  import { VirtualScrollStore, VirtualScrollXStore } from '../useVirtualScroll';
4
4
 
5
5
  /**
@@ -10,8 +10,6 @@ import { VirtualScrollStore, VirtualScrollXStore } from '../useVirtualScroll';
10
10
  export declare function useAreaSelection<DT extends Record<string, any>>(props: any, emits: any, tableContainerRef: Ref<HTMLDivElement | undefined>, dataSourceCopy: ShallowRef<DT[]>, tableHeaderLast: ShallowRef<StkTableColumn<DT>[]>, colKeyGen: ColKeyGen, cellKeyGen: CellKeyGen, scrollTo: (top: number | null, left: number | null) => void, virtualScroll: Ref<VirtualScrollStore>, virtualScrollX: Ref<VirtualScrollXStore>, getRowIndex: (row: DT) => number, getColumnIndex: (col: StkTableColumn<DT>) => number): {
11
11
  config: import('vue').ComputedRef<AreaSelectionConfig>;
12
12
  isSelecting: Ref<boolean, boolean>;
13
- getClass: (cellKey: string, absoluteRowIndex: number, colKey: UniqKey) => string[];
14
- getRowClass: (absoluteRowIndex: number) => string[];
15
13
  get: () => {
16
14
  rows: DT[];
17
15
  cols: StkTableColumn<DT>[];
@@ -3,7 +3,9 @@ export { registerFeature } from './registerFeature';
3
3
  export { default as StkTable } from './StkTable.vue';
4
4
  export type { Order, SortConfig, SortOption, SortState, StkTableColumn } from './types/index';
5
5
  export { binarySearch, insertToOrderedArray, strCompare, tableSort } from './utils';
6
- export { createFilter } from './custom-cells/Filter/index';
7
- export type { CreateFilterOption, FilterStatus } from './custom-cells/Filter/index';
6
+ export { createFilterCell } from './custom-cells/FilterCell/index';
7
+ export type { CreateFilterCellOption, FilterStatus } from './custom-cells/FilterCell/index';
8
8
  export { createEditableCell } from './custom-cells/EditableCell/index';
9
9
  export type { CreateEditableCellOptions } from './custom-cells/EditableCell/index';
10
+ export { createCheckboxCell } from './custom-cells/CheckboxCell/index';
11
+ export type { createCheckboxCellOptions } from './custom-cells/CheckboxCell/index';