react-glide-table 2.0.2 → 2.1.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/index.cjs CHANGED
@@ -33,6 +33,7 @@ __export(src_exports, {
33
33
  Table: () => Table,
34
34
  applyCellEdit: () => applyCellEdit,
35
35
  applyFillData: () => applyFillData,
36
+ applyLeafColumnOrder: () => applyLeafColumnOrder,
36
37
  applySelectionUpdater: () => applySelectionUpdater,
37
38
  buildColumnFreezeOffsets: () => buildColumnFreezeOffsets,
38
39
  buildColumnRowSpanMap: () => buildColumnRowSpanMap,
@@ -47,6 +48,7 @@ __export(src_exports, {
47
48
  collectCopyRowEntries: () => collectCopyRowEntries,
48
49
  collectCopyRows: () => collectCopyRows,
49
50
  collectFillChanges: () => collectFillChanges,
51
+ collectLeafColumnIds: () => collectLeafColumnIds,
50
52
  collectRowSpanColumns: () => collectRowSpanColumns,
51
53
  collectSearchMatchesInRange: () => collectSearchMatchesInRange,
52
54
  commitCellValue: () => commitCellValue,
@@ -72,6 +74,7 @@ __export(src_exports, {
72
74
  mapSearchResultToVisibleItem: () => mapSearchResultToVisibleItem,
73
75
  mapSearchResultsToVisibleKeys: () => mapSearchResultsToVisibleKeys,
74
76
  measureMergedSpanRowHeights: () => measureMergedSpanRowHeights,
77
+ moveColumnIds: () => moveColumnIds,
75
78
  nextSearchIndex: () => nextSearchIndex,
76
79
  nextSearchStride: () => nextSearchStride,
77
80
  parseCellEditValue: () => parseCellEditValue,
@@ -81,7 +84,9 @@ __export(src_exports, {
81
84
  resolveCellRenderer: () => resolveCellRenderer,
82
85
  resolveColumnFreezeSide: () => resolveColumnFreezeSide,
83
86
  resolveDataTableLabels: () => resolveDataTableLabels,
87
+ resolveDropEdge: () => resolveDropEdge,
84
88
  resolveHeaderFreezeOffset: () => resolveHeaderFreezeOffset,
89
+ resolveLeafColumnOrder: () => resolveLeafColumnOrder,
85
90
  resolvePasteColumnIds: () => resolvePasteColumnIds,
86
91
  resolveRowSelection: () => resolveRowSelection,
87
92
  resolveRowSpanAt: () => resolveRowSpanAt,
@@ -91,6 +96,7 @@ __export(src_exports, {
91
96
  toggleExpandedRowId: () => toggleExpandedRowId,
92
97
  useCellEdit: () => useCellEdit,
93
98
  useCellSelection: () => useCellSelection,
99
+ useColumnReorder: () => useColumnReorder,
94
100
  useConvertTreeData: () => useConvertTreeData,
95
101
  useGlideTable: () => useGlideTable,
96
102
  useInlineSearch: () => useInlineSearch,
@@ -107,6 +113,7 @@ var DEFAULT_DATA_TABLE_LABELS = {
107
113
  expandRow: "Expand row",
108
114
  collapseRow: "Collapse row",
109
115
  resizeColumn: "Resize column",
116
+ reorderColumn: "Reorder column",
110
117
  searchPlaceholder: "Search\u2026",
111
118
  searchResultHint: "Type to search",
112
119
  searchPrevious: "Previous result",
@@ -146,6 +153,7 @@ var DATA_TABLE_VIRTUAL_OVERSCAN = 8;
146
153
  var DATA_TABLE_COLUMN_SIZE = 150;
147
154
  var DATA_TABLE_COLUMN_MIN_SIZE = 40;
148
155
  var DATA_TABLE_COLUMN_MAX_SIZE = 800;
156
+ var DATA_TABLE_COLUMN_REORDER_THRESHOLD = 4;
149
157
 
150
158
  // src/components/ui/table/features/cell-edit/useCellEdit.ts
151
159
  var import_react = require("react");
@@ -1411,6 +1419,135 @@ function useCellSelection({
1411
1419
  };
1412
1420
  }
1413
1421
 
1422
+ // src/components/ui/table/features/column-reorder/columnReorder.ts
1423
+ function getColumnDefId(column) {
1424
+ if (column.id != null && column.id !== "") return column.id;
1425
+ if ("accessorKey" in column && column.accessorKey != null) {
1426
+ return String(column.accessorKey);
1427
+ }
1428
+ return void 0;
1429
+ }
1430
+ function getColumnDefChildren(column) {
1431
+ if (!("columns" in column) || !Array.isArray(column.columns)) return void 0;
1432
+ if (column.columns.length === 0) return void 0;
1433
+ return column.columns;
1434
+ }
1435
+ function collectLeafColumnIds(columns) {
1436
+ const ids = [];
1437
+ for (const column of columns) {
1438
+ const children = getColumnDefChildren(column);
1439
+ if (children) {
1440
+ ids.push(...collectLeafColumnIds(children));
1441
+ continue;
1442
+ }
1443
+ const id = getColumnDefId(column);
1444
+ if (id) ids.push(id);
1445
+ }
1446
+ return ids;
1447
+ }
1448
+ function areColumnOrdersEqual(left, right) {
1449
+ if (left.length !== right.length) return false;
1450
+ return left.every((id, index) => id === right[index]);
1451
+ }
1452
+ function resolveLeafColumnOrder(columns, order) {
1453
+ const leafIds = collectLeafColumnIds(columns);
1454
+ if (!order?.length) return leafIds;
1455
+ const leafSet = new Set(leafIds);
1456
+ const seen = /* @__PURE__ */ new Set();
1457
+ const next = order.filter((id) => {
1458
+ if (!leafSet.has(id) || seen.has(id)) return false;
1459
+ seen.add(id);
1460
+ return true;
1461
+ });
1462
+ for (const id of leafIds) {
1463
+ if (!seen.has(id)) next.push(id);
1464
+ }
1465
+ return next;
1466
+ }
1467
+ function flattenColumnSlots(columns, group) {
1468
+ const slots = [];
1469
+ for (const column of columns) {
1470
+ const id = getColumnDefId(column);
1471
+ const children = getColumnDefChildren(column);
1472
+ if (children) {
1473
+ const nestedGroup = id ? { id, def: column } : group;
1474
+ slots.push(...flattenColumnSlots(children, nestedGroup));
1475
+ continue;
1476
+ }
1477
+ if (!id) continue;
1478
+ slots.push({ id, def: column, group });
1479
+ }
1480
+ return slots;
1481
+ }
1482
+ function rebuildColumnTree(slots) {
1483
+ const result = [];
1484
+ let index = 0;
1485
+ while (index < slots.length) {
1486
+ const slot = slots[index];
1487
+ if (!slot.group) {
1488
+ result.push(slot.def);
1489
+ index += 1;
1490
+ continue;
1491
+ }
1492
+ const groupId = slot.group.id;
1493
+ const children = [];
1494
+ while (index < slots.length && slots[index]?.group?.id === groupId) {
1495
+ children.push(slots[index].def);
1496
+ index += 1;
1497
+ }
1498
+ const firstChildId = children[0] ? getColumnDefId(children[0]) : groupId;
1499
+ result.push({
1500
+ ...slot.group.def,
1501
+ id: `${groupId}::${firstChildId}`,
1502
+ columns: children
1503
+ });
1504
+ }
1505
+ return result;
1506
+ }
1507
+ function applyLeafColumnOrder(columns, order) {
1508
+ const resolved = resolveLeafColumnOrder(columns, order);
1509
+ const defaultOrder = collectLeafColumnIds(columns);
1510
+ if (areColumnOrdersEqual(resolved, defaultOrder)) {
1511
+ return columns;
1512
+ }
1513
+ const byId = new Map(
1514
+ flattenColumnSlots(columns).map((slot) => [
1515
+ slot.id,
1516
+ slot
1517
+ ])
1518
+ );
1519
+ const ordered = [];
1520
+ for (const id of resolved) {
1521
+ const slot = byId.get(id);
1522
+ if (slot) ordered.push(slot);
1523
+ }
1524
+ return rebuildColumnTree(ordered);
1525
+ }
1526
+ function moveColumnIds(order, fromIds, targetIds, edge) {
1527
+ if (fromIds.length === 0 || targetIds.length === 0) return [...order];
1528
+ const fromSet = new Set(fromIds);
1529
+ if (targetIds.some((id) => fromSet.has(id))) return [...order];
1530
+ const rest = order.filter((id) => !fromSet.has(id));
1531
+ const anchorId = edge === "before" ? targetIds[0] : targetIds[targetIds.length - 1];
1532
+ const anchorIndex = rest.indexOf(anchorId);
1533
+ if (anchorIndex < 0) return [...order];
1534
+ const insertAt = edge === "before" ? anchorIndex : anchorIndex + 1;
1535
+ return [...rest.slice(0, insertAt), ...fromIds, ...rest.slice(insertAt)];
1536
+ }
1537
+ function resolveDropEdge(clientX, rect) {
1538
+ return clientX < rect.left + rect.width / 2 ? "before" : "after";
1539
+ }
1540
+ function parseReorderIds(value) {
1541
+ if (!value) return [];
1542
+ return value.split(",").filter(Boolean);
1543
+ }
1544
+ function serializeReorderIds(ids) {
1545
+ return ids.join(",");
1546
+ }
1547
+ function isColumnReorderable(meta) {
1548
+ return meta?.reorderable !== false;
1549
+ }
1550
+
1414
1551
  // src/components/ui/table/features/column-freeze/columnFreeze.ts
1415
1552
  var HEADER_Z_BASE = 30;
1416
1553
  var BODY_Z_BASE = 5;
@@ -2286,6 +2423,9 @@ function useGlideTable(options) {
2286
2423
  columnSizing: controlledColumnSizing,
2287
2424
  onColumnSizingChange,
2288
2425
  columnResizeMode = "onChange",
2426
+ enableColumnReorder = false,
2427
+ columnOrder: controlledColumnOrder,
2428
+ onColumnOrderChange,
2289
2429
  enableColumnFreeze = false,
2290
2430
  enableInlineSearch = false,
2291
2431
  showSearch,
@@ -2308,6 +2448,7 @@ function useGlideTable(options) {
2308
2448
  const resolvedEnableSubtreeCopy = enableSubtreeCopy ?? enableExpand;
2309
2449
  const [internalRowSelection, setInternalRowSelection] = (0, import_react5.useState)({});
2310
2450
  const [internalColumnSizing, setInternalColumnSizing] = (0, import_react5.useState)({});
2451
+ const [internalColumnOrder, setInternalColumnOrder] = (0, import_react5.useState)([]);
2311
2452
  const [internalExpandedRows, setInternalExpandedRows] = (0, import_react5.useState)(
2312
2453
  () => /* @__PURE__ */ new Set()
2313
2454
  );
@@ -2328,6 +2469,21 @@ function useGlideTable(options) {
2328
2469
  internalRowSelection
2329
2470
  );
2330
2471
  const columnSizing = controlledColumnSizing ?? internalColumnSizing;
2472
+ const columnOrder = controlledColumnOrder ?? internalColumnOrder;
2473
+ const tableColumns = (0, import_react5.useMemo)(() => {
2474
+ if (!enableColumnReorder) return columns;
2475
+ return applyLeafColumnOrder(columns, columnOrder);
2476
+ }, [columnOrder, columns, enableColumnReorder]);
2477
+ const setColumnOrder = (0, import_react5.useCallback)(
2478
+ (next) => {
2479
+ if (onColumnOrderChange) {
2480
+ onColumnOrderChange(next);
2481
+ return;
2482
+ }
2483
+ setInternalColumnOrder(next);
2484
+ },
2485
+ [onColumnOrderChange]
2486
+ );
2331
2487
  const expandedRows = controlledExpandedRows ?? internalExpandedRows;
2332
2488
  const handleExpandedRowsChange = (0, import_react5.useCallback)(
2333
2489
  (next) => {
@@ -2352,7 +2508,7 @@ function useGlideTable(options) {
2352
2508
  });
2353
2509
  const table = (0, import_react_table.useReactTable)({
2354
2510
  data: tableData,
2355
- columns,
2511
+ columns: tableColumns,
2356
2512
  ...enableColumnResize ? {
2357
2513
  defaultColumn: {
2358
2514
  minSize: DATA_TABLE_COLUMN_MIN_SIZE,
@@ -2834,6 +2990,7 @@ function useGlideTable(options) {
2834
2990
  selectionLabel: labels.selection,
2835
2991
  enableCellSelection,
2836
2992
  enableColumnResize,
2993
+ enableColumnReorder,
2837
2994
  enableColumnFreeze,
2838
2995
  enableInlineSearch,
2839
2996
  shouldVirtualize,
@@ -2847,6 +3004,7 @@ function useGlideTable(options) {
2847
3004
  getCellContext,
2848
3005
  handleToggleSelect,
2849
3006
  clearHover,
3007
+ setColumnOrder,
2850
3008
  copySelection: stableCopySelection,
2851
3009
  inlineSearch: {
2852
3010
  showSearch: inlineSearch.showSearch,
@@ -2932,13 +3090,221 @@ function getColumnSizeStyle(size, options) {
2932
3090
  };
2933
3091
  }
2934
3092
 
3093
+ // src/components/ui/table/features/column-reorder/useColumnReorder.ts
3094
+ var import_react8 = require("react");
3095
+ function hitTestReorderHeader(table, clientX, clientY) {
3096
+ const headers = Array.from(
3097
+ table.querySelectorAll(
3098
+ "thead th[data-column-id][data-reorder-ids]"
3099
+ )
3100
+ );
3101
+ const containing = headers.find((element) => {
3102
+ const rect = element.getBoundingClientRect();
3103
+ return clientX >= rect.left && clientX <= rect.right && clientY >= rect.top && clientY <= rect.bottom;
3104
+ });
3105
+ if (containing) {
3106
+ return {
3107
+ columnId: containing.dataset.columnId ?? "",
3108
+ edge: resolveDropEdge(clientX, containing.getBoundingClientRect())
3109
+ };
3110
+ }
3111
+ const leaves = headers.filter(
3112
+ (element) => element.hasAttribute("data-reorder-leaf")
3113
+ );
3114
+ let match;
3115
+ for (const element of leaves) {
3116
+ const rect = element.getBoundingClientRect();
3117
+ if (clientX >= rect.left && clientX <= rect.right) {
3118
+ match = element;
3119
+ break;
3120
+ }
3121
+ }
3122
+ if (!match && leaves.length > 0) {
3123
+ const first = leaves[0].getBoundingClientRect();
3124
+ const last = leaves[leaves.length - 1].getBoundingClientRect();
3125
+ if (clientX < first.left) match = leaves[0];
3126
+ else if (clientX > last.right) match = leaves[leaves.length - 1];
3127
+ }
3128
+ if (!match) return null;
3129
+ return {
3130
+ columnId: match.dataset.columnId ?? "",
3131
+ edge: resolveDropEdge(clientX, match.getBoundingClientRect())
3132
+ };
3133
+ }
3134
+ function readTargetIds(table, columnId) {
3135
+ const element = table.querySelector(
3136
+ `thead th[data-column-id="${CSS.escape(columnId)}"]`
3137
+ );
3138
+ return parseReorderIds(element?.getAttribute("data-reorder-ids"));
3139
+ }
3140
+ function useColumnReorder(options) {
3141
+ const { enabled, columnOrder, onColumnOrderChange } = options;
3142
+ const sessionRef = (0, import_react8.useRef)(null);
3143
+ const columnOrderRef = (0, import_react8.useRef)(columnOrder);
3144
+ const onColumnOrderChangeRef = (0, import_react8.useRef)(onColumnOrderChange);
3145
+ const [draggingColumnId, setDraggingColumnId] = (0, import_react8.useState)(null);
3146
+ const [dropTarget, setDropTarget] = (0, import_react8.useState)(
3147
+ null
3148
+ );
3149
+ const dropTargetRef = (0, import_react8.useRef)(dropTarget);
3150
+ const previousUserSelectRef = (0, import_react8.useRef)(null);
3151
+ columnOrderRef.current = columnOrder;
3152
+ onColumnOrderChangeRef.current = onColumnOrderChange;
3153
+ dropTargetRef.current = dropTarget;
3154
+ const resetDrag = (0, import_react8.useCallback)(() => {
3155
+ sessionRef.current = null;
3156
+ setDraggingColumnId(null);
3157
+ setDropTarget(null);
3158
+ const backup = previousUserSelectRef.current;
3159
+ previousUserSelectRef.current = null;
3160
+ if (backup) {
3161
+ if (backup.value) {
3162
+ document.body.style.setProperty("user-select", backup.value, backup.priority);
3163
+ } else {
3164
+ document.body.style.removeProperty("user-select");
3165
+ }
3166
+ return;
3167
+ }
3168
+ document.body.style.removeProperty("user-select");
3169
+ }, []);
3170
+ (0, import_react8.useEffect)(() => {
3171
+ if (!enabled) resetDrag();
3172
+ }, [enabled, resetDrag]);
3173
+ (0, import_react8.useEffect)(() => {
3174
+ return () => {
3175
+ resetDrag();
3176
+ };
3177
+ }, [resetDrag]);
3178
+ const onHeaderPointerDown = (0, import_react8.useCallback)(
3179
+ (event, meta) => {
3180
+ if (!enabled || !meta.canDrag) return;
3181
+ if (event.button !== 0) return;
3182
+ if (event.pointerType === "mouse" && event.ctrlKey) return;
3183
+ const target = event.target;
3184
+ if (target instanceof Element && target.closest("[data-table-disable-cell-selection]")) {
3185
+ return;
3186
+ }
3187
+ const table = event.currentTarget.closest("table");
3188
+ if (!(table instanceof HTMLTableElement)) return;
3189
+ sessionRef.current = {
3190
+ pointerId: event.pointerId,
3191
+ startX: event.clientX,
3192
+ startY: event.clientY,
3193
+ columnId: meta.columnId,
3194
+ fromIds: meta.leafIds,
3195
+ table,
3196
+ active: false
3197
+ };
3198
+ },
3199
+ [enabled]
3200
+ );
3201
+ (0, import_react8.useEffect)(() => {
3202
+ if (!enabled) return;
3203
+ const onPointerMove = (event) => {
3204
+ const session = sessionRef.current;
3205
+ if (!session || event.pointerId !== session.pointerId) return;
3206
+ const deltaX = event.clientX - session.startX;
3207
+ const deltaY = event.clientY - session.startY;
3208
+ const distance = Math.hypot(deltaX, deltaY);
3209
+ if (!session.active) {
3210
+ if (distance < DATA_TABLE_COLUMN_REORDER_THRESHOLD) return;
3211
+ session.active = true;
3212
+ if (!previousUserSelectRef.current) {
3213
+ previousUserSelectRef.current = {
3214
+ value: document.body.style.getPropertyValue("user-select"),
3215
+ priority: document.body.style.getPropertyPriority("user-select")
3216
+ };
3217
+ }
3218
+ document.body.style.setProperty("user-select", "none");
3219
+ setDraggingColumnId(session.columnId);
3220
+ }
3221
+ event.preventDefault();
3222
+ const nextTarget = hitTestReorderHeader(
3223
+ session.table,
3224
+ event.clientX,
3225
+ event.clientY
3226
+ );
3227
+ if (!nextTarget || !nextTarget.columnId) {
3228
+ setDropTarget(null);
3229
+ return;
3230
+ }
3231
+ const targetIds = readTargetIds(session.table, nextTarget.columnId);
3232
+ const fromSet = new Set(session.fromIds);
3233
+ if (targetIds.some((id) => fromSet.has(id))) {
3234
+ setDropTarget(null);
3235
+ return;
3236
+ }
3237
+ setDropTarget((previous) => {
3238
+ if (previous?.columnId === nextTarget.columnId && previous.edge === nextTarget.edge) {
3239
+ return previous;
3240
+ }
3241
+ return nextTarget;
3242
+ });
3243
+ };
3244
+ const onPointerUp = (event) => {
3245
+ const session = sessionRef.current;
3246
+ if (!session || event.pointerId !== session.pointerId) {
3247
+ return;
3248
+ }
3249
+ if (session.active) {
3250
+ event.preventDefault();
3251
+ const target = dropTargetRef.current;
3252
+ if (target) {
3253
+ const targetIds = readTargetIds(session.table, target.columnId);
3254
+ const next = moveColumnIds(
3255
+ columnOrderRef.current,
3256
+ session.fromIds,
3257
+ targetIds,
3258
+ target.edge
3259
+ );
3260
+ onColumnOrderChangeRef.current(next);
3261
+ }
3262
+ const suppressClick = (clickEvent) => {
3263
+ clickEvent.preventDefault();
3264
+ clickEvent.stopPropagation();
3265
+ document.removeEventListener("click", suppressClick, true);
3266
+ };
3267
+ document.addEventListener("click", suppressClick, true);
3268
+ window.setTimeout(() => {
3269
+ document.removeEventListener("click", suppressClick, true);
3270
+ }, 0);
3271
+ }
3272
+ resetDrag();
3273
+ };
3274
+ const onPointerCancel = (event) => {
3275
+ const session = sessionRef.current;
3276
+ if (!session || event.pointerId !== session.pointerId) {
3277
+ return;
3278
+ }
3279
+ if (session.active) {
3280
+ event.preventDefault();
3281
+ }
3282
+ resetDrag();
3283
+ };
3284
+ document.addEventListener("pointermove", onPointerMove);
3285
+ document.addEventListener("pointerup", onPointerUp);
3286
+ document.addEventListener("pointercancel", onPointerCancel);
3287
+ return () => {
3288
+ document.removeEventListener("pointermove", onPointerMove);
3289
+ document.removeEventListener("pointerup", onPointerUp);
3290
+ document.removeEventListener("pointercancel", onPointerCancel);
3291
+ };
3292
+ }, [enabled, resetDrag]);
3293
+ return {
3294
+ isReordering: draggingColumnId != null,
3295
+ draggingColumnId,
3296
+ dropTarget,
3297
+ onHeaderPointerDown
3298
+ };
3299
+ }
3300
+
2935
3301
  // src/components/ui/table/components/DataTable/DataTable.tsx
2936
3302
  var import_react_table3 = require("@tanstack/react-table");
2937
- var import_react9 = require("react");
3303
+ var import_react10 = require("react");
2938
3304
 
2939
3305
  // src/components/ui/table/components/DataTable/DataTableRow.tsx
2940
3306
  var import_react_table2 = require("@tanstack/react-table");
2941
- var import_react8 = require("react");
3307
+ var import_react9 = require("react");
2942
3308
 
2943
3309
  // src/components/ui/table/components/icons.tsx
2944
3310
  var import_jsx_runtime3 = require("react/jsx-runtime");
@@ -3236,9 +3602,9 @@ function DataTableRow({
3236
3602
  const expandKey = toggleField && rowData[toggleField] !== null && rowData[toggleField] !== void 0 ? String(rowData[toggleField]) : null;
3237
3603
  const isExpanded = expandKey !== null && Boolean(expandedRows?.has(expandKey));
3238
3604
  const rowLevel = typeof rowData.level === "number" ? rowData.level : 0;
3239
- const editInputRef = (0, import_react8.useRef)(null);
3605
+ const editInputRef = (0, import_react9.useRef)(null);
3240
3606
  const isRowEditing = editingCell?.rowIndex === rowIndex;
3241
- (0, import_react8.useEffect)(() => {
3607
+ (0, import_react9.useEffect)(() => {
3242
3608
  if (!isRowEditing) return;
3243
3609
  editInputRef.current?.focus();
3244
3610
  editInputRef.current?.select();
@@ -3836,6 +4202,7 @@ function DataTable({
3836
4202
  selectionLabel,
3837
4203
  enableCellSelection,
3838
4204
  enableColumnResize,
4205
+ enableColumnReorder,
3839
4206
  enableColumnFreeze,
3840
4207
  enableInlineSearch,
3841
4208
  shouldVirtualize,
@@ -3848,6 +4215,7 @@ function DataTable({
3848
4215
  rowContextValue,
3849
4216
  handleToggleSelect,
3850
4217
  clearHover,
4218
+ setColumnOrder,
3851
4219
  inlineSearch
3852
4220
  } = useGlideTable(glideOptions);
3853
4221
  const ToolbarSlot = slots?.Toolbar ?? DataTableToolbar;
@@ -3857,7 +4225,13 @@ function DataTable({
3857
4225
  const EmptySlot = slots?.Empty ?? DefaultEmpty;
3858
4226
  const freezeOffsets = rowContextValue.columnFreeze.offsets;
3859
4227
  const headerGroups = getMergedHeaderGroups(table.getHeaderGroups());
3860
- const contextValue = (0, import_react9.useMemo)(
4228
+ const leafColumnIds = table.getVisibleLeafColumns().map((column) => column.id);
4229
+ const { isReordering, draggingColumnId, dropTarget, onHeaderPointerDown } = useColumnReorder({
4230
+ enabled: enableColumnReorder,
4231
+ columnOrder: leafColumnIds,
4232
+ onColumnOrderChange: setColumnOrder
4233
+ });
4234
+ const contextValue = (0, import_react10.useMemo)(
3861
4235
  () => ({ ...rowContextValue, classNames }),
3862
4236
  [rowContextValue, classNames]
3863
4237
  );
@@ -3879,6 +4253,8 @@ function DataTable({
3879
4253
  "DataTableJSX",
3880
4254
  !enableCellSelection && "DataTableJSX--no-cell-selection",
3881
4255
  enableColumnResize && "DataTableJSX--column-resize",
4256
+ enableColumnReorder && "DataTableJSX--column-reorder",
4257
+ isReordering && "DataTableJSX--column-reordering",
3882
4258
  enableColumnFreeze && "DataTableJSX--column-freeze",
3883
4259
  enableInlineSearch && "DataTableJSX--inline-search",
3884
4260
  classNames?.root,
@@ -3947,20 +4323,43 @@ function DataTable({
3947
4323
  ...sizeStyle,
3948
4324
  ...freezeStyle
3949
4325
  };
4326
+ const isPlaceholder = header.isPlaceholder;
4327
+ const leafColumns = header.column.getLeafColumns();
4328
+ const leafIds = leafColumns.map((leafColumn) => leafColumn.id);
4329
+ const isLeafHeader = !isPlaceholder && header.subHeaders.length === 0;
4330
+ const canDrag = enableColumnReorder && !isPlaceholder && leafIds.length > 0 && leafColumns.every(
4331
+ (leafColumn) => isColumnReorderable(leafColumn.columnDef.meta)
4332
+ );
4333
+ const isDragging = draggingColumnId === header.column.id;
4334
+ const dropEdge = !isPlaceholder && dropTarget?.columnId === header.column.id ? dropTarget.edge : void 0;
3950
4335
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
3951
4336
  "th",
3952
4337
  {
3953
4338
  colSpan: header.colSpan,
3954
4339
  rowSpan: header.mergedRowSpan,
4340
+ "data-column-id": enableColumnReorder && !isPlaceholder ? header.column.id : void 0,
4341
+ "data-reorder-ids": enableColumnReorder && !isPlaceholder ? serializeReorderIds(leafIds) : void 0,
4342
+ "data-reorder-leaf": enableColumnReorder && isLeafHeader ? "" : void 0,
4343
+ "data-reorderable": canDrag ? "" : void 0,
4344
+ "data-reordering": isDragging ? "" : void 0,
4345
+ "data-drop-edge": dropEdge,
3955
4346
  "data-resizing": header.column.getIsResizing() ? "" : void 0,
3956
4347
  "data-frozen": freezeOffset?.side,
3957
4348
  "data-freeze-edge": getColumnFreezeEdgeAttr(freezeOffset),
4349
+ "aria-grabbed": isDragging ? true : void 0,
4350
+ title: canDrag ? labels.reorderColumn : void 0,
4351
+ onPointerDown: enableColumnReorder ? (event) => onHeaderPointerDown(event, {
4352
+ columnId: header.column.id,
4353
+ leafIds,
4354
+ canDrag
4355
+ }) : void 0,
3958
4356
  style: Object.keys(headerStyle).length > 0 ? headerStyle : void 0,
3959
4357
  className: cn(
3960
4358
  "data-table-head-cell",
3961
4359
  freezeOffset && `data-table-head-cell--frozen-${freezeOffset.side}`,
3962
4360
  CELL_ALIGN_CLASS[align],
3963
4361
  classNames?.headCell,
4362
+ dropEdge && classNames?.dropEdge,
3964
4363
  headerClassName
3965
4364
  ),
3966
4365
  children: [
@@ -4082,7 +4481,7 @@ function DataTable({
4082
4481
  }
4083
4482
 
4084
4483
  // src/components/ui/table/components/Table/Table.tsx
4085
- var import_react12 = require("react");
4484
+ var import_react13 = require("react");
4086
4485
 
4087
4486
  // src/components/ui/table/components/Table/buildColumnDef.tsx
4088
4487
  var import_jsx_runtime8 = require("react/jsx-runtime");
@@ -4120,6 +4519,7 @@ function buildColumnDef(props, sort, onSort) {
4120
4519
  minWidth,
4121
4520
  maxWidth,
4122
4521
  resizable,
4522
+ reorderable,
4123
4523
  frozen,
4124
4524
  align,
4125
4525
  rowSpan,
@@ -4165,6 +4565,7 @@ function buildColumnDef(props, sort, onSort) {
4165
4565
  cellProps,
4166
4566
  cellRender: render,
4167
4567
  frozen,
4568
+ reorderable,
4168
4569
  className,
4169
4570
  headerClassName
4170
4571
  }
@@ -4210,10 +4611,10 @@ function countLeafColumns(nodes) {
4210
4611
  }
4211
4612
 
4212
4613
  // src/components/ui/table/components/Table/parseTableChildren.ts
4213
- var import_react11 = require("react");
4614
+ var import_react12 = require("react");
4214
4615
 
4215
4616
  // src/components/ui/table/components/Table/tableChildTypes.ts
4216
- var import_react10 = require("react");
4617
+ var import_react11 = require("react");
4217
4618
  var TABLE_HEADER_DISPLAY_NAME = "Table.Header";
4218
4619
  var TABLE_BODY_DISPLAY_NAME = "Table.Body";
4219
4620
  var TABLE_COLUMN_DISPLAY_NAME = "Table.Column";
@@ -4226,19 +4627,19 @@ function getComponentDisplayName(type) {
4226
4627
  return void 0;
4227
4628
  }
4228
4629
  function isTableHeaderElement(child) {
4229
- return (0, import_react10.isValidElement)(child) && getComponentDisplayName(child.type) === TABLE_HEADER_DISPLAY_NAME;
4630
+ return (0, import_react11.isValidElement)(child) && getComponentDisplayName(child.type) === TABLE_HEADER_DISPLAY_NAME;
4230
4631
  }
4231
4632
  function isTableBodyElement(child) {
4232
- return (0, import_react10.isValidElement)(child) && getComponentDisplayName(child.type) === TABLE_BODY_DISPLAY_NAME;
4633
+ return (0, import_react11.isValidElement)(child) && getComponentDisplayName(child.type) === TABLE_BODY_DISPLAY_NAME;
4233
4634
  }
4234
4635
  function isTableColumnElement(child) {
4235
- return (0, import_react10.isValidElement)(child) && getComponentDisplayName(child.type) === TABLE_COLUMN_DISPLAY_NAME;
4636
+ return (0, import_react11.isValidElement)(child) && getComponentDisplayName(child.type) === TABLE_COLUMN_DISPLAY_NAME;
4236
4637
  }
4237
4638
  function isTableColumnGroupElement(child) {
4238
- return (0, import_react10.isValidElement)(child) && getComponentDisplayName(child.type) === TABLE_COLUMN_GROUP_DISPLAY_NAME;
4639
+ return (0, import_react11.isValidElement)(child) && getComponentDisplayName(child.type) === TABLE_COLUMN_GROUP_DISPLAY_NAME;
4239
4640
  }
4240
4641
  function isTablePaginationElement(child) {
4241
- return (0, import_react10.isValidElement)(child) && getComponentDisplayName(child.type) === TABLE_PAGINATION_DISPLAY_NAME;
4642
+ return (0, import_react11.isValidElement)(child) && getComponentDisplayName(child.type) === TABLE_PAGINATION_DISPLAY_NAME;
4242
4643
  }
4243
4644
 
4244
4645
  // src/components/ui/table/components/Table/parseTableChildren.ts
@@ -4248,7 +4649,7 @@ function parseTableChildren(children) {
4248
4649
  body: null,
4249
4650
  pagination: null
4250
4651
  };
4251
- for (const child of import_react11.Children.toArray(children)) {
4652
+ for (const child of import_react12.Children.toArray(children)) {
4252
4653
  if (isTableHeaderElement(child)) {
4253
4654
  slots.header = child;
4254
4655
  continue;
@@ -4265,7 +4666,7 @@ function parseTableChildren(children) {
4265
4666
  }
4266
4667
  function walkColumnTreeNodes(children) {
4267
4668
  const result = [];
4268
- for (const child of import_react11.Children.toArray(children)) {
4669
+ for (const child of import_react12.Children.toArray(children)) {
4269
4670
  if (isTableColumnElement(child)) {
4270
4671
  result.push({
4271
4672
  type: "leaf",
@@ -4282,7 +4683,7 @@ function walkColumnTreeNodes(children) {
4282
4683
  });
4283
4684
  continue;
4284
4685
  }
4285
- if ((0, import_react11.isValidElement)(child)) {
4686
+ if ((0, import_react12.isValidElement)(child)) {
4286
4687
  const nested = child.props.children;
4287
4688
  if (nested != null) {
4288
4689
  result.push(...walkColumnTreeNodes(nested));
@@ -4408,12 +4809,12 @@ function TableRoot({
4408
4809
  filteredCount,
4409
4810
  ...dataTableProps
4410
4811
  }) {
4411
- const { header, pagination: paginationElement } = (0, import_react12.useMemo)(
4812
+ const { header, pagination: paginationElement } = (0, import_react13.useMemo)(
4412
4813
  () => parseTableChildren(children),
4413
4814
  [children]
4414
4815
  );
4415
- const [sort, setSort] = (0, import_react12.useState)(null);
4416
- const handleSort = (0, import_react12.useCallback)((field) => {
4816
+ const [sort, setSort] = (0, import_react13.useState)(null);
4817
+ const handleSort = (0, import_react13.useCallback)((field) => {
4417
4818
  setSort((previous) => {
4418
4819
  if (previous?.field !== field) {
4419
4820
  return { field, direction: "asc" };
@@ -4424,8 +4825,8 @@ function TableRoot({
4424
4825
  return null;
4425
4826
  });
4426
4827
  }, []);
4427
- const columnTree = (0, import_react12.useMemo)(() => extractColumnTree(header), [header]);
4428
- const columns = (0, import_react12.useMemo)(
4828
+ const columnTree = (0, import_react13.useMemo)(() => extractColumnTree(header), [header]);
4829
+ const columns = (0, import_react13.useMemo)(
4429
4830
  () => buildColumnDefsFromTree(columnTree, sort, handleSort),
4430
4831
  [columnTree, sort, handleSort]
4431
4832
  );
@@ -4433,7 +4834,7 @@ function TableRoot({
4433
4834
  const pageSize = paginationProps?.pageSize ?? 10;
4434
4835
  const page = paginationProps?.page ?? 1;
4435
4836
  const resolvedTotalCount = paginationProps?.totalCount ?? totalCount ?? data.length;
4436
- const tableData = (0, import_react12.useMemo)(() => {
4837
+ const tableData = (0, import_react13.useMemo)(() => {
4437
4838
  const sortedData = sortTableData(data, sort);
4438
4839
  if (!paginationProps) return sortedData;
4439
4840
  return paginateTableData(sortedData, page, pageSize);
@@ -4511,6 +4912,7 @@ var Table = Object.assign(TableRoot, {
4511
4912
  Table,
4512
4913
  applyCellEdit,
4513
4914
  applyFillData,
4915
+ applyLeafColumnOrder,
4514
4916
  applySelectionUpdater,
4515
4917
  buildColumnFreezeOffsets,
4516
4918
  buildColumnRowSpanMap,
@@ -4525,6 +4927,7 @@ var Table = Object.assign(TableRoot, {
4525
4927
  collectCopyRowEntries,
4526
4928
  collectCopyRows,
4527
4929
  collectFillChanges,
4930
+ collectLeafColumnIds,
4528
4931
  collectRowSpanColumns,
4529
4932
  collectSearchMatchesInRange,
4530
4933
  commitCellValue,
@@ -4550,6 +4953,7 @@ var Table = Object.assign(TableRoot, {
4550
4953
  mapSearchResultToVisibleItem,
4551
4954
  mapSearchResultsToVisibleKeys,
4552
4955
  measureMergedSpanRowHeights,
4956
+ moveColumnIds,
4553
4957
  nextSearchIndex,
4554
4958
  nextSearchStride,
4555
4959
  parseCellEditValue,
@@ -4559,7 +4963,9 @@ var Table = Object.assign(TableRoot, {
4559
4963
  resolveCellRenderer,
4560
4964
  resolveColumnFreezeSide,
4561
4965
  resolveDataTableLabels,
4966
+ resolveDropEdge,
4562
4967
  resolveHeaderFreezeOffset,
4968
+ resolveLeafColumnOrder,
4563
4969
  resolvePasteColumnIds,
4564
4970
  resolveRowSelection,
4565
4971
  resolveRowSpanAt,
@@ -4569,6 +4975,7 @@ var Table = Object.assign(TableRoot, {
4569
4975
  toggleExpandedRowId,
4570
4976
  useCellEdit,
4571
4977
  useCellSelection,
4978
+ useColumnReorder,
4572
4979
  useConvertTreeData,
4573
4980
  useGlideTable,
4574
4981
  useInlineSearch,