@lensui/lens-table 0.1.43 → 0.1.45

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
@@ -879,6 +879,7 @@ var COLORS = {
879
879
  selection: "#1677ff",
880
880
  selectionFill: "#edf4ff",
881
881
  axisSelectionFill: "#e8f2ff",
882
+ axisSelectionStripeFill: "#dfeeff",
882
883
  axisSelectionText: "#202124",
883
884
  rowHoverFill: "#f6f9fc",
884
885
  editedFill: "#fff1b8",
@@ -907,6 +908,7 @@ function paintGrid(options) {
907
908
  const headerLeafTop = options.headerLeafTop ?? 0;
908
909
  const headerLeafHeight = options.headerLeafHeight ?? headerHeight;
909
910
  const colors = { ...COLORS, ...options.colors };
911
+ const getAxisSelectionFill = (rowIndex, columnKey) => selectedColumnKeys.has(columnKey) && striped && rowIndex % 2 === 1 ? colors.axisSelectionStripeFill : colors.axisSelectionFill;
910
912
  const bodyTop = options.bodyTop ?? headerHeight;
911
913
  const getCellSpan = (rowIndex, columnIndex) => options.cellSpans.get(getCellCoordKey(rowIndex, columnIndex));
912
914
  const getCellWidth = (columnIndex, colSpan) => {
@@ -1017,7 +1019,7 @@ function paintGrid(options) {
1017
1019
  ctx.fillRect(x, y, cellWidth, cellHeight);
1018
1020
  }
1019
1021
  if (isAxisSelected) {
1020
- ctx.fillStyle = colors.axisSelectionFill;
1022
+ ctx.fillStyle = getAxisSelectionFill(rowIndex, column.key);
1021
1023
  ctx.fillRect(x, y, cellWidth, cellHeight);
1022
1024
  }
1023
1025
  if (hoveredRowIndex === rowIndex) {
@@ -1049,7 +1051,7 @@ function paintGrid(options) {
1049
1051
  ctx.fillRect(x, y, cellWidth, cellHeight);
1050
1052
  }
1051
1053
  if (isColumnDropTarget) {
1052
- ctx.fillStyle = isAxisSelected ? colors.axisSelectionFill : colors.columnDropTargetFill;
1054
+ ctx.fillStyle = isAxisSelected ? getAxisSelectionFill(rowIndex, column.key) : colors.columnDropTargetFill;
1053
1055
  ctx.fillRect(x, y, cellWidth, cellHeight);
1054
1056
  }
1055
1057
  ctx.fillStyle = colors.grid;
@@ -1061,14 +1063,14 @@ function paintGrid(options) {
1061
1063
  ctx.fillRect(x, y + cellHeight - 1, cellWidth, 1);
1062
1064
  }
1063
1065
  if (rowSpan > 1) {
1064
- const mergedFill = isColumnDropTarget ? isAxisSelected ? colors.axisSelectionFill : colors.columnDropTargetFill : annotation?.type === "background" ? annotation.color : isSelectedCell || isRangeCell ? colors.selectionFill : highlightEditedCells && !insertedRowKeys.has(rowKey) && editedCellKeys.has(`${typeof rowKey}:${String(rowKey)}\0${column.key}`) ? colors.editedFill : highlightInsertedRows && insertedRowKeys.has(rowKey) ? colors.insertedFill : hoveredRowIndex === rowIndex ? colors.rowHoverFill : isAxisSelected ? colors.axisSelectionFill : cellStyle?.backgroundColor ?? rowStyle?.backgroundColor ?? (striped && rowIndex % 2 === 1 ? colors.stripe : colors.background);
1066
+ const mergedFill = isColumnDropTarget ? isAxisSelected ? getAxisSelectionFill(rowIndex, column.key) : colors.columnDropTargetFill : annotation?.type === "background" ? annotation.color : isSelectedCell || isRangeCell ? colors.selectionFill : highlightEditedCells && !insertedRowKeys.has(rowKey) && editedCellKeys.has(`${typeof rowKey}:${String(rowKey)}\0${column.key}`) ? colors.editedFill : highlightInsertedRows && insertedRowKeys.has(rowKey) ? colors.insertedFill : hoveredRowIndex === rowIndex ? colors.rowHoverFill : isAxisSelected ? getAxisSelectionFill(rowIndex, column.key) : cellStyle?.backgroundColor ?? rowStyle?.backgroundColor ?? (striped && rowIndex % 2 === 1 ? colors.stripe : colors.background);
1065
1067
  ctx.fillStyle = mergedFill;
1066
1068
  for (let offset = 1; offset < rowSpan; offset += 1) {
1067
1069
  ctx.fillRect(x, y + offset * rowHeight - 1, cellWidth, 2);
1068
1070
  }
1069
1071
  }
1070
1072
  if (colSpan > 1 && !verticalBorderless) {
1071
- const mergedFill = isColumnDropTarget ? isAxisSelected ? colors.axisSelectionFill : colors.columnDropTargetFill : annotation?.type === "background" ? annotation.color : isSelectedCell || isRangeCell ? colors.selectionFill : highlightEditedCells && !insertedRowKeys.has(rowKey) && editedCellKeys.has(`${typeof rowKey}:${String(rowKey)}\0${column.key}`) ? colors.editedFill : highlightInsertedRows && insertedRowKeys.has(rowKey) ? colors.insertedFill : hoveredRowIndex === rowIndex ? colors.rowHoverFill : isAxisSelected ? colors.axisSelectionFill : cellStyle?.backgroundColor ?? rowStyle?.backgroundColor ?? (striped && rowIndex % 2 === 1 ? colors.stripe : colors.background);
1073
+ const mergedFill = isColumnDropTarget ? isAxisSelected ? getAxisSelectionFill(rowIndex, column.key) : colors.columnDropTargetFill : annotation?.type === "background" ? annotation.color : isSelectedCell || isRangeCell ? colors.selectionFill : highlightEditedCells && !insertedRowKeys.has(rowKey) && editedCellKeys.has(`${typeof rowKey}:${String(rowKey)}\0${column.key}`) ? colors.editedFill : highlightInsertedRows && insertedRowKeys.has(rowKey) ? colors.insertedFill : hoveredRowIndex === rowIndex ? colors.rowHoverFill : isAxisSelected ? getAxisSelectionFill(rowIndex, column.key) : cellStyle?.backgroundColor ?? rowStyle?.backgroundColor ?? (striped && rowIndex % 2 === 1 ? colors.stripe : colors.background);
1072
1074
  ctx.fillStyle = mergedFill;
1073
1075
  let offsetLeft = 0;
1074
1076
  for (let offset = 1; offset < colSpan; offset += 1) {
@@ -2347,6 +2349,7 @@ function TableInner({
2347
2349
  selection: readThemeColor(themeStyles, "--rvg-color-primary", "#1677ff"),
2348
2350
  selectionFill: readThemeColor(themeStyles, "--rvg-color-selection-fill", "#edf4ff"),
2349
2351
  axisSelectionFill: isSelectedColumnDrag || isSelectedColumnDropTarget ? readThemeColor(themeStyles, "--rvg-color-axis-selection-drag-fill", "#d8e8f8") : readThemeColor(themeStyles, "--rvg-color-axis-selection-fill", "#e8f2ff"),
2352
+ axisSelectionStripeFill: isSelectedColumnDrag || isSelectedColumnDropTarget ? readThemeColor(themeStyles, "--rvg-color-axis-selection-drag-fill", "#d8e8f8") : readThemeColor(themeStyles, "--rvg-color-axis-selection-stripe-fill", "#dfeeff"),
2350
2353
  axisSelectionText: isSelectedColumnDrag || isSelectedColumnDropTarget ? readThemeColor(themeStyles, "--rvg-color-axis-selection-drag-text", "#325b88") : readThemeColor(themeStyles, "--rvg-color-axis-selection-text", readThemeColor(themeStyles, "--rvg-color-text", "#202124")),
2351
2354
  rowHoverFill: readThemeColor(themeStyles, "--rvg-color-row-hover-fill", "#f6f9fc"),
2352
2355
  editedFill: editedCellHighlightColor ?? readThemeColor(themeStyles, "--rvg-color-edited-fill", "#fff1b8"),
@@ -2922,11 +2925,16 @@ function TableInner({
2922
2925
  setResizedColumnWidths((current) => current[columnKey] === width2 ? current : { ...current, [columnKey]: width2 });
2923
2926
  onColumnResize?.(columnKey, width2);
2924
2927
  }, [onColumnResize]);
2925
- const locateHeaderAction = (0, import_react5.useCallback)((clientX, columnIndex) => {
2928
+ const locateHeaderAction = (0, import_react5.useCallback)((clientX, clientY, columnIndex) => {
2926
2929
  if (columnIndex < 0 || !canvasRef.current) return null;
2927
2930
  const column = columns[columnIndex];
2928
2931
  if (column.rowSelection || column.rowDragHandle || column.rowNumber) return null;
2929
- const localX = clientX - canvasRef.current.getBoundingClientRect().left;
2932
+ const rect = canvasRef.current.getBoundingClientRect();
2933
+ const localX = clientX - rect.left;
2934
+ const localY = clientY - rect.top;
2935
+ const headerY = fixedHeader ? 0 : -scrollRef.current.top;
2936
+ const actionTop = headerY + headerLeafTop + (column.renderHeader ? 8 + Math.max(0, (16 - headerActionSize) / 2) : (headerLeafHeight - headerActionSize) / 2);
2937
+ if (localY < actionTop - 4 || localY > actionTop + headerActionSize + 4) return null;
2930
2938
  const columnRight = getDisplayedColumnLeft(columnIndex) + metrics[columnIndex].width;
2931
2939
  const visibleActions = getVisibleHeaderActions(column, metrics[columnIndex].width, columnDraggable, measureHeaderTitleWidth(columnIndex), headerActionSlotWidth);
2932
2940
  let right = columnRight - (visibleActions.drag ? headerActionSlotWidth : 2);
@@ -2936,7 +2944,7 @@ function TableInner({
2936
2944
  }
2937
2945
  if (visibleActions.filter && localX >= right - headerActionSlotWidth && localX < right) return "filter";
2938
2946
  return null;
2939
- }, [columnDraggable, columns, getDisplayedColumnLeft, headerActionSlotWidth, measureHeaderTitleWidth, metrics]);
2947
+ }, [columnDraggable, columns, fixedHeader, getDisplayedColumnLeft, headerActionSize, headerActionSlotWidth, headerLeafHeight, headerLeafTop, measureHeaderTitleWidth, metrics]);
2940
2948
  const isHeaderTitleTruncated = (0, import_react5.useCallback)((columnIndex) => {
2941
2949
  const canvas = canvasRef.current;
2942
2950
  if (columnIndex < 0 || !canvas) return false;
@@ -2947,15 +2955,20 @@ function TableInner({
2947
2955
  const actionWidth = (Number(visibleActions.drag) + Number(visibleActions.filter) + Number(visibleActions.sort)) * headerActionSlotWidth;
2948
2956
  return getHeaderTitleRequiredWidth(column, titleWidth) > Math.max(0, metric.width - actionWidth);
2949
2957
  }, [columnDraggable, columns, headerActionSlotWidth, measureHeaderTitleWidth, metrics]);
2950
- const locateHeaderDragHandle = (0, import_react5.useCallback)((clientX, columnIndex) => {
2958
+ const locateHeaderDragHandle = (0, import_react5.useCallback)((clientX, clientY, columnIndex) => {
2951
2959
  if (!columnDraggable || columnIndex < 0 || !canvasRef.current) return false;
2952
2960
  const column = columns[columnIndex];
2953
2961
  if (column.rowSelection || column.rowDragHandle || column.rowNumber) return false;
2954
2962
  if (!getVisibleHeaderActions(column, metrics[columnIndex].width, columnDraggable, measureHeaderTitleWidth(columnIndex), headerActionSlotWidth).drag) return false;
2955
- const localX = clientX - canvasRef.current.getBoundingClientRect().left;
2963
+ const rect = canvasRef.current.getBoundingClientRect();
2964
+ const localX = clientX - rect.left;
2965
+ const localY = clientY - rect.top;
2966
+ const headerY = fixedHeader ? 0 : -scrollRef.current.top;
2967
+ const actionTop = headerY + headerLeafTop + (column.renderHeader ? 8 + Math.max(0, (16 - headerActionSize) / 2) : (headerLeafHeight - headerActionSize) / 2);
2968
+ if (localY < actionTop - 4 || localY > actionTop + headerActionSize + 4) return false;
2956
2969
  const columnRight = getDisplayedColumnLeft(columnIndex) + metrics[columnIndex].width;
2957
2970
  return localX >= columnRight - headerActionSlotWidth && localX < columnRight - 2;
2958
- }, [columnDraggable, columns, getDisplayedColumnLeft, headerActionSlotWidth, measureHeaderTitleWidth, metrics]);
2971
+ }, [columnDraggable, columns, fixedHeader, getDisplayedColumnLeft, headerActionSize, headerActionSlotWidth, headerLeafHeight, headerLeafTop, measureHeaderTitleWidth, metrics]);
2959
2972
  const getHeaderCellLeft = (0, import_react5.useCallback)((cell) => {
2960
2973
  const startMetric = metrics[cell.startIndex];
2961
2974
  const fixedSide = columns[cell.startIndex]?.fixed;
@@ -3015,9 +3028,9 @@ function TableInner({
3015
3028
  return closest;
3016
3029
  }, [columnResizable, columns, fixedHeader, getHeaderCellLeft, getHeaderCellWidth, getHeaderLevelAtY, headerCells, headerHeight]);
3017
3030
  const locateHeaderResizeCell = (0, import_react5.useCallback)((clientX, clientY) => locateHeaderResizeHit(clientX, clientY)?.cell ?? null, [locateHeaderResizeHit]);
3018
- const locateHeaderCellDragHandle = (0, import_react5.useCallback)((clientX, cell) => {
3031
+ const locateHeaderCellDragHandle = (0, import_react5.useCallback)((clientX, clientY, cell) => {
3019
3032
  if (!columnDraggable || !canvasRef.current) return false;
3020
- if (cell.leaf) return locateHeaderDragHandle(clientX, cell.startIndex);
3033
+ if (cell.leaf) return locateHeaderDragHandle(clientX, clientY, cell.startIndex);
3021
3034
  const localX = clientX - canvasRef.current.getBoundingClientRect().left;
3022
3035
  const right = getHeaderCellLeft(cell) + getHeaderCellWidth(cell);
3023
3036
  return localX >= right - headerActionSlotWidth && localX < right - 2;
@@ -3675,7 +3688,7 @@ function TableInner({
3675
3688
  if (!columnDraggable || event.button !== 0 || columnDragRef.current) return;
3676
3689
  const sourceCell = locateHeaderCell(event.clientX, event.clientY);
3677
3690
  if (!sourceCell || locateHeaderResizeCell(event.clientX, event.clientY)) return;
3678
- if (sourceCell.leaf && locateHeaderAction(event.clientX, sourceCell.startIndex)) return;
3691
+ if (sourceCell.leaf && locateHeaderAction(event.clientX, event.clientY, sourceCell.startIndex)) return;
3679
3692
  const sourceColumn = columns[sourceCell.startIndex];
3680
3693
  if (!sourceColumn || sourceColumn.rowSelection || sourceColumn.rowDragHandle || sourceColumn.rowNumber) return;
3681
3694
  event.currentTarget.setPointerCapture(event.pointerId);
@@ -3834,6 +3847,7 @@ function TableInner({
3834
3847
  const rowTop = (fixedHeader ? 0 : -scrollPosition.top) + (headerRowOffsets[level] ?? 0);
3835
3848
  const rowHeight2 = headerRowHeights[level] ?? baseHeaderHeight;
3836
3849
  let anchorX = cellLeft + cellWidth / 2;
3850
+ let anchorY = rowTop + rowHeight2 / 2;
3837
3851
  let anchorLeft = cellLeft;
3838
3852
  let label = column.title;
3839
3853
  if (action === "title") {
@@ -3857,8 +3871,10 @@ function TableInner({
3857
3871
  anchorX = anchorLeft + textWidth;
3858
3872
  }
3859
3873
  } else if (action === "drag") {
3860
- anchorX = cellLeft + cellWidth;
3874
+ const right = cellLeft + cellWidth - headerActionSlotWidth;
3875
+ anchorX = right - headerActionSlotWidth / 2;
3861
3876
  anchorLeft = anchorX;
3877
+ anchorY = rowTop + headerLeafTop + (column.renderHeader ? 8 + Math.max(0, (16 - headerActionSize) / 2) : (headerLeafHeight - headerActionSize) / 2) + headerActionSize / 2;
3862
3878
  label = labels.dragColumn;
3863
3879
  } else if (action === "sort") {
3864
3880
  const direction = sortState?.columnKey === column.key ? sortState.direction : null;
@@ -3867,6 +3883,7 @@ function TableInner({
3867
3883
  const right = cellLeft + cellWidth - (visibleActions.drag ? headerActionSlotWidth : 2);
3868
3884
  anchorX = right - headerActionSlotWidth / 2;
3869
3885
  anchorLeft = anchorX;
3886
+ anchorY = rowTop + headerLeafTop + (column.renderHeader ? 8 + Math.max(0, (16 - headerActionSize) / 2) : (headerLeafHeight - headerActionSize) / 2) + headerActionSize / 2;
3870
3887
  } else if (action === "filter") {
3871
3888
  const value = filterValues[column.key];
3872
3889
  label = value ? labels.filterWithValue(value) : labels.filter;
@@ -3875,6 +3892,7 @@ function TableInner({
3875
3892
  if (visibleActions.sort) right -= headerActionSlotWidth;
3876
3893
  anchorX = right - headerActionSlotWidth / 2;
3877
3894
  anchorLeft = anchorX;
3895
+ anchorY = rowTop + headerLeafTop + (column.renderHeader ? 8 + Math.max(0, (16 - headerActionSize) / 2) : (headerLeafHeight - headerActionSize) / 2) + headerActionSize / 2 + 1;
3878
3896
  }
3879
3897
  const placement = anchorX + 328 > viewport.width ? "left" : "right";
3880
3898
  return {
@@ -3882,11 +3900,11 @@ function TableInner({
3882
3900
  columnIndex,
3883
3901
  action,
3884
3902
  left: placement === "right" ? anchorX + 8 : Math.max(8, anchorLeft - 8),
3885
- top: rowTop + rowHeight2 / 2,
3903
+ top: anchorY,
3886
3904
  label,
3887
3905
  placement
3888
3906
  };
3889
- }, [baseHeaderHeight, columnDraggable, columns, filterValues, fixedHeader, getDisplayedColumnLeft, getHeaderCellLeft, getHeaderCellWidth, headerActionSlotWidth, headerDepth, headerRowHeights, headerRowOffsets, labels, measureHeaderTitleWidth, metrics, scrollPosition.top, sortState, viewport.width]);
3907
+ }, [baseHeaderHeight, columnDraggable, columns, filterValues, fixedHeader, getDisplayedColumnLeft, getHeaderCellLeft, getHeaderCellWidth, headerActionSize, headerActionSlotWidth, headerDepth, headerLeafHeight, headerLeafTop, headerRowHeights, headerRowOffsets, labels, measureHeaderTitleWidth, metrics, scrollPosition.top, sortState, viewport.width]);
3890
3908
  const isPointerOnHeaderTitle = (0, import_react5.useCallback)((clientX, clientY, cell) => {
3891
3909
  const canvas = canvasRef.current;
3892
3910
  if (!canvas) return false;
@@ -4650,8 +4668,8 @@ function TableInner({
4650
4668
  const nextHoveredHeaderColumnIndex = inLeafHeader && columnIndex >= 0 ? columnIndex : null;
4651
4669
  setHoveredHeaderColumnIndex((current) => current === nextHoveredHeaderColumnIndex ? current : nextHoveredHeaderColumnIndex);
4652
4670
  const hoveredHeaderCell = inHeader ? locateHeaderCell(event.clientX, event.clientY) : null;
4653
- const hoveredAction = inLeafHeader ? locateHeaderAction(event.clientX, columnIndex) : null;
4654
- const hoveredDragHandle = Boolean(hoveredHeaderCell && locateHeaderCellDragHandle(event.clientX, hoveredHeaderCell));
4671
+ const hoveredAction = inLeafHeader ? locateHeaderAction(event.clientX, event.clientY, columnIndex) : null;
4672
+ const hoveredDragHandle = Boolean(hoveredHeaderCell && locateHeaderCellDragHandle(event.clientX, event.clientY, hoveredHeaderCell));
4655
4673
  const hoveredDragColumnIndex = hoveredHeaderCell?.startIndex ?? columnIndex;
4656
4674
  const customHeaderTooltipMatch = inHeader && !hoveredAction && !hoveredDragHandle ? locateCustomHeaderTooltip(event.clientX, event.clientY, columnIndex) : null;
4657
4675
  const hoveredContentTooltip = customHeaderTooltipMatch || null;
@@ -4756,7 +4774,7 @@ function TableInner({
4756
4774
  const headerDragCell = columnDraggable ? locateHeaderCell(event.clientX, event.clientY) : null;
4757
4775
  const columnIndex = locateColumn(event.clientX);
4758
4776
  const rowDragHandle = rowDraggable && columnIndex >= 0 && Boolean(columns[columnIndex].rowDragHandle) && locateRow(event.clientY) >= 0;
4759
- if (headerDragCell && locateHeaderCellDragHandle(event.clientX, headerDragCell) || rowDragHandle) {
4777
+ if (headerDragCell && locateHeaderCellDragHandle(event.clientX, event.clientY, headerDragCell) || rowDragHandle) {
4760
4778
  hideDragTooltips();
4761
4779
  document.documentElement.classList.add("rvg-is-dragging");
4762
4780
  event.currentTarget.style.cursor = "move";
@@ -4791,7 +4809,7 @@ function TableInner({
4791
4809
  clickedCellRef.current = null;
4792
4810
  if (localY < headerY + headerLeafTop) return;
4793
4811
  const columnIndex = locateColumn(event.clientX);
4794
- const action = locateHeaderAction(event.clientX, columnIndex);
4812
+ const action = locateHeaderAction(event.clientX, event.clientY, columnIndex);
4795
4813
  if (action === "sort") {
4796
4814
  const columnKey = columns[columnIndex].key;
4797
4815
  const next = sortState?.columnKey !== columnKey ? { columnKey, direction: "asc" } : sortState.direction === "asc" ? { columnKey, direction: "desc" } : null;
@@ -4803,7 +4821,7 @@ function TableInner({
4803
4821
  setFilterEditor({ columnIndex, left, top: Math.max(0, headerY + headerHeight), draft: filterValues[columns[columnIndex].key] ?? "" });
4804
4822
  return;
4805
4823
  }
4806
- if (locateHeaderDragHandle(event.clientX, columnIndex)) return;
4824
+ if (locateHeaderDragHandle(event.clientX, event.clientY, columnIndex)) return;
4807
4825
  if (columnIndex >= 0 && columns[columnIndex].rowSelection && rowSelection) {
4808
4826
  if (columns[columnIndex].rowSelectionIndicator === "arrow" || columns[columnIndex].rowSelectionIndicator === "none") return;
4809
4827
  setSelectionRange(null);
package/dist/index.css CHANGED
@@ -16,6 +16,7 @@
16
16
  --rvg-color-primary-soft: #edf4ff;
17
17
  --rvg-color-selection-fill: #edf4ff;
18
18
  --rvg-color-axis-selection-fill: #e8f2ff;
19
+ --rvg-color-axis-selection-stripe-fill: #dfeeff;
19
20
  --rvg-color-axis-selection-text: var(--rvg-color-text);
20
21
  --rvg-color-axis-selection-drag-fill: #d8e8f8;
21
22
  --rvg-color-axis-selection-drag-text: #325b88;
package/dist/index.js CHANGED
@@ -849,6 +849,7 @@ var COLORS = {
849
849
  selection: "#1677ff",
850
850
  selectionFill: "#edf4ff",
851
851
  axisSelectionFill: "#e8f2ff",
852
+ axisSelectionStripeFill: "#dfeeff",
852
853
  axisSelectionText: "#202124",
853
854
  rowHoverFill: "#f6f9fc",
854
855
  editedFill: "#fff1b8",
@@ -877,6 +878,7 @@ function paintGrid(options) {
877
878
  const headerLeafTop = options.headerLeafTop ?? 0;
878
879
  const headerLeafHeight = options.headerLeafHeight ?? headerHeight;
879
880
  const colors = { ...COLORS, ...options.colors };
881
+ const getAxisSelectionFill = (rowIndex, columnKey) => selectedColumnKeys.has(columnKey) && striped && rowIndex % 2 === 1 ? colors.axisSelectionStripeFill : colors.axisSelectionFill;
880
882
  const bodyTop = options.bodyTop ?? headerHeight;
881
883
  const getCellSpan = (rowIndex, columnIndex) => options.cellSpans.get(getCellCoordKey(rowIndex, columnIndex));
882
884
  const getCellWidth = (columnIndex, colSpan) => {
@@ -987,7 +989,7 @@ function paintGrid(options) {
987
989
  ctx.fillRect(x, y, cellWidth, cellHeight);
988
990
  }
989
991
  if (isAxisSelected) {
990
- ctx.fillStyle = colors.axisSelectionFill;
992
+ ctx.fillStyle = getAxisSelectionFill(rowIndex, column.key);
991
993
  ctx.fillRect(x, y, cellWidth, cellHeight);
992
994
  }
993
995
  if (hoveredRowIndex === rowIndex) {
@@ -1019,7 +1021,7 @@ function paintGrid(options) {
1019
1021
  ctx.fillRect(x, y, cellWidth, cellHeight);
1020
1022
  }
1021
1023
  if (isColumnDropTarget) {
1022
- ctx.fillStyle = isAxisSelected ? colors.axisSelectionFill : colors.columnDropTargetFill;
1024
+ ctx.fillStyle = isAxisSelected ? getAxisSelectionFill(rowIndex, column.key) : colors.columnDropTargetFill;
1023
1025
  ctx.fillRect(x, y, cellWidth, cellHeight);
1024
1026
  }
1025
1027
  ctx.fillStyle = colors.grid;
@@ -1031,14 +1033,14 @@ function paintGrid(options) {
1031
1033
  ctx.fillRect(x, y + cellHeight - 1, cellWidth, 1);
1032
1034
  }
1033
1035
  if (rowSpan > 1) {
1034
- const mergedFill = isColumnDropTarget ? isAxisSelected ? colors.axisSelectionFill : colors.columnDropTargetFill : annotation?.type === "background" ? annotation.color : isSelectedCell || isRangeCell ? colors.selectionFill : highlightEditedCells && !insertedRowKeys.has(rowKey) && editedCellKeys.has(`${typeof rowKey}:${String(rowKey)}\0${column.key}`) ? colors.editedFill : highlightInsertedRows && insertedRowKeys.has(rowKey) ? colors.insertedFill : hoveredRowIndex === rowIndex ? colors.rowHoverFill : isAxisSelected ? colors.axisSelectionFill : cellStyle?.backgroundColor ?? rowStyle?.backgroundColor ?? (striped && rowIndex % 2 === 1 ? colors.stripe : colors.background);
1036
+ const mergedFill = isColumnDropTarget ? isAxisSelected ? getAxisSelectionFill(rowIndex, column.key) : colors.columnDropTargetFill : annotation?.type === "background" ? annotation.color : isSelectedCell || isRangeCell ? colors.selectionFill : highlightEditedCells && !insertedRowKeys.has(rowKey) && editedCellKeys.has(`${typeof rowKey}:${String(rowKey)}\0${column.key}`) ? colors.editedFill : highlightInsertedRows && insertedRowKeys.has(rowKey) ? colors.insertedFill : hoveredRowIndex === rowIndex ? colors.rowHoverFill : isAxisSelected ? getAxisSelectionFill(rowIndex, column.key) : cellStyle?.backgroundColor ?? rowStyle?.backgroundColor ?? (striped && rowIndex % 2 === 1 ? colors.stripe : colors.background);
1035
1037
  ctx.fillStyle = mergedFill;
1036
1038
  for (let offset = 1; offset < rowSpan; offset += 1) {
1037
1039
  ctx.fillRect(x, y + offset * rowHeight - 1, cellWidth, 2);
1038
1040
  }
1039
1041
  }
1040
1042
  if (colSpan > 1 && !verticalBorderless) {
1041
- const mergedFill = isColumnDropTarget ? isAxisSelected ? colors.axisSelectionFill : colors.columnDropTargetFill : annotation?.type === "background" ? annotation.color : isSelectedCell || isRangeCell ? colors.selectionFill : highlightEditedCells && !insertedRowKeys.has(rowKey) && editedCellKeys.has(`${typeof rowKey}:${String(rowKey)}\0${column.key}`) ? colors.editedFill : highlightInsertedRows && insertedRowKeys.has(rowKey) ? colors.insertedFill : hoveredRowIndex === rowIndex ? colors.rowHoverFill : isAxisSelected ? colors.axisSelectionFill : cellStyle?.backgroundColor ?? rowStyle?.backgroundColor ?? (striped && rowIndex % 2 === 1 ? colors.stripe : colors.background);
1043
+ const mergedFill = isColumnDropTarget ? isAxisSelected ? getAxisSelectionFill(rowIndex, column.key) : colors.columnDropTargetFill : annotation?.type === "background" ? annotation.color : isSelectedCell || isRangeCell ? colors.selectionFill : highlightEditedCells && !insertedRowKeys.has(rowKey) && editedCellKeys.has(`${typeof rowKey}:${String(rowKey)}\0${column.key}`) ? colors.editedFill : highlightInsertedRows && insertedRowKeys.has(rowKey) ? colors.insertedFill : hoveredRowIndex === rowIndex ? colors.rowHoverFill : isAxisSelected ? getAxisSelectionFill(rowIndex, column.key) : cellStyle?.backgroundColor ?? rowStyle?.backgroundColor ?? (striped && rowIndex % 2 === 1 ? colors.stripe : colors.background);
1042
1044
  ctx.fillStyle = mergedFill;
1043
1045
  let offsetLeft = 0;
1044
1046
  for (let offset = 1; offset < colSpan; offset += 1) {
@@ -2317,6 +2319,7 @@ function TableInner({
2317
2319
  selection: readThemeColor(themeStyles, "--rvg-color-primary", "#1677ff"),
2318
2320
  selectionFill: readThemeColor(themeStyles, "--rvg-color-selection-fill", "#edf4ff"),
2319
2321
  axisSelectionFill: isSelectedColumnDrag || isSelectedColumnDropTarget ? readThemeColor(themeStyles, "--rvg-color-axis-selection-drag-fill", "#d8e8f8") : readThemeColor(themeStyles, "--rvg-color-axis-selection-fill", "#e8f2ff"),
2322
+ axisSelectionStripeFill: isSelectedColumnDrag || isSelectedColumnDropTarget ? readThemeColor(themeStyles, "--rvg-color-axis-selection-drag-fill", "#d8e8f8") : readThemeColor(themeStyles, "--rvg-color-axis-selection-stripe-fill", "#dfeeff"),
2320
2323
  axisSelectionText: isSelectedColumnDrag || isSelectedColumnDropTarget ? readThemeColor(themeStyles, "--rvg-color-axis-selection-drag-text", "#325b88") : readThemeColor(themeStyles, "--rvg-color-axis-selection-text", readThemeColor(themeStyles, "--rvg-color-text", "#202124")),
2321
2324
  rowHoverFill: readThemeColor(themeStyles, "--rvg-color-row-hover-fill", "#f6f9fc"),
2322
2325
  editedFill: editedCellHighlightColor ?? readThemeColor(themeStyles, "--rvg-color-edited-fill", "#fff1b8"),
@@ -2892,11 +2895,16 @@ function TableInner({
2892
2895
  setResizedColumnWidths((current) => current[columnKey] === width2 ? current : { ...current, [columnKey]: width2 });
2893
2896
  onColumnResize?.(columnKey, width2);
2894
2897
  }, [onColumnResize]);
2895
- const locateHeaderAction = useCallback2((clientX, columnIndex) => {
2898
+ const locateHeaderAction = useCallback2((clientX, clientY, columnIndex) => {
2896
2899
  if (columnIndex < 0 || !canvasRef.current) return null;
2897
2900
  const column = columns[columnIndex];
2898
2901
  if (column.rowSelection || column.rowDragHandle || column.rowNumber) return null;
2899
- const localX = clientX - canvasRef.current.getBoundingClientRect().left;
2902
+ const rect = canvasRef.current.getBoundingClientRect();
2903
+ const localX = clientX - rect.left;
2904
+ const localY = clientY - rect.top;
2905
+ const headerY = fixedHeader ? 0 : -scrollRef.current.top;
2906
+ const actionTop = headerY + headerLeafTop + (column.renderHeader ? 8 + Math.max(0, (16 - headerActionSize) / 2) : (headerLeafHeight - headerActionSize) / 2);
2907
+ if (localY < actionTop - 4 || localY > actionTop + headerActionSize + 4) return null;
2900
2908
  const columnRight = getDisplayedColumnLeft(columnIndex) + metrics[columnIndex].width;
2901
2909
  const visibleActions = getVisibleHeaderActions(column, metrics[columnIndex].width, columnDraggable, measureHeaderTitleWidth(columnIndex), headerActionSlotWidth);
2902
2910
  let right = columnRight - (visibleActions.drag ? headerActionSlotWidth : 2);
@@ -2906,7 +2914,7 @@ function TableInner({
2906
2914
  }
2907
2915
  if (visibleActions.filter && localX >= right - headerActionSlotWidth && localX < right) return "filter";
2908
2916
  return null;
2909
- }, [columnDraggable, columns, getDisplayedColumnLeft, headerActionSlotWidth, measureHeaderTitleWidth, metrics]);
2917
+ }, [columnDraggable, columns, fixedHeader, getDisplayedColumnLeft, headerActionSize, headerActionSlotWidth, headerLeafHeight, headerLeafTop, measureHeaderTitleWidth, metrics]);
2910
2918
  const isHeaderTitleTruncated = useCallback2((columnIndex) => {
2911
2919
  const canvas = canvasRef.current;
2912
2920
  if (columnIndex < 0 || !canvas) return false;
@@ -2917,15 +2925,20 @@ function TableInner({
2917
2925
  const actionWidth = (Number(visibleActions.drag) + Number(visibleActions.filter) + Number(visibleActions.sort)) * headerActionSlotWidth;
2918
2926
  return getHeaderTitleRequiredWidth(column, titleWidth) > Math.max(0, metric.width - actionWidth);
2919
2927
  }, [columnDraggable, columns, headerActionSlotWidth, measureHeaderTitleWidth, metrics]);
2920
- const locateHeaderDragHandle = useCallback2((clientX, columnIndex) => {
2928
+ const locateHeaderDragHandle = useCallback2((clientX, clientY, columnIndex) => {
2921
2929
  if (!columnDraggable || columnIndex < 0 || !canvasRef.current) return false;
2922
2930
  const column = columns[columnIndex];
2923
2931
  if (column.rowSelection || column.rowDragHandle || column.rowNumber) return false;
2924
2932
  if (!getVisibleHeaderActions(column, metrics[columnIndex].width, columnDraggable, measureHeaderTitleWidth(columnIndex), headerActionSlotWidth).drag) return false;
2925
- const localX = clientX - canvasRef.current.getBoundingClientRect().left;
2933
+ const rect = canvasRef.current.getBoundingClientRect();
2934
+ const localX = clientX - rect.left;
2935
+ const localY = clientY - rect.top;
2936
+ const headerY = fixedHeader ? 0 : -scrollRef.current.top;
2937
+ const actionTop = headerY + headerLeafTop + (column.renderHeader ? 8 + Math.max(0, (16 - headerActionSize) / 2) : (headerLeafHeight - headerActionSize) / 2);
2938
+ if (localY < actionTop - 4 || localY > actionTop + headerActionSize + 4) return false;
2926
2939
  const columnRight = getDisplayedColumnLeft(columnIndex) + metrics[columnIndex].width;
2927
2940
  return localX >= columnRight - headerActionSlotWidth && localX < columnRight - 2;
2928
- }, [columnDraggable, columns, getDisplayedColumnLeft, headerActionSlotWidth, measureHeaderTitleWidth, metrics]);
2941
+ }, [columnDraggable, columns, fixedHeader, getDisplayedColumnLeft, headerActionSize, headerActionSlotWidth, headerLeafHeight, headerLeafTop, measureHeaderTitleWidth, metrics]);
2929
2942
  const getHeaderCellLeft = useCallback2((cell) => {
2930
2943
  const startMetric = metrics[cell.startIndex];
2931
2944
  const fixedSide = columns[cell.startIndex]?.fixed;
@@ -2985,9 +2998,9 @@ function TableInner({
2985
2998
  return closest;
2986
2999
  }, [columnResizable, columns, fixedHeader, getHeaderCellLeft, getHeaderCellWidth, getHeaderLevelAtY, headerCells, headerHeight]);
2987
3000
  const locateHeaderResizeCell = useCallback2((clientX, clientY) => locateHeaderResizeHit(clientX, clientY)?.cell ?? null, [locateHeaderResizeHit]);
2988
- const locateHeaderCellDragHandle = useCallback2((clientX, cell) => {
3001
+ const locateHeaderCellDragHandle = useCallback2((clientX, clientY, cell) => {
2989
3002
  if (!columnDraggable || !canvasRef.current) return false;
2990
- if (cell.leaf) return locateHeaderDragHandle(clientX, cell.startIndex);
3003
+ if (cell.leaf) return locateHeaderDragHandle(clientX, clientY, cell.startIndex);
2991
3004
  const localX = clientX - canvasRef.current.getBoundingClientRect().left;
2992
3005
  const right = getHeaderCellLeft(cell) + getHeaderCellWidth(cell);
2993
3006
  return localX >= right - headerActionSlotWidth && localX < right - 2;
@@ -3645,7 +3658,7 @@ function TableInner({
3645
3658
  if (!columnDraggable || event.button !== 0 || columnDragRef.current) return;
3646
3659
  const sourceCell = locateHeaderCell(event.clientX, event.clientY);
3647
3660
  if (!sourceCell || locateHeaderResizeCell(event.clientX, event.clientY)) return;
3648
- if (sourceCell.leaf && locateHeaderAction(event.clientX, sourceCell.startIndex)) return;
3661
+ if (sourceCell.leaf && locateHeaderAction(event.clientX, event.clientY, sourceCell.startIndex)) return;
3649
3662
  const sourceColumn = columns[sourceCell.startIndex];
3650
3663
  if (!sourceColumn || sourceColumn.rowSelection || sourceColumn.rowDragHandle || sourceColumn.rowNumber) return;
3651
3664
  event.currentTarget.setPointerCapture(event.pointerId);
@@ -3804,6 +3817,7 @@ function TableInner({
3804
3817
  const rowTop = (fixedHeader ? 0 : -scrollPosition.top) + (headerRowOffsets[level] ?? 0);
3805
3818
  const rowHeight2 = headerRowHeights[level] ?? baseHeaderHeight;
3806
3819
  let anchorX = cellLeft + cellWidth / 2;
3820
+ let anchorY = rowTop + rowHeight2 / 2;
3807
3821
  let anchorLeft = cellLeft;
3808
3822
  let label = column.title;
3809
3823
  if (action === "title") {
@@ -3827,8 +3841,10 @@ function TableInner({
3827
3841
  anchorX = anchorLeft + textWidth;
3828
3842
  }
3829
3843
  } else if (action === "drag") {
3830
- anchorX = cellLeft + cellWidth;
3844
+ const right = cellLeft + cellWidth - headerActionSlotWidth;
3845
+ anchorX = right - headerActionSlotWidth / 2;
3831
3846
  anchorLeft = anchorX;
3847
+ anchorY = rowTop + headerLeafTop + (column.renderHeader ? 8 + Math.max(0, (16 - headerActionSize) / 2) : (headerLeafHeight - headerActionSize) / 2) + headerActionSize / 2;
3832
3848
  label = labels.dragColumn;
3833
3849
  } else if (action === "sort") {
3834
3850
  const direction = sortState?.columnKey === column.key ? sortState.direction : null;
@@ -3837,6 +3853,7 @@ function TableInner({
3837
3853
  const right = cellLeft + cellWidth - (visibleActions.drag ? headerActionSlotWidth : 2);
3838
3854
  anchorX = right - headerActionSlotWidth / 2;
3839
3855
  anchorLeft = anchorX;
3856
+ anchorY = rowTop + headerLeafTop + (column.renderHeader ? 8 + Math.max(0, (16 - headerActionSize) / 2) : (headerLeafHeight - headerActionSize) / 2) + headerActionSize / 2;
3840
3857
  } else if (action === "filter") {
3841
3858
  const value = filterValues[column.key];
3842
3859
  label = value ? labels.filterWithValue(value) : labels.filter;
@@ -3845,6 +3862,7 @@ function TableInner({
3845
3862
  if (visibleActions.sort) right -= headerActionSlotWidth;
3846
3863
  anchorX = right - headerActionSlotWidth / 2;
3847
3864
  anchorLeft = anchorX;
3865
+ anchorY = rowTop + headerLeafTop + (column.renderHeader ? 8 + Math.max(0, (16 - headerActionSize) / 2) : (headerLeafHeight - headerActionSize) / 2) + headerActionSize / 2 + 1;
3848
3866
  }
3849
3867
  const placement = anchorX + 328 > viewport.width ? "left" : "right";
3850
3868
  return {
@@ -3852,11 +3870,11 @@ function TableInner({
3852
3870
  columnIndex,
3853
3871
  action,
3854
3872
  left: placement === "right" ? anchorX + 8 : Math.max(8, anchorLeft - 8),
3855
- top: rowTop + rowHeight2 / 2,
3873
+ top: anchorY,
3856
3874
  label,
3857
3875
  placement
3858
3876
  };
3859
- }, [baseHeaderHeight, columnDraggable, columns, filterValues, fixedHeader, getDisplayedColumnLeft, getHeaderCellLeft, getHeaderCellWidth, headerActionSlotWidth, headerDepth, headerRowHeights, headerRowOffsets, labels, measureHeaderTitleWidth, metrics, scrollPosition.top, sortState, viewport.width]);
3877
+ }, [baseHeaderHeight, columnDraggable, columns, filterValues, fixedHeader, getDisplayedColumnLeft, getHeaderCellLeft, getHeaderCellWidth, headerActionSize, headerActionSlotWidth, headerDepth, headerLeafHeight, headerLeafTop, headerRowHeights, headerRowOffsets, labels, measureHeaderTitleWidth, metrics, scrollPosition.top, sortState, viewport.width]);
3860
3878
  const isPointerOnHeaderTitle = useCallback2((clientX, clientY, cell) => {
3861
3879
  const canvas = canvasRef.current;
3862
3880
  if (!canvas) return false;
@@ -4620,8 +4638,8 @@ function TableInner({
4620
4638
  const nextHoveredHeaderColumnIndex = inLeafHeader && columnIndex >= 0 ? columnIndex : null;
4621
4639
  setHoveredHeaderColumnIndex((current) => current === nextHoveredHeaderColumnIndex ? current : nextHoveredHeaderColumnIndex);
4622
4640
  const hoveredHeaderCell = inHeader ? locateHeaderCell(event.clientX, event.clientY) : null;
4623
- const hoveredAction = inLeafHeader ? locateHeaderAction(event.clientX, columnIndex) : null;
4624
- const hoveredDragHandle = Boolean(hoveredHeaderCell && locateHeaderCellDragHandle(event.clientX, hoveredHeaderCell));
4641
+ const hoveredAction = inLeafHeader ? locateHeaderAction(event.clientX, event.clientY, columnIndex) : null;
4642
+ const hoveredDragHandle = Boolean(hoveredHeaderCell && locateHeaderCellDragHandle(event.clientX, event.clientY, hoveredHeaderCell));
4625
4643
  const hoveredDragColumnIndex = hoveredHeaderCell?.startIndex ?? columnIndex;
4626
4644
  const customHeaderTooltipMatch = inHeader && !hoveredAction && !hoveredDragHandle ? locateCustomHeaderTooltip(event.clientX, event.clientY, columnIndex) : null;
4627
4645
  const hoveredContentTooltip = customHeaderTooltipMatch || null;
@@ -4726,7 +4744,7 @@ function TableInner({
4726
4744
  const headerDragCell = columnDraggable ? locateHeaderCell(event.clientX, event.clientY) : null;
4727
4745
  const columnIndex = locateColumn(event.clientX);
4728
4746
  const rowDragHandle = rowDraggable && columnIndex >= 0 && Boolean(columns[columnIndex].rowDragHandle) && locateRow(event.clientY) >= 0;
4729
- if (headerDragCell && locateHeaderCellDragHandle(event.clientX, headerDragCell) || rowDragHandle) {
4747
+ if (headerDragCell && locateHeaderCellDragHandle(event.clientX, event.clientY, headerDragCell) || rowDragHandle) {
4730
4748
  hideDragTooltips();
4731
4749
  document.documentElement.classList.add("rvg-is-dragging");
4732
4750
  event.currentTarget.style.cursor = "move";
@@ -4761,7 +4779,7 @@ function TableInner({
4761
4779
  clickedCellRef.current = null;
4762
4780
  if (localY < headerY + headerLeafTop) return;
4763
4781
  const columnIndex = locateColumn(event.clientX);
4764
- const action = locateHeaderAction(event.clientX, columnIndex);
4782
+ const action = locateHeaderAction(event.clientX, event.clientY, columnIndex);
4765
4783
  if (action === "sort") {
4766
4784
  const columnKey = columns[columnIndex].key;
4767
4785
  const next = sortState?.columnKey !== columnKey ? { columnKey, direction: "asc" } : sortState.direction === "asc" ? { columnKey, direction: "desc" } : null;
@@ -4773,7 +4791,7 @@ function TableInner({
4773
4791
  setFilterEditor({ columnIndex, left, top: Math.max(0, headerY + headerHeight), draft: filterValues[columns[columnIndex].key] ?? "" });
4774
4792
  return;
4775
4793
  }
4776
- if (locateHeaderDragHandle(event.clientX, columnIndex)) return;
4794
+ if (locateHeaderDragHandle(event.clientX, event.clientY, columnIndex)) return;
4777
4795
  if (columnIndex >= 0 && columns[columnIndex].rowSelection && rowSelection) {
4778
4796
  if (columns[columnIndex].rowSelectionIndicator === "arrow" || columns[columnIndex].rowSelectionIndicator === "none") return;
4779
4797
  setSelectionRange(null);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lensui/lens-table",
3
- "version": "0.1.43",
3
+ "version": "0.1.45",
4
4
  "description": "A lightweight, canvas-rendered React table component for LensUI.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",