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.d.cts CHANGED
@@ -1,6 +1,6 @@
1
- export { B as BuiltinCellKind, C as CellKind, a as CellRenderContext, b as CellRenderFn, c as CellRenderer, d as ColumnFreezeColumnInput, e as ColumnFreezeEdgeSide, f as ColumnFreezeMeta, g as ColumnFreezeOffset, h as ColumnFreezeSide, D as DEFAULT_DATA_TABLE_LABELS, i as DataTableClassNames, j as DataTableCopyActions, k as DataTableLabels, l as DataTableProps, m as DataTableScrollSlotProps, n as DataTableSlots, I as INLINE_SEARCH_MAX_RESULTS, P as PasteMode, R as RowSelectionMode, o as RowsPastePayload, S as SearchCorpusRow, p as SearchResultItem, q as SearchStatus, T as TableColumnGroupProps, r as TableColumnProps, s as TableProps, t as buildColumnFreezeOffsets, u as buildFlatSearchCorpus, v as buildSearchMatchKey, w as buildSearchMatchKeys, x as buildTreeSearchCorpus, y as cellValueToSearchText, z as collectAncestorKeysToExpand, A as collectSearchMatchesInRange, E as createSearchRegex, F as escapeSearchRegex, G as formatSearchResultLabel, H as getColumnFreezeEdgeAttr, J as getColumnFreezeStyle, K as mapSearchResultToVisibleItem, L as mapSearchResultsToVisibleKeys, M as nextSearchIndex, N as nextSearchStride, O as previousSearchIndex, Q as resolveColumnFreezeSide, U as resolveDataTableLabels, V as resolveHeaderFreezeOffset } from './types-bgEceyRV.cjs';
2
- export { BUILTIN_CELL_RENDERERS, CELL_SELECTION_EDGES_CLASS, CellContextWithUpdate, CellRendererRegistry, CellSelectionBounds, ColumnRowSpanMap, CopyRowEntry, CopySelectionMode, DEFAULT_TREE_CHILDREN_FIELD, DEFAULT_TREE_ID_FIELD, DEFAULT_TREE_PARENT_ID_FIELD, DEFAULT_TREE_QTY_FIELD, DragState, EditingCell, ResolvedTableCell, RowSpanInfo, TreeRow, UseConvertTreeDataParams, UseGlideTableOptions, UseGlideTableResult, UseInlineSearchOptions, UseInlineSearchResult, applyCellEdit, applyFillData, applySelectionUpdater, buildColumnRowSpanMap, buildRowsPastePayload, canExpandRow, collectCopyRowEntries, collectCopyRows, collectFillChanges, collectRowSpanColumns, commitCellValue, createCellRendererRegistry, flattenSubtreeRows, formatCellValue, formatDefaultCellValue, getCellEditDraftValue, getCellSelectionEdgeStyle, getColumnEditType, getColumnSizeStyle, getRowIndexInMergedCell, hasCellSelectionEdges, isCellInSelection, isColumnEditable, isEditablePasteTarget, measureMergedSpanRowHeights, parseCellEditValue, parseClipboardTSV, parseClipboardTSVWithDepths, resolveCellRenderer, resolvePasteColumnIds, resolveRowSelection, resolveRowSpanAt, rowRangeToHeightRatios, serializeCopyRowsToTSV, serializeSelectionToTSV, toggleExpandedRowId, useCellEdit, useCellSelection, useConvertTreeData, useGlideTable, useInlineSearch, withCellUpdate, writeSelectionToClipboard } from './core.cjs';
1
+ export { B as BuiltinCellKind, C as CellKind, a as CellRenderContext, b as CellRenderFn, c as CellRenderer, d as ColumnFreezeColumnInput, e as ColumnFreezeEdgeSide, f as ColumnFreezeMeta, g as ColumnFreezeOffset, h as ColumnFreezeSide, D as DEFAULT_DATA_TABLE_LABELS, i as DataTableClassNames, j as DataTableCopyActions, k as DataTableLabels, l as DataTableProps, m as DataTableScrollSlotProps, n as DataTableSlots, I as INLINE_SEARCH_MAX_RESULTS, P as PasteMode, R as RowSelectionMode, o as RowsPastePayload, S as SearchCorpusRow, p as SearchResultItem, q as SearchStatus, T as TableColumnGroupProps, r as TableColumnProps, s as TableProps, t as buildColumnFreezeOffsets, u as buildFlatSearchCorpus, v as buildSearchMatchKey, w as buildSearchMatchKeys, x as buildTreeSearchCorpus, y as cellValueToSearchText, z as collectAncestorKeysToExpand, A as collectSearchMatchesInRange, E as createSearchRegex, F as escapeSearchRegex, G as formatSearchResultLabel, H as getColumnFreezeEdgeAttr, J as getColumnFreezeStyle, K as mapSearchResultToVisibleItem, L as mapSearchResultsToVisibleKeys, M as nextSearchIndex, N as nextSearchStride, O as previousSearchIndex, Q as resolveColumnFreezeSide, U as resolveDataTableLabels, V as resolveHeaderFreezeOffset } from './types-CMUGtH-c.cjs';
2
+ export { BUILTIN_CELL_RENDERERS, CELL_SELECTION_EDGES_CLASS, CellContextWithUpdate, CellRendererRegistry, CellSelectionBounds, ColumnDropEdge, ColumnRowSpanMap, CopyRowEntry, CopySelectionMode, DEFAULT_TREE_CHILDREN_FIELD, DEFAULT_TREE_ID_FIELD, DEFAULT_TREE_PARENT_ID_FIELD, DEFAULT_TREE_QTY_FIELD, DragState, EditingCell, ResolvedTableCell, RowSpanInfo, TreeRow, UseConvertTreeDataParams, UseGlideTableOptions, UseGlideTableResult, UseInlineSearchOptions, UseInlineSearchResult, applyCellEdit, applyFillData, applyLeafColumnOrder, applySelectionUpdater, buildColumnRowSpanMap, buildRowsPastePayload, canExpandRow, collectCopyRowEntries, collectCopyRows, collectFillChanges, collectLeafColumnIds, collectRowSpanColumns, commitCellValue, createCellRendererRegistry, flattenSubtreeRows, formatCellValue, formatDefaultCellValue, getCellEditDraftValue, getCellSelectionEdgeStyle, getColumnEditType, getColumnSizeStyle, getRowIndexInMergedCell, hasCellSelectionEdges, isCellInSelection, isColumnEditable, isEditablePasteTarget, measureMergedSpanRowHeights, moveColumnIds, parseCellEditValue, parseClipboardTSV, parseClipboardTSVWithDepths, resolveCellRenderer, resolveDropEdge, resolveLeafColumnOrder, resolvePasteColumnIds, resolveRowSelection, resolveRowSpanAt, rowRangeToHeightRatios, serializeCopyRowsToTSV, serializeSelectionToTSV, toggleExpandedRowId, useCellEdit, useCellSelection, useColumnReorder, useConvertTreeData, useGlideTable, useInlineSearch, withCellUpdate, writeSelectionToClipboard } from './core.cjs';
3
3
  export { DataTable, Table, TableCompoundComponent, createTable } from './compound.cjs';
4
- export { ColumnDef, ColumnResizeMode, ColumnSizingState, RowSelectionState } from '@tanstack/react-table';
4
+ export { ColumnDef, ColumnOrderState, ColumnResizeMode, ColumnSizingState, RowSelectionState } from '@tanstack/react-table';
5
5
  import 'react';
6
6
  import '@tanstack/react-virtual';
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- export { B as BuiltinCellKind, C as CellKind, a as CellRenderContext, b as CellRenderFn, c as CellRenderer, d as ColumnFreezeColumnInput, e as ColumnFreezeEdgeSide, f as ColumnFreezeMeta, g as ColumnFreezeOffset, h as ColumnFreezeSide, D as DEFAULT_DATA_TABLE_LABELS, i as DataTableClassNames, j as DataTableCopyActions, k as DataTableLabels, l as DataTableProps, m as DataTableScrollSlotProps, n as DataTableSlots, I as INLINE_SEARCH_MAX_RESULTS, P as PasteMode, R as RowSelectionMode, o as RowsPastePayload, S as SearchCorpusRow, p as SearchResultItem, q as SearchStatus, T as TableColumnGroupProps, r as TableColumnProps, s as TableProps, t as buildColumnFreezeOffsets, u as buildFlatSearchCorpus, v as buildSearchMatchKey, w as buildSearchMatchKeys, x as buildTreeSearchCorpus, y as cellValueToSearchText, z as collectAncestorKeysToExpand, A as collectSearchMatchesInRange, E as createSearchRegex, F as escapeSearchRegex, G as formatSearchResultLabel, H as getColumnFreezeEdgeAttr, J as getColumnFreezeStyle, K as mapSearchResultToVisibleItem, L as mapSearchResultsToVisibleKeys, M as nextSearchIndex, N as nextSearchStride, O as previousSearchIndex, Q as resolveColumnFreezeSide, U as resolveDataTableLabels, V as resolveHeaderFreezeOffset } from './types-bgEceyRV.js';
2
- export { BUILTIN_CELL_RENDERERS, CELL_SELECTION_EDGES_CLASS, CellContextWithUpdate, CellRendererRegistry, CellSelectionBounds, ColumnRowSpanMap, CopyRowEntry, CopySelectionMode, DEFAULT_TREE_CHILDREN_FIELD, DEFAULT_TREE_ID_FIELD, DEFAULT_TREE_PARENT_ID_FIELD, DEFAULT_TREE_QTY_FIELD, DragState, EditingCell, ResolvedTableCell, RowSpanInfo, TreeRow, UseConvertTreeDataParams, UseGlideTableOptions, UseGlideTableResult, UseInlineSearchOptions, UseInlineSearchResult, applyCellEdit, applyFillData, applySelectionUpdater, buildColumnRowSpanMap, buildRowsPastePayload, canExpandRow, collectCopyRowEntries, collectCopyRows, collectFillChanges, collectRowSpanColumns, commitCellValue, createCellRendererRegistry, flattenSubtreeRows, formatCellValue, formatDefaultCellValue, getCellEditDraftValue, getCellSelectionEdgeStyle, getColumnEditType, getColumnSizeStyle, getRowIndexInMergedCell, hasCellSelectionEdges, isCellInSelection, isColumnEditable, isEditablePasteTarget, measureMergedSpanRowHeights, parseCellEditValue, parseClipboardTSV, parseClipboardTSVWithDepths, resolveCellRenderer, resolvePasteColumnIds, resolveRowSelection, resolveRowSpanAt, rowRangeToHeightRatios, serializeCopyRowsToTSV, serializeSelectionToTSV, toggleExpandedRowId, useCellEdit, useCellSelection, useConvertTreeData, useGlideTable, useInlineSearch, withCellUpdate, writeSelectionToClipboard } from './core.js';
1
+ export { B as BuiltinCellKind, C as CellKind, a as CellRenderContext, b as CellRenderFn, c as CellRenderer, d as ColumnFreezeColumnInput, e as ColumnFreezeEdgeSide, f as ColumnFreezeMeta, g as ColumnFreezeOffset, h as ColumnFreezeSide, D as DEFAULT_DATA_TABLE_LABELS, i as DataTableClassNames, j as DataTableCopyActions, k as DataTableLabels, l as DataTableProps, m as DataTableScrollSlotProps, n as DataTableSlots, I as INLINE_SEARCH_MAX_RESULTS, P as PasteMode, R as RowSelectionMode, o as RowsPastePayload, S as SearchCorpusRow, p as SearchResultItem, q as SearchStatus, T as TableColumnGroupProps, r as TableColumnProps, s as TableProps, t as buildColumnFreezeOffsets, u as buildFlatSearchCorpus, v as buildSearchMatchKey, w as buildSearchMatchKeys, x as buildTreeSearchCorpus, y as cellValueToSearchText, z as collectAncestorKeysToExpand, A as collectSearchMatchesInRange, E as createSearchRegex, F as escapeSearchRegex, G as formatSearchResultLabel, H as getColumnFreezeEdgeAttr, J as getColumnFreezeStyle, K as mapSearchResultToVisibleItem, L as mapSearchResultsToVisibleKeys, M as nextSearchIndex, N as nextSearchStride, O as previousSearchIndex, Q as resolveColumnFreezeSide, U as resolveDataTableLabels, V as resolveHeaderFreezeOffset } from './types-CMUGtH-c.js';
2
+ export { BUILTIN_CELL_RENDERERS, CELL_SELECTION_EDGES_CLASS, CellContextWithUpdate, CellRendererRegistry, CellSelectionBounds, ColumnDropEdge, ColumnRowSpanMap, CopyRowEntry, CopySelectionMode, DEFAULT_TREE_CHILDREN_FIELD, DEFAULT_TREE_ID_FIELD, DEFAULT_TREE_PARENT_ID_FIELD, DEFAULT_TREE_QTY_FIELD, DragState, EditingCell, ResolvedTableCell, RowSpanInfo, TreeRow, UseConvertTreeDataParams, UseGlideTableOptions, UseGlideTableResult, UseInlineSearchOptions, UseInlineSearchResult, applyCellEdit, applyFillData, applyLeafColumnOrder, applySelectionUpdater, buildColumnRowSpanMap, buildRowsPastePayload, canExpandRow, collectCopyRowEntries, collectCopyRows, collectFillChanges, collectLeafColumnIds, collectRowSpanColumns, commitCellValue, createCellRendererRegistry, flattenSubtreeRows, formatCellValue, formatDefaultCellValue, getCellEditDraftValue, getCellSelectionEdgeStyle, getColumnEditType, getColumnSizeStyle, getRowIndexInMergedCell, hasCellSelectionEdges, isCellInSelection, isColumnEditable, isEditablePasteTarget, measureMergedSpanRowHeights, moveColumnIds, parseCellEditValue, parseClipboardTSV, parseClipboardTSVWithDepths, resolveCellRenderer, resolveDropEdge, resolveLeafColumnOrder, resolvePasteColumnIds, resolveRowSelection, resolveRowSpanAt, rowRangeToHeightRatios, serializeCopyRowsToTSV, serializeSelectionToTSV, toggleExpandedRowId, useCellEdit, useCellSelection, useColumnReorder, useConvertTreeData, useGlideTable, useInlineSearch, withCellUpdate, writeSelectionToClipboard } from './core.js';
3
3
  export { DataTable, Table, TableCompoundComponent, createTable } from './compound.js';
4
- export { ColumnDef, ColumnResizeMode, ColumnSizingState, RowSelectionState } from '@tanstack/react-table';
4
+ export { ColumnDef, ColumnOrderState, ColumnResizeMode, ColumnSizingState, RowSelectionState } from '@tanstack/react-table';
5
5
  import 'react';
6
6
  import '@tanstack/react-virtual';
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;
@@ -2203,6 +2334,9 @@ function useGlideTable(options) {
2203
2334
  columnSizing: controlledColumnSizing,
2204
2335
  onColumnSizingChange,
2205
2336
  columnResizeMode = "onChange",
2337
+ enableColumnReorder = false,
2338
+ columnOrder: controlledColumnOrder,
2339
+ onColumnOrderChange,
2206
2340
  enableColumnFreeze = false,
2207
2341
  enableInlineSearch = false,
2208
2342
  showSearch,
@@ -2225,6 +2359,7 @@ function useGlideTable(options) {
2225
2359
  const resolvedEnableSubtreeCopy = enableSubtreeCopy ?? enableExpand;
2226
2360
  const [internalRowSelection, setInternalRowSelection] = useState4({});
2227
2361
  const [internalColumnSizing, setInternalColumnSizing] = useState4({});
2362
+ const [internalColumnOrder, setInternalColumnOrder] = useState4([]);
2228
2363
  const [internalExpandedRows, setInternalExpandedRows] = useState4(
2229
2364
  () => /* @__PURE__ */ new Set()
2230
2365
  );
@@ -2245,6 +2380,21 @@ function useGlideTable(options) {
2245
2380
  internalRowSelection
2246
2381
  );
2247
2382
  const columnSizing = controlledColumnSizing ?? internalColumnSizing;
2383
+ const columnOrder = controlledColumnOrder ?? internalColumnOrder;
2384
+ const tableColumns = useMemo3(() => {
2385
+ if (!enableColumnReorder) return columns;
2386
+ return applyLeafColumnOrder(columns, columnOrder);
2387
+ }, [columnOrder, columns, enableColumnReorder]);
2388
+ const setColumnOrder = useCallback4(
2389
+ (next) => {
2390
+ if (onColumnOrderChange) {
2391
+ onColumnOrderChange(next);
2392
+ return;
2393
+ }
2394
+ setInternalColumnOrder(next);
2395
+ },
2396
+ [onColumnOrderChange]
2397
+ );
2248
2398
  const expandedRows = controlledExpandedRows ?? internalExpandedRows;
2249
2399
  const handleExpandedRowsChange = useCallback4(
2250
2400
  (next) => {
@@ -2269,7 +2419,7 @@ function useGlideTable(options) {
2269
2419
  });
2270
2420
  const table = useReactTable({
2271
2421
  data: tableData,
2272
- columns,
2422
+ columns: tableColumns,
2273
2423
  ...enableColumnResize ? {
2274
2424
  defaultColumn: {
2275
2425
  minSize: DATA_TABLE_COLUMN_MIN_SIZE,
@@ -2751,6 +2901,7 @@ function useGlideTable(options) {
2751
2901
  selectionLabel: labels.selection,
2752
2902
  enableCellSelection,
2753
2903
  enableColumnResize,
2904
+ enableColumnReorder,
2754
2905
  enableColumnFreeze,
2755
2906
  enableInlineSearch,
2756
2907
  shouldVirtualize,
@@ -2764,6 +2915,7 @@ function useGlideTable(options) {
2764
2915
  getCellContext,
2765
2916
  handleToggleSelect,
2766
2917
  clearHover,
2918
+ setColumnOrder,
2767
2919
  copySelection: stableCopySelection,
2768
2920
  inlineSearch: {
2769
2921
  showSearch: inlineSearch.showSearch,
@@ -2849,13 +3001,226 @@ function getColumnSizeStyle(size, options) {
2849
3001
  };
2850
3002
  }
2851
3003
 
3004
+ // src/components/ui/table/features/column-reorder/useColumnReorder.ts
3005
+ import {
3006
+ useCallback as useCallback6,
3007
+ useEffect as useEffect6,
3008
+ useRef as useRef6,
3009
+ useState as useState5
3010
+ } from "react";
3011
+ function hitTestReorderHeader(table, clientX, clientY) {
3012
+ const headers = Array.from(
3013
+ table.querySelectorAll(
3014
+ "thead th[data-column-id][data-reorder-ids]"
3015
+ )
3016
+ );
3017
+ const containing = headers.find((element) => {
3018
+ const rect = element.getBoundingClientRect();
3019
+ return clientX >= rect.left && clientX <= rect.right && clientY >= rect.top && clientY <= rect.bottom;
3020
+ });
3021
+ if (containing) {
3022
+ return {
3023
+ columnId: containing.dataset.columnId ?? "",
3024
+ edge: resolveDropEdge(clientX, containing.getBoundingClientRect())
3025
+ };
3026
+ }
3027
+ const leaves = headers.filter(
3028
+ (element) => element.hasAttribute("data-reorder-leaf")
3029
+ );
3030
+ let match;
3031
+ for (const element of leaves) {
3032
+ const rect = element.getBoundingClientRect();
3033
+ if (clientX >= rect.left && clientX <= rect.right) {
3034
+ match = element;
3035
+ break;
3036
+ }
3037
+ }
3038
+ if (!match && leaves.length > 0) {
3039
+ const first = leaves[0].getBoundingClientRect();
3040
+ const last = leaves[leaves.length - 1].getBoundingClientRect();
3041
+ if (clientX < first.left) match = leaves[0];
3042
+ else if (clientX > last.right) match = leaves[leaves.length - 1];
3043
+ }
3044
+ if (!match) return null;
3045
+ return {
3046
+ columnId: match.dataset.columnId ?? "",
3047
+ edge: resolveDropEdge(clientX, match.getBoundingClientRect())
3048
+ };
3049
+ }
3050
+ function readTargetIds(table, columnId) {
3051
+ const element = table.querySelector(
3052
+ `thead th[data-column-id="${CSS.escape(columnId)}"]`
3053
+ );
3054
+ return parseReorderIds(element?.getAttribute("data-reorder-ids"));
3055
+ }
3056
+ function useColumnReorder(options) {
3057
+ const { enabled, columnOrder, onColumnOrderChange } = options;
3058
+ const sessionRef = useRef6(null);
3059
+ const columnOrderRef = useRef6(columnOrder);
3060
+ const onColumnOrderChangeRef = useRef6(onColumnOrderChange);
3061
+ const [draggingColumnId, setDraggingColumnId] = useState5(null);
3062
+ const [dropTarget, setDropTarget] = useState5(
3063
+ null
3064
+ );
3065
+ const dropTargetRef = useRef6(dropTarget);
3066
+ const previousUserSelectRef = useRef6(null);
3067
+ columnOrderRef.current = columnOrder;
3068
+ onColumnOrderChangeRef.current = onColumnOrderChange;
3069
+ dropTargetRef.current = dropTarget;
3070
+ const resetDrag = useCallback6(() => {
3071
+ sessionRef.current = null;
3072
+ setDraggingColumnId(null);
3073
+ setDropTarget(null);
3074
+ const backup = previousUserSelectRef.current;
3075
+ previousUserSelectRef.current = null;
3076
+ if (backup) {
3077
+ if (backup.value) {
3078
+ document.body.style.setProperty("user-select", backup.value, backup.priority);
3079
+ } else {
3080
+ document.body.style.removeProperty("user-select");
3081
+ }
3082
+ return;
3083
+ }
3084
+ document.body.style.removeProperty("user-select");
3085
+ }, []);
3086
+ useEffect6(() => {
3087
+ if (!enabled) resetDrag();
3088
+ }, [enabled, resetDrag]);
3089
+ useEffect6(() => {
3090
+ return () => {
3091
+ resetDrag();
3092
+ };
3093
+ }, [resetDrag]);
3094
+ const onHeaderPointerDown = useCallback6(
3095
+ (event, meta) => {
3096
+ if (!enabled || !meta.canDrag) return;
3097
+ if (event.button !== 0) return;
3098
+ if (event.pointerType === "mouse" && event.ctrlKey) return;
3099
+ const target = event.target;
3100
+ if (target instanceof Element && target.closest("[data-table-disable-cell-selection]")) {
3101
+ return;
3102
+ }
3103
+ const table = event.currentTarget.closest("table");
3104
+ if (!(table instanceof HTMLTableElement)) return;
3105
+ sessionRef.current = {
3106
+ pointerId: event.pointerId,
3107
+ startX: event.clientX,
3108
+ startY: event.clientY,
3109
+ columnId: meta.columnId,
3110
+ fromIds: meta.leafIds,
3111
+ table,
3112
+ active: false
3113
+ };
3114
+ },
3115
+ [enabled]
3116
+ );
3117
+ useEffect6(() => {
3118
+ if (!enabled) return;
3119
+ const onPointerMove = (event) => {
3120
+ const session = sessionRef.current;
3121
+ if (!session || event.pointerId !== session.pointerId) return;
3122
+ const deltaX = event.clientX - session.startX;
3123
+ const deltaY = event.clientY - session.startY;
3124
+ const distance = Math.hypot(deltaX, deltaY);
3125
+ if (!session.active) {
3126
+ if (distance < DATA_TABLE_COLUMN_REORDER_THRESHOLD) return;
3127
+ session.active = true;
3128
+ if (!previousUserSelectRef.current) {
3129
+ previousUserSelectRef.current = {
3130
+ value: document.body.style.getPropertyValue("user-select"),
3131
+ priority: document.body.style.getPropertyPriority("user-select")
3132
+ };
3133
+ }
3134
+ document.body.style.setProperty("user-select", "none");
3135
+ setDraggingColumnId(session.columnId);
3136
+ }
3137
+ event.preventDefault();
3138
+ const nextTarget = hitTestReorderHeader(
3139
+ session.table,
3140
+ event.clientX,
3141
+ event.clientY
3142
+ );
3143
+ if (!nextTarget || !nextTarget.columnId) {
3144
+ setDropTarget(null);
3145
+ return;
3146
+ }
3147
+ const targetIds = readTargetIds(session.table, nextTarget.columnId);
3148
+ const fromSet = new Set(session.fromIds);
3149
+ if (targetIds.some((id) => fromSet.has(id))) {
3150
+ setDropTarget(null);
3151
+ return;
3152
+ }
3153
+ setDropTarget((previous) => {
3154
+ if (previous?.columnId === nextTarget.columnId && previous.edge === nextTarget.edge) {
3155
+ return previous;
3156
+ }
3157
+ return nextTarget;
3158
+ });
3159
+ };
3160
+ const onPointerUp = (event) => {
3161
+ const session = sessionRef.current;
3162
+ if (!session || event.pointerId !== session.pointerId) {
3163
+ return;
3164
+ }
3165
+ if (session.active) {
3166
+ event.preventDefault();
3167
+ const target = dropTargetRef.current;
3168
+ if (target) {
3169
+ const targetIds = readTargetIds(session.table, target.columnId);
3170
+ const next = moveColumnIds(
3171
+ columnOrderRef.current,
3172
+ session.fromIds,
3173
+ targetIds,
3174
+ target.edge
3175
+ );
3176
+ onColumnOrderChangeRef.current(next);
3177
+ }
3178
+ const suppressClick = (clickEvent) => {
3179
+ clickEvent.preventDefault();
3180
+ clickEvent.stopPropagation();
3181
+ document.removeEventListener("click", suppressClick, true);
3182
+ };
3183
+ document.addEventListener("click", suppressClick, true);
3184
+ window.setTimeout(() => {
3185
+ document.removeEventListener("click", suppressClick, true);
3186
+ }, 0);
3187
+ }
3188
+ resetDrag();
3189
+ };
3190
+ const onPointerCancel = (event) => {
3191
+ const session = sessionRef.current;
3192
+ if (!session || event.pointerId !== session.pointerId) {
3193
+ return;
3194
+ }
3195
+ if (session.active) {
3196
+ event.preventDefault();
3197
+ }
3198
+ resetDrag();
3199
+ };
3200
+ document.addEventListener("pointermove", onPointerMove);
3201
+ document.addEventListener("pointerup", onPointerUp);
3202
+ document.addEventListener("pointercancel", onPointerCancel);
3203
+ return () => {
3204
+ document.removeEventListener("pointermove", onPointerMove);
3205
+ document.removeEventListener("pointerup", onPointerUp);
3206
+ document.removeEventListener("pointercancel", onPointerCancel);
3207
+ };
3208
+ }, [enabled, resetDrag]);
3209
+ return {
3210
+ isReordering: draggingColumnId != null,
3211
+ draggingColumnId,
3212
+ dropTarget,
3213
+ onHeaderPointerDown
3214
+ };
3215
+ }
3216
+
2852
3217
  // src/components/ui/table/components/DataTable/DataTable.tsx
2853
3218
  import { flexRender as flexRender2 } from "@tanstack/react-table";
2854
3219
  import { useMemo as useMemo4 } from "react";
2855
3220
 
2856
3221
  // src/components/ui/table/components/DataTable/DataTableRow.tsx
2857
3222
  import { flexRender } from "@tanstack/react-table";
2858
- import { useEffect as useEffect6, useRef as useRef6 } from "react";
3223
+ import { useEffect as useEffect7, useRef as useRef7 } from "react";
2859
3224
 
2860
3225
  // src/components/ui/table/components/icons.tsx
2861
3226
  import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
@@ -3153,9 +3518,9 @@ function DataTableRow({
3153
3518
  const expandKey = toggleField && rowData[toggleField] !== null && rowData[toggleField] !== void 0 ? String(rowData[toggleField]) : null;
3154
3519
  const isExpanded = expandKey !== null && Boolean(expandedRows?.has(expandKey));
3155
3520
  const rowLevel = typeof rowData.level === "number" ? rowData.level : 0;
3156
- const editInputRef = useRef6(null);
3521
+ const editInputRef = useRef7(null);
3157
3522
  const isRowEditing = editingCell?.rowIndex === rowIndex;
3158
- useEffect6(() => {
3523
+ useEffect7(() => {
3159
3524
  if (!isRowEditing) return;
3160
3525
  editInputRef.current?.focus();
3161
3526
  editInputRef.current?.select();
@@ -3753,6 +4118,7 @@ function DataTable({
3753
4118
  selectionLabel,
3754
4119
  enableCellSelection,
3755
4120
  enableColumnResize,
4121
+ enableColumnReorder,
3756
4122
  enableColumnFreeze,
3757
4123
  enableInlineSearch,
3758
4124
  shouldVirtualize,
@@ -3765,6 +4131,7 @@ function DataTable({
3765
4131
  rowContextValue,
3766
4132
  handleToggleSelect,
3767
4133
  clearHover,
4134
+ setColumnOrder,
3768
4135
  inlineSearch
3769
4136
  } = useGlideTable(glideOptions);
3770
4137
  const ToolbarSlot = slots?.Toolbar ?? DataTableToolbar;
@@ -3774,6 +4141,12 @@ function DataTable({
3774
4141
  const EmptySlot = slots?.Empty ?? DefaultEmpty;
3775
4142
  const freezeOffsets = rowContextValue.columnFreeze.offsets;
3776
4143
  const headerGroups = getMergedHeaderGroups(table.getHeaderGroups());
4144
+ const leafColumnIds = table.getVisibleLeafColumns().map((column) => column.id);
4145
+ const { isReordering, draggingColumnId, dropTarget, onHeaderPointerDown } = useColumnReorder({
4146
+ enabled: enableColumnReorder,
4147
+ columnOrder: leafColumnIds,
4148
+ onColumnOrderChange: setColumnOrder
4149
+ });
3777
4150
  const contextValue = useMemo4(
3778
4151
  () => ({ ...rowContextValue, classNames }),
3779
4152
  [rowContextValue, classNames]
@@ -3796,6 +4169,8 @@ function DataTable({
3796
4169
  "DataTableJSX",
3797
4170
  !enableCellSelection && "DataTableJSX--no-cell-selection",
3798
4171
  enableColumnResize && "DataTableJSX--column-resize",
4172
+ enableColumnReorder && "DataTableJSX--column-reorder",
4173
+ isReordering && "DataTableJSX--column-reordering",
3799
4174
  enableColumnFreeze && "DataTableJSX--column-freeze",
3800
4175
  enableInlineSearch && "DataTableJSX--inline-search",
3801
4176
  classNames?.root,
@@ -3864,20 +4239,43 @@ function DataTable({
3864
4239
  ...sizeStyle,
3865
4240
  ...freezeStyle
3866
4241
  };
4242
+ const isPlaceholder = header.isPlaceholder;
4243
+ const leafColumns = header.column.getLeafColumns();
4244
+ const leafIds = leafColumns.map((leafColumn) => leafColumn.id);
4245
+ const isLeafHeader = !isPlaceholder && header.subHeaders.length === 0;
4246
+ const canDrag = enableColumnReorder && !isPlaceholder && leafIds.length > 0 && leafColumns.every(
4247
+ (leafColumn) => isColumnReorderable(leafColumn.columnDef.meta)
4248
+ );
4249
+ const isDragging = draggingColumnId === header.column.id;
4250
+ const dropEdge = !isPlaceholder && dropTarget?.columnId === header.column.id ? dropTarget.edge : void 0;
3867
4251
  return /* @__PURE__ */ jsxs6(
3868
4252
  "th",
3869
4253
  {
3870
4254
  colSpan: header.colSpan,
3871
4255
  rowSpan: header.mergedRowSpan,
4256
+ "data-column-id": enableColumnReorder && !isPlaceholder ? header.column.id : void 0,
4257
+ "data-reorder-ids": enableColumnReorder && !isPlaceholder ? serializeReorderIds(leafIds) : void 0,
4258
+ "data-reorder-leaf": enableColumnReorder && isLeafHeader ? "" : void 0,
4259
+ "data-reorderable": canDrag ? "" : void 0,
4260
+ "data-reordering": isDragging ? "" : void 0,
4261
+ "data-drop-edge": dropEdge,
3872
4262
  "data-resizing": header.column.getIsResizing() ? "" : void 0,
3873
4263
  "data-frozen": freezeOffset?.side,
3874
4264
  "data-freeze-edge": getColumnFreezeEdgeAttr(freezeOffset),
4265
+ "aria-grabbed": isDragging ? true : void 0,
4266
+ title: canDrag ? labels.reorderColumn : void 0,
4267
+ onPointerDown: enableColumnReorder ? (event) => onHeaderPointerDown(event, {
4268
+ columnId: header.column.id,
4269
+ leafIds,
4270
+ canDrag
4271
+ }) : void 0,
3875
4272
  style: Object.keys(headerStyle).length > 0 ? headerStyle : void 0,
3876
4273
  className: cn(
3877
4274
  "data-table-head-cell",
3878
4275
  freezeOffset && `data-table-head-cell--frozen-${freezeOffset.side}`,
3879
4276
  CELL_ALIGN_CLASS[align],
3880
4277
  classNames?.headCell,
4278
+ dropEdge && classNames?.dropEdge,
3881
4279
  headerClassName
3882
4280
  ),
3883
4281
  children: [
@@ -3999,7 +4397,7 @@ function DataTable({
3999
4397
  }
4000
4398
 
4001
4399
  // src/components/ui/table/components/Table/Table.tsx
4002
- import { useCallback as useCallback6, useMemo as useMemo5, useState as useState5 } from "react";
4400
+ import { useCallback as useCallback7, useMemo as useMemo5, useState as useState6 } from "react";
4003
4401
 
4004
4402
  // src/components/ui/table/components/Table/buildColumnDef.tsx
4005
4403
  import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
@@ -4037,6 +4435,7 @@ function buildColumnDef(props, sort, onSort) {
4037
4435
  minWidth,
4038
4436
  maxWidth,
4039
4437
  resizable,
4438
+ reorderable,
4040
4439
  frozen,
4041
4440
  align,
4042
4441
  rowSpan,
@@ -4082,6 +4481,7 @@ function buildColumnDef(props, sort, onSort) {
4082
4481
  cellProps,
4083
4482
  cellRender: render,
4084
4483
  frozen,
4484
+ reorderable,
4085
4485
  className,
4086
4486
  headerClassName
4087
4487
  }
@@ -4329,8 +4729,8 @@ function TableRoot({
4329
4729
  () => parseTableChildren(children),
4330
4730
  [children]
4331
4731
  );
4332
- const [sort, setSort] = useState5(null);
4333
- const handleSort = useCallback6((field) => {
4732
+ const [sort, setSort] = useState6(null);
4733
+ const handleSort = useCallback7((field) => {
4334
4734
  setSort((previous) => {
4335
4735
  if (previous?.field !== field) {
4336
4736
  return { field, direction: "asc" };
@@ -4427,6 +4827,7 @@ export {
4427
4827
  Table,
4428
4828
  applyCellEdit,
4429
4829
  applyFillData,
4830
+ applyLeafColumnOrder,
4430
4831
  applySelectionUpdater,
4431
4832
  buildColumnFreezeOffsets,
4432
4833
  buildColumnRowSpanMap,
@@ -4441,6 +4842,7 @@ export {
4441
4842
  collectCopyRowEntries,
4442
4843
  collectCopyRows,
4443
4844
  collectFillChanges,
4845
+ collectLeafColumnIds,
4444
4846
  collectRowSpanColumns,
4445
4847
  collectSearchMatchesInRange,
4446
4848
  commitCellValue,
@@ -4466,6 +4868,7 @@ export {
4466
4868
  mapSearchResultToVisibleItem,
4467
4869
  mapSearchResultsToVisibleKeys,
4468
4870
  measureMergedSpanRowHeights,
4871
+ moveColumnIds,
4469
4872
  nextSearchIndex,
4470
4873
  nextSearchStride,
4471
4874
  parseCellEditValue,
@@ -4475,7 +4878,9 @@ export {
4475
4878
  resolveCellRenderer,
4476
4879
  resolveColumnFreezeSide,
4477
4880
  resolveDataTableLabels,
4881
+ resolveDropEdge,
4478
4882
  resolveHeaderFreezeOffset,
4883
+ resolveLeafColumnOrder,
4479
4884
  resolvePasteColumnIds,
4480
4885
  resolveRowSelection,
4481
4886
  resolveRowSpanAt,
@@ -4485,6 +4890,7 @@ export {
4485
4890
  toggleExpandedRowId,
4486
4891
  useCellEdit,
4487
4892
  useCellSelection,
4893
+ useColumnReorder,
4488
4894
  useConvertTreeData,
4489
4895
  useGlideTable,
4490
4896
  useInlineSearch,