@lensui/lens-table 0.1.17 → 0.1.19
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/README.md +1 -0
- package/dist/index.cjs +34 -8
- package/dist/index.d.cts +7 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +34 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -98,6 +98,7 @@ export function Example() {
|
|
|
98
98
|
| `verticalBorderless` | `boolean` | `false` | 已兼容保留,建议改用 `borderless`。 |
|
|
99
99
|
| `horizontalBorderless` | `boolean` | `false` | 是否隐藏横向行分隔线及上下边框,同时保留纵向列分隔线。可与 `striped` 配合使用。 |
|
|
100
100
|
| `frameBorderless` | `boolean` | `false` | 是否隐藏表格四周外框,同时保留内部行列分隔线。 |
|
|
101
|
+
| `rowStyle` | `(row, rowIndex) => { color?: string; backgroundColor?: string }` | - | 自定义整行绘制样式,覆盖数据列及自动生成的选择列、序号列和拖拽列。 |
|
|
101
102
|
| `striped` | `boolean \| string` | `false` | 是否显示斑马纹行背景。传`true` 使用主题变量,传颜色字符串可自定义斑马纹颜色,例如 `'#f6faff'`。 |
|
|
102
103
|
| `highlight` | `{ editedCells?: boolean \| string; insertedRows?: boolean \| string }` | `{}` | 高亮反馈配置。`editedCells` 控制编辑过的单元格底色,`insertedRows` 控制乐观插入行底色;传 `true` 使用默认色,传颜色字符串可自定义。 |
|
|
103
104
|
| `cellSpans` | `TableCellSpan[] \| ((ctx) => TableCellSpan \| { rowSpan?: number; colSpan?: number } \| null)` | `[]` | 合并主体单元格配置。可传数组,也可传函数按单元格生成规则。推荐使用 `rowKey` 定位;横向合并会限制在同一个固定列分区内,工具列不会参与合并。 |
|
package/dist/index.cjs
CHANGED
|
@@ -1007,6 +1007,7 @@ function paintGrid(options) {
|
|
|
1007
1007
|
const y = bodyTop + rowIndex * rowHeight - scrollTop + shift;
|
|
1008
1008
|
const row = rows[rowIndex];
|
|
1009
1009
|
const rowKey = getRowKey(row, rowIndex);
|
|
1010
|
+
const rowStyle = options.rowStyle?.(row, rowIndex);
|
|
1010
1011
|
for (let columnIndex = 0; columnIndex < columns.length; columnIndex += 1) {
|
|
1011
1012
|
if (layer === "scroll" ? columns[columnIndex].fixed !== void 0 : columns[columnIndex].fixed !== layer) continue;
|
|
1012
1013
|
if (layer === "scroll" && (columnIndex < range.columnStart || columnIndex >= range.columnEnd)) continue;
|
|
@@ -1029,6 +1030,10 @@ function paintGrid(options) {
|
|
|
1029
1030
|
ctx.fillStyle = striped && rowIndex % 2 === 1 ? colors.stripe : colors.background;
|
|
1030
1031
|
ctx.fillRect(x, y, cellWidth, cellHeight);
|
|
1031
1032
|
}
|
|
1033
|
+
if (rowStyle?.backgroundColor) {
|
|
1034
|
+
ctx.fillStyle = rowStyle.backgroundColor;
|
|
1035
|
+
ctx.fillRect(x, y, cellWidth, cellHeight);
|
|
1036
|
+
}
|
|
1032
1037
|
if (isAxisSelected) {
|
|
1033
1038
|
ctx.fillStyle = colors.axisSelectionFill;
|
|
1034
1039
|
ctx.fillRect(x, y, cellWidth, cellHeight);
|
|
@@ -1074,14 +1079,14 @@ function paintGrid(options) {
|
|
|
1074
1079
|
ctx.fillRect(x, y + cellHeight - 1, cellWidth, 1);
|
|
1075
1080
|
}
|
|
1076
1081
|
if (rowSpan > 1) {
|
|
1077
|
-
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 ?? (striped && rowIndex % 2 === 1 ? colors.stripe : colors.background);
|
|
1082
|
+
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);
|
|
1078
1083
|
ctx.fillStyle = mergedFill;
|
|
1079
1084
|
for (let offset = 1; offset < rowSpan; offset += 1) {
|
|
1080
1085
|
ctx.fillRect(x, y + offset * rowHeight - 1, cellWidth, 2);
|
|
1081
1086
|
}
|
|
1082
1087
|
}
|
|
1083
1088
|
if (colSpan > 1 && !verticalBorderless) {
|
|
1084
|
-
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 ?? (striped && rowIndex % 2 === 1 ? colors.stripe : colors.background);
|
|
1089
|
+
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);
|
|
1085
1090
|
ctx.fillStyle = mergedFill;
|
|
1086
1091
|
let offsetLeft = 0;
|
|
1087
1092
|
for (let offset = 1; offset < colSpan; offset += 1) {
|
|
@@ -1178,7 +1183,7 @@ function paintGrid(options) {
|
|
|
1178
1183
|
ctx.beginPath();
|
|
1179
1184
|
ctx.rect(x + 2, y + 1, Math.max(0, cellWidth - 4), cellHeight - 2);
|
|
1180
1185
|
ctx.clip();
|
|
1181
|
-
ctx.fillStyle = isAxisSelected && !isSelectedCell && !isRangeCell ? colors.axisSelectionText : cellStyle?.color ?? colors.text;
|
|
1186
|
+
ctx.fillStyle = isAxisSelected && !isSelectedCell && !isRangeCell ? colors.axisSelectionText : cellStyle?.color ?? rowStyle?.color ?? colors.text;
|
|
1182
1187
|
ctx.font = createCellFont(bodyFontSize);
|
|
1183
1188
|
ctx.textBaseline = "alphabetic";
|
|
1184
1189
|
ctx.textAlign = column.align === "right" ? "right" : column.align === "center" ? "center" : "left";
|
|
@@ -1626,6 +1631,7 @@ function TableInner({
|
|
|
1626
1631
|
horizontalBorderless = false,
|
|
1627
1632
|
frameBorderless = false,
|
|
1628
1633
|
striped = false,
|
|
1634
|
+
rowStyle,
|
|
1629
1635
|
highlight,
|
|
1630
1636
|
cellSpans = [],
|
|
1631
1637
|
loading = false,
|
|
@@ -1657,6 +1663,7 @@ function TableInner({
|
|
|
1657
1663
|
onSortChange,
|
|
1658
1664
|
onFilterChange,
|
|
1659
1665
|
onCellChange,
|
|
1666
|
+
editTrigger = "double-click",
|
|
1660
1667
|
onCellClick,
|
|
1661
1668
|
onCellDoubleClick,
|
|
1662
1669
|
onCellContextMenu,
|
|
@@ -1753,6 +1760,7 @@ function TableInner({
|
|
|
1753
1760
|
}, [columns, headerCells, headerDepth]);
|
|
1754
1761
|
const canvasRef = (0, import_react5.useRef)(null);
|
|
1755
1762
|
const scrollerRef = (0, import_react5.useRef)(null);
|
|
1763
|
+
const rootRef = (0, import_react5.useRef)(null);
|
|
1756
1764
|
const frameRef = (0, import_react5.useRef)(null);
|
|
1757
1765
|
const textFrameRef = (0, import_react5.useRef)(null);
|
|
1758
1766
|
const toastTimerRef = (0, import_react5.useRef)(null);
|
|
@@ -2036,6 +2044,18 @@ function TableInner({
|
|
|
2036
2044
|
const [selection, setSelection] = useControllableValue(resolvedSelectedCell, resolvedDefaultSelectedCell, handleSelectedCellChange);
|
|
2037
2045
|
const [selectionRange, setSelectionRange] = (0, import_react5.useState)(null);
|
|
2038
2046
|
const rangeDragRef = (0, import_react5.useRef)(null);
|
|
2047
|
+
(0, import_react5.useEffect)(() => {
|
|
2048
|
+
if (!selection) return void 0;
|
|
2049
|
+
const handleOutsidePointerDown = (event) => {
|
|
2050
|
+
const target = event.target;
|
|
2051
|
+
if (!(target instanceof Node) || rootRef.current?.contains(target)) return;
|
|
2052
|
+
clickedCellRef.current = null;
|
|
2053
|
+
setSelectionRange(null);
|
|
2054
|
+
setSelection(null);
|
|
2055
|
+
};
|
|
2056
|
+
document.addEventListener("pointerdown", handleOutsidePointerDown);
|
|
2057
|
+
return () => document.removeEventListener("pointerdown", handleOutsidePointerDown);
|
|
2058
|
+
}, [selection, setSelection]);
|
|
2039
2059
|
const applyRowOrder = (0, import_react5.useCallback)((sourceIndex, targetIndex) => {
|
|
2040
2060
|
if (sourceIndex === targetIndex || sourceIndex < 0 || targetIndex < 0 || sourceIndex >= rows.length || targetIndex >= rows.length) return;
|
|
2041
2061
|
const nextEntries = rows.map((row, index) => ({ row, key: getDataRowKey(row, index) }));
|
|
@@ -2311,8 +2331,8 @@ function TableInner({
|
|
|
2311
2331
|
const scroll = scrollRef.current;
|
|
2312
2332
|
const rowScrollTop = fixedHeader ? scroll.top : Math.max(0, scroll.top - bodyTop);
|
|
2313
2333
|
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 };
|
|
2314
|
-
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, 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 });
|
|
2315
|
-
}, [autoHeight, bodyTop, bodyViewportHeight, bottomSummaryHeight, cellAnnotations, cellSpanLookup, 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, rows, selectedColumnKeySet, selectedRowKeySet, selection, selectionRange, sortState, stripedColor, viewport.width, virtualOverscan]);
|
|
2334
|
+
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 });
|
|
2335
|
+
}, [autoHeight, bodyTop, bodyViewportHeight, bottomSummaryHeight, cellAnnotations, cellSpanLookup, 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]);
|
|
2316
2336
|
const scheduleDraw = (0, import_react5.useCallback)(() => {
|
|
2317
2337
|
if (frameRef.current === null) frameRef.current = requestAnimationFrame(draw);
|
|
2318
2338
|
}, [draw]);
|
|
@@ -4595,7 +4615,7 @@ function TableInner({
|
|
|
4595
4615
|
};
|
|
4596
4616
|
const currentScroll = scrollRef.current;
|
|
4597
4617
|
const scrollerBottom = Math.max(0, bottomSummaryHeight - horizontalScrollbarHeight);
|
|
4598
|
-
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: `rvg-root${!hasVerticalBorders ? " is-vertical-borderless" : ""}${horizontalBorderless ? " is-horizontal-borderless" : ""}${frameBorderless ? " is-frame-borderless" : ""}${hasStripedRows ? " is-striped" : ""}${insertBusy ? " is-inserting" : ""}${deleteBusy ? " is-deleting" : ""} ${loading && !hasCompletedLoadRef.current && !hasCustomLoading ? "is-initial-loading" : ""} ${className}`, style: rootStyle, children: [
|
|
4618
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { ref: rootRef, className: `rvg-root${!hasVerticalBorders ? " is-vertical-borderless" : ""}${horizontalBorderless ? " is-horizontal-borderless" : ""}${frameBorderless ? " is-frame-borderless" : ""}${hasStripedRows ? " is-striped" : ""}${insertBusy ? " is-inserting" : ""}${deleteBusy ? " is-deleting" : ""} ${loading && !hasCompletedLoadRef.current && !hasCustomLoading ? "is-initial-loading" : ""} ${className}`, style: rootStyle, children: [
|
|
4599
4619
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { ref: scrollerRef, className: `rvg-scroller${contextMenu ? " is-context-menu-open" : ""}`, style: { bottom: scrollerBottom }, onScroll: handleScroll, onCopy: handleCopy, onContextMenu: handleContextMenu, tabIndex: 0, role: "grid", "aria-label": ariaLabel, "aria-rowcount": rows.length, "aria-colcount": columns.length, onKeyDown: handleKeyDown, children: [
|
|
4600
4620
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
4601
4621
|
"canvas",
|
|
@@ -4777,7 +4797,12 @@ function TableInner({
|
|
|
4777
4797
|
return;
|
|
4778
4798
|
}
|
|
4779
4799
|
const cell = locateCell(event.clientX, event.clientY);
|
|
4780
|
-
if (!cell)
|
|
4800
|
+
if (!cell) {
|
|
4801
|
+
clickedCellRef.current = null;
|
|
4802
|
+
setSelectionRange(null);
|
|
4803
|
+
setSelection(null);
|
|
4804
|
+
return;
|
|
4805
|
+
}
|
|
4781
4806
|
if (columns[cell.columnIndex].rowDragHandle || columns[cell.columnIndex].rowNumber) {
|
|
4782
4807
|
clickedCellRef.current = null;
|
|
4783
4808
|
return;
|
|
@@ -4801,6 +4826,7 @@ function TableInner({
|
|
|
4801
4826
|
selectRow(cell.rowIndex, event);
|
|
4802
4827
|
}
|
|
4803
4828
|
revealCell(cell);
|
|
4829
|
+
if (editTrigger === "single-click") beginEdit(cell);
|
|
4804
4830
|
},
|
|
4805
4831
|
onDoubleClick: (event) => {
|
|
4806
4832
|
const cell = clickedCellRef.current ?? locateCell(event.clientX, event.clientY);
|
|
@@ -4809,7 +4835,7 @@ function TableInner({
|
|
|
4809
4835
|
if (column.rowNumber || column.rowSelection || column.rowDragHandle) return;
|
|
4810
4836
|
const row = rows[cell.rowIndex];
|
|
4811
4837
|
onCellDoubleClick?.({ ...cell, row, column, value: column.dataIndex === void 0 ? void 0 : row[column.dataIndex] }, event);
|
|
4812
|
-
if (!event.defaultPrevented) beginEdit(cell);
|
|
4838
|
+
if (!event.defaultPrevented && editTrigger === "double-click") beginEdit(cell);
|
|
4813
4839
|
},
|
|
4814
4840
|
onContextMenu: handleContextMenu
|
|
4815
4841
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -334,6 +334,11 @@ type TableContextMenu<Row> = boolean | TableContextMenuConfig<Row>;
|
|
|
334
334
|
interface TableProps<Row extends object> {
|
|
335
335
|
columns: GridColumn<Row>[];
|
|
336
336
|
rows: Row[];
|
|
337
|
+
/** Custom row paint style. Applies to data and generated utility columns. */
|
|
338
|
+
rowStyle?: (row: Row, rowIndex: number) => {
|
|
339
|
+
color?: string;
|
|
340
|
+
backgroundColor?: string;
|
|
341
|
+
};
|
|
337
342
|
/** Stable row id. Defaults to the row's `id` field when omitted. */
|
|
338
343
|
rowKey?: keyof Row | ((row: Row, index: number) => GridKey);
|
|
339
344
|
width?: number | string;
|
|
@@ -413,6 +418,8 @@ interface TableProps<Row extends object> {
|
|
|
413
418
|
/** Overrides the built-in text filtering. Return the rows that match the internally managed filter values. */
|
|
414
419
|
onFilterChange?: (rows: Row[], values: Readonly<Record<string, string>>) => Row[];
|
|
415
420
|
onCellChange?: (change: CellChange<Row>) => void | Promise<void>;
|
|
421
|
+
/** Starts editing from a single or double click. Defaults to double-click. */
|
|
422
|
+
editTrigger?: 'single-click' | 'double-click';
|
|
416
423
|
/** Fires on a data cell click, before the default selection behavior. */
|
|
417
424
|
onCellClick?: (cell: TableCellContext<Row>, event: MouseEvent<HTMLElement>) => void;
|
|
418
425
|
/** Fires before double-click editing. preventDefault() cancels editing. */
|
package/dist/index.d.ts
CHANGED
|
@@ -334,6 +334,11 @@ type TableContextMenu<Row> = boolean | TableContextMenuConfig<Row>;
|
|
|
334
334
|
interface TableProps<Row extends object> {
|
|
335
335
|
columns: GridColumn<Row>[];
|
|
336
336
|
rows: Row[];
|
|
337
|
+
/** Custom row paint style. Applies to data and generated utility columns. */
|
|
338
|
+
rowStyle?: (row: Row, rowIndex: number) => {
|
|
339
|
+
color?: string;
|
|
340
|
+
backgroundColor?: string;
|
|
341
|
+
};
|
|
337
342
|
/** Stable row id. Defaults to the row's `id` field when omitted. */
|
|
338
343
|
rowKey?: keyof Row | ((row: Row, index: number) => GridKey);
|
|
339
344
|
width?: number | string;
|
|
@@ -413,6 +418,8 @@ interface TableProps<Row extends object> {
|
|
|
413
418
|
/** Overrides the built-in text filtering. Return the rows that match the internally managed filter values. */
|
|
414
419
|
onFilterChange?: (rows: Row[], values: Readonly<Record<string, string>>) => Row[];
|
|
415
420
|
onCellChange?: (change: CellChange<Row>) => void | Promise<void>;
|
|
421
|
+
/** Starts editing from a single or double click. Defaults to double-click. */
|
|
422
|
+
editTrigger?: 'single-click' | 'double-click';
|
|
416
423
|
/** Fires on a data cell click, before the default selection behavior. */
|
|
417
424
|
onCellClick?: (cell: TableCellContext<Row>, event: MouseEvent<HTMLElement>) => void;
|
|
418
425
|
/** Fires before double-click editing. preventDefault() cancels editing. */
|
package/dist/index.js
CHANGED
|
@@ -977,6 +977,7 @@ function paintGrid(options) {
|
|
|
977
977
|
const y = bodyTop + rowIndex * rowHeight - scrollTop + shift;
|
|
978
978
|
const row = rows[rowIndex];
|
|
979
979
|
const rowKey = getRowKey(row, rowIndex);
|
|
980
|
+
const rowStyle = options.rowStyle?.(row, rowIndex);
|
|
980
981
|
for (let columnIndex = 0; columnIndex < columns.length; columnIndex += 1) {
|
|
981
982
|
if (layer === "scroll" ? columns[columnIndex].fixed !== void 0 : columns[columnIndex].fixed !== layer) continue;
|
|
982
983
|
if (layer === "scroll" && (columnIndex < range.columnStart || columnIndex >= range.columnEnd)) continue;
|
|
@@ -999,6 +1000,10 @@ function paintGrid(options) {
|
|
|
999
1000
|
ctx.fillStyle = striped && rowIndex % 2 === 1 ? colors.stripe : colors.background;
|
|
1000
1001
|
ctx.fillRect(x, y, cellWidth, cellHeight);
|
|
1001
1002
|
}
|
|
1003
|
+
if (rowStyle?.backgroundColor) {
|
|
1004
|
+
ctx.fillStyle = rowStyle.backgroundColor;
|
|
1005
|
+
ctx.fillRect(x, y, cellWidth, cellHeight);
|
|
1006
|
+
}
|
|
1002
1007
|
if (isAxisSelected) {
|
|
1003
1008
|
ctx.fillStyle = colors.axisSelectionFill;
|
|
1004
1009
|
ctx.fillRect(x, y, cellWidth, cellHeight);
|
|
@@ -1044,14 +1049,14 @@ function paintGrid(options) {
|
|
|
1044
1049
|
ctx.fillRect(x, y + cellHeight - 1, cellWidth, 1);
|
|
1045
1050
|
}
|
|
1046
1051
|
if (rowSpan > 1) {
|
|
1047
|
-
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 ?? (striped && rowIndex % 2 === 1 ? colors.stripe : colors.background);
|
|
1052
|
+
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);
|
|
1048
1053
|
ctx.fillStyle = mergedFill;
|
|
1049
1054
|
for (let offset = 1; offset < rowSpan; offset += 1) {
|
|
1050
1055
|
ctx.fillRect(x, y + offset * rowHeight - 1, cellWidth, 2);
|
|
1051
1056
|
}
|
|
1052
1057
|
}
|
|
1053
1058
|
if (colSpan > 1 && !verticalBorderless) {
|
|
1054
|
-
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 ?? (striped && rowIndex % 2 === 1 ? colors.stripe : colors.background);
|
|
1059
|
+
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);
|
|
1055
1060
|
ctx.fillStyle = mergedFill;
|
|
1056
1061
|
let offsetLeft = 0;
|
|
1057
1062
|
for (let offset = 1; offset < colSpan; offset += 1) {
|
|
@@ -1148,7 +1153,7 @@ function paintGrid(options) {
|
|
|
1148
1153
|
ctx.beginPath();
|
|
1149
1154
|
ctx.rect(x + 2, y + 1, Math.max(0, cellWidth - 4), cellHeight - 2);
|
|
1150
1155
|
ctx.clip();
|
|
1151
|
-
ctx.fillStyle = isAxisSelected && !isSelectedCell && !isRangeCell ? colors.axisSelectionText : cellStyle?.color ?? colors.text;
|
|
1156
|
+
ctx.fillStyle = isAxisSelected && !isSelectedCell && !isRangeCell ? colors.axisSelectionText : cellStyle?.color ?? rowStyle?.color ?? colors.text;
|
|
1152
1157
|
ctx.font = createCellFont(bodyFontSize);
|
|
1153
1158
|
ctx.textBaseline = "alphabetic";
|
|
1154
1159
|
ctx.textAlign = column.align === "right" ? "right" : column.align === "center" ? "center" : "left";
|
|
@@ -1596,6 +1601,7 @@ function TableInner({
|
|
|
1596
1601
|
horizontalBorderless = false,
|
|
1597
1602
|
frameBorderless = false,
|
|
1598
1603
|
striped = false,
|
|
1604
|
+
rowStyle,
|
|
1599
1605
|
highlight,
|
|
1600
1606
|
cellSpans = [],
|
|
1601
1607
|
loading = false,
|
|
@@ -1627,6 +1633,7 @@ function TableInner({
|
|
|
1627
1633
|
onSortChange,
|
|
1628
1634
|
onFilterChange,
|
|
1629
1635
|
onCellChange,
|
|
1636
|
+
editTrigger = "double-click",
|
|
1630
1637
|
onCellClick,
|
|
1631
1638
|
onCellDoubleClick,
|
|
1632
1639
|
onCellContextMenu,
|
|
@@ -1723,6 +1730,7 @@ function TableInner({
|
|
|
1723
1730
|
}, [columns, headerCells, headerDepth]);
|
|
1724
1731
|
const canvasRef = useRef2(null);
|
|
1725
1732
|
const scrollerRef = useRef2(null);
|
|
1733
|
+
const rootRef = useRef2(null);
|
|
1726
1734
|
const frameRef = useRef2(null);
|
|
1727
1735
|
const textFrameRef = useRef2(null);
|
|
1728
1736
|
const toastTimerRef = useRef2(null);
|
|
@@ -2006,6 +2014,18 @@ function TableInner({
|
|
|
2006
2014
|
const [selection, setSelection] = useControllableValue(resolvedSelectedCell, resolvedDefaultSelectedCell, handleSelectedCellChange);
|
|
2007
2015
|
const [selectionRange, setSelectionRange] = useState4(null);
|
|
2008
2016
|
const rangeDragRef = useRef2(null);
|
|
2017
|
+
useEffect2(() => {
|
|
2018
|
+
if (!selection) return void 0;
|
|
2019
|
+
const handleOutsidePointerDown = (event) => {
|
|
2020
|
+
const target = event.target;
|
|
2021
|
+
if (!(target instanceof Node) || rootRef.current?.contains(target)) return;
|
|
2022
|
+
clickedCellRef.current = null;
|
|
2023
|
+
setSelectionRange(null);
|
|
2024
|
+
setSelection(null);
|
|
2025
|
+
};
|
|
2026
|
+
document.addEventListener("pointerdown", handleOutsidePointerDown);
|
|
2027
|
+
return () => document.removeEventListener("pointerdown", handleOutsidePointerDown);
|
|
2028
|
+
}, [selection, setSelection]);
|
|
2009
2029
|
const applyRowOrder = useCallback2((sourceIndex, targetIndex) => {
|
|
2010
2030
|
if (sourceIndex === targetIndex || sourceIndex < 0 || targetIndex < 0 || sourceIndex >= rows.length || targetIndex >= rows.length) return;
|
|
2011
2031
|
const nextEntries = rows.map((row, index) => ({ row, key: getDataRowKey(row, index) }));
|
|
@@ -2281,8 +2301,8 @@ function TableInner({
|
|
|
2281
2301
|
const scroll = scrollRef.current;
|
|
2282
2302
|
const rowScrollTop = fixedHeader ? scroll.top : Math.max(0, scroll.top - bodyTop);
|
|
2283
2303
|
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 };
|
|
2284
|
-
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, 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 });
|
|
2285
|
-
}, [autoHeight, bodyTop, bodyViewportHeight, bottomSummaryHeight, cellAnnotations, cellSpanLookup, 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, rows, selectedColumnKeySet, selectedRowKeySet, selection, selectionRange, sortState, stripedColor, viewport.width, virtualOverscan]);
|
|
2304
|
+
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 });
|
|
2305
|
+
}, [autoHeight, bodyTop, bodyViewportHeight, bottomSummaryHeight, cellAnnotations, cellSpanLookup, 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]);
|
|
2286
2306
|
const scheduleDraw = useCallback2(() => {
|
|
2287
2307
|
if (frameRef.current === null) frameRef.current = requestAnimationFrame(draw);
|
|
2288
2308
|
}, [draw]);
|
|
@@ -4565,7 +4585,7 @@ function TableInner({
|
|
|
4565
4585
|
};
|
|
4566
4586
|
const currentScroll = scrollRef.current;
|
|
4567
4587
|
const scrollerBottom = Math.max(0, bottomSummaryHeight - horizontalScrollbarHeight);
|
|
4568
|
-
return /* @__PURE__ */ jsxs7("div", { className: `rvg-root${!hasVerticalBorders ? " is-vertical-borderless" : ""}${horizontalBorderless ? " is-horizontal-borderless" : ""}${frameBorderless ? " is-frame-borderless" : ""}${hasStripedRows ? " is-striped" : ""}${insertBusy ? " is-inserting" : ""}${deleteBusy ? " is-deleting" : ""} ${loading && !hasCompletedLoadRef.current && !hasCustomLoading ? "is-initial-loading" : ""} ${className}`, style: rootStyle, children: [
|
|
4588
|
+
return /* @__PURE__ */ jsxs7("div", { ref: rootRef, className: `rvg-root${!hasVerticalBorders ? " is-vertical-borderless" : ""}${horizontalBorderless ? " is-horizontal-borderless" : ""}${frameBorderless ? " is-frame-borderless" : ""}${hasStripedRows ? " is-striped" : ""}${insertBusy ? " is-inserting" : ""}${deleteBusy ? " is-deleting" : ""} ${loading && !hasCompletedLoadRef.current && !hasCustomLoading ? "is-initial-loading" : ""} ${className}`, style: rootStyle, children: [
|
|
4569
4589
|
/* @__PURE__ */ jsxs7("div", { ref: scrollerRef, className: `rvg-scroller${contextMenu ? " is-context-menu-open" : ""}`, style: { bottom: scrollerBottom }, onScroll: handleScroll, onCopy: handleCopy, onContextMenu: handleContextMenu, tabIndex: 0, role: "grid", "aria-label": ariaLabel, "aria-rowcount": rows.length, "aria-colcount": columns.length, onKeyDown: handleKeyDown, children: [
|
|
4570
4590
|
/* @__PURE__ */ jsx7(
|
|
4571
4591
|
"canvas",
|
|
@@ -4747,7 +4767,12 @@ function TableInner({
|
|
|
4747
4767
|
return;
|
|
4748
4768
|
}
|
|
4749
4769
|
const cell = locateCell(event.clientX, event.clientY);
|
|
4750
|
-
if (!cell)
|
|
4770
|
+
if (!cell) {
|
|
4771
|
+
clickedCellRef.current = null;
|
|
4772
|
+
setSelectionRange(null);
|
|
4773
|
+
setSelection(null);
|
|
4774
|
+
return;
|
|
4775
|
+
}
|
|
4751
4776
|
if (columns[cell.columnIndex].rowDragHandle || columns[cell.columnIndex].rowNumber) {
|
|
4752
4777
|
clickedCellRef.current = null;
|
|
4753
4778
|
return;
|
|
@@ -4771,6 +4796,7 @@ function TableInner({
|
|
|
4771
4796
|
selectRow(cell.rowIndex, event);
|
|
4772
4797
|
}
|
|
4773
4798
|
revealCell(cell);
|
|
4799
|
+
if (editTrigger === "single-click") beginEdit(cell);
|
|
4774
4800
|
},
|
|
4775
4801
|
onDoubleClick: (event) => {
|
|
4776
4802
|
const cell = clickedCellRef.current ?? locateCell(event.clientX, event.clientY);
|
|
@@ -4779,7 +4805,7 @@ function TableInner({
|
|
|
4779
4805
|
if (column.rowNumber || column.rowSelection || column.rowDragHandle) return;
|
|
4780
4806
|
const row = rows[cell.rowIndex];
|
|
4781
4807
|
onCellDoubleClick?.({ ...cell, row, column, value: column.dataIndex === void 0 ? void 0 : row[column.dataIndex] }, event);
|
|
4782
|
-
if (!event.defaultPrevented) beginEdit(cell);
|
|
4808
|
+
if (!event.defaultPrevented && editTrigger === "double-click") beginEdit(cell);
|
|
4783
4809
|
},
|
|
4784
4810
|
onContextMenu: handleContextMenu
|
|
4785
4811
|
}
|