react-glide-table 2.1.0 → 2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -259,6 +259,18 @@ import type { RowsPastePayload } from "react-glide-table/compound";
259
259
  Related props: `onRowsPaste`, `enableInsertPaste`, `enableSubtreeCopy`, `onCopyActionsReady`.
260
260
  Helpers (`/core`): `buildRowsPastePayload`, `parseClipboardTSV`, `parseClipboardTSVWithDepths`, `serializeSelectionToTSV`, …
261
261
 
262
+ ## Column width
263
+
264
+ `Column.width` sets the default size. `minWidth` / `maxWidth` are CSS constraints on header and body cells — they do not clamp drag-resize.
265
+
266
+ ```tsx
267
+ <ProductTable.Column field="note" minWidth={80} maxWidth={240}>
268
+ Note
269
+ </ProductTable.Column>
270
+ ```
271
+
272
+ With `ColumnDef` (non-compound), put the same values on `meta.minWidth` / `meta.maxWidth`.
273
+
262
274
  ## Column resize
263
275
 
264
276
  Opt in with `enableColumnResize`. Drag the handle on the right edge of a header cell; double-click resets to the column’s default `width` / `size`.
@@ -272,7 +284,12 @@ Opt in with `enableColumnResize`. Drag the handle on the right edge of a header
272
284
  // onColumnSizingChange={setSizing}
273
285
  >
274
286
  <ProductTable.Header>
275
- <ProductTable.Column field="name" width={200} minWidth={80} maxWidth={480}>
287
+ <ProductTable.Column
288
+ field="name"
289
+ width={200}
290
+ minResizeWidth={80}
291
+ maxResizeWidth={480}
292
+ >
276
293
  Name
277
294
  </ProductTable.Column>
278
295
  <ProductTable.Column field="sku" resizable={false}>
@@ -282,14 +299,15 @@ Opt in with `enableColumnResize`. Drag the handle on the right edge of a header
282
299
  </ProductTable>
283
300
  ```
284
301
 
285
- | Prop | Role |
286
- | ---------------------------------------- | -------------------------------------------- |
287
- | `enableColumnResize` | Turn on header drag resize (default `false`) |
288
- | `columnSizing` / `onColumnSizingChange` | Controlled width map `{ [columnId]: px }` |
289
- | `columnResizeMode` | `"onChange"` (live) or `"onEnd"` |
290
- | `Column.width` / `minWidth` / `maxWidth` | Default / clamp sizes |
291
- | `Column.resizable={false}` | Disable resize for one column |
292
- | `classNames.resizeHandle` | Style hook for the drag handle |
302
+ | Prop | Role |
303
+ | ------------------------------------------ | -------------------------------------------- |
304
+ | `enableColumnResize` | Turn on header drag resize (default `false`) |
305
+ | `columnSizing` / `onColumnSizingChange` | Controlled width map `{ [columnId]: px }` |
306
+ | `columnResizeMode` | `"onChange"` (live) or `"onEnd"` |
307
+ | `Column.width` | Default column size |
308
+ | `Column.minResizeWidth` / `maxResizeWidth` | Drag-resize clamp sizes |
309
+ | `Column.resizable={false}` | Disable resize for one column |
310
+ | `classNames.resizeHandle` | Style hook for the drag handle |
293
311
 
294
312
  ## Column reorder
295
313
 
package/dist/compound.cjs CHANGED
@@ -531,15 +531,29 @@ function flattenHeaderLeaves(column) {
531
531
 
532
532
  // src/components/ui/table/features/column-resize/columnResize.ts
533
533
  function getColumnSizeStyle(size, options) {
534
- const { force = false, lockMax = false } = options ?? {};
535
- if (!force && size === DATA_TABLE_COLUMN_SIZE) {
534
+ const { force = false, lockMax = false, minWidth, maxWidth } = options ?? {};
535
+ if (lockMax) {
536
+ return {
537
+ width: size,
538
+ minWidth: size,
539
+ maxWidth: size
540
+ };
541
+ }
542
+ const hasExplicitSize = force || size !== DATA_TABLE_COLUMN_SIZE;
543
+ if (!hasExplicitSize && minWidth == null && maxWidth == null) {
536
544
  return void 0;
537
545
  }
538
- return {
539
- width: size,
540
- minWidth: size,
541
- ...lockMax ? { maxWidth: size } : {}
542
- };
546
+ const style = {};
547
+ if (hasExplicitSize) {
548
+ style.width = size;
549
+ style.minWidth = minWidth ?? size;
550
+ } else if (minWidth != null) {
551
+ style.minWidth = minWidth;
552
+ }
553
+ if (maxWidth != null) {
554
+ style.maxWidth = maxWidth;
555
+ }
556
+ return style;
543
557
  }
544
558
 
545
559
  // src/components/ui/table/features/inline-search/inlineSearch.ts
@@ -890,23 +904,49 @@ var useConvertTreeData = ({
890
904
  function getRowFieldValue(row, key) {
891
905
  return row[key];
892
906
  }
893
- function computeRowSpans(data, rowSpanKey) {
907
+ function normalizeRowSpanParent(value) {
908
+ if (!value) return [];
909
+ return typeof value === "string" ? [value] : [...value];
910
+ }
911
+ function toParentSpanList(parentSpans) {
912
+ if (!parentSpans?.length) return [];
913
+ const first = parentSpans[0];
914
+ if (!Array.isArray(first)) {
915
+ return [parentSpans];
916
+ }
917
+ return parentSpans;
918
+ }
919
+ function buildStartRowLookup(spans) {
920
+ const startRows = new Array(spans.length);
921
+ let origin = 0;
922
+ for (let i = 0; i < spans.length; i++) {
923
+ if ((spans[i]?.rowSpan ?? 1) > 0) origin = i;
924
+ startRows[i] = origin;
925
+ }
926
+ return startRows;
927
+ }
928
+ function sharesParentGroup(parentStartRows, rowIndex) {
929
+ if (parentStartRows.length === 0 || rowIndex <= 0) return true;
930
+ return parentStartRows.every(
931
+ (startRows) => startRows[rowIndex - 1] === startRows[rowIndex]
932
+ );
933
+ }
934
+ function computeRowSpans(data, rowSpanKey, parentSpans) {
894
935
  if (data.length === 0) return [];
936
+ const parentStartRows = toParentSpanList(parentSpans).map(buildStartRowLookup);
895
937
  const result = [];
896
938
  for (let index = 0; index < data.length; index++) {
897
939
  const currentValue = getRowFieldValue(data[index], rowSpanKey);
898
940
  const previousValue = index > 0 ? getRowFieldValue(data[index - 1], rowSpanKey) : void 0;
899
- if (index > 0 && currentValue === previousValue) {
941
+ if (index > 0 && currentValue === previousValue && sharesParentGroup(parentStartRows, index)) {
900
942
  result.push({ rowSpan: 0, isFirstInGroup: false });
901
943
  continue;
902
944
  }
903
945
  let span = 1;
904
946
  for (let nextIndex = index + 1; nextIndex < data.length; nextIndex++) {
905
- if (getRowFieldValue(data[nextIndex], rowSpanKey) === currentValue) {
906
- span++;
907
- } else {
908
- break;
909
- }
947
+ if (getRowFieldValue(data[nextIndex], rowSpanKey) !== currentValue) break;
948
+ if (!sharesParentGroup(parentStartRows, nextIndex)) break;
949
+ span++;
910
950
  }
911
951
  result.push({ rowSpan: span, isFirstInGroup: true });
912
952
  }
@@ -928,10 +968,50 @@ function resolveRowSpanAt(rowSpans, rowIndex) {
928
968
  }
929
969
  return { startRow: rowIndex, rowSpan: 1 };
930
970
  }
971
+ function findRowSpanColumn(spec, ref) {
972
+ return spec.find((column) => column.columnId === ref) ?? spec.find((column) => column.rowSpanKey === ref);
973
+ }
931
974
  function buildColumnRowSpanMap(data, columnKeys) {
932
975
  const map = /* @__PURE__ */ new Map();
933
- for (const { columnId, rowSpanKey } of columnKeys) {
934
- map.set(columnId, computeRowSpans(data, rowSpanKey));
976
+ const visiting = /* @__PURE__ */ new Set();
977
+ const warnedCycles = /* @__PURE__ */ new Set();
978
+ const virtualParents = /* @__PURE__ */ new Map();
979
+ const spansForColumn = (columnId) => {
980
+ const cached = map.get(columnId);
981
+ if (cached !== void 0) return cached;
982
+ const column = columnKeys.find((item) => item.columnId === columnId);
983
+ if (!column) return void 0;
984
+ if (visiting.has(columnId)) {
985
+ if (!warnedCycles.has(columnId)) {
986
+ warnedCycles.add(columnId);
987
+ console.warn(
988
+ `[rowSpan] rowSpanParent cycle detected at column "${columnId}"; dropping the cyclic parent reference.`
989
+ );
990
+ }
991
+ return void 0;
992
+ }
993
+ visiting.add(columnId);
994
+ const parentSpans = (column.rowSpanParent ?? []).map((ref) => spansForParentRef(ref)).filter((spans2) => Boolean(spans2));
995
+ visiting.delete(columnId);
996
+ const spans = computeRowSpans(
997
+ data,
998
+ column.rowSpanKey,
999
+ parentSpans.length > 0 ? parentSpans : void 0
1000
+ );
1001
+ map.set(columnId, spans);
1002
+ return spans;
1003
+ };
1004
+ const spansForParentRef = (ref) => {
1005
+ const parentColumn = findRowSpanColumn(columnKeys, ref);
1006
+ if (parentColumn) return spansForColumn(parentColumn.columnId);
1007
+ const cached = virtualParents.get(ref);
1008
+ if (cached !== void 0) return cached;
1009
+ const spans = computeRowSpans(data, ref);
1010
+ virtualParents.set(ref, spans);
1011
+ return spans;
1012
+ };
1013
+ for (const column of columnKeys) {
1014
+ spansForColumn(column.columnId);
935
1015
  }
936
1016
  return map;
937
1017
  }
@@ -947,7 +1027,8 @@ function collectRowSpanColumns(columns) {
947
1027
  if (!columnId || !columnDef.meta?.rowSpan) continue;
948
1028
  result.push({
949
1029
  columnId,
950
- rowSpanKey: columnDef.meta.rowSpanKey ?? columnId
1030
+ rowSpanKey: columnDef.meta.rowSpanKey ?? columnId,
1031
+ rowSpanParent: normalizeRowSpanParent(columnDef.meta.rowSpanParent)
951
1032
  });
952
1033
  }
953
1034
  };
@@ -1340,7 +1421,9 @@ function DataTableRow({
1340
1421
  const hasSelectionEdges = hasCellSelectionEdges(selectionEdgeStyle);
1341
1422
  const sizeStyle = getColumnSizeStyle(cell.column.getSize(), {
1342
1423
  force: enableColumnResize,
1343
- lockMax: enableColumnResize
1424
+ lockMax: enableColumnResize,
1425
+ minWidth: meta?.minWidth,
1426
+ maxWidth: meta?.maxWidth
1344
1427
  });
1345
1428
  const freezeOffset = enableColumnFreeze ? freezeOffsets.get(columnId) : void 0;
1346
1429
  const freezeStyle = getColumnFreezeStyle(freezeOffset);
@@ -4163,7 +4246,9 @@ function DataTable({
4163
4246
  const canResize = enableColumnResize && header.column.getCanResize();
4164
4247
  const sizeStyle = getColumnSizeStyle(header.getSize(), {
4165
4248
  force: enableColumnResize,
4166
- lockMax: enableColumnResize
4249
+ lockMax: enableColumnResize,
4250
+ minWidth: header.column.columnDef.meta?.minWidth,
4251
+ maxWidth: header.column.columnDef.meta?.maxWidth
4167
4252
  });
4168
4253
  const freezeOffset = enableColumnFreeze ? resolveHeaderFreezeOffset(header.column, freezeOffsets) : void 0;
4169
4254
  const freezeStyle = getColumnFreezeStyle(freezeOffset, {
@@ -4403,12 +4488,15 @@ function buildColumnDef(props, sort, onSort) {
4403
4488
  width,
4404
4489
  minWidth,
4405
4490
  maxWidth,
4491
+ minResizeWidth,
4492
+ maxResizeWidth,
4406
4493
  resizable,
4407
4494
  reorderable,
4408
4495
  frozen,
4409
4496
  align,
4410
4497
  rowSpan,
4411
4498
  rowSpanKey,
4499
+ rowSpanParent,
4412
4500
  editable,
4413
4501
  editType,
4414
4502
  editInputProps,
@@ -4422,8 +4510,8 @@ function buildColumnDef(props, sort, onSort) {
4422
4510
  id: field,
4423
4511
  ...!virtual ? { accessorKey: field } : {},
4424
4512
  size: width ?? DATA_TABLE_COLUMN_SIZE,
4425
- ...minWidth != null ? { minSize: minWidth } : {},
4426
- ...maxWidth != null ? { maxSize: maxWidth } : {},
4513
+ ...minResizeWidth != null ? { minSize: minResizeWidth } : {},
4514
+ ...maxResizeWidth != null ? { maxSize: maxResizeWidth } : {},
4427
4515
  ...resizable === false ? { enableResizing: false } : {},
4428
4516
  header: sortable ? () => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4429
4517
  SortableHeader,
@@ -4443,6 +4531,7 @@ function buildColumnDef(props, sort, onSort) {
4443
4531
  align,
4444
4532
  rowSpan,
4445
4533
  rowSpanKey,
4534
+ rowSpanParent,
4446
4535
  editable,
4447
4536
  editType,
4448
4537
  editInputProps,
@@ -4451,6 +4540,8 @@ function buildColumnDef(props, sort, onSort) {
4451
4540
  cellRender: render,
4452
4541
  frozen,
4453
4542
  reorderable,
4543
+ minWidth,
4544
+ maxWidth,
4454
4545
  className,
4455
4546
  headerClassName
4456
4547
  }
@@ -1,7 +1,7 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode, ReactElement } from 'react';
3
- import { l as DataTableProps, r as TableColumnProps, T as TableColumnGroupProps, s as TableProps } from './types-CMUGtH-c.cjs';
4
- export { B as BuiltinCellKind, C as CellKind, a as CellRenderContext, b as CellRenderFn, c as CellRenderer, f as ColumnFreezeMeta, h as ColumnFreezeSide, i as DataTableClassNames, k as DataTableLabels, m as DataTableScrollSlotProps, n as DataTableSlots, P as PasteMode, R as RowSelectionMode, o as RowsPastePayload, p as SearchResultItem } from './types-CMUGtH-c.cjs';
3
+ import { l as DataTableProps, r as TableColumnProps, T as TableColumnGroupProps, s as TableProps } from './types-CnsQ8GZb.cjs';
4
+ export { B as BuiltinCellKind, C as CellKind, a as CellRenderContext, b as CellRenderFn, c as CellRenderer, f as ColumnFreezeMeta, h as ColumnFreezeSide, i as DataTableClassNames, k as DataTableLabels, m as DataTableScrollSlotProps, n as DataTableSlots, P as PasteMode, R as RowSelectionMode, o as RowsPastePayload, p as SearchResultItem } from './types-CnsQ8GZb.cjs';
5
5
  export { ColumnDef, ColumnOrderState, ColumnResizeMode, ColumnSizingState, RowSelectionState } from '@tanstack/react-table';
6
6
 
7
7
  /**
@@ -1,7 +1,7 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode, ReactElement } from 'react';
3
- import { l as DataTableProps, r as TableColumnProps, T as TableColumnGroupProps, s as TableProps } from './types-CMUGtH-c.js';
4
- export { B as BuiltinCellKind, C as CellKind, a as CellRenderContext, b as CellRenderFn, c as CellRenderer, f as ColumnFreezeMeta, h as ColumnFreezeSide, i as DataTableClassNames, k as DataTableLabels, m as DataTableScrollSlotProps, n as DataTableSlots, P as PasteMode, R as RowSelectionMode, o as RowsPastePayload, p as SearchResultItem } from './types-CMUGtH-c.js';
3
+ import { l as DataTableProps, r as TableColumnProps, T as TableColumnGroupProps, s as TableProps } from './types-CnsQ8GZb.js';
4
+ export { B as BuiltinCellKind, C as CellKind, a as CellRenderContext, b as CellRenderFn, c as CellRenderer, f as ColumnFreezeMeta, h as ColumnFreezeSide, i as DataTableClassNames, k as DataTableLabels, m as DataTableScrollSlotProps, n as DataTableSlots, P as PasteMode, R as RowSelectionMode, o as RowsPastePayload, p as SearchResultItem } from './types-CnsQ8GZb.js';
5
5
  export { ColumnDef, ColumnOrderState, ColumnResizeMode, ColumnSizingState, RowSelectionState } from '@tanstack/react-table';
6
6
 
7
7
  /**
package/dist/compound.js CHANGED
@@ -503,15 +503,29 @@ function flattenHeaderLeaves(column) {
503
503
 
504
504
  // src/components/ui/table/features/column-resize/columnResize.ts
505
505
  function getColumnSizeStyle(size, options) {
506
- const { force = false, lockMax = false } = options ?? {};
507
- if (!force && size === DATA_TABLE_COLUMN_SIZE) {
506
+ const { force = false, lockMax = false, minWidth, maxWidth } = options ?? {};
507
+ if (lockMax) {
508
+ return {
509
+ width: size,
510
+ minWidth: size,
511
+ maxWidth: size
512
+ };
513
+ }
514
+ const hasExplicitSize = force || size !== DATA_TABLE_COLUMN_SIZE;
515
+ if (!hasExplicitSize && minWidth == null && maxWidth == null) {
508
516
  return void 0;
509
517
  }
510
- return {
511
- width: size,
512
- minWidth: size,
513
- ...lockMax ? { maxWidth: size } : {}
514
- };
518
+ const style = {};
519
+ if (hasExplicitSize) {
520
+ style.width = size;
521
+ style.minWidth = minWidth ?? size;
522
+ } else if (minWidth != null) {
523
+ style.minWidth = minWidth;
524
+ }
525
+ if (maxWidth != null) {
526
+ style.maxWidth = maxWidth;
527
+ }
528
+ return style;
515
529
  }
516
530
 
517
531
  // src/components/ui/table/features/inline-search/inlineSearch.ts
@@ -862,23 +876,49 @@ var useConvertTreeData = ({
862
876
  function getRowFieldValue(row, key) {
863
877
  return row[key];
864
878
  }
865
- function computeRowSpans(data, rowSpanKey) {
879
+ function normalizeRowSpanParent(value) {
880
+ if (!value) return [];
881
+ return typeof value === "string" ? [value] : [...value];
882
+ }
883
+ function toParentSpanList(parentSpans) {
884
+ if (!parentSpans?.length) return [];
885
+ const first = parentSpans[0];
886
+ if (!Array.isArray(first)) {
887
+ return [parentSpans];
888
+ }
889
+ return parentSpans;
890
+ }
891
+ function buildStartRowLookup(spans) {
892
+ const startRows = new Array(spans.length);
893
+ let origin = 0;
894
+ for (let i = 0; i < spans.length; i++) {
895
+ if ((spans[i]?.rowSpan ?? 1) > 0) origin = i;
896
+ startRows[i] = origin;
897
+ }
898
+ return startRows;
899
+ }
900
+ function sharesParentGroup(parentStartRows, rowIndex) {
901
+ if (parentStartRows.length === 0 || rowIndex <= 0) return true;
902
+ return parentStartRows.every(
903
+ (startRows) => startRows[rowIndex - 1] === startRows[rowIndex]
904
+ );
905
+ }
906
+ function computeRowSpans(data, rowSpanKey, parentSpans) {
866
907
  if (data.length === 0) return [];
908
+ const parentStartRows = toParentSpanList(parentSpans).map(buildStartRowLookup);
867
909
  const result = [];
868
910
  for (let index = 0; index < data.length; index++) {
869
911
  const currentValue = getRowFieldValue(data[index], rowSpanKey);
870
912
  const previousValue = index > 0 ? getRowFieldValue(data[index - 1], rowSpanKey) : void 0;
871
- if (index > 0 && currentValue === previousValue) {
913
+ if (index > 0 && currentValue === previousValue && sharesParentGroup(parentStartRows, index)) {
872
914
  result.push({ rowSpan: 0, isFirstInGroup: false });
873
915
  continue;
874
916
  }
875
917
  let span = 1;
876
918
  for (let nextIndex = index + 1; nextIndex < data.length; nextIndex++) {
877
- if (getRowFieldValue(data[nextIndex], rowSpanKey) === currentValue) {
878
- span++;
879
- } else {
880
- break;
881
- }
919
+ if (getRowFieldValue(data[nextIndex], rowSpanKey) !== currentValue) break;
920
+ if (!sharesParentGroup(parentStartRows, nextIndex)) break;
921
+ span++;
882
922
  }
883
923
  result.push({ rowSpan: span, isFirstInGroup: true });
884
924
  }
@@ -900,10 +940,50 @@ function resolveRowSpanAt(rowSpans, rowIndex) {
900
940
  }
901
941
  return { startRow: rowIndex, rowSpan: 1 };
902
942
  }
943
+ function findRowSpanColumn(spec, ref) {
944
+ return spec.find((column) => column.columnId === ref) ?? spec.find((column) => column.rowSpanKey === ref);
945
+ }
903
946
  function buildColumnRowSpanMap(data, columnKeys) {
904
947
  const map = /* @__PURE__ */ new Map();
905
- for (const { columnId, rowSpanKey } of columnKeys) {
906
- map.set(columnId, computeRowSpans(data, rowSpanKey));
948
+ const visiting = /* @__PURE__ */ new Set();
949
+ const warnedCycles = /* @__PURE__ */ new Set();
950
+ const virtualParents = /* @__PURE__ */ new Map();
951
+ const spansForColumn = (columnId) => {
952
+ const cached = map.get(columnId);
953
+ if (cached !== void 0) return cached;
954
+ const column = columnKeys.find((item) => item.columnId === columnId);
955
+ if (!column) return void 0;
956
+ if (visiting.has(columnId)) {
957
+ if (!warnedCycles.has(columnId)) {
958
+ warnedCycles.add(columnId);
959
+ console.warn(
960
+ `[rowSpan] rowSpanParent cycle detected at column "${columnId}"; dropping the cyclic parent reference.`
961
+ );
962
+ }
963
+ return void 0;
964
+ }
965
+ visiting.add(columnId);
966
+ const parentSpans = (column.rowSpanParent ?? []).map((ref) => spansForParentRef(ref)).filter((spans2) => Boolean(spans2));
967
+ visiting.delete(columnId);
968
+ const spans = computeRowSpans(
969
+ data,
970
+ column.rowSpanKey,
971
+ parentSpans.length > 0 ? parentSpans : void 0
972
+ );
973
+ map.set(columnId, spans);
974
+ return spans;
975
+ };
976
+ const spansForParentRef = (ref) => {
977
+ const parentColumn = findRowSpanColumn(columnKeys, ref);
978
+ if (parentColumn) return spansForColumn(parentColumn.columnId);
979
+ const cached = virtualParents.get(ref);
980
+ if (cached !== void 0) return cached;
981
+ const spans = computeRowSpans(data, ref);
982
+ virtualParents.set(ref, spans);
983
+ return spans;
984
+ };
985
+ for (const column of columnKeys) {
986
+ spansForColumn(column.columnId);
907
987
  }
908
988
  return map;
909
989
  }
@@ -919,7 +999,8 @@ function collectRowSpanColumns(columns) {
919
999
  if (!columnId || !columnDef.meta?.rowSpan) continue;
920
1000
  result.push({
921
1001
  columnId,
922
- rowSpanKey: columnDef.meta.rowSpanKey ?? columnId
1002
+ rowSpanKey: columnDef.meta.rowSpanKey ?? columnId,
1003
+ rowSpanParent: normalizeRowSpanParent(columnDef.meta.rowSpanParent)
923
1004
  });
924
1005
  }
925
1006
  };
@@ -1312,7 +1393,9 @@ function DataTableRow({
1312
1393
  const hasSelectionEdges = hasCellSelectionEdges(selectionEdgeStyle);
1313
1394
  const sizeStyle = getColumnSizeStyle(cell.column.getSize(), {
1314
1395
  force: enableColumnResize,
1315
- lockMax: enableColumnResize
1396
+ lockMax: enableColumnResize,
1397
+ minWidth: meta?.minWidth,
1398
+ maxWidth: meta?.maxWidth
1316
1399
  });
1317
1400
  const freezeOffset = enableColumnFreeze ? freezeOffsets.get(columnId) : void 0;
1318
1401
  const freezeStyle = getColumnFreezeStyle(freezeOffset);
@@ -4158,7 +4241,9 @@ function DataTable({
4158
4241
  const canResize = enableColumnResize && header.column.getCanResize();
4159
4242
  const sizeStyle = getColumnSizeStyle(header.getSize(), {
4160
4243
  force: enableColumnResize,
4161
- lockMax: enableColumnResize
4244
+ lockMax: enableColumnResize,
4245
+ minWidth: header.column.columnDef.meta?.minWidth,
4246
+ maxWidth: header.column.columnDef.meta?.maxWidth
4162
4247
  });
4163
4248
  const freezeOffset = enableColumnFreeze ? resolveHeaderFreezeOffset(header.column, freezeOffsets) : void 0;
4164
4249
  const freezeStyle = getColumnFreezeStyle(freezeOffset, {
@@ -4398,12 +4483,15 @@ function buildColumnDef(props, sort, onSort) {
4398
4483
  width,
4399
4484
  minWidth,
4400
4485
  maxWidth,
4486
+ minResizeWidth,
4487
+ maxResizeWidth,
4401
4488
  resizable,
4402
4489
  reorderable,
4403
4490
  frozen,
4404
4491
  align,
4405
4492
  rowSpan,
4406
4493
  rowSpanKey,
4494
+ rowSpanParent,
4407
4495
  editable,
4408
4496
  editType,
4409
4497
  editInputProps,
@@ -4417,8 +4505,8 @@ function buildColumnDef(props, sort, onSort) {
4417
4505
  id: field,
4418
4506
  ...!virtual ? { accessorKey: field } : {},
4419
4507
  size: width ?? DATA_TABLE_COLUMN_SIZE,
4420
- ...minWidth != null ? { minSize: minWidth } : {},
4421
- ...maxWidth != null ? { maxSize: maxWidth } : {},
4508
+ ...minResizeWidth != null ? { minSize: minResizeWidth } : {},
4509
+ ...maxResizeWidth != null ? { maxSize: maxResizeWidth } : {},
4422
4510
  ...resizable === false ? { enableResizing: false } : {},
4423
4511
  header: sortable ? () => /* @__PURE__ */ jsx8(
4424
4512
  SortableHeader,
@@ -4438,6 +4526,7 @@ function buildColumnDef(props, sort, onSort) {
4438
4526
  align,
4439
4527
  rowSpan,
4440
4528
  rowSpanKey,
4529
+ rowSpanParent,
4441
4530
  editable,
4442
4531
  editType,
4443
4532
  editInputProps,
@@ -4446,6 +4535,8 @@ function buildColumnDef(props, sort, onSort) {
4446
4535
  cellRender: render,
4447
4536
  frozen,
4448
4537
  reorderable,
4538
+ minWidth,
4539
+ maxWidth,
4449
4540
  className,
4450
4541
  headerClassName
4451
4542
  }
package/dist/core.cjs CHANGED
@@ -2296,23 +2296,49 @@ function applySelectionUpdater(mode, updater, previous) {
2296
2296
  function getRowFieldValue(row, key) {
2297
2297
  return row[key];
2298
2298
  }
2299
- function computeRowSpans(data, rowSpanKey) {
2299
+ function normalizeRowSpanParent(value) {
2300
+ if (!value) return [];
2301
+ return typeof value === "string" ? [value] : [...value];
2302
+ }
2303
+ function toParentSpanList(parentSpans) {
2304
+ if (!parentSpans?.length) return [];
2305
+ const first = parentSpans[0];
2306
+ if (!Array.isArray(first)) {
2307
+ return [parentSpans];
2308
+ }
2309
+ return parentSpans;
2310
+ }
2311
+ function buildStartRowLookup(spans) {
2312
+ const startRows = new Array(spans.length);
2313
+ let origin = 0;
2314
+ for (let i = 0; i < spans.length; i++) {
2315
+ if ((spans[i]?.rowSpan ?? 1) > 0) origin = i;
2316
+ startRows[i] = origin;
2317
+ }
2318
+ return startRows;
2319
+ }
2320
+ function sharesParentGroup(parentStartRows, rowIndex) {
2321
+ if (parentStartRows.length === 0 || rowIndex <= 0) return true;
2322
+ return parentStartRows.every(
2323
+ (startRows) => startRows[rowIndex - 1] === startRows[rowIndex]
2324
+ );
2325
+ }
2326
+ function computeRowSpans(data, rowSpanKey, parentSpans) {
2300
2327
  if (data.length === 0) return [];
2328
+ const parentStartRows = toParentSpanList(parentSpans).map(buildStartRowLookup);
2301
2329
  const result = [];
2302
2330
  for (let index = 0; index < data.length; index++) {
2303
2331
  const currentValue = getRowFieldValue(data[index], rowSpanKey);
2304
2332
  const previousValue = index > 0 ? getRowFieldValue(data[index - 1], rowSpanKey) : void 0;
2305
- if (index > 0 && currentValue === previousValue) {
2333
+ if (index > 0 && currentValue === previousValue && sharesParentGroup(parentStartRows, index)) {
2306
2334
  result.push({ rowSpan: 0, isFirstInGroup: false });
2307
2335
  continue;
2308
2336
  }
2309
2337
  let span = 1;
2310
2338
  for (let nextIndex = index + 1; nextIndex < data.length; nextIndex++) {
2311
- if (getRowFieldValue(data[nextIndex], rowSpanKey) === currentValue) {
2312
- span++;
2313
- } else {
2314
- break;
2315
- }
2339
+ if (getRowFieldValue(data[nextIndex], rowSpanKey) !== currentValue) break;
2340
+ if (!sharesParentGroup(parentStartRows, nextIndex)) break;
2341
+ span++;
2316
2342
  }
2317
2343
  result.push({ rowSpan: span, isFirstInGroup: true });
2318
2344
  }
@@ -2334,10 +2360,50 @@ function resolveRowSpanAt(rowSpans, rowIndex) {
2334
2360
  }
2335
2361
  return { startRow: rowIndex, rowSpan: 1 };
2336
2362
  }
2363
+ function findRowSpanColumn(spec, ref) {
2364
+ return spec.find((column) => column.columnId === ref) ?? spec.find((column) => column.rowSpanKey === ref);
2365
+ }
2337
2366
  function buildColumnRowSpanMap(data, columnKeys) {
2338
2367
  const map = /* @__PURE__ */ new Map();
2339
- for (const { columnId, rowSpanKey } of columnKeys) {
2340
- map.set(columnId, computeRowSpans(data, rowSpanKey));
2368
+ const visiting = /* @__PURE__ */ new Set();
2369
+ const warnedCycles = /* @__PURE__ */ new Set();
2370
+ const virtualParents = /* @__PURE__ */ new Map();
2371
+ const spansForColumn = (columnId) => {
2372
+ const cached = map.get(columnId);
2373
+ if (cached !== void 0) return cached;
2374
+ const column = columnKeys.find((item) => item.columnId === columnId);
2375
+ if (!column) return void 0;
2376
+ if (visiting.has(columnId)) {
2377
+ if (!warnedCycles.has(columnId)) {
2378
+ warnedCycles.add(columnId);
2379
+ console.warn(
2380
+ `[rowSpan] rowSpanParent cycle detected at column "${columnId}"; dropping the cyclic parent reference.`
2381
+ );
2382
+ }
2383
+ return void 0;
2384
+ }
2385
+ visiting.add(columnId);
2386
+ const parentSpans = (column.rowSpanParent ?? []).map((ref) => spansForParentRef(ref)).filter((spans2) => Boolean(spans2));
2387
+ visiting.delete(columnId);
2388
+ const spans = computeRowSpans(
2389
+ data,
2390
+ column.rowSpanKey,
2391
+ parentSpans.length > 0 ? parentSpans : void 0
2392
+ );
2393
+ map.set(columnId, spans);
2394
+ return spans;
2395
+ };
2396
+ const spansForParentRef = (ref) => {
2397
+ const parentColumn = findRowSpanColumn(columnKeys, ref);
2398
+ if (parentColumn) return spansForColumn(parentColumn.columnId);
2399
+ const cached = virtualParents.get(ref);
2400
+ if (cached !== void 0) return cached;
2401
+ const spans = computeRowSpans(data, ref);
2402
+ virtualParents.set(ref, spans);
2403
+ return spans;
2404
+ };
2405
+ for (const column of columnKeys) {
2406
+ spansForColumn(column.columnId);
2341
2407
  }
2342
2408
  return map;
2343
2409
  }
@@ -2353,7 +2419,8 @@ function collectRowSpanColumns(columns) {
2353
2419
  if (!columnId || !columnDef.meta?.rowSpan) continue;
2354
2420
  result.push({
2355
2421
  columnId,
2356
- rowSpanKey: columnDef.meta.rowSpanKey ?? columnId
2422
+ rowSpanKey: columnDef.meta.rowSpanKey ?? columnId,
2423
+ rowSpanParent: normalizeRowSpanParent(columnDef.meta.rowSpanParent)
2357
2424
  });
2358
2425
  }
2359
2426
  };
@@ -3055,15 +3122,29 @@ function ResolvedTableCell({
3055
3122
 
3056
3123
  // src/components/ui/table/features/column-resize/columnResize.ts
3057
3124
  function getColumnSizeStyle(size, options) {
3058
- const { force = false, lockMax = false } = options ?? {};
3059
- if (!force && size === DATA_TABLE_COLUMN_SIZE) {
3125
+ const { force = false, lockMax = false, minWidth, maxWidth } = options ?? {};
3126
+ if (lockMax) {
3127
+ return {
3128
+ width: size,
3129
+ minWidth: size,
3130
+ maxWidth: size
3131
+ };
3132
+ }
3133
+ const hasExplicitSize = force || size !== DATA_TABLE_COLUMN_SIZE;
3134
+ if (!hasExplicitSize && minWidth == null && maxWidth == null) {
3060
3135
  return void 0;
3061
3136
  }
3062
- return {
3063
- width: size,
3064
- minWidth: size,
3065
- ...lockMax ? { maxWidth: size } : {}
3066
- };
3137
+ const style = {};
3138
+ if (hasExplicitSize) {
3139
+ style.width = size;
3140
+ style.minWidth = minWidth ?? size;
3141
+ } else if (minWidth != null) {
3142
+ style.minWidth = minWidth;
3143
+ }
3144
+ if (maxWidth != null) {
3145
+ style.maxWidth = maxWidth;
3146
+ }
3147
+ return style;
3067
3148
  }
3068
3149
 
3069
3150
  // src/components/ui/table/features/column-reorder/useColumnReorder.ts