stk-table-vue 0.11.1 → 0.11.2

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.
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * name: stk-table-vue
3
- * version: v0.11.1
3
+ * version: v0.11.2
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/
@@ -18,7 +18,7 @@ export type ScrollbarOptions = {
18
18
  * @param options 滚动条配置选项
19
19
  * @returns 滚动条相关状态和方法
20
20
  */
21
- export declare function useScrollbar(props: any, containerRef: Ref<HTMLDivElement | undefined>, virtualScroll: Ref<VirtualScrollStore>, virtualScrollX: Ref<VirtualScrollXStore>, updateVirtualScrollY: (sTop?: number) => void, scrollbarOptions: Ref<Required<ScrollbarOptions>>): readonly [Ref<{
21
+ export declare function useScrollbar(props: any, containerRef: Ref<HTMLDivElement | undefined>, virtualScroll: Ref<VirtualScrollStore>, virtualScrollX: Ref<VirtualScrollXStore>, updateVirtualScrollY: (sTop?: number) => void, scrollbarOptions: Ref<Required<ScrollbarOptions>>, isExperimentalScrollY: Ref<boolean | undefined>): readonly [Ref<{
22
22
  h: number;
23
23
  w: number;
24
24
  t: number;
@@ -41,7 +41,7 @@ export type VirtualScrollXStore = {
41
41
  * virtual scroll
42
42
  * @returns
43
43
  */
44
- export declare function useVirtualScroll<DT extends Record<string, any>>(props: any, tableContainerRef: Ref<HTMLElement | undefined>, trRef: Ref<HTMLTableRowElement[] | undefined>, dataSourceCopy: ShallowRef<PrivateRowDT[]>, tableHeaderLast: ShallowRef<PrivateStkTableColumn<PrivateRowDT>[]>, tableHeaders: ShallowRef<PrivateStkTableColumn<PrivateRowDT>[][]>, rowKeyGen: RowKeyGen, maxRowSpan: Map<UniqKey, number>, scrollbarOptions: Ref<Required<ScrollbarOptions>>): readonly [Ref<{
44
+ export declare function useVirtualScroll<DT extends Record<string, any>>(props: any, tableContainerRef: Ref<HTMLElement | undefined>, trRef: Ref<HTMLTableRowElement[] | undefined>, dataSourceCopy: ShallowRef<PrivateRowDT[]>, tableHeaderLast: ShallowRef<PrivateStkTableColumn<PrivateRowDT>[]>, tableHeaders: ShallowRef<PrivateStkTableColumn<PrivateRowDT>[][]>, rowKeyGen: RowKeyGen, maxRowSpan: Map<UniqKey, number>, scrollbarOptions: Ref<Required<ScrollbarOptions>>, isExperimentalScrollY: Ref<boolean | undefined>): readonly [Ref<{
45
45
  containerHeight: number;
46
46
  pageSize: number;
47
47
  startIndex: number;
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * name: stk-table-vue
3
- * version: v0.11.1
3
+ * version: v0.11.2
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/
@@ -365,6 +365,42 @@ function useAreaSelection(props, emits, tableContainerRef, dataSourceCopy, table
365
365
  }
366
366
  return map;
367
367
  });
368
+ const getFixedColWidths = computed(() => {
369
+ const cols = tableHeaderLast.value;
370
+ const leftAccumulated = [];
371
+ const rightAccumulated = [];
372
+ let leftSum = 0;
373
+ let rightSum = 0;
374
+ for (let i = 0, j = cols.length - 1; i < cols.length; i++, j--) {
375
+ const leftCol = cols[i];
376
+ const rightCol = cols[j];
377
+ if ((leftCol == null ? void 0 : leftCol.fixed) === "left") {
378
+ leftSum += getCalculatedColWidth(leftCol);
379
+ leftAccumulated.push({ i, w: leftSum });
380
+ }
381
+ if ((rightCol == null ? void 0 : rightCol.fixed) === "right") {
382
+ rightSum += getCalculatedColWidth(rightCol);
383
+ rightAccumulated.unshift({ i: j, w: rightSum });
384
+ }
385
+ }
386
+ return (colIndex) => {
387
+ let leftFixedWidth = 0;
388
+ for (let i = leftAccumulated.length - 1; i >= 0; i--) {
389
+ if (leftAccumulated[i].i < colIndex) {
390
+ leftFixedWidth = leftAccumulated[i].w;
391
+ break;
392
+ }
393
+ }
394
+ let rightFixedWidth = 0;
395
+ for (let i = rightAccumulated.length - 1; i >= 0; i--) {
396
+ if (rightAccumulated[i].i > colIndex) {
397
+ rightFixedWidth = rightAccumulated[i].w;
398
+ break;
399
+ }
400
+ }
401
+ return [leftFixedWidth, rightFixedWidth];
402
+ };
403
+ });
368
404
  const selectedCellKeys = computed(() => {
369
405
  const range = selectionRange.value;
370
406
  if (!range) return /* @__PURE__ */ new Set();
@@ -764,11 +800,12 @@ function useAreaSelection(props, emits, tableContainerRef, dataSourceCopy, table
764
800
  const targetColRight = targetColLeft + targetColWidth;
765
801
  const visibleLeft = container.scrollLeft;
766
802
  const visibleRight = visibleLeft + vsx.containerWidth;
803
+ const [leftFixedWidth, rightFixedWidth] = getFixedColWidths.value(colIndex);
767
804
  let newScrollLeft = null;
768
- if (targetColLeft < visibleLeft) {
769
- newScrollLeft = targetColLeft;
770
- } else if (targetColRight > visibleRight) {
771
- newScrollLeft = targetColRight - vsx.containerWidth;
805
+ if (targetColLeft < visibleLeft + leftFixedWidth) {
806
+ newScrollLeft = targetColLeft - leftFixedWidth;
807
+ } else if (targetColRight > visibleRight - rightFixedWidth) {
808
+ newScrollLeft = targetColRight - vsx.containerWidth + rightFixedWidth;
772
809
  }
773
810
  if (newScrollTop !== null || newScrollLeft !== null) {
774
811
  scrollTo(newScrollTop, newScrollLeft);
@@ -1586,7 +1623,7 @@ function useRowExpand(emits, dataSourceCopy, rowKeyGen) {
1586
1623
  }
1587
1624
  return [toggleExpandRow, setRowExpand];
1588
1625
  }
1589
- function useScrollbar(props, containerRef, virtualScroll, virtualScrollX, updateVirtualScrollY, scrollbarOptions) {
1626
+ function useScrollbar(props, containerRef, virtualScroll, virtualScrollX, updateVirtualScrollY, scrollbarOptions, isExperimentalScrollY) {
1590
1627
  const showScrollbar = ref({ x: false, y: false });
1591
1628
  const scrollbar = ref({ h: 0, w: 0, t: 0, l: 0 });
1592
1629
  let isDraggingVertical = false;
@@ -1650,7 +1687,6 @@ function useScrollbar(props, containerRef, virtualScroll, virtualScrollX, update
1650
1687
  document.addEventListener("touchend", onDragEnd);
1651
1688
  }
1652
1689
  function onVerticalDrag(e) {
1653
- var _a;
1654
1690
  if (!isDraggingVertical) return;
1655
1691
  e.preventDefault();
1656
1692
  const clientY = e instanceof MouseEvent ? e.clientY : e.touches[0].clientY;
@@ -1659,7 +1695,7 @@ function useScrollbar(props, containerRef, virtualScroll, virtualScrollX, update
1659
1695
  const scrollRange = scrollHeight - containerHeight;
1660
1696
  const trackRange = containerHeight - scrollbar.value.h;
1661
1697
  const scrollDelta = deltaY / trackRange * scrollRange;
1662
- if ((_a = props.experimental) == null ? void 0 : _a.scrollY) {
1698
+ if (isExperimentalScrollY.value) {
1663
1699
  const ratio = containerHeight / scrollHeight;
1664
1700
  const top = Math.round((dragStartTop + scrollDelta) * ratio);
1665
1701
  const maxTop = containerHeight - scrollbar.value.h;
@@ -2106,7 +2142,7 @@ function useTree(props, dataSourceCopy, rowKeyGen, emits) {
2106
2142
  return [toggleTreeNode, setTreeExpand, flatTreeData];
2107
2143
  }
2108
2144
  const VUE2_SCROLL_TIMEOUT_MS = 200;
2109
- function useVirtualScroll(props, tableContainerRef, trRef, dataSourceCopy, tableHeaderLast, tableHeaders, rowKeyGen, maxRowSpan, scrollbarOptions) {
2145
+ function useVirtualScroll(props, tableContainerRef, trRef, dataSourceCopy, tableHeaderLast, tableHeaders, rowKeyGen, maxRowSpan, scrollbarOptions, isExperimentalScrollY) {
2110
2146
  const tableHeaderHeight = computed(() => props.headerRowHeight * tableHeaders.value.length);
2111
2147
  const virtualScroll = ref({
2112
2148
  containerHeight: 0,
@@ -2266,7 +2302,6 @@ function useVirtualScroll(props, tableContainerRef, trRef, dataSourceCopy, table
2266
2302
  }
2267
2303
  }
2268
2304
  function updateVirtualScrollY(sTop = 0) {
2269
- var _a;
2270
2305
  const { pageSize, scrollTop, startIndex: oldStartIndex, endIndex: oldEndIndex, containerHeight } = virtualScroll.value;
2271
2306
  const dataSourceCopyTemp = dataSourceCopy.value;
2272
2307
  const dataLength = dataSourceCopyTemp.length;
@@ -2276,7 +2311,7 @@ function useVirtualScroll(props, tableContainerRef, trRef, dataSourceCopy, table
2276
2311
  const { enabled: scrollbarEnable } = scrollbarOptions.value;
2277
2312
  if (scrollbarEnable) {
2278
2313
  vsValue.scrollHeight = scrollHeight;
2279
- if ((_a = props.experimental) == null ? void 0 : _a.scrollY) {
2314
+ if (isExperimentalScrollY.value) {
2280
2315
  let maxTop;
2281
2316
  sTop = sTop < 0 ? 0 : sTop < (maxTop = scrollHeight - containerHeight) ? sTop : maxTop;
2282
2317
  vsValue.translateY = props.scrollRowByRow ? 0 : -(sTop % rowHeight);
@@ -2647,6 +2682,13 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
2647
2682
  height: 8,
2648
2683
  ...typeof props.scrollbar === "boolean" ? { enabled: props.scrollbar } : props.scrollbar
2649
2684
  }));
2685
+ const isExperimentalScrollY = computed(() => {
2686
+ var _a, _b;
2687
+ if (((_a = scrollbarOptions.value) == null ? void 0 : _a.enabled) && props.scrollRowByRow) {
2688
+ return true;
2689
+ }
2690
+ return (_b = props.experimental) == null ? void 0 : _b.scrollY;
2691
+ });
2650
2692
  const rowKeyGenCache = /* @__PURE__ */ new WeakMap();
2651
2693
  const [isSRBRActive] = useScrollRowByRow(props, tableContainerRef);
2652
2694
  const [onThDragStart, onThDragOver, onThDrop, isHeaderDraggable] = useThDrag(props, emits, colKeyGen);
@@ -2669,7 +2711,18 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
2669
2711
  updateVirtualScrollX,
2670
2712
  setAutoHeight,
2671
2713
  clearAllAutoHeight
2672
- ] = useVirtualScroll(props, tableContainerRef, trRef, dataSourceCopy, tableHeaderLast, tableHeaders, rowKeyGen, maxRowSpan, scrollbarOptions);
2714
+ ] = useVirtualScroll(
2715
+ props,
2716
+ tableContainerRef,
2717
+ trRef,
2718
+ dataSourceCopy,
2719
+ tableHeaderLast,
2720
+ tableHeaders,
2721
+ rowKeyGen,
2722
+ maxRowSpan,
2723
+ scrollbarOptions,
2724
+ isExperimentalScrollY
2725
+ );
2673
2726
  const rafUpdateVirtualScrollYForWheel = rafThrottle((scrollTop) => {
2674
2727
  updateVirtualScrollY(scrollTop);
2675
2728
  });
@@ -2679,7 +2732,8 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
2679
2732
  virtualScroll,
2680
2733
  virtualScrollX,
2681
2734
  updateVirtualScrollY,
2682
- scrollbarOptions
2735
+ scrollbarOptions,
2736
+ isExperimentalScrollY
2683
2737
  );
2684
2738
  const [hiddenCellMap, mergeCellsWrapper, hoverMergedCells, updateHoverMergedCells, activeMergedCells, updateActiveMergedCells] = useMergeCells(
2685
2739
  rowActiveProp,
@@ -3151,7 +3205,6 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
3151
3205
  }
3152
3206
  const [isWheeling, setIsWheeling] = useWheeling();
3153
3207
  function onTableWheel(e) {
3154
- var _a;
3155
3208
  if (props.smoothScroll) return;
3156
3209
  if (isColResizing.value) {
3157
3210
  e.stopPropagation();
@@ -3169,7 +3222,7 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
3169
3222
  if (isWheeling()) {
3170
3223
  e.preventDefault();
3171
3224
  }
3172
- if ((_a = props.experimental) == null ? void 0 : _a.scrollY) {
3225
+ if (isExperimentalScrollY.value) {
3173
3226
  rafUpdateVirtualScrollYForWheel(scrollTop + deltaY);
3174
3227
  updateCustomScrollbar();
3175
3228
  } else {
@@ -3487,7 +3540,6 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
3487
3540
  setFilter
3488
3541
  });
3489
3542
  return (_ctx, _cache) => {
3490
- var _a, _b, _c, _d;
3491
3543
  return openBlock(), createElementBlock("div", {
3492
3544
  ref_key: "tableContainerRef",
3493
3545
  ref: tableContainerRef,
@@ -3514,7 +3566,7 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
3514
3566
  "scroll-row-by-row": unref(isSRBRActive),
3515
3567
  "scrollbar-on": scrollbarOptions.value.enabled,
3516
3568
  "is-area-selecting": unref(isAreaSelecting),
3517
- "exp-scroll-y": (_a = __props.experimental) == null ? void 0 : _a.scrollY
3569
+ "exp-scroll-y": isExperimentalScrollY.value
3518
3570
  }]),
3519
3571
  tabindex: props.areaSelection ? 0 : void 0,
3520
3572
  style: normalizeStyle({
@@ -3529,7 +3581,7 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
3529
3581
  onScroll: onTableScroll,
3530
3582
  onWheel: onTableWheel
3531
3583
  }, [
3532
- !((_b = __props.experimental) == null ? void 0 : _b.scrollY) && SRBRTotalHeight.value ? (openBlock(), createElementBlock("div", {
3584
+ !isExperimentalScrollY.value && SRBRTotalHeight.value ? (openBlock(), createElementBlock("div", {
3533
3585
  key: 0,
3534
3586
  class: "row-by-row-table-height",
3535
3587
  style: normalizeStyle(`height: ${SRBRTotalHeight.value}px`)
@@ -3656,7 +3708,7 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
3656
3708
  onMousedown: onCellMouseDown,
3657
3709
  onMouseover: onCellMouseOver
3658
3710
  }, [
3659
- !((_c = __props.experimental) == null ? void 0 : _c.scrollY) && unref(virtual_on) && !unref(isSRBRActive) ? (openBlock(), createElementBlock("tr", {
3711
+ !isExperimentalScrollY.value && unref(virtual_on) && !unref(isSRBRActive) ? (openBlock(), createElementBlock("tr", {
3660
3712
  key: 0,
3661
3713
  style: normalizeStyle(`height:${unref(virtualScroll).offsetTop}px`),
3662
3714
  class: "padding-top-tr"
@@ -3689,16 +3741,16 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
3689
3741
  row: row.__EXP_R__,
3690
3742
  col: row.__EXP_C__
3691
3743
  }, () => {
3692
- var _a2;
3744
+ var _a;
3693
3745
  return [
3694
- createTextVNode(toDisplayString(((_a2 = row.__EXP_R__) == null ? void 0 : _a2[row.__EXP_C__.dataIndex]) ?? ""), 1)
3746
+ createTextVNode(toDisplayString(((_a = row.__EXP_R__) == null ? void 0 : _a[row.__EXP_C__.dataIndex]) ?? ""), 1)
3695
3747
  ];
3696
3748
  })
3697
3749
  ])
3698
3750
  ], 8, _hoisted_16)) : (openBlock(true), createElementBlock(Fragment, { key: 2 }, renderList(unref(virtualX_columnPart), (col, colIndex) => {
3699
- var _a2;
3751
+ var _a;
3700
3752
  return openBlock(), createElementBlock(Fragment, null, [
3701
- !unref(hiddenCellMap) || !((_a2 = unref(hiddenCellMap)[rowKeyGen(row)]) == null ? void 0 : _a2.has(colKeyGen.value(col))) ? (openBlock(), createElementBlock("td", mergeProps({
3753
+ !unref(hiddenCellMap) || !((_a = unref(hiddenCellMap)[rowKeyGen(row)]) == null ? void 0 : _a.has(colKeyGen.value(col))) ? (openBlock(), createElementBlock("td", mergeProps({
3702
3754
  key: colKeyGen.value(col)
3703
3755
  }, { ref_for: true }, getTDProps(row, col, rowIndex, colIndex), {
3704
3756
  onMouseenter: onCellMouseEnter,
@@ -3756,7 +3808,7 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
3756
3808
  unref(virtualX_on) ? (openBlock(), createElementBlock("td", _hoisted_22)) : createCommentVNode("", true)
3757
3809
  ], 16, _hoisted_14);
3758
3810
  }), 128)),
3759
- !((_d = __props.experimental) == null ? void 0 : _d.scrollY) ? (openBlock(), createElementBlock(Fragment, { key: 1 }, [
3811
+ !isExperimentalScrollY.value ? (openBlock(), createElementBlock(Fragment, { key: 1 }, [
3760
3812
  unref(virtual_on) && !unref(isSRBRActive) ? (openBlock(), createElementBlock("tr", {
3761
3813
  key: 0,
3762
3814
  style: normalizeStyle(`height: ${unref(virtual_offsetBottom)}px`)
package/lib/style.css CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * name: stk-table-vue
3
- * version: v0.11.1
3
+ * version: v0.11.2
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/
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stk-table-vue",
3
- "version": "0.11.1",
3
+ "version": "0.11.2",
4
4
  "description": "High performance 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",
@@ -26,7 +26,7 @@
26
26
  'scroll-row-by-row': isSRBRActive,
27
27
  'scrollbar-on': scrollbarOptions.enabled,
28
28
  'is-area-selecting': isAreaSelecting,
29
- 'exp-scroll-y': experimental?.scrollY,
29
+ 'exp-scroll-y': isExperimentalScrollY,
30
30
  }"
31
31
  :tabindex="props.areaSelection ? 0 : void 0"
32
32
  :style="{
@@ -41,7 +41,7 @@
41
41
  @scroll="onTableScroll"
42
42
  @wheel="onTableWheel"
43
43
  >
44
- <div v-if="!experimental?.scrollY && SRBRTotalHeight" class="row-by-row-table-height" :style="`height: ${SRBRTotalHeight}px`"></div>
44
+ <div v-if="!isExperimentalScrollY && SRBRTotalHeight" class="row-by-row-table-height" :style="`height: ${SRBRTotalHeight}px`"></div>
45
45
 
46
46
  <div v-if="colResizable" ref="colResizeIndicatorRef" class="column-resize-indicator"></div>
47
47
 
@@ -132,7 +132,7 @@
132
132
  @mouseover="onCellMouseOver"
133
133
  >
134
134
  <tr
135
- v-if="!experimental?.scrollY && virtual_on && !isSRBRActive"
135
+ v-if="!isExperimentalScrollY && virtual_on && !isSRBRActive"
136
136
  :style="`height:${virtualScroll.offsetTop}px`"
137
137
  class="padding-top-tr"
138
138
  >
@@ -208,7 +208,7 @@
208
208
  </template>
209
209
  <td v-if="virtualX_on" class="vt-x-right"></td>
210
210
  </tr>
211
- <template v-if="!experimental?.scrollY">
211
+ <template v-if="!isExperimentalScrollY">
212
212
  <tr v-if="virtual_on && !isSRBRActive" :style="`height: ${virtual_offsetBottom}px`"></tr>
213
213
  <tr v-if="SRBRBottomHeight" :style="`height: ${SRBRBottomHeight}px`"></tr>
214
214
  </template>
@@ -798,6 +798,13 @@ const scrollbarOptions = computed(() => ({
798
798
  ...(typeof props.scrollbar === 'boolean' ? { enabled: props.scrollbar } : props.scrollbar),
799
799
  }));
800
800
 
801
+ const isExperimentalScrollY = computed(() => {
802
+ if (scrollbarOptions.value?.enabled && props.scrollRowByRow) {
803
+ return true;
804
+ }
805
+ return props.experimental?.scrollY;
806
+ });
807
+
801
808
  const rowKeyGenCache = new WeakMap();
802
809
 
803
810
  const [isSRBRActive] = useScrollRowByRow(props, tableContainerRef);
@@ -825,7 +832,18 @@ const [
825
832
  updateVirtualScrollX,
826
833
  setAutoHeight,
827
834
  clearAllAutoHeight,
828
- ] = useVirtualScroll(props, tableContainerRef, trRef, dataSourceCopy, tableHeaderLast, tableHeaders, rowKeyGen, maxRowSpan, scrollbarOptions);
835
+ ] = useVirtualScroll(
836
+ props,
837
+ tableContainerRef,
838
+ trRef,
839
+ dataSourceCopy,
840
+ tableHeaderLast,
841
+ tableHeaders,
842
+ rowKeyGen,
843
+ maxRowSpan,
844
+ scrollbarOptions,
845
+ isExperimentalScrollY,
846
+ );
829
847
 
830
848
  /** requestAnimationFrame throttled version of updateVirtualScrollY for smoother wheel scrolling */
831
849
  const rafUpdateVirtualScrollYForWheel = rafThrottle((scrollTop: number) => {
@@ -839,6 +857,7 @@ const [scrollbar, showScrollbar, onVerticalScrollbarMouseDown, onHorizontalScrol
839
857
  virtualScrollX,
840
858
  updateVirtualScrollY,
841
859
  scrollbarOptions,
860
+ isExperimentalScrollY,
842
861
  );
843
862
 
844
863
  const [hiddenCellMap, mergeCellsWrapper, hoverMergedCells, updateHoverMergedCells, activeMergedCells, updateActiveMergedCells] = useMergeCells(
@@ -1438,7 +1457,7 @@ function onTableWheel(e: WheelEvent) {
1438
1457
  if (isWheeling()) {
1439
1458
  e.preventDefault();
1440
1459
  }
1441
- if (props.experimental?.scrollY) {
1460
+ if (isExperimentalScrollY.value) {
1442
1461
  rafUpdateVirtualScrollYForWheel(scrollTop + deltaY);
1443
1462
  updateCustomScrollbar();
1444
1463
  } else {
@@ -72,6 +72,60 @@ export function useAreaSelection<DT extends Record<string, any>>(
72
72
  return map;
73
73
  });
74
74
 
75
+ /**
76
+ * 获取固定列宽度的函数
77
+ * 缓存每个固定列位置的累计宽度,查询时直接返回
78
+ * @param colIndex 目标列索引
79
+ * @returns [leftFixedWidth, rightFixedWidth]
80
+ */
81
+ const getFixedColWidths = computed(() => {
82
+ const cols = tableHeaderLast.value;
83
+ type FixedColWidth = { i: number; /** accumulated width */ w: number };
84
+ // 保存每个固定列位置的累计宽度(包含当前列)
85
+ const leftAccumulated: FixedColWidth[] = [];
86
+ const rightAccumulated: FixedColWidth[] = [];
87
+
88
+ let leftSum = 0;
89
+ let rightSum = 0;
90
+
91
+ for (let i = 0, j = cols.length - 1; i < cols.length; i++, j--) {
92
+ const leftCol = cols[i];
93
+ const rightCol = cols[j];
94
+
95
+ if (leftCol?.fixed === 'left') {
96
+ leftSum += getCalculatedColWidth(leftCol);
97
+ leftAccumulated.push({ i, w: leftSum });
98
+ }
99
+
100
+ if (rightCol?.fixed === 'right') {
101
+ rightSum += getCalculatedColWidth(rightCol);
102
+ rightAccumulated.unshift({ i: j, w: rightSum });
103
+ }
104
+ }
105
+
106
+ return (colIndex: number) => {
107
+ // 查找目标列左侧最近的固定列的累计宽度
108
+ let leftFixedWidth = 0;
109
+ for (let i = leftAccumulated.length - 1; i >= 0; i--) {
110
+ if (leftAccumulated[i].i < colIndex) {
111
+ leftFixedWidth = leftAccumulated[i].w;
112
+ break;
113
+ }
114
+ }
115
+
116
+ // 查找目标列右侧最近的固定列的累计宽度
117
+ let rightFixedWidth = 0;
118
+ for (let i = rightAccumulated.length - 1; i >= 0; i--) {
119
+ if (rightAccumulated[i].i > colIndex) {
120
+ rightFixedWidth = rightAccumulated[i].w;
121
+ break;
122
+ }
123
+ }
124
+
125
+ return [leftFixedWidth, rightFixedWidth] as const;
126
+ };
127
+ });
128
+
75
129
  /** 根据 selectionRange 计算选区内所有 cellKey 的集合 */
76
130
  const selectedCellKeys = computed<Set<string>>(() => {
77
131
  const range = selectionRange.value;
@@ -639,14 +693,15 @@ export function useAreaSelection<DT extends Record<string, any>>(
639
693
  const visibleLeft = container.scrollLeft;
640
694
  const visibleRight = visibleLeft + vsx.containerWidth;
641
695
 
642
- // 计算需要的水平滚动位置
696
+ // 计算固定列的宽度(用于检测遮挡)
697
+ const [leftFixedWidth, rightFixedWidth] = getFixedColWidths.value(colIndex);
643
698
  let newScrollLeft: number | null = null;
644
- if (targetColLeft < visibleLeft) {
645
- // 目标列在可视区域左侧
646
- newScrollLeft = targetColLeft;
647
- } else if (targetColRight > visibleRight) {
648
- // 目标列在可视区域右侧
649
- newScrollLeft = targetColRight - vsx.containerWidth;
699
+ if (targetColLeft < visibleLeft + leftFixedWidth) {
700
+ // 目标列在左侧固定列遮挡区域内,需要向左滚动
701
+ newScrollLeft = targetColLeft - leftFixedWidth;
702
+ } else if (targetColRight > visibleRight - rightFixedWidth) {
703
+ // 目标列在右侧固定列遮挡区域内,需要向右滚动
704
+ newScrollLeft = targetColRight - vsx.containerWidth + rightFixedWidth;
650
705
  }
651
706
 
652
707
  // 执行滚动
@@ -27,6 +27,7 @@ export function useScrollbar(
27
27
  virtualScrollX: Ref<VirtualScrollXStore>,
28
28
  updateVirtualScrollY: (sTop?: number) => void,
29
29
  scrollbarOptions: Ref<Required<ScrollbarOptions>>,
30
+ isExperimentalScrollY: Ref<boolean | undefined>,
30
31
  ) {
31
32
  const showScrollbar = ref({ x: false, y: false });
32
33
  const scrollbar = ref({ h: 0, w: 0, t: 0, l: 0 });
@@ -114,7 +115,7 @@ export function useScrollbar(
114
115
  const trackRange = containerHeight - scrollbar.value.h;
115
116
  const scrollDelta = (deltaY / trackRange) * scrollRange;
116
117
 
117
- if (props.experimental?.scrollY) {
118
+ if (isExperimentalScrollY.value) {
118
119
  const ratio = containerHeight / scrollHeight;
119
120
  const top = Math.round((dragStartTop + scrollDelta) * ratio);
120
121
  const maxTop = containerHeight - scrollbar.value.h;
@@ -57,6 +57,7 @@ export function useVirtualScroll<DT extends Record<string, any>>(
57
57
  rowKeyGen: RowKeyGen,
58
58
  maxRowSpan: Map<UniqKey, number>,
59
59
  scrollbarOptions: Ref<Required<ScrollbarOptions>>,
60
+ isExperimentalScrollY: Ref<boolean | undefined>,
60
61
  ) {
61
62
  const tableHeaderHeight = computed(() => props.headerRowHeight * tableHeaders.value.length);
62
63
 
@@ -276,7 +277,7 @@ export function useVirtualScroll<DT extends Record<string, any>>(
276
277
  const { enabled: scrollbarEnable } = scrollbarOptions.value;
277
278
  if (scrollbarEnable) {
278
279
  vsValue.scrollHeight = scrollHeight;
279
- if (props.experimental?.scrollY) {
280
+ if (isExperimentalScrollY.value) {
280
281
  let maxTop: number;
281
282
  sTop = sTop < 0 ? 0 : sTop < (maxTop = scrollHeight - containerHeight) ? sTop : maxTop;
282
283
  vsValue.translateY = props.scrollRowByRow ? 0 : -(sTop % rowHeight);