react-glide-table 2.0.2 → 2.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.
- package/README.md +35 -0
- package/dist/compound.cjs +590 -126
- package/dist/compound.d.cts +3 -3
- package/dist/compound.d.ts +3 -3
- package/dist/compound.js +571 -102
- package/dist/core.cjs +444 -11
- package/dist/core.d.cts +53 -14
- package/dist/core.d.ts +53 -14
- package/dist/core.js +443 -11
- package/dist/index.cjs +509 -33
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +492 -17
- package/dist/{types-bgEceyRV.d.cts → types-Iot4g4sq.d.cts} +38 -2
- package/dist/{types-bgEceyRV.d.ts → types-Iot4g4sq.d.ts} +38 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6,6 +6,7 @@ var DEFAULT_DATA_TABLE_LABELS = {
|
|
|
6
6
|
expandRow: "Expand row",
|
|
7
7
|
collapseRow: "Collapse row",
|
|
8
8
|
resizeColumn: "Resize column",
|
|
9
|
+
reorderColumn: "Reorder column",
|
|
9
10
|
searchPlaceholder: "Search\u2026",
|
|
10
11
|
searchResultHint: "Type to search",
|
|
11
12
|
searchPrevious: "Previous result",
|
|
@@ -56,6 +57,7 @@ var DATA_TABLE_VIRTUAL_OVERSCAN = 8;
|
|
|
56
57
|
var DATA_TABLE_COLUMN_SIZE = 150;
|
|
57
58
|
var DATA_TABLE_COLUMN_MIN_SIZE = 40;
|
|
58
59
|
var DATA_TABLE_COLUMN_MAX_SIZE = 800;
|
|
60
|
+
var DATA_TABLE_COLUMN_REORDER_THRESHOLD = 4;
|
|
59
61
|
|
|
60
62
|
// src/components/ui/table/features/cell-edit/useCellEdit.ts
|
|
61
63
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
@@ -1321,6 +1323,135 @@ function useCellSelection({
|
|
|
1321
1323
|
};
|
|
1322
1324
|
}
|
|
1323
1325
|
|
|
1326
|
+
// src/components/ui/table/features/column-reorder/columnReorder.ts
|
|
1327
|
+
function getColumnDefId(column) {
|
|
1328
|
+
if (column.id != null && column.id !== "") return column.id;
|
|
1329
|
+
if ("accessorKey" in column && column.accessorKey != null) {
|
|
1330
|
+
return String(column.accessorKey);
|
|
1331
|
+
}
|
|
1332
|
+
return void 0;
|
|
1333
|
+
}
|
|
1334
|
+
function getColumnDefChildren(column) {
|
|
1335
|
+
if (!("columns" in column) || !Array.isArray(column.columns)) return void 0;
|
|
1336
|
+
if (column.columns.length === 0) return void 0;
|
|
1337
|
+
return column.columns;
|
|
1338
|
+
}
|
|
1339
|
+
function collectLeafColumnIds(columns) {
|
|
1340
|
+
const ids = [];
|
|
1341
|
+
for (const column of columns) {
|
|
1342
|
+
const children = getColumnDefChildren(column);
|
|
1343
|
+
if (children) {
|
|
1344
|
+
ids.push(...collectLeafColumnIds(children));
|
|
1345
|
+
continue;
|
|
1346
|
+
}
|
|
1347
|
+
const id = getColumnDefId(column);
|
|
1348
|
+
if (id) ids.push(id);
|
|
1349
|
+
}
|
|
1350
|
+
return ids;
|
|
1351
|
+
}
|
|
1352
|
+
function areColumnOrdersEqual(left, right) {
|
|
1353
|
+
if (left.length !== right.length) return false;
|
|
1354
|
+
return left.every((id, index) => id === right[index]);
|
|
1355
|
+
}
|
|
1356
|
+
function resolveLeafColumnOrder(columns, order) {
|
|
1357
|
+
const leafIds = collectLeafColumnIds(columns);
|
|
1358
|
+
if (!order?.length) return leafIds;
|
|
1359
|
+
const leafSet = new Set(leafIds);
|
|
1360
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1361
|
+
const next = order.filter((id) => {
|
|
1362
|
+
if (!leafSet.has(id) || seen.has(id)) return false;
|
|
1363
|
+
seen.add(id);
|
|
1364
|
+
return true;
|
|
1365
|
+
});
|
|
1366
|
+
for (const id of leafIds) {
|
|
1367
|
+
if (!seen.has(id)) next.push(id);
|
|
1368
|
+
}
|
|
1369
|
+
return next;
|
|
1370
|
+
}
|
|
1371
|
+
function flattenColumnSlots(columns, group) {
|
|
1372
|
+
const slots = [];
|
|
1373
|
+
for (const column of columns) {
|
|
1374
|
+
const id = getColumnDefId(column);
|
|
1375
|
+
const children = getColumnDefChildren(column);
|
|
1376
|
+
if (children) {
|
|
1377
|
+
const nestedGroup = id ? { id, def: column } : group;
|
|
1378
|
+
slots.push(...flattenColumnSlots(children, nestedGroup));
|
|
1379
|
+
continue;
|
|
1380
|
+
}
|
|
1381
|
+
if (!id) continue;
|
|
1382
|
+
slots.push({ id, def: column, group });
|
|
1383
|
+
}
|
|
1384
|
+
return slots;
|
|
1385
|
+
}
|
|
1386
|
+
function rebuildColumnTree(slots) {
|
|
1387
|
+
const result = [];
|
|
1388
|
+
let index = 0;
|
|
1389
|
+
while (index < slots.length) {
|
|
1390
|
+
const slot = slots[index];
|
|
1391
|
+
if (!slot.group) {
|
|
1392
|
+
result.push(slot.def);
|
|
1393
|
+
index += 1;
|
|
1394
|
+
continue;
|
|
1395
|
+
}
|
|
1396
|
+
const groupId = slot.group.id;
|
|
1397
|
+
const children = [];
|
|
1398
|
+
while (index < slots.length && slots[index]?.group?.id === groupId) {
|
|
1399
|
+
children.push(slots[index].def);
|
|
1400
|
+
index += 1;
|
|
1401
|
+
}
|
|
1402
|
+
const firstChildId = children[0] ? getColumnDefId(children[0]) : groupId;
|
|
1403
|
+
result.push({
|
|
1404
|
+
...slot.group.def,
|
|
1405
|
+
id: `${groupId}::${firstChildId}`,
|
|
1406
|
+
columns: children
|
|
1407
|
+
});
|
|
1408
|
+
}
|
|
1409
|
+
return result;
|
|
1410
|
+
}
|
|
1411
|
+
function applyLeafColumnOrder(columns, order) {
|
|
1412
|
+
const resolved = resolveLeafColumnOrder(columns, order);
|
|
1413
|
+
const defaultOrder = collectLeafColumnIds(columns);
|
|
1414
|
+
if (areColumnOrdersEqual(resolved, defaultOrder)) {
|
|
1415
|
+
return columns;
|
|
1416
|
+
}
|
|
1417
|
+
const byId = new Map(
|
|
1418
|
+
flattenColumnSlots(columns).map((slot) => [
|
|
1419
|
+
slot.id,
|
|
1420
|
+
slot
|
|
1421
|
+
])
|
|
1422
|
+
);
|
|
1423
|
+
const ordered = [];
|
|
1424
|
+
for (const id of resolved) {
|
|
1425
|
+
const slot = byId.get(id);
|
|
1426
|
+
if (slot) ordered.push(slot);
|
|
1427
|
+
}
|
|
1428
|
+
return rebuildColumnTree(ordered);
|
|
1429
|
+
}
|
|
1430
|
+
function moveColumnIds(order, fromIds, targetIds, edge) {
|
|
1431
|
+
if (fromIds.length === 0 || targetIds.length === 0) return [...order];
|
|
1432
|
+
const fromSet = new Set(fromIds);
|
|
1433
|
+
if (targetIds.some((id) => fromSet.has(id))) return [...order];
|
|
1434
|
+
const rest = order.filter((id) => !fromSet.has(id));
|
|
1435
|
+
const anchorId = edge === "before" ? targetIds[0] : targetIds[targetIds.length - 1];
|
|
1436
|
+
const anchorIndex = rest.indexOf(anchorId);
|
|
1437
|
+
if (anchorIndex < 0) return [...order];
|
|
1438
|
+
const insertAt = edge === "before" ? anchorIndex : anchorIndex + 1;
|
|
1439
|
+
return [...rest.slice(0, insertAt), ...fromIds, ...rest.slice(insertAt)];
|
|
1440
|
+
}
|
|
1441
|
+
function resolveDropEdge(clientX, rect) {
|
|
1442
|
+
return clientX < rect.left + rect.width / 2 ? "before" : "after";
|
|
1443
|
+
}
|
|
1444
|
+
function parseReorderIds(value) {
|
|
1445
|
+
if (!value) return [];
|
|
1446
|
+
return value.split(",").filter(Boolean);
|
|
1447
|
+
}
|
|
1448
|
+
function serializeReorderIds(ids) {
|
|
1449
|
+
return ids.join(",");
|
|
1450
|
+
}
|
|
1451
|
+
function isColumnReorderable(meta) {
|
|
1452
|
+
return meta?.reorderable !== false;
|
|
1453
|
+
}
|
|
1454
|
+
|
|
1324
1455
|
// src/components/ui/table/features/column-freeze/columnFreeze.ts
|
|
1325
1456
|
var HEADER_Z_BASE = 30;
|
|
1326
1457
|
var BODY_Z_BASE = 5;
|
|
@@ -2094,23 +2225,49 @@ function applySelectionUpdater(mode, updater, previous) {
|
|
|
2094
2225
|
function getRowFieldValue(row, key) {
|
|
2095
2226
|
return row[key];
|
|
2096
2227
|
}
|
|
2097
|
-
function
|
|
2228
|
+
function normalizeRowSpanParent(value) {
|
|
2229
|
+
if (!value) return [];
|
|
2230
|
+
return typeof value === "string" ? [value] : [...value];
|
|
2231
|
+
}
|
|
2232
|
+
function toParentSpanList(parentSpans) {
|
|
2233
|
+
if (!parentSpans?.length) return [];
|
|
2234
|
+
const first = parentSpans[0];
|
|
2235
|
+
if (!Array.isArray(first)) {
|
|
2236
|
+
return [parentSpans];
|
|
2237
|
+
}
|
|
2238
|
+
return parentSpans;
|
|
2239
|
+
}
|
|
2240
|
+
function buildStartRowLookup(spans) {
|
|
2241
|
+
const startRows = new Array(spans.length);
|
|
2242
|
+
let origin = 0;
|
|
2243
|
+
for (let i = 0; i < spans.length; i++) {
|
|
2244
|
+
if ((spans[i]?.rowSpan ?? 1) > 0) origin = i;
|
|
2245
|
+
startRows[i] = origin;
|
|
2246
|
+
}
|
|
2247
|
+
return startRows;
|
|
2248
|
+
}
|
|
2249
|
+
function sharesParentGroup(parentStartRows, rowIndex) {
|
|
2250
|
+
if (parentStartRows.length === 0 || rowIndex <= 0) return true;
|
|
2251
|
+
return parentStartRows.every(
|
|
2252
|
+
(startRows) => startRows[rowIndex - 1] === startRows[rowIndex]
|
|
2253
|
+
);
|
|
2254
|
+
}
|
|
2255
|
+
function computeRowSpans(data, rowSpanKey, parentSpans) {
|
|
2098
2256
|
if (data.length === 0) return [];
|
|
2257
|
+
const parentStartRows = toParentSpanList(parentSpans).map(buildStartRowLookup);
|
|
2099
2258
|
const result = [];
|
|
2100
2259
|
for (let index = 0; index < data.length; index++) {
|
|
2101
2260
|
const currentValue = getRowFieldValue(data[index], rowSpanKey);
|
|
2102
2261
|
const previousValue = index > 0 ? getRowFieldValue(data[index - 1], rowSpanKey) : void 0;
|
|
2103
|
-
if (index > 0 && currentValue === previousValue) {
|
|
2262
|
+
if (index > 0 && currentValue === previousValue && sharesParentGroup(parentStartRows, index)) {
|
|
2104
2263
|
result.push({ rowSpan: 0, isFirstInGroup: false });
|
|
2105
2264
|
continue;
|
|
2106
2265
|
}
|
|
2107
2266
|
let span = 1;
|
|
2108
2267
|
for (let nextIndex = index + 1; nextIndex < data.length; nextIndex++) {
|
|
2109
|
-
if (getRowFieldValue(data[nextIndex], rowSpanKey)
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
break;
|
|
2113
|
-
}
|
|
2268
|
+
if (getRowFieldValue(data[nextIndex], rowSpanKey) !== currentValue) break;
|
|
2269
|
+
if (!sharesParentGroup(parentStartRows, nextIndex)) break;
|
|
2270
|
+
span++;
|
|
2114
2271
|
}
|
|
2115
2272
|
result.push({ rowSpan: span, isFirstInGroup: true });
|
|
2116
2273
|
}
|
|
@@ -2132,10 +2289,50 @@ function resolveRowSpanAt(rowSpans, rowIndex) {
|
|
|
2132
2289
|
}
|
|
2133
2290
|
return { startRow: rowIndex, rowSpan: 1 };
|
|
2134
2291
|
}
|
|
2292
|
+
function findRowSpanColumn(spec, ref) {
|
|
2293
|
+
return spec.find((column) => column.columnId === ref) ?? spec.find((column) => column.rowSpanKey === ref);
|
|
2294
|
+
}
|
|
2135
2295
|
function buildColumnRowSpanMap(data, columnKeys) {
|
|
2136
2296
|
const map = /* @__PURE__ */ new Map();
|
|
2137
|
-
|
|
2138
|
-
|
|
2297
|
+
const visiting = /* @__PURE__ */ new Set();
|
|
2298
|
+
const warnedCycles = /* @__PURE__ */ new Set();
|
|
2299
|
+
const virtualParents = /* @__PURE__ */ new Map();
|
|
2300
|
+
const spansForColumn = (columnId) => {
|
|
2301
|
+
const cached = map.get(columnId);
|
|
2302
|
+
if (cached !== void 0) return cached;
|
|
2303
|
+
const column = columnKeys.find((item) => item.columnId === columnId);
|
|
2304
|
+
if (!column) return void 0;
|
|
2305
|
+
if (visiting.has(columnId)) {
|
|
2306
|
+
if (!warnedCycles.has(columnId)) {
|
|
2307
|
+
warnedCycles.add(columnId);
|
|
2308
|
+
console.warn(
|
|
2309
|
+
`[rowSpan] rowSpanParent cycle detected at column "${columnId}"; dropping the cyclic parent reference.`
|
|
2310
|
+
);
|
|
2311
|
+
}
|
|
2312
|
+
return void 0;
|
|
2313
|
+
}
|
|
2314
|
+
visiting.add(columnId);
|
|
2315
|
+
const parentSpans = (column.rowSpanParent ?? []).map((ref) => spansForParentRef(ref)).filter((spans2) => Boolean(spans2));
|
|
2316
|
+
visiting.delete(columnId);
|
|
2317
|
+
const spans = computeRowSpans(
|
|
2318
|
+
data,
|
|
2319
|
+
column.rowSpanKey,
|
|
2320
|
+
parentSpans.length > 0 ? parentSpans : void 0
|
|
2321
|
+
);
|
|
2322
|
+
map.set(columnId, spans);
|
|
2323
|
+
return spans;
|
|
2324
|
+
};
|
|
2325
|
+
const spansForParentRef = (ref) => {
|
|
2326
|
+
const parentColumn = findRowSpanColumn(columnKeys, ref);
|
|
2327
|
+
if (parentColumn) return spansForColumn(parentColumn.columnId);
|
|
2328
|
+
const cached = virtualParents.get(ref);
|
|
2329
|
+
if (cached !== void 0) return cached;
|
|
2330
|
+
const spans = computeRowSpans(data, ref);
|
|
2331
|
+
virtualParents.set(ref, spans);
|
|
2332
|
+
return spans;
|
|
2333
|
+
};
|
|
2334
|
+
for (const column of columnKeys) {
|
|
2335
|
+
spansForColumn(column.columnId);
|
|
2139
2336
|
}
|
|
2140
2337
|
return map;
|
|
2141
2338
|
}
|
|
@@ -2151,7 +2348,8 @@ function collectRowSpanColumns(columns) {
|
|
|
2151
2348
|
if (!columnId || !columnDef.meta?.rowSpan) continue;
|
|
2152
2349
|
result.push({
|
|
2153
2350
|
columnId,
|
|
2154
|
-
rowSpanKey: columnDef.meta.rowSpanKey ?? columnId
|
|
2351
|
+
rowSpanKey: columnDef.meta.rowSpanKey ?? columnId,
|
|
2352
|
+
rowSpanParent: normalizeRowSpanParent(columnDef.meta.rowSpanParent)
|
|
2155
2353
|
});
|
|
2156
2354
|
}
|
|
2157
2355
|
};
|
|
@@ -2203,6 +2401,9 @@ function useGlideTable(options) {
|
|
|
2203
2401
|
columnSizing: controlledColumnSizing,
|
|
2204
2402
|
onColumnSizingChange,
|
|
2205
2403
|
columnResizeMode = "onChange",
|
|
2404
|
+
enableColumnReorder = false,
|
|
2405
|
+
columnOrder: controlledColumnOrder,
|
|
2406
|
+
onColumnOrderChange,
|
|
2206
2407
|
enableColumnFreeze = false,
|
|
2207
2408
|
enableInlineSearch = false,
|
|
2208
2409
|
showSearch,
|
|
@@ -2225,6 +2426,7 @@ function useGlideTable(options) {
|
|
|
2225
2426
|
const resolvedEnableSubtreeCopy = enableSubtreeCopy ?? enableExpand;
|
|
2226
2427
|
const [internalRowSelection, setInternalRowSelection] = useState4({});
|
|
2227
2428
|
const [internalColumnSizing, setInternalColumnSizing] = useState4({});
|
|
2429
|
+
const [internalColumnOrder, setInternalColumnOrder] = useState4([]);
|
|
2228
2430
|
const [internalExpandedRows, setInternalExpandedRows] = useState4(
|
|
2229
2431
|
() => /* @__PURE__ */ new Set()
|
|
2230
2432
|
);
|
|
@@ -2245,6 +2447,21 @@ function useGlideTable(options) {
|
|
|
2245
2447
|
internalRowSelection
|
|
2246
2448
|
);
|
|
2247
2449
|
const columnSizing = controlledColumnSizing ?? internalColumnSizing;
|
|
2450
|
+
const columnOrder = controlledColumnOrder ?? internalColumnOrder;
|
|
2451
|
+
const tableColumns = useMemo3(() => {
|
|
2452
|
+
if (!enableColumnReorder) return columns;
|
|
2453
|
+
return applyLeafColumnOrder(columns, columnOrder);
|
|
2454
|
+
}, [columnOrder, columns, enableColumnReorder]);
|
|
2455
|
+
const setColumnOrder = useCallback4(
|
|
2456
|
+
(next) => {
|
|
2457
|
+
if (onColumnOrderChange) {
|
|
2458
|
+
onColumnOrderChange(next);
|
|
2459
|
+
return;
|
|
2460
|
+
}
|
|
2461
|
+
setInternalColumnOrder(next);
|
|
2462
|
+
},
|
|
2463
|
+
[onColumnOrderChange]
|
|
2464
|
+
);
|
|
2248
2465
|
const expandedRows = controlledExpandedRows ?? internalExpandedRows;
|
|
2249
2466
|
const handleExpandedRowsChange = useCallback4(
|
|
2250
2467
|
(next) => {
|
|
@@ -2269,7 +2486,7 @@ function useGlideTable(options) {
|
|
|
2269
2486
|
});
|
|
2270
2487
|
const table = useReactTable({
|
|
2271
2488
|
data: tableData,
|
|
2272
|
-
columns,
|
|
2489
|
+
columns: tableColumns,
|
|
2273
2490
|
...enableColumnResize ? {
|
|
2274
2491
|
defaultColumn: {
|
|
2275
2492
|
minSize: DATA_TABLE_COLUMN_MIN_SIZE,
|
|
@@ -2751,6 +2968,7 @@ function useGlideTable(options) {
|
|
|
2751
2968
|
selectionLabel: labels.selection,
|
|
2752
2969
|
enableCellSelection,
|
|
2753
2970
|
enableColumnResize,
|
|
2971
|
+
enableColumnReorder,
|
|
2754
2972
|
enableColumnFreeze,
|
|
2755
2973
|
enableInlineSearch,
|
|
2756
2974
|
shouldVirtualize,
|
|
@@ -2764,6 +2982,7 @@ function useGlideTable(options) {
|
|
|
2764
2982
|
getCellContext,
|
|
2765
2983
|
handleToggleSelect,
|
|
2766
2984
|
clearHover,
|
|
2985
|
+
setColumnOrder,
|
|
2767
2986
|
copySelection: stableCopySelection,
|
|
2768
2987
|
inlineSearch: {
|
|
2769
2988
|
showSearch: inlineSearch.showSearch,
|
|
@@ -2849,13 +3068,226 @@ function getColumnSizeStyle(size, options) {
|
|
|
2849
3068
|
};
|
|
2850
3069
|
}
|
|
2851
3070
|
|
|
3071
|
+
// src/components/ui/table/features/column-reorder/useColumnReorder.ts
|
|
3072
|
+
import {
|
|
3073
|
+
useCallback as useCallback6,
|
|
3074
|
+
useEffect as useEffect6,
|
|
3075
|
+
useRef as useRef6,
|
|
3076
|
+
useState as useState5
|
|
3077
|
+
} from "react";
|
|
3078
|
+
function hitTestReorderHeader(table, clientX, clientY) {
|
|
3079
|
+
const headers = Array.from(
|
|
3080
|
+
table.querySelectorAll(
|
|
3081
|
+
"thead th[data-column-id][data-reorder-ids]"
|
|
3082
|
+
)
|
|
3083
|
+
);
|
|
3084
|
+
const containing = headers.find((element) => {
|
|
3085
|
+
const rect = element.getBoundingClientRect();
|
|
3086
|
+
return clientX >= rect.left && clientX <= rect.right && clientY >= rect.top && clientY <= rect.bottom;
|
|
3087
|
+
});
|
|
3088
|
+
if (containing) {
|
|
3089
|
+
return {
|
|
3090
|
+
columnId: containing.dataset.columnId ?? "",
|
|
3091
|
+
edge: resolveDropEdge(clientX, containing.getBoundingClientRect())
|
|
3092
|
+
};
|
|
3093
|
+
}
|
|
3094
|
+
const leaves = headers.filter(
|
|
3095
|
+
(element) => element.hasAttribute("data-reorder-leaf")
|
|
3096
|
+
);
|
|
3097
|
+
let match;
|
|
3098
|
+
for (const element of leaves) {
|
|
3099
|
+
const rect = element.getBoundingClientRect();
|
|
3100
|
+
if (clientX >= rect.left && clientX <= rect.right) {
|
|
3101
|
+
match = element;
|
|
3102
|
+
break;
|
|
3103
|
+
}
|
|
3104
|
+
}
|
|
3105
|
+
if (!match && leaves.length > 0) {
|
|
3106
|
+
const first = leaves[0].getBoundingClientRect();
|
|
3107
|
+
const last = leaves[leaves.length - 1].getBoundingClientRect();
|
|
3108
|
+
if (clientX < first.left) match = leaves[0];
|
|
3109
|
+
else if (clientX > last.right) match = leaves[leaves.length - 1];
|
|
3110
|
+
}
|
|
3111
|
+
if (!match) return null;
|
|
3112
|
+
return {
|
|
3113
|
+
columnId: match.dataset.columnId ?? "",
|
|
3114
|
+
edge: resolveDropEdge(clientX, match.getBoundingClientRect())
|
|
3115
|
+
};
|
|
3116
|
+
}
|
|
3117
|
+
function readTargetIds(table, columnId) {
|
|
3118
|
+
const element = table.querySelector(
|
|
3119
|
+
`thead th[data-column-id="${CSS.escape(columnId)}"]`
|
|
3120
|
+
);
|
|
3121
|
+
return parseReorderIds(element?.getAttribute("data-reorder-ids"));
|
|
3122
|
+
}
|
|
3123
|
+
function useColumnReorder(options) {
|
|
3124
|
+
const { enabled, columnOrder, onColumnOrderChange } = options;
|
|
3125
|
+
const sessionRef = useRef6(null);
|
|
3126
|
+
const columnOrderRef = useRef6(columnOrder);
|
|
3127
|
+
const onColumnOrderChangeRef = useRef6(onColumnOrderChange);
|
|
3128
|
+
const [draggingColumnId, setDraggingColumnId] = useState5(null);
|
|
3129
|
+
const [dropTarget, setDropTarget] = useState5(
|
|
3130
|
+
null
|
|
3131
|
+
);
|
|
3132
|
+
const dropTargetRef = useRef6(dropTarget);
|
|
3133
|
+
const previousUserSelectRef = useRef6(null);
|
|
3134
|
+
columnOrderRef.current = columnOrder;
|
|
3135
|
+
onColumnOrderChangeRef.current = onColumnOrderChange;
|
|
3136
|
+
dropTargetRef.current = dropTarget;
|
|
3137
|
+
const resetDrag = useCallback6(() => {
|
|
3138
|
+
sessionRef.current = null;
|
|
3139
|
+
setDraggingColumnId(null);
|
|
3140
|
+
setDropTarget(null);
|
|
3141
|
+
const backup = previousUserSelectRef.current;
|
|
3142
|
+
previousUserSelectRef.current = null;
|
|
3143
|
+
if (backup) {
|
|
3144
|
+
if (backup.value) {
|
|
3145
|
+
document.body.style.setProperty("user-select", backup.value, backup.priority);
|
|
3146
|
+
} else {
|
|
3147
|
+
document.body.style.removeProperty("user-select");
|
|
3148
|
+
}
|
|
3149
|
+
return;
|
|
3150
|
+
}
|
|
3151
|
+
document.body.style.removeProperty("user-select");
|
|
3152
|
+
}, []);
|
|
3153
|
+
useEffect6(() => {
|
|
3154
|
+
if (!enabled) resetDrag();
|
|
3155
|
+
}, [enabled, resetDrag]);
|
|
3156
|
+
useEffect6(() => {
|
|
3157
|
+
return () => {
|
|
3158
|
+
resetDrag();
|
|
3159
|
+
};
|
|
3160
|
+
}, [resetDrag]);
|
|
3161
|
+
const onHeaderPointerDown = useCallback6(
|
|
3162
|
+
(event, meta) => {
|
|
3163
|
+
if (!enabled || !meta.canDrag) return;
|
|
3164
|
+
if (event.button !== 0) return;
|
|
3165
|
+
if (event.pointerType === "mouse" && event.ctrlKey) return;
|
|
3166
|
+
const target = event.target;
|
|
3167
|
+
if (target instanceof Element && target.closest("[data-table-disable-cell-selection]")) {
|
|
3168
|
+
return;
|
|
3169
|
+
}
|
|
3170
|
+
const table = event.currentTarget.closest("table");
|
|
3171
|
+
if (!(table instanceof HTMLTableElement)) return;
|
|
3172
|
+
sessionRef.current = {
|
|
3173
|
+
pointerId: event.pointerId,
|
|
3174
|
+
startX: event.clientX,
|
|
3175
|
+
startY: event.clientY,
|
|
3176
|
+
columnId: meta.columnId,
|
|
3177
|
+
fromIds: meta.leafIds,
|
|
3178
|
+
table,
|
|
3179
|
+
active: false
|
|
3180
|
+
};
|
|
3181
|
+
},
|
|
3182
|
+
[enabled]
|
|
3183
|
+
);
|
|
3184
|
+
useEffect6(() => {
|
|
3185
|
+
if (!enabled) return;
|
|
3186
|
+
const onPointerMove = (event) => {
|
|
3187
|
+
const session = sessionRef.current;
|
|
3188
|
+
if (!session || event.pointerId !== session.pointerId) return;
|
|
3189
|
+
const deltaX = event.clientX - session.startX;
|
|
3190
|
+
const deltaY = event.clientY - session.startY;
|
|
3191
|
+
const distance = Math.hypot(deltaX, deltaY);
|
|
3192
|
+
if (!session.active) {
|
|
3193
|
+
if (distance < DATA_TABLE_COLUMN_REORDER_THRESHOLD) return;
|
|
3194
|
+
session.active = true;
|
|
3195
|
+
if (!previousUserSelectRef.current) {
|
|
3196
|
+
previousUserSelectRef.current = {
|
|
3197
|
+
value: document.body.style.getPropertyValue("user-select"),
|
|
3198
|
+
priority: document.body.style.getPropertyPriority("user-select")
|
|
3199
|
+
};
|
|
3200
|
+
}
|
|
3201
|
+
document.body.style.setProperty("user-select", "none");
|
|
3202
|
+
setDraggingColumnId(session.columnId);
|
|
3203
|
+
}
|
|
3204
|
+
event.preventDefault();
|
|
3205
|
+
const nextTarget = hitTestReorderHeader(
|
|
3206
|
+
session.table,
|
|
3207
|
+
event.clientX,
|
|
3208
|
+
event.clientY
|
|
3209
|
+
);
|
|
3210
|
+
if (!nextTarget || !nextTarget.columnId) {
|
|
3211
|
+
setDropTarget(null);
|
|
3212
|
+
return;
|
|
3213
|
+
}
|
|
3214
|
+
const targetIds = readTargetIds(session.table, nextTarget.columnId);
|
|
3215
|
+
const fromSet = new Set(session.fromIds);
|
|
3216
|
+
if (targetIds.some((id) => fromSet.has(id))) {
|
|
3217
|
+
setDropTarget(null);
|
|
3218
|
+
return;
|
|
3219
|
+
}
|
|
3220
|
+
setDropTarget((previous) => {
|
|
3221
|
+
if (previous?.columnId === nextTarget.columnId && previous.edge === nextTarget.edge) {
|
|
3222
|
+
return previous;
|
|
3223
|
+
}
|
|
3224
|
+
return nextTarget;
|
|
3225
|
+
});
|
|
3226
|
+
};
|
|
3227
|
+
const onPointerUp = (event) => {
|
|
3228
|
+
const session = sessionRef.current;
|
|
3229
|
+
if (!session || event.pointerId !== session.pointerId) {
|
|
3230
|
+
return;
|
|
3231
|
+
}
|
|
3232
|
+
if (session.active) {
|
|
3233
|
+
event.preventDefault();
|
|
3234
|
+
const target = dropTargetRef.current;
|
|
3235
|
+
if (target) {
|
|
3236
|
+
const targetIds = readTargetIds(session.table, target.columnId);
|
|
3237
|
+
const next = moveColumnIds(
|
|
3238
|
+
columnOrderRef.current,
|
|
3239
|
+
session.fromIds,
|
|
3240
|
+
targetIds,
|
|
3241
|
+
target.edge
|
|
3242
|
+
);
|
|
3243
|
+
onColumnOrderChangeRef.current(next);
|
|
3244
|
+
}
|
|
3245
|
+
const suppressClick = (clickEvent) => {
|
|
3246
|
+
clickEvent.preventDefault();
|
|
3247
|
+
clickEvent.stopPropagation();
|
|
3248
|
+
document.removeEventListener("click", suppressClick, true);
|
|
3249
|
+
};
|
|
3250
|
+
document.addEventListener("click", suppressClick, true);
|
|
3251
|
+
window.setTimeout(() => {
|
|
3252
|
+
document.removeEventListener("click", suppressClick, true);
|
|
3253
|
+
}, 0);
|
|
3254
|
+
}
|
|
3255
|
+
resetDrag();
|
|
3256
|
+
};
|
|
3257
|
+
const onPointerCancel = (event) => {
|
|
3258
|
+
const session = sessionRef.current;
|
|
3259
|
+
if (!session || event.pointerId !== session.pointerId) {
|
|
3260
|
+
return;
|
|
3261
|
+
}
|
|
3262
|
+
if (session.active) {
|
|
3263
|
+
event.preventDefault();
|
|
3264
|
+
}
|
|
3265
|
+
resetDrag();
|
|
3266
|
+
};
|
|
3267
|
+
document.addEventListener("pointermove", onPointerMove);
|
|
3268
|
+
document.addEventListener("pointerup", onPointerUp);
|
|
3269
|
+
document.addEventListener("pointercancel", onPointerCancel);
|
|
3270
|
+
return () => {
|
|
3271
|
+
document.removeEventListener("pointermove", onPointerMove);
|
|
3272
|
+
document.removeEventListener("pointerup", onPointerUp);
|
|
3273
|
+
document.removeEventListener("pointercancel", onPointerCancel);
|
|
3274
|
+
};
|
|
3275
|
+
}, [enabled, resetDrag]);
|
|
3276
|
+
return {
|
|
3277
|
+
isReordering: draggingColumnId != null,
|
|
3278
|
+
draggingColumnId,
|
|
3279
|
+
dropTarget,
|
|
3280
|
+
onHeaderPointerDown
|
|
3281
|
+
};
|
|
3282
|
+
}
|
|
3283
|
+
|
|
2852
3284
|
// src/components/ui/table/components/DataTable/DataTable.tsx
|
|
2853
3285
|
import { flexRender as flexRender2 } from "@tanstack/react-table";
|
|
2854
3286
|
import { useMemo as useMemo4 } from "react";
|
|
2855
3287
|
|
|
2856
3288
|
// src/components/ui/table/components/DataTable/DataTableRow.tsx
|
|
2857
3289
|
import { flexRender } from "@tanstack/react-table";
|
|
2858
|
-
import { useEffect as
|
|
3290
|
+
import { useEffect as useEffect7, useRef as useRef7 } from "react";
|
|
2859
3291
|
|
|
2860
3292
|
// src/components/ui/table/components/icons.tsx
|
|
2861
3293
|
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
@@ -3153,9 +3585,9 @@ function DataTableRow({
|
|
|
3153
3585
|
const expandKey = toggleField && rowData[toggleField] !== null && rowData[toggleField] !== void 0 ? String(rowData[toggleField]) : null;
|
|
3154
3586
|
const isExpanded = expandKey !== null && Boolean(expandedRows?.has(expandKey));
|
|
3155
3587
|
const rowLevel = typeof rowData.level === "number" ? rowData.level : 0;
|
|
3156
|
-
const editInputRef =
|
|
3588
|
+
const editInputRef = useRef7(null);
|
|
3157
3589
|
const isRowEditing = editingCell?.rowIndex === rowIndex;
|
|
3158
|
-
|
|
3590
|
+
useEffect7(() => {
|
|
3159
3591
|
if (!isRowEditing) return;
|
|
3160
3592
|
editInputRef.current?.focus();
|
|
3161
3593
|
editInputRef.current?.select();
|
|
@@ -3753,6 +4185,7 @@ function DataTable({
|
|
|
3753
4185
|
selectionLabel,
|
|
3754
4186
|
enableCellSelection,
|
|
3755
4187
|
enableColumnResize,
|
|
4188
|
+
enableColumnReorder,
|
|
3756
4189
|
enableColumnFreeze,
|
|
3757
4190
|
enableInlineSearch,
|
|
3758
4191
|
shouldVirtualize,
|
|
@@ -3765,6 +4198,7 @@ function DataTable({
|
|
|
3765
4198
|
rowContextValue,
|
|
3766
4199
|
handleToggleSelect,
|
|
3767
4200
|
clearHover,
|
|
4201
|
+
setColumnOrder,
|
|
3768
4202
|
inlineSearch
|
|
3769
4203
|
} = useGlideTable(glideOptions);
|
|
3770
4204
|
const ToolbarSlot = slots?.Toolbar ?? DataTableToolbar;
|
|
@@ -3774,6 +4208,12 @@ function DataTable({
|
|
|
3774
4208
|
const EmptySlot = slots?.Empty ?? DefaultEmpty;
|
|
3775
4209
|
const freezeOffsets = rowContextValue.columnFreeze.offsets;
|
|
3776
4210
|
const headerGroups = getMergedHeaderGroups(table.getHeaderGroups());
|
|
4211
|
+
const leafColumnIds = table.getVisibleLeafColumns().map((column) => column.id);
|
|
4212
|
+
const { isReordering, draggingColumnId, dropTarget, onHeaderPointerDown } = useColumnReorder({
|
|
4213
|
+
enabled: enableColumnReorder,
|
|
4214
|
+
columnOrder: leafColumnIds,
|
|
4215
|
+
onColumnOrderChange: setColumnOrder
|
|
4216
|
+
});
|
|
3777
4217
|
const contextValue = useMemo4(
|
|
3778
4218
|
() => ({ ...rowContextValue, classNames }),
|
|
3779
4219
|
[rowContextValue, classNames]
|
|
@@ -3796,6 +4236,8 @@ function DataTable({
|
|
|
3796
4236
|
"DataTableJSX",
|
|
3797
4237
|
!enableCellSelection && "DataTableJSX--no-cell-selection",
|
|
3798
4238
|
enableColumnResize && "DataTableJSX--column-resize",
|
|
4239
|
+
enableColumnReorder && "DataTableJSX--column-reorder",
|
|
4240
|
+
isReordering && "DataTableJSX--column-reordering",
|
|
3799
4241
|
enableColumnFreeze && "DataTableJSX--column-freeze",
|
|
3800
4242
|
enableInlineSearch && "DataTableJSX--inline-search",
|
|
3801
4243
|
classNames?.root,
|
|
@@ -3864,20 +4306,43 @@ function DataTable({
|
|
|
3864
4306
|
...sizeStyle,
|
|
3865
4307
|
...freezeStyle
|
|
3866
4308
|
};
|
|
4309
|
+
const isPlaceholder = header.isPlaceholder;
|
|
4310
|
+
const leafColumns = header.column.getLeafColumns();
|
|
4311
|
+
const leafIds = leafColumns.map((leafColumn) => leafColumn.id);
|
|
4312
|
+
const isLeafHeader = !isPlaceholder && header.subHeaders.length === 0;
|
|
4313
|
+
const canDrag = enableColumnReorder && !isPlaceholder && leafIds.length > 0 && leafColumns.every(
|
|
4314
|
+
(leafColumn) => isColumnReorderable(leafColumn.columnDef.meta)
|
|
4315
|
+
);
|
|
4316
|
+
const isDragging = draggingColumnId === header.column.id;
|
|
4317
|
+
const dropEdge = !isPlaceholder && dropTarget?.columnId === header.column.id ? dropTarget.edge : void 0;
|
|
3867
4318
|
return /* @__PURE__ */ jsxs6(
|
|
3868
4319
|
"th",
|
|
3869
4320
|
{
|
|
3870
4321
|
colSpan: header.colSpan,
|
|
3871
4322
|
rowSpan: header.mergedRowSpan,
|
|
4323
|
+
"data-column-id": enableColumnReorder && !isPlaceholder ? header.column.id : void 0,
|
|
4324
|
+
"data-reorder-ids": enableColumnReorder && !isPlaceholder ? serializeReorderIds(leafIds) : void 0,
|
|
4325
|
+
"data-reorder-leaf": enableColumnReorder && isLeafHeader ? "" : void 0,
|
|
4326
|
+
"data-reorderable": canDrag ? "" : void 0,
|
|
4327
|
+
"data-reordering": isDragging ? "" : void 0,
|
|
4328
|
+
"data-drop-edge": dropEdge,
|
|
3872
4329
|
"data-resizing": header.column.getIsResizing() ? "" : void 0,
|
|
3873
4330
|
"data-frozen": freezeOffset?.side,
|
|
3874
4331
|
"data-freeze-edge": getColumnFreezeEdgeAttr(freezeOffset),
|
|
4332
|
+
"aria-grabbed": isDragging ? true : void 0,
|
|
4333
|
+
title: canDrag ? labels.reorderColumn : void 0,
|
|
4334
|
+
onPointerDown: enableColumnReorder ? (event) => onHeaderPointerDown(event, {
|
|
4335
|
+
columnId: header.column.id,
|
|
4336
|
+
leafIds,
|
|
4337
|
+
canDrag
|
|
4338
|
+
}) : void 0,
|
|
3875
4339
|
style: Object.keys(headerStyle).length > 0 ? headerStyle : void 0,
|
|
3876
4340
|
className: cn(
|
|
3877
4341
|
"data-table-head-cell",
|
|
3878
4342
|
freezeOffset && `data-table-head-cell--frozen-${freezeOffset.side}`,
|
|
3879
4343
|
CELL_ALIGN_CLASS[align],
|
|
3880
4344
|
classNames?.headCell,
|
|
4345
|
+
dropEdge && classNames?.dropEdge,
|
|
3881
4346
|
headerClassName
|
|
3882
4347
|
),
|
|
3883
4348
|
children: [
|
|
@@ -3999,7 +4464,7 @@ function DataTable({
|
|
|
3999
4464
|
}
|
|
4000
4465
|
|
|
4001
4466
|
// src/components/ui/table/components/Table/Table.tsx
|
|
4002
|
-
import { useCallback as
|
|
4467
|
+
import { useCallback as useCallback7, useMemo as useMemo5, useState as useState6 } from "react";
|
|
4003
4468
|
|
|
4004
4469
|
// src/components/ui/table/components/Table/buildColumnDef.tsx
|
|
4005
4470
|
import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
@@ -4037,10 +4502,12 @@ function buildColumnDef(props, sort, onSort) {
|
|
|
4037
4502
|
minWidth,
|
|
4038
4503
|
maxWidth,
|
|
4039
4504
|
resizable,
|
|
4505
|
+
reorderable,
|
|
4040
4506
|
frozen,
|
|
4041
4507
|
align,
|
|
4042
4508
|
rowSpan,
|
|
4043
4509
|
rowSpanKey,
|
|
4510
|
+
rowSpanParent,
|
|
4044
4511
|
editable,
|
|
4045
4512
|
editType,
|
|
4046
4513
|
editInputProps,
|
|
@@ -4075,6 +4542,7 @@ function buildColumnDef(props, sort, onSort) {
|
|
|
4075
4542
|
align,
|
|
4076
4543
|
rowSpan,
|
|
4077
4544
|
rowSpanKey,
|
|
4545
|
+
rowSpanParent,
|
|
4078
4546
|
editable,
|
|
4079
4547
|
editType,
|
|
4080
4548
|
editInputProps,
|
|
@@ -4082,6 +4550,7 @@ function buildColumnDef(props, sort, onSort) {
|
|
|
4082
4550
|
cellProps,
|
|
4083
4551
|
cellRender: render,
|
|
4084
4552
|
frozen,
|
|
4553
|
+
reorderable,
|
|
4085
4554
|
className,
|
|
4086
4555
|
headerClassName
|
|
4087
4556
|
}
|
|
@@ -4329,8 +4798,8 @@ function TableRoot({
|
|
|
4329
4798
|
() => parseTableChildren(children),
|
|
4330
4799
|
[children]
|
|
4331
4800
|
);
|
|
4332
|
-
const [sort, setSort] =
|
|
4333
|
-
const handleSort =
|
|
4801
|
+
const [sort, setSort] = useState6(null);
|
|
4802
|
+
const handleSort = useCallback7((field) => {
|
|
4334
4803
|
setSort((previous) => {
|
|
4335
4804
|
if (previous?.field !== field) {
|
|
4336
4805
|
return { field, direction: "asc" };
|
|
@@ -4427,6 +4896,7 @@ export {
|
|
|
4427
4896
|
Table,
|
|
4428
4897
|
applyCellEdit,
|
|
4429
4898
|
applyFillData,
|
|
4899
|
+
applyLeafColumnOrder,
|
|
4430
4900
|
applySelectionUpdater,
|
|
4431
4901
|
buildColumnFreezeOffsets,
|
|
4432
4902
|
buildColumnRowSpanMap,
|
|
@@ -4441,6 +4911,7 @@ export {
|
|
|
4441
4911
|
collectCopyRowEntries,
|
|
4442
4912
|
collectCopyRows,
|
|
4443
4913
|
collectFillChanges,
|
|
4914
|
+
collectLeafColumnIds,
|
|
4444
4915
|
collectRowSpanColumns,
|
|
4445
4916
|
collectSearchMatchesInRange,
|
|
4446
4917
|
commitCellValue,
|
|
@@ -4466,6 +4937,7 @@ export {
|
|
|
4466
4937
|
mapSearchResultToVisibleItem,
|
|
4467
4938
|
mapSearchResultsToVisibleKeys,
|
|
4468
4939
|
measureMergedSpanRowHeights,
|
|
4940
|
+
moveColumnIds,
|
|
4469
4941
|
nextSearchIndex,
|
|
4470
4942
|
nextSearchStride,
|
|
4471
4943
|
parseCellEditValue,
|
|
@@ -4475,7 +4947,9 @@ export {
|
|
|
4475
4947
|
resolveCellRenderer,
|
|
4476
4948
|
resolveColumnFreezeSide,
|
|
4477
4949
|
resolveDataTableLabels,
|
|
4950
|
+
resolveDropEdge,
|
|
4478
4951
|
resolveHeaderFreezeOffset,
|
|
4952
|
+
resolveLeafColumnOrder,
|
|
4479
4953
|
resolvePasteColumnIds,
|
|
4480
4954
|
resolveRowSelection,
|
|
4481
4955
|
resolveRowSpanAt,
|
|
@@ -4485,6 +4959,7 @@ export {
|
|
|
4485
4959
|
toggleExpandedRowId,
|
|
4486
4960
|
useCellEdit,
|
|
4487
4961
|
useCellSelection,
|
|
4962
|
+
useColumnReorder,
|
|
4488
4963
|
useConvertTreeData,
|
|
4489
4964
|
useGlideTable,
|
|
4490
4965
|
useInlineSearch,
|