react-glide-table 1.1.9 → 1.2.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.
@@ -1,8 +1,8 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode, ReactElement } from 'react';
3
- import { d as DataTableProps, T as TableColumnProps, g as TableProps } from './types-xxzMLUwM.js';
4
- export { a as DataTableClassNames, c as DataTableLabels, e as DataTableSlots, P as PasteMode, R as RowSelectionMode, f as RowsPastePayload } from './types-xxzMLUwM.js';
5
- export { ColumnDef, RowSelectionState } from '@tanstack/react-table';
3
+ import { g as DataTableProps, T as TableColumnProps, j as TableProps } from './types-D031_07N.js';
4
+ export { a as ColumnFreezeMeta, c as ColumnFreezeSide, d as DataTableClassNames, f as DataTableLabels, h as DataTableSlots, P as PasteMode, R as RowSelectionMode, i as RowsPastePayload } from './types-D031_07N.js';
5
+ export { ColumnDef, ColumnResizeMode, ColumnSizingState, RowSelectionState } from '@tanstack/react-table';
6
6
 
7
7
  /**
8
8
  * Unstyled DataTable shell: semantic HTML + interaction behavior.
package/dist/compound.js CHANGED
@@ -17,6 +17,9 @@ var ROW_HOVERED_BG_CLASS = "row-hovered";
17
17
  var CELL_SELECTION_FILL_CLASS = "cell-selection-fill";
18
18
  var DATA_TABLE_ROW_HEIGHT = 44;
19
19
  var DATA_TABLE_VIRTUAL_OVERSCAN = 8;
20
+ var DATA_TABLE_COLUMN_SIZE = 150;
21
+ var DATA_TABLE_COLUMN_MIN_SIZE = 40;
22
+ var DATA_TABLE_COLUMN_MAX_SIZE = 800;
20
23
 
21
24
  // src/components/ui/table/DataTableContext.tsx
22
25
  import { createContext, use } from "react";
@@ -357,6 +360,81 @@ function hasCellSelectionEdges(style) {
357
360
  );
358
361
  }
359
362
 
363
+ // src/components/ui/table/features/column-freeze/columnFreeze.ts
364
+ var HEADER_Z_BASE = 30;
365
+ var BODY_Z_BASE = 5;
366
+ function resolveColumnFreezeSide(frozen) {
367
+ if (frozen === true || frozen === "left") return "left";
368
+ if (frozen === "right") return "right";
369
+ return void 0;
370
+ }
371
+ function buildColumnFreezeOffsets(columns) {
372
+ const result = /* @__PURE__ */ new Map();
373
+ let leftOffset = 0;
374
+ const leftIds = [];
375
+ for (const column of columns) {
376
+ if (column.side !== "left") continue;
377
+ leftIds.push(column.id);
378
+ result.set(column.id, {
379
+ side: "left",
380
+ offset: leftOffset,
381
+ isEdge: false,
382
+ stack: 0
383
+ });
384
+ leftOffset += column.size;
385
+ }
386
+ leftIds.forEach((id, index) => {
387
+ const entry = result.get(id);
388
+ if (!entry) return;
389
+ entry.isEdge = index === leftIds.length - 1;
390
+ entry.stack = leftIds.length - index;
391
+ });
392
+ let rightOffset = 0;
393
+ const rightIds = [];
394
+ for (let index = columns.length - 1; index >= 0; index -= 1) {
395
+ const column = columns[index];
396
+ if (!column || column.side !== "right") continue;
397
+ rightIds.push(column.id);
398
+ result.set(column.id, {
399
+ side: "right",
400
+ offset: rightOffset,
401
+ isEdge: false,
402
+ stack: 0
403
+ });
404
+ rightOffset += column.size;
405
+ }
406
+ rightIds.forEach((id, index) => {
407
+ const entry = result.get(id);
408
+ if (!entry) return;
409
+ entry.isEdge = index === rightIds.length - 1;
410
+ entry.stack = rightIds.length - index;
411
+ });
412
+ return result;
413
+ }
414
+ function getColumnFreezeStyle(offset, options) {
415
+ if (!offset) return void 0;
416
+ const zBase = options?.isHeader ? HEADER_Z_BASE : BODY_Z_BASE;
417
+ return {
418
+ position: "sticky",
419
+ ...offset.side === "left" ? { left: offset.offset } : { right: offset.offset },
420
+ zIndex: zBase + offset.stack,
421
+ ...options?.isHeader ? { top: 0 } : {}
422
+ };
423
+ }
424
+
425
+ // src/components/ui/table/features/column-resize/columnResize.ts
426
+ function getColumnSizeStyle(size, options) {
427
+ const { force = false, lockMax = false } = options ?? {};
428
+ if (!force && size === DATA_TABLE_COLUMN_SIZE) {
429
+ return void 0;
430
+ }
431
+ return {
432
+ width: size,
433
+ minWidth: size,
434
+ ...lockMax ? { maxWidth: size } : {}
435
+ };
436
+ }
437
+
360
438
  // src/components/ui/table/features/row-expand/row-expand.ts
361
439
  import { useEffect, useMemo, useRef } from "react";
362
440
 
@@ -794,7 +872,18 @@ function DataTableRow({
794
872
  virtualIndex,
795
873
  measureElement
796
874
  }) {
797
- const { classNames, rowSpan, selection, cellSelection, cellEdit, expand } = useDataTableRowContext();
875
+ const {
876
+ classNames,
877
+ rowSpan,
878
+ selection,
879
+ cellSelection,
880
+ cellEdit,
881
+ expand,
882
+ columnResize,
883
+ columnFreeze
884
+ } = useDataTableRowContext();
885
+ const { enableColumnResize } = columnResize;
886
+ const { enableColumnFreeze, offsets: freezeOffsets } = columnFreeze;
798
887
  const {
799
888
  enableRowSpan,
800
889
  primaryRowSpanColumnId,
@@ -975,6 +1064,17 @@ function DataTableRow({
975
1064
  );
976
1065
  const resolveCellRowIndex = (clientY, element) => getRowIndexInMergedCell(clientY, element, rowIndex, cellRowSpan);
977
1066
  const hasSelectionEdges = hasCellSelectionEdges(selectionEdgeStyle);
1067
+ const sizeStyle = getColumnSizeStyle(cell.column.getSize(), {
1068
+ force: enableColumnResize,
1069
+ lockMax: enableColumnResize
1070
+ });
1071
+ const freezeOffset = enableColumnFreeze ? freezeOffsets.get(columnId) : void 0;
1072
+ const freezeStyle = getColumnFreezeStyle(freezeOffset);
1073
+ const cellStyle = {
1074
+ ...sizeStyle,
1075
+ ...freezeStyle,
1076
+ ...selectionEdgeStyle
1077
+ };
978
1078
  return /* @__PURE__ */ jsxs2(
979
1079
  "td",
980
1080
  {
@@ -988,6 +1088,8 @@ function DataTableRow({
988
1088
  "data-selection-edges": hasSelectionEdges ? "" : void 0,
989
1089
  "data-editable": editable ? "" : void 0,
990
1090
  "data-editing": isEditing ? "" : void 0,
1091
+ "data-frozen": freezeOffset?.side,
1092
+ "data-freeze-edge": freezeOffset?.isEdge ? "" : void 0,
991
1093
  onMouseDown: (event) => {
992
1094
  if (isEditing) {
993
1095
  event.stopPropagation();
@@ -1022,9 +1124,10 @@ function DataTableRow({
1022
1124
  event.stopPropagation();
1023
1125
  onStartEdit(rowIndex, cellIndex);
1024
1126
  },
1025
- style: selectionEdgeStyle,
1127
+ style: Object.keys(cellStyle).length > 0 ? cellStyle : void 0,
1026
1128
  className: cn(
1027
1129
  "data-table-cell",
1130
+ freezeOffset && `data-table-cell--frozen-${freezeOffset.side}`,
1028
1131
  CELL_ALIGN_CLASS[align],
1029
1132
  cellClassName,
1030
1133
  isMerged && "is-merged",
@@ -1786,7 +1889,8 @@ var DEFAULT_DATA_TABLE_LABELS = {
1786
1889
  loading: "Loading...",
1787
1890
  selection: (selectedCount) => selectedCount > 0 ? `\u2713 ${selectedCount} selected` : null,
1788
1891
  expandRow: "Expand row",
1789
- collapseRow: "Collapse row"
1892
+ collapseRow: "Collapse row",
1893
+ resizeColumn: "Resize column"
1790
1894
  };
1791
1895
  function resolveDataTableLabels(partial) {
1792
1896
  return {
@@ -1796,6 +1900,7 @@ function resolveDataTableLabels(partial) {
1796
1900
  }
1797
1901
 
1798
1902
  // src/core/useGlideTable.ts
1903
+ var EMPTY_COLUMN_FREEZE_OFFSETS = /* @__PURE__ */ new Map();
1799
1904
  function useGlideTable(options) {
1800
1905
  const {
1801
1906
  data,
@@ -1831,7 +1936,12 @@ function useGlideTable(options) {
1831
1936
  enableInsertPaste,
1832
1937
  enableVirtualization = true,
1833
1938
  estimateRowHeight = DATA_TABLE_ROW_HEIGHT,
1834
- virtualOverscan = DATA_TABLE_VIRTUAL_OVERSCAN
1939
+ virtualOverscan = DATA_TABLE_VIRTUAL_OVERSCAN,
1940
+ enableColumnResize = false,
1941
+ columnSizing: controlledColumnSizing,
1942
+ onColumnSizingChange,
1943
+ columnResizeMode = "onChange",
1944
+ enableColumnFreeze = false
1835
1945
  } = options;
1836
1946
  const labels = useMemo2(() => {
1837
1947
  const resolved = resolveDataTableLabels(labelsProp);
@@ -1845,6 +1955,7 @@ function useGlideTable(options) {
1845
1955
  const enableExpand = Boolean(toggleField);
1846
1956
  const resolvedEnableSubtreeCopy = enableSubtreeCopy ?? enableExpand;
1847
1957
  const [internalRowSelection, setInternalRowSelection] = useState3({});
1958
+ const [internalColumnSizing, setInternalColumnSizing] = useState3({});
1848
1959
  const [internalExpandedRows, setInternalExpandedRows] = useState3(
1849
1960
  () => /* @__PURE__ */ new Set()
1850
1961
  );
@@ -1863,6 +1974,7 @@ function useGlideTable(options) {
1863
1974
  controlledRowSelection,
1864
1975
  internalRowSelection
1865
1976
  );
1977
+ const columnSizing = controlledColumnSizing ?? internalColumnSizing;
1866
1978
  const expandedRows = controlledExpandedRows ?? internalExpandedRows;
1867
1979
  const handleExpandedRowsChange = useCallback3(
1868
1980
  (next) => {
@@ -1888,9 +2000,27 @@ function useGlideTable(options) {
1888
2000
  const table = useReactTable({
1889
2001
  data: tableData,
1890
2002
  columns,
2003
+ ...enableColumnResize ? {
2004
+ defaultColumn: {
2005
+ minSize: DATA_TABLE_COLUMN_MIN_SIZE,
2006
+ maxSize: DATA_TABLE_COLUMN_MAX_SIZE
2007
+ }
2008
+ } : {},
2009
+ enableColumnResizing: enableColumnResize,
2010
+ columnResizeMode,
1891
2011
  state: {
1892
- rowSelection: rowSelectionMode === "none" ? {} : rowSelection
2012
+ rowSelection: rowSelectionMode === "none" ? {} : rowSelection,
2013
+ ...enableColumnResize ? { columnSizing } : {}
1893
2014
  },
2015
+ onColumnSizingChange: enableColumnResize ? (updater) => {
2016
+ if (onColumnSizingChange) {
2017
+ onColumnSizingChange(updater);
2018
+ return;
2019
+ }
2020
+ setInternalColumnSizing(
2021
+ (previous) => typeof updater === "function" ? updater(previous) : updater
2022
+ );
2023
+ } : void 0,
1894
2024
  enableRowSelection: rowSelectionMode === "none" ? false : getRowCanSelect ? (row) => getRowCanSelect(row.original, row.index) : true,
1895
2025
  enableMultiRowSelection: rowSelectionMode === "multi",
1896
2026
  onRowSelectionChange: (updater) => {
@@ -1921,6 +2051,17 @@ function useGlideTable(options) {
1921
2051
  const selectedCount = selectedRows.length;
1922
2052
  const rows = table.getRowModel().rows;
1923
2053
  const columnCount = table.getAllLeafColumns().length || 1;
2054
+ const visibleLeafColumns = table.getVisibleLeafColumns();
2055
+ const columnFreezeOffsets = useMemo2(() => {
2056
+ if (!enableColumnFreeze) return EMPTY_COLUMN_FREEZE_OFFSETS;
2057
+ return buildColumnFreezeOffsets(
2058
+ visibleLeafColumns.map((column) => ({
2059
+ id: column.id,
2060
+ size: column.getSize(),
2061
+ side: resolveColumnFreezeSide(column.columnDef.meta?.frozen)
2062
+ }))
2063
+ );
2064
+ }, [enableColumnFreeze, visibleLeafColumns, columnSizing]);
1924
2065
  const rowVirtualizer = useVirtualizer({
1925
2066
  count: shouldVirtualize ? rows.length : 0,
1926
2067
  getScrollElement: () => scrollRef.current,
@@ -2037,6 +2178,13 @@ function useGlideTable(options) {
2037
2178
  onToggleExpand: handleToggleExpand,
2038
2179
  expandRowLabel: labels.expandRow,
2039
2180
  collapseRowLabel: labels.collapseRow
2181
+ },
2182
+ columnResize: {
2183
+ enableColumnResize
2184
+ },
2185
+ columnFreeze: {
2186
+ enableColumnFreeze,
2187
+ offsets: columnFreezeOffsets
2040
2188
  }
2041
2189
  };
2042
2190
  }, [
@@ -2069,7 +2217,10 @@ function useGlideTable(options) {
2069
2217
  preventExpand,
2070
2218
  handleToggleExpand,
2071
2219
  labels.expandRow,
2072
- labels.collapseRow
2220
+ labels.collapseRow,
2221
+ enableColumnResize,
2222
+ enableColumnFreeze,
2223
+ columnFreezeOffsets
2073
2224
  ]);
2074
2225
  const copySelectionRef = useRef5(copySelection);
2075
2226
  useEffect5(() => {
@@ -2090,6 +2241,8 @@ function useGlideTable(options) {
2090
2241
  loadingText: labels.loading,
2091
2242
  selectionLabel: labels.selection,
2092
2243
  enableCellSelection,
2244
+ enableColumnResize,
2245
+ enableColumnFreeze,
2093
2246
  shouldVirtualize,
2094
2247
  scrollRef,
2095
2248
  rowVirtualizer,
@@ -2155,10 +2308,13 @@ function DataTable({
2155
2308
  rows,
2156
2309
  columnCount,
2157
2310
  selectedCount,
2311
+ labels,
2158
2312
  emptyText,
2159
2313
  loadingText,
2160
2314
  selectionLabel,
2161
2315
  enableCellSelection,
2316
+ enableColumnResize,
2317
+ enableColumnFreeze,
2162
2318
  shouldVirtualize,
2163
2319
  scrollRef,
2164
2320
  rowVirtualizer,
@@ -2173,6 +2329,7 @@ function DataTable({
2173
2329
  const RowSlot = slots?.Row ?? DataTableRow;
2174
2330
  const PendingSlot = slots?.Pending ?? DefaultPending;
2175
2331
  const EmptySlot = slots?.Empty ?? DefaultEmpty;
2332
+ const freezeOffsets = rowContextValue.columnFreeze.offsets;
2176
2333
  const contextValue = useMemo3(
2177
2334
  () => ({ ...rowContextValue, classNames }),
2178
2335
  [rowContextValue, classNames]
@@ -2193,6 +2350,8 @@ function DataTable({
2193
2350
  className: cn(
2194
2351
  "DataTableJSX",
2195
2352
  !enableCellSelection && "DataTableJSX--no-cell-selection",
2353
+ enableColumnResize && "DataTableJSX--column-resize",
2354
+ enableColumnFreeze && "DataTableJSX--column-freeze",
2196
2355
  classNames?.root,
2197
2356
  className
2198
2357
  ),
@@ -2213,6 +2372,7 @@ function DataTable({
2213
2372
  "table",
2214
2373
  {
2215
2374
  className: cn("data-table", classNames?.table),
2375
+ style: enableColumnResize ? { width: table.getTotalSize() } : void 0,
2216
2376
  onDragStart: enableCellSelection ? (event) => event.preventDefault() : void 0,
2217
2377
  children: [
2218
2378
  /* @__PURE__ */ jsx5("thead", { className: cn("data-table-head", classNames?.head), children: table.getHeaderGroups().map((headerGroup) => /* @__PURE__ */ jsx5(
@@ -2222,22 +2382,54 @@ function DataTable({
2222
2382
  children: headerGroup.headers.map((header) => {
2223
2383
  const align = header.column.columnDef.meta?.align ?? "center";
2224
2384
  const headerClassName = header.column.columnDef.meta?.headerClassName;
2225
- return /* @__PURE__ */ jsx5(
2385
+ const canResize = enableColumnResize && header.column.getCanResize();
2386
+ const sizeStyle = getColumnSizeStyle(header.getSize(), {
2387
+ force: enableColumnResize,
2388
+ lockMax: enableColumnResize
2389
+ });
2390
+ const freezeOffset = enableColumnFreeze ? freezeOffsets.get(header.column.id) : void 0;
2391
+ const freezeStyle = getColumnFreezeStyle(freezeOffset, {
2392
+ isHeader: true
2393
+ });
2394
+ const headerStyle = {
2395
+ ...sizeStyle,
2396
+ ...freezeStyle
2397
+ };
2398
+ return /* @__PURE__ */ jsxs4(
2226
2399
  "th",
2227
2400
  {
2228
- style: {
2229
- width: header.getSize() !== 150 ? header.getSize() : void 0,
2230
- // Column sizing follows TanStack's `size`, but
2231
- // ensure the column keeps its min width when the container shrinks.
2232
- minWidth: header.getSize() !== 150 ? header.getSize() : void 0
2233
- },
2401
+ "data-resizing": header.column.getIsResizing() ? "" : void 0,
2402
+ "data-frozen": freezeOffset?.side,
2403
+ "data-freeze-edge": freezeOffset?.isEdge ? "" : void 0,
2404
+ style: Object.keys(headerStyle).length > 0 ? headerStyle : void 0,
2234
2405
  className: cn(
2235
2406
  "data-table-head-cell",
2407
+ freezeOffset && `data-table-head-cell--frozen-${freezeOffset.side}`,
2236
2408
  CELL_ALIGN_CLASS[align],
2237
2409
  classNames?.headCell,
2238
2410
  headerClassName
2239
2411
  ),
2240
- children: header.isPlaceholder ? null : flexRender2(header.column.columnDef.header, header.getContext())
2412
+ children: [
2413
+ header.isPlaceholder ? null : flexRender2(header.column.columnDef.header, header.getContext()),
2414
+ canResize ? /* @__PURE__ */ jsx5(
2415
+ "div",
2416
+ {
2417
+ role: "separator",
2418
+ "aria-orientation": "vertical",
2419
+ "aria-label": labels.resizeColumn,
2420
+ "data-table-disable-cell-selection": "",
2421
+ className: cn(
2422
+ "data-table-resize-handle",
2423
+ classNames?.resizeHandle
2424
+ ),
2425
+ onMouseDown: header.getResizeHandler(),
2426
+ onTouchStart: header.getResizeHandler(),
2427
+ onDoubleClick: () => {
2428
+ header.column.resetSize();
2429
+ }
2430
+ }
2431
+ ) : null
2432
+ ]
2241
2433
  },
2242
2434
  header.id
2243
2435
  );
@@ -2365,6 +2557,10 @@ function buildColumnDef(props, sort, onSort) {
2365
2557
  children,
2366
2558
  sortable = false,
2367
2559
  width,
2560
+ minWidth,
2561
+ maxWidth,
2562
+ resizable,
2563
+ frozen,
2368
2564
  align,
2369
2565
  rowSpan,
2370
2566
  rowSpanKey,
@@ -2378,7 +2574,10 @@ function buildColumnDef(props, sort, onSort) {
2378
2574
  return {
2379
2575
  id: field,
2380
2576
  ...!virtual ? { accessorKey: field } : {},
2381
- size: width ?? 150,
2577
+ size: width ?? DATA_TABLE_COLUMN_SIZE,
2578
+ ...minWidth != null ? { minSize: minWidth } : {},
2579
+ ...maxWidth != null ? { maxSize: maxWidth } : {},
2580
+ ...resizable === false ? { enableResizing: false } : {},
2382
2581
  header: sortable ? () => /* @__PURE__ */ jsx6(SortableHeader, { label: children, field, sort, onSort }) : (
2383
2582
  // eslint-disable-next-line @typescript-eslint/promise-function-async
2384
2583
  () => children
@@ -2398,6 +2597,7 @@ function buildColumnDef(props, sort, onSort) {
2398
2597
  editable,
2399
2598
  editType,
2400
2599
  editInputProps,
2600
+ frozen,
2401
2601
  className,
2402
2602
  headerClassName
2403
2603
  }
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,8 @@ __export(core_exports, {
40
41
  getCellEditDraftValue: () => getCellEditDraftValue,
41
42
  getCellSelectionEdgeStyle: () => getCellSelectionEdgeStyle,
42
43
  getColumnEditType: () => getColumnEditType,
44
+ getColumnFreezeStyle: () => getColumnFreezeStyle,
45
+ getColumnSizeStyle: () => getColumnSizeStyle,
43
46
  getRowIndexInMergedCell: () => getRowIndexInMergedCell,
44
47
  hasCellSelectionEdges: () => hasCellSelectionEdges,
45
48
  isCellInSelection: () => isCellInSelection,
@@ -49,6 +52,7 @@ __export(core_exports, {
49
52
  parseCellEditValue: () => parseCellEditValue,
50
53
  parseClipboardTSV: () => parseClipboardTSV,
51
54
  parseClipboardTSVWithDepths: () => parseClipboardTSVWithDepths,
55
+ resolveColumnFreezeSide: () => resolveColumnFreezeSide,
52
56
  resolveDataTableLabels: () => resolveDataTableLabels,
53
57
  resolvePasteColumnIds: () => resolvePasteColumnIds,
54
58
  resolveRowSelection: () => resolveRowSelection,
@@ -71,7 +75,8 @@ var DEFAULT_DATA_TABLE_LABELS = {
71
75
  loading: "Loading...",
72
76
  selection: (selectedCount) => selectedCount > 0 ? `\u2713 ${selectedCount} selected` : null,
73
77
  expandRow: "Expand row",
74
- collapseRow: "Collapse row"
78
+ collapseRow: "Collapse row",
79
+ resizeColumn: "Resize column"
75
80
  };
76
81
  function resolveDataTableLabels(partial) {
77
82
  return {
@@ -94,6 +99,9 @@ var import_react4 = require("react");
94
99
  // src/components/ui/table/constants.ts
95
100
  var DATA_TABLE_ROW_HEIGHT = 44;
96
101
  var DATA_TABLE_VIRTUAL_OVERSCAN = 8;
102
+ var DATA_TABLE_COLUMN_SIZE = 150;
103
+ var DATA_TABLE_COLUMN_MIN_SIZE = 40;
104
+ var DATA_TABLE_COLUMN_MAX_SIZE = 800;
97
105
 
98
106
  // src/components/ui/table/features/cell-edit/useCellEdit.ts
99
107
  var import_react = require("react");
@@ -984,6 +992,68 @@ function useCellSelection({
984
992
  };
985
993
  }
986
994
 
995
+ // src/components/ui/table/features/column-freeze/columnFreeze.ts
996
+ var HEADER_Z_BASE = 30;
997
+ var BODY_Z_BASE = 5;
998
+ function resolveColumnFreezeSide(frozen) {
999
+ if (frozen === true || frozen === "left") return "left";
1000
+ if (frozen === "right") return "right";
1001
+ return void 0;
1002
+ }
1003
+ function buildColumnFreezeOffsets(columns) {
1004
+ const result = /* @__PURE__ */ new Map();
1005
+ let leftOffset = 0;
1006
+ const leftIds = [];
1007
+ for (const column of columns) {
1008
+ if (column.side !== "left") continue;
1009
+ leftIds.push(column.id);
1010
+ result.set(column.id, {
1011
+ side: "left",
1012
+ offset: leftOffset,
1013
+ isEdge: false,
1014
+ stack: 0
1015
+ });
1016
+ leftOffset += column.size;
1017
+ }
1018
+ leftIds.forEach((id, index) => {
1019
+ const entry = result.get(id);
1020
+ if (!entry) return;
1021
+ entry.isEdge = index === leftIds.length - 1;
1022
+ entry.stack = leftIds.length - index;
1023
+ });
1024
+ let rightOffset = 0;
1025
+ const rightIds = [];
1026
+ for (let index = columns.length - 1; index >= 0; index -= 1) {
1027
+ const column = columns[index];
1028
+ if (!column || column.side !== "right") continue;
1029
+ rightIds.push(column.id);
1030
+ result.set(column.id, {
1031
+ side: "right",
1032
+ offset: rightOffset,
1033
+ isEdge: false,
1034
+ stack: 0
1035
+ });
1036
+ rightOffset += column.size;
1037
+ }
1038
+ rightIds.forEach((id, index) => {
1039
+ const entry = result.get(id);
1040
+ if (!entry) return;
1041
+ entry.isEdge = index === rightIds.length - 1;
1042
+ entry.stack = rightIds.length - index;
1043
+ });
1044
+ return result;
1045
+ }
1046
+ function getColumnFreezeStyle(offset, options) {
1047
+ if (!offset) return void 0;
1048
+ const zBase = options?.isHeader ? HEADER_Z_BASE : BODY_Z_BASE;
1049
+ return {
1050
+ position: "sticky",
1051
+ ...offset.side === "left" ? { left: offset.offset } : { right: offset.offset },
1052
+ zIndex: zBase + offset.stack,
1053
+ ...options?.isHeader ? { top: 0 } : {}
1054
+ };
1055
+ }
1056
+
987
1057
  // src/components/ui/table/features/row-expand/row-expand.ts
988
1058
  var import_react3 = require("react");
989
1059
  function getFieldValue(row, key) {
@@ -1249,6 +1319,7 @@ function collectRowSpanColumns(columns) {
1249
1319
  }
1250
1320
 
1251
1321
  // src/core/useGlideTable.ts
1322
+ var EMPTY_COLUMN_FREEZE_OFFSETS = /* @__PURE__ */ new Map();
1252
1323
  function useGlideTable(options) {
1253
1324
  const {
1254
1325
  data,
@@ -1284,7 +1355,12 @@ function useGlideTable(options) {
1284
1355
  enableInsertPaste,
1285
1356
  enableVirtualization = true,
1286
1357
  estimateRowHeight = DATA_TABLE_ROW_HEIGHT,
1287
- virtualOverscan = DATA_TABLE_VIRTUAL_OVERSCAN
1358
+ virtualOverscan = DATA_TABLE_VIRTUAL_OVERSCAN,
1359
+ enableColumnResize = false,
1360
+ columnSizing: controlledColumnSizing,
1361
+ onColumnSizingChange,
1362
+ columnResizeMode = "onChange",
1363
+ enableColumnFreeze = false
1288
1364
  } = options;
1289
1365
  const labels = (0, import_react4.useMemo)(() => {
1290
1366
  const resolved = resolveDataTableLabels(labelsProp);
@@ -1298,6 +1374,7 @@ function useGlideTable(options) {
1298
1374
  const enableExpand = Boolean(toggleField);
1299
1375
  const resolvedEnableSubtreeCopy = enableSubtreeCopy ?? enableExpand;
1300
1376
  const [internalRowSelection, setInternalRowSelection] = (0, import_react4.useState)({});
1377
+ const [internalColumnSizing, setInternalColumnSizing] = (0, import_react4.useState)({});
1301
1378
  const [internalExpandedRows, setInternalExpandedRows] = (0, import_react4.useState)(
1302
1379
  () => /* @__PURE__ */ new Set()
1303
1380
  );
@@ -1316,6 +1393,7 @@ function useGlideTable(options) {
1316
1393
  controlledRowSelection,
1317
1394
  internalRowSelection
1318
1395
  );
1396
+ const columnSizing = controlledColumnSizing ?? internalColumnSizing;
1319
1397
  const expandedRows = controlledExpandedRows ?? internalExpandedRows;
1320
1398
  const handleExpandedRowsChange = (0, import_react4.useCallback)(
1321
1399
  (next) => {
@@ -1341,9 +1419,27 @@ function useGlideTable(options) {
1341
1419
  const table = (0, import_react_table.useReactTable)({
1342
1420
  data: tableData,
1343
1421
  columns,
1422
+ ...enableColumnResize ? {
1423
+ defaultColumn: {
1424
+ minSize: DATA_TABLE_COLUMN_MIN_SIZE,
1425
+ maxSize: DATA_TABLE_COLUMN_MAX_SIZE
1426
+ }
1427
+ } : {},
1428
+ enableColumnResizing: enableColumnResize,
1429
+ columnResizeMode,
1344
1430
  state: {
1345
- rowSelection: rowSelectionMode === "none" ? {} : rowSelection
1431
+ rowSelection: rowSelectionMode === "none" ? {} : rowSelection,
1432
+ ...enableColumnResize ? { columnSizing } : {}
1346
1433
  },
1434
+ onColumnSizingChange: enableColumnResize ? (updater) => {
1435
+ if (onColumnSizingChange) {
1436
+ onColumnSizingChange(updater);
1437
+ return;
1438
+ }
1439
+ setInternalColumnSizing(
1440
+ (previous) => typeof updater === "function" ? updater(previous) : updater
1441
+ );
1442
+ } : void 0,
1347
1443
  enableRowSelection: rowSelectionMode === "none" ? false : getRowCanSelect ? (row) => getRowCanSelect(row.original, row.index) : true,
1348
1444
  enableMultiRowSelection: rowSelectionMode === "multi",
1349
1445
  onRowSelectionChange: (updater) => {
@@ -1374,6 +1470,17 @@ function useGlideTable(options) {
1374
1470
  const selectedCount = selectedRows.length;
1375
1471
  const rows = table.getRowModel().rows;
1376
1472
  const columnCount = table.getAllLeafColumns().length || 1;
1473
+ const visibleLeafColumns = table.getVisibleLeafColumns();
1474
+ const columnFreezeOffsets = (0, import_react4.useMemo)(() => {
1475
+ if (!enableColumnFreeze) return EMPTY_COLUMN_FREEZE_OFFSETS;
1476
+ return buildColumnFreezeOffsets(
1477
+ visibleLeafColumns.map((column) => ({
1478
+ id: column.id,
1479
+ size: column.getSize(),
1480
+ side: resolveColumnFreezeSide(column.columnDef.meta?.frozen)
1481
+ }))
1482
+ );
1483
+ }, [enableColumnFreeze, visibleLeafColumns, columnSizing]);
1377
1484
  const rowVirtualizer = (0, import_react_virtual.useVirtualizer)({
1378
1485
  count: shouldVirtualize ? rows.length : 0,
1379
1486
  getScrollElement: () => scrollRef.current,
@@ -1490,6 +1597,13 @@ function useGlideTable(options) {
1490
1597
  onToggleExpand: handleToggleExpand,
1491
1598
  expandRowLabel: labels.expandRow,
1492
1599
  collapseRowLabel: labels.collapseRow
1600
+ },
1601
+ columnResize: {
1602
+ enableColumnResize
1603
+ },
1604
+ columnFreeze: {
1605
+ enableColumnFreeze,
1606
+ offsets: columnFreezeOffsets
1493
1607
  }
1494
1608
  };
1495
1609
  }, [
@@ -1522,7 +1636,10 @@ function useGlideTable(options) {
1522
1636
  preventExpand,
1523
1637
  handleToggleExpand,
1524
1638
  labels.expandRow,
1525
- labels.collapseRow
1639
+ labels.collapseRow,
1640
+ enableColumnResize,
1641
+ enableColumnFreeze,
1642
+ columnFreezeOffsets
1526
1643
  ]);
1527
1644
  const copySelectionRef = (0, import_react4.useRef)(copySelection);
1528
1645
  (0, import_react4.useEffect)(() => {
@@ -1543,6 +1660,8 @@ function useGlideTable(options) {
1543
1660
  loadingText: labels.loading,
1544
1661
  selectionLabel: labels.selection,
1545
1662
  enableCellSelection,
1663
+ enableColumnResize,
1664
+ enableColumnFreeze,
1546
1665
  shouldVirtualize,
1547
1666
  scrollRef,
1548
1667
  rowVirtualizer,
@@ -1555,6 +1674,19 @@ function useGlideTable(options) {
1555
1674
  copySelection: stableCopySelection
1556
1675
  };
1557
1676
  }
1677
+
1678
+ // src/components/ui/table/features/column-resize/columnResize.ts
1679
+ function getColumnSizeStyle(size, options) {
1680
+ const { force = false, lockMax = false } = options ?? {};
1681
+ if (!force && size === DATA_TABLE_COLUMN_SIZE) {
1682
+ return void 0;
1683
+ }
1684
+ return {
1685
+ width: size,
1686
+ minWidth: size,
1687
+ ...lockMax ? { maxWidth: size } : {}
1688
+ };
1689
+ }
1558
1690
  // Annotate the CommonJS export names for ESM import in node:
1559
1691
  0 && (module.exports = {
1560
1692
  CELL_SELECTION_EDGES_CLASS,
@@ -1566,6 +1698,7 @@ function useGlideTable(options) {
1566
1698
  applyCellEdit,
1567
1699
  applyFillData,
1568
1700
  applySelectionUpdater,
1701
+ buildColumnFreezeOffsets,
1569
1702
  buildColumnRowSpanMap,
1570
1703
  buildRowsPastePayload,
1571
1704
  canExpandRow,
@@ -1577,6 +1710,8 @@ function useGlideTable(options) {
1577
1710
  getCellEditDraftValue,
1578
1711
  getCellSelectionEdgeStyle,
1579
1712
  getColumnEditType,
1713
+ getColumnFreezeStyle,
1714
+ getColumnSizeStyle,
1580
1715
  getRowIndexInMergedCell,
1581
1716
  hasCellSelectionEdges,
1582
1717
  isCellInSelection,
@@ -1586,6 +1721,7 @@ function useGlideTable(options) {
1586
1721
  parseCellEditValue,
1587
1722
  parseClipboardTSV,
1588
1723
  parseClipboardTSVWithDepths,
1724
+ resolveColumnFreezeSide,
1589
1725
  resolveDataTableLabels,
1590
1726
  resolvePasteColumnIds,
1591
1727
  resolveRowSelection,