@lensui/lens-table 0.1.10 → 0.1.12
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 +4 -1
- package/dist/index.cjs +95 -68
- package/dist/index.css +20 -10
- package/dist/index.d.cts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +95 -68
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -89,7 +89,7 @@ export function Example() {
|
|
|
89
89
|
| `rowKey` | `keyof Row \| ((row, index) => string \| number)` | `id` | 行唯一标识。默认读取每行的`id` 字段;如果数据不是 `id` 主键,请显式传入字段名或函数。 |
|
|
90
90
|
| `width` | `number \| string` | `100%` | 表格宽度。数字按像素处理,字符串可传`100%`、`80vw` 等。 |
|
|
91
91
|
| `height` | `number \| string` | `100%` | 表格最大高度。默认继承父容器高度;如果父容器没有可计算高度,则回落到`480px`。数据较少时默认按真实内容高度收缩,数据较多时不超过该高度。 |
|
|
92
|
-
| `layout` | `{ rowHeight?: number; headerHeight?: number }`
|
|
92
|
+
| `layout` | `{ rowHeight?: number; headerHeight?: number; headerActionSize?: number }` | `{ rowHeight: 36, headerHeight: 40, headerActionSize: 14 }` | 表格布局尺寸配置。`headerActionSize` 同步控制表头搜索、排序和拖拽图标的尺寸、占位及点击区域;自定义多行表头会以 `headerHeight` 为最小高度自动撑开。 |
|
|
93
93
|
| `rowHeight` | `number` | `36` | 已兼容保留,建议改用 `layout.rowHeight`。 |
|
|
94
94
|
| `headerHeight` | `number` | `40` | 已兼容保留,建议改用 `layout.headerHeight`。 |
|
|
95
95
|
| `fixedHeader` | `boolean` | `true` | 表头是否固定在顶部。 |
|
|
@@ -97,6 +97,7 @@ export function Example() {
|
|
|
97
97
|
| `borderless` | `boolean` | `false` | 是否弱化竖向边框。开启后隐藏单元格之间的竖线,但保留横向分隔线。 |
|
|
98
98
|
| `verticalBorderless` | `boolean` | `false` | 已兼容保留,建议改用 `borderless`。 |
|
|
99
99
|
| `horizontalBorderless` | `boolean` | `false` | 是否隐藏横向行分隔线及上下边框,同时保留纵向列分隔线。可与 `striped` 配合使用。 |
|
|
100
|
+
| `frameBorderless` | `boolean` | `false` | 是否隐藏表格四周外框,同时保留内部行列分隔线。 |
|
|
100
101
|
| `striped` | `boolean \| string` | `false` | 是否显示斑马纹行背景。传`true` 使用主题变量,传颜色字符串可自定义斑马纹颜色,例如 `'#f6faff'`。 |
|
|
101
102
|
| `highlight` | `{ editedCells?: boolean \| string; insertedRows?: boolean \| string }` | `{}` | 高亮反馈配置。`editedCells` 控制编辑过的单元格底色,`insertedRows` 控制乐观插入行底色;传 `true` 使用默认色,传颜色字符串可自定义。 |
|
|
102
103
|
| `cellSpans` | `TableCellSpan[] \| ((ctx) => TableCellSpan \| { rowSpan?: number; colSpan?: number } \| null)` | `[]` | 合并主体单元格配置。可传数组,也可传函数按单元格生成规则。推荐使用 `rowKey` 定位;横向合并会限制在同一个固定列分区内,工具列不会参与合并。 |
|
|
@@ -579,6 +580,7 @@ const columns: GridColumn<Row>[] = [
|
|
|
579
580
|
'--rvg-color-bg': '#0f172a',
|
|
580
581
|
'--rvg-color-text': '#e5e7eb',
|
|
581
582
|
'--rvg-color-grid': '#334155',
|
|
583
|
+
'--rvg-font-size-body': '12px',
|
|
582
584
|
} as React.CSSProperties}
|
|
583
585
|
/>
|
|
584
586
|
```
|
|
@@ -587,6 +589,7 @@ const columns: GridColumn<Row>[] = [
|
|
|
587
589
|
|
|
588
590
|
| 变量 | 说明 |
|
|
589
591
|
| ----------------------------------- | ---------------------------------------------------------------------------------- |
|
|
592
|
+
| `--rvg-font-size-body` | 数据正文及单元格编辑器字号,默认 `13px`;不影响表头字号。 |
|
|
590
593
|
| `--rvg-color-bg` | 表格背景色。 |
|
|
591
594
|
| `--rvg-color-header-bg` | 表头背景色。 |
|
|
592
595
|
| `--rvg-color-text` | 主文本颜色。 |
|
package/dist/index.cjs
CHANGED
|
@@ -692,18 +692,6 @@ function DateEditor({ editor, value: draft, style, locale, labels, onChange, onC
|
|
|
692
692
|
);
|
|
693
693
|
}
|
|
694
694
|
|
|
695
|
-
// src/core/typography.ts
|
|
696
|
-
var CELL_FONT = "13px Inter, ui-sans-serif, system-ui, sans-serif";
|
|
697
|
-
function getCellBaselineOffset(context) {
|
|
698
|
-
context.save();
|
|
699
|
-
context.textBaseline = "alphabetic";
|
|
700
|
-
const metrics = context.measureText("Mg");
|
|
701
|
-
context.restore();
|
|
702
|
-
const ascent = metrics.fontBoundingBoxAscent;
|
|
703
|
-
const descent = metrics.fontBoundingBoxDescent;
|
|
704
|
-
return Number.isFinite(ascent) && Number.isFinite(descent) ? (ascent - descent) / 2 : 0;
|
|
705
|
-
}
|
|
706
|
-
|
|
707
695
|
// src/components/editors/TextEditor.tsx
|
|
708
696
|
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
709
697
|
function TextEditor({ value, type, style, labels, onChange, onCommit, onCancel }) {
|
|
@@ -717,7 +705,7 @@ function TextEditor({ value, type, style, labels, onChange, onCommit, onCancel }
|
|
|
717
705
|
"input",
|
|
718
706
|
{
|
|
719
707
|
type,
|
|
720
|
-
style: { font:
|
|
708
|
+
style: { font: "var(--rvg-font-size-body) Inter, ui-sans-serif, system-ui, sans-serif", textAlign: style.textAlign },
|
|
721
709
|
value,
|
|
722
710
|
autoFocus: true,
|
|
723
711
|
onChange: (event) => onChange(event.target.value),
|
|
@@ -834,8 +822,8 @@ function getHeaderTitleRequiredWidth(column, titleWidth) {
|
|
|
834
822
|
const minimumReadableTitleWidth = Math.min(Math.ceil(titleWidth), 28);
|
|
835
823
|
return minimumReadableTitleWidth + (column.align === "center" ? 20 : 22);
|
|
836
824
|
}
|
|
837
|
-
function getVisibleHeaderActions(column, width, columnDraggable = false, titleWidth = 26) {
|
|
838
|
-
const capacity = Math.max(0, Math.floor((width - getHeaderTitleRequiredWidth(column, titleWidth)) /
|
|
825
|
+
function getVisibleHeaderActions(column, width, columnDraggable = false, titleWidth = 26, actionSlotWidth = HEADER_ACTION_SLOT_WIDTH) {
|
|
826
|
+
const capacity = Math.max(0, Math.floor((width - getHeaderTitleRequiredWidth(column, titleWidth)) / actionSlotWidth));
|
|
839
827
|
const candidates = [
|
|
840
828
|
isColumnFilterable(column) ? "filter" : null,
|
|
841
829
|
isColumnSortable(column) ? "sort" : null,
|
|
@@ -906,6 +894,18 @@ function hitTestColumn(metrics, contentX) {
|
|
|
906
894
|
return index < metrics.length ? index : -1;
|
|
907
895
|
}
|
|
908
896
|
|
|
897
|
+
// src/core/typography.ts
|
|
898
|
+
var createCellFont = (fontSize = 13) => `${fontSize}px Inter, ui-sans-serif, system-ui, sans-serif`;
|
|
899
|
+
function getCellBaselineOffset(context) {
|
|
900
|
+
context.save();
|
|
901
|
+
context.textBaseline = "alphabetic";
|
|
902
|
+
const metrics = context.measureText("Mg");
|
|
903
|
+
context.restore();
|
|
904
|
+
const ascent = metrics.fontBoundingBoxAscent;
|
|
905
|
+
const descent = metrics.fontBoundingBoxDescent;
|
|
906
|
+
return Number.isFinite(ascent) && Number.isFinite(descent) ? (ascent - descent) / 2 : 0;
|
|
907
|
+
}
|
|
908
|
+
|
|
909
909
|
// src/core/render.ts
|
|
910
910
|
var getCellCoordKey = (rowIndex, columnIndex) => `${rowIndex}:${columnIndex}`;
|
|
911
911
|
var COLORS = {
|
|
@@ -942,7 +942,7 @@ function ellipsizeText(context, text, maxWidth) {
|
|
|
942
942
|
return `${text.slice(0, start)}${ellipsis}`;
|
|
943
943
|
}
|
|
944
944
|
function paintGrid(options) {
|
|
945
|
-
const { context: ctx, width, height, pixelRatio, scrollLeft, scrollTop, rowHeight, headerHeight, fixedHeader, verticalBorderless, horizontalBorderless, striped, columnDraggable, sortState, filterValues, hoveredHeaderAction, rows, columns, metrics, range, selection, editing, hoveredRowIndex, selectionRange, selectedRowKeys, rowSelectionMode, selectedColumnKeys, highlightEditedCells, highlightInsertedRows, insertedRowKeys, editedCellKeys, cellAnnotations, getRowKey, rowDragPreview, columnDropTarget } = options;
|
|
945
|
+
const { context: ctx, width, height, pixelRatio, scrollLeft, scrollTop, rowHeight, bodyFontSize, headerActionSlotWidth, headerHeight, fixedHeader, verticalBorderless, horizontalBorderless, frameBorderless, striped, columnDraggable, sortState, filterValues, hoveredHeaderAction, rows, columns, metrics, range, selection, editing, hoveredRowIndex, selectionRange, selectedRowKeys, rowSelectionMode, selectedColumnKeys, highlightEditedCells, highlightInsertedRows, insertedRowKeys, editedCellKeys, cellAnnotations, getRowKey, rowDragPreview, columnDropTarget } = options;
|
|
946
946
|
const headerLeafTop = options.headerLeafTop ?? 0;
|
|
947
947
|
const headerLeafHeight = options.headerLeafHeight ?? headerHeight;
|
|
948
948
|
const colors = { ...COLORS, ...options.colors };
|
|
@@ -959,7 +959,7 @@ function paintGrid(options) {
|
|
|
959
959
|
ctx.clearRect(0, 0, width, height);
|
|
960
960
|
ctx.fillStyle = colors.background;
|
|
961
961
|
ctx.fillRect(0, 0, width, height);
|
|
962
|
-
ctx.font =
|
|
962
|
+
ctx.font = createCellFont(bodyFontSize);
|
|
963
963
|
const cellBaselineOffset = getCellBaselineOffset(ctx);
|
|
964
964
|
ctx.textBaseline = "middle";
|
|
965
965
|
const leftFixedWidth = columns.reduce((value, column, index) => column.fixed === "left" ? value + metrics[index].width : value, 0);
|
|
@@ -1063,7 +1063,9 @@ function paintGrid(options) {
|
|
|
1063
1063
|
ctx.fillRect(x, y, cellWidth, cellHeight);
|
|
1064
1064
|
}
|
|
1065
1065
|
ctx.fillStyle = colors.grid;
|
|
1066
|
-
if (!verticalBorderless
|
|
1066
|
+
if (!verticalBorderless && !(frameBorderless && columnIndex + colSpan >= columns.length)) {
|
|
1067
|
+
ctx.fillRect(x + cellWidth - 1, y, 1, cellHeight);
|
|
1068
|
+
}
|
|
1067
1069
|
if (rowIndex === rowBelowDragGap) ctx.fillRect(x, y, cellWidth, 1);
|
|
1068
1070
|
if (!horizontalBorderless && (!options.suppressLastRowBottomBorder || rowIndex !== rows.length - 1)) {
|
|
1069
1071
|
ctx.fillRect(x, y + cellHeight - 1, cellWidth, 1);
|
|
@@ -1159,7 +1161,7 @@ function paintGrid(options) {
|
|
|
1159
1161
|
ctx.rect(x + 2, y + 1, Math.max(0, cellWidth - 4), cellHeight - 2);
|
|
1160
1162
|
ctx.clip();
|
|
1161
1163
|
ctx.fillStyle = cellStyle?.color ?? colors.text;
|
|
1162
|
-
ctx.font =
|
|
1164
|
+
ctx.font = createCellFont(bodyFontSize);
|
|
1163
1165
|
ctx.textBaseline = "alphabetic";
|
|
1164
1166
|
ctx.textAlign = column.align === "right" ? "right" : column.align === "center" ? "center" : "left";
|
|
1165
1167
|
ctx.fillText(label, textX, y + cellHeight / 2 + cellBaselineOffset);
|
|
@@ -1205,14 +1207,16 @@ function paintGrid(options) {
|
|
|
1205
1207
|
ctx.fillRect(x, headerY, metric.width, headerHeight);
|
|
1206
1208
|
}
|
|
1207
1209
|
ctx.fillStyle = colors.grid;
|
|
1208
|
-
if (!verticalBorderless
|
|
1210
|
+
if (!verticalBorderless && !(frameBorderless && columnIndex === columns.length - 1)) {
|
|
1211
|
+
ctx.fillRect(x + metric.width - 1, headerY, 1, headerHeight);
|
|
1212
|
+
}
|
|
1209
1213
|
if (!horizontalBorderless) ctx.fillRect(x, headerY + headerHeight - 1, metric.width, 1);
|
|
1210
1214
|
const column = columns[columnIndex];
|
|
1211
1215
|
if (headerLeafTop === 0 && !column.rowSelection && !column.rowDragHandle && !column.rowNumber && !column.renderHeader && column.title) {
|
|
1212
1216
|
ctx.font = "600 13px Inter, ui-sans-serif, system-ui, sans-serif";
|
|
1213
1217
|
const titleWidth = ctx.measureText(column.title).width;
|
|
1214
|
-
const visibleActions = getVisibleHeaderActions(column, metric.width, columnDraggable, titleWidth);
|
|
1215
|
-
const actionWidth = (Number(visibleActions.drag) + Number(visibleActions.filter) + Number(visibleActions.sort)) *
|
|
1218
|
+
const visibleActions = getVisibleHeaderActions(column, metric.width, columnDraggable, titleWidth, headerActionSlotWidth);
|
|
1219
|
+
const actionWidth = (Number(visibleActions.drag) + Number(visibleActions.filter) + Number(visibleActions.sort)) * headerActionSlotWidth;
|
|
1216
1220
|
const contentWidth = Math.max(0, metric.width - actionWidth);
|
|
1217
1221
|
const padding = 10;
|
|
1218
1222
|
const clipWidth = contentWidth;
|
|
@@ -1242,12 +1246,12 @@ function paintGrid(options) {
|
|
|
1242
1246
|
ctx.fillRect(rightFixedLeft - 1, 0, 1, height);
|
|
1243
1247
|
}
|
|
1244
1248
|
ctx.fillStyle = colors.grid;
|
|
1245
|
-
if (!horizontalBorderless) ctx.fillRect(0, 0, width, 1);
|
|
1246
|
-
if (!verticalBorderless) {
|
|
1249
|
+
if (!horizontalBorderless && !frameBorderless) ctx.fillRect(0, 0, width, 1);
|
|
1250
|
+
if (!verticalBorderless && !frameBorderless) {
|
|
1247
1251
|
ctx.fillRect(0, 0, 1, height);
|
|
1248
1252
|
ctx.fillRect(width - 1, 0, 1, height);
|
|
1249
1253
|
}
|
|
1250
|
-
if (!horizontalBorderless && !options.suppressFrameBottomBorder) ctx.fillRect(0, height - 1, width, 1);
|
|
1254
|
+
if (!horizontalBorderless && !frameBorderless && !options.suppressFrameBottomBorder) ctx.fillRect(0, height - 1, width, 1);
|
|
1251
1255
|
if (selectionRange) {
|
|
1252
1256
|
const rowStart = Math.min(selectionRange.anchor.rowIndex, selectionRange.focus.rowIndex);
|
|
1253
1257
|
const rowEnd = Math.max(selectionRange.anchor.rowIndex, selectionRange.focus.rowIndex);
|
|
@@ -1468,6 +1472,10 @@ var waitForPaint = () => new Promise((resolve) => {
|
|
|
1468
1472
|
function readThemeColor(styles, name, fallback) {
|
|
1469
1473
|
return styles.getPropertyValue(name).trim() || fallback;
|
|
1470
1474
|
}
|
|
1475
|
+
function readThemePixel(styles, name, fallback) {
|
|
1476
|
+
const value = Number.parseFloat(styles.getPropertyValue(name));
|
|
1477
|
+
return Number.isFinite(value) && value > 0 ? value : fallback;
|
|
1478
|
+
}
|
|
1471
1479
|
function getDefaultRowKey(row, index) {
|
|
1472
1480
|
const id = row.id;
|
|
1473
1481
|
return typeof id === "string" || typeof id === "number" ? id : index;
|
|
@@ -1552,6 +1560,7 @@ function TableInner({
|
|
|
1552
1560
|
borderless,
|
|
1553
1561
|
verticalBorderless,
|
|
1554
1562
|
horizontalBorderless = false,
|
|
1563
|
+
frameBorderless = false,
|
|
1555
1564
|
striped = false,
|
|
1556
1565
|
highlight,
|
|
1557
1566
|
cellSpans = [],
|
|
@@ -1598,6 +1607,8 @@ function TableInner({
|
|
|
1598
1607
|
setSourceColumns((current) => reconcileColumns(current, columnProps));
|
|
1599
1608
|
}, [columnProps]);
|
|
1600
1609
|
const rowHeight = layout?.rowHeight ?? rowHeightProp ?? 36;
|
|
1610
|
+
const headerActionSize = Math.max(8, layout?.headerActionSize ?? 14);
|
|
1611
|
+
const headerActionSlotWidth = headerActionSize + 2;
|
|
1601
1612
|
const baseHeaderHeight = layout?.headerHeight ?? headerHeightProp ?? 40;
|
|
1602
1613
|
const headerDepth = (0, import_react5.useMemo)(() => Math.max(1, ...sourceColumns.map(getColumnDepth)), [sourceColumns]);
|
|
1603
1614
|
const { language, labels } = (0, import_react5.useMemo)(() => resolveGridLocale(locale), [locale]);
|
|
@@ -2212,6 +2223,7 @@ function TableInner({
|
|
|
2212
2223
|
const context = canvas.getContext("2d");
|
|
2213
2224
|
if (!context) return;
|
|
2214
2225
|
const themeStyles = getComputedStyle(canvas);
|
|
2226
|
+
const bodyFontSize = readThemePixel(themeStyles, "--rvg-font-size-body", 13);
|
|
2215
2227
|
const themeColors = {
|
|
2216
2228
|
background: readThemeColor(themeStyles, "--rvg-color-bg", "#ffffff"),
|
|
2217
2229
|
header: readThemeColor(themeStyles, "--rvg-color-header-bg", "#f5f6f7"),
|
|
@@ -2232,8 +2244,8 @@ function TableInner({
|
|
|
2232
2244
|
const scroll = scrollRef.current;
|
|
2233
2245
|
const rowScrollTop = fixedHeader ? scroll.top : Math.max(0, scroll.top - bodyTop);
|
|
2234
2246
|
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 };
|
|
2235
|
-
paintGrid({ context, width: viewport.width, height: renderHeight, pixelRatio: ratio, scrollLeft: scroll.left, scrollTop: scroll.top, rowHeight, headerHeight, headerLeafTop, headerLeafHeight, bodyTop, suppressLastRowBottomBorder: bottomSummaryHeight > 0, suppressFrameBottomBorder: bottomSummaryHeight > 0, fixedHeader, verticalBorderless: !hasVerticalBorders, horizontalBorderless, 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 });
|
|
2236
|
-
}, [bodyTop, bodyViewportHeight, bottomSummaryHeight, cellAnnotations, cellSpanLookup, columnDraggable, columnDropTarget, columns, editedCellHighlightColor, editedCellKeys, editing, renderHeight, filterValues, fixedHeader, getRowKey, hasStripedRows, hasVerticalBorders, headerDepth, headerHeight, headerLeafHeight, headerLeafTop, horizontalBorderless, highlightsEditedCells, highlightsInsertedRows, insertedRowHighlightColor, insertedRowKeySet, isVirtualized, metrics, rowDragPreview, rowHeight, rowSelectionMode, rows, selectedColumnKeySet, selectedRowKeySet, selection, selectionRange, sortState, stripedColor, viewport.width, virtualOverscan]);
|
|
2247
|
+
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, 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 });
|
|
2248
|
+
}, [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]);
|
|
2237
2249
|
const scheduleDraw = (0, import_react5.useCallback)(() => {
|
|
2238
2250
|
if (frameRef.current === null) frameRef.current = requestAnimationFrame(draw);
|
|
2239
2251
|
}, [draw]);
|
|
@@ -2799,34 +2811,34 @@ function TableInner({
|
|
|
2799
2811
|
if (column.rowSelection || column.rowDragHandle || column.rowNumber) return null;
|
|
2800
2812
|
const localX = clientX - canvasRef.current.getBoundingClientRect().left;
|
|
2801
2813
|
const columnRight = getDisplayedColumnLeft(columnIndex) + metrics[columnIndex].width;
|
|
2802
|
-
const visibleActions = getVisibleHeaderActions(column, metrics[columnIndex].width, columnDraggable, measureHeaderTitleWidth(columnIndex));
|
|
2803
|
-
let right = columnRight - (visibleActions.drag ?
|
|
2814
|
+
const visibleActions = getVisibleHeaderActions(column, metrics[columnIndex].width, columnDraggable, measureHeaderTitleWidth(columnIndex), headerActionSlotWidth);
|
|
2815
|
+
let right = columnRight - (visibleActions.drag ? headerActionSlotWidth : 2);
|
|
2804
2816
|
if (visibleActions.sort) {
|
|
2805
|
-
if (localX >= right -
|
|
2806
|
-
right -=
|
|
2817
|
+
if (localX >= right - headerActionSlotWidth && localX < right) return "sort";
|
|
2818
|
+
right -= headerActionSlotWidth;
|
|
2807
2819
|
}
|
|
2808
|
-
if (visibleActions.filter && localX >= right -
|
|
2820
|
+
if (visibleActions.filter && localX >= right - headerActionSlotWidth && localX < right) return "filter";
|
|
2809
2821
|
return null;
|
|
2810
|
-
}, [columnDraggable, columns, getDisplayedColumnLeft, measureHeaderTitleWidth, metrics]);
|
|
2822
|
+
}, [columnDraggable, columns, getDisplayedColumnLeft, headerActionSlotWidth, measureHeaderTitleWidth, metrics]);
|
|
2811
2823
|
const isHeaderTitleTruncated = (0, import_react5.useCallback)((columnIndex) => {
|
|
2812
2824
|
const canvas = canvasRef.current;
|
|
2813
2825
|
if (columnIndex < 0 || !canvas) return false;
|
|
2814
2826
|
const column = columns[columnIndex];
|
|
2815
2827
|
const metric = metrics[columnIndex];
|
|
2816
2828
|
const titleWidth = measureHeaderTitleWidth(columnIndex);
|
|
2817
|
-
const visibleActions = getVisibleHeaderActions(column, metric.width, columnDraggable, titleWidth);
|
|
2818
|
-
const actionWidth = (Number(visibleActions.drag) + Number(visibleActions.filter) + Number(visibleActions.sort)) *
|
|
2829
|
+
const visibleActions = getVisibleHeaderActions(column, metric.width, columnDraggable, titleWidth, headerActionSlotWidth);
|
|
2830
|
+
const actionWidth = (Number(visibleActions.drag) + Number(visibleActions.filter) + Number(visibleActions.sort)) * headerActionSlotWidth;
|
|
2819
2831
|
return getHeaderTitleRequiredWidth(column, titleWidth) > Math.max(0, metric.width - actionWidth);
|
|
2820
|
-
}, [columnDraggable, columns, measureHeaderTitleWidth, metrics]);
|
|
2832
|
+
}, [columnDraggable, columns, headerActionSlotWidth, measureHeaderTitleWidth, metrics]);
|
|
2821
2833
|
const locateHeaderDragHandle = (0, import_react5.useCallback)((clientX, columnIndex) => {
|
|
2822
2834
|
if (!columnDraggable || columnIndex < 0 || !canvasRef.current) return false;
|
|
2823
2835
|
const column = columns[columnIndex];
|
|
2824
2836
|
if (column.rowSelection || column.rowDragHandle || column.rowNumber) return false;
|
|
2825
|
-
if (!getVisibleHeaderActions(column, metrics[columnIndex].width, columnDraggable, measureHeaderTitleWidth(columnIndex)).drag) return false;
|
|
2837
|
+
if (!getVisibleHeaderActions(column, metrics[columnIndex].width, columnDraggable, measureHeaderTitleWidth(columnIndex), headerActionSlotWidth).drag) return false;
|
|
2826
2838
|
const localX = clientX - canvasRef.current.getBoundingClientRect().left;
|
|
2827
2839
|
const columnRight = getDisplayedColumnLeft(columnIndex) + metrics[columnIndex].width;
|
|
2828
|
-
return localX >= columnRight -
|
|
2829
|
-
}, [columnDraggable, columns, getDisplayedColumnLeft, measureHeaderTitleWidth, metrics]);
|
|
2840
|
+
return localX >= columnRight - headerActionSlotWidth && localX < columnRight - 2;
|
|
2841
|
+
}, [columnDraggable, columns, getDisplayedColumnLeft, headerActionSlotWidth, measureHeaderTitleWidth, metrics]);
|
|
2830
2842
|
const getHeaderCellLeft = (0, import_react5.useCallback)((cell) => {
|
|
2831
2843
|
const startMetric = metrics[cell.startIndex];
|
|
2832
2844
|
const fixedSide = columns[cell.startIndex]?.fixed;
|
|
@@ -2891,8 +2903,8 @@ function TableInner({
|
|
|
2891
2903
|
if (cell.leaf) return locateHeaderDragHandle(clientX, cell.startIndex);
|
|
2892
2904
|
const localX = clientX - canvasRef.current.getBoundingClientRect().left;
|
|
2893
2905
|
const right = getHeaderCellLeft(cell) + getHeaderCellWidth(cell);
|
|
2894
|
-
return localX >= right -
|
|
2895
|
-
}, [columnDraggable, getHeaderCellLeft, getHeaderCellWidth, locateHeaderDragHandle]);
|
|
2906
|
+
return localX >= right - headerActionSlotWidth && localX < right - 2;
|
|
2907
|
+
}, [columnDraggable, getHeaderCellLeft, getHeaderCellWidth, headerActionSlotWidth, locateHeaderDragHandle]);
|
|
2896
2908
|
const locateHeaderCell = (0, import_react5.useCallback)((clientX, clientY) => {
|
|
2897
2909
|
const canvas = canvasRef.current;
|
|
2898
2910
|
if (!canvas) return null;
|
|
@@ -3048,26 +3060,32 @@ function TableInner({
|
|
|
3048
3060
|
header.style.height = `${headerHeight}px`;
|
|
3049
3061
|
header.style.justifyContent = column.align === "right" ? "flex-end" : column.align === "center" ? "center" : "flex-start";
|
|
3050
3062
|
header.textContent = column.title;
|
|
3051
|
-
const visibleActions = getVisibleHeaderActions(column, columnWidth, columnDraggable, measureHeaderTitleWidth(sourceIndex));
|
|
3063
|
+
const visibleActions = getVisibleHeaderActions(column, columnWidth, columnDraggable, measureHeaderTitleWidth(sourceIndex), headerActionSlotWidth);
|
|
3052
3064
|
let actionRight = 2;
|
|
3053
3065
|
if (visibleActions.drag) {
|
|
3054
3066
|
const icon = createHeaderDragHandleSvg();
|
|
3055
3067
|
icon.classList.add("rvg-preview-header-icon");
|
|
3068
|
+
icon.style.width = `${headerActionSize}px`;
|
|
3069
|
+
icon.style.height = `${headerActionSize}px`;
|
|
3056
3070
|
icon.style.right = `${actionRight}px`;
|
|
3057
3071
|
header.appendChild(icon);
|
|
3058
|
-
actionRight +=
|
|
3072
|
+
actionRight += headerActionSlotWidth;
|
|
3059
3073
|
}
|
|
3060
3074
|
if (visibleActions.sort) {
|
|
3061
3075
|
const direction = sortState?.columnKey === column.key ? sortState.direction : null;
|
|
3062
3076
|
const icon = createHeaderSortSvg(direction);
|
|
3063
3077
|
icon.classList.add("rvg-preview-header-icon");
|
|
3078
|
+
icon.style.width = `${headerActionSize}px`;
|
|
3079
|
+
icon.style.height = `${headerActionSize}px`;
|
|
3064
3080
|
icon.style.right = `${actionRight}px`;
|
|
3065
3081
|
header.appendChild(icon);
|
|
3066
|
-
actionRight +=
|
|
3082
|
+
actionRight += headerActionSlotWidth;
|
|
3067
3083
|
}
|
|
3068
3084
|
if (visibleActions.filter) {
|
|
3069
3085
|
const icon = createHeaderSearchSvg(Boolean(filterValues[column.key]));
|
|
3070
3086
|
icon.classList.add("rvg-preview-header-icon", "rvg-preview-header-search-icon");
|
|
3087
|
+
icon.style.width = `${headerActionSize}px`;
|
|
3088
|
+
icon.style.height = `${headerActionSize}px`;
|
|
3071
3089
|
icon.style.right = `${actionRight}px`;
|
|
3072
3090
|
header.appendChild(icon);
|
|
3073
3091
|
}
|
|
@@ -3264,7 +3282,7 @@ function TableInner({
|
|
|
3264
3282
|
cleanupDrag();
|
|
3265
3283
|
cleanupDrop();
|
|
3266
3284
|
};
|
|
3267
|
-
}, [applyColumnOrder, applyRowOrder, bodyTop, columnDraggable, columns, filterValues, fixedHeader, getCellLabel, getDisplayedColumnLeft, getHeaderCellWidth, getRowKey, headerCells, headerHeight, hideDragTooltips, locateColumn, locateHeaderCell, locateHeaderCellDragHandle, locateHeaderResizeCell, locateRow, measureHeaderTitleWidth, metrics, rowDraggable, rowHeight, rows, selectedRowKeySet, selection, setDragGuide, setRowDragGuide, sortState, utilityColumnCount]);
|
|
3285
|
+
}, [applyColumnOrder, applyRowOrder, bodyTop, columnDraggable, columns, filterValues, fixedHeader, getCellLabel, getDisplayedColumnLeft, getHeaderCellWidth, getRowKey, headerActionSize, headerActionSlotWidth, headerCells, headerHeight, hideDragTooltips, locateColumn, locateHeaderCell, locateHeaderCellDragHandle, locateHeaderResizeCell, locateRow, measureHeaderTitleWidth, metrics, rowDraggable, rowHeight, rows, selectedRowKeySet, selection, setDragGuide, setRowDragGuide, sortState, utilityColumnCount]);
|
|
3268
3286
|
const locateCell = (0, import_react5.useCallback)((clientX, clientY) => {
|
|
3269
3287
|
const canvas = canvasRef.current;
|
|
3270
3288
|
if (!canvas) return null;
|
|
@@ -3708,28 +3726,28 @@ function TableInner({
|
|
|
3708
3726
|
const renderHeaderIcons = (columnIndex, left) => {
|
|
3709
3727
|
const column = columns[columnIndex];
|
|
3710
3728
|
if (column.rowSelection || column.rowDragHandle || column.rowNumber) return null;
|
|
3711
|
-
const top = headerLeafTop + (headerLeafHeight -
|
|
3712
|
-
const visibleActions = getVisibleHeaderActions(column, metrics[columnIndex].width, columnDraggable, measureHeaderTitleWidth(columnIndex));
|
|
3713
|
-
let right = left + metrics[columnIndex].width - (visibleActions.drag ?
|
|
3729
|
+
const top = headerLeafTop + (headerLeafHeight - headerActionSize) / 2;
|
|
3730
|
+
const visibleActions = getVisibleHeaderActions(column, metrics[columnIndex].width, columnDraggable, measureHeaderTitleWidth(columnIndex), headerActionSlotWidth);
|
|
3731
|
+
let right = left + metrics[columnIndex].width - (visibleActions.drag ? headerActionSlotWidth : 2);
|
|
3714
3732
|
const icons = [];
|
|
3715
3733
|
if (visibleActions.drag) {
|
|
3716
3734
|
const hovered = hoveredHeaderAction?.columnIndex === columnIndex && hoveredHeaderAction.action === "drag";
|
|
3717
3735
|
icons.push(
|
|
3718
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(HeaderDragIcon, { className: `rvg-header-icon rvg-header-drag-icon${hovered ? " is-hovered" : ""}`, style: { left: left + metrics[columnIndex].width -
|
|
3736
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(HeaderDragIcon, { className: `rvg-header-icon rvg-header-drag-icon${hovered ? " is-hovered" : ""}`, style: { left: left + metrics[columnIndex].width - headerActionSlotWidth, top } }, "drag")
|
|
3719
3737
|
);
|
|
3720
3738
|
}
|
|
3721
3739
|
if (visibleActions.sort) {
|
|
3722
3740
|
const hovered = hoveredHeaderAction?.columnIndex === columnIndex && hoveredHeaderAction.action === "sort";
|
|
3723
3741
|
const direction = sortState?.columnKey === column.key ? sortState.direction : null;
|
|
3724
3742
|
icons.push(
|
|
3725
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(HeaderSortIcon, { className: `rvg-header-icon${hovered ? " is-hovered" : ""}`, style: { left: right -
|
|
3743
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(HeaderSortIcon, { className: `rvg-header-icon${hovered ? " is-hovered" : ""}`, style: { left: right - headerActionSlotWidth, top }, direction }, "sort")
|
|
3726
3744
|
);
|
|
3727
|
-
right -=
|
|
3745
|
+
right -= headerActionSlotWidth;
|
|
3728
3746
|
}
|
|
3729
3747
|
if (visibleActions.filter) {
|
|
3730
3748
|
const hovered = hoveredHeaderAction?.columnIndex === columnIndex && hoveredHeaderAction.action === "filter";
|
|
3731
3749
|
icons.push(
|
|
3732
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(HeaderSearchIcon, { className: `rvg-header-icon rvg-header-search-icon${hovered ? " is-hovered" : ""}${filterValues[column.key] ? " is-active" : ""}`, style: { left: right -
|
|
3750
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(HeaderSearchIcon, { className: `rvg-header-icon rvg-header-search-icon${hovered ? " is-hovered" : ""}${filterValues[column.key] ? " is-active" : ""}`, style: { left: right - headerActionSlotWidth, top: top + 1 } }, "filter")
|
|
3733
3751
|
);
|
|
3734
3752
|
}
|
|
3735
3753
|
return icons;
|
|
@@ -3750,8 +3768,8 @@ function TableInner({
|
|
|
3750
3768
|
const context = canvas?.getContext("2d");
|
|
3751
3769
|
if (context) context.font = "600 13px Inter, ui-sans-serif, system-ui, sans-serif";
|
|
3752
3770
|
const titleWidth = context?.measureText(column.title).width ?? column.title.length * 13;
|
|
3753
|
-
const visibleActions = cell?.leaf || !cell ? getVisibleHeaderActions(column, cellWidth, columnDraggable, titleWidth) : null;
|
|
3754
|
-
const actionWidth = visibleActions ? (Number(visibleActions.drag) + Number(visibleActions.filter) + Number(visibleActions.sort)) *
|
|
3771
|
+
const visibleActions = cell?.leaf || !cell ? getVisibleHeaderActions(column, cellWidth, columnDraggable, titleWidth, headerActionSlotWidth) : null;
|
|
3772
|
+
const actionWidth = visibleActions ? (Number(visibleActions.drag) + Number(visibleActions.filter) + Number(visibleActions.sort)) * headerActionSlotWidth : columnDraggable ? headerActionSlotWidth : 0;
|
|
3755
3773
|
const contentWidth2 = Math.max(0, cellWidth - actionWidth);
|
|
3756
3774
|
const maxTextWidth = Math.max(0, contentWidth2 - 20);
|
|
3757
3775
|
const textWidth = Math.min(titleWidth, maxTextWidth);
|
|
@@ -3772,12 +3790,17 @@ function TableInner({
|
|
|
3772
3790
|
} else if (action === "sort") {
|
|
3773
3791
|
const direction = sortState?.columnKey === column.key ? sortState.direction : null;
|
|
3774
3792
|
label = direction === "asc" ? labels.sortAsc : direction === "desc" ? labels.sortDesc : labels.sortBoth;
|
|
3775
|
-
|
|
3793
|
+
const visibleActions = getVisibleHeaderActions(column, cellWidth, columnDraggable, measureHeaderTitleWidth(columnIndex), headerActionSlotWidth);
|
|
3794
|
+
const right = cellLeft + cellWidth - (visibleActions.drag ? headerActionSlotWidth : 2);
|
|
3795
|
+
anchorX = right - headerActionSlotWidth / 2;
|
|
3776
3796
|
anchorLeft = anchorX;
|
|
3777
3797
|
} else if (action === "filter") {
|
|
3778
3798
|
const value = filterValues[column.key];
|
|
3779
3799
|
label = value ? labels.filterWithValue(value) : labels.filter;
|
|
3780
|
-
|
|
3800
|
+
const visibleActions = getVisibleHeaderActions(column, cellWidth, columnDraggable, measureHeaderTitleWidth(columnIndex), headerActionSlotWidth);
|
|
3801
|
+
let right = cellLeft + cellWidth - (visibleActions.drag ? headerActionSlotWidth : 2);
|
|
3802
|
+
if (visibleActions.sort) right -= headerActionSlotWidth;
|
|
3803
|
+
anchorX = right - headerActionSlotWidth / 2;
|
|
3781
3804
|
anchorLeft = anchorX;
|
|
3782
3805
|
}
|
|
3783
3806
|
const placement = anchorX + 328 > viewport.width ? "left" : "right";
|
|
@@ -3790,7 +3813,7 @@ function TableInner({
|
|
|
3790
3813
|
label,
|
|
3791
3814
|
placement
|
|
3792
3815
|
};
|
|
3793
|
-
}, [baseHeaderHeight, columnDraggable, columns, filterValues, fixedHeader, getDisplayedColumnLeft, getHeaderCellLeft, getHeaderCellWidth, headerDepth, headerRowHeights, headerRowOffsets, labels, metrics, scrollPosition.top, sortState, viewport.width]);
|
|
3816
|
+
}, [baseHeaderHeight, columnDraggable, columns, filterValues, fixedHeader, getDisplayedColumnLeft, getHeaderCellLeft, getHeaderCellWidth, headerActionSlotWidth, headerDepth, headerRowHeights, headerRowOffsets, labels, measureHeaderTitleWidth, metrics, scrollPosition.top, sortState, viewport.width]);
|
|
3794
3817
|
const isPointerOnHeaderTitle = (0, import_react5.useCallback)((clientX, clientY, cell) => {
|
|
3795
3818
|
const canvas = canvasRef.current;
|
|
3796
3819
|
if (!canvas) return false;
|
|
@@ -3804,14 +3827,14 @@ function TableInner({
|
|
|
3804
3827
|
const context = canvas.getContext("2d");
|
|
3805
3828
|
if (context) context.font = "600 13px Inter, ui-sans-serif, system-ui, sans-serif";
|
|
3806
3829
|
const titleWidth = context?.measureText(column.title).width ?? column.title.length * 13;
|
|
3807
|
-
const visibleActions = cell.leaf ? getVisibleHeaderActions(column, cellWidth, columnDraggable, titleWidth) : null;
|
|
3808
|
-
const actionWidth = visibleActions ? (Number(visibleActions.drag) + Number(visibleActions.filter) + Number(visibleActions.sort)) *
|
|
3830
|
+
const visibleActions = cell.leaf ? getVisibleHeaderActions(column, cellWidth, columnDraggable, titleWidth, headerActionSlotWidth) : null;
|
|
3831
|
+
const actionWidth = visibleActions ? (Number(visibleActions.drag) + Number(visibleActions.filter) + Number(visibleActions.sort)) * headerActionSlotWidth : columnDraggable ? headerActionSlotWidth : 0;
|
|
3809
3832
|
const contentWidth2 = Math.max(0, cellWidth - actionWidth);
|
|
3810
3833
|
const textWidth = Math.min(titleWidth, Math.max(0, contentWidth2 - 20));
|
|
3811
3834
|
const textLeft = column.align === "right" ? cellLeft + contentWidth2 - 10 - textWidth : column.align === "center" ? cellLeft + contentWidth2 / 2 - textWidth / 2 : cellLeft + 10;
|
|
3812
3835
|
const textTop = rowTop + 8;
|
|
3813
3836
|
return localX >= textLeft - 4 && localX <= textLeft + textWidth + 4 && localY >= textTop - 2 && localY <= textTop + 18;
|
|
3814
|
-
}, [columnDraggable, fixedHeader, getHeaderCellLeft, getHeaderCellWidth, headerRowOffsets]);
|
|
3837
|
+
}, [columnDraggable, fixedHeader, getHeaderCellLeft, getHeaderCellWidth, headerActionSlotWidth, headerRowOffsets]);
|
|
3815
3838
|
const headerTooltip = (() => {
|
|
3816
3839
|
if (!visibleHeaderTooltip) return null;
|
|
3817
3840
|
return visibleHeaderTooltip;
|
|
@@ -4134,8 +4157,8 @@ function TableInner({
|
|
|
4134
4157
|
);
|
|
4135
4158
|
}
|
|
4136
4159
|
if (column.renderHeader) {
|
|
4137
|
-
const visibleActions = getVisibleHeaderActions(column, metrics[columnIndex].width, columnDraggable, measureHeaderTitleWidth(columnIndex));
|
|
4138
|
-
const actionWidth = (Number(visibleActions.drag) + Number(visibleActions.filter) + Number(visibleActions.sort)) *
|
|
4160
|
+
const visibleActions = getVisibleHeaderActions(column, metrics[columnIndex].width, columnDraggable, measureHeaderTitleWidth(columnIndex), headerActionSlotWidth);
|
|
4161
|
+
const actionWidth = (Number(visibleActions.drag) + Number(visibleActions.filter) + Number(visibleActions.sort)) * headerActionSlotWidth;
|
|
4139
4162
|
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
4140
4163
|
"div",
|
|
4141
4164
|
{
|
|
@@ -4179,13 +4202,13 @@ function TableInner({
|
|
|
4179
4202
|
const headerTop = (fixedHeader ? 0 : -currentScrollTop) + (headerRowOffsets[cell.level] ?? 0);
|
|
4180
4203
|
const left = fixedSide === "left" ? leftFixedOffsets.get(cell.startIndex) ?? 0 : fixedSide === "right" ? viewport.width - (rightFixedOffsets.get(cell.startIndex) ?? 0) - startMetric.width : getScrollableColumnLeft(cell.startIndex);
|
|
4181
4204
|
const width2 = cell.leaf ? startMetric.width : getCellDisplayWidth(cell.startIndex, cell.endIndex - cell.startIndex + 1);
|
|
4182
|
-
const visibleActions = cell.leaf ? getVisibleHeaderActions(column, startMetric.width, columnDraggable, measureHeaderTitleWidth(cell.startIndex)) : null;
|
|
4183
|
-
const actionWidth = visibleActions ? (Number(visibleActions.drag) + Number(visibleActions.filter) + Number(visibleActions.sort)) *
|
|
4205
|
+
const visibleActions = cell.leaf ? getVisibleHeaderActions(column, startMetric.width, columnDraggable, measureHeaderTitleWidth(cell.startIndex), headerActionSlotWidth) : null;
|
|
4206
|
+
const actionWidth = visibleActions ? (Number(visibleActions.drag) + Number(visibleActions.filter) + Number(visibleActions.sort)) * headerActionSlotWidth : columnDraggable && !cell.leaf ? headerActionSlotWidth : 0;
|
|
4184
4207
|
const isDropTarget = Boolean(columnDropTarget && cell.endIndex >= columnDropTarget.startIndex && cell.startIndex <= columnDropTarget.endIndex);
|
|
4185
4208
|
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
4186
4209
|
"div",
|
|
4187
4210
|
{
|
|
4188
|
-
className: `rvg-header-title rvg-header-group${column.renderHeader ? " is-custom" : ""}${cell.leaf ? " is-leaf" : ""}${isDropTarget ? " is-drop-target" : ""}`,
|
|
4211
|
+
className: `rvg-header-title rvg-header-group${column.renderHeader ? " is-custom" : ""}${cell.leaf ? " is-leaf" : ""}${cell.endIndex === columns.length - 1 ? " is-frame-right" : ""}${isDropTarget ? " is-drop-target" : ""}`,
|
|
4189
4212
|
"data-level": cell.level,
|
|
4190
4213
|
"data-measure-key": `group:${cell.key}:${cell.level}`,
|
|
4191
4214
|
style: {
|
|
@@ -4216,7 +4239,7 @@ function TableInner({
|
|
|
4216
4239
|
HeaderDragIcon,
|
|
4217
4240
|
{
|
|
4218
4241
|
className: `rvg-header-icon rvg-header-drag-icon${hoveredHeaderAction?.columnIndex === cell.startIndex && hoveredHeaderAction.action === "drag" ? " is-hovered" : ""}`,
|
|
4219
|
-
style: { left: width2 -
|
|
4242
|
+
style: { left: width2 - headerActionSlotWidth, top: (rowHeightForLevel - headerActionSize) / 2 }
|
|
4220
4243
|
}
|
|
4221
4244
|
)
|
|
4222
4245
|
]
|
|
@@ -4482,12 +4505,13 @@ function TableInner({
|
|
|
4482
4505
|
width,
|
|
4483
4506
|
height: autoHeight ? effectiveHeight : height,
|
|
4484
4507
|
minHeight: autoHeight || typeof height === "number" ? void 0 : FALLBACK_HEIGHT,
|
|
4508
|
+
"--rvg-header-action-size": `${headerActionSize}px`,
|
|
4485
4509
|
...stripedColor ? { "--rvg-color-stripe": stripedColor } : null,
|
|
4486
4510
|
...style
|
|
4487
4511
|
};
|
|
4488
4512
|
const currentScroll = scrollRef.current;
|
|
4489
4513
|
const scrollerBottom = Math.max(0, bottomSummaryHeight - horizontalScrollbarHeight);
|
|
4490
|
-
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: `rvg-root${!hasVerticalBorders ? " is-vertical-borderless" : ""}${horizontalBorderless ? " is-horizontal-borderless" : ""}${hasStripedRows ? " is-striped" : ""}${insertBusy ? " is-inserting" : ""}${deleteBusy ? " is-deleting" : ""} ${loading && !hasCompletedLoadRef.current && !hasCustomLoading ? "is-initial-loading" : ""} ${className}`, style: rootStyle, children: [
|
|
4514
|
+
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: [
|
|
4491
4515
|
/* @__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: [
|
|
4492
4516
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
4493
4517
|
"canvas",
|
|
@@ -4547,7 +4571,10 @@ function TableInner({
|
|
|
4547
4571
|
} else {
|
|
4548
4572
|
const label = getCellLabel(cell.rowIndex, cell.columnIndex);
|
|
4549
4573
|
const context = event.currentTarget.getContext("2d");
|
|
4550
|
-
if (context)
|
|
4574
|
+
if (context) {
|
|
4575
|
+
const bodyFontSize = readThemePixel(getComputedStyle(event.currentTarget), "--rvg-font-size-body", 13);
|
|
4576
|
+
context.font = `${bodyFontSize}px Inter, ui-sans-serif, system-ui, sans-serif`;
|
|
4577
|
+
}
|
|
4551
4578
|
const truncated = Boolean(label && context && context.measureText(label).width + 20 > metrics[cell.columnIndex].width);
|
|
4552
4579
|
if (!label || !tooltipConfig.cell && !truncated) {
|
|
4553
4580
|
showCellTooltipAfterDelay(null);
|
package/dist/index.css
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/* src/style.css */
|
|
2
2
|
:root {
|
|
3
|
+
--rvg-font-size-body: 13px;
|
|
3
4
|
--rvg-color-bg: #fff;
|
|
4
5
|
--rvg-color-header-bg: #f5f6f7;
|
|
5
6
|
--rvg-color-grid: #e3e6e8;
|
|
@@ -205,11 +206,12 @@
|
|
|
205
206
|
padding: 0 10px;
|
|
206
207
|
overflow: hidden;
|
|
207
208
|
color: var(--rvg-color-text);
|
|
208
|
-
font:
|
|
209
|
-
|
|
209
|
+
font-family:
|
|
210
|
+
Inter,
|
|
210
211
|
ui-sans-serif,
|
|
211
212
|
system-ui,
|
|
212
213
|
sans-serif;
|
|
214
|
+
font-size: 13px;
|
|
213
215
|
white-space: nowrap;
|
|
214
216
|
user-select: text;
|
|
215
217
|
pointer-events: auto;
|
|
@@ -220,6 +222,7 @@
|
|
|
220
222
|
cursor: default;
|
|
221
223
|
}
|
|
222
224
|
.rvg-cell-text {
|
|
225
|
+
font-size: var(--rvg-font-size-body);
|
|
223
226
|
transition: transform 140ms ease, opacity 100ms ease;
|
|
224
227
|
}
|
|
225
228
|
.rvg-row-drop-settling .rvg-cell-text {
|
|
@@ -251,11 +254,12 @@
|
|
|
251
254
|
align-items: center;
|
|
252
255
|
overflow: hidden;
|
|
253
256
|
color: var(--rvg-color-text);
|
|
254
|
-
font:
|
|
255
|
-
|
|
257
|
+
font-family:
|
|
258
|
+
Inter,
|
|
256
259
|
ui-sans-serif,
|
|
257
260
|
system-ui,
|
|
258
261
|
sans-serif;
|
|
262
|
+
font-size: var(--rvg-font-size-body);
|
|
259
263
|
white-space: nowrap;
|
|
260
264
|
pointer-events: none;
|
|
261
265
|
box-sizing: border-box;
|
|
@@ -753,6 +757,9 @@
|
|
|
753
757
|
background: var(--rvg-color-header-bg);
|
|
754
758
|
box-sizing: border-box;
|
|
755
759
|
}
|
|
760
|
+
.rvg-root.is-frame-borderless .rvg-header-group.is-frame-right {
|
|
761
|
+
border-right: 0;
|
|
762
|
+
}
|
|
756
763
|
.rvg-root.is-horizontal-borderless .rvg-header-group {
|
|
757
764
|
border-bottom: 0;
|
|
758
765
|
}
|
|
@@ -813,6 +820,9 @@
|
|
|
813
820
|
content: "";
|
|
814
821
|
pointer-events: none;
|
|
815
822
|
}
|
|
823
|
+
.rvg-root.is-frame-borderless .rvg-header-icons::after {
|
|
824
|
+
display: none;
|
|
825
|
+
}
|
|
816
826
|
.rvg-root.is-vertical-borderless .rvg-header-icons::after {
|
|
817
827
|
display: none;
|
|
818
828
|
}
|
|
@@ -832,8 +842,8 @@
|
|
|
832
842
|
}
|
|
833
843
|
.rvg-header-icon {
|
|
834
844
|
position: absolute;
|
|
835
|
-
width: 14px;
|
|
836
|
-
height: 14px;
|
|
845
|
+
width: var(--rvg-header-action-size, 14px);
|
|
846
|
+
height: var(--rvg-header-action-size, 14px);
|
|
837
847
|
overflow: visible;
|
|
838
848
|
color: var(--rvg-color-icon);
|
|
839
849
|
}
|
|
@@ -1587,7 +1597,7 @@
|
|
|
1587
1597
|
background: var(--rvg-color-bg);
|
|
1588
1598
|
color: var(--rvg-color-text);
|
|
1589
1599
|
font:
|
|
1590
|
-
|
|
1600
|
+
var(--rvg-font-size-body) Inter,
|
|
1591
1601
|
ui-sans-serif,
|
|
1592
1602
|
system-ui,
|
|
1593
1603
|
sans-serif;
|
|
@@ -1635,7 +1645,7 @@
|
|
|
1635
1645
|
background: transparent;
|
|
1636
1646
|
color: var(--rvg-color-text);
|
|
1637
1647
|
font:
|
|
1638
|
-
|
|
1648
|
+
var(--rvg-font-size-body) Inter,
|
|
1639
1649
|
ui-sans-serif,
|
|
1640
1650
|
system-ui,
|
|
1641
1651
|
sans-serif;
|
|
@@ -1670,7 +1680,7 @@
|
|
|
1670
1680
|
background: transparent;
|
|
1671
1681
|
color: var(--rvg-color-text);
|
|
1672
1682
|
font:
|
|
1673
|
-
|
|
1683
|
+
var(--rvg-font-size-body) Inter,
|
|
1674
1684
|
ui-sans-serif,
|
|
1675
1685
|
system-ui,
|
|
1676
1686
|
sans-serif;
|
|
@@ -1903,7 +1913,7 @@
|
|
|
1903
1913
|
background: var(--rvg-color-bg);
|
|
1904
1914
|
color: var(--rvg-color-text);
|
|
1905
1915
|
font:
|
|
1906
|
-
|
|
1916
|
+
var(--rvg-font-size-body) Inter,
|
|
1907
1917
|
ui-sans-serif,
|
|
1908
1918
|
system-ui,
|
|
1909
1919
|
sans-serif;
|
package/dist/index.d.cts
CHANGED
|
@@ -121,6 +121,8 @@ interface TableLayoutConfig {
|
|
|
121
121
|
rowHeight?: number;
|
|
122
122
|
/** Header height in pixels. Defaults to 40. */
|
|
123
123
|
headerHeight?: number;
|
|
124
|
+
/** Header action icon size in pixels. Defaults to 14. */
|
|
125
|
+
headerActionSize?: number;
|
|
124
126
|
}
|
|
125
127
|
interface TableCellSpan {
|
|
126
128
|
/** Row index in the current rows array. Prefer rowKey when row order can change. */
|
|
@@ -349,6 +351,8 @@ interface TableProps<Row extends object> {
|
|
|
349
351
|
verticalBorderless?: boolean;
|
|
350
352
|
/** Hide horizontal row and frame separators while keeping vertical grid lines. */
|
|
351
353
|
horizontalBorderless?: boolean;
|
|
354
|
+
/** Hide the outer table frame while keeping internal row and column separators. */
|
|
355
|
+
frameBorderless?: boolean;
|
|
352
356
|
/** Paint alternating row backgrounds. Pass a color string to customize the stripe color. */
|
|
353
357
|
striped?: boolean | string;
|
|
354
358
|
/** Visual highlight feedback configuration. All entries default to false. */
|
package/dist/index.d.ts
CHANGED
|
@@ -121,6 +121,8 @@ interface TableLayoutConfig {
|
|
|
121
121
|
rowHeight?: number;
|
|
122
122
|
/** Header height in pixels. Defaults to 40. */
|
|
123
123
|
headerHeight?: number;
|
|
124
|
+
/** Header action icon size in pixels. Defaults to 14. */
|
|
125
|
+
headerActionSize?: number;
|
|
124
126
|
}
|
|
125
127
|
interface TableCellSpan {
|
|
126
128
|
/** Row index in the current rows array. Prefer rowKey when row order can change. */
|
|
@@ -349,6 +351,8 @@ interface TableProps<Row extends object> {
|
|
|
349
351
|
verticalBorderless?: boolean;
|
|
350
352
|
/** Hide horizontal row and frame separators while keeping vertical grid lines. */
|
|
351
353
|
horizontalBorderless?: boolean;
|
|
354
|
+
/** Hide the outer table frame while keeping internal row and column separators. */
|
|
355
|
+
frameBorderless?: boolean;
|
|
352
356
|
/** Paint alternating row backgrounds. Pass a color string to customize the stripe color. */
|
|
353
357
|
striped?: boolean | string;
|
|
354
358
|
/** Visual highlight feedback configuration. All entries default to false. */
|
package/dist/index.js
CHANGED
|
@@ -662,18 +662,6 @@ function DateEditor({ editor, value: draft, style, locale, labels, onChange, onC
|
|
|
662
662
|
);
|
|
663
663
|
}
|
|
664
664
|
|
|
665
|
-
// src/core/typography.ts
|
|
666
|
-
var CELL_FONT = "13px Inter, ui-sans-serif, system-ui, sans-serif";
|
|
667
|
-
function getCellBaselineOffset(context) {
|
|
668
|
-
context.save();
|
|
669
|
-
context.textBaseline = "alphabetic";
|
|
670
|
-
const metrics = context.measureText("Mg");
|
|
671
|
-
context.restore();
|
|
672
|
-
const ascent = metrics.fontBoundingBoxAscent;
|
|
673
|
-
const descent = metrics.fontBoundingBoxDescent;
|
|
674
|
-
return Number.isFinite(ascent) && Number.isFinite(descent) ? (ascent - descent) / 2 : 0;
|
|
675
|
-
}
|
|
676
|
-
|
|
677
665
|
// src/components/editors/TextEditor.tsx
|
|
678
666
|
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
679
667
|
function TextEditor({ value, type, style, labels, onChange, onCommit, onCancel }) {
|
|
@@ -687,7 +675,7 @@ function TextEditor({ value, type, style, labels, onChange, onCommit, onCancel }
|
|
|
687
675
|
"input",
|
|
688
676
|
{
|
|
689
677
|
type,
|
|
690
|
-
style: { font:
|
|
678
|
+
style: { font: "var(--rvg-font-size-body) Inter, ui-sans-serif, system-ui, sans-serif", textAlign: style.textAlign },
|
|
691
679
|
value,
|
|
692
680
|
autoFocus: true,
|
|
693
681
|
onChange: (event) => onChange(event.target.value),
|
|
@@ -804,8 +792,8 @@ function getHeaderTitleRequiredWidth(column, titleWidth) {
|
|
|
804
792
|
const minimumReadableTitleWidth = Math.min(Math.ceil(titleWidth), 28);
|
|
805
793
|
return minimumReadableTitleWidth + (column.align === "center" ? 20 : 22);
|
|
806
794
|
}
|
|
807
|
-
function getVisibleHeaderActions(column, width, columnDraggable = false, titleWidth = 26) {
|
|
808
|
-
const capacity = Math.max(0, Math.floor((width - getHeaderTitleRequiredWidth(column, titleWidth)) /
|
|
795
|
+
function getVisibleHeaderActions(column, width, columnDraggable = false, titleWidth = 26, actionSlotWidth = HEADER_ACTION_SLOT_WIDTH) {
|
|
796
|
+
const capacity = Math.max(0, Math.floor((width - getHeaderTitleRequiredWidth(column, titleWidth)) / actionSlotWidth));
|
|
809
797
|
const candidates = [
|
|
810
798
|
isColumnFilterable(column) ? "filter" : null,
|
|
811
799
|
isColumnSortable(column) ? "sort" : null,
|
|
@@ -876,6 +864,18 @@ function hitTestColumn(metrics, contentX) {
|
|
|
876
864
|
return index < metrics.length ? index : -1;
|
|
877
865
|
}
|
|
878
866
|
|
|
867
|
+
// src/core/typography.ts
|
|
868
|
+
var createCellFont = (fontSize = 13) => `${fontSize}px Inter, ui-sans-serif, system-ui, sans-serif`;
|
|
869
|
+
function getCellBaselineOffset(context) {
|
|
870
|
+
context.save();
|
|
871
|
+
context.textBaseline = "alphabetic";
|
|
872
|
+
const metrics = context.measureText("Mg");
|
|
873
|
+
context.restore();
|
|
874
|
+
const ascent = metrics.fontBoundingBoxAscent;
|
|
875
|
+
const descent = metrics.fontBoundingBoxDescent;
|
|
876
|
+
return Number.isFinite(ascent) && Number.isFinite(descent) ? (ascent - descent) / 2 : 0;
|
|
877
|
+
}
|
|
878
|
+
|
|
879
879
|
// src/core/render.ts
|
|
880
880
|
var getCellCoordKey = (rowIndex, columnIndex) => `${rowIndex}:${columnIndex}`;
|
|
881
881
|
var COLORS = {
|
|
@@ -912,7 +912,7 @@ function ellipsizeText(context, text, maxWidth) {
|
|
|
912
912
|
return `${text.slice(0, start)}${ellipsis}`;
|
|
913
913
|
}
|
|
914
914
|
function paintGrid(options) {
|
|
915
|
-
const { context: ctx, width, height, pixelRatio, scrollLeft, scrollTop, rowHeight, headerHeight, fixedHeader, verticalBorderless, horizontalBorderless, striped, columnDraggable, sortState, filterValues, hoveredHeaderAction, rows, columns, metrics, range, selection, editing, hoveredRowIndex, selectionRange, selectedRowKeys, rowSelectionMode, selectedColumnKeys, highlightEditedCells, highlightInsertedRows, insertedRowKeys, editedCellKeys, cellAnnotations, getRowKey, rowDragPreview, columnDropTarget } = options;
|
|
915
|
+
const { context: ctx, width, height, pixelRatio, scrollLeft, scrollTop, rowHeight, bodyFontSize, headerActionSlotWidth, headerHeight, fixedHeader, verticalBorderless, horizontalBorderless, frameBorderless, striped, columnDraggable, sortState, filterValues, hoveredHeaderAction, rows, columns, metrics, range, selection, editing, hoveredRowIndex, selectionRange, selectedRowKeys, rowSelectionMode, selectedColumnKeys, highlightEditedCells, highlightInsertedRows, insertedRowKeys, editedCellKeys, cellAnnotations, getRowKey, rowDragPreview, columnDropTarget } = options;
|
|
916
916
|
const headerLeafTop = options.headerLeafTop ?? 0;
|
|
917
917
|
const headerLeafHeight = options.headerLeafHeight ?? headerHeight;
|
|
918
918
|
const colors = { ...COLORS, ...options.colors };
|
|
@@ -929,7 +929,7 @@ function paintGrid(options) {
|
|
|
929
929
|
ctx.clearRect(0, 0, width, height);
|
|
930
930
|
ctx.fillStyle = colors.background;
|
|
931
931
|
ctx.fillRect(0, 0, width, height);
|
|
932
|
-
ctx.font =
|
|
932
|
+
ctx.font = createCellFont(bodyFontSize);
|
|
933
933
|
const cellBaselineOffset = getCellBaselineOffset(ctx);
|
|
934
934
|
ctx.textBaseline = "middle";
|
|
935
935
|
const leftFixedWidth = columns.reduce((value, column, index) => column.fixed === "left" ? value + metrics[index].width : value, 0);
|
|
@@ -1033,7 +1033,9 @@ function paintGrid(options) {
|
|
|
1033
1033
|
ctx.fillRect(x, y, cellWidth, cellHeight);
|
|
1034
1034
|
}
|
|
1035
1035
|
ctx.fillStyle = colors.grid;
|
|
1036
|
-
if (!verticalBorderless
|
|
1036
|
+
if (!verticalBorderless && !(frameBorderless && columnIndex + colSpan >= columns.length)) {
|
|
1037
|
+
ctx.fillRect(x + cellWidth - 1, y, 1, cellHeight);
|
|
1038
|
+
}
|
|
1037
1039
|
if (rowIndex === rowBelowDragGap) ctx.fillRect(x, y, cellWidth, 1);
|
|
1038
1040
|
if (!horizontalBorderless && (!options.suppressLastRowBottomBorder || rowIndex !== rows.length - 1)) {
|
|
1039
1041
|
ctx.fillRect(x, y + cellHeight - 1, cellWidth, 1);
|
|
@@ -1129,7 +1131,7 @@ function paintGrid(options) {
|
|
|
1129
1131
|
ctx.rect(x + 2, y + 1, Math.max(0, cellWidth - 4), cellHeight - 2);
|
|
1130
1132
|
ctx.clip();
|
|
1131
1133
|
ctx.fillStyle = cellStyle?.color ?? colors.text;
|
|
1132
|
-
ctx.font =
|
|
1134
|
+
ctx.font = createCellFont(bodyFontSize);
|
|
1133
1135
|
ctx.textBaseline = "alphabetic";
|
|
1134
1136
|
ctx.textAlign = column.align === "right" ? "right" : column.align === "center" ? "center" : "left";
|
|
1135
1137
|
ctx.fillText(label, textX, y + cellHeight / 2 + cellBaselineOffset);
|
|
@@ -1175,14 +1177,16 @@ function paintGrid(options) {
|
|
|
1175
1177
|
ctx.fillRect(x, headerY, metric.width, headerHeight);
|
|
1176
1178
|
}
|
|
1177
1179
|
ctx.fillStyle = colors.grid;
|
|
1178
|
-
if (!verticalBorderless
|
|
1180
|
+
if (!verticalBorderless && !(frameBorderless && columnIndex === columns.length - 1)) {
|
|
1181
|
+
ctx.fillRect(x + metric.width - 1, headerY, 1, headerHeight);
|
|
1182
|
+
}
|
|
1179
1183
|
if (!horizontalBorderless) ctx.fillRect(x, headerY + headerHeight - 1, metric.width, 1);
|
|
1180
1184
|
const column = columns[columnIndex];
|
|
1181
1185
|
if (headerLeafTop === 0 && !column.rowSelection && !column.rowDragHandle && !column.rowNumber && !column.renderHeader && column.title) {
|
|
1182
1186
|
ctx.font = "600 13px Inter, ui-sans-serif, system-ui, sans-serif";
|
|
1183
1187
|
const titleWidth = ctx.measureText(column.title).width;
|
|
1184
|
-
const visibleActions = getVisibleHeaderActions(column, metric.width, columnDraggable, titleWidth);
|
|
1185
|
-
const actionWidth = (Number(visibleActions.drag) + Number(visibleActions.filter) + Number(visibleActions.sort)) *
|
|
1188
|
+
const visibleActions = getVisibleHeaderActions(column, metric.width, columnDraggable, titleWidth, headerActionSlotWidth);
|
|
1189
|
+
const actionWidth = (Number(visibleActions.drag) + Number(visibleActions.filter) + Number(visibleActions.sort)) * headerActionSlotWidth;
|
|
1186
1190
|
const contentWidth = Math.max(0, metric.width - actionWidth);
|
|
1187
1191
|
const padding = 10;
|
|
1188
1192
|
const clipWidth = contentWidth;
|
|
@@ -1212,12 +1216,12 @@ function paintGrid(options) {
|
|
|
1212
1216
|
ctx.fillRect(rightFixedLeft - 1, 0, 1, height);
|
|
1213
1217
|
}
|
|
1214
1218
|
ctx.fillStyle = colors.grid;
|
|
1215
|
-
if (!horizontalBorderless) ctx.fillRect(0, 0, width, 1);
|
|
1216
|
-
if (!verticalBorderless) {
|
|
1219
|
+
if (!horizontalBorderless && !frameBorderless) ctx.fillRect(0, 0, width, 1);
|
|
1220
|
+
if (!verticalBorderless && !frameBorderless) {
|
|
1217
1221
|
ctx.fillRect(0, 0, 1, height);
|
|
1218
1222
|
ctx.fillRect(width - 1, 0, 1, height);
|
|
1219
1223
|
}
|
|
1220
|
-
if (!horizontalBorderless && !options.suppressFrameBottomBorder) ctx.fillRect(0, height - 1, width, 1);
|
|
1224
|
+
if (!horizontalBorderless && !frameBorderless && !options.suppressFrameBottomBorder) ctx.fillRect(0, height - 1, width, 1);
|
|
1221
1225
|
if (selectionRange) {
|
|
1222
1226
|
const rowStart = Math.min(selectionRange.anchor.rowIndex, selectionRange.focus.rowIndex);
|
|
1223
1227
|
const rowEnd = Math.max(selectionRange.anchor.rowIndex, selectionRange.focus.rowIndex);
|
|
@@ -1438,6 +1442,10 @@ var waitForPaint = () => new Promise((resolve) => {
|
|
|
1438
1442
|
function readThemeColor(styles, name, fallback) {
|
|
1439
1443
|
return styles.getPropertyValue(name).trim() || fallback;
|
|
1440
1444
|
}
|
|
1445
|
+
function readThemePixel(styles, name, fallback) {
|
|
1446
|
+
const value = Number.parseFloat(styles.getPropertyValue(name));
|
|
1447
|
+
return Number.isFinite(value) && value > 0 ? value : fallback;
|
|
1448
|
+
}
|
|
1441
1449
|
function getDefaultRowKey(row, index) {
|
|
1442
1450
|
const id = row.id;
|
|
1443
1451
|
return typeof id === "string" || typeof id === "number" ? id : index;
|
|
@@ -1522,6 +1530,7 @@ function TableInner({
|
|
|
1522
1530
|
borderless,
|
|
1523
1531
|
verticalBorderless,
|
|
1524
1532
|
horizontalBorderless = false,
|
|
1533
|
+
frameBorderless = false,
|
|
1525
1534
|
striped = false,
|
|
1526
1535
|
highlight,
|
|
1527
1536
|
cellSpans = [],
|
|
@@ -1568,6 +1577,8 @@ function TableInner({
|
|
|
1568
1577
|
setSourceColumns((current) => reconcileColumns(current, columnProps));
|
|
1569
1578
|
}, [columnProps]);
|
|
1570
1579
|
const rowHeight = layout?.rowHeight ?? rowHeightProp ?? 36;
|
|
1580
|
+
const headerActionSize = Math.max(8, layout?.headerActionSize ?? 14);
|
|
1581
|
+
const headerActionSlotWidth = headerActionSize + 2;
|
|
1571
1582
|
const baseHeaderHeight = layout?.headerHeight ?? headerHeightProp ?? 40;
|
|
1572
1583
|
const headerDepth = useMemo(() => Math.max(1, ...sourceColumns.map(getColumnDepth)), [sourceColumns]);
|
|
1573
1584
|
const { language, labels } = useMemo(() => resolveGridLocale(locale), [locale]);
|
|
@@ -2182,6 +2193,7 @@ function TableInner({
|
|
|
2182
2193
|
const context = canvas.getContext("2d");
|
|
2183
2194
|
if (!context) return;
|
|
2184
2195
|
const themeStyles = getComputedStyle(canvas);
|
|
2196
|
+
const bodyFontSize = readThemePixel(themeStyles, "--rvg-font-size-body", 13);
|
|
2185
2197
|
const themeColors = {
|
|
2186
2198
|
background: readThemeColor(themeStyles, "--rvg-color-bg", "#ffffff"),
|
|
2187
2199
|
header: readThemeColor(themeStyles, "--rvg-color-header-bg", "#f5f6f7"),
|
|
@@ -2202,8 +2214,8 @@ function TableInner({
|
|
|
2202
2214
|
const scroll = scrollRef.current;
|
|
2203
2215
|
const rowScrollTop = fixedHeader ? scroll.top : Math.max(0, scroll.top - bodyTop);
|
|
2204
2216
|
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 };
|
|
2205
|
-
paintGrid({ context, width: viewport.width, height: renderHeight, pixelRatio: ratio, scrollLeft: scroll.left, scrollTop: scroll.top, rowHeight, headerHeight, headerLeafTop, headerLeafHeight, bodyTop, suppressLastRowBottomBorder: bottomSummaryHeight > 0, suppressFrameBottomBorder: bottomSummaryHeight > 0, fixedHeader, verticalBorderless: !hasVerticalBorders, horizontalBorderless, 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 });
|
|
2206
|
-
}, [bodyTop, bodyViewportHeight, bottomSummaryHeight, cellAnnotations, cellSpanLookup, columnDraggable, columnDropTarget, columns, editedCellHighlightColor, editedCellKeys, editing, renderHeight, filterValues, fixedHeader, getRowKey, hasStripedRows, hasVerticalBorders, headerDepth, headerHeight, headerLeafHeight, headerLeafTop, horizontalBorderless, highlightsEditedCells, highlightsInsertedRows, insertedRowHighlightColor, insertedRowKeySet, isVirtualized, metrics, rowDragPreview, rowHeight, rowSelectionMode, rows, selectedColumnKeySet, selectedRowKeySet, selection, selectionRange, sortState, stripedColor, viewport.width, virtualOverscan]);
|
|
2217
|
+
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, 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 });
|
|
2218
|
+
}, [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]);
|
|
2207
2219
|
const scheduleDraw = useCallback2(() => {
|
|
2208
2220
|
if (frameRef.current === null) frameRef.current = requestAnimationFrame(draw);
|
|
2209
2221
|
}, [draw]);
|
|
@@ -2769,34 +2781,34 @@ function TableInner({
|
|
|
2769
2781
|
if (column.rowSelection || column.rowDragHandle || column.rowNumber) return null;
|
|
2770
2782
|
const localX = clientX - canvasRef.current.getBoundingClientRect().left;
|
|
2771
2783
|
const columnRight = getDisplayedColumnLeft(columnIndex) + metrics[columnIndex].width;
|
|
2772
|
-
const visibleActions = getVisibleHeaderActions(column, metrics[columnIndex].width, columnDraggable, measureHeaderTitleWidth(columnIndex));
|
|
2773
|
-
let right = columnRight - (visibleActions.drag ?
|
|
2784
|
+
const visibleActions = getVisibleHeaderActions(column, metrics[columnIndex].width, columnDraggable, measureHeaderTitleWidth(columnIndex), headerActionSlotWidth);
|
|
2785
|
+
let right = columnRight - (visibleActions.drag ? headerActionSlotWidth : 2);
|
|
2774
2786
|
if (visibleActions.sort) {
|
|
2775
|
-
if (localX >= right -
|
|
2776
|
-
right -=
|
|
2787
|
+
if (localX >= right - headerActionSlotWidth && localX < right) return "sort";
|
|
2788
|
+
right -= headerActionSlotWidth;
|
|
2777
2789
|
}
|
|
2778
|
-
if (visibleActions.filter && localX >= right -
|
|
2790
|
+
if (visibleActions.filter && localX >= right - headerActionSlotWidth && localX < right) return "filter";
|
|
2779
2791
|
return null;
|
|
2780
|
-
}, [columnDraggable, columns, getDisplayedColumnLeft, measureHeaderTitleWidth, metrics]);
|
|
2792
|
+
}, [columnDraggable, columns, getDisplayedColumnLeft, headerActionSlotWidth, measureHeaderTitleWidth, metrics]);
|
|
2781
2793
|
const isHeaderTitleTruncated = useCallback2((columnIndex) => {
|
|
2782
2794
|
const canvas = canvasRef.current;
|
|
2783
2795
|
if (columnIndex < 0 || !canvas) return false;
|
|
2784
2796
|
const column = columns[columnIndex];
|
|
2785
2797
|
const metric = metrics[columnIndex];
|
|
2786
2798
|
const titleWidth = measureHeaderTitleWidth(columnIndex);
|
|
2787
|
-
const visibleActions = getVisibleHeaderActions(column, metric.width, columnDraggable, titleWidth);
|
|
2788
|
-
const actionWidth = (Number(visibleActions.drag) + Number(visibleActions.filter) + Number(visibleActions.sort)) *
|
|
2799
|
+
const visibleActions = getVisibleHeaderActions(column, metric.width, columnDraggable, titleWidth, headerActionSlotWidth);
|
|
2800
|
+
const actionWidth = (Number(visibleActions.drag) + Number(visibleActions.filter) + Number(visibleActions.sort)) * headerActionSlotWidth;
|
|
2789
2801
|
return getHeaderTitleRequiredWidth(column, titleWidth) > Math.max(0, metric.width - actionWidth);
|
|
2790
|
-
}, [columnDraggable, columns, measureHeaderTitleWidth, metrics]);
|
|
2802
|
+
}, [columnDraggable, columns, headerActionSlotWidth, measureHeaderTitleWidth, metrics]);
|
|
2791
2803
|
const locateHeaderDragHandle = useCallback2((clientX, columnIndex) => {
|
|
2792
2804
|
if (!columnDraggable || columnIndex < 0 || !canvasRef.current) return false;
|
|
2793
2805
|
const column = columns[columnIndex];
|
|
2794
2806
|
if (column.rowSelection || column.rowDragHandle || column.rowNumber) return false;
|
|
2795
|
-
if (!getVisibleHeaderActions(column, metrics[columnIndex].width, columnDraggable, measureHeaderTitleWidth(columnIndex)).drag) return false;
|
|
2807
|
+
if (!getVisibleHeaderActions(column, metrics[columnIndex].width, columnDraggable, measureHeaderTitleWidth(columnIndex), headerActionSlotWidth).drag) return false;
|
|
2796
2808
|
const localX = clientX - canvasRef.current.getBoundingClientRect().left;
|
|
2797
2809
|
const columnRight = getDisplayedColumnLeft(columnIndex) + metrics[columnIndex].width;
|
|
2798
|
-
return localX >= columnRight -
|
|
2799
|
-
}, [columnDraggable, columns, getDisplayedColumnLeft, measureHeaderTitleWidth, metrics]);
|
|
2810
|
+
return localX >= columnRight - headerActionSlotWidth && localX < columnRight - 2;
|
|
2811
|
+
}, [columnDraggable, columns, getDisplayedColumnLeft, headerActionSlotWidth, measureHeaderTitleWidth, metrics]);
|
|
2800
2812
|
const getHeaderCellLeft = useCallback2((cell) => {
|
|
2801
2813
|
const startMetric = metrics[cell.startIndex];
|
|
2802
2814
|
const fixedSide = columns[cell.startIndex]?.fixed;
|
|
@@ -2861,8 +2873,8 @@ function TableInner({
|
|
|
2861
2873
|
if (cell.leaf) return locateHeaderDragHandle(clientX, cell.startIndex);
|
|
2862
2874
|
const localX = clientX - canvasRef.current.getBoundingClientRect().left;
|
|
2863
2875
|
const right = getHeaderCellLeft(cell) + getHeaderCellWidth(cell);
|
|
2864
|
-
return localX >= right -
|
|
2865
|
-
}, [columnDraggable, getHeaderCellLeft, getHeaderCellWidth, locateHeaderDragHandle]);
|
|
2876
|
+
return localX >= right - headerActionSlotWidth && localX < right - 2;
|
|
2877
|
+
}, [columnDraggable, getHeaderCellLeft, getHeaderCellWidth, headerActionSlotWidth, locateHeaderDragHandle]);
|
|
2866
2878
|
const locateHeaderCell = useCallback2((clientX, clientY) => {
|
|
2867
2879
|
const canvas = canvasRef.current;
|
|
2868
2880
|
if (!canvas) return null;
|
|
@@ -3018,26 +3030,32 @@ function TableInner({
|
|
|
3018
3030
|
header.style.height = `${headerHeight}px`;
|
|
3019
3031
|
header.style.justifyContent = column.align === "right" ? "flex-end" : column.align === "center" ? "center" : "flex-start";
|
|
3020
3032
|
header.textContent = column.title;
|
|
3021
|
-
const visibleActions = getVisibleHeaderActions(column, columnWidth, columnDraggable, measureHeaderTitleWidth(sourceIndex));
|
|
3033
|
+
const visibleActions = getVisibleHeaderActions(column, columnWidth, columnDraggable, measureHeaderTitleWidth(sourceIndex), headerActionSlotWidth);
|
|
3022
3034
|
let actionRight = 2;
|
|
3023
3035
|
if (visibleActions.drag) {
|
|
3024
3036
|
const icon = createHeaderDragHandleSvg();
|
|
3025
3037
|
icon.classList.add("rvg-preview-header-icon");
|
|
3038
|
+
icon.style.width = `${headerActionSize}px`;
|
|
3039
|
+
icon.style.height = `${headerActionSize}px`;
|
|
3026
3040
|
icon.style.right = `${actionRight}px`;
|
|
3027
3041
|
header.appendChild(icon);
|
|
3028
|
-
actionRight +=
|
|
3042
|
+
actionRight += headerActionSlotWidth;
|
|
3029
3043
|
}
|
|
3030
3044
|
if (visibleActions.sort) {
|
|
3031
3045
|
const direction = sortState?.columnKey === column.key ? sortState.direction : null;
|
|
3032
3046
|
const icon = createHeaderSortSvg(direction);
|
|
3033
3047
|
icon.classList.add("rvg-preview-header-icon");
|
|
3048
|
+
icon.style.width = `${headerActionSize}px`;
|
|
3049
|
+
icon.style.height = `${headerActionSize}px`;
|
|
3034
3050
|
icon.style.right = `${actionRight}px`;
|
|
3035
3051
|
header.appendChild(icon);
|
|
3036
|
-
actionRight +=
|
|
3052
|
+
actionRight += headerActionSlotWidth;
|
|
3037
3053
|
}
|
|
3038
3054
|
if (visibleActions.filter) {
|
|
3039
3055
|
const icon = createHeaderSearchSvg(Boolean(filterValues[column.key]));
|
|
3040
3056
|
icon.classList.add("rvg-preview-header-icon", "rvg-preview-header-search-icon");
|
|
3057
|
+
icon.style.width = `${headerActionSize}px`;
|
|
3058
|
+
icon.style.height = `${headerActionSize}px`;
|
|
3041
3059
|
icon.style.right = `${actionRight}px`;
|
|
3042
3060
|
header.appendChild(icon);
|
|
3043
3061
|
}
|
|
@@ -3234,7 +3252,7 @@ function TableInner({
|
|
|
3234
3252
|
cleanupDrag();
|
|
3235
3253
|
cleanupDrop();
|
|
3236
3254
|
};
|
|
3237
|
-
}, [applyColumnOrder, applyRowOrder, bodyTop, columnDraggable, columns, filterValues, fixedHeader, getCellLabel, getDisplayedColumnLeft, getHeaderCellWidth, getRowKey, headerCells, headerHeight, hideDragTooltips, locateColumn, locateHeaderCell, locateHeaderCellDragHandle, locateHeaderResizeCell, locateRow, measureHeaderTitleWidth, metrics, rowDraggable, rowHeight, rows, selectedRowKeySet, selection, setDragGuide, setRowDragGuide, sortState, utilityColumnCount]);
|
|
3255
|
+
}, [applyColumnOrder, applyRowOrder, bodyTop, columnDraggable, columns, filterValues, fixedHeader, getCellLabel, getDisplayedColumnLeft, getHeaderCellWidth, getRowKey, headerActionSize, headerActionSlotWidth, headerCells, headerHeight, hideDragTooltips, locateColumn, locateHeaderCell, locateHeaderCellDragHandle, locateHeaderResizeCell, locateRow, measureHeaderTitleWidth, metrics, rowDraggable, rowHeight, rows, selectedRowKeySet, selection, setDragGuide, setRowDragGuide, sortState, utilityColumnCount]);
|
|
3238
3256
|
const locateCell = useCallback2((clientX, clientY) => {
|
|
3239
3257
|
const canvas = canvasRef.current;
|
|
3240
3258
|
if (!canvas) return null;
|
|
@@ -3678,28 +3696,28 @@ function TableInner({
|
|
|
3678
3696
|
const renderHeaderIcons = (columnIndex, left) => {
|
|
3679
3697
|
const column = columns[columnIndex];
|
|
3680
3698
|
if (column.rowSelection || column.rowDragHandle || column.rowNumber) return null;
|
|
3681
|
-
const top = headerLeafTop + (headerLeafHeight -
|
|
3682
|
-
const visibleActions = getVisibleHeaderActions(column, metrics[columnIndex].width, columnDraggable, measureHeaderTitleWidth(columnIndex));
|
|
3683
|
-
let right = left + metrics[columnIndex].width - (visibleActions.drag ?
|
|
3699
|
+
const top = headerLeafTop + (headerLeafHeight - headerActionSize) / 2;
|
|
3700
|
+
const visibleActions = getVisibleHeaderActions(column, metrics[columnIndex].width, columnDraggable, measureHeaderTitleWidth(columnIndex), headerActionSlotWidth);
|
|
3701
|
+
let right = left + metrics[columnIndex].width - (visibleActions.drag ? headerActionSlotWidth : 2);
|
|
3684
3702
|
const icons = [];
|
|
3685
3703
|
if (visibleActions.drag) {
|
|
3686
3704
|
const hovered = hoveredHeaderAction?.columnIndex === columnIndex && hoveredHeaderAction.action === "drag";
|
|
3687
3705
|
icons.push(
|
|
3688
|
-
/* @__PURE__ */ jsx7(HeaderDragIcon, { className: `rvg-header-icon rvg-header-drag-icon${hovered ? " is-hovered" : ""}`, style: { left: left + metrics[columnIndex].width -
|
|
3706
|
+
/* @__PURE__ */ jsx7(HeaderDragIcon, { className: `rvg-header-icon rvg-header-drag-icon${hovered ? " is-hovered" : ""}`, style: { left: left + metrics[columnIndex].width - headerActionSlotWidth, top } }, "drag")
|
|
3689
3707
|
);
|
|
3690
3708
|
}
|
|
3691
3709
|
if (visibleActions.sort) {
|
|
3692
3710
|
const hovered = hoveredHeaderAction?.columnIndex === columnIndex && hoveredHeaderAction.action === "sort";
|
|
3693
3711
|
const direction = sortState?.columnKey === column.key ? sortState.direction : null;
|
|
3694
3712
|
icons.push(
|
|
3695
|
-
/* @__PURE__ */ jsx7(HeaderSortIcon, { className: `rvg-header-icon${hovered ? " is-hovered" : ""}`, style: { left: right -
|
|
3713
|
+
/* @__PURE__ */ jsx7(HeaderSortIcon, { className: `rvg-header-icon${hovered ? " is-hovered" : ""}`, style: { left: right - headerActionSlotWidth, top }, direction }, "sort")
|
|
3696
3714
|
);
|
|
3697
|
-
right -=
|
|
3715
|
+
right -= headerActionSlotWidth;
|
|
3698
3716
|
}
|
|
3699
3717
|
if (visibleActions.filter) {
|
|
3700
3718
|
const hovered = hoveredHeaderAction?.columnIndex === columnIndex && hoveredHeaderAction.action === "filter";
|
|
3701
3719
|
icons.push(
|
|
3702
|
-
/* @__PURE__ */ jsx7(HeaderSearchIcon, { className: `rvg-header-icon rvg-header-search-icon${hovered ? " is-hovered" : ""}${filterValues[column.key] ? " is-active" : ""}`, style: { left: right -
|
|
3720
|
+
/* @__PURE__ */ jsx7(HeaderSearchIcon, { className: `rvg-header-icon rvg-header-search-icon${hovered ? " is-hovered" : ""}${filterValues[column.key] ? " is-active" : ""}`, style: { left: right - headerActionSlotWidth, top: top + 1 } }, "filter")
|
|
3703
3721
|
);
|
|
3704
3722
|
}
|
|
3705
3723
|
return icons;
|
|
@@ -3720,8 +3738,8 @@ function TableInner({
|
|
|
3720
3738
|
const context = canvas?.getContext("2d");
|
|
3721
3739
|
if (context) context.font = "600 13px Inter, ui-sans-serif, system-ui, sans-serif";
|
|
3722
3740
|
const titleWidth = context?.measureText(column.title).width ?? column.title.length * 13;
|
|
3723
|
-
const visibleActions = cell?.leaf || !cell ? getVisibleHeaderActions(column, cellWidth, columnDraggable, titleWidth) : null;
|
|
3724
|
-
const actionWidth = visibleActions ? (Number(visibleActions.drag) + Number(visibleActions.filter) + Number(visibleActions.sort)) *
|
|
3741
|
+
const visibleActions = cell?.leaf || !cell ? getVisibleHeaderActions(column, cellWidth, columnDraggable, titleWidth, headerActionSlotWidth) : null;
|
|
3742
|
+
const actionWidth = visibleActions ? (Number(visibleActions.drag) + Number(visibleActions.filter) + Number(visibleActions.sort)) * headerActionSlotWidth : columnDraggable ? headerActionSlotWidth : 0;
|
|
3725
3743
|
const contentWidth2 = Math.max(0, cellWidth - actionWidth);
|
|
3726
3744
|
const maxTextWidth = Math.max(0, contentWidth2 - 20);
|
|
3727
3745
|
const textWidth = Math.min(titleWidth, maxTextWidth);
|
|
@@ -3742,12 +3760,17 @@ function TableInner({
|
|
|
3742
3760
|
} else if (action === "sort") {
|
|
3743
3761
|
const direction = sortState?.columnKey === column.key ? sortState.direction : null;
|
|
3744
3762
|
label = direction === "asc" ? labels.sortAsc : direction === "desc" ? labels.sortDesc : labels.sortBoth;
|
|
3745
|
-
|
|
3763
|
+
const visibleActions = getVisibleHeaderActions(column, cellWidth, columnDraggable, measureHeaderTitleWidth(columnIndex), headerActionSlotWidth);
|
|
3764
|
+
const right = cellLeft + cellWidth - (visibleActions.drag ? headerActionSlotWidth : 2);
|
|
3765
|
+
anchorX = right - headerActionSlotWidth / 2;
|
|
3746
3766
|
anchorLeft = anchorX;
|
|
3747
3767
|
} else if (action === "filter") {
|
|
3748
3768
|
const value = filterValues[column.key];
|
|
3749
3769
|
label = value ? labels.filterWithValue(value) : labels.filter;
|
|
3750
|
-
|
|
3770
|
+
const visibleActions = getVisibleHeaderActions(column, cellWidth, columnDraggable, measureHeaderTitleWidth(columnIndex), headerActionSlotWidth);
|
|
3771
|
+
let right = cellLeft + cellWidth - (visibleActions.drag ? headerActionSlotWidth : 2);
|
|
3772
|
+
if (visibleActions.sort) right -= headerActionSlotWidth;
|
|
3773
|
+
anchorX = right - headerActionSlotWidth / 2;
|
|
3751
3774
|
anchorLeft = anchorX;
|
|
3752
3775
|
}
|
|
3753
3776
|
const placement = anchorX + 328 > viewport.width ? "left" : "right";
|
|
@@ -3760,7 +3783,7 @@ function TableInner({
|
|
|
3760
3783
|
label,
|
|
3761
3784
|
placement
|
|
3762
3785
|
};
|
|
3763
|
-
}, [baseHeaderHeight, columnDraggable, columns, filterValues, fixedHeader, getDisplayedColumnLeft, getHeaderCellLeft, getHeaderCellWidth, headerDepth, headerRowHeights, headerRowOffsets, labels, metrics, scrollPosition.top, sortState, viewport.width]);
|
|
3786
|
+
}, [baseHeaderHeight, columnDraggable, columns, filterValues, fixedHeader, getDisplayedColumnLeft, getHeaderCellLeft, getHeaderCellWidth, headerActionSlotWidth, headerDepth, headerRowHeights, headerRowOffsets, labels, measureHeaderTitleWidth, metrics, scrollPosition.top, sortState, viewport.width]);
|
|
3764
3787
|
const isPointerOnHeaderTitle = useCallback2((clientX, clientY, cell) => {
|
|
3765
3788
|
const canvas = canvasRef.current;
|
|
3766
3789
|
if (!canvas) return false;
|
|
@@ -3774,14 +3797,14 @@ function TableInner({
|
|
|
3774
3797
|
const context = canvas.getContext("2d");
|
|
3775
3798
|
if (context) context.font = "600 13px Inter, ui-sans-serif, system-ui, sans-serif";
|
|
3776
3799
|
const titleWidth = context?.measureText(column.title).width ?? column.title.length * 13;
|
|
3777
|
-
const visibleActions = cell.leaf ? getVisibleHeaderActions(column, cellWidth, columnDraggable, titleWidth) : null;
|
|
3778
|
-
const actionWidth = visibleActions ? (Number(visibleActions.drag) + Number(visibleActions.filter) + Number(visibleActions.sort)) *
|
|
3800
|
+
const visibleActions = cell.leaf ? getVisibleHeaderActions(column, cellWidth, columnDraggable, titleWidth, headerActionSlotWidth) : null;
|
|
3801
|
+
const actionWidth = visibleActions ? (Number(visibleActions.drag) + Number(visibleActions.filter) + Number(visibleActions.sort)) * headerActionSlotWidth : columnDraggable ? headerActionSlotWidth : 0;
|
|
3779
3802
|
const contentWidth2 = Math.max(0, cellWidth - actionWidth);
|
|
3780
3803
|
const textWidth = Math.min(titleWidth, Math.max(0, contentWidth2 - 20));
|
|
3781
3804
|
const textLeft = column.align === "right" ? cellLeft + contentWidth2 - 10 - textWidth : column.align === "center" ? cellLeft + contentWidth2 / 2 - textWidth / 2 : cellLeft + 10;
|
|
3782
3805
|
const textTop = rowTop + 8;
|
|
3783
3806
|
return localX >= textLeft - 4 && localX <= textLeft + textWidth + 4 && localY >= textTop - 2 && localY <= textTop + 18;
|
|
3784
|
-
}, [columnDraggable, fixedHeader, getHeaderCellLeft, getHeaderCellWidth, headerRowOffsets]);
|
|
3807
|
+
}, [columnDraggable, fixedHeader, getHeaderCellLeft, getHeaderCellWidth, headerActionSlotWidth, headerRowOffsets]);
|
|
3785
3808
|
const headerTooltip = (() => {
|
|
3786
3809
|
if (!visibleHeaderTooltip) return null;
|
|
3787
3810
|
return visibleHeaderTooltip;
|
|
@@ -4104,8 +4127,8 @@ function TableInner({
|
|
|
4104
4127
|
);
|
|
4105
4128
|
}
|
|
4106
4129
|
if (column.renderHeader) {
|
|
4107
|
-
const visibleActions = getVisibleHeaderActions(column, metrics[columnIndex].width, columnDraggable, measureHeaderTitleWidth(columnIndex));
|
|
4108
|
-
const actionWidth = (Number(visibleActions.drag) + Number(visibleActions.filter) + Number(visibleActions.sort)) *
|
|
4130
|
+
const visibleActions = getVisibleHeaderActions(column, metrics[columnIndex].width, columnDraggable, measureHeaderTitleWidth(columnIndex), headerActionSlotWidth);
|
|
4131
|
+
const actionWidth = (Number(visibleActions.drag) + Number(visibleActions.filter) + Number(visibleActions.sort)) * headerActionSlotWidth;
|
|
4109
4132
|
return /* @__PURE__ */ jsx7(
|
|
4110
4133
|
"div",
|
|
4111
4134
|
{
|
|
@@ -4149,13 +4172,13 @@ function TableInner({
|
|
|
4149
4172
|
const headerTop = (fixedHeader ? 0 : -currentScrollTop) + (headerRowOffsets[cell.level] ?? 0);
|
|
4150
4173
|
const left = fixedSide === "left" ? leftFixedOffsets.get(cell.startIndex) ?? 0 : fixedSide === "right" ? viewport.width - (rightFixedOffsets.get(cell.startIndex) ?? 0) - startMetric.width : getScrollableColumnLeft(cell.startIndex);
|
|
4151
4174
|
const width2 = cell.leaf ? startMetric.width : getCellDisplayWidth(cell.startIndex, cell.endIndex - cell.startIndex + 1);
|
|
4152
|
-
const visibleActions = cell.leaf ? getVisibleHeaderActions(column, startMetric.width, columnDraggable, measureHeaderTitleWidth(cell.startIndex)) : null;
|
|
4153
|
-
const actionWidth = visibleActions ? (Number(visibleActions.drag) + Number(visibleActions.filter) + Number(visibleActions.sort)) *
|
|
4175
|
+
const visibleActions = cell.leaf ? getVisibleHeaderActions(column, startMetric.width, columnDraggable, measureHeaderTitleWidth(cell.startIndex), headerActionSlotWidth) : null;
|
|
4176
|
+
const actionWidth = visibleActions ? (Number(visibleActions.drag) + Number(visibleActions.filter) + Number(visibleActions.sort)) * headerActionSlotWidth : columnDraggable && !cell.leaf ? headerActionSlotWidth : 0;
|
|
4154
4177
|
const isDropTarget = Boolean(columnDropTarget && cell.endIndex >= columnDropTarget.startIndex && cell.startIndex <= columnDropTarget.endIndex);
|
|
4155
4178
|
return /* @__PURE__ */ jsxs7(
|
|
4156
4179
|
"div",
|
|
4157
4180
|
{
|
|
4158
|
-
className: `rvg-header-title rvg-header-group${column.renderHeader ? " is-custom" : ""}${cell.leaf ? " is-leaf" : ""}${isDropTarget ? " is-drop-target" : ""}`,
|
|
4181
|
+
className: `rvg-header-title rvg-header-group${column.renderHeader ? " is-custom" : ""}${cell.leaf ? " is-leaf" : ""}${cell.endIndex === columns.length - 1 ? " is-frame-right" : ""}${isDropTarget ? " is-drop-target" : ""}`,
|
|
4159
4182
|
"data-level": cell.level,
|
|
4160
4183
|
"data-measure-key": `group:${cell.key}:${cell.level}`,
|
|
4161
4184
|
style: {
|
|
@@ -4186,7 +4209,7 @@ function TableInner({
|
|
|
4186
4209
|
HeaderDragIcon,
|
|
4187
4210
|
{
|
|
4188
4211
|
className: `rvg-header-icon rvg-header-drag-icon${hoveredHeaderAction?.columnIndex === cell.startIndex && hoveredHeaderAction.action === "drag" ? " is-hovered" : ""}`,
|
|
4189
|
-
style: { left: width2 -
|
|
4212
|
+
style: { left: width2 - headerActionSlotWidth, top: (rowHeightForLevel - headerActionSize) / 2 }
|
|
4190
4213
|
}
|
|
4191
4214
|
)
|
|
4192
4215
|
]
|
|
@@ -4452,12 +4475,13 @@ function TableInner({
|
|
|
4452
4475
|
width,
|
|
4453
4476
|
height: autoHeight ? effectiveHeight : height,
|
|
4454
4477
|
minHeight: autoHeight || typeof height === "number" ? void 0 : FALLBACK_HEIGHT,
|
|
4478
|
+
"--rvg-header-action-size": `${headerActionSize}px`,
|
|
4455
4479
|
...stripedColor ? { "--rvg-color-stripe": stripedColor } : null,
|
|
4456
4480
|
...style
|
|
4457
4481
|
};
|
|
4458
4482
|
const currentScroll = scrollRef.current;
|
|
4459
4483
|
const scrollerBottom = Math.max(0, bottomSummaryHeight - horizontalScrollbarHeight);
|
|
4460
|
-
return /* @__PURE__ */ jsxs7("div", { className: `rvg-root${!hasVerticalBorders ? " is-vertical-borderless" : ""}${horizontalBorderless ? " is-horizontal-borderless" : ""}${hasStripedRows ? " is-striped" : ""}${insertBusy ? " is-inserting" : ""}${deleteBusy ? " is-deleting" : ""} ${loading && !hasCompletedLoadRef.current && !hasCustomLoading ? "is-initial-loading" : ""} ${className}`, style: rootStyle, children: [
|
|
4484
|
+
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: [
|
|
4461
4485
|
/* @__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: [
|
|
4462
4486
|
/* @__PURE__ */ jsx7(
|
|
4463
4487
|
"canvas",
|
|
@@ -4517,7 +4541,10 @@ function TableInner({
|
|
|
4517
4541
|
} else {
|
|
4518
4542
|
const label = getCellLabel(cell.rowIndex, cell.columnIndex);
|
|
4519
4543
|
const context = event.currentTarget.getContext("2d");
|
|
4520
|
-
if (context)
|
|
4544
|
+
if (context) {
|
|
4545
|
+
const bodyFontSize = readThemePixel(getComputedStyle(event.currentTarget), "--rvg-font-size-body", 13);
|
|
4546
|
+
context.font = `${bodyFontSize}px Inter, ui-sans-serif, system-ui, sans-serif`;
|
|
4547
|
+
}
|
|
4521
4548
|
const truncated = Boolean(label && context && context.measureText(label).width + 20 > metrics[cell.columnIndex].width);
|
|
4522
4549
|
if (!label || !tooltipConfig.cell && !truncated) {
|
|
4523
4550
|
showCellTooltipAfterDelay(null);
|