react-glide-table 2.2.0 → 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/index.js CHANGED
@@ -750,6 +750,219 @@ function hasCellSelectionEdges(style) {
750
750
  }
751
751
 
752
752
  // src/components/ui/table/features/cell-selection/copyData.ts
753
+ import { isValidElement } from "react";
754
+ function isReactNodeIterable(node) {
755
+ return typeof node === "object" && node !== null && !isValidElement(node) && Symbol.iterator in node;
756
+ }
757
+ function getElementTypeName(type) {
758
+ if (typeof type === "string") return type;
759
+ if (typeof type === "function") {
760
+ const fn = type;
761
+ return fn.displayName || fn.name || "";
762
+ }
763
+ if (typeof type === "object" && type !== null) {
764
+ const component = type;
765
+ return component.displayName || component.render?.displayName || component.render?.name || "";
766
+ }
767
+ return "";
768
+ }
769
+ function isButtonReactElement(node) {
770
+ const typeName = getElementTypeName(node.type);
771
+ if (typeName === "button" || /button/i.test(typeName)) return true;
772
+ const props = node.props;
773
+ if (props.role === "button") return true;
774
+ if (typeName === "input" && props.type === "button") return true;
775
+ return false;
776
+ }
777
+ function isImageReactElement(node) {
778
+ const typeName = getElementTypeName(node.type);
779
+ return typeName === "img" || typeName === "image" || /image/i.test(typeName);
780
+ }
781
+ var IMAGE_URL_PROP_KEYS = ["src", "url", "href", "imageUrl", "srcUrl"];
782
+ function isLikelyUrl(value) {
783
+ const trimmed = value.trim();
784
+ if (!trimmed) return false;
785
+ if (/^(https?:|blob:|data:|\/\/)/i.test(trimmed)) return true;
786
+ if (trimmed.startsWith("/") && trimmed.includes("/")) return true;
787
+ return false;
788
+ }
789
+ function pickUrlFromUnknown(value) {
790
+ if (typeof value === "string") {
791
+ return isLikelyUrl(value) ? value.trim() : "";
792
+ }
793
+ if (Array.isArray(value)) {
794
+ return value.map((item) => pickUrlFromUnknown(item)).filter((item) => item.length > 0).join(", ");
795
+ }
796
+ if (value && typeof value === "object") {
797
+ const record = value;
798
+ for (const key of IMAGE_URL_PROP_KEYS) {
799
+ const candidate = record[key];
800
+ if (typeof candidate === "string" && candidate.trim()) {
801
+ return candidate.trim();
802
+ }
803
+ }
804
+ }
805
+ return "";
806
+ }
807
+ function imageElementText(node) {
808
+ const props = node.props;
809
+ for (const key of IMAGE_URL_PROP_KEYS) {
810
+ const candidate = props[key];
811
+ if (typeof candidate === "string" && candidate.trim()) {
812
+ return candidate.trim();
813
+ }
814
+ }
815
+ return "";
816
+ }
817
+ function reactNodeContainsImage(node) {
818
+ if (isValidElement(node)) {
819
+ if (isImageReactElement(node)) return true;
820
+ return reactNodeContainsImage(node.props.children);
821
+ }
822
+ if (isReactNodeIterable(node)) {
823
+ for (const child of node) {
824
+ if (reactNodeContainsImage(child)) return true;
825
+ }
826
+ }
827
+ return false;
828
+ }
829
+ function readImgUrl(img) {
830
+ const attr = img.getAttribute("src")?.trim() ?? "";
831
+ if (attr) return attr;
832
+ if (img instanceof HTMLImageElement) {
833
+ const current = img.currentSrc?.trim() ?? "";
834
+ if (current && current !== img.baseURI) return current;
835
+ }
836
+ return "";
837
+ }
838
+ function readDomImageUrls(rowIndex, colIndex, root) {
839
+ const scope = root ?? (typeof document === "undefined" ? null : document);
840
+ if (!scope) return "";
841
+ const cells = scope.querySelectorAll(
842
+ `[data-row-index="${rowIndex}"][data-col-index="${colIndex}"]`
843
+ );
844
+ for (const cell of cells) {
845
+ const urls = Array.from(cell.querySelectorAll("img")).flatMap((img) => {
846
+ const url = readImgUrl(img);
847
+ return url ? [url] : [];
848
+ });
849
+ if (urls.length > 0) return urls.join(", ");
850
+ }
851
+ return "";
852
+ }
853
+ function reactNodeToText(node) {
854
+ if (node == null || typeof node === "boolean") return "";
855
+ if (typeof node === "string" || typeof node === "number" || typeof node === "bigint") {
856
+ return String(node);
857
+ }
858
+ if (isReactNodeIterable(node)) {
859
+ let text = "";
860
+ for (const child of node) {
861
+ text += reactNodeToText(child);
862
+ }
863
+ return text;
864
+ }
865
+ if (isValidElement(node)) {
866
+ if (isButtonReactElement(node)) return "";
867
+ const props = node.props;
868
+ const childText = reactNodeToText(props.children);
869
+ if (childText) return childText;
870
+ const fromImage = imageElementText(node);
871
+ if (fromImage) return fromImage;
872
+ if (isImageReactElement(node)) return "";
873
+ if (typeof props.alt === "string" && props.alt) return props.alt;
874
+ if (typeof props.title === "string" && props.title) return props.title;
875
+ return "";
876
+ }
877
+ return "";
878
+ }
879
+ function sanitizeClipboardCell(text) {
880
+ return text.replace(/\s+/g, " ").trim();
881
+ }
882
+ function createCopyRenderRow(rowData, index) {
883
+ return {
884
+ id: getOriginalRowId(rowData) || String(index),
885
+ index,
886
+ original: rowData,
887
+ getIsCellDragSelected: () => false
888
+ };
889
+ }
890
+ function buildVisibleRowLookup(visibleRows) {
891
+ const lookup = /* @__PURE__ */ new Map();
892
+ for (const row of visibleRows) {
893
+ lookup.set(row.original, row);
894
+ }
895
+ return lookup;
896
+ }
897
+ function resolveCopyColumnId(cell) {
898
+ if (cell.column.id) return cell.column.id;
899
+ const columnDef = cell.column.columnDef;
900
+ if (columnDef.id) return columnDef.id;
901
+ if (columnDef.accessorKey != null && columnDef.accessorKey !== "") {
902
+ return String(columnDef.accessorKey);
903
+ }
904
+ return "";
905
+ }
906
+ function isPrimitiveCopyValue(value) {
907
+ return value == null || typeof value !== "object";
908
+ }
909
+ function extractRenderedCopyText(node, value, cellPosition, root) {
910
+ const rendered = sanitizeClipboardCell(reactNodeToText(node));
911
+ if (reactNodeContainsImage(node)) {
912
+ const fromDom = cellPosition != null ? sanitizeClipboardCell(
913
+ readDomImageUrls(cellPosition.rowIndex, cellPosition.colIndex, root)
914
+ ) : "";
915
+ if (fromDom) return fromDom;
916
+ if (rendered && isLikelyUrl(rendered)) return rendered;
917
+ return sanitizeClipboardCell(pickUrlFromUnknown(value));
918
+ }
919
+ return rendered;
920
+ }
921
+ function formatCopyCellText(rowData, columnDef, columnId, visibleRow, fallbackIndex, sourceCell, cellPosition, options) {
922
+ const meta = columnDef.meta;
923
+ const value = sourceCell ? sourceCell.getValue() : readRowColumnValue(rowData, columnDef);
924
+ const cellRender = meta?.cellRender;
925
+ if (typeof cellRender === "function") {
926
+ try {
927
+ const row = visibleRow ?? createCopyRenderRow(rowData, fallbackIndex);
928
+ const node = cellRender({
929
+ value,
930
+ row,
931
+ index: row.index,
932
+ columnId,
933
+ cellProps: meta?.cellProps,
934
+ update: () => {
935
+ }
936
+ });
937
+ return extractRenderedCopyText(node, value, cellPosition, options?.root);
938
+ } catch {
939
+ return formatCellValue(value);
940
+ }
941
+ }
942
+ if (options?.registry && meta?.kind && isPrimitiveCopyValue(value)) {
943
+ try {
944
+ const row = visibleRow ?? createCopyRenderRow(rowData, fallbackIndex);
945
+ const ctx = {
946
+ value,
947
+ row,
948
+ index: row.index,
949
+ columnId,
950
+ cellProps: meta.cellProps,
951
+ update: () => {
952
+ }
953
+ };
954
+ const renderer = resolveCellRenderer(options.registry, meta.kind, ctx);
955
+ if (renderer) {
956
+ const node = renderer.render(ctx);
957
+ const rendered = extractRenderedCopyText(node, value, cellPosition, options.root);
958
+ if (rendered) return rendered;
959
+ }
960
+ } catch {
961
+ return formatCellValue(value);
962
+ }
963
+ }
964
+ return formatCellValue(value);
965
+ }
753
966
  function formatPrimitive(value) {
754
967
  if (value === null || value === void 0) return "";
755
968
  if (typeof value === "string") return value;
@@ -855,37 +1068,47 @@ function collectCopyRowEntries(visibleRows, bounds, mode = "visible") {
855
1068
  function collectCopyRows(visibleRows, bounds, mode = "visible") {
856
1069
  return collectCopyRowEntries(visibleRows, bounds, mode).map((entry) => entry.row);
857
1070
  }
858
- function serializeCopyRowsToTSV(copyRows, visibleRows, bounds, depths) {
1071
+ function serializeCopyRowsToTSV(copyRows, visibleRows, bounds, depths, options) {
859
1072
  if (copyRows.length === 0) return "";
860
1073
  const { startCol, endCol } = bounds;
861
1074
  const columnCells = visibleRows[0]?.getVisibleCells().slice(startCol, endCol + 1) ?? [];
862
1075
  if (columnCells.length === 0) return "";
863
1076
  const resolvedDepths = depths && depths.length === copyRows.length ? depths : copyRows.map((row) => getRowDepth(row));
864
1077
  const minDepth = Math.min(...resolvedDepths);
1078
+ const visibleRowByOriginal = buildVisibleRowLookup(visibleRows);
865
1079
  return copyRows.map((rowData, index) => {
866
1080
  const relativeDepth = Math.max(0, (resolvedDepths[index] ?? 0) - minDepth);
867
- const line = columnCells.map(
868
- (cell) => formatCellValue(
869
- readRowColumnValue(
870
- rowData,
871
- cell.column.columnDef
872
- )
873
- )
874
- ).join(" ");
1081
+ const visibleRow = visibleRowByOriginal.get(rowData);
1082
+ const matchingCells = visibleRow?.getVisibleCells().slice(startCol, endCol + 1);
1083
+ const line = columnCells.map((templateCell, colOffset) => {
1084
+ const sourceCell = matchingCells?.[colOffset];
1085
+ const column = sourceCell?.column ?? templateCell.column;
1086
+ return formatCopyCellText(
1087
+ rowData,
1088
+ column.columnDef,
1089
+ resolveCopyColumnId(sourceCell ?? templateCell),
1090
+ visibleRow,
1091
+ visibleRow?.index ?? index,
1092
+ sourceCell,
1093
+ visibleRow != null ? { rowIndex: visibleRow.index, colIndex: startCol + colOffset } : void 0,
1094
+ options
1095
+ );
1096
+ }).join(" ");
875
1097
  return `${" ".repeat(relativeDepth)}${line}`;
876
1098
  }).join("\n");
877
1099
  }
878
- function serializeSelectionToTSV(visibleRows, bounds, mode = "visible") {
1100
+ function serializeSelectionToTSV(visibleRows, bounds, mode = "visible", options) {
879
1101
  const entries = collectCopyRowEntries(visibleRows, bounds, mode);
880
1102
  return serializeCopyRowsToTSV(
881
1103
  entries.map((entry) => entry.row),
882
1104
  visibleRows,
883
1105
  bounds,
884
- entries.map((entry) => entry.depth)
1106
+ entries.map((entry) => entry.depth),
1107
+ options
885
1108
  );
886
1109
  }
887
- async function writeSelectionToClipboard(visibleRows, bounds, mode = "visible") {
888
- const text = serializeSelectionToTSV(visibleRows, bounds, mode);
1110
+ async function writeSelectionToClipboard(visibleRows, bounds, mode = "visible", options) {
1111
+ const text = serializeSelectionToTSV(visibleRows, bounds, mode, options);
889
1112
  if (!text) return false;
890
1113
  try {
891
1114
  await navigator.clipboard.writeText(text);
@@ -1046,7 +1269,9 @@ function useCellSelection({
1046
1269
  onDataChange,
1047
1270
  onBatchChange,
1048
1271
  onRowsPaste,
1049
- onCellNavigate
1272
+ onCellNavigate,
1273
+ cellRendererRegistry,
1274
+ rootRef
1050
1275
  }) {
1051
1276
  const [dragState, setDragState] = useState2(INITIAL_DRAG_STATE);
1052
1277
  const pendingPasteModeRef = useRef2(null);
@@ -1170,15 +1395,28 @@ function useCellSelection({
1170
1395
  async (options) => {
1171
1396
  if (!enabled || !activeSelectionBounds) return false;
1172
1397
  const mode = options?.includeDescendants && enableSubtreeCopy ? "subtree" : "visible";
1173
- return writeSelectionToClipboard(rows, activeSelectionBounds, mode);
1398
+ return writeSelectionToClipboard(rows, activeSelectionBounds, mode, {
1399
+ registry: cellRendererRegistry,
1400
+ root: rootRef?.current
1401
+ });
1174
1402
  },
1175
- [activeSelectionBounds, enableSubtreeCopy, enabled, rows]
1403
+ [
1404
+ activeSelectionBounds,
1405
+ cellRendererRegistry,
1406
+ enableSubtreeCopy,
1407
+ enabled,
1408
+ rootRef,
1409
+ rows
1410
+ ]
1176
1411
  );
1177
1412
  useEffect2(() => {
1178
1413
  if (!enabled) return;
1179
1414
  const handleKeyDown = (e) => {
1180
1415
  if (!activeSelectionBounds) return;
1181
1416
  if (!(e.ctrlKey || e.metaKey)) return;
1417
+ if (isEditablePasteTarget(e.target) || isEditablePasteTarget(document.activeElement)) {
1418
+ return;
1419
+ }
1182
1420
  const isSubtreeShortcut = enableSubtreeCopy && e.shiftKey && e.key.toLowerCase() === "c";
1183
1421
  const isVisibleCopyShortcut = !e.shiftKey && e.key.toLowerCase() === "c";
1184
1422
  if (!isSubtreeShortcut && !isVisibleCopyShortcut) return;
@@ -2433,6 +2671,10 @@ function useGlideTable(options) {
2433
2671
  const [hoveredRowIndex, setHoveredRowIndex] = useState4(null);
2434
2672
  const scrollRef = useRef5(null);
2435
2673
  const rootRef = useRef5(null);
2674
+ const cellRendererRegistry = useMemo3(
2675
+ () => createCellRendererRegistry(cellRenderers),
2676
+ [cellRenderers]
2677
+ );
2436
2678
  const shouldVirtualize = enableVirtualization && !enableRowSpan;
2437
2679
  useEffect5(() => {
2438
2680
  if (enableVirtualization && enableRowSpan) {
@@ -2616,7 +2858,9 @@ function useGlideTable(options) {
2616
2858
  onDataChange,
2617
2859
  onBatchChange,
2618
2860
  onRowsPaste,
2619
- onCellNavigate: handleCellNavigate
2861
+ onCellNavigate: handleCellNavigate,
2862
+ cellRendererRegistry,
2863
+ rootRef
2620
2864
  });
2621
2865
  const {
2622
2866
  editingCell,
@@ -2626,10 +2870,6 @@ function useGlideTable(options) {
2626
2870
  commitEdit,
2627
2871
  cancelEdit
2628
2872
  } = useCellEdit({ data: tableData, rows, onDataChange, onCellChange });
2629
- const cellRendererRegistry = useMemo3(
2630
- () => createCellRendererRegistry(cellRenderers),
2631
- [cellRenderers]
2632
- );
2633
2873
  const commitRenderedCellValue = useCallback4(
2634
2874
  (rowId, columnId, value) => commitCellValue({
2635
2875
  data: tableData,
@@ -3011,7 +3251,9 @@ var DataTableContext = createContext(null);
3011
3251
  function useDataTableRowContext() {
3012
3252
  const context = use(DataTableContext);
3013
3253
  if (!context) {
3014
- throw new Error("useDataTableRowContext must be used within a DataTableContextProvider");
3254
+ throw new Error(
3255
+ "useDataTableRowContext must be used within a DataTableContextProvider"
3256
+ );
3015
3257
  }
3016
3258
  return context;
3017
3259
  }
@@ -3056,16 +3298,140 @@ function ResolvedTableCell({
3056
3298
  }
3057
3299
 
3058
3300
  // src/components/ui/table/features/column-resize/columnResize.ts
3301
+ function clamp(value, min, max) {
3302
+ return Math.min(Math.max(value, min), max);
3303
+ }
3304
+ function floorOf(column) {
3305
+ return column.minWidth ?? 0;
3306
+ }
3307
+ function ceilOf(column) {
3308
+ return column.maxWidth ?? Number.POSITIVE_INFINITY;
3309
+ }
3310
+ function preferOf(column) {
3311
+ const floor = floorOf(column);
3312
+ const ceil = ceilOf(column);
3313
+ const preferred = column.maxWidth ?? column.minWidth ?? 0;
3314
+ return clamp(preferred, floor, Number.isFinite(ceil) ? ceil : preferred);
3315
+ }
3316
+ function resolveColumnLayoutWidths(containerWidth, columns) {
3317
+ const widths = /* @__PURE__ */ new Map();
3318
+ const fixed = [];
3319
+ const bounded = [];
3320
+ let flexCount = 0;
3321
+ for (const column of columns) {
3322
+ if (column.width != null) {
3323
+ fixed.push(column);
3324
+ } else if (column.minWidth != null || column.maxWidth != null) {
3325
+ bounded.push(column);
3326
+ } else {
3327
+ flexCount += 1;
3328
+ }
3329
+ }
3330
+ let used = 0;
3331
+ for (const column of fixed) {
3332
+ let size = column.width;
3333
+ if (column.minWidth != null) size = Math.max(size, column.minWidth);
3334
+ if (column.maxWidth != null) size = Math.min(size, column.maxWidth);
3335
+ widths.set(column.id, size);
3336
+ used += size;
3337
+ }
3338
+ if (bounded.length === 0) {
3339
+ return widths;
3340
+ }
3341
+ const boundedSizes = /* @__PURE__ */ new Map();
3342
+ let preferredSum = 0;
3343
+ let floorSum = 0;
3344
+ for (const column of bounded) {
3345
+ const preferred = preferOf(column);
3346
+ boundedSizes.set(column.id, preferred);
3347
+ preferredSum += preferred;
3348
+ floorSum += floorOf(column);
3349
+ }
3350
+ if (containerWidth > 0) {
3351
+ const remaining = Math.max(0, containerWidth - used);
3352
+ if (remaining >= preferredSum) {
3353
+ } else if (remaining >= floorSum) {
3354
+ let deficit = preferredSum - remaining;
3355
+ const open = bounded.map((column) => ({
3356
+ id: column.id,
3357
+ current: boundedSizes.get(column.id),
3358
+ floor: floorOf(column)
3359
+ }));
3360
+ while (deficit >= 1) {
3361
+ const shrinkable = open.filter((entry) => entry.current > entry.floor);
3362
+ if (shrinkable.length === 0) break;
3363
+ const portion = Math.floor(deficit / shrinkable.length);
3364
+ const rem = deficit % shrinkable.length;
3365
+ let consumed = 0;
3366
+ for (let index = 0; index < shrinkable.length; index += 1) {
3367
+ const entry = shrinkable[index];
3368
+ const reduce = Math.min(
3369
+ entry.current - entry.floor,
3370
+ portion + (index < rem ? 1 : 0)
3371
+ );
3372
+ entry.current -= reduce;
3373
+ consumed += reduce;
3374
+ }
3375
+ if (consumed === 0) break;
3376
+ deficit -= consumed;
3377
+ }
3378
+ for (const entry of open) {
3379
+ boundedSizes.set(entry.id, entry.current);
3380
+ }
3381
+ } else {
3382
+ for (const column of bounded) {
3383
+ boundedSizes.set(column.id, floorOf(column));
3384
+ }
3385
+ }
3386
+ }
3387
+ for (const [id, size] of boundedSizes) {
3388
+ widths.set(id, Math.round(size));
3389
+ }
3390
+ return widths;
3391
+ }
3059
3392
  function getColumnSizeStyle(size, options) {
3060
- const { force = false, lockMax = false } = options ?? {};
3061
- if (!force && size === DATA_TABLE_COLUMN_SIZE) {
3393
+ const {
3394
+ force = false,
3395
+ lockMax = false,
3396
+ minWidth,
3397
+ maxWidth,
3398
+ layoutWidth
3399
+ } = options ?? {};
3400
+ if (lockMax) {
3401
+ return {
3402
+ width: size,
3403
+ minWidth: size,
3404
+ maxWidth: size
3405
+ };
3406
+ }
3407
+ if (layoutWidth != null) {
3408
+ return {
3409
+ width: layoutWidth,
3410
+ minWidth: layoutWidth,
3411
+ maxWidth: layoutWidth
3412
+ };
3413
+ }
3414
+ const resolvedSize = size;
3415
+ const hasExplicitSize = force || size !== DATA_TABLE_COLUMN_SIZE;
3416
+ if (!hasExplicitSize && minWidth == null && maxWidth == null) {
3062
3417
  return void 0;
3063
3418
  }
3064
- return {
3065
- width: size,
3066
- minWidth: size,
3067
- ...lockMax ? { maxWidth: size } : {}
3068
- };
3419
+ const style = {};
3420
+ if (hasExplicitSize) {
3421
+ const used = minWidth != null || maxWidth != null ? clamp(
3422
+ resolvedSize,
3423
+ minWidth ?? Number.NEGATIVE_INFINITY,
3424
+ maxWidth ?? Number.POSITIVE_INFINITY
3425
+ ) : resolvedSize;
3426
+ style.width = used;
3427
+ style.minWidth = minWidth ?? used;
3428
+ } else if (minWidth != null) {
3429
+ style.minWidth = minWidth;
3430
+ }
3431
+ if (maxWidth != null) {
3432
+ style.maxWidth = maxWidth;
3433
+ }
3434
+ return style;
3069
3435
  }
3070
3436
 
3071
3437
  // src/components/ui/table/features/column-reorder/useColumnReorder.ts
@@ -3283,7 +3649,7 @@ function useColumnReorder(options) {
3283
3649
 
3284
3650
  // src/components/ui/table/components/DataTable/DataTable.tsx
3285
3651
  import { flexRender as flexRender2 } from "@tanstack/react-table";
3286
- import { useMemo as useMemo4 } from "react";
3652
+ import { useEffect as useEffect8, useMemo as useMemo4, useState as useState6 } from "react";
3287
3653
 
3288
3654
  // src/components/ui/table/components/DataTable/DataTableRow.tsx
3289
3655
  import { flexRender } from "@tanstack/react-table";
@@ -3449,6 +3815,12 @@ function isInteractiveMouseTarget(target) {
3449
3815
  ].join(",");
3450
3816
  return target.closest(interactiveSelector) !== null;
3451
3817
  }
3818
+ function blurActiveElementOutside(container) {
3819
+ const active = document.activeElement;
3820
+ if (!(active instanceof HTMLElement) || active === document.body) return;
3821
+ if (container instanceof Node && container.contains(active)) return;
3822
+ active.blur();
3823
+ }
3452
3824
  function resolveExpandCellIndex(cells, toggleField) {
3453
3825
  if (!toggleField) return 0;
3454
3826
  const matchedIndex = cells.findIndex(
@@ -3481,7 +3853,7 @@ function DataTableRow({
3481
3853
  columnFreeze,
3482
3854
  inlineSearch
3483
3855
  } = useDataTableRowContext();
3484
- const { enableColumnResize } = columnResize;
3856
+ const { enableColumnResize, layoutWidths } = columnResize;
3485
3857
  const { enableColumnFreeze, offsets: freezeOffsets } = columnFreeze;
3486
3858
  const {
3487
3859
  enabled: enableInlineSearch,
@@ -3674,7 +4046,10 @@ function DataTableRow({
3674
4046
  const hasSelectionEdges = hasCellSelectionEdges(selectionEdgeStyle);
3675
4047
  const sizeStyle = getColumnSizeStyle(cell.column.getSize(), {
3676
4048
  force: enableColumnResize,
3677
- lockMax: enableColumnResize
4049
+ lockMax: enableColumnResize,
4050
+ minWidth: meta?.minWidth,
4051
+ maxWidth: meta?.maxWidth,
4052
+ layoutWidth: layoutWidths?.get(columnId)
3678
4053
  });
3679
4054
  const freezeOffset = enableColumnFreeze ? freezeOffsets.get(columnId) : void 0;
3680
4055
  const freezeStyle = getColumnFreezeStyle(freezeOffset);
@@ -3714,6 +4089,7 @@ function DataTableRow({
3714
4089
  if (!enableCellSelection) return;
3715
4090
  if (isInteractiveMouseTarget(event.target)) return;
3716
4091
  event.preventDefault();
4092
+ blurActiveElementOutside(event.currentTarget);
3717
4093
  onCellMouseDown(
3718
4094
  resolveCellRowIndex(event.clientY, event.currentTarget),
3719
4095
  cellIndex,
@@ -3877,6 +4253,7 @@ function DataTableRow({
3877
4253
  onMouseDown: (event) => {
3878
4254
  event.stopPropagation();
3879
4255
  event.preventDefault();
4256
+ blurActiveElementOutside(event.currentTarget);
3880
4257
  onFillHandleMouseDown(rowIndex, cellIndex);
3881
4258
  }
3882
4259
  }
@@ -4206,17 +4583,74 @@ function DataTable({
4206
4583
  const RowSlot = slots?.Row ?? DataTableRow;
4207
4584
  const PendingSlot = slots?.Pending ?? DefaultPending;
4208
4585
  const EmptySlot = slots?.Empty ?? DefaultEmpty;
4209
- const freezeOffsets = rowContextValue.columnFreeze.offsets;
4210
4586
  const headerGroups = getMergedHeaderGroups(table.getHeaderGroups());
4211
4587
  const leafColumnIds = table.getVisibleLeafColumns().map((column) => column.id);
4588
+ const columnLayoutMetaSignature = table.getVisibleLeafColumns().map((column) => {
4589
+ const meta = column.columnDef.meta;
4590
+ return `${column.id}:${meta?.width ?? ""}:${meta?.minWidth ?? ""}:${meta?.maxWidth ?? ""}`;
4591
+ }).join("|");
4212
4592
  const { isReordering, draggingColumnId, dropTarget, onHeaderPointerDown } = useColumnReorder({
4213
4593
  enabled: enableColumnReorder,
4214
4594
  columnOrder: leafColumnIds,
4215
4595
  onColumnOrderChange: setColumnOrder
4216
4596
  });
4597
+ const [containerWidth, setContainerWidth] = useState6(0);
4598
+ useEffect8(() => {
4599
+ if (enableColumnResize || isPending) return;
4600
+ const element = scrollRef.current;
4601
+ if (!element) return;
4602
+ const updateWidth = () => {
4603
+ setContainerWidth(Math.floor(element.clientWidth));
4604
+ };
4605
+ updateWidth();
4606
+ if (typeof ResizeObserver === "undefined") return;
4607
+ const observer = new ResizeObserver(() => {
4608
+ updateWidth();
4609
+ });
4610
+ observer.observe(element);
4611
+ return () => observer.disconnect();
4612
+ }, [enableColumnResize, isPending, scrollRef, rows.length, leafColumnIds.join("|")]);
4613
+ const layoutWidths = useMemo4(() => {
4614
+ if (enableColumnResize) return void 0;
4615
+ const columns = table.getVisibleLeafColumns().map((column) => ({
4616
+ id: column.id,
4617
+ width: column.columnDef.meta?.width,
4618
+ minWidth: column.columnDef.meta?.minWidth,
4619
+ maxWidth: column.columnDef.meta?.maxWidth
4620
+ }));
4621
+ return resolveColumnLayoutWidths(containerWidth, columns);
4622
+ }, [enableColumnResize, containerWidth, table, columnLayoutMetaSignature]);
4623
+ const freezeOffsets = useMemo4(() => {
4624
+ if (!enableColumnFreeze || enableColumnResize || !layoutWidths) {
4625
+ return rowContextValue.columnFreeze.offsets;
4626
+ }
4627
+ const columns = table.getVisibleLeafColumns().map((column) => ({
4628
+ id: column.id,
4629
+ size: layoutWidths.get(column.id) ?? column.getSize(),
4630
+ side: resolveColumnFreezeSide(column.columnDef.meta?.frozen)
4631
+ }));
4632
+ return buildColumnFreezeOffsets(columns);
4633
+ }, [
4634
+ enableColumnFreeze,
4635
+ enableColumnResize,
4636
+ layoutWidths,
4637
+ rowContextValue.columnFreeze.offsets,
4638
+ table
4639
+ ]);
4217
4640
  const contextValue = useMemo4(
4218
- () => ({ ...rowContextValue, classNames }),
4219
- [rowContextValue, classNames]
4641
+ () => ({
4642
+ ...rowContextValue,
4643
+ classNames,
4644
+ columnFreeze: {
4645
+ ...rowContextValue.columnFreeze,
4646
+ offsets: freezeOffsets
4647
+ },
4648
+ columnResize: {
4649
+ ...rowContextValue.columnResize,
4650
+ layoutWidths
4651
+ }
4652
+ }),
4653
+ [rowContextValue, classNames, freezeOffsets, layoutWidths]
4220
4654
  );
4221
4655
  if (isPending) {
4222
4656
  return /* @__PURE__ */ jsx7(
@@ -4295,7 +4729,10 @@ function DataTable({
4295
4729
  const canResize = enableColumnResize && header.column.getCanResize();
4296
4730
  const sizeStyle = getColumnSizeStyle(header.getSize(), {
4297
4731
  force: enableColumnResize,
4298
- lockMax: enableColumnResize
4732
+ lockMax: enableColumnResize,
4733
+ minWidth: header.column.columnDef.meta?.minWidth,
4734
+ maxWidth: header.column.columnDef.meta?.maxWidth,
4735
+ layoutWidth: layoutWidths?.get(header.column.id)
4299
4736
  });
4300
4737
  const freezeOffset = enableColumnFreeze ? resolveHeaderFreezeOffset(header.column, freezeOffsets) : void 0;
4301
4738
  const freezeStyle = getColumnFreezeStyle(freezeOffset, {
@@ -4308,7 +4745,9 @@ function DataTable({
4308
4745
  };
4309
4746
  const isPlaceholder = header.isPlaceholder;
4310
4747
  const leafColumns = header.column.getLeafColumns();
4311
- const leafIds = leafColumns.map((leafColumn) => leafColumn.id);
4748
+ const leafIds = leafColumns.map(
4749
+ (leafColumn) => leafColumn.id
4750
+ );
4312
4751
  const isLeafHeader = !isPlaceholder && header.subHeaders.length === 0;
4313
4752
  const canDrag = enableColumnReorder && !isPlaceholder && leafIds.length > 0 && leafColumns.every(
4314
4753
  (leafColumn) => isColumnReorderable(leafColumn.columnDef.meta)
@@ -4464,7 +4903,7 @@ function DataTable({
4464
4903
  }
4465
4904
 
4466
4905
  // src/components/ui/table/components/Table/Table.tsx
4467
- import { useCallback as useCallback7, useMemo as useMemo5, useState as useState6 } from "react";
4906
+ import { useCallback as useCallback7, useMemo as useMemo5, useState as useState7 } from "react";
4468
4907
 
4469
4908
  // src/components/ui/table/components/Table/buildColumnDef.tsx
4470
4909
  import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
@@ -4501,6 +4940,8 @@ function buildColumnDef(props, sort, onSort) {
4501
4940
  width,
4502
4941
  minWidth,
4503
4942
  maxWidth,
4943
+ minResizeWidth,
4944
+ maxResizeWidth,
4504
4945
  resizable,
4505
4946
  reorderable,
4506
4947
  frozen,
@@ -4521,8 +4962,8 @@ function buildColumnDef(props, sort, onSort) {
4521
4962
  id: field,
4522
4963
  ...!virtual ? { accessorKey: field } : {},
4523
4964
  size: width ?? DATA_TABLE_COLUMN_SIZE,
4524
- ...minWidth != null ? { minSize: minWidth } : {},
4525
- ...maxWidth != null ? { maxSize: maxWidth } : {},
4965
+ ...minResizeWidth != null ? { minSize: minResizeWidth } : {},
4966
+ ...maxResizeWidth != null ? { maxSize: maxResizeWidth } : {},
4526
4967
  ...resizable === false ? { enableResizing: false } : {},
4527
4968
  header: sortable ? () => /* @__PURE__ */ jsx8(
4528
4969
  SortableHeader,
@@ -4551,6 +4992,9 @@ function buildColumnDef(props, sort, onSort) {
4551
4992
  cellRender: render,
4552
4993
  frozen,
4553
4994
  reorderable,
4995
+ width,
4996
+ minWidth,
4997
+ maxWidth,
4554
4998
  className,
4555
4999
  headerClassName
4556
5000
  }
@@ -4596,10 +5040,10 @@ function countLeafColumns(nodes) {
4596
5040
  }
4597
5041
 
4598
5042
  // src/components/ui/table/components/Table/parseTableChildren.ts
4599
- import { Children, isValidElement as isValidElement2 } from "react";
5043
+ import { Children, isValidElement as isValidElement3 } from "react";
4600
5044
 
4601
5045
  // src/components/ui/table/components/Table/tableChildTypes.ts
4602
- import { isValidElement } from "react";
5046
+ import { isValidElement as isValidElement2 } from "react";
4603
5047
  var TABLE_HEADER_DISPLAY_NAME = "Table.Header";
4604
5048
  var TABLE_BODY_DISPLAY_NAME = "Table.Body";
4605
5049
  var TABLE_COLUMN_DISPLAY_NAME = "Table.Column";
@@ -4612,19 +5056,19 @@ function getComponentDisplayName(type) {
4612
5056
  return void 0;
4613
5057
  }
4614
5058
  function isTableHeaderElement(child) {
4615
- return isValidElement(child) && getComponentDisplayName(child.type) === TABLE_HEADER_DISPLAY_NAME;
5059
+ return isValidElement2(child) && getComponentDisplayName(child.type) === TABLE_HEADER_DISPLAY_NAME;
4616
5060
  }
4617
5061
  function isTableBodyElement(child) {
4618
- return isValidElement(child) && getComponentDisplayName(child.type) === TABLE_BODY_DISPLAY_NAME;
5062
+ return isValidElement2(child) && getComponentDisplayName(child.type) === TABLE_BODY_DISPLAY_NAME;
4619
5063
  }
4620
5064
  function isTableColumnElement(child) {
4621
- return isValidElement(child) && getComponentDisplayName(child.type) === TABLE_COLUMN_DISPLAY_NAME;
5065
+ return isValidElement2(child) && getComponentDisplayName(child.type) === TABLE_COLUMN_DISPLAY_NAME;
4622
5066
  }
4623
5067
  function isTableColumnGroupElement(child) {
4624
- return isValidElement(child) && getComponentDisplayName(child.type) === TABLE_COLUMN_GROUP_DISPLAY_NAME;
5068
+ return isValidElement2(child) && getComponentDisplayName(child.type) === TABLE_COLUMN_GROUP_DISPLAY_NAME;
4625
5069
  }
4626
5070
  function isTablePaginationElement(child) {
4627
- return isValidElement(child) && getComponentDisplayName(child.type) === TABLE_PAGINATION_DISPLAY_NAME;
5071
+ return isValidElement2(child) && getComponentDisplayName(child.type) === TABLE_PAGINATION_DISPLAY_NAME;
4628
5072
  }
4629
5073
 
4630
5074
  // src/components/ui/table/components/Table/parseTableChildren.ts
@@ -4668,7 +5112,7 @@ function walkColumnTreeNodes(children) {
4668
5112
  });
4669
5113
  continue;
4670
5114
  }
4671
- if (isValidElement2(child)) {
5115
+ if (isValidElement3(child)) {
4672
5116
  const nested = child.props.children;
4673
5117
  if (nested != null) {
4674
5118
  result.push(...walkColumnTreeNodes(nested));
@@ -4798,7 +5242,7 @@ function TableRoot({
4798
5242
  () => parseTableChildren(children),
4799
5243
  [children]
4800
5244
  );
4801
- const [sort, setSort] = useState6(null);
5245
+ const [sort, setSort] = useState7(null);
4802
5246
  const handleSort = useCallback7((field) => {
4803
5247
  setSort((previous) => {
4804
5248
  if (previous?.field !== field) {
@@ -4946,6 +5390,7 @@ export {
4946
5390
  previousSearchIndex,
4947
5391
  resolveCellRenderer,
4948
5392
  resolveColumnFreezeSide,
5393
+ resolveColumnLayoutWidths,
4949
5394
  resolveDataTableLabels,
4950
5395
  resolveDropEdge,
4951
5396
  resolveHeaderFreezeOffset,