@lensui/lens-table 0.1.7 → 0.1.9

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
@@ -1622,6 +1622,7 @@ function TableInner({
1622
1622
  const customContextMenuConfig = typeof contextMenuConfig === "object" ? contextMenuConfig : void 0;
1623
1623
  const [resizedColumnWidths, setResizedColumnWidths] = (0, import_react5.useState)({});
1624
1624
  const leafSourceColumns = (0, import_react5.useMemo)(() => flattenDataColumns(sourceColumns), [sourceColumns]);
1625
+ const sourceColumnWidthsRef = (0, import_react5.useRef)(new Map(leafSourceColumns.map((column) => [column.key, column.width])));
1625
1626
  const showRowCheckbox = Boolean(rowSelection) && (typeof rowSelection !== "object" || rowSelection.showCheckbox !== false);
1626
1627
  (0, import_react5.useEffect)(() => {
1627
1628
  if (!isProductionRuntime() && hasNestedFixedColumns(sourceColumns)) {
@@ -1697,7 +1698,8 @@ function TableInner({
1697
1698
  const hoveredRowIndexRef = (0, import_react5.useRef)(null);
1698
1699
  const [viewport, setViewport] = (0, import_react5.useState)({ width: 0, height: typeof height === "number" ? height : FALLBACK_HEIGHT });
1699
1700
  const [horizontalScrollbarHeight, setHorizontalScrollbarHeight] = (0, import_react5.useState)(0);
1700
- const resolvedHeight = typeof height === "number" ? height : viewport.height || FALLBACK_HEIGHT;
1701
+ const [availableHeight, setAvailableHeight] = (0, import_react5.useState)(FALLBACK_HEIGHT);
1702
+ const resolvedHeight = typeof height === "number" ? height : availableHeight;
1701
1703
  const [scrollPosition, setScrollPosition] = (0, import_react5.useState)({ left: 0, top: 0 });
1702
1704
  const scrollRef = (0, import_react5.useRef)({ left: 0, top: 0 });
1703
1705
  const [rowKeys, setRowKeys] = useControllableKeys(selectedRowKeys, defaultSelectedRowKeys, (keys) => {
@@ -1734,6 +1736,9 @@ function TableInner({
1734
1736
  setSelectionRange(null);
1735
1737
  }, [rangeSelection]);
1736
1738
  (0, import_react5.useEffect)(() => {
1739
+ const previousSourceWidths = sourceColumnWidthsRef.current;
1740
+ const nextSourceWidths = new Map(leafSourceColumns.map((column) => [column.key, column.width]));
1741
+ sourceColumnWidthsRef.current = nextSourceWidths;
1737
1742
  setResizedColumnWidths((current) => {
1738
1743
  const sourceColumnByKey = new Map(leafSourceColumns.map((column) => [column.key, column]));
1739
1744
  let changed = false;
@@ -1744,7 +1749,8 @@ function TableInner({
1744
1749
  changed = true;
1745
1750
  return;
1746
1751
  }
1747
- if (sourceColumn.width !== void 0 && sourceColumn.width !== value) {
1752
+ const sourceWidthChanged = previousSourceWidths.get(key) !== sourceColumn.width;
1753
+ if (sourceWidthChanged && sourceColumn.width !== void 0 && sourceColumn.width !== value) {
1748
1754
  changed = true;
1749
1755
  return;
1750
1756
  }
@@ -1981,7 +1987,11 @@ function TableInner({
1981
1987
  if (selection?.rowKey === editing.rowKey && selection.columnKey === editing.columnKey) return;
1982
1988
  setEditing(null);
1983
1989
  }, [editing, selection]);
1984
- const metrics = (0, import_react5.useMemo)(() => buildColumnMetrics(columns, { columnDraggable, viewportWidth: viewport.width }), [columnDraggable, columns, viewport.width]);
1990
+ const hasManualColumnWidths = Object.keys(resizedColumnWidths).length > 0;
1991
+ const metrics = (0, import_react5.useMemo)(() => buildColumnMetrics(columns, {
1992
+ columnDraggable,
1993
+ viewportWidth: hasManualColumnWidths ? 0 : viewport.width
1994
+ }), [columnDraggable, columns, hasManualColumnWidths, viewport.width]);
1985
1995
  const contentWidth = metrics.length > 0 ? metrics[metrics.length - 1].right : 0;
1986
1996
  const contentHeight = rows.length * rowHeight;
1987
1997
  const fixedWidth = (0, import_react5.useMemo)(() => columns.reduce((width2, column, index) => column.fixed === "left" ? width2 + metrics[index].width : width2, 0), [columns, metrics]);
@@ -2366,7 +2376,15 @@ function TableInner({
2366
2376
  (0, import_react5.useLayoutEffect)(() => {
2367
2377
  const element = scrollerRef.current;
2368
2378
  if (!element) return;
2379
+ const root = element.parentElement;
2369
2380
  const update = () => {
2381
+ if (root && typeof height !== "number") {
2382
+ const renderedHeight = root.style.height;
2383
+ root.style.height = height;
2384
+ const nextAvailableHeight = root.clientHeight || FALLBACK_HEIGHT;
2385
+ root.style.height = renderedHeight;
2386
+ setAvailableHeight(nextAvailableHeight);
2387
+ }
2370
2388
  const measuredHeight = element.clientHeight || (typeof height === "number" ? height : FALLBACK_HEIGHT);
2371
2389
  setViewport({ width: element.clientWidth, height: measuredHeight });
2372
2390
  setHorizontalScrollbarHeight(Math.max(0, element.offsetHeight - element.clientHeight));
@@ -2378,6 +2396,7 @@ function TableInner({
2378
2396
  }
2379
2397
  const observer = new ResizeObserver(update);
2380
2398
  observer.observe(element);
2399
+ if (root?.parentElement) observer.observe(root.parentElement);
2381
2400
  return () => observer.disconnect();
2382
2401
  }, [height]);
2383
2402
  (0, import_react5.useEffect)(() => {
@@ -2485,7 +2504,8 @@ function TableInner({
2485
2504
  const horizontalThumb = horizontalScrollbarThumbRef.current;
2486
2505
  if (!scroller || !verticalTrack || !verticalThumb || !horizontalTrack || !horizontalThumb) return;
2487
2506
  const maxScrollTop = scroller.scrollHeight - scroller.clientHeight;
2488
- if (maxScrollTop <= 1 || renderHeight <= 0) {
2507
+ const contentFitsAutoHeight = autoHeight && effectiveHeight >= realContentHeight - 1;
2508
+ if (contentFitsAutoHeight || maxScrollTop <= 1 || renderHeight <= 0) {
2489
2509
  verticalTrack.style.display = "none";
2490
2510
  } else {
2491
2511
  const top = fixedHeader ? bodyTop : 0;
@@ -2525,7 +2545,7 @@ function TableInner({
2525
2545
  horizontalTrack.style.bottom = `${bottomSummaryHeight + 2}px`;
2526
2546
  horizontalThumb.style.width = `${Math.min(trackWidth, thumbWidth)}px`;
2527
2547
  horizontalThumb.style.transform = `translateX(${thumbLeft}px)`;
2528
- }, [bodyTop, bottomSummaryHeight, effectiveHeight, fixedHeader, fixedWidth, renderHeight, rightFixedWidth, viewport.width]);
2548
+ }, [autoHeight, bodyTop, bottomSummaryHeight, effectiveHeight, fixedHeader, fixedWidth, realContentHeight, renderHeight, rightFixedWidth, viewport.width]);
2529
2549
  (0, import_react5.useLayoutEffect)(() => {
2530
2550
  updateCustomScrollbars();
2531
2551
  }, [contentHeight, contentWidth, updateCustomScrollbars, viewport.height, viewport.width]);
@@ -3578,6 +3598,18 @@ function TableInner({
3578
3598
  const { cell: resizeCell, edge: resizeEdge } = resizeHit;
3579
3599
  event.preventDefault();
3580
3600
  event.currentTarget.setPointerCapture(event.pointerId);
3601
+ setResizedColumnWidths((current) => {
3602
+ let changed = false;
3603
+ const next = { ...current };
3604
+ columns.forEach((column, index) => {
3605
+ if (column.rowSelection || column.rowDragHandle || column.rowNumber) return;
3606
+ const displayedWidth = metrics[index]?.width;
3607
+ if (displayedWidth === void 0 || next[column.key] === displayedWidth) return;
3608
+ next[column.key] = displayedWidth;
3609
+ changed = true;
3610
+ });
3611
+ return changed ? next : current;
3612
+ });
3581
3613
  const resizeIndex = resizeCell.endIndex;
3582
3614
  const resizeIndices = resizeCell.leaf ? [resizeIndex] : Array.from({ length: resizeCell.endIndex - resizeCell.startIndex + 1 }, (_, index) => resizeCell.startIndex + index);
3583
3615
  const startWidths = resizeIndices.map((index) => metrics[index].width);
@@ -3610,7 +3642,7 @@ function TableInner({
3610
3642
  const setGuideFromWidths = (nextWidths) => {
3611
3643
  const widthByIndex = new Map(drag.resizeIndices.map((columnIndex, index) => [columnIndex, nextWidths[index]]));
3612
3644
  const nextColumns = columns.map((column2, index) => widthByIndex.has(index) ? { ...column2, width: widthByIndex.get(index) } : column2);
3613
- const nextMetrics = buildColumnMetrics(nextColumns, { columnDraggable, viewportWidth: viewport.width });
3645
+ const nextMetrics = buildColumnMetrics(nextColumns, { columnDraggable, viewportWidth: 0 });
3614
3646
  setResizeGuideX(getHeaderCellEdgeFromMetrics(drag.resizeStartIndex, drag.resizeEndIndex, drag.resizeEdge, nextMetrics));
3615
3647
  };
3616
3648
  if (drag.resizeIndices.length > 1) {
package/dist/index.js CHANGED
@@ -1592,6 +1592,7 @@ function TableInner({
1592
1592
  const customContextMenuConfig = typeof contextMenuConfig === "object" ? contextMenuConfig : void 0;
1593
1593
  const [resizedColumnWidths, setResizedColumnWidths] = useState4({});
1594
1594
  const leafSourceColumns = useMemo(() => flattenDataColumns(sourceColumns), [sourceColumns]);
1595
+ const sourceColumnWidthsRef = useRef2(new Map(leafSourceColumns.map((column) => [column.key, column.width])));
1595
1596
  const showRowCheckbox = Boolean(rowSelection) && (typeof rowSelection !== "object" || rowSelection.showCheckbox !== false);
1596
1597
  useEffect2(() => {
1597
1598
  if (!isProductionRuntime() && hasNestedFixedColumns(sourceColumns)) {
@@ -1667,7 +1668,8 @@ function TableInner({
1667
1668
  const hoveredRowIndexRef = useRef2(null);
1668
1669
  const [viewport, setViewport] = useState4({ width: 0, height: typeof height === "number" ? height : FALLBACK_HEIGHT });
1669
1670
  const [horizontalScrollbarHeight, setHorizontalScrollbarHeight] = useState4(0);
1670
- const resolvedHeight = typeof height === "number" ? height : viewport.height || FALLBACK_HEIGHT;
1671
+ const [availableHeight, setAvailableHeight] = useState4(FALLBACK_HEIGHT);
1672
+ const resolvedHeight = typeof height === "number" ? height : availableHeight;
1671
1673
  const [scrollPosition, setScrollPosition] = useState4({ left: 0, top: 0 });
1672
1674
  const scrollRef = useRef2({ left: 0, top: 0 });
1673
1675
  const [rowKeys, setRowKeys] = useControllableKeys(selectedRowKeys, defaultSelectedRowKeys, (keys) => {
@@ -1704,6 +1706,9 @@ function TableInner({
1704
1706
  setSelectionRange(null);
1705
1707
  }, [rangeSelection]);
1706
1708
  useEffect2(() => {
1709
+ const previousSourceWidths = sourceColumnWidthsRef.current;
1710
+ const nextSourceWidths = new Map(leafSourceColumns.map((column) => [column.key, column.width]));
1711
+ sourceColumnWidthsRef.current = nextSourceWidths;
1707
1712
  setResizedColumnWidths((current) => {
1708
1713
  const sourceColumnByKey = new Map(leafSourceColumns.map((column) => [column.key, column]));
1709
1714
  let changed = false;
@@ -1714,7 +1719,8 @@ function TableInner({
1714
1719
  changed = true;
1715
1720
  return;
1716
1721
  }
1717
- if (sourceColumn.width !== void 0 && sourceColumn.width !== value) {
1722
+ const sourceWidthChanged = previousSourceWidths.get(key) !== sourceColumn.width;
1723
+ if (sourceWidthChanged && sourceColumn.width !== void 0 && sourceColumn.width !== value) {
1718
1724
  changed = true;
1719
1725
  return;
1720
1726
  }
@@ -1951,7 +1957,11 @@ function TableInner({
1951
1957
  if (selection?.rowKey === editing.rowKey && selection.columnKey === editing.columnKey) return;
1952
1958
  setEditing(null);
1953
1959
  }, [editing, selection]);
1954
- const metrics = useMemo(() => buildColumnMetrics(columns, { columnDraggable, viewportWidth: viewport.width }), [columnDraggable, columns, viewport.width]);
1960
+ const hasManualColumnWidths = Object.keys(resizedColumnWidths).length > 0;
1961
+ const metrics = useMemo(() => buildColumnMetrics(columns, {
1962
+ columnDraggable,
1963
+ viewportWidth: hasManualColumnWidths ? 0 : viewport.width
1964
+ }), [columnDraggable, columns, hasManualColumnWidths, viewport.width]);
1955
1965
  const contentWidth = metrics.length > 0 ? metrics[metrics.length - 1].right : 0;
1956
1966
  const contentHeight = rows.length * rowHeight;
1957
1967
  const fixedWidth = useMemo(() => columns.reduce((width2, column, index) => column.fixed === "left" ? width2 + metrics[index].width : width2, 0), [columns, metrics]);
@@ -2336,7 +2346,15 @@ function TableInner({
2336
2346
  useLayoutEffect2(() => {
2337
2347
  const element = scrollerRef.current;
2338
2348
  if (!element) return;
2349
+ const root = element.parentElement;
2339
2350
  const update = () => {
2351
+ if (root && typeof height !== "number") {
2352
+ const renderedHeight = root.style.height;
2353
+ root.style.height = height;
2354
+ const nextAvailableHeight = root.clientHeight || FALLBACK_HEIGHT;
2355
+ root.style.height = renderedHeight;
2356
+ setAvailableHeight(nextAvailableHeight);
2357
+ }
2340
2358
  const measuredHeight = element.clientHeight || (typeof height === "number" ? height : FALLBACK_HEIGHT);
2341
2359
  setViewport({ width: element.clientWidth, height: measuredHeight });
2342
2360
  setHorizontalScrollbarHeight(Math.max(0, element.offsetHeight - element.clientHeight));
@@ -2348,6 +2366,7 @@ function TableInner({
2348
2366
  }
2349
2367
  const observer = new ResizeObserver(update);
2350
2368
  observer.observe(element);
2369
+ if (root?.parentElement) observer.observe(root.parentElement);
2351
2370
  return () => observer.disconnect();
2352
2371
  }, [height]);
2353
2372
  useEffect2(() => {
@@ -2455,7 +2474,8 @@ function TableInner({
2455
2474
  const horizontalThumb = horizontalScrollbarThumbRef.current;
2456
2475
  if (!scroller || !verticalTrack || !verticalThumb || !horizontalTrack || !horizontalThumb) return;
2457
2476
  const maxScrollTop = scroller.scrollHeight - scroller.clientHeight;
2458
- if (maxScrollTop <= 1 || renderHeight <= 0) {
2477
+ const contentFitsAutoHeight = autoHeight && effectiveHeight >= realContentHeight - 1;
2478
+ if (contentFitsAutoHeight || maxScrollTop <= 1 || renderHeight <= 0) {
2459
2479
  verticalTrack.style.display = "none";
2460
2480
  } else {
2461
2481
  const top = fixedHeader ? bodyTop : 0;
@@ -2495,7 +2515,7 @@ function TableInner({
2495
2515
  horizontalTrack.style.bottom = `${bottomSummaryHeight + 2}px`;
2496
2516
  horizontalThumb.style.width = `${Math.min(trackWidth, thumbWidth)}px`;
2497
2517
  horizontalThumb.style.transform = `translateX(${thumbLeft}px)`;
2498
- }, [bodyTop, bottomSummaryHeight, effectiveHeight, fixedHeader, fixedWidth, renderHeight, rightFixedWidth, viewport.width]);
2518
+ }, [autoHeight, bodyTop, bottomSummaryHeight, effectiveHeight, fixedHeader, fixedWidth, realContentHeight, renderHeight, rightFixedWidth, viewport.width]);
2499
2519
  useLayoutEffect2(() => {
2500
2520
  updateCustomScrollbars();
2501
2521
  }, [contentHeight, contentWidth, updateCustomScrollbars, viewport.height, viewport.width]);
@@ -3548,6 +3568,18 @@ function TableInner({
3548
3568
  const { cell: resizeCell, edge: resizeEdge } = resizeHit;
3549
3569
  event.preventDefault();
3550
3570
  event.currentTarget.setPointerCapture(event.pointerId);
3571
+ setResizedColumnWidths((current) => {
3572
+ let changed = false;
3573
+ const next = { ...current };
3574
+ columns.forEach((column, index) => {
3575
+ if (column.rowSelection || column.rowDragHandle || column.rowNumber) return;
3576
+ const displayedWidth = metrics[index]?.width;
3577
+ if (displayedWidth === void 0 || next[column.key] === displayedWidth) return;
3578
+ next[column.key] = displayedWidth;
3579
+ changed = true;
3580
+ });
3581
+ return changed ? next : current;
3582
+ });
3551
3583
  const resizeIndex = resizeCell.endIndex;
3552
3584
  const resizeIndices = resizeCell.leaf ? [resizeIndex] : Array.from({ length: resizeCell.endIndex - resizeCell.startIndex + 1 }, (_, index) => resizeCell.startIndex + index);
3553
3585
  const startWidths = resizeIndices.map((index) => metrics[index].width);
@@ -3580,7 +3612,7 @@ function TableInner({
3580
3612
  const setGuideFromWidths = (nextWidths) => {
3581
3613
  const widthByIndex = new Map(drag.resizeIndices.map((columnIndex, index) => [columnIndex, nextWidths[index]]));
3582
3614
  const nextColumns = columns.map((column2, index) => widthByIndex.has(index) ? { ...column2, width: widthByIndex.get(index) } : column2);
3583
- const nextMetrics = buildColumnMetrics(nextColumns, { columnDraggable, viewportWidth: viewport.width });
3615
+ const nextMetrics = buildColumnMetrics(nextColumns, { columnDraggable, viewportWidth: 0 });
3584
3616
  setResizeGuideX(getHeaderCellEdgeFromMetrics(drag.resizeStartIndex, drag.resizeEndIndex, drag.resizeEdge, nextMetrics));
3585
3617
  };
3586
3618
  if (drag.resizeIndices.length > 1) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lensui/lens-table",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
4
  "description": "A lightweight, canvas-rendered React table component for LensUI.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",