@lensui/lens-table 0.1.0 → 0.1.1
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 +55 -26
- package/dist/index.d.cts +13 -2
- package/dist/index.d.ts +13 -2
- package/dist/index.js +55 -26
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -89,6 +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
|
+
| `autoHeight` | `boolean` | `false` | 是否按真实内容高度收缩表格。开启后数据较少时使用 `表头 + 行数 * 行高 + 合计行` 的高度,数据较多时不超过 `height`。 |
|
|
92
93
|
| `rowHeight` | `number` | `40` | 每行高度,固定行高用于高性能虚拟滚动。 |
|
|
93
94
|
| `headerHeight` | `number` | `44` | 表头高度,单位 px。 |
|
|
94
95
|
| `fixedHeader` | `boolean` | `true` | 表头是否固定在顶部。 |
|
package/dist/index.cjs
CHANGED
|
@@ -333,6 +333,7 @@ function LoadingSpinnerIcon() {
|
|
|
333
333
|
// src/components/editors/ChoiceEditor.tsx
|
|
334
334
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
335
335
|
function ChoiceEditor({ value, options, style, labels, onChange, onCommit, onCancel }) {
|
|
336
|
+
const editorStyle = typeof style.width === "number" ? { ...style, width: Math.max(0, style.width - 1) } : style;
|
|
336
337
|
const collection = (0, import_select.createListCollection)({
|
|
337
338
|
items: options,
|
|
338
339
|
itemToValue: (item) => item.value,
|
|
@@ -342,7 +343,7 @@ function ChoiceEditor({ value, options, style, labels, onChange, onCommit, onCan
|
|
|
342
343
|
import_select.Select.Root,
|
|
343
344
|
{
|
|
344
345
|
className: "rvg-choice-editor",
|
|
345
|
-
style,
|
|
346
|
+
style: editorStyle,
|
|
346
347
|
collection,
|
|
347
348
|
value: value ? [value] : [],
|
|
348
349
|
defaultOpen: true,
|
|
@@ -801,14 +802,38 @@ function getMinimumColumnWidth(column, columnDraggable = false) {
|
|
|
801
802
|
if (column.rowSelection || column.rowNumber) return 44;
|
|
802
803
|
return 60;
|
|
803
804
|
}
|
|
804
|
-
function buildColumnMetrics(columns,
|
|
805
|
+
function buildColumnMetrics(columns, columnDraggableOrOptions = false) {
|
|
806
|
+
const options = typeof columnDraggableOrOptions === "boolean" ? { columnDraggable: columnDraggableOrOptions } : columnDraggableOrOptions;
|
|
807
|
+
const columnDraggable = options.columnDraggable ?? false;
|
|
805
808
|
let left = 0;
|
|
806
|
-
|
|
809
|
+
const metrics = columns.map((column) => {
|
|
807
810
|
const width = Math.max(getMinimumColumnWidth(column, columnDraggable), column.width ?? DEFAULT_COLUMN_WIDTH);
|
|
808
811
|
const metric = { left, width, right: left + width };
|
|
809
812
|
left += width;
|
|
810
813
|
return metric;
|
|
811
814
|
});
|
|
815
|
+
const viewportWidth = options.viewportWidth ?? 0;
|
|
816
|
+
if (viewportWidth <= left || columns.length === 0) return metrics;
|
|
817
|
+
const stretchable = columns.map((column, index) => ({ column, index })).filter(({ column }) => column.fixed !== "right" && !column.rowSelection && !column.rowDragHandle && !column.rowNumber);
|
|
818
|
+
const targets = stretchable.length > 0 ? stretchable : columns.map((column, index) => ({ column, index })).filter(({ column }) => column.fixed !== "right");
|
|
819
|
+
if (targets.length === 0) return metrics;
|
|
820
|
+
const extra = viewportWidth - left;
|
|
821
|
+
const baseTotal = targets.reduce((sum, { index }) => sum + metrics[index].width, 0);
|
|
822
|
+
let assigned = 0;
|
|
823
|
+
const targetIndexSet = new Set(targets.map(({ index }) => index));
|
|
824
|
+
const nextWidths = metrics.map((metric, index) => {
|
|
825
|
+
if (!targetIndexSet.has(index)) return metric.width;
|
|
826
|
+
const isLastTarget = index === targets[targets.length - 1].index;
|
|
827
|
+
const addition = isLastTarget ? extra - assigned : Math.floor(extra * (metric.width / baseTotal));
|
|
828
|
+
assigned += addition;
|
|
829
|
+
return metric.width + addition;
|
|
830
|
+
});
|
|
831
|
+
left = 0;
|
|
832
|
+
return nextWidths.map((width) => {
|
|
833
|
+
const metric = { left, width, right: left + width };
|
|
834
|
+
left += width;
|
|
835
|
+
return metric;
|
|
836
|
+
});
|
|
812
837
|
}
|
|
813
838
|
function lowerBound(metrics, value) {
|
|
814
839
|
let low = 0;
|
|
@@ -1229,6 +1254,7 @@ function useControllableValue(value, defaultValue, onChange) {
|
|
|
1229
1254
|
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
1230
1255
|
var ANNOTATION_COLORS = ["#f44336", "#ff7a45", "#f5a623", "#f2c94c", "#52c41a", "#13a8a8", "#1677ff", "#597ef7", "#9254de", "#eb2f96"];
|
|
1231
1256
|
var FALLBACK_HEIGHT = 480;
|
|
1257
|
+
var EMPTY_BODY_HEIGHT = 240;
|
|
1232
1258
|
var VIRTUAL_OVERSCAN = 4;
|
|
1233
1259
|
var TOOLTIP_DELAY = 1e3;
|
|
1234
1260
|
var SUMMARY_CHUNK_SIZE = 5e3;
|
|
@@ -1302,6 +1328,7 @@ function Table({
|
|
|
1302
1328
|
rowKey,
|
|
1303
1329
|
width = "100%",
|
|
1304
1330
|
height = "100%",
|
|
1331
|
+
autoHeight = false,
|
|
1305
1332
|
rowHeight = 36,
|
|
1306
1333
|
headerHeight = 40,
|
|
1307
1334
|
fixedHeader = true,
|
|
@@ -1544,7 +1571,7 @@ function Table({
|
|
|
1544
1571
|
if (selection?.rowKey === editing.rowKey && selection.columnKey === editing.columnKey) return;
|
|
1545
1572
|
setEditing(null);
|
|
1546
1573
|
}, [editing, selection]);
|
|
1547
|
-
const metrics = (0, import_react5.useMemo)(() => buildColumnMetrics(columns, columnDraggable), [columnDraggable, columns]);
|
|
1574
|
+
const metrics = (0, import_react5.useMemo)(() => buildColumnMetrics(columns, { columnDraggable, viewportWidth: viewport.width }), [columnDraggable, columns, viewport.width]);
|
|
1548
1575
|
const contentWidth = metrics.length > 0 ? metrics[metrics.length - 1].right : 0;
|
|
1549
1576
|
const contentHeight = rows.length * rowHeight;
|
|
1550
1577
|
const fixedWidth = (0, import_react5.useMemo)(() => columns.reduce((width2, column, index) => column.fixed === "left" ? Math.max(width2, metrics[index].right) : width2, 0), [columns, metrics]);
|
|
@@ -1565,7 +1592,10 @@ function Table({
|
|
|
1565
1592
|
const topSummaryHeight = hasSummaryRow && summaryPosition === "top" ? rowHeight : 0;
|
|
1566
1593
|
const bottomSummaryHeight = hasSummaryRow && summaryPosition === "bottom" ? rowHeight : 0;
|
|
1567
1594
|
const bodyTop = headerHeight + topSummaryHeight;
|
|
1568
|
-
const
|
|
1595
|
+
const bodyContentHeight = rows.length === 0 ? EMPTY_BODY_HEIGHT : contentHeight;
|
|
1596
|
+
const realContentHeight = bodyTop + bodyContentHeight + bottomSummaryHeight + (contentWidth > viewport.width ? horizontalScrollbarHeight : 0);
|
|
1597
|
+
const effectiveHeight = autoHeight ? Math.max(bodyTop + bottomSummaryHeight, Math.min(resolvedHeight, realContentHeight)) : resolvedHeight;
|
|
1598
|
+
const bodyViewportHeight = Math.max(0, effectiveHeight - (fixedHeader ? headerHeight : 0) - topSummaryHeight);
|
|
1569
1599
|
const [summaryState, setSummaryState] = (0, import_react5.useState)(() => ({ columns: null, rows: null, values: /* @__PURE__ */ new Map(), pending: false }));
|
|
1570
1600
|
const summaryPending = hasSummaryRow && (loading || summaryState.pending || summaryState.columns !== columns || summaryState.rows !== rows);
|
|
1571
1601
|
const summaryValues = hasSummaryRow && summaryState.columns === columns && summaryState.rows === rows ? summaryState.values : /* @__PURE__ */ new Map();
|
|
@@ -1701,9 +1731,8 @@ function Table({
|
|
|
1701
1731
|
const canvas = canvasRef.current;
|
|
1702
1732
|
if (!canvas || viewport.width <= 0) return;
|
|
1703
1733
|
const ratio = Math.min(window.devicePixelRatio || 1, 2);
|
|
1704
|
-
const displayHeight = resolvedHeight;
|
|
1705
1734
|
const physicalWidth = Math.round(viewport.width * ratio);
|
|
1706
|
-
const physicalHeight = Math.round(
|
|
1735
|
+
const physicalHeight = Math.round(effectiveHeight * ratio);
|
|
1707
1736
|
if (canvas.width !== physicalWidth) canvas.width = physicalWidth;
|
|
1708
1737
|
if (canvas.height !== physicalHeight) canvas.height = physicalHeight;
|
|
1709
1738
|
const context = canvas.getContext("2d");
|
|
@@ -1726,8 +1755,8 @@ function Table({
|
|
|
1726
1755
|
const scroll = scrollRef.current;
|
|
1727
1756
|
const rowScrollTop = fixedHeader ? scroll.top : Math.max(0, scroll.top - bodyTop);
|
|
1728
1757
|
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 };
|
|
1729
|
-
paintGrid({ context, width: viewport.width, height:
|
|
1730
|
-
}, [bodyTop, bodyViewportHeight, bottomSummaryHeight, cellAnnotations, cellSpanLookup, columnDraggable, columns, editedCellHighlightColor, editedCellKeys, editing, filterValues, fixedHeader, getRowKey, hasStripedRows, hasVerticalBorders, headerHeight, highlightsEditedCells, highlightsInsertedRows, insertedRowHighlightColor, insertedRowKeySet, isVirtualized, metrics,
|
|
1758
|
+
paintGrid({ context, width: viewport.width, height: effectiveHeight, pixelRatio: ratio, scrollLeft: scroll.left, scrollTop: scroll.top, rowHeight, headerHeight, bodyTop, suppressLastRowBottomBorder: bottomSummaryHeight > 0, suppressFrameBottomBorder: bottomSummaryHeight > 0, fixedHeader, verticalBorderless: !hasVerticalBorders, striped: hasStripedRows, columnDraggable, sortState, filterValues, hoveredHeaderAction: hoveredHeaderActionRef.current, rows, columns, metrics, range, selection, editing, hoveredRowIndex: hoveredRowIndexRef.current, selectionRange, selectedRowKeys: selectedRowKeySet, selectedColumnKeys: selectedColumnKeySet, cellSpans: cellSpanLookup.covered, maxRowSpan: cellSpanLookup.maxRowSpan, highlightEditedCells: highlightsEditedCells, highlightInsertedRows: highlightsInsertedRows, insertedRowKeys: insertedRowKeySet, editedCellKeys, cellAnnotations, getRowKey, rowDragPreview, colors: themeColors });
|
|
1759
|
+
}, [bodyTop, bodyViewportHeight, bottomSummaryHeight, cellAnnotations, cellSpanLookup, columnDraggable, columns, editedCellHighlightColor, editedCellKeys, editing, effectiveHeight, filterValues, fixedHeader, getRowKey, hasStripedRows, hasVerticalBorders, headerHeight, highlightsEditedCells, highlightsInsertedRows, insertedRowHighlightColor, insertedRowKeySet, isVirtualized, metrics, rowDragPreview, rowHeight, rows, selectedColumnKeySet, selectedRowKeySet, selection, selectionRange, sortState, stripedColor, viewport.width, virtualOverscan]);
|
|
1731
1760
|
const scheduleDraw = (0, import_react5.useCallback)(() => {
|
|
1732
1761
|
if (frameRef.current === null) frameRef.current = requestAnimationFrame(draw);
|
|
1733
1762
|
}, [draw]);
|
|
@@ -1836,14 +1865,14 @@ function Table({
|
|
|
1836
1865
|
const horizontalStart = column.fixed === void 0 ? fixedWidth : 0;
|
|
1837
1866
|
const horizontalEnd = column.fixed === void 0 ? viewport.width - rightFixedWidth : viewport.width;
|
|
1838
1867
|
const verticalStart = fixedHeader ? bodyTop : 0;
|
|
1839
|
-
if (rawRight <= horizontalStart || rawLeft >= horizontalEnd || rawBottom <= verticalStart || rawTop >=
|
|
1868
|
+
if (rawRight <= horizontalStart || rawLeft >= horizontalEnd || rawBottom <= verticalStart || rawTop >= effectiveHeight) {
|
|
1840
1869
|
focus.style.display = "none";
|
|
1841
1870
|
} else {
|
|
1842
1871
|
const borderWidth = 2;
|
|
1843
1872
|
const left = Math.round(Math.max(rawLeft - borderWidth, horizontalStart - 1));
|
|
1844
1873
|
const right = Math.round(Math.min(rawRight + 1, horizontalEnd, viewport.width));
|
|
1845
1874
|
const top = Math.round(Math.max(rawTop - borderWidth, verticalStart - 1));
|
|
1846
|
-
const bottom = Math.round(Math.min(rawBottom + 1,
|
|
1875
|
+
const bottom = Math.round(Math.min(rawBottom + 1, effectiveHeight));
|
|
1847
1876
|
focus.style.display = "block";
|
|
1848
1877
|
focus.style.left = `${left}px`;
|
|
1849
1878
|
focus.style.top = `${top}px`;
|
|
@@ -1868,7 +1897,7 @@ function Table({
|
|
|
1868
1897
|
setHoveredCellTooltip(null);
|
|
1869
1898
|
scheduleDraw();
|
|
1870
1899
|
setEditing(null);
|
|
1871
|
-
}, [bodyTop, columns, fixedHeader, fixedWidth, getCellDisplayWidth, getCellSpan, getRowKey, metrics,
|
|
1900
|
+
}, [bodyTop, columns, effectiveHeight, fixedHeader, fixedWidth, getCellDisplayWidth, getCellSpan, getRowKey, metrics, rightFixedOffsets, rightFixedWidth, rowHeight, rows, scheduleDraw, selection, selectionRange, viewport.width]);
|
|
1872
1901
|
const locateColumn = (0, import_react5.useCallback)((clientX) => {
|
|
1873
1902
|
const canvas = canvasRef.current;
|
|
1874
1903
|
if (!canvas) return -1;
|
|
@@ -2456,13 +2485,13 @@ function Table({
|
|
|
2456
2485
|
const rowTop = (fixedHeader ? 0 : bodyTop) + rowIndex * rowHeight;
|
|
2457
2486
|
const rowBottom = rowTop + rowHeight * (span?.rowSpan ?? 1);
|
|
2458
2487
|
const cellWidth = getCellDisplayWidth(columnIndex, span?.colSpan ?? 1);
|
|
2459
|
-
const visibleRowHeight = fixedHeader ?
|
|
2488
|
+
const visibleRowHeight = fixedHeader ? effectiveHeight - bodyTop : effectiveHeight;
|
|
2460
2489
|
if (rowTop < scroller.scrollTop) scroller.scrollTop = rowTop;
|
|
2461
2490
|
if (rowBottom > scroller.scrollTop + visibleRowHeight) scroller.scrollTop = rowBottom - visibleRowHeight;
|
|
2462
2491
|
if (columns[columnIndex].fixed === void 0 && metric.left < scroller.scrollLeft + fixedWidth) scroller.scrollLeft = Math.max(0, metric.left - fixedWidth);
|
|
2463
2492
|
if (columns[columnIndex].fixed === void 0 && metric.left + cellWidth > scroller.scrollLeft + viewport.width - rightFixedWidth) scroller.scrollLeft = metric.left + cellWidth - viewport.width + rightFixedWidth;
|
|
2464
2493
|
}
|
|
2465
|
-
}, [beginEdit, bodyTop, columns, editing, fixedHeader, fixedWidth, getCellDisplayWidth, getCellSpan, getRowKey, metrics,
|
|
2494
|
+
}, [beginEdit, bodyTop, columns, editing, effectiveHeight, fixedHeader, fixedWidth, getCellDisplayWidth, getCellSpan, getRowKey, metrics, rightFixedWidth, rowHeight, rows, selection, setSelection, viewport.width]);
|
|
2466
2495
|
const editorStyle = (0, import_react5.useMemo)(() => {
|
|
2467
2496
|
if (!editing) return void 0;
|
|
2468
2497
|
const metric = metrics[editing.columnIndex];
|
|
@@ -2686,7 +2715,7 @@ function Table({
|
|
|
2686
2715
|
type: "cell",
|
|
2687
2716
|
...cell,
|
|
2688
2717
|
left: Math.min(Math.max(0, clientX - root.left), Math.max(0, viewport.width - 190)),
|
|
2689
|
-
top: Math.min(Math.max(0, clientY - root.top), Math.max(0,
|
|
2718
|
+
top: Math.min(Math.max(0, clientY - root.top), Math.max(0, effectiveHeight - 350))
|
|
2690
2719
|
});
|
|
2691
2720
|
onCellContextMenu?.({ ...cell, row: rows[cell.rowIndex], clientX, clientY });
|
|
2692
2721
|
};
|
|
@@ -2697,7 +2726,7 @@ function Table({
|
|
|
2697
2726
|
type: "header",
|
|
2698
2727
|
columnIndex,
|
|
2699
2728
|
left: Math.min(Math.max(0, clientX - root.left), Math.max(0, viewport.width - 180)),
|
|
2700
|
-
top: Math.min(Math.max(0, clientY - root.top), Math.max(0,
|
|
2729
|
+
top: Math.min(Math.max(0, clientY - root.top), Math.max(0, effectiveHeight - 68))
|
|
2701
2730
|
});
|
|
2702
2731
|
};
|
|
2703
2732
|
const getRowDragOffset = (rowIndex) => {
|
|
@@ -2927,7 +2956,7 @@ function Table({
|
|
|
2927
2956
|
const horizontalStart = column.fixed === void 0 ? fixedWidth : 0;
|
|
2928
2957
|
const horizontalEnd = column.fixed === void 0 ? viewport.width - rightFixedWidth : viewport.width;
|
|
2929
2958
|
const verticalStart = fixedHeader ? bodyTop : 0;
|
|
2930
|
-
if (rawLeft <= horizontalStart || rawLeft > horizontalEnd || rawTop <= verticalStart || rawTop >
|
|
2959
|
+
if (rawLeft <= horizontalStart || rawLeft > horizontalEnd || rawTop <= verticalStart || rawTop > effectiveHeight) return null;
|
|
2931
2960
|
return { left: rawLeft, top: rawTop, bounds };
|
|
2932
2961
|
})();
|
|
2933
2962
|
const selectionOutlineStyle = (() => {
|
|
@@ -2944,12 +2973,12 @@ function Table({
|
|
|
2944
2973
|
const horizontalStart = column.fixed === void 0 ? fixedWidth : 0;
|
|
2945
2974
|
const horizontalEnd = column.fixed === void 0 ? viewport.width - rightFixedWidth : viewport.width;
|
|
2946
2975
|
const verticalStart = fixedHeader ? bodyTop : 0;
|
|
2947
|
-
if (rawRight <= horizontalStart || rawLeft >= horizontalEnd || rawBottom <= verticalStart || rawTop >=
|
|
2976
|
+
if (rawRight <= horizontalStart || rawLeft >= horizontalEnd || rawBottom <= verticalStart || rawTop >= effectiveHeight) return null;
|
|
2948
2977
|
const borderWidth = 2;
|
|
2949
2978
|
const left = Math.round(Math.max(rawLeft - borderWidth, horizontalStart - 1));
|
|
2950
2979
|
const right = Math.round(Math.min(rawRight + 1, horizontalEnd, viewport.width));
|
|
2951
2980
|
const top = Math.round(Math.max(rawTop - borderWidth, verticalStart - 1));
|
|
2952
|
-
const bottom = Math.round(Math.min(rawBottom + 1,
|
|
2981
|
+
const bottom = Math.round(Math.min(rawBottom + 1, effectiveHeight));
|
|
2953
2982
|
return {
|
|
2954
2983
|
left,
|
|
2955
2984
|
top,
|
|
@@ -3082,8 +3111,8 @@ function Table({
|
|
|
3082
3111
|
};
|
|
3083
3112
|
const rootStyle = {
|
|
3084
3113
|
width,
|
|
3085
|
-
height,
|
|
3086
|
-
minHeight: typeof height === "number" ? void 0 : FALLBACK_HEIGHT,
|
|
3114
|
+
height: autoHeight ? effectiveHeight : height,
|
|
3115
|
+
minHeight: autoHeight || typeof height === "number" ? void 0 : FALLBACK_HEIGHT,
|
|
3087
3116
|
...stripedColor ? { "--rvg-color-stripe": stripedColor } : null,
|
|
3088
3117
|
...style
|
|
3089
3118
|
};
|
|
@@ -3096,7 +3125,7 @@ function Table({
|
|
|
3096
3125
|
{
|
|
3097
3126
|
ref: canvasRef,
|
|
3098
3127
|
className: "rvg-canvas",
|
|
3099
|
-
style: { width: viewport.width, height:
|
|
3128
|
+
style: { width: viewport.width, height: effectiveHeight },
|
|
3100
3129
|
onMouseMove: (event) => {
|
|
3101
3130
|
if (columnDragRef.current) return;
|
|
3102
3131
|
const rect = event.currentTarget.getBoundingClientRect();
|
|
@@ -3274,7 +3303,7 @@ function Table({
|
|
|
3274
3303
|
onContextMenu: handleContextMenu
|
|
3275
3304
|
}
|
|
3276
3305
|
),
|
|
3277
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "rvg-text-layer", style: { width: viewport.width, height:
|
|
3306
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "rvg-text-layer", style: { width: viewport.width, height: effectiveHeight, marginTop: -effectiveHeight }, onContextMenu: handleContextMenu, children: [
|
|
3278
3307
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "rvg-text-scroll-clip", style: { left: fixedWidth, right: rightFixedWidth }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
3279
3308
|
"div",
|
|
3280
3309
|
{
|
|
@@ -3298,7 +3327,7 @@ function Table({
|
|
|
3298
3327
|
columns.map((column, columnIndex) => column.fixed === "left" ? renderHeaderTitle(columnIndex, metrics[columnIndex].left) : null),
|
|
3299
3328
|
columns.map((column, columnIndex) => column.fixed === "right" ? renderHeaderTitle(columnIndex, viewport.width - (rightFixedOffsets.get(columnIndex) ?? 0) - metrics[columnIndex].width) : null)
|
|
3300
3329
|
] }),
|
|
3301
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "rvg-spacer", style: { width: contentWidth, height: contentHeight + bodyTop, marginTop: -
|
|
3330
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "rvg-spacer", style: { width: contentWidth, height: contentHeight + bodyTop, marginTop: -effectiveHeight } })
|
|
3302
3331
|
] }),
|
|
3303
3332
|
hasSummaryRow && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
3304
3333
|
"div",
|
|
@@ -3659,10 +3688,10 @@ function Table({
|
|
|
3659
3688
|
] })
|
|
3660
3689
|
] }),
|
|
3661
3690
|
renderEditor(),
|
|
3662
|
-
rows.length === 0 && !loading && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "rvg-empty", children: emptyContent ?? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(DefaultEmptyState, { label: labels.empty }) }),
|
|
3691
|
+
rows.length === 0 && !loading && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "rvg-empty", style: { top: bodyTop }, children: emptyContent ?? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(DefaultEmptyState, { label: labels.empty }) }),
|
|
3663
3692
|
loading && hasCustomLoading && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "rvg-custom-loading", "aria-label": labels.refreshing, children: loadingContent }),
|
|
3664
3693
|
loading && !hasCustomLoading && !hasCompletedLoadRef.current && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "rvg-initial-loading", style: { top: headerHeight }, "aria-label": labels.initialLoading, children: [
|
|
3665
|
-
Array.from({ length: Math.ceil((
|
|
3694
|
+
Array.from({ length: Math.ceil((effectiveHeight - headerHeight) / rowHeight) }, (_, rowIndex) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "rvg-loading-row", style: { height: rowHeight }, children: columns.map((column, columnIndex) => {
|
|
3666
3695
|
const left = getDisplayedColumnLeft(columnIndex);
|
|
3667
3696
|
const columnWidth = metrics[columnIndex].width;
|
|
3668
3697
|
if (left + columnWidth <= 0 || left >= viewport.width) return null;
|
package/dist/index.d.cts
CHANGED
|
@@ -282,6 +282,8 @@ interface TableProps<Row extends object> {
|
|
|
282
282
|
width?: number | string;
|
|
283
283
|
/** Grid height. Defaults to 100%; falls back to 480px when the parent has no height. */
|
|
284
284
|
height?: number | string;
|
|
285
|
+
/** Shrink the grid to its real content height when there are fewer rows than the configured height can display. */
|
|
286
|
+
autoHeight?: boolean;
|
|
285
287
|
rowHeight?: number;
|
|
286
288
|
headerHeight?: number;
|
|
287
289
|
fixedHeader?: boolean;
|
|
@@ -346,8 +348,13 @@ interface ViewportRange {
|
|
|
346
348
|
columnEnd: number;
|
|
347
349
|
}
|
|
348
350
|
|
|
349
|
-
declare function Table<Row extends object>({ columns: sourceColumns, rows: sourceRows, rowKey, width, height, rowHeight, headerHeight, fixedHeader, locale, verticalBorderless, striped, highlight, cellSpans, loading, loadingContent, virtualized, tooltip, summary, rowNumber, selectedCell, defaultSelectedCell, onSelectedCellChange, rangeSelection, rowSelection, selectedRowKeys, defaultSelectedRowKeys, onSelectedRowKeysChange, columnSelection, selectedColumnKeys, defaultSelectedColumnKeys, onSelectedColumnKeysChange, columnDraggable, columnResizable, onColumnOrderChange, onColumnResize, rowDraggable, onRowOrderChange, onInsertRows, onDeleteRows, sortState, onSortStateChange, filterValues, onFilterValuesChange, onCellChange, onCellContextMenu, contextMenu: contextMenuConfig, emptyContent, className, style, ariaLabel, }: TableProps<Row>): react.JSX.Element;
|
|
351
|
+
declare function Table<Row extends object>({ columns: sourceColumns, rows: sourceRows, rowKey, width, height, autoHeight, rowHeight, headerHeight, fixedHeader, locale, verticalBorderless, striped, highlight, cellSpans, loading, loadingContent, virtualized, tooltip, summary, rowNumber, selectedCell, defaultSelectedCell, onSelectedCellChange, rangeSelection, rowSelection, selectedRowKeys, defaultSelectedRowKeys, onSelectedRowKeysChange, columnSelection, selectedColumnKeys, defaultSelectedColumnKeys, onSelectedColumnKeysChange, columnDraggable, columnResizable, onColumnOrderChange, onColumnResize, rowDraggable, onRowOrderChange, onInsertRows, onDeleteRows, sortState, onSortStateChange, filterValues, onFilterValuesChange, onCellChange, onCellContextMenu, contextMenu: contextMenuConfig, emptyContent, className, style, ariaLabel, }: TableProps<Row>): react.JSX.Element;
|
|
350
352
|
|
|
353
|
+
type LayoutColumn<Row> = GridColumn<Row> & {
|
|
354
|
+
rowSelection?: boolean;
|
|
355
|
+
rowDragHandle?: boolean;
|
|
356
|
+
rowNumber?: boolean;
|
|
357
|
+
};
|
|
351
358
|
/**
|
|
352
359
|
* Cached horizontal geometry for one column.
|
|
353
360
|
*
|
|
@@ -360,11 +367,15 @@ interface ColumnMetric {
|
|
|
360
367
|
width: number;
|
|
361
368
|
right: number;
|
|
362
369
|
}
|
|
370
|
+
interface BuildColumnMetricsOptions {
|
|
371
|
+
columnDraggable?: boolean;
|
|
372
|
+
viewportWidth?: number;
|
|
373
|
+
}
|
|
363
374
|
/**
|
|
364
375
|
* Build cumulative column positions used by both canvas painting and DOM
|
|
365
376
|
* overlay placement.
|
|
366
377
|
*/
|
|
367
|
-
declare function buildColumnMetrics<Row>(columns:
|
|
378
|
+
declare function buildColumnMetrics<Row>(columns: LayoutColumn<Row>[], columnDraggableOrOptions?: boolean | BuildColumnMetricsOptions): ColumnMetric[];
|
|
368
379
|
/**
|
|
369
380
|
* Compute the row and column slice that should be painted for the current
|
|
370
381
|
* viewport.
|
package/dist/index.d.ts
CHANGED
|
@@ -282,6 +282,8 @@ interface TableProps<Row extends object> {
|
|
|
282
282
|
width?: number | string;
|
|
283
283
|
/** Grid height. Defaults to 100%; falls back to 480px when the parent has no height. */
|
|
284
284
|
height?: number | string;
|
|
285
|
+
/** Shrink the grid to its real content height when there are fewer rows than the configured height can display. */
|
|
286
|
+
autoHeight?: boolean;
|
|
285
287
|
rowHeight?: number;
|
|
286
288
|
headerHeight?: number;
|
|
287
289
|
fixedHeader?: boolean;
|
|
@@ -346,8 +348,13 @@ interface ViewportRange {
|
|
|
346
348
|
columnEnd: number;
|
|
347
349
|
}
|
|
348
350
|
|
|
349
|
-
declare function Table<Row extends object>({ columns: sourceColumns, rows: sourceRows, rowKey, width, height, rowHeight, headerHeight, fixedHeader, locale, verticalBorderless, striped, highlight, cellSpans, loading, loadingContent, virtualized, tooltip, summary, rowNumber, selectedCell, defaultSelectedCell, onSelectedCellChange, rangeSelection, rowSelection, selectedRowKeys, defaultSelectedRowKeys, onSelectedRowKeysChange, columnSelection, selectedColumnKeys, defaultSelectedColumnKeys, onSelectedColumnKeysChange, columnDraggable, columnResizable, onColumnOrderChange, onColumnResize, rowDraggable, onRowOrderChange, onInsertRows, onDeleteRows, sortState, onSortStateChange, filterValues, onFilterValuesChange, onCellChange, onCellContextMenu, contextMenu: contextMenuConfig, emptyContent, className, style, ariaLabel, }: TableProps<Row>): react.JSX.Element;
|
|
351
|
+
declare function Table<Row extends object>({ columns: sourceColumns, rows: sourceRows, rowKey, width, height, autoHeight, rowHeight, headerHeight, fixedHeader, locale, verticalBorderless, striped, highlight, cellSpans, loading, loadingContent, virtualized, tooltip, summary, rowNumber, selectedCell, defaultSelectedCell, onSelectedCellChange, rangeSelection, rowSelection, selectedRowKeys, defaultSelectedRowKeys, onSelectedRowKeysChange, columnSelection, selectedColumnKeys, defaultSelectedColumnKeys, onSelectedColumnKeysChange, columnDraggable, columnResizable, onColumnOrderChange, onColumnResize, rowDraggable, onRowOrderChange, onInsertRows, onDeleteRows, sortState, onSortStateChange, filterValues, onFilterValuesChange, onCellChange, onCellContextMenu, contextMenu: contextMenuConfig, emptyContent, className, style, ariaLabel, }: TableProps<Row>): react.JSX.Element;
|
|
350
352
|
|
|
353
|
+
type LayoutColumn<Row> = GridColumn<Row> & {
|
|
354
|
+
rowSelection?: boolean;
|
|
355
|
+
rowDragHandle?: boolean;
|
|
356
|
+
rowNumber?: boolean;
|
|
357
|
+
};
|
|
351
358
|
/**
|
|
352
359
|
* Cached horizontal geometry for one column.
|
|
353
360
|
*
|
|
@@ -360,11 +367,15 @@ interface ColumnMetric {
|
|
|
360
367
|
width: number;
|
|
361
368
|
right: number;
|
|
362
369
|
}
|
|
370
|
+
interface BuildColumnMetricsOptions {
|
|
371
|
+
columnDraggable?: boolean;
|
|
372
|
+
viewportWidth?: number;
|
|
373
|
+
}
|
|
363
374
|
/**
|
|
364
375
|
* Build cumulative column positions used by both canvas painting and DOM
|
|
365
376
|
* overlay placement.
|
|
366
377
|
*/
|
|
367
|
-
declare function buildColumnMetrics<Row>(columns:
|
|
378
|
+
declare function buildColumnMetrics<Row>(columns: LayoutColumn<Row>[], columnDraggableOrOptions?: boolean | BuildColumnMetricsOptions): ColumnMetric[];
|
|
368
379
|
/**
|
|
369
380
|
* Compute the row and column slice that should be painted for the current
|
|
370
381
|
* viewport.
|
package/dist/index.js
CHANGED
|
@@ -303,6 +303,7 @@ function LoadingSpinnerIcon() {
|
|
|
303
303
|
// src/components/editors/ChoiceEditor.tsx
|
|
304
304
|
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
305
305
|
function ChoiceEditor({ value, options, style, labels, onChange, onCommit, onCancel }) {
|
|
306
|
+
const editorStyle = typeof style.width === "number" ? { ...style, width: Math.max(0, style.width - 1) } : style;
|
|
306
307
|
const collection = createListCollection({
|
|
307
308
|
items: options,
|
|
308
309
|
itemToValue: (item) => item.value,
|
|
@@ -312,7 +313,7 @@ function ChoiceEditor({ value, options, style, labels, onChange, onCommit, onCan
|
|
|
312
313
|
Select.Root,
|
|
313
314
|
{
|
|
314
315
|
className: "rvg-choice-editor",
|
|
315
|
-
style,
|
|
316
|
+
style: editorStyle,
|
|
316
317
|
collection,
|
|
317
318
|
value: value ? [value] : [],
|
|
318
319
|
defaultOpen: true,
|
|
@@ -771,14 +772,38 @@ function getMinimumColumnWidth(column, columnDraggable = false) {
|
|
|
771
772
|
if (column.rowSelection || column.rowNumber) return 44;
|
|
772
773
|
return 60;
|
|
773
774
|
}
|
|
774
|
-
function buildColumnMetrics(columns,
|
|
775
|
+
function buildColumnMetrics(columns, columnDraggableOrOptions = false) {
|
|
776
|
+
const options = typeof columnDraggableOrOptions === "boolean" ? { columnDraggable: columnDraggableOrOptions } : columnDraggableOrOptions;
|
|
777
|
+
const columnDraggable = options.columnDraggable ?? false;
|
|
775
778
|
let left = 0;
|
|
776
|
-
|
|
779
|
+
const metrics = columns.map((column) => {
|
|
777
780
|
const width = Math.max(getMinimumColumnWidth(column, columnDraggable), column.width ?? DEFAULT_COLUMN_WIDTH);
|
|
778
781
|
const metric = { left, width, right: left + width };
|
|
779
782
|
left += width;
|
|
780
783
|
return metric;
|
|
781
784
|
});
|
|
785
|
+
const viewportWidth = options.viewportWidth ?? 0;
|
|
786
|
+
if (viewportWidth <= left || columns.length === 0) return metrics;
|
|
787
|
+
const stretchable = columns.map((column, index) => ({ column, index })).filter(({ column }) => column.fixed !== "right" && !column.rowSelection && !column.rowDragHandle && !column.rowNumber);
|
|
788
|
+
const targets = stretchable.length > 0 ? stretchable : columns.map((column, index) => ({ column, index })).filter(({ column }) => column.fixed !== "right");
|
|
789
|
+
if (targets.length === 0) return metrics;
|
|
790
|
+
const extra = viewportWidth - left;
|
|
791
|
+
const baseTotal = targets.reduce((sum, { index }) => sum + metrics[index].width, 0);
|
|
792
|
+
let assigned = 0;
|
|
793
|
+
const targetIndexSet = new Set(targets.map(({ index }) => index));
|
|
794
|
+
const nextWidths = metrics.map((metric, index) => {
|
|
795
|
+
if (!targetIndexSet.has(index)) return metric.width;
|
|
796
|
+
const isLastTarget = index === targets[targets.length - 1].index;
|
|
797
|
+
const addition = isLastTarget ? extra - assigned : Math.floor(extra * (metric.width / baseTotal));
|
|
798
|
+
assigned += addition;
|
|
799
|
+
return metric.width + addition;
|
|
800
|
+
});
|
|
801
|
+
left = 0;
|
|
802
|
+
return nextWidths.map((width) => {
|
|
803
|
+
const metric = { left, width, right: left + width };
|
|
804
|
+
left += width;
|
|
805
|
+
return metric;
|
|
806
|
+
});
|
|
782
807
|
}
|
|
783
808
|
function lowerBound(metrics, value) {
|
|
784
809
|
let low = 0;
|
|
@@ -1199,6 +1224,7 @@ function useControllableValue(value, defaultValue, onChange) {
|
|
|
1199
1224
|
import { Fragment as Fragment3, jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1200
1225
|
var ANNOTATION_COLORS = ["#f44336", "#ff7a45", "#f5a623", "#f2c94c", "#52c41a", "#13a8a8", "#1677ff", "#597ef7", "#9254de", "#eb2f96"];
|
|
1201
1226
|
var FALLBACK_HEIGHT = 480;
|
|
1227
|
+
var EMPTY_BODY_HEIGHT = 240;
|
|
1202
1228
|
var VIRTUAL_OVERSCAN = 4;
|
|
1203
1229
|
var TOOLTIP_DELAY = 1e3;
|
|
1204
1230
|
var SUMMARY_CHUNK_SIZE = 5e3;
|
|
@@ -1272,6 +1298,7 @@ function Table({
|
|
|
1272
1298
|
rowKey,
|
|
1273
1299
|
width = "100%",
|
|
1274
1300
|
height = "100%",
|
|
1301
|
+
autoHeight = false,
|
|
1275
1302
|
rowHeight = 36,
|
|
1276
1303
|
headerHeight = 40,
|
|
1277
1304
|
fixedHeader = true,
|
|
@@ -1514,7 +1541,7 @@ function Table({
|
|
|
1514
1541
|
if (selection?.rowKey === editing.rowKey && selection.columnKey === editing.columnKey) return;
|
|
1515
1542
|
setEditing(null);
|
|
1516
1543
|
}, [editing, selection]);
|
|
1517
|
-
const metrics = useMemo(() => buildColumnMetrics(columns, columnDraggable), [columnDraggable, columns]);
|
|
1544
|
+
const metrics = useMemo(() => buildColumnMetrics(columns, { columnDraggable, viewportWidth: viewport.width }), [columnDraggable, columns, viewport.width]);
|
|
1518
1545
|
const contentWidth = metrics.length > 0 ? metrics[metrics.length - 1].right : 0;
|
|
1519
1546
|
const contentHeight = rows.length * rowHeight;
|
|
1520
1547
|
const fixedWidth = useMemo(() => columns.reduce((width2, column, index) => column.fixed === "left" ? Math.max(width2, metrics[index].right) : width2, 0), [columns, metrics]);
|
|
@@ -1535,7 +1562,10 @@ function Table({
|
|
|
1535
1562
|
const topSummaryHeight = hasSummaryRow && summaryPosition === "top" ? rowHeight : 0;
|
|
1536
1563
|
const bottomSummaryHeight = hasSummaryRow && summaryPosition === "bottom" ? rowHeight : 0;
|
|
1537
1564
|
const bodyTop = headerHeight + topSummaryHeight;
|
|
1538
|
-
const
|
|
1565
|
+
const bodyContentHeight = rows.length === 0 ? EMPTY_BODY_HEIGHT : contentHeight;
|
|
1566
|
+
const realContentHeight = bodyTop + bodyContentHeight + bottomSummaryHeight + (contentWidth > viewport.width ? horizontalScrollbarHeight : 0);
|
|
1567
|
+
const effectiveHeight = autoHeight ? Math.max(bodyTop + bottomSummaryHeight, Math.min(resolvedHeight, realContentHeight)) : resolvedHeight;
|
|
1568
|
+
const bodyViewportHeight = Math.max(0, effectiveHeight - (fixedHeader ? headerHeight : 0) - topSummaryHeight);
|
|
1539
1569
|
const [summaryState, setSummaryState] = useState4(() => ({ columns: null, rows: null, values: /* @__PURE__ */ new Map(), pending: false }));
|
|
1540
1570
|
const summaryPending = hasSummaryRow && (loading || summaryState.pending || summaryState.columns !== columns || summaryState.rows !== rows);
|
|
1541
1571
|
const summaryValues = hasSummaryRow && summaryState.columns === columns && summaryState.rows === rows ? summaryState.values : /* @__PURE__ */ new Map();
|
|
@@ -1671,9 +1701,8 @@ function Table({
|
|
|
1671
1701
|
const canvas = canvasRef.current;
|
|
1672
1702
|
if (!canvas || viewport.width <= 0) return;
|
|
1673
1703
|
const ratio = Math.min(window.devicePixelRatio || 1, 2);
|
|
1674
|
-
const displayHeight = resolvedHeight;
|
|
1675
1704
|
const physicalWidth = Math.round(viewport.width * ratio);
|
|
1676
|
-
const physicalHeight = Math.round(
|
|
1705
|
+
const physicalHeight = Math.round(effectiveHeight * ratio);
|
|
1677
1706
|
if (canvas.width !== physicalWidth) canvas.width = physicalWidth;
|
|
1678
1707
|
if (canvas.height !== physicalHeight) canvas.height = physicalHeight;
|
|
1679
1708
|
const context = canvas.getContext("2d");
|
|
@@ -1696,8 +1725,8 @@ function Table({
|
|
|
1696
1725
|
const scroll = scrollRef.current;
|
|
1697
1726
|
const rowScrollTop = fixedHeader ? scroll.top : Math.max(0, scroll.top - bodyTop);
|
|
1698
1727
|
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 };
|
|
1699
|
-
paintGrid({ context, width: viewport.width, height:
|
|
1700
|
-
}, [bodyTop, bodyViewportHeight, bottomSummaryHeight, cellAnnotations, cellSpanLookup, columnDraggable, columns, editedCellHighlightColor, editedCellKeys, editing, filterValues, fixedHeader, getRowKey, hasStripedRows, hasVerticalBorders, headerHeight, highlightsEditedCells, highlightsInsertedRows, insertedRowHighlightColor, insertedRowKeySet, isVirtualized, metrics,
|
|
1728
|
+
paintGrid({ context, width: viewport.width, height: effectiveHeight, pixelRatio: ratio, scrollLeft: scroll.left, scrollTop: scroll.top, rowHeight, headerHeight, bodyTop, suppressLastRowBottomBorder: bottomSummaryHeight > 0, suppressFrameBottomBorder: bottomSummaryHeight > 0, fixedHeader, verticalBorderless: !hasVerticalBorders, striped: hasStripedRows, columnDraggable, sortState, filterValues, hoveredHeaderAction: hoveredHeaderActionRef.current, rows, columns, metrics, range, selection, editing, hoveredRowIndex: hoveredRowIndexRef.current, selectionRange, selectedRowKeys: selectedRowKeySet, selectedColumnKeys: selectedColumnKeySet, cellSpans: cellSpanLookup.covered, maxRowSpan: cellSpanLookup.maxRowSpan, highlightEditedCells: highlightsEditedCells, highlightInsertedRows: highlightsInsertedRows, insertedRowKeys: insertedRowKeySet, editedCellKeys, cellAnnotations, getRowKey, rowDragPreview, colors: themeColors });
|
|
1729
|
+
}, [bodyTop, bodyViewportHeight, bottomSummaryHeight, cellAnnotations, cellSpanLookup, columnDraggable, columns, editedCellHighlightColor, editedCellKeys, editing, effectiveHeight, filterValues, fixedHeader, getRowKey, hasStripedRows, hasVerticalBorders, headerHeight, highlightsEditedCells, highlightsInsertedRows, insertedRowHighlightColor, insertedRowKeySet, isVirtualized, metrics, rowDragPreview, rowHeight, rows, selectedColumnKeySet, selectedRowKeySet, selection, selectionRange, sortState, stripedColor, viewport.width, virtualOverscan]);
|
|
1701
1730
|
const scheduleDraw = useCallback2(() => {
|
|
1702
1731
|
if (frameRef.current === null) frameRef.current = requestAnimationFrame(draw);
|
|
1703
1732
|
}, [draw]);
|
|
@@ -1806,14 +1835,14 @@ function Table({
|
|
|
1806
1835
|
const horizontalStart = column.fixed === void 0 ? fixedWidth : 0;
|
|
1807
1836
|
const horizontalEnd = column.fixed === void 0 ? viewport.width - rightFixedWidth : viewport.width;
|
|
1808
1837
|
const verticalStart = fixedHeader ? bodyTop : 0;
|
|
1809
|
-
if (rawRight <= horizontalStart || rawLeft >= horizontalEnd || rawBottom <= verticalStart || rawTop >=
|
|
1838
|
+
if (rawRight <= horizontalStart || rawLeft >= horizontalEnd || rawBottom <= verticalStart || rawTop >= effectiveHeight) {
|
|
1810
1839
|
focus.style.display = "none";
|
|
1811
1840
|
} else {
|
|
1812
1841
|
const borderWidth = 2;
|
|
1813
1842
|
const left = Math.round(Math.max(rawLeft - borderWidth, horizontalStart - 1));
|
|
1814
1843
|
const right = Math.round(Math.min(rawRight + 1, horizontalEnd, viewport.width));
|
|
1815
1844
|
const top = Math.round(Math.max(rawTop - borderWidth, verticalStart - 1));
|
|
1816
|
-
const bottom = Math.round(Math.min(rawBottom + 1,
|
|
1845
|
+
const bottom = Math.round(Math.min(rawBottom + 1, effectiveHeight));
|
|
1817
1846
|
focus.style.display = "block";
|
|
1818
1847
|
focus.style.left = `${left}px`;
|
|
1819
1848
|
focus.style.top = `${top}px`;
|
|
@@ -1838,7 +1867,7 @@ function Table({
|
|
|
1838
1867
|
setHoveredCellTooltip(null);
|
|
1839
1868
|
scheduleDraw();
|
|
1840
1869
|
setEditing(null);
|
|
1841
|
-
}, [bodyTop, columns, fixedHeader, fixedWidth, getCellDisplayWidth, getCellSpan, getRowKey, metrics,
|
|
1870
|
+
}, [bodyTop, columns, effectiveHeight, fixedHeader, fixedWidth, getCellDisplayWidth, getCellSpan, getRowKey, metrics, rightFixedOffsets, rightFixedWidth, rowHeight, rows, scheduleDraw, selection, selectionRange, viewport.width]);
|
|
1842
1871
|
const locateColumn = useCallback2((clientX) => {
|
|
1843
1872
|
const canvas = canvasRef.current;
|
|
1844
1873
|
if (!canvas) return -1;
|
|
@@ -2426,13 +2455,13 @@ function Table({
|
|
|
2426
2455
|
const rowTop = (fixedHeader ? 0 : bodyTop) + rowIndex * rowHeight;
|
|
2427
2456
|
const rowBottom = rowTop + rowHeight * (span?.rowSpan ?? 1);
|
|
2428
2457
|
const cellWidth = getCellDisplayWidth(columnIndex, span?.colSpan ?? 1);
|
|
2429
|
-
const visibleRowHeight = fixedHeader ?
|
|
2458
|
+
const visibleRowHeight = fixedHeader ? effectiveHeight - bodyTop : effectiveHeight;
|
|
2430
2459
|
if (rowTop < scroller.scrollTop) scroller.scrollTop = rowTop;
|
|
2431
2460
|
if (rowBottom > scroller.scrollTop + visibleRowHeight) scroller.scrollTop = rowBottom - visibleRowHeight;
|
|
2432
2461
|
if (columns[columnIndex].fixed === void 0 && metric.left < scroller.scrollLeft + fixedWidth) scroller.scrollLeft = Math.max(0, metric.left - fixedWidth);
|
|
2433
2462
|
if (columns[columnIndex].fixed === void 0 && metric.left + cellWidth > scroller.scrollLeft + viewport.width - rightFixedWidth) scroller.scrollLeft = metric.left + cellWidth - viewport.width + rightFixedWidth;
|
|
2434
2463
|
}
|
|
2435
|
-
}, [beginEdit, bodyTop, columns, editing, fixedHeader, fixedWidth, getCellDisplayWidth, getCellSpan, getRowKey, metrics,
|
|
2464
|
+
}, [beginEdit, bodyTop, columns, editing, effectiveHeight, fixedHeader, fixedWidth, getCellDisplayWidth, getCellSpan, getRowKey, metrics, rightFixedWidth, rowHeight, rows, selection, setSelection, viewport.width]);
|
|
2436
2465
|
const editorStyle = useMemo(() => {
|
|
2437
2466
|
if (!editing) return void 0;
|
|
2438
2467
|
const metric = metrics[editing.columnIndex];
|
|
@@ -2656,7 +2685,7 @@ function Table({
|
|
|
2656
2685
|
type: "cell",
|
|
2657
2686
|
...cell,
|
|
2658
2687
|
left: Math.min(Math.max(0, clientX - root.left), Math.max(0, viewport.width - 190)),
|
|
2659
|
-
top: Math.min(Math.max(0, clientY - root.top), Math.max(0,
|
|
2688
|
+
top: Math.min(Math.max(0, clientY - root.top), Math.max(0, effectiveHeight - 350))
|
|
2660
2689
|
});
|
|
2661
2690
|
onCellContextMenu?.({ ...cell, row: rows[cell.rowIndex], clientX, clientY });
|
|
2662
2691
|
};
|
|
@@ -2667,7 +2696,7 @@ function Table({
|
|
|
2667
2696
|
type: "header",
|
|
2668
2697
|
columnIndex,
|
|
2669
2698
|
left: Math.min(Math.max(0, clientX - root.left), Math.max(0, viewport.width - 180)),
|
|
2670
|
-
top: Math.min(Math.max(0, clientY - root.top), Math.max(0,
|
|
2699
|
+
top: Math.min(Math.max(0, clientY - root.top), Math.max(0, effectiveHeight - 68))
|
|
2671
2700
|
});
|
|
2672
2701
|
};
|
|
2673
2702
|
const getRowDragOffset = (rowIndex) => {
|
|
@@ -2897,7 +2926,7 @@ function Table({
|
|
|
2897
2926
|
const horizontalStart = column.fixed === void 0 ? fixedWidth : 0;
|
|
2898
2927
|
const horizontalEnd = column.fixed === void 0 ? viewport.width - rightFixedWidth : viewport.width;
|
|
2899
2928
|
const verticalStart = fixedHeader ? bodyTop : 0;
|
|
2900
|
-
if (rawLeft <= horizontalStart || rawLeft > horizontalEnd || rawTop <= verticalStart || rawTop >
|
|
2929
|
+
if (rawLeft <= horizontalStart || rawLeft > horizontalEnd || rawTop <= verticalStart || rawTop > effectiveHeight) return null;
|
|
2901
2930
|
return { left: rawLeft, top: rawTop, bounds };
|
|
2902
2931
|
})();
|
|
2903
2932
|
const selectionOutlineStyle = (() => {
|
|
@@ -2914,12 +2943,12 @@ function Table({
|
|
|
2914
2943
|
const horizontalStart = column.fixed === void 0 ? fixedWidth : 0;
|
|
2915
2944
|
const horizontalEnd = column.fixed === void 0 ? viewport.width - rightFixedWidth : viewport.width;
|
|
2916
2945
|
const verticalStart = fixedHeader ? bodyTop : 0;
|
|
2917
|
-
if (rawRight <= horizontalStart || rawLeft >= horizontalEnd || rawBottom <= verticalStart || rawTop >=
|
|
2946
|
+
if (rawRight <= horizontalStart || rawLeft >= horizontalEnd || rawBottom <= verticalStart || rawTop >= effectiveHeight) return null;
|
|
2918
2947
|
const borderWidth = 2;
|
|
2919
2948
|
const left = Math.round(Math.max(rawLeft - borderWidth, horizontalStart - 1));
|
|
2920
2949
|
const right = Math.round(Math.min(rawRight + 1, horizontalEnd, viewport.width));
|
|
2921
2950
|
const top = Math.round(Math.max(rawTop - borderWidth, verticalStart - 1));
|
|
2922
|
-
const bottom = Math.round(Math.min(rawBottom + 1,
|
|
2951
|
+
const bottom = Math.round(Math.min(rawBottom + 1, effectiveHeight));
|
|
2923
2952
|
return {
|
|
2924
2953
|
left,
|
|
2925
2954
|
top,
|
|
@@ -3052,8 +3081,8 @@ function Table({
|
|
|
3052
3081
|
};
|
|
3053
3082
|
const rootStyle = {
|
|
3054
3083
|
width,
|
|
3055
|
-
height,
|
|
3056
|
-
minHeight: typeof height === "number" ? void 0 : FALLBACK_HEIGHT,
|
|
3084
|
+
height: autoHeight ? effectiveHeight : height,
|
|
3085
|
+
minHeight: autoHeight || typeof height === "number" ? void 0 : FALLBACK_HEIGHT,
|
|
3057
3086
|
...stripedColor ? { "--rvg-color-stripe": stripedColor } : null,
|
|
3058
3087
|
...style
|
|
3059
3088
|
};
|
|
@@ -3066,7 +3095,7 @@ function Table({
|
|
|
3066
3095
|
{
|
|
3067
3096
|
ref: canvasRef,
|
|
3068
3097
|
className: "rvg-canvas",
|
|
3069
|
-
style: { width: viewport.width, height:
|
|
3098
|
+
style: { width: viewport.width, height: effectiveHeight },
|
|
3070
3099
|
onMouseMove: (event) => {
|
|
3071
3100
|
if (columnDragRef.current) return;
|
|
3072
3101
|
const rect = event.currentTarget.getBoundingClientRect();
|
|
@@ -3244,7 +3273,7 @@ function Table({
|
|
|
3244
3273
|
onContextMenu: handleContextMenu
|
|
3245
3274
|
}
|
|
3246
3275
|
),
|
|
3247
|
-
/* @__PURE__ */ jsxs7("div", { className: "rvg-text-layer", style: { width: viewport.width, height:
|
|
3276
|
+
/* @__PURE__ */ jsxs7("div", { className: "rvg-text-layer", style: { width: viewport.width, height: effectiveHeight, marginTop: -effectiveHeight }, onContextMenu: handleContextMenu, children: [
|
|
3248
3277
|
/* @__PURE__ */ jsx7("div", { className: "rvg-text-scroll-clip", style: { left: fixedWidth, right: rightFixedWidth }, children: /* @__PURE__ */ jsxs7(
|
|
3249
3278
|
"div",
|
|
3250
3279
|
{
|
|
@@ -3268,7 +3297,7 @@ function Table({
|
|
|
3268
3297
|
columns.map((column, columnIndex) => column.fixed === "left" ? renderHeaderTitle(columnIndex, metrics[columnIndex].left) : null),
|
|
3269
3298
|
columns.map((column, columnIndex) => column.fixed === "right" ? renderHeaderTitle(columnIndex, viewport.width - (rightFixedOffsets.get(columnIndex) ?? 0) - metrics[columnIndex].width) : null)
|
|
3270
3299
|
] }),
|
|
3271
|
-
/* @__PURE__ */ jsx7("div", { className: "rvg-spacer", style: { width: contentWidth, height: contentHeight + bodyTop, marginTop: -
|
|
3300
|
+
/* @__PURE__ */ jsx7("div", { className: "rvg-spacer", style: { width: contentWidth, height: contentHeight + bodyTop, marginTop: -effectiveHeight } })
|
|
3272
3301
|
] }),
|
|
3273
3302
|
hasSummaryRow && /* @__PURE__ */ jsxs7(
|
|
3274
3303
|
"div",
|
|
@@ -3629,10 +3658,10 @@ function Table({
|
|
|
3629
3658
|
] })
|
|
3630
3659
|
] }),
|
|
3631
3660
|
renderEditor(),
|
|
3632
|
-
rows.length === 0 && !loading && /* @__PURE__ */ jsx7("div", { className: "rvg-empty", children: emptyContent ?? /* @__PURE__ */ jsx7(DefaultEmptyState, { label: labels.empty }) }),
|
|
3661
|
+
rows.length === 0 && !loading && /* @__PURE__ */ jsx7("div", { className: "rvg-empty", style: { top: bodyTop }, children: emptyContent ?? /* @__PURE__ */ jsx7(DefaultEmptyState, { label: labels.empty }) }),
|
|
3633
3662
|
loading && hasCustomLoading && /* @__PURE__ */ jsx7("div", { className: "rvg-custom-loading", "aria-label": labels.refreshing, children: loadingContent }),
|
|
3634
3663
|
loading && !hasCustomLoading && !hasCompletedLoadRef.current && /* @__PURE__ */ jsxs7("div", { className: "rvg-initial-loading", style: { top: headerHeight }, "aria-label": labels.initialLoading, children: [
|
|
3635
|
-
Array.from({ length: Math.ceil((
|
|
3664
|
+
Array.from({ length: Math.ceil((effectiveHeight - headerHeight) / rowHeight) }, (_, rowIndex) => /* @__PURE__ */ jsx7("div", { className: "rvg-loading-row", style: { height: rowHeight }, children: columns.map((column, columnIndex) => {
|
|
3636
3665
|
const left = getDisplayedColumnLeft(columnIndex);
|
|
3637
3666
|
const columnWidth = metrics[columnIndex].width;
|
|
3638
3667
|
if (left + columnWidth <= 0 || left >= viewport.width) return null;
|