@lensui/lens-table 0.1.74 → 0.1.76
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 +61 -14
- package/dist/index.css +1 -0
- package/dist/index.js +61 -14
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -335,11 +335,15 @@ var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
|
335
335
|
function SearchableChoiceEditor({ value, options, allowCustomValue, maxDropdownHeight, style, labels, onChange, onCommit, onCancel }) {
|
|
336
336
|
const editorRef = (0, import_react2.useRef)(null);
|
|
337
337
|
const popupRef = (0, import_react2.useRef)(null);
|
|
338
|
+
const activeOptionRef = (0, import_react2.useRef)(null);
|
|
338
339
|
const originalValueRef = (0, import_react2.useRef)(value);
|
|
339
340
|
const listboxId = (0, import_react2.useId)();
|
|
340
341
|
const originalValue = originalValueRef.current;
|
|
341
342
|
const [inputValue, setInputValue] = (0, import_react2.useState)(value);
|
|
342
|
-
const [activeIndex, setActiveIndex] = (0, import_react2.useState)(
|
|
343
|
+
const [activeIndex, setActiveIndex] = (0, import_react2.useState)(() => {
|
|
344
|
+
const selectedIndex = options.findIndex((option) => option.value === value);
|
|
345
|
+
return selectedIndex >= 0 ? selectedIndex : 0;
|
|
346
|
+
});
|
|
343
347
|
const [popupStyle, setPopupStyle] = (0, import_react2.useState)({});
|
|
344
348
|
const filteredOptions = (0, import_react2.useMemo)(() => {
|
|
345
349
|
const query = inputValue.trim().toLocaleLowerCase();
|
|
@@ -378,6 +382,9 @@ function SearchableChoiceEditor({ value, options, allowCustomValue, maxDropdownH
|
|
|
378
382
|
window.removeEventListener("scroll", positionPopup, true);
|
|
379
383
|
};
|
|
380
384
|
}, [maxDropdownHeight]);
|
|
385
|
+
(0, import_react2.useLayoutEffect)(() => {
|
|
386
|
+
activeOptionRef.current?.scrollIntoView?.({ block: "nearest", inline: "nearest" });
|
|
387
|
+
}, [activeIndex, filteredOptions, popupStyle]);
|
|
381
388
|
(0, import_react2.useEffect)(() => {
|
|
382
389
|
const handleOutsidePointer = (event) => {
|
|
383
390
|
const target = event.target;
|
|
@@ -432,6 +439,7 @@ function SearchableChoiceEditor({ value, options, allowCustomValue, maxDropdownH
|
|
|
432
439
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_portal.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { ref: popupRef, id: listboxId, role: "listbox", className: "rvg-choice-content rvg-searchable-choice-content", style: popupStyle, children: filteredOptions.map((option, index) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
433
440
|
"button",
|
|
434
441
|
{
|
|
442
|
+
ref: index === activeIndex ? activeOptionRef : void 0,
|
|
435
443
|
type: "button",
|
|
436
444
|
role: "option",
|
|
437
445
|
"aria-selected": option.value === originalValue,
|
|
@@ -1106,6 +1114,7 @@ function paintGrid(options) {
|
|
|
1106
1114
|
const headerLeafTop = options.headerLeafTop ?? 0;
|
|
1107
1115
|
const headerLeafHeight = options.headerLeafHeight ?? headerHeight;
|
|
1108
1116
|
const colors = { ...COLORS, ...options.colors };
|
|
1117
|
+
const resolveColor = options.resolveColor ?? ((color) => color);
|
|
1109
1118
|
const getAxisSelectionFill = (rowIndex, columnKey) => selectedColumnKeys.has(columnKey) && striped && rowIndex % 2 === 1 ? colors.axisSelectionStripeFill : colors.axisSelectionFill;
|
|
1110
1119
|
const bodyTop = options.bodyTop ?? headerHeight;
|
|
1111
1120
|
const getCellSpan = (rowIndex, columnIndex) => options.cellSpans.get(getCellCoordKey(rowIndex, columnIndex));
|
|
@@ -1169,8 +1178,9 @@ function paintGrid(options) {
|
|
|
1169
1178
|
const trailingRowStyle = options.rowStyle?.(row, rowIndex);
|
|
1170
1179
|
const y = bodyTop + rowIndex * rowHeight - scrollTop + getRowDragOffset(rowIndex);
|
|
1171
1180
|
const paintTrailingLayer = (fill) => {
|
|
1172
|
-
|
|
1173
|
-
|
|
1181
|
+
const resolvedFill = resolveColor(fill);
|
|
1182
|
+
if (!resolvedFill) return;
|
|
1183
|
+
ctx.fillStyle = resolvedFill;
|
|
1174
1184
|
ctx.fillRect(trailingBlankStart, y, width - trailingBlankStart, rowHeight);
|
|
1175
1185
|
};
|
|
1176
1186
|
if (striped && rowIndex % 2 === 1) paintTrailingLayer(colors.stripe);
|
|
@@ -1213,8 +1223,11 @@ function paintGrid(options) {
|
|
|
1213
1223
|
ctx.fillRect(x, y, cellWidth, cellHeight);
|
|
1214
1224
|
}
|
|
1215
1225
|
if (rowStyle?.backgroundColor) {
|
|
1216
|
-
|
|
1217
|
-
|
|
1226
|
+
const rowBackground = resolveColor(rowStyle.backgroundColor);
|
|
1227
|
+
if (rowBackground) {
|
|
1228
|
+
ctx.fillStyle = rowBackground;
|
|
1229
|
+
ctx.fillRect(x, y, cellWidth, cellHeight);
|
|
1230
|
+
}
|
|
1218
1231
|
}
|
|
1219
1232
|
if (isAxisSelected) {
|
|
1220
1233
|
ctx.fillStyle = getAxisSelectionFill(rowIndex, column.key);
|
|
@@ -1233,8 +1246,11 @@ function paintGrid(options) {
|
|
|
1233
1246
|
const rawValue = column.dataIndex === void 0 ? void 0 : row[column.dataIndex];
|
|
1234
1247
|
const cellStyle = column.cellStyle?.(rawValue, row, rowIndex);
|
|
1235
1248
|
if (!isSelectedCell && !isRangeCell && cellStyle?.backgroundColor) {
|
|
1236
|
-
|
|
1237
|
-
|
|
1249
|
+
const cellBackground = resolveColor(cellStyle.backgroundColor);
|
|
1250
|
+
if (cellBackground) {
|
|
1251
|
+
ctx.fillStyle = cellBackground;
|
|
1252
|
+
ctx.fillRect(x, y, cellWidth, cellHeight);
|
|
1253
|
+
}
|
|
1238
1254
|
}
|
|
1239
1255
|
if (highlightEditedCells && !insertedRowKeys.has(rowKey) && !isSelectedCell && editedCellKeys.has(`${typeof rowKey}:${String(rowKey)}\0${column.key}`)) {
|
|
1240
1256
|
ctx.fillStyle = colors.editedFill;
|
|
@@ -1245,8 +1261,11 @@ function paintGrid(options) {
|
|
|
1245
1261
|
ctx.fillRect(x, y, cellWidth, cellHeight);
|
|
1246
1262
|
}
|
|
1247
1263
|
if (annotation?.type === "background") {
|
|
1248
|
-
|
|
1249
|
-
|
|
1264
|
+
const annotationBackground = resolveColor(annotation.color);
|
|
1265
|
+
if (annotationBackground) {
|
|
1266
|
+
ctx.fillStyle = annotationBackground;
|
|
1267
|
+
ctx.fillRect(x, y, cellWidth, cellHeight);
|
|
1268
|
+
}
|
|
1250
1269
|
}
|
|
1251
1270
|
if (isColumnDropTarget) {
|
|
1252
1271
|
ctx.fillStyle = isAxisSelected ? getAxisSelectionFill(rowIndex, column.key) : colors.columnDropTargetFill;
|
|
@@ -1262,14 +1281,14 @@ function paintGrid(options) {
|
|
|
1262
1281
|
}
|
|
1263
1282
|
if (rowSpan > 1) {
|
|
1264
1283
|
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);
|
|
1265
|
-
ctx.fillStyle = mergedFill;
|
|
1284
|
+
ctx.fillStyle = resolveColor(mergedFill) ?? colors.background;
|
|
1266
1285
|
for (let offset = 1; offset < rowSpan; offset += 1) {
|
|
1267
1286
|
ctx.fillRect(x, y + offset * rowHeight - 1, cellWidth, 2);
|
|
1268
1287
|
}
|
|
1269
1288
|
}
|
|
1270
1289
|
if (colSpan > 1 && !verticalBorderless) {
|
|
1271
1290
|
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);
|
|
1272
|
-
ctx.fillStyle = mergedFill;
|
|
1291
|
+
ctx.fillStyle = resolveColor(mergedFill) ?? colors.background;
|
|
1273
1292
|
let offsetLeft = 0;
|
|
1274
1293
|
for (let offset = 1; offset < colSpan; offset += 1) {
|
|
1275
1294
|
offsetLeft += metrics[columnIndex + offset - 1]?.width ?? 0;
|
|
@@ -1365,7 +1384,8 @@ function paintGrid(options) {
|
|
|
1365
1384
|
ctx.beginPath();
|
|
1366
1385
|
ctx.rect(x + 2, y + 1, Math.max(0, cellWidth - 4), cellHeight - 2);
|
|
1367
1386
|
ctx.clip();
|
|
1368
|
-
|
|
1387
|
+
const textColor = isAxisSelected ? colors.axisSelectionText : isColumnDropTarget ? colors.text : resolveColor(cellStyle?.color ?? rowStyle?.color) ?? colors.text;
|
|
1388
|
+
ctx.fillStyle = textColor;
|
|
1369
1389
|
ctx.font = createCellFont(bodyFontSize);
|
|
1370
1390
|
ctx.textBaseline = "alphabetic";
|
|
1371
1391
|
ctx.textAlign = column.align === "right" ? "right" : column.align === "center" ? "center" : "left";
|
|
@@ -1375,7 +1395,7 @@ function paintGrid(options) {
|
|
|
1375
1395
|
}
|
|
1376
1396
|
if (annotation?.type === "corner") {
|
|
1377
1397
|
const cornerTop = y - 1;
|
|
1378
|
-
ctx.fillStyle = annotation.color;
|
|
1398
|
+
ctx.fillStyle = resolveColor(annotation.color) ?? colors.text;
|
|
1379
1399
|
ctx.beginPath();
|
|
1380
1400
|
ctx.moveTo(x + cellWidth - 10, cornerTop);
|
|
1381
1401
|
ctx.lineTo(x + cellWidth, cornerTop);
|
|
@@ -1761,6 +1781,18 @@ function readThemePixel(styles, name, fallback) {
|
|
|
1761
1781
|
const value = Number.parseFloat(styles.getPropertyValue(name));
|
|
1762
1782
|
return Number.isFinite(value) && value > 0 ? value : fallback;
|
|
1763
1783
|
}
|
|
1784
|
+
function resolveCanvasColor(styles, color) {
|
|
1785
|
+
if (!color) return void 0;
|
|
1786
|
+
let resolved = color.trim();
|
|
1787
|
+
for (let depth = 0; depth < 8; depth += 1) {
|
|
1788
|
+
const variable = resolved.match(/^var\(\s*(--[^,\s)]+)\s*(?:,\s*(.+))?\)$/);
|
|
1789
|
+
if (!variable) return resolved || void 0;
|
|
1790
|
+
const value = styles.getPropertyValue(variable[1]).trim();
|
|
1791
|
+
resolved = value || variable[2]?.trim() || "";
|
|
1792
|
+
if (!resolved) return void 0;
|
|
1793
|
+
}
|
|
1794
|
+
return void 0;
|
|
1795
|
+
}
|
|
1764
1796
|
function getDefaultRowKey(row, index) {
|
|
1765
1797
|
const id = row.id;
|
|
1766
1798
|
return typeof id === "string" || typeof id === "number" ? id : index;
|
|
@@ -1997,6 +2029,7 @@ function TableInner({
|
|
|
1997
2029
|
const rootRef = (0, import_react8.useRef)(null);
|
|
1998
2030
|
const frameRef = (0, import_react8.useRef)(null);
|
|
1999
2031
|
const textFrameRef = (0, import_react8.useRef)(null);
|
|
2032
|
+
const textLayoutScrollTopRef = (0, import_react8.useRef)(0);
|
|
2000
2033
|
const toastTimerRef = (0, import_react8.useRef)(null);
|
|
2001
2034
|
const headerTooltipTimerRef = (0, import_react8.useRef)(null);
|
|
2002
2035
|
const cellTooltipTimerRef = (0, import_react8.useRef)(null);
|
|
@@ -2581,7 +2614,7 @@ function TableInner({
|
|
|
2581
2614
|
const scroll = scrollRef.current;
|
|
2582
2615
|
const rowScrollTop = fixedHeader ? scroll.top : Math.max(0, scroll.top - bodyTop);
|
|
2583
2616
|
const range = isVirtualized ? getViewportRange(scroll.left, rowScrollTop, viewport.width, bodyViewportHeight, rows.length, rowHeight, metrics, virtualOverscan) : { rowStart: 0, rowEnd: rows.length, columnStart: 0, columnEnd: columns.length };
|
|
2584
|
-
paintGrid({ context, width: viewport.width, height: renderHeight, pixelRatio: ratio, scrollLeft: scroll.left, scrollTop: scroll.top, rowHeight, bodyFontSize, headerActionSlotWidth, headerHeight, headerLeafTop, headerLeafHeight, bodyTop, suppressLastRowBottomBorder: bottomSummaryHeight > 0, suppressFrameBottomBorder: bottomSummaryHeight > 0, fixedHeader, verticalBorderless: !hasVerticalBorders, horizontalBorderless, frameBorderless, extendVerticalGridLines: !autoHeight, striped: hasStripedRows, columnDraggable, sortState, filterValues, hoveredHeaderAction: hoveredHeaderActionRef.current, rows, rowStyle, columns, metrics, range, selection, editing, hoveredRowIndex: hoveredRowIndexRef.current, selectionRange, selectedRowKeys: selectedRowKeySet, rowSelectionMode, selectedColumnKeys: selectedColumnKeySet, cellSpans: cellSpanLookup.covered, maxRowSpan: cellSpanLookup.maxRowSpan, highlightEditedCells: highlightsEditedCells, highlightInsertedRows: highlightsInsertedRows, insertedRowKeys: insertedRowKeySet, editedCellKeys, cellAnnotations, getRowKey, rowDragPreview, columnDropTarget, colors: themeColors });
|
|
2617
|
+
paintGrid({ context, width: viewport.width, height: renderHeight, pixelRatio: ratio, scrollLeft: scroll.left, scrollTop: scroll.top, rowHeight, bodyFontSize, headerActionSlotWidth, headerHeight, headerLeafTop, headerLeafHeight, bodyTop, suppressLastRowBottomBorder: bottomSummaryHeight > 0, suppressFrameBottomBorder: bottomSummaryHeight > 0, fixedHeader, verticalBorderless: !hasVerticalBorders, horizontalBorderless, frameBorderless, extendVerticalGridLines: !autoHeight, striped: hasStripedRows, columnDraggable, sortState, filterValues, hoveredHeaderAction: hoveredHeaderActionRef.current, rows, rowStyle, columns, metrics, range, selection, editing, hoveredRowIndex: hoveredRowIndexRef.current, selectionRange, selectedRowKeys: selectedRowKeySet, rowSelectionMode, selectedColumnKeys: selectedColumnKeySet, cellSpans: cellSpanLookup.covered, maxRowSpan: cellSpanLookup.maxRowSpan, highlightEditedCells: highlightsEditedCells, highlightInsertedRows: highlightsInsertedRows, insertedRowKeys: insertedRowKeySet, editedCellKeys, cellAnnotations, getRowKey, rowDragPreview, columnDropTarget, resolveColor: (color) => resolveCanvasColor(themeStyles, color), colors: themeColors });
|
|
2585
2618
|
}, [autoHeight, bodyTop, bodyViewportHeight, bottomSummaryHeight, cellAnnotations, cellSpanLookup, columnDragPreview, columnDraggable, columnDropTarget, columns, editedCellHighlightColor, editedCellKeys, editing, renderHeight, filterValues, fixedHeader, frameBorderless, getRowKey, hasStripedRows, hasVerticalBorders, headerActionSlotWidth, headerDepth, headerHeight, headerLeafHeight, headerLeafTop, horizontalBorderless, highlightsEditedCells, highlightsInsertedRows, insertedRowHighlightColor, insertedRowKeySet, isVirtualized, metrics, rowDragPreview, rowHeight, rowSelectionMode, rowStyle, rows, selectedColumnKeySet, selectedRowKeySet, selection, selectionRange, sortState, stripedColor, viewport.width, virtualOverscan]);
|
|
2586
2619
|
const scheduleDraw = (0, import_react8.useCallback)(() => {
|
|
2587
2620
|
if (frameRef.current === null) frameRef.current = requestAnimationFrame(draw);
|
|
@@ -3034,6 +3067,13 @@ function TableInner({
|
|
|
3034
3067
|
horizontalScrollbarDragRef.current = null;
|
|
3035
3068
|
showCustomScrollbar("horizontal");
|
|
3036
3069
|
}, [showCustomScrollbar]);
|
|
3070
|
+
(0, import_react8.useLayoutEffect)(() => {
|
|
3071
|
+
textLayoutScrollTopRef.current = scrollPosition.top;
|
|
3072
|
+
const clips = rootRef.current?.querySelectorAll(".rvg-body-text-clip");
|
|
3073
|
+
clips?.forEach((clip) => {
|
|
3074
|
+
clip.style.transform = "";
|
|
3075
|
+
});
|
|
3076
|
+
}, [scrollPosition.top]);
|
|
3037
3077
|
const handleScroll = (0, import_react8.useCallback)(() => {
|
|
3038
3078
|
const element = scrollerRef.current;
|
|
3039
3079
|
if (!element) return;
|
|
@@ -3041,6 +3081,13 @@ function TableInner({
|
|
|
3041
3081
|
const scrollDeltaX = element.scrollLeft - previousScroll.left;
|
|
3042
3082
|
const scrollDeltaY = element.scrollTop - previousScroll.top;
|
|
3043
3083
|
scrollRef.current = { left: element.scrollLeft, top: element.scrollTop };
|
|
3084
|
+
const textDeltaY = element.scrollTop - textLayoutScrollTopRef.current;
|
|
3085
|
+
if (textDeltaY !== 0) {
|
|
3086
|
+
const clips = rootRef.current?.querySelectorAll(".rvg-body-text-clip");
|
|
3087
|
+
clips?.forEach((clip) => {
|
|
3088
|
+
clip.style.transform = `translate3d(0, ${-textDeltaY}px, 0)`;
|
|
3089
|
+
});
|
|
3090
|
+
}
|
|
3044
3091
|
syncSelectionEdgeTarget(element.scrollLeft, element.scrollTop);
|
|
3045
3092
|
const focus = selectionFocusRef.current;
|
|
3046
3093
|
if (focus && selection && !selectionRange) {
|
package/dist/index.css
CHANGED
package/dist/index.js
CHANGED
|
@@ -305,11 +305,15 @@ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
|
305
305
|
function SearchableChoiceEditor({ value, options, allowCustomValue, maxDropdownHeight, style, labels, onChange, onCommit, onCancel }) {
|
|
306
306
|
const editorRef = useRef(null);
|
|
307
307
|
const popupRef = useRef(null);
|
|
308
|
+
const activeOptionRef = useRef(null);
|
|
308
309
|
const originalValueRef = useRef(value);
|
|
309
310
|
const listboxId = useId2();
|
|
310
311
|
const originalValue = originalValueRef.current;
|
|
311
312
|
const [inputValue, setInputValue] = useState(value);
|
|
312
|
-
const [activeIndex, setActiveIndex] = useState(
|
|
313
|
+
const [activeIndex, setActiveIndex] = useState(() => {
|
|
314
|
+
const selectedIndex = options.findIndex((option) => option.value === value);
|
|
315
|
+
return selectedIndex >= 0 ? selectedIndex : 0;
|
|
316
|
+
});
|
|
313
317
|
const [popupStyle, setPopupStyle] = useState({});
|
|
314
318
|
const filteredOptions = useMemo(() => {
|
|
315
319
|
const query = inputValue.trim().toLocaleLowerCase();
|
|
@@ -348,6 +352,9 @@ function SearchableChoiceEditor({ value, options, allowCustomValue, maxDropdownH
|
|
|
348
352
|
window.removeEventListener("scroll", positionPopup, true);
|
|
349
353
|
};
|
|
350
354
|
}, [maxDropdownHeight]);
|
|
355
|
+
useLayoutEffect(() => {
|
|
356
|
+
activeOptionRef.current?.scrollIntoView?.({ block: "nearest", inline: "nearest" });
|
|
357
|
+
}, [activeIndex, filteredOptions, popupStyle]);
|
|
351
358
|
useEffect(() => {
|
|
352
359
|
const handleOutsidePointer = (event) => {
|
|
353
360
|
const target = event.target;
|
|
@@ -402,6 +409,7 @@ function SearchableChoiceEditor({ value, options, allowCustomValue, maxDropdownH
|
|
|
402
409
|
/* @__PURE__ */ jsx3(Portal, { children: /* @__PURE__ */ jsx3("div", { ref: popupRef, id: listboxId, role: "listbox", className: "rvg-choice-content rvg-searchable-choice-content", style: popupStyle, children: filteredOptions.map((option, index) => /* @__PURE__ */ jsxs3(
|
|
403
410
|
"button",
|
|
404
411
|
{
|
|
412
|
+
ref: index === activeIndex ? activeOptionRef : void 0,
|
|
405
413
|
type: "button",
|
|
406
414
|
role: "option",
|
|
407
415
|
"aria-selected": option.value === originalValue,
|
|
@@ -1076,6 +1084,7 @@ function paintGrid(options) {
|
|
|
1076
1084
|
const headerLeafTop = options.headerLeafTop ?? 0;
|
|
1077
1085
|
const headerLeafHeight = options.headerLeafHeight ?? headerHeight;
|
|
1078
1086
|
const colors = { ...COLORS, ...options.colors };
|
|
1087
|
+
const resolveColor = options.resolveColor ?? ((color) => color);
|
|
1079
1088
|
const getAxisSelectionFill = (rowIndex, columnKey) => selectedColumnKeys.has(columnKey) && striped && rowIndex % 2 === 1 ? colors.axisSelectionStripeFill : colors.axisSelectionFill;
|
|
1080
1089
|
const bodyTop = options.bodyTop ?? headerHeight;
|
|
1081
1090
|
const getCellSpan = (rowIndex, columnIndex) => options.cellSpans.get(getCellCoordKey(rowIndex, columnIndex));
|
|
@@ -1139,8 +1148,9 @@ function paintGrid(options) {
|
|
|
1139
1148
|
const trailingRowStyle = options.rowStyle?.(row, rowIndex);
|
|
1140
1149
|
const y = bodyTop + rowIndex * rowHeight - scrollTop + getRowDragOffset(rowIndex);
|
|
1141
1150
|
const paintTrailingLayer = (fill) => {
|
|
1142
|
-
|
|
1143
|
-
|
|
1151
|
+
const resolvedFill = resolveColor(fill);
|
|
1152
|
+
if (!resolvedFill) return;
|
|
1153
|
+
ctx.fillStyle = resolvedFill;
|
|
1144
1154
|
ctx.fillRect(trailingBlankStart, y, width - trailingBlankStart, rowHeight);
|
|
1145
1155
|
};
|
|
1146
1156
|
if (striped && rowIndex % 2 === 1) paintTrailingLayer(colors.stripe);
|
|
@@ -1183,8 +1193,11 @@ function paintGrid(options) {
|
|
|
1183
1193
|
ctx.fillRect(x, y, cellWidth, cellHeight);
|
|
1184
1194
|
}
|
|
1185
1195
|
if (rowStyle?.backgroundColor) {
|
|
1186
|
-
|
|
1187
|
-
|
|
1196
|
+
const rowBackground = resolveColor(rowStyle.backgroundColor);
|
|
1197
|
+
if (rowBackground) {
|
|
1198
|
+
ctx.fillStyle = rowBackground;
|
|
1199
|
+
ctx.fillRect(x, y, cellWidth, cellHeight);
|
|
1200
|
+
}
|
|
1188
1201
|
}
|
|
1189
1202
|
if (isAxisSelected) {
|
|
1190
1203
|
ctx.fillStyle = getAxisSelectionFill(rowIndex, column.key);
|
|
@@ -1203,8 +1216,11 @@ function paintGrid(options) {
|
|
|
1203
1216
|
const rawValue = column.dataIndex === void 0 ? void 0 : row[column.dataIndex];
|
|
1204
1217
|
const cellStyle = column.cellStyle?.(rawValue, row, rowIndex);
|
|
1205
1218
|
if (!isSelectedCell && !isRangeCell && cellStyle?.backgroundColor) {
|
|
1206
|
-
|
|
1207
|
-
|
|
1219
|
+
const cellBackground = resolveColor(cellStyle.backgroundColor);
|
|
1220
|
+
if (cellBackground) {
|
|
1221
|
+
ctx.fillStyle = cellBackground;
|
|
1222
|
+
ctx.fillRect(x, y, cellWidth, cellHeight);
|
|
1223
|
+
}
|
|
1208
1224
|
}
|
|
1209
1225
|
if (highlightEditedCells && !insertedRowKeys.has(rowKey) && !isSelectedCell && editedCellKeys.has(`${typeof rowKey}:${String(rowKey)}\0${column.key}`)) {
|
|
1210
1226
|
ctx.fillStyle = colors.editedFill;
|
|
@@ -1215,8 +1231,11 @@ function paintGrid(options) {
|
|
|
1215
1231
|
ctx.fillRect(x, y, cellWidth, cellHeight);
|
|
1216
1232
|
}
|
|
1217
1233
|
if (annotation?.type === "background") {
|
|
1218
|
-
|
|
1219
|
-
|
|
1234
|
+
const annotationBackground = resolveColor(annotation.color);
|
|
1235
|
+
if (annotationBackground) {
|
|
1236
|
+
ctx.fillStyle = annotationBackground;
|
|
1237
|
+
ctx.fillRect(x, y, cellWidth, cellHeight);
|
|
1238
|
+
}
|
|
1220
1239
|
}
|
|
1221
1240
|
if (isColumnDropTarget) {
|
|
1222
1241
|
ctx.fillStyle = isAxisSelected ? getAxisSelectionFill(rowIndex, column.key) : colors.columnDropTargetFill;
|
|
@@ -1232,14 +1251,14 @@ function paintGrid(options) {
|
|
|
1232
1251
|
}
|
|
1233
1252
|
if (rowSpan > 1) {
|
|
1234
1253
|
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);
|
|
1235
|
-
ctx.fillStyle = mergedFill;
|
|
1254
|
+
ctx.fillStyle = resolveColor(mergedFill) ?? colors.background;
|
|
1236
1255
|
for (let offset = 1; offset < rowSpan; offset += 1) {
|
|
1237
1256
|
ctx.fillRect(x, y + offset * rowHeight - 1, cellWidth, 2);
|
|
1238
1257
|
}
|
|
1239
1258
|
}
|
|
1240
1259
|
if (colSpan > 1 && !verticalBorderless) {
|
|
1241
1260
|
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);
|
|
1242
|
-
ctx.fillStyle = mergedFill;
|
|
1261
|
+
ctx.fillStyle = resolveColor(mergedFill) ?? colors.background;
|
|
1243
1262
|
let offsetLeft = 0;
|
|
1244
1263
|
for (let offset = 1; offset < colSpan; offset += 1) {
|
|
1245
1264
|
offsetLeft += metrics[columnIndex + offset - 1]?.width ?? 0;
|
|
@@ -1335,7 +1354,8 @@ function paintGrid(options) {
|
|
|
1335
1354
|
ctx.beginPath();
|
|
1336
1355
|
ctx.rect(x + 2, y + 1, Math.max(0, cellWidth - 4), cellHeight - 2);
|
|
1337
1356
|
ctx.clip();
|
|
1338
|
-
|
|
1357
|
+
const textColor = isAxisSelected ? colors.axisSelectionText : isColumnDropTarget ? colors.text : resolveColor(cellStyle?.color ?? rowStyle?.color) ?? colors.text;
|
|
1358
|
+
ctx.fillStyle = textColor;
|
|
1339
1359
|
ctx.font = createCellFont(bodyFontSize);
|
|
1340
1360
|
ctx.textBaseline = "alphabetic";
|
|
1341
1361
|
ctx.textAlign = column.align === "right" ? "right" : column.align === "center" ? "center" : "left";
|
|
@@ -1345,7 +1365,7 @@ function paintGrid(options) {
|
|
|
1345
1365
|
}
|
|
1346
1366
|
if (annotation?.type === "corner") {
|
|
1347
1367
|
const cornerTop = y - 1;
|
|
1348
|
-
ctx.fillStyle = annotation.color;
|
|
1368
|
+
ctx.fillStyle = resolveColor(annotation.color) ?? colors.text;
|
|
1349
1369
|
ctx.beginPath();
|
|
1350
1370
|
ctx.moveTo(x + cellWidth - 10, cornerTop);
|
|
1351
1371
|
ctx.lineTo(x + cellWidth, cornerTop);
|
|
@@ -1731,6 +1751,18 @@ function readThemePixel(styles, name, fallback) {
|
|
|
1731
1751
|
const value = Number.parseFloat(styles.getPropertyValue(name));
|
|
1732
1752
|
return Number.isFinite(value) && value > 0 ? value : fallback;
|
|
1733
1753
|
}
|
|
1754
|
+
function resolveCanvasColor(styles, color) {
|
|
1755
|
+
if (!color) return void 0;
|
|
1756
|
+
let resolved = color.trim();
|
|
1757
|
+
for (let depth = 0; depth < 8; depth += 1) {
|
|
1758
|
+
const variable = resolved.match(/^var\(\s*(--[^,\s)]+)\s*(?:,\s*(.+))?\)$/);
|
|
1759
|
+
if (!variable) return resolved || void 0;
|
|
1760
|
+
const value = styles.getPropertyValue(variable[1]).trim();
|
|
1761
|
+
resolved = value || variable[2]?.trim() || "";
|
|
1762
|
+
if (!resolved) return void 0;
|
|
1763
|
+
}
|
|
1764
|
+
return void 0;
|
|
1765
|
+
}
|
|
1734
1766
|
function getDefaultRowKey(row, index) {
|
|
1735
1767
|
const id = row.id;
|
|
1736
1768
|
return typeof id === "string" || typeof id === "number" ? id : index;
|
|
@@ -1967,6 +1999,7 @@ function TableInner({
|
|
|
1967
1999
|
const rootRef = useRef4(null);
|
|
1968
2000
|
const frameRef = useRef4(null);
|
|
1969
2001
|
const textFrameRef = useRef4(null);
|
|
2002
|
+
const textLayoutScrollTopRef = useRef4(0);
|
|
1970
2003
|
const toastTimerRef = useRef4(null);
|
|
1971
2004
|
const headerTooltipTimerRef = useRef4(null);
|
|
1972
2005
|
const cellTooltipTimerRef = useRef4(null);
|
|
@@ -2551,7 +2584,7 @@ function TableInner({
|
|
|
2551
2584
|
const scroll = scrollRef.current;
|
|
2552
2585
|
const rowScrollTop = fixedHeader ? scroll.top : Math.max(0, scroll.top - bodyTop);
|
|
2553
2586
|
const range = isVirtualized ? getViewportRange(scroll.left, rowScrollTop, viewport.width, bodyViewportHeight, rows.length, rowHeight, metrics, virtualOverscan) : { rowStart: 0, rowEnd: rows.length, columnStart: 0, columnEnd: columns.length };
|
|
2554
|
-
paintGrid({ context, width: viewport.width, height: renderHeight, pixelRatio: ratio, scrollLeft: scroll.left, scrollTop: scroll.top, rowHeight, bodyFontSize, headerActionSlotWidth, headerHeight, headerLeafTop, headerLeafHeight, bodyTop, suppressLastRowBottomBorder: bottomSummaryHeight > 0, suppressFrameBottomBorder: bottomSummaryHeight > 0, fixedHeader, verticalBorderless: !hasVerticalBorders, horizontalBorderless, frameBorderless, extendVerticalGridLines: !autoHeight, striped: hasStripedRows, columnDraggable, sortState, filterValues, hoveredHeaderAction: hoveredHeaderActionRef.current, rows, rowStyle, columns, metrics, range, selection, editing, hoveredRowIndex: hoveredRowIndexRef.current, selectionRange, selectedRowKeys: selectedRowKeySet, rowSelectionMode, selectedColumnKeys: selectedColumnKeySet, cellSpans: cellSpanLookup.covered, maxRowSpan: cellSpanLookup.maxRowSpan, highlightEditedCells: highlightsEditedCells, highlightInsertedRows: highlightsInsertedRows, insertedRowKeys: insertedRowKeySet, editedCellKeys, cellAnnotations, getRowKey, rowDragPreview, columnDropTarget, colors: themeColors });
|
|
2587
|
+
paintGrid({ context, width: viewport.width, height: renderHeight, pixelRatio: ratio, scrollLeft: scroll.left, scrollTop: scroll.top, rowHeight, bodyFontSize, headerActionSlotWidth, headerHeight, headerLeafTop, headerLeafHeight, bodyTop, suppressLastRowBottomBorder: bottomSummaryHeight > 0, suppressFrameBottomBorder: bottomSummaryHeight > 0, fixedHeader, verticalBorderless: !hasVerticalBorders, horizontalBorderless, frameBorderless, extendVerticalGridLines: !autoHeight, striped: hasStripedRows, columnDraggable, sortState, filterValues, hoveredHeaderAction: hoveredHeaderActionRef.current, rows, rowStyle, columns, metrics, range, selection, editing, hoveredRowIndex: hoveredRowIndexRef.current, selectionRange, selectedRowKeys: selectedRowKeySet, rowSelectionMode, selectedColumnKeys: selectedColumnKeySet, cellSpans: cellSpanLookup.covered, maxRowSpan: cellSpanLookup.maxRowSpan, highlightEditedCells: highlightsEditedCells, highlightInsertedRows: highlightsInsertedRows, insertedRowKeys: insertedRowKeySet, editedCellKeys, cellAnnotations, getRowKey, rowDragPreview, columnDropTarget, resolveColor: (color) => resolveCanvasColor(themeStyles, color), colors: themeColors });
|
|
2555
2588
|
}, [autoHeight, bodyTop, bodyViewportHeight, bottomSummaryHeight, cellAnnotations, cellSpanLookup, columnDragPreview, columnDraggable, columnDropTarget, columns, editedCellHighlightColor, editedCellKeys, editing, renderHeight, filterValues, fixedHeader, frameBorderless, getRowKey, hasStripedRows, hasVerticalBorders, headerActionSlotWidth, headerDepth, headerHeight, headerLeafHeight, headerLeafTop, horizontalBorderless, highlightsEditedCells, highlightsInsertedRows, insertedRowHighlightColor, insertedRowKeySet, isVirtualized, metrics, rowDragPreview, rowHeight, rowSelectionMode, rowStyle, rows, selectedColumnKeySet, selectedRowKeySet, selection, selectionRange, sortState, stripedColor, viewport.width, virtualOverscan]);
|
|
2556
2589
|
const scheduleDraw = useCallback2(() => {
|
|
2557
2590
|
if (frameRef.current === null) frameRef.current = requestAnimationFrame(draw);
|
|
@@ -3004,6 +3037,13 @@ function TableInner({
|
|
|
3004
3037
|
horizontalScrollbarDragRef.current = null;
|
|
3005
3038
|
showCustomScrollbar("horizontal");
|
|
3006
3039
|
}, [showCustomScrollbar]);
|
|
3040
|
+
useLayoutEffect3(() => {
|
|
3041
|
+
textLayoutScrollTopRef.current = scrollPosition.top;
|
|
3042
|
+
const clips = rootRef.current?.querySelectorAll(".rvg-body-text-clip");
|
|
3043
|
+
clips?.forEach((clip) => {
|
|
3044
|
+
clip.style.transform = "";
|
|
3045
|
+
});
|
|
3046
|
+
}, [scrollPosition.top]);
|
|
3007
3047
|
const handleScroll = useCallback2(() => {
|
|
3008
3048
|
const element = scrollerRef.current;
|
|
3009
3049
|
if (!element) return;
|
|
@@ -3011,6 +3051,13 @@ function TableInner({
|
|
|
3011
3051
|
const scrollDeltaX = element.scrollLeft - previousScroll.left;
|
|
3012
3052
|
const scrollDeltaY = element.scrollTop - previousScroll.top;
|
|
3013
3053
|
scrollRef.current = { left: element.scrollLeft, top: element.scrollTop };
|
|
3054
|
+
const textDeltaY = element.scrollTop - textLayoutScrollTopRef.current;
|
|
3055
|
+
if (textDeltaY !== 0) {
|
|
3056
|
+
const clips = rootRef.current?.querySelectorAll(".rvg-body-text-clip");
|
|
3057
|
+
clips?.forEach((clip) => {
|
|
3058
|
+
clip.style.transform = `translate3d(0, ${-textDeltaY}px, 0)`;
|
|
3059
|
+
});
|
|
3060
|
+
}
|
|
3014
3061
|
syncSelectionEdgeTarget(element.scrollLeft, element.scrollTop);
|
|
3015
3062
|
const focus = selectionFocusRef.current;
|
|
3016
3063
|
if (focus && selection && !selectionRange) {
|