stk-table-vue 0.6.4 → 0.6.6

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,10 +1,18 @@
1
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)
2
6
 
3
7
  Vue3 简易虚拟滚动表格。用于实时数据展示,新数据行高亮渐暗动效。
4
8
 
5
9
  Vue2.7支持引入源码(**ts**)使用。
6
10
 
7
- repo:
11
+ [Stk Table Vue 文档](https://ja-plus.github.io/stk-table-vue/)
12
+
13
+ ## License
14
+ MIT
15
+ repo(求 star🌟):
8
16
  - [Github](https://github.com/ja-plus/stk-table-vue)
9
17
  - [Gitee](https://gitee.com/japlus/stk-table-vue) 🇨🇳
10
18
 
@@ -227,7 +235,7 @@ export type StkProps = {
227
235
  * 列宽拖动时,每一列都必须要有width,且minWidth/maxWidth不生效。table width会变为"fit-content"。
228
236
  * - 会自动更新props.columns中的with属性
229
237
  */
230
- colResizable?: boolean;
238
+ colResizable?: boolean | ColResizableConfig;
231
239
  /** 可拖动至最小的列宽 */
232
240
  colMinWidth?: number;
233
241
  /**
@@ -281,7 +289,7 @@ export type StkProps = {
281
289
  expandConfig?: {
282
290
  height?: number;
283
291
  };
284
- /** 列拖动配置 */
292
+ /** 行拖动配置 */
285
293
  dragRowConfig?: {
286
294
  mode?: 'none' | 'insert' | 'swap';
287
295
  };
@@ -1,4 +1,4 @@
1
- import { AutoRowHeightConfig, DragRowConfig, ExpandConfig, HeaderDragConfig, HighlightConfig, Order, PrivateRowDT, SeqConfig, SortConfig, SortOption, StkTableColumn, UniqKeyProp } from './types/index';
1
+ import { AutoRowHeightConfig, DragRowConfig, ExpandConfig, HeaderDragConfig, HighlightConfig, Order, PrivateRowDT, SeqConfig, SortConfig, SortOption, StkTableColumn, UniqKeyProp, ColResizableConfig } from './types/index';
2
2
  /** Generic stands for DataType */
3
3
  type DT = any & PrivateRowDT;
4
4
  /**
@@ -26,6 +26,7 @@ declare function setSelectedCell(row?: DT, col?: StkTableColumn<DT>, option?: {
26
26
  * @param option.sort 是否触发排序-默认true
27
27
  * @param option.silent 是否禁止触发回调-默认true
28
28
  * @param option.force 是否触发排序-默认true
29
+ * @return 表格数据
29
30
  */
30
31
  declare function setSorter(colKey: string, order: Order, option?: {
31
32
  sortOption?: SortOption<DT>;
@@ -42,7 +43,10 @@ declare function resetSorter(): void;
42
43
  declare function scrollTo(top?: number | null, left?: number | null): void;
43
44
  /** get current table data */
44
45
  declare function getTableData(): any[];
45
- /** get current sort info */
46
+ /**
47
+ * get current sort info
48
+ * @return {{key:string,order:Order}[]}
49
+ */
46
50
  declare function getSortColumns(): {
47
51
  key: string | number | symbol | undefined;
48
52
  order: "desc" | "asc";
@@ -138,7 +142,7 @@ declare const _default: __VLS_WithTemplateSlots<import('vue').DefineComponent<{
138
142
  * 列宽拖动时,每一列都必须要有width,且minWidth/maxWidth不生效。table width会变为"fit-content"。
139
143
  * - 会自动更新props.columns中的with属性
140
144
  */
141
- colResizable?: boolean | undefined;
145
+ colResizable?: boolean | ColResizableConfig<any> | undefined;
142
146
  /** 可拖动至最小的列宽 */
143
147
  colMinWidth?: number | undefined;
144
148
  /**
@@ -169,7 +173,7 @@ declare const _default: __VLS_WithTemplateSlots<import('vue').DefineComponent<{
169
173
  seqConfig?: SeqConfig | undefined;
170
174
  /** 展开行配置 */
171
175
  expandConfig?: ExpandConfig | undefined;
172
- /** 列拖动配置 */
176
+ /** 行拖动配置 */
173
177
  dragRowConfig?: DragRowConfig | undefined;
174
178
  /**
175
179
  * 固定头,固定列实现方式。(非响应式)
@@ -383,7 +387,7 @@ declare const _default: __VLS_WithTemplateSlots<import('vue').DefineComponent<{
383
387
  * 列宽拖动时,每一列都必须要有width,且minWidth/maxWidth不生效。table width会变为"fit-content"。
384
388
  * - 会自动更新props.columns中的with属性
385
389
  */
386
- colResizable?: boolean | undefined;
390
+ colResizable?: boolean | ColResizableConfig<any> | undefined;
387
391
  /** 可拖动至最小的列宽 */
388
392
  colMinWidth?: number | undefined;
389
393
  /**
@@ -414,7 +418,7 @@ declare const _default: __VLS_WithTemplateSlots<import('vue').DefineComponent<{
414
418
  seqConfig?: SeqConfig | undefined;
415
419
  /** 展开行配置 */
416
420
  expandConfig?: ExpandConfig | undefined;
417
- /** 列拖动配置 */
421
+ /** 行拖动配置 */
418
422
  dragRowConfig?: DragRowConfig | undefined;
419
423
  /**
420
424
  * 固定头,固定列实现方式。(非响应式)
@@ -471,7 +475,7 @@ declare const _default: __VLS_WithTemplateSlots<import('vue').DefineComponent<{
471
475
  selectedCellRevokable: boolean;
472
476
  headerDrag: HeaderDragConfig;
473
477
  rowClassName: (row: any, i: number) => string;
474
- colResizable: boolean;
478
+ colResizable: boolean | ColResizableConfig<any>;
475
479
  colMinWidth: number;
476
480
  bordered: boolean | "h" | "v" | "body-v";
477
481
  autoResize: boolean | (() => void);
@@ -492,6 +496,7 @@ declare const _default: __VLS_WithTemplateSlots<import('vue').DefineComponent<{
492
496
  col: any;
493
497
  }): any;
494
498
  empty?(_: {}): any;
499
+ customBottom?(_: {}): any;
495
500
  }>;
496
501
  export default _default;
497
502
  type __VLS_WithTemplateSlots<T, S> = T & {
@@ -1,3 +1,3 @@
1
1
  export { default as StkTable } from './StkTable.vue';
2
- export { tableSort, insertToOrderedArray, strCompare } from './utils';
2
+ export { tableSort, insertToOrderedArray, strCompare, binarySearch } from './utils';
3
3
  export type { StkTableColumn } from './types/index';
@@ -185,6 +185,7 @@ export type SeqConfig = {
185
185
  };
186
186
  /** Configuration options for the expand column */
187
187
  export type ExpandConfig = {
188
+ /** worked in virtual mode */
188
189
  height?: number;
189
190
  };
190
191
  export type ExpandedRow = PrivateRowDT & {
@@ -211,4 +212,7 @@ export type AutoRowHeightConfig<DT> = {
211
212
  /** Estimated row height */
212
213
  expectedHeight?: number | ((row: DT, index: number) => number);
213
214
  };
215
+ export type ColResizableConfig<DT extends Record<string, any>> = {
216
+ disabled: (col: StkTableColumn<DT>) => boolean;
217
+ };
214
218
  export {};
@@ -11,6 +11,7 @@ type Params<DT extends Record<string, any>> = {
11
11
  };
12
12
  /** 列宽拖动 */
13
13
  export declare function useColResize<DT extends Record<string, any>>({ tableContainerRef, tableHeaderLast, colResizeIndicatorRef, props, emits, colKeyGen, fixedCols, }: Params<DT>): {
14
+ colResizeOn: ComputedRef<((col: StkTableColumn<DT>) => boolean) | (() => any)>;
14
15
  isColResizing: Ref<boolean, boolean>;
15
16
  onThResizeMouseDown: (e: MouseEvent, col: StkTableColumn<DT>, leftHandle?: boolean) => void;
16
17
  };
@@ -6,14 +6,14 @@ type Params<T extends Record<string, any>> = {
6
6
  colKeyGen: ComputedRef<(col: StkTableColumn<T>) => UniqKey>;
7
7
  getFixedColPosition: ComputedRef<(col: StkTableColumn<T>) => number>;
8
8
  tableHeaders: ShallowRef<StkTableColumn<T>[][]>;
9
- tableHeaderLast: ShallowRef<StkTableColumn<T>[]>;
9
+ tableHeadersForCalc: ShallowRef<StkTableColumn<T>[][]>;
10
10
  tableContainerRef: Ref<HTMLDivElement | undefined>;
11
11
  };
12
12
  /**
13
13
  * 固定列处理
14
14
  * @returns
15
15
  */
16
- export declare function useFixedCol<DT extends Record<string, any>>({ props, colKeyGen, getFixedColPosition, tableHeaders, tableHeaderLast, tableContainerRef, }: Params<DT>): {
16
+ export declare function useFixedCol<DT extends Record<string, any>>({ props, colKeyGen, getFixedColPosition, tableHeaders, tableHeadersForCalc, tableContainerRef, }: Params<DT>): {
17
17
  /** 正在被固定的列 */
18
18
  fixedCols: ShallowRef<StkTableColumn<DT>[], StkTableColumn<DT>[]>;
19
19
  /** 固定列class */
@@ -1,4 +1,6 @@
1
1
  import { Order, SortConfig, SortOption, SortState, StkTableColumn } from '../types';
2
+ /** 是否空值 */
3
+ export declare function isEmptyValue(val: any, isNumber?: boolean): boolean;
2
4
  /**
3
5
  * 对有序数组插入新数据
4
6
  *
@@ -12,6 +14,12 @@ import { Order, SortConfig, SortOption, SortState, StkTableColumn } from '../typ
12
14
  * @return targetArray 的浅拷贝
13
15
  */
14
16
  export declare function insertToOrderedArray<T extends object>(sortState: SortState<T>, newItem: T, targetArray: T[], sortConfig?: SortConfig<T>): T[];
17
+ /**
18
+ * 二分查找
19
+ * @param searchArray 查找数组
20
+ * @param compareCallback 比较函数,返回 -1|0|1
21
+ */
22
+ export declare function binarySearch(searchArray: any[], compareCallback: (midIndex: number) => number): number;
15
23
  /**
16
24
  * 字符串比较
17
25
  * @param a
@@ -19,7 +27,7 @@ export declare function insertToOrderedArray<T extends object>(sortState: SortSt
19
27
  * @param type 类型
20
28
  * @param isNumber 是否是数字类型
21
29
  * @param localeCompare 是否 使用Array.prototyshpe.localeCompare
22
- * @return {-1|0|1}
30
+ * @return {number} <0: a < b, 0: a = b, >0: a > b
23
31
  */
24
32
  export declare function strCompare(a: string, b: string, isNumber: boolean, localeCompare?: boolean): number;
25
33
  /**
@@ -37,5 +45,5 @@ export declare function tableSort<T extends Record<string, any>>(sortOption: Sor
37
45
  /** 多级表头深度 从0开始为一级*/
38
46
  export declare function howDeepTheHeader(arr: StkTableColumn<any>[], level?: number): number;
39
47
  /** number width +px */
40
- export declare function transformWidthToStr(width?: string | number): string;
48
+ export declare function transformWidthToStr(width?: string | number): string | undefined;
41
49
  export declare function getBrowsersVersion(browserName: string): number;
@@ -1,4 +1,4 @@
1
- import { openBlock, createElementBlock, createElementVNode, watch, onMounted, onBeforeUnmount, ref, shallowRef, computed, defineComponent, nextTick, toRaw, normalizeClass, unref, normalizeStyle, createCommentVNode, Fragment, renderList, createBlock, resolveDynamicComponent, toDisplayString, renderSlot, createVNode, createTextVNode } from "vue";
1
+ import { openBlock, createElementBlock, createElementVNode, watch, onMounted, onBeforeUnmount, ref, computed, shallowRef, defineComponent, nextTick, toRaw, normalizeClass, unref, normalizeStyle, createCommentVNode, Fragment, renderList, createBlock, resolveDynamicComponent, toDisplayString, renderSlot, createVNode, createTextVNode } from "vue";
2
2
  import { interpolateRgb } from "d3-interpolate";
3
3
  const _export_sfc = (sfc, props) => {
4
4
  const target = sfc.__vccOpts || sfc;
@@ -48,7 +48,7 @@ function _sfc_render(_ctx, _cache) {
48
48
  }
49
49
  const SortIcon = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["render", _sfc_render]]);
50
50
  function isEmptyValue(val, isNumber) {
51
- let isEmpty = val === null || val === "" || val === void 0;
51
+ let isEmpty = val === null || val === void 0;
52
52
  if (isNumber) {
53
53
  isEmpty = isEmpty || typeof val === "boolean" || Number.isNaN(+val);
54
54
  }
@@ -59,7 +59,6 @@ function insertToOrderedArray(sortState, newItem, targetArray, sortConfig = {})
59
59
  sortConfig = { emptyToBottom: false, ...sortConfig };
60
60
  let { sortType } = sortState;
61
61
  if (!sortType) sortType = typeof newItem[dataIndex];
62
- const isNumber = sortType === "number";
63
62
  const data = [...targetArray];
64
63
  if (!order || !data.length) {
65
64
  data.unshift(newItem);
@@ -68,26 +67,32 @@ function insertToOrderedArray(sortState, newItem, targetArray, sortConfig = {})
68
67
  if (sortConfig.emptyToBottom && isEmptyValue(newItem)) {
69
68
  data.push(newItem);
70
69
  }
71
- let sIndex = 0;
72
- let eIndex = data.length - 1;
70
+ const isNumber = sortType === "number";
73
71
  const targetVal = newItem[dataIndex];
74
- while (sIndex <= eIndex) {
75
- const midIndex = Math.floor((sIndex + eIndex) / 2);
72
+ const sIndex = binarySearch(data, (midIndex) => {
76
73
  const midVal = data[midIndex][dataIndex];
77
74
  const compareRes = strCompare(midVal, targetVal, isNumber, sortConfig.stringLocaleCompare);
75
+ return order === "asc" ? compareRes : -compareRes;
76
+ });
77
+ data.splice(sIndex, 0, newItem);
78
+ return data;
79
+ }
80
+ function binarySearch(searchArray, compareCallback) {
81
+ let sIndex = 0;
82
+ let eIndex = searchArray.length - 1;
83
+ while (sIndex <= eIndex) {
84
+ const midIndex = Math.floor((sIndex + eIndex) / 2);
85
+ const compareRes = compareCallback(midIndex);
78
86
  if (compareRes === 0) {
79
87
  sIndex = midIndex;
80
88
  break;
81
- } else if (compareRes === -1) {
82
- if (order === "asc") sIndex = midIndex + 1;
83
- else eIndex = midIndex - 1;
89
+ } else if (compareRes < 0) {
90
+ sIndex = midIndex + 1;
84
91
  } else {
85
- if (order === "asc") eIndex = midIndex - 1;
86
- else sIndex = midIndex + 1;
92
+ eIndex = midIndex - 1;
87
93
  }
88
94
  }
89
- data.splice(sIndex, 0, newItem);
90
- return data;
95
+ return sIndex;
91
96
  }
92
97
  function strCompare(a, b, isNumber, localeCompare = false) {
93
98
  let _a = a;
@@ -158,6 +163,7 @@ function howDeepTheHeader(arr, level = 0) {
158
163
  return Math.max(...levels);
159
164
  }
160
165
  function transformWidthToStr(width) {
166
+ if (width === void 0) return;
161
167
  const numberWidth = Number(width);
162
168
  return width + (!Number.isNaN(numberWidth) ? "px" : "");
163
169
  }
@@ -303,6 +309,12 @@ function useColResize({
303
309
  startOffsetTableX: 0,
304
310
  revertMoveX: false
305
311
  };
312
+ const colResizeOn = computed(() => {
313
+ if (Object.prototype.toString.call(props.colResizable) === "[object Object]") {
314
+ return (col) => !props.colResizable.disabled(col);
315
+ }
316
+ return () => props.colResizable;
317
+ });
306
318
  onMounted(() => {
307
319
  initColResizeEvent();
308
320
  });
@@ -411,6 +423,7 @@ function useColResize({
411
423
  return column;
412
424
  }
413
425
  return {
426
+ colResizeOn,
414
427
  isColResizing,
415
428
  onThResizeMouseDown
416
429
  };
@@ -420,7 +433,7 @@ function useFixedCol({
420
433
  colKeyGen,
421
434
  getFixedColPosition,
422
435
  tableHeaders,
423
- tableHeaderLast,
436
+ tableHeadersForCalc,
424
437
  tableContainerRef
425
438
  }) {
426
439
  const fixedShadowCols = shallowRef([]);
@@ -443,23 +456,8 @@ function useFixedCol({
443
456
  });
444
457
  return colMap;
445
458
  });
446
- function getColAndParentCols(col, type = 1) {
447
- if (!col) return [];
448
- const colsTemp = [];
449
- let node = { __PARENT__: col };
450
- while (node = node.__PARENT__) {
451
- if (type === 1 && node.fixed) {
452
- colsTemp.push(node);
453
- }
454
- if (type === 2) {
455
- colsTemp.push(node);
456
- }
457
- }
458
- return colsTemp;
459
- }
460
459
  function updateFixedShadow(virtualScrollX) {
461
460
  const fixedColsTemp = [];
462
- const fixedShadowColsTemp = [];
463
461
  let clientWidth, scrollLeft;
464
462
  if (virtualScrollX == null ? void 0 : virtualScrollX.value) {
465
463
  const {
@@ -478,26 +476,29 @@ function useFixedCol({
478
476
  clientWidth = cw;
479
477
  scrollLeft = sl;
480
478
  }
481
- let leftShadowCol = null;
482
- let rightShadowCol = null;
483
- let left = 0;
484
- tableHeaderLast.value.forEach((col) => {
485
- const position = getFixedColPosition.value(col);
486
- if (col.fixed === "left" && position + scrollLeft > left) {
487
- leftShadowCol = col;
488
- fixedColsTemp.push(...getColAndParentCols(col, 2));
489
- }
490
- left += getCalculatedColWidth(col);
491
- if (!rightShadowCol && col.fixed === "right" && scrollLeft + clientWidth - left < position) {
492
- rightShadowCol = col;
493
- }
494
- if (rightShadowCol && col.fixed === "right") {
495
- fixedColsTemp.push(...getColAndParentCols(col, 2));
496
- }
479
+ const leftShadowCol = [];
480
+ const rightShadowCol = [];
481
+ tableHeadersForCalc.value.forEach((row, level) => {
482
+ let left = 0;
483
+ row.forEach((col) => {
484
+ const position = getFixedColPosition.value(col);
485
+ const isFixedLeft = col.fixed === "left";
486
+ const isFixedRight = col.fixed === "right";
487
+ if (isFixedLeft && position + scrollLeft > left) {
488
+ fixedColsTemp.push(col);
489
+ leftShadowCol[level] = col;
490
+ }
491
+ left += getCalculatedColWidth(col);
492
+ if (isFixedRight && scrollLeft + clientWidth - left < position) {
493
+ fixedColsTemp.push(col);
494
+ if (!rightShadowCol[level]) {
495
+ rightShadowCol[level] = col;
496
+ }
497
+ }
498
+ });
497
499
  });
498
500
  if (props.fixedColShadow) {
499
- fixedShadowColsTemp.push(...getColAndParentCols(leftShadowCol), ...getColAndParentCols(rightShadowCol));
500
- fixedShadowCols.value = fixedShadowColsTemp.filter(Boolean);
501
+ fixedShadowCols.value = [...leftShadowCol, ...rightShadowCol].filter(Boolean);
501
502
  }
502
503
  fixedCols.value = fixedColsTemp;
503
504
  }
@@ -633,7 +634,7 @@ function useHighlight({ props, stkTableId, tableContainerRef }) {
633
634
  const { ts, duration } = store;
634
635
  const timeOffset = nowTs - ts;
635
636
  if (nowTs - ts < duration) {
636
- updateRowBgc(rowKeyValue, store, timeOffset);
637
+ updateRowAnimation(rowKeyValue, store, timeOffset);
637
638
  } else {
638
639
  highlightDimRowsAnimation.delete(rowKeyValue);
639
640
  }
@@ -708,7 +709,7 @@ function useHighlight({ props, stkTableId, tableContainerRef }) {
708
709
  const rowKeyValue = rowKeyValues[i];
709
710
  const store = { ts: nowTs, visible: false, keyframe, duration };
710
711
  highlightDimRowsAnimation.set(rowKeyValue, store);
711
- updateRowBgc(rowKeyValue, store, 0);
712
+ updateRowAnimation(rowKeyValue, store, 0);
712
713
  }
713
714
  calcRowHighlightLoop();
714
715
  } else {
@@ -770,7 +771,7 @@ function useHighlight({ props, stkTableId, tableContainerRef }) {
770
771
  }, duration)
771
772
  );
772
773
  }
773
- function updateRowBgc(rowKeyValue, store, timeOffset) {
774
+ function updateRowAnimation(rowKeyValue, store, timeOffset) {
774
775
  const rowEl = document.getElementById(stkTableId + "-" + String(rowKeyValue));
775
776
  const { visible, keyframe, duration: initialDuration } = store;
776
777
  if (!rowEl) {
@@ -916,7 +917,7 @@ function useThDrag({ props, emits, colKeyGen }) {
916
917
  emits("th-drop", th.dataset.colKey);
917
918
  }
918
919
  function handleColOrderChange(dragStartKey, dragEndKey) {
919
- if (!dragStartKey || !dragEndKey) return;
920
+ if (isEmptyValue(dragStartKey) || isEmptyValue(dragEndKey)) return;
920
921
  if (dragConfig.value.mode !== "none") {
921
922
  const columns = [...props.columns];
922
923
  const dragStartIndex = columns.findIndex((col) => colKeyGen.value(col) === dragStartKey);
@@ -1064,6 +1065,9 @@ function useVirtualScroll({
1064
1065
  offsetLeft: 0,
1065
1066
  scrollLeft: 0
1066
1067
  });
1068
+ const hasExpandCol = computed(() => {
1069
+ return tableHeaderLast.value.some((col) => col.type === "expand");
1070
+ });
1067
1071
  const virtual_on = computed(() => {
1068
1072
  return props.virtual && dataSourceCopy.value.length > virtualScroll.value.pageSize * 2;
1069
1073
  });
@@ -1170,7 +1174,8 @@ function useVirtualScroll({
1170
1174
  let expectedHeight;
1171
1175
  if (storedHeight) {
1172
1176
  return storedHeight;
1173
- } else if (expectedHeight = (_a = props.autoRowHeight) == null ? void 0 : _a.expectedHeight) {
1177
+ }
1178
+ if (expectedHeight = (_a = props.autoRowHeight) == null ? void 0 : _a.expectedHeight) {
1174
1179
  if (typeof expectedHeight === "function") {
1175
1180
  return expectedHeight(row);
1176
1181
  } else {
@@ -1179,6 +1184,18 @@ function useVirtualScroll({
1179
1184
  }
1180
1185
  return props.rowHeight || DEFAULT_ROW_HEIGHT;
1181
1186
  };
1187
+ const createGetRowHeightFn = () => {
1188
+ var _a;
1189
+ if (props.autoRowHeight) {
1190
+ return (row) => getAutoRowHeight(row);
1191
+ }
1192
+ if (hasExpandCol.value) {
1193
+ const { rowHeight } = virtualScroll.value;
1194
+ const expandedRowHeight = ((_a = props.expandConfig) == null ? void 0 : _a.height) || rowHeight;
1195
+ return (row) => row.__EXPANDED_ROW__ ? expandedRowHeight : rowHeight;
1196
+ }
1197
+ return () => props.rowHeight || DEFAULT_ROW_HEIGHT;
1198
+ };
1182
1199
  function updateVirtualScrollY(sTop = 0) {
1183
1200
  var _a;
1184
1201
  const { rowHeight, pageSize, scrollTop, startIndex: oldStartIndex, endIndex: oldEndIndex } = virtualScroll.value;
@@ -1186,21 +1203,27 @@ function useVirtualScroll({
1186
1203
  if (!virtual_on.value) {
1187
1204
  return;
1188
1205
  }
1206
+ const dataSourceCopyTemp = dataSourceCopy.value;
1189
1207
  const { autoRowHeight, stripe, optimizeVue2Scroll } = props;
1190
1208
  let startIndex = 0;
1191
1209
  let autoRowHeightTop = 0;
1192
- if (autoRowHeight) {
1193
- (_a = trRef.value) == null ? void 0 : _a.forEach((tr) => {
1194
- const { rowKey } = tr.dataset;
1195
- if (!rowKey || autoRowHeightMap.has(rowKey)) return;
1196
- autoRowHeightMap.set(rowKey, tr.offsetHeight);
1197
- });
1198
- for (let i = 0; i < dataSourceCopy.value.length; i++) {
1199
- const height = getAutoRowHeight(dataSourceCopy.value[i]);
1210
+ let getRowHeight = null;
1211
+ const dataLength = dataSourceCopyTemp.length;
1212
+ if (autoRowHeight || hasExpandCol.value) {
1213
+ if (autoRowHeight) {
1214
+ (_a = trRef.value) == null ? void 0 : _a.forEach((tr) => {
1215
+ const { rowKey } = tr.dataset;
1216
+ if (!rowKey || autoRowHeightMap.has(rowKey)) return;
1217
+ autoRowHeightMap.set(rowKey, tr.offsetHeight);
1218
+ });
1219
+ }
1220
+ getRowHeight = createGetRowHeightFn();
1221
+ for (let i = 0; i < dataLength; i++) {
1222
+ const height = getRowHeight(dataSourceCopyTemp[i]);
1200
1223
  autoRowHeightTop += height;
1201
1224
  if (autoRowHeightTop >= sTop) {
1202
1225
  startIndex = i;
1203
- autoRowHeightTop = autoRowHeightTop - height;
1226
+ autoRowHeightTop -= height;
1204
1227
  break;
1205
1228
  }
1206
1229
  }
@@ -1210,13 +1233,13 @@ function useVirtualScroll({
1210
1233
  let endIndex = startIndex + pageSize;
1211
1234
  if (stripe && startIndex > 0 && startIndex % 2) {
1212
1235
  startIndex -= 1;
1213
- if (autoRowHeight) {
1214
- const height = getAutoRowHeight(dataSourceCopy.value[startIndex]);
1236
+ if (autoRowHeight || hasExpandCol.value) {
1237
+ const height = getRowHeight(dataSourceCopyTemp[startIndex]);
1215
1238
  autoRowHeightTop -= height;
1216
1239
  }
1217
1240
  }
1218
1241
  startIndex = Math.max(0, startIndex);
1219
- endIndex = Math.min(endIndex, dataSourceCopy.value.length);
1242
+ endIndex = Math.min(endIndex, dataLength);
1220
1243
  if (startIndex >= endIndex) {
1221
1244
  startIndex = endIndex - pageSize;
1222
1245
  }
@@ -1224,7 +1247,7 @@ function useVirtualScroll({
1224
1247
  window.clearTimeout(vue2ScrollYTimeout);
1225
1248
  }
1226
1249
  let offsetTop = 0;
1227
- if (autoRowHeight) {
1250
+ if (autoRowHeight || hasExpandCol.value) {
1228
1251
  offsetTop = autoRowHeightTop;
1229
1252
  } else {
1230
1253
  if (oldStartIndex === startIndex && oldEndIndex === endIndex) {
@@ -1473,9 +1496,9 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1473
1496
  getFixedColPosition,
1474
1497
  tableContainerRef,
1475
1498
  tableHeaders,
1476
- tableHeaderLast
1499
+ tableHeadersForCalc
1477
1500
  });
1478
- const { isColResizing, onThResizeMouseDown } = useColResize({
1501
+ const { isColResizing, onThResizeMouseDown, colResizeOn } = useColResize({
1479
1502
  props,
1480
1503
  emits,
1481
1504
  colKeyGen,
@@ -2175,12 +2198,12 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
2175
2198
  col.sorter ? (openBlock(), createElementBlock("span", _hoisted_4, [
2176
2199
  createVNode(SortIcon)
2177
2200
  ])) : createCommentVNode("", true),
2178
- _ctx.colResizable && colIndex > 0 ? (openBlock(), createElementBlock("div", {
2201
+ unref(colResizeOn)(col) && colIndex > 0 ? (openBlock(), createElementBlock("div", {
2179
2202
  key: 4,
2180
2203
  class: "table-header-resizer left",
2181
2204
  onMousedown: (e) => unref(onThResizeMouseDown)(e, col, true)
2182
2205
  }, null, 40, _hoisted_5)) : createCommentVNode("", true),
2183
- _ctx.colResizable ? (openBlock(), createElementBlock("div", {
2206
+ unref(colResizeOn)(col) ? (openBlock(), createElementBlock("div", {
2184
2207
  key: 5,
2185
2208
  class: "table-header-resizer right",
2186
2209
  onMousedown: (e) => unref(onThResizeMouseDown)(e, col)
@@ -2235,7 +2258,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
2235
2258
  "expanded-row": row && row.__EXPANDED_ROW__
2236
2259
  }),
2237
2260
  style: normalizeStyle({
2238
- "--row-height": row && row.__EXPANDED_ROW__ && unref(virtual_on) && ((_a = props.expandConfig) == null ? void 0 : _a.height) && ((_b = props.expandConfig) == null ? void 0 : _b.height) + "px"
2261
+ "--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"
2239
2262
  }),
2240
2263
  onClick: (e) => onRowClick(e, row),
2241
2264
  onDblclick: (e) => onRowDblclick(e, row),
@@ -2325,13 +2348,15 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
2325
2348
  renderSlot(_ctx.$slots, "empty", {}, () => [
2326
2349
  _cache[7] || (_cache[7] = createTextVNode("暂无数据"))
2327
2350
  ])
2328
- ], 2)) : createCommentVNode("", true)
2351
+ ], 2)) : createCommentVNode("", true),
2352
+ renderSlot(_ctx.$slots, "customBottom")
2329
2353
  ], 38);
2330
2354
  };
2331
2355
  }
2332
2356
  });
2333
2357
  export {
2334
2358
  _sfc_main as StkTable,
2359
+ binarySearch,
2335
2360
  insertToOrderedArray,
2336
2361
  strCompare,
2337
2362
  tableSort
package/lib/style.css CHANGED
@@ -38,8 +38,6 @@
38
38
  display:flex;
39
39
  flex-direction:column;
40
40
  box-sizing:border-box;
41
- background-image:linear-gradient(180deg, #e8e8f4 1px, transparent 1px), linear-gradient(270deg, #e8e8f4 1px, transparent 1px), linear-gradient(0deg, #e8e8f4 1px, transparent 1px);
42
- background-image:var(--bg-border-top), var(--bg-border-right), var(--bg-border-bottom);
43
41
  }
44
42
  .stk-table.dark{
45
43
  --th-bgc:#202029;
@@ -63,21 +61,22 @@
63
61
  --drag-handle-hover-color:#5d6064;
64
62
  color:#d1d1e0;
65
63
  }
66
- .stk-table.headless{
64
+ .stk-table.headless.border{
67
65
  border-top:1px solid var(--border-color);
68
66
  background-image:var(--bg-border-right), var(--bg-border-bottom);
69
67
  }
70
68
  .stk-table.col-resizable .stk-table-main{
71
- width:-moz-fit-content !important;
72
- width:fit-content !important;
73
- min-width:-moz-min-content !important;
74
- min-width:min-content !important;
69
+ width:-moz-fit-content;
70
+ width:fit-content;
71
+ min-width:-moz-min-content;
72
+ min-width:min-content;
75
73
  }
76
74
  .stk-table.is-col-resizing th{
77
75
  pointer-events:none;
78
76
  }
79
77
  .stk-table.border{
80
78
  border-left:1px solid var(--border-color);
79
+ background-image:var(--bg-border-top), var(--bg-border-right), var(--bg-border-bottom);
81
80
  }
82
81
  .stk-table.border th,
83
82
  .stk-table.border td{
@@ -104,13 +103,13 @@
104
103
  .stk-table.stripe.vt-on .stk-tbody-main tr:nth-child(odd){
105
104
  background-color:var(--stripe-bgc);
106
105
  }
107
- .stk-table.stripe.row-hover .stk-tbody-main tr:hover{
106
+ .stk-table.stripe.row-hover .stk-table-main .stk-tbody-main tr:hover{
108
107
  background-color:var(--tr-hover-bgc);
109
108
  }
110
- .stk-table.stripe.row-active .stk-tbody-main tr.active{
109
+ .stk-table.stripe.row-active .stk-table-main .stk-tbody-main tr.active{
111
110
  background-color:var(--tr-active-bgc);
112
111
  }
113
- .stk-table.row-hover .stk-tbody-main tr:hover{
112
+ .stk-table.row-hover .stk-table-main .stk-tbody-main tr:hover{
114
113
  background-color:var(--tr-hover-bgc);
115
114
  }
116
115
  .stk-table.row-active .stk-tbody-main tr.active{
@@ -142,6 +141,9 @@
142
141
  max-height:calc(var(--header-row-height) * 1);
143
142
  max-height:calc(var(--header-row-height) * var(--row-span, 1));
144
143
  }
144
+ .stk-table.virtual .table-header-cell-wrapper .table-header-title{
145
+ max-height:inherit;
146
+ }
145
147
  .stk-table.virtual tbody td{
146
148
  height:var(--row-height);
147
149
  }
@@ -258,7 +260,7 @@
258
260
  .stk-table .expand-cell{
259
261
  cursor:pointer;
260
262
  }
261
- .stk-table .expand-cell .table-cell-wrapper.expanded-cell-wrapper::before{
263
+ .stk-table .expand-cell .expanded-cell-wrapper::before{
262
264
  content:'';
263
265
  display:inline-block;
264
266
  margin:0 2px;
@@ -269,7 +271,7 @@
269
271
  border-bottom:4px solid transparent;
270
272
  transition:transform 0.2s ease;
271
273
  }
272
- .stk-table .expand-cell .table-cell-wrapper.expanded-cell-wrapper > span{
274
+ .stk-table .expand-cell .expanded-cell-wrapper > span{
273
275
  margin-left:var(--cell-padding-x);
274
276
  }
275
277
  .stk-table .expand-cell.expanded .table-cell-wrapper::before{