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/README.md +114 -47
- package/dist/compound.cjs +236 -15
- package/dist/compound.d.cts +3 -3
- package/dist/compound.d.ts +3 -3
- package/dist/compound.js +236 -15
- package/dist/core.cjs +163 -4
- package/dist/core.d.cts +20 -5
- package/dist/core.d.ts +20 -5
- package/dist/core.js +158 -4
- package/dist/index.cjs +246 -15
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +241 -15
- package/dist/{types-xxzMLUwM.d.cts → types-B4uHdkrY.d.cts} +95 -3
- package/dist/{types-xxzMLUwM.d.ts → types-B4uHdkrY.d.ts} +95 -3
- package/package.json +23 -1
package/dist/index.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 {
|
|
@@ -46,6 +47,9 @@ var ROW_HOVERED_BG_CLASS = "row-hovered";
|
|
|
46
47
|
var CELL_SELECTION_FILL_CLASS = "cell-selection-fill";
|
|
47
48
|
var DATA_TABLE_ROW_HEIGHT = 44;
|
|
48
49
|
var DATA_TABLE_VIRTUAL_OVERSCAN = 8;
|
|
50
|
+
var DATA_TABLE_COLUMN_SIZE = 150;
|
|
51
|
+
var DATA_TABLE_COLUMN_MIN_SIZE = 40;
|
|
52
|
+
var DATA_TABLE_COLUMN_MAX_SIZE = 800;
|
|
49
53
|
|
|
50
54
|
// src/components/ui/table/features/cell-edit/useCellEdit.ts
|
|
51
55
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
@@ -936,6 +940,89 @@ function useCellSelection({
|
|
|
936
940
|
};
|
|
937
941
|
}
|
|
938
942
|
|
|
943
|
+
// src/components/ui/table/features/column-freeze/columnFreeze.ts
|
|
944
|
+
var HEADER_Z_BASE = 30;
|
|
945
|
+
var BODY_Z_BASE = 5;
|
|
946
|
+
function resolveColumnFreezeSide(frozen) {
|
|
947
|
+
if (frozen === true || frozen === "left") return "left";
|
|
948
|
+
if (frozen === "right") return "right";
|
|
949
|
+
return void 0;
|
|
950
|
+
}
|
|
951
|
+
function getColumnFreezeEdgeAttr(offset) {
|
|
952
|
+
if (!offset) return void 0;
|
|
953
|
+
if (offset.edgeLeft && offset.edgeRight) return "both";
|
|
954
|
+
if (offset.edgeLeft) return "left";
|
|
955
|
+
if (offset.edgeRight) return "right";
|
|
956
|
+
return void 0;
|
|
957
|
+
}
|
|
958
|
+
function buildColumnFreezeOffsets(columns) {
|
|
959
|
+
const result = /* @__PURE__ */ new Map();
|
|
960
|
+
let leftOffset = 0;
|
|
961
|
+
const leftIds = [];
|
|
962
|
+
for (const column of columns) {
|
|
963
|
+
if (column.side !== "left") continue;
|
|
964
|
+
leftIds.push(column.id);
|
|
965
|
+
result.set(column.id, {
|
|
966
|
+
side: "left",
|
|
967
|
+
offset: leftOffset,
|
|
968
|
+
isEdge: false,
|
|
969
|
+
edgeLeft: false,
|
|
970
|
+
edgeRight: false,
|
|
971
|
+
stack: 0
|
|
972
|
+
});
|
|
973
|
+
leftOffset += column.size;
|
|
974
|
+
}
|
|
975
|
+
leftIds.forEach((id, index) => {
|
|
976
|
+
const entry = result.get(id);
|
|
977
|
+
if (!entry) return;
|
|
978
|
+
entry.stack = leftIds.length - index;
|
|
979
|
+
});
|
|
980
|
+
let rightOffset = 0;
|
|
981
|
+
const rightIds = [];
|
|
982
|
+
for (let index = columns.length - 1; index >= 0; index -= 1) {
|
|
983
|
+
const column = columns[index];
|
|
984
|
+
if (!column || column.side !== "right") continue;
|
|
985
|
+
rightIds.push(column.id);
|
|
986
|
+
result.set(column.id, {
|
|
987
|
+
side: "right",
|
|
988
|
+
offset: rightOffset,
|
|
989
|
+
isEdge: false,
|
|
990
|
+
edgeLeft: false,
|
|
991
|
+
edgeRight: false,
|
|
992
|
+
stack: 0
|
|
993
|
+
});
|
|
994
|
+
rightOffset += column.size;
|
|
995
|
+
}
|
|
996
|
+
rightIds.forEach((id, index) => {
|
|
997
|
+
const entry = result.get(id);
|
|
998
|
+
if (!entry) return;
|
|
999
|
+
entry.stack = rightIds.length - index;
|
|
1000
|
+
});
|
|
1001
|
+
columns.forEach((column, index) => {
|
|
1002
|
+
if (!column.side) return;
|
|
1003
|
+
const entry = result.get(column.id);
|
|
1004
|
+
if (!entry) return;
|
|
1005
|
+
const prevSide = index > 0 ? columns[index - 1]?.side : void 0;
|
|
1006
|
+
const nextSide = index < columns.length - 1 ? columns[index + 1]?.side : void 0;
|
|
1007
|
+
entry.edgeLeft = prevSide !== column.side;
|
|
1008
|
+
entry.edgeRight = nextSide !== column.side;
|
|
1009
|
+
if (index === 0) entry.edgeLeft = false;
|
|
1010
|
+
if (index === columns.length - 1) entry.edgeRight = false;
|
|
1011
|
+
entry.isEdge = entry.edgeLeft || entry.edgeRight;
|
|
1012
|
+
});
|
|
1013
|
+
return result;
|
|
1014
|
+
}
|
|
1015
|
+
function getColumnFreezeStyle(offset, options) {
|
|
1016
|
+
if (!offset) return void 0;
|
|
1017
|
+
const zBase = options?.isHeader ? HEADER_Z_BASE : BODY_Z_BASE;
|
|
1018
|
+
return {
|
|
1019
|
+
position: "sticky",
|
|
1020
|
+
...offset.side === "left" ? { left: offset.offset } : { right: offset.offset },
|
|
1021
|
+
zIndex: zBase + offset.stack,
|
|
1022
|
+
...options?.isHeader ? { top: 0 } : {}
|
|
1023
|
+
};
|
|
1024
|
+
}
|
|
1025
|
+
|
|
939
1026
|
// src/components/ui/table/features/row-expand/row-expand.ts
|
|
940
1027
|
import { useEffect as useEffect3, useMemo, useRef as useRef3 } from "react";
|
|
941
1028
|
function getFieldValue(row, key) {
|
|
@@ -1201,6 +1288,7 @@ function collectRowSpanColumns(columns) {
|
|
|
1201
1288
|
}
|
|
1202
1289
|
|
|
1203
1290
|
// src/core/useGlideTable.ts
|
|
1291
|
+
var EMPTY_COLUMN_FREEZE_OFFSETS = /* @__PURE__ */ new Map();
|
|
1204
1292
|
function useGlideTable(options) {
|
|
1205
1293
|
const {
|
|
1206
1294
|
data,
|
|
@@ -1236,7 +1324,12 @@ function useGlideTable(options) {
|
|
|
1236
1324
|
enableInsertPaste,
|
|
1237
1325
|
enableVirtualization = true,
|
|
1238
1326
|
estimateRowHeight = DATA_TABLE_ROW_HEIGHT,
|
|
1239
|
-
virtualOverscan = DATA_TABLE_VIRTUAL_OVERSCAN
|
|
1327
|
+
virtualOverscan = DATA_TABLE_VIRTUAL_OVERSCAN,
|
|
1328
|
+
enableColumnResize = false,
|
|
1329
|
+
columnSizing: controlledColumnSizing,
|
|
1330
|
+
onColumnSizingChange,
|
|
1331
|
+
columnResizeMode = "onChange",
|
|
1332
|
+
enableColumnFreeze = false
|
|
1240
1333
|
} = options;
|
|
1241
1334
|
const labels = useMemo2(() => {
|
|
1242
1335
|
const resolved = resolveDataTableLabels(labelsProp);
|
|
@@ -1250,6 +1343,7 @@ function useGlideTable(options) {
|
|
|
1250
1343
|
const enableExpand = Boolean(toggleField);
|
|
1251
1344
|
const resolvedEnableSubtreeCopy = enableSubtreeCopy ?? enableExpand;
|
|
1252
1345
|
const [internalRowSelection, setInternalRowSelection] = useState3({});
|
|
1346
|
+
const [internalColumnSizing, setInternalColumnSizing] = useState3({});
|
|
1253
1347
|
const [internalExpandedRows, setInternalExpandedRows] = useState3(
|
|
1254
1348
|
() => /* @__PURE__ */ new Set()
|
|
1255
1349
|
);
|
|
@@ -1268,6 +1362,7 @@ function useGlideTable(options) {
|
|
|
1268
1362
|
controlledRowSelection,
|
|
1269
1363
|
internalRowSelection
|
|
1270
1364
|
);
|
|
1365
|
+
const columnSizing = controlledColumnSizing ?? internalColumnSizing;
|
|
1271
1366
|
const expandedRows = controlledExpandedRows ?? internalExpandedRows;
|
|
1272
1367
|
const handleExpandedRowsChange = useCallback3(
|
|
1273
1368
|
(next) => {
|
|
@@ -1293,9 +1388,27 @@ function useGlideTable(options) {
|
|
|
1293
1388
|
const table = useReactTable({
|
|
1294
1389
|
data: tableData,
|
|
1295
1390
|
columns,
|
|
1391
|
+
...enableColumnResize ? {
|
|
1392
|
+
defaultColumn: {
|
|
1393
|
+
minSize: DATA_TABLE_COLUMN_MIN_SIZE,
|
|
1394
|
+
maxSize: DATA_TABLE_COLUMN_MAX_SIZE
|
|
1395
|
+
}
|
|
1396
|
+
} : {},
|
|
1397
|
+
enableColumnResizing: enableColumnResize,
|
|
1398
|
+
columnResizeMode,
|
|
1296
1399
|
state: {
|
|
1297
|
-
rowSelection: rowSelectionMode === "none" ? {} : rowSelection
|
|
1400
|
+
rowSelection: rowSelectionMode === "none" ? {} : rowSelection,
|
|
1401
|
+
...enableColumnResize ? { columnSizing } : {}
|
|
1298
1402
|
},
|
|
1403
|
+
onColumnSizingChange: enableColumnResize ? (updater) => {
|
|
1404
|
+
if (onColumnSizingChange) {
|
|
1405
|
+
onColumnSizingChange(updater);
|
|
1406
|
+
return;
|
|
1407
|
+
}
|
|
1408
|
+
setInternalColumnSizing(
|
|
1409
|
+
(previous) => typeof updater === "function" ? updater(previous) : updater
|
|
1410
|
+
);
|
|
1411
|
+
} : void 0,
|
|
1299
1412
|
enableRowSelection: rowSelectionMode === "none" ? false : getRowCanSelect ? (row) => getRowCanSelect(row.original, row.index) : true,
|
|
1300
1413
|
enableMultiRowSelection: rowSelectionMode === "multi",
|
|
1301
1414
|
onRowSelectionChange: (updater) => {
|
|
@@ -1326,6 +1439,17 @@ function useGlideTable(options) {
|
|
|
1326
1439
|
const selectedCount = selectedRows.length;
|
|
1327
1440
|
const rows = table.getRowModel().rows;
|
|
1328
1441
|
const columnCount = table.getAllLeafColumns().length || 1;
|
|
1442
|
+
const visibleLeafColumns = table.getVisibleLeafColumns();
|
|
1443
|
+
const columnFreezeOffsets = useMemo2(() => {
|
|
1444
|
+
if (!enableColumnFreeze) return EMPTY_COLUMN_FREEZE_OFFSETS;
|
|
1445
|
+
return buildColumnFreezeOffsets(
|
|
1446
|
+
visibleLeafColumns.map((column) => ({
|
|
1447
|
+
id: column.id,
|
|
1448
|
+
size: column.getSize(),
|
|
1449
|
+
side: resolveColumnFreezeSide(column.columnDef.meta?.frozen)
|
|
1450
|
+
}))
|
|
1451
|
+
);
|
|
1452
|
+
}, [enableColumnFreeze, visibleLeafColumns, columnSizing]);
|
|
1329
1453
|
const rowVirtualizer = useVirtualizer({
|
|
1330
1454
|
count: shouldVirtualize ? rows.length : 0,
|
|
1331
1455
|
getScrollElement: () => scrollRef.current,
|
|
@@ -1442,6 +1566,13 @@ function useGlideTable(options) {
|
|
|
1442
1566
|
onToggleExpand: handleToggleExpand,
|
|
1443
1567
|
expandRowLabel: labels.expandRow,
|
|
1444
1568
|
collapseRowLabel: labels.collapseRow
|
|
1569
|
+
},
|
|
1570
|
+
columnResize: {
|
|
1571
|
+
enableColumnResize
|
|
1572
|
+
},
|
|
1573
|
+
columnFreeze: {
|
|
1574
|
+
enableColumnFreeze,
|
|
1575
|
+
offsets: columnFreezeOffsets
|
|
1445
1576
|
}
|
|
1446
1577
|
};
|
|
1447
1578
|
}, [
|
|
@@ -1474,7 +1605,10 @@ function useGlideTable(options) {
|
|
|
1474
1605
|
preventExpand,
|
|
1475
1606
|
handleToggleExpand,
|
|
1476
1607
|
labels.expandRow,
|
|
1477
|
-
labels.collapseRow
|
|
1608
|
+
labels.collapseRow,
|
|
1609
|
+
enableColumnResize,
|
|
1610
|
+
enableColumnFreeze,
|
|
1611
|
+
columnFreezeOffsets
|
|
1478
1612
|
]);
|
|
1479
1613
|
const copySelectionRef = useRef4(copySelection);
|
|
1480
1614
|
useEffect4(() => {
|
|
@@ -1495,6 +1629,8 @@ function useGlideTable(options) {
|
|
|
1495
1629
|
loadingText: labels.loading,
|
|
1496
1630
|
selectionLabel: labels.selection,
|
|
1497
1631
|
enableCellSelection,
|
|
1632
|
+
enableColumnResize,
|
|
1633
|
+
enableColumnFreeze,
|
|
1498
1634
|
shouldVirtualize,
|
|
1499
1635
|
scrollRef,
|
|
1500
1636
|
rowVirtualizer,
|
|
@@ -1508,6 +1644,19 @@ function useGlideTable(options) {
|
|
|
1508
1644
|
};
|
|
1509
1645
|
}
|
|
1510
1646
|
|
|
1647
|
+
// src/components/ui/table/features/column-resize/columnResize.ts
|
|
1648
|
+
function getColumnSizeStyle(size, options) {
|
|
1649
|
+
const { force = false, lockMax = false } = options ?? {};
|
|
1650
|
+
if (!force && size === DATA_TABLE_COLUMN_SIZE) {
|
|
1651
|
+
return void 0;
|
|
1652
|
+
}
|
|
1653
|
+
return {
|
|
1654
|
+
width: size,
|
|
1655
|
+
minWidth: size,
|
|
1656
|
+
...lockMax ? { maxWidth: size } : {}
|
|
1657
|
+
};
|
|
1658
|
+
}
|
|
1659
|
+
|
|
1511
1660
|
// src/components/ui/table/components/DataTable/DataTable.tsx
|
|
1512
1661
|
import { flexRender as flexRender2 } from "@tanstack/react-table";
|
|
1513
1662
|
import { useMemo as useMemo3 } from "react";
|
|
@@ -1714,7 +1863,18 @@ function DataTableRow({
|
|
|
1714
1863
|
virtualIndex,
|
|
1715
1864
|
measureElement
|
|
1716
1865
|
}) {
|
|
1717
|
-
const {
|
|
1866
|
+
const {
|
|
1867
|
+
classNames,
|
|
1868
|
+
rowSpan,
|
|
1869
|
+
selection,
|
|
1870
|
+
cellSelection,
|
|
1871
|
+
cellEdit,
|
|
1872
|
+
expand,
|
|
1873
|
+
columnResize,
|
|
1874
|
+
columnFreeze
|
|
1875
|
+
} = useDataTableRowContext();
|
|
1876
|
+
const { enableColumnResize } = columnResize;
|
|
1877
|
+
const { enableColumnFreeze, offsets: freezeOffsets } = columnFreeze;
|
|
1718
1878
|
const {
|
|
1719
1879
|
enableRowSpan,
|
|
1720
1880
|
primaryRowSpanColumnId,
|
|
@@ -1895,6 +2055,17 @@ function DataTableRow({
|
|
|
1895
2055
|
);
|
|
1896
2056
|
const resolveCellRowIndex = (clientY, element) => getRowIndexInMergedCell(clientY, element, rowIndex, cellRowSpan);
|
|
1897
2057
|
const hasSelectionEdges = hasCellSelectionEdges(selectionEdgeStyle);
|
|
2058
|
+
const sizeStyle = getColumnSizeStyle(cell.column.getSize(), {
|
|
2059
|
+
force: enableColumnResize,
|
|
2060
|
+
lockMax: enableColumnResize
|
|
2061
|
+
});
|
|
2062
|
+
const freezeOffset = enableColumnFreeze ? freezeOffsets.get(columnId) : void 0;
|
|
2063
|
+
const freezeStyle = getColumnFreezeStyle(freezeOffset);
|
|
2064
|
+
const cellStyle = {
|
|
2065
|
+
...sizeStyle,
|
|
2066
|
+
...freezeStyle,
|
|
2067
|
+
...selectionEdgeStyle
|
|
2068
|
+
};
|
|
1898
2069
|
return /* @__PURE__ */ jsxs2(
|
|
1899
2070
|
"td",
|
|
1900
2071
|
{
|
|
@@ -1908,6 +2079,8 @@ function DataTableRow({
|
|
|
1908
2079
|
"data-selection-edges": hasSelectionEdges ? "" : void 0,
|
|
1909
2080
|
"data-editable": editable ? "" : void 0,
|
|
1910
2081
|
"data-editing": isEditing ? "" : void 0,
|
|
2082
|
+
"data-frozen": freezeOffset?.side,
|
|
2083
|
+
"data-freeze-edge": getColumnFreezeEdgeAttr(freezeOffset),
|
|
1911
2084
|
onMouseDown: (event) => {
|
|
1912
2085
|
if (isEditing) {
|
|
1913
2086
|
event.stopPropagation();
|
|
@@ -1942,9 +2115,10 @@ function DataTableRow({
|
|
|
1942
2115
|
event.stopPropagation();
|
|
1943
2116
|
onStartEdit(rowIndex, cellIndex);
|
|
1944
2117
|
},
|
|
1945
|
-
style:
|
|
2118
|
+
style: Object.keys(cellStyle).length > 0 ? cellStyle : void 0,
|
|
1946
2119
|
className: cn(
|
|
1947
2120
|
"data-table-cell",
|
|
2121
|
+
freezeOffset && `data-table-cell--frozen-${freezeOffset.side}`,
|
|
1948
2122
|
CELL_ALIGN_CLASS[align],
|
|
1949
2123
|
cellClassName,
|
|
1950
2124
|
isMerged && "is-merged",
|
|
@@ -2177,10 +2351,13 @@ function DataTable({
|
|
|
2177
2351
|
rows,
|
|
2178
2352
|
columnCount,
|
|
2179
2353
|
selectedCount,
|
|
2354
|
+
labels,
|
|
2180
2355
|
emptyText,
|
|
2181
2356
|
loadingText,
|
|
2182
2357
|
selectionLabel,
|
|
2183
2358
|
enableCellSelection,
|
|
2359
|
+
enableColumnResize,
|
|
2360
|
+
enableColumnFreeze,
|
|
2184
2361
|
shouldVirtualize,
|
|
2185
2362
|
scrollRef,
|
|
2186
2363
|
rowVirtualizer,
|
|
@@ -2195,6 +2372,7 @@ function DataTable({
|
|
|
2195
2372
|
const RowSlot = slots?.Row ?? DataTableRow;
|
|
2196
2373
|
const PendingSlot = slots?.Pending ?? DefaultPending;
|
|
2197
2374
|
const EmptySlot = slots?.Empty ?? DefaultEmpty;
|
|
2375
|
+
const freezeOffsets = rowContextValue.columnFreeze.offsets;
|
|
2198
2376
|
const contextValue = useMemo3(
|
|
2199
2377
|
() => ({ ...rowContextValue, classNames }),
|
|
2200
2378
|
[rowContextValue, classNames]
|
|
@@ -2215,6 +2393,8 @@ function DataTable({
|
|
|
2215
2393
|
className: cn(
|
|
2216
2394
|
"DataTableJSX",
|
|
2217
2395
|
!enableCellSelection && "DataTableJSX--no-cell-selection",
|
|
2396
|
+
enableColumnResize && "DataTableJSX--column-resize",
|
|
2397
|
+
enableColumnFreeze && "DataTableJSX--column-freeze",
|
|
2218
2398
|
classNames?.root,
|
|
2219
2399
|
className
|
|
2220
2400
|
),
|
|
@@ -2235,6 +2415,7 @@ function DataTable({
|
|
|
2235
2415
|
"table",
|
|
2236
2416
|
{
|
|
2237
2417
|
className: cn("data-table", classNames?.table),
|
|
2418
|
+
style: enableColumnResize ? { width: table.getTotalSize() } : void 0,
|
|
2238
2419
|
onDragStart: enableCellSelection ? (event) => event.preventDefault() : void 0,
|
|
2239
2420
|
children: [
|
|
2240
2421
|
/* @__PURE__ */ jsx5("thead", { className: cn("data-table-head", classNames?.head), children: table.getHeaderGroups().map((headerGroup) => /* @__PURE__ */ jsx5(
|
|
@@ -2244,22 +2425,54 @@ function DataTable({
|
|
|
2244
2425
|
children: headerGroup.headers.map((header) => {
|
|
2245
2426
|
const align = header.column.columnDef.meta?.align ?? "center";
|
|
2246
2427
|
const headerClassName = header.column.columnDef.meta?.headerClassName;
|
|
2247
|
-
|
|
2428
|
+
const canResize = enableColumnResize && header.column.getCanResize();
|
|
2429
|
+
const sizeStyle = getColumnSizeStyle(header.getSize(), {
|
|
2430
|
+
force: enableColumnResize,
|
|
2431
|
+
lockMax: enableColumnResize
|
|
2432
|
+
});
|
|
2433
|
+
const freezeOffset = enableColumnFreeze ? freezeOffsets.get(header.column.id) : void 0;
|
|
2434
|
+
const freezeStyle = getColumnFreezeStyle(freezeOffset, {
|
|
2435
|
+
isHeader: true
|
|
2436
|
+
});
|
|
2437
|
+
const headerStyle = {
|
|
2438
|
+
...sizeStyle,
|
|
2439
|
+
...freezeStyle
|
|
2440
|
+
};
|
|
2441
|
+
return /* @__PURE__ */ jsxs4(
|
|
2248
2442
|
"th",
|
|
2249
2443
|
{
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
minWidth: header.getSize() !== 150 ? header.getSize() : void 0
|
|
2255
|
-
},
|
|
2444
|
+
"data-resizing": header.column.getIsResizing() ? "" : void 0,
|
|
2445
|
+
"data-frozen": freezeOffset?.side,
|
|
2446
|
+
"data-freeze-edge": getColumnFreezeEdgeAttr(freezeOffset),
|
|
2447
|
+
style: Object.keys(headerStyle).length > 0 ? headerStyle : void 0,
|
|
2256
2448
|
className: cn(
|
|
2257
2449
|
"data-table-head-cell",
|
|
2450
|
+
freezeOffset && `data-table-head-cell--frozen-${freezeOffset.side}`,
|
|
2258
2451
|
CELL_ALIGN_CLASS[align],
|
|
2259
2452
|
classNames?.headCell,
|
|
2260
2453
|
headerClassName
|
|
2261
2454
|
),
|
|
2262
|
-
children:
|
|
2455
|
+
children: [
|
|
2456
|
+
header.isPlaceholder ? null : flexRender2(header.column.columnDef.header, header.getContext()),
|
|
2457
|
+
canResize ? /* @__PURE__ */ jsx5(
|
|
2458
|
+
"div",
|
|
2459
|
+
{
|
|
2460
|
+
role: "separator",
|
|
2461
|
+
"aria-orientation": "vertical",
|
|
2462
|
+
"aria-label": labels.resizeColumn,
|
|
2463
|
+
"data-table-disable-cell-selection": "",
|
|
2464
|
+
className: cn(
|
|
2465
|
+
"data-table-resize-handle",
|
|
2466
|
+
classNames?.resizeHandle
|
|
2467
|
+
),
|
|
2468
|
+
onMouseDown: header.getResizeHandler(),
|
|
2469
|
+
onTouchStart: header.getResizeHandler(),
|
|
2470
|
+
onDoubleClick: () => {
|
|
2471
|
+
header.column.resetSize();
|
|
2472
|
+
}
|
|
2473
|
+
}
|
|
2474
|
+
) : null
|
|
2475
|
+
]
|
|
2263
2476
|
},
|
|
2264
2477
|
header.id
|
|
2265
2478
|
);
|
|
@@ -2387,6 +2600,10 @@ function buildColumnDef(props, sort, onSort) {
|
|
|
2387
2600
|
children,
|
|
2388
2601
|
sortable = false,
|
|
2389
2602
|
width,
|
|
2603
|
+
minWidth,
|
|
2604
|
+
maxWidth,
|
|
2605
|
+
resizable,
|
|
2606
|
+
frozen,
|
|
2390
2607
|
align,
|
|
2391
2608
|
rowSpan,
|
|
2392
2609
|
rowSpanKey,
|
|
@@ -2400,7 +2617,10 @@ function buildColumnDef(props, sort, onSort) {
|
|
|
2400
2617
|
return {
|
|
2401
2618
|
id: field,
|
|
2402
2619
|
...!virtual ? { accessorKey: field } : {},
|
|
2403
|
-
size: width ??
|
|
2620
|
+
size: width ?? DATA_TABLE_COLUMN_SIZE,
|
|
2621
|
+
...minWidth != null ? { minSize: minWidth } : {},
|
|
2622
|
+
...maxWidth != null ? { maxSize: maxWidth } : {},
|
|
2623
|
+
...resizable === false ? { enableResizing: false } : {},
|
|
2404
2624
|
header: sortable ? () => /* @__PURE__ */ jsx6(SortableHeader, { label: children, field, sort, onSort }) : (
|
|
2405
2625
|
// eslint-disable-next-line @typescript-eslint/promise-function-async
|
|
2406
2626
|
() => children
|
|
@@ -2420,6 +2640,7 @@ function buildColumnDef(props, sort, onSort) {
|
|
|
2420
2640
|
editable,
|
|
2421
2641
|
editType,
|
|
2422
2642
|
editInputProps,
|
|
2643
|
+
frozen,
|
|
2423
2644
|
className,
|
|
2424
2645
|
headerClassName
|
|
2425
2646
|
}
|
|
@@ -2695,6 +2916,7 @@ export {
|
|
|
2695
2916
|
applyCellEdit,
|
|
2696
2917
|
applyFillData,
|
|
2697
2918
|
applySelectionUpdater,
|
|
2919
|
+
buildColumnFreezeOffsets,
|
|
2698
2920
|
buildColumnRowSpanMap,
|
|
2699
2921
|
buildRowsPastePayload,
|
|
2700
2922
|
canExpandRow,
|
|
@@ -2707,6 +2929,9 @@ export {
|
|
|
2707
2929
|
getCellEditDraftValue,
|
|
2708
2930
|
getCellSelectionEdgeStyle,
|
|
2709
2931
|
getColumnEditType,
|
|
2932
|
+
getColumnFreezeEdgeAttr,
|
|
2933
|
+
getColumnFreezeStyle,
|
|
2934
|
+
getColumnSizeStyle,
|
|
2710
2935
|
getRowIndexInMergedCell,
|
|
2711
2936
|
hasCellSelectionEdges,
|
|
2712
2937
|
isCellInSelection,
|
|
@@ -2716,6 +2941,7 @@ export {
|
|
|
2716
2941
|
parseCellEditValue,
|
|
2717
2942
|
parseClipboardTSV,
|
|
2718
2943
|
parseClipboardTSVWithDepths,
|
|
2944
|
+
resolveColumnFreezeSide,
|
|
2719
2945
|
resolveDataTableLabels,
|
|
2720
2946
|
resolvePasteColumnIds,
|
|
2721
2947
|
resolveRowSelection,
|
|
@@ -1,5 +1,52 @@
|
|
|
1
|
-
import { ColumnDef, RowSelectionState, Updater, Row } from '@tanstack/react-table';
|
|
2
|
-
import { ReactNode, InputHTMLAttributes, ComponentType } from 'react';
|
|
1
|
+
import { ColumnDef, RowSelectionState, Updater, ColumnSizingState, OnChangeFn, ColumnResizeMode, Row } from '@tanstack/react-table';
|
|
2
|
+
import { CSSProperties, ReactNode, InputHTMLAttributes, ComponentType } from 'react';
|
|
3
|
+
|
|
4
|
+
/** Sticky edge for a frozen column. Does not reorder columns. */
|
|
5
|
+
type ColumnFreezeSide = "left" | "right";
|
|
6
|
+
/**
|
|
7
|
+
* Per-column freeze flag.
|
|
8
|
+
* `true` is sugar for `"left"`.
|
|
9
|
+
*/
|
|
10
|
+
type ColumnFreezeMeta = boolean | ColumnFreezeSide;
|
|
11
|
+
type ColumnFreezeColumnInput = {
|
|
12
|
+
id: string;
|
|
13
|
+
size: number;
|
|
14
|
+
side?: ColumnFreezeSide;
|
|
15
|
+
};
|
|
16
|
+
/** Which outer sides of a freeze island get a divider shadow. */
|
|
17
|
+
type ColumnFreezeEdgeSide = "left" | "right" | "both";
|
|
18
|
+
type ColumnFreezeOffset = {
|
|
19
|
+
side: ColumnFreezeSide;
|
|
20
|
+
/** Cumulative sticky inset (`left` or `right` in px). */
|
|
21
|
+
offset: number;
|
|
22
|
+
/** True when this cell is on an island boundary (any side). */
|
|
23
|
+
isEdge: boolean;
|
|
24
|
+
/** Shadow toward the previous column (scrollable / other island). */
|
|
25
|
+
edgeLeft: boolean;
|
|
26
|
+
/** Shadow toward the next column (scrollable / other island). */
|
|
27
|
+
edgeRight: boolean;
|
|
28
|
+
/** Relative stack order within the freeze side (higher = closer to the viewport edge). */
|
|
29
|
+
stack: number;
|
|
30
|
+
};
|
|
31
|
+
/** Normalize column `frozen` meta into a sticky side. */
|
|
32
|
+
declare function resolveColumnFreezeSide(frozen?: ColumnFreezeMeta): ColumnFreezeSide | undefined;
|
|
33
|
+
/** Serialize freeze-edge flags for `data-freeze-edge`. */
|
|
34
|
+
declare function getColumnFreezeEdgeAttr(offset: Pick<ColumnFreezeOffset, "edgeLeft" | "edgeRight"> | undefined): ColumnFreezeEdgeSide | undefined;
|
|
35
|
+
/**
|
|
36
|
+
* Build sticky insets for frozen columns without changing DOM/column order.
|
|
37
|
+
*
|
|
38
|
+
* - `left`: `left = Σ(widths of left-frozen columns before this one)`
|
|
39
|
+
* - `right`: `right = Σ(widths of right-frozen columns after this one)`
|
|
40
|
+
*
|
|
41
|
+
* Contiguous same-side freezes form one island — only the outer boundaries
|
|
42
|
+
* get edge shadows. Gaps between same-side freezes create separate islands,
|
|
43
|
+
* so both sides of the gap receive a shadow.
|
|
44
|
+
*/
|
|
45
|
+
declare function buildColumnFreezeOffsets(columns: ColumnFreezeColumnInput[]): Map<string, ColumnFreezeOffset>;
|
|
46
|
+
/** Sticky position styles for a frozen header or body cell. */
|
|
47
|
+
declare function getColumnFreezeStyle(offset: ColumnFreezeOffset | undefined, options?: {
|
|
48
|
+
isHeader?: boolean;
|
|
49
|
+
}): CSSProperties | undefined;
|
|
3
50
|
|
|
4
51
|
type DataTableLabels = {
|
|
5
52
|
empty: string;
|
|
@@ -7,6 +54,8 @@ type DataTableLabels = {
|
|
|
7
54
|
selection: (selectedCount: number) => ReactNode;
|
|
8
55
|
expandRow: string;
|
|
9
56
|
collapseRow: string;
|
|
57
|
+
/** Accessible label for the column resize handle */
|
|
58
|
+
resizeColumn: string;
|
|
10
59
|
};
|
|
11
60
|
/** Default copy. Override via the `labels` option. */
|
|
12
61
|
declare const DEFAULT_DATA_TABLE_LABELS: DataTableLabels;
|
|
@@ -31,6 +80,12 @@ declare module "@tanstack/react-table" {
|
|
|
31
80
|
editType?: CellEditType;
|
|
32
81
|
/** Inline editor input attribute overrides */
|
|
33
82
|
editInputProps?: DataTableEditInputProps;
|
|
83
|
+
/**
|
|
84
|
+
* Freeze (sticky) this column without reordering.
|
|
85
|
+
* `true` / `"left"` stick to the scrollport left; `"right"` to the right.
|
|
86
|
+
* Middle columns are allowed; multiple frozen columns stack via cumulative offsets.
|
|
87
|
+
*/
|
|
88
|
+
frozen?: ColumnFreezeMeta;
|
|
34
89
|
}
|
|
35
90
|
interface Row<TData> {
|
|
36
91
|
/**
|
|
@@ -180,6 +235,25 @@ type DataTableProps<T extends Record<string, unknown>> = {
|
|
|
180
235
|
estimateRowHeight?: number;
|
|
181
236
|
/** Virtualization overscan row count. Default 8 */
|
|
182
237
|
virtualOverscan?: number;
|
|
238
|
+
/**
|
|
239
|
+
* Enable drag-to-resize on column headers. Defaults to false.
|
|
240
|
+
* Opt out per column with `Column.resizable={false}` / `enableResizing: false`.
|
|
241
|
+
*/
|
|
242
|
+
enableColumnResize?: boolean;
|
|
243
|
+
/** Controlled column sizing map (`{ [columnId]: widthPx }`) */
|
|
244
|
+
columnSizing?: ColumnSizingState;
|
|
245
|
+
onColumnSizingChange?: OnChangeFn<ColumnSizingState>;
|
|
246
|
+
/**
|
|
247
|
+
* When to commit resize updates. Defaults to `"onChange"` (live while dragging).
|
|
248
|
+
* Use `"onEnd"` to update only after the pointer is released.
|
|
249
|
+
*/
|
|
250
|
+
columnResizeMode?: ColumnResizeMode;
|
|
251
|
+
/**
|
|
252
|
+
* Enable sticky freeze columns. Defaults to false.
|
|
253
|
+
* Mark columns with `Column.frozen` / `meta.frozen` (`true` | `"left"` | `"right"`).
|
|
254
|
+
* Does not reorder columns; offsets stack so frozen cells do not overlap.
|
|
255
|
+
*/
|
|
256
|
+
enableColumnFreeze?: boolean;
|
|
183
257
|
/**
|
|
184
258
|
* Optional UI part replacements for the unstyled DataTable renderer.
|
|
185
259
|
* Use with `createTable` / `Table.Column`, or pass columns directly to `DataTable`.
|
|
@@ -205,6 +279,8 @@ type DataTableClassNames = {
|
|
|
205
279
|
head?: string;
|
|
206
280
|
headRow?: string;
|
|
207
281
|
headCell?: string;
|
|
282
|
+
/** Column resize drag handle inside a header cell */
|
|
283
|
+
resizeHandle?: string;
|
|
208
284
|
body?: string;
|
|
209
285
|
emptyCell?: string;
|
|
210
286
|
virtualSpacer?: string;
|
|
@@ -266,7 +342,23 @@ type TableColumnProps<T extends Record<string, unknown>, K extends string = keyo
|
|
|
266
342
|
virtual?: boolean;
|
|
267
343
|
children?: ReactNode;
|
|
268
344
|
sortable?: boolean;
|
|
345
|
+
/** Initial / default column width in px (TanStack `size`) */
|
|
269
346
|
width?: number;
|
|
347
|
+
/** Minimum resize width in px. Defaults to the table min when omitted */
|
|
348
|
+
minWidth?: number;
|
|
349
|
+
/** Maximum resize width in px. Defaults to the table max when omitted */
|
|
350
|
+
maxWidth?: number;
|
|
351
|
+
/**
|
|
352
|
+
* When false, this column cannot be resized even if `enableColumnResize` is on.
|
|
353
|
+
* Defaults to true.
|
|
354
|
+
*/
|
|
355
|
+
resizable?: boolean;
|
|
356
|
+
/**
|
|
357
|
+
* Freeze (sticky) without changing column order.
|
|
358
|
+
* `true` / `"left"` → left edge; `"right"` → right edge.
|
|
359
|
+
* Requires `enableColumnFreeze`. Middle columns are allowed.
|
|
360
|
+
*/
|
|
361
|
+
frozen?: ColumnFreezeMeta;
|
|
270
362
|
align?: "left" | "center" | "right";
|
|
271
363
|
rowSpan?: boolean;
|
|
272
364
|
rowSpanKey?: string;
|
|
@@ -282,4 +374,4 @@ type TableProps<T extends Record<string, unknown>> = Omit<DataTableProps<T>, "co
|
|
|
282
374
|
children: ReactNode;
|
|
283
375
|
};
|
|
284
376
|
|
|
285
|
-
export { type
|
|
377
|
+
export { type ColumnFreezeColumnInput as C, DEFAULT_DATA_TABLE_LABELS as D, type PasteMode as P, type RowSelectionMode as R, type TableColumnProps as T, type ColumnFreezeEdgeSide as a, type ColumnFreezeMeta as b, type ColumnFreezeOffset as c, type ColumnFreezeSide as d, type DataTableClassNames as e, type DataTableCopyActions as f, type DataTableLabels as g, type DataTableProps as h, type DataTableSlots as i, type RowsPastePayload as j, type TableProps as k, buildColumnFreezeOffsets as l, getColumnFreezeEdgeAttr as m, getColumnFreezeStyle as n, resolveDataTableLabels as o, type CellEditType as p, resolveColumnFreezeSide as r };
|