react-glide-table 2.2.1 → 2.3.0

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/compound.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // src/components/ui/table/components/DataTable/DataTable.tsx
2
2
  import { flexRender as flexRender2 } from "@tanstack/react-table";
3
- import { useMemo as useMemo4 } from "react";
3
+ import { useEffect as useEffect8, useMemo as useMemo4, useState as useState6 } from "react";
4
4
 
5
5
  // src/components/ui/table/components/DataTable/DataTableRow.tsx
6
6
  import { flexRender } from "@tanstack/react-table";
@@ -30,7 +30,9 @@ var DataTableContext = createContext(null);
30
30
  function useDataTableRowContext() {
31
31
  const context = use(DataTableContext);
32
32
  if (!context) {
33
- throw new Error("useDataTableRowContext must be used within a DataTableContextProvider");
33
+ throw new Error(
34
+ "useDataTableRowContext must be used within a DataTableContextProvider"
35
+ );
34
36
  }
35
37
  return context;
36
38
  }
@@ -502,8 +504,105 @@ function flattenHeaderLeaves(column) {
502
504
  }
503
505
 
504
506
  // src/components/ui/table/features/column-resize/columnResize.ts
507
+ function clamp(value, min, max) {
508
+ return Math.min(Math.max(value, min), max);
509
+ }
510
+ function floorOf(column) {
511
+ return column.minWidth ?? 0;
512
+ }
513
+ function ceilOf(column) {
514
+ return column.maxWidth ?? Number.POSITIVE_INFINITY;
515
+ }
516
+ function preferOf(column) {
517
+ const floor = floorOf(column);
518
+ const ceil = ceilOf(column);
519
+ const preferred = column.maxWidth ?? column.minWidth ?? 0;
520
+ return clamp(preferred, floor, Number.isFinite(ceil) ? ceil : preferred);
521
+ }
522
+ function resolveColumnLayoutWidths(containerWidth, columns) {
523
+ const widths = /* @__PURE__ */ new Map();
524
+ const fixed = [];
525
+ const bounded = [];
526
+ let flexCount = 0;
527
+ for (const column of columns) {
528
+ if (column.width != null) {
529
+ fixed.push(column);
530
+ } else if (column.minWidth != null || column.maxWidth != null) {
531
+ bounded.push(column);
532
+ } else {
533
+ flexCount += 1;
534
+ }
535
+ }
536
+ let used = 0;
537
+ for (const column of fixed) {
538
+ let size = column.width;
539
+ if (column.minWidth != null) size = Math.max(size, column.minWidth);
540
+ if (column.maxWidth != null) size = Math.min(size, column.maxWidth);
541
+ widths.set(column.id, size);
542
+ used += size;
543
+ }
544
+ if (bounded.length === 0) {
545
+ return widths;
546
+ }
547
+ const boundedSizes = /* @__PURE__ */ new Map();
548
+ let preferredSum = 0;
549
+ let floorSum = 0;
550
+ for (const column of bounded) {
551
+ const preferred = preferOf(column);
552
+ boundedSizes.set(column.id, preferred);
553
+ preferredSum += preferred;
554
+ floorSum += floorOf(column);
555
+ }
556
+ if (containerWidth > 0) {
557
+ const remaining = Math.max(0, containerWidth - used);
558
+ if (remaining >= preferredSum) {
559
+ } else if (remaining >= floorSum) {
560
+ let deficit = preferredSum - remaining;
561
+ const open = bounded.map((column) => ({
562
+ id: column.id,
563
+ current: boundedSizes.get(column.id),
564
+ floor: floorOf(column)
565
+ }));
566
+ while (deficit >= 1) {
567
+ const shrinkable = open.filter((entry) => entry.current > entry.floor);
568
+ if (shrinkable.length === 0) break;
569
+ const portion = Math.floor(deficit / shrinkable.length);
570
+ const rem = deficit % shrinkable.length;
571
+ let consumed = 0;
572
+ for (let index = 0; index < shrinkable.length; index += 1) {
573
+ const entry = shrinkable[index];
574
+ const reduce = Math.min(
575
+ entry.current - entry.floor,
576
+ portion + (index < rem ? 1 : 0)
577
+ );
578
+ entry.current -= reduce;
579
+ consumed += reduce;
580
+ }
581
+ if (consumed === 0) break;
582
+ deficit -= consumed;
583
+ }
584
+ for (const entry of open) {
585
+ boundedSizes.set(entry.id, entry.current);
586
+ }
587
+ } else {
588
+ for (const column of bounded) {
589
+ boundedSizes.set(column.id, floorOf(column));
590
+ }
591
+ }
592
+ }
593
+ for (const [id, size] of boundedSizes) {
594
+ widths.set(id, Math.round(size));
595
+ }
596
+ return widths;
597
+ }
505
598
  function getColumnSizeStyle(size, options) {
506
- const { force = false, lockMax = false, minWidth, maxWidth } = options ?? {};
599
+ const {
600
+ force = false,
601
+ lockMax = false,
602
+ minWidth,
603
+ maxWidth,
604
+ layoutWidth
605
+ } = options ?? {};
507
606
  if (lockMax) {
508
607
  return {
509
608
  width: size,
@@ -511,14 +610,27 @@ function getColumnSizeStyle(size, options) {
511
610
  maxWidth: size
512
611
  };
513
612
  }
613
+ if (layoutWidth != null) {
614
+ return {
615
+ width: layoutWidth,
616
+ minWidth: layoutWidth,
617
+ maxWidth: layoutWidth
618
+ };
619
+ }
620
+ const resolvedSize = size;
514
621
  const hasExplicitSize = force || size !== DATA_TABLE_COLUMN_SIZE;
515
622
  if (!hasExplicitSize && minWidth == null && maxWidth == null) {
516
623
  return void 0;
517
624
  }
518
625
  const style = {};
519
626
  if (hasExplicitSize) {
520
- style.width = size;
521
- style.minWidth = minWidth ?? size;
627
+ const used = minWidth != null || maxWidth != null ? clamp(
628
+ resolvedSize,
629
+ minWidth ?? Number.NEGATIVE_INFINITY,
630
+ maxWidth ?? Number.POSITIVE_INFINITY
631
+ ) : resolvedSize;
632
+ style.width = used;
633
+ style.minWidth = minWidth ?? used;
522
634
  } else if (minWidth != null) {
523
635
  style.minWidth = minWidth;
524
636
  }
@@ -1168,6 +1280,12 @@ function isInteractiveMouseTarget(target) {
1168
1280
  ].join(",");
1169
1281
  return target.closest(interactiveSelector) !== null;
1170
1282
  }
1283
+ function blurActiveElementOutside(container) {
1284
+ const active = document.activeElement;
1285
+ if (!(active instanceof HTMLElement) || active === document.body) return;
1286
+ if (container instanceof Node && container.contains(active)) return;
1287
+ active.blur();
1288
+ }
1171
1289
  function resolveExpandCellIndex(cells, toggleField) {
1172
1290
  if (!toggleField) return 0;
1173
1291
  const matchedIndex = cells.findIndex(
@@ -1200,7 +1318,7 @@ function DataTableRow({
1200
1318
  columnFreeze,
1201
1319
  inlineSearch
1202
1320
  } = useDataTableRowContext();
1203
- const { enableColumnResize } = columnResize;
1321
+ const { enableColumnResize, layoutWidths } = columnResize;
1204
1322
  const { enableColumnFreeze, offsets: freezeOffsets } = columnFreeze;
1205
1323
  const {
1206
1324
  enabled: enableInlineSearch,
@@ -1395,7 +1513,8 @@ function DataTableRow({
1395
1513
  force: enableColumnResize,
1396
1514
  lockMax: enableColumnResize,
1397
1515
  minWidth: meta?.minWidth,
1398
- maxWidth: meta?.maxWidth
1516
+ maxWidth: meta?.maxWidth,
1517
+ layoutWidth: layoutWidths?.get(columnId)
1399
1518
  });
1400
1519
  const freezeOffset = enableColumnFreeze ? freezeOffsets.get(columnId) : void 0;
1401
1520
  const freezeStyle = getColumnFreezeStyle(freezeOffset);
@@ -1435,6 +1554,7 @@ function DataTableRow({
1435
1554
  if (!enableCellSelection) return;
1436
1555
  if (isInteractiveMouseTarget(event.target)) return;
1437
1556
  event.preventDefault();
1557
+ blurActiveElementOutside(event.currentTarget);
1438
1558
  onCellMouseDown(
1439
1559
  resolveCellRowIndex(event.clientY, event.currentTarget),
1440
1560
  cellIndex,
@@ -1598,6 +1718,7 @@ function DataTableRow({
1598
1718
  onMouseDown: (event) => {
1599
1719
  event.stopPropagation();
1600
1720
  event.preventDefault();
1721
+ blurActiveElementOutside(event.currentTarget);
1601
1722
  onFillHandleMouseDown(rowIndex, cellIndex);
1602
1723
  }
1603
1724
  }
@@ -2529,6 +2650,219 @@ function formatDefaultCellValue(value) {
2529
2650
  import { useCallback as useCallback3, useEffect as useEffect5, useRef as useRef5, useState as useState3 } from "react";
2530
2651
 
2531
2652
  // src/components/ui/table/features/cell-selection/copyData.ts
2653
+ import { isValidElement } from "react";
2654
+ function isReactNodeIterable(node) {
2655
+ return typeof node === "object" && node !== null && !isValidElement(node) && Symbol.iterator in node;
2656
+ }
2657
+ function getElementTypeName(type) {
2658
+ if (typeof type === "string") return type;
2659
+ if (typeof type === "function") {
2660
+ const fn = type;
2661
+ return fn.displayName || fn.name || "";
2662
+ }
2663
+ if (typeof type === "object" && type !== null) {
2664
+ const component = type;
2665
+ return component.displayName || component.render?.displayName || component.render?.name || "";
2666
+ }
2667
+ return "";
2668
+ }
2669
+ function isButtonReactElement(node) {
2670
+ const typeName = getElementTypeName(node.type);
2671
+ if (typeName === "button" || /button/i.test(typeName)) return true;
2672
+ const props = node.props;
2673
+ if (props.role === "button") return true;
2674
+ if (typeName === "input" && props.type === "button") return true;
2675
+ return false;
2676
+ }
2677
+ function isImageReactElement(node) {
2678
+ const typeName = getElementTypeName(node.type);
2679
+ return typeName === "img" || typeName === "image" || /image/i.test(typeName);
2680
+ }
2681
+ var IMAGE_URL_PROP_KEYS = ["src", "url", "href", "imageUrl", "srcUrl"];
2682
+ function isLikelyUrl(value) {
2683
+ const trimmed = value.trim();
2684
+ if (!trimmed) return false;
2685
+ if (/^(https?:|blob:|data:|\/\/)/i.test(trimmed)) return true;
2686
+ if (trimmed.startsWith("/") && trimmed.includes("/")) return true;
2687
+ return false;
2688
+ }
2689
+ function pickUrlFromUnknown(value) {
2690
+ if (typeof value === "string") {
2691
+ return isLikelyUrl(value) ? value.trim() : "";
2692
+ }
2693
+ if (Array.isArray(value)) {
2694
+ return value.map((item) => pickUrlFromUnknown(item)).filter((item) => item.length > 0).join(", ");
2695
+ }
2696
+ if (value && typeof value === "object") {
2697
+ const record = value;
2698
+ for (const key of IMAGE_URL_PROP_KEYS) {
2699
+ const candidate = record[key];
2700
+ if (typeof candidate === "string" && candidate.trim()) {
2701
+ return candidate.trim();
2702
+ }
2703
+ }
2704
+ }
2705
+ return "";
2706
+ }
2707
+ function imageElementText(node) {
2708
+ const props = node.props;
2709
+ for (const key of IMAGE_URL_PROP_KEYS) {
2710
+ const candidate = props[key];
2711
+ if (typeof candidate === "string" && candidate.trim()) {
2712
+ return candidate.trim();
2713
+ }
2714
+ }
2715
+ return "";
2716
+ }
2717
+ function reactNodeContainsImage(node) {
2718
+ if (isValidElement(node)) {
2719
+ if (isImageReactElement(node)) return true;
2720
+ return reactNodeContainsImage(node.props.children);
2721
+ }
2722
+ if (isReactNodeIterable(node)) {
2723
+ for (const child of node) {
2724
+ if (reactNodeContainsImage(child)) return true;
2725
+ }
2726
+ }
2727
+ return false;
2728
+ }
2729
+ function readImgUrl(img) {
2730
+ const attr = img.getAttribute("src")?.trim() ?? "";
2731
+ if (attr) return attr;
2732
+ if (img instanceof HTMLImageElement) {
2733
+ const current = img.currentSrc?.trim() ?? "";
2734
+ if (current && current !== img.baseURI) return current;
2735
+ }
2736
+ return "";
2737
+ }
2738
+ function readDomImageUrls(rowIndex, colIndex, root) {
2739
+ const scope = root ?? (typeof document === "undefined" ? null : document);
2740
+ if (!scope) return "";
2741
+ const cells = scope.querySelectorAll(
2742
+ `[data-row-index="${rowIndex}"][data-col-index="${colIndex}"]`
2743
+ );
2744
+ for (const cell of cells) {
2745
+ const urls = Array.from(cell.querySelectorAll("img")).flatMap((img) => {
2746
+ const url = readImgUrl(img);
2747
+ return url ? [url] : [];
2748
+ });
2749
+ if (urls.length > 0) return urls.join(", ");
2750
+ }
2751
+ return "";
2752
+ }
2753
+ function reactNodeToText(node) {
2754
+ if (node == null || typeof node === "boolean") return "";
2755
+ if (typeof node === "string" || typeof node === "number" || typeof node === "bigint") {
2756
+ return String(node);
2757
+ }
2758
+ if (isReactNodeIterable(node)) {
2759
+ let text = "";
2760
+ for (const child of node) {
2761
+ text += reactNodeToText(child);
2762
+ }
2763
+ return text;
2764
+ }
2765
+ if (isValidElement(node)) {
2766
+ if (isButtonReactElement(node)) return "";
2767
+ const props = node.props;
2768
+ const childText = reactNodeToText(props.children);
2769
+ if (childText) return childText;
2770
+ const fromImage = imageElementText(node);
2771
+ if (fromImage) return fromImage;
2772
+ if (isImageReactElement(node)) return "";
2773
+ if (typeof props.alt === "string" && props.alt) return props.alt;
2774
+ if (typeof props.title === "string" && props.title) return props.title;
2775
+ return "";
2776
+ }
2777
+ return "";
2778
+ }
2779
+ function sanitizeClipboardCell(text) {
2780
+ return text.replace(/\s+/g, " ").trim();
2781
+ }
2782
+ function createCopyRenderRow(rowData, index) {
2783
+ return {
2784
+ id: getOriginalRowId(rowData) || String(index),
2785
+ index,
2786
+ original: rowData,
2787
+ getIsCellDragSelected: () => false
2788
+ };
2789
+ }
2790
+ function buildVisibleRowLookup(visibleRows) {
2791
+ const lookup = /* @__PURE__ */ new Map();
2792
+ for (const row of visibleRows) {
2793
+ lookup.set(row.original, row);
2794
+ }
2795
+ return lookup;
2796
+ }
2797
+ function resolveCopyColumnId(cell) {
2798
+ if (cell.column.id) return cell.column.id;
2799
+ const columnDef = cell.column.columnDef;
2800
+ if (columnDef.id) return columnDef.id;
2801
+ if (columnDef.accessorKey != null && columnDef.accessorKey !== "") {
2802
+ return String(columnDef.accessorKey);
2803
+ }
2804
+ return "";
2805
+ }
2806
+ function isPrimitiveCopyValue(value) {
2807
+ return value == null || typeof value !== "object";
2808
+ }
2809
+ function extractRenderedCopyText(node, value, cellPosition, root) {
2810
+ const rendered = sanitizeClipboardCell(reactNodeToText(node));
2811
+ if (reactNodeContainsImage(node)) {
2812
+ const fromDom = cellPosition != null ? sanitizeClipboardCell(
2813
+ readDomImageUrls(cellPosition.rowIndex, cellPosition.colIndex, root)
2814
+ ) : "";
2815
+ if (fromDom) return fromDom;
2816
+ if (rendered && isLikelyUrl(rendered)) return rendered;
2817
+ return sanitizeClipboardCell(pickUrlFromUnknown(value));
2818
+ }
2819
+ return rendered;
2820
+ }
2821
+ function formatCopyCellText(rowData, columnDef, columnId, visibleRow, fallbackIndex, sourceCell, cellPosition, options) {
2822
+ const meta = columnDef.meta;
2823
+ const value = sourceCell ? sourceCell.getValue() : readRowColumnValue(rowData, columnDef);
2824
+ const cellRender = meta?.cellRender;
2825
+ if (typeof cellRender === "function") {
2826
+ try {
2827
+ const row = visibleRow ?? createCopyRenderRow(rowData, fallbackIndex);
2828
+ const node = cellRender({
2829
+ value,
2830
+ row,
2831
+ index: row.index,
2832
+ columnId,
2833
+ cellProps: meta?.cellProps,
2834
+ update: () => {
2835
+ }
2836
+ });
2837
+ return extractRenderedCopyText(node, value, cellPosition, options?.root);
2838
+ } catch {
2839
+ return formatCellValue(value);
2840
+ }
2841
+ }
2842
+ if (options?.registry && meta?.kind && isPrimitiveCopyValue(value)) {
2843
+ try {
2844
+ const row = visibleRow ?? createCopyRenderRow(rowData, fallbackIndex);
2845
+ const ctx = {
2846
+ value,
2847
+ row,
2848
+ index: row.index,
2849
+ columnId,
2850
+ cellProps: meta.cellProps,
2851
+ update: () => {
2852
+ }
2853
+ };
2854
+ const renderer = resolveCellRenderer(options.registry, meta.kind, ctx);
2855
+ if (renderer) {
2856
+ const node = renderer.render(ctx);
2857
+ const rendered = extractRenderedCopyText(node, value, cellPosition, options.root);
2858
+ if (rendered) return rendered;
2859
+ }
2860
+ } catch {
2861
+ return formatCellValue(value);
2862
+ }
2863
+ }
2864
+ return formatCellValue(value);
2865
+ }
2532
2866
  function formatPrimitive(value) {
2533
2867
  if (value === null || value === void 0) return "";
2534
2868
  if (typeof value === "string") return value;
@@ -2615,37 +2949,47 @@ function collectCopyRowEntries(visibleRows, bounds, mode = "visible") {
2615
2949
  }
2616
2950
  return result;
2617
2951
  }
2618
- function serializeCopyRowsToTSV(copyRows, visibleRows, bounds, depths) {
2952
+ function serializeCopyRowsToTSV(copyRows, visibleRows, bounds, depths, options) {
2619
2953
  if (copyRows.length === 0) return "";
2620
2954
  const { startCol, endCol } = bounds;
2621
2955
  const columnCells = visibleRows[0]?.getVisibleCells().slice(startCol, endCol + 1) ?? [];
2622
2956
  if (columnCells.length === 0) return "";
2623
2957
  const resolvedDepths = depths && depths.length === copyRows.length ? depths : copyRows.map((row) => getRowDepth(row));
2624
2958
  const minDepth = Math.min(...resolvedDepths);
2959
+ const visibleRowByOriginal = buildVisibleRowLookup(visibleRows);
2625
2960
  return copyRows.map((rowData, index) => {
2626
2961
  const relativeDepth = Math.max(0, (resolvedDepths[index] ?? 0) - minDepth);
2627
- const line = columnCells.map(
2628
- (cell) => formatCellValue(
2629
- readRowColumnValue(
2630
- rowData,
2631
- cell.column.columnDef
2632
- )
2633
- )
2634
- ).join(" ");
2962
+ const visibleRow = visibleRowByOriginal.get(rowData);
2963
+ const matchingCells = visibleRow?.getVisibleCells().slice(startCol, endCol + 1);
2964
+ const line = columnCells.map((templateCell, colOffset) => {
2965
+ const sourceCell = matchingCells?.[colOffset];
2966
+ const column = sourceCell?.column ?? templateCell.column;
2967
+ return formatCopyCellText(
2968
+ rowData,
2969
+ column.columnDef,
2970
+ resolveCopyColumnId(sourceCell ?? templateCell),
2971
+ visibleRow,
2972
+ visibleRow?.index ?? index,
2973
+ sourceCell,
2974
+ visibleRow != null ? { rowIndex: visibleRow.index, colIndex: startCol + colOffset } : void 0,
2975
+ options
2976
+ );
2977
+ }).join(" ");
2635
2978
  return `${" ".repeat(relativeDepth)}${line}`;
2636
2979
  }).join("\n");
2637
2980
  }
2638
- function serializeSelectionToTSV(visibleRows, bounds, mode = "visible") {
2981
+ function serializeSelectionToTSV(visibleRows, bounds, mode = "visible", options) {
2639
2982
  const entries = collectCopyRowEntries(visibleRows, bounds, mode);
2640
2983
  return serializeCopyRowsToTSV(
2641
2984
  entries.map((entry) => entry.row),
2642
2985
  visibleRows,
2643
2986
  bounds,
2644
- entries.map((entry) => entry.depth)
2987
+ entries.map((entry) => entry.depth),
2988
+ options
2645
2989
  );
2646
2990
  }
2647
- async function writeSelectionToClipboard(visibleRows, bounds, mode = "visible") {
2648
- const text = serializeSelectionToTSV(visibleRows, bounds, mode);
2991
+ async function writeSelectionToClipboard(visibleRows, bounds, mode = "visible", options) {
2992
+ const text = serializeSelectionToTSV(visibleRows, bounds, mode, options);
2649
2993
  if (!text) return false;
2650
2994
  try {
2651
2995
  await navigator.clipboard.writeText(text);
@@ -2803,7 +3147,9 @@ function useCellSelection({
2803
3147
  onDataChange,
2804
3148
  onBatchChange,
2805
3149
  onRowsPaste,
2806
- onCellNavigate
3150
+ onCellNavigate,
3151
+ cellRendererRegistry,
3152
+ rootRef
2807
3153
  }) {
2808
3154
  const [dragState, setDragState] = useState3(INITIAL_DRAG_STATE);
2809
3155
  const pendingPasteModeRef = useRef5(null);
@@ -2927,15 +3273,28 @@ function useCellSelection({
2927
3273
  async (options) => {
2928
3274
  if (!enabled || !activeSelectionBounds) return false;
2929
3275
  const mode = options?.includeDescendants && enableSubtreeCopy ? "subtree" : "visible";
2930
- return writeSelectionToClipboard(rows, activeSelectionBounds, mode);
3276
+ return writeSelectionToClipboard(rows, activeSelectionBounds, mode, {
3277
+ registry: cellRendererRegistry,
3278
+ root: rootRef?.current
3279
+ });
2931
3280
  },
2932
- [activeSelectionBounds, enableSubtreeCopy, enabled, rows]
3281
+ [
3282
+ activeSelectionBounds,
3283
+ cellRendererRegistry,
3284
+ enableSubtreeCopy,
3285
+ enabled,
3286
+ rootRef,
3287
+ rows
3288
+ ]
2933
3289
  );
2934
3290
  useEffect5(() => {
2935
3291
  if (!enabled) return;
2936
3292
  const handleKeyDown = (e) => {
2937
3293
  if (!activeSelectionBounds) return;
2938
3294
  if (!(e.ctrlKey || e.metaKey)) return;
3295
+ if (isEditablePasteTarget(e.target) || isEditablePasteTarget(document.activeElement)) {
3296
+ return;
3297
+ }
2939
3298
  const isSubtreeShortcut = enableSubtreeCopy && e.shiftKey && e.key.toLowerCase() === "c";
2940
3299
  const isVisibleCopyShortcut = !e.shiftKey && e.key.toLowerCase() === "c";
2941
3300
  if (!isSubtreeShortcut && !isVisibleCopyShortcut) return;
@@ -3498,6 +3857,10 @@ function useGlideTable(options) {
3498
3857
  const [hoveredRowIndex, setHoveredRowIndex] = useState5(null);
3499
3858
  const scrollRef = useRef7(null);
3500
3859
  const rootRef = useRef7(null);
3860
+ const cellRendererRegistry = useMemo3(
3861
+ () => createCellRendererRegistry(cellRenderers),
3862
+ [cellRenderers]
3863
+ );
3501
3864
  const shouldVirtualize = enableVirtualization && !enableRowSpan;
3502
3865
  useEffect7(() => {
3503
3866
  if (enableVirtualization && enableRowSpan) {
@@ -3681,7 +4044,9 @@ function useGlideTable(options) {
3681
4044
  onDataChange,
3682
4045
  onBatchChange,
3683
4046
  onRowsPaste,
3684
- onCellNavigate: handleCellNavigate
4047
+ onCellNavigate: handleCellNavigate,
4048
+ cellRendererRegistry,
4049
+ rootRef
3685
4050
  });
3686
4051
  const {
3687
4052
  editingCell,
@@ -3691,10 +4056,6 @@ function useGlideTable(options) {
3691
4056
  commitEdit,
3692
4057
  cancelEdit
3693
4058
  } = useCellEdit({ data: tableData, rows, onDataChange, onCellChange });
3694
- const cellRendererRegistry = useMemo3(
3695
- () => createCellRendererRegistry(cellRenderers),
3696
- [cellRenderers]
3697
- );
3698
4059
  const commitRenderedCellValue = useCallback5(
3699
4060
  (rowId, columnId, value) => commitCellValue({
3700
4061
  data: tableData,
@@ -4152,17 +4513,74 @@ function DataTable({
4152
4513
  const RowSlot = slots?.Row ?? DataTableRow;
4153
4514
  const PendingSlot = slots?.Pending ?? DefaultPending;
4154
4515
  const EmptySlot = slots?.Empty ?? DefaultEmpty;
4155
- const freezeOffsets = rowContextValue.columnFreeze.offsets;
4156
4516
  const headerGroups = getMergedHeaderGroups(table.getHeaderGroups());
4157
4517
  const leafColumnIds = table.getVisibleLeafColumns().map((column) => column.id);
4518
+ const columnLayoutMetaSignature = table.getVisibleLeafColumns().map((column) => {
4519
+ const meta = column.columnDef.meta;
4520
+ return `${column.id}:${meta?.width ?? ""}:${meta?.minWidth ?? ""}:${meta?.maxWidth ?? ""}`;
4521
+ }).join("|");
4158
4522
  const { isReordering, draggingColumnId, dropTarget, onHeaderPointerDown } = useColumnReorder({
4159
4523
  enabled: enableColumnReorder,
4160
4524
  columnOrder: leafColumnIds,
4161
4525
  onColumnOrderChange: setColumnOrder
4162
4526
  });
4527
+ const [containerWidth, setContainerWidth] = useState6(0);
4528
+ useEffect8(() => {
4529
+ if (enableColumnResize || isPending) return;
4530
+ const element = scrollRef.current;
4531
+ if (!element) return;
4532
+ const updateWidth = () => {
4533
+ setContainerWidth(Math.floor(element.clientWidth));
4534
+ };
4535
+ updateWidth();
4536
+ if (typeof ResizeObserver === "undefined") return;
4537
+ const observer = new ResizeObserver(() => {
4538
+ updateWidth();
4539
+ });
4540
+ observer.observe(element);
4541
+ return () => observer.disconnect();
4542
+ }, [enableColumnResize, isPending, scrollRef, rows.length, leafColumnIds.join("|")]);
4543
+ const layoutWidths = useMemo4(() => {
4544
+ if (enableColumnResize) return void 0;
4545
+ const columns = table.getVisibleLeafColumns().map((column) => ({
4546
+ id: column.id,
4547
+ width: column.columnDef.meta?.width,
4548
+ minWidth: column.columnDef.meta?.minWidth,
4549
+ maxWidth: column.columnDef.meta?.maxWidth
4550
+ }));
4551
+ return resolveColumnLayoutWidths(containerWidth, columns);
4552
+ }, [enableColumnResize, containerWidth, table, columnLayoutMetaSignature]);
4553
+ const freezeOffsets = useMemo4(() => {
4554
+ if (!enableColumnFreeze || enableColumnResize || !layoutWidths) {
4555
+ return rowContextValue.columnFreeze.offsets;
4556
+ }
4557
+ const columns = table.getVisibleLeafColumns().map((column) => ({
4558
+ id: column.id,
4559
+ size: layoutWidths.get(column.id) ?? column.getSize(),
4560
+ side: resolveColumnFreezeSide(column.columnDef.meta?.frozen)
4561
+ }));
4562
+ return buildColumnFreezeOffsets(columns);
4563
+ }, [
4564
+ enableColumnFreeze,
4565
+ enableColumnResize,
4566
+ layoutWidths,
4567
+ rowContextValue.columnFreeze.offsets,
4568
+ table
4569
+ ]);
4163
4570
  const contextValue = useMemo4(
4164
- () => ({ ...rowContextValue, classNames }),
4165
- [rowContextValue, classNames]
4571
+ () => ({
4572
+ ...rowContextValue,
4573
+ classNames,
4574
+ columnFreeze: {
4575
+ ...rowContextValue.columnFreeze,
4576
+ offsets: freezeOffsets
4577
+ },
4578
+ columnResize: {
4579
+ ...rowContextValue.columnResize,
4580
+ layoutWidths
4581
+ }
4582
+ }),
4583
+ [rowContextValue, classNames, freezeOffsets, layoutWidths]
4166
4584
  );
4167
4585
  if (isPending) {
4168
4586
  return /* @__PURE__ */ jsx7(
@@ -4243,7 +4661,8 @@ function DataTable({
4243
4661
  force: enableColumnResize,
4244
4662
  lockMax: enableColumnResize,
4245
4663
  minWidth: header.column.columnDef.meta?.minWidth,
4246
- maxWidth: header.column.columnDef.meta?.maxWidth
4664
+ maxWidth: header.column.columnDef.meta?.maxWidth,
4665
+ layoutWidth: layoutWidths?.get(header.column.id)
4247
4666
  });
4248
4667
  const freezeOffset = enableColumnFreeze ? resolveHeaderFreezeOffset(header.column, freezeOffsets) : void 0;
4249
4668
  const freezeStyle = getColumnFreezeStyle(freezeOffset, {
@@ -4256,7 +4675,9 @@ function DataTable({
4256
4675
  };
4257
4676
  const isPlaceholder = header.isPlaceholder;
4258
4677
  const leafColumns = header.column.getLeafColumns();
4259
- const leafIds = leafColumns.map((leafColumn) => leafColumn.id);
4678
+ const leafIds = leafColumns.map(
4679
+ (leafColumn) => leafColumn.id
4680
+ );
4260
4681
  const isLeafHeader = !isPlaceholder && header.subHeaders.length === 0;
4261
4682
  const canDrag = enableColumnReorder && !isPlaceholder && leafIds.length > 0 && leafColumns.every(
4262
4683
  (leafColumn) => isColumnReorderable(leafColumn.columnDef.meta)
@@ -4412,7 +4833,7 @@ function DataTable({
4412
4833
  }
4413
4834
 
4414
4835
  // src/components/ui/table/components/Table/Table.tsx
4415
- import { useCallback as useCallback7, useMemo as useMemo5, useState as useState6 } from "react";
4836
+ import { useCallback as useCallback7, useMemo as useMemo5, useState as useState7 } from "react";
4416
4837
 
4417
4838
  // src/components/ui/table/features/cell-render/ResolvedTableCell.tsx
4418
4839
  import { useCallback as useCallback6 } from "react";
@@ -4535,6 +4956,7 @@ function buildColumnDef(props, sort, onSort) {
4535
4956
  cellRender: render,
4536
4957
  frozen,
4537
4958
  reorderable,
4959
+ width,
4538
4960
  minWidth,
4539
4961
  maxWidth,
4540
4962
  className,
@@ -4582,10 +5004,10 @@ function countLeafColumns(nodes) {
4582
5004
  }
4583
5005
 
4584
5006
  // src/components/ui/table/components/Table/parseTableChildren.ts
4585
- import { Children, isValidElement as isValidElement2 } from "react";
5007
+ import { Children, isValidElement as isValidElement3 } from "react";
4586
5008
 
4587
5009
  // src/components/ui/table/components/Table/tableChildTypes.ts
4588
- import { isValidElement } from "react";
5010
+ import { isValidElement as isValidElement2 } from "react";
4589
5011
  var TABLE_HEADER_DISPLAY_NAME = "Table.Header";
4590
5012
  var TABLE_BODY_DISPLAY_NAME = "Table.Body";
4591
5013
  var TABLE_COLUMN_DISPLAY_NAME = "Table.Column";
@@ -4598,19 +5020,19 @@ function getComponentDisplayName(type) {
4598
5020
  return void 0;
4599
5021
  }
4600
5022
  function isTableHeaderElement(child) {
4601
- return isValidElement(child) && getComponentDisplayName(child.type) === TABLE_HEADER_DISPLAY_NAME;
5023
+ return isValidElement2(child) && getComponentDisplayName(child.type) === TABLE_HEADER_DISPLAY_NAME;
4602
5024
  }
4603
5025
  function isTableBodyElement(child) {
4604
- return isValidElement(child) && getComponentDisplayName(child.type) === TABLE_BODY_DISPLAY_NAME;
5026
+ return isValidElement2(child) && getComponentDisplayName(child.type) === TABLE_BODY_DISPLAY_NAME;
4605
5027
  }
4606
5028
  function isTableColumnElement(child) {
4607
- return isValidElement(child) && getComponentDisplayName(child.type) === TABLE_COLUMN_DISPLAY_NAME;
5029
+ return isValidElement2(child) && getComponentDisplayName(child.type) === TABLE_COLUMN_DISPLAY_NAME;
4608
5030
  }
4609
5031
  function isTableColumnGroupElement(child) {
4610
- return isValidElement(child) && getComponentDisplayName(child.type) === TABLE_COLUMN_GROUP_DISPLAY_NAME;
5032
+ return isValidElement2(child) && getComponentDisplayName(child.type) === TABLE_COLUMN_GROUP_DISPLAY_NAME;
4611
5033
  }
4612
5034
  function isTablePaginationElement(child) {
4613
- return isValidElement(child) && getComponentDisplayName(child.type) === TABLE_PAGINATION_DISPLAY_NAME;
5035
+ return isValidElement2(child) && getComponentDisplayName(child.type) === TABLE_PAGINATION_DISPLAY_NAME;
4614
5036
  }
4615
5037
 
4616
5038
  // src/components/ui/table/components/Table/parseTableChildren.ts
@@ -4654,7 +5076,7 @@ function walkColumnTreeNodes(children) {
4654
5076
  });
4655
5077
  continue;
4656
5078
  }
4657
- if (isValidElement2(child)) {
5079
+ if (isValidElement3(child)) {
4658
5080
  const nested = child.props.children;
4659
5081
  if (nested != null) {
4660
5082
  result.push(...walkColumnTreeNodes(nested));
@@ -4784,7 +5206,7 @@ function TableRoot({
4784
5206
  () => parseTableChildren(children),
4785
5207
  [children]
4786
5208
  );
4787
- const [sort, setSort] = useState6(null);
5209
+ const [sort, setSort] = useState7(null);
4788
5210
  const handleSort = useCallback7((field) => {
4789
5211
  setSort((previous) => {
4790
5212
  if (previous?.field !== field) {