@lensui/lens-table 0.1.24 → 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
  }
@@ -3585,6 +3594,8 @@ function TableInner({
3585
3594
  columnDragRef.current = null;
3586
3595
  setResizeGuideX(null);
3587
3596
  setResizeGuideTop(0);
3597
+ document.documentElement.classList.remove("rvg-is-dragging");
3598
+ event.currentTarget.style.cursor = "default";
3588
3599
  }, []);
3589
3600
  const clearColumnOrderPointerDrag = (0, import_react5.useCallback)((canvas) => {
3590
3601
  columnOrderDragRef.current = null;
@@ -3811,6 +3822,30 @@ function TableInner({
3811
3822
  const textTop = rowTop + 8;
3812
3823
  return localX >= textLeft - 4 && localX <= textLeft + textWidth + 4 && localY >= textTop - 2 && localY <= textTop + 18;
3813
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]);
3814
3849
  const headerTooltip = (() => {
3815
3850
  if (!visibleHeaderTooltip) return null;
3816
3851
  return visibleHeaderTooltip;
@@ -4136,17 +4171,19 @@ function TableInner({
4136
4171
  if (column.renderHeader) {
4137
4172
  const visibleActions = getVisibleHeaderActions(column, metrics[columnIndex].width, columnDraggable, measureHeaderTitleWidth(columnIndex), headerActionSlotWidth);
4138
4173
  const actionWidth = (Number(visibleActions.drag) + Number(visibleActions.filter) + Number(visibleActions.sort)) * headerActionSlotWidth;
4174
+ const isHeaderHovered = hoveredHeaderColumnIndex === columnIndex;
4139
4175
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4140
4176
  "div",
4141
4177
  {
4142
- 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" : ""}`,
4143
4179
  "data-level": headerDepth - 1,
4144
4180
  "data-measure-key": column.key,
4145
4181
  style: {
4146
4182
  left,
4147
4183
  top: leafTop,
4148
- width: Math.max(0, metrics[columnIndex].width - actionWidth),
4184
+ width: metrics[columnIndex].width,
4149
4185
  height: headerLeafHeight,
4186
+ "--rvg-header-action-width": `${actionWidth}px`,
4150
4187
  justifyContent: column.align === "right" ? "flex-end" : column.align === "center" ? "center" : "flex-start",
4151
4188
  textAlign: column.align === "right" ? "right" : column.align === "center" ? "center" : "left"
4152
4189
  },
@@ -4519,16 +4556,17 @@ function TableInner({
4519
4556
  const hoveredAction = inLeafHeader ? locateHeaderAction(event.clientX, columnIndex) : null;
4520
4557
  const hoveredDragHandle = Boolean(hoveredHeaderCell && locateHeaderCellDragHandle(event.clientX, hoveredHeaderCell));
4521
4558
  const hoveredDragColumnIndex = hoveredHeaderCell?.startIndex ?? columnIndex;
4522
- const hoveredTitle = inHeader && !hoveredAction && !hoveredDragHandle && hoveredHeaderCell && Boolean(hoveredHeaderCell.column.title) && isPointerOnHeaderTitle(event.clientX, event.clientY, hoveredHeaderCell) && (tooltipConfig.header || hoveredHeaderCell.leaf && isHeaderTitleTruncated(hoveredHeaderCell.startIndex));
4523
- const nextHover = hoveredAction ? { columnIndex, action: hoveredAction } : hoveredDragHandle ? { columnIndex: hoveredDragColumnIndex, action: "drag" } : hoveredTitle ? { columnIndex: hoveredHeaderCell.startIndex, action: "title" } : null;
4524
- 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;
4525
4563
  const previousHover = hoveredHeaderActionRef.current;
4526
4564
  if (previousHover?.columnIndex !== nextHover?.columnIndex || previousHover?.action !== nextHover?.action) {
4527
4565
  hoveredHeaderActionRef.current = nextHover;
4528
4566
  setHoveredHeaderAction(nextHover);
4529
- showHeaderTooltipAfterDelay(nextTooltip);
4530
4567
  scheduleDraw();
4531
4568
  }
4569
+ showHeaderTooltipAfterDelay(nextTooltip);
4532
4570
  if (inHeader) {
4533
4571
  if (hoveredRowIndexRef.current !== null) {
4534
4572
  hoveredRowIndexRef.current = null;
@@ -4580,12 +4618,12 @@ function TableInner({
4580
4618
  if (!isInsideText) {
4581
4619
  showCellTooltipAfterDelay(null);
4582
4620
  } else {
4583
- const placement = textRight + 330 > viewport.width ? "left" : "right";
4621
+ const placement = cellTop + rowHeight + 36 > renderHeight ? "above" : "below";
4584
4622
  const nextTooltip2 = {
4585
4623
  rowIndex: cell.rowIndex,
4586
4624
  columnIndex: cell.columnIndex,
4587
- left: placement === "right" ? textRight + 16 : Math.max(8, textLeft - 16),
4588
- 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,
4589
4627
  label,
4590
4628
  placement
4591
4629
  };
@@ -4614,6 +4652,8 @@ function TableInner({
4614
4652
  }
4615
4653
  },
4616
4654
  onPointerDown: (event) => {
4655
+ handleColumnPointerDown(event);
4656
+ if (columnDragRef.current) return;
4617
4657
  const headerDragCell = columnDraggable ? locateHeaderCell(event.clientX, event.clientY) : null;
4618
4658
  const columnIndex = locateColumn(event.clientX);
4619
4659
  const rowDragHandle = rowDraggable && columnIndex >= 0 && Boolean(columns[columnIndex].rowDragHandle) && locateRow(event.clientY) >= 0;
@@ -4622,8 +4662,7 @@ function TableInner({
4622
4662
  document.documentElement.classList.add("rvg-is-dragging");
4623
4663
  event.currentTarget.style.cursor = "move";
4624
4664
  }
4625
- handleColumnPointerDown(event);
4626
- if (!columnDragRef.current) handleColumnOrderPointerDown(event);
4665
+ handleColumnOrderPointerDown(event);
4627
4666
  beginRangeDrag(event);
4628
4667
  },
4629
4668
  onPointerMove: (event) => {
@@ -4681,6 +4720,12 @@ function TableInner({
4681
4720
  }
4682
4721
  const cell = locateCell(event.clientX, event.clientY);
4683
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
+ }
4684
4729
  clickedCellRef.current = null;
4685
4730
  setSelectionRange(null);
4686
4731
  setSelection(null);
package/dist/index.css CHANGED
@@ -903,7 +903,7 @@
903
903
  .rvg-header-tooltip,
904
904
  .rvg-cell-tooltip {
905
905
  position: absolute;
906
- z-index: 5;
906
+ z-index: 8;
907
907
  max-width: 320px;
908
908
  padding: 4px 7px;
909
909
  transform: translateY(-50%);
@@ -947,6 +947,33 @@
947
947
  right: -4px;
948
948
  border-left: 5px solid var(--rvg-color-tooltip-bg);
949
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
+ }
950
977
  .rvg-cell-tooltip.is-annotation::after {
951
978
  display: none;
952
979
  }
@@ -985,6 +1012,9 @@
985
1012
  pointer-events: none;
986
1013
  background: var(--rvg-color-primary);
987
1014
  }
1015
+ .rvg-column-guide.is-resizing {
1016
+ z-index: 7;
1017
+ }
988
1018
  .rvg-row-guide {
989
1019
  position: absolute;
990
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
  }
@@ -3555,6 +3564,8 @@ function TableInner({
3555
3564
  columnDragRef.current = null;
3556
3565
  setResizeGuideX(null);
3557
3566
  setResizeGuideTop(0);
3567
+ document.documentElement.classList.remove("rvg-is-dragging");
3568
+ event.currentTarget.style.cursor = "default";
3558
3569
  }, []);
3559
3570
  const clearColumnOrderPointerDrag = useCallback2((canvas) => {
3560
3571
  columnOrderDragRef.current = null;
@@ -3781,6 +3792,30 @@ function TableInner({
3781
3792
  const textTop = rowTop + 8;
3782
3793
  return localX >= textLeft - 4 && localX <= textLeft + textWidth + 4 && localY >= textTop - 2 && localY <= textTop + 18;
3783
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]);
3784
3819
  const headerTooltip = (() => {
3785
3820
  if (!visibleHeaderTooltip) return null;
3786
3821
  return visibleHeaderTooltip;
@@ -4106,17 +4141,19 @@ function TableInner({
4106
4141
  if (column.renderHeader) {
4107
4142
  const visibleActions = getVisibleHeaderActions(column, metrics[columnIndex].width, columnDraggable, measureHeaderTitleWidth(columnIndex), headerActionSlotWidth);
4108
4143
  const actionWidth = (Number(visibleActions.drag) + Number(visibleActions.filter) + Number(visibleActions.sort)) * headerActionSlotWidth;
4144
+ const isHeaderHovered = hoveredHeaderColumnIndex === columnIndex;
4109
4145
  return /* @__PURE__ */ jsx7(
4110
4146
  "div",
4111
4147
  {
4112
- 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" : ""}`,
4113
4149
  "data-level": headerDepth - 1,
4114
4150
  "data-measure-key": column.key,
4115
4151
  style: {
4116
4152
  left,
4117
4153
  top: leafTop,
4118
- width: Math.max(0, metrics[columnIndex].width - actionWidth),
4154
+ width: metrics[columnIndex].width,
4119
4155
  height: headerLeafHeight,
4156
+ "--rvg-header-action-width": `${actionWidth}px`,
4120
4157
  justifyContent: column.align === "right" ? "flex-end" : column.align === "center" ? "center" : "flex-start",
4121
4158
  textAlign: column.align === "right" ? "right" : column.align === "center" ? "center" : "left"
4122
4159
  },
@@ -4489,16 +4526,17 @@ function TableInner({
4489
4526
  const hoveredAction = inLeafHeader ? locateHeaderAction(event.clientX, columnIndex) : null;
4490
4527
  const hoveredDragHandle = Boolean(hoveredHeaderCell && locateHeaderCellDragHandle(event.clientX, hoveredHeaderCell));
4491
4528
  const hoveredDragColumnIndex = hoveredHeaderCell?.startIndex ?? columnIndex;
4492
- const hoveredTitle = inHeader && !hoveredAction && !hoveredDragHandle && hoveredHeaderCell && Boolean(hoveredHeaderCell.column.title) && isPointerOnHeaderTitle(event.clientX, event.clientY, hoveredHeaderCell) && (tooltipConfig.header || hoveredHeaderCell.leaf && isHeaderTitleTruncated(hoveredHeaderCell.startIndex));
4493
- const nextHover = hoveredAction ? { columnIndex, action: hoveredAction } : hoveredDragHandle ? { columnIndex: hoveredDragColumnIndex, action: "drag" } : hoveredTitle ? { columnIndex: hoveredHeaderCell.startIndex, action: "title" } : null;
4494
- 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;
4495
4533
  const previousHover = hoveredHeaderActionRef.current;
4496
4534
  if (previousHover?.columnIndex !== nextHover?.columnIndex || previousHover?.action !== nextHover?.action) {
4497
4535
  hoveredHeaderActionRef.current = nextHover;
4498
4536
  setHoveredHeaderAction(nextHover);
4499
- showHeaderTooltipAfterDelay(nextTooltip);
4500
4537
  scheduleDraw();
4501
4538
  }
4539
+ showHeaderTooltipAfterDelay(nextTooltip);
4502
4540
  if (inHeader) {
4503
4541
  if (hoveredRowIndexRef.current !== null) {
4504
4542
  hoveredRowIndexRef.current = null;
@@ -4550,12 +4588,12 @@ function TableInner({
4550
4588
  if (!isInsideText) {
4551
4589
  showCellTooltipAfterDelay(null);
4552
4590
  } else {
4553
- const placement = textRight + 330 > viewport.width ? "left" : "right";
4591
+ const placement = cellTop + rowHeight + 36 > renderHeight ? "above" : "below";
4554
4592
  const nextTooltip2 = {
4555
4593
  rowIndex: cell.rowIndex,
4556
4594
  columnIndex: cell.columnIndex,
4557
- left: placement === "right" ? textRight + 16 : Math.max(8, textLeft - 16),
4558
- 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,
4559
4597
  label,
4560
4598
  placement
4561
4599
  };
@@ -4584,6 +4622,8 @@ function TableInner({
4584
4622
  }
4585
4623
  },
4586
4624
  onPointerDown: (event) => {
4625
+ handleColumnPointerDown(event);
4626
+ if (columnDragRef.current) return;
4587
4627
  const headerDragCell = columnDraggable ? locateHeaderCell(event.clientX, event.clientY) : null;
4588
4628
  const columnIndex = locateColumn(event.clientX);
4589
4629
  const rowDragHandle = rowDraggable && columnIndex >= 0 && Boolean(columns[columnIndex].rowDragHandle) && locateRow(event.clientY) >= 0;
@@ -4592,8 +4632,7 @@ function TableInner({
4592
4632
  document.documentElement.classList.add("rvg-is-dragging");
4593
4633
  event.currentTarget.style.cursor = "move";
4594
4634
  }
4595
- handleColumnPointerDown(event);
4596
- if (!columnDragRef.current) handleColumnOrderPointerDown(event);
4635
+ handleColumnOrderPointerDown(event);
4597
4636
  beginRangeDrag(event);
4598
4637
  },
4599
4638
  onPointerMove: (event) => {
@@ -4651,6 +4690,12 @@ function TableInner({
4651
4690
  }
4652
4691
  const cell = locateCell(event.clientX, event.clientY);
4653
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
+ }
4654
4699
  clickedCellRef.current = null;
4655
4700
  setSelectionRange(null);
4656
4701
  setSelection(null);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lensui/lens-table",
3
- "version": "0.1.24",
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",