@lensui/lens-table 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1440,7 +1440,7 @@ function Table({
1440
1440
  const hoveredRowIndexRef = (0, import_react5.useRef)(null);
1441
1441
  const [viewport, setViewport] = (0, import_react5.useState)({ width: 0, height: typeof height === "number" ? height : FALLBACK_HEIGHT });
1442
1442
  const [horizontalScrollbarHeight, setHorizontalScrollbarHeight] = (0, import_react5.useState)(0);
1443
- const resolvedHeight = viewport.height || FALLBACK_HEIGHT;
1443
+ const resolvedHeight = typeof height === "number" ? height : viewport.height || FALLBACK_HEIGHT;
1444
1444
  const [scrollPosition, setScrollPosition] = (0, import_react5.useState)({ left: 0, top: 0 });
1445
1445
  const scrollRef = (0, import_react5.useRef)({ left: 0, top: 0 });
1446
1446
  const [selection, setSelection] = useControllableValue(selectedCell, defaultSelectedCell, onSelectedCellChange);
@@ -1588,14 +1588,15 @@ function Table({
1588
1588
  }, [columns, metrics]);
1589
1589
  const hasRowSelectionColumn = (0, import_react5.useMemo)(() => columns.some((column) => column.rowSelection), [columns]);
1590
1590
  const rowSelectionMode = typeof rowSelection === "object" ? rowSelection.mode ?? "multiple" : "multiple";
1591
- const hasSummaryRow = (0, import_react5.useMemo)(() => summaryEnabled && columns.some((column) => Boolean(column.summary)), [columns, summaryEnabled]);
1591
+ const hasSummaryRow = (0, import_react5.useMemo)(() => rows.length > 0 && summaryEnabled && columns.some((column) => Boolean(column.summary)), [columns, rows.length, summaryEnabled]);
1592
1592
  const topSummaryHeight = hasSummaryRow && summaryPosition === "top" ? rowHeight : 0;
1593
1593
  const bottomSummaryHeight = hasSummaryRow && summaryPosition === "bottom" ? rowHeight : 0;
1594
1594
  const bodyTop = headerHeight + topSummaryHeight;
1595
1595
  const bodyContentHeight = rows.length === 0 ? EMPTY_BODY_HEIGHT : contentHeight;
1596
1596
  const realContentHeight = bodyTop + bodyContentHeight + bottomSummaryHeight + (contentWidth > viewport.width ? horizontalScrollbarHeight : 0);
1597
1597
  const effectiveHeight = autoHeight ? Math.max(bodyTop + bottomSummaryHeight, Math.min(resolvedHeight, realContentHeight)) : resolvedHeight;
1598
- const bodyViewportHeight = Math.max(0, effectiveHeight - (fixedHeader ? headerHeight : 0) - topSummaryHeight);
1598
+ const renderHeight = Math.max(0, effectiveHeight - bottomSummaryHeight);
1599
+ const bodyViewportHeight = Math.max(0, renderHeight - (fixedHeader ? headerHeight : 0) - topSummaryHeight);
1599
1600
  const [summaryState, setSummaryState] = (0, import_react5.useState)(() => ({ columns: null, rows: null, values: /* @__PURE__ */ new Map(), pending: false }));
1600
1601
  const summaryPending = hasSummaryRow && (loading || summaryState.pending || summaryState.columns !== columns || summaryState.rows !== rows);
1601
1602
  const summaryValues = hasSummaryRow && summaryState.columns === columns && summaryState.rows === rows ? summaryState.values : /* @__PURE__ */ new Map();
@@ -1732,7 +1733,7 @@ function Table({
1732
1733
  if (!canvas || viewport.width <= 0) return;
1733
1734
  const ratio = Math.min(window.devicePixelRatio || 1, 2);
1734
1735
  const physicalWidth = Math.round(viewport.width * ratio);
1735
- const physicalHeight = Math.round(effectiveHeight * ratio);
1736
+ const physicalHeight = Math.round(renderHeight * ratio);
1736
1737
  if (canvas.width !== physicalWidth) canvas.width = physicalWidth;
1737
1738
  if (canvas.height !== physicalHeight) canvas.height = physicalHeight;
1738
1739
  const context = canvas.getContext("2d");
@@ -1755,8 +1756,8 @@ function Table({
1755
1756
  const scroll = scrollRef.current;
1756
1757
  const rowScrollTop = fixedHeader ? scroll.top : Math.max(0, scroll.top - bodyTop);
1757
1758
  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 };
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]);
1759
+ paintGrid({ context, width: viewport.width, height: renderHeight, 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 });
1760
+ }, [bodyTop, bodyViewportHeight, bottomSummaryHeight, cellAnnotations, cellSpanLookup, columnDraggable, columns, editedCellHighlightColor, editedCellKeys, editing, renderHeight, filterValues, fixedHeader, getRowKey, hasStripedRows, hasVerticalBorders, headerHeight, highlightsEditedCells, highlightsInsertedRows, insertedRowHighlightColor, insertedRowKeySet, isVirtualized, metrics, rowDragPreview, rowHeight, rows, selectedColumnKeySet, selectedRowKeySet, selection, selectionRange, sortState, stripedColor, viewport.width, virtualOverscan]);
1760
1761
  const scheduleDraw = (0, import_react5.useCallback)(() => {
1761
1762
  if (frameRef.current === null) frameRef.current = requestAnimationFrame(draw);
1762
1763
  }, [draw]);
@@ -1865,14 +1866,14 @@ function Table({
1865
1866
  const horizontalStart = column.fixed === void 0 ? fixedWidth : 0;
1866
1867
  const horizontalEnd = column.fixed === void 0 ? viewport.width - rightFixedWidth : viewport.width;
1867
1868
  const verticalStart = fixedHeader ? bodyTop : 0;
1868
- if (rawRight <= horizontalStart || rawLeft >= horizontalEnd || rawBottom <= verticalStart || rawTop >= effectiveHeight) {
1869
+ if (rawRight <= horizontalStart || rawLeft >= horizontalEnd || rawBottom <= verticalStart || rawTop >= renderHeight) {
1869
1870
  focus.style.display = "none";
1870
1871
  } else {
1871
1872
  const borderWidth = 2;
1872
1873
  const left = Math.round(Math.max(rawLeft - borderWidth, horizontalStart - 1));
1873
1874
  const right = Math.round(Math.min(rawRight + 1, horizontalEnd, viewport.width));
1874
1875
  const top = Math.round(Math.max(rawTop - borderWidth, verticalStart - 1));
1875
- const bottom = Math.round(Math.min(rawBottom + 1, effectiveHeight));
1876
+ const bottom = Math.round(Math.min(rawBottom + 1, renderHeight));
1876
1877
  focus.style.display = "block";
1877
1878
  focus.style.left = `${left}px`;
1878
1879
  focus.style.top = `${top}px`;
@@ -1897,7 +1898,7 @@ function Table({
1897
1898
  setHoveredCellTooltip(null);
1898
1899
  scheduleDraw();
1899
1900
  setEditing(null);
1900
- }, [bodyTop, columns, effectiveHeight, fixedHeader, fixedWidth, getCellDisplayWidth, getCellSpan, getRowKey, metrics, rightFixedOffsets, rightFixedWidth, rowHeight, rows, scheduleDraw, selection, selectionRange, viewport.width]);
1901
+ }, [bodyTop, columns, renderHeight, fixedHeader, fixedWidth, getCellDisplayWidth, getCellSpan, getRowKey, metrics, rightFixedOffsets, rightFixedWidth, rowHeight, rows, scheduleDraw, selection, selectionRange, viewport.width]);
1901
1902
  const locateColumn = (0, import_react5.useCallback)((clientX) => {
1902
1903
  const canvas = canvasRef.current;
1903
1904
  if (!canvas) return -1;
@@ -2485,13 +2486,13 @@ function Table({
2485
2486
  const rowTop = (fixedHeader ? 0 : bodyTop) + rowIndex * rowHeight;
2486
2487
  const rowBottom = rowTop + rowHeight * (span?.rowSpan ?? 1);
2487
2488
  const cellWidth = getCellDisplayWidth(columnIndex, span?.colSpan ?? 1);
2488
- const visibleRowHeight = fixedHeader ? effectiveHeight - bodyTop : effectiveHeight;
2489
+ const visibleRowHeight = fixedHeader ? renderHeight - bodyTop : renderHeight;
2489
2490
  if (rowTop < scroller.scrollTop) scroller.scrollTop = rowTop;
2490
2491
  if (rowBottom > scroller.scrollTop + visibleRowHeight) scroller.scrollTop = rowBottom - visibleRowHeight;
2491
2492
  if (columns[columnIndex].fixed === void 0 && metric.left < scroller.scrollLeft + fixedWidth) scroller.scrollLeft = Math.max(0, metric.left - fixedWidth);
2492
2493
  if (columns[columnIndex].fixed === void 0 && metric.left + cellWidth > scroller.scrollLeft + viewport.width - rightFixedWidth) scroller.scrollLeft = metric.left + cellWidth - viewport.width + rightFixedWidth;
2493
2494
  }
2494
- }, [beginEdit, bodyTop, columns, editing, effectiveHeight, fixedHeader, fixedWidth, getCellDisplayWidth, getCellSpan, getRowKey, metrics, rightFixedWidth, rowHeight, rows, selection, setSelection, viewport.width]);
2495
+ }, [beginEdit, bodyTop, columns, editing, renderHeight, fixedHeader, fixedWidth, getCellDisplayWidth, getCellSpan, getRowKey, metrics, rightFixedWidth, rowHeight, rows, selection, setSelection, viewport.width]);
2495
2496
  const editorStyle = (0, import_react5.useMemo)(() => {
2496
2497
  if (!editing) return void 0;
2497
2498
  const metric = metrics[editing.columnIndex];
@@ -2715,7 +2716,7 @@ function Table({
2715
2716
  type: "cell",
2716
2717
  ...cell,
2717
2718
  left: Math.min(Math.max(0, clientX - root.left), Math.max(0, viewport.width - 190)),
2718
- top: Math.min(Math.max(0, clientY - root.top), Math.max(0, effectiveHeight - 350))
2719
+ top: Math.min(Math.max(0, clientY - root.top), Math.max(0, renderHeight - 350))
2719
2720
  });
2720
2721
  onCellContextMenu?.({ ...cell, row: rows[cell.rowIndex], clientX, clientY });
2721
2722
  };
@@ -2726,7 +2727,7 @@ function Table({
2726
2727
  type: "header",
2727
2728
  columnIndex,
2728
2729
  left: Math.min(Math.max(0, clientX - root.left), Math.max(0, viewport.width - 180)),
2729
- top: Math.min(Math.max(0, clientY - root.top), Math.max(0, effectiveHeight - 68))
2730
+ top: Math.min(Math.max(0, clientY - root.top), Math.max(0, renderHeight - 68))
2730
2731
  });
2731
2732
  };
2732
2733
  const getRowDragOffset = (rowIndex) => {
@@ -2956,7 +2957,7 @@ function Table({
2956
2957
  const horizontalStart = column.fixed === void 0 ? fixedWidth : 0;
2957
2958
  const horizontalEnd = column.fixed === void 0 ? viewport.width - rightFixedWidth : viewport.width;
2958
2959
  const verticalStart = fixedHeader ? bodyTop : 0;
2959
- if (rawLeft <= horizontalStart || rawLeft > horizontalEnd || rawTop <= verticalStart || rawTop > effectiveHeight) return null;
2960
+ if (rawLeft <= horizontalStart || rawLeft > horizontalEnd || rawTop <= verticalStart || rawTop > renderHeight) return null;
2960
2961
  return { left: rawLeft, top: rawTop, bounds };
2961
2962
  })();
2962
2963
  const selectionOutlineStyle = (() => {
@@ -2973,12 +2974,12 @@ function Table({
2973
2974
  const horizontalStart = column.fixed === void 0 ? fixedWidth : 0;
2974
2975
  const horizontalEnd = column.fixed === void 0 ? viewport.width - rightFixedWidth : viewport.width;
2975
2976
  const verticalStart = fixedHeader ? bodyTop : 0;
2976
- if (rawRight <= horizontalStart || rawLeft >= horizontalEnd || rawBottom <= verticalStart || rawTop >= effectiveHeight) return null;
2977
+ if (rawRight <= horizontalStart || rawLeft >= horizontalEnd || rawBottom <= verticalStart || rawTop >= renderHeight) return null;
2977
2978
  const borderWidth = 2;
2978
2979
  const left = Math.round(Math.max(rawLeft - borderWidth, horizontalStart - 1));
2979
2980
  const right = Math.round(Math.min(rawRight + 1, horizontalEnd, viewport.width));
2980
2981
  const top = Math.round(Math.max(rawTop - borderWidth, verticalStart - 1));
2981
- const bottom = Math.round(Math.min(rawBottom + 1, effectiveHeight));
2982
+ const bottom = Math.round(Math.min(rawBottom + 1, renderHeight));
2982
2983
  return {
2983
2984
  left,
2984
2985
  top,
@@ -3093,8 +3094,10 @@ function Table({
3093
3094
  const renderSummaryCell = (columnIndex, left) => {
3094
3095
  const column = columns[columnIndex];
3095
3096
  const isUtility = column.rowSelection || column.rowDragHandle || column.rowNumber;
3096
- const summaryContent = summaryValues.has(column.key) ? summaryValues.get(column.key) : summaryEmptyValue;
3097
- const content = column.rowNumber ? language === "zh-CN" ? "\u5408\u8BA1" : "Total" : summaryPending ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "rvg-summary-skeleton" }) : summaryContent;
3097
+ const hasSummaryValue = summaryValues.has(column.key);
3098
+ const summaryContent = hasSummaryValue ? summaryValues.get(column.key) : summaryEmptyValue;
3099
+ const showSummarySkeleton = Boolean(column.summary) && summaryPending;
3100
+ const content = columnIndex === 0 ? language === "zh-CN" ? "\u5408\u8BA1" : "Total" : showSummarySkeleton ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "rvg-summary-skeleton" }) : summaryContent;
3098
3101
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3099
3102
  "div",
3100
3103
  {
@@ -3125,7 +3128,7 @@ function Table({
3125
3128
  {
3126
3129
  ref: canvasRef,
3127
3130
  className: "rvg-canvas",
3128
- style: { width: viewport.width, height: effectiveHeight },
3131
+ style: { width: viewport.width, height: renderHeight },
3129
3132
  onMouseMove: (event) => {
3130
3133
  if (columnDragRef.current) return;
3131
3134
  const rect = event.currentTarget.getBoundingClientRect();
@@ -3303,7 +3306,7 @@ function Table({
3303
3306
  onContextMenu: handleContextMenu
3304
3307
  }
3305
3308
  ),
3306
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "rvg-text-layer", style: { width: viewport.width, height: effectiveHeight, marginTop: -effectiveHeight }, onContextMenu: handleContextMenu, children: [
3309
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "rvg-text-layer", style: { width: viewport.width, height: renderHeight, marginTop: -renderHeight }, onContextMenu: handleContextMenu, children: [
3307
3310
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "rvg-text-scroll-clip", style: { left: fixedWidth, right: rightFixedWidth }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
3308
3311
  "div",
3309
3312
  {
@@ -3327,7 +3330,7 @@ function Table({
3327
3330
  columns.map((column, columnIndex) => column.fixed === "left" ? renderHeaderTitle(columnIndex, metrics[columnIndex].left) : null),
3328
3331
  columns.map((column, columnIndex) => column.fixed === "right" ? renderHeaderTitle(columnIndex, viewport.width - (rightFixedOffsets.get(columnIndex) ?? 0) - metrics[columnIndex].width) : null)
3329
3332
  ] }),
3330
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "rvg-spacer", style: { width: contentWidth, height: contentHeight + bodyTop, marginTop: -effectiveHeight } })
3333
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "rvg-spacer", style: { width: contentWidth, height: contentHeight + bodyTop, marginTop: -renderHeight } })
3331
3334
  ] }),
3332
3335
  hasSummaryRow && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
3333
3336
  "div",
@@ -3691,7 +3694,7 @@ function Table({
3691
3694
  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 }) }),
3692
3695
  loading && hasCustomLoading && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "rvg-custom-loading", "aria-label": labels.refreshing, children: loadingContent }),
3693
3696
  loading && !hasCustomLoading && !hasCompletedLoadRef.current && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "rvg-initial-loading", style: { top: headerHeight }, "aria-label": labels.initialLoading, children: [
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) => {
3697
+ Array.from({ length: Math.ceil((renderHeight - headerHeight) / rowHeight) }, (_, rowIndex) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "rvg-loading-row", style: { height: rowHeight }, children: columns.map((column, columnIndex) => {
3695
3698
  const left = getDisplayedColumnLeft(columnIndex);
3696
3699
  const columnWidth = metrics[columnIndex].width;
3697
3700
  if (left + columnWidth <= 0 || left >= viewport.width) return null;
package/dist/index.js CHANGED
@@ -1410,7 +1410,7 @@ function Table({
1410
1410
  const hoveredRowIndexRef = useRef2(null);
1411
1411
  const [viewport, setViewport] = useState4({ width: 0, height: typeof height === "number" ? height : FALLBACK_HEIGHT });
1412
1412
  const [horizontalScrollbarHeight, setHorizontalScrollbarHeight] = useState4(0);
1413
- const resolvedHeight = viewport.height || FALLBACK_HEIGHT;
1413
+ const resolvedHeight = typeof height === "number" ? height : viewport.height || FALLBACK_HEIGHT;
1414
1414
  const [scrollPosition, setScrollPosition] = useState4({ left: 0, top: 0 });
1415
1415
  const scrollRef = useRef2({ left: 0, top: 0 });
1416
1416
  const [selection, setSelection] = useControllableValue(selectedCell, defaultSelectedCell, onSelectedCellChange);
@@ -1558,14 +1558,15 @@ function Table({
1558
1558
  }, [columns, metrics]);
1559
1559
  const hasRowSelectionColumn = useMemo(() => columns.some((column) => column.rowSelection), [columns]);
1560
1560
  const rowSelectionMode = typeof rowSelection === "object" ? rowSelection.mode ?? "multiple" : "multiple";
1561
- const hasSummaryRow = useMemo(() => summaryEnabled && columns.some((column) => Boolean(column.summary)), [columns, summaryEnabled]);
1561
+ const hasSummaryRow = useMemo(() => rows.length > 0 && summaryEnabled && columns.some((column) => Boolean(column.summary)), [columns, rows.length, summaryEnabled]);
1562
1562
  const topSummaryHeight = hasSummaryRow && summaryPosition === "top" ? rowHeight : 0;
1563
1563
  const bottomSummaryHeight = hasSummaryRow && summaryPosition === "bottom" ? rowHeight : 0;
1564
1564
  const bodyTop = headerHeight + topSummaryHeight;
1565
1565
  const bodyContentHeight = rows.length === 0 ? EMPTY_BODY_HEIGHT : contentHeight;
1566
1566
  const realContentHeight = bodyTop + bodyContentHeight + bottomSummaryHeight + (contentWidth > viewport.width ? horizontalScrollbarHeight : 0);
1567
1567
  const effectiveHeight = autoHeight ? Math.max(bodyTop + bottomSummaryHeight, Math.min(resolvedHeight, realContentHeight)) : resolvedHeight;
1568
- const bodyViewportHeight = Math.max(0, effectiveHeight - (fixedHeader ? headerHeight : 0) - topSummaryHeight);
1568
+ const renderHeight = Math.max(0, effectiveHeight - bottomSummaryHeight);
1569
+ const bodyViewportHeight = Math.max(0, renderHeight - (fixedHeader ? headerHeight : 0) - topSummaryHeight);
1569
1570
  const [summaryState, setSummaryState] = useState4(() => ({ columns: null, rows: null, values: /* @__PURE__ */ new Map(), pending: false }));
1570
1571
  const summaryPending = hasSummaryRow && (loading || summaryState.pending || summaryState.columns !== columns || summaryState.rows !== rows);
1571
1572
  const summaryValues = hasSummaryRow && summaryState.columns === columns && summaryState.rows === rows ? summaryState.values : /* @__PURE__ */ new Map();
@@ -1702,7 +1703,7 @@ function Table({
1702
1703
  if (!canvas || viewport.width <= 0) return;
1703
1704
  const ratio = Math.min(window.devicePixelRatio || 1, 2);
1704
1705
  const physicalWidth = Math.round(viewport.width * ratio);
1705
- const physicalHeight = Math.round(effectiveHeight * ratio);
1706
+ const physicalHeight = Math.round(renderHeight * ratio);
1706
1707
  if (canvas.width !== physicalWidth) canvas.width = physicalWidth;
1707
1708
  if (canvas.height !== physicalHeight) canvas.height = physicalHeight;
1708
1709
  const context = canvas.getContext("2d");
@@ -1725,8 +1726,8 @@ function Table({
1725
1726
  const scroll = scrollRef.current;
1726
1727
  const rowScrollTop = fixedHeader ? scroll.top : Math.max(0, scroll.top - bodyTop);
1727
1728
  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 };
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]);
1729
+ paintGrid({ context, width: viewport.width, height: renderHeight, 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 });
1730
+ }, [bodyTop, bodyViewportHeight, bottomSummaryHeight, cellAnnotations, cellSpanLookup, columnDraggable, columns, editedCellHighlightColor, editedCellKeys, editing, renderHeight, filterValues, fixedHeader, getRowKey, hasStripedRows, hasVerticalBorders, headerHeight, highlightsEditedCells, highlightsInsertedRows, insertedRowHighlightColor, insertedRowKeySet, isVirtualized, metrics, rowDragPreview, rowHeight, rows, selectedColumnKeySet, selectedRowKeySet, selection, selectionRange, sortState, stripedColor, viewport.width, virtualOverscan]);
1730
1731
  const scheduleDraw = useCallback2(() => {
1731
1732
  if (frameRef.current === null) frameRef.current = requestAnimationFrame(draw);
1732
1733
  }, [draw]);
@@ -1835,14 +1836,14 @@ function Table({
1835
1836
  const horizontalStart = column.fixed === void 0 ? fixedWidth : 0;
1836
1837
  const horizontalEnd = column.fixed === void 0 ? viewport.width - rightFixedWidth : viewport.width;
1837
1838
  const verticalStart = fixedHeader ? bodyTop : 0;
1838
- if (rawRight <= horizontalStart || rawLeft >= horizontalEnd || rawBottom <= verticalStart || rawTop >= effectiveHeight) {
1839
+ if (rawRight <= horizontalStart || rawLeft >= horizontalEnd || rawBottom <= verticalStart || rawTop >= renderHeight) {
1839
1840
  focus.style.display = "none";
1840
1841
  } else {
1841
1842
  const borderWidth = 2;
1842
1843
  const left = Math.round(Math.max(rawLeft - borderWidth, horizontalStart - 1));
1843
1844
  const right = Math.round(Math.min(rawRight + 1, horizontalEnd, viewport.width));
1844
1845
  const top = Math.round(Math.max(rawTop - borderWidth, verticalStart - 1));
1845
- const bottom = Math.round(Math.min(rawBottom + 1, effectiveHeight));
1846
+ const bottom = Math.round(Math.min(rawBottom + 1, renderHeight));
1846
1847
  focus.style.display = "block";
1847
1848
  focus.style.left = `${left}px`;
1848
1849
  focus.style.top = `${top}px`;
@@ -1867,7 +1868,7 @@ function Table({
1867
1868
  setHoveredCellTooltip(null);
1868
1869
  scheduleDraw();
1869
1870
  setEditing(null);
1870
- }, [bodyTop, columns, effectiveHeight, fixedHeader, fixedWidth, getCellDisplayWidth, getCellSpan, getRowKey, metrics, rightFixedOffsets, rightFixedWidth, rowHeight, rows, scheduleDraw, selection, selectionRange, viewport.width]);
1871
+ }, [bodyTop, columns, renderHeight, fixedHeader, fixedWidth, getCellDisplayWidth, getCellSpan, getRowKey, metrics, rightFixedOffsets, rightFixedWidth, rowHeight, rows, scheduleDraw, selection, selectionRange, viewport.width]);
1871
1872
  const locateColumn = useCallback2((clientX) => {
1872
1873
  const canvas = canvasRef.current;
1873
1874
  if (!canvas) return -1;
@@ -2455,13 +2456,13 @@ function Table({
2455
2456
  const rowTop = (fixedHeader ? 0 : bodyTop) + rowIndex * rowHeight;
2456
2457
  const rowBottom = rowTop + rowHeight * (span?.rowSpan ?? 1);
2457
2458
  const cellWidth = getCellDisplayWidth(columnIndex, span?.colSpan ?? 1);
2458
- const visibleRowHeight = fixedHeader ? effectiveHeight - bodyTop : effectiveHeight;
2459
+ const visibleRowHeight = fixedHeader ? renderHeight - bodyTop : renderHeight;
2459
2460
  if (rowTop < scroller.scrollTop) scroller.scrollTop = rowTop;
2460
2461
  if (rowBottom > scroller.scrollTop + visibleRowHeight) scroller.scrollTop = rowBottom - visibleRowHeight;
2461
2462
  if (columns[columnIndex].fixed === void 0 && metric.left < scroller.scrollLeft + fixedWidth) scroller.scrollLeft = Math.max(0, metric.left - fixedWidth);
2462
2463
  if (columns[columnIndex].fixed === void 0 && metric.left + cellWidth > scroller.scrollLeft + viewport.width - rightFixedWidth) scroller.scrollLeft = metric.left + cellWidth - viewport.width + rightFixedWidth;
2463
2464
  }
2464
- }, [beginEdit, bodyTop, columns, editing, effectiveHeight, fixedHeader, fixedWidth, getCellDisplayWidth, getCellSpan, getRowKey, metrics, rightFixedWidth, rowHeight, rows, selection, setSelection, viewport.width]);
2465
+ }, [beginEdit, bodyTop, columns, editing, renderHeight, fixedHeader, fixedWidth, getCellDisplayWidth, getCellSpan, getRowKey, metrics, rightFixedWidth, rowHeight, rows, selection, setSelection, viewport.width]);
2465
2466
  const editorStyle = useMemo(() => {
2466
2467
  if (!editing) return void 0;
2467
2468
  const metric = metrics[editing.columnIndex];
@@ -2685,7 +2686,7 @@ function Table({
2685
2686
  type: "cell",
2686
2687
  ...cell,
2687
2688
  left: Math.min(Math.max(0, clientX - root.left), Math.max(0, viewport.width - 190)),
2688
- top: Math.min(Math.max(0, clientY - root.top), Math.max(0, effectiveHeight - 350))
2689
+ top: Math.min(Math.max(0, clientY - root.top), Math.max(0, renderHeight - 350))
2689
2690
  });
2690
2691
  onCellContextMenu?.({ ...cell, row: rows[cell.rowIndex], clientX, clientY });
2691
2692
  };
@@ -2696,7 +2697,7 @@ function Table({
2696
2697
  type: "header",
2697
2698
  columnIndex,
2698
2699
  left: Math.min(Math.max(0, clientX - root.left), Math.max(0, viewport.width - 180)),
2699
- top: Math.min(Math.max(0, clientY - root.top), Math.max(0, effectiveHeight - 68))
2700
+ top: Math.min(Math.max(0, clientY - root.top), Math.max(0, renderHeight - 68))
2700
2701
  });
2701
2702
  };
2702
2703
  const getRowDragOffset = (rowIndex) => {
@@ -2926,7 +2927,7 @@ function Table({
2926
2927
  const horizontalStart = column.fixed === void 0 ? fixedWidth : 0;
2927
2928
  const horizontalEnd = column.fixed === void 0 ? viewport.width - rightFixedWidth : viewport.width;
2928
2929
  const verticalStart = fixedHeader ? bodyTop : 0;
2929
- if (rawLeft <= horizontalStart || rawLeft > horizontalEnd || rawTop <= verticalStart || rawTop > effectiveHeight) return null;
2930
+ if (rawLeft <= horizontalStart || rawLeft > horizontalEnd || rawTop <= verticalStart || rawTop > renderHeight) return null;
2930
2931
  return { left: rawLeft, top: rawTop, bounds };
2931
2932
  })();
2932
2933
  const selectionOutlineStyle = (() => {
@@ -2943,12 +2944,12 @@ function Table({
2943
2944
  const horizontalStart = column.fixed === void 0 ? fixedWidth : 0;
2944
2945
  const horizontalEnd = column.fixed === void 0 ? viewport.width - rightFixedWidth : viewport.width;
2945
2946
  const verticalStart = fixedHeader ? bodyTop : 0;
2946
- if (rawRight <= horizontalStart || rawLeft >= horizontalEnd || rawBottom <= verticalStart || rawTop >= effectiveHeight) return null;
2947
+ if (rawRight <= horizontalStart || rawLeft >= horizontalEnd || rawBottom <= verticalStart || rawTop >= renderHeight) return null;
2947
2948
  const borderWidth = 2;
2948
2949
  const left = Math.round(Math.max(rawLeft - borderWidth, horizontalStart - 1));
2949
2950
  const right = Math.round(Math.min(rawRight + 1, horizontalEnd, viewport.width));
2950
2951
  const top = Math.round(Math.max(rawTop - borderWidth, verticalStart - 1));
2951
- const bottom = Math.round(Math.min(rawBottom + 1, effectiveHeight));
2952
+ const bottom = Math.round(Math.min(rawBottom + 1, renderHeight));
2952
2953
  return {
2953
2954
  left,
2954
2955
  top,
@@ -3063,8 +3064,10 @@ function Table({
3063
3064
  const renderSummaryCell = (columnIndex, left) => {
3064
3065
  const column = columns[columnIndex];
3065
3066
  const isUtility = column.rowSelection || column.rowDragHandle || column.rowNumber;
3066
- const summaryContent = summaryValues.has(column.key) ? summaryValues.get(column.key) : summaryEmptyValue;
3067
- const content = column.rowNumber ? language === "zh-CN" ? "\u5408\u8BA1" : "Total" : summaryPending ? /* @__PURE__ */ jsx7("span", { className: "rvg-summary-skeleton" }) : summaryContent;
3067
+ const hasSummaryValue = summaryValues.has(column.key);
3068
+ const summaryContent = hasSummaryValue ? summaryValues.get(column.key) : summaryEmptyValue;
3069
+ const showSummarySkeleton = Boolean(column.summary) && summaryPending;
3070
+ const content = columnIndex === 0 ? language === "zh-CN" ? "\u5408\u8BA1" : "Total" : showSummarySkeleton ? /* @__PURE__ */ jsx7("span", { className: "rvg-summary-skeleton" }) : summaryContent;
3068
3071
  return /* @__PURE__ */ jsx7(
3069
3072
  "div",
3070
3073
  {
@@ -3095,7 +3098,7 @@ function Table({
3095
3098
  {
3096
3099
  ref: canvasRef,
3097
3100
  className: "rvg-canvas",
3098
- style: { width: viewport.width, height: effectiveHeight },
3101
+ style: { width: viewport.width, height: renderHeight },
3099
3102
  onMouseMove: (event) => {
3100
3103
  if (columnDragRef.current) return;
3101
3104
  const rect = event.currentTarget.getBoundingClientRect();
@@ -3273,7 +3276,7 @@ function Table({
3273
3276
  onContextMenu: handleContextMenu
3274
3277
  }
3275
3278
  ),
3276
- /* @__PURE__ */ jsxs7("div", { className: "rvg-text-layer", style: { width: viewport.width, height: effectiveHeight, marginTop: -effectiveHeight }, onContextMenu: handleContextMenu, children: [
3279
+ /* @__PURE__ */ jsxs7("div", { className: "rvg-text-layer", style: { width: viewport.width, height: renderHeight, marginTop: -renderHeight }, onContextMenu: handleContextMenu, children: [
3277
3280
  /* @__PURE__ */ jsx7("div", { className: "rvg-text-scroll-clip", style: { left: fixedWidth, right: rightFixedWidth }, children: /* @__PURE__ */ jsxs7(
3278
3281
  "div",
3279
3282
  {
@@ -3297,7 +3300,7 @@ function Table({
3297
3300
  columns.map((column, columnIndex) => column.fixed === "left" ? renderHeaderTitle(columnIndex, metrics[columnIndex].left) : null),
3298
3301
  columns.map((column, columnIndex) => column.fixed === "right" ? renderHeaderTitle(columnIndex, viewport.width - (rightFixedOffsets.get(columnIndex) ?? 0) - metrics[columnIndex].width) : null)
3299
3302
  ] }),
3300
- /* @__PURE__ */ jsx7("div", { className: "rvg-spacer", style: { width: contentWidth, height: contentHeight + bodyTop, marginTop: -effectiveHeight } })
3303
+ /* @__PURE__ */ jsx7("div", { className: "rvg-spacer", style: { width: contentWidth, height: contentHeight + bodyTop, marginTop: -renderHeight } })
3301
3304
  ] }),
3302
3305
  hasSummaryRow && /* @__PURE__ */ jsxs7(
3303
3306
  "div",
@@ -3661,7 +3664,7 @@ function Table({
3661
3664
  rows.length === 0 && !loading && /* @__PURE__ */ jsx7("div", { className: "rvg-empty", style: { top: bodyTop }, children: emptyContent ?? /* @__PURE__ */ jsx7(DefaultEmptyState, { label: labels.empty }) }),
3662
3665
  loading && hasCustomLoading && /* @__PURE__ */ jsx7("div", { className: "rvg-custom-loading", "aria-label": labels.refreshing, children: loadingContent }),
3663
3666
  loading && !hasCustomLoading && !hasCompletedLoadRef.current && /* @__PURE__ */ jsxs7("div", { className: "rvg-initial-loading", style: { top: headerHeight }, "aria-label": labels.initialLoading, children: [
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) => {
3667
+ Array.from({ length: Math.ceil((renderHeight - headerHeight) / rowHeight) }, (_, rowIndex) => /* @__PURE__ */ jsx7("div", { className: "rvg-loading-row", style: { height: rowHeight }, children: columns.map((column, columnIndex) => {
3665
3668
  const left = getDisplayedColumnLeft(columnIndex);
3666
3669
  const columnWidth = metrics[columnIndex].width;
3667
3670
  if (left + columnWidth <= 0 || left >= viewport.width) return null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lensui/lens-table",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "A lightweight, canvas-rendered React table component for LensUI.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",