@lensui/lens-table 0.1.24 → 0.1.27
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 +112 -28
- package/dist/index.css +32 -2
- package/dist/index.js +112 -28
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -882,7 +882,7 @@ var COLORS = {
|
|
|
882
882
|
rowHoverFill: "#f6f9fc",
|
|
883
883
|
editedFill: "#fff1b8",
|
|
884
884
|
insertedFill: "#c8ead4",
|
|
885
|
-
columnDropTargetFill: "#
|
|
885
|
+
columnDropTargetFill: "#e2edf9",
|
|
886
886
|
stripe: "#fafbfc"
|
|
887
887
|
};
|
|
888
888
|
function ellipsizeText(context, text, maxWidth) {
|
|
@@ -959,13 +959,24 @@ 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 (
|
|
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 (
|
|
965
|
+
if (rowDragPreview?.sourceIndex === rowIndex) continue;
|
|
966
|
+
const row = rows[rowIndex];
|
|
967
|
+
const rowKey = getRowKey(row, rowIndex);
|
|
968
|
+
const trailingRowStyle = options.rowStyle?.(row, rowIndex);
|
|
966
969
|
const y = bodyTop + rowIndex * rowHeight - scrollTop + getRowDragOffset(rowIndex);
|
|
967
|
-
|
|
968
|
-
|
|
970
|
+
const paintTrailingLayer = (fill) => {
|
|
971
|
+
if (!fill) return;
|
|
972
|
+
ctx.fillStyle = fill;
|
|
973
|
+
ctx.fillRect(trailingBlankStart, y, width - trailingBlankStart, rowHeight);
|
|
974
|
+
};
|
|
975
|
+
if (striped && rowIndex % 2 === 1) paintTrailingLayer(colors.stripe);
|
|
976
|
+
paintTrailingLayer(trailingRowStyle?.backgroundColor);
|
|
977
|
+
if (selectedRowKeys.has(rowKey)) paintTrailingLayer(colors.axisSelectionFill);
|
|
978
|
+
if (hoveredRowIndex === rowIndex) paintTrailingLayer(colors.rowHoverFill);
|
|
979
|
+
if (highlightInsertedRows && insertedRowKeys.has(rowKey)) paintTrailingLayer(colors.insertedFill);
|
|
969
980
|
}
|
|
970
981
|
}
|
|
971
982
|
const paintBodyColumns = (layer) => {
|
|
@@ -990,6 +1001,7 @@ function paintGrid(options) {
|
|
|
990
1001
|
const cellWidth = getCellWidth(columnIndex, colSpan);
|
|
991
1002
|
const cellHeight = rowHeight * rowSpan;
|
|
992
1003
|
const isAxisSelected = selectedRowKeys.has(rowKey) || selectedColumnKeys.has(column.key);
|
|
1004
|
+
const isColumnDropTarget = Boolean(columnDropTarget && columnIndex >= columnDropTarget.startIndex && columnIndex <= columnDropTarget.endIndex);
|
|
993
1005
|
const rangeRowStart = selectionRange ? Math.min(selectionRange.anchor.rowIndex, selectionRange.focus.rowIndex) : -1;
|
|
994
1006
|
const rangeRowEnd = selectionRange ? Math.max(selectionRange.anchor.rowIndex, selectionRange.focus.rowIndex) : -1;
|
|
995
1007
|
const rangeColumnStart = selectionRange ? Math.min(selectionRange.anchor.columnIndex, selectionRange.focus.columnIndex) : -1;
|
|
@@ -1011,10 +1023,6 @@ function paintGrid(options) {
|
|
|
1011
1023
|
ctx.fillStyle = colors.rowHoverFill;
|
|
1012
1024
|
ctx.fillRect(x, y, cellWidth, cellHeight);
|
|
1013
1025
|
}
|
|
1014
|
-
if (columnDropTarget && columnIndex >= columnDropTarget.startIndex && columnIndex <= columnDropTarget.endIndex) {
|
|
1015
|
-
ctx.fillStyle = colors.columnDropTargetFill;
|
|
1016
|
-
ctx.fillRect(x, y, cellWidth, cellHeight);
|
|
1017
|
-
}
|
|
1018
1026
|
if (highlightInsertedRows && insertedRowKeys.has(rowKey)) {
|
|
1019
1027
|
ctx.fillStyle = colors.insertedFill;
|
|
1020
1028
|
ctx.fillRect(x, y, cellWidth, cellHeight);
|
|
@@ -1039,6 +1047,10 @@ function paintGrid(options) {
|
|
|
1039
1047
|
ctx.fillStyle = annotation.color;
|
|
1040
1048
|
ctx.fillRect(x, y, cellWidth, cellHeight);
|
|
1041
1049
|
}
|
|
1050
|
+
if (isColumnDropTarget) {
|
|
1051
|
+
ctx.fillStyle = colors.columnDropTargetFill;
|
|
1052
|
+
ctx.fillRect(x, y, cellWidth, cellHeight);
|
|
1053
|
+
}
|
|
1042
1054
|
ctx.fillStyle = colors.grid;
|
|
1043
1055
|
if (!verticalBorderless && !(frameBorderless && columnIndex + colSpan >= columns.length)) {
|
|
1044
1056
|
ctx.fillRect(x + cellWidth - 1, y, 1, cellHeight);
|
|
@@ -1048,14 +1060,14 @@ function paintGrid(options) {
|
|
|
1048
1060
|
ctx.fillRect(x, y + cellHeight - 1, cellWidth, 1);
|
|
1049
1061
|
}
|
|
1050
1062
|
if (rowSpan > 1) {
|
|
1051
|
-
const mergedFill = 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);
|
|
1063
|
+
const mergedFill = isColumnDropTarget ? 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);
|
|
1052
1064
|
ctx.fillStyle = mergedFill;
|
|
1053
1065
|
for (let offset = 1; offset < rowSpan; offset += 1) {
|
|
1054
1066
|
ctx.fillRect(x, y + offset * rowHeight - 1, cellWidth, 2);
|
|
1055
1067
|
}
|
|
1056
1068
|
}
|
|
1057
1069
|
if (colSpan > 1 && !verticalBorderless) {
|
|
1058
|
-
const mergedFill = 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);
|
|
1070
|
+
const mergedFill = isColumnDropTarget ? 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);
|
|
1059
1071
|
ctx.fillStyle = mergedFill;
|
|
1060
1072
|
let offsetLeft = 0;
|
|
1061
1073
|
for (let offset = 1; offset < colSpan; offset += 1) {
|
|
@@ -1152,11 +1164,11 @@ function paintGrid(options) {
|
|
|
1152
1164
|
ctx.beginPath();
|
|
1153
1165
|
ctx.rect(x + 2, y + 1, Math.max(0, cellWidth - 4), cellHeight - 2);
|
|
1154
1166
|
ctx.clip();
|
|
1155
|
-
ctx.fillStyle = isAxisSelected && !isSelectedCell && !isRangeCell ? colors.axisSelectionText : cellStyle?.color ?? rowStyle?.color ?? colors.text;
|
|
1167
|
+
ctx.fillStyle = isColumnDropTarget ? colors.text : isAxisSelected && !isSelectedCell && !isRangeCell ? colors.axisSelectionText : cellStyle?.color ?? rowStyle?.color ?? colors.text;
|
|
1156
1168
|
ctx.font = createCellFont(bodyFontSize);
|
|
1157
1169
|
ctx.textBaseline = "alphabetic";
|
|
1158
1170
|
ctx.textAlign = column.align === "right" ? "right" : column.align === "center" ? "center" : "left";
|
|
1159
|
-
ctx.fillText(label, textX, y + cellHeight / 2 + cellBaselineOffset);
|
|
1171
|
+
ctx.fillText(ellipsizeText(ctx, label, Math.max(0, cellWidth - padding * 2)), textX, y + cellHeight / 2 + cellBaselineOffset);
|
|
1160
1172
|
ctx.restore();
|
|
1161
1173
|
}
|
|
1162
1174
|
}
|
|
@@ -1215,6 +1227,25 @@ function paintGrid(options) {
|
|
|
1215
1227
|
paintExtendedColumnSelection("scroll");
|
|
1216
1228
|
paintExtendedColumnSelection("left");
|
|
1217
1229
|
paintExtendedColumnSelection("right");
|
|
1230
|
+
const paintExtendedColumnDropTarget = (layer) => {
|
|
1231
|
+
if (!columnDropTarget) return;
|
|
1232
|
+
ctx.save();
|
|
1233
|
+
if (layer === "scroll") {
|
|
1234
|
+
ctx.beginPath();
|
|
1235
|
+
ctx.rect(leftFixedWidth, extensionTop, Math.max(0, rightFixedLeft - leftFixedWidth), extensionHeight);
|
|
1236
|
+
ctx.clip();
|
|
1237
|
+
}
|
|
1238
|
+
ctx.fillStyle = colors.columnDropTargetFill;
|
|
1239
|
+
for (let columnIndex = columnDropTarget.startIndex; columnIndex <= columnDropTarget.endIndex; columnIndex += 1) {
|
|
1240
|
+
if (layer === "scroll" ? columns[columnIndex]?.fixed !== void 0 : columns[columnIndex]?.fixed !== layer) continue;
|
|
1241
|
+
if (layer === "scroll" && (columnIndex < range.columnStart || columnIndex >= range.columnEnd)) continue;
|
|
1242
|
+
ctx.fillRect(getColumnX(columnIndex), extensionTop, metrics[columnIndex].width, extensionHeight);
|
|
1243
|
+
}
|
|
1244
|
+
ctx.restore();
|
|
1245
|
+
};
|
|
1246
|
+
paintExtendedColumnDropTarget("scroll");
|
|
1247
|
+
paintExtendedColumnDropTarget("left");
|
|
1248
|
+
paintExtendedColumnDropTarget("right");
|
|
1218
1249
|
if (!verticalBorderless) {
|
|
1219
1250
|
paintExtendedColumnLines("scroll");
|
|
1220
1251
|
paintExtendedColumnLines("left");
|
|
@@ -1236,11 +1267,12 @@ function paintGrid(options) {
|
|
|
1236
1267
|
ctx.fillRect(x, headerY, metric.width, headerHeight);
|
|
1237
1268
|
}
|
|
1238
1269
|
const isAxisSelected = selectedColumnKeys.has(columns[columnIndex].key);
|
|
1270
|
+
const isColumnDropTarget = Boolean(columnDropTarget && columnIndex >= columnDropTarget.startIndex && columnIndex <= columnDropTarget.endIndex);
|
|
1239
1271
|
if (isAxisSelected) {
|
|
1240
1272
|
ctx.fillStyle = colors.axisSelectionFill;
|
|
1241
1273
|
ctx.fillRect(x, headerY, metric.width, headerHeight);
|
|
1242
1274
|
}
|
|
1243
|
-
if (
|
|
1275
|
+
if (isColumnDropTarget) {
|
|
1244
1276
|
ctx.fillStyle = colors.columnDropTargetFill;
|
|
1245
1277
|
ctx.fillRect(x, headerY, metric.width, headerHeight);
|
|
1246
1278
|
}
|
|
@@ -1269,7 +1301,7 @@ function paintGrid(options) {
|
|
|
1269
1301
|
ctx.beginPath();
|
|
1270
1302
|
ctx.rect(x + 2, headerY + headerLeafTop + 1, Math.max(0, clipWidth - 4), headerLeafHeight - 2);
|
|
1271
1303
|
ctx.clip();
|
|
1272
|
-
ctx.fillStyle = isAxisSelected ? colors.axisSelectionText : colors.muted;
|
|
1304
|
+
ctx.fillStyle = isColumnDropTarget ? colors.muted : isAxisSelected ? colors.axisSelectionText : colors.muted;
|
|
1273
1305
|
ctx.textAlign = titleAlign === "right" ? "right" : titleAlign === "center" ? "center" : "left";
|
|
1274
1306
|
ctx.fillText(title, textX, headerY + headerLeafTop + headerLeafHeight / 2);
|
|
1275
1307
|
ctx.restore();
|
|
@@ -1428,6 +1460,11 @@ function resolveColumnDropIndex(sourceIndex, targetIndex, edge, columnCount) {
|
|
|
1428
1460
|
function resolveColumnDropPlacement(edge) {
|
|
1429
1461
|
return edge === "right" ? "after" : "before";
|
|
1430
1462
|
}
|
|
1463
|
+
function resolveColumnDropHighlightRange(target, edge, cells) {
|
|
1464
|
+
if (edge === "right") return { startIndex: target.startIndex, endIndex: target.endIndex };
|
|
1465
|
+
const previous = cells.find((cell) => cell.endIndex === target.startIndex - 1 && cell.level === target.level && cell.parentKey === target.parentKey);
|
|
1466
|
+
return previous ? { startIndex: previous.startIndex, endIndex: previous.endIndex } : { startIndex: target.startIndex, endIndex: target.endIndex };
|
|
1467
|
+
}
|
|
1431
1468
|
var ANNOTATION_COLORS = ["#f44336", "#ff7a45", "#f5a623", "#f2c94c", "#52c41a", "#13a8a8", "#1677ff", "#597ef7", "#9254de", "#eb2f96"];
|
|
1432
1469
|
var FALLBACK_HEIGHT = 480;
|
|
1433
1470
|
var EMPTY_BODY_HEIGHT = 240;
|
|
@@ -2307,7 +2344,7 @@ function TableInner({
|
|
|
2307
2344
|
rowHoverFill: readThemeColor(themeStyles, "--rvg-color-row-hover-fill", "#f6f9fc"),
|
|
2308
2345
|
editedFill: editedCellHighlightColor ?? readThemeColor(themeStyles, "--rvg-color-edited-fill", "#fff1b8"),
|
|
2309
2346
|
insertedFill: insertedRowHighlightColor ?? readThemeColor(themeStyles, "--rvg-color-inserted-fill", "#c8ead4"),
|
|
2310
|
-
columnDropTargetFill: readThemeColor(themeStyles, "--rvg-color-column-drop-target-fill", "#
|
|
2347
|
+
columnDropTargetFill: readThemeColor(themeStyles, "--rvg-color-column-drop-target-fill", "#e2edf9"),
|
|
2311
2348
|
stripe: stripedColor ?? readThemeColor(themeStyles, "--rvg-color-stripe", "#fafbfc")
|
|
2312
2349
|
};
|
|
2313
2350
|
const scroll = scrollRef.current;
|
|
@@ -3585,6 +3622,8 @@ function TableInner({
|
|
|
3585
3622
|
columnDragRef.current = null;
|
|
3586
3623
|
setResizeGuideX(null);
|
|
3587
3624
|
setResizeGuideTop(0);
|
|
3625
|
+
document.documentElement.classList.remove("rvg-is-dragging");
|
|
3626
|
+
event.currentTarget.style.cursor = "default";
|
|
3588
3627
|
}, []);
|
|
3589
3628
|
const clearColumnOrderPointerDrag = (0, import_react5.useCallback)((canvas) => {
|
|
3590
3629
|
columnOrderDragRef.current = null;
|
|
@@ -3666,7 +3705,11 @@ function TableInner({
|
|
|
3666
3705
|
fixed: targetColumn.fixed,
|
|
3667
3706
|
columnEdge
|
|
3668
3707
|
};
|
|
3669
|
-
|
|
3708
|
+
const compatibleHighlightCells = headerCells.filter((cell) => {
|
|
3709
|
+
const cellColumn = columns[cell.startIndex];
|
|
3710
|
+
return cellColumn && !cellColumn.rowSelection && !cellColumn.rowDragHandle && !cellColumn.rowNumber && cellColumn.fixed === targetColumn.fixed;
|
|
3711
|
+
});
|
|
3712
|
+
setColumnDropTarget(resolveColumnDropHighlightRange(targetCell, columnEdge, compatibleHighlightCells));
|
|
3670
3713
|
setDragGuide(columnEdge === "right" ? targetLeft + targetWidth : targetLeft, headerRowOffsets[sourceCell.level] ?? 0);
|
|
3671
3714
|
}, [columns, getHeaderCellLeft, getHeaderCellWidth, headerCells, headerRowOffsets, hideDragTooltips, locateColumn, locateHeaderCell, setDragGuide]);
|
|
3672
3715
|
const finishColumnOrderPointerDrag = (0, import_react5.useCallback)((event, apply) => {
|
|
@@ -3811,6 +3854,34 @@ function TableInner({
|
|
|
3811
3854
|
const textTop = rowTop + 8;
|
|
3812
3855
|
return localX >= textLeft - 4 && localX <= textLeft + textWidth + 4 && localY >= textTop - 2 && localY <= textTop + 18;
|
|
3813
3856
|
}, [columnDraggable, fixedHeader, getHeaderCellLeft, getHeaderCellWidth, headerActionSlotWidth, headerRowOffsets]);
|
|
3857
|
+
const locateCustomHeaderTooltip = (0, import_react5.useCallback)((clientX, clientY, columnIndex) => {
|
|
3858
|
+
const root = rootRef.current;
|
|
3859
|
+
const canvas = canvasRef.current;
|
|
3860
|
+
if (!root || !canvas || columnIndex < 0) return null;
|
|
3861
|
+
const canvasRect = canvas.getBoundingClientRect();
|
|
3862
|
+
const targets = root.querySelectorAll(".rvg-header-title [data-rvg-tooltip]");
|
|
3863
|
+
for (const target of targets) {
|
|
3864
|
+
const rect = target.getBoundingClientRect();
|
|
3865
|
+
if (clientX < rect.left || clientX > rect.right || clientY < rect.top || clientY > rect.bottom) continue;
|
|
3866
|
+
const label = target.dataset.rvgTooltip?.trim();
|
|
3867
|
+
if (!label) return false;
|
|
3868
|
+
const visibleText = target.textContent?.replace(/\s+/g, " ").trim() ?? "";
|
|
3869
|
+
const candidates = [target, ...target.querySelectorAll("*")];
|
|
3870
|
+
const truncated = candidates.some((candidate) => candidate.scrollWidth > candidate.clientWidth + 1 || candidate.scrollHeight > candidate.clientHeight + 1);
|
|
3871
|
+
if (!truncated && label.replace(/\s+/g, " ").trim() === visibleText) return false;
|
|
3872
|
+
const rawLeft = rect.left - canvasRect.left;
|
|
3873
|
+
return {
|
|
3874
|
+
key: `content:${columnIndex}:${label}:${Math.round(rawLeft)}:${Math.round(rect.top - canvasRect.top)}`,
|
|
3875
|
+
columnIndex,
|
|
3876
|
+
action: "content",
|
|
3877
|
+
left: Math.max(8, Math.min(rawLeft, Math.max(8, viewport.width - 328))),
|
|
3878
|
+
top: rect.bottom - canvasRect.top + 4,
|
|
3879
|
+
label,
|
|
3880
|
+
placement: "below"
|
|
3881
|
+
};
|
|
3882
|
+
}
|
|
3883
|
+
return null;
|
|
3884
|
+
}, [viewport.width]);
|
|
3814
3885
|
const headerTooltip = (() => {
|
|
3815
3886
|
if (!visibleHeaderTooltip) return null;
|
|
3816
3887
|
return visibleHeaderTooltip;
|
|
@@ -4136,23 +4207,26 @@ function TableInner({
|
|
|
4136
4207
|
if (column.renderHeader) {
|
|
4137
4208
|
const visibleActions = getVisibleHeaderActions(column, metrics[columnIndex].width, columnDraggable, measureHeaderTitleWidth(columnIndex), headerActionSlotWidth);
|
|
4138
4209
|
const actionWidth = (Number(visibleActions.drag) + Number(visibleActions.filter) + Number(visibleActions.sort)) * headerActionSlotWidth;
|
|
4210
|
+
const isHeaderHovered = hoveredHeaderColumnIndex === columnIndex;
|
|
4139
4211
|
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
4140
4212
|
"div",
|
|
4141
4213
|
{
|
|
4142
|
-
className: `rvg-header-title is-custom${isAxisSelected ? " is-axis-selected" : ""}${isDropTarget ? " is-drop-target" : ""}`,
|
|
4214
|
+
className: `rvg-header-title is-custom${isHeaderHovered ? " is-header-hovered" : ""}${isAxisSelected ? " is-axis-selected" : ""}${isDropTarget ? " is-drop-target" : ""}`,
|
|
4143
4215
|
"data-level": headerDepth - 1,
|
|
4144
4216
|
"data-measure-key": column.key,
|
|
4145
4217
|
style: {
|
|
4146
4218
|
left,
|
|
4147
4219
|
top: leafTop,
|
|
4148
|
-
width:
|
|
4220
|
+
width: metrics[columnIndex].width,
|
|
4149
4221
|
height: headerLeafHeight,
|
|
4222
|
+
"--rvg-header-action-width": `${actionWidth}px`,
|
|
4150
4223
|
justifyContent: column.align === "right" ? "flex-end" : column.align === "center" ? "center" : "flex-start",
|
|
4151
4224
|
textAlign: column.align === "right" ? "right" : column.align === "center" ? "center" : "left"
|
|
4152
4225
|
},
|
|
4153
4226
|
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
4154
4227
|
"span",
|
|
4155
4228
|
{
|
|
4229
|
+
style: { width: "100%" },
|
|
4156
4230
|
ref: (node) => {
|
|
4157
4231
|
if (node) {
|
|
4158
4232
|
customHeaderContentRefs.current.set(column.key, node);
|
|
@@ -4519,16 +4593,19 @@ function TableInner({
|
|
|
4519
4593
|
const hoveredAction = inLeafHeader ? locateHeaderAction(event.clientX, columnIndex) : null;
|
|
4520
4594
|
const hoveredDragHandle = Boolean(hoveredHeaderCell && locateHeaderCellDragHandle(event.clientX, hoveredHeaderCell));
|
|
4521
4595
|
const hoveredDragColumnIndex = hoveredHeaderCell?.startIndex ?? columnIndex;
|
|
4522
|
-
const
|
|
4523
|
-
const
|
|
4524
|
-
const
|
|
4596
|
+
const customHeaderTooltipMatch = inHeader && !hoveredAction && !hoveredDragHandle ? locateCustomHeaderTooltip(event.clientX, event.clientY, columnIndex) : null;
|
|
4597
|
+
const hoveredContentTooltip = customHeaderTooltipMatch || null;
|
|
4598
|
+
const hoveredCustomContent = customHeaderTooltipMatch !== null;
|
|
4599
|
+
const hoveredTitle = inHeader && !hoveredAction && !hoveredDragHandle && !hoveredCustomContent && hoveredHeaderCell && Boolean(hoveredHeaderCell.column.title) && isPointerOnHeaderTitle(event.clientX, event.clientY, hoveredHeaderCell) && (tooltipConfig.header || hoveredHeaderCell.leaf && isHeaderTitleTruncated(hoveredHeaderCell.startIndex));
|
|
4600
|
+
const nextHover = hoveredAction ? { columnIndex, action: hoveredAction } : hoveredDragHandle ? { columnIndex: hoveredDragColumnIndex, action: "drag" } : hoveredContentTooltip ? { columnIndex, action: "content" } : hoveredTitle ? { columnIndex: hoveredHeaderCell.startIndex, action: "title" } : null;
|
|
4601
|
+
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
4602
|
const previousHover = hoveredHeaderActionRef.current;
|
|
4526
4603
|
if (previousHover?.columnIndex !== nextHover?.columnIndex || previousHover?.action !== nextHover?.action) {
|
|
4527
4604
|
hoveredHeaderActionRef.current = nextHover;
|
|
4528
4605
|
setHoveredHeaderAction(nextHover);
|
|
4529
|
-
showHeaderTooltipAfterDelay(nextTooltip);
|
|
4530
4606
|
scheduleDraw();
|
|
4531
4607
|
}
|
|
4608
|
+
showHeaderTooltipAfterDelay(nextTooltip);
|
|
4532
4609
|
if (inHeader) {
|
|
4533
4610
|
if (hoveredRowIndexRef.current !== null) {
|
|
4534
4611
|
hoveredRowIndexRef.current = null;
|
|
@@ -4580,12 +4657,12 @@ function TableInner({
|
|
|
4580
4657
|
if (!isInsideText) {
|
|
4581
4658
|
showCellTooltipAfterDelay(null);
|
|
4582
4659
|
} else {
|
|
4583
|
-
const placement =
|
|
4660
|
+
const placement = cellTop + rowHeight + 36 > renderHeight ? "above" : "below";
|
|
4584
4661
|
const nextTooltip2 = {
|
|
4585
4662
|
rowIndex: cell.rowIndex,
|
|
4586
4663
|
columnIndex: cell.columnIndex,
|
|
4587
|
-
left:
|
|
4588
|
-
top: cellTop + rowHeight
|
|
4664
|
+
left: Math.max(8, Math.min(textLeft, Math.max(8, viewport.width - 328))),
|
|
4665
|
+
top: placement === "below" ? cellTop + rowHeight + 4 : cellTop - 4,
|
|
4589
4666
|
label,
|
|
4590
4667
|
placement
|
|
4591
4668
|
};
|
|
@@ -4614,6 +4691,8 @@ function TableInner({
|
|
|
4614
4691
|
}
|
|
4615
4692
|
},
|
|
4616
4693
|
onPointerDown: (event) => {
|
|
4694
|
+
handleColumnPointerDown(event);
|
|
4695
|
+
if (columnDragRef.current) return;
|
|
4617
4696
|
const headerDragCell = columnDraggable ? locateHeaderCell(event.clientX, event.clientY) : null;
|
|
4618
4697
|
const columnIndex = locateColumn(event.clientX);
|
|
4619
4698
|
const rowDragHandle = rowDraggable && columnIndex >= 0 && Boolean(columns[columnIndex].rowDragHandle) && locateRow(event.clientY) >= 0;
|
|
@@ -4622,8 +4701,7 @@ function TableInner({
|
|
|
4622
4701
|
document.documentElement.classList.add("rvg-is-dragging");
|
|
4623
4702
|
event.currentTarget.style.cursor = "move";
|
|
4624
4703
|
}
|
|
4625
|
-
|
|
4626
|
-
if (!columnDragRef.current) handleColumnOrderPointerDown(event);
|
|
4704
|
+
handleColumnOrderPointerDown(event);
|
|
4627
4705
|
beginRangeDrag(event);
|
|
4628
4706
|
},
|
|
4629
4707
|
onPointerMove: (event) => {
|
|
@@ -4681,6 +4759,12 @@ function TableInner({
|
|
|
4681
4759
|
}
|
|
4682
4760
|
const cell = locateCell(event.clientX, event.clientY);
|
|
4683
4761
|
if (!cell) {
|
|
4762
|
+
const localX = event.clientX - rect.left;
|
|
4763
|
+
const trailingRowIndex = trailingColumnBorderLeft !== null && localX > trailingColumnBorderLeft ? locateRow(event.clientY) : -1;
|
|
4764
|
+
if (trailingRowIndex >= 0 && rowSelection) {
|
|
4765
|
+
selectRow(trailingRowIndex, event);
|
|
4766
|
+
return;
|
|
4767
|
+
}
|
|
4684
4768
|
clickedCellRef.current = null;
|
|
4685
4769
|
setSelectionRange(null);
|
|
4686
4770
|
setSelection(null);
|
package/dist/index.css
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
--rvg-color-selection-fill: #edf4ff;
|
|
18
18
|
--rvg-color-axis-selection-fill: #e8f2ff;
|
|
19
19
|
--rvg-color-axis-selection-text: var(--rvg-color-text);
|
|
20
|
-
--rvg-color-column-drop-target-fill: #
|
|
20
|
+
--rvg-color-column-drop-target-fill: #e2edf9;
|
|
21
21
|
--rvg-color-range-fill: #e8f1ff;
|
|
22
22
|
--rvg-color-row-hover-fill: #f6f9fc;
|
|
23
23
|
--rvg-color-hover: #f1f4f8;
|
|
@@ -903,7 +903,7 @@
|
|
|
903
903
|
.rvg-header-tooltip,
|
|
904
904
|
.rvg-cell-tooltip {
|
|
905
905
|
position: absolute;
|
|
906
|
-
z-index:
|
|
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
|
@@ -852,7 +852,7 @@ var COLORS = {
|
|
|
852
852
|
rowHoverFill: "#f6f9fc",
|
|
853
853
|
editedFill: "#fff1b8",
|
|
854
854
|
insertedFill: "#c8ead4",
|
|
855
|
-
columnDropTargetFill: "#
|
|
855
|
+
columnDropTargetFill: "#e2edf9",
|
|
856
856
|
stripe: "#fafbfc"
|
|
857
857
|
};
|
|
858
858
|
function ellipsizeText(context, text, maxWidth) {
|
|
@@ -929,13 +929,24 @@ 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 (
|
|
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 (
|
|
935
|
+
if (rowDragPreview?.sourceIndex === rowIndex) continue;
|
|
936
|
+
const row = rows[rowIndex];
|
|
937
|
+
const rowKey = getRowKey(row, rowIndex);
|
|
938
|
+
const trailingRowStyle = options.rowStyle?.(row, rowIndex);
|
|
936
939
|
const y = bodyTop + rowIndex * rowHeight - scrollTop + getRowDragOffset(rowIndex);
|
|
937
|
-
|
|
938
|
-
|
|
940
|
+
const paintTrailingLayer = (fill) => {
|
|
941
|
+
if (!fill) return;
|
|
942
|
+
ctx.fillStyle = fill;
|
|
943
|
+
ctx.fillRect(trailingBlankStart, y, width - trailingBlankStart, rowHeight);
|
|
944
|
+
};
|
|
945
|
+
if (striped && rowIndex % 2 === 1) paintTrailingLayer(colors.stripe);
|
|
946
|
+
paintTrailingLayer(trailingRowStyle?.backgroundColor);
|
|
947
|
+
if (selectedRowKeys.has(rowKey)) paintTrailingLayer(colors.axisSelectionFill);
|
|
948
|
+
if (hoveredRowIndex === rowIndex) paintTrailingLayer(colors.rowHoverFill);
|
|
949
|
+
if (highlightInsertedRows && insertedRowKeys.has(rowKey)) paintTrailingLayer(colors.insertedFill);
|
|
939
950
|
}
|
|
940
951
|
}
|
|
941
952
|
const paintBodyColumns = (layer) => {
|
|
@@ -960,6 +971,7 @@ function paintGrid(options) {
|
|
|
960
971
|
const cellWidth = getCellWidth(columnIndex, colSpan);
|
|
961
972
|
const cellHeight = rowHeight * rowSpan;
|
|
962
973
|
const isAxisSelected = selectedRowKeys.has(rowKey) || selectedColumnKeys.has(column.key);
|
|
974
|
+
const isColumnDropTarget = Boolean(columnDropTarget && columnIndex >= columnDropTarget.startIndex && columnIndex <= columnDropTarget.endIndex);
|
|
963
975
|
const rangeRowStart = selectionRange ? Math.min(selectionRange.anchor.rowIndex, selectionRange.focus.rowIndex) : -1;
|
|
964
976
|
const rangeRowEnd = selectionRange ? Math.max(selectionRange.anchor.rowIndex, selectionRange.focus.rowIndex) : -1;
|
|
965
977
|
const rangeColumnStart = selectionRange ? Math.min(selectionRange.anchor.columnIndex, selectionRange.focus.columnIndex) : -1;
|
|
@@ -981,10 +993,6 @@ function paintGrid(options) {
|
|
|
981
993
|
ctx.fillStyle = colors.rowHoverFill;
|
|
982
994
|
ctx.fillRect(x, y, cellWidth, cellHeight);
|
|
983
995
|
}
|
|
984
|
-
if (columnDropTarget && columnIndex >= columnDropTarget.startIndex && columnIndex <= columnDropTarget.endIndex) {
|
|
985
|
-
ctx.fillStyle = colors.columnDropTargetFill;
|
|
986
|
-
ctx.fillRect(x, y, cellWidth, cellHeight);
|
|
987
|
-
}
|
|
988
996
|
if (highlightInsertedRows && insertedRowKeys.has(rowKey)) {
|
|
989
997
|
ctx.fillStyle = colors.insertedFill;
|
|
990
998
|
ctx.fillRect(x, y, cellWidth, cellHeight);
|
|
@@ -1009,6 +1017,10 @@ function paintGrid(options) {
|
|
|
1009
1017
|
ctx.fillStyle = annotation.color;
|
|
1010
1018
|
ctx.fillRect(x, y, cellWidth, cellHeight);
|
|
1011
1019
|
}
|
|
1020
|
+
if (isColumnDropTarget) {
|
|
1021
|
+
ctx.fillStyle = colors.columnDropTargetFill;
|
|
1022
|
+
ctx.fillRect(x, y, cellWidth, cellHeight);
|
|
1023
|
+
}
|
|
1012
1024
|
ctx.fillStyle = colors.grid;
|
|
1013
1025
|
if (!verticalBorderless && !(frameBorderless && columnIndex + colSpan >= columns.length)) {
|
|
1014
1026
|
ctx.fillRect(x + cellWidth - 1, y, 1, cellHeight);
|
|
@@ -1018,14 +1030,14 @@ function paintGrid(options) {
|
|
|
1018
1030
|
ctx.fillRect(x, y + cellHeight - 1, cellWidth, 1);
|
|
1019
1031
|
}
|
|
1020
1032
|
if (rowSpan > 1) {
|
|
1021
|
-
const mergedFill = 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);
|
|
1033
|
+
const mergedFill = isColumnDropTarget ? 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);
|
|
1022
1034
|
ctx.fillStyle = mergedFill;
|
|
1023
1035
|
for (let offset = 1; offset < rowSpan; offset += 1) {
|
|
1024
1036
|
ctx.fillRect(x, y + offset * rowHeight - 1, cellWidth, 2);
|
|
1025
1037
|
}
|
|
1026
1038
|
}
|
|
1027
1039
|
if (colSpan > 1 && !verticalBorderless) {
|
|
1028
|
-
const mergedFill = 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);
|
|
1040
|
+
const mergedFill = isColumnDropTarget ? 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);
|
|
1029
1041
|
ctx.fillStyle = mergedFill;
|
|
1030
1042
|
let offsetLeft = 0;
|
|
1031
1043
|
for (let offset = 1; offset < colSpan; offset += 1) {
|
|
@@ -1122,11 +1134,11 @@ function paintGrid(options) {
|
|
|
1122
1134
|
ctx.beginPath();
|
|
1123
1135
|
ctx.rect(x + 2, y + 1, Math.max(0, cellWidth - 4), cellHeight - 2);
|
|
1124
1136
|
ctx.clip();
|
|
1125
|
-
ctx.fillStyle = isAxisSelected && !isSelectedCell && !isRangeCell ? colors.axisSelectionText : cellStyle?.color ?? rowStyle?.color ?? colors.text;
|
|
1137
|
+
ctx.fillStyle = isColumnDropTarget ? colors.text : isAxisSelected && !isSelectedCell && !isRangeCell ? colors.axisSelectionText : cellStyle?.color ?? rowStyle?.color ?? colors.text;
|
|
1126
1138
|
ctx.font = createCellFont(bodyFontSize);
|
|
1127
1139
|
ctx.textBaseline = "alphabetic";
|
|
1128
1140
|
ctx.textAlign = column.align === "right" ? "right" : column.align === "center" ? "center" : "left";
|
|
1129
|
-
ctx.fillText(label, textX, y + cellHeight / 2 + cellBaselineOffset);
|
|
1141
|
+
ctx.fillText(ellipsizeText(ctx, label, Math.max(0, cellWidth - padding * 2)), textX, y + cellHeight / 2 + cellBaselineOffset);
|
|
1130
1142
|
ctx.restore();
|
|
1131
1143
|
}
|
|
1132
1144
|
}
|
|
@@ -1185,6 +1197,25 @@ function paintGrid(options) {
|
|
|
1185
1197
|
paintExtendedColumnSelection("scroll");
|
|
1186
1198
|
paintExtendedColumnSelection("left");
|
|
1187
1199
|
paintExtendedColumnSelection("right");
|
|
1200
|
+
const paintExtendedColumnDropTarget = (layer) => {
|
|
1201
|
+
if (!columnDropTarget) return;
|
|
1202
|
+
ctx.save();
|
|
1203
|
+
if (layer === "scroll") {
|
|
1204
|
+
ctx.beginPath();
|
|
1205
|
+
ctx.rect(leftFixedWidth, extensionTop, Math.max(0, rightFixedLeft - leftFixedWidth), extensionHeight);
|
|
1206
|
+
ctx.clip();
|
|
1207
|
+
}
|
|
1208
|
+
ctx.fillStyle = colors.columnDropTargetFill;
|
|
1209
|
+
for (let columnIndex = columnDropTarget.startIndex; columnIndex <= columnDropTarget.endIndex; columnIndex += 1) {
|
|
1210
|
+
if (layer === "scroll" ? columns[columnIndex]?.fixed !== void 0 : columns[columnIndex]?.fixed !== layer) continue;
|
|
1211
|
+
if (layer === "scroll" && (columnIndex < range.columnStart || columnIndex >= range.columnEnd)) continue;
|
|
1212
|
+
ctx.fillRect(getColumnX(columnIndex), extensionTop, metrics[columnIndex].width, extensionHeight);
|
|
1213
|
+
}
|
|
1214
|
+
ctx.restore();
|
|
1215
|
+
};
|
|
1216
|
+
paintExtendedColumnDropTarget("scroll");
|
|
1217
|
+
paintExtendedColumnDropTarget("left");
|
|
1218
|
+
paintExtendedColumnDropTarget("right");
|
|
1188
1219
|
if (!verticalBorderless) {
|
|
1189
1220
|
paintExtendedColumnLines("scroll");
|
|
1190
1221
|
paintExtendedColumnLines("left");
|
|
@@ -1206,11 +1237,12 @@ function paintGrid(options) {
|
|
|
1206
1237
|
ctx.fillRect(x, headerY, metric.width, headerHeight);
|
|
1207
1238
|
}
|
|
1208
1239
|
const isAxisSelected = selectedColumnKeys.has(columns[columnIndex].key);
|
|
1240
|
+
const isColumnDropTarget = Boolean(columnDropTarget && columnIndex >= columnDropTarget.startIndex && columnIndex <= columnDropTarget.endIndex);
|
|
1209
1241
|
if (isAxisSelected) {
|
|
1210
1242
|
ctx.fillStyle = colors.axisSelectionFill;
|
|
1211
1243
|
ctx.fillRect(x, headerY, metric.width, headerHeight);
|
|
1212
1244
|
}
|
|
1213
|
-
if (
|
|
1245
|
+
if (isColumnDropTarget) {
|
|
1214
1246
|
ctx.fillStyle = colors.columnDropTargetFill;
|
|
1215
1247
|
ctx.fillRect(x, headerY, metric.width, headerHeight);
|
|
1216
1248
|
}
|
|
@@ -1239,7 +1271,7 @@ function paintGrid(options) {
|
|
|
1239
1271
|
ctx.beginPath();
|
|
1240
1272
|
ctx.rect(x + 2, headerY + headerLeafTop + 1, Math.max(0, clipWidth - 4), headerLeafHeight - 2);
|
|
1241
1273
|
ctx.clip();
|
|
1242
|
-
ctx.fillStyle = isAxisSelected ? colors.axisSelectionText : colors.muted;
|
|
1274
|
+
ctx.fillStyle = isColumnDropTarget ? colors.muted : isAxisSelected ? colors.axisSelectionText : colors.muted;
|
|
1243
1275
|
ctx.textAlign = titleAlign === "right" ? "right" : titleAlign === "center" ? "center" : "left";
|
|
1244
1276
|
ctx.fillText(title, textX, headerY + headerLeafTop + headerLeafHeight / 2);
|
|
1245
1277
|
ctx.restore();
|
|
@@ -1398,6 +1430,11 @@ function resolveColumnDropIndex(sourceIndex, targetIndex, edge, columnCount) {
|
|
|
1398
1430
|
function resolveColumnDropPlacement(edge) {
|
|
1399
1431
|
return edge === "right" ? "after" : "before";
|
|
1400
1432
|
}
|
|
1433
|
+
function resolveColumnDropHighlightRange(target, edge, cells) {
|
|
1434
|
+
if (edge === "right") return { startIndex: target.startIndex, endIndex: target.endIndex };
|
|
1435
|
+
const previous = cells.find((cell) => cell.endIndex === target.startIndex - 1 && cell.level === target.level && cell.parentKey === target.parentKey);
|
|
1436
|
+
return previous ? { startIndex: previous.startIndex, endIndex: previous.endIndex } : { startIndex: target.startIndex, endIndex: target.endIndex };
|
|
1437
|
+
}
|
|
1401
1438
|
var ANNOTATION_COLORS = ["#f44336", "#ff7a45", "#f5a623", "#f2c94c", "#52c41a", "#13a8a8", "#1677ff", "#597ef7", "#9254de", "#eb2f96"];
|
|
1402
1439
|
var FALLBACK_HEIGHT = 480;
|
|
1403
1440
|
var EMPTY_BODY_HEIGHT = 240;
|
|
@@ -2277,7 +2314,7 @@ function TableInner({
|
|
|
2277
2314
|
rowHoverFill: readThemeColor(themeStyles, "--rvg-color-row-hover-fill", "#f6f9fc"),
|
|
2278
2315
|
editedFill: editedCellHighlightColor ?? readThemeColor(themeStyles, "--rvg-color-edited-fill", "#fff1b8"),
|
|
2279
2316
|
insertedFill: insertedRowHighlightColor ?? readThemeColor(themeStyles, "--rvg-color-inserted-fill", "#c8ead4"),
|
|
2280
|
-
columnDropTargetFill: readThemeColor(themeStyles, "--rvg-color-column-drop-target-fill", "#
|
|
2317
|
+
columnDropTargetFill: readThemeColor(themeStyles, "--rvg-color-column-drop-target-fill", "#e2edf9"),
|
|
2281
2318
|
stripe: stripedColor ?? readThemeColor(themeStyles, "--rvg-color-stripe", "#fafbfc")
|
|
2282
2319
|
};
|
|
2283
2320
|
const scroll = scrollRef.current;
|
|
@@ -3555,6 +3592,8 @@ function TableInner({
|
|
|
3555
3592
|
columnDragRef.current = null;
|
|
3556
3593
|
setResizeGuideX(null);
|
|
3557
3594
|
setResizeGuideTop(0);
|
|
3595
|
+
document.documentElement.classList.remove("rvg-is-dragging");
|
|
3596
|
+
event.currentTarget.style.cursor = "default";
|
|
3558
3597
|
}, []);
|
|
3559
3598
|
const clearColumnOrderPointerDrag = useCallback2((canvas) => {
|
|
3560
3599
|
columnOrderDragRef.current = null;
|
|
@@ -3636,7 +3675,11 @@ function TableInner({
|
|
|
3636
3675
|
fixed: targetColumn.fixed,
|
|
3637
3676
|
columnEdge
|
|
3638
3677
|
};
|
|
3639
|
-
|
|
3678
|
+
const compatibleHighlightCells = headerCells.filter((cell) => {
|
|
3679
|
+
const cellColumn = columns[cell.startIndex];
|
|
3680
|
+
return cellColumn && !cellColumn.rowSelection && !cellColumn.rowDragHandle && !cellColumn.rowNumber && cellColumn.fixed === targetColumn.fixed;
|
|
3681
|
+
});
|
|
3682
|
+
setColumnDropTarget(resolveColumnDropHighlightRange(targetCell, columnEdge, compatibleHighlightCells));
|
|
3640
3683
|
setDragGuide(columnEdge === "right" ? targetLeft + targetWidth : targetLeft, headerRowOffsets[sourceCell.level] ?? 0);
|
|
3641
3684
|
}, [columns, getHeaderCellLeft, getHeaderCellWidth, headerCells, headerRowOffsets, hideDragTooltips, locateColumn, locateHeaderCell, setDragGuide]);
|
|
3642
3685
|
const finishColumnOrderPointerDrag = useCallback2((event, apply) => {
|
|
@@ -3781,6 +3824,34 @@ function TableInner({
|
|
|
3781
3824
|
const textTop = rowTop + 8;
|
|
3782
3825
|
return localX >= textLeft - 4 && localX <= textLeft + textWidth + 4 && localY >= textTop - 2 && localY <= textTop + 18;
|
|
3783
3826
|
}, [columnDraggable, fixedHeader, getHeaderCellLeft, getHeaderCellWidth, headerActionSlotWidth, headerRowOffsets]);
|
|
3827
|
+
const locateCustomHeaderTooltip = useCallback2((clientX, clientY, columnIndex) => {
|
|
3828
|
+
const root = rootRef.current;
|
|
3829
|
+
const canvas = canvasRef.current;
|
|
3830
|
+
if (!root || !canvas || columnIndex < 0) return null;
|
|
3831
|
+
const canvasRect = canvas.getBoundingClientRect();
|
|
3832
|
+
const targets = root.querySelectorAll(".rvg-header-title [data-rvg-tooltip]");
|
|
3833
|
+
for (const target of targets) {
|
|
3834
|
+
const rect = target.getBoundingClientRect();
|
|
3835
|
+
if (clientX < rect.left || clientX > rect.right || clientY < rect.top || clientY > rect.bottom) continue;
|
|
3836
|
+
const label = target.dataset.rvgTooltip?.trim();
|
|
3837
|
+
if (!label) return false;
|
|
3838
|
+
const visibleText = target.textContent?.replace(/\s+/g, " ").trim() ?? "";
|
|
3839
|
+
const candidates = [target, ...target.querySelectorAll("*")];
|
|
3840
|
+
const truncated = candidates.some((candidate) => candidate.scrollWidth > candidate.clientWidth + 1 || candidate.scrollHeight > candidate.clientHeight + 1);
|
|
3841
|
+
if (!truncated && label.replace(/\s+/g, " ").trim() === visibleText) return false;
|
|
3842
|
+
const rawLeft = rect.left - canvasRect.left;
|
|
3843
|
+
return {
|
|
3844
|
+
key: `content:${columnIndex}:${label}:${Math.round(rawLeft)}:${Math.round(rect.top - canvasRect.top)}`,
|
|
3845
|
+
columnIndex,
|
|
3846
|
+
action: "content",
|
|
3847
|
+
left: Math.max(8, Math.min(rawLeft, Math.max(8, viewport.width - 328))),
|
|
3848
|
+
top: rect.bottom - canvasRect.top + 4,
|
|
3849
|
+
label,
|
|
3850
|
+
placement: "below"
|
|
3851
|
+
};
|
|
3852
|
+
}
|
|
3853
|
+
return null;
|
|
3854
|
+
}, [viewport.width]);
|
|
3784
3855
|
const headerTooltip = (() => {
|
|
3785
3856
|
if (!visibleHeaderTooltip) return null;
|
|
3786
3857
|
return visibleHeaderTooltip;
|
|
@@ -4106,23 +4177,26 @@ function TableInner({
|
|
|
4106
4177
|
if (column.renderHeader) {
|
|
4107
4178
|
const visibleActions = getVisibleHeaderActions(column, metrics[columnIndex].width, columnDraggable, measureHeaderTitleWidth(columnIndex), headerActionSlotWidth);
|
|
4108
4179
|
const actionWidth = (Number(visibleActions.drag) + Number(visibleActions.filter) + Number(visibleActions.sort)) * headerActionSlotWidth;
|
|
4180
|
+
const isHeaderHovered = hoveredHeaderColumnIndex === columnIndex;
|
|
4109
4181
|
return /* @__PURE__ */ jsx7(
|
|
4110
4182
|
"div",
|
|
4111
4183
|
{
|
|
4112
|
-
className: `rvg-header-title is-custom${isAxisSelected ? " is-axis-selected" : ""}${isDropTarget ? " is-drop-target" : ""}`,
|
|
4184
|
+
className: `rvg-header-title is-custom${isHeaderHovered ? " is-header-hovered" : ""}${isAxisSelected ? " is-axis-selected" : ""}${isDropTarget ? " is-drop-target" : ""}`,
|
|
4113
4185
|
"data-level": headerDepth - 1,
|
|
4114
4186
|
"data-measure-key": column.key,
|
|
4115
4187
|
style: {
|
|
4116
4188
|
left,
|
|
4117
4189
|
top: leafTop,
|
|
4118
|
-
width:
|
|
4190
|
+
width: metrics[columnIndex].width,
|
|
4119
4191
|
height: headerLeafHeight,
|
|
4192
|
+
"--rvg-header-action-width": `${actionWidth}px`,
|
|
4120
4193
|
justifyContent: column.align === "right" ? "flex-end" : column.align === "center" ? "center" : "flex-start",
|
|
4121
4194
|
textAlign: column.align === "right" ? "right" : column.align === "center" ? "center" : "left"
|
|
4122
4195
|
},
|
|
4123
4196
|
children: /* @__PURE__ */ jsx7(
|
|
4124
4197
|
"span",
|
|
4125
4198
|
{
|
|
4199
|
+
style: { width: "100%" },
|
|
4126
4200
|
ref: (node) => {
|
|
4127
4201
|
if (node) {
|
|
4128
4202
|
customHeaderContentRefs.current.set(column.key, node);
|
|
@@ -4489,16 +4563,19 @@ function TableInner({
|
|
|
4489
4563
|
const hoveredAction = inLeafHeader ? locateHeaderAction(event.clientX, columnIndex) : null;
|
|
4490
4564
|
const hoveredDragHandle = Boolean(hoveredHeaderCell && locateHeaderCellDragHandle(event.clientX, hoveredHeaderCell));
|
|
4491
4565
|
const hoveredDragColumnIndex = hoveredHeaderCell?.startIndex ?? columnIndex;
|
|
4492
|
-
const
|
|
4493
|
-
const
|
|
4494
|
-
const
|
|
4566
|
+
const customHeaderTooltipMatch = inHeader && !hoveredAction && !hoveredDragHandle ? locateCustomHeaderTooltip(event.clientX, event.clientY, columnIndex) : null;
|
|
4567
|
+
const hoveredContentTooltip = customHeaderTooltipMatch || null;
|
|
4568
|
+
const hoveredCustomContent = customHeaderTooltipMatch !== null;
|
|
4569
|
+
const hoveredTitle = inHeader && !hoveredAction && !hoveredDragHandle && !hoveredCustomContent && hoveredHeaderCell && Boolean(hoveredHeaderCell.column.title) && isPointerOnHeaderTitle(event.clientX, event.clientY, hoveredHeaderCell) && (tooltipConfig.header || hoveredHeaderCell.leaf && isHeaderTitleTruncated(hoveredHeaderCell.startIndex));
|
|
4570
|
+
const nextHover = hoveredAction ? { columnIndex, action: hoveredAction } : hoveredDragHandle ? { columnIndex: hoveredDragColumnIndex, action: "drag" } : hoveredContentTooltip ? { columnIndex, action: "content" } : hoveredTitle ? { columnIndex: hoveredHeaderCell.startIndex, action: "title" } : null;
|
|
4571
|
+
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
4572
|
const previousHover = hoveredHeaderActionRef.current;
|
|
4496
4573
|
if (previousHover?.columnIndex !== nextHover?.columnIndex || previousHover?.action !== nextHover?.action) {
|
|
4497
4574
|
hoveredHeaderActionRef.current = nextHover;
|
|
4498
4575
|
setHoveredHeaderAction(nextHover);
|
|
4499
|
-
showHeaderTooltipAfterDelay(nextTooltip);
|
|
4500
4576
|
scheduleDraw();
|
|
4501
4577
|
}
|
|
4578
|
+
showHeaderTooltipAfterDelay(nextTooltip);
|
|
4502
4579
|
if (inHeader) {
|
|
4503
4580
|
if (hoveredRowIndexRef.current !== null) {
|
|
4504
4581
|
hoveredRowIndexRef.current = null;
|
|
@@ -4550,12 +4627,12 @@ function TableInner({
|
|
|
4550
4627
|
if (!isInsideText) {
|
|
4551
4628
|
showCellTooltipAfterDelay(null);
|
|
4552
4629
|
} else {
|
|
4553
|
-
const placement =
|
|
4630
|
+
const placement = cellTop + rowHeight + 36 > renderHeight ? "above" : "below";
|
|
4554
4631
|
const nextTooltip2 = {
|
|
4555
4632
|
rowIndex: cell.rowIndex,
|
|
4556
4633
|
columnIndex: cell.columnIndex,
|
|
4557
|
-
left:
|
|
4558
|
-
top: cellTop + rowHeight
|
|
4634
|
+
left: Math.max(8, Math.min(textLeft, Math.max(8, viewport.width - 328))),
|
|
4635
|
+
top: placement === "below" ? cellTop + rowHeight + 4 : cellTop - 4,
|
|
4559
4636
|
label,
|
|
4560
4637
|
placement
|
|
4561
4638
|
};
|
|
@@ -4584,6 +4661,8 @@ function TableInner({
|
|
|
4584
4661
|
}
|
|
4585
4662
|
},
|
|
4586
4663
|
onPointerDown: (event) => {
|
|
4664
|
+
handleColumnPointerDown(event);
|
|
4665
|
+
if (columnDragRef.current) return;
|
|
4587
4666
|
const headerDragCell = columnDraggable ? locateHeaderCell(event.clientX, event.clientY) : null;
|
|
4588
4667
|
const columnIndex = locateColumn(event.clientX);
|
|
4589
4668
|
const rowDragHandle = rowDraggable && columnIndex >= 0 && Boolean(columns[columnIndex].rowDragHandle) && locateRow(event.clientY) >= 0;
|
|
@@ -4592,8 +4671,7 @@ function TableInner({
|
|
|
4592
4671
|
document.documentElement.classList.add("rvg-is-dragging");
|
|
4593
4672
|
event.currentTarget.style.cursor = "move";
|
|
4594
4673
|
}
|
|
4595
|
-
|
|
4596
|
-
if (!columnDragRef.current) handleColumnOrderPointerDown(event);
|
|
4674
|
+
handleColumnOrderPointerDown(event);
|
|
4597
4675
|
beginRangeDrag(event);
|
|
4598
4676
|
},
|
|
4599
4677
|
onPointerMove: (event) => {
|
|
@@ -4651,6 +4729,12 @@ function TableInner({
|
|
|
4651
4729
|
}
|
|
4652
4730
|
const cell = locateCell(event.clientX, event.clientY);
|
|
4653
4731
|
if (!cell) {
|
|
4732
|
+
const localX = event.clientX - rect.left;
|
|
4733
|
+
const trailingRowIndex = trailingColumnBorderLeft !== null && localX > trailingColumnBorderLeft ? locateRow(event.clientY) : -1;
|
|
4734
|
+
if (trailingRowIndex >= 0 && rowSelection) {
|
|
4735
|
+
selectRow(trailingRowIndex, event);
|
|
4736
|
+
return;
|
|
4737
|
+
}
|
|
4654
4738
|
clickedCellRef.current = null;
|
|
4655
4739
|
setSelectionRange(null);
|
|
4656
4740
|
setSelection(null);
|