react-glide-table 1.1.9 → 1.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/core.cjs CHANGED
@@ -29,6 +29,7 @@ __export(core_exports, {
29
29
  applyCellEdit: () => applyCellEdit,
30
30
  applyFillData: () => applyFillData,
31
31
  applySelectionUpdater: () => applySelectionUpdater,
32
+ buildColumnFreezeOffsets: () => buildColumnFreezeOffsets,
32
33
  buildColumnRowSpanMap: () => buildColumnRowSpanMap,
33
34
  buildRowsPastePayload: () => buildRowsPastePayload,
34
35
  canExpandRow: () => canExpandRow,
@@ -40,6 +41,9 @@ __export(core_exports, {
40
41
  getCellEditDraftValue: () => getCellEditDraftValue,
41
42
  getCellSelectionEdgeStyle: () => getCellSelectionEdgeStyle,
42
43
  getColumnEditType: () => getColumnEditType,
44
+ getColumnFreezeEdgeAttr: () => getColumnFreezeEdgeAttr,
45
+ getColumnFreezeStyle: () => getColumnFreezeStyle,
46
+ getColumnSizeStyle: () => getColumnSizeStyle,
43
47
  getRowIndexInMergedCell: () => getRowIndexInMergedCell,
44
48
  hasCellSelectionEdges: () => hasCellSelectionEdges,
45
49
  isCellInSelection: () => isCellInSelection,
@@ -49,6 +53,7 @@ __export(core_exports, {
49
53
  parseCellEditValue: () => parseCellEditValue,
50
54
  parseClipboardTSV: () => parseClipboardTSV,
51
55
  parseClipboardTSVWithDepths: () => parseClipboardTSVWithDepths,
56
+ resolveColumnFreezeSide: () => resolveColumnFreezeSide,
52
57
  resolveDataTableLabels: () => resolveDataTableLabels,
53
58
  resolvePasteColumnIds: () => resolvePasteColumnIds,
54
59
  resolveRowSelection: () => resolveRowSelection,
@@ -71,7 +76,8 @@ var DEFAULT_DATA_TABLE_LABELS = {
71
76
  loading: "Loading...",
72
77
  selection: (selectedCount) => selectedCount > 0 ? `\u2713 ${selectedCount} selected` : null,
73
78
  expandRow: "Expand row",
74
- collapseRow: "Collapse row"
79
+ collapseRow: "Collapse row",
80
+ resizeColumn: "Resize column"
75
81
  };
76
82
  function resolveDataTableLabels(partial) {
77
83
  return {
@@ -94,6 +100,9 @@ var import_react4 = require("react");
94
100
  // src/components/ui/table/constants.ts
95
101
  var DATA_TABLE_ROW_HEIGHT = 44;
96
102
  var DATA_TABLE_VIRTUAL_OVERSCAN = 8;
103
+ var DATA_TABLE_COLUMN_SIZE = 150;
104
+ var DATA_TABLE_COLUMN_MIN_SIZE = 40;
105
+ var DATA_TABLE_COLUMN_MAX_SIZE = 800;
97
106
 
98
107
  // src/components/ui/table/features/cell-edit/useCellEdit.ts
99
108
  var import_react = require("react");
@@ -984,6 +993,89 @@ function useCellSelection({
984
993
  };
985
994
  }
986
995
 
996
+ // src/components/ui/table/features/column-freeze/columnFreeze.ts
997
+ var HEADER_Z_BASE = 30;
998
+ var BODY_Z_BASE = 5;
999
+ function resolveColumnFreezeSide(frozen) {
1000
+ if (frozen === true || frozen === "left") return "left";
1001
+ if (frozen === "right") return "right";
1002
+ return void 0;
1003
+ }
1004
+ function getColumnFreezeEdgeAttr(offset) {
1005
+ if (!offset) return void 0;
1006
+ if (offset.edgeLeft && offset.edgeRight) return "both";
1007
+ if (offset.edgeLeft) return "left";
1008
+ if (offset.edgeRight) return "right";
1009
+ return void 0;
1010
+ }
1011
+ function buildColumnFreezeOffsets(columns) {
1012
+ const result = /* @__PURE__ */ new Map();
1013
+ let leftOffset = 0;
1014
+ const leftIds = [];
1015
+ for (const column of columns) {
1016
+ if (column.side !== "left") continue;
1017
+ leftIds.push(column.id);
1018
+ result.set(column.id, {
1019
+ side: "left",
1020
+ offset: leftOffset,
1021
+ isEdge: false,
1022
+ edgeLeft: false,
1023
+ edgeRight: false,
1024
+ stack: 0
1025
+ });
1026
+ leftOffset += column.size;
1027
+ }
1028
+ leftIds.forEach((id, index) => {
1029
+ const entry = result.get(id);
1030
+ if (!entry) return;
1031
+ entry.stack = leftIds.length - index;
1032
+ });
1033
+ let rightOffset = 0;
1034
+ const rightIds = [];
1035
+ for (let index = columns.length - 1; index >= 0; index -= 1) {
1036
+ const column = columns[index];
1037
+ if (!column || column.side !== "right") continue;
1038
+ rightIds.push(column.id);
1039
+ result.set(column.id, {
1040
+ side: "right",
1041
+ offset: rightOffset,
1042
+ isEdge: false,
1043
+ edgeLeft: false,
1044
+ edgeRight: false,
1045
+ stack: 0
1046
+ });
1047
+ rightOffset += column.size;
1048
+ }
1049
+ rightIds.forEach((id, index) => {
1050
+ const entry = result.get(id);
1051
+ if (!entry) return;
1052
+ entry.stack = rightIds.length - index;
1053
+ });
1054
+ columns.forEach((column, index) => {
1055
+ if (!column.side) return;
1056
+ const entry = result.get(column.id);
1057
+ if (!entry) return;
1058
+ const prevSide = index > 0 ? columns[index - 1]?.side : void 0;
1059
+ const nextSide = index < columns.length - 1 ? columns[index + 1]?.side : void 0;
1060
+ entry.edgeLeft = prevSide !== column.side;
1061
+ entry.edgeRight = nextSide !== column.side;
1062
+ if (index === 0) entry.edgeLeft = false;
1063
+ if (index === columns.length - 1) entry.edgeRight = false;
1064
+ entry.isEdge = entry.edgeLeft || entry.edgeRight;
1065
+ });
1066
+ return result;
1067
+ }
1068
+ function getColumnFreezeStyle(offset, options) {
1069
+ if (!offset) return void 0;
1070
+ const zBase = options?.isHeader ? HEADER_Z_BASE : BODY_Z_BASE;
1071
+ return {
1072
+ position: "sticky",
1073
+ ...offset.side === "left" ? { left: offset.offset } : { right: offset.offset },
1074
+ zIndex: zBase + offset.stack,
1075
+ ...options?.isHeader ? { top: 0 } : {}
1076
+ };
1077
+ }
1078
+
987
1079
  // src/components/ui/table/features/row-expand/row-expand.ts
988
1080
  var import_react3 = require("react");
989
1081
  function getFieldValue(row, key) {
@@ -1249,6 +1341,7 @@ function collectRowSpanColumns(columns) {
1249
1341
  }
1250
1342
 
1251
1343
  // src/core/useGlideTable.ts
1344
+ var EMPTY_COLUMN_FREEZE_OFFSETS = /* @__PURE__ */ new Map();
1252
1345
  function useGlideTable(options) {
1253
1346
  const {
1254
1347
  data,
@@ -1284,7 +1377,12 @@ function useGlideTable(options) {
1284
1377
  enableInsertPaste,
1285
1378
  enableVirtualization = true,
1286
1379
  estimateRowHeight = DATA_TABLE_ROW_HEIGHT,
1287
- virtualOverscan = DATA_TABLE_VIRTUAL_OVERSCAN
1380
+ virtualOverscan = DATA_TABLE_VIRTUAL_OVERSCAN,
1381
+ enableColumnResize = false,
1382
+ columnSizing: controlledColumnSizing,
1383
+ onColumnSizingChange,
1384
+ columnResizeMode = "onChange",
1385
+ enableColumnFreeze = false
1288
1386
  } = options;
1289
1387
  const labels = (0, import_react4.useMemo)(() => {
1290
1388
  const resolved = resolveDataTableLabels(labelsProp);
@@ -1298,6 +1396,7 @@ function useGlideTable(options) {
1298
1396
  const enableExpand = Boolean(toggleField);
1299
1397
  const resolvedEnableSubtreeCopy = enableSubtreeCopy ?? enableExpand;
1300
1398
  const [internalRowSelection, setInternalRowSelection] = (0, import_react4.useState)({});
1399
+ const [internalColumnSizing, setInternalColumnSizing] = (0, import_react4.useState)({});
1301
1400
  const [internalExpandedRows, setInternalExpandedRows] = (0, import_react4.useState)(
1302
1401
  () => /* @__PURE__ */ new Set()
1303
1402
  );
@@ -1316,6 +1415,7 @@ function useGlideTable(options) {
1316
1415
  controlledRowSelection,
1317
1416
  internalRowSelection
1318
1417
  );
1418
+ const columnSizing = controlledColumnSizing ?? internalColumnSizing;
1319
1419
  const expandedRows = controlledExpandedRows ?? internalExpandedRows;
1320
1420
  const handleExpandedRowsChange = (0, import_react4.useCallback)(
1321
1421
  (next) => {
@@ -1341,9 +1441,27 @@ function useGlideTable(options) {
1341
1441
  const table = (0, import_react_table.useReactTable)({
1342
1442
  data: tableData,
1343
1443
  columns,
1444
+ ...enableColumnResize ? {
1445
+ defaultColumn: {
1446
+ minSize: DATA_TABLE_COLUMN_MIN_SIZE,
1447
+ maxSize: DATA_TABLE_COLUMN_MAX_SIZE
1448
+ }
1449
+ } : {},
1450
+ enableColumnResizing: enableColumnResize,
1451
+ columnResizeMode,
1344
1452
  state: {
1345
- rowSelection: rowSelectionMode === "none" ? {} : rowSelection
1453
+ rowSelection: rowSelectionMode === "none" ? {} : rowSelection,
1454
+ ...enableColumnResize ? { columnSizing } : {}
1346
1455
  },
1456
+ onColumnSizingChange: enableColumnResize ? (updater) => {
1457
+ if (onColumnSizingChange) {
1458
+ onColumnSizingChange(updater);
1459
+ return;
1460
+ }
1461
+ setInternalColumnSizing(
1462
+ (previous) => typeof updater === "function" ? updater(previous) : updater
1463
+ );
1464
+ } : void 0,
1347
1465
  enableRowSelection: rowSelectionMode === "none" ? false : getRowCanSelect ? (row) => getRowCanSelect(row.original, row.index) : true,
1348
1466
  enableMultiRowSelection: rowSelectionMode === "multi",
1349
1467
  onRowSelectionChange: (updater) => {
@@ -1374,6 +1492,17 @@ function useGlideTable(options) {
1374
1492
  const selectedCount = selectedRows.length;
1375
1493
  const rows = table.getRowModel().rows;
1376
1494
  const columnCount = table.getAllLeafColumns().length || 1;
1495
+ const visibleLeafColumns = table.getVisibleLeafColumns();
1496
+ const columnFreezeOffsets = (0, import_react4.useMemo)(() => {
1497
+ if (!enableColumnFreeze) return EMPTY_COLUMN_FREEZE_OFFSETS;
1498
+ return buildColumnFreezeOffsets(
1499
+ visibleLeafColumns.map((column) => ({
1500
+ id: column.id,
1501
+ size: column.getSize(),
1502
+ side: resolveColumnFreezeSide(column.columnDef.meta?.frozen)
1503
+ }))
1504
+ );
1505
+ }, [enableColumnFreeze, visibleLeafColumns, columnSizing]);
1377
1506
  const rowVirtualizer = (0, import_react_virtual.useVirtualizer)({
1378
1507
  count: shouldVirtualize ? rows.length : 0,
1379
1508
  getScrollElement: () => scrollRef.current,
@@ -1490,6 +1619,13 @@ function useGlideTable(options) {
1490
1619
  onToggleExpand: handleToggleExpand,
1491
1620
  expandRowLabel: labels.expandRow,
1492
1621
  collapseRowLabel: labels.collapseRow
1622
+ },
1623
+ columnResize: {
1624
+ enableColumnResize
1625
+ },
1626
+ columnFreeze: {
1627
+ enableColumnFreeze,
1628
+ offsets: columnFreezeOffsets
1493
1629
  }
1494
1630
  };
1495
1631
  }, [
@@ -1522,7 +1658,10 @@ function useGlideTable(options) {
1522
1658
  preventExpand,
1523
1659
  handleToggleExpand,
1524
1660
  labels.expandRow,
1525
- labels.collapseRow
1661
+ labels.collapseRow,
1662
+ enableColumnResize,
1663
+ enableColumnFreeze,
1664
+ columnFreezeOffsets
1526
1665
  ]);
1527
1666
  const copySelectionRef = (0, import_react4.useRef)(copySelection);
1528
1667
  (0, import_react4.useEffect)(() => {
@@ -1543,6 +1682,8 @@ function useGlideTable(options) {
1543
1682
  loadingText: labels.loading,
1544
1683
  selectionLabel: labels.selection,
1545
1684
  enableCellSelection,
1685
+ enableColumnResize,
1686
+ enableColumnFreeze,
1546
1687
  shouldVirtualize,
1547
1688
  scrollRef,
1548
1689
  rowVirtualizer,
@@ -1555,6 +1696,19 @@ function useGlideTable(options) {
1555
1696
  copySelection: stableCopySelection
1556
1697
  };
1557
1698
  }
1699
+
1700
+ // src/components/ui/table/features/column-resize/columnResize.ts
1701
+ function getColumnSizeStyle(size, options) {
1702
+ const { force = false, lockMax = false } = options ?? {};
1703
+ if (!force && size === DATA_TABLE_COLUMN_SIZE) {
1704
+ return void 0;
1705
+ }
1706
+ return {
1707
+ width: size,
1708
+ minWidth: size,
1709
+ ...lockMax ? { maxWidth: size } : {}
1710
+ };
1711
+ }
1558
1712
  // Annotate the CommonJS export names for ESM import in node:
1559
1713
  0 && (module.exports = {
1560
1714
  CELL_SELECTION_EDGES_CLASS,
@@ -1566,6 +1720,7 @@ function useGlideTable(options) {
1566
1720
  applyCellEdit,
1567
1721
  applyFillData,
1568
1722
  applySelectionUpdater,
1723
+ buildColumnFreezeOffsets,
1569
1724
  buildColumnRowSpanMap,
1570
1725
  buildRowsPastePayload,
1571
1726
  canExpandRow,
@@ -1577,6 +1732,9 @@ function useGlideTable(options) {
1577
1732
  getCellEditDraftValue,
1578
1733
  getCellSelectionEdgeStyle,
1579
1734
  getColumnEditType,
1735
+ getColumnFreezeEdgeAttr,
1736
+ getColumnFreezeStyle,
1737
+ getColumnSizeStyle,
1580
1738
  getRowIndexInMergedCell,
1581
1739
  hasCellSelectionEdges,
1582
1740
  isCellInSelection,
@@ -1586,6 +1744,7 @@ function useGlideTable(options) {
1586
1744
  parseCellEditValue,
1587
1745
  parseClipboardTSV,
1588
1746
  parseClipboardTSVWithDepths,
1747
+ resolveColumnFreezeSide,
1589
1748
  resolveDataTableLabels,
1590
1749
  resolvePasteColumnIds,
1591
1750
  resolveRowSelection,
package/dist/core.d.cts CHANGED
@@ -1,10 +1,10 @@
1
- import { C as CellEditType, a as DataTableClassNames, R as RowSelectionMode, d as DataTableProps, c as DataTableLabels, b as DataTableCopyActions, P as PasteMode, f as RowsPastePayload } from './types-xxzMLUwM.cjs';
2
- export { D as DEFAULT_DATA_TABLE_LABELS, r as resolveDataTableLabels } from './types-xxzMLUwM.cjs';
1
+ import { p as CellEditType, e as DataTableClassNames, R as RowSelectionMode, c as ColumnFreezeOffset, h as DataTableProps, g as DataTableLabels, f as DataTableCopyActions, P as PasteMode, j as RowsPastePayload } from './types-B4uHdkrY.cjs';
2
+ export { C as ColumnFreezeColumnInput, a as ColumnFreezeEdgeSide, b as ColumnFreezeMeta, d as ColumnFreezeSide, D as DEFAULT_DATA_TABLE_LABELS, l as buildColumnFreezeOffsets, m as getColumnFreezeEdgeAttr, n as getColumnFreezeStyle, r as resolveColumnFreezeSide, o as resolveDataTableLabels } from './types-B4uHdkrY.cjs';
3
3
  import { Row, ColumnDef, Table, Updater, RowSelectionState } from '@tanstack/react-table';
4
- export { ColumnDef, RowSelectionState } from '@tanstack/react-table';
4
+ export { ColumnDef, ColumnResizeMode, ColumnSizingState, RowSelectionState } from '@tanstack/react-table';
5
5
  import { Virtualizer, VirtualItem } from '@tanstack/react-virtual';
6
6
  import * as react from 'react';
7
- import { RefObject } from 'react';
7
+ import { RefObject, CSSProperties } from 'react';
8
8
 
9
9
  /** Neutral default field names for tree conversion */
10
10
  declare const DEFAULT_TREE_ID_FIELD = "id";
@@ -170,6 +170,13 @@ type DataTableRowContextValue = {
170
170
  expandRowLabel: string;
171
171
  collapseRowLabel: string;
172
172
  };
173
+ columnResize: {
174
+ enableColumnResize: boolean;
175
+ };
176
+ columnFreeze: {
177
+ enableColumnFreeze: boolean;
178
+ offsets: Map<string, ColumnFreezeOffset>;
179
+ };
173
180
  };
174
181
 
175
182
  type UseGlideTableOptions<T extends Record<string, unknown>> = Omit<DataTableProps<T>, "className" | "classNames" | "slots" | "summary" | "toolbar" | "isPending" | "totalCount" | "filteredCount">;
@@ -184,6 +191,8 @@ type UseGlideTableResult<T extends Record<string, unknown>> = {
184
191
  loadingText: string;
185
192
  selectionLabel: DataTableLabels["selection"];
186
193
  enableCellSelection: boolean;
194
+ enableColumnResize: boolean;
195
+ enableColumnFreeze: boolean;
187
196
  shouldVirtualize: boolean;
188
197
  scrollRef: RefObject<HTMLDivElement | null>;
189
198
  rowVirtualizer: Virtualizer<HTMLDivElement, Element>;
@@ -212,6 +221,12 @@ declare function useCellEdit<T extends Record<string, unknown>>({ data, rows, on
212
221
  cancelEdit: () => void;
213
222
  };
214
223
 
224
+ /** Width styles for header/body cells when column sizing is active. */
225
+ declare function getColumnSizeStyle(size: number, options?: {
226
+ force?: boolean;
227
+ lockMax?: boolean;
228
+ }): CSSProperties | undefined;
229
+
215
230
  type ParsedClipboardTSV = {
216
231
  values: string[][];
217
232
  /**
@@ -327,4 +342,4 @@ declare const useConvertTreeData: <T extends Record<string, unknown>>({ data, en
327
342
  declare function resolveRowSelection(mode: RowSelectionMode, controlledSelection: RowSelectionState | undefined, internalSelection: RowSelectionState): RowSelectionState;
328
343
  declare function applySelectionUpdater(mode: RowSelectionMode, updater: Updater<RowSelectionState>, previous: RowSelectionState): RowSelectionState;
329
344
 
330
- export { CELL_SELECTION_EDGES_CLASS, type CellSelectionBounds, type ColumnRowSpanMap, type CopyRowEntry, type CopySelectionMode, DEFAULT_TREE_CHILDREN_FIELD, DEFAULT_TREE_ID_FIELD, DEFAULT_TREE_PARENT_ID_FIELD, DEFAULT_TREE_QTY_FIELD, DataTableCopyActions, DataTableLabels, DataTableProps, type DragState, type EditingCell, PasteMode, RowSelectionMode, type RowSpanInfo, RowsPastePayload, type TreeRow, type UseConvertTreeDataParams, type UseGlideTableOptions, type UseGlideTableResult, applyCellEdit, applyFillData, applySelectionUpdater, buildColumnRowSpanMap, buildRowsPastePayload, canExpandRow, collectCopyRowEntries, collectCopyRows, collectFillChanges, collectRowSpanColumns, flattenSubtreeRows, getCellEditDraftValue, getCellSelectionEdgeStyle, getColumnEditType, getRowIndexInMergedCell, hasCellSelectionEdges, isCellInSelection, isColumnEditable, isEditablePasteTarget, measureMergedSpanRowHeights, parseCellEditValue, parseClipboardTSV, parseClipboardTSVWithDepths, resolvePasteColumnIds, resolveRowSelection, resolveRowSpanAt, rowRangeToHeightRatios, serializeCopyRowsToTSV, serializeSelectionToTSV, toggleExpandedRowId, useCellEdit, useCellSelection, useConvertTreeData, useGlideTable, writeSelectionToClipboard };
345
+ export { CELL_SELECTION_EDGES_CLASS, type CellSelectionBounds, ColumnFreezeOffset, type ColumnRowSpanMap, type CopyRowEntry, type CopySelectionMode, DEFAULT_TREE_CHILDREN_FIELD, DEFAULT_TREE_ID_FIELD, DEFAULT_TREE_PARENT_ID_FIELD, DEFAULT_TREE_QTY_FIELD, DataTableCopyActions, DataTableLabels, DataTableProps, type DragState, type EditingCell, PasteMode, RowSelectionMode, type RowSpanInfo, RowsPastePayload, type TreeRow, type UseConvertTreeDataParams, type UseGlideTableOptions, type UseGlideTableResult, applyCellEdit, applyFillData, applySelectionUpdater, buildColumnRowSpanMap, buildRowsPastePayload, canExpandRow, collectCopyRowEntries, collectCopyRows, collectFillChanges, collectRowSpanColumns, flattenSubtreeRows, getCellEditDraftValue, getCellSelectionEdgeStyle, getColumnEditType, getColumnSizeStyle, getRowIndexInMergedCell, hasCellSelectionEdges, isCellInSelection, isColumnEditable, isEditablePasteTarget, measureMergedSpanRowHeights, parseCellEditValue, parseClipboardTSV, parseClipboardTSVWithDepths, resolvePasteColumnIds, resolveRowSelection, resolveRowSpanAt, rowRangeToHeightRatios, serializeCopyRowsToTSV, serializeSelectionToTSV, toggleExpandedRowId, useCellEdit, useCellSelection, useConvertTreeData, useGlideTable, writeSelectionToClipboard };
package/dist/core.d.ts CHANGED
@@ -1,10 +1,10 @@
1
- import { C as CellEditType, a as DataTableClassNames, R as RowSelectionMode, d as DataTableProps, c as DataTableLabels, b as DataTableCopyActions, P as PasteMode, f as RowsPastePayload } from './types-xxzMLUwM.js';
2
- export { D as DEFAULT_DATA_TABLE_LABELS, r as resolveDataTableLabels } from './types-xxzMLUwM.js';
1
+ import { p as CellEditType, e as DataTableClassNames, R as RowSelectionMode, c as ColumnFreezeOffset, h as DataTableProps, g as DataTableLabels, f as DataTableCopyActions, P as PasteMode, j as RowsPastePayload } from './types-B4uHdkrY.js';
2
+ export { C as ColumnFreezeColumnInput, a as ColumnFreezeEdgeSide, b as ColumnFreezeMeta, d as ColumnFreezeSide, D as DEFAULT_DATA_TABLE_LABELS, l as buildColumnFreezeOffsets, m as getColumnFreezeEdgeAttr, n as getColumnFreezeStyle, r as resolveColumnFreezeSide, o as resolveDataTableLabels } from './types-B4uHdkrY.js';
3
3
  import { Row, ColumnDef, Table, Updater, RowSelectionState } from '@tanstack/react-table';
4
- export { ColumnDef, RowSelectionState } from '@tanstack/react-table';
4
+ export { ColumnDef, ColumnResizeMode, ColumnSizingState, RowSelectionState } from '@tanstack/react-table';
5
5
  import { Virtualizer, VirtualItem } from '@tanstack/react-virtual';
6
6
  import * as react from 'react';
7
- import { RefObject } from 'react';
7
+ import { RefObject, CSSProperties } from 'react';
8
8
 
9
9
  /** Neutral default field names for tree conversion */
10
10
  declare const DEFAULT_TREE_ID_FIELD = "id";
@@ -170,6 +170,13 @@ type DataTableRowContextValue = {
170
170
  expandRowLabel: string;
171
171
  collapseRowLabel: string;
172
172
  };
173
+ columnResize: {
174
+ enableColumnResize: boolean;
175
+ };
176
+ columnFreeze: {
177
+ enableColumnFreeze: boolean;
178
+ offsets: Map<string, ColumnFreezeOffset>;
179
+ };
173
180
  };
174
181
 
175
182
  type UseGlideTableOptions<T extends Record<string, unknown>> = Omit<DataTableProps<T>, "className" | "classNames" | "slots" | "summary" | "toolbar" | "isPending" | "totalCount" | "filteredCount">;
@@ -184,6 +191,8 @@ type UseGlideTableResult<T extends Record<string, unknown>> = {
184
191
  loadingText: string;
185
192
  selectionLabel: DataTableLabels["selection"];
186
193
  enableCellSelection: boolean;
194
+ enableColumnResize: boolean;
195
+ enableColumnFreeze: boolean;
187
196
  shouldVirtualize: boolean;
188
197
  scrollRef: RefObject<HTMLDivElement | null>;
189
198
  rowVirtualizer: Virtualizer<HTMLDivElement, Element>;
@@ -212,6 +221,12 @@ declare function useCellEdit<T extends Record<string, unknown>>({ data, rows, on
212
221
  cancelEdit: () => void;
213
222
  };
214
223
 
224
+ /** Width styles for header/body cells when column sizing is active. */
225
+ declare function getColumnSizeStyle(size: number, options?: {
226
+ force?: boolean;
227
+ lockMax?: boolean;
228
+ }): CSSProperties | undefined;
229
+
215
230
  type ParsedClipboardTSV = {
216
231
  values: string[][];
217
232
  /**
@@ -327,4 +342,4 @@ declare const useConvertTreeData: <T extends Record<string, unknown>>({ data, en
327
342
  declare function resolveRowSelection(mode: RowSelectionMode, controlledSelection: RowSelectionState | undefined, internalSelection: RowSelectionState): RowSelectionState;
328
343
  declare function applySelectionUpdater(mode: RowSelectionMode, updater: Updater<RowSelectionState>, previous: RowSelectionState): RowSelectionState;
329
344
 
330
- export { CELL_SELECTION_EDGES_CLASS, type CellSelectionBounds, type ColumnRowSpanMap, type CopyRowEntry, type CopySelectionMode, DEFAULT_TREE_CHILDREN_FIELD, DEFAULT_TREE_ID_FIELD, DEFAULT_TREE_PARENT_ID_FIELD, DEFAULT_TREE_QTY_FIELD, DataTableCopyActions, DataTableLabels, DataTableProps, type DragState, type EditingCell, PasteMode, RowSelectionMode, type RowSpanInfo, RowsPastePayload, type TreeRow, type UseConvertTreeDataParams, type UseGlideTableOptions, type UseGlideTableResult, applyCellEdit, applyFillData, applySelectionUpdater, buildColumnRowSpanMap, buildRowsPastePayload, canExpandRow, collectCopyRowEntries, collectCopyRows, collectFillChanges, collectRowSpanColumns, flattenSubtreeRows, getCellEditDraftValue, getCellSelectionEdgeStyle, getColumnEditType, getRowIndexInMergedCell, hasCellSelectionEdges, isCellInSelection, isColumnEditable, isEditablePasteTarget, measureMergedSpanRowHeights, parseCellEditValue, parseClipboardTSV, parseClipboardTSVWithDepths, resolvePasteColumnIds, resolveRowSelection, resolveRowSpanAt, rowRangeToHeightRatios, serializeCopyRowsToTSV, serializeSelectionToTSV, toggleExpandedRowId, useCellEdit, useCellSelection, useConvertTreeData, useGlideTable, writeSelectionToClipboard };
345
+ export { CELL_SELECTION_EDGES_CLASS, type CellSelectionBounds, ColumnFreezeOffset, type ColumnRowSpanMap, type CopyRowEntry, type CopySelectionMode, DEFAULT_TREE_CHILDREN_FIELD, DEFAULT_TREE_ID_FIELD, DEFAULT_TREE_PARENT_ID_FIELD, DEFAULT_TREE_QTY_FIELD, DataTableCopyActions, DataTableLabels, DataTableProps, type DragState, type EditingCell, PasteMode, RowSelectionMode, type RowSpanInfo, RowsPastePayload, type TreeRow, type UseConvertTreeDataParams, type UseGlideTableOptions, type UseGlideTableResult, applyCellEdit, applyFillData, applySelectionUpdater, buildColumnRowSpanMap, buildRowsPastePayload, canExpandRow, collectCopyRowEntries, collectCopyRows, collectFillChanges, collectRowSpanColumns, flattenSubtreeRows, getCellEditDraftValue, getCellSelectionEdgeStyle, getColumnEditType, getColumnSizeStyle, getRowIndexInMergedCell, hasCellSelectionEdges, isCellInSelection, isColumnEditable, isEditablePasteTarget, measureMergedSpanRowHeights, parseCellEditValue, parseClipboardTSV, parseClipboardTSVWithDepths, resolvePasteColumnIds, resolveRowSelection, resolveRowSpanAt, rowRangeToHeightRatios, serializeCopyRowsToTSV, serializeSelectionToTSV, toggleExpandedRowId, useCellEdit, useCellSelection, useConvertTreeData, useGlideTable, writeSelectionToClipboard };
package/dist/core.js CHANGED
@@ -4,7 +4,8 @@ var DEFAULT_DATA_TABLE_LABELS = {
4
4
  loading: "Loading...",
5
5
  selection: (selectedCount) => selectedCount > 0 ? `\u2713 ${selectedCount} selected` : null,
6
6
  expandRow: "Expand row",
7
- collapseRow: "Collapse row"
7
+ collapseRow: "Collapse row",
8
+ resizeColumn: "Resize column"
8
9
  };
9
10
  function resolveDataTableLabels(partial) {
10
11
  return {
@@ -38,6 +39,9 @@ import {
38
39
  // src/components/ui/table/constants.ts
39
40
  var DATA_TABLE_ROW_HEIGHT = 44;
40
41
  var DATA_TABLE_VIRTUAL_OVERSCAN = 8;
42
+ var DATA_TABLE_COLUMN_SIZE = 150;
43
+ var DATA_TABLE_COLUMN_MIN_SIZE = 40;
44
+ var DATA_TABLE_COLUMN_MAX_SIZE = 800;
41
45
 
42
46
  // src/components/ui/table/features/cell-edit/useCellEdit.ts
43
47
  import { useCallback, useEffect, useRef, useState } from "react";
@@ -928,6 +932,89 @@ function useCellSelection({
928
932
  };
929
933
  }
930
934
 
935
+ // src/components/ui/table/features/column-freeze/columnFreeze.ts
936
+ var HEADER_Z_BASE = 30;
937
+ var BODY_Z_BASE = 5;
938
+ function resolveColumnFreezeSide(frozen) {
939
+ if (frozen === true || frozen === "left") return "left";
940
+ if (frozen === "right") return "right";
941
+ return void 0;
942
+ }
943
+ function getColumnFreezeEdgeAttr(offset) {
944
+ if (!offset) return void 0;
945
+ if (offset.edgeLeft && offset.edgeRight) return "both";
946
+ if (offset.edgeLeft) return "left";
947
+ if (offset.edgeRight) return "right";
948
+ return void 0;
949
+ }
950
+ function buildColumnFreezeOffsets(columns) {
951
+ const result = /* @__PURE__ */ new Map();
952
+ let leftOffset = 0;
953
+ const leftIds = [];
954
+ for (const column of columns) {
955
+ if (column.side !== "left") continue;
956
+ leftIds.push(column.id);
957
+ result.set(column.id, {
958
+ side: "left",
959
+ offset: leftOffset,
960
+ isEdge: false,
961
+ edgeLeft: false,
962
+ edgeRight: false,
963
+ stack: 0
964
+ });
965
+ leftOffset += column.size;
966
+ }
967
+ leftIds.forEach((id, index) => {
968
+ const entry = result.get(id);
969
+ if (!entry) return;
970
+ entry.stack = leftIds.length - index;
971
+ });
972
+ let rightOffset = 0;
973
+ const rightIds = [];
974
+ for (let index = columns.length - 1; index >= 0; index -= 1) {
975
+ const column = columns[index];
976
+ if (!column || column.side !== "right") continue;
977
+ rightIds.push(column.id);
978
+ result.set(column.id, {
979
+ side: "right",
980
+ offset: rightOffset,
981
+ isEdge: false,
982
+ edgeLeft: false,
983
+ edgeRight: false,
984
+ stack: 0
985
+ });
986
+ rightOffset += column.size;
987
+ }
988
+ rightIds.forEach((id, index) => {
989
+ const entry = result.get(id);
990
+ if (!entry) return;
991
+ entry.stack = rightIds.length - index;
992
+ });
993
+ columns.forEach((column, index) => {
994
+ if (!column.side) return;
995
+ const entry = result.get(column.id);
996
+ if (!entry) return;
997
+ const prevSide = index > 0 ? columns[index - 1]?.side : void 0;
998
+ const nextSide = index < columns.length - 1 ? columns[index + 1]?.side : void 0;
999
+ entry.edgeLeft = prevSide !== column.side;
1000
+ entry.edgeRight = nextSide !== column.side;
1001
+ if (index === 0) entry.edgeLeft = false;
1002
+ if (index === columns.length - 1) entry.edgeRight = false;
1003
+ entry.isEdge = entry.edgeLeft || entry.edgeRight;
1004
+ });
1005
+ return result;
1006
+ }
1007
+ function getColumnFreezeStyle(offset, options) {
1008
+ if (!offset) return void 0;
1009
+ const zBase = options?.isHeader ? HEADER_Z_BASE : BODY_Z_BASE;
1010
+ return {
1011
+ position: "sticky",
1012
+ ...offset.side === "left" ? { left: offset.offset } : { right: offset.offset },
1013
+ zIndex: zBase + offset.stack,
1014
+ ...options?.isHeader ? { top: 0 } : {}
1015
+ };
1016
+ }
1017
+
931
1018
  // src/components/ui/table/features/row-expand/row-expand.ts
932
1019
  import { useEffect as useEffect3, useMemo, useRef as useRef3 } from "react";
933
1020
  function getFieldValue(row, key) {
@@ -1193,6 +1280,7 @@ function collectRowSpanColumns(columns) {
1193
1280
  }
1194
1281
 
1195
1282
  // src/core/useGlideTable.ts
1283
+ var EMPTY_COLUMN_FREEZE_OFFSETS = /* @__PURE__ */ new Map();
1196
1284
  function useGlideTable(options) {
1197
1285
  const {
1198
1286
  data,
@@ -1228,7 +1316,12 @@ function useGlideTable(options) {
1228
1316
  enableInsertPaste,
1229
1317
  enableVirtualization = true,
1230
1318
  estimateRowHeight = DATA_TABLE_ROW_HEIGHT,
1231
- virtualOverscan = DATA_TABLE_VIRTUAL_OVERSCAN
1319
+ virtualOverscan = DATA_TABLE_VIRTUAL_OVERSCAN,
1320
+ enableColumnResize = false,
1321
+ columnSizing: controlledColumnSizing,
1322
+ onColumnSizingChange,
1323
+ columnResizeMode = "onChange",
1324
+ enableColumnFreeze = false
1232
1325
  } = options;
1233
1326
  const labels = useMemo2(() => {
1234
1327
  const resolved = resolveDataTableLabels(labelsProp);
@@ -1242,6 +1335,7 @@ function useGlideTable(options) {
1242
1335
  const enableExpand = Boolean(toggleField);
1243
1336
  const resolvedEnableSubtreeCopy = enableSubtreeCopy ?? enableExpand;
1244
1337
  const [internalRowSelection, setInternalRowSelection] = useState3({});
1338
+ const [internalColumnSizing, setInternalColumnSizing] = useState3({});
1245
1339
  const [internalExpandedRows, setInternalExpandedRows] = useState3(
1246
1340
  () => /* @__PURE__ */ new Set()
1247
1341
  );
@@ -1260,6 +1354,7 @@ function useGlideTable(options) {
1260
1354
  controlledRowSelection,
1261
1355
  internalRowSelection
1262
1356
  );
1357
+ const columnSizing = controlledColumnSizing ?? internalColumnSizing;
1263
1358
  const expandedRows = controlledExpandedRows ?? internalExpandedRows;
1264
1359
  const handleExpandedRowsChange = useCallback3(
1265
1360
  (next) => {
@@ -1285,9 +1380,27 @@ function useGlideTable(options) {
1285
1380
  const table = useReactTable({
1286
1381
  data: tableData,
1287
1382
  columns,
1383
+ ...enableColumnResize ? {
1384
+ defaultColumn: {
1385
+ minSize: DATA_TABLE_COLUMN_MIN_SIZE,
1386
+ maxSize: DATA_TABLE_COLUMN_MAX_SIZE
1387
+ }
1388
+ } : {},
1389
+ enableColumnResizing: enableColumnResize,
1390
+ columnResizeMode,
1288
1391
  state: {
1289
- rowSelection: rowSelectionMode === "none" ? {} : rowSelection
1392
+ rowSelection: rowSelectionMode === "none" ? {} : rowSelection,
1393
+ ...enableColumnResize ? { columnSizing } : {}
1290
1394
  },
1395
+ onColumnSizingChange: enableColumnResize ? (updater) => {
1396
+ if (onColumnSizingChange) {
1397
+ onColumnSizingChange(updater);
1398
+ return;
1399
+ }
1400
+ setInternalColumnSizing(
1401
+ (previous) => typeof updater === "function" ? updater(previous) : updater
1402
+ );
1403
+ } : void 0,
1291
1404
  enableRowSelection: rowSelectionMode === "none" ? false : getRowCanSelect ? (row) => getRowCanSelect(row.original, row.index) : true,
1292
1405
  enableMultiRowSelection: rowSelectionMode === "multi",
1293
1406
  onRowSelectionChange: (updater) => {
@@ -1318,6 +1431,17 @@ function useGlideTable(options) {
1318
1431
  const selectedCount = selectedRows.length;
1319
1432
  const rows = table.getRowModel().rows;
1320
1433
  const columnCount = table.getAllLeafColumns().length || 1;
1434
+ const visibleLeafColumns = table.getVisibleLeafColumns();
1435
+ const columnFreezeOffsets = useMemo2(() => {
1436
+ if (!enableColumnFreeze) return EMPTY_COLUMN_FREEZE_OFFSETS;
1437
+ return buildColumnFreezeOffsets(
1438
+ visibleLeafColumns.map((column) => ({
1439
+ id: column.id,
1440
+ size: column.getSize(),
1441
+ side: resolveColumnFreezeSide(column.columnDef.meta?.frozen)
1442
+ }))
1443
+ );
1444
+ }, [enableColumnFreeze, visibleLeafColumns, columnSizing]);
1321
1445
  const rowVirtualizer = useVirtualizer({
1322
1446
  count: shouldVirtualize ? rows.length : 0,
1323
1447
  getScrollElement: () => scrollRef.current,
@@ -1434,6 +1558,13 @@ function useGlideTable(options) {
1434
1558
  onToggleExpand: handleToggleExpand,
1435
1559
  expandRowLabel: labels.expandRow,
1436
1560
  collapseRowLabel: labels.collapseRow
1561
+ },
1562
+ columnResize: {
1563
+ enableColumnResize
1564
+ },
1565
+ columnFreeze: {
1566
+ enableColumnFreeze,
1567
+ offsets: columnFreezeOffsets
1437
1568
  }
1438
1569
  };
1439
1570
  }, [
@@ -1466,7 +1597,10 @@ function useGlideTable(options) {
1466
1597
  preventExpand,
1467
1598
  handleToggleExpand,
1468
1599
  labels.expandRow,
1469
- labels.collapseRow
1600
+ labels.collapseRow,
1601
+ enableColumnResize,
1602
+ enableColumnFreeze,
1603
+ columnFreezeOffsets
1470
1604
  ]);
1471
1605
  const copySelectionRef = useRef4(copySelection);
1472
1606
  useEffect4(() => {
@@ -1487,6 +1621,8 @@ function useGlideTable(options) {
1487
1621
  loadingText: labels.loading,
1488
1622
  selectionLabel: labels.selection,
1489
1623
  enableCellSelection,
1624
+ enableColumnResize,
1625
+ enableColumnFreeze,
1490
1626
  shouldVirtualize,
1491
1627
  scrollRef,
1492
1628
  rowVirtualizer,
@@ -1499,6 +1635,19 @@ function useGlideTable(options) {
1499
1635
  copySelection: stableCopySelection
1500
1636
  };
1501
1637
  }
1638
+
1639
+ // src/components/ui/table/features/column-resize/columnResize.ts
1640
+ function getColumnSizeStyle(size, options) {
1641
+ const { force = false, lockMax = false } = options ?? {};
1642
+ if (!force && size === DATA_TABLE_COLUMN_SIZE) {
1643
+ return void 0;
1644
+ }
1645
+ return {
1646
+ width: size,
1647
+ minWidth: size,
1648
+ ...lockMax ? { maxWidth: size } : {}
1649
+ };
1650
+ }
1502
1651
  export {
1503
1652
  CELL_SELECTION_EDGES_CLASS,
1504
1653
  DEFAULT_DATA_TABLE_LABELS,
@@ -1509,6 +1658,7 @@ export {
1509
1658
  applyCellEdit,
1510
1659
  applyFillData,
1511
1660
  applySelectionUpdater,
1661
+ buildColumnFreezeOffsets,
1512
1662
  buildColumnRowSpanMap,
1513
1663
  buildRowsPastePayload,
1514
1664
  canExpandRow,
@@ -1520,6 +1670,9 @@ export {
1520
1670
  getCellEditDraftValue,
1521
1671
  getCellSelectionEdgeStyle,
1522
1672
  getColumnEditType,
1673
+ getColumnFreezeEdgeAttr,
1674
+ getColumnFreezeStyle,
1675
+ getColumnSizeStyle,
1523
1676
  getRowIndexInMergedCell,
1524
1677
  hasCellSelectionEdges,
1525
1678
  isCellInSelection,
@@ -1529,6 +1682,7 @@ export {
1529
1682
  parseCellEditValue,
1530
1683
  parseClipboardTSV,
1531
1684
  parseClipboardTSVWithDepths,
1685
+ resolveColumnFreezeSide,
1532
1686
  resolveDataTableLabels,
1533
1687
  resolvePasteColumnIds,
1534
1688
  resolveRowSelection,