@lensui/lens-table 0.1.23 → 0.1.25

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/dist/index.cjs CHANGED
@@ -959,12 +959,21 @@ function paintGrid(options) {
959
959
  return rowIndex >= rowDragPreview.targetIndex && rowIndex < rowDragPreview.sourceIndex ? rowHeight : 0;
960
960
  };
961
961
  const rowBelowDragGap = rowDragPreview ? rowDragPreview.sourceIndex <= rowDragPreview.targetIndex ? rowDragPreview.targetIndex + 1 : rowDragPreview.targetIndex : -1;
962
- if (striped && trailingBlankStart !== null) {
962
+ if (trailingBlankStart !== null) {
963
963
  const rowStart = Math.max(0, range.rowStart);
964
964
  for (let rowIndex = rowStart; rowIndex < range.rowEnd; rowIndex += 1) {
965
- if (rowIndex % 2 === 0 || rowDragPreview?.sourceIndex === rowIndex) continue;
965
+ if (rowDragPreview?.sourceIndex === rowIndex) continue;
966
+ const row = rows[rowIndex];
967
+ const rowKey = getRowKey(row, rowIndex);
968
+ const trailingRowStyle = options.rowStyle?.(row, rowIndex);
969
+ let fill = striped && rowIndex % 2 === 1 ? colors.stripe : null;
970
+ if (trailingRowStyle?.backgroundColor) fill = trailingRowStyle.backgroundColor;
971
+ if (selectedRowKeys.has(rowKey)) fill = colors.axisSelectionFill;
972
+ if (hoveredRowIndex === rowIndex) fill = colors.rowHoverFill;
973
+ if (highlightInsertedRows && insertedRowKeys.has(rowKey)) fill = colors.insertedFill;
974
+ if (!fill) continue;
966
975
  const y = bodyTop + rowIndex * rowHeight - scrollTop + getRowDragOffset(rowIndex);
967
- ctx.fillStyle = colors.stripe;
976
+ ctx.fillStyle = fill;
968
977
  ctx.fillRect(trailingBlankStart, y, width - trailingBlankStart, rowHeight);
969
978
  }
970
979
  }
@@ -1156,7 +1165,7 @@ function paintGrid(options) {
1156
1165
  ctx.font = createCellFont(bodyFontSize);
1157
1166
  ctx.textBaseline = "alphabetic";
1158
1167
  ctx.textAlign = column.align === "right" ? "right" : column.align === "center" ? "center" : "left";
1159
- ctx.fillText(label, textX, y + cellHeight / 2 + cellBaselineOffset);
1168
+ ctx.fillText(ellipsizeText(ctx, label, Math.max(0, cellWidth - padding * 2)), textX, y + cellHeight / 2 + cellBaselineOffset);
1160
1169
  ctx.restore();
1161
1170
  }
1162
1171
  }
@@ -2862,6 +2871,10 @@ function TableInner({
2862
2871
  if (columns[columnIndex].fixed === "right") return viewport.width - (rightFixedOffsets.get(columnIndex) ?? 0) - metric.width;
2863
2872
  return getScrollableColumnLeft(columnIndex) - scrollRef.current.left;
2864
2873
  }, [columns, getScrollableColumnLeft, leftFixedOffsets, metrics, rightFixedOffsets, viewport.width]);
2874
+ const trailingColumnBorderLeft = (0, import_react5.useMemo)(() => {
2875
+ const displayedContentRight = columns.reduce((right, _column, columnIndex) => Math.max(right, getDisplayedColumnLeft(columnIndex) + metrics[columnIndex].width), 0);
2876
+ return displayedContentRight > 0 && displayedContentRight < viewport.width ? Math.round(displayedContentRight) - 1 : null;
2877
+ }, [columns, getDisplayedColumnLeft, metrics, scrollPosition.left, viewport.width]);
2865
2878
  const getHeaderLevelAtY = (0, import_react5.useCallback)((localY, headerY) => {
2866
2879
  const y = localY - headerY;
2867
2880
  for (let level = 0; level < headerRowHeights.length; level += 1) {
@@ -3581,6 +3594,8 @@ function TableInner({
3581
3594
  columnDragRef.current = null;
3582
3595
  setResizeGuideX(null);
3583
3596
  setResizeGuideTop(0);
3597
+ document.documentElement.classList.remove("rvg-is-dragging");
3598
+ event.currentTarget.style.cursor = "default";
3584
3599
  }, []);
3585
3600
  const clearColumnOrderPointerDrag = (0, import_react5.useCallback)((canvas) => {
3586
3601
  columnOrderDragRef.current = null;
@@ -3807,6 +3822,30 @@ function TableInner({
3807
3822
  const textTop = rowTop + 8;
3808
3823
  return localX >= textLeft - 4 && localX <= textLeft + textWidth + 4 && localY >= textTop - 2 && localY <= textTop + 18;
3809
3824
  }, [columnDraggable, fixedHeader, getHeaderCellLeft, getHeaderCellWidth, headerActionSlotWidth, headerRowOffsets]);
3825
+ const locateCustomHeaderTooltip = (0, import_react5.useCallback)((clientX, clientY, columnIndex) => {
3826
+ const root = rootRef.current;
3827
+ const canvas = canvasRef.current;
3828
+ if (!root || !canvas || columnIndex < 0) return null;
3829
+ const canvasRect = canvas.getBoundingClientRect();
3830
+ const targets = root.querySelectorAll(".rvg-header-title [data-rvg-tooltip]");
3831
+ for (const target of targets) {
3832
+ const rect = target.getBoundingClientRect();
3833
+ if (clientX < rect.left || clientX > rect.right || clientY < rect.top || clientY > rect.bottom) continue;
3834
+ const label = target.dataset.rvgTooltip?.trim();
3835
+ if (!label) return null;
3836
+ const rawLeft = rect.left - canvasRect.left;
3837
+ return {
3838
+ key: `content:${columnIndex}:${label}:${Math.round(rawLeft)}:${Math.round(rect.top - canvasRect.top)}`,
3839
+ columnIndex,
3840
+ action: "content",
3841
+ left: Math.max(8, Math.min(rawLeft, Math.max(8, viewport.width - 328))),
3842
+ top: rect.bottom - canvasRect.top + 4,
3843
+ label,
3844
+ placement: "below"
3845
+ };
3846
+ }
3847
+ return null;
3848
+ }, [viewport.width]);
3810
3849
  const headerTooltip = (() => {
3811
3850
  if (!visibleHeaderTooltip) return null;
3812
3851
  return visibleHeaderTooltip;
@@ -4132,17 +4171,19 @@ function TableInner({
4132
4171
  if (column.renderHeader) {
4133
4172
  const visibleActions = getVisibleHeaderActions(column, metrics[columnIndex].width, columnDraggable, measureHeaderTitleWidth(columnIndex), headerActionSlotWidth);
4134
4173
  const actionWidth = (Number(visibleActions.drag) + Number(visibleActions.filter) + Number(visibleActions.sort)) * headerActionSlotWidth;
4174
+ const isHeaderHovered = hoveredHeaderColumnIndex === columnIndex;
4135
4175
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4136
4176
  "div",
4137
4177
  {
4138
- className: `rvg-header-title is-custom${isAxisSelected ? " is-axis-selected" : ""}${isDropTarget ? " is-drop-target" : ""}`,
4178
+ className: `rvg-header-title is-custom${isHeaderHovered ? " is-header-hovered" : ""}${isAxisSelected ? " is-axis-selected" : ""}${isDropTarget ? " is-drop-target" : ""}`,
4139
4179
  "data-level": headerDepth - 1,
4140
4180
  "data-measure-key": column.key,
4141
4181
  style: {
4142
4182
  left,
4143
4183
  top: leafTop,
4144
- width: Math.max(0, metrics[columnIndex].width - actionWidth),
4184
+ width: metrics[columnIndex].width,
4145
4185
  height: headerLeafHeight,
4186
+ "--rvg-header-action-width": `${actionWidth}px`,
4146
4187
  justifyContent: column.align === "right" ? "flex-end" : column.align === "center" ? "center" : "flex-start",
4147
4188
  textAlign: column.align === "right" ? "right" : column.align === "center" ? "center" : "left"
4148
4189
  },
@@ -4515,16 +4556,17 @@ function TableInner({
4515
4556
  const hoveredAction = inLeafHeader ? locateHeaderAction(event.clientX, columnIndex) : null;
4516
4557
  const hoveredDragHandle = Boolean(hoveredHeaderCell && locateHeaderCellDragHandle(event.clientX, hoveredHeaderCell));
4517
4558
  const hoveredDragColumnIndex = hoveredHeaderCell?.startIndex ?? columnIndex;
4518
- const hoveredTitle = inHeader && !hoveredAction && !hoveredDragHandle && hoveredHeaderCell && Boolean(hoveredHeaderCell.column.title) && isPointerOnHeaderTitle(event.clientX, event.clientY, hoveredHeaderCell) && (tooltipConfig.header || hoveredHeaderCell.leaf && isHeaderTitleTruncated(hoveredHeaderCell.startIndex));
4519
- const nextHover = hoveredAction ? { columnIndex, action: hoveredAction } : hoveredDragHandle ? { columnIndex: hoveredDragColumnIndex, action: "drag" } : hoveredTitle ? { columnIndex: hoveredHeaderCell.startIndex, action: "title" } : null;
4520
- const nextTooltip = hoveredAction && hoveredHeaderCell ? createHeaderTooltip(hoveredAction, columnIndex, hoveredHeaderCell) : hoveredDragHandle && hoveredHeaderCell ? createHeaderTooltip("drag", hoveredDragColumnIndex, hoveredHeaderCell) : hoveredTitle && hoveredHeaderCell ? createHeaderTooltip("title", hoveredHeaderCell.startIndex, hoveredHeaderCell) : null;
4559
+ const hoveredContentTooltip = inHeader && !hoveredAction && !hoveredDragHandle ? locateCustomHeaderTooltip(event.clientX, event.clientY, columnIndex) : null;
4560
+ const hoveredTitle = inHeader && !hoveredAction && !hoveredDragHandle && !hoveredContentTooltip && hoveredHeaderCell && Boolean(hoveredHeaderCell.column.title) && isPointerOnHeaderTitle(event.clientX, event.clientY, hoveredHeaderCell) && (tooltipConfig.header || hoveredHeaderCell.leaf && isHeaderTitleTruncated(hoveredHeaderCell.startIndex));
4561
+ const nextHover = hoveredAction ? { columnIndex, action: hoveredAction } : hoveredDragHandle ? { columnIndex: hoveredDragColumnIndex, action: "drag" } : hoveredContentTooltip ? { columnIndex, action: "content" } : hoveredTitle ? { columnIndex: hoveredHeaderCell.startIndex, action: "title" } : null;
4562
+ const nextTooltip = hoveredAction && hoveredHeaderCell ? createHeaderTooltip(hoveredAction, columnIndex, hoveredHeaderCell) : hoveredDragHandle && hoveredHeaderCell ? createHeaderTooltip("drag", hoveredDragColumnIndex, hoveredHeaderCell) : hoveredContentTooltip ? hoveredContentTooltip : hoveredTitle && hoveredHeaderCell ? createHeaderTooltip("title", hoveredHeaderCell.startIndex, hoveredHeaderCell) : null;
4521
4563
  const previousHover = hoveredHeaderActionRef.current;
4522
4564
  if (previousHover?.columnIndex !== nextHover?.columnIndex || previousHover?.action !== nextHover?.action) {
4523
4565
  hoveredHeaderActionRef.current = nextHover;
4524
4566
  setHoveredHeaderAction(nextHover);
4525
- showHeaderTooltipAfterDelay(nextTooltip);
4526
4567
  scheduleDraw();
4527
4568
  }
4569
+ showHeaderTooltipAfterDelay(nextTooltip);
4528
4570
  if (inHeader) {
4529
4571
  if (hoveredRowIndexRef.current !== null) {
4530
4572
  hoveredRowIndexRef.current = null;
@@ -4576,12 +4618,12 @@ function TableInner({
4576
4618
  if (!isInsideText) {
4577
4619
  showCellTooltipAfterDelay(null);
4578
4620
  } else {
4579
- const placement = textRight + 330 > viewport.width ? "left" : "right";
4621
+ const placement = cellTop + rowHeight + 36 > renderHeight ? "above" : "below";
4580
4622
  const nextTooltip2 = {
4581
4623
  rowIndex: cell.rowIndex,
4582
4624
  columnIndex: cell.columnIndex,
4583
- left: placement === "right" ? textRight + 16 : Math.max(8, textLeft - 16),
4584
- top: cellTop + rowHeight / 2,
4625
+ left: Math.max(8, Math.min(textLeft, Math.max(8, viewport.width - 328))),
4626
+ top: placement === "below" ? cellTop + rowHeight + 4 : cellTop - 4,
4585
4627
  label,
4586
4628
  placement
4587
4629
  };
@@ -4610,6 +4652,8 @@ function TableInner({
4610
4652
  }
4611
4653
  },
4612
4654
  onPointerDown: (event) => {
4655
+ handleColumnPointerDown(event);
4656
+ if (columnDragRef.current) return;
4613
4657
  const headerDragCell = columnDraggable ? locateHeaderCell(event.clientX, event.clientY) : null;
4614
4658
  const columnIndex = locateColumn(event.clientX);
4615
4659
  const rowDragHandle = rowDraggable && columnIndex >= 0 && Boolean(columns[columnIndex].rowDragHandle) && locateRow(event.clientY) >= 0;
@@ -4618,8 +4662,7 @@ function TableInner({
4618
4662
  document.documentElement.classList.add("rvg-is-dragging");
4619
4663
  event.currentTarget.style.cursor = "move";
4620
4664
  }
4621
- handleColumnPointerDown(event);
4622
- if (!columnDragRef.current) handleColumnOrderPointerDown(event);
4665
+ handleColumnOrderPointerDown(event);
4623
4666
  beginRangeDrag(event);
4624
4667
  },
4625
4668
  onPointerMove: (event) => {
@@ -4677,6 +4720,12 @@ function TableInner({
4677
4720
  }
4678
4721
  const cell = locateCell(event.clientX, event.clientY);
4679
4722
  if (!cell) {
4723
+ const localX = event.clientX - rect.left;
4724
+ const trailingRowIndex = trailingColumnBorderLeft !== null && localX > trailingColumnBorderLeft ? locateRow(event.clientY) : -1;
4725
+ if (trailingRowIndex >= 0 && rowSelection) {
4726
+ selectRow(trailingRowIndex, event);
4727
+ return;
4728
+ }
4680
4729
  clickedCellRef.current = null;
4681
4730
  setSelectionRange(null);
4682
4731
  setSelection(null);
@@ -4794,6 +4843,13 @@ function TableInner({
4794
4843
  columns.map((column, index) => column.fixed === "right" ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: renderHeaderIcons(index, viewport.width - (rightFixedOffsets.get(index) ?? 0) - metrics[index].width) }, column.key) : null)
4795
4844
  ] })
4796
4845
  ] }),
4846
+ hasVerticalBorders && trailingColumnBorderLeft !== null && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4847
+ "div",
4848
+ {
4849
+ className: "rvg-trailing-column-border",
4850
+ style: { left: trailingColumnBorderLeft, height: renderHeight }
4851
+ }
4852
+ ),
4797
4853
  headerTooltip && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: `rvg-header-tooltip is-${headerTooltip.placement}`, role: "tooltip", style: { left: headerTooltip.left, top: headerTooltip.top }, children: headerTooltip.label }),
4798
4854
  hoveredCellTooltip && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4799
4855
  "div",
package/dist/index.css CHANGED
@@ -808,6 +808,14 @@
808
808
  background: var(--rvg-color-grid);
809
809
  pointer-events: none;
810
810
  }
811
+ .rvg-trailing-column-border {
812
+ position: absolute;
813
+ z-index: 6;
814
+ top: 0;
815
+ width: 1px;
816
+ background: var(--rvg-color-grid);
817
+ pointer-events: none;
818
+ }
811
819
  .rvg-header-icons {
812
820
  position: absolute;
813
821
  z-index: 2;
@@ -895,7 +903,7 @@
895
903
  .rvg-header-tooltip,
896
904
  .rvg-cell-tooltip {
897
905
  position: absolute;
898
- z-index: 5;
906
+ z-index: 8;
899
907
  max-width: 320px;
900
908
  padding: 4px 7px;
901
909
  transform: translateY(-50%);
@@ -939,6 +947,33 @@
939
947
  right: -4px;
940
948
  border-left: 5px solid var(--rvg-color-tooltip-bg);
941
949
  }
950
+ .rvg-header-tooltip.is-below,
951
+ .rvg-cell-tooltip.is-below {
952
+ transform: none;
953
+ }
954
+ .rvg-header-tooltip.is-below::after,
955
+ .rvg-cell-tooltip.is-below::after {
956
+ top: -4px;
957
+ left: 10px;
958
+ transform: none;
959
+ border-right: 5px solid transparent;
960
+ border-bottom: 5px solid var(--rvg-color-tooltip-bg);
961
+ border-left: 5px solid transparent;
962
+ border-top: 0;
963
+ }
964
+ .rvg-cell-tooltip.is-above {
965
+ transform: translateY(-100%);
966
+ }
967
+ .rvg-cell-tooltip.is-above::after {
968
+ top: auto;
969
+ bottom: -4px;
970
+ left: 10px;
971
+ transform: none;
972
+ border-right: 5px solid transparent;
973
+ border-top: 5px solid var(--rvg-color-tooltip-bg);
974
+ border-bottom: 0;
975
+ border-left: 5px solid transparent;
976
+ }
942
977
  .rvg-cell-tooltip.is-annotation::after {
943
978
  display: none;
944
979
  }
@@ -977,6 +1012,9 @@
977
1012
  pointer-events: none;
978
1013
  background: var(--rvg-color-primary);
979
1014
  }
1015
+ .rvg-column-guide.is-resizing {
1016
+ z-index: 7;
1017
+ }
980
1018
  .rvg-row-guide {
981
1019
  position: absolute;
982
1020
  z-index: 3;
package/dist/index.js CHANGED
@@ -929,12 +929,21 @@ function paintGrid(options) {
929
929
  return rowIndex >= rowDragPreview.targetIndex && rowIndex < rowDragPreview.sourceIndex ? rowHeight : 0;
930
930
  };
931
931
  const rowBelowDragGap = rowDragPreview ? rowDragPreview.sourceIndex <= rowDragPreview.targetIndex ? rowDragPreview.targetIndex + 1 : rowDragPreview.targetIndex : -1;
932
- if (striped && trailingBlankStart !== null) {
932
+ if (trailingBlankStart !== null) {
933
933
  const rowStart = Math.max(0, range.rowStart);
934
934
  for (let rowIndex = rowStart; rowIndex < range.rowEnd; rowIndex += 1) {
935
- if (rowIndex % 2 === 0 || rowDragPreview?.sourceIndex === rowIndex) continue;
935
+ if (rowDragPreview?.sourceIndex === rowIndex) continue;
936
+ const row = rows[rowIndex];
937
+ const rowKey = getRowKey(row, rowIndex);
938
+ const trailingRowStyle = options.rowStyle?.(row, rowIndex);
939
+ let fill = striped && rowIndex % 2 === 1 ? colors.stripe : null;
940
+ if (trailingRowStyle?.backgroundColor) fill = trailingRowStyle.backgroundColor;
941
+ if (selectedRowKeys.has(rowKey)) fill = colors.axisSelectionFill;
942
+ if (hoveredRowIndex === rowIndex) fill = colors.rowHoverFill;
943
+ if (highlightInsertedRows && insertedRowKeys.has(rowKey)) fill = colors.insertedFill;
944
+ if (!fill) continue;
936
945
  const y = bodyTop + rowIndex * rowHeight - scrollTop + getRowDragOffset(rowIndex);
937
- ctx.fillStyle = colors.stripe;
946
+ ctx.fillStyle = fill;
938
947
  ctx.fillRect(trailingBlankStart, y, width - trailingBlankStart, rowHeight);
939
948
  }
940
949
  }
@@ -1126,7 +1135,7 @@ function paintGrid(options) {
1126
1135
  ctx.font = createCellFont(bodyFontSize);
1127
1136
  ctx.textBaseline = "alphabetic";
1128
1137
  ctx.textAlign = column.align === "right" ? "right" : column.align === "center" ? "center" : "left";
1129
- ctx.fillText(label, textX, y + cellHeight / 2 + cellBaselineOffset);
1138
+ ctx.fillText(ellipsizeText(ctx, label, Math.max(0, cellWidth - padding * 2)), textX, y + cellHeight / 2 + cellBaselineOffset);
1130
1139
  ctx.restore();
1131
1140
  }
1132
1141
  }
@@ -2832,6 +2841,10 @@ function TableInner({
2832
2841
  if (columns[columnIndex].fixed === "right") return viewport.width - (rightFixedOffsets.get(columnIndex) ?? 0) - metric.width;
2833
2842
  return getScrollableColumnLeft(columnIndex) - scrollRef.current.left;
2834
2843
  }, [columns, getScrollableColumnLeft, leftFixedOffsets, metrics, rightFixedOffsets, viewport.width]);
2844
+ const trailingColumnBorderLeft = useMemo(() => {
2845
+ const displayedContentRight = columns.reduce((right, _column, columnIndex) => Math.max(right, getDisplayedColumnLeft(columnIndex) + metrics[columnIndex].width), 0);
2846
+ return displayedContentRight > 0 && displayedContentRight < viewport.width ? Math.round(displayedContentRight) - 1 : null;
2847
+ }, [columns, getDisplayedColumnLeft, metrics, scrollPosition.left, viewport.width]);
2835
2848
  const getHeaderLevelAtY = useCallback2((localY, headerY) => {
2836
2849
  const y = localY - headerY;
2837
2850
  for (let level = 0; level < headerRowHeights.length; level += 1) {
@@ -3551,6 +3564,8 @@ function TableInner({
3551
3564
  columnDragRef.current = null;
3552
3565
  setResizeGuideX(null);
3553
3566
  setResizeGuideTop(0);
3567
+ document.documentElement.classList.remove("rvg-is-dragging");
3568
+ event.currentTarget.style.cursor = "default";
3554
3569
  }, []);
3555
3570
  const clearColumnOrderPointerDrag = useCallback2((canvas) => {
3556
3571
  columnOrderDragRef.current = null;
@@ -3777,6 +3792,30 @@ function TableInner({
3777
3792
  const textTop = rowTop + 8;
3778
3793
  return localX >= textLeft - 4 && localX <= textLeft + textWidth + 4 && localY >= textTop - 2 && localY <= textTop + 18;
3779
3794
  }, [columnDraggable, fixedHeader, getHeaderCellLeft, getHeaderCellWidth, headerActionSlotWidth, headerRowOffsets]);
3795
+ const locateCustomHeaderTooltip = useCallback2((clientX, clientY, columnIndex) => {
3796
+ const root = rootRef.current;
3797
+ const canvas = canvasRef.current;
3798
+ if (!root || !canvas || columnIndex < 0) return null;
3799
+ const canvasRect = canvas.getBoundingClientRect();
3800
+ const targets = root.querySelectorAll(".rvg-header-title [data-rvg-tooltip]");
3801
+ for (const target of targets) {
3802
+ const rect = target.getBoundingClientRect();
3803
+ if (clientX < rect.left || clientX > rect.right || clientY < rect.top || clientY > rect.bottom) continue;
3804
+ const label = target.dataset.rvgTooltip?.trim();
3805
+ if (!label) return null;
3806
+ const rawLeft = rect.left - canvasRect.left;
3807
+ return {
3808
+ key: `content:${columnIndex}:${label}:${Math.round(rawLeft)}:${Math.round(rect.top - canvasRect.top)}`,
3809
+ columnIndex,
3810
+ action: "content",
3811
+ left: Math.max(8, Math.min(rawLeft, Math.max(8, viewport.width - 328))),
3812
+ top: rect.bottom - canvasRect.top + 4,
3813
+ label,
3814
+ placement: "below"
3815
+ };
3816
+ }
3817
+ return null;
3818
+ }, [viewport.width]);
3780
3819
  const headerTooltip = (() => {
3781
3820
  if (!visibleHeaderTooltip) return null;
3782
3821
  return visibleHeaderTooltip;
@@ -4102,17 +4141,19 @@ function TableInner({
4102
4141
  if (column.renderHeader) {
4103
4142
  const visibleActions = getVisibleHeaderActions(column, metrics[columnIndex].width, columnDraggable, measureHeaderTitleWidth(columnIndex), headerActionSlotWidth);
4104
4143
  const actionWidth = (Number(visibleActions.drag) + Number(visibleActions.filter) + Number(visibleActions.sort)) * headerActionSlotWidth;
4144
+ const isHeaderHovered = hoveredHeaderColumnIndex === columnIndex;
4105
4145
  return /* @__PURE__ */ jsx7(
4106
4146
  "div",
4107
4147
  {
4108
- className: `rvg-header-title is-custom${isAxisSelected ? " is-axis-selected" : ""}${isDropTarget ? " is-drop-target" : ""}`,
4148
+ className: `rvg-header-title is-custom${isHeaderHovered ? " is-header-hovered" : ""}${isAxisSelected ? " is-axis-selected" : ""}${isDropTarget ? " is-drop-target" : ""}`,
4109
4149
  "data-level": headerDepth - 1,
4110
4150
  "data-measure-key": column.key,
4111
4151
  style: {
4112
4152
  left,
4113
4153
  top: leafTop,
4114
- width: Math.max(0, metrics[columnIndex].width - actionWidth),
4154
+ width: metrics[columnIndex].width,
4115
4155
  height: headerLeafHeight,
4156
+ "--rvg-header-action-width": `${actionWidth}px`,
4116
4157
  justifyContent: column.align === "right" ? "flex-end" : column.align === "center" ? "center" : "flex-start",
4117
4158
  textAlign: column.align === "right" ? "right" : column.align === "center" ? "center" : "left"
4118
4159
  },
@@ -4485,16 +4526,17 @@ function TableInner({
4485
4526
  const hoveredAction = inLeafHeader ? locateHeaderAction(event.clientX, columnIndex) : null;
4486
4527
  const hoveredDragHandle = Boolean(hoveredHeaderCell && locateHeaderCellDragHandle(event.clientX, hoveredHeaderCell));
4487
4528
  const hoveredDragColumnIndex = hoveredHeaderCell?.startIndex ?? columnIndex;
4488
- const hoveredTitle = inHeader && !hoveredAction && !hoveredDragHandle && hoveredHeaderCell && Boolean(hoveredHeaderCell.column.title) && isPointerOnHeaderTitle(event.clientX, event.clientY, hoveredHeaderCell) && (tooltipConfig.header || hoveredHeaderCell.leaf && isHeaderTitleTruncated(hoveredHeaderCell.startIndex));
4489
- const nextHover = hoveredAction ? { columnIndex, action: hoveredAction } : hoveredDragHandle ? { columnIndex: hoveredDragColumnIndex, action: "drag" } : hoveredTitle ? { columnIndex: hoveredHeaderCell.startIndex, action: "title" } : null;
4490
- const nextTooltip = hoveredAction && hoveredHeaderCell ? createHeaderTooltip(hoveredAction, columnIndex, hoveredHeaderCell) : hoveredDragHandle && hoveredHeaderCell ? createHeaderTooltip("drag", hoveredDragColumnIndex, hoveredHeaderCell) : hoveredTitle && hoveredHeaderCell ? createHeaderTooltip("title", hoveredHeaderCell.startIndex, hoveredHeaderCell) : null;
4529
+ const hoveredContentTooltip = inHeader && !hoveredAction && !hoveredDragHandle ? locateCustomHeaderTooltip(event.clientX, event.clientY, columnIndex) : null;
4530
+ const hoveredTitle = inHeader && !hoveredAction && !hoveredDragHandle && !hoveredContentTooltip && hoveredHeaderCell && Boolean(hoveredHeaderCell.column.title) && isPointerOnHeaderTitle(event.clientX, event.clientY, hoveredHeaderCell) && (tooltipConfig.header || hoveredHeaderCell.leaf && isHeaderTitleTruncated(hoveredHeaderCell.startIndex));
4531
+ const nextHover = hoveredAction ? { columnIndex, action: hoveredAction } : hoveredDragHandle ? { columnIndex: hoveredDragColumnIndex, action: "drag" } : hoveredContentTooltip ? { columnIndex, action: "content" } : hoveredTitle ? { columnIndex: hoveredHeaderCell.startIndex, action: "title" } : null;
4532
+ const nextTooltip = hoveredAction && hoveredHeaderCell ? createHeaderTooltip(hoveredAction, columnIndex, hoveredHeaderCell) : hoveredDragHandle && hoveredHeaderCell ? createHeaderTooltip("drag", hoveredDragColumnIndex, hoveredHeaderCell) : hoveredContentTooltip ? hoveredContentTooltip : hoveredTitle && hoveredHeaderCell ? createHeaderTooltip("title", hoveredHeaderCell.startIndex, hoveredHeaderCell) : null;
4491
4533
  const previousHover = hoveredHeaderActionRef.current;
4492
4534
  if (previousHover?.columnIndex !== nextHover?.columnIndex || previousHover?.action !== nextHover?.action) {
4493
4535
  hoveredHeaderActionRef.current = nextHover;
4494
4536
  setHoveredHeaderAction(nextHover);
4495
- showHeaderTooltipAfterDelay(nextTooltip);
4496
4537
  scheduleDraw();
4497
4538
  }
4539
+ showHeaderTooltipAfterDelay(nextTooltip);
4498
4540
  if (inHeader) {
4499
4541
  if (hoveredRowIndexRef.current !== null) {
4500
4542
  hoveredRowIndexRef.current = null;
@@ -4546,12 +4588,12 @@ function TableInner({
4546
4588
  if (!isInsideText) {
4547
4589
  showCellTooltipAfterDelay(null);
4548
4590
  } else {
4549
- const placement = textRight + 330 > viewport.width ? "left" : "right";
4591
+ const placement = cellTop + rowHeight + 36 > renderHeight ? "above" : "below";
4550
4592
  const nextTooltip2 = {
4551
4593
  rowIndex: cell.rowIndex,
4552
4594
  columnIndex: cell.columnIndex,
4553
- left: placement === "right" ? textRight + 16 : Math.max(8, textLeft - 16),
4554
- top: cellTop + rowHeight / 2,
4595
+ left: Math.max(8, Math.min(textLeft, Math.max(8, viewport.width - 328))),
4596
+ top: placement === "below" ? cellTop + rowHeight + 4 : cellTop - 4,
4555
4597
  label,
4556
4598
  placement
4557
4599
  };
@@ -4580,6 +4622,8 @@ function TableInner({
4580
4622
  }
4581
4623
  },
4582
4624
  onPointerDown: (event) => {
4625
+ handleColumnPointerDown(event);
4626
+ if (columnDragRef.current) return;
4583
4627
  const headerDragCell = columnDraggable ? locateHeaderCell(event.clientX, event.clientY) : null;
4584
4628
  const columnIndex = locateColumn(event.clientX);
4585
4629
  const rowDragHandle = rowDraggable && columnIndex >= 0 && Boolean(columns[columnIndex].rowDragHandle) && locateRow(event.clientY) >= 0;
@@ -4588,8 +4632,7 @@ function TableInner({
4588
4632
  document.documentElement.classList.add("rvg-is-dragging");
4589
4633
  event.currentTarget.style.cursor = "move";
4590
4634
  }
4591
- handleColumnPointerDown(event);
4592
- if (!columnDragRef.current) handleColumnOrderPointerDown(event);
4635
+ handleColumnOrderPointerDown(event);
4593
4636
  beginRangeDrag(event);
4594
4637
  },
4595
4638
  onPointerMove: (event) => {
@@ -4647,6 +4690,12 @@ function TableInner({
4647
4690
  }
4648
4691
  const cell = locateCell(event.clientX, event.clientY);
4649
4692
  if (!cell) {
4693
+ const localX = event.clientX - rect.left;
4694
+ const trailingRowIndex = trailingColumnBorderLeft !== null && localX > trailingColumnBorderLeft ? locateRow(event.clientY) : -1;
4695
+ if (trailingRowIndex >= 0 && rowSelection) {
4696
+ selectRow(trailingRowIndex, event);
4697
+ return;
4698
+ }
4650
4699
  clickedCellRef.current = null;
4651
4700
  setSelectionRange(null);
4652
4701
  setSelection(null);
@@ -4764,6 +4813,13 @@ function TableInner({
4764
4813
  columns.map((column, index) => column.fixed === "right" ? /* @__PURE__ */ jsx7("span", { children: renderHeaderIcons(index, viewport.width - (rightFixedOffsets.get(index) ?? 0) - metrics[index].width) }, column.key) : null)
4765
4814
  ] })
4766
4815
  ] }),
4816
+ hasVerticalBorders && trailingColumnBorderLeft !== null && /* @__PURE__ */ jsx7(
4817
+ "div",
4818
+ {
4819
+ className: "rvg-trailing-column-border",
4820
+ style: { left: trailingColumnBorderLeft, height: renderHeight }
4821
+ }
4822
+ ),
4767
4823
  headerTooltip && /* @__PURE__ */ jsx7("div", { className: `rvg-header-tooltip is-${headerTooltip.placement}`, role: "tooltip", style: { left: headerTooltip.left, top: headerTooltip.top }, children: headerTooltip.label }),
4768
4824
  hoveredCellTooltip && /* @__PURE__ */ jsx7(
4769
4825
  "div",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lensui/lens-table",
3
- "version": "0.1.23",
3
+ "version": "0.1.25",
4
4
  "description": "A lightweight, canvas-rendered React table component for LensUI.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",